Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Donald Haase
Cockatrice
Commits
abdaa610
Commit
abdaa610
authored
Jul 24, 2014
by
Gavin Bisesi
Browse files
Merge pull request #152 from ctrlaltca/master_feature_prices
Add pricing from deckbrew.com (refs #147)
parents
a8031321
49b3568b
Changes
9
Hide whitespace changes
Inline
Side-by-side
cockatrice/src/decklistmodel.cpp
View file @
abdaa610
...
...
@@ -472,13 +472,7 @@ void DeckListModel::printDeckList(QPrinter *printer)
doc
.
print
(
printer
);
}
void
DeckListModel
::
pricesUpdated
(
InnerDecklistNode
*
node
)
void
DeckListModel
::
pricesUpdated
()
{
if
(
!
node
)
node
=
root
;
if
(
node
->
isEmpty
())
return
;
emit
dataChanged
(
createIndex
(
0
,
2
,
node
->
at
(
0
)),
createIndex
(
node
->
size
()
-
1
,
2
,
node
->
last
()));
emit
layoutChanged
();
}
cockatrice/src/decklistmodel.h
View file @
abdaa610
...
...
@@ -51,7 +51,7 @@ public:
void
cleanList
();
DeckLoader
*
getDeckList
()
const
{
return
deckList
;
}
void
setDeckList
(
DeckLoader
*
_deck
);
void
pricesUpdated
(
InnerDecklistNode
*
node
=
0
);
void
pricesUpdated
();
private:
DeckLoader
*
deckList
;
InnerDecklistNode
*
root
;
...
...
cockatrice/src/dlg_settings.cpp
View file @
abdaa610
...
...
@@ -18,11 +18,13 @@
#include
<QInputDialog>
#include
<QSpinBox>
#include
<QDialogButtonBox>
#include
<QRadioButton>
#include
<QDebug>
#include
"carddatabase.h"
#include
"dlg_settings.h"
#include
"main.h"
#include
"settingscache.h"
#include
"priceupdater.h"
GeneralSettingsPage
::
GeneralSettingsPage
()
{
...
...
@@ -531,9 +533,30 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
priceTagsCheckBox
=
new
QCheckBox
;
priceTagsCheckBox
->
setChecked
(
settingsCache
->
getPriceTagFeature
());
connect
(
priceTagsCheckBox
,
SIGNAL
(
stateChanged
(
int
)),
settingsCache
,
SLOT
(
setPriceTagFeature
(
int
)));
priceTagSource0
=
new
QRadioButton
;
priceTagSource1
=
new
QRadioButton
;
switch
(
settingsCache
->
getPriceTagSource
())
{
case
AbstractPriceUpdater
::
DBPriceSource
:
priceTagSource1
->
setChecked
(
true
);
break
;
case
AbstractPriceUpdater
::
BLPPriceSource
:
default:
priceTagSource0
->
setChecked
(
true
);
break
;
}
connect
(
priceTagSource0
,
SIGNAL
(
toggled
(
bool
)),
this
,
SLOT
(
radioPriceTagSourceClicked
(
bool
)));
connect
(
priceTagSource1
,
SIGNAL
(
toggled
(
bool
)),
this
,
SLOT
(
radioPriceTagSourceClicked
(
bool
)));
connect
(
this
,
SIGNAL
(
priceTagSourceChanged
(
int
)),
settingsCache
,
SLOT
(
setPriceTagSource
(
int
)));
QGridLayout
*
generalGrid
=
new
QGridLayout
;
generalGrid
->
addWidget
(
priceTagsCheckBox
,
0
,
0
);
generalGrid
->
addWidget
(
priceTagSource0
,
1
,
0
);
generalGrid
->
addWidget
(
priceTagSource1
,
2
,
0
);
generalGroupBox
=
new
QGroupBox
;
generalGroupBox
->
setLayout
(
generalGrid
);
...
...
@@ -546,10 +569,26 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
void
DeckEditorSettingsPage
::
retranslateUi
()
{
priceTagsCheckBox
->
setText
(
tr
(
"Enable &price tag feature (using data from blacklotusproject.com)"
));
priceTagsCheckBox
->
setText
(
tr
(
"Enable &price tag feature"
));
priceTagSource0
->
setText
(
tr
(
"using data from blacklotusproject.com"
));
priceTagSource1
->
setText
(
tr
(
"using data from deckbrew.com"
));
generalGroupBox
->
setTitle
(
tr
(
"General"
));
}
void
DeckEditorSettingsPage
::
radioPriceTagSourceClicked
(
bool
checked
)
{
if
(
!
checked
)
return
;
int
source
=
AbstractPriceUpdater
::
BLPPriceSource
;
if
(
priceTagSource0
->
isChecked
())
source
=
AbstractPriceUpdater
::
BLPPriceSource
;
if
(
priceTagSource1
->
isChecked
())
source
=
AbstractPriceUpdater
::
DBPriceSource
;
emit
priceTagSourceChanged
(
source
);
}
MessagesSettingsPage
::
MessagesSettingsPage
()
{
aAdd
=
new
QAction
(
this
);
...
...
cockatrice/src/dlg_settings.h
View file @
abdaa610
...
...
@@ -15,6 +15,7 @@ class QCheckBox;
class
QLabel
;
class
QCloseEvent
;
class
QSpinBox
;
class
QRadioButton
;
class
AbstractSettingsPage
:
public
QWidget
{
public:
...
...
@@ -100,8 +101,13 @@ class DeckEditorSettingsPage : public AbstractSettingsPage {
public:
DeckEditorSettingsPage
();
void
retranslateUi
();
private
slots
:
void
radioPriceTagSourceClicked
(
bool
checked
);
signals:
void
priceTagSourceChanged
(
int
_priceTagSource
);
private:
QCheckBox
*
priceTagsCheckBox
;
QRadioButton
*
priceTagSource0
,
*
priceTagSource1
;
QGroupBox
*
generalGroupBox
;
};
...
...
cockatrice/src/priceupdater.cpp
View file @
abdaa610
...
...
@@ -4,25 +4,46 @@
*/
#include
<QNetworkAccessManager>
#include
<QNetworkReply>
#include
<QMessageBox>
#include
"qt-json/json.h"
#include
"priceupdater.h"
#include
"main.h"
#include
"carddatabase.h"
#if QT_VERSION < 0x050000
// for Qt::escape()
#include
<QtGui/qtextdocument.h>
#endif
/**
* Constructor.
*
* @param _deck deck.
*/
PriceUpdater
::
PriceUpdater
(
const
DeckList
*
_deck
)
Abstract
PriceUpdater
::
Abstract
PriceUpdater
(
const
DeckList
*
_deck
)
{
nam
=
new
QNetworkAccessManager
(
this
);
deck
=
_deck
;
}
// blacklotusproject.com
/**
* Constructor.
*
* @param _deck deck.
*/
BLPPriceUpdater
::
BLPPriceUpdater
(
const
DeckList
*
_deck
)
:
AbstractPriceUpdater
(
_deck
)
{
}
/**
* Update the prices of the cards in deckList.
*/
void
PriceUpdater
::
updatePrices
()
void
BLP
PriceUpdater
::
updatePrices
()
{
QString
q
=
"http://blacklotusproject.com/json/?cards="
;
QStringList
cards
=
deck
->
getCardList
();
...
...
@@ -38,7 +59,7 @@ void PriceUpdater::updatePrices()
/**
* Called when the download of the json file with the prices is finished.
*/
void
PriceUpdater
::
downloadFinished
()
void
BLP
PriceUpdater
::
downloadFinished
()
{
QNetworkReply
*
reply
=
static_cast
<
QNetworkReply
*>
(
sender
());
bool
ok
;
...
...
@@ -82,3 +103,183 @@ void PriceUpdater::downloadFinished()
deleteLater
();
emit
finishedUpdate
();
}
// deckbrew.com
/**
* Constructor.
*
* @param _deck deck.
*/
DBPriceUpdater
::
DBPriceUpdater
(
const
DeckList
*
_deck
)
:
AbstractPriceUpdater
(
_deck
)
{
}
/**
* Update the prices of the cards in deckList.
*/
void
DBPriceUpdater
::
updatePrices
()
{
QString
base
=
"https://api.deckbrew.com/mtg/cards"
,
q
=
""
;
QStringList
cards
=
deck
->
getCardList
();
muidMap
.
clear
();
urls
.
clear
();
CardInfo
*
card
;
int
muid
;
SetList
sets
;
bool
bNotFirst
=
false
;
for
(
int
i
=
0
;
i
<
cards
.
size
();
++
i
)
{
card
=
db
->
getCard
(
cards
[
i
],
false
);
sets
=
card
->
getSets
();
for
(
int
j
=
0
;
j
<
sets
.
size
();
++
j
)
{
muid
=
card
->
getMuId
(
sets
[
j
]
->
getShortName
());
//qDebug() << "muid " << muid << " card: " << cards[i] << endl;
if
(
bNotFirst
)
{
q
+=
QString
(
"&m=%1"
).
arg
(
muid
);
}
else
{
q
+=
QString
(
"?m=%1"
).
arg
(
muid
);
bNotFirst
=
true
;
}
muidMap
.
insert
(
muid
,
cards
[
i
]);
if
(
q
.
length
()
>
240
)
{
urls
.
append
(
base
+
q
);
bNotFirst
=
false
;
q
=
""
;
}
}
}
if
(
q
.
length
()
>
0
)
urls
.
append
(
base
+
q
);
requestNext
();
}
void
DBPriceUpdater
::
requestNext
()
{
if
(
urls
.
empty
())
return
;
QUrl
url
(
urls
.
takeFirst
(),
QUrl
::
TolerantMode
);
//qDebug() << "request prices from: " << url.toString() << endl;
QNetworkReply
*
reply
=
nam
->
get
(
QNetworkRequest
(
url
));
connect
(
reply
,
SIGNAL
(
finished
()),
this
,
SLOT
(
downloadFinished
()));
}
/**
* Called when the download of the json file with the prices is finished.
*/
void
DBPriceUpdater
::
downloadFinished
()
{
QNetworkReply
*
reply
=
static_cast
<
QNetworkReply
*>
(
sender
());
bool
ok
;
QString
tmp
=
QString
(
reply
->
readAll
());
// Errors are incapsulated in an object, check for them first
QVariantMap
resultMap
=
QtJson
::
Json
::
parse
(
tmp
,
ok
).
toMap
();
if
(
!
ok
)
{
QMessageBox
::
critical
(
this
,
tr
(
"Error"
),
tr
(
"A problem has occured while fetching card prices."
));
reply
->
deleteLater
();
if
(
urls
.
isEmpty
())
{
deleteLater
();
emit
finishedUpdate
();
}
else
{
requestNext
();
}
}
if
(
resultMap
.
contains
(
"errors"
))
{
QMessageBox
::
critical
(
this
,
tr
(
"Error"
),
tr
(
"A problem has occured while fetching card prices:"
)
+
"<br/>"
+
#if QT_VERSION < 0x050000
Qt
::
escape
(
resultMap
[
"errors"
].
toList
().
first
().
toString
())
#else
resultMap
[
"errors"
].
toList
().
first
().
toString
().
toHtmlEscaped
()
#endif
);
reply
->
deleteLater
();
if
(
urls
.
isEmpty
())
{
deleteLater
();
emit
finishedUpdate
();
}
else
{
requestNext
();
}
}
// Good results are a list
QVariantList
resultList
=
QtJson
::
Json
::
parse
(
tmp
,
ok
).
toList
();
if
(
!
ok
)
{
QMessageBox
::
critical
(
this
,
tr
(
"Error"
),
tr
(
"A problem has occured while fetching card prices."
));
reply
->
deleteLater
();
if
(
urls
.
isEmpty
())
{
deleteLater
();
emit
finishedUpdate
();
}
else
{
requestNext
();
}
}
QMap
<
QString
,
float
>
cardsPrice
;
QListIterator
<
QVariant
>
it
(
resultList
);
while
(
it
.
hasNext
())
{
QVariantMap
cardMap
=
it
.
next
().
toMap
();
// get sets list
QList
<
QVariant
>
editions
=
cardMap
.
value
(
"editions"
).
toList
();
foreach
(
QVariant
ed
,
editions
)
{
// retrieve card name "as we know it" from the muid
QVariantMap
edition
=
ed
.
toMap
();
QString
set
=
edition
.
value
(
"set_id"
).
toString
();
int
muid
=
edition
.
value
(
"multiverse_id"
).
toString
().
toInt
();
if
(
!
muidMap
.
contains
(
muid
))
continue
;
QString
name
=
muidMap
.
value
(
muid
);
// Prices are in USD cents
float
price
=
edition
.
value
(
"price"
).
toMap
().
value
(
"median"
).
toString
().
toFloat
()
/
100
;
//qDebug() << "card " << name << " set " << set << " price " << price << endl;
/**
* Make sure Masters Edition (MED) isn't the set, as it doesn't
* physically exist. Also check the price to see that the cheapest set
* ends up as the final price.
*/
if
(
set
!=
"MED"
&&
price
>
0
&&
(
!
cardsPrice
.
contains
(
name
)
||
cardsPrice
.
value
(
name
)
>
price
))
cardsPrice
.
insert
(
name
,
price
);
}
}
InnerDecklistNode
*
listRoot
=
deck
->
getRoot
();
for
(
int
i
=
0
;
i
<
listRoot
->
size
();
i
++
)
{
InnerDecklistNode
*
currentZone
=
dynamic_cast
<
InnerDecklistNode
*>
(
listRoot
->
at
(
i
));
for
(
int
j
=
0
;
j
<
currentZone
->
size
();
j
++
)
{
DecklistCardNode
*
currentCard
=
dynamic_cast
<
DecklistCardNode
*>
(
currentZone
->
at
(
j
));
if
(
!
currentCard
)
continue
;
float
price
=
cardsPrice
[
currentCard
->
getName
()];
if
(
price
>
0
)
currentCard
->
setPrice
(
price
);
}
}
reply
->
deleteLater
();
if
(
urls
.
isEmpty
())
{
deleteLater
();
emit
finishedUpdate
();
}
else
{
requestNext
();
}
}
cockatrice/src/priceupdater.h
View file @
abdaa610
#ifndef PRICEUPDATER_H
#define PRICEUPDATER_H
#include
<QNetwork
Reply
>
#include
<QNetwork
AccessManager
>
#include
"decklist.h"
class
QNetworkAccessManager
;
// If we don't typedef this, won't compile on OS X < 10.9
typedef
QMap
<
int
,
QString
>
MuidStringMap
;
/**
* Price Updater.
*
* @author Marcio Ribeiro <mmr@b1n.org>
*/
class
PriceUpdater
:
public
Q
Objec
t
class
Abstract
PriceUpdater
:
public
Q
Widge
t
{
Q_OBJECT
private:
public:
enum
PriceSource
{
BLPPriceSource
,
DBPriceSource
};
protected:
const
DeckList
*
deck
;
QNetworkAccessManager
*
nam
;
signals:
void
finishedUpdate
();
private
slots
:
void
downloadFinished
();
protected
slots
:
virtual
void
downloadFinished
()
=
0
;
public:
AbstractPriceUpdater
(
const
DeckList
*
deck
);
virtual
void
updatePrices
()
=
0
;
};
class
BLPPriceUpdater
:
public
AbstractPriceUpdater
{
Q_OBJECT
protected:
virtual
void
downloadFinished
();
public:
BLPPriceUpdater
(
const
DeckList
*
deck
);
virtual
void
updatePrices
();
};
class
DBPriceUpdater
:
public
AbstractPriceUpdater
{
Q_OBJECT
protected:
MuidStringMap
muidMap
;
QList
<
QString
>
urls
;
protected:
virtual
void
downloadFinished
();
void
requestNext
();
public:
PriceUpdater
(
const
DeckList
*
deck
);
void
updatePrices
();
DB
PriceUpdater
(
const
DeckList
*
deck
);
virtual
void
updatePrices
();
};
#endif
cockatrice/src/settingscache.cpp
View file @
abdaa610
...
...
@@ -45,6 +45,7 @@ SettingsCache::SettingsCache()
soundPath
=
settings
->
value
(
"sound/path"
).
toString
();
priceTagFeature
=
settings
->
value
(
"deckeditor/pricetags"
,
false
).
toBool
();
priceTagSource
=
settings
->
value
(
"deckeditor/pricetagsource"
,
0
).
toInt
();
ignoreUnregisteredUsers
=
settings
->
value
(
"chat/ignore_unregistered"
,
false
).
toBool
();
}
...
...
@@ -247,6 +248,12 @@ void SettingsCache::setPriceTagFeature(int _priceTagFeature)
emit
priceTagFeatureChanged
(
priceTagFeature
);
}
void
SettingsCache
::
setPriceTagSource
(
int
_priceTagSource
)
{
priceTagSource
=
_priceTagSource
;
settings
->
setValue
(
"deckeditor/pricetagsource"
,
priceTagSource
);
}
void
SettingsCache
::
setIgnoreUnregisteredUsers
(
bool
_ignoreUnregisteredUsers
)
{
ignoreUnregisteredUsers
=
_ignoreUnregisteredUsers
;
...
...
cockatrice/src/settingscache.h
View file @
abdaa610
...
...
@@ -53,6 +53,7 @@ private:
bool
soundEnabled
;
QString
soundPath
;
bool
priceTagFeature
;
int
priceTagSource
;
bool
ignoreUnregisteredUsers
;
QString
picUrl
;
QString
picUrlHq
;
...
...
@@ -87,6 +88,7 @@ public:
bool
getSoundEnabled
()
const
{
return
soundEnabled
;
}
QString
getSoundPath
()
const
{
return
soundPath
;
}
bool
getPriceTagFeature
()
const
{
return
priceTagFeature
;
}
int
getPriceTagSource
()
const
{
return
priceTagSource
;
}
bool
getIgnoreUnregisteredUsers
()
const
{
return
ignoreUnregisteredUsers
;
}
QString
getPicUrl
()
const
{
return
picUrl
;
}
QString
getPicUrlHq
()
const
{
return
picUrlHq
;
}
...
...
@@ -121,6 +123,7 @@ public slots:
void
setSoundEnabled
(
int
_soundEnabled
);
void
setSoundPath
(
const
QString
&
_soundPath
);
void
setPriceTagFeature
(
int
_priceTagFeature
);
void
setPriceTagSource
(
int
_priceTagSource
);
void
setIgnoreUnregisteredUsers
(
bool
_ignoreUnregisteredUsers
);
void
setPicUrl
(
const
QString
&
_picUrl
);
void
setPicUrlHq
(
const
QString
&
_picUrlHq
);
...
...
cockatrice/src/tab_deck_editor.cpp
View file @
abdaa610
...
...
@@ -651,7 +651,19 @@ void TabDeckEditor::setPriceTagFeatureEnabled(int enabled)
void
TabDeckEditor
::
actUpdatePrices
()
{
aUpdatePrices
->
setDisabled
(
true
);
PriceUpdater
*
up
=
new
PriceUpdater
(
deckModel
->
getDeckList
());
AbstractPriceUpdater
*
up
;
switch
(
settingsCache
->
getPriceTagSource
())
{
case
AbstractPriceUpdater
::
DBPriceSource
:
up
=
new
DBPriceUpdater
(
deckModel
->
getDeckList
());
break
;
case
AbstractPriceUpdater
::
BLPPriceSource
:
default:
up
=
new
BLPPriceUpdater
(
deckModel
->
getDeckList
());
break
;
}
connect
(
up
,
SIGNAL
(
finishedUpdate
()),
this
,
SLOT
(
finishedUpdatingPrices
()));
up
->
updatePrices
();
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment