tools/designer/src/components/widgetbox/widgetbox.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the Qt Designer of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 /*
00025 TRANSLATOR qdesigner_internal::WidgetBoxTreeView
00026 */
00027 
00028 #include "widgetbox.h"
00029 
00030 // sdk
00031 #include <QtDesigner/QtDesigner>
00032 
00033 // shared
00034 #include <pluginmanager_p.h>
00035 #include <sheet_delegate_p.h>
00036 #include <iconloader_p.h>
00037 #include <ui4_p.h>
00038 
00039 #include <QtGui/QtGui>
00040 #include <QtCore/qdebug.h>
00041 
00042 #include "widgetbox_dnditem.h"
00043 
00044 #define SCRATCHPAD_ITEM 1
00045 #define CUSTOM_ITEM     2
00046 
00047 #ifndef Q_MOC_RUN
00048 using namespace qdesigner_internal;
00049 #endif
00050 
00051 /*******************************************************************************
00052 ** Tools
00053 */
00054 static QDomElement childElement(QDomNode node, const QString &tag,
00055                                 const QString &attr_name,
00056                                 const QString &attr_value)
00057 {
00058     if (node.isElement()) {
00059         QDomElement elt = node.toElement();
00060         if (elt.tagName() == tag) {
00061             if (attr_name.isEmpty())
00062                 return elt;
00063             if (elt.hasAttribute(attr_name)) {
00064                 if (attr_value.isEmpty())
00065                     return elt;
00066                 if (elt.attribute(attr_name) == attr_value)
00067                     return elt;
00068             }
00069         }
00070     }
00071 
00072     QDomNode child = node.firstChild();
00073     for (; !child.isNull(); child = child.nextSibling()) {
00074         QDomElement elt = childElement(child, tag, attr_name, attr_value);
00075         if (!elt.isNull())
00076             return elt;
00077     }
00078 
00079     return QDomElement();
00080 }
00081 
00082 typedef QList<QDomElement> ElementList;
00083 static void _childElementList(QDomNode node, const QString &tag,
00084                                     const QString &attr_name,
00085                                     const QString &attr_value,
00086                                     ElementList *result)
00087 {
00088     if (node.isElement()) {
00089         QDomElement elt = node.toElement();
00090         if (elt.tagName() == tag) {
00091             if (attr_name.isEmpty()) {
00092                 result->append(elt);
00093             } else if (elt.hasAttribute(attr_name)) {
00094                 if (attr_value.isEmpty())
00095                     result->append(elt);
00096                 else if (elt.attribute(attr_name) == attr_value)
00097                     result->append(elt);
00098             }
00099         }
00100     }
00101 
00102     QDomNode child = node.firstChild();
00103     for (; !child.isNull(); child = child.nextSibling())
00104         _childElementList(child, tag, attr_name, attr_value, result);
00105 }
00106 
00107 static QString domToString(const QDomElement &elt)
00108 {
00109     QString result;
00110     QTextStream stream(&result, QIODevice::WriteOnly);
00111     elt.save(stream, 2);
00112     stream.flush();
00113     return result;
00114 }
00115 
00116 static QDomDocument stringToDom(const QString &xml)
00117 {
00118     QDomDocument result;
00119     result.setContent(xml);
00120     return result;
00121 }
00122 
00123 static DomWidget *xmlToUi(QString xml)
00124 {
00125     QDomDocument doc;
00126     QString err_msg;
00127     int err_line, err_col;
00128     if (!doc.setContent(xml, &err_msg, &err_line, &err_col)) {
00129         qWarning("xmlToUi: parse failed:\n%s\n:%d:%d: %s",
00130                     xml.toUtf8().constData(),
00131                     err_line, err_col,
00132                     err_msg.toUtf8().constData());
00133         return 0;
00134     }
00135 
00136     QDomElement dom_elt = doc.firstChildElement();
00137     if (dom_elt.nodeName() != QLatin1String("widget")) {
00138         qWarning("xmlToUi: invalid root element:\n%s", xml.toUtf8().constData());
00139         return 0;
00140     }
00141 
00142     DomWidget *widget = new DomWidget;
00143     widget->read(dom_elt);
00144     return widget;
00145 }
00146 
00147 /*******************************************************************************
00148 ** WidgetBoxItemDelegate
00149 */
00150 
00151 namespace qdesigner_internal {
00152 
00153 class WidgetBoxItemDelegate : public SheetDelegate
00154 {
00155 public:
00156     WidgetBoxItemDelegate(QTreeWidget *tree, QWidget *parent = 0)
00157         : SheetDelegate(tree, parent) {}
00158     QWidget *createEditor(QWidget *parent,
00159                           const QStyleOptionViewItem &option,
00160                           const QModelIndex &index) const;
00161 };
00162 
00163 /*******************************************************************************
00164 ** WidgetBoxTreeView
00165 */
00166 
00167 class WidgetBoxTreeView : public QTreeWidget
00168 {
00169     Q_OBJECT
00170 
00171 public:
00172     typedef QDesignerWidgetBoxInterface::Widget Widget;
00173     typedef QDesignerWidgetBoxInterface::Category Category;
00174     typedef QDesignerWidgetBoxInterface::CategoryList CategoryList;
00175 
00176     WidgetBoxTreeView(QDesignerFormEditorInterface *core, QWidget *parent = 0);
00177     ~WidgetBoxTreeView();
00178 
00179     int categoryCount() const;
00180     Category category(int cat_idx) const;
00181     void addCategory(const Category &cat);
00182     void removeCategory(int cat_idx);
00183 
00184     int widgetCount(int cat_idx) const;
00185     Widget widget(int cat_idx, int wgt_idx) const;
00186     void addWidget(int cat_idx, const Widget &wgt);
00187     void removeWidget(int cat_idx, int wgt_idx);
00188 
00189     void dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list);
00190 
00191     void setFileName(const QString &file_name);
00192     QString fileName() const;
00193     bool load();
00194     bool save();
00195 
00196 signals:
00197     void pressed(const QString dom_xml, const QPoint &global_mouse_pos);
00198 
00199 protected:
00200     void contextMenuEvent(QContextMenuEvent *e);
00201 
00202 private slots:
00203     void handleMousePress(QTreeWidgetItem *item);
00204     void removeCurrentItem();
00205     void editCurrentItem();
00206     void updateItemData(QTreeWidgetItem *item);
00207     void deleteScratchpad();
00208 
00209 private:
00210     QDesignerFormEditorInterface *m_core;
00211     QString m_file_name;
00212     mutable QHash<QString, QIcon> m_pluginIcons;
00213     QStringList m_widgetNames;
00214 
00215     CategoryList domToCateogryList(const QDomDocument &doc) const;
00216     Category domToCategory(const QDomElement &cat_elt) const;
00217     CategoryList loadCustomCategoryList() const;
00218     QDomDocument categoryListToDom(const CategoryList &cat_list) const;
00219 
00220     QTreeWidgetItem *widgetToItem(const Widget &wgt, QTreeWidgetItem *parent,
00221                                     bool editable = false);
00222     Widget itemToWidget(const QTreeWidgetItem *item) const;
00223 
00224     int indexOfCategory(const QString &name) const;
00225     int indexOfScratchpad();
00226 
00227     QString widgetDomXml(const Widget &widget) const;
00228 
00229     QString qtify(const QString &name) const;
00230 };
00231 
00232 }  // namespace qdesigner_internal
00233 
00234 QWidget *WidgetBoxItemDelegate::createEditor(QWidget *parent,
00235                                                 const QStyleOptionViewItem &option,
00236                                                 const QModelIndex &index) const
00237 {
00238     QWidget *result = SheetDelegate::createEditor(parent, option, index);
00239     QLineEdit *line_edit = qobject_cast<QLineEdit*>(result);
00240     if (line_edit == 0)
00241         return result;
00242     line_edit->setValidator(new QRegExpValidator(QRegExp(QLatin1String("[_a-zA-Z][_a-zA-Z0-9]*")), line_edit));
00243     return result;
00244 }
00245 
00246 
00247 WidgetBoxTreeView::WidgetBoxTreeView(QDesignerFormEditorInterface *core, QWidget *parent)
00248     : QTreeWidget(parent)
00249 {
00250     setFocusPolicy(Qt::NoFocus);
00251     setIconSize(QSize(22, 22));
00252 
00253     setItemDelegate(new WidgetBoxItemDelegate(this, this));
00254     setRootIsDecorated(false);
00255     setColumnCount(1);
00256     header()->hide();
00257     header()->setResizeMode(QHeaderView::Stretch);
00258 
00259     m_core = core;
00260 
00261     connect(this, SIGNAL(itemPressed(QTreeWidgetItem*,int)),
00262             this, SLOT(handleMousePress(QTreeWidgetItem*)));
00263     connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
00264             this, SLOT(updateItemData(QTreeWidgetItem*)));
00265 
00266     setEditTriggers(QAbstractItemView::AnyKeyPressed);
00267 }
00268 
00269 WidgetBoxTreeView::~WidgetBoxTreeView()
00270 {
00271     QSettings settings;
00272     settings.beginGroup(QLatin1String("WidgetBox"));
00273 
00274     QStringList open_cat;
00275     for (int i = 0; i < categoryCount(); ++i) {
00276         QTreeWidgetItem *cat_item = topLevelItem(i);
00277         if (isItemExpanded(cat_item))
00278             open_cat.append(cat_item->text(0));
00279     }
00280     settings.setValue(QLatin1String("open categories"), open_cat);
00281 
00282     settings.endGroup();
00283 }
00284 
00285 QString WidgetBoxTreeView::qtify(const QString &name) const
00286 {
00287     QString qname = name;
00288 
00289     Q_ASSERT(name.isEmpty() == false);
00290 
00291     if (qname.count() > 1 && qname.at(1).toUpper() == qname.at(1) && (qname.at(0) == QLatin1Char('Q') || qname.at(0) == QLatin1Char('K')))
00292         qname = qname.mid(1);
00293 
00294     int i=0;
00295     while (i < qname.length()) {
00296         if (qname.at(i).toLower() != qname.at(i))
00297             qname[i] = qname.at(i).toLower();
00298         else
00299             break;
00300 
00301         ++i;
00302     }
00303 
00304     return qname;
00305 }
00306 
00307 QString WidgetBoxTreeView::widgetDomXml(const Widget &widget) const
00308 {
00309     QString domXml = widget.domXml();
00310 
00311     if (domXml.isEmpty()) {
00312         QString defaultVarName = qtify(widget.name());
00313         QString typeStr = widget.type() == Widget::Default
00314                             ? QLatin1String("default")
00315                             : QLatin1String("custom");
00316 
00317         domXml = QString::fromUtf8("<widget class=\"%1\" name=\"%2\" type=\"%3\"/>")
00318             .arg(widget.name())
00319             .arg(defaultVarName)
00320             .arg(typeStr);
00321     }
00322 
00323     return domXml;
00324 }
00325 
00326 void WidgetBoxTreeView::setFileName(const QString &file_name)
00327 {
00328     m_file_name = file_name;
00329 }
00330 
00331 QString WidgetBoxTreeView::fileName() const
00332 {
00333     return m_file_name;
00334 }
00335 
00336 bool WidgetBoxTreeView::save()
00337 {
00338     if (fileName().isEmpty())
00339         return false;
00340 
00341     QFile file(fileName());
00342     if (!file.open(QIODevice::WriteOnly))
00343         return false;
00344 
00345     CategoryList cat_list;
00346     for (int i = 0; i < categoryCount(); ++i)
00347         cat_list.append(category(i));
00348 
00349     QDomDocument doc = categoryListToDom(cat_list);
00350     QTextStream stream(&file);
00351     doc.save(stream, 4);
00352 
00353     return true;
00354 }
00355 
00356 void WidgetBoxTreeView::handleMousePress(QTreeWidgetItem *item)
00357 {
00358     if (item == 0)
00359         return;
00360 
00361     if (item->parent() == 0) {
00362         setItemExpanded(item, !isItemExpanded(item));
00363         return;
00364     }
00365 
00366     QDesignerWidgetBoxInterface::Widget wgt = qvariant_cast<QDesignerWidgetBoxInterface::Widget>(item->data(0, Qt::UserRole));
00367     if (wgt.isNull())
00368         return;
00369 
00370     emit pressed(widgetDomXml(wgt), QCursor::pos());
00371 }
00372 
00373 int WidgetBoxTreeView::indexOfScratchpad()
00374 {
00375     for (int i = 0; i < topLevelItemCount(); ++i) {
00376         if (topLevelItem(i)->data(0, Qt::UserRole).toInt() == SCRATCHPAD_ITEM)
00377             return i;
00378     }
00379 
00380     QTreeWidgetItem *scratch_item = new QTreeWidgetItem(this);
00381     scratch_item->setText(0, tr("Scratchpad"));
00382     scratch_item->setData(0, Qt::UserRole, SCRATCHPAD_ITEM);
00383 
00384     return categoryCount() - 1;
00385 }
00386 
00387 int WidgetBoxTreeView::indexOfCategory(const QString &name) const
00388 {
00389     for (int i = 0; i < topLevelItemCount(); ++i) {
00390         if (topLevelItem(i)->text(0) == name)
00391             return i;
00392     }
00393     return -1;
00394 }
00395 
00396 bool WidgetBoxTreeView::load()
00397 {
00398     QString name = fileName();
00399 
00400     QFile f(name);
00401     if (!f.open(QIODevice::ReadOnly)) {
00402         return false;
00403     }
00404 
00405     QString error_msg;
00406     int line, col;
00407     QDomDocument doc;
00408     if (!doc.setContent(&f, &error_msg, &line, &col)) {
00409         qWarning("WidgetBox: failed to parse \"%s\": on line %d: %s",
00410                     name.toUtf8().constData(), line, error_msg.toUtf8().constData());
00411         return false;
00412     }
00413 
00414     CategoryList cat_list = domToCateogryList(doc);
00415     if (cat_list.isEmpty())
00416         return false;
00417 
00418     // make sure the scratchpad is always at the end
00419     int scratch_idx = -1;
00420     for (int i = 0; i < cat_list.size(); ++i) {
00421         if (cat_list.at(i).type() == Category::Scratchpad) {
00422             scratch_idx = i;
00423             break;
00424         }
00425     }
00426 
00427     foreach(Category cat, cat_list) {
00428         if (cat.type() != Category::Scratchpad)
00429             addCategory(cat);
00430     }
00431 
00432     CategoryList custom_cat_list = loadCustomCategoryList();
00433     foreach (Category cat, custom_cat_list)
00434         addCategory(cat);
00435 
00436     if (scratch_idx != -1)
00437         addCategory(cat_list.at(scratch_idx));
00438 
00439     // Restore which items are expanded
00440 
00441     QSettings settings;
00442     settings.beginGroup(QLatin1String("WidgetBox"));
00443 
00444     QStringList closed_cat;
00445     for (int i = 0; i < topLevelItemCount(); ++i) {
00446         QTreeWidgetItem *item = topLevelItem(i);
00447         if (!isItemExpanded(item))
00448             closed_cat.append(item->text(0));
00449     }
00450 
00451     closed_cat = settings.value(QLatin1String("Closed categories"), closed_cat).toStringList();
00452     for (int i = 0; i < closed_cat.size(); ++i) {
00453         int cat_idx = indexOfCategory(closed_cat[i]);
00454         if (cat_idx == -1)
00455             continue;
00456         QTreeWidgetItem *item = topLevelItem(cat_idx);
00457         if (item == 0)
00458             continue;
00459         setItemExpanded(item, false);
00460     }
00461 
00462     settings.endGroup();
00463 
00464     return true;
00465 }
00466 
00467 QDomDocument WidgetBoxTreeView::categoryListToDom(const CategoryList &cat_list) const
00468 {
00469     QDomDocument doc;
00470     QDomElement root = doc.createElement(QLatin1String("widgetbox"));
00471     doc.appendChild(root);
00472 
00473     foreach (Category cat, cat_list) {
00474         QDomElement cat_elt = doc.createElement(QLatin1String("category"));
00475         root.appendChild(cat_elt);
00476         cat_elt.setAttribute(QLatin1String("name"), cat.name());
00477         if (cat.type() == Category::Scratchpad)
00478             cat_elt.setAttribute(QLatin1String("type"), QLatin1String("scratchpad"));
00479         for (int i = 0; i < cat.widgetCount(); ++i) {
00480             Widget wgt = cat.widget(i);
00481             if (wgt.type() == Widget::Custom)
00482                 continue;
00483 
00484             DomWidget *dom_wgt = xmlToUi(widgetDomXml(wgt));
00485             QDomElement wgt_elt = dom_wgt->write(doc);
00486             wgt_elt.setAttribute(QLatin1String("name"), wgt.name());
00487             QString iconName = wgt.iconName();
00488             if (!iconName.startsWith("__qt_icon__"))
00489               wgt_elt.setAttribute(QLatin1String("icon"), wgt.iconName());
00490             wgt_elt.setAttribute(QLatin1String("type"), QLatin1String("default"));
00491             cat_elt.appendChild(wgt_elt);
00492         }
00493     }
00494 
00495     return doc;
00496 }
00497 
00498 WidgetBoxTreeView::CategoryList
00499     WidgetBoxTreeView::domToCateogryList(const QDomDocument &doc) const
00500 {
00501     CategoryList result;
00502 
00503     QDomElement root = doc.firstChildElement();
00504     if (root.nodeName() != QLatin1String("widgetbox")) {
00505         qWarning("WidgetCollectionModel::xmlToModel(): not a widgetbox file");
00506         return result;
00507     }
00508 
00509     QDomElement cat_elt = root.firstChildElement();
00510     for (; !cat_elt.isNull(); cat_elt = cat_elt.nextSiblingElement()) {
00511         if (cat_elt.nodeName() != QLatin1String("category")) {
00512             qWarning("WidgetCollectionModel::xmlToModel(): bad child of widgetbox: \"%s\"", cat_elt.nodeName().toUtf8().constData());
00513             return result;
00514         }
00515 
00516         Category cat = domToCategory(cat_elt);
00517         if (!cat.isNull())
00518             result.append(cat);
00519     }
00520 
00521     return result;
00522 }
00523 
00524 WidgetBoxTreeView::Category WidgetBoxTreeView::domToCategory(const QDomElement &cat_elt) const
00525 {
00526     QString name = cat_elt.attribute(QLatin1String("name"));
00527 
00528     if (name == QLatin1String("[invisible]"))
00529         return Category();
00530 
00531     Category result(name);
00532 
00533     if (cat_elt.attribute(QLatin1String("type")) == QLatin1String("scratchpad"))
00534         result.setType(Category::Scratchpad);
00535 
00536     QDomElement widget_elt = cat_elt.firstChildElement();
00537     for (; !widget_elt.isNull(); widget_elt = widget_elt.nextSiblingElement()) {
00538         QString type_attr = widget_elt.attribute("type");
00539         Widget::Type type = type_attr == QLatin1String("custom")
00540                                 ? Widget::Custom
00541                                 : Widget::Default;
00542 
00543         Widget w(widget_elt.attribute(QLatin1String("name")),
00544                     domToString(widget_elt),
00545                     widget_elt.attribute(QLatin1String("icon")),
00546                     type);
00547         result.addWidget(w);
00548     }
00549 
00550     return result;
00551 }
00552 
00553 static int findCategory(const QString &name, const WidgetBoxTreeView::CategoryList &list)
00554 {
00555     int idx = 0;
00556     foreach (const WidgetBoxTreeView::Category &cat, list) {
00557         if (cat.name() == name)
00558             return idx;
00559         ++idx;
00560     }
00561     return -1;
00562 }
00563 
00564 WidgetBoxTreeView::CategoryList WidgetBoxTreeView::loadCustomCategoryList() const
00565 {
00566     CategoryList result;
00567 
00568     QDesignerPluginManager *pm = m_core->pluginManager();
00569 
00570     QList<QDesignerCustomWidgetInterface*> customWidgets = pm->registeredCustomWidgets();
00571 
00572     foreach (QDesignerCustomWidgetInterface *c, customWidgets) {
00573         QString dom_xml = c->domXml();
00574         if (dom_xml.isEmpty())
00575             continue;
00576 
00577         QString cat_name = c->group();
00578         if (cat_name.isEmpty())
00579             cat_name = tr("Custom Widgets");
00580         else if (cat_name == QLatin1String("[invisible]"))
00581             continue;
00582 
00583         int idx = findCategory(cat_name, result);
00584         if (idx == -1) {
00585             result.append(Category(cat_name));
00586             idx = result.size() - 1;
00587         }
00588         Category &cat = result[idx];
00589 
00590         QIcon icon = c->icon();
00591 
00592         QString icon_name;
00593         if (icon.isNull())
00594             icon_name = QLatin1String("qtlogo.png");
00595         else {
00596             icon_name = QLatin1String("__qt_icon__") + c->name();
00597             m_pluginIcons.insert(icon_name, icon);
00598         }
00599 
00600         cat.addWidget(Widget(c->name(), dom_xml, icon_name, Widget::Custom));
00601     }
00602 
00603     return result;
00604 }
00605 
00606 QTreeWidgetItem *WidgetBoxTreeView::widgetToItem(const Widget &wgt,
00607                                                     QTreeWidgetItem *parent,
00608                                                     bool editable)
00609 {
00610     if (!editable && m_widgetNames.contains(wgt.name()))
00611         return 0;
00612 
00613     QTreeWidgetItem *item = new QTreeWidgetItem(parent);
00614     item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
00615 
00616     QString icon_name = wgt.iconName();
00617     if (icon_name.isEmpty())
00618         icon_name = QLatin1String("qtlogo.png");
00619 
00620     bool block = blockSignals(true);
00621     item->setText(0, wgt.name());
00622 
00623     if (!editable)
00624         m_widgetNames.append(wgt.name());
00625 
00626     QIcon icon;
00627     if (icon_name.startsWith("__qt_icon__"))
00628       icon = m_pluginIcons.value(icon_name);
00629     if (icon.isNull())
00630       icon = createIconSet(icon_name);
00631     item->setIcon(0, icon);
00632     item->setData(0, Qt::UserRole, qVariantFromValue(wgt));
00633     blockSignals(block);
00634 
00635     if (editable) {
00636         item->setFlags(Qt::ItemIsSelectable
00637                         | Qt::ItemIsEditable
00638                         | Qt::ItemIsEnabled);
00639     }
00640 
00641     return item;
00642 }
00643 
00644 WidgetBoxTreeView::Widget WidgetBoxTreeView::itemToWidget(const QTreeWidgetItem *item) const
00645 {
00646     return qvariant_cast<Widget>(item->data(0, Qt::UserRole));
00647 }
00648 
00649 int WidgetBoxTreeView::categoryCount() const
00650 {
00651     return topLevelItemCount();
00652 }
00653 
00654 WidgetBoxTreeView::Category WidgetBoxTreeView::category(int cat_idx) const
00655 {
00656     Category result;
00657 
00658     if (cat_idx >= topLevelItemCount())
00659         return result;
00660 
00661     QTreeWidgetItem *cat_item = topLevelItem(cat_idx);
00662     result.setName(cat_item->text(0));
00663 
00664     for (int i = 0; i < cat_item->childCount(); ++i) {
00665         QTreeWidgetItem *child = cat_item->child(i);
00666         result.addWidget(itemToWidget(child));
00667     }
00668 
00669     int j = cat_item->data(0, Qt::UserRole).toInt();
00670     if (j == SCRATCHPAD_ITEM)
00671         result.setType(Category::Scratchpad);
00672     else
00673         result.setType(Category::Default);
00674 
00675     return result;
00676 }
00677 
00678 void WidgetBoxTreeView::addCategory(const Category &cat)
00679 {
00680     if (cat.widgetCount() == 0)
00681         return;
00682 
00683     int idx = indexOfCategory(cat.name());
00684     QTreeWidgetItem *cat_item = 0;
00685     if (idx == -1) {
00686         cat_item = new QTreeWidgetItem(this);
00687         cat_item->setText(0, cat.name());
00688         setItemExpanded(cat_item, true);
00689 
00690         if (cat.type() == Category::Scratchpad)
00691             cat_item->setData(0, Qt::UserRole, SCRATCHPAD_ITEM);
00692     } else {
00693         cat_item = topLevelItem(idx);
00694     }
00695 
00696     for (int i = 0; i < cat.widgetCount(); ++i)
00697         widgetToItem(cat.widget(i), cat_item, cat.type() == Category::Scratchpad);
00698 }
00699 
00700 void WidgetBoxTreeView::removeCategory(int cat_idx)
00701 {
00702     if (cat_idx >= topLevelItemCount())
00703         return;
00704     delete takeTopLevelItem(cat_idx);
00705 }
00706 
00707 int WidgetBoxTreeView::widgetCount(int cat_idx) const
00708 {
00709     if (cat_idx >= topLevelItemCount())
00710         return 0;
00711 
00712     return topLevelItem(cat_idx)->childCount();
00713 }
00714 
00715 WidgetBoxTreeView::Widget WidgetBoxTreeView::widget(int cat_idx, int wgt_idx) const
00716 {
00717     if (cat_idx >= topLevelItemCount())
00718         return Widget();
00719 
00720     QTreeWidgetItem *cat_item = topLevelItem(cat_idx);
00721 
00722     if (wgt_idx >= cat_item->childCount())
00723         return Widget();
00724 
00725     return itemToWidget(cat_item->child(wgt_idx));
00726 }
00727 
00728 void WidgetBoxTreeView::addWidget(int cat_idx, const Widget &wgt)
00729 {
00730     if (cat_idx >= topLevelItemCount())
00731         return;
00732 
00733     QTreeWidgetItem *cat_item = topLevelItem(cat_idx);
00734 
00735     bool scratch = cat_item->data(0, Qt::UserRole).toInt() == SCRATCHPAD_ITEM;
00736     widgetToItem(wgt, cat_item, scratch);
00737 }
00738 
00739 void WidgetBoxTreeView::removeWidget(int cat_idx, int wgt_idx)
00740 {
00741     if (cat_idx >= topLevelItemCount())
00742         return;
00743 
00744     QTreeWidgetItem *cat_item = topLevelItem(cat_idx);
00745 
00746     if (wgt_idx >= cat_item->childCount())
00747         return;
00748 
00749     delete cat_item->takeChild(wgt_idx);
00750 }
00751 
00752 void WidgetBoxTreeView::removeCurrentItem()
00753 {
00754     QTreeWidgetItem *item = currentItem();
00755     if (item == 0)
00756         return;
00757 
00758     QTreeWidgetItem *parent = item->parent();
00759     if (parent == 0) {
00760         takeTopLevelItem(indexOfTopLevelItem(item));
00761     } else {
00762         parent->takeChild(parent->indexOfChild(item));
00763         setItemExpanded(parent, true);
00764         if (parent->data(0, Qt::UserRole).toInt() == SCRATCHPAD_ITEM
00765                 && parent->childCount() == 0) {
00766             QMetaObject::invokeMethod(this, "deleteScratchpad",
00767                                         Qt::QueuedConnection);
00768         }
00769     }
00770     delete item;
00771 
00772     save();
00773 }
00774 
00775 void WidgetBoxTreeView::deleteScratchpad()
00776 {
00777     int idx = indexOfScratchpad();
00778     if (idx == -1)
00779         return;
00780     delete takeTopLevelItem(idx);
00781 }
00782 
00783 void WidgetBoxTreeView::updateItemData(QTreeWidgetItem *item)
00784 {
00785     if (item->parent() == 0)
00786         return;
00787 
00788     Widget widget = qvariant_cast<Widget>(item->data(0, Qt::UserRole));
00789 
00790     if (item->text(0).isEmpty()) {
00791         QString widgetName = widget.name();
00792         if (!widgetName.isEmpty())
00793             item->setText(0, widgetName);
00794         return;
00795     }
00796 
00797     widget.setName(item->text(0));
00798     QDomDocument doc = stringToDom(widgetDomXml(widget));
00799     QDomElement widget_elt = doc.firstChildElement(QLatin1String("widget"));
00800     if (!widget_elt.isNull()) {
00801         widget_elt.setAttribute(QLatin1String("name"), item->text(0));
00802         widget.setDomXml(domToString(widget_elt));
00803     }
00804 
00805     bool block = blockSignals(true);
00806     item->setData(0, Qt::UserRole, qVariantFromValue(widget));
00807     blockSignals(block);
00808 
00809     save();
00810 }
00811 
00812 void WidgetBoxTreeView::editCurrentItem()
00813 {
00814     QModelIndex index = currentIndex();
00815     if (!index.isValid())
00816         return;
00817 
00818     edit(index);
00819 }
00820 
00821 void WidgetBoxTreeView::contextMenuEvent(QContextMenuEvent *e)
00822 {
00823     QPoint global_pos = mapToGlobal(e->pos());
00824     QTreeWidgetItem *item = itemAt(e->pos());
00825 
00826     bool scratchpad_menu = item != 0
00827                             && item->parent() != 0
00828                             && item->parent()->data(0, Qt::UserRole).toInt()
00829                                 ==  SCRATCHPAD_ITEM;
00830 
00831     if (scratchpad_menu) {
00832         e->accept();
00833         setCurrentItem(item);
00834         QMenu *menu = new QMenu(this);
00835         menu->addAction(tr("Remove"), this, SLOT(removeCurrentItem()));
00836         menu->addAction(tr("Edit name"), this, SLOT(editCurrentItem()));
00837         menu->exec(global_pos);
00838     } else {
00839         e->ignore();
00840     }
00841 }
00842 
00843 void WidgetBoxTreeView::dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list)
00844 {
00845     QTreeWidgetItem *last_item = 0;
00846 
00847     foreach (QDesignerDnDItemInterface *item, item_list) {
00848         QWidget *w = item->widget();
00849         if (w == 0)
00850             continue;
00851 
00852         DomUI *dom_ui = item->domUi();
00853         if (dom_ui == 0)
00854             continue;
00855 
00856         int scratch_idx = indexOfScratchpad();
00857         QTreeWidgetItem *scratch_item = topLevelItem(scratch_idx);
00858 
00859         QDomDocument dom;
00860         QDomElement elt = dom_ui->write(dom);
00861         QString xml = domToString(elt
00862                                     .firstChildElement(QLatin1String("widget"))
00863                                     .firstChildElement(QLatin1String("widget")));
00864 
00865         last_item = widgetToItem(Widget(w->objectName(), xml), scratch_item, true);
00866         setItemExpanded(scratch_item, true);
00867     }
00868 
00869     if (last_item != 0) {
00870         save();
00871         QApplication::setActiveWindow(this);
00872         setCurrentItem(last_item);
00873     }
00874 }
00875 
00876 /*******************************************************************************
00877 ** WidgetBox
00878 */
00879 
00880 WidgetBox::WidgetBox(QDesignerFormEditorInterface *core, QWidget *parent, Qt::WindowFlags flags)
00881     : QDesignerWidgetBoxInterface(parent, flags), m_core(core)
00882 {
00883     m_core = core;
00884 
00885     QVBoxLayout *l = new QVBoxLayout(this);
00886     l->setMargin(0);
00887 
00888     m_view = new WidgetBoxTreeView(m_core, this);
00889     l->addWidget(m_view);
00890 
00891     connect(m_view, SIGNAL(pressed(QString,QPoint)),
00892             this, SLOT(handleMousePress(QString,QPoint)));
00893 }
00894 
00895 WidgetBox::~WidgetBox()
00896 {
00897 }
00898 
00899 QDesignerFormEditorInterface *WidgetBox::core() const
00900 {
00901     return m_core;
00902 }
00903 
00904 void WidgetBox::handleMousePress(const QString &xml, const QPoint &global_mouse_pos)
00905 {
00906     DomWidget *dom_widget = xmlToUi(xml);
00907     if (dom_widget == 0)
00908         return;
00909     if (QApplication::mouseButtons() == Qt::LeftButton) {
00910         QList<QDesignerDnDItemInterface*> item_list;
00911         item_list.append(new WidgetBoxDnDItem(core(), dom_widget, global_mouse_pos));
00912         m_core->formWindowManager()->dragItems(item_list);
00913     }
00914 }
00915 
00916 int WidgetBox::categoryCount() const
00917 {
00918     return m_view->categoryCount();
00919 }
00920 
00921 QDesignerWidgetBoxInterface::Category WidgetBox::category(int cat_idx) const
00922 {
00923     return m_view->category(cat_idx);
00924 }
00925 
00926 void WidgetBox::addCategory(const Category &cat)
00927 {
00928     m_view->addCategory(cat);
00929 }
00930 
00931 void WidgetBox::removeCategory(int cat_idx)
00932 {
00933     m_view->removeCategory(cat_idx);
00934 }
00935 
00936 int WidgetBox::widgetCount(int cat_idx) const
00937 {
00938     return m_view->widgetCount(cat_idx);
00939 }
00940 
00941 QDesignerWidgetBoxInterface::Widget WidgetBox::widget(int cat_idx, int wgt_idx) const
00942 {
00943     return m_view->widget(cat_idx, wgt_idx);
00944 }
00945 
00946 void WidgetBox::addWidget(int cat_idx, const Widget &wgt)
00947 {
00948     m_view->addWidget(cat_idx, wgt);
00949 }
00950 
00951 void WidgetBox::removeWidget(int cat_idx, int wgt_idx)
00952 {
00953     m_view->removeWidget(cat_idx, wgt_idx);
00954 }
00955 
00956 void WidgetBox::dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list, const QPoint&)
00957 {
00958     m_view->dropWidgets(item_list);
00959 }
00960 
00961 void WidgetBox::setFileName(const QString &file_name)
00962 {
00963     m_view->setFileName(file_name);
00964 }
00965 
00966 QString WidgetBox::fileName() const
00967 {
00968     return m_view->fileName();
00969 }
00970 
00971 bool WidgetBox::load()
00972 {
00973     return m_view->load();
00974 }
00975 
00976 bool WidgetBox::save()
00977 {
00978     return m_view->save();
00979 }
00980 
00981 #include "widgetbox.moc"

Generated on Thu Mar 15 12:01:15 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1