diff --git a/CMakeLists.txt b/CMakeLists.txt index edb6c4f9740ebf5f5958aaf16fd6b525f8bfea6c..498df5aac7578066f286834fe18671f9a7e3ecdf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,11 +90,18 @@ target_compile_features(Vivy PRIVATE # More options and warnings target_compile_options(Vivy PRIVATE - -Wall -Wextra -Wshadow -pedantic - -Wcast-align -Wconversion -Wsign-conversion -Wunused-variable - -Wmisleading-indentation -Wnull-dereference -Wdouble-promotion + -Wall -Wextra -Wpedantic + -Wshadow + -Wcast-align + -Wconversion + -Wsign-conversion + -Wunused-variable + -Wmisleading-indentation + -Wnull-dereference + -Wdouble-promotion -Wformat=2 - -Woverloaded-virtual -Wnon-virtual-dtor + -Woverloaded-virtual + -Wnon-virtual-dtor -Wignored-qualifiers -fopenmp @@ -117,8 +124,11 @@ if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") # Disable some things because we want C++20 and don't control some Qt # generated files... - -Wno-c++98-compat -Wno-c++98-c++11-c++14-c++17-compat-pedantic + -Wno-c++98-compat -Wno-c++98-compat-pedantic + -Wno-c++98-c++11-c++14-c++17-compat-pedantic + -Wno-c++20-compat + -Wno-extra-semi-stmt -Wno-redundant-parens -Wno-padded diff --git a/PreCompiledHeaders.cmake b/PreCompiledHeaders.cmake index dce8f03b4c87f3ac598c970fe04e5e173e476c6e..f09e72ab569a20b3f841dd0b73132b36f301481f 100644 --- a/PreCompiledHeaders.cmake +++ b/PreCompiledHeaders.cmake @@ -23,6 +23,7 @@ set(STL_INC <climits> <ctype.h> <mutex> + <iomanip> ) set(EXT_INC PRIVATE diff --git a/src/Lib/AbstractDocument.hh b/src/Lib/AbstractDocument.hh index dfec447f3bdbc696e313bc6985b487ea94ad1a8a..c39fb5661a9cdcc3bd841950fe18c011f9214972 100644 --- a/src/Lib/AbstractDocument.hh +++ b/src/Lib/AbstractDocument.hh @@ -4,8 +4,10 @@ #error "This is a C++ header" #endif +#include "../VivyApplication.hh" #include "Utils.hh" #include "Uuid.hh" +#include "Log.hh" namespace Vivy { @@ -13,6 +15,9 @@ class AbstractDocument : public QObject { Q_OBJECT VIVY_UNMOVABLE_OBJECT(AbstractDocument) +protected: + VIVY_APP_LOGGABLE_OBJECT(AbstractDocument, logger) + void copyOrRenameWith(const QFileInfo &newFile, auto action, auto success) { const QFileInfo oldFile(getName()); @@ -21,7 +26,7 @@ class AbstractDocument : public QObject { QDir dirOp; const QString newAbsDirPath = newFile.dir().absolutePath(); if (!dirOp.exists(newAbsDirPath)) { - qInfo() << "Create folder " << newAbsDirPath; + logInfo() << "Create folder " << VIVY_LOG_QUOTED(newAbsDirPath); dirOp.mkpath(newAbsDirPath); } @@ -30,7 +35,7 @@ class AbstractDocument : public QObject { } if (newFile.exists()) { - qWarning() << "Deleting the already existing" << newFile; + logWarning() << "Deleting the already existing file " << VIVY_LOG_QUOTED(newFile); if (!dirOp.remove(newFile.absoluteFilePath())) throw std::runtime_error("Failed to remove " + newFile.absoluteFilePath().toStdString()); diff --git a/src/Lib/AbstractMediaContext.hh b/src/Lib/AbstractMediaContext.hh index f4a09ed6c040a96dcbea04d0b71fe2491430f727..a15609de50345b89f238deae99cbb8722de14456 100644 --- a/src/Lib/AbstractMediaContext.hh +++ b/src/Lib/AbstractMediaContext.hh @@ -10,10 +10,11 @@ extern "C" { #include <libavformat/avformat.h> #include <libswresample/swresample.h> #include <libavcodec/avfft.h> -#include <memory.h> } +#include "../VivyApplication.hh" #include "Utils.hh" +#include "Log.hh" namespace Vivy { @@ -53,6 +54,7 @@ public: static inline constexpr AVMediaType avMediaType = static_cast<AVMediaType>(AVMEDIA_TYPE); protected: + VIVY_APP_LOGGABLE_OBJECT(AbstractMediaStream, logger) using Super = AbstractMediaStream<AVMEDIA_TYPE>; protected: @@ -78,10 +80,10 @@ protected: if (avcodec_open2(codecContext.get(), codec, nullptr) < 0) throw std::runtime_error("failed to open audio decoder for a stream"); - qDebug() << "[Stream] Codec" << codec->name << "id:" << codecId; - qDebug() << "[Stream] sample rate:" << codecParams->sample_rate; - qDebug() << "[Stream] bit rate: " << codecParams->bit_rate; - qDebug() << "[Stream] channels: " << codecParams->channels; + VIVY_LOG_CTOR() << "Codec: " << VIVY_LOG_QUOTED(codec->name) << ", id: " << codecId; + VIVY_LOG_CTOR() << "Sample rate: " << codecParams->sample_rate; + VIVY_LOG_CTOR() << "Bit rate: " << codecParams->bit_rate; + VIVY_LOG_CTOR() << "Channels: " << codecParams->channels; } public: @@ -121,6 +123,7 @@ public: using StreamWeakPtr = std::weak_ptr<Stream>; protected: + VIVY_APP_LOGGABLE_OBJECT(AbstractMediaContext, logger) using Super = AbstractMediaContext<Stream>; public: @@ -160,10 +163,10 @@ public: -1, // We don't want related streams nullptr, 0); if (defaultStreamIndex < 0) - qCritical() << "Could not find the best stream"; + logError() << "Could not find the best stream"; - qDebug() << "Opened context for" << path << "with duration" << formatPtr->duration - << "and default stream index" << defaultStreamIndex; + logDebug() << "Opened context for " << VIVY_LOG_QUOTED(path) << " with duration " + << formatPtr->duration << " and default stream index " << defaultStreamIndex; } virtual ~AbstractMediaContext() {} diff --git a/src/Lib/Ass/AssFactory.cc b/src/Lib/Ass/AssFactory.cc index 08ca4b7e08e93d57f0ca273adb463fb27b2032cf..93f8a92dddfeaee1929db77d0ca3b74dcf58dab2 100644 --- a/src/Lib/Ass/AssFactory.cc +++ b/src/Lib/Ass/AssFactory.cc @@ -23,9 +23,10 @@ AssFactory::initFromStorage() noexcept // Dectect sections else if (line.startsWith("[") && line.endsWith("]")) { currentSection = line.mid(1, line.size() - 2); - qDebug() << "Parsing section" << currentSection; + logDebug() << "Parsing section " << VIVY_LOG_QUOTED(currentSection); if (!validSections.contains(currentSection)) { - qWarning() << "The current section" << currentSection << "is invalid, ignoring it"; + logWarning() << "The current section " << VIVY_LOG_QUOTED(currentSection) + << " is invalid, ignoring it"; currentSection = ""; } } @@ -37,12 +38,12 @@ AssFactory::initFromStorage() noexcept // Easy way to see if the line was invalid if (separatorIndex < 0) - qWarning() << "Invalid line #" << lineIndex << ":" << line; + logWarning() << "Invalid line #" << lineIndex << ": " << line; // Script's info else if (currentSection == sectionScriptInfo) { assInfo.insert(line.mid(0, separatorIndex), line.mid(baseValueIndex)); - qDebug() << "Got line #" << lineIndex << ":" << line; + logDebug() << "Got line #" << lineIndex << ": " << line; } // Skip the headers and the comment lines @@ -65,10 +66,10 @@ AssFactory::initFromStorage() noexcept for (const auto &assLine : eventsContent) assLines.push_back(std::make_shared<Line>(this, assLine)); } catch (const std::runtime_error &e) { - qCritical() << "Failed to create ASS style or events with error:" << e.what(); + logError() << "Failed to create ASS style or events with error: " << e.what(); } - qDebug() << "Got" << assLines.size() << "ASS dialog lines"; + logDebug() << "Got " << assLines.size() << " ASS dialog lines"; return true; } @@ -77,7 +78,7 @@ bool AssFactory::checkValidity() const noexcept { if (assInfo.isEmpty()) { - qCritical() << "Empty info section"; + logError() << "Empty info section"; return false; } @@ -87,7 +88,7 @@ AssFactory::checkValidity() const noexcept while (it != end) { bool ok = false; if (intTypeFields.contains(it.key()) && (static_cast<void>(it.value().toInt(&ok)), !ok)) { - qCritical() << it.key() << "is not an integer:" << it.value(); + logError() << it.key() << " is not an integer: " << it.value(); return false; } ++it; @@ -97,8 +98,8 @@ AssFactory::checkValidity() const noexcept for (const auto &fixedValues : checkedValues) { if (const auto &first = fixedValues.first; assInfo.contains(first) && assInfo[first] != fixedValues.second) { - qCritical() << "Invalid" << first << "as it should be equal to" << fixedValues.second - << "but was" << assInfo[first]; + logError() << "Invalid " << first << " as it should be equal to " << fixedValues.second + << " but was " << assInfo[first]; return false; } } diff --git a/src/Lib/Ass/AssFactory.hh b/src/Lib/Ass/AssFactory.hh index b220c0f1995a4c633664cb42554505080b494452..98c8f3fea31fd3513f238b77c181f61f69b9e0e1 100644 --- a/src/Lib/Ass/AssFactory.hh +++ b/src/Lib/Ass/AssFactory.hh @@ -1,6 +1,7 @@ -#ifndef VIVY_ASS_FACTORY_H -#define VIVY_ASS_FACTORY_H +#pragma once +#include "../../VivyApplication.hh" +#include "../Log.hh" #include "../Utils.hh" #include "Style.hh" #include "Line.hh" @@ -13,6 +14,7 @@ namespace Vivy::Ass { class AssFactory final { VIVY_UNMOVABLE_OBJECT(AssFactory) + VIVY_APP_LOGGABLE_OBJECT(AssFactory, logger) public: enum class Section { ScriptInfo = 1, Styles = 2, Events = 3 }; @@ -55,7 +57,4 @@ public: void getStyles(QVector<StylePtr> &) const noexcept; void getLines(QVector<LinePtr> &) const noexcept; }; - } - -#endif // VIVY_ASS_FACTORY_H diff --git a/src/Lib/Ass/Line.cc b/src/Lib/Ass/Line.cc index fe0b257ab4585b7d0d962f2577177238cd328db9..046e313168aeaaf52a917bafc7e0a00d0f7ea718 100644 --- a/src/Lib/Ass/Line.cc +++ b/src/Lib/Ass/Line.cc @@ -65,7 +65,8 @@ Line::initSylFromString(const QString &line) noexcept // Matches syllabes like: `{\toto}{\alpha&HFF}content` QRegularExpression re("((?:{[^}]*})+[^{]*)"); if (!re.isValid()) - qFatal("The regex '%s' is not valid...", re.pattern().toStdString().c_str()); + logFatal() << "The regex " << VIVY_LOG_QUOTED(re.pattern().toStdString().c_str()) + << " is not valid..."; bool once = false; try { @@ -77,9 +78,8 @@ Line::initSylFromString(const QString &line) noexcept once |= true; } } catch (const std::runtime_error &e) { - qCritical() << "Failed to init syllabes with line:" << line; - qCritical() << "Error was:" << e.what(); - qCritical() << "Fallback to all line is one syllabe"; + qCritical() << "Failed to init syllabes with line: " << VIVY_LOG_QUOTED(line) + << ". Error was: " << e.what() << ". Fallback to all line is one syllabe"; once = false; } diff --git a/src/Lib/Ass/Line.hh b/src/Lib/Ass/Line.hh index 15984da129990d512c3cdc388b67143a4d808d08..11f91de64ed4c0c204b096080b16ec453f97eb63 100644 --- a/src/Lib/Ass/Line.hh +++ b/src/Lib/Ass/Line.hh @@ -1,5 +1,7 @@ #pragma once +#include "../../VivyApplication.hh" +#include "../Log.hh" #include "Syl.hh" #include "StyleProperties.hh" #include "Style.hh" @@ -9,7 +11,8 @@ namespace Vivy::Ass class AssFactory; class Line final { -private: + VIVY_APP_LOGGABLE_OBJECT(Line, logger) + quint64 start{ 0 }; quint64 end{ 0 }; int layer{ 0 }; diff --git a/src/Lib/Ass/Style.cc b/src/Lib/Ass/Style.cc index 1a6ce05cc1658ca8169c81a338917cb37f535ba8..2f80c9d1db58c37be84001ba4bd3ca5b3b1072ed 100644 --- a/src/Lib/Ass/Style.cc +++ b/src/Lib/Ass/Style.cc @@ -102,7 +102,7 @@ Style::Style(const QString &styleString) Utils::decodeLineToInteger(content[StyleIndex::Encoding], "Encoding is not an integer"); if (encoding != 1) - qWarning() << "Encoding is not '1' in the ASS Style"; + logWarning() << "Encoding is not '1' in the ASS Style"; } QString @@ -127,13 +127,8 @@ Color::fromString(const QString &colorString) noexcept startIndex++; // A valid string color is like 'AARRGGBB' for now (skipped 'aH') - if (colorString.size() - startIndex != 8) { - qCritical() - << "Invalid color string: size - index_start =" << (colorString.size() - startIndex) - << "| string =" << colorString.mid(startIndex); - qCritical() << "Found an invalid color string:" << colorString; + if (colorString.size() - startIndex != 8) return Color::defaultValue; - } bool ok_alpha = false; bool ok_red = false; @@ -144,10 +139,8 @@ Color::fromString(const QString &colorString) noexcept int green = colorString.mid(startIndex + 4, 2).toInt(&ok_green, 16); int blue = colorString.mid(startIndex + 6, 2).toInt(&ok_blue, 16); - if (!(ok_alpha && ok_red && ok_green && ok_blue)) { - qCritical() << "Found an invalid color string:" << colorString; + if (!(ok_alpha && ok_red && ok_green && ok_blue)) return Color::defaultValue; - } return QColor(red, green, blue, alpha); } diff --git a/src/Lib/Ass/Style.hh b/src/Lib/Ass/Style.hh index 696cfc79e4b082a14e8b3ad295e31455611f283c..c6c5f10b91924355bb23f33039a1a34b278a2e2d 100644 --- a/src/Lib/Ass/Style.hh +++ b/src/Lib/Ass/Style.hh @@ -1,5 +1,7 @@ #pragma once +#include "../../VivyApplication.hh" +#include "../Log.hh" #include "AssPrivate.hh" namespace Vivy::Ass @@ -15,7 +17,8 @@ private: }; class Style final { -private: + VIVY_APP_LOGGABLE_OBJECT(Style, logger) + QString styleName; QString fontName; int fontSize{}; diff --git a/src/Lib/Ass/Syl.cc b/src/Lib/Ass/Syl.cc index bac0a4d0363e269ec1d984466a767881c53108a6..65d29a85cd80ce92f5a259edfed905f59f6440f1 100644 --- a/src/Lib/Ass/Syl.cc +++ b/src/Lib/Ass/Syl.cc @@ -1,8 +1,6 @@ #include "Syl.hh" #include "Line.hh" -#include <QRegularExpression> - using namespace Vivy::Ass; Syl::Syl(Line *const line, const QString &lineString, ConstructMode mode) noexcept @@ -23,9 +21,6 @@ quint64 Syl::getDurationFromString(const QString &line) noexcept { QRegularExpression re("\\\\(?:k|K|ko|kf)(\\d+)"); - if (!re.isValid()) - qFatal("The regex '%s' is not valid...", re.pattern().toStdString().c_str()); - quint64 duration = 0; QRegularExpressionMatchIterator it = re.globalMatch(line); diff --git a/src/Lib/Ass/Syl.hh b/src/Lib/Ass/Syl.hh index 084e14e5f93ea11e001260bae8543aeef48c96d9..461746e90d6f8acf4027ddab62a3fcedf58bdb40 100644 --- a/src/Lib/Ass/Syl.hh +++ b/src/Lib/Ass/Syl.hh @@ -1,10 +1,6 @@ -#ifndef VIVY_SYL_H -#define VIVY_SYL_H +#pragma once #include "StyleProperties.hh" -#include <QString> -#include <QVector> -#include <QtGlobal> namespace Vivy::Ass { @@ -37,7 +33,4 @@ public: private: static quint64 getDurationFromString(const QString &) noexcept; }; - } - -#endif diff --git a/src/Lib/Audio.cc b/src/Lib/Audio.cc index 218763c297441fe96745decac1d076922f209f15..fdf79c0fc29e9d58165d701c452447412f6b9655 100644 --- a/src/Lib/Audio.cc +++ b/src/Lib/Audio.cc @@ -46,10 +46,10 @@ AudioStream::AudioStream(AVCodec *streamCodec, AVFormatContext *formatPtr, AVStr AudioStream::~AudioStream() noexcept { if (dataPtr) { - qDebug() << "Free data ptr"; + VIVY_LOG_DTOR() << "Free data ptr for audio stream"; free(dataPtr); } - qDebug() << "Delete stream object"; + VIVY_LOG_DTOR() << "Delete audio stream object"; } QJsonObject @@ -68,7 +68,7 @@ AudioStream::decodeData() { if (isDecoded()) throw std::logic_error("audio stream is already resampled"); - qDebug() << "Launch decoding of stream" << streamIndexInContext; + logDebug() << "Launch decoding of stream " << streamIndexInContext; AVPacket packet; av_init_packet(&packet); @@ -137,8 +137,8 @@ AudioStream::decodeData() av_packet_unref(&packet); } - qDebug() << "Decoding data finished for stream" << streamIndexInContext - << "dataPtr =" << dataPtr << "with dataSize =" << dataSize; + logDebug() << "Decoding data finished for stream " << streamIndexInContext << " with dataPtr " + << dataPtr << " and dataSize " << dataSize; } // Delete decoded data, clean up thing diff --git a/src/Lib/CRTPStore.hh b/src/Lib/CRTPStore.hh index 8324d9c606635812731708f754c7997bbe6c49e2..2aa6da2c7bcb34ae8ed039058049d944b82bf4cf 100644 --- a/src/Lib/CRTPStore.hh +++ b/src/Lib/CRTPStore.hh @@ -4,6 +4,8 @@ #error "This is a C++ header" #endif +#include "../VivyApplication.hh" +#include "Log.hh" #include "Utils.hh" #include "Uuid.hh" @@ -21,6 +23,8 @@ template <class Store, class Document> class CRTPStore { VIVY_UNMOVABLE_OBJECT(CRTPStore) protected: + VIVY_APP_LOGGABLE_OBJECT(CRTPStore, logger) + std::map<Uuid, std::shared_ptr<Document>> documents{}; uint newDocumentNumber{ 1 }; static inline const QString newDocumentBaseName = QStringLiteral("Untitled "); @@ -56,7 +60,7 @@ public: auto *self = static_cast<Store *>(this); if (!self->documents.contains(uuid)) { - qCritical() << "Couldn't find the document " << uuid; + logError() << "Couldn't find the document " << uuid; throw std::runtime_error("Can't find the document"); } diff --git a/src/Lib/Document/CRTPSubDocument.hh b/src/Lib/Document/CRTPSubDocument.hh index c89f25c587539613cc5ad1f0c00305629f2eb984..7100a19ab30c7275d4cae86535dc0cd5c9f5c8c0 100644 --- a/src/Lib/Document/CRTPSubDocument.hh +++ b/src/Lib/Document/CRTPSubDocument.hh @@ -4,6 +4,8 @@ #error "This is a C++ header" #endif +#include "../../VivyApplication.hh" +#include "../Log.hh" #include "../Utils.hh" #include "../Audio.hh" #include "../Video.hh" @@ -15,10 +17,13 @@ namespace Vivy { // The Big CRTP class for all common things to all the subdocuments -template <class CRTPSubDocumentType, class Document, class Context> class CRTPSubDocument { +template <class CRTPSubDocumentType, class Document, class Context = void> class CRTPSubDocument { +protected: + VIVY_APP_LOGGABLE_OBJECT(CRTPSubDocument, logger) + friend std::unique_ptr<Document>; + public: using Type = CRTPSubDocumentType; - friend std::unique_ptr<Document>; protected: QString filePath; @@ -35,14 +40,15 @@ protected: public: static std::unique_ptr<Document> fromFile(const QString &path) noexcept { - qDebug() << "Init document from file " << path; - auto ret = std::unique_ptr<Document>(new Document()); + auto ret = std::unique_ptr<Document>(new Document()); + ret->logDebug() << "Init document from file " << VIVY_LOG_QUOTED(path); ret->filePath = path; try { ret->initFromPath(path); // May throw } catch (const std::runtime_error &e) { - qDebug().nospace() << "Failed to init document from file " << path << ": " << e.what(); + ret->logDebug() << "Failed to init document from file " << VIVY_LOG_QUOTED(path) << ": " + << e.what(); ret.reset(); } @@ -118,7 +124,7 @@ public: }; // ASS document -class AssSubDocument final : public CRTPSubDocument<AssDocumentType, AssSubDocument, void> { +class AssSubDocument final : public CRTPSubDocument<AssDocumentType, AssSubDocument> { static constexpr inline bool hasContext = false; const QStringList &suffixList = Vivy::Utils::assFileSuffix; diff --git a/src/Lib/Document/CRTPSubDocument/AudioSubDocument.cc b/src/Lib/Document/CRTPSubDocument/AudioSubDocument.cc index c91c3752109af9df968d21d46d32ca433557c1b9..d10fb949520f043cfd3d489f3127ddf23f4229fe 100644 --- a/src/Lib/Document/CRTPSubDocument/AudioSubDocument.cc +++ b/src/Lib/Document/CRTPSubDocument/AudioSubDocument.cc @@ -8,10 +8,10 @@ void AudioSubDocument::initFromPath(const QString &path) { if (contextPtr) - qDebug() << "Replacing the audio contetx by a new one for file" << path; + logDebug() << "Replacing the audio contetx by a new one for file " << VIVY_LOG_QUOTED(path); contextPtr.reset(new AudioContext(path)); // May throw - qDebug() << "Audio OK for" << path; + logDebug() << "Audio OK for " << VIVY_LOG_QUOTED(path); } QString diff --git a/src/Lib/Document/VivyDocument.cc b/src/Lib/Document/VivyDocument.cc index 6749fcc3cce6e5acb44bf584ccb9c345903835cc..6cff0405c0ea45aa91b05ce900c7660d150acbbc 100644 --- a/src/Lib/Document/VivyDocument.cc +++ b/src/Lib/Document/VivyDocument.cc @@ -154,18 +154,18 @@ VivyDocument::loadSubDocument(const QString &subName) noexcept if (detectDocumentType(file, &ableType)) { switch (ableType) { case Capabilities::AudioAble: - qDebug() << "Auto-detect audio document for" << subName; + logDebug() << "Auto-detect audio document for " << subName; setAudioSubDocument(file.absoluteFilePath()); return true; case Capabilities::VideoAble: - qDebug() << "Auto-detect video (and try audio) document for" << subName; + logDebug() << "Auto-detect video (and try audio) document for " << subName; setVideoSubDocument(file.absoluteFilePath()); setAudioSubDocument(file.absoluteFilePath()); return true; case Capabilities::AssAble: - qDebug() << "Auto-detect ASS document for" << subName; + logDebug() << "Auto-detect ASS document for " << subName; setAssSubDocument(file.absoluteFilePath()); return true; } @@ -180,24 +180,24 @@ VivyDocument::loadSubDocument(const QString &subName, VivyDocument::Capabilities QFileInfo file(subName); Capabilities ableType; if (!detectDocumentType(file, &ableType)) { - qCritical() << "Failed to detect type for file " << subName; + logError() << "Failed to detect type for file " << subName; return false; } if (ableType == Capabilities::AssAble && asType == Capabilities::AssAble) { - qDebug() << "Create an ass subDocument from " << subName; + logDebug() << "Create an ass subDocument from " << subName; setAssSubDocument(file.absoluteFilePath()); } else if (ableType == Capabilities::VideoAble && asType == Capabilities::VideoAble) { - qDebug() << "Create a video subDocument from " << subName; + logDebug() << "Create a video subDocument from " << subName; setVideoSubDocument(file.absoluteFilePath()); } else if (const bool requestAudio = (asType == Capabilities::AudioAble); (ableType == Capabilities::VideoAble && requestAudio) || (ableType == Capabilities::AudioAble && requestAudio)) { - qDebug() << "Create an audio subDocument from " << subName; + logDebug() << "Create an audio subDocument from " << subName; setAudioSubDocument(file.absoluteFilePath()); } @@ -237,7 +237,7 @@ VivyDocument::copy(const QString &newName) // Compute new paths, the document is really on disk initially else { - qDebug() << "Renaming a real file"; + logDebug() << "Renaming a real file to " << newName; copyWith(newPath, [=, this]() noexcept -> void { documentLocation = newPath.dir(); documentName = newPath.baseName(); @@ -259,7 +259,7 @@ VivyDocument::rename(const QString &newName) // Compute new paths, the document is really on disk initially else { - qDebug() << "Renaming a real file"; + logDebug() << "Renaming a real file to " << newName; renameWith(newPath, [=, this]() noexcept -> void { documentLocation = newPath.dir(); documentName = newPath.baseName(); @@ -285,8 +285,8 @@ VivyDocument::saveMemoryFile(const QFileInfo &newPath) documentLocation = newPath.absoluteDir(); name = newPath.absoluteFilePath(); documentOptions = static_cast<Options>(documentOptions & (~MemoryDocumentCreation)); - qDebug().nospace() << "Renaming a memory file => create it on disk with { " << documentLocation - << ", " << documentName << " }"; + logDebug() << "Renaming a memory file => create it on disk with { " + << documentLocation.absolutePath() << ", " << documentName << " }"; save(); } @@ -336,7 +336,7 @@ VivyDocument::getDocumentCapabilitiesString() const noexcept void VivyDocument::setAudioSubDocument(const QString filename) noexcept { - qDebug() << "[Audio sub-doc] Trying to open file" << filename; + logDebug() << "Audio sub-doc: Trying to open file " << filename; QFileInfo fileInfo(filename); const QString baseName = fileInfo.baseName(); @@ -353,7 +353,7 @@ VivyDocument::setAudioSubDocument(const QString filename) noexcept void VivyDocument::setVideoSubDocument(const QString filename) noexcept { - qDebug() << "[Video sub-doc] Trying to open file" << filename; + logDebug() << "Video sub-doc: Trying to open file " << filename; QFileInfo fileInfo(filename); const QString baseName = fileInfo.baseName(); @@ -370,7 +370,7 @@ VivyDocument::setVideoSubDocument(const QString filename) noexcept void VivyDocument::setAssSubDocument(const QString filename) noexcept { - qDebug() << "[ASS sub-doc] Trying to open file" << filename; + logDebug() << "ASS sub-doc: Trying to open file " << filename; QFileInfo fileInfo(filename); const QString baseName = fileInfo.baseName(); diff --git a/src/Lib/Document/VivyDocumentStore.cc b/src/Lib/Document/VivyDocumentStore.cc index 909d9e270367c90526b04c3c5c5f52d75d0fd93a..3d9618c86f192b0c79b8abce9a25f1fd34ddb042 100644 --- a/src/Lib/Document/VivyDocumentStore.cc +++ b/src/Lib/Document/VivyDocumentStore.cc @@ -15,10 +15,10 @@ VivyDocumentStore::newDocument(VivyDocument::Options opt) if (ret) { const Uuid uuid = ret->getUuid(); documents[uuid] = ret; - qDebug() << "Create new document " << newDocName << "with uuid" << uuid; + logDebug() << "Create new document " << newDocName << " with uuid" << uuid; return ret; } else { - qDebug() << "Failed to create new document " << newDocName; + logDebug() << "Failed to create new document " << newDocName; throw std::runtime_error("Failed to create the document"); } } diff --git a/src/Lib/Log.cc b/src/Lib/Log.cc index d23cabcc6e1e92fcb0ed3a30b254034a91cf8b6c..8cbebd7594a45800e6fc2b13f1b6f2a80a7506ea 100644 --- a/src/Lib/Log.cc +++ b/src/Lib/Log.cc @@ -1,10 +1,34 @@ #include "Log.hh" +// Vivy::LogLevel utility implementation +namespace Vivy +{ +const std::string_view +LogLevel::toStdStringView(const LogLevel::Level lvl) noexcept +{ + return LevelsStringViews[static_cast<Array::size_type>(lvl)]; +} +} + // Vivy::LogSinkDispatcher and child classes implementation namespace Vivy { LogSinkDispatcher::~LogSinkDispatcher() noexcept {} +const std::string_view +StderrLogSinkDispatcher::trunkFileName(const char *fileName) noexcept +{ + using size_type = std::string_view::size_type; + + static constexpr char basePrefix[] = "/src/"; + static constexpr size_type basePrefixLen = (sizeof(basePrefix) / sizeof(char)) - 1; + + const std::string_view fileNameView{ fileName }; + const size_type basePath = fileNameView.rfind(basePrefix); + return std::string_view{ fileNameView.data() + basePath + basePrefixLen, + fileNameView.data() + fileNameView.size() }; +} + StderrLogSinkDispatcher::StderrLogSinkDispatcher() noexcept : LogSinkDispatcher(std::string_view{ "stderr" }) { @@ -14,7 +38,10 @@ void StderrLogSinkDispatcher::handleLogMessage(const std::string_view category, const LogMessage &msg) noexcept { - std::cerr << '[' << category << "] " << msg.getTextBuffer() << '\n'; + std::cerr << "#(" << trunkFileName(msg.getHeader().fileName) << " +" + << msg.getHeader().lineNumberInFile << " | " + << LogLevel::toStdStringView(msg.getHeader().severity) << " -> " << category << ")\t" + << msg.getTextBuffer() << '\n'; } } @@ -59,6 +86,12 @@ LogSink::registerLogDispatcher(std::shared_ptr<LogSinkDispatcher> dispatcher) no { logDispatchers.push_back(dispatcher); } + +void +LogSink::registerLogger(std::shared_ptr<Logger> ptr) noexcept +{ + loggers.push_back(ptr); +} } // Vivy::Logger implementation @@ -72,7 +105,7 @@ Logger::sendLogMessage(LogMessage &&msg) const noexcept LogMessage Logger::logEvent(const char *fileName, const char *functionName, const int lineNumber, - const LogLevel logSeverity) noexcept + const LogLevel::Level logSeverity) noexcept { return LogMessage(this, LogMessage::Header{ .fileName = fileName, .functionName = functionName, @@ -111,12 +144,60 @@ LogMessage::operator<<(const std::string &msg) noexcept return (*this << msg.c_str()); } +LogMessage & +LogMessage::operator<<(const QVariant &variant) noexcept +{ + return (*this << variant.toString()); +} + LogMessage & LogMessage::operator<<(const QString &msg) noexcept { return (*this << msg.toStdString()); } +LogMessage & +LogMessage::operator<<(const QFileInfo &fileInfo) noexcept +{ + return (*this << "QFileInfo{ " << fileInfo.absoluteFilePath() << "}"); +} + +LogMessage & +LogMessage::operator<<(const double *ptr) noexcept +{ + return (*this << "Pointer{ double, " << pointerToString<double>(ptr) << " }"); +} + +LogMessage & +LogMessage::operator<<(const unsigned char c) noexcept +{ + return (*this << static_cast<char>(c)); +} + +LogMessage & +LogMessage::operator<<(const unsigned int i) noexcept +{ + return (*this << static_cast<unsigned long>(i)); +} + +LogMessage & +LogMessage::operator<<(const unsigned long i) noexcept +{ + return (*this << std::to_string(i)); +} + +LogMessage & +LogMessage::operator<<(const unsigned long long i) noexcept +{ + return (*this << std::to_string(i)); +} + +LogMessage & +LogMessage::operator<<(const long long i) noexcept +{ + return (*this << std::to_string(i)); +} + LogMessage & LogMessage::operator<<(const int i) noexcept { @@ -129,6 +210,17 @@ LogMessage::operator<<(const long i) noexcept return (*this << std::to_string(i)); } +LogMessage & +LogMessage::operator<<(const std::string_view strv) noexcept +{ + for (std::size_t i = 0; (i < strv.size()) && (indexInArray < messageBufferLength - 1); + ++i, ++indexInArray) { + textBuffer[indexInArray] = strv[i]; + } + textBuffer[indexInArray] = '\0'; + return *this; +} + LogMessage & LogMessage::operator<<(const char *str) noexcept { diff --git a/src/Lib/Log.hh b/src/Lib/Log.hh index 5b49381f4c705f2572730d535abe130544468b48..a14b53920c4bc3a08561a799106ffef144cc8c96 100644 --- a/src/Lib/Log.hh +++ b/src/Lib/Log.hh @@ -3,10 +3,10 @@ #include "Utils.hh" // Create a logger with a category -#define VIVY_GET_LOGGER(sink, cat) std::make_shared<Logger>((sink).get(), std::string_view{ #cat }) +#define VIVY_GET_LOGGER(sink, cat) (sink)->newLogger(std::string_view{ #cat }) // Log something in a logger -#define VIVY_LOG_WITH_LEVEL(log, level) log->logEvent(__FILE__, __func__, __LINE__, level) +#define VIVY_LOG_WITH_LEVEL(log, level) (log)->logEvent(__FILE__, __func__, __LINE__, level) #define VIVY_LOG_WARN(log) VIVY_LOG_WITH_LEVEL(log, Vivy::LogLevel::Warning) #define VIVY_LOG_DEBUG(log) VIVY_LOG_WITH_LEVEL(log, Vivy::LogLevel::Debug) #define VIVY_LOG_INFO(log) VIVY_LOG_WITH_LEVEL(log, Vivy::LogLevel::Info) @@ -17,15 +17,15 @@ // intended to be used in an object to not polluate namespaces. #define VIVY_DCL_LOG_SINK(sink) \ std::shared_ptr<LogSink> sink{ LogSink::newSink() }; \ - void flushLogSink() const noexcept { sink->flush(); } + void flushLogSink() const noexcept { (sink)->flush(); } // Declare a dispatch for a sink with no arguments in the constructor. #define VIVY_DCL_LOG_DISPATCH(sink, name, dispatch) \ - std::shared_ptr<dispatch> name{ sink->newDispatcher<dispatch>() }; + std::shared_ptr<dispatch> name{ (sink)->newDispatcher<dispatch>() }; // Declare a dispatch for a sink with arguments in the constructor. #define VIVY_DCL_LOG_DISPATCH_WITH(sink, name, dispatch, ...) \ - std::shared_ptr<dispatch> name{ sink->newDispatcher<dispatch>(__VA_ARGS__) }; + std::shared_ptr<dispatch> name{ (sink)->newDispatcher<dispatch>(__VA_ARGS__) }; // Install logger for the object. #define VIVY_LOGGABLE_OBJECT(sink, name, logger) \ @@ -36,8 +36,10 @@ LogMessage logInfo() const noexcept { return VIVY_LOG_INFO(logger); } \ LogMessage logDebug() const noexcept { return VIVY_LOG_DEBUG(logger); } -#define VIVY_LOG_CTOR(classname) logDebug() << #classname "::CTOR " -#define VIVY_LOG_DTOR(classname) logDebug() << #classname "::DTOR " +#define VIVY_LOG_CTOR() logDebug() << "<<CTOR>> " +#define VIVY_LOG_DTOR() logDebug() << "<<DTOR>> " + +#define VIVY_LOG_QUOTED(something) '\'' << (something) << '\'' // Install logger, use the global LogSink #define VIVY_APP_LOGGABLE_OBJECT(name, logger) \ @@ -52,13 +54,25 @@ class LogMessage; // The severity of an event. Critical will cause the LogSink to flush all // messages to its emeters and then abort. -enum class LogLevel : int { - Critical = std::numeric_limits<int>::max(), // Will trigger qFatal - Error = 4, - Warning = 3, - Info = 2, - Debug = 1, - None = std::numeric_limits<int>::min() // In option setup to disable logs +struct LogLevel final { + enum Level : int { + None, // In option setup to disable logs + Debug, + Info, + Warning, + Error, + Critical, // Will trigger qFatal + ___MaxAndUnused + }; + + static const std::string_view toStdStringView(const LogLevel::Level) noexcept; + +private: + using Array = std::array<const std::string_view, ___MaxAndUnused>; + static inline constexpr Array LevelsStringViews = { "None", "Debug", "Info", + "Warnin", "Error", "Critical" }; + + LogLevel() {} }; // A LogSinkDispatcher will excavate LogMessages from the Sink and do something @@ -85,6 +99,8 @@ public: class StderrLogSinkDispatcher : public LogSinkDispatcher { VIVY_UNMOVABLE_OBJECT(StderrLogSinkDispatcher) + static const std::string_view trunkFileName(const char *) noexcept; + public: explicit StderrLogSinkDispatcher() noexcept; void handleLogMessage(const std::string_view, const LogMessage &) noexcept override; @@ -103,6 +119,7 @@ public: ~LogSink() noexcept; void registerLogDispatcher(std::shared_ptr<LogSinkDispatcher>) noexcept; + void registerLogger(std::shared_ptr<Logger>) noexcept; void recieveLogMessage(const Logger *const, LogMessage &&) noexcept; void flush() noexcept; @@ -115,10 +132,18 @@ public: return dispatch; } + std::shared_ptr<Logger> newLogger(const StringType auto &category) noexcept + { + std::shared_ptr<Logger> logger = std::make_shared<Logger>(this, category); + registerLogger(logger); + return logger; + } + private: std::mutex messageQueueLock{}; std::vector<std::tuple<const std::string_view, LogMessage>> messageQueue; std::vector<std::shared_ptr<LogSinkDispatcher>> logDispatchers; + std::vector<std::shared_ptr<Logger>> loggers; }; // Message to be logged, constructed by a logger then send @@ -130,7 +155,7 @@ public: struct Header final { const char *fileName; const char *functionName; - const LogLevel severity; + const LogLevel::Level severity; const int lineNumberInFile; }; @@ -144,6 +169,14 @@ private: std::size_t indexInArray{ 0 }; const Logger *parentLogger{ nullptr }; + static std::string pointerToString(const auto *ptr) noexcept + { + std::stringstream stream; + stream << "0x" << std::setfill('0') << std::setw(sizeof(std::intptr_t) * 2) << std::hex + << reinterpret_cast<const std::intptr_t>(ptr); + return stream.str(); + } + public: VIVY_DISABLE_COPY_CTOR(LogMessage) VIVY_DISABLE_ASSIGN_OPERATORS(LogMessage) @@ -159,11 +192,20 @@ public: LogMessage &&sink() noexcept; LogMessage &operator<<(const std::string &) noexcept; + LogMessage &operator<<(const std::string_view) noexcept; LogMessage &operator<<(const QString &) noexcept; + LogMessage &operator<<(const QVariant &) noexcept; + LogMessage &operator<<(const QFileInfo &) noexcept; LogMessage &operator<<(const char *) noexcept; + LogMessage &operator<<(const double *) noexcept; LogMessage &operator<<(const char) noexcept; LogMessage &operator<<(const int) noexcept; LogMessage &operator<<(const long) noexcept; + LogMessage &operator<<(const long long) noexcept; + LogMessage &operator<<(const unsigned char) noexcept; + LogMessage &operator<<(const unsigned int) noexcept; + LogMessage &operator<<(const unsigned long) noexcept; + LogMessage &operator<<(const unsigned long long) noexcept; }; // A logger class, a client to LogSink. Will generate and send instances of @@ -187,6 +229,6 @@ public: void sendLogMessage(LogMessage &&) const noexcept; LogMessage logEvent(const char *fileName, const char *functionName, const int lineNumber, - const LogLevel) noexcept; + const LogLevel::Level) noexcept; }; } diff --git a/src/Lib/Uuid.cc b/src/Lib/Uuid.cc new file mode 100644 index 0000000000000000000000000000000000000000..7062680471fe5fa08e2aeb965807eac2b0dabd52 --- /dev/null +++ b/src/Lib/Uuid.cc @@ -0,0 +1,13 @@ +#include "Uuid.hh" +#include "Log.hh" + +Vivy::Uuid::Uuid() + : QUuid(QUuid::createUuid()) +{ +} + +Vivy::LogMessage & +Vivy::operator<<(Vivy::LogMessage &msg, Vivy::Uuid uuid) noexcept +{ + return msg << "UUID{ " << uuid.toString() << " }"; +} diff --git a/src/Lib/Uuid.hh b/src/Lib/Uuid.hh index 068277deeac9f8b33673fa2243a0c5e30e9c2223..083e001f7192acd29c20d6ee447ebd68b8fcb8f6 100644 --- a/src/Lib/Uuid.hh +++ b/src/Lib/Uuid.hh @@ -2,13 +2,11 @@ namespace Vivy { -class Uuid : public QUuid { -public: - explicit Uuid() - : QUuid(QUuid::createUuid()) - { - } - +struct Uuid : QUuid { + explicit Uuid(); QString toString() const noexcept { return QUuid::toString(Uuid::WithoutBraces); } }; + +class LogMessage; +LogMessage &operator<<(LogMessage &, Uuid) noexcept; } diff --git a/src/UI/AboutWindow.cc b/src/UI/AboutWindow.cc index 432c7fbf5b39c68138e08dfb33f8927534790dcb..5995a016b80a60fdd7cdb9ec9c708b36da4ce264 100644 --- a/src/UI/AboutWindow.cc +++ b/src/UI/AboutWindow.cc @@ -55,7 +55,7 @@ AboutWindow::LicenceLabel::LicenceLabel(QWidget *parent, const QString &url, const Qt::TextFormat format) : QTextEdit(parent) { - VIVY_LOG_CTOR() << "Creating label for licence '" << url << '\''; + VIVY_LOG_CTOR() << "Creating label for licence " << VIVY_LOG_QUOTED(url); QFile content(url); if (!content.open(QIODevice::ReadOnly | QIODevice::Text)) throw std::runtime_error("Failed to open file that should be accessible"); diff --git a/src/UI/DockWidgetTitleBar.cc b/src/UI/DockWidgetTitleBar.cc index 2e1cdaa099d9246e785e46919a317dd51cbb6785..46bc79c28f393361aef522ff04c94fee9394b6bf 100644 --- a/src/UI/DockWidgetTitleBar.cc +++ b/src/UI/DockWidgetTitleBar.cc @@ -7,18 +7,20 @@ DockWidgetTitleBar::DockWidgetTitleBar(QDockWidget *parent) noexcept , attachedDock(parent) { if (parent == nullptr) - qFatal("Can't pass a nullptr as a parent widget pointer"); + logFatal() << "Can't pass a nullptr as a parent widget pointer"; - auto *box = new QHBoxLayout(this); - box->addWidget(new QLabel(parent->windowTitle(), this)); + const QString name = parent->windowTitle(); + auto *const box = new QHBoxLayout(this); + box->addWidget(new QLabel(name, this)); qobject_cast<QHBoxLayout *>(layout())->setStretch(0, 1); + VIVY_LOG_CTOR() << "TitleBar added to dock " << VIVY_LOG_QUOTED(name); } void DockWidgetTitleBar::addToDock(QDockWidget *const dock) noexcept { DockWidgetTitleBar *const titleBar = new DockWidgetTitleBar(dock); - qDebug() << "Adding" << dock->windowTitle() << "to dock..."; + titleBar->logDebug() << "Adding " << VIVY_LOG_QUOTED(dock->windowTitle()) << " to dock..."; Utils::setTransparentBackgroundForWidget(titleBar); dock->setTitleBarWidget(titleBar); } diff --git a/src/UI/DockWidgetTitleBar.hh b/src/UI/DockWidgetTitleBar.hh index 620c9a947e3537b566ee45a69be521cf63b97005..f3eace6b0c63d4194878a6a9dc23b5cf6f041034 100644 --- a/src/UI/DockWidgetTitleBar.hh +++ b/src/UI/DockWidgetTitleBar.hh @@ -1,5 +1,7 @@ #pragma once +#include "../VivyApplication.hh" +#include "../Lib/Log.hh" #include "Utils.hh" namespace Vivy @@ -7,6 +9,7 @@ namespace Vivy class DockWidgetTitleBar final : public QWidget { Q_OBJECT VIVY_UNMOVABLE_OBJECT(DockWidgetTitleBar) + VIVY_APP_LOGGABLE_OBJECT(DockWidgetTitleBar, logger) QDockWidget *attachedDock{ nullptr }; explicit DockWidgetTitleBar(QDockWidget *parent) noexcept; diff --git a/src/UI/MainWindow.cc b/src/UI/MainWindow.cc index bfff0df4d0880b608db699d7a205fc782f19208e..0130076f5a9ea93237f18d6aa2273ae8310cca3c 100644 --- a/src/UI/MainWindow.cc +++ b/src/UI/MainWindow.cc @@ -1,3 +1,5 @@ +#include "../Lib/Document/VivyDocumentStore.hh" +#include "../Lib/Script/ScriptStore.hh" #include "../Lib/Utils.hh" #include "../VivyApplication.hh" #include "MainWindow.hh" @@ -164,7 +166,7 @@ MainWindow::MainWindow() noexcept void MainWindow::closeEvent(QCloseEvent *event) noexcept { - qDebug() << "Closing the main window!"; + logDebug() << "Closing the main window!"; forEachViews<VivyDocumentView>([](VivyDocumentView *view, int) { view->closeDocument(); }); QMainWindow::closeEvent(event); } @@ -191,7 +193,7 @@ MainWindow::openProperties(int index) noexcept return; } - qDebug().nospace() << "Tab n°" << index << " was double clicked"; + logDebug() << "Tab n°" << index << " was double clicked"; AbstractDocumentView *current = getTab(index); current->openProperties(); } @@ -226,7 +228,7 @@ MainWindow::saveFile() noexcept } catch (const std::runtime_error &e) { - qCritical() << "Failed to save current document:" << e.what(); + logError() << "Failed to save current document: " << e.what(); } } @@ -248,7 +250,7 @@ MainWindow::renameFile() noexcept } catch (const std::runtime_error &e) { - qCritical() << "Failed to save current document:" << e.what(); + logError() << "Failed to save current document: " << e.what(); } } @@ -270,7 +272,7 @@ MainWindow::saveFileAs() noexcept } catch (const std::runtime_error &e) { - qCritical() << "Failed to save current document:" << e.what(); + logError() << "Failed to save current document: " << e.what(); } } @@ -300,7 +302,8 @@ MainWindow::closeDocument(int index) noexcept &MainWindow::documentViewActionsChanged); if (documentToClose) { - qDebug() << "Delete document view" << documentToClose->getDocumentTabName(); + logDebug() + << "Delete document view " << VIVY_LOG_QUOTED(documentToClose->getDocumentTabName()); documentToClose->closeDocument(); delete documentToClose; } @@ -311,9 +314,9 @@ MainWindow::newDocument() noexcept { try { addTab(new VivyDocumentView( - vivyApp->documentStore.newDocument(VivyDocument::UntouchedByDefault), documents)); + vivyApp->documentStore->newDocument(VivyDocument::UntouchedByDefault), documents)); } catch (const std::runtime_error &e) { - qCritical() << "Failed to create a new empty document:" << e.what(); + logError() << "Failed to create a new empty document: " << e.what(); } } @@ -323,7 +326,7 @@ MainWindow::openDocument() noexcept const QString filename = dialogOpenFileName("Select a document to open", QDir::homePath(), Utils::getAnyTopLevelDocumentFileSuffixFilter()); if (filename.isEmpty()) { - qWarning() << "Found an empty filename, don't open a file"; + logDebug() << "Found an empty filename, don't open a file"; return; } @@ -331,18 +334,18 @@ MainWindow::openDocument() noexcept Utils::DocumentType fileType; if (!Utils::detectDocumentType(fileInfo, &fileType)) { - qWarning() << "Failed to detect file type for" << filename; + logWarning() << "Failed to detect file type for " << VIVY_LOG_QUOTED(filename); return; } // Handle the different types here try { if (fileType == Utils::DocumentType::Vivy) - addTab(new VivyDocumentView(vivyApp->documentStore.loadDocument(filename), documents)); + addTab(new VivyDocumentView(vivyApp->documentStore->loadDocument(filename), documents)); else if (fileType == Utils::DocumentType::VivyScript) { - auto scriptDocument = vivyApp->scriptStore.loadDocument(filename); - auto errorTuple = vivyApp->scriptStore.executeScript(scriptDocument->getUuid()); + auto scriptDocument = vivyApp->scriptStore->loadDocument(filename); + auto errorTuple = vivyApp->scriptStore->executeScript(scriptDocument->getUuid()); ScriptDocumentView *newView = new ScriptDocumentView(scriptDocument, documents); if (errorTuple.has_value()) { @@ -353,7 +356,8 @@ MainWindow::openDocument() noexcept addTab(newView); } } catch (const std::runtime_error &e) { - qCritical() << "Failed to load document" << filename << "with error:" << e.what(); + logError() << "Failed to load document " << VIVY_LOG_QUOTED(filename) + << " with error: " << e.what(); } } @@ -420,7 +424,7 @@ MainWindow::addTab(AbstractDocumentView *const tab) } }); documentViewActionsChanged(); - qDebug() << "View constructed successfully"; + logDebug() << "View constructed successfully"; } int @@ -487,19 +491,19 @@ MainWindow::findFirstUntouchedDocument() const noexcept void MainWindow::documentViewActionsChanged() noexcept { - qInfo() << "Document view action changed"; + logDebug() << "Document view action changed"; viewMenu->clear(); // Change document view menu if we have a document try { viewMenu->addActions(getCurrentDocumentView()->getViewsActions()); } catch (const std::runtime_error &e) { - qInfo() << "No view to display:" << e.what(); + logDebug() << "No view to display: " << e.what(); } } -static inline QString -executeDialog(MainWindow *const self, QFileDialog *const dialog) noexcept +QString +MainWindow::executeDialog(MainWindow *const self, QFileDialog *const dialog) noexcept { bool dialogAccepted = false; std::unique_ptr<VivyFileIconProvider> iconProvider(new VivyFileIconProvider()); @@ -515,7 +519,8 @@ executeDialog(MainWindow *const self, QFileDialog *const dialog) noexcept const QStringList resList = dialog->selectedFiles(); if (resList.size() != 1) { - qCritical() << "You must select only one file"; + self->logError() + << "You must select only one file, here got " << resList.size() << " files"; return QStringLiteral(""); } diff --git a/src/UI/MainWindow.hh b/src/UI/MainWindow.hh index 5389ab56ad3d5d139b3a5a8932cbc203dba20a37..30a31af108f94ceb43ce3dc34aa06f905ab33c91 100644 --- a/src/UI/MainWindow.hh +++ b/src/UI/MainWindow.hh @@ -4,7 +4,9 @@ #error "This is a C++ header" #endif +#include "../VivyApplication.hh" #include "../Lib/Utils.hh" +#include "../Lib/Log.hh" #include "../Lib/AbstractDocument.hh" #include "../Lib/Document/VivyDocumentStore.hh" #include "DocumentViews/AudioVisualizer.hh" @@ -17,6 +19,7 @@ class AboutWindow; class MainWindow final : public QMainWindow { Q_OBJECT + VIVY_APP_LOGGABLE_OBJECT(MainWindow, logger) QTabWidget *documents{ nullptr }; QMenu *viewMenu{ nullptr }; @@ -54,6 +57,8 @@ private: QString dialogSaveFileName(const QString &title, const QString &folder, const QString &filter) noexcept; + QString executeDialog(MainWindow *const self, QFileDialog *const dialog) noexcept; + // Do an action with the selected filename. The 'call' variable must be // callable like this: call(DocumentView, Document, QString) template <typename DV, typename D> @@ -62,7 +67,7 @@ private: const QString filename = dialogOpenFileName(title, QDir::homePath(), filter); if (filename.isEmpty()) { - qWarning() << "Found an empty filename, don't open a file"; + logWarning() << "Found an empty filename, don't open a file"; return; } @@ -74,7 +79,7 @@ private: call(view, doc, filename); } } catch (const std::runtime_error &e) { - qCritical() << "Operation failed with:" << e.what(); + logError() << "Operation failed with: " << e.what(); } } diff --git a/src/UI/ScriptDocumentView.cc b/src/UI/ScriptDocumentView.cc index 4adf39bc4438575573641438e57dc58483ac7cb1..1f510c7c4f48db6686035121bd5229f4db3a34e1 100644 --- a/src/UI/ScriptDocumentView.cc +++ b/src/UI/ScriptDocumentView.cc @@ -33,12 +33,15 @@ ScriptDocumentView::ScriptDocumentView(std::shared_ptr<ScriptDocument> ptr, QWid " font-family: \"FiraCode\";" " font-size: 10pt" "}")); + + VIVY_LOG_CTOR() << "Creating view for script " << VIVY_LOG_QUOTED(ptr->getName()) << " with " + << ptr->getUuid(); } ScriptDocumentView::~ScriptDocumentView() { setUseFakeVimEditor(false); - qDebug() << "~ScriptDocumentView"; + VIVY_LOG_DTOR() << "Closing a script view"; } void diff --git a/src/UI/ScriptDocumentView.hh b/src/UI/ScriptDocumentView.hh index c1acc9c31524571e2b7eedf0703991a12296b8fe..26c240cd81fef4ae759a655f4768de49c7344600 100644 --- a/src/UI/ScriptDocumentView.hh +++ b/src/UI/ScriptDocumentView.hh @@ -5,7 +5,9 @@ #error "This is a C++ header" #endif +#include "../VivyApplication.hh" #include "../Lib/Utils.hh" +#include "../Lib/Log.hh" #include "../Lib/Script/ScriptDocument.hh" #include "AbstractDocumentView.hh" #include "FakeVim/FakeVimHandler.hh" @@ -18,6 +20,7 @@ namespace Vivy class ScriptDocumentView final : public AbstractDocumentView { Q_OBJECT VIVY_UNMOVABLE_OBJECT(ScriptDocumentView) + VIVY_APP_LOGGABLE_OBJECT(ScriptDocumentView, logger) using FakeVimHandler = FakeVim::Internal::FakeVimHandler; diff --git a/src/UI/ScriptViews/EditorProxy.cc b/src/UI/ScriptViews/EditorProxy.cc index 1664c5adc72c09be58d54603a3385256c86d7a35..6cf6616d753a4b83465f814655869eed4ac84257 100644 --- a/src/UI/ScriptViews/EditorProxy.cc +++ b/src/UI/ScriptViews/EditorProxy.cc @@ -11,11 +11,10 @@ EditorProxy::connectSignals(FakeVimHandler *handler, QPlainTextEdit *editor) noe { EditorProxy *proxy = new EditorProxy(editor); - handler->commandBufferChanged.connect([proxy](const QString &contents, int cursorPos, - int /* anchorPos */, - int /* messageLevel */) noexcept -> void { - proxy->changeStatusMessage(contents, cursorPos); - }); + handler->commandBufferChanged.connect( + [proxy](const QString &contents, int cursorPos, int, int) noexcept -> void { + proxy->changeStatusMessage(contents, cursorPos); + }); handler->extraInformationChanged.connect( [proxy](const QString &text) noexcept -> void { proxy->changeExtraInformation(text); }); @@ -50,9 +49,11 @@ EditorProxy::EditorProxy(QPlainTextEdit *widg) noexcept : QObject() , widget(widg) { + VIVY_LOG_CTOR() + << "Creating new proxy for a the text view " << VIVY_LOG_QUOTED(widg->windowFilePath()); } -EditorProxy::~EditorProxy() { qDebug() << "~EditorProxy"; } +EditorProxy::~EditorProxy() { VIVY_LOG_DTOR() << "Delete editor proxy!"; } void EditorProxy::changeStatusData(const QString &info) noexcept @@ -136,12 +137,16 @@ EditorProxy::handleExCommand(bool *handled, const ExCommand &cmd) noexcept else if (wantQuit(cmd)) { // :q! - if (cmd.hasBang) + if (cmd.hasBang) { + logInfo() << "Want to force quit the editor!"; emit requestQuit(); + } // :q - else + else { + logInfo() << "Want to quit the editor"; emit requestQuit(); + } } else if (wantRun(cmd)) @@ -306,17 +311,20 @@ EditorProxy::wantSaveAndQuit(const ExCommand &cmd) noexcept bool EditorProxy::wantSave(const ExCommand &cmd) noexcept { + logInfo() << "Want to save the editor's file"; return cmd.matches("w", "write") || cmd.matches("wa", "wall"); } bool EditorProxy::wantQuit(const ExCommand &cmd) noexcept { + logInfo() << "Want to quit editor"; return cmd.matches("q", "quit") || cmd.matches("qa", "qall"); } bool EditorProxy::wantRun(const ExCommand &cmd) noexcept { + logInfo() << "Want to run a command: " << cmd.cmd; return cmd.matches("run", "run") || cmd.matches("make", "make"); } diff --git a/src/UI/ScriptViews/EditorProxy.hh b/src/UI/ScriptViews/EditorProxy.hh index c93a3823f753320f5521b446ddcb309bc5090d39..2abd88669c29c261cb55c3ed267a1c65370b1348 100644 --- a/src/UI/ScriptViews/EditorProxy.hh +++ b/src/UI/ScriptViews/EditorProxy.hh @@ -1,13 +1,9 @@ #pragma once +#include "../../VivyApplication.hh" +#include "../../Lib/Log.hh" #include "ScriptEditor.hh" -class QMainWindow; -class QTextDocument; -class QString; -class QWidget; -class QTextCursor; - namespace FakeVim::Internal { class FakeVimHandler; @@ -21,6 +17,7 @@ class EditorProxy; class EditorProxy final : public QObject { Q_OBJECT VIVY_UNMOVABLE_OBJECT(EditorProxy) + VIVY_APP_LOGGABLE_OBJECT(EditorProxy, logger) explicit EditorProxy(QPlainTextEdit *widget) noexcept; using FakeVimHandler = FakeVim::Internal::FakeVimHandler; diff --git a/src/UI/ScriptViews/ScriptEditor.cc b/src/UI/ScriptViews/ScriptEditor.cc index 80b88fcfdfaaa8bf24a6107c32b5413f92661bcd..4ba88645d892ba1848dd9e7d113b135b46a6d820 100644 --- a/src/UI/ScriptViews/ScriptEditor.cc +++ b/src/UI/ScriptViews/ScriptEditor.cc @@ -168,5 +168,5 @@ ScriptEditor::lineNumberAreaPaintEvent(QPaintEvent *event) noexcept void ScriptEditor::updateLastLuaError(int line, QString desc) { - qDebug() << "Update error on line" << line << "with description" << desc; + logDebug() << "Update error on line " << line << " with description " << desc; } diff --git a/src/UI/ScriptViews/ScriptEditor.hh b/src/UI/ScriptViews/ScriptEditor.hh index 5a68ef9c71bdd6afe31211179ae7c28dbeed5c8c..1a2391cf6a40495859c0be0eedf6ddb5dd1b58a6 100644 --- a/src/UI/ScriptViews/ScriptEditor.hh +++ b/src/UI/ScriptViews/ScriptEditor.hh @@ -4,6 +4,8 @@ #error "This is a C++ header" #endif +#include "../../VivyApplication.hh" +#include "../../Lib/Log.hh" #include "../../Lib/Utils.hh" namespace Vivy @@ -11,6 +13,7 @@ namespace Vivy class ScriptEditor final : public QPlainTextEdit { Q_OBJECT VIVY_UNMOVABLE_OBJECT(ScriptEditor) + VIVY_APP_LOGGABLE_OBJECT(ScriptEditor, logger) // Get the line numbers, private class class LineNumberArea final : public QWidget { diff --git a/src/UI/VivyDocumentView.cc b/src/UI/VivyDocumentView.cc index be7437916ed688742d5beeb24454295e5ea124b2..86e155afd60eac27964e0f270e8dba6f6d8ff4f8 100644 --- a/src/UI/VivyDocumentView.cc +++ b/src/UI/VivyDocumentView.cc @@ -6,6 +6,7 @@ #include "DocumentViews/AssLinesModel.hh" #include "../VivyApplication.hh" #include "../Lib/Document/VivyDocument.hh" +#include "../Lib/Document/VivyDocumentStore.hh" using namespace Vivy; @@ -13,6 +14,9 @@ VivyDocumentView::VivyDocumentView(std::shared_ptr<VivyDocument> doc, QWidget *p : AbstractDocumentView(AbstractDocumentView::Type::Vivy, parent) , document(doc) { + VIVY_LOG_CTOR() << "Creating view for vivy document " << VIVY_LOG_QUOTED(doc->getName()) + << " with " << doc->getUuid() << "..."; + setDockNestingEnabled(true); loadAudioView(); @@ -30,17 +34,17 @@ VivyDocumentView::VivyDocumentView(std::shared_ptr<VivyDocument> doc, QWidget *p viewsActions.append(openPropertiesAct); // The separator - QAction *separator = new QAction(this); + QAction *const separator = new QAction(this); separator->setSeparator(true); viewsActions.append(separator); + + VIVY_LOG_CTOR() << "View for " << doc->getUuid() << " done!"; } VivyDocumentView::~VivyDocumentView() noexcept { - qDebug() - << "Deleting the document view: ref count on document" << document->getName() << "is" - << document.use_count() << "and" << (visualizer ? "has visualizer" : "without visualizer"); - + VIVY_LOG_DTOR() << "Deleting view for " << document->getUuid() << ", file name is " + << VIVY_LOG_QUOTED(document->getName()); deleteAllContent(); } @@ -121,7 +125,7 @@ VivyDocumentView::loadAudioView() noexcept AudioContext::StreamPtr stream = audioDocument->getDefaultStream(); if (stream == nullptr) { - qCritical() << "Failed to get default audio stream"; + logError() << "Failed to get default audio stream"; return; } @@ -145,9 +149,8 @@ VivyDocumentView::loadAudioView() noexcept void VivyDocumentView::closeDocument() noexcept { - qDebug() << "Closing the document:" << document->getName() << "( ref count is" - << document.use_count() << ")"; - vivyApp->documentStore.closeDocument(document->getUuid()); + logDebug() << "Closing document " << document->getUuid(); + vivyApp->documentStore->closeDocument(document->getUuid()); allowToCloseAllDocks(); } diff --git a/src/UI/VivyDocumentView.hh b/src/UI/VivyDocumentView.hh index 0a6f13b4519362f6468632348a854051a44e4b64..a17d1c34c8a0cdbb61d9ae12807d10a96c383266 100644 --- a/src/UI/VivyDocumentView.hh +++ b/src/UI/VivyDocumentView.hh @@ -1,23 +1,25 @@ -#ifndef VIVY_DOCUMENTVIEW_H -#define VIVY_DOCUMENTVIEW_H +#pragma once #ifndef __cplusplus #error "This is a C++ header" #endif -#include "AbstractDocumentView.hh" +#include "../VivyApplication.hh" +#include "../Lib/Log.hh" #include "../Lib/Document/VivyDocument.hh" +#include "PropertyModel.hh" +#include "UnclosableDockWidget.hh" +#include "AbstractDocumentView.hh" #include "DocumentViews/VideoView.hh" #include "DocumentViews/AssLinesView.hh" #include "DocumentViews/AssLinesModel.hh" -#include "PropertyModel.hh" -#include "UnclosableDockWidget.hh" namespace Vivy { class VivyDocumentView final : public AbstractDocumentView { Q_OBJECT VIVY_UNMOVABLE_OBJECT(VivyDocumentView) + VIVY_APP_LOGGABLE_OBJECT(VivyDocumentView, logger) static inline constexpr QDockWidget::DockWidgetFeatures allDockFeatures = QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | @@ -53,7 +55,4 @@ private: UnclosableDockWidget *videoView{ nullptr }; QAction *openPropertiesAct{ nullptr }; }; - } - -#endif // VIVY_DOCUMENTVIEW_H diff --git a/src/VivyApplication.cc b/src/VivyApplication.cc index b6df260b646972708049f4ee0b98929c86516988..959fb498ee963830c45e371846a392004d9f194d 100644 --- a/src/VivyApplication.cc +++ b/src/VivyApplication.cc @@ -6,7 +6,7 @@ using namespace Vivy; VivyApplication::VivyApplication(int &argc, char **argv) : QApplication(argc, argv) { - VIVY_LOG_CTOR(VivyApplication) << "Construction is OK"; + VIVY_LOG_CTOR() << "Construction is OK"; } void @@ -27,7 +27,7 @@ VivyApplication::setTheme(Theme theme) noexcept stylesheet.open(QFile::ReadOnly | QFile::Text); QTextStream stylesheetStream(&stylesheet); setStyleSheet(stylesheetStream.readAll()); - logInfo() << "Theme set using " << sheet; + logInfo() << "Theme set using " << VIVY_LOG_QUOTED(sheet); } flushLogSink(); diff --git a/src/VivyApplication.hh b/src/VivyApplication.hh index 85e715d85209eb49388a21ec2aa102a3bcf56288..4a9985a35c48c5ed41d87f2dc2087f74f5ef7840 100644 --- a/src/VivyApplication.hh +++ b/src/VivyApplication.hh @@ -29,13 +29,14 @@ #define VIVY_MACOS #endif -#include "Lib/Script/ScriptStore.hh" -#include "Lib/Document/VivyDocumentStore.hh" #include "Lib/Log.hh" namespace Vivy { class MainWindow; +class ScriptStore; +class VivyDocumentStore; +class AbstractDocument; // Vivy application class class VivyApplication : public QApplication { @@ -45,8 +46,8 @@ class VivyApplication : public QApplication { VIVY_LOGGABLE_OBJECT(logSink, APPLICATION, logger) public: - VivyDocumentStore documentStore{}; - ScriptStore scriptStore{}; + std::shared_ptr<VivyDocumentStore> documentStore{}; + std::shared_ptr<ScriptStore> scriptStore{}; enum class Font { Monospace,