00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "widgetbox.h"
00029
00030
00031 #include <QtDesigner/QtDesigner>
00032
00033
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
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
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
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 }
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
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
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
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"