Implement icon picker, bring back raster icons.

This commit is contained in:
Petr Mrázek
2013-08-10 18:34:08 +02:00
parent bf5f5091ef
commit 1782d5ad9a
75 changed files with 1098 additions and 424 deletions

88
gui/IconPickerDialog.cpp Normal file
View File

@ -0,0 +1,88 @@
#include "IconPickerDialog.h"
#include "instancedelegate.h"
#include "ui_IconPickerDialog.h"
#include <IconListModel.h>
IconPickerDialog::IconPickerDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::IconPickerDialog)
{
ui->setupUi(this);
auto contentsWidget = ui->iconView;
contentsWidget->setViewMode(QListView::IconMode);
contentsWidget->setFlow(QListView::LeftToRight);
contentsWidget->setIconSize(QSize(48, 48));
contentsWidget->setMovement(QListView::Static);
contentsWidget->setResizeMode(QListView::Adjust);
contentsWidget->setSelectionMode(QAbstractItemView::SingleSelection);
contentsWidget->setSpacing(5);
contentsWidget->setWordWrap(false);
contentsWidget->setWrapping(true);
contentsWidget->setUniformItemSizes(true);
contentsWidget->setTextElideMode(Qt::ElideRight);
contentsWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
contentsWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
contentsWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
contentsWidget->setItemDelegate(new ListViewDelegate());
IconList * list = IconList::instance();
contentsWidget->setModel(list);
connect
(
contentsWidget,
SIGNAL(doubleClicked(QModelIndex)),
SLOT(activated(QModelIndex))
);
connect
(
contentsWidget->selectionModel(),
SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
SLOT(selectionChanged(QItemSelection,QItemSelection))
);
}
void IconPickerDialog::activated ( QModelIndex index )
{
selectedIconKey = index.data(Qt::UserRole).toString();
accept();
}
void IconPickerDialog::selectionChanged ( QItemSelection selected, QItemSelection deselected )
{
if(selected.empty())
return;
QString key = selected.first().indexes().first().data(Qt::UserRole).toString();
if(!key.isEmpty())
selectedIconKey = key;
}
int IconPickerDialog::exec ( QString selection )
{
IconList * list = IconList::instance();
auto contentsWidget = ui->iconView;
selectedIconKey = selection;
int index_nr = list->getIconIndex(selection);
auto model_index = list->index(index_nr);
contentsWidget->selectionModel()->select(model_index, QItemSelectionModel::Current | QItemSelectionModel::Select);
QMetaObject::invokeMethod(this, "delayed_scroll", Qt::QueuedConnection, Q_ARG(QModelIndex,model_index));
return QDialog::exec();
}
void IconPickerDialog::delayed_scroll ( QModelIndex model_index )
{
auto contentsWidget = ui->iconView;
contentsWidget->scrollTo(model_index);
}
IconPickerDialog::~IconPickerDialog()
{
delete ui;
}

26
gui/IconPickerDialog.h Normal file
View File

@ -0,0 +1,26 @@
#pragma once
#include <QDialog>
#include <QItemSelection>
namespace Ui {
class IconPickerDialog;
}
class IconPickerDialog : public QDialog
{
Q_OBJECT
public:
explicit IconPickerDialog(QWidget *parent = 0);
~IconPickerDialog();
int exec(QString selection);
QString selectedIconKey;
private:
Ui::IconPickerDialog *ui;
private slots:
void selectionChanged ( QItemSelection,QItemSelection );
void activated ( QModelIndex );
void delayed_scroll ( QModelIndex );
};

