Merge branch 'develop' of github.com:MultiMC/MultiMC5 into develop

This commit is contained in:
Andrew 2013-11-27 14:20:42 -06:00
commit d794a4d0bf
9 changed files with 156 additions and 87 deletions

View File

@ -346,6 +346,8 @@ logic/JavaUtils.h
logic/JavaUtils.cpp logic/JavaUtils.cpp
logic/NagUtils.h logic/NagUtils.h
logic/NagUtils.cpp logic/NagUtils.cpp
logic/SkinUtils.h
logic/SkinUtils.cpp
) )

View File

@ -76,6 +76,7 @@
#include "logic/OneSixUpdate.h" #include "logic/OneSixUpdate.h"
#include "logic/JavaUtils.h" #include "logic/JavaUtils.h"
#include "logic/NagUtils.h" #include "logic/NagUtils.h"
#include "logic/SkinUtils.h"
#include "logic/LegacyInstance.h" #include "logic/LegacyInstance.h"
@ -164,6 +165,41 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
statusBar()->addPermanentWidget(m_statusLeft, 1); statusBar()->addPermanentWidget(m_statusLeft, 1);
statusBar()->addPermanentWidget(m_statusRight, 0); statusBar()->addPermanentWidget(m_statusRight, 0);
// Add "manage accounts" button, right align
QWidget* spacer = new QWidget();
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
ui->mainToolBar->addWidget(spacer);
actionManageAccounts = new QToolButton(this);
actionManageAccounts->setToolTip(tr("Manage your Mojang or Minecraft accounts."));
actionManageAccounts->setObjectName("actionManageAccounts");
actionManageAccounts->setText(tr("Manage accounts"));
actionManageAccounts->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
actionManageAccounts->setLayoutDirection(Qt::RightToLeft);
MojangAccountPtr account = MMC->accounts()->activeAccount();
if(account != nullptr)
{
auto job = new NetJob("Startup player skins: " + account->username());
for(AccountProfile profile : account->profiles())
{
auto meta = MMC->metacache()->resolveEntry("skins", profile.name() + ".png");
auto action = CacheDownload::make(
QUrl("http://skins.minecraft.net/MinecraftSkins/" + profile.name() + ".png"),
meta);
job->addNetAction(action);
meta->stale = true;
}
connect(job, SIGNAL(succeeded()), SLOT(activeAccountChanged()));
job->start();
}
connect(actionManageAccounts, SIGNAL(clicked()), this, SLOT(on_actionManageAccounts_triggered()));
ui->mainToolBar->addWidget(actionManageAccounts);
// run the things that load and download other things... FIXME: this is NOT the place // run the things that load and download other things... FIXME: this is NOT the place
// FIXME: invisible actions in the background = NOPE. // FIXME: invisible actions in the background = NOPE.
{ {
@ -196,6 +232,20 @@ MainWindow::~MainWindow()
delete assets_downloader; delete assets_downloader;
} }
void MainWindow::activeAccountChanged()
{
MojangAccountPtr account = MMC->accounts()->activeAccount();
if(account != nullptr)
{
const AccountProfile *profile = account->currentProfile();
if(profile != nullptr)
{
actionManageAccounts->setIcon(SkinUtils::getFaceFromCache(profile->name()));
}
}
}
bool MainWindow::eventFilter(QObject *obj, QEvent *ev) bool MainWindow::eventFilter(QObject *obj, QEvent *ev)
{ {
if (obj == view) if (obj == view)
@ -427,6 +477,7 @@ void MainWindow::on_actionSettings_triggered()
void MainWindow::on_actionManageAccounts_triggered() void MainWindow::on_actionManageAccounts_triggered()
{ {
AccountListDialog dialog(this); AccountListDialog dialog(this);
connect(&dialog, SIGNAL(activeAccountChanged()), SLOT(activeAccountChanged()));
dialog.exec(); dialog.exec();
} }
@ -612,51 +663,6 @@ void MainWindow::prepareLaunch(BaseInstance* instance, MojangAccountPtr account)
tDialog.exec(updateTask); tDialog.exec(updateTask);
delete updateTask; delete updateTask;
} }
QString playerName = account->currentProfile()->name();
auto job = new NetJob("Player skin: " + playerName);
auto meta = MMC->metacache()->resolveEntry("skins", playerName + ".png");
auto action = CacheDownload::make(
QUrl("http://skins.minecraft.net/MinecraftSkins/" + playerName + ".png"),
meta);
job->addNetAction(action);
meta->stale = true;
job->start();
auto filename = MMC->metacache()->resolveEntry("skins", "skins.json")->getFullPath();
QFile listFile(filename);
// Add skin mapping
QByteArray data;
{
if (!listFile.open(QIODevice::ReadWrite))
{
QLOG_ERROR() << "Failed to open/make skins list JSON";
return;
}
data = listFile.readAll();
}
QJsonParseError jsonError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
QJsonObject root = jsonDoc.object();
QJsonObject mappings = root.value("mappings").toObject();
QJsonArray usernames = mappings.value(account->username()).toArray();
if (!usernames.contains(playerName))
{
usernames.prepend(playerName);
mappings[account->username()] = usernames;
root["mappings"] = mappings;
jsonDoc.setObject(root);
// QJson hack - shouldn't have to clear the file every time a save happens
listFile.resize(0);
listFile.write(jsonDoc.toJson());
}
} }
void MainWindow::launchInstance(BaseInstance *instance, MojangAccountPtr account) void MainWindow::launchInstance(BaseInstance *instance, MojangAccountPtr account)

