Add/remove/drag&drop for the icon picker.

This commit is contained in:
Petr Mrázek 2013-08-27 05:39:49 +02:00
parent e6999b3b62
commit 5573ed52e8
9 changed files with 210 additions and 35 deletions

View File

@ -2,6 +2,9 @@
#include "instancedelegate.h" #include "instancedelegate.h"
#include "ui_IconPickerDialog.h" #include "ui_IconPickerDialog.h"
#include "logic/IconListModel.h" #include "logic/IconListModel.h"
#include <QKeyEvent>
#include <QPushButton>
#include <QFileDialog>
IconPickerDialog::IconPickerDialog(QWidget *parent) : IconPickerDialog::IconPickerDialog(QWidget *parent) :
QDialog(parent), QDialog(parent),
@ -25,9 +28,24 @@ IconPickerDialog::IconPickerDialog(QWidget *parent) :
contentsWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); contentsWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
contentsWidget->setItemDelegate(new ListViewDelegate()); contentsWidget->setItemDelegate(new ListViewDelegate());
//contentsWidget->setAcceptDrops(true);
contentsWidget->setDropIndicatorShown(true);
contentsWidget->viewport()->setAcceptDrops(true);
contentsWidget->setDragDropMode(QAbstractItemView::DropOnly);
contentsWidget->setDefaultDropAction(Qt::CopyAction);
contentsWidget->installEventFilter(this);
IconList * list = IconList::instance(); IconList * list = IconList::instance();
contentsWidget->setModel(list); contentsWidget->setModel(list);
auto buttonAdd = ui->buttonBox->addButton("Add Icon",QDialogButtonBox::ResetRole);
auto buttonRemove = ui->buttonBox->addButton("Remove Icon",QDialogButtonBox::ResetRole);
connect(buttonAdd,SIGNAL(clicked(bool)),SLOT(addNewIcon()));
connect(buttonRemove,SIGNAL(clicked(bool)),SLOT(removeSelectedIcon()));
connect connect
( (
contentsWidget, contentsWidget,
@ -42,6 +60,43 @@ IconPickerDialog::IconPickerDialog(QWidget *parent) :
SLOT(selectionChanged(QItemSelection,QItemSelection)) SLOT(selectionChanged(QItemSelection,QItemSelection))
); );
} }
bool IconPickerDialog::eventFilter ( QObject* obj, QEvent* evt)
{
if(obj != ui->iconView)
return QDialog::eventFilter(obj ,evt);
if (evt->type() != QEvent::KeyPress)
{
return QDialog::eventFilter(obj ,evt);
}
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(evt);
IconList * list = IconList::instance();
switch(keyEvent->key())
{
case Qt::Key_Delete:
removeSelectedIcon();
return true;
case Qt::Key_Plus:
addNewIcon();
return true;
default:
break;
}
return QDialog::eventFilter(obj ,evt);
}
void IconPickerDialog::addNewIcon()
{
QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Icons", QString(), "Icons (*.png *.jpg *.jpeg)");
IconList * list = IconList::instance();
list->installIcons(fileNames);
}
void IconPickerDialog::removeSelectedIcon()
{
IconList * list = IconList::instance();
list->deleteIcon(selectedIconKey);
}
void IconPickerDialog::activated ( QModelIndex index ) void IconPickerDialog::activated ( QModelIndex index )
{ {

View File

@ -15,7 +15,8 @@ public:
~IconPickerDialog(); ~IconPickerDialog();
int exec(QString selection); int exec(QString selection);
QString selectedIconKey; QString selectedIconKey;
protected:
virtual bool eventFilter ( QObject* , QEvent* );
private: private:
Ui::IconPickerDialog *ui; Ui::IconPickerDialog *ui;
@ -23,4 +24,6 @@ private slots:
void selectionChanged ( QItemSelection,QItemSelection ); void selectionChanged ( QItemSelection,QItemSelection );
void activated ( QModelIndex ); void activated ( QModelIndex );
void delayed_scroll ( QModelIndex ); void delayed_scroll ( QModelIndex );
void addNewIcon();
void removeSelectedIcon();
}; };

