source: trunk/tools/designer/src/lib/shared/qdesigner_integration.cpp

Last change on this file 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: 17.0 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 "qdesigner_integration_p.h"
43#include "qdesigner_propertycommand_p.h"
44#include "qdesigner_propertyeditor_p.h"
45#include "qdesigner_objectinspector_p.h"
46#include "widgetdatabase_p.h"
47#include "pluginmanager_p.h"
48#include "widgetfactory_p.h"
49#include "qdesigner_widgetbox_p.h"
50#include "qtgradientmanager.h"
51#include "qtgradientutils.h"
52#include "qtresourcemodel_p.h"
53
54// sdk
55#include <QtDesigner/QDesignerFormEditorInterface>
56#include <QtDesigner/QDesignerFormWindowInterface>
57#include <QtDesigner/QDesignerFormWindowManagerInterface>
58#include <QtDesigner/QDesignerFormWindowCursorInterface>
59#include <QtDesigner/QDesignerActionEditorInterface>
60#include <QtDesigner/QDesignerWidgetBoxInterface>
61#include <QtDesigner/QExtensionManager>
62#include <QtDesigner/QDesignerResourceBrowserInterface>
63#include <QtDesigner/QDesignerPropertySheetExtension>
64
65#include <QtCore/QVariant>
66#include <QtCore/QFile>
67#include <QtCore/QDir>
68
69#include <QtCore/qdebug.h>
70
71QT_BEGIN_NAMESPACE
72
73namespace qdesigner_internal {
74
75// ---------------- DesignerIntegrationPrivate
76class QDesignerIntegrationPrivate {
77public:
78 QDesignerIntegrationPrivate()
79 : m_gradientManager(0),
80 m_fileWatcherBehaviour(QDesignerIntegration::PromptAndReload),
81 m_resourceEditingEnabled(true),
82 m_slotNavigationEnabled(false)
83 {}
84
85 QString m_gradientsPath;
86 QtGradientManager *m_gradientManager;
87 QDesignerIntegration::ResourceFileWatcherBehaviour m_fileWatcherBehaviour;
88 bool m_resourceEditingEnabled;
89 bool m_slotNavigationEnabled;
90};
91
92// -------------- QDesignerIntegration
93// As of 4.4, the header will be distributed with the Eclipse plugin.
94
95QDesignerIntegration::QDesignerIntegration(QDesignerFormEditorInterface *core, QObject *parent) :
96 QDesignerIntegrationInterface(core, parent),
97 m_d(new QDesignerIntegrationPrivate)
98{
99 initialize();
100}
101
102QDesignerIntegration::~QDesignerIntegration()
103{
104 QFile f(m_d->m_gradientsPath);
105 if (f.open(QIODevice::WriteOnly)) {
106 f.write(QtGradientUtils::saveState(m_d->m_gradientManager).toUtf8());
107 f.close();
108 }
109 delete m_d;
110}
111
112void QDesignerIntegration::initialize()
113{
114 //
115 // integrate the `Form Editor component'
116 //
117
118 // Extensions
119 if (QDesignerPropertyEditor *designerPropertyEditor= qobject_cast<QDesignerPropertyEditor *>(core()->propertyEditor())) {
120 connect(designerPropertyEditor, SIGNAL(propertyValueChanged(QString,QVariant,bool)), this, SLOT(updateProperty(QString,QVariant,bool)));
121 connect(designerPropertyEditor, SIGNAL(resetProperty(QString)), this, SLOT(resetProperty(QString)));
122 connect(designerPropertyEditor, SIGNAL(addDynamicProperty(QString,QVariant)),
123 this, SLOT(addDynamicProperty(QString,QVariant)));
124 connect(designerPropertyEditor, SIGNAL(removeDynamicProperty(QString)),
125 this, SLOT(removeDynamicProperty(QString)));
126 } else {
127 connect(core()->propertyEditor(), SIGNAL(propertyChanged(QString,QVariant)),
128 this, SLOT(updatePropertyPrivate(QString,QVariant)));
129 }
130
131 connect(core()->formWindowManager(), SIGNAL(formWindowAdded(QDesignerFormWindowInterface*)),
132 this, SLOT(setupFormWindow(QDesignerFormWindowInterface*)));
133
134 connect(core()->formWindowManager(), SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)),
135 this, SLOT(updateActiveFormWindow(QDesignerFormWindowInterface*)));
136
137 m_d->m_gradientManager = new QtGradientManager(this);
138 core()->setGradientManager(m_d->m_gradientManager);
139
140 QString designerFolder = QDir::homePath();
141 designerFolder += QDir::separator();
142 designerFolder += QLatin1String(".designer");
143 m_d->m_gradientsPath = designerFolder;
144 m_d->m_gradientsPath += QDir::separator();
145 m_d->m_gradientsPath += QLatin1String("gradients.xml");
146
147 QFile f(m_d->m_gradientsPath);
148 if (f.open(QIODevice::ReadOnly)) {
149 QtGradientUtils::restoreState(m_d->m_gradientManager, QString::fromAscii(f.readAll()));
150 f.close();
151 } else {
152 QFile defaultGradients(QLatin1String(":/trolltech/designer/defaultgradients.xml"));
153 if (defaultGradients.open(QIODevice::ReadOnly)) {
154 QtGradientUtils::restoreState(m_d->m_gradientManager, QString::fromAscii(defaultGradients.readAll()));
155 defaultGradients.close();
156 }
157 }
158
159 if (WidgetDataBase *widgetDataBase = qobject_cast<WidgetDataBase*>(core()->widgetDataBase()))
160 widgetDataBase->grabStandardWidgetBoxIcons();
161}
162
163void QDesignerIntegration::updateProperty(const QString &name, const QVariant &value, bool enableSubPropertyHandling)
164{
165 QDesignerFormWindowInterface *formWindow = core()->formWindowManager()->activeFormWindow();
166 if (!formWindow)
167 return;
168
169 Selection selection;
170 getSelection(selection);
171 if (selection.empty())
172 return;
173
174 SetPropertyCommand *cmd = new SetPropertyCommand(formWindow);
175 // find a reference object to compare to and to find the right group
176 if (cmd->init(selection.selection(), name, value, propertyEditorObject(), enableSubPropertyHandling)) {
177 formWindow->commandHistory()->push(cmd);
178 } else {
179 delete cmd;
180 qDebug() << "Unable to set property " << name << '.';
181 }
182
183 emit propertyChanged(formWindow, name, value);
184}
185
186void QDesignerIntegration::updatePropertyPrivate(const QString &name, const QVariant &value)
187{
188 updateProperty(name, value, true);
189}
190
191void QDesignerIntegration::resetProperty(const QString &name)
192{
193 QDesignerFormWindowInterface *formWindow = core()->formWindowManager()->activeFormWindow();
194 if (!formWindow)
195 return;
196
197 Selection selection;
198 getSelection(selection);
199 if (selection.empty())
200 return;
201
202
203 ResetPropertyCommand *cmd = new ResetPropertyCommand(formWindow);
204 // find a reference object to find the right group
205 if (cmd->init(selection.selection(), name, propertyEditorObject())) {
206 formWindow->commandHistory()->push(cmd);
207 } else {
208 delete cmd;
209 qDebug() << "** WARNING Unable to reset property " << name << '.';
210 }
211}
212
213void QDesignerIntegration::addDynamicProperty(const QString &name, const QVariant &value)
214{
215 QDesignerFormWindowInterface *formWindow = core()->formWindowManager()->activeFormWindow();
216 if (!formWindow)
217 return;
218
219 Selection selection;
220 getSelection(selection);
221 if (selection.empty())
222 return;
223
224 AddDynamicPropertyCommand *cmd = new AddDynamicPropertyCommand(formWindow);
225 if (cmd->init(selection.selection(), propertyEditorObject(), name, value)) {
226 formWindow->commandHistory()->push(cmd);
227 } else {
228 delete cmd;
229 qDebug() << "** WARNING Unable to add dynamic property " << name << '.';
230 }
231}
232
233void QDesignerIntegration::removeDynamicProperty(const QString &name)
234{
235 QDesignerFormWindowInterface *formWindow = core()->formWindowManager()->activeFormWindow();
236 if (!formWindow)
237 return;
238
239 Selection selection;
240 getSelection(selection);
241 if (selection.empty())
242 return;
243
244 RemoveDynamicPropertyCommand *cmd = new RemoveDynamicPropertyCommand(formWindow);
245 if (cmd->init(selection.selection(), propertyEditorObject(), name)) {
246 formWindow->commandHistory()->push(cmd);
247 } else {
248 delete cmd;
249 qDebug() << "** WARNING Unable to remove dynamic property " << name << '.';
250 }
251
252}
253
254
255void QDesignerIntegration::updateActiveFormWindow(QDesignerFormWindowInterface *formWindow)
256{
257 Q_UNUSED(formWindow);
258 updateSelection();
259}
260
261void QDesignerIntegration::setupFormWindow(QDesignerFormWindowInterface *formWindow)
262{
263 connect(formWindow, SIGNAL(selectionChanged()), this, SLOT(updateSelection()));
264 connect(formWindow, SIGNAL(activated(QWidget*)), this, SLOT(activateWidget(QWidget*)));
265}
266
267void QDesignerIntegration::updateGeometry()
268{
269}
270
271void QDesignerIntegration::updateSelection()
272{
273 QDesignerFormWindowInterface *formWindow = core()->formWindowManager()->activeFormWindow();
274 QWidget *selection = 0;
275
276 if (formWindow) {
277 selection = formWindow->cursor()->current();
278 }
279
280 if (QDesignerActionEditorInterface *actionEditor = core()->actionEditor())
281 actionEditor->setFormWindow(formWindow);
282
283 if (QDesignerPropertyEditorInterface *propertyEditor = core()->propertyEditor())
284 propertyEditor->setObject(selection);
285
286 if (QDesignerObjectInspectorInterface *objectInspector = core()->objectInspector())
287 objectInspector->setFormWindow(formWindow);
288
289}
290
291void QDesignerIntegration::activateWidget(QWidget *widget)
292{
293 Q_UNUSED(widget);
294}
295
296QWidget *QDesignerIntegration::containerWindow(QWidget *widget) const
297{
298 // Find the parent window to apply a geometry to.
299 while (widget) {
300 if (widget->isWindow())
301 break;
302 if (!qstrcmp(widget->metaObject()->className(), "QMdiSubWindow"))
303 break;
304
305 widget = widget->parentWidget();
306 }
307
308 return widget;
309}
310
311void QDesignerIntegration::getSelection(Selection &s)
312{
313 // Get multiselection from object inspector
314 if (QDesignerObjectInspector *designerObjectInspector = qobject_cast<QDesignerObjectInspector *>(core()->objectInspector())) {
315 designerObjectInspector->getSelection(s);
316 // Action editor puts actions that are not on the form yet
317 // into the property editor only.
318 if (s.empty())
319 if (QObject *object = core()->propertyEditor()->object())
320 s.objects.push_back(object);
321
322 } else {
323 // Just in case someone plugs in an old-style object inspector: Emulate selection
324 s.clear();
325 QDesignerFormWindowInterface *formWindow = core()->formWindowManager()->activeFormWindow();
326 if (!formWindow)
327 return;
328
329 QObject *object = core()->propertyEditor()->object();
330 if (object->isWidgetType()) {
331 QWidget *widget = static_cast<QWidget*>(object);
332 QDesignerFormWindowCursorInterface *cursor = formWindow->cursor();
333 if (cursor->isWidgetSelected(widget)) {
334 s.managed.push_back(widget);
335 } else {
336 s.unmanaged.push_back(widget);
337 }
338 } else {
339 s.objects.push_back(object);
340 }
341 }
342}
343
344QObject *QDesignerIntegration::propertyEditorObject()
345{
346 QDesignerPropertyEditorInterface *propertyEditor = core()->propertyEditor();
347 if (!propertyEditor)
348 return 0;
349 return propertyEditor->object();
350}
351
352// Load plugins into widget database and factory.
353void QDesignerIntegration::initializePlugins(QDesignerFormEditorInterface *formEditor)
354{
355 // load the plugins
356 WidgetDataBase *widgetDataBase = qobject_cast<WidgetDataBase*>(formEditor->widgetDataBase());
357 if (widgetDataBase) {
358 widgetDataBase->loadPlugins();
359 }
360
361 if (WidgetFactory *widgetFactory = qobject_cast<WidgetFactory*>(formEditor->widgetFactory())) {
362 widgetFactory->loadPlugins();
363 }
364
365 if (widgetDataBase) {
366 widgetDataBase->grabDefaultPropertyValues();
367 }
368}
369
370void QDesignerIntegration::updateCustomWidgetPlugins()
371{
372 QDesignerFormEditorInterface *formEditor = core();
373 if (QDesignerPluginManager *pm = formEditor->pluginManager())
374 pm->registerNewPlugins();
375
376 initializePlugins(formEditor);
377
378 // Do not just reload the last file as the WidgetBox merges the compiled-in resources
379 // and $HOME/.designer/widgetbox.xml. This would also double the scratchpad.
380 if (QDesignerWidgetBox *wb = qobject_cast<QDesignerWidgetBox*>(formEditor->widgetBox())) {
381 const QDesignerWidgetBox::LoadMode oldLoadMode = wb->loadMode();
382 wb->setLoadMode(QDesignerWidgetBox::LoadCustomWidgetsOnly);
383 wb->load();
384 wb->setLoadMode(oldLoadMode);
385 }
386}
387
388void QDesignerIntegration::emitObjectNameChanged(QDesignerFormWindowInterface *formWindow, QObject *object, const QString &newName, const QString &oldName)
389{
390 emit objectNameChanged(formWindow, object, newName, oldName);
391}
392
393void QDesignerIntegration::emitNavigateToSlot(const QString &objectName,
394 const QString &signalSignature,
395 const QStringList &parameterNames)
396{
397 emit navigateToSlot(objectName, signalSignature, parameterNames);
398}
399
400void QDesignerIntegration::emitNavigateToSlot(const QString &slotSignature)
401{
402 emit navigateToSlot(slotSignature);
403}
404
405void QDesignerIntegration::requestHelp(const QDesignerFormEditorInterface *core, const QString &manual, const QString &document)
406{
407 if (QDesignerIntegration *di = qobject_cast<QDesignerIntegration *>(core->integration()))
408 emit di->helpRequested(manual, document);
409}
410
411QDesignerResourceBrowserInterface *QDesignerIntegration::createResourceBrowser(QWidget *)
412{
413 return 0;
414}
415
416void QDesignerIntegration::setResourceFileWatcherBehaviour(ResourceFileWatcherBehaviour behaviour)
417{
418 m_d->m_fileWatcherBehaviour = behaviour;
419 core()->resourceModel()->setWatcherEnabled(behaviour != QDesignerIntegration::NoWatcher);
420}
421
422QDesignerIntegration::ResourceFileWatcherBehaviour QDesignerIntegration::resourceFileWatcherBehaviour() const
423{
424 return m_d->m_fileWatcherBehaviour;
425}
426
427void QDesignerIntegration::setResourceEditingEnabled(bool enable)
428{
429 m_d->m_resourceEditingEnabled = enable;
430}
431
432bool QDesignerIntegration::isResourceEditingEnabled() const
433{
434 return m_d->m_resourceEditingEnabled;
435}
436
437void QDesignerIntegration::setSlotNavigationEnabled(bool enable)
438{
439 m_d->m_slotNavigationEnabled = enable;
440}
441
442bool QDesignerIntegration::isSlotNavigationEnabled() const
443{
444 return m_d->m_slotNavigationEnabled;
445}
446
447static QString fixHelpClassName(const QString &className)
448{
449 // ### generalize using the Widget Data Base
450 if (className == QLatin1String("Line"))
451 return QLatin1String("QFrame");
452 if (className == QLatin1String("Spacer"))
453 return QLatin1String("QSpacerItem");
454 if (className == QLatin1String("QLayoutWidget"))
455 return QLatin1String("QLayout");
456 return className;
457}
458
459// Return class in which the property is defined
460static QString classForProperty(QDesignerFormEditorInterface *core,
461 QObject *object,
462 const QString &property)
463{
464 if (const QDesignerPropertySheetExtension *ps = qt_extension<QDesignerPropertySheetExtension *>(core->extensionManager(), object)) {
465 const int index = ps->indexOf(property);
466 if (index >= 0)
467 return ps->propertyGroup(index);
468 }
469 return QString();
470}
471
472QString QDesignerIntegration::contextHelpId() const
473{
474 QObject *currentObject = core()->propertyEditor()->object();
475 if (!currentObject)
476 return QString();
477 // Return a help index id consisting of "class::property"
478 QString className;
479 QString currentPropertyName = core()->propertyEditor()->currentPropertyName();
480 if (!currentPropertyName.isEmpty())
481 className = classForProperty(core(), currentObject, currentPropertyName);
482 if (className.isEmpty()) {
483 currentPropertyName.clear(); // We hit on some fake property.
484 className = WidgetFactory::classNameOf(core(), currentObject);
485 }
486 QString helpId = fixHelpClassName(className);
487 if (!currentPropertyName.isEmpty()) {
488 helpId += QLatin1String("::");
489 helpId += currentPropertyName;
490 }
491 return helpId;
492}
493
494} // namespace qdesigner_internal
495
496QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.