Merge branch 'develop' into feat/launcher-updater
4
.git-blame-ignore-revs
Normal file
@ -0,0 +1,4 @@
|
||||
# .git-blame-ignore-revs
|
||||
|
||||
# tabs -> spaces
|
||||
bbb3b3e6f6e3c0f95873f22e6d0a4aaf350f49d9
|
@ -697,7 +697,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
|
||||
// Java Settings
|
||||
m_settings->registerSetting("JavaPath", "");
|
||||
m_settings->registerSetting("JavaTimestamp", 0);
|
||||
m_settings->registerSetting("JavaSignature", "");
|
||||
m_settings->registerSetting("JavaArchitecture", "");
|
||||
m_settings->registerSetting("JavaRealArchitecture", "");
|
||||
m_settings->registerSetting("JavaVersion", "");
|
||||
|
@ -389,8 +389,6 @@ set(MINECRAFT_SOURCES
|
||||
minecraft/services/SkinDelete.cpp
|
||||
minecraft/services/SkinDelete.h
|
||||
|
||||
mojang/PackageManifest.h
|
||||
mojang/PackageManifest.cpp
|
||||
minecraft/Agent.h)
|
||||
|
||||
# the screenshots feature
|
||||
@ -752,6 +750,7 @@ SET(LAUNCHER_SOURCES
|
||||
VersionProxyModel.h
|
||||
VersionProxyModel.cpp
|
||||
Markdown.h
|
||||
Markdown.cpp
|
||||
|
||||
# Super secret!
|
||||
KonamiCode.h
|
||||
@ -895,8 +894,8 @@ SET(LAUNCHER_SOURCES
|
||||
ui/pages/global/APIPage.h
|
||||
|
||||
# GUI - platform pages
|
||||
ui/pages/modplatform/VanillaPage.cpp
|
||||
ui/pages/modplatform/VanillaPage.h
|
||||
ui/pages/modplatform/CustomPage.cpp
|
||||
ui/pages/modplatform/CustomPage.h
|
||||
|
||||
ui/pages/modplatform/ResourcePage.cpp
|
||||
ui/pages/modplatform/ResourcePage.h
|
||||
@ -1111,7 +1110,7 @@ qt_wrap_ui(LAUNCHER_UI
|
||||
ui/pages/instance/ScreenshotsPage.ui
|
||||
ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui
|
||||
ui/pages/modplatform/atlauncher/AtlPage.ui
|
||||
ui/pages/modplatform/VanillaPage.ui
|
||||
ui/pages/modplatform/CustomPage.ui
|
||||
ui/pages/modplatform/ResourcePage.ui
|
||||
ui/pages/modplatform/flame/FlamePage.ui
|
||||
ui/pages/modplatform/legacy_ftb/Page.ui
|
||||
|
@ -406,7 +406,7 @@ void create_link::make_link_list(const QString& offset)
|
||||
auto src_path = source_it.next();
|
||||
auto relative_path = src_dir.relativeFilePath(src_path);
|
||||
|
||||
if (m_max_depth >= 0 && pathDepth(relative_path) > m_max_depth){
|
||||
if (m_max_depth >= 0 && pathDepth(relative_path) > m_max_depth) {
|
||||
relative_path = pathTruncate(relative_path, m_max_depth);
|
||||
src_path = src_dir.filePath(relative_path);
|
||||
if (linkedPaths.contains(src_path)) {
|
||||
@ -697,7 +697,7 @@ QString pathTruncate(const QString& path, int depth)
|
||||
|
||||
QString trunc = QFileInfo(path).path();
|
||||
|
||||
if (pathDepth(trunc) > depth ) {
|
||||
if (pathDepth(trunc) > depth) {
|
||||
return pathTruncate(trunc, depth);
|
||||
}
|
||||
|
||||
@ -803,6 +803,9 @@ QString getDesktopDir()
|
||||
// Cross-platform Shortcut creation
|
||||
bool createShortcut(QString destination, QString target, QStringList args, QString name, QString icon)
|
||||
{
|
||||
if (destination.isEmpty()) {
|
||||
destination = PathCombine(getDesktopDir(), RemoveInvalidFilenameChars(name));
|
||||
}
|
||||
#if defined(Q_OS_MACOS)
|
||||
destination += ".command";
|
||||
|
||||
@ -825,6 +828,8 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
|
||||
|
||||
return true;
|
||||
#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
||||
if (!destination.endsWith(".desktop")) // in case of isFlatpak destination is already populated
|
||||
destination += ".desktop";
|
||||
QFile f(destination);
|
||||
f.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
QTextStream stream(&f);
|
||||
@ -1008,7 +1013,7 @@ FilesystemType getFilesystemType(const QString& name)
|
||||
{
|
||||
for (auto iter = s_filesystem_type_names.constBegin(); iter != s_filesystem_type_names.constEnd(); ++iter) {
|
||||
auto fs_names = iter.value();
|
||||
if(fs_names.contains(name.toUpper()))
|
||||
if (fs_names.contains(name.toUpper()))
|
||||
return iter.key();
|
||||
}
|
||||
return FilesystemType::UNKNOWN;
|
||||
|
31
launcher/Markdown.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2023 Joshua Goins <josh@redstrate.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Markdown.h"
|
||||
|
||||
QString markdownToHTML(const QString& markdown)
|
||||
{
|
||||
const QByteArray markdownData = markdown.toUtf8();
|
||||
char* buffer = cmark_markdown_to_html(markdownData.constData(), markdownData.length(), CMARK_OPT_NOBREAKS | CMARK_OPT_UNSAFE);
|
||||
|
||||
QString htmlStr(buffer);
|
||||
|
||||
free(buffer);
|
||||
|
||||
return htmlStr;
|
||||
}
|
@ -21,14 +21,4 @@
|
||||
#include <QString>
|
||||
#include <cmark.h>
|
||||
|
||||
static QString markdownToHTML(const QString& markdown)
|
||||
{
|
||||
const QByteArray markdownData = markdown.toUtf8();
|
||||
char* buffer = cmark_markdown_to_html(markdownData.constData(), markdownData.length(), CMARK_OPT_NOBREAKS | CMARK_OPT_UNSAFE);
|
||||
|
||||
QString htmlStr(buffer);
|
||||
|
||||
free(buffer);
|
||||
|
||||
return htmlStr;
|
||||
}
|
||||
QString markdownToHTML(const QString& markdown);
|
@ -81,15 +81,20 @@ void CheckJava::executeTask()
|
||||
}
|
||||
|
||||
QFileInfo javaInfo(realJavaPath);
|
||||
qlonglong javaUnixTime = javaInfo.lastModified().toMSecsSinceEpoch();
|
||||
auto storedUnixTime = settings->get("JavaTimestamp").toLongLong();
|
||||
qint64 javaUnixTime = javaInfo.lastModified().toMSecsSinceEpoch();
|
||||
auto storedSignature = settings->get("JavaSignature").toString();
|
||||
auto storedArchitecture = settings->get("JavaArchitecture").toString();
|
||||
auto storedRealArchitecture = settings->get("JavaRealArchitecture").toString();
|
||||
auto storedVersion = settings->get("JavaVersion").toString();
|
||||
auto storedVendor = settings->get("JavaVendor").toString();
|
||||
m_javaUnixTime = javaUnixTime;
|
||||
|
||||
QCryptographicHash hash(QCryptographicHash::Sha1);
|
||||
hash.addData(QByteArray::number(javaUnixTime));
|
||||
hash.addData(m_javaPath.toUtf8());
|
||||
m_javaSignature = hash.result().toHex();
|
||||
|
||||
// if timestamps are not the same, or something is missing, check!
|
||||
if (javaUnixTime != storedUnixTime || storedVersion.size() == 0
|
||||
if (m_javaSignature != storedSignature || storedVersion.size() == 0
|
||||
|| storedArchitecture.size() == 0 || storedRealArchitecture.size() == 0
|
||||
|| storedVendor.size() == 0)
|
||||
{
|
||||
@ -140,7 +145,7 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
|
||||
instance->settings()->set("JavaArchitecture", result.mojangPlatform);
|
||||
instance->settings()->set("JavaRealArchitecture", result.realPlatform);
|
||||
instance->settings()->set("JavaVendor", result.javaVendor);
|
||||
instance->settings()->set("JavaTimestamp", m_javaUnixTime);
|
||||
instance->settings()->set("JavaSignature", m_javaSignature);
|
||||
emitSucceeded();
|
||||
return;
|
||||
}
|
||||
|
@ -40,6 +40,6 @@ private:
|
||||
|
||||
private:
|
||||
QString m_javaPath;
|
||||
qlonglong m_javaUnixTime;
|
||||
QString m_javaSignature;
|
||||
JavaCheckerPtr m_JavaChecker;
|
||||
};
|
||||
|
@ -148,7 +148,7 @@ void MinecraftInstance::loadSpecificSettings()
|
||||
m_settings->registerOverride(global_settings->getSetting("IgnoreJavaCompatibility"), javaOrLocation);
|
||||
|
||||
// special!
|
||||
m_settings->registerPassthrough(global_settings->getSetting("JavaTimestamp"), javaOrLocation);
|
||||
m_settings->registerPassthrough(global_settings->getSetting("JavaSignature"), javaOrLocation);
|
||||
m_settings->registerPassthrough(global_settings->getSetting("JavaArchitecture"), javaOrLocation);
|
||||
m_settings->registerPassthrough(global_settings->getSetting("JavaRealArchitecture"), javaOrLocation);
|
||||
m_settings->registerPassthrough(global_settings->getSetting("JavaVersion"), javaOrLocation);
|
||||
|
@ -1,427 +0,0 @@
|
||||
#include "PackageManifest.h"
|
||||
#include <Json.h>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDebug>
|
||||
|
||||
#ifndef Q_OS_WIN32
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
namespace mojang_files {
|
||||
|
||||
const Hash hash_of_empty_string = "da39a3ee5e6b4b0d3255bfef95601890afd80709";
|
||||
|
||||
int Path::compare(const Path& rhs) const
|
||||
{
|
||||
auto left_cursor = begin();
|
||||
auto left_end = end();
|
||||
auto right_cursor = rhs.begin();
|
||||
auto right_end = rhs.end();
|
||||
|
||||
while (left_cursor != left_end && right_cursor != right_end)
|
||||
{
|
||||
if(*left_cursor < *right_cursor)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if(*left_cursor > *right_cursor)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
left_cursor++;
|
||||
right_cursor++;
|
||||
}
|
||||
|
||||
if(left_cursor == left_end)
|
||||
{
|
||||
if(right_cursor == right_end)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Package::addFile(const Path& path, const File& file) {
|
||||
addFolder(path.parent_path());
|
||||
files[path] = file;
|
||||
}
|
||||
|
||||
void Package::addFolder(Path folder) {
|
||||
if(!folder.has_parent_path()) {
|
||||
return;
|
||||
}
|
||||
do {
|
||||
folders.insert(folder);
|
||||
folder = folder.parent_path();
|
||||
} while(folder.has_parent_path());
|
||||
}
|
||||
|
||||
void Package::addLink(const Path& path, const Path& target) {
|
||||
addFolder(path.parent_path());
|
||||
symlinks[path] = target;
|
||||
}
|
||||
|
||||
void Package::addSource(const FileSource& source) {
|
||||
sources[source.hash] = source;
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
void fromJson(QJsonDocument & doc, Package & out) {
|
||||
std::set<Path> seen_paths;
|
||||
if (!doc.isObject())
|
||||
{
|
||||
throw JSONValidationError("file manifest is not an object");
|
||||
}
|
||||
QJsonObject root = doc.object();
|
||||
|
||||
auto filesObj = Json::ensureObject(root, "files");
|
||||
auto iter = filesObj.begin();
|
||||
while (iter != filesObj.end())
|
||||
{
|
||||
Path objectPath = Path(iter.key());
|
||||
auto value = iter.value();
|
||||
iter++;
|
||||
if(seen_paths.count(objectPath)) {
|
||||
throw JSONValidationError("duplicate path inside manifest, the manifest is invalid");
|
||||
}
|
||||
if (!value.isObject())
|
||||
{
|
||||
throw JSONValidationError("file entry inside manifest is not an an object");
|
||||
}
|
||||
seen_paths.insert(objectPath);
|
||||
|
||||
auto fileObject = value.toObject();
|
||||
auto type = Json::requireString(fileObject, "type");
|
||||
if(type == "directory") {
|
||||
out.addFolder(objectPath);
|
||||
continue;
|
||||
}
|
||||
else if(type == "file") {
|
||||
FileSource bestSource;
|
||||
File file;
|
||||
file.executable = Json::ensureBoolean(fileObject, QString("executable"), false);
|
||||
auto downloads = Json::requireObject(fileObject, "downloads");
|
||||
for(auto iter2 = downloads.begin(); iter2 != downloads.end(); iter2++) {
|
||||
FileSource source;
|
||||
|
||||
auto downloadObject = Json::requireObject(iter2.value());
|
||||
source.hash = Json::requireString(downloadObject, "sha1");
|
||||
source.size = Json::requireInteger(downloadObject, "size");
|
||||
source.url = Json::requireString(downloadObject, "url");
|
||||
|
||||
auto compression = iter2.key();
|
||||
if(compression == "raw") {
|
||||
file.hash = source.hash;
|
||||
file.size = source.size;
|
||||
source.compression = Compression::Raw;
|
||||
}
|
||||
else if (compression == "lzma") {
|
||||
source.compression = Compression::Lzma;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
bestSource.upgrade(source);
|
||||
}
|
||||
if(bestSource.isBad()) {
|
||||
throw JSONValidationError("No valid compression method for file " + iter.key());
|
||||
}
|
||||
out.addFile(objectPath, file);
|
||||
out.addSource(bestSource);
|
||||
}
|
||||
else if(type == "link") {
|
||||
auto target = Json::requireString(fileObject, "target");
|
||||
out.symlinks[objectPath] = target;
|
||||
out.addLink(objectPath, target);
|
||||
}
|
||||
else {
|
||||
throw JSONValidationError("Invalid item type in manifest: " + type);
|
||||
}
|
||||
}
|
||||
// make sure the containing folder exists
|
||||
out.folders.insert(Path());
|
||||
}
|
||||
}
|
||||
|
||||
Package Package::fromManifestContents(const QByteArray& contents)
|
||||
{
|
||||
Package out;
|
||||
try
|
||||
{
|
||||
auto doc = Json::requireDocument(contents, "Manifest");
|
||||
fromJson(doc, out);
|
||||
return out;
|
||||
}
|
||||
catch (const Exception &e)
|
||||
{
|
||||
qDebug() << QString("Unable to parse manifest: %1").arg(e.cause());
|
||||
out.valid = false;
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
Package Package::fromManifestFile(const QString & filename) {
|
||||
Package out;
|
||||
try
|
||||
{
|
||||
auto doc = Json::requireDocument(filename, filename);
|
||||
fromJson(doc, out);
|
||||
return out;
|
||||
}
|
||||
catch (const Exception &e)
|
||||
{
|
||||
qDebug() << QString("Unable to parse manifest file %1: %2").arg(filename, e.cause());
|
||||
out.valid = false;
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef Q_OS_WIN32
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace {
|
||||
// FIXME: Qt obscures symlink targets by making them absolute. that is useless. this is the workaround - we do it ourselves
|
||||
bool actually_read_symlink_target(const QString & filepath, Path & out)
|
||||
{
|
||||
struct ::stat st;
|
||||
// FIXME: here, we assume the native filesystem encoding. May the Gods have mercy upon our Souls.
|
||||
QByteArray nativePath = filepath.toUtf8();
|
||||
const char * filepath_cstr = nativePath.data();
|
||||
|
||||
if (lstat(filepath_cstr, &st) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto size = st.st_size ? st.st_size + 1 : PATH_MAX;
|
||||
std::string temp(size, '\0');
|
||||
// because we don't realiably know how long the damn thing actually is, we loop and expand. POSIX is naff
|
||||
do
|
||||
{
|
||||
auto link_length = ::readlink(filepath_cstr, &temp[0], temp.size());
|
||||
if(link_length == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(std::string::size_type(link_length) < temp.size())
|
||||
{
|
||||
// buffer was long enough and we managed to read the link target. RETURN here.
|
||||
temp.resize(link_length);
|
||||
out = Path(QString::fromUtf8(temp.c_str()));
|
||||
return true;
|
||||
}
|
||||
temp.resize(temp.size() * 2);
|
||||
} while (true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// FIXME: Qt filesystem abstraction is bad, but ... let's hope it doesn't break too much?
|
||||
// FIXME: The error handling is just DEFICIENT
|
||||
Package Package::fromInspectedFolder(const QString& folderPath)
|
||||
{
|
||||
QDir root(folderPath);
|
||||
|
||||
Package out;
|
||||
QDirIterator iterator(folderPath, QDir::NoDotAndDotDot | QDir::AllEntries | QDir::System | QDir::Hidden, QDirIterator::Subdirectories);
|
||||
while(iterator.hasNext()) {
|
||||
iterator.next();
|
||||
|
||||
auto fileInfo = iterator.fileInfo();
|
||||
auto relPath = root.relativeFilePath(fileInfo.filePath());
|
||||
// FIXME: this is probably completely busted on Windows anyway, so just disable it.
|
||||
// Qt makes shit up and doesn't understand the platform details
|
||||
// TODO: Actually use a filesystem library that isn't terrible and has decen license.
|
||||
// I only know one, and I wrote it. Sadly, currently proprietary. PAIN.
|
||||
#ifndef Q_OS_WIN32
|
||||
if(fileInfo.isSymLink()) {
|
||||
Path targetPath;
|
||||
if(!actually_read_symlink_target(fileInfo.filePath(), targetPath)) {
|
||||
qCritical() << "Folder inspection: Unknown filesystem object:" << fileInfo.absoluteFilePath();
|
||||
out.valid = false;
|
||||
}
|
||||
out.addLink(relPath, targetPath);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if(fileInfo.isDir()) {
|
||||
out.addFolder(relPath);
|
||||
}
|
||||
else if(fileInfo.isFile()) {
|
||||
File f;
|
||||
f.executable = fileInfo.isExecutable();
|
||||
f.size = fileInfo.size();
|
||||
// FIXME: async / optimize the hashing
|
||||
QFile input(fileInfo.absoluteFilePath());
|
||||
if(!input.open(QIODevice::ReadOnly)) {
|
||||
qCritical() << "Folder inspection: Failed to open file:" << fileInfo.absoluteFilePath();
|
||||
out.valid = false;
|
||||
break;
|
||||
}
|
||||
f.hash = QCryptographicHash::hash(input.readAll(), QCryptographicHash::Sha1).toHex().constData();
|
||||
out.addFile(relPath, f);
|
||||
}
|
||||
else {
|
||||
// Something else... oh my
|
||||
qCritical() << "Folder inspection: Unknown filesystem object:" << fileInfo.absoluteFilePath();
|
||||
out.valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
out.folders.insert(Path("."));
|
||||
out.valid = true;
|
||||
return out;
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct shallow_first_sort
|
||||
{
|
||||
bool operator()(const Path &lhs, const Path &rhs) const
|
||||
{
|
||||
auto lhs_depth = lhs.length();
|
||||
auto rhs_depth = rhs.length();
|
||||
if(lhs_depth < rhs_depth)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if(lhs_depth == rhs_depth)
|
||||
{
|
||||
if(lhs < rhs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct deep_first_sort
|
||||
{
|
||||
bool operator()(const Path &lhs, const Path &rhs) const
|
||||
{
|
||||
auto lhs_depth = lhs.length();
|
||||
auto rhs_depth = rhs.length();
|
||||
if(lhs_depth > rhs_depth)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if(lhs_depth == rhs_depth)
|
||||
{
|
||||
if(lhs < rhs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
UpdateOperations UpdateOperations::resolve(const Package& from, const Package& to)
|
||||
{
|
||||
UpdateOperations out;
|
||||
|
||||
if(!from.valid || !to.valid) {
|
||||
out.valid = false;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Files
|
||||
for(auto iter = from.files.begin(); iter != from.files.end(); iter++) {
|
||||
const auto ¤t_hash = iter->second.hash;
|
||||
const auto ¤t_executable = iter->second.executable;
|
||||
const auto &path = iter->first;
|
||||
|
||||
auto iter2 = to.files.find(path);
|
||||
if(iter2 == to.files.end()) {
|
||||
// removed
|
||||
out.deletes.push_back(path);
|
||||
continue;
|
||||
}
|
||||
auto new_hash = iter2->second.hash;
|
||||
auto new_executable = iter2->second.executable;
|
||||
if (current_hash != new_hash) {
|
||||
out.deletes.push_back(path);
|
||||
out.downloads.emplace(
|
||||
std::pair<Path, FileDownload>{
|
||||
path,
|
||||
FileDownload(to.sources.at(iter2->second.hash), iter2->second.executable)
|
||||
}
|
||||
);
|
||||
}
|
||||
else if (current_executable != new_executable) {
|
||||
out.executable_fixes[path] = new_executable;
|
||||
}
|
||||
}
|
||||
for(auto iter = to.files.begin(); iter != to.files.end(); iter++) {
|
||||
auto path = iter->first;
|
||||
if(!from.files.count(path)) {
|
||||
out.downloads.emplace(
|
||||
std::pair<Path, FileDownload>{
|
||||
path,
|
||||
FileDownload(to.sources.at(iter->second.hash), iter->second.executable)
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Folders
|
||||
std::set<Path, deep_first_sort> remove_folders;
|
||||
std::set<Path, shallow_first_sort> make_folders;
|
||||
for(auto from_path: from.folders) {
|
||||
auto iter = to.folders.find(from_path);
|
||||
if(iter == to.folders.end()) {
|
||||
remove_folders.insert(from_path);
|
||||
}
|
||||
}
|
||||
for(auto & rmdir: remove_folders) {
|
||||
out.rmdirs.push_back(rmdir);
|
||||
}
|
||||
for(auto to_path: to.folders) {
|
||||
auto iter = from.folders.find(to_path);
|
||||
if(iter == from.folders.end()) {
|
||||
make_folders.insert(to_path);
|
||||
}
|
||||
}
|
||||
for(auto & mkdir: make_folders) {
|
||||
out.mkdirs.push_back(mkdir);
|
||||
}
|
||||
|
||||
// Symlinks
|
||||
for(auto iter = from.symlinks.begin(); iter != from.symlinks.end(); iter++) {
|
||||
const auto ¤t_target = iter->second;
|
||||
const auto &path = iter->first;
|
||||
|
||||
auto iter2 = to.symlinks.find(path);
|
||||
if(iter2 == to.symlinks.end()) {
|
||||
// removed
|
||||
out.deletes.push_back(path);
|
||||
continue;
|
||||
}
|
||||
const auto &new_target = iter2->second;
|
||||
if (current_target != new_target) {
|
||||
out.deletes.push_back(path);
|
||||
out.mklinks[path] = iter2->second;
|
||||
}
|
||||
}
|
||||
for(auto iter = to.symlinks.begin(); iter != to.symlinks.end(); iter++) {
|
||||
auto path = iter->first;
|
||||
if(!from.symlinks.count(path)) {
|
||||
out.mklinks[path] = iter->second;
|
||||
}
|
||||
}
|
||||
out.valid = true;
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
@ -1,171 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <QStringList>
|
||||
#include "tasks/Task.h"
|
||||
|
||||
namespace mojang_files {
|
||||
|
||||
using Hash = QString;
|
||||
extern const Hash empty_hash;
|
||||
|
||||
// simple-ish path implementation. assumes always relative and does not allow '..' entries
|
||||
class Path
|
||||
{
|
||||
public:
|
||||
using parts_type = QStringList;
|
||||
|
||||
Path() = default;
|
||||
Path(QString string) {
|
||||
auto parts_in = string.split('/');
|
||||
for(auto & part: parts_in) {
|
||||
if(part.isEmpty() || part == ".") {
|
||||
continue;
|
||||
}
|
||||
if(part == "..") {
|
||||
if(parts.size()) {
|
||||
parts.pop_back();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
parts.push_back(part);
|
||||
}
|
||||
}
|
||||
|
||||
bool has_parent_path() const
|
||||
{
|
||||
return parts.size() > 0;
|
||||
}
|
||||
|
||||
Path parent_path() const
|
||||
{
|
||||
if (parts.empty())
|
||||
return Path();
|
||||
return Path(parts.begin(), std::prev(parts.end()));
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return parts.empty();
|
||||
}
|
||||
|
||||
int length() const
|
||||
{
|
||||
return parts.length();
|
||||
}
|
||||
|
||||
bool operator==(const Path & rhs) const {
|
||||
return parts == rhs.parts;
|
||||
}
|
||||
|
||||
bool operator!=(const Path & rhs) const {
|
||||
return parts != rhs.parts;
|
||||
}
|
||||
|
||||
inline bool operator<(const Path& rhs) const
|
||||
{
|
||||
return compare(rhs) < 0;
|
||||
}
|
||||
|
||||
parts_type::const_iterator begin() const
|
||||
{
|
||||
return parts.begin();
|
||||
}
|
||||
|
||||
parts_type::const_iterator end() const
|
||||
{
|
||||
return parts.end();
|
||||
}
|
||||
|
||||
QString toString() const {
|
||||
return parts.join("/");
|
||||
}
|
||||
|
||||
private:
|
||||
Path(const parts_type::const_iterator & start, const parts_type::const_iterator & end) {
|
||||
auto cursor = start;
|
||||
while(cursor != end) {
|
||||
parts.push_back(*cursor);
|
||||
cursor++;
|
||||
}
|
||||
}
|
||||
int compare(const Path& p) const;
|
||||
|
||||
parts_type parts;
|
||||
};
|
||||
|
||||
|
||||
enum class Compression {
|
||||
Raw,
|
||||
Lzma,
|
||||
Unknown
|
||||
};
|
||||
|
||||
|
||||
struct FileSource
|
||||
{
|
||||
Compression compression = Compression::Unknown;
|
||||
Hash hash;
|
||||
QString url;
|
||||
std::size_t size = 0;
|
||||
void upgrade(const FileSource & other) {
|
||||
if(compression == Compression::Unknown || other.size < size) {
|
||||
*this = other;
|
||||
}
|
||||
}
|
||||
bool isBad() const {
|
||||
return compression == Compression::Unknown;
|
||||
}
|
||||
};
|
||||
|
||||
struct File
|
||||
{
|
||||
Hash hash;
|
||||
bool executable;
|
||||
std::uint64_t size = 0;
|
||||
};
|
||||
|
||||
struct Package {
|
||||
static Package fromInspectedFolder(const QString &folderPath);
|
||||
static Package fromManifestFile(const QString &path);
|
||||
static Package fromManifestContents(const QByteArray& contents);
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return valid;
|
||||
}
|
||||
void addFolder(Path folder);
|
||||
void addFile(const Path & path, const File & file);
|
||||
void addLink(const Path & path, const Path & target);
|
||||
void addSource(const FileSource & source);
|
||||
|
||||
std::map<Hash, FileSource> sources;
|
||||
bool valid = true;
|
||||
std::set<Path> folders;
|
||||
std::map<Path, File> files;
|
||||
std::map<Path, Path> symlinks;
|
||||
};
|
||||
|
||||
struct FileDownload : FileSource
|
||||
{
|
||||
FileDownload(const FileSource& source, bool executable) {
|
||||
static_cast<FileSource &> (*this) = source;
|
||||
this->executable = executable;
|
||||
}
|
||||
bool executable = false;
|
||||
};
|
||||
|
||||
struct UpdateOperations {
|
||||
static UpdateOperations resolve(const Package & from, const Package & to);
|
||||
bool valid = false;
|
||||
std::vector<Path> deletes;
|
||||
std::vector<Path> rmdirs;
|
||||
std::vector<Path> mkdirs;
|
||||
std::map<Path, FileDownload> downloads;
|
||||
std::map<Path, Path> mklinks;
|
||||
std::map<Path, bool> executable_fixes;
|
||||
};
|
||||
|
||||
}
|
@ -16,7 +16,6 @@
|
||||
<file>scalable/jarmods.svg</file>
|
||||
<file>scalable/java.svg</file>
|
||||
<file>scalable/language.svg</file>
|
||||
<file>scalable/launcher.svg</file>
|
||||
<file>scalable/loadermods.svg</file>
|
||||
<file>scalable/log.svg</file>
|
||||
<file>scalable/minecraft.svg</file>
|
||||
|
@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.4 KiB |
@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.4 KiB |
@ -18,7 +18,6 @@
|
||||
<file>scalable/jarmods.svg</file>
|
||||
<file>scalable/java.svg</file>
|
||||
<file>scalable/language.svg</file>
|
||||
<file>scalable/launcher.svg</file>
|
||||
<file>scalable/loadermods.svg</file>
|
||||
<file>scalable/log.svg</file>
|
||||
<file>scalable/minecraft.svg</file>
|
||||
|
@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.4 KiB |
@ -18,7 +18,6 @@
|
||||
<file>scalable/jarmods.svg</file>
|
||||
<file>scalable/java.svg</file>
|
||||
<file>scalable/language.svg</file>
|
||||
<file>scalable/launcher.svg</file>
|
||||
<file>scalable/loadermods.svg</file>
|
||||
<file>scalable/log.svg</file>
|
||||
<file>scalable/minecraft.svg</file>
|
||||
|
@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" fill="#eeeeee" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m20 4h-16v16h16zm0 18h-16c-1.1046 0-2-0.89543-2-2v-16c0-1.1046 0.89543-2 2-2h16c1.1046 0 2 0.89543 2 2v16c0 1.1046-0.89543 2-2 2z"/><path d="m7.2 18c-0.225 0-0.45-0.075-0.6-0.15-0.375-0.225-0.6-0.6-0.6-1.05v-9.6c0-0.45 0.225-0.825 0.6-1.05 0.225-0.15 0.375-0.15 0.6-0.15 0.15 0 0.375 0.075 0.525 0.15l9.6 4.8c0.375 0.225 0.675 0.6 0.675 1.05 0 0.45-0.225 0.9-0.675 1.05l-9.6 4.8c-0.15 0.075-0.375 0.15-0.525 0.15z" clip-rule="evenodd" fill="#eeeeee" fill-rule="evenodd" stroke-width=".99999"/></svg>
|
Before Width: | Height: | Size: 660 B |
@ -16,7 +16,6 @@
|
||||
<file>scalable/jarmods.svg</file>
|
||||
<file>scalable/java.svg</file>
|
||||
<file>scalable/language.svg</file>
|
||||
<file>scalable/launcher.svg</file>
|
||||
<file>scalable/loadermods.svg</file>
|
||||
<file>scalable/log.svg</file>
|
||||
<file>scalable/minecraft.svg</file>
|
||||
|
@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.4 KiB |
@ -16,7 +16,6 @@
|
||||
<file>scalable/jarmods.svg</file>
|
||||
<file>scalable/java.svg</file>
|
||||
<file>scalable/language.svg</file>
|
||||
<file>scalable/launcher.svg</file>
|
||||
<file>scalable/loadermods.svg</file>
|
||||
<file>scalable/log.svg</file>
|
||||
<file>scalable/minecraft.svg</file>
|
||||
|
@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.4 KiB |
@ -16,7 +16,6 @@
|
||||
<file>scalable/jarmods.svg</file>
|
||||
<file>scalable/java.svg</file>
|
||||
<file>scalable/language.svg</file>
|
||||
<file>scalable/launcher.svg</file>
|
||||
<file>scalable/loadermods.svg</file>
|
||||
<file>scalable/log.svg</file>
|
||||
<file>scalable/minecraft.svg</file>
|
||||
|
@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.4 KiB |
@ -16,7 +16,6 @@
|
||||
<file>scalable/jarmods.svg</file>
|
||||
<file>scalable/java.svg</file>
|
||||
<file>scalable/language.svg</file>
|
||||
<file>scalable/launcher.svg</file>
|
||||
<file>scalable/loadermods.svg</file>
|
||||
<file>scalable/log.svg</file>
|
||||
<file>scalable/minecraft.svg</file>
|
||||
|
@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.4 KiB |
@ -16,7 +16,6 @@
|
||||
<file>scalable/jarmods.svg</file>
|
||||
<file>scalable/java.svg</file>
|
||||
<file>scalable/language.svg</file>
|
||||
<file>scalable/launcher.svg</file>
|
||||
<file>scalable/loadermods.svg</file>
|
||||
<file>scalable/log.svg</file>
|
||||
<file>scalable/minecraft.svg</file>
|
||||
|
@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.4 KiB |
@ -224,6 +224,13 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
|
||||
// disabled until we have an instance selected
|
||||
ui->instanceToolBar->setEnabled(false);
|
||||
setInstanceActionsEnabled(false);
|
||||
|
||||
// add a close button at the end of the main toolbar when running on gamescope / steam deck
|
||||
// FIXME: detect if we don't have server side decorations instead
|
||||
if (qgetenv("XDG_CURRENT_DESKTOP") == "gamescope") {
|
||||
ui->mainToolBar->addAction(ui->actionCloseWindow);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// add the toolbar toggles to the view menu
|
||||
@ -1503,140 +1510,113 @@ void MainWindow::on_actionKillInstance_triggered()
|
||||
|
||||
void MainWindow::on_actionCreateInstanceShortcut_triggered()
|
||||
{
|
||||
if (m_selectedInstance)
|
||||
{
|
||||
auto desktopPath = FS::getDesktopDir();
|
||||
if (desktopPath.isEmpty()) {
|
||||
// TODO come up with an alternative solution (open "save file" dialog)
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Couldn't find desktop?!"));
|
||||
return;
|
||||
}
|
||||
if (!m_selectedInstance)
|
||||
return;
|
||||
auto desktopPath = FS::getDesktopDir();
|
||||
if (desktopPath.isEmpty()) {
|
||||
// TODO come up with an alternative solution (open "save file" dialog)
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Couldn't find desktop?!"));
|
||||
return;
|
||||
}
|
||||
|
||||
QString desktopFilePath;
|
||||
QString appPath = QApplication::applicationFilePath();
|
||||
QString iconPath;
|
||||
QStringList args;
|
||||
#if defined(Q_OS_MACOS)
|
||||
QString appPath = QApplication::applicationFilePath();
|
||||
if (appPath.startsWith("/private/var/")) {
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("The launcher is in the folder it was extracted from, therefore it cannot create shortcuts."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (FS::createShortcut(FS::PathCombine(desktopPath, m_selectedInstance->name()),
|
||||
appPath, { "--launch", m_selectedInstance->id() },
|
||||
m_selectedInstance->name(), "")) {
|
||||
QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!"));
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create instance shortcut!"));
|
||||
}
|
||||
if (appPath.startsWith("/private/var/")) {
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"),
|
||||
tr("The launcher is in the folder it was extracted from, therefore it cannot create shortcuts."));
|
||||
return;
|
||||
}
|
||||
#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
||||
QString appPath = QApplication::applicationFilePath();
|
||||
if (appPath.startsWith("/tmp/.mount_")) {
|
||||
// AppImage!
|
||||
appPath = QProcessEnvironment::systemEnvironment().value(QStringLiteral("APPIMAGE"));
|
||||
if (appPath.isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Launcher is running as misconfigured AppImage? ($APPIMAGE environment variable is missing)"));
|
||||
}
|
||||
else if (appPath.endsWith("/"))
|
||||
{
|
||||
appPath.chop(1);
|
||||
}
|
||||
if (appPath.startsWith("/tmp/.mount_")) {
|
||||
// AppImage!
|
||||
appPath = QProcessEnvironment::systemEnvironment().value(QStringLiteral("APPIMAGE"));
|
||||
if (appPath.isEmpty()) {
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"),
|
||||
tr("Launcher is running as misconfigured AppImage? ($APPIMAGE environment variable is missing)"));
|
||||
} else if (appPath.endsWith("/")) {
|
||||
appPath.chop(1);
|
||||
}
|
||||
}
|
||||
|
||||
auto icon = APPLICATION->icons()->icon(m_selectedInstance->iconKey());
|
||||
if (icon == nullptr)
|
||||
{
|
||||
icon = APPLICATION->icons()->icon("grass");
|
||||
}
|
||||
auto icon = APPLICATION->icons()->icon(m_selectedInstance->iconKey());
|
||||
if (icon == nullptr) {
|
||||
icon = APPLICATION->icons()->icon("grass");
|
||||
}
|
||||
|
||||
QString iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "icon.png");
|
||||
iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "icon.png");
|
||||
|
||||
QFile iconFile(iconPath);
|
||||
if (!iconFile.open(QFile::WriteOnly))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut."));
|
||||
return;
|
||||
}
|
||||
bool success = icon->icon().pixmap(64, 64).save(&iconFile, "PNG");
|
||||
iconFile.close();
|
||||
QFile iconFile(iconPath);
|
||||
if (!iconFile.open(QFile::WriteOnly)) {
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut."));
|
||||
return;
|
||||
}
|
||||
bool success = icon->icon().pixmap(64, 64).save(&iconFile, "PNG");
|
||||
iconFile.close();
|
||||
|
||||
if (!success)
|
||||
{
|
||||
iconFile.remove();
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut."));
|
||||
return;
|
||||
}
|
||||
if (!success) {
|
||||
iconFile.remove();
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (DesktopServices::isFlatpak()) {
|
||||
desktopFilePath = FS::PathCombine(desktopPath, FS::RemoveInvalidFilenameChars(m_selectedInstance->name()) + ".desktop");
|
||||
QFileDialog fileDialog;
|
||||
// workaround to make sure the portal file dialog opens in the desktop directory
|
||||
fileDialog.setDirectoryUrl(desktopPath);
|
||||
desktopFilePath = fileDialog.getSaveFileName(this, tr("Create Shortcut"), desktopFilePath, tr("Desktop Entries (*.desktop)"));
|
||||
if (desktopFilePath.isEmpty())
|
||||
return; // file dialog canceled by user
|
||||
appPath = "flatpak";
|
||||
QString flatpakAppId = BuildConfig.LAUNCHER_DESKTOPFILENAME;
|
||||
flatpakAppId.remove(".desktop");
|
||||
args.append({ "run", flatpakAppId });
|
||||
}
|
||||
|
||||
QString desktopFilePath = FS::PathCombine(desktopPath, m_selectedInstance->name() + ".desktop");
|
||||
QStringList args;
|
||||
if (DesktopServices::isFlatpak()) {
|
||||
QFileDialog fileDialog;
|
||||
// workaround to make sure the portal file dialog opens in the desktop directory
|
||||
fileDialog.setDirectoryUrl(desktopPath);
|
||||
desktopFilePath = fileDialog.getSaveFileName(
|
||||
this, tr("Create Shortcut"), desktopFilePath,
|
||||
tr("Desktop Entries (*.desktop)"));
|
||||
if (desktopFilePath.isEmpty())
|
||||
return; // file dialog canceled by user
|
||||
appPath = "flatpak";
|
||||
QString flatpakAppId = BuildConfig.LAUNCHER_DESKTOPFILENAME;
|
||||
flatpakAppId.remove(".desktop");
|
||||
args.append({ "run", flatpakAppId });
|
||||
}
|
||||
args.append({ "--launch", m_selectedInstance->id() });
|
||||
if (FS::createShortcut(desktopFilePath, appPath, args, m_selectedInstance->name(), iconPath)) {
|
||||
QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!"));
|
||||
}
|
||||
else
|
||||
{
|
||||
iconFile.remove();
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create instance shortcut!"));
|
||||
}
|
||||
#elif defined(Q_OS_WIN)
|
||||
auto icon = APPLICATION->icons()->icon(m_selectedInstance->iconKey());
|
||||
if (icon == nullptr)
|
||||
{
|
||||
icon = APPLICATION->icons()->icon("grass");
|
||||
}
|
||||
auto icon = APPLICATION->icons()->icon(m_selectedInstance->iconKey());
|
||||
if (icon == nullptr) {
|
||||
icon = APPLICATION->icons()->icon("grass");
|
||||
}
|
||||
|
||||
QString iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "icon.ico");
|
||||
iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "icon.ico");
|
||||
|
||||
// part of fix for weird bug involving the window icon being replaced
|
||||
// dunno why it happens, but this 2-line fix seems to be enough, so w/e
|
||||
auto appIcon = APPLICATION->getThemedIcon("logo");
|
||||
// part of fix for weird bug involving the window icon being replaced
|
||||
// dunno why it happens, but this 2-line fix seems to be enough, so w/e
|
||||
auto appIcon = APPLICATION->getThemedIcon("logo");
|
||||
|
||||
QFile iconFile(iconPath);
|
||||
if (!iconFile.open(QFile::WriteOnly))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut."));
|
||||
return;
|
||||
}
|
||||
bool success = icon->icon().pixmap(64, 64).save(&iconFile, "ICO");
|
||||
iconFile.close();
|
||||
QFile iconFile(iconPath);
|
||||
if (!iconFile.open(QFile::WriteOnly)) {
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut."));
|
||||
return;
|
||||
}
|
||||
bool success = icon->icon().pixmap(64, 64).save(&iconFile, "ICO");
|
||||
iconFile.close();
|
||||
|
||||
// restore original window icon
|
||||
QGuiApplication::setWindowIcon(appIcon);
|
||||
// restore original window icon
|
||||
QGuiApplication::setWindowIcon(appIcon);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
iconFile.remove();
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut."));
|
||||
return;
|
||||
}
|
||||
if (!success) {
|
||||
iconFile.remove();
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (FS::createShortcut(FS::PathCombine(desktopPath, m_selectedInstance->name()),
|
||||
QApplication::applicationFilePath(), { "--launch", m_selectedInstance->id() },
|
||||
m_selectedInstance->name(), iconPath)) {
|
||||
QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!"));
|
||||
}
|
||||
else
|
||||
{
|
||||
iconFile.remove();
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create instance shortcut!"));
|
||||
}
|
||||
#else
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Not supported on your platform!"));
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Not supported on your platform!"));
|
||||
return;
|
||||
#endif
|
||||
args.append({ "--launch", m_selectedInstance->id() });
|
||||
if (FS::createShortcut(desktopFilePath, appPath, args, m_selectedInstance->name(), iconPath)) {
|
||||
QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!"));
|
||||
} else {
|
||||
#if not defined(Q_OS_MACOS)
|
||||
iconFile.remove();
|
||||
#endif
|
||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create instance shortcut!"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "ui/widgets/PageContainer.h"
|
||||
#include "ui/pages/modplatform/VanillaPage.h"
|
||||
#include "ui/pages/modplatform/CustomPage.h"
|
||||
#include "ui/pages/modplatform/atlauncher/AtlPage.h"
|
||||
#include "ui/pages/modplatform/legacy_ftb/Page.h"
|
||||
#include "ui/pages/modplatform/flame/FlamePage.h"
|
||||
@ -162,7 +162,7 @@ QList<BasePage *> NewInstanceDialog::getPages()
|
||||
|
||||
importPage = new ImportPage(this);
|
||||
|
||||
pages.append(new VanillaPage(this));
|
||||
pages.append(new CustomPage(this));
|
||||
pages.append(importPage);
|
||||
pages.append(new AtlPage(this));
|
||||
if (APPLICATION->capabilities() & Application::SupportsFlame)
|
||||
|
@ -44,7 +44,7 @@
|
||||
|
||||
class BasePage {
|
||||
public:
|
||||
using updateExtraInfoFunc = std::function<void(QString)>;
|
||||
using updateExtraInfoFunc = std::function<void(QString, QString)>;
|
||||
virtual ~BasePage() {}
|
||||
virtual QString id() const = 0;
|
||||
virtual QString displayName() const = 0;
|
||||
|
@ -83,7 +83,7 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared
|
||||
connect(selection_model, &QItemSelectionModel::currentChanged, this, &ExternalResourcesPage::current);
|
||||
auto updateExtra = [this]() {
|
||||
if (updateExtraInfo)
|
||||
updateExtraInfo(extraHeaderInfoString());
|
||||
updateExtraInfo(id(), extraHeaderInfoString());
|
||||
};
|
||||
connect(selection_model, &QItemSelectionModel::selectionChanged, this, updateExtra);
|
||||
connect(model.get(), &ResourceFolderModel::updateFinished, this, updateExtra);
|
||||
|
@ -85,12 +85,12 @@ void InstanceSettingsPage::globalSettingsButtonClicked(bool)
|
||||
case 0:
|
||||
APPLICATION->ShowGlobalSettings(this, "java-settings");
|
||||
return;
|
||||
case 1:
|
||||
APPLICATION->ShowGlobalSettings(this, "minecraft-settings");
|
||||
return;
|
||||
case 2:
|
||||
APPLICATION->ShowGlobalSettings(this, "custom-commands");
|
||||
return;
|
||||
default:
|
||||
APPLICATION->ShowGlobalSettings(this, "minecraft-settings");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,7 +207,7 @@ ModrinthManagedPackPage::ModrinthManagedPackPage(BaseInstance* inst, InstanceWin
|
||||
{
|
||||
Q_ASSERT(inst->isManagedPack());
|
||||
connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion()));
|
||||
connect(ui->updateButton, &QPushButton::pressed, this, &ModrinthManagedPackPage::update);
|
||||
connect(ui->updateButton, &QPushButton::clicked, this, &ModrinthManagedPackPage::update);
|
||||
}
|
||||
|
||||
// MODRINTH
|
||||
@ -334,7 +334,7 @@ FlameManagedPackPage::FlameManagedPackPage(BaseInstance* inst, InstanceWindow* i
|
||||
{
|
||||
Q_ASSERT(inst->isManagedPack());
|
||||
connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion()));
|
||||
connect(ui->updateButton, &QPushButton::pressed, this, &FlameManagedPackPage::update);
|
||||
connect(ui->updateButton, &QPushButton::clicked, this, &FlameManagedPackPage::update);
|
||||
}
|
||||
|
||||
void FlameManagedPackPage::parseManagedPack()
|
||||
|
@ -36,6 +36,7 @@
|
||||
*/
|
||||
|
||||
#include "ScreenshotsPage.h"
|
||||
#include "BuildConfig.h"
|
||||
#include "ui_ScreenshotsPage.h"
|
||||
|
||||
#include <QModelIndex>
|
||||
@ -380,16 +381,18 @@ void ScreenshotsPage::on_actionUpload_triggered()
|
||||
if (selection.isEmpty())
|
||||
return;
|
||||
|
||||
|
||||
QString text;
|
||||
QUrl baseUrl(BuildConfig.IMGUR_BASE_URL);
|
||||
if (selection.size() > 1)
|
||||
text = tr("You are about to upload %1 screenshots.\n\n"
|
||||
text = tr("You are about to upload %1 screenshots to %2.\n"
|
||||
"You should double-check for personal information.\n\n"
|
||||
"Are you sure?")
|
||||
.arg(selection.size());
|
||||
.arg(QString::number(selection.size()), baseUrl.host());
|
||||
else
|
||||
text =
|
||||
tr("You are about to upload the selected screenshot.\n\n"
|
||||
"Are you sure?");
|
||||
text = tr("You are about to upload the selected screenshot to %1.\n"
|
||||
"You should double-check for personal information.\n\n"
|
||||
"Are you sure?")
|
||||
.arg(baseUrl.host());
|
||||
|
||||
auto response = CustomMessageBox::selectable(this, "Confirm Upload", text, QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No,
|
||||
QMessageBox::No)
|
||||
|
@ -287,7 +287,6 @@ void VersionPage::updateButtons(int row)
|
||||
ui->actionAdd_Empty->setEnabled(controlsEnabled);
|
||||
ui->actionImport_Components->setEnabled(controlsEnabled);
|
||||
ui->actionReload->setEnabled(controlsEnabled);
|
||||
ui->actionInstall_mods->setEnabled(controlsEnabled);
|
||||
ui->actionReplace_Minecraft_jar->setEnabled(controlsEnabled);
|
||||
ui->actionAdd_to_Minecraft_jar->setEnabled(controlsEnabled);
|
||||
ui->actionAdd_Agents->setEnabled(controlsEnabled);
|
||||
|
@ -102,7 +102,6 @@
|
||||
<addaction name="actionInstall_Fabric"/>
|
||||
<addaction name="actionInstall_Quilt"/>
|
||||
<addaction name="actionInstall_LiteLoader"/>
|
||||
<addaction name="actionInstall_mods"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionAdd_to_Minecraft_jar"/>
|
||||
<addaction name="actionReplace_Minecraft_jar"/>
|
||||
@ -112,7 +111,6 @@
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionMinecraftFolder"/>
|
||||
<addaction name="actionLibrariesFolder"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionReload"/>
|
||||
<addaction name="actionDownload_All"/>
|
||||
</widget>
|
||||
@ -204,14 +202,6 @@
|
||||
<string>Install the LiteLoader package.</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionInstall_mods">
|
||||
<property name="text">
|
||||
<string>Install mods</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Install normal mods.</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAdd_to_Minecraft_jar">
|
||||
<property name="text">
|
||||
<string>Add to Minecraft.jar</string>
|
||||
|
@ -33,8 +33,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "VanillaPage.h"
|
||||
#include "ui_VanillaPage.h"
|
||||
#include "CustomPage.h"
|
||||
#include "ui_CustomPage.h"
|
||||
|
||||
#include <QTabBar>
|
||||
|
||||
@ -46,32 +46,32 @@
|
||||
#include "minecraft/VanillaInstanceCreationTask.h"
|
||||
#include "ui/dialogs/NewInstanceDialog.h"
|
||||
|
||||
VanillaPage::VanillaPage(NewInstanceDialog *dialog, QWidget *parent)
|
||||
: QWidget(parent), dialog(dialog), ui(new Ui::VanillaPage)
|
||||
CustomPage::CustomPage(NewInstanceDialog *dialog, QWidget *parent)
|
||||
: QWidget(parent), dialog(dialog), ui(new Ui::CustomPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
connect(ui->versionList, &VersionSelectWidget::selectedVersionChanged, this, &VanillaPage::setSelectedVersion);
|
||||
connect(ui->versionList, &VersionSelectWidget::selectedVersionChanged, this, &CustomPage::setSelectedVersion);
|
||||
filterChanged();
|
||||
connect(ui->alphaFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged);
|
||||
connect(ui->betaFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged);
|
||||
connect(ui->snapshotFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged);
|
||||
connect(ui->oldSnapshotFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged);
|
||||
connect(ui->releaseFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged);
|
||||
connect(ui->experimentsFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged);
|
||||
connect(ui->refreshBtn, &QPushButton::clicked, this, &VanillaPage::refresh);
|
||||
connect(ui->alphaFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged);
|
||||
connect(ui->betaFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged);
|
||||
connect(ui->snapshotFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged);
|
||||
connect(ui->oldSnapshotFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged);
|
||||
connect(ui->releaseFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged);
|
||||
connect(ui->experimentsFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged);
|
||||
connect(ui->refreshBtn, &QPushButton::clicked, this, &CustomPage::refresh);
|
||||
|
||||
connect(ui->loaderVersionList, &VersionSelectWidget::selectedVersionChanged, this, &VanillaPage::setSelectedLoaderVersion);
|
||||
connect(ui->noneFilter, &QRadioButton::toggled, this, &VanillaPage::loaderFilterChanged);
|
||||
connect(ui->forgeFilter, &QRadioButton::toggled, this, &VanillaPage::loaderFilterChanged);
|
||||
connect(ui->fabricFilter, &QRadioButton::toggled, this, &VanillaPage::loaderFilterChanged);
|
||||
connect(ui->quiltFilter, &QRadioButton::toggled, this, &VanillaPage::loaderFilterChanged);
|
||||
connect(ui->liteLoaderFilter, &QRadioButton::toggled, this, &VanillaPage::loaderFilterChanged);
|
||||
connect(ui->loaderRefreshBtn, &QPushButton::clicked, this, &VanillaPage::loaderRefresh);
|
||||
connect(ui->loaderVersionList, &VersionSelectWidget::selectedVersionChanged, this, &CustomPage::setSelectedLoaderVersion);
|
||||
connect(ui->noneFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
|
||||
connect(ui->forgeFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
|
||||
connect(ui->fabricFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
|
||||
connect(ui->quiltFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
|
||||
connect(ui->liteLoaderFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
|
||||
connect(ui->loaderRefreshBtn, &QPushButton::clicked, this, &CustomPage::loaderRefresh);
|
||||
|
||||
}
|
||||
|
||||
void VanillaPage::openedImpl()
|
||||
void CustomPage::openedImpl()
|
||||
{
|
||||
if(!initialized)
|
||||
{
|
||||
@ -85,19 +85,19 @@ void VanillaPage::openedImpl()
|
||||
}
|
||||
}
|
||||
|
||||
void VanillaPage::refresh()
|
||||
void CustomPage::refresh()
|
||||
{
|
||||
ui->versionList->loadList();
|
||||
}
|
||||
|
||||
void VanillaPage::loaderRefresh()
|
||||
void CustomPage::loaderRefresh()
|
||||
{
|
||||
if(ui->noneFilter->isChecked())
|
||||
return;
|
||||
ui->loaderVersionList->loadList();
|
||||
}
|
||||
|
||||
void VanillaPage::filterChanged()
|
||||
void CustomPage::filterChanged()
|
||||
{
|
||||
QStringList out;
|
||||
if(ui->alphaFilter->isChecked())
|
||||
@ -116,7 +116,7 @@ void VanillaPage::filterChanged()
|
||||
ui->versionList->setFilter(BaseVersionList::TypeRole, new RegexpFilter(regexp, false));
|
||||
}
|
||||
|
||||
void VanillaPage::loaderFilterChanged()
|
||||
void CustomPage::loaderFilterChanged()
|
||||
{
|
||||
QString minecraftVersion;
|
||||
if (m_selectedVersion)
|
||||
@ -172,37 +172,37 @@ void VanillaPage::loaderFilterChanged()
|
||||
ui->loaderVersionList->setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion));
|
||||
}
|
||||
|
||||
VanillaPage::~VanillaPage()
|
||||
CustomPage::~CustomPage()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool VanillaPage::shouldDisplay() const
|
||||
bool CustomPage::shouldDisplay() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void VanillaPage::retranslate()
|
||||
void CustomPage::retranslate()
|
||||
{
|
||||
ui->retranslateUi(this);
|
||||
}
|
||||
|
||||
BaseVersion::Ptr VanillaPage::selectedVersion() const
|
||||
BaseVersion::Ptr CustomPage::selectedVersion() const
|
||||
{
|
||||
return m_selectedVersion;
|
||||
}
|
||||
|
||||
BaseVersion::Ptr VanillaPage::selectedLoaderVersion() const
|
||||
BaseVersion::Ptr CustomPage::selectedLoaderVersion() const
|
||||
{
|
||||
return m_selectedLoaderVersion;
|
||||
}
|
||||
|
||||
QString VanillaPage::selectedLoader() const
|
||||
QString CustomPage::selectedLoader() const
|
||||
{
|
||||
return m_selectedLoader;
|
||||
}
|
||||
|
||||
void VanillaPage::suggestCurrent()
|
||||
void CustomPage::suggestCurrent()
|
||||
{
|
||||
if (!isOpened)
|
||||
{
|
||||
@ -227,14 +227,14 @@ void VanillaPage::suggestCurrent()
|
||||
dialog->setSuggestedIcon("default");
|
||||
}
|
||||
|
||||
void VanillaPage::setSelectedVersion(BaseVersion::Ptr version)
|
||||
void CustomPage::setSelectedVersion(BaseVersion::Ptr version)
|
||||
{
|
||||
m_selectedVersion = version;
|
||||
suggestCurrent();
|
||||
loaderFilterChanged();
|
||||
}
|
||||
|
||||
void VanillaPage::setSelectedLoaderVersion(BaseVersion::Ptr version)
|
||||
void CustomPage::setSelectedLoaderVersion(BaseVersion::Ptr version)
|
||||
{
|
||||
m_selectedLoaderVersion = version;
|
||||
suggestCurrent();
|
@ -43,21 +43,21 @@
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class VanillaPage;
|
||||
class CustomPage;
|
||||
}
|
||||
|
||||
class NewInstanceDialog;
|
||||
|
||||
class VanillaPage : public QWidget, public BasePage
|
||||
class CustomPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VanillaPage(NewInstanceDialog *dialog, QWidget *parent = 0);
|
||||
virtual ~VanillaPage();
|
||||
explicit CustomPage(NewInstanceDialog *dialog, QWidget *parent = 0);
|
||||
virtual ~CustomPage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return tr("Vanilla");
|
||||
return tr("Custom");
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
@ -96,7 +96,7 @@ private:
|
||||
private:
|
||||
bool initialized = false;
|
||||
NewInstanceDialog *dialog = nullptr;
|
||||
Ui::VanillaPage *ui = nullptr;
|
||||
Ui::CustomPage *ui = nullptr;
|
||||
bool m_versionSetByUser = false;
|
||||
BaseVersion::Ptr m_selectedVersion;
|
||||
BaseVersion::Ptr m_selectedLoaderVersion;
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>VanillaPage</class>
|
||||
<widget class="QWidget" name="VanillaPage">
|
||||
<class>CustomPage</class>
|
||||
<widget class="QWidget" name="CustomPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
@ -116,8 +116,8 @@ Page::Page(NewInstanceDialog* dialog, QWidget *parent)
|
||||
connect(ui->thirdPartyPackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &Page::onThirdPartyPackSelectionChanged);
|
||||
connect(ui->privatePackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &Page::onPrivatePackSelectionChanged);
|
||||
|
||||
connect(ui->addPackBtn, &QPushButton::pressed, this, &Page::onAddPackClicked);
|
||||
connect(ui->removePackBtn, &QPushButton::pressed, this, &Page::onRemovePackClicked);
|
||||
connect(ui->addPackBtn, &QPushButton::clicked, this, &Page::onAddPackClicked);
|
||||
connect(ui->removePackBtn, &QPushButton::clicked, this, &Page::onRemovePackClicked);
|
||||
|
||||
connect(ui->tabWidget, &QTabWidget::currentChanged, this, &Page::onTabChanged);
|
||||
|
||||
|
@ -59,7 +59,7 @@ void SetupWizard::pageChanged(int id)
|
||||
{
|
||||
setButtonLayout({QWizard::CustomButton1, QWizard::Stretch, QWizard::BackButton, QWizard::NextButton, QWizard::FinishButton});
|
||||
auto customButton = button(QWizard::CustomButton1);
|
||||
connect(customButton, &QAbstractButton::pressed, [&](){
|
||||
connect(customButton, &QAbstractButton::clicked, [&](){
|
||||
auto basePagePtr = getCurrentBasePage();
|
||||
if(basePagePtr)
|
||||
{
|
||||
|
@ -14,9 +14,6 @@
|
||||
*/
|
||||
|
||||
#include "ModListView.h"
|
||||
|
||||
#include "minecraft/mod/ModFolderModel.h"
|
||||
|
||||
#include <QHeaderView>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
@ -65,19 +62,6 @@ void ModListView::setModel ( QAbstractItemModel* model )
|
||||
for(int i = 1; i < head->count(); i++)
|
||||
head->setSectionResizeMode(i, QHeaderView::ResizeToContents);
|
||||
}
|
||||
|
||||
auto real_model = model;
|
||||
if (auto proxy_model = dynamic_cast<QSortFilterProxyModel*>(model); proxy_model)
|
||||
real_model = proxy_model->sourceModel();
|
||||
|
||||
if (auto mod_model = dynamic_cast<ModFolderModel*>(real_model); mod_model) {
|
||||
connect(mod_model, &ModFolderModel::updateFinished, this, [this, mod_model]{
|
||||
auto mods = mod_model->allMods();
|
||||
// Hide the 'Provider' column if no mod has a defined provider!
|
||||
setColumnHidden(ModFolderModel::Columns::ProviderColumn,
|
||||
std::none_of(mods.constBegin(), mods.constEnd(), [](auto const mod){ return mod->provider().has_value(); }));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ModListView::setResizeModes(const QList<QHeaderView::ResizeMode> &modes)
|
||||
|
@ -93,8 +93,8 @@ PageContainer::PageContainer(BasePageProvider *pageProvider, QString defaultId,
|
||||
page->listIndex = counter;
|
||||
page->setParentContainer(this);
|
||||
counter++;
|
||||
page->updateExtraInfo = [this](QString info) {
|
||||
if (m_currentPage)
|
||||
page->updateExtraInfo = [this](QString id, QString info) {
|
||||
if (m_currentPage && id == m_currentPage->id())
|
||||
m_header->setText(m_currentPage->displayName() + info);
|
||||
};
|
||||
}
|
||||
|
@ -67,7 +67,4 @@ else
|
||||
fi
|
||||
|
||||
# replace icon in themes
|
||||
for dir in ../launcher/resources/*/scalable
|
||||
do
|
||||
cp -v org.prismlauncher.PrismLauncher.svg "$dir/launcher.svg"
|
||||
done
|
||||
cp -v org.prismlauncher.PrismLauncher.svg "../launcher/resources/multimc/scalable/launcher.svg"
|
||||
|
@ -9,9 +9,6 @@ ecm_add_test(GZip_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::
|
||||
ecm_add_test(GradleSpecifier_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
|
||||
TEST_NAME GradleSpecifier)
|
||||
|
||||
ecm_add_test(PackageManifest_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
|
||||
TEST_NAME PackageManifest)
|
||||
|
||||
ecm_add_test(MojangVersionFormat_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
|
||||
TEST_NAME MojangVersionFormat)
|
||||
|
||||
|
@ -1,343 +0,0 @@
|
||||
#include <QTest>
|
||||
#include <QDebug>
|
||||
|
||||
#include <mojang/PackageManifest.h>
|
||||
|
||||
using namespace mojang_files;
|
||||
|
||||
QDebug operator<<(QDebug debug, const Path &path)
|
||||
{
|
||||
debug << path.toString();
|
||||
return debug;
|
||||
}
|
||||
|
||||
class PackageManifestTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void test_parse();
|
||||
void test_parse_file();
|
||||
void test_inspect();
|
||||
#ifndef Q_OS_WIN32
|
||||
void test_inspect_symlinks();
|
||||
#endif
|
||||
void mkdir_deep();
|
||||
void rmdir_deep();
|
||||
|
||||
void identical_file();
|
||||
void changed_file();
|
||||
void added_file();
|
||||
void removed_file();
|
||||
};
|
||||
|
||||
namespace {
|
||||
QByteArray basic_manifest = R"END(
|
||||
{
|
||||
"files": {
|
||||
"a/b.txt": {
|
||||
"type": "file",
|
||||
"downloads": {
|
||||
"raw": {
|
||||
"url": "http://dethware.org/b.txt",
|
||||
"sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
|
||||
"size": 0
|
||||
}
|
||||
},
|
||||
"executable": true
|
||||
},
|
||||
"a/b/c": {
|
||||
"type": "directory"
|
||||
},
|
||||
"a/b/c.txt": {
|
||||
"type": "link",
|
||||
"target": "../b.txt"
|
||||
}
|
||||
}
|
||||
}
|
||||
)END";
|
||||
}
|
||||
|
||||
void PackageManifestTest::test_parse()
|
||||
{
|
||||
auto manifest = Package::fromManifestContents(basic_manifest);
|
||||
QVERIFY(manifest.valid == true);
|
||||
QVERIFY(manifest.files.size() == 1);
|
||||
QVERIFY(manifest.files.count(Path("a/b.txt")));
|
||||
auto &file = manifest.files[Path("a/b.txt")];
|
||||
QVERIFY(file.executable == true);
|
||||
QVERIFY(file.hash == "da39a3ee5e6b4b0d3255bfef95601890afd80709");
|
||||
QVERIFY(file.size == 0);
|
||||
QVERIFY(manifest.folders.size() == 4);
|
||||
QVERIFY(manifest.folders.count(Path(".")));
|
||||
QVERIFY(manifest.folders.count(Path("a")));
|
||||
QVERIFY(manifest.folders.count(Path("a/b")));
|
||||
QVERIFY(manifest.folders.count(Path("a/b/c")));
|
||||
QVERIFY(manifest.symlinks.size() == 1);
|
||||
auto symlinkPath = Path("a/b/c.txt");
|
||||
QVERIFY(manifest.symlinks.count(symlinkPath));
|
||||
auto &symlink = manifest.symlinks[symlinkPath];
|
||||
QVERIFY(symlink == Path("../b.txt"));
|
||||
QVERIFY(manifest.sources.size() == 1);
|
||||
}
|
||||
|
||||
void PackageManifestTest::test_parse_file() {
|
||||
auto path = QFINDTESTDATA("testdata/PackageManifest/1.8.0_202-x64.json");
|
||||
auto manifest = Package::fromManifestFile(path);
|
||||
QVERIFY(manifest.valid == true);
|
||||
}
|
||||
|
||||
|
||||
void PackageManifestTest::test_inspect() {
|
||||
auto path = QFINDTESTDATA("testdata/PackageManifest/inspect_win/");
|
||||
auto manifest = Package::fromInspectedFolder(path);
|
||||
QVERIFY(manifest.valid == true);
|
||||
QVERIFY(manifest.files.size() == 2);
|
||||
QVERIFY(manifest.files.count(Path("a/b.txt")));
|
||||
auto &file1 = manifest.files[Path("a/b.txt")];
|
||||
QVERIFY(file1.executable == false);
|
||||
QVERIFY(file1.hash == "da39a3ee5e6b4b0d3255bfef95601890afd80709");
|
||||
QVERIFY(file1.size == 0);
|
||||
QVERIFY(manifest.files.count(Path("a/b/b.txt")));
|
||||
auto &file2 = manifest.files[Path("a/b/b.txt")];
|
||||
QVERIFY(file2.executable == false);
|
||||
QVERIFY(file2.hash == "da39a3ee5e6b4b0d3255bfef95601890afd80709");
|
||||
QVERIFY(file2.size == 0);
|
||||
QVERIFY(manifest.folders.size() == 3);
|
||||
QVERIFY(manifest.folders.count(Path(".")));
|
||||
QVERIFY(manifest.folders.count(Path("a")));
|
||||
QVERIFY(manifest.folders.count(Path("a/b")));
|
||||
QVERIFY(manifest.symlinks.size() == 0);
|
||||
}
|
||||
|
||||
#ifndef Q_OS_WIN32
|
||||
void PackageManifestTest::test_inspect_symlinks() {
|
||||
auto path = QFINDTESTDATA("testdata/PackageManifest/inspect/");
|
||||
auto manifest = Package::fromInspectedFolder(path);
|
||||
QVERIFY(manifest.valid == true);
|
||||
QVERIFY(manifest.files.size() == 1);
|
||||
QVERIFY(manifest.files.count(Path("a/b.txt")));
|
||||
auto &file = manifest.files[Path("a/b.txt")];
|
||||
QVERIFY(file.executable == true);
|
||||
QVERIFY(file.hash == "da39a3ee5e6b4b0d3255bfef95601890afd80709");
|
||||
QVERIFY(file.size == 0);
|
||||
QVERIFY(manifest.folders.size() == 3);
|
||||
QVERIFY(manifest.folders.count(Path(".")));
|
||||
QVERIFY(manifest.folders.count(Path("a")));
|
||||
QVERIFY(manifest.folders.count(Path("a/b")));
|
||||
QVERIFY(manifest.symlinks.size() == 1);
|
||||
QVERIFY(manifest.symlinks.count(Path("a/b/b.txt")));
|
||||
qDebug() << manifest.symlinks[Path("a/b/b.txt")];
|
||||
QVERIFY(manifest.symlinks[Path("a/b/b.txt")] == Path("../b.txt"));
|
||||
}
|
||||
#endif
|
||||
|
||||
void PackageManifestTest::mkdir_deep() {
|
||||
|
||||
Package from;
|
||||
auto to = Package::fromManifestContents(R"END(
|
||||
{
|
||||
"files": {
|
||||
"a/b/c/d/e": {
|
||||
"type": "directory"
|
||||
}
|
||||
}
|
||||
}
|
||||
)END");
|
||||
auto operations = UpdateOperations::resolve(from, to);
|
||||
QVERIFY(operations.deletes.size() == 0);
|
||||
QVERIFY(operations.rmdirs.size() == 0);
|
||||
|
||||
QVERIFY(operations.mkdirs.size() == 6);
|
||||
QVERIFY(operations.mkdirs[0] == Path("."));
|
||||
QVERIFY(operations.mkdirs[1] == Path("a"));
|
||||
QVERIFY(operations.mkdirs[2] == Path("a/b"));
|
||||
QVERIFY(operations.mkdirs[3] == Path("a/b/c"));
|
||||
QVERIFY(operations.mkdirs[4] == Path("a/b/c/d"));
|
||||
QVERIFY(operations.mkdirs[5] == Path("a/b/c/d/e"));
|
||||
|
||||
QVERIFY(operations.downloads.size() == 0);
|
||||
QVERIFY(operations.mklinks.size() == 0);
|
||||
QVERIFY(operations.executable_fixes.size() == 0);
|
||||
}
|
||||
|
||||
void PackageManifestTest::rmdir_deep() {
|
||||
|
||||
Package to;
|
||||
auto from = Package::fromManifestContents(R"END(
|
||||
{
|
||||
"files": {
|
||||
"a/b/c/d/e": {
|
||||
"type": "directory"
|
||||
}
|
||||
}
|
||||
}
|
||||
)END");
|
||||
auto operations = UpdateOperations::resolve(from, to);
|
||||
QVERIFY(operations.deletes.size() == 0);
|
||||
|
||||
QVERIFY(operations.rmdirs.size() == 6);
|
||||
QVERIFY(operations.rmdirs[0] == Path("a/b/c/d/e"));
|
||||
QVERIFY(operations.rmdirs[1] == Path("a/b/c/d"));
|
||||
QVERIFY(operations.rmdirs[2] == Path("a/b/c"));
|
||||
QVERIFY(operations.rmdirs[3] == Path("a/b"));
|
||||
QVERIFY(operations.rmdirs[4] == Path("a"));
|
||||
QVERIFY(operations.rmdirs[5] == Path("."));
|
||||
|
||||
QVERIFY(operations.mkdirs.size() == 0);
|
||||
QVERIFY(operations.downloads.size() == 0);
|
||||
QVERIFY(operations.mklinks.size() == 0);
|
||||
QVERIFY(operations.executable_fixes.size() == 0);
|
||||
}
|
||||
|
||||
void PackageManifestTest::identical_file() {
|
||||
QByteArray manifest = R"END(
|
||||
{
|
||||
"files": {
|
||||
"a/b/c/d/empty.txt": {
|
||||
"type": "file",
|
||||
"downloads": {
|
||||
"raw": {
|
||||
"url": "http://dethware.org/empty.txt",
|
||||
"sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
|
||||
"size": 0
|
||||
}
|
||||
},
|
||||
"executable": false
|
||||
}
|
||||
}
|
||||
}
|
||||
)END";
|
||||
auto from = Package::fromManifestContents(manifest);
|
||||
auto to = Package::fromManifestContents(manifest);
|
||||
auto operations = UpdateOperations::resolve(from, to);
|
||||
QVERIFY(operations.deletes.size() == 0);
|
||||
QVERIFY(operations.rmdirs.size() == 0);
|
||||
QVERIFY(operations.mkdirs.size() == 0);
|
||||
QVERIFY(operations.downloads.size() == 0);
|
||||
QVERIFY(operations.mklinks.size() == 0);
|
||||
QVERIFY(operations.executable_fixes.size() == 0);
|
||||
}
|
||||
|
||||
void PackageManifestTest::changed_file() {
|
||||
auto from = Package::fromManifestContents(R"END(
|
||||
{
|
||||
"files": {
|
||||
"a/b/c/d/file": {
|
||||
"type": "file",
|
||||
"downloads": {
|
||||
"raw": {
|
||||
"url": "http://dethware.org/empty.txt",
|
||||
"sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
|
||||
"size": 0
|
||||
}
|
||||
},
|
||||
"executable": false
|
||||
}
|
||||
}
|
||||
}
|
||||
)END");
|
||||
auto to = Package::fromManifestContents(R"END(
|
||||
{
|
||||
"files": {
|
||||
"a/b/c/d/file": {
|
||||
"type": "file",
|
||||
"downloads": {
|
||||
"raw": {
|
||||
"url": "http://dethware.org/space.txt",
|
||||
"sha1": "dd122581c8cd44d0227f9c305581ffcb4b6f1b46",
|
||||
"size": 1
|
||||
}
|
||||
},
|
||||
"executable": false
|
||||
}
|
||||
}
|
||||
}
|
||||
)END");
|
||||
auto operations = UpdateOperations::resolve(from, to);
|
||||
QVERIFY(operations.deletes.size() == 1);
|
||||
QCOMPARE(operations.deletes[0], Path("a/b/c/d/file"));
|
||||
QVERIFY(operations.rmdirs.size() == 0);
|
||||
QVERIFY(operations.mkdirs.size() == 0);
|
||||
QVERIFY(operations.downloads.size() == 1);
|
||||
QVERIFY(operations.mklinks.size() == 0);
|
||||
QVERIFY(operations.executable_fixes.size() == 0);
|
||||
}
|
||||
|
||||
void PackageManifestTest::added_file() {
|
||||
auto from = Package::fromManifestContents(R"END(
|
||||
{
|
||||
"files": {
|
||||
"a/b/c/d": {
|
||||
"type": "directory"
|
||||
}
|
||||
}
|
||||
}
|
||||
)END");
|
||||
auto to = Package::fromManifestContents(R"END(
|
||||
{
|
||||
"files": {
|
||||
"a/b/c/d/file": {
|
||||
"type": "file",
|
||||
"downloads": {
|
||||
"raw": {
|
||||
"url": "http://dethware.org/space.txt",
|
||||
"sha1": "dd122581c8cd44d0227f9c305581ffcb4b6f1b46",
|
||||
"size": 1
|
||||
}
|
||||
},
|
||||
"executable": false
|
||||
}
|
||||
}
|
||||
}
|
||||
)END");
|
||||
auto operations = UpdateOperations::resolve(from, to);
|
||||
QVERIFY(operations.deletes.size() == 0);
|
||||
QVERIFY(operations.rmdirs.size() == 0);
|
||||
QVERIFY(operations.mkdirs.size() == 0);
|
||||
QVERIFY(operations.downloads.size() == 1);
|
||||
QVERIFY(operations.mklinks.size() == 0);
|
||||
QVERIFY(operations.executable_fixes.size() == 0);
|
||||
}
|
||||
|
||||
void PackageManifestTest::removed_file() {
|
||||
auto from = Package::fromManifestContents(R"END(
|
||||
{
|
||||
"files": {
|
||||
"a/b/c/d/file": {
|
||||
"type": "file",
|
||||
"downloads": {
|
||||
"raw": {
|
||||
"url": "http://dethware.org/space.txt",
|
||||
"sha1": "dd122581c8cd44d0227f9c305581ffcb4b6f1b46",
|
||||
"size": 1
|
||||
}
|
||||
},
|
||||
"executable": false
|
||||
}
|
||||
}
|
||||
}
|
||||
)END");
|
||||
auto to = Package::fromManifestContents(R"END(
|
||||
{
|
||||
"files": {
|
||||
"a/b/c/d": {
|
||||
"type": "directory"
|
||||
}
|
||||
}
|
||||
}
|
||||
)END");
|
||||
auto operations = UpdateOperations::resolve(from, to);
|
||||
QVERIFY(operations.deletes.size() == 1);
|
||||
QCOMPARE(operations.deletes[0], Path("a/b/c/d/file"));
|
||||
QVERIFY(operations.rmdirs.size() == 0);
|
||||
QVERIFY(operations.mkdirs.size() == 0);
|
||||
QVERIFY(operations.downloads.size() == 0);
|
||||
QVERIFY(operations.mklinks.size() == 0);
|
||||
QVERIFY(operations.executable_fixes.size() == 0);
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(PackageManifestTest)
|
||||
|
||||
#include "PackageManifest_test.moc"
|
||||
|