View File

@ -1,23 +1,24 @@
#include "aboutdialog.h" #include "aboutdialog.h"
#include "ui_aboutdialog.h" #include "ui_aboutdialog.h"
#include <AppVersion.h>
#include <QIcon> #include <QIcon>
#include <QApplication> #include <QApplication>
AboutDialog::AboutDialog(QWidget *parent) : AboutDialog::AboutDialog(QWidget *parent) :
QDialog(parent), QDialog(parent),
ui(new Ui::AboutDialog) ui(new Ui::AboutDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->icon->setPixmap(QIcon(":/icons/multimc/scalable/apps/multimc.svg").pixmap(64)); ui->icon->setPixmap(QIcon(":/icons/multimc/scalable/apps/multimc.svg").pixmap(64));
ui->title->setText("MultiMC " + AppVersion::current.toString());
connect(ui->closeButton, SIGNAL(clicked()), SLOT(close()));
connect(ui->closeButton, SIGNAL(clicked()), SLOT(close())); QApplication::instance()->connect(ui->aboutQt, SIGNAL(clicked()), SLOT(aboutQt()));
QApplication::instance()->connect(ui->aboutQt, SIGNAL(clicked()), SLOT(aboutQt()));
} }
AboutDialog::~AboutDialog() AboutDialog::~AboutDialog()
{ {
delete ui; delete ui;
} }

View File

@ -42,13 +42,6 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QCheckBox" name="compatModeCheckBox">
<property name="text">
<string>Compatibility mode?</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QCheckBox" name="maximizedCheckBox"> <widget class="QCheckBox" name="maximizedCheckBox">
<property name="text"> <property name="text">
@ -403,7 +396,6 @@
<tabstops> <tabstops>
<tabstop>settingsTabs</tabstop> <tabstop>settingsTabs</tabstop>
<tabstop>windowSizeGroupBox</tabstop> <tabstop>windowSizeGroupBox</tabstop>
<tabstop>compatModeCheckBox</tabstop>
<tabstop>maximizedCheckBox</tabstop> <tabstop>maximizedCheckBox</tabstop>
<tabstop>windowWidthSpinBox</tabstop> <tabstop>windowWidthSpinBox</tabstop>
<tabstop>windowHeightSpinBox</tabstop> <tabstop>windowHeightSpinBox</tabstop>

View File

@ -87,6 +87,7 @@ MainWindow::MainWindow ( QWidget *parent ) :
// the rename label is inside the rename tool button // the rename label is inside the rename tool button
renameButton = new LabeledToolButton(); renameButton = new LabeledToolButton();
renameButton->setText("Instance Name"); renameButton->setText("Instance Name");
renameButton->setToolTip(ui->actionRenameInstance->toolTip());
connect(renameButton, SIGNAL(clicked(bool)), SLOT(on_actionRenameInstance_triggered())); connect(renameButton, SIGNAL(clicked(bool)), SLOT(on_actionRenameInstance_triggered()));
ui->instanceToolBar->insertWidget(ui->actionLaunchInstance, renameButton); ui->instanceToolBar->insertWidget(ui->actionLaunchInstance, renameButton);
ui->instanceToolBar->insertSeparator(ui->actionLaunchInstance); ui->instanceToolBar->insertSeparator(ui->actionLaunchInstance);

View File

