From 44ce228a6a5b397c80cffbc12bf54db8c9856e8b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint <Friedemann.Kleint@nokia.com> Date: Tue, 13 Apr 2010 16:13:06 +0200 Subject: [PATCH] Polish the Qt Designer custom widget wizard Start editing the class name when wizard page is initialized. Show a disabled widget page for the dummy widget item (least surprise). Add +/- buttons. Refuse invalid class names (by introducing an item model with setData() validation. Code polishing, explicitness, etc. Task-number: QTCREATORBUG-1123 --- .../customwidgetwizard/classdefinition.cpp | 91 +++++------ .../customwidgetwizard/classdefinition.h | 9 +- .../customwidgetwizard/classlist.cpp | 145 ++++++++++++++---- .../customwidgetwizard/classlist.h | 30 ++-- .../customwidgetpluginwizardpage.h | 4 +- .../customwidgetwidgetswizardpage.cpp | 49 ++++-- .../customwidgetwidgetswizardpage.h | 6 +- .../customwidgetwidgetswizardpage.ui | 40 +++-- 8 files changed, 265 insertions(+), 109 deletions(-) diff --git a/src/plugins/qt4projectmanager/customwidgetwizard/classdefinition.cpp b/src/plugins/qt4projectmanager/customwidgetwizard/classdefinition.cpp index 19ffe40f2cd..968a5237179 100644 --- a/src/plugins/qt4projectmanager/customwidgetwizard/classdefinition.cpp +++ b/src/plugins/qt4projectmanager/customwidgetwizard/classdefinition.cpp @@ -39,30 +39,35 @@ ClassDefinition::ClassDefinition(QWidget *parent) : QTabWidget(parent), m_domXmlChanged(false) { - setupUi(this); - iconPathChooser->setExpectedKind(Utils::PathChooser::File); - iconPathChooser->setPromptDialogTitle(tr("Select Icon")); - iconPathChooser->setPromptDialogFilter(tr("Icon files (*.png *.ico *.jpg *.xpm *.tif *.svg)")); + m_ui.setupUi(this); + m_ui.iconPathChooser->setExpectedKind(Utils::PathChooser::File); + m_ui.iconPathChooser->setPromptDialogTitle(tr("Select Icon")); + m_ui.iconPathChooser->setPromptDialogFilter(tr("Icon files (*.png *.ico *.jpg *.xpm *.tif *.svg)")); +} + +void ClassDefinition::enableButtons() +{ + on_libraryRadio_toggled(); } void ClassDefinition::on_libraryRadio_toggled() { - const bool enLib = libraryRadio->isChecked(); - widgetLibraryLabel->setEnabled(enLib); - widgetLibraryEdit->setEnabled(enLib); + const bool enLib = m_ui.libraryRadio->isChecked(); + m_ui.widgetLibraryLabel->setEnabled(enLib); + m_ui.widgetLibraryEdit->setEnabled(enLib); - const bool enSrc = skeletonCheck->isChecked(); - widgetSourceLabel->setEnabled(enSrc); - widgetSourceEdit->setEnabled(enSrc); - widgetBaseClassLabel->setEnabled(enSrc); - widgetBaseClassEdit->setEnabled(enSrc); + const bool enSrc = m_ui.skeletonCheck->isChecked(); + m_ui.widgetSourceLabel->setEnabled(enSrc); + m_ui.widgetSourceEdit->setEnabled(enSrc); + m_ui.widgetBaseClassLabel->setEnabled(enSrc); + m_ui.widgetBaseClassEdit->setEnabled(enSrc); const bool enPrj = !enLib || enSrc; - widgetProjectLabel->setEnabled(enPrj); - widgetProjectEdit->setEnabled(enPrj); - widgetProjectEdit->setText( - QFileInfo(widgetProjectEdit->text()).completeBaseName() + - (libraryRadio->isChecked() ? QLatin1String(".pro") : QLatin1String(".pri"))); + m_ui.widgetProjectLabel->setEnabled(enPrj); + m_ui.widgetProjectEdit->setEnabled(enPrj); + m_ui.widgetProjectEdit->setText( + QFileInfo(m_ui.widgetProjectEdit->text()).completeBaseName() + + (m_ui.libraryRadio->isChecked() ? QLatin1String(".pro") : QLatin1String(".pri"))); } void ClassDefinition::on_skeletonCheck_toggled() @@ -86,35 +91,35 @@ static inline QString xmlFromClassName(const QString &name) void ClassDefinition::setClassName(const QString &name) { - widgetLibraryEdit->setText(name.toLower()); - widgetHeaderEdit->setText(m_fileNamingParameters.headerFileName(name)); - pluginClassEdit->setText(name + QLatin1String("Plugin")); + m_ui.widgetLibraryEdit->setText(name.toLower()); + m_ui.widgetHeaderEdit->setText(m_fileNamingParameters.headerFileName(name)); + m_ui.pluginClassEdit->setText(name + QLatin1String("Plugin")); if (!m_domXmlChanged) { - domXmlEdit->setText(xmlFromClassName(name)); + m_ui.domXmlEdit->setText(xmlFromClassName(name)); m_domXmlChanged = false; } } void ClassDefinition::on_widgetLibraryEdit_textChanged() { - widgetProjectEdit->setText( - widgetLibraryEdit->text() + - (libraryRadio->isChecked() ? QLatin1String(".pro") : QLatin1String(".pri"))); + m_ui.widgetProjectEdit->setText( + m_ui.widgetLibraryEdit->text() + + (m_ui.libraryRadio->isChecked() ? QLatin1String(".pro") : QLatin1String(".pri"))); } void ClassDefinition::on_widgetHeaderEdit_textChanged() { - widgetSourceEdit->setText(m_fileNamingParameters.headerToSourceFileName(widgetHeaderEdit->text())); + m_ui.widgetSourceEdit->setText(m_fileNamingParameters.headerToSourceFileName(m_ui.widgetHeaderEdit->text())); } void ClassDefinition::on_pluginClassEdit_textChanged() { - pluginHeaderEdit->setText(m_fileNamingParameters.headerFileName(pluginClassEdit->text())); + m_ui.pluginHeaderEdit->setText(m_fileNamingParameters.headerFileName(m_ui.pluginClassEdit->text())); } void ClassDefinition::on_pluginHeaderEdit_textChanged() { - pluginSourceEdit->setText(m_fileNamingParameters.headerToSourceFileName(pluginHeaderEdit->text())); + m_ui.pluginSourceEdit->setText(m_fileNamingParameters.headerToSourceFileName(m_ui.pluginHeaderEdit->text())); } void ClassDefinition::on_domXmlEdit_textChanged() @@ -125,26 +130,26 @@ void ClassDefinition::on_domXmlEdit_textChanged() PluginOptions::WidgetOptions ClassDefinition::widgetOptions(const QString &className) const { PluginOptions::WidgetOptions wo; - wo.createSkeleton = skeletonCheck->isChecked(); + wo.createSkeleton = m_ui.skeletonCheck->isChecked(); wo.sourceType = - libraryRadio->isChecked() ? + m_ui.libraryRadio->isChecked() ? PluginOptions::WidgetOptions::LinkLibrary : PluginOptions::WidgetOptions::IncludeProject; - wo.widgetLibrary = widgetLibraryEdit->text(); - wo.widgetProjectFile = widgetProjectEdit->text(); + wo.widgetLibrary = m_ui.widgetLibraryEdit->text(); + wo.widgetProjectFile = m_ui.widgetProjectEdit->text(); wo.widgetClassName = className; - wo.widgetHeaderFile = widgetHeaderEdit->text(); - wo.widgetSourceFile = widgetSourceEdit->text(); - wo.widgetBaseClassName = widgetBaseClassEdit->text(); - wo.pluginClassName = pluginClassEdit->text(); - wo.pluginHeaderFile = pluginHeaderEdit->text(); - wo.pluginSourceFile = pluginSourceEdit->text(); - wo.iconFile = iconPathChooser->path(); - wo.group = groupEdit->text(); - wo.toolTip = tooltipEdit->text(); - wo.whatsThis = whatsthisEdit->toPlainText(); - wo.isContainer = containerCheck->isChecked(); - wo.domXml = domXmlEdit->toPlainText(); + wo.widgetHeaderFile = m_ui.widgetHeaderEdit->text(); + wo.widgetSourceFile = m_ui.widgetSourceEdit->text(); + wo.widgetBaseClassName = m_ui.widgetBaseClassEdit->text(); + wo.pluginClassName = m_ui.pluginClassEdit->text(); + wo.pluginHeaderFile = m_ui.pluginHeaderEdit->text(); + wo.pluginSourceFile = m_ui.pluginSourceEdit->text(); + wo.iconFile = m_ui.iconPathChooser->path(); + wo.group = m_ui.groupEdit->text(); + wo.toolTip = m_ui.tooltipEdit->text(); + wo.whatsThis = m_ui.whatsthisEdit->toPlainText(); + wo.isContainer = m_ui.containerCheck->isChecked(); + wo.domXml = m_ui.domXmlEdit->toPlainText(); return wo; } diff --git a/src/plugins/qt4projectmanager/customwidgetwizard/classdefinition.h b/src/plugins/qt4projectmanager/customwidgetwizard/classdefinition.h index 6b31c38c813..0cde494a9c8 100644 --- a/src/plugins/qt4projectmanager/customwidgetwizard/classdefinition.h +++ b/src/plugins/qt4projectmanager/customwidgetwizard/classdefinition.h @@ -39,12 +39,12 @@ namespace Qt4ProjectManager { namespace Internal { -class ClassDefinition : public QTabWidget, private Ui::ClassDefinition +class ClassDefinition : public QTabWidget { Q_OBJECT public: - ClassDefinition(QWidget *parent); + explicit ClassDefinition(QWidget *parent = 0); void setClassName(const QString &name); FileNamingParameters fileNamingParameters() const { return m_fileNamingParameters; } @@ -52,7 +52,9 @@ public: PluginOptions::WidgetOptions widgetOptions(const QString &className) const; -public Q_SLOTS: + void enableButtons(); + +private Q_SLOTS: void on_libraryRadio_toggled(); void on_skeletonCheck_toggled(); void on_widgetLibraryEdit_textChanged(); @@ -62,6 +64,7 @@ public Q_SLOTS: void on_domXmlEdit_textChanged(); private: + Ui::ClassDefinition m_ui; FileNamingParameters m_fileNamingParameters; bool m_domXmlChanged; }; diff --git a/src/plugins/qt4projectmanager/customwidgetwizard/classlist.cpp b/src/plugins/qt4projectmanager/customwidgetwizard/classlist.cpp index 99cd58d71de..bf1ebfb8b45 100644 --- a/src/plugins/qt4projectmanager/customwidgetwizard/classlist.cpp +++ b/src/plugins/qt4projectmanager/customwidgetwizard/classlist.cpp @@ -29,59 +29,146 @@ #include "classlist.h" +#include <utils/qtcassert.h> + #include <QtGui/QKeyEvent> #include <QtGui/QMessageBox> +#include <QtGui/QStandardItemModel> +#include <QtGui/QStandardItem> +#include <QtGui/QLabel> +#include <QtGui/QToolButton> + +#include <QtCore/QDebug> +#include <QtCore/QRegExp> namespace Qt4ProjectManager { namespace Internal { +// ClassModel: Validates the class name in setData() and +// refuses placeholders and invalid characters. +class ClassModel : public QStandardItemModel { +public: + explicit ClassModel(QObject *parent = 0); + virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + + void appendPlaceHolder() { appendClass(m_newClassPlaceHolder); } + + QModelIndex placeHolderIndex() const; + QString newClassPlaceHolder() const { return m_newClassPlaceHolder; } + +private: + void appendClass(const QString &); + + const QRegExp m_validator; + const QString m_newClassPlaceHolder; +}; + +ClassModel::ClassModel(QObject *parent) : + QStandardItemModel(0, 1, parent), + m_validator(QLatin1String("^[a-zA-Z][a-zA-Z0-9_]*$")), + m_newClassPlaceHolder(ClassList::tr("<New class>")) +{ + QTC_ASSERT(m_validator.isValid(), return) + appendPlaceHolder(); +} + +void ClassModel::appendClass(const QString &c) +{ + QStandardItem *item = new QStandardItem(c); + item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsEditable); + appendRow(item); +} + +bool ClassModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (role == Qt::EditRole && !m_validator.exactMatch(value.toString())) + return false; + return QStandardItemModel::setData(index, value, role); +} + +QModelIndex ClassModel::placeHolderIndex() const +{ + return index(rowCount() - 1, 0); +} + +// --------------- ClassList ClassList::ClassList(QWidget *parent) : - QListWidget(parent) + QListView(parent), + m_model(new ClassModel) { + setModel(m_model); connect(itemDelegate(), SIGNAL(closeEditor(QWidget *, QAbstractItemDelegate::EndEditHint)), SLOT(classEdited())); - insertNewItem(); + connect(selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), + this, SLOT(slotCurrentRowChanged(QModelIndex,QModelIndex))); +} + +void ClassList::startEditingNewClassItem() +{ + // Start editing the 'new class' item. + setFocus(); + + const QModelIndex index = m_model->placeHolderIndex(); + setCurrentIndex(index); + edit(index); +} + +QString ClassList::className(int row) const +{ + return m_model->item(row, 0)->text(); } void ClassList::classEdited() { - if (currentRow() == count() - 1) { - if (currentItem()->text() != tr("<New class>")) { - emit classAdded(currentItem()->text()); - insertNewItem(); + const QModelIndex index = currentIndex(); + QTC_ASSERT(index.isValid(), return) + + const QString name = className(index.row()); + if (index == m_model->placeHolderIndex()) { + // Real name class entered. + if (name != m_model->newClassPlaceHolder()) { + emit classAdded(name); + m_model->appendPlaceHolder(); } } else { - emit classRenamed(currentRow(), currentItem()->text()); + emit classRenamed(index.row(), name); } } -void ClassList::insertNewItem() +void ClassList::removeCurrentClass() { - QListWidgetItem *itm = new QListWidgetItem(tr("<New class>"), this); - itm->setFlags(Qt::ItemIsEnabled|Qt::ItemIsEditable); + const QModelIndex index = currentIndex(); + if (!index.isValid() || index == m_model->placeHolderIndex()) + return; + if (QMessageBox::question(this, + tr("Confirm Delete"), + tr("Delete class %1 from list?").arg(className(index.row())), + QMessageBox::Ok|QMessageBox::Cancel) != QMessageBox::Ok) + return; + // Delete row and set current on same item. + m_model->removeRows(index.row(), 1); + emit classDeleted(index.row()); + setCurrentIndex(m_model->indexFromItem(m_model->item(index.row(), 0))); } void ClassList::keyPressEvent(QKeyEvent *event) { - if (event->key() == Qt::Key_Delete) { - const int row = currentRow(); - if (row != count() - 1) { - if (QMessageBox::question(this, - tr("Confirm Delete"), - tr("Delete class %1 from list?").arg(currentItem()->text()), - QMessageBox::Ok|QMessageBox::Cancel) == QMessageBox::Ok) - { - delete currentItem(); - emit classDeleted(row); - setCurrentRow(row); - } - } - } else if (event->key() == Qt::Key_Insert) { - setCurrentRow(count() - 1); - editItem(currentItem()); - } else { - QListWidget::keyPressEvent(event); + switch (event->key()) { + case Qt::Key_Delete: + removeCurrentClass(); + break; + case Qt::Key_Insert: + startEditingNewClassItem(); + break; + default: + QListView::keyPressEvent(event); + break; } } +void ClassList::slotCurrentRowChanged(const QModelIndex ¤t, const QModelIndex &) +{ + emit currentRowChanged(current.row()); } -} + +} // namespace Internal +} // namespace Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/customwidgetwizard/classlist.h b/src/plugins/qt4projectmanager/customwidgetwizard/classlist.h index 3fa9ecb4f90..631d07d6d38 100644 --- a/src/plugins/qt4projectmanager/customwidgetwizard/classlist.h +++ b/src/plugins/qt4projectmanager/customwidgetwizard/classlist.h @@ -30,34 +30,46 @@ #ifndef CLASSLIST_H #define CLASSLIST_H -#include <QtGui/QListWidget> +#include <QtGui/QListView> + +QT_FORWARD_DECLARE_CLASS(QModelIndex) namespace Qt4ProjectManager { namespace Internal { +class ClassModel; -class ClassList : public QListWidget +// Class list for new Custom widget classes. Provides +// editable '<new class>' field and Delete/Insert key handling. +class ClassList : public QListView { Q_OBJECT public: - ClassList(QWidget *parent); + explicit ClassList(QWidget *parent = 0); -public slots: - void classEdited(); + QString className(int row) const; signals: void classAdded(const QString &name); void classRenamed(int index, const QString &newName); void classDeleted(int index); + void currentRowChanged(int); + +public slots: + void removeCurrentClass(); + void startEditingNewClassItem(); + +private slots: + void classEdited(); + void slotCurrentRowChanged(const QModelIndex &,const QModelIndex &); protected: void keyPressEvent(QKeyEvent *event); private: - void insertNewItem(); + ClassModel *m_model; }; -} -} - +} // namespace Internal +} // namespace Qt4ProjectManager #endif diff --git a/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetpluginwizardpage.h b/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetpluginwizardpage.h index 59c2300f347..6e06484ba2f 100644 --- a/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetpluginwizardpage.h +++ b/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetpluginwizardpage.h @@ -48,8 +48,8 @@ namespace Ui { class CustomWidgetPluginWizardPage : public QWizardPage { Q_OBJECT public: - CustomWidgetPluginWizardPage(QWidget *parent = 0); - ~CustomWidgetPluginWizardPage(); + explicit CustomWidgetPluginWizardPage(QWidget *parent = 0); + virtual ~CustomWidgetPluginWizardPage(); void init(const CustomWidgetWidgetsWizardPage *widgetsPage); diff --git a/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetwidgetswizardpage.cpp b/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetwidgetswizardpage.cpp index 56ee0eb0489..39322a8e3e1 100644 --- a/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetwidgetswizardpage.cpp +++ b/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetwidgetswizardpage.cpp @@ -32,9 +32,13 @@ #include "plugingenerator.h" #include "classdefinition.h" +#include <coreplugin/coreconstants.h> + #include <QtCore/QFileInfo> +#include <QtCore/QTimer> #include <QtGui/QStackedLayout> +#include <QtGui/QIcon> namespace Qt4ProjectManager { namespace Internal { @@ -42,13 +46,25 @@ namespace Internal { CustomWidgetWidgetsWizardPage::CustomWidgetWidgetsWizardPage(QWidget *parent) : QWizardPage(parent), m_ui(new Ui::CustomWidgetWidgetsWizardPage), + m_tabStackLayout(new QStackedLayout), m_complete(false) { m_ui->setupUi(this); - m_tabStack = new QStackedLayout(m_ui->tabStackWidget); - m_dummyTab = new QWidget(m_ui->tabStackWidget); - m_tabStack->addWidget(m_dummyTab); - connect(m_ui->classList, SIGNAL(currentRowChanged(int)), m_tabStack, SLOT(setCurrentIndex(int))); + m_ui->tabStackWidget->setLayout(m_tabStackLayout); + m_ui->addButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_PLUS))); + connect(m_ui->addButton, SIGNAL(clicked()), m_ui->classList, SLOT(startEditingNewClassItem())); + m_ui->deleteButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_MINUS))); + connect(m_ui->deleteButton, SIGNAL(clicked()), m_ui->classList, SLOT(removeCurrentClass())); + m_ui->deleteButton->setEnabled(false); + + // Disabled dummy for <new class> column>. + ClassDefinition *dummy = new ClassDefinition; + dummy->setFileNamingParameters(m_fileNamingParameters); + dummy->setEnabled(false); + m_tabStackLayout->addWidget(dummy); + + connect(m_ui->classList, SIGNAL(currentRowChanged(int)), + this, SLOT(slotCurrentRowChanged(int))); } CustomWidgetWidgetsWizardPage::~CustomWidgetWidgetsWizardPage() @@ -61,15 +77,28 @@ bool CustomWidgetWidgetsWizardPage::isComplete() const return m_complete; } +void CustomWidgetWidgetsWizardPage::initializePage() +{ + // Takes effect only if visible. + QTimer::singleShot(0, m_ui->classList, SLOT(startEditingNewClassItem())); +} + +void CustomWidgetWidgetsWizardPage::slotCurrentRowChanged(int row) +{ + const bool onDummyItem = row == m_tabStackLayout->count() - 1; + m_ui->deleteButton->setEnabled(!onDummyItem); + m_tabStackLayout->setCurrentIndex(row); +} + void CustomWidgetWidgetsWizardPage::on_classList_classAdded(const QString &name) { - ClassDefinition *cdef = new ClassDefinition(m_ui->tabStackWidget); + ClassDefinition *cdef = new ClassDefinition; cdef->setFileNamingParameters(m_fileNamingParameters); const int index = m_uiClassDefs.count(); - m_tabStack->insertWidget(index, cdef); - m_tabStack->setCurrentIndex(index); + m_tabStackLayout->insertWidget(index, cdef); + m_tabStackLayout->setCurrentIndex(index); m_uiClassDefs.append(cdef); - cdef->on_libraryRadio_toggled(); + cdef->enableButtons(); on_classList_classRenamed(index, name); // First class or collection class, re-check. slotCheckCompleteness(); @@ -77,7 +106,7 @@ void CustomWidgetWidgetsWizardPage::on_classList_classAdded(const QString &name) void CustomWidgetWidgetsWizardPage::on_classList_classDeleted(int index) { - delete m_tabStack->widget(index); + delete m_tabStackLayout->widget(index); m_uiClassDefs.removeAt(index); if (m_uiClassDefs.empty()) slotCheckCompleteness(); @@ -90,7 +119,7 @@ void CustomWidgetWidgetsWizardPage::on_classList_classRenamed(int index, const Q QString CustomWidgetWidgetsWizardPage::classNameAt(int i) const { - return m_ui->classList->item(i)->text(); + return m_ui->classList->className(i); } QList<PluginOptions::WidgetOptions> CustomWidgetWidgetsWizardPage::widgetOptions() const diff --git a/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetwidgetswizardpage.h b/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetwidgetswizardpage.h index 85c4444c0a1..12520bad6d7 100644 --- a/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetwidgetswizardpage.h +++ b/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetwidgetswizardpage.h @@ -68,19 +68,21 @@ public: int classCount() const { return m_uiClassDefs.size(); } QString classNameAt(int i) const; + virtual void initializePage(); + private Q_SLOTS: void on_classList_classAdded(const QString &name); void on_classList_classDeleted(int index); void on_classList_classRenamed(int index, const QString &newName); void slotCheckCompleteness(); + void slotCurrentRowChanged(int); private: void updatePluginTab(); Ui::CustomWidgetWidgetsWizardPage *m_ui; QList<ClassDefinition *> m_uiClassDefs; - QStackedLayout *m_tabStack; - QWidget *m_dummyTab; + QStackedLayout *m_tabStackLayout; FileNamingParameters m_fileNamingParameters; bool m_complete; }; diff --git a/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetwidgetswizardpage.ui b/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetwidgetswizardpage.ui index adf2b942f1c..7f48f5e36a4 100644 --- a/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetwidgetswizardpage.ui +++ b/src/plugins/qt4projectmanager/customwidgetwizard/customwidgetwidgetswizardpage.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>668</width> - <height>454</height> + <height>475</height> </rect> </property> <property name="windowTitle"> @@ -17,16 +17,6 @@ <string>Custom Widget List</string> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="2" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Widget &Classes:</string> - </property> - <property name="buddy"> - <cstring>classList</cstring> - </property> - </widget> - </item> <item row="2" column="1" rowspan="2"> <widget class="QWidget" name="tabStackWidget" native="true"> <property name="minimumSize"> @@ -70,6 +60,34 @@ </property> </spacer> </item> + <item row="2" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Widget &Classes:</string> + </property> + <property name="buddy"> + <cstring>classList</cstring> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="addButton"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="deleteButton"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + </layout> + </item> </layout> </widget> <customwidgets> -- GitLab