Merge remote-tracking branch 'origin/5.8' into 5.9
Conflicts: src/qml/compiler/qv4ssa.cpp src/quick/accessible/qaccessiblequickview_p.h src/quick/items/qquickmousearea.cpp src/quick/util/qquickanimatorjob.cpp tools/qmlplugindump/main.cpp Change-Id: I84474cf39895b9b757403971d2e9196e8c9d1809
This commit is contained in:
commit
b1fa22c168
|
@ -51,37 +51,37 @@ class AsyncImageResponse : public QQuickImageResponse, public QRunnable
|
|||
{
|
||||
public:
|
||||
AsyncImageResponse(const QString &id, const QSize &requestedSize)
|
||||
: m_id(id), m_requestedSize(requestedSize), m_texture(0)
|
||||
: m_id(id), m_requestedSize(requestedSize)
|
||||
{
|
||||
setAutoDelete(false);
|
||||
}
|
||||
|
||||
QQuickTextureFactory *textureFactory() const
|
||||
{
|
||||
return m_texture;
|
||||
return QQuickTextureFactory::textureFactoryForImage(m_image);
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
QImage image(50, 50, QImage::Format_RGB32);
|
||||
m_image = QImage(50, 50, QImage::Format_RGB32);
|
||||
if (m_id == "slow") {
|
||||
qDebug() << "Slow, red, sleeping for 5 seconds";
|
||||
QThread::sleep(5);
|
||||
image.fill(Qt::red);
|
||||
m_image.fill(Qt::red);
|
||||
} else {
|
||||
qDebug() << "Fast, blue, sleeping for 1 second";
|
||||
QThread::sleep(1);
|
||||
image.fill(Qt::blue);
|
||||
m_image.fill(Qt::blue);
|
||||
}
|
||||
if (m_requestedSize.isValid())
|
||||
image = image.scaled(m_requestedSize);
|
||||
m_texture = QQuickTextureFactory::textureFactoryForImage(image);
|
||||
m_image = m_image.scaled(m_requestedSize);
|
||||
|
||||
emit finished();
|
||||
}
|
||||
|
||||
QString m_id;
|
||||
QSize m_requestedSize;
|
||||
QQuickTextureFactory *m_texture;
|
||||
QImage m_image;
|
||||
};
|
||||
|
||||
class AsyncImageProvider : public QQuickAsyncImageProvider
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
TEMPLATE = subdirs
|
||||
|
||||
QT_FOR_CONFIG += quick-private
|
||||
|
||||
SUBDIRS += \
|
||||
builtins \
|
||||
qtqml \
|
||||
|
@ -18,7 +20,7 @@ qtHaveModule(quick) {
|
|||
sharedimage \
|
||||
testlib
|
||||
|
||||
qtConfig(opengl(es1|es2)?): \
|
||||
qtConfig(quick-sprite):qtConfig(opengl(es1|es2)?): \
|
||||
SUBDIRS += particles
|
||||
}
|
||||
|
||||
|
|
|
@ -564,7 +564,7 @@ Database connections are automatically closed during Javascript garbage collecti
|
|||
|
||||
The API can be used from JavaScript functions in your QML:
|
||||
|
||||
\snippet localstorage/localstorage/hello.qml 0
|
||||
\snippet qml/localstorage/hello.qml 0
|
||||
|
||||
The API conforms to the Synchronous API of the HTML5 Web Database API,
|
||||
\link http://www.w3.org/TR/2009/WD-webdatabase-20091029/ W3C Working Draft 29 October 2009\endlink.
|
||||
|
|
|
@ -1108,10 +1108,9 @@ QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolv
|
|||
continue;
|
||||
}
|
||||
|
||||
// Try again later and resolve the target alias first.
|
||||
_objectsWithAliases.append(objectIndex);
|
||||
// restore
|
||||
alias->idIndex = idIndex;
|
||||
// Try again later and resolve the target alias first.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -427,6 +427,7 @@ bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(temporaryfile)
|
||||
// Foo.qml -> Foo.qmlc
|
||||
QSaveFile cacheFile(cacheFilePath(unitUrl));
|
||||
if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
|
@ -459,6 +460,10 @@ bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
|
|||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
*errorString = QStringLiteral("features.temporaryfile is disabled.");
|
||||
return false;
|
||||
#endif // QT_CONFIG(temporaryfile)
|
||||
}
|
||||
|
||||
void CompilationUnit::prepareCodeOffsetsForDiskStorage(Unit *unit)
|
||||
|
|
|
@ -507,6 +507,16 @@ struct Q_AUTOTEST_EXPORT Temp: Expr {
|
|||
, memberResolver(0)
|
||||
{}
|
||||
|
||||
Temp(Type type, Kind kind, unsigned index)
|
||||
: Expr(TempExpr)
|
||||
, index(index)
|
||||
, isReadOnly(0)
|
||||
, kind(kind)
|
||||
, memberResolver(0)
|
||||
{
|
||||
this->type = type;
|
||||
}
|
||||
|
||||
void init(unsigned kind, unsigned index)
|
||||
{
|
||||
this->index = index;
|
||||
|
|
|
@ -3581,16 +3581,43 @@ public:
|
|||
, _replacement(0)
|
||||
{}
|
||||
|
||||
void operator()(Temp *toReplace, Expr *replacement, StatementWorklist &W, QVector<Stmt *> *newUses = 0)
|
||||
bool operator()(Temp *toReplace, Expr *replacement, StatementWorklist &W, QVector<Stmt *> *newUses = 0)
|
||||
{
|
||||
Q_ASSERT(replacement->asTemp() || replacement->asConst() || replacement->asName());
|
||||
|
||||
// qout << "Replacing ";toReplace->dump(qout);qout<<" by ";replacement->dump(qout);qout<<endl;
|
||||
|
||||
qSwap(_toReplace, toReplace);
|
||||
qSwap(_replacement, replacement);
|
||||
|
||||
const QVector<Stmt *> &uses = _defUses.uses(*_toReplace);
|
||||
|
||||
// Prevent the following:
|
||||
// L3:
|
||||
// %1 = phi L1: %2, L2: %3
|
||||
// %4 = phi L1: %5, L2: %6
|
||||
// %6 = %1
|
||||
// From turning into:
|
||||
// L3:
|
||||
// %1 = phi L1: %2, L2: %3
|
||||
// %4 = phi L1: %5, L2: %1
|
||||
//
|
||||
// Because both phi nodes are "executed in parallel", we cannot replace %6 by %1 in the
|
||||
// second phi node. So, if the defining statement for a temp is a phi node, and one of the
|
||||
// uses of the to-be-replaced statement is a phi node in the same block as the defining
|
||||
// statement, bail out.
|
||||
if (Temp *r = _replacement->asTemp()) {
|
||||
if (_defUses.defStmt(*r)->asPhi()) {
|
||||
BasicBlock *replacementDefBlock = _defUses.defStmtBlock(*r);
|
||||
for (Stmt *use : uses) {
|
||||
if (Phi *usePhi = use->asPhi()) {
|
||||
if (_defUses.defStmtBlock(*usePhi->targetTemp) == replacementDefBlock)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// qout << "Replacing ";toReplace->dump(qout);qout<<" by ";replacement->dump(qout);qout<<endl;
|
||||
|
||||
if (newUses)
|
||||
newUses->reserve(uses.size());
|
||||
|
||||
|
@ -3606,6 +3633,7 @@ public:
|
|||
|
||||
qSwap(_replacement, replacement);
|
||||
qSwap(_toReplace, toReplace);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -4082,11 +4110,12 @@ void optimizeSSA(StatementWorklist &W, DefUses &defUses, DominatorTree &df)
|
|||
// copy propagation:
|
||||
if (Temp *sourceTemp = m->source->asTemp()) {
|
||||
QVector<Stmt *> newT2Uses;
|
||||
replaceUses(targetTemp, sourceTemp, W, &newT2Uses);
|
||||
defUses.removeUse(s, *sourceTemp);
|
||||
defUses.addUses(*sourceTemp, newT2Uses);
|
||||
defUses.removeDef(*targetTemp);
|
||||
W.remove(s);
|
||||
if (replaceUses(targetTemp, sourceTemp, W, &newT2Uses)) {
|
||||
defUses.removeUse(s, *sourceTemp);
|
||||
defUses.addUses(*sourceTemp, newT2Uses);
|
||||
defUses.removeDef(*targetTemp);
|
||||
W.remove(s);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -5635,25 +5664,97 @@ void MoveMapping::add(Expr *from, Temp *to) {
|
|||
_moves.append(m);
|
||||
}
|
||||
|
||||
// Order the moves that are generated when resolving edges during register allocation (see [Wimmer1]
|
||||
// section 6 for details). Now these moves form one or more graphs, so we have to output them in
|
||||
// such an order that values don't get overwritten:
|
||||
// r1 <- r0
|
||||
// r2 <- r1
|
||||
// That input has to be ordered as follows in order to prevent the value in r1 from being lost:
|
||||
// r2 <- r1
|
||||
// r1 <- r0
|
||||
//
|
||||
// So, the algorithm is to output the leaves first, and take them out of the input. This will result
|
||||
// in some moves to become leaves (in the above example: when leaf r2 <- r1 is generated and taken
|
||||
// away, the r1 <- r0 is now a leaf), so we can output those and take those out, and repeat until
|
||||
// there are no more leafs.
|
||||
//
|
||||
// The tricky part is that there might be cycles:
|
||||
// r4 <- r5
|
||||
// r5 <- r4
|
||||
// These have to be turned into a "register swap":
|
||||
// r4 <=> r5
|
||||
//
|
||||
// So after running the above algorithm where we progressively remove the leaves, we are left with
|
||||
// zero or more cycles. To resolve those, we break one of the edges of the cycle, and for all other
|
||||
// edges we generate swaps. Note that the swaps will always occur as the last couple of moves,
|
||||
// because otherwise they might clobber sources for moves:
|
||||
// r4 <=> r5
|
||||
// r6 <- r5
|
||||
// Here, the value of r5 is already overwritten with the one in r4, so the correct order is:
|
||||
// r6 <- r5
|
||||
// r4 <=> r5
|
||||
void MoveMapping::order()
|
||||
{
|
||||
QList<Move> todo = _moves;
|
||||
QList<Move> output, swaps;
|
||||
QList<Move> output;
|
||||
output.reserve(_moves.size());
|
||||
QList<Move> delayed;
|
||||
delayed.reserve(_moves.size());
|
||||
|
||||
while (!todo.isEmpty()) {
|
||||
const Move m = todo.first();
|
||||
todo.removeFirst();
|
||||
schedule(m, todo, delayed, output, swaps);
|
||||
while (!_moves.isEmpty()) {
|
||||
// Take out all leaf edges, because we can output them without any problems.
|
||||
int nextLeaf = findLeaf();
|
||||
if (nextLeaf == -1)
|
||||
break; // No more leafs left, we're done here.
|
||||
output.append(_moves.takeAt(nextLeaf));
|
||||
// Now there might be new leaf edges: any move that had the input of the previously found
|
||||
// leaf as an output, so loop around.
|
||||
}
|
||||
|
||||
output += swaps;
|
||||
while (!_moves.isEmpty()) {
|
||||
// We're now left with one or more cycles.
|
||||
// Step one: break the/a cycle.
|
||||
_moves.removeFirst();
|
||||
// Step two: find the other edges of the cycle, starting with the one of that is now a leaf.
|
||||
while (!_moves.isEmpty()) {
|
||||
int nextLeaf = findLeaf();
|
||||
if (nextLeaf == -1)
|
||||
break; // We're done with this cycle.
|
||||
Move m = _moves.takeAt(nextLeaf);
|
||||
// Step three: get the edges from the cycle and turn it into a swap
|
||||
m.needsSwap = true;
|
||||
output.append(m);
|
||||
// Because we took out a leaf, find the next one.
|
||||
}
|
||||
// We're done with the cycle, let's see if there are more.
|
||||
}
|
||||
|
||||
Q_ASSERT(todo.isEmpty());
|
||||
Q_ASSERT(delayed.isEmpty());
|
||||
qSwap(_moves, output);
|
||||
_moves = output;
|
||||
}
|
||||
|
||||
int MoveMapping::findLeaf() const
|
||||
{
|
||||
for (int i = 0, e = _moves.size(); i != e; ++i) {
|
||||
// Take an edge from the list...
|
||||
const Temp *target = _moves.at(i).to;
|
||||
// ... and see if its target is used as a source...
|
||||
bool targetUsedAsSource = false;
|
||||
for (int j = 0; j != e; ++j) {
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
Expr *source = _moves.at(j).from;
|
||||
if (const Temp *sourceTemp = source->asTemp()) {
|
||||
if (overlappingStorage(*target, *sourceTemp)) {
|
||||
targetUsedAsSource = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ... if not, we have a leaf edge ...
|
||||
if (!targetUsedAsSource)
|
||||
return i;
|
||||
// .. otherwise we try the next one.
|
||||
}
|
||||
|
||||
return -1; // No leaf found
|
||||
}
|
||||
|
||||
QList<IR::Move *> MoveMapping::insertMoves(BasicBlock *bb, IR::Function *function, bool atEnd) const
|
||||
|
@ -5695,60 +5796,12 @@ void MoveMapping::dump() const
|
|||
}
|
||||
}
|
||||
|
||||
MoveMapping::Action MoveMapping::schedule(const Move &m, QList<Move> &todo, QList<Move> &delayed,
|
||||
QList<Move> &output, QList<Move> &swaps) const
|
||||
{
|
||||
const Moves usages = sourceUsages(m.to, todo) + sourceUsages(m.to, delayed);
|
||||
for (const Move &dependency : usages) {
|
||||
if (!output.contains(dependency)) {
|
||||
if (delayed.contains(dependency)) {
|
||||
// We have a cycle! Break it by swapping instead of assigning.
|
||||
if (DebugMoveMapping) {
|
||||
delayed += m;
|
||||
QBuffer buf;
|
||||
buf.open(QIODevice::WriteOnly);
|
||||
QTextStream out(&buf);
|
||||
IRPrinter printer(&out);
|
||||
out<<"we have a cycle! temps:" << endl;
|
||||
for (const Move &m : qAsConst(delayed)) {
|
||||
out<<"\t";
|
||||
printer.print(m.to);
|
||||
out<<" <- ";
|
||||
printer.print(m.from);
|
||||
out<<endl;
|
||||
}
|
||||
qDebug("%s", buf.data().constData());
|
||||
delayed.removeOne(m);
|
||||
}
|
||||
|
||||
return NeedsSwap;
|
||||
} else {
|
||||
delayed.append(m);
|
||||
todo.removeOne(dependency);
|
||||
Action action = schedule(dependency, todo, delayed, output, swaps);
|
||||
delayed.removeOne(m);
|
||||
Move mm(m);
|
||||
if (action == NeedsSwap) {
|
||||
mm.needsSwap = true;
|
||||
swaps.append(mm);
|
||||
} else {
|
||||
output.append(mm);
|
||||
}
|
||||
return action;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output.append(m);
|
||||
return NormalMove;
|
||||
}
|
||||
|
||||
// References:
|
||||
// [Wimmer1] C. Wimmer and M. Franz. Linear Scan Register Allocation on SSA Form. In Proceedings of
|
||||
// CGO’10, ACM Press, 2010
|
||||
// CGO'10, ACM Press, 2010
|
||||
// [Wimmer2] C. Wimmer and H. Mossenbock. Optimized Interval Splitting in a Linear Scan Register
|
||||
// Allocator. In Proceedings of the ACM/USENIX International Conference on Virtual
|
||||
// Execution Environments, pages 132–141. ACM Press, 2005.
|
||||
// Execution Environments, pages 132-141. ACM Press, 2005.
|
||||
// [Briggs] P. Briggs, K.D. Cooper, T.J. Harvey, and L.T. Simpson. Practical Improvements to the
|
||||
// Construction and Destruction of Static Single Assignment Form.
|
||||
// [Appel] A.W. Appel. Modern Compiler Implementation in Java. Second edition, Cambridge
|
||||
|
|
|
@ -265,15 +265,18 @@ private:
|
|||
QHash<BasicBlock *, BasicBlock *> startEndLoops;
|
||||
};
|
||||
|
||||
class MoveMapping
|
||||
class Q_AUTOTEST_EXPORT MoveMapping
|
||||
{
|
||||
#ifdef V4_AUTOTEST
|
||||
public:
|
||||
#endif
|
||||
struct Move {
|
||||
Expr *from;
|
||||
Temp *to;
|
||||
bool needsSwap;
|
||||
|
||||
Move(Expr *from, Temp *to)
|
||||
: from(from), to(to), needsSwap(false)
|
||||
Move(Expr *from, Temp *to, bool needsSwap = false)
|
||||
: from(from), to(to), needsSwap(needsSwap)
|
||||
{}
|
||||
|
||||
bool operator==(const Move &other) const
|
||||
|
@ -293,9 +296,7 @@ public:
|
|||
void dump() const;
|
||||
|
||||
private:
|
||||
enum Action { NormalMove, NeedsSwap };
|
||||
Action schedule(const Move &m, QList<Move> &todo, QList<Move> &delayed, QList<Move> &output,
|
||||
QList<Move> &swaps) const;
|
||||
int findLeaf() const;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -67,13 +67,15 @@ class QQuickWindow;
|
|||
|
||||
#ifdef QT_NO_QML_DEBUGGER
|
||||
|
||||
struct QV4DebugService
|
||||
class QV4DebugService
|
||||
{
|
||||
public:
|
||||
void signalEmitted(const QString &) {}
|
||||
};
|
||||
|
||||
struct QQmlProfilerService
|
||||
class QQmlProfilerService
|
||||
{
|
||||
public:
|
||||
void startProfiling(QJSEngine *engine, quint64 features = std::numeric_limits<quint64>::max())
|
||||
{
|
||||
Q_UNUSED(engine);
|
||||
|
@ -83,21 +85,23 @@ struct QQmlProfilerService
|
|||
void stopProfiling(QJSEngine *) {}
|
||||
};
|
||||
|
||||
struct QQmlEngineDebugService
|
||||
class QQmlEngineDebugService
|
||||
{
|
||||
public:
|
||||
void objectCreated(QJSEngine *, QObject *) {}
|
||||
virtual void setStatesDelegate(QQmlDebugStatesDelegate *) {}
|
||||
};
|
||||
|
||||
struct QQmlInspectorService {
|
||||
class QQmlInspectorService {
|
||||
public:
|
||||
void addWindow(QQuickWindow *) {}
|
||||
void setParentWindow(QQuickWindow *, QWindow *) {}
|
||||
void removeWindow(QQuickWindow *) {}
|
||||
};
|
||||
|
||||
struct QDebugMessageService {};
|
||||
struct QQmlEngineControlService {};
|
||||
struct QQmlNativeDebugService {};
|
||||
class QDebugMessageService {};
|
||||
class QQmlEngineControlService {};
|
||||
class QQmlNativeDebugService {};
|
||||
|
||||
#else
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ QT_BEGIN_NAMESPACE
|
|||
#define Q_QML_PROFILE(feature, profiler, Method)
|
||||
#define Q_QML_OC_PROFILE(member, Code)
|
||||
|
||||
struct QQmlProfiler {};
|
||||
class QQmlProfiler {};
|
||||
|
||||
struct QQmlBindingProfiler
|
||||
{
|
||||
|
|
|
@ -168,8 +168,9 @@
|
|||
from \a uri having version number composed from \a versionMajor and
|
||||
\a versionMinor.
|
||||
|
||||
While the type has a name and a type, it cannot be created, and the
|
||||
given error \a reason will result if creation is attempted.
|
||||
While the type has a name and a type, it cannot be created. An error
|
||||
message with the given \a reason is printed if the user attempts to
|
||||
create an instance of this type.
|
||||
|
||||
This is useful where the type is only intended for providing attached
|
||||
properties, enum values or an abstract base class with its extension.
|
||||
|
@ -189,11 +190,14 @@
|
|||
from \a uri having version number composed from \a versionMajor and
|
||||
\a versionMinor.
|
||||
|
||||
This function is useful to register Q_NAMESPACE namespaces.
|
||||
An instance of the meta object cannot be created. An error message with
|
||||
the given \a reason is printed if the user attempts to create it.
|
||||
|
||||
This function is useful for registering Q_NAMESPACE namespaces.
|
||||
|
||||
Returns the QML type id.
|
||||
|
||||
Example:
|
||||
For example:
|
||||
|
||||
\code
|
||||
namespace MyNamespace {
|
||||
|
@ -209,7 +213,7 @@
|
|||
qmlRegisterUncreatableMetaObject(MyNamespace::staticMetaObject, "io.qt", 1, 0, "MyNamespace", "Access to enums & flags only");
|
||||
\endcode
|
||||
|
||||
Now on QML side you can use the registered enums:
|
||||
On the QML side, you can now use the registered enums:
|
||||
\code
|
||||
Component.onCompleted: console.log(MyNamespace.Key2)
|
||||
\endcode
|
||||
|
|
|
@ -1138,6 +1138,8 @@ private:
|
|||
mapping.add(moveFrom, moveTo);
|
||||
}
|
||||
|
||||
if (DebugRegAlloc)
|
||||
mapping.dump();
|
||||
mapping.order();
|
||||
if (DebugRegAlloc)
|
||||
mapping.dump();
|
||||
|
@ -1958,10 +1960,10 @@ void RegisterAllocator::dump(IR::Function *function) const
|
|||
|
||||
// References:
|
||||
// [Wimmer1] C. Wimmer and M. Franz. Linear Scan Register Allocation on SSA Form. In Proceedings of
|
||||
// CGO’10, ACM Press, 2010
|
||||
// CGO'10, ACM Press, 2010
|
||||
// [Wimmer2] C. Wimmer and H. Mossenbock. Optimized Interval Splitting in a Linear Scan Register
|
||||
// Allocator. In Proceedings of the ACM/USENIX International Conference on Virtual
|
||||
// Execution Environments, pages 132–141. ACM Press, 2005.
|
||||
// Execution Environments, pages 132-141. ACM Press, 2005.
|
||||
// [Traub] Omri Traub, Glenn Holloway, and Michael D. Smith. Quality and Speed in Linear-scan
|
||||
// Register Allocation. In Proceedings of the ACM SIGPLAN 1998 Conference on Programming
|
||||
// Language Design and Implementation, pages 142–151, June 1998.
|
||||
// Language Design and Implementation, pages 142-151, June 1998.
|
||||
|
|
|
@ -525,7 +525,7 @@ QJSValue QJSEngine::newQObject(QObject *object)
|
|||
\since 5.8
|
||||
|
||||
Creates a JavaScript object that wraps the given QMetaObject
|
||||
The metaObject must outlive the script engine. It is recommended to only
|
||||
The \a metaObject must outlive the script engine. It is recommended to only
|
||||
use this method with static metaobjects.
|
||||
|
||||
|
||||
|
|
|
@ -61,8 +61,9 @@ namespace Debugging {
|
|||
|
||||
#ifdef QT_NO_QML_DEBUGGER
|
||||
|
||||
struct Debugger
|
||||
class Debugger
|
||||
{
|
||||
public:
|
||||
bool pauseAtNextOpportunity() const { return false; }
|
||||
void maybeBreakAtInstruction() {}
|
||||
void enteringFunction() {}
|
||||
|
|
|
@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE
|
|||
|
||||
namespace QV4 {
|
||||
namespace Profiling {
|
||||
struct Profiler {};
|
||||
class Profiler {};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1039,7 +1039,7 @@ QQmlEngine::~QQmlEngine()
|
|||
|
||||
/*! \fn void QQmlEngine::exit(int retCode)
|
||||
This signal is emitted when the QML loaded by the engine would like to exit
|
||||
from the event loop with the specified return code.
|
||||
from the event loop with the specified return code \a retCode.
|
||||
|
||||
\since 5.8
|
||||
\sa quit()
|
||||
|
|
|
@ -202,6 +202,7 @@ QQmlExpression::QQmlExpression(QQmlContextData *ctxt, QObject *scope,
|
|||
*/
|
||||
QQmlExpression::~QQmlExpression()
|
||||
{
|
||||
clearError();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -394,8 +394,9 @@ can be very useful while prototyping.
|
|||
\fn QQmlListProperty::QQmlListProperty(QObject *object, void *data,
|
||||
CountFunction count, AtFunction at)
|
||||
|
||||
Construct a readonly QQmlListProperty from a set of operation functions. An opaque \a data handle
|
||||
may be passed which can be accessed from within the operation functions. The list property
|
||||
Construct a readonly QQmlListProperty from a set of operation functions
|
||||
\a count and \a at. An opaque \a data handle may be passed which can be
|
||||
accessed from within the operation functions. The list property
|
||||
remains valid while \a object exists.
|
||||
*/
|
||||
|
||||
|
@ -404,8 +405,9 @@ remains valid while \a object exists.
|
|||
CountFunction count, AtFunction at,
|
||||
ClearFunction clear)
|
||||
|
||||
Construct a QQmlListProperty from a set of operation functions. An opaque \a data handle
|
||||
may be passed which can be accessed from within the operation functions. The list property
|
||||
Construct a QQmlListProperty from a set of operation functions \a append,
|
||||
\a count, \a at, and \a clear. An opaque \a data handle may be passed which
|
||||
can be accessed from within the operation functions. The list property
|
||||
remains valid while \a object exists.
|
||||
|
||||
Null pointers can be passed for any function. If any null pointers are passed in, the list
|
||||
|
|
|
@ -789,12 +789,12 @@ void QQmlPropertyPrivate::removeBinding(const QQmlProperty &that)
|
|||
QQmlAbstractBinding *
|
||||
QQmlPropertyPrivate::binding(QObject *object, QQmlPropertyIndex index)
|
||||
{
|
||||
findAliasTarget(object, index, &object, &index);
|
||||
|
||||
QQmlData *data = QQmlData::get(object);
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
findAliasTarget(object, index, &object, &index);
|
||||
|
||||
const int coreIndex = index.coreIndex();
|
||||
const int valueTypeIndex = index.valueTypeIndex();
|
||||
|
||||
|
@ -1399,9 +1399,9 @@ QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engi
|
|||
}
|
||||
|
||||
/*!
|
||||
Sets the property value to \a value and returns true.
|
||||
Returns false if the property can't be set because the
|
||||
\a value is the wrong type, for example.
|
||||
Sets the property value to \a value. Returns \c true on success, or
|
||||
\c false if the property can't be set because the \a value is the
|
||||
wrong type, for example.
|
||||
*/
|
||||
bool QQmlProperty::write(const QVariant &value) const
|
||||
{
|
||||
|
@ -1416,6 +1416,8 @@ bool QQmlProperty::write(const QVariant &value) const
|
|||
QQmlProperty p(object, name);
|
||||
p.write(value);
|
||||
\endcode
|
||||
|
||||
Returns \c true on success, \c false otherwise.
|
||||
*/
|
||||
bool QQmlProperty::write(QObject *object, const QString &name, const QVariant &value)
|
||||
{
|
||||
|
@ -1432,6 +1434,8 @@ bool QQmlProperty::write(QObject *object, const QString &name, const QVariant &v
|
|||
QQmlProperty p(object, name, ctxt);
|
||||
p.write(value);
|
||||
\endcode
|
||||
|
||||
Returns \c true on success, \c false otherwise.
|
||||
*/
|
||||
bool QQmlProperty::write(QObject *object,
|
||||
const QString &name,
|
||||
|
@ -1452,6 +1456,8 @@ bool QQmlProperty::write(QObject *object,
|
|||
QQmlProperty p(object, name, engine);
|
||||
p.write(value);
|
||||
\endcode
|
||||
|
||||
Returns \c true on success, \c false otherwise.
|
||||
*/
|
||||
bool QQmlProperty::write(QObject *object, const QString &name, const QVariant &value,
|
||||
QQmlEngine *engine)
|
||||
|
|
|
@ -129,15 +129,20 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q
|
|||
return w.asReturnedValue();
|
||||
}
|
||||
|
||||
static int enumForSingleton(String *name, QObject *qobjectSingleton)
|
||||
static int enumForSingleton(QV4::ExecutionEngine *v4, String *name, QObject *qobjectSingleton,
|
||||
QQmlType *type)
|
||||
{
|
||||
bool ok;
|
||||
int value = type->enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok);
|
||||
if (ok)
|
||||
return value;
|
||||
|
||||
// ### Optimize
|
||||
QByteArray enumName = name->toQString().toUtf8();
|
||||
const QMetaObject *metaObject = qobjectSingleton->metaObject();
|
||||
for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) {
|
||||
QMetaEnum e = metaObject->enumerator(ii);
|
||||
bool ok;
|
||||
int value = e.keyToValue(enumName.constData(), &ok);
|
||||
value = e.keyToValue(enumName.constData(), &ok);
|
||||
if (ok)
|
||||
return value;
|
||||
}
|
||||
|
@ -183,7 +188,7 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope
|
|||
// check for enum value
|
||||
const bool includeEnums = w->d()->mode == Heap::QmlTypeWrapper::IncludeEnums;
|
||||
if (includeEnums && name->startsWithUpper()) {
|
||||
const int value = enumForSingleton(name, qobjectSingleton);
|
||||
const int value = enumForSingleton(v4, name, qobjectSingleton, type);
|
||||
if (value != -1)
|
||||
return QV4::Primitive::fromInt32(value).asReturnedValue();
|
||||
}
|
||||
|
@ -196,7 +201,7 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope
|
|||
|
||||
// Warn when attempting to access a lowercased enum value, singleton case
|
||||
if (!ok && includeEnums && !name->startsWithUpper()) {
|
||||
const int value = enumForSingleton(name, qobjectSingleton);
|
||||
const int value = enumForSingleton(v4, name, qobjectSingleton, type);
|
||||
if (value != -1)
|
||||
return throwLowercaseEnumError(v4, name, type);
|
||||
}
|
||||
|
|
|
@ -81,6 +81,14 @@ QAccessibleInterface *QAccessibleQuickWindow::child(int index) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
QAccessibleInterface *QAccessibleQuickWindow::focusChild() const
|
||||
{
|
||||
QObject *focusObject = window()->focusObject();
|
||||
if (focusObject)
|
||||
return QAccessible::queryAccessibleInterface(focusObject);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QAccessible::Role QAccessibleQuickWindow::role() const
|
||||
{
|
||||
return QAccessible::Window; // FIXME
|
||||
|
|
|
@ -65,6 +65,7 @@ public:
|
|||
|
||||
QAccessibleInterface *parent() const override;
|
||||
QAccessibleInterface *child(int index) const override;
|
||||
QAccessibleInterface *focusChild() const override;
|
||||
|
||||
QAccessible::Role role() const override;
|
||||
QAccessible::State state() const override;
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
||||
** contributors may be used to endorse or promote products derived
|
||||
** from this software without specific prior written permission.
|
||||
**
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
//![0]
|
||||
import QtQuick 2.0
|
||||
|
||||
Rectangle {
|
||||
color: "white"
|
||||
width: 200
|
||||
height: 100
|
||||
|
||||
Text {
|
||||
text: "?"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
function findGreetings() {
|
||||
var db = openDatabaseSync("QDeclarativeExampleDB", "1.0", "The Example QML SQL!", 1000000);
|
||||
|
||||
db.transaction(
|
||||
function(tx) {
|
||||
// Create the database if it doesn't already exist
|
||||
tx.executeSql('CREATE TABLE IF NOT EXISTS Greeting(salutation TEXT, salutee TEXT)');
|
||||
|
||||
// Add (another) greeting row
|
||||
tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
|
||||
|
||||
// Show all added greetings
|
||||
var rs = tx.executeSql('SELECT * FROM Greeting');
|
||||
|
||||
var r = ""
|
||||
for (var i = 0; i < rs.rows.length; i++) {
|
||||
r += rs.rows.item(i).salutation + ", " + rs.rows.item(i).salutee + "\n"
|
||||
}
|
||||
text = r
|
||||
}
|
||||
)
|
||||
}
|
||||
Component.onCompleted: findGreetings()
|
||||
}
|
||||
}
|
||||
//![0]
|
|
@ -64,7 +64,7 @@
|
|||
In addition to the above features, GridLayout adds these features:
|
||||
\list
|
||||
\li \l{Layout::row}{Grid coordinates} can be specified with the \l{Layout::row}{Layout.row} and
|
||||
\l{Layout::column}{Layout.column}.
|
||||
\l{Layout::column}{Layout.column} properties.
|
||||
\li \l{GridLayout::flow}{Automatic grid coordinates} used together with the
|
||||
\l{GridLayout::flow}{flow}, \l{GridLayout::rows}{rows}, and
|
||||
\l{GridLayout::columns}{columns} properties.
|
||||
|
|
|
@ -36,10 +36,10 @@
|
|||
Models can be defined in C++ and then made available to QML. This is useful
|
||||
for exposing existing C++ data models or otherwise complex datasets to QML.
|
||||
|
||||
A C++ model class can be defined as a \l QStringList, a QObjectList or a
|
||||
\l QAbstractItemModel. The first two are useful for exposing simpler datasets,
|
||||
while QAbstractItemModel provides a more flexible solution for more complex
|
||||
models.
|
||||
A C++ model class can be defined as a \l QStringList, a \l QVariantList, a
|
||||
QObjectList or a \l QAbstractItemModel. The first three are useful for exposing
|
||||
simpler datasets, while QAbstractItemModel provides a more flexible solution for
|
||||
more complex models.
|
||||
|
||||
\section2 QStringList-based Model
|
||||
|
||||
|
@ -60,10 +60,20 @@ The complete source code for this example is available in
|
|||
\l {models/stringlistmodel}{examples/quick/models/stringlistmodel}
|
||||
within the Qt install directory.
|
||||
|
||||
\b{Note:} There is no way for the view to know that the contents of a QStringList
|
||||
have changed. If the QStringList changes, it will be necessary to reset
|
||||
\note There is no way for the view to know that the contents of a QStringList
|
||||
have changed. If the QStringList changes, it will be necessary to reset
|
||||
the model by calling QQmlContext::setContextProperty() again.
|
||||
|
||||
\section2 QVariantList-based Model
|
||||
|
||||
A model may be a single \l QVariantList, which provides the contents of the list
|
||||
via the \e modelData role.
|
||||
|
||||
The API works just like with \l QStringList, as shown in the previous section.
|
||||
|
||||
\note There is no way for the view to know that the contents of a QVariantList
|
||||
have changed. If the QVariantList changes, it will be necessary to reset
|
||||
the model.
|
||||
|
||||
\section2 QObjectList-based model
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ them, and where possible, pristine Anchor layouts should be preferred.
|
|||
|
||||
\section1 Anchors
|
||||
|
||||
Anchors allows an item to be placed either adjacent to or inside of another,
|
||||
Anchors allow an item to be placed either adjacent to or inside of another,
|
||||
by attaching one or more of the item's anchor-points (boundaries) to an
|
||||
anchor-point of the other. These anchors will remain even if the dimensions
|
||||
or location of one of the items changes, allowing for highly dynamic
|
||||
|
|
|
@ -31,18 +31,14 @@
|
|||
|
||||
\section1 Scene Graph Adaptations in Qt Quick
|
||||
|
||||
Originally Qt Quick only had one available renderer for parsing the scene graph
|
||||
and rendering the results to a render target. This renderer is now the default
|
||||
OpenGL Renderer which supports rendering either using the OpenGL ES 2.0 or
|
||||
OpenGL 2.0 (with framebuffer object extensions) APIs. The Qt Quick APIs have
|
||||
originally been designed with the assumption that OpenGL is always available.
|
||||
However, it is now possible to use other graphics API's to render Qt Quick
|
||||
scenes using the scene graph APIs.
|
||||
Originally Qt Quick always relied on OpenGL (OpenGL ES 2.0 or OpenGL 2.0) for parsing
|
||||
the scene graph and rendering the results to a render target. From Qt 5.8 onwards
|
||||
Qt Quick also supports rendering in software and with Direct3D 12.
|
||||
|
||||
\section1 Switching between the adaptation used by the application
|
||||
|
||||
The default of the OpenGL, or - in Qt builds with disabled OpenGL support - the
|
||||
software adaptation, can be overridden either by using an environment variable
|
||||
The default rendering backend is still OpenGL, or - in Qt builds with disabled OpenGL support -
|
||||
the software renderer. This can be overridden either by using an environment variable
|
||||
or a C++ API. The former consists of setting the \c{QT_QUICK_BACKEND} or the
|
||||
legacy \c{QMLSCENE_DEVICE} environment variable before launching applications.
|
||||
The latter is done by calling QQuickWindow::setSceneGraphBackend() early in the
|
||||
|
|
|
@ -125,7 +125,7 @@ the blue rectangle and beneath any of the blue rectangle's children.
|
|||
|
||||
Stacking order can be influenced with the \l Item::z property. Z values below 0 will stack below the parent, and if z
|
||||
values are assigned then siblings will stack in z-order (with creation order used to break ties). Z values only affect
|
||||
stacking compared to siblings and the parent item. If you have an item who is obscured by a subtree rooted above its
|
||||
stacking compared to siblings and the parent item. If you have an item which is obscured by a subtree rooted above its
|
||||
parent item, no z value on that item will increase its stacking order to stack above that subtree. To stack that item
|
||||
above the other subtree you'll have to alter z values farther up in the hierarchy, or re-arrange the visual item
|
||||
hierarchy.
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include <QOpenGLFramebufferObject>
|
||||
#include <QOpenGLFramebufferObjectFormat>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QtGui/private/qopenglextensions_p.h>
|
||||
#endif
|
||||
#include <QtCore/QThread>
|
||||
#include <QtGui/QGuiApplication>
|
||||
|
@ -499,9 +500,9 @@ bool QQuickContext2DFBOTexture::doMultisampling() const
|
|||
static bool multisamplingSupported = false;
|
||||
|
||||
if (!extensionsChecked) {
|
||||
const QSet<QByteArray> extensions = QOpenGLContext::currentContext()->extensions();
|
||||
multisamplingSupported = extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_multisample"))
|
||||
&& extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_blit"));
|
||||
QOpenGLExtensions *e = static_cast<QOpenGLExtensions *>(QOpenGLContext::currentContext()->functions());
|
||||
multisamplingSupported = e->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
|
||||
&& e->hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
|
||||
extensionsChecked = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -2349,8 +2349,11 @@ bool QQuickFlickable::filterMouseEvent(QQuickItem *receiver, QMouseEvent *event)
|
|||
bool QQuickFlickable::childMouseEventFilter(QQuickItem *i, QEvent *e)
|
||||
{
|
||||
Q_D(QQuickFlickable);
|
||||
if (!isVisible() || !isEnabled() || !isInteractive())
|
||||
if (!isVisible() || !isEnabled() || !isInteractive()) {
|
||||
d->cancelInteraction();
|
||||
return QQuickItem::childMouseEventFilter(i, e);
|
||||
}
|
||||
|
||||
switch (e->type()) {
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseMove:
|
||||
|
|
|
@ -2911,14 +2911,15 @@ void QQuickItemPrivate::addChild(QQuickItem *child)
|
|||
|
||||
childItems.append(child);
|
||||
|
||||
#if QT_CONFIG(cursor)
|
||||
QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
|
||||
|
||||
#if QT_CONFIG(cursor)
|
||||
// if the added child has a cursor and we do not currently have any children
|
||||
// with cursors, bubble the notification up
|
||||
if (childPrivate->subtreeCursorEnabled && !subtreeCursorEnabled)
|
||||
setHasCursorInChild(true);
|
||||
#endif
|
||||
|
||||
if (childPrivate->subtreeHoverEnabled && !subtreeHoverEnabled)
|
||||
setHasHoverInChild(true);
|
||||
|
||||
|
@ -2939,13 +2940,14 @@ void QQuickItemPrivate::removeChild(QQuickItem *child)
|
|||
childItems.removeOne(child);
|
||||
Q_ASSERT(!childItems.contains(child));
|
||||
|
||||
#if QT_CONFIG(cursor)
|
||||
QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
|
||||
|
||||
#if QT_CONFIG(cursor)
|
||||
// turn it off, if nothing else is using it
|
||||
if (childPrivate->subtreeCursorEnabled && subtreeCursorEnabled)
|
||||
setHasCursorInChild(false);
|
||||
#endif
|
||||
|
||||
if (childPrivate->subtreeHoverEnabled && subtreeHoverEnabled)
|
||||
setHasHoverInChild(false);
|
||||
|
||||
|
@ -3807,10 +3809,10 @@ QQuickItem::UpdatePaintNodeData::UpdatePaintNodeData()
|
|||
|
||||
/*!
|
||||
This function is called when an item should release graphics
|
||||
resources which are not already managed by the nodes returend from
|
||||
resources which are not already managed by the nodes returned from
|
||||
QQuickItem::updatePaintNode().
|
||||
|
||||
This happens when the item is about to be removed from window it
|
||||
This happens when the item is about to be removed from the window it
|
||||
was previously rendering to. The item is guaranteed to have a
|
||||
\l {QQuickItem::window()}{window} when the function is called.
|
||||
|
||||
|
|
|
@ -689,9 +689,10 @@ void QQuickMouseArea::mousePressEvent(QMouseEvent *event)
|
|||
#endif
|
||||
setHovered(true);
|
||||
d->startScene = event->windowPos();
|
||||
d->pressAndHoldTimer.start(pressAndHoldInterval(), this);
|
||||
setKeepMouseGrab(d->stealMouse);
|
||||
event->setAccepted(setPressed(event->button(), true, event->source()));
|
||||
if (event->isAccepted())
|
||||
d->pressAndHoldTimer.start(pressAndHoldInterval(), this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -738,23 +739,34 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
|
|||
bool dragY = drag()->axis() & QQuickDrag::YAxis;
|
||||
|
||||
QPointF dragPos = d->drag->target()->position();
|
||||
QPointF boundedDragPos = dragPos;
|
||||
if (dragX) {
|
||||
dragPos.setX(qBound(
|
||||
dragPos.setX(startPos.x() + curLocalPos.x() - startLocalPos.x());
|
||||
boundedDragPos.setX(qBound(
|
||||
d->drag->xmin(),
|
||||
startPos.x() + curLocalPos.x() - startLocalPos.x(),
|
||||
dragPos.x(),
|
||||
d->drag->xmax()));
|
||||
}
|
||||
if (dragY) {
|
||||
dragPos.setY(qBound(
|
||||
dragPos.setY(startPos.y() + curLocalPos.y() - startLocalPos.y());
|
||||
boundedDragPos.setY(qBound(
|
||||
d->drag->ymin(),
|
||||
startPos.y() + curLocalPos.y() - startLocalPos.y(),
|
||||
dragPos.y(),
|
||||
d->drag->ymax()));
|
||||
}
|
||||
if (d->drag->active())
|
||||
d->drag->target()->setPosition(dragPos);
|
||||
|
||||
if (!d->overThreshold && (QQuickWindowPrivate::dragOverThreshold(dragPos.x() - startPos.x(), Qt::XAxis, event, d->drag->threshold())
|
||||
|| QQuickWindowPrivate::dragOverThreshold(dragPos.y() - startPos.y(), Qt::YAxis, event, d->drag->threshold())))
|
||||
QPointF targetPos = d->drag->target()->position();
|
||||
|
||||
if (d->drag->active())
|
||||
d->drag->target()->setPosition(boundedDragPos);
|
||||
|
||||
bool dragOverThresholdX = QQuickWindowPrivate::dragOverThreshold(dragPos.x() - startPos.x(),
|
||||
Qt::XAxis, event, d->drag->threshold());
|
||||
bool dragOverThresholdY = QQuickWindowPrivate::dragOverThreshold(dragPos.y() - startPos.y(),
|
||||
Qt::YAxis, event, d->drag->threshold());
|
||||
|
||||
if (!d->overThreshold && (((targetPos.x() != boundedDragPos.x()) && dragOverThresholdX) ||
|
||||
((targetPos.y() != boundedDragPos.y()) && dragOverThresholdY)))
|
||||
{
|
||||
d->overThreshold = true;
|
||||
if (d->drag->smoothed())
|
||||
|
|
|
@ -256,10 +256,14 @@ void QQuickOpenGLShaderEffectCommon::connectPropertySignals(QQuickItem *item,
|
|||
qWarning("QQuickOpenGLShaderEffect: property '%s' does not have notification method!", d.name.constData());
|
||||
} else {
|
||||
auto *mapper = signalMappers[shaderType].at(i);
|
||||
mapper->setSignalIndex(pd->notifyIndex());
|
||||
mapper->setSignalIndex(itemMetaObject->property(d.propertyIndex).notifySignal().methodIndex());
|
||||
Q_ASSERT(item->metaObject() == itemMetaObject);
|
||||
QObjectPrivate::connectImpl(item, mapper->signalIndex(), item, nullptr, mapper,
|
||||
Qt::AutoConnection, nullptr, itemMetaObject);
|
||||
bool ok = QObjectPrivate::connectImpl(item, pd->notifyIndex(), item, nullptr, mapper,
|
||||
Qt::AutoConnection, nullptr, itemMetaObject);
|
||||
if (!ok)
|
||||
qWarning() << "Failed to connect to property" << itemMetaObject->property(d.propertyIndex).name()
|
||||
<< "(" << d.propertyIndex << ", signal index" << pd->notifyIndex()
|
||||
<< ") of item" << item;
|
||||
}
|
||||
} else {
|
||||
// If the source is set via a dynamic property, like the layer is, then we need this
|
||||
|
|
|
@ -873,4 +873,9 @@ void QQuickShaderEffectPrivate::updatePolish()
|
|||
q->m_impl->maybeUpdateShaders();
|
||||
}
|
||||
|
||||
bool QQuickShaderEffect::isOpenGLShaderEffect() const
|
||||
{
|
||||
return m_glImpl != Q_NULLPTR;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
@ -117,6 +117,8 @@ public:
|
|||
bool isComponentComplete() const;
|
||||
QString parseLog();
|
||||
|
||||
bool isOpenGLShaderEffect() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void fragmentShaderChanged();
|
||||
void vertexShaderChanged();
|
||||
|
|
|
@ -635,8 +635,8 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
|
|||
|
||||
// FIXME: make this work for mouse events too and get rid of the asTouchEvent in here.
|
||||
Q_ASSERT(pointerEvent->asPointerTouchEvent());
|
||||
QTouchEvent *event = pointerEvent->asPointerTouchEvent()->touchEventForItem(item);
|
||||
if (!event)
|
||||
QScopedPointer<QTouchEvent> event(pointerEvent->asPointerTouchEvent()->touchEventForItem(item));
|
||||
if (event.isNull())
|
||||
return false;
|
||||
|
||||
// For each point, check if it is accepted, if not, try the next point.
|
||||
|
@ -653,7 +653,7 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
|
|||
break;
|
||||
|
||||
qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << p.id() << "->" << item;
|
||||
QScopedPointer<QMouseEvent> mousePress(touchToMouseEvent(QEvent::MouseButtonPress, p, event, item, false));
|
||||
QScopedPointer<QMouseEvent> mousePress(touchToMouseEvent(QEvent::MouseButtonPress, p, event.data(), item, false));
|
||||
|
||||
// Send a single press and see if that's accepted
|
||||
QCoreApplication::sendEvent(item, mousePress.data());
|
||||
|
@ -667,7 +667,7 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
|
|||
pointerEventPoint->setGrabber(item);
|
||||
|
||||
if (checkIfDoubleClicked(event->timestamp())) {
|
||||
QScopedPointer<QMouseEvent> mouseDoubleClick(touchToMouseEvent(QEvent::MouseButtonDblClick, p, event, item, false));
|
||||
QScopedPointer<QMouseEvent> mouseDoubleClick(touchToMouseEvent(QEvent::MouseButtonDblClick, p, event.data(), item, false));
|
||||
QCoreApplication::sendEvent(item, mouseDoubleClick.data());
|
||||
event->setAccepted(mouseDoubleClick->isAccepted());
|
||||
if (!mouseDoubleClick->isAccepted()) {
|
||||
|
@ -684,7 +684,7 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
|
|||
} else if (touchMouseDevice == device && p.id() == touchMouseId) {
|
||||
if (p.state() & Qt::TouchPointMoved) {
|
||||
if (QQuickItem *mouseGrabberItem = q->mouseGrabberItem()) {
|
||||
QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseMove, p, event, mouseGrabberItem, false));
|
||||
QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseMove, p, event.data(), mouseGrabberItem, false));
|
||||
QCoreApplication::sendEvent(item, me.data());
|
||||
event->setAccepted(me->isAccepted());
|
||||
if (me->isAccepted()) {
|
||||
|
@ -695,7 +695,7 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
|
|||
// no grabber, check if we care about mouse hover
|
||||
// FIXME: this should only happen once, not recursively... I'll ignore it just ignore hover now.
|
||||
// hover for touch???
|
||||
QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseMove, p, event, item, false));
|
||||
QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseMove, p, event.data(), item, false));
|
||||
if (lastMousePosition.isNull())
|
||||
lastMousePosition = me->windowPos();
|
||||
QPointF last = lastMousePosition;
|
||||
|
@ -713,7 +713,7 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
|
|||
} else if (p.state() & Qt::TouchPointReleased) {
|
||||
// currently handled point was released
|
||||
if (QQuickItem *mouseGrabberItem = q->mouseGrabberItem()) {
|
||||
QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseButtonRelease, p, event, mouseGrabberItem, false));
|
||||
QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseButtonRelease, p, event.data(), mouseGrabberItem, false));
|
||||
QCoreApplication::sendEvent(item, me.data());
|
||||
|
||||
if (item->acceptHoverEvents() && p.screenPos() != QGuiApplicationPrivate::lastCursorPosition) {
|
||||
|
@ -4495,8 +4495,8 @@ QSGRendererInterface *QQuickWindow::rendererInterface() const
|
|||
\note The call to the function must happen before constructing the first
|
||||
QQuickWindow in the application. It cannot be changed afterwards.
|
||||
|
||||
If \a backend is invalid or an error occurs, the default backend (OpenGL or
|
||||
software, depending on the Qt configuration) is used.
|
||||
If the selected backend is invalid or an error occurs, the default backend
|
||||
(OpenGL or software, depending on the Qt configuration) is used.
|
||||
|
||||
\since 5.8
|
||||
*/
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
|
||||
#include <QtGui/QOpenGLFramebufferObject>
|
||||
#include <QtGui/QOpenGLFunctions>
|
||||
#include <QtGui/private/qopenglextensions_p.h>
|
||||
|
||||
#include <QtQuick/private/qsgdepthstencilbuffer_p.h>
|
||||
|
||||
|
@ -320,9 +321,9 @@ void QSGDefaultLayer::grab()
|
|||
if (m_context->openglContext()->format().samples() <= 1) {
|
||||
m_multisampling = false;
|
||||
} else {
|
||||
const QSet<QByteArray> extensions = m_context->openglContext()->extensions();
|
||||
m_multisampling = extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_multisample"))
|
||||
&& extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_blit"));
|
||||
QOpenGLExtensions *e = static_cast<QOpenGLExtensions *>(funcs);
|
||||
m_multisampling = e->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
|
||||
&& e->hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
|
||||
}
|
||||
m_multisamplingChecked = true;
|
||||
}
|
||||
|
|
|
@ -238,9 +238,9 @@ void QSGDefaultPainterNode::updateGeometry()
|
|||
void QSGDefaultPainterNode::updateRenderTarget()
|
||||
{
|
||||
if (!m_extensionsChecked) {
|
||||
const QSet<QByteArray> extensions = m_context->openglContext()->extensions();
|
||||
m_multisamplingSupported = extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_multisample"))
|
||||
&& extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_blit"));
|
||||
QOpenGLExtensions *e = static_cast<QOpenGLExtensions *>(QOpenGLContext::currentContext()->functions());
|
||||
m_multisamplingSupported = e->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
|
||||
&& e->hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
|
||||
m_extensionsChecked = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#if QT_CONFIG(quick_shadereffect) && QT_CONFIG(opengl)
|
||||
# include <private/qquickopenglshadereffectnode_p.h>
|
||||
# include <private/qquickopenglshadereffect_p.h>
|
||||
# include <private/qquickshadereffect_p.h>
|
||||
#endif
|
||||
#include <private/qanimationgroupjob_p.h>
|
||||
|
||||
|
@ -625,7 +626,8 @@ QQuickUniformAnimatorJob::QQuickUniformAnimatorJob()
|
|||
|
||||
void QQuickUniformAnimatorJob::setTarget(QQuickItem *target)
|
||||
{
|
||||
if (qobject_cast<QQuickOpenGLShaderEffect *>(target) != nullptr)
|
||||
QQuickShaderEffect* effect = qobject_cast<QQuickShaderEffect*>(target);
|
||||
if (effect && effect->isOpenGLShaderEffect())
|
||||
m_target = target;
|
||||
}
|
||||
|
||||
|
|
|
@ -151,6 +151,8 @@ QQuickTextureFactory *QQuickTextureFactory::textureFactoryForImage(const QImage
|
|||
If you are using QRunnable as base for your QQuickImageResponse
|
||||
ensure automatic deletion is disabled.
|
||||
|
||||
See the \l {imageresponseprovider}{Image Response Provider Example} for a complete implementation.
|
||||
|
||||
\sa QQuickImageProvider
|
||||
*/
|
||||
|
||||
|
@ -466,6 +468,8 @@ QQuickTextureFactory *QQuickImageProvider::requestTexture(const QString &id, QSi
|
|||
\inmodule QtQuick
|
||||
\brief The QQuickAsyncImageProvider class provides an interface for for asynchronous control of QML image requests.
|
||||
|
||||
See the \l {imageresponseprovider}{Image Response Provider Example} for a complete implementation.
|
||||
|
||||
\sa QQuickImageProvider
|
||||
*/
|
||||
QQuickAsyncImageProvider::QQuickAsyncImageProvider()
|
||||
|
|
|
@ -5,7 +5,7 @@ QT_FOR_CONFIG += network quick-private
|
|||
SUBDIRS += \
|
||||
qml
|
||||
|
||||
qtHaveModule(gui) {
|
||||
qtHaveModule(gui):qtConfig(animation) {
|
||||
SUBDIRS += \
|
||||
quick \
|
||||
qmltest
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -73,7 +73,7 @@ qtHaveModule(widgets) {
|
|||
SUBDIRS += $$PUBLICTESTS \
|
||||
qqmlextensionplugin
|
||||
SUBDIRS += $$METATYPETESTS
|
||||
!qtConfig(process) {
|
||||
qtConfig(process) {
|
||||
!contains(QT_CONFIG, no-qml-debug): SUBDIRS += debugger
|
||||
SUBDIRS += qmllint qmlplugindump
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import QtQml 2.2
|
||||
import x.y.z 1.0
|
||||
|
||||
QtObject {
|
||||
function x() {
|
||||
eval("1");
|
||||
return ExternalEnums.DocumentsLocation;
|
||||
}
|
||||
|
||||
property var a: ExternalEnums.DocumentsLocation
|
||||
property var b: x()
|
||||
}
|
|
@ -26,6 +26,7 @@
|
|||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <qstandardpaths.h>
|
||||
#include <qtest.h>
|
||||
#include <qqml.h>
|
||||
#include <qqmlprivate.h>
|
||||
|
@ -53,6 +54,7 @@ private slots:
|
|||
void invalidQmlTypeName();
|
||||
void registrationType();
|
||||
void compositeType();
|
||||
void externalEnums();
|
||||
|
||||
void isList();
|
||||
|
||||
|
@ -70,6 +72,20 @@ public:
|
|||
};
|
||||
QML_DECLARE_TYPE(TestType);
|
||||
|
||||
class ExternalEnums : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_ENUMS(QStandardPaths::StandardLocation QStandardPaths::LocateOptions)
|
||||
public:
|
||||
ExternalEnums(QObject *parent = nullptr) : QObject(parent) {}
|
||||
|
||||
static QObject *create(QQmlEngine *engine, QJSEngine *scriptEngine) {
|
||||
Q_UNUSED(scriptEngine);
|
||||
return new ExternalEnums(engine);
|
||||
}
|
||||
};
|
||||
QML_DECLARE_TYPE(ExternalEnums);
|
||||
|
||||
QObject *testTypeProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
|
||||
{
|
||||
Q_UNUSED(engine);
|
||||
|
@ -271,6 +287,23 @@ void tst_qqmlmetatype::compositeType()
|
|||
QCOMPARE(type->sourceUrl(), testFileUrl("ImplicitType.qml"));
|
||||
}
|
||||
|
||||
void tst_qqmlmetatype::externalEnums()
|
||||
{
|
||||
QQmlEngine engine;
|
||||
qmlRegisterSingletonType<ExternalEnums>("x.y.z", 1, 0, "ExternalEnums", ExternalEnums::create);
|
||||
|
||||
QQmlComponent c(&engine, testFileUrl("testExternalEnums.qml"));
|
||||
QObject *obj = c.create();
|
||||
QVERIFY(obj);
|
||||
QVariant a = obj->property("a");
|
||||
QCOMPARE(a.type(), QVariant::Int);
|
||||
QCOMPARE(a.toInt(), int(QStandardPaths::DocumentsLocation));
|
||||
QVariant b = obj->property("b");
|
||||
QCOMPARE(b.type(), QVariant::Int);
|
||||
QCOMPARE(b.toInt(), int(QStandardPaths::DocumentsLocation));
|
||||
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_qqmlmetatype)
|
||||
|
||||
#include "tst_qqmlmetatype.moc"
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import QtQuick 2.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property real test: 9
|
||||
property real test2: 3
|
||||
|
||||
property alias aliasProperty: innerObject.realProperty
|
||||
|
||||
property QtObject innerObject: QtObject {
|
||||
id: innerObject
|
||||
property real realProperty: test * test + test
|
||||
}
|
||||
|
||||
states: State {
|
||||
name: "switch"
|
||||
PropertyChanges {
|
||||
target: root
|
||||
aliasProperty: 32 * test2
|
||||
}
|
||||
}
|
||||
}
|
|
@ -135,6 +135,7 @@ private slots:
|
|||
|
||||
// Bugs
|
||||
void crashOnValueProperty();
|
||||
void aliasPropertyBindings_data();
|
||||
void aliasPropertyBindings();
|
||||
void noContext();
|
||||
void assignEmptyVariantMap();
|
||||
|
@ -1833,23 +1834,40 @@ void tst_qqmlproperty::crashOnValueProperty()
|
|||
QCOMPARE(p.read(), QVariant(20));
|
||||
}
|
||||
|
||||
// QTBUG-13719
|
||||
void tst_qqmlproperty::aliasPropertyBindings_data()
|
||||
{
|
||||
QTest::addColumn<QString>("file");
|
||||
QTest::addColumn<QString>("subObject");
|
||||
|
||||
QTest::newRow("same object") << "aliasPropertyBindings.qml" << "";
|
||||
QTest::newRow("different objects") << "aliasPropertyBindings2.qml" << "innerObject";
|
||||
}
|
||||
|
||||
// QTBUG-13719, QTBUG-58271
|
||||
void tst_qqmlproperty::aliasPropertyBindings()
|
||||
{
|
||||
QQmlComponent component(&engine, testFileUrl("aliasPropertyBindings.qml"));
|
||||
QFETCH(QString, file);
|
||||
QFETCH(QString, subObject);
|
||||
|
||||
QQmlComponent component(&engine, testFileUrl(file));
|
||||
|
||||
QObject *object = component.create();
|
||||
QVERIFY(object != 0);
|
||||
|
||||
QCOMPARE(object->property("realProperty").toReal(), 90.);
|
||||
// the object where realProperty lives
|
||||
QObject *realPropertyObject = object;
|
||||
if (!subObject.isEmpty())
|
||||
realPropertyObject = object->property(subObject.toLatin1()).value<QObject*>();
|
||||
|
||||
QCOMPARE(realPropertyObject->property("realProperty").toReal(), 90.);
|
||||
QCOMPARE(object->property("aliasProperty").toReal(), 90.);
|
||||
|
||||
object->setProperty("test", 10);
|
||||
|
||||
QCOMPARE(object->property("realProperty").toReal(), 110.);
|
||||
QCOMPARE(realPropertyObject->property("realProperty").toReal(), 110.);
|
||||
QCOMPARE(object->property("aliasProperty").toReal(), 110.);
|
||||
|
||||
QQmlProperty realProperty(object, QLatin1String("realProperty"));
|
||||
QQmlProperty realProperty(realPropertyObject, QLatin1String("realProperty"));
|
||||
QQmlProperty aliasProperty(object, QLatin1String("aliasProperty"));
|
||||
|
||||
// Check there is a binding on these two properties
|
||||
|
@ -1868,18 +1886,18 @@ void tst_qqmlproperty::aliasPropertyBindings()
|
|||
QCOMPARE(QQmlPropertyPrivate::binding(realProperty),
|
||||
QQmlPropertyPrivate::binding(aliasProperty));
|
||||
|
||||
QCOMPARE(object->property("realProperty").toReal(), 96.);
|
||||
QCOMPARE(realPropertyObject->property("realProperty").toReal(), 96.);
|
||||
QCOMPARE(object->property("aliasProperty").toReal(), 96.);
|
||||
|
||||
// Check the old binding really has not effect any more
|
||||
object->setProperty("test", 4);
|
||||
|
||||
QCOMPARE(object->property("realProperty").toReal(), 96.);
|
||||
QCOMPARE(realPropertyObject->property("realProperty").toReal(), 96.);
|
||||
QCOMPARE(object->property("aliasProperty").toReal(), 96.);
|
||||
|
||||
object->setProperty("test2", 9);
|
||||
|
||||
QCOMPARE(object->property("realProperty").toReal(), 288.);
|
||||
QCOMPARE(realPropertyObject->property("realProperty").toReal(), 288.);
|
||||
QCOMPARE(object->property("aliasProperty").toReal(), 288.);
|
||||
|
||||
// Revert
|
||||
|
@ -1890,12 +1908,12 @@ void tst_qqmlproperty::aliasPropertyBindings()
|
|||
QCOMPARE(QQmlPropertyPrivate::binding(realProperty),
|
||||
QQmlPropertyPrivate::binding(aliasProperty));
|
||||
|
||||
QCOMPARE(object->property("realProperty").toReal(), 20.);
|
||||
QCOMPARE(realPropertyObject->property("realProperty").toReal(), 20.);
|
||||
QCOMPARE(object->property("aliasProperty").toReal(), 20.);
|
||||
|
||||
object->setProperty("test2", 3);
|
||||
|
||||
QCOMPARE(object->property("realProperty").toReal(), 20.);
|
||||
QCOMPARE(realPropertyObject->property("realProperty").toReal(), 20.);
|
||||
QCOMPARE(object->property("aliasProperty").toReal(), 20.);
|
||||
|
||||
delete object;
|
||||
|
@ -1996,7 +2014,7 @@ void tst_qqmlproperty::warnOnInvalidBinding()
|
|||
QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
|
||||
|
||||
// V8 error message for invalid binding to anchor
|
||||
expectedWarning = testUrl.toString() + QString::fromLatin1(":14:33: Unable to assign QQuickItem_QML_6 to QQuickAnchorLine");
|
||||
expectedWarning = testUrl.toString() + QString::fromLatin1(":14:33: Unable to assign QQuickItem_QML_8 to QQuickAnchorLine");
|
||||
QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
|
||||
|
||||
QQmlComponent component(&engine, testUrl);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <qtest.h>
|
||||
|
||||
#define V4_AUTOTEST
|
||||
#include <private/qv4ssa_p.h>
|
||||
|
||||
class tst_v4misc: public QObject
|
||||
|
@ -40,6 +41,9 @@ private slots:
|
|||
void rangeSplitting_1();
|
||||
void rangeSplitting_2();
|
||||
void rangeSplitting_3();
|
||||
|
||||
void moveMapping_1();
|
||||
void moveMapping_2();
|
||||
};
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
@ -139,6 +143,94 @@ void tst_v4misc::rangeSplitting_3()
|
|||
QCOMPARE(interval.end(), 71);
|
||||
}
|
||||
|
||||
void tst_v4misc::moveMapping_1()
|
||||
{
|
||||
Temp fp2(DoubleType, Temp::PhysicalRegister, 2);
|
||||
Temp fp3(DoubleType, Temp::PhysicalRegister, 3);
|
||||
Temp fp4(DoubleType, Temp::PhysicalRegister, 4);
|
||||
Temp fp5(DoubleType, Temp::PhysicalRegister, 5);
|
||||
|
||||
MoveMapping mapping;
|
||||
mapping.add(&fp2, &fp3);
|
||||
mapping.add(&fp2, &fp4);
|
||||
mapping.add(&fp2, &fp5);
|
||||
mapping.add(&fp3, &fp2);
|
||||
|
||||
mapping.order();
|
||||
// mapping.dump();
|
||||
|
||||
QCOMPARE(mapping._moves.size(), 3);
|
||||
QVERIFY(mapping._moves.contains(MoveMapping::Move(&fp2, &fp4, false)));
|
||||
QVERIFY(mapping._moves.contains(MoveMapping::Move(&fp2, &fp5, false)));
|
||||
QVERIFY(mapping._moves.last() == MoveMapping::Move(&fp2, &fp3, true) ||
|
||||
mapping._moves.last() == MoveMapping::Move(&fp3, &fp2, true));
|
||||
}
|
||||
|
||||
void tst_v4misc::moveMapping_2()
|
||||
{
|
||||
Temp fp1(DoubleType, Temp::PhysicalRegister, 1);
|
||||
Temp fp2(DoubleType, Temp::PhysicalRegister, 2);
|
||||
Temp fp3(DoubleType, Temp::PhysicalRegister, 3);
|
||||
Temp fp4(DoubleType, Temp::PhysicalRegister, 4);
|
||||
Temp fp5(DoubleType, Temp::PhysicalRegister, 5);
|
||||
Temp fp6(DoubleType, Temp::PhysicalRegister, 6);
|
||||
Temp fp7(DoubleType, Temp::PhysicalRegister, 7);
|
||||
Temp fp8(DoubleType, Temp::PhysicalRegister, 8);
|
||||
Temp fp9(DoubleType, Temp::PhysicalRegister, 9);
|
||||
Temp fp10(DoubleType, Temp::PhysicalRegister, 10);
|
||||
Temp fp11(DoubleType, Temp::PhysicalRegister, 11);
|
||||
Temp fp12(DoubleType, Temp::PhysicalRegister, 12);
|
||||
Temp fp13(DoubleType, Temp::PhysicalRegister, 13);
|
||||
|
||||
MoveMapping mapping;
|
||||
mapping.add(&fp2, &fp1);
|
||||
mapping.add(&fp2, &fp3);
|
||||
mapping.add(&fp3, &fp2);
|
||||
mapping.add(&fp3, &fp4);
|
||||
|
||||
mapping.add(&fp9, &fp8);
|
||||
mapping.add(&fp8, &fp7);
|
||||
mapping.add(&fp7, &fp6);
|
||||
mapping.add(&fp7, &fp5);
|
||||
|
||||
mapping.add(&fp10, &fp11);
|
||||
mapping.add(&fp11, &fp12);
|
||||
mapping.add(&fp12, &fp13);
|
||||
mapping.add(&fp13, &fp10);
|
||||
|
||||
mapping.order();
|
||||
// mapping.dump();
|
||||
|
||||
QCOMPARE(mapping._moves.size(), 10);
|
||||
|
||||
QVERIFY(mapping._moves.contains(MoveMapping::Move(&fp2, &fp1, false)));
|
||||
QVERIFY(mapping._moves.contains(MoveMapping::Move(&fp3, &fp4, false)));
|
||||
QVERIFY(mapping._moves.contains(MoveMapping::Move(&fp7, &fp6, false)));
|
||||
QVERIFY(mapping._moves.contains(MoveMapping::Move(&fp7, &fp5, false)));
|
||||
QVERIFY(mapping._moves.contains(MoveMapping::Move(&fp8, &fp7, false)));
|
||||
QVERIFY(mapping._moves.contains(MoveMapping::Move(&fp9, &fp8, false)));
|
||||
|
||||
QVERIFY(mapping._moves.contains(MoveMapping::Move(&fp2, &fp3, true)) ||
|
||||
mapping._moves.contains(MoveMapping::Move(&fp3, &fp2, true)));
|
||||
QVERIFY(mapping._moves.contains(MoveMapping::Move(&fp10, &fp13, true)) ||
|
||||
mapping._moves.contains(MoveMapping::Move(&fp13, &fp10, true)));
|
||||
QVERIFY(mapping._moves.contains(MoveMapping::Move(&fp12, &fp13, true)) ||
|
||||
mapping._moves.contains(MoveMapping::Move(&fp13, &fp12, true)));
|
||||
QVERIFY(mapping._moves.contains(MoveMapping::Move(&fp12, &fp11, true)) ||
|
||||
mapping._moves.contains(MoveMapping::Move(&fp11, &fp12, true)));
|
||||
|
||||
QVERIFY(!mapping._moves.at(0).needsSwap);
|
||||
QVERIFY(!mapping._moves.at(1).needsSwap);
|
||||
QVERIFY(!mapping._moves.at(2).needsSwap);
|
||||
QVERIFY(!mapping._moves.at(3).needsSwap);
|
||||
QVERIFY(!mapping._moves.at(4).needsSwap);
|
||||
QVERIFY(!mapping._moves.at(5).needsSwap);
|
||||
QVERIFY(mapping._moves.at(6).needsSwap);
|
||||
QVERIFY(mapping._moves.at(7).needsSwap);
|
||||
QVERIFY(mapping._moves.at(8).needsSwap);
|
||||
QVERIFY(mapping._moves.at(9).needsSwap);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_v4misc)
|
||||
|
||||
#include "tst_v4misc.moc"
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
import QtQuick 2.0
|
||||
|
||||
Flickable {
|
||||
id: flickable
|
||||
width: 200; height: 200
|
||||
contentWidth: 400; contentHeight: 400
|
||||
|
||||
MouseArea {
|
||||
objectName: "mouseArea"
|
||||
width: 400; height: 400
|
||||
onDoubleClicked: flickable.visible = false
|
||||
}
|
||||
}
|
|
@ -80,6 +80,7 @@ private slots:
|
|||
void disabled();
|
||||
void flickVelocity();
|
||||
void margins();
|
||||
void cancelOnHide();
|
||||
void cancelOnMouseGrab();
|
||||
void clickAndDragWhenTransformed();
|
||||
void flickTwiceUsingTouches();
|
||||
|
@ -1425,6 +1426,25 @@ void tst_qquickflickable::margins()
|
|||
delete root;
|
||||
}
|
||||
|
||||
void tst_qquickflickable::cancelOnHide()
|
||||
{
|
||||
QScopedPointer<QQuickView> window(new QQuickView);
|
||||
window->setSource(testFileUrl("hide.qml"));
|
||||
QTRY_COMPARE(window->status(), QQuickView::Ready);
|
||||
QQuickViewTestUtil::centerOnScreen(window.data());
|
||||
QQuickViewTestUtil::moveMouseAway(window.data());
|
||||
window->show();
|
||||
QVERIFY(QTest::qWaitForWindowActive(window.data()));
|
||||
QVERIFY(window->rootObject());
|
||||
|
||||
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
|
||||
QVERIFY(flickable);
|
||||
|
||||
QTest::mouseDClick(window.data(), Qt::LeftButton);
|
||||
QVERIFY(!flickable->isVisible());
|
||||
QVERIFY(!QQuickFlickablePrivate::get(flickable)->pressed);
|
||||
}
|
||||
|
||||
void tst_qquickflickable::cancelOnMouseGrab()
|
||||
{
|
||||
QScopedPointer<QQuickView> window(new QQuickView);
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import QtQuick 2.0
|
||||
|
||||
Rectangle {
|
||||
width: 400
|
||||
height: 200
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
objectName: "mouseArea"
|
||||
width: 200
|
||||
height: 200
|
||||
|
||||
drag.target: mouseArea
|
||||
drag.axis: Drag.XAxis
|
||||
drag.minimumX: 0
|
||||
drag.maximumX: 200
|
||||
drag.threshold: 200
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "red"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -88,6 +88,7 @@ private slots:
|
|||
void invalidDrag_data() { rejectedButton_data(); }
|
||||
void invalidDrag();
|
||||
void cancelDragging();
|
||||
void availableDistanceLessThanDragThreshold();
|
||||
void setDragOnPressed();
|
||||
void updateMouseAreaPosOnClick();
|
||||
void updateMouseAreaPosOnResize();
|
||||
|
@ -585,6 +586,35 @@ void tst_QQuickMouseArea::cancelDragging()
|
|||
QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(122,122));
|
||||
}
|
||||
|
||||
// QTBUG-58347
|
||||
void tst_QQuickMouseArea::availableDistanceLessThanDragThreshold()
|
||||
{
|
||||
QQuickView view;
|
||||
QByteArray errorMessage;
|
||||
QVERIFY2(initView(view, testFileUrl("availableDistanceLessThanDragThreshold.qml"), true, &errorMessage),
|
||||
errorMessage.constData());
|
||||
view.show();
|
||||
view.requestActivate();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(&view));
|
||||
QVERIFY(view.rootObject());
|
||||
|
||||
QQuickMouseArea *mouseArea = view.rootObject()->findChild<QQuickMouseArea*>("mouseArea");
|
||||
QVERIFY(mouseArea);
|
||||
|
||||
QPoint position(100, 100);
|
||||
QTest::mousePress(&view, Qt::LeftButton, 0, position);
|
||||
QTest::qWait(10);
|
||||
position.setX(301);
|
||||
QTest::mouseMove(&view, position);
|
||||
position.setX(501);
|
||||
QTest::mouseMove(&view, position);
|
||||
QVERIFY(mouseArea->drag()->active());
|
||||
QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
|
||||
|
||||
QVERIFY(!mouseArea->drag()->active());
|
||||
QCOMPARE(mouseArea->x(), 200.0);
|
||||
}
|
||||
|
||||
void tst_QQuickMouseArea::setDragOnPressed()
|
||||
{
|
||||
QQuickView window;
|
||||
|
|
|
@ -6,6 +6,15 @@ HEADERS += conf.h
|
|||
SOURCES += main.cpp
|
||||
RESOURCES += qml.qrc
|
||||
|
||||
QMAKE_TARGET_PRODUCT = qml
|
||||
QMAKE_TARGET_DESCRIPTION = Utility that loads and displays QML documents
|
||||
|
||||
win32 {
|
||||
VERSION = $${QT_VERSION}.0
|
||||
} else {
|
||||
VERSION = $${QT_VERSION}
|
||||
}
|
||||
|
||||
mac {
|
||||
OTHER_FILES += Info.plist
|
||||
QMAKE_INFO_PLIST = Info.plist
|
||||
|
|
|
@ -17,4 +17,13 @@ FORMS += \
|
|||
pane.ui \
|
||||
import.ui
|
||||
|
||||
QMAKE_TARGET_PRODUCT = qmleasing
|
||||
QMAKE_TARGET_DESCRIPTION = QML easing curve editor
|
||||
|
||||
win32 {
|
||||
VERSION = $${QT_VERSION}.0
|
||||
} else {
|
||||
VERSION = $${QT_VERSION}
|
||||
}
|
||||
|
||||
load(qt_app)
|
||||
|
|
|
@ -5,4 +5,13 @@ DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII
|
|||
|
||||
SOURCES += main.cpp
|
||||
|
||||
QMAKE_TARGET_PRODUCT = qmlimportscanner
|
||||
QMAKE_TARGET_DESCRIPTION = Tool to scan projects for QML imports
|
||||
|
||||
win32 {
|
||||
VERSION = $${QT_VERSION}.0
|
||||
} else {
|
||||
VERSION = $${QT_VERSION}
|
||||
}
|
||||
|
||||
load(qt_tool)
|
||||
|
|
|
@ -5,4 +5,13 @@ SOURCES = qmljs.cpp
|
|||
|
||||
include($$PWD/../../src/3rdparty/masm/masm-defs.pri)
|
||||
|
||||
QMAKE_TARGET_PRODUCT = qmljs
|
||||
QMAKE_TARGET_DESCRIPTION = QML Javascript tool
|
||||
|
||||
win32 {
|
||||
VERSION = $${QT_VERSION}.0
|
||||
} else {
|
||||
VERSION = $${QT_VERSION}
|
||||
}
|
||||
|
||||
load(qt_tool)
|
||||
|
|
|
@ -4,4 +4,13 @@ QT = core qmldevtools-private
|
|||
|
||||
SOURCES += main.cpp
|
||||
|
||||
QMAKE_TARGET_PRODUCT = qmllint
|
||||
QMAKE_TARGET_DESCRIPTION = QML syntax verifier
|
||||
|
||||
win32 {
|
||||
VERSION = $${QT_VERSION}.0
|
||||
} else {
|
||||
VERSION = $${QT_VERSION}
|
||||
}
|
||||
|
||||
load(qt_tool)
|
||||
|
|
|
@ -2,4 +2,13 @@ option(host_build)
|
|||
QT = core qmldevtools-private
|
||||
SOURCES += main.cpp
|
||||
|
||||
QMAKE_TARGET_PRODUCT = qmlmin
|
||||
QMAKE_TARGET_DESCRIPTION = QML/JS minifier
|
||||
|
||||
win32 {
|
||||
VERSION = $${QT_VERSION}.0
|
||||
} else {
|
||||
VERSION = $${QT_VERSION}
|
||||
}
|
||||
|
||||
load(qt_tool)
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
#include <QtQuick/private/qquickevents_p_p.h>
|
||||
#include <QtQuick/private/qquickpincharea_p.h>
|
||||
|
||||
#ifdef QT_WIDGETS_LIB
|
||||
#include <QApplication>
|
||||
#endif // QT_WIDGETS_LIB
|
||||
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QFileInfo>
|
||||
|
@ -741,8 +745,8 @@ void sigSegvHandler(int) {
|
|||
void printUsage(const QString &appName)
|
||||
{
|
||||
std::cerr << qPrintable(QString(
|
||||
"Usage: %1 [-v] [-noinstantiate] [-defaultplatform] [-[non]relocatable] [-dependencies <dependencies.json>] [-merge <file-to-merge.qmltypes>] [-output <output-file.qmltypes>] [-noforceqtquick] module.uri version [module/import/path]\n"
|
||||
" %1 [-v] [-noinstantiate] -path path/to/qmldir/directory [version]\n"
|
||||
"Usage: %1 [-v] [-qapp] [-noinstantiate] [-defaultplatform] [-[non]relocatable] [-dependencies <dependencies.json>] [-merge <file-to-merge.qmltypes>] [-output <output-file.qmltypes>] [-noforceqtquick] module.uri version [module/import/path]\n"
|
||||
" %1 [-v] [-qapp] [-noinstantiate] -path path/to/qmldir/directory [version]\n"
|
||||
" %1 [-v] -builtins\n"
|
||||
"Example: %1 Qt.labs.folderlistmodel 2.0 /home/user/dev/qt-install/imports").arg(
|
||||
appName)) << std::endl;
|
||||
|
@ -866,7 +870,7 @@ static bool getDependencies(const QQmlEngine &engine, const QString &pluginImpor
|
|||
QByteArray depencenciesData = importScanner.readAllStandardOutput();
|
||||
if (!readDependenciesData(QLatin1String("<outputOfQmlimportscanner>"), depencenciesData,
|
||||
dependencies, QStringList(pluginImportUri), forceQtQuickDependency)) {
|
||||
std::cerr << "failed to proecess output of qmlimportscanner" << std::endl;
|
||||
std::cerr << "failed to process output of qmlimportscanner" << std::endl;
|
||||
if (importScanner.exitCode() != 0)
|
||||
std::cerr << importScanner.readAllStandardError().toStdString();
|
||||
return false;
|
||||
|
@ -992,10 +996,25 @@ int main(int argc, char *argv[])
|
|||
else
|
||||
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true);
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
// Check which kind of application should be instantiated.
|
||||
bool useQApplication = false;
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
QString arg = QLatin1String(argv[1]);
|
||||
if (arg == QLatin1String("--qapp") || arg == QLatin1String("-qapp"))
|
||||
useQApplication = true;
|
||||
}
|
||||
|
||||
#ifdef QT_WIDGETS_LIB
|
||||
QScopedPointer<QCoreApplication> app(useQApplication
|
||||
? new QApplication(argc, argv)
|
||||
: new QGuiApplication(argc, argv));
|
||||
#else
|
||||
QScopedPointer<QCoreApplication> app(new QGuiApplication(argc, argv));
|
||||
#endif // QT_WIDGETS_LIB
|
||||
|
||||
QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));
|
||||
const QStringList args = app.arguments();
|
||||
const QString appName = QFileInfo(app.applicationFilePath()).baseName();
|
||||
const QStringList args = app->arguments();
|
||||
const QString appName = QFileInfo(app->applicationFilePath()).baseName();
|
||||
if (args.size() < 2) {
|
||||
printUsage(appName);
|
||||
return EXIT_INVALIDARGUMENTS;
|
||||
|
@ -1065,6 +1084,9 @@ int main(int argc, char *argv[])
|
|||
} else if (arg == QLatin1String("--defaultplatform")
|
||||
|| arg == QLatin1String("-defaultplatform")) {
|
||||
continue;
|
||||
} else if (arg == QLatin1String("--qapp")
|
||||
|| arg == QLatin1String("-qapp")) {
|
||||
continue;
|
||||
} else {
|
||||
std::cerr << "Invalid argument: " << qPrintable(arg) << std::endl;
|
||||
return EXIT_INVALIDARGUMENTS;
|
||||
|
@ -1331,8 +1353,8 @@ int main(int argc, char *argv[])
|
|||
QTimer timer;
|
||||
timer.setSingleShot(true);
|
||||
timer.setInterval(0);
|
||||
QObject::connect(&timer, SIGNAL(timeout()), &app, SLOT(quit()));
|
||||
QObject::connect(&timer, SIGNAL(timeout()), app.data(), SLOT(quit()));
|
||||
timer.start();
|
||||
|
||||
return app.exec();
|
||||
return app->exec();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
QT += qml qml-private quick-private core-private
|
||||
qtHaveModule(widgets): QT += widgets
|
||||
|
||||
CONFIG += no_import_scan
|
||||
|
||||
|
@ -21,4 +22,13 @@ macx {
|
|||
CONFIG -= app_bundle
|
||||
}
|
||||
|
||||
QMAKE_TARGET_PRODUCT = qmlplugindump
|
||||
QMAKE_TARGET_DESCRIPTION = QML plugin dump tool
|
||||
|
||||
win32 {
|
||||
VERSION = $${QT_VERSION}.0
|
||||
} else {
|
||||
VERSION = $${QT_VERSION}
|
||||
}
|
||||
|
||||
load(qt_tool)
|
||||
|
|
|
@ -14,4 +14,13 @@ HEADERS += \
|
|||
qmlprofilerdata.h \
|
||||
qmlprofilerclient.h
|
||||
|
||||
QMAKE_TARGET_PRODUCT = qmlprofiler
|
||||
QMAKE_TARGET_DESCRIPTION = QML profiler
|
||||
|
||||
win32 {
|
||||
VERSION = $${QT_VERSION}.0
|
||||
} else {
|
||||
VERSION = $${QT_VERSION}
|
||||
}
|
||||
|
||||
load(qt_tool)
|
||||
|
|
|
@ -7,4 +7,13 @@ SOURCES += main.cpp
|
|||
DEFINES += QML_RUNTIME_TESTING
|
||||
!contains(QT_CONFIG, no-qml-debug): DEFINES += QT_QML_DEBUG_NO_WARNING
|
||||
|
||||
QMAKE_TARGET_PRODUCT = qmlscene
|
||||
QMAKE_TARGET_DESCRIPTION = Utility that loads and displays QML documents
|
||||
|
||||
win32 {
|
||||
VERSION = $${QT_VERSION}.0
|
||||
} else {
|
||||
VERSION = $${QT_VERSION}
|
||||
}
|
||||
|
||||
load(qt_tool)
|
||||
|
|
|
@ -3,4 +3,13 @@ SOURCES += main.cpp
|
|||
QT += qml qmltest
|
||||
CONFIG += no_import_scan
|
||||
|
||||
QMAKE_TARGET_PRODUCT = qmltestrunner
|
||||
QMAKE_TARGET_DESCRIPTION = QML test runner
|
||||
|
||||
win32 {
|
||||
VERSION = $${QT_VERSION}.0
|
||||
} else {
|
||||
VERSION = $${QT_VERSION}
|
||||
}
|
||||
|
||||
load(qt_tool)
|
||||
|
|
|
@ -4,4 +4,13 @@ QT += qml quick
|
|||
QT += quick-private
|
||||
macx:CONFIG -= app_bundle
|
||||
|
||||
QMAKE_TARGET_PRODUCT = qmltime
|
||||
QMAKE_TARGET_DESCRIPTION = Tool for benchmarking the instantiation of a QML component
|
||||
|
||||
win32 {
|
||||
VERSION = $${QT_VERSION}.0
|
||||
} else {
|
||||
VERSION = $${QT_VERSION}
|
||||
}
|
||||
|
||||
SOURCES += qmltime.cpp
|
||||
|
|
|
@ -16,8 +16,12 @@ SUBDIRS += \
|
|||
!static: {
|
||||
SUBDIRS += \
|
||||
qmlscene \
|
||||
qmlplugindump \
|
||||
qmltime
|
||||
|
||||
qtConfig(regularexpression) {
|
||||
SUBDIRS += \
|
||||
qmlplugindump
|
||||
}
|
||||
}
|
||||
qtHaveModule(widgets): SUBDIRS += qmleasing
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue