2022-05-26 22:18:54 +01:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
/*
|
2023-08-04 18:41:47 +01:00
|
|
|
* Prism Launcher - Minecraft Launcher
|
2022-05-26 22:18:54 +01:00
|
|
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, version 3.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* This file incorporates work covered by the following copyright and
|
|
|
|
* permission notice:
|
|
|
|
*
|
|
|
|
* Copyright 2013-2021 MultiMC Contributors
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2016-08-18 20:31:37 +01:00
|
|
|
#include "LogView.h"
|
|
|
|
#include <QScrollBar>
|
2023-08-14 17:16:53 +01:00
|
|
|
#include <QTextBlock>
|
2016-08-18 20:31:37 +01:00
|
|
|
|
|
|
|
LogView::LogView(QWidget* parent) : QPlainTextEdit(parent)
|
|
|
|
{
|
|
|
|
setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
|
|
|
|
m_defaultFormat = new QTextCharFormat(currentCharFormat());
|
|
|
|
}
|
|
|
|
|
|
|
|
LogView::~LogView()
|
|
|
|
{
|
2016-08-19 08:04:58 +01:00
|
|
|
delete m_defaultFormat;
|
2016-08-18 20:31:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void LogView::setWordWrap(bool wrapping)
|
|
|
|
{
|
2023-08-14 17:16:53 +01:00
|
|
|
if (wrapping) {
|
2016-08-18 20:31:37 +01:00
|
|
|
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
|
|
setLineWrapMode(QPlainTextEdit::WidgetWidth);
|
2023-08-14 17:16:53 +01:00
|
|
|
} else {
|
2016-08-18 20:31:37 +01:00
|
|
|
setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
|
|
|
setLineWrapMode(QPlainTextEdit::NoWrap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LogView::setModel(QAbstractItemModel* model)
|
|
|
|
{
|
2023-08-14 17:16:53 +01:00
|
|
|
if (m_model) {
|
2016-08-18 20:31:37 +01:00
|
|
|
disconnect(m_model, &QAbstractItemModel::modelReset, this, &LogView::repopulate);
|
|
|
|
disconnect(m_model, &QAbstractItemModel::rowsInserted, this, &LogView::rowsInserted);
|
|
|
|
disconnect(m_model, &QAbstractItemModel::rowsAboutToBeInserted, this, &LogView::rowsAboutToBeInserted);
|
|
|
|
disconnect(m_model, &QAbstractItemModel::rowsRemoved, this, &LogView::rowsRemoved);
|
|
|
|
}
|
|
|
|
m_model = model;
|
2023-08-14 17:16:53 +01:00
|
|
|
if (m_model) {
|
2016-08-18 20:31:37 +01:00
|
|
|
connect(m_model, &QAbstractItemModel::modelReset, this, &LogView::repopulate);
|
|
|
|
connect(m_model, &QAbstractItemModel::rowsInserted, this, &LogView::rowsInserted);
|
|
|
|
connect(m_model, &QAbstractItemModel::rowsAboutToBeInserted, this, &LogView::rowsAboutToBeInserted);
|
|
|
|
connect(m_model, &QAbstractItemModel::rowsRemoved, this, &LogView::rowsRemoved);
|
|
|
|
connect(m_model, &QAbstractItemModel::destroyed, this, &LogView::modelDestroyed);
|
|
|
|
}
|
|
|
|
repopulate();
|
|
|
|
}
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
QAbstractItemModel* LogView::model() const
|
2016-08-18 20:31:37 +01:00
|
|
|
{
|
|
|
|
return m_model;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LogView::modelDestroyed(QObject* model)
|
|
|
|
{
|
2023-08-14 17:16:53 +01:00
|
|
|
if (m_model == model) {
|
2016-08-18 20:31:37 +01:00
|
|
|
setModel(nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LogView::repopulate()
|
|
|
|
{
|
|
|
|
auto doc = document();
|
|
|
|
doc->clear();
|
2023-08-14 17:16:53 +01:00
|
|
|
if (!m_model) {
|
2016-08-18 20:31:37 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
rowsInserted(QModelIndex(), 0, m_model->rowCount() - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LogView::rowsAboutToBeInserted(const QModelIndex& parent, int first, int last)
|
|
|
|
{
|
|
|
|
Q_UNUSED(parent)
|
|
|
|
Q_UNUSED(first)
|
|
|
|
Q_UNUSED(last)
|
2023-08-14 17:16:53 +01:00
|
|
|
QScrollBar* bar = verticalScrollBar();
|
2016-08-18 20:31:37 +01:00
|
|
|
int max_bar = bar->maximum();
|
|
|
|
int val_bar = bar->value();
|
2023-08-14 17:16:53 +01:00
|
|
|
if (m_scroll) {
|
2016-08-18 20:31:37 +01:00
|
|
|
m_scroll = (max_bar - val_bar) <= 1;
|
2023-08-14 17:16:53 +01:00
|
|
|
} else {
|
2016-08-18 20:31:37 +01:00
|
|
|
m_scroll = val_bar == max_bar;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LogView::rowsInserted(const QModelIndex& parent, int first, int last)
|
|
|
|
{
|
2023-08-14 17:16:53 +01:00
|
|
|
for (int i = first; i <= last; i++) {
|
2016-08-18 20:31:37 +01:00
|
|
|
auto idx = m_model->index(i, 0, parent);
|
|
|
|
auto text = m_model->data(idx, Qt::DisplayRole).toString();
|
|
|
|
QTextCharFormat format(*m_defaultFormat);
|
|
|
|
auto font = m_model->data(idx, Qt::FontRole);
|
2023-08-14 17:16:53 +01:00
|
|
|
if (font.isValid()) {
|
2016-08-18 20:31:37 +01:00
|
|
|
format.setFont(font.value<QFont>());
|
|
|
|
}
|
2022-05-02 18:10:45 +01:00
|
|
|
auto fg = m_model->data(idx, Qt::ForegroundRole);
|
2023-08-14 17:16:53 +01:00
|
|
|
if (fg.isValid()) {
|
2016-08-18 20:31:37 +01:00
|
|
|
format.setForeground(fg.value<QColor>());
|
|
|
|
}
|
|
|
|
auto bg = m_model->data(idx, Qt::BackgroundRole);
|
2023-08-14 17:16:53 +01:00
|
|
|
if (bg.isValid()) {
|
2016-08-18 20:31:37 +01:00
|
|
|
format.setBackground(bg.value<QColor>());
|
|
|
|
}
|
|
|
|
auto workCursor = textCursor();
|
|
|
|
workCursor.movePosition(QTextCursor::End);
|
|
|
|
workCursor.insertText(text, format);
|
|
|
|
workCursor.insertBlock();
|
|
|
|
}
|
2023-08-14 17:16:53 +01:00
|
|
|
if (m_scroll && !m_scrolling) {
|
2016-08-18 20:31:37 +01:00
|
|
|
m_scrolling = true;
|
2023-08-14 17:16:53 +01:00
|
|
|
QMetaObject::invokeMethod(this, "scrollToBottom", Qt::QueuedConnection);
|
2016-08-18 20:31:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LogView::rowsRemoved(const QModelIndex& parent, int first, int last)
|
|
|
|
{
|
|
|
|
// TODO: some day... maybe
|
|
|
|
Q_UNUSED(parent)
|
|
|
|
Q_UNUSED(first)
|
|
|
|
Q_UNUSED(last)
|
|
|
|
}
|
|
|
|
|
|
|
|
void LogView::scrollToBottom()
|
|
|
|
{
|
|
|
|
m_scrolling = false;
|
|
|
|
verticalScrollBar()->setSliderPosition(verticalScrollBar()->maximum());
|
|
|
|
}
|
|
|
|
|
|
|
|
void LogView::findNext(const QString& what, bool reverse)
|
|
|
|
{
|
|
|
|
find(what, reverse ? QTextDocument::FindFlag::FindBackward : QTextDocument::FindFlag(0));
|
|
|
|
}
|