source: trunk/tools/designer/src/lib/shared/qdesigner_toolbox.cpp@ 651

Last change on this file since 651 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 16.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the Qt Designer of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qdesigner_toolbox_p.h"
43#include "qdesigner_command_p.h"
44#include "orderdialog_p.h"
45#include "promotiontaskmenu_p.h"
46#include "formwindowbase_p.h"
47
48#include <QtDesigner/QDesignerFormWindowInterface>
49
50#include <QtCore/QEvent>
51#include <QtGui/QAction>
52#include <QtGui/QToolBox>
53#include <QtGui/QMenu>
54#include <QtGui/QLayout>
55#include <QtGui/QApplication>
56#include <QtGui/QContextMenuEvent>
57#include <QtCore/QHash>
58
59QT_BEGIN_NAMESPACE
60
61QToolBoxHelper::QToolBoxHelper(QToolBox *toolbox) :
62 QObject(toolbox),
63 m_toolbox(toolbox),
64 m_actionDeletePage(new QAction(tr("Delete Page"), this)),
65 m_actionInsertPage(new QAction(tr("Before Current Page"), this)),
66 m_actionInsertPageAfter(new QAction(tr("After Current Page"), this)),
67 m_actionChangePageOrder(new QAction(tr("Change Page Order..."), this)),
68 m_pagePromotionTaskMenu(new qdesigner_internal::PromotionTaskMenu(0, qdesigner_internal::PromotionTaskMenu::ModeSingleWidget, this))
69{
70 connect(m_actionDeletePage, SIGNAL(triggered()), this, SLOT(removeCurrentPage()));
71 connect(m_actionInsertPage, SIGNAL(triggered()), this, SLOT(addPage()));
72 connect(m_actionInsertPageAfter, SIGNAL(triggered()), this, SLOT(addPageAfter()));
73 connect(m_actionChangePageOrder, SIGNAL(triggered()), this, SLOT(changeOrder()));
74
75 m_toolbox->installEventFilter(this);
76}
77
78void QToolBoxHelper::install(QToolBox *toolbox)
79{
80 new QToolBoxHelper(toolbox);
81}
82
83bool QToolBoxHelper::eventFilter(QObject *watched, QEvent *event)
84{
85 switch (event->type()) {
86 case QEvent::ChildPolished:
87 // Install on the buttons
88 if (watched == m_toolbox) {
89 QChildEvent *ce = static_cast<QChildEvent *>(event);
90 if (!qstrcmp(ce->child()->metaObject()->className(), "QToolBoxButton"))
91 ce->child()->installEventFilter(this);
92 }
93 break;
94 case QEvent::ContextMenu:
95 if (watched != m_toolbox) {
96 // An action invoked from the passive interactor (ToolBox button) might
97 // cause its deletion within its event handler, triggering a warning. Re-post
98 // the event to the toolbox.
99 QContextMenuEvent *current = static_cast<QContextMenuEvent *>(event);
100 QContextMenuEvent *copy = new QContextMenuEvent(current->reason(), current->pos(), current-> globalPos(), current->modifiers());
101 QApplication::postEvent(m_toolbox, copy);
102 current->accept();
103 return true;
104 }
105 break;
106 case QEvent::MouseButtonRelease:
107 if (watched != m_toolbox)
108 if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_toolbox)) {
109 fw->clearSelection();
110 fw->selectWidget(m_toolbox, true);
111 }
112 break;
113 default:
114 break;
115 }
116 return QObject::eventFilter(watched, event);
117}
118
119QToolBoxHelper *QToolBoxHelper::helperOf(const QToolBox *toolbox)
120{
121 // Look for 1st order children only..otherwise, we might get filters of nested widgets
122 const QObjectList children = toolbox->children();
123 const QObjectList::const_iterator cend = children.constEnd();
124 for (QObjectList::const_iterator it = children.constBegin(); it != cend; ++it) {
125 QObject *o = *it;
126 if (!o->isWidgetType())
127 if (QToolBoxHelper *h = qobject_cast<QToolBoxHelper *>(o))
128 return h;
129 }
130 return 0;
131}
132
133QMenu *QToolBoxHelper::addToolBoxContextMenuActions(const QToolBox *toolbox, QMenu *popup)
134{
135 QToolBoxHelper *helper = helperOf(toolbox);
136 if (!helper)
137 return 0;
138 return helper->addContextMenuActions(popup);
139}
140
141void QToolBoxHelper::removeCurrentPage()
142{
143 if (m_toolbox->currentIndex() == -1 || !m_toolbox->widget(m_toolbox->currentIndex()))
144 return;
145
146 if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_toolbox)) {
147 qdesigner_internal::DeleteToolBoxPageCommand *cmd = new qdesigner_internal::DeleteToolBoxPageCommand(fw);
148 cmd->init(m_toolbox);
149 fw->commandHistory()->push(cmd);
150 }
151}
152
153void QToolBoxHelper::addPage()
154{
155 if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_toolbox)) {
156 qdesigner_internal::AddToolBoxPageCommand *cmd = new qdesigner_internal::AddToolBoxPageCommand(fw);
157 cmd->init(m_toolbox, qdesigner_internal::AddToolBoxPageCommand::InsertBefore);
158 fw->commandHistory()->push(cmd);
159 }
160}
161
162void QToolBoxHelper::changeOrder()
163{
164 QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_toolbox);
165
166 if (!fw)
167 return;
168
169 const QWidgetList oldPages = qdesigner_internal::OrderDialog::pagesOfContainer(fw->core(), m_toolbox);
170 const int pageCount = oldPages.size();
171 if (pageCount < 2)
172 return;
173
174 qdesigner_internal::OrderDialog dlg(fw);
175 dlg.setPageList(oldPages);
176 if (dlg.exec() == QDialog::Rejected)
177 return;
178
179 const QWidgetList newPages = dlg.pageList();
180 if (newPages == oldPages)
181 return;
182
183 fw->beginCommand(tr("Change Page Order"));
184 for(int i=0; i < pageCount; ++i) {
185 if (newPages.at(i) == m_toolbox->widget(i))
186 continue;
187 qdesigner_internal::MoveToolBoxPageCommand *cmd = new qdesigner_internal::MoveToolBoxPageCommand(fw);
188 cmd->init(m_toolbox, newPages.at(i), i);
189 fw->commandHistory()->push(cmd);
190 }
191 fw->endCommand();
192}
193
194void QToolBoxHelper::addPageAfter()
195{
196 if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_toolbox)) {
197 qdesigner_internal::AddToolBoxPageCommand *cmd = new qdesigner_internal::AddToolBoxPageCommand(fw);
198 cmd->init(m_toolbox, qdesigner_internal::AddToolBoxPageCommand::InsertAfter);
199 fw->commandHistory()->push(cmd);
200 }
201}
202
203QPalette::ColorRole QToolBoxHelper::currentItemBackgroundRole() const
204{
205 const QWidget *w = m_toolbox->widget(0);
206 if (!w)
207 return QPalette::Window;
208 return w->backgroundRole();
209}
210
211void QToolBoxHelper::setCurrentItemBackgroundRole(QPalette::ColorRole role)
212{
213 const int count = m_toolbox->count();
214 for (int i = 0; i < count; ++i) {
215 QWidget *w = m_toolbox->widget(i);
216 w->setBackgroundRole(role);
217 w->update();
218 }
219}
220
221QMenu *QToolBoxHelper::addContextMenuActions(QMenu *popup) const
222{
223 QMenu *pageMenu = 0;
224 const int count = m_toolbox->count();
225 m_actionDeletePage->setEnabled(count > 1);
226 if (count) {
227 const QString pageSubMenuLabel = tr("Page %1 of %2").arg(m_toolbox->currentIndex() + 1).arg(count);
228 pageMenu = popup->addMenu(pageSubMenuLabel);
229
230 pageMenu->addAction(m_actionDeletePage);
231 // Set up promotion menu for current widget.
232 if (QWidget *page = m_toolbox->currentWidget ()) {
233 m_pagePromotionTaskMenu->setWidget(page);
234 m_pagePromotionTaskMenu->addActions(QDesignerFormWindowInterface::findFormWindow(m_toolbox),
235 qdesigner_internal::PromotionTaskMenu::SuppressGlobalEdit,
236 pageMenu);
237 }
238 }
239 QMenu *insertPageMenu = popup->addMenu(tr("Insert Page"));
240 insertPageMenu->addAction(m_actionInsertPageAfter);
241 insertPageMenu->addAction(m_actionInsertPage);
242 if (count > 1) {
243 popup->addAction(m_actionChangePageOrder);
244 }
245 popup->addSeparator();
246 return pageMenu;
247}
248
249// -------- QToolBoxWidgetPropertySheet
250
251static const char *currentItemTextKey = "currentItemText";
252static const char *currentItemNameKey = "currentItemName";
253static const char *currentItemIconKey = "currentItemIcon";
254static const char *currentItemToolTipKey = "currentItemToolTip";
255static const char *tabSpacingKey = "tabSpacing";
256
257enum { tabSpacingDefault = -1 };
258
259QToolBoxWidgetPropertySheet::QToolBoxWidgetPropertySheet(QToolBox *object, QObject *parent) :
260 QDesignerPropertySheet(object, parent),
261 m_toolBox(object)
262{
263 createFakeProperty(QLatin1String(currentItemTextKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue()));
264 createFakeProperty(QLatin1String(currentItemNameKey), QString());
265 createFakeProperty(QLatin1String(currentItemIconKey), qVariantFromValue(qdesigner_internal::PropertySheetIconValue()));
266 if (formWindowBase())
267 formWindowBase()->addReloadableProperty(this, indexOf(QLatin1String(currentItemIconKey)));
268 createFakeProperty(QLatin1String(currentItemToolTipKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue()));
269 createFakeProperty(QLatin1String(tabSpacingKey), QVariant(tabSpacingDefault));
270}
271
272QToolBoxWidgetPropertySheet::ToolBoxProperty QToolBoxWidgetPropertySheet::toolBoxPropertyFromName(const QString &name)
273{
274 typedef QHash<QString, ToolBoxProperty> ToolBoxPropertyHash;
275 static ToolBoxPropertyHash toolBoxPropertyHash;
276 if (toolBoxPropertyHash.empty()) {
277 toolBoxPropertyHash.insert(QLatin1String(currentItemTextKey), PropertyCurrentItemText);
278 toolBoxPropertyHash.insert(QLatin1String(currentItemNameKey), PropertyCurrentItemName);
279 toolBoxPropertyHash.insert(QLatin1String(currentItemIconKey), PropertyCurrentItemIcon);
280 toolBoxPropertyHash.insert(QLatin1String(currentItemToolTipKey), PropertyCurrentItemToolTip);
281 toolBoxPropertyHash.insert(QLatin1String(tabSpacingKey), PropertyTabSpacing);
282 }
283 return toolBoxPropertyHash.value(name, PropertyToolBoxNone);
284}
285
286void QToolBoxWidgetPropertySheet::setProperty(int index, const QVariant &value)
287{
288 const ToolBoxProperty toolBoxProperty = toolBoxPropertyFromName(propertyName(index));
289 // independent of index
290 switch (toolBoxProperty) {
291 case PropertyTabSpacing:
292 m_toolBox->layout()->setSpacing(value.toInt());
293 return;
294 case PropertyToolBoxNone:
295 QDesignerPropertySheet::setProperty(index, value);
296 return;
297 default:
298 break;
299 }
300 // index-dependent
301 const int currentIndex = m_toolBox->currentIndex();
302 QWidget *currentWidget = m_toolBox->currentWidget();
303 if (!currentWidget)
304 return;
305
306 switch (toolBoxProperty) {
307 case PropertyCurrentItemText:
308 m_toolBox->setItemText(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value)));
309 m_pageToData[currentWidget].text = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value);
310 break;
311 case PropertyCurrentItemName:
312 currentWidget->setObjectName(value.toString());
313 break;
314 case PropertyCurrentItemIcon:
315 m_toolBox->setItemIcon(currentIndex, qvariant_cast<QIcon>(resolvePropertyValue(index, value)));
316 m_pageToData[currentWidget].icon = qVariantValue<qdesigner_internal::PropertySheetIconValue>(value);
317 break;
318 case PropertyCurrentItemToolTip:
319 m_toolBox->setItemToolTip(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value)));
320 m_pageToData[currentWidget].tooltip = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value);
321 break;
322 case PropertyTabSpacing:
323 case PropertyToolBoxNone:
324 break;
325 }
326}
327
328bool QToolBoxWidgetPropertySheet::isEnabled(int index) const
329{
330 switch (toolBoxPropertyFromName(propertyName(index))) {
331 case PropertyToolBoxNone: // independent of index
332 case PropertyTabSpacing:
333 return QDesignerPropertySheet::isEnabled(index);
334 default:
335 break;
336 }
337 return m_toolBox->currentIndex() != -1;
338}
339
340QVariant QToolBoxWidgetPropertySheet::property(int index) const
341{
342 const ToolBoxProperty toolBoxProperty = toolBoxPropertyFromName(propertyName(index));
343 // independent of index
344 switch (toolBoxProperty) {
345 case PropertyTabSpacing:
346 return m_toolBox->layout()->spacing();
347 case PropertyToolBoxNone:
348 return QDesignerPropertySheet::property(index);
349 default:
350 break;
351 }
352 // index-dependent
353 QWidget *currentWidget = m_toolBox->currentWidget();
354 if (!currentWidget) {
355 if (toolBoxProperty == PropertyCurrentItemIcon)
356 return qVariantFromValue(qdesigner_internal::PropertySheetIconValue());
357 if (toolBoxProperty == PropertyCurrentItemText)
358 return qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
359 if (toolBoxProperty == PropertyCurrentItemToolTip)
360 return qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
361 return QVariant(QString());
362 }
363
364 // index-dependent
365 switch (toolBoxProperty) {
366 case PropertyCurrentItemText:
367 return qVariantFromValue(m_pageToData.value(currentWidget).text);
368 case PropertyCurrentItemName:
369 return currentWidget->objectName();
370 case PropertyCurrentItemIcon:
371 return qVariantFromValue(m_pageToData.value(currentWidget).icon);
372 case PropertyCurrentItemToolTip:
373 return qVariantFromValue(m_pageToData.value(currentWidget).tooltip);
374 case PropertyTabSpacing:
375 case PropertyToolBoxNone:
376 break;
377 }
378 return QVariant();
379}
380
381bool QToolBoxWidgetPropertySheet::reset(int index)
382{
383 const ToolBoxProperty toolBoxProperty = toolBoxPropertyFromName(propertyName(index));
384 // independent of index
385 switch (toolBoxProperty) {
386 case PropertyTabSpacing:
387 setProperty(index, QVariant(tabSpacingDefault));
388 return true;
389 case PropertyToolBoxNone:
390 return QDesignerPropertySheet::reset(index);
391 default:
392 break;
393 }
394 // index-dependent
395 QWidget *currentWidget = m_toolBox->currentWidget();
396 if (!currentWidget)
397 return false;
398
399 // index-dependent
400 switch (toolBoxProperty) {
401 case PropertyCurrentItemName:
402 setProperty(index, QString());
403 break;
404 case PropertyCurrentItemToolTip:
405 m_pageToData[currentWidget].tooltip = qdesigner_internal::PropertySheetStringValue();
406 setProperty(index, QString());
407 break;
408 case PropertyCurrentItemText:
409 m_pageToData[currentWidget].text = qdesigner_internal::PropertySheetStringValue();
410 setProperty(index, QString());
411 break;
412 case PropertyCurrentItemIcon:
413 m_pageToData[currentWidget].icon = qdesigner_internal::PropertySheetIconValue();
414 setProperty(index, QIcon());
415 break;
416 case PropertyTabSpacing:
417 case PropertyToolBoxNone:
418 break;
419 }
420 return true;
421}
422
423bool QToolBoxWidgetPropertySheet::checkProperty(const QString &propertyName)
424{
425 switch (toolBoxPropertyFromName(propertyName)) {
426 case PropertyCurrentItemText:
427 case PropertyCurrentItemName:
428 case PropertyCurrentItemToolTip:
429 case PropertyCurrentItemIcon:
430 return false;
431 default:
432 break;
433 }
434 return true;
435}
436
437QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.