GH-338, GH-513, GH-700 Unify edit instance with console window
* The resulting instance window can be closed at any point. * Main window is kept open and running instances are marked with a badge. * Multiple instances can now run from the same MultiMC - it's even more **multi** now. * MultiMC can be entirely closed, keeping Minecraft(s) running.
@ -92,11 +92,14 @@ bool BaseInstance::isRunning() const
|
||||
|
||||
void BaseInstance::setRunning(bool running)
|
||||
{
|
||||
if(running && !m_isRunning)
|
||||
if(running == m_isRunning)
|
||||
return;
|
||||
|
||||
if(running)
|
||||
{
|
||||
m_timeStarted = QDateTime::currentDateTime();
|
||||
}
|
||||
else if(!running && m_isRunning)
|
||||
else
|
||||
{
|
||||
qint64 current = settings()->get("totalTimePlayed").toLongLong();
|
||||
QDateTime timeEnded = QDateTime::currentDateTime();
|
||||
@ -104,6 +107,8 @@ void BaseInstance::setRunning(bool running)
|
||||
emit propertiesChanged(this);
|
||||
}
|
||||
m_isRunning = running;
|
||||
|
||||
emit runningStatusChanged(running);
|
||||
}
|
||||
|
||||
int64_t BaseInstance::totalTimePlayed() const
|
||||
@ -179,7 +184,7 @@ void BaseInstance::unsetFlag(const BaseInstance::InstanceFlag flag)
|
||||
|
||||
bool BaseInstance::canLaunch() const
|
||||
{
|
||||
return !(flags() & VersionBrokenFlag);
|
||||
return (!(flags() & VersionBrokenFlag)) && (!isRunning());
|
||||
}
|
||||
|
||||
bool BaseInstance::reload()
|
||||
@ -268,3 +273,8 @@ QStringList BaseInstance::extraArguments() const
|
||||
{
|
||||
return Commandline::splitArgs(settings()->get("JvmArgs").toString());
|
||||
}
|
||||
|
||||
std::shared_ptr<LaunchTask> BaseInstance::getLaunchTask()
|
||||
{
|
||||
return m_launchProcess;
|
||||
}
|
||||
|
@ -157,6 +157,9 @@ public:
|
||||
/// returns a valid launcher (task container)
|
||||
virtual std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) = 0;
|
||||
|
||||
/// returns the current launch task (if any)
|
||||
std::shared_ptr<LaunchTask> getLaunchTask();
|
||||
|
||||
/*!
|
||||
* Returns a task that should be done right before launch
|
||||
* This task should do any extra preparations needed
|
||||
@ -231,6 +234,10 @@ signals:
|
||||
|
||||
void flagsChanged();
|
||||
|
||||
void launchTaskChanged(std::shared_ptr<LaunchTask>);
|
||||
|
||||
void runningStatusChanged(bool running);
|
||||
|
||||
protected slots:
|
||||
void iconUpdated(QString key);
|
||||
|
||||
@ -240,6 +247,7 @@ protected:
|
||||
SettingsObjectPtr m_settings;
|
||||
InstanceFlags m_flags;
|
||||
bool m_isRunning = false;
|
||||
std::shared_ptr<LaunchTask> m_launchProcess;
|
||||
QDateTime m_timeStarted;
|
||||
};
|
||||
|
||||
|
@ -465,7 +465,9 @@ std::shared_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPtr s
|
||||
{
|
||||
process->setCensorFilter(createCensorFilterFromSession(session));
|
||||
}
|
||||
return process;
|
||||
m_launchProcess = process;
|
||||
emit launchTaskChanged(m_launchProcess);
|
||||
return m_launchProcess;
|
||||
}
|
||||
|
||||
QString MinecraftInstance::launchMethod()
|
||||
|
@ -103,12 +103,11 @@ SET(MULTIMC_SOURCES
|
||||
# GUI - windows
|
||||
MainWindow.h
|
||||
MainWindow.cpp
|
||||
ConsoleWindow.h
|
||||
ConsoleWindow.cpp
|
||||
InstanceWindow.h
|
||||
InstanceWindow.cpp
|
||||
|
||||
# GUI - settings-specific wrappers for paged dialog
|
||||
SettingsUI.h
|
||||
SettingsUI.cpp
|
||||
|
||||
# Processes
|
||||
LaunchInteraction.h
|
||||
|
@ -1,260 +0,0 @@
|
||||
/* Copyright 2013-2015 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.
|
||||
*/
|
||||
|
||||
#include "ConsoleWindow.h"
|
||||
#include "MultiMC.h"
|
||||
|
||||
#include <QScrollBar>
|
||||
#include <QMessageBox>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <qlayoutitem.h>
|
||||
#include <QCloseEvent>
|
||||
|
||||
#include <dialogs/CustomMessageBox.h>
|
||||
#include <dialogs/ProgressDialog.h>
|
||||
#include "widgets/PageContainer.h"
|
||||
#include "pages/LogPage.h"
|
||||
#include "InstancePageProvider.h"
|
||||
|
||||
#include "icons/IconList.h"
|
||||
|
||||
class LogPageProvider : public BasePageProvider
|
||||
{
|
||||
public:
|
||||
LogPageProvider(BasePageProviderPtr parent, BasePage * log_page)
|
||||
{
|
||||
m_parent = parent;
|
||||
m_log_page = log_page;
|
||||
}
|
||||
virtual QString dialogTitle() {return "Fake";};
|
||||
virtual QList<BasePage *> getPages()
|
||||
{
|
||||
auto pages = m_parent->getPages();
|
||||
pages.prepend(m_log_page);
|
||||
return pages;
|
||||
}
|
||||
private:
|
||||
BasePageProviderPtr m_parent;
|
||||
BasePage * m_log_page;
|
||||
};
|
||||
|
||||
ConsoleWindow::ConsoleWindow(std::shared_ptr<LaunchTask> proc, QWidget *parent)
|
||||
: QMainWindow(parent), m_proc(proc)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
auto instance = m_proc->instance();
|
||||
auto icon = MMC->icons()->getIcon(instance->iconKey());
|
||||
QString windowTitle = tr("Console window for ") + instance->name();
|
||||
|
||||
// Set window properties
|
||||
{
|
||||
setWindowIcon(icon);
|
||||
setWindowTitle(windowTitle);
|
||||
}
|
||||
|
||||
// Add page container
|
||||
{
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
auto provider = std::make_shared<InstancePageProvider>(m_proc->instance());
|
||||
auto baseprovider = std::dynamic_pointer_cast<BasePageProvider>(provider);
|
||||
auto proxy_provider = std::make_shared<LogPageProvider>(baseprovider, new LogPage(m_proc));
|
||||
m_container = new PageContainer(proxy_provider, "console", this);
|
||||
mainLayout->addWidget(m_container);
|
||||
mainLayout->setSpacing(0);
|
||||
mainLayout->setContentsMargins(0,0,0,0);
|
||||
setLayout(mainLayout);
|
||||
setCentralWidget(m_container);
|
||||
}
|
||||
|
||||
// Add custom buttons to the page container layout.
|
||||
{
|
||||
auto horizontalLayout = new QHBoxLayout();
|
||||
horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
|
||||
horizontalLayout->setContentsMargins(6, -1, 6, -1);
|
||||
|
||||
auto btnHelp = new QPushButton();
|
||||
btnHelp->setText(tr("Help"));
|
||||
horizontalLayout->addWidget(btnHelp);
|
||||
connect(btnHelp, SIGNAL(clicked(bool)), m_container, SLOT(help()));
|
||||
|
||||
auto spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
horizontalLayout->addSpacerItem(spacer);
|
||||
|
||||
m_killButton = new QPushButton();
|
||||
m_killButton->setText(tr("Kill Minecraft"));
|
||||
horizontalLayout->addWidget(m_killButton);
|
||||
connect(m_killButton, SIGNAL(clicked(bool)), SLOT(on_btnKillMinecraft_clicked()));
|
||||
|
||||
m_closeButton = new QPushButton();
|
||||
m_closeButton->setText(tr("Close"));
|
||||
horizontalLayout->addWidget(m_closeButton);
|
||||
connect(m_closeButton, SIGNAL(clicked(bool)), SLOT(on_closeButton_clicked()));
|
||||
|
||||
m_container->addButtons(horizontalLayout);
|
||||
}
|
||||
|
||||
// restore window state
|
||||
{
|
||||
auto base64State = MMC->settings()->get("ConsoleWindowState").toByteArray();
|
||||
restoreState(QByteArray::fromBase64(base64State));
|
||||
auto base64Geometry = MMC->settings()->get("ConsoleWindowGeometry").toByteArray();
|
||||
restoreGeometry(QByteArray::fromBase64(base64Geometry));
|
||||
}
|
||||
|
||||
// Set up tray icon
|
||||
{
|
||||
m_trayIcon = new QSystemTrayIcon(icon, this);
|
||||
m_trayIcon->setToolTip(windowTitle);
|
||||
|
||||
connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
|
||||
SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
|
||||
m_trayIcon->show();
|
||||
}
|
||||
|
||||
// Set up signal connections
|
||||
connect(m_proc.get(), &LaunchTask::succeeded, this, &ConsoleWindow::onSucceeded);
|
||||
connect(m_proc.get(), &LaunchTask::failed, this, &ConsoleWindow::onFailed);
|
||||
connect(m_proc.get(), &LaunchTask::requestProgress, this, &ConsoleWindow::onProgressRequested);
|
||||
|
||||
setMayClose(false);
|
||||
|
||||
if (m_proc->instance()->settings()->get("ShowConsole").toBool())
|
||||
{
|
||||
show();
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
|
||||
{
|
||||
switch (reason)
|
||||
{
|
||||
case QSystemTrayIcon::Trigger:
|
||||
{
|
||||
toggleConsole();
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::on_closeButton_clicked()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void ConsoleWindow::setMayClose(bool mayclose)
|
||||
{
|
||||
if(mayclose)
|
||||
m_closeButton->setText(tr("Close"));
|
||||
else
|
||||
m_closeButton->setText(tr("Hide"));
|
||||
m_mayclose = mayclose;
|
||||
}
|
||||
|
||||
void ConsoleWindow::toggleConsole()
|
||||
{
|
||||
if (isVisible())
|
||||
{
|
||||
if(!isActiveWindow())
|
||||
{
|
||||
activateWindow();
|
||||
return;
|
||||
}
|
||||
hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
show();
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
if (!m_mayclose)
|
||||
{
|
||||
toggleConsole();
|
||||
event->ignore();
|
||||
}
|
||||
else if(m_container->requestClose(event))
|
||||
{
|
||||
MMC->settings()->set("ConsoleWindowState", saveState().toBase64());
|
||||
MMC->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64());
|
||||
|
||||
emit isClosing();
|
||||
m_trayIcon->hide();
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::on_btnKillMinecraft_clicked()
|
||||
{
|
||||
m_killButton->setEnabled(false);
|
||||
auto response = CustomMessageBox::selectable(
|
||||
this, tr("Kill Minecraft?"),
|
||||
tr("This can cause the instance to get corrupted and should only be used if Minecraft "
|
||||
"is frozen for some reason"),
|
||||
QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec();
|
||||
if (response == QMessageBox::Yes)
|
||||
m_proc->abort();
|
||||
else
|
||||
m_killButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void ConsoleWindow::onSucceeded()
|
||||
{
|
||||
m_killButton->setEnabled(false);
|
||||
setMayClose(true);
|
||||
if (m_proc->instance()->settings()->get("AutoCloseConsole").toBool() && m_container->requestClose(nullptr))
|
||||
{
|
||||
this->close();
|
||||
return;
|
||||
}
|
||||
if (!isVisible())
|
||||
{
|
||||
show();
|
||||
}
|
||||
// Raise Window
|
||||
if (MMC->settings()->get("RaiseConsole").toBool())
|
||||
{
|
||||
raise();
|
||||
activateWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::onFailed(QString reason)
|
||||
{
|
||||
m_killButton->setEnabled(false);
|
||||
setMayClose(true);
|
||||
if (!isVisible())
|
||||
{
|
||||
show();
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::onProgressRequested(Task* task)
|
||||
{
|
||||
ProgressDialog progDialog(this);
|
||||
m_proc->proceed();
|
||||
progDialog.execWithTask(task);
|
||||
}
|
||||
|
||||
|
||||
ConsoleWindow::~ConsoleWindow()
|
||||
{
|
||||
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
#include "minecraft/legacy/LegacyInstance.h"
|
||||
#include <FileSystem.h>
|
||||
#include "pages/BasePage.h"
|
||||
#include "pages/LogPage.h"
|
||||
#include "pages/VersionPage.h"
|
||||
#include "pages/ModFolderPage.h"
|
||||
#include "pages/ResourcePackPage.h"
|
||||
@ -29,6 +30,7 @@ public:
|
||||
virtual QList<BasePage *> getPages() override
|
||||
{
|
||||
QList<BasePage *> values;
|
||||
values.append(new LogPage(inst));
|
||||
std::shared_ptr<OneSixInstance> onesix = std::dynamic_pointer_cast<OneSixInstance>(inst);
|
||||
if(onesix)
|
||||
{
|
||||
|
226
application/InstanceWindow.cpp
Normal file
@ -0,0 +1,226 @@
|
||||
/* Copyright 2013-2015 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.
|
||||
*/
|
||||
|
||||
#include "InstanceWindow.h"
|
||||
#include "MultiMC.h"
|
||||
|
||||
#include <QScrollBar>
|
||||
#include <QMessageBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <qlayoutitem.h>
|
||||
#include <QCloseEvent>
|
||||
|
||||
#include <dialogs/CustomMessageBox.h>
|
||||
#include <dialogs/ProgressDialog.h>
|
||||
#include "widgets/PageContainer.h"
|
||||
#include "InstancePageProvider.h"
|
||||
|
||||
#include "icons/IconList.h"
|
||||
|
||||
InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent)
|
||||
: QMainWindow(parent), m_instance(instance)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
auto icon = MMC->icons()->getIcon(m_instance->iconKey());
|
||||
QString windowTitle = tr("Console window for ") + m_instance->name();
|
||||
|
||||
// Set window properties
|
||||
{
|
||||
setWindowIcon(icon);
|
||||
setWindowTitle(windowTitle);
|
||||
}
|
||||
|
||||
// Add page container
|
||||
{
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
auto provider = std::make_shared<InstancePageProvider>(m_instance);
|
||||
m_container = new PageContainer(provider, "console", this);
|
||||
mainLayout->addWidget(m_container);
|
||||
mainLayout->setSpacing(0);
|
||||
mainLayout->setContentsMargins(0,0,0,0);
|
||||
setLayout(mainLayout);
|
||||
setCentralWidget(m_container);
|
||||
}
|
||||
|
||||
// Add custom buttons to the page container layout.
|
||||
{
|
||||
auto horizontalLayout = new QHBoxLayout();
|
||||
horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
|
||||
horizontalLayout->setContentsMargins(6, -1, 6, -1);
|
||||
|
||||
auto btnHelp = new QPushButton();
|
||||
btnHelp->setText(tr("Help"));
|
||||
horizontalLayout->addWidget(btnHelp);
|
||||
connect(btnHelp, SIGNAL(clicked(bool)), m_container, SLOT(help()));
|
||||
|
||||
auto spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
horizontalLayout->addSpacerItem(spacer);
|
||||
|
||||
m_killButton = new QPushButton();
|
||||
horizontalLayout->addWidget(m_killButton);
|
||||
setKillButton(m_instance->isRunning());
|
||||
connect(m_killButton, SIGNAL(clicked(bool)), SLOT(on_btnKillMinecraft_clicked()));
|
||||
|
||||
m_closeButton = new QPushButton();
|
||||
m_closeButton->setText(tr("Close"));
|
||||
horizontalLayout->addWidget(m_closeButton);
|
||||
connect(m_closeButton, SIGNAL(clicked(bool)), SLOT(on_closeButton_clicked()));
|
||||
|
||||
m_container->addButtons(horizontalLayout);
|
||||
}
|
||||
|
||||
// restore window state
|
||||
{
|
||||
auto base64State = MMC->settings()->get("ConsoleWindowState").toByteArray();
|
||||
restoreState(QByteArray::fromBase64(base64State));
|
||||
auto base64Geometry = MMC->settings()->get("ConsoleWindowGeometry").toByteArray();
|
||||
restoreGeometry(QByteArray::fromBase64(base64Geometry));
|
||||
}
|
||||
|
||||
// set up instance and launch process recognition
|
||||
{
|
||||
auto launchTask = m_instance->getLaunchTask();
|
||||
on_InstanceLaunchTask_changed(launchTask);
|
||||
connect(m_instance.get(), &BaseInstance::launchTaskChanged,
|
||||
this, &InstanceWindow::on_InstanceLaunchTask_changed);
|
||||
connect(m_instance.get(), &BaseInstance::runningStatusChanged,
|
||||
this, &InstanceWindow::on_RunningState_changed);
|
||||
}
|
||||
show();
|
||||
}
|
||||
|
||||
void InstanceWindow::setKillButton(bool kill)
|
||||
{
|
||||
if(kill)
|
||||
{
|
||||
m_killButton->setText(tr("Kill"));
|
||||
m_killButton->setToolTip(tr("Kill the running instance"));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_killButton->setText(tr("Launch"));
|
||||
m_killButton->setToolTip(tr("Launch the instance"));
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceWindow::on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> proc)
|
||||
{
|
||||
if(m_proc)
|
||||
{
|
||||
disconnect(m_proc.get(), &LaunchTask::succeeded, this, &InstanceWindow::onSucceeded);
|
||||
disconnect(m_proc.get(), &LaunchTask::failed, this, &InstanceWindow::onFailed);
|
||||
disconnect(m_proc.get(), &LaunchTask::requestProgress, this, &InstanceWindow::onProgressRequested);
|
||||
}
|
||||
|
||||
m_proc = proc;
|
||||
|
||||
if(m_proc)
|
||||
{
|
||||
// Set up signal connections
|
||||
connect(m_proc.get(), &LaunchTask::succeeded, this, &InstanceWindow::onSucceeded);
|
||||
connect(m_proc.get(), &LaunchTask::failed, this, &InstanceWindow::onFailed);
|
||||
connect(m_proc.get(), &LaunchTask::requestProgress, this, &InstanceWindow::onProgressRequested);
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceWindow::on_RunningState_changed(bool running)
|
||||
{
|
||||
setKillButton(running);
|
||||
m_container->refresh();
|
||||
}
|
||||
|
||||
void InstanceWindow::on_closeButton_clicked()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void InstanceWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
MMC->settings()->set("ConsoleWindowState", saveState().toBase64());
|
||||
MMC->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64());
|
||||
|
||||
if(m_container->requestClose(event))
|
||||
{
|
||||
emit isClosing();
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceWindow::on_btnKillMinecraft_clicked()
|
||||
{
|
||||
if(m_instance->isRunning())
|
||||
{
|
||||
auto response = CustomMessageBox::selectable(
|
||||
this, tr("Kill Minecraft?"),
|
||||
tr("This can cause the instance to get corrupted and should only be used if Minecraft "
|
||||
"is frozen for some reason"),
|
||||
QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec();
|
||||
if (response == QMessageBox::Yes)
|
||||
{
|
||||
m_proc->abort();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_launchController.reset(new LaunchController());
|
||||
m_launchController->setInstance(m_instance);
|
||||
m_launchController->setOnline(true);
|
||||
m_launchController->setParentWidget(this);
|
||||
m_launchController->start();
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceWindow::onSucceeded()
|
||||
{
|
||||
if (m_instance->settings()->get("AutoCloseConsole").toBool() && m_container->requestClose(nullptr))
|
||||
{
|
||||
this->close();
|
||||
return;
|
||||
}
|
||||
// Raise Window
|
||||
if (MMC->settings()->get("RaiseConsole").toBool())
|
||||
{
|
||||
show();
|
||||
raise();
|
||||
activateWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceWindow::onFailed(QString reason)
|
||||
{
|
||||
}
|
||||
|
||||
void InstanceWindow::onProgressRequested(Task* task)
|
||||
{
|
||||
ProgressDialog progDialog(this);
|
||||
m_proc->proceed();
|
||||
progDialog.execWithTask(task);
|
||||
}
|
||||
|
||||
QString InstanceWindow::instanceId()
|
||||
{
|
||||
return m_instance->id();
|
||||
}
|
||||
|
||||
bool InstanceWindow::selectPage(QString pageId)
|
||||
{
|
||||
return m_container->selectPage(pageId);
|
||||
}
|
||||
|
||||
InstanceWindow::~InstanceWindow()
|
||||
{
|
||||
}
|
@ -16,25 +16,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <QMainWindow>
|
||||
#include "LaunchInteraction.h"
|
||||
#include <QObjectPtr.h>
|
||||
#include <QSystemTrayIcon>
|
||||
#include "launch/LaunchTask.h"
|
||||
#include "pages/BasePageContainer.h"
|
||||
|
||||
class QPushButton;
|
||||
class PageContainer;
|
||||
class ConsoleWindow : public QMainWindow
|
||||
class InstanceWindow : public QMainWindow, public BasePageContainer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConsoleWindow(std::shared_ptr<LaunchTask> proc, QWidget *parent = 0);
|
||||
virtual ~ConsoleWindow();
|
||||
explicit InstanceWindow(InstancePtr proc, QWidget *parent = 0);
|
||||
virtual ~InstanceWindow();
|
||||
|
||||
/**
|
||||
* @brief specify if the window is allowed to close
|
||||
* @param mayclose
|
||||
* used to keep it alive while MC runs
|
||||
*/
|
||||
void setMayClose(bool mayclose);
|
||||
bool selectPage(QString pageId) override;
|
||||
|
||||
QString instanceId();
|
||||
|
||||
signals:
|
||||
void isClosing();
|
||||
@ -48,18 +48,20 @@ slots:
|
||||
void onFailed(QString reason);
|
||||
void onProgressRequested(Task *task);
|
||||
|
||||
// FIXME: add handlers for the other MinecraftLauncher signals (pre/post launch command
|
||||
// failures)
|
||||
void on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> proc);
|
||||
void on_RunningState_changed(bool running);
|
||||
|
||||
void iconActivated(QSystemTrayIcon::ActivationReason);
|
||||
void toggleConsole();
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *);
|
||||
void closeEvent(QCloseEvent *) override;
|
||||
|
||||
private:
|
||||
void setKillButton(bool kill);
|
||||
|
||||
private:
|
||||
std::shared_ptr<LaunchTask> m_proc;
|
||||
unique_qobject_ptr<LaunchController> m_launchController;
|
||||
InstancePtr m_instance;
|
||||
bool m_mayclose = true;
|
||||
QSystemTrayIcon *m_trayIcon = nullptr;
|
||||
PageContainer *m_container = nullptr;
|
||||
QPushButton *m_closeButton = nullptr;
|
||||
QPushButton *m_killButton = nullptr;
|
@ -1,11 +1,12 @@
|
||||
#include "LaunchInteraction.h"
|
||||
#include "MainWindow.h"
|
||||
#include <minecraft/auth/MojangAccountList.h>
|
||||
#include "MultiMC.h"
|
||||
#include "dialogs/CustomMessageBox.h"
|
||||
#include "dialogs/AccountSelectDialog.h"
|
||||
#include "dialogs/ProgressDialog.h"
|
||||
#include "dialogs/EditAccountDialog.h"
|
||||
#include "ConsoleWindow.h"
|
||||
#include "InstanceWindow.h"
|
||||
#include "BuildConfig.h"
|
||||
#include "JavaCommon.h"
|
||||
#include "SettingsUI.h"
|
||||
@ -204,13 +205,20 @@ void LaunchController::launchInstance()
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_parentWidget)
|
||||
auto mainWindow = qobject_cast<MainWindow *>(m_parentWidget);
|
||||
auto instanceWindow = qobject_cast<InstanceWindow *>(m_parentWidget);
|
||||
if(mainWindow)
|
||||
{
|
||||
m_parentWidget->hide();
|
||||
m_console = mainWindow->showInstanceWindow(m_instance);
|
||||
}
|
||||
else if(instanceWindow)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
else
|
||||
{
|
||||
m_console = new InstanceWindow(m_instance);
|
||||
}
|
||||
|
||||
m_console = new ConsoleWindow(m_launcher);
|
||||
connect(m_console, &ConsoleWindow::isClosing, this, &LaunchController::instanceEnded);
|
||||
connect(m_launcher.get(), &LaunchTask::readyForLaunch, this, &LaunchController::readyForLaunch);
|
||||
|
||||
m_launcher->prependStep(std::make_shared<TextPrint>(m_launcher.get(), "MultiMC version: " + BuildConfig.printableVersionString() + "\n\n", MessageLevel::MultiMC));
|
||||
@ -222,6 +230,7 @@ void LaunchController::readyForLaunch()
|
||||
if (!m_profiler)
|
||||
{
|
||||
m_launcher->proceed();
|
||||
emitSucceeded();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -230,6 +239,7 @@ void LaunchController::readyForLaunch()
|
||||
{
|
||||
m_launcher->abort();
|
||||
QMessageBox::critical(m_parentWidget, tr("Error"), tr("Couldn't start profiler: %1").arg(error));
|
||||
emitFailed("Profiler startup failed");
|
||||
return;
|
||||
}
|
||||
BaseProfiler *profilerInstance = m_profiler->createProfiler(m_launcher->instance(), this);
|
||||
@ -246,6 +256,7 @@ void LaunchController::readyForLaunch()
|
||||
msg.setModal(true);
|
||||
msg.exec();
|
||||
m_launcher->proceed();
|
||||
emitSucceeded();
|
||||
});
|
||||
connect(profilerInstance, &BaseProfiler::abortLaunch, [this](const QString & message)
|
||||
{
|
||||
@ -257,15 +268,7 @@ void LaunchController::readyForLaunch()
|
||||
msg.setModal(true);
|
||||
msg.exec();
|
||||
m_launcher->abort();
|
||||
emitFailed("Profiler startup failed");
|
||||
});
|
||||
profilerInstance->beginProfiling(m_launcher);
|
||||
}
|
||||
|
||||
void LaunchController::instanceEnded()
|
||||
{
|
||||
if(m_parentWidget)
|
||||
{
|
||||
m_parentWidget->show();
|
||||
}
|
||||
emitSucceeded();
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <BaseInstance.h>
|
||||
#include <tools/BaseProfiler.h>
|
||||
|
||||
class ConsoleWindow;
|
||||
class InstanceWindow;
|
||||
class LaunchController: public Task
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -36,14 +36,13 @@ private:
|
||||
|
||||
private slots:
|
||||
void readyForLaunch();
|
||||
void instanceEnded();
|
||||
|
||||
private:
|
||||
BaseProfilerFactory *m_profiler = nullptr;
|
||||
bool m_online = true;
|
||||
InstancePtr m_instance;
|
||||
QWidget * m_parentWidget = nullptr;
|
||||
ConsoleWindow *m_console = nullptr;
|
||||
InstanceWindow *m_console = nullptr;
|
||||
AuthSessionPtr m_session;
|
||||
std::shared_ptr <LaunchTask> m_launcher;
|
||||
};
|
||||
|
@ -67,6 +67,7 @@
|
||||
#include <updater/UpdateChecker.h>
|
||||
#include <DesktopServices.h>
|
||||
|
||||
#include "InstanceWindow.h"
|
||||
#include "InstancePageProvider.h"
|
||||
#include "InstanceProxyModel.h"
|
||||
#include "JavaCommon.h"
|
||||
@ -1424,24 +1425,62 @@ void MainWindow::on_actionSettings_triggered()
|
||||
update();
|
||||
}
|
||||
|
||||
InstanceWindow *MainWindow::showInstanceWindow(InstancePtr instance, QString page)
|
||||
{
|
||||
if(!instance)
|
||||
return nullptr;
|
||||
auto id = instance->id();
|
||||
InstanceWindow * window = nullptr;
|
||||
|
||||
auto iter = m_instanceWindows.find(id);
|
||||
if(iter != m_instanceWindows.end())
|
||||
{
|
||||
window = *iter;
|
||||
window->raise();
|
||||
window->activateWindow();
|
||||
}
|
||||
else
|
||||
{
|
||||
window = new InstanceWindow(instance, this);
|
||||
m_instanceWindows[id] = window;
|
||||
connect(window, &InstanceWindow::isClosing, this, &MainWindow::on_instanceWindowClose);
|
||||
}
|
||||
if(!page.isEmpty())
|
||||
{
|
||||
window->selectPage(page);
|
||||
}
|
||||
return window;
|
||||
}
|
||||
|
||||
void MainWindow::on_instanceWindowClose()
|
||||
{
|
||||
auto senderWindow = qobject_cast<InstanceWindow *>(QObject::sender());
|
||||
if(!senderWindow)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_instanceWindows.remove(senderWindow->instanceId());
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_actionInstanceSettings_triggered()
|
||||
{
|
||||
SettingsUI::ShowInstancePageDialog(m_selectedInstance, this, "settings");
|
||||
showInstanceWindow(m_selectedInstance, "settings");
|
||||
}
|
||||
|
||||
void MainWindow::on_actionEditInstNotes_triggered()
|
||||
{
|
||||
SettingsUI::ShowInstancePageDialog(m_selectedInstance, this, "notes");
|
||||
showInstanceWindow(m_selectedInstance, "notes");
|
||||
}
|
||||
|
||||
void MainWindow::on_actionEditInstance_triggered()
|
||||
{
|
||||
SettingsUI::ShowInstancePageDialog(m_selectedInstance, this);
|
||||
showInstanceWindow(m_selectedInstance);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionScreenshots_triggered()
|
||||
{
|
||||
SettingsUI::ShowInstancePageDialog(m_selectedInstance, this, "screenshots");
|
||||
showInstanceWindow(m_selectedInstance, "screenshots");
|
||||
}
|
||||
|
||||
void MainWindow::on_actionManageAccounts_triggered()
|
||||
@ -1586,10 +1625,8 @@ void MainWindow::on_actionLaunchInstanceOffline_triggered()
|
||||
|
||||
void MainWindow::launch(InstancePtr instance, bool online, BaseProfilerFactory *profiler)
|
||||
{
|
||||
if(!instance->canLaunch())
|
||||
if(instance->canLaunch())
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_launchController.reset(new LaunchController());
|
||||
m_launchController->setInstance(instance);
|
||||
m_launchController->setOnline(online);
|
||||
@ -1597,6 +1634,11 @@ void MainWindow::launch(InstancePtr instance, bool online, BaseProfilerFactory *
|
||||
m_launchController->setProfiler(profiler);
|
||||
m_launchController->start();
|
||||
}
|
||||
else if (instance->isRunning())
|
||||
{
|
||||
showInstanceWindow(instance, "console");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::taskEnd()
|
||||
{
|
||||
|
@ -37,6 +37,7 @@ class MinecraftLauncher;
|
||||
class BaseProfilerFactory;
|
||||
class GroupView;
|
||||
class ServerStatus;
|
||||
class InstanceWindow;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
@ -54,6 +55,8 @@ public:
|
||||
void checkSetDefaultJava();
|
||||
void checkInstancePathForProblems();
|
||||
|
||||
InstanceWindow *showInstanceWindow(InstancePtr instance, QString page = QString());
|
||||
|
||||
private slots:
|
||||
void onCatToggled(bool);
|
||||
|
||||
@ -159,6 +162,8 @@ private slots:
|
||||
*/
|
||||
void downloadUpdates(GoUpdate::Status status);
|
||||
|
||||
void on_instanceWindowClose();
|
||||
|
||||
private:
|
||||
void setCatBackground(bool enabled);
|
||||
void updateInstanceToolIcon(QString new_icon);
|
||||
@ -195,4 +200,7 @@ private:
|
||||
|
||||
// managed by the application object
|
||||
Task *m_versionLoadTask;
|
||||
|
||||
// map from instance ID to its window
|
||||
QMap<QString, InstanceWindow *> m_instanceWindows;
|
||||
};
|
||||
|
@ -1,9 +0,0 @@
|
||||
#include "SettingsUI.h"
|
||||
namespace SettingsUI
|
||||
{
|
||||
void ShowInstancePageDialog(InstancePtr instance, QWidget * parent, QString open_page)
|
||||
{
|
||||
auto provider = std::make_shared<InstancePageProvider>(instance);
|
||||
ShowPageDialog(provider, parent, open_page);
|
||||
}
|
||||
}
|
@ -23,6 +23,4 @@ void ShowPageDialog(T raw_provider, QWidget * parent, QString open_page = QStrin
|
||||
dlg.exec();
|
||||
}
|
||||
}
|
||||
|
||||
void ShowInstancePageDialog(InstancePtr instance, QWidget * parent, QString open_page = QString());
|
||||
}
|
||||
|
@ -122,6 +122,10 @@ void drawBadges(QPainter *painter, const QStyleOptionViewItemV4 &option, BaseIns
|
||||
{
|
||||
pixmaps.append("updateavailable");
|
||||
}
|
||||
if (instance->isRunning())
|
||||
{
|
||||
pixmaps.append("status-running");
|
||||
}
|
||||
|
||||
// begin easter eggs
|
||||
if (instance->name().contains("btw", Qt::CaseInsensitive) ||
|
||||
|
@ -12,15 +12,14 @@
|
||||
#include "GuiUtil.h"
|
||||
#include <ColorCache.h>
|
||||
|
||||
LogPage::LogPage(std::shared_ptr<LaunchTask> proc, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::LogPage), m_process(proc)
|
||||
LogPage::LogPage(InstancePtr instance, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::LogPage), m_instance(instance)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
connect(m_process.get(), SIGNAL(log(QString, MessageLevel::Enum)), this,
|
||||
SLOT(write(QString, MessageLevel::Enum)));
|
||||
|
||||
// create the format and set its font
|
||||
{
|
||||
defaultFormat = new QTextCharFormat(ui->text->currentCharFormat());
|
||||
QString fontFamily = MMC->settings()->get("ConsoleFont").toString();
|
||||
bool conversionOk = false;
|
||||
@ -30,9 +29,12 @@ LogPage::LogPage(std::shared_ptr<LaunchTask> proc, QWidget *parent)
|
||||
fontSize = 11;
|
||||
}
|
||||
defaultFormat->setFont(QFont(fontFamily, fontSize));
|
||||
}
|
||||
|
||||
// ensure we don't eat all the RAM
|
||||
{
|
||||
auto lineSetting = MMC->settings()->getSetting("ConsoleMaxLines");
|
||||
bool conversionOk = false;
|
||||
int maxLines = lineSetting->get().toInt(&conversionOk);
|
||||
if(!conversionOk)
|
||||
{
|
||||
@ -41,11 +43,26 @@ LogPage::LogPage(std::shared_ptr<LaunchTask> proc, QWidget *parent)
|
||||
}
|
||||
ui->text->setMaximumBlockCount(maxLines);
|
||||
|
||||
m_stopOnOverflow = MMC->settings()->get("ConsoleOverflowStop").toBool();
|
||||
}
|
||||
|
||||
// set up instance and launch process recognition
|
||||
{
|
||||
auto launchTask = m_instance->getLaunchTask();
|
||||
if(launchTask)
|
||||
{
|
||||
on_InstanceLaunchTask_changed(launchTask);
|
||||
}
|
||||
connect(m_instance.get(), &BaseInstance::launchTaskChanged,
|
||||
this, &LogPage::on_InstanceLaunchTask_changed);
|
||||
}
|
||||
|
||||
// set up text colors 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_colors.reset(new LogColorCache(origForeground, origBackground));
|
||||
|
||||
m_stopOnOverflow = MMC->settings()->get("ConsoleOverflowStop").toBool();
|
||||
}
|
||||
|
||||
auto findShortcut = new QShortcut(QKeySequence(QKeySequence::Find), this);
|
||||
connect(findShortcut, SIGNAL(activated()), SLOT(findActivated()));
|
||||
@ -62,6 +79,20 @@ LogPage::~LogPage()
|
||||
delete defaultFormat;
|
||||
}
|
||||
|
||||
void LogPage::on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> proc)
|
||||
{
|
||||
if(m_process)
|
||||
{
|
||||
disconnect(m_process.get(), &LaunchTask::log, this, &LogPage::write);
|
||||
}
|
||||
m_process = proc;
|
||||
if(m_process)
|
||||
{
|
||||
ui->text->clear();
|
||||
connect(m_process.get(), &LaunchTask::log, this, &LogPage::write);
|
||||
}
|
||||
}
|
||||
|
||||
bool LogPage::apply()
|
||||
{
|
||||
return true;
|
||||
@ -69,7 +100,7 @@ bool LogPage::apply()
|
||||
|
||||
bool LogPage::shouldDisplay() const
|
||||
{
|
||||
return m_process->instance()->isRunning();
|
||||
return m_instance->isRunning() || ui->text->blockCount() > 1;
|
||||
}
|
||||
|
||||
void LogPage::on_btnPaste_clicked()
|
||||
|
@ -34,7 +34,7 @@ class LogPage : public QWidget, public BasePage
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LogPage(std::shared_ptr<LaunchTask> proc, QWidget *parent = 0);
|
||||
explicit LogPage(InstancePtr instance, QWidget *parent = 0);
|
||||
virtual ~LogPage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
@ -77,8 +77,11 @@ private slots:
|
||||
void findNextActivated();
|
||||
void findPreviousActivated();
|
||||
|
||||
void on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> proc);
|
||||
|
||||
private:
|
||||
Ui::LogPage *ui;
|
||||
InstancePtr m_instance;
|
||||
std::shared_ptr<LaunchTask> m_process;
|
||||
int m_last_scroll_value = 0;
|
||||
bool m_scroll_active = true;
|
||||
|
@ -37,6 +37,7 @@
|
||||
<file>enderman.png</file>
|
||||
<file>herobrine.png</file>
|
||||
<file>derp.png</file>
|
||||
<file>status-running.png</file>
|
||||
|
||||
<!-- Update. GPLv2, https://code.google.com/p/gnome-colors/ -->
|
||||
<file>updateavailable.png</file>
|
||||
|
BIN
application/resources/instances/status-running.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
application/resources/multimc/16x16/status-running.png
Normal file
After Width: | Height: | Size: 675 B |
BIN
application/resources/multimc/22x22/status-running.png
Normal file
After Width: | Height: | Size: 957 B |
BIN
application/resources/multimc/24x24/status-running.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
application/resources/multimc/32x32/status-running.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
application/resources/multimc/48x48/status-running.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
application/resources/multimc/64x64/status-running.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
@ -150,6 +150,15 @@
|
||||
<file>48x48/status-yellow.png</file>
|
||||
<file>64x64/status-yellow.png</file>
|
||||
|
||||
<!-- A status icon for things that are in progress/running... Our own. -->
|
||||
<file>16x16/status-running.png</file>
|
||||
<file>24x24/status-running.png</file>
|
||||
<file>22x22/status-running.png</file>
|
||||
<file>32x32/status-running.png</file>
|
||||
<file>48x48/status-running.png</file>
|
||||
<file>64x64/status-running.png</file>
|
||||
<file>scalable/status-running.svg</file>
|
||||
|
||||
<!-- Plugin (blue recolor), CC-BY-SA 3.0, Oxygen icons. -->
|
||||
<file>16x16/loadermods.png</file>
|
||||
<file>24x24/loadermods.png</file>
|
||||
|
187
application/resources/multimc/scalable/status-running.svg
Normal file
@ -0,0 +1,187 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
width="32"
|
||||
height="32"
|
||||
id="svg2"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="status-running.svg"
|
||||
inkscape:export-filename="/home/peterix/minecraft/src/MultiMC5/application/resources/multimc/64x64/status-running.png"
|
||||
inkscape:export-xdpi="180"
|
||||
inkscape:export-ydpi="180">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2125"
|
||||
id="namedview32"
|
||||
showgrid="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-nodes="false"
|
||||
inkscape:bbox-paths="false"
|
||||
inkscape:snap-bbox-midpoints="false"
|
||||
inkscape:snap-bbox-edge-midpoints="false"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="false"
|
||||
inkscape:zoom="10.429825"
|
||||
inkscape:cx="2.5496161"
|
||||
inkscape:cy="28.936353"
|
||||
inkscape:window-x="1200"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4160"
|
||||
spacingx="0.5"
|
||||
spacingy="0.5"
|
||||
empspacing="8" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="linearGradient4162">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#0071f1;stop-opacity:1"
|
||||
id="stop4164" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#007ec3;stop-opacity:1"
|
||||
id="stop4166" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3827">
|
||||
<stop
|
||||
id="stop3829"
|
||||
style="stop-color:#b80000;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3831"
|
||||
style="stop-color:#600000;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3801">
|
||||
<stop
|
||||
id="stop3803"
|
||||
style="stop-color:#f1ab00;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3805"
|
||||
style="stop-color:#c39a00;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3005">
|
||||
<stop
|
||||
id="stop3007"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3781"
|
||||
style="stop-color:#ffffff;stop-opacity:0.49803922"
|
||||
offset="0.8142857" />
|
||||
<stop
|
||||
id="stop3009"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<filter
|
||||
color-interpolation-filters="sRGB"
|
||||
id="filter3797">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur3799"
|
||||
stdDeviation="0.52592593" />
|
||||
</filter>
|
||||
<radialGradient
|
||||
cx="3.9371533"
|
||||
cy="7.5016646"
|
||||
r="2.5"
|
||||
fx="3.9371533"
|
||||
fy="7.5016646"
|
||||
id="radialGradient3807"
|
||||
xlink:href="#linearGradient4162"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.4496779,1.5407764,-0.90127514,0.84794135,4.9906134,-4.9255796)" />
|
||||
<radialGradient
|
||||
cx="3.9371533"
|
||||
cy="7.5016646"
|
||||
r="2.5"
|
||||
fx="3.9371533"
|
||||
fy="7.5016646"
|
||||
id="radialGradient3823"
|
||||
xlink:href="#linearGradient3827"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.4496779,1.5407764,-0.90127514,0.84794135,4.9906134,-4.9255796)" />
|
||||
<radialGradient
|
||||
cx="3.9371533"
|
||||
cy="7.5016646"
|
||||
r="2.5"
|
||||
fx="3.9371533"
|
||||
fy="7.5016646"
|
||||
id="radialGradient3786"
|
||||
xlink:href="#linearGradient3801"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.4496779,1.5407764,-0.90127514,0.84794135,4.9906134,-4.9255796)" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(0,-1020.3622)"
|
||||
id="layer1">
|
||||
<path
|
||||
d="m 8,9.5 a 2.5,2.5 0 1 1 -5,0 2.5,2.5 0 1 1 5,0 z"
|
||||
transform="matrix(6.4,0,0,6.4,-19.2,975.5622)"
|
||||
id="path2997"
|
||||
style="color:#000000;fill:url(#radialGradient3807);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="M 31,16 A 15,15 0 1 1 1,16 15,15 0 1 1 31,16 z"
|
||||
transform="matrix(0.93333333,0,0,0.93333444,1.0666666,1021.4288)"
|
||||
id="path2999"
|
||||
style="color:#000000;fill:#009cff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<g
|
||||
id="g4187">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4168"
|
||||
d="m 10.455414,1028.3241 0,16.0761 L 24,1036.3622 Z"
|
||||
style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:0.95251006px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.54887217;fill:#ffffff;stroke:none"
|
||||
id="path3809-3"
|
||||
d="m 10.5,1044.3622 0,-16 13.5,8 z" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.0 KiB |
@ -60,7 +60,6 @@ PageContainer::PageContainer(BasePageProviderPtr pageProvider, QString defaultId
|
||||
createUI();
|
||||
m_model = new PageModel(this);
|
||||
m_proxyModel = new PageEntryFilterModel(this);
|
||||
int firstIndex = -1;
|
||||
int counter = 0;
|
||||
auto pages = pageProvider->getPages();
|
||||
for (auto page : pages)
|
||||
@ -69,10 +68,6 @@ PageContainer::PageContainer(BasePageProviderPtr pageProvider, QString defaultId
|
||||
page->listIndex = counter;
|
||||
page->setParentContainer(this);
|
||||
counter++;
|
||||
if (firstIndex == -1)
|
||||
{
|
||||
firstIndex = page->stackIndex;
|
||||
}
|
||||
}
|
||||
m_model->setPages(pages);
|
||||
|
||||
@ -111,6 +106,23 @@ bool PageContainer::selectPage(QString pageId)
|
||||
return false;
|
||||
}
|
||||
|
||||
void PageContainer::refresh()
|
||||
{
|
||||
m_proxyModel->invalidate();
|
||||
if(!m_currentPage->shouldDisplay())
|
||||
{
|
||||
auto index = m_proxyModel->index(0, 0);
|
||||
if(index.isValid())
|
||||
{
|
||||
m_pageList->setCurrentIndex(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: unhandled corner case: what to do when there's no page to select?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PageContainer::createUI()
|
||||
{
|
||||
m_pageStack = new QStackedLayout;
|
||||
|
@ -45,6 +45,8 @@ public:
|
||||
|
||||
virtual bool selectPage(QString pageId) override;
|
||||
|
||||
void refresh();
|
||||
|
||||
private:
|
||||
void createUI();
|
||||
private
|
||||
|