From 91396846206e6b41d32fa8a30888261581bd28dc Mon Sep 17 00:00:00 2001 From: Geir Vattekar Date: Fri, 8 Oct 2010 09:13:48 +0200 Subject: Doc: Update to Phonon overview --- doc/src/frameworks-technologies/phonon.qdoc | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/doc/src/frameworks-technologies/phonon.qdoc b/doc/src/frameworks-technologies/phonon.qdoc index 83afb91..9620136 100644 --- a/doc/src/frameworks-technologies/phonon.qdoc +++ b/doc/src/frameworks-technologies/phonon.qdoc @@ -524,24 +524,5 @@ the QtOpenGL shared library. If this is not what you want, it is possible to configure Qt without OpenGL support. In that case, you need to run \c configure with the \c -no-opengl option. - - \section1 Work in Progress - - Phonon and its Qt backends, though fully functional for - multimedia playback, are still under development. Functionality to - come is the possibility to capture media and more processors for - both music and video files. - - Another important consideration is to implement support for - storing media to files; i.e., not playing back media directly. - - We also hope in the future to be able to support direct - manipulation of media streams. This will give the programmer more - freedom to manipulate streams than just through processors. - - Currently, the multimedia framework supports one input source. It will be - possible to include several sources. This is useful in, for example, audio - mixer applications where several audio sources can be sent, processed and - output as a single audio stream. */ -- cgit v0.12 From a5dc543041511c73b87fbda685c041febc81b7d9 Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Fri, 8 Oct 2010 10:57:04 +0200 Subject: Fixed grammar mistake. Task-number: QTBUG-13712 --- src/corelib/tools/qsharedpointer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 5fac960..0310baa 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -395,7 +395,7 @@ \section1 Tracking QObject - QWeakPointer can be used to track deletion classes derives from QObject, + QWeakPointer can be used to track deletion classes that derive from QObject, even if they are not managed by QSharedPointer. When used in that role, QWeakPointer replaces the older QPointer in all use-cases. QWeakPointer is also more efficient than QPointer, so it should be preferred in all @@ -1163,7 +1163,7 @@ \since 4.6 \brief The qSharedPointerObjectCast function is for casting a shared pointer. - + Returns a shared pointer to the pointer held by \a other, using a \l qobject_cast() to type \tt X to obtain an internal pointer of the appropriate type. If the \tt qobject_cast fails, the object @@ -1432,7 +1432,7 @@ void QtSharedPointer::internalSafetyCheckAdd2(const void *d_ptr, const volatile Q_ASSERT(!kp->dPointers.contains(d_ptr)); //qDebug("Adding d=%p value=%p", d_ptr, ptr); - + const void *other_d_ptr = kp->dataPointers.value(ptr, 0); if (other_d_ptr) { # ifdef BACKTRACE_SUPPORTED -- cgit v0.12 From 18e4aaebb8cd1764eba1fce64bb202b63d2a74b8 Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Fri, 8 Oct 2010 12:16:51 +0200 Subject: Resized image, added missing files, and reformatted documentation of QtWebKit Image Analyzer example. --- doc/src/examples/webkit-bridge-imageanalyzer.qdoc | 24 ++-- doc/src/images/webkit-imageanalyzer-screenshot.png | Bin 190353 -> 56053 bytes examples/webkit/imageanalyzer/imageanalyzer.cpp | 8 +- examples/webkit/imageanalyzer/imageanalyzer.h | 73 +++++------ examples/webkit/imageanalyzer/mainwindow.h | 21 ++-- .../imageanalyzer/resources/imageanalyzer.qrc | 10 ++ examples/webkit/imageanalyzer/resources/index.html | 133 +++++++++++++++++++++ 7 files changed, 212 insertions(+), 57 deletions(-) create mode 100644 examples/webkit/imageanalyzer/resources/imageanalyzer.qrc create mode 100644 examples/webkit/imageanalyzer/resources/index.html diff --git a/doc/src/examples/webkit-bridge-imageanalyzer.qdoc b/doc/src/examples/webkit-bridge-imageanalyzer.qdoc index efc5623..b8c42c6 100644 --- a/doc/src/examples/webkit-bridge-imageanalyzer.qdoc +++ b/doc/src/examples/webkit-bridge-imageanalyzer.qdoc @@ -37,6 +37,9 @@ user interface, displaying web content written in HTML/JavaScript. The application uses QtConcurrent to distribute its work across as many CPU cores as are available from the system, so it can process each image in parallel. +For the full reference documentation of QtWebKit hybrid development, see +\l{qtwebkit-bridge.html}{The QtWebKit Bridge}. + Initially, you will see a user interface with an empty list of images. Clicking on some of the images in the lower pane below adds them to the list view above, as shown in the screenshot below. @@ -54,8 +57,8 @@ each image are shown. \image webkit-imageanalyzer-complete.png -The MainWindow is defined in C++, and creates a \c QNetworkCache and a -\c QWebView, and tells the \c QWebView to load the starting page, providing us +The MainWindow is defined in C++, and creates a \l QNetworkDiskCache and a +\l QWebView, and tells the \l QWebView to load the starting page, providing us with a user interface for the client. \snippet examples/webkit/imageanalyzer/mainwindow.cpp MainWindow - constructor @@ -67,8 +70,8 @@ likely be retrieved from the network rather than from resources. We wish to initialize an object reference in the JavaScript web page to point to our \tt ImageAnalyzer before any other scripts are run. To do this, we -connect the \c javaScriptWindowObjectCleared() signal to a slot which does the -object creation and handoff to JavaScript. +connect the \l{QWebFrame::}{javaScriptWindowObjectCleared()} signal to a slot +which does the object creation and handoff to JavaScript. \snippet examples/webkit/imageanalyzer/mainwindow.cpp MainWindow - addJSObject @@ -94,14 +97,15 @@ When the user clicks the \bold {Analyze} button, \c analyzeImages() is called, another regular JavaScript method, shown below. Notice it assumes the \c imageAnalyzer object is already defined and initialized in JavaScript space, but we guaranteed that by connecting our setup slot to the -appropriate signal, \c javaScriptWindowObjectCleared(). +appropriate signal, \l{QWebFrame::}{javaScriptWindowObjectCleared()}. \snippet examples/webkit/imageanalyzer/resources/index.html analyzeImages The only methods on \c ImageAnalyzer that we can or do call from JavaScript are -those which are exposed through Qt's MetaObject system: property getter/setter -methods, -\c public \c slots, \c signals, and other \c Q_INVOKABLE functions. +those which are exposed through \{The Meta-Object System}{Qt's MetaObject} +system: \l{The Property System}{property} getter/setter methods, +\c public \l {Signals & Slots}{signals and slots}, and other +\l{Q_INVOKABLE}{Q_INVOKABLE} functions. \snippet examples/webkit/imageanalyzer/imageanalyzer.h ImageAnalyzer - public interface \dots @@ -138,13 +142,13 @@ will load them into a QImage when the data is ready. \snippet examples/webkit/imageanalyzer/imageanalyzer.cpp ImageAnalyzer - handleReply After the images are loaded, they are queued up in preparation to be -sent in a batch for analysis to a \c QFutureWatcher, which will distribute the +sent in a batch for analysis to a \l QFutureWatcher, which will distribute the processing across multiple threads and cores, depending on how many are available. \snippet examples/webkit/imageanalyzer/imageanalyzer.cpp ImageAnalyzer - queueImage The function that gets performed on each image is \c averageRGB(), -as specified in argument 2 to the \c QtConcurrent::mapped() function. +as specified in argument 2 to the \l{QtConcurrent::mapped()} function. Notice it repeats the same calculations 100 times on each pixel to keep the CPU very busy. This is done only for the purposes of the demo so that the analysis takes a noticeable time to complete. diff --git a/doc/src/images/webkit-imageanalyzer-screenshot.png b/doc/src/images/webkit-imageanalyzer-screenshot.png index 987f8a2..c96371a 100644 Binary files a/doc/src/images/webkit-imageanalyzer-screenshot.png and b/doc/src/images/webkit-imageanalyzer-screenshot.png differ diff --git a/examples/webkit/imageanalyzer/imageanalyzer.cpp b/examples/webkit/imageanalyzer/imageanalyzer.cpp index c663cf3..1d0ee45 100644 --- a/examples/webkit/imageanalyzer/imageanalyzer.cpp +++ b/examples/webkit/imageanalyzer/imageanalyzer.cpp @@ -57,7 +57,7 @@ //! [ ImageAnalyzer - Constructor ] ImageAnalyzer::ImageAnalyzer(QNetworkDiskCache* netcache, QObject* parent) -: QObject(parent), m_cache(netcache), m_outstandingFetches(0) + : QObject(parent), m_cache(netcache), m_outstandingFetches(0) { /* ImageAnalyzer only wants to receive http responses for requests that it makes, so that's why it has its own @@ -69,11 +69,11 @@ ImageAnalyzer::ImageAnalyzer(QNetworkDiskCache* netcache, QObject* parent) m_network->setCache(m_cache); QObject::connect(m_network, SIGNAL(finished(QNetworkReply*)), - this, SLOT(handleReply(QNetworkReply*))); + this, SLOT(handleReply(QNetworkReply*))); QObject::connect(m_watcher, SIGNAL(finished()), - this, SLOT(doneProcessing())); + this, SLOT(doneProcessing())); QObject::connect(m_watcher, SIGNAL(progressValueChanged(int)), - this, SLOT(progressStatus(int))); + this, SLOT(progressStatus(int))); } //! [ ImageAnalyzer - Constructor ] ImageAnalyzer::~ImageAnalyzer() diff --git a/examples/webkit/imageanalyzer/imageanalyzer.h b/examples/webkit/imageanalyzer/imageanalyzer.h index f228c0e..1bb25dc 100644 --- a/examples/webkit/imageanalyzer/imageanalyzer.h +++ b/examples/webkit/imageanalyzer/imageanalyzer.h @@ -47,48 +47,53 @@ class QNetworkAccessManager; class QNetworkReply; class QNetworkDiskCache; + //! [ ImageAnalyzer - public interface ] class ImageAnalyzer : public QObject { Q_OBJECT - public: - ImageAnalyzer(QNetworkDiskCache * netcache, QObject * parent=0); +public: + ImageAnalyzer(QNetworkDiskCache * netcache, QObject * parent=0); + + QRgb lastResults(); + float lastRed(); + float lastGreen(); + float lastBlue(); + bool isBusy(); + Q_PROPERTY(bool busy READ isBusy); + Q_PROPERTY(float red READ lastRed); + Q_PROPERTY(float green READ lastGreen); + Q_PROPERTY(float blue READ lastBlue); + ~ImageAnalyzer(); + +public slots: + /*! initiates analysis of all the urls in the list */ + void startAnalysis(const QStringList & urls); + +signals: + void finishedAnalysis(); + void updateProgress(int completed, int total); + //! [ ImageAnalyzer - public interface ] + +private slots: + void handleReply(QNetworkReply*); + void doneProcessing(); + void progressStatus(int); - QRgb lastResults(); - float lastRed(); - float lastGreen(); - float lastBlue(); - bool isBusy(); - Q_PROPERTY(bool busy READ isBusy); - Q_PROPERTY(float red READ lastRed); - Q_PROPERTY(float green READ lastGreen); - Q_PROPERTY(float blue READ lastBlue); - ~ImageAnalyzer(); - public slots: - /*! initiates analysis of all the urls in the list */ - void startAnalysis(const QStringList & urls); - signals: - void finishedAnalysis(); - void updateProgress(int completed, int total); -//! [ ImageAnalyzer - public interface ] - private slots: - void handleReply(QNetworkReply*); - void doneProcessing(); - void progressStatus(int); private: - QRgb processImages(); - void fetchURLs(); - void queueImage(QImage img); + QRgb processImages(); + void fetchURLs(); + void queueImage(QImage img); -//! [ ImageAnalyzer - private members ] + //! [ ImageAnalyzer - private members ] private: - QNetworkAccessManager* m_network; - QNetworkDiskCache* m_cache; - QStringList m_URLQueue; - QList m_imageQueue; - int m_outstandingFetches; - QFutureWatcher * m_watcher; -//! [ ImageAnalyzer - private members ] + QNetworkAccessManager* m_network; + QNetworkDiskCache* m_cache; + QStringList m_URLQueue; + QList m_imageQueue; + int m_outstandingFetches; + QFutureWatcher * m_watcher; + //! [ ImageAnalyzer - private members ] }; QRgb averageRGB(const QImage &img); diff --git a/examples/webkit/imageanalyzer/mainwindow.h b/examples/webkit/imageanalyzer/mainwindow.h index 4c6b950..076e586 100644 --- a/examples/webkit/imageanalyzer/mainwindow.h +++ b/examples/webkit/imageanalyzer/mainwindow.h @@ -41,8 +41,8 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H -#include +#include class ImageAnalyzer; class QNetworkDiskCache; @@ -50,14 +50,17 @@ class QNetworkDiskCache; class MainWin : public QWebView { Q_OBJECT + +public: + explicit MainWin(QWidget * parent = 0); + +private: + ImageAnalyzer * m_analyzer; + QNetworkAccessManager * m_network; + QNetworkDiskCache * m_cache; + +private slots: + void addJSObject(); - public: - explicit MainWin(QWidget * parent = 0); - private: - ImageAnalyzer * m_analyzer; - QNetworkAccessManager * m_network; - QNetworkDiskCache * m_cache; - private slots: - void addJSObject(); }; #endif diff --git a/examples/webkit/imageanalyzer/resources/imageanalyzer.qrc b/examples/webkit/imageanalyzer/resources/imageanalyzer.qrc new file mode 100644 index 0000000..fe9a5df --- /dev/null +++ b/examples/webkit/imageanalyzer/resources/imageanalyzer.qrc @@ -0,0 +1,10 @@ + + + index.html + images/mtRainier.jpg + images/bellaCoola.jpg + images/trees.jpg + images/flower.jpg + images/seaShell.jpg + + diff --git a/examples/webkit/imageanalyzer/resources/index.html b/examples/webkit/imageanalyzer/resources/index.html new file mode 100644 index 0000000..6532951 --- /dev/null +++ b/examples/webkit/imageanalyzer/resources/index.html @@ -0,0 +1,133 @@ + + + + +
+
+
Images to be analyzed:
+ +
+ +
+
+ +
+
+

Image Analyzer

+
+
+

Status: Idle

+
+ Latest Results:
+ Red: n/a
+ Green: n/a
+ Blue: n/a
+
+

Click on images below to select for analysis

+
+
+ +
+
+ + + + + + +
+ + + + + + + -- cgit v0.12 From b546a7c8c57fdfe18b3293c8fef8c4a58ad77f59 Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Fri, 8 Oct 2010 14:53:02 +0200 Subject: Made several QMenuBar functions visible to qdoc and added documentation. Task-number: QTBUG-14026 Reviewed-by: David Boddie --- src/gui/widgets/qmenubar.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index df16f7f..ae56fa5 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -1628,10 +1628,10 @@ bool QMenuBar::eventFilter(QObject *object, QEvent *event) } /*! - \internal + Returns the QAction at \a pt. Returns 0 if there is no action at \a pt or if +the location has a separator. - Return the item at \a pt, or 0 if there is no item there or if it is - a separator item. + \sa addAction(), addSeparator() */ QAction *QMenuBar::actionAt(const QPoint &pt) const { @@ -1640,9 +1640,9 @@ QAction *QMenuBar::actionAt(const QPoint &pt) const } /*! - \internal + Returns the geometry of action \a act as a QRect. - Returns the geometry of action \a act. + \sa actionAt() */ QRect QMenuBar::actionGeometry(QAction *act) const { @@ -1836,10 +1836,17 @@ void QMenuBarPrivate::_q_updateLayout() } /*! - \internal + \fn void QMenuBar::setCornerWidget(QWidget *widget, Qt::Corner corner) - This sets widget \a w to be shown directly on the left of the first or - the right of the last menu item, depending on \a corner. + This sets the given \a widget to be shown directly on the left of the first + menu item, or on the right of the last menu item, depending on \a corner. + + The menu bar takes ownership of \a widget, reparenting it into the menu bar. + However, if the \a corner already contains a widget, this previous widget + will no longer be managed and will still be a visible child of the menu bar. + + \note Using a corner other than Qt::TopRightCorner or Qt::TopLeftCorner + will result in a warning. */ void QMenuBar::setCornerWidget(QWidget *w, Qt::Corner corner) { @@ -1869,10 +1876,11 @@ void QMenuBar::setCornerWidget(QWidget *w, Qt::Corner corner) } /*! - \internal + Returns the widget on the left of the first or on the right of the last menu + item, depending on \a corner. - Returns the widget in the left of the first or the right of the last menu - item, depending on \a corner. + \note Using a corner other than Qt::TopRightCorner or Qt::TopLeftCorner + will result in a warning. */ QWidget *QMenuBar::cornerWidget(Qt::Corner corner) const { -- cgit v0.12 From d11a15081c6385bb32ce78c8501fc259f56b2be2 Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Fri, 8 Oct 2010 16:37:34 +0200 Subject: Added Q_INVOKABLE to ignore file. Task-number: QTBUG-14281 Reviewed-by: David Boddie --- tools/qdoc3/test/qt-cpp-ignore.qdocconf | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/qdoc3/test/qt-cpp-ignore.qdocconf b/tools/qdoc3/test/qt-cpp-ignore.qdocconf index b78b512..5d52a47 100644 --- a/tools/qdoc3/test/qt-cpp-ignore.qdocconf +++ b/tools/qdoc3/test/qt-cpp-ignore.qdocconf @@ -71,8 +71,9 @@ Cpp.ignoretokens = QAXFACTORY_EXPORT \ QT_END_INCLUDE_NAMESPACE \ PHONON_EXPORT \ Q_DECLARATIVE_EXPORT \ - Q_GADGET \ - QWEBKIT_EXPORT + Q_GADGET \ + QWEBKIT_EXPORT \ + Q_INVOKABLE Cpp.ignoredirectives = Q_DECLARE_HANDLE \ Q_DECLARE_INTERFACE \ Q_DECLARE_METATYPE \ -- cgit v0.12 From 062b8cfa9b1ece569fe2a8ae18230c862ca6f857 Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Mon, 11 Oct 2010 15:14:56 +0200 Subject: Moved the property documentation to its proper location. Task-number: QTBUG-14351 Reviewed-by: David Boddie --- src/gui/graphicsview/qgraphicswidget.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 1bfe266..4a733be 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -750,6 +750,22 @@ QSizeF QGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c /*! \property QGraphicsWidget::layout \brief The layout of the widget + + Any existing layout manager is deleted before the new layout is assigned. If + \a layout is 0, the widget is left without a layout. Existing subwidgets' + geometries will remain unaffected. + + QGraphicsWidget takes ownership of \a layout. + + All widgets that are currently managed by \a layout or all of its + sublayouts, are automatically reparented to this item. The layout is then + invalidated, and the child widget geometries are adjusted according to + this item's geometry() and contentsMargins(). Children who are not + explicitly managed by \a layout remain unaffected by the layout after + it has been assigned to this widget. + + If no layout is currently managing this widget, layout() will return 0. + */ /*! -- cgit v0.12 From 0644896a666b1215dad9c04d73dd44f03554060d Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Mon, 11 Oct 2010 16:00:22 +0200 Subject: Added the default format of QTime::toString(). Task-number: QTBUG-13710 Reviewed-by: David Boddie --- src/corelib/tools/qdatetime.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index ab7530d..c252e64 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -1630,6 +1630,7 @@ QString QTime::toString(Qt::DateFormat format) const \endtable If the datetime is invalid, an empty string will be returned. + If \a format is empty, the default format "hh:mm:ss" is used. \sa QDate::toString() QDateTime::toString() */ -- cgit v0.12 From 087414e3ee4dd4c9f8f13c5a9eb69c5f70fb3d59 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 12 Oct 2010 17:19:46 +0200 Subject: Doc - remove disclaimer Task-number: QTBUG-14407 Reviewed-by: Friedemann Kleint Reviewed-by: Henry Haverinen --- doc/src/porting/qt4-designer.qdoc | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/doc/src/porting/qt4-designer.qdoc b/doc/src/porting/qt4-designer.qdoc index fff3e89..ea5147a 100644 --- a/doc/src/porting/qt4-designer.qdoc +++ b/doc/src/porting/qt4-designer.qdoc @@ -36,18 +36,14 @@ \QD has been completely re-written based on our experience with the previous versions of the product for Qt 3. One of the main new - ideas behind this new version is to release the application as a + ideas is to release the application as a collection of interchangeable components that include the property editor, the widget box, and other useful tools for creating graphical user interfaces with Qt. These components can either be used together in the \QD application, or independently integrated into other systems. As a result, certain features such as the project editor and code editor have been removed from the version - included with this release. - - The current version of \QD is near feature complete and can be used for - many tasks. However, it is still under continuous development. This - document will explain what is already in place. + included with release 4. See also the \l{Qt Designer Manual}. @@ -128,7 +124,7 @@ \row \i \bold{Widget Editing Mode} - The new \QD allows widgets to be dropped into existing layouts on + \QD now allows widgets to be dropped into existing layouts on the form. Previously, it was necessary to break layouts in order to add new widgets to them. @@ -189,7 +185,7 @@ \row \i \bold{The Resource Editor} - The new \QD fully supports The Qt Resource System, and provide the + \QD now fully supports The Qt Resource System, and provides the Resource Editor to help designers and developers manage the resources that are needed by their applications. @@ -210,8 +206,8 @@ \i \inlineimage designer-action-editor.png \i \bold{The Action Editor} - With the release of Qt 4.1, \QD introduces the Action Editor - simplifying the management of actions when creating main window + With the release of Qt 4.1, \QD the Action Editor was introduced + to simplify the management of actions when creating main window applications. When creating a main window, you can add a menu bar and toolbars @@ -261,7 +257,7 @@ \section1 Run-Time Support for Forms - With the Qt 4.1 release, the new QtUiTools module is introduced to + With the Qt 4.1 release, the new QtUiTools module was introduced to provide classes handling forms created with \QD. Currently the module only contains the QUiLoader class. -- cgit v0.12 From 1eb194d0b29e1bb3c5bafe711cea2c116cb2ea16 Mon Sep 17 00:00:00 2001 From: Morten Engvoldsen Date: Wed, 13 Oct 2010 09:48:18 +0200 Subject: Doc: adjusting the search field width --- doc/src/template/style/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/template/style/style.css b/doc/src/template/style/style.css index ec0202a..12d297d 100755 --- a/doc/src/template/style/style.css +++ b/doc/src/template/style/style.css @@ -650,7 +650,7 @@ margin-top: 5px; _margin: 0 0 0 -20px; padding: 10px; - width: 220px; + width: 30%; _width: 196px; height: 250px; overflow: auto; -- cgit v0.12 From 40b5c05b9921b5fa3ceae7f723c0b26c4861bda7 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 12 Oct 2010 16:38:30 +0200 Subject: tst_qcompleter: Add a test for QFileSystemModel Copied from the test for QDirModel Reviewed-by: Thierry --- tests/auto/qcompleter/tst_qcompleter.cpp | 82 +++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 6 deletions(-) diff --git a/tests/auto/qcompleter/tst_qcompleter.cpp b/tests/auto/qcompleter/tst_qcompleter.cpp index 1590528..3e05fbc 100644 --- a/tests/auto/qcompleter/tst_qcompleter.cpp +++ b/tests/auto/qcompleter/tst_qcompleter.cpp @@ -119,6 +119,8 @@ private slots: void directoryModel_data(); void directoryModel(); + void fileSystemModel_data(); + void fileSystemModel(); void changingModel_data(); void changingModel(); @@ -151,13 +153,14 @@ private slots: void task247560_keyboardNavigation(); private: - void filter(); + void filter(bool assync = false); void testRowCount(); enum ModelType { CASE_SENSITIVELY_SORTED_MODEL, CASE_INSENSITIVELY_SORTED_MODEL, DIRECTORY_MODEL, - HISTORY_MODEL + HISTORY_MODEL, + FILESYSTEM_MODEL }; void setSourceModel(ModelType); @@ -233,12 +236,21 @@ void tst_QCompleter::setSourceModel(ModelType type) completer->setModel(new QDirModel(completer)); completer->setCompletionColumn(0); break; + case FILESYSTEM_MODEL: + completer->setCsvCompletion(false); + { + QFileSystemModel *m = new QFileSystemModel(completer); + m->setRootPath("/"); + completer->setModel(m); + } + completer->setCompletionColumn(0); + break; default: qDebug() << "Invalid type"; } } -void tst_QCompleter::filter() +void tst_QCompleter::filter(bool assync) { QFETCH(QString, filterText); QFETCH(QString, step); @@ -250,6 +262,9 @@ void tst_QCompleter::filter() return; } + int times = 0; +retry: + completer->setCompletionPrefix(filterText); for (int i = 0; i < step.length(); i++) { @@ -265,9 +280,13 @@ void tst_QCompleter::filter() completer->setCurrentRow(row); } - //QModelIndex si = completer->currentIndex(); - //QCOMPARE(completer->model()->data(si).toString(), completion); - QVERIFY(0 == QString::compare(completer->currentCompletion(), completionText, completer->caseSensitivity())); + int r = QString::compare(completer->currentCompletion(), completionText, completer->caseSensitivity()); + if (assync && r && times < 10) { + times++; + QTest::qWait(50*times); + goto retry; + } + QVERIFY(!r); } // Testing get/set functions @@ -598,6 +617,57 @@ void tst_QCompleter::directoryModel() filter(); } +void tst_QCompleter::fileSystemModel_data() +{ + delete completer; + completer = new CsvCompleter; + completer->setModelSorting(QCompleter::CaseSensitivelySortedModel); + setSourceModel(FILESYSTEM_MODEL); + completer->setCaseSensitivity(Qt::CaseInsensitive); + + QTest::addColumn("filterText"); + QTest::addColumn("step"); + QTest::addColumn("completion"); + QTest::addColumn("completionText"); + + // NOTE: Add tests carefully, ensurely the paths exist on all systems + // Output is the sourceText; currentCompletionText() + + for (int i = 0; i < 2; i++) { + if (i == 1) + QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << ""; + +#if defined(Q_OS_WINCE) + QTest::newRow("()") << "" << "" << "/" << "/"; + QTest::newRow("()") << "\\Program" << "" << "Program Files" << "\\Program Files"; +#elif defined(Q_OS_WIN) + QTest::newRow("()") << "C" << "" << "C:" << "C:"; + QTest::newRow("()") << "C:\\Program" << "" << "Program Files" << "C:\\Program Files"; +#elif defined(Q_OS_SYMBIAN) + QTest::newRow("()") << "C" << "" << "C:" << "C:"; + QTest::newRow("()") << "C:\\re" << "" << "resource" << "C:\\resource"; +#elif defined (Q_OS_MAC) + QTest::newRow("()") << "" << "" << "/" << "/"; + QTest::newRow("(/a)") << "/a" << "" << "Applications" << "/Applications"; + QTest::newRow("(/d)") << "/d" << "" << "Developer" << "/Developer"; +#else + QTest::newRow("()") << "" << "" << "/" << "/"; +#if !defined(Q_OS_IRIX) && !defined(Q_OS_AIX) && !defined(Q_OS_HPUX) + QTest::newRow("(/h)") << "/h" << "" << "home" << "/home"; +#endif + QTest::newRow("(/et)") << "/et" << "" << "etc" << "/etc"; + QTest::newRow("(/etc/passw)") << "/etc/passw" << "" << "passwd" << "/etc/passwd"; +#endif + } +} + +void tst_QCompleter::fileSystemModel() +{ + //QFileSystemModel is assync. + filter(true); +} + + void tst_QCompleter::changingModel_data() { } -- cgit v0.12 From c416ec00e7c859a844a5bcb24c7a31147aed974c Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 13 Oct 2010 11:00:29 +0200 Subject: QCompleter: do not auto complete when directory is changed. Fixed regression for QCompleter associated with a QFileSystemModel. It would popup a popup each time the directory is changed. This was a regression in Qt 4.7.0, introduced with 319b0262418d74cc416a7d Task-number: QTBUG-14292 Reviewed-by: Thierry --- src/gui/util/qcompleter.cpp | 18 +++++--- src/gui/util/qcompleter_p.h | 1 + tests/auto/qcompleter/tst_qcompleter.cpp | 74 ++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 6 deletions(-) diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp index e718212..bcd601b 100644 --- a/src/gui/util/qcompleter.cpp +++ b/src/gui/util/qcompleter.cpp @@ -782,7 +782,8 @@ QMatchData QUnsortedModelEngine::filter(const QString& part, const QModelIndex& /////////////////////////////////////////////////////////////////////////////// QCompleterPrivate::QCompleterPrivate() : widget(0), proxy(0), popup(0), cs(Qt::CaseSensitive), role(Qt::EditRole), column(0), - maxVisibleItems(7), sorting(QCompleter::UnsortedModel), wrap(true), eatFocusOut(true) + maxVisibleItems(7), sorting(QCompleter::UnsortedModel), wrap(true), eatFocusOut(true), + hiddenBecauseNoMatch(false) { } @@ -921,12 +922,14 @@ void QCompleterPrivate::showPopup(const QRect& rect) void QCompleterPrivate::_q_fileSystemModelDirectoryLoaded(const QString &path) { Q_Q(QCompleter); -#ifndef QT_NO_LINEEDIT - QLineEdit *lineEdit = qobject_cast(widget); - //the path given by QFileSystemModel does not end with / - if (lineEdit && !lineEdit->text().isEmpty() && !q->completionPrefix().isEmpty() && q->completionPrefix() != path + QLatin1Char('/')) + // Slot called when QFileSystemModel has finished loading. + // If we hide the popup because there was no match because the model was not loaded yet, + // we re-start the completion when we get the results + if (hiddenBecauseNoMatch + && prefix.startsWith(path) && prefix != (path + '/') + && widget) { q->complete(); -#endif + } } /*! @@ -1200,6 +1203,7 @@ bool QCompleter::eventFilter(QObject *o, QEvent *e) Q_D(QCompleter); if (d->eatFocusOut && o == d->widget && e->type() == QEvent::FocusOut) { + d->hiddenBecauseNoMatch = false; if (d->popup && d->popup->isVisible()) return true; } @@ -1378,6 +1382,7 @@ void QCompleter::complete(const QRect& rect) { Q_D(QCompleter); QModelIndex idx = d->proxy->currentIndex(false); + d->hiddenBecauseNoMatch = false; if (d->mode == QCompleter::InlineCompletion) { if (idx.isValid()) d->_q_complete(idx, true); @@ -1389,6 +1394,7 @@ void QCompleter::complete(const QRect& rect) || (d->mode == QCompleter::UnfilteredPopupCompletion && d->proxy->rowCount() == 0)) { if (d->popup) d->popup->hide(); // no suggestion, hide + d->hiddenBecauseNoMatch = true; return; } diff --git a/src/gui/util/qcompleter_p.h b/src/gui/util/qcompleter_p.h index 8f00793..19b76e5 100644 --- a/src/gui/util/qcompleter_p.h +++ b/src/gui/util/qcompleter_p.h @@ -93,6 +93,7 @@ public: bool eatFocusOut; QRect popupRect; + bool hiddenBecauseNoMatch; void showPopup(const QRect&); void _q_complete(QModelIndex, bool = false); diff --git a/tests/auto/qcompleter/tst_qcompleter.cpp b/tests/auto/qcompleter/tst_qcompleter.cpp index 3e05fbc..6d28f9f 100644 --- a/tests/auto/qcompleter/tst_qcompleter.cpp +++ b/tests/auto/qcompleter/tst_qcompleter.cpp @@ -151,6 +151,7 @@ private slots: void task253125_lineEditCompletion_data(); void task253125_lineEditCompletion(); void task247560_keyboardNavigation(); + void QTBUG_14292_filesystem(); private: void filter(bool assync = false); @@ -571,6 +572,7 @@ void tst_QCompleter::csMatchingOnCiSortedModel() void tst_QCompleter::directoryModel_data() { delete completer; + completer = new CsvCompleter; completer->setModelSorting(QCompleter::CaseSensitivelySortedModel); setSourceModel(DIRECTORY_MODEL); @@ -1451,5 +1453,77 @@ void tst_QCompleter::task247560_keyboardNavigation() QCOMPARE(edit.text(), QString("row 3 column 1")); } +void tst_QCompleter::QTBUG_14292_filesystem() +{ + QDir tmpDir = QDir::temp(); + qsrand(QTime::currentTime().msec()); + QString d = "tst_QCompleter_" + QString::number(qrand()); + QVERIFY(tmpDir.mkdir(d)); + +#if 0 + struct Cleanup { + QString dir; + ~Cleanup() { + qDebug() << dir << + QFile::remove(dir); } + } cleanup; + cleanup.dir = tmpDir.absolutePath()+"/" +d; +#endif + + QVERIFY(tmpDir.cd(d)); + QVERIFY(tmpDir.mkdir("hello")); + QVERIFY(tmpDir.mkdir("holla")); + + QLineEdit edit; + QCompleter comp; + QFileSystemModel model; + model.setRootPath(tmpDir.path()); + comp.setModel(&model); + edit.setCompleter(&comp); + + edit.show(); + QApplication::setActiveWindow(&edit); + QTest::qWaitForWindowShown(&edit); + QTRY_VERIFY(QApplication::activeWindow() == &edit); + + QVERIFY(!comp.popup()->isVisible()); + edit.setText(tmpDir.path()); + QTest::keyClick(&edit, '/'); + QTRY_VERIFY(comp.popup()->isVisible()); + QCOMPARE(comp.popup()->model()->rowCount(), 2); + QTest::keyClick(&edit, 'h'); + QCOMPARE(comp.popup()->model()->rowCount(), 2); + QTest::keyClick(&edit, 'e'); + QCOMPARE(comp.popup()->model()->rowCount(), 1); + QTest::keyClick(&edit, 'r'); + QTRY_VERIFY(!comp.popup()->isVisible()); + QVERIFY(tmpDir.mkdir("hero")); + QTRY_VERIFY(comp.popup()->isVisible()); + QCOMPARE(comp.popup()->model()->rowCount(), 1); + QTest::keyClick(comp.popup(), Qt::Key_Escape); + QTRY_VERIFY(!comp.popup()->isVisible()); + QVERIFY(tmpDir.mkdir("nothingThere")); + //there is no reason creating a file should open a popup, it did in Qt 4.7.0 + QTest::qWait(60); + QVERIFY(!comp.popup()->isVisible()); + + QTest::keyClick(&edit, Qt::Key_Backspace); + QTRY_VERIFY(comp.popup()->isVisible()); + QCOMPARE(comp.popup()->model()->rowCount(), 2); + QTest::keyClick(&edit, 'm'); + QTRY_VERIFY(!comp.popup()->isVisible()); + + QWidget w; + w.show(); + QApplication::setActiveWindow(&w); + QTest::qWaitForWindowShown(&w); + QTRY_VERIFY(!edit.hasFocus() && !comp.popup()->hasFocus()); + + QVERIFY(tmpDir.mkdir("hemo")); + //there is no reason creating a file should open a popup, it did in Qt 4.7.0 + QTest::qWait(60); + QVERIFY(!comp.popup()->isVisible()); +} + QTEST_MAIN(tst_QCompleter) #include "tst_qcompleter.moc" -- cgit v0.12 From ab3304c663a62acb26af139d120f27a49a9d22ff Mon Sep 17 00:00:00 2001 From: Michael Dominic K Date: Wed, 13 Oct 2010 11:38:38 +0200 Subject: In meego graphics system, use always 16bit textures. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use GL_RGB16 for no-alpha images and RGBA4 for alpha images. Merge-request: 854 Reviewed-by: Samuel Rødal --- .../graphicssystems/meego/qmeegopixmapdata.cpp | 48 ++++++++++++++++++---- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp b/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp index 84fc593..799a28e 100644 --- a/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp +++ b/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp @@ -51,6 +51,24 @@ static EGLint preserved_image_attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, E QHash QMeeGoPixmapData::sharedImagesMap; +// This helper method converts (in place) a QImage::Format_ARGB4444_Premultiplied to +// GL-friendly Format_RGBA4444_Premultiplied. Just swaps the bits around really. +static void qARGBA4ToRGBA4(QImage *image) +{ + unsigned char *raw = static_cast (image->data_ptr()->data); + // FIXME image.bytesPerLine() is broken. Returns 512 for 128x128 image while it should + // return 256 + int bytesPerLine = image->width() * 2; + + for (int y = 0; y < image->height(); y++) { + for (int x = 0; x < image->width(); x++) { + unsigned short *target = (unsigned short *) (raw + (y * bytesPerLine + (x * 2))); + // FIXME Oh yeah, that's broken with endianness. + *target = (*target << 4) | (* target >> 12); + } + } +} + /* Public */ QMeeGoPixmapData::QMeeGoPixmapData() : QGLPixmapData(QPixmapData::PixmapType) @@ -108,8 +126,6 @@ void QMeeGoPixmapData::fromEGLImage(Qt::HANDLE handle) QMeeGoExtensions::eglQueryImageNOK(QEgl::display(), (EGLImageKHR) handle, EGL_HEIGHT, &newHeight); if (textureIsBound) { - // FIXME Remove this ugly hasAlphaChannel check when Qt lands the NoOpaqueCheck flag fix - // for QGLPixmapData. fromTexture(newTextureId, newWidth, newHeight, true); } else { qWarning("Failed to create a texture from an egl image!"); @@ -152,10 +168,9 @@ void QMeeGoPixmapData::fromEGLSharedImage(Qt::HANDLE handle, const QImage &si) } if (textureIsBound) { - // FIXME Remove this ugly hasAlphaChannel check when Qt lands the NoOpaqueCheck flag fix - // for QGLPixmapData. fromTexture(newTextureId, newWidth, newHeight, - (si.hasAlphaChannel() && const_cast(si).data_ptr()->checkForAlphaPixels())); + si.hasAlphaChannel()); + texture()->options &= ~QGLContext::InvertedYBindOption; softImage = si; QMeeGoPixmapData::registerSharedImage(handle, softImage); } else { @@ -171,15 +186,31 @@ Qt::HANDLE QMeeGoPixmapData::imageToEGLSharedImage(const QImage &image) QMeeGoExtensions::ensureInitialized(); glFinish(); - QGLPixmapData pixmapData(QPixmapData::PixmapType); - pixmapData.fromImage(image, 0); - GLuint textureId = pixmapData.bind(); + + GLuint textureId; + + glGenTextures(1, &textureId); + glBindTexture(GL_TEXTURE_2D, textureId); + if (image.hasAlphaChannel()) { + QImage convertedImage = image.convertToFormat(QImage::Format_ARGB4444_Premultiplied, Qt::NoOpaqueDetection); + qARGBA4ToRGBA4(&convertedImage); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, convertedImage.bits()); + } else { + QImage convertedImage = image.convertToFormat(QImage::Format_RGB16, Qt::NoOpaqueDetection); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, convertedImage.bits()); + } + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glFinish(); + + glBindTexture(GL_TEXTURE_2D, textureId); EGLImageKHR eglimage = QEgl::eglCreateImageKHR(QEgl::display(), QEglContext::currentContext(QEgl::OpenGL)->context(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer) textureId, preserved_image_attribs); + glDeleteTextures(1, &textureId); glFinish(); if (eglimage) { @@ -195,6 +226,7 @@ Qt::HANDLE QMeeGoPixmapData::imageToEGLSharedImage(const QImage &image) void QMeeGoPixmapData::updateFromSoftImage() { + // FIXME That's broken with recent 16bit textures changes. m_dirty = true; m_source = softImage; ensureCreated(); -- cgit v0.12 From 1af2d09523e3808e4589f05a4b8d42c308eb0841 Mon Sep 17 00:00:00 2001 From: Michael Dominic K Date: Wed, 13 Oct 2010 11:38:39 +0200 Subject: Proper dither & proper alpha checking. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge-request: 854 Reviewed-by: Samuel Rødal --- src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp b/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp index 799a28e..5473d09 100644 --- a/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp +++ b/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp @@ -169,7 +169,7 @@ void QMeeGoPixmapData::fromEGLSharedImage(Qt::HANDLE handle, const QImage &si) if (textureIsBound) { fromTexture(newTextureId, newWidth, newHeight, - si.hasAlphaChannel()); + (si.hasAlphaChannel() && const_cast(si).data_ptr()->checkForAlphaPixels())); texture()->options &= ~QGLContext::InvertedYBindOption; softImage = si; QMeeGoPixmapData::registerSharedImage(handle, softImage); @@ -191,12 +191,12 @@ Qt::HANDLE QMeeGoPixmapData::imageToEGLSharedImage(const QImage &image) glGenTextures(1, &textureId); glBindTexture(GL_TEXTURE_2D, textureId); - if (image.hasAlphaChannel()) { - QImage convertedImage = image.convertToFormat(QImage::Format_ARGB4444_Premultiplied, Qt::NoOpaqueDetection); + if (image.hasAlphaChannel() && (image.hasAlphaChannel() && const_cast(image).data_ptr()->checkForAlphaPixels())) { + QImage convertedImage = image.convertToFormat(QImage::Format_ARGB4444_Premultiplied, Qt::DiffuseAlphaDither | Qt::DiffuseDither | Qt::PreferDither); qARGBA4ToRGBA4(&convertedImage); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, convertedImage.bits()); } else { - QImage convertedImage = image.convertToFormat(QImage::Format_RGB16, Qt::NoOpaqueDetection); + QImage convertedImage = image.convertToFormat(QImage::Format_RGB16, Qt::DiffuseAlphaDither | Qt::DiffuseDither | Qt::PreferDither); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, convertedImage.bits()); } -- cgit v0.12 From fa6bad3c703fdb2d0218972c5774ed0a61948f84 Mon Sep 17 00:00:00 2001 From: Michael Dominic K Date: Wed, 13 Oct 2010 11:40:51 +0200 Subject: Correctly remove the egl alpha surface flags in meego graphics system. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge-request: 856 Reviewed-by: Samuel Rødal --- src/plugins/graphicssystems/meego/qmeegographicssystem.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp index f8b228c..b378b13 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp @@ -363,7 +363,9 @@ EGLSurface QMeeGoGraphicsSystem::getSurfaceForLiveTexturePixmap(QPixmap *pixmap) pixmapData->gl_surface = (void*)QEgl::createSurface(pixmap, config); if (hasAlpha) - pixmapData->flags = pixmapData->flags | QX11PixmapData::GlSurfaceCreatedWithAlpha; + pixmapData->flags |= QX11PixmapData::GlSurfaceCreatedWithAlpha; + else + pixmapData->flags &= ~QX11PixmapData::GlSurfaceCreatedWithAlpha; if (pixmapData->gl_surface == (void*)EGL_NO_SURFACE) return NULL; -- cgit v0.12 From 6f1f1317e68a261173ddb24a045dcc823b16a3bd Mon Sep 17 00:00:00 2001 From: Michael Dominic K Date: Wed, 13 Oct 2010 11:40:51 +0200 Subject: Correctly handle both 16bit and 32bit live pixmaps in meego graphics system. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge-request: 856 Reviewed-by: Samuel Rødal --- src/plugins/graphicssystems/meego/qmeegographicssystem.cpp | 14 +++++++++++--- src/plugins/graphicssystems/meego/qmeegographicssystem.h | 4 ++-- tools/qmeegographicssystemhelper/qmeegolivepixmap.cpp | 6 +++--- tools/qmeegographicssystemhelper/qmeegoruntime.cpp | 6 +++--- tools/qmeegographicssystemhelper/qmeegoruntime.h | 2 +- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp index b378b13..27e728a 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp @@ -275,7 +275,7 @@ bool QMeeGoGraphicsSystem::unlockLiveTexture(Qt::HANDLE h) } } -void QMeeGoGraphicsSystem::queryLiveTexture(Qt::HANDLE h, void **data, int *pitch) +void QMeeGoGraphicsSystem::queryLiveTexture(Qt::HANDLE h, void **data, int *pitch, QImage::Format *f) { // FIXME Only allow this on locked surfaces if (! liveTexturePixmaps.contains(h)) { @@ -289,6 +289,14 @@ void QMeeGoGraphicsSystem::queryLiveTexture(Qt::HANDLE h, void **data, int *pitc EGLSurface surface = getSurfaceForLiveTexturePixmap(liveTexturePixmaps.value(h)); eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_POINTER_KHR, (EGLint*) data); eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_PITCH_KHR, (EGLint*) pitch); + + // Ok, here we know we just support those two formats. Real solution would be: + // in liveTexturePixmaps store a small structure containing the pixmap and the + // original Qt format. + if (liveTexturePixmaps.value(h)->depth() > 16) + *f = QImage::Format_ARGB32_Premultiplied; + else + *f = QImage::Format_RGB16; } Qt::HANDLE QMeeGoGraphicsSystem::liveTextureToEGLImage(Qt::HANDLE h) @@ -441,9 +449,9 @@ bool qt_meego_live_texture_unlock(Qt::HANDLE h) return QMeeGoGraphicsSystem::unlockLiveTexture(h); } -void qt_meego_live_texture_query(Qt::HANDLE h, void **data, int *pitch) +void qt_meego_live_texture_query(Qt::HANDLE h, void **data, int *pitch, QImage::Format *f) { - return QMeeGoGraphicsSystem::queryLiveTexture(h, data, pitch); + return QMeeGoGraphicsSystem::queryLiveTexture(h, data, pitch, f); } Qt::HANDLE qt_meego_live_texture_to_egl_image(Qt::HANDLE h) diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.h b/src/plugins/graphicssystems/meego/qmeegographicssystem.h index 934d32d..fad0db6 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.h +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.h @@ -71,7 +71,7 @@ public: static void destroyLiveTexture(Qt::HANDLE h); static bool lockLiveTexture(Qt::HANDLE h); static bool unlockLiveTexture(Qt::HANDLE h); - static void queryLiveTexture(Qt::HANDLE h, void **data, int *pitch); + static void queryLiveTexture(Qt::HANDLE h, void **data, int *pitch, QImage::Format *format); static Qt::HANDLE liveTextureToEGLImage(Qt::HANDLE h); private: @@ -99,7 +99,7 @@ extern "C" { Q_DECL_EXPORT void m_live_texture_destroy(Qt::HANDLE h); Q_DECL_EXPORT bool m_live_texture_lock(Qt::HANDLE h); Q_DECL_EXPORT bool m_live_texture_unlock(Qt::HANDLE h); - Q_DECL_EXPORT void m_live_texture_query(Qt::HANDLE h, void **data, int *pitch); + Q_DECL_EXPORT void m_live_texture_query(Qt::HANDLE h, void **data, int *pitch, QImage::Format *f); Q_DECL_EXPORT Qt::HANDLE m_live_texture_to_egl_image(Qt::HANDLE h); } diff --git a/tools/qmeegographicssystemhelper/qmeegolivepixmap.cpp b/tools/qmeegographicssystemhelper/qmeegolivepixmap.cpp index b9dbb2b..5e36631 100644 --- a/tools/qmeegographicssystemhelper/qmeegolivepixmap.cpp +++ b/tools/qmeegographicssystemhelper/qmeegolivepixmap.cpp @@ -118,20 +118,20 @@ QImage* QMeeGoLivePixmap::lock() void *data = NULL; int pitch = 0; + QImage::Format format; if (! QMeeGoRuntime::lockLiveTexture(d->handle)) { qWarning("Failed to lock a live texture!"); return new QImage(); } - QMeeGoRuntime::queryLiveTexture(d->handle, &data, &pitch); + QMeeGoRuntime::queryLiveTexture(d->handle, &data, &pitch, &format); if (data == NULL || pitch == 0) { qWarning("Failed to query the live texture!"); return new QImage(); } - // FIXME Bug here! FIX FIX FIX FIX FIX FIX - return new QImage((uchar *) data, width(), height(), QImage::Format_RGB16); + return new QImage((uchar *) data, width(), height(), format); } void QMeeGoLivePixmap::release(QImage *img) diff --git a/tools/qmeegographicssystemhelper/qmeegoruntime.cpp b/tools/qmeegographicssystemhelper/qmeegoruntime.cpp index 44f9f58..215dffc 100644 --- a/tools/qmeegographicssystemhelper/qmeegoruntime.cpp +++ b/tools/qmeegographicssystemhelper/qmeegoruntime.cpp @@ -62,7 +62,7 @@ typedef Qt::HANDLE (*QMeeGoLiveTextureCreateFunc) (int w, int h, QImage::Format typedef bool (*QMeeGoLiveTextureLockFunc) (Qt::HANDLE h); typedef bool (*QMeeGoLiveTextureUnlockFunc) (Qt::HANDLE h); typedef void (*QMeeGoLiveTextureDestroyFunc) (Qt::HANDLE h); -typedef void (*QMeeGoLiveTextureQueryFunc) (Qt::HANDLE h, void **data, int *pitch); +typedef void (*QMeeGoLiveTextureQueryFunc) (Qt::HANDLE h, void **data, int *pitch, QImage::Format *format); typedef Qt::HANDLE (*QMeeGoLiveTextureToEglImageFunc) (Qt::HANDLE h); static QMeeGoImageToEglSharedImageFunc qt_meego_image_to_egl_shared_image = NULL; @@ -216,11 +216,11 @@ void QMeeGoRuntime::destroyLiveTexture(Qt::HANDLE h) qt_meego_live_texture_destroy(h); } -void QMeeGoRuntime::queryLiveTexture(Qt::HANDLE h, void **data, int *pitch) +void QMeeGoRuntime::queryLiveTexture(Qt::HANDLE h, void **data, int *pitch, QImage::Format *format) { ENSURE_INITIALIZED; Q_ASSERT(qt_meego_live_texture_query); - qt_meego_live_texture_query(h, data, pitch); + qt_meego_live_texture_query(h, data, pitch, format); } Qt::HANDLE QMeeGoRuntime::liveTextureToEGLImage(Qt::HANDLE handle) diff --git a/tools/qmeegographicssystemhelper/qmeegoruntime.h b/tools/qmeegographicssystemhelper/qmeegoruntime.h index 048b9be..9f2d505 100644 --- a/tools/qmeegographicssystemhelper/qmeegoruntime.h +++ b/tools/qmeegographicssystemhelper/qmeegoruntime.h @@ -60,7 +60,7 @@ public: static bool lockLiveTexture(Qt::HANDLE h); static bool unlockLiveTexture(Qt::HANDLE h); static void destroyLiveTexture(Qt::HANDLE h); - static void queryLiveTexture(Qt::HANDLE h, void **data, int *pitch); + static void queryLiveTexture(Qt::HANDLE h, void **data, int *pitch, QImage::Format *format); static Qt::HANDLE liveTextureToEGLImage(Qt::HANDLE); private: -- cgit v0.12 From 62dc9c9602987f4381481cc5642e3ea0782bb418 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 13 Oct 2010 11:42:10 +0200 Subject: Adjust the parent index for the itemsMoved call. Not doing this causes the parent QModelIndexes to be out of sync with the model. The fix in fe350ca756df6392b3d0b7840351fccc89f9ef6f is extended to also use adjusted indexes in the itemMove call. Merge-request: 849 Reviewed-by: Olivier Goffart --- src/corelib/kernel/qabstractitemmodel.cpp | 8 ++++---- tests/auto/modeltest/dynamictreemodel.cpp | 7 +++++++ tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp | 6 ++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 9a99ea1..05cb271 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -2637,8 +2637,6 @@ void QAbstractItemModel::endMoveRows() QAbstractItemModelPrivate::Change insertChange = d->changes.pop(); QAbstractItemModelPrivate::Change removeChange = d->changes.pop(); - d->itemsMoved(removeChange.parent, removeChange.first, removeChange.last, insertChange.parent, insertChange.first, Qt::Vertical); - QModelIndex adjustedSource = removeChange.parent; QModelIndex adjustedDestination = insertChange.parent; @@ -2649,6 +2647,8 @@ void QAbstractItemModel::endMoveRows() if (removeChange.needsAdjust) adjustedSource = createIndex(adjustedSource.row() + numMoved, adjustedSource.column(), adjustedSource.internalPointer()); + d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Vertical); + emit rowsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first); emit layoutChanged(); } @@ -2861,8 +2861,6 @@ void QAbstractItemModel::endMoveColumns() QAbstractItemModelPrivate::Change insertChange = d->changes.pop(); QAbstractItemModelPrivate::Change removeChange = d->changes.pop(); - d->itemsMoved(removeChange.parent, removeChange.first, removeChange.last, insertChange.parent, insertChange.first, Qt::Horizontal); - QModelIndex adjustedSource = removeChange.parent; QModelIndex adjustedDestination = insertChange.parent; @@ -2873,6 +2871,8 @@ void QAbstractItemModel::endMoveColumns() if (removeChange.needsAdjust) adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer()); + d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Horizontal); + emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first); emit layoutChanged(); } diff --git a/tests/auto/modeltest/dynamictreemodel.cpp b/tests/auto/modeltest/dynamictreemodel.cpp index b572eb1..fa634b6 100644 --- a/tests/auto/modeltest/dynamictreemodel.cpp +++ b/tests/auto/modeltest/dynamictreemodel.cpp @@ -63,6 +63,13 @@ QModelIndex DynamicTreeModel::index(int row, int column, const QModelIndex &pare QList > childIdColumns = m_childItems.value(parent.internalId()); + const qint64 grandParent = findParentId(parent.internalId()); + if (grandParent >= 0) { + QList > parentTable = m_childItems.value(grandParent); + Q_ASSERT(parent.column() < parentTable.size()); + QList parentSiblings = parentTable.at(parent.column()); + Q_ASSERT(parent.row() < parentSiblings.size()); + } if (childIdColumns.size() == 0) return QModelIndex(); diff --git a/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp b/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp index dbcccc9..b723253 100644 --- a/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp +++ b/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp @@ -1167,6 +1167,7 @@ void tst_QAbstractItemModel::testMoveToGrandParent_data() // Moving everything from one parent to another QTest::newRow("move12") << 0 << 9 << 10; + QTest::newRow("move13") << 0 << 9 << 0; } void tst_QAbstractItemModel::testMoveToGrandParent() @@ -1314,6 +1315,11 @@ void tst_QAbstractItemModel::testMoveToSibling_data() QTest::newRow("move09") << 8 << 8 << 4; QTest::newRow("move10") << 8 << 8 << 5; QTest::newRow("move11") << 8 << 8 << 6; + + // Move such that the destination parent no longer valid after the move. + // The destination parent is always QMI(5, 0), but after this move the + // row count is 5, so (5, 0) (used internally in QAIM) no longer refers to a valid index. + QTest::newRow("move12") << 0 << 4 << 0; } void tst_QAbstractItemModel::testMoveToSibling() -- cgit v0.12 From 1c86defda1d9cd3577898ec5f63c4d9bd250564b Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Wed, 13 Oct 2010 13:12:34 +0200 Subject: Fixed statement about const_iterator and some whitespace fixes. Task-number: QTBUG-14252 Reviewed-by: David Boddie --- src/corelib/tools/qlinkedlist.cpp | 4 ++-- src/corelib/tools/qlist.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qlinkedlist.cpp b/src/corelib/tools/qlinkedlist.cpp index 909d940..7213c6e 100644 --- a/src/corelib/tools/qlinkedlist.cpp +++ b/src/corelib/tools/qlinkedlist.cpp @@ -254,7 +254,7 @@ QLinkedListData QLinkedListData::shared_null = { \sa insert() */ -/*! +/*! \fn bool QLinkedList::removeOne(const T &value) \since 4.4 @@ -830,7 +830,7 @@ QLinkedListData QLinkedListData::shared_null = { QLinkedList\::const_iterator allows you to iterate over a QLinkedList\. If you want modify the QLinkedList as you iterate - over it, you must use QLinkedList::const_iterator instead. It is + over it, you must use QLinkedList::iterator instead. It is generally good practice to use QLinkedList::const_iterator on a non-const QLinkedList as well, unless you need to change the QLinkedList through the iterator. Const iterators are slightly diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 6cc6fc1..9ba3768 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -936,7 +936,7 @@ void **QListData::erase(void **xi) This function requires the value type to have an implementation of \c operator==(). - Note that QList uses 0-based indexes, just like C++ arrays. Negative + Note that QList uses 0-based indexes, just like C++ arrays. Negative indexes are not supported with the exception of the value mentioned above. -- cgit v0.12 From 9f766c977a329c84023a15fc66f52d26ff03447b Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 13 Oct 2010 13:27:06 +0200 Subject: Revert "Revert "Fix (implement!) hfw/wfh in QGridLayoutEngine"" This reverts commit 5bd6f7eb5c7d87c08539b6c2df416990cc417ec7. This is a revert of the revert. It is required apply the merge-request 847, which itself revert back part of this commit but fixing it the (hopefuly) right way --- src/gui/graphicsview/qgraphicslayoutitem.cpp | 51 ++- src/gui/graphicsview/qgraphicslayoutitem_p.h | 6 + src/gui/graphicsview/qgridlayoutengine.cpp | 251 +++++++++++++- src/gui/graphicsview/qgridlayoutengine_p.h | 23 +- .../tst_qgraphicsgridlayout.cpp | 364 ++++++++++++++++++++- 5 files changed, 678 insertions(+), 17 deletions(-) diff --git a/src/gui/graphicsview/qgraphicslayoutitem.cpp b/src/gui/graphicsview/qgraphicslayoutitem.cpp index ad4b2b5..634f68c 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem.cpp +++ b/src/gui/graphicsview/qgraphicslayoutitem.cpp @@ -48,6 +48,7 @@ #include "qgraphicslayoutitem.h" #include "qgraphicslayoutitem_p.h" #include "qwidget.h" +#include "qgraphicswidget.h" #include @@ -139,9 +140,11 @@ QSizeF *QGraphicsLayoutItemPrivate::effectiveSizeHints(const QSizeF &constraint) if (!sizeHintCacheDirty && cachedConstraint == constraint) return cachedSizeHints; + const bool hasConstraint = constraint.width() >= 0 || constraint.height() >= 0; + for (int i = 0; i < Qt::NSizeHints; ++i) { cachedSizeHints[i] = constraint; - if (userSizeHints) + if (userSizeHints && !hasConstraint) combineSize(cachedSizeHints[i], userSizeHints[i]); } @@ -259,6 +262,52 @@ void QGraphicsLayoutItemPrivate::setSizeComponent( q->updateGeometry(); } + +bool QGraphicsLayoutItemPrivate::hasHeightForWidth() const +{ + Q_Q(const QGraphicsLayoutItem); + if (isLayout) { + const QGraphicsLayout *l = static_cast(q); + for (int i = l->count() - 1; i >= 0; --i) { + if (QGraphicsLayoutItemPrivate::get(l->itemAt(i))->hasHeightForWidth()) + return true; + } + } else if (QGraphicsItem *item = q->graphicsItem()) { + if (item->isWidget()) { + QGraphicsWidget *w = static_cast(item); + if (w->layout()) { + return QGraphicsLayoutItemPrivate::get(w->layout())->hasHeightForWidth(); + } + } + } + return q->sizePolicy().hasHeightForWidth(); +} + +bool QGraphicsLayoutItemPrivate::hasWidthForHeight() const +{ + // enable this code when we add QSizePolicy::hasWidthForHeight() (For 4.8) +#if 1 + return false; +#else + Q_Q(const QGraphicsLayoutItem); + if (isLayout) { + const QGraphicsLayout *l = static_cast(q); + for (int i = l->count() - 1; i >= 0; --i) { + if (QGraphicsLayoutItemPrivate::get(l->itemAt(i))->hasWidthForHeight()) + return true; + } + } else if (QGraphicsItem *item = q->graphicsItem()) { + if (item->isWidget()) { + QGraphicsWidget *w = static_cast(item); + if (w->layout()) { + return QGraphicsLayoutItemPrivate::get(w->layout())->hasWidthForHeight(); + } + } + } + return q->sizePolicy().hasWidthForHeight(); +#endif +} + /*! \class QGraphicsLayoutItem \brief The QGraphicsLayoutItem class can be inherited to allow your custom diff --git a/src/gui/graphicsview/qgraphicslayoutitem_p.h b/src/gui/graphicsview/qgraphicslayoutitem_p.h index 15cc7a5..b752e03 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem_p.h +++ b/src/gui/graphicsview/qgraphicslayoutitem_p.h @@ -65,6 +65,9 @@ class Q_AUTOTEST_EXPORT QGraphicsLayoutItemPrivate public: virtual ~QGraphicsLayoutItemPrivate(); QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *parent, bool isLayout); + static QGraphicsLayoutItemPrivate *get(QGraphicsLayoutItem *q) { return q->d_func();} + static const QGraphicsLayoutItemPrivate *get(const QGraphicsLayoutItem *q) { return q->d_func();} + void init(); QSizeF *effectiveSizeHints(const QSizeF &constraint) const; QGraphicsItem *parentItem() const; @@ -73,6 +76,9 @@ public: enum SizeComponent { Width, Height }; void setSizeComponent(Qt::SizeHint which, SizeComponent component, qreal value); + bool hasHeightForWidth() const; + bool hasWidthForHeight() const; + QSizePolicy sizePolicy; QGraphicsLayoutItem *parent; diff --git a/src/gui/graphicsview/qgridlayoutengine.cpp b/src/gui/graphicsview/qgridlayoutengine.cpp index ae5bf90..1e3addc 100644 --- a/src/gui/graphicsview/qgridlayoutengine.cpp +++ b/src/gui/graphicsview/qgridlayoutengine.cpp @@ -545,6 +545,24 @@ QSizePolicy::Policy QGridLayoutItem::sizePolicy(Qt::Orientation orientation) con : sizePolicy.verticalPolicy(); } +/* + returns true if the size policy returns true for either hasHeightForWidth() + or hasWidthForHeight() + */ +bool QGridLayoutItem::hasDynamicConstraint() const +{ + return QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasHeightForWidth() + || QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasWidthForHeight(); +} + +Qt::Orientation QGridLayoutItem::dynamicConstraintOrientation() const +{ + if (QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasHeightForWidth()) + return Qt::Vertical; + else //if (QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasWidthForHeight()) + return Qt::Horizontal; +} + QSizePolicy::ControlTypes QGridLayoutItem::controlTypes(LayoutSide /* side */) const { return q_layoutItem->sizePolicy().controlType(); @@ -613,7 +631,14 @@ QRectF QGridLayoutItem::geometryWithin(qreal x, qreal y, qreal width, qreal heig qreal cellWidth = width; qreal cellHeight = height; - QSizeF size = effectiveMaxSize().boundedTo(QSizeF(cellWidth, cellHeight)); + QSize constraint; + if (hasDynamicConstraint()) { + if (dynamicConstraintOrientation() == Qt::Vertical) + constraint.setWidth(cellWidth); + else + constraint.setHeight(cellHeight); + } + QSizeF size = effectiveMaxSize(constraint).boundedTo(QSizeF(cellWidth, cellHeight)); width = size.width(); height = size.height(); @@ -675,13 +700,13 @@ void QGridLayoutItem::insertOrRemoveRows(int row, int delta, Qt::Orientation ori Note that effectiveSizeHint does not take sizePolicy into consideration, (since it only evaluates the hints, as the name implies) */ -QSizeF QGridLayoutItem::effectiveMaxSize() const +QSizeF QGridLayoutItem::effectiveMaxSize(const QSizeF &constraint) const { - QSizeF size; + QSizeF size = constraint; bool vGrow = (sizePolicy(Qt::Vertical) & QSizePolicy::GrowFlag) == QSizePolicy::GrowFlag; bool hGrow = (sizePolicy(Qt::Horizontal) & QSizePolicy::GrowFlag) == QSizePolicy::GrowFlag; if (!vGrow || !hGrow) { - QSizeF pref = layoutItem()->effectiveSizeHint(Qt::PreferredSize); + QSizeF pref = layoutItem()->effectiveSizeHint(Qt::PreferredSize, constraint); if (!vGrow) size.setHeight(pref.height()); if (!hGrow) @@ -689,7 +714,7 @@ QSizeF QGridLayoutItem::effectiveMaxSize() const } if (!size.isValid()) { - QSizeF maxSize = layoutItem()->effectiveSizeHint(Qt::MaximumSize); + QSizeF maxSize = layoutItem()->effectiveSizeHint(Qt::MaximumSize, constraint); if (size.width() == -1) size.setWidth(maxSize.width()); if (size.height() == -1) @@ -1010,6 +1035,7 @@ void QGridLayoutEngine::invalidate() q_cachedEffectiveLastRows[Ver] = -1; q_cachedDataForStyleInfo.invalidate(); q_cachedSize = QSizeF(); + q_cachedConstraintOrientation = UnknownConstraint; } static void visualRect(QRectF *geom, Qt::LayoutDirection dir, const QRectF &contentsRect) @@ -1074,10 +1100,13 @@ QRectF QGridLayoutEngine::cellRect(const QLayoutStyleInfo &styleInfo, } QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHint which, - const QSizeF & /* constraint */) const + const QSizeF &constraint) const { ensureColumnAndRowData(styleInfo); + if (hasDynamicConstraint()) + return dynamicallyConstrainedSizeHint(which, constraint); + switch (which) { case Qt::MinimumSize: return QSizeF(q_totalBoxes[Hor].q_minimumSize, q_totalBoxes[Ver].q_minimumSize); @@ -1375,7 +1404,11 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutSt box = &multiCell.q_box; multiCell.q_stretch = itemStretch; } - box->combine(item->box(orientation)); + // Items with constraints are not included in the orientation that + // they are constrained (since it depends on the hfw/constraint function). + // They must be combined at a later stage. + if (!item->hasDynamicConstraint() || orientation != item->dynamicConstraintOrientation()) + box->combine(item->box(orientation)); if (effectiveRowSpan == 1) { QSizePolicy::ControlTypes controls = item->controlTypes(top); @@ -1532,6 +1565,138 @@ void QGridLayoutEngine::ensureColumnAndRowData(const QLayoutStyleInfo &styleInfo q_cachedDataForStyleInfo = styleInfo; } +QSizeF QGridLayoutEngine::dynamicallyConstrainedSizeHint(Qt::SizeHint which, + const QSizeF &constraint) const +{ + Q_ASSERT(hasDynamicConstraint()); + if (constraint.width() < 0 && constraint.height() < 0) { + // Process the hfw / wfh items that we did not process in fillRowData() + const Qt::Orientation constraintOrient = constraintOrientation(); + + QGridLayoutRowData rowData = constraintOrient == Qt::Vertical ? q_rowData : q_columnData; + for (int i = q_items.count() - 1; i >= 0; --i) { + QGridLayoutItem *item = q_items.at(i); + if (item->hasDynamicConstraint()) { + QGridLayoutBox box = item->box(constraintOrient); + QGridLayoutBox &rowBox = rowData.boxes[item->firstRow(constraintOrient)]; + rowBox.combine(box); + } + } + + QGridLayoutBox totalBoxes[2]; + if (constraintOrient == Qt::Vertical) { + totalBoxes[Hor] = q_columnData.totalBox(0, columnCount()); + totalBoxes[Ver] = rowData.totalBox(0, rowCount()); + } else { + totalBoxes[Hor] = rowData.totalBox(0, columnCount()); + totalBoxes[Ver] = q_rowData.totalBox(0, rowCount()); + } + return QSizeF(totalBoxes[Hor].q_sizes(which), totalBoxes[Ver].q_sizes(which)); + } + + + Q_ASSERT(constraint.width() >= 0 || constraint.height() >= 0); + q_xx.resize(columnCount()); + q_yy.resize(rowCount()); + q_widths.resize(columnCount()); + q_heights.resize(rowCount()); + q_descents.resize(rowCount()); + + + const Qt::Orientation orientation = constraintOrientation(); + QGridLayoutRowData *colData; + QGridLayoutRowData constrainedRowData; + QGridLayoutBox *totalBox; + qreal *sizes; + qreal *pos; + qreal *descents; + qreal targetSize; + qreal cCount; + qreal rCount; + + if (orientation == Qt::Vertical) { + // height for width + colData = &q_columnData; + totalBox = &q_totalBoxes[Hor]; + sizes = q_widths.data(); + pos = q_xx.data(); + descents = 0; + targetSize = constraint.width(); + cCount = columnCount(); + rCount = rowCount(); + constrainedRowData = q_rowData; + } else { + // width for height + colData = &q_rowData; + totalBox = &q_totalBoxes[Ver]; + sizes = q_heights.data(); + pos = q_yy.data(); + descents = q_descents.data(); + targetSize = constraint.height(); + cCount = rowCount(); + rCount = columnCount(); + constrainedRowData = q_columnData; + } + colData->calculateGeometries(0, cCount, targetSize, pos, sizes, descents, *totalBox); + for (int i = q_items.count() - 1; i >= 0; --i) { + QGridLayoutItem *item = q_items.at(i); + + if (item->hasDynamicConstraint()) { + const qreal size = sizes[item->firstColumn(orientation)]; + QGridLayoutBox box = item->box(orientation, size); + QGridLayoutBox &rowBox = constrainedRowData.boxes[item->firstRow(orientation)]; + rowBox.combine(box); + } + } + const qreal newSize = constrainedRowData.totalBox(0, rCount).q_sizes(which); + + return (orientation == Qt::Vertical) ? QSizeF(targetSize, newSize) : QSizeF(newSize, targetSize); +} + + +/** + returns false if the layout has contradicting constraints (i.e. some items with a horizontal + constraint and other items with a vertical constraint) + */ +bool QGridLayoutEngine::ensureDynamicConstraint() const +{ + if (q_cachedConstraintOrientation == UnknownConstraint) { + for (int i = q_items.count() - 1; i >= 0; --i) { + QGridLayoutItem *item = q_items.at(i); + if (item->hasDynamicConstraint()) { + Qt::Orientation itemConstraintOrientation = item->dynamicConstraintOrientation(); + if (q_cachedConstraintOrientation == UnknownConstraint) { + q_cachedConstraintOrientation = itemConstraintOrientation; + } else if (q_cachedConstraintOrientation != itemConstraintOrientation) { + q_cachedConstraintOrientation = UnfeasibleConstraint; + qWarning("QGridLayoutEngine: Unfeasible, cannot mix horizontal and" + " vertical constraint in the same layout"); + return false; + } + } + } + if (q_cachedConstraintOrientation == UnknownConstraint) + q_cachedConstraintOrientation = NoConstraint; + } + return true; +} + +bool QGridLayoutEngine::hasDynamicConstraint() const +{ + if (!ensureDynamicConstraint()) + return false; + return q_cachedConstraintOrientation != NoConstraint; +} + +/* + * return value is only valid if hasConstraint() returns true + */ +Qt::Orientation QGridLayoutEngine::constraintOrientation() const +{ + (void)ensureDynamicConstraint(); + return (Qt::Orientation)q_cachedConstraintOrientation; +} + void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo, const QSizeF &size) const { @@ -1544,10 +1709,74 @@ void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo, q_widths.resize(columnCount()); q_heights.resize(rowCount()); q_descents.resize(rowCount()); - q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(), - 0, q_totalBoxes[Hor]); - q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(), - q_descents.data(), q_totalBoxes[Ver]); + + + Qt::Orientation orientation = Qt::Vertical; + if (hasDynamicConstraint()) + orientation = constraintOrientation(); + + /* + In order to do hfw we need to first distribute the columns, then the rows. + In order to do wfh we need to first distribute the rows, then the columns. + + If there is no constraint, the order of distributing the rows or columns first is irrelevant. + We choose horizontal just to keep the same behaviour as before (however, there shouldn't + be any behaviour difference). + */ + + QGridLayoutRowData *colData; + QGridLayoutRowData rowData; + qreal *widths; + qreal *heights; + qreal *xx; + qreal *yy; + qreal *xdescents = 0; + qreal *ydescents = 0; + qreal cCount; + qreal rCount; + QSizeF oSize = size; + if (orientation == Qt::Vertical) { + // height for width + colData = &q_columnData; + rowData = q_rowData; + widths = q_widths.data(); + heights = q_heights.data(); + xx = q_xx.data(); + yy = q_yy.data(); + cCount = columnCount(); + rCount = rowCount(); + ydescents = q_descents.data(); + } else { + // width for height + colData = &q_rowData; + rowData = q_columnData; + widths = q_heights.data(); + heights = q_widths.data(); + xx = q_yy.data(); + yy = q_xx.data(); + cCount = rowCount(); + rCount = columnCount(); + xdescents = q_descents.data(); + oSize.transpose(); + } + + colData->calculateGeometries(0, cCount, oSize.width(), xx, widths, + xdescents, q_totalBoxes[orientation == Qt::Horizontal]); + for (int i = q_items.count() - 1; i >= 0; --i) { + QGridLayoutItem *item = q_items.at(i); + const int col = item->firstColumn(orientation); + const int row = item->firstRow(orientation); + if (item->hasDynamicConstraint()) { + const qreal sz = widths[col]; + QGridLayoutBox box = item->box(orientation, sz); + rowData.boxes[row].combine(box); + } + } + + QGridLayoutBox &totalBox = q_totalBoxes[orientation == Qt::Vertical]; + totalBox = rowData.totalBox(0, rCount); + rowData.calculateGeometries(0, rCount, oSize.height(), yy, heights, + ydescents, totalBox); q_cachedSize = size; } diff --git a/src/gui/graphicsview/qgridlayoutengine_p.h b/src/gui/graphicsview/qgridlayoutengine_p.h index 9ac9a8e..580af7e 100644 --- a/src/gui/graphicsview/qgridlayoutengine_p.h +++ b/src/gui/graphicsview/qgridlayoutengine_p.h @@ -91,6 +91,14 @@ enum LayoutSide { Bottom }; +enum { + NoConstraint, + HorizontalConstraint, + VerticalConstraint, + UnknownConstraint, // need to update cache + UnfeasibleConstraint // not feasible, it be has some items with Vertical and others with Horizontal constraints +}; + template class QLayoutParameter { @@ -270,6 +278,10 @@ public: inline void setAlignment(Qt::Alignment alignment) { q_alignment = alignment; } QSizePolicy::Policy sizePolicy(Qt::Orientation orientation) const; + + bool hasDynamicConstraint() const; + Qt::Orientation dynamicConstraintOrientation() const; + QSizePolicy::ControlTypes controlTypes(LayoutSide side) const; QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; QGridLayoutBox box(Qt::Orientation orientation, qreal constraint = -1.0) const; @@ -280,7 +292,7 @@ public: void setGeometry(const QRectF &rect); void transpose(); void insertOrRemoveRows(int row, int delta, Qt::Orientation orientation = Qt::Vertical); - QSizeF effectiveMaxSize() const; + QSizeF effectiveMaxSize(const QSizeF &constraint) const; #ifdef QT_DEBUG void dump(int indent = 0) const; @@ -372,6 +384,14 @@ public: int column, int rowSpan, int columnSpan) const; QSizeF sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHint which, const QSizeF &constraint) const; + + // heightForWidth / widthForHeight support + QSizeF dynamicallyConstrainedSizeHint(Qt::SizeHint which, const QSizeF &constraint) const; + bool ensureDynamicConstraint() const; + bool hasDynamicConstraint() const; + Qt::Orientation constraintOrientation() const; + + QSizePolicy::ControlTypes controlTypes(LayoutSide side) const; void transpose(); void setVisualDirection(Qt::LayoutDirection direction); @@ -405,6 +425,7 @@ private: // Lazily computed from the above user input mutable int q_cachedEffectiveFirstRows[NOrientations]; mutable int q_cachedEffectiveLastRows[NOrientations]; + mutable quint8 q_cachedConstraintOrientation : 2; // Layout item input mutable QLayoutStyleInfo q_cachedDataForStyleInfo; diff --git a/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp b/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp index 5b03767..03c1d5b 100644 --- a/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp +++ b/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp @@ -107,12 +107,13 @@ private slots: void avoidRecursionInInsertItem(); void styleInfoLeak(); void task236367_maxSizeHint(); + void heightForWidth(); }; class RectWidget : public QGraphicsWidget { public: - RectWidget(QGraphicsItem *parent = 0) : QGraphicsWidget(parent){} + RectWidget(QGraphicsItem *parent = 0) : QGraphicsWidget(parent), m_fnConstraint(0) {} void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { @@ -125,9 +126,12 @@ public: QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const { - if (m_sizeHints[which].isValid()) { + if (constraint.width() < 0 && constraint.height() < 0 && m_sizeHints[which].isValid()) { return m_sizeHints[which]; } + if (m_fnConstraint) { + return m_fnConstraint(which, constraint); + } return QGraphicsWidget::sizeHint(which, constraint); } @@ -136,7 +140,13 @@ public: updateGeometry(); } + void setConstraintFunction(QSizeF (*fnConstraint)(Qt::SizeHint, const QSizeF &)) { + m_fnConstraint = fnConstraint; + } + QSizeF m_sizeHints[Qt::NSizeHints]; + QSizeF (*m_fnConstraint)(Qt::SizeHint, const QSizeF &); + }; struct ItemDesc @@ -146,7 +156,8 @@ struct ItemDesc m_rowSpan(1), m_colSpan(1), m_sizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred)), - m_align(0) + m_align(0), + m_fnConstraint(0) { } @@ -213,8 +224,20 @@ struct ItemDesc return (*this); } + ItemDesc &heightForWidth(QSizeF (*fnConstraint)(Qt::SizeHint, const QSizeF &)) { + m_fnConstraint = fnConstraint; + m_constraintOrientation = Qt::Vertical; + return (*this); + } + void apply(QGraphicsGridLayout *layout, QGraphicsWidget *item) { - item->setSizePolicy(m_sizePolicy); + QSizePolicy sp = m_sizePolicy; + if (m_fnConstraint) { + sp.setHeightForWidth(m_constraintOrientation == Qt::Vertical); + //sp.setWidthForHeight(m_constraintOrientation == Qt::Horizontal); + } + + item->setSizePolicy(sp); for (int i = 0; i < Qt::NSizeHints; ++i) { if (!m_sizes[i].isValid()) continue; @@ -233,6 +256,7 @@ struct ItemDesc break; } } + layout->addItem(item, m_pos.first, m_pos.second, m_rowSpan, m_colSpan); layout->setAlignment(item, m_align); } @@ -240,6 +264,7 @@ struct ItemDesc void apply(QGraphicsGridLayout *layout, RectWidget *item) { for (int i = 0; i < Qt::NSizeHints; ++i) item->setSizeHint((Qt::SizeHint)i, m_sizeHints[i]); + item->setConstraintFunction(m_fnConstraint); apply(layout, static_cast(item)); } @@ -251,6 +276,9 @@ struct ItemDesc QSizeF m_sizeHints[Qt::NSizeHints]; QSizeF m_sizes[Qt::NSizeHints]; Qt::Alignment m_align; + + Qt::Orientation m_constraintOrientation; + QSizeF (*m_fnConstraint)(Qt::SizeHint, const QSizeF &); }; typedef QList ItemList; @@ -2116,6 +2144,17 @@ void tst_QGraphicsGridLayout::alignment2() delete widget; } +static QSizeF hfw1(Qt::SizeHint, const QSizeF &constraint) +{ + QSizeF result(constraint); + if (constraint.width() < 0 && constraint.height() < 0) { + return QSizeF(50, 400); + } else if (constraint.width() >= 0) { + result.setHeight(20000./constraint.width()); + } + return result; +} + void tst_QGraphicsGridLayout::geometries_data() { @@ -2145,6 +2184,186 @@ void tst_QGraphicsGridLayout::geometries_data() << QRectF(0, 0, 60,10) << QRectF(0, 10, 60,10) ); + // change layout height and verify + QTest::newRow("hfw-h401") << (ItemList() + << ItemDesc(0,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(0,1) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,1) + .minSize(QSizeF(40,40)) + .preferredSize(QSizeF(50,400)) + .maxSize(QSizeF(500, 500)) + .heightForWidth(hfw1) + ) + << QSizeF(100, 401) + << (RectList() + << QRectF(0, 0, 50, 1) << QRectF(50, 0, 50, 1) + << QRectF(0, 1, 50,100) << QRectF(50, 1, 50,400) + ); + + + QTest::newRow("hfw-h408") << (ItemList() + << ItemDesc(0,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(0,1) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,1) + .minSize(QSizeF(40,40)) + .preferredSize(QSizeF(50,400)) + .maxSize(QSizeF(500, 500)) + .heightForWidth(hfw1) + ) + << QSizeF(100, 408) + << (RectList() + << QRectF(0, 0, 50, 8) << QRectF(50, 0, 50, 8) + << QRectF(0, 8, 50,100) << QRectF(50, 8, 50,400) + ); + + QTest::newRow("hfw-h410") << (ItemList() + << ItemDesc(0,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(0,1) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,1) + .minSize(QSizeF(40,40)) + .preferredSize(QSizeF(50,400)) + .maxSize(QSizeF(500, 500)) + .heightForWidth(hfw1) + ) + << QSizeF(100, 410) + << (RectList() + << QRectF(0, 0, 50,10) << QRectF(50, 0, 50,10) + << QRectF(0, 10, 50,100) << QRectF(50, 10, 50,400) + ); + + QTest::newRow("hfw-h470") << (ItemList() + << ItemDesc(0,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(0,1) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,1) + .minSize(QSizeF(40,40)) + .preferredSize(QSizeF(50,400)) + .maxSize(QSizeF(500, 500)) + .heightForWidth(hfw1) + ) + << QSizeF(100, 470) + << (RectList() + << QRectF(0, 0, 50,70) << QRectF(50, 0, 50,70) + << QRectF(0, 70, 50,100) << QRectF(50, 70, 50,400) + ); + + + // change layout width and verify + QTest::newRow("hfw-w100") << (ItemList() + << ItemDesc(0,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(0,1) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,1) + .minSize(QSizeF(40,40)) + .preferredSize(QSizeF(50,400)) + .maxSize(QSizeF(5000, 5000)) + .heightForWidth(hfw1) + ) + << QSizeF(100, 401) + << (RectList() + << QRectF( 0, 0, 50, 1) << QRectF( 50, 0, 50, 1) + << QRectF( 0, 1, 50, 100) << QRectF( 50, 1, 50, 400) + ); + + QTest::newRow("hfw-w160") << (ItemList() + << ItemDesc(0,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(0,1) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,1) + .minSize(QSizeF(40,40)) + .preferredSize(QSizeF(50,400)) + .maxSize(QSizeF(5000, 5000)) + .heightForWidth(hfw1) + ) + << QSizeF(160, 401) + << (RectList() + << QRectF( 0, 0, 80, 100) << QRectF( 80, 0, 80, 100) + << QRectF( 0, 100, 80, 100) << QRectF( 80, 100, 80, 250) + ); + + + QTest::newRow("hfw-w500") << (ItemList() + << ItemDesc(0,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(0,1) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,10)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,1) + .minSize(QSizeF(40,40)) + .preferredSize(QSizeF(50,400)) + .maxSize(QSizeF(5000, 5000)) + .heightForWidth(hfw1) + ) + << QSizeF(500, 401) + << (RectList() + << QRectF( 0, 0, 100, 100) << QRectF(100, 0, 100, 100) + << QRectF( 0, 100, 100, 100) << QRectF(100, 100, 400, 50) + ); + } void tst_QGraphicsGridLayout::geometries() @@ -2215,6 +2434,143 @@ void tst_QGraphicsGridLayout::task236367_maxSizeHint() QCOMPARE(widget->size(), QSizeF(w, h)); } +/* +static qreal hfw(qreal w) +{ + if (w == 0) + return 20000; + return 20000/w; +} +*/ +static QSizeF hfw(Qt::SizeHint /*which*/, const QSizeF &constraint) +{ + QSizeF result(constraint); + const qreal cw = constraint.width(); + const qreal ch = constraint.height(); + if (cw < 0 && ch < 0) { + return QSizeF(200, 100); + } else if (cw >= 0) { + result.setHeight(20000./cw); + } else if (cw == 0) { + result.setHeight(20000); + } else if (ch >= 0) { + result.setWidth(20000./ch); + } else if (ch == 0) { + result.setWidth(20000); + } + + return result; +} + +static qreal growthFactorBelowPreferredSize(qreal desired, qreal sumAvailable, qreal sumDesired) +{ + Q_ASSERT(sumDesired != 0.0); + return desired * qPow(sumAvailable / sumDesired, desired / sumDesired); +} + +static void expectedWidth(qreal minSize1, qreal prefSize1, + qreal minSize2, qreal prefSize2, + qreal targetSize, qreal *width1, qreal *width2) +{ + qreal sumAvail,factor1,factor2; + // stretch behaviour is different below and above preferred size... + if (targetSize < prefSize1 + prefSize2) { + sumAvail = targetSize - minSize1 - minSize2; + const qreal desired1 = prefSize1 - minSize1; + const qreal desired2 = prefSize2 - minSize2; + const qreal sumDesired = desired1 + desired2; + factor1 = growthFactorBelowPreferredSize(desired1, sumAvail, sumDesired); + factor2 = growthFactorBelowPreferredSize(desired2, sumAvail, sumDesired); + const qreal sumFactors = factor1 + factor2; + *width1 = sumAvail*factor1/sumFactors + minSize1; + *width2 = sumAvail*factor2/sumFactors + minSize2; + } else { + sumAvail = targetSize - prefSize1 - prefSize2; + factor1 = prefSize1; + factor2 = prefSize2; + const qreal sumFactors = factor1 + factor2; + *width1 = sumAvail*factor1/sumFactors + prefSize1; + *width2 = sumAvail*factor2/sumFactors + prefSize2; + } +} + + +bool qFuzzyCompare(const QSizeF &a, const QSizeF &b) +{ + return qFuzzyCompare(a.width(), b.width()) && qFuzzyCompare(a.height(), b.height()); +} + +void tst_QGraphicsGridLayout::heightForWidth() +{ + QGraphicsWidget *widget = new QGraphicsWidget; + QGraphicsGridLayout *layout = new QGraphicsGridLayout; + widget->setLayout(layout); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + RectWidget *w00 = new RectWidget; + w00->setSizeHint(Qt::MinimumSize, QSizeF(1,1)); + w00->setSizeHint(Qt::PreferredSize, QSizeF(10,10)); + w00->setSizeHint(Qt::MaximumSize, QSizeF(100,100)); + layout->addItem(w00, 0, 0); + + RectWidget *w01 = new RectWidget; + w01->setSizeHint(Qt::MinimumSize, QSizeF(1,1)); + w01->setSizeHint(Qt::PreferredSize, QSizeF(10,10)); + w01->setSizeHint(Qt::MaximumSize, QSizeF(100,100)); + layout->addItem(w01, 0, 1); + + RectWidget *w10 = new RectWidget; + w10->setSizeHint(Qt::MinimumSize, QSizeF(1,1)); + w10->setSizeHint(Qt::PreferredSize, QSizeF(10,10)); + w10->setSizeHint(Qt::MaximumSize, QSizeF(100,100)); + layout->addItem(w10, 1, 0); + + RectWidget *w11 = new RectWidget; + w11->setSizeHint(Qt::MinimumSize, QSizeF(1,1)); + w11->setSizeHint(Qt::MaximumSize, QSizeF(30000,30000)); + w11->setConstraintFunction(hfw); + QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred); + sp.setHeightForWidth(true); + w11->setSizePolicy(sp); + layout->addItem(w11, 1, 1); + + QSizeF prefSize = layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, -1)); + QCOMPARE(prefSize, QSizeF(10+200, 10+100)); + + QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(2, -1)), QSizeF(2, 20001)); + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(2, -1)), QSizeF(2, 20010)); + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(2, -1)), QSizeF(2, 20100)); + qreal width1; + qreal width2; + expectedWidth(1, 10, 1, 200, 20, &width1, &width2); + QSizeF expectedSize = hfw(Qt::MinimumSize, QSizeF(width2, -1)) + QSizeF(width1, 1); + QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(20, -1)), expectedSize); + expectedSize.rheight()+=9; + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(20, -1)), expectedSize); + expectedSize.rheight()+=90; + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(20, -1)), expectedSize); + + expectedWidth(1, 10, 1, 200, 300, &width1, &width2); + expectedSize = hfw(Qt::MinimumSize, QSizeF(width2, -1)) + QSizeF(width1, 1); + QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(300, -1)), expectedSize); + expectedSize.rheight()+=9; + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(300, -1)), expectedSize); + // the height of the hfw widget is shorter than the one to the left, which is 100, so + // the total height of the last row is 100 (which leaves the layout height to be 200) + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(300, -1)), QSizeF(300, 200)); + + // the hfw item is shorter than the item to the left + expectedWidth(1, 10, 1, 200, 500, &width1, &width2); + expectedSize = hfw(Qt::MinimumSize, QSizeF(width2, -1)) + QSizeF(width1, 1); + QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(500, -1)), expectedSize); + expectedSize.rheight()+=9; + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(500, -1)), expectedSize); + // the height of the hfw widget is shorter than the one to the left, which is 100, so + // the total height of the last row is 100 (which leaves the layout height to be 200) + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(500, -1)), QSizeF(500, 200)); + +} + QTEST_MAIN(tst_QGraphicsGridLayout) #include "tst_qgraphicsgridlayout.moc" -- cgit v0.12 From 6d4d265e7e67dde58e45d7d89f4974d0bd8b70e4 Mon Sep 17 00:00:00 2001 From: John Tapsell Date: Mon, 4 Oct 2010 01:03:41 +0100 Subject: QGridLayoutEngine - Rework height-for-width support so that row/col spanning works Task-number: QTBUG-13547 Reviewed-by: Olivier Goffart Merge-request: 847 --- src/gui/graphicsview/qgridlayoutengine.cpp | 300 ++++++++------------- src/gui/graphicsview/qgridlayoutengine_p.h | 13 +- .../tst_qgraphicsgridlayout.cpp | 35 +++ 3 files changed, 157 insertions(+), 191 deletions(-) diff --git a/src/gui/graphicsview/qgridlayoutengine.cpp b/src/gui/graphicsview/qgridlayoutengine.cpp index 1e3addc..acac46f 100644 --- a/src/gui/graphicsview/qgridlayoutengine.cpp +++ b/src/gui/graphicsview/qgridlayoutengine.cpp @@ -1102,20 +1102,76 @@ QRectF QGridLayoutEngine::cellRect(const QLayoutStyleInfo &styleInfo, QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHint which, const QSizeF &constraint) const { - ensureColumnAndRowData(styleInfo); + QGridLayoutBox sizehint_totalBoxes[NOrientations]; - if (hasDynamicConstraint()) - return dynamicallyConstrainedSizeHint(which, constraint); + if(rowCount() < 1 || columnCount() < 1 || !hasDynamicConstraint()) { + //No items with height for width, so it doesn't matter which order we do these in + if(q_cachedDataForStyleInfo != styleInfo) { + ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal); + ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical); + } else { + sizehint_totalBoxes[Hor] = q_totalBoxes[Hor]; + sizehint_totalBoxes[Ver] = q_totalBoxes[Ver]; + } + } else if(constraintOrientation() == Qt::Vertical) { + //We have items whose width depends on their height + if(q_cachedDataForStyleInfo != styleInfo) + ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal); + else + sizehint_totalBoxes[Hor] = q_totalBoxes[Hor]; + QVector sizehint_xx; + QVector sizehint_widths; + + sizehint_xx.resize(columnCount()); + sizehint_widths.resize(columnCount()); + qreal width = constraint.width(); + if(width < 0) { + /* It's not obvious what the behaviour should be. */ +/* if(which == Qt::MaximumSize) + width = sizehint_totalBoxes[Hor].q_maximumSize; + else if(which == Qt::MinimumSize) + width = sizehint_totalBoxes[Hor].q_minimumSize; + else*/ + width = sizehint_totalBoxes[Hor].q_preferredSize; + } + //Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as + //constraints to find the row heights + q_columnData.calculateGeometries(0, columnCount(), width, sizehint_xx.data(), sizehint_widths.data(), + 0, sizehint_totalBoxes[Hor]); + ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], styleInfo, sizehint_xx.data(), sizehint_widths.data(), Qt::Vertical); + } else { + //We have items whose height depends on their width + ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical); + QVector sizehint_yy; + QVector sizehint_heights; + + sizehint_yy.resize(rowCount()); + sizehint_heights.resize(rowCount()); + qreal height = constraint.height(); + if(height < 0) { +/* if(which == Qt::MaximumSize) + height = sizehint_totalBoxes[Ver].q_maximumSize; + else if(which == Qt::MinimumSize) + height = sizehint_totalBoxes[Ver].q_minimumSize; + else*/ + height = sizehint_totalBoxes[Ver].q_preferredSize; + } + //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as + //constraints to find the column widths + q_rowData.calculateGeometries(0, rowCount(), height, sizehint_yy.data(), sizehint_heights.data(), + 0, sizehint_totalBoxes[Ver]); + ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], styleInfo, sizehint_yy.data(), sizehint_heights.data(), Qt::Vertical); + } switch (which) { case Qt::MinimumSize: - return QSizeF(q_totalBoxes[Hor].q_minimumSize, q_totalBoxes[Ver].q_minimumSize); + return QSizeF(sizehint_totalBoxes[Hor].q_minimumSize, sizehint_totalBoxes[Ver].q_minimumSize); case Qt::PreferredSize: - return QSizeF(q_totalBoxes[Hor].q_preferredSize, q_totalBoxes[Ver].q_preferredSize); + return QSizeF(sizehint_totalBoxes[Hor].q_preferredSize, sizehint_totalBoxes[Ver].q_preferredSize); case Qt::MaximumSize: - return QSizeF(q_totalBoxes[Hor].q_maximumSize, q_totalBoxes[Ver].q_maximumSize); + return QSizeF(sizehint_totalBoxes[Hor].q_maximumSize, sizehint_totalBoxes[Ver].q_maximumSize); case Qt::MinimumDescent: - return QSizeF(-1.0, q_totalBoxes[Hor].q_minimumDescent); // ### doesn't work + return QSizeF(-1.0, sizehint_totalBoxes[Hor].q_minimumDescent); // ### doesn't work default: break; } @@ -1291,6 +1347,7 @@ void QGridLayoutEngine::insertOrRemoveRows(int row, int delta, Qt::Orientation o } void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutStyleInfo &styleInfo, + qreal *colPositions, qreal *colSizes, Qt::Orientation orientation) const { const int ButtonMask = QSizePolicy::ButtonBox | QSizePolicy::PushButton; @@ -1404,11 +1461,21 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutSt box = &multiCell.q_box; multiCell.q_stretch = itemStretch; } - // Items with constraints are not included in the orientation that - // they are constrained (since it depends on the hfw/constraint function). - // They must be combined at a later stage. - if (!item->hasDynamicConstraint() || orientation != item->dynamicConstraintOrientation()) + // Items with constraints need to be passed the constraint + if (colSizes && colPositions && item->hasDynamicConstraint() && orientation == item->dynamicConstraintOrientation()) { + /* Get the width of the item by summing up the widths of the columns that it spans. + * We need to have already calculated the widths of the columns by calling + * q_columns->calculateGeometries() before hand and passing the value in the colSizes + * and colPositions parameters. + * The variable name is still colSizes even when it actually has the row sizes + */ + qreal length = colSizes[item->lastColumn(orientation)]; + if (item->columnSpan(orientation) != 1) + length += colPositions[item->lastColumn(orientation)] - colPositions[item->firstColumn(orientation)]; + box->combine(item->box(orientation, length)); + } else { box->combine(item->box(orientation)); + } if (effectiveRowSpan == 1) { QSizePolicy::ControlTypes controls = item->controlTypes(top); @@ -1545,115 +1612,18 @@ void QGridLayoutEngine::ensureEffectiveFirstAndLastRows() const } } -void QGridLayoutEngine::ensureColumnAndRowData(const QLayoutStyleInfo &styleInfo) const +void QGridLayoutEngine::ensureColumnAndRowData(QGridLayoutRowData *rowData, QGridLayoutBox *totalBox, + const QLayoutStyleInfo &styleInfo, + qreal *colPositions, qreal *colSizes, + Qt::Orientation orientation) const { - if (q_cachedDataForStyleInfo == styleInfo) - return; - - q_columnData.reset(columnCount()); - q_rowData.reset(rowCount()); - - fillRowData(&q_columnData, styleInfo, Qt::Horizontal); - fillRowData(&q_rowData, styleInfo, Qt::Vertical); - - q_columnData.distributeMultiCells(); - q_rowData.distributeMultiCells(); - - q_totalBoxes[Hor] = q_columnData.totalBox(0, columnCount()); - q_totalBoxes[Ver] = q_rowData.totalBox(0, rowCount()); - - q_cachedDataForStyleInfo = styleInfo; + rowData->reset(rowCount(orientation)); + fillRowData(rowData, styleInfo, colPositions, colSizes, orientation); + rowData->distributeMultiCells(); + *totalBox = rowData->totalBox(0, rowCount(orientation)); + //We have items whose width depends on their height } -QSizeF QGridLayoutEngine::dynamicallyConstrainedSizeHint(Qt::SizeHint which, - const QSizeF &constraint) const -{ - Q_ASSERT(hasDynamicConstraint()); - if (constraint.width() < 0 && constraint.height() < 0) { - // Process the hfw / wfh items that we did not process in fillRowData() - const Qt::Orientation constraintOrient = constraintOrientation(); - - QGridLayoutRowData rowData = constraintOrient == Qt::Vertical ? q_rowData : q_columnData; - for (int i = q_items.count() - 1; i >= 0; --i) { - QGridLayoutItem *item = q_items.at(i); - if (item->hasDynamicConstraint()) { - QGridLayoutBox box = item->box(constraintOrient); - QGridLayoutBox &rowBox = rowData.boxes[item->firstRow(constraintOrient)]; - rowBox.combine(box); - } - } - - QGridLayoutBox totalBoxes[2]; - if (constraintOrient == Qt::Vertical) { - totalBoxes[Hor] = q_columnData.totalBox(0, columnCount()); - totalBoxes[Ver] = rowData.totalBox(0, rowCount()); - } else { - totalBoxes[Hor] = rowData.totalBox(0, columnCount()); - totalBoxes[Ver] = q_rowData.totalBox(0, rowCount()); - } - return QSizeF(totalBoxes[Hor].q_sizes(which), totalBoxes[Ver].q_sizes(which)); - } - - - Q_ASSERT(constraint.width() >= 0 || constraint.height() >= 0); - q_xx.resize(columnCount()); - q_yy.resize(rowCount()); - q_widths.resize(columnCount()); - q_heights.resize(rowCount()); - q_descents.resize(rowCount()); - - - const Qt::Orientation orientation = constraintOrientation(); - QGridLayoutRowData *colData; - QGridLayoutRowData constrainedRowData; - QGridLayoutBox *totalBox; - qreal *sizes; - qreal *pos; - qreal *descents; - qreal targetSize; - qreal cCount; - qreal rCount; - - if (orientation == Qt::Vertical) { - // height for width - colData = &q_columnData; - totalBox = &q_totalBoxes[Hor]; - sizes = q_widths.data(); - pos = q_xx.data(); - descents = 0; - targetSize = constraint.width(); - cCount = columnCount(); - rCount = rowCount(); - constrainedRowData = q_rowData; - } else { - // width for height - colData = &q_rowData; - totalBox = &q_totalBoxes[Ver]; - sizes = q_heights.data(); - pos = q_yy.data(); - descents = q_descents.data(); - targetSize = constraint.height(); - cCount = rowCount(); - rCount = columnCount(); - constrainedRowData = q_columnData; - } - colData->calculateGeometries(0, cCount, targetSize, pos, sizes, descents, *totalBox); - for (int i = q_items.count() - 1; i >= 0; --i) { - QGridLayoutItem *item = q_items.at(i); - - if (item->hasDynamicConstraint()) { - const qreal size = sizes[item->firstColumn(orientation)]; - QGridLayoutBox box = item->box(orientation, size); - QGridLayoutBox &rowBox = constrainedRowData.boxes[item->firstRow(orientation)]; - rowBox.combine(box); - } - } - const qreal newSize = constrainedRowData.totalBox(0, rCount).q_sizes(which); - - return (orientation == Qt::Vertical) ? QSizeF(targetSize, newSize) : QSizeF(newSize, targetSize); -} - - /** returns false if the layout has contradicting constraints (i.e. some items with a horizontal constraint and other items with a vertical constraint) @@ -1700,85 +1670,41 @@ Qt::Orientation QGridLayoutEngine::constraintOrientation() const void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo, const QSizeF &size) const { - ensureColumnAndRowData(styleInfo); - if (q_cachedSize == size) + if (q_cachedDataForStyleInfo == styleInfo && q_cachedSize == size) return; + q_cachedDataForStyleInfo = styleInfo; + q_cachedSize = size; + q_xx.resize(columnCount()); - q_yy.resize(rowCount()); q_widths.resize(columnCount()); + q_yy.resize(rowCount()); q_heights.resize(rowCount()); q_descents.resize(rowCount()); - - Qt::Orientation orientation = Qt::Vertical; - if (hasDynamicConstraint()) - orientation = constraintOrientation(); - - /* - In order to do hfw we need to first distribute the columns, then the rows. - In order to do wfh we need to first distribute the rows, then the columns. - - If there is no constraint, the order of distributing the rows or columns first is irrelevant. - We choose horizontal just to keep the same behaviour as before (however, there shouldn't - be any behaviour difference). - */ - - QGridLayoutRowData *colData; - QGridLayoutRowData rowData; - qreal *widths; - qreal *heights; - qreal *xx; - qreal *yy; - qreal *xdescents = 0; - qreal *ydescents = 0; - qreal cCount; - qreal rCount; - QSizeF oSize = size; - if (orientation == Qt::Vertical) { - // height for width - colData = &q_columnData; - rowData = q_rowData; - widths = q_widths.data(); - heights = q_heights.data(); - xx = q_xx.data(); - yy = q_yy.data(); - cCount = columnCount(); - rCount = rowCount(); - ydescents = q_descents.data(); + if(constraintOrientation() != Qt::Horizontal) { + //We might have items whose width depends on their height + ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal); + //Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as + //constraints to find the row heights + q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(), + 0, q_totalBoxes[Hor]); + ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], styleInfo, q_xx.data(), q_widths.data(), Qt::Vertical); + //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() + q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(), + q_descents.data(), q_totalBoxes[Ver]); } else { - // width for height - colData = &q_rowData; - rowData = q_columnData; - widths = q_heights.data(); - heights = q_widths.data(); - xx = q_yy.data(); - yy = q_xx.data(); - cCount = rowCount(); - rCount = columnCount(); - xdescents = q_descents.data(); - oSize.transpose(); + //We have items whose height depends on their width + ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical); + //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as + //constraints to find the column widths + q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(), + q_descents.data(), q_totalBoxes[Ver]); + ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], styleInfo, q_yy.data(), q_heights.data(), Qt::Horizontal); + //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() + q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(), + 0, q_totalBoxes[Hor]); } - - colData->calculateGeometries(0, cCount, oSize.width(), xx, widths, - xdescents, q_totalBoxes[orientation == Qt::Horizontal]); - for (int i = q_items.count() - 1; i >= 0; --i) { - QGridLayoutItem *item = q_items.at(i); - const int col = item->firstColumn(orientation); - const int row = item->firstRow(orientation); - if (item->hasDynamicConstraint()) { - const qreal sz = widths[col]; - QGridLayoutBox box = item->box(orientation, sz); - rowData.boxes[row].combine(box); - } - } - - QGridLayoutBox &totalBox = q_totalBoxes[orientation == Qt::Vertical]; - totalBox = rowData.totalBox(0, rCount); - rowData.calculateGeometries(0, rCount, oSize.height(), yy, heights, - ydescents, totalBox); - - q_cachedSize = size; } QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgridlayoutengine_p.h b/src/gui/graphicsview/qgridlayoutengine_p.h index 580af7e..02c74b0 100644 --- a/src/gui/graphicsview/qgridlayoutengine_p.h +++ b/src/gui/graphicsview/qgridlayoutengine_p.h @@ -93,8 +93,8 @@ enum LayoutSide { enum { NoConstraint, - HorizontalConstraint, - VerticalConstraint, + HorizontalConstraint, // Width depends on the height + VerticalConstraint, // Height depends on the width UnknownConstraint, // need to update cache UnfeasibleConstraint // not feasible, it be has some items with Vertical and others with Horizontal constraints }; @@ -410,9 +410,14 @@ private: void setItemAt(int row, int column, QGridLayoutItem *item); void insertOrRemoveRows(int row, int delta, Qt::Orientation orientation = Qt::Vertical); void fillRowData(QGridLayoutRowData *rowData, const QLayoutStyleInfo &styleInfo, - Qt::Orientation orientation = Qt::Vertical) const; + qreal *colPositions, qreal *colSizes, + Qt::Orientation orientation = Qt::Vertical) const; void ensureEffectiveFirstAndLastRows() const; - void ensureColumnAndRowData(const QLayoutStyleInfo &styleInfo) const; + void ensureColumnAndRowData(QGridLayoutRowData *rowData, QGridLayoutBox *totalBox, + const QLayoutStyleInfo &styleInfo, + qreal *colPositions, qreal *colSizes, + Qt::Orientation orientation) const; + void ensureGeometries(const QLayoutStyleInfo &styleInfo, const QSizeF &size) const; // User input diff --git a/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp b/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp index 03c1d5b..3827018 100644 --- a/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp +++ b/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp @@ -108,6 +108,7 @@ private slots: void styleInfoLeak(); void task236367_maxSizeHint(); void heightForWidth(); + void heightForWidthWithSpanning(); }; class RectWidget : public QGraphicsWidget @@ -2571,6 +2572,40 @@ void tst_QGraphicsGridLayout::heightForWidth() } +void tst_QGraphicsGridLayout::heightForWidthWithSpanning() +{ + QGraphicsWidget *widget = new QGraphicsWidget; + QGraphicsGridLayout *layout = new QGraphicsGridLayout; + widget->setLayout(layout); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + + RectWidget *w = new RectWidget; + w->setSizeHint(Qt::MinimumSize, QSizeF(1,1)); + w->setSizeHint(Qt::MaximumSize, QSizeF(30000,30000)); + w->setConstraintFunction(hfw); + QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred); + sp.setHeightForWidth(true); + w->setSizePolicy(sp); + layout->addItem(w, 0,0,2,2); + + QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, -1)), QSizeF(1, 100)); + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, -1)), QSizeF(200, 100)); + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, -1)), QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); + + QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(200, -1)), QSizeF(200, 100)); + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(200, -1)), QSizeF(200, 100)); + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(200, -1)), QSizeF(200, QWIDGETSIZE_MAX)); + + QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(2, -1)), QSizeF(2, 10000)); + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(2, -1)), QSizeF(2, 10000)); + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(2, -1)), QSizeF(2, QWIDGETSIZE_MAX)); + + QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(200, -1)), QSizeF(200, 100)); + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(200, -1)), QSizeF(200, 100)); + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(200, -1)), QSizeF(200, QWIDGETSIZE_MAX)); +} + QTEST_MAIN(tst_QGraphicsGridLayout) #include "tst_qgraphicsgridlayout.moc" -- cgit v0.12 From fcda1b785bd7d86011f49bfe96cb22b04202933f Mon Sep 17 00:00:00 2001 From: John Tapsell Date: Fri, 8 Oct 2010 15:10:20 +0100 Subject: QGraphicsLayoutItem - user set sizes should always override, even if there's a constraint Notes: * I have had to remove some of the old unit tests because the tested for strange behaviour. Now that height for width items behave more like normal items, it's no longer so easy to calculate what the geometries should be in strangely-sized layouts. * This also fixes alignment of height-for-width objects and adds a unit test for this. This couldn't be done in a seperate commit since the two fixes are related. Merge-request: 847 Reviewed-by: Olivier Goffart --- src/gui/graphicsview/qgraphicslayoutitem.cpp | 4 +- src/gui/graphicsview/qgridlayoutengine.cpp | 17 +- .../tst_qgraphicsgridlayout.cpp | 333 +++++++++++---------- 3 files changed, 188 insertions(+), 166 deletions(-) diff --git a/src/gui/graphicsview/qgraphicslayoutitem.cpp b/src/gui/graphicsview/qgraphicslayoutitem.cpp index 634f68c..e43f7fa 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem.cpp +++ b/src/gui/graphicsview/qgraphicslayoutitem.cpp @@ -140,11 +140,9 @@ QSizeF *QGraphicsLayoutItemPrivate::effectiveSizeHints(const QSizeF &constraint) if (!sizeHintCacheDirty && cachedConstraint == constraint) return cachedSizeHints; - const bool hasConstraint = constraint.width() >= 0 || constraint.height() >= 0; - for (int i = 0; i < Qt::NSizeHints; ++i) { cachedSizeHints[i] = constraint; - if (userSizeHints && !hasConstraint) + if (userSizeHints) combineSize(cachedSizeHints[i], userSizeHints[i]); } diff --git a/src/gui/graphicsview/qgridlayoutengine.cpp b/src/gui/graphicsview/qgridlayoutengine.cpp index acac46f..e486b4d 100644 --- a/src/gui/graphicsview/qgridlayoutengine.cpp +++ b/src/gui/graphicsview/qgridlayoutengine.cpp @@ -631,14 +631,17 @@ QRectF QGridLayoutItem::geometryWithin(qreal x, qreal y, qreal width, qreal heig qreal cellWidth = width; qreal cellHeight = height; - QSize constraint; + + QSizeF size = effectiveMaxSize(QSizeF(-1,-1)); if (hasDynamicConstraint()) { - if (dynamicConstraintOrientation() == Qt::Vertical) - constraint.setWidth(cellWidth); - else - constraint.setHeight(cellHeight); + if (dynamicConstraintOrientation() == Qt::Vertical) { + if (size.width() > cellWidth) + size = effectiveMaxSize(QSizeF(cellWidth, -1)); + } else if(size.height() > cellHeight) { + size = effectiveMaxSize(QSizeF(-1, cellHeight)); + } } - QSizeF size = effectiveMaxSize(constraint).boundedTo(QSizeF(cellWidth, cellHeight)); + size = size.boundedTo(QSizeF(cellWidth, cellHeight)); width = size.width(); height = size.height(); @@ -714,7 +717,7 @@ QSizeF QGridLayoutItem::effectiveMaxSize(const QSizeF &constraint) const } if (!size.isValid()) { - QSizeF maxSize = layoutItem()->effectiveSizeHint(Qt::MaximumSize, constraint); + QSizeF maxSize = layoutItem()->effectiveSizeHint(Qt::MaximumSize, size); if (size.width() == -1) size.setWidth(maxSize.width()); if (size.height() == -1) diff --git a/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp b/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp index 3827018..174e4aa 100644 --- a/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp +++ b/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp @@ -61,13 +61,19 @@ private slots: void qgraphicsgridlayout(); void addItem_data(); void addItem(); + void alignment_data(); void alignment(); void alignment2(); void alignment2_data(); + void columnAlignment_data(); void columnAlignment(); + void columnCount_data(); void columnCount(); + void columnMaximumWidth_data(); void columnMaximumWidth(); + void columnMinimumWidth_data(); void columnMinimumWidth(); + void columnPreferredWidth_data(); void columnPreferredWidth(); void setColumnFixedWidth(); void columnSpacing(); @@ -78,12 +84,18 @@ private slots: void horizontalSpacing(); void itemAt(); void removeAt(); + void rowAlignment_data(); void rowAlignment(); + void rowCount_data(); void rowCount(); + void rowMaximumHeight_data(); void rowMaximumHeight(); + void rowMinimumHeight_data(); void rowMinimumHeight(); + void rowPreferredHeight_data(); void rowPreferredHeight(); void rowSpacing(); + void rowStretchFactor_data(); void rowStretchFactor(); void setColumnSpacing_data(); void setColumnSpacing(); @@ -98,6 +110,7 @@ private slots: void sizeHint(); void verticalSpacing_data(); void verticalSpacing(); + void layoutDirection_data(); void layoutDirection(); void removeLayout(); void defaultStretchFactors_data(); @@ -371,7 +384,7 @@ void tst_QGraphicsGridLayout::qgraphicsgridlayout() layout.verticalSpacing(); } -static void populateLayout(QGraphicsGridLayout *gridLayout, int width, int height) +static void populateLayout(QGraphicsGridLayout *gridLayout, int width, int height, bool hasHeightForWidth = false) { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { @@ -380,6 +393,9 @@ static void populateLayout(QGraphicsGridLayout *gridLayout, int width, int heigh item->setPreferredSize(25, 25); item->setMaximumSize(50, 50); gridLayout->addItem(item, y, x); + QSizePolicy policy = item->sizePolicy(); + policy.setHeightForWidth(hasHeightForWidth); + item->setSizePolicy(policy); } } } @@ -396,18 +412,22 @@ static void populateLayout(QGraphicsGridLayout *gridLayout, int width, int heigh * |xxxx|+---|---+| * +----+----+----+ */ -static void populateLayoutWithSpansAndHoles(QGraphicsGridLayout *gridLayout) +static void populateLayoutWithSpansAndHoles(QGraphicsGridLayout *gridLayout, bool hasHeightForWidth = false) { QGraphicsWidget *item = new RectWidget(); item->setMinimumSize(10, 10); item->setPreferredSize(25, 25); item->setMaximumSize(50, 50); + QSizePolicy sizepolicy = item->sizePolicy(); + sizepolicy.setHeightForWidth(hasHeightForWidth); + item->setSizePolicy(sizepolicy); gridLayout->addItem(item, 0, 0, 1, 2); item = new RectWidget(); item->setMinimumSize(10, 10); item->setPreferredSize(25, 25); item->setMaximumSize(50, 50); + item->setSizePolicy(sizepolicy); gridLayout->addItem(item, 1, 1, 1, 2); } @@ -460,19 +480,28 @@ void tst_QGraphicsGridLayout::addItem() delete layout; } +void tst_QGraphicsGridLayout::alignment_data() +{ + QTest::addColumn("hasHeightForWidth"); + + QTest::newRow("") << false; + QTest::newRow("hasHeightForWidth") << true; +} + // public Qt::Alignment alignment(QGraphicsLayoutItem* item) const void tst_QGraphicsGridLayout::alignment() { #ifdef Q_WS_MAC QSKIP("Resizing a QGraphicsWidget to effectiveSizeHint(Qt::MaximumSize) is currently not supported on mac", SkipAll); #endif + QFETCH(bool, hasHeightForWidth); QGraphicsScene scene; QGraphicsView view(&scene); QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window); QGraphicsGridLayout *layout = new QGraphicsGridLayout(); scene.addItem(widget); widget->setLayout(layout); - populateLayout(layout, 3, 2); + populateLayout(layout, 3, 2, hasHeightForWidth); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); @@ -524,6 +553,14 @@ void tst_QGraphicsGridLayout::alignment() delete widget; } +void tst_QGraphicsGridLayout::columnAlignment_data() +{ + QTest::addColumn("hasHeightForWidth"); + + QTest::newRow("") << false; + QTest::newRow("hasHeightForWidth") << true; +} + // public void setColumnAlignment(int column, Qt::Alignment alignment) // public Qt::Alignment columnAlignment(int column) const void tst_QGraphicsGridLayout::columnAlignment() @@ -531,13 +568,14 @@ void tst_QGraphicsGridLayout::columnAlignment() #ifdef Q_WS_MAC QSKIP("Resizing a QGraphicsWidget to effectiveSizeHint(Qt::MaximumSize) is currently not supported on mac", SkipAll); #endif + QFETCH(bool, hasHeightForWidth); QGraphicsScene scene; QGraphicsView view(&scene); QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window); QGraphicsGridLayout *layout = new QGraphicsGridLayout(); scene.addItem(widget); widget->setLayout(layout); - populateLayout(layout, 3, 2); + populateLayout(layout, 3, 2, hasHeightForWidth); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(1); widget->setContentsMargins(0, 0, 0, 0); @@ -583,9 +621,17 @@ void tst_QGraphicsGridLayout::columnAlignment() delete widget; } +void tst_QGraphicsGridLayout::columnCount_data() +{ + QTest::addColumn("hasHeightForWidth"); + + QTest::newRow("") << false; + QTest::newRow("hasHeightForWidth") << true; +} // public int columnCount() const void tst_QGraphicsGridLayout::columnCount() { + QFETCH(bool, hasHeightForWidth); QGraphicsScene scene; QGraphicsView view(&scene); QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window); @@ -617,7 +663,7 @@ void tst_QGraphicsGridLayout::columnCount() // ### Talk with Jasmin. Not sure if removeAt() should adjust columnCount(). widget->setLayout(0); layout = new QGraphicsGridLayout(); - populateLayout(layout, 3, 2); + populateLayout(layout, 3, 2, hasHeightForWidth); QCOMPARE(layout->columnCount(), 3); layout->removeAt(5); layout->removeAt(3); @@ -632,16 +678,24 @@ void tst_QGraphicsGridLayout::columnCount() delete widget; } +void tst_QGraphicsGridLayout::columnMaximumWidth_data() +{ + QTest::addColumn("hasHeightForWidth"); + + QTest::newRow("") << false; + QTest::newRow("hasHeightForWidth") << true; +} // public qreal columnMaximumWidth(int column) const void tst_QGraphicsGridLayout::columnMaximumWidth() { + QFETCH(bool, hasHeightForWidth); QGraphicsScene scene; QGraphicsView view(&scene); QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window); QGraphicsGridLayout *layout = new QGraphicsGridLayout(); scene.addItem(widget); widget->setLayout(layout); - populateLayout(layout, 3, 2); + populateLayout(layout, 3, 2, hasHeightForWidth); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); @@ -667,16 +721,24 @@ void tst_QGraphicsGridLayout::columnMaximumWidth() delete widget; } +void tst_QGraphicsGridLayout::columnMinimumWidth_data() +{ + QTest::addColumn("hasHeightForWidth"); + + QTest::newRow("") << false; + QTest::newRow("hasHeightForWidth") << true; +} // public qreal columnMinimumWidth(int column) const void tst_QGraphicsGridLayout::columnMinimumWidth() { + QFETCH(bool, hasHeightForWidth); QGraphicsScene scene; QGraphicsView view(&scene); QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window); QGraphicsGridLayout *layout = new QGraphicsGridLayout(); scene.addItem(widget); widget->setLayout(layout); - populateLayout(layout, 3, 2); + populateLayout(layout, 3, 2, hasHeightForWidth); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); @@ -702,16 +764,24 @@ void tst_QGraphicsGridLayout::columnMinimumWidth() delete widget; } +void tst_QGraphicsGridLayout::columnPreferredWidth_data() +{ + QTest::addColumn("hasHeightForWidth"); + + QTest::newRow("") << false; + QTest::newRow("hasHeightForWidth") << true; +} // public qreal columnPreferredWidth(int column) const void tst_QGraphicsGridLayout::columnPreferredWidth() { + QFETCH(bool, hasHeightForWidth); QGraphicsScene scene; QGraphicsView view(&scene); QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window); QGraphicsGridLayout *layout = new QGraphicsGridLayout(); scene.addItem(widget); widget->setLayout(layout); - populateLayout(layout, 3, 2); + populateLayout(layout, 3, 2, hasHeightForWidth); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); @@ -1021,16 +1091,25 @@ void tst_QGraphicsGridLayout::removeAt() delete widget; } +void tst_QGraphicsGridLayout::rowAlignment_data() +{ + QTest::addColumn("hasHeightForWidth"); + + QTest::newRow("") << false; + QTest::newRow("hasHeightForWidth") << true; +} + // public Qt::Alignment rowAlignment(int row) const void tst_QGraphicsGridLayout::rowAlignment() { + QFETCH(bool, hasHeightForWidth); QGraphicsScene scene; QGraphicsView view(&scene); QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window); QGraphicsGridLayout *layout = new QGraphicsGridLayout(); scene.addItem(widget); widget->setLayout(layout); - populateLayout(layout, 2, 3); + populateLayout(layout, 2, 3, hasHeightForWidth); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(1); widget->setContentsMargins(0, 0, 0, 0); @@ -1080,17 +1159,26 @@ void tst_QGraphicsGridLayout::rowAlignment() delete widget; } +void tst_QGraphicsGridLayout::rowCount_data() +{ + QTest::addColumn("hasHeightForWidth"); + + QTest::newRow("") << false; + QTest::newRow("hasHeightForWidth") << true; +} + // public int rowCount() const // public int columnCount() const void tst_QGraphicsGridLayout::rowCount() { + QFETCH(bool, hasHeightForWidth); QGraphicsScene scene; QGraphicsView view(&scene); QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window); QGraphicsGridLayout *layout = new QGraphicsGridLayout(); scene.addItem(widget); widget->setLayout(layout); - populateLayout(layout, 2, 3); + populateLayout(layout, 2, 3, hasHeightForWidth); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); widget->setContentsMargins(0, 0, 0, 0); @@ -1100,23 +1188,32 @@ void tst_QGraphicsGridLayout::rowCount() // with spans and holes... widget->setLayout(0); layout = new QGraphicsGridLayout(); - populateLayoutWithSpansAndHoles(layout); + populateLayoutWithSpansAndHoles(layout, hasHeightForWidth); QCOMPARE(layout->rowCount(), 2); QCOMPARE(layout->columnCount(), 3); delete widget; } +void tst_QGraphicsGridLayout::rowMaximumHeight_data() +{ + QTest::addColumn("hasHeightForWidth"); + + QTest::newRow("") << false; + QTest::newRow("hasHeightForWidth") << true; +} + // public qreal rowMaximumHeight(int row) const void tst_QGraphicsGridLayout::rowMaximumHeight() { + QFETCH(bool, hasHeightForWidth); QGraphicsScene scene; QGraphicsView view(&scene); QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window); QGraphicsGridLayout *layout = new QGraphicsGridLayout; scene.addItem(widget); widget->setLayout(layout); - populateLayout(layout, 2, 3); + populateLayout(layout, 2, 3, hasHeightForWidth); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); @@ -1142,16 +1239,24 @@ void tst_QGraphicsGridLayout::rowMaximumHeight() delete widget; } +void tst_QGraphicsGridLayout::rowMinimumHeight_data() +{ + QTest::addColumn("hasHeightForWidth"); + + QTest::newRow("") << false; + QTest::newRow("hasHeightForWidth") << true; +} // public qreal rowMinimumHeight(int row) const void tst_QGraphicsGridLayout::rowMinimumHeight() { + QFETCH(bool, hasHeightForWidth); QGraphicsScene scene; QGraphicsView view(&scene); QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window); QGraphicsGridLayout *layout = new QGraphicsGridLayout(); scene.addItem(widget); widget->setLayout(layout); - populateLayout(layout, 2, 3); + populateLayout(layout, 2, 3, hasHeightForWidth); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); @@ -1177,16 +1282,24 @@ void tst_QGraphicsGridLayout::rowMinimumHeight() delete widget; } +void tst_QGraphicsGridLayout::rowPreferredHeight_data() +{ + QTest::addColumn("hasHeightForWidth"); + + QTest::newRow("") << false; + QTest::newRow("hasHeightForWidth") << true; +} // public qreal rowPreferredHeight(int row) const void tst_QGraphicsGridLayout::rowPreferredHeight() { + QFETCH(bool, hasHeightForWidth); QGraphicsScene scene; QGraphicsView view(&scene); QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window); QGraphicsGridLayout *layout = new QGraphicsGridLayout(); scene.addItem(widget); widget->setLayout(layout); - populateLayout(layout, 2, 3); + populateLayout(layout, 2, 3, hasHeightForWidth); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); @@ -1275,16 +1388,25 @@ void tst_QGraphicsGridLayout::rowSpacing() } +void tst_QGraphicsGridLayout::rowStretchFactor_data() +{ + QTest::addColumn("hasHeightForWidth"); + + QTest::newRow("") << false; + QTest::newRow("hasHeightForWidth") << true; +} + // public int rowStretchFactor(int row) const void tst_QGraphicsGridLayout::rowStretchFactor() { + QFETCH(bool, hasHeightForWidth); QGraphicsScene scene; QGraphicsView view(&scene); QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window); QGraphicsGridLayout *layout = new QGraphicsGridLayout(); scene.addItem(widget); widget->setLayout(layout); - populateLayout(layout, 2, 3); + populateLayout(layout, 2, 3, hasHeightForWidth); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); @@ -1308,9 +1430,12 @@ void tst_QGraphicsGridLayout::setColumnSpacing_data() { QTest::addColumn("column"); QTest::addColumn("spacing"); - QTest::newRow("null") << 0 << qreal(0.0); - QTest::newRow("10") << 0 << qreal(10.0); + QTest::addColumn("hasHeightForWidth"); + QTest::newRow("null") << 0 << qreal(0.0) << false; + QTest::newRow("10") << 0 << qreal(10.0) << false; + QTest::newRow("null, hasHeightForWidth") << 0 << qreal(0.0) << true; + QTest::newRow("10, hasHeightForWidth") << 0 << qreal(10.0) << true; } // public void setColumnSpacing(int column, qreal spacing) @@ -1318,6 +1443,7 @@ void tst_QGraphicsGridLayout::setColumnSpacing() { QFETCH(int, column); QFETCH(qreal, spacing); + QFETCH(bool, hasHeightForWidth); QGraphicsScene scene; QGraphicsView view(&scene); @@ -1325,7 +1451,7 @@ void tst_QGraphicsGridLayout::setColumnSpacing() QGraphicsGridLayout *layout = new QGraphicsGridLayout(); scene.addItem(widget); widget->setLayout(layout); - populateLayout(layout, 3, 2); + populateLayout(layout, 3, 2, hasHeightForWidth); layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); qreal oldSpacing = layout->columnSpacing(column); @@ -1362,9 +1488,12 @@ void tst_QGraphicsGridLayout::setRowSpacing_data() { QTest::addColumn("row"); QTest::addColumn("spacing"); - QTest::newRow("null") << 0 << qreal(0.0); - QTest::newRow("10") << 0 << qreal(10.0); + QTest::addColumn("hasHeightForWidth"); + QTest::newRow("null") << 0 << qreal(0.0) << false; + QTest::newRow("10") << 0 << qreal(10.0) << false; + QTest::newRow("null, hasHeightForWidth") << 0 << qreal(0.0) << true; + QTest::newRow("10, hasHeightForWidth") << 0 << qreal(10.0) << true; } // public void setRowSpacing(int row, qreal spacing) @@ -1372,6 +1501,7 @@ void tst_QGraphicsGridLayout::setRowSpacing() { QFETCH(int, row); QFETCH(qreal, spacing); + QFETCH(bool, hasHeightForWidth); QGraphicsScene scene; QGraphicsView view(&scene); @@ -1379,7 +1509,7 @@ void tst_QGraphicsGridLayout::setRowSpacing() QGraphicsGridLayout *layout = new QGraphicsGridLayout(); scene.addItem(widget); widget->setLayout(layout); - populateLayout(layout, 3, 2); + populateLayout(layout, 3, 2, hasHeightForWidth); layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); qreal oldSpacing = layout->rowSpacing(row); @@ -1393,21 +1523,25 @@ void tst_QGraphicsGridLayout::setRowSpacing() void tst_QGraphicsGridLayout::setSpacing_data() { QTest::addColumn("spacing"); - QTest::newRow("zero") << qreal(0.0); - QTest::newRow("17") << qreal(17.0); + QTest::addColumn("hasHeightForWidth"); + QTest::newRow("zero") << qreal(0.0) << false; + QTest::newRow("17") << qreal(17.0) << false; + QTest::newRow("zero, hasHeightForWidth") << qreal(0.0) << true; + QTest::newRow("17, hasHeightForWidth") << qreal(17.0) << true; } // public void setSpacing(qreal spacing) void tst_QGraphicsGridLayout::setSpacing() { QFETCH(qreal, spacing); + QFETCH(bool, hasHeightForWidth); QGraphicsScene scene; QGraphicsView view(&scene); QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window); QGraphicsGridLayout *layout = new QGraphicsGridLayout(); scene.addItem(widget); widget->setLayout(layout); - populateLayout(layout, 3, 2); + populateLayout(layout, 3, 2, hasHeightForWidth); layout->setContentsMargins(0, 0, 0, 0); QSizeF sh = layout->sizeHint(Qt::PreferredSize, QSizeF()); qreal oldVSpacing = layout->verticalSpacing(); @@ -1538,8 +1672,18 @@ void tst_QGraphicsGridLayout::verticalSpacing() delete widget; } +void tst_QGraphicsGridLayout::layoutDirection_data() +{ + QTest::addColumn("hasHeightForWidth"); + + QTest::newRow("") << false; + QTest::newRow("hasHeightForWidth") << true; +} + void tst_QGraphicsGridLayout::layoutDirection() { + QFETCH(bool, hasHeightForWidth); + QGraphicsScene scene; QGraphicsView view(&scene); @@ -1562,6 +1706,12 @@ void tst_QGraphicsGridLayout::layoutDirection() w4->setMinimumSize(30, 20); layout->addItem(w4, 1, 1); + QSizePolicy policy = w1->sizePolicy(); + policy.setHeightForWidth(hasHeightForWidth); + w1->setSizePolicy(policy); + w2->setSizePolicy(policy); + w4->setSizePolicy(policy); + layout->setAlignment(w2, Qt::AlignRight); layout->setAlignment(w3, Qt::AlignLeft); @@ -2200,9 +2350,9 @@ void tst_QGraphicsGridLayout::geometries_data() .preferredSize(QSizeF(50,10)) .maxSize(QSizeF(100, 100)) << ItemDesc(1,1) - .minSize(QSizeF(40,40)) - .preferredSize(QSizeF(50,400)) - .maxSize(QSizeF(500, 500)) + .minSize(QSizeF(40,-1)) + .preferredSize(QSizeF(50,-1)) + .maxSize(QSizeF(500, -1)) .heightForWidth(hfw1) ) << QSizeF(100, 401) @@ -2211,32 +2361,6 @@ void tst_QGraphicsGridLayout::geometries_data() << QRectF(0, 1, 50,100) << QRectF(50, 1, 50,400) ); - - QTest::newRow("hfw-h408") << (ItemList() - << ItemDesc(0,0) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,10)) - .maxSize(QSizeF(100, 100)) - << ItemDesc(0,1) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,10)) - .maxSize(QSizeF(100, 100)) - << ItemDesc(1,0) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,10)) - .maxSize(QSizeF(100, 100)) - << ItemDesc(1,1) - .minSize(QSizeF(40,40)) - .preferredSize(QSizeF(50,400)) - .maxSize(QSizeF(500, 500)) - .heightForWidth(hfw1) - ) - << QSizeF(100, 408) - << (RectList() - << QRectF(0, 0, 50, 8) << QRectF(50, 0, 50, 8) - << QRectF(0, 8, 50,100) << QRectF(50, 8, 50,400) - ); - QTest::newRow("hfw-h410") << (ItemList() << ItemDesc(0,0) .minSize(QSizeF(1,1)) @@ -2262,109 +2386,6 @@ void tst_QGraphicsGridLayout::geometries_data() << QRectF(0, 10, 50,100) << QRectF(50, 10, 50,400) ); - QTest::newRow("hfw-h470") << (ItemList() - << ItemDesc(0,0) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,10)) - .maxSize(QSizeF(100, 100)) - << ItemDesc(0,1) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,10)) - .maxSize(QSizeF(100, 100)) - << ItemDesc(1,0) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,10)) - .maxSize(QSizeF(100, 100)) - << ItemDesc(1,1) - .minSize(QSizeF(40,40)) - .preferredSize(QSizeF(50,400)) - .maxSize(QSizeF(500, 500)) - .heightForWidth(hfw1) - ) - << QSizeF(100, 470) - << (RectList() - << QRectF(0, 0, 50,70) << QRectF(50, 0, 50,70) - << QRectF(0, 70, 50,100) << QRectF(50, 70, 50,400) - ); - - - // change layout width and verify - QTest::newRow("hfw-w100") << (ItemList() - << ItemDesc(0,0) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,10)) - .maxSize(QSizeF(100, 100)) - << ItemDesc(0,1) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,10)) - .maxSize(QSizeF(100, 100)) - << ItemDesc(1,0) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,10)) - .maxSize(QSizeF(100, 100)) - << ItemDesc(1,1) - .minSize(QSizeF(40,40)) - .preferredSize(QSizeF(50,400)) - .maxSize(QSizeF(5000, 5000)) - .heightForWidth(hfw1) - ) - << QSizeF(100, 401) - << (RectList() - << QRectF( 0, 0, 50, 1) << QRectF( 50, 0, 50, 1) - << QRectF( 0, 1, 50, 100) << QRectF( 50, 1, 50, 400) - ); - - QTest::newRow("hfw-w160") << (ItemList() - << ItemDesc(0,0) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,10)) - .maxSize(QSizeF(100, 100)) - << ItemDesc(0,1) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,10)) - .maxSize(QSizeF(100, 100)) - << ItemDesc(1,0) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,10)) - .maxSize(QSizeF(100, 100)) - << ItemDesc(1,1) - .minSize(QSizeF(40,40)) - .preferredSize(QSizeF(50,400)) - .maxSize(QSizeF(5000, 5000)) - .heightForWidth(hfw1) - ) - << QSizeF(160, 401) - << (RectList() - << QRectF( 0, 0, 80, 100) << QRectF( 80, 0, 80, 100) - << QRectF( 0, 100, 80, 100) << QRectF( 80, 100, 80, 250) - ); - - - QTest::newRow("hfw-w500") << (ItemList() - << ItemDesc(0,0) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,10)) - .maxSize(QSizeF(100, 100)) - << ItemDesc(0,1) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,10)) - .maxSize(QSizeF(100, 100)) - << ItemDesc(1,0) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,10)) - .maxSize(QSizeF(100, 100)) - << ItemDesc(1,1) - .minSize(QSizeF(40,40)) - .preferredSize(QSizeF(50,400)) - .maxSize(QSizeF(5000, 5000)) - .heightForWidth(hfw1) - ) - << QSizeF(500, 401) - << (RectList() - << QRectF( 0, 0, 100, 100) << QRectF(100, 0, 100, 100) - << QRectF( 0, 100, 100, 100) << QRectF(100, 100, 400, 50) - ); - } void tst_QGraphicsGridLayout::geometries() -- cgit v0.12 From af9e4976bea7193a6f4ad09d823aaa1ffee25a3b Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Thu, 14 Oct 2010 11:01:33 +0200 Subject: Fixed autotest that was missing focus on Windows Reviewed-by: ogoffart --- tests/auto/qcompleter/tst_qcompleter.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/qcompleter/tst_qcompleter.cpp b/tests/auto/qcompleter/tst_qcompleter.cpp index 6d28f9f..bdd105c 100644 --- a/tests/auto/qcompleter/tst_qcompleter.cpp +++ b/tests/auto/qcompleter/tst_qcompleter.cpp @@ -1483,8 +1483,10 @@ void tst_QCompleter::QTBUG_14292_filesystem() edit.show(); QApplication::setActiveWindow(&edit); + edit.setFocus(); QTest::qWaitForWindowShown(&edit); QTRY_VERIFY(QApplication::activeWindow() == &edit); + QTRY_VERIFY(edit.hasFocus()); QVERIFY(!comp.popup()->isVisible()); edit.setText(tmpDir.path()); -- cgit v0.12 From f3180713921f73ea529b22379ce5f87392ce749a Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 14 Oct 2010 10:44:35 +0200 Subject: tst_qcompleter.cpp: fix test on mac. Disable the one that does not work --- tests/auto/qcompleter/tst_qcompleter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qcompleter/tst_qcompleter.cpp b/tests/auto/qcompleter/tst_qcompleter.cpp index bdd105c..425a230 100644 --- a/tests/auto/qcompleter/tst_qcompleter.cpp +++ b/tests/auto/qcompleter/tst_qcompleter.cpp @@ -651,7 +651,7 @@ void tst_QCompleter::fileSystemModel_data() #elif defined (Q_OS_MAC) QTest::newRow("()") << "" << "" << "/" << "/"; QTest::newRow("(/a)") << "/a" << "" << "Applications" << "/Applications"; - QTest::newRow("(/d)") << "/d" << "" << "Developer" << "/Developer"; +// QTest::newRow("(/d)") << "/d" << "" << "Developer" << "/Developer"; #else QTest::newRow("()") << "" << "" << "/" << "/"; #if !defined(Q_OS_IRIX) && !defined(Q_OS_AIX) && !defined(Q_OS_HPUX) -- cgit v0.12 From 830df741afc987f12d744bfab8a4b9ee538c212a Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 14 Oct 2010 18:29:32 +0200 Subject: tst_qcompleter: Fix the QTBUG_14292_filesystem test on X11 The last fix on Windows broke it on linux Reviewed-by: thierry --- tests/auto/qcompleter/tst_qcompleter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto/qcompleter/tst_qcompleter.cpp b/tests/auto/qcompleter/tst_qcompleter.cpp index 425a230..650c328 100644 --- a/tests/auto/qcompleter/tst_qcompleter.cpp +++ b/tests/auto/qcompleter/tst_qcompleter.cpp @@ -1483,9 +1483,9 @@ void tst_QCompleter::QTBUG_14292_filesystem() edit.show(); QApplication::setActiveWindow(&edit); - edit.setFocus(); QTest::qWaitForWindowShown(&edit); QTRY_VERIFY(QApplication::activeWindow() == &edit); + edit.setFocus(); QTRY_VERIFY(edit.hasFocus()); QVERIFY(!comp.popup()->isVisible()); @@ -1493,6 +1493,7 @@ void tst_QCompleter::QTBUG_14292_filesystem() QTest::keyClick(&edit, '/'); QTRY_VERIFY(comp.popup()->isVisible()); QCOMPARE(comp.popup()->model()->rowCount(), 2); + QApplication::processEvents(); QTest::keyClick(&edit, 'h'); QCOMPARE(comp.popup()->model()->rowCount(), 2); QTest::keyClick(&edit, 'e'); -- cgit v0.12 From a9cddeb760e85fbce2c1604b7e7b9b2affaaccd9 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 15 Oct 2010 10:43:07 +0200 Subject: Fix tst_moduleqt47::accidentalImport --- doc/src/snippets/declarative/keys/keys-handler.qml | 2 +- doc/src/snippets/declarative/keys/keys-pressed.qml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/snippets/declarative/keys/keys-handler.qml b/doc/src/snippets/declarative/keys/keys-handler.qml index 9e3a3b4..be0eedb 100644 --- a/doc/src/snippets/declarative/keys/keys-handler.qml +++ b/doc/src/snippets/declarative/keys/keys-handler.qml @@ -38,7 +38,7 @@ ** ****************************************************************************/ -import Qt 4.7 +import QtQuick 1.0 Item { width: 400; height: 400 diff --git a/doc/src/snippets/declarative/keys/keys-pressed.qml b/doc/src/snippets/declarative/keys/keys-pressed.qml index 523c95b..90a4e37 100644 --- a/doc/src/snippets/declarative/keys/keys-pressed.qml +++ b/doc/src/snippets/declarative/keys/keys-pressed.qml @@ -38,7 +38,7 @@ ** ****************************************************************************/ -import Qt 4.7 +import QtQuick 1.0 Item { width: 400; height: 400 -- cgit v0.12 From 9e378145294da33495d48b2c0742461ae6c2a3ba Mon Sep 17 00:00:00 2001 From: David Faure Date: Thu, 15 Jul 2010 16:08:43 +0200 Subject: QWorkspace: fix hardcoded min size overwriting the real min size The setMinimumSize call was having precedence over the minimumSizeHint, so when having a sizegrip enabled it was possible to resize a MDI window to a much smaller size than its min size (actually it would flicker between the two sizes, on each resize). Fixed by moving that min size (for the titlebar contents) to the calculations in minimumSizeHint(). Reviewed-by: mariusso --- src/gui/widgets/qworkspace.cpp | 15 +++++++++------ tests/auto/qworkspace/tst_qworkspace.cpp | 10 ++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/gui/widgets/qworkspace.cpp b/src/gui/widgets/qworkspace.cpp index 7180c4d..3a9b30c 100644 --- a/src/gui/widgets/qworkspace.cpp +++ b/src/gui/widgets/qworkspace.cpp @@ -2551,7 +2551,6 @@ QWorkspaceChild::QWorkspaceChild(QWidget* window, QWorkspace *parent, Qt::Window this, SLOT(titleBarDoubleClicked())); } - setMinimumSize(128, 0); int fw = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, this); setContentsMargins(fw, fw, fw, fw); @@ -2702,11 +2701,15 @@ QSize QWorkspaceChild::sizeHint() const QSize QWorkspaceChild::minimumSizeHint() const { - if (!childWidget) - return QWidget::minimumSizeHint() + baseSize(); - QSize s = childWidget->minimumSize(); - if (s.isEmpty()) - s = childWidget->minimumSizeHint(); + QSize s; + if (!childWidget) { + s = QWidget::minimumSizeHint(); + } else { + s = childWidget->minimumSize(); + if (s.isEmpty()) + s = childWidget->minimumSizeHint(); + } + s = s.expandedTo(QSize(128, 0)); return s + baseSize(); } diff --git a/tests/auto/qworkspace/tst_qworkspace.cpp b/tests/auto/qworkspace/tst_qworkspace.cpp index 4cf76b5..9039eb3 100644 --- a/tests/auto/qworkspace/tst_qworkspace.cpp +++ b/tests/auto/qworkspace/tst_qworkspace.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #if defined(QT3_SUPPORT) #include @@ -591,16 +592,25 @@ void tst_QWorkspace::childSize() MyChild *child = new MyChild(&ws); child->show(); + ws.addWindow(child); QCOMPARE(child->size(), child->sizeHint()); delete child; child = new MyChild(&ws); child->setFixedSize(200, 200); child->show(); + ws.addWindow(child); QCOMPARE(child->size(), child->minimumSize()); + QCOMPARE(child->parentWidget()->metaObject()->className(), "QWorkspaceChild"); + QVERIFY(child->parentWidget()->width() >= 200); + // check that the minimum size is respected, using closestAcceptableSize + // like QSizeGrip does. + const QSize newSize = QLayout::closestAcceptableSize(child->parentWidget(), QSize(100, 100)); + QVERIFY(newSize.width() >= 200); delete child; child = new MyChild(&ws); + ws.addWindow(child); child->resize(150, 150); child->show(); QCOMPARE(child->size(), QSize(150,150)); -- cgit v0.12 From 5fd505cac71e97cf181c0d05867a77e640814fc6 Mon Sep 17 00:00:00 2001 From: Fabien Freling Date: Fri, 15 Oct 2010 13:20:42 +0200 Subject: Disable the unified toolbar before entering fullscreen on Mac OS X. We are just enforcing what the documentation recommended. Task-number: QTBUG-13772 Reviewed-by: Samuel --- src/gui/kernel/qwidget.cpp | 34 ++++++++++++++++++++++++++++++++++ src/gui/widgets/qmainwindow.cpp | 4 ++-- src/gui/widgets/qmainwindowlayout_p.h | 1 + 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index f7c795e..9b44f15 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -68,6 +68,7 @@ # include "qt_cocoa_helpers_mac_p.h" # include "qmainwindow.h" # include "qtoolbar.h" +# include #endif #if defined(Q_WS_QWS) # include "qwsdisplay_qws.h" @@ -3002,6 +3003,15 @@ bool QWidget::isFullScreen() const */ void QWidget::showFullScreen() { +#ifdef Q_WS_MAC + // If the unified toolbar is enabled, we have to disable it before going fullscreen. + QMainWindow *mainWindow = qobject_cast(this); + if (mainWindow && mainWindow->unifiedTitleAndToolBarOnMac()) { + mainWindow->setUnifiedTitleAndToolBarOnMac(false); + QMainWindowLayout *mainLayout = qobject_cast(mainWindow->layout()); + mainLayout->activateUnifiedToolbarAfterFullScreen = true; + } +#endif // Q_WS_MAC ensurePolished(); #ifdef QT3_SUPPORT if (parent()) @@ -3034,6 +3044,18 @@ void QWidget::showMaximized() setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen)) | Qt::WindowMaximized); +#ifdef Q_WS_MAC + // If the unified toolbar was enabled before going fullscreen, we have to enable it back. + QMainWindow *mainWindow = qobject_cast(this); + if (mainWindow) + { + QMainWindowLayout *mainLayout = qobject_cast(mainWindow->layout()); + if (mainLayout->activateUnifiedToolbarAfterFullScreen) { + mainWindow->setUnifiedTitleAndToolBarOnMac(true); + mainLayout->activateUnifiedToolbarAfterFullScreen = false; + } + } +#endif // Q_WS_MAC show(); } @@ -3055,6 +3077,18 @@ void QWidget::showNormal() setWindowState(windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)); +#ifdef Q_WS_MAC + // If the unified toolbar was enabled before going fullscreen, we have to enable it back. + QMainWindow *mainWindow = qobject_cast(this); + if (mainWindow) + { + QMainWindowLayout *mainLayout = qobject_cast(mainWindow->layout()); + if (mainLayout->activateUnifiedToolbarAfterFullScreen) { + mainWindow->setUnifiedTitleAndToolBarOnMac(true); + mainLayout->activateUnifiedToolbarAfterFullScreen = false; + } + } +#endif // Q_WS_MAC show(); } diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index 1183be6..d971f61 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -78,6 +78,7 @@ public: : layout(0), explicitIconSize(false), toolButtonStyle(Qt::ToolButtonIconOnly) #ifdef Q_WS_MAC , useHIToolBar(false) + , activateUnifiedToolbarAfterFullScreen(false) #endif #if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR) , hasOldCursor(false) , cursorAdjusted(false) @@ -89,6 +90,7 @@ public: Qt::ToolButtonStyle toolButtonStyle; #ifdef Q_WS_MAC bool useHIToolBar; + bool activateUnifiedToolbarAfterFullScreen; #endif void init(); QList hoverSeparator; @@ -1501,8 +1503,6 @@ bool QMainWindow::event(QEvent *event) \i Before Qt 4.5, if you called showFullScreen() on the main window, the QToolbar would disappear since it is considered to be part of the title bar. Qt 4.5 and up will now work around this by pulling the toolbars out and back into the regular toolbar and vice versa when you swap out. - However, a good practice would be that turning off the unified toolbar before you call - showFullScreen() and restoring it after you call showNormal(). \endlist Setting this back to false will remove these restrictions. diff --git a/src/gui/widgets/qmainwindowlayout_p.h b/src/gui/widgets/qmainwindowlayout_p.h index e1b981c..3e1a95d 100644 --- a/src/gui/widgets/qmainwindowlayout_p.h +++ b/src/gui/widgets/qmainwindowlayout_p.h @@ -335,6 +335,7 @@ public: void cleanUpMacToolbarItems(); void fixSizeInUnifiedToolbar(QToolBar *tb) const; bool useHIToolBar; + bool activateUnifiedToolbarAfterFullScreen; void syncUnifiedToolbarVisibility(); bool blockVisiblityCheck; #endif -- cgit v0.12