itemlibrarymodel.cpp 9.96 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8
9
10
11
12
13
14
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15
16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
18
19
20
21
22
23
24
25
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
29

30
#include "itemlibrarymodel.h"
31
#include "itemlibraryinfo.h"
32
#include "itemlibrarysection.h"
33
#include "itemlibraryitem.h"
34
#include "itemlibrarysection.h"
35

36
37
#include <model.h>
#include <nodemetainfo.h>
38

39
#include <QVariant>
40
#include <QMetaProperty>
41
#include <QMimeData>
42
#include <QPainter>
43
44
#include <QPen>
#include <qdebug.h>
45

46
static bool inline registerItemLibrarySortedModel() {
47
    qmlRegisterType<QmlDesigner::ItemLibrarySectionModel>();
48
49
    return true;
}
50

51
52
namespace QmlDesigner {

53
54
static QHash<QString, bool> collapsedStateHash;

55

56
57
58
59
60
61
62
63
64
void ItemLibraryModel::setExpanded(bool expanded, const QString &section)
{
    if (collapsedStateHash.contains(section))
        collapsedStateHash.remove(section);

    if (!expanded) //default is true
        collapsedStateHash.insert(section, expanded);
}

65
ItemLibraryModel::ItemLibraryModel(QObject *parent)
66
    : QAbstractListModel(parent),
67
68
      m_nextLibId(0)
{
69
    addRoleNames();
70
71
72
73
}

ItemLibraryModel::~ItemLibraryModel()
{
74
    clearSections();
75
76
}

77
78
79
80
81
82
83
84
85
86
87
88
89
90
int ItemLibraryModel::rowCount(const QModelIndex & /*parent*/) const
{
    return visibleSectionCount();
}

QVariant ItemLibraryModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || index.row() +1 > visibleSectionCount())
        return QVariant();


    if (m_roleNames.contains(role)) {
        QVariant value = visibleSections().at(index.row())->property(m_roleNames.value(role));

91
        ItemLibrarySectionModel* model = qobject_cast<ItemLibrarySectionModel *>(value.value<QObject*>());
92
93
94
95
96
97
98
99
100
101
102
103
104
105
        if (model)
            return QVariant::fromValue(model);

        ItemLibraryModel* model2 = qobject_cast<ItemLibraryModel *>(value.value<QObject*>());
        if (model2)
            return QVariant::fromValue(model2);

        return value;
    }

    qWarning() << Q_FUNC_INFO << "invalid role requested";

    return QVariant();
}
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

QString ItemLibraryModel::searchText() const
{
    return m_searchText;
}


void ItemLibraryModel::setSearchText(const QString &searchText)
{
    QString lowerSearchText = searchText.toLower();

    if (m_searchText != lowerSearchText) {
        m_searchText = lowerSearchText;
        emit searchTextChanged();

        updateVisibility();
    }
}

125
126
127
128
129
int ItemLibraryModel::getSectionLibId(int itemLibId)
{
    return m_sections.value(itemLibId);
}

Thomas Hartmann's avatar
Thomas Hartmann committed
130
Import entryToImport(const ItemLibraryEntry &entry)
131
{
132
133
134
    if (entry.majorVersion() == -1 && entry.minorVersion() == -1)
        return Import::createFileImport(entry.requiredImport());

Thomas Hartmann's avatar
Thomas Hartmann committed
135
136
137
    return Import::createLibraryImport(entry.requiredImport(), QString::number(entry.majorVersion()) + QLatin1Char('.') +
                                                               QString::number(entry.minorVersion()));

138
139
140
}

void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
141
{
142
143
144
    if (!model)
        return;

145
146
    QMap<QString, int> sections;

147
    clearSections();
148
    m_itemInfos.clear();
149
150
    m_sections.clear();
    m_nextLibId = 0;
151

152
153
154
    QStringList imports;
    foreach (const Import &import, model->imports())
        if (import.isLibraryImport())
155
            imports << import.url() + QLatin1Char(' ') + import.version();
156

157
    foreach (ItemLibraryEntry entry, itemLibraryInfo->entries()) {
158

159
160
         NodeMetaInfo metaInfo = model->metaInfo(entry.typeName(), -1, -1);
         bool valid = metaInfo.isValid() && metaInfo.majorVersion() == entry.majorVersion();
161

162
         if (valid
163
                 && (entry.requiredImport().isEmpty()
164
                     || model->hasImport(entryToImport(entry), true, true))) {
165
            QString itemSectionName = entry.category();
166
            ItemLibrarySection *sectionModel;
167
            ItemLibraryItem *itemModel;
168
169
170
171
            int itemId = m_nextLibId++, sectionId;

            if (sections.contains(itemSectionName)) {
                sectionId = sections.value(itemSectionName);
172
                sectionModel = section(sectionId);
173
174
            } else {
                sectionId = m_nextLibId++;
175
                sectionModel = new ItemLibrarySection(sectionId, itemSectionName, this);
176
                addSection(sectionModel, sectionId);
177
178
179
180
181
                sections.insert(itemSectionName, sectionId);
            }

            m_itemInfos.insert(itemId, entry);

182
            itemModel = new ItemLibraryItem(sectionModel);
183
            itemModel->setItemLibraryEntry(entry);
184
185
186
            sectionModel->addSectionEntry(itemModel);
            m_sections.insert(itemId, sectionId);
        }
187
    }
188
189
190
191
192
193
194
195

    updateVisibility();
}


