1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Designer of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #include "treewidgeteditor.h"
30 #include <formwindowbase_p.h>
31 #include <iconloader_p.h>
32 #include <qdesigner_command_p.h>
33 #include <qdesigner_utils_p.h>
34 #include <abstractformbuilder.h>
35 #include <designerpropertymanager.h>
36 #include <qttreepropertybrowser.h>
37 
38 #include <QtDesigner/abstractformwindow.h>
39 #include <QtDesigner/abstractformeditor.h>
40 
41 #include <QtCore/qdir.h>
42 #include <QtCore/qqueue.h>
43 #include <QtWidgets/qheaderview.h>
44 #include <QtWidgets/qtreewidgetitemiterator.h>
45 
46 QT_BEGIN_NAMESPACE
47 
48 namespace qdesigner_internal {
49 
TreeWidgetEditor(QDesignerFormWindowInterface * form,QDialog * dialog)50 TreeWidgetEditor::TreeWidgetEditor(QDesignerFormWindowInterface *form, QDialog *dialog)
51     : AbstractItemEditor(form, nullptr), m_updatingBrowser(false)
52 {
53     m_columnEditor = new ItemListEditor(form, this);
54     m_columnEditor->setObjectName(QStringLiteral("columnEditor"));
55     m_columnEditor->setNewItemText(tr("New Column"));
56     ui.setupUi(dialog);
57 
58     injectPropertyBrowser(ui.itemsTab, ui.widget);
59     connect(ui.showPropertiesButton, &QAbstractButton::clicked,
60             this, &TreeWidgetEditor::togglePropertyBrowser);
61     setPropertyBrowserVisible(false);
62 
63     ui.tabWidget->insertTab(0, m_columnEditor, tr("&Columns"));
64     ui.tabWidget->setCurrentIndex(0);
65     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
66 
67     ui.newItemButton->setIcon(createIconSet(QString::fromUtf8("plus.png")));
68     ui.newSubItemButton->setIcon(createIconSet(QString::fromUtf8("downplus.png")));
69     ui.deleteItemButton->setIcon(createIconSet(QString::fromUtf8("minus.png")));
70     ui.moveItemUpButton->setIcon(createIconSet(QString::fromUtf8("up.png")));
71     ui.moveItemDownButton->setIcon(createIconSet(QString::fromUtf8("down.png")));
72     ui.moveItemRightButton->setIcon(createIconSet(QString::fromUtf8("leveldown.png")));
73     ui.moveItemLeftButton->setIcon(createIconSet(QString::fromUtf8("levelup.png")));
74 
75     ui.treeWidget->header()->setSectionsMovable(false);
76 
77     connect(ui.newItemButton, &QAbstractButton::clicked, this, &TreeWidgetEditor::on_newItemButton_clicked);
78     connect(ui.newSubItemButton, &QAbstractButton::clicked, this, &TreeWidgetEditor::on_newSubItemButton_clicked);
79     connect(ui.moveItemUpButton, &QAbstractButton::clicked, this, &TreeWidgetEditor::on_moveItemUpButton_clicked);
80     connect(ui.moveItemDownButton, &QAbstractButton::clicked, this, &TreeWidgetEditor::on_moveItemDownButton_clicked);
81     connect(ui.moveItemRightButton, &QAbstractButton::clicked, this, &TreeWidgetEditor::on_moveItemRightButton_clicked);
82     connect(ui.moveItemLeftButton, &QAbstractButton::clicked, this, &TreeWidgetEditor::on_moveItemLeftButton_clicked);
83     connect(ui.deleteItemButton, &QAbstractButton::clicked, this, &TreeWidgetEditor::on_deleteItemButton_clicked);
84     connect(ui.treeWidget, &QTreeWidget::currentItemChanged,
85             this, &TreeWidgetEditor::on_treeWidget_currentItemChanged);
86     connect(ui.treeWidget, &QTreeWidget::itemChanged,
87             this, &TreeWidgetEditor::on_treeWidget_itemChanged);
88 
89     connect(m_columnEditor, &ItemListEditor::indexChanged,
90             this, &TreeWidgetEditor::on_columnEditor_indexChanged);
91     connect(m_columnEditor, &ItemListEditor::itemChanged,
92             this, &TreeWidgetEditor::on_columnEditor_itemChanged);
93     connect(m_columnEditor, &ItemListEditor::itemInserted,
94             this, &TreeWidgetEditor::on_columnEditor_itemInserted);
95     connect(m_columnEditor, &ItemListEditor::itemDeleted,
96             this, &TreeWidgetEditor::on_columnEditor_itemDeleted);
97     connect(m_columnEditor, &ItemListEditor::itemMovedUp,
98             this, &TreeWidgetEditor::on_columnEditor_itemMovedUp);
99     connect(m_columnEditor, &ItemListEditor::itemMovedDown,
100             this, &TreeWidgetEditor::on_columnEditor_itemMovedDown);
101 
102     connect(iconCache(), &DesignerIconCache::reloaded, this, &TreeWidgetEditor::cacheReloaded);
103 }
104 
105 static AbstractItemEditor::PropertyDefinition treeHeaderPropList[] = {
106     { Qt::DisplayPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "text" },
107     { Qt::DecorationPropertyRole, 0, DesignerPropertyManager::designerIconTypeId, "icon" },
108     { Qt::ToolTipPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "toolTip" },
109     { Qt::StatusTipPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "statusTip" },
110     { Qt::WhatsThisPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "whatsThis" },
111     { Qt::FontRole, QVariant::Font, nullptr, "font" },
112     { Qt::TextAlignmentRole, 0, DesignerPropertyManager::designerAlignmentTypeId, "textAlignment" },
113     { Qt::BackgroundRole, QVariant::Color, nullptr, "background" },
114     { Qt::ForegroundRole, QVariant::Brush, nullptr, "foreground" },
115     { 0, 0, nullptr, nullptr }
116 };
117 
118 static AbstractItemEditor::PropertyDefinition treeItemColumnPropList[] = {
119     { Qt::DisplayPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "text" },
120     { Qt::DecorationPropertyRole, 0, DesignerPropertyManager::designerIconTypeId, "icon" },
121     { Qt::ToolTipPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "toolTip" },
122     { Qt::StatusTipPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "statusTip" },
123     { Qt::WhatsThisPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "whatsThis" },
124     { Qt::FontRole, QVariant::Font, nullptr, "font" },
125     { Qt::TextAlignmentRole, 0, DesignerPropertyManager::designerAlignmentTypeId, "textAlignment" },
126     { Qt::BackgroundRole, QVariant::Brush, nullptr, "background" },
127     { Qt::ForegroundRole, QVariant::Brush, nullptr, "foreground" },
128     { Qt::CheckStateRole, 0, QtVariantPropertyManager::enumTypeId, "checkState" },
129     { 0, 0, nullptr, nullptr }
130 };
131 
132 static AbstractItemEditor::PropertyDefinition treeItemCommonPropList[] = {
133     { ItemFlagsShadowRole, 0, QtVariantPropertyManager::flagTypeId, "flags" },
134     { 0, 0, nullptr, nullptr }
135 };
136 
setupPropertyGroup(const QString & title,PropertyDefinition * propDefs)137 QtVariantProperty *TreeWidgetEditor::setupPropertyGroup(const QString &title, PropertyDefinition *propDefs)
138 {
139     setupProperties(propDefs);
140     QtVariantProperty *groupProp = m_propertyManager->addProperty(QtVariantPropertyManager::groupTypeId(), title);
141     for (QtVariantProperty *prop : qAsConst(m_rootProperties))
142         groupProp->addSubProperty(prop);
143     m_rootProperties.clear();
144     return groupProp;
145 }
146 
fillContentsFromTreeWidget(QTreeWidget * treeWidget)147 TreeWidgetContents TreeWidgetEditor::fillContentsFromTreeWidget(QTreeWidget *treeWidget)
148 {
149     TreeWidgetContents treeCont;
150     treeCont.fromTreeWidget(treeWidget, false);
151     treeCont.applyToTreeWidget(ui.treeWidget, iconCache(), true);
152 
153     treeCont.m_headerItem.applyToListWidget(m_columnEditor->listWidget(), iconCache(), true);
154     m_columnEditor->setupEditor(treeWidget, treeHeaderPropList);
155 
156     QList<QtVariantProperty*> rootProperties;
157     rootProperties.append(setupPropertyGroup(tr("Per column properties"), treeItemColumnPropList));
158     rootProperties.append(setupPropertyGroup(tr("Common properties"), treeItemCommonPropList));
159     m_rootProperties = rootProperties;
160     m_propertyBrowser->setPropertiesWithoutValueMarked(true);
161     m_propertyBrowser->setRootIsDecorated(false);
162     setupObject(treeWidget);
163 
164     if (ui.treeWidget->topLevelItemCount() > 0)
165         ui.treeWidget->setCurrentItem(ui.treeWidget->topLevelItem(0));
166 
167     updateEditor();
168 
169     return treeCont;
170 }
171 
contents() const172 TreeWidgetContents TreeWidgetEditor::contents() const
173 {
174     TreeWidgetContents retVal;
175     retVal.fromTreeWidget(ui.treeWidget, true);
176     return retVal;
177 }
178 
setItemData(int role,const QVariant & v)179 void TreeWidgetEditor::setItemData(int role, const QVariant &v)
180 {
181     const int col = (role == ItemFlagsShadowRole) ? 0 : ui.treeWidget->currentColumn();
182     QVariant newValue = v;
183     BoolBlocker block(m_updatingBrowser);
184     if (role == Qt::FontRole && newValue.type() == QVariant::Font) {
185         QFont oldFont = ui.treeWidget->font();
186         QFont newFont = qvariant_cast<QFont>(newValue).resolve(oldFont);
187         newValue = QVariant::fromValue(newFont);
188         ui.treeWidget->currentItem()->setData(col, role, QVariant()); // force the right font with the current resolve mask is set (item view bug)
189     }
190     ui.treeWidget->currentItem()->setData(col, role, newValue);
191 }
192 
getItemData(int role) const193 QVariant TreeWidgetEditor::getItemData(int role) const
194 {
195     const int col = (role == ItemFlagsShadowRole) ? 0 : ui.treeWidget->currentColumn();
196     return ui.treeWidget->currentItem()->data(col, role);
197 }
198 
defaultItemFlags() const199 int TreeWidgetEditor::defaultItemFlags() const
200 {
201     static const int flags = QTreeWidgetItem().flags();
202     return flags;
203 }
204 
on_newItemButton_clicked()205 void TreeWidgetEditor::on_newItemButton_clicked()
206 {
207     QTreeWidgetItem *curItem = ui.treeWidget->currentItem();
208     QTreeWidgetItem *newItem = nullptr;
209     ui.treeWidget->blockSignals(true);
210     if (curItem) {
211         if (curItem->parent())
212             newItem = new QTreeWidgetItem(curItem->parent(), curItem);
213         else
214             newItem = new QTreeWidgetItem(ui.treeWidget, curItem);
215     } else
216         newItem = new QTreeWidgetItem(ui.treeWidget);
217     const QString newItemText = tr("New Item");
218     newItem->setText(0, newItemText);
219     newItem->setData(0, Qt::DisplayPropertyRole, QVariant::fromValue(PropertySheetStringValue(newItemText)));
220     newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
221     ui.treeWidget->blockSignals(false);
222 
223     ui.treeWidget->setCurrentItem(newItem, qMax(ui.treeWidget->currentColumn(), 0));
224     updateEditor();
225     ui.treeWidget->editItem(newItem, ui.treeWidget->currentColumn());
226 }
227 
on_newSubItemButton_clicked()228 void TreeWidgetEditor::on_newSubItemButton_clicked()
229 {
230     QTreeWidgetItem *curItem = ui.treeWidget->currentItem();
231     if (!curItem)
232         return;
233 
234     ui.treeWidget->blockSignals(true);
235     QTreeWidgetItem *newItem = new QTreeWidgetItem(curItem);
236     const QString newItemText = tr("New Subitem");
237     newItem->setText(0, newItemText);
238     newItem->setData(0, Qt::DisplayPropertyRole, QVariant::fromValue(PropertySheetStringValue(newItemText)));
239     newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
240     ui.treeWidget->blockSignals(false);
241 
242     ui.treeWidget->setCurrentItem(newItem, ui.treeWidget->currentColumn());
243     updateEditor();
244     ui.treeWidget->editItem(newItem, ui.treeWidget->currentColumn());
245 }
246 
on_deleteItemButton_clicked()247 void TreeWidgetEditor::on_deleteItemButton_clicked()
248 {
249     QTreeWidgetItem *curItem = ui.treeWidget->currentItem();
250     if (!curItem)
251         return;
252 
253     QTreeWidgetItem *nextCurrent = nullptr;
254     if (curItem->parent()) {
255         int idx = curItem->parent()->indexOfChild(curItem);
256         if (idx == curItem->parent()->childCount() - 1)
257             idx--;
258         else
259             idx++;
260         if (idx < 0)
261             nextCurrent = curItem->parent();
262         else
263             nextCurrent = curItem->parent()->child(idx);
264     } else {
265         int idx = ui.treeWidget->indexOfTopLevelItem(curItem);
266         if (idx == ui.treeWidget->topLevelItemCount() - 1)
267             idx--;
268         else
269             idx++;
270         if (idx >= 0)
271             nextCurrent = ui.treeWidget->topLevelItem(idx);
272     }
273     closeEditors();
274     ui.treeWidget->blockSignals(true);
275     delete curItem;
276     ui.treeWidget->blockSignals(false);
277 
278     if (nextCurrent)
279         ui.treeWidget->setCurrentItem(nextCurrent, ui.treeWidget->currentColumn());
280     updateEditor();
281 }
282 
on_moveItemUpButton_clicked()283 void TreeWidgetEditor::on_moveItemUpButton_clicked()
284 {
285     QTreeWidgetItem *curItem = ui.treeWidget->currentItem();
286     if (!curItem)
287         return;
288 
289     int idx;
290     if (curItem->parent())
291         idx = curItem->parent()->indexOfChild(curItem);
292     else
293         idx = ui.treeWidget->indexOfTopLevelItem(curItem);
294     if (idx == 0)
295         return;
296 
297     QTreeWidgetItem *takenItem;
298     ui.treeWidget->blockSignals(true);
299     if (curItem->parent()) {
300         QTreeWidgetItem *parentItem = curItem->parent();
301         takenItem = parentItem->takeChild(idx);
302         parentItem->insertChild(idx - 1, takenItem);
303     } else {
304         takenItem = ui.treeWidget->takeTopLevelItem(idx);
305         ui.treeWidget->insertTopLevelItem(idx - 1, takenItem);
306     }
307     ui.treeWidget->blockSignals(false);
308 
309     ui.treeWidget->setCurrentItem(takenItem, ui.treeWidget->currentColumn());
310     updateEditor();
311 }
312 
on_moveItemDownButton_clicked()313 void TreeWidgetEditor::on_moveItemDownButton_clicked()
314 {
315     QTreeWidgetItem *curItem = ui.treeWidget->currentItem();
316     if (!curItem)
317         return;
318 
319     int idx, idxCount;
320     if (curItem->parent()) {
321         idx = curItem->parent()->indexOfChild(curItem);
322         idxCount = curItem->parent()->childCount();
323     } else {
324         idx = ui.treeWidget->indexOfTopLevelItem(curItem);
325         idxCount = ui.treeWidget->topLevelItemCount();
326     }
327     if (idx == idxCount - 1)
328         return;
329 
330     QTreeWidgetItem *takenItem;
331     ui.treeWidget->blockSignals(true);
332     if (curItem->parent()) {
333         QTreeWidgetItem *parentItem = curItem->parent();
334         takenItem = parentItem->takeChild(idx);
335         parentItem->insertChild(idx + 1, takenItem);
336     } else {
337         takenItem = ui.treeWidget->takeTopLevelItem(idx);
338         ui.treeWidget->insertTopLevelItem(idx + 1, takenItem);
339     }
340     ui.treeWidget->blockSignals(false);
341 
342     ui.treeWidget->setCurrentItem(takenItem, ui.treeWidget->currentColumn());
343     updateEditor();
344 }
345 
on_moveItemLeftButton_clicked()346 void TreeWidgetEditor::on_moveItemLeftButton_clicked()
347 {
348     QTreeWidgetItem *curItem = ui.treeWidget->currentItem();
349     if (!curItem)
350         return;
351 
352     QTreeWidgetItem *parentItem = curItem->parent();
353     if (!parentItem)
354         return;
355 
356     ui.treeWidget->blockSignals(true);
357     QTreeWidgetItem *takenItem = parentItem->takeChild(parentItem->indexOfChild(curItem));
358     if (parentItem->parent()) {
359         int idx = parentItem->parent()->indexOfChild(parentItem);
360         parentItem->parent()->insertChild(idx, takenItem);
361     } else {
362         int idx = ui.treeWidget->indexOfTopLevelItem(parentItem);
363         ui.treeWidget->insertTopLevelItem(idx, takenItem);
364     }
365     ui.treeWidget->blockSignals(false);
366 
367     ui.treeWidget->setCurrentItem(takenItem, ui.treeWidget->currentColumn());
368     updateEditor();
369 }
370 
on_moveItemRightButton_clicked()371 void TreeWidgetEditor::on_moveItemRightButton_clicked()
372 {
373     QTreeWidgetItem *curItem = ui.treeWidget->currentItem();
374     if (!curItem)
375         return;
376 
377     int idx, idxCount;
378     if (curItem->parent()) {
379         idx = curItem->parent()->indexOfChild(curItem);
380         idxCount = curItem->parent()->childCount();
381     } else {
382         idx = ui.treeWidget->indexOfTopLevelItem(curItem);
383         idxCount = ui.treeWidget->topLevelItemCount();
384     }
385     if (idx == idxCount - 1)
386         return;
387 
388     QTreeWidgetItem *takenItem;
389     ui.treeWidget->blockSignals(true);
390     if (curItem->parent()) {
391         QTreeWidgetItem *parentItem = curItem->parent()->child(idx + 1);
392         takenItem = curItem->parent()->takeChild(idx);
393         parentItem->insertChild(0, takenItem);
394     } else {
395         QTreeWidgetItem *parentItem = ui.treeWidget->topLevelItem(idx + 1);
396         takenItem = ui.treeWidget->takeTopLevelItem(idx);
397         parentItem->insertChild(0, takenItem);
398     }
399     ui.treeWidget->blockSignals(false);
400 
401     ui.treeWidget->setCurrentItem(takenItem, ui.treeWidget->currentColumn());
402     updateEditor();
403 }
404 
togglePropertyBrowser()405 void TreeWidgetEditor::togglePropertyBrowser()
406 {
407     setPropertyBrowserVisible(!m_propertyBrowser->isVisible());
408 }
409 
setPropertyBrowserVisible(bool v)410 void TreeWidgetEditor::setPropertyBrowserVisible(bool v)
411 {
412     ui.showPropertiesButton->setText(v ? tr("Properties &>>") : tr("Properties &<<"));
413     m_propertyBrowser->setVisible(v);
414 }
415 
on_treeWidget_currentItemChanged()416 void TreeWidgetEditor::on_treeWidget_currentItemChanged()
417 {
418     m_columnEditor->setCurrentIndex(ui.treeWidget->currentColumn());
419     updateEditor();
420 }
421 
on_treeWidget_itemChanged(QTreeWidgetItem * item,int column)422 void TreeWidgetEditor::on_treeWidget_itemChanged(QTreeWidgetItem *item, int column)
423 {
424     if (m_updatingBrowser)
425         return;
426 
427     PropertySheetStringValue val = qvariant_cast<PropertySheetStringValue>(item->data(column, Qt::DisplayPropertyRole));
428     val.setValue(item->text(column));
429     BoolBlocker block(m_updatingBrowser);
430     item->setData(column, Qt::DisplayPropertyRole, QVariant::fromValue(val));
431 
432     updateBrowser();
433 }
434 
on_columnEditor_indexChanged(int idx)435 void TreeWidgetEditor::on_columnEditor_indexChanged(int idx)
436 {
437     if (QTreeWidgetItem *item = ui.treeWidget->currentItem())
438         ui.treeWidget->setCurrentItem(item, idx);
439 }
440 
on_columnEditor_itemChanged(int idx,int role,const QVariant & v)441 void TreeWidgetEditor::on_columnEditor_itemChanged(int idx, int role, const QVariant &v)
442 {
443     if (role == Qt::DisplayPropertyRole)
444         ui.treeWidget->headerItem()->setData(idx, Qt::EditRole, qvariant_cast<PropertySheetStringValue>(v).value());
445     ui.treeWidget->headerItem()->setData(idx, role, v);
446 }
447 
updateEditor()448 void TreeWidgetEditor::updateEditor()
449 {
450     QTreeWidgetItem *current = ui.treeWidget->currentItem();
451 
452     bool itemsEnabled = false;
453     bool currentItemEnabled = false;
454     bool moveItemUpEnabled = false;
455     bool moveItemDownEnabled = false;
456     bool moveItemRightEnabled = false;
457     bool moveItemLeftEnabled = false;
458 
459     if (ui.treeWidget->columnCount() > 0) {
460         itemsEnabled = true;
461         if (current) {
462             int idx;
463             int idxCount;
464             currentItemEnabled = true;
465             if (current->parent()) {
466                 moveItemLeftEnabled = true;
467                 idx = current->parent()->indexOfChild(current);
468                 idxCount = current->parent()->childCount();
469             } else {
470                 idx = ui.treeWidget->indexOfTopLevelItem(current);
471                 idxCount = ui.treeWidget->topLevelItemCount();
472             }
473             if (idx > 0)
474                 moveItemUpEnabled = true;
475             if (idx < idxCount - 1) {
476                 moveItemDownEnabled = true;
477                 moveItemRightEnabled = true;
478             }
479         }
480     }
481     ui.tabWidget->setTabEnabled(1, itemsEnabled);
482     ui.newSubItemButton->setEnabled(currentItemEnabled);
483     ui.deleteItemButton->setEnabled(currentItemEnabled);
484 
485     ui.moveItemUpButton->setEnabled(moveItemUpEnabled);
486     ui.moveItemDownButton->setEnabled(moveItemDownEnabled);
487     ui.moveItemRightButton->setEnabled(moveItemRightEnabled);
488     ui.moveItemLeftButton->setEnabled(moveItemLeftEnabled);
489 
490     if (current)
491         updateBrowser();
492     else
493         m_propertyBrowser->clear();
494 }
495 
moveColumnItems(const PropertyDefinition * propList,QTreeWidgetItem * item,int fromColumn,int toColumn,int step)496 void TreeWidgetEditor::moveColumnItems(const PropertyDefinition *propList,
497         QTreeWidgetItem *item, int fromColumn, int toColumn, int step)
498 {
499     BoolBlocker block(m_updatingBrowser);
500 
501     QList<QVariant> saveCol;
502     for (int j = 0; propList[j].name; j++)
503         saveCol.append(item->data(toColumn, propList[j].role));
504     QVariant editVariant = item->data(toColumn, Qt::EditRole);
505     QVariant toolTipVariant = item->data(toColumn, Qt::ToolTipRole);
506     QVariant statusTipVariant = item->data(toColumn, Qt::StatusTipRole);
507     QVariant whatsThisVariant = item->data(toColumn, Qt::WhatsThisRole);
508     QVariant decorationVariant = item->data(toColumn, Qt::DecorationRole);
509     for (int i = toColumn; i != fromColumn; i += step) {
510         for (int j = 0; propList[j].name; j++)
511             item->setData(i, propList[j].role, item->data(i + step, propList[j].role));
512         item->setData(i, Qt::EditRole, item->data(i + step, Qt::EditRole));
513         item->setData(i, Qt::ToolTipRole, item->data(i + step, Qt::ToolTipRole));
514         item->setData(i, Qt::StatusTipRole, item->data(i + step, Qt::StatusTipRole));
515         item->setData(i, Qt::WhatsThisRole, item->data(i + step, Qt::WhatsThisRole));
516         item->setData(i, Qt::DecorationRole, item->data(i + step, Qt::DecorationRole));
517     }
518     for (int j = 0; propList[j].name; j++)
519         item->setData(fromColumn, propList[j].role, saveCol[j]);
520     item->setData(fromColumn, Qt::EditRole, editVariant);
521     item->setData(fromColumn, Qt::ToolTipRole, toolTipVariant);
522     item->setData(fromColumn, Qt::StatusTipRole, statusTipVariant);
523     item->setData(fromColumn, Qt::WhatsThisRole, whatsThisVariant);
524     item->setData(fromColumn, Qt::DecorationRole, decorationVariant);
525 }
526 
moveColumns(int fromColumn,int toColumn,int step)527 void TreeWidgetEditor::moveColumns(int fromColumn, int toColumn, int step)
528 {
529     ui.treeWidget->blockSignals(true);
530 
531     moveColumnItems(treeHeaderPropList, ui.treeWidget->headerItem(), fromColumn, toColumn, step);
532 
533     QQueue<QTreeWidgetItem *> pendingQueue;
534     for (int i = 0; i < ui.treeWidget->topLevelItemCount(); i++)
535         pendingQueue.enqueue(ui.treeWidget->topLevelItem(i));
536 
537     while (!pendingQueue.isEmpty()) {
538         QTreeWidgetItem *item = pendingQueue.dequeue();
539         for (int i = 0; i < item->childCount(); i++)
540             pendingQueue.enqueue(item->child(i));
541 
542         moveColumnItems(treeItemColumnPropList, item, fromColumn, toColumn, step);
543     }
544 
545     ui.treeWidget->blockSignals(false);
546 }
547 
moveColumnsLeft(int fromColumn,int toColumn)548 void TreeWidgetEditor::moveColumnsLeft(int fromColumn, int toColumn)
549 {
550     if (fromColumn >= toColumn)
551         return;
552 
553     moveColumns(fromColumn, toColumn, -1);
554 }
555 
moveColumnsRight(int fromColumn,int toColumn)556 void TreeWidgetEditor::moveColumnsRight(int fromColumn, int toColumn)
557 {
558     if (fromColumn >= toColumn)
559         return;
560 
561     moveColumns(toColumn, fromColumn, 1);
562 }
563 
on_columnEditor_itemInserted(int idx)564 void TreeWidgetEditor::on_columnEditor_itemInserted(int idx)
565 {
566     int columnCount = ui.treeWidget->columnCount();
567     ui.treeWidget->setColumnCount(columnCount + 1);
568     ui.treeWidget->headerItem()->setText(columnCount, m_columnEditor->newItemText());
569     moveColumnsLeft(idx, columnCount);
570 
571     updateEditor();
572 }
573 
on_columnEditor_itemDeleted(int idx)574 void TreeWidgetEditor::on_columnEditor_itemDeleted(int idx)
575 {
576     closeEditors();
577 
578     int columnCount = ui.treeWidget->columnCount() - 1;
579     if (!columnCount)
580         ui.treeWidget->clear();
581     else
582         moveColumnsRight(idx, columnCount);
583     ui.treeWidget->setColumnCount(columnCount);
584 
585     updateEditor();
586 }
587 
on_columnEditor_itemMovedUp(int idx)588 void TreeWidgetEditor::on_columnEditor_itemMovedUp(int idx)
589 {
590     moveColumnsRight(idx - 1, idx);
591 
592     ui.treeWidget->setCurrentItem(ui.treeWidget->currentItem(), idx - 1);
593     updateEditor();
594 }
595 
on_columnEditor_itemMovedDown(int idx)596 void TreeWidgetEditor::on_columnEditor_itemMovedDown(int idx)
597 {
598     moveColumnsLeft(idx, idx + 1);
599 
600     ui.treeWidget->setCurrentItem(ui.treeWidget->currentItem(), idx + 1);
601     updateEditor();
602 }
603 
closeEditors()604 void TreeWidgetEditor::closeEditors()
605 {
606     if (QTreeWidgetItem *cur = ui.treeWidget->currentItem() ) {
607         const int numCols = cur->columnCount ();
608         for (int i = 0; i < numCols; i++)
609             ui.treeWidget->closePersistentEditor (cur, i);
610     }
611 }
612 
cacheReloaded()613 void TreeWidgetEditor::cacheReloaded()
614 {
615     reloadIconResources(iconCache(), ui.treeWidget);
616 }
617 
TreeWidgetEditorDialog(QDesignerFormWindowInterface * form,QWidget * parent)618 TreeWidgetEditorDialog::TreeWidgetEditorDialog(QDesignerFormWindowInterface *form, QWidget *parent) :
619     QDialog(parent), m_editor(form, this)
620 {
621     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
622 }
623 
fillContentsFromTreeWidget(QTreeWidget * treeWidget)624 TreeWidgetContents TreeWidgetEditorDialog::fillContentsFromTreeWidget(QTreeWidget *treeWidget)
625 {
626     return m_editor.fillContentsFromTreeWidget(treeWidget);
627 }
628 
contents() const629 TreeWidgetContents TreeWidgetEditorDialog::contents() const
630 {
631     return m_editor.contents();
632 }
633 
634 } // namespace qdesigner_internal
635 
636 QT_END_NAMESPACE
637