From fc198dd3085a2cd33fbaa7a3d2c95c2c8d3ee31a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 8 Aug 2016 00:00:11 +0200 Subject: NOISSUE rework of minecraft log Now uses a model and a list view instead of text This lets mmc keep track of the contents regardless of whether the instance windows are open This is currently missing a way to select and copy text from the log. --- api/logic/CMakeLists.txt | 2 + api/logic/launch/LaunchTask.cpp | 12 +++- api/logic/launch/LaunchTask.h | 12 ++-- api/logic/launch/LogModel.cpp | 135 ++++++++++++++++++++++++++++++++++++++++ api/logic/launch/LogModel.h | 51 +++++++++++++++ 5 files changed, 204 insertions(+), 8 deletions(-) create mode 100644 api/logic/launch/LogModel.cpp create mode 100644 api/logic/launch/LogModel.h (limited to 'api/logic') diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt index 4514d8c3..8a1f2f41 100644 --- a/api/logic/CMakeLists.txt +++ b/api/logic/CMakeLists.txt @@ -119,6 +119,8 @@ set(LAUNCH_SOURCES launch/LaunchTask.h launch/LoggedProcess.cpp launch/LoggedProcess.h + launch/LogModel.cpp + launch/LogModel.h launch/MessageLevel.cpp launch/MessageLevel.h ) diff --git a/api/logic/launch/LaunchTask.cpp b/api/logic/launch/LaunchTask.cpp index 5b7ff182..9c09caf4 100644 --- a/api/logic/launch/LaunchTask.cpp +++ b/api/logic/launch/LaunchTask.cpp @@ -167,6 +167,15 @@ bool LaunchTask::abort() return false; } +shared_qobject_ptr LaunchTask::getLogModel() +{ + if(!m_logModel) + { + m_logModel.reset(new LogModel()); + } + return m_logModel; +} + void LaunchTask::onLogLines(const QStringList &lines, MessageLevel::Enum defaultLevel) { for (auto & line: lines) @@ -193,7 +202,8 @@ void LaunchTask::onLogLine(QString line, MessageLevel::Enum level) // censor private user info line = censorPrivateInfo(line); - emit log(line, level); + auto &model = *getLogModel(); + model.append(level, line); } void LaunchTask::emitSucceeded() diff --git a/api/logic/launch/LaunchTask.h b/api/logic/launch/LaunchTask.h index 447445ca..f2fb3a2c 100644 --- a/api/logic/launch/LaunchTask.h +++ b/api/logic/launch/LaunchTask.h @@ -17,6 +17,8 @@ #pragma once #include +#include +#include "LogModel.h" #include "BaseInstance.h" #include "MessageLevel.h" #include "LoggedProcess.h" @@ -80,6 +82,8 @@ public: /* methods */ */ virtual bool abort() override; + shared_qobject_ptr getLogModel(); + public: QString substituteVariables(const QString &cmd) const; QString censorPrivateInfo(QString in); @@ -98,13 +102,6 @@ signals: void requestLogging(); - /** - * @brief emitted when we want to log something - * @param text the text to log - * @param level the level to log at - */ - void log(QString text, MessageLevel::Enum level = MessageLevel::MultiMC); - public slots: void onLogLines(const QStringList& lines, MessageLevel::Enum defaultLevel = MessageLevel::MultiMC); void onLogLine(QString line, MessageLevel::Enum defaultLevel = MessageLevel::MultiMC); @@ -114,6 +111,7 @@ public slots: protected: /* data */ InstancePtr m_instance; + shared_qobject_ptr m_logModel; QList > m_steps; QMap m_censorFilter; int currentStep = -1; diff --git a/api/logic/launch/LogModel.cpp b/api/logic/launch/LogModel.cpp new file mode 100644 index 00000000..c12a0488 --- /dev/null +++ b/api/logic/launch/LogModel.cpp @@ -0,0 +1,135 @@ +#include "LogModel.h" + +LogModel::LogModel(QObject *parent):QAbstractListModel(parent) +{ + m_content.resize(m_maxLines); +} + +int LogModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + + return m_numLines; +} + +QVariant LogModel::data(const QModelIndex &index, int role) const +{ + if (index.row() < 0 || index.row() >= m_numLines) + return QVariant(); + + auto row = index.row(); + auto realRow = (row + m_firstLine) % m_maxLines; + if (role == Qt::DisplayRole || role == Qt::EditRole) + { + return m_content[realRow].line; + } + if(role == LevelRole) + { + return m_content[realRow].level; + } + + return QVariant(); +} + +void LogModel::append(MessageLevel::Enum level, QString line) +{ + int lineNum = (m_firstLine + m_numLines) % m_maxLines; + // overflow + if(m_numLines == m_maxLines) + { + if(m_stopOnOverflow) + { + // nothing more to do, the buffer is full + return; + } + beginRemoveRows(QModelIndex(), 0, 0); + m_firstLine = (m_firstLine + 1) % m_maxLines; + m_numLines --; + endRemoveRows(); + } + else if (m_numLines == m_maxLines - 1 && m_stopOnOverflow) + { + level = MessageLevel::Fatal; + line = m_overflowMessage; + } + beginInsertRows(QModelIndex(), m_numLines, m_numLines); + m_numLines ++; + m_content[lineNum].level = level; + m_content[lineNum].line = line; + endInsertRows(); +} + +void LogModel::clear() +{ + beginResetModel(); + m_firstLine = 0; + m_numLines = 0; + endResetModel(); +} + +QString LogModel::toPlainText() +{ + QString out; + out.reserve(m_numLines * 80); + for(int i = 0; i < m_numLines; i++) + { + QString & line = m_content[(m_firstLine + i) % m_maxLines].line; + out.append(line + '\n'); + } + out.squeeze(); + return out; +} + +void LogModel::setMaxLines(int maxLines) +{ + // no-op + if(maxLines == m_maxLines) + { + return; + } + // if it all still fits in the buffer, just resize it + if(m_firstLine + m_numLines < maxLines) + { + m_maxLines = maxLines; + m_content.resize(maxLines); + return; + } + // otherwise, we need to reorganize the data because it crosses the wrap boundary + QVector newContent; + newContent.resize(maxLines); + if(m_numLines <= maxLines) + { + // if it all fits in the new buffer, just copy it over + for(int i = 0; i < m_numLines; i++) + { + newContent[i] = m_content[(m_firstLine + i) % m_maxLines]; + } + m_content.swap(newContent); + } + else + { + // if it doesn't fit, part of the data needs to be thrown away (the oldest log messages) + int lead = m_numLines - maxLines; + beginRemoveRows(QModelIndex(), 0, lead - 1); + for(int i = 0; i < maxLines; i++) + { + newContent[i] = m_content[(m_firstLine + lead + i) % m_maxLines]; + } + m_numLines = m_maxLines; + m_content.swap(newContent); + endRemoveRows(); + } + m_firstLine = 0; + m_maxLines = maxLines; +} + +void LogModel::setStopOnOverflow(bool stop) +{ + m_stopOnOverflow = stop; +} + +void LogModel::setOverflowMessage(const QString& overflowMessage) +{ + m_overflowMessage = overflowMessage; +} diff --git a/api/logic/launch/LogModel.h b/api/logic/launch/LogModel.h new file mode 100644 index 00000000..87e6b583 --- /dev/null +++ b/api/logic/launch/LogModel.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include "MessageLevel.h" + +#include + +class MULTIMC_LOGIC_EXPORT LogModel : public QAbstractListModel +{ + Q_OBJECT +public: + explicit LogModel(QObject *parent = 0); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role) const; + + void append(MessageLevel::Enum, QString line); + void clear(); + + QString toPlainText(); + + void setMaxLines(int maxLines); + void setStopOnOverflow(bool stop); + void setOverflowMessage(const QString & overflowMessage); + + enum Roles + { + LevelRole = Qt::UserRole + }; + +private /* types */: + struct entry + { + MessageLevel::Enum level; + QString line; + }; + +private: /* data */ + QVector m_content; + int m_maxLines = 1000; + // first line in the circular buffer + int m_firstLine = 0; + // number of lines occupied in the circular buffer + int m_numLines = 0; + bool m_stopOnOverflow = false; + QString m_overflowMessage = "OVERFLOW"; + +private: + Q_DISABLE_COPY(LogModel) +}; -- cgit v1.2.3