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 | |
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(s: "New Column" )); |
56 | ui.setupUi(dialog); |
57 | |
58 | injectPropertyBrowser(parent: ui.itemsTab, widget: ui.widget); |
59 | connect(sender: ui.showPropertiesButton, signal: &QAbstractButton::clicked, |
60 | receiver: this, slot: &TreeWidgetEditor::togglePropertyBrowser); |
61 | setPropertyBrowserVisible(false); |
62 | |
63 | ui.tabWidget->insertTab(index: 0, widget: m_columnEditor, tr(s: "&Columns" )); |
64 | ui.tabWidget->setCurrentIndex(0); |
65 | setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); |
66 | |
67 | ui.newItemButton->setIcon(createIconSet(name: QString::fromUtf8(str: "plus.png" ))); |
68 | ui.newSubItemButton->setIcon(createIconSet(name: QString::fromUtf8(str: "downplus.png" ))); |
69 | ui.deleteItemButton->setIcon(createIconSet(name: QString::fromUtf8(str: "minus.png" ))); |
70 | ui.moveItemUpButton->setIcon(createIconSet(name: QString::fromUtf8(str: "up.png" ))); |
71 | ui.moveItemDownButton->setIcon(createIconSet(name: QString::fromUtf8(str: "down.png" ))); |
72 | ui.moveItemRightButton->setIcon(createIconSet(name: QString::fromUtf8(str: "leveldown.png" ))); |
73 | ui.moveItemLeftButton->setIcon(createIconSet(name: QString::fromUtf8(str: "levelup.png" ))); |
74 | |
75 | ui.treeWidget->header()->setSectionsMovable(false); |
76 | |
77 | connect(sender: ui.newItemButton, signal: &QAbstractButton::clicked, receiver: this, slot: &TreeWidgetEditor::on_newItemButton_clicked); |
78 | connect(sender: ui.newSubItemButton, signal: &QAbstractButton::clicked, receiver: this, slot: &TreeWidgetEditor::on_newSubItemButton_clicked); |
79 | connect(sender: ui.moveItemUpButton, signal: &QAbstractButton::clicked, receiver: this, slot: &TreeWidgetEditor::on_moveItemUpButton_clicked); |
80 | connect(sender: ui.moveItemDownButton, signal: &QAbstractButton::clicked, receiver: this, slot: &TreeWidgetEditor::on_moveItemDownButton_clicked); |
81 | connect(sender: ui.moveItemRightButton, signal: &QAbstractButton::clicked, receiver: this, slot: &TreeWidgetEditor::on_moveItemRightButton_clicked); |
82 | connect(sender: ui.moveItemLeftButton, signal: &QAbstractButton::clicked, receiver: this, slot: &TreeWidgetEditor::on_moveItemLeftButton_clicked); |
83 | connect(sender: ui.deleteItemButton, signal: &QAbstractButton::clicked, receiver: this, slot: &TreeWidgetEditor::on_deleteItemButton_clicked); |
84 | connect(sender: ui.treeWidget, signal: &QTreeWidget::currentItemChanged, |
85 | receiver: this, slot: &TreeWidgetEditor::on_treeWidget_currentItemChanged); |
86 | connect(sender: ui.treeWidget, signal: &QTreeWidget::itemChanged, |
87 | receiver: this, slot: &TreeWidgetEditor::on_treeWidget_itemChanged); |
88 | |
89 | connect(sender: m_columnEditor, signal: &ItemListEditor::indexChanged, |
90 | receiver: this, slot: &TreeWidgetEditor::on_columnEditor_indexChanged); |
91 | connect(sender: m_columnEditor, signal: &ItemListEditor::itemChanged, |
92 | receiver: this, slot: &TreeWidgetEditor::on_columnEditor_itemChanged); |
93 | connect(sender: m_columnEditor, signal: &ItemListEditor::itemInserted, |
94 | receiver: this, slot: &TreeWidgetEditor::on_columnEditor_itemInserted); |
95 | connect(sender: m_columnEditor, signal: &ItemListEditor::itemDeleted, |
96 | receiver: this, slot: &TreeWidgetEditor::on_columnEditor_itemDeleted); |
97 | connect(sender: m_columnEditor, signal: &ItemListEditor::itemMovedUp, |
98 | receiver: this, slot: &TreeWidgetEditor::on_columnEditor_itemMovedUp); |
99 | connect(sender: m_columnEditor, signal: &ItemListEditor::itemMovedDown, |
100 | receiver: this, slot: &TreeWidgetEditor::on_columnEditor_itemMovedDown); |
101 | |
102 | connect(sender: iconCache(), signal: &DesignerIconCache::reloaded, receiver: this, slot: &TreeWidgetEditor::cacheReloaded); |
103 | } |
104 | |
105 | static AbstractItemEditor::PropertyDefinition [] = { |
106 | { .role: Qt::DisplayPropertyRole, .type: 0, .typeFunc: DesignerPropertyManager::designerStringTypeId, .name: "text" }, |
107 | { .role: Qt::DecorationPropertyRole, .type: 0, .typeFunc: DesignerPropertyManager::designerIconTypeId, .name: "icon" }, |
108 | { .role: Qt::ToolTipPropertyRole, .type: 0, .typeFunc: DesignerPropertyManager::designerStringTypeId, .name: "toolTip" }, |
109 | { .role: Qt::StatusTipPropertyRole, .type: 0, .typeFunc: DesignerPropertyManager::designerStringTypeId, .name: "statusTip" }, |
110 | { .role: Qt::WhatsThisPropertyRole, .type: 0, .typeFunc: DesignerPropertyManager::designerStringTypeId, .name: "whatsThis" }, |
111 | { .role: Qt::FontRole, .type: QVariant::Font, .typeFunc: nullptr, .name: "font" }, |
112 | { .role: Qt::TextAlignmentRole, .type: 0, .typeFunc: DesignerPropertyManager::designerAlignmentTypeId, .name: "textAlignment" }, |
113 | { .role: Qt::BackgroundRole, .type: QVariant::Color, .typeFunc: nullptr, .name: "background" }, |
114 | { .role: Qt::ForegroundRole, .type: QVariant::Brush, .typeFunc: nullptr, .name: "foreground" }, |
115 | { .role: 0, .type: 0, .typeFunc: nullptr, .name: nullptr } |
116 | }; |
117 | |
118 | static AbstractItemEditor::PropertyDefinition treeItemColumnPropList[] = { |
119 | { .role: Qt::DisplayPropertyRole, .type: 0, .typeFunc: DesignerPropertyManager::designerStringTypeId, .name: "text" }, |
120 | { .role: Qt::DecorationPropertyRole, .type: 0, .typeFunc: DesignerPropertyManager::designerIconTypeId, .name: "icon" }, |
121 | { .role: Qt::ToolTipPropertyRole, .type: 0, .typeFunc: DesignerPropertyManager::designerStringTypeId, .name: "toolTip" }, |
122 | { .role: Qt::StatusTipPropertyRole, .type: 0, .typeFunc: DesignerPropertyManager::designerStringTypeId, .name: "statusTip" }, |
123 | { .role: Qt::WhatsThisPropertyRole, .type: 0, .typeFunc: DesignerPropertyManager::designerStringTypeId, .name: "whatsThis" }, |
124 | { .role: Qt::FontRole, .type: QVariant::Font, .typeFunc: nullptr, .name: "font" }, |
125 | { .role: Qt::TextAlignmentRole, .type: 0, .typeFunc: DesignerPropertyManager::designerAlignmentTypeId, .name: "textAlignment" }, |
126 | { .role: Qt::BackgroundRole, .type: QVariant::Brush, .typeFunc: nullptr, .name: "background" }, |
127 | { .role: Qt::ForegroundRole, .type: QVariant::Brush, .typeFunc: nullptr, .name: "foreground" }, |
128 | { .role: Qt::CheckStateRole, .type: 0, .typeFunc: QtVariantPropertyManager::enumTypeId, .name: "checkState" }, |
129 | { .role: 0, .type: 0, .typeFunc: nullptr, .name: nullptr } |
130 | }; |
131 | |
132 | static AbstractItemEditor::PropertyDefinition treeItemCommonPropList[] = { |
133 | { .role: ItemFlagsShadowRole, .type: 0, .typeFunc: QtVariantPropertyManager::flagTypeId, .name: "flags" }, |
134 | { .role: 0, .type: 0, .typeFunc: nullptr, .name: nullptr } |
135 | }; |
136 | |
137 | QtVariantProperty *TreeWidgetEditor::setupPropertyGroup(const QString &title, PropertyDefinition *propDefs) |
138 | { |
139 | setupProperties(propList: propDefs); |
140 | QtVariantProperty *groupProp = m_propertyManager->addProperty(propertyType: QtVariantPropertyManager::groupTypeId(), name: title); |
141 | for (QtVariantProperty *prop : qAsConst(t&: m_rootProperties)) |
142 | groupProp->addSubProperty(property: prop); |
143 | m_rootProperties.clear(); |
144 | return groupProp; |
145 | } |
146 | |
147 | TreeWidgetContents TreeWidgetEditor::fillContentsFromTreeWidget(QTreeWidget *treeWidget) |
148 | { |
149 | TreeWidgetContents treeCont; |
150 | treeCont.fromTreeWidget(treeWidget, editor: false); |
151 | treeCont.applyToTreeWidget(treeWidget: ui.treeWidget, iconCache: iconCache(), editor: true); |
152 | |
153 | treeCont.m_headerItem.applyToListWidget(listWidget: m_columnEditor->listWidget(), iconCache: iconCache(), editor: true); |
154 | m_columnEditor->setupEditor(object: treeWidget, propDefs: treeHeaderPropList); |
155 | |
156 | QList<QtVariantProperty*> rootProperties; |
157 | rootProperties.append(t: setupPropertyGroup(title: tr(s: "Per column properties" ), propDefs: treeItemColumnPropList)); |
158 | rootProperties.append(t: setupPropertyGroup(title: tr(s: "Common properties" ), propDefs: 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(index: 0)); |
166 | |
167 | updateEditor(); |
168 | |
169 | return treeCont; |
170 | } |
171 | |
172 | TreeWidgetContents TreeWidgetEditor::contents() const |
173 | { |
174 | TreeWidgetContents retVal; |
175 | retVal.fromTreeWidget(treeWidget: ui.treeWidget, editor: true); |
176 | return retVal; |
177 | } |
178 | |
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>(v: newValue).resolve(oldFont); |
187 | newValue = QVariant::fromValue(value: newFont); |
188 | ui.treeWidget->currentItem()->setData(column: col, role, value: QVariant()); // force the right font with the current resolve mask is set (item view bug) |
189 | } |
190 | ui.treeWidget->currentItem()->setData(column: col, role, value: newValue); |
191 | } |
192 | |
193 | QVariant TreeWidgetEditor::getItemData(int role) const |
194 | { |
195 | const int col = (role == ItemFlagsShadowRole) ? 0 : ui.treeWidget->currentColumn(); |
196 | return ui.treeWidget->currentItem()->data(column: col, role); |
197 | } |
198 | |
199 | int TreeWidgetEditor::defaultItemFlags() const |
200 | { |
201 | static const int flags = QTreeWidgetItem().flags(); |
202 | return flags; |
203 | } |
204 | |
205 | void TreeWidgetEditor::on_newItemButton_clicked() |
206 | { |
207 | QTreeWidgetItem *curItem = ui.treeWidget->currentItem(); |
208 | QTreeWidgetItem *newItem = nullptr; |
209 | ui.treeWidget->blockSignals(b: 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(s: "New Item" ); |
218 | newItem->setText(column: 0, atext: newItemText); |
219 | newItem->setData(column: 0, role: Qt::DisplayPropertyRole, value: QVariant::fromValue(value: PropertySheetStringValue(newItemText))); |
220 | newItem->setFlags(newItem->flags() | Qt::ItemIsEditable); |
221 | ui.treeWidget->blockSignals(b: false); |
222 | |
223 | ui.treeWidget->setCurrentItem(item: newItem, column: qMax(a: ui.treeWidget->currentColumn(), b: 0)); |
224 | updateEditor(); |
225 | ui.treeWidget->editItem(item: newItem, column: ui.treeWidget->currentColumn()); |
226 | } |
227 | |
228 | void TreeWidgetEditor::on_newSubItemButton_clicked() |
229 | { |
230 | QTreeWidgetItem *curItem = ui.treeWidget->currentItem(); |
231 | if (!curItem) |
232 | return; |
233 | |
234 | ui.treeWidget->blockSignals(b: true); |
235 | QTreeWidgetItem *newItem = new QTreeWidgetItem(curItem); |
236 | const QString newItemText = tr(s: "New Subitem" ); |
237 | newItem->setText(column: 0, atext: newItemText); |
238 | newItem->setData(column: 0, role: Qt::DisplayPropertyRole, value: QVariant::fromValue(value: PropertySheetStringValue(newItemText))); |
239 | newItem->setFlags(newItem->flags() | Qt::ItemIsEditable); |
240 | ui.treeWidget->blockSignals(b: false); |
241 | |
242 | ui.treeWidget->setCurrentItem(item: newItem, column: ui.treeWidget->currentColumn()); |
243 | updateEditor(); |
244 | ui.treeWidget->editItem(item: newItem, column: ui.treeWidget->currentColumn()); |
245 | } |
246 | |
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(achild: 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(index: idx); |
264 | } else { |
265 | int idx = ui.treeWidget->indexOfTopLevelItem(item: curItem); |
266 | if (idx == ui.treeWidget->topLevelItemCount() - 1) |
267 | idx--; |
268 | else |
269 | idx++; |
270 | if (idx >= 0) |
271 | nextCurrent = ui.treeWidget->topLevelItem(index: idx); |
272 | } |
273 | closeEditors(); |
274 | ui.treeWidget->blockSignals(b: true); |
275 | delete curItem; |
276 | ui.treeWidget->blockSignals(b: false); |
277 | |
278 | if (nextCurrent) |
279 | ui.treeWidget->setCurrentItem(item: nextCurrent, column: ui.treeWidget->currentColumn()); |
280 | updateEditor(); |
281 | } |
282 | |
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(achild: curItem); |
292 | else |
293 | idx = ui.treeWidget->indexOfTopLevelItem(item: curItem); |
294 | if (idx == 0) |
295 | return; |
296 | |
297 | QTreeWidgetItem *takenItem; |
298 | ui.treeWidget->blockSignals(b: true); |
299 | if (curItem->parent()) { |
300 | QTreeWidgetItem *parentItem = curItem->parent(); |
301 | takenItem = parentItem->takeChild(index: idx); |
302 | parentItem->insertChild(index: idx - 1, child: takenItem); |
303 | } else { |
304 | takenItem = ui.treeWidget->takeTopLevelItem(index: idx); |
305 | ui.treeWidget->insertTopLevelItem(index: idx - 1, item: takenItem); |
306 | } |
307 | ui.treeWidget->blockSignals(b: false); |
308 | |
309 | ui.treeWidget->setCurrentItem(item: takenItem, column: ui.treeWidget->currentColumn()); |
310 | updateEditor(); |
311 | } |
312 | |
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(achild: curItem); |
322 | idxCount = curItem->parent()->childCount(); |
323 | } else { |
324 | idx = ui.treeWidget->indexOfTopLevelItem(item: curItem); |
325 | idxCount = ui.treeWidget->topLevelItemCount(); |
326 | } |
327 | if (idx == idxCount - 1) |
328 | return; |
329 | |
330 | QTreeWidgetItem *takenItem; |
331 | ui.treeWidget->blockSignals(b: true); |
332 | if (curItem->parent()) { |
333 | QTreeWidgetItem *parentItem = curItem->parent(); |
334 | takenItem = parentItem->takeChild(index: idx); |
335 | parentItem->insertChild(index: idx + 1, child: takenItem); |
336 | } else { |
337 | takenItem = ui.treeWidget->takeTopLevelItem(index: idx); |
338 | ui.treeWidget->insertTopLevelItem(index: idx + 1, item: takenItem); |
339 | } |
340 | ui.treeWidget->blockSignals(b: false); |
341 | |
342 | ui.treeWidget->setCurrentItem(item: takenItem, column: ui.treeWidget->currentColumn()); |
343 | updateEditor(); |
344 | } |
345 | |
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(b: true); |
357 | QTreeWidgetItem *takenItem = parentItem->takeChild(index: parentItem->indexOfChild(achild: curItem)); |
358 | if (parentItem->parent()) { |
359 | int idx = parentItem->parent()->indexOfChild(achild: parentItem); |
360 | parentItem->parent()->insertChild(index: idx, child: takenItem); |
361 | } else { |
362 | int idx = ui.treeWidget->indexOfTopLevelItem(item: parentItem); |
363 | ui.treeWidget->insertTopLevelItem(index: idx, item: takenItem); |
364 | } |
365 | ui.treeWidget->blockSignals(b: false); |
366 | |
367 | ui.treeWidget->setCurrentItem(item: takenItem, column: ui.treeWidget->currentColumn()); |
368 | updateEditor(); |
369 | } |
370 | |
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(achild: curItem); |
380 | idxCount = curItem->parent()->childCount(); |
381 | } else { |
382 | idx = ui.treeWidget->indexOfTopLevelItem(item: curItem); |
383 | idxCount = ui.treeWidget->topLevelItemCount(); |
384 | } |
385 | if (idx == idxCount - 1) |
386 | return; |
387 | |
388 | QTreeWidgetItem *takenItem; |
389 | ui.treeWidget->blockSignals(b: true); |
390 | if (curItem->parent()) { |
391 | QTreeWidgetItem *parentItem = curItem->parent()->child(index: idx + 1); |
392 | takenItem = curItem->parent()->takeChild(index: idx); |
393 | parentItem->insertChild(index: 0, child: takenItem); |
394 | } else { |
395 | QTreeWidgetItem *parentItem = ui.treeWidget->topLevelItem(index: idx + 1); |
396 | takenItem = ui.treeWidget->takeTopLevelItem(index: idx); |
397 | parentItem->insertChild(index: 0, child: takenItem); |
398 | } |
399 | ui.treeWidget->blockSignals(b: false); |
400 | |
401 | ui.treeWidget->setCurrentItem(item: takenItem, column: ui.treeWidget->currentColumn()); |
402 | updateEditor(); |
403 | } |
404 | |
405 | void TreeWidgetEditor::togglePropertyBrowser() |
406 | { |
407 | setPropertyBrowserVisible(!m_propertyBrowser->isVisible()); |
408 | } |
409 | |
410 | void TreeWidgetEditor::setPropertyBrowserVisible(bool v) |
411 | { |
412 | ui.showPropertiesButton->setText(v ? tr(s: "Properties &>>" ) : tr(s: "Properties &<<" )); |
413 | m_propertyBrowser->setVisible(v); |
414 | } |
415 | |
416 | void TreeWidgetEditor::on_treeWidget_currentItemChanged() |
417 | { |
418 | m_columnEditor->setCurrentIndex(ui.treeWidget->currentColumn()); |
419 | updateEditor(); |
420 | } |
421 | |
422 | void TreeWidgetEditor::on_treeWidget_itemChanged(QTreeWidgetItem *item, int column) |
423 | { |
424 | if (m_updatingBrowser) |
425 | return; |
426 | |
427 | PropertySheetStringValue val = qvariant_cast<PropertySheetStringValue>(v: item->data(column, role: Qt::DisplayPropertyRole)); |
428 | val.setValue(item->text(column)); |
429 | BoolBlocker block(m_updatingBrowser); |
430 | item->setData(column, role: Qt::DisplayPropertyRole, value: QVariant::fromValue(value: val)); |
431 | |
432 | updateBrowser(); |
433 | } |
434 | |
435 | void TreeWidgetEditor::on_columnEditor_indexChanged(int idx) |
436 | { |
437 | if (QTreeWidgetItem *item = ui.treeWidget->currentItem()) |
438 | ui.treeWidget->setCurrentItem(item, column: idx); |
439 | } |
440 | |
441 | void TreeWidgetEditor::on_columnEditor_itemChanged(int idx, int role, const QVariant &v) |
442 | { |
443 | if (role == Qt::DisplayPropertyRole) |
444 | ui.treeWidget->headerItem()->setData(column: idx, role: Qt::EditRole, value: qvariant_cast<PropertySheetStringValue>(v).value()); |
445 | ui.treeWidget->headerItem()->setData(column: idx, role, value: v); |
446 | } |
447 | |
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(achild: current); |
468 | idxCount = current->parent()->childCount(); |
469 | } else { |
470 | idx = ui.treeWidget->indexOfTopLevelItem(item: 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(index: 1, enabled: 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 | |
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(t: item->data(column: toColumn, role: propList[j].role)); |
504 | QVariant editVariant = item->data(column: toColumn, role: Qt::EditRole); |
505 | QVariant toolTipVariant = item->data(column: toColumn, role: Qt::ToolTipRole); |
506 | QVariant statusTipVariant = item->data(column: toColumn, role: Qt::StatusTipRole); |
507 | QVariant whatsThisVariant = item->data(column: toColumn, role: Qt::WhatsThisRole); |
508 | QVariant decorationVariant = item->data(column: toColumn, role: Qt::DecorationRole); |
509 | for (int i = toColumn; i != fromColumn; i += step) { |
510 | for (int j = 0; propList[j].name; j++) |
511 | item->setData(column: i, role: propList[j].role, value: item->data(column: i + step, role: propList[j].role)); |
512 | item->setData(column: i, role: Qt::EditRole, value: item->data(column: i + step, role: Qt::EditRole)); |
513 | item->setData(column: i, role: Qt::ToolTipRole, value: item->data(column: i + step, role: Qt::ToolTipRole)); |
514 | item->setData(column: i, role: Qt::StatusTipRole, value: item->data(column: i + step, role: Qt::StatusTipRole)); |
515 | item->setData(column: i, role: Qt::WhatsThisRole, value: item->data(column: i + step, role: Qt::WhatsThisRole)); |
516 | item->setData(column: i, role: Qt::DecorationRole, value: item->data(column: i + step, role: Qt::DecorationRole)); |
517 | } |
518 | for (int j = 0; propList[j].name; j++) |
519 | item->setData(column: fromColumn, role: propList[j].role, value: saveCol[j]); |
520 | item->setData(column: fromColumn, role: Qt::EditRole, value: editVariant); |
521 | item->setData(column: fromColumn, role: Qt::ToolTipRole, value: toolTipVariant); |
522 | item->setData(column: fromColumn, role: Qt::StatusTipRole, value: statusTipVariant); |
523 | item->setData(column: fromColumn, role: Qt::WhatsThisRole, value: whatsThisVariant); |
524 | item->setData(column: fromColumn, role: Qt::DecorationRole, value: decorationVariant); |
525 | } |
526 | |
527 | void TreeWidgetEditor::moveColumns(int fromColumn, int toColumn, int step) |
528 | { |
529 | ui.treeWidget->blockSignals(b: true); |
530 | |
531 | moveColumnItems(propList: treeHeaderPropList, item: ui.treeWidget->headerItem(), fromColumn, toColumn, step); |
532 | |
533 | QQueue<QTreeWidgetItem *> pendingQueue; |
534 | for (int i = 0; i < ui.treeWidget->topLevelItemCount(); i++) |
535 | pendingQueue.enqueue(t: ui.treeWidget->topLevelItem(index: i)); |
536 | |
537 | while (!pendingQueue.isEmpty()) { |
538 | QTreeWidgetItem *item = pendingQueue.dequeue(); |
539 | for (int i = 0; i < item->childCount(); i++) |
540 | pendingQueue.enqueue(t: item->child(index: i)); |
541 | |
542 | moveColumnItems(propList: treeItemColumnPropList, item, fromColumn, toColumn, step); |
543 | } |
544 | |
545 | ui.treeWidget->blockSignals(b: false); |
546 | } |
547 | |
548 | void TreeWidgetEditor::moveColumnsLeft(int fromColumn, int toColumn) |
549 | { |
550 | if (fromColumn >= toColumn) |
551 | return; |
552 | |
553 | moveColumns(fromColumn, toColumn, step: -1); |
554 | } |
555 | |
556 | void TreeWidgetEditor::moveColumnsRight(int fromColumn, int toColumn) |
557 | { |
558 | if (fromColumn >= toColumn) |
559 | return; |
560 | |
561 | moveColumns(fromColumn: toColumn, toColumn: fromColumn, step: 1); |
562 | } |
563 | |
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(column: columnCount, atext: m_columnEditor->newItemText()); |
569 | moveColumnsLeft(fromColumn: idx, toColumn: columnCount); |
570 | |
571 | updateEditor(); |
572 | } |
573 | |
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(fromColumn: idx, toColumn: columnCount); |
583 | ui.treeWidget->setColumnCount(columnCount); |
584 | |
585 | updateEditor(); |
586 | } |
587 | |
588 | void TreeWidgetEditor::on_columnEditor_itemMovedUp(int idx) |
589 | { |
590 | moveColumnsRight(fromColumn: idx - 1, toColumn: idx); |
591 | |
592 | ui.treeWidget->setCurrentItem(item: ui.treeWidget->currentItem(), column: idx - 1); |
593 | updateEditor(); |
594 | } |
595 | |
596 | void TreeWidgetEditor::on_columnEditor_itemMovedDown(int idx) |
597 | { |
598 | moveColumnsLeft(fromColumn: idx, toColumn: idx + 1); |
599 | |
600 | ui.treeWidget->setCurrentItem(item: ui.treeWidget->currentItem(), column: idx + 1); |
601 | updateEditor(); |
602 | } |
603 | |
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 (item: cur, column: i); |
610 | } |
611 | } |
612 | |
613 | void TreeWidgetEditor::cacheReloaded() |
614 | { |
615 | reloadIconResources(iconCache: iconCache(), object: ui.treeWidget); |
616 | } |
617 | |
618 | TreeWidgetEditorDialog::TreeWidgetEditorDialog(QDesignerFormWindowInterface *form, QWidget *parent) : |
619 | QDialog(parent), m_editor(form, this) |
620 | { |
621 | setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); |
622 | } |
623 | |
624 | TreeWidgetContents TreeWidgetEditorDialog::fillContentsFromTreeWidget(QTreeWidget *treeWidget) |
625 | { |
626 | return m_editor.fillContentsFromTreeWidget(treeWidget); |
627 | } |
628 | |
629 | TreeWidgetContents TreeWidgetEditorDialog::contents() const |
630 | { |
631 | return m_editor.contents(); |
632 | } |
633 | |
634 | } // namespace qdesigner_internal |
635 | |
636 | QT_END_NAMESPACE |
637 | |