summaryrefslogtreecommitdiffstats
path: root/tools/designer/src/components/widgetbox
diff options
context:
space:
mode:
Diffstat (limited to 'tools/designer/src/components/widgetbox')
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox.cpp232
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox.h103
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox.pri14
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox.qrc5
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox.xml932
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp215
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox_dnditem.h67
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox_global.h57
-rw-r--r--tools/designer/src/components/widgetbox/widgetboxcategorylistview.cpp494
-rw-r--r--tools/designer/src/components/widgetbox/widgetboxcategorylistview.h118
-rw-r--r--tools/designer/src/components/widgetbox/widgetboxtreewidget.cpp998
-rw-r--r--tools/designer/src/components/widgetbox/widgetboxtreewidget.h150
12 files changed, 3385 insertions, 0 deletions
diff --git a/tools/designer/src/components/widgetbox/widgetbox.cpp b/tools/designer/src/components/widgetbox/widgetbox.cpp
new file mode 100644
index 0000000..d8c6aa3
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox.cpp
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "widgetbox.h"
+#include "widgetboxtreewidget.h"
+#include "widgetbox_dnditem.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+
+#include <iconloader_p.h>
+#include <qdesigner_utils_p.h>
+#include <filterwidget_p.h>
+
+#include <QtGui/QDropEvent>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QApplication>
+#include <QtGui/QToolBar>
+#include <QtGui/QIcon>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+WidgetBox::WidgetBox(QDesignerFormEditorInterface *core, QWidget *parent, Qt::WindowFlags flags)
+ : QDesignerWidgetBox(parent, flags),
+ m_core(core),
+ m_view(new WidgetBoxTreeWidget(m_core))
+{
+
+ QVBoxLayout *l = new QVBoxLayout(this);
+ l->setMargin(0);
+ l->setSpacing(0);
+
+ // Prevent the filter from grabbing focus since Our view has Qt::NoFocus
+ FilterWidget *filterWidget = new FilterWidget(0, FilterWidget::LayoutAlignNone);
+ filterWidget->setRefuseFocus(true);
+ connect(filterWidget, SIGNAL(filterChanged(QString)), m_view, SLOT(filter(QString)));
+ l->addWidget(filterWidget);
+
+ // View
+ connect(m_view, SIGNAL(pressed(QString,QString,QPoint)),
+ this, SLOT(handleMousePress(QString,QString,QPoint)));
+ l->addWidget(m_view);
+
+ setAcceptDrops (true);
+}
+
+WidgetBox::~WidgetBox()
+{
+}
+
+QDesignerFormEditorInterface *WidgetBox::core() const
+{
+ return m_core;
+}
+
+void WidgetBox::handleMousePress(const QString &name, const QString &xml, const QPoint &global_mouse_pos)
+{
+ if (QApplication::mouseButtons() != Qt::LeftButton)
+ return;
+
+ DomUI *ui = xmlToUi(name, xml, true);
+ if (ui == 0)
+ return;
+ QList<QDesignerDnDItemInterface*> item_list;
+ item_list.append(new WidgetBoxDnDItem(core(), ui, global_mouse_pos));
+ m_core->formWindowManager()->dragItems(item_list);
+}
+
+int WidgetBox::categoryCount() const
+{
+ return m_view->categoryCount();
+}
+
+QDesignerWidgetBoxInterface::Category WidgetBox::category(int cat_idx) const
+{
+ return m_view->category(cat_idx);
+}
+
+void WidgetBox::addCategory(const Category &cat)
+{
+ m_view->addCategory(cat);
+}
+
+void WidgetBox::removeCategory(int cat_idx)
+{
+ m_view->removeCategory(cat_idx);
+}
+
+int WidgetBox::widgetCount(int cat_idx) const
+{
+ return m_view->widgetCount(cat_idx);
+}
+
+QDesignerWidgetBoxInterface::Widget WidgetBox::widget(int cat_idx, int wgt_idx) const
+{
+ return m_view->widget(cat_idx, wgt_idx);
+}
+
+void WidgetBox::addWidget(int cat_idx, const Widget &wgt)
+{
+ m_view->addWidget(cat_idx, wgt);
+}
+
+void WidgetBox::removeWidget(int cat_idx, int wgt_idx)
+{
+ m_view->removeWidget(cat_idx, wgt_idx);
+}
+
+void WidgetBox::dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list, const QPoint&)
+{
+ m_view->dropWidgets(item_list);
+}
+
+void WidgetBox::setFileName(const QString &file_name)
+{
+ m_view->setFileName(file_name);
+}
+
+QString WidgetBox::fileName() const
+{
+ return m_view->fileName();
+}
+
+bool WidgetBox::load()
+{
+ return m_view->load(loadMode());
+}
+
+bool WidgetBox::loadContents(const QString &contents)
+{
+ return m_view->loadContents(contents);
+}
+
+bool WidgetBox::save()
+{
+ return m_view->save();
+}
+
+static const QDesignerMimeData *checkDragEvent(QDropEvent * event,
+ bool acceptEventsFromWidgetBox)
+{
+ const QDesignerMimeData *mimeData = qobject_cast<const QDesignerMimeData *>(event->mimeData());
+ if (!mimeData) {
+ event->ignore();
+ return 0;
+ }
+ // If desired, ignore a widget box drag and drop, where widget==0.
+ if (!acceptEventsFromWidgetBox) {
+ const bool fromWidgetBox = !mimeData->items().first()->widget();
+ if (fromWidgetBox) {
+ event->ignore();
+ return 0;
+ }
+ }
+
+ mimeData->acceptEvent(event);
+ return mimeData;
+}
+
+void WidgetBox::dragEnterEvent (QDragEnterEvent * event)
+{
+ // We accept event originating from the widget box also here,
+ // because otherwise Windows will not show the DnD pixmap.
+ checkDragEvent(event, true);
+}
+
+void WidgetBox::dragMoveEvent(QDragMoveEvent * event)
+{
+ checkDragEvent(event, true);
+}
+
+void WidgetBox::dropEvent(QDropEvent * event)
+{
+ const QDesignerMimeData *mimeData = checkDragEvent(event, false);
+ if (!mimeData)
+ return;
+
+ dropWidgets(mimeData->items(), event->pos());
+ QDesignerMimeData::removeMovedWidgetsFromSourceForm(mimeData->items());
+}
+
+QIcon WidgetBox::iconForWidget(const QString &className, const QString &category) const
+{
+ Widget widgetData;
+ if (!findWidget(this, className, category, &widgetData))
+ return QIcon();
+ return m_view->iconForWidget(widgetData.iconName());
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/widgetbox/widgetbox.h b/tools/designer/src/components/widgetbox/widgetbox.h
new file mode 100644
index 0000000..e77c0ed
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WIDGETBOX_H
+#define WIDGETBOX_H
+
+#include "widgetbox_global.h"
+#include <qdesigner_widgetbox_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class WidgetBoxTreeWidget;
+
+class QT_WIDGETBOX_EXPORT WidgetBox : public QDesignerWidgetBox
+{
+ Q_OBJECT
+public:
+ explicit WidgetBox(QDesignerFormEditorInterface *core, QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ virtual ~WidgetBox();
+
+ QDesignerFormEditorInterface *core() const;
+
+ virtual int categoryCount() const;
+ virtual Category category(int cat_idx) const;
+ virtual void addCategory(const Category &cat);
+ virtual void removeCategory(int cat_idx);
+
+ virtual int widgetCount(int cat_idx) const;
+ virtual Widget widget(int cat_idx, int wgt_idx) const;
+ virtual void addWidget(int cat_idx, const Widget &wgt);
+ virtual void removeWidget(int cat_idx, int wgt_idx);
+
+ void dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list, const QPoint &global_mouse_pos);
+
+ virtual void setFileName(const QString &file_name);
+ virtual QString fileName() const;
+ virtual bool load();
+ virtual bool save();
+
+ virtual bool loadContents(const QString &contents);
+ virtual QIcon iconForWidget(const QString &className, const QString &category = QString()) const;
+
+protected:
+ virtual void dragEnterEvent (QDragEnterEvent * event);
+ virtual void dragMoveEvent(QDragMoveEvent * event);
+ virtual void dropEvent (QDropEvent * event);
+
+private slots:
+ void handleMousePress(const QString &name, const QString &xml, const QPoint &global_mouse_pos);
+
+private:
+ QDesignerFormEditorInterface *m_core;
+ WidgetBoxTreeWidget *m_view;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // WIDGETBOX_H
diff --git a/tools/designer/src/components/widgetbox/widgetbox.pri b/tools/designer/src/components/widgetbox/widgetbox.pri
new file mode 100644
index 0000000..dd8ad00
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox.pri
@@ -0,0 +1,14 @@
+
+INCLUDEPATH += $$PWD
+
+SOURCES += $$PWD/widgetboxcategorylistview.cpp \
+ $$PWD/widgetboxtreewidget.cpp \
+ $$PWD/widgetbox.cpp \
+ $$PWD/widgetbox_dnditem.cpp
+HEADERS += $$PWD/widgetboxcategorylistview.h \
+ $$PWD/widgetboxtreewidget.h \
+ $$PWD/widgetbox.h \
+ $$PWD/widgetbox_global.h \
+ $$PWD/widgetbox_dnditem.h
+
+RESOURCES += $$PWD/widgetbox.qrc
diff --git a/tools/designer/src/components/widgetbox/widgetbox.qrc b/tools/designer/src/components/widgetbox/widgetbox.qrc
new file mode 100644
index 0000000..7ecf78c
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/trolltech/widgetbox">
+ <file>widgetbox.xml</file>
+ </qresource>
+</RCC>
diff --git a/tools/designer/src/components/widgetbox/widgetbox.xml b/tools/designer/src/components/widgetbox/widgetbox.xml
new file mode 100644
index 0000000..462ac7d
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox.xml
@@ -0,0 +1,932 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+**************************************************************************-->
+<widgetbox version="4.2">
+ <category name="Layouts">
+
+ <categoryentry name="Vertical Layout" icon="win/editvlayout.png">
+ <ui>
+ <widget class="QWidget">
+ <property name="objectName">
+ <string notr="true">verticalLayoutWidget</string>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>160</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ </layout>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Horizontal Layout" icon="win/edithlayout.png">
+ <ui>
+ <widget class="QWidget">
+ <property name="objectName">
+ <string notr="true">horizontalLayoutWidget</string>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>160</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ </layout>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Grid Layout" icon="win/editgrid.png">
+ <ui>
+ <widget class="QWidget">
+ <property name="objectName">
+ <string notr="true">gridLayoutWidget</string>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>160</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ </layout>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Form Layout" icon="win/editform.png">
+ <ui>
+ <widget class="QWidget">
+ <property name="objectName">
+ <string notr="true">formLayoutWidget</string>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>160</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ </layout>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+
+ <category name="Spacers">
+
+ <categoryentry name="Horizontal Spacer" icon="widgets/spacer.png">
+ <ui>
+ <widget class="Spacer">
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="objectName">
+ <string notr="true">horizontalSpacer</string>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Vertical Spacer" icon="widgets/vspacer.png">
+ <ui>
+ <widget class="Spacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="objectName">
+ <string notr="true">verticalSpacer</string>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+
+ <category name="Buttons">
+
+ <categoryentry name="Push Button" icon="widgets/pushbutton.png">
+ <ui>
+ <widget class="QPushButton">
+ <property name="text" >
+ <string>PushButton</string>
+ </property>
+ <property name="objectName">
+ <string notr="true">pushButton</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Tool Button" icon="widgets/toolbutton.png">
+ <ui>
+ <widget class="QToolButton">
+ <property name="objectName">
+ <string notr="true">toolButton</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Radio Button" icon="widgets/radiobutton.png">
+ <ui>
+ <widget class="QRadioButton">
+ <property name="text" >
+ <string>RadioButton</string>
+ </property>
+ <property name="objectName">
+ <string notr="true">radioButton</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Check Box" icon="widgets/checkbox.png">
+ <ui>
+ <widget class="QCheckBox">
+ <property name="text" >
+ <string>CheckBox</string>
+ </property>
+ <property name="objectName">
+ <string notr="true">checkBox</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Command Link Button" icon="widgets/commandlinkbutton.png">
+ <ui>
+ <widget class="QCommandLinkButton">
+ <property name="text" >
+ <string>CommandLinkButton</string>
+ </property>
+ <property name="objectName">
+ <string notr="true">commandLinkButton</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Button Box" icon="widgets/dialogbuttonbox.png">
+ <ui>
+ <widget class="QDialogButtonBox">
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Ok|QDialogButtonBox::Cancel</set>
+ </property>
+ <property name="objectName">
+ <string notr="true">buttonBox</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+
+ <category name="Item Views (Model-Based)">
+
+ <categoryentry name="List View" icon="widgets/listbox.png">
+ <ui>
+ <widget class="QListView">
+ <property name="objectName">
+ <string notr="true">listView</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Tree View" icon="widgets/listview.png">
+ <ui>
+ <widget class="QTreeView">
+ <property name="objectName">
+ <string notr="true">treeView</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Table View" icon="widgets/table.png">
+ <ui>
+ <widget class="QTableView">
+ <property name="objectName">
+ <string notr="true">tableView</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Column View" icon="widgets/columnview.png">
+ <ui>
+ <widget class="QColumnView">
+ <property name="objectName">
+ <string notr="true">columnView</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+
+ <category name="Item Widgets (Item-Based)">
+ <categoryentry name="List Widget" icon="widgets/listbox.png">
+ <ui>
+ <widget class="QListWidget">
+ <property name="objectName">
+ <string notr="true">listWidget</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Tree Widget" icon="widgets/listview.png">
+ <ui>
+ <widget class="QTreeWidget">
+ <property name="objectName">
+ <string notr="true">treeWidget</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Table Widget" icon="widgets/table.png">
+ <ui>
+ <widget class="QTableWidget">
+ <property name="objectName">
+ <string notr="true">tableWidget</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+
+ <category name="Containers">
+
+ <categoryentry name="Group Box" icon="widgets/groupbox.png">
+ <ui>
+ <widget class="QGroupBox">
+ <property name="title" >
+ <string>GroupBox</string>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>120</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">groupBox</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry icon="widgets/scrollarea.png" type="default" name="Scroll Area">
+ <ui>
+ <widget class="QScrollArea">
+ <property name="objectName" >
+ <string notr="true" >scrollArea</string>
+ </property>
+ <property name="widgetResizable" >
+ <bool>true</bool>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>120</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <widget class="QWidget" name="scrollAreaWidgetContents">
+ </widget>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Tool Box" icon="widgets/toolbox.png">
+ <ui>
+ <widget class="QToolBox">
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ <property name="objectName">
+ <string notr="true">toolBox</string>
+ </property>
+ <widget class="QWidget" name="page" >
+ <attribute name="label">
+ <string>Page 1</string>
+ </attribute>
+ </widget>
+ <widget class="QWidget" name="page" >
+ <attribute name="label">
+ <string>Page 2</string>
+ </attribute>
+ </widget>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Tab Widget" icon="widgets/tabwidget.png">
+ <ui>
+ <widget class="QTabWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>120</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">tabWidget</string>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ </widget>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 2</string>
+ </attribute>
+ </widget>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Stacked Widget" icon="widgets/widgetstack.png">
+ <ui>
+ <widget class="QStackedWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>120</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">stackedWidget</string>
+ </property>
+ <widget class="QWidget" name="page" />
+ <widget class="QWidget" name="page" />
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Frame" icon="widgets/frame.png">
+ <ui>
+ <widget class="QFrame">
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>120</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="objectName">
+ <string notr="true">frame</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Widget" icon="widgets/widget.png">
+ <ui>
+ <widget class="QWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>120</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">widget</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="MdiArea" icon="widgets/mdiarea.png">
+ <ui>
+ <widget class="QMdiArea">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>200</width>
+ <height>160</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">mdiArea</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Dock Widget" icon="widgets/dockwidget.png">
+ <ui>
+ <widget class="QDockWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>120</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">dockWidget</string>
+ </property>
+ <widget class="QWidget" name="dockWidgetContents" />
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+
+ <category name="Input Widgets">
+
+ <categoryentry name="Combo Box" icon="widgets/combobox.png">
+ <ui>
+ <widget class="QComboBox">
+ <property name="geometry" >
+ <rect>
+ <x>119</x>
+ <y>28</y>
+ <width>41</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">comboBox</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Font Combo Box" icon="widgets/fontcombobox.png">
+ <ui>
+ <widget class="QFontComboBox">
+ <property name="geometry" >
+ <rect>
+ <x>119</x>
+ <y>28</y>
+ <width>41</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">fontComboBox</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Line Edit" icon="widgets/lineedit.png">
+ <ui>
+ <widget class="QLineEdit">
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>1</y>
+ <width>113</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">lineEdit</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Text Edit" icon="widgets/textedit.png">
+ <ui>
+ <widget class="QTextEdit">
+ <property name="objectName">
+ <string notr="true">textEdit</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>104</width>
+ <height>64</height>
+ </rect>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Plain Text Edit" icon="widgets/plaintextedit.png">
+ <ui>
+ <widget class="QPlainTextEdit">
+ <property name="objectName">
+ <string notr="true">plainTextEdit</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>104</width>
+ <height>64</height>
+ </rect>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Spin Box" icon="widgets/spinbox.png">
+ <ui>
+ <widget class="QSpinBox">
+ <property name="geometry" >
+ <rect>
+ <x>119</x>
+ <y>0</y>
+ <width>42</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">spinBox</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Double Spin Box" icon="widgets/doublespinbox.png">
+ <ui>
+ <widget class="QDoubleSpinBox">
+ <property name="geometry" >
+ <rect>
+ <x>119</x>
+ <y>0</y>
+ <width>62</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">doubleSpinBox</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Time Edit" icon="widgets/timeedit.png">
+ <ui>
+ <widget class="QTimeEdit">
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>28</y>
+ <width>118</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">timeEdit</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Date Edit" icon="widgets/dateedit.png">
+ <ui>
+ <widget class="QDateEdit">
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>28</y>
+ <width>110</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">dateEdit</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Date/Time Edit" icon="widgets/datetimeedit.png">
+ <ui>
+ <widget class="QDateTimeEdit">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>28</y>
+ <width>194</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">dateTimeEdit</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Dial" icon="widgets/dial.png">
+ <ui>
+ <widget class="QDial">
+ <property name="geometry" >
+ <rect>
+ <x>110</x>
+ <y>0</y>
+ <width>50</width>
+ <height>64</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">dial</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Horizontal Scroll Bar" icon="widgets/hscrollbar.png">
+ <ui>
+ <widget class="QScrollBar">
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>126</y>
+ <width>160</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">horizontalScrollBar</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Vertical Scroll Bar" icon="widgets/vscrollbar.png">
+ <ui>
+ <widget class="QScrollBar">
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>126</y>
+ <width>16</width>
+ <height>160</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">verticalScrollBar</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Horizontal Slider" icon="widgets/hslider.png">
+ <ui>
+ <widget class="QSlider">
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>126</y>
+ <width>160</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">horizontalSlider</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Vertical Slider" icon="widgets/vslider.png">
+ <ui>
+ <widget class="QSlider">
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>126</y>
+ <width>16</width>
+ <height>160</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">verticalSlider</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+
+
+ <category name="Display Widgets">
+
+ <categoryentry name="Label" icon="widgets/label.png">
+ <ui>
+ <widget class="QLabel">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ <property name="objectName">
+ <string notr="true">label</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Text Browser" icon="widgets/textedit.png">
+ <ui>
+ <widget class="QTextBrowser">
+ <property name="objectName">
+ <string notr="true">textBrowser</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Graphics View" icon="widgets/graphicsview.png">
+ <ui>
+ <widget class="QGraphicsView">
+ <property name="objectName">
+ <string notr="true">graphicsView</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Calendar" icon="widgets/calendarwidget.png">
+ <ui>
+ <widget class="QCalendarWidget">
+ <property name="objectName">
+ <string notr="true">calendarWidget</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="LCD Number" icon="widgets/lcdnumber.png">
+ <ui>
+ <widget class="QLCDNumber">
+ <property name="objectName">
+ <string notr="true">lcdNumber</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Progress Bar" icon="widgets/progress.png">
+ <ui>
+ <widget class="QProgressBar">
+ <property name="value" >
+ <number>24</number>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>9</x>
+ <y>38</y>
+ <width>118</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">progressBar</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Horizontal Line" icon="widgets/line.png">
+ <ui>
+ <widget class="Line">
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="objectName">
+ <string notr="true">line</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>9</x>
+ <y>67</y>
+ <width>118</width>
+ <height>3</height>
+ </rect>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Vertical Line" icon="widgets/vline.png">
+ <ui>
+ <widget class="Line">
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="objectName">
+ <string notr="true">line</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>133</x>
+ <y>9</y>
+ <width>3</width>
+ <height>61</height>
+ </rect>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+</widgetbox>
diff --git a/tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp b/tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp
new file mode 100644
index 0000000..1dc63a5
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "widgetbox_dnditem.h"
+#include "ui4_p.h"
+
+#include <widgetfactory_p.h>
+#include <spacer_widget_p.h>
+#include <qdesigner_formbuilder_p.h>
+#include <qtresourcemodel_p.h>
+#include <formscriptrunner_p.h>
+#include <formwindowbase_p.h>
+#include <qdesigner_utils_p.h>
+#include <qdesigner_dockwidget_p.h>
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+
+#include <QtGui/QStyle>
+#include <QtGui/QApplication>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+/*******************************************************************************
+** WidgetBoxResource
+*/
+
+static inline DeviceProfile currentDeviceProfile(const QDesignerFormEditorInterface *core)
+{
+ if (QDesignerFormWindowInterface *cfw = core->formWindowManager()->activeFormWindow())
+ if (const FormWindowBase *fwb = qobject_cast<const FormWindowBase *>(cfw))
+ return fwb->deviceProfile();
+ return DeviceProfile();
+}
+
+class WidgetBoxResource : public QDesignerFormBuilder
+{
+public:
+ WidgetBoxResource(QDesignerFormEditorInterface *core);
+
+ // protected->public
+ QWidget *createUI(DomUI *ui, QWidget *parents) { return QDesignerFormBuilder::create(ui, parents); }
+
+protected:
+
+ virtual QWidget *create(DomWidget *ui_widget, QWidget *parents);
+ virtual QWidget *createWidget(const QString &widgetName, QWidget *parentWidget, const QString &name);
+};
+
+WidgetBoxResource::WidgetBoxResource(QDesignerFormEditorInterface *core) :
+ QDesignerFormBuilder(core, DisableScripts, currentDeviceProfile(core))
+{
+}
+
+
+QWidget *WidgetBoxResource::createWidget(const QString &widgetName, QWidget *parentWidget, const QString &name)
+{
+ if (widgetName == QLatin1String("Spacer")) {
+ Spacer *spacer = new Spacer(parentWidget);
+ spacer->setObjectName(name);
+ return spacer;
+ }
+
+ return QDesignerFormBuilder::createWidget(widgetName, parentWidget, name);
+}
+
+QWidget *WidgetBoxResource::create(DomWidget *ui_widget, QWidget *parent)
+{
+ QWidget *result = QDesignerFormBuilder::create(ui_widget, parent);
+ // It is possible to have a syntax error or something in custom
+ // widget XML, so, try to recover here by creating an artificial
+ // top level + widget.
+ if (!result) {
+ const QString msg = QApplication::translate("qdesigner_internal::WidgetBox", "Warning: Widget creation failed in the widget box. This could be caused by invalid custom widget XML.");
+ qdesigner_internal::designerWarning(msg);
+ result = new QWidget(parent);
+ new QWidget(result);
+ }
+ result->setFocusPolicy(Qt::NoFocus);
+ result->setObjectName(ui_widget->attributeName());
+ return result;
+}
+
+/*******************************************************************************
+** WidgetBoxResource
+*/
+
+static QSize geometryProp(const DomWidget *dw)
+{
+ const QList<DomProperty*> prop_list = dw->elementProperty();
+ const QString geometry = QLatin1String("geometry");
+ foreach (DomProperty *prop, prop_list) {
+ if (prop->attributeName() != geometry)
+ continue;
+ DomRect *dr = prop->elementRect();
+ if (dr == 0)
+ continue;
+ return QSize(dr->elementWidth(), dr->elementHeight());
+ }
+ return QSize();
+}
+
+static QSize domWidgetSize(const DomWidget *dw)
+{
+ QSize size = geometryProp(dw);
+ if (size.isValid())
+ return size;
+
+ foreach (const DomWidget *child, dw->elementWidget()) {
+ size = geometryProp(child);
+ if (size.isValid())
+ return size;
+ }
+
+ foreach (const DomLayout *dl, dw->elementLayout()) {
+ foreach (DomLayoutItem *item, dl->elementItem()) {
+ const DomWidget *child = item->elementWidget();
+ if (child == 0)
+ continue;
+ size = geometryProp(child);
+ if (size.isValid())
+ return size;
+ }
+ }
+
+ return QSize();
+}
+
+static QWidget *decorationFromDomWidget(DomUI *dom_ui, QDesignerFormEditorInterface *core)
+{
+ WidgetBoxResource builder(core);
+ // We have the builder create the articial QWidget fake top level as a tooltip
+ // because the size algorithm works better at weird DPI settings
+ // if the actual widget is created as a child of a container
+ QWidget *fakeTopLevel = builder.createUI(dom_ui, static_cast<QWidget*>(0));
+ fakeTopLevel->setParent(0, Qt::ToolTip); // Container
+ // Actual widget
+ const DomWidget *domW = dom_ui->elementWidget()->elementWidget().front();
+ QWidget *w = qFindChildren<QWidget*>(fakeTopLevel).front();
+ Q_ASSERT(w);
+ // hack begin;
+ // We set _q_dockDrag dynamic property which will be detected in drag enter event of form window.
+ // Dock drop is handled in special way (highlight goes to central widget of main window)
+ if (qobject_cast<QDesignerDockWidget *>(w))
+ fakeTopLevel->setProperty("_q_dockDrag", QVariant(true));
+ // hack end;
+ w->setAutoFillBackground(true); // Different style for embedded
+ QSize size = domWidgetSize(domW);
+ const QSize minimumSize = w->minimumSizeHint();
+ if (!size.isValid())
+ size = w->sizeHint();
+ if (size.width() < minimumSize.width())
+ size.setWidth(minimumSize.width());
+ if (size.height() < minimumSize.height())
+ size.setHeight(minimumSize.height());
+ // A QWidget might have size -1,-1 if no geometry property is specified in the widget box.
+ if (size.isEmpty())
+ size = size.expandedTo(QSize(16, 16));
+ w->setGeometry(QRect(QPoint(0, 0), size));
+ fakeTopLevel->resize(size);
+ return fakeTopLevel;
+}
+
+WidgetBoxDnDItem::WidgetBoxDnDItem(QDesignerFormEditorInterface *core,
+ DomUI *dom_ui,
+ const QPoint &global_mouse_pos) :
+ QDesignerDnDItem(CopyDrop)
+{
+ QWidget *decoration = decorationFromDomWidget(dom_ui, core);
+ decoration->move(global_mouse_pos - QPoint(5, 5));
+
+ init(dom_ui, 0, decoration, global_mouse_pos);
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/widgetbox/widgetbox_dnditem.h b/tools/designer/src/components/widgetbox/widgetbox_dnditem.h
new file mode 100644
index 0000000..0641f69
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox_dnditem.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WIDGETBOX_DNDITEM_H
+#define WIDGETBOX_DNDITEM_H
+
+#include <qdesigner_dnditem_p.h>
+#include "widgetbox_global.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class DomUI;
+
+namespace qdesigner_internal {
+
+class QT_WIDGETBOX_EXPORT WidgetBoxDnDItem : public QDesignerDnDItem
+{
+public:
+ WidgetBoxDnDItem(QDesignerFormEditorInterface *core,
+ DomUI *dom_ui,
+ const QPoint &global_mouse_pos);
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // WIDGETBOX_DNDITEM_H
diff --git a/tools/designer/src/components/widgetbox/widgetbox_global.h b/tools/designer/src/components/widgetbox/widgetbox_global.h
new file mode 100644
index 0000000..3e95063
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox_global.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WIDGETBOX_GLOBAL_H
+#define WIDGETBOX_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#ifdef Q_OS_WIN
+#ifdef QT_WIDGETBOX_LIBRARY
+# define QT_WIDGETBOX_EXPORT
+#else
+# define QT_WIDGETBOX_EXPORT
+#endif
+#else
+#define QT_WIDGETBOX_EXPORT
+#endif
+
+#endif // WIDGETBOX_GLOBAL_H
diff --git a/tools/designer/src/components/widgetbox/widgetboxcategorylistview.cpp b/tools/designer/src/components/widgetbox/widgetboxcategorylistview.cpp
new file mode 100644
index 0000000..fad13f2
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetboxcategorylistview.cpp
@@ -0,0 +1,494 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "widgetboxcategorylistview.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+
+#include <QtXml/QDomDocument>
+
+#include <QtGui/QIcon>
+#include <QtGui/QListView>
+#include <QtGui/QLineEdit>
+#include <QtGui/QItemDelegate>
+#include <QtGui/QSortFilterProxyModel>
+
+#include <QtCore/QAbstractListModel>
+#include <QtCore/QList>
+#include <QtCore/QTextStream>
+#include <QtCore/QRegExp>
+
+static const char *widgetElementC = "widget";
+static const char *nameAttributeC = "name";
+static const char *uiOpeningTagC = "<ui>";
+static const char *uiClosingTagC = "</ui>";
+
+QT_BEGIN_NAMESPACE
+
+enum { FilterRole = Qt::UserRole + 11 };
+
+static QString domToString(const QDomElement &elt)
+{
+ QString result;
+ QTextStream stream(&result, QIODevice::WriteOnly);
+ elt.save(stream, 2);
+ stream.flush();
+ return result;
+}
+
+static QDomDocument stringToDom(const QString &xml)
+{
+ QDomDocument result;
+ result.setContent(xml);
+ return result;
+}
+
+namespace qdesigner_internal {
+
+// Entry of the model list
+
+struct WidgetBoxCategoryEntry {
+ WidgetBoxCategoryEntry();
+ explicit WidgetBoxCategoryEntry(const QDesignerWidgetBoxInterface::Widget &widget, const QIcon &icon, bool editable);
+
+ QDesignerWidgetBoxInterface::Widget widget;
+ QString toolTip;
+ QString whatsThis;
+ QIcon icon;
+ bool editable;
+};
+
+
+WidgetBoxCategoryEntry::WidgetBoxCategoryEntry() :
+ editable(false)
+{
+}
+
+WidgetBoxCategoryEntry::WidgetBoxCategoryEntry(const QDesignerWidgetBoxInterface::Widget &w, const QIcon &i, bool e) :
+ widget(w),
+ icon(i),
+ editable(e)
+{
+}
+
+/* WidgetBoxCategoryModel, representing a list of category entries. Uses a
+ * QAbstractListModel since the behaviour depends on the view mode of the list
+ * view, it does not return text in the case of IconMode. */
+
+class WidgetBoxCategoryModel : public QAbstractListModel {
+public:
+ explicit WidgetBoxCategoryModel(QDesignerFormEditorInterface *core, QObject *parent = 0);
+
+ // QAbstractListModel
+ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ virtual bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);
+ virtual Qt::ItemFlags flags (const QModelIndex & index ) const;
+ virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
+
+ // The model returns no text in icon mode, so, it also needs to know it
+ QListView::ViewMode viewMode() const;
+ void setViewMode(QListView::ViewMode vm);
+
+ void addWidget(const QDesignerWidgetBoxInterface::Widget &widget, const QIcon &icon, bool editable);
+
+ QDesignerWidgetBoxInterface::Widget widgetAt(const QModelIndex & index) const;
+ QDesignerWidgetBoxInterface::Widget widgetAt(int row) const;
+
+ int indexOfWidget(const QString &name);
+
+ QDesignerWidgetBoxInterface::Category category() const;
+ bool removeCustomWidgets();
+
+private:
+ typedef QList<WidgetBoxCategoryEntry> WidgetBoxCategoryEntrys;
+
+ QDesignerFormEditorInterface *m_core;
+ WidgetBoxCategoryEntrys m_items;
+ QListView::ViewMode m_viewMode;
+};
+
+WidgetBoxCategoryModel::WidgetBoxCategoryModel(QDesignerFormEditorInterface *core, QObject *parent) :
+ QAbstractListModel(parent),
+ m_core(core),
+ m_viewMode(QListView::ListMode)
+{
+}
+
+QListView::ViewMode WidgetBoxCategoryModel::viewMode() const
+{
+ return m_viewMode;
+}
+
+void WidgetBoxCategoryModel::setViewMode(QListView::ViewMode vm)
+{
+ if (m_viewMode == vm)
+ return;
+ m_viewMode = vm;
+ if (!m_items.empty())
+ reset();
+}
+
+int WidgetBoxCategoryModel::indexOfWidget(const QString &name)
+{
+ const int count = m_items.size();
+ for (int i = 0; i < count; i++)
+ if (m_items.at(i).widget.name() == name)
+ return i;
+ return -1;
+}
+
+QDesignerWidgetBoxInterface::Category WidgetBoxCategoryModel::category() const
+{
+ QDesignerWidgetBoxInterface::Category rc;
+ const WidgetBoxCategoryEntrys::const_iterator cend = m_items.constEnd();
+ for (WidgetBoxCategoryEntrys::const_iterator it = m_items.constBegin(); it != cend; ++it)
+ rc.addWidget(it->widget);
+ return rc;
+}
+
+bool WidgetBoxCategoryModel::removeCustomWidgets()
+{
+ // Typically, we are a whole category of custom widgets, so, remove all
+ // and do reset.
+ bool changed = false;
+ for (WidgetBoxCategoryEntrys::iterator it = m_items.begin(); it != m_items.end(); )
+ if (it->widget.type() == QDesignerWidgetBoxInterface::Widget::Custom) {
+ it = m_items.erase(it);
+ changed = true;
+ } else {
+ ++it;
+ }
+ if (changed)
+ reset();
+ return changed;
+}
+
+void WidgetBoxCategoryModel::addWidget(const QDesignerWidgetBoxInterface::Widget &widget, const QIcon &icon,bool editable)
+{
+ // build item
+ WidgetBoxCategoryEntry item(widget, icon, editable);
+ const QDesignerWidgetDataBaseInterface *db = m_core->widgetDataBase();
+ const int dbIndex = db->indexOfClassName(widget.name());
+ if (dbIndex != -1) {
+ const QDesignerWidgetDataBaseItemInterface *dbItem = db->item(dbIndex);
+ const QString toolTip = dbItem->toolTip();
+ if (!toolTip.isEmpty())
+ item.toolTip = toolTip;
+ const QString whatsThis = dbItem->whatsThis();
+ if (!whatsThis.isEmpty())
+ item.whatsThis = whatsThis;
+ }
+ // insert
+ const int row = m_items.size();
+ beginInsertRows(QModelIndex(), row, row);
+ m_items.push_back(item);
+ endInsertRows();
+}
+
+QVariant WidgetBoxCategoryModel::data(const QModelIndex &index, int role) const
+{
+ const int row = index.row();
+ if (row < 0 || row >= m_items.size())
+ return QVariant();
+
+ const WidgetBoxCategoryEntry &item = m_items.at(row);
+ switch (role) {
+ case Qt::DisplayRole:
+ // No text in icon mode
+ return QVariant(m_viewMode == QListView::ListMode ? item.widget.name() : QString());
+ case Qt::DecorationRole:
+ return QVariant(item.icon);
+ case Qt::EditRole:
+ return QVariant(item.widget.name());
+ case Qt::ToolTipRole: {
+ if (m_viewMode == QListView::ListMode)
+ return QVariant(item.toolTip);
+ // Icon mode tooltip should contain the class name
+ QString tt = item.widget.name();
+ if (!item.toolTip.isEmpty()) {
+ tt += QLatin1Char('\n');
+ tt += item.toolTip;
+ }
+ return QVariant(tt);
+
+ }
+ case Qt::WhatsThisRole:
+ return QVariant(item.whatsThis);
+ case FilterRole:
+ return item.widget.name();
+ }
+ return QVariant();
+}
+
+bool WidgetBoxCategoryModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ const int row = index.row();
+ if (role != Qt::EditRole || row < 0 || row >= m_items.size() || value.type() != QVariant::String)
+ return false;
+ // Set name and adapt Xml
+ WidgetBoxCategoryEntry &item = m_items[row];
+ const QString newName = value.toString();
+ item.widget.setName(newName);
+
+ const QDomDocument doc = stringToDom(WidgetBoxCategoryListView::widgetDomXml(item.widget));
+ QDomElement widget_elt = doc.firstChildElement(QLatin1String(widgetElementC));
+ if (!widget_elt.isNull()) {
+ widget_elt.setAttribute(QLatin1String(nameAttributeC), newName);
+ item.widget.setDomXml(domToString(widget_elt));
+ }
+ emit dataChanged(index, index);
+ return true;
+}
+
+Qt::ItemFlags WidgetBoxCategoryModel::flags(const QModelIndex &index) const
+{
+ Qt::ItemFlags rc = Qt::ItemIsEnabled;
+ const int row = index.row();
+ if (row >= 0 && row < m_items.size())
+ if (m_items.at(row).editable) {
+ rc |= Qt::ItemIsSelectable;
+ // Can change name in list mode only
+ if (m_viewMode == QListView::ListMode)
+ rc |= Qt::ItemIsEditable;
+ }
+ return rc;
+}
+
+int WidgetBoxCategoryModel::rowCount(const QModelIndex & /*parent*/) const
+{
+ return m_items.size();
+}
+
+bool WidgetBoxCategoryModel::removeRows(int row, int count, const QModelIndex & parent)
+{
+ if (row < 0 || count < 1)
+ return false;
+ const int size = m_items.size();
+ const int last = row + count - 1;
+ if (row >= size || last >= size)
+ return false;
+ beginRemoveRows(parent, row, last);
+ for (int r = last; r >= row; r--)
+ m_items.removeAt(r);
+ endRemoveRows();
+ return true;
+}
+
+QDesignerWidgetBoxInterface::Widget WidgetBoxCategoryModel::widgetAt(const QModelIndex & index) const
+{
+ return widgetAt(index.row());
+}
+
+QDesignerWidgetBoxInterface::Widget WidgetBoxCategoryModel::widgetAt(int row) const
+{
+ if (row < 0 || row >= m_items.size())
+ return QDesignerWidgetBoxInterface::Widget();
+ return m_items.at(row).widget;
+}
+
+/* WidgetSubBoxItemDelegate, ensures a valid name using a regexp validator */
+
+class WidgetBoxCategoryEntryDelegate : public QItemDelegate
+{
+public:
+ explicit WidgetBoxCategoryEntryDelegate(QWidget *parent = 0) : QItemDelegate(parent) {}
+ QWidget *createEditor(QWidget *parent,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+};
+
+QWidget *WidgetBoxCategoryEntryDelegate::createEditor(QWidget *parent,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ QWidget *result = QItemDelegate::createEditor(parent, option, index);
+ if (QLineEdit *line_edit = qobject_cast<QLineEdit*>(result)) {
+ const QRegExp re = QRegExp(QLatin1String("[_a-zA-Z][_a-zA-Z0-9]*"));
+ Q_ASSERT(re.isValid());
+ line_edit->setValidator(new QRegExpValidator(re, line_edit));
+ }
+ return result;
+}
+
+// ---------------------- WidgetBoxCategoryListView
+
+WidgetBoxCategoryListView::WidgetBoxCategoryListView(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QListView(parent),
+ m_proxyModel(new QSortFilterProxyModel(this)),
+ m_model(new WidgetBoxCategoryModel(core, this))
+{
+ setFocusPolicy(Qt::NoFocus);
+ setFrameShape(QFrame::NoFrame);
+ setIconSize(QSize(22, 22));
+ setSpacing(1);
+ setTextElideMode(Qt::ElideMiddle);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setResizeMode(QListView::Adjust);
+ setUniformItemSizes(true);
+
+ setItemDelegate(new WidgetBoxCategoryEntryDelegate(this));
+
+ connect(this, SIGNAL(pressed(QModelIndex)), this, SLOT(slotPressed(QModelIndex)));
+ setEditTriggers(QAbstractItemView::AnyKeyPressed);
+
+ m_proxyModel->setSourceModel(m_model);
+ m_proxyModel->setFilterRole(FilterRole);
+ setModel(m_proxyModel);
+ connect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SIGNAL(scratchPadChanged()));
+}
+
+void WidgetBoxCategoryListView::setViewMode(ViewMode vm)
+{
+ QListView::setViewMode(vm);
+ m_model->setViewMode(vm);
+}
+
+void WidgetBoxCategoryListView::setCurrentItem(AccessMode am, int row)
+{
+ const QModelIndex index = am == FilteredAccess ?
+ m_proxyModel->index(row, 0) :
+ m_proxyModel->mapFromSource(m_model->index(row, 0));
+
+ if (index.isValid())
+ setCurrentIndex(index);
+}
+
+void WidgetBoxCategoryListView::slotPressed(const QModelIndex &index)
+{
+ const QDesignerWidgetBoxInterface::Widget wgt = m_model->widgetAt(m_proxyModel->mapToSource(index));
+ if (wgt.isNull())
+ return;
+ emit pressed(wgt.name(), widgetDomXml(wgt), QCursor::pos());
+}
+
+void WidgetBoxCategoryListView::removeCurrentItem()
+{
+ const QModelIndex index = currentIndex();
+ if (!index.isValid() || !m_proxyModel->removeRow(index.row()))
+ return;
+
+ // We check the unfiltered item count here, we don't want to get removed if the
+ // filtered view is empty
+ if (m_model->rowCount()) {
+ emit itemRemoved();
+ } else {
+ emit lastItemRemoved();
+ }
+}
+
+void WidgetBoxCategoryListView::editCurrentItem()
+{
+ const QModelIndex index = currentIndex();
+ if (index.isValid())
+ edit(index);
+}
+
+int WidgetBoxCategoryListView::count(AccessMode am) const
+{
+ return am == FilteredAccess ? m_proxyModel->rowCount() : m_model->rowCount();
+}
+
+int WidgetBoxCategoryListView::mapRowToSource(int filterRow) const
+{
+ const QModelIndex filterIndex = m_proxyModel->index(filterRow, 0);
+ return m_proxyModel->mapToSource(filterIndex).row();
+}
+
+QDesignerWidgetBoxInterface::Widget WidgetBoxCategoryListView::widgetAt(AccessMode am, const QModelIndex & index) const
+{
+ const QModelIndex unfilteredIndex = am == FilteredAccess ? m_proxyModel->mapToSource(index) : index;
+ return m_model->widgetAt(unfilteredIndex);
+}
+
+QDesignerWidgetBoxInterface::Widget WidgetBoxCategoryListView::widgetAt(AccessMode am, int row) const
+{
+ return m_model->widgetAt(am == UnfilteredAccess ? row : mapRowToSource(row));
+}
+
+void WidgetBoxCategoryListView::removeRow(AccessMode am, int row)
+{
+ m_model->removeRow(am == UnfilteredAccess ? row : mapRowToSource(row));
+}
+
+bool WidgetBoxCategoryListView::containsWidget(const QString &name)
+{
+ return m_model->indexOfWidget(name) != -1;
+}
+
+void WidgetBoxCategoryListView::addWidget(const QDesignerWidgetBoxInterface::Widget &widget, const QIcon &icon, bool editable)
+{
+ m_model->addWidget(widget, icon, editable);
+}
+
+QString WidgetBoxCategoryListView::widgetDomXml(const QDesignerWidgetBoxInterface::Widget &widget)
+{
+ QString domXml = widget.domXml();
+
+ if (domXml.isEmpty()) {
+ domXml = QLatin1String(uiOpeningTagC);
+ domXml += QLatin1String("<widget class=\"");
+ domXml += widget.name();
+ domXml += QLatin1String("\"/>");
+ domXml += QLatin1String(uiClosingTagC);
+ }
+ return domXml;
+}
+
+void WidgetBoxCategoryListView::filter(const QRegExp &re)
+{
+ m_proxyModel->setFilterRegExp(re);
+}
+
+QDesignerWidgetBoxInterface::Category WidgetBoxCategoryListView::category() const
+{
+ return m_model->category();
+}
+
+bool WidgetBoxCategoryListView::removeCustomWidgets()
+{
+ return m_model->removeCustomWidgets();
+}
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/widgetbox/widgetboxcategorylistview.h b/tools/designer/src/components/widgetbox/widgetboxcategorylistview.h
new file mode 100644
index 0000000..c8c5d3a
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetboxcategorylistview.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WIDGETBOXCATEGORYLISTVIEW_H
+#define WIDGETBOXCATEGORYLISTVIEW_H
+
+#include <QtDesigner/QDesignerWidgetBoxInterface>
+
+#include <QtGui/QListView>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerDnDItemInterface;
+
+class QSortFilterProxyModel;
+class QRegExp;
+
+namespace qdesigner_internal {
+
+class WidgetBoxCategoryModel;
+
+// List view of a category, switchable between icon and list mode.
+// Provides a filtered view.
+class WidgetBoxCategoryListView : public QListView
+{
+ Q_OBJECT
+public:
+ // Whether to access the filtered or unfiltered view
+ enum AccessMode { FilteredAccess, UnfilteredAccess };
+
+ explicit WidgetBoxCategoryListView(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+ void setViewMode(ViewMode vm);
+
+ void dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list);
+
+ using QListView::contentsSize;
+
+ // These methods operate on the filtered/unfiltered model according to accessmode
+ int count(AccessMode am) const;
+ QDesignerWidgetBoxInterface::Widget widgetAt(AccessMode am, const QModelIndex &index) const;
+ QDesignerWidgetBoxInterface::Widget widgetAt(AccessMode am, int row) const;
+ void removeRow(AccessMode am, int row);
+ void setCurrentItem(AccessMode am, int row);
+
+ // These methods operate on the unfiltered model and are used for serialization
+ void addWidget(const QDesignerWidgetBoxInterface::Widget &widget, const QIcon &icon, bool editable);
+ bool containsWidget(const QString &name);
+ QDesignerWidgetBoxInterface::Category category() const;
+ bool removeCustomWidgets();
+
+ // Helper: Ensure a <ui> tag in the case of empty XML
+ static QString widgetDomXml(const QDesignerWidgetBoxInterface::Widget &widget);
+
+signals:
+ void scratchPadChanged();
+ void pressed(const QString &name, const QString &xml, const QPoint &globalPos);
+ void itemRemoved();
+ void lastItemRemoved();
+
+public slots:
+ void filter(const QRegExp &re);
+
+private slots:
+ void slotPressed(const QModelIndex &index);
+ void removeCurrentItem();
+ void editCurrentItem();
+
+private:
+ int mapRowToSource(int filterRow) const;
+ QSortFilterProxyModel *m_proxyModel;
+ WidgetBoxCategoryModel *m_model;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // WIDGETBOXCATEGORYLISTVIEW_H
diff --git a/tools/designer/src/components/widgetbox/widgetboxtreewidget.cpp b/tools/designer/src/components/widgetbox/widgetboxtreewidget.cpp
new file mode 100644
index 0000000..799f96f
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetboxtreewidget.cpp
@@ -0,0 +1,998 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "widgetboxtreewidget.h"
+#include "widgetboxcategorylistview.h"
+
+// shared
+#include <iconloader_p.h>
+#include <sheet_delegate_p.h>
+#include <QtDesigner/private/abstractsettings_p.h>
+#include <ui4_p.h>
+#include <qdesigner_utils_p.h>
+#include <pluginmanager_p.h>
+
+// sdk
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerDnDItemInterface>
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+#include <QtDesigner/private/abstractsettings_p.h>
+
+#include <QtGui/QHeaderView>
+#include <QtGui/QApplication>
+#include <QtGui/QTreeWidgetItem>
+#include <QtGui/QContextMenuEvent>
+#include <QtGui/QAction>
+#include <QtGui/QActionGroup>
+#include <QtGui/QMenu>
+
+#include <QtCore/QFile>
+#include <QtCore/QTimer>
+#include <QtCore/QDebug>
+
+static const char *widgetBoxRootElementC = "widgetbox";
+static const char *widgetElementC = "widget";
+static const char *uiElementC = "ui";
+static const char *categoryElementC = "category";
+static const char *categoryEntryElementC = "categoryentry";
+static const char *nameAttributeC = "name";
+static const char *typeAttributeC = "type";
+static const char *iconAttributeC = "icon";
+static const char *defaultTypeValueC = "default";
+static const char *customValueC = "custom";
+static const char *iconPrefixC = "__qt_icon__";
+static const char *scratchPadValueC = "scratchpad";
+static const char *qtLogoC = "qtlogo.png";
+static const char *invisibleNameC = "[invisible]";
+
+enum TopLevelRole { NORMAL_ITEM, SCRATCHPAD_ITEM, CUSTOM_ITEM };
+
+QT_BEGIN_NAMESPACE
+
+static void setTopLevelRole(TopLevelRole tlr, QTreeWidgetItem *item)
+{
+ item->setData(0, Qt::UserRole, QVariant(tlr));
+}
+
+static TopLevelRole topLevelRole(const QTreeWidgetItem *item)
+{
+ return static_cast<TopLevelRole>(item->data(0, Qt::UserRole).toInt());
+}
+
+namespace qdesigner_internal {
+
+WidgetBoxTreeWidget::WidgetBoxTreeWidget(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QTreeWidget(parent),
+ m_core(core),
+ m_iconMode(false),
+ m_scratchPadDeleteTimer(0)
+{
+ setFocusPolicy(Qt::NoFocus);
+ setIndentation(0);
+ setRootIsDecorated(false);
+ setColumnCount(1);
+ header()->hide();
+ header()->setResizeMode(QHeaderView::Stretch);
+ setTextElideMode(Qt::ElideMiddle);
+ setVerticalScrollMode(ScrollPerPixel);
+
+ setItemDelegate(new SheetDelegate(this, this));
+
+ connect(this, SIGNAL(itemPressed(QTreeWidgetItem*,int)),
+ this, SLOT(handleMousePress(QTreeWidgetItem*)));
+}
+
+QIcon WidgetBoxTreeWidget::iconForWidget(QString iconName) const
+{
+ if (iconName.isEmpty())
+ iconName = QLatin1String(qtLogoC);
+
+ if (iconName.startsWith(QLatin1String(iconPrefixC))) {
+ const IconCache::const_iterator it = m_pluginIcons.constFind(iconName);
+ if (it != m_pluginIcons.constEnd())
+ return it.value();
+ }
+ return createIconSet(iconName);
+}
+
+WidgetBoxCategoryListView *WidgetBoxTreeWidget::categoryViewAt(int idx) const
+{
+ WidgetBoxCategoryListView *rc = 0;
+ if (QTreeWidgetItem *cat_item = topLevelItem(idx))
+ if (QTreeWidgetItem *embedItem = cat_item->child(0))
+ rc = qobject_cast<WidgetBoxCategoryListView*>(itemWidget(embedItem, 0));
+ Q_ASSERT(rc);
+ return rc;
+}
+
+void WidgetBoxTreeWidget::saveExpandedState() const
+{
+ QStringList closedCategories;
+ if (const int numCategories = categoryCount()) {
+ for (int i = 0; i < numCategories; ++i) {
+ const QTreeWidgetItem *cat_item = topLevelItem(i);
+ if (!isItemExpanded(cat_item))
+ closedCategories.append(cat_item->text(0));
+ }
+ }
+ QDesignerSettingsInterface *settings = m_core->settingsManager();
+ settings->beginGroup(QLatin1String(widgetBoxRootElementC));
+ settings->setValue(QLatin1String("Closed categories"), closedCategories);
+ settings->setValue(QLatin1String("View mode"), m_iconMode);
+ settings->endGroup();
+}
+
+void WidgetBoxTreeWidget::restoreExpandedState()
+{
+ typedef QSet<QString> StringSet;
+ QDesignerSettingsInterface *settings = m_core->settingsManager();
+ m_iconMode = settings->value(QLatin1String("WidgetBox/View mode")).toBool();
+ updateViewMode();
+ const StringSet closedCategories = settings->value(QLatin1String("WidgetBox/Closed categories"), QStringList()).toStringList().toSet();
+ expandAll();
+ if (closedCategories.empty())
+ return;
+
+ if (const int numCategories = categoryCount()) {
+ for (int i = 0; i < numCategories; ++i) {
+ QTreeWidgetItem *item = topLevelItem(i);
+ if (closedCategories.contains(item->text(0)))
+ item->setExpanded(false);
+ }
+ }
+}
+
+WidgetBoxTreeWidget::~WidgetBoxTreeWidget()
+{
+ saveExpandedState();
+}
+
+void WidgetBoxTreeWidget::setFileName(const QString &file_name)
+{
+ m_file_name = file_name;
+}
+
+QString WidgetBoxTreeWidget::fileName() const
+{
+ return m_file_name;
+}
+
+bool WidgetBoxTreeWidget::save()
+{
+ if (fileName().isEmpty())
+ return false;
+
+ QFile file(fileName());
+ if (!file.open(QIODevice::WriteOnly))
+ return false;
+
+ CategoryList cat_list;
+ const int count = categoryCount();
+ for (int i = 0; i < count; ++i)
+ cat_list.append(category(i));
+
+ QXmlStreamWriter writer(&file);
+ writer.setAutoFormatting(true);
+ writer.setAutoFormattingIndent(1);
+ writer.writeStartDocument();
+ writeCategories(writer, cat_list);
+ writer.writeEndDocument();
+
+ return true;
+}
+
+void WidgetBoxTreeWidget::slotSave()
+{
+ save();
+}
+
+void WidgetBoxTreeWidget::handleMousePress(QTreeWidgetItem *item)
+{
+ if (item == 0)
+ return;
+
+ if (QApplication::mouseButtons() != Qt::LeftButton)
+ return;
+
+ if (item->parent() == 0) {
+ setItemExpanded(item, !isItemExpanded(item));
+ return;
+ }
+}
+
+int WidgetBoxTreeWidget::ensureScratchpad()
+{
+ const int existingIndex = indexOfScratchpad();
+ if (existingIndex != -1)
+ return existingIndex;
+
+ QTreeWidgetItem *scratch_item = new QTreeWidgetItem(this);
+ scratch_item->setText(0, tr("Scratchpad"));
+ setTopLevelRole(SCRATCHPAD_ITEM, scratch_item);
+ addCategoryView(scratch_item, false); // Scratchpad in list mode.
+ return categoryCount() - 1;
+}
+
+WidgetBoxCategoryListView *WidgetBoxTreeWidget::addCategoryView(QTreeWidgetItem *parent, bool iconMode)
+{
+ QTreeWidgetItem *embed_item = new QTreeWidgetItem(parent);
+ embed_item->setFlags(Qt::ItemIsEnabled);
+ WidgetBoxCategoryListView *categoryView = new WidgetBoxCategoryListView(m_core, this);
+ categoryView->setViewMode(iconMode ? QListView::IconMode : QListView::ListMode);
+ connect(categoryView, SIGNAL(scratchPadChanged()), this, SLOT(slotSave()));
+ connect(categoryView, SIGNAL(pressed(QString,QString,QPoint)), this, SIGNAL(pressed(QString,QString,QPoint)));
+ connect(categoryView, SIGNAL(itemRemoved()), this, SLOT(slotScratchPadItemDeleted()));
+ connect(categoryView, SIGNAL(lastItemRemoved()), this, SLOT(slotLastScratchPadItemDeleted()));
+ setItemWidget(embed_item, 0, categoryView);
+ return categoryView;
+}
+
+int WidgetBoxTreeWidget::indexOfScratchpad() const
+{
+ if (const int numTopLevels = topLevelItemCount()) {
+ for (int i = numTopLevels - 1; i >= 0; --i) {
+ if (topLevelRole(topLevelItem(i)) == SCRATCHPAD_ITEM)
+ return i;
+ }
+ }
+ return -1;
+}
+
+int WidgetBoxTreeWidget::indexOfCategory(const QString &name) const
+{
+ const int topLevelCount = topLevelItemCount();
+ for (int i = 0; i < topLevelCount; ++i) {
+ if (topLevelItem(i)->text(0) == name)
+ return i;
+ }
+ return -1;
+}
+
+bool WidgetBoxTreeWidget::load(QDesignerWidgetBox::LoadMode loadMode)
+{
+ switch (loadMode) {
+ case QDesignerWidgetBox::LoadReplace:
+ clear();
+ break;
+ case QDesignerWidgetBox::LoadCustomWidgetsOnly:
+ addCustomCategories(true);
+ updateGeometries();
+ return true;
+ default:
+ break;
+ }
+
+ const QString name = fileName();
+
+ QFile f(name);
+ if (!f.open(QIODevice::ReadOnly)) // Might not exist at first startup
+ return false;
+
+ const QString contents = QString::fromUtf8(f.readAll());
+ return loadContents(contents);
+}
+
+bool WidgetBoxTreeWidget::loadContents(const QString &contents)
+{
+ QString errorMessage;
+ CategoryList cat_list;
+ if (!readCategories(m_file_name, contents, &cat_list, &errorMessage)) {
+ qdesigner_internal::designerWarning(errorMessage);
+ return false;
+ }
+
+ foreach(const Category &cat, cat_list)
+ addCategory(cat);
+
+ addCustomCategories(false);
+ // Restore which items are expanded
+ restoreExpandedState();
+ return true;
+}
+
+void WidgetBoxTreeWidget::addCustomCategories(bool replace)
+{
+ if (replace) {
+ // clear out all existing custom widgets
+ if (const int numTopLevels = topLevelItemCount()) {
+ for (int t = 0; t < numTopLevels ; ++t)
+ categoryViewAt(t)->removeCustomWidgets();
+ }
+ }
+ // re-add
+ const CategoryList customList = loadCustomCategoryList();
+ const CategoryList::const_iterator cend = customList.constEnd();
+ for (CategoryList::const_iterator it = customList.constBegin(); it != cend; ++it)
+ addCategory(*it);
+}
+
+static inline QString msgXmlError(const QString &fileName, const QXmlStreamReader &r)
+{
+ return QDesignerWidgetBox::tr("An error has been encountered at line %1 of %2: %3")
+ .arg(r.lineNumber()).arg(fileName, r.errorString());
+}
+
+bool WidgetBoxTreeWidget::readCategories(const QString &fileName, const QString &contents,
+ CategoryList *cats, QString *errorMessage)
+{
+ // Read widget box XML:
+ //
+ //<widgetbox version="4.5">
+ // <category name="Layouts">
+ // <categoryentry name="Vertical Layout" icon="win/editvlayout.png" type="default">
+ // <widget class="QListWidget" ...>
+ // ...
+
+ QXmlStreamReader reader(contents);
+
+
+ // Entries of category with name="invisible" should be ignored
+ bool ignoreEntries = false;
+
+ while (!reader.atEnd()) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement: {
+ const QStringRef tag = reader.name();
+ if (tag == QLatin1String(widgetBoxRootElementC)) {
+ //<widgetbox version="4.5">
+ continue;
+ }
+ if (tag == QLatin1String(categoryElementC)) {
+ // <category name="Layouts">
+ const QXmlStreamAttributes attributes = reader.attributes();
+ const QString categoryName = attributes.value(QLatin1String(nameAttributeC)).toString();
+ if (categoryName == QLatin1String(invisibleNameC)) {
+ ignoreEntries = true;
+ } else {
+ Category category(categoryName);
+ if (attributes.value(QLatin1String(typeAttributeC)) == QLatin1String(scratchPadValueC))
+ category.setType(Category::Scratchpad);
+ cats->push_back(category);
+ }
+ continue;
+ }
+ if (tag == QLatin1String(categoryEntryElementC)) {
+ // <categoryentry name="Vertical Layout" icon="win/editvlayout.png" type="default">
+ if (!ignoreEntries) {
+ QXmlStreamAttributes attr = reader.attributes();
+ const QString widgetName = attr.value(QLatin1String(nameAttributeC)).toString();
+ const QString widgetIcon = attr.value(QLatin1String(iconAttributeC)).toString();
+ const WidgetBoxTreeWidget::Widget::Type widgetType =
+ attr.value(QLatin1String(typeAttributeC)).toString()
+ == QLatin1String(customValueC) ?
+ WidgetBoxTreeWidget::Widget::Custom :
+ WidgetBoxTreeWidget::Widget::Default;
+
+ Widget w;
+ w.setName(widgetName);
+ w.setIconName(widgetIcon);
+ w.setType(widgetType);
+ if (!readWidget(&w, contents, reader))
+ continue;
+
+ cats->back().addWidget(w);
+ } // ignoreEntries
+ continue;
+ }
+ break;
+ }
+ case QXmlStreamReader::EndElement: {
+ const QStringRef tag = reader.name();
+ if (tag == QLatin1String(widgetBoxRootElementC)) {
+ continue;
+ }
+ if (tag == QLatin1String(categoryElementC)) {
+ ignoreEntries = false;
+ continue;
+ }
+ if (tag == QLatin1String(categoryEntryElementC)) {
+ continue;
+ }
+ break;
+ }
+ default: break;
+ }
+ }
+
+ if (reader.hasError()) {
+ *errorMessage = msgXmlError(fileName, reader);
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ * Read out a widget within a category. This can either be
+ * enclosed in a <ui> element or a (legacy) <widget> element which may
+ * contain nested <widget> elements.
+ *
+ * Examples:
+ *
+ * <ui language="c++">
+ * <widget class="MultiPageWidget" name="multipagewidget"> ... </widget>
+ * <customwidgets>...</customwidgets>
+ * <ui>
+ *
+ * or
+ *
+ * <widget>
+ * <widget> ... </widget>
+ * ...
+ * <widget>
+ *
+ * Returns true on success, false if end was reached or an error has been encountered
+ * in which case the reader has its error flag set. If successful, the current item
+ * of the reader will be the closing element (</ui> or </widget>)
+ */
+bool WidgetBoxTreeWidget::readWidget(Widget *w, const QString &xml, QXmlStreamReader &r)
+{
+ qint64 startTagPosition =0, endTagPosition = 0;
+
+ int nesting = 0;
+ bool endEncountered = false;
+ bool parsedWidgetTag = false;
+ QString outmostElement;
+ while (!endEncountered) {
+ const qint64 currentPosition = r.characterOffset();
+ switch(r.readNext()) {
+ case QXmlStreamReader::StartElement:
+ if (nesting++ == 0) {
+ // First element must be <ui> or (legacy) <widget>
+ const QStringRef name = r.name();
+ if (name == QLatin1String(uiElementC)) {
+ startTagPosition = currentPosition;
+ } else {
+ if (name == QLatin1String(widgetElementC)) {
+ startTagPosition = currentPosition;
+ parsedWidgetTag = true;
+ } else {
+ r.raiseError(QDesignerWidgetBox::tr("Unexpected element <%1> encountered when parsing for <widget> or <ui>").arg(name.toString()));
+ return false;
+ }
+ }
+ } else {
+ // We are within <ui> looking for the first <widget> tag
+ if (!parsedWidgetTag && r.name() == QLatin1String(widgetElementC)) {
+ parsedWidgetTag = true;
+ }
+ }
+ break;
+ case QXmlStreamReader::EndElement:
+ // Reached end of widget?
+ if (--nesting == 0) {
+ endTagPosition = r.characterOffset();
+ endEncountered = true;
+ }
+ break;
+ case QXmlStreamReader::EndDocument:
+ r.raiseError(QDesignerWidgetBox::tr("Unexpected end of file encountered when parsing widgets."));
+ return false;
+ case QXmlStreamReader::Invalid:
+ return false;
+ default:
+ break;
+ }
+ }
+ if (!parsedWidgetTag) {
+ r.raiseError(QDesignerWidgetBox::tr("A widget element could not be found."));
+ return false;
+ }
+ // Oddity: Startposition is 1 off
+ QString widgetXml = xml.mid(startTagPosition, endTagPosition - startTagPosition);
+ const QChar lessThan = QLatin1Char('<');
+ if (!widgetXml.startsWith(lessThan))
+ widgetXml.prepend(lessThan);
+ w->setDomXml(widgetXml);
+ return true;
+}
+
+void WidgetBoxTreeWidget::writeCategories(QXmlStreamWriter &writer, const CategoryList &cat_list) const
+{
+ const QString widgetbox = QLatin1String(widgetBoxRootElementC);
+ const QString name = QLatin1String(nameAttributeC);
+ const QString type = QLatin1String(typeAttributeC);
+ const QString icon = QLatin1String(iconAttributeC);
+ const QString defaultType = QLatin1String(defaultTypeValueC);
+ const QString category = QLatin1String(categoryElementC);
+ const QString categoryEntry = QLatin1String(categoryEntryElementC);
+ const QString iconPrefix = QLatin1String(iconPrefixC);
+ const QString widgetTag = QLatin1String(widgetElementC);
+
+ //
+ // <widgetbox>
+ // <category name="Layouts">
+ // <categoryEntry name="Vertical Layout" type="default" icon="win/editvlayout.png">
+ // <ui>
+ // ...
+ // </ui>
+ // </categoryEntry>
+ // ...
+ // </category>
+ // ...
+ // </widgetbox>
+ //
+
+ writer.writeStartElement(widgetbox);
+
+ foreach (const Category &cat, cat_list) {
+ writer.writeStartElement(category);
+ writer.writeAttribute(name, cat.name());
+ if (cat.type() == Category::Scratchpad)
+ writer.writeAttribute(type, QLatin1String(scratchPadValueC));
+
+ const int widgetCount = cat.widgetCount();
+ for (int i = 0; i < widgetCount; ++i) {
+ const Widget wgt = cat.widget(i);
+ if (wgt.type() == Widget::Custom)
+ continue;
+
+ writer.writeStartElement(categoryEntry);
+ writer.writeAttribute(name, wgt.name());
+ if (!wgt.iconName().startsWith(iconPrefix))
+ writer.writeAttribute(icon, wgt.iconName());
+ writer.writeAttribute(type, defaultType);
+
+ const DomUI *domUI = QDesignerWidgetBox::xmlToUi(wgt.name(), WidgetBoxCategoryListView::widgetDomXml(wgt), false);
+ if (domUI) {
+ domUI->write(writer);
+ delete domUI;
+ }
+
+ writer.writeEndElement(); // categoryEntry
+ }
+ writer.writeEndElement(); // categoryEntry
+ }
+
+ writer.writeEndElement(); // widgetBox
+}
+
+static int findCategory(const QString &name, const WidgetBoxTreeWidget::CategoryList &list)
+{
+ int idx = 0;
+ foreach (const WidgetBoxTreeWidget::Category &cat, list) {
+ if (cat.name() == name)
+ return idx;
+ ++idx;
+ }
+ return -1;
+}
+
+static inline bool isValidIcon(const QIcon &icon)
+{
+ if (!icon.isNull()) {
+ const QList<QSize> availableSizes = icon.availableSizes();
+ if (!availableSizes.empty())
+ return !availableSizes.front().isEmpty();
+ }
+ return false;
+}
+
+WidgetBoxTreeWidget::CategoryList WidgetBoxTreeWidget::loadCustomCategoryList() const
+{
+ CategoryList result;
+
+ const QDesignerPluginManager *pm = m_core->pluginManager();
+ const QDesignerPluginManager::CustomWidgetList customWidgets = pm->registeredCustomWidgets();
+ if (customWidgets.empty())
+ return result;
+
+ static const QString customCatName = tr("Custom Widgets");
+
+ const QString invisible = QLatin1String(invisibleNameC);
+ const QString iconPrefix = QLatin1String(iconPrefixC);
+
+ foreach(QDesignerCustomWidgetInterface *c, customWidgets) {
+ const QString dom_xml = c->domXml();
+ if (dom_xml.isEmpty())
+ continue;
+
+ const QString pluginName = c->name();
+ const QDesignerCustomWidgetData data = pm->customWidgetData(c);
+ QString displayName = data.xmlDisplayName();
+ if (displayName.isEmpty())
+ displayName = pluginName;
+
+ QString cat_name = c->group();
+ if (cat_name.isEmpty())
+ cat_name = customCatName;
+ else if (cat_name == invisible)
+ continue;
+
+ int idx = findCategory(cat_name, result);
+ if (idx == -1) {
+ result.append(Category(cat_name));
+ idx = result.size() - 1;
+ }
+ Category &cat = result[idx];
+
+ const QIcon icon = c->icon();
+
+ QString icon_name;
+ if (isValidIcon(icon)) {
+ icon_name = iconPrefix;
+ icon_name += pluginName;
+ m_pluginIcons.insert(icon_name, icon);
+ } else {
+ icon_name = QLatin1String(qtLogoC);
+ }
+
+ cat.addWidget(Widget(displayName, dom_xml, icon_name, Widget::Custom));
+ }
+
+ return result;
+}
+
+void WidgetBoxTreeWidget::adjustSubListSize(QTreeWidgetItem *cat_item)
+{
+ QTreeWidgetItem *embedItem = cat_item->child(0);
+ WidgetBoxCategoryListView *list_widget = static_cast<WidgetBoxCategoryListView*>(itemWidget(embedItem, 0));
+ list_widget->setFixedWidth(header()->width());
+ list_widget->doItemsLayout();
+ const int height = qMax(list_widget->contentsSize().height() ,1);
+ list_widget->setFixedHeight(height);
+ embedItem->setSizeHint(0, QSize(-1, height - 1));
+}
+
+int WidgetBoxTreeWidget::categoryCount() const
+{
+ return topLevelItemCount();
+}
+
+WidgetBoxTreeWidget::Category WidgetBoxTreeWidget::category(int cat_idx) const
+{
+ if (cat_idx >= topLevelItemCount())
+ return Category();
+
+ QTreeWidgetItem *cat_item = topLevelItem(cat_idx);
+
+ QTreeWidgetItem *embedItem = cat_item->child(0);
+ WidgetBoxCategoryListView *categoryView = static_cast<WidgetBoxCategoryListView*>(itemWidget(embedItem, 0));
+
+ Category result = categoryView->category();
+ result.setName(cat_item->text(0));
+
+ switch (topLevelRole(cat_item)) {
+ case SCRATCHPAD_ITEM:
+ result.setType(Category::Scratchpad);
+ break;
+ default:
+ result.setType(Category::Default);
+ break;
+ }
+ return result;
+}
+
+void WidgetBoxTreeWidget::addCategory(const Category &cat)
+{
+ if (cat.widgetCount() == 0)
+ return;
+
+ const bool isScratchPad = cat.type() == Category::Scratchpad;
+ WidgetBoxCategoryListView *categoryView;
+ QTreeWidgetItem *cat_item;
+
+ if (isScratchPad) {
+ const int idx = ensureScratchpad();
+ categoryView = categoryViewAt(idx);
+ cat_item = topLevelItem(idx);
+ } else {
+ const int existingIndex = indexOfCategory(cat.name());
+ if (existingIndex == -1) {
+ cat_item = new QTreeWidgetItem();
+ cat_item->setText(0, cat.name());
+ setTopLevelRole(NORMAL_ITEM, cat_item);
+ // insert before scratchpad
+ const int scratchPadIndex = indexOfScratchpad();
+ if (scratchPadIndex == -1) {
+ addTopLevelItem(cat_item);
+ } else {
+ insertTopLevelItem(scratchPadIndex, cat_item);
+ }
+ setItemExpanded(cat_item, true);
+ categoryView = addCategoryView(cat_item, m_iconMode);
+ } else {
+ categoryView = categoryViewAt(existingIndex);
+ cat_item = topLevelItem(existingIndex);
+ }
+ }
+ // The same categories are read from the file $HOME, avoid duplicates
+ const int widgetCount = cat.widgetCount();
+ for (int i = 0; i < widgetCount; ++i) {
+ const Widget w = cat.widget(i);
+ if (!categoryView->containsWidget(w.name()))
+ categoryView->addWidget(w, iconForWidget(w.iconName()), isScratchPad);
+ }
+ adjustSubListSize(cat_item);
+}
+
+void WidgetBoxTreeWidget::removeCategory(int cat_idx)
+{
+ if (cat_idx >= topLevelItemCount())
+ return;
+ delete takeTopLevelItem(cat_idx);
+}
+
+int WidgetBoxTreeWidget::widgetCount(int cat_idx) const
+{
+ if (cat_idx >= topLevelItemCount())
+ return 0;
+ // SDK functions want unfiltered access
+ return categoryViewAt(cat_idx)->count(WidgetBoxCategoryListView::UnfilteredAccess);
+}
+
+WidgetBoxTreeWidget::Widget WidgetBoxTreeWidget::widget(int cat_idx, int wgt_idx) const
+{
+ if (cat_idx >= topLevelItemCount())
+ return Widget();
+ // SDK functions want unfiltered access
+ WidgetBoxCategoryListView *categoryView = categoryViewAt(cat_idx);
+ return categoryView->widgetAt(WidgetBoxCategoryListView::UnfilteredAccess, wgt_idx);
+}
+
+void WidgetBoxTreeWidget::addWidget(int cat_idx, const Widget &wgt)
+{
+ if (cat_idx >= topLevelItemCount())
+ return;
+
+ QTreeWidgetItem *cat_item = topLevelItem(cat_idx);
+ WidgetBoxCategoryListView *categoryView = categoryViewAt(cat_idx);
+
+ const bool scratch = topLevelRole(cat_item) == SCRATCHPAD_ITEM;
+ categoryView->addWidget(wgt, iconForWidget(wgt.iconName()), scratch);
+ adjustSubListSize(cat_item);
+}
+
+void WidgetBoxTreeWidget::removeWidget(int cat_idx, int wgt_idx)
+{
+ if (cat_idx >= topLevelItemCount())
+ return;
+
+ WidgetBoxCategoryListView *categoryView = categoryViewAt(cat_idx);
+
+ // SDK functions want unfiltered access
+ const WidgetBoxCategoryListView::AccessMode am = WidgetBoxCategoryListView::UnfilteredAccess;
+ if (wgt_idx >= categoryView->count(am))
+ return;
+
+ categoryView->removeRow(am, wgt_idx);
+}
+
+void WidgetBoxTreeWidget::slotScratchPadItemDeleted()
+{
+ const int scratch_idx = indexOfScratchpad();
+ QTreeWidgetItem *scratch_item = topLevelItem(scratch_idx);
+ adjustSubListSize(scratch_item);
+ save();
+}
+
+void WidgetBoxTreeWidget::slotLastScratchPadItemDeleted()
+{
+ // Remove the scratchpad in the next idle loop
+ if (!m_scratchPadDeleteTimer) {
+ m_scratchPadDeleteTimer = new QTimer(this);
+ m_scratchPadDeleteTimer->setSingleShot(true);
+ m_scratchPadDeleteTimer->setInterval(0);
+ connect(m_scratchPadDeleteTimer, SIGNAL(timeout()), this, SLOT(deleteScratchpad()));
+ }
+ if (!m_scratchPadDeleteTimer->isActive())
+ m_scratchPadDeleteTimer->start();
+}
+
+void WidgetBoxTreeWidget::deleteScratchpad()
+{
+ const int idx = indexOfScratchpad();
+ if (idx == -1)
+ return;
+ delete takeTopLevelItem(idx);
+ save();
+}
+
+
+void WidgetBoxTreeWidget::slotListMode()
+{
+ m_iconMode = false;
+ updateViewMode();
+}
+
+void WidgetBoxTreeWidget::slotIconMode()
+{
+ m_iconMode = true;
+ updateViewMode();
+}
+
+void WidgetBoxTreeWidget::updateViewMode()
+{
+ if (const int numTopLevels = topLevelItemCount()) {
+ for (int i = numTopLevels - 1; i >= 0; --i) {
+ QTreeWidgetItem *topLevel = topLevelItem(i);
+ // Scratch pad stays in list mode.
+ const QListView::ViewMode viewMode = m_iconMode && (topLevelRole(topLevel) != SCRATCHPAD_ITEM) ? QListView::IconMode : QListView::ListMode;
+ WidgetBoxCategoryListView *categoryView = categoryViewAt(i);
+ if (viewMode != categoryView->viewMode()) {
+ categoryView->setViewMode(viewMode);
+ adjustSubListSize(topLevelItem(i));
+ }
+ }
+ }
+
+ updateGeometries();
+}
+
+void WidgetBoxTreeWidget::resizeEvent(QResizeEvent *e)
+{
+ QTreeWidget::resizeEvent(e);
+ if (const int numTopLevels = topLevelItemCount()) {
+ for (int i = numTopLevels - 1; i >= 0; --i)
+ adjustSubListSize(topLevelItem(i));
+ }
+}
+
+void WidgetBoxTreeWidget::contextMenuEvent(QContextMenuEvent *e)
+{
+ QTreeWidgetItem *item = itemAt(e->pos());
+
+ const bool scratchpad_menu = item != 0
+ && item->parent() != 0
+ && topLevelRole(item->parent()) == SCRATCHPAD_ITEM;
+
+ QMenu menu;
+ menu.addAction(tr("Expand all"), this, SLOT(expandAll()));
+ menu.addAction(tr("Collapse all"), this, SLOT(collapseAll()));
+ menu.addSeparator();
+
+ QAction *listModeAction = menu.addAction(tr("List View"));
+ QAction *iconModeAction = menu.addAction(tr("Icon View"));
+ listModeAction->setCheckable(true);
+ iconModeAction->setCheckable(true);
+ QActionGroup *viewModeGroup = new QActionGroup(&menu);
+ viewModeGroup->addAction(listModeAction);
+ viewModeGroup->addAction(iconModeAction);
+ if (m_iconMode)
+ iconModeAction->setChecked(true);
+ else
+ listModeAction->setChecked(true);
+ connect(listModeAction, SIGNAL(triggered()), SLOT(slotListMode()));
+ connect(iconModeAction, SIGNAL(triggered()), SLOT(slotIconMode()));
+
+ if (scratchpad_menu) {
+ menu.addSeparator();
+ menu.addAction(tr("Remove"), itemWidget(item, 0), SLOT(removeCurrentItem()));
+ if (!m_iconMode)
+ menu.addAction(tr("Edit name"), itemWidget(item, 0), SLOT(editCurrentItem()));
+ }
+ e->accept();
+ menu.exec(mapToGlobal(e->pos()));
+}
+
+void WidgetBoxTreeWidget::dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list)
+{
+ QTreeWidgetItem *scratch_item = 0;
+ WidgetBoxCategoryListView *categoryView = 0;
+ bool added = false;
+
+ foreach (QDesignerDnDItemInterface *item, item_list) {
+ QWidget *w = item->widget();
+ if (w == 0)
+ continue;
+
+ DomUI *dom_ui = item->domUi();
+ if (dom_ui == 0)
+ continue;
+
+ const int scratch_idx = ensureScratchpad();
+ scratch_item = topLevelItem(scratch_idx);
+ categoryView = categoryViewAt(scratch_idx);
+
+ // Temporarily remove the fake toplevel in-between
+ DomWidget *fakeTopLevel = dom_ui->takeElementWidget();
+ DomWidget *firstWidget = 0;
+ if (fakeTopLevel && !fakeTopLevel->elementWidget().isEmpty()) {
+ firstWidget = fakeTopLevel->elementWidget().first();
+ dom_ui->setElementWidget(firstWidget);
+ } else {
+ dom_ui->setElementWidget(fakeTopLevel);
+ continue;
+ }
+
+ // Serialize to XML
+ QString xml;
+ {
+ QXmlStreamWriter writer(&xml);
+ writer.setAutoFormatting(true);
+ writer.setAutoFormattingIndent(1);
+ writer.writeStartDocument();
+ dom_ui->write(writer);
+ writer.writeEndDocument();
+ }
+
+ // Insert fake toplevel again
+ dom_ui->takeElementWidget();
+ dom_ui->setElementWidget(fakeTopLevel);
+
+ const Widget wgt = Widget(w->objectName(), xml);
+ categoryView->addWidget(wgt, iconForWidget(wgt.iconName()), true);
+ setItemExpanded(scratch_item, true);
+ added = true;
+ }
+
+ if (added) {
+ save();
+ QApplication::setActiveWindow(this);
+ // Is the new item visible in filtered mode?
+ const WidgetBoxCategoryListView::AccessMode am = WidgetBoxCategoryListView::FilteredAccess;
+ if (const int count = categoryView->count(am))
+ categoryView->setCurrentItem(am, count - 1);
+ categoryView->adjustSize(); // XXX
+ adjustSubListSize(scratch_item);
+ }
+}
+
+void WidgetBoxTreeWidget::filter(const QString &f)
+{
+ const bool empty = f.isEmpty();
+ const QRegExp re = empty ? QRegExp() : QRegExp(f, Qt::CaseInsensitive, QRegExp::FixedString);
+ const int numTopLevels = topLevelItemCount();
+ bool changed = false;
+ for (int i = 0; i < numTopLevels; i++) {
+ QTreeWidgetItem *tl = topLevelItem(i);
+ WidgetBoxCategoryListView *categoryView = categoryViewAt(i);
+ // Anything changed? -> Enable the category
+ const int oldCount = categoryView->count(WidgetBoxCategoryListView::FilteredAccess);
+ categoryView->filter(re);
+ const int newCount = categoryView->count(WidgetBoxCategoryListView::FilteredAccess);
+ if (oldCount != newCount) {
+ changed = true;
+ const bool categoryEnabled = newCount > 0 || empty;
+ if (categoryEnabled) {
+ categoryView->adjustSize();
+ adjustSubListSize(tl);
+ }
+ setRowHidden (i, QModelIndex(), !categoryEnabled);
+ }
+ }
+ if (changed)
+ updateGeometries();
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/widgetbox/widgetboxtreewidget.h b/tools/designer/src/components/widgetbox/widgetboxtreewidget.h
new file mode 100644
index 0000000..9282a0f
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetboxtreewidget.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WIDGETBOXTREEWIDGET_H
+#define WIDGETBOXTREEWIDGET_H
+
+#include <qdesigner_widgetbox_p.h>
+
+#include <QtGui/QTreeWidget>
+#include <QtGui/QIcon>
+#include <QtCore/QList>
+#include <QtCore/QHash>
+#include <QtCore/QXmlStreamReader> // Cannot forward declare them on Mac
+#include <QtCore/QXmlStreamWriter>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerDnDItemInterface;
+
+class QTimer;
+
+namespace qdesigner_internal {
+
+class WidgetBoxCategoryListView;
+
+// WidgetBoxTreeWidget: A tree of categories
+
+class WidgetBoxTreeWidget : public QTreeWidget
+{
+ Q_OBJECT
+
+public:
+ typedef QDesignerWidgetBoxInterface::Widget Widget;
+ typedef QDesignerWidgetBoxInterface::Category Category;
+ typedef QDesignerWidgetBoxInterface::CategoryList CategoryList;
+
+ explicit WidgetBoxTreeWidget(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+ ~WidgetBoxTreeWidget();
+
+ int categoryCount() const;
+ Category category(int cat_idx) const;
+ void addCategory(const Category &cat);
+ void removeCategory(int cat_idx);
+
+ int widgetCount(int cat_idx) const;
+ Widget widget(int cat_idx, int wgt_idx) const;
+ void addWidget(int cat_idx, const Widget &wgt);
+ void removeWidget(int cat_idx, int wgt_idx);
+
+ void dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list);
+
+ void setFileName(const QString &file_name);
+ QString fileName() const;
+ bool load(QDesignerWidgetBox::LoadMode loadMode);
+ bool loadContents(const QString &contents);
+ bool save();
+ QIcon iconForWidget(QString iconName) const;
+
+signals:
+ void pressed(const QString name, const QString dom_xml, const QPoint &global_mouse_pos);
+
+public slots:
+ void filter(const QString &);
+
+protected:
+ void contextMenuEvent(QContextMenuEvent *e);
+ void resizeEvent(QResizeEvent *e);
+
+private slots:
+ void slotSave();
+ void slotScratchPadItemDeleted();
+ void slotLastScratchPadItemDeleted();
+
+ void handleMousePress(QTreeWidgetItem *item);
+ void deleteScratchpad();
+ void slotListMode();
+ void slotIconMode();
+
+private:
+ WidgetBoxCategoryListView *addCategoryView(QTreeWidgetItem *parent, bool iconMode);
+ WidgetBoxCategoryListView *categoryViewAt(int idx) const;
+ void adjustSubListSize(QTreeWidgetItem *cat_item);
+
+ static bool readCategories(const QString &fileName, const QString &xml, CategoryList *cats, QString *errorMessage);
+ static bool readWidget(Widget *w, const QString &xml, QXmlStreamReader &r);
+
+ CategoryList loadCustomCategoryList() const;
+ void writeCategories(QXmlStreamWriter &writer, const CategoryList &cat_list) const;
+
+ int indexOfCategory(const QString &name) const;
+ int indexOfScratchpad() const;
+ int ensureScratchpad();
+ void addCustomCategories(bool replace);
+
+ void saveExpandedState() const;
+ void restoreExpandedState();
+ void updateViewMode();
+
+ QDesignerFormEditorInterface *m_core;
+ QString m_file_name;
+ typedef QHash<QString, QIcon> IconCache;
+ mutable IconCache m_pluginIcons;
+ bool m_iconMode;
+ QTimer *m_scratchPadDeleteTimer;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // WIDGETBOXTREEWIDGET_H