~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to tools/designer/src/components/widgetbox/widgetbox.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the designer application of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include "widgetbox.h"
 
30
 
 
31
// sdk
 
32
#include <QtDesigner/QtDesigner>
 
33
 
 
34
// shared
 
35
#include <pluginmanager_p.h>
 
36
#include <sheet_delegate_p.h>
 
37
#include <iconloader_p.h>
 
38
 
 
39
#include <QtGui/QtGui>
 
40
#include <QtCore/qdebug.h>
 
41
 
 
42
#include "widgetbox_dnditem.h"
 
43
 
 
44
#define SCRATCHPAD_ITEM 1
 
45
#define CUSTOM_ITEM     2
 
46
 
 
47
#ifndef Q_MOC_RUN
 
48
using namespace qdesigner_internal;
 
49
#endif
 
50
 
 
51
/*******************************************************************************
 
52
** Tools
 
53
*/
 
54
static QDomElement childElement(QDomNode node, const QString &tag,
 
55
                                const QString &attr_name,
 
56
                                const QString &attr_value)
 
57
{
 
58
    if (node.isElement()) {
 
59
        QDomElement elt = node.toElement();
 
60
        if (elt.tagName() == tag) {
 
61
            if (attr_name.isEmpty())
 
62
                return elt;
 
63
            if (elt.hasAttribute(attr_name)) {
 
64
                if (attr_value.isEmpty())
 
65
                    return elt;
 
66
                if (elt.attribute(attr_name) == attr_value)
 
67
                    return elt;
 
68
            }
 
69
        }
 
70
    }
 
71
 
 
72
    QDomNode child = node.firstChild();
 
73
    for (; !child.isNull(); child = child.nextSibling()) {
 
74
        QDomElement elt = childElement(child, tag, attr_name, attr_value);
 
75
        if (!elt.isNull())
 
76
            return elt;
 
77
    }
 
78
 
 
79
    return QDomElement();
 
80
}
 
81
 
 
82
typedef QList<QDomElement> ElementList;
 
83
static void _childElementList(QDomNode node, const QString &tag,
 
84
                                    const QString &attr_name,
 
85
                                    const QString &attr_value,
 
86
                                    ElementList *result)
 
87
{
 
88
    if (node.isElement()) {
 
89
        QDomElement elt = node.toElement();
 
90
        if (elt.tagName() == tag) {
 
91
            if (attr_name.isEmpty()) {
 
92
                result->append(elt);
 
93
            } else if (elt.hasAttribute(attr_name)) {
 
94
                if (attr_value.isEmpty())
 
95
                    result->append(elt);
 
96
                else if (elt.attribute(attr_name) == attr_value)
 
97
                    result->append(elt);
 
98
            }
 
99
        }
 
100
    }
 
101
 
 
102
    QDomNode child = node.firstChild();
 
103
    for (; !child.isNull(); child = child.nextSibling())
 
104
        _childElementList(child, tag, attr_name, attr_value, result);
 
105
}
 
106
 
 
107
static QString domToString(const QDomElement &elt)
 
108
{
 
109
    QString result;
 
110
    QTextStream stream(&result, QIODevice::WriteOnly);
 
111
    elt.save(stream, 2);
 
112
    stream.flush();
 
113
    return result;
 
114
}
 
115
 
 
116
static QDomDocument stringToDom(const QString &xml)
 
117
{
 
118
    QDomDocument result;
 
119
    result.setContent(xml);
 
120
    return result;
 
121
}
 
122
 
 
123
static DomWidget *xmlToUi(QString xml)
 
124
{
 
125
    QDomDocument doc;
 
126
    QString err_msg;
 
127
    int err_line, err_col;
 
128
    if (!doc.setContent(xml, &err_msg, &err_line, &err_col)) {
 
129
        qWarning("xmlToUi: parse failed:\n%s\n:%d:%d: %s",
 
130
                    xml.toUtf8().constData(),
 
131
                    err_line, err_col,
 
132
                    err_msg.toUtf8().constData());
 
133
        return 0;
 
134
    }
 
135
 
 
136
    QDomElement dom_elt = doc.firstChildElement();
 
137
    if (dom_elt.nodeName() != QLatin1String("widget")) {
 
138
        qWarning("xmlToUi: invalid root element:\n%s", xml.toUtf8().constData());
 
139
        return 0;
 
140
    }
 
141
 
 
142
    DomWidget *widget = new DomWidget;
 
143
    widget->read(dom_elt);
 
144
    return widget;
 
145
}
 
146
 
 
147
/*******************************************************************************
 
148
** WidgetBoxItemDelegate
 
149
*/
 
