mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-03 07:45:30 +08:00
qt 6.6.0 clean
This commit is contained in:
@ -552,6 +552,10 @@ void tst_QIcon::availableSizes()
|
||||
|
||||
void tst_QIcon::name()
|
||||
{
|
||||
const auto reset = qScopeGuard([]{
|
||||
QIcon::setThemeName({});
|
||||
QIcon::setThemeSearchPaths({});
|
||||
});
|
||||
{
|
||||
// No name if icon does not come from a theme
|
||||
QIcon icon(":/image.png");
|
||||
@ -629,6 +633,7 @@ void tst_QIcon::task184901_badCache()
|
||||
|
||||
void tst_QIcon::fromTheme()
|
||||
{
|
||||
const bool abIconFromPlatform = !QIcon::fromTheme("address-book-new").isNull();
|
||||
QString firstSearchPath = QLatin1String(":/icons");
|
||||
QString secondSearchPath = QLatin1String(":/second_icons");
|
||||
QIcon::setThemeSearchPaths(QStringList() << firstSearchPath << secondSearchPath);
|
||||
@ -725,7 +730,7 @@ void tst_QIcon::fromTheme()
|
||||
// Make sure setting the theme name clears the state
|
||||
QIcon::setThemeName("");
|
||||
abIcon = QIcon::fromTheme("address-book-new");
|
||||
QVERIFY(abIcon.isNull());
|
||||
QCOMPARE_NE(abIcon.isNull(), abIconFromPlatform);
|
||||
|
||||
// Test fallback icon behavior for empty theme names.
|
||||
// Can only reliably test this on systems that don't have a
|
||||
@ -809,7 +814,7 @@ void tst_QIcon::fromThemeCache()
|
||||
QTest::qWait(1000); // wait enough to have a different modification time in seconds
|
||||
QVERIFY(QFile(QStringLiteral(":/styles/commonstyle/images/standardbutton-save-16.png"))
|
||||
.copy(dir.path() + QLatin1String("/testcache/16x16/actions/button-save.png")));
|
||||
QVERIFY(QFileInfo(cacheName).lastModified() < QFileInfo(dir.path() + QLatin1String("/testcache/16x16/actions")).lastModified());
|
||||
QVERIFY(QFileInfo(cacheName).lastModified(QTimeZone::UTC) < QFileInfo(dir.path() + QLatin1String("/testcache/16x16/actions")).lastModified(QTimeZone::UTC));
|
||||
QIcon::setThemeSearchPaths(QStringList() << dir.path()); // reload themes
|
||||
QVERIFY(!QIcon::fromTheme("button-open").isNull());
|
||||
|
||||
@ -830,7 +835,7 @@ void tst_QIcon::fromThemeCache()
|
||||
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
|
||||
QCOMPARE(process.exitCode(), 0);
|
||||
#endif // QT_CONFIG(process)
|
||||
QVERIFY(QFileInfo(cacheName).lastModified() >= QFileInfo(dir.path() + QLatin1String("/testcache/16x16/actions")).lastModified());
|
||||
QVERIFY(QFileInfo(cacheName).lastModified(QTimeZone::UTC) >= QFileInfo(dir.path() + QLatin1String("/testcache/16x16/actions")).lastModified(QTimeZone::UTC));
|
||||
QIcon::setThemeSearchPaths(QStringList() << dir.path()); // reload themes
|
||||
QVERIFY(!QIcon::fromTheme("button-open").isNull());
|
||||
QVERIFY(!QIcon::fromTheme("button-open-fallback").isNull());
|
||||
|
@ -34,7 +34,9 @@ private slots:
|
||||
void find();
|
||||
void insert();
|
||||
void failedInsertReturnsInvalidKey();
|
||||
#if QT_DEPRECATED_SINCE(6, 6)
|
||||
void replace();
|
||||
#endif
|
||||
void remove();
|
||||
void clear();
|
||||
void pixmapKey();
|
||||
@ -120,11 +122,15 @@ void tst_QPixmapCache::setCacheLimit()
|
||||
QVERIFY(!QPixmapCache::find(key, p1));
|
||||
|
||||
QPixmapCache::setCacheLimit(1000);
|
||||
#if QT_DEPRECATED_SINCE(6, 6)
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
p1 = new QPixmap(2, 3);
|
||||
QVERIFY(!QPixmapCache::replace(key, *p1));
|
||||
QVERIFY(!QPixmapCache::find(key, p1));
|
||||
|
||||
delete p1;
|
||||
#endif // QT_DEPRECATED_SINCE(6, 6)
|
||||
|
||||
//Let check if keys are released when the pixmap cache is
|
||||
//full or has been flushed.
|
||||
@ -317,6 +323,9 @@ void tst_QPixmapCache::failedInsertReturnsInvalidKey()
|
||||
QVERIFY(!success); // QString API
|
||||
}
|
||||
|
||||
#if QT_DEPRECATED_SINCE(6, 6)
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
void tst_QPixmapCache::replace()
|
||||
{
|
||||
//The int part of the API
|
||||
@ -345,6 +354,8 @@ void tst_QPixmapCache::replace()
|
||||
//Broken keys
|
||||
QCOMPARE(QPixmapCache::replace(QPixmapCache::Key(), p2), false);
|
||||
}
|
||||
QT_WARNING_POP
|
||||
#endif // QT_DEPRECATED_SINCE(6, 6)
|
||||
|
||||
void tst_QPixmapCache::remove()
|
||||
{
|
||||
|
@ -14,8 +14,8 @@ struct MyApplication : public QGuiApplication
|
||||
{
|
||||
if (event->type() == QEvent::FileOpen) {
|
||||
QFileOpenEvent* ev = static_cast<QFileOpenEvent *>(event);
|
||||
QFile file;
|
||||
bool ok = ev->openFile(file, QFile::Append | QFile::Unbuffered);
|
||||
QFile file(ev->file());
|
||||
bool ok = file.open(QFile::Append | QFile::Unbuffered);
|
||||
if (ok)
|
||||
file.write(QByteArray("+external"));
|
||||
return true;
|
||||
|
@ -78,8 +78,8 @@ void tst_qfileopenevent::constructor()
|
||||
|
||||
QByteArray tst_qfileopenevent::readFileContent(QFileOpenEvent& event)
|
||||
{
|
||||
QFile file;
|
||||
event.openFile(file, QFile::ReadOnly);
|
||||
QFile file(event.file());
|
||||
file.open(QFile::ReadOnly);
|
||||
file.seek(0);
|
||||
QByteArray data = file.readAll();
|
||||
return data;
|
||||
@ -87,8 +87,8 @@ QByteArray tst_qfileopenevent::readFileContent(QFileOpenEvent& event)
|
||||
|
||||
bool tst_qfileopenevent::appendFileContent(QFileOpenEvent& event, const QByteArray& writeContent)
|
||||
{
|
||||
QFile file;
|
||||
bool ok = event.openFile(file, QFile::Append | QFile::Unbuffered);
|
||||
QFile file(event.file());
|
||||
bool ok = file.open(QFile::Append | QFile::Unbuffered);
|
||||
if (ok)
|
||||
ok = file.write(writeContent) == writeContent.size();
|
||||
return ok;
|
||||
@ -127,8 +127,8 @@ void tst_qfileopenevent::handleLifetime()
|
||||
QScopedPointer<QFileOpenEvent> event(createFileAndEvent(QLatin1String("testHandleLifetime"), QByteArray("test content")));
|
||||
|
||||
// open a QFile after the original RFile is closed
|
||||
QFile qFile;
|
||||
QCOMPARE(event->openFile(qFile, QFile::Append | QFile::Unbuffered), true);
|
||||
QFile qFile(event->file());
|
||||
QVERIFY(qFile.open(QFile::Append | QFile::Unbuffered));
|
||||
event.reset(0);
|
||||
|
||||
// write to the QFile after the event is closed
|
||||
@ -152,7 +152,8 @@ void tst_qfileopenevent::multiOpen()
|
||||
|
||||
QFile files[5];
|
||||
for (int i=0; i<5; i++) {
|
||||
QCOMPARE(event->openFile(files[i], QFile::ReadOnly), true);
|
||||
files[i].setFileName(event->file());
|
||||
QVERIFY(files[i].open(QFile::ReadOnly));
|
||||
}
|
||||
for (int i=0; i<5; i++)
|
||||
files[i].seek(i);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
#include <QStringView>
|
||||
#include <QSignalSpy>
|
||||
|
||||
Q_LOGGING_CATEGORY(lcTests, "qt.gui.tests")
|
||||
|
||||
@ -35,6 +36,7 @@ private slots:
|
||||
void screenDpiAndDpr_data();
|
||||
void screenDpiAndDpr();
|
||||
void screenDpiChange();
|
||||
void screenDpiChangeWithWindow();
|
||||
void environment_QT_SCALE_FACTOR();
|
||||
void environment_QT_SCREEN_SCALE_FACTORS_data();
|
||||
void environment_QT_SCREEN_SCALE_FACTORS();
|
||||
@ -55,6 +57,8 @@ private slots:
|
||||
void mouseVelocity_data();
|
||||
void setCursor();
|
||||
void setCursor_data();
|
||||
void setGlobalFactorEmits();
|
||||
void setScreenFactorEmits();
|
||||
};
|
||||
|
||||
/// Offscreen platform plugin test setup
|
||||
@ -235,6 +239,9 @@ void tst_QHighDpi::screenDpiAndDpr()
|
||||
|
||||
QWindow window(screen);
|
||||
QCOMPARE(window.devicePixelRatio(), screen->devicePixelRatio());
|
||||
window.setGeometry(QRect(screen->geometry().center(), QSize(10, 10)));
|
||||
window.create();
|
||||
QCOMPARE(window.devicePixelRatio(), screen->devicePixelRatio());
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,12 +268,48 @@ void tst_QHighDpi::screenDpiChange()
|
||||
for (QScreen *screen : app->screens()) {
|
||||
QCOMPARE(screen->devicePixelRatio(), newDpi / standardBaseDpi);
|
||||
QCOMPARE(screen->logicalDotsPerInch(), newDpi / screen->devicePixelRatio());
|
||||
|
||||
QWindow window(screen);
|
||||
QCOMPARE(window.devicePixelRatio(), screen->devicePixelRatio());
|
||||
window.create();
|
||||
QCOMPARE(window.devicePixelRatio(), screen->devicePixelRatio());
|
||||
}
|
||||
QCOMPARE(app->devicePixelRatio(), newDpi / standardBaseDpi);
|
||||
}
|
||||
|
||||
void tst_QHighDpi::screenDpiChangeWithWindow()
|
||||
{
|
||||
QList<qreal> dpiValues = { 96, 192, 288 };
|
||||
std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues));
|
||||
|
||||
// Create windows for screens
|
||||
QList<QScreen *> screens = app->screens();
|
||||
QList<QWindow *> windows;
|
||||
for (int i = 0; i < screens.count(); ++i) {
|
||||
QScreen *screen = screens[i];
|
||||
QWindow *window = new QWindow();
|
||||
windows.append(window);
|
||||
window->setGeometry(QRect(screen->geometry().center(), QSize(10, 10)));
|
||||
window->create();
|
||||
QCOMPARE(window->devicePixelRatio(), dpiValues[i] / standardBaseDpi);
|
||||
}
|
||||
|
||||
// Change screen DPI
|
||||
QList<qreal> newDpiValues = { 288, 192, 96 };
|
||||
QJsonValue config = offscreenConfiguration();
|
||||
QCborMap map = QCborMap::fromJsonObject(config.toObject());
|
||||
for (int i = 0; i < screens.count(); ++i) {
|
||||
map[QLatin1String("screens")][i][QLatin1String("logicalDpi")] = newDpiValues[i];
|
||||
}
|
||||
setOffscreenConfiguration(map.toJsonObject());
|
||||
|
||||
// Verify that window DPR changes on Screen DPI change.
|
||||
for (int i = 0; i < screens.count(); ++i) {
|
||||
QWindow *window = windows[i];
|
||||
QCOMPARE(window->devicePixelRatio(), newDpiValues[i] / standardBaseDpi);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QHighDpi::environment_QT_SCALE_FACTOR()
|
||||
{
|
||||
qreal factor = 3.1415;
|
||||
@ -313,9 +356,10 @@ void tst_QHighDpi::environment_QT_SCREEN_SCALE_FACTORS()
|
||||
QFETCH(QByteArray, environment);
|
||||
QFETCH(QList<qreal>, expectedDprValues);
|
||||
|
||||
qputenv("QT_SCREEN_SCALE_FACTORS", environment);
|
||||
|
||||
// Verify that setting QT_SCREEN_SCALE_FACTORS overrides the from-platform-screen-DPI DPR.
|
||||
{
|
||||
qputenv("QT_SCREEN_SCALE_FACTORS", environment);
|
||||
std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(platformScreenDpi));
|
||||
int i = 0;
|
||||
for (QScreen *screen : app->screens()) {
|
||||
@ -327,6 +371,18 @@ void tst_QHighDpi::environment_QT_SCREEN_SCALE_FACTORS()
|
||||
QCOMPARE(window.devicePixelRatio(), expextedDpr);
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that setHighDpiScaleFactorRoundingPolicy applies to QT_SCREEN_SCALE_FACTORS as well
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round);
|
||||
{
|
||||
std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(platformScreenDpi));
|
||||
int i = 0;
|
||||
for (QScreen *screen : app->screens()) {
|
||||
qreal expectedRounderDpr = qRound(expectedDprValues[i++]);
|
||||
qreal windowDpr = QWindow(screen).devicePixelRatio();
|
||||
QCOMPARE(windowDpr, expectedRounderDpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QHighDpi::environment_QT_USE_PHYSICAL_DPI()
|
||||
@ -798,5 +854,34 @@ void tst_QHighDpi::setCursor()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QHighDpi::setGlobalFactorEmits()
|
||||
{
|
||||
QList<qreal> dpiValues { 96, 96, 96 };
|
||||
std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues));
|
||||
|
||||
std::vector<std::unique_ptr<QSignalSpy>> spies;
|
||||
for (QScreen *screen : app->screens())
|
||||
spies.push_back(std::make_unique<QSignalSpy>(screen, &QScreen::geometryChanged));
|
||||
|
||||
QHighDpiScaling::setGlobalFactor(2);
|
||||
|
||||
for (const auto &spy : spies)
|
||||
QCOMPARE(spy->count(), 1);
|
||||
|
||||
QHighDpiScaling::setGlobalFactor(1);
|
||||
}
|
||||
|
||||
void tst_QHighDpi::setScreenFactorEmits()
|
||||
{
|
||||
QList<qreal> dpiValues { 96, 96, 96 };
|
||||
std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues));
|
||||
|
||||
for (QScreen *screen : app->screens()) {
|
||||
QSignalSpy spy(screen, &QScreen::geometryChanged);
|
||||
QHighDpiScaling::setScreenFactor(screen, 2);
|
||||
QCOMPARE(spy.count(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
#include "tst_qhighdpi.moc"
|
||||
QTEST_APPLESS_MAIN(tst_QHighDpi);
|
||||
|
@ -23,6 +23,7 @@ private Q_SLOTS:
|
||||
void cannotCheckIfInvalidBrushSet();
|
||||
void checkIfBrushForCurrentGroupSet();
|
||||
void cacheKey();
|
||||
void dataStream();
|
||||
};
|
||||
|
||||
void tst_QPalette::roleValues_data()
|
||||
@ -51,9 +52,10 @@ void tst_QPalette::roleValues_data()
|
||||
QTest::newRow("QPalette::ToolTipBase") << int(QPalette::ToolTipBase) << 18;
|
||||
QTest::newRow("QPalette::ToolTipText") << int(QPalette::ToolTipText) << 19;
|
||||
QTest::newRow("QPalette::PlaceholderText") << int(QPalette::PlaceholderText) << 20;
|
||||
QTest::newRow("QPalette::Accent") << int(QPalette::Accent) << 21;
|
||||
|
||||
// Change this value as you add more roles.
|
||||
QTest::newRow("QPalette::NColorRoles") << int(QPalette::NColorRoles) << 21;
|
||||
QTest::newRow("QPalette::NColorRoles") << int(QPalette::NColorRoles) << 22;
|
||||
}
|
||||
|
||||
void tst_QPalette::roleValues()
|
||||
@ -236,8 +238,14 @@ void tst_QPalette::setAllPossibleBrushes()
|
||||
}
|
||||
|
||||
for (int r = 0; r < QPalette::NColorRoles; ++r) {
|
||||
const QPalette::ColorRole role = static_cast<QPalette::ColorRole>(r);
|
||||
for (int g = 0; g < QPalette::NColorGroups; ++g) {
|
||||
QVERIFY(p.isBrushSet(QPalette::ColorGroup(g), QPalette::ColorRole(r)));
|
||||
const QPalette::ColorGroup group = static_cast<QPalette::ColorGroup>(g);
|
||||
// NoRole has no resolve bit => isBrushSet returns false
|
||||
if (role == QPalette::NoRole)
|
||||
QVERIFY(!p.isBrushSet(group, role));
|
||||
else
|
||||
QVERIFY(p.isBrushSet(group, role));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -341,5 +349,44 @@ void tst_QPalette::cacheKey()
|
||||
loggerShallowDetach.dismiss();
|
||||
}
|
||||
|
||||
void tst_QPalette::dataStream()
|
||||
{
|
||||
const QColor highlight(42, 42, 42);
|
||||
const QColor accent(13, 13, 13);
|
||||
QPalette palette;
|
||||
palette.setBrush(QPalette::Highlight, highlight);
|
||||
palette.setBrush(QPalette::Accent, accent);
|
||||
|
||||
// When saved with Qt_6_5 or earlier, Accent defaults to Highlight
|
||||
{
|
||||
QByteArray b;
|
||||
{
|
||||
QDataStream stream(&b, QIODevice::WriteOnly);
|
||||
stream.setVersion(QDataStream::Qt_6_5);
|
||||
stream << palette;
|
||||
}
|
||||
QPalette test;
|
||||
QDataStream stream (&b, QIODevice::ReadOnly);
|
||||
stream.setVersion(QDataStream::Qt_6_5);
|
||||
stream >> test;
|
||||
QCOMPARE(test.accent().color(), highlight);
|
||||
}
|
||||
|
||||
// When saved with Qt_6_6 or later, Accent is saved explicitly
|
||||
{
|
||||
QByteArray b;
|
||||
{
|
||||
QDataStream stream(&b, QIODevice::WriteOnly);
|
||||
stream.setVersion(QDataStream::Qt_6_6);
|
||||
stream << palette;
|
||||
}
|
||||
QPalette test;
|
||||
QDataStream stream (&b, QIODevice::ReadOnly);
|
||||
stream.setVersion(QDataStream::Qt_6_6);
|
||||
stream >> test;
|
||||
QCOMPARE(test.accent().color(), accent);
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QPalette)
|
||||
#include "tst_qpalette.moc"
|
||||
|
@ -23,3 +23,8 @@ android
|
||||
android
|
||||
[modalWindowModallity]
|
||||
android
|
||||
[enterLeaveOnWindowShowHide]
|
||||
windows-10
|
||||
windows-11
|
||||
android
|
||||
rhel
|
||||
|
@ -14,8 +14,9 @@ qt_internal_add_test(tst_qwindow
|
||||
Qt::GuiPrivate
|
||||
)
|
||||
|
||||
if(APPLE OR WIN32)
|
||||
if(APPLE OR WIN32 OR QT_FEATURE_xcb)
|
||||
qt_internal_add_test(tst_foreignwindow
|
||||
LOWDPI
|
||||
SOURCES
|
||||
tst_foreignwindow.cpp
|
||||
LIBRARIES
|
||||
@ -28,6 +29,10 @@ if(APPLE OR WIN32)
|
||||
set_source_files_properties(tst_foreignwindow.cpp PROPERTIES LANGUAGE OBJCXX)
|
||||
set_property(TARGET tst_foreignwindow PROPERTY PROPERTY MACOSX_BUNDLE TRUE)
|
||||
endif()
|
||||
|
||||
if(QT_FEATURE_xcb)
|
||||
target_link_libraries(tst_foreignwindow PRIVATE XCB::XCB)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
## Scopes:
|
||||
|
@ -7,114 +7,7 @@
|
||||
#include <private/qguiapplication_p.h>
|
||||
#include <qpa/qplatformintegration.h>
|
||||
|
||||
#if defined(Q_OS_MACOS)
|
||||
# include <AppKit/AppKit.h>
|
||||
#elif defined(Q_OS_WIN)
|
||||
# include <winuser.h>
|
||||
#endif
|
||||
|
||||
Q_LOGGING_CATEGORY(lcTests, "qt.gui.tests")
|
||||
|
||||
class NativeWindow
|
||||
{
|
||||
Q_DISABLE_COPY(NativeWindow)
|
||||
public:
|
||||
NativeWindow();
|
||||
~NativeWindow();
|
||||
|
||||
operator WId() const { return reinterpret_cast<WId>(m_handle); }
|
||||
|
||||
void setGeometry(const QRect &rect);
|
||||
QRect geometry() const;
|
||||
|
||||
private:
|
||||
#if defined(Q_OS_MACOS)
|
||||
NSView *m_handle = nullptr;
|
||||
#elif defined(Q_OS_WIN)
|
||||
HWND m_handle = nullptr;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(Q_OS_MACOS)
|
||||
|
||||
@interface View : NSView
|
||||
@end
|
||||
|
||||
@implementation View
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
qCDebug(lcTests) << "Initialized" << self;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
qCDebug(lcTests) << "Deallocating" << self;
|
||||
[super dealloc];
|
||||
}
|
||||
@end
|
||||
|
||||
NativeWindow::NativeWindow()
|
||||
: m_handle([View new])
|
||||
{
|
||||
}
|
||||
|
||||
NativeWindow::~NativeWindow()
|
||||
{
|
||||
[m_handle release];
|
||||
}
|
||||
|
||||
void NativeWindow::setGeometry(const QRect &rect)
|
||||
{
|
||||
m_handle.frame = QRectF(rect).toCGRect();
|
||||
}
|
||||
|
||||
QRect NativeWindow::geometry() const
|
||||
{
|
||||
return QRectF::fromCGRect(m_handle.frame).toRect();
|
||||
}
|
||||
|
||||
#elif defined(Q_OS_WIN)
|
||||
|
||||
NativeWindow::NativeWindow()
|
||||
{
|
||||
static const LPCWSTR className = []{
|
||||
WNDCLASS wc = {};
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.hInstance = GetModuleHandle(nullptr);
|
||||
wc.lpszClassName = L"Native Window";
|
||||
RegisterClass(&wc);
|
||||
return wc.lpszClassName;
|
||||
}();
|
||||
m_handle = CreateWindowEx(0, className, nullptr, WS_POPUP,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
|
||||
}
|
||||
|
||||
NativeWindow::~NativeWindow()
|
||||
{
|
||||
DestroyWindow(m_handle);
|
||||
}
|
||||
|
||||
void NativeWindow::setGeometry(const QRect &rect)
|
||||
{
|
||||
MoveWindow(m_handle, rect.x(), rect.y(), rect.width(), rect.height(), false);
|
||||
}
|
||||
|
||||
QRect NativeWindow::geometry() const
|
||||
{
|
||||
WINDOWPLACEMENT wp;
|
||||
wp.length = sizeof(WINDOWPLACEMENT);
|
||||
if (GetWindowPlacement(m_handle, &wp)) {
|
||||
RECT r = wp.rcNormalPosition;
|
||||
return QRect(r.left, r.top, r.right - r.left, r.bottom - r.top);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
#endif
|
||||
#include "../../../../shared/nativewindow.h"
|
||||
|
||||
class tst_ForeignWindow: public QObject
|
||||
{
|
||||
@ -130,6 +23,8 @@ private slots:
|
||||
|
||||
void fromWinId();
|
||||
void initialState();
|
||||
|
||||
void embedForeignWindow();
|
||||
};
|
||||
|
||||
void tst_ForeignWindow::fromWinId()
|
||||
@ -165,6 +60,7 @@ void tst_ForeignWindow::initialState()
|
||||
|
||||
const QRect initialGeometry(123, 456, 321, 654);
|
||||
nativeWindow.setGeometry(initialGeometry);
|
||||
QTRY_COMPARE(nativeWindow.geometry(), initialGeometry);
|
||||
|
||||
std::unique_ptr<QWindow> foreignWindow(QWindow::fromWinId(nativeWindow));
|
||||
QCOMPARE(nativeWindow.geometry(), initialGeometry);
|
||||
@ -174,5 +70,22 @@ void tst_ForeignWindow::initialState()
|
||||
QCOMPARE(foreignWindow->geometry(), initialGeometry);
|
||||
}
|
||||
|
||||
void tst_ForeignWindow::embedForeignWindow()
|
||||
{
|
||||
// A foreign window embedded into a Qt UI requires that the rest of Qt
|
||||
// is to be able to treat the foreign child window as any other window
|
||||
// that it can show, hide, stack, and move around.
|
||||
|
||||
QWindow parentWindow;
|
||||
|
||||
NativeWindow nativeWindow;
|
||||
QVERIFY(nativeWindow);
|
||||
|
||||
// As a prerequisite to that, we must be able to reparent the foreign window
|
||||
std::unique_ptr<QWindow> foreignWindow(QWindow::fromWinId(nativeWindow));
|
||||
foreignWindow.release()->setParent(&parentWindow);
|
||||
QTRY_COMPARE(nativeWindow.parentWinId(), parentWindow.winId());
|
||||
}
|
||||
|
||||
#include <tst_foreignwindow.moc>
|
||||
QTEST_MAIN(tst_ForeignWindow)
|
||||
|
@ -89,6 +89,10 @@ private slots:
|
||||
void qobject_castOnDestruction();
|
||||
void touchToMouseTranslationByPopup();
|
||||
void stateChangeSignal();
|
||||
#ifndef QT_NO_CURSOR
|
||||
void enterLeaveOnWindowShowHide_data();
|
||||
void enterLeaveOnWindowShowHide();
|
||||
#endif
|
||||
|
||||
private:
|
||||
QPoint m_availableTopLeft;
|
||||
@ -2883,6 +2887,87 @@ void tst_QWindow::stateChangeSignal()
|
||||
CHECK_SIGNAL(Qt::WindowMinimized);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_CURSOR
|
||||
void tst_QWindow::enterLeaveOnWindowShowHide_data()
|
||||
{
|
||||
QTest::addColumn<Qt::WindowType>("windowType");
|
||||
QTest::addRow("dialog") << Qt::Dialog;
|
||||
QTest::addRow("popup") << Qt::Popup;
|
||||
}
|
||||
|
||||
/*!
|
||||
Verify that we get enter and leave events if the window under the mouse
|
||||
opens and closes a modal dialog or popup. QWindow might get multiple
|
||||
events in a row, as the various QPA plugins need to use different techniques
|
||||
to synthesize events if the native platform doesn't provide them for us.
|
||||
*/
|
||||
void tst_QWindow::enterLeaveOnWindowShowHide()
|
||||
{
|
||||
if (isPlatformWayland())
|
||||
QSKIP("Can't set cursor position and qWaitForWindowActive on Wayland");
|
||||
|
||||
QFETCH(Qt::WindowType, windowType);
|
||||
|
||||
class Window : public QWindow
|
||||
{
|
||||
public:
|
||||
int numEnterEvents = 0;
|
||||
int numLeaveEvents = 0;
|
||||
QPoint enterPosition;
|
||||
protected:
|
||||
bool event(QEvent *e) override
|
||||
{
|
||||
switch (e->type()) {
|
||||
case QEvent::Enter:
|
||||
++numEnterEvents;
|
||||
enterPosition = static_cast<QEnterEvent*>(e)->position().toPoint();
|
||||
break;
|
||||
case QEvent::Leave:
|
||||
++numLeaveEvents;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QWindow::event(e);
|
||||
}
|
||||
};
|
||||
|
||||
int expectedEnter = 0;
|
||||
int expectedLeave = 0;
|
||||
|
||||
Window window;
|
||||
const QRect screenGeometry = window.screen()->availableGeometry();
|
||||
const QPoint cursorPos = screenGeometry.topLeft() + QPoint(50, 50);
|
||||
window.setGeometry(QRect(cursorPos - QPoint(50, 50), screenGeometry.size() / 4));
|
||||
QCursor::setPos(cursorPos);
|
||||
|
||||
if (!QTest::qWaitFor([&]{ return window.geometry().contains(QCursor::pos()); }))
|
||||
QSKIP("We can't move the cursor");
|
||||
|
||||
window.show();
|
||||
window.requestActivate();
|
||||
QVERIFY(QTest::qWaitForWindowActive(&window));
|
||||
|
||||
++expectedEnter;
|
||||
QTRY_COMPARE_WITH_TIMEOUT(window.numEnterEvents, expectedEnter, 250);
|
||||
QCOMPARE(window.enterPosition, window.mapFromGlobal(QCursor::pos()));
|
||||
|
||||
QWindow secondary;
|
||||
secondary.setFlag(windowType);
|
||||
secondary.setModality(Qt::WindowModal);
|
||||
secondary.setTransientParent(&window);
|
||||
secondary.setPosition(cursorPos + QPoint(50, 50));
|
||||
secondary.show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(&secondary));
|
||||
++expectedLeave;
|
||||
QTRY_VERIFY(window.numLeaveEvents >= expectedLeave);
|
||||
secondary.close();
|
||||
++expectedEnter;
|
||||
QTRY_VERIFY(window.numEnterEvents >= expectedEnter);
|
||||
QCOMPARE(window.enterPosition, window.mapFromGlobal(QCursor::pos()));
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <tst_qwindow.moc>
|
||||
QTEST_MAIN(tst_QWindow)
|
||||
|
||||
|
@ -1,6 +1,39 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include <QVector2D>
|
||||
#include <QVector3D>
|
||||
#include <QVector4D>
|
||||
#ifdef QVARIANT_H
|
||||
# error "This test requires qvector{2,3,4}d.h to not include qvariant.h"
|
||||
#endif
|
||||
|
||||
// don't assume <type_traits>
|
||||
template <typename T, typename U>
|
||||
constexpr inline bool my_is_same_v = false;
|
||||
template <typename T>
|
||||
constexpr inline bool my_is_same_v<T, T> = true;
|
||||
|
||||
#define CHECK(cvref) \
|
||||
static_assert(my_is_same_v<decltype(get<0>(std::declval<QVector2D cvref >())), float cvref >); \
|
||||
static_assert(my_is_same_v<decltype(get<1>(std::declval<QVector2D cvref >())), float cvref >); \
|
||||
\
|
||||
static_assert(my_is_same_v<decltype(get<0>(std::declval<QVector3D cvref >())), float cvref >); \
|
||||
static_assert(my_is_same_v<decltype(get<1>(std::declval<QVector3D cvref >())), float cvref >); \
|
||||
static_assert(my_is_same_v<decltype(get<2>(std::declval<QVector3D cvref >())), float cvref >); \
|
||||
\
|
||||
static_assert(my_is_same_v<decltype(get<0>(std::declval<QVector4D cvref >())), float cvref >); \
|
||||
static_assert(my_is_same_v<decltype(get<1>(std::declval<QVector4D cvref >())), float cvref >); \
|
||||
static_assert(my_is_same_v<decltype(get<2>(std::declval<QVector4D cvref >())), float cvref >); \
|
||||
static_assert(my_is_same_v<decltype(get<3>(std::declval<QVector4D cvref >())), float cvref >)
|
||||
|
||||
CHECK(&);
|
||||
CHECK(const &);
|
||||
CHECK(&&);
|
||||
CHECK(const &&);
|
||||
|
||||
#undef CHECK
|
||||
|
||||
#include <QTest>
|
||||
#include <QtCore/qmath.h>
|
||||
#include <QtGui/qvector2d.h>
|
||||
|
@ -349,8 +349,10 @@ void tst_QColorSpace::imageConversion64PM()
|
||||
|
||||
for (int j = 0; j < 16; ++j) {
|
||||
int a = j * 15;
|
||||
for (int i = 0; i < 256; ++i)
|
||||
testImage.setPixel(i, j, qPremultiply(qRgba(i, i, i, a)));
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
QRgba64 color = QRgba64::fromRgba(i, i, i, a);
|
||||
testImage.setPixelColor(i, j, QColor::fromRgba64(color));
|
||||
}
|
||||
}
|
||||
|
||||
testImage.setColorSpace(fromColorSpace);
|
||||
@ -389,8 +391,8 @@ void tst_QColorSpace::imageConversion64PM()
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
QRgb expected = qPremultiply(qRgba(i, i, i, expectedAlpha));
|
||||
QRgb p = testImage.pixel(i, j);
|
||||
QCOMPARE(qRed(p), qGreen(p));
|
||||
QCOMPARE(qRed(p), qBlue(p));
|
||||
QVERIFY(qAbs(qRed(p) - qGreen(p)) <= 1);
|
||||
QVERIFY(qAbs(qRed(p) - qBlue(p)) <= 1);
|
||||
QCOMPARE(qAlpha(p), expectedAlpha);
|
||||
QVERIFY((lastRed - qRed(p)) <= 0);
|
||||
QVERIFY((lastGreen - qGreen(p)) <= 0);
|
||||
|
@ -470,15 +470,19 @@ void tst_QPathClipper::clipTest(int subjectIndex, int clipIndex, QPathClipper::O
|
||||
break;
|
||||
}
|
||||
|
||||
if (expected != inResult) {
|
||||
char str[256];
|
||||
const char *opStr =
|
||||
op == QPathClipper::BoolAnd ? "and" :
|
||||
op == QPathClipper::BoolOr ? "or" : "sub";
|
||||
sprintf(str, "Expected: %d, actual: %d, subject: %d, clip: %d, op: %s\n",
|
||||
int(expected), int(inResult), subjectIndex, clipIndex, opStr);
|
||||
QFAIL(str);
|
||||
}
|
||||
auto failLogger = qScopeGuard([&]{
|
||||
qCritical().noquote().nospace()
|
||||
<< "\n\tExpected: " << expected
|
||||
<< "\n\tActual: " << inResult
|
||||
<< "\n\tSubject: " << subjectIndex
|
||||
<< "\n\tClip: " << clipIndex
|
||||
<< "\n\tOp: " << (op == QPathClipper::BoolAnd
|
||||
? "and"
|
||||
: op == QPathClipper::BoolOr
|
||||
? "or" : "sub");
|
||||
});
|
||||
QCOMPARE(inResult, expected);
|
||||
failLogger.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,3 +15,14 @@ qsb --glsl 320es,410 --msl 12 --msltess simpletess.vert -o simpletess.vert.qsb
|
||||
qsb --glsl 320es,410 --msl 12 --tess-mode triangles simpletess.tesc -o simpletess.tesc.qsb
|
||||
qsb --glsl 320es,410 --msl 12 --tess-vertex-count 3 simpletess.tese -o simpletess.tese.qsb
|
||||
qsb --glsl 320es,410 --msl 12 simpletess.frag -o simpletess.frag.qsb
|
||||
qsb --glsl 310es,430 --msl 12 --hlsl 50 storagebuffer.comp -o storagebuffer.comp.qsb
|
||||
qsb --glsl 320es,430 --msl 12 --msltess storagebuffer_runtime.vert -o storagebuffer_runtime.vert.qsb
|
||||
qsb --glsl 320es,430 --msl 12 --tess-mode triangles storagebuffer_runtime.tesc -o storagebuffer_runtime.tesc.qsb
|
||||
qsb --glsl 320es,430 --msl 12 --tess-vertex-count 3 storagebuffer_runtime.tese -o storagebuffer_runtime.tese.qsb
|
||||
qsb --glsl 320es,430 --msl 12 storagebuffer_runtime.frag -o storagebuffer_runtime.frag.qsb
|
||||
qsb --glsl 320es,430 --hlsl 50 -c --msl 12 storagebuffer_runtime.comp -o storagebuffer_runtime.comp.qsb
|
||||
qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o half.vert.qsb half.vert
|
||||
qsb --glsl 320es,430 --msl 21 --msltess tessinterfaceblocks.vert -o tessinterfaceblocks.vert.qsb
|
||||
qsb --glsl 320es,430 --msl 21 --tess-mode triangles tessinterfaceblocks.tesc -o tessinterfaceblocks.tesc.qsb
|
||||
qsb --glsl 320es,430 --msl 21 --tess-vertex-count 3 tessinterfaceblocks.tese -o tessinterfaceblocks.tese.qsb
|
||||
qsb --glsl 320es,430 --msl 21 simpletess.frag -o tessinterfaceblocks.frag.qsb
|
||||
|
10
tests/auto/gui/rhi/qrhi/data/half.vert
Normal file
10
tests/auto/gui/rhi/qrhi/data/half.vert
Normal file
@ -0,0 +1,10 @@
|
||||
#version 440
|
||||
|
||||
layout(location = 0) in vec3 position;
|
||||
|
||||
out gl_PerVertex { vec4 gl_Position; };
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(position, 1.0);
|
||||
}
|
BIN
tests/auto/gui/rhi/qrhi/data/half.vert.qsb
Normal file
BIN
tests/auto/gui/rhi/qrhi/data/half.vert.qsb
Normal file
Binary file not shown.
28
tests/auto/gui/rhi/qrhi/data/storagebuffer.comp
Normal file
28
tests/auto/gui/rhi/qrhi/data/storagebuffer.comp
Normal file
@ -0,0 +1,28 @@
|
||||
#version 430
|
||||
layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
|
||||
layout (binding = 0, std430) buffer toGpu
|
||||
{
|
||||
float _float;
|
||||
vec2 _vec2;
|
||||
vec3 _vec3;
|
||||
vec4 _vec4;
|
||||
};
|
||||
|
||||
layout (binding = 1, std140) buffer fromGpu
|
||||
{
|
||||
int _int;
|
||||
ivec2 _ivec2;
|
||||
ivec3 _ivec3;
|
||||
ivec4 _ivec4;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
_int = int(_float);
|
||||
_ivec2 = ivec2(_vec2);
|
||||
_ivec3 = ivec3(_vec3);
|
||||
_ivec4 = ivec4(_vec4);
|
||||
}
|
||||
|
BIN
tests/auto/gui/rhi/qrhi/data/storagebuffer.comp.qsb
Normal file
BIN
tests/auto/gui/rhi/qrhi/data/storagebuffer.comp.qsb
Normal file
Binary file not shown.
25
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.comp
Normal file
25
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.comp
Normal file
@ -0,0 +1,25 @@
|
||||
#version 430
|
||||
|
||||
layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
layout (binding = 0, std430) buffer toGpu
|
||||
{
|
||||
float _float[];
|
||||
};
|
||||
|
||||
|
||||
layout (binding = 1, std140) buffer fromGpu
|
||||
{
|
||||
int _int[];
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
int length = min(_float.length(), _int.length());
|
||||
|
||||
for (int i = 0; i < length; ++i)
|
||||
_int[i] = int(_float[i]);
|
||||
|
||||
}
|
||||
|
||||
|
BIN
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.comp.qsb
Normal file
BIN
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.comp.qsb
Normal file
Binary file not shown.
33
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.frag
Normal file
33
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.frag
Normal file
@ -0,0 +1,33 @@
|
||||
#version 450
|
||||
|
||||
layout (location = 0) out vec4 fragColor;
|
||||
|
||||
layout (std430, binding = 1) readonly buffer ssboG
|
||||
{
|
||||
float g[];
|
||||
};
|
||||
|
||||
layout (std430, binding = 2) readonly buffer ssboB
|
||||
{
|
||||
float b[];
|
||||
};
|
||||
|
||||
layout (std430, binding = 6) readonly buffer ssboR
|
||||
{
|
||||
float r[];
|
||||
};
|
||||
|
||||
layout (std430, binding = 3) readonly buffer ssbo3
|
||||
{
|
||||
vec4 _vec4;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
// some OpenGL implementations will optimize out the buffer variables if we don't use them
|
||||
// resulting in a .length() of 0.
|
||||
float a = (r[0]+g[0]+b[0])>0?1:1;
|
||||
|
||||
fragColor = a * vec4(r.length(), g.length(), b.length(), 255)/vec4(255);
|
||||
}
|
BIN
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.frag.qsb
Normal file
BIN
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.frag.qsb
Normal file
Binary file not shown.
42
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.tesc
Normal file
42
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.tesc
Normal file
@ -0,0 +1,42 @@
|
||||
#version 450
|
||||
|
||||
layout(vertices = 3) out;
|
||||
|
||||
|
||||
layout (std430, binding = 7) readonly buffer ssbo7
|
||||
{
|
||||
float float7[];
|
||||
};
|
||||
|
||||
layout (std430, binding = 8) readonly buffer ssbo8
|
||||
{
|
||||
float float8[];
|
||||
};
|
||||
|
||||
layout (std430, binding = 9) readonly buffer ssbo9
|
||||
{
|
||||
float float9[];
|
||||
};
|
||||
|
||||
layout (std430, binding = 10) readonly buffer ssbo10
|
||||
{
|
||||
float float10[];
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
// some OpenGL implementations will optimize out the buffer variables if we don't use them
|
||||
// resulting in a .length() of 0
|
||||
float a = float7[0] == 0 && float8[0] == 0 && float9[0] == 0 && float10[0] == 0 ? 1 : 1;
|
||||
|
||||
if (gl_InvocationID == 0) {
|
||||
gl_TessLevelOuter[0] = float7.length() * a;
|
||||
gl_TessLevelOuter[1] = float8.length() * a;
|
||||
gl_TessLevelOuter[2] = float9.length() * a;
|
||||
gl_TessLevelInner[0] = float10.length() * a;
|
||||
}
|
||||
|
||||
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
|
||||
|
||||
}
|
BIN
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.tesc.qsb
Normal file
BIN
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.tesc.qsb
Normal file
Binary file not shown.
39
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.tese
Normal file
39
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.tese
Normal file
@ -0,0 +1,39 @@
|
||||
#version 450
|
||||
|
||||
layout(triangles, fractional_odd_spacing, ccw) in;
|
||||
|
||||
layout (std140, binding = 6) uniform unused0
|
||||
{
|
||||
int unused;
|
||||
}u0;
|
||||
|
||||
layout (binding = 0) uniform u
|
||||
{
|
||||
mat4 matrix;
|
||||
};
|
||||
|
||||
layout (std430, binding = 5) readonly buffer ssbo5
|
||||
{
|
||||
float _float[];
|
||||
};
|
||||
|
||||
layout (std430, binding = 8) readonly buffer ssbo8
|
||||
{
|
||||
float float8[];
|
||||
};
|
||||
|
||||
layout (std430, binding = 1) readonly buffer unused1
|
||||
{
|
||||
int unused[];
|
||||
}u1;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// some OpenGL implementations will optimize out the buffer variables if we don't use them
|
||||
// resulting in a .length() of 0
|
||||
float a = _float[0] == 0 && float8[0] == 1 ? 1 : 1;
|
||||
|
||||
if(_float.length() == 64)
|
||||
gl_Position = a * matrix * ((gl_TessCoord.x * gl_in[0].gl_Position) + (gl_TessCoord.y * gl_in[1].gl_Position) + (gl_TessCoord.z * gl_in[2].gl_Position)) * (float8.length()==2?1:0);
|
||||
}
|
BIN
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.tese.qsb
Normal file
BIN
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.tese.qsb
Normal file
Binary file not shown.
48
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.vert
Normal file
48
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.vert
Normal file
@ -0,0 +1,48 @@
|
||||
#version 450
|
||||
|
||||
layout (location = 0) in vec3 position;
|
||||
|
||||
layout (std140, binding = 6) uniform unused0
|
||||
{
|
||||
int unused;
|
||||
}u0;
|
||||
|
||||
layout (binding = 0) uniform u
|
||||
{
|
||||
mat4 matrix;
|
||||
};
|
||||
|
||||
layout (std430, binding = 5) readonly buffer ssbo5
|
||||
{
|
||||
float _float[];
|
||||
};
|
||||
|
||||
layout (std140, binding = 3) readonly buffer ssbo3
|
||||
{
|
||||
vec4 _vec4;
|
||||
};
|
||||
|
||||
layout (std430, binding = 4) readonly buffer ssbo1
|
||||
{
|
||||
bool _bool[];
|
||||
};
|
||||
|
||||
layout (std430, binding = 1) readonly buffer unused1
|
||||
{
|
||||
int unused[];
|
||||
}u1;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
// some OpenGL implementations will optimize out the buffer variables if we don't use them
|
||||
// resulting in a .length() of 0
|
||||
float a = _float[0] == 0 && _bool[0] ? 1 : 1;
|
||||
|
||||
gl_Position = vec4(0);
|
||||
|
||||
if(_bool.length() == 32)
|
||||
gl_Position = a * matrix * vec4(position*_vec4.xyz, _float.length() == 64 ? 1.0 : 0.0);
|
||||
|
||||
}
|
BIN
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.vert.qsb
Normal file
BIN
tests/auto/gui/rhi/qrhi/data/storagebuffer_runtime.vert.qsb
Normal file
Binary file not shown.
BIN
tests/auto/gui/rhi/qrhi/data/tessinterfaceblocks.frag.qsb
Normal file
BIN
tests/auto/gui/rhi/qrhi/data/tessinterfaceblocks.frag.qsb
Normal file
Binary file not shown.
56
tests/auto/gui/rhi/qrhi/data/tessinterfaceblocks.tesc
Normal file
56
tests/auto/gui/rhi/qrhi/data/tessinterfaceblocks.tesc
Normal file
@ -0,0 +1,56 @@
|
||||
#version 440
|
||||
|
||||
layout(vertices = 3) out;
|
||||
|
||||
layout(location = 4) in VertOut
|
||||
{
|
||||
vec3 v_color;
|
||||
int a;
|
||||
float b;
|
||||
}vOut[];
|
||||
|
||||
layout(location = 5) out TescOutA {
|
||||
vec3 color;
|
||||
int id;
|
||||
}tcOutA[];
|
||||
|
||||
layout(location = 10) out TescOutB {
|
||||
vec2 some;
|
||||
int other[3];
|
||||
vec3 variables;
|
||||
}tcOutB[];
|
||||
|
||||
layout(location = 2) patch out TescOutC {
|
||||
vec3 stuff;
|
||||
float more_stuff;
|
||||
}tcOutC;
|
||||
|
||||
void main()
|
||||
{
|
||||
// tesc builtin outputs
|
||||
gl_TessLevelOuter[0] = 1.0;
|
||||
gl_TessLevelOuter[1] = 2.0;
|
||||
gl_TessLevelOuter[2] = 3.0;
|
||||
gl_TessLevelOuter[3] = 4.0;
|
||||
gl_TessLevelInner[0] = 5.0;
|
||||
gl_TessLevelInner[1] = 6.0;
|
||||
|
||||
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
|
||||
gl_out[gl_InvocationID].gl_PointSize = 10 + gl_InvocationID;
|
||||
gl_out[gl_InvocationID].gl_ClipDistance[0] = 20.0 + gl_InvocationID;
|
||||
gl_out[gl_InvocationID].gl_ClipDistance[1] = 40.0 + gl_InvocationID;
|
||||
gl_out[gl_InvocationID].gl_ClipDistance[2] = 60.0 + gl_InvocationID;
|
||||
gl_out[gl_InvocationID].gl_ClipDistance[3] = 80.0 + gl_InvocationID;
|
||||
gl_out[gl_InvocationID].gl_ClipDistance[4] = 100.0 + gl_InvocationID;
|
||||
|
||||
// outputs
|
||||
tcOutA[gl_InvocationID].color = vOut[gl_InvocationID].v_color;
|
||||
tcOutA[gl_InvocationID].id = gl_InvocationID + 91;
|
||||
tcOutB[gl_InvocationID].some = vec2(gl_InvocationID, vOut[gl_InvocationID].a);
|
||||
tcOutB[gl_InvocationID].other[0] = gl_PrimitiveID + 10;
|
||||
tcOutB[gl_InvocationID].other[1] = gl_PrimitiveID + 20;
|
||||
tcOutB[gl_InvocationID].other[2] = gl_PrimitiveID + 30;
|
||||
tcOutB[gl_InvocationID].variables = vec3(3.0f, vOut[gl_InvocationID].b, 17.0f);
|
||||
tcOutC.stuff = vec3(1.0, 2.0, 3.0);
|
||||
tcOutC.more_stuff = 4.0;
|
||||
}
|
BIN
tests/auto/gui/rhi/qrhi/data/tessinterfaceblocks.tesc.qsb
Normal file
BIN
tests/auto/gui/rhi/qrhi/data/tessinterfaceblocks.tesc.qsb
Normal file
Binary file not shown.
96
tests/auto/gui/rhi/qrhi/data/tessinterfaceblocks.tese
Normal file
96
tests/auto/gui/rhi/qrhi/data/tessinterfaceblocks.tese
Normal file
@ -0,0 +1,96 @@
|
||||
#version 440
|
||||
|
||||
layout(triangles, fractional_odd_spacing, ccw) in;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 mvp;
|
||||
};
|
||||
|
||||
layout(location = 5) in TescOutA {
|
||||
vec3 color;
|
||||
int id;
|
||||
}tcOutA[];
|
||||
|
||||
layout(location = 10) in TescOutB {
|
||||
vec2 some;
|
||||
int other[3];
|
||||
vec3 variables;
|
||||
}tcOutB[];
|
||||
|
||||
layout(location = 2) patch in TescOutC {
|
||||
vec3 stuff;
|
||||
float more_stuff;
|
||||
}tcOutC;
|
||||
|
||||
layout(location = 0) out vec3 outColor;
|
||||
|
||||
struct A {
|
||||
vec3 color;
|
||||
int id;
|
||||
};
|
||||
|
||||
struct B {
|
||||
vec2 some;
|
||||
int other[3];
|
||||
vec3 variables;
|
||||
};
|
||||
|
||||
struct C {
|
||||
vec3 stuff;
|
||||
float more_stuff;
|
||||
};
|
||||
|
||||
struct Element {
|
||||
A a[3];
|
||||
B b[3];
|
||||
C c;
|
||||
vec4 tesslevelOuter;
|
||||
vec2 tessLevelInner;
|
||||
float pointSize[3];
|
||||
float clipDistance[3][5];
|
||||
vec3 tessCoord;
|
||||
int patchVerticesIn;
|
||||
int primitiveID;
|
||||
};
|
||||
|
||||
layout(std430, binding = 1) buffer result {
|
||||
int count;
|
||||
Element elements[];
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = mvp * ((gl_TessCoord.x * gl_in[0].gl_Position) + (gl_TessCoord.y * gl_in[1].gl_Position) + (gl_TessCoord.z * gl_in[2].gl_Position));
|
||||
outColor = gl_TessCoord.x * tcOutA[0].color + gl_TessCoord.y * tcOutA[1].color + gl_TessCoord.z * tcOutA[2].color;
|
||||
|
||||
count = 1;
|
||||
|
||||
elements[gl_PrimitiveID].c.stuff = tcOutC.stuff;
|
||||
elements[gl_PrimitiveID].c.more_stuff = tcOutC.more_stuff;
|
||||
elements[gl_PrimitiveID].tesslevelOuter = vec4(gl_TessLevelOuter[0], gl_TessLevelOuter[1], gl_TessLevelOuter[2], gl_TessLevelOuter[3]);
|
||||
elements[gl_PrimitiveID].tessLevelInner = vec2(gl_TessLevelInner[0], gl_TessLevelInner[1]);
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
|
||||
elements[gl_PrimitiveID].a[i].color = tcOutA[i].color;
|
||||
elements[gl_PrimitiveID].a[i].id = tcOutA[i].id;
|
||||
|
||||
elements[gl_PrimitiveID].b[i].some = tcOutB[i].some;
|
||||
elements[gl_PrimitiveID].b[i].other = tcOutB[i].other;
|
||||
elements[gl_PrimitiveID].b[i].variables = tcOutB[i].variables;
|
||||
|
||||
elements[gl_PrimitiveID].pointSize[i] = gl_in[i].gl_PointSize;
|
||||
elements[gl_PrimitiveID].clipDistance[i][0] = gl_in[i].gl_ClipDistance[0];
|
||||
elements[gl_PrimitiveID].clipDistance[i][1] = gl_in[i].gl_ClipDistance[1];
|
||||
elements[gl_PrimitiveID].clipDistance[i][2] = gl_in[i].gl_ClipDistance[2];
|
||||
elements[gl_PrimitiveID].clipDistance[i][3] = gl_in[i].gl_ClipDistance[3];
|
||||
elements[gl_PrimitiveID].clipDistance[i][4] = gl_in[i].gl_ClipDistance[4];
|
||||
|
||||
}
|
||||
|
||||
elements[gl_PrimitiveID].tessCoord = gl_TessCoord;
|
||||
elements[gl_PrimitiveID].patchVerticesIn = 3;
|
||||
elements[gl_PrimitiveID].primitiveID = gl_PrimitiveID;
|
||||
|
||||
}
|
||||
|
BIN
tests/auto/gui/rhi/qrhi/data/tessinterfaceblocks.tese.qsb
Normal file
BIN
tests/auto/gui/rhi/qrhi/data/tessinterfaceblocks.tese.qsb
Normal file
Binary file not shown.
20
tests/auto/gui/rhi/qrhi/data/tessinterfaceblocks.vert
Normal file
20
tests/auto/gui/rhi/qrhi/data/tessinterfaceblocks.vert
Normal file
@ -0,0 +1,20 @@
|
||||
#version 440
|
||||
|
||||
layout(location = 0) in vec3 position;
|
||||
layout(location = 1) in vec3 color;
|
||||
|
||||
|
||||
layout(location = 4) out VertOut
|
||||
{
|
||||
vec3 v_color;
|
||||
int a;
|
||||
float b;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(position, 1.0);
|
||||
v_color = color;
|
||||
a = gl_VertexIndex;
|
||||
b = 13.0f + gl_VertexIndex;
|
||||
}
|
BIN
tests/auto/gui/rhi/qrhi/data/tessinterfaceblocks.vert.qsb
Normal file
BIN
tests/auto/gui/rhi/qrhi/data/tessinterfaceblocks.vert.qsb
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -5,8 +5,8 @@
|
||||
#include <QFile>
|
||||
#include <QBuffer>
|
||||
|
||||
#include <QtGui/private/qshaderdescription_p_p.h>
|
||||
#include <QtGui/private/qshader_p_p.h>
|
||||
#include <private/qshaderdescription_p.h>
|
||||
#include <private/qshader_p.h>
|
||||
|
||||
class tst_QShader : public QObject
|
||||
{
|
||||
|
@ -26,7 +26,6 @@ endif()
|
||||
if(QT_FEATURE_private_tests)
|
||||
add_subdirectory(qfontcache)
|
||||
add_subdirectory(qtextlayout)
|
||||
add_subdirectory(qzip)
|
||||
add_subdirectory(qtextodfwriter)
|
||||
endif()
|
||||
if(TARGET Qt::Xml)
|
||||
|
@ -1543,20 +1543,26 @@ void tst_QCssParser::gradient()
|
||||
QList<QCss::StyleRule> rules = testSelector.styleRulesForNode(n);
|
||||
QList<QCss::Declaration> decls = rules.at(0).declarations;
|
||||
QCss::ValueExtractor ve(decls);
|
||||
QBrush fg, sfg, pfg;
|
||||
QBrush sbg, abg;
|
||||
QVERIFY(ve.extractPalette(&fg, &sfg, &sbg, &abg, &pfg));
|
||||
QBrush foreground;
|
||||
QBrush selectedForeground;
|
||||
QBrush selectedBackground;
|
||||
QBrush alternateBackground;
|
||||
QBrush placeHolderTextForeground;
|
||||
QBrush accent;
|
||||
QVERIFY(ve.extractPalette(&foreground, &selectedForeground, &selectedBackground,
|
||||
&alternateBackground, &placeHolderTextForeground, &accent));
|
||||
|
||||
if (type == "linear") {
|
||||
QCOMPARE(sbg.style(), Qt::LinearGradientPattern);
|
||||
const QLinearGradient *lg = static_cast<const QLinearGradient *>(sbg.gradient());
|
||||
QCOMPARE(selectedBackground.style(), Qt::LinearGradientPattern);
|
||||
const auto *lg = static_cast<const QLinearGradient *>(selectedBackground.gradient());
|
||||
QCOMPARE(lg->start(), start);
|
||||
QCOMPARE(lg->finalStop(), finalStop);
|
||||
} else if (type == "conical") {
|
||||
QCOMPARE(sbg.style(), Qt::ConicalGradientPattern);
|
||||
const QConicalGradient *cg = static_cast<const QConicalGradient *>(sbg.gradient());
|
||||
QCOMPARE(selectedBackground.style(), Qt::ConicalGradientPattern);
|
||||
const auto *cg = static_cast<const QConicalGradient *>(selectedBackground.gradient());
|
||||
QCOMPARE(cg->center(), start);
|
||||
}
|
||||
const QGradient *g = sbg.gradient();
|
||||
const QGradient *g = selectedBackground.gradient();
|
||||
QCOMPARE(g->spread(), QGradient::Spread(spread));
|
||||
QCOMPARE(g->stops().at(0).first, stop0);
|
||||
QCOMPARE(g->stops().at(0).second, color0);
|
||||
|
@ -54,6 +54,7 @@ private slots:
|
||||
void setFamilies();
|
||||
void setFamiliesAndFamily_data();
|
||||
void setFamiliesAndFamily();
|
||||
void featureAccessors();
|
||||
};
|
||||
|
||||
// Testing get/set functions
|
||||
@ -150,7 +151,7 @@ void tst_QFont::italicOblique()
|
||||
continue;
|
||||
}
|
||||
QFont f = QFontDatabase::font(family, style, 12);
|
||||
QVERIFY(f.italic());
|
||||
QVERIFY2(f.italic(), qPrintable(QString::asprintf("Failed for font \"%ls\"", qUtf16Printable(f.family()))));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -841,5 +842,37 @@ void tst_QFont::setFamiliesAndFamily()
|
||||
QFontDatabase::removeApplicationFont(weirdFontId);
|
||||
}
|
||||
|
||||
void tst_QFont::featureAccessors()
|
||||
{
|
||||
QFont font;
|
||||
QVERIFY(font.featureTags().isEmpty());
|
||||
font.setFeature("abcd", 0xc0ffee);
|
||||
|
||||
quint32 abcdTag = QFont::stringToTag("abcd");
|
||||
quint32 bcdeTag = QFont::stringToTag("bcde");
|
||||
QVERIFY(font.isFeatureSet(abcdTag));
|
||||
QVERIFY(!font.isFeatureSet(bcdeTag));
|
||||
QCOMPARE(font.featureTags().size(), 1);
|
||||
QCOMPARE(font.featureTags().first(), abcdTag);
|
||||
QCOMPARE(QFont::tagToString(font.featureTags().first()), QByteArray("abcd"));
|
||||
QCOMPARE(font.featureValue(abcdTag), 0xc0ffeeU);
|
||||
QCOMPARE(font.featureValue(bcdeTag), 0U);
|
||||
font.setFeature(abcdTag, 0xf00d);
|
||||
QCOMPARE(font.featureTags().size(), 1);
|
||||
QCOMPARE(font.featureValue(abcdTag), 0xf00dU);
|
||||
font.setFeature("abcde", 0xcaca0);
|
||||
QVERIFY(!font.isFeatureSet(QFont::stringToTag("abcde")));
|
||||
QCOMPARE(font.featureTags().size(), 1);
|
||||
QFont font2 = font;
|
||||
|
||||
font.unsetFeature("abcd");
|
||||
QVERIFY(!font.isFeatureSet(QFont::stringToTag("abcd")));
|
||||
QVERIFY(font.featureTags().isEmpty());
|
||||
|
||||
QVERIFY(font2.isFeatureSet(QFont::stringToTag("abcd")));
|
||||
font2.clearFeatures();
|
||||
QVERIFY(font.featureTags().isEmpty());
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QFont)
|
||||
#include "tst_qfont.moc"
|
||||
|
@ -967,7 +967,7 @@ void tst_QGlyphRun::objectReplacementCharacter()
|
||||
QList<QGlyphRun> glyphRuns = layout.glyphRuns();
|
||||
QCOMPARE(glyphRuns.size(), 1);
|
||||
QCOMPARE(glyphRuns.first().glyphIndexes().size(), 1);
|
||||
QCOMPARE(glyphRuns.first().glyphIndexes().first(), 5);
|
||||
QCOMPARE(glyphRuns.first().glyphIndexes().first(), uint(5));
|
||||
}
|
||||
|
||||
#endif // QT_NO_RAWFONT
|
||||
|
@ -1545,15 +1545,20 @@ void tst_QTextCursor::insertMarkdown_data()
|
||||
<< 6 << QString("0) eggs\n1) maple syrup\n")
|
||||
<< QString("bread\u2029eggs\u2029maple syrup\u2029milk")
|
||||
<< QString("bread\neggs\nmaple syrup\nmilk")
|
||||
<< QString("1) bread\n2) eggs\n1) maple syrup\n2) milk\n");
|
||||
// renumbering would happen if we re-read the whole document
|
||||
<< QString("1) bread\n2) eggs\n0) maple syrup\n1) milk\n");
|
||||
// Renumbering would happen if we re-read the whole document.
|
||||
// Currently insertion only uses the new list format after a paragraph separator.
|
||||
// For that reason "bread" and "eggs" use the original list format, while "maple syrup" and
|
||||
// "milk" use the format from the just inserted list.
|
||||
|
||||
QTest::newRow("list after a list")
|
||||
<< "1) bread\n2) milk\n\n" << 2
|
||||
<< 13 << QString("\n0) eggs\n1) maple syrup\n")
|
||||
<< QString("bread\u2029milk\u2029eggs\u2029maple syrup")
|
||||
<< QString("bread\nmilk\neggs\nmaple syrup")
|
||||
<< QString("1) bread\n2) milk\n3) eggs\n1) maple syrup\n");
|
||||
<< QString("1) bread\n2) milk\n3) eggs\n0) maple syrup\n");
|
||||
// Same behavior as above. "eggs" uses the original list format, but "maple syrup" uses the
|
||||
// format of the inserted list, which means "maple syrup" now has a start of 0.
|
||||
|
||||
const QString markdownHeadingString("# Hello\nWorld\n");
|
||||
|
||||
|
@ -1780,6 +1780,22 @@ void tst_QTextDocument::toHtml_data()
|
||||
"<li class=\"unchecked\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">unchecked item</li>\n"
|
||||
"<li class=\"checked\" style=\" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">checked item</li></ul>");
|
||||
}
|
||||
|
||||
{
|
||||
CREATE_DOC_AND_CURSOR();
|
||||
|
||||
QTextListFormat fmt;
|
||||
fmt.setStyle(QTextListFormat::ListDecimal);
|
||||
fmt.setStart(4);
|
||||
cursor.insertList(fmt);
|
||||
cursor.insertText("Blah");
|
||||
cursor.insertBlock();
|
||||
cursor.insertText("Bleh");
|
||||
|
||||
QTest::newRow("ordered list with start") << QTextDocumentFragment(&doc)
|
||||
<< QString("EMPTYBLOCK") +
|
||||
QString("<ol start=\"4\" style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;\">\n<li style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Blah</li>\n<li style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Bleh</li></ol>");
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QTextDocument::toHtml()
|
||||
|
@ -96,6 +96,7 @@ private slots:
|
||||
void html_thCentered();
|
||||
void orderedListNumbering();
|
||||
void html_blockAfterList();
|
||||
void html_listStartAttribute();
|
||||
void html_subAndSuperScript();
|
||||
void html_cssColors();
|
||||
void obeyFragmentMarkersInImport();
|
||||
@ -1471,6 +1472,22 @@ void tst_QTextDocumentFragment::html_blockAfterList()
|
||||
QCOMPARE(cursor.blockFormat().indent(), 0);
|
||||
}
|
||||
|
||||
void tst_QTextDocumentFragment::html_listStartAttribute()
|
||||
{
|
||||
const char html[] = "<ol start=-1><li>Foo</ol><ol><li>Bar</ol>";
|
||||
cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
|
||||
|
||||
cursor.movePosition(QTextCursor::Start);
|
||||
|
||||
QVERIFY(cursor.currentList());
|
||||
QCOMPARE(cursor.currentList()->format().start(), -1);
|
||||
|
||||
QVERIFY(cursor.movePosition(QTextCursor::NextBlock));
|
||||
|
||||
QVERIFY(cursor.currentList());
|
||||
QCOMPARE(cursor.currentList()->format().start(), 1);
|
||||
}
|
||||
|
||||
void tst_QTextDocumentFragment::html_subAndSuperScript()
|
||||
{
|
||||
const char subHtml[] = "<sub>Subby</sub>";
|
||||
|
@ -36,6 +36,8 @@ private slots:
|
||||
void blockUpdate();
|
||||
void numbering_data();
|
||||
void numbering();
|
||||
void start_data();
|
||||
void start();
|
||||
|
||||
private:
|
||||
QTextDocument *doc;
|
||||
@ -400,5 +402,61 @@ void tst_QTextList::numbering()
|
||||
QCOMPARE(cursor.currentList()->itemText(cursor.block()), result);
|
||||
}
|
||||
|
||||
void tst_QTextList::start_data()
|
||||
{
|
||||
QTest::addColumn<int>("format");
|
||||
QTest::addColumn<int>("start");
|
||||
QTest::addColumn<QStringList>("expectedItemTexts");
|
||||
|
||||
QTest::newRow("-1.") << int(QTextListFormat::ListDecimal) << -1
|
||||
<< QStringList{ "-1.", "0.", "1." };
|
||||
QTest::newRow("0.") << int(QTextListFormat::ListDecimal) << 0
|
||||
<< QStringList{ "0.", "1.", "2." };
|
||||
QTest::newRow("1.") << int(QTextListFormat::ListDecimal) << 1
|
||||
<< QStringList{ "1.", "2.", "3." };
|
||||
|
||||
QTest::newRow("A. -1") << int(QTextListFormat::ListUpperAlpha) << -1
|
||||
<< QStringList{ "-1.", "0.", "A." };
|
||||
QTest::newRow("A. 0.") << int(QTextListFormat::ListUpperAlpha) << 0
|
||||
<< QStringList{ "0.", "A.", "B." };
|
||||
QTest::newRow("a. -1") << int(QTextListFormat::ListLowerAlpha) << -1
|
||||
<< QStringList{ "-1.", "0.", "a." };
|
||||
QTest::newRow("a. 0.") << int(QTextListFormat::ListLowerAlpha) << 0
|
||||
<< QStringList{ "0.", "a.", "b." };
|
||||
QTest::newRow("d. 4.") << int(QTextListFormat::ListLowerAlpha) << 4
|
||||
<< QStringList{ "d.", "e.", "f." };
|
||||
|
||||
QTest::newRow("I. -1") << int(QTextListFormat::ListUpperRoman) << -1
|
||||
<< QStringList{ "-1.", "0.", "I." };
|
||||
QTest::newRow("I. 0.") << int(QTextListFormat::ListUpperRoman) << 0
|
||||
<< QStringList{ "0.", "I.", "II." };
|
||||
QTest::newRow("i. -1") << int(QTextListFormat::ListLowerRoman) << -1
|
||||
<< QStringList{ "-1.", "0.", "i." };
|
||||
QTest::newRow("i. 0.") << int(QTextListFormat::ListLowerRoman) << 0
|
||||
<< QStringList{ "0.", "i.", "ii." };
|
||||
}
|
||||
|
||||
void tst_QTextList::start()
|
||||
{
|
||||
QFETCH(int, format);
|
||||
QFETCH(int, start);
|
||||
QFETCH(QStringList, expectedItemTexts);
|
||||
|
||||
QTextListFormat fmt;
|
||||
fmt.setStyle(QTextListFormat::Style(format));
|
||||
fmt.setStart(start);
|
||||
QTextList *list = cursor.createList(fmt);
|
||||
QVERIFY(list);
|
||||
|
||||
while (list->count() < int(expectedItemTexts.size()))
|
||||
cursor.insertBlock();
|
||||
|
||||
QCOMPARE(list->count(), expectedItemTexts.size());
|
||||
|
||||
for (int i = 0; i < list->count(); ++i)
|
||||
QCOMPARE(cursor.currentList()->itemText(cursor.currentList()->item(i)),
|
||||
expectedItemTexts[i]);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QTextList)
|
||||
#include "tst_qtextlist.moc"
|
||||
|
@ -182,36 +182,58 @@ void tst_QTextMarkdownImporter::thematicBreaks()
|
||||
void tst_QTextMarkdownImporter::lists_data()
|
||||
{
|
||||
QTest::addColumn<QString>("input");
|
||||
QTest::addColumn<int>("skipToCheckStart");
|
||||
QTest::addColumn<int>("expectedListStart");
|
||||
QTest::addColumn<int>("expectedItemCount");
|
||||
QTest::addColumn<bool>("expectedEmptyItems");
|
||||
QTest::addColumn<QString>("rewrite");
|
||||
|
||||
// Some of these cases show odd behavior, which is subject to change
|
||||
// as the importer and the writer are tweaked to fix bugs over time.
|
||||
QTest::newRow("dot newline") << ".\n" << 0 << true << ".\n\n";
|
||||
QTest::newRow("number dot newline") << "1.\n" << 1 << true << "1. \n";
|
||||
QTest::newRow("star newline") << "*\n" << 1 << true << "* \n";
|
||||
QTest::newRow("hyphen newline") << "-\n" << 1 << true << "- \n";
|
||||
QTest::newRow("hyphen space newline") << "- \n" << 1 << true << "- \n";
|
||||
QTest::newRow("hyphen space letter newline") << "- a\n" << 1 << false << "- a\n";
|
||||
QTest::newRow("dot newline") << ".\n" << 0 << 1 << 0 << true << ".\n\n";
|
||||
QTest::newRow("number dot newline") << "1.\n" << 0 << 1 << 1 << true << "1. \n";
|
||||
QTest::newRow("number offset start") << "2. text\n" << 0 << 2 << 1 << false << "2. text\n";
|
||||
QTest::newRow("second list offset start")
|
||||
<< "1. text\n\nintervening paragraph\n\n4. second list item"
|
||||
<< 2 << 4 << 2 << false
|
||||
<< "1. text\n\nintervening paragraph\n\n4. second list item\n";
|
||||
QTest::newRow("list continuation offset start")
|
||||
<< "3. text\n\n next paragraph in item 1\n10. second list item"
|
||||
<< 2 << 3 << 2 << false
|
||||
<< "3. text\n\n next paragraph in item 1\n\n4. second list item\n";
|
||||
QTest::newRow("nested list offset start")
|
||||
<< "1. text\n\n 0. indented list item\n\n4. second item in first list"
|
||||
<< 1 << 0 << 3 << false
|
||||
<< "1. text\n 0. indented list item\n2. second item in first list\n";
|
||||
QTest::newRow("offset start after nested list")
|
||||
<< "1. text\n\n 0. indented list item\n\n4. second item in first list"
|
||||
<< 2 << 1 << 3 << false
|
||||
<< "1. text\n 0. indented list item\n2. second item in first list\n";
|
||||
QTest::newRow("star newline") << "*\n" << 0 << 1 << 1 << true << "* \n";
|
||||
QTest::newRow("hyphen newline") << "-\n" << 0 << 1 << 1 << true << "- \n";
|
||||
QTest::newRow("hyphen space newline") << "- \n" << 0 << 1 << 1 << true << "- \n";
|
||||
QTest::newRow("hyphen space letter newline") << "- a\n" << 0 << 1 << 1 << false << "- a\n";
|
||||
QTest::newRow("hyphen nbsp newline") <<
|
||||
QString::fromUtf8("-\u00A0\n") << 0 << true << "-\u00A0\n\n";
|
||||
QTest::newRow("nested empty lists") << "*\n *\n *\n" << 1 << true << " * \n";
|
||||
QTest::newRow("list nested in empty list") << "-\n * a\n" << 2 << false << "- \n * a\n";
|
||||
QString::fromUtf8("-\u00A0\n") << 0 << 1 << 0 << true << "-\u00A0\n\n";
|
||||
QTest::newRow("nested empty lists") << "*\n *\n *\n" << 0 << 1 << 1 << true << " * \n";
|
||||
QTest::newRow("list nested in empty list") << "-\n * a\n" << 0 << 1 << 2 << false << "- \n * a\n";
|
||||
QTest::newRow("lists nested in empty lists")
|
||||
<< "-\n * a\n * b\n- c\n *\n + d\n" << 5 << false
|
||||
<< "-\n * a\n * b\n- c\n *\n + d\n" << 0 << 1 << 5 << false
|
||||
<< "- \n * a\n * b\n- c *\n + d\n";
|
||||
QTest::newRow("numeric lists nested in empty lists")
|
||||
<< "- \n 1. a\n 2. b\n- c\n 1.\n + d\n" << 4 << false
|
||||
<< "- \n 1. a\n 2. b\n- c\n 1.\n + d\n" << 0 << 1 << 4 << false
|
||||
<< "- \n 1. a\n 2. b\n- c 1. + d\n";
|
||||
QTest::newRow("styled spans in list items")
|
||||
<< "1. normal text\n2. **bold** text\n3. `code` in the item\n4. *italic* text\n5. _underlined_ text\n" << 5 << false
|
||||
<< "1. normal text\n2. **bold** text\n3. `code` in the item\n4. *italic* text\n5. _underlined_ text\n"
|
||||
<< 0 << 1 << 5 << false
|
||||
<< "1. normal text\n2. **bold** text\n3. `code` in the item\n4. *italic* text\n5. _underlined_ text\n";
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownImporter::lists()
|
||||
{
|
||||
QFETCH(QString, input);
|
||||
QFETCH(int, skipToCheckStart);
|
||||
QFETCH(int, expectedListStart);
|
||||
QFETCH(int, expectedItemCount);
|
||||
QFETCH(bool, expectedEmptyItems);
|
||||
QFETCH(QString, rewrite);
|
||||
@ -227,6 +249,8 @@ void tst_QTextMarkdownImporter::lists()
|
||||
out.close();
|
||||
}
|
||||
#endif
|
||||
qCDebug(lcTests) << " original:" << input;
|
||||
qCDebug(lcTests) << "rewritten:" << doc.toMarkdown();
|
||||
|
||||
QTextFrame::iterator iterator = doc.rootFrame()->begin();
|
||||
QTextFrame *currentFrame = iterator.currentFrame();
|
||||
@ -239,10 +263,12 @@ void tst_QTextMarkdownImporter::lists()
|
||||
QCOMPARE(iterator.currentFrame(), currentFrame);
|
||||
// Check whether the block is text or a horizontal rule
|
||||
QTextBlock block = iterator.currentBlock();
|
||||
QTextListFormat listFmt;
|
||||
if (block.textList()) {
|
||||
++itemCount;
|
||||
if (!block.text().isEmpty())
|
||||
emptyItems = false;
|
||||
listFmt = block.textList()->format();
|
||||
}
|
||||
qCDebug(lcTests, "%d %s%s", i,
|
||||
(block.textList() ? "<li>" : "<p>"), qPrintable(block.text()));
|
||||
@ -261,6 +287,11 @@ void tst_QTextMarkdownImporter::lists()
|
||||
QCOMPARE(listItemFmt.fontItalic(), false);
|
||||
QCOMPARE(listItemFmt.fontUnderline(), false);
|
||||
QCOMPARE(listItemFmt.fontFixedPitch(), false);
|
||||
if (i == skipToCheckStart) {
|
||||
qCDebug(lcTests) << "skipped to list item" << i << block.text()
|
||||
<< "start" << listFmt.start() << "expected" << expectedListStart;
|
||||
QCOMPARE(listFmt.start(), expectedListStart);
|
||||
}
|
||||
++iterator;
|
||||
++i;
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ private slots:
|
||||
void testWriteNestedBulletLists_data();
|
||||
void testWriteNestedBulletLists();
|
||||
void testWriteNestedNumericLists();
|
||||
void testWriteNumericListWithStart();
|
||||
void testWriteTable();
|
||||
void rewriteDocument_data();
|
||||
void rewriteDocument();
|
||||
@ -284,6 +285,7 @@ void tst_QTextMarkdownWriter::testWriteNestedNumericLists()
|
||||
list1->add(cursor.block());
|
||||
|
||||
QTextListFormat fmt2;
|
||||
// Alpha "numbering" is not supported in markdown, so we'll actually get decimal.
|
||||
fmt2.setStyle(QTextListFormat::ListLowerAlpha);
|
||||
fmt2.setNumberSuffix(QLatin1String(")"));
|
||||
fmt2.setIndent(2);
|
||||
@ -305,7 +307,24 @@ void tst_QTextMarkdownWriter::testWriteNestedNumericLists()
|
||||
list2->add(cursor.block());
|
||||
|
||||
const QString output = documentToUnixMarkdown();
|
||||
// There's no QTextList API to set the starting number so we hard-coded all lists to start at 1 (QTBUG-65384)
|
||||
|
||||
#ifdef DEBUG_WRITE_OUTPUT
|
||||
{
|
||||
QFile out(QDir::temp().filePath(QLatin1String(QTest::currentTestFunction()) + ".md"));
|
||||
out.open(QFile::WriteOnly);
|
||||
out.write(output.toUtf8());
|
||||
out.close();
|
||||
}
|
||||
{
|
||||
QFile out(QDir::temp().filePath(QLatin1String(QTest::currentTestFunction()) + ".html"));
|
||||
out.open(QFile::WriteOnly);
|
||||
out.write(document->toHtml().toUtf8());
|
||||
out.close();
|
||||
}
|
||||
#endif
|
||||
|
||||
// While we can set the start index for a block, if list items intersect each other, they will
|
||||
// still use the list numbering.
|
||||
const QString expected = QString::fromLatin1(
|
||||
"1. ListItem 1\n 1) ListItem 2\n 1. ListItem 3\n2. ListItem 4\n 2) ListItem 5\n");
|
||||
if (output != expected && isMainFontFixed())
|
||||
@ -313,6 +332,92 @@ void tst_QTextMarkdownWriter::testWriteNestedNumericLists()
|
||||
QCOMPARE(output, expected);
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::testWriteNumericListWithStart()
|
||||
{
|
||||
QTextCursor cursor(document);
|
||||
|
||||
// The first list will start at 2.
|
||||
QTextListFormat fmt1;
|
||||
fmt1.setStyle(QTextListFormat::ListDecimal);
|
||||
fmt1.setStart(2);
|
||||
QTextList *list1 = cursor.createList(fmt1);
|
||||
cursor.insertText("ListItem 1");
|
||||
list1->add(cursor.block());
|
||||
|
||||
// This list uses the default start (1) again.
|
||||
QTextListFormat fmt2;
|
||||
// Alpha "numbering" is not supported in markdown, so we'll actually get decimal.
|
||||
fmt2.setStyle(QTextListFormat::ListLowerAlpha);
|
||||
fmt2.setNumberSuffix(QLatin1String(")"));
|
||||
fmt2.setIndent(2);
|
||||
QTextList *list2 = cursor.insertList(fmt2);
|
||||
cursor.insertText("ListItem 2");
|
||||
|
||||
// Negative list numbers are disallowed by most Markdown implementations. This list will start
|
||||
// at 1 for that reason.
|
||||
QTextListFormat fmt3;
|
||||
fmt3.setStyle(QTextListFormat::ListDecimal);
|
||||
fmt3.setIndent(3);
|
||||
fmt3.setStart(-1);
|
||||
cursor.insertList(fmt3);
|
||||
cursor.insertText("ListItem 3");
|
||||
|
||||
// Continuing list1, so the second item will have the number 3.
|
||||
cursor.insertBlock();
|
||||
cursor.insertText("ListItem 4");
|
||||
list1->add(cursor.block());
|
||||
|
||||
// This will look out of place: it's in a different position than its list would suggest.
|
||||
// Generates invalid markdown numbering (OK for humans, but md4c will parse it differently than we "meant").
|
||||
// TODO QTBUG-111707: the writer needs to add newlines, otherwise ListItem 5 becomes part of the text for ListItem 4.
|
||||
cursor.insertBlock();
|
||||
cursor.insertText("ListItem 5");
|
||||
list2->add(cursor.block());
|
||||
|
||||
// 0 indexed lists are fine.
|
||||
QTextListFormat fmt4;
|
||||
fmt4.setStyle(QTextListFormat::ListDecimal);
|
||||
fmt4.setStart(0);
|
||||
QTextList *list4 = cursor.insertList(fmt4);
|
||||
cursor.insertText("SecondList Item 0");
|
||||
list4->add(cursor.block());
|
||||
|
||||
// Ensure list numbers are incremented properly.
|
||||
cursor.insertBlock();
|
||||
cursor.insertText("SecondList Item 1");
|
||||
list4->add(cursor.block());
|
||||
|
||||
const QString output = documentToUnixMarkdown();
|
||||
const QString expected = QString::fromLatin1(
|
||||
R"(2. ListItem 1
|
||||
1) ListItem 2
|
||||
1. ListItem 3
|
||||
3. ListItem 4
|
||||
2) ListItem 5
|
||||
0. SecondList Item 0
|
||||
1. SecondList Item 1
|
||||
)");
|
||||
|
||||
#ifdef DEBUG_WRITE_OUTPUT
|
||||
{
|
||||
QFile out(QDir::temp().filePath(QLatin1String(QTest::currentTestFunction()) + ".md"));
|
||||
out.open(QFile::WriteOnly);
|
||||
out.write(output.toUtf8());
|
||||
out.close();
|
||||
}
|
||||
{
|
||||
QFile out(QDir::temp().filePath(QLatin1String(QTest::currentTestFunction()) + ".html"));
|
||||
out.open(QFile::WriteOnly);
|
||||
out.write(document->toHtml().toUtf8());
|
||||
out.close();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (output != expected && isMainFontFixed())
|
||||
QEXPECT_FAIL("", "fixed-pitch main font (QTBUG-103484)", Continue);
|
||||
QCOMPARE(output, expected);
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::testWriteTable()
|
||||
{
|
||||
QTextCursor cursor(document);
|
||||
|
@ -1,21 +0,0 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qzip Test:
|
||||
#####################################################################
|
||||
|
||||
# Collect test data
|
||||
file(GLOB_RECURSE test_data
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
testdata/*
|
||||
)
|
||||
|
||||
qt_internal_add_test(tst_qzip
|
||||
SOURCES
|
||||
tst_qzip.cpp
|
||||
LIBRARIES
|
||||
Qt::Gui
|
||||
Qt::GuiPrivate
|
||||
TESTDATA ${test_data}
|
||||
)
|
BIN
tests/auto/gui/text/qzip/testdata/symlink.zip
vendored
BIN
tests/auto/gui/text/qzip/testdata/symlink.zip
vendored
Binary file not shown.
BIN
tests/auto/gui/text/qzip/testdata/test.zip
vendored
BIN
tests/auto/gui/text/qzip/testdata/test.zip
vendored
Binary file not shown.
@ -1,116 +0,0 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include <QTest>
|
||||
#include <QDebug>
|
||||
#include <QBuffer>
|
||||
|
||||
#include <private/qzipwriter_p.h>
|
||||
#include <private/qzipreader_p.h>
|
||||
|
||||
class tst_QZip : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void basicUnpack();
|
||||
void symlinks();
|
||||
void readTest();
|
||||
void createArchive();
|
||||
};
|
||||
|
||||
void tst_QZip::basicUnpack()
|
||||
{
|
||||
QZipReader zip(QFINDTESTDATA("/testdata/test.zip"), QIODevice::ReadOnly);
|
||||
QList<QZipReader::FileInfo> files = zip.fileInfoList();
|
||||
QCOMPARE(files.size(), 2);
|
||||
|
||||
QZipReader::FileInfo fi = files.at(0);
|
||||
QVERIFY(fi.isValid());
|
||||
QCOMPARE(fi.filePath, QString("test"));
|
||||
QCOMPARE(uint(fi.isDir), (uint) 1);
|
||||
QCOMPARE(uint(fi.isFile), (uint) 0);
|
||||
QCOMPARE(uint(fi.isSymLink), (uint) 0);
|
||||
|
||||
QCOMPARE(fi.permissions,QFile::Permissions( QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner
|
||||
| QFile::ReadUser | QFile::WriteUser | QFile::ExeUser ));
|
||||
|
||||
QCOMPARE(fi.lastModified, QDateTime::fromString("2005.11.11 13:08:02", "yyyy.MM.dd HH:mm:ss"));
|
||||
|
||||
fi = files.at(1);
|
||||
QVERIFY(fi.isValid());
|
||||
QCOMPARE(fi.filePath, QString("test/test.txt"));
|
||||
QCOMPARE(uint(fi.isDir), (uint) 0);
|
||||
QCOMPARE(uint(fi.isFile), (uint) 1);
|
||||
QCOMPARE(uint(fi.isSymLink), (uint) 0);
|
||||
|
||||
QVERIFY(fi.permissions == QFile::Permissions( QFile::ReadOwner | QFile::WriteOwner
|
||||
| QFile::ReadUser | QFile::WriteUser ));
|
||||
|
||||
QCOMPARE(fi.lastModified, QDateTime::fromString("2005.11.11 13:08:02", "yyyy.MM.dd HH:mm:ss"));
|
||||
|
||||
QCOMPARE(zip.fileData("test/test.txt"), QByteArray("content\n"));
|
||||
|
||||
fi = zip.entryInfoAt(-1);
|
||||
QVERIFY(!fi.isValid());
|
||||
}
|
||||
|
||||
void tst_QZip::symlinks()
|
||||
{
|
||||
QZipReader zip(QFINDTESTDATA("/testdata/symlink.zip"), QIODevice::ReadOnly);
|
||||
QList<QZipReader::FileInfo> files = zip.fileInfoList();
|
||||
QCOMPARE(files.size(), 2);
|
||||
|
||||
QZipReader::FileInfo fi = files.at(0);
|
||||
QVERIFY(fi.isValid());
|
||||
QCOMPARE(fi.filePath, QString("symlink"));
|
||||
QVERIFY(!fi.isDir);
|
||||
QVERIFY(!fi.isFile);
|
||||
QVERIFY(fi.isSymLink);
|
||||
|
||||
QCOMPARE(zip.fileData("symlink"), QByteArray("destination"));
|
||||
|
||||
fi = files.at(1);
|
||||
QVERIFY(fi.isValid());
|
||||
QCOMPARE(fi.filePath, QString("destination"));
|
||||
QVERIFY(!fi.isDir);
|
||||
QVERIFY(fi.isFile);
|
||||
QVERIFY(!fi.isSymLink);
|
||||
}
|
||||
|
||||
void tst_QZip::readTest()
|
||||
{
|
||||
QZipReader zip("foobar.zip", QIODevice::ReadOnly); // non existing file.
|
||||
QList<QZipReader::FileInfo> files = zip.fileInfoList();
|
||||
QCOMPARE(files.size(), 0);
|
||||
QByteArray b = zip.fileData("foobar");
|
||||
QCOMPARE(b.size(), 0);
|
||||
}
|
||||
|
||||
void tst_QZip::createArchive()
|
||||
{
|
||||
QBuffer buffer;
|
||||
QZipWriter zip(&buffer);
|
||||
QByteArray fileContents("simple file contents\nline2\n");
|
||||
zip.addFile("My Filename", fileContents);
|
||||
zip.close();
|
||||
QByteArray zipFile = buffer.buffer();
|
||||
|
||||
// QFile f("createArchiveTest.zip"); f.open(QIODevice::WriteOnly); f.write(zipFile); f.close();
|
||||
|
||||
QBuffer buffer2(&zipFile);
|
||||
QZipReader zip2(&buffer2);
|
||||
QList<QZipReader::FileInfo> files = zip2.fileInfoList();
|
||||
QCOMPARE(files.size(), 1);
|
||||
QZipReader::FileInfo file = files.at(0);
|
||||
QCOMPARE(file.filePath, QString("My Filename"));
|
||||
QCOMPARE(uint(file.isDir), (uint) 0);
|
||||
QCOMPARE(uint(file.isFile), (uint) 1);
|
||||
QCOMPARE(uint(file.isSymLink), (uint) 0);
|
||||
QCOMPARE(file.permissions, QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::WriteUser) );
|
||||
QCOMPARE(file.size, (long long) 27);
|
||||
QCOMPARE(zip2.fileData("My Filename"), fileContents);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QZip)
|
||||
#include "tst_qzip.moc"
|
Reference in New Issue
Block a user