67
gui/IconPickerDialog.ui Normal file
View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>IconPickerDialog</class>
<widget class="QDialog" name="IconPickerDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>676</width>
<height>555</height>
</rect>
</property>
<property name="windowTitle">
<string>Pick icon</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QListView" name="iconView"/>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>IconPickerDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>IconPickerDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,127 +0,0 @@
#include "iconcache.h"
#include <QMap>
#include <QWebView>
#include <QWebFrame>
#include <QEventLoop>
#include <QWebElement>
IconCache* IconCache::m_Instance = 0;
QMutex IconCache::mutex;
#define MAX_SIZE 1024
class Private : public QWebView
{
Q_OBJECT
public:
QString name;
QSize size;
QMap<QString, QIcon> icons;
public:
Private()
{
connect(this, SIGNAL(loadFinished(bool)), this, SLOT(svgLoaded(bool)));
setFixedSize(MAX_SIZE, MAX_SIZE);
QPalette pal = palette();
pal.setColor(QPalette::Base, Qt::transparent);
setPalette(pal);
setAttribute(Qt::WA_OpaquePaintEvent, false);
size = QSize(128,128);
}
void renderSVGIcon(QString name);
signals:
void svgRendered();
private slots:
void svgLoaded(bool ok);
};
void Private::svgLoaded(bool ok)
{
if (!ok)
{
emit svgRendered();
return;
}
// check for SVG root tag
QString root = page()->currentFrame()->documentElement().tagName();
if (root.compare("svg", Qt::CaseInsensitive) != 0)
{
emit svgRendered();
return;
}
// get the size of the svg image, check if it's valid
auto elem = page()->currentFrame()->documentElement();
double width = elem.attribute("width").toDouble();
double height = elem.attribute("height").toDouble();
if (width == 0.0 || height == 0.0 || width == MAX_SIZE || height == MAX_SIZE)
{
emit svgRendered();
return;
}
// create the target surface
QSize t = size.isValid() ? size : QSize(width, height);
QImage img(t, QImage::Format_ARGB32_Premultiplied);
img.fill(Qt::transparent);
// prepare the painter, scale to required size
QPainter p(&img);
if(size.isValid())
{
p.scale(size.width() / width, size.height() / height);
}
// the best quality
p.setRenderHint(QPainter::Antialiasing);
p.setRenderHint(QPainter::TextAntialiasing);
p.setRenderHint(QPainter::SmoothPixmapTransform);
page()->mainFrame()->render(&p,QWebFrame::ContentsLayer);
p.end();
icons[name] = QIcon(QPixmap::fromImage(img));
emit svgRendered();
}
void Private::renderSVGIcon ( QString name )
{
// use event loop to wait for signal
QEventLoop loop;
this->name = name;
QString prefix = "qrc:/icons/instances/";
QObject::connect(this, SIGNAL(svgRendered()), &loop, SLOT(quit()));
load(QUrl(prefix + name));
loop.exec();
}
IconCache::IconCache():d(new Private())
{
}
QIcon IconCache::getIcon ( QString name )
{
if(name == "default")
name = "infinity";
{
auto iter = d->icons.find(name);
if(iter != d->icons.end())
return *iter;
}
d->renderSVGIcon(name);
auto iter = d->icons.find(name);
if(iter != d->icons.end())
return *iter;
// Fallback for icons that don't exist.
QString path = ":/icons/instances/infinity";
//path += name;
d->icons[name] = QIcon(path);
return d->icons[name];
}
#include "iconcache.moc"

View File

@ -1,43 +0,0 @@
#pragma once
#include <QMutex>
#include <QtGui/QIcon>
class Private;
class IconCache
{
public:
static IconCache* instance()
{
if (!m_Instance)
{
mutex.lock();
if (!m_Instance)
m_Instance = new IconCache;
mutex.unlock();
}
return m_Instance;
}
static void drop()
{
mutex.lock();
delete m_Instance;
m_Instance = 0;
mutex.unlock();
}
QIcon getIcon(QString name);
private:
IconCache();
// hide copy constructor
IconCache(const IconCache &);
// hide assign op
IconCache& operator=(const IconCache &);
static IconCache* m_Instance;
static QMutex mutex;
Private* d;
};

View File

