Merge pull request #47 from sylvan-basilisk/editor-redesign
addition of advanced filtering features in deck editor
This commit is contained in:
commit
2b7d5d0ef2
23 changed files with 1658 additions and 107 deletions
|
@ -26,6 +26,7 @@ SET(cockatrice_SOURCES
|
||||||
src/handzone.cpp
|
src/handzone.cpp
|
||||||
src/handcounter.cpp
|
src/handcounter.cpp
|
||||||
src/carddatabase.cpp
|
src/carddatabase.cpp
|
||||||
|
src/keysignals.cpp
|
||||||
src/gameview.cpp
|
src/gameview.cpp
|
||||||
src/gameselector.cpp
|
src/gameselector.cpp
|
||||||
src/decklistmodel.cpp
|
src/decklistmodel.cpp
|
||||||
|
@ -33,6 +34,13 @@ SET(cockatrice_SOURCES
|
||||||
src/dlg_load_deck_from_clipboard.cpp
|
src/dlg_load_deck_from_clipboard.cpp
|
||||||
src/dlg_load_remote_deck.cpp
|
src/dlg_load_remote_deck.cpp
|
||||||
src/cardinfowidget.cpp
|
src/cardinfowidget.cpp
|
||||||
|
src/cardframe.cpp
|
||||||
|
src/cardinfopicture.cpp
|
||||||
|
src/cardinfotext.cpp
|
||||||
|
src/filterbuilder.cpp
|
||||||
|
src/cardfilter.cpp
|
||||||
|
src/filtertreemodel.cpp
|
||||||
|
src/filtertree.cpp
|
||||||
src/messagelogwidget.cpp
|
src/messagelogwidget.cpp
|
||||||
src/zoneviewzone.cpp
|
src/zoneviewzone.cpp
|
||||||
src/zoneviewwidget.cpp
|
src/zoneviewwidget.cpp
|
||||||
|
@ -103,6 +111,7 @@ SET(cockatrice_HEADERS
|
||||||
src/handzone.h
|
src/handzone.h
|
||||||
src/handcounter.h
|
src/handcounter.h
|
||||||
src/carddatabase.h
|
src/carddatabase.h
|
||||||
|
src/keysignals.h
|
||||||
src/gameview.h
|
src/gameview.h
|
||||||
src/gameselector.h
|
src/gameselector.h
|
||||||
src/decklistmodel.h
|
src/decklistmodel.h
|
||||||
|
@ -110,6 +119,13 @@ SET(cockatrice_HEADERS
|
||||||
src/dlg_load_deck_from_clipboard.h
|
src/dlg_load_deck_from_clipboard.h
|
||||||
src/dlg_load_remote_deck.h
|
src/dlg_load_remote_deck.h
|
||||||
src/cardinfowidget.h
|
src/cardinfowidget.h
|
||||||
|
src/cardframe.h
|
||||||
|
src/cardinfopicture.h
|
||||||
|
src/cardinfotext.h
|
||||||
|
src/filterbuilder.h
|
||||||
|
src/cardfilter.h
|
||||||
|
src/filtertreemodel.h
|
||||||
|
src/filtertree.h
|
||||||
src/messagelogwidget.h
|
src/messagelogwidget.h
|
||||||
src/zoneviewzone.h
|
src/zoneviewzone.h
|
||||||
src/zoneviewwidget.h
|
src/zoneviewwidget.h
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "carddatabasemodel.h"
|
#include "carddatabasemodel.h"
|
||||||
|
#include "filtertree.h"
|
||||||
|
|
||||||
CardDatabaseModel::CardDatabaseModel(CardDatabase *_db, QObject *parent)
|
CardDatabaseModel::CardDatabaseModel(CardDatabase *_db, QObject *parent)
|
||||||
: QAbstractListModel(parent), db(_db)
|
: QAbstractListModel(parent), db(_db)
|
||||||
|
@ -109,6 +110,7 @@ CardDatabaseDisplayModel::CardDatabaseDisplayModel(QObject *parent)
|
||||||
: QSortFilterProxyModel(parent),
|
: QSortFilterProxyModel(parent),
|
||||||
isToken(ShowAll)
|
isToken(ShowAll)
|
||||||
{
|
{
|
||||||
|
filterTree = NULL;
|
||||||
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||||
setSortCaseSensitivity(Qt::CaseInsensitive);
|
setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||||
}
|
}
|
||||||
|
@ -116,7 +118,6 @@ CardDatabaseDisplayModel::CardDatabaseDisplayModel(QObject *parent)
|
||||||
bool CardDatabaseDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex & /*sourceParent*/) const
|
bool CardDatabaseDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex & /*sourceParent*/) const
|
||||||
{
|
{
|
||||||
CardInfo const *info = static_cast<CardDatabaseModel *>(sourceModel())->getCard(sourceRow);
|
CardInfo const *info = static_cast<CardDatabaseModel *>(sourceModel())->getCard(sourceRow);
|
||||||
|
|
||||||
if (((isToken == ShowTrue) && !info->getIsToken()) || ((isToken == ShowFalse) && info->getIsToken()))
|
if (((isToken == ShowTrue) && !info->getIsToken()) || ((isToken == ShowFalse) && info->getIsToken()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -144,6 +145,9 @@ bool CardDatabaseDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex
|
||||||
if (!cardTypes.contains(info->getMainCardType()))
|
if (!cardTypes.contains(info->getMainCardType()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (filterTree != NULL)
|
||||||
|
return filterTree->acceptsCard(info);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,5 +157,22 @@ void CardDatabaseDisplayModel::clearSearch()
|
||||||
cardText.clear();
|
cardText.clear();
|
||||||
cardTypes.clear();
|
cardTypes.clear();
|
||||||
cardColors.clear();
|
cardColors.clear();
|
||||||
|
if (filterTree != NULL)
|
||||||
|
filterTree->clear();
|
||||||
invalidateFilter();
|
invalidateFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CardDatabaseDisplayModel::setFilterTree(FilterTree *filterTree)
|
||||||
|
{
|
||||||
|
if (this->filterTree != NULL)
|
||||||
|
disconnect(this->filterTree, 0, this, 0);
|
||||||
|
|
||||||
|
this->filterTree = filterTree;
|
||||||
|
connect(this->filterTree, SIGNAL(changed()), this, SLOT(filterTreeChanged()));
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardDatabaseDisplayModel::filterTreeChanged()
|
||||||
|
{
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
|
|
||||||
|
class FilterTree;
|
||||||
|
|
||||||
class CardDatabaseModel : public QAbstractListModel {
|
class CardDatabaseModel : public QAbstractListModel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
@ -36,8 +38,10 @@ private:
|
||||||
FilterBool isToken;
|
FilterBool isToken;
|
||||||
QString cardNameBeginning, cardName, cardText;
|
QString cardNameBeginning, cardName, cardText;
|
||||||
QSet<QString> cardNameSet, cardTypes, cardColors;
|
QSet<QString> cardNameSet, cardTypes, cardColors;
|
||||||
|
FilterTree *filterTree;
|
||||||
public:
|
public:
|
||||||
CardDatabaseDisplayModel(QObject *parent = 0);
|
CardDatabaseDisplayModel(QObject *parent = 0);
|
||||||
|
void setFilterTree(FilterTree *filterTree);
|
||||||
void setIsToken(FilterBool _isToken) { isToken = _isToken; invalidate(); }
|
void setIsToken(FilterBool _isToken) { isToken = _isToken; invalidate(); }
|
||||||
void setCardNameBeginning(const QString &_beginning) { cardNameBeginning = _beginning; invalidate(); }
|
void setCardNameBeginning(const QString &_beginning) { cardNameBeginning = _beginning; invalidate(); }
|
||||||
void setCardName(const QString &_cardName) { cardName = _cardName; invalidate(); }
|
void setCardName(const QString &_cardName) { cardName = _cardName; invalidate(); }
|
||||||
|
@ -48,6 +52,8 @@ public:
|
||||||
void clearSearch();
|
void clearSearch();
|
||||||
protected:
|
protected:
|
||||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
|
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
|
||||||
|
private slots:
|
||||||
|
void filterTreeChanged();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
37
cockatrice/src/cardfilter.cpp
Normal file
37
cockatrice/src/cardfilter.cpp
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#include "cardfilter.h"
|
||||||
|
|
||||||
|
const char *CardFilter::typeName(Type t)
|
||||||
|
{
|
||||||
|
switch (t) {
|
||||||
|
case TypeAnd:
|
||||||
|
return "and";
|
||||||
|
case TypeOr:
|
||||||
|
return "or";
|
||||||
|
case TypeAndNot:
|
||||||
|
return "and not";
|
||||||
|
case TypeOrNot:
|
||||||
|
return "or not";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *CardFilter::attrName(Attr a)
|
||||||
|
{
|
||||||
|
switch (a) {
|
||||||
|
case AttrName:
|
||||||
|
return "name";
|
||||||
|
case AttrType:
|
||||||
|
return "type";
|
||||||
|
case AttrColor:
|
||||||
|
return "color";
|
||||||
|
case AttrText:
|
||||||
|
return "text";
|
||||||
|
case AttrSet:
|
||||||
|
return "set";
|
||||||
|
case AttrManaCost:
|
||||||
|
return "mana cost";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
44
cockatrice/src/cardfilter.h
Normal file
44
cockatrice/src/cardfilter.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef CARDFILTER_H
|
||||||
|
#define CARDFILTER_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class CardFilter {
|
||||||
|
public:
|
||||||
|
enum Type {
|
||||||
|
TypeAnd = 0,
|
||||||
|
TypeOr,
|
||||||
|
TypeAndNot,
|
||||||
|
TypeOrNot,
|
||||||
|
TypeEnd
|
||||||
|
};
|
||||||
|
|
||||||
|
/* if you add an atribute here you also need to
|
||||||
|
* add its string representation in attrName */
|
||||||
|
enum Attr {
|
||||||
|
AttrName = 0,
|
||||||
|
AttrType,
|
||||||
|
AttrColor,
|
||||||
|
AttrText,
|
||||||
|
AttrSet,
|
||||||
|
AttrManaCost,
|
||||||
|
AttrEnd
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum Type t;
|
||||||
|
enum Attr a;
|
||||||
|
QString trm;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CardFilter(QString term, Type type, Attr attr) : trm(term), t(type), a(attr) {};
|
||||||
|
|
||||||
|
Type type() const { return t; }
|
||||||
|
const QString &term() const { return trm; }
|
||||||
|
Attr attr() const { return a; }
|
||||||
|
|
||||||
|
static const char *typeName(Type t);
|
||||||
|
static const char *attrName(Attr a);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
59
cockatrice/src/cardframe.cpp
Normal file
59
cockatrice/src/cardframe.cpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#include "cardframe.h"
|
||||||
|
|
||||||
|
#include "carditem.h"
|
||||||
|
#include "carddatabase.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "cardinfopicture.h"
|
||||||
|
#include "cardinfotext.h"
|
||||||
|
|
||||||
|
CardFrame::CardFrame(int width, int height,
|
||||||
|
const QString &cardName, QWidget *parent)
|
||||||
|
: QStackedWidget(parent)
|
||||||
|
, info(0)
|
||||||
|
, cardTextOnly(false)
|
||||||
|
{
|
||||||
|
setFrameStyle(QFrame::Panel | QFrame::Raised);
|
||||||
|
setMaximumWidth(width);
|
||||||
|
setMinimumWidth(width);
|
||||||
|
setMaximumHeight(height);
|
||||||
|
setMinimumHeight(height);
|
||||||
|
pic = new CardInfoPicture(width);
|
||||||
|
addWidget(pic);
|
||||||
|
text = new CardInfoText();
|
||||||
|
addWidget(text);
|
||||||
|
connect(pic, SIGNAL(hasPictureChanged()), this, SLOT(hasPictureChanged()));
|
||||||
|
setCard(db->getCard(cardName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardFrame::setCard(CardInfo *card)
|
||||||
|
{
|
||||||
|
if (info)
|
||||||
|
disconnect(info, 0, this, 0);
|
||||||
|
info = card;
|
||||||
|
connect(info, SIGNAL(destroyed()), this, SLOT(clear()));
|
||||||
|
text->setCard(info);
|
||||||
|
pic->setCard(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardFrame::setCard(const QString &cardName)
|
||||||
|
{
|
||||||
|
setCard(db->getCard(cardName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardFrame::setCard(AbstractCardItem *card)
|
||||||
|
{
|
||||||
|
setCard(card->getInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardFrame::clear()
|
||||||
|
{
|
||||||
|
setCard(db->getCard());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardFrame::hasPictureChanged()
|
||||||
|
{
|
||||||
|
if (pic->hasPicture() && !cardTextOnly)
|
||||||
|
setCurrentWidget(pic);
|
||||||
|
else
|
||||||
|
setCurrentWidget(text);
|
||||||
|
}
|
36
cockatrice/src/cardframe.h
Normal file
36
cockatrice/src/cardframe.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef CARDFRAME_H
|
||||||
|
#define CARDFRAME_H
|
||||||
|
|
||||||
|
#include <QStackedWidget>
|
||||||
|
|
||||||
|
class AbstractCardItem;
|
||||||
|
class CardInfo;
|
||||||
|
class CardInfoPicture;
|
||||||
|
class CardInfoText;
|
||||||
|
|
||||||
|
class CardFrame : public QStackedWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
CardInfo *info;
|
||||||
|
CardInfoPicture *pic;
|
||||||
|
CardInfoText *text;
|
||||||
|
bool cardTextOnly;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CardFrame(int width, int height, const QString &cardName = QString(),
|
||||||
|
QWidget *parent = 0);
|
||||||
|
void setCardTextOnly(bool status) { cardTextOnly = status; hasPictureChanged(); }
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setCard(CardInfo *card);
|
||||||
|
void setCard(const QString &cardName);
|
||||||
|
void setCard(AbstractCardItem *card);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void hasPictureChanged();
|
||||||
|
void toggleCardTextOnly() { setCardTextOnly(!cardTextOnly); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
53
cockatrice/src/cardinfopicture.cpp
Normal file
53
cockatrice/src/cardinfopicture.cpp
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#include "cardinfopicture.h"
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include "carditem.h"
|
||||||
|
#include "carddatabase.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
CardInfoPicture::CardInfoPicture(int maximumWidth, QWidget *parent)
|
||||||
|
: QLabel(parent)
|
||||||
|
, info(0)
|
||||||
|
, noPicture(true)
|
||||||
|
{
|
||||||
|
setMaximumWidth(maximumWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardInfoPicture::setNoPicture(bool status)
|
||||||
|
{
|
||||||
|
if (noPicture != status) {
|
||||||
|
noPicture = status;
|
||||||
|
emit hasPictureChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardInfoPicture::setCard(CardInfo *card)
|
||||||
|
{
|
||||||
|
if (info)
|
||||||
|
disconnect(info, 0, this, 0);
|
||||||
|
info = card;
|
||||||
|
connect(info, SIGNAL(pixmapUpdated()), this, SLOT(updatePixmap()));
|
||||||
|
|
||||||
|
updatePixmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardInfoPicture::updatePixmap()
|
||||||
|
{
|
||||||
|
qreal aspectRatio = (qreal) CARD_HEIGHT / (qreal) CARD_WIDTH;
|
||||||
|
qreal pixmapWidth = this->width();
|
||||||
|
|
||||||
|
if (pixmapWidth == 0) {
|
||||||
|
setNoPicture(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap *resizedPixmap = info->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio));
|
||||||
|
if (resizedPixmap) {
|
||||||
|
setNoPicture(false);
|
||||||
|
this->setPixmap(*resizedPixmap);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setNoPicture(true);
|
||||||
|
this->setPixmap(*(db->getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio))));
|
||||||
|
}
|
||||||
|
}
|
34
cockatrice/src/cardinfopicture.h
Normal file
34
cockatrice/src/cardinfopicture.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef CARDINFOPICTURE_H
|
||||||
|
#define CARDINFOPICTURE_H
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
|
class AbstractCardItem;
|
||||||
|
class CardInfo;
|
||||||
|
|
||||||
|
class CardInfoPicture : public QLabel {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void hasPictureChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
CardInfo *info;
|
||||||
|
bool noPicture;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CardInfoPicture(int maximumWidth, QWidget *parent = 0);
|
||||||
|
bool hasPicture() const { return !noPicture; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setNoPicture(bool status);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setCard(CardInfo *card);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void updatePixmap();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
67
cockatrice/src/cardinfotext.cpp
Normal file
67
cockatrice/src/cardinfotext.cpp
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
#include "cardinfotext.h"
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QTextEdit>
|
||||||
|
#include <QGridLayout>
|
||||||
|
#include "carditem.h"
|
||||||
|
#include "carddatabase.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
CardInfoText::CardInfoText(QWidget *parent)
|
||||||
|
: QFrame(parent)
|
||||||
|
, info(0)
|
||||||
|
{
|
||||||
|
nameLabel1 = new QLabel;
|
||||||
|
nameLabel2 = new QLabel;
|
||||||
|
nameLabel2->setWordWrap(true);
|
||||||
|
manacostLabel1 = new QLabel;
|
||||||
|
manacostLabel2 = new QLabel;
|
||||||
|
manacostLabel2->setWordWrap(true);
|
||||||
|
cardtypeLabel1 = new QLabel;
|
||||||
|
cardtypeLabel2 = new QLabel;
|
||||||
|
cardtypeLabel2->setWordWrap(true);
|
||||||
|
powtoughLabel1 = new QLabel;
|
||||||
|
powtoughLabel2 = new QLabel;
|
||||||
|
loyaltyLabel1 = new QLabel;
|
||||||
|
loyaltyLabel2 = new QLabel;
|
||||||
|
|
||||||
|
textLabel = new QTextEdit();
|
||||||
|
textLabel->setReadOnly(true);
|
||||||
|
|
||||||
|
QGridLayout *grid = new QGridLayout(this);
|
||||||
|
int row = 0;
|
||||||
|
grid->addWidget(nameLabel1, row, 0);
|
||||||
|
grid->addWidget(nameLabel2, row++, 1);
|
||||||
|
grid->addWidget(manacostLabel1, row, 0);
|
||||||
|
grid->addWidget(manacostLabel2, row++, 1);
|
||||||
|
grid->addWidget(cardtypeLabel1, row, 0);
|
||||||
|
grid->addWidget(cardtypeLabel2, row++, 1);
|
||||||
|
grid->addWidget(powtoughLabel1, row, 0);
|
||||||
|
grid->addWidget(powtoughLabel2, row++, 1);
|
||||||
|
grid->addWidget(loyaltyLabel1, row, 0);
|
||||||
|
grid->addWidget(loyaltyLabel2, row++, 1);
|
||||||
|
grid->addWidget(textLabel, row, 0, -1, 2);
|
||||||
|
grid->setRowStretch(row, 1);
|
||||||
|
grid->setColumnStretch(1, 1);
|
||||||
|
|
||||||
|
retranslateUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardInfoText::setCard(CardInfo *card)
|
||||||
|
{
|
||||||
|
nameLabel2->setText(card->getName());
|
||||||
|
manacostLabel2->setText(card->getManaCost());
|
||||||
|
cardtypeLabel2->setText(card->getCardType());
|
||||||
|
powtoughLabel2->setText(card->getPowTough());
|
||||||
|
loyaltyLabel2->setText(card->getLoyalty() > 0 ? QString::number(card->getLoyalty()) : QString());
|
||||||
|
textLabel->setText(card->getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardInfoText::retranslateUi()
|
||||||
|
{
|
||||||
|
nameLabel1->setText(tr("Name:"));
|
||||||
|
manacostLabel1->setText(tr("Mana cost:"));
|
||||||
|
cardtypeLabel1->setText(tr("Card type:"));
|
||||||
|
powtoughLabel1->setText(tr("P / T:"));
|
||||||
|
loyaltyLabel1->setText(tr("Loyalty:"));
|
||||||
|
}
|
31
cockatrice/src/cardinfotext.h
Normal file
31
cockatrice/src/cardinfotext.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef CARDINFOTEXT_H
|
||||||
|
#define CARDINFOTEXT_H
|
||||||
|
|
||||||
|
#include <QFrame>
|
||||||
|
|
||||||
|
class QLabel;
|
||||||
|
class QTextEdit;
|
||||||
|
class CardInfo;
|
||||||
|
|
||||||
|
class CardInfoText : public QFrame {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
QLabel *nameLabel1, *nameLabel2;
|
||||||
|
QLabel *manacostLabel1, *manacostLabel2;
|
||||||
|
QLabel *cardtypeLabel1, *cardtypeLabel2;
|
||||||
|
QLabel *powtoughLabel1, *powtoughLabel2;
|
||||||
|
QLabel *loyaltyLabel1, *loyaltyLabel2;
|
||||||
|
QTextEdit *textLabel;
|
||||||
|
|
||||||
|
CardInfo *info;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CardInfoText(QWidget *parent = 0);
|
||||||
|
void retranslateUi();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setCard(CardInfo *card);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -169,7 +169,6 @@ Qt::ItemFlags DeckListModel::flags(const QModelIndex &index) const
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Qt::ItemFlags result = Qt::ItemIsEnabled;
|
Qt::ItemFlags result = Qt::ItemIsEnabled;
|
||||||
if (getNode<DecklistModelCardNode *>(index))
|
|
||||||
result |= Qt::ItemIsSelectable;
|
result |= Qt::ItemIsSelectable;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -236,6 +235,38 @@ InnerDecklistNode *DeckListModel::createNodeIfNeeded(const QString &name, InnerD
|
||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DecklistModelCardNode *DeckListModel::findCardNode(const QString &cardName, const QString &zoneName) const
|
||||||
|
{
|
||||||
|
InnerDecklistNode *zoneNode, *typeNode;
|
||||||
|
CardInfo *info;
|
||||||
|
QString cardType;
|
||||||
|
|
||||||
|
zoneNode = dynamic_cast<InnerDecklistNode *>(root->findChild(zoneName));
|
||||||
|
if(!zoneNode)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
info = db->getCard(cardName);
|
||||||
|
if(!info)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
cardType = info->getMainCardType();
|
||||||
|
typeNode = dynamic_cast<InnerDecklistNode *>(zoneNode->findChild(cardType));
|
||||||
|
if(!typeNode)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return dynamic_cast<DecklistModelCardNode *>(typeNode->findChild(cardName));
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex DeckListModel::findCard(const QString &cardName, const QString &zoneName) const
|
||||||
|
{
|
||||||
|
DecklistModelCardNode *cardNode;
|
||||||
|
|
||||||
|
cardNode = findCardNode(cardName, zoneName);
|
||||||
|
if(!cardNode)
|
||||||
|
return QModelIndex();
|
||||||
|
return nodeToIndex(cardNode);
|
||||||
|
}
|
||||||
|
|
||||||
QModelIndex DeckListModel::addCard(const QString &cardName, const QString &zoneName)
|
QModelIndex DeckListModel::addCard(const QString &cardName, const QString &zoneName)
|
||||||
{
|
{
|
||||||
InnerDecklistNode *zoneNode = createNodeIfNeeded(zoneName, root);
|
InnerDecklistNode *zoneNode = createNodeIfNeeded(zoneName, root);
|
||||||
|
|
|
@ -45,6 +45,7 @@ public:
|
||||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||||
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
|
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
|
||||||
|
QModelIndex findCard(const QString &cardName, const QString &zoneName) const;
|
||||||
QModelIndex addCard(const QString &cardName, const QString &zoneName);
|
QModelIndex addCard(const QString &cardName, const QString &zoneName);
|
||||||
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
|
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
|
||||||
void cleanList();
|
void cleanList();
|
||||||
|
@ -56,6 +57,7 @@ private:
|
||||||
InnerDecklistNode *root;
|
InnerDecklistNode *root;
|
||||||
InnerDecklistNode *createNodeIfNeeded(const QString &name, InnerDecklistNode *parent);
|
InnerDecklistNode *createNodeIfNeeded(const QString &name, InnerDecklistNode *parent);
|
||||||
QModelIndex nodeToIndex(AbstractDecklistNode *node) const;
|
QModelIndex nodeToIndex(AbstractDecklistNode *node) const;
|
||||||
|
DecklistModelCardNode *findCardNode(const QString &cardName, const QString &zoneName) const;
|
||||||
void emitRecursiveUpdates(const QModelIndex &index);
|
void emitRecursiveUpdates(const QModelIndex &index);
|
||||||
void sortHelper(InnerDecklistNode *node, Qt::SortOrder order);
|
void sortHelper(InnerDecklistNode *node, Qt::SortOrder order);
|
||||||
|
|
||||||
|
|
84
cockatrice/src/filterbuilder.cpp
Normal file
84
cockatrice/src/filterbuilder.cpp
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#include "filterbuilder.h"
|
||||||
|
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QLineEdit>
|
||||||
|
|
||||||
|
#include "cardfilter.h"
|
||||||
|
|
||||||
|
FilterBuilder::FilterBuilder(QWidget *parent)
|
||||||
|
: QFrame(parent)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout;
|
||||||
|
QHBoxLayout *addFilter = new QHBoxLayout;
|
||||||
|
|
||||||
|
filterCombo = new QComboBox;
|
||||||
|
for (i = 0; i < CardFilter::AttrEnd; i++)
|
||||||
|
filterCombo->addItem(
|
||||||
|
tr(CardFilter::attrName(static_cast<CardFilter::Attr>(i))),
|
||||||
|
QVariant(i)
|
||||||
|
);
|
||||||
|
|
||||||
|
typeCombo = new QComboBox;
|
||||||
|
for (i = 0; i < CardFilter::TypeEnd; i++)
|
||||||
|
typeCombo->addItem(
|
||||||
|
tr(CardFilter::typeName(static_cast<CardFilter::Type>(i))),
|
||||||
|
QVariant(i)
|
||||||
|
);
|
||||||
|
|
||||||
|
QPushButton *ok = new QPushButton("+");
|
||||||
|
ok->setMaximumSize(20, 20);
|
||||||
|
|
||||||
|
addFilter->addWidget(ok);
|
||||||
|
addFilter->addWidget(typeCombo);
|
||||||
|
addFilter->addWidget(filterCombo, Qt::AlignLeft);
|
||||||
|
|
||||||
|
edit = new QLineEdit;
|
||||||
|
edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
|
layout->addLayout(addFilter);
|
||||||
|
layout->addWidget(edit);
|
||||||
|
|
||||||
|
setFrameStyle(QFrame::Panel | QFrame::Raised);
|
||||||
|
layout->setAlignment(Qt::AlignTop);
|
||||||
|
setLayout(layout);
|
||||||
|
|
||||||
|
connect(edit, SIGNAL(returnPressed()), this, SLOT(emit_add()));
|
||||||
|
connect(ok, SIGNAL(released()), this, SLOT(emit_add()));
|
||||||
|
connect(filterCombo, SIGNAL(currentIndexChanged(int)), edit, SLOT(clear()));
|
||||||
|
fltr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterBuilder::~FilterBuilder()
|
||||||
|
{
|
||||||
|
destroyFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterBuilder::destroyFilter()
|
||||||
|
{
|
||||||
|
if (fltr)
|
||||||
|
delete fltr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int comboCurrentIntData(const QComboBox *combo)
|
||||||
|
{
|
||||||
|
return combo->itemData(combo->currentIndex()).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterBuilder::emit_add()
|
||||||
|
{
|
||||||
|
QString txt;
|
||||||
|
|
||||||
|
txt = edit->text();
|
||||||
|
if (txt.length() < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
destroyFilter();
|
||||||
|
fltr = new CardFilter(txt,
|
||||||
|
static_cast<CardFilter::Type>(comboCurrentIntData(typeCombo)),
|
||||||
|
static_cast<CardFilter::Attr>(comboCurrentIntData(filterCombo)));
|
||||||
|
emit add(fltr);
|
||||||
|
edit->clear();
|
||||||
|
}
|
35
cockatrice/src/filterbuilder.h
Normal file
35
cockatrice/src/filterbuilder.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef FILTERBUILDER_H
|
||||||
|
#define FILTERBUILDER_H
|
||||||
|
|
||||||
|
#include <QFrame>
|
||||||
|
|
||||||
|
class QCheckBox;
|
||||||
|
class QComboBox;
|
||||||
|
class QLineEdit;
|
||||||
|
class CardFilter;
|
||||||
|
|
||||||
|
class FilterBuilder : public QFrame {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
QComboBox *typeCombo;
|
||||||
|
QComboBox *filterCombo;
|
||||||
|
QLineEdit *edit;
|
||||||
|
CardFilter *fltr;
|
||||||
|
|
||||||
|
void destroyFilter();
|
||||||
|
|
||||||
|
public:
|
||||||
|
FilterBuilder(QWidget *parent = 0);
|
||||||
|
~FilterBuilder();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void add(const CardFilter *f);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
private slots:
|
||||||
|
void emit_add();
|
||||||
|
protected:
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
339
cockatrice/src/filtertree.cpp
Normal file
339
cockatrice/src/filtertree.cpp
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
#include "filtertree.h"
|
||||||
|
#include "cardfilter.h"
|
||||||
|
#include "carddatabase.h"
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
FilterTreeNode *FilterTreeBranch<T>::nodeAt(int i) const
|
||||||
|
{
|
||||||
|
return ((childNodes.size() > i)? childNodes.at(i) : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void FilterTreeBranch<T>::deleteAt(int i)
|
||||||
|
{
|
||||||
|
preRemoveChild(this, i);
|
||||||
|
delete childNodes.takeAt(i);
|
||||||
|
postRemoveChild(this, i);
|
||||||
|
nodeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
int FilterTreeBranch<T>::childIndex(const FilterTreeNode *node) const
|
||||||
|
{
|
||||||
|
FilterTreeNode *unconst;
|
||||||
|
T downcasted;
|
||||||
|
|
||||||
|
/* to do the dynamic cast to T we will lose const'ness, but we can
|
||||||
|
* trust QList::indexOf */
|
||||||
|
unconst = (FilterTreeNode *) node;
|
||||||
|
downcasted = dynamic_cast<T>(unconst);
|
||||||
|
if (downcasted == NULL)
|
||||||
|
return -1;
|
||||||
|
return childNodes.indexOf(downcasted);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
FilterTreeBranch<T>::~FilterTreeBranch()
|
||||||
|
{
|
||||||
|
while (!childNodes.isEmpty())
|
||||||
|
delete childNodes.takeFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
const FilterItemList *LogicMap::findTypeList(CardFilter::Type type) const
|
||||||
|
{
|
||||||
|
QList<FilterItemList *>::const_iterator i;
|
||||||
|
|
||||||
|
for (i = childNodes.constBegin(); i != childNodes.constEnd(); i++)
|
||||||
|
if ((*i)->type == type)
|
||||||
|
return *i;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterItemList *LogicMap::typeList(CardFilter::Type type)
|
||||||
|
{
|
||||||
|
QList<FilterItemList *>::iterator i;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (i = childNodes.begin(); i != childNodes.end(); i++) {
|
||||||
|
if ((*i)->type == type)
|
||||||
|
break;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (i == childNodes.end()) {
|
||||||
|
preInsertChild(this, count);
|
||||||
|
i = childNodes.insert(i, new FilterItemList(type, this));
|
||||||
|
postInsertChild(this, count);
|
||||||
|
nodeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
return *i;
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterTreeNode *LogicMap::parent() const
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FilterItemList::termIndex(const QString &term) const
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < childNodes.count(); i++)
|
||||||
|
if ((childNodes.at(i))->term == term)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterTreeNode *FilterItemList::termNode(const QString &term)
|
||||||
|
{
|
||||||
|
int i, count;
|
||||||
|
FilterItem *fi;
|
||||||
|
|
||||||
|
i = termIndex(term);
|
||||||
|
if (i < 0) {
|
||||||
|
fi = new FilterItem(term, this);
|
||||||
|
count = childNodes.count();
|
||||||
|
preInsertChild(this, count);
|
||||||
|
childNodes.append(fi);
|
||||||
|
postInsertChild(this, count);
|
||||||
|
nodeChanged();
|
||||||
|
return fi;
|
||||||
|
}
|
||||||
|
|
||||||
|
return childNodes.at(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterItemList::testTypeAnd(const CardInfo *info, CardFilter::Attr attr) const
|
||||||
|
{
|
||||||
|
QList<FilterItem *>::const_iterator i;
|
||||||
|
|
||||||
|
for (i = childNodes.constBegin(); i != childNodes.constEnd(); i++) {
|
||||||
|
if (!(*i)->isEnabled())
|
||||||
|
continue;
|
||||||
|
if (!(*i)->acceptCardAttr(info, attr))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterItemList::testTypeAndNot(const CardInfo *info, CardFilter::Attr attr) const
|
||||||
|
{
|
||||||
|
// if any one in the list is true, return false
|
||||||
|
return !testTypeOr(info, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterItemList::testTypeOr(const CardInfo *info, CardFilter::Attr attr) const
|
||||||
|
{
|
||||||
|
QList<FilterItem *>::const_iterator i;
|
||||||
|
|
||||||
|
for (i = childNodes.constBegin(); i != childNodes.constEnd(); i++) {
|
||||||
|
if (!(*i)->isEnabled())
|
||||||
|
continue;
|
||||||
|
if ((*i)->acceptCardAttr(info, attr))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterItemList::testTypeOrNot(const CardInfo *info, CardFilter::Attr attr) const
|
||||||
|
{
|
||||||
|
// if any one in the list is false, return true
|
||||||
|
return !testTypeAnd(info, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterItem::acceptName(const CardInfo *info) const
|
||||||
|
{
|
||||||
|
return info->getName().contains(term, Qt::CaseInsensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterItem::acceptType(const CardInfo *info) const
|
||||||
|
{
|
||||||
|
return info->getCardType().contains(term, Qt::CaseInsensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterItem::acceptColor(const CardInfo *info) const
|
||||||
|
{
|
||||||
|
QStringList::const_iterator i;
|
||||||
|
bool status;
|
||||||
|
|
||||||
|
status = false;
|
||||||
|
for (i = info->getColors().constBegin(); i != info->getColors().constEnd(); i++)
|
||||||
|
if ((*i).contains(term, Qt::CaseInsensitive)) {
|
||||||
|
status = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterItem::acceptText(const CardInfo *info) const
|
||||||
|
{
|
||||||
|
return info->getText().contains(term, Qt::CaseInsensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterItem::acceptSet(const CardInfo *info) const
|
||||||
|
{
|
||||||
|
SetList::const_iterator i;
|
||||||
|
bool status;
|
||||||
|
|
||||||
|
status = false;
|
||||||
|
for (i = info->getSets().constBegin(); i != info->getSets().constEnd(); i++)
|
||||||
|
if ((*i)->getShortName() == term
|
||||||
|
|| (*i)->getLongName().contains(term, Qt::CaseInsensitive)) {
|
||||||
|
status = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterItem::acceptManaCost(const CardInfo *info) const
|
||||||
|
{
|
||||||
|
return (info->getManaCost() == term);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterItem::acceptCardAttr(const CardInfo *info, CardFilter::Attr attr) const
|
||||||
|
{
|
||||||
|
bool status;
|
||||||
|
|
||||||
|
switch (attr) {
|
||||||
|
case CardFilter::AttrName:
|
||||||
|
status = acceptName(info);
|
||||||
|
break;
|
||||||
|
case CardFilter::AttrType:
|
||||||
|
status = acceptType(info);
|
||||||
|
break;
|
||||||
|
case CardFilter::AttrColor:
|
||||||
|
status = acceptColor(info);
|
||||||
|
break;
|
||||||
|
case CardFilter::AttrText:
|
||||||
|
status = acceptText(info);
|
||||||
|
break;
|
||||||
|
case CardFilter::AttrSet:
|
||||||
|
status = acceptSet(info);
|
||||||
|
break;
|
||||||
|
case CardFilter::AttrManaCost:
|
||||||
|
status = acceptManaCost(info);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
status = true; /* ignore this attribute */
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* need to define these here to make QT happy, otherwise
|
||||||
|
* moc doesnt find some of the FilterTreeBranch symbols.
|
||||||
|
*/
|
||||||
|
FilterTree::FilterTree() {}
|
||||||
|
FilterTree::~FilterTree() {}
|
||||||
|
|
||||||
|
LogicMap *FilterTree::attrLogicMap(CardFilter::Attr attr)
|
||||||
|
{
|
||||||
|
QList<LogicMap *>::iterator i;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (i = childNodes.begin(); i != childNodes.end(); i++) {
|
||||||
|
if ((*i)->attr == attr)
|
||||||
|
break;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == childNodes.end()) {
|
||||||
|
preInsertChild(this, count);
|
||||||
|
i = childNodes.insert(i, new LogicMap(attr, this));
|
||||||
|
postInsertChild(this, count);
|
||||||
|
nodeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
return *i;
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterItemList *FilterTree::attrTypeList(CardFilter::Attr attr,
|
||||||
|
CardFilter::Type type)
|
||||||
|
{
|
||||||
|
return attrLogicMap(attr)->typeList(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FilterTree::findTermIndex(CardFilter::Attr attr, CardFilter::Type type,
|
||||||
|
const QString &term)
|
||||||
|
{
|
||||||
|
attrTypeList(attr, type)->termIndex(term);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FilterTree::findTermIndex(const CardFilter *f)
|
||||||
|
{
|
||||||
|
return findTermIndex(f->attr(), f->type(), f->term());
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterTreeNode *FilterTree::termNode(CardFilter::Attr attr, CardFilter::Type type,
|
||||||
|
const QString &term)
|
||||||
|
{
|
||||||
|
return attrTypeList(attr, type)->termNode(term);
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterTreeNode *FilterTree::termNode(const CardFilter *f)
|
||||||
|
{
|
||||||
|
return termNode(f->attr(), f->type(), f->term());
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterTreeNode *FilterTree::attrTypeNode(CardFilter::Attr attr,
|
||||||
|
CardFilter::Type type)
|
||||||
|
{
|
||||||
|
return attrTypeList(attr, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterTree::testAttr(const CardInfo *info, const LogicMap *lm) const
|
||||||
|
{
|
||||||
|
const FilterItemList *fil;
|
||||||
|
bool status;
|
||||||
|
|
||||||
|
status = true;
|
||||||
|
|
||||||
|
fil = lm->findTypeList(CardFilter::TypeAnd);
|
||||||
|
if (fil != NULL && fil->isEnabled() && !fil->testTypeAnd(info, lm->attr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fil = lm->findTypeList(CardFilter::TypeAndNot);
|
||||||
|
if (fil != NULL && fil->isEnabled() && !fil->testTypeAndNot(info, lm->attr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fil = lm->findTypeList(CardFilter::TypeOr);
|
||||||
|
if (fil != NULL && fil->isEnabled()) {
|
||||||
|
status = false;
|
||||||
|
// if this is true we can return because it is OR'd with the OrNot list
|
||||||
|
if (fil->testTypeOr(info, lm->attr))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fil = lm->findTypeList(CardFilter::TypeOrNot);
|
||||||
|
if (fil != NULL && fil->isEnabled() && fil->testTypeOrNot(info, lm->attr))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterTree::acceptsCard(const CardInfo *info) const
|
||||||
|
{
|
||||||
|
QList<LogicMap *>::const_iterator i;
|
||||||
|
|
||||||
|
for (i = childNodes.constBegin(); i != childNodes.constEnd(); i++)
|
||||||
|
if ((*i)->isEnabled() && !testAttr(info, *i))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterTree::clear()
|
||||||
|
{
|
||||||
|
while(childCount() > 0)
|
||||||
|
deleteAt(0);
|
||||||
|
}
|
163
cockatrice/src/filtertree.h
Normal file
163
cockatrice/src/filtertree.h
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
#ifndef FILTERTREE_H
|
||||||
|
#define FILTERTREE_H
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "cardfilter.h"
|
||||||
|
|
||||||
|
class CardInfo;
|
||||||
|
|
||||||
|
class FilterTreeNode {
|
||||||
|
private:
|
||||||
|
bool enabled;
|
||||||
|
public:
|
||||||
|
FilterTreeNode() : enabled(true) {}
|
||||||
|
virtual bool isEnabled() const { return enabled; }
|
||||||
|
virtual void enable() { enabled = true; nodeChanged(); }
|
||||||
|
virtual void disable() { enabled = false; nodeChanged(); }
|
||||||
|
virtual FilterTreeNode *parent() const { return NULL; }
|
||||||
|
virtual FilterTreeNode *nodeAt(int i) const { return NULL; }
|
||||||
|
virtual void deleteAt(int i) {}
|
||||||
|
virtual int childCount() const { return 0; }
|
||||||
|
virtual int childIndex(const FilterTreeNode *node) const { return -1; }
|
||||||
|
virtual int index() const { return (parent() != NULL)? parent()->childIndex(this) : -1; }
|
||||||
|
virtual QString text() const { return QString(textCStr()); }
|
||||||
|
virtual bool isLeaf() const { return false; }
|
||||||
|
virtual const char *textCStr() const { return ""; }
|
||||||
|
virtual void nodeChanged() const {
|
||||||
|
if (parent() != NULL) parent()->nodeChanged();
|
||||||
|
}
|
||||||
|
virtual void preInsertChild(const FilterTreeNode *p, int i) const {
|
||||||
|
if (parent() != NULL) parent()->preInsertChild(p, i);
|
||||||
|
}
|
||||||
|
virtual void postInsertChild(const FilterTreeNode *p, int i) const {
|
||||||
|
if (parent() != NULL) parent()->postInsertChild(p, i);
|
||||||
|
}
|
||||||
|
virtual void preRemoveChild(const FilterTreeNode *p, int i) const {
|
||||||
|
if (parent() != NULL) parent()->preRemoveChild(p, i);
|
||||||
|
}
|
||||||
|
virtual void postRemoveChild(const FilterTreeNode *p, int i) const {
|
||||||
|
if (parent() != NULL) parent()->postRemoveChild(p, i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class FilterTreeBranch : public FilterTreeNode {
|
||||||
|
protected:
|
||||||
|
QList<T> childNodes;
|
||||||
|
public:
|
||||||
|
~FilterTreeBranch();
|
||||||
|
FilterTreeNode *nodeAt(int i) const;
|
||||||
|
void deleteAt(int i);
|
||||||
|
int childCount() const { return childNodes.size(); }
|
||||||
|
int childIndex(const FilterTreeNode *node) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FilterItemList;
|
||||||
|
class FilterTree;
|
||||||
|
class LogicMap : public FilterTreeBranch<FilterItemList *> {
|
||||||
|
|
||||||
|
private:
|
||||||
|
FilterTree *const p;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const CardFilter::Attr attr;
|
||||||
|
|
||||||
|
LogicMap(CardFilter::Attr a, FilterTree *parent)
|
||||||
|
: attr(a), p(parent) {}
|
||||||
|
const FilterItemList *findTypeList(CardFilter::Type type) const;
|
||||||
|
FilterItemList *typeList(CardFilter::Type type);
|
||||||
|
FilterTreeNode *parent() const;
|
||||||
|
const char* textCStr() const { return CardFilter::attrName(attr); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class FilterItem;
|
||||||
|
class FilterItemList : public FilterTreeBranch<FilterItem *> {
|
||||||
|
private:
|
||||||
|
LogicMap *const p;
|
||||||
|
public:
|
||||||
|
const CardFilter::Type type;
|
||||||
|
|
||||||
|
FilterItemList(CardFilter::Type t, LogicMap *parent)
|
||||||
|
: type(t), p(parent) {}
|
||||||
|
CardFilter::Attr attr() const { return p->attr; }
|
||||||
|
FilterTreeNode *parent() const { return p; }
|
||||||
|
int termIndex(const QString &term) const;
|
||||||
|
FilterTreeNode *termNode(const QString &term);
|
||||||
|
const char *textCStr() const { return CardFilter::typeName(type); }
|
||||||
|
|
||||||
|
bool testTypeAnd(const CardInfo *info, CardFilter::Attr attr) const;
|
||||||
|
bool testTypeAndNot(const CardInfo *info, CardFilter::Attr attr) const;
|
||||||
|
bool testTypeOr(const CardInfo *info, CardFilter::Attr attr) const;
|
||||||
|
bool testTypeOrNot(const CardInfo *info, CardFilter::Attr attr) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FilterItem : public FilterTreeNode {
|
||||||
|
private:
|
||||||
|
FilterItemList *const p;
|
||||||
|
public:
|
||||||
|
const QString term;
|
||||||
|
|
||||||
|
FilterItem(QString trm, FilterItemList *parent)
|
||||||
|
: p(parent), term(trm) {}
|
||||||
|
|
||||||
|
CardFilter::Attr attr() const { return p->attr(); }
|
||||||
|
CardFilter::Type type() const { return p->type; }
|
||||||
|
FilterTreeNode *parent() const { return p; }
|
||||||
|
QString text() const { return term; }
|
||||||
|
const char *textCStr() const { return term.toStdString().c_str(); }
|
||||||
|
bool isLeaf() const { return true; }
|
||||||
|
|
||||||
|
bool acceptName(const CardInfo *info) const;
|
||||||
|
bool acceptType(const CardInfo *info) const;
|
||||||
|
bool acceptColor(const CardInfo *info) const;
|
||||||
|
bool acceptText(const CardInfo *info) const;
|
||||||
|
bool acceptSet(const CardInfo *info) const;
|
||||||
|
bool acceptManaCost(const CardInfo *info) const;
|
||||||
|
bool acceptCardAttr(const CardInfo *info, CardFilter::Attr attr) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FilterTree : public QObject, public FilterTreeBranch<LogicMap *> {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void preInsertRow(const FilterTreeNode *parent, int i) const;
|
||||||
|
void postInsertRow(const FilterTreeNode *parent, int i) const;
|
||||||
|
void preRemoveRow(const FilterTreeNode *parent, int i) const;
|
||||||
|
void postRemoveRow(const FilterTreeNode *parent, int i) const;
|
||||||
|
void changed() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
LogicMap *attrLogicMap(CardFilter::Attr attr);
|
||||||
|
FilterItemList *attrTypeList(CardFilter::Attr attr,
|
||||||
|
CardFilter::Type type);
|
||||||
|
|
||||||
|
bool testAttr(const CardInfo *info, const LogicMap *lm) const;
|
||||||
|
|
||||||
|
void nodeChanged() const { emit changed(); }
|
||||||
|
void preInsertChild(const FilterTreeNode *p, int i) const { emit preInsertRow(p, i); }
|
||||||
|
void postInsertChild(const FilterTreeNode *p, int i) const { emit postInsertRow(p, i); }
|
||||||
|
void preRemoveChild(const FilterTreeNode *p, int i) const { emit preRemoveRow(p, i); }
|
||||||
|
void postRemoveChild(const FilterTreeNode *p, int i) const { emit postRemoveRow(p, i); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
FilterTree();
|
||||||
|
~FilterTree();
|
||||||
|
int findTermIndex(CardFilter::Attr attr, CardFilter::Type type,
|
||||||
|
const QString &term);
|
||||||
|
int findTermIndex(const CardFilter *f);
|
||||||
|
FilterTreeNode *termNode(CardFilter::Attr attr, CardFilter::Type type,
|
||||||
|
const QString &term);
|
||||||
|
FilterTreeNode *termNode(const CardFilter *f);
|
||||||
|
FilterTreeNode *attrTypeNode(CardFilter::Attr attr,
|
||||||
|
CardFilter::Type type);
|
||||||
|
const char *textCStr() { return "root"; }
|
||||||
|
int index() const { return 0; }
|
||||||
|
|
||||||
|
bool acceptsCard(const CardInfo *info) const;
|
||||||
|
void clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
272
cockatrice/src/filtertreemodel.cpp
Normal file
272
cockatrice/src/filtertreemodel.cpp
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
#include <QFont>
|
||||||
|
#include "filtertreemodel.h"
|
||||||
|
#include "filtertree.h"
|
||||||
|
#include "cardfilter.h"
|
||||||
|
|
||||||
|
FilterTreeModel::FilterTreeModel(QObject *parent)
|
||||||
|
: QAbstractItemModel(parent)
|
||||||
|
{
|
||||||
|
fTree = new FilterTree;
|
||||||
|
connect(fTree,
|
||||||
|
SIGNAL(preInsertRow(const FilterTreeNode *, int)),
|
||||||
|
this, SLOT(proxyBeginInsertRow(const FilterTreeNode *, int)));
|
||||||
|
connect(fTree,
|
||||||
|
SIGNAL(postInsertRow(const FilterTreeNode *, int)),
|
||||||
|
this, SLOT(proxyEndInsertRow(const FilterTreeNode *, int)));
|
||||||
|
connect(fTree,
|
||||||
|
SIGNAL(preRemoveRow(const FilterTreeNode *, int)),
|
||||||
|
this, SLOT(proxyBeginRemoveRow(const FilterTreeNode *, int)));
|
||||||
|
connect(fTree,
|
||||||
|
SIGNAL(postRemoveRow(const FilterTreeNode *, int)),
|
||||||
|
this, SLOT(proxyEndRemoveRow(const FilterTreeNode *, int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterTreeModel::~FilterTreeModel()
|
||||||
|
{
|
||||||
|
delete fTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterTreeModel::proxyBeginInsertRow(const FilterTreeNode *node, int i)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
idx = node->index();
|
||||||
|
if (idx >= 0)
|
||||||
|
beginInsertRows(createIndex(idx, 0, (void *) node), i, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterTreeModel::proxyEndInsertRow(const FilterTreeNode *node, int)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
idx = node->index();
|
||||||
|
if (idx >= 0)
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterTreeModel::proxyBeginRemoveRow(const FilterTreeNode *node, int i)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
idx = node->index();
|
||||||
|
if (idx >= 0)
|
||||||
|
beginRemoveRows(createIndex(idx, 0, (void *) node), i, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterTreeModel::proxyEndRemoveRow(const FilterTreeNode *node, int)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
idx = node->index();
|
||||||
|
if (idx >= 0)
|
||||||
|
endRemoveRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterTreeNode *FilterTreeModel::indexToNode(const QModelIndex &idx) const
|
||||||
|
{
|
||||||
|
void *ip;
|
||||||
|
FilterTreeNode *node;
|
||||||
|
|
||||||
|
if (!idx.isValid())
|
||||||
|
return fTree;
|
||||||
|
|
||||||
|
ip = idx.internalPointer();
|
||||||
|
if (ip == NULL)
|
||||||
|
return fTree;
|
||||||
|
|
||||||
|
node = static_cast<FilterTreeNode *>(ip);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterTreeModel::addFilter(const CardFilter *f)
|
||||||
|
{
|
||||||
|
emit layoutAboutToBeChanged();
|
||||||
|
fTree->termNode(f);
|
||||||
|
emit layoutChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
int FilterTreeModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
const FilterTreeNode *node;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (parent.column() > 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
node = indexToNode(parent);
|
||||||
|
if (node)
|
||||||
|
result = node->childCount();
|
||||||
|
else
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FilterTreeModel::columnCount(const QModelIndex &/*parent*/) const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant FilterTreeModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
const FilterTreeNode *node;
|
||||||
|
|
||||||
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
if (index.column() >= columnCount())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
node = indexToNode(index);
|
||||||
|
if (node == NULL)
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
switch (role) {
|
||||||
|
case Qt::FontRole:
|
||||||
|
if (!node->isLeaf()) {
|
||||||
|
QFont f;
|
||||||
|
f.setBold(true);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
case Qt::EditRole:
|
||||||
|
case Qt::ToolTipRole:
|
||||||
|
case Qt::StatusTipRole:
|
||||||
|
case Qt::WhatsThisRole:
|
||||||
|
if(!node->isLeaf())
|
||||||
|
return tr(node->textCStr());
|
||||||
|
else
|
||||||
|
return node->text();
|
||||||
|
case Qt::CheckStateRole:
|
||||||
|
if (node->isEnabled())
|
||||||
|
return Qt::Checked;
|
||||||
|
else
|
||||||
|
return Qt::Unchecked;
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterTreeModel::setData(const QModelIndex &index,
|
||||||
|
const QVariant &value, int role)
|
||||||
|
{
|
||||||
|
FilterTreeNode *node;
|
||||||
|
|
||||||
|
if (!index.isValid())
|
||||||
|
return false;
|
||||||
|
if (index.column() >= columnCount())
|
||||||
|
return false;
|
||||||
|
if (role != Qt::CheckStateRole )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
node = indexToNode(index);
|
||||||
|
if (node == NULL || node == fTree)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
|
||||||
|
if (state == Qt::Checked)
|
||||||
|
node->enable();
|
||||||
|
else
|
||||||
|
node->disable();
|
||||||
|
|
||||||
|
emit dataChanged(index, index);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags FilterTreeModel::flags(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
const FilterTreeNode *node;
|
||||||
|
Qt::ItemFlags result;
|
||||||
|
|
||||||
|
if (!index.isValid())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
node = indexToNode(index);
|
||||||
|
if (node == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
result = Qt::ItemIsEnabled;
|
||||||
|
if (node == fTree)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result |= Qt::ItemIsSelectable;
|
||||||
|
result |= Qt::ItemIsUserCheckable;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex FilterTreeModel::nodeIndex(const FilterTreeNode *node, int row, int column) const
|
||||||
|
{
|
||||||
|
FilterTreeNode *child;
|
||||||
|
|
||||||
|
if (column > 0 || row >= node->childCount())
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
child = node->nodeAt(row);
|
||||||
|
return createIndex(row, column, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex FilterTreeModel::index(int row, int column,
|
||||||
|
const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
const FilterTreeNode *node;
|
||||||
|
|
||||||
|
if (!hasIndex(row, column, parent))
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
node = indexToNode(parent);
|
||||||
|
if (node == NULL)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
return nodeIndex(node, row, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex FilterTreeModel::parent(const QModelIndex &ind) const
|
||||||
|
{
|
||||||
|
const FilterTreeNode *node;
|
||||||
|
FilterTreeNode *parent;
|
||||||
|
int row;
|
||||||
|
QModelIndex idx;
|
||||||
|
|
||||||
|
if (!ind.isValid())
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
node = indexToNode(ind);
|
||||||
|
if (node == NULL || node == fTree)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
parent = node->parent();
|
||||||
|
if (parent) {
|
||||||
|
row = parent->index();
|
||||||
|
if (row < 0)
|
||||||
|
return QModelIndex();
|
||||||
|
idx = createIndex(row, 0, parent);
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterTreeModel::removeRows(int row, int count, const QModelIndex & parent)
|
||||||
|
{
|
||||||
|
FilterTreeNode *node;
|
||||||
|
int i, last;
|
||||||
|
|
||||||
|
last = row+count-1;
|
||||||
|
if (!parent.isValid() || count < 1 || row < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
node = indexToNode(parent);
|
||||||
|
if (node == NULL || last >= node->childCount())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
node->deleteAt(row);
|
||||||
|
|
||||||
|
if (node != fTree && node->childCount() < 1)
|
||||||
|
return removeRow(parent.row(), parent.parent());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
44
cockatrice/src/filtertreemodel.h
Normal file
44
cockatrice/src/filtertreemodel.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef FILTERTREEMODEL_H
|
||||||
|
#define FILTERTREEMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
|
||||||
|
class FilterTree;
|
||||||
|
class CardFilter;
|
||||||
|
class FilterTreeNode;
|
||||||
|
|
||||||
|
class FilterTreeModel : public QAbstractItemModel {
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
FilterTree *fTree;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void addFilter(const CardFilter *f);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void proxyBeginInsertRow(const FilterTreeNode *, int);
|
||||||
|
void proxyEndInsertRow(const FilterTreeNode *, int);
|
||||||
|
void proxyBeginRemoveRow(const FilterTreeNode *, int);
|
||||||
|
void proxyEndRemoveRow(const FilterTreeNode *, int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
FilterTreeNode *indexToNode(const QModelIndex &idx) const;
|
||||||
|
QModelIndex nodeIndex(const FilterTreeNode *node, int row, int column) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FilterTreeModel(QObject *parent = 0);
|
||||||
|
~FilterTreeModel();
|
||||||
|
FilterTree *filterTree() const { return fTree; }
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const;
|
||||||
|
QVariant data(const QModelIndex &index, int role) const;
|
||||||
|
bool setData(const QModelIndex &index, const QVariant &value,
|
||||||
|
int role = Qt::EditRole);
|
||||||
|
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||||
|
QModelIndex parent(const QModelIndex &ind) const;
|
||||||
|
QModelIndex index(int row, int column,
|
||||||
|
const QModelIndex &parent) const;
|
||||||
|
bool removeRows(int row, int count, const QModelIndex & parent);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
65
cockatrice/src/keysignals.cpp
Normal file
65
cockatrice/src/keysignals.cpp
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#include "keysignals.h"
|
||||||
|
#include <QKeyEvent>
|
||||||
|
|
||||||
|
bool KeySignals::eventFilter(QObject * /*object*/, QEvent *event) {
|
||||||
|
QKeyEvent *kevent;
|
||||||
|
|
||||||
|
if(event->type() != QEvent::KeyPress)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
kevent = static_cast<QKeyEvent *>(event);
|
||||||
|
switch(kevent->key()) {
|
||||||
|
case Qt::Key_Return:
|
||||||
|
case Qt::Key_Enter:
|
||||||
|
if (kevent->modifiers().testFlag(Qt::AltModifier)
|
||||||
|
&& kevent->modifiers().testFlag(Qt::ControlModifier) )
|
||||||
|
emit onCtrlAltEnter();
|
||||||
|
else if (kevent->modifiers() & Qt::ControlModifier)
|
||||||
|
emit onCtrlEnter();
|
||||||
|
else
|
||||||
|
emit onEnter();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case Qt::Key_Right:
|
||||||
|
emit onRight();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case Qt::Key_Left:
|
||||||
|
emit onLeft();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case Qt::Key_Delete:
|
||||||
|
case Qt::Key_Backspace:
|
||||||
|
emit onDelete();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case Qt::Key_Minus:
|
||||||
|
if (kevent->modifiers().testFlag(Qt::AltModifier)
|
||||||
|
&& kevent->modifiers().testFlag(Qt::ControlModifier) )
|
||||||
|
emit onCtrlAltMinus();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case Qt::Key_Equal:
|
||||||
|
if (kevent->modifiers().testFlag(Qt::AltModifier)
|
||||||
|
&& kevent->modifiers().testFlag(Qt::ControlModifier) )
|
||||||
|
emit onCtrlAltEqual();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case Qt::Key_BracketLeft:
|
||||||
|
if (kevent->modifiers().testFlag(Qt::AltModifier)
|
||||||
|
&& kevent->modifiers().testFlag(Qt::ControlModifier) )
|
||||||
|
emit onCtrlAltLBracket();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case Qt::Key_BracketRight:
|
||||||
|
if (kevent->modifiers().testFlag(Qt::AltModifier)
|
||||||
|
&& kevent->modifiers().testFlag(Qt::ControlModifier) )
|
||||||
|
emit onCtrlAltRBracket();
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
21
cockatrice/src/keysignals.h
Normal file
21
cockatrice/src/keysignals.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include <QObject>
|
||||||
|
#include <QEvent>
|
||||||
|
|
||||||
|
class KeySignals : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void onEnter();
|
||||||
|
void onCtrlEnter();
|
||||||
|
void onCtrlAltEnter();
|
||||||
|
void onLeft();
|
||||||
|
void onRight();
|
||||||
|
void onDelete();
|
||||||
|
void onCtrlAltMinus();
|
||||||
|
void onCtrlAltEqual();
|
||||||
|
void onCtrlAltLBracket();
|
||||||
|
void onCtrlAltRBracket();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool eventFilter(QObject *, QEvent *event);
|
||||||
|
};
|
|
@ -22,7 +22,6 @@
|
||||||
#include "carddatabasemodel.h"
|
#include "carddatabasemodel.h"
|
||||||
#include "decklistmodel.h"
|
#include "decklistmodel.h"
|
||||||
#include "cardinfowidget.h"
|
#include "cardinfowidget.h"
|
||||||
#include "dlg_cardsearch.h"
|
|
||||||
#include "dlg_load_deck_from_clipboard.h"
|
#include "dlg_load_deck_from_clipboard.h"
|
||||||
#include "dlg_edit_tokens.h"
|
#include "dlg_edit_tokens.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
@ -34,6 +33,9 @@
|
||||||
#include "pending_command.h"
|
#include "pending_command.h"
|
||||||
#include "pb/response.pb.h"
|
#include "pb/response.pb.h"
|
||||||
#include "pb/command_deck_upload.pb.h"
|
#include "pb/command_deck_upload.pb.h"
|
||||||
|
#include "filtertreemodel.h"
|
||||||
|
#include "cardframe.h"
|
||||||
|
#include "filterbuilder.h"
|
||||||
|
|
||||||
void SearchLineEdit::keyPressEvent(QKeyEvent *event)
|
void SearchLineEdit::keyPressEvent(QKeyEvent *event)
|
||||||
{
|
{
|
||||||
|
@ -45,9 +47,6 @@ void SearchLineEdit::keyPressEvent(QKeyEvent *event)
|
||||||
TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
||||||
: Tab(_tabSupervisor, parent), modified(false)
|
: Tab(_tabSupervisor, parent), modified(false)
|
||||||
{
|
{
|
||||||
aSearch = new QAction(QString(), this);
|
|
||||||
aSearch->setIcon(QIcon(":/resources/icon_search.svg"));
|
|
||||||
connect(aSearch, SIGNAL(triggered()), this, SLOT(actSearch()));
|
|
||||||
aClearSearch = new QAction(QString(), this);
|
aClearSearch = new QAction(QString(), this);
|
||||||
aClearSearch->setIcon(QIcon(":/resources/icon_clearsearch.svg"));
|
aClearSearch->setIcon(QIcon(":/resources/icon_clearsearch.svg"));
|
||||||
connect(aClearSearch, SIGNAL(triggered()), this, SLOT(actClearSearch()));
|
connect(aClearSearch, SIGNAL(triggered()), this, SLOT(actClearSearch()));
|
||||||
|
@ -55,25 +54,36 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
||||||
searchLabel = new QLabel();
|
searchLabel = new QLabel();
|
||||||
searchEdit = new SearchLineEdit;
|
searchEdit = new SearchLineEdit;
|
||||||
searchLabel->setBuddy(searchEdit);
|
searchLabel->setBuddy(searchEdit);
|
||||||
|
setFocusProxy(searchEdit);
|
||||||
|
setFocusPolicy(Qt::ClickFocus);
|
||||||
|
|
||||||
|
searchEdit->installEventFilter(&searchKeySignals);
|
||||||
connect(searchEdit, SIGNAL(textChanged(const QString &)), this, SLOT(updateSearch(const QString &)));
|
connect(searchEdit, SIGNAL(textChanged(const QString &)), this, SLOT(updateSearch(const QString &)));
|
||||||
connect(searchEdit, SIGNAL(returnPressed()), this, SLOT(actAddCard()));
|
connect(&searchKeySignals, SIGNAL(onEnter()), this, SLOT(actAddCard()));
|
||||||
QToolButton *searchButton = new QToolButton;
|
connect(&searchKeySignals, SIGNAL(onCtrlAltEqual()), this, SLOT(actAddCard()));
|
||||||
searchButton->setDefaultAction(aSearch);
|
connect(&searchKeySignals, SIGNAL(onCtrlAltRBracket()), this, SLOT(actAddCardToSideboard()));
|
||||||
QToolButton *clearSearchButton = new QToolButton;
|
connect(&searchKeySignals, SIGNAL(onCtrlAltMinus()), this, SLOT(actDecrementCard()));
|
||||||
clearSearchButton->setDefaultAction(aClearSearch);
|
connect(&searchKeySignals, SIGNAL(onCtrlAltLBracket()), this, SLOT(actDecrementCardFromSideboard()));
|
||||||
|
connect(&searchKeySignals, SIGNAL(onCtrlAltEnter()), this, SLOT(actAddCardToSideboard()));
|
||||||
|
connect(&searchKeySignals, SIGNAL(onCtrlEnter()), this, SLOT(actAddCardToSideboard()));
|
||||||
|
|
||||||
|
QToolBar *deckEditToolBar = new QToolBar;
|
||||||
|
deckEditToolBar->setOrientation(Qt::Horizontal);
|
||||||
|
deckEditToolBar->setIconSize(QSize(24, 24));
|
||||||
|
|
||||||
QHBoxLayout *searchLayout = new QHBoxLayout;
|
QHBoxLayout *searchLayout = new QHBoxLayout;
|
||||||
|
searchLayout->addWidget(deckEditToolBar);
|
||||||
searchLayout->addWidget(searchLabel);
|
searchLayout->addWidget(searchLabel);
|
||||||
searchLayout->addWidget(searchEdit);
|
searchLayout->addWidget(searchEdit);
|
||||||
searchLayout->addWidget(searchButton);
|
|
||||||
searchLayout->addWidget(clearSearchButton);
|
|
||||||
|
|
||||||
databaseModel = new CardDatabaseModel(db, this);
|
databaseModel = new CardDatabaseModel(db, this);
|
||||||
databaseDisplayModel = new CardDatabaseDisplayModel(this);
|
databaseDisplayModel = new CardDatabaseDisplayModel(this);
|
||||||
databaseDisplayModel->setSourceModel(databaseModel);
|
databaseDisplayModel->setSourceModel(databaseModel);
|
||||||
databaseDisplayModel->setFilterKeyColumn(0);
|
databaseDisplayModel->setFilterKeyColumn(0);
|
||||||
databaseDisplayModel->sort(0, Qt::AscendingOrder);
|
databaseDisplayModel->sort(0, Qt::AscendingOrder);
|
||||||
|
|
||||||
databaseView = new QTreeView();
|
databaseView = new QTreeView();
|
||||||
|
databaseView->setFocusProxy(searchEdit);
|
||||||
databaseView->setModel(databaseDisplayModel);
|
databaseView->setModel(databaseDisplayModel);
|
||||||
databaseView->setUniformRowHeights(true);
|
databaseView->setUniformRowHeights(true);
|
||||||
databaseView->setRootIsDecorated(false);
|
databaseView->setRootIsDecorated(false);
|
||||||
|
@ -89,21 +99,33 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
||||||
leftFrame->addLayout(searchLayout);
|
leftFrame->addLayout(searchLayout);
|
||||||
leftFrame->addWidget(databaseView);
|
leftFrame->addWidget(databaseView);
|
||||||
|
|
||||||
cardInfo = new CardInfoWidget(CardInfoWidget::ModeDeckEditor);
|
cardInfo = new CardFrame(250, 356);
|
||||||
cardInfo->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
|
aCardTextOnly = new QAction(QString(), this);
|
||||||
|
aCardTextOnly->setCheckable(true);
|
||||||
|
connect(aCardTextOnly, SIGNAL(triggered()), cardInfo, SLOT(toggleCardTextOnly()));
|
||||||
|
|
||||||
QToolBar *verticalToolBar = new QToolBar;
|
filterModel = new FilterTreeModel();
|
||||||
verticalToolBar->setOrientation(Qt::Vertical);
|
databaseDisplayModel->setFilterTree(filterModel->filterTree());
|
||||||
verticalToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
filterView = new QTreeView;
|
||||||
verticalToolBar->setIconSize(QSize(24, 24));
|
filterView->setModel(filterModel);
|
||||||
QHBoxLayout *verticalToolBarLayout = new QHBoxLayout;
|
filterView->setMaximumWidth(250);
|
||||||
verticalToolBarLayout->addStretch();
|
filterView->setUniformRowHeights(true);
|
||||||
verticalToolBarLayout->addWidget(verticalToolBar);
|
filterView->setHeaderHidden(true);
|
||||||
verticalToolBarLayout->addStretch();
|
filterView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
connect(filterModel, SIGNAL(layoutChanged()), filterView, SLOT(expandAll()));
|
||||||
|
connect(filterView, SIGNAL(customContextMenuRequested(const QPoint &)),
|
||||||
|
this, SLOT(filterViewCustomContextMenu(const QPoint &)));
|
||||||
|
FilterBuilder *filterBuilder = new FilterBuilder;
|
||||||
|
filterBuilder->setMaximumWidth(250);
|
||||||
|
connect(filterBuilder, SIGNAL(add(const CardFilter *)), filterModel, SLOT(addFilter(const CardFilter *)));
|
||||||
|
|
||||||
|
QVBoxLayout *filter = new QVBoxLayout;
|
||||||
|
filter->addWidget(filterBuilder, 0, Qt::AlignTop);
|
||||||
|
filter->addWidget(filterView, 10);
|
||||||
|
|
||||||
QVBoxLayout *middleFrame = new QVBoxLayout;
|
QVBoxLayout *middleFrame = new QVBoxLayout;
|
||||||
middleFrame->addWidget(cardInfo, 10);
|
middleFrame->addWidget(cardInfo, 0, Qt::AlignTop);
|
||||||
middleFrame->addLayout(verticalToolBarLayout);
|
middleFrame->addLayout(filter, 10);
|
||||||
|
|
||||||
deckModel = new DeckListModel(this);
|
deckModel = new DeckListModel(this);
|
||||||
connect(deckModel, SIGNAL(deckHashChanged()), this, SLOT(updateHash()));
|
connect(deckModel, SIGNAL(deckHashChanged()), this, SLOT(updateHash()));
|
||||||
|
@ -111,7 +133,14 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
||||||
deckView->setModel(deckModel);
|
deckView->setModel(deckModel);
|
||||||
deckView->setUniformRowHeights(true);
|
deckView->setUniformRowHeights(true);
|
||||||
deckView->header()->setResizeMode(QHeaderView::ResizeToContents);
|
deckView->header()->setResizeMode(QHeaderView::ResizeToContents);
|
||||||
|
deckView->installEventFilter(&deckViewKeySignals);
|
||||||
connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &)));
|
connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &)));
|
||||||
|
connect(&deckViewKeySignals, SIGNAL(onEnter()), this, SLOT(actIncrement()));
|
||||||
|
connect(&deckViewKeySignals, SIGNAL(onCtrlAltEqual()), this, SLOT(actIncrement()));
|
||||||
|
connect(&deckViewKeySignals, SIGNAL(onCtrlAltMinus()), this, SLOT(actDecrement()));
|
||||||
|
connect(&deckViewKeySignals, SIGNAL(onRight()), this, SLOT(actIncrement()));
|
||||||
|
connect(&deckViewKeySignals, SIGNAL(onLeft()), this, SLOT(actDecrement()));
|
||||||
|
connect(&deckViewKeySignals, SIGNAL(onDelete()), this, SLOT(actRemoveCard()));
|
||||||
|
|
||||||
nameLabel = new QLabel();
|
nameLabel = new QLabel();
|
||||||
nameEdit = new QLineEdit;
|
nameEdit = new QLineEdit;
|
||||||
|
@ -160,7 +189,7 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
||||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||||
mainLayout->addLayout(leftFrame, 10);
|
mainLayout->addLayout(leftFrame, 10);
|
||||||
mainLayout->addLayout(middleFrame);
|
mainLayout->addLayout(middleFrame);
|
||||||
mainLayout->addLayout(rightFrame, 10);
|
mainLayout->addLayout(rightFrame);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
aNewDeck = new QAction(QString(), this);
|
aNewDeck = new QAction(QString(), this);
|
||||||
|
@ -214,8 +243,8 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
||||||
dbMenu->addAction(aEditSets);
|
dbMenu->addAction(aEditSets);
|
||||||
dbMenu->addAction(aEditTokens);
|
dbMenu->addAction(aEditTokens);
|
||||||
dbMenu->addSeparator();
|
dbMenu->addSeparator();
|
||||||
dbMenu->addAction(aSearch);
|
|
||||||
dbMenu->addAction(aClearSearch);
|
dbMenu->addAction(aClearSearch);
|
||||||
|
dbMenu->addAction(aCardTextOnly);
|
||||||
addTabMenu(dbMenu);
|
addTabMenu(dbMenu);
|
||||||
|
|
||||||
aAddCard = new QAction(QString(), this);
|
aAddCard = new QAction(QString(), this);
|
||||||
|
@ -234,14 +263,12 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
||||||
aDecrement->setIcon(QIcon(":/resources/decrement.svg"));
|
aDecrement->setIcon(QIcon(":/resources/decrement.svg"));
|
||||||
connect(aDecrement, SIGNAL(triggered()), this, SLOT(actDecrement()));
|
connect(aDecrement, SIGNAL(triggered()), this, SLOT(actDecrement()));
|
||||||
|
|
||||||
verticalToolBar->addAction(aAddCard);
|
deckEditToolBar->addAction(aAddCard);
|
||||||
verticalToolBar->addAction(aAddCardToSideboard);
|
deckEditToolBar->addAction(aAddCardToSideboard);
|
||||||
verticalToolBar->addAction(aRemoveCard);
|
deckEditToolBar->addAction(aRemoveCard);
|
||||||
verticalToolBar->addAction(aIncrement);
|
deckEditToolBar->addAction(aIncrement);
|
||||||
verticalToolBar->addAction(aDecrement);
|
deckEditToolBar->addAction(aDecrement);
|
||||||
verticalToolBar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
deckEditToolBar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||||
|
|
||||||
dlgCardSearch = new DlgCardSearch(this);
|
|
||||||
|
|
||||||
retranslateUi();
|
retranslateUi();
|
||||||
|
|
||||||
|
@ -255,7 +282,7 @@ TabDeckEditor::~TabDeckEditor()
|
||||||
|
|
||||||
void TabDeckEditor::retranslateUi()
|
void TabDeckEditor::retranslateUi()
|
||||||
{
|
{
|
||||||
aSearch->setText(tr("&Search..."));
|
aCardTextOnly->setText(tr("Show card text only"));
|
||||||
aClearSearch->setText(tr("&Clear search"));
|
aClearSearch->setText(tr("&Clear search"));
|
||||||
searchLabel->setText(tr("&Search for:"));
|
searchLabel->setText(tr("&Search for:"));
|
||||||
|
|
||||||
|
@ -278,9 +305,8 @@ void TabDeckEditor::retranslateUi()
|
||||||
aClose->setShortcut(tr("Ctrl+Q"));
|
aClose->setShortcut(tr("Ctrl+Q"));
|
||||||
|
|
||||||
aAddCard->setText(tr("Add card to &maindeck"));
|
aAddCard->setText(tr("Add card to &maindeck"));
|
||||||
aAddCard->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Return")) << QKeySequence(tr("Enter")));
|
|
||||||
aAddCardToSideboard->setText(tr("Add card to &sideboard"));
|
aAddCardToSideboard->setText(tr("Add card to &sideboard"));
|
||||||
aAddCardToSideboard->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Ctrl+Return")) << QKeySequence(tr("Ctrl+Enter")));
|
|
||||||
aRemoveCard->setText(tr("&Remove row"));
|
aRemoveCard->setText(tr("&Remove row"));
|
||||||
aRemoveCard->setShortcut(tr("Del"));
|
aRemoveCard->setShortcut(tr("Del"));
|
||||||
aIncrement->setText(tr("&Increment number"));
|
aIncrement->setText(tr("&Increment number"));
|
||||||
|
@ -497,17 +523,6 @@ void TabDeckEditor::actEditTokens()
|
||||||
db->saveToFile(settingsCache->getTokenDatabasePath(), true);
|
db->saveToFile(settingsCache->getTokenDatabasePath(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabDeckEditor::actSearch()
|
|
||||||
{
|
|
||||||
if (dlgCardSearch->exec()) {
|
|
||||||
searchEdit->clear();
|
|
||||||
databaseDisplayModel->setCardName(dlgCardSearch->getCardName());
|
|
||||||
databaseDisplayModel->setCardText(dlgCardSearch->getCardText());
|
|
||||||
databaseDisplayModel->setCardTypes(dlgCardSearch->getCardTypes());
|
|
||||||
databaseDisplayModel->setCardColors(dlgCardSearch->getCardColors());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabDeckEditor::actClearSearch()
|
void TabDeckEditor::actClearSearch()
|
||||||
{
|
{
|
||||||
databaseDisplayModel->clearSearch();
|
databaseDisplayModel->clearSearch();
|
||||||
|
@ -520,21 +535,29 @@ void TabDeckEditor::recursiveExpand(const QModelIndex &index)
|
||||||
deckView->expand(index);
|
deckView->expand(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabDeckEditor::addCardHelper(QString zoneName)
|
CardInfo *TabDeckEditor::currentCardInfo() const
|
||||||
{
|
{
|
||||||
const QModelIndex currentIndex = databaseView->selectionModel()->currentIndex();
|
const QModelIndex currentIndex = databaseView->selectionModel()->currentIndex();
|
||||||
if (!currentIndex.isValid())
|
if (!currentIndex.isValid())
|
||||||
return;
|
return NULL;
|
||||||
const QString cardName = currentIndex.sibling(currentIndex.row(), 0).data().toString();
|
const QString cardName = currentIndex.sibling(currentIndex.row(), 0).data().toString();
|
||||||
|
|
||||||
CardInfo *info = db->getCard(cardName);
|
return db->getCard(cardName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::addCardHelper(QString zoneName)
|
||||||
|
{
|
||||||
|
const CardInfo *info;
|
||||||
|
|
||||||
|
info = currentCardInfo();
|
||||||
|
if(!info)
|
||||||
|
return;
|
||||||
if (info->getIsToken())
|
if (info->getIsToken())
|
||||||
zoneName = "tokens";
|
zoneName = "tokens";
|
||||||
|
|
||||||
QModelIndex newCardIndex = deckModel->addCard(cardName, zoneName);
|
QModelIndex newCardIndex = deckModel->addCard(info->getName(), zoneName);
|
||||||
recursiveExpand(newCardIndex);
|
recursiveExpand(newCardIndex);
|
||||||
deckView->setCurrentIndex(newCardIndex);
|
deckView->setCurrentIndex(newCardIndex);
|
||||||
|
|
||||||
setModified(true);
|
setModified(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,31 +580,57 @@ void TabDeckEditor::actRemoveCard()
|
||||||
setModified(true);
|
setModified(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::offsetCountAtIndex(const QModelIndex &idx, int offset)
|
||||||
|
{
|
||||||
|
if (!idx.isValid() || offset == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QModelIndex numberIndex = idx.sibling(idx.row(), 0);
|
||||||
|
const int count = deckModel->data(numberIndex, Qt::EditRole).toInt();
|
||||||
|
const int new_count = count + offset;
|
||||||
|
deckView->setCurrentIndex(numberIndex);
|
||||||
|
if (new_count <= 0)
|
||||||
|
deckModel->removeRow(idx.row(), idx.parent());
|
||||||
|
else
|
||||||
|
deckModel->setData(numberIndex, new_count, Qt::EditRole);
|
||||||
|
setModified(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::decrementCardHelper(QString zoneName)
|
||||||
|
{
|
||||||
|
const CardInfo *info;
|
||||||
|
QModelIndex idx;
|
||||||
|
|
||||||
|
info = currentCardInfo();
|
||||||
|
if(!info)
|
||||||
|
return;
|
||||||
|
if (info->getIsToken())
|
||||||
|
zoneName = "tokens";
|
||||||
|
|
||||||
|
idx = deckModel->findCard(info->getName(), zoneName);
|
||||||
|
offsetCountAtIndex(idx, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::actDecrementCard()
|
||||||
|
{
|
||||||
|
decrementCardHelper("main");
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::actDecrementCardFromSideboard()
|
||||||
|
{
|
||||||
|
decrementCardHelper("side");
|
||||||
|
}
|
||||||
|
|
||||||
void TabDeckEditor::actIncrement()
|
void TabDeckEditor::actIncrement()
|
||||||
{
|
{
|
||||||
const QModelIndex ¤tIndex = deckView->selectionModel()->currentIndex();
|
const QModelIndex ¤tIndex = deckView->selectionModel()->currentIndex();
|
||||||
if (!currentIndex.isValid())
|
offsetCountAtIndex(currentIndex, 1);
|
||||||
return;
|
|
||||||
const QModelIndex numberIndex = currentIndex.sibling(currentIndex.row(), 0);
|
|
||||||
const int count = deckModel->data(numberIndex, Qt::EditRole).toInt();
|
|
||||||
deckView->setCurrentIndex(numberIndex);
|
|
||||||
deckModel->setData(numberIndex, count + 1, Qt::EditRole);
|
|
||||||
setModified(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabDeckEditor::actDecrement()
|
void TabDeckEditor::actDecrement()
|
||||||
{
|
{
|
||||||
const QModelIndex ¤tIndex = deckView->selectionModel()->currentIndex();
|
const QModelIndex ¤tIndex = deckView->selectionModel()->currentIndex();
|
||||||
if (!currentIndex.isValid())
|
offsetCountAtIndex(currentIndex, -1);
|
||||||
return;
|
|
||||||
const QModelIndex numberIndex = currentIndex.sibling(currentIndex.row(), 0);
|
|
||||||
const int count = deckModel->data(numberIndex, Qt::EditRole).toInt();
|
|
||||||
deckView->setCurrentIndex(numberIndex);
|
|
||||||
if (count == 1)
|
|
||||||
deckModel->removeRow(currentIndex.row(), currentIndex.parent());
|
|
||||||
else
|
|
||||||
deckModel->setData(numberIndex, count - 1, Qt::EditRole);
|
|
||||||
setModified(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabDeckEditor::actUpdatePrices()
|
void TabDeckEditor::actUpdatePrices()
|
||||||
|
@ -620,3 +669,31 @@ void TabDeckEditor::setModified(bool _modified)
|
||||||
modified = _modified;
|
modified = _modified;
|
||||||
emit tabTextChanged(this, getTabText());
|
emit tabTextChanged(this, getTabText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::filterViewCustomContextMenu(const QPoint &point) {
|
||||||
|
QMenu menu;
|
||||||
|
QAction *action;
|
||||||
|
QModelIndex idx;
|
||||||
|
|
||||||
|
idx = filterView->indexAt(point);
|
||||||
|
if (!idx.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
action = menu.addAction(QString("delete"));
|
||||||
|
action->setData(point);
|
||||||
|
connect(&menu, SIGNAL(triggered(QAction *)),
|
||||||
|
this, SLOT(filterRemove(QAction *)));
|
||||||
|
menu.exec(filterView->mapToGlobal(point));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::filterRemove(QAction *action) {
|
||||||
|
QPoint point;
|
||||||
|
QModelIndex idx;
|
||||||
|
|
||||||
|
point = action->data().toPoint();
|
||||||
|
idx = filterView->indexAt(point);
|
||||||
|
if (!idx.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
filterModel->removeRow(idx.row(), idx.parent());
|
||||||
|
}
|
||||||
|
|
|
@ -4,18 +4,20 @@
|
||||||
#include "tab.h"
|
#include "tab.h"
|
||||||
#include <QAbstractItemModel>
|
#include <QAbstractItemModel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
|
#include "keysignals.h"
|
||||||
|
|
||||||
class CardDatabaseModel;
|
class CardDatabaseModel;
|
||||||
class CardDatabaseDisplayModel;
|
class CardDatabaseDisplayModel;
|
||||||
class DeckListModel;
|
class DeckListModel;
|
||||||
class QTreeView;
|
class QTreeView;
|
||||||
class QTableView;
|
class QTableView;
|
||||||
class CardInfoWidget;
|
class CardFrame;
|
||||||
class QTextEdit;
|
class QTextEdit;
|
||||||
class DlgCardSearch;
|
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class DeckLoader;
|
class DeckLoader;
|
||||||
class Response;
|
class Response;
|
||||||
|
class FilterTreeModel;
|
||||||
|
class CardInfo;
|
||||||
|
|
||||||
class SearchLineEdit : public QLineEdit {
|
class SearchLineEdit : public QLineEdit {
|
||||||
private:
|
private:
|
||||||
|
@ -49,7 +51,6 @@ private slots:
|
||||||
void actEditSets();
|
void actEditSets();
|
||||||
void actEditTokens();
|
void actEditTokens();
|
||||||
|
|
||||||
void actSearch();
|
|
||||||
void actClearSearch();
|
void actClearSearch();
|
||||||
|
|
||||||
void actAddCard();
|
void actAddCard();
|
||||||
|
@ -57,12 +58,20 @@ private slots:
|
||||||
void actRemoveCard();
|
void actRemoveCard();
|
||||||
void actIncrement();
|
void actIncrement();
|
||||||
void actDecrement();
|
void actDecrement();
|
||||||
|
void actDecrementCard();
|
||||||
|
void actDecrementCardFromSideboard();
|
||||||
|
|
||||||
void actUpdatePrices();
|
void actUpdatePrices();
|
||||||
|
|
||||||
void finishedUpdatingPrices();
|
void finishedUpdatingPrices();
|
||||||
void saveDeckRemoteFinished(const Response &r);
|
void saveDeckRemoteFinished(const Response &r);
|
||||||
|
void filterViewCustomContextMenu(const QPoint &point);
|
||||||
|
void filterRemove(QAction *action);
|
||||||
private:
|
private:
|
||||||
|
CardInfo *currentCardInfo() const;
|
||||||
void addCardHelper(QString zoneName);
|
void addCardHelper(QString zoneName);
|
||||||
|
void offsetCountAtIndex(const QModelIndex &idx, int offset);
|
||||||
|
void decrementCardHelper(QString zoneName);
|
||||||
void recursiveExpand(const QModelIndex &index);
|
void recursiveExpand(const QModelIndex &index);
|
||||||
bool confirmClose();
|
bool confirmClose();
|
||||||
|
|
||||||
|
@ -70,21 +79,26 @@ private:
|
||||||
CardDatabaseDisplayModel *databaseDisplayModel;
|
CardDatabaseDisplayModel *databaseDisplayModel;
|
||||||
DeckListModel *deckModel;
|
DeckListModel *deckModel;
|
||||||
QTreeView *databaseView;
|
QTreeView *databaseView;
|
||||||
|
|
||||||
QTreeView *deckView;
|
QTreeView *deckView;
|
||||||
CardInfoWidget *cardInfo;
|
KeySignals deckViewKeySignals;
|
||||||
|
CardFrame *cardInfo;
|
||||||
QLabel *searchLabel;
|
QLabel *searchLabel;
|
||||||
SearchLineEdit *searchEdit;
|
SearchLineEdit *searchEdit;
|
||||||
|
KeySignals searchKeySignals;
|
||||||
|
|
||||||
QLabel *nameLabel;
|
QLabel *nameLabel;
|
||||||
QLineEdit *nameEdit;
|
QLineEdit *nameEdit;
|
||||||
QLabel *commentsLabel;
|
QLabel *commentsLabel;
|
||||||
QTextEdit *commentsEdit;
|
QTextEdit *commentsEdit;
|
||||||
QLabel *hashLabel1;
|
QLabel *hashLabel1;
|
||||||
QLabel *hashLabel;
|
QLabel *hashLabel;
|
||||||
DlgCardSearch *dlgCardSearch;
|
FilterTreeModel *filterModel;
|
||||||
|
QTreeView *filterView;
|
||||||
|
|
||||||
QMenu *deckMenu, *dbMenu;
|
QMenu *deckMenu, *dbMenu;
|
||||||
QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aPrintDeck, *aAnalyzeDeck, *aClose;
|
QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aPrintDeck, *aAnalyzeDeck, *aClose;
|
||||||
QAction *aEditSets, *aEditTokens, *aSearch, *aClearSearch;
|
QAction *aEditSets, *aEditTokens, *aClearSearch, *aCardTextOnly;
|
||||||
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement, *aUpdatePrices;
|
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement, *aUpdatePrices;
|
||||||
|
|
||||||
bool modified;
|
bool modified;
|
||||||
|
|
Loading…
Reference in a new issue