diff options
Diffstat (limited to 'src/gui')
55 files changed, 2741 insertions, 4936 deletions
diff --git a/src/gui/configure.json b/src/gui/configure.json index 4de159d97a..9d9d312048 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -1638,15 +1638,9 @@ "condition": "features.imageformat_xpm", "output": [ "publicFeature", "feature" ] }, - "shortcut": { - "label": "QShortcut", - "purpose": "Provides keyboard accelerators and shortcuts.", - "section": "Kernel", - "output": [ "publicFeature", "feature" ] - }, "action": { - "label": "QAction", - "purpose": "Provides widget actions.", + "label": "Q(Gui)Action(Group)", + "purpose": "Provides abstract user interface actions.", "section": "Kernel", "output": [ "publicFeature", "feature" ] }, diff --git a/src/gui/doc/snippets/picture/picture.cpp b/src/gui/doc/snippets/picture/picture.cpp index 863476fdbf..807c263b19 100644 --- a/src/gui/doc/snippets/picture/picture.cpp +++ b/src/gui/doc/snippets/picture/picture.cpp @@ -80,82 +80,3 @@ int main() painter.end(); // painting done //! [1] } - - QPicture myPicture; - { - // FORMATS -//! [2] - const QStringList list = QPicture::inputFormatList(); - for (const QString &string : list) - myProcessing(string); -//! [2] - } - - { - // OUTPUT -//! [3] - const QStringList list = QPicture::outputFormatList(); - for (const QString &string : list) - myProcessing(string); -//! [3] - } - - { - // PIC READ -//! [4] - QPictureIO iio; - QPixmap pixmap; - iio.setFileName("vegeburger.pic"); - if (iio.read()) { // OK - QPicture picture = iio.picture(); - QPainter painter(&pixmap); - painter.drawPicture(0, 0, picture); - } -//! [4] - } - - { - QPixmap pixmap; - // PIC WRITE -//! [5] - QPictureIO iio; - QPicture picture; - QPainter painter(&picture); - painter.drawPixmap(0, 0, pixmap); - iio.setPicture(picture); - iio.setFileName("vegeburger.pic"); - iio.setFormat("PIC"); - if (iio.write()) - return true; // returned true if written successfully -//! [5] - } - -} - -// SVG READ -//! [6] -void readSVG(QPictureIO *picture) -{ - // read the picture using the picture->ioDevice() -} -//! [6] - -// SVG WRITE -//! [7] -void writeSVG(QPictureIO *picture) -{ - // write the picture using the picture->ioDevice() -} -//! [7] - -// USE SVG -void foo() { - -//! [8] - // add the SVG picture handler - // ... -//! [8] - QPictureIO::defineIOHandler("SVG", 0, 0, readSVG, writeSVG); - // ... - -} diff --git a/src/gui/doc/src/dontdocument.qdoc b/src/gui/doc/src/dontdocument.qdoc index b360acefc1..6b50daba88 100644 --- a/src/gui/doc/src/dontdocument.qdoc +++ b/src/gui/doc/src/dontdocument.qdoc @@ -27,7 +27,7 @@ /*! \dontdocument (QTypeInfo QScreenOrientationChangeEvent QApplicationStateChangeEvent - QImageTextKeyLang QMetaTypeId QAbstractUndoItem + QMetaTypeId QAbstractUndoItem QOpenGLVersionStatus QOpenGLVersionFunctionsBackend QOpenGLVersionFunctionsStorage diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index 1f42f28d1e..760b737ec3 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -14,7 +14,6 @@ HEADERS += \ image/qpaintengine_pic_p.h \ image/qpicture.h \ image/qpicture_p.h \ - image/qpictureformatplugin.h \ image/qpixmap.h \ image/qpixmap_raster_p.h \ image/qpixmap_blitter_p.h \ @@ -38,7 +37,6 @@ SOURCES += \ image/qimagewriter.cpp \ image/qpaintengine_pic.cpp \ image/qpicture.cpp \ - image/qpictureformatplugin.cpp \ image/qpixmap.cpp \ image/qpixmapcache.cpp \ image/qplatformpixmap.cpp \ @@ -59,9 +57,6 @@ win32:!winrt: SOURCES += image/qpixmap_win.cpp darwin: OBJECTIVE_SOURCES += image/qimage_darwin.mm -NO_PCH_SOURCES += image/qimage_compat.cpp -false: SOURCES += $$NO_PCH_SOURCES # Hack for QtCreator - # Built-in image format support HEADERS += \ image/qbmphandler_p.h \ diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 3ddc52bed4..08b1373f96 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -1381,11 +1381,7 @@ int QImage::colorCount() const \sa colorTable(), setColor(), {QImage#Image Transformations}{Image Transformations} */ -#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) void QImage::setColorTable(const QVector<QRgb> &colors) -#else -void QImage::setColorTable(const QVector<QRgb> colors) -#endif { if (!d) return; @@ -1395,11 +1391,7 @@ void QImage::setColorTable(const QVector<QRgb> colors) if (!d) return; -#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) d->colortable = colors; -#else - d->colortable = std::move(const_cast<QVector<QRgb>&>(colors)); -#endif d->has_alpha_clut = false; for (int i = 0; i < d->colortable.size(); ++i) { if (qAlpha(d->colortable.at(i)) != 255) { @@ -1472,25 +1464,6 @@ void QImage::setDevicePixelRatio(qreal scaleFactor) d->devicePixelRatio = scaleFactor; } -#if QT_DEPRECATED_SINCE(5, 10) -/*! - \since 4.6 - \obsolete - Returns the number of bytes occupied by the image data. - - Note this method should never be called on an image larger than 2 gigabytes. - Instead use sizeInBytes(). - - \sa sizeInBytes(), bytesPerLine(), bits(), {QImage#Image Information}{Image - Information} -*/ -int QImage::byteCount() const -{ - Q_ASSERT(!d || d->nbytes < std::numeric_limits<int>::max()); - return d ? int(d->nbytes) : 0; -} -#endif - /*! \since 5.10 Returns the image data size in bytes. @@ -1510,17 +1483,10 @@ qsizetype QImage::sizeInBytes() const \sa scanLine() */ -#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) qsizetype QImage::bytesPerLine() const { return d ? d->bytes_per_line : 0; } -#else -int QImage::bytesPerLine() const -{ - return d ? d->bytes_per_line : 0; -} -#endif /*! @@ -4054,71 +4020,10 @@ void QImage::setText(const QString &key, const QString &value) } /*! - \fn QString QImage::text(const char* key, const char* language) const - \obsolete - - Returns the text recorded for the given \a key in the given \a - language, or in a default language if \a language is 0. - - Use text() instead. - - The language the text is recorded in is no longer relevant since - the text is always set using QString and UTF-8 representation. -*/ - -/*! - \fn QString QImage::text(const QImageTextKeyLang& keywordAndLanguage) const - \overload - \obsolete - - Returns the text recorded for the given \a keywordAndLanguage. - - Use text() instead. - - The language the text is recorded in is no longer relevant since - the text is always set using QString and UTF-8 representation. -*/ - -/*! - \fn void QImage::setText(const char* key, const char* language, const QString& text) - \obsolete - - Sets the image text to the given \a text and associate it with the - given \a key. The text is recorded in the specified \a language, - or in a default language if \a language is 0. - - Use setText() instead. - - The language the text is recorded in is no longer relevant since - the text is always set using QString and UTF-8 representation. - - \omit - Records string \a for the keyword \a key. The \a key should be - a portable keyword recognizable by other software - some suggested - values can be found in - \l{http://www.libpng.org/pub/png/spec/1.2/png-1.2-pdg.html#C.Anc-text} - {the PNG specification}. \a s can be any text. \a lang should - specify the language code (see - \l{http://www.rfc-editor.org/rfc/rfc1766.txt}{RFC 1766}) or 0. - \endomit -*/ - -/* - Sets the image bits to the \a pixmap contents and returns a - reference to the image. - - If the image shares data with other images, it will first - dereference the shared data. - - Makes a call to QPixmap::convertToImage(). -*/ - -/*! \internal Used by QPainter to retrieve a paint engine for the image. */ - QPaintEngine *QImage::paintEngine() const { if (!d) @@ -4364,22 +4269,6 @@ bool qt_xForm_helper(const QTransform &trueMat, int xoffset, int type, int depth #undef IWX_LSB #undef IWX_PIX -/*! \fn int QImage::serialNumber() const - \obsolete - Returns a number that identifies the contents of this - QImage object. Distinct QImage objects can only have the same - serial number if they refer to the same contents (but they don't - have to). - - Use cacheKey() instead. - - \warning The serial number doesn't necessarily change when the - image is altered. This means that it may be dangerous to use - it as a cache key. - - \sa operator==() -*/ - /*! Returns a number that identifies the contents of this QImage object. Distinct QImage objects can only have the same key if they @@ -5085,50 +4974,6 @@ QDebug operator<<(QDebug dbg, const QImage &i) } #endif -/*! - \fn void QImage::setNumColors(int n) - \obsolete - - Resizes the color table to contain \a n entries. - - \sa setColorCount() - */ - -/*! - \fn int QImage::numBytes() const - \obsolete - - Returns the number of bytes occupied by the image data. - - \sa sizeInBytes() - */ - -/*! - \fn QStringList QImage::textLanguages() const - \obsolete - - Returns the language identifiers for which some texts are recorded. - Note that if you want to iterate over the list, you should iterate over a copy. - - The language the text is recorded in is no longer relevant since the text is - always set using QString and UTF-8 representation. - - \sa textKeys() - */ - -/*! - \fn QList<QImageTextKeyLang> QImage::textList() const - \obsolete - - Returns a list of QImageTextKeyLang objects that enumerate all the texts - key/language pairs set for this image. - - The language the text is recorded in is no longer relevant since the text - is always set using QString and UTF-8 representation. - - \sa textKeys() - */ - static Q_CONSTEXPR QPixelFormat pixelformats[] = { //QImage::Format_Invalid: QPixelFormat(), diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 115071c16e..b8df4b83d1 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -50,10 +50,6 @@ #include <QtCore/qrect.h> #include <QtCore/qstring.h> -#if QT_DEPRECATED_SINCE(5, 0) -#include <QtCore/qstringlist.h> -#endif - #if defined(Q_OS_DARWIN) || defined(Q_QDOC) Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(CGImage); #endif @@ -68,31 +64,9 @@ class QMatrix; class QStringList; class QTransform; class QVariant; -template <class T> class QList; template <class T> class QVector; struct QImageData; -class QImageDataMisc; // internal -#if QT_DEPRECATED_SINCE(5, 0) -class QImageTextKeyLang { -public: - QT_DEPRECATED QImageTextKeyLang(const char* k, const char* l) : key(k), lang(l) { } - QT_DEPRECATED QImageTextKeyLang() { } - - QByteArray key; - QByteArray lang; - - bool operator< (const QImageTextKeyLang& other) const - { return key < other.key || (key==other.key && lang < other.lang); } - bool operator== (const QImageTextKeyLang& other) const - { return key==other.key && lang==other.lang; } - inline bool operator!= (const QImageTextKeyLang &other) const - { return !operator==(other); } -private: - friend class QImage; - QImageTextKeyLang(bool /*dummy*/) {} -}; -#endif typedef void (*QImageCleanupFunction)(void*); @@ -179,7 +153,6 @@ public: Format format() const; -#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QIMAGE_COMPAT_CPP) Q_REQUIRED_RESULT Q_ALWAYS_INLINE QImage convertToFormat(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor) const & { return convertToFormat_helper(f, flags); } Q_REQUIRED_RESULT Q_ALWAYS_INLINE QImage convertToFormat(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor) && @@ -189,9 +162,6 @@ public: else return convertToFormat_helper(f, flags); } -#else - Q_REQUIRED_RESULT QImage convertToFormat(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor) const; -#endif Q_REQUIRED_RESULT QImage convertToFormat(Format f, const QVector<QRgb> &colorTable, Qt::ImageConversionFlags flags = Qt::AutoColor) const; bool reinterpretAsFormat(Format f); @@ -217,19 +187,12 @@ public: const uchar *bits() const; const uchar *constBits() const; -#if QT_DEPRECATED_SINCE(5, 10) - QT_DEPRECATED_X("Use sizeInBytes") int byteCount() const; -#endif qsizetype sizeInBytes() const; uchar *scanLine(int); const uchar *scanLine(int) const; const uchar *constScanLine(int) const; -#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) qsizetype bytesPerLine() const; -#else - int bytesPerLine() const; -#endif bool valid(int x, int y) const; bool valid(const QPoint &pt) const; @@ -250,11 +213,7 @@ public: void setPixelColor(const QPoint &pt, const QColor &c); QVector<QRgb> colorTable() const; -#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) void setColorTable(const QVector<QRgb> &colors); -#else - void setColorTable(const QVector<QRgb> colors); -#endif qreal devicePixelRatio() const; void setDevicePixelRatio(qreal scaleFactor); @@ -286,7 +245,6 @@ public: static QMatrix trueMatrix(const QMatrix &, int w, int h); QImage transformed(const QTransform &matrix, Qt::TransformationMode mode = Qt::FastTransformation) const; static QTransform trueMatrix(const QTransform &, int w, int h); -#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QIMAGE_COMPAT_CPP) QImage mirrored(bool horizontally = false, bool vertically = true) const & { return mirrored_helper(horizontally, vertically); } QImage &&mirrored(bool horizontally = false, bool vertically = true) && @@ -295,10 +253,6 @@ public: { return rgbSwapped_helper(); } QImage &&rgbSwapped() && { rgbSwapped_inplace(); return std::move(*this); } -#else - QImage mirrored(bool horizontally = false, bool vertically = true) const; - QImage rgbSwapped() const; -#endif void invertPixels(InvertMode = InvertRgb); QColorSpace colorSpace() const; @@ -321,9 +275,6 @@ public: inline static QImage fromData(const QByteArray &data, const char *format = nullptr) { return fromData(reinterpret_cast<const uchar *>(data.constData()), data.size(), format); } -#if QT_DEPRECATED_SINCE(5, 0) - QT_DEPRECATED inline int serialNumber() const { return cacheKey() >> 32; } -#endif qint64 cacheKey() const; QPaintEngine *paintEngine() const override; @@ -349,20 +300,6 @@ public: CGImageRef toCGImage() const Q_DECL_CF_RETURNS_RETAINED; #endif -#if QT_DEPRECATED_SINCE(5, 0) - QT_DEPRECATED inline QString text(const char *key, const char *lang = nullptr) const; - QT_DEPRECATED inline QList<QImageTextKeyLang> textList() const; - QT_DEPRECATED inline QStringList textLanguages() const; - QT_DEPRECATED inline QString text(const QImageTextKeyLang&) const; - QT_DEPRECATED inline void setText(const char* key, const char* lang, const QString&); -#endif - -#if QT_DEPRECATED_SINCE(5, 0) - QT_DEPRECATED inline int numColors() const; - QT_DEPRECATED inline void setNumColors(int); - QT_DEPRECATED inline int numBytes() const; -#endif - protected: virtual int metric(PaintDeviceMetric metric) const override; QImage mirrored_helper(bool horizontal, bool vertical) const; @@ -397,99 +334,6 @@ inline void QImage::setPixel(const QPoint &pt, uint index_or_rgb) { setPixel(pt. inline QColor QImage::pixelColor(const QPoint &pt) const { return pixelColor(pt.x(), pt.y()); } inline void QImage::setPixelColor(const QPoint &pt, const QColor &c) { setPixelColor(pt.x(), pt.y(), c); } -#if QT_DEPRECATED_SINCE(5, 0) - -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED - -inline QString QImage::text(const char* key, const char* lang) const -{ - if (!d) - return QString(); - QString k = QString::fromLatin1(key); - if (lang && *lang) - k += QLatin1Char('/') + QString::fromLatin1(lang); - return text(k); -} - -inline QList<QImageTextKeyLang> QImage::textList() const -{ - QList<QImageTextKeyLang> imageTextKeys; - if (!d) - return imageTextKeys; - QStringList keys = textKeys(); - for (int i = 0; i < keys.size(); ++i) { - int index = keys.at(i).indexOf(QLatin1Char('/')); - if (index > 0) { - QImageTextKeyLang tkl(true); - tkl.key = keys.at(i).left(index).toLatin1(); - tkl.lang = keys.at(i).mid(index+1).toLatin1(); - imageTextKeys += tkl; - } - } - - return imageTextKeys; -} - -inline QStringList QImage::textLanguages() const -{ - if (!d) - return QStringList(); - QStringList keys = textKeys(); - QStringList languages; - for (int i = 0; i < keys.size(); ++i) { - int index = keys.at(i).indexOf(QLatin1Char('/')); - if (index > 0) - languages += keys.at(i).mid(index+1); - } - - return languages; -} - -inline QString QImage::text(const QImageTextKeyLang&kl) const -{ - if (!d) - return QString(); - QString k = QString::fromLatin1(kl.key.constData()); - if (!kl.lang.isEmpty()) - k += QLatin1Char('/') + QString::fromLatin1(kl.lang.constData()); - return text(k); -} - -inline void QImage::setText(const char* key, const char* lang, const QString &s) -{ - if (!d) - return; - detach(); - - // In case detach() ran out of memory - if (!d) - return; - - QString k = QString::fromLatin1(key); - if (lang && *lang) - k += QLatin1Char('/') + QString::fromLatin1(lang); - setText(k, s); -} - -QT_WARNING_POP - -inline int QImage::numColors() const -{ - return colorCount(); -} - -inline void QImage::setNumColors(int n) -{ - setColorCount(n); -} - -inline int QImage::numBytes() const -{ - return int(sizeInBytes()); -} -#endif - // QImage stream functions #if !defined(QT_NO_DATASTREAM) diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index 0930955f5a..9277472c3c 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -140,7 +140,7 @@ QImageData::calculateImageParameters(qsizetype width, qsizetype height, qsizetyp qsizetype dummy; if (mul_overflow(height, qsizetype(sizeof(uchar *)), &dummy)) return invalid; // why is this here? -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) +#if 1 || QT_VERSION < QT_VERSION_CHECK(6,0,0) // ### can only fix this if QImage dimensions are not int anymore // Disallow images where width * depth calculations might overflow if (width > (INT_MAX - 31) / depth) return invalid; diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp index 3a32cc7f15..d469ac8aae 100644 --- a/src/gui/image/qpicture.cpp +++ b/src/gui/image/qpicture.cpp @@ -264,14 +264,14 @@ void QPicture::setData(const char* data, uint size) \sa save() */ -bool QPicture::load(const QString &fileName, const char *format) +bool QPicture::load(const QString &fileName) { QFile f(fileName); if (!f.open(QIODevice::ReadOnly)) { operator=(QPicture()); return false; } - return load(&f, format); + return load(&f); } /*! @@ -280,21 +280,8 @@ bool QPicture::load(const QString &fileName, const char *format) \a dev is the device to use for loading. */ -bool QPicture::load(QIODevice *dev, const char *format) +bool QPicture::load(QIODevice *dev) { - if(format) { -#ifndef QT_NO_PICTUREIO - QPictureIO io(dev, format); - if (io.read()) { - operator=(io.picture()); - return true; - } -#endif - qWarning("QPicture::load: No such picture format: %s", format); - operator=(QPicture()); - return false; - } - detach(); QByteArray a = dev->readAll(); @@ -312,7 +299,7 @@ bool QPicture::load(QIODevice *dev, const char *format) \sa load() */ -bool QPicture::save(const QString &fileName, const char *format) +bool QPicture::save(const QString &fileName) { if (paintingActive()) { qWarning("QPicture::save: still being painted on. " @@ -320,27 +307,10 @@ bool QPicture::save(const QString &fileName, const char *format) return false; } - - if(format) { -#ifndef QT_NO_PICTUREIO - QPictureIO io(fileName, format); - bool result = io.write(); - if (result) { - operator=(io.picture()); - } else if (format) -#else - bool result = false; -#endif - { - qWarning("QPicture::save: No such picture format: %s", format); - } - return result; - } - QFile f(fileName); if (!f.open(QIODevice::WriteOnly)) return false; - return save(&f, format); + return save(&f); } /*! @@ -349,7 +319,7 @@ bool QPicture::save(const QString &fileName, const char *format) \a dev is the device to use for saving. */ -bool QPicture::save(QIODevice *dev, const char *format) +bool QPicture::save(QIODevice *dev) { if (paintingActive()) { qWarning("QPicture::save: still being painted on. " @@ -357,22 +327,6 @@ bool QPicture::save(QIODevice *dev, const char *format) return false; } - if(format) { -#ifndef QT_NO_PICTUREIO - QPictureIO io(dev, format); - bool result = io.write(); - if (result) { - operator=(io.picture()); - } else if (format) -#else - bool result = false; -#endif - { - qWarning("QPicture::save: No such picture format: %s", format); - } - return result; - } - dev->write(d_func()->pictb.buffer(), d_func()->pictb.buffer().size()); return true; } @@ -1189,780 +1143,6 @@ QDataStream &operator>>(QDataStream &s, QPicture &r) } #endif // QT_NO_DATASTREAM - -#ifndef QT_NO_PICTUREIO - -QT_BEGIN_INCLUDE_NAMESPACE -#include "qregexp.h" -#include "qpictureformatplugin.h" -QT_END_INCLUDE_NAMESPACE - -#if QT_DEPRECATED_SINCE(5, 10) -/*! - \obsolete - - Returns a string that specifies the picture format of the file \a - fileName, or \nullptr if the file cannot be read or if the format - is not recognized. - - \sa load(), save() -*/ - -const char* QPicture::pictureFormat(const QString &fileName) -{ - const QByteArray format = QPictureIO::pictureFormat(fileName); - // This function returns a const char * from a QByteArray. - // Double check that the QByteArray is not detached, otherwise - // we would return a dangling pointer. - Q_ASSERT(!format.isDetached()); - return format; -} - -/*! - \obsolete - - Returns a list of picture formats that are supported for picture - input. - - \sa outputFormats(), inputFormatList(), QPictureIO -*/ -QList<QByteArray> QPicture::inputFormats() -{ - return QPictureIO::inputFormats(); -} - -static QStringList qToStringList(const QList<QByteArray> &arr) -{ - QStringList list; - const int count = arr.count(); - list.reserve(count); - for (int i = 0; i < count; ++i) - list.append(QString::fromLatin1(arr.at(i))); - return list; -} - -/*! - \obsolete - - Returns a list of picture formats that are supported for picture - input. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \snippet picture/picture.cpp 2 - - \sa outputFormatList(), inputFormats(), QPictureIO -*/ -QStringList QPicture::inputFormatList() -{ - return qToStringList(QPictureIO::inputFormats()); -} - - -/*! - \obsolete - - Returns a list of picture formats that are supported for picture - output. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \snippet picture/picture.cpp 3 - - \sa inputFormatList(), outputFormats(), QPictureIO -*/ -QStringList QPicture::outputFormatList() -{ - return qToStringList(QPictureIO::outputFormats()); -} - -/*! - \obsolete - - Returns a list of picture formats that are supported for picture - output. - - \sa inputFormats(), outputFormatList(), QPictureIO -*/ -QList<QByteArray> QPicture::outputFormats() -{ - return QPictureIO::outputFormats(); -} -#endif // QT_DEPRECATED_SINCE(5, 10) - -/***************************************************************************** - QPictureIO member functions - *****************************************************************************/ - -/*! - \obsolete - - \class QPictureIO - - \brief The QPictureIO class contains parameters for loading and - saving pictures. - - \ingroup painting - \ingroup io - \inmodule QtGui - - QPictureIO contains a QIODevice object that is used for picture data - I/O. The programmer can install new picture file formats in addition - to those that Qt provides. - - You don't normally need to use this class; QPicture::load(), - QPicture::save(). - - \sa QPicture, QPixmap, QFile -*/ - -struct QPictureIOData -{ - QPicture pi; // picture - int iostat; // IO status - QByteArray frmt; // picture format - QIODevice *iodev; // IO device - QString fname; // file name - QString descr; // picture description - const char *parameters; - int quality; - float gamma; -}; - -/*! - Constructs a QPictureIO object with all parameters set to zero. -*/ - -QPictureIO::QPictureIO() -{ - init(); -} - -/*! - Constructs a QPictureIO object with the I/O device \a ioDevice and a - \a format tag. -*/ - -QPictureIO::QPictureIO(QIODevice *ioDevice, const char *format) -{ - init(); - d->iodev = ioDevice; - d->frmt = format; -} - -/*! - Constructs a QPictureIO object with the file name \a fileName and a - \a format tag. -*/ - -QPictureIO::QPictureIO(const QString &fileName, const char* format) -{ - init(); - d->frmt = format; - d->fname = fileName; -} - -/*! - Contains initialization common to all QPictureIO constructors. -*/ - -void QPictureIO::init() -{ - d = new QPictureIOData(); - d->parameters = nullptr; - d->quality = -1; // default quality of the current format - d->gamma=0.0f; - d->iostat = 0; - d->iodev = nullptr; -} - -/*! - Destroys the object and all related data. -*/ - -QPictureIO::~QPictureIO() -{ - if (d->parameters) - delete [] d->parameters; - delete d; -} - - -/***************************************************************************** - QPictureIO picture handler functions - *****************************************************************************/ - -class QPictureHandler -{ -public: - QPictureHandler(const char *f, const char *h, const QByteArray& fl, - picture_io_handler r, picture_io_handler w); - QByteArray format; // picture format - QRegExp header; // picture header pattern - enum TMode { Untranslated=0, TranslateIn, TranslateInOut } text_mode; - picture_io_handler read_picture; // picture read function - picture_io_handler write_picture; // picture write function - bool obsolete; // support not "published" -}; - -QPictureHandler::QPictureHandler(const char *f, const char *h, const QByteArray& fl, - picture_io_handler r, picture_io_handler w) - : format(f), header(QString::fromLatin1(h)) -{ - text_mode = Untranslated; - if (fl.contains('t')) - text_mode = TranslateIn; - else if (fl.contains('T')) - text_mode = TranslateInOut; - obsolete = fl.contains('O'); - read_picture = r; - write_picture = w; -} - -typedef QList<QPictureHandler *> QPHList; -Q_GLOBAL_STATIC(QPHList, pictureHandlers) - -void qt_init_picture_plugins() -{ - typedef QMultiMap<int, QString> PluginKeyMap; - typedef PluginKeyMap::const_iterator PluginKeyMapConstIterator; - - static QBasicMutex mutex; - const auto locker = qt_scoped_lock(mutex); - static QFactoryLoader loader(QPictureFormatInterface_iid, - QStringLiteral("/pictureformats")); - - const PluginKeyMap keyMap = loader.keyMap(); - const PluginKeyMapConstIterator cend = keyMap.constEnd(); - for (PluginKeyMapConstIterator it = keyMap.constBegin(); it != cend; ++it) { - if (QPictureFormatPlugin *format = qobject_cast<QPictureFormatPlugin*>(loader.instance(it.key()))) - format->installIOHandler(it.value()); - } -} - -static void cleanup() -{ - // make sure that picture handlers are delete before plugin manager - if (QPHList *list = pictureHandlers()) { - qDeleteAll(*list); - list->clear(); - } -} - -void qt_init_picture_handlers() // initialize picture handlers -{ - static QBasicAtomicInt done = Q_BASIC_ATOMIC_INITIALIZER(0); - if (done.testAndSetRelaxed(0, 1)) { - qAddPostRoutine(cleanup); - } -} - -static QPictureHandler *get_picture_handler(const char *format) -{ // get pointer to handler - qt_init_picture_handlers(); - qt_init_picture_plugins(); - if (QPHList *list = pictureHandlers()) { - for (int i = 0; i < list->size(); ++i) { - if (list->at(i)->format == format) - return list->at(i); - } - } - return nullptr; // no such handler -} - - -/*! - Defines a picture I/O handler for the picture format called \a - format, which is recognized using the regular - expression defined in \a header, read using \a readPicture and - written using \a writePicture. - - \a flags is a string of single-character flags for this format. - The only flag defined currently is T (upper case), so the only - legal value for \a flags are "T" and the empty string. The "T" - flag means that the picture file is a text file, and Qt should treat - all newline conventions as equivalent. (XPM files and some PPM - files are text files for example.) - - \a format is used to select a handler to write a QPicture; \a header - is used to select a handler to read an picture file. - - If \a readPicture is \nullptr, the QPictureIO will not be able - to read pictures in \a format. If \a writePicture is \nullptr, - the QPictureIO will not be able to write pictures in \a format. If - both are null, the QPictureIO object is valid but useless. - - Example: - \snippet picture/picture.cpp 6 - \codeline - \snippet picture/picture.cpp 7 - \codeline - \snippet picture/picture.cpp 8 - - Before the regular expression test, all the 0 bytes in the file header are - converted to 1 bytes. This is done because when Qt was ASCII-based, QRegExp - could not handle 0 bytes in strings. - - The regexp is only applied on the first 14 bytes of the file. - - (Note that if one handlerIO supports writing a format and another - supports reading it, Qt supports both reading and writing. If two - handlers support the same operation, Qt chooses one arbitrarily.) -*/ - -void QPictureIO::defineIOHandler(const char *format, - const char *header, - const char *flags, - picture_io_handler readPicture, - picture_io_handler writePicture) -{ - qt_init_picture_handlers(); - if (QPHList *list = pictureHandlers()) { - QPictureHandler *p; - p = new QPictureHandler(format, header, QByteArray(flags), readPicture, writePicture); - list->prepend(p); - } -} - - -/***************************************************************************** - QPictureIO normal member functions - *****************************************************************************/ - -/*! - Returns the picture currently set. - - \sa setPicture() -*/ -const QPicture &QPictureIO::picture() const { return d->pi; } - -/*! - Returns the picture's IO status. A non-zero value indicates an - error, whereas 0 means that the IO operation was successful. - - \sa setStatus() -*/ -int QPictureIO::status() const { return d->iostat; } - -/*! - Returns the picture format string or \nullptr if no format has been - explicitly set. -*/ -const char *QPictureIO::format() const { return d->frmt; } - -/*! - Returns the IO device currently set. - - \sa setIODevice() -*/ -QIODevice *QPictureIO::ioDevice() const { return d->iodev; } - -/*! - Returns the file name currently set. - - \sa setFileName() -*/ -QString QPictureIO::fileName() const { return d->fname; } - - -/*! - Returns the picture description string. - - \sa setDescription() -*/ -QString QPictureIO::description() const { return d->descr; } - -/*! - Sets the picture to \a picture. - - \sa picture() -*/ -void QPictureIO::setPicture(const QPicture &picture) -{ - d->pi = picture; -} - -/*! - Sets the picture IO status to \a status. A non-zero value indicates - an error, whereas 0 means that the IO operation was successful. - - \sa status() -*/ -void QPictureIO::setStatus(int status) -{ - d->iostat = status; -} - -/*! - Sets the picture format to \a format for the picture to be read or - written. - - It is necessary to specify a format before writing an picture, but - it is not necessary to specify a format before reading an picture. - - If no format has been set, Qt guesses the picture format before - reading it. If a format is set the picture will only be read if it - has that format. - - \sa read(), write(), format() -*/ -void QPictureIO::setFormat(const char *format) -{ - d->frmt = format; -} - -/*! - Sets the IO device to be used for reading or writing an picture. - - Setting the IO device allows pictures to be read/written to any - block-oriented QIODevice. - - If \a ioDevice is not null, this IO device will override file name - settings. - - \sa setFileName() -*/ -void QPictureIO::setIODevice(QIODevice *ioDevice) -{ - d->iodev = ioDevice; -} - -/*! - Sets the name of the file to read or write an picture from to \a - fileName. - - \sa setIODevice() -*/ -void QPictureIO::setFileName(const QString &fileName) -{ - d->fname = fileName; -} - -/*! - Returns the quality of the written picture, related to the - compression ratio. - - \sa setQuality(), QPicture::save() -*/ -int QPictureIO::quality() const -{ - return d->quality; -} - -/*! - Sets the quality of the written picture to \a q, related to the - compression ratio. - - \a q must be in the range -1..100. Specify 0 to obtain small - compressed files, 100 for large uncompressed files. (-1 signifies - the default compression.) - - \sa quality(), QPicture::save() -*/ - -void QPictureIO::setQuality(int q) -{ - d->quality = q; -} - -/*! - Returns the picture's parameters string. - - \sa setParameters() -*/ - -const char *QPictureIO::parameters() const -{ - return d->parameters; -} - -/*! - Sets the picture's parameter string to \a parameters. This is for - picture handlers that require special parameters. - - Although the current picture formats supported by Qt ignore the - parameters string, it may be used in future extensions or by - contributions (for example, JPEG). - - \sa parameters() -*/ - -void QPictureIO::setParameters(const char *parameters) -{ - if (d->parameters) - delete [] d->parameters; - d->parameters = qstrdup(parameters); -} - -/*! - Sets the gamma value at which the picture will be viewed to \a - gamma. If the picture format stores a gamma value for which the - picture is intended to be used, then this setting will be used to - modify the picture. Setting to 0.0 will disable gamma correction - (i.e. any specification in the file will be ignored). - - The default value is 0.0. - - \sa gamma() -*/ -void QPictureIO::setGamma(float gamma) -{ - d->gamma=gamma; -} - -/*! - Returns the gamma value at which the picture will be viewed. - - \sa setGamma() -*/ -float QPictureIO::gamma() const -{ - return d->gamma; -} - -/*! - Sets the picture description string for picture handlers that support - picture descriptions to \a description. - - Currently, no picture format supported by Qt uses the description - string. -*/ - -void QPictureIO::setDescription(const QString &description) -{ - d->descr = description; -} - - -/*! - Returns a string that specifies the picture format of the file \a - fileName, or null if the file cannot be read or if the format is - not recognized. -*/ - -QByteArray QPictureIO::pictureFormat(const QString &fileName) -{ - QFile file(fileName); - QByteArray format; - if (!file.open(QIODevice::ReadOnly)) - return format; - format = pictureFormat(&file); - file.close(); - return format; -} - -/*! - \overload - - Returns a string that specifies the picture format of the picture read - from IO device \a d, or 0 if the device cannot be read or if the - format is not recognized. - - Make sure that \a d is at the right position in the device (for - example, at the beginning of the file). - - \sa QIODevice::pos() -*/ - -QByteArray QPictureIO::pictureFormat(QIODevice *d) -{ - // if you change this change the documentation for defineIOHandler() - const int buflen = 14; - - char buf[buflen]; - char buf2[buflen]; - qt_init_picture_handlers(); - qt_init_picture_plugins(); - int pos = d->pos(); // save position - int rdlen = d->read(buf, buflen); // read a few bytes - - QByteArray format; - if (rdlen != buflen) - return format; - - memcpy(buf2, buf, buflen); - - for (int n = 0; n < rdlen; n++) - if (buf[n] == '\0') - buf[n] = '\001'; - if (rdlen > 0) { - buf[rdlen - 1] = '\0'; - QString bufStr = QString::fromLatin1(buf); - if (QPHList *list = pictureHandlers()) { - for (int i = 0; i < list->size(); ++i) { - if (list->at(i)->header.indexIn(bufStr) != -1) { // try match with headers - format = list->at(i)->format; - break; - } - } - } - } - d->seek(pos); // restore position - return format; -} - -/*! - Returns a sorted list of picture formats that are supported for - picture input. -*/ -QList<QByteArray> QPictureIO::inputFormats() -{ - QList<QByteArray> result; - - qt_init_picture_handlers(); - qt_init_picture_plugins(); - - if (QPHList *list = pictureHandlers()) { - for (int i = 0; i < list->size(); ++i) { - QPictureHandler *p = list->at(i); - if (p->read_picture && !p->obsolete && !result.contains(p->format)) - result.append(p->format); - } - } - std::sort(result.begin(), result.end()); - - return result; -} - -/*! - Returns a sorted list of picture formats that are supported for - picture output. -*/ -QList<QByteArray> QPictureIO::outputFormats() -{ - qt_init_picture_handlers(); - qt_init_picture_plugins(); - - QList<QByteArray> result; - if (QPHList *list = pictureHandlers()) { - for (int i = 0; i < list->size(); ++i) { - QPictureHandler *p = list->at(i); - if (p->write_picture && !p->obsolete && !result.contains(p->format)) - result.append(p->format); - } - } - return result; -} - - - -/*! - Reads an picture into memory and returns \c true if the picture was - successfully read; otherwise returns \c false. - - Before reading an picture you must set an IO device or a file name. - If both an IO device and a file name have been set, the IO device - will be used. - - Setting the picture file format string is optional. - - Note that this function does \e not set the \l{format()}{format} used to read the picture. If you need that - information, use the pictureFormat() static functions. - - Example: - - \snippet picture/picture.cpp 4 - - \sa setIODevice(), setFileName(), setFormat(), write(), QPixmap::load() -*/ -bool QPictureIO::read() -{ - QFile file; - QByteArray picture_format; - QPictureHandler *h; - - if (d->iodev) { // read from io device - // ok, already open - } else if (!d->fname.isEmpty()) { // read from file - file.setFileName(d->fname); - if (!file.open(QIODevice::ReadOnly)) - return false; // cannot open file - d->iodev = &file; - } else { // no file name or io device - return false; - } - if (d->frmt.isEmpty()) { - // Try to guess format - picture_format = pictureFormat(d->iodev); // get picture format - if (picture_format.isEmpty()) { - if (file.isOpen()) { // unknown format - file.close(); - d->iodev = nullptr; - } - return false; - } - } else { - picture_format = d->frmt; - } - - h = get_picture_handler(picture_format); - if (file.isOpen()) { -#if !defined(Q_OS_UNIX) - if (h && h->text_mode) { // reopen in translated mode - file.close(); - file.open(QIODevice::ReadOnly | QIODevice::Text); - } - else -#endif - file.seek(0); // position to start - } - d->iostat = 1; // assume error - - if (h && h->read_picture) - (*h->read_picture)(this); - - if (file.isOpen()) { // picture was read using file - file.close(); - d->iodev = nullptr; - } - return d->iostat == 0; // picture successfully read? -} - - -/*! - Writes an picture to an IO device and returns \c true if the picture was - successfully written; otherwise returns \c false. - - Before writing an picture you must set an IO device or a file name. - If both an IO device and a file name have been set, the IO device - will be used. - - The picture will be written using the specified picture format. - - Example: - \snippet picture/picture.cpp 5 - - \sa setIODevice(), setFileName(), setFormat(), read(), QPixmap::save() -*/ -bool QPictureIO::write() -{ - if (d->frmt.isEmpty()) - return false; - QPictureHandler *h = get_picture_handler(d->frmt); - if (!h || !h->write_picture) { - qWarning("QPictureIO::write: No such picture format handler: %s", - format()); - return false; - } - QFile file; - if (!d->iodev && !d->fname.isEmpty()) { - file.setFileName(d->fname); - bool translate = h->text_mode==QPictureHandler::TranslateInOut; - QIODevice::OpenMode fmode = translate ? QIODevice::WriteOnly | QIODevice::Text : QIODevice::OpenMode(QIODevice::WriteOnly); - if (!file.open(fmode)) // couldn't create file - return false; - d->iodev = &file; - } - d->iostat = 1; - (*h->write_picture)(this); - if (file.isOpen()) { // picture was written using file - file.close(); - d->iodev = nullptr; - } - return d->iostat == 0; // picture successfully written? -} -#endif //QT_NO_PICTUREIO - QT_END_NAMESPACE #endif // QT_NO_PICTURE diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h index 189e57b9a3..34860985ed 100644 --- a/src/gui/image/qpicture.h +++ b/src/gui/image/qpicture.h @@ -48,7 +48,6 @@ QT_BEGIN_NAMESPACE - #ifndef QT_NO_PICTURE class QPicturePrivate; @@ -69,10 +68,10 @@ public: bool play(QPainter *p); - bool load(QIODevice *dev, const char *format = nullptr); - bool load(const QString &fileName, const char *format = nullptr); - bool save(QIODevice *dev, const char *format = nullptr); - bool save(const QString &fileName, const char *format = nullptr); + bool load(QIODevice *dev); + bool load(const QString &fileName); + bool save(QIODevice *dev); + bool save(const QString &fileName); QRect boundingRect() const; void setBoundingRect(const QRect &r); @@ -88,14 +87,6 @@ public: friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &in, const QPicture &p); friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &in, QPicture &p); -#if QT_DEPRECATED_SINCE(5, 10) - static QT_DEPRECATED const char* pictureFormat(const QString &fileName); - static QT_DEPRECATED QList<QByteArray> inputFormats(); - static QT_DEPRECATED QList<QByteArray> outputFormats(); - static QT_DEPRECATED QStringList inputFormatList(); - static QT_DEPRECATED QStringList outputFormatList(); -#endif // QT_DEPRECATED_SINCE(5, 10) - QPaintEngine *paintEngine() const override; protected: @@ -118,67 +109,6 @@ public: Q_DECLARE_SHARED(QPicture) - -#ifndef QT_NO_PICTUREIO -class QIODevice; -class QPictureIO; -typedef void (*picture_io_handler)(QPictureIO *); // picture IO handler - -struct QPictureIOData; - -class Q_GUI_EXPORT QPictureIO -{ -public: - QPictureIO(); - QPictureIO(QIODevice *ioDevice, const char *format); - QPictureIO(const QString &fileName, const char *format); - ~QPictureIO(); - - const QPicture &picture() const; - int status() const; - const char *format() const; - QIODevice *ioDevice() const; - QString fileName() const; - int quality() const; - QString description() const; - const char *parameters() const; - float gamma() const; - - void setPicture(const QPicture &); - void setStatus(int); - void setFormat(const char *); - void setIODevice(QIODevice *); - void setFileName(const QString &); - void setQuality(int); - void setDescription(const QString &); - void setParameters(const char *); - void setGamma(float); - - bool read(); - bool write(); - - static QByteArray pictureFormat(const QString &fileName); - static QByteArray pictureFormat(QIODevice *); - static QList<QByteArray> inputFormats(); - static QList<QByteArray> outputFormats(); - - static void defineIOHandler(const char *format, - const char *header, - const char *flags, - picture_io_handler read_picture, - picture_io_handler write_picture); - -private: - Q_DISABLE_COPY(QPictureIO) - - void init(); - - QPictureIOData *d; -}; - -#endif //QT_NO_PICTUREIO - - /***************************************************************************** QPicture stream functions *****************************************************************************/ diff --git a/src/gui/image/qpictureformatplugin.cpp b/src/gui/image/qpictureformatplugin.cpp deleted file mode 100644 index ef57ad720f..0000000000 --- a/src/gui/image/qpictureformatplugin.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qpictureformatplugin.h" -#if !defined(QT_NO_PICTURE) -#include "qpicture.h" - -QT_BEGIN_NAMESPACE - -/*! - \obsolete - - \class QPictureFormatPlugin - \brief The QPictureFormatPlugin class provides an abstract base - for custom picture format plugins. - - \ingroup plugins - \inmodule QtGui - - The picture format plugin is a simple plugin interface that makes - it easy to create custom picture formats that can be used - transparently by applications. - - Writing an picture format plugin is achieved by subclassing this - base class, reimplementing the pure virtual functions - loadPicture(), savePicture(), and installIOHandler(), and - exporting the class with the Q_PLUGIN_METADATA() macro. - - The json file containing the metadata should contain one entry - with the list of picture formats supported by the plugin: - - \code - { "Keys": [ "mypictureformat" ] } - \endcode - - \sa {How to Create Qt Plugins} -*/ - -/*! - \fn bool QPictureFormatPlugin::installIOHandler(const QString &format) - - Installs a QPictureIO picture I/O handler for the picture format \a - format. Returns \c true on success. -*/ - - -/*! - Constructs an picture format plugin with the given \a parent. - This is invoked automatically by the moc generated code that exports the plugin. -*/ -QPictureFormatPlugin::QPictureFormatPlugin(QObject *parent) - : QObject(parent) -{ -} - -/*! - Destroys the picture format plugin. - - You never have to call this explicitly. Qt destroys a plugin - automatically when it is no longer used. -*/ -QPictureFormatPlugin::~QPictureFormatPlugin() -{ -} - - -/*! - Loads the picture stored in the file called \a fileName, with the - given \a format, into *\a picture. Returns \c true on success; - otherwise returns \c false. - - \sa savePicture() -*/ -bool QPictureFormatPlugin::loadPicture(const QString &format, const QString &fileName, QPicture *picture) -{ - Q_UNUSED(format) - Q_UNUSED(fileName) - Q_UNUSED(picture) - return false; -} - -/*! - Saves the given \a picture into the file called \a fileName, - using the specified \a format. Returns \c true on success; otherwise - returns \c false. - - \sa loadPicture() -*/ -bool QPictureFormatPlugin::savePicture(const QString &format, const QString &fileName, const QPicture &picture) -{ - Q_UNUSED(format) - Q_UNUSED(fileName) - Q_UNUSED(picture) - return false; -} - -#endif // QT_NO_PICTURE - -QT_END_NAMESPACE diff --git a/src/gui/itemmodels/qstandarditemmodel.h b/src/gui/itemmodels/qstandarditemmodel.h index a9ee25da75..f1c6e6df5c 100644 --- a/src/gui/itemmodels/qstandarditemmodel.h +++ b/src/gui/itemmodels/qstandarditemmodel.h @@ -53,8 +53,6 @@ QT_REQUIRE_CONFIG(standarditemmodel); QT_BEGIN_NAMESPACE -template <class T> class QList; - class QStandardItemModel; class QStandardItemPrivate; @@ -344,8 +342,11 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - // Qt 6: add override keyword - bool clearItemData(const QModelIndex &index); + bool clearItemData(const QModelIndex &index) +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + override +#endif + ; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index 9c80f1e2cc..3784abdacc 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -48,11 +48,8 @@ HEADERS += \ kernel/qinputmethod.h \ kernel/qinputmethod_p.h \ kernel/qinternalmimedata_p.h \ - kernel/qkeysequence.h \ - kernel/qkeysequence_p.h \ kernel/qkeymapper_p.h \ kernel/qpalette.h \ - kernel/qshortcutmap_p.h \ kernel/qsessionmanager.h \ kernel/qsessionmanager_p.h \ kernel/qwindowdefs.h \ @@ -108,12 +105,10 @@ SOURCES += \ kernel/qevent.cpp \ kernel/qinputmethod.cpp \ kernel/qinternalmimedata.cpp \ - kernel/qkeysequence.cpp \ kernel/qkeymapper.cpp \ kernel/qpalette.cpp \ kernel/qguivariant.cpp \ kernel/qscreen.cpp \ - kernel/qshortcutmap.cpp \ kernel/qstylehints.cpp \ kernel/qtouchdevice.cpp \ kernel/qplatformsharedgraphicscache.cpp \ @@ -131,6 +126,18 @@ SOURCES += \ kernel/qhighdpiscaling.cpp \ kernel/qtestsupport_gui.cpp +qtConfig(action) { + HEADERS += \ + kernel/qguiaction.h \ + kernel/qguiaction_p.h \ + kernel/qguiactiongroup.h \ + kernel/qguiactiongroup_p.h + + SOURCES += \ + kernel/qguiactiongroup.cpp \ + kernel/qguiaction.cpp +} + qtConfig(draganddrop) { HEADERS += \ kernel/qdnd_p.h \ @@ -160,4 +167,17 @@ qtConfig(opengl) { kernel/qopenglwindow.cpp } +qtConfig(shortcut) { + HEADERS += \ + kernel/qguishortcut.h \ + kernel/qguishortcut_p.h \ + kernel/qshortcutmap_p.h \ + kernel/qkeysequence.h \ + kernel/qkeysequence_p.h + SOURCES += \ + kernel/qguishortcut.cpp \ + kernel/qshortcutmap.cpp \ + kernel/qkeysequence.cpp +} + win32:HEADERS+=kernel/qwindowdefs_win.h diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index c69cc8ce6f..ede68f0719 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -1225,7 +1225,7 @@ Qt::KeyboardModifiers QKeyEvent::modifiers() const return QInputEvent::modifiers(); } -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) /*! \fn bool QKeyEvent::matches(QKeySequence::StandardKey key) const \since 4.2 @@ -1241,7 +1241,7 @@ bool QKeyEvent::matches(QKeySequence::StandardKey matchKey) const const QList<QKeySequence> bindings = QKeySequence::keyBindings(matchKey); return bindings.contains(QKeySequence(searchkey)); } -#endif // QT_NO_SHORTCUT +#endif // QT_CONFIG(shortcut) /*! @@ -2696,10 +2696,6 @@ QNativeGestureEvent::QNativeGestureEvent(Qt::NativeGestureType type, const QPoin { } #endif -typedef QHash<const QNativeGestureEvent*, const QTouchDevice*> NativeGestureEventDataHash; -// ### Qt6: move this to a member in QNativeGestureEvent -Q_GLOBAL_STATIC(NativeGestureEventDataHash, g_nativeGestureEventDataHash) - /*! Constructs a native gesture event of type \a type originating from \a device. @@ -2714,27 +2710,20 @@ QNativeGestureEvent::QNativeGestureEvent(Qt::NativeGestureType type, const QTouc const QPointF &screenPos, qreal realValue, ulong sequenceId, quint64 intValue) : QInputEvent(QEvent::NativeGesture), mGestureType(type), mLocalPos(localPos), mWindowPos(windowPos), mScreenPos(screenPos), mRealValue(realValue), - mSequenceId(sequenceId), mIntValue(intValue) + mSequenceId(sequenceId), mIntValue(intValue), mDevice(device) { - g_nativeGestureEventDataHash->insert(this, device); } QNativeGestureEvent::~QNativeGestureEvent() -{ - g_nativeGestureEventDataHash->remove(this); -} + = default; /*! + \fn const QTouchDevice *QNativeGestureEvent::device() const \since 5.10 Returns the device. */ -const QTouchDevice *QNativeGestureEvent::device() const -{ - return g_nativeGestureEventDataHash->value(this); -} - /*! \fn QNativeGestureEvent::gestureType() const \since 5.2 @@ -3336,18 +3325,18 @@ QWhatsThisClickedEvent::~QWhatsThisClickedEvent() /*! \class QActionEvent \brief The QActionEvent class provides an event that is generated - when a QAction is added, removed, or changed. + when a QGuiAction is added, removed, or changed. \ingroup events \inmodule QtGui - Actions can be added to widgets using QWidget::addAction(). This - generates an \l ActionAdded event, which you can handle to provide + Actions can be added to controls, for example by using QWidget::addAction(). + This generates an \l ActionAdded event, which you can handle to provide custom behavior. For example, QToolBar reimplements QWidget::actionEvent() to create \l{QToolButton}s for the actions. - \sa QAction, QWidget::addAction(), QWidget::removeAction(), QWidget::actions() + \sa QGuiAction, QWidget::addAction(), QWidget::removeAction(), QWidget::actions() */ /*! @@ -3358,7 +3347,7 @@ QWhatsThisClickedEvent::~QWhatsThisClickedEvent() type is ActionAdded, the action is to be inserted before the action \a before. If \a before is 0, the action is appended. */ -QActionEvent::QActionEvent(int type, QAction *action, QAction *before) +QActionEvent::QActionEvent(int type, QGuiAction *action, QGuiAction *before) : QEvent(static_cast<QEvent::Type>(type)), act(action), bef(before) {} @@ -3593,7 +3582,7 @@ QToolBarChangeEvent::~QToolBarChangeEvent() #endif // QT_NO_TOOLBAR -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) /*! Constructs a shortcut event for the given \a key press, @@ -3614,7 +3603,7 @@ QShortcutEvent::~QShortcutEvent() { } -#endif // QT_NO_SHORTCUT +#endif // QT_CONFIG(shortcut) #ifndef QT_NO_DEBUG_STREAM @@ -3968,7 +3957,7 @@ QT_WARNING_POP dbg << ')'; } break; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) case QEvent::Shortcut: { const QShortcutEvent *se = static_cast<const QShortcutEvent *>(e); dbg << "QShortcutEvent(" << se->key().toString() << ", id=" << se->shortcutId(); diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index f363ece48b..6f3215652b 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -45,7 +45,9 @@ #include <QtGui/qregion.h> #include <QtCore/qnamespace.h> #include <QtCore/qstring.h> -#include <QtGui/qkeysequence.h> +#if QT_CONFIG(shortcut) +# include <QtGui/qkeysequence.h> +#endif #include <QtCore/qcoreevent.h> #include <QtCore/qvariant.h> #include <QtCore/qmap.h> // ### Qt 6: Remove @@ -59,7 +61,7 @@ QT_BEGIN_NAMESPACE -class QAction; +class QGuiAction; #ifndef QT_NO_GESTURES class QGesture; #endif @@ -350,7 +352,7 @@ public: const QPointF &windowPos() const { return mWindowPos; } const QPointF &screenPos() const { return mScreenPos; } - const QTouchDevice *device() const; + const QTouchDevice *device() const { return mDevice; } protected: Qt::NativeGestureType mGestureType; @@ -360,6 +362,7 @@ protected: qreal mRealValue; ulong mSequenceId; quint64 mIntValue; + const QTouchDevice *mDevice; }; #endif // QT_NO_GESTURES @@ -374,7 +377,7 @@ public: ~QKeyEvent(); int key() const { return k; } -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) bool matches(QKeySequence::StandardKey key) const; #endif Qt::KeyboardModifiers modifiers() const; @@ -750,18 +753,18 @@ private: }; #endif -#ifndef QT_NO_ACTION +#if QT_CONFIG(action) class Q_GUI_EXPORT QActionEvent : public QEvent { - QAction *act, *bef; + QGuiAction *act, *bef; public: - QActionEvent(int type, QAction *action, QAction *before = nullptr); + QActionEvent(int type, QGuiAction *action, QGuiAction *before = nullptr); ~QActionEvent(); - inline QAction *action() const { return act; } - inline QAction *before() const { return bef; } + inline QGuiAction *action() const { return act; } + inline QGuiAction *before() const { return bef; } }; -#endif +#endif // QT_CONFIG(action) class Q_GUI_EXPORT QFileOpenEvent : public QEvent { @@ -791,7 +794,7 @@ private: }; #endif -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) class Q_GUI_EXPORT QShortcutEvent : public QEvent { public: @@ -826,10 +829,10 @@ private: Q_GUI_EXPORT QDebug operator<<(QDebug, const QEvent *); #endif -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) inline bool operator==(QKeyEvent *e, QKeySequence::StandardKey key){return (e ? e->matches(key) : false);} inline bool operator==(QKeySequence::StandardKey key, QKeyEvent *e){return (e ? e->matches(key) : false);} -#endif // QT_NO_SHORTCUT +#endif // QT_CONFIG(shortcut) class Q_GUI_EXPORT QPointingDeviceUniqueId { @@ -854,14 +857,6 @@ private: }; Q_DECLARE_TYPEINFO(QPointingDeviceUniqueId, Q_MOVABLE_TYPE); -#if 0 -#pragma qt_sync_suspend_processing -#endif -template <> class QList<QPointingDeviceUniqueId> {}; // to prevent instantiation: use QVector instead -#if 0 -#pragma qt_sync_resume_processing -#endif - Q_GUI_EXPORT bool operator==(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) noexcept; inline bool operator!=(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) noexcept { return !operator==(lhs, rhs); } diff --git a/src/gui/kernel/qguiaction.cpp b/src/gui/kernel/qguiaction.cpp new file mode 100644 index 0000000000..7c7d86f5ab --- /dev/null +++ b/src/gui/kernel/qguiaction.cpp @@ -0,0 +1,1214 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qguiaction.h" +#include "qguiactiongroup.h" + +#include "qguiaction_p.h" +#include "qguiapplication.h" +#include "qevent.h" +#include "qlist.h" +#include "qstylehints.h" +#if QT_CONFIG(shortcut) +# include <private/qshortcutmap_p.h> +#endif +#include <private/qguiapplication_p.h> +#include <private/qdebug_p.h> + +#define QAPP_CHECK(functionName) \ + if (Q_UNLIKELY(!QCoreApplication::instance())) { \ + qWarning("QAction: Initialize Q(Gui)Application before calling '" functionName "'."); \ + return; \ + } + +QT_BEGIN_NAMESPACE + +/* + internal: guesses a descriptive text from a text suited for a menu entry + */ +static QString qt_strippedText(QString s) +{ + s.remove(QLatin1String("...")); + for (int i = 0; i < s.size(); ++i) { + if (s.at(i) == QLatin1Char('&')) + s.remove(i, 1); + } + return s.trimmed(); +} + +QGuiActionPrivate::QGuiActionPrivate() : +#if QT_CONFIG(shortcut) + autorepeat(1), +#endif + enabled(1), forceDisabled(0), visible(1), forceInvisible(0), checkable(0), + checked(0), separator(0), fontSet(false), + iconVisibleInMenu(-1), shortcutVisibleInContextMenu(-1) +{ +} + +#if QT_CONFIG(shortcut) +static bool dummy(QObject *, Qt::ShortcutContext) { return false; } // only for GUI testing. + +QShortcutMap::ContextMatcher QGuiActionPrivate::contextMatcher() const +{ + return dummy; +} +#endif // QT_CONFIG(shortcut) + +QGuiActionPrivate::~QGuiActionPrivate() = default; + +void QGuiActionPrivate::sendDataChanged() +{ + Q_Q(QGuiAction); + QActionEvent e(QEvent::ActionChanged, q); + QCoreApplication::sendEvent(q, &e); + + emit q->changed(); +} + +#if QT_CONFIG(shortcut) +void QGuiActionPrivate::redoGrab(QShortcutMap &map) +{ + Q_Q(QGuiAction); + if (shortcutId) + map.removeShortcut(shortcutId, q); + if (shortcut.isEmpty()) + return; + shortcutId = map.addShortcut(q, shortcut, shortcutContext, contextMatcher()); + if (!enabled) + map.setShortcutEnabled(false, shortcutId, q); + if (!autorepeat) + map.setShortcutAutoRepeat(false, shortcutId, q); +} + +void QGuiActionPrivate::redoGrabAlternate(QShortcutMap &map) +{ + Q_Q(QGuiAction); + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + if (const int id = alternateShortcutIds.at(i)) + map.removeShortcut(id, q); + } + alternateShortcutIds.clear(); + if (alternateShortcuts.isEmpty()) + return; + for(int i = 0; i < alternateShortcuts.count(); ++i) { + const QKeySequence& alternate = alternateShortcuts.at(i); + if (!alternate.isEmpty()) + alternateShortcutIds.append(map.addShortcut(q, alternate, shortcutContext, contextMatcher())); + else + alternateShortcutIds.append(0); + } + if (!enabled) { + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + const int id = alternateShortcutIds.at(i); + map.setShortcutEnabled(false, id, q); + } + } + if (!autorepeat) { + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + const int id = alternateShortcutIds.at(i); + map.setShortcutAutoRepeat(false, id, q); + } + } +} + +void QGuiActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map) +{ + Q_Q(QGuiAction); + if (shortcutId) + map.setShortcutEnabled(enable, shortcutId, q); + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + if (const int id = alternateShortcutIds.at(i)) + map.setShortcutEnabled(enable, id, q); + } +} +#endif // QT_NO_SHORTCUT + + +/*! + \class QGuiAction + \brief QGuiAction is the base class for actions, an abstract user interface + action that can be inserted into widgets. + \since 6.0 + + \inmodule QtGui + + In applications many common commands can be invoked via menus, + toolbar buttons, and keyboard shortcuts. Since the user expects + each command to be performed in the same way, regardless of the + user interface used, it is useful to represent each command as + an \e action. + + Actions can be added to menus and toolbars, and will + automatically keep them in sync. For example, in a word processor, + if the user presses a Bold toolbar button, the Bold menu item + will automatically be checked. + + Actions can be created as independent objects, but they may + also be created during the construction of menus; the QMenu class + contains convenience functions for creating actions suitable for + use as menu items. + + A QGuiAction may contain an icon, menu text, a shortcut, status text, + "What's This?" text, and a tooltip. Most of these can be set in + the constructor. They can also be set independently with + setIcon(), setText(), setIconText(), setShortcut(), + setStatusTip(), setWhatsThis(), and setToolTip(). For menu items, + it is possible to set an individual font with setFont(). + + We recommend that actions are created as children of the window + they are used in. In most cases actions will be children of + the application's main window. + + \sa QMenu, QToolBar, {Application Example} +*/ + +/*! + \fn void QGuiAction::trigger() + + This is a convenience slot that calls activate(Trigger). +*/ + +/*! + \fn void QGuiAction::hover() + + This is a convenience slot that calls activate(Hover). +*/ + +/*! + \enum QGuiAction::MenuRole + + This enum describes how an action should be moved into the application menu on \macos. + + \value NoRole This action should not be put into the application menu + \value TextHeuristicRole This action should be put in the application menu based on the action's text + as described in the QMenuBar documentation. + \value ApplicationSpecificRole This action should be put in the application menu with an application specific role + \value AboutQtRole This action handles the "About Qt" menu item. + \value AboutRole This action should be placed where the "About" menu item is in the application menu. The text of + the menu item will be set to "About <application name>". The application name is fetched from the + \c{Info.plist} file in the application's bundle (See \l{Qt for macOS - Deployment}). + \value PreferencesRole This action should be placed where the "Preferences..." menu item is in the application menu. + \value QuitRole This action should be placed where the Quit menu item is in the application menu. + + Setting this value only has effect on items that are in the immediate menus + of the menubar, not the submenus of those menus. For example, if you have + File menu in your menubar and the File menu has a submenu, setting the + MenuRole for the actions in that submenu have no effect. They will never be moved. +*/ + +/*! + Constructs an action with \a parent. If \a parent is an action + group the action will be automatically inserted into the group. + + \note The \a parent argument is optional since Qt 5.7. +*/ +QGuiAction::QGuiAction(QObject *parent) + : QGuiAction(*new QGuiActionPrivate, parent) +{ +} + +/*! + Constructs an action with some \a text and \a parent. If \a + parent is an action group the action will be automatically + inserted into the group. + + The action uses a stripped version of \a text (e.g. "\&Menu + Option..." becomes "Menu Option") as descriptive text for + tool buttons. You can override this by setting a specific + description with setText(). The same text will be used for + tooltips unless you specify a different text using + setToolTip(). + +*/ +QGuiAction::QGuiAction(const QString &text, QObject *parent) + : QGuiAction(parent) +{ + Q_D(QGuiAction); + d->text = text; +} + +/*! + Constructs an action with an \a icon and some \a text and \a + parent. If \a parent is an action group the action will be + automatically inserted into the group. + + The action uses a stripped version of \a text (e.g. "\&Menu + Option..." becomes "Menu Option") as descriptive text for + tool buttons. You can override this by setting a specific + description with setText(). The same text will be used for + tooltips unless you specify a different text using + setToolTip(). +*/ +QGuiAction::QGuiAction(const QIcon &icon, const QString &text, QObject *parent) + : QGuiAction(text, parent) +{ + Q_D(QGuiAction); + d->icon = icon; +} + +/*! + \internal +*/ +QGuiAction::QGuiAction(QGuiActionPrivate &dd, QObject *parent) + : QObject(dd, parent) +{ + Q_D(QGuiAction); + d->group = qobject_cast<QGuiActionGroup *>(parent); + if (d->group) + d->group->addAction(this); +} + +#if QT_CONFIG(shortcut) +/*! + \property QGuiAction::shortcut + \brief the action's primary shortcut key + + Valid keycodes for this property can be found in \l Qt::Key and + \l Qt::Modifier. There is no default shortcut key. +*/ +void QGuiAction::setShortcut(const QKeySequence &shortcut) +{ + QAPP_CHECK("setShortcut"); + + Q_D(QGuiAction); + if (d->shortcut == shortcut) + return; + + d->shortcut = shortcut; + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); + d->sendDataChanged(); +} + +/*! + Sets \a shortcuts as the list of shortcuts that trigger the + action. The first element of the list is the primary shortcut. + + \sa shortcut +*/ +void QGuiAction::setShortcuts(const QList<QKeySequence> &shortcuts) +{ + Q_D(QGuiAction); + + QList <QKeySequence> listCopy = shortcuts; + + QKeySequence primary; + if (!listCopy.isEmpty()) + primary = listCopy.takeFirst(); + + if (d->shortcut == primary && d->alternateShortcuts == listCopy) + return; + + QAPP_CHECK("setShortcuts"); + + d->shortcut = primary; + d->alternateShortcuts = listCopy; + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); + d->redoGrabAlternate(QGuiApplicationPrivate::instance()->shortcutMap); + d->sendDataChanged(); +} + +/*! + Sets a platform dependent list of shortcuts based on the \a key. + The result of calling this function will depend on the currently running platform. + Note that more than one shortcut can assigned by this action. + If only the primary shortcut is required, use setShortcut instead. + + \sa QKeySequence::keyBindings() +*/ +void QGuiAction::setShortcuts(QKeySequence::StandardKey key) +{ + QList <QKeySequence> list = QKeySequence::keyBindings(key); + setShortcuts(list); +} + +/*! + Returns the primary shortcut. + + \sa setShortcuts() +*/ +QKeySequence QGuiAction::shortcut() const +{ + Q_D(const QGuiAction); + return d->shortcut; +} + +/*! + Returns the list of shortcuts, with the primary shortcut as + the first element of the list. + + \sa setShortcuts() +*/ +QList<QKeySequence> QGuiAction::shortcuts() const +{ + Q_D(const QGuiAction); + QList <QKeySequence> shortcuts; + if (!d->shortcut.isEmpty()) + shortcuts << d->shortcut; + if (!d->alternateShortcuts.isEmpty()) + shortcuts << d->alternateShortcuts; + return shortcuts; +} + +/*! + \property QGuiAction::shortcutContext + \brief the context for the action's shortcut + + Valid values for this property can be found in \l Qt::ShortcutContext. + The default value is Qt::WindowShortcut. +*/ +void QGuiAction::setShortcutContext(Qt::ShortcutContext context) +{ + Q_D(QGuiAction); + if (d->shortcutContext == context) + return; + QAPP_CHECK("setShortcutContext"); + d->shortcutContext = context; + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); + d->redoGrabAlternate(QGuiApplicationPrivate::instance()->shortcutMap); + d->sendDataChanged(); +} + +Qt::ShortcutContext QGuiAction::shortcutContext() const +{ + Q_D(const QGuiAction); + return d->shortcutContext; +} + +/*! + \property QGuiAction::autoRepeat + \brief whether the action can auto repeat + + If true, the action will auto repeat when the keyboard shortcut + combination is held down, provided that keyboard auto repeat is + enabled on the system. + The default value is true. +*/ +void QGuiAction::setAutoRepeat(bool on) +{ + Q_D(QGuiAction); + if (d->autorepeat == on) + return; + QAPP_CHECK("setAutoRepeat"); + d->autorepeat = on; + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); + d->redoGrabAlternate(QGuiApplicationPrivate::instance()->shortcutMap); + d->sendDataChanged(); +} + +bool QGuiAction::autoRepeat() const +{ + Q_D(const QGuiAction); + return d->autorepeat; +} +#endif // QT_CONFIG(shortcut) + +/*! + \property QGuiAction::font + \brief the action's font + + The font property is used to render the text set on the + QAction. The font will can be considered a hint as it will not be + consulted in all cases based upon application and style. + + By default, this property contains the application's default font. + + \sa setText() +*/ +void QGuiAction::setFont(const QFont &font) +{ + Q_D(QGuiAction); + if (d->font == font) + return; + + d->fontSet = true; + d->font = font; + d->sendDataChanged(); +} + +QFont QGuiAction::font() const +{ + Q_D(const QGuiAction); + return d->font; +} + + +/*! + Destroys the object and frees allocated resources. +*/ +QGuiAction::~QGuiAction() +{ + Q_D(QGuiAction); + if (d->group) + d->group->removeAction(this); +#if QT_CONFIG(shortcut) + if (d->shortcutId && qApp) { + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(d->shortcutId, this); + for (int id : qAsConst(d->alternateShortcutIds)) + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this); + } +#endif +} + +/*! + Sets this action group to \a group. The action will be automatically + added to the group's list of actions. + + Actions within the group will be mutually exclusive. + + \sa QGuiActionGroup, guiActionGroup() +*/ +void QGuiAction::setActionGroup(QGuiActionGroup *group) +{ + Q_D(QGuiAction); + if(group == d->group) + return; + + if(d->group) + d->group->removeAction(this); + d->group = group; + if(group) + group->addAction(this); + d->sendDataChanged(); +} + +/*! + Returns the action group for this action. If no action group manages + this action, then \nullptr will be returned. + + \sa QGuiActionGroup, setActionGroup() +*/ +QGuiActionGroup *QGuiAction::guiActionGroup() const +{ + Q_D(const QGuiAction); + return d->group; +} + + +/*! + \property QGuiAction::icon + \brief the action's icon + + In toolbars, the icon is used as the tool button icon; in menus, + it is displayed to the left of the menu text. There is no default + icon. + + If a null icon (QIcon::isNull()) is passed into this function, + the icon of the action is cleared. +*/ +void QGuiAction::setIcon(const QIcon &icon) +{ + Q_D(QGuiAction); + d->icon = icon; + d->sendDataChanged(); +} + +QIcon QGuiAction::icon() const +{ + Q_D(const QGuiAction); + return d->icon; +} + +/*! + If \a b is true then this action will be considered a separator. + + How a separator is represented depends on the widget it is inserted + into. Under most circumstances the text, submenu, and icon will be + ignored for separator actions. + + \sa isSeparator() +*/ +void QGuiAction::setSeparator(bool b) +{ + Q_D(QGuiAction); + if (d->separator == b) + return; + + d->separator = b; + d->sendDataChanged(); +} + +/*! + Returns \c true if this action is a separator action; otherwise it + returns \c false. + + \sa setSeparator() +*/ +bool QGuiAction::isSeparator() const +{ + Q_D(const QGuiAction); + return d->separator; +} + +/*! + \property QGuiAction::text + \brief the action's descriptive text + + If the action is added to a menu, the menu option will consist of + the icon (if there is one), the text, and the shortcut (if there + is one). If the text is not explicitly set in the constructor, or + by using setText(), the action's description icon text will be + used as text. There is no default text. + + \sa iconText +*/ +void QGuiAction::setText(const QString &text) +{ + Q_D(QGuiAction); + if (d->text == text) + return; + + d->text = text; + d->sendDataChanged(); +} + +QString QGuiAction::text() const +{ + Q_D(const QGuiAction); + QString s = d->text; + if(s.isEmpty()) { + s = d->iconText; + s.replace(QLatin1Char('&'), QLatin1String("&&")); + } + return s; +} + +/*! + \property QGuiAction::iconText + \brief the action's descriptive icon text + + If QToolBar::toolButtonStyle is set to a value that permits text to + be displayed, the text defined held in this property appears as a + label in the relevant tool button. + + It also serves as the default text in menus and tooltips if the action + has not been defined with setText() or setToolTip(), and will + also be used in toolbar buttons if no icon has been defined using setIcon(). + + If the icon text is not explicitly set, the action's normal text will be + used for the icon text. + + By default, this property contains an empty string. + + \sa setToolTip(), setStatusTip() +*/ +void QGuiAction::setIconText(const QString &text) +{ + Q_D(QGuiAction); + if (d->iconText == text) + return; + + d->iconText = text; + d->sendDataChanged(); +} + +QString QGuiAction::iconText() const +{ + Q_D(const QGuiAction); + if (d->iconText.isEmpty()) + return qt_strippedText(d->text); + return d->iconText; +} + +/*! + \property QGuiAction::toolTip + \brief the action's tooltip + + This text is used for the tooltip. If no tooltip is specified, + the action's text is used. + + By default, this property contains the action's text. + + \sa setStatusTip(), setShortcut() +*/ +void QGuiAction::setToolTip(const QString &tooltip) +{ + Q_D(QGuiAction); + if (d->tooltip == tooltip) + return; + + d->tooltip = tooltip; + d->sendDataChanged(); +} + +QString QGuiAction::toolTip() const +{ + Q_D(const QGuiAction); + if (d->tooltip.isEmpty()) { + if (!d->text.isEmpty()) + return qt_strippedText(d->text); + return qt_strippedText(d->iconText); + } + return d->tooltip; +} + +/*! + \property QGuiAction::statusTip + \brief the action's status tip + + The status tip is displayed on all status bars provided by the + action's top-level parent widget. + + By default, this property contains an empty string. + + \sa setToolTip(), showStatusText() +*/ +void QGuiAction::setStatusTip(const QString &statustip) +{ + Q_D(QGuiAction); + if (d->statustip == statustip) + return; + + d->statustip = statustip; + d->sendDataChanged(); +} + +QString QGuiAction::statusTip() const +{ + Q_D(const QGuiAction); + return d->statustip; +} + +/*! + \property QGuiAction::whatsThis + \brief the action's "What's This?" help text + + The "What's This?" text is used to provide a brief description of + the action. The text may contain rich text. There is no default + "What's This?" text. + + \sa QWhatsThis +*/ +void QGuiAction::setWhatsThis(const QString &whatsthis) +{ + Q_D(QGuiAction); + if (d->whatsthis == whatsthis) + return; + + d->whatsthis = whatsthis; + d->sendDataChanged(); +} + +QString QGuiAction::whatsThis() const +{ + Q_D(const QGuiAction); + return d->whatsthis; +} + +/*! + \enum QGuiAction::Priority + + This enum defines priorities for actions in user interface. + + \value LowPriority The action should not be prioritized in + the user interface. + + \value NormalPriority + + \value HighPriority The action should be prioritized in + the user interface. + + \sa priority +*/ + + +/*! + \property QGuiAction::priority + + \brief the actions's priority in the user interface. + + This property can be set to indicate how the action should be prioritized + in the user interface. + + For instance, when toolbars have the Qt::ToolButtonTextBesideIcon + mode set, then actions with LowPriority will not show the text + labels. +*/ +void QGuiAction::setPriority(Priority priority) +{ + Q_D(QGuiAction); + if (d->priority == priority) + return; + + d->priority = priority; + d->sendDataChanged(); +} + +QGuiAction::Priority QGuiAction::priority() const +{ + Q_D(const QGuiAction); + return d->priority; +} + +/*! + \property QGuiAction::checkable + \brief whether the action is a checkable action + + A checkable action is one which has an on/off state. For example, + in a word processor, a Bold toolbar button may be either on or + off. An action which is not a toggle action is a command action; + a command action is simply executed, e.g. file save. + By default, this property is \c false. + + In some situations, the state of one toggle action should depend + on the state of others. For example, "Left Align", "Center" and + "Right Align" toggle actions are mutually exclusive. To achieve + exclusive toggling, add the relevant toggle actions to a + QGuiActionGroup with the QGuiActionGroup::exclusive property set to + true. + + \sa setChecked() +*/ +void QGuiAction::setCheckable(bool b) +{ + Q_D(QGuiAction); + if (d->checkable == b) + return; + + d->checkable = b; + d->checked = false; + d->sendDataChanged(); +} + +bool QGuiAction::isCheckable() const +{ + Q_D(const QGuiAction); + return d->checkable; +} + +/*! + \fn void QGuiAction::toggle() + + This is a convenience function for the \l checked property. + Connect to it to change the checked state to its opposite state. +*/ +void QGuiAction::toggle() +{ + Q_D(QGuiAction); + setChecked(!d->checked); +} + +/*! + \property QGuiAction::checked + \brief whether the action is checked. + + Only checkable actions can be checked. By default, this is false + (the action is unchecked). + + \note The notifier signal for this property is toggled(). As toggling + a QAction changes its state, it will also emit a changed() signal. + + \sa checkable, toggled() +*/ +void QGuiAction::setChecked(bool b) +{ + Q_D(QGuiAction); + if (!d->checkable || d->checked == b) + return; + + QPointer<QGuiAction> guard(this); + d->checked = b; + d->sendDataChanged(); + if (guard) + emit toggled(b); +} + +bool QGuiAction::isChecked() const +{ + Q_D(const QGuiAction); + return d->checked; +} + +/*! + \fn void QGuiAction::setDisabled(bool b) + + This is a convenience function for the \l enabled property, that + is useful for signals--slots connections. If \a b is true the + action is disabled; otherwise it is enabled. +*/ + +/*! + \property QGuiAction::enabled + \brief whether the action is enabled + + Disabled actions cannot be chosen by the user. They do not + disappear from menus or toolbars, but they are displayed in a way + which indicates that they are unavailable. For example, they might + be displayed using only shades of gray. + + \uicontrol{What's This?} help on disabled actions is still available, provided + that the QAction::whatsThis property is set. + + An action will be disabled when all widgets to which it is added + (with QWidget::addAction()) are disabled or not visible. When an + action is disabled, it is not possible to trigger it through its + shortcut. + + By default, this property is \c true (actions are enabled). + + \sa text +*/ +void QGuiAction::setEnabled(bool b) +{ + Q_D(QGuiAction); + if (b == d->enabled && b != d->forceDisabled) + return; + d->forceDisabled = !b; + if (b && (!d->visible || (d->group && !d->group->isEnabled()))) + return; + QAPP_CHECK("setEnabled"); + d->enabled = b; +#if QT_CONFIG(shortcut) + d->setShortcutEnabled(b, QGuiApplicationPrivate::instance()->shortcutMap); +#endif + d->sendDataChanged(); +} + +bool QGuiAction::isEnabled() const +{ + Q_D(const QGuiAction); + return d->enabled; +} + +/*! + \property QGuiAction::visible + \brief whether the action can be seen (e.g. in menus and toolbars) + + If \e visible is true the action can be seen (e.g. in menus and + toolbars) and chosen by the user; if \e visible is false the + action cannot be seen or chosen by the user. + + Actions which are not visible are \e not grayed out; they do not + appear at all. + + By default, this property is \c true (actions are visible). +*/ +void QGuiAction::setVisible(bool b) +{ + Q_D(QGuiAction); + if (b == d->visible && b != d->forceInvisible) + return; + QAPP_CHECK("setVisible"); + d->forceInvisible = !b; + d->visible = b; + d->enabled = b && !d->forceDisabled && (!d->group || d->group->isEnabled()) ; +#if QT_CONFIG(shortcut) + d->setShortcutEnabled(d->enabled, QGuiApplicationPrivate::instance()->shortcutMap); +#endif + d->sendDataChanged(); +} + + +bool QGuiAction::isVisible() const +{ + Q_D(const QGuiAction); + return d->visible; +} + +/*! + \reimp +*/ +bool QGuiAction::event(QEvent *e) +{ +#if QT_CONFIG(shortcut) + if (e->type() == QEvent::Shortcut) { + QShortcutEvent *se = static_cast<QShortcutEvent *>(e); + Q_ASSERT_X(se->key() == d_func()->shortcut || d_func()->alternateShortcuts.contains(se->key()), + "QAction::event", + "Received shortcut event from incorrect shortcut"); + if (se->isAmbiguous()) + qWarning("QAction::event: Ambiguous shortcut overload: %s", se->key().toString(QKeySequence::NativeText).toLatin1().constData()); + else + activate(Trigger); + return true; + } +#endif // QT_CONFIG(shortcut) + return QObject::event(e); +} + +/*! + Returns the user data as set in QAction::setData. + + \sa setData() +*/ +QVariant QGuiAction::data() const +{ + Q_D(const QGuiAction); + return d->userData; +} + +/*! + Sets the action's internal data to the given \a userData. + + \sa data() +*/ +void QGuiAction::setData(const QVariant &data) +{ + Q_D(QGuiAction); + if (d->userData == data) + return; + d->userData = data; + d->sendDataChanged(); +} + +/*! + Sends the relevant signals for ActionEvent \a event. + + Action based widgets use this API to cause the QAction + to emit signals as well as emitting their own. +*/ +void QGuiAction::activate(ActionEvent event) +{ + Q_D(QGuiAction); + if(event == Trigger) { + QPointer<QObject> guard = this; + if(d->checkable) { + // the checked action of an exclusive group may not be unchecked + if (d->checked && (d->group + && d->group->exclusionPolicy() == QGuiActionGroup::ExclusionPolicy::Exclusive + && d->group->checkedGuiAction() == this)) { + if (!guard.isNull()) + emit triggered(true); + return; + } + setChecked(!d->checked); + } + if (!guard.isNull()) + emit triggered(d->checked); + } else if(event == Hover) { + emit hovered(); + } +} + +/*! + \fn void QGuiAction::triggered(bool checked) + + This signal is emitted when an action is activated by the user; + for example, when the user clicks a menu option, toolbar button, + or presses an action's shortcut key combination, or when trigger() + was called. Notably, it is \e not emitted when setChecked() or + toggle() is called. + + If the action is checkable, \a checked is true if the action is + checked, or false if the action is unchecked. + + \sa activate(), toggled(), checked +*/ + +/*! + \fn void QGuiAction::toggled(bool checked) + + This signal is emitted whenever a checkable action changes its + isChecked() status. This can be the result of a user interaction, + or because setChecked() was called. As setChecked() changes the + QAction, it emits changed() in addition to toggled(). + + \a checked is true if the action is checked, or false if the + action is unchecked. + + \sa activate(), triggered(), checked +*/ + +/*! + \fn void QGuiAction::hovered() + + This signal is emitted when an action is highlighted by the user; + for example, when the user pauses with the cursor over a menu option, + toolbar button, or presses an action's shortcut key combination. + + \sa activate() +*/ + +/*! + \fn void QGuiAction::changed() + + This signal is emitted when an action has changed. If you + are only interested in actions in a given widget, you can + watch for QWidget::actionEvent() sent with an + QEvent::ActionChanged. + + \sa QWidget::actionEvent() +*/ + +/*! + \enum QGuiAction::ActionEvent + + This enum type is used when calling QAction::activate() + + \value Trigger this will cause the QAction::triggered() signal to be emitted. + + \value Hover this will cause the QAction::hovered() signal to be emitted. +*/ + +/*! + \property QGuiAction::menuRole + \brief the action's menu role + + This indicates what role the action serves in the application menu on + \macos. By default all actions have the TextHeuristicRole, which means that + the action is added based on its text (see QMenuBar for more information). + + The menu role can only be changed before the actions are put into the menu + bar in \macos (usually just before the first application window is + shown). +*/ +void QGuiAction::setMenuRole(MenuRole menuRole) +{ + Q_D(QGuiAction); + if (d->menuRole == menuRole) + return; + + d->menuRole = menuRole; + d->sendDataChanged(); +} + +QGuiAction::MenuRole QGuiAction::menuRole() const +{ + Q_D(const QGuiAction); + return d->menuRole; +} + +/*! + \property QGuiAction::iconVisibleInMenu + \brief Whether or not an action should show an icon in a menu + + In some applications, it may make sense to have actions with icons in the + toolbar, but not in menus. If true, the icon (if valid) is shown in the menu, when it + is false, it is not shown. + + The default is to follow whether the Qt::AA_DontShowIconsInMenus attribute + is set for the application. Explicitly settings this property overrides + the presence (or abscence) of the attribute. + + For example: + \snippet code/src_gui_kernel_qaction.cpp 0 + + \sa icon, QCoreApplication::setAttribute() +*/ +void QGuiAction::setIconVisibleInMenu(bool visible) +{ + Q_D(QGuiAction); + if (d->iconVisibleInMenu == -1 || visible != bool(d->iconVisibleInMenu)) { + int oldValue = d->iconVisibleInMenu; + d->iconVisibleInMenu = visible; + // Only send data changed if we really need to. + if (oldValue != -1 + || visible == !QCoreApplication::testAttribute(Qt::AA_DontShowIconsInMenus)) { + d->sendDataChanged(); + } + } +} + +bool QGuiAction::isIconVisibleInMenu() const +{ + Q_D(const QGuiAction); + if (d->iconVisibleInMenu == -1) { + return !QCoreApplication::testAttribute(Qt::AA_DontShowIconsInMenus); + } + return d->iconVisibleInMenu; +} + +/*! + \property QGuiAction::shortcutVisibleInContextMenu + \brief Whether or not an action should show a shortcut in a context menu + + In some applications, it may make sense to have actions with shortcuts in + context menus. If true, the shortcut (if valid) is shown when the action is + shown via a context menu, when it is false, it is not shown. + + The default is to follow whether the Qt::AA_DontShowShortcutsInContextMenus attribute + is set for the application, falling back to the widget style hint. + Explicitly setting this property overrides the presence (or abscence) of the attribute. + + \sa shortcut, QCoreApplication::setAttribute() +*/ +void QGuiAction::setShortcutVisibleInContextMenu(bool visible) +{ + Q_D(QGuiAction); + if (d->shortcutVisibleInContextMenu == -1 || visible != bool(d->shortcutVisibleInContextMenu)) { + int oldValue = d->shortcutVisibleInContextMenu; + d->shortcutVisibleInContextMenu = visible; + // Only send data changed if we really need to. + if (oldValue != -1 + || visible == !QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus)) { + d->sendDataChanged(); + } + } +} + +bool QGuiAction::isShortcutVisibleInContextMenu() const +{ + Q_D(const QGuiAction); + if (d->shortcutVisibleInContextMenu == -1) { + return !QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus) + && QGuiApplication::styleHints()->showShortcutsInContextMenus(); + } + return d->shortcutVisibleInContextMenu; +} + +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug d, const QGuiAction *action) +{ + QDebugStateSaver saver(d); + d.nospace(); + d << "QAction(" << static_cast<const void *>(action); + if (action) { + d << " text=" << action->text(); + if (!action->toolTip().isEmpty()) + d << " toolTip=" << action->toolTip(); + if (action->isCheckable()) + d << " checked=" << action->isChecked(); +#if QT_CONFIG(shortcut) + if (!action->shortcut().isEmpty()) + d << " shortcut=" << action->shortcut(); +#endif + d << " menuRole="; + QtDebugUtils::formatQEnum(d, action->menuRole()); + d << " visible=" << action->isVisible(); + } else { + d << '0'; + } + d << ')'; + return d; +} +#endif // QT_NO_DEBUG_STREAM + +QT_END_NAMESPACE + +#include "moc_qguiaction.cpp" diff --git a/src/gui/kernel/qguiaction.h b/src/gui/kernel/qguiaction.h new file mode 100644 index 0000000000..454f66893f --- /dev/null +++ b/src/gui/kernel/qguiaction.h @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGUIACTION_H +#define QGUIACTION_H + +#include <QtGui/qtguiglobal.h> +#if QT_CONFIG(shortcut) +# include <QtGui/qkeysequence.h> +#endif +#include <QtGui/qicon.h> +#include <QtCore/qstring.h> +#include <QtCore/qvariant.h> + +QT_REQUIRE_CONFIG(action); + +QT_BEGIN_NAMESPACE + +class QActionEvent; +class QGuiActionGroup; +class QGuiActionPrivate; + +class Q_GUI_EXPORT QGuiAction : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QGuiAction) + + Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY changed) + Q_PROPERTY(bool checked READ isChecked WRITE setChecked NOTIFY toggled) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY changed) + Q_PROPERTY(QIcon icon READ icon WRITE setIcon NOTIFY changed) + Q_PROPERTY(QString text READ text WRITE setText NOTIFY changed) + Q_PROPERTY(QString iconText READ iconText WRITE setIconText NOTIFY changed) + Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip NOTIFY changed) + Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip NOTIFY changed) + Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis NOTIFY changed) + Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed) +#if QT_CONFIG(shortcut) + Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut NOTIFY changed) + Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext NOTIFY changed) + Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY changed) +#endif // QT_CONFIG(shortcut) + Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY changed) + Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed) + Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed) + Q_PROPERTY(bool shortcutVisibleInContextMenu READ isShortcutVisibleInContextMenu WRITE setShortcutVisibleInContextMenu NOTIFY changed) + Q_PROPERTY(Priority priority READ priority WRITE setPriority) + +public: + // note this is copied into qplatformmenu.h, which must stay in sync + enum MenuRole { NoRole = 0, TextHeuristicRole, ApplicationSpecificRole, AboutQtRole, + AboutRole, PreferencesRole, QuitRole }; + Q_ENUM(MenuRole) + enum Priority { LowPriority = 0, + NormalPriority = 128, + HighPriority = 256}; + Q_ENUM(Priority) + explicit QGuiAction(QObject *parent = nullptr); + explicit QGuiAction(const QString &text, QObject *parent = nullptr); + explicit QGuiAction(const QIcon &icon, const QString &text, QObject *parent = nullptr); + + ~QGuiAction(); + + void setActionGroup(QGuiActionGroup *group); + QGuiActionGroup *guiActionGroup() const; + void setIcon(const QIcon &icon); + QIcon icon() const; + + void setText(const QString &text); + QString text() const; + + void setIconText(const QString &text); + QString iconText() const; + + void setToolTip(const QString &tip); + QString toolTip() const; + + void setStatusTip(const QString &statusTip); + QString statusTip() const; + + void setWhatsThis(const QString &what); + QString whatsThis() const; + + void setPriority(Priority priority); + Priority priority() const; + + void setSeparator(bool b); + bool isSeparator() const; + +#if QT_CONFIG(shortcut) + void setShortcut(const QKeySequence &shortcut); + QKeySequence shortcut() const; + + void setShortcuts(const QList<QKeySequence> &shortcuts); + void setShortcuts(QKeySequence::StandardKey); + QList<QKeySequence> shortcuts() const; + + void setShortcutContext(Qt::ShortcutContext context); + Qt::ShortcutContext shortcutContext() const; + + void setAutoRepeat(bool); + bool autoRepeat() const; +#endif // QT_CONFIG(shortcut) + + void setFont(const QFont &font); + QFont font() const; + + void setCheckable(bool); + bool isCheckable() const; + + QVariant data() const; + void setData(const QVariant &var); + + bool isChecked() const; + + bool isEnabled() const; + + bool isVisible() const; + + enum ActionEvent { Trigger, Hover }; + void activate(ActionEvent event); + + void setMenuRole(MenuRole menuRole); + MenuRole menuRole() const; + + void setIconVisibleInMenu(bool visible); + bool isIconVisibleInMenu() const; + + void setShortcutVisibleInContextMenu(bool show); + bool isShortcutVisibleInContextMenu() const; + +protected: + bool event(QEvent *) override; + QGuiAction(QGuiActionPrivate &dd, QObject *parent); + +public Q_SLOTS: + void trigger() { activate(Trigger); } + void hover() { activate(Hover); } + void setChecked(bool); + void toggle(); + void setEnabled(bool); + inline void setDisabled(bool b) { setEnabled(!b); } + void setVisible(bool); + +Q_SIGNALS: + void changed(); + void triggered(bool checked = false); + void hovered(); + void toggled(bool); + +private: + Q_DISABLE_COPY(QGuiAction) + friend class QGuiActionGroup; +}; + +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug, const QGuiAction *); +#endif + +QT_END_NAMESPACE + +#endif // QGUIACTION_H diff --git a/src/gui/kernel/qguiaction_p.h b/src/gui/kernel/qguiaction_p.h new file mode 100644 index 0000000000..3358ed1070 --- /dev/null +++ b/src/gui/kernel/qguiaction_p.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGUIACTION_P_H +#define QGUIACTION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/private/qtguiglobal_p.h> +#include <QtGui/qguiaction.h> +#include <QtGui/qfont.h> +#if QT_CONFIG(shortcut) +# include <QtGui/private/qshortcutmap_p.h> +#endif +#include "private/qobject_p.h" + +QT_REQUIRE_CONFIG(action); + +QT_BEGIN_NAMESPACE + +class QShortcutMap; + +class Q_GUI_EXPORT QGuiActionPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGuiAction) +public: + QGuiActionPrivate(); + ~QGuiActionPrivate(); + +#if QT_CONFIG(shortcut) + virtual QShortcutMap::ContextMatcher contextMatcher() const; +#endif + + static QGuiActionPrivate *get(QGuiAction *q) + { + return q->d_func(); + } + + + QPointer<QGuiActionGroup> group; + QString text; + QString iconText; + QIcon icon; + QString tooltip; + QString statustip; + QString whatsthis; +#if QT_CONFIG(shortcut) + QKeySequence shortcut; + QList<QKeySequence> alternateShortcuts; +#endif + QVariant userData; +#if QT_CONFIG(shortcut) + int shortcutId = 0; + QVector<int> alternateShortcutIds; + Qt::ShortcutContext shortcutContext = Qt::WindowShortcut; + uint autorepeat : 1; +#endif + QFont font; + uint enabled : 1, forceDisabled : 1; + uint visible : 1, forceInvisible : 1; + uint checkable : 1; + uint checked : 1; + uint separator : 1; + uint fontSet : 1; + + int iconVisibleInMenu : 2; // Only has values -1, 0, and 1 + int shortcutVisibleInContextMenu : 2; // Only has values -1, 0, and 1 + + QGuiAction::MenuRole menuRole = QGuiAction::TextHeuristicRole; + QGuiAction::Priority priority = QGuiAction::NormalPriority; + +#if QT_CONFIG(shortcut) + void redoGrab(QShortcutMap &map); + void redoGrabAlternate(QShortcutMap &map); + void setShortcutEnabled(bool enable, QShortcutMap &map); +#endif // QT_NO_SHORTCUT + + void sendDataChanged(); +}; + +QT_END_NAMESPACE + +#endif // QACTION_P_H diff --git a/src/gui/kernel/qguiactiongroup.cpp b/src/gui/kernel/qguiactiongroup.cpp new file mode 100644 index 0000000000..7360214aad --- /dev/null +++ b/src/gui/kernel/qguiactiongroup.cpp @@ -0,0 +1,346 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qguiactiongroup.h" + +#include "qguiaction.h" +#include "qguiaction_p.h" +#include "qguiactiongroup_p.h" +#include "qevent.h" +#include "qlist.h" + +QT_BEGIN_NAMESPACE + +QGuiActionGroupPrivate::QGuiActionGroupPrivate() : + enabled(1), visible(1) +{ +} + +QGuiActionGroupPrivate::~QGuiActionGroupPrivate() = default; + +void QGuiActionGroup::_q_actionChanged() +{ + Q_D(QGuiActionGroup); + auto action = qobject_cast<QGuiAction*>(sender()); + Q_ASSERT_X(action != nullptr, "QGuiActionGroup::_q_actionChanged", "internal error"); + if (d->exclusionPolicy != QGuiActionGroup::ExclusionPolicy::None) { + if (action->isChecked()) { + if (action != d->current) { + if (!d->current.isNull()) + d->current->setChecked(false); + d->current = action; + } + } else if (action == d->current) { + d->current = nullptr; + } + } +} + +void QGuiActionGroup::_q_actionTriggered() +{ + Q_D(QGuiActionGroup); + auto action = qobject_cast<QGuiAction*>(sender()); + Q_ASSERT_X(action != nullptr, "QGuiActionGroup::_q_actionTriggered", "internal error"); + d->emitSignal(QGuiActionGroupPrivate::Triggered, action); +} + +void QGuiActionGroup::_q_actionHovered() +{ + Q_D(QGuiActionGroup); + auto action = qobject_cast<QGuiAction*>(sender()); + Q_ASSERT_X(action != nullptr, "QGuiActionGroup::_q_actionHovered", "internal error"); + d->emitSignal(QGuiActionGroupPrivate::Hovered, action); +} + +/*! + \class QGuiActionGroup + \brief The QGuiActionGroup class groups actions together. + \since 6.0 + + \inmodule QtGui + + QGuiActionGroup is a base class for classes grouping + classes inhheriting QGuiAction objects together. + + In some situations it is useful to group QGuiAction objects together. + For example, if you have a \uicontrol{Left Align} action, a \uicontrol{Right + Align} action, a \uicontrol{Justify} action, and a \uicontrol{Center} action, + only one of these actions should be active at any one time. One + simple way of achieving this is to group the actions together in + an action group, inheriting QGuiActionGroup. + + \sa QGuiAction +*/ + +/*! + \enum QGuiActionGroup::ExclusionPolicy + + This enum specifies the different policies that can be used to + control how the group performs exclusive checking on checkable actions. + + \value None + The actions in the group can be checked independently of each other. + + \value Exclusive + Exactly one action can be checked at any one time. + This is the default policy. + + \value ExclusiveOptional + At most one action can be checked at any one time. The actions + can also be all unchecked. + + \sa exclusionPolicy +*/ + +/*! + Constructs an action group for the \a parent object. + + The action group is exclusive by default. Call setExclusive(false) + to make the action group non-exclusive. To make the group exclusive + but allow unchecking the active action call instead + setExclusionPolicy(QGuiActionGroup::ExclusionPolicy::ExclusiveOptional) +*/ +QGuiActionGroup::QGuiActionGroup(QObject* parent) : + QGuiActionGroup(*new QGuiActionGroupPrivate, parent) +{ +} + +QGuiActionGroup::QGuiActionGroup(QGuiActionGroupPrivate &dd, QObject *parent) : + QObject(dd, parent) +{ +} + +/*! + Destroys the action group. +*/ +QGuiActionGroup::~QGuiActionGroup() = default; + +/*! + \fn QGuiAction *QGuiActionGroup::addAction(QGuiAction *action) + + Adds the \a action to this group, and returns it. + + Normally an action is added to a group by creating it with the + group as its parent, so this function is not usually used. + + \sa QGuiAction::setActionGroup() +*/ +QGuiAction *QGuiActionGroup::addAction(QGuiAction* a) +{ + Q_D(QGuiActionGroup); + if (!d->actions.contains(a)) { + d->actions.append(a); + QObject::connect(a, &QGuiAction::triggered, this, &QGuiActionGroup::_q_actionTriggered); + QObject::connect(a, &QGuiAction::changed, this, &QGuiActionGroup::_q_actionChanged); + QObject::connect(a, &QGuiAction::hovered, this, &QGuiActionGroup::_q_actionHovered); + } + if (!a->d_func()->forceDisabled) { + a->setEnabled(d->enabled); + a->d_func()->forceDisabled = false; + } + if (!a->d_func()->forceInvisible) { + a->setVisible(d->visible); + a->d_func()->forceInvisible = false; + } + if (a->isChecked()) + d->current = a; + QGuiActionGroup *oldGroup = a->d_func()->group; + if (oldGroup != this) { + if (oldGroup) + oldGroup->removeAction(a); + a->d_func()->group = this; + a->d_func()->sendDataChanged(); + } + return a; +} + +/*! + Removes the \a action from this group. The action will have no + parent as a result. + + \sa QGuiAction::setActionGroup() +*/ +void QGuiActionGroup::removeAction(QGuiAction *action) +{ + Q_D(QGuiActionGroup); + if (d->actions.removeAll(action)) { + if (action == d->current) + d->current = nullptr; + QObject::disconnect(action, &QGuiAction::triggered, this, &QGuiActionGroup::_q_actionTriggered); + QObject::disconnect(action, &QGuiAction::changed, this, &QGuiActionGroup::_q_actionChanged); + QObject::disconnect(action, &QGuiAction::hovered, this, &QGuiActionGroup::_q_actionHovered); + action->d_func()->group = nullptr; + } +} + +/*! + Returns the list of this groups's actions. This may be empty. +*/ +QList<QGuiAction*> QGuiActionGroup::guiActions() const +{ + Q_D(const QGuiActionGroup); + return d->actions; +} + +/*! + \brief Enable or disable the group exclusion checking + + This is a convenience method that calls + setExclusionPolicy(ExclusionPolicy::Exclusive) when \a b is true, + else setExclusionPolicy(QActionGroup::ExclusionPolicy::None). + + \sa QGuiActionGroup::exclusionPolicy +*/ +void QGuiActionGroup::setExclusive(bool b) +{ + setExclusionPolicy(b ? QGuiActionGroup::ExclusionPolicy::Exclusive + : QGuiActionGroup::ExclusionPolicy::None); +} + +/*! + \brief Returns true if the group is exclusive + + The group is exclusive if the ExclusionPolicy is either Exclusive + or ExclusionOptional. + +*/ +bool QGuiActionGroup::isExclusive() const +{ + return exclusionPolicy() != QGuiActionGroup::ExclusionPolicy::None; +} + +/*! + \property QGuiActionGroup::exclusionPolicy + \brief This property holds the group exclusive checking policy + + If exclusionPolicy is set to Exclusive, only one checkable + action in the action group can ever be active at any time. If the user + chooses another checkable action in the group, the one they chose becomes + active and the one that was active becomes inactive. If exclusionPolicy is + set to ExclusionOptional the group is exclusive but the active checkable + action in the group can be unchecked leaving the group with no actions + checked. + + \sa QGuiAction::checkable +*/ +void QGuiActionGroup::setExclusionPolicy(QGuiActionGroup::ExclusionPolicy policy) +{ + Q_D(QGuiActionGroup); + d->exclusionPolicy = policy; +} + +QGuiActionGroup::ExclusionPolicy QGuiActionGroup::exclusionPolicy() const +{ + Q_D(const QGuiActionGroup); + return d->exclusionPolicy; +} + +/*! + \fn void QGuiActionGroup::setDisabled(bool b) + + This is a convenience function for the \l enabled property, that + is useful for signals--slots connections. If \a b is true the + action group is disabled; otherwise it is enabled. +*/ + +/*! + \property QGuiActionGroup::enabled + \brief whether the action group is enabled + + Each action in the group will be enabled or disabled unless it + has been explicitly disabled. + + \sa QGuiAction::setEnabled() +*/ +void QGuiActionGroup::setEnabled(bool b) +{ + Q_D(QGuiActionGroup); + d->enabled = b; + for (auto action : qAsConst(d->actions)) { + if (!action->d_func()->forceDisabled) { + action->setEnabled(b); + action->d_func()->forceDisabled = false; + } + } +} + +bool QGuiActionGroup::isEnabled() const +{ + Q_D(const QGuiActionGroup); + return d->enabled; +} + +/*! + Returns the currently checked action in the group, or \nullptr if + none are checked. +*/ +QGuiAction *QGuiActionGroup::checkedGuiAction() const +{ + Q_D(const QGuiActionGroup); + return d->current.data(); +} + +/*! + \property QGuiActionGroup::visible + \brief whether the action group is visible + + Each action in the action group will match the visible state of + this group unless it has been explicitly hidden. + + \sa QGuiAction::setEnabled() +*/ +void QGuiActionGroup::setVisible(bool b) +{ + Q_D(QGuiActionGroup); + d->visible = b; + for (auto action : qAsConst(d->actions)) { + if (!action->d_func()->forceInvisible) { + action->setVisible(b); + action->d_func()->forceInvisible = false; + } + } +} + +bool QGuiActionGroup::isVisible() const +{ + Q_D(const QGuiActionGroup); + return d->visible; +} + +QT_END_NAMESPACE diff --git a/src/gui/opengl/qopengltimerquery.h b/src/gui/kernel/qguiactiongroup.h index 27da74a3fb..ef08fb2e04 100644 --- a/src/gui/opengl/qopengltimerquery.h +++ b/src/gui/kernel/qguiactiongroup.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -37,80 +37,68 @@ ** ****************************************************************************/ -#ifndef QOPENGLTIMERQUERY_H -#define QOPENGLTIMERQUERY_H +#ifndef QGUIACTIONGROUP_H +#define QGUIACTIONGROUP_H #include <QtGui/qtguiglobal.h> +#include <QtGui/qguiaction.h> -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) - -#include <QtCore/QObject> -#include <QtGui/qopengl.h> +QT_REQUIRE_CONFIG(action); QT_BEGIN_NAMESPACE -class QOpenGLTimerQueryPrivate; +class QGuiActionGroupPrivate; -class Q_GUI_EXPORT QOpenGLTimerQuery : public QObject +class Q_GUI_EXPORT QGuiActionGroup : public QObject { Q_OBJECT + Q_DECLARE_PRIVATE(QGuiActionGroup) -public: - explicit QOpenGLTimerQuery(QObject *parent = nullptr); - ~QOpenGLTimerQuery(); - - bool create(); - void destroy(); - bool isCreated() const; - GLuint objectId() const; - - void begin(); - void end(); - GLuint64 waitForTimestamp() const; - void recordTimestamp(); - bool isResultAvailable() const; - GLuint64 waitForResult() const; - -private: - Q_DECLARE_PRIVATE(QOpenGLTimerQuery) - Q_DISABLE_COPY(QOpenGLTimerQuery) -}; - - -class QOpenGLTimeMonitorPrivate; - -class Q_GUI_EXPORT QOpenGLTimeMonitor : public QObject -{ - Q_OBJECT + Q_PROPERTY(QGuiActionGroup::ExclusionPolicy exclusionPolicy READ exclusionPolicy WRITE setExclusionPolicy) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) + Q_PROPERTY(bool visible READ isVisible WRITE setVisible) public: - explicit QOpenGLTimeMonitor(QObject *parent = nullptr); - ~QOpenGLTimeMonitor(); - - void setSampleCount(int sampleCount); - int sampleCount() const; - - bool create(); - void destroy(); - bool isCreated() const; - QVector<GLuint> objectIds() const; - - int recordSample(); - - bool isResultAvailable() const; - - QVector<GLuint64> waitForSamples() const; - QVector<GLuint64> waitForIntervals() const; - - void reset(); + enum class ExclusionPolicy { + None, + Exclusive, + ExclusiveOptional + }; + Q_ENUM(ExclusionPolicy) + + explicit QGuiActionGroup(QObject *parent); + ~QGuiActionGroup(); + + QGuiAction *addAction(QGuiAction *a); + void removeAction(QGuiAction *a); + QList<QGuiAction*> guiActions() const; + QGuiAction *checkedGuiAction() const; + + bool isExclusive() const; + bool isEnabled() const; + bool isVisible() const; + ExclusionPolicy exclusionPolicy() const; + + +public Q_SLOTS: + void setEnabled(bool); + inline void setDisabled(bool b) { setEnabled(!b); } + void setVisible(bool); + void setExclusive(bool); + void setExclusionPolicy(ExclusionPolicy policy); + +private Q_SLOTS: + void _q_actionTriggered(); + void _q_actionHovered(); + void _q_actionChanged(); + +protected: + QGuiActionGroup(QGuiActionGroupPrivate &dd, QObject *parent); private: - Q_DECLARE_PRIVATE(QOpenGLTimeMonitor) - Q_DISABLE_COPY(QOpenGLTimeMonitor) + Q_DISABLE_COPY(QGuiActionGroup) }; QT_END_NAMESPACE -#endif // QT_NO_OPENGL - -#endif // QOPENGLTIMERQUERY_H +#endif // QGUIACTIONGROUP_H diff --git a/src/gui/image/qimage_compat.cpp b/src/gui/kernel/qguiactiongroup_p.h index ba31a9ac9b..99a58262c9 100644 --- a/src/gui/image/qimage_compat.cpp +++ b/src/gui/kernel/qguiactiongroup_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -37,30 +37,55 @@ ** ****************************************************************************/ -#ifdef QIMAGE_H -# error "This file cannot be used with precompiled headers" +#ifndef QGUIACTIONGROUP_P_H +#define QGUIACTIONGROUP_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/private/qtguiglobal_p.h> +#include <QtGui/qguiactiongroup.h> +#include <QtGui/qfont.h> +#if QT_CONFIG(shortcut) +# include <QtGui/private/qshortcutmap_p.h> #endif -#define QT_COMPILING_QIMAGE_COMPAT_CPP +#include "private/qobject_p.h" -#include "qimage.h" +QT_REQUIRE_CONFIG(action); QT_BEGIN_NAMESPACE -// These implementations must be the same as the inline versions in qimage.h - -QImage QImage::convertToFormat(Format f, Qt::ImageConversionFlags flags) const +class Q_GUI_EXPORT QGuiActionGroupPrivate : public QObjectPrivate { - return convertToFormat_helper(f, flags); -} + Q_DECLARE_PUBLIC(QGuiActionGroup) +public: + enum Signal { Triggered, Hovered }; -QImage QImage::mirrored(bool horizontally, bool vertically) const -{ - return mirrored_helper(horizontally, vertically); -} + QGuiActionGroupPrivate(); + ~QGuiActionGroupPrivate(); -QImage QImage::rgbSwapped() const -{ - return rgbSwapped_helper(); -} + virtual void emitSignal(Signal, QGuiAction *) {} + + QList<QGuiAction *> actions; + QPointer<QGuiAction> current; + uint enabled : 1; + uint visible : 1; + QGuiActionGroup::ExclusionPolicy exclusionPolicy = QGuiActionGroup::ExclusionPolicy::Exclusive; + +private: + void _q_actionTriggered(); //private slot + void _q_actionChanged(); //private slot + void _q_actionHovered(); //private slot +}; QT_END_NAMESPACE + +#endif // QACTIONGROUP_P_H diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 29ed2af7a5..2291241ef6 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1187,14 +1187,18 @@ Q_LOGGING_CATEGORY(lcQpaPluginLoading, "qt.qpa.plugin"); static void init_platform(const QString &pluginNamesWithArguments, const QString &platformPluginPath, const QString &platformThemeName, int &argc, char **argv) { - QStringList plugins = pluginNamesWithArguments.split(QLatin1Char(';')); + QStringList plugins = pluginNamesWithArguments.split(QLatin1Char(';'), QString::SkipEmptyParts); QStringList platformArguments; QStringList availablePlugins = QPlatformIntegrationFactory::keys(platformPluginPath); for (const auto &pluginArgument : plugins) { // Split into platform name and arguments - QStringList arguments = pluginArgument.split(QLatin1Char(':')); + QStringList arguments = pluginArgument.split(QLatin1Char(':'), QString::SkipEmptyParts); + if (arguments.isEmpty()) + continue; const QString name = arguments.takeFirst().toLower(); QString argumentsKey = name; + if (name.isEmpty()) + continue; argumentsKey[0] = argumentsKey.at(0).toUpper(); arguments.append(QLibraryInfo::platformPluginArguments(argumentsKey)); diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index ee493faa5d..9f3fa7212a 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -62,7 +62,10 @@ #include <qpa/qwindowsysteminterface.h> #include <qpa/qwindowsysteminterface_p.h> -#include "private/qshortcutmap_p.h" +#if QT_CONFIG(shortcut) +# include "private/qshortcutmap_p.h" +#endif + #include <qicon.h> QT_BEGIN_NAMESPACE @@ -263,7 +266,7 @@ public: QIcon forcedWindowIcon; static QList<QObject *> generic_plugin_list; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) QShortcutMap shortcutMap; #endif diff --git a/src/gui/kernel/qguishortcut.cpp b/src/gui/kernel/qguishortcut.cpp new file mode 100644 index 0000000000..add1dce12e --- /dev/null +++ b/src/gui/kernel/qguishortcut.cpp @@ -0,0 +1,354 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qguishortcut.h" +#include "qguishortcut_p.h" + +#include <qevent.h> +#include <qguiapplication.h> +#include <qwindow.h> +#include <private/qguiapplication_p.h> +#include <qpa/qplatformmenu.h> + +QT_BEGIN_NAMESPACE + +#define QAPP_CHECK(functionName) \ + if (Q_UNLIKELY(!qApp)) { \ + qWarning("QGuiShortcut: Initialize QGuiApplication before calling '" functionName "'."); \ + return; \ + } + +/*! + \class QGuiShortcut + \brief The QGuiShortcut class is a base class for handling keyboard shortcuts. + + \ingroup events + \inmodule QtGui + \since 6.0 + + The QGuiShortcut class is a base class for classes providing a way of + connecting keyboard shortcuts to Qt's \l{signals and slots} mechanism, + so that objects can be informed when a shortcut is executed. The shortcut + can be set up to contain all the key presses necessary to + describe a keyboard shortcut, including the states of modifier + keys such as \uicontrol Shift, \uicontrol Ctrl, and \uicontrol Alt. + + \target mnemonic + + \sa QShortcutEvent, QKeySequence, QAction +*/ + +/*! + \fn void QGuiShortcut::activated() + + This signal is emitted when the user types the shortcut's key + sequence. + + \sa activatedAmbiguously() +*/ + +/*! + \fn void QGuiShortcut::activatedAmbiguously() + + When a key sequence is being typed at the keyboard, it is said to + be ambiguous as long as it matches the start of more than one + shortcut. + + When a shortcut's key sequence is completed, + activatedAmbiguously() is emitted if the key sequence is still + ambiguous (i.e., it is the start of one or more other shortcuts). + The activated() signal is not emitted in this case. + + \sa activated() +*/ + +static bool simpleContextMatcher(QObject *object, Qt::ShortcutContext context) +{ + auto guiShortcut = qobject_cast<QGuiShortcut *>(object); + if (QGuiApplication::applicationState() != Qt::ApplicationActive || guiShortcut == nullptr) + return false; + if (context == Qt::ApplicationShortcut) + return true; + auto focusWindow = QGuiApplication::focusWindow(); + if (!focusWindow) + return false; + auto window = qobject_cast<const QWindow *>(guiShortcut->parent()); + if (!window) + return false; + if (focusWindow == window && focusWindow->isTopLevel()) + return context == Qt::WindowShortcut || context == Qt::WidgetWithChildrenShortcut; + return focusWindow->isAncestorOf(window, QWindow::ExcludeTransients); +} + +QShortcutMap::ContextMatcher QGuiShortcutPrivate::contextMatcher() const +{ + return simpleContextMatcher; +} + +void QGuiShortcutPrivate::redoGrab(QShortcutMap &map) +{ + Q_Q(QGuiShortcut); + if (Q_UNLIKELY(!parent)) { + qWarning("QGuiShortcut: No window parent defined"); + return; + } + + if (sc_id) + map.removeShortcut(sc_id, q); + if (sc_sequence.isEmpty()) + return; + sc_id = map.addShortcut(q, sc_sequence, sc_context, contextMatcher()); + if (!sc_enabled) + map.setShortcutEnabled(false, sc_id, q); + if (!sc_autorepeat) + map.setShortcutAutoRepeat(false, sc_id, q); +} + +/*! + Constructs a QGuiShortcut object for the \a parent window. Since no + shortcut key sequence is specified, the shortcut will not emit any + signals. + + \sa setKey() +*/ +QGuiShortcut::QGuiShortcut(QWindow *parent) + : QGuiShortcut(*new QGuiShortcutPrivate, parent) +{ +} + +/*! + Constructs a QGuiShortcut object for the \a parent window. The shortcut + operates on its parent, listening for \l{QShortcutEvent}s that + match the \a key sequence. Depending on the ambiguity of the + event, the shortcut will call the \a member function, or the \a + ambiguousMember function, if the key press was in the shortcut's + \a context. +*/ +QGuiShortcut::QGuiShortcut(const QKeySequence &key, QWindow *parent, + const char *member, const char *ambiguousMember, + Qt::ShortcutContext context) + : QGuiShortcut(*new QGuiShortcutPrivate, key, parent, member, ambiguousMember, context) +{ +} + +/*! + \internal +*/ +QGuiShortcut::QGuiShortcut(QGuiShortcutPrivate &dd, QObject *parent) + : QObject(dd, parent) +{ + Q_ASSERT(parent != nullptr); +} + +/*! + \internal +*/ +QGuiShortcut::QGuiShortcut(QGuiShortcutPrivate &dd, + const QKeySequence &key, QObject *parent, + const char *member, const char *ambiguousMember, + Qt::ShortcutContext context) + : QGuiShortcut(dd, parent) +{ + QAPP_CHECK("QGuiShortcut"); + + Q_D(QGuiShortcut); + d->sc_context = context; + d->sc_sequence = key; + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); + if (member) + connect(this, SIGNAL(activated()), parent, member); + if (ambiguousMember) + connect(this, SIGNAL(activatedAmbiguously()), parent, ambiguousMember); +} + +/*! + Destroys the shortcut. +*/ +QGuiShortcut::~QGuiShortcut() +{ + Q_D(QGuiShortcut); + if (qApp) + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(d->sc_id, this); +} + +/*! + \property QGuiShortcut::key + \brief the shortcut's key sequence + + This is a key sequence with an optional combination of Shift, Ctrl, + and Alt. The key sequence may be supplied in a number of ways: + + \snippet code/src_gui_kernel_qshortcut.cpp 1 + + By default, this property contains an empty key sequence. +*/ +void QGuiShortcut::setKey(const QKeySequence &key) +{ + Q_D(QGuiShortcut); + if (d->sc_sequence == key) + return; + QAPP_CHECK("setKey"); + d->sc_sequence = key; + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); +} + +QKeySequence QGuiShortcut::key() const +{ + Q_D(const QGuiShortcut); + return d->sc_sequence; +} + +/*! + \property QGuiShortcut::enabled + \brief whether the shortcut is enabled + + An enabled shortcut emits the activated() or activatedAmbiguously() + signal when a QShortcutEvent occurs that matches the shortcut's + key() sequence. + + If the application is in \c WhatsThis mode the shortcut will not emit + the signals, but will show the "What's This?" text instead. + + By default, this property is \c true. + + \sa whatsThis +*/ +void QGuiShortcut::setEnabled(bool enable) +{ + Q_D(QGuiShortcut); + if (d->sc_enabled == enable) + return; + QAPP_CHECK("setEnabled"); + d->sc_enabled = enable; + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, d->sc_id, this); +} + +bool QGuiShortcut::isEnabled() const +{ + Q_D(const QGuiShortcut); + return d->sc_enabled; +} + +/*! + \property QGuiShortcut::context + \brief the context in which the shortcut is valid + + A shortcut's context decides in which circumstances a shortcut is + allowed to be triggered. The normal context is Qt::WindowShortcut, + which allows the shortcut to trigger if the parent (the widget + containing the shortcut) is a subwidget of the active top-level + window. + + By default, this property is set to Qt::WindowShortcut. +*/ +void QGuiShortcut::setContext(Qt::ShortcutContext context) +{ + Q_D(QGuiShortcut); + if (d->sc_context == context) + return; + QAPP_CHECK("setContext"); + d->sc_context = context; + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); +} + +Qt::ShortcutContext QGuiShortcut::context() const +{ + Q_D(const QGuiShortcut); + return d->sc_context; +} + +/*! + \property QGuiShortcut::autoRepeat + \brief whether the shortcut can auto repeat + + If true, the shortcut will auto repeat when the keyboard shortcut + combination is held down, provided that keyboard auto repeat is + enabled on the system. + The default value is true. +*/ +void QGuiShortcut::setAutoRepeat(bool on) +{ + Q_D(QGuiShortcut); + if (d->sc_autorepeat == on) + return; + QAPP_CHECK("setAutoRepeat"); + d->sc_autorepeat = on; + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(on, d->sc_id, this); +} + +bool QGuiShortcut::autoRepeat() const +{ + Q_D(const QGuiShortcut); + return d->sc_autorepeat; +} + +/*! + Returns the shortcut's ID. + + \sa QShortcutEvent::shortcutId() +*/ +int QGuiShortcut::id() const +{ + Q_D(const QGuiShortcut); + return d->sc_id; +} + +/*! + \internal +*/ +bool QGuiShortcut::event(QEvent *e) +{ + Q_D(QGuiShortcut); + if (d->sc_enabled && e->type() == QEvent::Shortcut) { + auto se = static_cast<QShortcutEvent *>(e); + if (se->shortcutId() == d->sc_id && se->key() == d->sc_sequence + && !d->handleWhatsThis()) { + if (se->isAmbiguous()) + emit activatedAmbiguously(); + else + emit activated(); + return true; + } + } + return QObject::event(e); +} + +QT_END_NAMESPACE + +#include "moc_qguishortcut.cpp" diff --git a/src/gui/kernel/qguishortcut.h b/src/gui/kernel/qguishortcut.h new file mode 100644 index 0000000000..fb64f10c84 --- /dev/null +++ b/src/gui/kernel/qguishortcut.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGUISHORTCUT_H +#define QGUISHORTCUT_H + +#include <QtGui/qtguiglobal.h> +#include <QtGui/qkeysequence.h> +#include <QtCore/qobject.h> + +QT_REQUIRE_CONFIG(shortcut); + +QT_BEGIN_NAMESPACE + +class QGuiShortcutPrivate; +class QWindow; + +class Q_GUI_EXPORT QGuiShortcut : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QGuiShortcut) + Q_PROPERTY(QKeySequence key READ key WRITE setKey) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) + Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat) + Q_PROPERTY(Qt::ShortcutContext context READ context WRITE setContext) +public: + explicit QGuiShortcut(QWindow *parent); + explicit QGuiShortcut(const QKeySequence& key, QWindow *parent, + const char *member = nullptr, const char *ambiguousMember = nullptr, + Qt::ShortcutContext context = Qt::WindowShortcut); + ~QGuiShortcut(); + + void setKey(const QKeySequence& key); + QKeySequence key() const; + + void setEnabled(bool enable); + bool isEnabled() const; + + void setContext(Qt::ShortcutContext context); + Qt::ShortcutContext context() const; + + void setAutoRepeat(bool on); + bool autoRepeat() const; + + int id() const; + +Q_SIGNALS: + void activated(); + void activatedAmbiguously(); + +protected: + QGuiShortcut(QGuiShortcutPrivate &dd, QObject *parent); + QGuiShortcut(QGuiShortcutPrivate &dd, const QKeySequence& key, QObject *parent, + const char *member, const char *ambiguousMember, + Qt::ShortcutContext context); + + bool event(QEvent *e) override; +}; + +QT_END_NAMESPACE + +#endif // QGUISHORTCUT_H diff --git a/src/gui/image/qpictureformatplugin.h b/src/gui/kernel/qguishortcut_p.h index 3f59c04d79..420b02ef1a 100644 --- a/src/gui/image/qpictureformatplugin.h +++ b/src/gui/kernel/qguishortcut_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -37,40 +37,56 @@ ** ****************************************************************************/ -#ifndef QPICTUREFORMATPLUGIN_H -#define QPICTUREFORMATPLUGIN_H +#ifndef QGUISHORTCUT_P_H +#define QGUISHORTCUT_P_H -#include <QtGui/qtguiglobal.h> -#include <QtCore/qplugin.h> -#include <QtCore/qfactoryinterface.h> +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// -QT_BEGIN_NAMESPACE +#include <QtGui/private/qtguiglobal_p.h> +#include "qguishortcut.h" +#include <QtGui/qkeysequence.h> + +#include <QtCore/qstring.h> +#include <QtCore/private/qobject_p.h> +#include <private/qshortcutmap_p.h> -#if !defined(QT_NO_PICTURE) -class QPicture; -class QImage; -class QString; -class QStringList; -#define QPictureFormatInterface_iid "org.qt-project.Qt.QPictureFormatInterface" +QT_BEGIN_NAMESPACE -class Q_GUI_EXPORT QPictureFormatPlugin : public QObject +class QShortcutMap; + +/* + \internal + Private data accessed through d-pointer. +*/ +class Q_GUI_EXPORT QGuiShortcutPrivate : public QObjectPrivate { - Q_OBJECT + Q_DECLARE_PUBLIC(QGuiShortcut) public: - explicit QPictureFormatPlugin(QObject *parent = nullptr); - ~QPictureFormatPlugin(); + QGuiShortcutPrivate() = default; - virtual bool loadPicture(const QString &format, const QString &filename, QPicture *pic); - virtual bool savePicture(const QString &format, const QString &filename, const QPicture &pic); - virtual bool installIOHandler(const QString &format) = 0; + virtual QShortcutMap::ContextMatcher contextMatcher() const; + virtual bool handleWhatsThis() { return false; } + QKeySequence sc_sequence; + Qt::ShortcutContext sc_context = Qt::WindowShortcut; + bool sc_enabled = true; + bool sc_autorepeat = true; + int sc_id = 0; + void redoGrab(QShortcutMap &map); }; -#endif // QT_NO_PICTURE - QT_END_NAMESPACE -#endif // QPICTUREFORMATPLUGIN_H +#endif // QGUISHORTCUT_P_H diff --git a/src/gui/kernel/qguivariant.cpp b/src/gui/kernel/qguivariant.cpp index 4ed9d032f6..0f29633222 100644 --- a/src/gui/kernel/qguivariant.cpp +++ b/src/gui/kernel/qguivariant.cpp @@ -44,7 +44,9 @@ #include "qcursor.h" #include "qfont.h" #include "qimage.h" -#include "qkeysequence.h" +#if QT_CONFIG(shortcut) +# include "qkeysequence.h" +#endif #include "qtransform.h" #include "qmatrix.h" #include "qpalette.h" @@ -188,7 +190,7 @@ static bool convert(const QVariant::Private *d, int t, case QVariant::String: { QString *str = static_cast<QString *>(result); switch (d->type) { -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) case QVariant::KeySequence: *str = (*v_cast<QKeySequence>(d)).toString(QKeySequence::NativeText); return true; @@ -238,7 +240,7 @@ static bool convert(const QVariant::Private *d, int t, return true; } break; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) case QVariant::Int: if (d->type == QVariant::KeySequence) { const QKeySequence &seq = *v_cast<QKeySequence>(d); @@ -277,7 +279,7 @@ static bool convert(const QVariant::Private *d, int t, return true; } break; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) case QVariant::KeySequence: { QKeySequence *seq = static_cast<QKeySequence *>(result); switch (d->type) { diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h index 8364557020..fd53747fdd 100644 --- a/src/gui/kernel/qkeymapper_p.h +++ b/src/gui/kernel/qkeymapper_p.h @@ -53,7 +53,6 @@ #include <QtGui/private/qtguiglobal_p.h> #include <qobject.h> #include <private/qobject_p.h> -#include <qkeysequence.h> #include <qlist.h> #include <qlocale.h> #include <qevent.h> diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index e1244e1006..d5bdf1f15b 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -42,8 +42,6 @@ #include <qpa/qplatformtheme.h> #include "private/qguiapplication_p.h" -#if !defined(QT_NO_SHORTCUT) || defined(Q_CLANG_QDOC) - #include "qdebug.h" #include <QtCore/qhashfunctions.h> #ifndef QT_NO_DATASTREAM @@ -1679,9 +1677,6 @@ QDebug operator<<(QDebug dbg, const QKeySequence &p) } #endif -#endif // QT_NO_SHORTCUT - - /*! \typedef QKeySequence::DataPtr \internal diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h index 3dcbbe5941..68f256c37a 100644 --- a/src/gui/kernel/qkeysequence.h +++ b/src/gui/kernel/qkeysequence.h @@ -44,10 +44,9 @@ #include <QtCore/qstring.h> #include <QtCore/qobjectdefs.h> -QT_BEGIN_NAMESPACE - +QT_REQUIRE_CONFIG(shortcut); -#if !defined(QT_NO_SHORTCUT) || defined(Q_CLANG_QDOC) +QT_BEGIN_NAMESPACE class QKeySequence; @@ -227,17 +226,6 @@ Q_DECLARE_SHARED(QKeySequence) Q_GUI_EXPORT QDebug operator<<(QDebug, const QKeySequence &); #endif -#else - -class Q_GUI_EXPORT QKeySequence -{ -public: - QKeySequence() {} - QKeySequence(int) {} -}; - -#endif // QT_NO_SHORTCUT - QT_END_NAMESPACE #endif // QKEYSEQUENCE_H diff --git a/src/gui/kernel/qkeysequence_p.h b/src/gui/kernel/qkeysequence_p.h index fbcab5d34e..8c59505561 100644 --- a/src/gui/kernel/qkeysequence_p.h +++ b/src/gui/kernel/qkeysequence_p.h @@ -56,9 +56,10 @@ #include <algorithm> +QT_REQUIRE_CONFIG(shortcut); + QT_BEGIN_NAMESPACE -#ifndef QT_NO_SHORTCUT struct QKeyBinding { QKeySequence::StandardKey standardKey; @@ -87,7 +88,6 @@ public: Q_GUI_EXPORT static QString keyName(int key, QKeySequence::SequenceFormat format); static int decodeString(QString accel, QKeySequence::SequenceFormat format); }; -#endif // QT_NO_SHORTCUT QT_END_NAMESPACE diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp index fc063bc72c..e31ce00e14 100644 --- a/src/gui/kernel/qpalette.cpp +++ b/src/gui/kernel/qpalette.cpp @@ -44,10 +44,28 @@ #include "qvariant.h" #include "qdebug.h" +#include <QtCore/qmetaobject.h> + QT_BEGIN_NAMESPACE static int qt_palette_count = 1; +static constexpr QPalette::ResolveMask colorRoleOffset(QPalette::ColorGroup colorGroup) +{ + return QPalette::NColorRoles * colorGroup; +} + +static constexpr QPalette::ResolveMask bitPosition(QPalette::ColorGroup colorGroup, + QPalette::ColorRole colorRole) +{ + return colorRole + colorRoleOffset(colorGroup); +} + +Q_STATIC_ASSERT_X(bitPosition(QPalette::ColorGroup(QPalette::NColorGroups - 1), + QPalette::ColorRole(QPalette::NColorRoles - 1)) + < sizeof(QPalette::ResolveMask) * CHAR_BIT, + "The resolve mask type is not wide enough to fit the entire bit mask."); + class QPalettePrivate { public: QPalettePrivate() : ref(1), ser_no(qt_palette_count++), detach_no(0) { } @@ -321,11 +339,8 @@ static void qt_palette_from_color(QPalette &pal, const QColor &button) Returns the placeholder text brush of the current color group. - \note Before Qt 5.12, the placeholder text color was hard-coded in the code as - QPalette::text().color() where an alpha of 128 was applied. - We continue to support this behavior by default, unless you set your own brush. - One can get back the original placeholder color setting the special QBrush default - constructor as placeholder brush. + \note Before Qt 5.12, the placeholder text color was hard-coded as QPalette::text().color() + with an alpha of 128 applied. In Qt 6, it is an independent color. \sa ColorRole, brush() */ @@ -538,8 +553,6 @@ static void qt_palette_from_color(QPalette &pal, const QColor &button) QPalette::QPalette() : d(nullptr) { - data.current_group = Active; - data.resolve_mask = 0; // Initialize to application palette if present, else default to black. // This makes it possible to instantiate QPalette outside QGuiApplication, // for example in the platform plugins. @@ -549,7 +562,7 @@ QPalette::QPalette() } else { init(); qt_palette_from_color(*this, Qt::black); - data.resolve_mask = 0; + data.resolveMask = 0; } } @@ -681,8 +694,6 @@ QPalette::~QPalette() /*!\internal*/ void QPalette::init() { d = new QPalettePrivate; - data.resolve_mask = 0; - data.current_group = Active; //as a default.. } /*! @@ -739,7 +750,7 @@ const QBrush &QPalette::brush(ColorGroup gr, ColorRole cr) const Q_ASSERT(cr < NColorRoles); if(gr >= (int)NColorGroups) { if(gr == Current) { - gr = (ColorGroup)data.current_group; + gr = data.currentGroup; } else { qWarning("QPalette::brush: Unknown ColorGroup: %d", (int)gr); gr = Active; @@ -777,38 +788,18 @@ void QPalette::setBrush(ColorGroup cg, ColorRole cr, const QBrush &b) } if (cg == Current) { - cg = ColorGroup(data.current_group); + cg = data.currentGroup; } else if (cg >= NColorGroups) { qWarning("QPalette::setBrush: Unknown ColorGroup: %d", cg); cg = Active; } - // For placeholder we want to continue to respect the original behavior, which is - // derivating the text color, but only if user has not yet set his own brush. - // We then use Qt::NoBrush as an inernal way to know if the brush is customized or not. - - // ### Qt 6 - remove this special case - // Part 1 - Restore initial color to the given color group - if (cr == PlaceholderText && b == QBrush()) { - QColor col = brush(Text).color(); - col.setAlpha(128); - setBrush(cg, PlaceholderText, QBrush(col, Qt::NoBrush)); - return; - } - if (d->br[cg][cr] != b) { detach(); d->br[cg][cr] = b; } - data.resolve_mask |= (1<<cr); - - // ### Qt 6 - remove this special case - // Part 2 - Update initial color to the given color group - if (cr == Text && d->br[cg][PlaceholderText].style() == Qt::NoBrush) { - QColor col = brush(Text).color(); - col.setAlpha(128); - setBrush(cg, PlaceholderText, QBrush(col, Qt::NoBrush)); - } + + data.resolveMask |= ResolveMask(1) << bitPosition(cg, cr); } /*! @@ -817,12 +808,30 @@ void QPalette::setBrush(ColorGroup cg, ColorRole cr, const QBrush &b) Returns \c true if the ColorGroup \a cg and ColorRole \a cr has been set previously on this palette; otherwise returns \c false. - \sa setBrush() + The ColorGroup \a cg should be less than QPalette::NColorGroups, + but you can use QPalette::Current. In this case, the previously + set current color group will be used. + + The ColorRole \a cr should be less than QPalette::NColorRoles. + + \sa setBrush(), currentColorGroup() */ bool QPalette::isBrushSet(ColorGroup cg, ColorRole cr) const { - Q_UNUSED(cg); - return (data.resolve_mask & (1<<cr)); + if (cg == Current) + cg = data.currentGroup; + + if (cg >= NColorGroups) { + qWarning() << "Wrong color group:" << cg; + return false; + } + + if (cr >= NColorRoles) { + qWarning() << "Wrong color role:" << cr; + return false; + } + + return data.resolveMask & (ResolveMask(1) << bitPosition(cg, cr)); } /*! @@ -887,7 +896,7 @@ bool QPalette::isEqual(QPalette::ColorGroup group1, QPalette::ColorGroup group2) { if(group1 >= (int)NColorGroups) { if(group1 == Current) { - group1 = (ColorGroup)data.current_group; + group1 = data.currentGroup; } else { qWarning("QPalette::brush: Unknown ColorGroup(1): %d", (int)group1); group1 = Active; @@ -895,7 +904,7 @@ bool QPalette::isEqual(QPalette::ColorGroup group1, QPalette::ColorGroup group2) } if(group2 >= (int)NColorGroups) { if(group2 == Current) { - group2 = (ColorGroup)data.current_group; + group2 = data.currentGroup; } else { qWarning("QPalette::brush: Unknown ColorGroup(2): %d", (int)group2); group2 = Active; @@ -946,21 +955,25 @@ qint64 QPalette::cacheKey() const */ QPalette QPalette::resolve(const QPalette &other) const { - if ((*this == other && data.resolve_mask == other.data.resolve_mask) - || data.resolve_mask == 0) { + if ((*this == other && data.resolveMask == other.data.resolveMask) + || data.resolveMask == 0) { QPalette o = other; - o.data.resolve_mask = data.resolve_mask; + o.data.resolveMask = data.resolveMask; return o; } QPalette palette(*this); palette.detach(); - for(int role = 0; role < (int)NColorRoles; role++) - if (!(data.resolve_mask & (1<<role))) - for(int grp = 0; grp < (int)NColorGroups; grp++) + for (int role = 0; role < int(NColorRoles); ++role) { + for (int grp = 0; grp < int(NColorGroups); ++grp) { + if (!(data.resolveMask & (ResolveMask(1) << bitPosition(ColorGroup(grp), ColorRole(role))))) { palette.d->br[grp][role] = other.d->br[grp][role]; - palette.data.resolve_mask |= other.data.resolve_mask; + } + } + } + + palette.data.resolveMask |= other.data.resolveMask; return palette; } @@ -971,7 +984,12 @@ QPalette QPalette::resolve(const QPalette &other) const */ /*! - \fn void QPalette::resolve(uint mask) + \typedef ResolveMaskType + \internal + */ + +/*! + \fn void QPalette::resolve(ResolveMaskType mask) \internal */ @@ -1105,10 +1123,15 @@ void QPalette::setColorGroup(ColorGroup cg, const QBrush &windowText, const QBru QBrush(Qt::blue), QBrush(Qt::magenta), QBrush(toolTipBase), QBrush(toolTipText)); - data.resolve_mask &= ~(1 << Highlight); - data.resolve_mask &= ~(1 << HighlightedText); - data.resolve_mask &= ~(1 << LinkVisited); - data.resolve_mask &= ~(1 << Link); + for (int cr = Highlight; cr <= LinkVisited; ++cr) { + if (cg == All) { + for (int group = Active; group < NColorGroups; ++group) { + data.resolveMask &= ~(ResolveMask(1) << bitPosition(ColorGroup(group), ColorRole(cr))); + } + } else { + data.resolveMask &= ~(ResolveMask(1) << bitPosition(ColorGroup(cg), ColorRole(cr))); + } + } } @@ -1177,6 +1200,8 @@ Q_GUI_EXPORT QPalette qt_fusionPalette() QColor button = backGround; QColor shadow = dark.darker(135); QColor disabledShadow = shadow.lighter(150); + QColor placeholder = text; + placeholder.setAlpha(128); QPalette fusionPalette(Qt::black,backGround,light,dark,mid,text,base); fusionPalette.setBrush(QPalette::Midlight, midLight); @@ -1194,40 +1219,65 @@ Q_GUI_EXPORT QPalette qt_fusionPalette() fusionPalette.setBrush(QPalette::Active, QPalette::Highlight, QColor(48, 140, 198)); fusionPalette.setBrush(QPalette::Inactive, QPalette::Highlight, QColor(48, 140, 198)); fusionPalette.setBrush(QPalette::Disabled, QPalette::Highlight, QColor(145, 145, 145)); + + fusionPalette.setBrush(QPalette::PlaceholderText, placeholder); + return fusionPalette; } #ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug dbg, const QPalette &p) +static QString groupsToString(const QPalette &p, QPalette::ColorRole cr) { - const char *colorGroupNames[] = {"Active", "Disabled", "Inactive"}; - const char *colorRoleNames[] = - {"WindowText", "Button", "Light", "Midlight", "Dark", "Mid", "Text", - "BrightText", "ButtonText", "Base", "Window", "Shadow", "Highlight", - "HighlightedText", "Link", "LinkVisited", "AlternateBase", "NoRole", - "ToolTipBase","ToolTipText", "PlaceholderText" }; - QDebugStateSaver saver(dbg); - QDebug nospace = dbg.nospace(); - const uint mask = p.resolve(); - nospace << "QPalette(resolve=" << Qt::hex << Qt::showbase << mask << ','; - for (int role = 0; role < (int)QPalette::NColorRoles; ++role) { - if (mask & (1<<role)) { - if (role) - nospace << ','; - nospace << colorRoleNames[role] << ":["; - for (int group = 0; group < (int)QPalette::NColorGroups; ++group) { - if (group) - nospace << ','; - const QRgb color = p.color(static_cast<QPalette::ColorGroup>(group), - static_cast<QPalette::ColorRole>(role)).rgba(); - nospace << colorGroupNames[group] << ':' << color; - } - nospace << ']'; + const auto groupEnum = QMetaEnum::fromType<QPalette::ColorGroup>(); + + QString groupString; + for (int group = 0; group < QPalette::NColorGroups; ++group) { + const auto cg = QPalette::ColorGroup(group); + + if (p.isBrushSet(cg, cr)) { + const auto &color = p.color(cg, cr); + groupString += QString::fromUtf8(groupEnum.valueToKey(cg)) + QLatin1Char(':') + + color.name(QColor::HexArgb) + QLatin1Char(','); } } - nospace << ')' << Qt::noshowbase << Qt::dec; - return dbg; + groupString.chop(1); + + return groupString; } + +static QString rolesToString(const QPalette &p) +{ + const auto roleEnum = QMetaEnum::fromType<QPalette::ColorRole>(); + + QString roleString; + for (int role = 0; role < QPalette::NColorRoles; ++role) { + const auto cr = QPalette::ColorRole(role); + + auto groupString = groupsToString(p, cr); + if (!groupString.isEmpty()) + roleString += QString::fromUtf8(roleEnum.valueToKey(cr)) + QStringLiteral(":[") + + groupString + QStringLiteral("],"); + } + roleString.chop(1); + + return roleString; +} + +QDebug operator<<(QDebug dbg, const QPalette &p) +{ + QDebugStateSaver saver(dbg); + dbg.nospace(); + + dbg << "QPalette(resolve=" << Qt::hex << Qt::showbase << p.resolve(); + + auto roleString = rolesToString(p); + if (!roleString.isEmpty()) + dbg << ',' << roleString; + + dbg << ')'; + + return dbg; + } #endif QT_END_NAMESPACE diff --git a/src/gui/kernel/qpalette.h b/src/gui/kernel/qpalette.h index d3a840d9ad..c95640d383 100644 --- a/src/gui/kernel/qpalette.h +++ b/src/gui/kernel/qpalette.h @@ -72,14 +72,12 @@ public: { other.d = nullptr; } inline QPalette &operator=(QPalette &&other) noexcept { - for_faster_swapping_dont_use = other.for_faster_swapping_dont_use; qSwap(d, other.d); return *this; } void swap(QPalette &other) noexcept { qSwap(d, other.d); - qSwap(for_faster_swapping_dont_use, other.for_faster_swapping_dont_use); } operator QVariant() const; @@ -103,8 +101,8 @@ public: }; Q_ENUM(ColorRole) - inline ColorGroup currentColorGroup() const { return static_cast<ColorGroup>(data.current_group); } - inline void setCurrentColorGroup(ColorGroup cg) { data.current_group = cg; } + inline ColorGroup currentColorGroup() const { return data.currentGroup; } + inline void setCurrentColorGroup(ColorGroup cg) { data.currentGroup = cg; } inline const QColor &color(ColorGroup cg, ColorRole cr) const { return brush(cg, cr).color(); } @@ -158,9 +156,11 @@ public: #endif qint64 cacheKey() const; - QPalette resolve(const QPalette &) const; - inline uint resolve() const { return data.resolve_mask; } - inline void resolve(uint mask) { data.resolve_mask = mask; } + QPalette resolve(const QPalette &other) const; + + using ResolveMask = quint64; + inline ResolveMask resolve() const { return data.resolveMask; } + inline void resolve(ResolveMask mask) { data.resolveMask = mask; } private: void setColorGroup(ColorGroup cr, const QBrush &windowText, const QBrush &button, @@ -185,13 +185,11 @@ private: QPalettePrivate *d; struct Data { - uint current_group : 4; - uint resolve_mask : 28; - }; - union { - Data data; - quint32 for_faster_swapping_dont_use; + ResolveMask resolveMask{0}; + ColorGroup currentGroup{Active}; }; + Data data; + friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &s, const QPalette &p); }; diff --git a/src/gui/kernel/qplatformmenu.h b/src/gui/kernel/qplatformmenu.h index 28c29a704c..8e470aefd3 100644 --- a/src/gui/kernel/qplatformmenu.h +++ b/src/gui/kernel/qplatformmenu.h @@ -52,7 +52,9 @@ #include <QtGui/qtguiglobal.h> #include <QtCore/qpointer.h> #include <QtGui/QFont> -#include <QtGui/QKeySequence> +#if QT_CONFIG(shortcut) +# include <QtGui/QKeySequence> +#endif #include <QtGui/QIcon> QT_BEGIN_NAMESPACE @@ -85,7 +87,7 @@ public: virtual void setRole(MenuRole role) = 0; virtual void setCheckable(bool checkable) = 0; virtual void setChecked(bool isChecked) = 0; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) virtual void setShortcut(const QKeySequence& shortcut) = 0; #endif virtual void setEnabled(bool enabled) = 0; diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp index 71521c0339..93fd59e53f 100644 --- a/src/gui/kernel/qplatformtheme.cpp +++ b/src/gui/kernel/qplatformtheme.cpp @@ -167,7 +167,7 @@ QT_BEGIN_NAMESPACE */ -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) // Table of key bindings. It must be sorted on key sequence: // The integer value of VK_KEY | Modifier Keys (e.g., VK_META, and etc.) // A priority of 1 indicates that this is the primary key binding when multiple are defined. @@ -623,7 +623,7 @@ static inline int maybeSwapShortcut(int shortcut) } #endif -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) // mixed-mode predicate: all of these overloads are actually needed (but not all for every compiler) struct ByStandardKey { typedef bool result_type; @@ -688,6 +688,7 @@ QString QPlatformTheme::standardButtonText(int button) const return QPlatformTheme::defaultStandardButtonText(button); } +#if QT_CONFIG(shortcut) /*! Returns the mnemonic that should be used for a standard \a button. @@ -700,6 +701,7 @@ QKeySequence QPlatformTheme::standardButtonShortcut(int button) const Q_UNUSED(button) return QKeySequence(); } +#endif // QT_CONFIG(shortcut) QString QPlatformTheme::defaultStandardButtonText(int button) { @@ -784,7 +786,7 @@ unsigned QPlatformThemePrivate::currentKeyPlatforms() { const uint keyboardScheme = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::KeyboardScheme).toInt(); unsigned result = 1u << keyboardScheme; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) if (keyboardScheme == QPlatformTheme::KdeKeyboardScheme || keyboardScheme == QPlatformTheme::GnomeKeyboardScheme || keyboardScheme == QPlatformTheme::CdeKeyboardScheme) diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h index 3185fc4541..6ed612b785 100644 --- a/src/gui/kernel/qplatformtheme.h +++ b/src/gui/kernel/qplatformtheme.h @@ -51,7 +51,9 @@ #include <QtGui/qtguiglobal.h> #include <QtCore/QScopedPointer> -#include <QtGui/QKeySequence> +#if QT_CONFIG(shortcut) +# include <QtGui/QKeySequence> +#endif QT_BEGIN_NAMESPACE @@ -312,12 +314,14 @@ public: QPlatformTheme::IconOptions iconOptions = { }) const; virtual QIconEngine *createIconEngine(const QString &iconName) const; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) virtual QList<QKeySequence> keyBindings(QKeySequence::StandardKey key) const; #endif virtual QString standardButtonText(int button) const; +#if QT_CONFIG(shortcut) virtual QKeySequence standardButtonShortcut(int button) const; +#endif static QVariant defaultThemeHint(ThemeHint hint); static QString defaultStandardButtonText(int button); diff --git a/src/gui/kernel/qplatformtheme_p.h b/src/gui/kernel/qplatformtheme_p.h index 73deb890bb..2c16fec141 100644 --- a/src/gui/kernel/qplatformtheme_p.h +++ b/src/gui/kernel/qplatformtheme_p.h @@ -52,7 +52,9 @@ // #include <QtGui/private/qtguiglobal_p.h> -#include "private/qkeysequence_p.h" +#if QT_CONFIG(shortcut) +# include "private/qkeysequence_p.h" +#endif QT_BEGIN_NAMESPACE @@ -67,7 +69,7 @@ public: void initializeSystemPalette(); -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) static const QKeyBinding keyBindings[]; static const uint numberOfKeyBindings; #endif diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp index a7ea20266b..6039101cf4 100644 --- a/src/gui/kernel/qshortcutmap.cpp +++ b/src/gui/kernel/qshortcutmap.cpp @@ -49,8 +49,6 @@ #include <algorithm> -#ifndef QT_NO_SHORTCUT - QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcShortcutMap, "qt.gui.shortcutmap") @@ -689,5 +687,3 @@ void QShortcutMap::dumpMap() const #endif QT_END_NAMESPACE - -#endif // QT_NO_SHORTCUT diff --git a/src/gui/kernel/qshortcutmap_p.h b/src/gui/kernel/qshortcutmap_p.h index 8fc68229fb..aa3dd969f0 100644 --- a/src/gui/kernel/qshortcutmap_p.h +++ b/src/gui/kernel/qshortcutmap_p.h @@ -56,9 +56,9 @@ #include "QtCore/qvector.h" #include "QtCore/qscopedpointer.h" -QT_BEGIN_NAMESPACE +QT_REQUIRE_CONFIG(shortcut); -#ifndef QT_NO_SHORTCUT +QT_BEGIN_NAMESPACE // To enable dump output uncomment below //#define Dump_QShortcutMap @@ -106,8 +106,6 @@ private: QScopedPointer<QShortcutMapPrivate> d_ptr; }; -#endif // QT_NO_SHORTCUT - QT_END_NAMESPACE #endif // QSHORTCUTMAP_P_H diff --git a/src/gui/kernel/qwindowdefs.h b/src/gui/kernel/qwindowdefs.h index b4f3ed4712..cb0842da8c 100644 --- a/src/gui/kernel/qwindowdefs.h +++ b/src/gui/kernel/qwindowdefs.h @@ -43,6 +43,7 @@ #include <QtGui/qtguiglobal.h> #include <QtCore/qobjectdefs.h> #include <QtCore/qnamespace.h> +#include <QtCore/qcontainerfwd.h> QT_BEGIN_NAMESPACE @@ -80,7 +81,6 @@ class QString; class QByteArray; class QApplication; -template<typename T> class QList; typedef QList<QWidget *> QWidgetList; typedef QList<QWindow *> QWindowList; diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 3e7d592016..2de0131640 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -442,7 +442,7 @@ void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window, ulong t bool QWindowSystemInterface::handleShortcutEvent(QWindow *window, ulong timestamp, int keyCode, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, const QString &text, bool autorepeat, ushort count) { -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) if (!window) window = QGuiApplication::focusWindow(); @@ -1247,7 +1247,7 @@ Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *window, QEvent::Type t, int k, Qt:: Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1) { -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) // FIXME: This method should not allow targeting a specific object, but should // instead forward the event to a window, which then takes care of normal event diff --git a/src/gui/opengl/opengl.pri b/src/gui/opengl/opengl.pri index 24758afdeb..26060ea5df 100644 --- a/src/gui/opengl/opengl.pri +++ b/src/gui/opengl/opengl.pri @@ -27,7 +27,6 @@ qtConfig(opengl) { opengl/qopenglversionfunctions.h \ opengl/qopenglversionfunctionsfactory_p.h \ opengl/qopenglvertexarrayobject.h \ - opengl/qopengldebug.h \ opengl/qopengltextureblitter.h \ opengl/qopengltexture.h \ opengl/qopengltexture_p.h \ @@ -53,7 +52,6 @@ qtConfig(opengl) { opengl/qopenglversionfunctions.cpp \ opengl/qopenglversionfunctionsfactory.cpp \ opengl/qopenglvertexarrayobject.cpp \ - opengl/qopengldebug.cpp \ opengl/qopengltextureblitter.cpp \ opengl/qopengltexture.cpp \ opengl/qopengltexturehelper.cpp \ @@ -87,9 +85,7 @@ qtConfig(opengl) { opengl/qopenglfunctions_4_2_compatibility.h \ opengl/qopenglfunctions_4_3_compatibility.h \ opengl/qopenglfunctions_4_4_compatibility.h \ - opengl/qopenglfunctions_4_5_compatibility.h \ - opengl/qopenglqueryhelper_p.h \ - opengl/qopengltimerquery.h + opengl/qopenglfunctions_4_5_compatibility.h SOURCES += opengl/qopenglfunctions_1_0.cpp \ opengl/qopenglfunctions_1_1.cpp \ @@ -116,8 +112,7 @@ qtConfig(opengl) { opengl/qopenglfunctions_4_2_compatibility.cpp \ opengl/qopenglfunctions_4_3_compatibility.cpp \ opengl/qopenglfunctions_4_4_compatibility.cpp \ - opengl/qopenglfunctions_4_5_compatibility.cpp \ - opengl/qopengltimerquery.cpp + opengl/qopenglfunctions_4_5_compatibility.cpp } qtConfig(opengles2) { diff --git a/src/gui/opengl/qopengldebug.cpp b/src/gui/opengl/qopengldebug.cpp deleted file mode 100644 index 310006feaf..0000000000 --- a/src/gui/opengl/qopengldebug.cpp +++ /dev/null @@ -1,1826 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtCore/private/qobject_p.h> -#include <QtCore/qglobal.h> -#include <QtCore/qvarlengtharray.h> -#include <QtGui/qopengl.h> -#include <QtGui/qopenglfunctions.h> -#include <QtGui/qoffscreensurface.h> - -#include "qopengldebug.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QOpenGLDebugMessage - \brief The QOpenGLDebugMessage class wraps an OpenGL debug message. - \inmodule QtGui - \reentrant - \since 5.1 - \ingroup shared - \ingroup painting-3D - - Debug messages are usually created by the OpenGL server and then read by - OpenGL clients (either from the OpenGL internal debug log, or logged in real-time). - A debug message has a textual representation, a vendor-specific numeric id, - a source, a type and a severity. - - It's also possible for applications or third-party libraries and toolkits - to create and insert messages in the debug log. In order to do so, you can use - the createApplicationMessage() or the createThirdPartyMessage() static functions. - - \sa QOpenGLDebugLogger -*/ - -/*! - \class QOpenGLDebugLogger - \brief The QOpenGLDebugLogger enables logging of OpenGL debugging messages. - \inmodule QtGui - \since 5.1 - \ingroup painting-3D - - \tableofcontents - - \section1 Introduction - - OpenGL programming can be very error prone. Most of the time, a single - failing call to OpenGL can cause an entire portion of an application to - stop working, with nothing being drawn on the screen. - - The only way to be sure that no errors are being returned from the OpenGL - implementation is checking with \c{glGetError} after each and every API - call. Moreover, OpenGL errors stack up, therefore glGetError should always - be used in a loop like this: - - \snippet code/src_gui_opengl_qopengldebug.cpp 0 - - If you try to clear the error stack, make sure not just keep going until - GL_NO_ERROR is returned but also break on GL_CONTEXT_LOST as that error - value will keep repeating. - - There are also many other information we are interested in (as application - developers), for instance performance issues, or warnings about using - deprecated APIs. Those kind of messages are not reported through the - ordinary OpenGL error reporting mechanisms. - - QOpenGLDebugLogger aims at addressing these issues by providing access to - the \e{OpenGL debug log}. If your OpenGL implementation supports it (by - exposing the \c{GL_KHR_debug} extension), messages from the OpenGL server - will be either logged in an internal OpenGL log, or passed in "real-time" - to listeners as they're generated from OpenGL. - - QOpenGLDebugLogger supports both these modes of operation. Refer to the - following sections to find out the differences between them. - - \section1 Creating an OpenGL Debug Context - - For efficiency reasons, OpenGL implementations are allowed not to create - any debug output at all, unless the OpenGL context is a debug context. In order - to create a debug context from Qt, you must set the QSurfaceFormat::DebugContext - format option on the QSurfaceFormat used to create the QOpenGLContext object: - - \snippet code/src_gui_opengl_qopengldebug.cpp 1 - - Note that requesting a 3.2 OpenGL Core Profile is just for the example's - purposes; this class is not tied to any specific OpenGL or OpenGL ES - version, as it relies on the availability of the \c{GL_KHR_debug} extension - (see below). - - \section1 Creating and Initializing a QOpenGLDebugLogger - - QOpenGLDebugLogger is a simple QObject-derived class. Just like all QObject - subclasses, you create an instance (and optionally specify a parent - object), and like the other OpenGL functions in Qt you \e{must} initialize - it before usage by calling initialize() whilst there is a current OpenGL context: - - \snippet code/src_gui_opengl_qopengldebug.cpp 2 - - Note that the \c{GL_KHR_debug} extension \e{must} be available in the context - in order to access the messages logged by OpenGL. You can check the - presence of this extension by calling: - - \snippet code/src_gui_opengl_qopengldebug.cpp 3 - - where \c{ctx} is a valid QOpenGLContext. If the extension is not available, - initialize() will return false. - - \section1 Reading the Internal OpenGL Debug Log - - OpenGL implementations keep an internal log of debug messages. Messages - stored in this log can be retrieved by using the loggedMessages() function: - - \snippet code/src_gui_opengl_qopengldebug.cpp 4 - - The internal log has a limited size; when it fills up, older messages will - get discarded to make room for the new incoming messages. When you call - loggedMessages(), the internal log will be emptied as well. - - If you want to be sure not to lose any debug message, you must use real-time - logging instead of calling this function. However, debug messages might - still be generated in the timespan between context creation and activation - of real-time logging (or, in general, when the real-time logging is disabled). - - \section1 Real-time logging of messages - - It is also possible to receive a stream of debug messages from the OpenGL - server \e{as they are generated} by the implementation. In order to do so, - you need to connect a suitable slot to the messageLogged() signal, and - start logging by calling startLogging(): - - \snippet code/src_gui_opengl_qopengldebug.cpp 5 - - Similarly, logging can be disabled at any time by calling the stopLogging() - function. - - Real-time logging can be either asynchronous or synchronous, depending on - the parameter passed to startLogging(). When logging in asynchronous mode - (the default, as it has a very small overhead), the OpenGL implementation - can generate messages at any time, and/or in an order which is different from the - order of the OpenGL commands which caused those messages to be logged. - The messages could also be generated from a thread that it's different from - the thread the context is currently bound to. This is because OpenGL - implementations are usually highly threaded and asynchronous, and therefore - no warranties are made about the relative order and the timings of the - debug messages. - - On the other hand, logging in synchronous mode has a high overhead, but - the OpenGL implementation guarantees that all the messages caused by a - certain command are received in order, before the command returns, - and from the same thread the OpenGL context is bound to. - - This means that when logging in synchronous mode you will be able to run - your OpenGL application in a debugger, put a breakpoint on a slot connected - to the messageLogged() signal, and see in the backtrace the exact call - that caused the logged message. This can be extremely useful to debug - an OpenGL problem. Note that if OpenGL rendering is happening in another - thread, you must force the signal/slot connection type to Qt::DirectConnection - in order to be able to see the actual backtrace. - - Refer to the LoggingMode enum documentation for more information about - logging modes. - - \note When real-time logging is enabled, debug messages will \e{not} be - inserted in the internal OpenGL debug log any more; messages already - present in the internal log will not be deleted, nor they will be emitted - through the messageLogged() signal. Since some messages might be generated - before real-time logging is started (and therefore be kept in the internal - OpenGL log), it is important to always check if it contains any message - after calling startLogging(). - - \section1 Inserting Messages in the Debug Log - - It is possible for applications and libraries to insert custom messages in - the debug log, for instance for marking a group of related OpenGL commands - and therefore being then able to identify eventual messages coming from them. - - In order to do so, you can create a QOpenGLDebugMessage object by calling - \l{QOpenGLDebugMessage::}{createApplicationMessage()} or - \l{QOpenGLDebugMessage::}{createThirdPartyMessage()}, and then inserting it - into the log by calling logMessage(): - - \snippet code/src_gui_opengl_qopengldebug.cpp 6 - - Note that OpenGL implementations have a vendor-specific limit to the length - of the messages that can be inserted in the debug log. You can retrieve - this length by calling the maximumMessageLength() method; messages longer - than the limit will automatically get truncated. - - \section1 Controlling the Debug Output - - QOpenGLDebugMessage is also able to apply filters to the debug messages, and - therefore limit the amount of messages logged. You can enable or disable - logging of messages by calling enableMessages() and disableMessages() - respectively. By default, all messages are logged. - - It is possible to enable or disable messages by selecting them by: - - \list - \li source, type and severity (and including all ids in the selection); - \li id, source and type (and including all severities in the selection). - \endlist - - Note that the "enabled" status for a given message is a property of the - (id, source, type, severity) tuple; the message attributes \e{do not} form - a hierarchy of any kind. You should be careful about the order of the calls - to enableMessages() and disableMessages(), as it will change which - messages will are enabled / disabled. - - It's not possible to filter by the message text itself; applications - have to do that on their own (in slots connected to the messageLogged() - signal, or after fetching the messages in the internal debug log - through loggedMessages()). - - In order to simplify the management of the enabled / disabled statuses, - QOpenGLDebugMessage also supports the concept of \c{debug groups}. A debug - group contains the group of enabled / disabled configurations of debug - messages. Moreover, debug groups are organized in a stack: it is possible - to push and pop groups by calling pushGroup() and popGroup() respectively. - (When an OpenGL context is created, there is already a group in the stack). - - The enableMessages() and disableMessages() functions will modify the - configuration in the current debug group, that is, the one at the top of - the debug groups stack. - - When a new group is pushed onto the debug groups stack, it will inherit - the configuration of the group that was previously on the top of the stack. - Vice versa, popping a debug group will restore the configuration of - the debug group that becomes the new top. - - Pushing (respectively popping) debug groups will also automatically generate - a debug message of type QOpenGLDebugMessage::GroupPushType (respectively - \l{QOpenGLDebugMessage::}{GroupPopType}). - - \sa QOpenGLDebugMessage -*/ - -/*! - \enum QOpenGLDebugMessage::Source - - The Source enum defines the source of the debug message. - - \value InvalidSource - The source of the message is invalid; this is the source of a - default-constructed QOpenGLDebugMessage object. - - \value APISource - The message was generated in response to OpenGL API calls. - - \value WindowSystemSource - The message was generated by the window system. - - \value ShaderCompilerSource - The message was generated by the shader compiler. - - \value ThirdPartySource - The message was generated by a third party, for instance an OpenGL - framework a or debugging toolkit. - - \value ApplicationSource - The message was generated by the application itself. - - \value OtherSource - The message was generated by a source not included in this - enumeration. - - \omitvalue LastSource - - \value AnySource - This value corresponds to a mask of all possible message sources. -*/ - -/*! - \enum QOpenGLDebugMessage::Type - - The Type enum defines the type of the debug message. - - \value InvalidType - The type of the message is invalid; this is the type of a - default-constructed QOpenGLDebugMessage object. - - \value ErrorType - The message represents an error. - - \value DeprecatedBehaviorType - The message represents an usage of deprecated behavior. - - \value UndefinedBehaviorType - The message represents an usage of undefined behavior. - - \value PortabilityType - The message represents an usage of vendor-specific behavior, - that might pose portability concerns. - - \value PerformanceType - The message represents a performance issue. - - \value OtherType - The message represents a type not included in this - enumeration. - - \value MarkerType - The message represents a marker in the debug log. - - \value GroupPushType - The message represents a debug group push operation. - - \value GroupPopType - The message represents a debug group pop operation. - - \omitvalue LastType - - \value AnyType - This value corresponds to a mask of all possible message types. -*/ - -/*! - \enum QOpenGLDebugMessage::Severity - - The Severity enum defines the severity of the debug message. - - \value InvalidSeverity - The severity of the message is invalid; this is the severity of a - default-constructed QOpenGLDebugMessage object. - - \value HighSeverity - The message has a high severity. - - \value MediumSeverity - The message has a medium severity. - - \value LowSeverity - The message has a low severity. - - \value NotificationSeverity - The message is a notification. - - \omitvalue LastSeverity - - \value AnySeverity - This value corresponds to a mask of all possible message severities. -*/ - -/*! - \property QOpenGLDebugLogger::loggingMode - - \brief the logging mode passed to startLogging(). - - Note that logging must have been started or the value of this property - will be meaningless. - - \sa startLogging(), isLogging() -*/ -/*! - \enum QOpenGLDebugLogger::LoggingMode - - The LoggingMode enum defines the logging mode of the logger object. - - \value AsynchronousLogging - Messages from the OpenGL server are logged asynchronously. This means - that messages can be logged some time after the corresponding OpenGL - actions that caused them, and even be received in an out-of-order - fashion, depending on the OpenGL implementation. This mode has a very low - performance penalty, as OpenGL implementations are heavily threaded - and asynchronous by nature. - - \value SynchronousLogging - Messages from the OpenGL server are logged synchronously and - sequentially. This has a severe performance hit, as OpenGL - implementations are very asynchronous by nature; but it's very useful - to debug OpenGL problems, as OpenGL guarantees that the messages - generated by a OpenGL command will be logged before the corresponding - command execution has returned. Therefore, you can install a breakpoint - on the messageLogged() signal and see in the backtrace which OpenGL - command caused it; the only caveat is that if you are using OpenGL from - multiple threads you may need to force direct connection when - connecting to the messageLogged() signal. -*/ - -// When using OpenGL ES 2.0, all the necessary GL_KHR_debug constants are -// provided in qopengles2ext.h. Unfortunately, newer versions of that file -// suffix everything with _KHR which causes extra headache when the goal is -// to have a single piece of code that builds in all our target -// environments. Therefore, try to detect this and use our custom defines -// instead, which we anyway need for OS X. - -#if defined(GL_KHR_debug) && defined(GL_DEBUG_SOURCE_API_KHR) -#define USE_MANUAL_DEFS -#endif - -// Under OSX (at least up to 10.8) we cannot include our copy of glext.h, -// but we use the system-wide one, which unfortunately lacks all the needed -// defines/typedefs. In order to make the code compile, we just add here -// the GL_KHR_debug defines. - -#ifndef GL_KHR_debug -#define GL_KHR_debug 1 -#define USE_MANUAL_DEFS -#endif - -#ifdef USE_MANUAL_DEFS - -#ifndef GL_DEBUG_OUTPUT_SYNCHRONOUS -#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 -#endif -#ifndef GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH -#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243 -#endif -#ifndef GL_DEBUG_CALLBACK_FUNCTION -#define GL_DEBUG_CALLBACK_FUNCTION 0x8244 -#endif -#ifndef GL_DEBUG_CALLBACK_USER_PARAM -#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245 -#endif -#ifndef GL_DEBUG_SOURCE_API -#define GL_DEBUG_SOURCE_API 0x8246 -#endif -#ifndef GL_DEBUG_SOURCE_WINDOW_SYSTEM -#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 -#endif -#ifndef GL_DEBUG_SOURCE_SHADER_COMPILER -#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 -#endif -#ifndef GL_DEBUG_SOURCE_THIRD_PARTY -#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 -#endif -#ifndef GL_DEBUG_SOURCE_APPLICATION -#define GL_DEBUG_SOURCE_APPLICATION 0x824A -#endif -#ifndef GL_DEBUG_SOURCE_OTHER -#define GL_DEBUG_SOURCE_OTHER 0x824B -#endif -#ifndef GL_DEBUG_TYPE_ERROR -#define GL_DEBUG_TYPE_ERROR 0x824C -#endif -#ifndef GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR -#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D -#endif -#ifndef GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR -#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E -#endif -#ifndef GL_DEBUG_TYPE_PORTABILITY -#define GL_DEBUG_TYPE_PORTABILITY 0x824F -#endif -#ifndef GL_DEBUG_TYPE_PERFORMANCE -#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 -#endif -#ifndef GL_DEBUG_TYPE_OTHER -#define GL_DEBUG_TYPE_OTHER 0x8251 -#endif -#ifndef GL_DEBUG_TYPE_MARKER -#define GL_DEBUG_TYPE_MARKER 0x8268 -#endif -#ifndef GL_DEBUG_TYPE_PUSH_GROUP -#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 -#endif -#ifndef GL_DEBUG_TYPE_POP_GROUP -#define GL_DEBUG_TYPE_POP_GROUP 0x826A -#endif -#ifndef GL_DEBUG_SEVERITY_NOTIFICATION -#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B -#endif -#ifndef GL_MAX_DEBUG_GROUP_STACK_DEPTH -#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C -#endif -#ifndef GL_DEBUG_GROUP_STACK_DEPTH -#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D -#endif -#ifndef GL_BUFFER -#define GL_BUFFER 0x82E0 -#endif -#ifndef GL_SHADER -#define GL_SHADER 0x82E1 -#endif -#ifndef GL_PROGRAM -#define GL_PROGRAM 0x82E2 -#endif -#ifndef GL_QUERY -#define GL_QUERY 0x82E3 -#endif -#ifndef GL_PROGRAM_PIPELINE -#define GL_PROGRAM_PIPELINE 0x82E4 -#endif -#ifndef GL_SAMPLER -#define GL_SAMPLER 0x82E6 -#endif -#ifndef GL_DISPLAY_LIST -#define GL_DISPLAY_LIST 0x82E7 -#endif -#ifndef GL_MAX_LABEL_LENGTH -#define GL_MAX_LABEL_LENGTH 0x82E8 -#endif -#ifndef GL_MAX_DEBUG_MESSAGE_LENGTH -#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143 -#endif -#ifndef GL_MAX_DEBUG_LOGGED_MESSAGES -#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144 -#endif -#ifndef GL_DEBUG_LOGGED_MESSAGES -#define GL_DEBUG_LOGGED_MESSAGES 0x9145 -#endif -#ifndef GL_DEBUG_SEVERITY_HIGH -#define GL_DEBUG_SEVERITY_HIGH 0x9146 -#endif -#ifndef GL_DEBUG_SEVERITY_MEDIUM -#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 -#endif -#ifndef GL_DEBUG_SEVERITY_LOW -#define GL_DEBUG_SEVERITY_LOW 0x9148 -#endif -#ifndef GL_DEBUG_OUTPUT -#define GL_DEBUG_OUTPUT 0x92E0 -#endif -#ifndef GL_CONTEXT_FLAG_DEBUG_BIT -#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 -#endif -#ifndef GL_STACK_OVERFLOW -#define GL_STACK_OVERFLOW 0x0503 -#endif -#ifndef GL_STACK_UNDERFLOW -#define GL_STACK_UNDERFLOW 0x0504 -#endif - -typedef void (QOPENGLF_APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const GLvoid *userParam); - -#endif /* USE_MANUAL_DEFS */ - - -/*! - \internal -*/ -static QOpenGLDebugMessage::Source qt_messageSourceFromGL(GLenum source) -{ - switch (source) { - case GL_DEBUG_SOURCE_API: - return QOpenGLDebugMessage::APISource; - case GL_DEBUG_SOURCE_WINDOW_SYSTEM: - return QOpenGLDebugMessage::WindowSystemSource; - case GL_DEBUG_SOURCE_SHADER_COMPILER: - return QOpenGLDebugMessage::ShaderCompilerSource; - case GL_DEBUG_SOURCE_THIRD_PARTY: - return QOpenGLDebugMessage::ThirdPartySource; - case GL_DEBUG_SOURCE_APPLICATION: - return QOpenGLDebugMessage::ApplicationSource; - case GL_DEBUG_SOURCE_OTHER: - return QOpenGLDebugMessage::OtherSource; - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message source from GL"); - return QOpenGLDebugMessage::OtherSource; -} - -/*! - \internal -*/ -static GLenum qt_messageSourceToGL(QOpenGLDebugMessage::Source source) -{ - switch (source) { - case QOpenGLDebugMessage::InvalidSource: - break; - case QOpenGLDebugMessage::APISource: - return GL_DEBUG_SOURCE_API; - case QOpenGLDebugMessage::WindowSystemSource: - return GL_DEBUG_SOURCE_WINDOW_SYSTEM; - case QOpenGLDebugMessage::ShaderCompilerSource: - return GL_DEBUG_SOURCE_SHADER_COMPILER; - case QOpenGLDebugMessage::ThirdPartySource: - return GL_DEBUG_SOURCE_THIRD_PARTY; - case QOpenGLDebugMessage::ApplicationSource: - return GL_DEBUG_SOURCE_APPLICATION; - case QOpenGLDebugMessage::OtherSource: - return GL_DEBUG_SOURCE_OTHER; - case QOpenGLDebugMessage::AnySource: - break; - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message source"); - return GL_DEBUG_SOURCE_OTHER; -} - -/*! - \internal -*/ -static QString qt_messageSourceToString(QOpenGLDebugMessage::Source source) -{ - switch (source) { - case QOpenGLDebugMessage::InvalidSource: - return QStringLiteral("InvalidSource"); - case QOpenGLDebugMessage::APISource: - return QStringLiteral("APISource"); - case QOpenGLDebugMessage::WindowSystemSource: - return QStringLiteral("WindowSystemSource"); - case QOpenGLDebugMessage::ShaderCompilerSource: - return QStringLiteral("ShaderCompilerSource"); - case QOpenGLDebugMessage::ThirdPartySource: - return QStringLiteral("ThirdPartySource"); - case QOpenGLDebugMessage::ApplicationSource: - return QStringLiteral("ApplicationSource"); - case QOpenGLDebugMessage::OtherSource: - return QStringLiteral("OtherSource"); - case QOpenGLDebugMessage::AnySource: - return QStringLiteral("AnySource"); - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message source"); - return QString(); -} - -/*! - \internal -*/ -static QOpenGLDebugMessage::Type qt_messageTypeFromGL(GLenum type) -{ - switch (type) { - case GL_DEBUG_TYPE_ERROR: - return QOpenGLDebugMessage::ErrorType; - case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: - return QOpenGLDebugMessage::DeprecatedBehaviorType; - case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: - return QOpenGLDebugMessage::UndefinedBehaviorType; - case GL_DEBUG_TYPE_PORTABILITY: - return QOpenGLDebugMessage::PortabilityType; - case GL_DEBUG_TYPE_PERFORMANCE: - return QOpenGLDebugMessage::PerformanceType; - case GL_DEBUG_TYPE_OTHER: - return QOpenGLDebugMessage::OtherType; - case GL_DEBUG_TYPE_MARKER: - return QOpenGLDebugMessage::MarkerType; - case GL_DEBUG_TYPE_PUSH_GROUP: - return QOpenGLDebugMessage::GroupPushType; - case GL_DEBUG_TYPE_POP_GROUP: - return QOpenGLDebugMessage::GroupPopType; - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message type from GL"); - return QOpenGLDebugMessage::OtherType; -} - -/*! - \internal -*/ -static GLenum qt_messageTypeToGL(QOpenGLDebugMessage::Type type) -{ - switch (type) { - case QOpenGLDebugMessage::InvalidType: - break; - case QOpenGLDebugMessage::ErrorType: - return GL_DEBUG_TYPE_ERROR; - case QOpenGLDebugMessage::DeprecatedBehaviorType: - return GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR; - case QOpenGLDebugMessage::UndefinedBehaviorType: - return GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR; - case QOpenGLDebugMessage::PortabilityType: - return GL_DEBUG_TYPE_PORTABILITY; - case QOpenGLDebugMessage::PerformanceType: - return GL_DEBUG_TYPE_PERFORMANCE; - case QOpenGLDebugMessage::OtherType: - return GL_DEBUG_TYPE_OTHER; - case QOpenGLDebugMessage::MarkerType: - return GL_DEBUG_TYPE_MARKER; - case QOpenGLDebugMessage::GroupPushType: - return GL_DEBUG_TYPE_PUSH_GROUP; - case QOpenGLDebugMessage::GroupPopType: - return GL_DEBUG_TYPE_POP_GROUP; - case QOpenGLDebugMessage::AnyType: - break; - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type"); - return GL_DEBUG_TYPE_OTHER; -} - -/*! - \internal -*/ -static QString qt_messageTypeToString(QOpenGLDebugMessage::Type type) -{ - switch (type) { - case QOpenGLDebugMessage::InvalidType: - return QStringLiteral("InvalidType"); - case QOpenGLDebugMessage::ErrorType: - return QStringLiteral("ErrorType"); - case QOpenGLDebugMessage::DeprecatedBehaviorType: - return QStringLiteral("DeprecatedBehaviorType"); - case QOpenGLDebugMessage::UndefinedBehaviorType: - return QStringLiteral("UndefinedBehaviorType"); - case QOpenGLDebugMessage::PortabilityType: - return QStringLiteral("PortabilityType"); - case QOpenGLDebugMessage::PerformanceType: - return QStringLiteral("PerformanceType"); - case QOpenGLDebugMessage::OtherType: - return QStringLiteral("OtherType"); - case QOpenGLDebugMessage::MarkerType: - return QStringLiteral("MarkerType"); - case QOpenGLDebugMessage::GroupPushType: - return QStringLiteral("GroupPushType"); - case QOpenGLDebugMessage::GroupPopType: - return QStringLiteral("GroupPopType"); - case QOpenGLDebugMessage::AnyType: - return QStringLiteral("AnyType"); - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message type"); - return QString(); -} - -/*! - \internal -*/ -static QOpenGLDebugMessage::Severity qt_messageSeverityFromGL(GLenum severity) -{ - switch (severity) { - case GL_DEBUG_SEVERITY_HIGH: - return QOpenGLDebugMessage::HighSeverity; - case GL_DEBUG_SEVERITY_MEDIUM: - return QOpenGLDebugMessage::MediumSeverity; - case GL_DEBUG_SEVERITY_LOW: - return QOpenGLDebugMessage::LowSeverity; - case GL_DEBUG_SEVERITY_NOTIFICATION: - return QOpenGLDebugMessage::NotificationSeverity; - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message severity from GL"); - return QOpenGLDebugMessage::NotificationSeverity; -} - -/*! - \internal -*/ -static GLenum qt_messageSeverityToGL(QOpenGLDebugMessage::Severity severity) -{ - switch (severity) { - case QOpenGLDebugMessage::InvalidSeverity: - break; - case QOpenGLDebugMessage::HighSeverity: - return GL_DEBUG_SEVERITY_HIGH; - case QOpenGLDebugMessage::MediumSeverity: - return GL_DEBUG_SEVERITY_MEDIUM; - case QOpenGLDebugMessage::LowSeverity: - return GL_DEBUG_SEVERITY_LOW; - case QOpenGLDebugMessage::NotificationSeverity: - return GL_DEBUG_SEVERITY_NOTIFICATION; - case QOpenGLDebugMessage::AnySeverity: - break; - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message severity"); - return GL_DEBUG_SEVERITY_NOTIFICATION; -} - -/*! - \internal -*/ -static QString qt_messageSeverityToString(QOpenGLDebugMessage::Severity severity) -{ - switch (severity) { - case QOpenGLDebugMessage::InvalidSeverity: - return QStringLiteral("InvalidSeverity"); - case QOpenGLDebugMessage::HighSeverity: - return QStringLiteral("HighSeverity"); - case QOpenGLDebugMessage::MediumSeverity: - return QStringLiteral("MediumSeverity"); - case QOpenGLDebugMessage::LowSeverity: - return QStringLiteral("LowSeverity"); - case QOpenGLDebugMessage::NotificationSeverity: - return QStringLiteral("NotificationSeverity"); - case QOpenGLDebugMessage::AnySeverity: - return QStringLiteral("AnySeverity"); - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message severity"); - return QString(); -} - -class QOpenGLDebugMessagePrivate : public QSharedData -{ -public: - QOpenGLDebugMessagePrivate(); - - QString message; - GLuint id; - QOpenGLDebugMessage::Source source; - QOpenGLDebugMessage::Type type; - QOpenGLDebugMessage::Severity severity; -}; - -/*! - \internal -*/ -QOpenGLDebugMessagePrivate::QOpenGLDebugMessagePrivate() - : message(), - id(0), - source(QOpenGLDebugMessage::InvalidSource), - type(QOpenGLDebugMessage::InvalidType), - severity(QOpenGLDebugMessage::InvalidSeverity) -{ -} - - -/*! - Constructs a debug message with an empty message string, id set to 0, - source set to InvalidSource, type set to InvalidType, and severity set to - InvalidSeverity. - - \note This constructor should not be used to create a debug message; - instead, use the createApplicationMessage() or the createThirdPartyMessage() - static functions. - - \sa createApplicationMessage(), createThirdPartyMessage() -*/ -QOpenGLDebugMessage::QOpenGLDebugMessage() - : d(new QOpenGLDebugMessagePrivate) -{ -} - -/*! - Constructs a debug message as a copy of \a debugMessage. - - \sa operator=() -*/ -QOpenGLDebugMessage::QOpenGLDebugMessage(const QOpenGLDebugMessage &debugMessage) - : d(debugMessage.d) -{ -} - -/*! - Destroys this debug message. -*/ -QOpenGLDebugMessage::~QOpenGLDebugMessage() -{ -} - -/*! - Assigns the message \a debugMessage to this object, and returns a reference - to the copy. -*/ -QOpenGLDebugMessage &QOpenGLDebugMessage::operator=(const QOpenGLDebugMessage &debugMessage) -{ - d = debugMessage.d; - return *this; -} - -/*! - \fn QOpenGLDebugMessage &QOpenGLDebugMessage::operator=(QOpenGLDebugMessage &&debugMessage) - - Move-assigns \a debugMessage to this object. -*/ - -/*! - \fn void QOpenGLDebugMessage::swap(QOpenGLDebugMessage &debugMessage) - - Swaps the message \a debugMessage with this message. This operation is very - fast and never fails. -*/ - -/*! - Returns the source of the debug message. -*/ -QOpenGLDebugMessage::Source QOpenGLDebugMessage::source() const -{ - return d->source; -} - -/*! - Returns the type of the debug message. -*/ -QOpenGLDebugMessage::Type QOpenGLDebugMessage::type() const -{ - return d->type; -} - -/*! - Returns the severity of the debug message. -*/ -QOpenGLDebugMessage::Severity QOpenGLDebugMessage::severity() const -{ - return d->severity; -} - -/*! - Returns the id of the debug message. Ids are generally vendor-specific. -*/ -GLuint QOpenGLDebugMessage::id() const -{ - return d->id; -} - -/*! - Returns the textual message contained by this debug message. -*/ -QString QOpenGLDebugMessage::message() const -{ - return d->message; -} - -/*! - Constructs and returns a debug message with \a text as its text, \a id - as id, \a severity as severity, and \a type as type. The message source - will be set to ApplicationSource. - - \sa QOpenGLDebugLogger::logMessage(), createThirdPartyMessage() -*/ -QOpenGLDebugMessage QOpenGLDebugMessage::createApplicationMessage(const QString &text, - GLuint id, - QOpenGLDebugMessage::Severity severity, - QOpenGLDebugMessage::Type type) -{ - QOpenGLDebugMessage m; - m.d->message = text; - m.d->id = id; - m.d->severity = severity; - m.d->type = type; - m.d->source = ApplicationSource; - return m; -} - -/*! - Constructs and returns a debug message with \a text as its text, \a id - as id, \a severity as severity, and \a type as type. The message source - will be set to ThirdPartySource. - - \sa QOpenGLDebugLogger::logMessage(), createApplicationMessage() -*/ -QOpenGLDebugMessage QOpenGLDebugMessage::createThirdPartyMessage(const QString &text, - GLuint id, - QOpenGLDebugMessage::Severity severity, - QOpenGLDebugMessage::Type type) -{ - QOpenGLDebugMessage m; - m.d->message = text; - m.d->id = id; - m.d->severity = severity; - m.d->type = type; - m.d->source = ThirdPartySource; - return m; -} - -/*! - Returns \c true if this debug message is equal to \a debugMessage, or false - otherwise. Two debugging messages are equal if they have the same textual - message, the same id, the same source, the same type and the same severity. - - \sa operator!=() -*/ -bool QOpenGLDebugMessage::operator==(const QOpenGLDebugMessage &debugMessage) const -{ - return (d == debugMessage.d) - || (d->id == debugMessage.d->id - && d->source == debugMessage.d->source - && d->type == debugMessage.d->type - && d->severity == debugMessage.d->severity - && d->message == debugMessage.d->message); -} - -/*! - \fn bool QOpenGLDebugMessage::operator!=(const QOpenGLDebugMessage &debugMessage) const - - Returns \c true if this message is different from \a debugMessage, or false - otherwise. - - \sa operator==() -*/ - -#ifndef QT_NO_DEBUG_STREAM -/*! - \relates QOpenGLDebugMessage - - Writes the source \a source into the debug object \a debug for debugging - purposes. -*/ -QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Source source) -{ - QDebugStateSaver saver(debug); - debug.nospace() << "QOpenGLDebugMessage::Source(" - << qt_messageSourceToString(source) - << ')'; - return debug; -} - -/*! - \relates QOpenGLDebugMessage - - Writes the type \a type into the debug object \a debug for debugging - purposes. -*/ -QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Type type) -{ - QDebugStateSaver saver(debug); - debug.nospace() << "QOpenGLDebugMessage::Type(" - << qt_messageTypeToString(type) - << ')'; - return debug; -} - -/*! - \relates QOpenGLDebugMessage - - Writes the severity \a severity into the debug object \a debug for debugging - purposes. -*/ -QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Severity severity) -{ - QDebugStateSaver saver(debug); - debug.nospace() << "QOpenGLDebugMessage::Severity(" - << qt_messageSeverityToString(severity) - << ')'; - return debug; -} - -/*! - \relates QOpenGLDebugMessage - - Writes the message \a message into the debug object \a debug for debugging - purposes. -*/ -QDebug operator<<(QDebug debug, const QOpenGLDebugMessage &message) -{ - QDebugStateSaver saver(debug); - debug.nospace() << "QOpenGLDebugMessage(" - << qt_messageSourceToString(message.source()) << ", " - << message.id() << ", " - << message.message() << ", " - << qt_messageSeverityToString(message.severity()) << ", " - << qt_messageTypeToString(message.type()) << ')'; - return debug; - -} -#endif // QT_NO_DEBUG_STREAM - -typedef void (QOPENGLF_APIENTRYP qt_glDebugMessageControl_t)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); -typedef void (QOPENGLF_APIENTRYP qt_glDebugMessageInsert_t)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); -typedef void (QOPENGLF_APIENTRYP qt_glDebugMessageCallback_t)(GLDEBUGPROC callback, const void *userParam); -typedef GLuint (QOPENGLF_APIENTRYP qt_glGetDebugMessageLog_t)(GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); -typedef void (QOPENGLF_APIENTRYP qt_glPushDebugGroup_t)(GLenum source, GLuint id, GLsizei length, const GLchar *message); -typedef void (QOPENGLF_APIENTRYP qt_glPopDebugGroup_t)(); -typedef void (QOPENGLF_APIENTRYP qt_glGetPointerv_t)(GLenum pname, GLvoid **params); - -class QOpenGLDebugLoggerPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QOpenGLDebugLogger) -public: - QOpenGLDebugLoggerPrivate(); - - void handleMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *rawMessage); - void controlDebugMessages(QOpenGLDebugMessage::Sources sources, - QOpenGLDebugMessage::Types types, - QOpenGLDebugMessage::Severities severities, - const QVector<GLuint> &ids, - const QByteArray &callerName, - bool enable); - void _q_contextAboutToBeDestroyed(); - - qt_glDebugMessageControl_t glDebugMessageControl; - qt_glDebugMessageInsert_t glDebugMessageInsert; - qt_glDebugMessageCallback_t glDebugMessageCallback; - qt_glGetDebugMessageLog_t glGetDebugMessageLog; - qt_glPushDebugGroup_t glPushDebugGroup; - qt_glPopDebugGroup_t glPopDebugGroup; - qt_glGetPointerv_t glGetPointerv; - - GLDEBUGPROC oldDebugCallbackFunction; - void *oldDebugCallbackParameter; - QOpenGLContext *context; - GLint maxMessageLength; - QOpenGLDebugLogger::LoggingMode loggingMode; - bool initialized : 1; - bool isLogging : 1; - bool debugWasEnabled : 1; - bool syncDebugWasEnabled : 1; -}; - -/*! - \internal -*/ -QOpenGLDebugLoggerPrivate::QOpenGLDebugLoggerPrivate() - : glDebugMessageControl(nullptr), - glDebugMessageInsert(nullptr), - glDebugMessageCallback(nullptr), - glGetDebugMessageLog(nullptr), - glPushDebugGroup(nullptr), - glPopDebugGroup(nullptr), - oldDebugCallbackFunction(nullptr), - context(nullptr), - maxMessageLength(0), - loggingMode(QOpenGLDebugLogger::AsynchronousLogging), - initialized(false), - isLogging(false), - debugWasEnabled(false), - syncDebugWasEnabled(false) -{ -} - -/*! - \internal -*/ -void QOpenGLDebugLoggerPrivate::handleMessage(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar *rawMessage) -{ - if (oldDebugCallbackFunction) - oldDebugCallbackFunction(source, type, id, severity, length, rawMessage, oldDebugCallbackParameter); - - QOpenGLDebugMessage message; - - QOpenGLDebugMessagePrivate *messagePrivate = message.d.data(); - messagePrivate->source = qt_messageSourceFromGL(source); - messagePrivate->type = qt_messageTypeFromGL(type); - messagePrivate->id = id; - messagePrivate->severity = qt_messageSeverityFromGL(severity); - // not passing the length to fromUtf8, as some bugged OpenGL drivers - // do not handle the length correctly. Just rely on the message to be NUL terminated. - messagePrivate->message = QString::fromUtf8(rawMessage); - - Q_Q(QOpenGLDebugLogger); - emit q->messageLogged(message); -} - -/*! - \internal -*/ -void QOpenGLDebugLoggerPrivate::controlDebugMessages(QOpenGLDebugMessage::Sources sources, - QOpenGLDebugMessage::Types types, - QOpenGLDebugMessage::Severities severities, - const QVector<GLuint> &ids, - const QByteArray &callerName, - bool enable) -{ - if (!initialized) { - qWarning("QOpenGLDebugLogger::%s(): object must be initialized before enabling/disabling messages", callerName.constData()); - return; - } - if (sources == QOpenGLDebugMessage::InvalidSource) { - qWarning("QOpenGLDebugLogger::%s(): invalid source specified", callerName.constData()); - return; - } - if (types == QOpenGLDebugMessage::InvalidType) { - qWarning("QOpenGLDebugLogger::%s(): invalid type specified", callerName.constData()); - return; - } - if (severities == QOpenGLDebugMessage::InvalidSeverity) { - qWarning("QOpenGLDebugLogger::%s(): invalid severity specified", callerName.constData()); - return; - } - - QVarLengthArray<GLenum, 8> glSources; - QVarLengthArray<GLenum, 8> glTypes; - QVarLengthArray<GLenum, 8> glSeverities; - - if (ids.count() > 0) { - Q_ASSERT(severities == QOpenGLDebugMessage::AnySeverity); - - // The GL_KHR_debug extension says: - // - // - If <count> is greater than zero, then <ids> is an array of <count> - // message IDs for the specified combination of <source> and <type>. In - // this case, if <source> or <type> is DONT_CARE, or <severity> is not - // DONT_CARE, the error INVALID_OPERATION is generated. If <count> is - // zero, the value if <ids> is ignored. - // - // This means we can't convert AnySource or AnyType into DONT_CARE, but we have to roll - // them into individual sources/types. - - if (sources == QOpenGLDebugMessage::AnySource) { - sources = QOpenGLDebugMessage::InvalidSource; - for (uint i = 1; i <= QOpenGLDebugMessage::LastSource; i = i << 1) - sources |= QOpenGLDebugMessage::Source(i); - } - - if (types == QOpenGLDebugMessage::AnyType) { - types = QOpenGLDebugMessage::InvalidType; - for (uint i = 1; i <= QOpenGLDebugMessage::LastType; i = i << 1) - types |= QOpenGLDebugMessage::Type(i); - } - } - -#define CONVERT_TO_GL_DEBUG_MESSAGE_CONTROL_PARAMETERS(type, source, target) \ - if (source == QOpenGLDebugMessage::Any ## type) { \ - target << GL_DONT_CARE; \ - } else { \ - for (uint i = 1; i <= QOpenGLDebugMessage::Last ## type; i = i << 1) \ - if (source.testFlag(QOpenGLDebugMessage:: type (i))) \ - target << qt_message ## type ## ToGL (QOpenGLDebugMessage:: type (i)); \ - } - - CONVERT_TO_GL_DEBUG_MESSAGE_CONTROL_PARAMETERS(Source, sources, glSources) - CONVERT_TO_GL_DEBUG_MESSAGE_CONTROL_PARAMETERS(Type, types, glTypes) - CONVERT_TO_GL_DEBUG_MESSAGE_CONTROL_PARAMETERS(Severity, severities, glSeverities) -#undef CONVERT_TO_GL_DEBUG_MESSAGE_CONTROL_PARAMETERS - - const GLsizei idCount = ids.count(); - // The GL_KHR_debug extension says that if idCount is 0, idPtr must be ignored. - // Unfortunately, some bugged drivers do NOT ignore it, so pass NULL in case. - const GLuint * const idPtr = idCount ? ids.constData() : nullptr; - - for (GLenum source : glSources) - for (GLenum type : glTypes) - for (GLenum severity : glSeverities) - glDebugMessageControl(source, type, severity, idCount, idPtr, GLboolean(enable)); -} - -/*! - \internal -*/ -void QOpenGLDebugLoggerPrivate::_q_contextAboutToBeDestroyed() -{ - Q_ASSERT(context); - - // Re-make our context current somehow, otherwise stopLogging will fail. - - // Save the current context and its surface in case we need to set them back - QOpenGLContext *currentContext = QOpenGLContext::currentContext(); - QSurface *currentSurface = nullptr; - - QScopedPointer<QOffscreenSurface> offscreenSurface; - - if (context != currentContext) { - // Make our old context current on a temporary surface - if (currentContext) - currentSurface = currentContext->surface(); - - offscreenSurface.reset(new QOffscreenSurface); - offscreenSurface->setFormat(context->format()); - offscreenSurface->create(); - if (!context->makeCurrent(offscreenSurface.data())) - qWarning("QOpenGLDebugLoggerPrivate::_q_contextAboutToBeDestroyed(): could not make the owning GL context current for cleanup"); - } - - Q_Q(QOpenGLDebugLogger); - q->stopLogging(); - - if (offscreenSurface) { - // We did change the current context: set it back - if (currentContext) - currentContext->makeCurrent(currentSurface); - else - context->doneCurrent(); - } - - QObject::disconnect(context, SIGNAL(aboutToBeDestroyed()), q, SLOT(_q_contextAboutToBeDestroyed())); - context = nullptr; - initialized = false; -} - -extern "C" { -static void QOPENGLF_APIENTRY qt_opengl_debug_callback(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar *rawMessage, - const GLvoid *userParam) -{ - QOpenGLDebugLoggerPrivate *loggerPrivate = static_cast<QOpenGLDebugLoggerPrivate *>(const_cast<GLvoid *>(userParam)); - loggerPrivate->handleMessage(source, type, id, severity, length, rawMessage); -} -} - -/*! - Constructs a new logger object with the given \a parent. - - \note The object must be initialized before logging can happen. - - \sa initialize() -*/ -QOpenGLDebugLogger::QOpenGLDebugLogger(QObject *parent) - : QObject(*new QOpenGLDebugLoggerPrivate, parent) -{ - // QOpenGLDebugMessage is going to be mostly used as an argument - // of a cross thread connection, therefore let's ease the life for the users - // and register the type for them. - qRegisterMetaType<QOpenGLDebugMessage>(); -} - -/*! - Destroys the logger object. -*/ -QOpenGLDebugLogger::~QOpenGLDebugLogger() -{ - stopLogging(); -} - -/*! - Initializes the object in the current OpenGL context. The context must - support the \c{GL_KHR_debug} extension for the initialization to succeed. - The object must be initialized before any logging can happen. - - It is safe to call this function multiple times from the same context. - - This function can also be used to change the context of a previously - initialized object; note that in this case the object must not be logging - when you call this function. - - Returns \c true if the logger is successfully initialized; false otherwise. - - \sa QOpenGLContext -*/ -bool QOpenGLDebugLogger::initialize() -{ - QOpenGLContext *context = QOpenGLContext::currentContext(); - if (!context) { - qWarning("QOpenGLDebugLogger::initialize(): no current OpenGL context found."); - return false; - } - - Q_D(QOpenGLDebugLogger); - if (d->context == context) { - // context is non-NULL, d->context is non NULL only on successful initialization. - Q_ASSERT(d->initialized); - return true; - } - - if (d->isLogging) { - qWarning("QOpenGLDebugLogger::initialize(): cannot initialize the object while logging. Please stop the logging first."); - return false; - } - - if (d->context) - disconnect(d->context, SIGNAL(aboutToBeDestroyed()), this, SLOT(_q_contextAboutToBeDestroyed())); - - d->initialized = false; - d->context = nullptr; - - if (!context->hasExtension(QByteArrayLiteral("GL_KHR_debug"))) - return false; - - d->context = context; - connect(d->context, SIGNAL(aboutToBeDestroyed()), this, SLOT(_q_contextAboutToBeDestroyed())); - -#define GET_DEBUG_PROC_ADDRESS(procName) \ - d->procName = reinterpret_cast< qt_ ## procName ## _t >( \ - d->context->getProcAddress(d->context->isOpenGLES() ? (#procName "KHR") : (#procName)) \ - ); - - GET_DEBUG_PROC_ADDRESS(glDebugMessageControl); - GET_DEBUG_PROC_ADDRESS(glDebugMessageInsert); - GET_DEBUG_PROC_ADDRESS(glDebugMessageCallback); - GET_DEBUG_PROC_ADDRESS(glGetDebugMessageLog); - GET_DEBUG_PROC_ADDRESS(glPushDebugGroup); - GET_DEBUG_PROC_ADDRESS(glPopDebugGroup); - GET_DEBUG_PROC_ADDRESS(glGetPointerv) - -#undef GET_DEBUG_PROC_ADDRESS - - QOpenGLContext::currentContext()->functions()->glGetIntegerv(GL_MAX_DEBUG_MESSAGE_LENGTH, &d->maxMessageLength); - -#ifndef QT_NO_DEBUG - if (!d->context->format().testOption(QSurfaceFormat::DebugContext)) { - qWarning("QOpenGLDebugLogger::initialize(): the current context is not a debug context:\n" - " this means that the GL may not generate any debug output at all.\n" - " To avoid this warning, try creating the context with the\n" - " QSurfaceFormat::DebugContext surface format option."); - } -#endif // QT_NO_DEBUG - - d->initialized = true; - return true; -} - -/*! - Returns \c true if this object is currently logging, false otherwise. - - \sa startLogging() -*/ -bool QOpenGLDebugLogger::isLogging() const -{ - Q_D(const QOpenGLDebugLogger); - return d->isLogging; -} - -/*! - Starts logging messages coming from the OpenGL server. When a new message - is received, the signal messageLogged() is emitted, carrying the logged - message as argument. - - \a loggingMode specifies whether the logging must be asynchronous (the default) - or synchronous. - - QOpenGLDebugLogger will record the values of \c{GL_DEBUG_OUTPUT} and - \c{GL_DEBUG_OUTPUT_SYNCHRONOUS} when logging is started, and set them back - when logging is stopped. Moreover, any user-defined OpenGL debug callback - installed when this function is invoked will be restored when logging is - stopped; QOpenGLDebugLogger will ensure that the pre-existing callback will - still be invoked when logging. - - \note It's not possible to change the logging mode without stopping and - starting logging again. This might change in a future version of Qt. - - \note The object must be initialized before logging can happen. - - \sa stopLogging(), initialize() -*/ -void QOpenGLDebugLogger::startLogging(QOpenGLDebugLogger::LoggingMode loggingMode) -{ - Q_D(QOpenGLDebugLogger); - if (!d->initialized) { - qWarning("QOpenGLDebugLogger::startLogging(): object must be initialized before logging can start"); - return; - } - if (d->isLogging) { - qWarning("QOpenGLDebugLogger::startLogging(): this object is already logging"); - return; - } - - d->isLogging = true; - d->loggingMode = loggingMode; - - d->glGetPointerv(GL_DEBUG_CALLBACK_FUNCTION, reinterpret_cast<void **>(&d->oldDebugCallbackFunction)); - d->glGetPointerv(GL_DEBUG_CALLBACK_USER_PARAM, &d->oldDebugCallbackParameter); - - d->glDebugMessageCallback(&qt_opengl_debug_callback, d); - - QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); - d->debugWasEnabled = funcs->glIsEnabled(GL_DEBUG_OUTPUT); - d->syncDebugWasEnabled = funcs->glIsEnabled(GL_DEBUG_OUTPUT_SYNCHRONOUS); - - if (d->loggingMode == SynchronousLogging) - funcs->glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - else - funcs->glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - - funcs->glEnable(GL_DEBUG_OUTPUT); -} - -/*! - Returns the logging mode of the object. - - \sa startLogging() -*/ -QOpenGLDebugLogger::LoggingMode QOpenGLDebugLogger::loggingMode() const -{ - Q_D(const QOpenGLDebugLogger); - return d->loggingMode; -} - -/*! - Stops logging messages from the OpenGL server. - - \sa startLogging() -*/ -void QOpenGLDebugLogger::stopLogging() -{ - Q_D(QOpenGLDebugLogger); - if (!d->isLogging) - return; - - QOpenGLContext *currentContext = QOpenGLContext::currentContext(); - if (!currentContext || currentContext != d->context) { - qWarning("QOpenGLDebugLogger::stopLogging(): attempting to stop logging with the wrong OpenGL context current"); - return; - } - - d->isLogging = false; - - d->glDebugMessageCallback(d->oldDebugCallbackFunction, d->oldDebugCallbackParameter); - - QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); - if (!d->debugWasEnabled) - funcs->glDisable(GL_DEBUG_OUTPUT); - - if (d->syncDebugWasEnabled) - funcs->glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - else - funcs->glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS); -} - -/*! - Inserts the message \a debugMessage into the OpenGL debug log. This provides - a way for applications or libraries to insert custom messages that can - ease the debugging of OpenGL applications. - - \note \a debugMessage must have QOpenGLDebugMessage::ApplicationSource or - QOpenGLDebugMessage::ThirdPartySource as its source, and a valid - type and severity, otherwise it will not be inserted into the log. - - \note The object must be initialized before logging can happen. - - \sa initialize() -*/ -void QOpenGLDebugLogger::logMessage(const QOpenGLDebugMessage &debugMessage) -{ - Q_D(QOpenGLDebugLogger); - if (!d->initialized) { - qWarning("QOpenGLDebugLogger::logMessage(): object must be initialized before logging messages"); - return; - } - if (debugMessage.source() != QOpenGLDebugMessage::ApplicationSource - && debugMessage.source() != QOpenGLDebugMessage::ThirdPartySource) { - qWarning("QOpenGLDebugLogger::logMessage(): using a message source different from ApplicationSource\n" - " or ThirdPartySource is not supported by GL_KHR_debug. The message will not be logged."); - return; - } - if (debugMessage.type() == QOpenGLDebugMessage::InvalidType - || debugMessage.type() == QOpenGLDebugMessage::AnyType - || debugMessage.severity() == QOpenGLDebugMessage::InvalidSeverity - || debugMessage.severity() == QOpenGLDebugMessage::AnySeverity) { - qWarning("QOpenGLDebugLogger::logMessage(): the message has a non-valid type and/or severity. The message will not be logged."); - return; - } - - const GLenum source = qt_messageSourceToGL(debugMessage.source()); - const GLenum type = qt_messageTypeToGL(debugMessage.type()); - const GLenum severity = qt_messageSeverityToGL(debugMessage.severity()); - QByteArray rawMessage = debugMessage.message().toUtf8(); - rawMessage.append('\0'); - - if (rawMessage.length() > d->maxMessageLength) { - qWarning("QOpenGLDebugLogger::logMessage(): message too long, truncating it\n" - " (%d bytes long, but the GL accepts up to %d bytes)", rawMessage.length(), d->maxMessageLength); - rawMessage.resize(d->maxMessageLength - 1); - rawMessage.append('\0'); - } - - // Don't pass rawMessage.length(), as unfortunately bugged - // OpenGL drivers will eat the trailing NUL in the message. Just rely - // on the message being NUL terminated. - d->glDebugMessageInsert(source, - type, - debugMessage.id(), - severity, - -1, - rawMessage.constData()); -} - -/*! - Pushes a debug group with name \a name, id \a id, and source \a source onto - the debug groups stack. If the group is successfully pushed, OpenGL will - automatically log a message with message \a name, id \a id, source \a - source, type QOpenGLDebugMessage::GroupPushType and severity - QOpenGLDebugMessage::NotificationSeverity. - - The newly pushed group will inherit the same filtering settings of the - group that was on the top of the stack; that is, the filtering will not be - changed by pushing a new group. - - \note The \a source must either be QOpenGLDebugMessage::ApplicationSource or - QOpenGLDebugMessage::ThirdPartySource, otherwise the group will not be pushed. - - \note The object must be initialized before managing debug groups. - - \sa popGroup(), enableMessages(), disableMessages() -*/ -void QOpenGLDebugLogger::pushGroup(const QString &name, GLuint id, QOpenGLDebugMessage::Source source) -{ - Q_D(QOpenGLDebugLogger); - if (!d->initialized) { - qWarning("QOpenGLDebugLogger::pushGroup(): object must be initialized before pushing a debug group"); - return; - } - if (source != QOpenGLDebugMessage::ApplicationSource - && source != QOpenGLDebugMessage::ThirdPartySource) { - qWarning("QOpenGLDebugLogger::pushGroup(): using a source different from ApplicationSource\n" - " or ThirdPartySource is not supported by GL_KHR_debug. The group will not be pushed."); - return; - } - - QByteArray rawName = name.toUtf8(); - rawName.append('\0'); - if (rawName.length() > d->maxMessageLength) { - qWarning("QOpenGLDebugLogger::pushGroup(): group name too long, truncating it\n" - " (%d bytes long, but the GL accepts up to %d bytes)", rawName.length(), d->maxMessageLength); - rawName.resize(d->maxMessageLength - 1); - rawName.append('\0'); - } - - // Don't pass rawMessage.length(), as unfortunately bugged - // OpenGL drivers will eat the trailing NUL in the name. Just rely - // on the name being NUL terminated. - d->glPushDebugGroup(qt_messageSourceToGL(source), id, -1, rawName.constData()); -} - -/*! - Pops the topmost debug group from the debug groups stack. If the group is - successfully popped, OpenGL will automatically log a message with message, - id and source matching those of the popped group, type - QOpenGLDebugMessage::GroupPopType and severity - QOpenGLDebugMessage::NotificationSeverity. - - Popping a debug group will restore the message filtering settings of the - group that becomes the top of the debug groups stack. - - \note The object must be initialized before managing debug groups. - - \sa pushGroup() -*/ -void QOpenGLDebugLogger::popGroup() -{ - Q_D(QOpenGLDebugLogger); - if (!d->initialized) { - qWarning("QOpenGLDebugLogger::pushGroup(): object must be initialized before popping a debug group"); - return; - } - - d->glPopDebugGroup(); -} - -/*! - Enables the logging of messages from the given \a sources, of the given \a - types and with the given \a severities and any message id. - - The logging will be enabled in the current control group. - - \sa disableMessages(), pushGroup(), popGroup() -*/ -void QOpenGLDebugLogger::enableMessages(QOpenGLDebugMessage::Sources sources, - QOpenGLDebugMessage::Types types, - QOpenGLDebugMessage::Severities severities) -{ - Q_D(QOpenGLDebugLogger); - d->controlDebugMessages(sources, - types, - severities, - QVector<GLuint>(), - QByteArrayLiteral("enableMessages"), - true); -} - -/*! - Enables the logging of messages with the given \a ids, from the given \a - sources and of the given \a types and any severity. - - The logging will be enabled in the current control group. - - \sa disableMessages(), pushGroup(), popGroup() -*/ -void QOpenGLDebugLogger::enableMessages(const QVector<GLuint> &ids, - QOpenGLDebugMessage::Sources sources, - QOpenGLDebugMessage::Types types) -{ - Q_D(QOpenGLDebugLogger); - d->controlDebugMessages(sources, - types, - QOpenGLDebugMessage::AnySeverity, - ids, - QByteArrayLiteral("enableMessages"), - true); -} - -/*! - Disables the logging of messages with the given \a sources, of the given \a - types and with the given \a severities and any message id. - - The logging will be disabled in the current control group. - - \sa enableMessages(), pushGroup(), popGroup() -*/ -void QOpenGLDebugLogger::disableMessages(QOpenGLDebugMessage::Sources sources, - QOpenGLDebugMessage::Types types, - QOpenGLDebugMessage::Severities severities) -{ - Q_D(QOpenGLDebugLogger); - d->controlDebugMessages(sources, - types, - severities, - QVector<GLuint>(), - QByteArrayLiteral("disableMessages"), - false); -} - -/*! - Disables the logging of messages with the given \a ids, from the given \a - sources and of the given \a types and any severity. - - The logging will be disabled in the current control group. - - \sa enableMessages(), pushGroup(), popGroup() -*/ -void QOpenGLDebugLogger::disableMessages(const QVector<GLuint> &ids, - QOpenGLDebugMessage::Sources sources, - QOpenGLDebugMessage::Types types) -{ - Q_D(QOpenGLDebugLogger); - d->controlDebugMessages(sources, - types, - QOpenGLDebugMessage::AnySeverity, - ids, - QByteArrayLiteral("disableMessages"), - false); -} - -/*! - Reads all the available messages in the OpenGL internal debug log and - returns them. Moreover, this function will clear the internal debug log, - so that subsequent invocations will not return messages that were - already returned. - - \sa startLogging() -*/ -QList<QOpenGLDebugMessage> QOpenGLDebugLogger::loggedMessages() const -{ - Q_D(const QOpenGLDebugLogger); - if (!d->initialized) { - qWarning("QOpenGLDebugLogger::loggedMessages(): object must be initialized before reading logged messages"); - return QList<QOpenGLDebugMessage>(); - } - - static const GLuint maxMessageCount = 128; - GLuint messagesRead; - GLenum messageSources[maxMessageCount]; - GLenum messageTypes[maxMessageCount]; - GLuint messageIds[maxMessageCount]; - GLenum messageSeverities[maxMessageCount]; - GLsizei messageLengths[maxMessageCount]; - - QByteArray messagesBuffer; - messagesBuffer.resize(maxMessageCount * d->maxMessageLength); - - QList<QOpenGLDebugMessage> messages; - do { - messagesRead = d->glGetDebugMessageLog(maxMessageCount, - GLsizei(messagesBuffer.size()), - messageSources, - messageTypes, - messageIds, - messageSeverities, - messageLengths, - messagesBuffer.data()); - - const char *messagesBufferPtr = messagesBuffer.constData(); - for (GLuint i = 0; i < messagesRead; ++i) { - QOpenGLDebugMessage message; - - QOpenGLDebugMessagePrivate *messagePrivate = message.d.data(); - messagePrivate->source = qt_messageSourceFromGL(messageSources[i]); - messagePrivate->type = qt_messageTypeFromGL(messageTypes[i]); - messagePrivate->id = messageIds[i]; - messagePrivate->severity = qt_messageSeverityFromGL(messageSeverities[i]); - messagePrivate->message = QString::fromUtf8(messagesBufferPtr, messageLengths[i] - 1); - - messagesBufferPtr += messageLengths[i]; - messages << message; - } - } while (messagesRead == maxMessageCount); - - return messages; -} - -/*! - \fn void QOpenGLDebugLogger::messageLogged(const QOpenGLDebugMessage &debugMessage) - - This signal is emitted when a debug message (wrapped by the \a debugMessage - argument) is logged from the OpenGL server. - - Depending on the OpenGL implementation, this signal can be emitted - from other threads than the one(s) the receiver(s) lives in, and even - different from the thread the QOpenGLContext in which this object has - been initialized lives in. Moreover, the signal could be emitted from - multiple threads at the same time. This is normally not a problem, - as Qt will utilize a queued connection for cross-thread signal emissions, - but if you force the connection type to Direct then you must be aware of - the potential races in the slots connected to this signal. - - If logging have been started in SynchronousLogging mode, OpenGL guarantees - that this signal will be emitted from the same thread the QOpenGLContext - has been bound to, and no concurrent invocations will ever happen. - - \note Logging must have been started, or this signal will not be emitted. - - \sa startLogging() -*/ - -/*! - Returns the maximum supported length, in bytes, for the text of the messages - passed to logMessage(). This is also the maximum length of a debug group - name, as pushing or popping groups will automatically log a message with - the debug group name as the message text. - - If a message text is too long, it will be automatically truncated by - QOpenGLDebugLogger. - - \note Message texts are encoded in UTF-8 when they get passed to OpenGL, so - their size in bytes does not usually match the amount of UTF-16 code units, - as returned, for instance, by QString::length(). (It does if the message contains - 7-bit ASCII only data, which is typical for debug messages.) -*/ -qint64 QOpenGLDebugLogger::maximumMessageLength() const -{ - Q_D(const QOpenGLDebugLogger); - if (!d->initialized) { - qWarning("QOpenGLDebugLogger::maximumMessageLength(): object must be initialized before reading the maximum message length"); - return -1; - } - return d->maxMessageLength; -} - - -QT_END_NAMESPACE - -#include "moc_qopengldebug.cpp" diff --git a/src/gui/opengl/qopengldebug.h b/src/gui/opengl/qopengldebug.h deleted file mode 100644 index 7363985d60..0000000000 --- a/src/gui/opengl/qopengldebug.h +++ /dev/null @@ -1,221 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QOPENGLDEBUG_H -#define QOPENGLDEBUG_H - -#include <QtGui/qtguiglobal.h> - -#ifndef QT_NO_OPENGL - -#include <QtCore/qshareddata.h> -#include <QtCore/qflags.h> -#include <QtCore/qlist.h> -#include <QtCore/qvector.h> -#include <QtCore/qmetatype.h> -#include <QtCore/qdebug.h> -#include <QtGui/qopenglcontext.h> - -#if defined(Q_CLANG_QDOC) -#undef GLuint -typedef unsigned int GLuint; -#endif - -QT_BEGIN_NAMESPACE - -class QOpenGLDebugLogger; -class QOpenGLDebugLoggerPrivate; -class QOpenGLDebugMessagePrivate; - -class Q_GUI_EXPORT QOpenGLDebugMessage -{ -public: - enum Source { - InvalidSource = 0x00000000, - APISource = 0x00000001, - WindowSystemSource = 0x00000002, - ShaderCompilerSource = 0x00000004, - ThirdPartySource = 0x00000008, - ApplicationSource = 0x00000010, - OtherSource = 0x00000020, - LastSource = OtherSource, // private API - AnySource = 0xffffffff - }; - Q_DECLARE_FLAGS(Sources, Source) - - enum Type { - InvalidType = 0x00000000, - ErrorType = 0x00000001, - DeprecatedBehaviorType = 0x00000002, - UndefinedBehaviorType = 0x00000004, - PortabilityType = 0x00000008, - PerformanceType = 0x00000010, - OtherType = 0x00000020, - MarkerType = 0x00000040, - GroupPushType = 0x00000080, - GroupPopType = 0x00000100, - LastType = GroupPopType, // private API - AnyType = 0xffffffff - }; - Q_DECLARE_FLAGS(Types, Type) - - enum Severity { - InvalidSeverity = 0x00000000, - HighSeverity = 0x00000001, - MediumSeverity = 0x00000002, - LowSeverity = 0x00000004, - NotificationSeverity = 0x00000008, - LastSeverity = NotificationSeverity, // private API - AnySeverity = 0xffffffff - }; - Q_DECLARE_FLAGS(Severities, Severity) - - QOpenGLDebugMessage(); - QOpenGLDebugMessage(const QOpenGLDebugMessage &debugMessage); - - QOpenGLDebugMessage &operator=(const QOpenGLDebugMessage &debugMessage); - QOpenGLDebugMessage &operator=(QOpenGLDebugMessage &&other) noexcept { swap(other); return *this; } - ~QOpenGLDebugMessage(); - - void swap(QOpenGLDebugMessage &other) noexcept { qSwap(d, other.d); } - - Source source() const; - Type type() const; - Severity severity() const; - GLuint id() const; - QString message() const; - - static QOpenGLDebugMessage createApplicationMessage(const QString &text, - GLuint id = 0, - Severity severity = NotificationSeverity, - Type type = OtherType); - static QOpenGLDebugMessage createThirdPartyMessage(const QString &text, - GLuint id = 0, - Severity severity = NotificationSeverity, - Type type = OtherType); - - bool operator==(const QOpenGLDebugMessage &debugMessage) const; - inline bool operator!=(const QOpenGLDebugMessage &debugMessage) const { return !operator==(debugMessage); } - -private: - friend class QOpenGLDebugLogger; - friend class QOpenGLDebugLoggerPrivate; - QSharedDataPointer<QOpenGLDebugMessagePrivate> d; -}; - -Q_DECLARE_SHARED(QOpenGLDebugMessage) -Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLDebugMessage::Sources) -Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLDebugMessage::Types) -Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLDebugMessage::Severities) - -#ifndef QT_NO_DEBUG_STREAM -Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QOpenGLDebugMessage &message); -Q_GUI_EXPORT QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Source source); -Q_GUI_EXPORT QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Type type); -Q_GUI_EXPORT QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Severity severity); -#endif - -class QOpenGLDebugLoggerPrivate; - -class Q_GUI_EXPORT QOpenGLDebugLogger : public QObject -{ - Q_OBJECT - Q_PROPERTY(LoggingMode loggingMode READ loggingMode) - -public: - enum LoggingMode { - AsynchronousLogging, - SynchronousLogging - }; - Q_ENUM(LoggingMode) - - explicit QOpenGLDebugLogger(QObject *parent = nullptr); - ~QOpenGLDebugLogger(); - - bool initialize(); - - bool isLogging() const; - LoggingMode loggingMode() const; - - qint64 maximumMessageLength() const; - - void pushGroup(const QString &name, - GLuint id = 0, - QOpenGLDebugMessage::Source source = QOpenGLDebugMessage::ApplicationSource); - void popGroup(); - - void enableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, - QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, - QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity); - - void enableMessages(const QVector<GLuint> &ids, - QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, - QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType); - - void disableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, - QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, - QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity); - - void disableMessages(const QVector<GLuint> &ids, - QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, - QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType); - - QList<QOpenGLDebugMessage> loggedMessages() const; - -public Q_SLOTS: - void logMessage(const QOpenGLDebugMessage &debugMessage); - void startLogging(LoggingMode loggingMode = AsynchronousLogging); - void stopLogging(); - -Q_SIGNALS: - void messageLogged(const QOpenGLDebugMessage &debugMessage); - -private: - Q_DISABLE_COPY(QOpenGLDebugLogger) - Q_DECLARE_PRIVATE(QOpenGLDebugLogger) - Q_PRIVATE_SLOT(d_func(), void _q_contextAboutToBeDestroyed()) -}; - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QOpenGLDebugMessage) - -#endif // QT_NO_OPENGL - -#endif // QOPENGLDEBUG_H diff --git a/src/gui/opengl/qopenglqueryhelper_p.h b/src/gui/opengl/qopenglqueryhelper_p.h deleted file mode 100644 index ad91ca9f96..0000000000 --- a/src/gui/opengl/qopenglqueryhelper_p.h +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QOPENGLQUERYHELPER_P_H -#define QOPENGLQUERYHELPER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtGui/private/qtguiglobal_p.h> - -#if !defined(QT_OPENGL_ES_2) - -#include <QtGui/QOpenGLContext> - -QT_BEGIN_NAMESPACE - -// Helper class used by QOpenGLTimerQuery and later will be used by -// QOpenGLOcclusionQuery -class QOpenGLQueryHelper -{ -public: - QOpenGLQueryHelper(QOpenGLContext *context) - : GetQueryObjectuiv(nullptr), - GetQueryObjectiv(nullptr), - GetQueryiv(nullptr), - EndQuery(nullptr), - BeginQuery(nullptr), - IsQuery(nullptr), - DeleteQueries(nullptr), - GenQueries(nullptr), - GetInteger64v(nullptr), - GetQueryObjectui64v(nullptr), - GetQueryObjecti64v(nullptr), - QueryCounter(nullptr) - { - Q_ASSERT(context); - - // Core in OpenGL >=1.5 - GetQueryObjectuiv = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLuint *)>(context->getProcAddress("glGetQueryObjectuiv")); - GetQueryObjectiv = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint *)>(context->getProcAddress("glGetQueryObjectiv")); - GetQueryiv = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLenum , GLint *)>(context->getProcAddress("glGetQueryiv")); - EndQuery = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum )>(context->getProcAddress("glEndQuery")); - BeginQuery = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLuint )>(context->getProcAddress("glBeginQuery")); - IsQuery = reinterpret_cast<GLboolean (QOPENGLF_APIENTRYP)(GLuint )>(context->getProcAddress("glIsQuery")); - DeleteQueries = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , const GLuint *)>(context->getProcAddress("glDeleteQueries")); - GenQueries = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , GLuint *)>(context->getProcAddress("glGenQueries")); - - // Core in OpenGL >=3.2 - GetInteger64v = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint64 *)>(context->getProcAddress("glGetInteger64v")); - - // Core in OpenGL >=3.3 / ARB_timer_query - GetQueryObjectui64v = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLuint64 *)>(context->getProcAddress("glGetQueryObjectui64v")); - GetQueryObjecti64v = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint64 *)>(context->getProcAddress("glGetQueryObjecti64v")); - QueryCounter = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum )>(context->getProcAddress("glQueryCounter")); - } - - inline void glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) - { - GetQueryObjectuiv(id, pname, params); - } - - inline void glGetQueryObjectiv(GLuint id, GLenum pname, GLint *params) - { - GetQueryObjectiv(id, pname, params); - } - - inline void glGetQueryiv(GLenum target, GLenum pname, GLint *params) - { - GetQueryiv(target, pname, params); - } - - inline void glEndQuery(GLenum target) - { - EndQuery(target); - } - - inline void glBeginQuery(GLenum target, GLuint id) - { - BeginQuery(target, id); - } - - inline GLboolean glIsQuery(GLuint id) - { - return IsQuery(id); - } - - inline void glDeleteQueries(GLsizei n, const GLuint *ids) - { - DeleteQueries(n, ids); - } - - inline void glGenQueries(GLsizei n, GLuint *ids) - { - GenQueries(n, ids); - } - - inline void glGetInteger64v(GLenum pname, GLint64 *params) - { - GetInteger64v(pname, params); - } - - inline void glGetQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params) - { - GetQueryObjectui64v(id, pname, params); - } - - inline void glGetQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params) - { - GetQueryObjecti64v(id, pname, params); - } - - inline void glQueryCounter(GLuint id, GLenum target) - { - QueryCounter(id, target); - } - -private: - // Core in OpenGL >=1.5 - void (QOPENGLF_APIENTRYP GetQueryObjectuiv)(GLuint id, GLenum pname, GLuint *params); - void (QOPENGLF_APIENTRYP GetQueryObjectiv)(GLuint id, GLenum pname, GLint *params); - void (QOPENGLF_APIENTRYP GetQueryiv)(GLenum target, GLenum pname, GLint *params); - void (QOPENGLF_APIENTRYP EndQuery)(GLenum target); - void (QOPENGLF_APIENTRYP BeginQuery)(GLenum target, GLuint id); - GLboolean (QOPENGLF_APIENTRYP IsQuery)(GLuint id); - void (QOPENGLF_APIENTRYP DeleteQueries)(GLsizei n, const GLuint *ids); - void (QOPENGLF_APIENTRYP GenQueries)(GLsizei n, GLuint *ids); - - // Core in OpenGL >=3.2 - void (QOPENGLF_APIENTRYP GetInteger64v)(GLenum pname, GLint64 *params); - - // Core in OpenGL >=3.3 and provided by ARB_timer_query - void (QOPENGLF_APIENTRYP GetQueryObjectui64v)(GLuint id, GLenum pname, GLuint64 *params); - void (QOPENGLF_APIENTRYP GetQueryObjecti64v)(GLuint id, GLenum pname, GLint64 *params); - void (QOPENGLF_APIENTRYP QueryCounter)(GLuint id, GLenum target); -}; - -QT_END_NAMESPACE - -#endif - -#endif // QOPENGLQUERYHELPER_P_H diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp index cf4a8dee8d..fd282e3ba0 100644 --- a/src/gui/opengl/qopengltexture.cpp +++ b/src/gui/opengl/qopengltexture.cpp @@ -4612,7 +4612,7 @@ QOpenGLTexture::WrapMode QOpenGLTexture::wrapMode(QOpenGLTexture::CoordinateDire \note This function has no effect on Mac and Qt built for OpenGL ES 2. \sa borderColor() */ -void QOpenGLTexture::setBorderColor(QColor color) +void QOpenGLTexture::setBorderColor(const QColor &color) { setBorderColor(static_cast<float>(color.redF()), static_cast<float>(color.greenF()), static_cast<float>(color.blueF()), static_cast<float>(color.alphaF())); diff --git a/src/gui/opengl/qopengltexture.h b/src/gui/opengl/qopengltexture.h index 7d984babc8..539b6aa7b2 100644 --- a/src/gui/opengl/qopengltexture.h +++ b/src/gui/opengl/qopengltexture.h @@ -621,7 +621,7 @@ public: void setWrapMode(CoordinateDirection direction, WrapMode mode); WrapMode wrapMode(CoordinateDirection direction) const; - void setBorderColor(QColor color); + void setBorderColor(const QColor &color); void setBorderColor(float r, float g, float b, float a); void setBorderColor(int r, int g, int b, int a); void setBorderColor(uint r, uint g, uint b, uint a); diff --git a/src/gui/opengl/qopengltimerquery.cpp b/src/gui/opengl/qopengltimerquery.cpp deleted file mode 100644 index a4e10b42f7..0000000000 --- a/src/gui/opengl/qopengltimerquery.cpp +++ /dev/null @@ -1,880 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qopengltimerquery.h" - -#include "qopenglqueryhelper_p.h" -#include <QtCore/private/qobject_p.h> -#include <QtGui/QOpenGLContext> -#include <QtGui/QOpenGLFunctions> - -QT_BEGIN_NAMESPACE - -// Helper class used as fallback if OpenGL <3.3 is being used with EXT_timer_query -class QExtTimerQueryHelper -{ -public: - QExtTimerQueryHelper(QOpenGLContext *context) - { - Q_ASSERT(context); - GetQueryObjectui64vEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLuint64EXT *)>(context->getProcAddress("glGetQueryObjectui64vEXT")); - GetQueryObjecti64vEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint64EXT *)>(context->getProcAddress("glGetQueryObjecti64vEXT")); - } - - inline void glGetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params) - { - GetQueryObjectui64vEXT(id, pname, params); - } - - inline void glGetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params) - { - GetQueryObjecti64vEXT(id, pname, params); - } - -private: - void (QOPENGLF_APIENTRYP GetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLuint64EXT *params); - void (QOPENGLF_APIENTRYP GetQueryObjecti64vEXT)(GLuint id, GLenum pname, GLint64EXT *params); -}; - -class QOpenGLTimerQueryPrivate : public QObjectPrivate -{ -public: - QOpenGLTimerQueryPrivate() - : QObjectPrivate(), - context(nullptr), - ext(nullptr), - timeInterval(0), - timer(0) - { - } - - ~QOpenGLTimerQueryPrivate() - { - delete core; - delete ext; - } - - bool create(); - void destroy(); - void begin(); - void end(); - GLuint64 waitForTimeStamp() const; - void recordTimestamp(); - bool isResultAvailable() const; - GLuint64 result() const; - - // There are several cases we must handle: - // OpenGL >=3.3 includes timer queries as a core feature - // ARB_timer_query has same functionality as above. Requires OpenGL 3.2 - // EXT_timer_query offers limited support. Can be used with OpenGL >=1.5 - // - // Note that some implementations (OS X) provide OpenGL 3.2 but do not expose the - // ARB_timer_query extension. In such situations we must also be able to handle - // using the EXT_timer_query extension with any version of OpenGL. - // - // OpenGL 1.5 or above contains the generic query API and OpenGL 3.3 and - // ARB_timer_query provide the 64-bit query API. These are wrapped by - // QOpenGLQueryHelper. All we need to handle in addition is the EXT_timer_query - // case and to take care not to call the Core/ARB functions when we only - // have EXT_timer_query available. - QOpenGLContext *context; - QOpenGLQueryHelper *core; - QExtTimerQueryHelper *ext; - mutable GLuint64 timeInterval; - GLuint timer; -}; - -bool QOpenGLTimerQueryPrivate::create() -{ - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - - if (timer && context == ctx) - return true; - - context = ctx; - if (!context) { - qWarning("A current OpenGL context is required to create timer query objects"); - return false; - } - - if (context->isOpenGLES()) { - qWarning("QOpenGLTimerQuery: Not supported on OpenGL ES"); - return false; - } - - // Resolve the functions provided by OpenGL 1.5 and OpenGL 3.3 or ARB_timer_query - core = new QOpenGLQueryHelper(context); - - // Check to see if we also need to resolve the functions for EXT_timer_query - QSurfaceFormat f = context->format(); - if (f.version() <= qMakePair<int, int>(3, 2) - && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query")) - && context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) { - ext = new QExtTimerQueryHelper(context); - } else if (f.version() <= qMakePair<int, int>(3, 2) - && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query")) - && !context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) { - qWarning("QOpenGLTimerQuery requires one of:\n" - " OpenGL 3.3 or newer,\n" - " OpenGL 3.2 and the ARB_timer_query extension\n" - " or the EXT_timer query extension"); - return false; - } - - core->glGenQueries(1, &timer); - return (timer != 0); -} - -void QOpenGLTimerQueryPrivate::destroy() -{ - if (!timer) - return; - - core->glDeleteQueries(1, &timer); - timer = 0; - context = nullptr; -} - -// GL_TIME_ELAPSED_EXT is not defined on OS X 10.6 -#if !defined(GL_TIME_ELAPSED_EXT) -#define GL_TIME_ELAPSED_EXT 0x88BF -#endif - -// GL_TIME_ELAPSED is not defined on OS X 10.7 or 10.8 yet -#if !defined(GL_TIME_ELAPSED) -#define GL_TIME_ELAPSED GL_TIME_ELAPSED_EXT -#endif - -void QOpenGLTimerQueryPrivate::begin() -{ - core->glBeginQuery(GL_TIME_ELAPSED, timer); -} - -void QOpenGLTimerQueryPrivate::end() -{ - core->glEndQuery(GL_TIME_ELAPSED); -} - -void QOpenGLTimerQueryPrivate::recordTimestamp() -{ - // Don't call glQueryCounter if we only have EXT_timer_query -#if defined(GL_TIMESTAMP) - if (!ext) - core->glQueryCounter(timer, GL_TIMESTAMP); - else - qWarning("QOpenGLTimerQuery::recordTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query"); -#else - qWarning("QOpenGLTimerQuery::recordTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query"); -#endif -} - -GLuint64 QOpenGLTimerQueryPrivate::waitForTimeStamp() const -{ - GLint64 tmp = 0; -#if defined(GL_TIMESTAMP) - if (!ext) - core->glGetInteger64v(GL_TIMESTAMP, &tmp); - else - qWarning("QOpenGLTimerQuery::waitForTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query"); -#else - qWarning("QOpenGLTimerQuery::waitForTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query"); -#endif - GLuint64 timestamp(tmp); - return timestamp; -} - -bool QOpenGLTimerQueryPrivate::isResultAvailable() const -{ - GLuint available = GL_FALSE; - core->glGetQueryObjectuiv(timer, GL_QUERY_RESULT_AVAILABLE, &available); - return available; -} - -GLuint64 QOpenGLTimerQueryPrivate::result() const -{ - if (!ext) - core->glGetQueryObjectui64v(timer, GL_QUERY_RESULT, &timeInterval); - else - ext->glGetQueryObjectui64vEXT(timer, GL_QUERY_RESULT, &timeInterval); - return timeInterval; -} - -/*! - \class QOpenGLTimerQuery - \brief The QOpenGLTimerQuery class wraps an OpenGL timer query object. - \inmodule QtGui - \since 5.1 - \ingroup painting-3D - - OpenGL timer query objects are OpenGL managed resources to measure the - execution times of sequences of OpenGL commands on the GPU. - - OpenGL offers various levels of support for timer queries, depending on - the version of OpenGL you have and the presence of the ARB_timer_query or - EXT_timer_query extensions. The support can be summarized as: - - \list - \li OpenGL >=3.3 offers full support for all timer query functionality. - \li OpenGL 3.2 with the ARB_timer_query extension offers full support - for all timer query functionality. - \li OpenGL <=3.2 with the EXT_timer_query extension offers limited support - in that the timestamp of the GPU cannot be queried. Places where this - impacts functions provided by Qt classes will be highlighted in the - function documentation. - \li OpenGL ES 2 (and OpenGL ES 3) do not provide any support for OpenGL - timer queries. - \endlist - - OpenGL represents time with a granularity of 1 nanosecond (1e-9 seconds). As a - consequence of this, 32-bit integers would only give a total possible duration - of approximately 4 seconds, which would not be difficult to exceed in poorly - performing or lengthy operations. OpenGL therefore uses 64 bit integer types - to represent times. A GLuint64 variable has enough width to contain a duration - of hundreds of years, which is plenty for real-time rendering needs. - - As with the other Qt OpenGL classes, QOpenGLTimerQuery has a create() - function to create the underlying OpenGL object. This is to allow the developer to - ensure that there is a valid current OpenGL context at the time. - - Once created, timer queries can be issued in one of several ways. The simplest - method is to delimit a block of commands with calls to begin() and end(). This - instructs OpenGL to measure the time taken from completing all commands issued - prior to begin() until the completion of all commands issued prior to end(). - - At the end of a frame we can retrieve the results by calling waitForResult(). - As this function's name implies, it blocks CPU execution until OpenGL notifies - that the timer query result is available. To avoid blocking, you can check - if the query result is available by calling isResultAvailable(). Note that - modern GPUs are deeply pipelined and query results may not become available for - between 1-5 frames after they were issued. - - Note that OpenGL does not permit nesting or interleaving of multiple timer queries - using begin() and end(). Using multiple timer queries and recordTimestamp() avoids - this limitation. When using recordTimestamp() the result can be obtained at - some later time using isResultAvailable() and waitForResult(). Qt provides the - convenience class QOpenGLTimeMonitor that helps with using multiple query objects. - - \sa QOpenGLTimeMonitor -*/ - -/*! - Creates a QOpenGLTimerQuery instance with the given \a parent. You must call create() - with a valid OpenGL context before using. -*/ -QOpenGLTimerQuery::QOpenGLTimerQuery(QObject *parent) - : QObject(*new QOpenGLTimerQueryPrivate, parent) -{ -} - -/*! - Destroys the QOpenGLTimerQuery and the underlying OpenGL resource. -*/ -QOpenGLTimerQuery::~QOpenGLTimerQuery() -{ - QOpenGLContext* ctx = QOpenGLContext::currentContext(); - - Q_D(QOpenGLTimerQuery); - QOpenGLContext *oldContext = nullptr; - if (d->context != ctx) { - oldContext = ctx; - if (d->context->makeCurrent(oldContext->surface())) { - ctx = d->context; - } else { - qWarning("QOpenGLTimerQuery::~QOpenGLTimerQuery() failed to make query objects's context current"); - ctx = nullptr; - } - } - - if (ctx) - destroy(); - - if (oldContext) { - if (!oldContext->makeCurrent(oldContext->surface())) - qWarning("QOpenGLTimerQuery::~QOpenGLTimerQuery() failed to restore current context"); - } -} - -/*! - Creates the underlying OpenGL timer query object. There must be a valid OpenGL context - that supports query objects current for this function to succeed. - - Returns \c true if the OpenGL timer query object was successfully created. -*/ -bool QOpenGLTimerQuery::create() -{ - Q_D(QOpenGLTimerQuery); - return d->create(); -} - -/*! - Destroys the underlying OpenGL timer query object. The context that was current when - create() was called must be current when calling this function. -*/ -void QOpenGLTimerQuery::destroy() -{ - Q_D(QOpenGLTimerQuery); - d->destroy(); -} - -/*! - Returns \c true if the underlying OpenGL query object has been created. If this - returns \c true and the associated OpenGL context is current, then you are able to issue - queries with this object. -*/ -bool QOpenGLTimerQuery::isCreated() const -{ - Q_D(const QOpenGLTimerQuery); - return (d->timer != 0); -} - -/*! - Returns the id of the underlying OpenGL query object. -*/ -GLuint QOpenGLTimerQuery::objectId() const -{ - Q_D(const QOpenGLTimerQuery); - return d->timer; -} - -/*! - Marks the start point in the OpenGL command queue for a sequence of commands to - be timed by this query object. - - This is useful for simple use-cases. Usually it is better to use recordTimestamp(). - - \sa end(), isResultAvailable(), waitForResult(), recordTimestamp() -*/ -void QOpenGLTimerQuery::begin() -{ - Q_D(QOpenGLTimerQuery); - d->begin(); -} - -/*! - Marks the end point in the OpenGL command queue for a sequence of commands to - be timed by this query object. - - This is useful for simple use-cases. Usually it is better to use recordTimestamp(). - - \sa begin(), isResultAvailable(), waitForResult(), recordTimestamp() -*/ -void QOpenGLTimerQuery::end() -{ - Q_D(QOpenGLTimerQuery); - d->end(); -} - -/*! - Places a marker in the OpenGL command queue for the GPU to record the timestamp - when this marker is reached by the GPU. This function is non-blocking and the - result will become available at some later time. - - The availability of the result can be checked with isResultAvailable(). The result - can be fetched with waitForResult() which will block if the result is not yet - available. - - \sa waitForResult(), isResultAvailable(), begin(), end() -*/ -void QOpenGLTimerQuery::recordTimestamp() -{ - Q_D(QOpenGLTimerQuery); - return d->recordTimestamp(); -} - -/*! - Returns the current timestamp of the GPU when all previously issued OpenGL - commands have been received but not necessarily executed by the GPU. - - This function blocks until the result is returned. - - \sa recordTimestamp() -*/ -GLuint64 QOpenGLTimerQuery::waitForTimestamp() const -{ - Q_D(const QOpenGLTimerQuery); - return d->waitForTimeStamp(); -} - -/*! - Returns \c true if the OpenGL timer query result is available. - - This function is non-blocking and ideally should be used to check for the - availability of the query result before calling waitForResult(). - - \sa waitForResult() -*/ -bool QOpenGLTimerQuery::isResultAvailable() const -{ - Q_D(const QOpenGLTimerQuery); - return d->isResultAvailable(); -} - -/*! - Returns the result of the OpenGL timer query. - - This function will block until the result is made available by OpenGL. It is - recommended to call isResultAvailable() to ensure that the result is available - to avoid unnecessary blocking and stalling. - - \sa isResultAvailable() -*/ -GLuint64 QOpenGLTimerQuery::waitForResult() const -{ - Q_D(const QOpenGLTimerQuery); - return d->result(); -} - - -class QOpenGLTimeMonitorPrivate : public QObjectPrivate -{ -public: - QOpenGLTimeMonitorPrivate() - : QObjectPrivate(), - timers(), - timeSamples(), - context(nullptr), - core(nullptr), - ext(nullptr), - requestedSampleCount(2), - currentSample(-1), - timerQueryActive(false) - { - } - - ~QOpenGLTimeMonitorPrivate() - { - delete core; - delete ext; - } - - bool create(); - void destroy(); - void recordSample(); - bool isResultAvailable() const; - QVector<GLuint64> samples() const; - QVector<GLuint64> intervals() const; - void reset(); - - QVector<GLuint> timers; - mutable QVector<GLuint64> timeSamples; - - QOpenGLContext *context; - QOpenGLQueryHelper *core; - QExtTimerQueryHelper *ext; - - int requestedSampleCount; - int currentSample; - mutable bool timerQueryActive; -}; - -bool QOpenGLTimeMonitorPrivate::create() -{ - if (!timers.isEmpty() && timers.at(0) != 0 && timers.size() == requestedSampleCount) - return true; - - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - if (context && context != ctx) { - qWarning("QTimeMonitor: Attempting to use different OpenGL context to recreate timers.\n" - "Please call destroy() first or use the same context to previously create"); - return false; - } - - context = ctx; - if (!context) { - qWarning("A current OpenGL context is required to create timer query objects"); - return false; - } - - // Resize the vectors that hold the timers and the recorded samples - timers.resize(requestedSampleCount); - timeSamples.resize(requestedSampleCount); - - // Resolve the functions provided by OpenGL 1.5 and OpenGL 3.3 or ARB_timer_query - core = new QOpenGLQueryHelper(context); - - // Check to see if we also need to resolve the functions for EXT_timer_query - QSurfaceFormat f = context->format(); - if (f.version() <= qMakePair<int, int>(3, 2) - && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query")) - && context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) { - ext = new QExtTimerQueryHelper(context); - } else if (f.version() <= qMakePair<int, int>(3, 2) - && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query")) - && !context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) { - qWarning("QOpenGLTimeMonitor requires one of:\n" - " OpenGL 3.3 or newer,\n" - " OpenGL 3.2 and the ARB_timer_query extension\n" - " or the EXT_timer query extension"); - return false; - } - - core->glGenQueries(requestedSampleCount, timers.data()); - return (timers.at(0) != 0); -} - -void QOpenGLTimeMonitorPrivate::destroy() -{ - if (timers.isEmpty() || timers.at(0) == 0) - return; - - core->glDeleteQueries(timers.size(), timers.data()); - timers.clear(); - delete core; - core = nullptr; - delete ext; - ext = nullptr; - context = nullptr; -} - -void QOpenGLTimeMonitorPrivate::recordSample() -{ - // Use glQueryCounter() and GL_TIMESTAMP where available. - // Otherwise, simulate it with glBeginQuery()/glEndQuery() - if (!ext) { -#if defined(GL_TIMESTAMP) - core->glQueryCounter(timers.at(++currentSample), GL_TIMESTAMP); -#endif - } else { - if (currentSample == -1) { - core->glBeginQuery(GL_TIME_ELAPSED_EXT, timers.at(++currentSample)); - timerQueryActive = true; - } else if (currentSample < timers.size() - 1) { - core->glEndQuery(GL_TIME_ELAPSED_EXT); - core->glBeginQuery(GL_TIME_ELAPSED_EXT, timers.at(++currentSample)); - } else { - if (timerQueryActive) { - core->glEndQuery(GL_TIME_ELAPSED_EXT); - timerQueryActive = false; - } - } - } -} - -bool QOpenGLTimeMonitorPrivate::isResultAvailable() const -{ - // The OpenGL spec says that if a query result is ready then the results of all queries - // of the same type issued before it must also be ready. Therefore we only need to check - // the availability of the result for the last issued query - GLuint available = GL_FALSE; - core->glGetQueryObjectuiv(timers.at(currentSample), GL_QUERY_RESULT_AVAILABLE, &available); - return available; -} - -QVector<GLuint64> QOpenGLTimeMonitorPrivate::samples() const -{ - // For the Core and ARB options just ask for the timestamp for each timer query. - // For the EXT implementation we cannot obtain timestamps so we defer any result - // collection to the intervals() function - if (!ext) { - for (int i = 0; i <= currentSample; ++i) - core->glGetQueryObjectui64v(timers.at(i), GL_QUERY_RESULT, &timeSamples[i]); - } else { - qWarning("QOpenGLTimeMonitor::samples() requires OpenGL >=3.3\n" - "or OpenGL 3.2 and GL_ARB_timer_query"); - } - return timeSamples; -} - -QVector<GLuint64> QOpenGLTimeMonitorPrivate::intervals() const -{ - QVector<GLuint64> intervals(timers.size() - 1); - if (!ext) { - // Obtain the timestamp samples and calculate the interval durations - const QVector<GLuint64> timeStamps = samples(); - for (int i = 0; i < intervals.size(); ++i) - intervals[i] = timeStamps[i+1] - timeStamps[i]; - } else { - // Stop the last timer if needed - if (timerQueryActive) { - core->glEndQuery(GL_TIME_ELAPSED_EXT); - timerQueryActive = false; - } - - // Obtain the results from all timers apart from the redundant last one. In this - // case the results actually are the intervals not timestamps - for (int i = 0; i < currentSample; ++i) - ext->glGetQueryObjectui64vEXT(timers.at(i), GL_QUERY_RESULT, &intervals[i]); - } - - return intervals; -} - -void QOpenGLTimeMonitorPrivate::reset() -{ - currentSample = -1; - timeSamples.fill(0); -} - - -/*! - \class QOpenGLTimeMonitor - \brief The QOpenGLTimeMonitor class wraps a sequence of OpenGL timer query objects. - \inmodule QtGui - \since 5.1 - \ingroup painting-3D - - The QOpenGLTimeMonitor class is a convenience wrapper around a collection of OpenGL - timer query objects used to measure intervals of time on the GPU to the level of - granularity required by your rendering application. - - The OpenGL timer queries objects are queried in sequence to record the GPU - timestamps at positions of interest in your rendering code. Once the results for - all issues timer queries become available, the results can be fetched and - QOpenGLTimerMonitor will calculate the recorded time intervals for you. - - The typical use case of this class is to either profile your application's rendering - algorithms or to adjust those algorithms in real-time for dynamic performance/quality - balancing. - - Prior to using QOpenGLTimeMonitor in your rendering function you should set the - required number of sample points that you wish to record by calling setSamples(). Note - that measuring N sample points will produce N-1 time intervals. Once you have set the - number of sample points, call the create() function with a valid current OpenGL context - to create the necessary query timer objects. These steps are usually performed just - once in an initialization function. - - Use the recordSample() function to delimit blocks of code containing OpenGL commands - that you wish to time. You can check availability of the resulting time - samples and time intervals with isResultAvailable(). The calculated time intervals and - the raw timestamp samples can be retrieved with the blocking waitForIntervals() and - waitForSamples() functions respectively. - - After retrieving the results and before starting a new round of taking samples - (for example, in the next frame) be sure to call the reset() function which will clear - the cached results and reset the timer index back to the first timer object. - - \sa QOpenGLTimerQuery -*/ - -/*! - Creates a QOpenGLTimeMonitor instance with the given \a parent. You must call create() - with a valid OpenGL context before using. - - \sa setSampleCount(), create() -*/ -QOpenGLTimeMonitor::QOpenGLTimeMonitor(QObject *parent) - : QObject(*new QOpenGLTimeMonitorPrivate, parent) -{ -} - -/*! - Destroys the QOpenGLTimeMonitor and any underlying OpenGL resources. -*/ -QOpenGLTimeMonitor::~QOpenGLTimeMonitor() -{ - QOpenGLContext* ctx = QOpenGLContext::currentContext(); - - Q_D(QOpenGLTimeMonitor); - QOpenGLContext *oldContext = nullptr; - if (d->context != ctx) { - oldContext = ctx; - if (d->context->makeCurrent(oldContext->surface())) { - ctx = d->context; - } else { - qWarning("QOpenGLTimeMonitor::~QOpenGLTimeMonitor() failed to make time monitor's context current"); - ctx = nullptr; - } - } - - if (ctx) - destroy(); - - if (oldContext) { - if (!oldContext->makeCurrent(oldContext->surface())) - qWarning("QOpenGLTimeMonitor::~QOpenGLTimeMonitor() failed to restore current context"); - } -} - -/*! - Sets the number of sample points to \a sampleCount. After setting the number - of samples with this function, you must call create() to instantiate the underlying - OpenGL timer query objects. - - The new \a sampleCount must be at least 2. - - \sa sampleCount(), create(), recordSample() -*/ -void QOpenGLTimeMonitor::setSampleCount(int sampleCount) -{ - // We need at least 2 samples to get an interval - if (sampleCount < 2) - return; - Q_D(QOpenGLTimeMonitor); - d->requestedSampleCount = sampleCount; -} - -/*! - Returns the number of sample points that have been requested with - setSampleCount(). If create was successfully called following setSampleCount(), - then the value returned will be the actual number of sample points - that can be used. - - The default value for sample count is 2, leading to the measurement of a - single interval. - - \sa setSampleCount() -*/ -int QOpenGLTimeMonitor::sampleCount() const -{ - Q_D(const QOpenGLTimeMonitor); - return d->requestedSampleCount; -} - -/*! - Instantiate sampleCount() OpenGL timer query objects that will be used - to track the amount of time taken to execute OpenGL commands between - successive calls to recordSample(). - - Returns \c true if the OpenGL timer query objects could be created. - - \sa destroy(), setSampleCount(), recordSample() -*/ -bool QOpenGLTimeMonitor::create() -{ - Q_D(QOpenGLTimeMonitor); - return d->create(); -} - -/*! - Destroys any OpenGL timer query objects used within this instance. - - \sa create() -*/ -void QOpenGLTimeMonitor::destroy() -{ - Q_D(QOpenGLTimeMonitor); - d->destroy(); -} - -/*! - Returns \c true if the underlying OpenGL query objects have been created. If this - returns \c true and the associated OpenGL context is current, then you are able to record - time samples with this object. -*/ -bool QOpenGLTimeMonitor::isCreated() const -{ - Q_D(const QOpenGLTimeMonitor); - return (!d->timers.isEmpty() && d->timers.at(0) != 0); -} - -/*! - Returns a QVector containing the object Ids of the OpenGL timer query objects. -*/ -QVector<GLuint> QOpenGLTimeMonitor::objectIds() const -{ - Q_D(const QOpenGLTimeMonitor); - return d->timers; -} - -/*! - Issues an OpenGL timer query at this point in the OpenGL command queue. Calling this - function in a sequence in your application's rendering function, will build up - details of the GPU time taken to execute the OpenGL commands between successive - calls to this function. - - \sa setSampleCount(), isResultAvailable(), waitForSamples(), waitForIntervals() -*/ -int QOpenGLTimeMonitor::recordSample() -{ - Q_D(QOpenGLTimeMonitor); - d->recordSample(); - return d->currentSample; -} - -/*! - Returns \c true if the OpenGL timer query results are available. - - \sa waitForSamples(), waitForIntervals() -*/ -bool QOpenGLTimeMonitor::isResultAvailable() const -{ - Q_D(const QOpenGLTimeMonitor); - return d->isResultAvailable(); -} - -/*! - Returns a QVector containing the GPU timestamps taken with recordSample(). - - This function will block until OpenGL indicates the results are available. It - is recommended to check the availability of the result prior to calling this - function with isResultAvailable(). - - \note This function only works on systems that have OpenGL >=3.3 or the - ARB_timer_query extension. See QOpenGLTimerQuery for more details. - - \sa waitForIntervals(), isResultAvailable() -*/ -QVector<GLuint64> QOpenGLTimeMonitor::waitForSamples() const -{ - Q_D(const QOpenGLTimeMonitor); - return d->samples(); -} - -/*! - Returns a QVector containing the time intervals delimited by the calls to - recordSample(). The resulting vector will contain one fewer element as - this represents the intervening intervals rather than the actual timestamp - samples. - - This function will block until OpenGL indicates the results are available. It - is recommended to check the availability of the result prior to calling this - function with isResultAvailable(). - - \sa waitForSamples(), isResultAvailable() -*/ -QVector<GLuint64> QOpenGLTimeMonitor::waitForIntervals() const -{ - Q_D(const QOpenGLTimeMonitor); - return d->intervals(); -} - -/*! - Resets the time monitor ready for use in another frame of rendering. Call - this once you have obtained the previous results and before calling - recordSample() for the first time on the next frame. - - \sa recordSample() -*/ -void QOpenGLTimeMonitor::reset() -{ - Q_D(QOpenGLTimeMonitor); - d->reset(); -} - -QT_END_NAMESPACE diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index 8780cce223..c567b25468 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -855,18 +855,6 @@ QColor::QColor(Spec spec) noexcept */ /*! - Returns the name of the color in the format "#RRGGBB"; i.e. a "#" - character followed by three two-digit hexadecimal numbers. - - \sa setNamedColor() -*/ - -QString QColor::name() const -{ - return name(HexRgb); -} - -/*! \since 5.2 Returns the name of the color in the specified \a format. @@ -1086,6 +1074,7 @@ void QColor::setHsvF(qreal h, qreal s, qreal v, qreal a) || (v < qreal(0.0) || v > qreal(1.0)) || (a < qreal(0.0) || a > qreal(1.0))) { qWarning("QColor::setHsvF: HSV parameters out of range"); + invalidate(); return; } @@ -1198,7 +1187,8 @@ void QColor::setHslF(qreal h, qreal s, qreal l, qreal a) || (s < qreal(0.0) || s > qreal(1.0)) || (l < qreal(0.0) || l > qreal(1.0)) || (a < qreal(0.0) || a > qreal(1.0))) { - qWarning("QColor::setHsvF: HSV parameters out of range"); + qWarning("QColor::setHslF: HSL parameters out of range"); + invalidate(); return; } @@ -1224,7 +1214,7 @@ void QColor::setHslF(qreal h, qreal s, qreal l, qreal a) void QColor::setHsl(int h, int s, int l, int a) { if (h < -1 || (uint)s > 255 || (uint)l > 255 || (uint)a > 255) { - qWarning("QColor::setHsv: HSV parameters out of range"); + qWarning("QColor::setHsl: HSL parameters out of range"); invalidate(); return; } @@ -2626,16 +2616,6 @@ QColor QColor::fromHslF(qreal h, qreal s, qreal l, qreal a) } /*! - \obsolete - - Use the \c const overload instead. -*/ -void QColor::getCmyk(int *c, int *m, int *y, int *k, int *a) -{ - const_cast<const QColor *>(this)->getCmyk(c, m, y, k, a); -} - -/*! Sets the contents pointed to by \a c, \a m, \a y, \a k, and \a a, to the cyan, magenta, yellow, black, and alpha-channel (transparency) components of the color's CMYK value. @@ -2665,16 +2645,6 @@ void QColor::getCmyk(int *c, int *m, int *y, int *k, int *a) const } /*! - \obsolete - - Use the \c const overload instead. -*/ -void QColor::getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a) -{ - const_cast<const QColor *>(this)->getCmykF(c, m, y, k, a); -} - -/*! Sets the contents pointed to by \a c, \a m, \a y, \a k, and \a a, to the cyan, magenta, yellow, black, and alpha-channel (transparency) components of the color's CMYK value. @@ -2719,6 +2689,7 @@ void QColor::setCmyk(int c, int m, int y, int k, int a) || k < 0 || k > 255 || a < 0 || a > 255) { qWarning("QColor::setCmyk: CMYK parameters out of range"); + invalidate(); return; } @@ -2748,6 +2719,7 @@ void QColor::setCmykF(qreal c, qreal m, qreal y, qreal k, qreal a) || k < qreal(0.0) || k > qreal(1.0) || a < qreal(0.0) || a > qreal(1.0)) { qWarning("QColor::setCmykF: CMYK parameters out of range"); + invalidate(); return; } @@ -2920,18 +2892,6 @@ QColor QColor::dark(int factor) const noexcept } #endif -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) -/*! - Assigns a copy of \a color to this color, and returns a reference to it. -*/ -QColor &QColor::operator=(const QColor &color) noexcept -{ - cspec = color.cspec; - ct.argb = color.ct.argb; - return *this; -} -#endif - /*! \overload Assigns a copy of \a color and returns a reference to this color. */ diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h index f0d7dd23ad..423a0ac50f 100644 --- a/src/gui/painting/qcolor.h +++ b/src/gui/painting/qcolor.h @@ -46,6 +46,8 @@ #include <QtCore/qstringlist.h> #include <QtGui/qrgba64.h> +#include <limits.h> + QT_BEGIN_NAMESPACE @@ -87,24 +89,11 @@ public: inline QColor(QLatin1String name); QColor(Spec spec) noexcept; -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) - // ### Qt 6: remove all of these, the trivial ones are fine. - Q_DECL_CONSTEXPR QColor(const QColor &color) noexcept - : cspec(color.cspec), ct(color.ct) - {} - Q_DECL_CONSTEXPR QColor(QColor &&other) noexcept : cspec(other.cspec), ct(other.ct) {} - QColor &operator=(QColor &&other) noexcept - { cspec = other.cspec; ct = other.ct; return *this; } - QColor &operator=(const QColor &) noexcept; -#endif // Qt < 6 - QColor &operator=(Qt::GlobalColor color) noexcept; bool isValid() const noexcept; - // ### Qt 6: merge overloads - QString name() const; - QString name(NameFormat format) const; + QString name(NameFormat format = HexRgb) const; #if QT_STRINGVIEW_LEVEL < 2 void setNamedColor(const QString& name); @@ -180,11 +169,9 @@ public: qreal yellowF() const noexcept; qreal blackF() const noexcept; - void getCmyk(int *c, int *m, int *y, int *k, int *a = nullptr); // ### Qt 6: remove void getCmyk(int *c, int *m, int *y, int *k, int *a = nullptr) const; void setCmyk(int c, int m, int y, int k, int a = 255); - void getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a = nullptr); // ### Qt 6: remove void getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a = nullptr) const; void setCmykF(qreal c, qreal m, qreal y, qreal k, qreal a = 1.0); diff --git a/src/gui/painting/qdrawhelper_ssse3.cpp b/src/gui/painting/qdrawhelper_ssse3.cpp index 14d7047bb6..a175b591dd 100644 --- a/src/gui/painting/qdrawhelper_ssse3.cpp +++ b/src/gui/painting/qdrawhelper_ssse3.cpp @@ -197,7 +197,7 @@ void qt_memfill24_ssse3(quint24 *dest, quint24 color, qsizetype count) quint24 *end = dest + count; constexpr uchar x = 2, y = 1, z = 0; - Q_DECL_ALIGN(__m128i) static const uchar + alignas(__m128i) static const uchar shuffleMask[16 + 1] = { x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y }; __m128i mval1 = _mm_shuffle_epi8(m, _mm_load_si128(reinterpret_cast<const __m128i *>(shuffleMask))); diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h index 80b092f177..63e6b48e4f 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -49,7 +49,6 @@ QT_BEGIN_NAMESPACE class QStringList; -template <class T> class QList; struct QFontDef; class QFontEngine; diff --git a/src/gui/text/qfontengine_qpf2.cpp b/src/gui/text/qfontengine_qpf2.cpp index e00f9d058c..d636bca510 100644 --- a/src/gui/text/qfontengine_qpf2.cpp +++ b/src/gui/text/qfontengine_qpf2.cpp @@ -168,7 +168,7 @@ const QFontEngineQPF2::Glyph *QFontEngineQPF2::findGlyph(glyph_t g) const bool QFontEngineQPF2::verifyHeader(const uchar *data, int size) { - VERIFY(quintptr(data) % Q_ALIGNOF(Header) == 0); + VERIFY(quintptr(data) % alignof(Header) == 0); VERIFY(size >= int(sizeof(Header))); const Header *header = reinterpret_cast<const Header *>(data); if (header->magic[0] != 'Q' diff --git a/src/gui/text/qtextoption.h b/src/gui/text/qtextoption.h index 8b57278633..a90d73dc43 100644 --- a/src/gui/text/qtextoption.h +++ b/src/gui/text/qtextoption.h @@ -48,8 +48,6 @@ QT_BEGIN_NAMESPACE - -template <typename T> class QList; struct QTextOptionPrivate; class Q_GUI_EXPORT QTextOption diff --git a/src/gui/util/qgridlayoutengine.cpp b/src/gui/util/qgridlayoutengine.cpp index 4af5e47f8f..2b81d34848 100644 --- a/src/gui/util/qgridlayoutengine.cpp +++ b/src/gui/util/qgridlayoutengine.cpp @@ -960,7 +960,7 @@ void QGridLayoutEngine::insertItem(QGridLayoutItem *item, int index) { maybeExpandGrid(item->lastRow(), item->lastColumn()); - if (index == -1) + if (index < 0 || index >= q_items.size()) q_items.append(item); else q_items.insert(index, item); diff --git a/src/gui/util/qtexturefiledata.cpp b/src/gui/util/qtexturefiledata.cpp index 41cbd1b15a..3c8130c229 100644 --- a/src/gui/util/qtexturefiledata.cpp +++ b/src/gui/util/qtexturefiledata.cpp @@ -38,11 +38,7 @@ ****************************************************************************/ #include "qtexturefiledata_p.h" -#include <QMetaEnum> #include <QSize> -#if QT_CONFIG(opengl) -#include <QOpenGLTexture> -#endif QT_BEGIN_NAMESPACE @@ -247,13 +243,7 @@ void QTextureFileData::setLogName(const QByteArray &name) static QByteArray glFormatName(quint32 fmt) { - const char *id = nullptr; -#if QT_CONFIG(opengl) - id = QMetaEnum::fromType<QOpenGLTexture::TextureFormat>().valueToKey(fmt); -#endif - QByteArray res(id ? id : "(?)"); - res += " [0x" + QByteArray::number(fmt, 16).rightJustified(4, '0') + ']'; - return res; + return QByteArray("0x" + QByteArray::number(fmt, 16).rightJustified(4, '0')); } QDebug operator<<(QDebug dbg, const QTextureFileData &d) |