150
 
 
151
namespace qdesigner_internal {
 
152
 
 
153
class WidgetBoxItemDelegate : public SheetDelegate
 
154
{
 
155
public:
 
156
    WidgetBoxItemDelegate(QTreeWidget *tree, QWidget *parent = 0)
 
157
        : SheetDelegate(tree, parent) {}
 
158
    QWidget *createEditor(QWidget *parent,
 
159
                          const QStyleOptionViewItem &option,
 
160
                          const QModelIndex &index) const;
 
161
};
 
162
 
 
163
/*******************************************************************************
 
164
** WidgetBoxTreeView
 
165
*/
 
166
 
 
167
class WidgetBoxTreeView : public QTreeWidget
 
168
{
 
169
    Q_OBJECT
 
170
 
 
171
public:
 
172
    typedef QDesignerWidgetBoxInterface::Widget Widget;
 
173
    typedef QDesignerWidgetBoxInterface::Category Category;
 
174
    typedef QDesignerWidgetBoxInterface::CategoryList CategoryList;
 
175
 
 
176
    WidgetBoxTreeView(QDesignerFormEditorInterface *core, QWidget *parent = 0);
 
177
    ~WidgetBoxTreeView();
 
178
 
 
179
    int categoryCount() const;
 
180
    Category category(int cat_idx) const;
 
181
    void addCategory(const Category &cat);
 
182
    void removeCategory(int cat_idx);
 
183
 
 
184
    int widgetCount(int cat_idx) const;
 
185
    Widget widget(int cat_idx, int wgt_idx) const;
 
186
    void addWidget(int cat_idx, const Widget &wgt);
 
187
    void removeWidget(int cat_idx, int wgt_idx);
 
188
 
 
189
    void dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list);
 
190
 
 
191
    void setFileName(const QString &file_name);
 
192
    QString fileName() const;
 
193
    bool load();
 
194
    bool save();
 
195
 
 
196
signals:
 
197
    void pressed(const QString dom_xml, const QPoint &global_mouse_pos);
 
198
 
 
199
protected:
 
200
    void contextMenuEvent(QContextMenuEvent *e);
 
201
 
 
202
private slots:
 
203
    void handleMousePress(QTreeWidgetItem *item);
 
204
    void removeCurrentItem();
 
205
    void editCurrentItem();
 
206
    void updateItemData(QTreeWidgetItem *item);
 
207
    void deleteScratchpad();
 
208
 
 
209
private:
 
210
    QDesignerFormEditorInterface *m_core;
 
211
    QString m_file_name;
 
212
    mutable QHash<QString, QIcon> m_pluginIcons;
 
213
 
 
214
    CategoryList domToCateogryList(const QDomDocument &doc) const;
 
215
    Category domToCategory(const QDomElement &cat_elt) const;
 
216
    CategoryList loadCustomCategoryList() const;
 
217
    QDomDocument categoryListToDom(const CategoryList &cat_list) const;
 
218
 
 
219
    QTreeWidgetItem *widgetToItem(const Widget &wgt, QTreeWidgetItem *parent,
 
220
                                    bool editable = false);
 
221
    Widget itemToWidget(const QTreeWidgetItem *item) const;
 
222
 
 
223
    int indexOfCategory(const QString &name) const;
 
224
    int indexOfScratchpad();
 
225
 
 
226
    QString widgetDomXml(const Widget &widget) const;
 
227
 
 
228
    QString qtify(const QString &name) const;
 
229
};
 
230
 
 
231
}  // namespace qdesigner_internal
 
232
 
 
233
QWidget *WidgetBoxItemDelegate::createEditor(QWidget *parent,
 
234
                                                const QStyleOptionViewItem &option,
 
235
                                                const QModelIndex &index) const
 
236
{
 
237
    QWidget *result = SheetDelegate::createEditor(parent, option, index);
 
238
    QLineEdit *line_edit = qobject_cast<QLineEdit*>(result);
 
239
    if (line_edit == 0)
 
240
        return result;
 
241
    line_edit->setValidator(new QRegExpValidator(QRegExp(QLatin1String("[_a-zA-Z][_a-zA-Z0-9]*")), line_edit));
 
242
    return result;
 
243
}
 
244
 
 
245
 
 
246
WidgetBoxTreeView::WidgetBoxTreeView(QDesignerFormEditorInterface *core, QWidget *parent)
 
247
    : QTreeWidget(parent)
 
248
{
 
249
    setItemDelegate(new WidgetBoxItemDelegate(this, this));
 
250
    setRootIsDecorated(false);
 
251
    setColumnCount(1);
 
252
    header()->hide();
 
253
    header()->setResizeMode(QHeaderView::Stretch);
 
254
 
 
255
    m_core = core;
 
256
 
 
257
    connect(this, SIGNAL(itemPressed(QTreeWidgetItem*,int)),
 
258
            this, SLOT(handleMousePress(QTreeWidgetItem*)));
 
259
    connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
 
260
            this, SLOT(updateItemData(QTreeWidgetItem*)));
 