@ -43,12 +43,8 @@ void SettingsDialog::showEvent ( QShowEvent* ev )
void SettingsDialog::updateCheckboxStuff() void SettingsDialog::updateCheckboxStuff()
{ {
ui->windowWidthSpinBox->setEnabled(!(ui->compatModeCheckBox->isChecked() || ui->windowWidthSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
ui->maximizedCheckBox->isChecked())); ui->windowHeightSpinBox->setEnabled(! ui->maximizedCheckBox->isChecked());
ui->windowHeightSpinBox->setEnabled(!(ui->compatModeCheckBox->isChecked() ||
ui->maximizedCheckBox->isChecked()));
ui->maximizedCheckBox->setEnabled(!ui->compatModeCheckBox->isChecked());
} }
void SettingsDialog::on_instDirBrowseBtn_clicked() void SettingsDialog::on_instDirBrowseBtn_clicked()

View File

@ -54,6 +54,9 @@
<property name="text"> <property name="text">
<string>By last launched</string> <string>By last launched</string>
</property> </property>
<attribute name="buttonGroup">
<string notr="true">sortingModeGroup</string>
</attribute>
</widget> </widget>
</item> </item>
<item> <item>
@ -61,6 +64,9 @@
<property name="text"> <property name="text">
<string>By name</string> <string>By name</string>
</property> </property>
<attribute name="buttonGroup">
<string notr="true">sortingModeGroup</string>
</attribute>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -175,13 +181,6 @@
<string>Window Size</string> <string>Window Size</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QCheckBox" name="compatModeCheckBox">
<property name="text">
<string>Compatibility mode?</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QCheckBox" name="maximizedCheckBox"> <widget class="QCheckBox" name="maximizedCheckBox">
<property name="text"> <property name="text">
@ -504,4 +503,7 @@
</hints> </hints>
</connection> </connection>
</connections> </connections>
<buttongroups>
<buttongroup name="sortingModeGroup"/>
</buttongroups>
</ui> </ui>

View File

