mirror of
https://github.com/UltimMC/Launcher.git
synced 2025-12-13 20:22:13 +00:00
Compare commits
31 Commits
0.6.5
...
feature/so
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b09f3448f9 | ||
|
|
ce12f1a734 | ||
|
|
c1953739d9 | ||
|
|
e8bf9cef24 | ||
|
|
8aa4b9dac5 | ||
|
|
4836ba22cd | ||
|
|
6c30076b6c | ||
|
|
83c48a0f1a | ||
|
|
d251097545 | ||
|
|
c35dbd972e | ||
|
|
0c5d121452 | ||
|
|
53ad5cb436 | ||
|
|
d87bd4b588 | ||
|
|
86850ef5d0 | ||
|
|
30fba4d407 | ||
|
|
932160818e | ||
|
|
59e1ed3d87 | ||
|
|
3470a3df96 | ||
|
|
61913daaf3 | ||
|
|
cb71dfa605 | ||
|
|
2be98baaba | ||
|
|
0ce637bf0e | ||
|
|
70ed30f9e6 | ||
|
|
414946cad9 | ||
|
|
1fc199697c | ||
|
|
9292d846b6 | ||
|
|
22db95ce3b | ||
|
|
597fe50d37 | ||
|
|
bf93ba02e9 | ||
|
|
07c1685ff1 | ||
|
|
a5e531d4f1 |
@@ -187,8 +187,7 @@ Qt::DropActions IconList::supportedDropActions() const
|
||||
return Qt::CopyAction;
|
||||
}
|
||||
|
||||
bool IconList::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
|
||||
const QModelIndex &parent)
|
||||
bool IconList::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
|
||||
{
|
||||
if (action == Qt::IgnoreAction)
|
||||
return true;
|
||||
|
||||
@@ -80,7 +80,7 @@ protected slots:
|
||||
void fileChanged(const QString &path);
|
||||
void SettingChanged(const Setting & setting, QVariant value);
|
||||
private:
|
||||
std::shared_ptr<QFileSystemWatcher> m_watcher;
|
||||
shared_qobject_ptr<QFileSystemWatcher> m_watcher;
|
||||
bool is_watching;
|
||||
QMap<QString, int> name_index;
|
||||
QVector<MMCIcon> icons;
|
||||
|
||||
@@ -102,3 +102,17 @@ void MMCIcon::replace(IconType new_type, const QString& key)
|
||||
m_images[new_type].filename = QString();
|
||||
m_images[new_type].key = key;
|
||||
}
|
||||
|
||||
QString MMCIcon::getFilePath() const
|
||||
{
|
||||
if(m_current_type == IconType::ToBeDeleted){
|
||||
return QString();
|
||||
}
|
||||
return m_images[m_current_type].filename;
|
||||
}
|
||||
|
||||
|
||||
bool MMCIcon::isBuiltIn() const
|
||||
{
|
||||
return m_current_type == IconType::Builtin;
|
||||
}
|
||||
|
||||
@@ -46,4 +46,6 @@ struct MULTIMC_GUI_EXPORT MMCIcon
|
||||
void remove(IconType rm_type);
|
||||
void replace(IconType new_type, QIcon icon, QString path = QString());
|
||||
void replace(IconType new_type, const QString &key);
|
||||
bool isBuiltIn() const;
|
||||
QString getFilePath() const;
|
||||
};
|
||||
|
||||
@@ -175,11 +175,6 @@ QString BaseInstance::instanceRoot() const
|
||||
return m_rootDir;
|
||||
}
|
||||
|
||||
InstancePtr BaseInstance::getSharedPtr()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
SettingsObjectPtr BaseInstance::settings() const
|
||||
{
|
||||
return m_settings;
|
||||
@@ -253,7 +248,7 @@ QStringList BaseInstance::extraArguments() const
|
||||
return Commandline::splitArgs(settings()->get("JvmArgs").toString());
|
||||
}
|
||||
|
||||
std::shared_ptr<LaunchTask> BaseInstance::getLaunchTask()
|
||||
shared_qobject_ptr<LaunchTask> BaseInstance::getLaunchTask()
|
||||
{
|
||||
return m_launchProcess;
|
||||
}
|
||||
|
||||
@@ -134,8 +134,6 @@ public:
|
||||
/// Sets the last launched time to 'val' milliseconds since epoch
|
||||
void setLastLaunch(qint64 val = QDateTime::currentMSecsSinceEpoch());
|
||||
|
||||
InstancePtr getSharedPtr();
|
||||
|
||||
/*!
|
||||
* \brief Gets this instance's settings object.
|
||||
* This settings object stores instance-specific settings.
|
||||
@@ -147,10 +145,10 @@ public:
|
||||
virtual shared_qobject_ptr<Task> createUpdateTask(Net::Mode mode) = 0;
|
||||
|
||||
/// returns a valid launcher (task container)
|
||||
virtual std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) = 0;
|
||||
virtual shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) = 0;
|
||||
|
||||
/// returns the current launch task (if any)
|
||||
std::shared_ptr<LaunchTask> getLaunchTask();
|
||||
shared_qobject_ptr<LaunchTask> getLaunchTask();
|
||||
|
||||
/*!
|
||||
* Create envrironment variables for running the instance
|
||||
@@ -241,7 +239,7 @@ signals:
|
||||
*/
|
||||
void propertiesChanged(BaseInstance *inst);
|
||||
|
||||
void launchTaskChanged(std::shared_ptr<LaunchTask>);
|
||||
void launchTaskChanged(shared_qobject_ptr<LaunchTask>);
|
||||
|
||||
void runningStatusChanged(bool running);
|
||||
|
||||
@@ -255,7 +253,7 @@ protected: /* data */
|
||||
SettingsObjectPtr m_settings;
|
||||
// InstanceFlags m_flags;
|
||||
bool m_isRunning = false;
|
||||
std::shared_ptr<LaunchTask> m_launchProcess;
|
||||
shared_qobject_ptr<LaunchTask> m_launchProcess;
|
||||
QDateTime m_timeStarted;
|
||||
|
||||
private: /* data */
|
||||
@@ -265,6 +263,6 @@ private: /* data */
|
||||
bool m_hasBrokenVersion = false;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<BaseInstance>)
|
||||
Q_DECLARE_METATYPE(shared_qobject_ptr<BaseInstance>)
|
||||
//Q_DECLARE_METATYPE(BaseInstance::InstanceFlag)
|
||||
//Q_DECLARE_OPERATORS_FOR_FLAGS(BaseInstance::InstanceFlags)
|
||||
|
||||
@@ -182,9 +182,11 @@ set(NEWS_SOURCES
|
||||
|
||||
# Icon interface
|
||||
set(ICONS_SOURCES
|
||||
# News System
|
||||
# Icons System and related code
|
||||
icons/IIconList.h
|
||||
icons/IIconList.cpp
|
||||
icons/IconUtils.h
|
||||
icons/IconUtils.cpp
|
||||
)
|
||||
|
||||
# Minecraft services status checker
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "NullInstance.h"
|
||||
#include "settings/INISettingsObject.h"
|
||||
#include "icons/IIconList.h"
|
||||
#include "icons/IconUtils.h"
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
// FIXME: this does not belong here, it's Minecraft/Flame specific
|
||||
@@ -393,8 +394,9 @@ void InstanceImportTask::processMultiMC()
|
||||
else
|
||||
{
|
||||
m_instIcon = instance.iconKey();
|
||||
auto importIconPath = FS::PathCombine(instance.instanceRoot(), m_instIcon + ".png");
|
||||
if (QFile::exists(importIconPath))
|
||||
|
||||
auto importIconPath = IconUtils::findBestIconIn(instance.instanceRoot(), m_instIcon);
|
||||
if (!importIconPath.isNull() && QFile::exists(importIconPath))
|
||||
{
|
||||
// import icon
|
||||
auto iconList = ENV.icons();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "BaseInstance.h"
|
||||
#include "launch/LaunchTask.h"
|
||||
|
||||
class NullInstance: public BaseInstance
|
||||
{
|
||||
@@ -11,46 +12,46 @@ public:
|
||||
setVersionBroken(true);
|
||||
}
|
||||
virtual ~NullInstance() {};
|
||||
virtual void saveNow() override
|
||||
void saveNow() override
|
||||
{
|
||||
}
|
||||
virtual QString getStatusbarDescription() override
|
||||
QString getStatusbarDescription() override
|
||||
{
|
||||
return tr("Unknown instance type");
|
||||
};
|
||||
virtual QSet< QString > traits() const override
|
||||
QSet< QString > traits() const override
|
||||
{
|
||||
return {};
|
||||
};
|
||||
virtual QString instanceConfigFolder() const override
|
||||
QString instanceConfigFolder() const override
|
||||
{
|
||||
return instanceRoot();
|
||||
};
|
||||
virtual std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr) override
|
||||
shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
virtual shared_qobject_ptr< Task > createUpdateTask(Net::Mode mode) override
|
||||
shared_qobject_ptr< Task > createUpdateTask(Net::Mode mode) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
virtual QProcessEnvironment createEnvironment() override
|
||||
QProcessEnvironment createEnvironment() override
|
||||
{
|
||||
return QProcessEnvironment();
|
||||
}
|
||||
virtual QMap<QString, QString> getVariables() const override
|
||||
QMap<QString, QString> getVariables() const override
|
||||
{
|
||||
return QMap<QString, QString>();
|
||||
}
|
||||
virtual IPathMatcher::Ptr getLogFileMatcher() override
|
||||
IPathMatcher::Ptr getLogFileMatcher() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
virtual QString getLogFileRoot() override
|
||||
QString getLogFileRoot() override
|
||||
{
|
||||
return instanceRoot();
|
||||
}
|
||||
virtual QString typeName() const override
|
||||
QString typeName() const override
|
||||
{
|
||||
return "Null";
|
||||
}
|
||||
|
||||
62
api/logic/icons/IconUtils.cpp
Normal file
62
api/logic/icons/IconUtils.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "IconUtils.h"
|
||||
|
||||
#include "FileSystem.h"
|
||||
#include <QDirIterator>
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace {
|
||||
std::array<const char *, 6> validIconExtensions = {{
|
||||
"svg",
|
||||
"png",
|
||||
"ico",
|
||||
"gif",
|
||||
"jpg",
|
||||
"jpeg"
|
||||
}};
|
||||
}
|
||||
|
||||
namespace IconUtils{
|
||||
|
||||
QString findBestIconIn(const QString &folder, const QString & iconKey) {
|
||||
int best_found = validIconExtensions.size();
|
||||
QString best_filename;
|
||||
|
||||
QDirIterator it(folder, QDir::NoDotAndDotDot | QDir::Files, QDirIterator::NoIteratorFlags);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
auto fileInfo = it.fileInfo();
|
||||
|
||||
if(fileInfo.completeBaseName() != iconKey)
|
||||
continue;
|
||||
|
||||
auto extension = fileInfo.suffix();
|
||||
|
||||
for(int i = 0; i < best_found; i++) {
|
||||
if(extension == validIconExtensions[i]) {
|
||||
best_found = i;
|
||||
qDebug() << i << " : " << fileInfo.fileName();
|
||||
best_filename = fileInfo.fileName();
|
||||
}
|
||||
}
|
||||
}
|
||||
return FS::PathCombine(folder, best_filename);
|
||||
}
|
||||
|
||||
QString getIconFilter() {
|
||||
QString out;
|
||||
QTextStream stream(&out);
|
||||
stream << '(';
|
||||
for(size_t i = 0; i < validIconExtensions.size() - 1; i++) {
|
||||
if(i > 0) {
|
||||
stream << " ";
|
||||
}
|
||||
stream << "*." << validIconExtensions[i];
|
||||
}
|
||||
stream << " *." << validIconExtensions[validIconExtensions.size() - 1];
|
||||
stream << ')';
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
14
api/logic/icons/IconUtils.h
Normal file
14
api/logic/icons/IconUtils.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include "multimc_logic_export.h"
|
||||
|
||||
namespace IconUtils {
|
||||
|
||||
// Given a folder and an icon key, find 'best' of the icons with the given key in there and return its path
|
||||
MULTIMC_LOGIC_EXPORT QString findBestIconIn(const QString &folder, const QString & iconKey);
|
||||
|
||||
// Get icon file type filter for file browser dialogs
|
||||
MULTIMC_LOGIC_EXPORT QString getIconFilter();
|
||||
|
||||
}
|
||||
@@ -75,8 +75,8 @@ void JavaChecker::stderrReady()
|
||||
void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
||||
{
|
||||
killTimer.stop();
|
||||
QProcessPtr _process;
|
||||
_process.swap(process);
|
||||
QProcessPtr _process = process;
|
||||
process.reset();
|
||||
|
||||
JavaCheckResult result;
|
||||
{
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <QTimer>
|
||||
#include <memory>
|
||||
|
||||
#include "QObjectPtr.h"
|
||||
|
||||
#include "multimc_logic_export.h"
|
||||
|
||||
#include "JavaVersion.h"
|
||||
@@ -27,8 +29,8 @@ struct MULTIMC_LOGIC_EXPORT JavaCheckResult
|
||||
} validity = Validity::Errored;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<QProcess> QProcessPtr;
|
||||
typedef std::shared_ptr<JavaChecker> JavaCheckerPtr;
|
||||
typedef shared_qobject_ptr<QProcess> QProcessPtr;
|
||||
typedef shared_qobject_ptr<JavaChecker> JavaCheckerPtr;
|
||||
class MULTIMC_LOGIC_EXPORT JavaChecker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "tasks/Task.h"
|
||||
|
||||
class JavaCheckerJob;
|
||||
typedef std::shared_ptr<JavaCheckerJob> JavaCheckerJobPtr;
|
||||
typedef shared_qobject_ptr<JavaCheckerJob> JavaCheckerJobPtr;
|
||||
|
||||
// FIXME: this just seems horribly redundant
|
||||
class JavaCheckerJob : public Task
|
||||
|
||||
@@ -149,7 +149,7 @@ void JavaListLoadTask::executeTask()
|
||||
JavaUtils ju;
|
||||
QList<QString> candidate_paths = ju.FindJavaPaths();
|
||||
|
||||
m_job = std::shared_ptr<JavaCheckerJob>(new JavaCheckerJob("Java detection"));
|
||||
m_job = new JavaCheckerJob("Java detection");
|
||||
connect(m_job.get(), &Task::finished, this, &JavaListLoadTask::javaCheckerFinished);
|
||||
connect(m_job.get(), &Task::progress, this, &Task::setProgress);
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "JavaCheckerJob.h"
|
||||
#include "JavaInstall.h"
|
||||
|
||||
#include "QObjectPtr.h"
|
||||
|
||||
#include "multimc_logic_export.h"
|
||||
|
||||
class JavaListLoadTask;
|
||||
@@ -75,7 +77,7 @@ public slots:
|
||||
void javaCheckerFinished();
|
||||
|
||||
protected:
|
||||
std::shared_ptr<JavaCheckerJob> m_job;
|
||||
shared_qobject_ptr<JavaCheckerJob> m_job;
|
||||
JavaInstallList *m_list;
|
||||
JavaInstall *m_currentRecommended;
|
||||
};
|
||||
|
||||
@@ -60,7 +60,7 @@ void CheckJava::executeTask()
|
||||
// if timestamps are not the same, or something is missing, check!
|
||||
if (javaUnixTime != storedUnixTime || storedVersion.size() == 0 || storedArchitecture.size() == 0)
|
||||
{
|
||||
m_JavaChecker = std::make_shared<JavaChecker>();
|
||||
m_JavaChecker = new JavaChecker();
|
||||
emit logLine(tr("Checking Java version..."), MessageLevel::MultiMC);
|
||||
connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, &CheckJava::checkJavaFinished);
|
||||
m_JavaChecker->m_path = realJavaPath;
|
||||
|
||||
@@ -33,9 +33,9 @@ void LaunchTask::init()
|
||||
m_instance->setRunning(true);
|
||||
}
|
||||
|
||||
std::shared_ptr<LaunchTask> LaunchTask::create(InstancePtr inst)
|
||||
shared_qobject_ptr<LaunchTask> LaunchTask::create(InstancePtr inst)
|
||||
{
|
||||
std::shared_ptr<LaunchTask> proc(new LaunchTask(inst));
|
||||
shared_qobject_ptr<LaunchTask> proc(new LaunchTask(inst));
|
||||
proc->init();
|
||||
return proc;
|
||||
}
|
||||
@@ -44,12 +44,12 @@ LaunchTask::LaunchTask(InstancePtr instance): m_instance(instance)
|
||||
{
|
||||
}
|
||||
|
||||
void LaunchTask::appendStep(std::shared_ptr<LaunchStep> step)
|
||||
void LaunchTask::appendStep(shared_qobject_ptr<LaunchStep> step)
|
||||
{
|
||||
m_steps.append(step);
|
||||
}
|
||||
|
||||
void LaunchTask::prependStep(std::shared_ptr<LaunchStep> step)
|
||||
void LaunchTask::prependStep(shared_qobject_ptr<LaunchStep> step)
|
||||
{
|
||||
m_steps.prepend(step);
|
||||
}
|
||||
|
||||
@@ -45,11 +45,11 @@ public:
|
||||
};
|
||||
|
||||
public: /* methods */
|
||||
static std::shared_ptr<LaunchTask> create(InstancePtr inst);
|
||||
static shared_qobject_ptr<LaunchTask> create(InstancePtr inst);
|
||||
virtual ~LaunchTask() {};
|
||||
|
||||
void appendStep(std::shared_ptr<LaunchStep> step);
|
||||
void prependStep(std::shared_ptr<LaunchStep> step);
|
||||
void appendStep(shared_qobject_ptr<LaunchStep> step);
|
||||
void prependStep(shared_qobject_ptr<LaunchStep> step);
|
||||
void setCensorFilter(QMap<QString, QString> filter);
|
||||
|
||||
InstancePtr instance()
|
||||
@@ -117,7 +117,7 @@ private: /*methods */
|
||||
protected: /* data */
|
||||
InstancePtr m_instance;
|
||||
shared_qobject_ptr<LogModel> m_logModel;
|
||||
QList <std::shared_ptr<LaunchStep>> m_steps;
|
||||
QList <shared_qobject_ptr<LaunchStep>> m_steps;
|
||||
QMap<QString, QString> m_censorFilter;
|
||||
int currentStep = -1;
|
||||
State state = NotStarted;
|
||||
|
||||
@@ -74,7 +74,7 @@ Meta::BaseEntity::~BaseEntity()
|
||||
|
||||
QUrl Meta::BaseEntity::url() const
|
||||
{
|
||||
return QUrl("https://v1.meta.multimc.org").resolved(localFilename());
|
||||
return QUrl("https://meta.multimc.org/v1/").resolved(localFilename());
|
||||
}
|
||||
|
||||
bool Meta::BaseEntity::loadLocalFile()
|
||||
|
||||
@@ -586,6 +586,15 @@ void ComponentUpdateTask::resolveDependencies(bool checkOnly)
|
||||
{
|
||||
component->m_version = "3.1.2";
|
||||
}
|
||||
else if (add.uid == "net.fabricmc.intermediary")
|
||||
{
|
||||
auto minecraft = std::find_if(components.begin(), components.end(), [](ComponentPtr & cmp){
|
||||
return cmp->getID() == "net.minecraft";
|
||||
});
|
||||
if(minecraft != components.end()) {
|
||||
component->m_version = (*minecraft)->getVersion();
|
||||
}
|
||||
}
|
||||
}
|
||||
// HACK HACK HACK HACK FIXME: this is a placeholder for deciding what version to use. For now, it is hardcoded.
|
||||
// ############################################################################################################
|
||||
|
||||
@@ -777,22 +777,22 @@ shared_qobject_ptr<Task> MinecraftInstance::createUpdateTask(Net::Mode mode)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPtr session)
|
||||
shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPtr session)
|
||||
{
|
||||
auto process = LaunchTask::create(std::dynamic_pointer_cast<MinecraftInstance>(getSharedPtr()));
|
||||
// FIXME: get rid of shared_from_this ...
|
||||
auto process = LaunchTask::create(std::dynamic_pointer_cast<MinecraftInstance>(shared_from_this()));
|
||||
auto pptr = process.get();
|
||||
|
||||
ENV.icons()->saveIcon(iconKey(), FS::PathCombine(gameRoot(), "icon.png"), "PNG");
|
||||
|
||||
// print a header
|
||||
{
|
||||
process->appendStep(std::make_shared<TextPrint>(pptr, "Minecraft folder is:\n" + gameRoot() + "\n\n", MessageLevel::MultiMC));
|
||||
process->appendStep(new TextPrint(pptr, "Minecraft folder is:\n" + gameRoot() + "\n\n", MessageLevel::MultiMC));
|
||||
}
|
||||
|
||||
// check java
|
||||
{
|
||||
auto step = std::make_shared<CheckJava>(pptr);
|
||||
process->appendStep(step);
|
||||
process->appendStep(new CheckJava(pptr));
|
||||
}
|
||||
|
||||
// check launch method
|
||||
@@ -800,14 +800,14 @@ std::shared_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPtr s
|
||||
QString method = launchMethod();
|
||||
if(!validMethods.contains(method))
|
||||
{
|
||||
process->appendStep(std::make_shared<TextPrint>(pptr, "Selected launch method \"" + method + "\" is not valid.\n", MessageLevel::Fatal));
|
||||
process->appendStep(new TextPrint(pptr, "Selected launch method \"" + method + "\" is not valid.\n", MessageLevel::Fatal));
|
||||
return process;
|
||||
}
|
||||
|
||||
// run pre-launch command if that's needed
|
||||
if(getPreLaunchCommand().size())
|
||||
{
|
||||
auto step = std::make_shared<PreLaunchCommand>(pptr);
|
||||
auto step = new PreLaunchCommand(pptr);
|
||||
step->setWorkingDirectory(gameRoot());
|
||||
process->appendStep(step);
|
||||
}
|
||||
@@ -815,42 +815,37 @@ std::shared_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPtr s
|
||||
// if we aren't in offline mode,.
|
||||
if(session->status != AuthSession::PlayableOffline)
|
||||
{
|
||||
process->appendStep(std::make_shared<ClaimAccount>(pptr, session));
|
||||
process->appendStep(std::make_shared<Update>(pptr, Net::Mode::Online));
|
||||
process->appendStep(new ClaimAccount(pptr, session));
|
||||
process->appendStep(new Update(pptr, Net::Mode::Online));
|
||||
}
|
||||
else
|
||||
{
|
||||
process->appendStep(std::make_shared<Update>(pptr, Net::Mode::Offline));
|
||||
process->appendStep(new Update(pptr, Net::Mode::Offline));
|
||||
}
|
||||
|
||||
// if there are any jar mods
|
||||
{
|
||||
auto step = std::make_shared<ModMinecraftJar>(pptr);
|
||||
process->appendStep(step);
|
||||
process->appendStep(new ModMinecraftJar(pptr));
|
||||
}
|
||||
|
||||
// print some instance info here...
|
||||
{
|
||||
auto step = std::make_shared<PrintInstanceInfo>(pptr, session);
|
||||
process->appendStep(step);
|
||||
process->appendStep(new PrintInstanceInfo(pptr, session));
|
||||
}
|
||||
|
||||
// create the server-resource-packs folder (workaround for Minecraft bug MCL-3732)
|
||||
{
|
||||
auto step = std::make_shared<CreateServerResourcePacksFolder>(pptr);
|
||||
process->appendStep(step);
|
||||
process->appendStep(new CreateServerResourcePacksFolder(pptr));
|
||||
}
|
||||
|
||||
// extract native jars if needed
|
||||
{
|
||||
auto step = std::make_shared<ExtractNatives>(pptr);
|
||||
process->appendStep(step);
|
||||
process->appendStep(new ExtractNatives(pptr));
|
||||
}
|
||||
|
||||
// reconstruct assets if needed
|
||||
{
|
||||
auto step = std::make_shared<ReconstructAssets>(pptr);
|
||||
process->appendStep(step);
|
||||
process->appendStep(new ReconstructAssets(pptr));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -858,14 +853,14 @@ std::shared_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPtr s
|
||||
auto method = launchMethod();
|
||||
if(method == "LauncherPart")
|
||||
{
|
||||
auto step = std::make_shared<LauncherPartLaunch>(pptr);
|
||||
auto step = new LauncherPartLaunch(pptr);
|
||||
step->setWorkingDirectory(gameRoot());
|
||||
step->setAuthSession(session);
|
||||
process->appendStep(step);
|
||||
}
|
||||
else if (method == "DirectJava")
|
||||
{
|
||||
auto step = std::make_shared<DirectJavaLaunch>(pptr);
|
||||
auto step = new DirectJavaLaunch(pptr);
|
||||
step->setWorkingDirectory(gameRoot());
|
||||
step->setAuthSession(session);
|
||||
process->appendStep(step);
|
||||
@@ -875,7 +870,7 @@ std::shared_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPtr s
|
||||
// run post-exit command if that's needed
|
||||
if(getPostExitCommand().size())
|
||||
{
|
||||
auto step = std::make_shared<PostLaunchCommand>(pptr);
|
||||
auto step = new PostLaunchCommand(pptr);
|
||||
step->setWorkingDirectory(gameRoot());
|
||||
process->appendStep(step);
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
|
||||
////// Launch stuff //////
|
||||
shared_qobject_ptr<Task> createUpdateTask(Net::Mode mode) override;
|
||||
std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) override;
|
||||
shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) override;
|
||||
QStringList extraArguments() const override;
|
||||
QStringList verboseDescription(AuthSessionPtr session) override;
|
||||
QList<Mod> getJarMods() const;
|
||||
|
||||
@@ -96,6 +96,19 @@ void Mod::repath(const QFileInfo &file)
|
||||
zip.close();
|
||||
return;
|
||||
}
|
||||
else if (zip.setCurrentFile("fabric.mod.json"))
|
||||
{
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
zip.close();
|
||||
return;
|
||||
}
|
||||
|
||||
ReadFabricModInfo(file.readAll());
|
||||
file.close();
|
||||
zip.close();
|
||||
return;
|
||||
}
|
||||
else if (zip.setCurrentFile("forgeversion.properties"))
|
||||
{
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
@@ -224,6 +237,48 @@ void Mod::ReadMCModInfo(QByteArray contents)
|
||||
}
|
||||
}
|
||||
|
||||
// https://fabricmc.net/wiki/documentation:fabric_mod_json
|
||||
void Mod::ReadFabricModInfo(QByteArray contents)
|
||||
{
|
||||
QJsonParseError jsonError;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(contents, &jsonError);
|
||||
auto object = jsonDoc.object();
|
||||
auto schemaVersion = object.contains("schemaVersion") ? object.value("schemaVersion").toInt(0) : 0;
|
||||
|
||||
m_mod_id = object.value("id").toString();
|
||||
m_version = object.value("version").toString();
|
||||
|
||||
m_name = object.contains("name") ? object.value("name").toString() : m_mod_id;
|
||||
m_description = object.value("description").toString();
|
||||
|
||||
if (schemaVersion >= 1)
|
||||
{
|
||||
QJsonArray authors = object.value("authors").toArray();
|
||||
m_authors = "";
|
||||
|
||||
for (int i = 0; i < authors.size(); i++)
|
||||
{
|
||||
QString author_name = authors.at(i).isObject()
|
||||
? authors.at(i).toObject().value("name").toString()
|
||||
: authors.at(i).toString();
|
||||
|
||||
if (i > 0)
|
||||
m_authors += ", " + author_name;
|
||||
else {
|
||||
m_authors += author_name;
|
||||
}
|
||||
}
|
||||
|
||||
if (object.contains("contact"))
|
||||
{
|
||||
QJsonObject contact = object.value("contact").toObject();
|
||||
|
||||
if (contact.contains("homepage"))
|
||||
m_homeurl = contact.value("homepage").toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Mod::ReadForgeInfo(QByteArray contents)
|
||||
{
|
||||
// Read the data
|
||||
|
||||
@@ -113,6 +113,7 @@ public:
|
||||
|
||||
private:
|
||||
void ReadMCModInfo(QByteArray contents);
|
||||
void ReadFabricModInfo(QByteArray contents);
|
||||
void ReadForgeInfo(QByteArray contents);
|
||||
void ReadLiteModInfo(QByteArray contents);
|
||||
|
||||
|
||||
@@ -123,8 +123,8 @@ bool SimpleModList::installMod(const QString &filename)
|
||||
qDebug() << "Cannot recognize mod type of" << originalPath << ", ignoring it.";
|
||||
return false;
|
||||
}
|
||||
auto newpath = FS::NormalizePath(FS::PathCombine(m_dir.path(), fileinfo.fileName()));
|
||||
|
||||
auto newpath = FS::NormalizePath(FS::PathCombine(m_dir.path(), fileinfo.fileName()));
|
||||
if(originalPath == newpath)
|
||||
{
|
||||
qDebug() << "Overwriting the mod (" << originalPath << ") with itself makes no sense...";
|
||||
@@ -133,7 +133,7 @@ bool SimpleModList::installMod(const QString &filename)
|
||||
|
||||
if (type == Mod::MOD_SINGLEFILE || type == Mod::MOD_ZIPFILE || type == Mod::MOD_LITEMOD)
|
||||
{
|
||||
if(QFile::exists(newpath))
|
||||
if(QFile::exists(newpath) || QFile::exists(newpath + QString(".disabled")))
|
||||
{
|
||||
if(!QFile::remove(newpath))
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "BaseInstance.h"
|
||||
#include "minecraft/Mod.h"
|
||||
#include "launch/LaunchTask.h"
|
||||
|
||||
#include "multimc_logic_export.h"
|
||||
|
||||
@@ -112,7 +113,7 @@ public:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) override
|
||||
shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "BaseProfiler.h"
|
||||
#include "QObjectPtr.h"
|
||||
|
||||
#include <QProcess>
|
||||
|
||||
@@ -7,7 +8,7 @@ BaseProfiler::BaseProfiler(SettingsObjectPtr settings, InstancePtr instance, QOb
|
||||
{
|
||||
}
|
||||
|
||||
void BaseProfiler::beginProfiling(std::shared_ptr<LaunchTask> process)
|
||||
void BaseProfiler::beginProfiling(shared_qobject_ptr<LaunchTask> process)
|
||||
{
|
||||
beginProfilingImpl(process);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "BaseExternalTool.h"
|
||||
#include "QObjectPtr.h"
|
||||
|
||||
#include "multimc_logic_export.h"
|
||||
|
||||
@@ -17,13 +18,13 @@ public:
|
||||
|
||||
public
|
||||
slots:
|
||||
void beginProfiling(std::shared_ptr<LaunchTask> process);
|
||||
void beginProfiling(shared_qobject_ptr<LaunchTask> process);
|
||||
void abortProfiling();
|
||||
|
||||
protected:
|
||||
QProcess *m_profilerProcess;
|
||||
|
||||
virtual void beginProfilingImpl(std::shared_ptr<LaunchTask> process) = 0;
|
||||
virtual void beginProfilingImpl(shared_qobject_ptr<LaunchTask> process) = 0;
|
||||
virtual void abortProfilingImpl();
|
||||
|
||||
signals:
|
||||
|
||||
@@ -17,7 +17,7 @@ private slots:
|
||||
void profilerFinished(int exit, QProcess::ExitStatus status);
|
||||
|
||||
protected:
|
||||
void beginProfilingImpl(std::shared_ptr<LaunchTask> process);
|
||||
void beginProfilingImpl(shared_qobject_ptr<LaunchTask> process);
|
||||
|
||||
private:
|
||||
int listeningPort = 0;
|
||||
@@ -47,7 +47,7 @@ void JProfiler::profilerFinished(int exit, QProcess::ExitStatus status)
|
||||
}
|
||||
}
|
||||
|
||||
void JProfiler::beginProfilingImpl(std::shared_ptr<LaunchTask> process)
|
||||
void JProfiler::beginProfilingImpl(shared_qobject_ptr<LaunchTask> process)
|
||||
{
|
||||
listeningPort = globalSettings->get("JProfilerPort").toInt();
|
||||
QProcess *profiler = new QProcess(this);
|
||||
|
||||
@@ -18,7 +18,7 @@ private slots:
|
||||
void profilerFinished(int exit, QProcess::ExitStatus status);
|
||||
|
||||
protected:
|
||||
void beginProfilingImpl(std::shared_ptr<LaunchTask> process);
|
||||
void beginProfilingImpl(shared_qobject_ptr<LaunchTask> process);
|
||||
};
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ void JVisualVM::profilerFinished(int exit, QProcess::ExitStatus status)
|
||||
}
|
||||
}
|
||||
|
||||
void JVisualVM::beginProfilingImpl(std::shared_ptr<LaunchTask> process)
|
||||
void JVisualVM::beginProfilingImpl(shared_qobject_ptr<LaunchTask> process)
|
||||
{
|
||||
QProcess *profiler = new QProcess(this);
|
||||
QStringList profilerArgs =
|
||||
|
||||
@@ -133,6 +133,7 @@ TranslationsModel::TranslationsModel(QString path, QObject* parent): QAbstractLi
|
||||
{
|
||||
d.reset(new Private);
|
||||
d->m_dir.setPath(path);
|
||||
FS::ensureFolderPathExists(path);
|
||||
reloadLocalFiles();
|
||||
|
||||
d->watcher = new QFileSystemWatcher(this);
|
||||
@@ -151,7 +152,7 @@ void TranslationsModel::translationDirChanged(const QString& path)
|
||||
selectLanguage(selectedLanguage());
|
||||
}
|
||||
|
||||
void TranslationsModel::indexRecieved()
|
||||
void TranslationsModel::indexReceived()
|
||||
{
|
||||
qDebug() << "Got translations index!";
|
||||
d->m_index_job.reset();
|
||||
@@ -558,7 +559,7 @@ void TranslationsModel::downloadIndex()
|
||||
d->m_index_task = Net::Download::makeCached(QUrl("https://files.multimc.org/translations/index_v2.json"), entry);
|
||||
d->m_index_job->addNetAction(d->m_index_task);
|
||||
connect(d->m_index_job.get(), &NetJob::failed, this, &TranslationsModel::indexFailed);
|
||||
connect(d->m_index_job.get(), &NetJob::succeeded, this, &TranslationsModel::indexRecieved);
|
||||
connect(d->m_index_job.get(), &NetJob::succeeded, this, &TranslationsModel::indexReceived);
|
||||
d->m_index_job->start();
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ private:
|
||||
TranslationsModel &operator=(const TranslationsModel &) = delete;
|
||||
|
||||
private slots:
|
||||
void indexRecieved();
|
||||
void indexReceived();
|
||||
void indexFailed(QString reason);
|
||||
void dlFailed(QString reason);
|
||||
void dlGood();
|
||||
|
||||
@@ -64,9 +64,6 @@ SET(MULTIMC_SOURCES
|
||||
themes/SystemTheme.cpp
|
||||
themes/SystemTheme.h
|
||||
|
||||
# GUI - settings-specific wrappers for paged dialog
|
||||
SettingsUI.h
|
||||
|
||||
# Processes
|
||||
LaunchController.h
|
||||
LaunchController.cpp
|
||||
|
||||
@@ -144,7 +144,7 @@ void InstanceWindow::on_btnLaunchMinecraftOffline_clicked()
|
||||
MMC->launch(m_instance, false, nullptr);
|
||||
}
|
||||
|
||||
void InstanceWindow::on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> proc)
|
||||
void InstanceWindow::on_InstanceLaunchTask_changed(shared_qobject_ptr<LaunchTask> proc)
|
||||
{
|
||||
m_proc = proc;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ slots:
|
||||
void on_btnKillMinecraft_clicked();
|
||||
void on_btnLaunchMinecraftOffline_clicked();
|
||||
|
||||
void on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> proc);
|
||||
void on_InstanceLaunchTask_changed(shared_qobject_ptr<LaunchTask> proc);
|
||||
void on_RunningState_changed(bool running);
|
||||
void on_instanceStatusChanged(BaseInstance::Status, BaseInstance::Status newStatus);
|
||||
|
||||
@@ -63,7 +63,7 @@ private:
|
||||
void updateLaunchButtons();
|
||||
|
||||
private:
|
||||
std::shared_ptr<LaunchTask> m_proc;
|
||||
shared_qobject_ptr<LaunchTask> m_proc;
|
||||
InstancePtr m_instance;
|
||||
bool m_doNotSave = false;
|
||||
PageContainer *m_container = nullptr;
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "InstanceWindow.h"
|
||||
#include "BuildConfig.h"
|
||||
#include "JavaCommon.h"
|
||||
#include "SettingsUI.h"
|
||||
#include <QLineEdit>
|
||||
#include <QInputDialog>
|
||||
#include <tasks/Task.h>
|
||||
@@ -53,7 +52,7 @@ void LaunchController::login()
|
||||
if (reply == QMessageBox::Yes)
|
||||
{
|
||||
// Open the account manager.
|
||||
SettingsUI::ShowPageDialog(MMC->globalSettingsPages(), m_parentWidget, "accounts");
|
||||
MMC->ShowGlobalSettings(m_parentWidget, "accounts");
|
||||
}
|
||||
}
|
||||
else if (account.get() == nullptr)
|
||||
@@ -218,7 +217,7 @@ void LaunchController::launchInstance()
|
||||
connect(m_launcher.get(), &LaunchTask::requestProgress, this, &LaunchController::onProgressRequested);
|
||||
|
||||
|
||||
m_launcher->prependStep(std::make_shared<TextPrint>(m_launcher.get(), "MultiMC version: " + BuildConfig.printableVersionString() + "\n\n", MessageLevel::MultiMC));
|
||||
m_launcher->prependStep(new TextPrint(m_launcher.get(), "MultiMC version: " + BuildConfig.printableVersionString() + "\n\n", MessageLevel::MultiMC));
|
||||
m_launcher->start();
|
||||
}
|
||||
|
||||
|
||||
@@ -57,5 +57,5 @@ private:
|
||||
QWidget * m_parentWidget = nullptr;
|
||||
InstanceWindow *m_console = nullptr;
|
||||
AuthSessionPtr m_session;
|
||||
std::shared_ptr <LaunchTask> m_launcher;
|
||||
shared_qobject_ptr<LaunchTask> m_launcher;
|
||||
};
|
||||
|
||||
@@ -70,7 +70,6 @@
|
||||
#include "InstanceProxyModel.h"
|
||||
#include "JavaCommon.h"
|
||||
#include "LaunchController.h"
|
||||
#include "SettingsUI.h"
|
||||
#include "groupview/GroupView.h"
|
||||
#include "groupview/InstanceDelegate.h"
|
||||
#include "widgets/LabeledToolButton.h"
|
||||
@@ -662,6 +661,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
|
||||
// Create the instance list widget
|
||||
{
|
||||
view = new GroupView(ui->centralWidget);
|
||||
view->setTextElideMode(Qt::TextElideMode::ElideRight);
|
||||
|
||||
view->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
// FIXME: leaks ListViewDelegate
|
||||
@@ -703,6 +703,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
|
||||
// model reset -> selection is invalid. All the instance pointers are wrong.
|
||||
connect(MMC->instances().get(), &InstanceList::dataIsInvalid, this, &MainWindow::selectionBad);
|
||||
|
||||
// When the global settings page closes, we want to know about it and update our state
|
||||
connect(MMC, &MultiMC::globalSettingsClosed, this, &MainWindow::globalSettingsClosed);
|
||||
|
||||
m_statusLeft = new QLabel(tr("No instance selected"), this);
|
||||
m_statusRight = new ServerStatus(this);
|
||||
statusBar()->addPermanentWidget(m_statusLeft, 1);
|
||||
@@ -902,15 +905,21 @@ void MainWindow::showInstanceContextMenu(const QPoint &pos)
|
||||
void MainWindow::updateToolsMenu()
|
||||
{
|
||||
QToolButton *launchButton = dynamic_cast<QToolButton*>(ui->instanceToolBar->widgetForAction(ui->actionLaunchInstance));
|
||||
QToolButton *launchOfflineButton = dynamic_cast<QToolButton*>(ui->instanceToolBar->widgetForAction(ui->actionLaunchInstanceOffline));
|
||||
|
||||
if(!m_selectedInstance || m_selectedInstance->isRunning())
|
||||
{
|
||||
ui->actionLaunchInstance->setMenu(nullptr);
|
||||
ui->actionLaunchInstanceOffline->setMenu(nullptr);
|
||||
launchButton->setPopupMode(QToolButton::InstantPopup);
|
||||
launchOfflineButton->setPopupMode(QToolButton::InstantPopup);
|
||||
return;
|
||||
}
|
||||
|
||||
QMenu *launchMenu = ui->actionLaunchInstance->menu();
|
||||
QMenu *launchOfflineMenu = ui->actionLaunchInstanceOffline->menu();
|
||||
launchButton->setPopupMode(QToolButton::MenuButtonPopup);
|
||||
launchOfflineButton->setPopupMode(QToolButton::MenuButtonPopup);
|
||||
if (launchMenu)
|
||||
{
|
||||
launchMenu->clear();
|
||||
@@ -919,21 +928,39 @@ void MainWindow::updateToolsMenu()
|
||||
{
|
||||
launchMenu = new QMenu(this);
|
||||
}
|
||||
if (launchOfflineMenu) {
|
||||
launchOfflineMenu->clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
launchOfflineMenu = new QMenu(this);
|
||||
}
|
||||
|
||||
QAction *normalLaunch = launchMenu->addAction(tr("Launch"));
|
||||
QAction *normalLaunchOffline = launchOfflineMenu->addAction(tr("Launch Offline"));
|
||||
connect(normalLaunch, &QAction::triggered, [this]()
|
||||
{
|
||||
MMC->launch(m_selectedInstance);
|
||||
MMC->launch(m_selectedInstance, true);
|
||||
});
|
||||
launchMenu->addSeparator()->setText(tr("Profilers"));
|
||||
connect(normalLaunchOffline, &QAction::triggered, [this]()
|
||||
{
|
||||
MMC->launch(m_selectedInstance, false);
|
||||
});
|
||||
QString profilersTitle = tr("Profilers");
|
||||
launchMenu->addSeparator()->setText(profilersTitle);
|
||||
launchOfflineMenu->addSeparator()->setText(profilersTitle);
|
||||
for (auto profiler : MMC->profilers().values())
|
||||
{
|
||||
QAction *profilerAction = launchMenu->addAction(profiler->name());
|
||||
QAction *profilerOfflineAction = launchOfflineMenu->addAction(profiler->name());
|
||||
QString error;
|
||||
if (!profiler->check(&error))
|
||||
{
|
||||
profilerAction->setDisabled(true);
|
||||
profilerAction->setToolTip(tr("Profiler not setup correctly. Go into settings, \"External Tools\"."));
|
||||
profilerOfflineAction->setDisabled(true);
|
||||
QString profilerToolTip = tr("Profiler not setup correctly. Go into settings, \"External Tools\".");
|
||||
profilerAction->setToolTip(profilerToolTip);
|
||||
profilerOfflineAction->setToolTip(profilerToolTip);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -941,9 +968,14 @@ void MainWindow::updateToolsMenu()
|
||||
{
|
||||
MMC->launch(m_selectedInstance, true, profiler.get());
|
||||
});
|
||||
connect(profilerOfflineAction, &QAction::triggered, [this, profiler]()
|
||||
{
|
||||
MMC->launch(m_selectedInstance, false, profiler.get());
|
||||
});
|
||||
}
|
||||
}
|
||||
ui->actionLaunchInstance->setMenu(launchMenu);
|
||||
ui->actionLaunchInstanceOffline->setMenu(launchOfflineMenu);
|
||||
}
|
||||
|
||||
QString profileInUseFilter(const QString & profile, bool used)
|
||||
@@ -1543,7 +1575,11 @@ void MainWindow::checkForUpdates()
|
||||
|
||||
void MainWindow::on_actionSettings_triggered()
|
||||
{
|
||||
SettingsUI::ShowPageDialog(MMC->globalSettingsPages(), this, "global-settings");
|
||||
MMC->ShowGlobalSettings(this, "global-settings");
|
||||
}
|
||||
|
||||
void MainWindow::globalSettingsClosed()
|
||||
{
|
||||
// FIXME: quick HACK to make this work. improve, optimize.
|
||||
MMC->instances()->loadList();
|
||||
proxymodel->invalidate();
|
||||
@@ -1579,7 +1615,7 @@ void MainWindow::on_actionScreenshots_triggered()
|
||||
|
||||
void MainWindow::on_actionManageAccounts_triggered()
|
||||
{
|
||||
SettingsUI::ShowPageDialog(MMC->globalSettingsPages(), this, "accounts");
|
||||
MMC->ShowGlobalSettings(this, "accounts");
|
||||
}
|
||||
|
||||
void MainWindow::on_actionReportBug_triggered()
|
||||
@@ -1634,7 +1670,8 @@ void MainWindow::on_actionDeleteInstance_triggered()
|
||||
tr("CAREFUL!"),
|
||||
tr("About to delete: %1\nThis is permanent and will completely delete the instance.\n\nAre you sure?").arg(m_selectedInstance->name()),
|
||||
QMessageBox::Warning,
|
||||
QMessageBox::Yes | QMessageBox::No
|
||||
QMessageBox::Yes | QMessageBox::No,
|
||||
QMessageBox::No
|
||||
)->exec();
|
||||
if (response == QMessageBox::Yes)
|
||||
{
|
||||
|
||||
@@ -181,6 +181,8 @@ private slots:
|
||||
|
||||
void konamiTriggered();
|
||||
|
||||
void globalSettingsClosed();
|
||||
|
||||
private:
|
||||
void addInstance(QString url = QString());
|
||||
void activateInstance(InstancePtr instance);
|
||||
|
||||
@@ -66,6 +66,8 @@
|
||||
#include <ganalytics.h>
|
||||
#include <sys.h>
|
||||
|
||||
#include "pagedialog/PageDialog.h"
|
||||
|
||||
|
||||
#if defined Q_OS_WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
@@ -552,7 +554,8 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
|
||||
{
|
||||
":/icons/multimc/32x32/instances/",
|
||||
":/icons/multimc/50x50/instances/",
|
||||
":/icons/multimc/128x128/instances/"
|
||||
":/icons/multimc/128x128/instances/",
|
||||
":/icons/multimc/scalable/instances/"
|
||||
};
|
||||
m_icons.reset(new IconList(instFolders, setting->get().toString()));
|
||||
connect(setting.get(), &Setting::SettingChanged,[&](const Setting &, QVariant value)
|
||||
@@ -1087,6 +1090,20 @@ void MultiMC::controllerFailed(const QString& error)
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMC::ShowGlobalSettings(class QWidget* parent, QString open_page)
|
||||
{
|
||||
if(!m_globalSettingsProvider) {
|
||||
return;
|
||||
}
|
||||
emit globalSettingsAboutToOpen();
|
||||
{
|
||||
SettingsObject::Lock lock(MMC->settings());
|
||||
PageDialog dlg(m_globalSettingsProvider.get(), open_page, parent);
|
||||
dlg.exec();
|
||||
}
|
||||
emit globalSettingsClosed();
|
||||
}
|
||||
|
||||
MainWindow* MultiMC::showMainWindow(bool minimized)
|
||||
{
|
||||
if(m_mainWindow)
|
||||
|
||||
@@ -65,11 +65,6 @@ public:
|
||||
return m_settings;
|
||||
}
|
||||
|
||||
std::shared_ptr<GenericPageProvider> globalSettingsPages() const
|
||||
{
|
||||
return m_globalSettingsProvider;
|
||||
}
|
||||
|
||||
qint64 timeSinceStart() const
|
||||
{
|
||||
return startTime.msecsTo(QDateTime::currentDateTime());
|
||||
@@ -146,8 +141,12 @@ public:
|
||||
void updateIsRunning(bool running);
|
||||
bool updatesAreAllowed();
|
||||
|
||||
void ShowGlobalSettings(class QWidget * parent, QString open_page = QString());
|
||||
|
||||
signals:
|
||||
void updateAllowedChanged(bool status);
|
||||
void globalSettingsAboutToOpen();
|
||||
void globalSettingsClosed();
|
||||
|
||||
public slots:
|
||||
bool launch(InstancePtr instance, bool online = true, BaseProfilerFactory *profiler = nullptr);
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
#include "pages/BasePageProvider.h"
|
||||
#include "MultiMC.h"
|
||||
#include "pagedialog/PageDialog.h"
|
||||
#include "InstancePageProvider.h"
|
||||
#include <settings/SettingsObject.h>
|
||||
#include <BaseInstance.h>
|
||||
|
||||
/*
|
||||
* FIXME: this is a fragment. find a better place for it.
|
||||
*/
|
||||
namespace SettingsUI
|
||||
{
|
||||
template <typename T>
|
||||
void ShowPageDialog(T raw_provider, QWidget * parent, QString open_page = QString())
|
||||
{
|
||||
auto provider = std::dynamic_pointer_cast<BasePageProvider>(raw_provider);
|
||||
if(!provider)
|
||||
return;
|
||||
{
|
||||
SettingsObject::Lock lock(MMC->settings());
|
||||
PageDialog dlg(provider.get(), open_page, parent);
|
||||
dlg.exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -343,19 +343,15 @@ void SaveIcon(InstancePtr m_instance)
|
||||
auto iconKey = m_instance->iconKey();
|
||||
auto iconList = MMC->icons();
|
||||
auto mmcIcon = iconList->icon(iconKey);
|
||||
if(mmcIcon)
|
||||
{
|
||||
bool saveIcon = false;
|
||||
switch(mmcIcon->type())
|
||||
{
|
||||
case IconType::FileBased:
|
||||
case IconType::Transient:
|
||||
saveIcon = true;
|
||||
default:
|
||||
break;
|
||||
if(!mmcIcon || mmcIcon->isBuiltIn()) {
|
||||
return;
|
||||
}
|
||||
auto path = mmcIcon->getFilePath();
|
||||
if(!path.isNull()) {
|
||||
QFileInfo inInfo (path);
|
||||
FS::copy(path, FS::PathCombine(m_instance->instanceRoot(), inInfo.fileName())) ();
|
||||
return;
|
||||
}
|
||||
if(saveIcon)
|
||||
{
|
||||
auto & image = mmcIcon->m_images[mmcIcon->type()];
|
||||
auto & icon = image.icon;
|
||||
auto sizes = icon.availableSizes();
|
||||
@@ -378,8 +374,6 @@ void SaveIcon(InstancePtr m_instance)
|
||||
}
|
||||
auto pixmap = icon.pixmap(largest);
|
||||
pixmap.save(FS::PathCombine(m_instance->instanceRoot(), iconKey + ".png"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ExportInstanceDialog::doExport()
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "groupview/InstanceDelegate.h"
|
||||
|
||||
#include "icons/IconList.h"
|
||||
#include "icons/IconUtils.h"
|
||||
#include <DesktopServices.h>
|
||||
|
||||
IconPickerDialog::IconPickerDialog(QWidget *parent)
|
||||
@@ -103,8 +104,8 @@ void IconPickerDialog::addNewIcon()
|
||||
//: The title of the select icons open file dialog
|
||||
QString selectIcons = tr("Select Icons");
|
||||
//: The type of icon files
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, selectIcons, QString(),
|
||||
tr("Icons") + "(*.png *.jpg *.jpeg *.ico *.svg *.gif)");
|
||||
auto filter = IconUtils::getIconFilter();
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, selectIcons, QString(), tr("Icons %1").arg(filter));
|
||||
MMC->icons()->installIcons(fileNames);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ static void viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &he
|
||||
height = 0;
|
||||
widthUsed = 0;
|
||||
textLayout.beginLayout();
|
||||
QString str = textLayout.text();
|
||||
while (true)
|
||||
{
|
||||
QTextLine line = textLayout.createLine();
|
||||
@@ -190,11 +189,13 @@ void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
|
||||
|
||||
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
|
||||
|
||||
// FIXME: Things go really weird with long instance names
|
||||
// const int iconSize = style->pixelMetric(QStyle::PM_IconViewIconSize);
|
||||
const int iconSize = 48;
|
||||
QRect iconbox = opt.rect;
|
||||
const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, opt.widget) + 1;
|
||||
const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr, opt.widget) + 1;
|
||||
QRect textRect = opt.rect;
|
||||
textRect.setWidth(qMin(textRect.width(), iconbox.width()));
|
||||
QRect textHighlightRect = textRect;
|
||||
// clip the decoration on top, remove width padding
|
||||
textRect.adjust(textMargin, iconSize + textMargin + 5, -textMargin, 0);
|
||||
|
||||
@@ -22,12 +22,12 @@ deploy() {
|
||||
|
||||
runmmc() {
|
||||
cd ${INSTDIR}
|
||||
./MultiMC
|
||||
./MultiMC "$@"
|
||||
}
|
||||
|
||||
if [[ ! -f ${INSTDIR}/MultiMC ]]; then
|
||||
deploy
|
||||
runmmc
|
||||
runmmc "$@"
|
||||
else
|
||||
runmmc
|
||||
runmmc "$@"
|
||||
fi
|
||||
|
||||
@@ -21,6 +21,9 @@ InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent)
|
||||
ui->setupUi(this);
|
||||
auto sysMB = Sys::getSystemRam() / Sys::megabyte;
|
||||
ui->maxMemSpinBox->setMaximum(sysMB);
|
||||
connect(ui->openGlobalJavaSettingsButton, &QCommandLinkButton::clicked, this, &InstanceSettingsPage::globalSettingsButtonClicked);
|
||||
connect(MMC, &MultiMC::globalSettingsAboutToOpen, this, &InstanceSettingsPage::applySettings);
|
||||
connect(MMC, &MultiMC::globalSettingsClosed, this, &InstanceSettingsPage::loadSettings);
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
@@ -34,6 +37,21 @@ InstanceSettingsPage::~InstanceSettingsPage()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::globalSettingsButtonClicked(bool)
|
||||
{
|
||||
switch(ui->settingsTabs->currentIndex()) {
|
||||
case 0:
|
||||
MMC->ShowGlobalSettings(this, "java-settings");
|
||||
return;
|
||||
case 1:
|
||||
MMC->ShowGlobalSettings(this, "minecraft-settings");
|
||||
return;
|
||||
case 2:
|
||||
MMC->ShowGlobalSettings(this, "custom-commands");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool InstanceSettingsPage::apply()
|
||||
{
|
||||
applySettings();
|
||||
|
||||
@@ -66,6 +66,8 @@ private slots:
|
||||
|
||||
void checkerFinished();
|
||||
|
||||
void globalSettingsButtonClicked(bool checked);
|
||||
|
||||
private:
|
||||
Ui::InstanceSettingsPage *ui;
|
||||
BaseInstance *m_instance;
|
||||
|
||||
@@ -6,23 +6,21 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>553</width>
|
||||
<height>522</height>
|
||||
<width>738</width>
|
||||
<height>804</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
<item>
|
||||
<widget class="QCommandLinkButton" name="openGlobalJavaSettingsButton">
|
||||
<property name="text">
|
||||
<string>Open Global Settings</string>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
<property name="description">
|
||||
<string>The settings here are overrides for global settings.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="settingsTabs">
|
||||
<property name="tabShape">
|
||||
@@ -367,6 +365,7 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>openGlobalJavaSettingsButton</tabstop>
|
||||
<tabstop>settingsTabs</tabstop>
|
||||
<tabstop>javaSettingsGroupBox</tabstop>
|
||||
<tabstop>javaPathTextBox</tabstop>
|
||||
|
||||
@@ -192,7 +192,7 @@ void LogPage::UIToModelState()
|
||||
m_model->suspend(ui->trackLogCheckbox->checkState() != Qt::Checked);
|
||||
}
|
||||
|
||||
void LogPage::setInstanceLaunchTaskChanged(std::shared_ptr<LaunchTask> proc, bool initial)
|
||||
void LogPage::setInstanceLaunchTaskChanged(shared_qobject_ptr<LaunchTask> proc, bool initial)
|
||||
{
|
||||
m_process = proc;
|
||||
if(m_process)
|
||||
@@ -215,7 +215,7 @@ void LogPage::setInstanceLaunchTaskChanged(std::shared_ptr<LaunchTask> proc, boo
|
||||
}
|
||||
}
|
||||
|
||||
void LogPage::onInstanceLaunchTaskChanged(std::shared_ptr<LaunchTask> proc)
|
||||
void LogPage::onInstanceLaunchTaskChanged(shared_qobject_ptr<LaunchTask> proc)
|
||||
{
|
||||
setInstanceLaunchTaskChanged(proc, false);
|
||||
}
|
||||
|
||||
@@ -69,17 +69,17 @@ private slots:
|
||||
void findNextActivated();
|
||||
void findPreviousActivated();
|
||||
|
||||
void onInstanceLaunchTaskChanged(std::shared_ptr<LaunchTask> proc);
|
||||
void onInstanceLaunchTaskChanged(shared_qobject_ptr<LaunchTask> proc);
|
||||
|
||||
private:
|
||||
void modelStateToUI();
|
||||
void UIToModelState();
|
||||
void setInstanceLaunchTaskChanged(std::shared_ptr<LaunchTask> proc, bool initial);
|
||||
void setInstanceLaunchTaskChanged(shared_qobject_ptr<LaunchTask> proc, bool initial);
|
||||
|
||||
private:
|
||||
Ui::LogPage *ui;
|
||||
InstancePtr m_instance;
|
||||
std::shared_ptr<LaunchTask> m_process;
|
||||
shared_qobject_ptr<LaunchTask> m_process;
|
||||
|
||||
LogFormatProxyModel * m_proxy;
|
||||
shared_qobject_ptr <LogModel> m_model;
|
||||
|
||||
@@ -64,8 +64,8 @@ struct Server
|
||||
|
||||
void serialize(nbt::tag_compound& server)
|
||||
{
|
||||
server.insert("name", m_name.toUtf8().toStdString());
|
||||
server.insert("ip", m_address.toUtf8().toStdString());
|
||||
server.insert("name", m_name.trimmed().toUtf8().toStdString());
|
||||
server.insert("ip", m_address.trimmed().toUtf8().toStdString());
|
||||
if(m_icon.size())
|
||||
{
|
||||
server.insert("icon", m_icon.toBase64().toStdString());
|
||||
|
||||
@@ -180,6 +180,7 @@ void VersionPage::packageCurrent(const QModelIndex ¤t, const QModelIndex &
|
||||
|
||||
void VersionPage::updateVersionControls()
|
||||
{
|
||||
ui->fabricBtn->setEnabled(true);
|
||||
ui->forgeBtn->setEnabled(true);
|
||||
ui->liteloaderBtn->setEnabled(true);
|
||||
updateButtons();
|
||||
@@ -187,6 +188,7 @@ void VersionPage::updateVersionControls()
|
||||
|
||||
void VersionPage::disableVersionControls()
|
||||
{
|
||||
ui->fabricBtn->setEnabled(false);
|
||||
ui->forgeBtn->setEnabled(false);
|
||||
ui->liteloaderBtn->setEnabled(false);
|
||||
ui->reloadBtn->setEnabled(false);
|
||||
@@ -316,6 +318,12 @@ void VersionPage::on_changeVersionBtn_clicked()
|
||||
return;
|
||||
}
|
||||
VersionSelectDialog vselect(list.get(), tr("Change %1 version").arg(name), this);
|
||||
if (uid == "net.fabricmc.intermediary")
|
||||
{
|
||||
vselect.setEmptyString(tr("No Fabric Loader versions are currently available."));
|
||||
vselect.setEmptyErrorString(tr("Couldn't load or download the Fabric Loader version lists!"));
|
||||
vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft"));
|
||||
}
|
||||
auto currentVersion = patch->getVersion();
|
||||
if(!currentVersion.isEmpty())
|
||||
{
|
||||
@@ -389,6 +397,33 @@ void VersionPage::on_forgeBtn_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
void VersionPage::on_fabricBtn_clicked()
|
||||
{
|
||||
auto vlist = ENV.metadataIndex()->get("net.fabricmc.fabric-loader");
|
||||
if(!vlist)
|
||||
{
|
||||
return;
|
||||
}
|
||||
VersionSelectDialog vselect(vlist.get(), tr("Select Fabric Loader version"), this);
|
||||
vselect.setEmptyString(tr("No Fabric Loader versions are currently available."));
|
||||
vselect.setEmptyErrorString(tr("Couldn't load or download the Fabric Loader version lists!"));
|
||||
|
||||
auto currentVersion = m_profile->getComponentVersion("net.fabricmc.fabric-loader");
|
||||
if(!currentVersion.isEmpty())
|
||||
{
|
||||
vselect.setCurrentVersion(currentVersion);
|
||||
}
|
||||
|
||||
if (vselect.exec() && vselect.selectedVersion())
|
||||
{
|
||||
auto vsn = vselect.selectedVersion();
|
||||
m_profile->setComponentVersion("net.fabricmc.fabric-loader", vsn->descriptor());
|
||||
m_profile->resolve(Net::Mode::Online);
|
||||
preselect(m_profile->rowCount(QModelIndex())-1);
|
||||
m_container->refreshContainer();
|
||||
}
|
||||
}
|
||||
|
||||
void VersionPage::on_addEmptyBtn_clicked()
|
||||
{
|
||||
NewComponentDialog compdialog(QString(), QString(), this);
|
||||
|
||||
@@ -49,6 +49,7 @@ public:
|
||||
virtual bool shouldDisplay() const override;
|
||||
|
||||
private slots:
|
||||
void on_fabricBtn_clicked();
|
||||
void on_forgeBtn_clicked();
|
||||
void on_addEmptyBtn_clicked();
|
||||
void on_liteloaderBtn_clicked();
|
||||
|
||||
@@ -170,6 +170,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fabricBtn">
|
||||
<property name="toolTip">
|
||||
<string>Install the Fabric Loader package.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Install Fabric</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="liteloaderBtn">
|
||||
<property name="toolTip">
|
||||
@@ -298,6 +308,7 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>tabWidget</tabstop>
|
||||
<tabstop>packageView</tabstop>
|
||||
<tabstop>changeVersionBtn</tabstop>
|
||||
<tabstop>moveUpBtn</tabstop>
|
||||
@@ -307,6 +318,7 @@
|
||||
<tabstop>editBtn</tabstop>
|
||||
<tabstop>revertBtn</tabstop>
|
||||
<tabstop>forgeBtn</tabstop>
|
||||
<tabstop>fabricBtn</tabstop>
|
||||
<tabstop>liteloaderBtn</tabstop>
|
||||
<tabstop>modBtn</tabstop>
|
||||
<tabstop>jarmodBtn</tabstop>
|
||||
@@ -314,7 +326,6 @@
|
||||
<tabstop>addEmptyBtn</tabstop>
|
||||
<tabstop>reloadBtn</tabstop>
|
||||
<tabstop>downloadBtn</tabstop>
|
||||
<tabstop>tabWidget</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Name=multimc
|
||||
Comment=MultiMC Default Icons
|
||||
Inherits=default
|
||||
Directories=8x8,16x16,22x22,24x24,32x32,32x32/instances,48x48,50x50/instances,64x64,128x128/instances,256x256,scalable
|
||||
Directories=8x8,16x16,22x22,24x24,32x32,32x32/instances,48x48,50x50/instances,64x64,128x128/instances,256x256,scalable,scalable/instances
|
||||
|
||||
[8x8]
|
||||
Size=8
|
||||
@@ -51,3 +51,8 @@ Size=48
|
||||
Type=Scalable
|
||||
MinSize=16
|
||||
MaxSize=256
|
||||
|
||||
[scalable/instances]
|
||||
Size=128
|
||||
MinSize=16
|
||||
MaxSize=256
|
||||
|
||||
@@ -308,5 +308,7 @@
|
||||
<file>32x32/instances/tnt.png</file>
|
||||
|
||||
<file>50x50/instances/enderman.png</file>
|
||||
|
||||
<file>scalable/instances/fox.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
290
application/resources/multimc/scalable/instances/fox.svg
Normal file
290
application/resources/multimc/scalable/instances/fox.svg
Normal file
@@ -0,0 +1,290 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<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"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 33.866666 33.866666"
|
||||
height="128"
|
||||
width="128">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<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,-263.13334)"
|
||||
id="layer1">
|
||||
<path
|
||||
id="rect4750"
|
||||
d="m 4.233333,267.36667 v 6.35 6.35 3.175 3.175 3.175 3.175 h 25.4 v -3.175 -3.175 -3.175 -3.175 -6.35 -6.35 h -6.35 v 6.35 h -12.7 v -3.175 -3.175 z"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#800000;stroke-width:0.79375;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
||||
<g
|
||||
id="g4748">
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#f9f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.19062567;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4553"
|
||||
width="6.3500032"
|
||||
height="6.3499975"
|
||||
x="4.233326"
|
||||
y="267.36667" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#b48f83;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59531283;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4553-6-2"
|
||||
width="3.1750014"
|
||||
height="3.1749992"
|
||||
x="7.4083276"
|
||||
y="270.54166" />
|
||||
<rect
|
||||
y="267.36667"
|
||||
x="23.283335"
|
||||
height="6.3499975"
|
||||
width="6.3500032"
|
||||
id="rect4623"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#f9f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.19062567;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
||||
<rect
|
||||
y="270.54166"
|
||||
x="23.283335"
|
||||
height="3.1749992"
|
||||
width="3.1750014"
|
||||
id="rect4627"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#b48f83;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59531283;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#e27c21;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59531283;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4672"
|
||||
width="25.400013"
|
||||
height="15.875009"
|
||||
x="4.233326"
|
||||
y="273.71667" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#cc6920;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59531283;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4629"
|
||||
width="3.1750016"
|
||||
height="6.3500032"
|
||||
x="4.2333255"
|
||||
y="273.71667" />
|
||||
<rect
|
||||
y="273.71667"
|
||||
x="26.458338"
|
||||
height="6.3500032"
|
||||
width="3.1750016"
|
||||
id="rect4631"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#cc6920;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59531283;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#e78f41;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59531283;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4636"
|
||||
width="6.3500032"
|
||||
height="3.1750016"
|
||||
x="13.758331"
|
||||
y="283.24167" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#b05122;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59531283;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4638"
|
||||
width="3.1750016"
|
||||
height="3.1750016"
|
||||
x="4.2333255"
|
||||
y="280.06668" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#cc6920;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59531283;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4640"
|
||||
width="3.1750016"
|
||||
height="3.1750016"
|
||||
x="7.4083276"
|
||||
y="280.06668" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#f9f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.84189939;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4644"
|
||||
width="6.3500028"
|
||||
height="3.1750016"
|
||||
x="4.233326"
|
||||
y="283.24167" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#06040e;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59531283;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4642"
|
||||
width="3.1750016"
|
||||
height="3.1750016"
|
||||
x="4.2333255"
|
||||
y="283.24167" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#f9f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.84189939;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4646"
|
||||
width="6.3500028"
|
||||
height="3.1750016"
|
||||
x="23.283337"
|
||||
y="283.24167" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#06040e;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59531283;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4648"
|
||||
width="3.1750016"
|
||||
height="3.1750016"
|
||||
x="26.45834"
|
||||
y="283.24167" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#cc6920;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59531283;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4650"
|
||||
width="3.1750016"
|
||||
height="3.1750016"
|
||||
x="23.283337"
|
||||
y="280.06668" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#b05122;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59531283;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4652"
|
||||
width="3.1750016"
|
||||
height="3.1750016"
|
||||
x="26.45834"
|
||||
y="280.06668" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#cc6920;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59531283;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4654"
|
||||
width="25.400013"
|
||||
height="3.1750016"
|
||||
x="4.2333255"
|
||||
y="286.41666" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#e7d9d3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59531283;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4656"
|
||||
width="25.400013"
|
||||
height="3.1750016"
|
||||
x="4.2333255"
|
||||
y="289.59167" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5612604;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4917"
|
||||
width="25.4"
|
||||
height="0.26457807"
|
||||
x="4.2333331"
|
||||
y="273.71667" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.48607069;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4921"
|
||||
width="0.2645835"
|
||||
height="19.049997"
|
||||
x="4.2333331"
|
||||
y="273.71667" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#f9f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.19062555;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4658"
|
||||
width="12.700007"
|
||||
height="6.3500013"
|
||||
x="10.583333"
|
||||
y="286.41666" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#06040e;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.19062555;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4660"
|
||||
width="6.3500037"
|
||||
height="3.1750007"
|
||||
x="13.758333"
|
||||
y="286.41669" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#e7d9d3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.19062555;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4662"
|
||||
width="3.1750019"
|
||||
height="3.1750007"
|
||||
x="10.583333"
|
||||
y="286.41669" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#e7d9d3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.19062555;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4664"
|
||||
width="3.1750019"
|
||||
height="3.1750007"
|
||||
x="20.108334"
|
||||
y="286.41669" />
|
||||
<rect
|
||||
y="286.41669"
|
||||
x="10.583333"
|
||||
height="6.3499832"
|
||||
width="0.2645835"
|
||||
id="rect4923"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2806327;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.39686465;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4951"
|
||||
width="12.699996"
|
||||
height="0.26456967"
|
||||
x="10.583333"
|
||||
y="286.41669" />
|
||||
<rect
|
||||
y="273.71667"
|
||||
x="29.36875"
|
||||
height="19.049982"
|
||||
width="0.26458356"
|
||||
id="rect4953"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.48607057;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
||||
<rect
|
||||
y="292.50208"
|
||||
x="23.283333"
|
||||
height="0.26457682"
|
||||
width="6.3499994"
|
||||
id="rect4957"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28062955;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2806325;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4959"
|
||||
width="0.2645838"
|
||||
height="6.3499656"
|
||||
x="23.018749"
|
||||
y="286.41669" />
|
||||
<rect
|
||||
y="292.50208"
|
||||
x="4.2333331"
|
||||
height="0.26457968"
|
||||
width="6.3499999"
|
||||
id="rect4961"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28063107;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
||||
<rect
|
||||
y="267.36667"
|
||||
x="4.2333331"
|
||||
height="6.3499956"
|
||||
width="0.2645835"
|
||||
id="rect4963"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28063297;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28063536;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4965"
|
||||
width="6.349998"
|
||||
height="0.26458791"
|
||||
x="4.2333331"
|
||||
y="267.36667" />
|
||||
<rect
|
||||
y="267.36667"
|
||||
x="23.283333"
|
||||
height="6.3499956"
|
||||
width="0.2645835"
|
||||
id="rect4963-9"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.280633;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28063536;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4965-1"
|
||||
width="6.349998"
|
||||
height="0.26458791"
|
||||
x="23.283333"
|
||||
y="267.36667" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28063306;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect4985"
|
||||
width="0.26458356"
|
||||
height="6.3499975"
|
||||
x="29.36875"
|
||||
y="267.36667" />
|
||||
<rect
|
||||
y="267.36667"
|
||||
x="10.318749"
|
||||
height="6.3499975"
|
||||
width="0.26458356"
|
||||
id="rect4987"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28063306;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 18 KiB |
Reference in New Issue
Block a user