261
 
 
262
    setEditTriggers(QAbstractItemView::AnyKeyPressed);
 
263
}
 
264
 
 
265
WidgetBoxTreeView::~WidgetBoxTreeView()
 
266
{
 
267
    QSettings settings;
 
268
    settings.beginGroup(QLatin1String("WidgetBox"));
 
269
 
 
270
    QStringList open_cat;
 
271
    for (int i = 0; i < categoryCount(); ++i) {
 
272
        QTreeWidgetItem *cat_item = topLevelItem(i);
 
273
        if (isItemExpanded(cat_item))
 
274
            open_cat.append(cat_item->text(0));
 
275
    }
 
276
    settings.setValue(QLatin1String("open categories"), open_cat);
 
277
 
 
278
    settings.endGroup();
 
279
}
 
280
 
 
281
QString WidgetBoxTreeView::qtify(const QString &name) const
 
282
{
 
283
    QString qname = name;
 
284
 
 
285
    Q_ASSERT(name.isEmpty() == false);
 
286
 
 
287
    if (qname.count() > 1 && qname.at(1).toUpper() == qname.at(1) && (qname.at(0) == QLatin1Char('Q') || qname.at(0) == QLatin1Char('K')))
 
288
        qname = qname.mid(1);
 
289
 
 
290
    int i=0;
 
291
    while (i < qname.length()) {
 
292
        if (qname.at(i).toLower() != qname.at(i))
 
293
            qname[i] = qname.at(i).toLower();
 
294
        else
 
295
            break;
 
296
 
 
297
        ++i;
 
298
    }
 
299
 
 
300
    return qname;
 
301
}
 
302
 
 
303
QString WidgetBoxTreeView::widgetDomXml(const Widget &widget) const
 
304
{
 
305
    QString domXml = widget.domXml();
 
306
 
 
307
    if (domXml.isEmpty()) {
 
308
        QString defaultVarName = qtify(widget.name());
 
309
        QString typeStr = widget.type() == Widget::Default
 
310
                            ? QLatin1String("default")
 
311
                            : QLatin1String("custom");
 
312
 
 
313
        domXml = QString::fromUtf8("<widget class=\"%1\" name=\"%2\" type=\"%3\"/>")
 
314
            .arg(widget.name())
 
315
            .arg(defaultVarName)
 
316
            .arg(typeStr);
 
317
    }
 
318
 
 
319
    return domXml;
 
320
}
 
321
 
 
322
void WidgetBoxTreeView::setFileName(const QString &file_name)
 
323
{
 
324
    m_file_name = file_name;
 
325
}
 
326
 
 
327
QString WidgetBoxTreeView::fileName() const
 
328
{
 
329
    return m_file_name;
 
330
}
 
331
 
 
332
bool WidgetBoxTreeView::save()
 
333
{
 
334
    if (fileName().isEmpty())
 
335
        return false;
 
336
 
 
337
    QFile file(fileName());
 
338
    if (!file.open(QIODevice::WriteOnly))
 
339
        return false;
 
340
 
 
341
    CategoryList cat_list;
 
342
    for (int i = 0; i < categoryCount(); ++i)
 
343
        cat_list.append(category(i));
 
344
 
 
345
    QDomDocument doc = categoryListToDom(cat_list);
 
346
    QTextStream stream(&file);
 
347
    doc.save(stream, 4);
 
348
 
 
349
    return true;
 
350
}
 
351
 
 
352
void WidgetBoxTreeView::handleMousePress(QTreeWidgetItem *item)
 
353
{
 
354
    if (item == 0)
 
355
        return;
 
356
 
 
357
    if (item->parent() == 0) {
 
358
        setItemExpanded(item, !isItemExpanded(item));
 
359
        return;
 
360
    }
 
361
 
 
362
    QDesignerWidgetBoxInterface::Widget wgt = qvariant_cast<QDesignerWidgetBoxInterface::Widget>(item->data(0, Qt::UserRole));
 
363
    if (wgt.isNull())
 
364
        return;
 
365
 
 
366
    emit pressed(widgetDomXml(wgt), QCursor::pos());
 
367
}
 
368
 
 
369
int WidgetBoxTreeView::indexOfScratchpad()
 
370
{
 
371
    for (int i = 0; i < topLevelItemCount(); ++i) {
 
372
        if (topLevelItem(i)->data(0, Qt::UserRole).toInt() == SCRATCHPAD_ITEM)
 
373
            return i;
 
374
    }
 
375
 
 
376
    QTreeWidgetItem *scratch_item = new QTreeWidgetItem(this);
 
377
    scratch_item->setText(0, tr("Scratchpad"));
 
378
    scratch_item->setData(0, Qt::UserRole, SCRATCHPAD_ITEM);
 
379
 
 
380
    return categoryCount() - 1;
 
381
}
 
