Commit 9ff8979d authored by Eike Ziller's avatar Eike Ziller

Merge remote-tracking branch 'origin/2.7'

Conflicts:
	src/plugins/cpptools/cppchecksymbols.h
	src/plugins/qmldesigner/components/formeditor/resizecontroller.cpp

Change-Id: I887ba071fa637ad44e39bcae581738fa078a6612
parents e6eb0612 567098f2
......@@ -268,16 +268,23 @@
\li \c fieldpagetitle specifies the title of the page.
\li \c field specifies whether the field is mandatory (\c true or
\c false). You can use the value of the \c name field as a
variable in other files (for example, \c {%MESSAGE%}.
\li \c fields specifies the user interface objects on the page.
\li \c fieldcontrol specifies the field. \c class specifies the
field type. You can use interface objects from the QWidget class
to create fields. This example uses QLineEdit to create an input
field.
\li \c field specifies one object. You can use a set of interface objects
from QtWidgets classes, derived from QWidget, to create fields. This example
uses QLineEdit to create an input field. For more information about the objects
that you can add, see \l {Supported Widgets}.
\li \c validator specifies a regular expression to check the
\li \c mandatory specifies whether the field is mandatory (\c true or
\c false). For more information, see QWizardPage::registerField().
\li \c name specifies a name that you can use as a placeholder variable in the
template file (for example, \c {%MESSAGE%}).
\li \c class specifies the type of the \c fieldcontrol. The XML attributes that you
can specify for the field depend on the field type.
\li For a QLineEdit, \c validator specifies a regular expression to check the
characters allowed in the field.
\li \c defaulttext specifies text that appears in the field by
......@@ -292,7 +299,7 @@
\section1 Creating Class Wizards
The widget.xml file for a class wizard is very similar to that for a project
The wizard.xml file for a class wizard is very similar to that for a project
wizard. The differences are discussed below.
To create a class wizard:
......@@ -360,9 +367,18 @@
<fielddescription xml:lang="de">Klassenname:</fielddescription>
</field>
<field name="Datatype">
<fieldcontrol class="QComboBox" combochoices="QString,int" defaultindex="0" />
<fieldcontrol class="QComboBox" defaultindex="0">
<comboentries>
<comboentry value="QString">
<comboentrytext>class QString</comboentrytext>
<comboentrytext xml:lang="de">Klasse QString</comboentrytext>
</comboentry>
<comboentry value="int">
<comboentrytext>Integer</comboentrytext>
<comboentrytext xml:lang="de">Ganzzahlwert</comboentrytext>
</comboentry>
</comboentries>
</fieldcontrol>
<fielddescription>Data type:</fielddescription>
<fielddescription xml:lang="de">Datentyp:</fielddescription>
</field>
......@@ -371,11 +387,85 @@
\endcode
In addition to QLineEdit, QComboBox is used in the class wizard to
create a field. \c combochoices specifies the options in the combobox
and \c defaultindex specifies that QString is the default value.
create a field. Specify the following XML attributes:
\list
\li \c defaultindex specifies which comboentry is displayed by default. In the above
example, "0" means that the first comboentry is the default value.
\li \c comboentries specifies the options in the combobox.
\li \c value specifies the type of each \c comboentry, QString or integer.
\li \c comboentrytext specifies the text of the entry.
\endlist
\endlist
\section1 Supported Widgets
You can use the following interface objects to create fields in the wizards:
\list
\li PathChooser utility to set paths
\li Check boxes with text labels (QCheckBox)
\li Combined button and popup lists (QComboBox)
\li One-line text editors (QLineEdit)
\li Multi-line rich text editors (QTextEdit)
\endlist
Using QLineEdit and QComboBox is described in the previous sections.
The following sections show examples of using the other classes and describe the XML
attributes that you can specify for the \c fieldcontrol element of a field in a particular
\c class.
\section2 Path Choosers
\code
<field mandatory="true" name="QtCreatorSources">
<fieldcontrol class="Utils::PathChooser" defaulttext="" />
<fielddescription>Qt Creator sources:</fielddescription>
</field>
\endcode
The \c defaulttext attribute specifies text that appears in the field by default.
\section2 Check Boxes
To make check boxes appear selected by default, set the \c fieldcontrol attribute
\c defaultvalue to \c true. Any other value or omitting the attribute makes the check box
appear not selected.
For example:
\code
<field name="CONSOLE">
<fieldcontrol class="QCheckBox" defaultvalue="true"/>
<fielddescription>Console application</fielddescription>
</field>
\endcode
For more examples about using check boxes, see \l{Processing Template Files}.
\section2 Text Editors
\code
<field name="License">
<fieldcontrol class="QTextEdit" defaulttext="Put your license text here" />
<fielddescription>License:</fielddescription>
</field>
\endcode
The \c defaulttext attribute specifies text that appears in the field by default.
\section1 Processing Template Files
When processing a template source file, placeholders specifying the field
......@@ -396,9 +486,29 @@
\endlist
In the \c{helloworld} example, the placeholder \c %NETWORK% is used together with the
QCheckBox class. The following line is added to the project file:
\code
%NETWORK%QT += network
\endcode
And the following field is specified in the wizard.xml:
\code
<field name="NETWORK">
<fieldcontrol class="QCheckBox" truevalue="" falsevalue="# "/>
<fielddescription>Include network module</fielddescription>
<fielddescription xml:lang="de">Netzwerk-Modul verwenden</fielddescription>
</field>
\endcode
If the checkbox is checked, the placeholder is replaced by \c truevalue. If it is not
checked, the placeholder is replaced by \c falsevalue.
You can use conditions to add sections of the file depending on field
values. Use a syntax that is similar to C++ preprocessing, as demonstrated
in the profile of the \c{helloworld} example:
in the project file of the \c{helloworld} example:
\code
......@@ -412,6 +522,16 @@
whether the script module is added. The expressions must expand to valid
Javascript expressions after field replacement.
For example, the following field is specified in the wizard.xml:
\code
<field name="SCRIPT">
<fieldcontrol class="QCheckBox"/>
<fielddescription>Include script module</fielddescription>
<fielddescription xml:lang="de">Script-Modul verwenden</fielddescription>
</field>
\endcode
\section1 Pre-defined Standard Variables
In addition to the field values entered by the user, you can use
......
......@@ -54,6 +54,17 @@
#include <private/qqmltimer_p.h>
#include <private/qqmlengine_p.h>
static bool isPropertyBlackListed(const QmlDesigner::PropertyName &propertyName)
{
if (propertyName.contains(".") && propertyName.contains("__"))
return true;
if (propertyName.count(".") > 1)
return true;
return false;
}
namespace QmlDesigner {
namespace Internal {
......@@ -534,6 +545,9 @@ void ObjectNodeInstance::refreshProperty(const PropertyName &name)
bool ObjectNodeInstance::hasBindingForProperty(const PropertyName &name, bool *hasChanged) const
{
if (isPropertyBlackListed(name))
return false;
QQmlProperty property(object(), name, context());
bool hasBinding = QQmlPropertyPrivate::binding(property);
......@@ -602,6 +616,9 @@ QVariant ObjectNodeInstance::property(const PropertyName &name) const
// TODO: handle model nodes
if (isPropertyBlackListed(name))
return QVariant();
QQmlProperty property(object(), name, context());
if (property.property().isEnumType()) {
QVariant value = property.read();
......@@ -664,6 +681,9 @@ PropertyNameList ObjectNodeInstance::propertyNames() const
QString ObjectNodeInstance::instanceType(const PropertyName &name) const
{
if (isPropertyBlackListed(name))
return QLatin1String("undefined");
QQmlProperty property(object(), name, context());
if (!property.isValid())
return QLatin1String("undefined");
......@@ -783,7 +803,13 @@ static void disableTiledBackingStore(QObject *object)
Q_UNUSED(object);
}
PropertyNameList propertyNameForWritableProperties(QObject *object, const PropertyName &baseName = PropertyName(), QObjectList *inspectedObjects = new QObjectList())
static void addToPropertyNameListIfNotBlackListed(PropertyNameList *propertyNameList, const PropertyName &propertyName)
{
if (!isPropertyBlackListed(propertyName))
propertyNameList->append(propertyName);
}
PropertyNameList propertyNameListForWritableProperties(QObject *object, const PropertyName &baseName = PropertyName(), QObjectList *inspectedObjects = new QObjectList())
{
PropertyNameList propertyNameList;
......@@ -800,16 +826,16 @@ PropertyNameList propertyNameForWritableProperties(QObject *object, const Proper
if (declarativeProperty.name() != "parent") {
QObject *childObject = QQmlMetaType::toQObject(declarativeProperty.read());
if (childObject)
propertyNameList.append(propertyNameForWritableProperties(childObject, baseName + PropertyName(metaProperty.name()) + '.', inspectedObjects));
propertyNameList.append(propertyNameListForWritableProperties(childObject, baseName + PropertyName(metaProperty.name()) + '.', inspectedObjects));
}
} else if (QQmlValueTypeFactory::valueType(metaProperty.userType())) {
QQmlValueType *valueType = QQmlValueTypeFactory::valueType(metaProperty.userType());
valueType->setValue(metaProperty.read(object));
propertyNameList.append(propertyNameForWritableProperties(valueType, baseName + PropertyName(metaProperty.name()) + '.', inspectedObjects));
propertyNameList.append(propertyNameListForWritableProperties(valueType, baseName + PropertyName(metaProperty.name()) + '.', inspectedObjects));
}
if (metaProperty.isReadable() && metaProperty.isWritable()) {
propertyNameList.append(baseName + PropertyName(metaProperty.name()));
addToPropertyNameListIfNotBlackListed(&propertyNameList, baseName + PropertyName(metaProperty.name()));
}
}
......@@ -821,7 +847,7 @@ static void fixResourcePathsForObject(QObject *object)
if (qgetenv("QMLDESIGNER_RC_PATHS").isEmpty())
return;
PropertyNameList propertyNameList = propertyNameForWritableProperties(object);
PropertyNameList propertyNameList = propertyNameListForWritableProperties(object);
foreach (const PropertyName &propertyName, propertyNameList) {
QQmlProperty property(object, propertyName, QQmlEngine::contextForObject(object));
......@@ -1037,7 +1063,7 @@ void ObjectNodeInstance::deactivateState()
void ObjectNodeInstance::populateResetHashes()
{
PropertyNameList propertyNameList = propertyNameForWritableProperties(object());
PropertyNameList propertyNameList = propertyNameListForWritableProperties(object());
foreach (const PropertyName &propertyName, propertyNameList) {
QQmlProperty property(object(), propertyName, QQmlEngine::contextForObject(object()));
......
......@@ -278,8 +278,6 @@ static void disableTextCursor(QQuickItem *item)
void QuickItemNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance)
{
disableTextCursor(quickItem());
if (instanceId() == 0) {
DesignerSupport::setRootItem(nodeInstanceServer()->quickView(), quickItem());
} else {
......@@ -448,7 +446,7 @@ void QuickItemNodeInstance::refresh()
repositioning(quickItem());
}
void doComponentCompleteRecursive(QQuickItem *item)
static void doComponentCompleteRecursive(QQuickItem *item)
{
if (item) {
if (DesignerSupport::isComponentComplete(item))
......@@ -465,6 +463,8 @@ void QuickItemNodeInstance::doComponentComplete()
{
doComponentCompleteRecursive(quickItem());
disableTextCursor(quickItem());
quickItem()->update();
}
......
......@@ -336,8 +336,14 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
if (name->identifier() != 0 && scope->isBlock()) {
bindings()->lookupInScope(name, scope, &candidates, /*templateId = */ 0, /*binding=*/ 0);
if (! candidates.isEmpty())
break; // it's a local.
if (! candidates.isEmpty()) {
// it's a local.
//for qualified it can be outside of the local scope
if (name->isQualifiedNameId())
continue;
else
break;
}
for (unsigned i = 0; i < scope->memberCount(); ++i) {
if (UsingNamespaceDirective *u = scope->memberAt(i)->asUsingNamespaceDirective()) {
......@@ -353,8 +359,14 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
} else if (Function *fun = scope->asFunction()) {
bindings()->lookupInScope(name, fun, &candidates, /*templateId = */ 0, /*binding=*/ 0);
if (! candidates.isEmpty())
break; // it's an argument or a template parameter.
if (! candidates.isEmpty()) {
// it's an argument or a template parameter.
//for qualified it can be outside of the local scope
if (name->isQualifiedNameId())
continue;
else
break;
}
if (fun->name() && fun->name()->isQualifiedNameId()) {
if (ClassOrNamespace *binding = bindings()->lookupType(fun)) {
......@@ -380,8 +392,14 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
} else if (Template *templ = scope->asTemplate()) {
bindings()->lookupInScope(name, templ, &candidates, /*templateId = */ 0, /*binding=*/ 0);
if (! candidates.isEmpty())
return candidates; // it's a template parameter.
if (! candidates.isEmpty()) {
// it's a template parameter.
//for qualified it can be outside of the local scope
if (name->isQualifiedNameId())
continue;
else
break;
}
} else if (scope->asNamespace()
|| scope->asClass()
......@@ -624,7 +642,8 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
if (s->asNamespaceAlias() && binding) {
ClassOrNamespace *targetNamespaceBinding = binding->lookupType(name);
if (targetNamespaceBinding && targetNamespaceBinding->symbols().size() == 1) {
//there can be many namespace definitions
if (targetNamespaceBinding && targetNamespaceBinding->symbols().size() > 0) {
Symbol *resolvedSymbol = targetNamespaceBinding->symbols().first();
item.setType(resolvedSymbol->type()); // override the type
}
......@@ -1107,29 +1126,26 @@ bool ClassOrNamespace::NestedClassInstantiator::isInstantiateNestedClassNeeded(c
bool ClassOrNamespace::NestedClassInstantiator::containsTemplateType(Declaration *declaration) const
{
Type *memberType = declaration->type().type();
NamedType *memberNamedType = findMemberNamedType(memberType);
if (memberNamedType) {
const Name *name = memberNamedType->name();
if (_subst.contains(name))
return true;
}
return false;
NamedType *namedType = findNamedType(memberType);
return namedType && _subst.contains(namedType->name());
}
bool ClassOrNamespace::NestedClassInstantiator::containsTemplateType(Function * /*function*/) const
bool ClassOrNamespace::NestedClassInstantiator::containsTemplateType(Function *function) const
{
//TODO: make implementation
return false;
Type *returnType = function->returnType().type();
NamedType *namedType = findNamedType(returnType);
return namedType && _subst.contains(namedType->name());
//TODO: in future we will need also check function arguments, for now returned value is enough
}
NamedType *ClassOrNamespace::NestedClassInstantiator::findMemberNamedType(Type *memberType) const
NamedType *ClassOrNamespace::NestedClassInstantiator::findNamedType(Type *memberType) const
{
if (NamedType *namedType = memberType->asNamedType())
return namedType;
else if (PointerType *pointerType = memberType->asPointerType())
return findMemberNamedType(pointerType->elementType().type());
return findNamedType(pointerType->elementType().type());
else if (ReferenceType *referenceType = memberType->asReferenceType())
return findMemberNamedType(referenceType->elementType().type());
return findNamedType(referenceType->elementType().type());
return 0;
}
......
......@@ -155,7 +155,7 @@ private:
bool isInstantiateNestedClassNeeded(const QList<Symbol *> &symbols) const;
bool containsTemplateType(Declaration *declaration) const;
bool containsTemplateType(Function *function) const;
NamedType *findMemberNamedType(Type *memberType) const;
NamedType *findNamedType(Type *memberType) const;
QSet<ClassOrNamespace *> _alreadyConsideredNestedClassInstantiations;
CreateBindings *_factory;
......
......@@ -125,7 +125,11 @@ public:
QByteArray preprocessedExpression(const QByteArray &utf8code) const;
void setExpandTemplates(bool expandTemplates)
{ m_expandTemplates = expandTemplates; }
{
if (m_bindings)
m_bindings->setExpandTemplates(expandTemplates);
m_expandTemplates = expandTemplates;
}
private:
......
DEFINES += NDEBUG
#DEFINES += DEBUG_LOOKUP
unix:QMAKE_CXXFLAGS_DEBUG += -O2
win32:QMAKE_CXXFLAGS_DEBUG += -O2
include(../../qtcreatorlibrary.pri)
include(cplusplus-lib.pri)
......@@ -43,14 +43,6 @@ class StaticAnalysisMessages
Q_DECLARE_TR_FUNCTIONS(QmlJS::StaticAnalysisMessages)
public:
class PrototypeMessageData {
public:
Type type;
Severity severity;
QString message;
int placeholders;
};
void newMsg(Type type, Severity severity, const QString &message, int placeholders = 0)
{
PrototypeMessageData prototype;
......@@ -248,7 +240,7 @@ Message::Message(Type type,
: location(location), type(type)
{
QTC_ASSERT(messages()->messages.contains(type), return);
const StaticAnalysisMessages::PrototypeMessageData &prototype = messages()->messages.value(type);
const PrototypeMessageData &prototype = prototypeForMessageType(type);
severity = prototype.severity;
message = prototype.message;
if (prototype.placeholders == 0) {
......@@ -299,3 +291,11 @@ QRegExp Message::suppressionPattern()
{
return QRegExp(QLatin1String("@disable-check M(\\d+)"));
}
const PrototypeMessageData Message::prototypeForMessageType(Type type)
{
QTC_CHECK(messages()->messages.contains(type));
const PrototypeMessageData &prototype = messages()->messages.value(type);
return prototype;
}
......@@ -131,6 +131,14 @@ enum Type
ErrInvalidArrayValueLength = 323
};
class QMLJS_EXPORT PrototypeMessageData {
public:
Type type;
Severity severity;
QString message;
int placeholders;
};
class QMLJS_EXPORT Message
{
public:
......@@ -152,6 +160,8 @@ public:
QString message;
Type type;
Severity severity;
static const PrototypeMessageData prototypeForMessageType(Type type);
};
} // namespace StaticAnalysis
......
......@@ -58,7 +58,7 @@ public:
static bool isMacHost() { return hostOs() == HostOsMac; }
static inline bool isAnyUnixHost();
static QString appendExecutableSuffix(const QString &executable)
static QString withExecutableSuffix(const QString &executable)
{
QString finalName = executable;
if (isWindowsHost())
......
......@@ -226,6 +226,7 @@ QString PathChooserPrivate::expandedPath(const QString &input) const
case PathChooser::Directory:
case PathChooser::ExistingDirectory:
case PathChooser::File:
case PathChooser::SaveFile:
if (!m_baseDirectory.isEmpty() && QFileInfo(path).isRelative())
return QFileInfo(m_baseDirectory + QLatin1Char('/') + path).absoluteFilePath();
break;
......@@ -377,6 +378,11 @@ void PathChooser::slotBrowse()
makeDialogTitle(tr("Choose File")), predefined,
d->m_dialogFilter);
break;
case PathChooser::SaveFile:
newPath = QFileDialog::getSaveFileName(this,
makeDialogTitle(tr("Choose File")), predefined,
d->m_dialogFilter);
break;
case PathChooser::Any: {
QFileDialog dialog(this);
dialog.setFileMode(QFileDialog::AnyFile);
......@@ -464,6 +470,13 @@ bool PathChooser::validatePath(const QString &path, QString *errorMessage)
return false;
}
break;
case PathChooser::SaveFile:
if (!fi.absoluteDir().exists()) {
if (errorMessage)
*errorMessage = tr("The directory '%1' does not exist.").arg(QDir::toNativeSeparators(fi.absolutePath()));
return false;
}
break;
case PathChooser::ExistingCommand:
if (!fi.exists()) {
if (errorMessage)
......@@ -513,6 +526,14 @@ bool PathChooser::validatePath(const QString &path, QString *errorMessage)
}
break;
case PathChooser::SaveFile:
if (fi.exists() && fi.isDir()) {
if (errorMessage)
*errorMessage = tr("The path <b>%1</b> is not a file.").arg(QDir::toNativeSeparators(fi.absolutePath()));
return false;
}
break;
case PathChooser::ExistingCommand:
if (!fi.isFile() || !fi.isExecutable()) {
if (errorMessage)
......
......@@ -70,6 +70,7 @@ public:
ExistingDirectory,
Directory, // A directory, doesn't need to exist
File,
SaveFile,
ExistingCommand, // A command that must exist at the time of selection
Command, // A command that may or may not exist at the time of selection (e.g. result of a build)
Any
......
......@@ -81,6 +81,7 @@ namespace {
const QLatin1String KeystoreLocationKey("KeystoreLocation");
const QLatin1String AutomaticKitCreationKey("AutomatiKitCreation");
const QLatin1String PartitionSizeKey("PartitionSize");
const QLatin1String ToolchainHostKey("ToolchainHost");
const QLatin1String ArmToolchainPrefix("arm-linux-androideabi");
const QLatin1String X86ToolchainPrefix("x86");
const QLatin1String MipsToolchainPrefix("mipsel-linux-android");
......@@ -152,6 +153,7 @@ AndroidConfig::AndroidConfig(const QSettings &settings)
antLocation = FileName::fromString(settings.value(AntLocationKey).toString());
openJDKLocation = FileName::fromString(settings.value(OpenJDKLocationKey).toString());
keystoreLocation = FileName::fromString(settings.value(KeystoreLocationKey).toString());
toolchainHost = settings.value(ToolchainHostKey).toString();
automaticKitCreation = settings.value(AutomaticKitCreationKey, true).toBool();
PersistentSettingsReader reader;
......@@ -163,6 +165,7 @@ AndroidConfig::AndroidConfig(const QSettings &settings)
antLocation = FileName::fromString(reader.restoreValue(AntLocationKey).toString());
openJDKLocation = FileName::fromString(reader.restoreValue(OpenJDKLocationKey).toString());
keystoreLocation = FileName::fromString(reader.restoreValue(KeystoreLocationKey).toString());
toolchainHost = reader.restoreValue(ToolchainHostKey).toString();
QVariant v = reader.restoreValue(AutomaticKitCreationKey);
if (v.isValid())
automaticKitCreation = v.toBool();
......@@ -190,11 +193,16 @@ void AndroidConfig::save(QSettings &settings) const
settings.setValue(KeystoreLocationKey, keystoreLocation.toString());
settings.setValue(PartitionSizeKey, partitionSize);
settings.setValue(AutomaticKitCreationKey, automaticKitCreation);