QString ItemLibraryModel::getTypeName(int libId)
{
    return m_itemInfos.value(libId).typeName();
196
197
}

198

199
QMimeData *ItemLibraryModel::getMimeData(const ItemLibraryEntry &itemLibraryEntry)
200
{
201
202
203
204
    QMimeData *mimeData = new QMimeData();

    QByteArray data;
    QDataStream stream(&data, QIODevice::WriteOnly);
205
    stream << itemLibraryEntry;
206
    mimeData->setData(QStringLiteral("application/vnd.bauhaus.itemlibraryinfo"), data);
207

208
    mimeData->removeFormat(QStringLiteral("text/plain"));
209

210
    return mimeData;
211
212
}

213

214
QPixmap ItemLibraryModel::getLibraryEntryIcon(int libId)
215
{
216
    return QPixmap(m_itemInfos.value(libId).libraryEntryIconPath());
217
218
}

219
ItemLibrarySection *ItemLibraryModel::section(int libraryId)
220
{
221
    return m_sectionModels.value(libraryId);
222
223
}

224
QList<ItemLibrarySection *> ItemLibraryModel::sections() const
225
{
226
227
228
    return m_sectionModels.values();
}

229
void ItemLibraryModel::addSection(ItemLibrarySection *sectionModel, int sectionId)
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
{
    m_sectionModels.insert(sectionId, sectionModel);
    sectionModel->setVisible(true);
}

void ItemLibraryModel::clearSections()
{
    beginResetModel();
    qDeleteAll(m_sectionModels);
    m_sectionModels.clear();
    endResetModel();
}

void ItemLibraryModel::registerQmlTypes()
{
245
    qmlRegisterType<QmlDesigner::ItemLibrarySectionModel>();
246
247
248
249
250
251
252
    qmlRegisterType<QmlDesigner::ItemLibraryModel>();
}

int ItemLibraryModel::visibleSectionCount() const
{
    int visibleCount = 0;

253
    auto sectionIterator = m_sectionModels.constBegin();
254
    while (sectionIterator != m_sectionModels.constEnd()) {
255
        ItemLibrarySection *sectionModel = sectionIterator.value();
256
257
258
259
260
261
262
263
        if (sectionModel->isVisible())
            ++visibleCount;
        ++sectionIterator;
    }

    return visibleCount;
}

264
QList<ItemLibrarySection *> ItemLibraryModel::visibleSections() const
265
{
266
    QList<ItemLibrarySection *> visibleSectionList;
267

268
    auto sectionIterator = m_sectionModels.constBegin();
269
    while (sectionIterator != m_sectionModels.constEnd()) {
270
        ItemLibrarySection *sectionModel = sectionIterator.value();
271
272
273
274
275
276
        if (sectionModel->isVisible())
            visibleSectionList.append(sectionModel);
        ++sectionIterator;
    }

    return visibleSectionList;
277
}
278

279
280
void ItemLibraryModel::updateVisibility()
{
281
282
    beginResetModel();
    endResetModel();
283
284
    bool changed = false;

285
    auto sectionIterator = m_sectionModels.constBegin();
286
    while (sectionIterator != m_sectionModels.constEnd()) {
287
        ItemLibrarySection *sectionModel = sectionIterator.value();
288

289
        QString sectionSearchText = m_searchText;
290

291
        if (sectionModel->sectionName().toLower().contains(m_searchText))
292
            sectionSearchText.clear();
293

294
295
296
297
298
299
        bool sectionChanged = false,
            sectionVisibility = sectionModel->updateSectionVisibility(sectionSearchText,
                                                                      &sectionChanged);
        if (sectionChanged) {
            changed = true;
            if (sectionVisibility)
300
                emit sectionVisibilityChanged(sectionIterator.key());
301
        }
302

303
304
        changed |= sectionModel->setVisible(sectionVisibility);
        ++sectionIterator;
305
306
    }

307
308
    if (changed)
        emit visibilityChanged();
309
310
}

311
312
313
void ItemLibraryModel::addRoleNames()
{
    int role = 0;
314
315
    for (int propertyIndex = 0; propertyIndex < ItemLibrarySection::staticMetaObject.propertyCount(); ++propertyIndex) {
        QMetaProperty property = ItemLibrarySection::staticMetaObject.property(propertyIndex);
316
317
318
319
320
321
322
        m_roleNames.insert(role, property.name());
        ++role;
    }

    setRoleNames(m_roleNames);
}

323
int ItemLibraryModel::getWidth(const ItemLibraryEntry &itemLibraryEntry)
324
{
325
    foreach (const ItemLibraryEntry::Property &property, itemLibraryEntry.properties())
326
    {
327
        if (property.name() == "width")
328
329
            return property.value().toInt();
    }
330

331
332
333
    return 64;
}

334
int ItemLibraryModel::getHeight(const ItemLibraryEntry &itemLibraryEntry)
335
{
336
    foreach (const ItemLibraryEntry::Property &property, itemLibraryEntry.properties())
337
    {
338
        if (property.name() == "height")
339
340
            return property.value().toInt();
    }
341

342
343
344
    return 64;
}

345
346
347
348
349
void registerQmlTypes()
{
    registerItemLibrarySortedModel();
}

350
} // namespace QmlDesigner
351