Add/remove/drag&drop for the icon picker.
This commit is contained in:
		@@ -3,7 +3,8 @@
 | 
			
		||||
#include <QMap>
 | 
			
		||||
#include <QEventLoop>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
 | 
			
		||||
#include <QMimeData>
 | 
			
		||||
#include <QUrl>
 | 
			
		||||
#define MAX_SIZE 1024
 | 
			
		||||
IconList* IconList::m_Instance = 0;
 | 
			
		||||
QMutex IconList::mutex;
 | 
			
		||||
@@ -14,6 +15,7 @@ struct entry
 | 
			
		||||
	QString name;
 | 
			
		||||
	QIcon icon;
 | 
			
		||||
	bool is_builtin;
 | 
			
		||||
	QString filename;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Private : public QObject
 | 
			
		||||
@@ -56,6 +58,61 @@ IconList::~IconList()
 | 
			
		||||
	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
 | 
			
		||||
{
 | 
			
		||||
	if(!index.isValid())
 | 
			
		||||
@@ -84,18 +141,65 @@ int IconList::rowCount ( const QModelIndex& parent ) const
 | 
			
		||||
	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 )
 | 
			
		||||
{
 | 
			
		||||
	auto iter = d->index.find(key);
 | 
			
		||||
	if(iter != d->index.end())
 | 
			
		||||
	{
 | 
			
		||||
		if(d->icons[*iter].is_builtin) return false;
 | 
			
		||||
		if(d->icons[*iter].is_builtin)
 | 
			
		||||
			return false;
 | 
			
		||||
		
 | 
			
		||||
		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
 | 
			
		||||
		d->icons[*iter] = {key, name, icon, is_builtin};
 | 
			
		||||
		oldOne = {key, name, icon, is_builtin, path};
 | 
			
		||||
		dataChanged(index(*iter),index(*iter));
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
@@ -104,12 +208,25 @@ bool IconList::addIcon ( QString key, QString name, QString path, bool is_builti
 | 
			
		||||
		if(icon.isNull()) return false;
 | 
			
		||||
		
 | 
			
		||||
		// 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;
 | 
			
		||||
		endInsertRows();
 | 
			
		||||
		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 )
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,14 @@ public:
 | 
			
		||||
	virtual int rowCount ( const QModelIndex& parent = QModelIndex() ) const;
 | 
			
		||||
	
 | 
			
		||||
	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:
 | 
			
		||||
	virtual ~IconList();
 | 
			
		||||
@@ -27,6 +34,7 @@ private:
 | 
			
		||||
	IconList ( const IconList & ) = delete;
 | 
			
		||||
	// hide assign op
 | 
			
		||||
	IconList& operator= ( const IconList & ) = delete;
 | 
			
		||||
	void reindex();
 | 
			
		||||
	static IconList* m_Instance;
 | 
			
		||||
	static QMutex mutex;
 | 
			
		||||
	Private* d;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user