From 8e44ab2338f4ca63d58de4b3329c384df9d6c053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 19 Mar 2018 02:36:12 +0100 Subject: NOISSUE redo new instance dialog --- application/pages/instance/LogPage.cpp | 312 +++++++++++++++++++++++++++++++++ 1 file changed, 312 insertions(+) create mode 100644 application/pages/instance/LogPage.cpp (limited to 'application/pages/instance/LogPage.cpp') diff --git a/application/pages/instance/LogPage.cpp b/application/pages/instance/LogPage.cpp new file mode 100644 index 00000000..0fa1ee67 --- /dev/null +++ b/application/pages/instance/LogPage.cpp @@ -0,0 +1,312 @@ +#include "LogPage.h" +#include "ui_LogPage.h" + +#include "MultiMC.h" + +#include +#include +#include + +#include "launch/LaunchTask.h" +#include +#include "GuiUtil.h" +#include + +class LogFormatProxyModel : public QIdentityProxyModel +{ +public: + LogFormatProxyModel(QObject* parent = nullptr) : QIdentityProxyModel(parent) + { + } + QVariant data(const QModelIndex &index, int role) const override + { + switch(role) + { + case Qt::FontRole: + return m_font; + case Qt::TextColorRole: + { + MessageLevel::Enum level = (MessageLevel::Enum) QIdentityProxyModel::data(index, LogModel::LevelRole).toInt(); + return m_colors->getFront(level); + } + case Qt::BackgroundRole: + { + MessageLevel::Enum level = (MessageLevel::Enum) QIdentityProxyModel::data(index, LogModel::LevelRole).toInt(); + return m_colors->getBack(level); + } + default: + return QIdentityProxyModel::data(index, role); + } + } + + void setFont(QFont font) + { + m_font = font; + } + + void setColors(LogColorCache* colors) + { + m_colors.reset(colors); + } + + QModelIndex find(const QModelIndex &start, const QString &value, bool reverse) const + { + QModelIndex parentIndex = parent(start); + auto compare = [&](int r) -> QModelIndex + { + QModelIndex idx = index(r, start.column(), parentIndex); + if (!idx.isValid() || idx == start) + { + return QModelIndex(); + } + QVariant v = data(idx, Qt::DisplayRole); + QString t = v.toString(); + if (t.contains(value, Qt::CaseInsensitive)) + return idx; + return QModelIndex(); + }; + if(reverse) + { + int from = start.row(); + int to = 0; + + for (int i = 0; i < 2; ++i) + { + for (int r = from; (r >= to); --r) + { + auto idx = compare(r); + if(idx.isValid()) + return idx; + } + // prepare for the next iteration + from = rowCount() - 1; + to = start.row(); + } + } + else + { + int from = start.row(); + int to = rowCount(parentIndex); + + for (int i = 0; i < 2; ++i) + { + for (int r = from; (r < to); ++r) + { + auto idx = compare(r); + if(idx.isValid()) + return idx; + } + // prepare for the next iteration + from = 0; + to = start.row(); + } + } + return QModelIndex(); + } +private: + QFont m_font; + std::unique_ptr m_colors; +}; + +LogPage::LogPage(InstancePtr instance, QWidget *parent) + : QWidget(parent), ui(new Ui::LogPage), m_instance(instance) +{ + ui->setupUi(this); + ui->tabWidget->tabBar()->hide(); + + m_proxy = new LogFormatProxyModel(this); + // set up text colors in the log proxy and adapt them to the current theme foreground and background + { + auto origForeground = ui->text->palette().color(ui->text->foregroundRole()); + auto origBackground = ui->text->palette().color(ui->text->backgroundRole()); + m_proxy->setColors(new LogColorCache(origForeground, origBackground)); + } + + // set up fonts in the log proxy + { + QString fontFamily = MMC->settings()->get("ConsoleFont").toString(); + bool conversionOk = false; + int fontSize = MMC->settings()->get("ConsoleFontSize").toInt(&conversionOk); + if(!conversionOk) + { + fontSize = 11; + } + m_proxy->setFont(QFont(fontFamily, fontSize)); + } + + ui->text->setModel(m_proxy); + + // set up instance and launch process recognition + { + auto launchTask = m_instance->getLaunchTask(); + if(launchTask) + { + setInstanceLaunchTaskChanged(launchTask, true); + } + connect(m_instance.get(), &BaseInstance::launchTaskChanged, this, &LogPage::onInstanceLaunchTaskChanged); + } + + auto findShortcut = new QShortcut(QKeySequence(QKeySequence::Find), this); + connect(findShortcut, SIGNAL(activated()), SLOT(findActivated())); + auto findNextShortcut = new QShortcut(QKeySequence(QKeySequence::FindNext), this); + connect(findNextShortcut, SIGNAL(activated()), SLOT(findNextActivated())); + connect(ui->searchBar, SIGNAL(returnPressed()), SLOT(on_findButton_clicked())); + auto findPreviousShortcut = new QShortcut(QKeySequence(QKeySequence::FindPrevious), this); + connect(findPreviousShortcut, SIGNAL(activated()), SLOT(findPreviousActivated())); +} + +LogPage::~LogPage() +{ + delete ui; +} + +void LogPage::modelStateToUI() +{ + if(m_model->wrapLines()) + { + ui->text->setWordWrap(true); + ui->wrapCheckbox->setCheckState(Qt::Checked); + } + else + { + ui->text->setWordWrap(false); + ui->wrapCheckbox->setCheckState(Qt::Unchecked); + } + if(m_model->suspended()) + { + ui->trackLogCheckbox->setCheckState(Qt::Unchecked); + } + else + { + ui->trackLogCheckbox->setCheckState(Qt::Checked); + } +} + +void LogPage::UIToModelState() +{ + if(!m_model) + { + return; + } + m_model->setLineWrap(ui->wrapCheckbox->checkState() == Qt::Checked); + m_model->suspend(ui->trackLogCheckbox->checkState() != Qt::Checked); +} + +void LogPage::setInstanceLaunchTaskChanged(std::shared_ptr proc, bool initial) +{ + m_process = proc; + if(m_process) + { + m_model = proc->getLogModel(); + m_proxy->setSourceModel(m_model.get()); + if(initial) + { + modelStateToUI(); + } + else + { + UIToModelState(); + } + } + else + { + m_proxy->setSourceModel(nullptr); + m_model.reset(); + } +} + +void LogPage::onInstanceLaunchTaskChanged(std::shared_ptr proc) +{ + setInstanceLaunchTaskChanged(proc, false); +} + +bool LogPage::apply() +{ + return true; +} + +bool LogPage::shouldDisplay() const +{ + return m_instance->isRunning() || m_proxy->rowCount() > 0; +} + +void LogPage::on_btnPaste_clicked() +{ + if(!m_model) + return; + + //FIXME: turn this into a proper task and move the upload logic out of GuiUtil! + m_model->append(MessageLevel::MultiMC, tr("MultiMC: Log upload triggered at: %1").arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date))); + auto url = GuiUtil::uploadPaste(m_model->toPlainText(), this); + if(!url.isEmpty()) + { + m_model->append(MessageLevel::MultiMC, tr("MultiMC: Log uploaded to: %1").arg(url)); + } + else + { + m_model->append(MessageLevel::Error, tr("MultiMC: Log upload failed!")); + } +} + +void LogPage::on_btnCopy_clicked() +{ + if(!m_model) + return; + m_model->append(MessageLevel::MultiMC, QString("Clipboard copy at: %1").arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date))); + GuiUtil::setClipboardText(m_model->toPlainText()); +} + +void LogPage::on_btnClear_clicked() +{ + if(!m_model) + return; + m_model->clear(); + m_container->refreshContainer(); +} + +void LogPage::on_btnBottom_clicked() +{ + ui->text->scrollToBottom(); +} + +void LogPage::on_trackLogCheckbox_clicked(bool checked) +{ + if(!m_model) + return; + m_model->suspend(!checked); +} + +void LogPage::on_wrapCheckbox_clicked(bool checked) +{ + ui->text->setWordWrap(checked); + if(!m_model) + return; + m_model->setLineWrap(checked); +} + +void LogPage::on_findButton_clicked() +{ + auto modifiers = QApplication::keyboardModifiers(); + bool reverse = modifiers & Qt::ShiftModifier; + ui->text->findNext(ui->searchBar->text(), reverse); +} + +void LogPage::findNextActivated() +{ + ui->text->findNext(ui->searchBar->text(), false); +} + +void LogPage::findPreviousActivated() +{ + ui->text->findNext(ui->searchBar->text(), true); +} + +void LogPage::findActivated() +{ + // focus the search bar if it doesn't have focus + if (!ui->searchBar->hasFocus()) + { + ui->searchBar->setFocus(); + ui->searchBar->selectAll(); + } +} -- cgit v1.2.3