382
 
 
383
int WidgetBoxTreeView::indexOfCategory(const QString &name) const
 
384
{
 
385
    for (int i = 0; i < topLevelItemCount(); ++i) {
 
386
        if (topLevelItem(i)->text(0) == name)
 
387
            return i;
 
388
    }
 
389
    return -1;
 
390
}
 
391
 
 
392
bool WidgetBoxTreeView::load()
 
393
{
 
394
    QString name = fileName();
 
395
 
 
396
    QFile f(name);
 
397
    if (!f.open(QIODevice::ReadOnly)) {
 
398
        return false;
 
399
    }
 
400
 
 
401
    QString error_msg;
 
402
    int line, col;
 
403
    QDomDocument doc;
 
404
    if (!doc.setContent(&f, &error_msg, &line, &col)) {
 
405
        qWarning("WidgetBox: failed to parse \"%s\": on line %d: %s",
 
406
                    name.toUtf8().constData(), line, error_msg.toUtf8().constData());
 
407
        return false;
 
408
    }
 
409
 
 
410
    CategoryList cat_list = domToCateogryList(doc);
 
411
    if (cat_list.isEmpty())
 
412
        return false;
 
413
 
 
414
    // make sure the scratchpad is always at the end
 
415
    int scratch_idx = -1;
 
416
    for (int i = 0; i < cat_list.size(); ++i) {
 
417
        if (cat_list.at(i).type() == Category::Scratchpad) {
 
418
            scratch_idx = i;
 
419
            break;
 
420
        }
 
421
    }
 
422
 
 
423
    clear();
 
424
    foreach(Category cat, cat_list) {
 
425
        if (cat.type() != Category::Scratchpad)
 
426
            addCategory(cat);
 
427
    }
 
428
 
 
429
    CategoryList custom_cat_list = loadCustomCategoryList();
 
430
    foreach (Category cat, custom_cat_list)
 
431
        addCategory(cat);
 
432
 
 
433
    if (scratch_idx != -1)
 
434
        addCategory(cat_list.at(scratch_idx));
 
435
 
 
436
    // Restore which items are expanded
 
437
 
 
438
    QSettings settings;
 
439
    settings.beginGroup(QLatin1String("WidgetBox"));
 
440
 
 
441
    QStringList closed_cat;
 
442
    for (int i = 0; i < topLevelItemCount(); ++i) {
 
443
        QTreeWidgetItem *item = topLevelItem(i);
 
444
        if (!isItemExpanded(item))
 
445
            closed_cat.append(item->text(0));
 
446
    }
 
447
 
 
448
    closed_cat = settings.value(QLatin1String("Closed categories"), closed_cat).toStringList();
 
449
    for (int i = 0; i < closed_cat.size(); ++i) {
 
450
        int cat_idx = indexOfCategory(closed_cat[i]);
 
451
        if (cat_idx == -1)
 
452
            continue;
 
453
        QTreeWidgetItem *item = topLevelItem(cat_idx);
 
454
        if (item == 0)
 
455
            continue;
 
456
        setItemExpanded(item, false);
 
457
    }
 
458
 
 
459
    settings.endGroup();
 
460
 
 
461
    return true;
 
462
}
 
463
 
 
464
QDomDocument WidgetBoxTreeView::categoryListToDom(const CategoryList &cat_list) const
 
465
{
 
466
    QDomDocument doc;
 
467
    QDomElement root = doc.createElement(QLatin1String("widgetbox"));
 
468
    doc.appendChild(root);
 
469
 
 
470
    foreach (Category cat, cat_list) {
 
471
        QDomElement cat_elt = doc.createElement(QLatin1String("category"));
 
472
        root.appendChild(cat_elt);
 
473
        cat_elt.setAttribute(QLatin1String("name"), cat.name());
 
474
        if (cat.type() == Category::Scratchpad)
 
475
            cat_elt.setAttribute(QLatin1String("type"), QLatin1String("scratchpad"));
 
476
        for (int i = 0; i < cat.widgetCount(); ++i) {
 
477
            Widget wgt = cat.widget(i);
 
478
            if (wgt.type() == Widget::Custom)
 
479
                continue;
 
480
 
 
481
            DomWidget *dom_wgt = xmlToUi(widgetDomXml(wgt));
 
482
            QDomElement wgt_elt = dom_wgt->write(doc);
 
483
            wgt_elt.setAttribute(QLatin1String("name"), wgt.name());
 
484
            QString iconName = wgt.iconName();
 
485
            if (!iconName.startsWith("__qt_icon__"))
 
486
              wgt_elt.setAttribute(QLatin1String("icon"), wgt.iconName());
 
487
            wgt_elt.setAttribute(QLatin1String("type"), QLatin1String("default"));
 
488
            cat_elt.appendChild(wgt_elt);
 
489
        }
 
490
    }
 
491
 
 
492
    return doc;
 
493
}
 
