diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 68300081a..aacff39cf 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -313,6 +313,7 @@ set(cockatrice_SOURCES src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.cpp src/interface/key_signals.cpp src/interface/logger.cpp + src/interface/recording.cpp src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_bracket_navigation_widget.cpp src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_bracket_navigation_widget.h src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_budget_navigation_widget.cpp diff --git a/cockatrice/resources/config/qtlogging.ini b/cockatrice/resources/config/qtlogging.ini index 20aa206ce..0ee230667 100644 --- a/cockatrice/resources/config/qtlogging.ini +++ b/cockatrice/resources/config/qtlogging.ini @@ -10,6 +10,7 @@ # or set = false to disable logging #main = true +#recording = true #qt_translator = true #window_main.* = true #release_channel = true diff --git a/cockatrice/src/interface/recording.cpp b/cockatrice/src/interface/recording.cpp new file mode 100644 index 000000000..79a22ef81 --- /dev/null +++ b/cockatrice/src/interface/recording.cpp @@ -0,0 +1,120 @@ +#include "recording.h" + +#include +#include +#include + +XMLEventObserver::XMLEventObserver(QObject *p) : pqEventObserver(p) +{ + XMLStream = nullptr; +} + +XMLEventObserver::~XMLEventObserver() +{ + delete XMLStream; +} + +void XMLEventObserver::setStream(QTextStream *stream) +{ + if (XMLStream) { + XMLStream->writeEndElement(); + XMLStream->writeEndDocument(); + delete XMLStream; + XMLStream = nullptr; + } + if (Stream) { + *Stream << XMLString; + } + XMLString = QString(); + pqEventObserver::setStream(stream); + if (Stream) { + XMLStream = new QXmlStreamWriter(&XMLString); + XMLStream->setAutoFormatting(true); + XMLStream->writeStartDocument(); + XMLStream->writeStartElement("events"); + } +} + +void XMLEventObserver::onRecordEvent(const QString &widget, + const QString &command, + const QString &arguments, + const int &eventType) +{ + if (XMLStream) { + XMLStream->writeStartElement("event"); + XMLStream->writeAttribute("widget", widget); + if (eventType == pqEventTypes::ACTION_EVENT) { + XMLStream->writeAttribute("command", command); + } else // if(eventType == pqEventTypes::CHECK_EVENT) + { + XMLStream->writeAttribute("property", command); + } + XMLStream->writeAttribute("arguments", arguments); + XMLStream->writeEndElement(); + } +} + +XMLEventSource::XMLEventSource(QObject *p) : pqEventSource(p) +{ + XMLStream = nullptr; +} + +XMLEventSource::~XMLEventSource() +{ + delete XMLStream; +} + +void XMLEventSource::setContent(const QString &xmlFileName) +{ + delete XMLStream; + XMLStream = nullptr; + + QFile xml(xmlFileName); + if (!xml.open(QIODevice::ReadOnly)) { + qCWarning(RecordingLog) << "Failed to load " << xmlFileName; + return; + } + QByteArray data = xml.readAll(); + XMLStream = new QXmlStreamReader(data); + /* This checked for valid event objects, but also caused the first event + * to get dropped. Commenting this out in the example. If you wish to report + * empty XML test files a flag indicating whether valid events were found is + * probably the best way to go. + while (!XMLStream->atEnd()) + { + QXmlStreamReader::TokenType token = XMLStream->readNext(); + if (token == QXmlStreamReader::StartElement) + { + if (XMLStream->name() == "event") + { + break; + } + } + } */ + if (XMLStream->atEnd()) { + qCWarning(RecordingLog) << "Invalid xml from" << xmlFileName; + } +} + +int XMLEventSource::getNextEvent(QString &widget, QString &command, QString &arguments, int &eventType) +{ + if (XMLStream->atEnd()) { + return DONE; + } + while (!XMLStream->atEnd()) { + QXmlStreamReader::TokenType token = XMLStream->readNext(); + if (token == QXmlStreamReader::StartElement) { + if (XMLStream->name() == "event") { + break; + } + } + } + if (XMLStream->atEnd()) { + return DONE; + } + eventType = pqEventTypes::ACTION_EVENT; + widget = XMLStream->attributes().value("widget").toString(); + command = XMLStream->attributes().value("command").toString(); + arguments = XMLStream->attributes().value("arguments").toString(); + return SUCCESS; +} diff --git a/cockatrice/src/interface/recording.h b/cockatrice/src/interface/recording.h new file mode 100644 index 000000000..ea8162b92 --- /dev/null +++ b/cockatrice/src/interface/recording.h @@ -0,0 +1,44 @@ +#ifndef COCKATRICE_RECORDING_H +#define COCKATRICE_RECORDING_H + +#include "pqEventObserver.h" +#include "pqEventSource.h" + +#include + +inline Q_LOGGING_CATEGORY(RecordingLog, "recording"); + +class QXmlStreamReader; +class QXmlStreamWriter; + +class XMLEventObserver : public pqEventObserver +{ + QXmlStreamWriter *XMLStream; + QString XMLString; + +public: + explicit XMLEventObserver(QObject *p); + ~XMLEventObserver() override; + +protected: + void setStream(QTextStream *stream) override; + void onRecordEvent(const QString &widget, + const QString &command, + const QString &arguments, + const int &eventType) override; +}; + +class XMLEventSource : public pqEventSource +{ + QXmlStreamReader *XMLStream; + +public: + explicit XMLEventSource(QObject *p); + ~XMLEventSource() override; + +protected: + void setContent(const QString &xmlFileName) override; + int getNextEvent(QString &widget, QString &command, QString &arguments, int &eventType) override; +}; + +#endif // COCKATRICE_RECORDING_H diff --git a/cockatrice/src/interface/window_main.cpp b/cockatrice/src/interface/window_main.cpp index 8195ab500..14653b38a 100644 --- a/cockatrice/src/interface/window_main.cpp +++ b/cockatrice/src/interface/window_main.cpp @@ -42,6 +42,7 @@ #include "pqEventSource.h" #include "pqEventTypes.h" #include "pqTestUtility.h" +#include "recording.h" #include "version_string.h" #include "widgets/utility/get_text_with_max.h" @@ -863,137 +864,6 @@ void MainWindow::createMenus() helpMenu->addAction(aPlayRecording); } -class XMLEventObserver : public pqEventObserver -{ - QXmlStreamWriter *XMLStream; - QString XMLString; - -public: - XMLEventObserver(QObject *p) : pqEventObserver(p) - { - this->XMLStream = NULL; - } - - ~XMLEventObserver() override - { - delete this->XMLStream; - } - -protected: - void setStream(QTextStream *stream) override - { - if (this->XMLStream) { - this->XMLStream->writeEndElement(); - this->XMLStream->writeEndDocument(); - delete this->XMLStream; - this->XMLStream = NULL; - } - if (this->Stream) { - *this->Stream << this->XMLString; - } - this->XMLString = QString(); - pqEventObserver::setStream(stream); - if (this->Stream) { - this->XMLStream = new QXmlStreamWriter(&this->XMLString); - this->XMLStream->setAutoFormatting(true); - this->XMLStream->writeStartDocument(); - this->XMLStream->writeStartElement("events"); - } - } - - void onRecordEvent(const QString &widget, - const QString &command, - const QString &arguments, - const int &eventType) override - { - if (this->XMLStream) { - this->XMLStream->writeStartElement("event"); - this->XMLStream->writeAttribute("widget", widget); - if (eventType == pqEventTypes::ACTION_EVENT) { - this->XMLStream->writeAttribute("command", command); - } else // if(eventType == pqEventTypes::CHECK_EVENT) - { - this->XMLStream->writeAttribute("property", command); - } - this->XMLStream->writeAttribute("arguments", arguments); - this->XMLStream->writeEndElement(); - } - } -}; - -class XMLEventSource : public pqEventSource -{ - typedef pqEventSource Superclass; - QXmlStreamReader *XMLStream; - -public: - XMLEventSource(QObject *p) : Superclass(p) - { - this->XMLStream = NULL; - } - ~XMLEventSource() override - { - delete this->XMLStream; - } - -protected: - void setContent(const QString &xmlfilename) override - { - delete this->XMLStream; - this->XMLStream = NULL; - - QFile xml(xmlfilename); - if (!xml.open(QIODevice::ReadOnly)) { - qDebug() << "Failed to load " << xmlfilename; - return; - } - QByteArray data = xml.readAll(); - this->XMLStream = new QXmlStreamReader(data); - /* This checked for valid event objects, but also caused the first event - * to get dropped. Commenting this out in the example. If you wish to report - * empty XML test files a flag indicating whether valid events were found is - * probably the best way to go. - while (!this->XMLStream->atEnd()) - { - QXmlStreamReader::TokenType token = this->XMLStream->readNext(); - if (token == QXmlStreamReader::StartElement) - { - if (this->XMLStream->name() == "event") - { - break; - } - } - } */ - if (this->XMLStream->atEnd()) { - qDebug() << "Invalid xml"; - } - return; - } - - int getNextEvent(QString &widget, QString &command, QString &arguments, int &eventType) override - { - if (this->XMLStream->atEnd()) { - return DONE; - } - while (!this->XMLStream->atEnd()) { - QXmlStreamReader::TokenType token = this->XMLStream->readNext(); - if (token == QXmlStreamReader::StartElement) { - if (this->XMLStream->name() == "event") { - break; - } - } - } - if (this->XMLStream->atEnd()) { - return DONE; - } - eventType = pqEventTypes::ACTION_EVENT; - widget = this->XMLStream->attributes().value("widget").toString(); - command = this->XMLStream->attributes().value("command").toString(); - arguments = this->XMLStream->attributes().value("arguments").toString(); - return SUCCESS; - } -}; - MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), localServer(nullptr), bHasActivated(false), askedForDbUpdater(false), cardUpdateProcess(nullptr), logviewDialog(nullptr)