diff --git a/.gitignore b/.gitignore index b0ccf34e0..f147c1458 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ compile_commands.json .vscode/ .cache .gdb_history +cockatrice/resources/config/qtlogging.ini diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 2122edbc6..c88aca46b 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -56,6 +56,7 @@ set(cockatrice_SOURCES src/dialogs/dlg_tip_of_the_day.cpp src/dialogs/dlg_update.cpp src/dialogs/dlg_view_log.cpp + src/dialogs/dlg_load_deck.cpp src/game/filters/filter_string.cpp src/game/filters/filter_builder.cpp src/game/filters/filter_tree.cpp @@ -168,6 +169,9 @@ set(cockatrice_SOURCES add_subdirectory(sounds) add_subdirectory(themes) +configure_file( + ${CMAKE_SOURCE_DIR}/cockatrice/resources/config/qtlogging.ini ${CMAKE_BINARY_DIR}/cockatrice/qtlogging.ini COPYONLY +) set(cockatrice_RESOURCES cockatrice.qrc) diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index 2d147bcf6..c93499cf3 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -41,6 +41,8 @@ resources/config/deckeditor.svg resources/config/shorcuts.svg resources/config/sound.svg + resources/config/debug.ini + resources/config/qtlogging.ini resources/counters/w.svg resources/counters/w_highlight.svg diff --git a/cockatrice/resources/config/debug.ini b/cockatrice/resources/config/debug.ini new file mode 100644 index 000000000..a1d203c7a --- /dev/null +++ b/cockatrice/resources/config/debug.ini @@ -0,0 +1,11 @@ +[debug] +showCardId=false + +[localgame] +onStartup=false +playerCount=1 +;deck\Player 1=path/to/deck +;deck\Player 2=path/to/deck + +; Fun Fact: You can assign a deck to your username and it will auto load and ready when you join a server game +;deck\Your Username Here=path/to/deck diff --git a/cockatrice/resources/config/qtlogging.ini b/cockatrice/resources/config/qtlogging.ini new file mode 100644 index 000000000..325ac6536 --- /dev/null +++ b/cockatrice/resources/config/qtlogging.ini @@ -0,0 +1,2 @@ +[Rules] +picture_loader.debug = true \ No newline at end of file diff --git a/cockatrice/src/client/tabs/tab_deck_editor.cpp b/cockatrice/src/client/tabs/tab_deck_editor.cpp index 79982129b..8de574798 100644 --- a/cockatrice/src/client/tabs/tab_deck_editor.cpp +++ b/cockatrice/src/client/tabs/tab_deck_editor.cpp @@ -5,6 +5,7 @@ #include "../../client/ui/widgets/cards/card_info_frame_widget.h" #include "../../deck/deck_list_model.h" #include "../../deck/deck_stats_interface.h" +#include "../../dialogs/dlg_load_deck.h" #include "../../dialogs/dlg_load_deck_from_clipboard.h" #include "../../game/cards/card_database_manager.h" #include "../../game/cards/card_database_model.h" @@ -1007,9 +1008,7 @@ void TabDeckEditor::actLoadDeck() return; } - QFileDialog dialog(this, tr("Load deck")); - dialog.setDirectory(SettingsCache::instance().getDeckPath()); - dialog.setNameFilters(DeckLoader::fileNameFilters); + DlgLoadDeck dialog(this); if (!dialog.exec()) return; diff --git a/cockatrice/src/client/tabs/tab_game.cpp b/cockatrice/src/client/tabs/tab_game.cpp index 043112173..9897b3865 100644 --- a/cockatrice/src/client/tabs/tab_game.cpp +++ b/cockatrice/src/client/tabs/tab_game.cpp @@ -4,6 +4,7 @@ #include "../../deck/deck_loader.h" #include "../../deck/deck_view.h" #include "../../dialogs/dlg_create_game.h" +#include "../../dialogs/dlg_load_deck.h" #include "../../dialogs/dlg_load_remote_deck.h" #include "../../dialogs/dlg_manage_sets.h" #include "../../game/board/arrow_item.h" @@ -338,9 +339,7 @@ void DeckViewContainer::unloadDeck() void DeckViewContainer::loadLocalDeck() { - QFileDialog dialog(this, tr("Load deck")); - dialog.setDirectory(SettingsCache::instance().getDeckPath()); - dialog.setNameFilters(DeckLoader::fileNameFilters); + DlgLoadDeck dialog(this); if (!dialog.exec()) return; @@ -815,6 +814,12 @@ void TabGame::actSay() if (completer->popup()->isVisible()) return; + if (sayEdit->text().startsWith("/card ")) { + cardInfoFrameWidget->setCard(sayEdit->text().mid(6)); + sayEdit->clear(); + return; + } + if (!sayEdit->text().isEmpty()) { Command_GameSay cmd; cmd.set_message(sayEdit->text().toStdString()); diff --git a/cockatrice/src/client/ui/picture_loader.cpp b/cockatrice/src/client/ui/picture_loader.cpp index 8eb4a7fb9..a2eed3f28 100644 --- a/cockatrice/src/client/ui/picture_loader.cpp +++ b/cockatrice/src/client/ui/picture_loader.cpp @@ -23,8 +23,11 @@ #include #include #include +#include #include +Q_LOGGING_CATEGORY(PictureLoaderLog, "picture_loader") + // never cache more than 300 cards at once for a single deck #define CACHED_CARD_PER_DECK_MAX 300 @@ -189,8 +192,8 @@ void PictureLoaderWorker::processLoadQueue() QString cardName = cardBeingLoaded.getCard()->getName(); QString correctedCardName = cardBeingLoaded.getCard()->getCorrectedName(); - qDebug().nospace() << "PictureLoader: [card: " << cardName << " set: " << setName - << "]: Trying to load picture"; + qCDebug(PictureLoaderLog).nospace() + << "PictureLoader: [card: " << cardName << " set: " << setName << "]: Trying to load picture"; if (CardDatabaseManager::getInstance()->isProviderIdForPreferredPrinting( cardName, cardBeingLoaded.getCard()->getPixmapCacheKey())) { @@ -199,8 +202,8 @@ void PictureLoaderWorker::processLoadQueue() } } - qDebug().nospace() << "PictureLoader: [card: " << cardName << " set: " << setName - << "]: No custom picture, trying to download"; + qCDebug(PictureLoaderLog).nospace() << "PictureLoader: [card: " << cardName << " set: " << setName + << "]: No custom picture, trying to download"; cardsToDownload.append(cardBeingLoaded); cardBeingLoaded.clear(); if (!downloadRunning) { @@ -242,22 +245,22 @@ bool PictureLoaderWorker::cardImageExistsOnDisk(QString &setName, QString &corre for (const auto &_picsPath : picsPaths) { imgReader.setFileName(_picsPath); if (imgReader.read(&image)) { - qDebug().nospace() << "PictureLoader: [card: " << correctedCardname << " set: " << setName - << "]: Picture found on disk."; + qCDebug(PictureLoaderLog).nospace() + << "PictureLoader: [card: " << correctedCardname << " set: " << setName << "]: Picture found on disk."; imageLoaded(cardBeingLoaded.getCard(), image); return true; } imgReader.setFileName(_picsPath + ".full"); if (imgReader.read(&image)) { - qDebug().nospace() << "PictureLoader: [card: " << correctedCardname << " set: " << setName - << "]: Picture.full found on disk."; + qCDebug(PictureLoaderLog).nospace() << "PictureLoader: [card: " << correctedCardname << " set: " << setName + << "]: Picture.full found on disk."; imageLoaded(cardBeingLoaded.getCard(), image); return true; } imgReader.setFileName(_picsPath + ".xlhq"); if (imgReader.read(&image)) { - qDebug().nospace() << "PictureLoader: [card: " << correctedCardname << " set: " << setName - << "]: Picture.xlhq found on disk."; + qCDebug(PictureLoaderLog).nospace() << "PictureLoader: [card: " << correctedCardname << " set: " << setName + << "]: Picture.xlhq found on disk."; imageLoaded(cardBeingLoaded.getCard(), image); return true; } @@ -303,18 +306,19 @@ static int parse(const QString &urlTemplate, } QString propertyValue = getProperty(cardPropertyName); if (propertyValue.isEmpty()) { - qDebug().nospace() << "PictureLoader: [card: " << cardName << " set: " << setName << "]: Requested " - << propType << "property (" << cardPropertyName << ") for Url template (" << urlTemplate - << ") is not available"; + qCDebug(PictureLoaderLog).nospace() + << "PictureLoader: [card: " << cardName << " set: " << setName << "]: Requested " << propType + << "property (" << cardPropertyName << ") for Url template (" << urlTemplate << ") is not available"; return 1; } else { int propLength = propertyValue.length(); if (subStrLen > 0) { if (subStrPos + subStrLen > propLength) { - qDebug().nospace() << "PictureLoader: [card: " << cardName << " set: " << setName << "]: Requested " - << propType << " property (" << cardPropertyName << ") for Url template (" - << urlTemplate << ") is smaller than substr specification (" << subStrPos - << " + " << subStrLen << " > " << propLength << ")"; + qCDebug(PictureLoaderLog).nospace() + << "PictureLoader: [card: " << cardName << " set: " << setName << "]: Requested " << propType + << " property (" << cardPropertyName << ") for Url template (" << urlTemplate + << ") is smaller than substr specification (" << subStrPos << " + " << subStrLen << " > " + << propLength << ")"; return 1; } else { propertyValue = propertyValue.mid(subStrPos, subStrLen); @@ -325,9 +329,10 @@ static int parse(const QString &urlTemplate, if (!fillWith.isEmpty()) { int fillLength = fillWith.length(); if (fillLength < propLength) { - qDebug().nospace() << "PictureLoader: [card: " << cardName << " set: " << setName << "]: Requested " - << propType << " property (" << cardPropertyName << ") for Url template (" - << urlTemplate << ") is longer than fill specification (" << fillWith << ")"; + qCDebug(PictureLoaderLog).nospace() + << "PictureLoader: [card: " << cardName << " set: " << setName << "]: Requested " << propType + << " property (" << cardPropertyName << ") for Url template (" << urlTemplate + << ") is longer than fill specification (" << fillWith << ")"; return 1; } else { @@ -394,9 +399,9 @@ QString PictureToLoad::transformUrl(const QString &urlTemplate) const * populated in this card, so it should return an empty string, * indicating an invalid Url. */ - qDebug().nospace() << "PictureLoader: [card: " << cardName << " set: " << setName - << "]: Requested information (" << prop << ") for Url template (" << urlTemplate - << ") is not available"; + qCDebug(PictureLoaderLog).nospace() + << "PictureLoader: [card: " << cardName << " set: " << setName << "]: Requested information (" + << prop << ") for Url template (" << urlTemplate << ") is not available"; return QString(); } } @@ -424,9 +429,10 @@ void PictureLoaderWorker::startNextPicDownload() picDownloadFailed(); } else { QUrl url(picUrl); - qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName() - << " set: " << cardBeingDownloaded.getSetName() << "]: Trying to fetch picture from url " - << url.toDisplayString(); + qCDebug(PictureLoaderLog).nospace() + << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName() + << " set: " << cardBeingDownloaded.getSetName() << "]: Trying to fetch picture from url " + << url.toDisplayString(); makeRequest(url); } } @@ -442,10 +448,11 @@ void PictureLoaderWorker::picDownloadFailed() loadQueue.prepend(cardBeingDownloaded); mutex.unlock(); } else { - qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName() - << " set: " << cardBeingDownloaded.getSetName() << "]: Picture NOT found, " - << (picDownload ? "download failed" : "downloads disabled") - << ", no more url combinations to try: BAILING OUT"; + qCDebug(PictureLoaderLog).nospace() + << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName() + << " set: " << cardBeingDownloaded.getSetName() << "]: Picture NOT found, " + << (picDownload ? "download failed" : "downloads disabled") + << ", no more url combinations to try: BAILING OUT"; imageLoaded(cardBeingDownloaded.getCard(), QImage()); cardBeingDownloaded.clear(); } @@ -463,9 +470,10 @@ QNetworkReply *PictureLoaderWorker::makeRequest(const QUrl &url) // Check if the redirect is cached QUrl cachedRedirect = getCachedRedirect(url); if (!cachedRedirect.isEmpty()) { - qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName() - << " set: " << cardBeingDownloaded.getSetName() << "]: Using cached redirect for " - << url.toDisplayString() << " to " << cachedRedirect.toDisplayString(); + qCDebug(PictureLoaderLog).nospace() + << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName() + << " set: " << cardBeingDownloaded.getSetName() << "]: Using cached redirect for " << url.toDisplayString() + << " to " << cachedRedirect.toDisplayString(); return makeRequest(cachedRedirect); // Use the cached redirect } @@ -487,9 +495,10 @@ QNetworkReply *PictureLoaderWorker::makeRequest(const QUrl &url) } cacheRedirect(url, redirectUrl); - qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName() - << " set: " << cardBeingDownloaded.getSetName() << "]: Caching redirect from " - << url.toDisplayString() << " to " << redirectUrl.toDisplayString(); + qCDebug(PictureLoaderLog).nospace() + << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName() + << " set: " << cardBeingDownloaded.getSetName() << "]: Caching redirect from " << url.toDisplayString() + << " to " << redirectUrl.toDisplayString(); } reply->deleteLater(); @@ -566,19 +575,19 @@ void PictureLoaderWorker::picDownloadFinished(QNetworkReply *reply) if (reply->error()) { if (isFromCache) { - qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() - << " set: " << cardBeingDownloaded.getSetName() - << "]: Removing corrupted cache file for url " << reply->url().toDisplayString() - << " and retrying (" << reply->errorString() << ")"; + qCDebug(PictureLoaderLog).nospace() + << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() + << " set: " << cardBeingDownloaded.getSetName() << "]: Removing corrupted cache file for url " + << reply->url().toDisplayString() << " and retrying (" << reply->errorString() << ")"; networkManager->cache()->remove(reply->url()); makeRequest(reply->url()); } else { - qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() - << " set: " << cardBeingDownloaded.getSetName() - << "]: " << (picDownload ? "Download" : "Cache search") << " failed for url " - << reply->url().toDisplayString() << " (" << reply->errorString() << ")"; + qCDebug(PictureLoaderLog).nospace() + << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() + << " set: " << cardBeingDownloaded.getSetName() << "]: " << (picDownload ? "Download" : "Cache search") + << " failed for url " << reply->url().toDisplayString() << " (" << reply->errorString() << ")"; picDownloadFailed(); startNextPicDownload(); @@ -593,9 +602,10 @@ void PictureLoaderWorker::picDownloadFinished(QNetworkReply *reply) if (statusCode == 301 || statusCode == 302 || statusCode == 303 || statusCode == 305 || statusCode == 307 || statusCode == 308) { QUrl redirectUrl = reply->header(QNetworkRequest::LocationHeader).toUrl(); - qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() - << " set: " << cardBeingDownloaded.getSetName() << "]: following " - << (isFromCache ? "cached redirect" : "redirect") << " to " << redirectUrl.toDisplayString(); + qCDebug(PictureLoaderLog).nospace() + << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() + << " set: " << cardBeingDownloaded.getSetName() << "]: following " + << (isFromCache ? "cached redirect" : "redirect") << " to " << redirectUrl.toDisplayString(); makeRequest(redirectUrl); reply->deleteLater(); return; @@ -605,9 +615,9 @@ void PictureLoaderWorker::picDownloadFinished(QNetworkReply *reply) const QByteArray &picData = reply->peek(reply->size()); if (imageIsBlackListed(picData)) { - qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() - << " set: " << cardBeingDownloaded.getSetName() - << "]: Picture found, but blacklisted, will consider it as not found"; + qCDebug(PictureLoaderLog).nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() + << " set: " << cardBeingDownloaded.getSetName() + << "]: Picture found, but blacklisted, will consider it as not found"; picDownloadFailed(); reply->deleteLater(); @@ -640,19 +650,19 @@ void PictureLoaderWorker::picDownloadFinished(QNetworkReply *reply) imageLoaded(cardBeingDownloaded.getCard(), testImage); logSuccessMessage = true; } else { - qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() - << " set: " << cardBeingDownloaded.getSetName() << "]: Possible " - << (isFromCache ? "cached" : "downloaded") << " picture at " - << reply->url().toDisplayString() << " could not be loaded: " << reply->errorString(); + qCDebug(PictureLoaderLog).nospace() + << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() + << " set: " << cardBeingDownloaded.getSetName() << "]: Possible " << (isFromCache ? "cached" : "downloaded") + << " picture at " << reply->url().toDisplayString() << " could not be loaded: " << reply->errorString(); picDownloadFailed(); } if (logSuccessMessage) { - qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() - << " set: " << cardBeingDownloaded.getSetName() << "]: Image successfully " - << (isFromCache ? "loaded from cached" : "downloaded from") << " url " - << reply->url().toDisplayString(); + qCDebug(PictureLoaderLog).nospace() + << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() + << " set: " << cardBeingDownloaded.getSetName() << "]: Image successfully " + << (isFromCache ? "loaded from cached" : "downloaded from") << " url " << reply->url().toDisplayString(); } reply->deleteLater(); @@ -719,7 +729,7 @@ void PictureLoader::getCardBackPixmap(QPixmap &pixmap, QSize size) { QString backCacheKey = "_trice_card_back_" + QString::number(size.width()) + QString::number(size.height()); if (!QPixmapCache::find(backCacheKey, &pixmap)) { - qDebug() << "PictureLoader: cache fail for" << backCacheKey; + qCDebug(PictureLoaderLog) << "PictureLoader: cache fail for" << backCacheKey; pixmap = QPixmap("theme:cardback").scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); QPixmapCache::insert(backCacheKey, pixmap); } @@ -729,7 +739,7 @@ void PictureLoader::getCardBackLoadingInProgressPixmap(QPixmap &pixmap, QSize si { QString backCacheKey = "_trice_card_back_" + QString::number(size.width()) + QString::number(size.height()); if (!QPixmapCache::find(backCacheKey, &pixmap)) { - qDebug() << "PictureLoader: cache fail for" << backCacheKey; + qCDebug(PictureLoaderLog) << "PictureLoader: cache fail for" << backCacheKey; pixmap = QPixmap("theme:cardback").scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); QPixmapCache::insert(backCacheKey, pixmap); } @@ -739,7 +749,7 @@ void PictureLoader::getCardBackLoadingFailedPixmap(QPixmap &pixmap, QSize size) { QString backCacheKey = "_trice_card_back_" + QString::number(size.width()) + QString::number(size.height()); if (!QPixmapCache::find(backCacheKey, &pixmap)) { - qDebug() << "PictureLoader: cache fail for" << backCacheKey; + qCDebug(PictureLoaderLog) << "PictureLoader: cache fail for" << backCacheKey; pixmap = QPixmap("theme:cardback").scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); QPixmapCache::insert(backCacheKey, pixmap); } diff --git a/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.cpp b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.cpp index 33f76ada7..9943b9403 100644 --- a/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.cpp +++ b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.cpp @@ -57,10 +57,14 @@ PrintingSelector::PrintingSelector(QWidget *parent, layout->addWidget(cardSelectionBar); // Connect deck model data change signal to update display - connect(deckModel, &DeckListModel::dataChanged, this, [this]() { - // Delay the update to avoid race conditions - QTimer::singleShot(100, this, &PrintingSelector::updateDisplay); - }); + connect(deckModel, &DeckListModel::rowsInserted, this, &PrintingSelector::printingsInDeckChanged); + connect(deckModel, &DeckListModel::rowsRemoved, this, &PrintingSelector::printingsInDeckChanged); +} + +void PrintingSelector::printingsInDeckChanged() +{ + // Delay the update to avoid race conditions + QTimer::singleShot(100, this, &PrintingSelector::updateDisplay); } /** @@ -89,6 +93,12 @@ void PrintingSelector::setCard(const CardInfoPtr &newCard, const QString &_curre if (newCard.isNull()) { return; } + + // we don't need to redraw the widget if the card is the same + if (!selectedCard.isNull() && selectedCard->getName() == newCard->getName()) { + return; + } + selectedCard = newCard; currentZone = _currentZone; if (isVisible()) { diff --git a/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.h b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.h index 1e9b01b29..547d4dbef 100644 --- a/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.h +++ b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.h @@ -37,6 +37,9 @@ public slots: void toggleVisibilityCardSizeSlider(bool _state); void toggleVisibilityNavigationButtons(bool _state); +private slots: + void printingsInDeckChanged(); + private: QVBoxLayout *layout; PrintingSelectorViewOptionsToolbarWidget *viewOptionsToolbar; diff --git a/cockatrice/src/client/ui/window_main.cpp b/cockatrice/src/client/ui/window_main.cpp index b0cf4165e..ff25471a1 100644 --- a/cockatrice/src/client/ui/window_main.cpp +++ b/cockatrice/src/client/ui/window_main.cpp @@ -366,6 +366,12 @@ void MainWindow::actViewLog() logviewDialog->activateWindow(); } +void MainWindow::actOpenSettingsFolder() +{ + QString dir = SettingsCache::instance().getSettingsPath(); + QDesktopServices::openUrl(QUrl::fromLocalFile(dir)); +} + void MainWindow::serverTimeout() { QMessageBox::critical(this, tr("Error"), tr("Server timeout")); @@ -687,6 +693,7 @@ void MainWindow::retranslateUi() aUpdate->setText(tr("Check for Client Updates")); aCheckCardUpdates->setText(tr("Check for Card Updates...")); aViewLog->setText(tr("View &Debug Log")); + aOpenSettingsFolder->setText(tr("Open Settings Folder")); aShow->setText(tr("Show/Hide")); @@ -743,6 +750,8 @@ void MainWindow::createActions() connect(aCheckCardUpdates, SIGNAL(triggered()), this, SLOT(actCheckCardUpdates())); aViewLog = new QAction(this); connect(aViewLog, SIGNAL(triggered()), this, SLOT(actViewLog())); + aOpenSettingsFolder = new QAction(this); + connect(aOpenSettingsFolder, &QAction::triggered, this, &MainWindow::actOpenSettingsFolder); aShow = new QAction(this); connect(aShow, SIGNAL(triggered()), this, SLOT(actShow())); @@ -818,6 +827,7 @@ void MainWindow::createMenus() helpMenu->addAction(aCheckCardUpdates); helpMenu->addSeparator(); helpMenu->addAction(aViewLog); + helpMenu->addAction(aOpenSettingsFolder); } MainWindow::MainWindow(QWidget *parent) diff --git a/cockatrice/src/client/ui/window_main.h b/cockatrice/src/client/ui/window_main.h index 356b6f529..4efed7fd5 100644 --- a/cockatrice/src/client/ui/window_main.h +++ b/cockatrice/src/client/ui/window_main.h @@ -84,6 +84,7 @@ private slots: void actTips(); void actUpdate(); void actViewLog(); + void actOpenSettingsFolder(); void forgotPasswordSuccess(); void forgotPasswordError(); void promptForgotPasswordReset(); @@ -134,7 +135,8 @@ private: QAction *aConnect, *aDisconnect, *aSinglePlayer, *aWatchReplay, *aDeckEditor, *aVisualDeckStorage, *aFullScreen, *aSettings, *aExit, *aAbout, *aTips, *aCheckCardUpdates, *aRegister, *aForgotPassword, *aUpdate, *aViewLog, *aManageSets, *aEditTokens, *aOpenCustomFolder, *aOpenCustomsetsFolder, *aAddCustomSet, *aReloadCardDatabase, - *aShow; + *aShow, *aOpenSettingsFolder; + TabSupervisor *tabSupervisor; WndSets *wndSets; RemoteClient *client; diff --git a/cockatrice/src/dialogs/dlg_load_deck.cpp b/cockatrice/src/dialogs/dlg_load_deck.cpp new file mode 100644 index 000000000..0fabdaaa3 --- /dev/null +++ b/cockatrice/src/dialogs/dlg_load_deck.cpp @@ -0,0 +1,22 @@ +#include "dlg_load_deck.h" + +#include "../deck/deck_loader.h" +#include "../settings/cache_settings.h" + +DlgLoadDeck::DlgLoadDeck(QWidget *parent) : QFileDialog(parent, tr("Load Deck")) +{ + QString startingDir = SettingsCache::instance().recents().getLatestDeckDirPath(); + if (startingDir.isEmpty()) { + startingDir = SettingsCache::instance().getDeckPath(); + } + + setDirectory(startingDir); + setNameFilters(DeckLoader::fileNameFilters); + + connect(this, &DlgLoadDeck::accepted, this, &DlgLoadDeck::actAccepted); +} + +void DlgLoadDeck::actAccepted() +{ + SettingsCache::instance().recents().setLatestDeckDirPath(directory().absolutePath()); +} \ No newline at end of file diff --git a/cockatrice/src/dialogs/dlg_load_deck.h b/cockatrice/src/dialogs/dlg_load_deck.h new file mode 100644 index 000000000..13df97995 --- /dev/null +++ b/cockatrice/src/dialogs/dlg_load_deck.h @@ -0,0 +1,21 @@ + +#ifndef DLG_LOAD_DECK_H +#define DLG_LOAD_DECK_H + +#include + +/** + * The file dialog for "Load Deck" operations. + * Handles remembering the most recently used deck loading directory. + */ +class DlgLoadDeck : public QFileDialog +{ + Q_OBJECT + + void actAccepted(); + +public: + explicit DlgLoadDeck(QWidget *parent = nullptr); +}; + +#endif // DLG_LOAD_DECK_H diff --git a/cockatrice/src/dialogs/dlg_load_deck_from_clipboard.cpp b/cockatrice/src/dialogs/dlg_load_deck_from_clipboard.cpp index e3673d1a3..dd06b45c8 100644 --- a/cockatrice/src/dialogs/dlg_load_deck_from_clipboard.cpp +++ b/cockatrice/src/dialogs/dlg_load_deck_from_clipboard.cpp @@ -71,3 +71,13 @@ void DlgLoadDeckFromClipboard::actOK() delete deckLoader; } } + +void DlgLoadDeckFromClipboard::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Return && event->modifiers() & Qt::ControlModifier) { + event->accept(); + actOK(); + return; + } + QDialog::keyPressEvent(event); +} \ No newline at end of file diff --git a/cockatrice/src/dialogs/dlg_load_deck_from_clipboard.h b/cockatrice/src/dialogs/dlg_load_deck_from_clipboard.h index 7a9833b41..56c75f707 100644 --- a/cockatrice/src/dialogs/dlg_load_deck_from_clipboard.h +++ b/cockatrice/src/dialogs/dlg_load_deck_from_clipboard.h @@ -26,6 +26,9 @@ public: { return deckList; } + +protected: + void keyPressEvent(QKeyEvent *event) override; }; #endif diff --git a/cockatrice/src/main.cpp b/cockatrice/src/main.cpp index b9bf7ea56..2384fb7e5 100644 --- a/cockatrice/src/main.cpp +++ b/cockatrice/src/main.cpp @@ -136,6 +136,9 @@ int main(int argc, char *argv[]) SetUnhandledExceptionFilter(CockatriceUnhandledExceptionFilter); #endif + // Set the QT_LOGGING_CONF environment variable + qputenv("QT_LOGGING_CONF", "./qtlogging.ini"); + QApplication app(argc, argv); QObject::connect(&app, &QApplication::lastWindowClosed, &app, &QApplication::quit); diff --git a/cockatrice/src/settings/debug_settings.cpp b/cockatrice/src/settings/debug_settings.cpp index 75276a091..f6f12f60e 100644 --- a/cockatrice/src/settings/debug_settings.cpp +++ b/cockatrice/src/settings/debug_settings.cpp @@ -5,9 +5,9 @@ DebugSettings::DebugSettings(const QString &settingPath, QObject *parent) : SettingsManager(settingPath + "debug.ini", parent) { - // force debug.ini to be created if it doesn't exist yet + // Create the default debug.ini if it doesn't exist yet if (!QFile(settingPath + "debug.ini").exists()) { - setValue(false, "showCardId", "debug"); + QFile::copy(":/resources/config/debug.ini", settingPath + "debug.ini"); } } diff --git a/cockatrice/src/settings/recents_settings.cpp b/cockatrice/src/settings/recents_settings.cpp index da3c5313e..5bbec3c8c 100644 --- a/cockatrice/src/settings/recents_settings.cpp +++ b/cockatrice/src/settings/recents_settings.cpp @@ -29,4 +29,14 @@ void RecentsSettings::updateRecentlyOpenedDeckPaths(const QString &deckPath) setValue(deckPaths, "deckpaths", "deckbuilder"); emit recentlyOpenedDeckPathsChanged(); +} + +QString RecentsSettings::getLatestDeckDirPath() +{ + return getValue("latestDeckDir", "dirs").toString(); +} + +void RecentsSettings::setLatestDeckDirPath(const QString &dirPath) +{ + setValue(dirPath, "latestDeckDir", "dirs"); } \ No newline at end of file diff --git a/cockatrice/src/settings/recents_settings.h b/cockatrice/src/settings/recents_settings.h index c240b100d..6e91cd2f0 100644 --- a/cockatrice/src/settings/recents_settings.h +++ b/cockatrice/src/settings/recents_settings.h @@ -16,6 +16,9 @@ public: void clearRecentlyOpenedDeckPaths(); void updateRecentlyOpenedDeckPaths(const QString &deckPath); + QString getLatestDeckDirPath(); + void setLatestDeckDirPath(const QString &dirPath); + signals: void recentlyOpenedDeckPathsChanged(); };