summaryrefslogtreecommitdiffstats
path: root/api/logic
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2016-08-18 21:31:37 +0200
committerPetr Mrázek <peterix@gmail.com>2016-08-19 08:05:43 +0200
commit67eca08b2260f19ff296c0b6cb73eb3b0479e4b2 (patch)
tree96027e6397b24ee87d8d116448387c959a7e197b /api/logic
parent9aff21c1810f366f599fc5d35dfd3d7bc216f759 (diff)
downloadMultiMC-67eca08b2260f19ff296c0b6cb73eb3b0479e4b2.tar
MultiMC-67eca08b2260f19ff296c0b6cb73eb3b0479e4b2.tar.gz
MultiMC-67eca08b2260f19ff296c0b6cb73eb3b0479e4b2.tar.lz
MultiMC-67eca08b2260f19ff296c0b6cb73eb3b0479e4b2.tar.xz
MultiMC-67eca08b2260f19ff296c0b6cb73eb3b0479e4b2.zip
NOISSUE use model/view for Minecraft log data
Diffstat (limited to 'api/logic')
-rw-r--r--api/logic/CMakeLists.txt2
-rw-r--r--api/logic/launch/LaunchTask.cpp12
-rw-r--r--api/logic/launch/LaunchTask.h12
-rw-r--r--api/logic/launch/LogModel.cpp135
-rw-r--r--api/logic/launch/LogModel.h51
5 files changed, 204 insertions, 8 deletions
diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt
index 415584fc..c430b53f 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<LogModel> 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 <QProcess>
+#include <QObjectPtr.h>
+#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<LogModel> 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<LogModel> m_logModel;
QList <std::shared_ptr<LaunchStep>> m_steps;
QMap<QString, QString> 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<entry> 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 <QAbstractListModel>
+#include <QString>
+#include "MessageLevel.h"
+
+#include <multimc_logic_export.h>
+
+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 <entry> 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)
+};