494
 
 
495
WidgetBoxTreeView::CategoryList
 
496
    WidgetBoxTreeView::domToCateogryList(const QDomDocument &doc) const
 
497
{
 
498
    CategoryList result;
 
499
 
 
500
    QDomElement root = doc.firstChildElement();
 
501
    if (root.nodeName() != QLatin1String("widgetbox")) {
 
502
        qWarning("WidgetCollectionModel::xmlToModel(): not a widgetbox file");
 
503
        return result;
 
504
    }
 
505
 
 
506
    QDomElement cat_elt = root.firstChildElement();
 
507
    for (; !cat_elt.isNull(); cat_elt = cat_elt.nextSiblingElement()) {
 
508
        if (cat_elt.nodeName() != QLatin1String("category")) {
 
509
            qWarning("WidgetCollectionModel::xmlToModel(): bad child of widgetbox: \"%s\"", cat_elt.nodeName().toUtf8().constData());
 
510
            return result;
 
511
        }
 
512
 
 
513
        Category cat = domToCategory(cat_elt);
 
514
        if (!cat.isNull())
 
515
            result.append(cat);
 
516
    }
 
517
 
 
518
    return result;
 
519
}
 
520
 
 
521
WidgetBoxTreeView::Category WidgetBoxTreeView::domToCategory(const QDomElement &cat_elt) const
 
522
{
 
523
    Category result(cat_elt.attribute(QLatin1String("name")));
 
524
    if (cat_elt.attribute(QLatin1String("type"))
 
525
                                        == QLatin1String("scratchpad"))
 
526
        result.setType(Category::Scratchpad);
 
527
 
 
528
    QDomElement widget_elt = cat_elt.firstChildElement();
 
529
    for (; !widget_elt.isNull(); widget_elt = widget_elt.nextSiblingElement()) {
 
530
        QString type_attr = widget_elt.attribute("type");
 
531
        Widget::Type type = type_attr == QLatin1String("custom")
 
532
                                ? Widget::Custom
 
533
                                : Widget::Default;
 
534
 
 
535
        Widget w(widget_elt.attribute(QLatin1String("name")),
 
536
                    domToString(widget_elt),
 
537
                    widget_elt.attribute(QLatin1String("icon")),
 
538
                    type);
 
539
        result.addWidget(w);
 
540
    }
 
541
 
 
542
    return result;
 
543
}
 
544
 
 
545
static int findCategory(const QString &name, const WidgetBoxTreeView::CategoryList &list)
 
546
{
 
547
    int idx = 0;
 
548
    foreach (const WidgetBoxTreeView::Category &cat, list) {
 
549
        if (cat.name() == name)
 
550
            return idx;
 
551
        ++idx;
 
552
    }
 
553
    return -1;
 
554
}
 
555
 
 
556
WidgetBoxTreeView::CategoryList WidgetBoxTreeView::loadCustomCategoryList() const
 
557
{
 
558
    CategoryList result;
 
559
 
 
560
    PluginManager *pm = m_core->pluginManager();
 
561
 
 
562
    QList<QDesignerCustomWidgetInterface*> customWidgets = pm->registeredCustomWidgets();
 
563
 
 
564
    foreach (QDesignerCustomWidgetInterface *c, customWidgets) {
 
565
        QString dom_xml = c->domXml();
 
566
        if (dom_xml.isEmpty())
 
567
            continue;
 
568
 
 
569
        QString cat_name = c->group();
 
570
        if (cat_name.isEmpty())
 
571
            cat_name = tr("Custom Widgets");
 
572
 
 
573
        int idx = findCategory(cat_name, result);
 
574
        if (idx == -1) {
 
575
            result.append(Category(cat_name));
 
576
            idx = result.size() - 1;
 
577
        }
 
578
        Category &cat = result[idx];
 
579
 
 
580
        QIcon icon = c->icon();
 
581
 
 
582
        QString icon_name;
 
583
        if (icon.isNull())
 
584
            icon_name = QLatin1String("qtlogo.png");
 
585
        else {
 
586
            icon_name = QLatin1String("__qt_icon__") + c->name();
 
587
            m_pluginIcons.insert(icon_name, icon);
 
588
        }
 
589
 
 
590
        cat.addWidget(Widget(c->name(), dom_xml, icon_name, Widget::Custom));
 
591
    }
 
592
 
 
593
    return result;
 
594
}
 
595
 
 
596
QTreeWidgetItem *WidgetBoxTreeView::widgetToItem(const Widget &wgt,
 
597
                                                    QTreeWidgetItem *parent,
 
598
                                                    bool editable)
 
