summaryrefslogtreecommitdiffstats
path: root/application/widgets
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 /application/widgets
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 'application/widgets')
-rw-r--r--application/widgets/LogView.cpp143
-rw-r--r--application/widgets/LogView.h36
2 files changed, 179 insertions, 0 deletions
diff --git a/application/widgets/LogView.cpp b/application/widgets/LogView.cpp
new file mode 100644
index 00000000..9cd91b2e
--- /dev/null
+++ b/application/widgets/LogView.cpp
@@ -0,0 +1,143 @@
+#include "LogView.h"
+#include <QTextBlock>
+#include <QScrollBar>
+
+LogView::LogView(QWidget* parent) : QPlainTextEdit(parent)
+{
+ setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
+ m_defaultFormat = new QTextCharFormat(currentCharFormat());
+}
+
+LogView::~LogView()
+{
+}
+
+void LogView::setWordWrap(bool wrapping)
+{
+ if(wrapping)
+ {
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setLineWrapMode(QPlainTextEdit::WidgetWidth);
+ }
+ else
+ {
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ setLineWrapMode(QPlainTextEdit::NoWrap);
+ }
+}
+
+void LogView::setModel(QAbstractItemModel* model)
+{
+ if(m_model)
+ {
+ 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;
+ if(m_model)
+ {
+ 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();
+}
+
+QAbstractItemModel * LogView::model() const
+{
+ return m_model;
+}
+
+void LogView::modelDestroyed(QObject* model)
+{
+ if(m_model == model)
+ {
+ setModel(nullptr);
+ }
+}
+
+void LogView::repopulate()
+{
+ auto doc = document();
+ doc->clear();
+ if(!m_model)
+ {
+ 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)
+ QScrollBar *bar = verticalScrollBar();
+ int max_bar = bar->maximum();
+ int val_bar = bar->value();
+ if (m_scroll)
+ {
+ m_scroll = (max_bar - val_bar) <= 1;
+ }
+ else
+ {
+ m_scroll = val_bar == max_bar;
+ }
+}
+
+void LogView::rowsInserted(const QModelIndex& parent, int first, int last)
+{
+ for(int i = first; i <= last; i++)
+ {
+ 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);
+ if(font.isValid())
+ {
+ format.setFont(font.value<QFont>());
+ }
+ auto fg = m_model->data(idx, Qt::TextColorRole);
+ if(fg.isValid())
+ {
+ format.setForeground(fg.value<QColor>());
+ }
+ auto bg = m_model->data(idx, Qt::BackgroundRole);
+ if(bg.isValid())
+ {
+ format.setBackground(bg.value<QColor>());
+ }
+ auto workCursor = textCursor();
+ workCursor.movePosition(QTextCursor::End);
+ workCursor.insertText(text, format);
+ workCursor.insertBlock();
+ }
+ if(m_scroll && !m_scrolling)
+ {
+ m_scrolling = true;
+ QMetaObject::invokeMethod( this, "scrollToBottom", Qt::QueuedConnection);
+ }
+}
+
+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));
+}
diff --git a/application/widgets/LogView.h b/application/widgets/LogView.h
new file mode 100644
index 00000000..bb6747cd
--- /dev/null
+++ b/application/widgets/LogView.h
@@ -0,0 +1,36 @@
+#pragma once
+#include <QPlainTextEdit>
+#include <QAbstractItemView>
+
+class QAbstractItemModel;
+
+class LogView: public QPlainTextEdit
+{
+ Q_OBJECT
+public:
+ explicit LogView(QWidget *parent = nullptr);
+ virtual ~LogView();
+
+ virtual void setModel(QAbstractItemModel *model);
+ QAbstractItemModel *model() const;
+
+public slots:
+ void setWordWrap(bool wrapping);
+ void findNext(const QString & what, bool reverse);
+ void scrollToBottom();
+
+protected slots:
+ void repopulate();
+ // note: this supports only appending
+ void rowsInserted(const QModelIndex &parent, int first, int last);
+ void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ // note: this supports only removing from front
+ void rowsRemoved(const QModelIndex &parent, int first, int last);
+ void modelDestroyed(QObject * model);
+
+protected:
+ QAbstractItemModel *m_model = nullptr;
+ QTextCharFormat *m_defaultFormat = nullptr;
+ bool m_scroll = false;
+ bool m_scrolling = false;
+};