NOISSUE use model/view for Minecraft log data
This commit is contained in:
		@@ -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
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -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()
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										135
									
								
								api/logic/launch/LogModel.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								api/logic/launch/LogModel.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								api/logic/launch/LogModel.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								api/logic/launch/LogModel.h
									
									
									
									
									
										Normal file
									
								
							@@ -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)
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user