@ -1,7 +1,8 @@
#include "instancemodel.h"
#include <BaseInstance.h>
#include <IconListModel.h>
#include <QIcon>
#include "iconcache.h"
//#include "iconcache.h"
InstanceModel::InstanceModel ( const InstanceList& instances, QObject *parent )
: QAbstractListModel ( parent ), m_instances ( &instances )
@ -71,7 +72,7 @@ QVariant InstanceModel::data ( const QModelIndex& index, int role ) const
}
case Qt::DecorationRole:
{
IconCache * ic = IconCache::instance();
IconList * ic = IconList::instance();
// FIXME: replace with an icon cache/renderer
/*
QString path = ":/icons/instances/";

View File

@ -62,6 +62,7 @@
#include "instancemodel.h"
#include "instancedelegate.h"
#include "IconPickerDialog.h"
#include "lists/MinecraftVersionList.h"
#include "lists/LwjglVersionList.h"
@ -178,23 +179,24 @@ void MainWindow::on_actionAddInstance_triggered()
waitLoop.exec();
}
NewInstanceDialog *newInstDlg = new NewInstanceDialog ( this );
if (!newInstDlg->exec())
NewInstanceDialog newInstDlg( this );
if (!newInstDlg.exec())
return;
BaseInstance *newInstance = NULL;
QString instDirName = DirNameFromString(newInstDlg->instName());
QString instDirName = DirNameFromString(newInstDlg.instName());
QString instDir = PathCombine(globalSettings->get("InstanceDir").toString(), instDirName);
auto &loader = InstanceFactory::get();
auto error = loader.createInstance(newInstance, newInstDlg->selectedVersion(), instDir);
auto error = loader.createInstance(newInstance, newInstDlg.selectedVersion(), instDir);
QString errorMsg = QString("Failed to create instance %1: ").arg(instDirName);
switch (error)
{
case InstanceFactory::NoCreateError:
newInstance->setName(newInstDlg->instName());
newInstance->setName(newInstDlg.instName());
newInstance->setIconKey(newInstDlg.iconKey());
instList.add(InstancePtr(newInstance));
return;
@ -215,20 +217,33 @@ void MainWindow::on_actionAddInstance_triggered()
}
}
void MainWindow::on_actionChangeInstIcon_triggered()
{
BaseInstance* inst = selectedInstance();
if(!inst)
return;
IconPickerDialog dlg(this);
dlg.exec(selectedInstance()->iconKey());
if(dlg.result() == QDialog::Accepted)
{
selectedInstance()->setIconKey(dlg.selectedIconKey);
}
}
void MainWindow::on_actionChangeInstGroup_triggered()
{
BaseInstance* inst = selectedInstance();
if(inst)
{
bool ok = false;
QString name ( inst->group() );
QInputDialog dlg(this);
dlg.result();
name = QInputDialog::getText ( this, tr ( "Group name" ), tr ( "Enter a new group name." ),
QLineEdit::Normal, name, &ok );
if(ok)
inst->setGroup(name);
}
if(!inst)
return;
bool ok = false;
QString name ( inst->group() );
name = QInputDialog::getText ( this, tr ( "Group name" ), tr ( "Enter a new group name." ),
QLineEdit::Normal, name, &ok );
if(ok)
inst->setGroup(name);
}
@ -390,7 +405,8 @@ void MainWindow::doLogin(const QString& errorMsg)
return;
LoginDialog* loginDlg = new LoginDialog(this, errorMsg);
if (loginDlg->exec())
loginDlg->exec();
if(loginDlg->result() == QDialog::Accepted)
{
UserInfo uInfo{loginDlg->getUsername(), loginDlg->getPassword()};
@ -515,10 +531,10 @@ void MainWindow::on_actionChangeInstMCVersion_triggered()
BaseInstance *inst = selectedInstance();
VersionSelectDialog *vselect = new VersionSelectDialog(inst->versionList(), this);
if (vselect->exec() && vselect->selectedVersion())
VersionSelectDialog vselect(inst->versionList(), this);
if (vselect.exec() && vselect.selectedVersion())
{
inst->setIntendedVersionId(vselect->selectedVersion()->descriptor());
inst->setIntendedVersionId(vselect.selectedVersion()->descriptor());
}
}
@ -529,8 +545,9 @@ void MainWindow::on_actionChangeInstLWJGLVersion_triggered()
if (!inst)
return;
LWJGLSelectDialog *lselect = new LWJGLSelectDialog(this);
if (lselect->exec())
LWJGLSelectDialog lselect(this);
lselect.exec();
if (lselect.result() == QDialog::Accepted)
{
}

View File

@ -63,6 +63,8 @@ private slots:
void on_actionChangeInstGroup_triggered();
void on_actionChangeInstIcon_triggered();
void on_actionViewInstanceFolder_triggered();
void on_actionViewSelectedInstFolder_triggered();

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>692</width>
<height>596</height>
<width>688</width>
<height>650</height>
</rect>
</property>
<property name="windowTitle">
@ -71,6 +71,9 @@
<property name="windowTitle">
<string>Instance Toolbar</string>
</property>
<property name="allowedAreas">
<set>Qt::LeftToolBarArea|Qt::RightToolBarArea</set>
</property>
<property name="floatable">
<bool>false</bool>
</property>
@ -275,7 +278,7 @@
</action>
<action name="actionChangeInstIcon">
<property name="enabled">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="text">
<string>Change Icon</string>
@ -345,7 +348,7 @@
</action>
<action name="actionEditInstMods">
<property name="enabled">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="text">
<string>Edit Mods</string>
@ -358,6 +361,9 @@
</property>
</action>
<action name="actionChangeInstMCVersion">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Change Version</string>
</property>
@ -369,6 +375,9 @@
</property>
</action>
<action name="actionChangeInstLWJGLVersion">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Change LWJGL</string>
</property>
@ -380,6 +389,9 @@
</property>
</action>
<action name="actionRebuildInstJar">
<property name="checkable">
<bool>false</bool>
</property>
<property name="enabled">
<bool>false</bool>
</property>

View File

@ -22,9 +22,11 @@
#include "InstanceVersion.h"
#include "tasks/Task.h"
#include <IconListModel.h>
#include "versionselectdialog.h"
#include "taskdialog.h"
#include "IconPickerDialog.h"
#include <QLayout>
#include <QPushButton>
@ -40,7 +42,7 @@ NewInstanceDialog::NewInstanceDialog(QWidget *parent) :
ui->setupUi(this);
resize(minimumSizeHint());
layout()->setSizeConstraint(QLayout::SetFixedSize);
/*
if (!MinecraftVersionList::getMainList().isLoaded())
{
TaskDialog *taskDlg = new TaskDialog(this);
@ -48,7 +50,11 @@ NewInstanceDialog::NewInstanceDialog(QWidget *parent) :
loadTask->setParent(taskDlg);
taskDlg->exec(loadTask);
}
*/
setSelectedVersion(MinecraftVersionList::getMainList().getLatestStable());
InstIconKey = "infinity";
IconList * list = IconList::instance();
ui->iconButton->setIcon(list->getIcon(InstIconKey));
}
NewInstanceDialog::~NewInstanceDialog()
@ -85,8 +91,7 @@ QString NewInstanceDialog::instName() const
QString NewInstanceDialog::iconKey() const
{
// TODO: Implement icon stuff.
return "default";
return InstIconKey;
}
const InstVersion *NewInstanceDialog::selectedVersion() const
@ -96,15 +101,29 @@ const InstVersion *NewInstanceDialog::selectedVersion() const
void NewInstanceDialog::on_btnChangeVersion_clicked()
{
VersionSelectDialog *vselect = new VersionSelectDialog(&MinecraftVersionList::getMainList(), this);
if (vselect->exec())
VersionSelectDialog vselect(&MinecraftVersionList::getMainList(), this);
vselect.exec();
if (vselect.result() == QDialog::Accepted)
{
const InstVersion *version = vselect->selectedVersion();
const InstVersion *version = vselect.selectedVersion();
if (version)
setSelectedVersion(version);
}
}
void NewInstanceDialog::on_iconButton_clicked()
{
IconPickerDialog dlg;
dlg.exec(InstIconKey);
if(dlg.result() == QDialog::Accepted)
{
IconList * list = IconList::instance();
InstIconKey = dlg.selectedIconKey;
ui->iconButton->setIcon(list->getIcon(InstIconKey));
}
}
void NewInstanceDialog::on_instNameTextBox_textChanged(const QString &arg1)
{
updateDialogState();

View File

@ -45,13 +45,14 @@ public:
private slots:
void on_btnChangeVersion_clicked();
void on_iconButton_clicked();
void on_instNameTextBox_textChanged(const QString &arg1);
private:
Ui::NewInstanceDialog *ui;
const InstVersion *m_selectedVersion;
QString InstIconKey;
};
#endif // NEWINSTANCEDIALOG_H