diff options
| -rw-r--r-- | src/corelib/text/qlocale_icu.cpp | 12 | ||||
| -rw-r--r-- | src/gui/image/qpaintengine_pic.cpp | 17 | ||||
| -rw-r--r-- | src/gui/image/qpicture.cpp | 6 | ||||
| -rw-r--r-- | src/gui/image/qpicture_p.h | 1 | ||||
| -rw-r--r-- | src/gui/painting/qcolorspace.cpp | 4 | ||||
| -rw-r--r-- | src/gui/painting/qpainter.cpp | 17 | ||||
| -rw-r--r-- | src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | 20 | ||||
| -rw-r--r-- | src/plugins/styles/modernwindows/qwindows11style.cpp | 41 |
8 files changed, 69 insertions, 49 deletions
diff --git a/src/corelib/text/qlocale_icu.cpp b/src/corelib/text/qlocale_icu.cpp index a10ae1c84b2..7e1dba5ee92 100644 --- a/src/corelib/text/qlocale_icu.cpp +++ b/src/corelib/text/qlocale_icu.cpp @@ -17,10 +17,10 @@ static_assert(std::is_same_v<UChar, char16_t>, namespace QtIcuPrivate { -enum class CaseConversion : bool { Upper, Lower }; +enum class IcuCaseConversion : bool { Upper, Lower }; static bool qt_u_strToCase(const QString &str, QString *out, const char *localeID, - CaseConversion conv) + IcuCaseConversion conv) { Q_ASSERT(out); @@ -34,9 +34,9 @@ static bool qt_u_strToCase(const QString &str, QString *out, const char *localeI // try to be a completely transparent wrapper: using R [[maybe_unused]] = decltype(u_strToUpper(std::forward<decltype(args)>(args)...)); switch (conv) { - case CaseConversion::Upper: + case IcuCaseConversion::Upper: return u_strToUpper(std::forward<decltype(args)>(args)...); - case CaseConversion::Lower: + case IcuCaseConversion::Lower: return u_strToLower(std::forward<decltype(args)>(args)...); }; Q_UNREACHABLE_RETURN(R{0}); @@ -79,7 +79,7 @@ QString QLocalePrivate::toUpper(const QString &str, bool *ok) const Q_ASSERT(ok); using namespace QtIcuPrivate; QString out; - *ok = qt_u_strToCase(str, &out, bcp47Name('_'), CaseConversion::Upper); + *ok = qt_u_strToCase(str, &out, bcp47Name('_'), IcuCaseConversion::Upper); return out; } @@ -88,7 +88,7 @@ QString QLocalePrivate::toLower(const QString &str, bool *ok) const Q_ASSERT(ok); using namespace QtIcuPrivate; QString out; - *ok = qt_u_strToCase(str, &out, bcp47Name('_'), CaseConversion::Lower); + *ok = qt_u_strToCase(str, &out, bcp47Name('_'), IcuCaseConversion::Lower); return out; } diff --git a/src/gui/image/qpaintengine_pic.cpp b/src/gui/image/qpaintengine_pic.cpp index ba4888cef75..b151c3b2d18 100644 --- a/src/gui/image/qpaintengine_pic.cpp +++ b/src/gui/image/qpaintengine_pic.cpp @@ -31,6 +31,7 @@ public: QDataStream s; QPainter *pt; QPicturePrivate *pic_d; + bool sizeLimitExceeded = false; }; QPicturePaintEngine::QPicturePaintEngine() @@ -68,6 +69,7 @@ bool QPicturePaintEngine::begin(QPaintDevice *pd) d->s.setVersion(d->pic_d->formatMajor); d->pic_d->pictb.open(QIODevice::WriteOnly | QIODevice::Truncate); + d->sizeLimitExceeded = false; d->s.writeRawData(qt_mfhdr_tag, 4); d->s << (quint16) 0 << (quint16) d->pic_d->formatMajor << (quint16) d->pic_d->formatMinor; d->s << (quint8) QPicturePrivate::PdcBegin << (quint8) sizeof(qint32); @@ -109,7 +111,7 @@ bool QPicturePaintEngine::end() d->s << cs; // write checksum d->pic_d->pictb.close(); setActive(false); - return true; + return !d->sizeLimitExceeded; } #define SERIALIZE_CMD(c) \ @@ -286,6 +288,19 @@ void QPicturePaintEngine::updateRenderHints(QPainter::RenderHints hints) void QPicturePaintEngine::writeCmdLength(int pos, const QRectF &r, bool corr) { Q_D(QPicturePaintEngine); + + constexpr int sizeLimit = std::numeric_limits<int>::max() - 8; // Leave room for ending bytes + if (d->sizeLimitExceeded || d->pic_d->pictb.pos() > sizeLimit) { + d->pic_d->trecs--; // Remove last command added, started by SERIALIZE_CMD + d->pic_d->pictb.seek(pos - 2); + d->pic_d->pictbData.resize(pos - 2); + if (!d->sizeLimitExceeded) { + d->sizeLimitExceeded = true; + qWarning("QPicture: size limit exceeded, will be truncated"); + } + return; + } + int newpos = d->pic_d->pictb.pos(); // new position int length = newpos - pos; QRectF br(r); diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp index ac0525d7abf..db2a5fd9ba9 100644 --- a/src/gui/image/qpicture.cpp +++ b/src/gui/image/qpicture.cpp @@ -970,7 +970,8 @@ QPicture& QPicture::operator=(const QPicture &p) Constructs a QPicturePrivate */ QPicturePrivate::QPicturePrivate() - : in_memory_only(false) + : pictb(&pictbData), + in_memory_only(false) { } @@ -980,7 +981,8 @@ QPicturePrivate::QPicturePrivate() Copy-Constructs a QPicturePrivate. Needed when detaching. */ QPicturePrivate::QPicturePrivate(const QPicturePrivate &other) - : trecs(other.trecs), + : pictb(&pictbData), + trecs(other.trecs), formatOk(other.formatOk), formatMinor(other.formatMinor), brect(other.brect), diff --git a/src/gui/image/qpicture_p.h b/src/gui/image/qpicture_p.h index c512f49320b..1d8142f44b7 100644 --- a/src/gui/image/qpicture_p.h +++ b/src/gui/image/qpicture_p.h @@ -113,6 +113,7 @@ public: bool checkFormat(); void resetFormat(); + QByteArray pictbData; QBuffer pictb; int trecs; bool formatOk; diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp index c43d133dd1e..9149971b999 100644 --- a/src/gui/painting/qcolorspace.cpp +++ b/src/gui/painting/qcolorspace.cpp @@ -1206,12 +1206,12 @@ QByteArray QColorSpace::iccProfile() const QColorSpace QColorSpace::fromIccProfile(const QByteArray &iccProfile) { // Must detach if input is fromRawData(); nullTerminated() is trick to do that and nothing else - const QByteArray ownedIccProfile(iccProfile.nullTerminated()); + QByteArray ownedIccProfile = iccProfile.nullTerminated(); QColorSpace colorSpace; if (QIcc::fromIccProfile(ownedIccProfile, &colorSpace)) return colorSpace; colorSpace.detach(); - colorSpace.d_ptr->iccProfile = ownedIccProfile; + colorSpace.d_ptr->iccProfile = std::move(ownedIccProfile); return colorSpace; } diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index a3f9f069b69..2b6a8a858f9 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -6474,8 +6474,9 @@ QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextO and height (on both 1x and 2x displays), and produces high-resolution output on 2x displays. - The \a position offset is always in the painter coordinate system, - indepentent of display devicePixelRatio. + The \a position offset is provided in the device independent pixels + relative to the top-left corner of the \a rectangle. The \a position + can be used to align the repeating pattern inside the \a rectangle. \sa drawPixmap() */ @@ -6497,8 +6498,8 @@ void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPo qt_painter_thread_test(d->device->devType(), d->engine->type(), "drawTiledPixmap()"); #endif - qreal sw = pixmap.width(); - qreal sh = pixmap.height(); + const qreal sw = pixmap.width() / pixmap.devicePixelRatio(); + const qreal sh = pixmap.height() / pixmap.devicePixelRatio(); qreal sx = sp.x(); qreal sy = sp.y(); if (sx < 0) @@ -6579,8 +6580,12 @@ void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPo (\a{x}, \a{y}) specifies the top-left point in the paint device that is to be drawn onto; with the given \a width and \a - height. (\a{sx}, \a{sy}) specifies the top-left point in the \a - pixmap that is to be drawn; this defaults to (0, 0). + height. + + (\a{sx}, \a{sy}) specifies the origin inside the specified rectangle + where the pixmap will be drawn. The origin position is specified in + the device independent pixels relative to (\a{x}, \a{y}). This defaults + to (0, 0). */ #ifndef QT_NO_PICTURE diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 4c4e5fac962..52540666718 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -733,6 +733,26 @@ bool QCocoaFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit return false; } + if (qt_apple_isSandboxed()) { + static bool canRead = qt_mac_processHasEntitlement( + u"com.apple.security.files.user-selected.read-only"_s); + static bool canReadWrite = qt_mac_processHasEntitlement( + u"com.apple.security.files.user-selected.read-write"_s); + + if (options()->acceptMode() == QFileDialogOptions::AcceptSave + && !canReadWrite) { + qWarning() << "Sandboxed application is missing user-selected files" + << "read-write entitlement. Falling back to non-native dialog"; + return false; + } + + if (!canReadWrite && !canRead) { + qWarning() << "Sandboxed application is missing user-selected files" + << "entitlement. Falling back to non-native dialog"; + return false; + } + } + createNSOpenSavePanelDelegate(); return [m_delegate showPanel:windowModality withParent:parent]; diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp index bf4b3c6a9bc..ffba4f775c8 100644 --- a/src/plugins/styles/modernwindows/qwindows11style.cpp +++ b/src/plugins/styles/modernwindows/qwindows11style.cpp @@ -24,6 +24,7 @@ #if QT_CONFIG(mdiarea) #include <QtWidgets/qmdiarea.h> #endif +#include <QtWidgets/qplaintextedit.h> #include <QtWidgets/qtextedit.h> #include <QtWidgets/qtreeview.h> #if QT_CONFIG(datetimeedit) @@ -1027,7 +1028,9 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption if (frame->frameShape == QFrame::NoFrame) break; - drawLineEditFrame(painter, rect, option, qobject_cast<const QTextEdit *>(widget) != nullptr); + const bool isEditable = qobject_cast<const QTextEdit *>(widget) != nullptr + || qobject_cast<const QPlainTextEdit *>(widget) != nullptr; + drawLineEditFrame(painter, rect, option, isEditable); } break; } @@ -1452,36 +1455,10 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op #endif // QT_CONFIG(progressbar) case CE_PushButtonLabel: if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { - using namespace StyleOptionHelper; - const bool isEnabled = !isDisabled(option); - - QRect textRect = btn->rect.marginsRemoved(QMargins(contentHMargin, 0, contentHMargin, 0)); - int tf = Qt::AlignCenter | Qt::TextShowMnemonic; - if (!proxy()->styleHint(SH_UnderlineShortcut, btn, widget)) - tf |= Qt::TextHideMnemonic; - - if (!btn->icon.isNull()) { - //Center both icon and text - QIcon::Mode mode = isEnabled ? QIcon::Normal : QIcon::Disabled; - if (mode == QIcon::Normal && btn->state & State_HasFocus) - mode = QIcon::Active; - QIcon::State state = isChecked(btn) ? QIcon::On : QIcon::Off; - - int iconSpacing = 4;//### 4 is currently hardcoded in QPushButton::sizeHint() - - QRect iconRect = QRect(textRect.x(), textRect.y(), btn->iconSize.width(), textRect.height()); - QRect vIconRect = visualRect(btn->direction, btn->rect, iconRect); - textRect.setLeft(textRect.left() + iconRect.width() + iconSpacing); - - if (isChecked(btn) || isPressed(btn)) - vIconRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, option, widget), - proxy()->pixelMetric(PM_ButtonShiftVertical, option, widget)); - btn->icon.paint(painter, vIconRect, Qt::AlignCenter, mode, state); - } - - auto vTextRect = visualRect(btn->direction, btn->rect, textRect); - painter->setPen(controlTextColor(option)); - proxy()->drawItemText(painter, vTextRect, tf, option->palette, isEnabled, btn->text); + QStyleOptionButton btnCopy(*btn); + btnCopy.rect = btn->rect.marginsRemoved(QMargins(contentHMargin, 0, contentHMargin, 0)); + btnCopy.palette.setBrush(QPalette::ButtonText, controlTextColor(option)); + QCommonStyle::drawControl(element, &btnCopy, painter, widget); } break; case CE_PushButtonBevel: @@ -2625,7 +2602,7 @@ QIcon QWindows11Style::standardIcon(StandardPixmap standardIcon, switch (standardIcon) { case SP_LineEditClearButton: { if (d->m_lineEditClearButton.isNull()) { - auto e = new WinFontIconEngine(Clear.at(0), d->assetFont); + auto e = new WinFontIconEngine(Clear, d->assetFont); d->m_lineEditClearButton = QIcon(e); } return d->m_lineEditClearButton; |
