diff --git a/cockatrice/src/carddatabase.cpp b/cockatrice/src/carddatabase.cpp index 2045f95e..3b8d9e95 100644 --- a/cockatrice/src/carddatabase.cpp +++ b/cockatrice/src/carddatabase.cpp @@ -295,6 +295,8 @@ QString CardInfo::getMainCardType() const int pos; if ((pos = result.indexOf('-')) != -1) result.remove(pos, result.length()); + if ((pos = result.indexOf("—")) != -1) + result.remove(pos, result.length()); if ((pos = result.indexOf("//")) != -1) result.remove(pos, result.length()); result = result.simplified(); diff --git a/cockatrice/src/decklistmodel.cpp b/cockatrice/src/decklistmodel.cpp index e8518046..00d92fae 100644 --- a/cockatrice/src/decklistmodel.cpp +++ b/cockatrice/src/decklistmodel.cpp @@ -14,7 +14,7 @@ #include "deck_loader.h" DeckListModel::DeckListModel(QObject *parent) - : QAbstractItemModel(parent) + : QAbstractItemModel(parent), lastKnownColumn(1), lastKnownOrder(Qt::AscendingOrder) { deckList = new DeckLoader; connect(deckList, SIGNAL(deckLoaded()), this, SLOT(rebuildTree())); @@ -275,23 +275,20 @@ QModelIndex DeckListModel::addCard(const QString &cardName, const QString &zoneN QString cardType = info->getMainCardType(); InnerDecklistNode *cardTypeNode = createNodeIfNeeded(cardType, zoneNode); + QModelIndex parentIndex = nodeToIndex(cardTypeNode); DecklistModelCardNode *cardNode = dynamic_cast(cardTypeNode->findChild(cardName)); if (!cardNode) { DecklistCardNode *decklistCard = deckList->addCard(cardName, zoneName); - QModelIndex parentIndex = nodeToIndex(cardTypeNode); beginInsertRows(parentIndex, cardTypeNode->size(), cardTypeNode->size()); cardNode = new DecklistModelCardNode(decklistCard, cardTypeNode); endInsertRows(); - sort(1); - emitRecursiveUpdates(parentIndex); - return nodeToIndex(cardNode); } else { cardNode->setNumber(cardNode->getNumber() + 1); - QModelIndex ind = nodeToIndex(cardNode); - emitRecursiveUpdates(ind); deckList->updateDeckHash(); - return ind; } + sort(lastKnownColumn, lastKnownOrder); + emitRecursiveUpdates(parentIndex); + return nodeToIndex(cardNode); } QModelIndex DeckListModel::nodeToIndex(AbstractDecklistNode *node) const @@ -318,7 +315,7 @@ void DeckListModel::sortHelper(InnerDecklistNode *node, Qt::SortOrder order) } } changePersistentIndexList(from, to); - + // Recursion for (int i = node->size() - 1; i >= 0; --i) { InnerDecklistNode *subNode = dynamic_cast(node->at(i)); @@ -327,9 +324,24 @@ void DeckListModel::sortHelper(InnerDecklistNode *node, Qt::SortOrder order) } } -void DeckListModel::sort(int /*column*/, Qt::SortOrder order) +void DeckListModel::sort(int column, Qt::SortOrder order) { + lastKnownColumn = column; + lastKnownOrder = order; + emit layoutAboutToBeChanged(); + DeckSortMethod sortMethod; + switch(column) { + case 0: + sortMethod = ByNumber; + break; + case 1: + sortMethod = ByName; + break; + case 2: + sortMethod = ByPrice; + } + root->setSortMethod(sortMethod); sortHelper(root, order); emit layoutChanged(); } diff --git a/cockatrice/src/decklistmodel.h b/cockatrice/src/decklistmodel.h index 27376c7a..2873c818 100644 --- a/cockatrice/src/decklistmodel.h +++ b/cockatrice/src/decklistmodel.h @@ -55,6 +55,8 @@ public: private: DeckLoader *deckList; InnerDecklistNode *root; + int lastKnownColumn; + Qt::SortOrder lastKnownOrder; InnerDecklistNode *createNodeIfNeeded(const QString &name, InnerDecklistNode *parent); QModelIndex nodeToIndex(AbstractDecklistNode *node) const; DecklistModelCardNode *findCardNode(const QString &cardName, const QString &zoneName) const; diff --git a/cockatrice/src/main.cpp b/cockatrice/src/main.cpp index 4c953e51..84975fb1 100644 --- a/cockatrice/src/main.cpp +++ b/cockatrice/src/main.cpp @@ -108,9 +108,9 @@ int main(int argc, char *argv[]) qtTranslator = new QTranslator; translator = new QTranslator; installNewTranslator(); - + qsrand(QDateTime::currentDateTime().toTime_t()); - + bool startMainProgram = true; const QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation); if (!db->getLoadSuccess()) diff --git a/cockatrice/src/tab_deck_editor.cpp b/cockatrice/src/tab_deck_editor.cpp index 91c8819e..11ec0d3d 100644 --- a/cockatrice/src/tab_deck_editor.cpp +++ b/cockatrice/src/tab_deck_editor.cpp @@ -132,6 +132,8 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent) deckView = new QTreeView(); deckView->setModel(deckModel); deckView->setUniformRowHeights(true); + deckView->setSortingEnabled(true); + deckView->sortByColumn(1, Qt::AscendingOrder); deckView->header()->setResizeMode(QHeaderView::ResizeToContents); deckView->installEventFilter(&deckViewKeySignals); connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &))); @@ -655,10 +657,10 @@ void TabDeckEditor::setDeck(DeckLoader *_deck) nameEdit->setText(deckModel->getDeckList()->getName()); commentsEdit->setText(deckModel->getDeckList()->getComments()); updateHash(); - deckModel->sort(1); + deckModel->sort(deckView->header()->sortIndicatorSection(), deckView->header()->sortIndicatorOrder()); deckView->expandAll(); setModified(false); - + db->cacheCardPixmaps(deckModel->getDeckList()->getCardList()); deckView->expandAll(); setModified(false); diff --git a/common/decklist.cpp b/common/decklist.cpp index d9a3d7f3..8ba9378e 100644 --- a/common/decklist.cpp +++ b/common/decklist.cpp @@ -104,6 +104,13 @@ QString InnerDecklistNode::visibleNameFromName(const QString &_name) return _name; } +void InnerDecklistNode::setSortMethod(DeckSortMethod method) +{ + sortMethod = method; + for (int i = 0; i < size(); i++) + at(i)->setSortMethod(method); +} + QString InnerDecklistNode::getVisibleName() const { return visibleNameFromName(name); @@ -163,21 +170,95 @@ float InnerDecklistNode::recursivePrice(bool countTotalCards) const } bool InnerDecklistNode::compare(AbstractDecklistNode *other) const +{ + switch (sortMethod) { + case 0: + return compareNumber(other); + case 1: + return compareName(other); + case 2: + return comparePrice(other); + } +} + +bool InnerDecklistNode::compareNumber(AbstractDecklistNode *other) const { InnerDecklistNode *other2 = dynamic_cast(other); - if (other2) - return (getName() > other->getName()); - else + if (other2) { + int n1 = recursiveCount(true); + int n2 = other2->recursiveCount(true); + return (n1 != n2) ? (n1 > n2) : compareName(other); + } else { return false; + } +} + +bool InnerDecklistNode::compareName(AbstractDecklistNode *other) const +{ + InnerDecklistNode *other2 = dynamic_cast(other); + if (other2) { + return (getName() > other2->getName()); + } else { + return false; + } +} + +bool InnerDecklistNode::comparePrice(AbstractDecklistNode *other) const +{ + InnerDecklistNode *other2 = dynamic_cast(other); + if (other2) { + int p1 = 100*recursivePrice(true); + int p2 = 100*other2->recursivePrice(true); + return (p1 != p2) ? (p1 > p2) : compareName(other); + } else { + return false; + } } bool AbstractDecklistCardNode::compare(AbstractDecklistNode *other) const +{ + switch (sortMethod) { + case ByNumber: + return compareNumber(other); + case ByName: + return compareName(other); + case ByPrice: + return compareTotalPrice(other); + } +} + +bool AbstractDecklistCardNode::compareNumber(AbstractDecklistNode *other) const { AbstractDecklistCardNode *other2 = dynamic_cast(other); - if (other2) - return (getName() > other->getName()); - else + if (other2) { + int n1 = getNumber(); + int n2 = other2->getNumber(); + return (n1 != n2) ? (n1 > n2) : compareName(other); + } else { return true; + } +} + +bool AbstractDecklistCardNode::compareName(AbstractDecklistNode *other) const +{ + AbstractDecklistCardNode *other2 = dynamic_cast(other); + if (other2) { + return (getName() > other2->getName()); + } else { + return true; + } +} + +bool AbstractDecklistCardNode::compareTotalPrice(AbstractDecklistNode *other) const +{ + AbstractDecklistCardNode *other2 = dynamic_cast(other); + if (other2) { + int p1 = 100*getTotalPrice(); + int p2 = 100*other2->getTotalPrice(); + return (p1 != p2) ? (p1 > p2) : compareName(other); + } else { + return true; + } } class InnerDecklistNode::compareFunctor { diff --git a/common/decklist.h b/common/decklist.h index 2e8f4a9b..94df407a 100644 --- a/common/decklist.h +++ b/common/decklist.h @@ -29,24 +29,28 @@ public: SideboardPlan(const QString &_name = QString(), const QList &_moveList = QList()); bool readElement(QXmlStreamReader *xml); void write(QXmlStreamWriter *xml); - + QString getName() const { return name; } const QList &getMoveList() const { return moveList; } void setMoveList(const QList &_moveList); }; +enum DeckSortMethod { ByNumber, ByName, ByPrice }; + class AbstractDecklistNode { protected: InnerDecklistNode *parent; + DeckSortMethod sortMethod; public: AbstractDecklistNode(InnerDecklistNode *_parent = 0); virtual ~AbstractDecklistNode() { } + virtual void setSortMethod(DeckSortMethod method) { sortMethod = method; } virtual QString getName() const = 0; InnerDecklistNode *getParent() const { return parent; } int depth() const; virtual int height() const = 0; virtual bool compare(AbstractDecklistNode *other) const = 0; - + virtual bool readElement(QXmlStreamReader *xml) = 0; virtual void writeElement(QXmlStreamWriter *xml) = 0; }; @@ -59,6 +63,7 @@ public: InnerDecklistNode(const QString &_name = QString(), InnerDecklistNode *_parent = 0) : AbstractDecklistNode(_parent), name(_name) { } InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent = 0); virtual ~InnerDecklistNode(); + void setSortMethod(DeckSortMethod method); QString getName() const { return name; } void setName(const QString &_name) { name = _name; } static QString visibleNameFromName(const QString &_name); @@ -69,8 +74,11 @@ public: int recursiveCount(bool countTotalCards = false) const; float recursivePrice(bool countTotalCards = false) const; bool compare(AbstractDecklistNode *other) const; + bool compareNumber(AbstractDecklistNode *other) const; + bool compareName(AbstractDecklistNode *other) const; + bool comparePrice(AbstractDecklistNode *other) const; QVector > sort(Qt::SortOrder order = Qt::AscendingOrder); - + bool readElement(QXmlStreamReader *xml); void writeElement(QXmlStreamWriter *xml); }; @@ -87,7 +95,10 @@ public: float getTotalPrice() const { return getNumber() * getPrice(); } int height() const { return 0; } bool compare(AbstractDecklistNode *other) const; - + bool compareNumber(AbstractDecklistNode *other) const; + bool compareName(AbstractDecklistNode *other) const; + bool compareTotalPrice(AbstractDecklistNode *other) const; + bool readElement(QXmlStreamReader *xml); void writeElement(QXmlStreamWriter *xml); }; diff --git a/doc/usermanual/Usermanual.pdf b/doc/usermanual/Usermanual.pdf index 2fdcdb3f..3d279df3 100644 Binary files a/doc/usermanual/Usermanual.pdf and b/doc/usermanual/Usermanual.pdf differ diff --git a/doc/usermanual/Usermanual.tex b/doc/usermanual/Usermanual.tex index 634c0040..e87ffa2f 100644 --- a/doc/usermanual/Usermanual.tex +++ b/doc/usermanual/Usermanual.tex @@ -224,7 +224,7 @@ Start the oracle.exe (the installer does this automatically) and let it generate \end{enumerate} Congratulations, you may now use Cockatrice! -\subsubsection{Linux and BSD} +\subsubsection{Linux, BSD, OS X} The following procedures have been tested with Debian Wheezy, Fedora 18, XUbuntu 13.10, FreeBSD 9.1 and 10.0. If you use Gentoo with KDE you have the needed prerequisites and may continue with downloading the source. If you use Bodhi or Arch Linux (AUR) or another distribution that includes Cockatrice, you might install Cockatrice from the default packages -- though the package might be old, @@ -239,6 +239,7 @@ Before you install new software, you should update your system. The following in yum install qt-devel qt-mobility-devel protobuf-devel protobuf-compiler cmake} \item[FreeBSD 9] \shellcmd{pkg\_add -r qt4 qt4-linguist qt4-moc qt4-qmake qt4-rcc qt4-uic git cmake protobuf} \item[FreeBSD 10] \shellcmd{pkg install qt4 qt4-linguist qt4-moc qt4-qmake qt4-rcc qt4-uic git cmake protobuf} + \item[OS X] \shellcmd{brew install qt cmake protobuf} \end{description} \item Download the sources from github via \\ \shellcmd{cd\\ git clone https://github.com/Daenyth/Cockatrice.git} \item To compile the sources, change into the newly created directory, create a build directory and invoke cmake:\\ @@ -253,9 +254,6 @@ make}\\ The default paths for decks, pics, cards and tokens are located in \\ \shellcmd{/home//.local/share/data/Cockatrice/Cockatrice}. \end{enumerate} -\subsubsection{MacOS X} -TODO, please contribute this section! See Linux section, then use the \shellcmd{prepareMacRelease.sh} script from Cockatrice. - \subsection{Building the Server} You don't need your own server if you plan to play only. But as Cockatrice is open source you are free to run your own. The compilation works like already written above, but instead of invoking \shellcmd{cmake ..}, you have to do it like this: