52 #include <QtDesigner/QDesignerDnDItemInterface>
53 #include <QtDesigner/QDesignerFormEditorInterface>
55 #if QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
56 #include <QtDesigner/QDesignerCustomWidgetInterface>
58 #include <QtUiPlugin/QDesignerCustomWidgetInterface>
62 #include <QActionGroup>
63 #include <QApplication>
64 #include <QContextMenuEvent>
65 #include <QHeaderView>
67 #include <QTreeWidgetItem>
69 #include <QtCore/QDebug>
70 #include <QtCore/QFile>
71 #include <QtCore/QTimer>
87 static const char*
qtLogoC =
"qtlogo.png";
92 return QIcon(QString::fromUtf8(
":/widgetbox/") +
name);
101 item->setData(0, Qt::UserRole, QVariant(tlr));
106 return static_cast<ETopLevelRole>(item->data(0, Qt::UserRole).toInt());
112 : QTreeWidget(parent), m_core(core), m_iconMode(false), m_scratchPadDeleteTimer(nullptr)
114 setFocusPolicy(Qt::NoFocus);
116 setRootIsDecorated(
false);
119 #if QT_VERSION >= 0x050000
120 header()->setSectionResizeMode(QHeaderView::Stretch);
122 setTextElideMode(Qt::ElideMiddle);
123 setVerticalScrollMode(ScrollPerPixel);
127 connect(
this, SIGNAL(itemPressed(QTreeWidgetItem*,
int)),
this,
133 if (iconName.isEmpty())
134 iconName = QLatin1String(
qtLogoC);
136 if (iconName.startsWith(QLatin1String(
iconPrefixC))) {
137 const IconCache::const_iterator it =
m_pluginIcons.constFind(iconName);
147 if (QTreeWidgetItem* cat_item = topLevelItem(idx))
148 if (QTreeWidgetItem* embedItem = cat_item->child(0))
149 rc = qobject_cast<WidgetBoxCategoryListView*>(itemWidget(embedItem, 0));
161 std::cout <<
"WidgetBoxTreeWidget::restoreExpandedState() -> XXX Not implemented." << std::endl;
186 if (!file.open(QIODevice::WriteOnly))
191 for (
int i = 0; i < count; ++i)
194 QXmlStreamWriter writer(&file);
195 writer.setAutoFormatting(
true);
196 writer.setAutoFormattingIndent(1);
197 writer.writeStartDocument();
199 writer.writeEndDocument();
214 if (QApplication::mouseButtons() != Qt::LeftButton)
217 if (item->parent() ==
nullptr) {
218 #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
219 item->setExpanded(!item->isExpanded());
221 setItemExpanded(item, !isItemExpanded(item));
230 if (existingIndex != -1)
231 return existingIndex;
233 QTreeWidgetItem* scratch_item =
new QTreeWidgetItem(
this);
234 scratch_item->setText(0,
"Scratchpad");
243 QTreeWidgetItem* embed_item =
new QTreeWidgetItem(parent);
244 embed_item->setFlags(Qt::ItemIsEnabled);
246 categoryView->
setViewMode(iconMode ? QListView::IconMode : QListView::ListMode);
247 connect(categoryView, SIGNAL(scratchPadChanged()),
this, SLOT(
slotSave()));
248 connect(categoryView, SIGNAL(
pressed(QString, QString, QPoint)),
this,
249 SIGNAL(
pressed(QString, QString, QPoint)));
252 setItemWidget(embed_item, 0, categoryView);
258 if (
const int numTopLevels = topLevelItemCount()) {
259 for (
int i = numTopLevels - 1; i >= 0; --i) {
269 const int topLevelCount = topLevelItemCount();
270 for (
int i = 0; i < topLevelCount; ++i) {
271 if (topLevelItem(i)->text(0) ==
name)
293 if (!f.open(QIODevice::ReadOnly))
296 const QString contents = QString::fromUtf8(f.readAll());
302 QString errorMessage;
308 for (
const Category& cat : cat_list)
318 if (
const int numTopLevels = topLevelItemCount()) {
319 for (
int t = 0; t < numTopLevels; ++t)
325 const CategoryList::const_iterator cend = customList.constEnd();
326 for (CategoryList::const_iterator it = customList.constBegin(); it != cend; ++it)
330 static inline QString
msgXmlError(
const QString& fileName,
const QXmlStreamReader& r)
332 return QString(
"An error has been encountered at line %1 of %2: %3")
334 .arg(fileName, r.errorString());
348 QXmlStreamReader reader(contents);
351 bool ignoreEntries =
false;
353 while (!reader.atEnd()) {
354 switch (reader.readNext()) {
355 case QXmlStreamReader::StartElement: {
356 const QStringRef tag = reader.name();
363 const QXmlStreamAttributes attributes = reader.attributes();
364 const QString categoryName =
367 ignoreEntries =
true;
372 category.setType(Category::Scratchpad);
379 if (!ignoreEntries) {
380 QXmlStreamAttributes attr = reader.attributes();
381 const QString widgetName = attr.value(QLatin1String(
nameAttributeC)).toString();
382 const QString widgetIcon = attr.value(QLatin1String(
iconAttributeC)).toString();
383 const WidgetBoxTreeWidget::Widget::Type widgetType =
386 ? WidgetBoxTreeWidget::Widget::Custom
387 : WidgetBoxTreeWidget::Widget::Default;
390 w.setName(widgetName);
391 w.setIconName(widgetIcon);
392 w.setType(widgetType);
396 cats->back().addWidget(w);
402 case QXmlStreamReader::EndElement: {
403 const QStringRef tag = reader.name();
408 ignoreEntries =
false;
421 if (reader.hasError()) {
454 qint64 startTagPosition = 0, endTagPosition = 0;
457 bool endEncountered =
false;
458 bool parsedWidgetTag =
false;
459 QString outmostElement;
460 while (!endEncountered) {
461 const qint64 currentPosition = r.characterOffset();
462 switch (r.readNext()) {
463 case QXmlStreamReader::StartElement:
464 if (nesting++ == 0) {
466 const QStringRef
name = r.name();
468 startTagPosition = currentPosition;
471 startTagPosition = currentPosition;
472 parsedWidgetTag =
true;
474 r.raiseError(QString(
"Unexpected element <%1> encountered when "
475 "parsing for <widget> or <ui>")
476 .arg(
name.toString()));
482 if (!parsedWidgetTag && r.name() == QLatin1String(
widgetElementC)) {
483 parsedWidgetTag =
true;
487 case QXmlStreamReader::EndElement:
489 if (--nesting == 0) {
490 endTagPosition = r.characterOffset();
491 endEncountered =
true;
494 case QXmlStreamReader::EndDocument:
495 r.raiseError(
"Unexpected end of file encountered when parsing widgets.");
497 case QXmlStreamReader::Invalid:
503 if (!parsedWidgetTag) {
504 r.raiseError(
"A widget element could not be found.");
508 QString widgetXml = xml.mid(startTagPosition, endTagPosition - startTagPosition);
509 const QChar lessThan = QLatin1Char(
'<');
510 if (!widgetXml.startsWith(lessThan))
511 widgetXml.prepend(lessThan);
512 w->setDomXml(widgetXml);
526 const QString iconPrefix = QLatin1String(
iconPrefixC);
543 writer.writeStartElement(widgetbox);
545 for (
const Category& cat : cat_list) {
547 writer.writeAttribute(
name, cat.name());
548 if (cat.type() == Category::Scratchpad)
553 const Widget wgt = cat.widget(i);
554 if (wgt.type() == Widget::Custom)
557 writer.writeStartElement(categoryEntry);
558 writer.writeAttribute(
name, wgt.name());
559 if (!wgt.iconName().startsWith(iconPrefix))
560 writer.writeAttribute(icon, wgt.iconName());
561 writer.writeAttribute(type, defaultType);
566 domUI->
write(writer);
569 writer.writeEndElement();
571 writer.writeEndElement();
573 writer.writeEndElement();
580 std::cout <<
"WidgetBoxTreeWidget::loadCustomCategoryList() -> XXX Not implemented."
587 QTreeWidgetItem* embedItem = cat_item->child(0);
588 if (embedItem ==
nullptr)
593 list_widget->setFixedWidth(header()->width());
594 list_widget->doItemsLayout();
595 const int height = qMax(list_widget->contentsSize().height(), 1);
596 list_widget->setFixedHeight(height);
597 embedItem->setSizeHint(0, QSize(-1, height - 1));
602 return topLevelItemCount();
607 if (cat_idx >= topLevelItemCount())
610 QTreeWidgetItem* cat_item = topLevelItem(cat_idx);
612 QTreeWidgetItem* embedItem = cat_item->child(0);
617 result.setName(cat_item->text(0));
621 result.setType(Category::Scratchpad);
624 result.setType(Category::Default);
632 if (cat.widgetCount() == 0)
635 const bool isScratchPad = cat.type() == Category::Scratchpad;
637 QTreeWidgetItem* cat_item;
642 cat_item = topLevelItem(idx);
645 if (existingIndex == -1) {
646 cat_item =
new QTreeWidgetItem();
647 cat_item->setText(0, cat.name());
651 if (scratchPadIndex == -1) {
652 addTopLevelItem(cat_item);
654 insertTopLevelItem(scratchPadIndex, cat_item);
656 #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
657 cat_item->setExpanded(
true);
659 setItemExpanded(cat_item,
true);
665 cat_item = topLevelItem(existingIndex);
671 const Widget w = cat.widget(i);
680 if (cat_idx >= topLevelItemCount())
682 delete takeTopLevelItem(cat_idx);
687 if (cat_idx >= topLevelItemCount())
695 if (cat_idx >= topLevelItemCount())
704 if (cat_idx >= topLevelItemCount())
707 QTreeWidgetItem* cat_item = topLevelItem(cat_idx);
717 if (cat_idx >= topLevelItemCount())
724 if (wgt_idx >= categoryView->
count(am))
733 QTreeWidgetItem* scratch_item = topLevelItem(scratch_idx);
756 delete takeTopLevelItem(idx);
774 if (
const int numTopLevels = topLevelItemCount()) {
775 for (
int i = numTopLevels - 1; i >= 0; --i) {
776 QTreeWidgetItem* topLevel = topLevelItem(i);
778 const QListView::ViewMode viewMode =
780 : QListView::ListMode;
782 if (viewMode != categoryView->viewMode()) {
783 categoryView->setViewMode(viewMode);
793 QTreeWidget::resizeEvent(e);
794 if (
const int numTopLevels = topLevelItemCount()) {
795 for (
int i = numTopLevels - 1; i >= 0; --i)
802 QTreeWidgetItem* item = itemAt(e->pos());
804 const bool scratchpad_menu = item !=
nullptr && item->parent() !=
nullptr
808 menu.addAction(
"Expand all",
this, SLOT(expandAll()));
809 menu.addAction(
"Collapse all",
this, SLOT(collapseAll()));
812 QAction* listModeAction = menu.addAction(
"List View");
813 QAction* iconModeAction = menu.addAction(
"Icon View");
814 listModeAction->setCheckable(
true);
815 iconModeAction->setCheckable(
true);
816 QActionGroup* viewModeGroup =
new QActionGroup(&menu);
817 viewModeGroup->addAction(listModeAction);
818 viewModeGroup->addAction(iconModeAction);
820 iconModeAction->setChecked(
true);
822 listModeAction->setChecked(
true);
823 connect(listModeAction, SIGNAL(triggered()), SLOT(
slotListMode()));
824 connect(iconModeAction, SIGNAL(triggered()), SLOT(
slotIconMode()));
826 if (scratchpad_menu) {
828 menu.addAction(
"Remove", itemWidget(item, 0), SLOT(removeCurrentItem()));
830 menu.addAction(
"Edit name", itemWidget(item, 0), SLOT(editCurrentItem()));
833 menu.exec(mapToGlobal(e->pos()));
838 QTreeWidgetItem* scratch_item =
nullptr;
842 for (QDesignerDnDItemInterface* item : item_list) {
843 QWidget* w = item->widget();
847 DomUI* dom_ui = item->domUi();
848 if (dom_ui ==
nullptr)
852 scratch_item = topLevelItem(scratch_idx);
858 if (fakeTopLevel && !fakeTopLevel->
elementWidget().isEmpty()) {
868 QXmlStreamWriter writer(&xml);
869 writer.setAutoFormatting(
true);
870 writer.setAutoFormattingIndent(1);
871 writer.writeStartDocument();
872 dom_ui->
write(writer);
873 writer.writeEndDocument();
881 #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
882 scratch_item->setExpanded(
true);
884 setItemExpanded(scratch_item,
true);
891 QApplication::setActiveWindow(
this);
894 if (
const int count = categoryView->
count(am))
896 categoryView->adjustSize();
903 const bool empty = f.isEmpty();
904 QRegExp re = empty ? QRegExp() : QRegExp(f, Qt::CaseInsensitive, QRegExp::FixedString);
905 const int numTopLevels = topLevelItemCount();
906 bool changed =
false;
907 for (
int i = 0; i < numTopLevels; i++) {
908 QTreeWidgetItem* tl = topLevelItem(i);
914 if (oldCount != newCount) {
916 const bool categoryEnabled = newCount > 0 || empty;
917 if (categoryEnabled) {
918 categoryView->adjustSize();
921 setRowHidden(i, QModelIndex(), !categoryEnabled);
Defines the macro ASSERT.
#define ASSERT(condition)
void setElementWidget(DomWidget *a)
DomWidget * takeElementWidget()
void write(QXmlStreamWriter &writer, const QString &tagName="") const
sample designer interface
QString const & name(EShape k)
static QString msgXmlError(const QString &fileName, const QXmlStreamReader &r)
QDESIGNER_SHARED_EXPORT void designerWarning(const QString &message)