diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index 3d89cc11d..ebf5f44ed 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -38,6 +38,11 @@ resources/remove_row.svg resources/arrow_left_green.svg resources/arrow_right_green.svg + + resources/arrow_top_green.svg + resources/arrow_up_green.svg + resources/arrow_down_green.svg + resources/arrow_bottom_green.svg resources/icon_ready_start.svg resources/icon_not_ready_start.svg diff --git a/cockatrice/resources/arrow_bottom_green.svg b/cockatrice/resources/arrow_bottom_green.svg new file mode 100644 index 000000000..3a45053ad --- /dev/null +++ b/cockatrice/resources/arrow_bottom_green.svg @@ -0,0 +1,793 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/cockatrice/resources/arrow_down_green.svg b/cockatrice/resources/arrow_down_green.svg new file mode 100644 index 000000000..574c12060 --- /dev/null +++ b/cockatrice/resources/arrow_down_green.svg @@ -0,0 +1,793 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/cockatrice/resources/arrow_top_green.svg b/cockatrice/resources/arrow_top_green.svg new file mode 100644 index 000000000..c515c6a1d --- /dev/null +++ b/cockatrice/resources/arrow_top_green.svg @@ -0,0 +1,793 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/cockatrice/resources/arrow_up_green.svg b/cockatrice/resources/arrow_up_green.svg new file mode 100644 index 000000000..1d0f61112 --- /dev/null +++ b/cockatrice/resources/arrow_up_green.svg @@ -0,0 +1,792 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/cockatrice/src/carddatabase.cpp b/cockatrice/src/carddatabase.cpp index 5fbf81c5c..4a3705b99 100644 --- a/cockatrice/src/carddatabase.cpp +++ b/cockatrice/src/carddatabase.cpp @@ -14,6 +14,7 @@ #include #include #include +#include const int CardDatabase::versionNeeded = 3; const char* CardDatabase::TOKENS_SETNAME = "TK"; @@ -1028,6 +1029,8 @@ LoadStatus CardDatabase::loadCardDatabase(const QString &path, bool tokens) allSets.append(setsIterator.next().value()); allSets.sortByKey(); + if(!tokens) + checkUnknownSets(); emit cardListChanged(); } @@ -1098,3 +1101,51 @@ void CardDatabase::picsPathChanged() pictureLoader->setPicsPath(settingsCache->getPicsPath()); clearPixmapCache(); } + +void CardDatabase::checkUnknownSets() +{ + SetList sets = getSetList(); + + // no set is enabled. Probably this is the first time running trice + if(!sets.getEnabledSetsNum()) + { + sets.guessSortKeys(); + sets.sortByKey(); + sets.enableAll(); + + detectedFirstRun = true; + return; + } + + int numUnknownSets = sets.getUnknownSetsNum(); + // no unkown sets. + if(!numUnknownSets) + return; + + QMessageBox msgbox(QMessageBox::Question, tr("New sets found"), tr("%1 new set(s) have been found in the card database. Do you want to enable them?").arg(numUnknownSets), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + + switch(msgbox.exec()) + { + case QMessageBox::No: + sets.markAllAsKnown(); + break; + case QMessageBox::Yes: + sets.enableAllUnknown(); + break; + default: + break; + } + + return; +} + +bool CardDatabase::hasDetectedFirstRun() +{ + if(detectedFirstRun) + { + detectedFirstRun=false; + return true; + } + + return false; +} \ No newline at end of file diff --git a/cockatrice/src/carddatabase.h b/cockatrice/src/carddatabase.h index 080a136e8..24deb947b 100644 --- a/cockatrice/src/carddatabase.h +++ b/cockatrice/src/carddatabase.h @@ -232,12 +232,14 @@ protected: QThread *pictureLoaderThread; PictureLoader *pictureLoader; LoadStatus loadStatus; + bool detectedFirstRun; private: static const int versionNeeded; void loadCardsFromXml(QXmlStreamReader &xml, bool tokens); void loadSetsFromXml(QXmlStreamReader &xml); CardInfo *getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound); + void checkUnknownSets(); public: static const char* TOKENS_SETNAME; @@ -265,6 +267,7 @@ public: bool getLoadSuccess() const { return loadStatus == Ok; } void cacheCardPixmaps(const QStringList &cardNames); void loadImage(CardInfo *card); + bool hasDetectedFirstRun(); public slots: void clearPixmapCache(); LoadStatus loadCardDatabase(const QString &path, bool tokens = false); diff --git a/cockatrice/src/tab_deck_editor.cpp b/cockatrice/src/tab_deck_editor.cpp index bb3d9e272..91a15a3c2 100644 --- a/cockatrice/src/tab_deck_editor.cpp +++ b/cockatrice/src/tab_deck_editor.cpp @@ -293,8 +293,7 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent) resize(950, 700); - connect(this, SIGNAL(setListChanged()), db, SIGNAL(cardListChanged())); - QTimer::singleShot(0, this, SLOT(checkUnknownSets())); + QTimer::singleShot(0, this, SLOT(checkFirstRunDetected())); } TabDeckEditor::~TabDeckEditor() @@ -786,39 +785,11 @@ void TabDeckEditor::filterRemove(QAction *action) { filterModel->removeRow(idx.row(), idx.parent()); } -void TabDeckEditor::checkUnknownSets() +void TabDeckEditor::checkFirstRunDetected() { - SetList sets = db->getSetList(); - - // no set is enabled. Probably this is the first time running trice - if(!sets.getEnabledSetsNum()) + if(db->hasDetectedFirstRun()) { - sets.guessSortKeys(); - sets.sortByKey(); - sets.enableAll(); - db->emitCardListChanged(); - + QMessageBox::information(this, tr("Welcome"), tr("Hi! Its seems like it's the first time you run this version of Cockatrice.\nAll the sets in the card database have been enabled.\nRead more about changing the set order or disabling specific sets in the the \"Edit Sets\" window.")); actEditSets(); - return; - } - - int numUnknownSets = sets.getUnknownSetsNum(); - // no unkown sets. - if(!numUnknownSets) - return; - - int ret = QMessageBox::question(this, tr("New sets found"), tr("%1 new set(s) have been found in the card database. Do you want to enable them?").arg(numUnknownSets), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Yes); - - switch(ret) - { - case QMessageBox::No: - sets.markAllAsKnown(); - break; - case QMessageBox::Yes: - sets.enableAllUnknown(); - db->emitCardListChanged(); - break; - default: - break; } } \ No newline at end of file diff --git a/cockatrice/src/tab_deck_editor.h b/cockatrice/src/tab_deck_editor.h index af83703de..f482aaada 100644 --- a/cockatrice/src/tab_deck_editor.h +++ b/cockatrice/src/tab_deck_editor.h @@ -113,10 +113,9 @@ public: bool confirmClose(); public slots: void closeRequest(); - void checkUnknownSets(); + void checkFirstRunDetected(); signals: void deckEditorClosing(TabDeckEditor *tab); - void setListChanged(); }; #endif diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index ab12abd0f..f69a18dd7 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -325,6 +325,7 @@ void MainWindow::retranslateUi() #endif aAbout->setText(tr("&About Cockatrice")); helpMenu->setTitle(tr("&Help")); + aCheckCardUpdates->setText(tr("Check card updates...")); tabSupervisor->retranslateUi(); } @@ -353,6 +354,9 @@ void MainWindow::createActions() aAbout = new QAction(this); connect(aAbout, SIGNAL(triggered()), this, SLOT(actAbout())); + aCheckCardUpdates = new QAction(this); + connect(aCheckCardUpdates, SIGNAL(triggered()), this, SLOT(actCheckCardUpdates())); + #if defined(__APPLE__) /* For OSX */ aSettings->setMenuRole(QAction::PreferencesRole); aExit->setMenuRole(QAction::QuitRole); @@ -383,6 +387,7 @@ void MainWindow::createMenus() cockatriceMenu->addAction(aFullScreen); cockatriceMenu->addSeparator(); cockatriceMenu->addAction(aSettings); + cockatriceMenu->addAction(aCheckCardUpdates); cockatriceMenu->addSeparator(); cockatriceMenu->addAction(aExit); @@ -391,7 +396,7 @@ void MainWindow::createMenus() } MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent), localServer(0), bHasActivated(false) + : QMainWindow(parent), localServer(0), bHasActivated(false), cardUpdateProcess(0) { connect(settingsCache, SIGNAL(pixmapCacheSizeChanged(int)), this, SLOT(pixmapCacheSizeChanged(int))); pixmapCacheSizeChanged(settingsCache->getPixmapCacheSize()); @@ -522,3 +527,93 @@ void MainWindow::pixmapCacheSizeChanged(int newSizeInMBs) void MainWindow::maximize() { showNormal(); } + +/* CARD UPDATER */ + +void MainWindow::actCheckCardUpdates() +{ + if(cardUpdateProcess) + { + QMessageBox::information(this, tr("Information"), tr("A card update is already ongoing.")); + return; + } + + cardUpdateProcess = new QProcess(this); + connect(cardUpdateProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(cardUpdateError(QProcess::ProcessError))); + connect(cardUpdateProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(cardUpdateFinished(int, QProcess::ExitStatus))); + + // full "run the update" command; leave empty if not present + QString updaterCmd; + QString binaryName; + QDir dir = QDir(QApplication::applicationDirPath()); + +#if defined(Q_OS_MAC) + binaryName = getCardUpdaterBinaryName(); + + // exit from the application bundle + dir.cdUp(); + dir.cdUp(); + dir.cdUp(); + dir.cd(binaryName + ".app"); + dir.cd("Contents"); + dir.cd("MacOS"); +#elif defined(Q_OS_WIN) + binaryName = getCardUpdaterBinaryName() + ".exe"; +#else + binaryName = getCardUpdaterBinaryName(); +#endif + + if(dir.exists(binaryName)) + updaterCmd = dir.absoluteFilePath(binaryName); + + if(updaterCmd.isEmpty()) + { + QMessageBox::warning(this, tr("Error"), tr("Unable to run the card updater: ") + dir.absoluteFilePath(binaryName)); + return; + } + + cardUpdateProcess->start(updaterCmd); +} + +void MainWindow::cardUpdateError(QProcess::ProcessError err) +{ + QString error; + switch(err) + { + case QProcess::FailedToStart: + error = tr("failed to start."); + break; + case QProcess::Crashed: + error = tr("crashed."); + break; + case QProcess::Timedout: + error = tr("timed out."); + break; + case QProcess::WriteError: + error = tr("write error."); + break; + case QProcess::ReadError: + error = tr("read error."); + break; + case QProcess::UnknownError: + default: + error = tr("unknown error."); + break; + } + + cardUpdateProcess->deleteLater(); + cardUpdateProcess = 0; + + QMessageBox::warning(this, tr("Error"), tr("The card updater exited with an error: %1").arg(error)); +} + +void MainWindow::cardUpdateFinished(int, QProcess::ExitStatus) +{ + cardUpdateProcess->deleteLater(); + cardUpdateProcess = 0; + + QMessageBox::information(this, tr("Information"), tr("Card update completed successfully. Will now reload card database.")); + + // this will force a database reload + settingsCache->setCardDatabasePath(settingsCache->getCardDatabasePath()); +} diff --git a/cockatrice/src/window_main.h b/cockatrice/src/window_main.h index 8993fc72e..1087d2e72 100644 --- a/cockatrice/src/window_main.h +++ b/cockatrice/src/window_main.h @@ -22,6 +22,7 @@ #include #include +#include #include "abstractclient.h" #include "pb/response.pb.h" @@ -62,6 +63,10 @@ private slots: void iconActivated(QSystemTrayIcon::ActivationReason reason); void maximize(); + + void actCheckCardUpdates(); + void cardUpdateError(QProcess::ProcessError err); + void cardUpdateFinished(int exitCode, QProcess::ExitStatus exitStatus); private: static const QString appName; void setClientStatusTitle(); @@ -71,11 +76,13 @@ private: void createTrayIcon(); void createTrayActions(); + // TODO: add a preference item to choose updater name for other games + inline QString getCardUpdaterBinaryName() { return "oracle"; }; QList tabMenus; QMenu *cockatriceMenu, *helpMenu; QAction *aConnect, *aDisconnect, *aSinglePlayer, *aWatchReplay, *aDeckEditor, *aFullScreen, *aSettings, *aExit, - *aAbout; + *aAbout, *aCheckCardUpdates; TabSupervisor *tabSupervisor; QMenu *trayIconMenu; @@ -89,6 +96,7 @@ private: bool bHasActivated; QMessageBox *serverShutdownMessageBox; + QProcess * cardUpdateProcess; public: MainWindow(QWidget *parent = 0); ~MainWindow(); diff --git a/cockatrice/src/window_sets.cpp b/cockatrice/src/window_sets.cpp index b5178421a..db486f06d 100644 --- a/cockatrice/src/window_sets.cpp +++ b/cockatrice/src/window_sets.cpp @@ -10,10 +10,48 @@ #include #include #include +#include +#include +#include WndSets::WndSets(QWidget *parent) : QMainWindow(parent) { + // left toolbar + QToolBar *setsEditToolBar = new QToolBar; + setsEditToolBar->setOrientation(Qt::Vertical); + setsEditToolBar->setIconSize(QSize(24, 24)); + setsEditToolBar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + + aTop = new QAction(QString(), this); + aTop->setIcon(QIcon(":/resources/arrow_top_green.svg")); + aTop->setToolTip(tr("Move selected set to top")); + aTop->setEnabled(false); + connect(aTop, SIGNAL(triggered()), this, SLOT(actTop())); + setsEditToolBar->addAction(aTop); + + aUp = new QAction(QString(), this); + aUp->setIcon(QIcon(":/resources/arrow_up_green.svg")); + aUp->setToolTip(tr("Move selected set up")); + aUp->setEnabled(false); + connect(aUp, SIGNAL(triggered()), this, SLOT(actUp())); + setsEditToolBar->addAction(aUp); + + aDown = new QAction(QString(), this); + aDown->setIcon(QIcon(":/resources/arrow_down_green.svg")); + aDown->setToolTip(tr("Move selected set down")); + aDown->setEnabled(false); + connect(aDown, SIGNAL(triggered()), this, SLOT(actDown())); + setsEditToolBar->addAction(aDown); + + aBottom = new QAction(QString(), this); + aBottom->setIcon(QIcon(":/resources/arrow_bottom_green.svg")); + aBottom->setToolTip(tr("Move selected set to bottom")); + aBottom->setEnabled(false); + connect(aBottom, SIGNAL(triggered()), this, SLOT(actBottom())); + setsEditToolBar->addAction(aBottom); + + // view model = new SetsModel(db, this); view = new QTreeView; view->setModel(model); @@ -43,59 +81,32 @@ WndSets::WndSets(QWidget *parent) view->setColumnHidden(SetsModel::IsKnownCol, true); view->setRootIsDecorated(false); - enableButton = new QPushButton(tr("Enable set")); - connect(enableButton, SIGNAL(clicked()), this, SLOT(actEnable())); - disableButton = new QPushButton(tr("Disable set")); - connect(disableButton, SIGNAL(clicked()), this, SLOT(actDisable())); + connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), + this, SLOT(actToggleButtons(const QItemSelection &, const QItemSelection &))); + + // bottom buttons enableAllButton = new QPushButton(tr("Enable all sets")); connect(enableAllButton, SIGNAL(clicked()), this, SLOT(actEnableAll())); disableAllButton = new QPushButton(tr("Disable all sets")); connect(disableAllButton, SIGNAL(clicked()), this, SLOT(actDisableAll())); - upButton = new QPushButton(tr("Move selected set up")); - connect(upButton, SIGNAL(clicked()), this, SLOT(actUp())); - downButton = new QPushButton(tr("Move selected set down")); - connect(downButton, SIGNAL(clicked()), this, SLOT(actDown())); - topButton = new QPushButton(tr("Move selected set to top")); - connect(topButton, SIGNAL(clicked()), this, SLOT(actTop())); - bottomButton = new QPushButton(tr("Move selected set to bottom")); - connect(bottomButton, SIGNAL(clicked()), this, SLOT(actBottom())); - enableButton->setDisabled(true); - disableButton->setDisabled(true); - upButton->setDisabled(true); - downButton->setDisabled(true); - topButton->setDisabled(true); - bottomButton->setDisabled(true); - - connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), - this, SLOT(actToggleButtons(const QItemSelection &, const QItemSelection &))); - - QGroupBox *toggleFrame = new QGroupBox(tr("Enable sets")); - QVBoxLayout *toggleVBox = new QVBoxLayout; - toggleVBox->addWidget(enableButton); - toggleVBox->addWidget(disableButton); - toggleVBox->addWidget(enableAllButton); - toggleVBox->addWidget(disableAllButton); - toggleFrame->setLayout(toggleVBox); - - QGroupBox *sortFrame = new QGroupBox(tr("Sort sets")); - QVBoxLayout *sortVBox = new QVBoxLayout; - sortVBox->addWidget(upButton); - sortVBox->addWidget(downButton); - sortVBox->addWidget(topButton); - sortVBox->addWidget(bottomButton); - sortFrame->setLayout(sortVBox); + QLabel *labNotes = new QLabel; + labNotes->setText("Enable the sets that you want to have available in the deck editor.\nMove sets around to change their order, or click on a column header to sort sets on that field.\nSets order decides the source that will be used when loading images for a specific card.\nDisabled sets will still be used for loading images."); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(buttonBox, SIGNAL(accepted()), this, SLOT(actSave())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(actRestore())); QGridLayout *mainLayout = new QGridLayout; - mainLayout->addWidget(view, 0, 0, 1, 2); - mainLayout->addWidget(toggleFrame, 1, 0, 1, 1); - mainLayout->addWidget(sortFrame, 1, 1, 1, 1); - mainLayout->addWidget(buttonBox, 2, 0, 1, 2); + mainLayout->addWidget(setsEditToolBar, 0, 0, 1, 1); + mainLayout->addWidget(view, 0, 1, 1, 2); + mainLayout->addWidget(enableAllButton, 1, 1, 1, 1); + mainLayout->addWidget(disableAllButton, 1, 2, 1, 1); + mainLayout->addWidget(labNotes, 2, 1, 1, 2); + mainLayout->addWidget(buttonBox, 3, 1, 1, 2); + mainLayout->setColumnStretch(1, 1); + mainLayout->setColumnStretch(2, 1); QWidget *centralWidget = new QWidget; centralWidget->setLayout(mainLayout); @@ -125,12 +136,10 @@ void WndSets::actRestore() void WndSets::actToggleButtons(const QItemSelection & selected, const QItemSelection &) { bool disabled = selected.empty(); - upButton->setDisabled(disabled); - downButton->setDisabled(disabled); - topButton->setDisabled(disabled); - bottomButton->setDisabled(disabled); - enableButton->setDisabled(disabled); - disableButton->setDisabled(disabled); + aTop->setDisabled(disabled); + aUp->setDisabled(disabled); + aDown->setDisabled(disabled); + aBottom->setDisabled(disabled); } void WndSets::selectRow(int row) diff --git a/cockatrice/src/window_sets.h b/cockatrice/src/window_sets.h index cd341cdbb..0d57a62d5 100644 --- a/cockatrice/src/window_sets.h +++ b/cockatrice/src/window_sets.h @@ -15,8 +15,8 @@ class WndSets : public QMainWindow { private: SetsModel *model; QTreeView *view; - QPushButton *enableButton, *disableButton, *enableAllButton, *disableAllButton, - *upButton, *downButton, *bottomButton, *topButton; + QPushButton *enableAllButton, *disableAllButton; + QAction *aUp, *aDown, *aBottom, *aTop; public: WndSets(QWidget *parent = 0); ~WndSets();