View File

@ -146,6 +146,8 @@ slots:
void startTask(Task *task); void startTask(Task *task);
void activeAccountChanged();
protected: protected:
bool eventFilter(QObject *obj, QEvent *ev); bool eventFilter(QObject *obj, QEvent *ev);
void setCatBackground(bool enabled); void setCatBackground(bool enabled);
@ -167,4 +169,6 @@ private:
QLabel *m_statusLeft; QLabel *m_statusLeft;
QLabel *m_statusRight; QLabel *m_statusRight;
QToolButton *actionManageAccounts;
}; };

View File

@ -70,7 +70,6 @@
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionCheckUpdate"/> <addaction name="actionCheckUpdate"/>
<addaction name="actionSettings"/> <addaction name="actionSettings"/>
<addaction name="actionManageAccounts"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionReportBug"/> <addaction name="actionReportBug"/>
<addaction name="actionNews"/> <addaction name="actionNews"/>

View File

@ -21,6 +21,7 @@
#include <logger/QsLog.h> #include <logger/QsLog.h>
#include <logic/auth/AuthenticateTask.h> #include <logic/auth/AuthenticateTask.h>
#include <logic/net/NetJob.h>
#include <gui/dialogs/LoginDialog.h> #include <gui/dialogs/LoginDialog.h>
#include <gui/dialogs/ProgressDialog.h> #include <gui/dialogs/ProgressDialog.h>
@ -56,6 +57,8 @@ void AccountListDialog::on_rmAccountBtn_clicked()
{ {
QModelIndex selected = selection.first(); QModelIndex selected = selection.first();
m_accounts->removeAccount(selected); m_accounts->removeAccount(selected);
emit activeAccountChanged();
} }
} }
@ -72,7 +75,9 @@ void AccountListDialog::on_setActiveBtn_clicked()
QModelIndex selected = selection.first(); QModelIndex selected = selection.first();
MojangAccountPtr account = selected.data(MojangAccountList::PointerRole).value<MojangAccountPtr>(); MojangAccountPtr account = selected.data(MojangAccountList::PointerRole).value<MojangAccountPtr>();
m_accounts->setActiveAccount(account->username()); m_accounts->setActiveAccount(account->username());
}
emit activeAccountChanged();
}
} }
void AccountListDialog::on_closeBtnBox_rejected() void AccountListDialog::on_closeBtnBox_rejected()
@ -108,5 +113,21 @@ void AccountListDialog::onLoginComplete()
MojangAccountPtr account = m_authTask->getMojangAccount(); MojangAccountPtr account = m_authTask->getMojangAccount();
m_accounts->addAccount(account); m_accounts->addAccount(account);
//ui->listView->update(); //ui->listView->update();
// Grab associated player skins
auto job = new NetJob("Player skins: " + account->username());
for(AccountProfile profile : account->profiles())
{
auto meta = MMC->metacache()->resolveEntry("skins", profile.name() + ".png");
auto action = CacheDownload::make(
QUrl("http://skins.minecraft.net/MinecraftSkins/" + profile.name() + ".png"),
meta);
job->addNetAction(action);
meta->stale = true;
}
connect(job, SIGNAL(succeeded()), SIGNAL(activeAccountChanged()));
job->start();
} }

