Merge remote-tracking branch 'origin/5.11' into dev
Change-Id: I42ec9e6aafc203465cbeb88af70c7af26b7df8ed
This commit is contained in:
commit
6cf3428a43
@ -76,7 +76,7 @@ sub normalizePath {
|
||||
# set output basedir to be where ever syncqt is run from
|
||||
our $out_basedir = getcwd();
|
||||
normalizePath(\$out_basedir);
|
||||
our $build_basedir = $out_basedir;
|
||||
our $build_basedir;
|
||||
our $basedir;
|
||||
|
||||
# Make sure we use Windows line endings for chomp and friends on Windows.
|
||||
@ -129,7 +129,7 @@ sub showUsage
|
||||
print " -showonly Show action but not perform (default: " . ($showonly ? "yes" : "no") . ")\n";
|
||||
print " -minimal Do not create CamelCase headers (default: " . ($minimal ? "yes" : "no") . ")\n";
|
||||
print " -outdir <PATH> Specify output directory for sync (default: $out_basedir)\n";
|
||||
print " -builddir <PATH> Specify build directory for sync (default: $build_basedir)\n";
|
||||
print " -builddir <PATH> Specify build directory for sync (default: same as -outdir)\n";
|
||||
print " -version <VERSION> Specify the module's version (default: detect from qglobal.h)\n";
|
||||
print " -quiet Only report problems, not activity (same as -verbose 0)\n";
|
||||
print " -v, -verbose <level> Sets the verbosity level (max. 4) (default: $verbose_level)\n";
|
||||
@ -592,21 +592,18 @@ sub copyFile
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Syntax: findFiles(dir, match, descend)
|
||||
# Syntax: findFiles(dir, match)
|
||||
# Params: dir, string, directory to search for name
|
||||
# match, string, regular expression to match in dir
|
||||
# descend, integer, 0 = non-recursive search
|
||||
# 1 = recurse search into subdirectories
|
||||
#
|
||||
# Purpose: Finds files matching a regular expression.
|
||||
# Returns: List of matching files.
|
||||
#
|
||||
# Examples:
|
||||
# findFiles("/usr","\.cpp$",1) - finds .cpp files in /usr and below
|
||||
# findFiles("/tmp","^#",0) - finds #* files in /tmp
|
||||
# Example:
|
||||
# findFiles("/tmp", "^#") - finds #* files in /tmp
|
||||
######################################################################
|
||||
sub findFiles {
|
||||
my ($dir,$match,$descend) = @_;
|
||||
my ($dir, $match) = @_;
|
||||
my ($file,$p,@files);
|
||||
local(*D);
|
||||
normalizePath(\$dir);
|
||||
@ -621,9 +618,6 @@ sub findFiles {
|
||||
next if ( $file =~ /^\.\.?$/ );
|
||||
$p = $file;
|
||||
($file =~ /$match/) && (push @files, $p);
|
||||
if ( $descend && -d $p && ! -l $p ) {
|
||||
push @files, &findFiles($p,$match,$descend);
|
||||
}
|
||||
}
|
||||
closedir(D);
|
||||
}
|
||||
@ -728,7 +722,7 @@ sub globosort($$) {
|
||||
}
|
||||
|
||||
# check if this is an in-source build, and if so use that as the basedir too
|
||||
$basedir = locateSyncProfile($build_basedir);
|
||||
$basedir = locateSyncProfile($out_basedir);
|
||||
if ($basedir) {
|
||||
$basedir = dirname($basedir) ;
|
||||
normalizePath(\$basedir);
|
||||
@ -899,6 +893,8 @@ while ( @ARGV ) {
|
||||
die "Could not find any sync.profile for your module!\nPass <module directory> to syncqt to sync your header files.\nsyncqt failed" if (!$basedir);
|
||||
die "The -version argument is mandatory" if (!$module_version);
|
||||
|
||||
$build_basedir = $out_basedir if (!defined($build_basedir));
|
||||
|
||||
our @ignore_headers = ();
|
||||
our @ignore_for_master_contents = ();
|
||||
our @ignore_for_include_check = ();
|
||||
@ -1016,7 +1012,7 @@ foreach my $lib (@modules_to_sync) {
|
||||
|
||||
#calc files and "copy" them
|
||||
foreach my $subdir (@subdirs) {
|
||||
my @headers = findFiles($subdir, "^[-a-z0-9_]*\\.h\$" , 0);
|
||||
my @headers = findFiles($subdir, "^[-a-z0-9_]*\\.h\$");
|
||||
@headers = grep(!/^qt[a-z0-9]+-config(_p)?\.h$/, @headers);
|
||||
if (defined $inject_headers{$subdir}) {
|
||||
foreach my $if (@{$inject_headers{$subdir}}) {
|
||||
|
@ -176,6 +176,7 @@
|
||||
]
|
||||
},
|
||||
"sources": [
|
||||
{ "type": "pkgConfig", "args": "libpcre2-16" },
|
||||
"-lpcre2-16"
|
||||
]
|
||||
},
|
||||
|
@ -401,7 +401,7 @@ QString QMimeBinaryProvider::resolveAlias(const QString &name)
|
||||
return QLatin1String(mimeType);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
return QString();
|
||||
}
|
||||
|
||||
void QMimeBinaryProvider::addAliases(const QString &name, QStringList &result)
|
||||
@ -729,7 +729,7 @@ void QMimeXMLProvider::addAliases(const QString &name, QStringList &result)
|
||||
|
||||
QString QMimeXMLProvider::resolveAlias(const QString &name)
|
||||
{
|
||||
return m_aliases.value(name, name);
|
||||
return m_aliases.value(name);
|
||||
}
|
||||
|
||||
void QMimeXMLProvider::addAlias(const QString &alias, const QString &name)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -147,9 +147,17 @@ struct Q_AUTOTEST_EXPORT QScriptAnalysis
|
||||
TabOrObject = Tab,
|
||||
Object = 7
|
||||
};
|
||||
unsigned short script : 7;
|
||||
unsigned short bidiLevel : 6; // Unicode Bidi algorithm embedding level (0-61)
|
||||
unsigned short flags : 3;
|
||||
enum BidiFlags {
|
||||
BidiBN = 1,
|
||||
BidiMaybeResetToParagraphLevel = 2,
|
||||
BidiResetToParagraphLevel = 4,
|
||||
BidiMirrored = 8
|
||||
};
|
||||
unsigned short script : 8;
|
||||
unsigned short flags : 4;
|
||||
unsigned short bidiFlags : 4;
|
||||
unsigned short bidiLevel : 8; // Unicode Bidi algorithm embedding level (0-125)
|
||||
QChar::Direction bidiDirection : 8; // used when running the bidi algorithm
|
||||
inline bool operator == (const QScriptAnalysis &other) const {
|
||||
return script == other.script && bidiLevel == other.bidiLevel && flags == other.flags;
|
||||
}
|
||||
|
@ -2758,6 +2758,7 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
|
||||
glyph_start++;
|
||||
for (int i = glyph_end - 1; i >= glyph_start; i--)
|
||||
x += glyphs.effectiveAdvance(i);
|
||||
x -= eng->offsetInLigature(si, pos, end, glyph_pos);
|
||||
} else {
|
||||
int start = qMax(line.from - si->position, 0);
|
||||
int glyph_start = logClusters[start];
|
||||
@ -2766,8 +2767,8 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
|
||||
glyph_end--;
|
||||
for (int i = glyph_start; i <= glyph_end; i++)
|
||||
x += glyphs.effectiveAdvance(i);
|
||||
x += eng->offsetInLigature(si, pos, end, glyph_pos);
|
||||
}
|
||||
x += eng->offsetInLigature(si, pos, end, glyph_pos);
|
||||
}
|
||||
|
||||
if (eng->option.wrapMode() != QTextOption::NoWrap && x > line.x + line.width)
|
||||
|
@ -51,7 +51,7 @@
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <Unknwn.h>
|
||||
#include <unknwn.h>
|
||||
|
||||
#ifndef __IUIAutomationElement_INTERFACE_DEFINED__
|
||||
|
||||
|
@ -51,7 +51,7 @@
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <Unknwn.h>
|
||||
#include <unknwn.h>
|
||||
|
||||
#ifndef __IRawElementProviderSimple_INTERFACE_DEFINED__
|
||||
#define __IRawElementProviderSimple_INTERFACE_DEFINED__
|
||||
|
@ -350,6 +350,13 @@ void QWindowsMenuItem::setIsSeparator(bool isSeparator)
|
||||
if (m_separator == isSeparator)
|
||||
return;
|
||||
m_separator = isSeparator;
|
||||
if (m_parentMenu == nullptr)
|
||||
return;
|
||||
MENUITEMINFO menuItemInfo;
|
||||
menuItemInfoInit(menuItemInfo);
|
||||
menuItemInfo.fMask = MIIM_FTYPE;
|
||||
menuItemInfo.fType = isSeparator ? MFT_SEPARATOR : MFT_STRING;
|
||||
SetMenuItemInfo(parentMenuHandle(), m_id, FALSE, &menuItemInfo);
|
||||
}
|
||||
|
||||
void QWindowsMenuItem::setCheckable(bool checkable)
|
||||
|
@ -583,7 +583,9 @@ QRect QXcbScreen::availableGeometry() const
|
||||
QImage::Format QXcbScreen::format() const
|
||||
{
|
||||
QImage::Format format;
|
||||
qt_xcb_imageFormatForVisual(connection(), screen()->root_depth, visualForId(screen()->root_visual), &format);
|
||||
bool needsRgbSwap;
|
||||
qt_xcb_imageFormatForVisual(connection(), screen()->root_depth, visualForId(screen()->root_visual), &format, &needsRgbSwap);
|
||||
// We are ignoring needsRgbSwap here and just assumes the backing-store will handle it.
|
||||
return format;
|
||||
}
|
||||
|
||||
|
@ -268,6 +268,11 @@ static bool isValidSlot(const QMetaMethod &sl)
|
||||
|| name == "init" || name == "cleanup");
|
||||
}
|
||||
|
||||
namespace QTestPrivate
|
||||
{
|
||||
Q_TESTLIB_EXPORT Qt::MouseButtons qtestMouseButtons = Qt::NoButton;
|
||||
}
|
||||
|
||||
namespace QTest
|
||||
{
|
||||
class WatchDog;
|
||||
@ -1074,6 +1079,7 @@ bool TestMethods::invokeTest(int index, const char *data, WatchDog *watchDog) co
|
||||
QTestDataSetter s(curDataIndex >= dataCount ? static_cast<QTestData *>(0)
|
||||
: table.testData(curDataIndex));
|
||||
|
||||
QTestPrivate::qtestMouseButtons = Qt::NoButton;
|
||||
if (watchDog)
|
||||
watchDog->beginTest();
|
||||
invokeTestOnData(index);
|
||||
|
@ -68,11 +68,16 @@ Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *window, const QPointF &local, con
|
||||
Qt::MouseButtons state, Qt::MouseButton button,
|
||||
QEvent::Type type, Qt::KeyboardModifiers mods, int timestamp);
|
||||
|
||||
namespace QTestPrivate
|
||||
{
|
||||
extern Q_TESTLIB_EXPORT Qt::MouseButtons qtestMouseButtons;
|
||||
}
|
||||
|
||||
namespace QTest
|
||||
{
|
||||
enum MouseAction { MousePress, MouseRelease, MouseClick, MouseDClick, MouseMove };
|
||||
|
||||
extern Q_TESTLIB_EXPORT Qt::MouseButton lastMouseButton;
|
||||
extern Q_TESTLIB_EXPORT Qt::MouseButton lastMouseButton; // ### unsued
|
||||
extern Q_TESTLIB_EXPORT int lastMouseTimestamp;
|
||||
|
||||
// This value is used to emulate timestamps to avoid creating double clicks by mistake.
|
||||
@ -117,30 +122,35 @@ namespace QTest
|
||||
QPointF global = window->mapToGlobal(pos);
|
||||
QPointer<QWindow> w(window);
|
||||
|
||||
using namespace QTestPrivate;
|
||||
switch (action)
|
||||
{
|
||||
case MouseDClick:
|
||||
qt_handleMouseEvent(w, pos, global, button, button, QEvent::MouseButtonPress,
|
||||
qtestMouseButtons.setFlag(button, true);
|
||||
qt_handleMouseEvent(w, pos, global, qtestMouseButtons, button, QEvent::MouseButtonPress,
|
||||
stateKey, ++lastMouseTimestamp);
|
||||
qt_handleMouseEvent(w, pos, global, Qt::NoButton, button, QEvent::MouseButtonRelease,
|
||||
qtestMouseButtons.setFlag(button, false);
|
||||
qt_handleMouseEvent(w, pos, global, qtestMouseButtons, button, QEvent::MouseButtonRelease,
|
||||
stateKey, ++lastMouseTimestamp);
|
||||
Q_FALLTHROUGH();
|
||||
case MousePress:
|
||||
case MouseClick:
|
||||
qt_handleMouseEvent(w, pos, global, button, button, QEvent::MouseButtonPress,
|
||||
qtestMouseButtons.setFlag(button, true);
|
||||
qt_handleMouseEvent(w, pos, global, qtestMouseButtons, button, QEvent::MouseButtonPress,
|
||||
stateKey, ++lastMouseTimestamp);
|
||||
lastMouseButton = button;
|
||||
lastMouseButton = button; // ### unsued
|
||||
if (action == MousePress)
|
||||
break;
|
||||
Q_FALLTHROUGH();
|
||||
case MouseRelease:
|
||||
qt_handleMouseEvent(w, pos, global, Qt::NoButton, button, QEvent::MouseButtonRelease,
|
||||
qtestMouseButtons.setFlag(button, false);
|
||||
qt_handleMouseEvent(w, pos, global, qtestMouseButtons, button, QEvent::MouseButtonRelease,
|
||||
stateKey, ++lastMouseTimestamp);
|
||||
lastMouseTimestamp += mouseDoubleClickInterval; // avoid double clicks being generated
|
||||
lastMouseButton = Qt::NoButton;
|
||||
lastMouseButton = Qt::NoButton; // ### unsued
|
||||
break;
|
||||
case MouseMove:
|
||||
qt_handleMouseEvent(w, pos, global, lastMouseButton, Qt::NoButton, QEvent::MouseMove,
|
||||
qt_handleMouseEvent(w, pos, global, qtestMouseButtons, Qt::NoButton, QEvent::MouseMove,
|
||||
stateKey, ++lastMouseTimestamp);
|
||||
break;
|
||||
default:
|
||||
|
@ -2163,9 +2163,11 @@ void QHeaderViewPrivate::_q_sectionsAboutToBeChanged()
|
||||
layoutChangePersistentSections.clear();
|
||||
layoutChangePersistentSections.reserve(std::min(10, sectionItems.count()));
|
||||
// after layoutChanged another section can be last stretched section
|
||||
if (stretchLastSection) {
|
||||
if (stretchLastSection && lastSectionLogicalIdx >= 0 && lastSectionLogicalIdx < sectionItems.count()) {
|
||||
const int visual = visualIndex(lastSectionLogicalIdx);
|
||||
sectionItems[visual].size = lastSectionSize;
|
||||
if (visual >= 0 && visual < sectionItems.size()) {
|
||||
sectionItems[visual].size = lastSectionSize;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < sectionItems.size(); ++i) {
|
||||
auto s = sectionItems.at(i);
|
||||
@ -4045,7 +4047,7 @@ bool QHeaderViewPrivate::read(QDataStream &in)
|
||||
QVector<SectionItem> newSectionItems;
|
||||
for (int u = 0; u < sectionItemsIn.count(); ++u) {
|
||||
int count = sectionItemsIn.at(u).tmpDataStreamSectionCount;
|
||||
if (count > 0)
|
||||
if (count > 1)
|
||||
sectionItemsIn[u].size /= count;
|
||||
for (int n = 0; n < count; ++n)
|
||||
newSectionItems.append(sectionItemsIn[u]);
|
||||
|
@ -127,6 +127,8 @@ public:
|
||||
~QTipLabel();
|
||||
static QTipLabel *instance;
|
||||
|
||||
void updateSize();
|
||||
|
||||
bool eventFilter(QObject *, QEvent *) override;
|
||||
|
||||
QBasicTimer hideTimer, expireTimer;
|
||||
@ -214,13 +216,18 @@ void QTipLabel::reuseTip(const QString &text, int msecDisplayTime)
|
||||
|
||||
setWordWrap(Qt::mightBeRichText(text));
|
||||
setText(text);
|
||||
updateSize();
|
||||
restartExpireTimer(msecDisplayTime);
|
||||
}
|
||||
|
||||
void QTipLabel::updateSize()
|
||||
{
|
||||
QFontMetrics fm(font());
|
||||
QSize extra(1, 0);
|
||||
// Make it look good with the default ToolTip font on Mac, which has a small descent.
|
||||
if (fm.descent() == 2 && fm.ascent() >= 11)
|
||||
++extra.rheight();
|
||||
resize(sizeHint() + extra);
|
||||
restartExpireTimer(msecDisplayTime);
|
||||
}
|
||||
|
||||
void QTipLabel::paintEvent(QPaintEvent *ev)
|
||||
@ -387,6 +394,9 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w)
|
||||
if (w) {
|
||||
connect(w, SIGNAL(destroyed()),
|
||||
QTipLabel::instance, SLOT(styleSheetParentDestroyed()));
|
||||
// QTBUG-64550: A font inherited by the style sheet might change the size,
|
||||
// particular on Windows, where the tip is not parented on a window.
|
||||
QTipLabel::instance->updateSize();
|
||||
}
|
||||
}
|
||||
#endif //QT_NO_STYLE_STYLESHEET
|
||||
|
@ -1045,6 +1045,31 @@ void tst_QMimeDatabase::installNewLocalMimeType()
|
||||
QCOMPARE(db.mimeTypeForFile(qmlTestFile).name(),
|
||||
QString::fromLatin1("text/x-qml"));
|
||||
|
||||
// Now that we have two directories with mime definitions, check that everything still works
|
||||
inheritance();
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
aliases();
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
icons();
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
comment();
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
mimeTypeForFileWithContent();
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
mimeTypeForName();
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
// Now test removing local mimetypes
|
||||
for (int i = 1 ; i <= 3 ; ++i)
|
||||
QFile::remove(destDir + QStringLiteral("invalid-magic%1.xml").arg(i));
|
||||
|
@ -2367,49 +2367,44 @@ void tst_QWindow::generatedMouseMove()
|
||||
{
|
||||
InputTestWindow w;
|
||||
w.setGeometry(QRect(m_availableTopLeft + QPoint(100, 100), m_testWindowSize));
|
||||
w.setFlags(w.flags() | Qt::FramelessWindowHint); // ### FIXME: QTBUG-63542
|
||||
w.show();
|
||||
QVERIFY(QTest::qWaitForWindowActive(&w));
|
||||
QPoint point(10, 10);
|
||||
QPoint step(2, 2);
|
||||
|
||||
QVERIFY(w.mouseMovedCount == 0);
|
||||
QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::NoButton, Qt::NoButton, QEvent::MouseMove);
|
||||
QCoreApplication::processEvents();
|
||||
QTest::mouseMove(&w, point);
|
||||
QVERIFY(w.mouseMovedCount == 1);
|
||||
// Press that does not change position should not generate mouse move
|
||||
QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::LeftButton, Qt::LeftButton, QEvent::MouseButtonPress);
|
||||
QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::LeftButton | Qt::RightButton, Qt::RightButton, QEvent::MouseButtonPress);
|
||||
QCoreApplication::processEvents();
|
||||
// A press event that does not change position should not generate mouse move
|
||||
QTest::mousePress(&w, Qt::LeftButton, 0, point);
|
||||
QTest::mousePress(&w, Qt::RightButton, 0, point);
|
||||
|
||||
QVERIFY(w.mouseMovedCount == 1);
|
||||
|
||||
// Test moves generated for mouse release
|
||||
// Verify that a move event is generated for a mouse release event that changes position
|
||||
point += step;
|
||||
QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::RightButton, Qt::LeftButton, QEvent::MouseButtonRelease);
|
||||
QCoreApplication::processEvents();
|
||||
QTest::mouseRelease(&w, Qt::LeftButton, 0, point);
|
||||
QVERIFY(w.mouseMovedCount == 2);
|
||||
QVERIFY(w.buttonStateInGeneratedMove == (Qt::LeftButton | Qt::RightButton));
|
||||
point += step;
|
||||
QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::NoButton, Qt::RightButton, QEvent::MouseButtonRelease);
|
||||
QCoreApplication::processEvents();
|
||||
QTest::mouseRelease(&w, Qt::RightButton, 0, point);
|
||||
QVERIFY(w.mouseMovedCount == 3);
|
||||
QVERIFY(w.buttonStateInGeneratedMove == Qt::RightButton);
|
||||
|
||||
// Test moves generated for mouse press
|
||||
// Verify that a move event is generated for a mouse press event that changes position
|
||||
point += step;
|
||||
QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::LeftButton, Qt::LeftButton, QEvent::MouseButtonPress);
|
||||
QCoreApplication::processEvents();
|
||||
QTest::mousePress(&w, Qt::LeftButton, 0, point);
|
||||
QVERIFY(w.mouseMovedCount == 4);
|
||||
QVERIFY(w.buttonStateInGeneratedMove == Qt::NoButton);
|
||||
point += step;
|
||||
QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::LeftButton | Qt::RightButton, Qt::RightButton, QEvent::MouseButtonPress);
|
||||
QCoreApplication::processEvents();
|
||||
QTest::mousePress(&w, Qt::RightButton, 0, point);
|
||||
QVERIFY(w.mouseMovedCount == 5);
|
||||
QVERIFY(w.buttonStateInGeneratedMove == Qt::LeftButton);
|
||||
|
||||
// Release that does not change position should not generate mouse move
|
||||
QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::LeftButton, Qt::RightButton, QEvent::MouseButtonRelease);
|
||||
QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::NoButton, Qt::LeftButton, QEvent::MouseButtonRelease);
|
||||
QCoreApplication::processEvents();
|
||||
// A release event that does not change position should not generate mouse move
|
||||
QTest::mouseRelease(&w, Qt::RightButton, 0, point);
|
||||
QTest::mouseRelease(&w, Qt::LeftButton, 0, point);
|
||||
QVERIFY(w.mouseMovedCount == 5);
|
||||
}
|
||||
|
||||
|
@ -969,12 +969,14 @@ void tst_QLocalSocket::processConnection()
|
||||
QProcess producer;
|
||||
ProcessOutputDumper producerOutputDumper(&producer);
|
||||
QList<QProcess*> consumers;
|
||||
producer.setProcessChannelMode(QProcess::MergedChannels);
|
||||
producer.start(socketProcess, serverArguments);
|
||||
QVERIFY2(producer.waitForStarted(-1), qPrintable(producer.errorString()));
|
||||
for (int i = 0; i < processes; ++i) {
|
||||
QStringList arguments = QStringList() << "--client";
|
||||
QProcess *p = new QProcess;
|
||||
consumers.append(p);
|
||||
p->setProcessChannelMode(QProcess::MergedChannels);
|
||||
p->start(socketProcess, arguments);
|
||||
}
|
||||
|
||||
|
@ -106,33 +106,62 @@ const LV logical_visual[] = {
|
||||
// LRO: \342\200\255
|
||||
// RLO: \342\200\256
|
||||
|
||||
{ "override1", "\342\200\256hello\342\200\254", "\342\200\254olleh\342\200\256", QChar::DirL },
|
||||
{ "override1", "\342\200\256hello\342\200\254", "\342\200\256olleh\342\200\254", QChar::DirL },
|
||||
{ "override2", "\342\200\255hello\342\200\254", "\342\200\255hello\342\200\254", QChar::DirL },
|
||||
{ "override3", "\342\200\255\327\251\327\234\327\225\327\235\342\200\254", "\342\200\255\327\251\327\234\327\225\327\235\342\200\254", QChar::DirL },
|
||||
{ "override4", "\342\200\256\327\251\327\234\327\225\327\235\342\200\254", "\342\200\254\327\235\327\225\327\234\327\251\342\200\256", QChar::DirL },
|
||||
{ "override4", "\342\200\256\327\251\327\234\327\225\327\235\342\200\254", "\342\200\256\327\235\327\225\327\234\327\251\342\200\254", QChar::DirL },
|
||||
{ "override5", "\342\200\256hello\342\200\254", "\342\200\254olleh\342\200\256", QChar::DirR },
|
||||
{ "override6", "\342\200\255hello\342\200\254", "\342\200\255hello\342\200\254", QChar::DirR },
|
||||
{ "override7", "\342\200\255\327\251\327\234\327\225\327\235\342\200\254", "\342\200\255\327\251\327\234\327\225\327\235\342\200\254", QChar::DirR },
|
||||
{ "override6", "\342\200\255hello\342\200\254", "\342\200\254hello\342\200\255", QChar::DirR },
|
||||
{ "override7", "\342\200\255\327\251\327\234\327\225\327\235\342\200\254", "\342\200\254\327\251\327\234\327\225\327\235\342\200\255", QChar::DirR },
|
||||
{ "override8", "\342\200\256\327\251\327\234\327\225\327\235\342\200\254", "\342\200\254\327\235\327\225\327\234\327\251\342\200\256", QChar::DirR },
|
||||
|
||||
{ "override9", "\327\224\342\200\255\327\251\327\234\342\200\256hello\342\200\254\327\225\327\235\342\200\254", "\342\200\255\327\251\327\234\342\200\254olleh\342\200\256\327\225\327\235\342\200\254\327\224", QChar::DirL },
|
||||
{ "override10", "\327\224\342\200\255\327\251\327\234\342\200\256hello\342\200\254\327\225\327\235\342\200\254", "\342\200\255\327\251\327\234\342\200\254olleh\342\200\256\327\225\327\235\342\200\254\327\224", QChar::DirR },
|
||||
{ "override9", "\327\224\342\200\255\327\251\327\234\342\200\256hello\342\200\254\327\225\327\235\342\200\254",
|
||||
"\327\251\327\234\342\200\256olleh\342\200\254\327\225\327\235\342\200\255\327\224\342\200\254", QChar::DirL },
|
||||
{ "override10", "\327\224\342\200\255\327\251\327\234\342\200\256hello\342\200\254\327\225\327\235\342\200\254",
|
||||
"\342\200\254\327\251\327\234\342\200\256olleh\342\200\254\327\225\327\235\342\200\255\327\224", QChar::DirR },
|
||||
|
||||
|
||||
{ "embed1", "\342\200\252hello\342\200\254", "\342\200\252hello\342\200\254", QChar::DirL },
|
||||
{ "embed2", "\342\200\253hello\342\200\254", "\342\200\254hello\342\200\253", QChar::DirL },
|
||||
{ "embed3", "\342\200\252hello\342\200\254", "\342\200\252hello\342\200\254", QChar::DirR },
|
||||
{ "embed2", "\342\200\253hello\342\200\254", "\342\200\253hello\342\200\254", QChar::DirL },
|
||||
{ "embed3", "\342\200\252hello\342\200\254", "\342\200\254hello\342\200\252", QChar::DirR },
|
||||
{ "embed4", "\342\200\253hello\342\200\254", "\342\200\254hello\342\200\253", QChar::DirR },
|
||||
{ "embed5", "\342\200\252\327\251\327\234\327\225\327\235\342\200\254", "\342\200\252\327\235\327\225\327\234\327\251\342\200\254", QChar::DirL },
|
||||
{ "embed6", "\342\200\253\327\251\327\234\327\225\327\235\342\200\254", "\342\200\254\327\235\327\225\327\234\327\251\342\200\253", QChar::DirL },
|
||||
{ "embed7", "\342\200\252\327\251\327\234\327\225\327\235\342\200\254", "\342\200\252\327\235\327\225\327\234\327\251\342\200\254", QChar::DirR },
|
||||
{ "embed6", "\342\200\253\327\251\327\234\327\225\327\235\342\200\254", "\342\200\253\327\235\327\225\327\234\327\251\342\200\254", QChar::DirL },
|
||||
{ "embed7", "\342\200\252\327\251\327\234\327\225\327\235\342\200\254", "\342\200\254\327\235\327\225\327\234\327\251\342\200\252", QChar::DirR },
|
||||
{ "embed8", "\342\200\253\327\251\327\234\327\225\327\235\342\200\254", "\342\200\254\327\235\327\225\327\234\327\251\342\200\253", QChar::DirR },
|
||||
|
||||
{ "embed9", "\342\200\252x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\252x \327\235\327\225\327\234\327\251 y\342\200\254", QChar::DirL },
|
||||
{ "embed10", "\342\200\253x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\254y \327\235\327\225\327\234\327\251 x\342\200\253", QChar::DirL },
|
||||
{ "embed11", "\342\200\252x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\252x \327\235\327\225\327\234\327\251 y\342\200\254", QChar::DirR },
|
||||
{ "embed10", "\342\200\253x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\253y \327\235\327\225\327\234\327\251 x\342\200\254", QChar::DirL },
|
||||
{ "embed11", "\342\200\252x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\254x \327\235\327\225\327\234\327\251 y\342\200\252", QChar::DirR },
|
||||
{ "embed12", "\342\200\253x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\254y \327\235\327\225\327\234\327\251 x\342\200\253", QChar::DirR },
|
||||
{ "zwsp", "+0\342\200\213f-1", "+0\342\200\213f-1", QChar::DirL },
|
||||
|
||||
// Alef: \xD7\x90
|
||||
|
||||
{ "bracketpair_1_ltr", "\xD7\x90(\xD7\x90[&a]!)a", "\xD7\x90(\xD7\x90[&a]!)a", QChar::DirL },
|
||||
{ "bracketpair_1_rtl", "\xD7\x90(\xD7\x90[&a]!)a", "a(![a&]\xD7\x90)\xD7\x90", QChar::DirR },
|
||||
|
||||
{ "bracketpair_2_ltr", "a(\xD7\x90[&a]!)\xD7\x90", "a(\xD7\x90[&a]!)\xD7\x90", QChar::DirL },
|
||||
{ "bracketpair_2_rtl", "a(\xD7\x90[&a]!)\xD7\x90", "\xD7\x90(![a&]\xD7\x90)a", QChar::DirR },
|
||||
|
||||
{ "bracketpair_3_ltr", "\xD7\x90(a[&\xD7\x90]!)a", "\xD7\x90(a[&\xD7\x90]!)a", QChar::DirL },
|
||||
{ "bracketpair_3_rtl", "\xD7\x90(a[&\xD7\x90]!)a", "a(![\xD7\x90&]a)\xD7\x90", QChar::DirR },
|
||||
|
||||
{ "bracketpair_4_ltr", "a (a \xD7\x90) \xD7\x90", "a (a \xD7\x90) \xD7\x90", QChar::DirL },
|
||||
{ "bracketpair_4_rtl", "a (a \xD7\x90) \xD7\x90", "\xD7\x90 (\xD7\x90 a) a", QChar::DirR },
|
||||
|
||||
{ "bracketpair_5_ltr", "\xD7\x90 (a \xD7\x90) a", "\xD7\x90 (a \xD7\x90) a", QChar::DirL },
|
||||
{ "bracketpair_5_rtl", "\xD7\x90 (a \xD7\x90) a", "a (\xD7\x90 a) \xD7\x90", QChar::DirR },
|
||||
|
||||
{ "bracketpair_6_ltr", "a (\xD7\x90 a) \xD7\x90", "a (\xD7\x90 a) \xD7\x90", QChar::DirL },
|
||||
{ "bracketpair_6_rtl", "a (\xD7\x90 a) \xD7\x90", "\xD7\x90 (a \xD7\x90) a", QChar::DirR },
|
||||
|
||||
{ "bracketpair_7_ltr", "\xD7\x90\xD7\x90 book(s)", "\xD7\x90\xD7\x90 book(s)", QChar::DirL },
|
||||
{ "bracketpair_7_rtl", "\xD7\x90\xD7\x90 book(s)", "book(s) \xD7\x90\xD7\x90", QChar::DirR },
|
||||
|
||||
{ "bracketpair_8_ltr", "a \xD7\x90\xD7\x90(\xD7\x90)", "a (\xD7\x90)\xD7\x90\xD7\x90", QChar::DirL },
|
||||
{ "bracketpair_8_rtl", "a \xD7\x90\xD7\x90(\xD7\x90)", "(\xD7\x90)\xD7\x90\xD7\x90 a", QChar::DirR },
|
||||
|
||||
|
||||
{ 0, 0, 0, QChar::DirON }
|
||||
};
|
||||
|
96437
tests/auto/other/qcomplextext/data/BidiCharacterTest.txt
Normal file
96437
tests/auto/other/qcomplextext/data/BidiCharacterTest.txt
Normal file
File diff suppressed because it is too large
Load Diff
497589
tests/auto/other/qcomplextext/data/BidiTest.txt
Normal file
497589
tests/auto/other/qcomplextext/data/BidiTest.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,3 +3,10 @@ TARGET = tst_qcomplextext
|
||||
QT += testlib
|
||||
QT += core-private gui-private
|
||||
SOURCES += tst_qcomplextext.cpp
|
||||
|
||||
TESTDATA += data
|
||||
|
||||
android {
|
||||
RESOURCES += \
|
||||
testdata.qrc
|
||||
}
|
||||
|
@ -47,6 +47,12 @@ private slots:
|
||||
void bidiCursorLogicalMovement();
|
||||
void bidiInvalidCursorNoMovement_data();
|
||||
void bidiInvalidCursorNoMovement();
|
||||
|
||||
void bidiCharacterTest_data();
|
||||
void bidiCharacterTest();
|
||||
void bidiTest_data();
|
||||
void bidiTest();
|
||||
|
||||
};
|
||||
|
||||
void tst_QComplexText::bidiReorderString_data()
|
||||
@ -93,7 +99,7 @@ void tst_QComplexText::bidiReorderString()
|
||||
QString sub = logical.mid(si.position, e.length(visualOrder[i]));
|
||||
if (si.analysis.bidiLevel % 2) {
|
||||
// reverse sub
|
||||
QChar *a = (QChar *)sub.unicode();
|
||||
QChar *a = sub.data();
|
||||
QChar *b = a + sub.length() - 1;
|
||||
while (a < b) {
|
||||
QChar tmp = *a;
|
||||
@ -273,5 +279,282 @@ void tst_QComplexText::bidiCursor_PDF()
|
||||
QVERIFY(line.cursorToX(size) == line.cursorToX(size - 1));
|
||||
}
|
||||
|
||||
void tst_QComplexText::bidiCharacterTest_data()
|
||||
{
|
||||
QTest::addColumn<QString>("data");
|
||||
QTest::addColumn<int>("paragraphDirection");
|
||||
QTest::addColumn<QVector<int>>("resolvedLevels");
|
||||
QTest::addColumn<QVector<int>>("visualOrder");
|
||||
|
||||
QString testFile = QFINDTESTDATA("data/BidiCharacterTest.txt");
|
||||
QFile f(testFile);
|
||||
QVERIFY(f.exists());
|
||||
|
||||
f.open(QIODevice::ReadOnly);
|
||||
|
||||
int linenum = 0;
|
||||
while (!f.atEnd()) {
|
||||
linenum++;
|
||||
|
||||
QByteArray line = f.readLine().simplified();
|
||||
if (line.startsWith('#') || line.isEmpty())
|
||||
continue;
|
||||
QVERIFY(!line.contains('#'));
|
||||
|
||||
QList<QByteArray> parts = line.split(';');
|
||||
QVERIFY(parts.size() == 5);
|
||||
|
||||
QString data;
|
||||
QList<QByteArray> dataParts = parts.at(0).split(' ');
|
||||
for (const auto &p : dataParts) {
|
||||
bool ok;
|
||||
data += QChar((ushort)p.toInt(&ok, 16));
|
||||
QVERIFY(ok);
|
||||
}
|
||||
|
||||
int paragraphDirection = parts.at(1).toInt();
|
||||
// int resolvedParagraphLevel = parts.at(2).toInt();
|
||||
|
||||
QVector<int> resolvedLevels;
|
||||
QList<QByteArray> levelParts = parts.at(3).split(' ');
|
||||
for (const auto &p : levelParts) {
|
||||
if (p == "x") {
|
||||
resolvedLevels += -1;
|
||||
} else {
|
||||
bool ok;
|
||||
resolvedLevels += p.toInt(&ok);
|
||||
QVERIFY(ok);
|
||||
}
|
||||
}
|
||||
|
||||
QVector<int> visualOrder;
|
||||
QList<QByteArray> orderParts = parts.at(4).split(' ');
|
||||
for (const auto &p : orderParts) {
|
||||
bool ok;
|
||||
visualOrder += p.toInt(&ok);
|
||||
QVERIFY(ok);
|
||||
}
|
||||
|
||||
const QByteArray nm = "line #" + QByteArray::number(linenum);
|
||||
QTest::newRow(nm.constData()) << data << paragraphDirection << resolvedLevels << visualOrder;
|
||||
}
|
||||
}
|
||||
|
||||
static void testBidiString(const QString &data, int paragraphDirection, const QVector<int> &resolvedLevels, const QVector<int> &visualOrder)
|
||||
{
|
||||
Q_UNUSED(resolvedLevels);
|
||||
|
||||
QTextEngine e(data, QFont());
|
||||
Qt::LayoutDirection pDir = Qt::LeftToRight;
|
||||
if (paragraphDirection == 1)
|
||||
pDir = Qt::RightToLeft;
|
||||
else if (paragraphDirection == 2)
|
||||
pDir = Qt::LayoutDirectionAuto;
|
||||
|
||||
e.option.setTextDirection(pDir);
|
||||
e.itemize();
|
||||
quint8 levels[1024];
|
||||
int visual[1024];
|
||||
int nitems = e.layoutData->items.size();
|
||||
int i;
|
||||
for (i = 0; i < nitems; ++i) {
|
||||
//qDebug("item %d bidiLevel=%d", i, e.items[i].analysis.bidiLevel);
|
||||
levels[i] = e.layoutData->items[i].analysis.bidiLevel;
|
||||
}
|
||||
e.bidiReorder(nitems, levels, visual);
|
||||
|
||||
QString visualString;
|
||||
for (i = 0; i < nitems; ++i) {
|
||||
QScriptItem &si = e.layoutData->items[visual[i]];
|
||||
QString sub;
|
||||
for (int j = si.position; j < si.position + e.length(visual[i]); ++j) {
|
||||
switch (data.at(j).direction()) {
|
||||
case QChar::DirLRE:
|
||||
case QChar::DirRLE:
|
||||
case QChar::DirLRO:
|
||||
case QChar::DirRLO:
|
||||
case QChar::DirPDF:
|
||||
case QChar::DirBN:
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sub += data.at(j);
|
||||
}
|
||||
|
||||
// remove explicit embedding characters, as the test data has them removed as well
|
||||
sub.remove(QChar(0x202a));
|
||||
sub.remove(QChar(0x202b));
|
||||
sub.remove(QChar(0x202c));
|
||||
sub.remove(QChar(0x202d));
|
||||
sub.remove(QChar(0x202e));
|
||||
if (si.analysis.bidiLevel % 2) {
|
||||
// reverse sub
|
||||
QChar *a = sub.data();
|
||||
QChar *b = a + sub.length() - 1;
|
||||
while (a < b) {
|
||||
QChar tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
++a;
|
||||
--b;
|
||||
}
|
||||
a = (QChar *)sub.unicode();
|
||||
b = a + sub.length();
|
||||
// while (a<b) {
|
||||
// *a = a->mirroredChar();
|
||||
// ++a;
|
||||
// }
|
||||
}
|
||||
visualString += sub;
|
||||
}
|
||||
QString expected;
|
||||
// qDebug() << "expected visual order";
|
||||
for (int i : visualOrder) {
|
||||
// qDebug() << " " << i << hex << data[i].unicode();
|
||||
expected.append(data[i]);
|
||||
}
|
||||
|
||||
QCOMPARE(visualString, expected);
|
||||
|
||||
}
|
||||
|
||||
void tst_QComplexText::bidiCharacterTest()
|
||||
{
|
||||
QFETCH(QString, data);
|
||||
QFETCH(int, paragraphDirection);
|
||||
QFETCH(QVector<int>, resolvedLevels);
|
||||
QFETCH(QVector<int>, visualOrder);
|
||||
|
||||
testBidiString(data, paragraphDirection, resolvedLevels, visualOrder);
|
||||
}
|
||||
|
||||
ushort unicodeForDirection(const QByteArray &direction)
|
||||
{
|
||||
struct {
|
||||
const char *string;
|
||||
ushort unicode;
|
||||
} dirToUnicode[] = {
|
||||
{ "L", 0x41 },
|
||||
{ "R", 0x5d0 },
|
||||
{ "EN", 0x30 },
|
||||
{ "ES", 0x2b },
|
||||
{ "ET", 0x24 },
|
||||
{ "AN", 0x660 },
|
||||
{ "CS", 0x2c },
|
||||
{ "B", QChar::ParagraphSeparator },
|
||||
{ "S", 0x9 },
|
||||
{ "WS", 0x20 },
|
||||
{ "ON", 0x2a },
|
||||
{ "LRE", 0x202a },
|
||||
{ "LRO", 0x202d },
|
||||
{ "AL", 0x627 },
|
||||
{ "RLE", 0x202b },
|
||||
{ "RLO", 0x202e },
|
||||
{ "PDF", 0x202c },
|
||||
{ "NSM", 0x300 },
|
||||
{ "BN", 0xad },
|
||||
{ "LRI", 0x2066 },
|
||||
{ "RLI", 0x2067 },
|
||||
{ "FSI", 0x2068 },
|
||||
{ "PDI", 0x2069 }
|
||||
};
|
||||
for (const auto &e : dirToUnicode) {
|
||||
if (e.string == direction)
|
||||
return e.unicode;
|
||||
}
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
void tst_QComplexText::bidiTest_data()
|
||||
{
|
||||
QTest::addColumn<QString>("data");
|
||||
QTest::addColumn<int>("paragraphDirection");
|
||||
QTest::addColumn<QVector<int>>("resolvedLevels");
|
||||
QTest::addColumn<QVector<int>>("visualOrder");
|
||||
|
||||
QString testFile = QFINDTESTDATA("data/BidiTest.txt");
|
||||
QFile f(testFile);
|
||||
QVERIFY(f.exists());
|
||||
|
||||
f.open(QIODevice::ReadOnly);
|
||||
|
||||
int linenum = 0;
|
||||
QVector<int> resolvedLevels;
|
||||
QVector<int> visualOrder;
|
||||
while (!f.atEnd()) {
|
||||
linenum++;
|
||||
|
||||
QByteArray line = f.readLine().simplified();
|
||||
if (line.startsWith('#') || line.isEmpty())
|
||||
continue;
|
||||
QVERIFY(!line.contains('#'));
|
||||
|
||||
if (line.startsWith("@Levels:")) {
|
||||
line = line.mid(strlen("@Levels:")).simplified();
|
||||
|
||||
resolvedLevels.clear();
|
||||
QList<QByteArray> levelParts = line.split(' ');
|
||||
for (const auto &p : levelParts) {
|
||||
if (p == "x") {
|
||||
resolvedLevels += -1;
|
||||
} else {
|
||||
bool ok;
|
||||
resolvedLevels += p.toInt(&ok);
|
||||
QVERIFY(ok);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
} else if (line.startsWith("@Reorder:")) {
|
||||
line = line.mid(strlen("@Reorder:")).simplified();
|
||||
|
||||
visualOrder.clear();
|
||||
QList<QByteArray> orderParts = line.split(' ');
|
||||
for (const auto &p : orderParts) {
|
||||
if (p.isEmpty())
|
||||
continue;
|
||||
bool ok;
|
||||
visualOrder += p.toInt(&ok);
|
||||
QVERIFY(ok);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
QList<QByteArray> parts = line.split(';');
|
||||
Q_ASSERT(parts.size() == 2);
|
||||
|
||||
QString data;
|
||||
QList<QByteArray> dataParts = parts.at(0).split(' ');
|
||||
for (const auto &p : dataParts) {
|
||||
ushort uc = unicodeForDirection(p);
|
||||
data += QChar(uc);
|
||||
}
|
||||
|
||||
int paragraphDirections = parts.at(1).toInt();
|
||||
|
||||
const QByteArray nm = "line #" + QByteArray::number(linenum);
|
||||
if (paragraphDirections & 1)
|
||||
QTest::newRow((nm + " (Auto)").constData()) << data << 2 << resolvedLevels << visualOrder;
|
||||
if (paragraphDirections & 2)
|
||||
QTest::newRow((nm + " (LTR)").constData()) << data << 0 << resolvedLevels << visualOrder;
|
||||
if (paragraphDirections & 4)
|
||||
QTest::newRow((nm + " (RTL)").constData()) << data << 1 << resolvedLevels << visualOrder;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void tst_QComplexText::bidiTest()
|
||||
{
|
||||
QFETCH(QString, data);
|
||||
QFETCH(int, paragraphDirection);
|
||||
QFETCH(QVector<int>, resolvedLevels);
|
||||
QFETCH(QVector<int>, visualOrder);
|
||||
|
||||
testBidiString(data, paragraphDirection, resolvedLevels, visualOrder);
|
||||
}
|
||||
|
||||
|
||||
|
||||
QTEST_MAIN(tst_QComplexText)
|
||||
#include "tst_qcomplextext.moc"
|
||||
|
7
tests/auto/testlib/selftests/mouse/mouse.pro
Normal file
7
tests/auto/testlib/selftests/mouse/mouse.pro
Normal file
@ -0,0 +1,7 @@
|
||||
SOURCES += tst_mouse.cpp
|
||||
QT += testlib testlib-private gui gui-private
|
||||
|
||||
mac:CONFIG -= app_bundle
|
||||
CONFIG -= debug_and_release_target
|
||||
|
||||
TARGET = mouse
|
215
tests/auto/testlib/selftests/mouse/tst_mouse.cpp
Normal file
215
tests/auto/testlib/selftests/mouse/tst_mouse.cpp
Normal file
@ -0,0 +1,215 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtTest>
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QCursor>
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace QTestPrivate {
|
||||
extern Q_TESTLIB_EXPORT Qt::MouseButtons qtestMouseButtons; // from qtestcase.cpp
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class tst_Mouse : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void stateHandlingPart1_data();
|
||||
void stateHandlingPart1();
|
||||
void stateHandlingPart2();
|
||||
void deterministicEvents_data();
|
||||
void deterministicEvents();
|
||||
};
|
||||
|
||||
class MouseWindow : public QWindow
|
||||
{
|
||||
public:
|
||||
Qt::MouseButtons stateInMouseMove = Qt::NoButton;
|
||||
int moveCount = 0;
|
||||
int pressCount = 0;
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *)
|
||||
{
|
||||
pressCount++;
|
||||
}
|
||||
|
||||
void mouseMoveEvent(QMouseEvent *e)
|
||||
{
|
||||
moveCount++;
|
||||
stateInMouseMove = e->buttons();
|
||||
}
|
||||
};
|
||||
|
||||
void tst_Mouse::stateHandlingPart1_data()
|
||||
{
|
||||
QTest::addColumn<bool>("dummy");
|
||||
QTest::newRow("dummy-1") << true;
|
||||
QTest::newRow("dummy-2") << true;
|
||||
}
|
||||
|
||||
void tst_Mouse::stateHandlingPart1()
|
||||
{
|
||||
QFETCH(bool, dummy);
|
||||
Q_UNUSED(dummy);
|
||||
|
||||
QWindow w;
|
||||
w.setFlags(w.flags() | Qt::FramelessWindowHint); // ### FIXME: QTBUG-63542
|
||||
w.show();
|
||||
w.setGeometry(100, 100, 200, 200);
|
||||
QVERIFY(QTest::qWaitForWindowActive(&w));
|
||||
|
||||
QPoint point(10, 10);
|
||||
QPoint step(1, 1);
|
||||
|
||||
// verify that we have a clean state after the previous data set
|
||||
QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::NoButton);
|
||||
|
||||
QTest::mousePress(&w, Qt::LeftButton, 0, point);
|
||||
QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::LeftButton);
|
||||
QTest::mousePress(&w, Qt::RightButton, 0, point);
|
||||
QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::LeftButton | Qt::RightButton);
|
||||
QTest::mouseMove(&w, point += step);
|
||||
QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::LeftButton | Qt::RightButton);
|
||||
QTest::mouseRelease(&w, Qt::LeftButton, 0, point);
|
||||
QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::RightButton);
|
||||
QTest::mouseMove(&w, point += step);
|
||||
QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::RightButton);
|
||||
// test invalid input - left button was already released
|
||||
QTest::mouseRelease(&w, Qt::LeftButton, 0, point += point);
|
||||
QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::RightButton);
|
||||
// test invalid input - right button is already pressed
|
||||
QTest::mousePress(&w, Qt::RightButton, 0, point);
|
||||
QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::RightButton);
|
||||
// now continue with valid input
|
||||
QTest::mouseRelease(&w, Qt::RightButton, 0, point += point);
|
||||
QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::NoButton);
|
||||
QTest::mouseMove(&w, point += step);
|
||||
QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::NoButton);
|
||||
|
||||
// exit this test function with some button in a pressed state
|
||||
QTest::mousePress(&w, Qt::LeftButton, 0, point);
|
||||
QTest::mousePress(&w, Qt::RightButton, 0, point);
|
||||
QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::LeftButton | Qt::RightButton);
|
||||
}
|
||||
|
||||
void tst_Mouse::stateHandlingPart2()
|
||||
{
|
||||
MouseWindow w;
|
||||
w.setFlags(w.flags() | Qt::FramelessWindowHint); // ### FIXME: QTBUG-63542
|
||||
w.show();
|
||||
w.setGeometry(100, 100, 200, 200);
|
||||
QVERIFY(QTest::qWaitForWindowActive(&w));
|
||||
|
||||
// verify that we have a clean state after stateHandlingPart1()
|
||||
QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::NoButton);
|
||||
|
||||
#if !QT_CONFIG(cursor)
|
||||
QSKIP("This part of the test requires the QCursor API");
|
||||
#else
|
||||
// The windowing system's view on a current button state might be different
|
||||
// from the qtestlib's mouse button state. This test verifies that the mouse
|
||||
// events generated by the system are adjusted to reflect qtestlib's view
|
||||
// on the current button state.
|
||||
// SKIP: not convinced yet that there is a valid use case for this.
|
||||
|
||||
QSKIP("Not implemented beyond this point!");
|
||||
|
||||
QPoint point(40, 40);
|
||||
QTest::mousePress(&w, Qt::LeftButton, 0, point);
|
||||
QTest::mousePress(&w, Qt::RightButton, 0, point);
|
||||
QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::LeftButton | Qt::RightButton);
|
||||
w.moveCount = 0;
|
||||
// The windowing system will send mouse events with no buttons set
|
||||
QPoint moveToPoint = w.mapToGlobal(point + QPoint(1, 1));
|
||||
if (QCursor::pos() == moveToPoint)
|
||||
moveToPoint += QPoint(1, 1);
|
||||
QCursor::setPos(moveToPoint);
|
||||
QTRY_COMPARE(w.moveCount, 1);
|
||||
// Verify that qtestlib adjusted the button state
|
||||
QCOMPARE(w.stateInMouseMove, Qt::LeftButton | Qt::RightButton);
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_Mouse::deterministicEvents_data()
|
||||
{
|
||||
QTest::addColumn<bool>("firstRun");
|
||||
QTest::newRow("first-run-true") << true;
|
||||
QTest::newRow("first-run-false") << false;
|
||||
}
|
||||
|
||||
void tst_Mouse::deterministicEvents()
|
||||
{
|
||||
/* QGuiApplication uses QGuiApplicationPrivate::lastCursorPosition to
|
||||
determine if it needs to generate an additional mouse move event for
|
||||
mouse press/release. Verify that this property is reset to it's default
|
||||
value, ensuring deterministic event generation behavior. Not resetting
|
||||
this value might affect event generation for subsequent tests runs (in
|
||||
unlikely case where a subsquent test does a mouse press in a pos that is
|
||||
equal to QGuiApplicationPrivate::lastCursorPosition, not causing mouse
|
||||
move to be generated.
|
||||
NOTE: running this test alone as in "./mouse deterministicEvents:first-run-false"
|
||||
won't test what this test is designed to test. */
|
||||
|
||||
QSKIP("Not implemented!");
|
||||
|
||||
/* It is undecided how and at what scope we want to handle reseting
|
||||
lastCursorPosition, or perhaps Qt should not be generating mouse move
|
||||
events as documented in QGuiApplicationPrivate::processMouseEvent(),
|
||||
then the problem would go away - ### Qt6 ? */
|
||||
|
||||
QVERIFY(qIsInf(QGuiApplicationPrivate::lastCursorPosition.x()));
|
||||
QVERIFY(qIsInf(QGuiApplicationPrivate::lastCursorPosition.y()));
|
||||
|
||||
QFETCH(bool, firstRun);
|
||||
|
||||
MouseWindow w;
|
||||
w.setFlags(w.flags() | Qt::FramelessWindowHint); // ### FIXME: QTBUG-63542
|
||||
w.show();
|
||||
w.setGeometry(100, 100, 200, 200);
|
||||
QVERIFY(QTest::qWaitForWindowActive(&w));
|
||||
|
||||
QCOMPARE(w.pressCount, 0);
|
||||
QCOMPARE(w.moveCount, 0);
|
||||
static QPoint m_cachedLastCursorPosition;
|
||||
if (firstRun) {
|
||||
QTest::mousePress(&w, Qt::LeftButton, 0, QPoint(40, 40));
|
||||
m_cachedLastCursorPosition = QGuiApplicationPrivate::lastCursorPosition.toPoint();
|
||||
} else {
|
||||
QPoint point = w.mapFromGlobal(m_cachedLastCursorPosition);
|
||||
QTest::mousePress(&w, Qt::LeftButton, 0, point);
|
||||
}
|
||||
QCOMPARE(w.pressCount, 1);
|
||||
QCOMPARE(w.moveCount, 1);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_Mouse)
|
||||
#include "tst_mouse.moc"
|
@ -47,7 +47,8 @@ SUBPROGRAMS = \
|
||||
verbose2 \
|
||||
verifyexceptionthrown \
|
||||
warnings \
|
||||
xunit
|
||||
xunit \
|
||||
mouse
|
||||
|
||||
INCLUDEPATH += ../../../../shared/
|
||||
HEADERS += ../../../../shared/emulationdetector.h
|
||||
|
@ -2502,7 +2502,7 @@ void tst_QAbstractItemView::checkFocusAfterActivationChanges()
|
||||
view->setItemDelegate(&delegate);
|
||||
w.show();
|
||||
|
||||
QTest::qWaitForWindowActive(&w);
|
||||
QVERIFY(QTest::qWaitForWindowActive(&w));
|
||||
QVERIFY(le->hasFocus());
|
||||
|
||||
view->setFocus();
|
||||
@ -2513,12 +2513,11 @@ void tst_QAbstractItemView::checkFocusAfterActivationChanges()
|
||||
QVERIFY(delegate.openedEditor->hasFocus());
|
||||
|
||||
QApplication::setActiveWindow(&otherTopLevel);
|
||||
QTest::qWaitForWindowActive(&otherTopLevel);
|
||||
otherTopLevel.setFocus();
|
||||
QVERIFY(!delegate.openedEditor);
|
||||
QTRY_VERIFY(!delegate.openedEditor);
|
||||
|
||||
QApplication::setActiveWindow(&w);
|
||||
QTest::qWaitForWindowActive(&w);
|
||||
QVERIFY(QTest::qWaitForWindowActive(&w));
|
||||
QVERIFY(view->hasFocus());
|
||||
}
|
||||
|
||||
|
@ -2363,6 +2363,7 @@ void tst_QHeaderView::checkLayoutChangeEmptyModel()
|
||||
QtTestModel tm;
|
||||
tm.cols = 11;
|
||||
QTableView tv;
|
||||
tv.verticalHeader()->setStretchLastSection(true);
|
||||
tv.setModel(&tm);
|
||||
|
||||
const int section4Size = tv.horizontalHeader()->sectionSize(4) + 1;
|
||||
|
@ -28,6 +28,8 @@
|
||||
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
#include <qfont.h>
|
||||
#include <qfontmetrics.h>
|
||||
#include <qtooltip.h>
|
||||
#include <qwhatsthis.h>
|
||||
#include <qscreen.h>
|
||||
@ -43,6 +45,7 @@ private slots:
|
||||
void task183679();
|
||||
void whatsThis();
|
||||
void setPalette();
|
||||
void qtbug64550_stylesheet();
|
||||
};
|
||||
|
||||
void tst_QToolTip::init()
|
||||
@ -53,6 +56,7 @@ void tst_QToolTip::init()
|
||||
void tst_QToolTip::cleanup()
|
||||
{
|
||||
QTRY_VERIFY(QApplication::topLevelWidgets().isEmpty());
|
||||
qApp->setStyleSheet(QString());
|
||||
}
|
||||
|
||||
class Widget_task183679 : public QWidget
|
||||
@ -66,10 +70,12 @@ public:
|
||||
QTimer::singleShot(msecs, this, SLOT(showToolTip()));
|
||||
}
|
||||
|
||||
static inline QString toolTipText() { return QStringLiteral("tool tip text"); }
|
||||
|
||||
private slots:
|
||||
void showToolTip()
|
||||
{
|
||||
QToolTip::showText(mapToGlobal(QPoint(0, 0)), "tool tip text", this);
|
||||
QToolTip::showText(mapToGlobal(QPoint(0, 0)), Widget_task183679::toolTipText(), this);
|
||||
}
|
||||
};
|
||||
|
||||
@ -146,6 +152,15 @@ void tst_QToolTip::whatsThis()
|
||||
QVERIFY2(whatsThisHeight > 100, QByteArray::number(whatsThisHeight)); // Test QTBUG-2416
|
||||
}
|
||||
|
||||
static QWidget *findToolTip()
|
||||
{
|
||||
const QWidgetList &topLevelWidgets = QApplication::topLevelWidgets();
|
||||
for (QWidget *widget : topLevelWidgets) {
|
||||
if (widget->windowType() == Qt::ToolTip && widget->objectName() == QLatin1String("qtooltip_label"))
|
||||
return widget;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void tst_QToolTip::setPalette()
|
||||
{
|
||||
@ -156,16 +171,7 @@ void tst_QToolTip::setPalette()
|
||||
|
||||
QTRY_VERIFY(QToolTip::isVisible());
|
||||
|
||||
QWidget *toolTip = 0;
|
||||
foreach (QWidget *widget, QApplication::topLevelWidgets()) {
|
||||
if (widget->windowType() == Qt::ToolTip
|
||||
&& widget->objectName() == QLatin1String("qtooltip_label"))
|
||||
{
|
||||
toolTip = widget;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QWidget *toolTip = findToolTip();
|
||||
QVERIFY(toolTip);
|
||||
QTRY_VERIFY(toolTip->isVisible());
|
||||
|
||||
@ -178,5 +184,39 @@ void tst_QToolTip::setPalette()
|
||||
QToolTip::hideText();
|
||||
}
|
||||
|
||||
static QByteArray msgSizeTooSmall(const QSize &actual, const QSize &expected)
|
||||
{
|
||||
return QByteArray::number(actual.width()) + 'x'
|
||||
+ QByteArray::number(actual.height()) + " < "
|
||||
+ QByteArray::number(expected.width()) + 'x'
|
||||
+ QByteArray::number(expected.height());
|
||||
}
|
||||
|
||||
// QTBUG-4550: When setting a style sheet specifying a font size on the tooltip's
|
||||
// parent widget (as opposed to setting on QApplication), the tooltip should
|
||||
// resize accordingly. This is an issue on Windows since the ToolTip widget is
|
||||
// not directly parented on the widget itself.
|
||||
// Set a large font size and verify that the tool tip is big enough.
|
||||
void tst_QToolTip::qtbug64550_stylesheet()
|
||||
{
|
||||
Widget_task183679 widget;
|
||||
widget.setStyleSheet(QStringLiteral("* { font-size: 48pt; }\n"));
|
||||
widget.show();
|
||||
QApplication::setActiveWindow(&widget);
|
||||
QVERIFY(QTest::qWaitForWindowActive(&widget));
|
||||
|
||||
widget.showDelayedToolTip(100);
|
||||
QTRY_VERIFY(QToolTip::isVisible());
|
||||
QWidget *toolTip = findToolTip();
|
||||
QVERIFY(toolTip);
|
||||
QTRY_VERIFY(toolTip->isVisible());
|
||||
|
||||
const QRect boundingRect = QFontMetrics(widget.font()).boundingRect(Widget_task183679::toolTipText());
|
||||
const QSize toolTipSize = toolTip->size();
|
||||
QVERIFY2(toolTipSize.width() >= boundingRect.width()
|
||||
&& toolTipSize.height() >= boundingRect.height(),
|
||||
msgSizeTooSmall(toolTipSize, boundingRect.size()).constData());
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QToolTip)
|
||||
#include "tst_qtooltip.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user