From 2e0b0be2ce30394269559590b42c81de27301ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 14 Aug 2019 12:39:27 +0200 Subject: Get rid of QWidgetBackingStoreTracker It was added for Symbian almost 10 years ago (d7057e7c1f1a), for a somewhat dubious use-case. The Symbian code is since long gone (ae30d7141), so the remaining pieces are just adding complexity to the already intricate workings of the QtWidgets backingstore/painting logic. Task-number: QTBUG-8697 Change-Id: I82af610a8ac26719c588ac63f06b4501f59b400d Reviewed-by: Paul Olav Tvete --- src/widgets/kernel/qwidget.cpp | 105 ++--------------------------- src/widgets/kernel/qwidget_p.h | 48 +------------ src/widgets/kernel/qwidgetbackingstore.cpp | 10 +-- src/widgets/kernel/qwidgetwindow.cpp | 2 +- 4 files changed, 13 insertions(+), 152 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index ba9b2a0487..066dfaa183 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -146,91 +146,6 @@ static inline bool qRectIntersects(const QRect &r1, const QRect &r2) extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp -/*! - \internal - \class QWidgetBackingStoreTracker - \brief Class which allows tracking of which widgets are using a given backing store - - QWidgetBackingStoreTracker is a thin wrapper around a QWidgetBackingStore pointer, - which maintains a list of the QWidgets which are currently using the backing - store. This list is modified via the registerWidget and unregisterWidget functions. - */ - -QWidgetBackingStoreTracker::QWidgetBackingStoreTracker() - : m_ptr(0) -{ - -} - -QWidgetBackingStoreTracker::~QWidgetBackingStoreTracker() -{ - delete m_ptr; -} - -/*! - \internal - Destroy the contained QWidgetBackingStore, if not null, and clear the list of - widgets using the backing store, then create a new QWidgetBackingStore, providing - the QWidget. - */ -void QWidgetBackingStoreTracker::create(QWidget *widget) -{ - destroy(); - m_ptr = new QWidgetBackingStore(widget); -} - -/*! - \internal - Destroy the contained QWidgetBackingStore, if not null, and clear the list of - widgets using the backing store. - */ -void QWidgetBackingStoreTracker::destroy() -{ - delete m_ptr; - m_ptr = 0; - m_widgets.clear(); -} - -/*! - \internal - Add the widget to the list of widgets currently using the backing store. - If the widget was already in the list, this function is a no-op. - */ -void QWidgetBackingStoreTracker::registerWidget(QWidget *w) -{ - Q_ASSERT(m_ptr); - Q_ASSERT(w->internalWinId()); - Q_ASSERT(qt_widget_private(w)->maybeBackingStore() == m_ptr); - m_widgets.insert(w); -} - -/*! - \internal - Remove the widget from the list of widgets currently using the backing store. - If the widget was in the list, and removing it causes the list to be empty, - the backing store is deleted. - If the widget was not in the list, this function is a no-op. - */ -void QWidgetBackingStoreTracker::unregisterWidget(QWidget *w) -{ - if (m_widgets.remove(w) && m_widgets.isEmpty()) { - delete m_ptr; - m_ptr = 0; - } -} - -/*! - \internal - Recursively remove widget and all of its descendents. - */ -void QWidgetBackingStoreTracker::unregisterWidgetSubtree(QWidget *widget) -{ - unregisterWidget(widget); - foreach (QObject *child, widget->children()) - if (QWidget *childWidget = qobject_cast(child)) - unregisterWidgetSubtree(childWidget); -} - QWidgetPrivate::QWidgetPrivate(int version) : QObjectPrivate(version) , extra(0) @@ -1364,10 +1279,8 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow) d->create(); // a real toplevel window needs a backing store - if (isWindow() && windowType() != Qt::Desktop) { - d->topData()->backingStoreTracker.destroy(); - d->topData()->backingStoreTracker.create(this); - } + if (isWindow() && windowType() != Qt::Desktop) + d->topData()->widgetBackingStore.reset(new QWidgetBackingStore(this)); d->setModal_sys(); @@ -1891,7 +1804,7 @@ void QWidgetPrivate::deleteTLSysExtra() //the qplatformbackingstore may hold a reference to the window, so the backingstore //needs to be deleted first. - extra->topextra->backingStoreTracker.destroy(); + extra->topextra->widgetBackingStore.reset(nullptr); deleteBackingStore(this); #ifndef QT_NO_OPENGL extra->topextra->widgetTextures.clear(); @@ -10755,16 +10668,8 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) if (newParent && isAncestorOf(focusWidget())) focusWidget()->clearFocus(); - QTLWExtra *oldTopExtra = window()->d_func()->maybeTopData(); - QWidgetBackingStoreTracker *oldBsTracker = oldTopExtra ? &oldTopExtra->backingStoreTracker : 0; - d->setParent_sys(parent, f); - QTLWExtra *topExtra = window()->d_func()->maybeTopData(); - QWidgetBackingStoreTracker *bsTracker = topExtra ? &topExtra->backingStoreTracker : 0; - if (oldBsTracker && oldBsTracker != bsTracker) - oldBsTracker->unregisterWidgetSubtree(this); - if (desktopWidget) parent = 0; @@ -11134,7 +11039,7 @@ void QWidgetPrivate::repaint(T r) QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) - tlwExtra->backingStoreTracker->markDirty(r, q, QWidgetBackingStore::UpdateNow); + tlwExtra->widgetBackingStore->markDirty(r, q, QWidgetBackingStore::UpdateNow); } /*! @@ -11209,7 +11114,7 @@ void QWidgetPrivate::update(T r) QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) - tlwExtra->backingStoreTracker->markDirty(clipped, q); + tlwExtra->widgetBackingStore->markDirty(clipped, q); } /*! diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 970f5c0378..b4a9d283db 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -116,56 +116,12 @@ protected: QRegion m_region; }; - - -class Q_AUTOTEST_EXPORT QWidgetBackingStoreTracker -{ - -public: - QWidgetBackingStoreTracker(); - ~QWidgetBackingStoreTracker(); - - void create(QWidget *tlw); - void destroy(); - - void registerWidget(QWidget *w); - void unregisterWidget(QWidget *w); - void unregisterWidgetSubtree(QWidget *w); - - inline QWidgetBackingStore* data() - { - return m_ptr; - } - - inline QWidgetBackingStore* operator->() - { - return m_ptr; - } - - inline QWidgetBackingStore& operator*() - { - return *m_ptr; - } - - inline operator bool() const - { - return (nullptr != m_ptr); - } - -private: - Q_DISABLE_COPY_MOVE(QWidgetBackingStoreTracker) - -private: - QWidgetBackingStore* m_ptr; - QSet m_widgets; -}; - struct QTLWExtra { // *************************** Cross-platform variables ***************************** // Regular pointers (keep them together to avoid gaps on 64 bits architectures). std::unique_ptr icon; // widget icon - QWidgetBackingStoreTracker backingStoreTracker; + std::unique_ptr widgetBackingStore; QBackingStore *backingStore; QPainter *sharedPainter; QWidgetWindow *window; @@ -1028,7 +984,7 @@ inline QWidgetBackingStore *QWidgetPrivate::maybeBackingStore() const { Q_Q(const QWidget); QTLWExtra *x = q->window()->d_func()->maybeTopData(); - return x ? x->backingStoreTracker.data() : nullptr; + return x ? x->widgetBackingStore.get() : nullptr; } QT_END_NAMESPACE diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 009ffb17a1..1b963010d1 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -300,7 +300,7 @@ void QWidgetBackingStore::unflushPaint(QWidget *widget, const QRegion &rgn) if (!tlwExtra) return; - qt_flush(widget, rgn, tlwExtra->backingStoreTracker->store, tlw, 0, tlw->d_func()->maybeBackingStore()); + qt_flush(widget, rgn, tlwExtra->widgetBackingStore->store, tlw, 0, tlw->d_func()->maybeBackingStore()); } #endif // QT_NO_PAINT_DEBUG @@ -800,7 +800,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) invalidateBackingStore((newRect & clipR).translated(-data.crect.topLeft())); } else { - QWidgetBackingStore *wbs = x->backingStoreTracker.data(); + QWidgetBackingStore *wbs = x->widgetBackingStore.get(); QRegion childExpose(newRect & clipR); QRegion overlappedExpose; @@ -864,7 +864,7 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) if (x->inTopLevelResize) return; - QWidgetBackingStore *wbs = x->backingStoreTracker.data(); + QWidgetBackingStore *wbs = x->widgetBackingStore.get(); if (!wbs) return; @@ -1528,10 +1528,10 @@ void QWidgetPrivate::invalidateBackingStore(const T &r) if (masked.isEmpty()) return; - tlwExtra->backingStoreTracker->markDirty(masked, q, + tlwExtra->widgetBackingStore->markDirty(masked, q, QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid); } else { - tlwExtra->backingStoreTracker->markDirty(clipped, q, + tlwExtra->widgetBackingStore->markDirty(clipped, q, QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid); } } diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 5537ff497a..a01a377956 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -770,7 +770,7 @@ void QWidgetWindow::repaintWindow() QTLWExtra *tlwExtra = m_widget->window()->d_func()->maybeTopData(); if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) - tlwExtra->backingStoreTracker->markDirty(m_widget->rect(), m_widget, + tlwExtra->widgetBackingStore->markDirty(m_widget->rect(), m_widget, QWidgetBackingStore::UpdateNow, QWidgetBackingStore::BufferInvalid); } -- cgit v1.2.3 From f556505f63a4255b681ba8a32e1f29ccb79725ce Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 24 May 2019 22:06:09 +0200 Subject: QWidget: replace manual memory management with unique_ptr [6/N]: extra Had to port a lot of caching temporaries, too. Decided to leave them as crefs to unique_ptr to catch any mischief users may be doing with the raw pointer instead (like deleting it). Also fixed a use of 0 as nullptr (by standardizing on pointer-to-bool conversion, as is done everywhere else in qwidget.cpp), and made one impregnable if condition readable. Change-Id: Ifdc240bf352c52de0bc3c186fa7a5f4cb2882dd0 Reviewed-by: Volker Hilsheimer --- src/widgets/graphicsview/qgraphicsproxywidget.cpp | 12 ++++----- src/widgets/kernel/qapplication.cpp | 4 +-- src/widgets/kernel/qshortcut.cpp | 2 +- src/widgets/kernel/qwidget.cpp | 30 +++++++++++------------ src/widgets/kernel/qwidget_p.h | 4 +-- 5 files changed, 25 insertions(+), 27 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/graphicsview/qgraphicsproxywidget.cpp b/src/widgets/graphicsview/qgraphicsproxywidget.cpp index 2b6712075f..7413a26261 100644 --- a/src/widgets/graphicsview/qgraphicsproxywidget.cpp +++ b/src/widgets/graphicsview/qgraphicsproxywidget.cpp @@ -404,7 +404,7 @@ void QGraphicsProxyWidgetPrivate::_q_removeWidgetSlot() { Q_Q(QGraphicsProxyWidget); if (!widget.isNull()) { - if (QWExtra *extra = widget->d_func()->extra) + if (const auto &extra = widget->d_func()->extra) extra->proxyWidget = 0; } widget = 0; @@ -477,8 +477,8 @@ void QGraphicsProxyWidgetPrivate::updateProxyInputMethodAcceptanceFromWidget() */ void QGraphicsProxyWidgetPrivate::embedSubWindow(QWidget *subWin) { - QWExtra *extra; - if (!((extra = subWin->d_func()->extra) && extra->proxyWidget)) { + const auto &extra = subWin->d_func()->extra; + if (!extra || !extra->proxyWidget) { QGraphicsProxyWidget *subProxy = new QGraphicsProxyWidget(q_func(), subWin->windowFlags()); subProxy->d_func()->setWidget_helper(subWin, false); } @@ -631,7 +631,7 @@ void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool auto if (!newWidget) return; if (!newWidget->isWindow()) { - QWExtra *extra = newWidget->parentWidget()->d_func()->extra; + const auto &extra = newWidget->parentWidget()->d_func()->extra; if (!extra || !extra->proxyWidget) { qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p " "which is not a toplevel widget, and is not a child of an embedded widget", newWidget); @@ -641,10 +641,10 @@ void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool auto // Register this proxy within the widget's private. // ### This is a bit backdoorish - QWExtra *extra = newWidget->d_func()->extra; + QWExtra *extra = newWidget->d_func()->extra.get(); if (!extra) { newWidget->d_func()->createExtra(); - extra = newWidget->d_func()->extra; + extra = newWidget->d_func()->extra.get(); } QGraphicsProxyWidget **proxyWidget = &extra->proxyWidget; if (*proxyWidget) { diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 94b14ecb4f..629c696544 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -3388,7 +3388,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) #if QT_CONFIG(graphicsview) // QGraphicsProxyWidget handles its own propagation, // and we must not change QDragManagers currentTarget. - QWExtra *extra = w->window()->d_func()->extra; + const auto &extra = w->window()->d_func()->extra; if (extra && extra->proxyWidget) { res = d->notify_helper(w, dragEvent); break; @@ -3416,7 +3416,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) #if QT_CONFIG(graphicsview) // QGraphicsProxyWidget handles its own propagation, // and we must not change QDragManagers currentTarget. - QWExtra *extra = w->window()->d_func()->extra; + const auto &extra = w->window()->d_func()->extra; bool isProxyWidget = extra && extra->proxyWidget; if (!isProxyWidget) #endif diff --git a/src/widgets/kernel/qshortcut.cpp b/src/widgets/kernel/qshortcut.cpp index a4ebcdfc84..39b08dbc1e 100644 --- a/src/widgets/kernel/qshortcut.cpp +++ b/src/widgets/kernel/qshortcut.cpp @@ -178,7 +178,7 @@ static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidge // Below is Qt::WindowShortcut context QWidget *tlw = w->window(); #if QT_CONFIG(graphicsview) - if (auto topData = static_cast(QObjectPrivate::get(tlw))->extra) { + if (auto topData = static_cast(QObjectPrivate::get(tlw))->extra.get()) { if (topData->proxyWidget) { bool res = correctGraphicsWidgetContext(context, topData->proxyWidget, active_window); return res; diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 066dfaa183..2edbe05e32 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -148,7 +148,6 @@ extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp QWidgetPrivate::QWidgetPrivate(int version) : QObjectPrivate(version) - , extra(0) , focus_next(0) , focus_prev(0) , focus_child(0) @@ -1553,7 +1552,7 @@ QWidget::~QWidget() while (w->d_func()->extra && w->d_func()->extra->focus_proxy) w = w->d_func()->extra->focus_proxy; QWidget *window = w->window(); - QWExtra *e = window ? window->d_func()->extra : 0; + QWExtra *e = window ? window->d_func()->extra.get() : nullptr ; if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this)) #endif clearFocus(); @@ -1732,7 +1731,7 @@ void QWidgetPrivate::createTLExtra() void QWidgetPrivate::createExtra() { if (!extra) { // if not exists - extra = new QWExtra; + extra = qt_make_unique(); extra->glContext = 0; #if QT_CONFIG(graphicsview) extra->proxyWidget = 0; @@ -1780,9 +1779,8 @@ void QWidgetPrivate::deleteExtra() deleteTLSysExtra(); // extra->topextra->backingStore destroyed in QWidgetPrivate::deleteTLSysExtra() } - delete extra; // extra->xic destroyed in QWidget::destroy() - extra = 0; + extra.reset(); } } @@ -1853,7 +1851,7 @@ QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst const QRect siblingRect = sibling->d_func()->effectiveRectFor(sibling->data->crect); if (qRectIntersects(siblingRect, r)) { - const QWExtra *siblingExtra = sibling->d_func()->extra; + const auto &siblingExtra = sibling->d_func()->extra; if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) { continue; @@ -3858,7 +3856,7 @@ QSize QWidget::sizeIncrement() const QSize QWidget::baseSize() const { Q_D(const QWidget); - return (d->extra != 0 && d->extra->topextra != 0) + return (d->extra && d->extra->topextra) ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh) : QSize(0, 0); } @@ -5858,7 +5856,7 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint * QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin) { if (origin) { - QWExtra *extra = origin->d_func()->extra; + const auto &extra = origin->d_func()->extra; if (extra && extra->proxyWidget) return extra->proxyWidget; return nearestGraphicsProxyWidget(origin->parentWidget()); @@ -6404,7 +6402,7 @@ bool QWidget::hasFocus() const w = w->d_func()->extra->focus_proxy; #if QT_CONFIG(graphicsview) if (QWidget *window = w->window()) { - QWExtra *e = window->d_func()->extra; + const auto &e = window->d_func()->extra; if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w) return true; } @@ -6465,7 +6463,7 @@ void QWidget::setFocus(Qt::FocusReason reason) #if QT_CONFIG(graphicsview) QWidget *previousProxyFocus = 0; - if (QWExtra *topData = window()->d_func()->extra) { + if (const auto &topData = window()->d_func()->extra) { if (topData->proxyWidget && topData->proxyWidget->hasFocus()) { previousProxyFocus = topData->proxyWidget->widget()->focusWidget(); if (previousProxyFocus && previousProxyFocus->focusProxy()) @@ -6478,7 +6476,7 @@ void QWidget::setFocus(Qt::FocusReason reason) #if QT_CONFIG(graphicsview) // Update proxy state - if (QWExtra *topData = window()->d_func()->extra) { + if (const auto &topData = window()->d_func()->extra) { if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) { f->d_func()->updateFocusChild(); topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1; @@ -6519,7 +6517,7 @@ void QWidget::setFocus(Qt::FocusReason reason) } #endif #if QT_CONFIG(graphicsview) - if (QWExtra *topData = window()->d_func()->extra) { + if (const auto &topData = window()->d_func()->extra) { if (topData->proxyWidget) { if (previousProxyFocus && previousProxyFocus != f) { // Send event to self @@ -6532,7 +6530,7 @@ void QWidget::setFocus(Qt::FocusReason reason) if (!isHidden()) { #if QT_CONFIG(graphicsview) // Update proxy state - if (QWExtra *topData = window()->d_func()->extra) + if (const auto &topData = window()->d_func()->extra) if (topData->proxyWidget && topData->proxyWidget->hasFocus()) topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget(); #endif @@ -6669,7 +6667,7 @@ void QWidget::clearFocus() } #if QT_CONFIG(graphicsview) - QWExtra *topData = d_func()->extra; + const auto &topData = d_func()->extra; if (topData && topData->proxyWidget) topData->proxyWidget->clearFocus(); #endif @@ -6835,7 +6833,7 @@ bool QWidget::isActiveWindow() const return true; #if QT_CONFIG(graphicsview) - if (QWExtra *tlwExtra = tlw->d_func()->extra) { + if (const auto &tlwExtra = tlw->d_func()->extra) { if (isVisible() && tlwExtra->proxyWidget) return tlwExtra->proxyWidget->isActiveWindow(); } @@ -10325,7 +10323,7 @@ void QWidget::setSizePolicy(QSizePolicy policy) d->size_policy = policy; #if QT_CONFIG(graphicsview) - if (QWExtra *extra = d->extra) { + if (const auto &extra = d->extra) { if (extra->proxyWidget) extra->proxyWidget->setSizePolicy(policy); } diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index b4a9d283db..687e8bef09 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -669,7 +669,7 @@ public: // Variables. // Regular pointers (keep them together to avoid gaps on 64 bit architectures). - QWExtra *extra; + std::unique_ptr extra; QWidget *focus_next; QWidget *focus_prev; QWidget *focus_child; @@ -945,7 +945,7 @@ public: inline QWExtra *QWidgetPrivate::extraData() const { - return extra; + return extra.get(); } inline QTLWExtra *QWidgetPrivate::topData() const -- cgit v1.2.3 From d46415c0af5c84b5924694a090a0cd70fdb18158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 12 Aug 2019 23:32:44 +0200 Subject: wasm: Add saveFileContent() Saves a file by file download, where the user can choose the file name and location using a file dialog. Change-Id: I4d2ecc76fc33bb65fdf3d7ca3fcd9566c62547dd Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/widgets/dialogs/qfiledialog.cpp | 45 ++++++++++++++++++++++ src/widgets/dialogs/qfiledialog.h | 1 + .../snippets/code/src_gui_dialogs_qfiledialog.cpp | 5 +++ 3 files changed, 51 insertions(+) (limited to 'src/widgets') diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index a89192e76f..a1b9003c1c 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -2447,6 +2447,51 @@ void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::funct #endif } +/*! + This is a convenience static function that saves \a fileContent to a file, using + a file name and location chosen by the user. \a fileNameHint can be provided to + suggest a file name to the user. + + This function is used to save files to the local file system on Qt for WebAssembly, where + the web sandbox places restrictions on how such access may happen. Its implementation will + make the browser display a native file dialog, where the user makes the file selection. + + It can also be used on other platforms, where it will fall back to using QFileDialog. + + The function is asynchronous and returns immediately. + + \snippet code/src_gui_dialogs_qfiledialog.cpp 16 + \since 5.14 +*/ +void QFileDialog::saveFileContent(const QByteArray &fileContent, const QString &fileNameHint) +{ +#ifdef Q_OS_WASM + QWasmLocalFileAccess::saveFile(fileContent.constData(), fileContent.size(), fileNameHint.toStdString()); +#else + QFileDialog *dialog = new QFileDialog(); + dialog->setAcceptMode(QFileDialog::AcceptSave); + dialog->setFileMode(QFileDialog::AnyFile); + dialog->selectFile(fileNameHint); + + auto fileSelected = [=](const QString &fileName) { + if (!fileName.isNull()) { + QFile selectedFile(fileName); + if (selectedFile.open(QIODevice::WriteOnly)) + selectedFile.write(fileContent); + } + }; + + auto dialogClosed = [=](int code) { + Q_UNUSED(code); + delete dialog; + }; + + connect(dialog, &QFileDialog::fileSelected, fileSelected); + connect(dialog, &QFileDialog::finished, dialogClosed); + dialog->show(); +#endif +} + /*! This is a convenience static function that will return a file name selected by the user. The file does not have to exist. diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h index 354a1f928b..790f52f2e7 100644 --- a/src/widgets/dialogs/qfiledialog.h +++ b/src/widgets/dialogs/qfiledialog.h @@ -284,6 +284,7 @@ public: static void getOpenFileContent(const QString &nameFilter, const std::function &fileContentsReady); + static void saveFileContent(const QByteArray &fileContent, const QString &fileNameHint = QString()); protected: QFileDialog(const QFileDialogArgs &args); diff --git a/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp b/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp index 39aca459db..7ccd827a04 100644 --- a/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp +++ b/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp @@ -155,3 +155,8 @@ auto fileOpenCompleted = [](const QString &fileName, const QByteArray &fileConte } QFileDialog::getOpenFileContent("Images (*.png *.xpm *.jpg)", fileContentReady); //! [15] + +//! [16] +QByteArray imageData; // obtained from e.g. QImage::save() +QFileDialog::saveFile("myimage.png", imageData); +//! [16] -- cgit v1.2.3 From 5b2dfbc649a7c20a93223cd4c274a4b0fe847df8 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 24 May 2019 21:20:37 +0200 Subject: Long live QSize(F)::grownBy/shrunkBy() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These functions tighten the integration of QMargins(F) with the rest of the geometry classes by providing a way to apply margins to sizes (and later, rects). Apply them in a few obvious cases across QtWidgets. [ChangeLog][QtCore][QSize/QSizeF] Added grownBy(QMargin(F))/shrunkBy(QMargin(F)). Change-Id: I8a549436824cdb7fb6125a8cde89d5bf02826934 Reviewed-by: MÃ¥rten Nordheim Reviewed-by: Shawn Rutledge Reviewed-by: Edward Welbourne --- src/widgets/widgets/qdockarealayout.cpp | 21 ++++++--------------- src/widgets/widgets/qdockwidget.cpp | 7 +++---- 2 files changed, 9 insertions(+), 19 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp index 55ae42db04..8844a85987 100644 --- a/src/widgets/widgets/qdockarealayout.cpp +++ b/src/widgets/widgets/qdockarealayout.cpp @@ -138,11 +138,8 @@ bool QDockAreaLayoutItem::skip() const QSize QDockAreaLayoutItem::minimumSize() const { - if (widgetItem != 0) { - int left, top, right, bottom; - widgetItem->widget()->getContentsMargins(&left, &top, &right, &bottom); - return widgetItem->minimumSize() + QSize(left+right, top+bottom); - } + if (widgetItem) + return widgetItem->minimumSize().grownBy(widgetItem->widget()->contentsMargins()); if (subinfo != 0) return subinfo->minimumSize(); return QSize(0, 0); @@ -150,11 +147,8 @@ QSize QDockAreaLayoutItem::minimumSize() const QSize QDockAreaLayoutItem::maximumSize() const { - if (widgetItem != 0) { - int left, top, right, bottom; - widgetItem->widget()->getContentsMargins(&left, &top, &right, &bottom); - return widgetItem->maximumSize()+ QSize(left+right, top+bottom); - } + if (widgetItem) + return widgetItem->maximumSize().grownBy(widgetItem->widget()->contentsMargins()); if (subinfo != 0) return subinfo->maximumSize(); return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); @@ -180,11 +174,8 @@ QSize QDockAreaLayoutItem::sizeHint() const { if (placeHolderItem != 0) return QSize(0, 0); - if (widgetItem != 0) { - int left, top, right, bottom; - widgetItem->widget()->getContentsMargins(&left, &top, &right, &bottom); - return widgetItem->sizeHint() + QSize(left+right, top+bottom); - } + if (widgetItem) + return widgetItem->sizeHint().grownBy(widgetItem->widget()->contentsMargins()); if (subinfo != 0) return subinfo->sizeHint(); return QSize(-1, -1); diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index 28a7cee2a0..a7010f9260 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -381,11 +381,10 @@ QSize QDockWidgetLayout::sizeFromContent(const QSize &content, bool floating) co if (content.height() < 0) result.setHeight(-1); - int left, top, right, bottom; - w->getContentsMargins(&left, &top, &right, &bottom); + const QMargins margins = w->contentsMargins(); //we need to subtract the contents margin (it will be added by the caller) - QSize min = w->minimumSize() - QSize(left + right, top + bottom); - QSize max = w->maximumSize() - QSize(left + right, top + bottom); + QSize min = w->minimumSize().shrunkBy(margins); + QSize max = w->maximumSize().shrunkBy(margins); /* A floating dockwidget will automatically get its minimumSize set to the layout's minimum size + deco. We're *not* interested in this, we only take minimumSize() -- cgit v1.2.3