View File

@ -47,6 +47,9 @@ slots:
// This will be sent when the "close" button is clicked. // This will be sent when the "close" button is clicked.
void on_closeBtnBox_rejected(); void on_closeBtnBox_rejected();
signals:
void activeAccountChanged();
protected: protected:
std::shared_ptr<MojangAccountList> m_accounts; std::shared_ptr<MojangAccountList> m_accounts;

View File

@ -18,6 +18,7 @@
#include "keyring.h" #include "keyring.h"
#include "gui/Platform.h" #include "gui/Platform.h"
#include "MultiMC.h" #include "MultiMC.h"
#include "logic/SkinUtils.h"
#include <QFile> #include <QFile>
#include <QJsonObject> #include <QJsonObject>
@ -168,47 +169,10 @@ void LoginDialog::userTextChanged(const QString &user)
ui->rememberPasswordCheckbox->setChecked(!passwd.isEmpty()); ui->rememberPasswordCheckbox->setChecked(!passwd.isEmpty());
ui->passwordTextBox->setText(passwd); ui->passwordTextBox->setText(passwd);
QByteArray data; QPixmap face = SkinUtils::getFaceFromCache(user);
{ gotFace = !face.isNull();
auto filename =
MMC->metacache()->resolveEntry("skins", "skins.json")->getFullPath();
QFile listFile(filename);
if (!listFile.open(QIODevice::ReadOnly))
return;
data = listFile.readAll();
}
QJsonParseError jsonError; if(gotFace) ui->lblFace->setPixmap(face);
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
QJsonObject root = jsonDoc.object();
QJsonObject mappings = root.value("mappings").toObject();
if (!mappings[user].isUndefined())
{
QJsonArray usernames = mappings.value(user).toArray();
if (!usernames.isEmpty())
{
QString mapped_username = usernames[0].toString();
if (!mapped_username.isEmpty())
{
QFile fskin(MMC->metacache()
->resolveEntry("skins", mapped_username + ".png")
->getFullPath());
if (fskin.exists())
{
QPixmap skin(MMC->metacache()
->resolveEntry("skins", mapped_username + ".png")
->getFullPath());
QPixmap face =
skin.copy(8, 8, 8, 8).scaled(48, 48, Qt::KeepAspectRatio);
ui->lblFace->setPixmap(face);
gotFace = true;
}
}
}
}
} }
ui->lblFace->setVisible(gotFace); ui->lblFace->setVisible(gotFace);

47
logic/SkinUtils.cpp Normal file
View File

@ -0,0 +1,47 @@
/* Copyright 2013 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "MultiMC.h"
#include "logic/SkinUtils.h"
#include "net/HttpMetaCache.h"
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
namespace SkinUtils
{
/*
* Given a username, return a pixmap of the cached skin (if it exists), QPixmap() otherwise
*/
QPixmap getFaceFromCache(QString username, int height, int width)
{
QFile fskin(MMC->metacache()
->resolveEntry("skins", username + ".png")
->getFullPath());
if (fskin.exists())
{
QPixmap skin(fskin.fileName());
if(!skin.isNull())
{
return skin.copy(8, 8, 8, 8).scaled(height, width, Qt::KeepAspectRatio);
}
}
return QPixmap();
}
}

23
logic/SkinUtils.h Normal file
View File

@ -0,0 +1,23 @@
/* Copyright 2013 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <QPixmap>
namespace SkinUtils
{
QPixmap getFaceFromCache(QString username, int height = 48, int width = 48);
}