599
{
 
600
    QTreeWidgetItem *item = new QTreeWidgetItem(parent);
 
601
    item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
 
602
 
 
603
    QString icon_name = wgt.iconName();
 
604
    if (icon_name.isEmpty())
 
605
        icon_name = QLatin1String("qtlogo.png");
 
606
 
 
607
    bool block = blockSignals(true);
 
608
    item->setText(0, wgt.name());
 
609
 
 
610
    QIcon icon;
 
611
    if (icon_name.startsWith("__qt_icon__"))
 
612
      icon = m_pluginIcons.value(icon_name);
 
613
    if (icon.isNull())
 
614
      icon = createIconSet(icon_name);
 
615
    item->setIcon(0, icon);
 
616
    item->setData(0, Qt::UserRole, qVariantFromValue(wgt));
 
617
    blockSignals(block);
 
618
 
 
619
    if (editable) {
 
620
        item->setFlags(Qt::ItemIsSelectable
 
621
                        | Qt::ItemIsEditable
 
622
                        | Qt::ItemIsEnabled);
 
623
    }
 
624
 
 
625
    return item;
 
626
}
 
627
 
 
628
WidgetBoxTreeView::Widget WidgetBoxTreeView::itemToWidget(const QTreeWidgetItem *item) const
 
629
{
 
630
    return qvariant_cast<Widget>(item->data(0, Qt::UserRole));
 
631
}
 
632
 
 
633
int WidgetBoxTreeView::categoryCount() const
 
634
{
 
635
    return topLevelItemCount();
 
636
}
 
637
 
 
638
WidgetBoxTreeView::Category WidgetBoxTreeView::category(int cat_idx) const
 
639
{
 
640
    Category result;
 
641
 
 
642
    if (cat_idx >= topLevelItemCount())
 
643
        return result;
 
644
 
 
645
    QTreeWidgetItem *cat_item = topLevelItem(cat_idx);
 
646
    result.setName(cat_item->text(0));
 
647
 
 
648
    for (int i = 0; i < cat_item->childCount(); ++i) {
 
649
        QTreeWidgetItem *child = cat_item->child(i);
 
650
        result.addWidget(itemToWidget(child));
 
651
    }
 
652
 
 
653
    int j = cat_item->data(0, Qt::UserRole).toInt();
 
654
    if (j == SCRATCHPAD_ITEM)
 
655
        result.setType(Category::Scratchpad);
 
656
    else
 
657
        result.setType(Category::Default);
 
658
 
 
659
    return result;
 
660
}
 
661
 
 
662
void WidgetBoxTreeView::addCategory(const Category &cat)
 
663
{
 
664
    if (cat.widgetCount() == 0)
 
665
        return;
 
666
 
 
667
    int idx = indexOfCategory(cat.name());
 
668
    QTreeWidgetItem *cat_item = 0;
 
669
    if (idx == -1) {
 
670
        cat_item = new QTreeWidgetItem(this);
 
671
        cat_item->setText(0, cat.name());
 
672
        setItemExpanded(cat_item, true);
 
673
 
 
674
        if (cat.type() == Category::Scratchpad)
 
675
            cat_item->setData(0, Qt::UserRole, SCRATCHPAD_ITEM);
 
676
    } else {
 
677
        cat_item = topLevelItem(idx);
 
678
    }
 
679
 
 
680
    for (int i = 0; i < cat.widgetCount(); ++i)
 
681
        widgetToItem(cat.widget(i), cat_item, cat.type() == Category::Scratchpad);
 
682
}
 
683
 
 
684
void WidgetBoxTreeView::removeCategory(int cat_idx)
 
685
{
 
686
    if (cat_idx >= topLevelItemCount())
 
687
        return;
 
688
    delete takeTopLevelItem(cat_idx);
 
689
}
 
690
 
 
691
int WidgetBoxTreeView::widgetCount(int cat_idx) const
 
692
{
 
693
    if (cat_idx >= topLevelItemCount())
 
694
        return 0;
 
695
 
 
696
    return topLevelItem(cat_idx)->childCount();
 
697
}
 
698
 
 
699
WidgetBoxTreeView::Widget WidgetBoxTreeView::widget(int cat_idx, int wgt_idx) const
 
700
{
 
701
    if (cat_idx >= topLevelItemCount())
 
702
        return Widget();
 
703
 
 
704
    QTreeWidgetItem *cat_item = topLevelItem(cat_idx);
 
705
 
 
706
    if (wgt_idx >= cat_item->childCount())
 
707
        return Widget();
 
708
 
 
709
    return itemToWidget(cat_item->child(wgt_idx));
 
710
}
 
711
 
 
712
void WidgetBoxTreeView::addWidget(int cat_idx, const Widget &wgt)
 
