source: trunk/tools/designer/src/lib/shared/morphmenu.cpp@ 846

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

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 23.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 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 "morphmenu_p.h"
43#include "formwindowbase_p.h"
44#include "widgetfactory_p.h"
45#include "qdesigner_formwindowcommand_p.h"
46#include "qlayout_widget_p.h"
47#include "layoutinfo_p.h"
48#include "qdesigner_propertycommand_p.h"
49
50#include <QtDesigner/QExtensionManager>
51#include <QtDesigner/QDesignerContainerExtension>
52#include <QtDesigner/QDesignerFormWindowInterface>
53#include <QtDesigner/QDesignerFormEditorInterface>
54#include <QtDesigner/QDesignerLanguageExtension>
55#include <QtDesigner/QDesignerWidgetDataBaseInterface>
56#include <QtDesigner/QDesignerMetaDataBaseInterface>
57#include <QtDesigner/QDesignerPropertySheetExtension>
58
59#include <QtGui/QWidget>
60#include <QtGui/QAction>
61#include <QtGui/QMenu>
62#include <QtGui/QApplication>
63#include <QtGui/QLayout>
64#include <QtGui/QUndoStack>
65
66#include <QtGui/QFrame>
67#include <QtGui/QGroupBox>
68#include <QtGui/QTabWidget>
69#include <QtGui/QStackedWidget>
70#include <QtGui/QToolBox>
71#include <QtGui/QAbstractItemView>
72#include <QtGui/QAbstractButton>
73#include <QtGui/QAbstractSpinBox>
74#include <QtGui/QTextEdit>
75#include <QtGui/QPlainTextEdit>
76#include <QtGui/QLabel>
77
78#include <QtCore/QStringList>
79#include <QtCore/QMap>
80#include <QtCore/QVariant>
81#include <QtCore/QSignalMapper>
82#include <QtCore/QDebug>
83
84Q_DECLARE_METATYPE(QWidgetList)
85
86QT_BEGIN_NAMESPACE
87
88// Helpers for the dynamic properties that store Z/Widget order
89static const char *widgetOrderPropertyC = "_q_widgetOrder";
90static const char *zOrderPropertyC = "_q_zOrder";
91
92/* Morphing in Designer:
93 * It is possible to morph:
94 * - Non-Containers into similar widgets by category
95 * - Simple page containers into similar widgets or page-based containers with
96 * a single page (in theory also into a QLayoutWidget, but this might
97 * not always be appropriate).
98 * - Page-based containers into page-based containers or simple containers if
99 * they have just one page
100 * [Page based containers meaning here having a container extension]
101 * Morphing types are restricted to the basic Qt types. Morphing custom
102 * widgets is considered risky since they might have unmanaged layouts
103 * or the like.
104 *
105 * Requirements:
106 * - The widget must be on a non-laid out parent or in a layout managed
107 * by Designer
108 * - Its child widgets must be non-laid out or in a layout managed
109 * by Designer
110 * Note that child widgets can be
111 * - On the widget itself in the case of simple containers
112 * - On several pages in the case of page-based containers
113 * This is what is called 'childContainers' in the code (the widget itself
114 * or the list of container extension pages).
115 *
116 * The Morphing process encompasses:
117 * - Create a target widget and apply properties as far as applicable
118 * If the target widget has a container extension, add a sufficient
119 * number of pages.
120 * - Transferring the child widgets over to the new childContainers.
121 * In the case of a managed layout on a childContainer, this is simply
122 * set on the target childContainer, which is a new Qt 4.5
123 * functionality.
124 * - Replace the widget itself in the parent layout
125 */
126
127namespace qdesigner_internal {
128
129enum MorphCategory {
130 MorphCategoryNone, MorphSimpleContainer, MorphPageContainer, MorphItemView,
131 MorphButton, MorphSpinBox, MorphTextEdit
132};
133
134// Determine category of a widget
135static MorphCategory category(const QWidget *w)
136{
137 // Simple containers: Exact match
138 const QMetaObject *mo = w->metaObject();
139 if (mo == &QWidget::staticMetaObject || mo == &QFrame::staticMetaObject || mo == &QGroupBox::staticMetaObject || mo == &QLayoutWidget::staticMetaObject)
140 return MorphSimpleContainer;
141 if (mo == &QTabWidget::staticMetaObject || mo == &QStackedWidget::staticMetaObject || mo == &QToolBox::staticMetaObject)
142 return MorphPageContainer;
143 if (qobject_cast<const QAbstractItemView*>(w))
144 return MorphItemView;
145 if (qobject_cast<const QAbstractButton *>(w))
146 return MorphButton;
147 if (qobject_cast<const QAbstractSpinBox *>(w))
148 return MorphSpinBox;
149 if (qobject_cast<const QPlainTextEdit *>(w) || qobject_cast<const QTextEdit*>(w))
150 return MorphTextEdit;
151
152 return MorphCategoryNone;
153}
154
155/* Return the similar classes of a category. This is currently restricted
156 * to the known Qt classes with no precautions to parse the Widget Database
157 * (which is too risky, custom classes might have container extensions
158 * or non-managed layouts, etc.). */
159
160static QStringList classesOfCategory(MorphCategory cat)
161{
162 typedef QMap<MorphCategory, QStringList> CandidateCache;
163 static CandidateCache candidateCache;
164 CandidateCache::iterator it = candidateCache.find(cat);
165 if (it == candidateCache.end()) {
166 it = candidateCache.insert(cat, QStringList());
167 QStringList &l = it.value();
168 switch (cat) {
169 case MorphCategoryNone:
170 break;
171 case MorphSimpleContainer:
172 // Do not generally allow to morph into a layout.
173 // This can be risky in case of container pages,etc.
174 l << QLatin1String("QWidget") << QLatin1String("QFrame") << QLatin1String("QGroupBox");
175 break;
176 case MorphPageContainer:
177 l << QLatin1String("QTabWidget") << QLatin1String("QStackedWidget") << QLatin1String("QToolBox");
178 break;
179 case MorphItemView:
180 l << QLatin1String("QListView") << QLatin1String("QListWidget")
181 << QLatin1String("QTreeView") << QLatin1String("QTreeWidget")
182 << QLatin1String("QTableView") << QLatin1String("QTableWidget")
183 << QLatin1String("QColumnView");
184 break;
185 case MorphButton:
186 l << QLatin1String("QCheckBox") << QLatin1String("QRadioButton")
187 << QLatin1String("QPushButton") << QLatin1String("QToolButton")
188 << QLatin1String("QCommandLinkButton");
189 break;
190 case MorphSpinBox:
191 l << QLatin1String("QDateTimeEdit") << QLatin1String("QDateEdit")
192 << QLatin1String("QTimeEdit")
193 << QLatin1String("QSpinBox") << QLatin1String("QDoubleSpinBox");
194 break;
195 case MorphTextEdit:
196 l << QLatin1String("QTextEdit") << QLatin1String("QPlainTextEdit");
197 break;
198 }
199 }
200 return it.value();
201}
202
203// Return the widgets containing the children to be transferred to. This is the
204// widget itself in most cases, except for QDesignerContainerExtension cases
205static QWidgetList childContainers(const QDesignerFormEditorInterface *core, QWidget *w)
206{
207 if (const QDesignerContainerExtension *ce = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), w)) {
208 QWidgetList children;
209 if (const int count = ce->count()) {
210 for (int i = 0; i < count; i++)
211 children.push_back(ce->widget(i));
212 }
213 return children;
214 }
215 QWidgetList self;
216 self.push_back(w);
217 return self;
218}
219
220// Suggest a suitable objectname for the widget to be morphed into
221// Replace the class name parts: 'xxFrame' -> 'xxGroupBox', 'frame' -> 'groupBox'
222static QString suggestObjectName(const QString &oldClassName, const QString &newClassName, const QString &oldName)
223{
224 QString oldClassPart = oldClassName;
225 QString newClassPart = newClassName;
226 if (oldClassPart.startsWith(QLatin1Char('Q')))
227 oldClassPart.remove(0, 1);
228 if (newClassPart.startsWith(QLatin1Char('Q')))
229 newClassPart.remove(0, 1);
230
231 QString newName = oldName;
232 newName.replace(oldClassPart, newClassPart);
233 oldClassPart[0] = oldClassPart.at(0).toLower();
234 newClassPart[0] = newClassPart.at(0).toLower();
235 newName.replace(oldClassPart, newClassPart);
236 return newName;
237}
238
239// Find the label whose buddy the widget is.
240QLabel *buddyLabelOf(QDesignerFormWindowInterface *fw, QWidget *w)
241{
242 typedef QList<QLabel*> LabelList;
243 const LabelList labelList = qFindChildren<QLabel*>(fw);
244 if (labelList.empty())
245 return 0;
246 const LabelList::const_iterator cend = labelList.constEnd();
247 for (LabelList::const_iterator it = labelList.constBegin(); it != cend; ++it )
248 if ( (*it)->buddy() == w)
249 return *it;
250 return 0;
251}
252
253// Replace widgets in a widget-list type dynamic property of the parent
254// used for Z-order, etc.
255static void replaceWidgetListDynamicProperty(QWidget *parentWidget,
256 QWidget *oldWidget, QWidget *newWidget,
257 const char *name)
258{
259 QWidgetList list = qVariantValue<QWidgetList>(parentWidget->property(name));
260 const int index = list.indexOf(oldWidget);
261 if (index != -1) {
262 list.replace(index, newWidget);
263 parentWidget->setProperty(name, qVariantFromValue(list));
264 }
265}
266
267/* Morph a widget into another class. Use the static addMorphMacro() to
268 * add a respective command sequence to the undo stack as it emits signals
269 * which cause other commands to be added. */
270class MorphWidgetCommand : public QDesignerFormWindowCommand
271{
272 Q_DISABLE_COPY(MorphWidgetCommand)
273public:
274
275 explicit MorphWidgetCommand(QDesignerFormWindowInterface *formWindow);
276 ~MorphWidgetCommand();
277
278 // Convenience to add a morph command sequence macro
279 static bool addMorphMacro(QDesignerFormWindowInterface *formWindow, QWidget *w, const QString &newClass);
280
281 bool init(QWidget *widget, const QString &newClass);
282
283 QString newWidgetName() const { return m_afterWidget->objectName(); }
284
285 virtual void redo();
286 virtual void undo();
287
288 static QStringList candidateClasses(QDesignerFormWindowInterface *fw, QWidget *w);
289
290private:
291 static bool canMorph(QDesignerFormWindowInterface *fw, QWidget *w, int *childContainerCount = 0, MorphCategory *cat = 0);
292 void morph(QWidget *before, QWidget *after);
293
294 QWidget *m_beforeWidget;
295 QWidget *m_afterWidget;
296};
297
298bool MorphWidgetCommand::addMorphMacro(QDesignerFormWindowInterface *fw, QWidget *w, const QString &newClass)
299{
300 MorphWidgetCommand *morphCmd = new MorphWidgetCommand(fw);
301 if (!morphCmd->init(w, newClass)) {
302 qWarning("*** Unable to create a MorphWidgetCommand");
303 delete morphCmd;
304 return false;
305 }
306 QLabel *buddyLabel = buddyLabelOf(fw, w);
307 // Need a macro since it adds further commands
308 QUndoStack *us = fw->commandHistory();
309 us->beginMacro(morphCmd->text());
310 // Have the signal slot/buddy editors add their commands to delete widget
311 if (FormWindowBase *fwb = qobject_cast<FormWindowBase*>(fw))
312 fwb->emitWidgetRemoved(w);
313
314 const QString newWidgetName = morphCmd->newWidgetName();
315 us->push(morphCmd);
316
317 // restore buddy using the QByteArray name.
318 if (buddyLabel) {
319 SetPropertyCommand *buddyCmd = new SetPropertyCommand(fw);
320 buddyCmd->init(buddyLabel, QLatin1String("buddy"), QVariant(newWidgetName.toUtf8()));
321 us->push(buddyCmd);
322 }
323 us->endMacro();
324 return true;
325}
326
327MorphWidgetCommand::MorphWidgetCommand(QDesignerFormWindowInterface *formWindow) :
328 QDesignerFormWindowCommand(QString(), formWindow),
329 m_beforeWidget(0),
330 m_afterWidget(0)
331{
332}
333
334MorphWidgetCommand::~MorphWidgetCommand()
335{
336}
337
338bool MorphWidgetCommand::init(QWidget *widget, const QString &newClassName)
339{
340 QDesignerFormWindowInterface *fw = formWindow();
341 QDesignerFormEditorInterface *core = fw->core();
342
343 if (!canMorph(fw, widget))
344 return false;
345
346 const QString oldClassName = WidgetFactory::classNameOf(core, widget);
347 const QString oldName = widget->objectName();
348 //: MorphWidgetCommand description
349 setText(QApplication::translate("Command", "Morph %1/'%2' into %3").arg(oldClassName, oldName, newClassName));
350
351 m_beforeWidget = widget;
352 m_afterWidget = core->widgetFactory()->createWidget(newClassName, fw);
353 if (!m_afterWidget)
354 return false;
355
356 // Set object name. Do not unique it (as to maintain it).
357 m_afterWidget->setObjectName(suggestObjectName(oldClassName, newClassName, oldName));
358
359 // If the target has a container extension, we add enough new pages to take
360 // up the children of the before widget
361 if (QDesignerContainerExtension* c = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), m_afterWidget)) {
362 if (const int pageCount = childContainers(core, m_beforeWidget).size()) {
363 const QString qWidget = QLatin1String("QWidget");
364 const QString containerName = m_afterWidget->objectName();
365 for (int i = 0; i < pageCount; i++) {
366 QString name = containerName;
367 name += QLatin1String("Page");
368 name += QString::number(i + 1);
369 QWidget *page = core->widgetFactory()->createWidget(qWidget);
370 page->setObjectName(name);
371 fw->ensureUniqueObjectName(page);
372 c->addWidget(page);
373 core->metaDataBase()->add(page);
374 }
375 }
376 }
377
378 // Copy over applicable properties
379 const QDesignerPropertySheetExtension *beforeSheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), widget);
380 QDesignerPropertySheetExtension *afterSheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), m_afterWidget);
381 const QString objectNameProperty = QLatin1String("objectName");
382 const int count = beforeSheet->count();
383 for (int i = 0; i < count; i++)
384 if (beforeSheet->isVisible(i) && beforeSheet->isChanged(i)) {
385 const QString name = beforeSheet->propertyName(i);
386 if (name != objectNameProperty) {
387 const int afterIndex = afterSheet->indexOf(name);
388 if (afterIndex != -1 && afterSheet->isVisible(afterIndex) && afterSheet->propertyGroup(afterIndex) == beforeSheet->propertyGroup(i)) {
389 afterSheet->setProperty(i, beforeSheet->property(i));
390 afterSheet->setChanged(i, true);
391 } else {
392 // Some mismatch. The rest won't match, either
393 break;
394 }
395 }
396 }
397 return true;
398}
399
400void MorphWidgetCommand::redo()
401{
402 morph(m_beforeWidget, m_afterWidget);
403}
404
405void MorphWidgetCommand::undo()
406{
407 morph(m_afterWidget, m_beforeWidget);
408}
409
410void MorphWidgetCommand::morph(QWidget *before, QWidget *after)
411{
412 QDesignerFormWindowInterface *fw = formWindow();
413
414 fw->unmanageWidget(before);
415
416 const QRect oldGeom = before->geometry();
417 QWidget *parent = before->parentWidget();
418 Q_ASSERT(parent);
419 /* Morphing consists of main 2 steps
420 * 1) Move over children (laid out, non-laid out)
421 * 2) Register self with new parent (laid out, non-laid out) */
422
423 // 1) Move children. Loop over child containers
424 QWidgetList beforeChildContainers = childContainers(fw->core(), before);
425 QWidgetList afterChildContainers = childContainers(fw->core(), after);
426 Q_ASSERT(beforeChildContainers.size() == afterChildContainers.size());
427 const int childContainerCount = beforeChildContainers.size();
428 for (int i = 0; i < childContainerCount; i++) {
429 QWidget *beforeChildContainer = beforeChildContainers.at(i);
430 QWidget *afterChildContainer = afterChildContainers.at(i);
431 if (QLayout *childLayout = beforeChildContainer->layout()) {
432 // Laid-out: Move the layout (since 4.5)
433 afterChildContainer->setLayout(childLayout);
434 } else {
435 // Non-Laid-out: Reparent, move over
436 const QObjectList c = beforeChildContainer->children();
437 const QObjectList::const_iterator cend = c.constEnd();
438 for (QObjectList::const_iterator it = c.constBegin(); it != cend; ++it) {
439 if ( (*it)->isWidgetType()) {
440 QWidget *w = static_cast<QWidget*>(*it);
441 if (fw->isManaged(w)) {
442 const QRect geom = w->geometry();
443 w->setParent(afterChildContainer);
444 w->setGeometry(geom);
445 }
446 }
447 }
448 }
449 afterChildContainer->setProperty(widgetOrderPropertyC, beforeChildContainer->property(widgetOrderPropertyC));
450 afterChildContainer->setProperty(zOrderPropertyC, beforeChildContainer->property(zOrderPropertyC));
451 }
452
453 // 2) Replace the actual widget in the parent layout
454 after->setGeometry(oldGeom);
455 if (QLayout *containingLayout = LayoutInfo::managedLayout(fw->core(), parent)) {
456 LayoutHelper *lh = LayoutHelper::createLayoutHelper(LayoutInfo::layoutType(fw->core(), containingLayout));
457 Q_ASSERT(lh);
458 lh->replaceWidget(containingLayout, before, after);
459 delete lh;
460 } else {
461 before->hide();
462 before->setParent(0);
463 after->setParent(parent);
464 after->setGeometry(oldGeom);
465 }
466
467 // Check various properties: Z order, form tab order
468 replaceWidgetListDynamicProperty(parent, before, after, widgetOrderPropertyC);
469 replaceWidgetListDynamicProperty(parent, before, after, zOrderPropertyC);
470
471 QDesignerMetaDataBaseItemInterface *formItem = fw->core()->metaDataBase()->item(fw);
472 QWidgetList tabOrder = formItem->tabOrder();
473 const int tabIndex = tabOrder.indexOf(before);
474 if (tabIndex != -1) {
475 tabOrder.replace(tabIndex, after);
476 formItem->setTabOrder(tabOrder);
477 }
478
479 after->show();
480 fw->manageWidget(after);
481
482 fw->clearSelection(false);
483 fw->selectWidget(after);
484}
485
486/* Check if morphing is possible. It must be a valid category and the parent/
487 * child relationships must be either non-laidout or directly on
488 * Designer-managed layouts. */
489bool MorphWidgetCommand::canMorph(QDesignerFormWindowInterface *fw, QWidget *w, int *ptrToChildContainerCount, MorphCategory *ptrToCat)
490{
491 if (ptrToChildContainerCount)
492 *ptrToChildContainerCount = 0;
493 const MorphCategory cat = category(w);
494 if (ptrToCat)
495 *ptrToCat = cat;
496 if (cat == MorphCategoryNone)
497 return false;
498
499 QDesignerFormEditorInterface *core = fw->core();
500 // Don't know how to fiddle class names in Jambi..
501 if (qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core))
502 return false;
503 if (!fw->isManaged(w) || w == fw->mainContainer())
504 return false;
505 // Check the parent relationship. We accept only managed parent widgets
506 // with a single, managed layout in which widget is a member.
507 QWidget *parent = w->parentWidget();
508 if (parent == 0)
509 return false;
510 if (QLayout *pl = LayoutInfo::managedLayout(core, parent))
511 if (pl->indexOf(w) < 0 || !core->metaDataBase()->item(pl))
512 return false;
513 // Check Widget database
514 const QDesignerWidgetDataBaseInterface *wdb = core->widgetDataBase();
515 const int wdbindex = wdb->indexOfObject(w);
516 if (wdbindex == -1)
517 return false;
518 const bool isContainer = wdb->item(wdbindex)->isContainer();
519 if (!isContainer)
520 return true;
521 // Check children. All child containers must be non-laid-out or have managed layouts
522 const QWidgetList pages = childContainers(core, w);
523 const int pageCount = pages.size();
524 if (ptrToChildContainerCount)
525 *ptrToChildContainerCount = pageCount;
526 if (pageCount) {
527 for (int i = 0; i < pageCount; i++)
528 if (QLayout *cl = pages.at(i)->layout())
529 if (!core->metaDataBase()->item(cl))
530 return false;
531 }
532 return true;
533}
534
535QStringList MorphWidgetCommand::candidateClasses(QDesignerFormWindowInterface *fw, QWidget *w)
536{
537 int childContainerCount;
538 MorphCategory cat;
539 if (!canMorph(fw, w, &childContainerCount, &cat))
540 return QStringList();
541
542 QStringList rc = classesOfCategory(cat);
543 switch (cat) {
544 // Frames, etc can always be morphed into one-page page containers
545 case MorphSimpleContainer:
546 rc += classesOfCategory(MorphPageContainer);
547 break;
548 // Multipage-Containers can be morphed into simple containers if they
549 // have 1 page.
550 case MorphPageContainer:
551 if (childContainerCount == 1)
552 rc += classesOfCategory(MorphSimpleContainer);
553 break;
554 default:
555 break;
556 }
557 return rc;
558}
559
560// MorphMenu
561MorphMenu::MorphMenu(QObject *parent) :
562 QObject(parent),
563 m_subMenuAction(0),
564 m_menu(0),
565 m_mapper(0),
566 m_widget(0),
567 m_formWindow(0)
568{
569}
570
571void MorphMenu::populate(QWidget *w, QDesignerFormWindowInterface *fw, ActionList& al)
572{
573 if (populateMenu(w, fw))
574 al.push_back(m_subMenuAction);
575}
576
577void MorphMenu::populate(QWidget *w, QDesignerFormWindowInterface *fw, QMenu& m)
578{
579 if (populateMenu(w, fw))
580 m.addAction(m_subMenuAction);
581}
582
583void MorphMenu::slotMorph(const QString &newClassName)
584{
585 MorphWidgetCommand::addMorphMacro(m_formWindow, m_widget, newClassName);
586}
587
588bool MorphMenu::populateMenu(QWidget *w, QDesignerFormWindowInterface *fw)
589{
590 m_widget = 0;
591 m_formWindow = 0;
592
593 // Clear menu
594 if (m_subMenuAction) {
595 m_subMenuAction->setVisible(false);
596 m_menu->clear();
597 }
598
599 // Checks: Must not be main container
600 if (w == fw->mainContainer())
601 return false;
602
603 const QStringList c = MorphWidgetCommand::candidateClasses(fw, w);
604 if (c.empty())
605 return false;
606
607 // Pull up
608 m_widget = w;
609 m_formWindow = fw;
610 const QString oldClassName = WidgetFactory::classNameOf(fw->core(), w);
611
612 if (!m_subMenuAction) {
613 m_subMenuAction = new QAction(tr("Morph into"), this);
614 m_menu = new QMenu;
615 m_subMenuAction->setMenu(m_menu);
616 m_mapper = new QSignalMapper(this);
617 connect(m_mapper , SIGNAL(mapped(QString)), this, SLOT(slotMorph(QString)));
618 }
619
620 // Add actions
621 const QStringList::const_iterator cend = c.constEnd();
622 for (QStringList::const_iterator it = c.constBegin(); it != cend; ++it) {
623 if (*it != oldClassName) {
624 QAction *a = m_menu->addAction(*it);
625 m_mapper->setMapping (a, *it);
626 connect(a, SIGNAL(triggered()), m_mapper, SLOT(map()));
627 }
628 }
629 m_subMenuAction->setVisible(true);
630 return true;
631}
632
633} // namespace qdesigner_internal
634
635QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.