@ -3,7 +3,8 @@
#include <QMap> #include <QMap>
#include <QEventLoop> #include <QEventLoop>
#include <QDir> #include <QDir>
#include <QMimeData>
#include <QUrl>
#define MAX_SIZE 1024 #define MAX_SIZE 1024
IconList* IconList::m_Instance = 0; IconList* IconList::m_Instance = 0;
QMutex IconList::mutex; QMutex IconList::mutex;
@ -14,6 +15,7 @@ struct entry
QString name; QString name;
QIcon icon; QIcon icon;
bool is_builtin; bool is_builtin;
QString filename;
}; };
class Private : public QObject class Private : public QObject
@ -56,6 +58,61 @@ IconList::~IconList()
d = nullptr; d = nullptr;
} }
QStringList IconList::mimeTypes() const
{
QStringList types;
types << "text/uri-list";
return types;
}
Qt::DropActions IconList::supportedDropActions() const
{
return Qt::CopyAction;
}
bool IconList::dropMimeData ( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent )
{
if (action == Qt::IgnoreAction)
return true;
// check if the action is supported
if (!data || !(action & supportedDropActions()))
return false;
// files dropped from outside?
if(data->hasUrls())
{
/*
bool was_watching = is_watching;
if(was_watching)
stopWatching();
*/
auto urls = data->urls();
QStringList iconFiles;
for(auto url: urls)
{
// only local files may be dropped...
if(!url.isLocalFile())
continue;
iconFiles += url.toLocalFile();
}
installIcons(iconFiles);
/*
if(was_watching)
startWatching();
*/
return true;
}
return false;
}
Qt::ItemFlags IconList::flags ( const QModelIndex& index ) const
{
Qt::ItemFlags defaultFlags = QAbstractListModel::flags ( index );
if (index.isValid())
return Qt::ItemIsDropEnabled | defaultFlags;
else
return Qt::ItemIsDropEnabled | defaultFlags;
}
QVariant IconList::data ( const QModelIndex& index, int role ) const QVariant IconList::data ( const QModelIndex& index, int role ) const
{ {
if(!index.isValid()) if(!index.isValid())
@ -84,18 +141,65 @@ int IconList::rowCount ( const QModelIndex& parent ) const
return d->icons.size(); return d->icons.size();
} }
void IconList::installIcons ( QStringList iconFiles )
{
for(QString file: iconFiles)
{
QFileInfo fileinfo(file);
if(!fileinfo.isReadable() || !fileinfo.isFile())
continue;
QString target = PathCombine("icons", fileinfo.fileName());
QString suffix = fileinfo.suffix();
if(suffix != "jpeg" && suffix != "png" && suffix != "jpg")
continue;
if(!QFile::copy(file, target))
continue;
QString key = fileinfo.baseName();
addIcon(key, key, target);
}
}
bool IconList::deleteIcon ( QString key )
{
int iconIdx = getIconIndex(key);
if(iconIdx == -1)
return false;
auto & iconEntry = d->icons[iconIdx];
if(iconEntry.is_builtin)
return false;
if(QFile::remove(iconEntry.filename))
{
beginRemoveRows(QModelIndex(), iconIdx, iconIdx);
d->icons.remove(iconIdx);
reindex();
endRemoveRows();
}
return true;
}
bool IconList::addIcon ( QString key, QString name, QString path, bool is_builtin ) bool IconList::addIcon ( QString key, QString name, QString path, bool is_builtin )
{ {
auto iter = d->index.find(key); auto iter = d->index.find(key);
if(iter != d->index.end()) if(iter != d->index.end())
{ {
if(d->icons[*iter].is_builtin) return false; if(d->icons[*iter].is_builtin)
return false;
QIcon icon(path); QIcon icon(path);
if(icon.isNull()) return false; if(icon.isNull())
return false;
auto & oldOne = d->icons[*iter];
if(!QFile::remove(oldOne.filename))
return false;
// replace the icon // replace the icon
d->icons[*iter] = {key, name, icon, is_builtin}; oldOne = {key, name, icon, is_builtin, path};
dataChanged(index(*iter),index(*iter));
return true; return true;
} }
else else
@ -104,12 +208,25 @@ bool IconList::addIcon ( QString key, QString name, QString path, bool is_builti
if(icon.isNull()) return false; if(icon.isNull()) return false;
// add a new icon // add a new icon
d->icons.push_back({key, name, icon, is_builtin}); beginInsertRows(QModelIndex(), d->icons.size(),d->icons.size());
d->icons.push_back({key, name, icon, is_builtin, path});
d->index[key] = d->icons.size() - 1; d->index[key] = d->icons.size() - 1;
endInsertRows();
return true; return true;
} }
} }
void IconList::reindex()
{
d->index.clear();
int i = 0;
for(auto& iter: d->icons)
{
d->index[iter.key] = i;
i++;
}
}
QIcon IconList::getIcon ( QString key ) QIcon IconList::getIcon ( QString key )
{ {

View File

@ -18,7 +18,14 @@ public:
virtual int rowCount ( const QModelIndex& parent = QModelIndex() ) const; virtual int rowCount ( const QModelIndex& parent = QModelIndex() ) const;
bool addIcon(QString key, QString name, QString path, bool is_builtin = false); bool addIcon(QString key, QString name, QString path, bool is_builtin = false);
bool deleteIcon(QString key);
virtual QStringList mimeTypes() const;
virtual Qt::DropActions supportedDropActions() const;
virtual bool dropMimeData ( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent );
virtual Qt::ItemFlags flags ( const QModelIndex& index ) const;
void installIcons ( QStringList iconFiles );
private: private:
virtual ~IconList(); virtual ~IconList();
@ -27,6 +34,7 @@ private:
IconList ( const IconList & ) = delete; IconList ( const IconList & ) = delete;
// hide assign op // hide assign op
IconList& operator= ( const IconList & ) = delete; IconList& operator= ( const IconList & ) = delete;
void reindex();
static IconList* m_Instance; static IconList* m_Instance;
static QMutex mutex; static QMutex mutex;
Private* d; Private* d;