713
{
 
714
    if (cat_idx >= topLevelItemCount())
 
715
        return;
 
716
 
 
717
    QTreeWidgetItem *cat_item = topLevelItem(cat_idx);
 
718
 
 
719
    bool scratch = cat_item->data(0, Qt::UserRole).toInt() == SCRATCHPAD_ITEM;
 
720
    widgetToItem(wgt, cat_item, scratch);
 
721
}
 
722
 
 
723
void WidgetBoxTreeView::removeWidget(int cat_idx, int wgt_idx)
 
724
{
 
725
    if (cat_idx >= topLevelItemCount())
 
726
        return;
 
727
 
 
728
    QTreeWidgetItem *cat_item = topLevelItem(cat_idx);
 
729
 
 
730
    if (wgt_idx >= cat_item->childCount())
 
731
        return;
 
732
 
 
733
    delete cat_item->takeChild(wgt_idx);
 
734
}
 
735
 
 
736
void WidgetBoxTreeView::removeCurrentItem()
 
737
{
 
738
    QTreeWidgetItem *item = currentItem();
 
739
    if (item == 0)
 
740
        return;
 
741
 
 
742
    QTreeWidgetItem *parent = item->parent();
 
743
    if (parent == 0) {
 
744
        takeTopLevelItem(indexOfTopLevelItem(item));
 
745
    } else {
 
746
        parent->takeChild(parent->indexOfChild(item));
 
747
        setItemExpanded(parent, true);
 
748
        if (parent->data(0, Qt::UserRole).toInt() == SCRATCHPAD_ITEM
 
749
                && parent->childCount() == 0) {
 
750
            QMetaObject::invokeMethod(this, "deleteScratchpad",
 
751
                                        Qt::QueuedConnection);
 
752
        }
 
753
    }
 
754
    delete item;
 
755
 
 
756
    save();
 
757
}
 
758
 
 
759
void WidgetBoxTreeView::deleteScratchpad()
 
760
{
 
761
    int idx = indexOfScratchpad();
 
762
    if (idx == -1)
 
763
        return;
 
764
    delete takeTopLevelItem(idx);
 
765
}
 
766
 
 
767
void WidgetBoxTreeView::updateItemData(QTreeWidgetItem *item)
 
768
{
 
769
    if (item->parent() == 0)
 
770
        return;
 
771
 
 
772
    Widget widget = qvariant_cast<Widget>(item->data(0, Qt::UserRole));
 
773
 
 
774
    if (item->text(0).isEmpty()) {
 
775
        item->setText(0, widget.name());
 
776
        return;
 
777
    }
 
778
 
 
779
    widget.setName(item->text(0));
 
780
    QDomDocument doc = stringToDom(widgetDomXml(widget));
 
781
    QDomElement widget_elt = doc.firstChildElement(QLatin1String("widget"));
 
782
    if (!widget_elt.isNull()) {
 
783
        widget_elt.setAttribute(QLatin1String("name"), item->text(0));
 
784
        widget.setDomXml(domToString(widget_elt));
 
785
    }
 
786
 
 
787
    bool block = blockSignals(true);
 
788
    item->setData(0, Qt::UserRole, qVariantFromValue(widget));
 
789
    blockSignals(block);
 
790
 
 
791
    save();
 
792
}
 
793
 
 
794
void WidgetBoxTreeView::editCurrentItem()
 
795
{
 
796
    QModelIndex index = currentIndex();
 
797
    if (!index.isValid())
 
798
        return;
 
799
 
 
800
    edit(index);
 
801
}
 
802
 
 
803
void WidgetBoxTreeView::contextMenuEvent(QContextMenuEvent *e)
 
804
{
 
805
    QPoint global_pos = mapToGlobal(e->pos());
 
806
    QTreeWidgetItem *item = itemAt(e->pos());
 
807
 
 
808
    bool scratchpad_menu = item != 0
 
809
                            && item->parent() != 0
 
810
                            && item->parent()->data(0, Qt::UserRole).toInt()
 
811
                                ==  SCRATCHPAD_ITEM;
 
812
 
 
813
    if (scratchpad_menu) {
 
814
        e->accept();
 
815
        setCurrentItem(item);
 
816
        QMenu *menu = new QMenu(this);
 
817
        menu->addAction(tr("Remove"), this, SLOT(removeCurrentItem()));
 
818
        menu->addAction(tr("Edit name"), this, SLOT(editCurrentItem()));
 
819
        menu->exec(global_pos);
 
820
    } else {
 
821
        e->ignore();
 
822
    }
 
823
}
 
824
 
 
825
void WidgetBoxTreeView::dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list)
 
