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 "qdesigner_propertyeditor_p.h"
30 #include "pluginmanager_p.h"
31 
32 #include <QtDesigner/abstractformeditor.h>
33 #include <QtDesigner/dynamicpropertysheet.h>
34 #include <QtDesigner/propertysheet.h>
35 #include <QtDesigner/qextensionmanager.h>
36 #include <widgetfactory_p.h>
37 #include <QtWidgets/qaction.h>
38 #include <QtWidgets/qlineedit.h>
39 #include <QtWidgets/qabstractbutton.h>
40 
41 QT_BEGIN_NAMESPACE
42 
43 namespace qdesigner_internal {
44 using StringPropertyParameters = QDesignerPropertyEditor::StringPropertyParameters;
45 // A map of property name to type
46 using PropertyNameTypeMap = QHash<QString, StringPropertyParameters>;
47 
48 // Compile a map of hard-coded string property types
stringPropertyTypes()49 static const PropertyNameTypeMap &stringPropertyTypes()
50 {
51     static PropertyNameTypeMap propertyNameTypeMap;
52     if (propertyNameTypeMap.isEmpty()) {
53         const StringPropertyParameters richtext(ValidationRichText, true);
54         // Accessibility. Both are texts the narrator reads
55         propertyNameTypeMap.insert(QStringLiteral("accessibleDescription"), richtext);
56         propertyNameTypeMap.insert(QStringLiteral("accessibleName"), richtext);
57         // object names
58         const StringPropertyParameters objectName(ValidationObjectName, false);
59         propertyNameTypeMap.insert(QStringLiteral("buddy"), objectName);
60         propertyNameTypeMap.insert(QStringLiteral("currentItemName"), objectName);
61         propertyNameTypeMap.insert(QStringLiteral("currentPageName"), objectName);
62         propertyNameTypeMap.insert(QStringLiteral("currentTabName"), objectName);
63         propertyNameTypeMap.insert(QStringLiteral("layoutName"), objectName);
64         propertyNameTypeMap.insert(QStringLiteral("spacerName"), objectName);
65         // Style sheet
66         propertyNameTypeMap.insert(QStringLiteral("styleSheet"), StringPropertyParameters(ValidationStyleSheet, false));
67         // Buttons/  QCommandLinkButton
68         const StringPropertyParameters multiline(ValidationMultiLine, true);
69         propertyNameTypeMap.insert(QStringLiteral("description"), multiline);
70         propertyNameTypeMap.insert(QStringLiteral("iconText"), multiline);
71         // Tooltips, etc.
72         propertyNameTypeMap.insert(QStringLiteral("toolTip"), richtext);
73         propertyNameTypeMap.insert(QStringLiteral("whatsThis"), richtext);
74         propertyNameTypeMap.insert(QStringLiteral("windowIconText"), richtext);
75         propertyNameTypeMap.insert(QStringLiteral("html"), richtext);
76         //  A QWizard page id
77         propertyNameTypeMap.insert(QStringLiteral("pageId"), StringPropertyParameters(ValidationSingleLine, false));
78         // QPlainTextEdit
79         propertyNameTypeMap.insert(QStringLiteral("plainText"), StringPropertyParameters(ValidationMultiLine, true));
80     }
81     return propertyNameTypeMap;
82 }
83 
QDesignerPropertyEditor(QWidget * parent,Qt::WindowFlags flags)84 QDesignerPropertyEditor::QDesignerPropertyEditor(QWidget *parent, Qt::WindowFlags flags) :
85     QDesignerPropertyEditorInterface(parent, flags)
86 {
87     // Make old signal work for  compatibility
88     connect(this, &QDesignerPropertyEditorInterface::propertyChanged,
89             this, &QDesignerPropertyEditor::slotPropertyChanged);
90 }
91 
isDynamicProperty(QDesignerFormEditorInterface * core,QObject * object,const QString & propertyName)92 static inline bool isDynamicProperty(QDesignerFormEditorInterface *core, QObject *object,
93                                      const QString &propertyName)
94 {
95     if (const QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core->extensionManager(), object)) {
96         if (dynamicSheet->dynamicPropertiesAllowed()) {
97             if (QDesignerPropertySheetExtension *propertySheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), object)) {
98                 const int index = propertySheet->indexOf(propertyName);
99                 return index >= 0 && dynamicSheet->isDynamicProperty(index);
100             }
101         }
102     }
103     return false;
104 }
105 
textPropertyValidationMode(QDesignerFormEditorInterface * core,const QObject * object,const QString & propertyName,bool isMainContainer)106 QDesignerPropertyEditor::StringPropertyParameters QDesignerPropertyEditor::textPropertyValidationMode(
107         QDesignerFormEditorInterface *core, const QObject *object,
108         const QString &propertyName, bool isMainContainer)
109 {
110     // object name - no comment
111     if (propertyName == QStringLiteral("objectName")) {
112         const TextPropertyValidationMode vm =  isMainContainer ? ValidationObjectNameScope : ValidationObjectName;
113         return StringPropertyParameters(vm, false);
114     }
115 
116     // Check custom widgets by class.
117     const QString className = WidgetFactory::classNameOf(core, object);
118     const QDesignerCustomWidgetData customData = core->pluginManager()->customWidgetData(className);
119     if (!customData.isNull()) {
120         StringPropertyParameters customType;
121         if (customData.xmlStringPropertyType(propertyName, &customType))
122             return customType;
123     }
124 
125     if (isDynamicProperty(core, const_cast<QObject *>(object), propertyName))
126         return StringPropertyParameters(ValidationMultiLine, true);
127 
128     // Check hardcoded property ames
129    const PropertyNameTypeMap::const_iterator hit = stringPropertyTypes().constFind(propertyName);
130    if (hit != stringPropertyTypes().constEnd())
131        return hit.value();
132 
133     // text: Check according to widget type.
134     if (propertyName == QStringLiteral("text")) {
135         if (qobject_cast<const QAction *>(object) || qobject_cast<const QLineEdit *>(object))
136             return StringPropertyParameters(ValidationSingleLine, true);
137         if (qobject_cast<const QAbstractButton *>(object))
138             return StringPropertyParameters(ValidationMultiLine, true);
139         return StringPropertyParameters(ValidationRichText, true);
140     }
141 
142    // Fuzzy matching
143     if (propertyName.endsWith(QStringLiteral("Name")))
144         return StringPropertyParameters(ValidationSingleLine, true);
145 
146     if (propertyName.endsWith(QStringLiteral("ToolTip")))
147         return StringPropertyParameters(ValidationRichText, true);
148 
149 #ifdef Q_OS_WIN // No translation for the active X "control" property
150     if (propertyName == QStringLiteral("control") && className == QStringLiteral("QAxWidget"))
151         return StringPropertyParameters(ValidationSingleLine, false);
152 #endif
153 
154     // default to single
155     return StringPropertyParameters(ValidationSingleLine, true);
156 }
157 
emitPropertyValueChanged(const QString & name,const QVariant & value,bool enableSubPropertyHandling)158 void QDesignerPropertyEditor::emitPropertyValueChanged(const QString &name, const QVariant &value, bool enableSubPropertyHandling)
159 {
160     // Avoid duplicate signal emission - see below
161     m_propertyChangedForwardingBlocked = true;
162     emit propertyValueChanged(name, value, enableSubPropertyHandling);
163     emit propertyChanged(name, value);
164     m_propertyChangedForwardingBlocked = false;
165 }
166 
slotPropertyChanged(const QString & name,const QVariant & value)167 void QDesignerPropertyEditor::slotPropertyChanged(const QString &name, const QVariant &value)
168 {
169     // Forward signal from Integration using the old interfaces.
170     if (!m_propertyChangedForwardingBlocked)
171         emit propertyValueChanged(name, value, true);
172 }
173 
174 }
175 
176 QT_END_NAMESPACE
177