diff --git a/cockatrice/src/client/tabs/tab_deck_editor.cpp b/cockatrice/src/client/tabs/tab_deck_editor.cpp index f9a7632dc..cc8c53069 100644 --- a/cockatrice/src/client/tabs/tab_deck_editor.cpp +++ b/cockatrice/src/client/tabs/tab_deck_editor.cpp @@ -1045,7 +1045,7 @@ void TabDeckEditor::openDeckFromFile(const QString &fileName, DeckOpenLocation d DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(fileName); auto *l = new DeckLoader; - if (l->loadFromFile(fileName, fmt)) { + if (l->loadFromFile(fileName, fmt, true)) { SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(fileName); updateBannerCardComboBox(); if (!l->getBannerCard().isEmpty()) { diff --git a/cockatrice/src/client/tabs/tab_deck_storage.cpp b/cockatrice/src/client/tabs/tab_deck_storage.cpp index 718eedb2a..4435e5a22 100644 --- a/cockatrice/src/client/tabs/tab_deck_storage.cpp +++ b/cockatrice/src/client/tabs/tab_deck_storage.cpp @@ -203,7 +203,7 @@ void TabDeckStorage::actOpenLocalDeck() QString filePath = localDirModel->filePath(curLeft); DeckLoader deckLoader; - if (!deckLoader.loadFromFile(filePath, DeckLoader::CockatriceFormat)) + if (!deckLoader.loadFromFile(filePath, DeckLoader::CockatriceFormat, true)) continue; SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(filePath); diff --git a/cockatrice/src/client/tabs/tab_game.cpp b/cockatrice/src/client/tabs/tab_game.cpp index acdb6d0bf..daa51e974 100644 --- a/cockatrice/src/client/tabs/tab_game.cpp +++ b/cockatrice/src/client/tabs/tab_game.cpp @@ -307,7 +307,7 @@ void DeckViewContainer::replaceDeckStorageWithDeckView(QMouseEvent *event, DeckP QString deckString; DeckLoader deck; - bool error = !deck.loadFromFile(fileName, fmt); + bool error = !deck.loadFromFile(fileName, fmt, true); if (!error) { deckString = deck.writeToString_Native(); error = deckString.length() > MAX_FILE_LENGTH; @@ -357,7 +357,7 @@ void DeckViewContainer::loadDeckFromFile(const QString &filePath) QString deckString; DeckLoader deck; - bool error = !deck.loadFromFile(filePath, fmt); + bool error = !deck.loadFromFile(filePath, fmt, true); if (!error) { deckString = deck.writeToString_Native(); error = deckString.length() > MAX_FILE_LENGTH; diff --git a/cockatrice/src/client/tabs/visual_deck_storage/tab_deck_storage_visual.cpp b/cockatrice/src/client/tabs/visual_deck_storage/tab_deck_storage_visual.cpp index 831e7ed97..7d3370f3b 100644 --- a/cockatrice/src/client/tabs/visual_deck_storage/tab_deck_storage_visual.cpp +++ b/cockatrice/src/client/tabs/visual_deck_storage/tab_deck_storage_visual.cpp @@ -78,7 +78,7 @@ void TabDeckStorageVisual::actOpenLocalDeck(QMouseEvent *event, DeckPreviewCardP { (void)event; DeckLoader deckLoader; - if (!deckLoader.loadFromFile(instance->filePath, DeckLoader::CockatriceFormat)) + if (!deckLoader.loadFromFile(instance->filePath, DeckLoader::CockatriceFormat, true)) return; emit openDeckEditor(&deckLoader); diff --git a/cockatrice/src/deck/deck_loader.cpp b/cockatrice/src/deck/deck_loader.cpp index e64ef7446..a4c1fa4ed 100644 --- a/cockatrice/src/deck/deck_loader.cpp +++ b/cockatrice/src/deck/deck_loader.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -34,7 +35,7 @@ DeckLoader::DeckLoader(const DeckLoader &other) { } -bool DeckLoader::loadFromFile(const QString &fileName, FileFormat fmt) +bool DeckLoader::loadFromFile(const QString &fileName, FileFormat fmt, bool userRequest) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -50,7 +51,7 @@ bool DeckLoader::loadFromFile(const QString &fileName, FileFormat fmt) result = loadFromFile_Native(&file); qDebug() << "Loaded from" << fileName << "-" << result; if (!result) { - qDebug() << "Retying as plain format"; + qDebug() << "Retrying as plain format"; file.seek(0); result = loadFromFile_Plain(&file); fmt = PlainTextFormat; @@ -65,6 +66,9 @@ bool DeckLoader::loadFromFile(const QString &fileName, FileFormat fmt) if (result) { lastFileName = fileName; lastFileFormat = fmt; + if (userRequest) { + updateLastLoadedTimestamp(fileName, fmt); + } emit deckLoaded(); } @@ -110,6 +114,59 @@ bool DeckLoader::saveToFile(const QString &fileName, FileFormat fmt) return result; } +bool DeckLoader::updateLastLoadedTimestamp(const QString &fileName, FileFormat fmt) +{ + QFileInfo fileInfo(fileName); + if (!fileInfo.exists()) { + qWarning() << "File does not exist:" << fileName; + return false; + } + + QDateTime originalTimestamp = fileInfo.lastModified(); + + // Open the file for writing + QFile file(fileName); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + qWarning() << "Failed to open file for writing:" << fileName; + return false; + } + + bool result = false; + + // Perform file modifications + switch (fmt) { + case PlainTextFormat: + break; + case CockatriceFormat: + setLastLoadedTimestamp(QDateTime::currentDateTime().toString()); + result = saveToFile_Native(&file); + break; + } + + file.close(); // Close the file to ensure changes are flushed + + if (result) { + lastFileName = fileName; + lastFileFormat = fmt; + + // Re-open the file and set the original timestamp + if (!file.open(QIODevice::ReadWrite)) { + qWarning() << "Failed to re-open file to set timestamp:" << fileName; + return false; + } + + if (!file.setFileTime(originalTimestamp, QFileDevice::FileModificationTime)) { + qWarning() << "Failed to set modification time for file:" << fileName; + file.close(); + return false; + } + + file.close(); + } + + return result; +} + // This struct is here to support the forEachCard function call, defined in decklist. It // requires a function to be called for each card, and passes an inner node and a card for // each card in the decklist. @@ -120,7 +177,7 @@ struct FormatDeckListForExport QString &sideBoardCards; // create main operator for struct, allowing the foreachcard to work. FormatDeckListForExport(QString &_mainBoardCards, QString &_sideBoardCards) - : mainBoardCards(_mainBoardCards), sideBoardCards(_sideBoardCards){}; + : mainBoardCards(_mainBoardCards), sideBoardCards(_sideBoardCards) {}; void operator()(const InnerDecklistNode *node, const DecklistCardNode *card) const { diff --git a/cockatrice/src/deck/deck_loader.h b/cockatrice/src/deck/deck_loader.h index 3f1ff1d28..741e5fe30 100644 --- a/cockatrice/src/deck/deck_loader.h +++ b/cockatrice/src/deck/deck_loader.h @@ -42,9 +42,10 @@ public: static FileFormat getFormatFromName(const QString &fileName); - bool loadFromFile(const QString &fileName, FileFormat fmt); + bool loadFromFile(const QString &fileName, FileFormat fmt, bool userRequest = false); bool loadFromRemote(const QString &nativeString, int remoteDeckId); bool saveToFile(const QString &fileName, FileFormat fmt); + bool updateLastLoadedTimestamp(const QString &fileName, FileFormat fmt); QString exportDeckToDecklist(); void resolveSetNameAndNumberToProviderID(); diff --git a/common/decklist.cpp b/common/decklist.cpp index 5c34fdb06..c6f345d58 100644 --- a/common/decklist.cpp +++ b/common/decklist.cpp @@ -368,7 +368,8 @@ DeckList::DeckList() // TODO: https://qt-project.org/doc/qt-4.8/qobject.html#no-copy-constructor-or-assignment-operator DeckList::DeckList(const DeckList &other) - : QObject(), name(other.name), comments(other.comments), bannerCard(other.bannerCard), deckHash(other.deckHash) + : QObject(), name(other.name), comments(other.comments), bannerCard(other.bannerCard), deckHash(other.deckHash), + lastLoadedTimestamp(other.lastLoadedTimestamp) { root = new InnerDecklistNode(other.getRoot()); @@ -419,13 +420,14 @@ bool DeckList::readElement(QXmlStreamReader *xml) { const QString childName = xml->name().toString(); if (xml->isStartElement()) { - if (childName == "deckname") + if (childName == "lastLoadedTimestamp") { + lastLoadedTimestamp = xml->readElementText(); + } else if (childName == "deckname") name = xml->readElementText(); else if (childName == "comments") comments = xml->readElementText(); else if (childName == "bannerCard") { bannerCard = xml->readElementText(); - qDebug() << "Deckloader found the banner card " << bannerCard; } else if (childName == "zone") { InnerDecklistNode *newZone = getZoneObjFromName(xml->attributes().value("name").toString()); newZone->readElement(xml); @@ -445,6 +447,7 @@ void DeckList::write(QXmlStreamWriter *xml) { xml->writeStartElement("cockatrice_deck"); xml->writeAttribute("version", "1"); + xml->writeTextElement("lastLoadedTimestamp", lastLoadedTimestamp); xml->writeTextElement("deckname", name); xml->writeTextElement("comments", comments); xml->writeTextElement("bannerCard", bannerCard); diff --git a/common/decklist.h b/common/decklist.h index 3c879e376..8da5ae44b 100644 --- a/common/decklist.h +++ b/common/decklist.h @@ -252,6 +252,7 @@ class DeckList : public QObject private: QString name, comments, bannerCard; QString deckHash; + QString lastLoadedTimestamp; QMap sideboardPlans; InnerDecklistNode *root; void getCardListHelper(InnerDecklistNode *node, QSet &result) const; @@ -283,6 +284,10 @@ public slots: { bannerCard = _bannerCard; } + void setLastLoadedTimestamp(const QString &_lastLoadedTimestamp = QString()) + { + lastLoadedTimestamp = _lastLoadedTimestamp; + } public: explicit DeckList(); @@ -301,6 +306,10 @@ public: { return bannerCard; } + QString getLastLoadedTimestamp() const + { + return lastLoadedTimestamp; + } QList getCurrentSideboardPlan(); void setCurrentSideboardPlan(const QList &plan); const QMap &getSideboardPlans() const