826
{
 
827
    QTreeWidgetItem *last_item = 0;
 
828
 
 
829
    foreach (QDesignerDnDItemInterface *item, item_list) {
 
830
        QWidget *w = item->widget();
 
831
        if (w == 0)
 
832
            continue;
 
833
 
 
834
        DomUI *dom_ui = item->domUi();
 
835
        if (dom_ui == 0)
 
836
            continue;
 
837
 
 
838
        int scratch_idx = indexOfScratchpad();
 
839
        QTreeWidgetItem *scratch_item = topLevelItem(scratch_idx);
 
840
 
 
841
        QDomDocument dom;
 
842
        QDomElement elt = dom_ui->write(dom);
 
843
        QString xml = domToString(elt
 
844
                                    .firstChildElement(QLatin1String("widget"))
 
845
                                    .firstChildElement(QLatin1String("widget")));
 
846
 
 
847
        last_item = widgetToItem(Widget(w->objectName(), xml), scratch_item, true);
 
848
        setItemExpanded(scratch_item, true);
 
849
    }
 
850
 
 
851
    if (last_item != 0) {
 
852
        save();
 
853
        QApplication::setActiveWindow(this);
 
854
        setCurrentItem(last_item);
 
855
    }
 
856
}
 
857
 
 
858
/*******************************************************************************
 
859
** WidgetBox
 
860
*/
 
861
 
 
862
WidgetBox::WidgetBox(QDesignerFormEditorInterface *core, QWidget *parent, Qt::WFlags flags)
 
863
    : QDesignerWidgetBoxInterface(parent, flags), m_core(core)
 
864
{
 
865
    m_core = core;
 
866
 
 
867
    QVBoxLayout *l = new QVBoxLayout(this);
 
868
    l->setMargin(0);
 
869
 
 
870
    m_view = new WidgetBoxTreeView(m_core, this);
 
871
    l->addWidget(m_view);
 
872
 
 
873
    connect(m_view, SIGNAL(pressed(QString,QPoint)),
 
874
            this, SLOT(handleMousePress(QString,QPoint)));
 
875
}
 
876
 
 
877
WidgetBox::~WidgetBox()
 
878
{
 
879
}
 
880
 
 
881
QDesignerFormEditorInterface *WidgetBox::core() const
 
882
{
 
883
    return m_core;
 
884
}
 
885
 
 
886
void WidgetBox::handleMousePress(const QString &xml, const QPoint &global_mouse_pos)
 
887
{
 
888
    DomWidget *dom_widget = xmlToUi(xml);
 
889
    if (dom_widget == 0)
 
890
        return;
 
891
    if (QApplication::mouseButtons() == Qt::LeftButton) {
 
892
        QList<QDesignerDnDItemInterface*> item_list;
 
893
        item_list.append(new WidgetBoxDnDItem(core(), dom_widget, global_mouse_pos));
 
894
        m_core->formWindowManager()->dragItems(item_list);
 
895
    }
 
896
}
 
897
 
 
898
int WidgetBox::categoryCount() const
 
899
{
 
900
    return m_view->categoryCount();
 
901
}
 
902
 
 
903
QDesignerWidgetBoxInterface::Category WidgetBox::category(int cat_idx) const
 
904
{
 
905
    return m_view->category(cat_idx);
 
906
}
 
907
 
 
908
void WidgetBox::addCategory(const Category &cat)
 
909
{
 
910
    m_view->addCategory(cat);
 
911
}
 
912
 
 
913
void WidgetBox::removeCategory(int cat_idx)
 
914
{
 
915
    m_view->removeCategory(cat_idx);
 
916
}
 
917
 
 
918
int WidgetBox::widgetCount(int cat_idx) const
 
919
{
 
920
    return m_view->widgetCount(cat_idx);
 
921
}
 
922
 
 
923
QDesignerWidgetBoxInterface::Widget WidgetBox::widget(int cat_idx, int wgt_idx) const
 
924
{
 
925
    return m_view->widget(cat_idx, wgt_idx);
 
926
}
 
927
 
 
928
void WidgetBox::addWidget(int cat_idx, const Widget &wgt)
 
929
{
 
930
    m_view->addWidget(cat_idx, wgt);
 
931
}
 
932
 
 
933
void WidgetBox::removeWidget(int cat_idx, int wgt_idx)
 
934
{
 
935
    m_view->removeWidget(cat_idx, wgt_idx);
 
936
}
 
937
 
 
938
void WidgetBox::dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list, const QPoint&)
 
939
{
 
940
    m_view->dropWidgets(item_list);
 
941
}
 
942
 
 
943
void WidgetBox::setFileName(const QString &file_name)
 
944
{
 
945
    m_view->setFileName(file_name);
 
946
}
 
947
 
 
948
QString WidgetBox::fileName() const
 
949
{
 
950
    return m_view->fileName();
 
951
}
 
952
 
 
953
bool WidgetBox::load()
 
954
{
 
955
    return m_view->load();
 
956
}
 
957
 
 
958
bool WidgetBox::save()
 
959
{
 
960
    return m_view->save();
 
961
}
 
962
 
 
963
#include "widgetbox.moc"