QmlDesigner.ItemLibrary: remove declarative private dependecy

We derived from QDeclarativeListModel which is private.
This patch uses QAbstractListModel instead.

Change-Id: Ib567433f5fbb38780b32e5a9291d2cb87730e624
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
Reviewed-by: Marco Bubke <marco.bubke@digia.com>
This commit is contained in:
Thomas Hartmann
2013-08-06 16:45:59 +02:00
parent 9385c9f9e8
commit fd4e68ac7e
5 changed files with 412 additions and 259 deletions

View File

@@ -33,11 +33,16 @@
#include <nodemetainfo.h> #include <nodemetainfo.h>
#include <QVariant> #include <QVariant>
#include <QMetaProperty>
#include <QMimeData> #include <QMimeData>
#include <QPainter> #include <QPainter>
#include <QPen> #include <QPen>
#include <qdebug.h> #include <qdebug.h>
static bool inline registerItemLibrarySortedModel() {
qmlRegisterType<QmlDesigner::Internal::ItemLibrarySortedModel>();
return true;
}
namespace QmlDesigner { namespace QmlDesigner {
@@ -45,31 +50,59 @@ namespace Internal {
static QHash<QString, bool> collapsedStateHash; static QHash<QString, bool> collapsedStateHash;
ItemLibrarySortedModel::ItemLibrarySortedModel(QObject *parent) :
template <class T> QAbstractListModel(parent)
ItemLibrarySortedModel<T>::ItemLibrarySortedModel(QObject *parent) :
QDeclarativeListModel(parent)
{ {
} }
ItemLibrarySortedModel::~ItemLibrarySortedModel()
template <class T>
ItemLibrarySortedModel<T>::~ItemLibrarySortedModel()
{ {
clearElements(); clearElements();
} }
int ItemLibrarySortedModel::rowCount(const QModelIndex &) const
template <class T>
void ItemLibrarySortedModel<T>::clearElements()
{ {
while (m_elementOrder.count() > 0) return m_privList.count();
removeElement(m_elementOrder.at(0).libId);
} }
QVariant ItemLibrarySortedModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row()+1 > m_privList.count()) {
qDebug() << Q_FUNC_INFO << "invalid index requested";
return QVariant();
}
template <class T> if (m_roleNames.contains(role)) {
void ItemLibrarySortedModel<T>::addElement(T *element, int libId) QVariant value = m_privList.at(index.row())->property(m_roleNames.value(role));
if (ItemLibrarySortedModel* model = qobject_cast<ItemLibrarySortedModel *>(value.value<QObject*>())) {
return QVariant::fromValue(model);
}
return m_privList.at(index.row())->property(m_roleNames.value(role));
}
qWarning() << Q_FUNC_INFO << "invalid role requested";
return QVariant();
}
void ItemLibrarySortedModel::clearElements()
{
beginResetModel();
while (m_elementOrder.count() > 0)
removeElement(m_elementOrder.at(0).libId);
endResetModel();
}
static bool compareFunction(QObject *first, QObject *second)
{
static const char sortRoleName[] = "sortingRole";
return first->property(sortRoleName).toString() < second->property(sortRoleName).toString();
}
void ItemLibrarySortedModel::addElement(QObject *element, int libId)
{ {
struct order_struct orderEntry; struct order_struct orderEntry;
orderEntry.libId = libId; orderEntry.libId = libId;
@@ -77,7 +110,7 @@ void ItemLibrarySortedModel<T>::addElement(T *element, int libId)
int pos = 0; int pos = 0;
while ((pos < m_elementOrder.count()) && while ((pos < m_elementOrder.count()) &&
(*(m_elementModels.value(m_elementOrder.at(pos).libId)) < *element)) compareFunction(m_elementModels.value(m_elementOrder.at(pos).libId), element))
++pos; ++pos;
m_elementModels.insert(libId, element); m_elementModels.insert(libId, element);
@@ -86,10 +119,9 @@ void ItemLibrarySortedModel<T>::addElement(T *element, int libId)
setElementVisible(libId, true); setElementVisible(libId, true);
} }
template <class T> void ItemLibrarySortedModel::removeElement(int libId)
void ItemLibrarySortedModel<T>::removeElement(int libId)
{ {
T *element = m_elementModels.value(libId); QObject *element = m_elementModels.value(libId);
int pos = findElement(libId); int pos = findElement(libId);
setElementVisible(libId, false); setElementVisible(libId, false);
@@ -100,49 +132,77 @@ void ItemLibrarySortedModel<T>::removeElement(int libId)
delete element; delete element;
} }
bool ItemLibrarySortedModel::elementVisible(int libId) const
template <class T>
bool ItemLibrarySortedModel<T>::elementVisible(int libId) const
{ {
int pos = findElement(libId); int pos = findElement(libId);
return m_elementOrder.at(pos).visible; return m_elementOrder.at(pos).visible;
} }
bool ItemLibrarySortedModel::setElementVisible(int libId, bool visible)
template <class T>
bool ItemLibrarySortedModel<T>::setElementVisible(int libId, bool visible)
{ {
int pos = findElement(libId); int pos = findElement(libId);
if (m_elementOrder.at(pos).visible == visible) if (m_elementOrder.at(pos).visible == visible)
return false; return false;
int visiblePos = visibleElementPosition(libId); int visiblePos = visibleElementPosition(libId);
if (visible) if (visible) {
insert(visiblePos, *(m_elementModels.value(libId))); privateInsert(visiblePos, (m_elementModels.value(libId)));
else } else {
remove(visiblePos); privateRemove(visiblePos);
}
m_elementOrder[pos].visible = visible; m_elementOrder[pos].visible = visible;
return true; return true;
} }
void ItemLibrarySortedModel::privateInsert(int pos, QObject *element)
{
QObject *object = element;
template <class T> for (int i = 0; i < object->metaObject()->propertyCount(); ++i) {
const QMap<int, T *> &ItemLibrarySortedModel<T>::elements() const QMetaProperty property = object->metaObject()->property(i);
addRoleName(property.name());
}
m_privList.insert(pos, element);
}
void ItemLibrarySortedModel::privateRemove(int pos)
{
m_privList.removeAt(pos);
}
const QMap<int, QObject *> &ItemLibrarySortedModel::elements() const
{ {
return m_elementModels; return m_elementModels;
} }
template<typename T>
const QList<T> ItemLibrarySortedModel::elementsByType() const
{
QList<T> objectList;
template <class T> foreach (QObject *item, elements()) {
T *ItemLibrarySortedModel<T>::elementModel(int libId) T object = qobject_cast<T>(item);
if (object)
objectList.append(object);
}
return objectList;
}
QObject *ItemLibrarySortedModel::element(int libId)
{ {
return m_elementModels.value(libId); return m_elementModels.value(libId);
} }
template<typename T>
T ItemLibrarySortedModel::elementByType(int libId)
{
return qobject_cast<T>(element(libId));
}
template <class T> int ItemLibrarySortedModel::findElement(int libId) const
int ItemLibrarySortedModel<T>::findElement(int libId) const
{ {
int i = 0; int i = 0;
QListIterator<struct order_struct> it(m_elementOrder); QListIterator<struct order_struct> it(m_elementOrder);
@@ -156,8 +216,7 @@ int ItemLibrarySortedModel<T>::findElement(int libId) const
return -1; return -1;
} }
template <class T> int ItemLibrarySortedModel::visibleElementPosition(int libId) const
int ItemLibrarySortedModel<T>::visibleElementPosition(int libId) const
{ {
int i = 0; int i = 0;
QListIterator<struct order_struct> it(m_elementOrder); QListIterator<struct order_struct> it(m_elementOrder);
@@ -173,26 +232,36 @@ int ItemLibrarySortedModel<T>::visibleElementPosition(int libId) const
return -1; return -1;
} }
void ItemLibrarySortedModel::resetModel()
{
beginResetModel();
endResetModel();
}
void ItemLibrarySortedModel::addRoleName(const QByteArray &roleName)
{
if (m_roleNames.values().contains(roleName)) {
return;
}
ItemLibraryItemModel::ItemLibraryItemModel(QScriptEngine *scriptEngine, int itemLibId, const QString &itemName) int key = m_roleNames.count();
: QScriptValue(scriptEngine->newObject()), m_roleNames.insert(key, roleName);
m_scriptEngine(scriptEngine), setRoleNames(m_roleNames);
}
ItemLibraryItemModel::ItemLibraryItemModel(int itemLibId, const QString &itemName, QObject *parent)
: QObject(parent),
m_libId(itemLibId), m_libId(itemLibId),
m_name(itemName), m_name(itemName),
m_iconSize(64, 64) m_iconSize(64, 64)
{ {
QScriptValue pixmapScriptValue(m_scriptEngine->newVariant(QPixmap()));
setProperty(QLatin1String("itemLibId"), itemLibId);
setProperty(QLatin1String("itemName"), itemName);
setProperty(QLatin1String("itemPixmap"), pixmapScriptValue);
} }
ItemLibraryItemModel::~ItemLibraryItemModel() ItemLibraryItemModel::~ItemLibraryItemModel()
{ {
setProperty(QLatin1String("itemPixmap"), QVariant::Invalid);
} }
@@ -207,45 +276,37 @@ QString ItemLibraryItemModel::itemName() const
return m_name; return m_name;
} }
QString ItemLibraryItemModel::itemLibraryIconPath() const
{
//Prepend image provider prefix
return QLatin1String("image://qmldesigner_itemlibrary/")+ m_iconPath;
}
QVariant ItemLibraryItemModel::sortingRole() const
{
return itemName();
}
void ItemLibraryItemModel::setItemIconPath(const QString &iconPath) void ItemLibraryItemModel::setItemIconPath(const QString &iconPath)
{ {
m_iconPath = iconPath; m_iconPath = iconPath;
setProperty(QLatin1String("itemLibraryIconPath"),
QString(QLatin1String("image://qmldesigner_itemlibrary/") + iconPath));
} }
void ItemLibraryItemModel::setItemIconSize(const QSize &itemIconSize) void ItemLibraryItemModel::setItemIconSize(const QSize &itemIconSize)
{ {
m_iconSize = itemIconSize; m_iconSize = itemIconSize;
// qDebug() << "set icon size" << itemIconSize;
setItemIconPath(m_iconPath); setItemIconPath(m_iconPath);
} }
ItemLibrarySectionModel::ItemLibrarySectionModel(int sectionLibId, const QString &sectionName, QObject *parent)
bool ItemLibraryItemModel::operator<(const ItemLibraryItemModel &other) const : QObject(parent),
{
return itemName() < other.itemName();
}
ItemLibrarySectionModel::ItemLibrarySectionModel(QScriptEngine *scriptEngine, int sectionLibId, const QString &sectionName, QObject *parent)
: QScriptValue(scriptEngine->newObject()),
m_name(sectionName), m_name(sectionName),
m_sectionLibId(sectionLibId),
m_sectionExpanded(true),
m_sectionEntries(parent) m_sectionEntries(parent)
{ {
QScriptValue::setProperty(QLatin1String("sectionLibId"), sectionLibId); if (collapsedStateHash.contains(sectionName))
QScriptValue::setProperty(QLatin1String("sectionName"), sectionName); m_sectionExpanded= collapsedStateHash.value(sectionName);
QScriptValue::setProperty(QLatin1String("sectionEntries"),
scriptEngine->newVariant(QVariant::fromValue(static_cast<QDeclarativeListModel *>(&m_sectionEntries))));
if (collapsedStateHash.contains(sectionName)) {
QScriptValue::setProperty(QLatin1String("sectionExpanded"), collapsedStateHash.value(sectionName));
} else {
QScriptValue::setProperty(QLatin1String("sectionExpanded"), true);
}
} }
@@ -254,6 +315,24 @@ QString ItemLibrarySectionModel::sectionName() const
return m_name; return m_name;
} }
int ItemLibrarySectionModel::sectionLibId() const
{
return m_sectionLibId;
}
bool ItemLibrarySectionModel::sectionExpanded() const
{
return m_sectionExpanded;
}
QVariant ItemLibrarySectionModel::sortingRole() const
{
if (sectionName() == QLatin1String("QML Components")) //Qml Components always come first
return QVariant(QLatin1String("AA.this_comes_first"));
return sectionName();
}
void ItemLibrarySectionModel::addSectionEntry(ItemLibraryItemModel *sectionEntry) void ItemLibrarySectionModel::addSectionEntry(ItemLibraryItemModel *sectionEntry)
{ {
@@ -266,6 +345,10 @@ void ItemLibrarySectionModel::removeSectionEntry(int itemLibId)
m_sectionEntries.removeElement(itemLibId); m_sectionEntries.removeElement(itemLibId);
} }
QObject *ItemLibrarySectionModel::sectionEntries()
{
return &m_sectionEntries;
}
int ItemLibrarySectionModel::visibleItemIndex(int itemLibId) int ItemLibrarySectionModel::visibleItemIndex(int itemLibId)
{ {
@@ -285,11 +368,13 @@ bool ItemLibrarySectionModel::updateSectionVisibility(const QString &searchText,
*changed = false; *changed = false;
QMap<int, ItemLibraryItemModel *>::const_iterator itemIt = m_sectionEntries.elements().constBegin(); QMap<int, QObject *>::const_iterator itemIt = m_sectionEntries.elements().constBegin();
while (itemIt != m_sectionEntries.elements().constEnd()) { while (itemIt != m_sectionEntries.elements().constEnd()) {
bool itemVisible = itemIt.value()->itemName().toLower().contains(searchText), bool itemVisible = m_sectionEntries.elementByType<ItemLibraryItemModel*>(
itemChanged = false; itemIt.key())->itemName().toLower().contains(searchText);
bool itemChanged = false;
itemChanged = m_sectionEntries.setElementVisible(itemIt.key(), itemVisible); itemChanged = m_sectionEntries.setElementVisible(itemIt.key(), itemVisible);
*changed |= itemChanged; *changed |= itemChanged;
@@ -300,24 +385,21 @@ bool ItemLibrarySectionModel::updateSectionVisibility(const QString &searchText,
++itemIt; ++itemIt;
} }
m_sectionEntries.resetModel();
emit sectionEntriesChanged();
return haveVisibleItems; return haveVisibleItems;
} }
void ItemLibrarySectionModel::updateItemIconSize(const QSize &itemIconSize) void ItemLibrarySectionModel::updateItemIconSize(const QSize &itemIconSize)
{ {
foreach (ItemLibraryItemModel *item, m_sectionEntries.elements()) { foreach (ItemLibraryItemModel* itemLibraryItemModel, m_sectionEntries.elementsByType<ItemLibraryItemModel*>()) {
item->setItemIconSize(itemIconSize); itemLibraryItemModel->setItemIconSize(itemIconSize);
} }
} }
bool ItemLibrarySectionModel::operator<(const ItemLibrarySectionModel &other) const
{
if (sectionName() == QLatin1String("QML Components")) //Qml Components always come first
return true;
return sectionName() < other.sectionName();
}
void ItemLibraryModel::setExpanded(bool expanded, const QString &section) void ItemLibraryModel::setExpanded(bool expanded, const QString &section)
{ {
if (collapsedStateHash.contains(section)) if (collapsedStateHash.contains(section))
@@ -327,9 +409,8 @@ void ItemLibraryModel::setExpanded(bool expanded, const QString &section)
collapsedStateHash.insert(section, expanded); collapsedStateHash.insert(section, expanded);
} }
ItemLibraryModel::ItemLibraryModel(QScriptEngine *scriptEngine, QObject *parent) ItemLibraryModel::ItemLibraryModel(QObject *parent)
: ItemLibrarySortedModel<ItemLibrarySectionModel>(parent), : ItemLibrarySortedModel(parent),
m_scriptEngine(scriptEngine),
m_searchText(""), m_searchText(""),
m_itemIconSize(64, 64), m_itemIconSize(64, 64),
m_nextLibId(0) m_nextLibId(0)
@@ -365,15 +446,16 @@ void ItemLibraryModel::setItemIconSize(const QSize &itemIconSize)
{ {
m_itemIconSize = itemIconSize; m_itemIconSize = itemIconSize;
foreach (ItemLibrarySectionModel *section, elements().values()) foreach (ItemLibrarySectionModel* itemLibrarySectionModel, sections()) {
section->updateItemIconSize(itemIconSize); itemLibrarySectionModel->updateItemIconSize(itemIconSize);
}
} }
int ItemLibraryModel::getItemSectionIndex(int itemLibId) int ItemLibraryModel::getItemSectionIndex(int itemLibId)
{ {
if (m_sections.contains(itemLibId)) if (m_sections.contains(itemLibId))
return elementModel(m_sections.value(itemLibId))->visibleItemIndex(itemLibId); return section(m_sections.value(itemLibId))->visibleItemIndex(itemLibId);
else else
return -1; return -1;
} }
@@ -394,7 +476,7 @@ bool ItemLibraryModel::isItemVisible(int itemLibId)
if (!elementVisible(sectionLibId)) if (!elementVisible(sectionLibId))
return false; return false;
return elementModel(sectionLibId)->isItemVisible(itemLibId); return section(sectionLibId)->isItemVisible(itemLibId);
} }
Import entryToImport(const ItemLibraryEntry &entry) Import entryToImport(const ItemLibraryEntry &entry)
@@ -439,17 +521,17 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
if (sections.contains(itemSectionName)) { if (sections.contains(itemSectionName)) {
sectionId = sections.value(itemSectionName); sectionId = sections.value(itemSectionName);
sectionModel = elementModel(sectionId); sectionModel = section(sectionId);
} else { } else {
sectionId = m_nextLibId++; sectionId = m_nextLibId++;
sectionModel = new ItemLibrarySectionModel(m_scriptEngine.data(), sectionId, itemSectionName, this); sectionModel = new ItemLibrarySectionModel(sectionId, itemSectionName, this);
addElement(sectionModel, sectionId); addElement(sectionModel, sectionId);
sections.insert(itemSectionName, sectionId); sections.insert(itemSectionName, sectionId);
} }
m_itemInfos.insert(itemId, entry); m_itemInfos.insert(itemId, entry);
itemModel = new ItemLibraryItemModel(m_scriptEngine.data(), itemId, entry.name()); itemModel = new ItemLibraryItemModel(itemId, entry.name(), sectionModel);
// delayed creation of (default) icons // delayed creation of (default) icons
if (entry.iconPath().isEmpty()) if (entry.iconPath().isEmpty())
@@ -501,15 +583,26 @@ QIcon ItemLibraryModel::getIcon(int libId)
return m_itemInfos.value(libId).icon(); return m_itemInfos.value(libId).icon();
} }
ItemLibrarySectionModel *ItemLibraryModel::section(int libId)
{
return elementByType<ItemLibrarySectionModel*>(libId);
}
QList<ItemLibrarySectionModel *> ItemLibraryModel::sections() const
{
return elementsByType<ItemLibrarySectionModel*>();
}
void ItemLibraryModel::updateVisibility() void ItemLibraryModel::updateVisibility()
{ {
beginResetModel();
endResetModel();
bool changed = false; bool changed = false;
QMap<int, ItemLibrarySectionModel *>::const_iterator sectionIt = elements().constBegin(); QMap<int, QObject *>::const_iterator sectionIt = elements().constBegin();
while (sectionIt != elements().constEnd()) { while (sectionIt != elements().constEnd()) {
ItemLibrarySectionModel *sectionModel = section(sectionIt.key());
ItemLibrarySectionModel *sectionModel = sectionIt.value();
QString sectionSearchText = m_searchText; QString sectionSearchText = m_searchText;
if (sectionModel->sectionName().toLower().contains(m_searchText)) if (sectionModel->sectionName().toLower().contains(m_searchText))
@@ -564,6 +657,11 @@ QPixmap ItemLibraryModel::createDragPixmap(int , int )
return QPixmap::fromImage(dragImage); return QPixmap::fromImage(dragImage);
} }
void registerQmlTypes()
{
registerItemLibrarySortedModel();
}
} // namespace Internal } // namespace Internal
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -32,8 +32,8 @@
#include <QMap> #include <QMap>
#include <QIcon> #include <QIcon>
#include <QScriptEngine> #include <QAbstractListModel>
#include <private/qdeclarativelistmodel_p.h> #include <QtDeclarative>
QT_FORWARD_DECLARE_CLASS(QMimeData) QT_FORWARD_DECLARE_CLASS(QMimeData)
@@ -45,52 +45,82 @@ class Model;
namespace Internal { namespace Internal {
template <class T> void registerQmlTypes();
class ItemLibrarySortedModel: public QDeclarativeListModel {
class ItemLibrarySortedModel: public QAbstractListModel {
Q_OBJECT
public: public:
ItemLibrarySortedModel(QObject *parent = 0); ItemLibrarySortedModel(QObject *parent = 0);
~ItemLibrarySortedModel(); ~ItemLibrarySortedModel();
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
void clearElements(); void clearElements();
void addElement(T *element, int libId); void addElement(QObject *element, int libId);
void removeElement(int libId); void removeElement(int libId);
bool elementVisible(int libId) const; bool elementVisible(int libId) const;
bool setElementVisible(int libId, bool visible); bool setElementVisible(int libId, bool visible);
const QMap<int, T *> &elements() const; void privateInsert(int pos, QObject *element);
void privateRemove(int pos);
const QMap<int, QObject *> &elements() const;
template<typename T>
const QList<T> elementsByType() const;
QObject *element(int libId);
template<typename T>
T elementByType(int libId);
T *elementModel(int libId);
int findElement(int libId) const; int findElement(int libId) const;
int visibleElementPosition(int libId) const; int visibleElementPosition(int libId) const;
void resetModel();
private: private:
void addRoleName(const QByteArray &roleName);
struct order_struct { struct order_struct {
int libId; int libId;
bool visible; bool visible;
}; };
QMap<int, T *> m_elementModels; QMap<int, QObject *> m_elementModels;
QList<struct order_struct> m_elementOrder; QList<struct order_struct> m_elementOrder;
QList<QObject *> m_privList;
QHash<int, QByteArray> m_roleNames;
}; };
class ItemLibraryItemModel: public QObject {
Q_OBJECT
Q_PROPERTY(int itemLibId READ itemLibId FINAL)
Q_PROPERTY(QString itemName READ itemName FINAL)
Q_PROPERTY(QString itemLibraryIconPath READ itemLibraryIconPath FINAL)
Q_PROPERTY(QVariant sortingRole READ sortingRole FINAL)
class ItemLibraryItemModel: public QScriptValue {
public: public:
ItemLibraryItemModel(QScriptEngine *scriptEngine, int itemLibId, const QString &itemName); ItemLibraryItemModel(int itemLibId, const QString &itemName, QObject *parent);
~ItemLibraryItemModel(); ~ItemLibraryItemModel();
int itemLibId() const; int itemLibId() const;
QString itemName() const; QString itemName() const;
QString itemLibraryIconPath() const;
QVariant sortingRole() const;
void setItemIconPath(const QString &iconPath); void setItemIconPath(const QString &iconPath);
void setItemIconSize(const QSize &itemIconSize); void setItemIconSize(const QSize &itemIconSize);
bool operator<(const ItemLibraryItemModel &other) const;
private: private:
QWeakPointer<QScriptEngine> m_scriptEngine;
int m_libId; int m_libId;
QString m_name; QString m_name;
QString m_iconPath; QString m_iconPath;
@@ -98,14 +128,27 @@ private:
}; };
class ItemLibrarySectionModel: public QScriptValue { class ItemLibrarySectionModel: public QObject {
Q_OBJECT
Q_PROPERTY(QObject* sectionEntries READ sectionEntries NOTIFY sectionEntriesChanged FINAL)
Q_PROPERTY(int sectionLibId READ sectionLibId FINAL)
Q_PROPERTY(QString sectionName READ sectionName FINAL)
Q_PROPERTY(bool sectionExpanded READ sectionExpanded FINAL)
Q_PROPERTY(QVariant sortingRole READ sortingRole FINAL)
public: public:
ItemLibrarySectionModel(QScriptEngine *scriptEngine, int sectionLibId, const QString &sectionName, QObject *parent = 0); ItemLibrarySectionModel(int sectionLibId, const QString &sectionName, QObject *parent = 0);
QString sectionName() const; QString sectionName() const;
int sectionLibId() const;
bool sectionExpanded() const;
QVariant sortingRole() const;
void addSectionEntry(ItemLibraryItemModel *sectionEntry); void addSectionEntry(ItemLibraryItemModel *sectionEntry);
void removeSectionEntry(int itemLibId); void removeSectionEntry(int itemLibId);
QObject *sectionEntries();
int visibleItemIndex(int itemLibId); int visibleItemIndex(int itemLibId);
bool isItemVisible(int itemLibId); bool isItemVisible(int itemLibId);
@@ -113,20 +156,24 @@ public:
bool updateSectionVisibility(const QString &searchText, bool *changed); bool updateSectionVisibility(const QString &searchText, bool *changed);
void updateItemIconSize(const QSize &itemIconSize); void updateItemIconSize(const QSize &itemIconSize);
bool operator<(const ItemLibrarySectionModel &other) const; signals:
void sectionEntriesChanged();
private: private:
QString m_name; QString m_name;
ItemLibrarySortedModel<ItemLibraryItemModel> m_sectionEntries; int m_sectionLibId;
bool m_sectionExpanded;
ItemLibrarySortedModel m_sectionEntries;
}; };
class ItemLibraryModel: public ItemLibrarySortedModel<ItemLibrarySectionModel> { class ItemLibraryModel: public ItemLibrarySortedModel {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString searchText READ searchText WRITE setSearchText NOTIFY searchTextChanged) Q_PROPERTY(QString searchText READ searchText WRITE setSearchText NOTIFY searchTextChanged)
public: public:
explicit ItemLibraryModel(QScriptEngine *scriptEngine, QObject *parent = 0); explicit ItemLibraryModel(QObject *parent = 0);
~ItemLibraryModel(); ~ItemLibraryModel();
QString searchText() const; QString searchText() const;
@@ -137,6 +184,9 @@ public:
QMimeData *getMimeData(int libId); QMimeData *getMimeData(int libId);
QIcon getIcon(int libId); QIcon getIcon(int libId);
ItemLibrarySectionModel* section(int libId);
QList<ItemLibrarySectionModel*> sections() const;
public slots: public slots:
void setSearchText(const QString &searchText); void setSearchText(const QString &searchText);
void setItemIconSize(const QSize &itemIconSize); void setItemIconSize(const QSize &itemIconSize);
@@ -159,7 +209,6 @@ private:
int getHeight(const ItemLibraryEntry &entry); int getHeight(const ItemLibraryEntry &entry);
QPixmap createDragPixmap(int width, int height); QPixmap createDragPixmap(int width, int height);
QWeakPointer<QScriptEngine> m_scriptEngine;
QMap<int, ItemLibraryEntry> m_itemInfos; QMap<int, ItemLibraryEntry> m_itemInfos;
QMap<int, int> m_sections; QMap<int, int> m_sections;
@@ -171,5 +220,7 @@ private:
} // namespace Internal } // namespace Internal
} // namespace QmlDesigner } // namespace QmlDesigner
QML_DECLARE_TYPE(QmlDesigner::Internal::ItemLibrarySortedModel)
#endif // ITEMLIBRARYMODEL_H #endif // ITEMLIBRARYMODEL_H

View File

@@ -67,6 +67,8 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
m_resourcesView(new Internal::ItemLibraryTreeView(this)), m_resourcesView(new Internal::ItemLibraryTreeView(this)),
m_filterFlag(QtBasic) m_filterFlag(QtBasic)
{ {
Internal::registerQmlTypes();
setWindowTitle(tr("Library", "Title of library view")); setWindowTitle(tr("Library", "Title of library view"));
/* create Items view and its model */ /* create Items view and its model */
@@ -75,7 +77,7 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
m_itemsView->setAcceptDrops(false); m_itemsView->setAcceptDrops(false);
m_itemsView->setFocusPolicy(Qt::ClickFocus); m_itemsView->setFocusPolicy(Qt::ClickFocus);
m_itemsView->setResizeMode(QDeclarativeView::SizeRootObjectToView); m_itemsView->setResizeMode(QDeclarativeView::SizeRootObjectToView);
m_itemLibraryModel = new Internal::ItemLibraryModel(QDeclarativeEnginePrivate::getScriptEngine(m_itemsView->engine()), this); m_itemLibraryModel = new Internal::ItemLibraryModel(this);
m_itemLibraryModel->setItemIconSize(m_itemIconSize); m_itemLibraryModel->setItemIconSize(m_itemIconSize);
QDeclarativeContext *rootContext = m_itemsView->rootContext(); QDeclarativeContext *rootContext = m_itemsView->rootContext();

View File

@@ -90,146 +90,147 @@ focus */
onEntered: { onEntered: {
if (!pressed) if (!pressed)
stopDragAndDrop() stopDragAndDrop()
}
}
signal selectionUpdated(int itemSectionIndex)
property int selectedItemLibId: -1
property int selectionSectionLibId: -1
function setSelection(itemLibId) {
selectedItemLibId = itemLibId
selectionSectionLibId = itemLibraryModel.getSectionLibId(itemLibId)
selectionUpdated(itemLibraryModel.getItemSectionIndex(itemLibId))
}
function unsetSelection() {
selectedItemLibId = -1
selectionSectionLibId = -1
selectionUpdated(-1)
}
Connections {
target: itemLibraryModel
onVisibilityChanged: {
if (itemLibraryModel.isItemVisible(selectedItemLibId))
setSelection(selectedItemLibId)
else
unsetSelection()
}
}
/* the following 3 properties are calculated here for performance
reasons and then passed to the section views */
property int entriesPerRow: Math.max(1, Math.floor((itemsFlickable.width - 2) / style.cellWidth))
property int cellWidth: Math.floor((itemsFlickable.width - 2) / entriesPerRow)
property int cellHeight: style.cellHeight
Component {
id: sectionDelegate
SectionView {
id: section
entriesPerRow: itemsView.entriesPerRow
cellWidth: itemsView.cellWidth
cellHeight: itemsView.cellHeight
width: itemsFlickable.width
itemHighlight: selector
property bool containsSelection: (selectionSectionLibId == sectionLibId)
onItemSelected: {
itemsView.setSelection(itemLibId)
itemsView.itemSelected(itemLibId)
} }
onItemDragged: {
section.itemSelected(itemLibId)
itemsView.itemDragged(itemLibId)
} }
signal selectionUpdated(int itemSectionIndex) Connections {
target: itemsView
property int selectedItemLibId: -1 onExpandAllEntries: section.expand()
property int selectionSectionLibId: -1 onSelectionUpdated: {
if (containsSelection) {
function setSelection(itemLibId) { section.setSelection(itemSectionIndex)
selectedItemLibId = itemLibId section.focusSelection(itemsFlickable)
selectionSectionLibId = itemLibraryModel.getSectionLibId(itemLibId) } else
selectionUpdated(itemLibraryModel.getItemSectionIndex(itemLibId)) section.unsetSelection()
} }
}
function unsetSelection() { Component {
selectedItemLibId = -1 id: selector
selectionSectionLibId = -1
selectionUpdated(-1) Selector {
x: containsSelection? section.currentItem.x:0
y: containsSelection? section.currentItem.y:0
width: itemsView.cellWidth
height: itemsView.cellHeight
visible: containsSelection
} }
}
}
}
Connections { Flickable {
target: itemLibraryModel id: itemsFlickable
onVisibilityChanged: {
if (itemLibraryModel.isItemVisible(selectedItemLibId))
setSelection(selectedItemLibId)
else
unsetSelection()
}
}
/* the following 3 properties are calculated here for performance anchors.top: parent.top
reasons and then passed to the section views */ anchors.topMargin: 3
property int entriesPerRow: Math.max(1, Math.floor((itemsFlickable.width - 2) / style.cellWidth)) anchors.bottom: parent.bottom
property int cellWidth: Math.floor((itemsFlickable.width - 2) / entriesPerRow) anchors.left: parent.left
property int cellHeight: style.cellHeight anchors.right: scrollbarFrame.left
boundsBehavior: Flickable.DragOverBounds
Component { interactive: false
id: sectionDelegate contentHeight: col.height
SectionView { /* Limit the content position. Without this, resizing would get the
id: section
entriesPerRow: itemsView.entriesPerRow
cellWidth: itemsView.cellWidth
cellHeight: itemsView.cellHeight
width: itemsFlickable.width
itemHighlight: selector
property bool containsSelection: (selectionSectionLibId == sectionLibId)
onItemSelected: {
itemsView.setSelection(itemLibId)
itemsView.itemSelected(itemLibId)
}
onItemDragged: {
section.itemSelected(itemLibId)
itemsView.itemDragged(itemLibId)
}
Connections {
target: itemsView
onExpandAllEntries: section.expand()
onSelectionUpdated: {
if (containsSelection) {
section.setSelection(itemSectionIndex)
section.focusSelection(itemsFlickable)
} else
section.unsetSelection()
}
}
Component {
id: selector
Selector {
x: containsSelection? section.currentItem.x:0
y: containsSelection? section.currentItem.y:0
width: itemsView.cellWidth
height: itemsView.cellHeight
visible: containsSelection
}
}
}
}
Flickable {
id: itemsFlickable
anchors.top: parent.top
anchors.topMargin: 3
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: scrollbarFrame.left
boundsBehavior: Flickable.DragOverBounds
interactive: false
contentHeight: col.height
/* Limit the content position. Without this, resizing would get the
content position out of scope regarding the scrollbar. */ content position out of scope regarding the scrollbar. */
function limitContentPos() { function limitContentPos() {
if (contentY < 0) { if (contentY < 0) {
contentY = 0; contentY = 0;
} else { } else {
var maxContentY = Math.max(0, contentHeight - height) var maxContentY = Math.max(0, contentHeight - height)
if (contentY > maxContentY) if (contentY > maxContentY)
contentY = maxContentY; contentY = maxContentY;
} }
} }
onHeightChanged: limitContentPos() onHeightChanged: limitContentPos()
onContentHeightChanged: limitContentPos() onContentHeightChanged: limitContentPos()
Column { Column {
id: col id: col
Repeater { Repeater {
model: itemLibraryModel // to be set in Qml context model: itemLibraryModel // to be set in Qml context
delegate: sectionDelegate delegate: sectionDelegate
} }
} }
} }
Item { Item {
id: scrollbarFrame id: scrollbarFrame
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: 2 anchors.topMargin: 2
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: 1 anchors.bottomMargin: 1
anchors.right: parent.right anchors.right: parent.right
width: (itemsFlickable.contentHeight > itemsFlickable.height)? 11:0 width: (itemsFlickable.contentHeight > itemsFlickable.height)? 11:0
Scrollbar { Scrollbar {
id: scrollbar id: scrollbar
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: 1 anchors.leftMargin: 1
flickable: itemsFlickable flickable: itemsFlickable
} }
} }
} }

View File

@@ -77,18 +77,18 @@ Column {
var currentItemX = sectionView.x + gridFrame.x + gridView.x + gridView.currentItem.x; var currentItemX = sectionView.x + gridFrame.x + gridView.x + gridView.currentItem.x;
var currentItemY = sectionView.y + gridFrame.y + gridView.y + gridView.currentItem.y var currentItemY = sectionView.y + gridFrame.y + gridView.y + gridView.currentItem.y
- gridView.contentY; // workaround: GridView reports wrong contentY - gridView.contentY; // workaround: GridView reports wrong contentY
if (currentItemY < flickable.contentY) if (currentItemY < flickable.contentY)
pos = Math.max(0, currentItemY) pos = Math.max(0, currentItemY)
else if ((currentItemY + gridView.currentItem.height) > else if ((currentItemY + gridView.currentItem.height) >
(flickable.contentY + flickable.height - 1)) (flickable.contentY + flickable.height - 1))
pos = Math.min(Math.max(0, flickable.contentHeight - flickable.height), pos = Math.min(Math.max(0, flickable.contentHeight - flickable.height),
currentItemY + gridView.currentItem.height - flickable.height + 1) currentItemY + gridView.currentItem.height - flickable.height + 1)
if (pos >= 0) if (pos >= 0)
flickable.contentY = pos flickable.contentY = pos
} }
// internal // internal
@@ -168,7 +168,8 @@ Column {
clip: true clip: true
width: entriesPerRow * cellWidth + 1 width: entriesPerRow * cellWidth + 1
height: Math.ceil(sectionEntries.count / entriesPerRow) * cellHeight + 1 height: gridView.model !== undefined ? Math.ceil(gridView.count / sectionView.entriesPerRow) * cellHeight + 1 : 0
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
GridView { GridView {
@@ -198,18 +199,18 @@ updated properly under all conditions */
} }
states: [ states: [
State { State {
name: "shrunk" name: "shrunk"
PropertyChanges { PropertyChanges {
target: gridFrame target: gridFrame
height: 0 height: 0
opacity: 0 opacity: 0
}
PropertyChanges {
target: arrow
rotation: -90
}
} }
PropertyChanges {
target: arrow
rotation: -90
}
}
] ]
} }