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 "abstractintegration.h" |
30 | #include "abstractformwindow.h" |
31 | #include "abstractformwindowmanager.h" |
32 | #include "abstractformwindowcursor.h" |
33 | #include "abstractformeditor.h" |
34 | #include "abstractactioneditor.h" |
35 | #include "abstractwidgetbox.h" |
36 | #include "abstractresourcebrowser.h" |
37 | #include "propertysheet.h" |
38 | #include "abstractpropertyeditor.h" |
39 | #include "qextensionmanager.h" |
40 | |
41 | #include <qtresourcemodel_p.h> |
42 | |
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 | #include <QtCore/qvariant.h> |
55 | #include <QtCore/qfile.h> |
56 | #include <QtCore/qdir.h> |
57 | |
58 | #include <QtCore/qdebug.h> |
59 | |
60 | QT_BEGIN_NAMESPACE |
61 | |
62 | /*! |
63 | \class QDesignerIntegrationInterface |
64 | |
65 | \brief The QDesignerIntegrationInterface glues together parts of \QD |
66 | and allows for overwriting functionality for IDE integration. |
67 | |
68 | \internal |
69 | |
70 | \inmodule QtDesigner |
71 | |
72 | \sa QDesignerFormEditorInterface |
73 | */ |
74 | |
75 | /*! |
76 | \enum QDesignerIntegrationInterface::ResourceFileWatcherBehaviour |
77 | |
78 | \internal |
79 | |
80 | This enum describes if and how resource files are watched. |
81 | |
82 | \value NoResourceFileWatcher Do not watch for changes |
83 | \value ReloadResourceFileSilently Reload files silently. |
84 | \value PromptToReloadResourceFile Prompt the user to reload. |
85 | */ |
86 | |
87 | /*! |
88 | \enum QDesignerIntegrationInterface::FeatureFlag |
89 | |
90 | \internal |
91 | |
92 | This enum describes the features that are available and can be |
93 | controlled by the integration. |
94 | |
95 | \value ResourceEditorFeature The resource editor is enabled. |
96 | \value SlotNavigationFeature Provide context menu entry offering 'Go to slot'. |
97 | \value DefaultWidgetActionFeature Trigger the preferred action of |
98 | QDesignerTaskMenuExtension when widget is activated. |
99 | \value DefaultFeature Default for \QD |
100 | |
101 | \sa hasFeature(), features() |
102 | */ |
103 | |
104 | /*! |
105 | \property QDesignerIntegrationInterface::headerSuffix |
106 | |
107 | Returns the suffix of the header of promoted widgets. |
108 | */ |
109 | |
110 | /*! |
111 | \property QDesignerIntegrationInterface::headerLowercase |
112 | |
113 | Returns whether headers of promoted widgets should be lower-cased (as the user types the class name). |
114 | */ |
115 | |
116 | /*! |
117 | \fn virtual void QDesignerIntegrationInterface::updateSelection() |
118 | |
119 | \brief Sets the selected widget of the form window in various components. |
120 | |
121 | \internal |
122 | |
123 | In IDE integrations, the method can be overwritten to move the selection handles |
124 | of the form's main window, should it be selected. |
125 | */ |
126 | |
127 | /*! |
128 | \fn virtual QWidget *QDesignerIntegrationInterface::containerWindow(QWidget *widget) const |
129 | |
130 | \brief Returns the outer window containing a form for applying main container geometries. |
131 | |
132 | \internal |
133 | |
134 | Should be implemented by IDE integrations. |
135 | */ |
136 | |
137 | /*! |
138 | \fn virtual QDesignerResourceBrowserInterface *QDesignerIntegrationInterface::createResourceBrowser(QWidget *parent = 0) |
139 | |
140 | \brief Creates a resource browser depending on IDE integration. |
141 | |
142 | \internal |
143 | |
144 | \note Language integration takes precedence. |
145 | */ |
146 | |
147 | /*! |
148 | \fn virtual void QDesignerIntegrationInterface::updateProperty(const QString &name, const QVariant &value, bool enableSubPropertyHandling) |
149 | |
150 | \brief Triggered by the property editor to update a property value. |
151 | |
152 | \internal |
153 | |
154 | If a different property editor is used, it should invoke this function. |
155 | */ |
156 | |
157 | /*! |
158 | \fn virtual void QDesignerIntegrationInterface::updateProperty(const QString &name, const QVariant &value) |
159 | |
160 | \brief Triggered by the property editor to update a property value without subproperty handling. |
161 | |
162 | \internal |
163 | |
164 | If a different property editor is used, it should invoke this function. |
165 | */ |
166 | |
167 | /*! |
168 | \fn virtual void QDesignerIntegrationInterface::resetProperty(const QString &name) |
169 | |
170 | \brief Triggered by the property editor to reset a property value. |
171 | |
172 | \internal |
173 | |
174 | If a different property editor is used, it should invoke this function. |
175 | */ |
176 | |
177 | /*! |
178 | \fn virtual void QDesignerIntegrationInterface::addDynamicProperty(const QString &name, const QVariant &value) |
179 | |
180 | \brief Triggered by the property editor to add a dynamic property value. |
181 | |
182 | \internal |
183 | |
184 | If a different property editor is used, it should invoke this function. |
185 | */ |
186 | |
187 | /*! |
188 | \fn virtual void QDesignerIntegrationInterface::removeDynamicProperty(const QString &name) |
189 | |
190 | \brief Triggered by the property editor to remove a dynamic property. |
191 | |
192 | \internal |
193 | |
194 | If a different property editor is used, it should invoke this function. |
195 | */ |
196 | |
197 | /*! |
198 | \fn virtual void QDesignerIntegrationInterface::updateActiveFormWindow(QDesignerFormWindowInterface *formWindow) |
199 | |
200 | \brief Sets up the active form window. |
201 | |
202 | \internal |
203 | */ |
204 | |
205 | /*! |
206 | \fn virtual void QDesignerIntegrationInterface::setupFormWindow(QDesignerFormWindowInterface *formWindow) |
207 | |
208 | \brief Sets up the new form window. |
209 | |
210 | \internal |
211 | */ |
212 | |
213 | /*! |
214 | \fn virtual void QDesignerIntegrationInterface::updateCustomWidgetPlugins() |
215 | |
216 | \brief Triggers a reload of the custom widget plugins. |
217 | |
218 | \internal |
219 | */ |
220 | |
221 | class QDesignerIntegrationInterfacePrivate |
222 | { |
223 | public: |
224 | QDesignerIntegrationInterfacePrivate(QDesignerFormEditorInterface *core) : |
225 | m_core(core) {} |
226 | |
227 | QDesignerFormEditorInterface *m_core; |
228 | }; |
229 | |
230 | QDesignerIntegrationInterface::QDesignerIntegrationInterface(QDesignerFormEditorInterface *core, QObject *parent) |
231 | : QObject(parent), d(new QDesignerIntegrationInterfacePrivate(core)) |
232 | { |
233 | core->setIntegration(this); |
234 | } |
235 | |
236 | QDesignerIntegrationInterface::~QDesignerIntegrationInterface() = default; |
237 | |
238 | QDesignerFormEditorInterface *QDesignerIntegrationInterface::core() const |
239 | { |
240 | return d->m_core; |
241 | } |
242 | |
243 | bool QDesignerIntegrationInterface::hasFeature(Feature f) const |
244 | { |
245 | return (features() & f) != 0; |
246 | } |
247 | |
248 | void QDesignerIntegrationInterface::emitObjectNameChanged(QDesignerFormWindowInterface *formWindow, QObject *object, const QString &newName, const QString &oldName) |
249 | { |
250 | emit objectNameChanged(formWindow, object, newName, oldName); |
251 | } |
252 | |
253 | void QDesignerIntegrationInterface::emitNavigateToSlot(const QString &objectName, |
254 | const QString &signalSignature, |
255 | const QStringList ¶meterNames) |
256 | { |
257 | emit navigateToSlot(objectName, signalSignature, parameterNames); |
258 | } |
259 | |
260 | void QDesignerIntegrationInterface::emitNavigateToSlot(const QString &slotSignature) |
261 | { |
262 | emit navigateToSlot(slotSignature); |
263 | } |
264 | |
265 | void QDesignerIntegrationInterface::emitHelpRequested(const QString &manual, const QString &document) |
266 | { |
267 | emit helpRequested(manual, document); |
268 | } |
269 | |
270 | /*! |
271 | \class QDesignerIntegration |
272 | |
273 | \brief The QDesignerIntegration class is \QD's implementation of |
274 | QDesignerIntegrationInterface. |
275 | |
276 | \internal |
277 | |
278 | \inmodule QtDesigner |
279 | |
280 | IDE integrations should register classes derived from QDesignerIntegration |
281 | with QDesignerFormEditorInterface. |
282 | */ |
283 | |
284 | namespace qdesigner_internal { |
285 | |
286 | class QDesignerIntegrationPrivate { |
287 | public: |
288 | explicit QDesignerIntegrationPrivate(QDesignerIntegration *qq); |
289 | |
290 | QWidget *containerWindow(QWidget *widget) const; |
291 | |
292 | // Load plugins into widget database and factory. |
293 | static void initializePlugins(QDesignerFormEditorInterface *formEditor); |
294 | |
295 | QString contextHelpId() const; |
296 | |
297 | void updateProperty(const QString &name, const QVariant &value, bool enableSubPropertyHandling); |
298 | void resetProperty(const QString &name); |
299 | void addDynamicProperty(const QString &name, const QVariant &value); |
300 | void removeDynamicProperty(const QString &name); |
301 | |
302 | void setupFormWindow(QDesignerFormWindowInterface *formWindow); |
303 | void updateSelection(); |
304 | void updateCustomWidgetPlugins(); |
305 | |
306 | void updatePropertyPrivate(const QString &name, const QVariant &value); |
307 | |
308 | void initialize(); |
309 | void getSelection(qdesigner_internal::Selection &s); |
310 | QObject *propertyEditorObject(); |
311 | |
312 | QDesignerIntegration *q; |
313 | QString ; |
314 | bool ; |
315 | QDesignerIntegrationInterface::Feature m_features; |
316 | QDesignerIntegrationInterface::ResourceFileWatcherBehaviour m_resourceFileWatcherBehaviour; |
317 | QString m_gradientsPath; |
318 | QtGradientManager *m_gradientManager; |
319 | }; |
320 | |
321 | QDesignerIntegrationPrivate::QDesignerIntegrationPrivate(QDesignerIntegration *qq) : |
322 | q(qq), |
323 | headerSuffix(QStringLiteral(".h" )), |
324 | headerLowercase(true), |
325 | m_features(QDesignerIntegrationInterface::DefaultFeature), |
326 | m_resourceFileWatcherBehaviour(QDesignerIntegrationInterface::PromptToReloadResourceFile), |
327 | m_gradientManager(nullptr) |
328 | { |
329 | } |
330 | |
331 | void QDesignerIntegrationPrivate::initialize() |
332 | { |
333 | // |
334 | // integrate the `Form Editor component' |
335 | // |
336 | |
337 | // Extensions |
338 | QDesignerFormEditorInterface *core = q->core(); |
339 | if (QDesignerPropertyEditor *designerPropertyEditor= qobject_cast<QDesignerPropertyEditor *>(object: core->propertyEditor())) { |
340 | QObject::connect(sender: designerPropertyEditor, signal: &QDesignerPropertyEditor::propertyValueChanged, |
341 | receiver: q, slot: QOverload<const QString &, const QVariant &, bool>::of(ptr: &QDesignerIntegration::updateProperty)); |
342 | QObject::connect(sender: designerPropertyEditor, signal: &QDesignerPropertyEditor::resetProperty, |
343 | receiver: q, slot: &QDesignerIntegration::resetProperty); |
344 | QObject::connect(sender: designerPropertyEditor, signal: &QDesignerPropertyEditor::addDynamicProperty, |
345 | receiver: q, slot: &QDesignerIntegration::addDynamicProperty); |
346 | QObject::connect(sender: designerPropertyEditor, signal: &QDesignerPropertyEditor::removeDynamicProperty, |
347 | receiver: q, slot: &QDesignerIntegration::removeDynamicProperty); |
348 | } else { |
349 | QObject::connect(sender: core->propertyEditor(), SIGNAL(propertyChanged(QString,QVariant)), |
350 | receiver: q, SLOT(updatePropertyPrivate(QString,QVariant))); // ### fixme: VS Integration leftover? |
351 | } |
352 | |
353 | QObject::connect(sender: core->formWindowManager(), signal: &QDesignerFormWindowManagerInterface::formWindowAdded, |
354 | receiver: q, slot: &QDesignerIntegrationInterface::setupFormWindow); |
355 | |
356 | QObject::connect(sender: core->formWindowManager(), signal: &QDesignerFormWindowManagerInterface::activeFormWindowChanged, |
357 | receiver: q, slot: &QDesignerIntegrationInterface::updateActiveFormWindow); |
358 | |
359 | m_gradientManager = new QtGradientManager(q); |
360 | core->setGradientManager(m_gradientManager); |
361 | |
362 | QString designerFolder = QDir::homePath(); |
363 | designerFolder += QDir::separator(); |
364 | designerFolder += QStringLiteral(".designer" ); |
365 | m_gradientsPath = designerFolder; |
366 | m_gradientsPath += QDir::separator(); |
367 | m_gradientsPath += QStringLiteral("gradients.xml" ); |
368 | |
369 | QFile f(m_gradientsPath); |
370 | if (f.open(flags: QIODevice::ReadOnly)) { |
371 | QtGradientUtils::restoreState(manager: m_gradientManager, state: QString::fromLatin1(str: f.readAll())); |
372 | f.close(); |
373 | } else { |
374 | QFile defaultGradients(QStringLiteral(":/qt-project.org/designer/defaultgradients.xml" )); |
375 | if (defaultGradients.open(flags: QIODevice::ReadOnly)) { |
376 | QtGradientUtils::restoreState(manager: m_gradientManager, state: QString::fromLatin1(str: defaultGradients.readAll())); |
377 | defaultGradients.close(); |
378 | } |
379 | } |
380 | |
381 | if (WidgetDataBase *widgetDataBase = qobject_cast<WidgetDataBase*>(object: core->widgetDataBase())) |
382 | widgetDataBase->grabStandardWidgetBoxIcons(); |
383 | } |
384 | |
385 | void QDesignerIntegrationPrivate::updateProperty(const QString &name, const QVariant &value, bool enableSubPropertyHandling) |
386 | { |
387 | QDesignerFormWindowInterface *formWindow = q->core()->formWindowManager()->activeFormWindow(); |
388 | if (!formWindow) |
389 | return; |
390 | |
391 | Selection selection; |
392 | getSelection(s&: selection); |
393 | if (selection.empty()) |
394 | return; |
395 | |
396 | SetPropertyCommand *cmd = new SetPropertyCommand(formWindow); |
397 | // find a reference object to compare to and to find the right group |
398 | if (cmd->init(list: selection.selection(), propertyName: name, newValue: value, referenceObject: propertyEditorObject(), enableSubPropertyHandling)) { |
399 | formWindow->commandHistory()->push(cmd); |
400 | } else { |
401 | delete cmd; |
402 | qDebug() << "Unable to set property " << name << '.'; |
403 | } |
404 | } |
405 | |
406 | void QDesignerIntegrationPrivate::resetProperty(const QString &name) |
407 | { |
408 | QDesignerFormWindowInterface *formWindow = q->core()->formWindowManager()->activeFormWindow(); |
409 | if (!formWindow) |
410 | return; |
411 | |
412 | Selection selection; |
413 | getSelection(s&: selection); |
414 | if (selection.empty()) |
415 | return; |
416 | |
417 | ResetPropertyCommand *cmd = new ResetPropertyCommand(formWindow); |
418 | // find a reference object to find the right group |
419 | if (cmd->init(list: selection.selection(), propertyName: name, referenceObject: propertyEditorObject())) { |
420 | formWindow->commandHistory()->push(cmd); |
421 | } else { |
422 | delete cmd; |
423 | qDebug() << "** WARNING Unable to reset property " << name << '.'; |
424 | } |
425 | } |
426 | |
427 | void QDesignerIntegrationPrivate::addDynamicProperty(const QString &name, const QVariant &value) |
428 | { |
429 | QDesignerFormWindowInterface *formWindow = q->core()->formWindowManager()->activeFormWindow(); |
430 | if (!formWindow) |
431 | return; |
432 | |
433 | Selection selection; |
434 | getSelection(s&: selection); |
435 | if (selection.empty()) |
436 | return; |
437 | |
438 | AddDynamicPropertyCommand *cmd = new AddDynamicPropertyCommand(formWindow); |
439 | if (cmd->init(selection: selection.selection(), current: propertyEditorObject(), propertyName: name, value)) { |
440 | formWindow->commandHistory()->push(cmd); |
441 | } else { |
442 | delete cmd; |
443 | qDebug() << "** WARNING Unable to add dynamic property " << name << '.'; |
444 | } |
445 | } |
446 | |
447 | void QDesignerIntegrationPrivate::removeDynamicProperty(const QString &name) |
448 | { |
449 | QDesignerFormWindowInterface *formWindow = q->core()->formWindowManager()->activeFormWindow(); |
450 | if (!formWindow) |
451 | return; |
452 | |
453 | Selection selection; |
454 | getSelection(s&: selection); |
455 | if (selection.empty()) |
456 | return; |
457 | |
458 | RemoveDynamicPropertyCommand *cmd = new RemoveDynamicPropertyCommand(formWindow); |
459 | if (cmd->init(selection: selection.selection(), current: propertyEditorObject(), propertyName: name)) { |
460 | formWindow->commandHistory()->push(cmd); |
461 | } else { |
462 | delete cmd; |
463 | qDebug() << "** WARNING Unable to remove dynamic property " << name << '.'; |
464 | } |
465 | |
466 | } |
467 | |
468 | void QDesignerIntegrationPrivate::setupFormWindow(QDesignerFormWindowInterface *formWindow) |
469 | { |
470 | QObject::connect(sender: formWindow, signal: &QDesignerFormWindowInterface::selectionChanged, |
471 | receiver: q, slot: &QDesignerIntegrationInterface::updateSelection); |
472 | } |
473 | |
474 | void QDesignerIntegrationPrivate::updateSelection() |
475 | { |
476 | QDesignerFormEditorInterface *core = q->core(); |
477 | QDesignerFormWindowInterface *formWindow = core->formWindowManager()->activeFormWindow(); |
478 | QWidget *selection = nullptr; |
479 | |
480 | if (formWindow) { |
481 | selection = formWindow->cursor()->current(); |
482 | } |
483 | |
484 | if (QDesignerActionEditorInterface *actionEditor = core->actionEditor()) |
485 | actionEditor->setFormWindow(formWindow); |
486 | |
487 | if (QDesignerPropertyEditorInterface *propertyEditor = core->propertyEditor()) |
488 | propertyEditor->setObject(selection); |
489 | |
490 | if (QDesignerObjectInspectorInterface *objectInspector = core->objectInspector()) |
491 | objectInspector->setFormWindow(formWindow); |
492 | |
493 | } |
494 | |
495 | QWidget *QDesignerIntegrationPrivate::containerWindow(QWidget *widget) const |
496 | { |
497 | // Find the parent window to apply a geometry to. |
498 | while (widget) { |
499 | if (widget->isWindow()) |
500 | break; |
501 | if (!qstrcmp(str1: widget->metaObject()->className(), str2: "QMdiSubWindow" )) |
502 | break; |
503 | |
504 | widget = widget->parentWidget(); |
505 | } |
506 | |
507 | return widget; |
508 | } |
509 | |
510 | void QDesignerIntegrationPrivate::getSelection(Selection &s) |
511 | { |
512 | QDesignerFormEditorInterface *core = q->core(); |
513 | // Get multiselection from object inspector |
514 | if (QDesignerObjectInspector *designerObjectInspector = qobject_cast<QDesignerObjectInspector *>(object: core->objectInspector())) { |
515 | designerObjectInspector->getSelection(s); |
516 | // Action editor puts actions that are not on the form yet |
517 | // into the property editor only. |
518 | if (s.empty()) |
519 | if (QObject *object = core->propertyEditor()->object()) |
520 | s.objects.push_back(t: object); |
521 | |
522 | } else { |
523 | // Just in case someone plugs in an old-style object inspector: Emulate selection |
524 | s.clear(); |
525 | QDesignerFormWindowInterface *formWindow = core->formWindowManager()->activeFormWindow(); |
526 | if (!formWindow) |
527 | return; |
528 | |
529 | QObject *object = core->propertyEditor()->object(); |
530 | if (object->isWidgetType()) { |
531 | QWidget *widget = static_cast<QWidget*>(object); |
532 | QDesignerFormWindowCursorInterface *cursor = formWindow->cursor(); |
533 | if (cursor->isWidgetSelected(widget)) { |
534 | s.managed.push_back(t: widget); |
535 | } else { |
536 | s.unmanaged.push_back(t: widget); |
537 | } |
538 | } else { |
539 | s.objects.push_back(t: object); |
540 | } |
541 | } |
542 | } |
543 | |
544 | QObject *QDesignerIntegrationPrivate::propertyEditorObject() |
545 | { |
546 | if (QDesignerPropertyEditorInterface *propertyEditor = q->core()->propertyEditor()) |
547 | return propertyEditor->object(); |
548 | return nullptr; |
549 | } |
550 | |
551 | // Load plugins into widget database and factory. |
552 | void QDesignerIntegrationPrivate::initializePlugins(QDesignerFormEditorInterface *formEditor) |
553 | { |
554 | // load the plugins |
555 | qdesigner_internal::WidgetDataBase *widgetDataBase = qobject_cast<qdesigner_internal::WidgetDataBase*>(object: formEditor->widgetDataBase()); |
556 | if (widgetDataBase) { |
557 | widgetDataBase->loadPlugins(); |
558 | } |
559 | |
560 | if (qdesigner_internal::WidgetFactory *widgetFactory = qobject_cast<qdesigner_internal::WidgetFactory*>(object: formEditor->widgetFactory())) { |
561 | widgetFactory->loadPlugins(); |
562 | } |
563 | |
564 | if (widgetDataBase) { |
565 | widgetDataBase->grabDefaultPropertyValues(); |
566 | } |
567 | } |
568 | |
569 | void QDesignerIntegrationPrivate::updateCustomWidgetPlugins() |
570 | { |
571 | QDesignerFormEditorInterface *formEditor = q->core(); |
572 | if (QDesignerPluginManager *pm = formEditor->pluginManager()) |
573 | pm->registerNewPlugins(); |
574 | |
575 | initializePlugins(formEditor); |
576 | |
577 | // Do not just reload the last file as the WidgetBox merges the compiled-in resources |
578 | // and $HOME/.designer/widgetbox.xml. This would also double the scratchpad. |
579 | if (QDesignerWidgetBox *wb = qobject_cast<QDesignerWidgetBox*>(object: formEditor->widgetBox())) { |
580 | const QDesignerWidgetBox::LoadMode oldLoadMode = wb->loadMode(); |
581 | wb->setLoadMode(QDesignerWidgetBox::LoadCustomWidgetsOnly); |
582 | wb->load(); |
583 | wb->setLoadMode(oldLoadMode); |
584 | } |
585 | } |
586 | |
587 | static QString fixHelpClassName(const QString &className) |
588 | { |
589 | // ### generalize using the Widget Data Base |
590 | if (className == QStringLiteral("Line" )) |
591 | return QStringLiteral("QFrame" ); |
592 | if (className == QStringLiteral("Spacer" )) |
593 | return QStringLiteral("QSpacerItem" ); |
594 | if (className == QStringLiteral("QLayoutWidget" )) |
595 | return QStringLiteral("QLayout" ); |
596 | return className; |
597 | } |
598 | |
599 | // Return class in which the property is defined |
600 | static QString classForProperty(QDesignerFormEditorInterface *core, |
601 | QObject *object, |
602 | const QString &property) |
603 | { |
604 | if (const QDesignerPropertySheetExtension *ps = qt_extension<QDesignerPropertySheetExtension *>(manager: core->extensionManager(), object)) { |
605 | const int index = ps->indexOf(name: property); |
606 | if (index >= 0) |
607 | return ps->propertyGroup(index); |
608 | } |
609 | return QString(); |
610 | } |
611 | |
612 | QString QDesignerIntegrationPrivate::contextHelpId() const |
613 | { |
614 | QDesignerFormEditorInterface *core = q->core(); |
615 | QObject *currentObject = core->propertyEditor()->object(); |
616 | if (!currentObject) |
617 | return QString(); |
618 | // Return a help index id consisting of "class::property" |
619 | QString className; |
620 | QString currentPropertyName = core->propertyEditor()->currentPropertyName(); |
621 | if (!currentPropertyName.isEmpty()) |
622 | className = classForProperty(core, object: currentObject, property: currentPropertyName); |
623 | if (className.isEmpty()) { |
624 | currentPropertyName.clear(); // We hit on some fake property. |
625 | className = qdesigner_internal::WidgetFactory::classNameOf(core, o: currentObject); |
626 | } |
627 | QString helpId = fixHelpClassName(className); |
628 | if (!currentPropertyName.isEmpty()) { |
629 | helpId += QStringLiteral("::" ); |
630 | helpId += currentPropertyName; |
631 | } |
632 | return helpId; |
633 | } |
634 | |
635 | } // namespace qdesigner_internal |
636 | |
637 | // -------------- QDesignerIntegration |
638 | // As of 4.4, the header will be distributed with the Eclipse plugin. |
639 | |
640 | QDesignerIntegration::QDesignerIntegration(QDesignerFormEditorInterface *core, QObject *parent) : |
641 | QDesignerIntegrationInterface(core, parent), |
642 | d(new qdesigner_internal::QDesignerIntegrationPrivate(this)) |
643 | { |
644 | d->initialize(); |
645 | } |
646 | |
647 | QDesignerIntegration::~QDesignerIntegration() |
648 | { |
649 | QFile f(d->m_gradientsPath); |
650 | if (f.open(flags: QIODevice::WriteOnly)) { |
651 | f.write(data: QtGradientUtils::saveState(manager: d->m_gradientManager).toUtf8()); |
652 | f.close(); |
653 | } |
654 | } |
655 | |
656 | QString QDesignerIntegration::() const |
657 | { |
658 | return d->headerSuffix; |
659 | } |
660 | |
661 | void QDesignerIntegration::(const QString &) |
662 | { |
663 | d->headerSuffix = headerSuffix; |
664 | } |
665 | |
666 | bool QDesignerIntegration::() const |
667 | { |
668 | return d->headerLowercase; |
669 | } |
670 | |
671 | void QDesignerIntegration::(bool ) |
672 | { |
673 | d->headerLowercase = headerLowercase; |
674 | } |
675 | |
676 | QDesignerIntegrationInterface::Feature QDesignerIntegration::features() const |
677 | { |
678 | return d->m_features; |
679 | } |
680 | |
681 | void QDesignerIntegration::setFeatures(Feature f) |
682 | { |
683 | d->m_features = f; |
684 | } |
685 | |
686 | QDesignerIntegrationInterface::ResourceFileWatcherBehaviour QDesignerIntegration::resourceFileWatcherBehaviour() const |
687 | { |
688 | return d->m_resourceFileWatcherBehaviour; |
689 | } |
690 | |
691 | void QDesignerIntegration::setResourceFileWatcherBehaviour(ResourceFileWatcherBehaviour behaviour) |
692 | { |
693 | if (d->m_resourceFileWatcherBehaviour != behaviour) { |
694 | d->m_resourceFileWatcherBehaviour = behaviour; |
695 | core()->resourceModel()->setWatcherEnabled(behaviour != QDesignerIntegrationInterface::NoResourceFileWatcher); |
696 | } |
697 | } |
698 | |
699 | void QDesignerIntegration::updateProperty(const QString &name, const QVariant &value, bool enableSubPropertyHandling) |
700 | { |
701 | d->updateProperty(name, value, enableSubPropertyHandling); |
702 | emit propertyChanged(formWindow: core()->formWindowManager()->activeFormWindow(), name, value); |
703 | } |
704 | |
705 | void QDesignerIntegration::updateProperty(const QString &name, const QVariant &value) |
706 | { |
707 | updateProperty(name, value, enableSubPropertyHandling: true); |
708 | } |
709 | |
710 | void QDesignerIntegration::resetProperty(const QString &name) |
711 | { |
712 | d->resetProperty(name); |
713 | } |
714 | |
715 | void QDesignerIntegration::addDynamicProperty(const QString &name, const QVariant &value) |
716 | { |
717 | d->addDynamicProperty(name, value); |
718 | } |
719 | |
720 | void QDesignerIntegration::removeDynamicProperty(const QString &name) |
721 | { |
722 | d->removeDynamicProperty(name); |
723 | } |
724 | |
725 | void QDesignerIntegration::updateActiveFormWindow(QDesignerFormWindowInterface *) |
726 | { |
727 | d->updateSelection(); |
728 | } |
729 | |
730 | void QDesignerIntegration::setupFormWindow(QDesignerFormWindowInterface *formWindow) |
731 | { |
732 | d->setupFormWindow(formWindow); |
733 | connect(sender: formWindow, signal: &QDesignerFormWindowInterface::selectionChanged, |
734 | receiver: this, slot: &QDesignerIntegrationInterface::updateSelection); |
735 | } |
736 | |
737 | void QDesignerIntegration::updateSelection() |
738 | { |
739 | d->updateSelection(); |
740 | } |
741 | |
742 | QWidget *QDesignerIntegration::containerWindow(QWidget *widget) const |
743 | { |
744 | return d->containerWindow(widget); |
745 | } |
746 | |
747 | // Load plugins into widget database and factory. |
748 | void QDesignerIntegration::initializePlugins(QDesignerFormEditorInterface *formEditor) |
749 | { |
750 | qdesigner_internal::QDesignerIntegrationPrivate::initializePlugins(formEditor); |
751 | } |
752 | |
753 | void QDesignerIntegration::updateCustomWidgetPlugins() |
754 | { |
755 | d->updateCustomWidgetPlugins(); |
756 | } |
757 | |
758 | QDesignerResourceBrowserInterface *QDesignerIntegration::createResourceBrowser(QWidget *) |
759 | { |
760 | return nullptr; |
761 | } |
762 | |
763 | QString QDesignerIntegration::contextHelpId() const |
764 | { |
765 | return d->contextHelpId(); |
766 | } |
767 | |
768 | QT_END_NAMESPACE |
769 | |