diff options
841 files changed, 30818 insertions, 11228 deletions
@@ -75,6 +75,7 @@ my @modules_to_sync ; $force_relative = 1 if ( -d "/System/Library/Frameworks" ); my $out_basedir = $basedir; $out_basedir =~ s=\\=/=g; +my $quoted_basedir = "\Q$basedir"; # functions ---------------------------------------------------------- @@ -350,11 +351,9 @@ sub syncHeader { ###################################################################### sub fixPaths { my ($file, $dir) = @_; - $dir =~ s=^$basedir/=$out_basedir/= if(!($basedir eq $out_basedir)); + $dir =~ s=^$quoted_basedir/=$out_basedir/= if(!($basedir eq $out_basedir)); $file =~ s=\\=/=g; - $file =~ s/\+/\\+/g; $dir =~ s=\\=/=g; - $dir =~ s/\+/\\+/g; #setup my $ret = $file; @@ -378,7 +377,7 @@ sub fixPaths { my $slash = index($file_dir, "/", $i); last if($slash == -1); my $tmp = substr($file_dir, 0, $slash); - last unless($dir =~ m,^$tmp/,); + last unless($dir =~ m,^\Q$tmp\E/,); $match_dir = $tmp; $i = $slash; } @@ -389,7 +388,7 @@ sub fixPaths { for(my $i = 0; $i < $count; $i++) { $dots .= "../"; } - $ret =~ s,^$match_dir,$dots,; + $ret =~ s,^\Q$match_dir\E,$dots,; } $ret =~ s,/+,/,g; return $ret; @@ -507,13 +506,13 @@ sub symlinkFile if ($isunix) { print "symlink created for $file " unless $quiet; - if ( $force_relative && ($ifile =~ /^$basedir/)) { + if ( $force_relative && ($ifile =~ /^$quoted_basedir/)) { my $t = getcwd(); my $c = -1; my $p = "../"; - $t =~ s-^$basedir/--; + $t =~ s-^$quoted_basedir/--; $p .= "../" while( ($c = index( $t, "/", $c + 1)) != -1 ); - $file =~ s-^$basedir/-$p-; + $file =~ s-^$quoted_basedir/-$p-; print " ($file)\n" unless $quiet; } print "\n" unless $quiet; @@ -835,7 +834,7 @@ foreach my $lib (@modules_to_sync) { @headers = ( "$out_basedir/include/$lib/$header" ); # write forwarding headers to include/Qt - if ($lib ne "phonon" && $subdir =~ /^$basedir\/src/) { + if ($lib ne "phonon" && $subdir =~ /^$quoted_basedir\/src/) { my $file_name = "$out_basedir/include/Qt/$header"; my $file_op = '>'; my $header_content = ''; diff --git a/config.tests/x11/glxfbconfig/glxfbconfig.pro b/config.tests/x11/glxfbconfig/glxfbconfig.pro index 4705ca6..65f855a 100644 --- a/config.tests/x11/glxfbconfig/glxfbconfig.pro +++ b/config.tests/x11/glxfbconfig/glxfbconfig.pro @@ -7,4 +7,4 @@ for(p, QMAKE_LIBDIR_OPENGL) { } CONFIG -= qt -LIBS += -lGL -lGLU +LIBS += -lGL diff --git a/config.tests/x11/opengl/opengl.cpp b/config.tests/x11/opengl/opengl.cpp index 3802365..6c1815d 100644 --- a/config.tests/x11/opengl/opengl.cpp +++ b/config.tests/x11/opengl/opengl.cpp @@ -40,11 +40,6 @@ ****************************************************************************/ #include <GL/gl.h> -#include <GL/glu.h> - -#ifndef GLU_VERSION_1_2 -# error "Required GLU version 1.2 not found." -#endif int main(int, char **) { diff --git a/config.tests/x11/opengl/opengl.pro b/config.tests/x11/opengl/opengl.pro index 5fd41d3..5c3a1c5 100644 --- a/config.tests/x11/opengl/opengl.pro +++ b/config.tests/x11/opengl/opengl.pro @@ -8,4 +8,4 @@ for(p, QMAKE_LIBDIR_OPENGL) { CONFIG -= qt win32-g++*:LIBS += -lopengl32 -else:LIBS += -lGL -lGLU +else:LIBS += -lGL diff --git a/demos/affine/main.cpp b/demos/affine/main.cpp index 85da546..e14dc6b 100644 --- a/demos/affine/main.cpp +++ b/demos/affine/main.cpp @@ -53,7 +53,7 @@ int main(int argc, char **argv) QStyle *arthurStyle = new ArthurStyle(); xformWidget.setStyle(arthurStyle); - QList<QWidget *> widgets = qFindChildren<QWidget *>(&xformWidget); + QList<QWidget *> widgets = xformWidget.findChildren<QWidget *>(); foreach (QWidget *w, widgets) { w->setStyle(arthurStyle); w->setAttribute(Qt::WA_AcceptTouchEvents); diff --git a/demos/boxes/glbuffers.cpp b/demos/boxes/glbuffers.cpp index 694d05b..84ab26c 100644 --- a/demos/boxes/glbuffers.cpp +++ b/demos/boxes/glbuffers.cpp @@ -42,6 +42,16 @@ #include "glbuffers.h" #include <QtGui/qmatrix4x4.h> + +void qgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) +{ + const GLdouble ymax = zNear * tan(fovy * M_PI / 360.0); + const GLdouble ymin = -ymax; + const GLdouble xmin = ymin * aspect; + const GLdouble xmax = ymax * aspect; + glFrustum(xmin, xmax, ymin, ymax, zNear, zFar); +} + //============================================================================// // GLTexture // //============================================================================// diff --git a/demos/boxes/glbuffers.h b/demos/boxes/glbuffers.h index 67a4ea6..8c1e209 100644 --- a/demos/boxes/glbuffers.h +++ b/demos/boxes/glbuffers.h @@ -58,6 +58,8 @@ if (m_failed || !(assertion)) { returnStatement; \ } +void qgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar); + QT_BEGIN_NAMESPACE class QMatrix4x4; QT_END_NAMESPACE diff --git a/demos/boxes/qtbox.cpp b/demos/boxes/qtbox.cpp index 3aaf985..e3a5978 100644 --- a/demos/boxes/qtbox.cpp +++ b/demos/boxes/qtbox.cpp @@ -324,7 +324,7 @@ void QtBox::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWi glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadMatrixf(moveToRectMatrix); - gluPerspective(60.0, 1.0, 0.01, 10.0); + qgluPerspective(60.0, 1.0, 0.01, 10.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); diff --git a/demos/boxes/scene.cpp b/demos/boxes/scene.cpp index 97953f2..d65af22 100644 --- a/demos/boxes/scene.cpp +++ b/demos/boxes/scene.cpp @@ -922,7 +922,7 @@ void Scene::drawBackground(QPainter *painter, const QRectF &) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); - gluPerspective(60.0, width / height, 0.01, 15.0); + qgluPerspective(60.0, width / height, 0.01, 15.0); glMatrixMode(GL_MODELVIEW); diff --git a/demos/browser/browserapplication.cpp b/demos/browser/browserapplication.cpp index ed95d32..633307c 100644 --- a/demos/browser/browserapplication.cpp +++ b/demos/browser/browserapplication.cpp @@ -231,14 +231,14 @@ void BrowserApplication::loadSettings() QString standardFontFamily = defaultSettings->fontFamily(QWebSettings::StandardFont); int standardFontSize = defaultSettings->fontSize(QWebSettings::DefaultFontSize); QFont standardFont = QFont(standardFontFamily, standardFontSize); - standardFont = qVariantValue<QFont>(settings.value(QLatin1String("standardFont"), standardFont)); + standardFont = qvariant_cast<QFont>(settings.value(QLatin1String("standardFont"), standardFont)); defaultSettings->setFontFamily(QWebSettings::StandardFont, standardFont.family()); defaultSettings->setFontSize(QWebSettings::DefaultFontSize, standardFont.pointSize()); QString fixedFontFamily = defaultSettings->fontFamily(QWebSettings::FixedFont); int fixedFontSize = defaultSettings->fontSize(QWebSettings::DefaultFixedFontSize); QFont fixedFont = QFont(fixedFontFamily, fixedFontSize); - fixedFont = qVariantValue<QFont>(settings.value(QLatin1String("fixedFont"), fixedFont)); + fixedFont = qvariant_cast<QFont>(settings.value(QLatin1String("fixedFont"), fixedFont)); defaultSettings->setFontFamily(QWebSettings::FixedFont, fixedFont.family()); defaultSettings->setFontSize(QWebSettings::DefaultFixedFontSize, fixedFont.pointSize()); diff --git a/demos/browser/cookiejar.cpp b/demos/browser/cookiejar.cpp index 835b61b..d318e3a 100644 --- a/demos/browser/cookiejar.cpp +++ b/demos/browser/cookiejar.cpp @@ -186,7 +186,7 @@ void CookieJar::save() if (cookies.at(i).isSessionCookie()) cookies.removeAt(i); } - cookieSettings.setValue(QLatin1String("cookies"), qVariantFromValue<QList<QNetworkCookie> >(cookies)); + cookieSettings.setValue(QLatin1String("cookies"), QVariant::fromValue<QList<QNetworkCookie> >(cookies)); cookieSettings.beginGroup(QLatin1String("Exceptions")); cookieSettings.setValue(QLatin1String("block"), m_exceptions_block); cookieSettings.setValue(QLatin1String("allow"), m_exceptions_allow); diff --git a/demos/browser/settings.cpp b/demos/browser/settings.cpp index fba781b..6e9bc2c 100644 --- a/demos/browser/settings.cpp +++ b/demos/browser/settings.cpp @@ -121,8 +121,8 @@ void SettingsDialog::loadFromSettings() // Appearance settings.beginGroup(QLatin1String("websettings")); - fixedFont = qVariantValue<QFont>(settings.value(QLatin1String("fixedFont"), fixedFont)); - standardFont = qVariantValue<QFont>(settings.value(QLatin1String("standardFont"), standardFont)); + fixedFont = qvariant_cast<QFont>(settings.value(QLatin1String("fixedFont"), fixedFont)); + standardFont = qvariant_cast<QFont>(settings.value(QLatin1String("standardFont"), standardFont)); standardLabel->setText(QString(QLatin1String("%1 %2")).arg(standardFont.family()).arg(standardFont.pointSize())); fixedLabel->setText(QString(QLatin1String("%1 %2")).arg(fixedFont.family()).arg(fixedFont.pointSize())); diff --git a/demos/composition/main.cpp b/demos/composition/main.cpp index aa8c139..a528dff 100644 --- a/demos/composition/main.cpp +++ b/demos/composition/main.cpp @@ -59,7 +59,7 @@ int main(int argc, char **argv) QStyle *arthurStyle = new ArthurStyle(); compWidget.setStyle(arthurStyle); - QList<QWidget *> widgets = qFindChildren<QWidget *>(&compWidget); + QList<QWidget *> widgets = compWidget.findChildren<QWidget *>(); foreach (QWidget *w, widgets) w->setStyle(arthurStyle); compWidget.show(); diff --git a/demos/declarative/snake/content/Link.qml b/demos/declarative/snake/content/Link.qml index 942008d..b5538df 100644 --- a/demos/declarative/snake/content/Link.qml +++ b/demos/declarative/snake/content/Link.qml @@ -77,7 +77,12 @@ Item { id:link id: actualImageRotation origin.x: width/2; origin.y: height/2; angle: rotation * 90 - Behavior on angle { NumberAnimation { duration: spawned ? 200 : 0} } + Behavior on angle { + RotationAnimation{ + direction: RotationAnimation.Shortest + duration: spawned ? 200 : 0 + } + } } } diff --git a/demos/declarative/snake/content/snake.js b/demos/declarative/snake/content/snake.js index c2e9d3a..2a99aa8 100644 --- a/demos/declarative/snake/content/snake.js +++ b/demos/declarative/snake/content/snake.js @@ -22,20 +22,26 @@ function rand(n) function scheduleDirection(dir) { - direction = dir; - if(scheduledDirections[scheduledDirections.length-1]!=direction) - scheduledDirections.push(direction); + if (state == "starting") { + direction = dir; + headDirection = direction; + head.rotation = headDirection; + } else if (state == "running"){ + direction = dir; + if(scheduledDirections[scheduledDirections.length-1]!=direction) + scheduledDirections.push(direction); + } } function startNewGame() { - if (state == "starting") + if (state == "starting") { return; + } if (heartbeat.running) { endGame(); startNewGameTimer.running = true; - state = ""; return; } diff --git a/demos/declarative/snake/snake.qml b/demos/declarative/snake/snake.qml index 4d989df..df6e3ab 100644 --- a/demos/declarative/snake/snake.qml +++ b/demos/declarative/snake/snake.qml @@ -86,7 +86,7 @@ Rectangle { onTriggered: { Logic.moveSkull() } } Timer { - id: startNewGameTimer; + id: startNewGameTimer; interval: 700; onTriggered: { Logic.startNewGame(); } } @@ -94,11 +94,11 @@ Rectangle { Timer { id: startHeartbeatTimer; interval: 1000 ; - onTriggered: { state = "running"; heartbeat.running = true; } + onTriggered: { state = "running"; heartbeat.running = true;} } - Image { + Image { id: title source: "content/pics/snake.jpg" @@ -107,14 +107,28 @@ Rectangle { anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter - Text { - color: "white" - font.pointSize: 24 - horizontalAlignment: Text.AlignHCenter - text: "Last Score:\t" + lastScore + "\nHighscore:\t" + highScores.topScore; - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.bottom - anchors.bottomMargin: gridSize + Column { + spacing: 140 + anchors.verticalCenter: parent.verticalCenter; + anchors.left: parent.left; + anchors.right: parent.right; + + Text { + color: "white" + font.pointSize: 48 + font.italic: true; + font.bold: true; + text: "Snake" + anchors.horizontalCenter: parent.horizontalCenter; + } + + Text { + color: "white" + font.pointSize: 24 + anchors.horizontalCenter: parent.horizontalCenter; + //horizontalAlignment: Text.AlignHCenter + text: "Last Score:\t" + lastScore + "\nHighscore:\t" + highScores.topScore; + } } } @@ -144,7 +158,7 @@ Rectangle { MouseArea { anchors.fill: parent onPressed: { - if (!head || !heartbeat.running) { + if (screen.state == "") { Logic.startNewGame(); return; } @@ -235,10 +249,12 @@ Rectangle { from: "*" to: "starting" NumberAnimation { target: progressIndicator; property: "width"; duration: 1000 } - NumberAnimation { target: title; property: "opacity"; duration: 500 } + NumberAnimation { property: "opacity"; duration: 200 } }, Transition { - NumberAnimation { target: title; property: "opacity"; duration: 500 } + to: "starting" + NumberAnimation { target: progressIndicator; property: "width"; duration: 1000 } + NumberAnimation { property: "opacity"; duration: 200 } } ] diff --git a/demos/deform/main.cpp b/demos/deform/main.cpp index bef075a..c5491b3 100644 --- a/demos/deform/main.cpp +++ b/demos/deform/main.cpp @@ -56,7 +56,7 @@ int main(int argc, char **argv) QStyle *arthurStyle = new ArthurStyle(); deformWidget.setStyle(arthurStyle); - QList<QWidget *> widgets = qFindChildren<QWidget *>(&deformWidget); + QList<QWidget *> widgets = deformWidget.findChildren<QWidget *>(); foreach (QWidget *w, widgets) w->setStyle(arthurStyle); diff --git a/demos/deform/pathdeform.cpp b/demos/deform/pathdeform.cpp index 636d103..d6ac19e 100644 --- a/demos/deform/pathdeform.cpp +++ b/demos/deform/pathdeform.cpp @@ -297,7 +297,7 @@ void PathDeformWidget::setStyle( QStyle * style ) { m_controls->setStyle(style); - QList<QWidget *> widgets = qFindChildren<QWidget *>(m_controls); + QList<QWidget *> widgets = m_controls->findChildren<QWidget *>(); foreach (QWidget *w, widgets) w->setStyle(style); } diff --git a/demos/embeddeddialogs/customproxy.cpp b/demos/embeddeddialogs/customproxy.cpp index bd56f5a..a715f5e 100644 --- a/demos/embeddeddialogs/customproxy.cpp +++ b/demos/embeddeddialogs/customproxy.cpp @@ -113,7 +113,7 @@ QVariant CustomProxy::itemChange(GraphicsItemChange change, const QVariant &valu { if (change == ItemChildAddedChange || change == ItemChildRemovedChange) { if (change == ItemChildAddedChange) { - currentPopup = qVariantValue<QGraphicsItem *>(value); + currentPopup = qvariant_cast<QGraphicsItem *>(value); currentPopup->setCacheMode(ItemCoordinateCache); if (scene()) currentPopup->installSceneEventFilter(this); diff --git a/demos/gradients/main.cpp b/demos/gradients/main.cpp index 8291e85..6678fa2 100644 --- a/demos/gradients/main.cpp +++ b/demos/gradients/main.cpp @@ -52,7 +52,7 @@ int main(int argc, char **argv) GradientWidget gradientWidget(0); QStyle *arthurStyle = new ArthurStyle(); gradientWidget.setStyle(arthurStyle); - QList<QWidget *> widgets = qFindChildren<QWidget *>(&gradientWidget); + QList<QWidget *> widgets = gradientWidget.findChildren<QWidget *>(); foreach (QWidget *w, widgets) { w->setStyle(arthurStyle); w->setAttribute(Qt::WA_AcceptTouchEvents); diff --git a/demos/interview/model.cpp b/demos/interview/model.cpp index 840bc60..88f200d 100644 --- a/demos/interview/model.cpp +++ b/demos/interview/model.cpp @@ -109,7 +109,7 @@ QVariant Model::headerData(int section, Qt::Orientation orientation, int role) c if (role == Qt::DisplayRole) return QString::number(section); if (role == Qt::DecorationRole) - return qVariantFromValue(services); + return QVariant::fromValue(services); return QAbstractItemModel::headerData(section, orientation, role); } diff --git a/demos/mainwindow/colorswatch.cpp b/demos/mainwindow/colorswatch.cpp index aab4f03..d4dbdca 100644 --- a/demos/mainwindow/colorswatch.cpp +++ b/demos/mainwindow/colorswatch.cpp @@ -454,7 +454,7 @@ void ColorSwatch::updateContextMenu() tabMenu->clear(); splitHMenu->clear(); splitVMenu->clear(); - QList<ColorSwatch*> dock_list = qFindChildren<ColorSwatch*>(mainWindow); + QList<ColorSwatch*> dock_list = mainWindow->findChildren<ColorSwatch*>(); foreach (ColorSwatch *dock, dock_list) { // if (!dock->isVisible() || dock->isFloating()) // continue; @@ -467,7 +467,7 @@ void ColorSwatch::updateContextMenu() void ColorSwatch::splitInto(QAction *action) { QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget()); - QList<ColorSwatch*> dock_list = qFindChildren<ColorSwatch*>(mainWindow); + QList<ColorSwatch*> dock_list = mainWindow->findChildren<ColorSwatch*>(); ColorSwatch *target = 0; foreach (ColorSwatch *dock, dock_list) { if (action->text() == dock->objectName()) { @@ -486,7 +486,7 @@ void ColorSwatch::splitInto(QAction *action) void ColorSwatch::tabInto(QAction *action) { QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget()); - QList<ColorSwatch*> dock_list = qFindChildren<ColorSwatch*>(mainWindow); + QList<ColorSwatch*> dock_list = mainWindow->findChildren<ColorSwatch*>(); ColorSwatch *target = 0; foreach (ColorSwatch *dock, dock_list) { if (action->text() == dock->objectName()) { diff --git a/demos/mainwindow/toolbar.cpp b/demos/mainwindow/toolbar.cpp index dd12419..a988d85 100644 --- a/demos/mainwindow/toolbar.cpp +++ b/demos/mainwindow/toolbar.cpp @@ -232,7 +232,7 @@ void ToolBar::updateMenu() void ToolBar::order() { QList<QAction *> ordered, actions1 = actions(), - actions2 = qFindChildren<QAction *>(this); + actions2 = findChildren<QAction *>(); while (!actions2.isEmpty()) { QAction *action = actions2.takeFirst(); if (!actions1.contains(action)) diff --git a/demos/pathstroke/main.cpp b/demos/pathstroke/main.cpp index 534b233..b10b2ea 100644 --- a/demos/pathstroke/main.cpp +++ b/demos/pathstroke/main.cpp @@ -53,7 +53,7 @@ int main(int argc, char **argv) PathStrokeWidget pathStrokeWidget(smallScreen); QStyle *arthurStyle = new ArthurStyle(); pathStrokeWidget.setStyle(arthurStyle); - QList<QWidget *> widgets = qFindChildren<QWidget *>(&pathStrokeWidget); + QList<QWidget *> widgets = pathStrokeWidget.findChildren<QWidget *>(); foreach (QWidget *w, widgets) { w->setStyle(arthurStyle); w->setAttribute(Qt::WA_AcceptTouchEvents); diff --git a/demos/pathstroke/pathstroke.cpp b/demos/pathstroke/pathstroke.cpp index 257d02a..308c540 100644 --- a/demos/pathstroke/pathstroke.cpp +++ b/demos/pathstroke/pathstroke.cpp @@ -382,7 +382,7 @@ void PathStrokeWidget::setStyle( QStyle * style ) { m_controls->setStyle(style); - QList<QWidget *> widgets = qFindChildren<QWidget *>(m_controls); + QList<QWidget *> widgets = m_controls->findChildren<QWidget *>(); foreach (QWidget *w, widgets) w->setStyle(style); } diff --git a/demos/shared/arthurstyle.cpp b/demos/shared/arthurstyle.cpp index 4be9079..3a2a2cb 100644 --- a/demos/shared/arthurstyle.cpp +++ b/demos/shared/arthurstyle.cpp @@ -394,7 +394,7 @@ int ArthurStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QWid void ArthurStyle::polish(QWidget *widget) { if (widget->layout() && qobject_cast<QGroupBox *>(widget)) { - if (qFindChildren<QGroupBox *>(widget).size() == 0) { + if (widget->findChildren<QGroupBox *>().size() == 0) { widget->layout()->setSpacing(0); widget->layout()->setMargin(12); } else { diff --git a/demos/shared/arthurwidgets.cpp b/demos/shared/arthurwidgets.cpp index 4182ff1..2eaf96b 100644 --- a/demos/shared/arthurwidgets.cpp +++ b/demos/shared/arthurwidgets.cpp @@ -313,7 +313,7 @@ void ArthurFrame::loadSourceFile(const QString &sourceFile) void ArthurFrame::showSource() { // Check for existing source - if (qFindChild<QTextBrowser *>(this)) + if (findChild<QTextBrowser *>()) return; QString contents; diff --git a/demos/spectrum/app/settingsdialog.cpp b/demos/spectrum/app/settingsdialog.cpp index b5e8459..1f125c9 100644 --- a/demos/spectrum/app/settingsdialog.cpp +++ b/demos/spectrum/app/settingsdialog.cpp @@ -65,13 +65,13 @@ SettingsDialog::SettingsDialog( QAudioDeviceInfo device; foreach (device, availableInputDevices) m_inputDeviceComboBox->addItem(device.deviceName(), - qVariantFromValue(device)); + QVariant::fromValue(device)); foreach (device, availableOutputDevices) m_outputDeviceComboBox->addItem(device.deviceName(), - qVariantFromValue(device)); + QVariant::fromValue(device)); - m_windowFunctionComboBox->addItem(tr("None"), qVariantFromValue(int(NoWindow))); - m_windowFunctionComboBox->addItem("Hann", qVariantFromValue(int(HannWindow))); + m_windowFunctionComboBox->addItem(tr("None"), QVariant::fromValue(int(NoWindow))); + m_windowFunctionComboBox->addItem("Hann", QVariant::fromValue(int(HannWindow))); m_windowFunctionComboBox->setCurrentIndex(m_windowFunction); // Initialize default devices diff --git a/demos/spreadsheet/spreadsheetitem.cpp b/demos/spreadsheet/spreadsheetitem.cpp index e1f0143..93c82a0 100644 --- a/demos/spreadsheet/spreadsheetitem.cpp +++ b/demos/spreadsheet/spreadsheetitem.cpp @@ -72,10 +72,10 @@ QVariant SpreadSheetItem::data(int role) const if (role == Qt::TextColorRole) { if (!isNumber) - return qVariantFromValue(QColor(Qt::black)); + return QVariant::fromValue(QColor(Qt::black)); else if (number < 0) - return qVariantFromValue(QColor(Qt::red)); - return qVariantFromValue(QColor(Qt::blue)); + return QVariant::fromValue(QColor(Qt::red)); + return QVariant::fromValue(QColor(Qt::blue)); } if (role == Qt::TextAlignmentRole) diff --git a/dist/changes-4.6.0 b/dist/changes-4.6.0 index 3e7d33b..2ebdc7c 100644 --- a/dist/changes-4.6.0 +++ b/dist/changes-4.6.0 @@ -177,7 +177,7 @@ QtCore * Many optimisations. * Added QVariant::toFloat() and QVariant::toReal(). * Added QVariant(float) constructor. - * qvariant_cast<QVariant> and qVariantFromValue<QVariant> are now + * qvariant_cast<QVariant> and QVariant::fromValue<QVariant> are now identity functions. * Added support for math3d types. diff --git a/dist/changes-4.8.0 b/dist/changes-4.8.0 new file mode 100644 index 0000000..0c28274 --- /dev/null +++ b/dist/changes-4.8.0 @@ -0,0 +1,139 @@ +Qt 4.8 introduces many new features and improvements as well as bugfixes +over the 4.7.x series. For more details, refer to the online documentation +included in this distribution. The documentation is also available online: + + http://qt.nokia.com/doc/4.8 + +The Qt version 4.8 series is binary compatible with the 4.7.x series. +Applications compiled for 4.7 will continue to run with 4.8. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt.nokia.com/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* General * +**************************************************************************** + +General Improvements +-------------------- + +- + +Third party components +---------------------- + + - Updated libpng to version x.y.z + + +**************************************************************************** +* Library * +**************************************************************************** + +QtCore +------ + - Removed support for QT_NO_THREAD define for QHostInfo. + +QtGui +----- + + - QTabBar: reduced minimumSizeHint if ElideMode is set. + + QtOpenGL + -------- + - Removed dependency of OpenGL Utility Library (GLU) + - Added QGLFunctions, which provides cross-platform access to the + OpenGL/ES 2.0 API. + + +**************************************************************************** +* Database Drivers * +**************************************************************************** + + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Qt for Linux/X11 +---------------- + + +Qt for Windows +-------------- + + +Qt for Mac OS X +--------------- + + +Qt for Embedded Linux +--------------------- + + +Qt for Windows CE +----------------- + + +**************************************************************************** +* Compiler Specific Changes * +**************************************************************************** + + +**************************************************************************** +* Tools * +**************************************************************************** + +- Build System + +- Assistant + + +- Designer + + +- Linguist + - Linguist GUI + + - lupdate + + - lrelease + + +- rcc + + +- moc + + +- uic + + +- uic3 + + +- qmake + + +- configure + + +- qtconfig + + +- qt3to4 + + +**************************************************************************** +* Plugins * +**************************************************************************** + + +**************************************************************************** +* Important Behavior Changes * +**************************************************************************** + diff --git a/doc/src/declarative/advtutorial.qdoc b/doc/src/declarative/advtutorial.qdoc index 1341bbb..4c97e1a 100644 --- a/doc/src/declarative/advtutorial.qdoc +++ b/doc/src/declarative/advtutorial.qdoc @@ -425,7 +425,7 @@ First we call \c sendHighScore() (explained in the section below) if it is possi Then, we use the \l{Offline Storage API} to maintain a persistant SQL database unique to this application. We create an offline storage database for the high scores using \c openDatabase() and prepare the data and SQL query that we want to use to save it. The offline storage API uses SQL queries for data manipulation and retrival, and in the \c db.transaction() call we use three SQL queries to initialize the database (if necessary), and then add to and retrieve high scores. To use the returned data, we turn it into a string with one line per row returned, and show a dialog containing that string. -This is one way of storing and displaying high scores locally, but certainly not the only way. A more complex alternative would be to create a high score dialog component, and pass it the results for processing and display (instead of reusing the \c Dialog). This would allow a more themeable dialog that could beter present the high scores. If your QML is the UI for a C++ application, you could also have passed the score to a C++ function to store it locally in a variety of ways, including a simple format without SQL or in another SQL database. +This is one way of storing and displaying high scores locally, but certainly not the only way. A more complex alternative would be to create a high score dialog component, and pass it the results for processing and display (instead of reusing the \c Dialog). This would allow a more themeable dialog that could better present the high scores. If your QML is the UI for a C++ application, you could also have passed the score to a C++ function to store it locally in a variety of ways, including a simple format without SQL or in another SQL database. \section3 Storing high scores online diff --git a/doc/src/declarative/example-slideswitch.qdoc b/doc/src/declarative/example-slideswitch.qdoc index 1a40f14..09b6006 100644 --- a/doc/src/declarative/example-slideswitch.qdoc +++ b/doc/src/declarative/example-slideswitch.qdoc @@ -35,7 +35,7 @@ The code for this example can be found in the \c $QTDIR/examples/declarative/ui- \section1 Overview -The elements that composed the switch are: +The elements that compose the switch are: \list \o a \c on property (the interface to interact with the switch), diff --git a/doc/src/declarative/extending.qdoc b/doc/src/declarative/extending.qdoc index 0cc989d..a1ffde0 100644 --- a/doc/src/declarative/extending.qdoc +++ b/doc/src/declarative/extending.qdoc @@ -124,7 +124,7 @@ The QML snippet shown above assigns a \c Person object to the \c BirthdayParty's QML can set properties of types that are more complex than basic intrinsics like integers and strings. Properties can also be object pointers, Qt interface -pointers, lists of object points, and lists of Qt interface pointers. As QML +pointers, lists of object pointers, and lists of Qt interface pointers. As QML is typesafe it ensures that only valid types are assigned to these properties, just like it does for primitive types. diff --git a/doc/src/development/qmake-manual.qdoc b/doc/src/development/qmake-manual.qdoc index f4becf8..b6b48bc 100644 --- a/doc/src/development/qmake-manual.qdoc +++ b/doc/src/development/qmake-manual.qdoc @@ -1385,12 +1385,16 @@ On the Symbian platform, generic PKG file content can also be specified with this variable. You can use either \c pkg_prerules or \c pkg_postrules to pass raw data to PKG file. The strings in \c pkg_prerules are added before - package-body and \c pkg_postrules after. The strings defined in - \c pkg_postrules or \c pkg_prerules are not parsed by qmake, so they - should be in a format understood by Symbian package generation tools. + package-body and \c pkg_postrules after. \c pkg_prerules is used for + defining vendor information, dependencies, custom package headers, and the + like, while \c pkg_postrules is used for custom file deployment and + embedded sis directives. + The strings defined in \c pkg_postrules or \c pkg_prerules are not parsed + by qmake, so they should be in a format understood by Symbian package + generation tools. Please consult the Symbian platform documentation for correct syntax. - For example, to deploy DLL and add a new dependency: + For example, to deploy DLL and add a new dependency: \snippet doc/src/snippets/code/doc_src_qmake-manual.qdoc 140 @@ -1406,13 +1410,28 @@ \o localized and unique vendor, for example \BR %{"Vendor-EN", ..., "Vendor-FR"} :"Unique vendor name" - \endlist + \endlist - If you decide to override any of these statements, you need to pay + If you decide to override any of these statements, you need to pay attention that also other statements stay valid. For example if you override languages statement, you must override also package-header statement and all other statements which are language specific. + On the Symbian platform, three separate PKG files are generated: + + \list + \o <app>_template.pkg - For application SIS file. Rules suffix: \c{.main} + \o <app>_installer.pkg - For smart installer SIS file. Rules suffix: \c{.installer} + \o <app>_stub.pkg - For ROM stubs. Rules suffix: \c{.stub} + \endlist + + \c pkg_prerules and \c pkg_postrules given without rules suffix will + intelligently apply to each of these files, but rules can also be + targeted to only one of above files by appending listed rules suffix + to the variable name: + + \snippet doc/src/snippets/code/doc_src_qmake-manual.qdoc 152 + On the Symbian platform, the \c default_deployment item specifies default platform and package dependencies. Those dependencies can be selectively disabled if alternative dependencies need to be defined diff --git a/doc/src/examples/customtype.qdoc b/doc/src/examples/customtype.qdoc index e003129..0765c5f 100644 --- a/doc/src/examples/customtype.qdoc +++ b/doc/src/examples/customtype.qdoc @@ -117,7 +117,7 @@ \snippet examples/tools/customtype/main.cpp storing a custom value - Alternatively, the qVariantFromValue() and qVariantSetValue() functions + Alternatively, the QVariant::fromValue() and qVariantSetValue() functions can be used if you are using a compiler without support for member template functions. diff --git a/doc/src/examples/multicastreceiver.qdoc b/doc/src/examples/multicastreceiver.qdoc new file mode 100644 index 0000000..f769705 --- /dev/null +++ b/doc/src/examples/multicastreceiver.qdoc @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in a +** written agreement between you and Nokia. +** +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of this +** file. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example network/multicastreceiver + \title Multicast Receiver Example + + The Multicast Receiever example shows how to receive information that is + sent to a multicast group. + + \image multicastreceiver-example.png +*/ diff --git a/doc/src/examples/multicastsender.qdoc b/doc/src/examples/multicastsender.qdoc new file mode 100644 index 0000000..271be60 --- /dev/null +++ b/doc/src/examples/multicastsender.qdoc @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in a +** written agreement between you and Nokia. +** +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of this +** file. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example network/multicastsender + \title Multicast Sender Example + + The Multicast Sender example shows how to send information to multiple + clients in a multicast group. + + \image multicastsender-example.png +*/ diff --git a/doc/src/getting-started/examples.qdoc b/doc/src/getting-started/examples.qdoc index e8c85e6..f849bf0 100644 --- a/doc/src/getting-started/examples.qdoc +++ b/doc/src/getting-started/examples.qdoc @@ -473,6 +473,8 @@ \o \l{network/bearercloud}{Bearer Cloud}\raisedaster \o \l{network/bearermonitor}{Bearer Monitor} \o \l{network/securesocketclient}{Secure Socket Client} + \o \l{network/multicastreceiver}{Multicast Receiver} + \o \l{network/multicastsender}{Multicast Sender} \endlist Examples marked with an asterisk (*) are fully documented. diff --git a/doc/src/images/multicastreceiver-example.png b/doc/src/images/multicastreceiver-example.png Binary files differnew file mode 100644 index 0000000..8de11cd --- /dev/null +++ b/doc/src/images/multicastreceiver-example.png diff --git a/doc/src/images/multicastsender-example.png b/doc/src/images/multicastsender-example.png Binary files differnew file mode 100644 index 0000000..a619b04 --- /dev/null +++ b/doc/src/images/multicastsender-example.png diff --git a/doc/src/network-programming/qtnetwork.qdoc b/doc/src/network-programming/qtnetwork.qdoc index dcee1b8..fce12a7 100644 --- a/doc/src/network-programming/qtnetwork.qdoc +++ b/doc/src/network-programming/qtnetwork.qdoc @@ -257,8 +257,13 @@ QUdpSocket::readDatagram() to read the datagram. The \l{network/broadcastsender}{Broadcast Sender} and - \l{network/broadcastreceiver}{Broadcast Receiver} examples show - how to write a UDP sender and a UDP receiver using Qt. + \l{network/broadcastreceiver}{Broadcast Receiver} examples show how to + write a UDP sender and a UDP receiver using Qt. + + QUdpSocket also supports multicasting. The + \l{network/multicastsender}{Multicast Sender} and + \l{network/multicastreceiver}{Multicast Receiver} examples show how to use + write UDP multicast clients. \section1 Resolving Host Names using QHostInfo diff --git a/doc/src/porting/porting4.qdoc b/doc/src/porting/porting4.qdoc index 7b80e13..69bf877 100644 --- a/doc/src/porting/porting4.qdoc +++ b/doc/src/porting/porting4.qdoc @@ -2374,8 +2374,8 @@ pointer to a QObjectList. See also the comments on QObjectList below. - Use QObject::findChildren() (or qFindChildren() if you need MSVC 6 - compatibility) instead of QObject::queryList(). For example: + Use QObject::findChildren() instead of QObject::queryList(). + For example: \snippet doc/src/snippets/code/doc_src_porting4.qdoc 18 diff --git a/doc/src/snippets/accessibilityslidersnippet.cpp b/doc/src/snippets/accessibilityslidersnippet.cpp index 466579d..05cbe40 100644 --- a/doc/src/snippets/accessibilityslidersnippet.cpp +++ b/doc/src/snippets/accessibilityslidersnippet.cpp @@ -227,7 +227,7 @@ QVariant QAccessibleAbstractSlider::invokeMethodEx(Method method, int child, con case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods; - return qVariantFromValue(set | qvariant_cast<QSet<QAccessible::Method> >( + return QVariant::fromValue(set | qvariant_cast<QSet<QAccessible::Method> >( QAccessibleWidgetEx::invokeMethodEx(method, child, params))); } default: diff --git a/doc/src/snippets/code/doc_src_porting4.qdoc b/doc/src/snippets/code/doc_src_porting4.qdoc index 7a39f2e..9ed557c 100644 --- a/doc/src/snippets/code/doc_src_porting4.qdoc +++ b/doc/src/snippets/code/doc_src_porting4.qdoc @@ -165,7 +165,7 @@ while (i.hasNext()) { //! [18] -QList<QWidget *> myWidgets = qFindChildren<QWidget *>(myParent); +QList<QWidget *> myWidgets = myParent->findChildren<QWidget *>(); //! [18] diff --git a/doc/src/snippets/code/doc_src_qmake-manual.qdoc b/doc/src/snippets/code/doc_src_qmake-manual.qdoc index 4ac7d5e..0436130 100644 --- a/doc/src/snippets/code/doc_src_qmake-manual.qdoc +++ b/doc/src/snippets/code/doc_src_qmake-manual.qdoc @@ -1002,3 +1002,8 @@ symbian { RSS_RULES.service_list += "uid = 0x12345678; datatype_list = \{\}; opaque_data = r_my_icon;" RSS_RULES.footer +="RESOURCE CAPTION_AND_ICON_INFO r_my_icon \{ icon_file =\"$$PWD/my_icon.svg\"; \}" //! [151] + +//! [152] +my_note.pkg_postrules.installer = "\"myinstallnote.txt\" - \"\", FILETEXT, TEXTCONTINUE" +DEPLOYMENT += my_note +//! [152] diff --git a/doc/src/snippets/code/doc_src_qtscript.qdoc b/doc/src/snippets/code/doc_src_qtscript.qdoc index 8effdf3..a81029e 100644 --- a/doc/src/snippets/code/doc_src_qtscript.qdoc +++ b/doc/src/snippets/code/doc_src_qtscript.qdoc @@ -964,7 +964,7 @@ QScriptValue constructXmlStreamReader(QScriptContext *context, QScriptEngine *en XmlStreamReaderPointer pointer(reader); // store the shared pointer in the script object that we are constructing - return engine->newVariant(context->thisObject(), qVariantFromValue(pointer)); + return engine->newVariant(context->thisObject(), QVariant::fromValue(pointer)); } //! [93] diff --git a/doc/src/snippets/code/src_corelib_kernel_qvariant.cpp b/doc/src/snippets/code/src_corelib_kernel_qvariant.cpp index 472c90e..9a86583 100644 --- a/doc/src/snippets/code/src_corelib_kernel_qvariant.cpp +++ b/doc/src/snippets/code/src_corelib_kernel_qvariant.cpp @@ -132,5 +132,5 @@ return QVariant::fromValue(s); //! [8] QObject *object = getObjectFromSomewhere(); -QVariant data = qVariantFromValue(object); +QVariant data = QVariant::fromValue(object); //! [8] diff --git a/doc/src/snippets/code/src_gui_accessible_qaccessible.cpp b/doc/src/snippets/code/src_gui_accessible_qaccessible.cpp index 8434d81..c5ca441 100644 --- a/doc/src/snippets/code/src_gui_accessible_qaccessible.cpp +++ b/doc/src/snippets/code/src_gui_accessible_qaccessible.cpp @@ -46,3 +46,7 @@ if (child) { delete child; } //! [0] + +//! [1] +typedef QAccessibleInterface* myFactoryFunction(const QString &key, QObject *); +//! [1]
\ No newline at end of file diff --git a/doc/src/snippets/code/src_xmlpatterns_api_qxmlquery.cpp b/doc/src/snippets/code/src_xmlpatterns_api_qxmlquery.cpp index 139e0a3..ef5cfb2 100644 --- a/doc/src/snippets/code/src_xmlpatterns_api_qxmlquery.cpp +++ b/doc/src/snippets/code/src_xmlpatterns_api_qxmlquery.cpp @@ -163,7 +163,7 @@ break; default: if (v.userType() == qMetaTypeId<QXmlName>()) { - QXmlName n = qVariantValue<QXmlName>(v); + QXmlName n = qvariant_cast<QXmlName>(v); // process QXmlName n... } else { diff --git a/doc/src/xml-processing/xml-patterns.qdoc b/doc/src/xml-processing/xml-patterns.qdoc index d0c8709..9f1917d 100644 --- a/doc/src/xml-processing/xml-patterns.qdoc +++ b/doc/src/xml-processing/xml-patterns.qdoc @@ -415,7 +415,7 @@ slight-of-hand using the \l{QMetaType} {Qt metatype system}. We must modify our example to use a couple of template functions, a friend of QMetaType (qMetaTypeId<T>()) and a friend of QVariant - (qVariantValue<T>()): + (qvariant_cast<T>()): \snippet doc/src/snippets/code/src_xmlpatterns_api_qxmlquery.cpp 6 diff --git a/examples/activeqt/hierarchy/objects.cpp b/examples/activeqt/hierarchy/objects.cpp index 918f219..bb0b701 100644 --- a/examples/activeqt/hierarchy/objects.cpp +++ b/examples/activeqt/hierarchy/objects.cpp @@ -62,7 +62,7 @@ void QParentWidget::createSubWidget(const QString &name) //! [1] //! [2] QSubWidget *QParentWidget::subWidget(const QString &name) { - return qFindChild<QSubWidget*>(this, name); + return findChild<QSubWidget*>(name); } //! [2] diff --git a/examples/animation/easing/window.cpp b/examples/animation/easing/window.cpp index a555024..8d9775d 100644 --- a/examples/animation/easing/window.cpp +++ b/examples/animation/easing/window.cpp @@ -44,7 +44,7 @@ Window::Window(QWidget *parent) : QWidget(parent), m_iconSize(64, 64) { m_ui.setupUi(this); - QButtonGroup *buttonGroup = qFindChild<QButtonGroup *>(this); // ### workaround for uic in 4.4 + QButtonGroup *buttonGroup = findChild<QButtonGroup *>(); // ### workaround for uic in 4.4 m_ui.easingCurvePicker->setIconSize(m_iconSize); m_ui.easingCurvePicker->setMinimumHeight(m_iconSize.height() + 50); buttonGroup->setId(m_ui.lineRadio, 0); diff --git a/examples/designer/calculatorbuilder/calculatorform.cpp b/examples/designer/calculatorbuilder/calculatorform.cpp index 34c869e..fa6ccb3 100644 --- a/examples/designer/calculatorbuilder/calculatorform.cpp +++ b/examples/designer/calculatorbuilder/calculatorform.cpp @@ -58,9 +58,9 @@ CalculatorForm::CalculatorForm(QWidget *parent) //! [1] //! [2] - ui_inputSpinBox1 = qFindChild<QSpinBox*>(this, "inputSpinBox1"); - ui_inputSpinBox2 = qFindChild<QSpinBox*>(this, "inputSpinBox2"); - ui_outputWidget = qFindChild<QLabel*>(this, "outputWidget"); + ui_inputSpinBox1 = findChild<QSpinBox*>("inputSpinBox1"); + ui_inputSpinBox2 = findChild<QSpinBox*>("inputSpinBox2"); + ui_outputWidget = findChild<QLabel*>("outputWidget"); //! [2] //! [3] diff --git a/examples/draganddrop/puzzle/pieceslist.cpp b/examples/draganddrop/puzzle/pieceslist.cpp index 77e8723..6e82145 100644 --- a/examples/draganddrop/puzzle/pieceslist.cpp +++ b/examples/draganddrop/puzzle/pieceslist.cpp @@ -103,7 +103,7 @@ void PiecesList::startDrag(Qt::DropActions /*supportedActions*/) QByteArray itemData; QDataStream dataStream(&itemData, QIODevice::WriteOnly); - QPixmap pixmap = qVariantValue<QPixmap>(item->data(Qt::UserRole)); + QPixmap pixmap = qvariant_cast<QPixmap>(item->data(Qt::UserRole)); QPoint location = item->data(Qt::UserRole+1).toPoint(); dataStream << pixmap << location; diff --git a/examples/graphicsview/diagramscene/mainwindow.cpp b/examples/graphicsview/diagramscene/mainwindow.cpp index 7d82df0..03e821d 100644 --- a/examples/graphicsview/diagramscene/mainwindow.cpp +++ b/examples/graphicsview/diagramscene/mainwindow.cpp @@ -236,7 +236,7 @@ void MainWindow::textColorChanged() textAction = qobject_cast<QAction *>(sender()); fontColorToolButton->setIcon(createColorToolButtonIcon( ":/images/textpointer.png", - qVariantValue<QColor>(textAction->data()))); + qvariant_cast<QColor>(textAction->data()))); textButtonTriggered(); } //! [12] @@ -247,7 +247,7 @@ void MainWindow::itemColorChanged() fillAction = qobject_cast<QAction *>(sender()); fillColorToolButton->setIcon(createColorToolButtonIcon( ":/images/floodfill.png", - qVariantValue<QColor>(fillAction->data()))); + qvariant_cast<QColor>(fillAction->data()))); fillButtonTriggered(); } //! [13] @@ -258,7 +258,7 @@ void MainWindow::lineColorChanged() lineAction = qobject_cast<QAction *>(sender()); lineColorToolButton->setIcon(createColorToolButtonIcon( ":/images/linecolor.png", - qVariantValue<QColor>(lineAction->data()))); + qvariant_cast<QColor>(lineAction->data()))); lineButtonTriggered(); } //! [14] @@ -266,21 +266,21 @@ void MainWindow::lineColorChanged() //! [15] void MainWindow::textButtonTriggered() { - scene->setTextColor(qVariantValue<QColor>(textAction->data())); + scene->setTextColor(qvariant_cast<QColor>(textAction->data())); } //! [15] //! [16] void MainWindow::fillButtonTriggered() { - scene->setItemColor(qVariantValue<QColor>(fillAction->data())); + scene->setItemColor(qvariant_cast<QColor>(fillAction->data())); } //! [16] //! [17] void MainWindow::lineButtonTriggered() { - scene->setLineColor(qVariantValue<QColor>(lineAction->data())); + scene->setLineColor(qvariant_cast<QColor>(lineAction->data())); } //! [17] diff --git a/examples/graphicsview/dragdroprobot/robot.cpp b/examples/graphicsview/dragdroprobot/robot.cpp index 44ecda3..caca309 100644 --- a/examples/graphicsview/dragdroprobot/robot.cpp +++ b/examples/graphicsview/dragdroprobot/robot.cpp @@ -77,7 +77,7 @@ void RobotPart::dropEvent(QGraphicsSceneDragDropEvent *event) { dragOver = false; if (event->mimeData()->hasColor()) - color = qVariantValue<QColor>(event->mimeData()->colorData()); + color = qvariant_cast<QColor>(event->mimeData()->colorData()); update(); } //! [3] @@ -139,7 +139,7 @@ void RobotHead::dropEvent(QGraphicsSceneDragDropEvent *event) { if (event->mimeData()->hasImage()) { dragOver = false; - pixmap = qVariantValue<QPixmap>(event->mimeData()->imageData()); + pixmap = qvariant_cast<QPixmap>(event->mimeData()->imageData()); update(); } else { RobotPart::dropEvent(event); diff --git a/examples/graphicsview/padnavigator/padnavigator.cpp b/examples/graphicsview/padnavigator/padnavigator.cpp index 4988664..3ea68de 100644 --- a/examples/graphicsview/padnavigator/padnavigator.cpp +++ b/examples/graphicsview/padnavigator/padnavigator.cpp @@ -135,9 +135,9 @@ PadNavigator::PadNavigator(const QSize &size, QWidget *parent) smoothFlipRotation->setEasingCurve(QEasingCurve::InOutQuad); smoothFlipXRotation->setEasingCurve(QEasingCurve::InOutQuad); smoothFlipYRotation->setEasingCurve(QEasingCurve::InOutQuad); - smoothFlipScale->setKeyValueAt(0, qVariantValue<qreal>(1.0)); - smoothFlipScale->setKeyValueAt(0.5, qVariantValue<qreal>(0.7)); - smoothFlipScale->setKeyValueAt(1, qVariantValue<qreal>(1.0)); + smoothFlipScale->setKeyValueAt(0, qvariant_cast<qreal>(1.0)); + smoothFlipScale->setKeyValueAt(0.5, qvariant_cast<qreal>(0.7)); + smoothFlipScale->setKeyValueAt(1, qvariant_cast<qreal>(1.0)); flipAnimation->addAnimation(smoothFlipRotation); flipAnimation->addAnimation(smoothFlipScale); flipAnimation->addAnimation(smoothFlipXRotation); @@ -172,13 +172,13 @@ PadNavigator::PadNavigator(const QSize &size, QWidget *parent) frontState->assignProperty(pad, "fill", false); frontState->assignProperty(splash, "opacity", 0.0); frontState->assignProperty(backItem, "visible", false); - frontState->assignProperty(flipRotation, "angle", qVariantValue<qreal>(0.0)); + frontState->assignProperty(flipRotation, "angle", qvariant_cast<qreal>(0.0)); frontState->assignProperty(selectionItem, "visible", true); backState->assignProperty(pad, "fill", true); backState->assignProperty(backItem, "visible", true); - backState->assignProperty(xRotation, "angle", qVariantValue<qreal>(0.0)); - backState->assignProperty(yRotation, "angle", qVariantValue<qreal>(0.0)); - backState->assignProperty(flipRotation, "angle", qVariantValue<qreal>(180.0)); + backState->assignProperty(xRotation, "angle", qvariant_cast<qreal>(0.0)); + backState->assignProperty(yRotation, "angle", qvariant_cast<qreal>(0.0)); + backState->assignProperty(flipRotation, "angle", qvariant_cast<qreal>(180.0)); backState->assignProperty(selectionItem, "visible", false); stateMachine->addDefaultAnimation(smoothXRotation); stateMachine->addDefaultAnimation(smoothYRotation); diff --git a/examples/itemviews/coloreditorfactory/colorlisteditor.cpp b/examples/itemviews/coloreditorfactory/colorlisteditor.cpp index 1af5831..4f4a954 100644 --- a/examples/itemviews/coloreditorfactory/colorlisteditor.cpp +++ b/examples/itemviews/coloreditorfactory/colorlisteditor.cpp @@ -50,7 +50,7 @@ ColorListEditor::ColorListEditor(QWidget *widget) : QComboBox(widget) //! [0] QColor ColorListEditor::color() const { - return qVariantValue<QColor>(itemData(currentIndex(), Qt::DecorationRole)); + return qvariant_cast<QColor>(itemData(currentIndex(), Qt::DecorationRole)); } //! [0] diff --git a/examples/itemviews/puzzle/piecesmodel.cpp b/examples/itemviews/puzzle/piecesmodel.cpp index e110cf1..e55663b 100644 --- a/examples/itemviews/puzzle/piecesmodel.cpp +++ b/examples/itemviews/puzzle/piecesmodel.cpp @@ -124,7 +124,7 @@ QMimeData *PiecesModel::mimeData(const QModelIndexList &indexes) const foreach (QModelIndex index, indexes) { if (index.isValid()) { - QPixmap pixmap = qVariantValue<QPixmap>(data(index, Qt::UserRole)); + QPixmap pixmap = qvariant_cast<QPixmap>(data(index, Qt::UserRole)); QPoint location = data(index, Qt::UserRole+1).toPoint(); stream << pixmap << location; } diff --git a/examples/itemviews/stardelegate/main.cpp b/examples/itemviews/stardelegate/main.cpp index d9f655d..444017e 100644 --- a/examples/itemviews/stardelegate/main.cpp +++ b/examples/itemviews/stardelegate/main.cpp @@ -71,7 +71,7 @@ void populateTableWidget(QTableWidget *tableWidget) QTableWidgetItem *item2 = new QTableWidgetItem(staticData[row].artist); QTableWidgetItem *item3 = new QTableWidgetItem; item3->setData(0, - qVariantFromValue(StarRating(staticData[row].rating))); + QVariant::fromValue(StarRating(staticData[row].rating))); tableWidget->setItem(row, 0, item0); tableWidget->setItem(row, 1, item1); diff --git a/examples/itemviews/stardelegate/stardelegate.cpp b/examples/itemviews/stardelegate/stardelegate.cpp index 44dd54f..ebb2e38 100644 --- a/examples/itemviews/stardelegate/stardelegate.cpp +++ b/examples/itemviews/stardelegate/stardelegate.cpp @@ -48,8 +48,8 @@ void StarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { - if (qVariantCanConvert<StarRating>(index.data())) { - StarRating starRating = qVariantValue<StarRating>(index.data()); + if (index.data().canConvert<StarRating>()) { + StarRating starRating = qvariant_cast<StarRating>(index.data()); if (option.state & QStyle::State_Selected) painter->fillRect(option.rect, option.palette.highlight()); @@ -66,8 +66,8 @@ void StarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, QSize StarDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { - if (qVariantCanConvert<StarRating>(index.data())) { - StarRating starRating = qVariantValue<StarRating>(index.data()); + if (index.data().canConvert<StarRating>()) { + StarRating starRating = qvariant_cast<StarRating>(index.data()); return starRating.sizeHint(); } else { return QStyledItemDelegate::sizeHint(option, index); @@ -81,7 +81,7 @@ QWidget *StarDelegate::createEditor(QWidget *parent, const QModelIndex &index) const { - if (qVariantCanConvert<StarRating>(index.data())) { + if (index.data().canConvert<StarRating>()) { StarEditor *editor = new StarEditor(parent); connect(editor, SIGNAL(editingFinished()), this, SLOT(commitAndCloseEditor())); @@ -96,8 +96,8 @@ QWidget *StarDelegate::createEditor(QWidget *parent, void StarDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { - if (qVariantCanConvert<StarRating>(index.data())) { - StarRating starRating = qVariantValue<StarRating>(index.data()); + if (index.data().canConvert<StarRating>()) { + StarRating starRating = qvariant_cast<StarRating>(index.data()); StarEditor *starEditor = qobject_cast<StarEditor *>(editor); starEditor->setStarRating(starRating); } else { @@ -110,9 +110,9 @@ void StarDelegate::setEditorData(QWidget *editor, void StarDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { - if (qVariantCanConvert<StarRating>(index.data())) { + if (index.data().canConvert<StarRating>()) { StarEditor *starEditor = qobject_cast<StarEditor *>(editor); - model->setData(index, qVariantFromValue(starEditor->starRating())); + model->setData(index, QVariant::fromValue(starEditor->starRating())); } else { QStyledItemDelegate::setModelData(editor, model, index); } diff --git a/examples/multimedia/audiodevices/audiodevices.cpp b/examples/multimedia/audiodevices/audiodevices.cpp index 5ab4918..6eb0763 100644 --- a/examples/multimedia/audiodevices/audiodevices.cpp +++ b/examples/multimedia/audiodevices/audiodevices.cpp @@ -155,7 +155,7 @@ void AudioTest::modeChanged(int idx) deviceBox->clear(); foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(mode)) - deviceBox->addItem(deviceInfo.deviceName(), qVariantFromValue(deviceInfo)); + deviceBox->addItem(deviceInfo.deviceName(), QVariant::fromValue(deviceInfo)); deviceBox->setCurrentIndex(0); deviceChanged(0); diff --git a/examples/multimedia/audioinput/audioinput.cpp b/examples/multimedia/audioinput/audioinput.cpp index 4e5f2a3..cf18335 100644 --- a/examples/multimedia/audioinput/audioinput.cpp +++ b/examples/multimedia/audioinput/audioinput.cpp @@ -237,7 +237,7 @@ void InputTest::initializeWindow() m_deviceBox = new QComboBox(this); QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); for(int i = 0; i < devices.size(); ++i) - m_deviceBox->addItem(devices.at(i).deviceName(), qVariantFromValue(devices.at(i))); + m_deviceBox->addItem(devices.at(i).deviceName(), QVariant::fromValue(devices.at(i))); connect(m_deviceBox, SIGNAL(activated(int)), SLOT(deviceChanged(int))); layout->addWidget(m_deviceBox); diff --git a/examples/multimedia/audiooutput/audiooutput.cpp b/examples/multimedia/audiooutput/audiooutput.cpp index bc2324e..4e74a25 100644 --- a/examples/multimedia/audiooutput/audiooutput.cpp +++ b/examples/multimedia/audiooutput/audiooutput.cpp @@ -176,7 +176,7 @@ void AudioTest::initializeWindow() m_deviceBox = new QComboBox(this); foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) - m_deviceBox->addItem(deviceInfo.deviceName(), qVariantFromValue(deviceInfo)); + m_deviceBox->addItem(deviceInfo.deviceName(), QVariant::fromValue(deviceInfo)); connect(m_deviceBox,SIGNAL(activated(int)),SLOT(deviceChanged(int))); layout->addWidget(m_deviceBox); diff --git a/examples/network/multicastreceiver/main.cpp b/examples/network/multicastreceiver/main.cpp new file mode 100644 index 0000000..8483271 --- /dev/null +++ b/examples/network/multicastreceiver/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> + +#include "receiver.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + Receiver receiver; + receiver.show(); + return receiver.exec(); +} diff --git a/examples/network/multicastreceiver/multicastreceiver.pro b/examples/network/multicastreceiver/multicastreceiver.pro new file mode 100644 index 0000000..400c92e --- /dev/null +++ b/examples/network/multicastreceiver/multicastreceiver.pro @@ -0,0 +1,12 @@ +HEADERS = receiver.h +SOURCES = receiver.cpp \ + main.cpp +QT += network + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/network/multicastreceiver +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS multicastreceiver.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/network/multicastreceiver +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/examples/network/multicastreceiver/receiver.cpp b/examples/network/multicastreceiver/receiver.cpp new file mode 100644 index 0000000..073fdce --- /dev/null +++ b/examples/network/multicastreceiver/receiver.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> +#include <QtNetwork> + +#include "receiver.h" + +Receiver::Receiver(QWidget *parent) + : QDialog(parent) +{ + groupAddress = QHostAddress("239.255.43.21"); + + statusLabel = new QLabel(tr("Listening for multicasted messages")); + quitButton = new QPushButton(tr("&Quit")); + + udpSocket = new QUdpSocket(this); + udpSocket->bind(45454, QUdpSocket::ShareAddress); + udpSocket->joinMulticastGroup(groupAddress); + + connect(udpSocket, SIGNAL(readyRead()), + this, SLOT(processPendingDatagrams())); + connect(quitButton, SIGNAL(clicked()), this, SLOT(close())); + + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->addStretch(1); + buttonLayout->addWidget(quitButton); + buttonLayout->addStretch(1); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(statusLabel); + mainLayout->addLayout(buttonLayout); + setLayout(mainLayout); + + setWindowTitle(tr("Multicast Receiver")); +} + +void Receiver::processPendingDatagrams() +{ + while (udpSocket->hasPendingDatagrams()) { + QByteArray datagram; + datagram.resize(udpSocket->pendingDatagramSize()); + udpSocket->readDatagram(datagram.data(), datagram.size()); + statusLabel->setText(tr("Received datagram: \"%1\"") + .arg(datagram.data())); + } +} diff --git a/examples/network/multicastreceiver/receiver.h b/examples/network/multicastreceiver/receiver.h new file mode 100644 index 0000000..e226028 --- /dev/null +++ b/examples/network/multicastreceiver/receiver.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef RECEIVER_H +#define RECEIVER_H + +#include <QDialog> +#include <QHostAddress> + +QT_BEGIN_NAMESPACE +class QLabel; +class QPushButton; +class QUdpSocket; +QT_END_NAMESPACE + +class Receiver : public QDialog +{ + Q_OBJECT + +public: + Receiver(QWidget *parent = 0); + +private slots: + void processPendingDatagrams(); + +private: + QLabel *statusLabel; + QPushButton *quitButton; + QUdpSocket *udpSocket; + QHostAddress groupAddress; +}; + +#endif diff --git a/examples/network/multicastsender/main.cpp b/examples/network/multicastsender/main.cpp new file mode 100644 index 0000000..9309322 --- /dev/null +++ b/examples/network/multicastsender/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> + +#include "sender.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + Sender sender; + sender.show(); + return sender.exec(); +} diff --git a/examples/network/multicastsender/multicastsender.pro b/examples/network/multicastsender/multicastsender.pro new file mode 100644 index 0000000..7543f00 --- /dev/null +++ b/examples/network/multicastsender/multicastsender.pro @@ -0,0 +1,12 @@ +HEADERS = sender.h +SOURCES = sender.cpp \ + main.cpp +QT += network + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/network/multicastsender +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS multicastsender.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/network/multicastsender +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/examples/network/multicastsender/sender.cpp b/examples/network/multicastsender/sender.cpp new file mode 100644 index 0000000..7fa9750 --- /dev/null +++ b/examples/network/multicastsender/sender.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> +#include <QtNetwork> + +#include "sender.h" + +Sender::Sender(QWidget *parent) + : QDialog(parent) +{ + groupAddress = QHostAddress("239.255.43.21"); + + statusLabel = new QLabel(tr("Ready to multicast datagrams to group %1 on port 45454").arg(groupAddress.toString())); + + ttlLabel = new QLabel(tr("TTL for multicast datagrams:")); + ttlSpinBox = new QSpinBox; + ttlSpinBox->setRange(0, 255); + + QHBoxLayout *ttlLayout = new QHBoxLayout; + ttlLayout->addWidget(ttlLabel); + ttlLayout->addWidget(ttlSpinBox); + + startButton = new QPushButton(tr("&Start")); + quitButton = new QPushButton(tr("&Quit")); + + buttonBox = new QDialogButtonBox; + buttonBox->addButton(startButton, QDialogButtonBox::ActionRole); + buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole); + + timer = new QTimer(this); + udpSocket = new QUdpSocket(this); + messageNo = 1; + + connect(ttlSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ttlChanged(int))); + connect(startButton, SIGNAL(clicked()), this, SLOT(startSending())); + connect(quitButton, SIGNAL(clicked()), this, SLOT(close())); + connect(timer, SIGNAL(timeout()), this, SLOT(sendDatagram())); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(statusLabel); + mainLayout->addLayout(ttlLayout); + mainLayout->addWidget(buttonBox); + setLayout(mainLayout); + + setWindowTitle(tr("Multicast Sender")); + ttlSpinBox->setValue(1); +} + +void Sender::ttlChanged(int newTtl) +{ + udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, newTtl); +} + +void Sender::startSending() +{ + startButton->setEnabled(false); + timer->start(1000); +} + +void Sender::sendDatagram() +{ + statusLabel->setText(tr("Now sending datagram %1").arg(messageNo)); + QByteArray datagram = "Multicast message " + QByteArray::number(messageNo); + udpSocket->writeDatagram(datagram.data(), datagram.size(), + groupAddress, 45454); + ++messageNo; +} diff --git a/examples/network/multicastsender/sender.h b/examples/network/multicastsender/sender.h new file mode 100644 index 0000000..f119883 --- /dev/null +++ b/examples/network/multicastsender/sender.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SENDER_H +#define SENDER_H + +#include <QDialog> +#include <QHostAddress> + +QT_BEGIN_NAMESPACE +class QDialogButtonBox; +class QLabel; +class QPushButton; +class QTimer; +class QUdpSocket; +class QSpinBox; +QT_END_NAMESPACE + +class Sender : public QDialog +{ + Q_OBJECT + +public: + Sender(QWidget *parent = 0); + +private slots: + void ttlChanged(int newTtl); + void startSending(); + void sendDatagram(); + +private: + QLabel *statusLabel; + QLabel *ttlLabel; + QSpinBox *ttlSpinBox; + QPushButton *startButton; + QPushButton *quitButton; + QDialogButtonBox *buttonBox; + QUdpSocket *udpSocket; + QTimer *timer; + QHostAddress groupAddress; + int messageNo; +}; + +#endif diff --git a/examples/network/network.pro b/examples/network/network.pro index 458561a..0012a97 100644 --- a/examples/network/network.pro +++ b/examples/network/network.pro @@ -16,7 +16,9 @@ SUBDIRS = \ threadedfortuneserver \ googlesuggest \ torrent \ - bearermonitor + bearermonitor \ + multicastreceiver \ + multicastsender contains(QT_CONFIG, svg) { SUBDIRS += bearercloud diff --git a/examples/network/torrent/bencodeparser.cpp b/examples/network/torrent/bencodeparser.cpp index d6b6078..aa498d6 100644 --- a/examples/network/torrent/bencodeparser.cpp +++ b/examples/network/torrent/bencodeparser.cpp @@ -171,7 +171,7 @@ bool BencodeParser::getList(QList<QVariant> *list) else if (getList(&tmpList)) tmp << tmpList; else if (getDictionary(&dictionary)) - tmp << qVariantFromValue<QMap<QByteArray, QVariant> >(dictionary); + tmp << QVariant::fromValue<QMap<QByteArray, QVariant> >(dictionary); else { errString = QString("error at index %1").arg(index); return false; @@ -217,7 +217,7 @@ bool BencodeParser::getDictionary(QMap<QByteArray, QVariant> *dictionary) else if (getList(&tmpList)) tmp.insert(key, tmpList); else if (getDictionary(&dictionary)) - tmp.insert(key, qVariantFromValue<QMap<QByteArray, QVariant> >(dictionary)); + tmp.insert(key, QVariant::fromValue<QMap<QByteArray, QVariant> >(dictionary)); else { errString = QString("error at index %1").arg(index); return false; diff --git a/examples/network/torrent/metainfo.cpp b/examples/network/torrent/metainfo.cpp index a6e7511..a7cd978 100644 --- a/examples/network/torrent/metainfo.cpp +++ b/examples/network/torrent/metainfo.cpp @@ -83,7 +83,7 @@ bool MetaInfo::parse(const QByteArray &data) if (!dict.contains("info")) return false; - QMap<QByteArray, QVariant> info = qVariantValue<Dictionary>(dict.value("info")); + QMap<QByteArray, QVariant> info = qvariant_cast<Dictionary>(dict.value("info")); if (info.contains("files")) { metaInfoFileForm = MultiFileForm; @@ -91,7 +91,7 @@ bool MetaInfo::parse(const QByteArray &data) QList<QVariant> files = info.value("files").toList(); for (int i = 0; i < files.size(); ++i) { - QMap<QByteArray, QVariant> file = qVariantValue<Dictionary>(files.at(i)); + QMap<QByteArray, QVariant> file = qvariant_cast<Dictionary>(files.at(i)); QList<QVariant> pathElements = file.value("path").toList(); QByteArray path; foreach (QVariant p, pathElements) { diff --git a/examples/network/torrent/trackerclient.cpp b/examples/network/torrent/trackerclient.cpp index 61d7e95..07194fa 100644 --- a/examples/network/torrent/trackerclient.cpp +++ b/examples/network/torrent/trackerclient.cpp @@ -210,7 +210,7 @@ void TrackerClient::httpRequestDone(bool error) QList<QVariant> peerTmp = peerEntry.toList(); for (int i = 0; i < peerTmp.size(); ++i) { TorrentPeer tmp; - QMap<QByteArray, QVariant> peer = qVariantValue<QMap<QByteArray, QVariant> >(peerTmp.at(i)); + QMap<QByteArray, QVariant> peer = qvariant_cast<QMap<QByteArray, QVariant> >(peerTmp.at(i)); tmp.id = QString::fromUtf8(peer.value("peer id").toByteArray()); tmp.address.setAddress(QString::fromUtf8(peer.value("ip").toByteArray())); tmp.port = peer.value("port").toInt(); diff --git a/examples/richtext/textobject/svgtextobject.cpp b/examples/richtext/textobject/svgtextobject.cpp index c84725d..2442623 100644 --- a/examples/richtext/textobject/svgtextobject.cpp +++ b/examples/richtext/textobject/svgtextobject.cpp @@ -48,7 +48,7 @@ QSizeF SvgTextObject::intrinsicSize(QTextDocument * /*doc*/, int /*posInDocument*/, const QTextFormat &format) { - QImage bufferedImage = qVariantValue<QImage>(format.property(Window::SvgData)); + QImage bufferedImage = qvariant_cast<QImage>(format.property(Window::SvgData)); QSize size = bufferedImage.size(); if (size.height() > 25) @@ -63,7 +63,7 @@ void SvgTextObject::drawObject(QPainter *painter, const QRectF &rect, QTextDocument * /*doc*/, int /*posInDocument*/, const QTextFormat &format) { - QImage bufferedImage = qVariantValue<QImage>(format.property(Window::SvgData)); + QImage bufferedImage = qvariant_cast<QImage>(format.property(Window::SvgData)); painter->drawImage(rect, bufferedImage); } diff --git a/examples/script/calculator/main.cpp b/examples/script/calculator/main.cpp index 8030a87..c258a9b 100644 --- a/examples/script/calculator/main.cpp +++ b/examples/script/calculator/main.cpp @@ -89,7 +89,7 @@ int main(int argc, char **argv) //! [2] #if !defined(QT_NO_SCRIPTTOOLS) - QLineEdit *display = qFindChild<QLineEdit*>(ui, "display"); + QLineEdit *display = ui->findChild<QLineEdit*>("display"); QObject::connect(display, SIGNAL(returnPressed()), debugWindow, SLOT(show())); #endif diff --git a/examples/script/context2d/context2d.cpp b/examples/script/context2d/context2d.cpp index c408736..49fc3bc 100644 --- a/examples/script/context2d/context2d.cpp +++ b/examples/script/context2d/context2d.cpp @@ -278,7 +278,7 @@ QVariant Context2D::strokeStyle() const void Context2D::setStrokeStyle(const QVariant &style) { - if (qVariantCanConvert<CanvasGradient>(style)) { + if (style.canConvert<CanvasGradient>()) { CanvasGradient cg = qvariant_cast<CanvasGradient>(style); m_state.strokeStyle = cg.value; } else { @@ -296,7 +296,7 @@ QVariant Context2D::fillStyle() const //! [3] void Context2D::setFillStyle(const QVariant &style) { - if (qVariantCanConvert<CanvasGradient>(style)) { + if (style.canConvert<CanvasGradient>()) { CanvasGradient cg = qvariant_cast<CanvasGradient>(style); m_state.fillStyle = cg.value; } else { diff --git a/examples/script/context2d/domimage.cpp b/examples/script/context2d/domimage.cpp index 801e1a2..f655c6f 100644 --- a/examples/script/context2d/domimage.cpp +++ b/examples/script/context2d/domimage.cpp @@ -84,7 +84,7 @@ static QScriptValue Image(QScriptContext *context, QScriptEngine *env) { QScriptValue val = context->thisObject(); DomImage *image = new DomImage(); - QScriptValue klass = env->newVariant(qVariantFromValue(image)); + QScriptValue klass = env->newVariant(QVariant::fromValue(image)); klass.setPrototype(DomImage::s_self); return klass; } diff --git a/examples/script/customclass/bytearrayclass.cpp b/examples/script/customclass/bytearrayclass.cpp index 5ecee0a..7bf6d3f 100644 --- a/examples/script/customclass/bytearrayclass.cpp +++ b/examples/script/customclass/bytearrayclass.cpp @@ -88,7 +88,7 @@ ByteArrayClass::ByteArrayClass(QScriptEngine *engine) proto.setPrototype(global.property("Object").property("prototype")); ctor = engine->newFunction(construct, proto); - ctor.setData(qScriptValueFromValue(engine, this)); + ctor.setData(engine->toScriptValue(this)); } //! [0] @@ -204,7 +204,7 @@ QScriptValue ByteArrayClass::newInstance(int size) //! [1] QScriptValue ByteArrayClass::newInstance(const QByteArray &ba) { - QScriptValue data = engine()->newVariant(qVariantFromValue(ba)); + QScriptValue data = engine()->newVariant(QVariant::fromValue(ba)); return engine()->newObject(this, data); } //! [1] @@ -228,7 +228,7 @@ QScriptValue ByteArrayClass::toScriptValue(QScriptEngine *eng, const QByteArray QScriptValue ctor = eng->globalObject().property("ByteArray"); ByteArrayClass *cls = qscriptvalue_cast<ByteArrayClass*>(ctor.data()); if (!cls) - return eng->newVariant(qVariantFromValue(ba)); + return eng->newVariant(QVariant::fromValue(ba)); return cls->newInstance(ba); } diff --git a/examples/script/marshal/main.cpp b/examples/script/marshal/main.cpp index adfeaf1..270cb56 100644 --- a/examples/script/marshal/main.cpp +++ b/examples/script/marshal/main.cpp @@ -49,7 +49,7 @@ QScriptValue toScriptValue(QScriptEngine *eng, const Container &cont) typename Container::const_iterator end = cont.end(); typename Container::const_iterator it; for (it = begin; it != end; ++it) - a.setProperty(quint32(it - begin), qScriptValueFromValue(eng, *it)); + a.setProperty(quint32(it - begin), eng->toScriptValue(*it)); return a; } diff --git a/examples/script/qstetrix/main.cpp b/examples/script/qstetrix/main.cpp index e12e26d..c802584 100644 --- a/examples/script/qstetrix/main.cpp +++ b/examples/script/qstetrix/main.cpp @@ -120,7 +120,7 @@ int main(int argc, char *argv[]) QScriptValue tetrix = ctor.construct(QScriptValueList() << scriptUi); //! [3] - QPushButton *debugButton = qFindChild<QPushButton*>(ui, "debugButton"); + QPushButton *debugButton = ui->findChild<QPushButton*>("debugButton"); #if !defined(QT_NO_SCRIPTTOOLS) QObject::connect(debugButton, SIGNAL(clicked()), debugger.action(QScriptEngineDebugger::InterruptAction), diff --git a/examples/sql/querymodel/customsqlmodel.cpp b/examples/sql/querymodel/customsqlmodel.cpp index f444acf..75d16b4 100644 --- a/examples/sql/querymodel/customsqlmodel.cpp +++ b/examples/sql/querymodel/customsqlmodel.cpp @@ -58,7 +58,7 @@ QVariant CustomSqlModel::data(const QModelIndex &index, int role) const return value.toString().toUpper(); } if (role == Qt::TextColorRole && index.column() == 1) - return qVariantFromValue(QColor(Qt::blue)); + return QVariant::fromValue(QColor(Qt::blue)); return value; } //! [0] diff --git a/examples/tools/customtype/main.cpp b/examples/tools/customtype/main.cpp index 229cd18..430613a 100644 --- a/examples/tools/customtype/main.cpp +++ b/examples/tools/customtype/main.cpp @@ -65,7 +65,7 @@ int main(int argc, char *argv[]) //! [retrieving a custom value] Message retrieved = stored.value<Message>(); qDebug() << "Retrieved:" << retrieved; - retrieved = qVariantValue<Message>(stored); + retrieved = qvariant_cast<Message>(stored); qDebug() << "Retrieved:" << retrieved; //! [retrieving a custom value] diff --git a/examples/uitools/textfinder/textfinder.cpp b/examples/uitools/textfinder/textfinder.cpp index 4bb6600..1682acd 100644 --- a/examples/uitools/textfinder/textfinder.cpp +++ b/examples/uitools/textfinder/textfinder.cpp @@ -49,9 +49,9 @@ TextFinder::TextFinder(QWidget *parent) QWidget *formWidget = loadUiFile(); //! [1] - ui_findButton = qFindChild<QPushButton*>(this, "findButton"); - ui_textEdit = qFindChild<QTextEdit*>(this, "textEdit"); - ui_lineEdit = qFindChild<QLineEdit*>(this, "lineEdit"); + ui_findButton = findChild<QPushButton*>("findButton"); + ui_textEdit = findChild<QTextEdit*>("textEdit"); + ui_lineEdit = findChild<QLineEdit*>("lineEdit"); //! [0] //! [1] //! [2] diff --git a/examples/widgets/validators/localeselector.cpp b/examples/widgets/validators/localeselector.cpp index e4aae1a..0a48d66 100644 --- a/examples/widgets/validators/localeselector.cpp +++ b/examples/widgets/validators/localeselector.cpp @@ -294,7 +294,7 @@ LocaleSelector::LocaleSelector(QWidget *parent) QString text = QLocale::languageToString(QLocale::Language(l.lang)) + QLatin1Char('/') + QLocale::countryToString(QLocale::Country(l.country)); - addItem(text, qVariantFromValue(l)); + addItem(text, QVariant::fromValue(l)); } setCurrentIndex(curIndex); @@ -307,6 +307,6 @@ void LocaleSelector::emitLocaleSelected(int index) QVariant v = itemData(index); if (!v.isValid()) return; - SupportedLocale l = qVariantValue<SupportedLocale>(v); + SupportedLocale l = qvariant_cast<SupportedLocale>(v); emit localeSelected(QLocale(QLocale::Language(l.lang), QLocale::Country(l.country))); } diff --git a/examples/xmlpatterns/recipes/querymainwindow.cpp b/examples/xmlpatterns/recipes/querymainwindow.cpp index 0fd2483..8a4c606 100644 --- a/examples/xmlpatterns/recipes/querymainwindow.cpp +++ b/examples/xmlpatterns/recipes/querymainwindow.cpp @@ -49,10 +49,10 @@ QueryMainWindow::QueryMainWindow() : ui_defaultQueries(0) { setupUi(this); - new XmlSyntaxHighlighter(qFindChild<QTextEdit*>(this, "inputTextEdit")->document()); - new XmlSyntaxHighlighter(qFindChild<QTextEdit*>(this, "outputTextEdit")->document()); + new XmlSyntaxHighlighter(findChild<QTextEdit*>("inputTextEdit")->document()); + new XmlSyntaxHighlighter(findChild<QTextEdit*>("outputTextEdit")->document()); - ui_defaultQueries = qFindChild<QComboBox*>(this, "defaultQueries"); + ui_defaultQueries = findChild<QComboBox*>("defaultQueries"); QMetaObject::connectSlotsByName(this); connect(ui_defaultQueries, SIGNAL(currentIndexChanged(int)), SLOT(displayQuery(int))); @@ -71,7 +71,7 @@ void QueryMainWindow::displayQuery(int index) QFile queryFile(QString(":files/") + ui_defaultQueries->itemText(index)); queryFile.open(QIODevice::ReadOnly); const QString query(QString::fromLatin1(queryFile.readAll())); - qFindChild<QTextEdit*>(this, "queryTextEdit")->setPlainText(query); + findChild<QTextEdit*>("queryTextEdit")->setPlainText(query); evaluate(query); } @@ -90,7 +90,7 @@ void QueryMainWindow::loadInputFile() QTextStream in(&forView); QString inputDocument = in.readAll(); - qFindChild<QTextEdit*>(this, "inputTextEdit")->setPlainText(inputDocument); + findChild<QTextEdit*>("inputTextEdit")->setPlainText(inputDocument); } @@ -116,7 +116,7 @@ void QueryMainWindow::evaluate(const QString &str) return; buffer.close(); - qFindChild<QTextEdit*>(this, "outputTextEdit")->setPlainText(QString::fromUtf8(outArray.constData())); + findChild<QTextEdit*>("outputTextEdit")->setPlainText(QString::fromUtf8(outArray.constData())); } //! [2] diff --git a/mkspecs/aix-g++-64/qmake.conf b/mkspecs/aix-g++-64/qmake.conf index d9d9c38..b0179d5 100644 --- a/mkspecs/aix-g++-64/qmake.conf +++ b/mkspecs/aix-g++-64/qmake.conf @@ -63,7 +63,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthreads diff --git a/mkspecs/aix-g++/qmake.conf b/mkspecs/aix-g++/qmake.conf index 5fc4c17..2e2e991 100644 --- a/mkspecs/aix-g++/qmake.conf +++ b/mkspecs/aix-g++/qmake.conf @@ -63,7 +63,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthreads diff --git a/mkspecs/aix-xlc-64/qmake.conf b/mkspecs/aix-xlc-64/qmake.conf index ae87b88..486b8c6 100644 --- a/mkspecs/aix-xlc-64/qmake.conf +++ b/mkspecs/aix-xlc-64/qmake.conf @@ -62,7 +62,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthreads diff --git a/mkspecs/aix-xlc/qmake.conf b/mkspecs/aix-xlc/qmake.conf index fe91236..8655db6 100644 --- a/mkspecs/aix-xlc/qmake.conf +++ b/mkspecs/aix-xlc/qmake.conf @@ -63,7 +63,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthreads diff --git a/mkspecs/common/linux.conf b/mkspecs/common/linux.conf index 4fbe2dc..e443be1 100644 --- a/mkspecs/common/linux.conf +++ b/mkspecs/common/linux.conf @@ -28,7 +28,7 @@ QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_NIS = -lnsl QMAKE_LIBS_EGL = -lEGL -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_OPENGL_ES1 = -lGLES_CM QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 diff --git a/mkspecs/cygwin-g++/qmake.conf b/mkspecs/cygwin-g++/qmake.conf index 29d0958..ddfceb0 100644 --- a/mkspecs/cygwin-g++/qmake.conf +++ b/mkspecs/cygwin-g++/qmake.conf @@ -65,7 +65,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread diff --git a/mkspecs/darwin-g++/qmake.conf b/mkspecs/darwin-g++/qmake.conf index fc55503..84dc764 100644 --- a/mkspecs/darwin-g++/qmake.conf +++ b/mkspecs/darwin-g++/qmake.conf @@ -74,7 +74,7 @@ QMAKE_LFLAGS_RPATH = QMAKE_LIBS_DYNLOAD = QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = diff --git a/mkspecs/features/unix/gdb_dwarf_index.prf b/mkspecs/features/unix/gdb_dwarf_index.prf new file mode 100644 index 0000000..e2167a6 --- /dev/null +++ b/mkspecs/features/unix/gdb_dwarf_index.prf @@ -0,0 +1,15 @@ +!CONFIG(separate_debug_info):CONFIG(debug, debug|release):!staticlib:!static:!contains(TEMPLATE, subdirs):!isEmpty(QMAKE_OBJCOPY) { + + QMAKE_GDB_INDEX = { test -z \"$(DESTDIR)\" || cd \"$(DESTDIR)\"; } && \ + test \$\$(gdb --version | sed -e \'s,[^(]*(GDB).\\([0-9]\\)\\.\\([0-9]\\).*,\\1\\2,;q\') -gt 71 && \ + gdb --nx --batch --quiet -ex \'set confirm off\' -ex \'save gdb-index .\' -ex quit \'$(TARGET)\' && \ + test -f $(TARGET).gdb-index && \ + $$QMAKE_OBJCOPY --add-section \'.gdb_index=$(TARGET).gdb-index\' --set-section-flags \'.gdb_index=readonly\' \'$(TARGET)\' \'$(TARGET)\' && \ + $$QMAKE_DEL_FILE $(TARGET).gdb-index || true + + !isEmpty(QMAKE_POST_LINK):QMAKE_POST_LINK = $$escape_expand(\\n\\t)$$QMAKE_POST_LINK + QMAKE_POST_LINK = $$QMAKE_GDB_INDEX $$QMAKE_POST_LINK + + silent:QMAKE_POST_LINK = @echo indexing $@ for gdb && $$QMAKE_POST_LINK +} + diff --git a/mkspecs/freebsd-g++/qmake.conf b/mkspecs/freebsd-g++/qmake.conf index 51a1960..9de93d4 100644 --- a/mkspecs/freebsd-g++/qmake.conf +++ b/mkspecs/freebsd-g++/qmake.conf @@ -5,7 +5,7 @@ MAKEFILE_GENERATOR = UNIX TARGET_PLATFORM = unix TEMPLATE = app -CONFIG += qt warn_on release link_prl +CONFIG += qt warn_on release link_prl gdb_dwarf_index QT += core gui QMAKE_CFLAGS_THREAD = -pthread -D_THREAD_SAFE @@ -28,7 +28,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = diff --git a/mkspecs/freebsd-g++34/qmake.conf b/mkspecs/freebsd-g++34/qmake.conf index 810efab..0f52993 100644 --- a/mkspecs/freebsd-g++34/qmake.conf +++ b/mkspecs/freebsd-g++34/qmake.conf @@ -63,7 +63,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = diff --git a/mkspecs/freebsd-g++40/qmake.conf b/mkspecs/freebsd-g++40/qmake.conf index 4b0ac4c..bf42711 100644 --- a/mkspecs/freebsd-g++40/qmake.conf +++ b/mkspecs/freebsd-g++40/qmake.conf @@ -5,7 +5,7 @@ MAKEFILE_GENERATOR = UNIX TARGET_PLATFORM = unix TEMPLATE = app -CONFIG += qt warn_on release link_prl +CONFIG += qt warn_on release link_prl gdb_dwarf_index QT += core gui QMAKE_CC = gcc40 @@ -63,7 +63,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = diff --git a/mkspecs/freebsd-icc/qmake.conf b/mkspecs/freebsd-icc/qmake.conf index 99d6126..acc8f14 100644 --- a/mkspecs/freebsd-icc/qmake.conf +++ b/mkspecs/freebsd-icc/qmake.conf @@ -86,7 +86,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = diff --git a/mkspecs/hpux-acc-64/qmake.conf b/mkspecs/hpux-acc-64/qmake.conf index 38c8555..b9aaf5a 100644 --- a/mkspecs/hpux-acc-64/qmake.conf +++ b/mkspecs/hpux-acc-64/qmake.conf @@ -106,7 +106,7 @@ QMAKE_LIBS = -lm QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL -lXt +QMAKE_LIBS_OPENGL = -lGL -lXt QMAKE_LIBS_OPENGL_QT = -lGL -lXt QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly diff --git a/mkspecs/hpux-acc-o64/qmake.conf b/mkspecs/hpux-acc-o64/qmake.conf index 630129c..389e813 100644 --- a/mkspecs/hpux-acc-o64/qmake.conf +++ b/mkspecs/hpux-acc-o64/qmake.conf @@ -104,7 +104,7 @@ QMAKE_LIBS_DYNLOAD = -ldld QMAKE_LIBS_X11 = -lXext -lX11 QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly diff --git a/mkspecs/hpux-acc/qmake.conf b/mkspecs/hpux-acc/qmake.conf index 1c732c6..d1b6e5c 100644 --- a/mkspecs/hpux-acc/qmake.conf +++ b/mkspecs/hpux-acc/qmake.conf @@ -85,7 +85,7 @@ QMAKE_LIBS = -lm QMAKE_LIBS_DYNLOAD = -ldld QMAKE_LIBS_X11 = -lXext -lX11 QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL -lXt +QMAKE_LIBS_OPENGL = -lGL -lXt QMAKE_LIBS_OPENGL_QT = -lGL -lXt QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly diff --git a/mkspecs/hpux-g++-64/qmake.conf b/mkspecs/hpux-g++-64/qmake.conf index d8b0a4a..f796496 100644 --- a/mkspecs/hpux-g++-64/qmake.conf +++ b/mkspecs/hpux-g++-64/qmake.conf @@ -68,7 +68,7 @@ QMAKE_LIBS = -lm QMAKE_LIBS_DYNLOAD = -ldld QMAKE_LIBS_X11 = -lXext -lX11 QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly diff --git a/mkspecs/hpux-g++/qmake.conf b/mkspecs/hpux-g++/qmake.conf index 312c44b..e9891e7 100644 --- a/mkspecs/hpux-g++/qmake.conf +++ b/mkspecs/hpux-g++/qmake.conf @@ -68,7 +68,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = -ldld QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly diff --git a/mkspecs/hpuxi-acc-32/qmake.conf b/mkspecs/hpuxi-acc-32/qmake.conf index a26cb32..d7e4a0a 100644 --- a/mkspecs/hpuxi-acc-32/qmake.conf +++ b/mkspecs/hpuxi-acc-32/qmake.conf @@ -60,7 +60,7 @@ QMAKE_LIBS = -lm QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL -lXt +QMAKE_LIBS_OPENGL = -lGL -lXt QMAKE_LIBS_OPENGL_QT = -lGL -lXt QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly diff --git a/mkspecs/hpuxi-acc-64/qmake.conf b/mkspecs/hpuxi-acc-64/qmake.conf index 3e2d59f..3ed9b55 100644 --- a/mkspecs/hpuxi-acc-64/qmake.conf +++ b/mkspecs/hpuxi-acc-64/qmake.conf @@ -103,7 +103,7 @@ QMAKE_LIBS = -lm QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL -lXt +QMAKE_LIBS_OPENGL = -lGL -lXt QMAKE_LIBS_OPENGL_QT = -lGL -lXt QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly diff --git a/mkspecs/hpuxi-g++-64/qmake.conf b/mkspecs/hpuxi-g++-64/qmake.conf index 3151d85..a8f445c 100644 --- a/mkspecs/hpuxi-g++-64/qmake.conf +++ b/mkspecs/hpuxi-g++-64/qmake.conf @@ -71,7 +71,7 @@ QMAKE_LIBS = -lm QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly diff --git a/mkspecs/hurd-g++/qmake.conf b/mkspecs/hurd-g++/qmake.conf index 6570e40..d89f2e4 100644 --- a/mkspecs/hurd-g++/qmake.conf +++ b/mkspecs/hurd-g++/qmake.conf @@ -67,7 +67,7 @@ QMAKE_LIBS_NIS = -lnsl QMAKE_LIBS_QT_THREAD = -lqt-mt QMAKE_LIBS_THREAD = -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_MOC = $$[QT_INSTALL_BINS]/moc diff --git a/mkspecs/irix-cc-64/qmake.conf b/mkspecs/irix-cc-64/qmake.conf index b8d316e..ec94824 100644 --- a/mkspecs/irix-cc-64/qmake.conf +++ b/mkspecs/irix-cc-64/qmake.conf @@ -94,7 +94,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL -lm +QMAKE_LIBS_OPENGL = -lGL -lm QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread diff --git a/mkspecs/irix-cc/qmake.conf b/mkspecs/irix-cc/qmake.conf index 2f4f03f..777da9b 100644 --- a/mkspecs/irix-cc/qmake.conf +++ b/mkspecs/irix-cc/qmake.conf @@ -94,7 +94,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL -lm +QMAKE_LIBS_OPENGL = -lGL -lm QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread diff --git a/mkspecs/irix-g++-64/qmake.conf b/mkspecs/irix-g++-64/qmake.conf index 610d92c..aa853de 100644 --- a/mkspecs/irix-g++-64/qmake.conf +++ b/mkspecs/irix-g++-64/qmake.conf @@ -67,7 +67,7 @@ QMAKE_LIBS_X11SM = -lSM -lICE # libGLU is using the SGI C++ library internally and this somehow clashes # with the GNU C++ library (similar name mangling and symbol names?) # so we add -lC so that the SGI C++ library is used first... -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread diff --git a/mkspecs/irix-g++/qmake.conf b/mkspecs/irix-g++/qmake.conf index 41841f3..77d47a9 100644 --- a/mkspecs/irix-g++/qmake.conf +++ b/mkspecs/irix-g++/qmake.conf @@ -67,7 +67,7 @@ QMAKE_LIBS_X11SM = -lSM -lICE # libGLU is using the SGI C++ library internally and this somehow clashes # with the GNU C++ library (similar name mangling and symbol names?) # so we add -lC so that the SGI C++ library is used first... -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread diff --git a/mkspecs/linux-cxx/qmake.conf b/mkspecs/linux-cxx/qmake.conf index 879c78a..ce303b7 100644 --- a/mkspecs/linux-cxx/qmake.conf +++ b/mkspecs/linux-cxx/qmake.conf @@ -60,7 +60,7 @@ QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_NIS = -lnsl -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_MOC = $$[QT_INSTALL_BINS]/moc diff --git a/mkspecs/linux-ecc-64/qmake.conf b/mkspecs/linux-ecc-64/qmake.conf index aa50b87..61a056b 100644 --- a/mkspecs/linux-ecc-64/qmake.conf +++ b/mkspecs/linux-ecc-64/qmake.conf @@ -63,7 +63,7 @@ QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_NIS = -lnsl -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread diff --git a/mkspecs/linux-g++-32/qmake.conf b/mkspecs/linux-g++-32/qmake.conf index 1e5c50b..f425c0d 100644 --- a/mkspecs/linux-g++-32/qmake.conf +++ b/mkspecs/linux-g++-32/qmake.conf @@ -5,7 +5,7 @@ MAKEFILE_GENERATOR = UNIX TARGET_PLATFORM = unix TEMPLATE = app -CONFIG += qt warn_on release incremental link_prl +CONFIG += qt warn_on release incremental link_prl gdb_dwarf_index QT += core gui QMAKE_INCREMENTAL_STYLE = sublib diff --git a/mkspecs/linux-g++-64/qmake.conf b/mkspecs/linux-g++-64/qmake.conf index e7372cc..b8877a9 100644 --- a/mkspecs/linux-g++-64/qmake.conf +++ b/mkspecs/linux-g++-64/qmake.conf @@ -8,7 +8,7 @@ MAKEFILE_GENERATOR = UNIX TARGET_PLATFORM = unix TEMPLATE = app -CONFIG += qt warn_on release incremental link_prl +CONFIG += qt warn_on release incremental link_prl gdb_dwarf_index QT += core gui QMAKE_INCREMENTAL_STYLE = sublib diff --git a/mkspecs/linux-g++-maemo/qmake.conf b/mkspecs/linux-g++-maemo/qmake.conf index a977e7a..8f85c54 100644 --- a/mkspecs/linux-g++-maemo/qmake.conf +++ b/mkspecs/linux-g++-maemo/qmake.conf @@ -5,7 +5,7 @@ MAKEFILE_GENERATOR = UNIX TARGET_PLATFORM = unix TEMPLATE = app -CONFIG += qt warn_on release incremental link_prl +CONFIG += qt warn_on release incremental link_prl gdb_dwarf_index CONFIG += nostrip QT += core gui QMAKE_INCREMENTAL_STYLE = sublib diff --git a/mkspecs/linux-g++/qmake.conf b/mkspecs/linux-g++/qmake.conf index 4b21896..d772b5e 100644 --- a/mkspecs/linux-g++/qmake.conf +++ b/mkspecs/linux-g++/qmake.conf @@ -5,7 +5,7 @@ MAKEFILE_GENERATOR = UNIX TARGET_PLATFORM = unix TEMPLATE = app -CONFIG += qt warn_on release incremental link_prl +CONFIG += qt warn_on release incremental link_prl gdb_dwarf_index QT += core gui QMAKE_INCREMENTAL_STYLE = sublib diff --git a/mkspecs/linux-icc/qmake.conf b/mkspecs/linux-icc/qmake.conf index 3b26f7d..f40a465 100644 --- a/mkspecs/linux-icc/qmake.conf +++ b/mkspecs/linux-icc/qmake.conf @@ -13,7 +13,7 @@ MAKEFILE_GENERATOR = UNIX TARGET_PLATFORM = unix TEMPLATE = app -CONFIG += qt warn_on release link_prl +CONFIG += qt warn_on release link_prl gdb_dwarf_index QT += core gui QMAKE_CC = icc @@ -70,7 +70,7 @@ QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_NIS = -lnsl -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread diff --git a/mkspecs/linux-kcc/qmake.conf b/mkspecs/linux-kcc/qmake.conf index 5c6001c..01e3b73 100644 --- a/mkspecs/linux-kcc/qmake.conf +++ b/mkspecs/linux-kcc/qmake.conf @@ -72,7 +72,7 @@ QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_NIS = -lnsl -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = diff --git a/mkspecs/linux-llvm/qmake.conf b/mkspecs/linux-llvm/qmake.conf index 73d6609..77f8d81 100644 --- a/mkspecs/linux-llvm/qmake.conf +++ b/mkspecs/linux-llvm/qmake.conf @@ -5,7 +5,7 @@ MAKEFILE_GENERATOR = UNIX TARGET_PLATFORM = unix TEMPLATE = app -CONFIG += qt warn_on release incremental link_prl +CONFIG += qt warn_on release incremental link_prl gdb_dwarf_index QT += core gui QMAKE_INCREMENTAL_STYLE = sublib diff --git a/mkspecs/linux-lsb-g++/qmake.conf b/mkspecs/linux-lsb-g++/qmake.conf index d359625..4197db0 100644 --- a/mkspecs/linux-lsb-g++/qmake.conf +++ b/mkspecs/linux-lsb-g++/qmake.conf @@ -5,7 +5,7 @@ MAKEFILE_GENERATOR = UNIX TARGET_PLATFORM = unix TEMPLATE = app -CONFIG += qt warn_on release incremental link_prl +CONFIG += qt warn_on release incremental link_prl gdb_dwarf_index QT += core gui QMAKE_INCREMENTAL_STYLE = sublib diff --git a/mkspecs/linux-pgcc/qmake.conf b/mkspecs/linux-pgcc/qmake.conf index 16d0023..63ede78 100644 --- a/mkspecs/linux-pgcc/qmake.conf +++ b/mkspecs/linux-pgcc/qmake.conf @@ -63,7 +63,7 @@ QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_NIS = -lnsl -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread diff --git a/mkspecs/lynxos-g++/qmake.conf b/mkspecs/lynxos-g++/qmake.conf index fc0fc43..6b6f405 100644 --- a/mkspecs/lynxos-g++/qmake.conf +++ b/mkspecs/lynxos-g++/qmake.conf @@ -66,7 +66,7 @@ QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_NIS = -lnsl -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread diff --git a/mkspecs/netbsd-g++/qmake.conf b/mkspecs/netbsd-g++/qmake.conf index 1d3fd2b..ab4b7c3 100644 --- a/mkspecs/netbsd-g++/qmake.conf +++ b/mkspecs/netbsd-g++/qmake.conf @@ -5,7 +5,7 @@ MAKEFILE_GENERATOR = UNIX TARGET_PLATFORM = unix TEMPLATE = app -CONFIG += qt warn_on release link_prl +CONFIG += qt warn_on release link_prl gdb_dwarf_index QT += core gui QMAKE_CC = gcc @@ -64,7 +64,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = diff --git a/mkspecs/openbsd-g++/qmake.conf b/mkspecs/openbsd-g++/qmake.conf index c948c90..56d9416 100644 --- a/mkspecs/openbsd-g++/qmake.conf +++ b/mkspecs/openbsd-g++/qmake.conf @@ -5,7 +5,7 @@ MAKEFILE_GENERATOR = UNIX TARGET_PLATFORM = unix TEMPLATE = app -CONFIG += qt warn_on release link_prl +CONFIG += qt warn_on release link_prl gdb_dwarf_index QT += core gui QMAKE_CC = gcc @@ -65,7 +65,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = diff --git a/mkspecs/sco-cc/qmake.conf b/mkspecs/sco-cc/qmake.conf index 6eb5ca1..179b774 100644 --- a/mkspecs/sco-cc/qmake.conf +++ b/mkspecs/sco-cc/qmake.conf @@ -60,7 +60,7 @@ QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lresolv -lsocket -lnsl -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL -lXt +QMAKE_LIBS_OPENGL = -lGL -lXt QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_MOC = $$[QT_INSTALL_BINS]/moc diff --git a/mkspecs/sco-g++/qmake.conf b/mkspecs/sco-g++/qmake.conf index d4091ff..9b321a4 100644 --- a/mkspecs/sco-g++/qmake.conf +++ b/mkspecs/sco-g++/qmake.conf @@ -61,7 +61,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lsocket -lm -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_MOC = $$[QT_INSTALL_BINS]/moc diff --git a/mkspecs/solaris-cc-64/qmake.conf b/mkspecs/solaris-cc-64/qmake.conf index a026756..80709af 100644 --- a/mkspecs/solaris-cc-64/qmake.conf +++ b/mkspecs/solaris-cc-64/qmake.conf @@ -83,7 +83,7 @@ QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lresolv -lsocket -lnsl QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_NIS = -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -lrt QMAKE_LIBS_NETWORK = -lresolv -lsocket -lxnet -lnsl diff --git a/mkspecs/solaris-cc/qmake.conf b/mkspecs/solaris-cc/qmake.conf index 8a8f1ac..0672841 100644 --- a/mkspecs/solaris-cc/qmake.conf +++ b/mkspecs/solaris-cc/qmake.conf @@ -66,7 +66,7 @@ QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lresolv -lsocket -lnsl QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_NIS = -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -lrt QMAKE_LIBS_NETWORK = -lresolv -lsocket -lxnet -lnsl diff --git a/mkspecs/solaris-g++-64/qmake.conf b/mkspecs/solaris-g++-64/qmake.conf index 01e331c..7bc7b9f 100644 --- a/mkspecs/solaris-g++-64/qmake.conf +++ b/mkspecs/solaris-g++-64/qmake.conf @@ -87,7 +87,7 @@ QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lresolv -lsocket -lnsl QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_NIS = -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -lrt QMAKE_LIBS_NETWORK = -lresolv -lsocket -lxnet -lnsl diff --git a/mkspecs/solaris-g++/qmake.conf b/mkspecs/solaris-g++/qmake.conf index c7f6406..be21cdd 100644 --- a/mkspecs/solaris-g++/qmake.conf +++ b/mkspecs/solaris-g++/qmake.conf @@ -70,7 +70,7 @@ QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lresolv -lsocket -lnsl QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_NIS = -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -lrt QMAKE_LIBS_NETWORK = -lresolv -lsocket -lxnet -lnsl diff --git a/mkspecs/tru64-cxx/qmake.conf b/mkspecs/tru64-cxx/qmake.conf index d2c6937..afabf3e 100644 --- a/mkspecs/tru64-cxx/qmake.conf +++ b/mkspecs/tru64-cxx/qmake.conf @@ -60,7 +60,7 @@ QMAKE_LIBS = -lm QMAKE_LIBS_DYNLOAD = QMAKE_LIBS_X11 = -lXext -lX11 QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lrt diff --git a/mkspecs/tru64-g++/qmake.conf b/mkspecs/tru64-g++/qmake.conf index f2b8e39..6acd5cd 100644 --- a/mkspecs/tru64-g++/qmake.conf +++ b/mkspecs/tru64-g++/qmake.conf @@ -62,7 +62,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -lexc -lrt diff --git a/mkspecs/unixware-cc/qmake.conf b/mkspecs/unixware-cc/qmake.conf index 5f88b80..74478d6 100644 --- a/mkspecs/unixware-cc/qmake.conf +++ b/mkspecs/unixware-cc/qmake.conf @@ -64,7 +64,7 @@ QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lresolv -lsocket -lnsl -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL -lXt +QMAKE_LIBS_OPENGL = -lGL -lXt QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = diff --git a/mkspecs/unixware-g++/qmake.conf b/mkspecs/unixware-g++/qmake.conf index 34d6d61..a158d95 100644 --- a/mkspecs/unixware-g++/qmake.conf +++ b/mkspecs/unixware-g++/qmake.conf @@ -64,7 +64,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lresolv -lsocket -lnsl -lm QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL -lXt +QMAKE_LIBS_OPENGL = -lGL -lXt QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lthread diff --git a/mkspecs/unsupported/linux-host-g++/qmake.conf b/mkspecs/unsupported/linux-host-g++/qmake.conf index 38849f8..46ecf37 100644 --- a/mkspecs/unsupported/linux-host-g++/qmake.conf +++ b/mkspecs/unsupported/linux-host-g++/qmake.conf @@ -101,7 +101,7 @@ QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_NIS = -lnsl QMAKE_LIBS_EGL = -lEGL -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_OPENGL_ES1 = -lGLES_CM QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 diff --git a/mkspecs/unsupported/qnx-g++/qmake.conf b/mkspecs/unsupported/qnx-g++/qmake.conf index 37e7bce..dfe9bed 100644 --- a/mkspecs/unsupported/qnx-g++/qmake.conf +++ b/mkspecs/unsupported/qnx-g++/qmake.conf @@ -31,7 +31,7 @@ QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = QMAKE_LIBS_X11 = -lXext -lX11 -lm -lsocket QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = QMAKE_LIBS_NETWORK = -lsocket diff --git a/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf b/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf index e3eb6cd..a3b571b 100644 --- a/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf +++ b/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf @@ -78,7 +78,7 @@ QMAKE_LIBS_DYNLOAD = QMAKE_LIBS_X11 = -lXext -lX11 QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_NIS = -lnsl -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = QMAKE_LIBS_NETWORK = # -lnetwrap # only needed if kernel is missing gethostbyname and friends diff --git a/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf b/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf index d0aeff6..8bdf1c5 100644 --- a/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf +++ b/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf @@ -78,7 +78,7 @@ QMAKE_LIBS_DYNLOAD = QMAKE_LIBS_X11 = -lXext -lX11 QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_NIS = -lnsl -QMAKE_LIBS_OPENGL = -lGLU -lGL +QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = QMAKE_LIBS_NETWORK = # -lnet # only needed if kernel is missing gethostbyname and friends diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index 8d56fc8..561cd0a 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -71,7 +71,7 @@ CPPFLAGS = -I. -Igenerators -Igenerators/unix -Igenerators/win32 -Igenerators/ma -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED \ -DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_NO_COMPONENT -DQT_NO_STL \ -DQT_NO_COMPRESS -I$(QMAKESPEC) -DHAVE_QCONFIG_CPP -DQT_NO_THREAD -DQT_NO_QOBJECT \ - -DQT_NO_GEOM_VARIANT $(OPENSOURCE_CXXFLAGS) + -DQT_NO_GEOM_VARIANT -DQT_NO_DEPRECATED $(OPENSOURCE_CXXFLAGS) CXXFLAGS = @QMAKE_CXXFLAGS@ $(CPPFLAGS) diff --git a/qmake/cachekeys.h b/qmake/cachekeys.h index 63bd224..c5c1631 100644 --- a/qmake/cachekeys.h +++ b/qmake/cachekeys.h @@ -166,12 +166,9 @@ struct FileFixifyCacheKey inline uint qHash(const FileFixifyCacheKey &f) { return f.hashCode(); } // ------------------------------------------------------------------------------------------------- -// As MSVC 6.0 can't handle template functions that well, we need a separate function for each type -inline void qmakeDeleteCacheClear_QMapStringInt(void *i) { delete reinterpret_cast<QMap<QString,int> *>(i); } -inline void qmakeDeleteCacheClear_QStringList(void *i) { delete reinterpret_cast<QStringList *>(i); } -inline void qmakeDeleteCacheClear_QHashFixStringCacheKeyQString(void *i) { delete reinterpret_cast<QHash<FixStringCacheKey, QString> *>(i); } -inline void qmakeDeleteCacheClear_QHashFileInfoCacheKeyQFileInfo(void *i) { delete reinterpret_cast<QHash<FileInfoCacheKey, QFileInfo> *>(i); } -inline void qmakeDeleteCacheClear_QHashFileFixifyCacheKeyQString(void *i) { delete reinterpret_cast<QHash<FileFixifyCacheKey, QString> *>(i); } +template <typename T> +inline void qmakeDeleteCacheClear(void *i) { delete reinterpret_cast<T*>(i); } + inline void qmakeFreeCacheClear(void *i) { free(i); } typedef void (*qmakeCacheClearFunc)(void *); diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 3cb1942..9579ae4 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -2738,7 +2738,7 @@ MakefileGenerator::fileInfo(QString file) const static QFileInfo noInfo = QFileInfo(); if(!cache) { cache = new QHash<FileInfoCacheKey, QFileInfo>; - qmakeAddCacheClear(qmakeDeleteCacheClear_QHashFileInfoCacheKeyQFileInfo, (void**)&cache); + qmakeAddCacheClear(qmakeDeleteCacheClear<QHash<FileInfoCacheKey, QFileInfo> >, (void**)&cache); } FileInfoCacheKey cacheKey(file); QFileInfo value = cache->value(cacheKey, noInfo); @@ -2817,7 +2817,7 @@ MakefileGenerator::fileFixify(const QString& file, const QString &out_d, const Q static QHash<FileFixifyCacheKey, QString> *cache = 0; if(!cache) { cache = new QHash<FileFixifyCacheKey, QString>; - qmakeAddCacheClear(qmakeDeleteCacheClear_QHashFileFixifyCacheKeyQString, (void**)&cache); + qmakeAddCacheClear(qmakeDeleteCacheClear<QHash<FileFixifyCacheKey, QString> >, (void**)&cache); } FileFixifyCacheKey cacheKey(ret, out_d, in_d, fix, canon); QString cacheVal = cache->value(cacheKey); diff --git a/qmake/generators/symbian/symbiancommon.cpp b/qmake/generators/symbian/symbiancommon.cpp index a60ae07..0da06af 100644 --- a/qmake/generators/symbian/symbiancommon.cpp +++ b/qmake/generators/symbian/symbiancommon.cpp @@ -197,44 +197,71 @@ void SymbianCommonGenerator::generatePkgFile(const QString &iconFile, bool epocB tw << headerComment.arg(wrapperPkgFilename).arg(dateStr); ts << headerComment.arg(stubPkgFileName).arg(dateStr); - // Construct QStringList from pkg_prerules since we need search it before printed to file - // Note: Though there can't be more than one language or header line, use stringlists + QStringList commonRawPreRules; + QStringList mainRawPreRules; + QStringList instRawPreRules; + QStringList stubRawPreRules; + + // Though there can't be more than one language or header line, use stringlists // in case user wants comments to go with the rules. - QStringList rawPkgPreRules; + // Note that it makes no sense to have file specific language or header rules, + // except what is provided for installer header via "DEPLOYMENT.installer_header" variable, + // because stub and main headers should always match. Vendor rules are similarly limited to + // make code cleaner as it is unlikely anyone will want different vendor in different files. QStringList languageRules; QStringList headerRules; - foreach(QString deploymentItem, project->values("DEPLOYMENT")) { - foreach(QString pkgrulesItem, project->values(deploymentItem + ".pkg_prerules")) { - QStringList pkgrulesValue = project->values(pkgrulesItem); - // If there is no stringlist defined for a rule, use rule name directly - // This is convenience for defining single line mmp statements - if (pkgrulesValue.isEmpty()) { - if (pkgrulesItem.startsWith("&")) - languageRules << pkgrulesItem; - else if (pkgrulesItem.startsWith("#")) - headerRules << pkgrulesItem; - else - rawPkgPreRules << pkgrulesItem; - } else { - if (containsStartWithItem('&', pkgrulesValue)) { - foreach(QString pkgrule, pkgrulesValue) { - languageRules << pkgrule; - } - } else if (containsStartWithItem('#', pkgrulesValue)) { - foreach(QString pkgrule, pkgrulesValue) { - headerRules << pkgrule; - } - } else { - foreach(QString pkgrule, pkgrulesValue) { - rawPkgPreRules << pkgrule; - } - } - } + QStringList vendorRules; + + QStringList commonRawPostRules; + QStringList mainRawPostRules; + QStringList instRawPostRules; + QStringList stubRawPostRules; + + QStringList failList; // Used for detecting incorrect usage + + QString emptySuffix; + QString mainSuffix(".main"); + QString instSuffix(".installer"); + QString stubSuffix(".stub"); + + foreach(QString item, project->values("DEPLOYMENT")) { + parsePreRules(item, emptySuffix, &commonRawPreRules, &languageRules, &headerRules, &vendorRules); + parsePreRules(item, mainSuffix, &mainRawPreRules, &failList, &failList, &failList); + parsePreRules(item, instSuffix, &instRawPreRules, &failList, &failList, &failList); + parsePreRules(item, stubSuffix, &stubRawPreRules, &failList, &failList, &failList); + + parsePostRules(item, emptySuffix, &commonRawPostRules); + parsePostRules(item, mainSuffix, &mainRawPostRules); + parsePostRules(item, instSuffix, &instRawPostRules); + parsePostRules(item, stubSuffix, &stubRawPostRules); + } + + if (!failList.isEmpty()) { + fprintf(stderr, "Warning: Custom language, header, or vendor definitions are not " + "supported by file specific pkg_prerules.* variables.\n" + "Use plain pkg_prerules and/or DEPLOYMENT.installer_header for customizing " + "these items.\n"); + } + + foreach(QString item, commonRawPreRules) { + if (item.startsWith("(")) { + // Only regular pkg file should have package dependencies + mainRawPreRules << item; + } else if (item.startsWith("[")) { + // stub pkg file should not have platform dependencies + mainRawPreRules << item; + instRawPreRules << item; + } else { + mainRawPreRules << item; + instRawPreRules << item; + stubRawPreRules << item; } } - // Apply some defaults if specific data does not exist in PKG pre-rules + // Currently common postrules only go to main + mainRawPostRules << commonRawPostRules; + // Apply some defaults if specific data does not exist in PKG pre-rules if (languageRules.isEmpty()) { // language, (*** hardcoded to english atm, should be parsed from TRANSLATIONS) languageRules << "; Language\n&EN\n\n"; @@ -306,49 +333,38 @@ void SymbianCommonGenerator::generatePkgFile(const QString &iconFile, bool epocB ts << headerRules.join("\n") << endl; } - // Localized vendor name - QString vendorName; - if (!containsStartWithItem('%', rawPkgPreRules)) { - vendorName += "; Localised Vendor name\n%{\"Vendor\"}\n\n"; + // Vendor name + if (!containsStartWithItem('%', vendorRules)) { + vendorRules << "; Default localized vendor name\n%{\"Vendor\"}\n\n"; } - - // Unique vendor name - if (!containsStartWithItem(':', rawPkgPreRules)) { - vendorName += "; Unique Vendor name\n:\"Vendor\"\n\n"; + if (!containsStartWithItem(':', vendorRules)) { + vendorRules << "; Default unique vendor name\n:\"Vendor\"\n\n"; } - t << vendorName; - tw << vendorName; - ts << vendorName; + t << vendorRules.join("\n") << endl; + tw << vendorRules.join("\n") << endl; + ts << vendorRules.join("\n") << endl; // PKG pre-rules - these are added before actual file installations i.e. SIS package body - if (rawPkgPreRules.size()) { - QString comment = "\n; Manual PKG pre-rules from PRO files\n"; + QString comment = "\n; Manual PKG pre-rules from PRO files\n"; + + if (mainRawPreRules.size()) { t << comment; + t << mainRawPreRules.join("\n") << endl; + } + if (instRawPreRules.size()) { tw << comment; + tw << instRawPreRules.join("\n") << endl; + } + if (stubRawPreRules.size()) { ts << comment; - - foreach(QString item, rawPkgPreRules) { - // Only regular pkg file should have package dependencies - if (item.startsWith("(")) { - t << item << endl; - } - // stub pkg file should not have platform dependencies - else if (item.startsWith("[")) { - t << item << endl; - tw << item << endl; - } - else { - t << item << endl; - ts << item << endl; - tw << item << endl; - } - } - t << endl; - ts << endl; - tw << endl; + ts << stubRawPreRules.join("\n") << endl; } + t << endl; + tw << endl; + ts << endl; + // Begin Manufacturer block if (!project->values("DEPLOYMENT.manufacturers").isEmpty()) { QString manufacturerStr("IF "); @@ -474,21 +490,19 @@ void SymbianCommonGenerator::generatePkgFile(const QString &iconFile, bool epocB ts << endl; // PKG post-rules - these are added after actual file installations i.e. SIS package body - t << "; Manual PKG post-rules from PRO files" << endl; - foreach(QString deploymentItem, project->values("DEPLOYMENT")) { - foreach(QString pkgrulesItem, project->values(deploymentItem + ".pkg_postrules")) { - QStringList pkgrulesValue = project->values(pkgrulesItem); - // If there is no stringlist defined for a rule, use rule name directly - // This is convenience for defining single line statements - if (pkgrulesValue.isEmpty()) { - t << pkgrulesItem << endl; - } else { - foreach(QString pkgrule, pkgrulesValue) { - t << pkgrule << endl; - } - } - t << endl; - } + comment = "; Manual PKG post-rules from PRO files\n"; + + if (mainRawPostRules.size()) { + t << comment; + t << mainRawPostRules.join("\n") << endl; + } + if (instRawPostRules.size()) { + tw << comment; + tw << instRawPostRules.join("\n") << endl; + } + if (stubRawPostRules.size()) { + ts << comment; + ts << stubRawPostRules.join("\n") << endl; } // Close Manufacturer block @@ -1030,3 +1044,66 @@ void SymbianCommonGenerator::fillQt2S60LangMapTable() qt2S60LangMapTable.insert("ny", "SC"); //Chewa // } +void SymbianCommonGenerator::parsePreRules(const QString &deploymentVariable, + const QString &variableSuffix, + QStringList *rawRuleList, + QStringList *languageRuleList, + QStringList *headerRuleList, + QStringList *vendorRuleList) +{ + QMakeProject *project = generator->project; + foreach(QString pkgrulesItem, project->values(deploymentVariable + ".pkg_prerules" + variableSuffix)) { + QStringList pkgrulesValue = project->values(pkgrulesItem); + // If there is no stringlist defined for a rule, use rule name directly + // This is convenience for defining single line statements + if (pkgrulesValue.isEmpty()) { + if (pkgrulesItem.startsWith("&")) + *languageRuleList << pkgrulesItem; + else if (pkgrulesItem.startsWith("#")) + *headerRuleList << pkgrulesItem; + else if (pkgrulesItem.startsWith("%") || pkgrulesItem.startsWith(":")) + *vendorRuleList << pkgrulesItem; + else + *rawRuleList << pkgrulesItem; + } else { + if (containsStartWithItem('&', pkgrulesValue)) { + foreach(QString pkgrule, pkgrulesValue) { + *languageRuleList << pkgrule; + } + } else if (containsStartWithItem('#', pkgrulesValue)) { + foreach(QString pkgrule, pkgrulesValue) { + *headerRuleList << pkgrule; + } + } else if (containsStartWithItem('%', pkgrulesValue) + || containsStartWithItem(':', pkgrulesValue)) { + foreach(QString pkgrule, pkgrulesValue) { + *vendorRuleList << pkgrule; + } + } else { + foreach(QString pkgrule, pkgrulesValue) { + *rawRuleList << pkgrule; + } + } + } + } +} + +void SymbianCommonGenerator::parsePostRules(const QString &deploymentVariable, + const QString &variableSuffix, + QStringList *rawRuleList) +{ + QMakeProject *project = generator->project; + foreach(QString pkgrulesItem, project->values(deploymentVariable + ".pkg_postrules" + variableSuffix)) { + QStringList pkgrulesValue = project->values(pkgrulesItem); + // If there is no stringlist defined for a rule, use rule name directly + // This is convenience for defining single line statements + if (pkgrulesValue.isEmpty()) { + *rawRuleList << pkgrulesItem; + } else { + foreach(QString pkgrule, pkgrulesValue) { + *rawRuleList << pkgrule; + } + } + } +} + diff --git a/qmake/generators/symbian/symbiancommon.h b/qmake/generators/symbian/symbiancommon.h index dae1e4a..80f2079 100644 --- a/qmake/generators/symbian/symbiancommon.h +++ b/qmake/generators/symbian/symbiancommon.h @@ -86,6 +86,17 @@ protected: QStringList symbianLangCodesFromTsFiles(); void fillQt2S60LangMapTable(); + void parsePreRules(const QString &deploymentVariable, + const QString &variableSuffix, + QStringList *rawRuleList, + QStringList *languageRuleList, + QStringList *headerRuleList, + QStringList *vendorRuleList); + void parsePostRules(const QString &deploymentVariable, + const QString &variableSuffix, + QStringList *rawRuleList); + + protected: MakefileGenerator *generator; diff --git a/qmake/generators/symbian/symmake.cpp b/qmake/generators/symbian/symmake.cpp index 0b0033a..09a3fc8 100644 --- a/qmake/generators/symbian/symmake.cpp +++ b/qmake/generators/symbian/symmake.cpp @@ -707,25 +707,13 @@ void SymbianMakefileGenerator::writeMmpFileLibraryPart(QTextStream& t) if (lib.startsWith("-l")) { lib.remove(0, 2); QString mmpStatement; - if (lib.endsWith(".dll")) { - lib.chop(4); - mmpStatement = "LIBRARY\t\t"; - } else if (lib.endsWith(".lib")) { + if (lib.endsWith(".lib")) { lib.chop(4); mmpStatement = "STATICLIBRARY\t"; } else { - // Hacky way to find out what kind of library it is. Check the - // ARMV5 build directory for library type. We default to shared - // library, since that is more common. - QString udebStaticLibLocation(epocRoot()); - QString urelStaticLibLocation(udebStaticLibLocation); - udebStaticLibLocation += QString("epoc32/release/armv5/udeb/%1.lib").arg(lib); - urelStaticLibLocation += QString("epoc32/release/armv5/urel/%1.lib").arg(lib); - if (QFile::exists(udebStaticLibLocation) || QFile::exists(urelStaticLibLocation)) { - mmpStatement = "STATICLIBRARY\t"; - } else { - mmpStatement = "LIBRARY\t\t"; - } + if (lib.endsWith(".dll")) + lib.chop(4); + mmpStatement = "LIBRARY\t\t"; } t << mmpStatement << lib << ".lib" << endl; } diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp index 2505056..a397ae9 100644 --- a/qmake/generators/win32/msbuild_objectmodel.cpp +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -50,26 +50,14 @@ QT_BEGIN_NAMESPACE // XML Tags --------------------------------------------------------- const char _CLCompile[] = "ClCompile"; -const char _Configuration[] = "Configuration"; -const char _Configurations[] = "Configurations"; -const char q_File[] = "File"; -const char _FileConfiguration[] = "FileConfiguration"; -const char q_Files[] = "Files"; -const char _Filter[] = "Filter"; -const char _Globals[] = "Globals"; const char _ItemGroup[] = "ItemGroup"; const char _Link[] = "Link"; const char _Midl[] = "Midl"; -const char _Platform[] = "Platform"; -const char _Platforms[] = "Platforms"; const char _ResourceCompile[] = "ResourceCompile"; -const char _Tool[] = "Tool"; -const char _VisualStudioProject[] = "VisualStudioProject"; // XML Properties --------------------------------------------------- const char _AddModuleNamesToAssembly[] = "AddModuleNamesToAssembly"; const char _AdditionalDependencies[] = "AdditionalDependencies"; -const char _AdditionalFiles[] = "AdditionalFiles"; const char _AdditionalIncludeDirectories[] = "AdditionalIncludeDirectories"; const char _AdditionalLibraryDirectories[] = "AdditionalLibraryDirectories"; const char _AdditionalManifestDependencies[] = "AdditionalManifestDependencies"; @@ -97,11 +85,8 @@ const char _CLRSupportLastError[] = "CLRSupportLastError"; const char _CLRThreadAttribute[] = "CLRThreadAttribute"; const char _CLRUnmanagedCodeCheck[] = "CLRUnmanagedCodeCheck"; const char _Command[] = "Command"; -const char _CommandLine[] = "CommandLine"; const char _CompileAs[] = "CompileAs"; const char _CompileAsManaged[] = "CompileAsManaged"; -const char _CompileForArchitecture[] = "CompileForArchitecture"; -const char _CompileOnly[] = "CompileOnly"; const char _ConfigurationType[] = "ConfigurationType"; const char _CPreprocessOptions[] = "CPreprocessOptions"; const char _CreateHotpatchableImage[] = "CreateHotpatchableImage"; @@ -109,26 +94,20 @@ const char _CreateHotPatchableImage[] = "CreateHotPatchableImage"; const char _Culture[] = "Culture"; const char _DataExecutionPrevention[] = "DataExecutionPrevention"; const char _DebugInformationFormat[] = "DebugInformationFormat"; -const char _DefaultCharIsUnsigned[] = "DefaultCharIsUnsigned"; const char _DefaultCharType[] = "DefaultCharType"; const char _DelayLoadDLLs[] = "DelayLoadDLLs"; const char _DelaySign[] = "DelaySign"; const char _DeleteExtensionsOnClean[] = "DeleteExtensionsOnClean"; -const char _Description[] = "Description"; -const char _Detect64BitPortabilityProblems[] = "Detect64BitPortabilityProblems"; const char _DisableLanguageExtensions[] = "DisableLanguageExtensions"; const char _DisableSpecificWarnings[] = "DisableSpecificWarnings"; const char _DisplayLibrary[] = "DisplayLibrary"; const char _DLLDataFileName[] = "DLLDataFileName"; -const char _Driver[] = "Driver"; const char _EmbedManagedResourceFile[] = "EmbedManagedResourceFile"; const char _EnableCOMDATFolding[] = "EnableCOMDATFolding"; const char _EnableUAC[] = "EnableUAC"; const char _EnableErrorChecks[] = "EnableErrorChecks"; const char _EnableEnhancedInstructionSet[] = "EnableEnhancedInstructionSet"; const char _EnableFiberSafeOptimizations[] = "EnableFiberSafeOptimizations"; -const char _EnableFunctionLevelLinking[] = "EnableFunctionLevelLinking"; -const char _EnableIntrinsicFunctions[] = "EnableIntrinsicFunctions"; const char _EnablePREfast[] = "EnablePREfast"; const char _EntryPointSymbol[] = "EntryPointSymbol"; const char _ErrorCheckAllocations[] = "ErrorCheckAllocations"; @@ -138,64 +117,50 @@ const char _ErrorCheckRefPointers[] = "ErrorCheckRefPointers"; const char _ErrorCheckStubData[] = "ErrorCheckStubData"; const char _ErrorReporting[] = "ErrorReporting"; const char _ExceptionHandling[] = "ExceptionHandling"; -const char _ExcludedFromBuild[] = "ExcludedFromBuild"; const char _ExpandAttributedSource[] = "ExpandAttributedSource"; const char _ExportNamedFunctions[] = "ExportNamedFunctions"; const char _FavorSizeOrSpeed[] = "FavorSizeOrSpeed"; -const char _FixedBaseAddress[] = "FixedBaseAddress"; const char _FloatingPointModel[] = "FloatingPointModel"; const char _FloatingPointExceptions[] = "FloatingPointExceptions"; const char _ForceConformanceInForLoopScope[] = "ForceConformanceInForLoopScope"; -const char _ForceFileOutput[] = "ForceFileOutput"; const char _ForceSymbolReferences[] = "ForceSymbolReferences"; const char _ForcedIncludeFiles[] = "ForcedIncludeFiles"; const char _ForcedUsingFiles[] = "ForcedUsingFiles"; -const char _FullIncludePath[] = "FullIncludePath"; const char _FunctionLevelLinking[] = "FunctionLevelLinking"; const char _FunctionOrder[] = "FunctionOrder"; const char _GenerateClientFiles[] = "GenerateClientFiles"; const char _GenerateDebugInformation[] = "GenerateDebugInformation"; const char _GenerateManifest[] = "GenerateManifest"; const char _GenerateMapFile[] = "GenerateMapFile"; -const char _GeneratePreprocessedFile[] = "GeneratePreprocessedFile"; const char _GenerateServerFiles[] = "GenerateServerFiles"; const char _GenerateStublessProxies[] = "GenerateStublessProxies"; const char _GenerateTypeLibrary[] = "GenerateTypeLibrary"; const char _GenerateXMLDocumentationFiles[] = "GenerateXMLDocumentationFiles"; -const char _GlobalOptimizations[] = "GlobalOptimizations"; const char _HeaderFileName[] = "HeaderFileName"; const char _HeapCommitSize[] = "HeapCommitSize"; const char _HeapReserveSize[] = "HeapReserveSize"; const char _IgnoreAllDefaultLibraries[] = "IgnoreAllDefaultLibraries"; -const char _IgnoreDefaultLibraryNames[] = "IgnoreDefaultLibraryNames"; const char _IgnoreEmbeddedIDL[] = "IgnoreEmbeddedIDL"; const char _IgnoreImportLibrary[] = "IgnoreImportLibrary"; const char _IgnoreSpecificDefaultLibraries[] = "IgnoreSpecificDefaultLibraries"; const char _IgnoreStandardIncludePath[] = "IgnoreStandardIncludePath"; -const char _ImageHasSafeExceptionHandlers[] = "ImageHasSafeExceptionHandlers"; const char _ImportLibrary[] = "ImportLibrary"; -const char _ImproveFloatingPointConsistency[] = "ImproveFloatingPointConsistency"; const char _InlineFunctionExpansion[] = "InlineFunctionExpansion"; const char _IntrinsicFunctions[] = "IntrinsicFunctions"; const char _InterfaceIdentifierFileName[] = "InterfaceIdentifierFileName"; const char _IntermediateDirectory[] = "IntermediateDirectory"; -const char _InterworkCalls[] = "InterworkCalls"; const char _KeyContainer[] = "KeyContainer"; const char _KeyFile[] = "KeyFile"; -const char _Keyword[] = "Keyword"; -const char _KeepComments[] = "KeepComments"; const char _LargeAddressAware[] = "LargeAddressAware"; const char _LinkDLL[] = "LinkDLL"; const char _LinkErrorReporting[] = "LinkErrorReporting"; const char _LinkIncremental[] = "LinkIncremental"; const char _LinkStatus[] = "LinkStatus"; const char _LinkTimeCodeGeneration[] = "LinkTimeCodeGeneration"; -const char _LinkToManagedResourceFile[] = "LinkToManagedResourceFile"; const char _LocaleID[] = "LocaleID"; const char _ManifestFile[] = "ManifestFile"; const char _MapExports[] = "MapExports"; const char _MapFileName[] = "MapFileName"; -const char _MapLines[] = "MapLines "; const char _MergedIDLBaseFileName[] = "MergedIDLBaseFileName"; const char _MergeSections[] = "MergeSections"; const char _Message[] = "Message"; @@ -203,32 +168,22 @@ const char _MidlCommandFile[] = "MidlCommandFile"; const char _MinimalRebuild[] = "MinimalRebuild"; const char _MkTypLibCompatible[] = "MkTypLibCompatible"; const char _ModuleDefinitionFile[] = "ModuleDefinitionFile"; -const char _MSDOSStubFileName[] = "MSDOSStubFileName"; const char _MultiProcessorCompilation[] = "MultiProcessorCompilation"; const char _Name[] = "Name"; const char _NoEntryPoint[] = "NoEntryPoint"; const char _NullTerminateStrings[] = "NullTerminateStrings"; -const char _ObjectFile[] = "ObjectFile"; const char _ObjectFiles[] = "ObjectFiles"; const char _ObjectFileName[] = "ObjectFileName"; const char _OmitDefaultLibName[] = "OmitDefaultLibName"; const char _OmitFramePointers[] = "OmitFramePointers"; -const char _OpenMP[] = "OpenMP"; const char _OpenMPSupport[] = "OpenMPSupport"; const char _Optimization[] = "Optimization"; -const char _OptimizeForProcessor[] = "OptimizeForProcessor"; -const char _OptimizeForWindows98[] = "OptimizeForWindows98"; -const char _OptimizeForWindowsApplication[] = "OptimizeForWindowsApplication"; const char _OptimizeReferences[] = "OptimizeReferences"; const char _OutputDirectory[] = "OutputDirectory"; const char _OutputFile[] = "OutputFile"; -const char _Outputs[] = "Outputs"; -const char _ParseFiles[] = "ParseFiles"; -const char _Path[] = "Path"; const char _PrecompiledHeader[] = "PrecompiledHeader"; const char _PrecompiledHeaderFile[] = "PrecompiledHeaderFile"; const char _PrecompiledHeaderOutputFile[] = "PrecompiledHeaderOutputFile"; -const char _PrecompiledHeaderThrough[] = "PrecompiledHeaderThrough"; const char _PreprocessorDefinitions[] = "PreprocessorDefinitions"; const char _PreprocessKeepComments[] = "PreprocessKeepComments"; const char _PreprocessOutputPath[] = "PreprocessOutputPath"; @@ -236,11 +191,7 @@ const char _PreprocessSuppressLineNumbers[] = "PreprocessSuppressLineNumbers const char _PreprocessToFile[] = "PreprocessToFile"; const char _PreventDllBinding[] = "PreventDllBinding"; const char _PrimaryOutput[] = "PrimaryOutput"; -const char _Profile[] = "Profile"; -const char _ProfileGuidedDatabase[] = "ProfileGuidedDatabase"; -const char _ProjectGUID[] = "ProjectGUID"; const char _ProcessorNumber[] = "ProcessorNumber"; -const char _ProjectType[] = "ProjectType"; const char _ProgramDatabase[] = "ProgramDatabase"; const char _ProgramDataBaseFileName[] = "ProgramDataBaseFileName"; const char _ProgramDatabaseFile[] = "ProgramDatabaseFile"; @@ -248,22 +199,16 @@ const char _ProxyFileName[] = "ProxyFileName"; const char _RandomizedBaseAddress[] = "RandomizedBaseAddress"; const char _RedirectOutputAndErrors[] = "RedirectOutputAndErrors"; const char _RegisterOutput[] = "RegisterOutput"; -const char _RelativePath[] = "RelativePath"; -const char _RemoteDirectory[] = "RemoteDirectory"; const char _RemoveObjects[] = "RemoveObjects"; -const char _ResourceOnlyDLL[] = "ResourceOnlyDLL"; const char _ResourceOutputFileName[] = "ResourceOutputFileName"; const char _RuntimeLibrary[] = "RuntimeLibrary"; const char _RuntimeTypeInfo[] = "RuntimeTypeInfo"; -const char _SccProjectName[] = "SccProjectName"; -const char _SccLocalPath[] = "SccLocalPath"; const char _SectionAlignment[] = "SectionAlignment"; const char _ServerStubFile[] = "ServerStubFile"; const char _SetChecksum[] = "SetChecksum"; const char _ShowIncludes[] = "ShowIncludes"; const char _ShowProgress[] = "ShowProgress"; const char _SmallerTypeCheck[] = "SmallerTypeCheck"; -const char _SpecifySectionAttributes[] = "SpecifySectionAttributes"; const char _StackCommitSize[] = "StackCommitSize"; const char _StackReserveSize[] = "StackReserveSize"; const char _StringPooling[] = "StringPooling"; @@ -294,19 +239,12 @@ const char _UACExecutionLevel[] = "UACExecutionLevel"; const char _UACUIAccess[] = "UACUIAccess"; const char _UndefineAllPreprocessorDefinitions[]= "UndefineAllPreprocessorDefinitions"; const char _UndefinePreprocessorDefinitions[] = "UndefinePreprocessorDefinitions"; -const char _UniqueIdentifier[] = "UniqueIdentifier"; const char _UseFullPaths[] = "UseFullPaths"; const char _UseOfATL[] = "UseOfATL"; const char _UseOfMfc[] = "UseOfMfc"; -const char _UsePrecompiledHeader[] = "UsePrecompiledHeader"; const char _UseUnicodeForAssemblerListing[] = "UseUnicodeForAssemblerListing"; const char _ValidateAllParameters[] = "ValidateAllParameters"; -const char _VCCLCompilerTool[] = "VCCLCompilerTool"; -const char _VCLibrarianTool[] = "VCLibrarianTool"; -const char _VCLinkerTool[] = "VCLinkerTool"; const char _VCCustomBuildTool[] = "VCCustomBuildTool"; -const char _VCResourceCompilerTool[] = "VCResourceCompilerTool"; -const char _VCMIDLTool[] = "VCMIDLTool"; const char _Verbose[] = "Verbose"; const char _Version[] = "Version"; const char _WarnAsError[] = "WarnAsError"; @@ -343,7 +281,6 @@ inline XmlOutput::xml_output attrTagS(const char *name, const QString &v) return tagValue(name, v); } - inline XmlOutput::xml_output attrTagX(const char *name, const QStringList &v, const char *s = ",") { if(v.isEmpty()) @@ -376,733 +313,991 @@ inline XmlOutput::xml_output valueTagT( const triState v) return valueTag(v == _True ? "true" : "false"); } +// Tree file generation --------------------------------------------- +void XTreeNode::generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCProject &tool, const QString &filter) { + + if (children.size()) { + // Filter + ChildrenMap::ConstIterator it, end = children.constEnd(); + if (!tagName.isEmpty()) { + xmlFilter << tag("Filter") + << attrTag("Include", tagName) + << attrTagS("Extensions", ""); + } + // First round, do nested filters + for (it = children.constBegin(); it != end; ++it) + if ((*it)->children.size()) + (*it)->generateXML(xml, xmlFilter, it.key(), tool, filter); + // Second round, do leafs + for (it = children.constBegin(); it != end; ++it) + if (!(*it)->children.size()) + (*it)->generateXML(xml, xmlFilter, it.key(), tool, filter); + + if (!tagName.isEmpty()) + xml << closetag("Filter"); + } else { + // Leaf + VCXProjectWriter::outputFileConfigs(tool, xml, xmlFilter, info, filter); + } +} + + +// Flat file generation --------------------------------------------- +void XFlatNode::generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &/*tagName*/, VCProject &tool, const QString &filter) { + if (children.size()) { + ChildrenMapFlat::ConstIterator it = children.constBegin(); + ChildrenMapFlat::ConstIterator end = children.constEnd(); + xml << tag(_ItemGroup); + xmlFilter << tag(_ItemGroup); + for (; it != end; ++it) { + VCXProjectWriter::outputFileConfigs(tool, xml, xmlFilter, (*it), filter); + } + xml << closetag(); + xmlFilter << closetag(); + } +} + +void VCXProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool) +{ + xml.setIndentString(" "); + + xml << decl("1.0", "utf-8") + << tag("Project") + << attrTag("DefaultTargets","Build") + << attrTag("ToolsVersion", "4.0") + << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003") + << tag("ItemGroup") + << attrTag("Label", "ProjectConfigurations"); + + xml << tag("ProjectConfiguration") + << attrTag("Include" , tool.Configuration.Name) + << tagValue("Configuration", tool.Configuration.ConfigurationName) + << tagValue("Platform", tool.PlatformName) + << closetag(); + + xml << closetag() + << tag("PropertyGroup") + << attrTag("Label", "Globals") + << tagValue("ProjectGuid", tool.ProjectGUID) + << tagValue("RootNamespace", tool.Name) + << tagValue("Keyword", tool.Keyword) + << closetag(); + + // config part. + xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"); + + write(xml, tool.Configuration); + + xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props"); + + // Extension settings + xml << tag("ImportGroup") + << attrTag("Label", "ExtensionSettings") + << closetag(); + + // PropertySheets + xml << tag("ImportGroup") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << attrTag("Label", "PropertySheets"); + + xml << tag("Import") + << attrTag("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props") + << attrTag("Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')") + << closetag() + << closetag(); + + + // UserMacros + xml << tag("PropertyGroup") + << attrTag("Label", "UserMacros") + << closetag(); + + xml << tag("PropertyGroup"); + + if ( !tool.Configuration.OutputDirectory.isEmpty() ) { + xml<< tag("OutDir") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTag(tool.Configuration.OutputDirectory); + } + if ( !tool.Configuration.IntermediateDirectory.isEmpty() ) { + xml<< tag("IntDir") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTag(tool.Configuration.IntermediateDirectory); + } + if ( !tool.Configuration.PrimaryOutput.isEmpty() ) { + xml<< tag("TargetName") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTag(tool.Configuration.PrimaryOutput); + } + + if ( tool.Configuration.linker.IgnoreImportLibrary != unset) { + xml<< tag("IgnoreImportLibrary") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTagT(tool.Configuration.linker.IgnoreImportLibrary); + } + + if ( tool.Configuration.linker.LinkIncremental != linkIncrementalDefault) { + const triState ts = (tool.Configuration.linker.LinkIncremental == linkIncrementalYes ? _True : _False); + xml<< tag("LinkIncremental") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTagT(ts); + } + + if ( tool.Configuration.preBuild.ExcludedFromBuild != unset ) + { + xml<< tag("PreBuildEventUseInBuild") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTagT(!tool.Configuration.preBuild.ExcludedFromBuild); + } + + if ( tool.Configuration.preLink.ExcludedFromBuild != unset ) + { + xml<< tag("PreLinkEventUseInBuild") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTagT(!tool.Configuration.preLink.ExcludedFromBuild); + } + + if ( tool.Configuration.postBuild.ExcludedFromBuild != unset ) + { + xml<< tag("PostBuildEventUseInBuild") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTagT(!tool.Configuration.postBuild.ExcludedFromBuild); + } + xml << closetag(); + + xml << tag("ItemDefinitionGroup") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)); + + // ClCompile + write(xml, tool.Configuration.compiler); + + // Link + write(xml, tool.Configuration.linker); + + // Midl + write(xml, tool.Configuration.idl); + + // ResourceCompiler + write(xml, tool.Configuration.resource); + + // Post build event + if ( tool.Configuration.postBuild.ExcludedFromBuild != unset ) + write(xml, tool.Configuration.postBuild); + + // Pre build event + if ( tool.Configuration.preBuild.ExcludedFromBuild != unset ) + write(xml, tool.Configuration.preBuild); + + // Pre link event + if ( tool.Configuration.preLink.ExcludedFromBuild != unset ) + write(xml, tool.Configuration.preLink); + + xml << closetag(); + + QFile filterFile; + filterFile.setFileName(Option::output.fileName().append(".filters")); + filterFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); + QTextStream ts(&filterFile); + XmlOutput xmlFilter(ts, XmlOutput::NoConversion); + + xmlFilter.setIndentString(" "); + + xmlFilter << decl("1.0", "utf-8") + << tag("Project") + << attrTag("ToolsVersion", "4.0") + << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"); + + xmlFilter << tag("ItemGroup"); + + VCProject tempProj; + tempProj.SingleProjects += tool; + + addFilters(tempProj, xmlFilter, "Form Files"); + addFilters(tempProj, xmlFilter, "Generated Files"); + addFilters(tempProj, xmlFilter, "Header Files"); + addFilters(tempProj, xmlFilter, "LexYacc Files"); + addFilters(tempProj, xmlFilter, "Resource Files"); + addFilters(tempProj, xmlFilter, "Source Files"); + addFilters(tempProj, xmlFilter, "Translation Files"); + xmlFilter << closetag(); + + outputFilter(tempProj, xml, xmlFilter, "Source Files"); + outputFilter(tempProj, xml, xmlFilter, "Header Files"); + outputFilter(tempProj, xml, xmlFilter, "Generated Files"); + outputFilter(tempProj, xml, xmlFilter, "LexYacc Files"); + outputFilter(tempProj, xml, xmlFilter, "Translation Files"); + outputFilter(tempProj, xml, xmlFilter, "Form Files"); + outputFilter(tempProj, xml, xmlFilter, "Resource Files"); + + for (int x = 0; x < tempProj.ExtraCompilers.count(); ++x) { + outputFilter(tempProj, xml, xmlFilter, tempProj.ExtraCompilers.at(x)); + } + + xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets"); + + xml << tag("ImportGroup") + << attrTag("Label", "ExtensionTargets") + << closetag(); +} + +void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool) +{ + if (tool.SingleProjects.count() == 0) { + warn_msg(WarnLogic, "Generator: .NET: no single project in merge project, no output"); + return; + } + + xml.setIndentString(" "); + + xml << decl("1.0", "utf-8") + << tag("Project") + << attrTag("DefaultTargets","Build") + << attrTag("ToolsVersion", "4.0") + << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003") + << tag("ItemGroup") + << attrTag("Label", "ProjectConfigurations"); + + for (int i = 0; i < tool.SingleProjects.count(); ++i) { + xml << tag("ProjectConfiguration") + << attrTag("Include" , tool.SingleProjects.at(i).Configuration.Name) + << tagValue("Configuration", tool.SingleProjects.at(i).Configuration.ConfigurationName) + << tagValue("Platform", tool.SingleProjects.at(i).PlatformName) + << closetag(); + } + + xml << closetag() + << tag("PropertyGroup") + << attrTag("Label", "Globals") + << tagValue("ProjectGuid", tool.ProjectGUID) + << tagValue("RootNamespace", tool.Name) + << tagValue("Keyword", tool.Keyword) + << closetag(); + + // config part. + xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"); + for (int i = 0; i < tool.SingleProjects.count(); ++i) + write(xml, tool.SingleProjects.at(i).Configuration); + xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props"); + + // Extension settings + xml << tag("ImportGroup") + << attrTag("Label", "ExtensionSettings") + << closetag(); + + // PropertySheets + for (int i = 0; i < tool.SingleProjects.count(); ++i) { + xml << tag("ImportGroup") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << attrTag("Label", "PropertySheets"); + + xml << tag("Import") + << attrTag("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props") + << attrTag("Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')") + << closetag() + << closetag(); + } + + // UserMacros + xml << tag("PropertyGroup") + << attrTag("Label", "UserMacros") + << closetag(); + + xml << tag("PropertyGroup"); + for (int i = 0; i < tool.SingleProjects.count(); ++i) { + + if ( !tool.SingleProjects.at(i).Configuration.OutputDirectory.isEmpty() ) { + xml << tag("OutDir") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTag(tool.SingleProjects.at(i).Configuration.OutputDirectory); + } + if ( !tool.SingleProjects.at(i).Configuration.IntermediateDirectory.isEmpty() ) { + xml << tag("IntDir") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTag(tool.SingleProjects.at(i).Configuration.IntermediateDirectory); + } + if ( !tool.SingleProjects.at(i).Configuration.PrimaryOutput.isEmpty() ) { + xml << tag("TargetName") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTag(tool.SingleProjects.at(i).Configuration.PrimaryOutput); + } + + if ( tool.SingleProjects.at(i).Configuration.linker.IgnoreImportLibrary != unset) { + xml << tag("IgnoreImportLibrary") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTagT(tool.SingleProjects.at(i).Configuration.linker.IgnoreImportLibrary); + } + + if ( tool.SingleProjects.at(i).Configuration.linker.LinkIncremental != unset) { + const triState ts = (tool.SingleProjects.at(i).Configuration.linker.LinkIncremental == linkIncrementalYes ? _True : _False); + xml << tag("LinkIncremental") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTagT(ts); + } + + if ( tool.SingleProjects.at(i).Configuration.preBuild.ExcludedFromBuild != unset ) + { + xml << tag("PreBuildEventUseInBuild") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTagT(!tool.SingleProjects.at(i).Configuration.preBuild.ExcludedFromBuild); + } + + if ( tool.SingleProjects.at(i).Configuration.preLink.ExcludedFromBuild != unset ) + { + xml << tag("PreLinkEventUseInBuild") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTagT(!tool.SingleProjects.at(i).Configuration.preLink.ExcludedFromBuild); + } + + if ( tool.SingleProjects.at(i).Configuration.postBuild.ExcludedFromBuild != unset ) + { + xml << tag("PostBuildEventUseInBuild") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTagT(!tool.SingleProjects.at(i).Configuration.postBuild.ExcludedFromBuild); + } + } + xml << closetag(); + + for (int i = 0; i < tool.SingleProjects.count(); ++i) { + xml << tag("ItemDefinitionGroup") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)); + + // ClCompile + write(xml, tool.SingleProjects.at(i).Configuration.compiler); + + // Link + write(xml, tool.SingleProjects.at(i).Configuration.linker); + + // Midl + write(xml, tool.SingleProjects.at(i).Configuration.idl); + + // ResourceCompiler + write(xml, tool.SingleProjects.at(i).Configuration.resource); + + // Post build event + if ( tool.SingleProjects.at(i).Configuration.postBuild.ExcludedFromBuild != unset ) + write(xml, tool.SingleProjects.at(i).Configuration.postBuild); + + // Pre build event + if ( tool.SingleProjects.at(i).Configuration.preBuild.ExcludedFromBuild != unset ) + write(xml, tool.SingleProjects.at(i).Configuration.preBuild); + + // Pre link event + if ( tool.SingleProjects.at(i).Configuration.preLink.ExcludedFromBuild != unset ) + write(xml, tool.SingleProjects.at(i).Configuration.preLink); + + xml << closetag(); + } + + // The file filters are added in a separate file for MSBUILD. + QFile filterFile; + filterFile.setFileName(Option::output.fileName().append(".filters")); + filterFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); + QTextStream ts(&filterFile); + XmlOutput xmlFilter(ts, XmlOutput::NoConversion); + + xmlFilter.setIndentString(" "); + + xmlFilter << decl("1.0", "utf-8") + << tag("Project") + << attrTag("ToolsVersion", "4.0") + << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"); + + xmlFilter << tag("ItemGroup"); + + addFilters(tool, xmlFilter, "Form Files"); + addFilters(tool, xmlFilter, "Generated Files"); + addFilters(tool, xmlFilter, "Header Files"); + addFilters(tool, xmlFilter, "LexYacc Files"); + addFilters(tool, xmlFilter, "Resource Files"); + addFilters(tool, xmlFilter, "Source Files"); + addFilters(tool, xmlFilter, "Translation Files"); + xmlFilter << closetag(); + + outputFilter(tool, xml, xmlFilter, "Source Files"); + outputFilter(tool, xml, xmlFilter, "Header Files"); + outputFilter(tool, xml, xmlFilter, "Generated Files"); + outputFilter(tool, xml, xmlFilter, "LexYacc Files"); + outputFilter(tool, xml, xmlFilter, "Translation Files"); + outputFilter(tool, xml, xmlFilter, "Form Files"); + outputFilter(tool, xml, xmlFilter, "Resource Files"); + for (int x = 0; x < tool.ExtraCompilers.count(); ++x) { + outputFilter(tool, xml, xmlFilter, tool.ExtraCompilers.at(x)); + } + outputFilter(tool, xml, xmlFilter, "Root Files"); + + xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets"); + + xml << tag("ImportGroup") + << attrTag("Label", "ExtensionTargets") + << closetag(); +} + +static inline QString toString(asmListingOption option) +{ + switch (option) { + case asmListingAsmMachine: + return "AssemblyAndMachineCode"; + case asmListingAsmMachineSrc: + return "All"; + case asmListingAsmSrc: + return "AssemblyAndSourceCode"; + case asmListingAssemblyOnly: + return "AssemblyCode"; + } + return QString(); +} + +static inline QString toString(basicRuntimeCheckOption option) +{ + switch (option) { + case runtimeBasicCheckNone: + return ""; + case runtimeCheckStackFrame: + return "StackFrameRuntimeCheck"; + case runtimeCheckUninitVariables: + return "UninitializedLocalUsageCheck"; + case runtimeBasicCheckAll: + return "EnableFastChecks"; + } + return QString(); +} + +static inline QString toString(callingConventionOption option) +{ + switch (option) { + case callConventionCDecl: + return "Cdecl"; + case callConventionFastCall: + return "FastCall"; + case callConventionStdCall: + return "StdCall"; + } + return QString(); +} + +static inline QString toString(CompileAsOptions option) +{ + switch (option) { + case compileAsC: + return "CompileAsC"; + case compileAsCPlusPlus: + return "CompileAsCpp"; + } + return QString(); +} + +static inline QString toString(compileAsManagedOptions option) +{ + switch (option) { + case managedAssembly: + return "true"; + case managedAssemblyPure: + return "Safe"; + case managedAssemblyOldSyntax: + return "OldSyntax"; + } + return QString(); +} + +static inline QString toString(debugOption option) +{ + switch (option) { + case debugOldStyleInfo: + return "OldStyle"; + case debugEditAndContinue: + return "EditAndContinue"; + case debugEnabled: + return "ProgramDatabase"; + } + return QString(); +} + +static inline QString toString(enhancedInstructionSetOption option) +{ + switch (option) { + case archSSE: + return "StreamingSIMDExtensions"; + case archSSE2: + return "StreamingSIMDExtensions2"; + } + return QString(); +} + +static inline QString toString(exceptionHandling option) +{ + switch (option) { + case ehNone: + return "false"; + case ehNoSEH: + return "Sync"; + case ehSEH: + return "Async"; + } + return QString(); +} + +static inline QString toString(favorSizeOrSpeedOption option) +{ + switch (option) { + case favorSize: + return "Size"; + case favorSpeed: + return "Speed"; + } + return QString(); +} + +static inline QString toString(floatingPointModel option) +{ + switch (option) { + case floatingPointFast: + return "Fast"; + case floatingPointPrecise: + return "Precise"; + case floatingPointStrict: + return "Strict"; + } + return QString(); +} + +static inline QString toString(inlineExpansionOption option) +{ + switch (option) { + case expandDisable: + return "Disabled"; + case expandOnlyInline: + return "OnlyExplicitInline"; + case expandAnySuitable: + return "AnySuitable"; + } + return QString(); +} + +static inline QString toString(optimizeOption option) +{ + switch (option) { + case optimizeMinSpace: + return "MinSpace"; + case optimizeMaxSpeed: + return "MaxSpeed"; + } + return QString(); +} + +static inline QString toString(pchOption option) +{ + switch (option) { + case pchNone: + return "NotUsing"; + case pchCreateUsingSpecific: + return "Create"; + case pchUseUsingSpecific: + return "Use"; + } + return QString(); +} + +static inline QString toString(runtimeLibraryOption option) +{ + switch (option) { + case rtMultiThreaded: + return "MultiThreaded"; + case rtMultiThreadedDLL: + return "MultiThreadedDLL"; + case rtMultiThreadedDebug: + return "MultiThreadedDebug"; + case rtMultiThreadedDebugDLL: + return "MultiThreadedDebugDLL"; + } + return QString(); +} + +static inline QString toString(structMemberAlignOption option) +{ + switch (option) { + case alignSingleByte: + return "1Byte"; + case alignTwoBytes: + return "2Bytes"; + case alignFourBytes: + return "4Bytes"; + case alignEightBytes: + return "8Bytes"; + case alignSixteenBytes: + return "16Bytes"; + } + return QString(); +} + +static inline QString toString(warningLevelOption option) +{ + switch (option) { + case warningLevel_0: + return "TurnOffAllWarnings"; + case warningLevel_1: + return "Level1"; + case warningLevel_2: + return "Level2"; + case warningLevel_3: + return "Level3"; + case warningLevel_4: + return "Level4"; + } + return QString(); +} + +static inline QString toString(optLinkTimeCodeGenType option) +{ + switch (option) { + case optLTCGEnabled: + return "UseLinkTimeCodeGeneration"; + case optLTCGInstrument: + return "PGInstrument"; + case optLTCGOptimize: + return "PGOptimization"; + case optLTCGUpdate: + return "PGUpdate"; + } + return QString(); +} + +static inline QString toString(subSystemOption option) +{ + switch (option) { + case subSystemConsole: + return "Console"; + case subSystemWindows: + return "Windows"; + case optLTCGOptimize: + return "PGOptimization"; + case optLTCGUpdate: + return "PGUpdate"; + } + return QString(); +} + +static inline QString toString(machineTypeOption option) +{ + switch (option) { + case machineX86: + return "MachineX86"; + case machineX64: + return "MachineX64"; + } + return QString(); +} + +static inline QString toString(midlCharOption option) +{ + switch (option) { + case midlCharUnsigned: + return "Unsigned"; + case midlCharSigned: + return "Signed"; + case midlCharAscii7: + return "Ascii"; + } + return QString(); +} + +static inline QString toString(midlErrorCheckOption option) +{ + switch (option) { + case midlDisableAll: + return "None"; + case midlEnableAll: + return "All"; + } + return QString(); +} + +static inline QString toString(midlStructMemberAlignOption option) +{ + switch (option) { + case midlAlignSingleByte: + return "1"; + case midlAlignTwoBytes: + return "2"; + case midlAlignFourBytes: + return "4"; + case midlAlignEightBytes: + return "8"; + case midlAlignSixteenBytes: + return "16"; + } + return QString(); +} + +static inline QString toString(midlTargetEnvironment option) +{ + switch (option) { + case midlTargetWin32: + return "Win32"; + case midlTargetWin64: + return "X64"; + } + return QString(); +} + +static inline QString toString(midlWarningLevelOption option) +{ + switch (option) { + case midlWarningLevel_0: + return "0"; + case midlWarningLevel_1: + return "1"; + case midlWarningLevel_2: + return "2"; + case midlWarningLevel_3: + return "3"; + case midlWarningLevel_4: + return "4"; + } + return QString(); +} + +static inline QString toString(enumResourceLangID option) +{ + if (option == 0) + return QString(); + else + return QString::number(qlonglong(option)); +} + +static inline QString toString(charSet option) +{ + switch (option) { + case charSetNotSet: + return "NotSet"; + case charSetUnicode: + return "Unicode"; + case charSetMBCS: + return "MultiByte"; + } + return QString(); +} + +static inline QString toString(ConfigurationTypes option) +{ + switch (option) { + case typeApplication: + return "Application"; + case typeDynamicLibrary: + return "DynamicLibrary"; + case typeStaticLibrary: + return "StaticLibrary"; + } + return QString(); +} + +static inline QString toString(useOfATL option) +{ + switch (option) { + case useATLStatic: + return "Static"; + case useATLDynamic: + return "Dynamic"; + } + return QString(); +} + +static inline QString toString(useOfMfc option) +{ + switch (option) { + case useMfcStatic: + return "Static"; + case useMfcDynamic: + return "Dynamic"; + } + return QString(); +} + +static inline triState toTriState(browseInfoOption option) +{ + switch (option) + { + case brInfoNone: + return _False; + case brAllInfo: + case brNoLocalSymbols: + return _True; + } + return unset; +} + +static inline triState toTriState(preprocessOption option) +{ + switch (option) + { + case preprocessNo: + return _False; + case preprocessNoLineNumbers: + case preprocessYes: + return _True; + } + return unset; +} + +static inline triState toTriState(optFoldingType option) +{ + switch (option) + { + case optNoFolding: + return _False; + case optFolding: + return _True; + } + return unset; +} + +static inline triState toTriState(addressAwarenessType option) +{ + switch (option) + { + case addrAwareDefault: + return unset; + case addrAwareNoLarge: + return _False; + case addrAwareLarge: + return _True; + } + return unset; +} + +static inline triState toTriState(linkIncrementalType option) +{ + switch (option) + { + case linkIncrementalDefault: + return unset; + case linkIncrementalNo: + return _False; + case linkIncrementalYes: + return _True; + } + return unset; +} + +static inline triState toTriState(linkProgressOption option) +{ + switch (option) + { + case linkProgressNotSet: + return unset; + case linkProgressAll: + case linkProgressLibs: + return _True; + } + return unset; +} + +static inline triState toTriState(optRefType option) +{ + switch (option) + { + case optReferencesDefault: + return unset; + case optNoReferences: + return _False; + case optReferences: + return _True; + } + return unset; +} -// VCXCLCompilerTool ------------------------------------------------- -VCXCLCompilerTool::VCXCLCompilerTool() - : BrowseInformation(_False), - BufferSecurityCheck(_False), - CreateHotpatchableImage(unset), - DisableLanguageExtensions(unset), - EnableFiberSafeOptimizations(unset), - EnablePREfast(unset), - ExpandAttributedSource(unset), - FloatingPointExceptions(unset), - ForceConformanceInForLoopScope(unset), - FunctionLevelLinking(unset), - GenerateXMLDocumentationFiles(unset), - IgnoreStandardIncludePath(unset), - IntrinsicFunctions(unset), - MinimalRebuild(unset), - MultiProcessorCompilation(unset), - OmitDefaultLibName(unset), - OmitFramePointers(unset), - Optimization("Disabled"), - OpenMPSupport(unset), - PreprocessKeepComments(unset), - PreprocessSuppressLineNumbers(unset), - RuntimeTypeInfo(unset), - ShowIncludes(unset), - SmallerTypeCheck(unset), - StringPooling(unset), - SuppressStartupBanner(unset), - TreatWarningAsError(unset), - TreatWChar_tAsBuiltInType(unset), - UndefineAllPreprocessorDefinitions(unset), - UseFullPaths(unset), - UseUnicodeForAssemblerListing(unset), - WholeProgramOptimization(unset) +static inline triState toTriState(termSvrAwarenessType option) { + switch (option) + { + case termSvrAwareDefault: + return unset; + case termSvrAwareNo: + return _False; + case termSvrAwareYes: + return _True; + } + return unset; } -XmlOutput &operator<<(XmlOutput &xml, const VCXCLCompilerTool &tool) +void VCXProjectWriter::write(XmlOutput &xml, const VCCLCompilerTool &tool) { - return xml + xml << tag(_CLCompile) << attrTagX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories, ";") << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ") << attrTagX(_AdditionalUsingDirectories, tool.AdditionalUsingDirectories, ";") - << attrTagS(_AlwaysAppend, tool.AlwaysAppend) +//unused << attrTagS(_AlwaysAppend, tool.AlwaysAppend) << attrTagS(_AssemblerListingLocation, tool.AssemblerListingLocation) - << attrTagS(_AssemblerOutput, tool.AssemblerOutput) - << attrTagS(_BasicRuntimeChecks, tool.BasicRuntimeChecks) - << attrTagT(_BrowseInformation, tool.BrowseInformation) + << attrTagS(_AssemblerOutput, toString(tool.AssemblerOutput)) + << attrTagS(_BasicRuntimeChecks, toString(tool.BasicRuntimeChecks)) + << attrTagT(_BrowseInformation, toTriState(tool.BrowseInformation)) << attrTagS(_BrowseInformationFile, tool.BrowseInformationFile) << attrTagT(_BufferSecurityCheck, tool.BufferSecurityCheck) - << attrTagS(_CallingConvention, tool.CallingConvention) - << attrTagS(_CompileAs, tool.CompileAs) - << attrTagS(_CompileAsManaged, tool.CompileAsManaged) + << attrTagS(_CallingConvention, toString(tool.CallingConvention)) + << attrTagS(_CompileAs, toString(tool.CompileAs)) + << attrTagS(_CompileAsManaged, toString(tool.CompileAsManaged)) << attrTagT(_CreateHotpatchableImage, tool.CreateHotpatchableImage) - << attrTagS(_DebugInformationFormat, tool.DebugInformationFormat) + << attrTagS(_DebugInformationFormat, toString(tool.DebugInformationFormat)) << attrTagT(_DisableLanguageExtensions, tool.DisableLanguageExtensions) << attrTagX(_DisableSpecificWarnings, tool.DisableSpecificWarnings, ";") - << attrTagS(_EnableEnhancedInstructionSet, tool.EnableEnhancedInstructionSet) + << attrTagS(_EnableEnhancedInstructionSet, toString(tool.EnableEnhancedInstructionSet)) << attrTagT(_EnableFiberSafeOptimizations, tool.EnableFiberSafeOptimizations) << attrTagT(_EnablePREfast, tool.EnablePREfast) << attrTagS(_ErrorReporting, tool.ErrorReporting) - << attrTagS(_ExceptionHandling, tool.ExceptionHandling) + << attrTagS(_ExceptionHandling, toString(tool.ExceptionHandling)) << attrTagT(_ExpandAttributedSource, tool.ExpandAttributedSource) - << attrTagS(_FavorSizeOrSpeed, tool.FavorSizeOrSpeed) + << attrTagS(_FavorSizeOrSpeed, toString(tool.FavorSizeOrSpeed)) << attrTagT(_FloatingPointExceptions, tool.FloatingPointExceptions) - << attrTagS(_FloatingPointModel, tool.FloatingPointModel) + << attrTagS(_FloatingPointModel, toString(tool.FloatingPointModel)) << attrTagT(_ForceConformanceInForLoopScope, tool.ForceConformanceInForLoopScope) << attrTagX(_ForcedIncludeFiles, tool.ForcedIncludeFiles, ";") << attrTagX(_ForcedUsingFiles, tool.ForcedUsingFiles, ";") - << attrTagT(_FunctionLevelLinking, tool.FunctionLevelLinking) + << attrTagT(_FunctionLevelLinking, tool.EnableFunctionLevelLinking) << attrTagT(_GenerateXMLDocumentationFiles, tool.GenerateXMLDocumentationFiles) << attrTagT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) - << attrTagS(_InlineFunctionExpansion, tool.InlineFunctionExpansion) - << attrTagT(_IntrinsicFunctions, tool.IntrinsicFunctions) + << attrTagS(_InlineFunctionExpansion, toString(tool.InlineFunctionExpansion)) + << attrTagT(_IntrinsicFunctions, tool.EnableIntrinsicFunctions) << attrTagT(_MinimalRebuild, tool.MinimalRebuild) << attrTagT(_MultiProcessorCompilation, tool.MultiProcessorCompilation) - << attrTagS(_ObjectFileName, tool.ObjectFileName) - << attrTagX(_ObjectFiles, tool.ObjectFiles, ";") + << attrTagS(_ObjectFileName, tool.ObjectFile) +//unused << attrTagX(_ObjectFiles, tool.ObjectFiles, ";") << attrTagT(_OmitDefaultLibName, tool.OmitDefaultLibName) << attrTagT(_OmitFramePointers, tool.OmitFramePointers) - << attrTagT(_OpenMPSupport, tool.OpenMPSupport) - << attrTagS(_Optimization, tool.Optimization) - << attrTagS(_PrecompiledHeader, tool.PrecompiledHeader) - << attrTagS(_PrecompiledHeaderFile, tool.PrecompiledHeaderFile) - << attrTagS(_PrecompiledHeaderOutputFile, tool.PrecompiledHeaderOutputFile) - << attrTagT(_PreprocessKeepComments, tool.PreprocessKeepComments) + << attrTagT(_OpenMPSupport, tool.OpenMP) + << attrTagS(_Optimization, toString(tool.Optimization)) + << attrTagS(_PrecompiledHeader, toString(tool.UsePrecompiledHeader)) + << attrTagS(_PrecompiledHeaderFile, tool.PrecompiledHeaderThrough) + << attrTagS(_PrecompiledHeaderOutputFile, tool.PrecompiledHeaderFile) + << attrTagT(_PreprocessKeepComments, tool.KeepComments) << attrTagX(_PreprocessorDefinitions, tool.PreprocessorDefinitions, ";") << attrTagS(_PreprocessOutputPath, tool.PreprocessOutputPath) << attrTagT(_PreprocessSuppressLineNumbers, tool.PreprocessSuppressLineNumbers) - << attrTagT(_PreprocessToFile, tool.PreprocessToFile) + << attrTagT(_PreprocessToFile, toTriState(tool.GeneratePreprocessedFile)) << attrTagS(_ProgramDataBaseFileName, tool.ProgramDataBaseFileName) - << attrTagS(_ProcessorNumber, tool.ProcessorNumber) - << attrTagS(_RuntimeLibrary, tool.RuntimeLibrary) + << attrTagS(_ProcessorNumber, tool.MultiProcessorCompilationProcessorCount) + << attrTagS(_RuntimeLibrary, toString(tool.RuntimeLibrary)) << attrTagT(_RuntimeTypeInfo, tool.RuntimeTypeInfo) << attrTagT(_ShowIncludes, tool.ShowIncludes) << attrTagT(_SmallerTypeCheck, tool.SmallerTypeCheck) << attrTagT(_StringPooling, tool.StringPooling) - << attrTagS(_StructMemberAlignment, tool.StructMemberAlignment) + << attrTagS(_StructMemberAlignment, toString(tool.StructMemberAlignment)) << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) - << attrTagS(_TreatSpecificWarningsAsErrors, tool.TreatSpecificWarningsAsErrors) - << attrTagT(_TreatWarningAsError, tool.TreatWarningAsError) +//unused << attrTagS(_TreatSpecificWarningsAsErrors, tool.TreatSpecificWarningsAsErrors) + << attrTagT(_TreatWarningAsError, tool.WarnAsError) << attrTagT(_TreatWChar_tAsBuiltInType, tool.TreatWChar_tAsBuiltInType) << attrTagT(_UndefineAllPreprocessorDefinitions, tool.UndefineAllPreprocessorDefinitions) << attrTagX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions, ";") - << attrTagT(_UseFullPaths, tool.UseFullPaths) + << attrTagT(_UseFullPaths, tool.DisplayFullPaths) << attrTagT(_UseUnicodeForAssemblerListing, tool.UseUnicodeForAssemblerListing) - << attrTagS(_WarningLevel, tool.WarningLevel) + << attrTagS(_WarningLevel, toString(tool.WarningLevel)) << attrTagT(_WholeProgramOptimization, tool.WholeProgramOptimization) << attrTagS(_XMLDocumentationFileName, tool.XMLDocumentationFileName) << closetag(_CLCompile); } -bool VCXCLCompilerTool::parseOption(const char* option) +void VCXProjectWriter::write(XmlOutput &xml, const VCLinkerTool &tool) { - // skip index 0 ('/' or '-') - char first = option[1]; - char second = option[2]; - char third = option[3]; - char fourth = option[4]; - bool found = true; - - switch (first) { - case '?': - qWarning("Generator: Option '/?' : MSVC.NET projects do not support outputting help info"); - found = false; - break; - case '@': - qWarning("Generator: Option '/@': MSVC.NET projects do not support the use of a response file"); - found = false; - break; - case 'l': - qWarning("Generator: Option '/link': qmake generator does not support passing link options through the compiler tool"); - found = false; - break; - case 'A': - if(second != 'I') { - found = false; - break; - } - AdditionalUsingDirectories += option+3; - break; - case 'C': - PreprocessKeepComments = _True; - break; - case 'D': - PreprocessorDefinitions += option+2; - break; - case 'E': - if(second == 'H') { - QString opt(option); - if (opt.endsWith("EHa")) - ExceptionHandling = "Async"; - else if (opt.endsWith("EHsc")) - ExceptionHandling = "Sync"; - else if (opt.endsWith("EHs")) - ExceptionHandling = "SyncCThrow"; - else { - ExceptionHandling = "false"; - } - break; - }else if(second == 'P') { - PreprocessSuppressLineNumbers = _True; - } - found = false; - break; - case 'F': - if(second <= '9' && second >= '0') { - AdditionalOptions += option; - break; - } else { - switch (second) { - case 'A': - if(third == 'c') { - AssemblerOutput = "AssemblyAndMachineCode"; - if(fourth == 's') - AssemblerOutput = "All"; - } else if(third == 's') { - AssemblerOutput = "AssemblyAndSourceCode"; - } else if(third == 'u') { - UseUnicodeForAssemblerListing = _True; - } else { - AssemblerOutput = "AssemblyCode"; - } - break; - case 'a': - AssemblerListingLocation = option+3; - break; - case 'C': - UseFullPaths = _True; - break; - case 'd': - ProgramDataBaseFileName = option+3; - break; - case 'I': - ForcedIncludeFiles += option+3; - break; - case 'i': - PreprocessOutputPath += option+3; - break; - case 'm': - AdditionalOptions += option; - break; - case 'R': - BrowseInformation = _True; - BrowseInformationFile = option+3; - break; - case 'r': - BrowseInformation = _True; - BrowseInformationFile = option+3; - break; - case 'U': - ForcedUsingFiles += option+3; - break; - case 'o': - ObjectFileName = option+3; - break; - case 'p': - PrecompiledHeaderOutputFile = option+3; - break; - case 'x': - ExpandAttributedSource = _True; - break; - default: - found = false; - break; - } - } - break; - case 'G': - switch (second) { - case 'F': - StringPooling = _True; - break; - case 'L': - WholeProgramOptimization = _True; - if(third == '-') - WholeProgramOptimization = _False; - break; - case 'R': - RuntimeTypeInfo = _True; - if(third == '-') - RuntimeTypeInfo = _False; - break; - case 'S': - BufferSecurityCheck = _True; - if(third == '-') - BufferSecurityCheck = _False; - break; - case 'T': - EnableFiberSafeOptimizations = _True; - break; - case 'd': - CallingConvention = "Cdecl"; - break; - case 'm': - MinimalRebuild = _True; - if(third == '-') - MinimalRebuild = _False; - break; - case 'r': - CallingConvention = "FastCall"; - break; - case 'y': - FunctionLevelLinking = _True; - break; - case 'z': - CallingConvention = "StdCall"; - break; - default: - found = false; - break; - } - break; - case 'H': - AdditionalOptions += option; - break; - case 'I': - AdditionalIncludeDirectories += option+2; - break; - case 'L': - if(second == 'D') { - AdditionalOptions += option; - break; - } - found = false; - break; - case 'M': - if(second == 'D') { - RuntimeLibrary = "MultiThreadedDLL"; - if(third == 'd') - RuntimeLibrary = "MultiThreadedDebugDLL"; - break; - } else if(second == 'P') { - MultiProcessorCompilation = _True; - ProcessorNumber = option+3; - break; - } else if(second == 'T') { - RuntimeLibrary = "MultiThreaded"; - if(third == 'd') - RuntimeLibrary = "MultiThreadedDebug"; - break; - } - found = false; - break; - case 'O': - switch (second) { - case '1': - Optimization = "MinSpace"; - break; - case '2': - Optimization = "MaxSpeed"; - break; - case 'b': - if(third == '0') - InlineFunctionExpansion = "Disabled"; - else if(third == '1') - InlineFunctionExpansion = "OnlyExplicitInline"; - else if(third == '2') - InlineFunctionExpansion = "AnySuitable"; - else - found = false; - break; - case 'd': - Optimization = "Disabled"; - break; - case 'i': - IntrinsicFunctions = _True; - break; - case 'p': - if(third == 'e') - OpenMPSupport = _True; - else - found = false; - break; - case 's': - FavorSizeOrSpeed = "Size"; - break; - case 't': - FavorSizeOrSpeed = "Speed"; - break; - case 'x': - Optimization = "Full"; - break; - case 'y': - OmitFramePointers = _True; - if(third == '-') - OmitFramePointers = _False; - break; - default: - found = false; - break; - } - break; - case 'P': - PreprocessToFile = _True; - break; - case 'Q': - if(second == 'I') { - AdditionalOptions += option; - break; - } - found = false; - break; - case 'R': - if(second == 'T' && third == 'C') { - if(fourth == '1') - BasicRuntimeChecks = "EnableFastChecks"; - else if(fourth == 'c') - SmallerTypeCheck = _True; - else if(fourth == 's') - BasicRuntimeChecks = "StackFrameRuntimeCheck"; - else if(fourth == 'u') - BasicRuntimeChecks = "UninitializedLocalUsageCheck"; - else - found = false; break; - } - break; - case 'T': - if(second == 'C') { - CompileAs = "CompileAsC"; - } else if(second == 'P') { - CompileAs = "CompileAsCpp"; - } else { - qWarning("Generator: Options '/Tp<filename>' and '/Tc<filename>' are not supported by qmake"); - found = false; break; - } - break; - case 'U': - UndefinePreprocessorDefinitions += option+2; - break; - case 'V': - AdditionalOptions += option; - break; - case 'W': - switch (second) { - case 'a': - WarningLevel = "EnableAllWarnings"; - break; - case '4': - WarningLevel = "Level4"; - break; - case '3': - WarningLevel = "Level3"; - break; - case '2': - WarningLevel = "Level2"; - break; - case '1': - WarningLevel = "Level1"; - break; - case '0': - WarningLevel = "TurnOffAllWarnings"; - break; - case 'L': - AdditionalOptions += option; - break; - case 'X': - TreatWarningAsError = _True; - break; - case 'p': - if(third == '6' && fourth == '4') { - // Deprecated for VS2010 but can be used under Additional Options. - AdditionalOptions += option; - break; - } - // Fallthrough - default: - found = false; break; - } - break; - case 'X': - IgnoreStandardIncludePath = _True; - break; - case 'Y': - switch (second) { - case '\0': - case '-': - AdditionalOptions += option; - break; - case 'c': - PrecompiledHeader = "Create"; - PrecompiledHeaderFile = option+3; - break; - case 'd': - case 'l': - AdditionalOptions += option; - break; - case 'u': - PrecompiledHeader = "Use"; - PrecompiledHeaderFile = option+3; - break; - default: - found = false; break; - } - break; - case 'Z': - switch (second) { - case '7': - DebugInformationFormat = "OldStyle"; - break; - case 'I': - DebugInformationFormat = "EditAndContinue"; - break; - case 'i': - DebugInformationFormat = "ProgramDatabase"; - break; - case 'l': - OmitDefaultLibName = _True; - break; - case 'a': - DisableLanguageExtensions = _True; - break; - case 'e': - DisableLanguageExtensions = _False; - break; - case 'c': - if(third == ':') { - const char *c = option + 4; - // Go to the end of the option - while ( *c != '\0' && *c != ' ' && *c != '-') - ++c; - if(fourth == 'f') - ForceConformanceInForLoopScope = ((*c) == '-' ? _False : _True); - else if(fourth == 'w') - TreatWChar_tAsBuiltInType = ((*c) == '-' ? _False : _True); - else - found = false; - } else { - found = false; break; - } - break; - case 'g': - case 'm': - case 's': - AdditionalOptions += option; - break; - case 'p': - switch (third) - { - case '\0': - case '1': - StructMemberAlignment = "1Byte"; - if(fourth == '6') - StructMemberAlignment = "16Bytes"; - break; - case '2': - StructMemberAlignment = "2Bytes"; - break; - case '4': - StructMemberAlignment = "4Bytes"; - break; - case '8': - StructMemberAlignment = "8Bytes"; - break; - default: - found = false; break; - } - break; - default: - found = false; break; - } - break; - case 'a': - if (second == 'r' && third == 'c' && fourth == 'h') { - if (option[5] == ':') { - const char *o = option; - if (o[6] == 'S' && o[7] == 'S' && o[8] == 'E') { - EnableEnhancedInstructionSet = o[9] == '2' ? "StreamingSIMDExtensions2" : "StreamingSIMDExtensions"; - break; - } - } - } else if (second == 'n' && third == 'a' && fourth == 'l') { - EnablePREfast = _True; - break; - } - found = false; - break; - case 'b': // see http://msdn.microsoft.com/en-us/library/fwkeyyhe%28VS.100%29.aspx - if (second == 'i' && third == 'g' && fourth == 'o') { - const char *o = option; - if (o[5] == 'b' && o[6] == 'j') { - AdditionalOptions += option; - break; - } - } - found = false; - break; - case 'c': - if(second == 'l') { - if(*(option+5) == 'p') { - CompileAsManaged = "Pure"; - } else if(*(option+5) == 's') { - CompileAsManaged = "Safe"; - } else if(*(option+5) == 'o') { - CompileAsManaged = "OldSyntax"; - } else { - CompileAsManaged = "true"; - } - } else { - found = false; - break; - } - break; - case 'd': - if(second != 'o' && third == 'c') { - GenerateXMLDocumentationFiles = _True; - XMLDocumentationFileName += option+4; - break; - } - found = false; - break; - case 'e': - if (second == 'r' && third == 'r' && fourth == 'o') { - if (option[12] == ':') { - if ( option[13] == 'n') { - ErrorReporting = "None"; - } else if (option[13] == 'p') { - ErrorReporting = "Prompt"; - } else if (option[13] == 'q') { - ErrorReporting = "Queue"; - } else if (option[13] == 's') { - ErrorReporting = "Send"; - } else { - found = false; - } - break; - } - } - found = false; - break; - case 'f': - if(second == 'p' && third == ':') { - // Go to the end of the option - const char *c = option + 4; - while (*c != '\0' && *c != ' ' && *c != '-') - ++c; - switch (fourth) { - case 'e': - FloatingPointExceptions = ((*c) == '-' ? _False : _True); - break; - case 'f': - FloatingPointModel = "Fast"; - break; - case 'p': - FloatingPointModel = "Precise"; - break; - case 's': - FloatingPointModel = "Strict"; - break; - default: - found = false; - break; - } - } - break; - case 'h': - if(second == 'o' && third == 't' && fourth == 'p') { - CreateHotpatchableImage = _True; - break; - } - qWarning("Generator: Option '/help': MSVC.NET projects do not support outputting help info"); - found = false; - break; - case 'n': - if(second == 'o' && third == 'l' && fourth == 'o') { - SuppressStartupBanner = _True; - break; - } - found = false; - break; - case 'o': - if (second == 'p' && third == 'e' && fourth == 'n') { - OpenMPSupport = _True; - break; - } - found = false; - break; - case 's': - if(second == 'h' && third == 'o' && fourth == 'w') { - ShowIncludes = _True; - break; - } - found = false; - break; - case 'u': - UndefineAllPreprocessorDefinitions = _True; - break; - case 'v': - if(second == 'd' || second == 'm') { - AdditionalOptions += option; - break; - } - found = false; - break; - case 'w': - switch (second) { - case 'd': - DisableSpecificWarnings += option+3; - break; - case 'e': - TreatSpecificWarningsAsErrors = option+3; - break; - default: - AdditionalOptions += option; - } - break; - default: - AdditionalOptions += option; - break; - } - if(!found) { - warn_msg(WarnLogic, "Could not parse Compiler option: %s, added as AdditionalOption", option); - AdditionalOptions += option; - } - return true; -} - -// VCLinkerTool ----------------------------------------------------- -VCXLinkerTool::VCXLinkerTool() - : AllowIsolation(unset), - AssemblyDebug(unset), - DataExecutionPrevention(unset), - DelaySign(unset), - EnableCOMDATFolding(unset), - EnableUAC(unset), - FixedBaseAddress(unset), - GenerateDebugInformation(unset), - GenerateManifest(unset), - GenerateMapFile(unset), - HeapCommitSize(-1), - HeapReserveSize(-1), - IgnoreAllDefaultLibraries(unset), - IgnoreEmbeddedIDL(unset), - IgnoreImportLibrary(_True), - ImageHasSafeExceptionHandlers(unset), - LargeAddressAware(unset), - LinkDLL(unset), - LinkIncremental(unset), - LinkStatus(unset), - MapExports(unset), - NoEntryPoint(unset), - OptimizeReferences(unset), - PreventDllBinding(unset), - RandomizedBaseAddress(unset), - RegisterOutput(unset), - SectionAlignment(-1), - SetChecksum(unset), - //StackCommitSize(-1), - //StackReserveSize(-1), - SupportNobindOfDelayLoadedDLL(unset), - SupportUnloadOfDelayLoadedDLL(unset), - SuppressStartupBanner(unset), - SwapRunFromCD(unset), - SwapRunFromNet(unset), - TerminalServerAware(unset), - TreatLinkerWarningAsErrors(unset), - TurnOffAssemblyGeneration(unset), - TypeLibraryResourceID(0), - UACUIAccess(unset) -{ -} - -XmlOutput &operator<<(XmlOutput &xml, const VCXLinkerTool &tool) -{ - return xml + xml << tag(_Link) << attrTagX(_AdditionalDependencies, tool.AdditionalDependencies, ";") << attrTagX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories, ";") @@ -1116,18 +1311,15 @@ XmlOutput &operator<<(XmlOutput &xml, const VCXLinkerTool &tool) << attrTagS(_CLRImageType, tool.CLRImageType) << attrTagS(_CLRSupportLastError, tool.CLRSupportLastError) << attrTagS(_CLRThreadAttribute, tool.CLRThreadAttribute) - << attrTagS(_CLRUnmanagedCodeCheck, tool.CLRUnmanagedCodeCheck) - << attrTagS(_CreateHotPatchableImage, tool.CreateHotPatchableImage) + << attrTagT(_CLRUnmanagedCodeCheck, tool.CLRUnmanagedCodeCheck) +//unused << attrTagS(_CreateHotPatchableImage, tool.CreateHotPatchableImage) << attrTagT(_DataExecutionPrevention, tool.DataExecutionPrevention) << attrTagX(_DelayLoadDLLs, tool.DelayLoadDLLs, ";") << attrTagT(_DelaySign, tool.DelaySign) - << attrTagS(_Driver, tool.Driver) - << attrTagX(_EmbedManagedResourceFile, tool.EmbedManagedResourceFile, ";") - << attrTagT(_EnableCOMDATFolding, tool.EnableCOMDATFolding) + << attrTagS(_EmbedManagedResourceFile, tool.LinkToManagedResourceFile) + << attrTagT(_EnableCOMDATFolding, toTriState(tool.EnableCOMDATFolding)) << attrTagT(_EnableUAC, tool.EnableUAC) << attrTagS(_EntryPointSymbol, tool.EntryPointSymbol) - << attrTagT(_FixedBaseAddress, tool.FixedBaseAddress) - << attrTagS(_ForceFileOutput, tool.ForceFileOutput) << attrTagX(_ForceSymbolReferences, tool.ForceSymbolReferences, ";") << attrTagS(_FunctionOrder, tool.FunctionOrder) << attrTagT(_GenerateDebugInformation, tool.GenerateDebugInformation) @@ -1138,17 +1330,16 @@ XmlOutput &operator<<(XmlOutput &xml, const VCXLinkerTool &tool) << attrTagT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries) << attrTagT(_IgnoreEmbeddedIDL, tool.IgnoreEmbeddedIDL) << attrTagT(_IgnoreImportLibrary, tool.IgnoreImportLibrary) - << attrTagX(_IgnoreSpecificDefaultLibraries, tool.IgnoreSpecificDefaultLibraries, ";") - << attrTagT(_ImageHasSafeExceptionHandlers, tool.ImageHasSafeExceptionHandlers) + << attrTagX(_IgnoreSpecificDefaultLibraries, tool.IgnoreDefaultLibraryNames, ";") << attrTagS(_ImportLibrary, tool.ImportLibrary) << attrTagS(_KeyContainer, tool.KeyContainer) << attrTagS(_KeyFile, tool.KeyFile) - << attrTagT(_LargeAddressAware, tool.LargeAddressAware) - << attrTagT(_LinkDLL, tool.LinkDLL) + << attrTagT(_LargeAddressAware, toTriState(tool.LargeAddressAware)) + << attrTagT(_LinkDLL, (tool.config->ConfigurationType == typeDynamicLibrary ? _True : unset)) << attrTagS(_LinkErrorReporting, tool.LinkErrorReporting) - << attrTagT(_LinkIncremental, tool.LinkIncremental) - << attrTagT(_LinkStatus, tool.LinkStatus) - << attrTagS(_LinkTimeCodeGeneration, tool.LinkTimeCodeGeneration) + << attrTagT(_LinkIncremental, toTriState(tool.LinkIncremental)) + << attrTagT(_LinkStatus, toTriState(tool.ShowProgress)) + << attrTagS(_LinkTimeCodeGeneration, toString(tool.LinkTimeCodeGeneration)) << attrTagS(_ManifestFile, tool.ManifestFile) << attrTagT(_MapExports, tool.MapExports) << attrTagS(_MapFileName, tool.MapFileName) @@ -1156,32 +1347,27 @@ XmlOutput &operator<<(XmlOutput &xml, const VCXLinkerTool &tool) << attrTagS(_MergeSections, tool.MergeSections) << attrTagS(_MidlCommandFile, tool.MidlCommandFile) << attrTagS(_ModuleDefinitionFile, tool.ModuleDefinitionFile) - << attrTagS(_MSDOSStubFileName, tool.MSDOSStubFileName) - << attrTagT(_NoEntryPoint, tool.NoEntryPoint) - << attrTagT(_OptimizeReferences, tool.OptimizeReferences) + << attrTagT(_NoEntryPoint, tool.ResourceOnlyDLL) + << attrTagT(_OptimizeReferences, toTriState(tool.OptimizeReferences)) << attrTagS(_OutputFile, tool.OutputFile) << attrTagT(_PreventDllBinding, tool.PreventDllBinding) - << attrTagS(_Profile, tool.Profile) - << attrTagS(_ProfileGuidedDatabase, tool.ProfileGuidedDatabase) << attrTagS(_ProgramDatabaseFile, tool.ProgramDatabaseFile) << attrTagT(_RandomizedBaseAddress, tool.RandomizedBaseAddress) << attrTagT(_RegisterOutput, tool.RegisterOutput) << attrTagL(_SectionAlignment, tool.SectionAlignment, /*ifNot*/ -1) << attrTagT(_SetChecksum, tool.SetChecksum) - << attrTagS(_ShowProgress, tool.ShowProgress) - << attrTagS(_SpecifySectionAttributes, tool.SpecifySectionAttributes) - << attrTagS(_StackCommitSize, tool.StackCommitSize) - << attrTagS(_StackReserveSize, tool.StackReserveSize) + << attrTagL(_StackCommitSize, tool.StackCommitSize, /*ifNot*/ -1) + << attrTagL(_StackReserveSize, tool.StackReserveSize, /*ifNot*/ -1) << attrTagS(_StripPrivateSymbols, tool.StripPrivateSymbols) - << attrTagS(_SubSystem, tool.SubSystem) - << attrTagT(_SupportNobindOfDelayLoadedDLL, tool.SupportNobindOfDelayLoadedDLL) + << attrTagS(_SubSystem, toString(tool.SubSystem)) +// << attrTagT(_SupportNobindOfDelayLoadedDLL, tool.SupportNobindOfDelayLoadedDLL) << attrTagT(_SupportUnloadOfDelayLoadedDLL, tool.SupportUnloadOfDelayLoadedDLL) << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) << attrTagT(_SwapRunFromCD, tool.SwapRunFromCD) << attrTagT(_SwapRunFromNet, tool.SwapRunFromNet) - << attrTagS(_TargetMachine, tool.TargetMachine) - << attrTagT(_TerminalServerAware, tool.TerminalServerAware) - << attrTagT(_TreatLinkerWarningAsErrors, tool.TreatLinkerWarningAsErrors) + << attrTagS(_TargetMachine, toString(tool.TargetMachine)) + << attrTagT(_TerminalServerAware, toTriState(tool.TerminalServerAware)) + << attrTagT(_TreatLinkerWarningAsErrors, tool.TreatWarningsAsErrors) << attrTagT(_TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration) << attrTagS(_TypeLibraryFile, tool.TypeLibraryFile) << attrTagL(_TypeLibraryResourceID, tool.TypeLibraryResourceID, /*ifNot*/ 0) @@ -1191,619 +1377,18 @@ XmlOutput &operator<<(XmlOutput &xml, const VCXLinkerTool &tool) << closetag(_Link); } -// Hashing routine to do fast option lookups ---- -// Slightly rewritten to stop on ':' ',' and '\0' -// Original routine in qtranslator.cpp ---------- -static uint elfHash(const char* name) +void VCXProjectWriter::write(XmlOutput &xml, const VCMIDLTool &tool) { - const uchar *k; - uint h = 0; - uint g; - - if(name) { - k = (const uchar *) name; - while((*k) && - (*k)!= ':' && - (*k)!=',' && - (*k)!=' ') { - h = (h << 4) + *k++; - if((g = (h & 0xf0000000)) != 0) - h ^= g >> 24; - h &= ~g; - } - } - if(!h) - h = 1; - return h; -} - -//#define USE_DISPLAY_HASH -#ifdef USE_DISPLAY_HASH -static void displayHash(const char* str) -{ - printf("case 0x%07x: // %s\n break;\n", elfHash(str), str); -} -#endif - -bool VCXLinkerTool::parseOption(const char* option) -{ -#ifdef USE_DISPLAY_HASH - // Main options - displayHash("/ALIGN"); displayHash("/ALLOWBIND"); displayHash("/ASSEMBLYMODULE"); - displayHash("/ASSEMBLYRESOURCE"); displayHash("/BASE"); displayHash("/DEBUG"); - displayHash("/DEF"); displayHash("/DEFAULTLIB"); displayHash("/DELAY"); - displayHash("/DELAYLOAD"); displayHash("/DLL"); displayHash("/DRIVER"); - displayHash("/ENTRY"); displayHash("/EXETYPE"); displayHash("/EXPORT"); - displayHash("/FIXED"); displayHash("/FORCE"); displayHash("/HEAP"); - displayHash("/IDLOUT"); displayHash("/IGNORE"); displayHash("/IGNOREIDL"); displayHash("/IMPLIB"); - displayHash("/INCLUDE"); displayHash("/INCREMENTAL"); displayHash("/LARGEADDRESSAWARE"); - displayHash("/LIBPATH"); displayHash("/LTCG"); displayHash("/MACHINE"); - displayHash("/MAP"); displayHash("/MAPINFO"); displayHash("/MERGE"); - displayHash("/MIDL"); displayHash("/NOASSEMBLY"); displayHash("/NODEFAULTLIB"); - displayHash("/NOENTRY"); displayHash("/NOLOGO"); displayHash("/OPT"); - displayHash("/ORDER"); displayHash("/OUT"); displayHash("/PDB"); - displayHash("/PDBSTRIPPED"); displayHash("/RELEASE"); displayHash("/SECTION"); - displayHash("/STACK"); displayHash("/STUB"); displayHash("/SUBSYSTEM"); - displayHash("/SWAPRUN"); displayHash("/TLBID"); displayHash("/TLBOUT"); - displayHash("/TSAWARE"); displayHash("/VERBOSE"); displayHash("/VERSION"); - displayHash("/VXD"); displayHash("/WS "); displayHash("/libpath"); - -#endif -#ifdef USE_DISPLAY_HASH - // Sub options - displayHash("UNLOAD"); displayHash("NOBIND"); displayHash("no"); displayHash("NOSTATUS"); displayHash("STATUS"); - displayHash("AM33"); displayHash("ARM"); displayHash("CEE"); displayHash("EBC"); displayHash("IA64"); displayHash("X86"); displayHash("X64"); displayHash("M32R"); - displayHash("MIPS"); displayHash("MIPS16"); displayHash("MIPSFPU"); displayHash("MIPSFPU16"); displayHash("MIPSR41XX"); displayHash("PPC"); - displayHash("SH3"); displayHash("SH3DSP"); displayHash("SH4"); displayHash("SH5"); displayHash("THUMB"); displayHash("TRICORE"); displayHash("EXPORTS"); - displayHash("LINES"); displayHash("REF"); displayHash("NOREF"); displayHash("ICF"); displayHash("WIN98"); displayHash("NOWIN98"); - displayHash("CONSOLE"); displayHash("EFI_APPLICATION"); displayHash("EFI_BOOT_SERVICE_DRIVER"); displayHash("EFI_ROM"); displayHash("EFI_RUNTIME_DRIVER"); displayHash("NATIVE"); - displayHash("POSIX"); displayHash("WINDOWS"); displayHash("WINDOWSCE"); displayHash("NET"); displayHash("CD"); displayHash("NO"); -#endif - bool found = true; - switch (elfHash(option)) { - case 0x6b21972: // /DEFAULTLIB:library - case 0xaca9d75: // /EXETYPE[:DYNAMIC | :DEV386] - case 0x3ad5444: // /EXPORT:entryname[,@ordinal[,NONAME]][,DATA] - case 0x3dc3455: // /IGNORE:number,number,number,number ### NOTE: This one is undocumented, but it is even used by Microsoft. - // In recent versions of the Microsoft linker they have disabled this undocumented feature. - case 0x0034bc4: // /VXD - AdditionalOptions += option; - break; - case 0x3360dbe: // /ALIGN[:number] - SectionAlignment = QString(option+7).toLongLong(); - break; - case 0x1485c34: // /ALLOWBIND[:NO] - if(*(option+10) == ':' && (*(option+11) == 'n' || *(option+11) == 'N')) - PreventDllBinding = _False; - else - PreventDllBinding = _True; - break; - case 0x312011e: // /ALLOWISOLATION[:NO] - if(*(option+15) == ':' && (*(option+16) == 'n' || *(option+16) == 'N')) - AllowIsolation = _False; - else - AllowIsolation = _True; - break; - case 0x679c075: // /ASSEMBLYMODULE:filename - AddModuleNamesToAssembly += option+15; - break; - case 0x75f35f7: // /ASSEMBLYDEBUG[:DISABLE] - if(*(option+14) == ':' && (*(option+15) == 'D')) - AssemblyDebug = _False; - else - AssemblyDebug = _True; - break; - case 0x43294a5: // /ASSEMBLYLINKRESOURCE:filename - AssemblyLinkResource += option+22; - break; - case 0x062d065: // /ASSEMBLYRESOURCE:filename - EmbedManagedResourceFile += option+18; - break; - case 0x0336675: // /BASE:{address | @filename,key} - // Do we need to do a manual lookup when '@filename,key'? - // Seems BaseAddress only can contain the location... - // We don't use it in Qt, so keep it simple for now - BaseAddress = option+6; - break; - case 0x63bf065: // /CLRIMAGETYPE:{IJW|PURE|SAFE} - if(*(option+14) == 'I') - CLRImageType = "ForceIJWImage"; - else if(*(option+14) == 'P') - CLRImageType = "ForcePureILImage"; - else if(*(option+14) == 'S') - CLRImageType = "ForceSafeILImage"; - break; - case 0x5f2a6a2: // /CLRSUPPORTLASTERROR{:NO | SYSTEMDLL} - if(*(option+20) == ':') { - if(*(option+21) == 'N') { - CLRSupportLastError = "Disabled"; - } else if(*(option+21) == 'S') { - CLRSupportLastError = "SystemDlls"; - } - } else { - CLRSupportLastError = "Enabled"; - } - break; - case 0xc7984f5: // /CLRTHREADATTRIBUTE:{STA|MTA|NONE} - if(*(option+20) == 'N') - CLRThreadAttribute = "DefaultThreadingAttribute"; - else if(*(option+20) == 'M') - CLRThreadAttribute = "MTAThreadingAttribute"; - else if(*(option+20) == 'S') - CLRThreadAttribute = "STAThreadingAttribute"; - break; - case 0xa8c637b: // /CLRUNMANAGEDCODECHECK[:NO] - if(*(option+23) == 'N') - CLRUnmanagedCodeCheck = _False; - else - CLRUnmanagedCodeCheck = _True; - break; - case 0x3389797: // /DEBUG - GenerateDebugInformation = _True; - break; - case 0x0033896: // /DEF:filename - ModuleDefinitionFile = option+5; - break; - case 0x338a069: // /DELAY:{UNLOAD | NOBIND} - if(*(option+7) == 'U') - SupportNobindOfDelayLoadedDLL = _True; - else if(*(option+7) == 'N') - SupportUnloadOfDelayLoadedDLL = _True; - break; - case 0x06f4bf4: // /DELAYLOAD:dllname - DelayLoadDLLs += option+11; - break; - case 0x06d451e: // /DELAYSIGN[:NO] - if(*(option+10) == ':' && (*(option+11) == 'n' || *(option+11) == 'N')) - DelaySign = _False; - else - DelaySign = _True; - break; - case 0x003390c: // /DLL - LinkDLL = _True; - break; - case 0x396ea92: // /DRIVER[:UPONLY | :WDM] - if((*(option+7) == ':') && (*(option+8) == 'U')) - Driver = "UpOnly"; - else if((*(option+7) == ':') && (*(option+8) == 'W')) - Driver = "WDM"; - else - Driver = "Driver"; - break; - case 0x2ee8415: // /DYNAMICBASE[:NO] - if(*(option+12) == ':' && (*(option+13) == 'n' || *(option+13) == 'N')) - RandomizedBaseAddress = _False; - else - RandomizedBaseAddress = _True; - break; - case 0x33a3979: // /ENTRY:function - EntryPointSymbol = option+7; - break; - case 0x4504334: // /ERRORREPORT:[ NONE | PROMPT | QUEUE | SEND ] - if(*(option+12) == ':' ) { - if(*(option+13) == 'N') - LinkErrorReporting = "NoErrorReport"; - else if(*(option+13) == 'P') - LinkErrorReporting = "PromptImmediately"; - else if(*(option+13) == 'Q') - LinkErrorReporting = "QueueForNextLogin"; - else if(*(option+13) == 'S') - LinkErrorReporting = "SendErrorReport"; - } - break; - case 0x33aec94: // /FIXED[:NO] - if(*(option+6) == ':' && (*(option+7) == 'n' || *(option+7) == 'N')) - FixedBaseAddress = _False; - else - FixedBaseAddress = _True; - break; - case 0x33b4675: // /FORCE:[MULTIPLE|UNRESOLVED] - if(*(option+6) == ':' && *(option+7) == 'M' ) - ForceFileOutput = "MultiplyDefinedSymbolOnly"; - else if(*(option+6) == ':' && *(option+7) == 'U' ) - ForceFileOutput = "UndefinedSymbolOnly"; - else - ForceFileOutput = "Enabled"; - break; - case 0x96d4e4e: // /FUNCTIONPADMIN[:space] - if(*(option+15) == ':') { - if(*(option+16) == '5') - CreateHotPatchableImage = "X86Image"; - else if(*(option+16) == '6') - CreateHotPatchableImage = "X64Image"; - else if((*(option+16) == '1') && (*(option+17) == '6')) - CreateHotPatchableImage = "ItaniumImage"; - } else { - CreateHotPatchableImage = "Enabled"; - } - break; - case 0x033c960: // /HEAP:reserve[,commit] - { - QStringList both = QString(option+6).split(","); - HeapReserveSize = both[0].toLongLong(); - if(both.count() == 2) - HeapCommitSize = both[1].toLongLong(); - } - break; - case 0x3d91494: // /IDLOUT:[path\]filename - MergedIDLBaseFileName = option+8; - break; - case 0x345a04c: // /IGNOREIDL - IgnoreEmbeddedIDL = _True; - break; - case 0x3e250e2: // /IMPLIB:filename - ImportLibrary = option+8; - break; - case 0xe281ab5: // /INCLUDE:symbol - ForceSymbolReferences += option+9; - break; - case 0xb28103c: // /INCREMENTAL[:no] - if(*(option+12) == ':' && - (*(option+13) == 'n' || *(option+13) == 'N')) - LinkIncremental = _False; - else - LinkIncremental = _True; - break; - case 0x07f1ab2: // /KEYCONTAINER:name - KeyContainer = option+14; - break; - case 0xfadaf35: // /KEYFILE:filename - KeyFile = option+9; - break; - case 0x26e4675: // /LARGEADDRESSAWARE[:no] - if(*(option+18) == ':' && - *(option+19) == 'n') - LargeAddressAware = _False; - else - LargeAddressAware = _True; - break; - case 0x2f96bc8: // /libpath:dir - case 0x0d745c8: // /LIBPATH:dir - AdditionalLibraryDirectories += option+9; - break; - case 0x0341877: // /LTCG[:NOSTATUS|:STATUS] - config->WholeProgramOptimization = _True; - LinkTimeCodeGeneration = "UseLinkTimeCodeGeneration"; - if(*(option+5) == ':') { - const char* str = option+6; - if (*str == 'S') - LinkStatus = _True; - else if (*str == 'N') - LinkStatus = _False; -#ifndef Q_OS_WIN - else if (strncasecmp(str, "pginstrument", 12)) - LinkTimeCodeGeneration = "PGInstrument"; - else if (strncasecmp(str, "pgoptimize", 10)) - LinkTimeCodeGeneration = "PGOptimization"; - else if (strncasecmp(str, "pgupdate", 8 )) - LinkTimeCodeGeneration = "PGUpdate"; -#else - - else if (_stricmp(str, "pginstrument")) - LinkTimeCodeGeneration = "PGInstrument"; - else if (_stricmp(str, "pgoptimize")) - LinkTimeCodeGeneration = "PGOptimization"; - else if (_stricmp(str, "pgupdate")) - LinkTimeCodeGeneration = "PGUpdate"; -#endif - } - break; - case 0x379ED25: - case 0x157cf65: // /MACHINE:{AM33|ARM|CEE|IA64|X86|M32R|MIPS|MIPS16|MIPSFPU|MIPSFPU16|MIPSR41XX|PPC|SH3|SH4|SH5|THUMB|TRICORE} - switch (elfHash(option+9)) { - case 0x0005bb6: // X86 - TargetMachine = "MachineX86"; - break; - case 0x0005b94: // X64 - TargetMachine = "MachineX64"; - break; - case 0x000466d: // ARM - TargetMachine = "MachineARM"; - break; - case 0x0004963: // EBC - TargetMachine = "MachineEBC"; - break; - case 0x004d494: // IA64 - TargetMachine = "MachineIA64"; - break; - case 0x0051e53: // MIPS - TargetMachine = "MachineMIPS"; - break; - case 0x51e5646: // MIPS16 - TargetMachine = "MachineMIPS16"; - break; - case 0x1e57b05: // MIPSFPU - TargetMachine = "MachineMIPSFPU"; - break; - case 0x57b09a6: // MIPSFPU16 - TargetMachine = "MachineMIPSFPU16"; - break; - case 0x00057b4: // SH4 - TargetMachine = "MachineSH4"; - break; - case 0x058da12: // THUMB - TargetMachine = "MachineTHUMB"; - break; - // put the others in AdditionalOptions... - case 0x0046063: // AM33 - case 0x0004795: // CEE - case 0x0050672: // M32R - case 0x5852738: // MIPSR41XX - case 0x0005543: // PPC - case 0x00057b3: // SH3 - case 0x57b7980: // SH3DSP - case 0x00057b5: // SH5 - case 0x96d8435: // TRICORE - default: - AdditionalOptions += option; - break; - } - break; - case 0x62d9e94: // /MANIFEST[:NO] - if ((*(option+9) == ':' && (*(option+10) == 'N' || *(option+10) == 'n'))) - GenerateManifest = _False; - else - GenerateManifest = _True; - break; - case 0x8b64559: // /MANIFESTDEPENDENCY:manifest_dependency - AdditionalManifestDependencies += option+20; - break; - case 0xe9e8195: // /MANIFESTFILE:filename - ManifestFile = option+14; - break; - case 0x9e9fb83: // /MANIFESTUAC http://msdn.microsoft.com/en-us/library/bb384691%28VS.100%29.aspx - if ((*(option+12) == ':' && (*(option+13) == 'N' || *(option+13) == 'n'))) - EnableUAC = _False; - else if((*(option+12) == ':' && (*(option+13) == 'l' || *(option+14) == 'e'))) { // level - if(*(option+20) == 'a') - UACExecutionLevel = "AsInvoker"; - else if(*(option+20) == 'h') - UACExecutionLevel = "HighestAvailable"; - else if(*(option+20) == 'r') - UACExecutionLevel = "RequireAdministrator"; - } else if((*(option+12) == ':' && (*(option+13) == 'u' || *(option+14) == 'i'))) { // uiAccess - if(*(option+22) == 't') - UACUIAccess = _True; - else - UACUIAccess = _False; - } else if((*(option+12) == ':' && (*(option+13) == 'f' || *(option+14) == 'r'))) { // fragment - AdditionalOptions += option; - }else - EnableUAC = _True; - break; - case 0x0034160: // /MAP[:filename] - GenerateMapFile = _True; - if (option[4] == ':') - MapFileName = option+5; - break; - case 0x164e1ef: // /MAPINFO:{EXPORTS} - if(*(option+9) == 'E') - MapExports = _True; - break; - case 0x341a6b5: // /MERGE:from=to - MergeSections = option+7; - break; - case 0x0341d8c: // /MIDL:@file - MidlCommandFile = option+7; - break; - case 0x84e2679: // /NOASSEMBLY - TurnOffAssemblyGeneration = _True; - break; - case 0x2b21942: // /NODEFAULTLIB[:library] - if(*(option+13) == '\0') - IgnoreAllDefaultLibraries = _True; - else - IgnoreSpecificDefaultLibraries += option+14; - break; - case 0x33a3a39: // /NOENTRY - NoEntryPoint = _True; - break; - case 0x434138f: // /NOLOGO - SuppressStartupBanner = _True; - break; - case 0xc841054: // /NXCOMPAT[:NO] - if ((*(option+9) == ':' && (*(option+10) == 'N' || *(option+10) == 'n'))) - DataExecutionPrevention = _False; - else - DataExecutionPrevention = _True; - break; - case 0x0034454: // /OPT:{REF | NOREF | ICF[=iterations] | NOICF | WIN98 | NOWIN98} - { - char third = *(option+7); - switch (third) { - case 'F': // REF - if(*(option+5) == 'R') { - OptimizeReferences = _True; - } else { // ICF[=iterations] - EnableCOMDATFolding = _True; - // [=iterations] case is not documented - } - break; - case 'R': // NOREF - OptimizeReferences = _False; - break; - case 'I': // NOICF - EnableCOMDATFolding = _False; - break; - default: - found = false; - } - } - break; - case 0x34468a2: // /ORDER:@filename - FunctionOrder = option+8; - break; - case 0x00344a4: // /OUT:filename - OutputFile = option+5; - break; - case 0x0034482: // /PDB:filename - ProgramDatabaseFile = option+5; - break; - case 0xa2ad314: // /PDBSTRIPPED:pdb_file_name - StripPrivateSymbols = option+13; - break; - case 0x00344b4: // /PGD:filename - ProfileGuidedDatabase = option+5; - break; - case 0x573af45: // /PROFILE - Profile = _True; - break; - case 0x6a09535: // /RELEASE - SetChecksum = _True; - break; - case 0x75AA4D8: // /SAFESEH:{NO} - { - if(*(option+8) == ':' && *(option+9) == 'N') - ImageHasSafeExceptionHandlers = _False; - else - ImageHasSafeExceptionHandlers = _True; - } - break; - case 0x7988f7e: // /SECTION:name,[E][R][W][S][D][K][L][P][X][,ALIGN=#] - SpecifySectionAttributes = option+9; - break; - case 0x348857b: // /STACK:reserve[,commit] - { - QStringList both = QString(option+7).split(","); - StackReserveSize = both[0].toLongLong(); - if(both.count() == 2) - StackCommitSize = both[1].toLongLong(); - } - break; - case 0x0348992: // /STUB:filename - MSDOSStubFileName = option+6; - break; - case 0x9B3C00D: - case 0x78dc00d: // /SUBSYSTEM:{CONSOLE|EFI_APPLICATION|EFI_BOOT_SERVICE_DRIVER|EFI_ROM|EFI_RUNTIME_DRIVER|NATIVE|POSIX|WINDOWS|WINDOWSCE}[,major[.minor]] - { - // Split up in subsystem, and version number - QStringList both = QString(option+11).split(","); - switch (elfHash(both[0].toLatin1())) { - case 0x8438445: // CONSOLE - SubSystem = "Console"; - break; - case 0xbe29493: // WINDOWS - SubSystem = "Windows"; - break; - case 0x5268ea5: // NATIVE - SubSystem = "Native"; - break; - case 0x240949e: // EFI_APPLICATION - SubSystem = "EFI Application"; - break; - case 0xe617652: // EFI_BOOT_SERVICE_DRIVER - SubSystem = "EFI Boot Service Driver"; - break; - case 0x9af477d: // EFI_ROM - SubSystem = "EFI ROM"; - break; - case 0xd34df42: // EFI_RUNTIME_DRIVER - SubSystem = "EFI Runtime"; - break; - case 0x2949c95: // WINDOWSCE - SubSystem = "WindowsCE"; - break; - case 0x05547e8: // POSIX - SubSystem = "POSIX"; - break; - // The following are undocumented, so add them to AdditionalOptions - case 0x4B69795: // windowsce - AdditionalOptions += option; - break; - default: - found = false; - } - } - break; - case 0x8b654de: // /SWAPRUN:{NET | CD} - if(*(option+9) == 'N') - SwapRunFromNet = _True; - else if(*(option+9) == 'C') - SwapRunFromCD = _True; - else - found = false; - break; - case 0x34906d4: // /TLBID:id - TypeLibraryResourceID = QString(option+7).toLongLong(); - break; - case 0x4907494: // /TLBOUT:[path\]filename - TypeLibraryFile = option+8; - break; - case 0x976b525: // /TSAWARE[:NO] - if(*(option+8) == ':') - TerminalServerAware = _False; - else - TerminalServerAware = _True; - break; - case 0xaa67735: // /VERBOSE[:ICF |:LIB |:REF |:SAFESEH] - if(*(option+9) == ':') { - if (*(option+10) == 'I') { - ShowProgress = "LinkVerboseICF"; - } else if ( *(option+10) == 'L') { - ShowProgress = "LinkVerboseLib"; - } else if ( *(option+10) == 'R') { - ShowProgress = "LinkVerboseREF"; - } else if ( *(option+10) == 'S') { - ShowProgress = "LinkVerboseSAFESEH"; - } else if ( *(option+10) == 'C') { - ShowProgress = "LinkVerboseCLR"; - } - } else { - ShowProgress = "LinkVerbose"; - } - break; - case 0xaa77f7e: // /VERSION:major[.minor] - Version = option+9; - break; - case 0x0034c50: // /WS[:NO] - if(*(option+3) == ':') - TreatLinkerWarningAsErrors = _False; - else - TreatLinkerWarningAsErrors = _True; - break; - default: - AdditionalOptions += option; - break; - } - if(!found) { - warn_msg(WarnLogic, "Could not parse Linker options: %s, added as AdditionalOption", option); - AdditionalOptions += option; - } - return found; -} - -// VCMIDLTool ------------------------------------------------------- -VCXMIDLTool::VCXMIDLTool() - : ApplicationConfigurationMode(unset), - ErrorCheckAllocations(unset), - ErrorCheckBounds(unset), - ErrorCheckEnumRange(unset), - ErrorCheckRefPointers(unset), - ErrorCheckStubData(unset), - GenerateStublessProxies(unset), - GenerateTypeLibrary(unset), - IgnoreStandardIncludePath(unset), - LocaleID(-1), - MkTypLibCompatible(unset), - SuppressCompilerWarnings(unset), - SuppressStartupBanner(unset), - ValidateAllParameters(unset), - WarnAsError(unset) -{ -} - -XmlOutput &operator<<(XmlOutput &xml, const VCXMIDLTool &tool) -{ - return xml + xml << tag(_Midl) << attrTagX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories, ";") << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ") << attrTagT(_ApplicationConfigurationMode, tool.ApplicationConfigurationMode) << attrTagS(_ClientStubFile, tool.ClientStubFile) - << attrTagS(_CPreprocessOptions, tool.CPreprocessOptions) - << attrTagS(_DefaultCharType, tool.DefaultCharType) + << attrTagX(_CPreprocessOptions, tool.CPreprocessOptions, " ") + << attrTagS(_DefaultCharType, toString(tool.DefaultCharType)) << attrTagS(_DLLDataFileName, tool.DLLDataFileName) - << attrTagS(_EnableErrorChecks, tool.EnableErrorChecks) + << attrTagS(_EnableErrorChecks, toString(tool.EnableErrorChecks)) << attrTagT(_ErrorCheckAllocations, tool.ErrorCheckAllocations) << attrTagT(_ErrorCheckBounds, tool.ErrorCheckBounds) << attrTagT(_ErrorCheckEnumRange, tool.ErrorCheckEnumRange) @@ -1823,324 +1408,20 @@ XmlOutput &operator<<(XmlOutput &xml, const VCXMIDLTool &tool) << attrTagS(_ProxyFileName, tool.ProxyFileName) << attrTagS(_RedirectOutputAndErrors, tool.RedirectOutputAndErrors) << attrTagS(_ServerStubFile, tool.ServerStubFile) - << attrTagS(_StructMemberAlignment, tool.StructMemberAlignment) + << attrTagS(_StructMemberAlignment, toString(tool.StructMemberAlignment)) << attrTagT(_SuppressCompilerWarnings, tool.SuppressCompilerWarnings) << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) - << attrTagS(_TargetEnvironment, tool.TargetEnvironment) + << attrTagS(_TargetEnvironment, toString(tool.TargetEnvironment)) << attrTagS(_TypeLibFormat, tool.TypeLibFormat) << attrTagS(_TypeLibraryName, tool.TypeLibraryName) << attrTagX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions, ";") << attrTagT(_ValidateAllParameters, tool.ValidateAllParameters) << attrTagT(_WarnAsError, tool.WarnAsError) - << attrTagS(_WarningLevel, tool.WarningLevel) + << attrTagS(_WarningLevel, toString(tool.WarningLevel)) << closetag(_Midl); } -bool VCXMIDLTool::parseOption(const char* option) -{ -#ifdef USE_DISPLAY_HASH - displayHash("/D name[=def]"); displayHash("/I directory-list"); displayHash("/Oi"); - displayHash("/Oic"); displayHash("/Oicf"); displayHash("/Oif"); displayHash("/Os"); - displayHash("/U name"); displayHash("/WX"); displayHash("/W{0|1|2|3|4}"); - displayHash("/Zp {N}"); displayHash("/Zs"); displayHash("/acf filename"); - displayHash("/align {N}"); displayHash("/app_config"); displayHash("/c_ext"); - displayHash("/char ascii7"); displayHash("/char signed"); displayHash("/char unsigned"); - displayHash("/client none"); displayHash("/client stub"); displayHash("/confirm"); - displayHash("/cpp_cmd cmd_line"); displayHash("/cpp_opt options"); - displayHash("/cstub filename"); displayHash("/dlldata filename"); displayHash("/env win32"); - displayHash("/env win64"); displayHash("/error all"); displayHash("/error allocation"); - displayHash("/error bounds_check"); displayHash("/error enum"); displayHash("/error none"); - displayHash("/error ref"); displayHash("/error stub_data"); displayHash("/h filename"); - displayHash("/header filename"); displayHash("/iid filename"); displayHash("/lcid"); - displayHash("/mktyplib203"); displayHash("/ms_ext"); displayHash("/ms_union"); - displayHash("/msc_ver <nnnn>"); displayHash("/newtlb"); displayHash("/no_cpp"); - displayHash("/no_def_idir"); displayHash("/no_default_epv"); displayHash("/no_format_opt"); - displayHash("/no_warn"); displayHash("/nocpp"); displayHash("/nologo"); displayHash("/notlb"); - displayHash("/o filename"); displayHash("/oldnames"); displayHash("/oldtlb"); - displayHash("/osf"); displayHash("/out directory"); displayHash("/pack {N}"); - displayHash("/prefix all"); displayHash("/prefix client"); displayHash("/prefix server"); - displayHash("/prefix switch"); displayHash("/protocol all"); displayHash("/protocol dce"); - displayHash("/protocol ndr64"); displayHash("/proxy filename"); displayHash("/robust"); - displayHash("/rpcss"); displayHash("/savePP"); displayHash("/server none"); - displayHash("/server stub"); displayHash("/sstub filename"); displayHash("/syntax_check"); - displayHash("/target {system}"); displayHash("/tlb filename"); displayHash("/use_epv"); - displayHash("/win32"); displayHash("/win64"); -#endif - bool found = true; - int offset = 0; - switch(elfHash(option)) { - case 0x0000334: // /D name[=def] - PreprocessorDefinitions += option+3; - break; - case 0x0000339: // /I directory-list - AdditionalIncludeDirectories += option+3; - break; - case 0x0345f96: // /Oicf - case 0x00345f6: // /Oif - GenerateStublessProxies = _True; - break; - case 0x0000345: // /U name - UndefinePreprocessorDefinitions += option+3; - break; - case 0x00034c8: // /WX - WarnAsError = _True; - break; - case 0x3582fde: // /align {N} - offset = 3; // Fallthrough - case 0x0003510: // /Zp {N} - switch (*(option+offset+4)) { - case '1': - StructMemberAlignment = (*(option+offset+5) == '\0') ? "1" : "16"; - break; - case '2': - StructMemberAlignment = "2"; - break; - case '4': - StructMemberAlignment = "4"; - break; - case '8': - StructMemberAlignment = "8"; - break; - default: - found = false; - } - break; - case 0x5b1cb97: // /app_config - ApplicationConfigurationMode = _True; - break; - case 0x0359e82: // /char {ascii7|signed|unsigned} - switch(*(option+6)) { - case 'a': - DefaultCharType = "Ascii"; - break; - case 's': - DefaultCharType = "Signed"; - break; - case 'u': - DefaultCharType = "Unsigned"; - break; - default: - found = false; - } - break; - case 0x5a2fc64: // /client {none|stub} - if(*(option+8) == 's') - GenerateClientFiles = "Stub"; - else - GenerateClientFiles = "None"; - break; - case 0xa766524: // /cpp_opt options - CPreprocessOptions += option+9; - break; - case 0x35aabb2: // /cstub filename - ClientStubFile = option+7; - break; - case 0xb32abf1: // /dlldata filename - DLLDataFileName = option + 9; - break; - case 0x0035c56: // /env {win32|ia64|x64} - if(*(option+7) == 'w' && *(option+10) == '3') - TargetEnvironment = "Win32"; - else if(*(option+7) == 'i') - TargetEnvironment = "Itanium"; - else if(*(option+7) == 'x') - TargetEnvironment = "X64"; - else - AdditionalOptions += option; - break; - case 0x35c9962: // /error {all|allocation|bounds_check|enum|none|ref|stub_data} - EnableErrorChecks = midlEnableCustom; - switch (*(option+7)) { - case '\0': - EnableErrorChecks = "EnableCustom"; - break; - case 'a': - if(*(option+10) == '\0') - EnableErrorChecks = "All"; - else - ErrorCheckAllocations = _True; - break; - case 'b': - ErrorCheckBounds = _True; - break; - case 'e': - ErrorCheckEnumRange = _True; - break; - case 'n': - EnableErrorChecks = "None"; - break; - case 'r': - ErrorCheckRefPointers = _True; - break; - case 's': - ErrorCheckStubData = _True; - break; - default: - found = false; - } - break; - case 0x5eb7af2: // /header filename - offset = 5; - case 0x0000358: // /h filename - HeaderFileName = option + offset + 3; - break; - case 0x0035ff4: // /iid filename - InterfaceIdentifierFileName = option+5; - break; - case 0x64b7933: // /mktyplib203 - MkTypLibCompatible = _True; - break; - case 0x64ceb12: // /newtlb - TypeLibFormat = "NewFormat"; - break; - case 0x8e0b0a2: // /no_def_idir - IgnoreStandardIncludePath = _True; - break; - case 0x65635ef: // /nologo - SuppressStartupBanner = _True; - break; - case 0x695e9f4: // /no_robust - ValidateAllParameters = _False; - break; - case 0x3656b22: // /notlb - GenerateTypeLibrary = _True; - break; - case 0x556dbee: // /no_warn - SuppressCompilerWarnings = _True; - break; - case 0x000035f: // /o filename - RedirectOutputAndErrors = option+3; - break; - case 0x662bb12: // /oldtlb - TypeLibFormat = "OldFormat"; - break; - case 0x00366c4: // /out directory - OutputDirectory = option+5; - break; - case 0x36796f9: // /proxy filename - ProxyFileName = option+7; - break; - case 0x6959c94: // /robust - ValidateAllParameters = _True; - break; - case 0x69c9cf2: // /server {none|stub} - if(*(option+8) == 's') - GenerateServerFiles = "Stub"; - else - GenerateServerFiles = "None"; - break; - case 0x36aabb2: // /sstub filename - ServerStubFile = option+7; - break; - case 0x0036b22: // /tlb filename - TypeLibraryName = option+5; - break; - case 0x36e0162: // /win32 - TargetEnvironment = "Win32"; - break; - case 0x36e0194: // /win64 - TargetEnvironment = "Itanium"; - break; - case 0x0003459: // /Oi - case 0x00345f3: // /Oic - case 0x0003463: // /Os - case 0x0003513: // /Zs - case 0x0035796: // /acf filename - case 0x3595cf4: // /c_ext - case 0xa64d3dd: // /confirm - case 0xa765b64: // /cpp_cmd cmd_line - case 0x03629f4: // /lcid - case 0x6495cc4: // /ms_ext - case 0x96c7a1e: // /ms_union - case 0x4996fa2: // /msc_ver <nnnn> - case 0x6555a40: // /no_cpp - case 0xf64d6a6: // /no_default_epv - case 0x6dd9384: // /no_format_opt - case 0x3655a70: // /nocpp - case 0x2b455a3: // /oldnames - case 0x0036696: // /osf - case 0x036679b: // /pack {N} - case 0x678bd38: // /prefix {all|client|server|switch} - case 0x96b702c: // /protocol {all|dce|ndr64} - case 0x3696aa3: // /rpcss - case 0x698ca60: // /savePP - case 0xce9b12b: // /syntax_check - case 0xc9b5f16: // /use_epv - AdditionalOptions += option; - break; - default: - // /W{0|1|2|3|4} case - if(*(option+1) == 'W') { - switch (*(option+2)) { - case '0': - WarningLevel = "0"; - break; - case '1': - WarningLevel = "1"; - break; - case '2': - WarningLevel = "2"; - break; - case '3': - WarningLevel = "3"; - break; - case '4': - WarningLevel = "4"; - break; - default: - found = false; - } - } - break; - } - if(!found) - warn_msg(WarnLogic, "Could not parse MIDL option: %s", option); - return true; -} - -// VCLibrarianTool -------------------------------------------------- -VCXLibrarianTool::VCXLibrarianTool() - : IgnoreAllDefaultLibraries(unset), - LinkTimeCodeGeneration(unset), - SuppressStartupBanner(_True), - TreatLibWarningAsErrors(unset), - Verbose(unset) -{ -} - -XmlOutput &operator<<(XmlOutput &xml, const VCXLibrarianTool &tool) -{ - return xml - << tag(_Link) - << attrTagX(_AdditionalDependencies, tool.AdditionalDependencies, ";") - << attrTagX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories, ";") - << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ") - << attrTagS(_DisplayLibrary, tool.DisplayLibrary) - << attrTagS(_ErrorReporting, tool.ErrorReporting) - << attrTagX(_ExportNamedFunctions, tool.ExportNamedFunctions, ";") - << attrTagX(_ForceSymbolReferences, tool.ForceSymbolReferences, ";") - << attrTagT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries) - << attrTagX(_IgnoreSpecificDefaultLibraries, tool.IgnoreSpecificDefaultLibraries, ";") - << attrTagT(_LinkTimeCodeGeneration, tool.LinkTimeCodeGeneration) - << attrTagS(_ModuleDefinitionFile, tool.ModuleDefinitionFile) - << attrTagS(_Name, tool.Name) - << attrTagS(_OutputFile, tool.OutputFile) - << attrTagX(_RemoveObjects, tool.RemoveObjects, ";") - << attrTagS(_SubSystem, tool.SubSystem) - << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) - << attrTagS(_TargetMachine, tool.TargetMachine) - << attrTagT(_TreatLibWarningAsErrors, tool.TreatLibWarningAsErrors) - << attrTagT(_Verbose, tool.Verbose) - << closetag(_Link); -} - -// VCCustomBuildTool ------------------------------------------------ -VCXCustomBuildTool::VCXCustomBuildTool() -{ - ToolName = "VCXCustomBuildTool"; -} - -XmlOutput &operator<<(XmlOutput &xml, const VCXCustomBuildTool &tool) +void VCXProjectWriter::write(XmlOutput &xml, const VCCustomBuildTool &tool) { // The code below offers two ways to split custom build step commands. // Normally the $$escape_expand(\n\t) is used in a project file, which is correctly translated @@ -2168,124 +1449,98 @@ XmlOutput &operator<<(XmlOutput &xml, const VCXCustomBuildTool &tool) cmds += cmdl; } + const QString &configName = tool.config->Name; + if ( !tool.AdditionalDependencies.isEmpty() ) { xml << tag("AdditionalInputs") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.ConfigName)) + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(configName)) << valueTagDefX(tool.AdditionalDependencies, "AdditionalInputs", ";"); } if( !cmds.isEmpty() ) { xml << tag("Command") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.ConfigName)) + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(configName)) << valueTag(cmds); } if ( !tool.Description.isEmpty() ) { xml << tag("Message") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.ConfigName)) + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(configName)) << valueTag(tool.Description); } if ( !tool.Outputs.isEmpty() ) { xml << tag("Outputs") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.ConfigName)) + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(configName)) << valueTagDefX(tool.Outputs, "Outputs", ";"); } - - return xml; } -// VCResourceCompilerTool ------------------------------------------- -VCXResourceCompilerTool::VCXResourceCompilerTool() - : IgnoreStandardIncludePath(unset), - NullTerminateStrings(unset), - ShowProgress(unset), - SuppressStartupBanner(unset) +void VCXProjectWriter::write(XmlOutput &xml, const VCLibrarianTool &tool) { - PreprocessorDefinitions = QStringList("NDEBUG"); + xml + << tag(_Link) + << attrTagX(_AdditionalDependencies, tool.AdditionalDependencies, ";") + << attrTagX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories, ";") + << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ") +//unused << attrTagS(_DisplayLibrary, tool.DisplayLibrary) +//unused << attrTagS(_ErrorReporting, tool.ErrorReporting) + << attrTagX(_ExportNamedFunctions, tool.ExportNamedFunctions, ";") + << attrTagX(_ForceSymbolReferences, tool.ForceSymbolReferences, ";") + << attrTagT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries) + << attrTagX(_IgnoreSpecificDefaultLibraries, tool.IgnoreDefaultLibraryNames, ";") +//unused << attrTagT(_LinkTimeCodeGeneration, tool.LinkTimeCodeGeneration) + << attrTagS(_ModuleDefinitionFile, tool.ModuleDefinitionFile) +//unused << attrTagS(_Name, tool.Name) + << attrTagS(_OutputFile, tool.OutputFile) +//unused << attrTagX(_RemoveObjects, tool.RemoveObjects, ";") +//unused << attrTagS(_SubSystem, tool.SubSystem) + << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) +//unused << attrTagS(_TargetMachine, tool.TargetMachine) +//unused << attrTagT(_TreatLibWarningAsErrors, tool.TreatLibWarningAsErrors) +//unused << attrTagT(_Verbose, tool.Verbose) + << closetag(_Link); } -XmlOutput &operator<<(XmlOutput &xml, const VCXResourceCompilerTool &tool) +void VCXProjectWriter::write(XmlOutput &xml, const VCResourceCompilerTool &tool) { - return xml + xml << tag(_ResourceCompile) << attrTagX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories, ";") - << attrTagS(_AdditionalOptions, tool.AdditionalOptions) - << attrTagS(_Culture, tool.Culture) + << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ") + << attrTagS(_Culture, toString(tool.Culture)) << attrTagT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) - << attrTagT(_NullTerminateStrings, tool.NullTerminateStrings) +//unused << attrTagT(_NullTerminateStrings, tool.NullTerminateStrings) << attrTagX(_PreprocessorDefinitions, tool.PreprocessorDefinitions, ";") << attrTagS(_ResourceOutputFileName, tool.ResourceOutputFileName) - << attrTagT(_ShowProgress, tool.ShowProgress) + << attrTagT(_ShowProgress, toTriState(tool.ShowProgress)) << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) - << attrTagS(_TrackerLogDirectory, tool.TrackerLogDirectory) - << attrTagS(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions) +//unused << attrTagS(_TrackerLogDirectory, tool.TrackerLogDirectory) +//unused << attrTagS(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions) << closetag(_ResourceCompile); } -// VCXDeploymentTool -------------------------------------------- -VCXDeploymentTool::VCXDeploymentTool() -{ - DeploymentTag = "DeploymentTool"; - RemoteDirectory = ""; -} - -// http://msdn.microsoft.com/en-us/library/sa69he4t.aspx -XmlOutput &operator<<(XmlOutput &xml, const VCXDeploymentTool &tool) +void VCXProjectWriter::write(XmlOutput &xml, const VCEventTool &tool) { - if (tool.AdditionalFiles.isEmpty()) - return xml; - return xml - << tag(tool.DeploymentTag) - << closetag(tool.DeploymentTag); -} - -// VCEventTool ------------------------------------------------- -XmlOutput &operator<<(XmlOutput &xml, const VCXEventTool &tool) -{ - return xml + xml << tag(tool.EventName) << attrTagS(_Command, tool.CommandLine) << attrTagS(_Message, tool.Description) << closetag(tool.EventName); } -// VCXPostBuildEventTool --------------------------------------------- -VCXPostBuildEventTool::VCXPostBuildEventTool() -{ - EventName = "PostBuildEvent"; -} - -// VCXPreBuildEventTool ---------------------------------------------- -VCXPreBuildEventTool::VCXPreBuildEventTool() -{ - EventName = "PreBuildEvent"; -} - -// VCXPreLinkEventTool ----------------------------------------------- -VCXPreLinkEventTool::VCXPreLinkEventTool() -{ - EventName = "PreLinkEvent"; -} - -// VCConfiguration -------------------------------------------------- - -VCXConfiguration::VCXConfiguration() - : ATLMinimizesCRunTimeLibraryUsage(unset), - BuildBrowserInformation(unset), - RegisterOutput(unset), - WholeProgramOptimization(unset) +void VCXProjectWriter::write(XmlOutput &xml, const VCDeploymentTool &tool) { - compiler.config = this; - linker.config = this; - idl.config = this; + Q_UNUSED(xml); + Q_UNUSED(tool); + // SmartDevice deployment not supported in VS 2010 } -XmlOutput &operator<<(XmlOutput &xml, const VCXConfiguration &tool) +void VCXProjectWriter::write(XmlOutput &xml, const VCConfiguration &tool) { xml << tag("PropertyGroup") << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Name)) @@ -2293,714 +1548,155 @@ XmlOutput &operator<<(XmlOutput &xml, const VCXConfiguration &tool) << attrTagS(_OutputDirectory, tool.OutputDirectory) << attrTagT(_ATLMinimizesCRunTimeLibraryUsage, tool.ATLMinimizesCRunTimeLibraryUsage) << attrTagT(_BuildBrowserInformation, tool.BuildBrowserInformation) - << attrTagS(_CharacterSet, tool.CharacterSet) - << attrTagS(_ConfigurationType, tool.ConfigurationType) + << attrTagS(_CharacterSet, toString(tool.CharacterSet)) + << attrTagS(_ConfigurationType, toString(tool.ConfigurationType)) << attrTagS(_DeleteExtensionsOnClean, tool.DeleteExtensionsOnClean) << attrTagS(_ImportLibrary, tool.ImportLibrary) << attrTagS(_IntermediateDirectory, tool.IntermediateDirectory) << attrTagS(_PrimaryOutput, tool.PrimaryOutput) << attrTagS(_ProgramDatabase, tool.ProgramDatabase) << attrTagT(_RegisterOutput, tool.RegisterOutput) - << attrTagS(_UseOfATL, tool.UseOfATL) - << attrTagS(_UseOfMfc, tool.UseOfMfc) + << attrTagS(_UseOfATL, toString(tool.UseOfATL)) + << attrTagS(_UseOfMfc, toString(tool.UseOfMfc)) << attrTagT(_WholeProgramOptimization, tool.WholeProgramOptimization) << closetag(); - return xml; -} -// VCXFilter --------------------------------------------------------- -VCXFilter::VCXFilter() - : ParseFiles(unset), - Config(0) -{ - useCustomBuildTool = false; - useCompilerTool = false; } -void VCXFilter::addFile(const QString& filename) +void VCXProjectWriter::write(XmlOutput &xml, VCFilter &tool) { - Files += VCXFilterFile(filename); + Q_UNUSED(xml); + Q_UNUSED(tool); + // unused in this generator } -void VCXFilter::addFile(const VCXFilterFile& fileInfo) +void VCXProjectWriter::addFilters(VCProject &project, XmlOutput &xmlFilter, const QString &filtername) { - Files += VCXFilterFile(fileInfo); -} - -void VCXFilter::addFiles(const QStringList& fileList) -{ - for (int i = 0; i < fileList.count(); ++i) - addFile(fileList.at(i)); -} + bool added = false; -void VCXFilter::modifyPCHstage(QString str) -{ - bool autogenSourceFile = Project->autogenPrecompCPP; - bool pchThroughSourceFile = !Project->precompCPP.isEmpty(); - bool isCFile = false; - for (QStringList::Iterator it = Option::c_ext.begin(); it != Option::c_ext.end(); ++it) { - if (str.endsWith(*it)) { - isCFile = true; - break; + for (int i = 0; i < project.SingleProjects.count(); ++i) { + VCFilter filter; + const VCProjectSingleConfig &singleCfg = project.SingleProjects.at(i); + if (filtername == "Root Files") { + filter = singleCfg.RootFiles; + } else if (filtername == "Source Files") { + filter = singleCfg.SourceFiles; + } else if (filtername == "Header Files") { + filter = singleCfg.HeaderFiles; + } else if (filtername == "Generated Files") { + filter = singleCfg.GeneratedFiles; + } else if (filtername == "LexYacc Files") { + filter = singleCfg.LexYaccFiles; + } else if (filtername == "Translation Files") { + filter = singleCfg.TranslationFiles; + } else if (filtername == "Form Files") { + filter = singleCfg.FormFiles; + } else if (filtername == "Resource Files") { + filter = singleCfg.ResourceFiles; + } else { + // ExtraCompilers + filter = project.SingleProjects[i].filterForExtraCompiler(filtername); } - } - bool isHFile = str.endsWith(".h") && (str == Project->precompH); - bool isCPPFile = pchThroughSourceFile && (str == Project->precompCPP); - - if(!isCFile && !isHFile && !isCPPFile) - return; - if(isHFile && pchThroughSourceFile) { - if (autogenSourceFile) { - useCustomBuildTool = true; - QString toFile(Project->precompCPP); - CustomBuildTool.Description = "Generating precompiled header source file '" + toFile + "' ..."; - CustomBuildTool.Outputs += toFile; - - QStringList lines; - CustomBuildTool.CommandLine += - "echo /*-------------------------------------------------------------------- >" + toFile; - lines << "* Precompiled header source file used by Visual Studio.NET to generate"; - lines << "* the .pch file."; - lines << "*"; - lines << "* Due to issues with the dependencies checker within the IDE, it"; - lines << "* sometimes fails to recompile the PCH file, if we force the IDE to"; - lines << "* create the PCH file directly from the header file."; - lines << "*"; - lines << "* This file is auto-generated by qmake since no PRECOMPILED_SOURCE was"; - lines << "* specified, and is used as the common stdafx.cpp. The file is only"; - lines << "* generated when creating .vcxproj project files, and is not used for"; - lines << "* command line compilations by nmake."; - lines << "*"; - lines << "* WARNING: All changes made in this file will be lost."; - lines << "--------------------------------------------------------------------*/"; - lines << "#include \"" + Project->precompHFilename + "\""; - foreach(QString line, lines) - CustomBuildTool.CommandLine += "echo " + line + ">>" + toFile; + if(!filter.Files.isEmpty() && !added) { + xmlFilter << tag("Filter") + << attrTag("Include", filtername) + << attrTagS("UniqueIdentifier", filter.Guid) + << attrTagS("Extensions", filter.Filter) + << attrTagT("ParseFiles", filter.ParseFiles) + << closetag(); } - return; } - - useCompilerTool = true; - // Setup PCH options - CompilerTool.PrecompiledHeader = (isCFile ? "NotUsing" : "Create" ); - CompilerTool.PrecompiledHeaderFile = (isCPPFile ? QString("$(INHERIT)") : QString("$(NOINHERIT)")); - CompilerTool.ForcedIncludeFiles = QStringList("$(NOINHERIT)"); } -bool VCXFilter::addExtraCompiler(const VCXFilterFile &info) +// outputs a given filter for all existing configurations of a project +void VCXProjectWriter::outputFilter(VCProject &project, XmlOutput &xml, XmlOutput &xmlFilter, const QString &filtername) { - const QStringList &extraCompilers = Project->extraCompilerSources.value(info.file); - if (extraCompilers.isEmpty()) - return false; - - QString inFile = info.file; - - // is the extracompiler rule on a file with a built in compiler? - const QStringList &objectMappedFile = Project->extraCompilerOutputs[inFile]; - bool hasBuiltIn = false; - if (!objectMappedFile.isEmpty()) { - hasBuiltIn = Project->hasBuiltinCompiler(objectMappedFile.at(0)); -// qDebug("*** Extra compiler file has object mapped file '%s' => '%s'", qPrintable(inFile), qPrintable(objectMappedFile.join(" "))); - } - - CustomBuildTool.AdditionalDependencies.clear(); - CustomBuildTool.CommandLine.clear(); - CustomBuildTool.Description.clear(); - CustomBuildTool.Outputs.clear(); - CustomBuildTool.ToolPath.clear(); - CustomBuildTool.ToolName = QLatin1String(_VCCustomBuildTool); - - for (int x = 0; x < extraCompilers.count(); ++x) { - const QString &extraCompilerName = extraCompilers.at(x); - - if (!Project->verifyExtraCompiler(extraCompilerName, inFile) && !hasBuiltIn) - continue; - - // All information about the extra compiler - QString tmp_out = Project->project->first(extraCompilerName + ".output"); - QString tmp_cmd = Project->project->variables()[extraCompilerName + ".commands"].join(" "); - QString tmp_cmd_name = Project->project->variables()[extraCompilerName + ".name"].join(" "); - QStringList tmp_dep = Project->project->variables()[extraCompilerName + ".depends"]; - QString tmp_dep_cmd = Project->project->variables()[extraCompilerName + ".depend_command"].join(" "); - QStringList vars = Project->project->variables()[extraCompilerName + ".variables"]; - QStringList configs = Project->project->variables()[extraCompilerName + ".CONFIG"]; - bool combined = configs.indexOf("combine") != -1; - - QString cmd, cmd_name, out; - QStringList deps, inputs; - // Variabel replacement of output name - out = Option::fixPathToTargetOS( - Project->replaceExtraCompilerVariables(tmp_out, inFile, QString()), - false); - - // If file has built-in compiler, we've swapped the input and output of - // the command, as we in Visual Studio cannot have a Custom Buildstep on - // a file which uses a built-in compiler. We would in this case only get - // the result from the extra compiler. If 'hasBuiltIn' is true, we know - // that we're actually on the _output_file_ of the result, and we - // therefore swap inFile and out below, since the extra-compiler still - // must see it as the original way. If the result also has a built-in - // compiler, too bad.. - if (hasBuiltIn) { - out = inFile; - inFile = objectMappedFile.at(0); - } + XNode *root; + if (project.SingleProjects.at(0).flat_files) + root = new XFlatNode; + else + root = new XTreeNode; - // Dependency for the output - if(!tmp_dep.isEmpty()) - deps = tmp_dep; - if(!tmp_dep_cmd.isEmpty()) { - // Execute dependency command, and add every line as a dep - char buff[256]; - QString dep_cmd = Project->replaceExtraCompilerVariables(tmp_dep_cmd, Option::fixPathToLocalOS(inFile, true, false), out); - if(Project->canExecute(dep_cmd)) { - if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) { - QString indeps; - while(!feof(proc)) { - int read_in = (int)fread(buff, 1, 255, proc); - if(!read_in) - break; - indeps += QByteArray(buff, read_in); - } - QT_PCLOSE(proc); - if(!indeps.isEmpty()) { - QStringList extradeps = indeps.split(QLatin1Char('\n')); - for (int i = 0; i < extradeps.count(); ++i) { - QString dd = extradeps.at(i).simplified(); - if (!dd.isEmpty()) - deps += Project->fileFixify(dd); - } - } - } - } - } - for (int i = 0; i < deps.count(); ++i) - deps[i] = Option::fixPathToTargetOS( - Project->replaceExtraCompilerVariables(deps.at(i), inFile, out), - false).trimmed(); - // Command for file - if (combined) { - // Add dependencies for each file - QStringList tmp_in = Project->project->variables()[extraCompilerName + ".input"]; - for (int a = 0; a < tmp_in.count(); ++a) { - const QStringList &files = Project->project->variables()[tmp_in.at(a)]; - for (int b = 0; b < files.count(); ++b) { - deps += Project->findDependencies(files.at(b)); - inputs += Option::fixPathToTargetOS(files.at(b), false); - } - } - deps += inputs; // input files themselves too.. + QString name, extfilter; + triState parse; - // Replace variables for command w/all input files - // ### join gives path issues with directories containing spaces! - cmd = Project->replaceExtraCompilerVariables(tmp_cmd, - inputs.join(" "), - out); + for (int i = 0; i < project.SingleProjects.count(); ++i) { + VCFilter filter; + const VCProjectSingleConfig &singleCfg = project.SingleProjects.at(i); + if (filtername == "Root Files") { + filter = singleCfg.RootFiles; + } else if (filtername == "Source Files") { + filter = singleCfg.SourceFiles; + } else if (filtername == "Header Files") { + filter = singleCfg.HeaderFiles; + } else if (filtername == "Generated Files") { + filter = singleCfg.GeneratedFiles; + } else if (filtername == "LexYacc Files") { + filter = singleCfg.LexYaccFiles; + } else if (filtername == "Translation Files") { + filter = singleCfg.TranslationFiles; + } else if (filtername == "Form Files") { + filter = singleCfg.FormFiles; + } else if (filtername == "Resource Files") { + filter = singleCfg.ResourceFiles; } else { - deps += inFile; // input file itself too.. - cmd = Project->replaceExtraCompilerVariables(tmp_cmd, - inFile, - out); - } - // Name for command - if(!tmp_cmd_name.isEmpty()) { - cmd_name = Project->replaceExtraCompilerVariables(tmp_cmd_name, inFile, out); - } else { - int space = cmd.indexOf(' '); - if(space != -1) - cmd_name = cmd.left(space); - else - cmd_name = cmd; - if((cmd_name[0] == '\'' || cmd_name[0] == '"') && - cmd_name[0] == cmd_name[cmd_name.length()-1]) - cmd_name = cmd_name.mid(1,cmd_name.length()-2); - } - - // Fixify paths - for (int i = 0; i < deps.count(); ++i) - deps[i] = Option::fixPathToTargetOS(deps[i], false); - - - // Output in info.additionalFile ----------- - if (!CustomBuildTool.Description.isEmpty()) - CustomBuildTool.Description += " & "; - CustomBuildTool.Description += cmd_name; - CustomBuildTool.CommandLine += cmd.trimmed().split("\n", QString::SkipEmptyParts); - int space = cmd.indexOf(' '); - QFileInfo finf(cmd.left(space)); - if (CustomBuildTool.ToolPath.isEmpty()) - CustomBuildTool.ToolPath += Option::fixPathToTargetOS(finf.path()); - CustomBuildTool.Outputs += out; - - deps += CustomBuildTool.AdditionalDependencies; - deps += cmd.left(cmd.indexOf(' ')); - // Make sure that all deps are only once - QMap<QString, bool> uniqDeps; - for (int c = 0; c < deps.count(); ++c) { - QString aDep = deps.at(c).trimmed(); - if (!aDep.isEmpty()) - uniqDeps[aDep] = false; - } - CustomBuildTool.AdditionalDependencies = uniqDeps.keys(); - } - - // Ensure that none of the output files are also dependencies. Or else, the custom buildstep - // will be rebuild every time, even if nothing has changed. - foreach(QString output, CustomBuildTool.Outputs) { - CustomBuildTool.AdditionalDependencies.removeAll(output); - } - - useCustomBuildTool = !CustomBuildTool.CommandLine.isEmpty(); - return useCustomBuildTool; -} - -bool VCXFilter::outputFileConfig(XmlOutput &xml, XmlOutput &xmlFilter, const QString &filename, const QString &filtername, bool fileAllreadyAdded) -{ - bool fileAdded = false; - - // Clearing each filter tool - useCustomBuildTool = false; - useCompilerTool = false; - CustomBuildTool = VCXCustomBuildTool(); - CompilerTool = VCXCLCompilerTool(); - - // Unset some default options - CompilerTool.BufferSecurityCheck = unset; - CompilerTool.DebugInformationFormat = ""; - CompilerTool.ExceptionHandling = ""; - //CompilerTool.Optimization = optimizeDefault; - CompilerTool.ProgramDataBaseFileName.clear(); - CompilerTool.RuntimeLibrary = ""; - //CompilerTool.WarningLevel = warningLevelUnknown; - CompilerTool.config = Config; - - bool inBuild = false; - VCXFilterFile info; - for (int i = 0; i < Files.count(); ++i) { - if (Files.at(i).file == filename) { - info = Files.at(i); - inBuild = true; - } - } - inBuild &= !info.excludeFromBuild; - - if (inBuild) { - addExtraCompiler(info); - if(Project->usePCH) - modifyPCHstage(info.file); - } else { - // Excluded files uses an empty compiler stage - if(info.excludeFromBuild) - useCompilerTool = true; - } - - // Actual XML output ---------------------------------- - if(useCustomBuildTool || useCompilerTool || !inBuild) { - - if (useCustomBuildTool) - { - CustomBuildTool.ConfigName = (*Config).Name; - - if ( !fileAllreadyAdded ) { - - fileAdded = true; - - xmlFilter << tag("CustomBuild") - << attrTag("Include",Option::fixPathToLocalOS(filename)) - << attrTagS("Filter", filtername); - - xml << tag("CustomBuild") - << attrTag("Include",Option::fixPathToLocalOS(filename)); - - if ( filtername == "Form Files" || filtername == "Generated Files" || filtername == "Resource Files" ) - xml << attrTagS("FileType", "Document"); - } - - xml << CustomBuildTool; - } - - if ( !fileAdded && !fileAllreadyAdded ) - { - fileAdded = true; - - if (filtername == "Source Files") { - - xmlFilter << tag("ClCompile") - << attrTag("Include",Option::fixPathToLocalOS(filename)) - << attrTagS("Filter", filtername); - - xml << tag("ClCompile") - << attrTag("Include",Option::fixPathToLocalOS(filename)); - - } else if(filtername == "Header Files") { - - xmlFilter << tag("ClInclude") - << attrTag("Include",Option::fixPathToLocalOS(filename)) - << attrTagS("Filter", filtername); - - xml << tag("ClInclude") - << attrTag("Include",Option::fixPathToLocalOS(filename)); - } else if(filtername == "Generated Files" || filtername == "Form Files") { - - if (filename.endsWith(".h")) { - - xmlFilter << tag("ClInclude") - << attrTag("Include",Option::fixPathToLocalOS(filename)) - << attrTagS("Filter", filtername); - - xml << tag("ClInclude") - << attrTag("Include",Option::fixPathToLocalOS(filename)); - } else if(filename.endsWith(".cpp")) { - - xmlFilter << tag("ClCompile") - << attrTag("Include",Option::fixPathToLocalOS(filename)) - << attrTagS("Filter", filtername); - - xml << tag("ClCompile") - << attrTag("Include",Option::fixPathToLocalOS(filename)); - } else if(filename.endsWith(".res")) { - - xmlFilter << tag("CustomBuild") - << attrTag("Include",Option::fixPathToLocalOS(filename)) - << attrTagS("Filter", filtername); - - xml << tag("CustomBuild") - << attrTag("Include",Option::fixPathToLocalOS(filename)); - } else { - - xmlFilter << tag("CustomBuild") - << attrTag("Include",Option::fixPathToLocalOS(filename)) - << attrTagS("Filter", filtername); - - xml << tag("CustomBuild") - << attrTag("Include",Option::fixPathToLocalOS(filename)); - } - } else if(filtername == "Root Files") { - - if (filename.endsWith(".rc")) { - - xmlFilter << tag("ResourceCompile") - << attrTag("Include",Option::fixPathToLocalOS(filename)); - - xml << tag("ResourceCompile") - << attrTag("Include",Option::fixPathToLocalOS(filename)); - } - } - } - - if(!inBuild) { - - xml << tag("ExcludedFromBuild") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg((*Config).Name)) - << valueTag("true"); - } - - if (useCompilerTool) { - - if ( !CompilerTool.ForcedIncludeFiles.isEmpty() ) { - xml << tag("ForcedIncludeFiles") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg((*Config).Name)) - << valueTagX(CompilerTool.ForcedIncludeFiles); - } - - if ( !CompilerTool.PrecompiledHeaderFile.isEmpty() ) { - - xml << tag("PrecompiledHeaderFile") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg((*Config).Name)) - << valueTag(CompilerTool.PrecompiledHeaderFile); - } - - if ( !CompilerTool.PrecompiledHeader.isEmpty() ) { - - xml << tag("PrecompiledHeader") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg((*Config).Name)) - << valueTag(CompilerTool.PrecompiledHeader); - } + // ExtraCompilers + filter = project.SingleProjects[i].filterForExtraCompiler(filtername); } - } - - return fileAdded; -} - - -// VCXProjectSingleConfig -------------------------------------------- -VCXFilter nullVCXFilter; -VCXFilter& VCXProjectSingleConfig::filterForExtraCompiler(const QString &compilerName) -{ - for (int i = 0; i < ExtraCompilersFiles.count(); ++i) - if (ExtraCompilersFiles.at(i).Name == compilerName) - return ExtraCompilersFiles[i]; - return nullVCXFilter; -} - - -XmlOutput &operator<<(XmlOutput &xml, const VCXProjectSingleConfig &tool) -{ - xml.setIndentString(" "); - - xml << decl("1.0", "utf-8") - << tag("Project") - << attrTag("DefaultTargets","Build") - << attrTag("ToolsVersion", "4.0") - << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003") - << tag("ItemGroup") - << attrTag("Label", "ProjectConfigurations"); - - xml << tag("ProjectConfiguration") - << attrTag("Include" , tool.Configuration.Name) - << tagValue("Configuration", tool.Configuration.ConfigurationName) - << tagValue("Platform", tool.PlatformName) - << closetag(); - - xml << closetag() - << tag("PropertyGroup") - << attrTag("Label", "Globals") - << tagValue("ProjectGuid", tool.ProjectGUID) - << tagValue("RootNamespace", tool.Name) - << tagValue("Keyword", tool.Keyword) - << closetag(); - - // config part. - xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"); - - xml << tool.Configuration; - - xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props"); - - // Extension settings - xml << tag("ImportGroup") - << attrTag("Label", "ExtensionSettings") - << closetag(); - - // PropertySheets - xml << tag("ImportGroup") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) - << attrTag("Label", "PropertySheets"); - - xml << tag("Import") - << attrTag("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props") - << attrTag("Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')") - << closetag() - << closetag(); - - - // UserMacros - xml << tag("PropertyGroup") - << attrTag("Label", "UserMacros") - << closetag(); - - xml << tag("PropertyGroup"); - - if ( !tool.Configuration.OutputDirectory.isEmpty() ) { - xml<< tag("OutDir") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) - << valueTag(tool.Configuration.OutputDirectory); - } - if ( !tool.Configuration.IntermediateDirectory.isEmpty() ) { - xml<< tag("IntDir") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) - << valueTag(tool.Configuration.IntermediateDirectory); - } - if ( !tool.Configuration.TargetName.isEmpty() ) { - xml<< tag("TargetName") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) - << valueTag(tool.Configuration.TargetName); - } - - if ( tool.Configuration.linker.IgnoreImportLibrary != unset) { - xml<< tag("IgnoreImportLibrary") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) - << valueTagT(tool.Configuration.linker.IgnoreImportLibrary); - } - - if ( tool.Configuration.linker.LinkIncremental != unset) { - xml<< tag("LinkIncremental") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) - << valueTagT(tool.Configuration.linker.LinkIncremental); - } - - if ( tool.Configuration.preBuild.UseInBuild != unset ) - { - xml<< tag("PreBuildEventUseInBuild") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) - << valueTagT(tool.Configuration.preBuild.UseInBuild); - } - - if ( tool.Configuration.preLink.UseInBuild != unset ) - { - xml<< tag("PreLinkEventUseInBuild") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) - << valueTagT(tool.Configuration.preLink.UseInBuild); - } - - if ( tool.Configuration.postBuild.UseInBuild != unset ) - { - xml<< tag("PostBuildEventUseInBuild") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) - << valueTagT(tool.Configuration.postBuild.UseInBuild); - } - xml << closetag(); - - xml << tag("ItemDefinitionGroup") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)); - - // ClCompile - xml << tool.Configuration.compiler; - - // Link - xml << tool.Configuration.linker; - - // Midl - xml << tool.Configuration.idl; - - // ResourceCompiler - xml << tool.Configuration.resource; - - // Post build event - if ( tool.Configuration.postBuild.UseInBuild != unset ) - xml << tool.Configuration.postBuild; - - // Pre build event - if ( tool.Configuration.preBuild.UseInBuild != unset ) - xml << tool.Configuration.preBuild; - - // Pre link event - if ( tool.Configuration.preLink.UseInBuild != unset ) - xml << tool.Configuration.preLink; - - xml << closetag(); - - QFile filterFile; - filterFile.setFileName(Option::output.fileName().append(".filters")); - filterFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); - QTextStream ts(&filterFile); - XmlOutput xmlFilter(ts, XmlOutput::NoConversion); - - xmlFilter.setIndentString(" "); - - xmlFilter << decl("1.0", "utf-8") - << tag("Project") - << attrTag("ToolsVersion", "4.0") - << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"); - - xmlFilter << tag("ItemGroup"); - - VCXProject tempProj; - tempProj.SingleProjects += tool; - tempProj.addFilters(xmlFilter, "Form Files"); - tempProj.addFilters(xmlFilter, "Generated Files"); - tempProj.addFilters(xmlFilter, "Header Files"); - tempProj.addFilters(xmlFilter, "LexYacc Files"); - tempProj.addFilters(xmlFilter, "Resource Files"); - tempProj.addFilters(xmlFilter, "Source Files"); - tempProj.addFilters(xmlFilter, "Translation Files"); - xmlFilter << closetag(); - - tempProj.outputFilter(xml, xmlFilter, "Source Files"); - tempProj.outputFilter(xml, xmlFilter, "Header Files"); - tempProj.outputFilter(xml, xmlFilter, "Generated Files"); - tempProj.outputFilter(xml, xmlFilter, "LexYacc Files"); - tempProj.outputFilter(xml, xmlFilter, "Translation Files"); - tempProj.outputFilter(xml, xmlFilter, "Form Files"); - tempProj.outputFilter(xml, xmlFilter, "Resource Files"); - - for (int x = 0; x < tempProj.ExtraCompilers.count(); ++x) { - tempProj.outputFilter(xml, xmlFilter, tempProj.ExtraCompilers.at(x)); - } - - xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets"); - - xml << tag("ImportGroup") - << attrTag("Label", "ExtensionTargets") - << closetag(); - - return xml; -} - - -// Tree file generation --------------------------------------------- -void XTreeNode::generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCXProject &tool, const QString &filter) { + // Merge all files in this filter to root tree + for (int x = 0; x < filter.Files.count(); ++x) + root->addElement(filter.Files.at(x)); - if (children.size()) { - // Filter - ChildrenMap::ConstIterator it, end = children.constEnd(); - if (!tagName.isEmpty()) { - xmlFilter << tag("Filter") - << attrTag("Include", tagName) - << attrTagS("Extensions", ""); + // Save filter setting from first filter. Next filters + // may differ but we cannot handle that. (ex. extfilter) + if (name.isEmpty()) { + name = filter.Name; + extfilter = filter.Filter; + parse = filter.ParseFiles; } - // First round, do nested filters - for (it = children.constBegin(); it != end; ++it) - if ((*it)->children.size()) - (*it)->generateXML(xml, xmlFilter, it.key(), tool, filter); - // Second round, do leafs - for (it = children.constBegin(); it != end; ++it) - if (!(*it)->children.size()) - (*it)->generateXML(xml, xmlFilter, it.key(), tool, filter); - - if (!tagName.isEmpty()) - xml << closetag("Filter"); - } else { - // Leaf - tool.outputFileConfigs(xml, xmlFilter, info, filter); } -} + if (!root->hasElements()) + return; -// Flat file generation --------------------------------------------- -void XFlatNode::generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &/*tagName*/, VCXProject &tool, const QString &filter) { - if (children.size()) { - ChildrenMapFlat::ConstIterator it = children.constBegin(); - ChildrenMapFlat::ConstIterator end = children.constEnd(); - xml << tag(_ItemGroup); - xmlFilter << tag(_ItemGroup); - for (; it != end; ++it) { - tool.outputFileConfigs(xml, xmlFilter, (*it), filter); - } - xml << closetag(); - xmlFilter << closetag(); - } + root->generateXML(xml, xmlFilter, "", project, filtername); // output root tree } - -// VCXProject -------------------------------------------------------- // Output all configurations (by filtername) for a file (by info) -// A filters config output is in VCXFilter.outputFileConfig() -void VCXProject::outputFileConfigs(XmlOutput &xml, - XmlOutput &xmlFilter, - const VCXFilterFile &info, - const QString &filtername) +// A filters config output is in VCFilter.outputFileConfig() +void VCXProjectWriter::outputFileConfigs(VCProject &project, XmlOutput &xml, XmlOutput &xmlFilter, const VCFilterFile &info, const QString &filtername) { // We need to check if the file has any custom build step. // If there is one then it has to be included with "CustomBuild Include" bool fileAdded = false; - for (int i = 0; i < SingleProjects.count(); ++i) { - VCXFilter filter; + for (int i = 0; i < project.SingleProjects.count(); ++i) { + VCFilter filter; + const VCProjectSingleConfig &singleCfg = project.SingleProjects.at(i); if (filtername == "Root Files") { - filter = SingleProjects.at(i).RootFiles; + filter = singleCfg.RootFiles; } else if (filtername == "Source Files") { - filter = SingleProjects.at(i).SourceFiles; + filter = singleCfg.SourceFiles; } else if (filtername == "Header Files") { - filter = SingleProjects.at(i).HeaderFiles; + filter = singleCfg.HeaderFiles; } else if (filtername == "Generated Files") { - filter = SingleProjects.at(i).GeneratedFiles; + filter = singleCfg.GeneratedFiles; } else if (filtername == "LexYacc Files") { - filter = SingleProjects.at(i).LexYaccFiles; + filter = singleCfg.LexYaccFiles; } else if (filtername == "Translation Files") { - filter = SingleProjects.at(i).TranslationFiles; + filter = singleCfg.TranslationFiles; } else if (filtername == "Form Files") { - filter = SingleProjects.at(i).FormFiles; + filter = singleCfg.FormFiles; } else if (filtername == "Resource Files") { - filter = SingleProjects.at(i).ResourceFiles; + filter = singleCfg.ResourceFiles; } else { // ExtraCompilers - filter = SingleProjects[i].filterForExtraCompiler(filtername); + filter = project.SingleProjects[i].filterForExtraCompiler(filtername); } if (filter.Config) // only if the filter is not empty - if (filter.outputFileConfig(xml, xmlFilter, info.file, filtername, fileAdded)) // only add it once. + if (outputFileConfig(filter, xml, xmlFilter, info.file, filtername, fileAdded)) // only add it once. fileAdded = true; } @@ -3084,296 +1780,165 @@ void VCXProject::outputFileConfigs(XmlOutput &xml, xmlFilter << closetag(); } -// outputs a given filter for all existing configurations of a project -void VCXProject::outputFilter(XmlOutput &xml, - XmlOutput &xmlFilter, - const QString &filtername) +bool VCXProjectWriter::outputFileConfig(VCFilter &filter, XmlOutput &xml, XmlOutput &xmlFilter, const QString &filename, const QString &filtername, bool fileAllreadyAdded) { - XNode *root; - if (SingleProjects.at(0).flat_files) - root = new XFlatNode; - else - root = new XTreeNode; - - QString name, extfilter; - triState parse; + bool fileAdded = false; - for (int i = 0; i < SingleProjects.count(); ++i) { - VCXFilter filter; - if (filtername == "Root Files") { - filter = SingleProjects.at(i).RootFiles; - } else if (filtername == "Source Files") { - filter = SingleProjects.at(i).SourceFiles; - } else if (filtername == "Header Files") { - filter = SingleProjects.at(i).HeaderFiles; - } else if (filtername == "Generated Files") { - filter = SingleProjects.at(i).GeneratedFiles; - } else if (filtername == "LexYacc Files") { - filter = SingleProjects.at(i).LexYaccFiles; - } else if (filtername == "Translation Files") { - filter = SingleProjects.at(i).TranslationFiles; - } else if (filtername == "Form Files") { - filter = SingleProjects.at(i).FormFiles; - } else if (filtername == "Resource Files") { - filter = SingleProjects.at(i).ResourceFiles; - } else { - // ExtraCompilers - filter = SingleProjects[i].filterForExtraCompiler(filtername); - } + // Clearing each filter tool + filter.useCustomBuildTool = false; + filter.useCompilerTool = false; + filter.CustomBuildTool = VCCustomBuildTool(); + filter.CompilerTool = VCCLCompilerTool(); - // Merge all files in this filter to root tree - for (int x = 0; x < filter.Files.count(); ++x) - root->addElement(filter.Files.at(x)); + // Unset some default options + filter.CustomBuildTool.config = filter.Config; + filter.CompilerTool.BufferSecurityCheck = unset; + filter.CompilerTool.DebugInformationFormat = debugUnknown; + filter.CompilerTool.ExceptionHandling = ehDefault; + filter.CompilerTool.ProgramDataBaseFileName.clear(); + filter.CompilerTool.RuntimeLibrary = rtUnknown; + filter.CompilerTool.config = filter.Config; - // Save filter setting from first filter. Next filters - // may differ but we cannot handle that. (ex. extfilter) - if (name.isEmpty()) { - name = filter.Name; - extfilter = filter.Filter; - parse = filter.ParseFiles; + bool inBuild = false; + VCFilterFile info; + for (int i = 0; i < filter.Files.count(); ++i) { + if (filter.Files.at(i).file == filename) { + info = filter.Files.at(i); + inBuild = true; } } + inBuild &= !info.excludeFromBuild; - if (!root->hasElements()) - return; - - root->generateXML(xml, xmlFilter, "", *this, filtername); // output root tree -} - - -void VCXProject::addFilters(XmlOutput &xmlFilter, - const QString &filtername) -{ - bool added = false; - - for (int i = 0; i < SingleProjects.count(); ++i) { - VCXFilter filter; - if (filtername == "Root Files") { - filter = SingleProjects.at(i).RootFiles; - } else if (filtername == "Source Files") { - filter = SingleProjects.at(i).SourceFiles; - } else if (filtername == "Header Files") { - filter = SingleProjects.at(i).HeaderFiles; - } else if (filtername == "Generated Files") { - filter = SingleProjects.at(i).GeneratedFiles; - } else if (filtername == "LexYacc Files") { - filter = SingleProjects.at(i).LexYaccFiles; - } else if (filtername == "Translation Files") { - filter = SingleProjects.at(i).TranslationFiles; - } else if (filtername == "Form Files") { - filter = SingleProjects.at(i).FormFiles; - } else if (filtername == "Resource Files") { - filter = SingleProjects.at(i).ResourceFiles; - } else { - // ExtraCompilers - filter = SingleProjects[i].filterForExtraCompiler(filtername); - } - - if(!filter.Files.isEmpty() && !added) { - added = true; - xmlFilter << tag("Filter") - << attrTag("Include", filtername) - << attrTagS("UniqueIdentifier", filter.Guid) - << attrTagS("Extensions", filter.Filter) - << attrTagT("ParseFiles", filter.ParseFiles) - << closetag(); - } + if (inBuild) { + filter.addExtraCompiler(info); + if (filter.Project->usePCH) + filter.modifyPCHstage(info.file); + } else { + // Excluded files uses an empty compiler stage + if(info.excludeFromBuild) + filter.useCompilerTool = true; } -} - -XmlOutput &operator<<(XmlOutput &xml, VCXProject &tool) -{ + // Actual XML output ---------------------------------- + if (filter.useCustomBuildTool || filter.useCompilerTool || !inBuild) { - if (tool.SingleProjects.count() == 0) { - warn_msg(WarnLogic, "Generator: .NET: no single project in merge project, no output"); - return xml; - } + if (filter.useCustomBuildTool) + { + if ( !fileAllreadyAdded ) { - xml.setIndentString(" "); + fileAdded = true; - xml << decl("1.0", "utf-8") - << tag("Project") - << attrTag("DefaultTargets","Build") - << attrTag("ToolsVersion", "4.0") - << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003") - << tag("ItemGroup") - << attrTag("Label", "ProjectConfigurations"); + xmlFilter << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(filename)) + << attrTagS("Filter", filtername); - for (int i = 0; i < tool.SingleProjects.count(); ++i) { - xml << tag("ProjectConfiguration") - << attrTag("Include" , tool.SingleProjects.at(i).Configuration.Name) - << tagValue("Configuration", tool.SingleProjects.at(i).Configuration.ConfigurationName) - << tagValue("Platform", tool.SingleProjects.at(i).PlatformName) - << closetag(); - } + xml << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(filename)); - xml << closetag() - << tag("PropertyGroup") - << attrTag("Label", "Globals") - << tagValue("ProjectGuid", tool.ProjectGUID) - << tagValue("RootNamespace", tool.Name) - << tagValue("Keyword", tool.Keyword) - << closetag(); + if ( filtername == "Form Files" || filtername == "Generated Files" || filtername == "Resource Files" ) + xml << attrTagS("FileType", "Document"); + } - // config part. - xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"); - for (int i = 0; i < tool.SingleProjects.count(); ++i) - xml << tool.SingleProjects.at(i).Configuration; - xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props"); + filter.Project->projectWriter->write(xml, filter.CustomBuildTool); + } - // Extension settings - xml << tag("ImportGroup") - << attrTag("Label", "ExtensionSettings") - << closetag(); + if ( !fileAdded && !fileAllreadyAdded ) + { + fileAdded = true; - // PropertySheets - for (int i = 0; i < tool.SingleProjects.count(); ++i) { - xml << tag("ImportGroup") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) - << attrTag("Label", "PropertySheets"); + if (filtername == "Source Files") { - xml << tag("Import") - << attrTag("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props") - << attrTag("Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')") - << closetag() - << closetag(); - } + xmlFilter << tag("ClCompile") + << attrTag("Include",Option::fixPathToLocalOS(filename)) + << attrTagS("Filter", filtername); - // UserMacros - xml << tag("PropertyGroup") - << attrTag("Label", "UserMacros") - << closetag(); + xml << tag("ClCompile") + << attrTag("Include",Option::fixPathToLocalOS(filename)); - xml << tag("PropertyGroup"); - for (int i = 0; i < tool.SingleProjects.count(); ++i) { + } else if(filtername == "Header Files") { - if ( !tool.SingleProjects.at(i).Configuration.OutputDirectory.isEmpty() ) { - xml << tag("OutDir") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) - << valueTag(tool.SingleProjects.at(i).Configuration.OutputDirectory); - } - if ( !tool.SingleProjects.at(i).Configuration.IntermediateDirectory.isEmpty() ) { - xml << tag("IntDir") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) - << valueTag(tool.SingleProjects.at(i).Configuration.IntermediateDirectory); - } - if ( !tool.SingleProjects.at(i).Configuration.TargetName.isEmpty() ) { - xml << tag("TargetName") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) - << valueTag(tool.SingleProjects.at(i).Configuration.TargetName); - } + xmlFilter << tag("ClInclude") + << attrTag("Include",Option::fixPathToLocalOS(filename)) + << attrTagS("Filter", filtername); - if ( tool.SingleProjects.at(i).Configuration.linker.IgnoreImportLibrary != unset) { - xml << tag("IgnoreImportLibrary") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) - << valueTagT(tool.SingleProjects.at(i).Configuration.linker.IgnoreImportLibrary); - } + xml << tag("ClInclude") + << attrTag("Include",Option::fixPathToLocalOS(filename)); + } else if(filtername == "Generated Files" || filtername == "Form Files") { - if ( tool.SingleProjects.at(i).Configuration.linker.LinkIncremental != unset) { - xml << tag("LinkIncremental") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) - << valueTagT(tool.SingleProjects.at(i).Configuration.linker.LinkIncremental); - } + if (filename.endsWith(".h")) { - if ( tool.SingleProjects.at(i).Configuration.preBuild.UseInBuild != unset ) - { - xml << tag("PreBuildEventUseInBuild") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) - << valueTagT(tool.SingleProjects.at(i).Configuration.preBuild.UseInBuild); - } + xmlFilter << tag("ClInclude") + << attrTag("Include",Option::fixPathToLocalOS(filename)) + << attrTagS("Filter", filtername); - if ( tool.SingleProjects.at(i).Configuration.preLink.UseInBuild != unset ) - { - xml << tag("PreLinkEventUseInBuild") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) - << valueTagT(tool.SingleProjects.at(i).Configuration.preLink.UseInBuild); - } + xml << tag("ClInclude") + << attrTag("Include",Option::fixPathToLocalOS(filename)); + } else if(filename.endsWith(".cpp")) { - if ( tool.SingleProjects.at(i).Configuration.postBuild.UseInBuild != unset ) - { - xml << tag("PostBuildEventUseInBuild") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) - << valueTagT(tool.SingleProjects.at(i).Configuration.postBuild.UseInBuild); - } - } - xml << closetag(); + xmlFilter << tag("ClCompile") + << attrTag("Include",Option::fixPathToLocalOS(filename)) + << attrTagS("Filter", filtername); - for (int i = 0; i < tool.SingleProjects.count(); ++i) { - xml << tag("ItemDefinitionGroup") - << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)); + xml << tag("ClCompile") + << attrTag("Include",Option::fixPathToLocalOS(filename)); + } else if(filename.endsWith(".res")) { - // ClCompile - xml << tool.SingleProjects.at(i).Configuration.compiler; + xmlFilter << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(filename)) + << attrTagS("Filter", filtername); - // Link - xml << tool.SingleProjects.at(i).Configuration.linker; + xml << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(filename)); + } else { - // Midl - xml << tool.SingleProjects.at(i).Configuration.idl; + xmlFilter << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(filename)) + << attrTagS("Filter", filtername); - // ResourceCompiler - xml << tool.SingleProjects.at(i).Configuration.resource; + xml << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(filename)); + } + } else if(filtername == "Root Files") { - // Post build event - if ( tool.SingleProjects.at(i).Configuration.postBuild.UseInBuild != unset ) - xml << tool.SingleProjects.at(i).Configuration.postBuild; - - // Pre build event - if ( tool.SingleProjects.at(i).Configuration.preBuild.UseInBuild != unset ) - xml << tool.SingleProjects.at(i).Configuration.preBuild; + if (filename.endsWith(".rc")) { - // Pre link event - if ( tool.SingleProjects.at(i).Configuration.preLink.UseInBuild != unset ) - xml << tool.SingleProjects.at(i).Configuration.preLink; + xmlFilter << tag("ResourceCompile") + << attrTag("Include",Option::fixPathToLocalOS(filename)); - xml << closetag(); - } + xml << tag("ResourceCompile") + << attrTag("Include",Option::fixPathToLocalOS(filename)); + } + } + } - // The file filters are added in a separate file for MSBUILD. - QFile filterFile; - filterFile.setFileName(Option::output.fileName().append(".filters")); - filterFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); - QTextStream ts(&filterFile); - XmlOutput xmlFilter(ts, XmlOutput::NoConversion); + if(!inBuild) { - xmlFilter.setIndentString(" "); + xml << tag("ExcludedFromBuild") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(filter.Config->Name)) + << valueTag("true"); + } - xmlFilter << decl("1.0", "utf-8") - << tag("Project") - << attrTag("ToolsVersion", "4.0") - << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"); + if (filter.useCompilerTool) { - xmlFilter << tag("ItemGroup"); + if ( !filter.CompilerTool.ForcedIncludeFiles.isEmpty() ) { + xml << tag("ForcedIncludeFiles") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(filter.Config->Name)) + << valueTagX(filter.CompilerTool.ForcedIncludeFiles); + } - tool.addFilters(xmlFilter, "Form Files"); - tool.addFilters(xmlFilter, "Generated Files"); - tool.addFilters(xmlFilter, "Header Files"); - tool.addFilters(xmlFilter, "LexYacc Files"); - tool.addFilters(xmlFilter, "Resource Files"); - tool.addFilters(xmlFilter, "Source Files"); - tool.addFilters(xmlFilter, "Translation Files"); - xmlFilter << closetag(); + if ( !filter.CompilerTool.PrecompiledHeaderThrough.isEmpty() ) { - tool.outputFilter(xml, xmlFilter, "Source Files"); - tool.outputFilter(xml, xmlFilter, "Header Files"); - tool.outputFilter(xml, xmlFilter, "Generated Files"); - tool.outputFilter(xml, xmlFilter, "LexYacc Files"); - tool.outputFilter(xml, xmlFilter, "Translation Files"); - tool.outputFilter(xml, xmlFilter, "Form Files"); - tool.outputFilter(xml, xmlFilter, "Resource Files"); - for (int x = 0; x < tool.ExtraCompilers.count(); ++x) { - tool.outputFilter(xml, xmlFilter, tool.ExtraCompilers.at(x)); + xml << tag("PrecompiledHeaderFile") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(filter.Config->Name)) + << valueTag(filter.CompilerTool.PrecompiledHeaderThrough) + << tag("PrecompiledHeader") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(filter.Config->Name)) + << valueTag(toString(filter.CompilerTool.UsePrecompiledHeader)); + } + } } - tool.outputFilter(xml, xmlFilter, "Root Files"); - - xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets"); - xml << tag("ImportGroup") - << attrTag("Label", "ExtensionTargets") - << closetag(); - - return xml; + return fileAdded; } QT_END_NAMESPACE diff --git a/qmake/generators/win32/msbuild_objectmodel.h b/qmake/generators/win32/msbuild_objectmodel.h index 567985d..498552e 100644 --- a/qmake/generators/win32/msbuild_objectmodel.h +++ b/qmake/generators/win32/msbuild_objectmodel.h @@ -54,519 +54,24 @@ QT_BEGIN_NAMESPACE - -class VCXConfiguration; -class VCXProject; - -class VCXCLCompilerTool : public VCToolBase -{ -public: - // Functions - VCXCLCompilerTool(); - virtual ~VCXCLCompilerTool(){} - bool parseOption(const char* option); - - // Variables - QStringList AdditionalIncludeDirectories; - QStringList AdditionalOptions; - QStringList AdditionalUsingDirectories; - QString AlwaysAppend; - QString AssemblerListingLocation; - QString AssemblerOutput; - QString BasicRuntimeChecks; - triState BrowseInformation; - QString BrowseInformationFile; - triState BufferSecurityCheck; - QString CallingConvention; - QString CompileAs; - QString CompileAsManaged; - triState CreateHotpatchableImage; - QString DebugInformationFormat; - triState DisableLanguageExtensions; - QStringList DisableSpecificWarnings; - QString EnableEnhancedInstructionSet; - triState EnableFiberSafeOptimizations; - triState EnablePREfast; - QString ErrorReporting; - QString ExceptionHandling; - triState ExpandAttributedSource; - QString FavorSizeOrSpeed; - triState FloatingPointExceptions; - QString FloatingPointModel; - triState ForceConformanceInForLoopScope; - QStringList ForcedIncludeFiles; - QStringList ForcedUsingFiles; - triState FunctionLevelLinking; - triState GenerateXMLDocumentationFiles; - triState IgnoreStandardIncludePath; - QString InlineFunctionExpansion; - triState IntrinsicFunctions; - triState MinimalRebuild; - triState MultiProcessorCompilation; - QString ObjectFileName; - QStringList ObjectFiles; - triState OmitDefaultLibName; - triState OmitFramePointers; - triState OpenMPSupport; - QString Optimization; - QString PrecompiledHeader; - QString PrecompiledHeaderFile; - QString PrecompiledHeaderOutputFile; - triState PreprocessKeepComments; - QStringList PreprocessorDefinitions; - QString PreprocessOutputPath; - triState PreprocessSuppressLineNumbers; - triState PreprocessToFile; - QString ProgramDataBaseFileName; - QString ProcessorNumber; - QString RuntimeLibrary; - triState RuntimeTypeInfo; - triState ShowIncludes; - triState SmallerTypeCheck; - triState StringPooling; - QString StructMemberAlignment; - triState SuppressStartupBanner; - QString TreatSpecificWarningsAsErrors; - triState TreatWarningAsError; - triState TreatWChar_tAsBuiltInType; - triState UndefineAllPreprocessorDefinitions; - QStringList UndefinePreprocessorDefinitions; - triState UseFullPaths; - triState UseUnicodeForAssemblerListing; - QString WarningLevel; - triState WholeProgramOptimization; - QString XMLDocumentationFileName; - - VCXConfiguration* config; -}; - -class VCXLinkerTool : public VCToolBase -{ -public: - // Functions - VCXLinkerTool(); - virtual ~VCXLinkerTool(){} - bool parseOption(const char* option); - - // Variables - QStringList AdditionalDependencies; - QStringList AdditionalLibraryDirectories; - QStringList AdditionalManifestDependencies; - QStringList AdditionalOptions; - QStringList AddModuleNamesToAssembly; - triState AllowIsolation; - triState AssemblyDebug; - QStringList AssemblyLinkResource; - QString BaseAddress; - QString CLRImageType; - QString CLRSupportLastError; - QString CLRThreadAttribute; - QString CLRUnmanagedCodeCheck; - QString CreateHotPatchableImage; - triState DataExecutionPrevention; - QStringList DelayLoadDLLs; - triState DelaySign; - QString Driver; - QStringList EmbedManagedResourceFile; - triState EnableCOMDATFolding; - triState EnableUAC; - QString EntryPointSymbol; - triState FixedBaseAddress; - QString ForceFileOutput; - QStringList ForceSymbolReferences; - QString FunctionOrder; - triState GenerateDebugInformation; - triState GenerateManifest; - triState GenerateMapFile; - qlonglong HeapCommitSize; - qlonglong HeapReserveSize; - triState IgnoreAllDefaultLibraries; - triState IgnoreEmbeddedIDL; - triState IgnoreImportLibrary; - QStringList IgnoreSpecificDefaultLibraries; - triState ImageHasSafeExceptionHandlers; - QString ImportLibrary; - QString KeyContainer; - QString KeyFile; - triState LargeAddressAware; - triState LinkDLL; - QString LinkErrorReporting; - triState LinkIncremental; - triState LinkStatus; - QString LinkTimeCodeGeneration; - QString ManifestFile; - triState MapExports; - QString MapFileName; - QString MergedIDLBaseFileName; - QString MergeSections; - QString MidlCommandFile; - QString ModuleDefinitionFile; - QString MSDOSStubFileName; - triState NoEntryPoint; - triState OptimizeReferences; - QString OutputFile; - triState PreventDllBinding; - QString Profile; - QString ProfileGuidedDatabase; - QString ProgramDatabaseFile; - triState RandomizedBaseAddress; - triState RegisterOutput; - qlonglong SectionAlignment; - triState SetChecksum; - QString ShowProgress; - QString SpecifySectionAttributes; - QString StackCommitSize; - QString StackReserveSize; - QString StripPrivateSymbols; - QString SubSystem; - triState SupportNobindOfDelayLoadedDLL; - triState SupportUnloadOfDelayLoadedDLL; - triState SuppressStartupBanner; - triState SwapRunFromCD; - triState SwapRunFromNet; - QString TargetMachine; - triState TerminalServerAware; - triState TreatLinkerWarningAsErrors; - triState TurnOffAssemblyGeneration; - QString TypeLibraryFile; - qlonglong TypeLibraryResourceID; - QString UACExecutionLevel; - triState UACUIAccess; - QString Version; - - - VCXConfiguration* config; -}; - -class VCXMIDLTool : public VCToolBase -{ -public: - // Functions - VCXMIDLTool(); - virtual ~VCXMIDLTool(){} - bool parseOption(const char* option); - - // Variables - QStringList AdditionalIncludeDirectories; - QStringList AdditionalOptions; - triState ApplicationConfigurationMode; - QString ClientStubFile; - QString CPreprocessOptions; - QString DefaultCharType; - QString DLLDataFileName; - QString EnableErrorChecks; - triState ErrorCheckAllocations; - triState ErrorCheckBounds; - triState ErrorCheckEnumRange; - triState ErrorCheckRefPointers; - triState ErrorCheckStubData; - QString GenerateClientFiles; - QString GenerateServerFiles; - triState GenerateStublessProxies; - triState GenerateTypeLibrary; - QString HeaderFileName; - triState IgnoreStandardIncludePath; - QString InterfaceIdentifierFileName; - qlonglong LocaleID; - triState MkTypLibCompatible; - QString OutputDirectory; - QStringList PreprocessorDefinitions; - QString ProxyFileName; - QString RedirectOutputAndErrors; - QString ServerStubFile; - QString StructMemberAlignment; - triState SuppressCompilerWarnings; - triState SuppressStartupBanner; - QString TargetEnvironment; - QString TypeLibFormat; - QString TypeLibraryName; - QStringList UndefinePreprocessorDefinitions; - triState ValidateAllParameters; - triState WarnAsError; - QString WarningLevel; - - VCXConfiguration* config; -}; - -class VCXLibrarianTool : public VCToolBase -{ -public: - // Functions - VCXLibrarianTool(); - virtual ~VCXLibrarianTool(){} - bool parseOption(const char*){ return false; }; - - // Variables - QStringList AdditionalDependencies; - QStringList AdditionalLibraryDirectories; - QStringList AdditionalOptions; - QString DisplayLibrary; - QString ErrorReporting; - QStringList ExportNamedFunctions; - QStringList ForceSymbolReferences; - triState IgnoreAllDefaultLibraries; - QStringList IgnoreSpecificDefaultLibraries; - triState LinkTimeCodeGeneration; - QString ModuleDefinitionFile; - QString Name; - QString OutputFile; - QStringList RemoveObjects; - QString SubSystem; - triState SuppressStartupBanner; - QString TargetMachine; - triState TreatLibWarningAsErrors; - triState Verbose; - -}; - -class VCXCustomBuildTool : public VCToolBase -{ -public: - // Functions - VCXCustomBuildTool(); - virtual ~VCXCustomBuildTool(){} - bool parseOption(const char*){ return false; }; - - // Variables - QStringList AdditionalDependencies; - QStringList CommandLine; - QString Description; - QStringList Outputs; - QString ToolName; - QString ToolPath; - QString ConfigName; -}; - -class VCXResourceCompilerTool : public VCToolBase -{ -public: - // Functions - VCXResourceCompilerTool(); - virtual ~VCXResourceCompilerTool(){} - bool parseOption(const char*){ return false; }; - - // Variables - QStringList AdditionalIncludeDirectories; - QString AdditionalOptions; - QString Culture; - triState IgnoreStandardIncludePath; - triState NullTerminateStrings; - QStringList PreprocessorDefinitions; - QString ResourceOutputFileName; - triState ShowProgress; - triState SuppressStartupBanner; - QString TrackerLogDirectory; - QString UndefinePreprocessorDefinitions; -}; - -class VCXDeploymentTool -{ -public: - // Functions - VCXDeploymentTool(); - virtual ~VCXDeploymentTool() {} - - // Variables - QString DeploymentTag; - QString RemoteDirectory; - QString AdditionalFiles; -}; - -class VCXEventTool : public VCToolBase -{ -protected: - // Functions - VCXEventTool() : UseInBuild(unset){}; - virtual ~VCXEventTool(){} - bool parseOption(const char*){ return false; }; - -public: - // Variables - QString CommandLine; - QString Description; - triState UseInBuild; - QString EventName; - QString ToolPath; -}; - -class VCXPostBuildEventTool : public VCXEventTool -{ -public: - VCXPostBuildEventTool(); - ~VCXPostBuildEventTool(){} -}; - -class VCXPreBuildEventTool : public VCXEventTool -{ -public: - VCXPreBuildEventTool(); - ~VCXPreBuildEventTool(){} -}; - -class VCXPreLinkEventTool : public VCXEventTool -{ -public: - VCXPreLinkEventTool(); - ~VCXPreLinkEventTool(){} -}; - -class VCXConfiguration -{ -public: - // Functions - VCXConfiguration(); - ~VCXConfiguration(){} - - // Variables - triState ATLMinimizesCRunTimeLibraryUsage; - triState BuildBrowserInformation; - QString CharacterSet; - QString ConfigurationType; - QString DeleteExtensionsOnClean; - QString ImportLibrary; - QString IntermediateDirectory; - QString Name; - QString ConfigurationName; - QString OutputDirectory; - QString PrimaryOutput; - QString ProgramDatabase; - triState RegisterOutput; - QString TargetName; - QString UseOfATL; - QString UseOfMfc; - triState WholeProgramOptimization; - - // XML sub-parts - VCXCLCompilerTool compiler; - VCXLibrarianTool librarian; - VCXLinkerTool linker; - VCXMIDLTool idl; - VCXResourceCompilerTool resource; - VCXCustomBuildTool custom; - VCXDeploymentTool deployment; // Not likely to be supported: http://msdn.microsoft.com/en-us/library/sa69he4t.aspx - VCXPostBuildEventTool postBuild; - VCXPreBuildEventTool preBuild; - VCXPreLinkEventTool preLink; -}; - -struct VCXFilterFile -{ - VCXFilterFile() - { excludeFromBuild = false; } - VCXFilterFile(const QString &filename, bool exclude = false ) - { file = filename; excludeFromBuild = exclude; } - VCXFilterFile(const QString &filename, const QString &additional, bool exclude = false ) - { file = filename; excludeFromBuild = exclude; additionalFile = additional; } - bool operator==(const VCXFilterFile &other){ - return file == other.file - && additionalFile == other.additionalFile - && excludeFromBuild == other.excludeFromBuild; - } - - bool excludeFromBuild; - QString file; - QString additionalFile; // For tools like MOC -}; - -class VcxprojGenerator; -class VCXFilter -{ -public: - // Functions - VCXFilter(); - ~VCXFilter(){}; - - void addFile(const QString& filename); - void addFile(const VCXFilterFile& fileInfo); - void addFiles(const QStringList& fileList); - bool addExtraCompiler(const VCXFilterFile &info); - void modifyPCHstage(QString str); - bool outputFileConfig(XmlOutput &xml, XmlOutput &xmlFilter, const QString &filename, const QString &filtername, bool fileAllreadyAdded); - - // Variables - QString Name; - QString Filter; - QString Guid; - triState ParseFiles; - VcxprojGenerator* Project; - VCXConfiguration* Config; - QList<VCXFilterFile> Files; - - customBuildCheck CustomBuild; - - bool useCustomBuildTool; - VCXCustomBuildTool CustomBuildTool; - - bool useCompilerTool; - VCXCLCompilerTool CompilerTool; -}; - -typedef QList<VCXFilter> VCXFilterList; -class VCXProjectSingleConfig -{ -public: - enum FilterTypes { - None, - Source, - Header, - Generated, - LexYacc, - Translation, - Resources, - Extras - }; - // Functions - VCXProjectSingleConfig(){}; - ~VCXProjectSingleConfig(){} - - // Variables - QString Name; - QString Version; - QString ProjectGUID; - QString Keyword; - QString SccProjectName; - QString SccLocalPath; - QString PlatformName; - - // XML sub-parts - VCXConfiguration Configuration; - VCXFilter RootFiles; - VCXFilter SourceFiles; - VCXFilter HeaderFiles; - VCXFilter GeneratedFiles; - VCXFilter LexYaccFiles; - VCXFilter TranslationFiles; - VCXFilter FormFiles; - VCXFilter ResourceFiles; - VCXFilterList ExtraCompilersFiles; - - bool flat_files; - - // Accessor for extracompilers - VCXFilter &filterForExtraCompiler(const QString &compilerName); -}; - - - // Tree & Flat view of files -------------------------------------------------- -class VCXFilter; class XNode { public: virtual ~XNode() { } - void addElement(const VCXFilterFile &file) { + void addElement(const VCFilterFile &file) { addElement(file.file, file); } - virtual void addElement(const QString &filepath, const VCXFilterFile &allInfo) = 0; + virtual void addElement(const QString &filepath, const VCFilterFile &allInfo) = 0; virtual void removeElements()= 0; - virtual void generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCXProject &tool, const QString &filter) = 0; + virtual void generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCProject &tool, const QString &filter) = 0; virtual bool hasElements() = 0; }; class XTreeNode : public XNode { typedef QMap<QString, XTreeNode*> ChildrenMap; - VCXFilterFile info; + VCFilterFile info; ChildrenMap children; public: @@ -582,7 +87,7 @@ public: return Uindex; } - void addElement(const QString &filepath, const VCXFilterFile &allInfo){ + void addElement(const QString &filepath, const VCFilterFile &allInfo){ QString newNodeName(filepath); int index = pathIndex(filepath); @@ -609,7 +114,7 @@ public: children.clear(); } - void generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCXProject &tool, const QString &filter); + void generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCProject &tool, const QString &filter); bool hasElements() { return children.size() != 0; } @@ -617,7 +122,7 @@ public: class XFlatNode : public XNode { - typedef QMap<QString, VCXFilterFile> ChildrenMapFlat; + typedef QMap<QString, VCFilterFile> ChildrenMapFlat; ChildrenMapFlat children; public: @@ -633,7 +138,7 @@ public: return Uindex; } - void addElement(const QString &filepath, const VCXFilterFile &allInfo){ + void addElement(const QString &filepath, const VCFilterFile &allInfo){ QString newKey(filepath); int index = pathIndex(filepath); @@ -649,60 +154,39 @@ public: children.clear(); } - void generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCXProject &proj, const QString &filter); + void generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCProject &proj, const QString &filter); bool hasElements() { return children.size() != 0; } }; -// ---------------------------------------------------------------------------- -class VCXProject +class VCXProjectWriter : public VCProjectWriter { public: - // Variables - QString Name; - QString Version; - QString ProjectGUID; - QString Keyword; - QString SccProjectName; - QString SccLocalPath; - QString PlatformName; - - // Single projects - QList<VCXProjectSingleConfig> SingleProjects; + void write(XmlOutput &, VCProjectSingleConfig &); + void write(XmlOutput &, VCProject &); - // List of all extracompilers - QStringList ExtraCompilers; + void write(XmlOutput &, const VCCLCompilerTool &); + void write(XmlOutput &, const VCLinkerTool &); + void write(XmlOutput &, const VCMIDLTool &); + void write(XmlOutput &, const VCCustomBuildTool &); + void write(XmlOutput &, const VCLibrarianTool &); + void write(XmlOutput &, const VCResourceCompilerTool &); + void write(XmlOutput &, const VCEventTool &); + void write(XmlOutput &, const VCDeploymentTool &); + void write(XmlOutput &, const VCConfiguration &); + void write(XmlOutput &, VCFilter &); - // Functions - void outputFilter(XmlOutput &xml, - XmlOutput &xmlFilter, - const QString &filtername); - - void outputFileConfigs(XmlOutput &xml, - XmlOutput &xmlFilter, - const VCXFilterFile &info, - const QString &filtername); - - void addFilters(XmlOutput &xmlFilter, - const QString &filtername); +private: + static void addFilters(VCProject &project, XmlOutput &xmlFilter, const QString &filterName); + static void outputFilter(VCProject &project, XmlOutput &xml, XmlOutput &xmlFilter, const QString &filtername); + static void outputFileConfigs(VCProject &project, XmlOutput &xml, XmlOutput &xmlFilter, const VCFilterFile &info, const QString &filtername); + static bool outputFileConfig(VCFilter &filter, XmlOutput &xml, XmlOutput &xmlFilter, const QString &filename, const QString &filtername, bool fileAllreadyAdded); + friend class XTreeNode; + friend class XFlatNode; }; - -XmlOutput &operator<<(XmlOutput &, const VCXCLCompilerTool &); -XmlOutput &operator<<(XmlOutput &, const VCXLinkerTool &); -XmlOutput &operator<<(XmlOutput &, const VCXMIDLTool &); -XmlOutput &operator<<(XmlOutput &, const VCXCustomBuildTool &); -XmlOutput &operator<<(XmlOutput &, const VCXLibrarianTool &); -XmlOutput &operator<<(XmlOutput &, const VCXResourceCompilerTool &); -XmlOutput &operator<<(XmlOutput &, const VCXEventTool &); -XmlOutput &operator<<(XmlOutput &, const VCXDeploymentTool &); -XmlOutput &operator<<(XmlOutput &, const VCXConfiguration &); -XmlOutput &operator<<(XmlOutput &, const VCXProjectSingleConfig &); -XmlOutput &operator<<(XmlOutput &, VCXProject &); - - QT_END_NAMESPACE #endif // MSVC_OBJECTMODEL_H diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 92e8aeb..0adb152 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -129,10 +129,12 @@ QString NmakeMakefileGenerator::var(const QString &value) p.replace("-c", precompRule); // Cannot use -Gm with -FI & -Yu, as this gives an // internal compiler error, on the newer compilers + // ### work-around for a VS 2003 bug. Move to some prf file or remove completely. p.remove("-Gm"); return p; } else if (value == "QMAKE_CXXFLAGS") { // Remove internal compiler error option + // ### work-around for a VS 2003 bug. Move to some prf file or remove completely. return MakefileGenerator::var(value).remove("-Gm"); } } diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index 980e686..b1de302 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -280,6 +280,14 @@ inline XmlOutput::xml_output attrX(const char *name, const QStringList &v, const return attr(name, v.join(s)); } +triState operator!(const triState &rhs) +{ + if (rhs == unset) + return rhs; + triState lhs = (rhs == _True ? _False : _True); + return lhs; +} + // VCCLCompilerTool ------------------------------------------------- VCCLCompilerTool::VCCLCompilerTool() : AssemblerOutput(asmListingNone), @@ -305,12 +313,14 @@ VCCLCompilerTool::VCCLCompilerTool() FloatingPointExceptions(unset), ForceConformanceInForLoopScope(unset), GeneratePreprocessedFile(preprocessNo), + PreprocessSuppressLineNumbers(unset), GlobalOptimizations(unset), IgnoreStandardIncludePath(unset), ImproveFloatingPointConsistency(unset), InlineFunctionExpansion(expandDefault), KeepComments(unset), MinimalRebuild(unset), + OmitDefaultLibName(unset), OmitFramePointers(unset), OpenMP(unset), Optimization(optimizeCustom), @@ -328,11 +338,17 @@ VCCLCompilerTool::VCCLCompilerTool() TurnOffAssemblyGeneration(unset), UndefineAllPreprocessorDefinitions(unset), UsePrecompiledHeader(pchNone), + UseUnicodeForAssemblerListing(unset), WarnAsError(unset), WarningLevel(warningLevel_0), WholeProgramOptimization(unset), CompileForArchitecture(archUnknown), - InterworkCalls(unset) + InterworkCalls(unset), + EnablePREfast(unset), + DisplayFullPaths(unset), + MultiProcessorCompilation(unset), + GenerateXMLDocumentationFiles(unset), + CreateHotpatchableImage(unset) { } @@ -369,82 +385,6 @@ inline XmlOutput::xml_output xformExceptionHandlingNET2005(exceptionHandling eh, return attrS(_ExceptionHandling, (eh == ehNoSEH ? "true" : "false")); } -XmlOutput &operator<<(XmlOutput &xml, const VCCLCompilerTool &tool) -{ - return xml - << tag(_Tool) - << attrS(_Name, _VCCLCompilerTool) - << attrX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories) - << attrX(_AdditionalOptions, tool.AdditionalOptions, " ") - << attrX(_AdditionalUsingDirectories, tool.AdditionalUsingDirectories) - << attrS(_AssemblerListingLocation, tool.AssemblerListingLocation) - << attrE(_AssemblerOutput, tool.AssemblerOutput, /*ifNot*/ asmListingNone) - << attrE(_BasicRuntimeChecks, tool.BasicRuntimeChecks, /*ifNot*/ runtimeBasicCheckNone) - << attrE(_BrowseInformation, tool.BrowseInformation, /*ifNot*/ brInfoNone) - << attrS(_BrowseInformationFile, tool.BrowseInformationFile) - << attrT(_BufferSecurityCheck, tool.BufferSecurityCheck) - << attrE(_CallingConvention, tool.CallingConvention, /*ifNot*/ callConventionDefault) - << attrE(_CompileAs, tool.CompileAs, compileAsDefault) - << attrE(_CompileAsManaged, tool.CompileAsManaged, /*ifNot*/ managedDefault) - << attrT(_CompileOnly, tool.CompileOnly) - << attrE(_DebugInformationFormat, tool.DebugInformationFormat, /*ifNot*/ debugUnknown) - << attrT(_DefaultCharIsUnsigned, tool.DefaultCharIsUnsigned) - << attrT(_Detect64BitPortabilityProblems, tool.Detect64BitPortabilityProblems) - << attrT(_DisableLanguageExtensions, tool.DisableLanguageExtensions) - << attrX(_DisableSpecificWarnings, tool.DisableSpecificWarnings) - << attrE(_EnableEnhancedInstructionSet, tool.EnableEnhancedInstructionSet, /*ifnot*/ archNotSet) - << attrT(_EnableFiberSafeOptimizations, tool.EnableFiberSafeOptimizations) - << attrT(_EnableFunctionLevelLinking, tool.EnableFunctionLevelLinking) - << attrT(_EnableIntrinsicFunctions, tool.EnableIntrinsicFunctions) - << xformExceptionHandlingNET2005(tool.ExceptionHandling, tool.config->CompilerVersion) - << attrT(_ExpandAttributedSource, tool.ExpandAttributedSource) - << attrE(_FavorSizeOrSpeed, tool.FavorSizeOrSpeed, /*ifNot*/ favorNone) - - << attrE(_FloatingPointModel, tool.FloatingPointModel, /*ifNot*/ floatingPointNotSet) - << attrT(_FloatingPointExceptions, tool.FloatingPointExceptions) - - << attrT(_ForceConformanceInForLoopScope, tool.ForceConformanceInForLoopScope) - << attrX(_ForcedIncludeFiles, tool.ForcedIncludeFiles) - << attrX(_ForcedUsingFiles, tool.ForcedUsingFiles) - << attrE(_GeneratePreprocessedFile, tool.GeneratePreprocessedFile, /*ifNot*/ preprocessUnknown) - << attrT(_GlobalOptimizations, tool.GlobalOptimizations) - << attrT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) - << attrT(_ImproveFloatingPointConsistency, tool.ImproveFloatingPointConsistency) - << attrE(_InlineFunctionExpansion, tool.InlineFunctionExpansion, /*ifNot*/ expandDefault) - << attrT(_KeepComments, tool.KeepComments) - << attrT(_MinimalRebuild, tool.MinimalRebuild) - << attrS(_ObjectFile, tool.ObjectFile) - << attrT(_OmitFramePointers, tool.OmitFramePointers) - << attrT(_OpenMP, tool.OpenMP) - << attrE(_Optimization, tool.Optimization, /*ifNot*/ optimizeDefault) - << attrE(_OptimizeForProcessor, tool.OptimizeForProcessor, /*ifNot*/ procOptimizeBlended) - << attrT(_OptimizeForWindowsApplication, tool.OptimizeForWindowsApplication) - << attrS(_OutputFile, tool.OutputFile) - << attrS(_PrecompiledHeaderFile, tool.PrecompiledHeaderFile) - << attrS(_PrecompiledHeaderThrough, tool.PrecompiledHeaderThrough) - << attrX(_PreprocessorDefinitions, tool.PreprocessorDefinitions) - << (tool.ProgramDataBaseFileName.isNull() ? noxml() : attr(_ProgramDataBaseFileName, tool.ProgramDataBaseFileName)) - << attrE(_RuntimeLibrary, tool.RuntimeLibrary, /*ifNot*/ rtUnknown) - << attrT(_RuntimeTypeInfo, tool.RuntimeTypeInfo) - << attrT(_ShowIncludes, tool.ShowIncludes) - << attrT(_SmallerTypeCheck, tool.SmallerTypeCheck) - << attrT(_StringPooling, tool.StringPooling) - << attrE(_StructMemberAlignment, tool.StructMemberAlignment, /*ifNot*/ alignNotSet) - << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner) - << attrT(_TreatWChar_tAsBuiltInType, tool.TreatWChar_tAsBuiltInType) - << attrT(_TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration) - << attrT(_UndefineAllPreprocessorDefinitions, tool.UndefineAllPreprocessorDefinitions) - << attrX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions) - << (!tool.PrecompiledHeaderFile.isEmpty() || !tool.PrecompiledHeaderThrough.isEmpty() ? xformUsePrecompiledHeaderForNET2005(tool.UsePrecompiledHeader, tool.config->CompilerVersion) : noxml()) - << attrT(_WarnAsError, tool.WarnAsError) - << attrE(_WarningLevel, tool.WarningLevel, /*ifNot*/ warningLevelUnknown) - << attrT(_WholeProgramOptimization, tool.WholeProgramOptimization) - << attrE(_CompileForArchitecture, tool.CompileForArchitecture, /*ifNot*/ archUnknown) - << attrT(_InterworkCalls, tool.InterworkCalls) - - << closetag(_Tool); -} - bool VCCLCompilerTool::parseOption(const char* option) { // skip index 0 ('/' or '-') @@ -457,6 +397,10 @@ bool VCCLCompilerTool::parseOption(const char* option) switch (first) { case '?': case 'h': + if(second == 'o' && third == 't' && fourth == 'p') { + CreateHotpatchableImage = _True; + break; + } qWarning("Generator: Option '/?', '/help': MSVC.NET projects do not support outputting help info"); found = false; break; @@ -482,7 +426,7 @@ bool VCCLCompilerTool::parseOption(const char* option) break; case 'E': if(second == 'H') { - QString opt(option); + QByteArray opt(option + 2); if (opt.contains('a') && !opt.contains('s') && !opt.contains('c')) ExceptionHandling = ehSEH; else if (!opt.contains('a') && opt.contains("s-") && opt.contains("c-")) @@ -501,6 +445,8 @@ bool VCCLCompilerTool::parseOption(const char* option) AdditionalOptions += option; } break; + } else if (second == 'P') { + PreprocessSuppressLineNumbers = _True; } GeneratePreprocessedFile = preprocessYes; break; @@ -517,16 +463,24 @@ bool VCCLCompilerTool::parseOption(const char* option) AssemblerOutput = asmListingAsmMachineSrc; } else if(third == 's') { AssemblerOutput = asmListingAsmSrc; + } else if (third == 'u') { + UseUnicodeForAssemblerListing = _True; } else { AssemblerOutput = asmListingAssemblyOnly; } break; + case 'C': + DisplayFullPaths = _True; + break; case 'a': AssemblerListingLocation = option+3; break; case 'I': ForcedIncludeFiles += option+3; break; + case 'i': + PreprocessOutputPath += option+3; + break; case 'R': BrowseInformation = brAllInfo; BrowseInformationFile = option+3; @@ -598,6 +552,8 @@ bool VCCLCompilerTool::parseOption(const char* option) break; case 'S': BufferSecurityCheck = _True; + if(third == '-') + BufferSecurityCheck = _False; break; case 'T': EnableFiberSafeOptimizations = _True; @@ -675,10 +631,14 @@ bool VCCLCompilerTool::parseOption(const char* option) RuntimeLibrary = rtMultiThreadedDebug; break; } else if (second == 'P') { - if (config->CompilerVersion >= NET2005) + if (config->CompilerVersion >= NET2005) { AdditionalOptions += option; - else + } else if (config->CompilerVersion >= NET2010) { + MultiProcessorCompilation = _True; + MultiProcessorCompilationProcessorCount = option+3; + } else { warn_msg(WarnLogic, "/MP option is not supported in Visual C++ < 2005, ignoring."); + } break; } found = false; break; @@ -855,7 +815,12 @@ bool VCCLCompilerTool::parseOption(const char* option) break; case 'p': if(third == '6' && fourth == '4') { - Detect64BitPortabilityProblems = _True; + if (config->CompilerVersion >= NET2010) { + // Deprecated for VS2010 but can be used under Additional Options. + AdditionalOptions += option; + } else { + Detect64BitPortabilityProblems = _True; + } break; } // Fallthrough @@ -907,7 +872,7 @@ bool VCCLCompilerTool::parseOption(const char* option) DebugInformationFormat = debugEnabled; break; case 'l': - DebugInformationFormat = debugEditAndContinue; + OmitDefaultLibName = _True; break; case 'a': DisableLanguageExtensions = _True; @@ -971,6 +936,9 @@ bool VCCLCompilerTool::parseOption(const char* option) break; } } + } else if (second == 'n' && third == 'a' && fourth == 'l') { + EnablePREfast = _True; + break; } found = false; break; @@ -1029,10 +997,34 @@ bool VCCLCompilerTool::parseOption(const char* option) } break; case 'd': - if(second != 'r') { - found = false; break; + if (second == 'r') { + CompileAsManaged = managedAssembly; + break; + } else if (second != 'o' && third == 'c') { + GenerateXMLDocumentationFiles = _True; + XMLDocumentationFileName += option+4; + break; } - CompileAsManaged = managedAssembly; + found = false; + break; + case 'e': + if (second == 'r' && third == 'r' && fourth == 'o') { + if (option[12] == ':') { + if ( option[13] == 'n') { + ErrorReporting = "None"; + } else if (option[13] == 'p') { + ErrorReporting = "Prompt"; + } else if (option[13] == 'q') { + ErrorReporting = "Queue"; + } else if (option[13] == 's') { + ErrorReporting = "Send"; + } else { + found = false; + } + break; + } + } + found = false; break; case 'f': if(second == 'p' && third == ':') { @@ -1115,7 +1107,8 @@ bool VCCLCompilerTool::parseOption(const char* option) // VCLinkerTool ----------------------------------------------------- VCLinkerTool::VCLinkerTool() - : EnableCOMDATFolding(optFoldingDefault), + : DataExecutionPrevention(unset), + EnableCOMDATFolding(optFoldingDefault), GenerateDebugInformation(unset), GenerateMapFile(unset), HeapCommitSize(-1), @@ -1131,6 +1124,7 @@ VCLinkerTool::VCLinkerTool() MapLines(unset), OptimizeForWindows98(optWin98Default), OptimizeReferences(optReferencesDefault), + RandomizedBaseAddress(unset), RegisterOutput(unset), ResourceOnlyDLL(unset), SetChecksum(unset), @@ -1144,72 +1138,21 @@ VCLinkerTool::VCLinkerTool() SwapRunFromNet(unset), TargetMachine(machineNotSet), TerminalServerAware(termSvrAwareDefault), + TreatWarningsAsErrors(unset), TurnOffAssemblyGeneration(unset), - TypeLibraryResourceID(0) + TypeLibraryResourceID(0), + GenerateManifest(unset), + EnableUAC(unset), + UACUIAccess(unset), + SectionAlignment(-1), + PreventDllBinding(unset), + AllowIsolation(unset), + AssemblyDebug(unset), + CLRUnmanagedCodeCheck(unset), + DelaySign(unset) { } -XmlOutput &operator<<(XmlOutput &xml, const VCLinkerTool &tool) -{ - return xml - << tag(_Tool) - << attrS(_Name, _VCLinkerTool) - << attrX(_AdditionalDependencies, tool.AdditionalDependencies, " ") - << attrX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories) - << attrX(_AdditionalOptions, tool.AdditionalOptions, " ") - << attrX(_AddModuleNamesToAssembly, tool.AddModuleNamesToAssembly) - << attrS(_BaseAddress, tool.BaseAddress) - << attrX(_DelayLoadDLLs, tool.DelayLoadDLLs) - << attrE(_EnableCOMDATFolding, tool.EnableCOMDATFolding, /*ifNot*/ optFoldingDefault) - << attrS(_EntryPointSymbol, tool.EntryPointSymbol) - << attrX(_ForceSymbolReferences, tool.ForceSymbolReferences) - << attrS(_FunctionOrder, tool.FunctionOrder) - << attrT(_GenerateDebugInformation, tool.GenerateDebugInformation) - << attrT(_GenerateMapFile, tool.GenerateMapFile) - << attrL(_HeapCommitSize, tool.HeapCommitSize, /*ifNot*/ -1) - << attrL(_HeapReserveSize, tool.HeapReserveSize, /*ifNot*/ -1) - << attrT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries) - << attrX(_IgnoreDefaultLibraryNames, tool.IgnoreDefaultLibraryNames) - << attrT(_IgnoreEmbeddedIDL, tool.IgnoreEmbeddedIDL) - << attrT(_IgnoreImportLibrary, tool.IgnoreImportLibrary) - << attrS(_ImportLibrary, tool.ImportLibrary) - << attrE(_LargeAddressAware, tool.LargeAddressAware, /*ifNot*/ addrAwareDefault) - << attrT(_LinkDLL, tool.LinkDLL) - << attrE(_LinkIncremental, tool.LinkIncremental, /*ifNot*/ linkIncrementalDefault) - << attrE(_LinkTimeCodeGeneration, tool.LinkTimeCodeGeneration) - << attrS(_LinkToManagedResourceFile, tool.LinkToManagedResourceFile) - << attrT(_MapExports, tool.MapExports) - << attrS(_MapFileName, tool.MapFileName) - << attrT(_MapLines, tool.MapLines) - << attrS(_MergedIDLBaseFileName, tool.MergedIDLBaseFileName) - << attrS(_MergeSections, tool.MergeSections) - << attrS(_MidlCommandFile, tool.MidlCommandFile) - << attrS(_ModuleDefinitionFile, tool.ModuleDefinitionFile) - << attrE(_OptimizeForWindows98, tool.OptimizeForWindows98, /*ifNot*/ optWin98Default) - << attrE(_OptimizeReferences, tool.OptimizeReferences, /*ifNot*/ optReferencesDefault) - << attrS(_OutputFile, tool.OutputFile) - << attr(_ProgramDatabaseFile, tool.ProgramDatabaseFile) - << attrT(_RegisterOutput, tool.RegisterOutput) - << attrT(_ResourceOnlyDLL, tool.ResourceOnlyDLL) - << attrT(_SetChecksum, tool.SetChecksum) - << attrE(_ShowProgress, tool.ShowProgress, /*ifNot*/ linkProgressNotSet) - << attrL(_StackCommitSize, tool.StackCommitSize, /*ifNot*/ -1) - << attrL(_StackReserveSize, tool.StackReserveSize, /*ifNot*/ -1) - << attrS(_StripPrivateSymbols, tool.StripPrivateSymbols) - << attrE(_SubSystem, tool.SubSystem) - << attrT(_SupportUnloadOfDelayLoadedDLL, tool.SupportUnloadOfDelayLoadedDLL) - << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner) - << attrT(_SwapRunFromCD, tool.SwapRunFromCD) - << attrT(_SwapRunFromNet, tool.SwapRunFromNet) - << attrE(_TargetMachine, tool.TargetMachine, /*ifNot*/ machineNotSet) - << attrE(_TerminalServerAware, tool.TerminalServerAware, /*ifNot*/ termSvrAwareDefault) - << attrT(_TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration) - << attrS(_TypeLibraryFile, tool.TypeLibraryFile) - << attrL(_TypeLibraryResourceID, tool.TypeLibraryResourceID, /*ifNot*/ rcUseDefault) - << attrS(_Version, tool.Version) - << closetag(_Tool); -} - // Hashing routine to do fast option lookups ---- // Slightly rewritten to stop on ':' ',' and '\0' // Original routine in qtranslator.cpp ---------- @@ -1279,26 +1222,57 @@ bool VCLinkerTool::parseOption(const char* option) displayHash("POSIX"); displayHash("WINDOWS"); displayHash("WINDOWSCE"); displayHash("NET"); displayHash("CD"); displayHash("NO"); #endif bool found = true; - switch (elfHash(option)) { - case 0x3360dbe: // /ALIGN[:number] - case 0x1485c34: // /ALLOWBIND[:NO] + const uint optionHash = elfHash(option); + if (config->CompilerVersion < NET2010) { + switch (optionHash) { + case 0x3360dbe: // /ALIGN[:number] + case 0x1485c34: // /ALLOWBIND[:NO] + case 0x33aec94: // /FIXED[:NO] + case 0x7988f7e: // /SECTION:name,[E][R][W][S][D][K][L][P][X][,ALIGN=#] + case 0x0348992: // /STUB:filename + AdditionalOptions += option; + return true; + } + } + + switch (optionHash) { case 0x6b21972: // /DEFAULTLIB:library case 0x396ea92: // /DRIVER[:UPONLY | :WDM] case 0xaca9d75: // /EXETYPE[:DYNAMIC | :DEV386] case 0x3ad5444: // /EXPORT:entryname[,@ordinal[,NONAME]][,DATA] - case 0x33aec94: // /FIXED[:NO] case 0x33b4675: // /FORCE:[MULTIPLE|UNRESOLVED] case 0x3dc3455: // /IGNORE:number,number,number,number ### NOTE: This one is undocumented, but it is even used by Microsoft. // In recent versions of the Microsoft linker they have disabled this undocumented feature. - case 0x7988f7e: // /SECTION:name,[E][R][W][S][D][K][L][P][X][,ALIGN=#] - case 0x0348992: // /STUB:filename case 0x0034bc4: // /VXD - case 0x0034c50: // /WS AdditionalOptions += option; break; + case 0x3360dbe: // /ALIGN[:number] + SectionAlignment = QString(option+7).toLongLong(); + break; + case 0x1485c34: // /ALLOWBIND[:NO] + if(*(option+10) == ':' && (*(option+11) == 'n' || *(option+11) == 'N')) + PreventDllBinding = _False; + else + PreventDllBinding = _True; + break; + case 0x312011e: // /ALLOWISOLATION[:NO] + if(*(option+15) == ':' && (*(option+16) == 'n' || *(option+16) == 'N')) + AllowIsolation = _False; + else + AllowIsolation = _True; + break; case 0x679c075: // /ASSEMBLYMODULE:filename AddModuleNamesToAssembly += option+15; break; + case 0x75f35f7: // /ASSEMBLYDEBUG[:DISABLE] + if(*(option+14) == ':' && (*(option+15) == 'D')) + AssemblyDebug = _False; + else + AssemblyDebug = _True; + break; + case 0x43294a5: // /ASSEMBLYLINKRESOURCE:filename + AssemblyLinkResource += option+22; + break; case 0x062d065: // /ASSEMBLYRESOURCE:filename LinkToManagedResourceFile = option+18; break; @@ -1308,6 +1282,71 @@ bool VCLinkerTool::parseOption(const char* option) // We don't use it in Qt, so keep it simple for now BaseAddress = option+6; break; + case 0x63bf065: // /CLRIMAGETYPE:{IJW|PURE|SAFE} + if(*(option+14) == 'I') + CLRImageType = "ForceIJWImage"; + else if(*(option+14) == 'P') + CLRImageType = "ForcePureILImage"; + else if(*(option+14) == 'S') + CLRImageType = "ForceSafeILImage"; + break; + case 0x5f2a6a2: // /CLRSUPPORTLASTERROR{:NO | SYSTEMDLL} + if(*(option+20) == ':') { + if(*(option+21) == 'N') { + CLRSupportLastError = "Disabled"; + } else if(*(option+21) == 'S') { + CLRSupportLastError = "SystemDlls"; + } + } else { + CLRSupportLastError = "Enabled"; + } + break; + case 0xc7984f5: // /CLRTHREADATTRIBUTE:{STA|MTA|NONE} + if(*(option+20) == 'N') + CLRThreadAttribute = "DefaultThreadingAttribute"; + else if(*(option+20) == 'M') + CLRThreadAttribute = "MTAThreadingAttribute"; + else if(*(option+20) == 'S') + CLRThreadAttribute = "STAThreadingAttribute"; + break; + case 0xa8c637b: // /CLRUNMANAGEDCODECHECK[:NO] + if(*(option+23) == 'N') + CLRUnmanagedCodeCheck = _False; + else + CLRUnmanagedCodeCheck = _True; + break; + case 0x62d9e94: // /MANIFEST[:NO] + if ((*(option+9) == ':' && (*(option+10) == 'N' || *(option+10) == 'n'))) + GenerateManifest = _False; + else + GenerateManifest = _True; + break; + case 0x8b64559: // /MANIFESTDEPENDENCY:manifest_dependency + AdditionalManifestDependencies += option+20; + break; + case 0xe9e8195: // /MANIFESTFILE:filename + ManifestFile = option+14; + break; + case 0x9e9fb83: // /MANIFESTUAC http://msdn.microsoft.com/en-us/library/bb384691%28VS.100%29.aspx + if ((*(option+12) == ':' && (*(option+13) == 'N' || *(option+13) == 'n'))) + EnableUAC = _False; + else if((*(option+12) == ':' && (*(option+13) == 'l' || *(option+14) == 'e'))) { // level + if(*(option+20) == 'a') + UACExecutionLevel = "AsInvoker"; + else if(*(option+20) == 'h') + UACExecutionLevel = "HighestAvailable"; + else if(*(option+20) == 'r') + UACExecutionLevel = "RequireAdministrator"; + } else if((*(option+12) == ':' && (*(option+13) == 'u' || *(option+14) == 'i'))) { // uiAccess + if(*(option+22) == 't') + UACUIAccess = _True; + else + UACUIAccess = _False; + } else if((*(option+12) == ':' && (*(option+13) == 'f' || *(option+14) == 'r'))) { // fragment + AdditionalOptions += option; + }else + EnableUAC = _True; + break; case 0x3389797: // /DEBUG GenerateDebugInformation = _True; break; @@ -1322,12 +1361,36 @@ bool VCLinkerTool::parseOption(const char* option) case 0x06f4bf4: // /DELAYLOAD:dllname DelayLoadDLLs += option+11; break; + case 0x06d451e: // /DELAYSIGN[:NO] + if(*(option+10) == ':' && (*(option+11) == 'n' || *(option+11) == 'N')) + DelaySign = _False; + else + DelaySign = _True; + break; case 0x003390c: // /DLL // This option is not used for vcproj files break; + case 0x2ee8415: // /DYNAMICBASE[:NO] + if(*(option+12) == ':' && (*(option+13) == 'n' || *(option+13) == 'N')) + RandomizedBaseAddress = _False; + else + RandomizedBaseAddress = _True; + break; case 0x33a3979: // /ENTRY:function EntryPointSymbol = option+7; break; + case 0x4504334: // /ERRORREPORT:[ NONE | PROMPT | QUEUE | SEND ] + if(*(option+12) == ':' ) { + if(*(option+13) == 'N') + LinkErrorReporting = "NoErrorReport"; + else if(*(option+13) == 'P') + LinkErrorReporting = "PromptImmediately"; + else if(*(option+13) == 'Q') + LinkErrorReporting = "QueueForNextLogin"; + else if(*(option+13) == 'S') + LinkErrorReporting = "SendErrorReport"; + } + break; case 0x033c960: // /HEAP:reserve[,commit] { QStringList both = QString(option+6).split(","); @@ -1355,6 +1418,12 @@ bool VCLinkerTool::parseOption(const char* option) else LinkIncremental = linkIncrementalYes; break; + case 0x07f1ab2: // /KEYCONTAINER:name + KeyContainer = option+14; + break; + case 0xfadaf35: // /KEYFILE:filename + KeyFile = option+9; + break; case 0x26e4675: // /LARGEADDRESSAWARE[:no] if(*(option+18) == ':' && *(option+19) == 'n') @@ -1460,6 +1529,12 @@ bool VCLinkerTool::parseOption(const char* option) case 0x434138f: // /NOLOGO SuppressStartupBanner = _True; break; + case 0xc841054: // /NXCOMPAT[:NO] + if ((*(option+9) == ':' && (*(option+10) == 'N' || *(option+10) == 'n'))) + DataExecutionPrevention = _False; + else + DataExecutionPrevention = _True; + break; case 0x0034454: // /OPT:{REF | NOREF | ICF[=iterations] | NOICF | WIN98 | NOWIN98} { char third = *(option+7); @@ -1537,7 +1612,7 @@ bool VCLinkerTool::parseOption(const char* option) case 0x5268ea5: // NATIVE case 0x05547e8: // POSIX case 0x2949c95: // WINDOWSCE - case 0x4B69795: // windowsce + case 0x4B69795: // windowsce AdditionalOptions += option; break; default: @@ -1576,6 +1651,16 @@ bool VCLinkerTool::parseOption(const char* option) case 0xaa77f7e: // /VERSION:major[.minor] Version = option+9; break; + case 0x0034c50: // /WS[:NO] + if (config->CompilerVersion >= NET2010) { + if(*(option+3) == ':') + TreatWarningsAsErrors = _False; + else + TreatWarningsAsErrors = _True; + } else { + AdditionalOptions += option; + } + break; default: AdditionalOptions += option; break; @@ -1605,46 +1690,12 @@ VCMIDLTool::VCMIDLTool() TargetEnvironment(midlTargetNotSet), ValidateParameters(unset), WarnAsError(unset), - WarningLevel(midlWarningLevel_0) -{ -} - -XmlOutput &operator<<(XmlOutput &xml, const VCMIDLTool &tool) + WarningLevel(midlWarningLevel_0), + ApplicationConfigurationMode(unset), + ValidateAllParameters(unset), + SuppressCompilerWarnings(unset), + LocaleID(-1) { - return xml - << tag(_Tool) - << attrS(_Name, _VCMIDLTool) - << attrX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories) - << attrX(_AdditionalOptions, tool.AdditionalOptions, " ") - << attrX(_CPreprocessOptions, tool.CPreprocessOptions) - << attrE(_DefaultCharType, tool.DefaultCharType) - << attrS(_DLLDataFileName, tool.DLLDataFileName) - << attrE(_EnableErrorChecks, tool.EnableErrorChecks) - << attrT(_ErrorCheckAllocations, tool.ErrorCheckAllocations) - << attrT(_ErrorCheckBounds, tool.ErrorCheckBounds) - << attrT(_ErrorCheckEnumRange, tool.ErrorCheckEnumRange) - << attrT(_ErrorCheckRefPointers, tool.ErrorCheckRefPointers) - << attrT(_ErrorCheckStubData, tool.ErrorCheckStubData) - << attrX(_FullIncludePath, tool.FullIncludePath) - << attrT(_GenerateStublessProxies, tool.GenerateStublessProxies) - << attrT(_GenerateTypeLibrary, tool.GenerateTypeLibrary) - << attrS(_HeaderFileName, tool.HeaderFileName) - << attrT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) - << attrS(_InterfaceIdentifierFileName, tool.InterfaceIdentifierFileName) - << attrT(_MkTypLibCompatible, tool.MkTypLibCompatible) - << attrS(_OutputDirectory, tool.OutputDirectory) - << attrX(_PreprocessorDefinitions, tool.PreprocessorDefinitions) - << attrS(_ProxyFileName, tool.ProxyFileName) - << attrS(_RedirectOutputAndErrors, tool.RedirectOutputAndErrors) - << attrE(_StructMemberAlignment, tool.StructMemberAlignment, /*ifNot*/ midlAlignNotSet) - << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner) - << attrE(_TargetEnvironment, tool.TargetEnvironment, /*ifNot*/ midlTargetNotSet) - << attrS(_TypeLibraryName, tool.TypeLibraryName) - << attrX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions) - << attrT(_ValidateParameters, tool.ValidateParameters) - << attrT(_WarnAsError, tool.WarnAsError) - << attrE(_WarningLevel, tool.WarningLevel) - << closetag(_Tool); } bool VCMIDLTool::parseOption(const char* option) @@ -1679,7 +1730,25 @@ bool VCMIDLTool::parseOption(const char* option) #endif bool found = true; int offset = 0; - switch(elfHash(option)) { + + const uint optionHash = elfHash(option); + + if (config->CompilerVersion < NET2010) { + switch (optionHash) { + case 0x5b1cb97: // /app_config + case 0x5a2fc64: // /client {none|stub} + case 0x35aabb2: // /cstub filename + case 0x64ceb12: // /newtlb + case 0x556dbee: // /no_warn + case 0x662bb12: // /oldtlb + case 0x69c9cf2: // /server {none|stub} + case 0x36aabb2: // /sstub filename + AdditionalOptions += option; + return true; + } + } + + switch(optionHash) { case 0x0000334: // /D name[=def] PreprocessorDefinitions += option+3; break; @@ -1716,6 +1785,9 @@ bool VCMIDLTool::parseOption(const char* option) found = false; } break; + case 0x5b1cb97: // /app_config + ApplicationConfigurationMode = _True; + break; case 0x0359e82: // /char {ascii7|signed|unsigned} switch(*(option+6)) { case 'a': @@ -1731,9 +1803,18 @@ bool VCMIDLTool::parseOption(const char* option) found = false; } break; + case 0x5a2fc64: // /client {none|stub} + if(*(option+8) == 's') + GenerateClientFiles = "Stub"; + else + GenerateClientFiles = "None"; + break; case 0xa766524: // /cpp_opt options CPreprocessOptions += option+9; break; + case 0x35aabb2: // /cstub filename + ClientStubFile = option+7; + break; case 0xb32abf1: // /dlldata filename DLLDataFileName = option + 9; break; @@ -1779,18 +1860,30 @@ bool VCMIDLTool::parseOption(const char* option) case 0x64b7933: // /mktyplib203 MkTypLibCompatible = _True; break; + case 0x64ceb12: // /newtlb + TypeLibFormat = "NewFormat"; + break; case 0x8e0b0a2: // /no_def_idir IgnoreStandardIncludePath = _True; break; case 0x65635ef: // /nologo SuppressStartupBanner = _True; break; + case 0x695e9f4: // /no_robust + ValidateAllParameters = _False; + break; case 0x3656b22: // /notlb GenerateTypeLibrary = _True; break; + case 0x556dbee: // /no_warn + SuppressCompilerWarnings = _True; + break; case 0x000035f: // /o filename RedirectOutputAndErrors = option+3; break; + case 0x662bb12: // /oldtlb + TypeLibFormat = "OldFormat"; + break; case 0x00366c4: // /out directory OutputDirectory = option+5; break; @@ -1806,6 +1899,15 @@ bool VCMIDLTool::parseOption(const char* option) else TargetEnvironment = midlTargetWin32; break; + case 0x69c9cf2: // /server {none|stub} + if(*(option+8) == 's') + GenerateServerFiles = "Stub"; + else + GenerateServerFiles = "None"; + break; + case 0x36aabb2: // /sstub filename + ServerStubFile = option+7; + break; case 0x0036b22: // /tlb filename TypeLibraryName = option+5; break; @@ -1820,32 +1922,24 @@ bool VCMIDLTool::parseOption(const char* option) case 0x0003463: // /Os case 0x0003513: // /Zs case 0x0035796: // /acf filename - case 0x5b1cb97: // /app_config case 0x3595cf4: // /c_ext - case 0x5a2fc64: // /client {none|stub} case 0xa64d3dd: // /confirm case 0xa765b64: // /cpp_cmd cmd_line - case 0x35aabb2: // /cstub filename case 0x03629f4: // /lcid case 0x6495cc4: // /ms_ext case 0x96c7a1e: // /ms_union case 0x4996fa2: // /msc_ver <nnnn> - case 0x64ceb12: // /newtlb case 0x6555a40: // /no_cpp case 0xf64d6a6: // /no_default_epv case 0x6dd9384: // /no_format_opt - case 0x556dbee: // /no_warn case 0x3655a70: // /nocpp case 0x2b455a3: // /oldnames - case 0x662bb12: // /oldtlb case 0x0036696: // /osf case 0x036679b: // /pack {N} case 0x678bd38: // /prefix {all|client|server|switch} case 0x96b702c: // /protocol {all|dce|ndr64} case 0x3696aa3: // /rpcss case 0x698ca60: // /savePP - case 0x69c9cf2: // /server {none|stub} - case 0x36aabb2: // /sstub filename case 0xce9b12b: // /syntax_check case 0xc9b5f16: // /use_epv AdditionalOptions += option; @@ -1887,94 +1981,22 @@ VCLibrarianTool::VCLibrarianTool() { } -XmlOutput &operator<<(XmlOutput &xml, const VCLibrarianTool &tool) -{ - return xml - << tag(_Tool) - << attrS(_Name, _VCLibrarianTool) - << attrX(_AdditionalDependencies, tool.AdditionalDependencies) - << attrX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories) - << attrX(_AdditionalOptions, tool.AdditionalOptions, " ") - << attrX(_ExportNamedFunctions, tool.ExportNamedFunctions) - << attrX(_ForceSymbolReferences, tool.ForceSymbolReferences) - << attrT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries) - << attrX(_IgnoreDefaultLibraryNames, tool.IgnoreDefaultLibraryNames) - << attrS(_ModuleDefinitionFile, tool.ModuleDefinitionFile) - << attrS(_OutputFile, tool.OutputFile) - << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner) - << closetag(_Tool); -} - // VCCustomBuildTool ------------------------------------------------ VCCustomBuildTool::VCCustomBuildTool() { ToolName = "VCCustomBuildTool"; } -XmlOutput &operator<<(XmlOutput &xml, const VCCustomBuildTool &tool) -{ - // The code below offers two ways to split custom build step commands. - // Normally the $$escape_expand(\n\t) is used in a project file, which is correctly translated - // in all generators. However, if you use $$escape_expand(\n\r) (or \n\h) instead, the VCPROJ - // generator will instead of binding the commands with " && " will insert a proper newline into - // the VCPROJ file. We sometimes use this method of splitting commands if the custom buildstep - // contains a command-line which is too big to run on certain OS. - QString cmds; - int end = tool.CommandLine.count(); - for(int i = 0; i < end; ++i) { - QString cmdl = tool.CommandLine.at(i); - if (cmdl.contains("\r\t")) { - if (i == end - 1) - cmdl = cmdl.trimmed(); - cmdl.replace("\r\t", " && "); - } else if (cmdl.contains("\r\n")) { - ; - } else if (cmdl.contains("\r\\h")) { - // The above \r\n should work, but doesn't, so we have this hack - cmdl.replace("\r\\h", "\r\n"); - } else { - if (i < end - 1) - cmdl += " && "; - } - cmds += cmdl; - } - return xml - << tag(_Tool) - << attrS(_Name, tool.ToolName) - << attrX(_AdditionalDependencies, tool.AdditionalDependencies, ";") - << attrS(_CommandLine, cmds) - << attrS(_Description, tool.Description) - << attrX(_Outputs, tool.Outputs, ";") - << attrS(_Path, tool.ToolPath) - << closetag(_Tool); -} - // VCResourceCompilerTool ------------------------------------------- VCResourceCompilerTool::VCResourceCompilerTool() : Culture(rcUseDefault), IgnoreStandardIncludePath(unset), - ShowProgress(linkProgressNotSet) + ShowProgress(linkProgressNotSet), + SuppressStartupBanner(unset) { PreprocessorDefinitions = QStringList("NDEBUG"); } -XmlOutput &operator<<(XmlOutput &xml, const VCResourceCompilerTool &tool) -{ - return xml - << tag(_Tool) - << attrS(_Name, _VCResourceCompilerTool) - << attrS(_Path, tool.ToolPath) - << attrX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories) - << attrX(_AdditionalOptions, tool.AdditionalOptions, " ") - << attrE(_Culture, tool.Culture, /*ifNot*/ rcUseDefault) - << attrX(_FullIncludePath, tool.FullIncludePath) - << attrT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) - << attrX(_PreprocessorDefinitions, tool.PreprocessorDefinitions) - << attrS(_ResourceOutputFileName, tool.ResourceOutputFileName) - << attrE(_ShowProgress, tool.ShowProgress, /*ifNot*/ linkProgressNotSet) - << closetag(_Tool); -} - // VCDeploymentTool -------------------------------------------- VCDeploymentTool::VCDeploymentTool() : RegisterOutput(registerNo) @@ -1983,47 +2005,31 @@ VCDeploymentTool::VCDeploymentTool() RemoteDirectory = ""; } -XmlOutput &operator<<(XmlOutput &xml, const VCDeploymentTool &tool) +VCEventTool::VCEventTool(const QString &eventName) + : ExcludedFromBuild(unset) { - if (tool.AdditionalFiles.isEmpty()) - return xml; - return xml - << tag(tool.DeploymentTag) - << attrS(_RemoteDirectory, tool.RemoteDirectory) - << attrE(_RegisterOutput, tool.RegisterOutput) - << attrS(_AdditionalFiles, tool.AdditionalFiles) - << closetag(tool.DeploymentTag); -} - -// VCEventTool ------------------------------------------------- -XmlOutput &operator<<(XmlOutput &xml, const VCEventTool &tool) -{ - return xml - << tag(_Tool) - << attrS(_Name, tool.ToolName) - << attrS(_Path, tool.ToolPath) - << attrS(_CommandLine, tool.CommandLine) - << attrS(_Description, tool.Description) - << attrT(_ExcludedFromBuild, tool.ExcludedFromBuild) - << closetag(_Tool); + EventName = eventName; + ToolName = "VC"; + ToolName += eventName; + ToolName += "Tool"; } // VCPostBuildEventTool --------------------------------------------- VCPostBuildEventTool::VCPostBuildEventTool() + : VCEventTool("PostBuildEvent") { - ToolName = "VCPostBuildEventTool"; } // VCPreBuildEventTool ---------------------------------------------- VCPreBuildEventTool::VCPreBuildEventTool() + : VCEventTool("PreBuildEvent") { - ToolName = "VCPreBuildEventTool"; } // VCPreLinkEventTool ----------------------------------------------- VCPreLinkEventTool::VCPreLinkEventTool() + : VCEventTool("PreLinkEvent") { - ToolName = "VCPreLinkEventTool"; } // VCConfiguration -------------------------------------------------- @@ -2041,41 +2047,9 @@ VCConfiguration::VCConfiguration() compiler.config = this; linker.config = this; idl.config = this; + custom.config = this; } -XmlOutput &operator<<(XmlOutput &xml, const VCConfiguration &tool) -{ - xml << tag(_Configuration) - << attrS(_Name, tool.Name) - << attrS(_OutputDirectory, tool.OutputDirectory) - << attrT(_ATLMinimizesCRunTimeLibraryUsage, tool.ATLMinimizesCRunTimeLibraryUsage) - << attrT(_BuildBrowserInformation, tool.BuildBrowserInformation) - << attrE(_CharacterSet, tool.CharacterSet, /*ifNot*/ charSetNotSet) - << attrE(_ConfigurationType, tool.ConfigurationType) - << attrS(_DeleteExtensionsOnClean, tool.DeleteExtensionsOnClean) - << attrS(_ImportLibrary, tool.ImportLibrary) - << attrS(_IntermediateDirectory, tool.IntermediateDirectory) - << attrS(_PrimaryOutput, tool.PrimaryOutput) - << attrS(_ProgramDatabase, tool.ProgramDatabase) - << attrT(_RegisterOutput, tool.RegisterOutput) - << attrE(_UseOfATL, tool.UseOfATL, /*ifNot*/ useATLNotSet) - << attrE(_UseOfMfc, tool.UseOfMfc) - << attrT(_WholeProgramOptimization, tool.WholeProgramOptimization) - << tool.compiler - << tool.custom; - if (tool.ConfigurationType == typeStaticLibrary) - xml << tool.librarian; - else - xml << tool.linker; - xml << tool.idl - << tool.postBuild - << tool.preBuild - << tool.preLink - << tool.resource - << tool.deployment - << closetag(_Configuration); - return xml; -} // VCFilter --------------------------------------------------------- VCFilter::VCFilter() : ParseFiles(unset), @@ -2137,7 +2111,9 @@ void VCFilter::modifyPCHstage(QString str) lines << "*"; lines << "* This file is auto-generated by qmake since no PRECOMPILED_SOURCE was"; lines << "* specified, and is used as the common stdafx.cpp. The file is only"; - lines << "* generated when creating .vcproj project files, and is not used for"; + lines << QLatin1String("* generated when creating ") + + (Config->CompilerVersion < NET2010 ? ".vcproj" : ".vcxproj") + + " project files, and is not used for"; lines << "* command line compilations by nmake."; lines << "*"; lines << "* WARNING: All changes made in this file will be lost."; @@ -2325,135 +2301,17 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info) return useCustomBuildTool; } -void VCFilter::outputFileConfig(XmlOutput &xml, const QString &filename) -{ - // Clearing each filter tool - useCustomBuildTool = false; - useCompilerTool = false; - CustomBuildTool = VCCustomBuildTool(); - CompilerTool = VCCLCompilerTool(); - - // Unset some default options - CompilerTool.BufferSecurityCheck = unset; - CompilerTool.DebugInformationFormat = debugUnknown; - CompilerTool.ExceptionHandling = ehDefault; - CompilerTool.GeneratePreprocessedFile = preprocessUnknown; - CompilerTool.Optimization = optimizeDefault; - CompilerTool.ProgramDataBaseFileName.clear(); - CompilerTool.RuntimeLibrary = rtUnknown; - CompilerTool.WarningLevel = warningLevelUnknown; - CompilerTool.config = Config; - - bool inBuild = false; - VCFilterFile info; - for (int i = 0; i < Files.count(); ++i) { - if (Files.at(i).file == filename) { - info = Files.at(i); - inBuild = true; - } - } - inBuild &= !info.excludeFromBuild; - - if (inBuild) { - addExtraCompiler(info); - if(Project->usePCH) - modifyPCHstage(info.file); - } else { - // Excluded files uses an empty compiler stage - if(info.excludeFromBuild) - useCompilerTool = true; - } - - // Actual XML output ---------------------------------- - if(useCustomBuildTool || useCompilerTool || !inBuild) { - xml << tag(_FileConfiguration) - << attr(_Name, (*Config).Name) - << (!inBuild ? attrS(_ExcludedFromBuild, "true") : noxml()); - if (useCustomBuildTool) - xml << CustomBuildTool; - if (useCompilerTool) - xml << CompilerTool; - xml << closetag(_FileConfiguration); - } -} - -XmlOutput &operator<<(XmlOutput &xml, VCFilter &tool) -{ - if(!tool.Files.count()) - return xml; - - if (!tool.Name.isEmpty()) { - xml << tag(_Filter) - << attrS(_Name, tool.Name) - << attrS(_Filter, tool.Filter) - << attrS(_UniqueIdentifier, tool.Guid) - << attrT(_ParseFiles, tool.ParseFiles); - } - for (int i = 0; i < tool.Files.count(); ++i) { - const VCFilterFile &info = tool.Files.at(i); - xml << tag(q_File) - << attrS(_RelativePath, Option::fixPathToLocalOS(info.file)) - << data(); // In case no custom builds, to avoid "/>" endings - tool.outputFileConfig(xml, tool.Files.at(i).file); - xml << closetag(q_File); - } - if (!tool.Name.isEmpty()) - xml << closetag(_Filter); - return xml; -} - // VCProjectSingleConfig -------------------------------------------- -VCFilter nullFilter; VCFilter& VCProjectSingleConfig::filterForExtraCompiler(const QString &compilerName) { for (int i = 0; i < ExtraCompilersFiles.count(); ++i) if (ExtraCompilersFiles.at(i).Name == compilerName) return ExtraCompilersFiles[i]; - return nullFilter; -} - -XmlOutput &operator<<(XmlOutput &xml, const VCProjectSingleConfig &tool) -{ - xml << decl("1.0", "Windows-1252") - << tag(_VisualStudioProject) - << attrS(_ProjectType, "Visual C++") - << attrS(_Version, tool.Version) - << attrS(_Name, tool.Name) - << attrS(_ProjectGUID, tool.ProjectGUID) - << attrS(_Keyword, tool.Keyword) - << attrS(_SccProjectName, tool.SccProjectName) - << attrS(_SccLocalPath, tool.SccLocalPath) - << tag(_Platforms) - << tag(_Platform) - << attrS(_Name, tool.PlatformName) - << closetag(_Platforms) - << tag(_Configurations) - << tool.Configuration; - xml << closetag(_Configurations) - << tag(q_Files); - // Add this configuration into a multi-config project, since that's where we have the flat/tree - // XML output functionality - VCProject tempProj; - tempProj.SingleProjects += tool; - tempProj.outputFilter(xml, "Sources"); - tempProj.outputFilter(xml, "Headers"); - tempProj.outputFilter(xml, "GeneratedFiles"); - tempProj.outputFilter(xml, "LexYaccFiles"); - tempProj.outputFilter(xml, "TranslationFiles"); - tempProj.outputFilter(xml, "FormFiles"); - tempProj.outputFilter(xml, "ResourceFiles"); - for (int x = 0; x < tempProj.ExtraCompilers.count(); ++x) { - tempProj.outputFilter(xml, tempProj.ExtraCompilers.at(x)); - } - tempProj.outputFilter(xml, "RootFiles"); - xml << closetag(q_Files) - << tag(_Globals) - << data(); // No "/>" end tag - return xml; + static VCFilter nullFilter; + return nullFilter; } - // Tree file generation --------------------------------------------- void TreeNode::generateXML(XmlOutput &xml, const QString &tagName, VCProject &tool, const QString &filter) { if (children.size()) { @@ -2477,69 +2335,431 @@ void TreeNode::generateXML(XmlOutput &xml, const QString &tagName, VCProject &to xml << closetag("Filter"); } else { // Leaf - tool.outputFileConfigs(xml, info, filter); + VCProjectWriter::outputFileConfigs(tool, xml, info, filter); } } - // Flat file generation --------------------------------------------- void FlatNode::generateXML(XmlOutput &xml, const QString &/*tagName*/, VCProject &tool, const QString &filter) { if (children.size()) { ChildrenMapFlat::ConstIterator it = children.constBegin(); ChildrenMapFlat::ConstIterator end = children.constEnd(); for (; it != end; ++it) { - tool.outputFileConfigs(xml, (*it), filter); + VCProjectWriter::outputFileConfigs(tool, xml, (*it), filter); } } } +void VCProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool) +{ + xml << decl("1.0", "Windows-1252") + << tag(_VisualStudioProject) + << attrS(_ProjectType, "Visual C++") + << attrS(_Version, tool.Version) + << attrS(_Name, tool.Name) + << attrS(_ProjectGUID, tool.ProjectGUID) + << attrS(_Keyword, tool.Keyword) + << attrS(_SccProjectName, tool.SccProjectName) + << attrS(_SccLocalPath, tool.SccLocalPath) + << tag(_Platforms) + << tag(_Platform) + << attrS(_Name, tool.PlatformName) + << closetag(_Platforms) + << tag(_Configurations); + write(xml, tool.Configuration); + xml << closetag(_Configurations) + << tag(q_Files); + // Add this configuration into a multi-config project, since that's where we have the flat/tree + // XML output functionality + VCProject tempProj; + tempProj.SingleProjects += tool; + outputFilter(tempProj, xml, "Sources"); + outputFilter(tempProj, xml, "Headers"); + outputFilter(tempProj, xml, "GeneratedFiles"); + outputFilter(tempProj, xml, "LexYaccFiles"); + outputFilter(tempProj, xml, "TranslationFiles"); + outputFilter(tempProj, xml, "FormFiles"); + outputFilter(tempProj, xml, "ResourceFiles"); + for (int x = 0; x < tempProj.ExtraCompilers.count(); ++x) { + outputFilter(tempProj, xml, tempProj.ExtraCompilers.at(x)); + } + outputFilter(tempProj, xml, "RootFiles"); + xml << closetag(q_Files) + << tag(_Globals) + << data(); // No "/>" end tag +} -// VCProject -------------------------------------------------------- -// Output all configurations (by filtername) for a file (by info) -// A filters config output is in VCFilter.outputFileConfig() -void VCProject::outputFileConfigs(XmlOutput &xml, -// VCProjectSingleConfig::FilterTypes type - const VCFilterFile &info, - const QString &filtername) +void VCProjectWriter::write(XmlOutput &xml, VCProject &tool) { - xml << tag(q_File) - << attrS(_RelativePath, Option::fixPathToLocalOS(info.file)); - for (int i = 0; i < SingleProjects.count(); ++i) { - VCFilter filter; - if (filtername == "RootFiles") { - filter = SingleProjects.at(i).RootFiles; - } else if (filtername == "Sources") { - filter = SingleProjects.at(i).SourceFiles; - } else if (filtername == "Headers") { - filter = SingleProjects.at(i).HeaderFiles; - } else if (filtername == "GeneratedFiles") { - filter = SingleProjects.at(i).GeneratedFiles; - } else if (filtername == "LexYaccFiles") { - filter = SingleProjects.at(i).LexYaccFiles; - } else if (filtername == "TranslationFiles") { - filter = SingleProjects.at(i).TranslationFiles; - } else if (filtername == "FormFiles") { - filter = SingleProjects.at(i).FormFiles; - } else if (filtername == "ResourceFiles") { - filter = SingleProjects.at(i).ResourceFiles; + if (tool.SingleProjects.count() == 0) { + warn_msg(WarnLogic, "Generator: .NET: no single project in merge project, no output"); + return; + } + + xml << decl("1.0", "Windows-1252") + << tag(_VisualStudioProject) + << attrS(_ProjectType, "Visual C++") + << attrS(_Version, tool.Version) + << attrS(_Name, tool.Name) + << attrS(_ProjectGUID, tool.ProjectGUID) + << attrS(_Keyword, tool.Keyword) + << attrS(_SccProjectName, tool.SccProjectName) + << attrS(_SccLocalPath, tool.SccLocalPath) + << tag(_Platforms) + << tag(_Platform) + << attrS(_Name, tool.PlatformName) + << closetag(_Platforms) + << tag(_Configurations); + // Output each configuration + for (int i = 0; i < tool.SingleProjects.count(); ++i) + write(xml, tool.SingleProjects.at(i).Configuration); + xml << closetag(_Configurations) + << tag(q_Files); + outputFilter(tool, xml, "Sources"); + outputFilter(tool, xml, "Headers"); + outputFilter(tool, xml, "GeneratedFiles"); + outputFilter(tool, xml, "LexYaccFiles"); + outputFilter(tool, xml, "TranslationFiles"); + outputFilter(tool, xml, "FormFiles"); + outputFilter(tool, xml, "ResourceFiles"); + for (int x = 0; x < tool.ExtraCompilers.count(); ++x) { + outputFilter(tool, xml, tool.ExtraCompilers.at(x)); + } + outputFilter(tool, xml, "RootFiles"); + xml << closetag(q_Files) + << tag(_Globals) + << data(); // No "/>" end tag +} + +void VCProjectWriter::write(XmlOutput &xml, const VCCLCompilerTool &tool) +{ + xml << tag(_Tool) + << attrS(_Name, _VCCLCompilerTool) + << attrX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories) + << attrX(_AdditionalOptions, tool.AdditionalOptions, " ") + << attrX(_AdditionalUsingDirectories, tool.AdditionalUsingDirectories) + << attrS(_AssemblerListingLocation, tool.AssemblerListingLocation) + << attrE(_AssemblerOutput, tool.AssemblerOutput, /*ifNot*/ asmListingNone) + << attrE(_BasicRuntimeChecks, tool.BasicRuntimeChecks, /*ifNot*/ runtimeBasicCheckNone) + << attrE(_BrowseInformation, tool.BrowseInformation, /*ifNot*/ brInfoNone) + << attrS(_BrowseInformationFile, tool.BrowseInformationFile) + << attrT(_BufferSecurityCheck, tool.BufferSecurityCheck) + << attrE(_CallingConvention, tool.CallingConvention, /*ifNot*/ callConventionDefault) + << attrE(_CompileAs, tool.CompileAs, compileAsDefault) + << attrE(_CompileAsManaged, tool.CompileAsManaged, /*ifNot*/ managedDefault) + << attrT(_CompileOnly, tool.CompileOnly) + << attrE(_DebugInformationFormat, tool.DebugInformationFormat, /*ifNot*/ debugUnknown) + << attrT(_DefaultCharIsUnsigned, tool.DefaultCharIsUnsigned) + << attrT(_Detect64BitPortabilityProblems, tool.Detect64BitPortabilityProblems) + << attrT(_DisableLanguageExtensions, tool.DisableLanguageExtensions) + << attrX(_DisableSpecificWarnings, tool.DisableSpecificWarnings) + << attrE(_EnableEnhancedInstructionSet, tool.EnableEnhancedInstructionSet, /*ifnot*/ archNotSet) + << attrT(_EnableFiberSafeOptimizations, tool.EnableFiberSafeOptimizations) + << attrT(_EnableFunctionLevelLinking, tool.EnableFunctionLevelLinking) + << attrT(_EnableIntrinsicFunctions, tool.EnableIntrinsicFunctions) + << xformExceptionHandlingNET2005(tool.ExceptionHandling, tool.config->CompilerVersion) + << attrT(_ExpandAttributedSource, tool.ExpandAttributedSource) + << attrE(_FavorSizeOrSpeed, tool.FavorSizeOrSpeed, /*ifNot*/ favorNone) + + << attrE(_FloatingPointModel, tool.FloatingPointModel, /*ifNot*/ floatingPointNotSet) + << attrT(_FloatingPointExceptions, tool.FloatingPointExceptions) + + << attrT(_ForceConformanceInForLoopScope, tool.ForceConformanceInForLoopScope) + << attrX(_ForcedIncludeFiles, tool.ForcedIncludeFiles) + << attrX(_ForcedUsingFiles, tool.ForcedUsingFiles) + << attrE(_GeneratePreprocessedFile, tool.GeneratePreprocessedFile, /*ifNot*/ preprocessUnknown) + << attrT(_GlobalOptimizations, tool.GlobalOptimizations) + << attrT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) + << attrT(_ImproveFloatingPointConsistency, tool.ImproveFloatingPointConsistency) + << attrE(_InlineFunctionExpansion, tool.InlineFunctionExpansion, /*ifNot*/ expandDefault) + << attrT(_KeepComments, tool.KeepComments) + << attrT(_MinimalRebuild, tool.MinimalRebuild) + << attrS(_ObjectFile, tool.ObjectFile) + << attrT(_OmitFramePointers, tool.OmitFramePointers) + << attrT(_OpenMP, tool.OpenMP) + << attrE(_Optimization, tool.Optimization, /*ifNot*/ optimizeDefault) + << attrE(_OptimizeForProcessor, tool.OptimizeForProcessor, /*ifNot*/ procOptimizeBlended) + << attrT(_OptimizeForWindowsApplication, tool.OptimizeForWindowsApplication) + << attrS(_OutputFile, tool.OutputFile) + << attrS(_PrecompiledHeaderFile, tool.PrecompiledHeaderFile) + << attrS(_PrecompiledHeaderThrough, tool.PrecompiledHeaderThrough) + << attrX(_PreprocessorDefinitions, tool.PreprocessorDefinitions) + << (tool.ProgramDataBaseFileName.isNull() ? noxml() : attr(_ProgramDataBaseFileName, tool.ProgramDataBaseFileName)) + << attrE(_RuntimeLibrary, tool.RuntimeLibrary, /*ifNot*/ rtUnknown) + << attrT(_RuntimeTypeInfo, tool.RuntimeTypeInfo) + << attrT(_ShowIncludes, tool.ShowIncludes) + << attrT(_SmallerTypeCheck, tool.SmallerTypeCheck) + << attrT(_StringPooling, tool.StringPooling) + << attrE(_StructMemberAlignment, tool.StructMemberAlignment, /*ifNot*/ alignNotSet) + << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner) + << attrT(_TreatWChar_tAsBuiltInType, tool.TreatWChar_tAsBuiltInType) + << attrT(_TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration) + << attrT(_UndefineAllPreprocessorDefinitions, tool.UndefineAllPreprocessorDefinitions) + << attrX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions) + << (!tool.PrecompiledHeaderFile.isEmpty() || !tool.PrecompiledHeaderThrough.isEmpty() ? xformUsePrecompiledHeaderForNET2005(tool.UsePrecompiledHeader, tool.config->CompilerVersion) : noxml()) + << attrT(_WarnAsError, tool.WarnAsError) + << attrE(_WarningLevel, tool.WarningLevel, /*ifNot*/ warningLevelUnknown) + << attrT(_WholeProgramOptimization, tool.WholeProgramOptimization) + << attrE(_CompileForArchitecture, tool.CompileForArchitecture, /*ifNot*/ archUnknown) + << attrT(_InterworkCalls, tool.InterworkCalls) + + << closetag(_Tool); +} + +void VCProjectWriter::write(XmlOutput &xml, const VCLinkerTool &tool) +{ + xml << tag(_Tool) + << attrS(_Name, _VCLinkerTool) + << attrX(_AdditionalDependencies, tool.AdditionalDependencies, " ") + << attrX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories) + << attrX(_AdditionalOptions, tool.AdditionalOptions, " ") + << attrX(_AddModuleNamesToAssembly, tool.AddModuleNamesToAssembly) + << attrS(_BaseAddress, tool.BaseAddress) + << attrX(_DelayLoadDLLs, tool.DelayLoadDLLs) + << attrE(_EnableCOMDATFolding, tool.EnableCOMDATFolding, /*ifNot*/ optFoldingDefault) + << attrS(_EntryPointSymbol, tool.EntryPointSymbol) + << attrX(_ForceSymbolReferences, tool.ForceSymbolReferences) + << attrS(_FunctionOrder, tool.FunctionOrder) + << attrT(_GenerateDebugInformation, tool.GenerateDebugInformation) + << attrT(_GenerateMapFile, tool.GenerateMapFile) + << attrL(_HeapCommitSize, tool.HeapCommitSize, /*ifNot*/ -1) + << attrL(_HeapReserveSize, tool.HeapReserveSize, /*ifNot*/ -1) + << attrT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries) + << attrX(_IgnoreDefaultLibraryNames, tool.IgnoreDefaultLibraryNames) + << attrT(_IgnoreEmbeddedIDL, tool.IgnoreEmbeddedIDL) + << attrT(_IgnoreImportLibrary, tool.IgnoreImportLibrary) + << attrS(_ImportLibrary, tool.ImportLibrary) + << attrE(_LargeAddressAware, tool.LargeAddressAware, /*ifNot*/ addrAwareDefault) + << attrT(_LinkDLL, tool.LinkDLL) + << attrE(_LinkIncremental, tool.LinkIncremental, /*ifNot*/ linkIncrementalDefault) + << attrE(_LinkTimeCodeGeneration, tool.LinkTimeCodeGeneration) + << attrS(_LinkToManagedResourceFile, tool.LinkToManagedResourceFile) + << attrT(_MapExports, tool.MapExports) + << attrS(_MapFileName, tool.MapFileName) + << attrT(_MapLines, tool.MapLines) + << attrS(_MergedIDLBaseFileName, tool.MergedIDLBaseFileName) + << attrS(_MergeSections, tool.MergeSections) + << attrS(_MidlCommandFile, tool.MidlCommandFile) + << attrS(_ModuleDefinitionFile, tool.ModuleDefinitionFile) + << attrE(_OptimizeForWindows98, tool.OptimizeForWindows98, /*ifNot*/ optWin98Default) + << attrE(_OptimizeReferences, tool.OptimizeReferences, /*ifNot*/ optReferencesDefault) + << attrS(_OutputFile, tool.OutputFile) + << attr(_ProgramDatabaseFile, tool.ProgramDatabaseFile) + << attrT(_RegisterOutput, tool.RegisterOutput) + << attrT(_ResourceOnlyDLL, tool.ResourceOnlyDLL) + << attrT(_SetChecksum, tool.SetChecksum) + << attrE(_ShowProgress, tool.ShowProgress, /*ifNot*/ linkProgressNotSet) + << attrL(_StackCommitSize, tool.StackCommitSize, /*ifNot*/ -1) + << attrL(_StackReserveSize, tool.StackReserveSize, /*ifNot*/ -1) + << attrS(_StripPrivateSymbols, tool.StripPrivateSymbols) + << attrE(_SubSystem, tool.SubSystem) + << attrT(_SupportUnloadOfDelayLoadedDLL, tool.SupportUnloadOfDelayLoadedDLL) + << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner) + << attrT(_SwapRunFromCD, tool.SwapRunFromCD) + << attrT(_SwapRunFromNet, tool.SwapRunFromNet) + << attrE(_TargetMachine, tool.TargetMachine, /*ifNot*/ machineNotSet) + << attrE(_TerminalServerAware, tool.TerminalServerAware, /*ifNot*/ termSvrAwareDefault) + << attrT(_TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration) + << attrS(_TypeLibraryFile, tool.TypeLibraryFile) + << attrL(_TypeLibraryResourceID, tool.TypeLibraryResourceID, /*ifNot*/ rcUseDefault) + << attrS(_Version, tool.Version) + << closetag(_Tool); +} + +void VCProjectWriter::write(XmlOutput &xml, const VCMIDLTool &tool) +{ + xml << tag(_Tool) + << attrS(_Name, _VCMIDLTool) + << attrX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories) + << attrX(_AdditionalOptions, tool.AdditionalOptions, " ") + << attrX(_CPreprocessOptions, tool.CPreprocessOptions) + << attrE(_DefaultCharType, tool.DefaultCharType) + << attrS(_DLLDataFileName, tool.DLLDataFileName) + << attrE(_EnableErrorChecks, tool.EnableErrorChecks) + << attrT(_ErrorCheckAllocations, tool.ErrorCheckAllocations) + << attrT(_ErrorCheckBounds, tool.ErrorCheckBounds) + << attrT(_ErrorCheckEnumRange, tool.ErrorCheckEnumRange) + << attrT(_ErrorCheckRefPointers, tool.ErrorCheckRefPointers) + << attrT(_ErrorCheckStubData, tool.ErrorCheckStubData) + << attrX(_FullIncludePath, tool.FullIncludePath) + << attrT(_GenerateStublessProxies, tool.GenerateStublessProxies) + << attrT(_GenerateTypeLibrary, tool.GenerateTypeLibrary) + << attrS(_HeaderFileName, tool.HeaderFileName) + << attrT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) + << attrS(_InterfaceIdentifierFileName, tool.InterfaceIdentifierFileName) + << attrT(_MkTypLibCompatible, tool.MkTypLibCompatible) + << attrS(_OutputDirectory, tool.OutputDirectory) + << attrX(_PreprocessorDefinitions, tool.PreprocessorDefinitions) + << attrS(_ProxyFileName, tool.ProxyFileName) + << attrS(_RedirectOutputAndErrors, tool.RedirectOutputAndErrors) + << attrE(_StructMemberAlignment, tool.StructMemberAlignment, /*ifNot*/ midlAlignNotSet) + << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner) + << attrE(_TargetEnvironment, tool.TargetEnvironment, /*ifNot*/ midlTargetNotSet) + << attrS(_TypeLibraryName, tool.TypeLibraryName) + << attrX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions) + << attrT(_ValidateParameters, tool.ValidateParameters) + << attrT(_WarnAsError, tool.WarnAsError) + << attrE(_WarningLevel, tool.WarningLevel) + << closetag(_Tool); +} + +void VCProjectWriter::write(XmlOutput &xml, const VCCustomBuildTool &tool) +{ + // The code below offers two ways to split custom build step commands. + // Normally the $$escape_expand(\n\t) is used in a project file, which is correctly translated + // in all generators. However, if you use $$escape_expand(\n\r) (or \n\h) instead, the VCPROJ + // generator will instead of binding the commands with " && " will insert a proper newline into + // the VCPROJ file. We sometimes use this method of splitting commands if the custom buildstep + // contains a command-line which is too big to run on certain OS. + QString cmds; + int end = tool.CommandLine.count(); + for(int i = 0; i < end; ++i) { + QString cmdl = tool.CommandLine.at(i); + if (cmdl.contains("\r\t")) { + if (i == end - 1) + cmdl = cmdl.trimmed(); + cmdl.replace("\r\t", " && "); + } else if (cmdl.contains("\r\n")) { + ; + } else if (cmdl.contains("\r\\h")) { + // The above \r\n should work, but doesn't, so we have this hack + cmdl.replace("\r\\h", "\r\n"); } else { - // ExtraCompilers - filter = SingleProjects[i].filterForExtraCompiler(filtername); + if (i < end - 1) + cmdl += " && "; } + cmds += cmdl; + } + xml << tag(_Tool) + << attrS(_Name, tool.ToolName) + << attrX(_AdditionalDependencies, tool.AdditionalDependencies, ";") + << attrS(_CommandLine, cmds) + << attrS(_Description, tool.Description) + << attrX(_Outputs, tool.Outputs, ";") + << attrS(_Path, tool.ToolPath) + << closetag(_Tool); +} - if (filter.Config) // only if the filter is not empty - filter.outputFileConfig(xml, info.file); +void VCProjectWriter::write(XmlOutput &xml, const VCLibrarianTool &tool) +{ + xml + << tag(_Tool) + << attrS(_Name, _VCLibrarianTool) + << attrX(_AdditionalDependencies, tool.AdditionalDependencies) + << attrX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories) + << attrX(_AdditionalOptions, tool.AdditionalOptions, " ") + << attrX(_ExportNamedFunctions, tool.ExportNamedFunctions) + << attrX(_ForceSymbolReferences, tool.ForceSymbolReferences) + << attrT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries) + << attrX(_IgnoreDefaultLibraryNames, tool.IgnoreDefaultLibraryNames) + << attrS(_ModuleDefinitionFile, tool.ModuleDefinitionFile) + << attrS(_OutputFile, tool.OutputFile) + << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner) + << closetag(_Tool); +} + +void VCProjectWriter::write(XmlOutput &xml, const VCResourceCompilerTool &tool) +{ + xml + << tag(_Tool) + << attrS(_Name, _VCResourceCompilerTool) + << attrS(_Path, tool.ToolPath) + << attrX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories) + << attrX(_AdditionalOptions, tool.AdditionalOptions, " ") + << attrE(_Culture, tool.Culture, /*ifNot*/ rcUseDefault) + << attrX(_FullIncludePath, tool.FullIncludePath) + << attrT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) + << attrX(_PreprocessorDefinitions, tool.PreprocessorDefinitions) + << attrS(_ResourceOutputFileName, tool.ResourceOutputFileName) + << attrE(_ShowProgress, tool.ShowProgress, /*ifNot*/ linkProgressNotSet) + << closetag(_Tool); +} + +void VCProjectWriter::write(XmlOutput &xml, const VCEventTool &tool) +{ + xml + << tag(_Tool) + << attrS(_Name, tool.ToolName) + << attrS(_Path, tool.ToolPath) + << attrS(_CommandLine, tool.CommandLine) + << attrS(_Description, tool.Description) + << attrT(_ExcludedFromBuild, tool.ExcludedFromBuild) + << closetag(_Tool); +} + +void VCProjectWriter::write(XmlOutput &xml, const VCDeploymentTool &tool) +{ + if (tool.AdditionalFiles.isEmpty()) + return; + xml << tag(tool.DeploymentTag) + << attrS(_RemoteDirectory, tool.RemoteDirectory) + << attrE(_RegisterOutput, tool.RegisterOutput) + << attrS(_AdditionalFiles, tool.AdditionalFiles) + << closetag(tool.DeploymentTag); +} + +void VCProjectWriter::write(XmlOutput &xml, const VCConfiguration &tool) +{ + xml << tag(_Configuration) + << attrS(_Name, tool.Name) + << attrS(_OutputDirectory, tool.OutputDirectory) + << attrT(_ATLMinimizesCRunTimeLibraryUsage, tool.ATLMinimizesCRunTimeLibraryUsage) + << attrT(_BuildBrowserInformation, tool.BuildBrowserInformation) + << attrE(_CharacterSet, tool.CharacterSet, /*ifNot*/ charSetNotSet) + << attrE(_ConfigurationType, tool.ConfigurationType) + << attrS(_DeleteExtensionsOnClean, tool.DeleteExtensionsOnClean) + << attrS(_ImportLibrary, tool.ImportLibrary) + << attrS(_IntermediateDirectory, tool.IntermediateDirectory) + << attrS(_PrimaryOutput, tool.PrimaryOutput) + << attrS(_ProgramDatabase, tool.ProgramDatabase) + << attrT(_RegisterOutput, tool.RegisterOutput) + << attrE(_UseOfATL, tool.UseOfATL, /*ifNot*/ useATLNotSet) + << attrE(_UseOfMfc, tool.UseOfMfc) + << attrT(_WholeProgramOptimization, tool.WholeProgramOptimization); + write(xml, tool.compiler); + write(xml, tool.custom); + if (tool.ConfigurationType == typeStaticLibrary) + write(xml, tool.librarian); + else + write(xml, tool.linker); + write(xml, tool.idl); + write(xml, tool.postBuild); + write(xml, tool.preBuild); + write(xml, tool.preLink); + write(xml, tool.resource); + write(xml, tool.deployment); + xml << closetag(_Configuration); +} + +void VCProjectWriter::write(XmlOutput &xml, VCFilter &tool) +{ + if(!tool.Files.count()) + return; + + if (!tool.Name.isEmpty()) { + xml << tag(_Filter) + << attrS(_Name, tool.Name) + << attrS(_Filter, tool.Filter) + << attrS(_UniqueIdentifier, tool.Guid) + << attrT(_ParseFiles, tool.ParseFiles); } - xml << closetag(q_File); + for (int i = 0; i < tool.Files.count(); ++i) { + const VCFilterFile &info = tool.Files.at(i); + xml << tag(q_File) + << attrS(_RelativePath, Option::fixPathToLocalOS(info.file)) + << data(); // In case no custom builds, to avoid "/>" endings + outputFileConfig(tool, xml, tool.Files.at(i).file); + xml << closetag(q_File); + } + if (!tool.Name.isEmpty()) + xml << closetag(_Filter); } // outputs a given filter for all existing configurations of a project -void VCProject::outputFilter(XmlOutput &xml, -// VCProjectSingleConfig::FilterTypes type - const QString &filtername) +void VCProjectWriter::outputFilter(VCProject &project, XmlOutput &xml, const QString &filtername) { Node *root; - if (SingleProjects.at(0).flat_files) + if (project.SingleProjects.at(0).flat_files) root = new FlatNode; else root = new TreeNode; @@ -2547,27 +2767,28 @@ void VCProject::outputFilter(XmlOutput &xml, QString name, extfilter, guid; triState parse; - for (int i = 0; i < SingleProjects.count(); ++i) { + for (int i = 0; i < project.SingleProjects.count(); ++i) { VCFilter filter; + const VCProjectSingleConfig &projectSingleConfig = project.SingleProjects.at(i); if (filtername == "RootFiles") { - filter = SingleProjects.at(i).RootFiles; + filter = projectSingleConfig.RootFiles; } else if (filtername == "Sources") { - filter = SingleProjects.at(i).SourceFiles; + filter = projectSingleConfig.SourceFiles; } else if (filtername == "Headers") { - filter = SingleProjects.at(i).HeaderFiles; + filter = projectSingleConfig.HeaderFiles; } else if (filtername == "GeneratedFiles") { - filter = SingleProjects.at(i).GeneratedFiles; + filter = projectSingleConfig.GeneratedFiles; } else if (filtername == "LexYaccFiles") { - filter = SingleProjects.at(i).LexYaccFiles; + filter = projectSingleConfig.LexYaccFiles; } else if (filtername == "TranslationFiles") { - filter = SingleProjects.at(i).TranslationFiles; + filter = projectSingleConfig.TranslationFiles; } else if (filtername == "FormFiles") { - filter = SingleProjects.at(i).FormFiles; + filter = projectSingleConfig.FormFiles; } else if (filtername == "ResourceFiles") { - filter = SingleProjects.at(i).ResourceFiles; + filter = projectSingleConfig.ResourceFiles; } else { // ExtraCompilers - filter = SingleProjects[i].filterForExtraCompiler(filtername); + filter = project.SingleProjects[i].filterForExtraCompiler(filtername); } // Merge all files in this filter to root tree @@ -2595,52 +2816,98 @@ void VCProject::outputFilter(XmlOutput &xml, << attrS(_UniqueIdentifier, guid) << attrT(_ParseFiles, parse); } - root->generateXML(xml, "", *this, filtername); // output root tree + root->generateXML(xml, "", project, filtername); // output root tree if (!name.isEmpty()) xml << closetag(_Filter); } -XmlOutput &operator<<(XmlOutput &xml, VCProject &tool) +// Output all configurations (by filtername) for a file (by info) +// A filters config output is in VCFilter.outputFileConfig() +void VCProjectWriter::outputFileConfigs(VCProject &project, XmlOutput &xml, const VCFilterFile &info, const QString &filtername) { - if (tool.SingleProjects.count() == 0) { - warn_msg(WarnLogic, "Generator: .NET: no single project in merge project, no output"); - return xml; + xml << tag(q_File) + << attrS(_RelativePath, Option::fixPathToLocalOS(info.file)); + for (int i = 0; i < project.SingleProjects.count(); ++i) { + VCFilter filter; + const VCProjectSingleConfig &projectSingleConfig = project.SingleProjects.at(i); + if (filtername == "RootFiles") { + filter = projectSingleConfig.RootFiles; + } else if (filtername == "Sources") { + filter = projectSingleConfig.SourceFiles; + } else if (filtername == "Headers") { + filter = projectSingleConfig.HeaderFiles; + } else if (filtername == "GeneratedFiles") { + filter = projectSingleConfig.GeneratedFiles; + } else if (filtername == "LexYaccFiles") { + filter = projectSingleConfig.LexYaccFiles; + } else if (filtername == "TranslationFiles") { + filter = projectSingleConfig.TranslationFiles; + } else if (filtername == "FormFiles") { + filter = projectSingleConfig.FormFiles; + } else if (filtername == "ResourceFiles") { + filter = projectSingleConfig.ResourceFiles; + } else { + // ExtraCompilers + filter = project.SingleProjects[i].filterForExtraCompiler(filtername); + } + + if (filter.Config) // only if the filter is not empty + outputFileConfig(filter, xml, info.file); } + xml << closetag(q_File); +} - xml << decl("1.0", "Windows-1252") - << tag(_VisualStudioProject) - << attrS(_ProjectType, "Visual C++") - << attrS(_Version, tool.Version) - << attrS(_Name, tool.Name) - << attrS(_ProjectGUID, tool.ProjectGUID) - << attrS(_Keyword, tool.Keyword) - << attrS(_SccProjectName, tool.SccProjectName) - << attrS(_SccLocalPath, tool.SccLocalPath) - << tag(_Platforms) - << tag(_Platform) - << attrS(_Name, tool.PlatformName) - << closetag(_Platforms) - << tag(_Configurations); - // Output each configuration - for (int i = 0; i < tool.SingleProjects.count(); ++i) - xml << tool.SingleProjects.at(i).Configuration; - xml << closetag(_Configurations) - << tag(q_Files); - tool.outputFilter(xml, "Sources"); - tool.outputFilter(xml, "Headers"); - tool.outputFilter(xml, "GeneratedFiles"); - tool.outputFilter(xml, "LexYaccFiles"); - tool.outputFilter(xml, "TranslationFiles"); - tool.outputFilter(xml, "FormFiles"); - tool.outputFilter(xml, "ResourceFiles"); - for (int x = 0; x < tool.ExtraCompilers.count(); ++x) { - tool.outputFilter(xml, tool.ExtraCompilers.at(x)); +void VCProjectWriter::outputFileConfig(VCFilter &filter, XmlOutput &xml, const QString &filename) +{ + // Clearing each filter tool + filter.useCustomBuildTool = false; + filter.useCompilerTool = false; + filter.CustomBuildTool = VCCustomBuildTool(); + filter.CompilerTool = VCCLCompilerTool(); + + // Unset some default options + filter.CustomBuildTool.config = filter.Config; + filter.CompilerTool.BufferSecurityCheck = unset; + filter.CompilerTool.DebugInformationFormat = debugUnknown; + filter.CompilerTool.ExceptionHandling = ehDefault; + filter.CompilerTool.GeneratePreprocessedFile = preprocessUnknown; + filter.CompilerTool.Optimization = optimizeDefault; + filter.CompilerTool.ProgramDataBaseFileName.clear(); + filter.CompilerTool.RuntimeLibrary = rtUnknown; + filter.CompilerTool.WarningLevel = warningLevelUnknown; + filter.CompilerTool.config = filter.Config; + + bool inBuild = false; + VCFilterFile info; + for (int i = 0; i < filter.Files.count(); ++i) { + if (filter.Files.at(i).file == filename) { + info = filter.Files.at(i); + inBuild = true; + } + } + inBuild &= !info.excludeFromBuild; + + if (inBuild) { + filter.addExtraCompiler(info); + if(filter.Project->usePCH) + filter.modifyPCHstage(info.file); + } else { + // Excluded files uses an empty compiler stage + if(info.excludeFromBuild) + filter.useCompilerTool = true; + } + + // Actual XML output ---------------------------------- + if (filter.useCustomBuildTool || filter.useCompilerTool || !inBuild) { + xml << tag(_FileConfiguration) + << attr(_Name, filter.Config->Name) + << (!inBuild ? attrS(_ExcludedFromBuild, "true") : noxml()); + if (filter.useCustomBuildTool) + filter.Project->projectWriter->write(xml, filter.CustomBuildTool); + if (filter.useCompilerTool) + filter.Project->projectWriter->write(xml, filter.CompilerTool); + xml << closetag(_FileConfiguration); } - tool.outputFilter(xml, "RootFiles"); - xml << closetag(q_Files) - << tag(_Globals) - << data(); // No "/>" end tag - return xml; } QT_END_NAMESPACE diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h index 97f8570..c70e897 100644 --- a/qmake/generators/win32/msvc_objectmodel.h +++ b/qmake/generators/win32/msvc_objectmodel.h @@ -86,6 +86,9 @@ enum triState { _False = 0, _True = 1 }; + +triState operator!(const triState &rhs); + enum addressAwarenessType { addrAwareDefault, addrAwareNoLarge, @@ -467,7 +470,7 @@ enum warningLevelOption { class VCToolBase { protected: // Functions - VCToolBase(){}; + VCToolBase(){} virtual ~VCToolBase(){} virtual bool parseOption(const char* option) = 0; public: @@ -520,6 +523,7 @@ public: QStringList ForcedIncludeFiles; QStringList ForcedUsingFiles; preprocessOption GeneratePreprocessedFile; + triState PreprocessSuppressLineNumbers; triState GlobalOptimizations; triState IgnoreStandardIncludePath; triState ImproveFloatingPointConsistency; @@ -527,6 +531,7 @@ public: triState KeepComments; triState MinimalRebuild; QString ObjectFile; + triState OmitDefaultLibName; triState OmitFramePointers; triState OpenMP; optimizeOption Optimization; @@ -549,11 +554,24 @@ public: triState UndefineAllPreprocessorDefinitions; QStringList UndefinePreprocessorDefinitions; pchOption UsePrecompiledHeader; + triState UseUnicodeForAssemblerListing; triState WarnAsError; warningLevelOption WarningLevel; triState WholeProgramOptimization; useOfArchitecture CompileForArchitecture; triState InterworkCalls; + + // VS2010 + triState EnablePREfast; + triState DisplayFullPaths; + triState MultiProcessorCompilation; + QString MultiProcessorCompilationProcessorCount; + triState GenerateXMLDocumentationFiles; + QString XMLDocumentationFileName; + QString ErrorReporting; + triState CreateHotpatchableImage; + QString PreprocessOutputPath; + VCConfiguration* config; }; @@ -571,6 +589,7 @@ public: QStringList AdditionalOptions; QStringList AddModuleNamesToAssembly; QString BaseAddress; + triState DataExecutionPrevention; QStringList DelayLoadDLLs; optFoldingType EnableCOMDATFolding; QString EntryPointSymbol; @@ -601,6 +620,7 @@ public: optRefType OptimizeReferences; QString OutputFile; QString ProgramDatabaseFile; + triState RandomizedBaseAddress; triState RegisterOutput; triState ResourceOnlyDLL; triState SetChecksum; @@ -615,10 +635,33 @@ public: triState SwapRunFromNet; machineTypeOption TargetMachine; termSvrAwarenessType TerminalServerAware; + triState TreatWarningsAsErrors; triState TurnOffAssemblyGeneration; QString TypeLibraryFile; qlonglong TypeLibraryResourceID; QString Version; + + // VS2010 + triState GenerateManifest; + QStringList AdditionalManifestDependencies; + QString ManifestFile; + triState EnableUAC; + QString UACExecutionLevel; + triState UACUIAccess; + qlonglong SectionAlignment; + triState PreventDllBinding; + triState AllowIsolation; + triState AssemblyDebug; + QStringList AssemblyLinkResource; + QString CLRImageType; + QString CLRSupportLastError; + QString CLRThreadAttribute; + triState CLRUnmanagedCodeCheck; + triState DelaySign; + QString KeyContainer; + QString KeyFile; + QString LinkErrorReporting; + VCConfiguration* config; }; @@ -661,6 +704,18 @@ public: triState ValidateParameters; triState WarnAsError; midlWarningLevelOption WarningLevel; + + // VS 2010 + triState ApplicationConfigurationMode; + QString GenerateClientFiles; + QString ClientStubFile; + QString TypeLibFormat; + triState ValidateAllParameters; + triState SuppressCompilerWarnings; + QString GenerateServerFiles; + QString ServerStubFile; + qlonglong LocaleID; + VCConfiguration* config; }; @@ -670,7 +725,7 @@ public: // Functions VCLibrarianTool(); virtual ~VCLibrarianTool(){} - bool parseOption(const char*){ return false; }; + bool parseOption(const char*){ return false; } // Variables QStringList AdditionalDependencies; @@ -691,7 +746,7 @@ public: // Functions VCCustomBuildTool(); virtual ~VCCustomBuildTool(){} - bool parseOption(const char*){ return false; }; + bool parseOption(const char*){ return false; } // Variables QStringList AdditionalDependencies; @@ -700,6 +755,8 @@ public: QStringList Outputs; QString ToolName; QString ToolPath; + + VCConfiguration* config; }; class VCResourceCompilerTool : public VCToolBase @@ -708,7 +765,7 @@ public: // Functions VCResourceCompilerTool(); virtual ~VCResourceCompilerTool(){} - bool parseOption(const char*){ return false; }; + bool parseOption(const char*){ return false; } // Variables QStringList AdditionalIncludeDirectories; @@ -720,6 +777,7 @@ public: QString ResourceOutputFileName; linkProgressOption ShowProgress; QString ToolPath; + triState SuppressStartupBanner; }; class VCDeploymentTool @@ -740,15 +798,16 @@ class VCEventTool : public VCToolBase { protected: // Functions - VCEventTool() : ExcludedFromBuild(unset){}; + VCEventTool(const QString &eventName); virtual ~VCEventTool(){} - bool parseOption(const char*){ return false; }; + bool parseOption(const char*){ return false; } public: // Variables QString CommandLine; QString Description; triState ExcludedFromBuild; + QString EventName; QString ToolName; QString ToolPath; }; @@ -791,7 +850,8 @@ public: QString DeleteExtensionsOnClean; QString ImportLibrary; QString IntermediateDirectory; - QString Name; + QString Name; // "ConfigurationName|PlatformName" + QString ConfigurationName; QString OutputDirectory; QString PrimaryOutput; QString ProgramDatabase; @@ -848,14 +908,13 @@ class VCFilter public: // Functions VCFilter(); - ~VCFilter(){}; + ~VCFilter(){} void addFile(const QString& filename); void addFile(const VCFilterFile& fileInfo); void addFiles(const QStringList& fileList); bool addExtraCompiler(const VCFilterFile &info); void modifyPCHstage(QString str); - void outputFileConfig(XmlOutput &xml, const QString &filename); // Variables QString Name; @@ -873,9 +932,6 @@ public: bool useCompilerTool; VCCLCompilerTool CompilerTool; - -private: - friend XmlOutput &operator<<(XmlOutput &xml, VCFilter &tool); }; typedef QList<VCFilter> VCFilterList; @@ -893,7 +949,7 @@ public: Extras }; // Functions - VCProjectSingleConfig(){}; + VCProjectSingleConfig(){} ~VCProjectSingleConfig(){} // Variables @@ -923,8 +979,6 @@ public: VCFilter &filterForExtraCompiler(const QString &compilerName); }; - - // Tree & Flat view of files -------------------------------------------------- class VCFilter; class Node @@ -1050,30 +1104,35 @@ public: // List of all extracompilers QStringList ExtraCompilers; +}; - // Functions - void outputFilter(XmlOutput &xml, -// VCProjectSingleConfig::FilterTypes type, - const QString &filtername); - - void outputFileConfigs(XmlOutput &xml, -// VCProjectSingleConfig::FilterTypes type, - const VCFilterFile &info, - const QString &filtername); -}; - -XmlOutput &operator<<(XmlOutput &, const VCCLCompilerTool &); -XmlOutput &operator<<(XmlOutput &, const VCLinkerTool &); -XmlOutput &operator<<(XmlOutput &, const VCMIDLTool &); -XmlOutput &operator<<(XmlOutput &, const VCCustomBuildTool &); -XmlOutput &operator<<(XmlOutput &, const VCLibrarianTool &); -XmlOutput &operator<<(XmlOutput &, const VCResourceCompilerTool &); -XmlOutput &operator<<(XmlOutput &, const VCEventTool &); -XmlOutput &operator<<(XmlOutput &, const VCDeploymentTool &); -XmlOutput &operator<<(XmlOutput &, const VCConfiguration &); -XmlOutput &operator<<(XmlOutput &, VCFilter &); -XmlOutput &operator<<(XmlOutput &, const VCProjectSingleConfig &); -XmlOutput &operator<<(XmlOutput &, VCProject &); +class VCProjectWriter +{ +public: + virtual ~VCProjectWriter() {} + + virtual void write(XmlOutput &, VCProjectSingleConfig &); + virtual void write(XmlOutput &, VCProject &); + + virtual void write(XmlOutput &, const VCCLCompilerTool &); + virtual void write(XmlOutput &, const VCLinkerTool &); + virtual void write(XmlOutput &, const VCMIDLTool &); + virtual void write(XmlOutput &, const VCCustomBuildTool &); + virtual void write(XmlOutput &, const VCLibrarianTool &); + virtual void write(XmlOutput &, const VCResourceCompilerTool &); + virtual void write(XmlOutput &, const VCEventTool &); + virtual void write(XmlOutput &, const VCDeploymentTool &); + virtual void write(XmlOutput &, const VCConfiguration &); + virtual void write(XmlOutput &, VCFilter &); + +private: + static void outputFilter(VCProject &project, XmlOutput &xml, const QString &filtername); + static void outputFileConfigs(VCProject &project, XmlOutput &xml, const VCFilterFile &info, const QString &filtername); + static void outputFileConfig(VCFilter &filter, XmlOutput &xml, const QString &filename); + + friend class TreeNode; + friend class FlatNode; +}; QT_END_NAMESPACE diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index 8686ae8..f32ba7e 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -51,7 +51,6 @@ #include <stdlib.h> //#define DEBUG_SOLUTION_GEN -//#define DEBUG_PROJECT_GEN QT_BEGIN_NAMESPACE // Filter GUIDs (Do NOT change these!) ------------------------------ @@ -206,9 +205,18 @@ const char _slnExtSections[] = "\n\tGlobalSection(ExtensibilityGlobals) = pos "\n\tEndGlobalSection"; // ------------------------------------------------------------------ -VcprojGenerator::VcprojGenerator() : Win32MakefileGenerator(), init_flag(false) +VcprojGenerator::VcprojGenerator() + : Win32MakefileGenerator(), + init_flag(false), + projectWriter(0) { } + +VcprojGenerator::~VcprojGenerator() +{ + delete projectWriter; +} + bool VcprojGenerator::writeMakefile(QTextStream &t) { initProject(); // Fills the whole project with proper data @@ -229,7 +237,7 @@ bool VcprojGenerator::writeMakefile(QTextStream &t) if(!project->isActiveConfig("build_pass")) { debug_msg(1, "Generator: MSVC.NET: Writing single configuration project file"); XmlOutput xmlOut(t); - xmlOut << vcProject; + projectWriter->write(xmlOut, vcProject); } return true; } @@ -281,7 +289,7 @@ bool VcprojGenerator::writeProjectMakefile() mergedProject.PlatformName = mergedProjects.at(0)->vcProject.PlatformName; XmlOutput xmlOut(t); - xmlOut << mergedProject; + projectWriter->write(xmlOut, mergedProject); return true; } else if(project->first("TEMPLATE") == "vcsubdirs") { return writeMakefile(t); @@ -649,12 +657,13 @@ bool VcprojGenerator::hasBuiltinCompiler(const QString &file) void VcprojGenerator::init() { - if(init_flag) + if (init_flag) return; - if(project->first("TEMPLATE") == "vcsubdirs") { //too much work for subdirs - init_flag = true; + init_flag = true; + projectWriter = createProjectWriter(); + + if(project->first("TEMPLATE") == "vcsubdirs") //too much work for subdirs return; - } debug_msg(1, "Generator: MSVC.NET: Initializing variables"); @@ -667,6 +676,20 @@ void VcprojGenerator::init() project->values("QMAKESPEC").append(qgetenv("QMAKESPEC")); processVars(); + + project->values("QMAKE_LIBS") += escapeFilePaths(project->values("LIBS")); + project->values("QMAKE_LIBS_PRIVATE") += escapeFilePaths(project->values("LIBS_PRIVATE")); + + if(!project->values("VERSION").isEmpty()) { + QString version = project->values("VERSION")[0]; + int firstDot = version.indexOf("."); + QString major = version.left(firstDot); + QString minor = version.right(version.length() - firstDot - 1); + minor.replace(QRegExp("\\."), ""); + project->values("QMAKE_LFLAGS").append("/VERSION:" + major + "." + minor); + } + + MakefileGenerator::init(); initOld(); // Currently calling old DSP code to set variables. CLEAN UP! // Figure out what we're trying to build @@ -749,11 +772,16 @@ void VcprojGenerator::init() bool VcprojGenerator::mergeBuildProject(MakefileGenerator *other) { - VcprojGenerator *otherVC = static_cast<VcprojGenerator*>(other); - if (!otherVC) { + if (!other || !other->projectFile()) { + warn_msg(WarnLogic, "VcprojGenerator: Cannot merge null project."); + return false; + } + if (other->projectFile()->first("MAKEFILE_GENERATOR") != project->first("MAKEFILE_GENERATOR")) { warn_msg(WarnLogic, "VcprojGenerator: Cannot merge other types of projects! (ignored)"); return false; } + + VcprojGenerator *otherVC = static_cast<VcprojGenerator*>(other); mergedProjects += otherVC; return true; } @@ -777,6 +805,9 @@ void VcprojGenerator::initProject() // Own elements ----------------------------- vcProject.Name = unescapeFilePath(project->first("QMAKE_ORIG_TARGET")); switch(which_dotnet_version()) { + case NET2010: + vcProject.Version = "10.00"; + break; case NET2008: vcProject.Version = "9,00"; break; @@ -846,9 +877,28 @@ void VcprojGenerator::initConfiguration() break; } + if (conf.CompilerVersion >= NET2010) { + conf.OutputDirectory = project->first("DESTDIR"); + + if(conf.OutputDirectory.isEmpty()) + conf.OutputDirectory = ".\\"; + + if(!conf.OutputDirectory.endsWith("\\")) + conf.OutputDirectory += '\\'; + + // The target name could have been changed. + conf.PrimaryOutput = project->first("TARGET"); + if ( !conf.PrimaryOutput.isEmpty() && !project->first("TARGET_VERSION_EXT").isEmpty() && project->isActiveConfig("shared")) + conf.PrimaryOutput.append(project->first("TARGET_VERSION_EXT")); + } else { + conf.PrimaryOutput = project->first("PrimaryOutput"); + conf.OutputDirectory = "."; + } + conf.Name = project->values("BUILD_NAME").join(" "); if (conf.Name.isEmpty()) conf.Name = isDebug ? "Debug" : "Release"; + conf.ConfigurationName = conf.Name; if (project->isEmpty("CE_SDK") || project->isEmpty("CE_ARCH")) { conf.Name += (conf.idl.TargetEnvironment == midlTargetWin64 ? "|Win64" : "|Win32"); } else { @@ -861,8 +911,6 @@ void VcprojGenerator::initConfiguration() conf.DeleteExtensionsOnClean = project->first("DeleteExtensionsOnClean"); conf.ImportLibrary = conf.linker.ImportLibrary; conf.IntermediateDirectory = project->first("OBJECTS_DIR"); - conf.OutputDirectory = "."; - conf.PrimaryOutput = project->first("PrimaryOutput"); conf.WholeProgramOptimization = conf.compiler.WholeProgramOptimization; temp = project->first("UseOfATL"); if(!temp.isEmpty()) @@ -887,7 +935,6 @@ void VcprojGenerator::initConfiguration() } else { conf.compiler.PreprocessorDefinitions += "NDEBUG"; } - } void VcprojGenerator::initCompilerTool() @@ -907,39 +954,24 @@ void VcprojGenerator::initCompilerTool() conf.compiler.PrecompiledHeaderFile = "$(IntDir)\\" + precompPch; conf.compiler.PrecompiledHeaderThrough = project->first("PRECOMPILED_HEADER"); conf.compiler.ForcedIncludeFiles = project->values("PRECOMPILED_HEADER"); - // Minimal build option triggers an Internal Compiler Error - // when used in conjunction with /FI and /Yu, so remove it - project->values("QMAKE_CFLAGS_DEBUG").removeAll("-Gm"); - project->values("QMAKE_CFLAGS_DEBUG").removeAll("/Gm"); - project->values("QMAKE_CXXFLAGS_DEBUG").removeAll("-Gm"); - project->values("QMAKE_CXXFLAGS_DEBUG").removeAll("/Gm"); - } - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS")); - if(project->isActiveConfig("debug")){ - // Debug version - if((projectTarget == Application) || (projectTarget == StaticLib)) - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DBG")); - else - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DLLDBG")); - } else { - // Release version - conf.compiler.PreprocessorDefinitions += "QT_NO_DEBUG"; - conf.compiler.PreprocessorDefinitions += "NDEBUG"; - if((projectTarget == Application) || (projectTarget == StaticLib)) - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT")); - else - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DLL")); + if (conf.CompilerVersion <= NET2003) { + // Minimal build option triggers an Internal Compiler Error + // when used in conjunction with /FI and /Yu, so remove it + // ### work-around for a VS 2003 bug. Move to some prf file or remove completely. + project->values("QMAKE_CFLAGS_DEBUG").removeAll("-Gm"); + project->values("QMAKE_CFLAGS_DEBUG").removeAll("/Gm"); + project->values("QMAKE_CXXFLAGS_DEBUG").removeAll("-Gm"); + project->values("QMAKE_CXXFLAGS_DEBUG").removeAll("/Gm"); + } } - // Common for both release and debug - if(project->isActiveConfig("windows")) - conf.compiler.PreprocessorDefinitions += project->values("MSVCPROJ_WINCONDEF"); + conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS")); - // Can this be set for ALL configs? - // If so, use qmake.conf! - if(projectTarget == SharedLib) + if (project->isActiveConfig("windows")) conf.compiler.PreprocessorDefinitions += "_WINDOWS"; + else if (project->isActiveConfig("console")) + conf.compiler.PreprocessorDefinitions += "_CONSOLE"; conf.compiler.PreprocessorDefinitions += project->values("DEFINES"); conf.compiler.PreprocessorDefinitions += project->values("PRL_EXPORT_DEFINES"); @@ -964,7 +996,17 @@ void VcprojGenerator::initLinkerTool() { findLibraries(); // Need to add the highest version of the libs VCConfiguration &conf = vcProject.Configuration; - conf.linker.parseOptions(project->values("MSVCPROJ_LFLAGS")); + conf.linker.parseOptions(project->values("QMAKE_LFLAGS")); + + foreach (const QString &libDir, project->values("QMAKE_LIBDIR")) { + if (libDir.startsWith("/LIBPATH:")) + conf.linker.AdditionalLibraryDirectories += libDir.mid(9); + else + conf.linker.AdditionalLibraryDirectories += libDir; + } + + if (!project->values("DEF_FILE").isEmpty()) + conf.linker.ModuleDefinitionFile = project->first("DEF_FILE"); foreach(QString libs, project->values("MSVCPROJ_LIBS")) { if (libs.left(9).toUpper() == "/LIBPATH:") { @@ -1014,7 +1056,6 @@ void VcprojGenerator::initResourceTool() conf.resource.ResourceOutputFileName = project->first("DESTDIR") + "/$(InputName).res"; } - void VcprojGenerator::initIDLTool() { } @@ -1280,7 +1321,6 @@ void VcprojGenerator::initTranslationFiles() vcProject.TranslationFiles.CustomBuild = none; } - void VcprojGenerator::initFormFiles() { vcProject.FormFiles.Name = "Form Files"; @@ -1296,7 +1336,6 @@ void VcprojGenerator::initFormFiles() vcProject.FormFiles.CustomBuild = none; } - void VcprojGenerator::initResourceFiles() { vcProject.ResourceFiles.Name = "Resource Files"; @@ -1424,86 +1463,11 @@ void VcprojGenerator::initExtraCompilerOutputs() } } -/* \internal - Sets up all needed variables from the environment and all the different caches and .conf files -*/ - void VcprojGenerator::initOld() { - if(init_flag) - return; - - init_flag = true; - QStringList::Iterator it; - - // Decode version, and add it to $$MSVCPROJ_VERSION -------------- - if(!project->values("VERSION").isEmpty()) { - QString version = project->values("VERSION")[0]; - int firstDot = version.indexOf("."); - QString major = version.left(firstDot); - QString minor = version.right(version.length() - firstDot - 1); - minor.replace(QRegExp("\\."), ""); - project->values("MSVCPROJ_VERSION").append("/VERSION:" + major + "." + minor); - project->values("QMAKE_LFLAGS").append("/VERSION:" + major + "." + minor); - } - - project->values("QMAKE_LIBS") += escapeFilePaths(project->values("LIBS")); - project->values("QMAKE_LIBS_PRIVATE") += escapeFilePaths(project->values("LIBS_PRIVATE")); - - // Get filename w/o extension ----------------------------------- - QString msvcproj_project = ""; - QString targetfilename = ""; - if(!project->isEmpty("TARGET")) { - project->values("TARGET") = unescapeFilePaths(project->values("TARGET")); - targetfilename = msvcproj_project = project->first("TARGET"); - } - - // Init base class too ------------------------------------------- - MakefileGenerator::init(); - - if(msvcproj_project.isEmpty()) - msvcproj_project = Option::output.fileName(); - - msvcproj_project = msvcproj_project.right(msvcproj_project.length() - msvcproj_project.lastIndexOf("\\") - 1); - msvcproj_project = msvcproj_project.left(msvcproj_project.lastIndexOf(".")); - msvcproj_project.replace(QRegExp("-"), ""); - - project->values("MSVCPROJ_PROJECT").append(msvcproj_project); - QStringList &proj = project->values("MSVCPROJ_PROJECT"); - - for(it = proj.begin(); it != proj.end(); ++it) - (*it).replace(QRegExp("\\.[a-zA-Z0-9_]*$"), ""); - - // SUBSYSTEM ----------------------------------------------------- - if(!project->values("QMAKE_APP_FLAG").isEmpty()) { - project->values("MSVCPROJ_TEMPLATE").append("win32app" + project->first("VCPROJ_EXTENSION")); - if(project->isActiveConfig("console")) { - project->values("MSVCPROJ_CONSOLE").append("CONSOLE"); - project->values("MSVCPROJ_WINCONDEF").append("_CONSOLE"); - project->values("MSVCPROJ_VCPROJTYPE").append("0x0103"); - project->values("MSVCPROJ_SUBSYSTEM").append("CONSOLE"); - } else { - project->values("MSVCPROJ_CONSOLE").clear(); - project->values("MSVCPROJ_WINCONDEF").append("_WINDOWS"); - project->values("MSVCPROJ_VCPROJTYPE").append("0x0101"); - project->values("MSVCPROJ_SUBSYSTEM").append("WINDOWS"); - } - } - // $$QMAKE.. -> $$MSVCPROJ.. ------------------------------------- project->values("MSVCPROJ_LIBS") += project->values("QMAKE_LIBS"); project->values("MSVCPROJ_LIBS") += project->values("QMAKE_LIBS_PRIVATE"); - project->values("MSVCPROJ_LFLAGS") += project->values("QMAKE_LFLAGS"); - if(!project->values("QMAKE_LIBDIR").isEmpty()) { - QStringList strl = project->values("QMAKE_LIBDIR"); - QStringList::iterator stri; - for(stri = strl.begin(); stri != strl.end(); ++stri) { - if(!(*stri).startsWith("/LIBPATH:")) - (*stri).prepend("/LIBPATH:"); - } - project->values("MSVCPROJ_LFLAGS") += strl; - } - project->values("MSVCPROJ_CXXFLAGS") += project->values("QMAKE_CXXFLAGS"); QStringList &incs = project->values("INCLUDEPATH"); for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) { QString inc = (*incit); @@ -1542,9 +1506,6 @@ void VcprojGenerator::initOld() project->values("MSVCPROJ_COPY_DLL_DESC").append(deststr); } - if (!project->values("DEF_FILE").isEmpty()) - project->values("MSVCPROJ_LFLAGS").append("/DEF:"+project->first("DEF_FILE")); - project->values("QMAKE_INTERNAL_PRL_LIBS") << "MSVCPROJ_LIBS"; // Verbose output if "-d -d"... @@ -1554,6 +1515,11 @@ void VcprojGenerator::initOld() // ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------ +VCProjectWriter *VcprojGenerator::createProjectWriter() +{ + return new VCProjectWriter; +} + QString VcprojGenerator::replaceExtraCompilerVariables(const QString &var, const QStringList &in, const QStringList &out) { QString ret = MakefileGenerator::replaceExtraCompilerVariables(var, in, out); @@ -1572,8 +1538,6 @@ QString VcprojGenerator::replaceExtraCompilerVariables(const QString &var, const return ret; } - - bool VcprojGenerator::openOutput(QFile &file, const QString &/*build*/) const { QString outdir; @@ -1625,7 +1589,6 @@ QString VcprojGenerator::findTemplate(QString file) return ret; } - void VcprojGenerator::processPrlVariable(const QString &var, const QStringList &l) { if(var == "QMAKE_PRL_DEFINES") { @@ -1644,9 +1607,8 @@ void VcprojGenerator::outputVariables() #if 0 qDebug("Generator: MSVC.NET: List of current variables:"); for(QMap<QString, QStringList>::ConstIterator it = project->variables().begin(); it != project->variables().end(); ++it) - qDebug("Generator: MSVC.NET: %s => %s", it.key().toLatin1().constData(), it.data().join(" | ").toLatin1().constData()); + qDebug("Generator: MSVC.NET: %s => %s", qPrintable(it.key()), qPrintable(it.value().join(" | "))); #endif } QT_END_NAMESPACE - diff --git a/qmake/generators/win32/msvc_vcproj.h b/qmake/generators/win32/msvc_vcproj.h index 8f028a1..a603500 100644 --- a/qmake/generators/win32/msvc_vcproj.h +++ b/qmake/generators/win32/msvc_vcproj.h @@ -78,8 +78,10 @@ public: QMap<QString, QStringList> extraCompilerSources; QMap<QString, QStringList> extraCompilerOutputs; bool usePCH; + VCProjectWriter *projectWriter; protected: + virtual VCProjectWriter *createProjectWriter(); virtual bool doDepends() const { return false; } //never necesary virtual void processSources() { filterIncludedFiles("SOURCES"); filterIncludedFiles("GENERATED_SOURCES"); } virtual QString replaceExtraCompilerVariables(const QString &, const QStringList &, const QStringList &); @@ -135,9 +137,6 @@ private: friend class VCFilter; }; -inline VcprojGenerator::~VcprojGenerator() -{ } - inline QString VcprojGenerator::defaultMakefile() const { return project->first("TARGET") + project->first("VCPROJ_EXTENSION"); diff --git a/qmake/generators/win32/msvc_vcxproj.cpp b/qmake/generators/win32/msvc_vcxproj.cpp index 271d9ae..7ba0c65 100644 --- a/qmake/generators/win32/msvc_vcxproj.cpp +++ b/qmake/generators/win32/msvc_vcxproj.cpp @@ -64,772 +64,10 @@ QT_BEGIN_NAMESPACE VcxprojGenerator::VcxprojGenerator() : VcprojGenerator() { } -bool VcxprojGenerator::writeMakefile(QTextStream &t) -{ - initProject(); // Fills the whole project with proper data - - // Generate solution file - if(project->first("TEMPLATE") == "vcsubdirs") { - if (!project->isActiveConfig("build_pass")) { - debug_msg(1, "Generator: MSVC.NET: Writing solution file"); - writeSubDirs(t); - } else { - debug_msg(1, "Generator: MSVC.NET: Not writing solution file for build_pass configs"); - } - return true; - } else - // Generate single configuration project file - if (project->first("TEMPLATE") == "vcapp" || - project->first("TEMPLATE") == "vclib") { - if(!project->isActiveConfig("build_pass")) { - debug_msg(1, "Generator: MSVC.NET: Writing single configuration project file"); - XmlOutput xmlOut(t); - xmlOut << vcxProject; - } - return true; - } - return project->isActiveConfig("build_pass"); -} - - -void VcxprojGenerator::initProject() -{ - // Initialize XML sub elements - // - Do this first since project elements may need - // - to know of certain configuration options - initConfiguration(); - initRootFiles(); - initSourceFiles(); - initHeaderFiles(); - initGeneratedFiles(); - initLexYaccFiles(); - initTranslationFiles(); - initFormFiles(); - initResourceFiles(); - initExtraCompilerOutputs(); - - // Own elements ----------------------------- - vcxProject.Name = unescapeFilePath(project->first("QMAKE_ORIG_TARGET")); - - vcxProject.Keyword = project->first("VCPROJ_KEYWORD"); - if (project->isEmpty("CE_SDK") || project->isEmpty("CE_ARCH")) { - vcxProject.PlatformName = vcxProject.Configuration.idl.TargetEnvironment; - if ( vcxProject.Configuration.idl.TargetEnvironment.isEmpty() ) - vcxProject.PlatformName = "Win32"; - } else { - vcxProject.PlatformName = project->values("CE_SDK").join(" ") + " (" + project->first("CE_ARCH") + ")"; - } - // These are not used by Qt, but may be used by customers - vcxProject.SccProjectName = project->first("SCCPROJECTNAME"); - vcxProject.SccLocalPath = project->first("SCCLOCALPATH"); - vcxProject.flat_files = project->isActiveConfig("flat"); -} - - -void VcxprojGenerator::initConfiguration() -{ - // Initialize XML sub elements - // - Do this first since main configuration elements may need - // - to know of certain compiler/linker options - VCXConfiguration &conf = vcxProject.Configuration; - - initCompilerTool(); - - // Only on configuration per build - bool isDebug = project->isActiveConfig("debug"); - - if(projectTarget == StaticLib) - initLibrarianTool(); - else { - conf.linker.GenerateDebugInformation = isDebug ? _True : _False; - initLinkerTool(); - } - initResourceTool(); - initIDLTool(); - - // Own elements ----------------------------- - QString temp = project->first("BuildBrowserInformation"); - switch (projectTarget) { - case SharedLib: - conf.ConfigurationType = "DynamicLibrary"; - break; - case StaticLib: - conf.ConfigurationType = "StaticLibrary"; - break; - case Application: - default: - conf.ConfigurationType = "Application"; - break; - } - - conf.OutputDirectory = project->first("DESTDIR"); - - if(conf.OutputDirectory.isEmpty()) - conf.OutputDirectory = ".\\"; - - if(!conf.OutputDirectory.endsWith("\\")) - conf.OutputDirectory += '\\'; - - // The target name could have been changed. - conf.TargetName = project->first("TARGET"); - if ( !conf.TargetName.isEmpty() && !project->first("TARGET_VERSION_EXT").isEmpty() && project->isActiveConfig("shared")) - conf.TargetName.append(project->first("TARGET_VERSION_EXT")); - - conf.Name = project->values("BUILD_NAME").join(" "); - if (conf.Name.isEmpty()) - conf.Name = isDebug ? "Debug" : "Release"; - conf.ConfigurationName = conf.Name; - if (project->isEmpty("CE_SDK") || project->isEmpty("CE_ARCH")) { - conf.Name += (conf.idl.TargetEnvironment == "Win64" ? "|Win64" : "|Win32"); - } else { - conf.Name += "|" + project->values("CE_SDK").join(" ") + " (" + project->first("CE_ARCH") + ")"; - } - conf.ATLMinimizesCRunTimeLibraryUsage = (project->first("ATLMinimizesCRunTimeLibraryUsage").isEmpty() ? _False : _True); - conf.BuildBrowserInformation = triState(temp.isEmpty() ? (short)unset : temp.toShort()); - temp = project->first("CharacterSet"); - if (!temp.isEmpty()) - { - switch (charSet(temp.toShort())) { - - case charSetMBCS: - conf.CharacterSet = "MultiByte"; - break; - case charSetUnicode: - conf.CharacterSet = "Unicode"; - break; - case charSetNotSet: - default: - conf.CharacterSet = "NotSet"; - break; - } - } - conf.DeleteExtensionsOnClean = project->first("DeleteExtensionsOnClean"); - conf.ImportLibrary = conf.linker.ImportLibrary; - conf.IntermediateDirectory = project->first("OBJECTS_DIR"); - //conf.OutputDirectory = "."; - conf.PrimaryOutput = project->first("PrimaryOutput"); - conf.WholeProgramOptimization = conf.compiler.WholeProgramOptimization; - temp = project->first("UseOfATL"); - if(!temp.isEmpty()) - { - switch (useOfATL(temp.toShort())) { - - case useATLStatic: - conf.UseOfATL = "Static"; - break; - case useATLDynamic: - conf.UseOfATL = "Dynamic"; - break; - case useATLNotSet: - default: - conf.UseOfATL = "false"; - break; - } - } - temp = project->first("UseOfMfc"); - if(!temp.isEmpty()) - { - switch (useOfMfc(temp.toShort())) { - - case useMfcStatic: - conf.UseOfMfc = "Static"; - break; - case useMfcDynamic: - conf.UseOfMfc = "Dynamic"; - break; - case useMfcStdWin: - default: - conf.UseOfMfc = "false"; - break; - } - } - - // Configuration does not need parameters from - // these sub XML items; - initCustomBuildTool(); - initPreBuildEventTools(); - initPostBuildEventTools(); - // Only deploy for CE projects - if (!project->isEmpty("CE_SDK") && !project->isEmpty("CE_ARCH")) - initDeploymentTool(); - initPreLinkEventTools(); - - // Set definite values in both configurations - if (isDebug) { - conf.compiler.PreprocessorDefinitions.removeAll("NDEBUG"); - } else { - conf.compiler.PreprocessorDefinitions += "NDEBUG"; - } -} - - -void VcxprojGenerator::initCompilerTool() -{ - QString placement = project->first("OBJECTS_DIR"); - if(placement.isEmpty()) - placement = ".\\"; - - VCXConfiguration &conf = vcxProject.Configuration; - conf.compiler.AssemblerListingLocation = placement ; - conf.compiler.ProgramDataBaseFileName = ".\\" ; - conf.compiler.ObjectFileName = placement ; - conf.compiler.ExceptionHandling = "false"; - // PCH - if (usePCH) { - conf.compiler.PrecompiledHeader = "Use"; - conf.compiler.PrecompiledHeaderOutputFile = "$(IntDir)\\" + precompPch; - conf.compiler.PrecompiledHeaderFile = project->first("PRECOMPILED_HEADER"); - conf.compiler.ForcedIncludeFiles = project->values("PRECOMPILED_HEADER"); - conf.compiler.PreprocessToFile = _False; - conf.compiler.PreprocessSuppressLineNumbers = _False; - // Minimal build option triggers an Internal Compiler Error - // when used in conjunction with /FI and /Yu, so remove it - project->values("QMAKE_CFLAGS_DEBUG").removeAll("-Gm"); - project->values("QMAKE_CFLAGS_DEBUG").removeAll("/Gm"); - project->values("QMAKE_CXXFLAGS_DEBUG").removeAll("-Gm"); - project->values("QMAKE_CXXFLAGS_DEBUG").removeAll("/Gm"); - } - - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS")); - if(project->isActiveConfig("debug")){ - // Debug version - if((projectTarget == Application) || (projectTarget == StaticLib)) - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DBG")); - else - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DLLDBG")); - } else { - // Release version - conf.compiler.PreprocessorDefinitions += "QT_NO_DEBUG"; - conf.compiler.PreprocessorDefinitions += "NDEBUG"; - if((projectTarget == Application) || (projectTarget == StaticLib)) - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT")); - else - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DLL")); - } - - // Common for both release and debug - if(project->isActiveConfig("windows")) - conf.compiler.PreprocessorDefinitions += project->values("MSVCPROJ_WINCONDEF"); - - // Can this be set for ALL configs? - // If so, use qmake.conf! - if(projectTarget == SharedLib) - conf.compiler.PreprocessorDefinitions += "_WINDOWS"; - - conf.compiler.PreprocessorDefinitions += project->values("DEFINES"); - conf.compiler.PreprocessorDefinitions += project->values("PRL_EXPORT_DEFINES"); - conf.compiler.parseOptions(project->values("MSVCPROJ_INCPATH")); -} - -void VcxprojGenerator::initLinkerTool() -{ - findLibraries(); // Need to add the highest version of the libs - VCXConfiguration &conf = vcxProject.Configuration; - conf.linker.parseOptions(project->values("MSVCPROJ_LFLAGS")); - - foreach(QString libs, project->values("MSVCPROJ_LIBS")) { - if (libs.left(9).toUpper() == "/LIBPATH:") { - QStringList l = QStringList(libs); - conf.linker.parseOptions(l); - } else { - conf.linker.AdditionalDependencies += libs; - } - } - - switch (projectTarget) { - case Application: - conf.linker.OutputFile = project->first("DESTDIR"); - break; - case SharedLib: - conf.linker.parseOptions(project->values("MSVCPROJ_LIBOPTIONS")); - conf.linker.OutputFile = project->first("DESTDIR"); - break; - case StaticLib: //unhandled - added to remove warnings.. - break; - } - - if(conf.linker.OutputFile.isEmpty()) - conf.linker.OutputFile = ".\\"; - - if(!conf.linker.OutputFile.endsWith("\\")) - conf.linker.OutputFile += '\\'; - - conf.linker.OutputFile += project->first("MSVCPROJ_TARGET"); - - if(project->isActiveConfig("dll")){ - conf.linker.parseOptions(project->values("QMAKE_LFLAGS_QT_DLL")); - } -} - -void VcxprojGenerator::initResourceTool() -{ - VCXConfiguration &conf = vcxProject.Configuration; - conf.resource.PreprocessorDefinitions = conf.compiler.PreprocessorDefinitions; - - // We need to add _DEBUG for the debug version of the project, since the normal compiler defines - // do not contain it. (The compiler defines this symbol automatically, which is wy we don't need - // to add it for the compiler) However, the resource tool does not do this. - if(project->isActiveConfig("debug")) - conf.resource.PreprocessorDefinitions += "_DEBUG"; - if(project->isActiveConfig("staticlib")) - conf.resource.ResourceOutputFileName = project->first("DESTDIR") + "/$(InputName).res"; -} - - -void VcxprojGenerator::initPostBuildEventTools() -{ - VCXConfiguration &conf = vcxProject.Configuration; - if(!project->values("QMAKE_POST_LINK").isEmpty()) { - QString cmdline = var("QMAKE_POST_LINK"); - conf.postBuild.CommandLine = cmdline; - conf.postBuild.Description = cmdline; - conf.postBuild.UseInBuild = _True; - } - - QString signature = !project->isEmpty("SIGNATURE_FILE") ? var("SIGNATURE_FILE") : var("DEFAULT_SIGNATURE"); - bool useSignature = !signature.isEmpty() && !project->isActiveConfig("staticlib") && - !project->isEmpty("CE_SDK") && !project->isEmpty("CE_ARCH"); - if(useSignature) { - conf.postBuild.CommandLine.prepend(QLatin1String("signtool sign /F ") + signature + " \"$(TargetPath)\"\n" + - (!conf.postBuild.CommandLine.isEmpty() ? " && " : "")); - conf.postBuild.UseInBuild = _True; - } - - if(!project->values("MSVCPROJ_COPY_DLL").isEmpty()) { - if(!conf.postBuild.CommandLine.isEmpty()) - conf.postBuild.CommandLine += " && "; - conf.postBuild.Description += var("MSVCPROJ_COPY_DLL_DESC"); - conf.postBuild.CommandLine += var("MSVCPROJ_COPY_DLL"); - conf.postBuild.UseInBuild = _True; - } -} - - -void VcxprojGenerator::initDeploymentTool() -{ - VCXConfiguration &conf = vcxProject.Configuration; - QString targetPath = project->values("deploy.path").join(" "); - if (targetPath.isEmpty()) - targetPath = QString("%CSIDL_PROGRAM_FILES%\\") + project->first("TARGET"); - if (targetPath.endsWith("/") || targetPath.endsWith("\\")) - targetPath.chop(1); - - // Only deploy Qt libs for shared build - if (!project->values("QMAKE_QT_DLL").isEmpty()) { - QStringList& arg = project->values("MSVCPROJ_LIBS"); - for (QStringList::ConstIterator it = arg.constBegin(); it != arg.constEnd(); ++it) { - if (it->contains(project->first("QMAKE_LIBDIR"))) { - QString dllName = *it; - - if (dllName.contains(QLatin1String("QAxContainer")) - || dllName.contains(QLatin1String("qtmain")) - || dllName.contains(QLatin1String("QtUiTools"))) - continue; - dllName.replace(QLatin1String(".lib") , QLatin1String(".dll")); - QFileInfo info(dllName); - conf.deployment.AdditionalFiles += info.fileName() - + "|" + QDir::toNativeSeparators(info.absolutePath()) - + "|" + targetPath - + "|0;"; - } - } - } - - // C-runtime deployment - QString runtime = project->values("QT_CE_C_RUNTIME").join(QLatin1String(" ")); - if (!runtime.isEmpty() && (runtime != QLatin1String("no"))) { - QString runtimeVersion = QLatin1String("msvcr"); - QString mkspec = project->first("QMAKESPEC"); - // If no .qmake.cache has been found, we fallback to the original mkspec - if (mkspec.isEmpty()) - mkspec = project->first("QMAKESPEC_ORIGINAL"); - - if (!mkspec.isEmpty()) { - if (mkspec.endsWith("2010")) - runtimeVersion.append("100"); - else if (mkspec.endsWith("2008")) - runtimeVersion.append("90"); - else - runtimeVersion.append("80"); - if (project->isActiveConfig("debug")) - runtimeVersion.append("d"); - runtimeVersion.append(".dll"); - - if (runtime == "yes") { - // Auto-find C-runtime - QString vcInstallDir = qgetenv("VCINSTALLDIR"); - if (!vcInstallDir.isEmpty()) { - vcInstallDir += "\\ce\\dll\\"; - vcInstallDir += project->values("CE_ARCH").join(QLatin1String(" ")); - if (!QFileInfo(vcInstallDir + QDir::separator() + runtimeVersion).exists()) - runtime.clear(); - else - runtime = vcInstallDir; - } - } - } - - if (!runtime.isEmpty() && runtime != QLatin1String("yes")) { - conf.deployment.AdditionalFiles += runtimeVersion - + "|" + QDir::toNativeSeparators(runtime) - + "|" + targetPath - + "|0;"; - } - } - - // foreach item in DEPLOYMENT - foreach(QString item, project->values("DEPLOYMENT")) { - // get item.path - QString devicePath = project->first(item + ".path"); - if (devicePath.isEmpty()) - devicePath = targetPath; - // check if item.path is relative (! either /,\ or %) - if (!(devicePath.at(0) == QLatin1Char('/') - || devicePath.at(0) == QLatin1Char('\\') - || devicePath.at(0) == QLatin1Char('%'))) { - // create output path - devicePath = Option::fixPathToLocalOS(QDir::cleanPath(targetPath + QLatin1Char('\\') + devicePath)); - } - // foreach d in item.sources - foreach(QString source, project->values(item + ".sources")) { - QString itemDevicePath = devicePath; - source = Option::fixPathToLocalOS(source); - QString nameFilter; - QFileInfo info(source); - QString searchPath; - if (info.isDir()) { - nameFilter = QLatin1String("*"); - itemDevicePath += "\\" + info.fileName(); - searchPath = info.absoluteFilePath(); - } else { - nameFilter = source.split('\\').last(); - searchPath = info.absolutePath(); - } - - int pathSize = searchPath.size(); - QDirIterator iterator(searchPath, QStringList() << nameFilter - , QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks - , QDirIterator::Subdirectories); - // foreach dirIterator-entry in d - while(iterator.hasNext()) { - iterator.next(); - QString absoluteItemPath = Option::fixPathToLocalOS(QFileInfo(iterator.filePath()).absolutePath()); - // Identify if it is just another subdir - int diffSize = absoluteItemPath.size() - pathSize; - // write out rules - conf.deployment.AdditionalFiles += iterator.fileName() - + "|" + absoluteItemPath - + "|" + itemDevicePath + (diffSize ? (absoluteItemPath.right(diffSize)) : QLatin1String("")) - + "|0;"; - } - } - } -} - -void VcxprojGenerator::initPreLinkEventTools() -{ - VCXConfiguration &conf = vcxProject.Configuration; - if(!project->values("QMAKE_PRE_LINK").isEmpty()) { - QString cmdline = var("QMAKE_PRE_LINK"); - conf.preLink.Description = cmdline; - conf.preLink.CommandLine = cmdline; - conf.preLink.UseInBuild = _True; - } -} - -void VcxprojGenerator::initRootFiles() -{ - vcxProject.RootFiles.addFiles(project->values("RC_FILE")); - vcxProject.RootFiles.Project = this; - vcxProject.RootFiles.Config = &(vcxProject.Configuration); - vcxProject.RootFiles.CustomBuild = none; -} - -void VcxprojGenerator::initSourceFiles() -{ - vcxProject.SourceFiles.Name = "Source Files"; - vcxProject.SourceFiles.Filter = "cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"; - vcxProject.SourceFiles.Guid = _GUIDSourceFiles; - - vcxProject.SourceFiles.addFiles(project->values("SOURCES")); - - vcxProject.SourceFiles.Project = this; - vcxProject.SourceFiles.Config = &(vcxProject.Configuration); - vcxProject.SourceFiles.CustomBuild = none; -} - -void VcxprojGenerator::initHeaderFiles() -{ - vcxProject.HeaderFiles.Name = "Header Files"; - vcxProject.HeaderFiles.Filter = "h;hpp;hxx;hm;inl;inc;xsd"; - vcxProject.HeaderFiles.Guid = _GUIDHeaderFiles; - - vcxProject.HeaderFiles.addFiles(project->values("HEADERS")); - if (usePCH) // Generated PCH cpp file - vcxProject.HeaderFiles.addFile(precompH); - - vcxProject.HeaderFiles.Project = this; - vcxProject.HeaderFiles.Config = &(vcxProject.Configuration); -} - -void VcxprojGenerator::initGeneratedFiles() -{ - vcxProject.GeneratedFiles.Name = "Generated Files"; - vcxProject.GeneratedFiles.Filter = "cpp;c;cxx;moc;h;def;odl;idl;res"; - vcxProject.GeneratedFiles.Guid = _GUIDGeneratedFiles; - - // ### These cannot have CustomBuild (mocSrc)!! - vcxProject.GeneratedFiles.addFiles(project->values("GENERATED_SOURCES")); - vcxProject.GeneratedFiles.addFiles(project->values("GENERATED_FILES")); - vcxProject.GeneratedFiles.addFiles(project->values("IDLSOURCES")); - vcxProject.GeneratedFiles.addFiles(project->values("RES_FILE")); - vcxProject.GeneratedFiles.addFiles(project->values("QMAKE_IMAGE_COLLECTION")); // compat - if(!extraCompilerOutputs.isEmpty()) - vcxProject.GeneratedFiles.addFiles(extraCompilerOutputs.keys()); - - vcxProject.GeneratedFiles.Project = this; - vcxProject.GeneratedFiles.Config = &(vcxProject.Configuration); -} - -void VcxprojGenerator::initLexYaccFiles() -{ - vcxProject.LexYaccFiles.Name = "Lex / Yacc Files"; - vcxProject.LexYaccFiles.ParseFiles = _False; - vcxProject.LexYaccFiles.Filter = "l;y"; - vcxProject.LexYaccFiles.Guid = _GUIDLexYaccFiles; - - vcxProject.LexYaccFiles.addFiles(project->values("LEXSOURCES")); - vcxProject.LexYaccFiles.addFiles(project->values("YACCSOURCES")); - - vcxProject.LexYaccFiles.Project = this; - vcxProject.LexYaccFiles.Config = &(vcxProject.Configuration); - vcxProject.LexYaccFiles.CustomBuild = lexyacc; -} - -void VcxprojGenerator::initTranslationFiles() -{ - vcxProject.TranslationFiles.Name = "Translation Files"; - vcxProject.TranslationFiles.ParseFiles = _False; - vcxProject.TranslationFiles.Filter = "ts;xlf"; - vcxProject.TranslationFiles.Guid = _GUIDTranslationFiles; - - vcxProject.TranslationFiles.addFiles(project->values("TRANSLATIONS")); - - vcxProject.TranslationFiles.Project = this; - vcxProject.TranslationFiles.Config = &(vcxProject.Configuration); - vcxProject.TranslationFiles.CustomBuild = none; -} - - -void VcxprojGenerator::initFormFiles() -{ - vcxProject.FormFiles.Name = "Form Files"; - vcxProject.FormFiles.ParseFiles = _False; - vcxProject.FormFiles.Filter = "ui"; - vcxProject.FormFiles.Guid = _GUIDFormFiles; - - vcxProject.FormFiles.addFiles(project->values("FORMS")); - vcxProject.FormFiles.addFiles(project->values("FORMS3")); - - vcxProject.FormFiles.Project = this; - vcxProject.FormFiles.Config = &(vcxProject.Configuration); - vcxProject.FormFiles.CustomBuild = none; -} - - -void VcxprojGenerator::initResourceFiles() -{ - vcxProject.ResourceFiles.Name = "Resource Files"; - vcxProject.ResourceFiles.ParseFiles = _False; - vcxProject.ResourceFiles.Filter = "qrc;*"; //"rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;ts;xlf;qrc"; - vcxProject.ResourceFiles.Guid = _GUIDResourceFiles; - - // Bad hack, please look away ------------------------------------- - QString rcc_dep_cmd = project->values("rcc.depend_command").join(" "); - if(!rcc_dep_cmd.isEmpty()) { - QStringList qrc_files = project->values("RESOURCES"); - QStringList deps; - if(!qrc_files.isEmpty()) { - for (int i = 0; i < qrc_files.count(); ++i) { - char buff[256]; - QString dep_cmd = replaceExtraCompilerVariables(rcc_dep_cmd, qrc_files.at(i),""); - - dep_cmd = Option::fixPathToLocalOS(dep_cmd, true, false); - if(canExecute(dep_cmd)) { - if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) { - QString indeps; - while(!feof(proc)) { - int read_in = (int)fread(buff, 1, 255, proc); - if(!read_in) - break; - indeps += QByteArray(buff, read_in); - } - QT_PCLOSE(proc); - if(!indeps.isEmpty()) - deps += fileFixify(indeps.replace('\n', ' ').simplified().split(' ')); - } - } - } - vcxProject.ResourceFiles.addFiles(deps); - } - } - // You may look again -------------------------------------------- - - vcxProject.ResourceFiles.addFiles(project->values("RESOURCES")); - vcxProject.ResourceFiles.addFiles(project->values("IMAGES")); - - vcxProject.ResourceFiles.Project = this; - vcxProject.ResourceFiles.Config = &(vcxProject.Configuration); - vcxProject.ResourceFiles.CustomBuild = none; -} - -void VcxprojGenerator::initExtraCompilerOutputs() -{ - QStringList otherFilters; - otherFilters << "FORMS" - << "FORMS3" - << "GENERATED_FILES" - << "GENERATED_SOURCES" - << "HEADERS" - << "IDLSOURCES" - << "IMAGES" - << "LEXSOURCES" - << "QMAKE_IMAGE_COLLECTION" - << "RC_FILE" - << "RESOURCES" - << "RES_FILE" - << "SOURCES" - << "TRANSLATIONS" - << "YACCSOURCES"; - const QStringList &quc = project->values("QMAKE_EXTRA_COMPILERS"); - for(QStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) { - QString extracompilerName = project->first((*it) + ".name"); - if (extracompilerName.isEmpty()) - extracompilerName = (*it); - - // Create an extra compiler filter and add the files - VCXFilter extraCompile; - extraCompile.Name = extracompilerName; - extraCompile.ParseFiles = _False; - extraCompile.Filter = ""; - extraCompile.Guid = QString(_GUIDExtraCompilerFiles) + "-" + (*it); - - // If the extra compiler has a variable_out set the output file - // is added to an other file list, and does not need its own.. - bool addOnInput = hasBuiltinCompiler(project->first((*it) + ".output")); - QString tmp_other_out = project->first((*it) + ".variable_out"); - if (!tmp_other_out.isEmpty() && !addOnInput) - continue; - - if (!addOnInput) { - QString tmp_out = project->first((*it) + ".output"); - if (project->values((*it) + ".CONFIG").indexOf("combine") != -1) { - // Combined output, only one file result - extraCompile.addFile( - Option::fixPathToTargetOS(replaceExtraCompilerVariables(tmp_out, QString(), QString()), false)); - } else { - // One output file per input - QStringList tmp_in = project->values(project->first((*it) + ".input")); - for (int i = 0; i < tmp_in.count(); ++i) { - const QString &filename = tmp_in.at(i); - if (extraCompilerSources.contains(filename)) - extraCompile.addFile( - Option::fixPathToTargetOS(replaceExtraCompilerVariables(filename, tmp_out, QString()), false)); - } - } - } else { - // In this case we the outputs have a built-in compiler, so we cannot add the custom - // build steps there. So, we turn it around and add it to the input files instead, - // provided that the input file variable is not handled already (those in otherFilters - // are handled, so we avoid them). - QStringList inputVars = project->values((*it) + ".input"); - foreach(QString inputVar, inputVars) { - if (!otherFilters.contains(inputVar)) { - QStringList tmp_in = project->values(inputVar); - for (int i = 0; i < tmp_in.count(); ++i) { - const QString &filename = tmp_in.at(i); - if (extraCompilerSources.contains(filename)) - extraCompile.addFile( - Option::fixPathToTargetOS(replaceExtraCompilerVariables(filename, QString(), QString()), false)); - } - } - } - } - extraCompile.Project = this; - extraCompile.Config = &(vcxProject.Configuration); - extraCompile.CustomBuild = none; - - vcxProject.ExtraCompilersFiles.append(extraCompile); - } -} - - - -bool VcxprojGenerator::writeProjectMakefile() -{ - usePlatformDir(); - QTextStream t(&Option::output); - - // Check if all requirements are fulfilled - if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) { - fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n", - var("QMAKE_FAILED_REQUIREMENTS").toLatin1().constData()); - return true; - } - - // Generate project file - if(project->first("TEMPLATE") == "vcapp" || - project->first("TEMPLATE") == "vclib") { - if (!mergedProjects.count()) { - warn_msg(WarnLogic, "Generator: MSVC.NET: no single configuration created, cannot output project!"); - return false; - } - - debug_msg(1, "Generator: MSVC.NET: Writing project file"); - VCXProject mergedProject; - for (int i = 0; i < mergedProjects.count(); ++i) { - VCXProjectSingleConfig *singleProject = &(mergedProjects.at(i)->vcxProject); - mergedProject.SingleProjects += *singleProject; - for (int j = 0; j < singleProject->ExtraCompilersFiles.count(); ++j) { - const QString &compilerName = singleProject->ExtraCompilersFiles.at(j).Name; - if (!mergedProject.ExtraCompilers.contains(compilerName)) - mergedProject.ExtraCompilers += compilerName; - } - } - - if(mergedProjects.count() > 1 && - mergedProjects.at(0)->vcxProject.Name == - mergedProjects.at(1)->vcxProject.Name) - mergedProjects.at(0)->writePrlFile(); - mergedProject.Name = unescapeFilePath(project->first("QMAKE_ORIG_TARGET")); - mergedProject.Version = mergedProjects.at(0)->vcxProject.Version; - mergedProject.ProjectGUID = project->isEmpty("QMAKE_UUID") ? getProjectUUID().toString().toUpper() : project->first("QMAKE_UUID"); - mergedProject.Keyword = project->first("VCPROJ_KEYWORD"); - mergedProject.SccProjectName = mergedProjects.at(0)->vcxProject.SccProjectName; - mergedProject.SccLocalPath = mergedProjects.at(0)->vcxProject.SccLocalPath; - mergedProject.PlatformName = mergedProjects.at(0)->vcxProject.PlatformName; - - XmlOutput xmlOut(t); - xmlOut << mergedProject; - return true; - } else if(project->first("TEMPLATE") == "vcsubdirs") { - return writeMakefile(t); - } - return false; -} - - - -bool VcxprojGenerator::mergeBuildProject(MakefileGenerator *other) +VCProjectWriter *VcxprojGenerator::createProjectWriter() { - VcxprojGenerator *otherVC = static_cast<VcxprojGenerator*>(other); - if (!otherVC) { - warn_msg(WarnLogic, "VcxprojGenerator: Cannot merge other types of projects! (ignored)"); - return false; - } - mergedProjects += otherVC; - return true; + return new VCXProjectWriter; } QT_END_NAMESPACE diff --git a/qmake/generators/win32/msvc_vcxproj.h b/qmake/generators/win32/msvc_vcxproj.h index 8a183e9..45e6b95 100644 --- a/qmake/generators/win32/msvc_vcxproj.h +++ b/qmake/generators/win32/msvc_vcxproj.h @@ -50,45 +50,15 @@ QT_BEGIN_NAMESPACE class VcxprojGenerator : public VcprojGenerator { - bool writeMakefile(QTextStream &); - bool writeProjectMakefile(); - public: VcxprojGenerator(); ~VcxprojGenerator(); protected: - virtual bool supportsMetaBuild() { return true; } - virtual bool supportsMergedBuilds() { return true; } - virtual bool mergeBuildProject(MakefileGenerator *other); - - virtual void initProject(); - - void initConfiguration(); - void initCompilerTool(); - void initDeploymentTool(); - void initLinkerTool(); - void initPreLinkEventTools(); - void initPostBuildEventTools(); - void initRootFiles(); - void initResourceTool(); - void initSourceFiles(); - void initHeaderFiles(); - void initGeneratedFiles(); - void initTranslationFiles(); - void initFormFiles(); - void initResourceFiles(); - void initLexYaccFiles(); - void initExtraCompilerOutputs(); - - // Used for single project - VCXProjectSingleConfig vcxProject; - - // Holds all configurations for glue (merged) project - QList<VcxprojGenerator*> mergedProjects; + virtual VCProjectWriter *createProjectWriter(); private: - friend class VCXFilter; + friend class VCFilter; }; diff --git a/qmake/option.cpp b/qmake/option.cpp index 8db3797..27e7c18 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -621,7 +621,7 @@ Option::fixString(QString string, uchar flags) static QHash<FixStringCacheKey, QString> *cache = 0; if(!cache) { cache = new QHash<FixStringCacheKey, QString>; - qmakeAddCacheClear(qmakeDeleteCacheClear_QHashFixStringCacheKeyQString, (void**)&cache); + qmakeAddCacheClear(qmakeDeleteCacheClear<QHash<FixStringCacheKey, QString> >, (void**)&cache); } FixStringCacheKey cacheKey(string, flags); if(cache->contains(cacheKey)) { diff --git a/qmake/project.cpp b/qmake/project.cpp index cb02923..29d4242 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -87,7 +87,7 @@ QMap<QString, ExpandFunc> qmake_expandFunctions() static QMap<QString, ExpandFunc> *qmake_expand_functions = 0; if(!qmake_expand_functions) { qmake_expand_functions = new QMap<QString, ExpandFunc>; - qmakeAddCacheClear(qmakeDeleteCacheClear_QMapStringInt, (void**)&qmake_expand_functions); + qmakeAddCacheClear(qmakeDeleteCacheClear<QMap<QString, ExpandFunc> >, (void**)&qmake_expand_functions); qmake_expand_functions->insert("member", E_MEMBER); qmake_expand_functions->insert("first", E_FIRST); qmake_expand_functions->insert("last", E_LAST); @@ -1631,7 +1631,7 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QMap<QString, QStringL if(!feature_roots) { validateModes(); feature_roots = new QStringList(qmake_feature_paths(prop)); - qmakeAddCacheClear(qmakeDeleteCacheClear_QStringList, (void**)&feature_roots); + qmakeAddCacheClear(qmakeDeleteCacheClear<QStringList>, (void**)&feature_roots); } debug_msg(2, "Looking for feature '%s' in (%s)", file.toLatin1().constData(), feature_roots->join("::").toLatin1().constData()); diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c b/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c index 7cd82bb..4b68e64 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c +++ b/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c @@ -424,12 +424,8 @@ static HB_Bool myanmar_shape_syllable(HB_Bool openType, HB_ShaperItem *item, HB_ #ifndef NO_OPENTYPE if (openType) { - unsigned short logClusters[32]; hb_uint32 where[32]; - for (i = 0; i < len; ++i) - logClusters[i] = i; - for (i = 0; i < len; ++i) { where[i] = ~(PreSubstProperty | BelowSubstProperty diff --git a/src/3rdparty/phonon/phonon/mediacontroller.cpp b/src/3rdparty/phonon/phonon/mediacontroller.cpp index 59fd5c7..9f651d6 100644 --- a/src/3rdparty/phonon/phonon/mediacontroller.cpp +++ b/src/3rdparty/phonon/phonon/mediacontroller.cpp @@ -216,14 +216,14 @@ void MediaController::setCurrentAudioChannel(const Phonon::AudioChannelDescripti { IFACE; iface->interfaceCall(AddonInterface::AudioChannelInterface, - AddonInterface::setCurrentAudioChannel, QList<QVariant>() << qVariantFromValue(stream)); + AddonInterface::setCurrentAudioChannel, QList<QVariant>() << QVariant::fromValue(stream)); } void MediaController::setCurrentSubtitle(const Phonon::SubtitleDescription &stream) { IFACE; iface->interfaceCall(AddonInterface::SubtitleInterface, - AddonInterface::setCurrentSubtitle, QList<QVariant>() << qVariantFromValue(stream)); + AddonInterface::setCurrentSubtitle, QList<QVariant>() << QVariant::fromValue(stream)); } #undef IFACE diff --git a/src/3rdparty/phonon/phonon/qsettingsgroup_p.h b/src/3rdparty/phonon/phonon/qsettingsgroup_p.h index f28ecaa..f25b15e 100644 --- a/src/3rdparty/phonon/phonon/qsettingsgroup_p.h +++ b/src/3rdparty/phonon/phonon/qsettingsgroup_p.h @@ -54,7 +54,7 @@ class QSettingsGroup template<typename T> inline T value(const QString &key, const T &def) const { - return qvariant_cast<T>(value(key, qVariantFromValue(def))); + return qvariant_cast<T>(value(key, QVariant::fromValue(def))); } inline QVariant value(const QString &key, const QVariant &def) const @@ -66,7 +66,7 @@ class QSettingsGroup inline void setValue(const QString &key, const T &value) { Q_ASSERT(m_mutableSettings); - m_mutableSettings->setValue(m_group + key, qVariantFromValue(value)); + m_mutableSettings->setValue(m_group + key, QVariant::fromValue(value)); } inline void removeEntry(const QString &key) diff --git a/src/3rdparty/phonon/qt7/videowidget.mm b/src/3rdparty/phonon/qt7/videowidget.mm index 736dcdf..c281e16 100644 --- a/src/3rdparty/phonon/qt7/videowidget.mm +++ b/src/3rdparty/phonon/qt7/videowidget.mm @@ -278,7 +278,7 @@ public: glMatrixMode(GL_PROJECTION); glLoadIdentity(); glViewport(0, 0, GLsizei(w), GLsizei(h)); - gluOrtho2D(0, GLsizei(w), 0, GLsizei(h)); + glOrtho(0, GLsizei(w), 0, GLsizei(h), -1, 1); updateGL(); } diff --git a/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp b/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp index 2212f58..7f5d37d 100644 --- a/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp +++ b/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp @@ -567,7 +567,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type if (qstring.mid(lastSlash + 1).contains(QLatin1Char('i'))) realRe.setCaseSensitivity(Qt::CaseInsensitive); - ret = qVariantFromValue(realRe); + ret = QVariant::fromValue(realRe); dist = 0; } else { qConvDebug() << "couldn't parse a JS regexp"; @@ -578,7 +578,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type QRegExp re(qstring); if (re.isValid()) { - ret = qVariantFromValue(re); + ret = QVariant::fromValue(re); dist = 10; } } @@ -590,7 +590,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type if (qtinst) { if (qtinst->getObject()) { qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject(); - ret = qVariantFromValue(qtinst->getObject()); + ret = QVariant::fromValue(qtinst->getObject()); qConvDebug() << ret; dist = 0; } else { @@ -601,7 +601,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type } } else if (type == Null) { QObject* nullobj = 0; - ret = qVariantFromValue(nullobj); + ret = QVariant::fromValue(nullobj); dist = 0; } else { qConvDebug() << "previous type was not an object:" << type; @@ -614,7 +614,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type if (qtinst) { if (qtinst->getObject()) { qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject(); - ret = qVariantFromValue((void *)qtinst->getObject()); + ret = QVariant::fromValue((void *)qtinst->getObject()); qConvDebug() << ret; dist = 0; } else { @@ -624,7 +624,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type qConvDebug() << "wasn't a qtinstance"; } } else if (type == Null) { - ret = qVariantFromValue((void*)0); + ret = QVariant::fromValue((void*)0); dist = 0; } else if (type == Number) { // I don't think that converting a double to a pointer is a wise diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp index 88c7a1c..9de5c08 100644 --- a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp +++ b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp @@ -101,7 +101,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) // Make sure we get updates for each frame m_videoWidget->installEventFilter(this); - foreach (QWidget* widget, qFindChildren<QWidget*>(m_videoWidget)) + foreach (QWidget* widget, m_videoWidget->findChildren<QWidget*>()) widget->installEventFilter(this); connect(m_mediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)), diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp index 5db94a8..5004b67 100644 --- a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp +++ b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp @@ -185,7 +185,7 @@ void MediaPlayerPrivate::load(const String& url) // Don't set the header if there are no cookies. // This prevents a warning from being emitted. if (!cookies.isEmpty()) - request.setHeader(QNetworkRequest::CookieHeader, qVariantFromValue(cookies)); + request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies)); // Set the refferer, but not when requesting insecure content from a secure page QUrl documentUrl = QUrl(QString(document->documentURI())); diff --git a/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp index e584f97..dcae35f 100644 --- a/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp +++ b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp @@ -306,7 +306,7 @@ public: } Q_INVOKABLE QObjectList myInvokableWithQObjectListArg(const QObjectList &lst) { m_qtFunctionInvoked = 14; - m_actuals << qVariantFromValue(lst); + m_actuals << QVariant::fromValue(lst); return lst; } Q_INVOKABLE QVariant myInvokableWithVariantArg(const QVariant &v) { @@ -321,38 +321,38 @@ public: } Q_INVOKABLE QList<int> myInvokableWithListOfIntArg(const QList<int> &lst) { m_qtFunctionInvoked = 17; - m_actuals << qVariantFromValue(lst); + m_actuals << QVariant::fromValue(lst); return lst; } Q_INVOKABLE QObject* myInvokableWithQObjectStarArg(QObject* obj) { m_qtFunctionInvoked = 18; - m_actuals << qVariantFromValue(obj); + m_actuals << QVariant::fromValue(obj); return obj; } Q_INVOKABLE QBrush myInvokableWithQBrushArg(const QBrush &brush) { m_qtFunctionInvoked = 19; - m_actuals << qVariantFromValue(brush); + m_actuals << QVariant::fromValue(brush); return brush; } Q_INVOKABLE void myInvokableWithBrushStyleArg(Qt::BrushStyle style) { m_qtFunctionInvoked = 43; - m_actuals << qVariantFromValue(style); + m_actuals << QVariant::fromValue(style); } Q_INVOKABLE void myInvokableWithVoidStarArg(void* arg) { m_qtFunctionInvoked = 44; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } Q_INVOKABLE void myInvokableWithAmbiguousArg(int arg) { m_qtFunctionInvoked = 45; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } Q_INVOKABLE void myInvokableWithAmbiguousArg(uint arg) { m_qtFunctionInvoked = 46; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } Q_INVOKABLE void myInvokableWithDefaultArgs(int arg1, const QString &arg2 = "") { m_qtFunctionInvoked = 47; - m_actuals << qVariantFromValue(arg1) << qVariantFromValue(arg2); + m_actuals << QVariant::fromValue(arg1) << qVariantFromValue(arg2); } Q_INVOKABLE QObject& myInvokableReturningRef() { m_qtFunctionInvoked = 48; @@ -364,11 +364,11 @@ public: } Q_INVOKABLE void myInvokableWithPointArg(const QPoint &arg) { const_cast<MyQObject*>(this)->m_qtFunctionInvoked = 50; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } Q_INVOKABLE void myInvokableWithPointArg(const QPointF &arg) { const_cast<MyQObject*>(this)->m_qtFunctionInvoked = 51; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } Q_INVOKABLE void myInvokableWithBoolArg(bool arg) { m_qtFunctionInvoked = 52; @@ -416,7 +416,7 @@ public Q_SLOTS: } void myOverloadedSlot(QObject* arg) { m_qtFunctionInvoked = 41; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } void myOverloadedSlot(bool arg) { m_qtFunctionInvoked = 25; @@ -818,7 +818,7 @@ void tst_QWebFrame::getSetStaticProperty() QCOMPARE(evalJS("myObject.variantProperty === 'bar'"), sTrue); m_myObject->setVariantProperty(42); QCOMPARE(evalJS("myObject.variantProperty === 42"), sTrue); - m_myObject->setVariantProperty(qVariantFromValue(QBrush())); + m_myObject->setVariantProperty(QVariant::fromValue(QBrush())); //XFAIL // QCOMPARE(evalJS("typeof myObject.variantProperty"), sVariant); @@ -1240,7 +1240,7 @@ void tst_QWebFrame::callQtInvokable() /* XFAIL - variant support m_myObject->resetQtFunctionInvoked(); { - m_myObject->setVariantProperty(qVariantFromValue(QBrush())); + m_myObject->setVariantProperty(QVariant::fromValue(QBrush())); QVariant ret = evalJS("myObject.myInvokableWithVariantArg(myObject.variantProperty)"); QVERIFY(ret.isVariant()); QCOMPARE(m_myObject->qtFunctionInvoked(), 15); diff --git a/src/activeqt/container/qaxbase.cpp b/src/activeqt/container/qaxbase.cpp index 7692749..806e2b1 100644 --- a/src/activeqt/container/qaxbase.cpp +++ b/src/activeqt/container/qaxbase.cpp @@ -3540,7 +3540,7 @@ int QAxBase::internalProperty(QMetaObject::Call call, int index, void **v) proptype = 0; } else if (t == QVariant::UserType) { qvar = QVariant(qRegisterMetaType<void*>(prop.typeName()), (void**)v[0]); -// qVariantSetValue(qvar, *(void**)v[0], prop.typeName()); +// qvar.setValue(*(void**)v[0], prop.typeName()); } else { proptype = d->metaObject()->propertyType(propname); qvar = QVariant(t, v[0]); @@ -3628,9 +3628,9 @@ int QAxBase::internalInvoke(QMetaObject::Call call, int index, void **v) if (!qvar.isValid()) { if (type == "IDispatch*") - qVariantSetValue(qvar, *(IDispatch**)v[p+1]); + qvar.setValue(*(IDispatch**)v[p+1]); else if (type == "IUnknown*") - qVariantSetValue(qvar, *(IUnknown**)v[p+1]); + qvar.setValue(*(IUnknown**)v[p+1]); else if (type == "QVariant") qvar = *(QVariant*)v[p + 1]; else if (mo->indexOfEnumerator(type) != -1) @@ -4395,15 +4395,15 @@ QVariant QAxBase::asVariant() const QByteArray cn(className()); if (cn == "QAxObject" || cn == "QAxWidget" || cn == "QAxBase") { if (d->dispatch()) - qVariantSetValue(qvar, d->dispatch()); + qvar.setValue(d->dispatch()); else if (d->ptr) - qVariantSetValue(qvar, d->ptr); + qvar.setValue(d->ptr); } else { cn = cn.mid(cn.lastIndexOf(':') + 1); QObject *object = qObject(); if (QMetaType::type(cn)) qvar = QVariant(qRegisterMetaType<QObject*>(cn + '*'), &object); -// qVariantSetValue(qvar, qObject(), cn + '*'); +// qvar.setValue(qObject(), cn + '*'); } return qvar; diff --git a/src/activeqt/container/qaxwidget.cpp b/src/activeqt/container/qaxwidget.cpp index 7afce5b..d3f736b 100644 --- a/src/activeqt/container/qaxwidget.cpp +++ b/src/activeqt/container/qaxwidget.cpp @@ -1163,7 +1163,7 @@ HRESULT WINAPI QAxClientSite::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPW AX_DEBUG(QAxClientSite::InsertMenus); QMenuBar *mb = menuBar; if (!mb) - mb = qFindChild<QMenuBar*>(widget->window()); + mb = widget->window()->findChild<QMenuBar*>(); if (!mb) return E_NOTIMPL; menuBar = mb; @@ -1309,7 +1309,7 @@ HRESULT WINAPI QAxClientSite::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND m_menuOwner = hwndActiveObject; QMenuBar *mb = menuBar; if (!mb) - mb = qFindChild<QMenuBar*>(widget->window()); + mb = widget->window()->findChild<QMenuBar*>(); if (!mb) return E_NOTIMPL; menuBar = mb; diff --git a/src/activeqt/control/qaxserver.cpp b/src/activeqt/control/qaxserver.cpp index 7728e50..2512f05 100644 --- a/src/activeqt/control/qaxserver.cpp +++ b/src/activeqt/control/qaxserver.cpp @@ -285,7 +285,7 @@ HRESULT UpdateRegistry(BOOL bRegister) |OLEMISC_RECOMPOSEONRESIZE; if (!control) olemisc |= OLEMISC_INVISIBLEATRUNTIME; - else if (qFindChild<QMenuBar*>(object) && !qax_disable_inplaceframe) + else if (object->findChild<QMenuBar*>() && !qax_disable_inplaceframe) olemisc |= OLEMISC_WANTSTOMENUMERGE; settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/."), className + QLatin1String(" Class")); diff --git a/src/activeqt/control/qaxserverbase.cpp b/src/activeqt/control/qaxserverbase.cpp index d8e7ea3..d833228 100644 --- a/src/activeqt/control/qaxserverbase.cpp +++ b/src/activeqt/control/qaxserverbase.cpp @@ -1313,7 +1313,7 @@ bool QAxServerBase::internalCreate() // install an event filter for stock events if (isWidget) { qt.object->installEventFilter(this); - const QList<QWidget*> children = qFindChildren<QWidget*>(qt.object); + const QList<QWidget*> children = qt.object->findChildren<QWidget*>(); QList<QWidget*>::ConstIterator it = children.constBegin(); while (it != children.constEnd()) { (*it)->installEventFilter(this); @@ -2047,10 +2047,10 @@ int QAxServerBase::qt_metacall(QMetaObject::Call call, int index, void **argv) if (vt == QVariant::UserType) { if (ptype.endsWith('*')) { variant = QVariant(QMetaType::type(ptype), (void**)argv[p+1]); - // qVariantSetValue(variant, *(void**)(argv[p + 1]), ptype); + // variant.setValue(*(void**)(argv[p + 1]), ptype); } else { variant = QVariant(QMetaType::type(ptype), argv[p+1]); - // qVariantSetValue(variant, argv[p + 1], ptype); + // variant.setValue(argv[p + 1], ptype); } } else { variant = QVariant(vt, argv[p + 1]); @@ -2537,7 +2537,7 @@ HRESULT WINAPI QAxServerBase::Invoke(DISPID dispidMember, REFIID riid, if (!type.isEmpty() && pvarResult) { if (!varp[0].isValid() && type != "QVariant") varp[0] = QVariant(QMetaType::type(type), argv_pointer); -// qVariantSetValue(varp[0], argv_pointer[0], type); +// varp[0].setValue(argv_pointer[0], type); ok = QVariantToVARIANT(varp[0], *pvarResult, type); } } @@ -3325,7 +3325,7 @@ HRESULT WINAPI QAxServerBase::OnAmbientPropertyChange(DISPID dispID) break; { QVariant qvar = VARIANTToQVariant(var, "QFont", QVariant::Font); - QFont qfont = qVariantValue<QFont>(qvar); + QFont qfont = qvariant_cast<QFont>(qvar); qt.widget->setFont(qfont); } break; @@ -3818,7 +3818,7 @@ HRESULT QAxServerBase::internalActivate() // Gone active by now, take care of UIACTIVATE canTakeFocus = qt.widget->focusPolicy() != Qt::NoFocus && !inDesignMode; if (!canTakeFocus && !inDesignMode) { - QList<QWidget*> widgets = qFindChildren<QWidget*>(qt.widget); + QList<QWidget*> widgets = qt.widget->findChildren<QWidget*>(); for (int w = 0; w < widgets.count(); ++w) { QWidget *widget = widgets[w]; canTakeFocus = widget->focusPolicy() != Qt::NoFocus; @@ -3844,13 +3844,13 @@ HRESULT QAxServerBase::internalActivate() if (m_spInPlaceFrame) { hr = m_spInPlaceFrame->SetActiveObject(this, QStringToBSTR(class_name)); if (!FAILED(hr)) { - menuBar = (qt.widget && !qax_disable_inplaceframe) ? qFindChild<QMenuBar*>(qt.widget) : 0; + menuBar = (qt.widget && !qax_disable_inplaceframe) ? qt.widget->findChild<QMenuBar*>() : 0; if (menuBar && !menuBar->isVisible()) { createMenu(menuBar); menuBar->hide(); menuBar->installEventFilter(this); } - statusBar = qt.widget ? qFindChild<QStatusBar*>(qt.widget) : 0; + statusBar = qt.widget ? qt.widget->findChild<QStatusBar*>() : 0; if (statusBar && !statusBar->isVisible()) { const int index = statusBar->metaObject()->indexOfSignal("messageChanged(QString)"); QMetaObject::connect(statusBar, index, this, -1); diff --git a/src/activeqt/shared/qaxtypes.cpp b/src/activeqt/shared/qaxtypes.cpp index 957733e..6ed9738 100644 --- a/src/activeqt/shared/qaxtypes.cpp +++ b/src/activeqt/shared/qaxtypes.cpp @@ -954,20 +954,20 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint break; case VT_I4: if (type == QVariant::Color || (!type && typeName == "QColor")) - var = qVariantFromValue(OLEColorToQColor(arg.lVal)); + var = QVariant::fromValue(OLEColorToQColor(arg.lVal)); #ifndef QT_NO_CURSOR else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) - var = qVariantFromValue(QCursor(static_cast<Qt::CursorShape>(arg.lVal))); + var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(arg.lVal))); #endif else var = (int)arg.lVal; break; case VT_I4|VT_BYREF: if (type == QVariant::Color || (!type && typeName == "QColor")) - var = qVariantFromValue(OLEColorToQColor((int)*arg.plVal)); + var = QVariant::fromValue(OLEColorToQColor((int)*arg.plVal)); #ifndef QT_NO_CURSOR else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) - var = qVariantFromValue(QCursor(static_cast<Qt::CursorShape>(*arg.plVal))); + var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(*arg.plVal))); #endif else var = (int)*arg.plVal; @@ -992,20 +992,20 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint break; case VT_UI4: if (type == QVariant::Color || (!type && typeName == "QColor")) - var = qVariantFromValue(OLEColorToQColor(arg.ulVal)); + var = QVariant::fromValue(OLEColorToQColor(arg.ulVal)); #ifndef QT_NO_CURSOR else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) - var = qVariantFromValue(QCursor(static_cast<Qt::CursorShape>(arg.ulVal))); + var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(arg.ulVal))); #endif else var = (int)arg.ulVal; break; case VT_UI4|VT_BYREF: if (type == QVariant::Color || (!type && typeName == "QColor")) - var = qVariantFromValue(OLEColorToQColor((uint)*arg.pulVal)); + var = QVariant::fromValue(OLEColorToQColor((uint)*arg.pulVal)); #ifndef QT_NO_CURSOR else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) - var = qVariantFromValue(QCursor(static_cast<Qt::CursorShape>(*arg.pulVal))); + var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(*arg.pulVal))); #endif else var = (int)*arg.pulVal; @@ -1084,20 +1084,20 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint if (disp) disp->QueryInterface(IID_IFont, (void**)&ifont); if (ifont) { - var = qVariantFromValue(IFontToQFont(ifont)); + var = QVariant::fromValue(IFontToQFont(ifont)); ifont->Release(); } else { - var = qVariantFromValue(QFont()); + var = QVariant::fromValue(QFont()); } } else if (type == QVariant::Pixmap || (!type && (typeName == "QPixmap" || typeName == "QPixmap*"))) { IPicture *ipic = 0; if (disp) disp->QueryInterface(IID_IPicture, (void**)&ipic); if (ipic) { - var = qVariantFromValue(IPictureToQPixmap(ipic)); + var = QVariant::fromValue(IPictureToQPixmap(ipic)); ipic->Release(); } else { - var = qVariantFromValue(QPixmap()); + var = QVariant::fromValue(QPixmap()); } } else { #ifdef QAX_SERVER @@ -1118,7 +1118,7 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint #ifndef QAX_SERVER if (typeName == "QVariant") { QAxObject *object = new QAxObject(disp); - var = qVariantFromValue<QAxObject*>(object); + var = QVariant::fromValue<QAxObject*>(object); } else if (typeName != "IDispatch*" && QMetaType::type(typeName)) { QByteArray typeNameStr = QByteArray(typeName); int pIndex = typeName.lastIndexOf('*'); @@ -1145,7 +1145,7 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint unkn = *arg.ppunkVal; else unkn = arg.punkVal; - qVariantSetValue(var, unkn); + var.setValue(unkn); } break; case VT_ARRAY|VT_VARIANT: diff --git a/src/corelib/concurrent/qfuture.h b/src/corelib/concurrent/qfuture.h index 02ae40a..2856f5e 100644 --- a/src/corelib/concurrent/qfuture.h +++ b/src/corelib/concurrent/qfuture.h @@ -210,7 +210,7 @@ public: bool operator==(const QFuture &other) const { return (d == other.d); } bool operator!=(const QFuture &other) const { return (d != other.d); } -#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(Q_CC_XLC) +#if !defined(Q_CC_XLC) template <typename T> QFuture(const QFuture<T> &other) : d(other.d) diff --git a/src/corelib/concurrent/qfuturewatcher.cpp b/src/corelib/concurrent/qfuturewatcher.cpp index d4573c6..21b0789 100644 --- a/src/corelib/concurrent/qfuturewatcher.cpp +++ b/src/corelib/concurrent/qfuturewatcher.cpp @@ -359,6 +359,15 @@ void QFutureWatcherBase::connectNotify(const char * signal) Q_D(QFutureWatcherBase); if (qstrcmp(signal, SIGNAL(resultReadyAt(int))) == 0) d->resultAtConnected.ref(); +#ifndef QT_NO_DEBUG + if (qstrcmp(signal, SIGNAL(finished())) == 0) { + if (futureInterface().isRunning()) { + //connections should be established before calling stFuture to avoid race. + // (The future could finish before the connection is made.) + qWarning("QFutureWatcher::connect: connecting after calling setFuture() is likely to produce race"); + } + } +#endif } void QFutureWatcherBase::disconnectNotify(const char * signal) diff --git a/src/corelib/concurrent/qtconcurrentcompilertest.h b/src/corelib/concurrent/qtconcurrentcompilertest.h index 982a50c..4fbb3d7 100644 --- a/src/corelib/concurrent/qtconcurrentcompilertest.h +++ b/src/corelib/concurrent/qtconcurrentcompilertest.h @@ -51,12 +51,6 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) -#ifdef Q_CC_MSVC -# if _MSC_VER < 1300 -# define QT_CONURRENT_NONSTANDARD_COMPILER -# endif -#endif - #if defined (Q_CC_MSVC) && (_MSC_VER < 1300) # define QT_TYPENAME #else diff --git a/src/corelib/concurrent/qtconcurrentiteratekernel.h b/src/corelib/concurrent/qtconcurrentiteratekernel.h index 23aaae8..29d276b 100644 --- a/src/corelib/concurrent/qtconcurrentiteratekernel.h +++ b/src/corelib/concurrent/qtconcurrentiteratekernel.h @@ -184,12 +184,9 @@ public: #if defined (QT_NO_STL) : begin(_begin), end(_end), current(_begin), currentIndex(0), forIteration(false), progressReportingEnabled(true) -#elif !defined(QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION) +#else : begin(_begin), end(_end), current(_begin), currentIndex(0), forIteration(selectIteration(typename std::iterator_traits<Iterator>::iterator_category())), progressReportingEnabled(true) -#else - : begin(_begin), end(_end), currentIndex(0), - forIteration(selectIteration(std::iterator_category(_begin))), progressReportingEnabled(true) #endif { #if defined (QT_NO_STL) diff --git a/src/corelib/concurrent/qthreadpool.cpp b/src/corelib/concurrent/qthreadpool.cpp index 9e4189e..f25a494 100644 --- a/src/corelib/concurrent/qthreadpool.cpp +++ b/src/corelib/concurrent/qthreadpool.cpp @@ -41,6 +41,7 @@ #include "qthreadpool.h" #include "qthreadpool_p.h" +#include "qelapsedtimer.h" #ifndef QT_NO_THREAD @@ -288,11 +289,21 @@ void QThreadPoolPrivate::reset() isExiting = false; } -void QThreadPoolPrivate::waitForDone() +bool QThreadPoolPrivate::waitForDone(int msecs) { QMutexLocker locker(&mutex); - while (!(queue.isEmpty() && activeThreads == 0)) - noActiveThreads.wait(locker.mutex()); + if (msecs < 0) { + while (!(queue.isEmpty() && activeThreads == 0)) + noActiveThreads.wait(locker.mutex()); + } else { + QElapsedTimer timer; + timer.start(); + int t; + while (!(queue.isEmpty() && activeThreads == 0) && + ((t = msecs - timer.elapsed()) > 0)) + noActiveThreads.wait(locker.mutex(), t); + } + return queue.isEmpty() && activeThreads == 0; } /*! \internal @@ -617,6 +628,23 @@ void QThreadPool::waitForDone() d->reset(); } +/*! + \overload waitForDone() + \since 4.8 + + Waits up to \a msecs milliseconds for all threads to exit and removes all + threads from the thread pool. Returns true if all threads were removed; + otherwise it returns false. +*/ +bool QThreadPool::waitForDone(int msecs) +{ + Q_D(QThreadPool); + bool rc = d->waitForDone(msecs); + if (rc) + d->reset(); + return rc; +} + QT_END_NAMESPACE #endif diff --git a/src/corelib/concurrent/qthreadpool.h b/src/corelib/concurrent/qthreadpool.h index cc1e059..0bd1884 100644 --- a/src/corelib/concurrent/qthreadpool.h +++ b/src/corelib/concurrent/qthreadpool.h @@ -85,6 +85,7 @@ public: void releaseThread(); void waitForDone(); + bool waitForDone(int msecs); }; QT_END_NAMESPACE diff --git a/src/corelib/concurrent/qthreadpool_p.h b/src/corelib/concurrent/qthreadpool_p.h index 8a2cf98..3d2d6be 100644 --- a/src/corelib/concurrent/qthreadpool_p.h +++ b/src/corelib/concurrent/qthreadpool_p.h @@ -82,7 +82,7 @@ public: void startThread(QRunnable *runnable = 0); void reset(); - void waitForDone(); + bool waitForDone(int msecs = -1); bool startFrontRunnable(); void stealRunnable(QRunnable *); diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h index d53504a..e0e946b 100644 --- a/src/corelib/global/qendian.h +++ b/src/corelib/global/qendian.h @@ -89,7 +89,7 @@ template <typename T> inline void qToUnaligned(const T src, uchar *dest) * and return the value in host-endian encoding. * There is no requirement that \a src must be aligned. */ -#if defined Q_CC_MSVC && _MSC_VER < 1300 || defined Q_CC_SUN +#if defined Q_CC_SUN inline quint64 qFromLittleEndian_helper(const uchar *src, quint64 *dest) { return 0 @@ -177,7 +177,7 @@ template <> inline qint16 qFromLittleEndian<qint16>(const uchar *src) * and return the value in host-endian encoding. * There is no requirement that \a src must be aligned. */ -#if defined Q_CC_MSVC && _MSC_VER < 1300 || defined Q_CC_SUN +#if defined Q_CC_SUN inline quint64 qFromBigEndian_helper(const uchar *src, quint64 *dest) { return 0 diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 401af85..c992735 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1984,7 +1984,7 @@ QSysInfo::SymbianVersion QSysInfo::symbianVersion() */ void qt_check_pointer(const char *n, int l) { - qWarning("In file %s, line %d: Out of memory", n, l); + qFatal("In file %s, line %d: Out of memory", n, l); } /* \internal @@ -2215,7 +2215,8 @@ void qt_message_output(QtMsgType msgType, const char *buf) _LIT(format, "[Qt Message] %S"); const int maxBlockSize = 256 - ((const TDesC &)format).Length(); const TPtrC8 ptr(reinterpret_cast<const TUint8*>(buf)); - HBufC* hbuffer = q_check_ptr(HBufC::New(qMin(maxBlockSize, ptr.Length()))); + HBufC* hbuffer = HBufC::New(qMin(maxBlockSize, ptr.Length())); + Q_CHECK_PTR(hbuffer); for (int i = 0; i < ptr.Length(); i += hbuffer->Length()) { hbuffer->Des().Copy(ptr.Mid(i, qMin(maxBlockSize, ptr.Length()-i))); RDebug::Print(format, hbuffer); diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 8f27b03..02196e4 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -44,11 +44,11 @@ #include <stddef.h> -#define QT_VERSION_STR "4.7.0" +#define QT_VERSION_STR "4.8.0" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x040700 +#define QT_VERSION 0x040800 /* can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)) */ @@ -383,31 +383,12 @@ namespace QT_NAMESPACE {} #elif defined(_MSC_VER) # define Q_CC_MSVC -/* proper support of bool for _MSC_VER >= 1100 */ +# define Q_CC_MSVC_NET # define Q_CANNOT_DELETE_CONSTANT # define Q_OUTOFLINE_TEMPLATE inline # define Q_NO_TEMPLATE_FRIENDS -# define QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION -# define Q_ALIGNOF(type) __alignof(type) -# define Q_DECL_ALIGN(n) __declspec(align(n)) - -/* Visual C++.Net issues for _MSC_VER >= 1300 */ -# if _MSC_VER >= 1300 -# define Q_CC_MSVC_NET -# if _MSC_VER < 1310 || (defined(Q_OS_WIN64) && defined(_M_IA64)) -# define Q_TYPENAME -# else -# undef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION -# endif -# else -# define Q_NO_USING_KEYWORD -# define QT_NO_MEMBER_TEMPLATES -# endif -# if _MSC_VER < 1310 -# define QT_NO_QOBJECT_CHECK -# define Q_TYPENAME -# define QT_NO_TEMPLATE_TEMPLATE_PARAMETERS -# endif +# define Q_ALIGNOF(type) __alignof(type) +# define Q_DECL_ALIGN(n) __declspec(align(n)) /* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */ # if defined(__INTEL_COMPILER) # define Q_CC_INTEL @@ -493,6 +474,26 @@ namespace QT_NAMESPACE {} # define QT_NO_ARM_EABI # endif # endif +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403 + /* C++0x features supported in GCC 4.3: */ +# define Q_COMPILER_RVALUE_REFS +# endif +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 + /* C++0x features supported in GCC 4.4: */ +# define Q_COMPILER_VARIADIC_TEMPLATES +# define Q_COMPILER_AUTO_TYPE +# define Q_COMPILER_EXTERN_TEMPLATES +# define Q_COMPILER_DEFAULT_DELETE_MEMBERS +# define Q_COMPILER_CLASS_ENUM +# define Q_COMPILER_INITIALIZER_LISTS +# endif +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 + /* C++0x features supported in GCC 4.5: */ +# define Q_COMPILER_LAMBDA +# define Q_COMPILER_UNICODE_STRINGS +# endif +# endif /* IBM compiler versions are a bit messy. There are actually two products: the C product, and the C++ product. The C++ compiler is always packaged @@ -924,10 +925,10 @@ redefine to built-in booleans to make autotests work properly */ #endif /* - Proper for-scoping in VC++6 and MIPSpro CC + Proper for-scoping in MIPSpro CC */ #ifndef QT_NO_KEYWORDS -# if (defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) && !defined(Q_CC_INTEL)) || defined(Q_CC_MIPS) || (defined(Q_CC_HPACC) && defined(__ia64)) +# if defined(Q_CC_MIPS) || (defined(Q_CC_HPACC) && defined(__ia64)) # define for if(0){}else for # endif #endif @@ -951,7 +952,7 @@ redefine to built-in booleans to make autotests work properly */ # define Q_DECL_DEPRECATED Q_DECL_DEPRECATED #elif (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && (__GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 >= 2))) || defined(Q_CC_RVCT) # define Q_DECL_DEPRECATED __attribute__ ((__deprecated__)) -#elif defined(Q_CC_MSVC) && (_MSC_VER >= 1300) +#elif defined(Q_CC_MSVC) # define Q_DECL_DEPRECATED __declspec(deprecated) # if defined (Q_CC_INTEL) # define Q_DECL_VARIABLE_DEPRECATED @@ -1055,7 +1056,7 @@ redefine to built-in booleans to make autotests work properly */ #else # define QT_FASTCALL #endif -# elif defined(Q_CC_MSVC) && (_MSC_VER > 1300 || defined(Q_CC_INTEL)) +# elif defined(Q_CC_MSVC) # define QT_FASTCALL __fastcall # else # define QT_FASTCALL @@ -1362,15 +1363,22 @@ class QDataStream; # else # define Q_GUI_EXPORT_INLINE inline # endif +# if defined(QT_BUILD_COMPAT_LIB) +# define Q_COMPAT_EXPORT_INLINE Q_COMPAT_EXPORT inline +# else +# define Q_COMPAT_EXPORT_INLINE inline +# endif #elif defined(Q_CC_RVCT) // we force RVCT not to export inlines by passing --visibility_inlines_hidden // so we need to just inline it, rather than exporting and inlining // note: this affects the contents of the DEF files (ie. these functions do not appear) # define Q_CORE_EXPORT_INLINE inline # define Q_GUI_EXPORT_INLINE inline +# define Q_COMPAT_EXPORT_INLINE inline #else # define Q_CORE_EXPORT_INLINE Q_CORE_EXPORT inline # define Q_GUI_EXPORT_INLINE Q_GUI_EXPORT inline +# define Q_COMPAT_EXPORT_INLINE Q_COMPAT_EXPORT inline #endif /* @@ -1702,7 +1710,7 @@ Q_CORE_EXPORT void qBadAlloc(); #ifdef QT_NO_EXCEPTIONS # if defined(QT_NO_DEBUG) -# define Q_CHECK_PTR(p) qt_noop(); +# define Q_CHECK_PTR(p) qt_noop() # else # define Q_CHECK_PTR(p) do {if(!(p))qt_check_pointer(__FILE__,__LINE__);} while (0) # endif @@ -1716,12 +1724,7 @@ inline T *q_check_ptr(T *p) { Q_CHECK_PTR(p); return p; } #if (defined(Q_CC_GNU) && !defined(Q_OS_SOLARIS)) || defined(Q_CC_HPACC) || defined(Q_CC_DIAB) # define Q_FUNC_INFO __PRETTY_FUNCTION__ #elif defined(_MSC_VER) - /* MSVC 2002 doesn't have __FUNCSIG__ nor can it handle QT_STRINGIFY. */ -# if _MSC_VER <= 1300 -# define Q_FUNC_INFO __FILE__ "(line number unavailable)" -# else -# define Q_FUNC_INFO __FUNCSIG__ -# endif +# define Q_FUNC_INFO __FUNCSIG__ #else # if defined(Q_OS_SOLARIS) || defined(Q_CC_XLC) || defined(Q_OS_SYMBIAN) # define Q_FUNC_INFO __FILE__ "(line number unavailable)" @@ -1971,8 +1974,6 @@ static inline bool qIsNull(float f) qIsDetached - data sharing functionality */ -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION - /* The catch-all template. */ @@ -2005,28 +2006,6 @@ public: }; }; -#else - -template <typename T> char QTypeInfoHelper(T*(*)()); -void* QTypeInfoHelper(...); - -template <typename T> inline bool qIsDetached(T &) { return true; } - -template <typename T> -class QTypeInfo -{ -public: - enum { - isPointer = (1 == sizeof(QTypeInfoHelper((T(*)())0))), - isComplex = !isPointer, - isStatic = !isPointer, - isLarge = (sizeof(T)>sizeof(void*)), - isDummy = false - }; -}; - -#endif /* QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION */ - /* Specialize a specific type with: @@ -2043,8 +2022,7 @@ enum { /* TYPEINFO flags */ Q_DUMMY_TYPE = 0x4 }; -#define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \ -template <> \ +#define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \ class QTypeInfo<TYPE > \ { \ public: \ @@ -2058,6 +2036,11 @@ public: \ static inline const char *name() { return #TYPE; } \ } +#define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \ +template<> \ +Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) + + template <typename T> inline void qSwap(T &value1, T &value2) { @@ -2140,10 +2123,6 @@ Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n); # pragma warning(disable: 4231) /* nonstandard extension used : 'extern' before template explicit instantiation */ # pragma warning(disable: 4710) /* function not inlined */ # pragma warning(disable: 4530) /* C++ exception handler used, but unwind semantics are not enabled. Specify -GX */ -# if _MSC_VER < 1300 -# pragma warning(disable: 4284) /* return type for 'type1::operator ->' is 'type2 *' */ - /* (ie; not a UDT or reference to a UDT. Will produce errors if applied using infix notation) */ -# endif # elif defined(Q_CC_BOR) # pragma option -w-inl # pragma option -w-aus @@ -2217,13 +2196,9 @@ public: #define Q_DECLARE_FLAGS(Flags, Enum)\ typedef QFlags<Enum> Flags; -#if defined Q_CC_MSVC && _MSC_VER < 1300 -# define Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) -#else -# define Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) \ +#define Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) \ inline QIncompatibleFlag operator|(Flags::enum_type f1, int f2) \ { return QIncompatibleFlag(int(f1) | f2); } -#endif #define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \ inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) \ @@ -2280,9 +2255,9 @@ template <typename T> inline const QForeachContainer<T> *qForeachContainer(const QForeachContainerBase *base, const T *) { return static_cast<const QForeachContainer<T> *>(base); } -#if (defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) && !defined(Q_CC_INTEL)) || defined(Q_CC_MIPS) +#if defined(Q_CC_MIPS) /* - Proper for-scoping in VC++6 and MIPSpro CC + Proper for-scoping in MIPSpro CC */ # define Q_FOREACH(variable,container) \ if(0){}else \ @@ -2639,12 +2614,6 @@ QT_LICENSED_MODULE(DBus) # define QT_NO_QFUTURE #endif -// MSVC 6.0 and MSVC .NET 2002, can`t handle the map(), etc templates, -// but the QFuture class compiles. -#if (defined(Q_CC_MSVC) && _MSC_VER <= 1300) -# define QT_NO_CONCURRENT -#endif - // gcc 3 version has problems with some of the // map/filter overloads. #if defined(Q_CC_GNU) && (__GNUC__ < 4) @@ -2663,6 +2632,12 @@ QT_LICENSED_MODULE(DBus) # define QT_NO_PROCESS #endif +#if defined (__ELF__) +# if defined (Q_OS_LINUX) || defined (Q_OS_SOLARIS) || defined (Q_OS_FREEBSD) || defined (Q_OS_OPENBSD) || defined (Q_OS_IRIX) +# define Q_OF_ELF +# endif +#endif + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 3952836..a531009 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -534,6 +534,7 @@ public: AA_DontUseNativeMenuBar = 6, AA_MacDontSwapCtrlAndMeta = 7, AA_S60DontConstructApplicationPanes = 8, + AA_X11InitThreads = 9, // Add new attributes before this line AA_AttributeCount diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 5cd7f0e..137da0e 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -156,6 +156,11 @@ whole lifetime. This attribute must be set before QApplication is constructed. + \value AA_X11InitThreads Calls XInitThreads() as part of the QApplication + construction in order to make Xlib calls thread-safe. This + attribute must be set before QApplication is constructed. + + \omitvalue AA_AttributeCount */ diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp index d6b6f11..37a093c 100644 --- a/src/corelib/io/qabstractfileengine.cpp +++ b/src/corelib/io/qabstractfileengine.cpp @@ -41,12 +41,16 @@ #include "qabstractfileengine.h" #include "private/qabstractfileengine_p.h" +#ifdef QT_BUILD_CORE_LIB +#include "private/qresource_p.h" +#endif #include "qdatetime.h" #include "qreadwritelock.h" #include "qvariant.h" // built-in handlers #include "qfsfileengine.h" #include "qdiriterator.h" +#include "qstringbuilder.h" QT_BEGIN_NAMESPACE @@ -94,6 +98,8 @@ QT_BEGIN_NAMESPACE \sa QAbstractFileEngine, QAbstractFileEngine::create() */ +static bool qt_file_engine_handlers_in_use = false; + /* All application-wide handlers are stored in this list. The mutex must be acquired to ensure thread safety. @@ -123,6 +129,7 @@ Q_GLOBAL_STATIC(QAbstractFileEngineHandlerList, fileEngineHandlers) QAbstractFileEngineHandler::QAbstractFileEngineHandler() { QWriteLocker locker(fileEngineHandlerMutex()); + qt_file_engine_handlers_in_use = true; fileEngineHandlers()->prepend(this); } @@ -134,8 +141,12 @@ QAbstractFileEngineHandler::~QAbstractFileEngineHandler() { QWriteLocker locker(fileEngineHandlerMutex()); // Remove this handler from the handler list only if the list is valid. - if (!qt_abstractfileenginehandlerlist_shutDown) - fileEngineHandlers()->removeAll(this); + if (!qt_abstractfileenginehandlerlist_shutDown) { + QAbstractFileEngineHandlerList *handlers = fileEngineHandlers(); + handlers->removeOne(this); + if (handlers->isEmpty()) + qt_file_engine_handlers_in_use = false; + } } /*! @@ -166,33 +177,48 @@ QAbstractFileEngineHandler::~QAbstractFileEngineHandler() */ QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName) { - { + if (qt_file_engine_handlers_in_use) { QReadLocker locker(fileEngineHandlerMutex()); // check for registered handlers that can load the file - for (int i = 0; i < fileEngineHandlers()->size(); i++) { - if (QAbstractFileEngine *ret = fileEngineHandlers()->at(i)->create(fileName)) + QAbstractFileEngineHandlerList *handlers = fileEngineHandlers(); + for (int i = 0; i < handlers->size(); i++) { + if (QAbstractFileEngine *ret = handlers->at(i)->create(fileName)) return ret; } } #ifdef QT_BUILD_CORE_LIB - if (!fileName.startsWith(QLatin1Char('/'))) { - int prefixSeparator = fileName.indexOf(QLatin1Char(':')); - if (prefixSeparator > 1) { - QString prefix = fileName.left(prefixSeparator); - QString fileNameWithoutPrefix = fileName.mid(prefixSeparator + 1).prepend(QLatin1Char('/')); - const QStringList &paths = QDir::searchPaths(prefix); + for (int prefixSeparator = 0; prefixSeparator < fileName.size(); ++prefixSeparator) { + QChar const ch = fileName[prefixSeparator]; + if (ch == QLatin1Char('/')) + break; + + if (ch == QLatin1Char(':')) { + if (prefixSeparator == 0) + return new QResourceFileEngine(fileName); + + if (prefixSeparator == 1) + break; + + const QStringList &paths = QDir::searchPaths(fileName.left(prefixSeparator)); for (int i = 0; i < paths.count(); i++) { - QString path = paths.at(i); - path.append(fileNameWithoutPrefix); - QAbstractFileEngine *engine = create(path); + QAbstractFileEngine *engine = create(paths.at(i) % QLatin1Char('/') % fileName.mid(prefixSeparator + 1)); if (engine && (engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::ExistsFlag)) { return engine; } delete engine; } + + break; } + + // There's no need to fully validate the prefix here. Consulting the + // unicode tables could be expensive and validation is already + // performed in QDir::setSearchPaths. + // + // if (!ch.isLetterOrNumber()) + // break; } #endif diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index 222ba8f..774c4bc 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -85,10 +85,11 @@ public: Qt_4_4 = 10, Qt_4_5 = 11, Qt_4_6 = 12, - Qt_4_7 = Qt_4_6 -#if QT_VERSION >= 0x040800 -#error Add the datastream version for this Qt version + Qt_4_7 = Qt_4_6, Qt_4_8 = Qt_4_7 +#if QT_VERSION >= 0x040900 +#error Add the datastream version for this Qt version + Qt_4_9 = Qt_4_8 #endif }; diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index 093312f..a9d5ad4 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -137,10 +137,8 @@ public: inline QNoDebug &nospace() { return *this; } inline QNoDebug &maybeSpace() { return *this; } -#ifndef QT_NO_MEMBER_TEMPLATES template<typename T> inline QNoDebug &operator<<(const T &) { return *this; } -#endif }; Q_CORE_EXPORT_INLINE QDebug qCritical() { return QDebug(QtCriticalMsg); } @@ -285,11 +283,6 @@ Q_CORE_EXPORT_INLINE QDebug qDebug() { return QDebug(QtDebugMsg); } inline QNoDebug qDebug() { return QNoDebug(); } #define qDebug QT_NO_QDEBUG_MACRO -#ifdef QT_NO_MEMBER_TEMPLATES -template<typename T> -inline QNoDebug operator<<(QNoDebug debug, const T &) { return debug; } -#endif - #endif #if !defined(QT_NO_WARNING_OUTPUT) diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index efcc8f9..426f61e 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -778,6 +778,7 @@ QString QDir::relativeFilePath(const QString &fileName) const return result; } +#ifndef QT_NO_DEPRECATED /*! \obsolete @@ -787,6 +788,7 @@ QString QDir::convertSeparators(const QString &pathName) { return toNativeSeparators(pathName); } +#endif /*! \since 4.2 @@ -1854,7 +1856,8 @@ QString QDir::homePath() /*! Returns the absolute path of the system's temporary directory. - On Unix/Linux systems this is usually \c{/tmp}; on Windows this is + On Unix/Linux systems this is the path in the \c TMPDIR environment + variable or \c{/tmp} if \c TMPDIR is not defined. On Windows this is usually the path in the \c TEMP or \c TMP environment variable. Whether a directory separator is added to the end or not, depends on the operating system. diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h index 7e5fbac..9eab24f 100644 --- a/src/corelib/io/qdir.h +++ b/src/corelib/io/qdir.h @@ -128,6 +128,10 @@ public: QDir &operator=(const QDir &); QDir &operator=(const QString &path); +#ifdef Q_COMPILER_RVALUE_REFS + inline QDir &operator=(QDir &&other) + { qSwap(d_ptr, other.d_ptr); return *this; } +#endif void setPath(const QString &path); QString path() const; diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h index f0128b1..aec7543 100644 --- a/src/corelib/io/qfileinfo.h +++ b/src/corelib/io/qfileinfo.h @@ -67,6 +67,10 @@ public: ~QFileInfo(); QFileInfo &operator=(const QFileInfo &fileinfo); +#ifdef Q_COMPILER_RVALUE_REFS + inline QFileInfo&operator=(QFileInfo &&other) + { qSwap(d_ptr, other.d_ptr); return *this; } +#endif bool operator==(const QFileInfo &fileinfo); // 5.0 - remove me bool operator==(const QFileInfo &fileinfo) const; inline bool operator!=(const QFileInfo &fileinfo) { return !(operator==(fileinfo)); } // 5.0 - remove me diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index 249ce0f..71df3c2 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -86,7 +86,8 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths, while (it.hasNext()) { QString path = it.next(); QString normalPath = path; - if ((normalPath.endsWith(QLatin1Char('/')) || normalPath.endsWith(QLatin1Char('\\'))) + if ((normalPath.endsWith(QLatin1Char('/')) && !normalPath.endsWith(QLatin1String(":/"))) + || (normalPath.endsWith(QLatin1Char('\\')) && !normalPath.endsWith(QLatin1String(":\\"))) #ifdef Q_OS_WINCE && normalPath.size() > 1) #else diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index a1ffb81..511a1a6 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -189,9 +189,15 @@ QString QFSFileEnginePrivate::canonicalized(const QString &path) known.insert(path); do { #ifdef Q_OS_WIN - // UNC, skip past the first two elements - if (separatorPos == 0 && tmpPath.startsWith(QLatin1String("//"))) - separatorPos = tmpPath.indexOf(slash, 2); + if (separatorPos == 0) { + if (tmpPath.size() >= 2 && tmpPath.at(0) == slash && tmpPath.at(1) == slash) { + // UNC, skip past the first two elements + separatorPos = tmpPath.indexOf(slash, 2); + } else if (tmpPath.size() >= 3 && tmpPath.at(1) == QLatin1Char(':') && tmpPath.at(2) == slash) { + // volume root, skip since it can not be a symlink + separatorPos = 2; + } + } if (separatorPos != -1) #endif separatorPos = tmpPath.indexOf(slash, separatorPos + 1); @@ -208,6 +214,8 @@ QString QFSFileEnginePrivate::canonicalized(const QString &path) fi.setFile(prefix); if (fi.isSymLink()) { QString target = fi.symLinkTarget(); + if(QFileInfo(target).isRelative()) + target = fi.absolutePath() + slash + target; if (separatorPos != -1) { if (fi.isDir() && !target.endsWith(slash)) target.append(slash); diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index d83f7ee..774932a 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -880,6 +880,9 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const if ((baseName.size() > 0 && baseName.at(0) == QLatin1Char('.')) # if !defined(QWS) && defined(Q_OS_MAC) || _q_isMacHidden(d->filePath) +# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + || d->st.st_flags & UF_HIDDEN +# endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 # endif ) { ret |= HiddenFlag; @@ -1089,7 +1092,8 @@ QString QFSFileEngine::fileName(FileName file) const int size = PATH_CHUNK_SIZE; while (1) { - s = q_check_ptr((char *) ::realloc(s, size)); + s = (char *) ::realloc(s, size); + Q_CHECK_PTR(s); len = ::readlink(d->nativeFilePath.constData(), s, size); if (len < 0) { ::free(s); diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index d5c53bb..c27a424 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -155,6 +155,8 @@ static TRUSTEE_W worldTrusteeW; typedef BOOL (WINAPI *PtrGetUserProfileDirectoryW)(HANDLE, LPWSTR, LPDWORD); static PtrGetUserProfileDirectoryW ptrGetUserProfileDirectoryW = 0; +typedef BOOL (WINAPI *PtrGetVolumePathNamesForVolumeNameW)(LPCWSTR,LPWSTR,DWORD,PDWORD); +static PtrGetVolumePathNamesForVolumeNameW ptrGetVolumePathNamesForVolumeNameW = 0; QT_END_INCLUDE_NAMESPACE @@ -213,6 +215,9 @@ void QFSFileEnginePrivate::resolveLibs() HINSTANCE userenvHnd = QSystemLibrary::load(L"userenv"); if (userenvHnd) ptrGetUserProfileDirectoryW = (PtrGetUserProfileDirectoryW)GetProcAddress(userenvHnd, "GetUserProfileDirectoryW"); + HINSTANCE kernel32 = LoadLibrary(L"kernel32"); + if(kernel32) + ptrGetVolumePathNamesForVolumeNameW = (PtrGetVolumePathNamesForVolumeNameW)GetProcAddress(kernel32, "GetVolumePathNamesForVolumeNameW"); #endif } } @@ -1286,7 +1291,12 @@ static QString readSymLink(const QString &link) REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER*)qMalloc(bufsize); DWORD retsize = 0; if (::DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, 0, 0, rdb, bufsize, &retsize, 0)) { - if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { + if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { + int length = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t); + int offset = rdb->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar_t); + const wchar_t* PathBuffer = &rdb->MountPointReparseBuffer.PathBuffer[offset]; + result = QString::fromWCharArray(PathBuffer, length); + } else if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { int length = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t); int offset = rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t); const wchar_t* PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[offset]; @@ -1298,6 +1308,20 @@ static QString readSymLink(const QString &link) } qFree(rdb); CloseHandle(handle); + +#if !defined(QT_NO_LIBRARY) + QFSFileEnginePrivate::resolveLibs(); + if (ptrGetVolumePathNamesForVolumeNameW) { + QRegExp matchVolName(QLatin1String("^Volume\\{([a-z]|[0-9]|-)+\\}\\\\"), Qt::CaseInsensitive); + if(matchVolName.indexIn(result) == 0) { + DWORD len; + wchar_t buffer[MAX_PATH]; + QString volumeName = result.mid(0, matchVolName.matchedLength()).prepend(QLatin1String("\\\\?\\")); + if(ptrGetVolumePathNamesForVolumeNameW((wchar_t*)volumeName.utf16(), buffer, MAX_PATH, &len) != 0) + result.replace(0,matchVolName.matchedLength(), QString::fromWCharArray(buffer)); + } + } +#endif } #else Q_UNUSED(link); @@ -1549,7 +1573,7 @@ bool QFSFileEnginePrivate::isSymlink() const if (hFind != INVALID_HANDLE_VALUE) { ::FindClose(hFind); if ((findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) - && findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK) { + && (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK || findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT)) { is_link = true; } } @@ -1649,10 +1673,12 @@ QString QFSFileEngine::fileName(FileName file) const if (!isRelativePath()) { #if !defined(Q_OS_WINCE) - if ((d->filePath.size() > 2 && d->filePath.at(1) == QLatin1Char(':') - && d->filePath.at(2) != QLatin1Char('/')) || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt - d->filePath.startsWith(QLatin1Char('/')) // It's a absolute path to the current drive, so \a.txt -> Z:\a.txt - ) { + if (d->filePath.startsWith(QLatin1Char('/')) || // It's a absolute path to the current drive, so \a.txt -> Z:\a.txt + d->filePath.size() == 2 || // It's a drive letter that needs to get a working dir appended + (d->filePath.size() > 2 && d->filePath.at(2) != QLatin1Char('/')) || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt + d->filePath.contains(QLatin1String("/../")) || d->filePath.contains(QLatin1String("/./")) || + d->filePath.endsWith(QLatin1String("/..")) || d->filePath.endsWith(QLatin1String("/."))) + { ret = QDir::fromNativeSeparators(nativeAbsoluteFilePath(d->filePath)); } else { ret = d->filePath; diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 26e587d..8544fba 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -1633,6 +1633,12 @@ QString QIODevice::errorString() const This function is called by QIODevice. Reimplement this function when creating a subclass of QIODevice. + When reimplementing this function it is important that this function + reads all the required data before returning. This is required in order + for QDataStream to be able to operate on the class. QDataStream assumes + all the requested information was read and therefore does not retry reading + if there was a problem. + \sa read() readLine() writeData() */ @@ -1645,6 +1651,12 @@ QString QIODevice::errorString() const This function is called by QIODevice. Reimplement this function when creating a subclass of QIODevice. + When reimplementing this function it is important that this function + writes all the data available before returning. This is required in order + for QDataStream to be able to operate on the class. QDataStream assumes + all the information was written and therefore does not retry writing if + there was a problem. + \sa read() write() */ diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index ce9c57e..929885c 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -1185,21 +1185,6 @@ QResource::unregisterResource(const uchar *rccData, const QString &resourceRoot) return false; } -//file type handler -class QResourceFileEngineHandler : public QAbstractFileEngineHandler -{ -public: - QResourceFileEngineHandler() { } - ~QResourceFileEngineHandler() { } - QAbstractFileEngine *create(const QString &path) const; -}; -QAbstractFileEngine *QResourceFileEngineHandler::create(const QString &path) const -{ - if (path.size() > 0 && path.startsWith(QLatin1Char(':'))) - return new QResourceFileEngine(path); - return 0; -} - //resource engine class QResourceFileEnginePrivate : public QAbstractFileEnginePrivate { @@ -1506,12 +1491,6 @@ bool QResourceFileEnginePrivate::unmap(uchar *ptr) return true; } -//Initialization and cleanup -Q_GLOBAL_STATIC(QResourceFileEngineHandler, resource_file_handler) - -static int qt_force_resource_init() { resource_file_handler(); return 1; } -Q_CORE_EXPORT void qInitResourceIO() { resource_file_handler(); } -static int qt_forced_resource_init = qt_force_resource_init(); -Q_CONSTRUCTOR_FUNCTION(qt_force_resource_init) +Q_CORE_EXPORT void qInitResourceIO() { } // ### Qt 5: remove QT_END_NAMESPACE diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index edd6d2b..f25c272 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -252,9 +252,7 @@ bool QConfFile::isWritable() const } else { // Create the directories to the file. QDir dir(fileInfo.absolutePath()); - if (dir.exists() && dir.isReadable()) { - return true; - } else { + if (!dir.exists()) { if (!dir.mkpath(dir.absolutePath())) return false; } diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index d1fab2d..b122cd2 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -966,14 +966,14 @@ static void QT_FASTCALL _fragment(const char **ptr, QUrlParseData *parseData) } struct NameprepCaseFoldingEntry { - int uc; + uint uc; ushort mapping[4]; }; -inline bool operator<(int one, const NameprepCaseFoldingEntry &other) +inline bool operator<(uint one, const NameprepCaseFoldingEntry &other) { return one < other.uc; } -inline bool operator<(const NameprepCaseFoldingEntry &one, int other) +inline bool operator<(const NameprepCaseFoldingEntry &one, uint other) { return one.uc < other; } static const NameprepCaseFoldingEntry NameprepCaseFolding[] = { @@ -1862,45 +1862,44 @@ static const NameprepCaseFoldingEntry NameprepCaseFolding[] = { { 0xFF38, { 0xFF58, 0x0000, 0x0000, 0x0000 } }, { 0xFF39, { 0xFF59, 0x0000, 0x0000, 0x0000 } }, { 0xFF3A, { 0xFF5A, 0x0000, 0x0000, 0x0000 } }, - // ##### -/* { 0x10400, { 0x10428, 0x0000, 0x0000, 0x0000 } }, - { 0x10401, { 0x10429, 0x0000, 0x0000, 0x0000 } }, - { 0x10402, { 0x1042A, 0x0000, 0x0000, 0x0000 } }, - { 0x10403, { 0x1042B, 0x0000, 0x0000, 0x0000 } }, - { 0x10404, { 0x1042C, 0x0000, 0x0000, 0x0000 } }, - { 0x10405, { 0x1042D, 0x0000, 0x0000, 0x0000 } }, - { 0x10406, { 0x1042E, 0x0000, 0x0000, 0x0000 } }, - { 0x10407, { 0x1042F, 0x0000, 0x0000, 0x0000 } }, - { 0x10408, { 0x10430, 0x0000, 0x0000, 0x0000 } }, - { 0x10409, { 0x10431, 0x0000, 0x0000, 0x0000 } }, - { 0x1040A, { 0x10432, 0x0000, 0x0000, 0x0000 } }, - { 0x1040B, { 0x10433, 0x0000, 0x0000, 0x0000 } }, - { 0x1040C, { 0x10434, 0x0000, 0x0000, 0x0000 } }, - { 0x1040D, { 0x10435, 0x0000, 0x0000, 0x0000 } }, - { 0x1040E, { 0x10436, 0x0000, 0x0000, 0x0000 } }, - { 0x1040F, { 0x10437, 0x0000, 0x0000, 0x0000 } }, - { 0x10410, { 0x10438, 0x0000, 0x0000, 0x0000 } }, - { 0x10411, { 0x10439, 0x0000, 0x0000, 0x0000 } }, - { 0x10412, { 0x1043A, 0x0000, 0x0000, 0x0000 } }, - { 0x10413, { 0x1043B, 0x0000, 0x0000, 0x0000 } }, - { 0x10414, { 0x1043C, 0x0000, 0x0000, 0x0000 } }, - { 0x10415, { 0x1043D, 0x0000, 0x0000, 0x0000 } }, - { 0x10416, { 0x1043E, 0x0000, 0x0000, 0x0000 } }, - { 0x10417, { 0x1043F, 0x0000, 0x0000, 0x0000 } }, - { 0x10418, { 0x10440, 0x0000, 0x0000, 0x0000 } }, - { 0x10419, { 0x10441, 0x0000, 0x0000, 0x0000 } }, - { 0x1041A, { 0x10442, 0x0000, 0x0000, 0x0000 } }, - { 0x1041B, { 0x10443, 0x0000, 0x0000, 0x0000 } }, - { 0x1041C, { 0x10444, 0x0000, 0x0000, 0x0000 } }, - { 0x1041D, { 0x10445, 0x0000, 0x0000, 0x0000 } }, - { 0x1041E, { 0x10446, 0x0000, 0x0000, 0x0000 } }, - { 0x1041F, { 0x10447, 0x0000, 0x0000, 0x0000 } }, - { 0x10420, { 0x10448, 0x0000, 0x0000, 0x0000 } }, - { 0x10421, { 0x10449, 0x0000, 0x0000, 0x0000 } }, - { 0x10422, { 0x1044A, 0x0000, 0x0000, 0x0000 } }, - { 0x10423, { 0x1044B, 0x0000, 0x0000, 0x0000 } }, - { 0x10424, { 0x1044C, 0x0000, 0x0000, 0x0000 } }, - { 0x10425, { 0x1044D, 0x0000, 0x0000, 0x0000 } },*/ + { 0x10400, { 0xd801, 0xdc28, 0x0000, 0x0000 } }, + { 0x10401, { 0xd801, 0xdc29, 0x0000, 0x0000 } }, + { 0x10402, { 0xd801, 0xdc2A, 0x0000, 0x0000 } }, + { 0x10403, { 0xd801, 0xdc2B, 0x0000, 0x0000 } }, + { 0x10404, { 0xd801, 0xdc2C, 0x0000, 0x0000 } }, + { 0x10405, { 0xd801, 0xdc2D, 0x0000, 0x0000 } }, + { 0x10406, { 0xd801, 0xdc2E, 0x0000, 0x0000 } }, + { 0x10407, { 0xd801, 0xdc2F, 0x0000, 0x0000 } }, + { 0x10408, { 0xd801, 0xdc30, 0x0000, 0x0000 } }, + { 0x10409, { 0xd801, 0xdc31, 0x0000, 0x0000 } }, + { 0x1040A, { 0xd801, 0xdc32, 0x0000, 0x0000 } }, + { 0x1040B, { 0xd801, 0xdc33, 0x0000, 0x0000 } }, + { 0x1040C, { 0xd801, 0xdc34, 0x0000, 0x0000 } }, + { 0x1040D, { 0xd801, 0xdc35, 0x0000, 0x0000 } }, + { 0x1040E, { 0xd801, 0xdc36, 0x0000, 0x0000 } }, + { 0x1040F, { 0xd801, 0xdc37, 0x0000, 0x0000 } }, + { 0x10410, { 0xd801, 0xdc38, 0x0000, 0x0000 } }, + { 0x10411, { 0xd801, 0xdc39, 0x0000, 0x0000 } }, + { 0x10412, { 0xd801, 0xdc3A, 0x0000, 0x0000 } }, + { 0x10413, { 0xd801, 0xdc3B, 0x0000, 0x0000 } }, + { 0x10414, { 0xd801, 0xdc3C, 0x0000, 0x0000 } }, + { 0x10415, { 0xd801, 0xdc3D, 0x0000, 0x0000 } }, + { 0x10416, { 0xd801, 0xdc3E, 0x0000, 0x0000 } }, + { 0x10417, { 0xd801, 0xdc3F, 0x0000, 0x0000 } }, + { 0x10418, { 0xd801, 0xdc40, 0x0000, 0x0000 } }, + { 0x10419, { 0xd801, 0xdc41, 0x0000, 0x0000 } }, + { 0x1041A, { 0xd801, 0xdc42, 0x0000, 0x0000 } }, + { 0x1041B, { 0xd801, 0xdc43, 0x0000, 0x0000 } }, + { 0x1041C, { 0xd801, 0xdc44, 0x0000, 0x0000 } }, + { 0x1041D, { 0xd801, 0xdc45, 0x0000, 0x0000 } }, + { 0x1041E, { 0xd801, 0xdc46, 0x0000, 0x0000 } }, + { 0x1041F, { 0xd801, 0xdc47, 0x0000, 0x0000 } }, + { 0x10420, { 0xd801, 0xdc48, 0x0000, 0x0000 } }, + { 0x10421, { 0xd801, 0xdc49, 0x0000, 0x0000 } }, + { 0x10422, { 0xd801, 0xdc4A, 0x0000, 0x0000 } }, + { 0x10423, { 0xd801, 0xdc4B, 0x0000, 0x0000 } }, + { 0x10424, { 0xd801, 0xdc4C, 0x0000, 0x0000 } }, + { 0x10425, { 0xd801, 0xdc4D, 0x0000, 0x0000 } }, { 0x1D400, { 0x0061, 0x0000, 0x0000, 0x0000 } }, { 0x1D401, { 0x0062, 0x0000, 0x0000, 0x0000 } }, { 0x1D402, { 0x0063, 0x0000, 0x0000, 0x0000 } }, @@ -2355,17 +2354,23 @@ static void mapToLowerCase(QString *str, int from) { int N = sizeof(NameprepCaseFolding) / sizeof(NameprepCaseFolding[0]); - QChar *d = 0; + ushort *d = 0; for (int i = from; i < str->size(); ++i) { - int uc = str->at(i).unicode(); + uint uc = str->at(i).unicode(); if (uc < 0x80) { if (uc <= 'Z' && uc >= 'A') { - uc |= 0x20; if (!d) - d = str->data(); - d[i] = QChar(uc); + d = reinterpret_cast<ushort *>(str->data()); + d[i] = (uc | 0x20); } } else { + if (QChar(uc).isHighSurrogate() && i < str->size() - 1) { + ushort low = str->at(i + 1).unicode(); + if (QChar(low).isLowSurrogate()) { + uc = QChar::surrogateToUcs4(uc, low); + ++i; + } + } const NameprepCaseFoldingEntry *entry = qBinaryFind(NameprepCaseFolding, NameprepCaseFolding + N, uc); @@ -2374,23 +2379,26 @@ static void mapToLowerCase(QString *str, int from) while (l < 4 && entry->mapping[l]) ++l; if (l > 1) { - str->replace(i, 1, (const QChar *)&entry->mapping[0], l); + if (uc <= 0xffff) + str->replace(i, 1, reinterpret_cast<const QChar *>(&entry->mapping[0]), l); + else + str->replace(i-1, 2, reinterpret_cast<const QChar *>(&entry->mapping[0]), l); d = 0; } else { if (!d) - d = str->data(); - d[i] = QChar(entry->mapping[0]); + d = reinterpret_cast<ushort *>(str->data()); + d[i] = entry->mapping[0]; } } } } } -static bool isMappedToNothing(const QChar &ch) +static bool isMappedToNothing(uint uc) { - if (ch.unicode() < 0xad) + if (uc < 0xad) return false; - switch (ch.unicode()) { + switch (uc) { case 0x00AD: case 0x034F: case 0x1806: case 0x180B: case 0x180C: case 0x180D: case 0x200B: case 0x200C: case 0x200D: case 0x2060: case 0xFE00: case 0xFE01: case 0xFE02: case 0xFE03: case 0xFE04: case 0xFE05: case 0xFE06: case 0xFE07: @@ -2409,66 +2417,72 @@ static void stripProhibitedOutput(QString *str, int from) const ushort *in = out; const ushort *end = (ushort *)str->data() + str->size(); while (in < end) { - ushort uc = *in; - if (uc < 0x80 || - !(uc <= 0x009F - || uc == 0x00A0 - || uc == 0x0340 - || uc == 0x0341 - || uc == 0x06DD - || uc == 0x070F - || uc == 0x1680 - || uc == 0x180E - || (uc >= 0x2000 && uc <= 0x200B) - || uc == 0x200C - || uc == 0x200D - || uc == 0x200E - || uc == 0x200F - || (uc >= 0x2028 && uc <= 0x202F) - || uc == 0x205F - || (uc >= 0x2060 && uc <= 0x2063) - || uc == 0x206A - || (uc >= 0x206A && uc <= 0x206F) - || (uc >= 0x2FF0 && uc <= 0x2FFB) - || uc == 0x3000 - || (uc >= 0xD800 && uc <= 0xDFFF) - || (uc >= 0xE000 && uc <= 0xF8FF) - || (uc >= 0xFDD0 && uc <= 0xFDEF) - || uc == 0xFEFF - || (uc >= 0xFFF9 && uc <= 0xFFFC) - || (uc >= 0xFFFA && (uc <= 0xFFFE || uc == 0xFFFF)) - /* ### Add NAMEPREP support for surrogates - || uc == 0xE0001 - || (uc >= 0x2FFFE && uc <= 0x2FFFF) - || (uc >= 0x1D173 && uc <= 0x1D17A) - || (uc >= 0x1FFFE && uc <= 0x1FFFF) - || (uc >= 0x3FFFE && uc <= 0x3FFFF) - || (uc >= 0x4FFFE && uc <= 0x4FFFF) - || (uc >= 0x5FFFE && uc <= 0x5FFFF) - || (uc >= 0x6FFFE && uc <= 0x6FFFF) - || (uc >= 0x7FFFE && uc <= 0x7FFFF) - || (uc >= 0x8FFFE && uc <= 0x8FFFF) - || (uc >= 0x9FFFE && uc <= 0x9FFFF) - || (uc >= 0xAFFFE && uc <= 0xAFFFF) - || (uc >= 0xBFFFE && uc <= 0xBFFFF) - || (uc >= 0xCFFFE && uc <= 0xCFFFF) - || (uc >= 0xDFFFE && uc <= 0xDFFFF) - || (uc >= 0xE0020 && uc <= 0xE007F) - || (uc >= 0xEFFFE && uc <= 0xEFFFF) - || (uc >= 0xF0000 && uc <= 0xFFFFD) - || (uc >= 0xFFFFE && uc <= 0xFFFFF) - || (uc >= 0x100000 && uc <= 0x10FFFD) - || (uc >= 0x10FFFE && uc <= 0x10FFFF)*/)) - *out++ = *in; + uint uc = *in; + if (QChar(uc).isHighSurrogate() && in < end - 1) { + ushort low = *(in + 1); + if (QChar(low).isLowSurrogate()) { + ++in; + uc = QChar::surrogateToUcs4(uc, low); + } + } + if (uc <= 0xFFFF) { + if (uc < 0x80 || + !(uc <= 0x009F + || uc == 0x00A0 + || uc == 0x0340 + || uc == 0x0341 + || uc == 0x06DD + || uc == 0x070F + || uc == 0x1680 + || uc == 0x180E + || (uc >= 0x2000 && uc <= 0x200F) + || (uc >= 0x2028 && uc <= 0x202F) + || uc == 0x205F + || (uc >= 0x2060 && uc <= 0x2063) + || (uc >= 0x206A && uc <= 0x206F) + || (uc >= 0x2FF0 && uc <= 0x2FFB) + || uc == 0x3000 + || (uc >= 0xD800 && uc <= 0xDFFF) + || (uc >= 0xE000 && uc <= 0xF8FF) + || (uc >= 0xFDD0 && uc <= 0xFDEF) + || uc == 0xFEFF + || (uc >= 0xFFF9 && uc <= 0xFFFF))) { + *out++ = *in; + } + } else { + if (!((uc >= 0x1D173 && uc <= 0x1D17A) + || (uc >= 0x1FFFE && uc <= 0x1FFFF) + || (uc >= 0x2FFFE && uc <= 0x2FFFF) + || (uc >= 0x3FFFE && uc <= 0x3FFFF) + || (uc >= 0x4FFFE && uc <= 0x4FFFF) + || (uc >= 0x5FFFE && uc <= 0x5FFFF) + || (uc >= 0x6FFFE && uc <= 0x6FFFF) + || (uc >= 0x7FFFE && uc <= 0x7FFFF) + || (uc >= 0x8FFFE && uc <= 0x8FFFF) + || (uc >= 0x9FFFE && uc <= 0x9FFFF) + || (uc >= 0xAFFFE && uc <= 0xAFFFF) + || (uc >= 0xBFFFE && uc <= 0xBFFFF) + || (uc >= 0xCFFFE && uc <= 0xCFFFF) + || (uc >= 0xDFFFE && uc <= 0xDFFFF) + || uc == 0xE0001 + || (uc >= 0xE0020 && uc <= 0xE007F) + || (uc >= 0xEFFFE && uc <= 0xEFFFF) + || (uc >= 0xF0000 && uc <= 0xFFFFD) + || (uc >= 0xFFFFE && uc <= 0xFFFFF) + || (uc >= 0x100000 && uc <= 0x10FFFD) + || (uc >= 0x10FFFE && uc <= 0x10FFFF))) { + *out++ = QChar::highSurrogate(uc); + *out++ = QChar::lowSurrogate(uc); + } + } ++in; } if (in != out) str->truncate(out - str->utf16()); } -static bool isBidirectionalRorAL(const QChar &c) +static bool isBidirectionalRorAL(uint uc) { - ushort uc = c.unicode(); if (uc < 0x5b0) return false; return uc == 0x05BE @@ -2507,9 +2521,8 @@ static bool isBidirectionalRorAL(const QChar &c) || (uc >= 0xFE76 && uc <= 0xFEFC); } -static bool isBidirectionalL(const QChar &ch) +static bool isBidirectionalL(uint uc) { - ushort uc = ch.unicode(); if (uc < 0xaa) return (uc >= 0x0041 && uc <= 0x005A) || (uc >= 0x0061 && uc <= 0x007A); @@ -2874,8 +2887,7 @@ static bool isBidirectionalL(const QChar &ch) return true; } - /* ### Add NAMEPREP support for surrogates - || (uc >= 0x10300 && uc <= 0x1031E) + if ((uc >= 0x10300 && uc <= 0x1031E) || (uc >= 0x10320 && uc <= 0x10323) || (uc >= 0x10330 && uc <= 0x1034A) || (uc >= 0x10400 && uc <= 0x10425) @@ -2911,7 +2923,9 @@ static bool isBidirectionalL(const QChar &ch) || (uc >= 0x20000 && uc <= 0x2A6D6) || (uc >= 0x2F800 && uc <= 0x2FA1D) || (uc >= 0xF0000 && uc <= 0xFFFFD) - || (uc >= 0x100000 && uc <= 0x10FFFD)*/ + || (uc >= 0x100000 && uc <= 0x10FFFD)) { + return true; + } return false; } @@ -2944,13 +2958,37 @@ void qt_nameprep(QString *source, int from) return; // everything was mapped easily (lowercased, actually) int firstNonAscii = out - src; + // Characters unassigned in Unicode 3.2 are not allowed in "stored string" scheme + // but allowed in "query" scheme + // (Table A.1) + const bool isUnassignedAllowed = false; // ### // Characters commonly mapped to nothing are simply removed // (Table B.1) const QChar *in = out; - while (in < e) { - if (!isMappedToNothing(*in)) - *out++ = *in; - ++in; + for ( ; in < e; ++in) { + uint uc = in->unicode(); + if (QChar(uc).isHighSurrogate() && in < e - 1) { + ushort low = in[1].unicode(); + if (QChar(low).isLowSurrogate()) { + ++in; + uc = QChar::surrogateToUcs4(uc, low); + } + } + if (!isUnassignedAllowed) { + QChar::UnicodeVersion version = QChar::unicodeVersion(uc); + if (version == QChar::Unicode_Unassigned || version > QChar::Unicode_3_2) { + source->resize(from); // not allowed, clear the label + return; + } + } + if (!isMappedToNothing(uc)) { + if (uc <= 0xFFFF) { + *out++ = *in; + } else { + *out++ = QChar::highSurrogate(uc); + *out++ = QChar::lowSurrogate(uc); + } + } } if (out != in) source->truncate(out - src); @@ -2961,7 +2999,8 @@ void qt_nameprep(QString *source, int from) // Normalize to Unicode 3.2 form KC extern void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::UnicodeVersion version, int from); - qt_string_normalize(source, QString::NormalizationForm_KC, QChar::Unicode_3_2, firstNonAscii); + qt_string_normalize(source, QString::NormalizationForm_KC, QChar::Unicode_3_2, + firstNonAscii > from ? firstNonAscii - 1 : from); // Strip prohibited output stripProhibitedOutput(source, firstNonAscii); @@ -2972,14 +3011,22 @@ void qt_nameprep(QString *source, int from) src = source->data(); e = src + source->size(); for (in = src + from; in < e && (!containsLCat || !containsRandALCat); ++in) { - if (isBidirectionalL(*in)) + uint uc = in->unicode(); + if (QChar(uc).isHighSurrogate() && in < e - 1) { + ushort low = in[1].unicode(); + if (QChar(low).isLowSurrogate()) { + ++in; + uc = QChar::surrogateToUcs4(uc, low); + } + } + if (isBidirectionalL(uc)) containsLCat = true; - else if (isBidirectionalRorAL(*in)) + else if (isBidirectionalRorAL(uc)) containsRandALCat = true; } if (containsRandALCat) { - if (containsLCat || (!isBidirectionalRorAL(src[from]) - || !isBidirectionalRorAL(e[-1]))) + if (containsLCat || (!isBidirectionalRorAL(src[from].unicode()) + || !isBidirectionalRorAL(e[-1].unicode()))) source->resize(from); // not allowed, clear the label } } @@ -6024,19 +6071,22 @@ bool QUrl::isDetached() const /*! - Returns a QUrl representation of \a localFile, interpreted as a - local file. + Returns a QUrl representation of \a localFile, interpreted as a local + file. This function accepts paths separated by slashes as well as the + native separator for this platform. - \sa toLocalFile() + This function also accepts paths with a doubled leading slash (or + backslash) to indicate a remote file, as in + "//servername/path/to/file.txt". Note that only certain platforms can + actually open this file using QFile::open(). + + \sa toLocalFile(), isLocalFile(), QDir::toNativeSeparators */ QUrl QUrl::fromLocalFile(const QString &localFile) { QUrl url; url.setScheme(QLatin1String("file")); - QString deslashified = localFile; - deslashified.replace(QLatin1Char('\\'), QLatin1Char('/')); - - + QString deslashified = QDir::fromNativeSeparators(localFile); // magic for drives on windows if (deslashified.length() > 1 && deslashified.at(1) == QLatin1Char(':') && deslashified.at(0) != QLatin1Char('/')) { @@ -6055,35 +6105,61 @@ QUrl QUrl::fromLocalFile(const QString &localFile) } /*! - Returns the path of this URL formatted as a local file path. + Returns the path of this URL formatted as a local file path. The path + returned will use forward slashes, even if it was originally created + from one with backslashes. - \sa fromLocalFile() + If this URL contains a non-empty hostname, it will be encoded in the + returned value in the form found on SMB networks (for example, + "//servername/path/to/file.txt"). + + \sa fromLocalFile(), isLocalFile() */ QString QUrl::toLocalFile() const { - if (!d) return QString(); - if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); + // the call to isLocalFile() also ensures that we're parsed + if (!isLocalFile()) + return QString(); QString tmp; QString ourPath = path(); - if (d->scheme.isEmpty() || QString::compare(d->scheme, QLatin1String("file"), Qt::CaseInsensitive) == 0) { - // magic for shared drive on windows - if (!d->host.isEmpty()) { - tmp = QLatin1String("//") + d->host + (ourPath.length() > 0 && ourPath.at(0) != QLatin1Char('/') - ? QLatin1Char('/') + ourPath : ourPath); - } else { - tmp = ourPath; - // magic for drives on windows - if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':')) - tmp.remove(0, 1); - } + // magic for shared drive on windows + if (!d->host.isEmpty()) { + tmp = QLatin1String("//") + d->host + (ourPath.length() > 0 && ourPath.at(0) != QLatin1Char('/') + ? QLatin1Char('/') + ourPath : ourPath); + } else { + tmp = ourPath; + // magic for drives on windows + if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':')) + tmp.remove(0, 1); } return tmp; } /*! + \since 4.7 + Returns true if this URL is pointing to a local file path. A URL is a + local file path if the scheme is "file". + + Note that this function considers URLs with hostnames to be local file + paths, even if the eventual file path cannot be opened with + QFile::open(). + + \sa fromLocalFile(), toLocalFile() +*/ +bool QUrl::isLocalFile() const +{ + if (!d) return false; + if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); + + if (d->scheme.compare(QLatin1String("file"), Qt::CaseInsensitive) != 0) + return false; // not file + return true; +} + +/*! Returns true if this URL is a parent of \a childUrl. \a childUrl is a child of this URL if the two URLs share the same scheme and authority, and this URL's path is a parent of the path of \a childUrl. diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h index 6f8331a..563be5f 100644 --- a/src/corelib/io/qurl.h +++ b/src/corelib/io/qurl.h @@ -94,6 +94,10 @@ public: #ifndef QT_NO_URL_CAST_FROM_STRING QUrl &operator =(const QString &url); #endif +#ifdef Q_COMPILER_RVALUE_REFS + inline QUrl &operator=(QUrl &&other) + { qSwap(d, other.d); return *this; } +#endif ~QUrl(); void setUrl(const QString &url); @@ -183,6 +187,7 @@ public: static QUrl fromLocalFile(const QString &localfile); QString toLocalFile() const; + bool isLocalFile() const; QString toString(FormattingOptions options = None) const; diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 9a99ea1..4fc9792 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -532,7 +532,7 @@ bool QAbstractItemModelPrivate::variantLessThan(const QVariant &v1, const QVaria case 1: //floating point return v1.toReal() < v2.toReal(); default: - return v1.toString() < v2.toString(); + return v1.toString().localeAwareCompare(v2.toString()) < 0; } } diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp index 66296b0..df1c1ef 100644 --- a/src/corelib/kernel/qcore_symbian_p.cpp +++ b/src/corelib/kernel/qcore_symbian_p.cpp @@ -61,7 +61,8 @@ Q_CORE_EXPORT HBufC* qt_QString2HBufC(const QString& aString) #else TPtrC16 ptr(qt_QString2TPtrC(aString)); #endif - buffer = q_check_ptr(HBufC::New(ptr.Length())); + buffer = HBufC::New(ptr.Length()); + Q_CHECK_PTR(buffer); buffer->Des().Copy(ptr); return buffer; } @@ -81,8 +82,9 @@ QHBufC::QHBufC() } QHBufC::QHBufC(const QHBufC &src) - : m_hBufC(q_check_ptr(src.m_hBufC->Alloc())) + : m_hBufC(src.m_hBufC->Alloc()) { + Q_CHECK_PTR(m_hBufC); } /*! diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index d3f399b..e967884 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -122,6 +122,11 @@ static SystemDriveFunc PtrGetSystemDrive=0; extern QString qAppFileName(); #endif +int QCoreApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly, but it's at least 4.0.0 +#if defined(QT3_SUPPORT) +bool QCoreApplicationPrivate::useQt3Support = true; +#endif + #if !defined(Q_OS_WIN) #ifdef Q_OS_MAC QString QCoreApplicationPrivate::macMenuBarName() @@ -263,10 +268,14 @@ struct QCoreApplicationData { Q_GLOBAL_STATIC(QCoreApplicationData, coreappdata) -QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv) +QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint flags) : QObjectPrivate(), argc(aargc), argv(aargv), application_type(0), eventFilter(0), in_exec(false), aboutToQuitEmitted(false) { + app_compile_version = flags & 0xffffff; +#if defined(QT3_SUPPORT) + useQt3Support = !(flags & 0x01000000); +#endif static const char *const empty = ""; if (argc == 0 || argv == 0) { argc = 0; @@ -511,7 +520,7 @@ void QCoreApplication::flush() one valid character string. */ QCoreApplication::QCoreApplication(int &argc, char **argv) - : QObject(*new QCoreApplicationPrivate(argc, argv)) + : QObject(*new QCoreApplicationPrivate(argc, argv, 0x040000)) { init(); QCoreApplicationPrivate::eventDispatcher->startingUp(); @@ -527,6 +536,25 @@ QCoreApplication::QCoreApplication(int &argc, char **argv) #endif } +QCoreApplication::QCoreApplication(int &argc, char **argv, int _internal) +: QObject(*new QCoreApplicationPrivate(argc, argv, _internal)) +{ + init(); + QCoreApplicationPrivate::eventDispatcher->startingUp(); +#if defined(Q_OS_SYMBIAN) +#ifndef QT_NO_LIBRARY + // Refresh factoryloader, as text codecs are requested during lib path + // resolving process and won't be therefore properly loaded. + // Unknown if this is symbian specific issue. + QFactoryLoader::refreshAll(); +#endif +#ifndef QT_NO_SYSTEMLOCALE + d_func()->symbianInit(); +#endif +#endif //Q_OS_SYMBIAN +} + + // ### move to QCoreApplicationPrivate constructor? void QCoreApplication::init() { @@ -805,11 +833,6 @@ bool QCoreApplication::notify(QObject *receiver, QEvent *event) d->checkReceiverThread(receiver); #endif -#ifdef QT3_SUPPORT - if (event->type() == QEvent::ChildRemoved && !receiver->d_func()->pendingChildInsertedEvents.isEmpty()) - receiver->d_func()->removePendingChildInsertedEvents(static_cast<QChildEvent *>(event)->child()); -#endif // QT3_SUPPORT - return receiver->isWidgetType() ? false : d->notify_helper(receiver, event); } @@ -1019,6 +1042,7 @@ int QCoreApplication::exec() return returnCode; } + /*! Tells the application to exit with a return code. @@ -1475,7 +1499,7 @@ void QCoreApplication::removePostedEvents(QObject *receiver, int eventType) --pe.receiver->d_func()->postedEvents; #ifdef QT3_SUPPORT if (pe.event->type() == QEvent::ChildInsertedRequest) - pe.receiver->d_func()->removePendingChildInsertedEvents(0); + pe.receiver->d_func()->pendingChildInsertedEvents.clear(); #endif pe.event->posted = false; events.append(pe.event); diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h index d87103e..f1c7c26 100644 --- a/src/corelib/kernel/qcoreapplication.h +++ b/src/corelib/kernel/qcoreapplication.h @@ -78,7 +78,23 @@ class Q_CORE_EXPORT QCoreApplication : public QObject Q_DECLARE_PRIVATE(QCoreApplication) public: - QCoreApplication(int &argc, char **argv); + enum { ApplicationFlags = QT_VERSION +#if !defined(QT3_SUPPORT) + | 0x01000000 +#endif + }; + +#if defined(QT_BUILD_CORE_LIB) || defined(qdoc) + QCoreApplication(int &argc, char **argv); // ### Qt5 remove +#endif +#if !defined(qdoc) + QCoreApplication(int &argc, char **argv, int +#if !defined(QT_BUILD_CORE_LIB) + = ApplicationFlags +#endif + ); +#endif + ~QCoreApplication(); #ifdef QT_DEPRECATED diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index e066137..2355c37 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -75,7 +75,7 @@ class Q_CORE_EXPORT QCoreApplicationPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QCoreApplication) public: - QCoreApplicationPrivate(int &aargc, char **aargv); + QCoreApplicationPrivate(int &aargc, char **aargv, uint flags); ~QCoreApplicationPrivate(); bool sendThroughApplicationEventFilters(QObject *, QEvent *); @@ -129,6 +129,10 @@ public: static uint attribs; static inline bool testAttribute(uint flag) { return attribs & (1 << flag); } + static int app_compile_version; +#if defined(QT3_SUPPORT) + static bool useQt3Support; +#endif }; QT_END_NAMESPACE diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 5cc6ae3..02736dd 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -1013,7 +1013,8 @@ bool QEventDispatcherSymbian::hasPendingEvents() void QEventDispatcherSymbian::registerSocketNotifier ( QSocketNotifier * notifier ) { - QSocketActiveObject *socketAO = q_check_ptr(new QSocketActiveObject(this, notifier)); + QSocketActiveObject *socketAO = new QSocketActiveObject(this, notifier); + Q_CHECK_PTR(socketAO); m_notifiers.insert(notifier, socketAO); selectThread().requestSocketEvents(notifier, &socketAO->iStatus); } diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 9854e68..ceb2a9c 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -266,7 +266,25 @@ QObject *QMetaObject::cast(QObject *obj) const const QMetaObject *m = obj->metaObject(); do { if (m == this) - return const_cast<QObject*>(obj); + return obj; + } while ((m = m->d.superdata)); + } + return 0; +} + +/*! + \internal + + Returns \a obj if object \a obj inherits from this + meta-object; otherwise returns 0. +*/ +const QObject *QMetaObject::cast(const QObject *obj) const +{ + if (obj) { + const QMetaObject *m = obj->metaObject(); + do { + if (m == this) + return obj; } while ((m = m->d.superdata)); } return 0; @@ -1558,6 +1576,12 @@ bool QMetaMethod::invoke(QObject *object, : Qt::QueuedConnection; } +#ifdef QT_NO_THREAD + if (connectionType == Qt::BlockingQueuedConnection) { + connectionType = Qt::DirectConnection; + } +#endif + // invoke! void *param[] = { returnValue.data(), @@ -1576,7 +1600,7 @@ bool QMetaMethod::invoke(QObject *object, int methodIndex = ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset(); if (connectionType == Qt::DirectConnection) { return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, methodIndex, param) < 0; - } else { + } else if (connectionType == Qt::QueuedConnection) { if (returnValue.data()) { qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in " "queued connections"); @@ -1609,40 +1633,21 @@ bool QMetaMethod::invoke(QObject *object, } } - if (connectionType == Qt::QueuedConnection) { - QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, - 0, - -1, - nargs, - types, - args)); - } else { - if (currentThread == objectThread) { - qWarning("QMetaMethod::invoke: Dead lock detected in " - "BlockingQueuedConnection: Receiver is %s(%p)", - mobj->className(), object); - } + QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, + 0, -1, nargs, types, args)); + } else { // blocking queued connection +#ifndef QT_NO_THREAD + if (currentThread == objectThread) { + qWarning("QMetaMethod::invoke: Dead lock detected in " + "BlockingQueuedConnection: Receiver is %s(%p)", + mobj->className(), object); + } - // blocking queued connection -#ifdef QT_NO_THREAD - QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, - 0, - -1, - nargs, - types, - args)); -#else - QSemaphore semaphore; - QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, - 0, - -1, - nargs, - types, - args, - &semaphore)); - semaphore.acquire(); + QSemaphore semaphore; + QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, + 0, -1, 0, 0, param, &semaphore)); + semaphore.acquire(); #endif // QT_NO_THREAD - } } return true; } diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index b700351..8124487 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -138,6 +138,8 @@ private: const QMetaObject *mobj; uint handle; friend struct QMetaObject; + friend struct QMetaObjectPrivate; + friend class QObject; }; Q_DECLARE_TYPEINFO(QMetaMethod, Q_MOVABLE_TYPE); diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 4a03874..40b8715 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -131,6 +131,8 @@ struct QMetaObjectPrivate #ifndef QT_NO_QOBJECT //defined in qobject.cpp enum DisconnectType { DisconnectAll, DisconnectOne }; + static void memberIndexes(const QObject *obj, const QMetaMethod &member, + int *signalIndex, int *methodIndex); static bool connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type = 0, int *types = 0); diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index fef02cf..bb77d2c 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -311,6 +311,7 @@ static const struct { const char * typeName; int typeNameLength; int type; } typ QT_ADD_STATIC_METATYPE("long long", QMetaType::LongLong), QT_ADD_STATIC_METATYPE("unsigned long long", QMetaType::ULongLong), QT_ADD_STATIC_METATYPE("qint8", QMetaType::Char), + QT_ADD_STATIC_METATYPE("signed char", QMetaType::Char), QT_ADD_STATIC_METATYPE("quint8", QMetaType::UChar), QT_ADD_STATIC_METATYPE("qint16", QMetaType::Short), QT_ADD_STATIC_METATYPE("quint16", QMetaType::UShort), diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index e16ffe8..eebb3db 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -353,6 +353,7 @@ Q_DECLARE_BUILTIN_METATYPE(QChar, QChar) Q_DECLARE_BUILTIN_METATYPE(long, Long) Q_DECLARE_BUILTIN_METATYPE(short, Short) Q_DECLARE_BUILTIN_METATYPE(char, Char) +Q_DECLARE_BUILTIN_METATYPE(signed char, Char) Q_DECLARE_BUILTIN_METATYPE(ulong, ULong) Q_DECLARE_BUILTIN_METATYPE(ushort, UShort) Q_DECLARE_BUILTIN_METATYPE(uchar, UChar) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 8330e47..ceffa66 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -149,9 +149,11 @@ QObjectPrivate::QObjectPrivate(int version) postedEvents = 0; extraData = 0; connectedSignals[0] = connectedSignals[1] = 0; - inEventHandler = false; inThreadChangeEvent = false; +#ifdef QT_JAMBI_BUILD + inEventHandler = false; deleteWatch = 0; +#endif metaObject = 0; hasGuards = false; } @@ -159,8 +161,10 @@ QObjectPrivate::QObjectPrivate(int version) QObjectPrivate::~QObjectPrivate() { delete static_cast<QAbstractDynamicMetaObject*>(metaObject); +#ifdef QT_JAMBI_BUILD if (deleteWatch) *deleteWatch = 1; +#endif #ifndef QT_NO_USERDATA if (extraData) qDeleteAll(extraData->userData); @@ -169,6 +173,7 @@ QObjectPrivate::~QObjectPrivate() } +#ifdef QT_JAMBI_BUILD int *QObjectPrivate::setDeleteWatch(QObjectPrivate *d, int *w) { int *old = d->deleteWatch; d->deleteWatch = w; @@ -183,18 +188,15 @@ void QObjectPrivate::resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int dele if (oldWatch) *oldWatch = deleteWatch; } - - - - +#endif #ifdef QT3_SUPPORT void QObjectPrivate::sendPendingChildInsertedEvents() { Q_Q(QObject); for (int i = 0; i < pendingChildInsertedEvents.size(); ++i) { - QObject *c = pendingChildInsertedEvents.at(i); - if (!c) + QObject *c = pendingChildInsertedEvents.at(i).data(); + if (!c || c->parent() != q) continue; QChildEvent childEvent(QEvent::ChildInserted, c); QCoreApplication::sendEvent(q, &childEvent); @@ -202,26 +204,6 @@ void QObjectPrivate::sendPendingChildInsertedEvents() pendingChildInsertedEvents.clear(); } -void QObjectPrivate::removePendingChildInsertedEvents(QObject *child) -{ - if (!child) { - pendingChildInsertedEvents.clear(); - return; - } - - // the QObject destructor calls QObject::removeChild, which calls - // QCoreApplication::sendEvent() directly. this can happen while the event - // loop is in the middle of posting events, and when we get here, we may - // not have any more posted events for this object. - - // if this is a child remove event and the child insert hasn't - // been dispatched yet, kill that insert - for (int i = 0; i < pendingChildInsertedEvents.size(); ++i) { - QObject *&c = pendingChildInsertedEvents[i]; - if (c == child) - c = 0; - } -} #endif @@ -476,11 +458,6 @@ void QMetaObject::changeGuard(QObject **ptr, QObject *o) */ void QObjectPrivate::clearGuards(QObject *object) { - QObjectPrivate *priv = QObjectPrivate::get(object); - - if (!priv->hasGuards) - return; - GuardHash *hash = 0; QMutex *mutex = 0; QT_TRY { @@ -515,12 +492,14 @@ QMetaCallEvent::QMetaCallEvent(int id, const QObject *sender, int signalId, */ QMetaCallEvent::~QMetaCallEvent() { - for (int i = 0; i < nargs_; ++i) { - if (types_[i] && args_[i]) - QMetaType::destroy(types_[i], args_[i]); + if (types_) { + for (int i = 0; i < nargs_; ++i) { + if (types_[i] && args_[i]) + QMetaType::destroy(types_[i], args_[i]); + } + qFree(types_); + qFree(args_); } - if (types_) qFree(types_); - if (args_) qFree(args_); #ifndef QT_NO_THREAD if (semaphore_) semaphore_->release(); @@ -730,13 +709,15 @@ QObject::QObject(QObject *parent) d_ptr->q_ptr = this; d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current(); d->threadData->ref(); - QT_TRY { - if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) - parent = 0; - setParent(parent); - } QT_CATCH(...) { - d->threadData->deref(); - QT_RETHROW; + if (parent) { + QT_TRY { + if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) + parent = 0; + setParent(parent); + } QT_CATCH(...) { + d->threadData->deref(); + QT_RETHROW; + } } qt_addObject(this); } @@ -755,9 +736,11 @@ QObject::QObject(QObject *parent, const char *name) qt_addObject(d_ptr->q_ptr = this); d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current(); d->threadData->ref(); - if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) - parent = 0; - setParent(parent); + if (parent) { + if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) + parent = 0; + setParent(parent); + } setObjectName(QString::fromAscii(name)); } #endif @@ -771,21 +754,23 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent) d_ptr->q_ptr = this; d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current(); d->threadData->ref(); - QT_TRY { - if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) - parent = 0; - if (d->isWidget) { - if (parent) { - d->parent = parent; - d->parent->d_func()->children.append(this); + if (parent) { + QT_TRY { + if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) + parent = 0; + if (d->isWidget) { + if (parent) { + d->parent = parent; + d->parent->d_func()->children.append(this); + } + // no events sent here, this is done at the end of the QWidget constructor + } else { + setParent(parent); } - // no events sent here, this is done at the end of the QWidget constructor - } else { - setParent(parent); + } QT_CATCH(...) { + d->threadData->deref(); + QT_RETHROW; } - } QT_CATCH(...) { - d->threadData->deref(); - QT_RETHROW; } qt_addObject(this); } @@ -820,7 +805,7 @@ QObject::~QObject() d->wasDeleted = true; d->blockSig = 0; // unblock signals so we always emit destroyed() - if (!d->isWidget) { + if (d->hasGuards && !d->isWidget) { // set all QPointers for this object to zero - note that // ~QWidget() does this for us, so we don't have to do it twice QObjectPrivate::clearGuards(this); @@ -838,22 +823,16 @@ QObject::~QObject() delete d->sharedRefcount; } - QT_TRY { - emit destroyed(this); - } QT_CATCH(...) { - // all the signal/slots connections are still in place - if we don't - // quit now, we will crash pretty soon. - qWarning("Detected an unexpected exception in ~QObject while emitting destroyed()."); -#if defined(Q_BUILD_INTERNAL) && !defined(QT_NO_EXCEPTIONS) - struct AutotestException : public std::exception - { - const char *what() const throw() { return "autotest swallow"; } - } autotestException; - // throw autotestException; -#else - QT_RETHROW; -#endif + if (d->isSignalConnected(0)) { + QT_TRY { + emit destroyed(this); + } QT_CATCH(...) { + // all the signal/slots connections are still in place - if we don't + // quit now, we will crash pretty soon. + qWarning("Detected an unexpected exception in ~QObject while emitting destroyed()."); + QT_RETHROW; + } } if (d->declarativeData) @@ -891,7 +870,7 @@ QObject::~QObject() if (c->next) c->next->prev = c->prev; } if (needToUnlock) - m->unlock(); + m->unlockInline(); connectionList.first = c->nextConnectionList; delete c; @@ -915,7 +894,7 @@ QObject::~QObject() bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); //the node has maybe been removed while the mutex was unlocked in relock? if (!node || node->sender != sender) { - m->unlock(); + m->unlockInline(); continue; } node->receiver = 0; @@ -925,7 +904,7 @@ QObject::~QObject() node = node->next; if (needToUnlock) - m->unlock(); + m->unlockInline(); } } @@ -935,12 +914,6 @@ QObject::~QObject() d->threadData->eventDispatcher->unregisterTimers(this); } -#ifdef QT3_SUPPORT - d->pendingChildInsertedEvents.clear(); -#endif - - d->eventFilters.clear(); - if (!d->children.isEmpty()) d->deleteChildren(); @@ -1196,7 +1169,9 @@ bool QObject::event(QEvent *e) case QEvent::MetaCall: { +#ifdef QT_JAMBI_BUILD d_func()->inEventHandler = false; +#endif QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e); QObjectPrivate::Sender currentSender; currentSender.sender = const_cast<QObject*>(mce->sender()); @@ -1514,11 +1489,14 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData currentSender->ref = 0; currentSender = 0; +#ifdef QT_JAMBI_BUILD // the current event thread also shouldn't restore the delete watch inEventHandler = false; + if (deleteWatch) *deleteWatch = 1; deleteWatch = 0; +#endif // set new thread data targetData->ref(); @@ -1768,11 +1746,7 @@ QObjectList QObject::queryList(const char *inheritsClass, \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 11 - \warning This function is not available with MSVC 6. Use - qFindChild() instead if you need to support that version of the - compiler. - - \sa findChildren(), qFindChild() + \sa findChildren() */ /*! @@ -1792,11 +1766,7 @@ QObjectList QObject::queryList(const char *inheritsClass, \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 13 - \warning This function is not available with MSVC 6. Use - qFindChildren() instead if you need to support that version of the - compiler. - - \sa findChild(), qFindChildren() + \sa findChild() */ /*! @@ -1807,20 +1777,19 @@ QObjectList QObject::queryList(const char *inheritsClass, and that have names matching the regular expression \a regExp, or an empty list if there are no such objects. The search is performed recursively. - - \warning This function is not available with MSVC 6. Use - qFindChildren() instead if you need to support that version of the - compiler. */ /*! \fn T qFindChild(const QObject *obj, const QString &name) \relates QObject + \obsolete This function is equivalent to - \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QObject::findChild() */ @@ -1828,11 +1797,14 @@ QObjectList QObject::queryList(const char *inheritsClass, /*! \fn QList<T> qFindChildren(const QObject *obj, const QString &name) \relates QObject + \obsolete This function is equivalent to - \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QObject::findChildren() */ @@ -1843,9 +1815,13 @@ QObjectList QObject::queryList(const char *inheritsClass, \overload qFindChildren() This function is equivalent to - \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a regExp). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a regExp). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. + + \sa QObject::findChildren() */ /*! @@ -1855,9 +1831,11 @@ QObjectList QObject::queryList(const char *inheritsClass, \overload qFindChildren() This function is equivalent to - \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QObject::findChild() */ @@ -1869,9 +1847,11 @@ QObjectList QObject::queryList(const char *inheritsClass, \overload qFindChildren() This function is equivalent to - \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QObject::findChildren() */ @@ -1991,12 +1971,14 @@ void QObjectPrivate::setParent_helper(QObject *o) QChildEvent e(QEvent::ChildAdded, q); QCoreApplication::sendEvent(parent, &e); #ifdef QT3_SUPPORT - if (parent->d_func()->pendingChildInsertedEvents.isEmpty()) { - QCoreApplication::postEvent(parent, - new QEvent(QEvent::ChildInsertedRequest), - Qt::HighEventPriority); + if (QCoreApplicationPrivate::useQt3Support) { + if (parent->d_func()->pendingChildInsertedEvents.isEmpty()) { + QCoreApplication::postEvent(parent, + new QEvent(QEvent::ChildInsertedRequest), + Qt::HighEventPriority); + } + parent->d_func()->pendingChildInsertedEvents.append(q); } - parent->d_func()->pendingChildInsertedEvents.append(q); #endif } } @@ -2305,7 +2287,7 @@ static void err_info_about_objects(const char * func, a thread different from this object's thread. Do not use this function in this type of scenario. - \sa QSignalMapper + \sa senderSignalIndex(), QSignalMapper */ QObject *QObject::sender() const @@ -2316,13 +2298,53 @@ QObject *QObject::sender() const if (!d->currentSender) return 0; - // Return 0 if d->currentSender isn't in d->senders - bool found = false; - for (QObjectPrivate::Connection *c = d->senders; c && !found; c = c->next) - found = (c->sender == d->currentSender->sender); - if (!found) - return 0; - return d->currentSender->sender; + for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) { + if (c->sender == d->currentSender->sender) + return d->currentSender->sender; + } + + return 0; +} + +/*! + \since 4.8 + + Returns the meta-method index of the signal that called the currently + executing slot, which is a member of the class returned by sender(). + If called outside of a slot activated by a signal, -1 is returned. + + For signals with default parameters, this function will always return + the index with all parameters, regardless of which was used with + connect(). For example, the signal \c {destroyed(QObject *obj = 0)} + will have two different indexes (with and without the parameter), but + this function will always return the index with a parameter. This does + not apply when overloading signals with different parameters. + + \warning This function violates the object-oriented principle of + modularity. However, getting access to the signal index might be useful + when many signals are connected to a single slot. + + \warning The return value of this function is not valid when the slot + is called via a Qt::DirectConnection from a thread different from this + object's thread. Do not use this function in this type of scenario. + + \sa sender(), QMetaObject::indexOfSignal(), QMetaObject::method() +*/ + +int QObject::senderSignalIndex() const +{ + Q_D(const QObject); + + QMutexLocker locker(signalSlotLock(this)); + if (!d->currentSender) + return -1; + + for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) { + if (c->sender == d->currentSender->sender) + return d->currentSender->signal; + } + + return -1; } /*! @@ -2384,6 +2406,71 @@ int QObject::receivers(const char *signal) const } /*! + \internal + + This helper function calculates signal and method index for the given + member in the specified class. + + \li If member.mobj is 0 then both signalIndex and methodIndex are set to -1. + + \li If specified member is not a member of obj instance class (or one of + its parent classes) then both signalIndex and methodIndex are set to -1. + + This function is used by QObject::connect and QObject::disconnect which + are working with QMetaMethod. + + \param[out] signalIndex is set to the signal index of member. If the member + specified is not signal this variable is set to -1. + + \param[out] methodIndex is set to the method index of the member. If the + member is not a method of the object specified by obj param this variable + is set to -1. +*/ +void QMetaObjectPrivate::memberIndexes(const QObject *obj, + const QMetaMethod &member, + int *signalIndex, int *methodIndex) +{ + *signalIndex = -1; + *methodIndex = -1; + if (!obj || !member.mobj) + return; + const QMetaObject *m = obj->metaObject(); + // Check that member is member of obj class + while (m != 0 && m != member.mobj) + m = m->d.superdata; + if (!m) + return; + *signalIndex = *methodIndex = (member.handle - get(member.mobj)->methodData)/5; + + int signalOffset; + int methodOffset; + computeOffsets(m, &signalOffset, &methodOffset); + + *methodIndex += methodOffset; + if (member.methodType() == QMetaMethod::Signal) { + *signalIndex = originalClone(m, *signalIndex); + *signalIndex += signalOffset; + } else { + *signalIndex = -1; + } +} + +static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaMethod &signal, + const QMetaObject *receiver, const QMetaMethod &method) +{ + if (signal.attributes() & QMetaMethod::Compatibility) { + if (!(method.attributes() & QMetaMethod::Compatibility)) + qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)", + sender->className(), signal.signature()); + } else if ((method.attributes() & QMetaMethod::Compatibility) && + method.methodType() == QMetaMethod::Signal) { + qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)", + sender->className(), signal.signature(), + receiver->className(), method.signature()); + } +} + +/*! \threadsafe Creates a connection of the given \a type from the \a signal in @@ -2560,7 +2647,7 @@ bool QObject::connect(const QObject *sender, const char *signal, } int *types = 0; - if ((type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection) + if ((type == Qt::QueuedConnection) && !(types = queuedConnectionTypes(smeta->method(signal_absolute_index).parameterTypes()))) return false; @@ -2568,15 +2655,8 @@ bool QObject::connect(const QObject *sender, const char *signal, { QMetaMethod smethod = smeta->method(signal_absolute_index); QMetaMethod rmethod = rmeta->method(method_index); - if (warnCompat) { - if(smethod.attributes() & QMetaMethod::Compatibility) { - if (!(rmethod.attributes() & QMetaMethod::Compatibility)) - qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)", smeta->className(), signal); - } else if(rmethod.attributes() & QMetaMethod::Compatibility && membcode != QSIGNAL_CODE) { - qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)", - smeta->className(), signal, rmeta->className(), method); - } - } + if (warnCompat) + check_and_warn_compat(smeta, smethod, rmeta, rmethod); } #endif if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index, type, types)) @@ -2585,6 +2665,111 @@ bool QObject::connect(const QObject *sender, const char *signal, return true; } +/*! + \since 4.8 + + Creates a connection of the given \a type from the \a signal in + the \a sender object to the \a method in the \a receiver object. + Returns true if the connection succeeds; otherwise returns false. + + This function works in the same way as + connect(const QObject *sender, const char *signal, + const QObject *receiver, const char *method, + Qt::ConnectionType type) + but it uses QMetaMethod to specify signal and method. + + \see connect(const QObject *sender, const char *signal, + const QObject *receiver, const char *method, + Qt::ConnectionType type) + */ +bool QObject::connect(const QObject *sender, const QMetaMethod &signal, + const QObject *receiver, const QMetaMethod &method, + Qt::ConnectionType type) +{ +#ifndef QT_NO_DEBUG + bool warnCompat = true; +#endif + if (type == Qt::AutoCompatConnection) { + type = Qt::AutoConnection; +#ifndef QT_NO_DEBUG + warnCompat = false; +#endif + } + + if (sender == 0 + || receiver == 0 + || signal.methodType() != QMetaMethod::Signal + || method.methodType() == QMetaMethod::Constructor) { + qWarning("QObject::connect: Cannot connect %s::%s to %s::%s", + sender ? sender->metaObject()->className() : "(null)", + signal.signature(), + receiver ? receiver->metaObject()->className() : "(null)", + method.signature() ); + return false; + } + + // Reconstructing SIGNAL() macro result for signal.signature() string + QByteArray signalSignature; + signalSignature.reserve(qstrlen(signal.signature())+1); + signalSignature.append((char)(QSIGNAL_CODE + '0')); + signalSignature.append(signal.signature()); + + { + QByteArray methodSignature; + methodSignature.reserve(qstrlen(method.signature())+1); + methodSignature.append((char)(method.methodType() == QMetaMethod::Slot ? QSLOT_CODE + : method.methodType() == QMetaMethod::Signal ? QSIGNAL_CODE : 0 + '0')); + methodSignature.append(method.signature()); + const void *cbdata[] = { sender, signalSignature.constData(), receiver, methodSignature.constData(), &type }; + if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata)) + return true; + } + + + int signal_index; + int method_index; + { + int dummy; + QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy); + QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index); + } + + const QMetaObject *smeta = sender->metaObject(); + const QMetaObject *rmeta = receiver->metaObject(); + if (signal_index == -1) { + qWarning("QObject::connect: Can't find signal %s on instance of class %s", + signal.signature(), smeta->className()); + return false; + } + if (method_index == -1) { + qWarning("QObject::connect: Can't find method %s on instance of class %s", + method.signature(), rmeta->className()); + return false; + } + + if (!QMetaObject::checkConnectArgs(signal.signature(), method.signature())) { + qWarning("QObject::connect: Incompatible sender/receiver arguments" + "\n %s::%s --> %s::%s", + smeta->className(), signal.signature(), + rmeta->className(), method.signature()); + return false; + } + + int *types = 0; + if ((type == Qt::QueuedConnection) + && !(types = queuedConnectionTypes(signal.parameterTypes()))) + return false; + +#ifndef QT_NO_DEBUG + if (warnCompat) + check_and_warn_compat(smeta, signal, rmeta, method); +#endif + if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index, type, types)) + return false; + + const_cast<QObject*>(sender)->connectNotify(signalSignature.constData()); + return true; +} /*! \fn bool QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type) const @@ -2764,6 +2949,107 @@ bool QObject::disconnect(const QObject *sender, const char *signal, return res; } +/*! + \since 4.8 + + Disconnects \a signal in object \a sender from \a method in object + \a receiver. Returns true if the connection is successfully broken; + otherwise returns false. + + This function provides the same posibilities like + disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method) + but uses QMetaMethod to represent the signal and the method to be disconnected. + + Additionally this function returnsfalse and no signals and slots disconnected + if: + \list 1 + + \i \a signal is not a member of sender class or one of its parent classes. + + \i \a method is not a member of receiver class or one of its parent classes. + + \i \a signal instance represents not a signal. + + \endlist + + QMetaMethod() may be used as wildcard in the meaning "any signal" or "any slot in receiving object". + In the same way 0 can be used for \a receiver in the meaning "any receiving object". In this case + method shoud also be QMetaMethod(). \a sender parameter should be never 0. + + \see disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method) + */ +bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal, + const QObject *receiver, const QMetaMethod &method) +{ + if (sender == 0 || (receiver == 0 && method.mobj != 0)) { + qWarning("Object::disconnect: Unexpected null parameter"); + return false; + } + if (signal.mobj) { + if(signal.methodType() != QMetaMethod::Signal) { + qWarning("Object::%s: Attempt to %s non-signal %s::%s", + "disconnect","unbind", + sender->metaObject()->className(), signal.signature()); + return false; + } + } + if (method.mobj) { + if(method.methodType() == QMetaMethod::Constructor) { + qWarning("QObject::disconect: cannot use constructor as argument %s::%s", + receiver->metaObject()->className(), method.signature()); + return false; + } + } + + // Reconstructing SIGNAL() macro result for signal.signature() string + QByteArray signalSignature; + if (signal.mobj) { + signalSignature.reserve(qstrlen(signal.signature())+1); + signalSignature.append((char)(QSIGNAL_CODE + '0')); + signalSignature.append(signal.signature()); + } + + { + QByteArray methodSignature; + if (method.mobj) { + methodSignature.reserve(qstrlen(method.signature())+1); + methodSignature.append((char)(method.methodType() == QMetaMethod::Slot ? QSLOT_CODE + : method.methodType() == QMetaMethod::Signal ? QSIGNAL_CODE : 0 + '0')); + methodSignature.append(method.signature()); + } + const void *cbdata[] = { sender, signal.mobj ? signalSignature.constData() : 0, + receiver, method.mobj ? methodSignature.constData() : 0 }; + if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata)) + return true; + } + + int signal_index; + int method_index; + { + int dummy; + QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy); + QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index); + } + // If we are here sender is not null. If signal is not null while signal_index + // is -1 then this signal is not a member of sender. + if (signal.mobj && signal_index == -1) { + qWarning("QObject::disconect: signal %s not found on class %s", + signal.signature(), sender->metaObject()->className()); + return false; + } + // If this condition is true then method is not a member of receeiver. + if (receiver && method.mobj && method_index == -1) { + qWarning("QObject::disconect: method %s not found on class %s", + method.signature(), receiver->metaObject()->className()); + return false; + } + + if (!QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index)) + return false; + + const_cast<QObject*>(sender)->disconnectNotify(method.mobj ? signalSignature.constData() : 0); + return true; +} /*! \threadsafe @@ -2981,7 +3267,7 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, } if (needToUnlock) - receiverMutex->unlock(); + receiverMutex->unlockInline(); c->receiver = 0; @@ -3068,7 +3354,7 @@ void QMetaObject::connectSlotsByName(QObject *o) return; const QMetaObject *mo = o->metaObject(); Q_ASSERT(mo); - const QObjectList list = qFindChildren<QObject *>(o, QString()); + const QObjectList list = o->findChildren<QObject *>(QString()); for (int i = 0; i < mo->methodCount(); ++i) { const char *slot = mo->method(i).signature(); Q_ASSERT(slot); @@ -3115,8 +3401,7 @@ void QMetaObject::connectSlotsByName(QObject *o) } } -static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, - void **argv, QSemaphore *semaphore = 0) +static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv) { if (!c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) { QMetaMethod m = sender->metaObject()->method(signal); @@ -3146,30 +3431,9 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect signal, nargs, types, - args, - semaphore)); + args)); } -static void blocking_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv) -{ - if (QThread::currentThread() == c->receiver->thread()) { - qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: " - "Sender is %s(%p), receiver is %s(%p)", - sender->metaObject()->className(), sender, - c->receiver->metaObject()->className(), c->receiver); - } - -#ifdef QT_NO_THREAD - queued_activate(sender, signal, c, argv); -#else - QSemaphore semaphore; - queued_activate(sender, signal, c, argv, &semaphore); - QMutex *mutex = signalSlotLock(sender); - mutex->unlock(); - semaphore.acquire(); - mutex->lock(); -#endif -} /*!\internal \obsolete. @@ -3233,23 +3497,38 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign continue; QObject * const receiver = c->receiver; + const int method = c->method; + const bool receiverInSameThread = currentThreadData == receiver->d_func()->threadData; // determine if this connection should be sent immediately or // put into the event queue if ((c->connectionType == Qt::AutoConnection - && (currentThreadData != sender->d_func()->threadData + && (!receiverInSameThread || receiver->d_func()->threadData != sender->d_func()->threadData)) || (c->connectionType == Qt::QueuedConnection)) { queued_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv); continue; +#ifndef QT_NO_THREAD } else if (c->connectionType == Qt::BlockingQueuedConnection) { - blocking_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv); + locker.unlock(); + if (receiverInSameThread) { + qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: " + "Sender is %s(%p), receiver is %s(%p)", + sender->metaObject()->className(), sender, + receiver->metaObject()->className(), receiver); + } + QSemaphore semaphore; + QCoreApplication::postEvent(receiver, new QMetaCallEvent(method, + sender, signal_absolute_index, + 0, 0, + argv ? argv : empty_argv, + &semaphore)); + semaphore.acquire(); + locker.relock(); continue; +#endif } - - const int method = c->method; QObjectPrivate::Sender currentSender; - const bool receiverInSameThread = currentThreadData == receiver->d_func()->threadData; QObjectPrivate::Sender *previousSender = 0; if (receiverInSameThread) { currentSender.sender = sender; diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index d98d1f0..63fdf76 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -77,19 +77,9 @@ class QObjectUserData; typedef QList<QObject*> QObjectList; -#if defined Q_CC_MSVC && _MSC_VER < 1300 -template<typename T> inline T qFindChild(const QObject *o, const QString &name = QString(), T = 0); -template<typename T> inline QList<T> qFindChildren(const QObject *o, const QString &name = QString(), T = 0); -# ifndef QT_NO_REGEXP -template<typename T> inline QList<T> qFindChildren(const QObject *o, const QRegExp &re, T = 0); -# endif -#else -template<typename T> inline T qFindChild(const QObject *, const QString & = QString()); -template<typename T> inline QList<T> qFindChildren(const QObject *, const QString & = QString()); -# ifndef QT_NO_REGEXP -template<typename T> inline QList<T> qFindChildren(const QObject *, const QRegExp &); -# endif -#endif +Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QRegExp *re, + const QMetaObject &mo, QList<void *> *list); +Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo); class #if defined(__INTEL_COMPILER) && defined(Q_OS_WIN) @@ -109,7 +99,7 @@ public: uint ownObjectName : 1; uint sendChildEvents : 1; uint receiveChildEvents : 1; - uint inEventHandler : 1; + uint inEventHandler : 1; //only used if QT_JAMBI_BUILD uint inThreadChangeEvent : 1; uint hasGuards : 1; //true iff there is one or more QPointer attached to this object uint unused : 22; @@ -164,20 +154,36 @@ public: int startTimer(int interval); void killTimer(int id); -#ifndef QT_NO_MEMBER_TEMPLATES template<typename T> inline T findChild(const QString &aName = QString()) const - { return qFindChild<T>(this, aName); } + { return static_cast<T>(qt_qFindChild_helper(this, aName, reinterpret_cast<T>(0)->staticMetaObject)); } template<typename T> inline QList<T> findChildren(const QString &aName = QString()) const - { return qFindChildren<T>(this, aName); } + { + QList<T> list; + union { + QList<T> *typedList; + QList<void *> *voidList; + } u; + u.typedList = &list; + qt_qFindChildren_helper(this, aName, 0, reinterpret_cast<T>(0)->staticMetaObject, u.voidList); + return list; + } #ifndef QT_NO_REGEXP template<typename T> inline QList<T> findChildren(const QRegExp &re) const - { return qFindChildren<T>(this, re); } -#endif + { + QList<T> list; + union { + QList<T> *typedList; + QList<void *> *voidList; + } u; + u.typedList = &list; + qt_qFindChildren_helper(this, QString(), &re, reinterpret_cast<T>(0)->staticMetaObject, u.voidList); + return list; + } #endif #ifdef QT3_SUPPORT @@ -207,6 +213,21 @@ public: #endif #endif ); + + static bool connect(const QObject *sender, const QMetaMethod &signal, + const QObject *receiver, const QMetaMethod &method, + Qt::ConnectionType type = +#ifdef qdoc + Qt::AutoConnection +#else +#ifdef QT3_SUPPORT + Qt::AutoCompatConnection +#else + Qt::AutoConnection +#endif +#endif + ); + inline bool connect(const QObject *sender, const char *signal, const char *member, Qt::ConnectionType type = #ifdef qdoc @@ -222,6 +243,8 @@ public: static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member); + static bool disconnect(const QObject *sender, const QMetaMethod &signal, + const QObject *receiver, const QMetaMethod &member); inline bool disconnect(const char *signal = 0, const QObject *receiver = 0, const char *member = 0) { return disconnect(this, signal, receiver, member); } @@ -257,6 +280,7 @@ public Q_SLOTS: protected: QObject *sender() const; + int senderSignalIndex() const; int receivers(const char* signal) const; virtual void timerEvent(QTimerEvent *); @@ -321,46 +345,31 @@ public: }; #endif -Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QRegExp *re, - const QMetaObject &mo, QList<void *> *list); -Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo); - +#ifdef QT_DEPRECATED template<typename T> -inline T qFindChild(const QObject *o, const QString &name) -{ return static_cast<T>(qt_qFindChild_helper(o, name, reinterpret_cast<T>(0)->staticMetaObject)); } +inline QT_DEPRECATED T qFindChild(const QObject *o, const QString &name = QString()) +{ return o->findChild<T>(name); } template<typename T> -inline QList<T> qFindChildren(const QObject *o, const QString &name) +inline QT_DEPRECATED QList<T> qFindChildren(const QObject *o, const QString &name = QString()) { - QList<T> list; - union { - QList<T> *typedList; - QList<void *> *voidList; - } u; - u.typedList = &list; - qt_qFindChildren_helper(o, name, 0, reinterpret_cast<T>(0)->staticMetaObject, u.voidList); - return list; + return o->findChildren<T>(name); } #ifndef QT_NO_REGEXP template<typename T> -inline QList<T> qFindChildren(const QObject *o, const QRegExp &re) +inline QT_DEPRECATED QList<T> qFindChildren(const QObject *o, const QRegExp &re) { - QList<T> list; - union { - QList<T> *typedList; - QList<void *> *voidList; - } u; - u.typedList = &list; - qt_qFindChildren_helper(o, QString(), &re, reinterpret_cast<T>(0)->staticMetaObject, u.voidList); - return list; + return o->findChildren<T>(re); } #endif +#endif //QT_DEPRECATED + template <class T> inline T qobject_cast(QObject *object) { -#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(QT_NO_QOBJECT_CHECK) +#if !defined(QT_NO_QOBJECT_CHECK) reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(object)); #endif return static_cast<T>(reinterpret_cast<T>(0)->staticMetaObject.cast(object)); @@ -369,14 +378,10 @@ inline T qobject_cast(QObject *object) template <class T> inline T qobject_cast(const QObject *object) { - // this will cause a compilation error if T is not const - register T ptr = static_cast<T>(object); - Q_UNUSED(ptr); - -#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(QT_NO_QOBJECT_CHECK) +#if !defined(QT_NO_QOBJECT_CHECK) reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(const_cast<QObject *>(object))); #endif - return static_cast<T>(const_cast<QObject *>(reinterpret_cast<T>(0)->staticMetaObject.cast(const_cast<QObject *>(object)))); + return static_cast<T>(reinterpret_cast<T>(0)->staticMetaObject.cast(object)); } diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 4800e6a..82023d4 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -55,6 +55,7 @@ #include "QtCore/qobject.h" #include "QtCore/qpointer.h" +#include "QtCore/qsharedpointer.h" #include "QtCore/qcoreevent.h" #include "QtCore/qlist.h" #include "QtCore/qvector.h" @@ -153,7 +154,6 @@ public: #ifdef QT3_SUPPORT void sendPendingChildInsertedEvents(); - void removePendingChildInsertedEvents(QObject *child); #endif static inline Sender *setCurrentSender(QObject *receiver, @@ -161,8 +161,10 @@ public: static inline void resetCurrentSender(QObject *receiver, Sender *currentSender, Sender *previousSender); +#ifdef QT_JAMBI_BUILD static int *setDeleteWatch(QObjectPrivate *d, int *newWatch); static void resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch); +#endif static void clearGuards(QObject *); static QObjectPrivate *get(QObject *o) { @@ -184,7 +186,7 @@ public: mutable quint32 connectedSignals[2]; #ifdef QT3_SUPPORT - QList<QObject *> pendingChildInsertedEvents; + QVector< QWeakPointer<QObject> > pendingChildInsertedEvents; #else // preserve binary compatibility with code compiled without Qt 3 support // keeping the binary layout stable helps the Qt Creator debugger @@ -200,7 +202,9 @@ public: // these objects are all used to indicate that a QObject was deleted // plus QPointer, which keeps a separate list QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount; +#ifdef QT_JAMBI_BUILD int *deleteWatch; +#endif }; diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 555a1f5..db46ba5 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -117,7 +117,7 @@ class QString; # define QT_TR_FUNCTIONS #endif -#if defined(QT_NO_MEMBER_TEMPLATES) || defined(QT_NO_QOBJECT_CHECK) +#if defined(QT_NO_QOBJECT_CHECK) /* tmake ignore Q_OBJECT */ #define Q_OBJECT_CHECK #else @@ -144,7 +144,7 @@ inline int qYouForgotTheQ_OBJECT_Macro(T, T) { return 0; } template <typename T1, typename T2> inline void qYouForgotTheQ_OBJECT_Macro(T1, T2) {} -#endif // QT_NO_MEMBER_TEMPLATES +#endif // QT_NO_QOBJECT_CHECK #ifdef Q_NO_DATA_RELOCATION #define Q_OBJECT_GETSTATICMETAOBJECT static const QMetaObject &getStaticMetaObject(); @@ -298,6 +298,7 @@ struct Q_CORE_EXPORT QMetaObject const QMetaObject *superClass() const; QObject *cast(QObject *obj) const; + const QObject *cast(const QObject *obj) const; #ifndef QT_NO_TRANSLATION // ### Qt 4: Merge overloads diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp index fe93ebc..0782ffe 100644 --- a/src/corelib/kernel/qsharedmemory.cpp +++ b/src/corelib/kernel/qsharedmemory.cpp @@ -142,9 +142,12 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, remain. Do not mix using QtSharedMemory and QSharedMemory. Port everything to QSharedMemory. - \warning QSharedMemory changes the key in a Qt-specific way. - It is therefore currently not possible to use the shared memory of - non-Qt applications with QSharedMemory. + \warning QSharedMemory changes the key in a Qt-specific way, unless otherwise + specified. Interoperation with non-Qt applications is achieved by first creating + a default shared memory with QSharedMemory() and then setting a native key with + setNativeKey(). When using native keys, shared memory is not protected against + multiple accesses on it (e.g. unable to lock()) and a user-defined mechanism + should be used to achieve a such protection. */ /*! @@ -153,8 +156,8 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, Constructs a shared memory object with the given \a parent. The shared memory object's key is not set by the constructor, so the shared memory object does not have an underlying shared memory - segment attached. The key must be set with setKey() before create() - or attach() can be used. + segment attached. The key must be set with setKey() or setNativeKey() + before create() or attach() can be used. \sa setKey() */ @@ -191,24 +194,62 @@ QSharedMemory::~QSharedMemory() } /*! - Sets a new \a key for this shared memory object. If \a key and the - current key are the same, the function returns without doing - anything. If the shared memory object is attached to an underlying - shared memory segment, it will \l {detach()} {detach} from it before - setting the new key. This function does not do an attach(). + Sets the platform independent \a key for this shared memory object. If \a key + is the same as the current key, the function returns without doing anything. - \sa key() isAttached() - */ + You can call key() to retrieve the platform independent key. Internally, + QSharedMemory converts this key into a platform specific key. If you instead + call nativeKey(), you will get the platform specific, converted key. + + If the shared memory object is attached to an underlying shared memory + segment, it will \l {detach()} {detach} from it before setting the new key. + This function does not do an attach(). + + \sa key() nativeKey() isAttached() +*/ void QSharedMemory::setKey(const QString &key) { Q_D(QSharedMemory); - if (key == d->key) + if (key == d->key && d->makePlatformSafeKey(key) == d->nativeKey) return; if (isAttached()) detach(); d->cleanHandle(); d->key = key; + d->nativeKey = d->makePlatformSafeKey(key); +} + +/*! + \since 4.8 + + Sets the native, platform specific, \a key for this shared memory object. If + \a key is the same as the current native key, the function returns without + doing anything. If all you want is to assign a key to a segment, you should + call setKey() instead. + + You can call nativeKey() to retrieve the native key. If a native key has been + assigned, calling key() will return a null string. + + If the shared memory object is attached to an underlying shared memory + segment, it will \l {detach()} {detach} from it before setting the new key. + This function does not do an attach(). + + The application will not be portable if you set a native key. + + \sa nativeKey() key() isAttached() +*/ +void QSharedMemory::setNativeKey(const QString &key) +{ + Q_D(QSharedMemory); + if (key == d->nativeKey && d->key.isNull()) + return; + + if (isAttached()) + detach(); + d->cleanHandle(); + d->key = QString(); + d->nativeKey = key; } bool QSharedMemoryPrivate::initKey() @@ -251,13 +292,15 @@ bool QSharedMemoryPrivate::initKey() } /*! - Returns the key assigned to this shared memory. The key is the - identifier used by the operating system to identify the shared - memory segment. When QSharedMemory is used for interprocess - communication, the key is how each process attaches to the shared - memory segment through which the IPC occurs. + Returns the key assigned with setKey() to this shared memory, or a null key + if no key has been assigned, or if the segment is using a nativeKey(). The + key is the identifier used by Qt applications to identify the shared memory + segment. + + You can find the native, platform specific, key used by the operating system + by calling nativeKey(). - \sa setKey() + \sa setKey() setNativeKey() */ QString QSharedMemory::key() const { @@ -266,13 +309,30 @@ QString QSharedMemory::key() const } /*! - Creates a shared memory segment of \a size bytes with the key passed - to the constructor or set with setKey(), attaches to the new shared - memory segment with the given access \a mode, and returns \tt true. - If a shared memory segment identified by the key already exists, the - attach operation is not performed, and \tt false is returned. When - the return value is \tt false, call error() to determine which error - occurred. + \since 4.8 + + Returns the native, platform specific, key for this shared memory object. The + native key is the identifier used by the operating system to identify the + shared memory segment. + + You can use the native key to access shared memory segments that have not + been created by Qt, or to grant shared memory access to non-Qt applications. + + \sa setKey() setNativeKey() +*/ +QString QSharedMemory::nativeKey() const +{ + Q_D(const QSharedMemory); + return d->nativeKey; +} + +/*! + Creates a shared memory segment of \a size bytes with the key passed to the + constructor, set with setKey() or set with setNativeKey(), then attaches to + the new shared memory segment with the given access \a mode and returns + \tt true. If a shared memory segment identified by the key already exists, + the attach operation is not performed and \tt false is returned. When the + return value is \tt false, call error() to determine which error occurred. \sa error() */ @@ -294,7 +354,7 @@ bool QSharedMemory::create(int size, AccessMode mode) QString function = QLatin1String("QSharedMemory::create"); #ifndef QT_NO_SYSTEMSEMAPHORE QSharedMemoryLocker lock(this); - if (!d->tryLocker(&lock, function)) + if (!d->key.isNull() && !d->tryLocker(&lock, function)) return false; #endif @@ -338,7 +398,7 @@ int QSharedMemory::size() const /*! Attempts to attach the process to the shared memory segment identified by the key that was passed to the constructor or to a - call to setKey(). The access \a mode is \l {QSharedMemory::} + call to setKey() or setNativeKey(). The access \a mode is \l {QSharedMemory::} {ReadWrite} by default. It can also be \l {QSharedMemory::} {ReadOnly}. Returns true if the attach operation is successful. If false is returned, call error() to determine which error occurred. @@ -355,7 +415,7 @@ bool QSharedMemory::attach(AccessMode mode) return false; #ifndef QT_NO_SYSTEMSEMAPHORE QSharedMemoryLocker lock(this); - if (!d->tryLocker(&lock, QLatin1String("QSharedMemory::attach"))) + if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::attach"))) return false; #endif @@ -395,7 +455,7 @@ bool QSharedMemory::detach() #ifndef QT_NO_SYSTEMSEMAPHORE QSharedMemoryLocker lock(this); - if (!d->tryLocker(&lock, QLatin1String("QSharedMemory::detach"))) + if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::detach"))) return false; #endif @@ -451,9 +511,9 @@ const void *QSharedMemory::data() const by this process and returns true. If another process has locked the segment, this function blocks until the lock is released. Then it acquires the lock and returns true. If this function returns false, - it means either that you have ignored a false return from create() - or attach(), or that QSystemSemaphore::acquire() failed due to an - unknown system error. + it means that you have ignored a false return from create() or attach(), + that you have set the key with setNativeKey() or that + QSystemSemaphore::acquire() failed due to an unknown system error. \sa unlock(), data(), QSystemSemaphore::acquire() */ diff --git a/src/corelib/kernel/qsharedmemory.h b/src/corelib/kernel/qsharedmemory.h index fba939c..5673f43 100644 --- a/src/corelib/kernel/qsharedmemory.h +++ b/src/corelib/kernel/qsharedmemory.h @@ -85,6 +85,8 @@ public: void setKey(const QString &key); QString key() const; + void setNativeKey(const QString &key); + QString nativeKey() const; bool create(int size, AccessMode mode = ReadWrite); int size() const; diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h index a52f8b3..632a6e9 100644 --- a/src/corelib/kernel/qsharedmemory_p.h +++ b/src/corelib/kernel/qsharedmemory_p.h @@ -122,6 +122,7 @@ public: void *memory; int size; QString key; + QString nativeKey; QSharedMemory::SharedMemoryError error; QString errorString; #ifndef QT_NO_SYSTEMSEMAPHORE diff --git a/src/corelib/kernel/qsharedmemory_symbian.cpp b/src/corelib/kernel/qsharedmemory_symbian.cpp index 9b84eb56..091c2b5 100644 --- a/src/corelib/kernel/qsharedmemory_symbian.cpp +++ b/src/corelib/kernel/qsharedmemory_symbian.cpp @@ -107,16 +107,14 @@ bool QSharedMemoryPrivate::cleanHandle() bool QSharedMemoryPrivate::create(int size) { - // Get a windows acceptable key - QString safeKey = makePlatformSafeKey(key); QString function = QLatin1String("QSharedMemory::create"); - if (safeKey.isEmpty()) { + if (nativeKey.isEmpty()) { error = QSharedMemory::KeyError; errorString = QSharedMemory::tr("%1: key error").arg(function); return false; } - TPtrC ptr(qt_QString2TPtrC(safeKey)); + TPtrC ptr(qt_QString2TPtrC(nativeKey)); TInt err = chunk.CreateGlobal(ptr, size, size); @@ -136,14 +134,13 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode /* mode */) // Grab a pointer to the memory block if (!chunk.Handle()) { QString function = QLatin1String("QSharedMemory::handle"); - QString safeKey = makePlatformSafeKey(key); - if (safeKey.isEmpty()) { + if (nativeKey.isEmpty()) { error = QSharedMemory::KeyError; errorString = QSharedMemory::tr("%1: unable to make key").arg(function); return false; } - TPtrC ptr(qt_QString2TPtrC(safeKey)); + TPtrC ptr(qt_QString2TPtrC(nativeKey)); TInt err = KErrNoMemory; diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp index a5f79c2..064979b 100644 --- a/src/corelib/kernel/qsharedmemory_unix.cpp +++ b/src/corelib/kernel/qsharedmemory_unix.cpp @@ -116,21 +116,20 @@ key_t QSharedMemoryPrivate::handle() return unix_key; // don't allow making handles on empty keys - if (key.isEmpty()) { + if (nativeKey.isEmpty()) { errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::handle:")); error = QSharedMemory::KeyError; return 0; } // ftok requires that an actual file exists somewhere - QString fileName = makePlatformSafeKey(key); - if (!QFile::exists(fileName)) { + if (!QFile::exists(nativeKey)) { errorString = QSharedMemory::tr("%1: UNIX key file doesn't exist").arg(QLatin1String("QSharedMemory::handle:")); error = QSharedMemory::NotFound; return 0; } - unix_key = ftok(QFile::encodeName(fileName).constData(), 'Q'); + unix_key = ftok(QFile::encodeName(nativeKey).constData(), 'Q'); if (-1 == unix_key) { errorString = QSharedMemory::tr("%1: ftok failed").arg(QLatin1String("QSharedMemory::handle:")); error = QSharedMemory::KeyError; @@ -181,7 +180,7 @@ bool QSharedMemoryPrivate::create(int size) { // build file if needed bool createdFile = false; - int built = createUnixKeyFile(makePlatformSafeKey(key)); + int built = createUnixKeyFile(nativeKey); if (built == -1) { errorString = QSharedMemory::tr("%1: unable to make key").arg(QLatin1String("QSharedMemory::handle:")); error = QSharedMemory::KeyError; @@ -194,7 +193,7 @@ bool QSharedMemoryPrivate::create(int size) // get handle if (!handle()) { if (createdFile) - QFile::remove(makePlatformSafeKey(key)); + QFile::remove(nativeKey); return false; } @@ -210,7 +209,7 @@ bool QSharedMemoryPrivate::create(int size) setErrorString(function); } if (createdFile && error != QSharedMemory::AlreadyExists) - QFile::remove(makePlatformSafeKey(key)); + QFile::remove(nativeKey); return false; } @@ -295,7 +294,7 @@ bool QSharedMemoryPrivate::detach() } // remove file - if (!QFile::remove(makePlatformSafeKey(key))) + if (!QFile::remove(nativeKey)) return false; } return true; diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp index 0f5fdc7..0cdb123 100644 --- a/src/corelib/kernel/qsharedmemory_win.cpp +++ b/src/corelib/kernel/qsharedmemory_win.cpp @@ -99,18 +99,17 @@ HANDLE QSharedMemoryPrivate::handle() { if (!hand) { QString function = QLatin1String("QSharedMemory::handle"); - QString safeKey = makePlatformSafeKey(key); - if (safeKey.isEmpty()) { + if (nativeKey.isEmpty()) { error = QSharedMemory::KeyError; errorString = QSharedMemory::tr("%1: unable to make key").arg(function); return false; } #ifndef Q_OS_WINCE - hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, (wchar_t*)safeKey.utf16()); + hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, (wchar_t*)nativeKey.utf16()); #else // This works for opening a mapping too, but always opens it with read/write access in // attach as it seems. - hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 0, (wchar_t*)safeKey.utf16()); + hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 0, (wchar_t*)nativeKey.utf16()); #endif if (!hand) { setErrorString(function); @@ -133,17 +132,15 @@ bool QSharedMemoryPrivate::cleanHandle() bool QSharedMemoryPrivate::create(int size) { - // Get a windows acceptable key - QString safeKey = makePlatformSafeKey(key); QString function = QLatin1String("QSharedMemory::create"); - if (safeKey.isEmpty()) { + if (nativeKey.isEmpty()) { error = QSharedMemory::KeyError; errorString = QSharedMemory::tr("%1: key error").arg(function); return false; } // Create the file mapping. - hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size, (wchar_t*)safeKey.utf16()); + hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size, (wchar_t*)nativeKey.utf16()); setErrorString(function); // hand is valid when it already exists unlike unix so explicitly check diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index f5d7c0d..feb85ce 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -947,11 +947,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, case QMetaType::UChar: case QMetaType::UShort: case QMetaType::ULong: -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - *f = (double)(qlonglong)qMetaTypeUNumber(d); -#else *f = double(qMetaTypeUNumber(d)); -#endif break; default: *f = 0.0; @@ -986,11 +982,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, case QMetaType::UChar: case QMetaType::UShort: case QMetaType::ULong: -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - *f = (float)(qlonglong)qMetaTypeUNumber(d); -#else *f = float(qMetaTypeUNumber(d)); -#endif break; default: *f = 0.0f; @@ -1084,7 +1076,7 @@ static void streamDebug(QDebug dbg, const QVariant &v) dbg.nospace() << v.toFloat(); break; case QMetaType::QObjectStar: - dbg.nospace() << qVariantValue<QObject *>(v); + dbg.nospace() << qvariant_cast<QObject *>(v); break; case QVariant::Double: dbg.nospace() << v.toDouble(); @@ -1245,7 +1237,7 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler; conversion functions to data types defined in QtGui, such as QColor, QImage, and QPixmap. In other words, there is no \c toColor() function. Instead, you can use the QVariant::value() or - the qVariantValue() template function. For example: + the qvariant_cast() template function. For example: \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 2 @@ -1360,12 +1352,12 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler; Note that you have to pass the address of the variable you want stored. - Usually, you never have to use this constructor, use qVariantFromValue() + Usually, you never have to use this constructor, use QVariant::fromValue() instead to construct variants from the pointer types represented by \c QMetaType::VoidStar, \c QMetaType::QObjectStar and \c QMetaType::QWidgetStar. - \sa qVariantFromValue(), Type + \sa QVariant::fromValue(), Type */ /*! @@ -3074,10 +3066,6 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 4 - \warning This function is not available with MSVC 6. Use - qVariantSetValue() instead if you need to support that version of - the compiler. - \sa value(), fromValue(), canConvert() */ @@ -3095,10 +3083,6 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 5 - \warning This function is not available with MSVC 6. Use - qVariantValue() or qvariant_cast() instead if you need to support - that version of the compiler. - \sa setValue(), fromValue(), canConvert() */ @@ -3111,10 +3095,6 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 6 - \warning This function is not available with MSVC 6. Use - qVariantCanConvert() instead if you need to support that version - of the compiler. - \sa convert() */ @@ -3130,23 +3110,22 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \note If you are working with custom types, you should use the Q_DECLARE_METATYPE() macro to register your custom type. - \warning This function is not available with MSVC 6. Use - qVariantFromValue() instead if you need to support that version - of the compiler. - \sa setValue(), value() */ /*! \fn QVariant qVariantFromValue(const T &value) \relates QVariant + \obsolete Returns a variant containing a copy of the given \a value with template type \c{T}. - This function is equivalent to QVariant::fromValue(\a value). It - is provided as a work-around for MSVC 6, which doesn't support - member template functions. + This function is equivalent to QVariant::fromValue(\a value). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. For example, a QObject pointer can be stored in a variant with the following code: @@ -3158,13 +3137,16 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) /*! \fn void qVariantSetValue(QVariant &variant, const T &value) \relates QVariant + \obsolete Sets the contents of the given \a variant to a copy of the \a value with the specified template type \c{T}. - This function is equivalent to QVariant::setValue(\a value). It - is provided as a work-around for MSVC 6, which doesn't support - member template functions. + This function is equivalent to QVariant::setValue(\a value). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QVariant::setValue() */ @@ -3175,33 +3157,39 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) Returns the given \a value converted to the template type \c{T}. - This function is equivalent to qVariantValue(). + This function is equivalent to QVariant::value(). - \sa qVariantValue(), QVariant::value() + \sa QVariant::value() */ /*! \fn T qVariantValue(const QVariant &value) \relates QVariant + \obsolete Returns the given \a value converted to the template type \c{T}. This function is equivalent to - \l{QVariant::value()}{QVariant::value}<T>(\a value). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \l{QVariant::value()}{QVariant::value}<T>(\a value). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QVariant::value(), qvariant_cast() */ /*! \fn bool qVariantCanConvert(const QVariant &value) \relates QVariant + \obsolete Returns true if the given \a value can be converted to the template type specified; otherwise returns false. - This function is equivalent to QVariant::canConvert(\a value). It - is provided as a work-around for MSVC 6, which doesn't support - member template functions. + This function is equivalent to QVariant::canConvert(\a value). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QVariant::canConvert() */ diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index cb2825c..b267954 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -83,19 +83,11 @@ class QUrl; class QVariant; class QVariantComparisonHelper; -#ifndef QT_NO_MEMBER_TEMPLATES template <typename T> inline QVariant qVariantFromValue(const T &); -template <typename T> -inline void qVariantSetValue(QVariant &, const T &); - -template<typename T> -inline T qVariantValue(const QVariant &); - template<typename T> -inline bool qVariantCanConvert(const QVariant &); -#endif +inline T qvariant_cast(const QVariant &); class Q_CORE_EXPORT QVariant { @@ -227,6 +219,10 @@ class Q_CORE_EXPORT QVariant QVariant(Qt::GlobalColor color); QVariant& operator=(const QVariant &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QVariant &operator=(QVariant &&other) + { qSwap(d, other.d); return *this; } +#endif Type type() const; int userType() const; @@ -327,13 +323,12 @@ class Q_CORE_EXPORT QVariant const void *constData() const; inline const void *data() const { return constData(); } -#ifndef QT_NO_MEMBER_TEMPLATES template<typename T> inline void setValue(const T &value); template<typename T> inline T value() const - { return qVariantValue<T>(*this); } + { return qvariant_cast<T>(*this); } template<typename T> static inline QVariant fromValue(const T &value) @@ -341,8 +336,7 @@ class Q_CORE_EXPORT QVariant template<typename T> bool canConvert() const - { return qVariantCanConvert<T>(*this); } -#endif + { return canConvert(Type(qMetaTypeId<T>())); } public: #ifndef qdoc @@ -527,11 +521,9 @@ inline QSize &QVariant::asSize() { return *reinterpret_cast<QSize *>(castOrDetach(Size)); } #endif //QT3_SUPPORT -#ifndef QT_NO_MEMBER_TEMPLATES template<typename T> inline void QVariant::setValue(const T &avalue) { qVariantSetValue(*this, avalue); } -#endif #ifndef QT_NO_DATASTREAM Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant& p); @@ -594,16 +586,16 @@ template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v) return v; } +#ifdef QT_DEPRECATED template<typename T> -inline T qVariantValue(const QVariant &variant) +inline QT_DEPRECATED T qVariantValue(const QVariant &variant) { return qvariant_cast<T>(variant); } template<typename T> -inline bool qVariantCanConvert(const QVariant &variant) -{ - return variant.canConvert(static_cast<QVariant::Type>( - qMetaTypeId<T>(static_cast<T *>(0)))); -} +inline QT_DEPRECATED bool qVariantCanConvert(const QVariant &variant) +{ return variant.template canConvert<T>(); } +#endif + #endif Q_DECLARE_SHARED(QVariant) Q_DECLARE_TYPEINFO(QVariant, Q_MOVABLE_TYPE); diff --git a/src/corelib/plugin/plugin.pri b/src/corelib/plugin/plugin.pri index ba86353..50b005d 100644 --- a/src/corelib/plugin/plugin.pri +++ b/src/corelib/plugin/plugin.pri @@ -8,13 +8,15 @@ HEADERS += \ plugin/qplugin.h \ plugin/quuid.h \ plugin/qfactoryloader_p.h \ - plugin/qsystemlibrary_p.h + plugin/qsystemlibrary_p.h \ + plugin/qelfparser_p.h SOURCES += \ plugin/qpluginloader.cpp \ plugin/qfactoryloader.cpp \ plugin/quuid.cpp \ - plugin/qlibrary.cpp + plugin/qlibrary.cpp \ + plugin/qelfparser_p.cpp win32 { SOURCES += \ diff --git a/src/corelib/plugin/qelfparser_p.cpp b/src/corelib/plugin/qelfparser_p.cpp new file mode 100644 index 0000000..2e77ae7 --- /dev/null +++ b/src/corelib/plugin/qelfparser_p.cpp @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlibrary_p.h" +#include "qelfparser_p.h" +#include <qdebug.h> + +QT_BEGIN_NAMESPACE + +// #define QELFPARSER_DEBUG 1 + +const char *QElfParser::parseSectionHeader(const char *data, ElfSectionHeader *sh) +{ + sh->name = read<qelfword_t>(data); + data += sizeof(qelfword_t); // sh_name + sh->type = read<qelfword_t>(data); + data += sizeof(qelfword_t) // sh_type + + sizeof(qelfaddr_t) // sh_flags + + sizeof(qelfaddr_t); // sh_addr + sh->offset = read<qelfoff_t>(data); + data += sizeof(qelfoff_t); // sh_offset + sh->size = read<qelfword_t>(data); + data += sizeof(qelfword_t); // sh_size + return data; +} + +int QElfParser::parse(const char *dataStart, ulong fdlen, const QString &library, QLibraryPrivate *lib, long *pos, ulong *sectionlen) +{ +#if defined(QELFPARSER_DEBUG) + qDebug() << "QElfParser::parse " << library; +#endif + + if (fdlen < 64){ + if (lib) + lib->errorString = QLibrary::tr("'%1' is not an ELF object (%2)").arg(library).arg(QLatin1String("file too small")); + return NotElf; + } + const char *data = dataStart; + if (qstrncmp(data, "\177ELF", 4) != 0) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is not an ELF object").arg(library); + return NotElf; + } + // 32 or 64 bit + if (data[4] != 1 && data[4] != 2) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("odd cpu architecture")); + return Corrupt; + } + m_bits = (data[4] << 5); + + /* If you remove this check, to read ELF objects of a different arch, please make sure you modify the typedefs + to match the _plugin_ architecture. + */ + if ((sizeof(void*) == 4 && m_bits != 32) || (sizeof(void*) == 8 && m_bits != 64)) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("wrong cpu architecture")); + return Corrupt; + } + // endian + if (data[5] == 0) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("odd endianess")); + return Corrupt; + } + m_endian = (data[5] == 1 ? ElfLittleEndian : ElfBigEndian); + + data += 16 // e_ident + + sizeof(qelfhalf_t) // e_type + + sizeof(qelfhalf_t) // e_machine + + sizeof(qelfword_t) // e_version + + sizeof(qelfaddr_t) // e_entry + + sizeof(qelfoff_t); // e_phoff + + qelfoff_t e_shoff = read<qelfoff_t> (data); + data += sizeof(qelfoff_t) // e_shoff + + sizeof(qelfword_t); // e_flags + + qelfhalf_t e_shsize = read<qelfhalf_t> (data); + + if (e_shsize > fdlen) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("unexpected e_shsize")); + return Corrupt; + } + + data += sizeof(qelfhalf_t) // e_ehsize + + sizeof(qelfhalf_t) // e_phentsize + + sizeof(qelfhalf_t); // e_phnum + + qelfhalf_t e_shentsize = read<qelfhalf_t> (data); + + if (e_shentsize % 4){ + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("unexpected e_shentsize")); + return Corrupt; + } + data += sizeof(qelfhalf_t); // e_shentsize + qelfhalf_t e_shnum = read<qelfhalf_t> (data); + data += sizeof(qelfhalf_t); // e_shnum + qelfhalf_t e_shtrndx = read<qelfhalf_t> (data); + data += sizeof(qelfhalf_t); // e_shtrndx + + if ((e_shnum * e_shentsize) > fdlen) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("announced %2 sections, each %3 bytes, exceed file size")) + .arg(e_shnum).arg(e_shentsize); + return Corrupt; + } + +#if defined(QELFPARSER_DEBUG) + qDebug() << e_shnum << "sections starting at " << ("0x" + QByteArray::number(e_shoff, 16)).data() << "each" << e_shentsize << "bytes"; +#endif + + ElfSectionHeader strtab; + qulonglong soff = e_shoff + e_shentsize * (e_shtrndx); + + if ((soff + e_shentsize) > fdlen || soff % 4 || soff == 0) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("shstrtab section header seems to be at %1")) + .arg(QString::number(soff, 16)); + return Corrupt; + } + + parseSectionHeader(dataStart + soff, &strtab); + m_stringTableFileOffset = strtab.offset; + + if ((m_stringTableFileOffset + e_shentsize) >= fdlen || m_stringTableFileOffset == 0) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("string table seems to be at %1")) + .arg(QString::number(soff, 16)); + return Corrupt; + } + +#if defined(QELFPARSER_DEBUG) + qDebug(".shstrtab at 0x%s", QByteArray::number(m_stringTableFileOffset, 16).data()); +#endif + + const char *s = dataStart + e_shoff; + for (int i = 0; i < e_shnum; ++i) { + ElfSectionHeader sh; + parseSectionHeader(s, &sh); + if (sh.name == 0) { + s += e_shentsize; + continue; + } + const char *shnam = dataStart + m_stringTableFileOffset + sh.name; + + if (m_stringTableFileOffset + sh.name > fdlen) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("section name %2 of %3 behind end of file")) + .arg(i).arg(e_shnum); + return Corrupt; + } + +#if defined(QELFPARSER_DEBUG) + qDebug() << "++++" << i << shnam; +#endif + + if (qstrcmp(shnam, ".qtplugin") == 0 || qstrcmp(shnam, ".rodata") == 0) { + if (!(sh.type & 0x1)) { + if (shnam[1] == 'r') { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("empty .rodata. not a library.")); + return Corrupt; + } +#if defined(QELFPARSER_DEBUG) + qDebug()<<"section is not program data. skipped."; +#endif + s += e_shentsize; + continue; + } + + if (sh.offset == 0 || (sh.offset + sh.size) > fdlen) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("missing section data. This is not a library.")); + return Corrupt; + } + *pos = sh.offset; + *sectionlen = sh.size - 1; + if (shnam[1] == 'q') + return Ok; + } + s += e_shentsize; + } + return NoQtSection; +} + +QT_END_NAMESPACE + diff --git a/src/corelib/plugin/qelfparser_p.h b/src/corelib/plugin/qelfparser_p.h new file mode 100644 index 0000000..380d5a1 --- /dev/null +++ b/src/corelib/plugin/qelfparser_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QELFPARSER_P_H +#define QELFPARSER_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 <qendian.h> +#include <qglobal.h> + +QT_BEGIN_NAMESPACE + +class QString; +class QLibraryPrivate; + +typedef quint16 qelfhalf_t; +typedef quint32 qelfword_t; +typedef quintptr qelfoff_t; +typedef quintptr qelfaddr_t; + +class QElfParser +{ +public: + enum {Ok = 0, NotElf = 1, NoQtSection = 2, Corrupt = 3}; + enum {ElfLittleEndian = 0, ElfBigEndian = 1}; + + struct ElfSectionHeader + { + qelfword_t name; + qelfword_t type; + qelfoff_t offset; + qelfword_t size; + }; + + int m_endian; + int m_bits; + int m_stringTableFileOffset; + + template <typename T> + T read(const char *s) + { + if (m_endian == ElfBigEndian) + return qFromBigEndian<T>(reinterpret_cast<const uchar *>(s)); + else + return qFromLittleEndian<T>(reinterpret_cast<const uchar *>(s)); + } + + const char *parseSectionHeader(const char* s, ElfSectionHeader *sh); + int parse(const char *m_s, ulong fdlen, const QString &library, QLibraryPrivate *lib, long *pos, ulong *sectionlen); +}; + +QT_END_NAMESPACE + +#endif // QELFPARSER_P_H + diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 1874a9e..239509e 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -38,7 +38,6 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - #include "qplatformdefs.h" #include "qlibrary.h" @@ -61,11 +60,10 @@ #include <qdebug.h> #include <qvector.h> #include <qdir.h> +#include "qelfparser_p.h" QT_BEGIN_NAMESPACE -//#define QT_DEBUG_COMPONENT - #ifdef QT_NO_DEBUG # define QLIBRARY_AS_DEBUG false #else @@ -365,11 +363,35 @@ static bool qt_unix_query(const QString &library, uint *version, bool *debug, QB fdlen = data.size(); } - // verify that the pattern is present in the plugin + /* + ELF binaries on GNU, have .qplugin sections. + */ + long pos = 0; const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA"; const ulong plen = qstrlen(pattern); - long pos = qt_find_pattern(filedata, fdlen, pattern, plen); - +#if defined (Q_OF_ELF) && defined(Q_CC_GNU) + int r = QElfParser().parse(filedata, fdlen, library, lib, &pos, &fdlen); + if (r == QElfParser::NoQtSection) { + if (pos > 0) { + // find inside .rodata + long rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen); + if (rel < 0) { + pos = -1; + } else { + pos += rel; + } + } else { + pos = qt_find_pattern(filedata, fdlen, pattern, plen); + } + } else if (r != QElfParser::Ok) { + if (lib && qt_debug_component()) { + qWarning(qPrintable(lib->errorString)); + } + return false; + } +#else + pos = qt_find_pattern(filedata, fdlen, pattern, plen); +#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU) bool ret = false; if (pos >= 0) ret = qt_parse_pattern(filedata + pos, version, debug, key); @@ -388,10 +410,14 @@ struct LibraryData { LibraryData() : settings(0) { } ~LibraryData() { delete settings; + foreach(QLibraryPrivate *lib, loadedLibs) { + lib->unload(); + } } QSettings *settings; LibraryMap libraryMap; + QSet<QLibraryPrivate*> loadedLibs; }; Q_GLOBAL_STATIC(LibraryData, libraryData) @@ -443,7 +469,18 @@ bool QLibraryPrivate::load() return true; if (fileName.isEmpty()) return false; - return load_sys(); + + bool ret = load_sys(); + if (ret) { + //when loading a library we add a reference to it so that the QLibraryPrivate won't get deleted + //this allows to unload the library at a later time + if (LibraryData *lib = libraryData()) { + lib->loadedLibs += this; + libraryRefCount.ref(); + } + } + + return ret; } bool QLibraryPrivate::unload() @@ -451,10 +488,16 @@ bool QLibraryPrivate::unload() if (!pHnd) return false; if (!libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to - if (instance) - delete instance(); + delete inst.data(); if (unload_sys()) { - instance = 0; + if (qt_debug_component()) + qWarning() << "QLibraryPrivate::unload succeeded on" << fileName; + //when the library is unloaded, we release the reference on it so that 'this' + //can get deleted + if (LibraryData *lib = libraryData()) { + if (lib->loadedLibs.remove(this)) + libraryRefCount.deref(); + } pHnd = 0; } } @@ -496,7 +539,7 @@ bool QLibraryPrivate::loadPlugin() \table \header \i Platform \i Valid suffixes - \row \i Windows \i \c .dll + \row \i Windows \i \c .dll, \c .DLL \row \i Unix/Linux \i \c .so \row \i AIX \i \c .a \row \i HP-UX \i \c .sl, \c .so (HP-UXi) @@ -509,7 +552,7 @@ bool QLibraryPrivate::loadPlugin() bool QLibrary::isLibrary(const QString &fileName) { #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) - return fileName.endsWith(QLatin1String(".dll")); + return fileName.endsWith(QLatin1String(".dll"), Qt::CaseInsensitive); #elif defined(Q_OS_SYMBIAN) // Plugin stubs are also considered libraries in Symbian. return (fileName.endsWith(QLatin1String(".dll")) || @@ -571,6 +614,46 @@ bool QLibrary::isLibrary(const QString &fileName) } +#if defined (Q_OS_WIN) && defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(Q_CC_INTEL) +#define QT_USE_MS_STD_EXCEPTION 1 +const char* qt_try_versioninfo(void *pfn, bool *exceptionThrown) +{ + *exceptionThrown = false; + const char *szData = 0; + typedef const char * (*VerificationFunction)(); + VerificationFunction func = reinterpret_cast<VerificationFunction>(pfn); + __try { + if(func) + szData = func(); + } __except(EXCEPTION_EXECUTE_HANDLER) { + *exceptionThrown = true; + } + return szData; +} +#endif + +#ifdef Q_CC_BOR +typedef const char * __stdcall (*QtPluginQueryVerificationDataFunction)(); +#else +typedef const char * (*QtPluginQueryVerificationDataFunction)(); +#endif + +bool qt_get_verificationdata(QtPluginQueryVerificationDataFunction pfn, uint *qt_version, bool *debug, QByteArray *key, bool *exceptionThrown) +{ + *exceptionThrown = false; + const char *szData = 0; + if (!pfn) + return false; +#ifdef QT_USE_MS_STD_EXCEPTION + szData = qt_try_versioninfo((void *)pfn, exceptionThrown); + if (*exceptionThrown) + return false; +#else + szData = pfn(); +#endif + return qt_parse_pattern(szData, qt_version, debug, key); +} + bool QLibraryPrivate::isPlugin(QSettings *settings) { errorString.clear(); @@ -646,70 +729,82 @@ bool QLibraryPrivate::isPlugin(QSettings *settings) } else #endif { - bool temporary_load = false; + bool retryLoadLibrary = false; // Only used on Windows with MS compiler.(false in other cases) + do { + bool temporary_load = false; #ifdef Q_OS_WIN - HMODULE hTempModule = 0; + HMODULE hTempModule = 0; #endif - if (!pHnd) { + if (!pHnd) { #ifdef Q_OS_WIN - //avoid 'Bad Image' message box - UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - hTempModule = ::LoadLibraryEx((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, DONT_RESOLVE_DLL_REFERENCES); - SetErrorMode(oldmode); + DWORD dwFlags = (retryLoadLibrary) ? 0: DONT_RESOLVE_DLL_REFERENCES; + //avoid 'Bad Image' message box + UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); + hTempModule = ::LoadLibraryEx((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, dwFlags); + SetErrorMode(oldmode); #else # if defined(Q_OS_SYMBIAN) - //Guard against accidentally trying to load non-plugin libraries by making sure the stub exists - if (fileinfo.exists()) + //Guard against accidentally trying to load non-plugin libraries by making sure the stub exists + if (fileinfo.exists()) # endif - temporary_load = load_sys(); + temporary_load = load_sys(); #endif - } -# ifdef Q_CC_BOR - typedef const char * __stdcall (*QtPluginQueryVerificationDataFunction)(); -# else - typedef const char * (*QtPluginQueryVerificationDataFunction)(); -# endif + } #ifdef Q_OS_WIN - QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule - ? (QtPluginQueryVerificationDataFunction) + QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule ? (QtPluginQueryVerificationDataFunction) #ifdef Q_OS_WINCE - ::GetProcAddress(hTempModule, L"qt_plugin_query_verification_data") + ::GetProcAddress(hTempModule, L"qt_plugin_query_verification_data") #else - ::GetProcAddress(hTempModule, "qt_plugin_query_verification_data") + ::GetProcAddress(hTempModule, "qt_plugin_query_verification_data") #endif : (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); #else - QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = NULL; + QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = NULL; # if defined(Q_OS_SYMBIAN) - if (temporary_load) { - qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); - // If resolving with function name failed (i.e. not STDDLL), try resolving using known ordinal - if (!qtPluginQueryVerificationDataFunction) - qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("1"); - } + if (temporary_load) { + qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); + // If resolving with function name failed (i.e. not STDDLL), try resolving using known ordinal + if (!qtPluginQueryVerificationDataFunction) + qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("1"); + } # else - qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); + qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); # endif #endif - - if (!qtPluginQueryVerificationDataFunction - || !qt_parse_pattern(qtPluginQueryVerificationDataFunction(), &qt_version, &debug, &key)) { - qt_version = 0; - key = "unknown"; - if (temporary_load) - unload_sys(); - } else { - success = true; - } -#ifdef Q_OS_WIN - if (hTempModule) { - BOOL ok = ::FreeLibrary(hTempModule); - if (ok) { - hTempModule = 0; + bool exceptionThrown = false; + bool ret = qt_get_verificationdata(qtPluginQueryVerificationDataFunction, + &qt_version, &debug, &key, &exceptionThrown); + if (!exceptionThrown) { + if (!ret) { + qt_version = 0; + key = "unknown"; + if (temporary_load) + unload_sys(); + } else { + success = true; + } + retryLoadLibrary = false; + } +#ifdef QT_USE_MS_STD_EXCEPTION + else { + // An exception was thrown when calling qt_plugin_query_verification_data(). + // This usually happens when plugin is compiled with the /clr compiler flag, + // & will only work if the dependencies are loaded & DLLMain() is called. + // LoadLibrary() will do this, try once with this & if it fails dont load. + retryLoadLibrary = !retryLoadLibrary; } +#endif +#ifdef Q_OS_WIN + if (hTempModule) { + BOOL ok = ::FreeLibrary(hTempModule); + if (ok) { + hTempModule = 0; + } - } + } #endif + } while(retryLoadLibrary); // Will be 'false' in all cases other than when an + // exception is thrown(will happen only when using a MS compiler) } // Qt 4.5 compatibility: stl doesn't affect binary compatibility @@ -1039,7 +1134,7 @@ void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &ver */ void *QLibrary::resolve(const char *symbol) { - if (!load()) + if (!isLoaded() && !load()) return 0; return d->resolve(symbol); } @@ -1182,15 +1277,11 @@ QLibrary::LoadHints QLibrary::loadHints() const /* Internal, for debugging */ bool qt_debug_component() { -#if defined(QT_DEBUG_COMPONENT) - return true; //compatibility? -#else static int debug_env = -1; if (debug_env == -1) debug_env = QT_PREPEND_NAMESPACE(qgetenv)("QT_DEBUG_PLUGINS").toInt(); return debug_env != 0; -#endif } QT_END_NAMESPACE diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h index 02dc523..b73fce5 100644 --- a/src/corelib/plugin/qlibrary_p.h +++ b/src/corelib/plugin/qlibrary_p.h @@ -60,6 +60,7 @@ #include "QtCore/qpointer.h" #include "QtCore/qstringlist.h" #include "QtCore/qplugin.h" +#include "QtCore/qsharedpointer.h" #ifndef QT_NO_LIBRARY @@ -90,6 +91,7 @@ public: static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString()); + QWeakPointer<QObject> inst; QtPluginInstanceFunction instance; uint qt_version; QString lastModified; diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp index e8f0eae..9ad1c01 100644 --- a/src/corelib/plugin/qlibrary_unix.cpp +++ b/src/corelib/plugin/qlibrary_unix.cpp @@ -223,11 +223,15 @@ bool QLibraryPrivate::load_sys() #ifdef Q_OS_MAC if (!pHnd) { - if (CFBundleRef bundle = CFBundleGetBundleWithIdentifier(QCFString(fileName))) { + QByteArray utf8Bundle = fileName.toUtf8(); + QCFType<CFURLRef> bundleUrl = CFURLCreateFromFileSystemRepresentation(NULL, reinterpret_cast<const UInt8*>(utf8Bundle.data()), utf8Bundle.length(), true); + QCFType<CFBundleRef> bundle = CFBundleCreate(NULL, bundleUrl); + if(bundle) { QCFType<CFURLRef> url = CFBundleCopyExecutableURL(bundle); - QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); - pHnd = dlopen(QFile::encodeName(str), dlFlags); - attempt = str; + char executableFile[FILENAME_MAX]; + CFURLGetFileSystemRepresentation(url, true, reinterpret_cast<UInt8*>(executableFile), FILENAME_MAX); + attempt = QString::fromUtf8(executableFile); + pHnd = dlopen(QFile::encodeName(attempt), dlFlags); } } #endif diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index 7f541f1..bd49b15 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -101,13 +101,17 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio // NOTE: if you change pattern, you MUST change the pattern in // qlibrary.cpp as well. changing the pattern will break all // backwards compatibility as well (no old plugins will be loaded). +// QT5: should probably remove the entire pattern thing and do the section +// trick for all platforms. for now, keep it and fallback to scan for it. # ifdef QPLUGIN_DEBUG_STR # undef QPLUGIN_DEBUG_STR # endif # ifdef QT_NO_DEBUG # define QPLUGIN_DEBUG_STR "false" +# define QPLUGIN_SECTION_DEBUG_STR "" # else # define QPLUGIN_DEBUG_STR "true" +# define QPLUGIN_SECTION_DEBUG_STR ".debug" # endif # define Q_PLUGIN_VERIFICATION_DATA \ static const char qt_plugin_verification_data[] = \ @@ -116,6 +120,13 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio "debug="QPLUGIN_DEBUG_STR"\n" \ "buildkey="QT_BUILD_KEY; +# if defined (Q_OF_ELF) && defined (Q_CC_GNU) +# define Q_PLUGIN_VERIFICATION_SECTION \ + __attribute__ ((section (".qtplugin"))) __attribute__((used)) +# else +# define Q_PLUGIN_VERIFICATION_SECTION +# endif + # if defined (Q_OS_WIN32) && defined(Q_CC_BOR) # define Q_STANDARD_CALL __stdcall # else @@ -123,7 +134,7 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio # endif # define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \ - Q_PLUGIN_VERIFICATION_DATA \ + Q_PLUGIN_VERIFICATION_SECTION Q_PLUGIN_VERIFICATION_DATA \ Q_EXTERN_C Q_DECL_EXPORT \ const char * Q_STANDARD_CALL qt_plugin_query_verification_data() \ { return qt_plugin_verification_data; } \ diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index b1d1ecc..9f322df 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -198,11 +198,11 @@ QPluginLoader::~QPluginLoader() */ QObject *QPluginLoader::instance() { - if (!load()) + if (!isLoaded() && !load()) return 0; - if (d->instance) - return d->instance(); - return 0; + if (!d->inst && d->instance) + d->inst = d->instance(); + return d->inst.data(); } /*! diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 4b371f7..d704615 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -793,7 +793,7 @@ void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &tr } // We require that at least one animation is valid. // ### generalize - QList<QVariantAnimation*> variantAnims = qFindChildren<QVariantAnimation*>(anim); + QList<QVariantAnimation*> variantAnims = anim->findChildren<QVariantAnimation*>(); if (QVariantAnimation *va = qobject_cast<QVariantAnimation*>(anim)) variantAnims.append(va); @@ -1178,7 +1178,7 @@ void QStateMachinePrivate::removeStartState() void QStateMachinePrivate::clearHistory() { Q_Q(QStateMachine); - QList<QHistoryState*> historyStates = qFindChildren<QHistoryState*>(q); + QList<QHistoryState*> historyStates = q->findChildren<QHistoryState*>(); for (int i = 0; i < historyStates.size(); ++i) { QHistoryState *h = historyStates.at(i); QHistoryStatePrivate::get(h)->configuration.clear(); @@ -1440,7 +1440,7 @@ void QStateMachinePrivate::goToState(QAbstractState *targetState) Q_ASSERT(sourceState != 0); // Reuse previous GoToStateTransition in case of several calls to // goToState() in a row. - GoToStateTransition *trans = qFindChild<GoToStateTransition*>(sourceState); + GoToStateTransition *trans = sourceState->findChild<GoToStateTransition*>(); if (!trans) { trans = new GoToStateTransition(targetState); sourceState->addTransition(trans); @@ -1562,7 +1562,7 @@ void QStateMachinePrivate::unregisterAllTransitions() { Q_Q(QStateMachine); { - QList<QSignalTransition*> transitions = qFindChildren<QSignalTransition*>(rootState()); + QList<QSignalTransition*> transitions = rootState()->findChildren<QSignalTransition*>(); for (int i = 0; i < transitions.size(); ++i) { QSignalTransition *t = transitions.at(i); if (t->machine() == q) @@ -1570,7 +1570,7 @@ void QStateMachinePrivate::unregisterAllTransitions() } } { - QList<QEventTransition*> transitions = qFindChildren<QEventTransition*>(rootState()); + QList<QEventTransition*> transitions = rootState()->findChildren<QEventTransition*>(); for (int i = 0; i < transitions.size(); ++i) { QEventTransition *t = transitions.at(i); if (t->machine() == q) diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index 43df13a..b85a22d 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -130,7 +130,7 @@ QMutex::QMutex(RecursionMode mode) \warning Destroying a locked mutex may result in undefined behavior. */ QMutex::~QMutex() -{ delete d; } +{ delete static_cast<QMutexPrivate *>(d); } /*! Locks the mutex. If another thread has locked the mutex then this @@ -146,6 +146,7 @@ QMutex::~QMutex() */ void QMutex::lock() { + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); Qt::HANDLE self; if (d->recursive) { @@ -158,11 +159,6 @@ void QMutex::lock() bool isLocked = d->contenders.fetchAndAddAcquire(1) == 0; if (!isLocked) { -#ifndef QT_NO_DEBUG - if (d->owner == self) - qWarning() << "QMutex::lock: Deadlock detected in thread" << d->owner; -#endif - // didn't get the lock, wait for it isLocked = d->wait(); Q_ASSERT_X(isLocked, "QMutex::lock", @@ -178,54 +174,11 @@ void QMutex::lock() return; } -#ifndef QT_NO_DEBUG - self = QThread::currentThreadId(); -#endif bool isLocked = d->contenders == 0 && d->contenders.testAndSetAcquire(0, 1); if (!isLocked) { - int spinCount = 0; - int lastSpinCount = d->lastSpinCount; - - enum { AdditionalSpins = 20, SpinCountPenalizationDivisor = 4 }; - const int maximumSpinCount = lastSpinCount + AdditionalSpins; - - do { - if (spinCount++ > maximumSpinCount) { - // puts("spinning useless, sleeping"); - isLocked = d->contenders.fetchAndAddAcquire(1) == 0; - if (!isLocked) { -#ifndef QT_NO_DEBUG - if (d->owner == self) - qWarning() << "QMutex::lock: Deadlock detected in thread" << d->owner; -#endif - - // didn't get the lock, wait for it - isLocked = d->wait(); - Q_ASSERT_X(isLocked, "QMutex::lock", - "Internal error, infinite wait has timed out."); - - // don't need to wait for the lock anymore - d->contenders.deref(); - } - // decrease the lastSpinCount since we didn't actually get the lock by spinning - spinCount = -d->lastSpinCount / SpinCountPenalizationDivisor; - break; - } - - isLocked = d->contenders == 0 && d->contenders.testAndSetAcquire(0, 1); - } while (!isLocked); - - // adjust the last spin lock count - lastSpinCount = d->lastSpinCount; - d->lastSpinCount = spinCount >= 0 - ? qMax(lastSpinCount, spinCount) - : lastSpinCount + spinCount; + lockInternal(); } - -#ifndef QT_NO_DEBUG - d->owner = self; -#endif } /*! @@ -247,6 +200,7 @@ void QMutex::lock() */ bool QMutex::tryLock() { + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); Qt::HANDLE self; if (d->recursive) { @@ -270,18 +224,12 @@ bool QMutex::tryLock() return isLocked; } -#ifndef QT_NO_DEBUG - self = QThread::currentThreadId(); -#endif bool isLocked = d->contenders == 0 && d->contenders.testAndSetAcquire(0, 1); if (!isLocked) { // some other thread has the mutex locked, or we tried to // recursively lock an non-recursive mutex return isLocked; } -#ifndef QT_NO_DEBUG - d->owner = self; -#endif return isLocked; } @@ -310,6 +258,7 @@ bool QMutex::tryLock() */ bool QMutex::tryLock(int timeout) { + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); Qt::HANDLE self; if (d->recursive) { @@ -337,9 +286,6 @@ bool QMutex::tryLock(int timeout) return true; } -#ifndef QT_NO_DEBUG - self = QThread::currentThreadId(); -#endif bool isLocked = d->contenders.fetchAndAddAcquire(1) == 0; if (!isLocked) { // didn't get the lock, wait for it @@ -350,9 +296,6 @@ bool QMutex::tryLock(int timeout) if (!isLocked) return false; } -#ifndef QT_NO_DEBUG - d->owner = self; -#endif return true; } @@ -366,8 +309,7 @@ bool QMutex::tryLock(int timeout) */ void QMutex::unlock() { - Q_ASSERT_X(d->owner == QThread::currentThreadId(), "QMutex::unlock()", - "A mutex must be unlocked in the same thread that locked it."); + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); if (d->recursive) { if (!--d->count) { @@ -376,9 +318,6 @@ void QMutex::unlock() d->wakeUp(); } } else { -#ifndef QT_NO_DEBUG - d->owner = 0; -#endif if (!d->contenders.testAndSetRelease(1, 0)) d->wakeUp(); } @@ -506,6 +445,72 @@ void QMutex::unlock() Use the constructor that takes a RecursionMode parameter instead. */ +/*! + \internal helper for lockInline() + */ +void QMutex::lockInternal() +{ + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); + int spinCount = 0; + int lastSpinCount = d->lastSpinCount; + + enum { AdditionalSpins = 20, SpinCountPenalizationDivisor = 4 }; + const int maximumSpinCount = lastSpinCount + AdditionalSpins; + + do { + if (spinCount++ > maximumSpinCount) { + // puts("spinning useless, sleeping"); + bool isLocked = d->contenders.fetchAndAddAcquire(1) == 0; + if (!isLocked) { + + // didn't get the lock, wait for it + isLocked = d->wait(); + Q_ASSERT_X(isLocked, "QMutex::lock", + "Internal error, infinite wait has timed out."); + + // don't need to wait for the lock anymore + d->contenders.deref(); + } + // decrease the lastSpinCount since we didn't actually get the lock by spinning + spinCount = -d->lastSpinCount / SpinCountPenalizationDivisor; + break; + } + } while (d->contenders != 0 || !d->contenders.testAndSetAcquire(0, 1)); + + // adjust the last spin lock count + lastSpinCount = d->lastSpinCount; + d->lastSpinCount = spinCount >= 0 + ? qMax(lastSpinCount, spinCount) + : lastSpinCount + spinCount; +} + +/*! + \internal +*/ +void QMutex::unlockInternal() +{ + static_cast<QMutexPrivate *>(d)->wakeUp(); +} + +/*! + \fn QMutex::lockInline() + \internal + inline version of QMutex::lock() +*/ + +/*! + \fn QMutex::unlockInline() + \internal + inline version of QMutex::unlock() +*/ + +/*! + \fn QMutex::tryLockInline() + \internal + inline version of QMutex::tryLock() +*/ + + QT_END_NAMESPACE #endif // QT_NO_THREAD diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h index 509f300..710b794 100644 --- a/src/corelib/thread/qmutex.h +++ b/src/corelib/thread/qmutex.h @@ -43,6 +43,7 @@ #define QMUTEX_H #include <QtCore/qglobal.h> +#include <QtCore/qatomic.h> #include <new> QT_BEGIN_HEADER @@ -53,7 +54,8 @@ QT_MODULE(Core) #ifndef QT_NO_THREAD -class QMutexPrivate; +class QAtomicInt; +class QMutexData; class Q_CORE_EXPORT QMutex { @@ -66,10 +68,13 @@ public: explicit QMutex(RecursionMode mode = NonRecursive); ~QMutex(); - void lock(); - bool tryLock(); + void lock(); //### Qt5: make inline; + inline void lockInline(); + bool tryLock(); //### Qt5: make inline; bool tryLock(int timeout); - void unlock(); + inline bool tryLockInline(); + void unlock(); //### Qt5: make inline; + inline void unlockInline(); #if defined(QT3_SUPPORT) inline QT3_SUPPORT bool locked() @@ -86,9 +91,11 @@ public: #endif private: + void lockInternal(); + void unlockInternal(); Q_DISABLE_COPY(QMutex) - QMutexPrivate *d; + QMutexData *d; }; class Q_CORE_EXPORT QMutexLocker @@ -99,7 +106,7 @@ public: Q_ASSERT_X((reinterpret_cast<quintptr>(m) & quintptr(1u)) == quintptr(0), "QMutexLocker", "QMutex pointer is misaligned"); if (m) { - m->lock(); + m->lockInline(); val = reinterpret_cast<quintptr>(m) | quintptr(1u); } else { val = 0; @@ -111,7 +118,7 @@ public: { if ((val & quintptr(1u)) == quintptr(1u)) { val &= ~quintptr(1u); - mutex()->unlock(); + mutex()->unlockInline(); } } @@ -119,7 +126,7 @@ public: { if (val) { if ((val & quintptr(1u)) == quintptr(0u)) { - mutex()->lock(); + mutex()->lockInline(); val |= quintptr(1u); } } @@ -145,6 +152,46 @@ private: quintptr val; }; +class QMutexData +{ + public: + QAtomicInt contenders; + const uint recursive : 1; + uint reserved : 31; + protected: + QMutexData(QMutex::RecursionMode mode); + ~QMutexData(); +}; + +inline void QMutex::unlockInline() +{ + if (d->recursive) { + unlock(); + } else if (!d->contenders.testAndSetRelease(1, 0)) { + unlockInternal(); + } +} + +inline bool QMutex::tryLockInline() +{ + if (d->recursive) { + return tryLock(); + } else { + return d->contenders.testAndSetAcquire(0, 1); + } +} + +inline void QMutex::lockInline() +{ + if (d->recursive) { + lock(); + } else if(!tryLockInline()) { + lockInternal(); + } +} + + + #else // QT_NO_THREAD @@ -157,9 +204,11 @@ public: inline ~QMutex() {} static inline void lock() {} - static inline bool tryLock() { return true; } - static inline bool tryLock(int timeout) { Q_UNUSED(timeout); return true; } - static void unlock() {} + static inline void lockInline() {} + static inline bool tryLock(int timeout = 0) { Q_UNUSED(timeout); return true; } + static inline bool tryLockInline() { return true; } + static inline void unlock() {} + static inline void unlockInline() {} #if defined(QT3_SUPPORT) static inline QT3_SUPPORT bool locked() { return false; } diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h index dce162a..6126423 100644 --- a/src/corelib/thread/qmutex_p.h +++ b/src/corelib/thread/qmutex_p.h @@ -56,10 +56,11 @@ #include <QtCore/qglobal.h> #include <QtCore/qnamespace.h> +#include <QtCore/qmutex.h> QT_BEGIN_NAMESPACE -class QMutexPrivate { +class QMutexPrivate : public QMutexData { public: QMutexPrivate(QMutex::RecursionMode mode); ~QMutexPrivate(); @@ -68,8 +69,6 @@ public: bool wait(int timeout = -1); void wakeUp(); - const bool recursive; - QAtomicInt contenders; volatile int lastSpinCount; Qt::HANDLE owner; uint count; @@ -83,6 +82,12 @@ public: #endif }; +inline QMutexData::QMutexData(QMutex::RecursionMode mode) + : recursive(mode == QMutex::Recursive) +{} + +inline QMutexData::~QMutexData() {} + QT_END_NAMESPACE #endif // QMUTEX_P_H diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index a58368c..7e7ef22 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -63,7 +63,7 @@ static void report_error(int code, const char *where, const char *what) QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode) - : recursive(mode == QMutex::Recursive), contenders(0), lastSpinCount(0), owner(0), count(0), wakeup(false) + : QMutexData(mode), lastSpinCount(0), owner(0), count(0), wakeup(false) { report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init"); report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init"); diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp index 9d58953..a810000 100644 --- a/src/corelib/thread/qmutex_win.cpp +++ b/src/corelib/thread/qmutex_win.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode) - : recursive(mode == QMutex::Recursive), contenders(0), lastSpinCount(0), owner(0), count(0) + : QMutexData(mode), lastSpinCount(0), owner(0), count(0) { event = CreateEvent(0, FALSE, FALSE, 0); if (!event) diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h index 702125c..375ded1 100644 --- a/src/corelib/thread/qorderedmutexlocker_p.h +++ b/src/corelib/thread/qorderedmutexlocker_p.h @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE -class QMutex; +#include <QtCore/qmutex.h> /* Locks 2 mutexes in a defined order, avoiding a recursive lock if @@ -79,8 +79,8 @@ public: void relock() { if (!locked) { - if (mtx1) mtx1->lock(); - if (mtx2) mtx2->lock(); + if (mtx1) mtx1->lockInline(); + if (mtx2) mtx2->lockInline(); locked = true; } } @@ -88,8 +88,8 @@ public: void unlock() { if (locked) { - if (mtx1) mtx1->unlock(); - if (mtx2) mtx2->unlock(); + if (mtx1) mtx1->unlockInline(); + if (mtx2) mtx2->unlockInline(); locked = false; } } @@ -100,10 +100,10 @@ public: if (mtx1 == mtx2) return false; if (mtx1 < mtx2) { - mtx2->lock(); + mtx2->lockInline(); return true; } - if (!mtx2->tryLock()) { + if (!mtx2->tryLockInline()) { mtx1->unlock(); mtx2->lock(); mtx1->lock(); diff --git a/src/corelib/thread/qthreadstorage.h b/src/corelib/thread/qthreadstorage.h index 3a786ba..6264674 100644 --- a/src/corelib/thread/qthreadstorage.h +++ b/src/corelib/thread/qthreadstorage.h @@ -91,8 +91,6 @@ inline void qThreadStorage_setLocalData(QThreadStorageData &d, T **t) { (void) d.set(*t); } -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION - // value-based specialization template <typename T> inline @@ -116,8 +114,6 @@ inline void qThreadStorage_setLocalData(QThreadStorageData &d, T *t) { (void) d.set(new T(*t)); } -#endif // QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION - // MOC_SKIP_END #endif diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h index 60cdc9c..bd79904 100644 --- a/src/corelib/tools/qbitarray.h +++ b/src/corelib/tools/qbitarray.h @@ -63,6 +63,10 @@ public: explicit QBitArray(int size, bool val = false); QBitArray(const QBitArray &other) : d(other.d) {} inline QBitArray &operator=(const QBitArray &other) { d = other.d; return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + inline QBitArray &operator=(QBitArray &&other) + { qSwap(d, other.d); return *this; } +#endif inline int size() const { return (d.size() << 3) - *d.constData(); } inline int count() const { return (d.size() << 3) - *d.constData(); } diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 033da90..0a4aad2 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -542,12 +542,14 @@ QByteArray qUncompress(const uchar* data, int nbytes) forever { ulong alloc = len; - d.reset(q_check_ptr(static_cast<QByteArray::Data *>(qRealloc(d.take(), sizeof(QByteArray::Data) + alloc)))); - if (!d) { + QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + alloc)); + if (!p) { // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS qWarning("qUncompress: could not allocate enough memory to uncompress data"); return QByteArray(); } + d.take(); // realloc was successful + d.reset(p); int res = ::uncompress((uchar*)d->array, &len, (uchar*)data+4, nbytes-4); @@ -555,12 +557,14 @@ QByteArray qUncompress(const uchar* data, int nbytes) switch (res) { case Z_OK: if (len != alloc) { - d.reset(q_check_ptr(static_cast<QByteArray::Data *>(qRealloc(d.take(), sizeof(QByteArray::Data) + len)))); - if (!d) { + QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + len)); + if (!p) { // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS qWarning("qUncompress: could not allocate enough memory to uncompress data"); return QByteArray(); } + d.take(); // realloc was successful + d.reset(p); } d->ref = 1; d->alloc = d->size = len; diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index a3fe3f5..3cdcaab 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -144,6 +144,10 @@ public: QByteArray &operator=(const QByteArray &); QByteArray &operator=(const char *str); +#ifdef Q_COMPILER_RVALUE_REFS + inline QByteArray &operator=(QByteArray &&other) + { qSwap(d, other.d); return *this; } +#endif inline int size() const; bool isEmpty() const; diff --git a/src/corelib/tools/qcache.h b/src/corelib/tools/qcache.h index 44477d7..debab7d 100644 --- a/src/corelib/tools/qcache.h +++ b/src/corelib/tools/qcache.h @@ -61,7 +61,7 @@ class QCache }; Node *f, *l; QHash<Key, Node> hash; - void *unused; + void *unused; // ### Qt5: remove int mx, total; inline void unlink(Node &n) { diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h index f767962..4c1a846 100644 --- a/src/corelib/tools/qcontiguouscache.h +++ b/src/corelib/tools/qcontiguouscache.h @@ -110,6 +110,10 @@ public: inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } QContiguousCache<T> &operator=(const QContiguousCache<T> &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QContiguousCache<T> &operator=(QContiguousCache<T> &&other) + { qSwap(d, other.d); return *this; } +#endif bool operator==(const QContiguousCache<T> &other) const; inline bool operator!=(const QContiguousCache<T> &other) const { return !(*this == other); } diff --git a/src/corelib/tools/qelapsedtimer.cpp b/src/corelib/tools/qelapsedtimer.cpp index cb5e701..4adddf9 100644 --- a/src/corelib/tools/qelapsedtimer.cpp +++ b/src/corelib/tools/qelapsedtimer.cpp @@ -136,10 +136,11 @@ QT_BEGIN_NAMESPACE implementations, to guarantee that the same reference clock is being used. - \value SystemTime The human-readable system time. This clock is not monotonic. - \value MonotonicClock The system's monotonic clock, usually found in Unix systems. This clock is monotonic and does not overflow. - \value TickCounter The system's tick counter, used on Windows and Symbian systems. This clock may overflow. - \value MachAbsoluteTime The Mach kernel's absolute time (Mac OS X). This clock is monotonic and does not overflow. + \value SystemTime The human-readable system time. This clock is not monotonic. + \value MonotonicClock The system's monotonic clock, usually found in Unix systems. This clock is monotonic and does not overflow. + \value TickCounter The system's tick counter, used on Windows and Symbian systems. This clock may overflow. + \value MachAbsoluteTime The Mach kernel's absolute time (Mac OS X). This clock is monotonic and does not overflow. + \value PerformanceCounter The high-resolution performance counter provided by Windows. This clock is monotonic and does not overflow. \section2 SystemTime @@ -163,7 +164,9 @@ QT_BEGIN_NAMESPACE The tick counter clock type is based on the system's or the processor's tick counter, multiplied by the duration of a tick. This clock type is - used on Windows and Symbian platforms. + used on Windows and Symbian platforms. If the high-precision performance + counter is available on Windows, the \tt{PerformanceCounter} clock type + is used instead. The TickCounter clock type is the only clock type that may overflow. Windows Vista and Windows Server 2008 support the extended 64-bit tick @@ -191,6 +194,16 @@ QT_BEGIN_NAMESPACE This clock is monotonic and does not overflow. + \section2 PerformanceCounter + + This clock uses the Windows functions \tt{QueryPerformanceCounter} and + \tt{QueryPerformanceFrequency} to access the system's high-precision + performance counter. Since this counter may not be available on all + systems, QElapsedTimer will fall back to the \tt{TickCounter} clock + automatically, if this clock cannot be used. + + This clock is monotonic and does not overflow. + \sa clockType(), isMonotonic() */ diff --git a/src/corelib/tools/qelapsedtimer.h b/src/corelib/tools/qelapsedtimer.h index 0d6f0be..b996f6a 100644 --- a/src/corelib/tools/qelapsedtimer.h +++ b/src/corelib/tools/qelapsedtimer.h @@ -57,7 +57,8 @@ public: SystemTime, MonotonicClock, TickCounter, - MachAbsoluteTime + MachAbsoluteTime, + PerformanceCounter }; static ClockType clockType(); static bool isMonotonic(); diff --git a/src/corelib/tools/qelapsedtimer_win.cpp b/src/corelib/tools/qelapsedtimer_win.cpp index 135196a..c77acaa 100644 --- a/src/corelib/tools/qelapsedtimer_win.cpp +++ b/src/corelib/tools/qelapsedtimer_win.cpp @@ -42,6 +42,9 @@ #include "qelapsedtimer.h" #include <windows.h> +// Result of QueryPerformanceFrequency, 0 indicates that the high resolution timer is unavailable +static quint64 counterFrequency = 0; + typedef ULONGLONG (WINAPI *PtrGetTickCount64)(void); static PtrGetTickCount64 ptrGetTickCount64 = 0; @@ -65,12 +68,44 @@ static void resolveLibs() ptrGetTickCount64 = (PtrGetTickCount64)GetProcAddress(kernel32, "GetTickCount64"); #endif + // Retrieve the number of high-resolution performance counter ticks per second + LARGE_INTEGER frequency; + if (!QueryPerformanceFrequency(&frequency)) { + counterFrequency = 0; + } else { + counterFrequency = frequency.QuadPart; + } + done = true; } +static inline qint64 ticksToMilliseconds(qint64 ticks) +{ + if (counterFrequency > 0) { + // QueryPerformanceCounter uses an arbitrary frequency + return ticks * 1000 / counterFrequency; + } else { + // GetTickCount(64) return milliseconds + return ticks; + } +} + static quint64 getTickCount() { resolveLibs(); + + // This avoids a division by zero and disables the high performance counter if it's not available + if (counterFrequency > 0) { + LARGE_INTEGER counter; + + if (QueryPerformanceCounter(&counter)) { + return counter.QuadPart; + } else { + qWarning("QueryPerformanceCounter failed, although QueryPerformanceFrequency succeeded."); + return 0; + } + } + if (ptrGetTickCount64) return ptrGetTickCount64(); @@ -85,7 +120,12 @@ static quint64 getTickCount() QElapsedTimer::ClockType QElapsedTimer::clockType() { - return TickCounter; + resolveLibs(); + + if (counterFrequency > 0) + return PerformanceCounter; + else + return TickCounter; } bool QElapsedTimer::isMonotonic() @@ -104,22 +144,24 @@ qint64 QElapsedTimer::restart() qint64 oldt1 = t1; t1 = getTickCount(); t2 = 0; - return t1 - oldt1; + return ticksToMilliseconds(t1 - oldt1); } qint64 QElapsedTimer::elapsed() const { - return getTickCount() - t1; + qint64 elapsed = getTickCount() - t1; + return ticksToMilliseconds(elapsed); } qint64 QElapsedTimer::msecsSinceReference() const { - return t1; + return ticksToMilliseconds(t1); } qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const { - return other.t1 - t1; + qint64 difference = other.t1 - t1; + return ticksToMilliseconds(difference); } qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index c7e4bc1..992ff33 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -225,7 +225,7 @@ struct QHashNode inline bool same_key(uint h0, const Key &key0) { return h0 == h && key0 == key; } }; -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION + #define Q_HASH_DECLARE_INT_NODES(key_type) \ template <class T> \ struct QHashDummyNode<key_type, T> { \ @@ -253,7 +253,6 @@ Q_HASH_DECLARE_INT_NODES(ushort); Q_HASH_DECLARE_INT_NODES(int); Q_HASH_DECLARE_INT_NODES(uint); #undef Q_HASH_DECLARE_INT_NODES -#endif // QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION template <class Key, class T> class QHash @@ -284,6 +283,10 @@ public: inline ~QHash() { if (!d->ref.deref()) freeData(d); } QHash<Key, T> &operator=(const QHash<Key, T> &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QHash<Key, T> &operator=(QHash<Key, T> &&other) + { qSwap(d, other.d); return *this; } +#endif bool operator==(const QHash<Key, T> &other) const; inline bool operator!=(const QHash<Key, T> &other) const { return !(*this == other); } @@ -513,8 +516,6 @@ Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode2(QHashData::Node *node) { #ifdef Q_CC_BOR concrete(node)->~QHashNode<Key, T>(); -#elif defined(QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION) - concrete(node)->~QHashNode(); #else concrete(node)->~Node(); #endif diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index 9b3efa3..c087944 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -85,6 +85,10 @@ public: inline QLinkedList(const QLinkedList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach(); } ~QLinkedList(); QLinkedList<T> &operator=(const QLinkedList<T> &); +#ifdef Q_COMPILER_RVALUE_REFS + inline QLinkedList<T> &operator=(QLinkedList<T> &&other) + { qSwap(d, other.d); return *this; } +#endif bool operator==(const QLinkedList<T> &l) const; inline bool operator!=(const QLinkedList<T> &l) const { return !(*this == l); } diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index d843cbe..8f988d6 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -50,6 +50,10 @@ #include <iterator> #include <list> #endif +#ifdef Q_COMPILER_INITIALIZER_LISTS +#include <iterator> +#include <initializer_list> +#endif #include <new> #include <limits.h> @@ -118,6 +122,14 @@ public: inline QList(const QList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach_helper(); } ~QList(); QList<T> &operator=(const QList<T> &l); +#ifdef Q_COMPILER_RVALUE_REFS + inline QList &operator=(QList &&other) + { qSwap(d, other.d); return *this; } +#endif +#ifdef Q_COMPILER_INITIALIZER_LISTS + inline QList(std::initializer_list<T> args) : d(&QListData::shared_null) + { d->ref.ref(); qCopy(args.begin(), args.end(), std::back_inserter(*this)); } +#endif bool operator==(const QList<T> &l) const; inline bool operator!=(const QList<T> &l) const { return !(*this == l); } @@ -713,7 +725,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper() template <typename T> Q_OUTOFLINE_TEMPLATE QList<T>::~QList() { - if (d && !d->ref.deref()) + if (!d->ref.deref()) free(d); } @@ -741,8 +753,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::free(QListData::Data *data) { node_destruct(reinterpret_cast<Node *>(data->array + data->begin), reinterpret_cast<Node *>(data->array + data->end)); - if (data->ref == 0) - qFree(data); + qFree(data); } diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 1c2aad3..ce8fd75 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -107,7 +107,6 @@ template <class Key> inline bool qMapLessThanKey(const Key &key1, const Key &key return key1 < key2; } -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION template <class Ptr> inline bool qMapLessThanKey(Ptr *key1, Ptr *key2) { Q_ASSERT(sizeof(quintptr) == sizeof(Ptr *)); @@ -119,7 +118,6 @@ template <class Ptr> inline bool qMapLessThanKey(const Ptr *key1, const Ptr *key Q_ASSERT(sizeof(quintptr) == sizeof(const Ptr *)); return quintptr(key1) < quintptr(key2); } -#endif // QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION template <class Key, class T> struct QMapNode { @@ -187,6 +185,10 @@ public: inline ~QMap() { if (!d) return; if (!d->ref.deref()) freeData(d); } QMap<Key, T> &operator=(const QMap<Key, T> &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QMap<Key, T> &operator=(QMap<Key, T> &&other) + { qSwap(d, other.d); return *this; } +#endif #ifndef QT_NO_STL explicit QMap(const typename std::map<Key, T> &other); std::map<Key, T> toStdMap() const; @@ -640,13 +642,13 @@ Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::freeData(QMapData *x) while (next != x) { cur = next; next = cur->forward[0]; -#if defined(_MSC_VER) && (_MSC_VER >= 1300) +#if defined(_MSC_VER) #pragma warning(disable:4189) #endif Node *concreteNode = concrete(reinterpret_cast<QMapData::Node *>(cur)); concreteNode->key.~Key(); concreteNode->value.~T(); -#if defined(_MSC_VER) && (_MSC_VER >= 1300) +#if defined(_MSC_VER) #pragma warning(default:4189) #endif } diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index 36827d0..a0df065 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -4172,6 +4172,8 @@ int QRegExp::matchedLength() const } #ifndef QT_NO_REGEXP_CAPTURE + +#ifndef QT_NO_DEPRECATED /*! \obsolete Returns the number of captures contained in the regular expression. @@ -4182,6 +4184,7 @@ int QRegExp::numCaptures() const { return captureCount(); } +#endif /*! \since 4.6 diff --git a/src/corelib/tools/qregexp.h b/src/corelib/tools/qregexp.h index e19c130..0b4a702 100644 --- a/src/corelib/tools/qregexp.h +++ b/src/corelib/tools/qregexp.h @@ -76,6 +76,10 @@ public: QRegExp(const QRegExp &rx); ~QRegExp(); QRegExp &operator=(const QRegExp &rx); +#ifdef Q_COMPILER_RVALUE_REFS + inline QRegExp &operator=(QRegExp &&other) + { qSwap(priv,other.priv); return *this; } +#endif bool operator==(const QRegExp &rx) const; inline bool operator!=(const QRegExp &rx) const { return !operator==(rx); } diff --git a/src/corelib/tools/qscopedpointer.h b/src/corelib/tools/qscopedpointer.h index bc76a3b..40d3851 100644 --- a/src/corelib/tools/qscopedpointer.h +++ b/src/corelib/tools/qscopedpointer.h @@ -54,7 +54,7 @@ struct QScopedPointerDeleter static inline void cleanup(T *pointer) { // Enforce a complete type. - // If you get a compile error here, read the secion on forward declared + // If you get a compile error here, read the section on forward declared // classes in the QScopedPointer documentation. typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; (void) sizeof(IsIncompleteType); @@ -69,7 +69,7 @@ struct QScopedPointerArrayDeleter static inline void cleanup(T *pointer) { // Enforce a complete type. - // If you get a compile error here, read the secion on forward declared + // If you get a compile error here, read the section on forward declared // classes in the QScopedPointer documentation. typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; (void) sizeof(IsIncompleteType); @@ -186,11 +186,18 @@ template <class T, class Cleanup> Q_INLINE_TEMPLATE void qSwap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) { p1.swap(p2); } +namespace QtPrivate { + template <typename X, typename Y> struct QScopedArrayEnsureSameType; + template <typename X> struct QScopedArrayEnsureSameType<X,X> { typedef X* Type; }; + template <typename X> struct QScopedArrayEnsureSameType<const X, X> { typedef X* Type; }; +} + template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> > class QScopedArrayPointer : public QScopedPointer<T, Cleanup> { public: - explicit inline QScopedArrayPointer(T *p = 0) + template <typename D> + explicit inline QScopedArrayPointer(D *p = 0, typename QtPrivate::QScopedArrayEnsureSameType<T,D>::Type = 0) : QScopedPointer<T, Cleanup>(p) { } @@ -206,6 +213,17 @@ public: } private: + explicit inline QScopedArrayPointer(void *) { + // Enforce the same type. + + // If you get a compile error here, make sure you declare + // QScopedArrayPointer with the same template type as you pass to the + // constructor. See also the QScopedPointer documentation. + + // Storing a scalar array as a pointer to a different type is not + // allowed and results in undefined behavior. + } + Q_DISABLE_COPY(QScopedArrayPointer) }; diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index fe50d4d..dc3c45a 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -61,6 +61,10 @@ public: inline QSet<T> &operator=(const QSet<T> &other) { q_hash = other.q_hash; return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + inline QSet<T> &operator=(QSet<T> &&other) + { qSwap(q_hash, other.q_hash); return *this; } +#endif inline bool operator==(const QSet<T> &other) const { return q_hash == other.q_hash; } diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index 6483c90..b646a9d 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -113,6 +113,10 @@ public: } return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) + { qSwap(d, other.d); return *this; } +#endif inline bool operator!() const { return !d; } @@ -163,14 +167,12 @@ public: explicit QExplicitlySharedDataPointer(T *data); inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); } -#ifndef QT_NO_MEMBER_TEMPLATES template<class X> inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) : d(static_cast<T *>(o.data())) { if(d) d->ref.ref(); } -#endif inline QExplicitlySharedDataPointer<T> & operator=(const QExplicitlySharedDataPointer<T> &o) { if (o.d != d) { @@ -194,6 +196,10 @@ public: } return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) + { qSwap(d, other.d); return *this; } +#endif inline bool operator!() const { return !d; } diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 5fac960..8f9559a 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -1275,8 +1275,6 @@ QT_END_NAMESPACE -#if !defined(QT_NO_MEMBER_TEMPLATES) - //# define QT_SHARED_POINTER_BACKTRACE_SUPPORT # ifdef QT_SHARED_POINTER_BACKTRACE_SUPPORT # if defined(__GLIBC__) && (__GLIBC__ >= 2) && !defined(__UCLIBC__) && !defined(QT_LINUXBASE) @@ -1501,5 +1499,3 @@ void QtSharedPointer::internalSafetyCheckCleanCheck() } QT_END_NAMESPACE - -#endif diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h index c51ade6..e0f4dca 100644 --- a/src/corelib/tools/qsharedpointer.h +++ b/src/corelib/tools/qsharedpointer.h @@ -47,10 +47,7 @@ #include <QtCore/qshareddata.h> #ifndef Q_QDOC -# if !defined(QT_NO_MEMBER_TEMPLATES) -// QSharedPointer requires member template support # include <QtCore/qsharedpointer_impl.h> -# endif #else QT_BEGIN_HEADER diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 4cce339..20dda12 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -109,7 +109,6 @@ namespace QtSharedPointer { template <class T> inline void normalDeleter(T *t) { delete t; } // this uses partial template specialization - // the only compilers that didn't support this were MSVC 6.0 and 2002 template <class T> struct RemovePointer; template <class T> struct RemovePointer<T *> { typedef T Type; }; template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; }; @@ -323,7 +322,6 @@ namespace QtSharedPointer { protected: typedef ExternalRefCountData Data; - inline void ref() const { d->weakref.ref(); d->strongref.ref(); } inline void deref() { deref(d, this->value); } static inline void deref(Data *d, T *value) @@ -388,7 +386,13 @@ namespace QtSharedPointer { template <class X> inline void internalCopy(const ExternalRefCount<X> &other) { - internalSet(other.d, other.data()); + Data *o = other.d; + T *actual = other.value; + if (o) + other.ref(); + qSwap(d, o); + qSwap(this->value, actual); + deref(o, actual); } inline void internalSwap(ExternalRefCount &other) @@ -404,6 +408,7 @@ namespace QtSharedPointer { template <class X> friend class QT_PREPEND_NAMESPACE(QWeakPointer); template <class X, class Y> friend QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src); #endif + inline void ref() const { d->weakref.ref(); d->strongref.ref(); } inline void internalSet(Data *o, T *actual) { @@ -460,6 +465,13 @@ public: BaseClass::internalCopy(other); return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + inline QSharedPointer<T> &operator=(QSharedPointer<T> &&other) + { + QSharedPointer<T>::internalSwap(other); + return *this; + } +#endif template <class X> inline QSharedPointer(const QSharedPointer<X> &other) : BaseClass(other) @@ -844,9 +856,13 @@ qobject_cast(const QWeakPointer<T> &src) { return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src); } - #endif + +template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_MOVABLE_TYPE); +template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedPointer<T>, Q_MOVABLE_TYPE); + + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 3521b31..7589f59 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -111,7 +111,23 @@ int qFindString(const QChar *haystack, int haystackLen, int from, const QChar *needle, int needleLen, Qt::CaseSensitivity cs); int qFindStringBoyerMoore(const QChar *haystack, int haystackLen, int from, const QChar *needle, int needleLen, Qt::CaseSensitivity cs); - +static inline int qt_last_index_of(const QChar *haystack, int haystackLen, const QChar &needle, + int from, Qt::CaseSensitivity cs); +static inline int qt_string_count(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, + Qt::CaseSensitivity cs); +static inline int qt_string_count(const QChar *haystack, int haystackLen, + const QChar &needle, Qt::CaseSensitivity cs); +static inline int qt_find_latin1_string(const QChar *hay, int size, const QLatin1String &needle, + int from, Qt::CaseSensitivity cs); +static inline bool qt_starts_with(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs); +static inline bool qt_starts_with(const QChar *haystack, int haystackLen, + const QLatin1String &needle, Qt::CaseSensitivity cs); +static inline bool qt_ends_with(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs); +static inline bool qt_ends_with(const QChar *haystack, int haystackLen, + const QLatin1String &needle, Qt::CaseSensitivity cs); // Unicode case-insensitive comparison static int ucstricmp(const ushort *a, const ushort *ae, const ushort *b, const ushort *be) @@ -350,11 +366,7 @@ inline char qToLower(char ch) return ch; } -#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 -const QString::Null QString::null; -#else const QString::Null QString::null = { }; -#endif /*! \macro QT_NO_CAST_FROM_ASCII @@ -945,6 +957,24 @@ QString QString::fromWCharArray(const wchar_t *string, int size) \sa utf16(), toAscii(), toLatin1(), toUtf8(), toLocal8Bit() */ +template<typename T> int toUcs4_helper(const unsigned short *uc, int length, T *out) +{ + int i = 0; + for (; i < length; ++i) { + uint u = uc[i]; + if (QChar::isHighSurrogate(u) && i < length-1) { + ushort low = uc[i+1]; + if (QChar::isLowSurrogate(low)) { + ++i; + u = QChar::surrogateToUcs4(u, low); + } + } + *out = T(u); + ++out; + } + return i; +} + /*! \since 4.2 @@ -969,21 +999,7 @@ int QString::toWCharArray(wchar_t *array) const memcpy(array, utf16(), sizeof(wchar_t)*length()); return length(); } else { - wchar_t *a = array; - const unsigned short *uc = utf16(); - for (int i = 0; i < length(); ++i) { - uint u = uc[i]; - if (QChar::isHighSurrogate(u) && i + 1 < length()) { - ushort low = uc[i+1]; - if (QChar::isLowSurrogate(low)) { - u = QChar::surrogateToUcs4(u, low); - ++i; - } - } - *a = wchar_t(u); - ++a; - } - return a - array; + return toUcs4_helper<wchar_t>(utf16(), length(), array); } } @@ -1316,7 +1332,9 @@ void QString::realloc(int alloc) asciiCache->remove(d); } #endif - d = static_cast<Data *>(q_check_ptr(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar)))); + Data *p = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar))); + Q_CHECK_PTR(p); + d = p; d->alloc = alloc; d->data = d->array; } @@ -2480,14 +2498,10 @@ int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const \sa lastIndexOf(), contains(), count() */ + int QString::indexOf(const QLatin1String &str, int from, Qt::CaseSensitivity cs) const { - int len = qstrlen(str.latin1()); - QVarLengthArray<ushort> s(len); - for (int i = 0; i < len; ++i) - s[i] = str.latin1()[i]; - - return qFindString(unicode(), length(), from, (const QChar *)s.data(), len, cs); + return qt_find_latin1_string(unicode(), size(), str, from, cs); } int qFindString( @@ -2577,6 +2591,23 @@ int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const return findChar(unicode(), length(), ch, from, cs); } +/*! + \since 4.8 + + \overload indexOf() + + Returns the index position of the first occurrence of the string + reference \a str in this string, searching forward from index + position \a from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. +*/ +int QString::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const +{ + return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs); +} + static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *needle, int sl, Qt::CaseSensitivity cs) { /* @@ -2656,12 +2687,13 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c if (from > delta) from = delta; - return lastIndexOfHelper(d->data, from, str.d->data, str.d->size, cs); } /*! \since 4.5 + \overload lastIndexOf() + Returns the index position of the last occurrence of the string \a str in this string, searching backward from index position \a from. If \a from is -1 (default), the search starts at the last @@ -2709,26 +2741,43 @@ int QString::lastIndexOf(const QLatin1String &str, int from, Qt::CaseSensitivity */ int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const { - ushort c = ch.unicode(); - if (from < 0) - from += d->size; - if (from < 0 || from >= d->size) - return -1; - if (from >= 0) { - const ushort *n = d->data + from; - const ushort *b = d->data; - if (cs == Qt::CaseSensitive) { - for (; n >= b; --n) - if (*n == c) - return n - b; - } else { - c = foldCase(c); - for (; n >= b; --n) - if (foldCase(*n) == c) - return n - b; - } + return qt_last_index_of(unicode(), size(), ch, from, cs); } + +/*! + \since 4.8 + \overload lastIndexOf() + + Returns the index position of the last occurrence of the string + reference \a str in this string, searching backward from index + position \a from. If \a from is -1 (default), the search starts at + the last character; if \a from is -2, at the next to last character + and so on. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa indexOf(), contains(), count() +*/ +int QString::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const +{ + const int sl = str.size(); + if (sl == 1) + return lastIndexOf(str.at(0), from, cs); + + const int l = d->size; + if (from < 0) + from += l; + int delta = l - sl; + if (from == l && sl == 0) + return from; + if (from < 0 || from >= l || delta < 0) return -1; + if (from > delta) + from = delta; + + return lastIndexOfHelper(d->data, from, reinterpret_cast<const ushort*>(str.unicode()), + str.size(), cs); } #ifndef QT_NO_REGEXP @@ -2903,19 +2952,10 @@ QString& QString::replace(const QRegExp &rx, const QString &after) \sa contains(), indexOf() */ + int QString::count(const QString &str, Qt::CaseSensitivity cs) const { - int num = 0; - int i = -1; - if (d->size > 500 && str.d->size > 5) { - QStringMatcher matcher(str, cs); - while ((i = matcher.indexIn(*this, i + 1)) != -1) - ++num; - } else { - while ((i = indexOf(str, i + 1, cs)) != -1) - ++num; - } - return num; + return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); } /*! @@ -2923,25 +2963,29 @@ int QString::count(const QString &str, Qt::CaseSensitivity cs) const Returns the number of occurrences of character \a ch in the string. */ + int QString::count(QChar ch, Qt::CaseSensitivity cs) const { - ushort c = ch.unicode(); - int num = 0; - const ushort *i = d->data + d->size; - const ushort *b = d->data; - if (cs == Qt::CaseSensitive) { - while (i != b) - if (*--i == c) - ++num; - } else { - c = foldCase(c); - while (i != b) - if (foldCase(*(--i)) == c) - ++num; + return qt_string_count(unicode(), size(), ch, cs); } - return num; + +/*! + \since 4.8 + \overload count() + Returns the number of (potentially overlapping) occurrences of the + string reference \a str in this string. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa contains(), indexOf() +*/ +int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const +{ + return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); } + /*! \fn bool QString::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Returns true if this string contains an occurrence of the string @@ -2964,6 +3008,18 @@ int QString::count(QChar ch, Qt::CaseSensitivity cs) const character \a ch; otherwise returns false. */ +/*! \fn bool QString::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + \since 4.8 + + Returns true if this string contains an occurrence of the string + reference \a str; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa indexOf(), count() +*/ + /*! \fn bool QString::contains(const QRegExp &rx) const \overload contains() @@ -3365,22 +3421,8 @@ QString QString::mid(int position, int n) const */ bool QString::startsWith(const QString& s, Qt::CaseSensitivity cs) const { - if (d == &shared_null) - return (s.d == &shared_null); - if (d->size == 0) - return s.d->size == 0; - if (s.d->size > d->size) - return false; - if (cs == Qt::CaseSensitive) { - return qMemEquals(d->data, s.d->data, s.d->size); - } else { - uint last = 0; - uint olast = 0; - for (int i = 0; i < s.d->size; ++i) - if (foldCase(d->data[i], last) != foldCase(s.d->data[i], olast)) - return false; - } - return true; + return qt_starts_with(isNull() ? 0 : unicode(), size(), + s.isNull() ? 0 : s.unicode(), s.size(), cs); } /*! @@ -3388,24 +3430,7 @@ bool QString::startsWith(const QString& s, Qt::CaseSensitivity cs) const */ bool QString::startsWith(const QLatin1String& s, Qt::CaseSensitivity cs) const { - if (d == &shared_null) - return (s.latin1() == 0); - if (d->size == 0) - return !s.latin1() || *s.latin1() == 0; - int slen = qstrlen(s.latin1()); - if (slen > d->size) - return false; - const uchar *latin = (const uchar *)s.latin1(); - if (cs == Qt::CaseSensitive) { - for (int i = 0; i < slen; ++i) - if (d->data[i] != latin[i]) - return false; - } else { - for (int i = 0; i < slen; ++i) - if (foldCase(d->data[i]) != foldCase((ushort)latin[i])) - return false; - } - return true; + return qt_starts_with(isNull() ? 0 : unicode(), size(), s, cs); } /*! @@ -3423,6 +3448,23 @@ bool QString::startsWith(const QChar &c, Qt::CaseSensitivity cs) const } /*! + \since 4.8 + \overload + Returns true if the string starts with the string reference \a s; + otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa endsWith() +*/ +bool QString::startsWith(const QStringRef &s, Qt::CaseSensitivity cs) const +{ + return qt_starts_with(isNull() ? 0 : unicode(), size(), + s.isNull() ? 0 : s.unicode(), s.size(), cs); +} + +/*! Returns true if the string ends with \a s; otherwise returns false. @@ -3435,49 +3477,34 @@ bool QString::startsWith(const QChar &c, Qt::CaseSensitivity cs) const */ bool QString::endsWith(const QString& s, Qt::CaseSensitivity cs) const { - if (d == &shared_null) - return (s.d == &shared_null); - if (d->size == 0) - return s.d->size == 0; - int pos = d->size - s.d->size; - if (pos < 0) - return false; - if (cs == Qt::CaseSensitive) { - return qMemEquals(d->data + pos, s.d->data, s.d->size); - } else { - uint last = 0; - uint olast = 0; - for (int i = 0; i < s.length(); i++) - if (foldCase(d->data[pos+i], last) != foldCase(s.d->data[i], olast)) - return false; + return qt_ends_with(isNull() ? 0 : unicode(), size(), + s.isNull() ? 0 : s.unicode(), s.size(), cs); } - return true; + +/*! + \since 4.8 + \overload endsWith() + Returns true if the string ends with the string reference \a s; + otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa startsWith() +*/ +bool QString::endsWith(const QStringRef &s, Qt::CaseSensitivity cs) const +{ + return qt_ends_with(isNull() ? 0 : unicode(), size(), + s.isNull() ? 0 : s.unicode(), s.size(), cs); } + /*! \overload endsWith() */ bool QString::endsWith(const QLatin1String& s, Qt::CaseSensitivity cs) const { - if (d == &shared_null) - return (s.latin1() == 0); - if (d->size == 0) - return !s.latin1() || *s.latin1() == 0; - int slen = qstrlen(s.latin1()); - int pos = d->size - slen; - const uchar *latin = (const uchar *)s.latin1(); - if (pos < 0) - return false; - if (cs == Qt::CaseSensitive) { - for (int i = 0; i < slen; i++) - if (d->data[pos+i] != latin[i]) - return false; - } else { - for (int i = 0; i < slen; i++) - if (foldCase(d->data[pos+i]) != foldCase((ushort)latin[i])) - return false; - } - return true; + return qt_ends_with(isNull() ? 0 : unicode(), size(), s, cs); } /*! @@ -3716,20 +3743,8 @@ QVector<uint> QString::toUcs4() const { QVector<uint> v(length()); uint *a = v.data(); - const unsigned short *uc = utf16(); - for (int i = 0; i < length(); ++i) { - uint u = uc[i]; - if (QChar(u).isHighSurrogate() && i < length()-1) { - ushort low = uc[i+1]; - if (QChar(low).isLowSurrogate()) { - ++i; - u = QChar::surrogateToUcs4(u, low); - } - } - *a = u; - ++a; - } - v.resize(a - v.data()); + int len = toUcs4_helper<uint>(utf16(), length(), a); + v.resize(len); return v; } @@ -7659,6 +7674,7 @@ QDataStream &operator>>(QDataStream &in, QString &str) Use the startsWith(QString, Qt::CaseSensitive) overload instead. */ + /*! \fn bool QString::endsWith(const QString &s, bool cs) const @@ -8364,4 +8380,717 @@ QStringRef QString::midRef(int position, int n) const return QStringRef(this, position, n); } +/*! + \since 4.8 + + Returns the index position of the first occurrence of the string \a + str in this string reference, searching forward from index position + \a from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + If \a from is -1, the search starts at the last character; if it is + -2, at the next to last character and so on. + + \sa QString::indexOf(), lastIndexOf(), contains(), count() +*/ +int QStringRef::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const +{ + return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs); +} + +/*! + \since 4.8 + \overload indexOf() + + Returns the index position of the first occurrence of the + character \a ch in the string reference, searching forward from + index position \a from. Returns -1 if \a ch could not be found. + + \sa QString::indexOf(), lastIndexOf(), contains(), count() +*/ +int QStringRef::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const +{ + return findChar(unicode(), length(), ch, from, cs); +} + +/*! + \since 4.8 + + Returns the index position of the first occurrence of the string \a + str in this string reference, searching forward from index position + \a from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + If \a from is -1, the search starts at the last character; if it is + -2, at the next to last character and so on. + + \sa QString::indexOf(), lastIndexOf(), contains(), count() +*/ +int QStringRef::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const +{ + return qt_find_latin1_string(unicode(), size(), str, from, cs); +} + +/*! + \since 4.8 + + \overload indexOf() + + Returns the index position of the first occurrence of the string + reference \a str in this string reference, searching forward from + index position \a from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::indexOf(), lastIndexOf(), contains(), count() +*/ +int QStringRef::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const +{ + return qFindString(unicode(), size(), from, str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + + Returns the index position of the last occurrence of the string \a + str in this string reference, searching backward from index position + \a from. If \a from is -1 (default), the search starts at the last + character; if \a from is -2, at the next to last character and so + on. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::lastIndexOf(), indexOf(), contains(), count() +*/ +int QStringRef::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const +{ + const int sl = str.size(); + if (sl == 1) + return lastIndexOf(str.at(0), from, cs); + + const int l = size();; + if (from < 0) + from += l; + int delta = l - sl; + if (from == l && sl == 0) + return from; + if (from < 0 || from >= l || delta < 0) + return -1; + if (from > delta) + from = delta; + + return lastIndexOfHelper(reinterpret_cast<const ushort*>(unicode()), from, + reinterpret_cast<const ushort*>(str.unicode()), str.size(), cs); +} + +/*! + \since 4.8 + \overload lastIndexOf() + + Returns the index position of the last occurrence of the character + \a ch, searching backward from position \a from. + + \sa QString::lastIndexOf(), indexOf(), contains(), count() +*/ +int QStringRef::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const +{ + return qt_last_index_of(unicode(), size(), ch, from, cs); +} + +/*! + \since 4.8 + \overload lastIndexOf() + + Returns the index position of the last occurrence of the string \a + str in this string reference, searching backward from index position + \a from. If \a from is -1 (default), the search starts at the last + character; if \a from is -2, at the next to last character and so + on. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::lastIndexOf(), indexOf(), contains(), count() +*/ +int QStringRef::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const +{ + const int sl = qstrlen(str.latin1()); + if (sl == 1) + return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs); + + const int l = size(); + if (from < 0) + from += l; + int delta = l - sl; + if (from == l && sl == 0) + return from; + if (from < 0 || from >= l || delta < 0) + return -1; + if (from > delta) + from = delta; + + QVarLengthArray<ushort> s(sl); + for (int i = 0; i < sl; ++i) + s[i] = str.latin1()[i]; + + return lastIndexOfHelper(reinterpret_cast<const ushort*>(unicode()), from, s.data(), sl, cs); +} + +/*! + \since 4.8 + \overload lastIndexOf() + + Returns the index position of the last occurrence of the string + reference \a str in this string reference, searching backward from + index position \a from. If \a from is -1 (default), the search + starts at the last character; if \a from is -2, at the next to last + character and so on. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::lastIndexOf(), indexOf(), contains(), count() +*/ +int QStringRef::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const +{ + const int sl = str.size(); + if (sl == 1) + return lastIndexOf(str.at(0), from, cs); + + const int l = size(); + if (from < 0) + from += l; + int delta = l - sl; + if (from == l && sl == 0) + return from; + if (from < 0 || from >= l || delta < 0) + return -1; + if (from > delta) + from = delta; + + return lastIndexOfHelper(reinterpret_cast<const ushort*>(unicode()), from, + reinterpret_cast<const ushort*>(str.unicode()), + str.size(), cs); +} + +/*! + \since 4.8 + Returns the number of (potentially overlapping) occurrences of + the string \a str in this string reference. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa QString::count(), contains(), indexOf() +*/ +int QStringRef::count(const QString &str, Qt::CaseSensitivity cs) const +{ + return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + \overload count() + + Returns the number of occurrences of the character \a ch in the + string reference. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa QString::count(), contains(), indexOf() +*/ +int QStringRef::count(QChar ch, Qt::CaseSensitivity cs) const +{ + return qt_string_count(unicode(), size(), ch, cs); +} + +/*! + \since 4.8 + \overload count() + + Returns the number of (potentially overlapping) occurrences of the + string reference \a str in this string reference. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa QString::count(), contains(), indexOf() +*/ +int QStringRef::count(const QStringRef &str, Qt::CaseSensitivity cs) const +{ + return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + + Returns true if the string reference starts with \a str; otherwise + returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa QString::startsWith(), endsWith() +*/ +bool QStringRef::startsWith(const QString &str, Qt::CaseSensitivity cs) const +{ + return qt_starts_with(isNull() ? 0 : unicode(), size(), + str.isNull() ? 0 : str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + \overload startsWith() + \sa QString::startsWith(), endsWith() +*/ +bool QStringRef::startsWith(QLatin1String str, Qt::CaseSensitivity cs) const +{ + return qt_starts_with(isNull() ? 0 : unicode(), size(), str, cs); +} + +/*! + \since 4.8 + \overload startsWith() + \sa QString::startsWith(), endsWith() +*/ +bool QStringRef::startsWith(const QStringRef &str, Qt::CaseSensitivity cs) const +{ + return qt_starts_with(isNull() ? 0 : unicode(), size(), + str.isNull() ? 0 : str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + \overload startsWith() + + Returns true if the string reference starts with \a ch; otherwise + returns false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::startsWith(), endsWith() +*/ +bool QStringRef::startsWith(QChar ch, Qt::CaseSensitivity cs) const +{ + if (!isEmpty()) { + const ushort *data = reinterpret_cast<const ushort*>(unicode()); + return (cs == Qt::CaseSensitive + ? data[0] == ch + : foldCase(data[0]) == foldCase(ch.unicode())); + } else { + return false; + } +} + +/*! + \since 4.8 + Returns true if the string reference ends with \a str; otherwise + returns false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::endsWith(), startsWith() +*/ +bool QStringRef::endsWith(const QString &str, Qt::CaseSensitivity cs) const +{ + return qt_ends_with(isNull() ? 0 : unicode(), size(), + str.isNull() ? 0 : str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + \overload endsWith() + + Returns true if the string reference ends with \a ch; otherwise + returns false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::endsWith(), endsWith() +*/ +bool QStringRef::endsWith(QChar ch, Qt::CaseSensitivity cs) const +{ + if (!isEmpty()) { + const ushort *data = reinterpret_cast<const ushort*>(unicode()); + const int size = length(); + return (cs == Qt::CaseSensitive + ? data[size - 1] == ch + : foldCase(data[size - 1]) == foldCase(ch.unicode())); + } else { + return false; + } +} + +/*! + \since 4.8 + \overload endsWith() + \sa QString::endsWith(), endsWith() +*/ +bool QStringRef::endsWith(QLatin1String str, Qt::CaseSensitivity cs) const +{ + return qt_ends_with(isNull() ? 0 : unicode(), size(), str, cs); +} + +/*! + \since 4.8 + \overload endsWith() + \sa QString::endsWith(), endsWith() +*/ +bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const +{ + return qt_ends_with(isNull() ? 0 : unicode(), size(), + str.isNull() ? 0 : str.unicode(), str.size(), cs); +} + + +/*! \fn bool QStringRef::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + + \since 4.8 + Returns true if this string reference contains an occurrence of + the string \a str; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa indexOf(), count() +*/ + +/*! \fn bool QStringRef::contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + + \overload contains() + \since 4.8 + + Returns true if this string contains an occurrence of the + character \a ch; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + +*/ + +/*! \fn bool QStringRef::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + \overload contains() + \since 4.8 + + Returns true if this string reference contains an occurrence of + the string reference \a str; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa indexOf(), count() +*/ + +/*! \fn bool QStringRef::contains(QLatin1String str, Qt::CaseSensitivity cs) const + \since 4,8 + \overload contains() + + Returns true if this string reference contains an occurrence of + the string \a str; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa indexOf(), count() +*/ + +static inline int qt_last_index_of(const QChar *haystack, int haystackLen, const QChar &needle, + int from, Qt::CaseSensitivity cs) +{ + ushort c = needle.unicode(); + if (from < 0) + from += haystackLen; + if (from < 0 || from >= haystackLen) + return -1; + if (from >= 0) { + const ushort *b = reinterpret_cast<const ushort*>(haystack); + const ushort *n = b + from; + if (cs == Qt::CaseSensitive) { + for (; n >= b; --n) + if (*n == c) + return n - b; + } else { + c = foldCase(c); + for (; n >= b; --n) + if (foldCase(*n) == c) + return n - b; + } + } + return -1; + + +} + +static inline int qt_string_count(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, + Qt::CaseSensitivity cs) +{ + int num = 0; + int i = -1; + if (haystackLen > 500 && needleLen > 5) { + QStringMatcher matcher(needle, needleLen, cs); + while ((i = matcher.indexIn(haystack, haystackLen, i + 1)) != -1) + ++num; + } else { + while ((i = qFindString(haystack, haystackLen, i + 1, needle, needleLen, cs)) != -1) + ++num; + } + return num; +} + +static inline int qt_string_count(const QChar *unicode, int size, const QChar &ch, + Qt::CaseSensitivity cs) +{ + ushort c = ch.unicode(); + int num = 0; + const ushort *b = reinterpret_cast<const ushort*>(unicode); + const ushort *i = b + size; + if (cs == Qt::CaseSensitive) { + while (i != b) + if (*--i == c) + ++num; + } else { + c = foldCase(c); + while (i != b) + if (foldCase(*(--i)) == c) + ++num; + } + return num; +} + +static inline int qt_find_latin1_string(const QChar *haystack, int size, + const QLatin1String &needle, + int from, Qt::CaseSensitivity cs) +{ + const char *latin1 = needle.latin1(); + int len = qstrlen(latin1); + QVarLengthArray<ushort> s(len); + for (int i = 0; i < len; ++i) + s[i] = latin1[i]; + + return qFindString(haystack, size, from, + reinterpret_cast<const QChar*>(s.constData()), len, cs); +} + +static inline bool qt_starts_with(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs) +{ + if (!haystack) + return !needle; + if (haystackLen == 0) + return needleLen == 0; + if (needleLen > haystackLen) + return false; + + const ushort *h = reinterpret_cast<const ushort*>(haystack); + const ushort *n = reinterpret_cast<const ushort*>(needle); + + if (cs == Qt::CaseSensitive) { + return qMemEquals(h, n, needleLen); + } else { + uint last = 0; + uint olast = 0; + for (int i = 0; i < needleLen; ++i) + if (foldCase(h[i], last) != foldCase(n[i], olast)) + return false; + } + return true; +} + +static inline bool qt_starts_with(const QChar *haystack, int haystackLen, + const QLatin1String &needle, Qt::CaseSensitivity cs) +{ + if (!haystack) + return !needle.latin1(); + if (haystackLen == 0) + return !needle.latin1() || *needle.latin1() == 0; + const int slen = qstrlen(needle.latin1()); + if (slen > haystackLen) + return false; + const ushort *data = reinterpret_cast<const ushort*>(haystack); + const uchar *latin = reinterpret_cast<const uchar*>(needle.latin1()); + if (cs == Qt::CaseSensitive) { + for (int i = 0; i < slen; ++i) + if (data[i] != latin[i]) + return false; + } else { + for (int i = 0; i < slen; ++i) + if (foldCase(data[i]) != foldCase((ushort)latin[i])) + return false; + } + return true; +} + +static inline bool qt_ends_with(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs) +{ + if (!haystack) + return !needle; + if (haystackLen == 0) + return needleLen == 0; + const int pos = haystackLen - needleLen; + if (pos < 0) + return false; + + const ushort *h = reinterpret_cast<const ushort*>(haystack); + const ushort *n = reinterpret_cast<const ushort*>(needle); + + if (cs == Qt::CaseSensitive) { + return qMemEquals(h + pos, n, needleLen); + } else { + uint last = 0; + uint olast = 0; + for (int i = 0; i < needleLen; i++) + if (foldCase(h[pos+i], last) != foldCase(n[i], olast)) + return false; + } + return true; +} + + +static inline bool qt_ends_with(const QChar *haystack, int haystackLen, + const QLatin1String &needle, Qt::CaseSensitivity cs) +{ + if (!haystack) + return !needle.latin1(); + if (haystackLen == 0) + return !needle.latin1() || *needle.latin1() == 0; + const int slen = qstrlen(needle.latin1()); + int pos = haystackLen - slen; + if (pos < 0) + return false; + const uchar *latin = reinterpret_cast<const uchar*>(needle.latin1()); + const ushort *data = reinterpret_cast<const ushort*>(haystack); + if (cs == Qt::CaseSensitive) { + for (int i = 0; i < slen; i++) + if (data[pos+i] != latin[i]) + return false; + } else { + for (int i = 0; i < slen; i++) + if (foldCase(data[pos+i]) != foldCase((ushort)latin[i])) + return false; + } + return true; +} + +/*! + \since 4.8 + + Returns a Latin-1 representation of the string as a QByteArray. + + The returned byte array is undefined if the string contains non-Latin1 + characters. Those characters may be suppressed or replaced with a + question mark. + + \sa toAscii(), toUtf8(), toLocal8Bit(), QTextCodec +*/ +QByteArray QStringRef::toLatin1() const +{ + return toLatin1_helper(unicode(), length()); +} + +/*! + \since 4.8 + + Returns an 8-bit representation of the string as a QByteArray. + + If a codec has been set using QTextCodec::setCodecForCStrings(), + it is used to convert Unicode to 8-bit char; otherwise this + function does the same as toLatin1(). + + Note that, despite the name, this function does not necessarily return an US-ASCII + (ANSI X3.4-1986) string and its result may not be US-ASCII compatible. + + \sa toLatin1(), toUtf8(), toLocal8Bit(), QTextCodec +*/ +QByteArray QStringRef::toAscii() const +{ +#ifndef QT_NO_TEXTCODEC + if (QString::codecForCStrings) + return QString::codecForCStrings->fromUnicode(unicode(), length()); +#endif // QT_NO_TEXTCODEC + return toLatin1(); +} + +/*! + \since 4.8 + + Returns the local 8-bit representation of the string as a + QByteArray. The returned byte array is undefined if the string + contains characters not supported by the local 8-bit encoding. + + QTextCodec::codecForLocale() is used to perform the conversion from + Unicode. If the locale encoding could not be determined, this function + does the same as toLatin1(). + + If this string contains any characters that cannot be encoded in the + locale, the returned byte array is undefined. Those characters may be + suppressed or replaced by another. + + \sa toAscii(), toLatin1(), toUtf8(), QTextCodec +*/ +QByteArray QStringRef::toLocal8Bit() const +{ +#ifndef QT_NO_TEXTCODEC + if (QTextCodec::codecForLocale()) + return QTextCodec::codecForLocale()->fromUnicode(unicode(), length()); +#endif // QT_NO_TEXTCODEC + return toLatin1(); +} + +/*! + \since 4.8 + + Returns a UTF-8 representation of the string as a QByteArray. + + UTF-8 is a Unicode codec and can represent all characters in a Unicode + string like QString. + + However, in the Unicode range, there are certain codepoints that are not + considered characters. The Unicode standard reserves the last two + codepoints in each Unicode Plane (U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, + U+2FFFE, etc.), as well as 16 codepoints in the range U+FDD0..U+FDDF, + inclusive, as non-characters. If any of those appear in the string, they + may be discarded and will not appear in the UTF-8 representation, or they + may be replaced by one or more replacement characters. + + \sa toAscii(), toLatin1(), toLocal8Bit(), QTextCodec +*/ +QByteArray QStringRef::toUtf8() const +{ + if (isNull()) + return QByteArray(); + + return QUtf8::convertFromUnicode(constData(), length(), 0); +} + +/*! + \since 4.8 + + Returns a UCS-4/UTF-32 representation of the string as a QVector<uint>. + + UCS-4 is a Unicode codec and is lossless. All characters from this string + can be encoded in UCS-4. + + \sa fromUtf8(), toAscii(), toLatin1(), toLocal8Bit(), QTextCodec, fromUcs4(), toWCharArray() +*/ +QVector<uint> QStringRef::toUcs4() const +{ + QVector<uint> v(length()); + uint *a = v.data(); + int len = toUcs4_helper<uint>(reinterpret_cast<const unsigned short *>(unicode()), length(), a); + v.resize(len); + return v; +} + QT_END_NAMESPACE diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 06e4d47..589fdc2 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -51,14 +51,7 @@ #endif #ifndef QT_NO_STL -# if defined (Q_CC_MSVC_NET) && _MSC_VER < 1310 // Avoids nasty warning for xlocale, line 450 -# pragma warning (push) -# pragma warning (disable : 4189) -# include <string> -# pragma warning (pop) -# else -# include <string> -# endif +# include <string> # ifndef QT_NO_STL_WCHAR // workaround for some headers not typedef'ing std::wstring @@ -111,7 +104,10 @@ public: QString &operator=(QChar c); QString &operator=(const QString &); inline QString &operator=(const QLatin1String &); - +#ifdef Q_COMPILER_RVALUE_REFS + inline QString &operator=(QString &&other) + { qSwap(d, other.d); return *this; } +#endif inline int size() const { return d->size; } inline int count() const { return d->size; } inline int length() const; @@ -198,14 +194,18 @@ public: int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int indexOf(const QString &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int indexOf(const QLatin1String &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int indexOf(const QStringRef &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int lastIndexOf(QChar c, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int lastIndexOf(const QString &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int lastIndexOf(const QLatin1String &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(const QStringRef &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; inline QBool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; inline QBool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QBool contains(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int count(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; #ifndef QT_NO_REGEXP int indexOf(const QRegExp &, int from = 0) const; @@ -241,9 +241,11 @@ public: QStringRef midRef(int position, int n = -1) const Q_REQUIRED_RESULT; bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool startsWith(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool startsWith(const QLatin1String &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool startsWith(const QChar &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool endsWith(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool endsWith(const QLatin1String &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool endsWith(const QChar &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; @@ -902,6 +904,8 @@ inline QString::const_iterator QString::constEnd() const { return reinterpret_cast<const QChar*>(d->data + d->size); } inline QBool QString::contains(const QString &s, Qt::CaseSensitivity cs) const { return QBool(indexOf(s, 0, cs) != -1); } +inline QBool QString::contains(const QStringRef &s, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(s, 0, cs) != -1); } inline QBool QString::contains(QChar c, Qt::CaseSensitivity cs) const { return QBool(indexOf(c, 0, cs) != -1); } @@ -1123,6 +1127,34 @@ public: m_size = other.m_size; return *this; } + int indexOf(const QString &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int indexOf(QChar ch, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int indexOf(QLatin1String str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int indexOf(const QStringRef &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(const QString &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(QChar ch, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(QLatin1String str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(const QStringRef &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + inline QBool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QBool contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QBool contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QBool contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int count(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool startsWith(const QStringRef &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool endsWith(const QStringRef &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QStringRef &operator=(const QString *string); inline const QChar *unicode() const { @@ -1133,6 +1165,12 @@ public: inline const QChar *data() const { return unicode(); } inline const QChar *constData() const { return unicode(); } + QByteArray toAscii() const Q_REQUIRED_RESULT; + QByteArray toLatin1() const Q_REQUIRED_RESULT; + QByteArray toUtf8() const Q_REQUIRED_RESULT; + QByteArray toLocal8Bit() const Q_REQUIRED_RESULT; + QVector<uint> toUcs4() const Q_REQUIRED_RESULT; + inline void clear() { m_string = 0; m_position = m_size = 0; } QString toString() const; inline bool isEmpty() const { return m_size == 0; } @@ -1241,6 +1279,16 @@ inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QString &s inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QStringRef &s2) { return QString::localeAwareCompare_helper(s1.constData(), s1.length(), s2.constData(), s2.length()); } +inline QBool QStringRef::contains(const QString &s, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(s, 0, cs) != -1); } +inline QBool QStringRef::contains(QLatin1String s, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(s, 0, cs) != -1); } +inline QBool QStringRef::contains(QChar c, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(c, 0, cs) != -1); } +inline QBool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(s, 0, cs) != -1); } + + QT_END_NAMESPACE diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 2b8d054..7eee33d 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -53,6 +53,9 @@ #endif #include <stdlib.h> #include <string.h> +#ifdef Q_COMPILER_INITIALIZER_LISTS +#include <initializer_list> +#endif QT_BEGIN_HEADER @@ -118,6 +121,13 @@ public: inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); } inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(p); } QVector<T> &operator=(const QVector<T> &v); +#ifdef Q_COMPILER_RVALUE_REFS + inline QVector<T> operator=(QVector<T> &&other) + { qSwap(p, other.p); return *this; } +#endif +#ifdef Q_COMPILER_INITIALIZER_LISTS + inline QVector(std::initializer_list<T> args); +#endif bool operator==(const QVector<T> &v) const; inline bool operator!=(const QVector<T> &v) const { return !(*this == v); } @@ -297,7 +307,6 @@ public: inline std::vector<T> toStdVector() const { std::vector<T> tmp; tmp.reserve(size()); qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; } #endif - private: friend class QRegion; // Optimization for QRegion::rects() @@ -426,6 +435,22 @@ QVector<T>::QVector(int asize, const T &t) new (--i) T(t); } +#ifdef Q_COMPILER_INITIALIZER_LISTS +template <typename T> +QVector<T>::QVector(std::initializer_list<T> args) +{ + p = malloc(args.size()); + d->ref = 1; + d->alloc = d->size = args.size(); + d->sharable = true; + d->capacity = false; + T* i = p->array + d->size; + auto it = args.end(); + while (i != p->array) + new (--i) T(*(--it)); +} +#endif + template <typename T> void QVector<T>::free(Data *x) { @@ -790,11 +815,8 @@ QT_END_INCLUDE_NAMESPACE #else #define Q_TEMPLATE_EXTERN extern #endif -# pragma warning(push) /* MSVC 6.0 doesn't care about the disabling in qglobal.h (why?), so do it here */ -# pragma warning(disable: 4231) /* nonstandard extension used : 'extern' before template explicit instantiation */ Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPointF>; Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPoint>; -# pragma warning(pop) #endif QT_END_NAMESPACE diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp index 4e9c1ad..9ff0ff1 100644 --- a/src/dbus/qdbusabstractinterface.cpp +++ b/src/dbus/qdbusabstractinterface.cpp @@ -208,7 +208,7 @@ bool QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const Q QLatin1String(DBUS_INTERFACE_PROPERTIES), QLatin1String("Set")); QDBusMessagePrivate::setParametersValidated(msg, true); - msg << interface << QString::fromUtf8(mp.name()) << qVariantFromValue(QDBusVariant(value)); + msg << interface << QString::fromUtf8(mp.name()) << QVariant::fromValue(QDBusVariant(value)); QDBusMessage reply = connection.call(msg, QDBus::Block); if (reply.type() != QDBusMessage::ReplyMessage) { diff --git a/src/dbus/qdbusdemarshaller.cpp b/src/dbus/qdbusdemarshaller.cpp index 6e19218..0df4c6b 100644 --- a/src/dbus/qdbusdemarshaller.cpp +++ b/src/dbus/qdbusdemarshaller.cpp @@ -188,11 +188,11 @@ QVariant QDBusDemarshaller::toVariantInternal() { switch (q_dbus_message_iter_get_arg_type(&iterator)) { case DBUS_TYPE_BYTE: - return qVariantFromValue(toByte()); + return QVariant::fromValue(toByte()); case DBUS_TYPE_INT16: - return qVariantFromValue(toShort()); + return QVariant::fromValue(toShort()); case DBUS_TYPE_UINT16: - return qVariantFromValue(toUShort()); + return QVariant::fromValue(toUShort()); case DBUS_TYPE_INT32: return toInt(); case DBUS_TYPE_UINT32: @@ -208,11 +208,11 @@ QVariant QDBusDemarshaller::toVariantInternal() case DBUS_TYPE_STRING: return toString(); case DBUS_TYPE_OBJECT_PATH: - return qVariantFromValue(toObjectPath()); + return QVariant::fromValue(toObjectPath()); case DBUS_TYPE_SIGNATURE: - return qVariantFromValue(toSignature()); + return QVariant::fromValue(toSignature()); case DBUS_TYPE_VARIANT: - return qVariantFromValue(toVariant()); + return QVariant::fromValue(toVariant()); case DBUS_TYPE_ARRAY: switch (q_dbus_message_iter_get_element_type(&iterator)) { @@ -222,14 +222,14 @@ QVariant QDBusDemarshaller::toVariantInternal() case DBUS_TYPE_STRING: return toStringList(); case DBUS_TYPE_DICT_ENTRY: - return qVariantFromValue(duplicate()); + return QVariant::fromValue(duplicate()); default: - return qVariantFromValue(duplicate()); + return QVariant::fromValue(duplicate()); } case DBUS_TYPE_STRUCT: - return qVariantFromValue(duplicate()); + return QVariant::fromValue(duplicate()); default: qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'", diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 3833874..498c1cb 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -809,14 +809,14 @@ bool QDBusConnectionPrivate::activateCall(QObject* object, int flags, const QDBu slotData.slotIdx = -1; slotData.metaTypes.clear(); slotCache.hash.insert(cacheKey, slotData); - object->setProperty(cachePropertyName, qVariantFromValue(slotCache)); + object->setProperty(cachePropertyName, QVariant::fromValue(slotCache)); return false; } } // save to the cache slotCache.hash.insert(cacheKey, slotData); - object->setProperty(cachePropertyName, qVariantFromValue(slotCache)); + object->setProperty(cachePropertyName, QVariant::fromValue(slotCache)); // found the slot to be called deliverCall(object, flags, msg, slotData.metaTypes, slotData.slotIdx); diff --git a/src/dbus/qdbusinternalfilters.cpp b/src/dbus/qdbusinternalfilters.cpp index 78abf94..b6cf1fd 100644 --- a/src/dbus/qdbusinternalfilters.cpp +++ b/src/dbus/qdbusinternalfilters.cpp @@ -264,7 +264,7 @@ QDBusMessage qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode &node return propertyNotFoundError(msg, interface_name, property_name); } - return msg.createReply(qVariantFromValue(QDBusVariant(value))); + return msg.createReply(QVariant::fromValue(QDBusVariant(value))); } enum PropertyWriteResult { @@ -334,7 +334,7 @@ static int writeProperty(QObject *obj, const QByteArray &property_name, QVariant // we have to demarshall before writing void *null = 0; QVariant other(id, null); - if (!QDBusMetaType::demarshall(qVariantValue<QDBusArgument>(value), id, other.data())) { + if (!QDBusMetaType::demarshall(qvariant_cast<QDBusArgument>(value), id, other.data())) { qWarning("QDBusConnection: type `%s' (%d) is not registered with QtDBus. " "Use qDBusRegisterMetaType to register it", mp.typeName(), id); @@ -495,7 +495,7 @@ QDBusMessage qDBusPropertyGetAll(const QDBusConnectionPrivate::ObjectTreeNode &n return interfaceNotFoundError(msg, interface_name); } - return msg.createReply(qVariantFromValue(result)); + return msg.createReply(QVariant::fromValue(result)); } QT_END_NAMESPACE diff --git a/src/declarative/debugger/qdeclarativedebug.cpp b/src/declarative/debugger/qdeclarativedebug.cpp index 1ffe441..bf07080 100644 --- a/src/declarative/debugger/qdeclarativedebug.cpp +++ b/src/declarative/debugger/qdeclarativedebug.cpp @@ -194,7 +194,7 @@ void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugOb { QDeclarativeDebugObjectReference obj; obj.m_debugId = prop.m_value.toInt(); - prop.m_value = qVariantFromValue(obj); + prop.m_value = QVariant::fromValue(obj); break; } case QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::Unknown: diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 84b0ccf..c507795 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -1052,63 +1052,50 @@ void QDeclarativeFlickablePrivate::data_append(QDeclarativeListProperty<QObject> o->setParent(prop->object); } -static inline int children_count_helper(QGraphicsObject *object) +int QDeclarativeFlickablePrivate::data_count(QDeclarativeListProperty<QObject> *property) { - QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(object); - return d->children.count(); + QDeclarativeItem *contentItem= static_cast<QDeclarativeFlickablePrivate*>(property->data)->contentItem; + return contentItem->childItems().count() + contentItem->children().count(); } -static inline QObject *children_at_helper(QGraphicsObject *object, int index) +QObject *QDeclarativeFlickablePrivate::data_at(QDeclarativeListProperty<QObject> *property, int index) { - QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(object); - if (index >= 0 && index < d->children.count()) - return d->children.at(index)->toGraphicsObject(); - else - return 0; -} + QDeclarativeItem *contentItem = static_cast<QDeclarativeFlickablePrivate*>(property->data)->contentItem; -static inline void children_clear_helper(QGraphicsObject *object) -{ - QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(object); - int childCount = d->children.count(); - for (int index = 0 ;index < childCount; index++) - QGraphicsItemPrivate::get(d->children.at(0))->setParentItemHelper(0, /*newParentVariant=*/0, /*thisPointerVariant=*/0); -} + int childItemCount = contentItem->childItems().count(); -int QDeclarativeFlickablePrivate::data_count(QDeclarativeListProperty<QObject> *prop) -{ - return QDeclarativeItemPrivate::resources_count(prop) + - children_count_helper(static_cast<QDeclarativeFlickablePrivate*>(prop->data)->contentItem); -} + if (index < 0) + return 0; + + if (index < childItemCount) { + return contentItem->childItems().at(index)->toGraphicsObject(); + } else { + return contentItem->children().at(index - childItemCount); + } -QObject *QDeclarativeFlickablePrivate::data_at(QDeclarativeListProperty<QObject> *prop, int i) -{ - int resourcesCount = QDeclarativeItemPrivate::resources_count(prop); - if (i < resourcesCount) - return QDeclarativeItemPrivate::resources_at(prop, i); - const int j = i - resourcesCount; - QGraphicsObject *contentObject = static_cast<QDeclarativeFlickablePrivate*>(prop->data)->contentItem; - if (j < children_count_helper(contentObject)) - return children_at_helper(contentObject, j); return 0; } -void QDeclarativeFlickablePrivate::data_clear(QDeclarativeListProperty<QObject> *prop) +void QDeclarativeFlickablePrivate::data_clear(QDeclarativeListProperty<QObject> *property) { - QDeclarativeItemPrivate::resources_clear(prop); - QGraphicsObject *contentObject = - static_cast<QDeclarativeFlickablePrivate*>(prop->data)->contentItem; - children_clear_helper(contentObject); + QDeclarativeItem *contentItem = static_cast<QDeclarativeFlickablePrivate*>(property->data)->contentItem; + + const QList<QGraphicsItem*> graphicsItems = contentItem->childItems(); + for (int i = 0; i < graphicsItems.count(); i++) + contentItem->scene()->removeItem(graphicsItems[i]); + + const QList<QObject*> objects = contentItem->children(); + for (int i = 0; i < objects.count(); i++) + objects[i]->setParent(0); } QDeclarativeListProperty<QObject> QDeclarativeFlickable::flickableData() { Q_D(QDeclarativeFlickable); return QDeclarativeListProperty<QObject>(this, (void *)d, QDeclarativeFlickablePrivate::data_append, - QDeclarativeFlickablePrivate::data_count, - QDeclarativeFlickablePrivate::data_at, - QDeclarativeFlickablePrivate::data_clear - ); + QDeclarativeFlickablePrivate::data_count, + QDeclarativeFlickablePrivate::data_at, + QDeclarativeFlickablePrivate::data_clear); } QDeclarativeListProperty<QGraphicsObject> QDeclarativeFlickable::flickableChildren() diff --git a/src/declarative/qml/parser/qdeclarativejsengine_p.h b/src/declarative/qml/parser/qdeclarativejsengine_p.h index 1389244..d0b744d 100644 --- a/src/declarative/qml/parser/qdeclarativejsengine_p.h +++ b/src/declarative/qml/parser/qdeclarativejsengine_p.h @@ -88,12 +88,6 @@ uint qHash(const QDeclarativeJS::NameId &id); } // end of namespace QDeclarativeJS -#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 -//this ensures that code outside QDeclarativeJS can use the hash function -//it also a workaround for some compilers -inline uint qHash(const QDeclarativeJS::NameId &nameId) { return QDeclarativeJS::qHash(nameId); } -#endif - namespace QDeclarativeJS { class Lexer; diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 80db230..06b1ed3 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -1291,7 +1291,7 @@ QScriptValue QDeclarativeEnginePrivate::vector3d(QScriptContext *ctxt, QScriptEn qsreal x = ctxt->argument(0).toNumber(); qsreal y = ctxt->argument(1).toNumber(); qsreal z = ctxt->argument(2).toNumber(); - return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QVector3D(x, y, z))); + return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QVector3D(x, y, z))); } /*! @@ -1311,14 +1311,14 @@ QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptE QScriptValue formatArg = ctxt->argument(1); if (formatArg.isString()) { QString format = formatArg.toString(); - return engine->newVariant(qVariantFromValue(date.toString(format))); + return engine->newVariant(QVariant::fromValue(date.toString(format))); } else if (formatArg.isNumber()) { enumFormat = Qt::DateFormat(formatArg.toUInt32()); } else { return ctxt->throwError(QLatin1String("Qt.formatDate(): Invalid date format")); } } - return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); + return engine->newVariant(QVariant::fromValue(date.toString(enumFormat))); } /*! @@ -1339,14 +1339,14 @@ QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptE QScriptValue formatArg = ctxt->argument(1); if (formatArg.isString()) { QString format = formatArg.toString(); - return engine->newVariant(qVariantFromValue(date.toString(format))); + return engine->newVariant(QVariant::fromValue(date.toString(format))); } else if (formatArg.isNumber()) { enumFormat = Qt::DateFormat(formatArg.toUInt32()); } else { return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid time format")); } } - return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); + return engine->newVariant(QVariant::fromValue(date.toString(enumFormat))); } /*! @@ -1430,14 +1430,14 @@ QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScr QScriptValue formatArg = ctxt->argument(1); if (formatArg.isString()) { QString format = formatArg.toString(); - return engine->newVariant(qVariantFromValue(date.toString(format))); + return engine->newVariant(QVariant::fromValue(date.toString(format))); } else if (formatArg.isNumber()) { enumFormat = Qt::DateFormat(formatArg.toUInt32()); } else { return ctxt->throwError(QLatin1String("Qt.formatDateTime(): Invalid datetime format")); } } - return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); + return engine->newVariant(QVariant::fromValue(date.toString(enumFormat))); } #endif // QT_NO_DATESTRING @@ -1466,7 +1466,7 @@ QScriptValue QDeclarativeEnginePrivate::rgba(QScriptContext *ctxt, QScriptEngine if (a < 0.0) a=0.0; if (a > 1.0) a=1.0; - return qScriptValueFromValue(engine, qVariantFromValue(QColor::fromRgbF(r, g, b, a))); + return engine->toScriptValue(QVariant::fromValue(QColor::fromRgbF(r, g, b, a))); } /*! @@ -1494,7 +1494,7 @@ QScriptValue QDeclarativeEnginePrivate::hsla(QScriptContext *ctxt, QScriptEngine if (a < 0.0) a=0.0; if (a > 1.0) a=1.0; - return qScriptValueFromValue(engine, qVariantFromValue(QColor::fromHslF(h, s, l, a))); + return engine->toScriptValue(QVariant::fromValue(QColor::fromHslF(h, s, l, a))); } /*! @@ -1517,7 +1517,7 @@ QScriptValue QDeclarativeEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine if (w < 0 || h < 0) return engine->nullValue(); - return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QRectF(x, y, w, h))); + return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QRectF(x, y, w, h))); } /*! @@ -1530,7 +1530,7 @@ QScriptValue QDeclarativeEnginePrivate::point(QScriptContext *ctxt, QScriptEngin return ctxt->throwError(QLatin1String("Qt.point(): Invalid arguments")); qsreal x = ctxt->argument(0).toNumber(); qsreal y = ctxt->argument(1).toNumber(); - return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QPointF(x, y))); + return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QPointF(x, y))); } /*! @@ -1543,7 +1543,7 @@ QScriptValue QDeclarativeEnginePrivate::size(QScriptContext *ctxt, QScriptEngine return ctxt->throwError(QLatin1String("Qt.size(): Invalid arguments")); qsreal w = ctxt->argument(0).toNumber(); qsreal h = ctxt->argument(1).toNumber(); - return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QSizeF(w, h))); + return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QSizeF(w, h))); } /*! @@ -1579,7 +1579,7 @@ QScriptValue QDeclarativeEnginePrivate::lighter(QScriptContext *ctxt, QScriptEng if (ctxt->argumentCount() == 2) factor = ctxt->argument(1).toNumber(); color = color.lighter(int(qRound(factor*100.))); - return qScriptValueFromValue(engine, qVariantFromValue(color)); + return engine->toScriptValue(QVariant::fromValue(color)); } /*! @@ -1616,7 +1616,7 @@ QScriptValue QDeclarativeEnginePrivate::darker(QScriptContext *ctxt, QScriptEngi if (ctxt->argumentCount() == 2) factor = ctxt->argument(1).toNumber(); color = color.darker(int(qRound(factor*100.))); - return qScriptValueFromValue(engine, qVariantFromValue(color)); + return engine->toScriptValue(QVariant::fromValue(color)); } /*! @@ -1854,7 +1854,7 @@ QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine a + inv_a * color.alphaF()); } - return qScriptValueFromValue(engine, qVariantFromValue(finalColor)); + return engine->toScriptValue(QVariant::fromValue(finalColor)); } QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val) @@ -1884,7 +1884,7 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v if (objOk) { return objectClass->newQObject(obj); } else { - return qScriptValueFromValue(&scriptEngine, val); + return scriptEngine.toScriptValue(val); } } diff --git a/src/declarative/qml/qdeclarativesqldatabase.cpp b/src/declarative/qml/qdeclarativesqldatabase.cpp index 45f277e..42b596a 100644 --- a/src/declarative/qml/qdeclarativesqldatabase.cpp +++ b/src/declarative/qml/qdeclarativesqldatabase.cpp @@ -237,7 +237,7 @@ static QScriptValue qmlsqldatabase_executeSql(QScriptContext *context, QScriptEn if (!qmlengine->sqlQueryClass) qmlengine->sqlQueryClass = new QDeclarativeSqlQueryScriptClass(engine); QScriptValue rows = engine->newObject(qmlengine->sqlQueryClass); - rows.setData(engine->newVariant(qVariantFromValue(query))); + rows.setData(engine->newVariant(QVariant::fromValue(query))); rows.setProperty(QLatin1String("item"), engine->newFunction(qmlsqldatabase_item,1), QScriptValue::SkipInEnumeration); result.setProperty(QLatin1String("rows"),rows); result.setProperty(QLatin1String("rowsAffected"),query.numRowsAffected()); @@ -275,7 +275,7 @@ static QScriptValue qmlsqldatabase_change_version(QScriptContext *context, QScri QScriptValue instance = engine->newObject(); instance.setProperty(QLatin1String("executeSql"), engine->newFunction(qmlsqldatabase_executeSql,1)); - QScriptValue tx = engine->newVariant(instance,qVariantFromValue(db)); + QScriptValue tx = engine->newVariant(instance,QVariant::fromValue(db)); QString foundvers = context->thisObject().property(QLatin1String("version")).toString(); if (from_version!=foundvers) { @@ -319,7 +319,7 @@ static QScriptValue qmlsqldatabase_transaction_shared(QScriptContext *context, Q QScriptValue instance = engine->newObject(); instance.setProperty(QLatin1String("executeSql"), engine->newFunction(readOnly ? qmlsqldatabase_executeSql_readonly : qmlsqldatabase_executeSql,1)); - QScriptValue tx = engine->newVariant(instance,qVariantFromValue(db)); + QScriptValue tx = engine->newVariant(instance,QVariant::fromValue(db)); db.transaction(); callback.call(QScriptValue(), QScriptValueList() << tx); @@ -403,7 +403,7 @@ static QScriptValue qmlsqldatabase_open_sync(QScriptContext *context, QScriptEng instance.setProperty(QLatin1String("version"), version, QScriptValue::ReadOnly); instance.setProperty(QLatin1String("changeVersion"), engine->newFunction(qmlsqldatabase_change_version,3)); - QScriptValue result = engine->newVariant(instance,qVariantFromValue(database)); + QScriptValue result = engine->newVariant(instance,QVariant::fromValue(database)); if (created && dbcreationCallback.isFunction()) { dbcreationCallback.call(QScriptValue(), QScriptValueList() << result); diff --git a/src/declarative/qml/qdeclarativestringconverters.cpp b/src/declarative/qml/qdeclarativestringconverters.cpp index 7534a2c..8ec68ff 100644 --- a/src/declarative/qml/qdeclarativestringconverters.cpp +++ b/src/declarative/qml/qdeclarativestringconverters.cpp @@ -92,7 +92,7 @@ QVariant QDeclarativeStringConverters::variantFromString(const QString &s) QSizeF sz = sizeFFromString(s, &ok); if (ok) return QVariant(sz); QVector3D v = vector3DFromString(s, &ok); - if (ok) return qVariantFromValue(v); + if (ok) return QVariant::fromValue(v); return QVariant(s); } diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp index 789116e..509ca6b 100644 --- a/src/declarative/qml/qdeclarativeworkerscript.cpp +++ b/src/declarative/qml/qdeclarativeworkerscript.cpp @@ -331,7 +331,7 @@ QVariant QDeclarativeWorkerScriptEnginePrivate::scriptValueToVariant(const QScri QDeclarativeListModelWorkerAgent *agent = lm->agent(); if (agent) { QDeclarativeListModelWorkerAgent::VariantRef v(agent); - return qVariantFromValue(v); + return QVariant::fromValue(v); } else { return QVariant(); } diff --git a/src/declarative/qml/qdeclarativexmlhttprequest.cpp b/src/declarative/qml/qdeclarativexmlhttprequest.cpp index 332acc4..adfdbb3 100644 --- a/src/declarative/qml/qdeclarativexmlhttprequest.cpp +++ b/src/declarative/qml/qdeclarativexmlhttprequest.cpp @@ -58,6 +58,8 @@ #include <QtCore/qstack.h> #include <QtCore/qdebug.h> +#include <QtCore/QStringBuilder> + #ifndef QT_NO_XMLSTREAMREADER // From DOM-Level-3-Core spec @@ -510,7 +512,7 @@ QScriptValue Node::create(QScriptEngine *engine, NodeImpl *data) node.d = data; if (data) A(data); - return engine->newVariant(instance, qVariantFromValue(node)); + return engine->newVariant(instance, QVariant::fromValue(node)); } QScriptValue Element::prototype(QScriptEngine *engine) @@ -710,7 +712,7 @@ QScriptValue Document::load(QScriptEngine *engine, const QByteArray &data) instance.setPrototype(Document::prototype(engine)); Node documentNode; documentNode.d = document; - return engine->newVariant(instance, qVariantFromValue(documentNode)); + return engine->newVariant(instance, QVariant::fromValue(documentNode)); } Node::Node() @@ -761,7 +763,7 @@ QScriptValue NamedNodeMap::create(QScriptEngine *engine, NodeImpl *data, QList<N map.list = list; if (data) A(data); - instance.setData(engine->newVariant(qVariantFromValue(map))); + instance.setData(engine->newVariant(QVariant::fromValue(map))); if (!QDeclarativeScriptEngine::get(engine)->namedNodeMapClass) QDeclarativeScriptEngine::get(engine)->namedNodeMapClass= new NamedNodeMapClass(engine); @@ -818,7 +820,7 @@ QScriptValue NodeList::create(QScriptEngine *engine, NodeImpl *data) list.d = data; if (data) A(data); - instance.setData(engine->newVariant(qVariantFromValue(list))); + instance.setData(engine->newVariant(QVariant::fromValue(list))); if (!QDeclarativeScriptEngine::get(engine)->nodeListClass) QDeclarativeScriptEngine::get(engine)->nodeListClass= new NodeListClass(engine); @@ -1090,10 +1092,9 @@ QString QDeclarativeXMLHttpRequest::headers() foreach (const HeaderPair &header, m_headersList) { if (ret.length()) - ret.append(QString::fromUtf8("\r\n")); - ret.append(QString::fromUtf8(header.first)); - ret.append(QString::fromUtf8(": ")); - ret.append(QString::fromUtf8(header.second)); + ret.append(QLatin1String("\r\n")); + ret = ret % QString::fromUtf8(header.first) % QLatin1String(": ") + % QString::fromUtf8(header.second); } return ret; } @@ -1105,9 +1106,9 @@ void QDeclarativeXMLHttpRequest::fillHeadersList() m_headersList.clear(); foreach (const QByteArray &header, headerList) { HeaderPair pair (header.toLower(), m_network->rawHeader(header)); - if (pair.first == "set-cookie" || - pair.first == "set-cookie2") - continue; + if (pair.first == "set-cookie" || + pair.first == "set-cookie2") + continue; m_headersList << pair; } diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index ea3da25..3a96f98 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -2940,4 +2940,8 @@ void QDeclarativeAnchorAnimation::transition(QDeclarativeStateActions &actions, } } +QDeclarativeScriptActionPrivate::QDeclarativeScriptActionPrivate() + : QDeclarativeAbstractAnimationPrivate(), hasRunScriptScript(false), reversing(false), proxy(this), rsa(0) {} + + QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativeanimation_p.h b/src/declarative/util/qdeclarativeanimation_p.h index cdd5041..8cb17e4 100644 --- a/src/declarative/util/qdeclarativeanimation_p.h +++ b/src/declarative/util/qdeclarativeanimation_p.h @@ -63,7 +63,7 @@ QT_MODULE(Declarative) class QDeclarativeAbstractAnimationPrivate; class QDeclarativeAnimationGroup; -class Q_AUTOTEST_EXPORT QDeclarativeAbstractAnimation : public QObject, public QDeclarativePropertyValueSource, public QDeclarativeParserStatus +class Q_DECLARATIVE_EXPORT QDeclarativeAbstractAnimation : public QObject, public QDeclarativePropertyValueSource, public QDeclarativeParserStatus { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeAbstractAnimation) diff --git a/src/declarative/util/qdeclarativeanimation_p_p.h b/src/declarative/util/qdeclarativeanimation_p_p.h index e38580c..26c04d4 100644 --- a/src/declarative/util/qdeclarativeanimation_p_p.h +++ b/src/declarative/util/qdeclarativeanimation_p_p.h @@ -247,8 +247,7 @@ class QDeclarativeScriptActionPrivate : public QDeclarativeAbstractAnimationPriv { Q_DECLARE_PUBLIC(QDeclarativeScriptAction) public: - QDeclarativeScriptActionPrivate() - : QDeclarativeAbstractAnimationPrivate(), hasRunScriptScript(false), reversing(false), proxy(this), rsa(0) {} + QDeclarativeScriptActionPrivate(); void init(); diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index 3263238..5ce95e9 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -800,7 +800,7 @@ void QDeclarativeListModelParser::setCustomData(QObject *obj, const QByteArray & { ModelNode *n = nodes.top(); ModelNode *n2 = new ModelNode(rv->m_nested); - n->values << qVariantFromValue(n2); + n->values << QVariant::fromValue(n2); nodes.push(n2); if (processingSet) n->isArray = true; @@ -1339,7 +1339,7 @@ bool NestedListModel::insert(int index, const QScriptValue& valuemap) ModelNode *mn = new ModelNode(this); mn->listIndex = index; mn->setObjectValue(valuemap); - _root->values.insert(index,qVariantFromValue(mn)); + _root->values.insert(index,QVariant::fromValue(mn)); return true; } @@ -1513,7 +1513,7 @@ void ModelNode::setListValue(const QScriptValue& valuelist) { value->listIndex = i; value->values << v.toVariant(); } - values.append(qVariantFromValue(value)); + values.append(QVariant::fromValue(value)); } } diff --git a/src/declarative/util/qdeclarativeview.cpp b/src/declarative/util/qdeclarativeview.cpp index 8f06858..7b88610 100644 --- a/src/declarative/util/qdeclarativeview.cpp +++ b/src/declarative/util/qdeclarativeview.cpp @@ -702,6 +702,23 @@ void QDeclarativeView::paintEvent(QPaintEvent *event) if (frameRateDebug()) qDebug() << "paintEvent:" << d->frameTimer.elapsed() << "time since last frame:" << time; + +#if QT_SHOW_DECLARATIVEVIEW_FPS + static QTime timer; + static int frames; + + if (frames == 0) { + timer.start(); + } else if (timer.elapsed() > 5000) { + qreal avgtime = timer.elapsed() / (qreal) frames; + qDebug("Average time per frame: %f ms (%i fps)", avgtime, int(1000 / avgtime)); + timer.start(); + frames = 0; + } + ++frames; + scene()->update(); +#endif + } QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index f0ed80b..870a523 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -806,7 +806,7 @@ QScriptValue QDeclarativeXmlListModel::get(int index) const QScriptValue sv = sengine->newObject(); for (int i=0; i<d->roleObjects.count(); i++) - sv.setProperty(d->roleObjects[i]->name(), qScriptValueFromValue(sengine, d->data.value(i).value(index))); + sv.setProperty(d->roleObjects[i]->name(), sengine->toScriptValue(d->data.value(i).value(index))); return sv; } diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index 0921bdb..a6d1dbd 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -409,13 +409,18 @@ static void qAccessibleCleanup() /*! \typedef QAccessible::InterfaceFactory - A function pointer type. Use a function with this prototype to install - interface factories with installFactory(). + This is a typedef for a pointer to a function with the following + signature: - The function receives a QObject pointer. If the QObject - provides a QAccessibleInterface, it sets the second parameter to - point to the corresponding QAccessibleInterface, and returns true; - otherwise returns false. + \snippet doc/src/snippets/code/src_gui_accessible_qaccessible.cpp 1 + + The function receives a QString and a QObject pointer, where the + QString is the key identifying the interface. The QObject is used + to pass on to the QAccessibleInterface so that it can hold a reference + to it. + + If the key and the QObject does not have a corresponding + QAccessibleInterface, a null-pointer will be returned. Installed factories are called by queryAccessibilityInterface() until one provides an interface. diff --git a/src/gui/accessible/qaccessibleobject.cpp b/src/gui/accessible/qaccessibleobject.cpp index 7b2e7ce..3a4809e 100644 --- a/src/gui/accessible/qaccessibleobject.cpp +++ b/src/gui/accessible/qaccessibleobject.cpp @@ -276,7 +276,7 @@ QAccessible::Relation QAccessibleApplication::relationTo(int child, const for (int i = 0; i < tlw.count(); ++i) { QWidget *w = tlw.at(i); - QObjectList cl = qFindChildren<QObject *>(w, QString()); + QObjectList cl = w->findChildren<QObject *>(QString()); if (cl.contains(o)) return Ancestor; } diff --git a/src/gui/accessible/qaccessiblewidget.cpp b/src/gui/accessible/qaccessiblewidget.cpp index 7c13367..5b439a9 100644 --- a/src/gui/accessible/qaccessiblewidget.cpp +++ b/src/gui/accessible/qaccessiblewidget.cpp @@ -1015,7 +1015,7 @@ QVariant QAccessibleWidgetEx::invokeMethodEx(Method method, int child, const QVa case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods << ForegroundColor << BackgroundColor; - return qVariantFromValue(set); + return QVariant::fromValue(set); } case ForegroundColor: return widget()->palette().color(widget()->foregroundRole()); diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp index 9e0437c..5a791fc 100644 --- a/src/gui/dialogs/qdialog.cpp +++ b/src/gui/dialogs/qdialog.cpp @@ -337,7 +337,7 @@ void QDialogPrivate::setDefault(QPushButton *pushButton) { Q_Q(QDialog); bool hasMain = false; - QList<QPushButton*> list = qFindChildren<QPushButton*>(q); + QList<QPushButton*> list = q->findChildren<QPushButton*>(); for (int i=0; i<list.size(); ++i) { QPushButton *pb = list.at(i); if (pb->window() == q) { @@ -372,7 +372,7 @@ void QDialogPrivate::setMainDefault(QPushButton *pushButton) void QDialogPrivate::hideDefault() { Q_Q(QDialog); - QList<QPushButton*> list = qFindChildren<QPushButton*>(q); + QList<QPushButton*> list = q->findChildren<QPushButton*>(); for (int i=0; i<list.size(); ++i) { list.at(i)->setDefault(false); } @@ -675,7 +675,7 @@ void QDialog::keyPressEvent(QKeyEvent *e) switch (e->key()) { case Qt::Key_Enter: case Qt::Key_Return: { - QList<QPushButton*> list = qFindChildren<QPushButton*>(this); + QList<QPushButton*> list = findChildren<QPushButton*>(); for (int i=0; i<list.size(); ++i) { QPushButton *pb = list.at(i); if (pb->isDefault() && pb->isVisible()) { diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index cb74a3c..a0dca5d 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -2209,9 +2209,9 @@ void QFileDialogPrivate::createWidgets() #ifndef QT_NO_FSCOMPLETER completer = new QFSCompleter(model, q); qFileDialogUi->fileNameEdit->setCompleter(completer); +#endif // QT_NO_FSCOMPLETER QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)), q, SLOT(_q_autoCompleteFileName(QString))); -#endif // QT_NO_FSCOMPLETER QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)), q, SLOT(_q_updateOkButton())); diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp index 8a6190f..b8aafe3 100644 --- a/src/gui/dialogs/qfilesystemmodel.cpp +++ b/src/gui/dialogs/qfilesystemmodel.cpp @@ -1290,6 +1290,10 @@ QString QFileSystemModelPrivate::filePath(const QModelIndex &index) const if ((fullPath.length() > 2) && fullPath[0] == QLatin1Char('/') && fullPath[1] == QLatin1Char('/')) fullPath = fullPath.mid(1); #endif +#if defined(Q_OS_WIN) + if (fullPath.length() == 2 && fullPath.endsWith(QLatin1Char(':'))) + fullPath.append(QLatin1Char('/')); +#endif return fullPath; } @@ -1608,6 +1612,14 @@ bool QFileSystemModel::event(QEvent *event) return QAbstractItemModel::event(event); } +bool QFileSystemModel::rmdir(const QModelIndex &aindex) const +{ + QString path = filePath(aindex); + QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func()); + d->fileInfoGatherer.removePath(path); + return QDir().rmdir(path); +} + /*! \internal diff --git a/src/gui/dialogs/qfilesystemmodel.h b/src/gui/dialogs/qfilesystemmodel.h index d8178c7..741f22b 100644 --- a/src/gui/dialogs/qfilesystemmodel.h +++ b/src/gui/dialogs/qfilesystemmodel.h @@ -139,7 +139,7 @@ public: QDateTime lastModified(const QModelIndex &index) const; QModelIndex mkdir(const QModelIndex &parent, const QString &name); - inline bool rmdir(const QModelIndex &index) const; + bool rmdir(const QModelIndex &index) const; // ### Qt5: should not be const inline QString fileName(const QModelIndex &index) const; inline QIcon fileIcon(const QModelIndex &index) const; QFile::Permissions permissions(const QModelIndex &index) const; @@ -163,8 +163,6 @@ private: friend class QFileDialogPrivate; }; -inline bool QFileSystemModel::rmdir(const QModelIndex &aindex) const -{ QDir dir; return dir.rmdir(filePath(aindex)); } inline QString QFileSystemModel::fileName(const QModelIndex &aindex) const { return aindex.data(Qt::DisplayRole).toString(); } inline QIcon QFileSystemModel::fileIcon(const QModelIndex &aindex) const diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp index fe25b0f..f849996 100644 --- a/src/gui/dialogs/qmessagebox.cpp +++ b/src/gui/dialogs/qmessagebox.cpp @@ -412,7 +412,7 @@ void QMessageBoxPrivate::updateSize() void QMessageBoxPrivate::hideSpecial() { Q_Q(QMessageBox); - QList<QPushButton*> list = qFindChildren<QPushButton*>(q); + QList<QPushButton*> list = q->findChildren<QPushButton*>(); for (int i=0; i<list.size(); ++i) { QPushButton *pb = list.at(i); QString text = pb->text(); @@ -1266,7 +1266,7 @@ bool QMessageBox::event(QEvent *e) (e->type() == QEvent::OkRequest) ? QApplication::translate("QMessageBox", "OK") : QApplication::translate("QMessageBox", "Help"); - QList<QPushButton*> list = qFindChildren<QPushButton*>(this); + QList<QPushButton*> list = findChildren<QPushButton*>(); for (int i=0; i<list.size(); ++i) { QPushButton *pb = list.at(i); if (pb->text() == bName) { @@ -1513,7 +1513,7 @@ static QMessageBox::StandardButton showNewMessageBox(QWidget *parent, int(defaultButton), 0); QMessageBox msgBox(icon, title, text, QMessageBox::NoButton, parent); - QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(&msgBox); + QDialogButtonBox *buttonBox = msgBox.findChild<QDialogButtonBox*>(); Q_ASSERT(buttonBox != 0); uint mask = QMessageBox::FirstButton; diff --git a/src/gui/dialogs/qnspanelproxy_mac.mm b/src/gui/dialogs/qnspanelproxy_mac.mm index 0bd5c63..0e8d64d 100644 --- a/src/gui/dialogs/qnspanelproxy_mac.mm +++ b/src/gui/dialogs/qnspanelproxy_mac.mm @@ -42,6 +42,7 @@ #include <qdialogbuttonbox.h> #if defined(Q_WS_MAC) #include <private/qt_mac_p.h> +#include <private/qcocoaintrospection_p.h> #import <AppKit/AppKit.h> #import <Foundation/Foundation.h> #import <objc/objc-class.h> @@ -137,46 +138,6 @@ QT_USE_NAMESPACE QT_BEGIN_NAMESPACE -void macStartIntercept(SEL originalSel, SEL fakeSel, Class baseClass, Class proxyClass) -{ -#ifndef QT_MAC_USE_COCOA - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) -#endif - { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - // The following code replaces the _implementation_ for the selector we want to hack - // (originalSel) with the implementation found in proxyClass. Then it creates - // a new 'backup' method inside baseClass containing the old, original, - // implementation (fakeSel). You can let the proxy implementation of originalSel - // call fakeSel if needed (similar approach to calling a super class implementation). - // fakeSel must also be implemented in proxyClass, as the signature is used - // as template for the method one we add into baseClass. - // NB: You will typically never create any instances of proxyClass; we use it - // only for stealing its contents and put it into baseClass. - Method originalMethod = class_getInstanceMethod(baseClass, originalSel); - Method newMethod = class_getInstanceMethod(proxyClass, originalSel); - Method fakeMethod = class_getInstanceMethod(proxyClass, fakeSel); - - IMP originalImp = method_setImplementation(originalMethod, method_getImplementation(newMethod)); - class_addMethod(baseClass, fakeSel, originalImp, method_getTypeEncoding(fakeMethod)); -#endif - } -} - -void macStopIntercept(SEL originalSel, SEL fakeSel, Class baseClass, Class /* proxyClass */) -{ -#ifndef QT_MAC_USE_COCOA - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) -#endif - { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - Method originalMethod = class_getInstanceMethod(baseClass, originalSel); - Method fakeMethodInBaseClass = class_getInstanceMethod(baseClass, fakeSel); - method_setImplementation(originalMethod, method_getImplementation(fakeMethodInBaseClass)); -#endif - } -} - /* Intercept the NSColorPanel constructor if the shared color panel doesn't exist yet. What's going on here is @@ -188,12 +149,18 @@ void macStopIntercept(SEL originalSel, SEL fakeSel, Class baseClass, Class /* pr */ void macStartInterceptNSPanelCtor() { - macStartIntercept(@selector(initWithContentRect:styleMask:backing:defer:), - @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:), - [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]); - macStartIntercept(@selector(initWithContentRect:styleMask:backing:defer:screen:), - @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:), - [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]); + qt_cocoa_change_implementation( + [NSPanel class], + @selector(initWithContentRect:styleMask:backing:defer:), + [QT_MANGLE_NAMESPACE(QNSPanelProxy) class], + @selector(initWithContentRect:styleMask:backing:defer:), + @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:)); + qt_cocoa_change_implementation( + [NSPanel class], + @selector(initWithContentRect:styleMask:backing:defer:screen:), + [QT_MANGLE_NAMESPACE(QNSPanelProxy) class], + @selector(initWithContentRect:styleMask:backing:defer:screen:), + @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:)); } /* @@ -201,12 +168,14 @@ void macStartInterceptNSPanelCtor() */ void macStopInterceptNSPanelCtor() { - macStopIntercept(@selector(initWithContentRect:styleMask:backing:defer:screen:), - @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:), - [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]); - macStopIntercept(@selector(initWithContentRect:styleMask:backing:defer:), - @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:), - [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]); + qt_cocoa_change_back_implementation( + [NSPanel class], + @selector(initWithContentRect:styleMask:backing:defer:screen:), + @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:)); + qt_cocoa_change_back_implementation( + [NSPanel class], + @selector(initWithContentRect:styleMask:backing:defer:), + @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:)); } /* @@ -216,8 +185,12 @@ void macStopInterceptNSPanelCtor() void macStartInterceptWindowTitle(QWidget *window) { currentWindow = window; - macStartIntercept(@selector(setTitle:), @selector(qt_fakeSetTitle:), - [NSWindow class], [QT_MANGLE_NAMESPACE(QNSWindowProxy) class]); + qt_cocoa_change_implementation( + [NSWindow class], + @selector(setTitle:), + [QT_MANGLE_NAMESPACE(QNSWindowProxy) class], + @selector(setTitle:), + @selector(qt_fakeSetTitle:)); } /* @@ -226,8 +199,10 @@ void macStartInterceptWindowTitle(QWidget *window) void macStopInterceptWindowTitle() { currentWindow = 0; - macStopIntercept(@selector(setTitle:), @selector(qt_fakeSetTitle:), - [NSWindow class], [QT_MANGLE_NAMESPACE(QNSWindowProxy) class]); + qt_cocoa_change_back_implementation( + [NSWindow class], + @selector(setTitle:), + @selector(qt_fakeSetTitle:)); } /* diff --git a/src/gui/graphicsview/qgraphicsgridlayout.cpp b/src/gui/graphicsview/qgraphicsgridlayout.cpp index 3fc7f10..4104834 100644 --- a/src/gui/graphicsview/qgraphicsgridlayout.cpp +++ b/src/gui/graphicsview/qgraphicsgridlayout.cpp @@ -589,6 +589,18 @@ void QGraphicsGridLayout::removeAt(int index) } /*! + Removes the layout item \a item without destroying it. + Ownership of the item is transferred to the caller. + + \sa addItem() +*/ +void QGraphicsGridLayout::removeItem(QGraphicsLayoutItem *item) +{ + Q_D(QGraphicsGridLayout); + int index = d->engine.indexOf(item); + removeAt(index); +} +/*! \reimp */ void QGraphicsGridLayout::invalidate() diff --git a/src/gui/graphicsview/qgraphicsgridlayout.h b/src/gui/graphicsview/qgraphicsgridlayout.h index 6580a02..d10235c 100644 --- a/src/gui/graphicsview/qgraphicsgridlayout.h +++ b/src/gui/graphicsview/qgraphicsgridlayout.h @@ -109,11 +109,12 @@ public: int columnCount() const; QGraphicsLayoutItem *itemAt(int row, int column) const; - + // inherited from QGraphicsLayout int count() const; QGraphicsLayoutItem *itemAt(int index) const; void removeAt(int index); + void removeItem(QGraphicsLayoutItem *item); void invalidate(); diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index b404692..096be63 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1703,12 +1703,12 @@ void QGraphicsItem::setParentItem(QGraphicsItem *newParent) return; const QVariant newParentVariant(itemChange(QGraphicsItem::ItemParentChange, - qVariantFromValue<QGraphicsItem *>(newParent))); - newParent = qVariantValue<QGraphicsItem *>(newParentVariant); + QVariant::fromValue<QGraphicsItem *>(newParent))); + newParent = qvariant_cast<QGraphicsItem *>(newParentVariant); if (newParent == d_ptr->parent) return; - const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(this)); + const QVariant thisPointerVariant(QVariant::fromValue<QGraphicsItem *>(this)); d_ptr->setParentItemHelper(newParent, &newParentVariant, &thisPointerVariant); } @@ -2132,7 +2132,7 @@ void QGraphicsItem::setToolTip(const QString &toolTip) */ QCursor QGraphicsItem::cursor() const { - return qVariantValue<QCursor>(d_ptr->extra(QGraphicsItemPrivate::ExtraCursor)); + return qvariant_cast<QCursor>(d_ptr->extra(QGraphicsItemPrivate::ExtraCursor)); } /*! @@ -2152,8 +2152,8 @@ QCursor QGraphicsItem::cursor() const */ void QGraphicsItem::setCursor(const QCursor &cursor) { - const QVariant cursorVariant(itemChange(ItemCursorChange, qVariantFromValue<QCursor>(cursor))); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qVariantValue<QCursor>(cursorVariant)); + const QVariant cursorVariant(itemChange(ItemCursorChange, QVariant::fromValue<QCursor>(cursor))); + d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qvariant_cast<QCursor>(cursorVariant)); d_ptr->hasCursor = 1; if (d_ptr->scene) { d_ptr->scene->d_func()->allItemsUseDefaultCursor = false; @@ -2279,7 +2279,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo // Schedule redrawing if (update) { - QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData)); + QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); if (c) c->purge(); if (scene) { @@ -3706,7 +3706,7 @@ void QGraphicsItem::setPos(const QPointF &pos) } // Notify the item that the position is changing. - const QVariant newPosVariant(itemChange(ItemPositionChange, qVariantFromValue<QPointF>(pos))); + const QVariant newPosVariant(itemChange(ItemPositionChange, QVariant::fromValue<QPointF>(pos))); QPointF newPos = newPosVariant.toPointF(); if (newPos == d_ptr->pos) return; @@ -4060,7 +4060,7 @@ void QGraphicsItem::setTransformOriginPoint(const QPointF &origin) if (d_ptr->flags & ItemSendsGeometryChanges) { // Notify the item that the origin point is changing. const QVariant newOriginVariant(itemChange(ItemTransformOriginPointChange, - qVariantFromValue<QPointF>(origin))); + QVariant::fromValue<QPointF>(origin))); newOrigin = newOriginVariant.toPointF(); } @@ -4079,7 +4079,7 @@ void QGraphicsItem::setTransformOriginPoint(const QPointF &origin) // Send post-notification. if (d_ptr->flags & ItemSendsGeometryChanges) - itemChange(ItemTransformOriginPointHasChanged, qVariantFromValue<QPointF>(newOrigin)); + itemChange(ItemTransformOriginPointHasChanged, QVariant::fromValue<QPointF>(newOrigin)); } /*! @@ -4341,8 +4341,8 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) } // Notify the item that the transformation matrix is changing. - const QVariant newMatrixVariant = qVariantFromValue<QMatrix>(newTransform.toAffine()); - newTransform = QTransform(qVariantValue<QMatrix>(itemChange(ItemMatrixChange, newMatrixVariant))); + const QVariant newMatrixVariant = QVariant::fromValue<QMatrix>(newTransform.toAffine()); + newTransform = QTransform(qvariant_cast<QMatrix>(itemChange(ItemMatrixChange, newMatrixVariant))); if (d_ptr->transformData->transform == newTransform) return; @@ -4350,7 +4350,7 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) d_ptr->setTransformHelper(newTransform); // Send post-notification. - itemChange(ItemTransformHasChanged, qVariantFromValue<QTransform>(newTransform)); + itemChange(ItemTransformHasChanged, QVariant::fromValue<QTransform>(newTransform)); } /*! @@ -4391,8 +4391,8 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) // Notify the item that the transformation matrix is changing. const QVariant newTransformVariant(itemChange(ItemTransformChange, - qVariantFromValue<QTransform>(newTransform))); - newTransform = qVariantValue<QTransform>(newTransformVariant); + QVariant::fromValue<QTransform>(newTransform))); + newTransform = qvariant_cast<QTransform>(newTransformVariant); if (d_ptr->transformData->transform == newTransform) return; @@ -5245,7 +5245,7 @@ QRegion QGraphicsItem::boundingRegion(const QTransform &itemToDeviceTransform) c qreal QGraphicsItem::boundingRegionGranularity() const { return d_ptr->hasBoundingRegionGranularity - ? qVariantValue<qreal>(d_ptr->extra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity)) + ? qvariant_cast<qreal>(d_ptr->extra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity)) : 0; } @@ -5281,7 +5281,7 @@ void QGraphicsItem::setBoundingRegionGranularity(qreal granularity) } d_ptr->hasBoundingRegionGranularity = 1; d_ptr->setExtra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity, - qVariantFromValue<qreal>(granularity)); + QVariant::fromValue<qreal>(granularity)); } /*! @@ -5456,7 +5456,7 @@ void QGraphicsItemPrivate::removeChild(QGraphicsItem *child) */ QGraphicsItemCache *QGraphicsItemPrivate::maybeExtraItemCache() const { - return (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData)); + return (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); } /*! @@ -5464,11 +5464,11 @@ QGraphicsItemCache *QGraphicsItemPrivate::maybeExtraItemCache() const */ QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const { - QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData)); + QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); if (!c) { QGraphicsItemPrivate *that = const_cast<QGraphicsItemPrivate *>(this); c = new QGraphicsItemCache; - that->setExtra(ExtraCacheData, qVariantFromValue<void *>(c)); + that->setExtra(ExtraCacheData, QVariant::fromValue<void *>(c)); } return c; } @@ -5478,7 +5478,7 @@ QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const */ void QGraphicsItemPrivate::removeExtraItemCache() { - QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData)); + QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); if (c) { c->purge(); delete c; @@ -8085,6 +8085,8 @@ QPen QAbstractGraphicsShapeItem::pen() const void QAbstractGraphicsShapeItem::setPen(const QPen &pen) { Q_D(QAbstractGraphicsShapeItem); + if (d->pen == pen) + return; prepareGeometryChange(); d->pen = pen; d->boundingRect = QRectF(); @@ -8115,6 +8117,8 @@ QBrush QAbstractGraphicsShapeItem::brush() const void QAbstractGraphicsShapeItem::setBrush(const QBrush &brush) { Q_D(QAbstractGraphicsShapeItem); + if (d->brush == brush) + return; d->brush = brush; update(); } @@ -9245,6 +9249,8 @@ QPen QGraphicsLineItem::pen() const void QGraphicsLineItem::setPen(const QPen &pen) { Q_D(QGraphicsLineItem); + if (d->pen == pen) + return; prepareGeometryChange(); d->pen = pen; update(); diff --git a/src/gui/graphicsview/qgraphicsitemanimation.cpp b/src/gui/graphicsview/qgraphicsitemanimation.cpp index 9cb9a8d..9689616 100644 --- a/src/gui/graphicsview/qgraphicsitemanimation.cpp +++ b/src/gui/graphicsview/qgraphicsitemanimation.cpp @@ -49,20 +49,20 @@ The QGraphicsItemAnimation class animates a QGraphicsItem. You can schedule changes to the item's transformation matrix at - specified steps. The QGraphicsItemAnimation class has a - current step value. When this value changes the transformations - scheduled at that step are performed. The current step of the + specified steps. The QGraphicsItemAnimation class has a + current step value. When this value changes the transformations + scheduled at that step are performed. The current step of the animation is set with the \c setStep() function. QGraphicsItemAnimation will do a simple linear interpolation - between the nearest adjacent scheduled changes to calculate the + between the nearest adjacent scheduled changes to calculate the matrix. For instance, if you set the position of an item at values 0.0 and 1.0, the animation will show the item moving in a straight - line between these positions. The same is true for scaling and + line between these positions. The same is true for scaling and rotation. It is usual to use the class with a QTimeLine. The timeline's - \l{QTimeLine::}{valueChanged()} signal is then connected to the + \l{QTimeLine::}{valueChanged()} signal is then connected to the \c setStep() slot. For example, you can set up an item for rotation by calling \c setRotationAt() for different step values. The animations timeline is set with the setTimeLine() function. @@ -286,7 +286,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::posList() const QList<QPair<qreal, QPointF> > list; for (int i = 0; i < d->xPosition.size(); ++i) list << QPair<qreal, QPointF>(d->xPosition.at(i).step, QPointF(d->xPosition.at(i).value, d->yPosition.at(i).value)); - + return list; } @@ -343,7 +343,7 @@ QList<QPair<qreal, qreal> > QGraphicsItemAnimation::rotationList() const QList<QPair<qreal, qreal> > list; for (int i = 0; i < d->rotation.size(); ++i) list << QPair<qreal, qreal>(d->rotation.at(i).step, d->rotation.at(i).value); - + return list; } @@ -395,7 +395,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::translationList() const QList<QPair<qreal, QPointF> > list; for (int i = 0; i < d->xTranslation.size(); ++i) list << QPair<qreal, QPointF>(d->xTranslation.at(i).step, QPointF(d->xTranslation.at(i).value, d->yTranslation.at(i).value)); - + return list; } @@ -447,7 +447,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::scaleList() const QList<QPair<qreal, QPointF> > list; for (int i = 0; i < d->horizontalScale.size(); ++i) list << QPair<qreal, QPointF>(d->horizontalScale.at(i).step, QPointF(d->horizontalScale.at(i).value, d->verticalScale.at(i).value)); - + return list; } @@ -499,7 +499,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::shearList() const QList<QPair<qreal, QPointF> > list; for (int i = 0; i < d->horizontalShear.size(); ++i) list << QPair<qreal, QPointF>(d->horizontalShear.at(i).step, QPointF(d->horizontalShear.at(i).value, d->verticalShear.at(i).value)); - + return list; } diff --git a/src/gui/graphicsview/qgraphicslayout.cpp b/src/gui/graphicsview/qgraphicslayout.cpp index 86b4589..91f386f 100644 --- a/src/gui/graphicsview/qgraphicslayout.cpp +++ b/src/gui/graphicsview/qgraphicslayout.cpp @@ -145,7 +145,7 @@ QT_BEGIN_NAMESPACE /*! Contructs a QGraphicsLayout object. - + \a parent is passed to QGraphicsLayoutItem's constructor and the QGraphicsLayoutItem's isLayout argument is set to \e true. @@ -259,7 +259,7 @@ void QGraphicsLayout::activate() return; d->activateRecursive(this); - + // we don't call activate on a sublayout, but somebody might. // Therefore, we walk to the parentitem of the toplevel layout. QGraphicsLayoutItem *parentItem = this; @@ -270,7 +270,7 @@ void QGraphicsLayout::activate() Q_ASSERT(!parentItem->isLayout()); setGeometry(parentItem->contentsRect()); // relayout children - + // ### bug, should be parentItem ? parentLayoutItem()->updateGeometry(); // bubble up; will set activated to false // ### too many resizes? maybe we should walk up the chain to the @@ -307,7 +307,7 @@ void QGraphicsLayout::invalidate() // does not call the base implementation? In addition, updateGeometry() // does more than we need. layoutItem->d_func()->sizeHintCacheDirty = true; - layoutItem = layoutItem->parentLayoutItem(); + layoutItem = layoutItem->parentLayoutItem(); } if (layoutItem) layoutItem->d_func()->sizeHintCacheDirty = true; @@ -347,7 +347,7 @@ void QGraphicsLayout::updateGeometry() widget. QGraphicsLayout uses this event handler to listen for layout related events such as geometry changes, layout changes or layout direction changes. - + \a e is a pointer to the event. You can reimplement this event handler to track similar events for your diff --git a/src/gui/graphicsview/qgraphicslayout_p.cpp b/src/gui/graphicsview/qgraphicslayout_p.cpp index 88652ec..163fc65 100644 --- a/src/gui/graphicsview/qgraphicslayout_p.cpp +++ b/src/gui/graphicsview/qgraphicslayout_p.cpp @@ -136,13 +136,13 @@ static bool removeLayoutItemFromLayout(QGraphicsLayout *lay, QGraphicsLayoutItem /*! \internal - This function is called from subclasses to add a layout item \a layoutItem + This function is called from subclasses to add a layout item \a layoutItem to a layout. It takes care of automatically reparenting graphics items, if needed. If \a layoutItem is a is already in a layout, it will remove it from that layout. - + */ void QGraphicsLayoutPrivate::addChildLayoutItem(QGraphicsLayoutItem *layoutItem) { @@ -150,14 +150,14 @@ void QGraphicsLayoutPrivate::addChildLayoutItem(QGraphicsLayoutItem *layoutItem) if (QGraphicsLayoutItem *maybeLayout = layoutItem->parentLayoutItem()) { if (maybeLayout->isLayout()) removeLayoutItemFromLayout(static_cast<QGraphicsLayout*>(maybeLayout), layoutItem); - } + } layoutItem->setParentLayoutItem(q); if (layoutItem->isLayout()) { if (QGraphicsItem *parItem = parentItem()) { static_cast<QGraphicsLayout*>(layoutItem)->d_func()->reparentChildItems(parItem); } } else { - if (QGraphicsItem *item = layoutItem->graphicsItem()) { + if (QGraphicsItem *item = layoutItem->graphicsItem()) { QGraphicsItem *newParent = parentItem(); QGraphicsItem *oldParent = item->parentItem(); if (oldParent == newParent || !newParent) @@ -182,7 +182,7 @@ void QGraphicsLayoutPrivate::activateRecursive(QGraphicsLayoutItem *item) QGraphicsLayout *layout = static_cast<QGraphicsLayout *>(item); if (layout->d_func()->activated) layout->invalidate(); - + for (int i = layout->count() - 1; i >= 0; --i) { QGraphicsLayoutItem *childItem = layout->itemAt(i); if (childItem) @@ -194,5 +194,5 @@ void QGraphicsLayoutPrivate::activateRecursive(QGraphicsLayoutItem *item) QT_END_NAMESPACE - + #endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicslayout_p.h b/src/gui/graphicsview/qgraphicslayout_p.h index 3083555..5c8e706 100644 --- a/src/gui/graphicsview/qgraphicslayout_p.h +++ b/src/gui/graphicsview/qgraphicslayout_p.h @@ -84,7 +84,7 @@ class QLayoutStyleInfo public: inline QLayoutStyleInfo() { invalidate(); } inline QLayoutStyleInfo(QStyle *style, QWidget *widget) - : m_valid(true), m_style(style), m_widget(widget) + : m_valid(true), m_style(style), m_widget(widget) { Q_ASSERT(style); if (widget) //### @@ -112,7 +112,7 @@ public: return m_defaultSpacing[o - 1]; } - inline qreal perItemSpacing(QSizePolicy::ControlType control1, + inline qreal perItemSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation) const { @@ -132,7 +132,7 @@ class Q_AUTOTEST_EXPORT QGraphicsLayoutPrivate : public QGraphicsLayoutItemPriva Q_DECLARE_PUBLIC(QGraphicsLayout) public: - QGraphicsLayoutPrivate() : QGraphicsLayoutItemPrivate(0, true), left(-1.0), top(-1.0), right(-1.0), bottom(-1.0), + QGraphicsLayoutPrivate() : QGraphicsLayoutItemPrivate(0, true), left(-1.0), top(-1.0), right(-1.0), bottom(-1.0), activated(true) { } void reparentChildItems(QGraphicsItem *newParent); @@ -148,7 +148,7 @@ public: QT_END_NAMESPACE - + #endif //QT_NO_GRAPHICSVIEW #endif diff --git a/src/gui/graphicsview/qgraphicslayoutitem.cpp b/src/gui/graphicsview/qgraphicslayoutitem.cpp index 634f68c..34ec4e0 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem.cpp +++ b/src/gui/graphicsview/qgraphicslayoutitem.cpp @@ -285,10 +285,6 @@ bool QGraphicsLayoutItemPrivate::hasHeightForWidth() const bool QGraphicsLayoutItemPrivate::hasWidthForHeight() const { - // enable this code when we add QSizePolicy::hasWidthForHeight() (For 4.8) -#if 1 - return false; -#else Q_Q(const QGraphicsLayoutItem); if (isLayout) { const QGraphicsLayout *l = static_cast<const QGraphicsLayout *>(q); @@ -305,7 +301,6 @@ bool QGraphicsLayoutItemPrivate::hasWidthForHeight() const } } return q->sizePolicy().hasWidthForHeight(); -#endif } /*! @@ -697,7 +692,7 @@ void QGraphicsLayoutItem::setMaximumHeight(qreal height) is equivalent to the item's position in parent coordinates). You must reimplement this function in a subclass of QGraphicsLayoutItem to - receive geometry updates. The layout will call this function when it does a + receive geometry updates. The layout will call this function when it does a rearrangement. If \a rect is outside of the bounds of minimumSize and maximumSize, it diff --git a/src/gui/graphicsview/qgraphicslayoutitem.h b/src/gui/graphicsview/qgraphicslayoutitem.h index f707c62..cb894a4 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem.h +++ b/src/gui/graphicsview/qgraphicslayoutitem.h @@ -118,7 +118,7 @@ protected: private: QSizeF *effectiveSizeHints(const QSizeF &constraint) const; Q_DECLARE_PRIVATE(QGraphicsLayoutItem) - + friend class QGraphicsLayout; }; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 54fdf3f..7cb442f 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -2544,8 +2544,8 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Notify the item that its scene is changing, and allow the item to // react. const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, - qVariantFromValue<QGraphicsScene *>(this))); - QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant); + QVariant::fromValue<QGraphicsScene *>(this))); + QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant); if (targetScene != this) { if (targetScene && item->d_ptr->scene != targetScene) targetScene->addItem(item); @@ -2956,8 +2956,8 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) // Notify the item that it's scene is changing to 0, allowing the item to // react. const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, - qVariantFromValue<QGraphicsScene *>(0))); - QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant); + QVariant::fromValue<QGraphicsScene *>(0))); + QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant); if (targetScene != 0 && targetScene != this) { targetScene->addItem(item); return; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index c8aca80..d568c40 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3709,7 +3709,7 @@ void QGraphicsView::drawForeground(QPainter *painter, const QRectF &rect) } /*! - \obsolete + \obsolete Draws the items \a items in the scene using \a painter, after the background and before the foreground are drawn. \a numItems is the number diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index 7bd9ecb..62be800 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -62,6 +62,7 @@ #include "qgraphicssceneevent.h" #include <QtGui/qstyleoption.h> #include <private/qabstractscrollarea_p.h> +#include <private/qapplication_p.h> QT_BEGIN_NAMESPACE @@ -180,21 +181,24 @@ public: inline void dispatchPendingUpdateRequests() { -#ifndef Q_WS_MAC - // QWidget::update() works slightly different on the Mac; it's not part of - // our backing store so it needs special threatment. - if (qt_widget_private(viewport)->paintOnScreen()) - QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest); - else - QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest); -#else - // At this point either HIViewSetNeedsDisplay (Carbon) or setNeedsDisplay: YES (Cocoa) - // is called, which means there's a pending update request. We want to dispatch it - // now because otherwise graphics view updates would require two - // round-trips in the event loop before the item is painted. - extern void qt_mac_dispatchPendingUpdateRequests(QWidget *); - qt_mac_dispatchPendingUpdateRequests(viewport->window()); -#endif +#ifdef Q_WS_MAC + // QWidget::update() works slightly different on the Mac without the raster engine; + // it's not part of our backing store so it needs special threatment. + if (QApplicationPrivate::graphics_system_name != "raster") { + // At this point either HIViewSetNeedsDisplay (Carbon) or setNeedsDisplay: YES (Cocoa) + // is called, which means there's a pending update request. We want to dispatch it + // now because otherwise graphics view updates would require two + // round-trips in the event loop before the item is painted. + extern void qt_mac_dispatchPendingUpdateRequests(QWidget *); + qt_mac_dispatchPendingUpdateRequests(viewport->window()); + } else +#endif // !Q_WS_MAC + { + if (qt_widget_private(viewport)->paintOnScreen()) + QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest); + else + QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest); + } } void setUpdateClip(QGraphicsItem *); diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp index 3466733..f99749c 100644 --- a/src/gui/graphicsview/qgraphicswidget_p.cpp +++ b/src/gui/graphicsview/qgraphicswidget_p.cpp @@ -46,6 +46,7 @@ #include <QtCore/qdebug.h> #include <QtCore/qnumeric.h> #include "qgraphicswidget_p.h" +#include "qgraphicslayoutitem_p.h" #include "qgraphicslayout.h" #include "qgraphicsscene_p.h" #include <QtGui/qapplication.h> @@ -415,8 +416,7 @@ static qreal minimumHeightForWidth(qreal width, qreal minh, qreal maxh, bool heightForWidth = true) { qreal minimumHeightForWidth = -1; - const QSizePolicy sp = widget->layout() ? widget->layout()->sizePolicy() : widget->sizePolicy(); - const bool hasHFW = sp.hasHeightForWidth(); + const bool hasHFW = QGraphicsLayoutItemPrivate::get(widget)->hasHeightForWidth(); if (hasHFW == heightForWidth) { minimumHeightForWidth = hasHFW ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(width, -1)).height() @@ -505,21 +505,31 @@ static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry, qreal width = qBound(min.width(), proposedRect.width(), max.width()); qreal height = qBound(min.height(), proposedRect.height(), max.height()); - QSizePolicy sp = widget->sizePolicy(); - if (const QGraphicsLayout *l = widget->layout()) { - sp = l->sizePolicy(); - } - const bool hasHFW = sp.hasHeightForWidth(); // || sp.hasWidthForHeight(); + const bool hasHFW = QGraphicsLayoutItemPrivate::get(widget)->hasHeightForWidth(); + const bool hasWFH = QGraphicsLayoutItemPrivate::get(widget)->hasWidthForHeight(); - const bool widthChanged = proposedRect.width() < widget->size().width(); - const bool heightChanged = proposedRect.height() < widget->size().height(); + const bool widthChanged = proposedRect.width() != widget->size().width(); + const bool heightChanged = proposedRect.height() != widget->size().height(); - if (hasHFW) { + if (hasHFW || hasWFH) { if (widthChanged || heightChanged) { - const qreal minh = min.height(); - const qreal maxh = max.height(); - const qreal proposedHFW = minimumHeightForWidth(width, minh, maxh, widget); - if (proposedHFW > proposedRect.height()) { + qreal minExtent; + qreal maxExtent; + qreal constraint; + qreal proposed; + if (hasHFW) { + minExtent = min.height(); + maxExtent = max.height(); + constraint = width; + proposed = proposedRect.height(); + } else { + // width for height + minExtent = min.width(); + maxExtent = max.width(); + constraint = height; + proposed = proposedRect.width(); + } + if (minimumHeightForWidth(constraint, minExtent, maxExtent, widget, hasHFW) > proposed) { QSizeF effectiveSize = closestAcceptableSize(QSizeF(width, height), widget); width = effectiveSize.width(); height = effectiveSize.height(); diff --git a/src/gui/graphicsview/qgridlayoutengine.cpp b/src/gui/graphicsview/qgridlayoutengine.cpp index f3b2026..98e6781 100644 --- a/src/gui/graphicsview/qgridlayoutengine.cpp +++ b/src/gui/graphicsview/qgridlayoutengine.cpp @@ -801,6 +801,15 @@ QGridLayoutItem *QGridLayoutEngine::itemAt(int index) const return q_items.at(index); } +int QGridLayoutEngine::indexOf(QGraphicsLayoutItem *item) const +{ + for (int i = 0; i < q_items.size(); ++i) { + if (item == q_items.at(i)->layoutItem()) + return i; + } + return -1; +} + int QGridLayoutEngine::effectiveFirstRow(Qt::Orientation orientation) const { ensureEffectiveFirstAndLastRows(); diff --git a/src/gui/graphicsview/qgridlayoutengine_p.h b/src/gui/graphicsview/qgridlayoutengine_p.h index 580af7e..55451d7 100644 --- a/src/gui/graphicsview/qgridlayoutengine_p.h +++ b/src/gui/graphicsview/qgridlayoutengine_p.h @@ -338,6 +338,7 @@ public: // returns the number of items inserted, which may be less than (rowCount * columnCount) int itemCount() const; QGridLayoutItem *itemAt(int index) const; + int indexOf(QGraphicsLayoutItem *item) const; int effectiveFirstRow(Qt::Orientation orientation = Qt::Vertical) const; int effectiveLastRow(Qt::Orientation orientation = Qt::Vertical) const; diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h index faef07b..fd591e6 100644 --- a/src/gui/image/qicon.h +++ b/src/gui/image/qicon.h @@ -71,6 +71,10 @@ public: explicit QIcon(QIconEngineV2 *engine); ~QIcon(); QIcon &operator=(const QIcon &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QIcon &operator=(QIcon &&other) + { qSwap(d, other.d); return *this; } +#endif operator QVariant() const; QPixmap pixmap(const QSize &size, Mode mode = Normal, State state = Off) const; diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index ac148ee..300e04b 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -2022,6 +2022,88 @@ void QImage::fill(uint pixel) 0, 0, d->width, d->height, d->bytes_per_line); } + +/*! + \fn void QImage::fill(Qt::GlobalColor color) + + \overload + + \since 4.8 + */ + +void QImage::fill(Qt::GlobalColor color) +{ + fill(QColor(color)); +} + + + +/*! + \fn void QImage::fill(Qt::GlobalColor color) + + \overload + + Fills the entire image with the given \a color. + + If the depth of the image is 1, the image will be filled with 1 if + \a color equals Qt::color0; it will otherwise be filled with 0. + + If the depth of the image is 8, the image will be filled with the + index corresponding the \a color in the color table if present; it + will otherwise be filled with 0.| + + \since 4.8 +*/ + +void QImage::fill(const QColor &color) +{ + if (!d) + return; + detach(); + + // In case we run out of memory + if (!d) + return; + + if (d->depth == 32) { + uint pixel = color.rgba(); + if (d->format == QImage::Format_ARGB32_Premultiplied) + pixel = PREMUL(pixel); + fill((uint) pixel); + + } else if (d->depth == 16 && d->format == QImage::Format_RGB16) { + qrgb565 p(color.rgba()); + fill((uint) p.rawValue()); + + } else if (d->depth == 1) { + if (color == Qt::color1) + fill((uint) 1); + else + fill((uint) 0); + + } else if (d->depth == 8) { + uint pixel = 0; + for (int i=0; i<d->colortable.size(); ++i) { + if (color.rgba() == d->colortable.at(i)) { + pixel = i; + break; + } + } + fill(pixel); + + } else { + QPainter p(this); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(rect(), color); + } + +} + + + + + + /*! Inverts all pixel values in the image. diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 896061f..4fe7da2 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -140,6 +140,11 @@ public: ~QImage(); QImage &operator=(const QImage &); +#ifdef Q_COMPILER_RVALUE_REFS + inline QImage &operator=(QImage &&other) + { qSwap(d, other.d); return *this; } +#endif + bool isNull() const; int devType() const; @@ -210,6 +215,9 @@ public: void setColorTable(const QVector<QRgb> colors); void fill(uint pixel); + void fill(const QColor &color); + void fill(Qt::GlobalColor color); + bool hasAlphaChannel() const; void setAlphaChannel(const QImage &alphaChannel); diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index ec56af2..03ee902 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -1092,7 +1092,7 @@ QColor QImageReader::backgroundColor() const if (!d->initHandler()) return QColor(); if (d->handler->supportsOption(QImageIOHandler::BackgroundColor)) - return qVariantValue<QColor>(d->handler->option(QImageIOHandler::BackgroundColor)); + return qvariant_cast<QColor>(d->handler->option(QImageIOHandler::BackgroundColor)); return QColor(); } diff --git a/src/gui/image/qmnghandler.cpp b/src/gui/image/qmnghandler.cpp index cf53af0..40f1b54 100644 --- a/src/gui/image/qmnghandler.cpp +++ b/src/gui/image/qmnghandler.cpp @@ -481,7 +481,7 @@ void QMngHandler::setOption(ImageOption option, const QVariant & value) { Q_D(QMngHandler); if (option == QImageIOHandler::BackgroundColor) - d->setBackgroundColor(qVariantValue<QColor>(value)); + d->setBackgroundColor(qvariant_cast<QColor>(value)); } /*! \reimp */ diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h index 63ef42e..49b0fd6 100644 --- a/src/gui/image/qpicture.h +++ b/src/gui/image/qpicture.h @@ -81,6 +81,10 @@ public: void setBoundingRect(const QRect &r); QPicture& operator=(const QPicture &p); +#ifdef Q_COMPILER_RVALUE_REFS + inline QPicture &operator=(QPicture &&other) + { qSwap(d_ptr, other.d_ptr); return *this; } +#endif void detach(); bool isDetached() const; diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 1e502bd..4cfadf8 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -99,7 +99,7 @@ static bool qt_pixmap_thread_test() return false; } #ifndef Q_WS_WIN - if (qApp->thread() != QThread::currentThread()) { + if (!QApplication::testAttribute(Qt::AA_X11InitThreads) && qApp->thread() != QThread::currentThread()) { qWarning("QPixmap: It is not safe to use pixmaps outside the GUI thread"); return false; } diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h index 64ca8a3..e9f9365 100644 --- a/src/gui/image/qpixmap.h +++ b/src/gui/image/qpixmap.h @@ -83,6 +83,10 @@ public: ~QPixmap(); QPixmap &operator=(const QPixmap &); +#ifdef Q_COMPILER_RVALUE_REFS + inline QPixmap &operator=(QPixmap &&other) + { qSwap(data, other.data); return *this; } +#endif operator QVariant() const; bool isNull() const; // ### Qt 5: make inline diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp index 3d9c363..9f8e643 100644 --- a/src/gui/image/qpixmap_x11.cpp +++ b/src/gui/image/qpixmap_x11.cpp @@ -310,7 +310,7 @@ static int defaultScreen = -1; QPixmap member functions *****************************************************************************/ -static int qt_pixmap_serial = 0; +QBasicAtomicInt qt_pixmap_serial = Q_BASIC_ATOMIC_INITIALIZER(0); int Q_GUI_EXPORT qt_x11_preferred_pixmap_depth = 0; QX11PixmapData::QX11PixmapData(PixelType type) @@ -327,7 +327,7 @@ QPixmapData *QX11PixmapData::createCompatiblePixmapData() const void QX11PixmapData::resize(int width, int height) { - setSerialNumber(++qt_pixmap_serial); + setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); w = width; h = height; @@ -410,7 +410,7 @@ struct QX11AlphaDetector void QX11PixmapData::fromImage(const QImage &img, Qt::ImageConversionFlags flags) { - setSerialNumber(++qt_pixmap_serial); + setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); w = img.width(); h = img.height(); @@ -2014,7 +2014,7 @@ QPixmap QX11PixmapData::transformed(const QTransform &transform, x11Data->hd = (Qt::HANDLE)XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()), w, h, d); - x11Data->setSerialNumber(++qt_pixmap_serial); + x11Data->setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); #ifndef QT_NO_XRENDER if (X11->use_xrender) { @@ -2265,7 +2265,7 @@ void QX11PixmapData::copy(const QPixmapData *data, const QRect &rect) const QX11PixmapData *x11Data = static_cast<const QX11PixmapData*>(data); - setSerialNumber(++qt_pixmap_serial); + setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); flags &= ~Uninitialized; xinfo = x11Data->xinfo; @@ -2385,7 +2385,7 @@ QPixmap QPixmap::fromX11Pixmap(Qt::HANDLE pixmap, QPixmap::ShareMode mode) } QX11PixmapData *data = new QX11PixmapData(depth == 1 ? QPixmapData::BitmapType : QPixmapData::PixmapType); - data->setSerialNumber(++qt_pixmap_serial); + data->setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); data->flags = QX11PixmapData::Readonly; data->share_mode = mode; data->w = width; diff --git a/src/gui/image/qtiffhandler.cpp b/src/gui/image/qtiffhandler.cpp index de4f680..2e8b998 100644 --- a/src/gui/image/qtiffhandler.cpp +++ b/src/gui/image/qtiffhandler.cpp @@ -196,9 +196,12 @@ bool QTiffHandler::read(QImage *image) uint16 bitPerSample; if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample)) bitPerSample = 1; + uint16 samplesPerPixel; // they may be e.g. grayscale with 2 samples per pixel + if (!TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel)) + samplesPerPixel = 1; bool grayscale = photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE; - if (grayscale && bitPerSample == 1) { + if (grayscale && bitPerSample == 1 && samplesPerPixel == 1) { if (image->size() != QSize(width, height) || image->format() != QImage::Format_Mono) *image = QImage(width, height, QImage::Format_Mono); QVector<QRgb> colortable(2); @@ -220,7 +223,7 @@ bool QTiffHandler::read(QImage *image) } } } else { - if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8) { + if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8 && samplesPerPixel == 1) { if (image->size() != QSize(width, height) || image->format() != QImage::Format_Indexed8) *image = QImage(width, height, QImage::Format_Indexed8); if (!image->isNull()) { diff --git a/src/gui/itemviews/qabstractitemdelegate.cpp b/src/gui/itemviews/qabstractitemdelegate.cpp index 0ea6d67..edbeeb8 100644 --- a/src/gui/itemviews/qabstractitemdelegate.cpp +++ b/src/gui/itemviews/qabstractitemdelegate.cpp @@ -362,7 +362,7 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event, case QEvent::ToolTip: { QHelpEvent *he = static_cast<QHelpEvent*>(event); QVariant tooltip = index.data(Qt::ToolTipRole); - if (qVariantCanConvert<QString>(tooltip)) { + if (tooltip.canConvert<QString>()) { QToolTip::showText(he->globalPos(), tooltip.toString(), view); return true; } @@ -376,7 +376,7 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event, case QEvent::WhatsThis: { QHelpEvent *he = static_cast<QHelpEvent*>(event); QVariant whatsthis = index.data(Qt::WhatsThisRole); - if (qVariantCanConvert<QString>(whatsthis)) { + if (whatsthis.canConvert<QString>()) { QWhatsThis::showText(he->globalPos(), whatsthis.toString(), view); return true; } diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 4ffd284..0842ee8 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -79,6 +79,7 @@ QAbstractItemViewPrivate::QAbstractItemViewPrivate() pressedAlreadySelected(false), viewportEnteredNeeded(false), state(QAbstractItemView::NoState), + stateBeforeAnimation(QAbstractItemView::NoState), editTriggers(QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed), lastTrigger(QAbstractItemView::NoEditTriggers), tabKeyNavigation(false), @@ -652,7 +653,7 @@ void QAbstractItemView::setModel(QAbstractItemModel *model) "QAbstractItemView::setModel", "A model should return the exact same index " "(including its internal id/pointer) when asked for it twice in a row."); - Q_ASSERT_X(d->model->index(0,0).parent() == QModelIndex(), + Q_ASSERT_X(!d->model->index(0,0).parent().isValid(), "QAbstractItemView::setModel", "The parent of a top level index should be invalid"); @@ -1036,10 +1037,12 @@ void QAbstractItemView::reset() { Q_D(QAbstractItemView); d->delayedReset.stop(); //make sure we stop the timer - QList<QEditorInfo>::const_iterator it = d->editors.constBegin(); - for (; it != d->editors.constEnd(); ++it) - d->releaseEditor(it->editor); - d->editors.clear(); + foreach (const QEditorInfo &info, d->indexEditorHash) { + if (info.widget) + d->releaseEditor(info.widget.data()); + } + d->editorIndexHash.clear(); + d->indexEditorHash.clear(); d->persistent.clear(); d->currentIndexSet = false; setState(NoState); @@ -2333,7 +2336,7 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) case Qt::Key_Return: // Propagate the enter if you couldn't edit the item and there are no // current editors (if there are editors, the event was most likely propagated from it). - if (!edit(currentIndex(), EditKeyPressed, event) && d->editors.isEmpty()) + if (!edit(currentIndex(), EditKeyPressed, event) && d->editorIndexHash.isEmpty()) event->ignore(); break; #else @@ -2518,7 +2521,7 @@ bool QAbstractItemView::edit(const QModelIndex &index, EditTrigger trigger, QEve if (!d->isIndexValid(index)) return false; - if (QWidget *w = (d->persistent.isEmpty() ? static_cast<QWidget*>(0) : d->editorForIndex(index).editor.data())) { + if (QWidget *w = (d->persistent.isEmpty() ? static_cast<QWidget*>(0) : d->editorForIndex(index).widget.data())) { if (w->focusPolicy() == Qt::NoFocus) return false; w->setFocus(); @@ -2578,15 +2581,15 @@ void QAbstractItemView::updateEditorData() void QAbstractItemView::updateEditorGeometries() { Q_D(QAbstractItemView); - if(d->editors.isEmpty()) + if(d->editorIndexHash.isEmpty()) return; QStyleOptionViewItemV4 option = d->viewOptionsV4(); - QList<QEditorInfo>::iterator it = d->editors.begin(); + QEditorIndexHash::iterator it = d->editorIndexHash.begin(); QWidgetList editorsToRelease; QWidgetList editorsToHide; - while (it != d->editors.end()) { - QModelIndex index = it->index; - QWidget *editor = it->editor; + while (it != d->editorIndexHash.end()) { + QModelIndex index = it.value(); + QWidget *editor = it.key(); if (index.isValid() && editor) { option.rect = visualRect(index); if (option.rect.isValid()) { @@ -2599,13 +2602,14 @@ void QAbstractItemView::updateEditorGeometries() } ++it; } else { - it = d->editors.erase(it); + d->indexEditorHash.remove(it.value()); + it = d->editorIndexHash.erase(it); editorsToRelease << editor; } } //we hide and release the editor outside of the loop because it might change the focus and try - //to change the d->editors list. + //to change the editors hashes. for (int i = 0; i < editorsToHide.count(); ++i) { editorsToHide.at(i)->hide(); } @@ -2945,7 +2949,7 @@ int QAbstractItemView::sizeHintForRow(int row) const { Q_D(const QAbstractItemView); - if (row < 0 || row >= d->model->rowCount() || !model()) + if (row < 0 || row >= d->model->rowCount(d->root)) return -1; ensurePolished(); @@ -2956,8 +2960,8 @@ int QAbstractItemView::sizeHintForRow(int row) const QModelIndex index; for (int c = 0; c < colCount; ++c) { index = d->model->index(row, c, d->root); - if (QWidget *editor = d->editorForIndex(index).editor) - height = qMax(height, editor->size().height()); + if (QWidget *editor = d->editorForIndex(index).widget.data()) + height = qMax(height, editor->height()); int hint = d->delegateForIndex(index)->sizeHint(option, index).height(); height = qMax(height, hint); } @@ -2976,7 +2980,7 @@ int QAbstractItemView::sizeHintForColumn(int column) const { Q_D(const QAbstractItemView); - if (column < 0 || column >= d->model->columnCount() || !model()) + if (column < 0 || column >= d->model->columnCount(d->root)) return -1; ensurePolished(); @@ -2987,7 +2991,7 @@ int QAbstractItemView::sizeHintForColumn(int column) const QModelIndex index; for (int r = 0; r < rows; ++r) { index = d->model->index(r, column, d->root); - if (QWidget *editor = d->editorForIndex(index).editor) + if (QWidget *editor = d->editorForIndex(index).widget.data()) width = qMax(width, editor->sizeHint().width()); int hint = d->delegateForIndex(index)->sizeHint(option, index).width(); width = qMax(width, hint); @@ -3023,8 +3027,7 @@ void QAbstractItemView::openPersistentEditor(const QModelIndex &index) void QAbstractItemView::closePersistentEditor(const QModelIndex &index) { Q_D(QAbstractItemView); - QWidget *editor = d->editorForIndex(index).editor; - if (editor) { + if (QWidget *editor = d->editorForIndex(index).widget.data()) { if (index == selectionModel()->currentIndex()) closeEditor(editor, QAbstractItemDelegate::RevertModelCache); d->persistent.remove(editor); @@ -3088,9 +3091,11 @@ void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget QWidget* QAbstractItemView::indexWidget(const QModelIndex &index) const { Q_D(const QAbstractItemView); - if (!d->isIndexValid(index)) - return 0; - return d->editorForIndex(index).editor; + if (d->isIndexValid(index)) + if (QWidget *editor = d->editorForIndex(index).widget.data()) + return editor; + + return 0; } /*! @@ -3152,12 +3157,12 @@ void QAbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelInde // Single item changed Q_D(QAbstractItemView); if (topLeft == bottomRight && topLeft.isValid()) { - const QEditorInfo editorInfo = d->editorForIndex(topLeft); + const QEditorInfo &editorInfo = d->editorForIndex(topLeft); //we don't update the edit data if it is static - if (!editorInfo.isStatic && editorInfo.editor) { + if (!editorInfo.isStatic && editorInfo.widget) { QAbstractItemDelegate *delegate = d->delegateForIndex(topLeft); if (delegate) { - delegate->setEditorData(editorInfo.editor, topLeft); + delegate->setEditorData(editorInfo.widget.data(), topLeft); } } if (isVisible() && !d->delayedPendingLayout) { @@ -3231,12 +3236,17 @@ void QAbstractItemView::rowsAboutToBeRemoved(const QModelIndex &parent, int star } // Remove all affected editors; this is more efficient than waiting for updateGeometries() to clean out editors for invalid indexes - for (int i = d->editors.size() - 1; i >= 0; --i) { - const QModelIndex index = d->editors.at(i).index; - QWidget *editor = d->editors.at(i).editor; + QEditorIndexHash::iterator i = d->editorIndexHash.begin(); + while (i != d->editorIndexHash.end()) { + const QModelIndex index = i.value(); if (index.row() >= start && index.row() <= end && d->model->parent(index) == parent) { - d->editors.removeAt(i); - d->releaseEditor(editor); + QWidget *editor = i.key(); + QEditorInfo info = d->indexEditorHash.take(index); + i = d->editorIndexHash.erase(i); + if (info.widget) + d->releaseEditor(editor); + } else { + ++i; } } } @@ -3293,17 +3303,20 @@ void QAbstractItemViewPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &par } // Remove all affected editors; this is more efficient than waiting for updateGeometries() to clean out editors for invalid indexes - QList<QEditorInfo>::iterator it = editors.begin(); - while (it != editors.end()) { - QModelIndex index = it->index; + QEditorIndexHash::iterator it = editorIndexHash.begin(); + while (it != editorIndexHash.end()) { + QModelIndex index = it.value(); if (index.column() <= start && index.column() >= end && model->parent(index) == parent) { - QWidget *editor = it->editor; - it = editors.erase(it); - releaseEditor(editor); + QWidget *editor = it.key(); + QEditorInfo info = indexEditorHash.take(it.value()); + it = editorIndexHash.erase(it); + if (info.widget) + releaseEditor(editor); } else { ++it; } } + } /*! @@ -3385,7 +3398,7 @@ void QAbstractItemView::currentChanged(const QModelIndex ¤t, const QModelI if (previous.isValid()) { QModelIndex buddy = d->model->buddy(previous); - QWidget *editor = d->editorForIndex(buddy).editor; + QWidget *editor = d->editorForIndex(buddy).widget.data(); if (editor && !d->persistent.contains(editor)) { commitData(editor); if (current.row() != previous.row()) @@ -3911,7 +3924,7 @@ QWidget *QAbstractItemViewPrivate::editor(const QModelIndex &index, const QStyleOptionViewItem &options) { Q_Q(QAbstractItemView); - QWidget *w = editorForIndex(index).editor; + QWidget *w = editorForIndex(index).widget.data(); if (!w) { QAbstractItemDelegate *delegate = delegateForIndex(index); if (!delegate) @@ -3942,6 +3955,7 @@ QWidget *QAbstractItemViewPrivate::editor(const QModelIndex &index, #endif } } + return w; } @@ -3950,11 +3964,11 @@ void QAbstractItemViewPrivate::updateEditorData(const QModelIndex &tl, const QMo // we are counting on having relatively few editors const bool checkIndexes = tl.isValid() && br.isValid(); const QModelIndex parent = tl.parent(); - QList<QEditorInfo>::const_iterator it = editors.constBegin(); - for (; it != editors.constEnd(); ++it) { - QWidget *editor = it->editor; - const QModelIndex index = it->index; - if (it->isStatic || editor == 0 || !index.isValid() || + QIndexEditorHash::const_iterator it = indexEditorHash.constBegin(); + for (; it != indexEditorHash.constEnd(); ++it) { + QWidget *editor = it.value().widget.data(); + const QModelIndex index = it.key(); + if (it.value().isStatic || !editor || !index.isValid() || (checkIndexes && (index.row() < tl.row() || index.row() > br.row() || index.column() < tl.column() || index.column() > br.column() @@ -4027,41 +4041,40 @@ void QAbstractItemViewPrivate::checkPersistentEditorFocus() } -QEditorInfo QAbstractItemViewPrivate::editorForIndex(const QModelIndex &index) const +const QEditorInfo & QAbstractItemViewPrivate::editorForIndex(const QModelIndex &index) const { - QList<QEditorInfo>::const_iterator it = editors.constBegin(); - for (; it != editors.constEnd(); ++it) { - if (it->index == index) - return *it; - } + static QEditorInfo nullInfo; - return QEditorInfo(); + QIndexEditorHash::const_iterator it = indexEditorHash.find(index); + if (it == indexEditorHash.end()) + return nullInfo; + + return it.value(); } QModelIndex QAbstractItemViewPrivate::indexForEditor(QWidget *editor) const { - QList<QEditorInfo>::const_iterator it = editors.constBegin(); - for (; it != editors.constEnd(); ++it) { - if (it->editor == editor) - return it->index; - } - return QModelIndex(); + QEditorIndexHash::const_iterator it = editorIndexHash.find(editor); + if (it == editorIndexHash.end()) + return QModelIndex(); + + return it.value(); } void QAbstractItemViewPrivate::removeEditor(QWidget *editor) { - QList<QEditorInfo>::iterator it = editors.begin(); - for (; it != editors.end(); ) { - if (it->editor == editor) - it = editors.erase(it); - else - ++it; + QEditorIndexHash::iterator it = editorIndexHash.find(editor); + if (it != editorIndexHash.end()) + { + indexEditorHash.remove(it.value()); + editorIndexHash.erase(it); } } void QAbstractItemViewPrivate::addEditor(const QModelIndex &index, QWidget *editor, bool isStatic) { - editors.append(QEditorInfo(index, editor, isStatic)); + editorIndexHash.insert(editor, index); + indexEditorHash.insert(index, QEditorInfo(editor, isStatic)); } bool QAbstractItemViewPrivate::sendDelegateEvent(const QModelIndex &index, QEvent *event) const diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index fce74f3..03b413a 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -70,22 +70,18 @@ QT_BEGIN_NAMESPACE -struct QEditorInfo -{ - QEditorInfo() : isStatic(false) - { - } - - QEditorInfo(const QPersistentModelIndex &i, QWidget *e, bool b) : index(i), editor(e), isStatic(b) - { - } - - QPersistentModelIndex index; - QPointer<QWidget> editor; - bool isStatic; //true when called from setIndexWidget +struct QEditorInfo { + QEditorInfo(QWidget *e, bool s): widget(QWeakPointer<QWidget>(e)), isStatic(s) {} + QEditorInfo(): isStatic(false) {} + QWeakPointer<QWidget> widget; + bool isStatic; }; +// Fast associativity between Persistent editors and indices. +typedef QHash<QWidget *, QPersistentModelIndex> QEditorIndexHash; +typedef QHash<QPersistentModelIndex, QEditorInfo> QIndexEditorHash; + typedef QPair<QRect, QModelIndex> QItemViewPaintPair; typedef QList<QItemViewPaintPair> QItemViewPaintPairs; @@ -135,8 +131,9 @@ public: } void stopAutoScroll() { autoScrollTimer.stop(); autoScrollCount = 0;} - - bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); +#ifndef QT_NO_DRAGANDDROP + virtual bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); +#endif bool droppingOnItself(QDropEvent *event, const QModelIndex &index); QWidget *editor(const QModelIndex &index, const QStyleOptionViewItem &options); @@ -247,9 +244,9 @@ public: : q->horizontalOffset(), q->verticalOffset()); } - QEditorInfo editorForIndex(const QModelIndex &index) const; + const QEditorInfo &editorForIndex(const QModelIndex &index) const; inline bool hasEditor(const QModelIndex &index) const { - return editorForIndex(index).editor != 0; + return indexEditorHash.find(index) != indexEditorHash.constEnd(); } QModelIndex indexForEditor(QWidget *editor) const; @@ -352,7 +349,8 @@ public: QAbstractItemView::SelectionMode selectionMode; QAbstractItemView::SelectionBehavior selectionBehavior; - QList<QEditorInfo> editors; + QEditorIndexHash editorIndexHash; + QIndexEditorHash indexEditorHash; QSet<QWidget*> persistent; QWidget *currentlyCommittingEditor; @@ -367,6 +365,7 @@ public: bool viewportEnteredNeeded; QAbstractItemView::State state; + QAbstractItemView::State stateBeforeAnimation; QAbstractItemView::EditTriggers editTriggers; QAbstractItemView::EditTrigger lastTrigger; diff --git a/src/gui/itemviews/qabstractproxymodel.cpp b/src/gui/itemviews/qabstractproxymodel.cpp index 1c600e2..51dfa7a 100644 --- a/src/gui/itemviews/qabstractproxymodel.cpp +++ b/src/gui/itemviews/qabstractproxymodel.cpp @@ -45,6 +45,9 @@ #include "qitemselectionmodel.h" #include <private/qabstractproxymodel_p.h> +#include <QtCore/QSize> +#include <QtCore/QStringList> + QT_BEGIN_NAMESPACE @@ -270,6 +273,15 @@ bool QAbstractProxyModel::setData(const QModelIndex &index, const QVariant &valu /*! \reimp */ +bool QAbstractProxyModel::setItemData(const QModelIndex &index, const QMap< int, QVariant >& roles) +{ + Q_D(QAbstractProxyModel); + return d->model->setItemData(mapToSource(index), roles); +} + +/*! + \reimp + */ bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) { Q_D(QAbstractProxyModel); @@ -284,6 +296,90 @@ bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation return d->model->setHeaderData(sourceSection, orientation, value, role); } +/*! + \reimp + */ +QModelIndex QAbstractProxyModel::buddy(const QModelIndex &index) const +{ + Q_D(const QAbstractProxyModel); + return mapFromSource(d->model->buddy(mapToSource(index))); +} + +/*! + \reimp + */ +bool QAbstractProxyModel::canFetchMore(const QModelIndex &parent) const +{ + Q_D(const QAbstractProxyModel); + return d->model->canFetchMore(mapToSource(parent)); +} + +/*! + \reimp + */ +void QAbstractProxyModel::fetchMore(const QModelIndex &parent) +{ + Q_D(QAbstractProxyModel); + d->model->fetchMore(mapToSource(parent)); +} + +/*! + \reimp + */ +void QAbstractProxyModel::sort(int column, Qt::SortOrder order) +{ + Q_D(QAbstractProxyModel); + d->model->sort(column, order); +} + +/*! + \reimp + */ +QSize QAbstractProxyModel::span(const QModelIndex &index) const +{ + Q_D(const QAbstractProxyModel); + return d->model->span(mapToSource(index)); +} + +/*! + \reimp + */ +bool QAbstractProxyModel::hasChildren(const QModelIndex &parent) const +{ + Q_D(const QAbstractProxyModel); + return d->model->hasChildren(mapToSource(parent)); +} + +/*! + \reimp + */ +QMimeData* QAbstractProxyModel::mimeData(const QModelIndexList &indexes) const +{ + Q_D(const QAbstractProxyModel); + QModelIndexList list; + foreach(const QModelIndex &index, indexes) + list << mapToSource(index); + return d->model->mimeData(indexes); +} + +/*! + \reimp + */ +QStringList QAbstractProxyModel::mimeTypes() const +{ + Q_D(const QAbstractProxyModel); + return d->model->mimeTypes(); +} + +/*! + \reimp + */ +Qt::DropActions QAbstractProxyModel::supportedDropActions() const +{ + Q_D(const QAbstractProxyModel); + return d->model->supportedDropActions(); +} + QT_END_NAMESPACE #include "moc_qabstractproxymodel.cpp" diff --git a/src/gui/itemviews/qabstractproxymodel.h b/src/gui/itemviews/qabstractproxymodel.h index c6bb985..a5a1168 100644 --- a/src/gui/itemviews/qabstractproxymodel.h +++ b/src/gui/itemviews/qabstractproxymodel.h @@ -81,8 +81,20 @@ public: Qt::ItemFlags flags(const QModelIndex &index) const; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + bool setItemData(const QModelIndex& index, const QMap<int, QVariant> &roles); bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole); + QModelIndex buddy(const QModelIndex &index) const; + bool canFetchMore(const QModelIndex &parent) const; + void fetchMore(const QModelIndex &parent); + void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); + QSize span(const QModelIndex &index) const; + bool hasChildren(const QModelIndex &parent = QModelIndex()) const; + + QMimeData* mimeData(const QModelIndexList &indexes) const; + QStringList mimeTypes() const; + Qt::DropActions supportedDropActions() const; + protected: QAbstractProxyModel(QAbstractProxyModelPrivate &, QObject *parent); diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp index 67854a3..7eb3ddc 100644 --- a/src/gui/itemviews/qheaderview.cpp +++ b/src/gui/itemviews/qheaderview.cpp @@ -2105,7 +2105,7 @@ void QHeaderView::paintEvent(QPaintEvent *e) QVariant variant = d->model->headerData(logical, d->orientation, Qt::FontRole); - if (variant.isValid() && qVariantCanConvert<QFont>(variant)) { + if (variant.isValid() && variant.canConvert<QFont>()) { QFont sectionFont = qvariant_cast<QFont>(variant); painter.setFont(sectionFont); } @@ -2485,13 +2485,13 @@ void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logical opt.icon = qvariant_cast<QPixmap>(variant); QVariant foregroundBrush = d->model->headerData(logicalIndex, d->orientation, Qt::ForegroundRole); - if (qVariantCanConvert<QBrush>(foregroundBrush)) + if (foregroundBrush.canConvert<QBrush>()) opt.palette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(foregroundBrush)); QPointF oldBO = painter->brushOrigin(); QVariant backgroundBrush = d->model->headerData(logicalIndex, d->orientation, Qt::BackgroundRole); - if (qVariantCanConvert<QBrush>(backgroundBrush)) { + if (backgroundBrush.canConvert<QBrush>()) { opt.palette.setBrush(QPalette::Button, qvariant_cast<QBrush>(backgroundBrush)); opt.palette.setBrush(QPalette::Window, qvariant_cast<QBrush>(backgroundBrush)); painter->setBrushOrigin(opt.rect.topLeft()); @@ -2552,7 +2552,7 @@ QSize QHeaderView::sectionSizeFromContents(int logicalIndex) const QVariant var = d->model->headerData(logicalIndex, d->orientation, Qt::FontRole); QFont fnt; - if (var.isValid() && qVariantCanConvert<QFont>(var)) + if (var.isValid() && var.canConvert<QFont>()) fnt = qvariant_cast<QFont>(var); else fnt = font(); diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp index 9bbfc23..6556a3e 100644 --- a/src/gui/itemviews/qitemdelegate.cpp +++ b/src/gui/itemviews/qitemdelegate.cpp @@ -850,7 +850,7 @@ void QItemDelegate::drawBackground(QPainter *painter, painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight)); } else { QVariant value = index.data(Qt::BackgroundRole); - if (qVariantCanConvert<QBrush>(value)) { + if (value.canConvert<QBrush>()) { QPointF oldBO = painter->brushOrigin(); painter->setBrushOrigin(option.rect.topLeft()); painter->fillRect(option.rect, qvariant_cast<QBrush>(value)); @@ -1278,7 +1278,8 @@ bool QItemDelegate::editorEvent(QEvent *event, // make sure that we have the right event type if ((event->type() == QEvent::MouseButtonRelease) - || (event->type() == QEvent::MouseButtonDblClick)) { + || (event->type() == QEvent::MouseButtonDblClick) + || (event->type() == QEvent::MouseButtonPress)) { QRect checkRect = check(option, option.rect, Qt::Checked); QRect emptyRect; doLayout(option, &checkRect, &emptyRect, &emptyRect, false); @@ -1287,7 +1288,8 @@ bool QItemDelegate::editorEvent(QEvent *event, return false; // eat the double click events inside the check rect - if (event->type() == QEvent::MouseButtonDblClick) + if ((event->type() == QEvent::MouseButtonPress) + || (event->type() == QEvent::MouseButtonDblClick)) return true; } else if (event->type() == QEvent::KeyPress) { @@ -1326,7 +1328,7 @@ QStyleOptionViewItem QItemDelegate::setOptions(const QModelIndex &index, // set foreground brush value = index.data(Qt::ForegroundRole); - if (qVariantCanConvert<QBrush>(value)) + if (value.canConvert<QBrush>()) opt.palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value)); return opt; diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp index f848321..7156b87 100644 --- a/src/gui/itemviews/qitemselectionmodel.cpp +++ b/src/gui/itemviews/qitemselectionmodel.cpp @@ -212,6 +212,7 @@ bool QItemSelectionRange::intersects(const QItemSelectionRange &other) const { return (isValid() && other.isValid() && parent() == other.parent() + && model() == other.model() && ((top() <= other.top() && bottom() >= other.top()) || (top() >= other.top() && top() <= other.bottom())) && ((left() <= other.left() && right() >= other.left()) @@ -508,7 +509,7 @@ void QItemSelection::merge(const QItemSelection &other, QItemSelectionModel::Sel void QItemSelection::split(const QItemSelectionRange &range, const QItemSelectionRange &other, QItemSelection *result) { - if (range.parent() != other.parent()) + if (range.parent() != other.parent() || range.model() != other.model()) return; QModelIndex parent = other.parent(); @@ -634,6 +635,7 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare } QItemSelection deselected; + QItemSelection newParts; QItemSelection::iterator it = ranges.begin(); while (it != ranges.end()) { if (it->topLeft().parent() != parent) { // Check parents until reaching root or contained in range @@ -659,13 +661,20 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()), it->bottomRight())); *it = QItemSelectionRange(it->topLeft(), model->index(start - 1, it->right(), it->parent())); ++it; - } else { - if (it->top() < start && end < it->bottom()) // Middle intersection (do nothing) - deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()), - model->index(end, it->left(), it->parent()))); + } else if (it->top() < start && end < it->bottom()) { // Middle intersection + // If the parent contains (1, 2, 3, 4, 5, 6, 7, 8) and [3, 4, 5, 6] is selected, + // and [4, 5] is removed, we need to split [3, 4, 5, 6] into [3], [4, 5] and [6]. + // [4, 5] is appended to deselected, and [3] and [6] remain part of the selection + // in ranges. + const QItemSelectionRange removedRange(model->index(start, it->right(), it->parent()), + model->index(end, it->left(), it->parent())); + deselected.append(removedRange); + QItemSelection::split(*it, removedRange, &newParts); + it = ranges.erase(it); + } else ++it; - } } + ranges.append(newParts); if (!deselected.isEmpty()) emit q->selectionChanged(QItemSelection(), deselected); diff --git a/src/gui/itemviews/qitemselectionmodel.h b/src/gui/itemviews/qitemselectionmodel.h index 436514f..e2bd06b 100644 --- a/src/gui/itemviews/qitemselectionmodel.h +++ b/src/gui/itemviews/qitemselectionmodel.h @@ -101,6 +101,30 @@ public: { return (tl == other.tl && br == other.br); } inline bool operator!=(const QItemSelectionRange &other) const { return !operator==(other); } + inline bool operator<(const QItemSelectionRange &other) const + { + // Comparing parents will compare the models, but if two equivalent ranges + // in two different models have invalid parents, they would appear the same + if (other.tl.model() == tl.model()) { + // parent has to be calculated, so we only do so once. + const QModelIndex topLeftParent = tl.parent(); + const QModelIndex otherTopLeftParent = other.tl.parent(); + if (topLeftParent == otherTopLeftParent) { + if (other.tl.row() == tl.row()) { + if (other.tl.column() == tl.column()) { + if (other.br.row() == br.row()) { + return br.column() < other.br.column(); + } + return br.row() < other.br.row(); + } + return tl.column() < other.tl.column(); + } + return tl.row() < other.tl.row(); + } + return topLeftParent < otherTopLeftParent; + } + return tl.model() < other.tl.model(); + } inline bool isValid() const { diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 76d7642..ce1f0e5 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -756,10 +756,13 @@ void QListView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e // if the parent is above d->root in the tree, nothing will happen QAbstractItemView::rowsAboutToBeRemoved(parent, start, end); if (parent == d->root) { - for (int i = d->hiddenRows.count() - 1; i >= 0; --i) { - int hiddenRow = d->hiddenRows.at(i).row(); + QSet<QPersistentModelIndex>::iterator it = d->hiddenRows.begin(); + while (it != d->hiddenRows.end()) { + int hiddenRow = it->row(); if (hiddenRow >= start && hiddenRow <= end) { - d->hiddenRows.remove(i); + it = d->hiddenRows.erase(it); + } else { + ++it; } } } @@ -1033,16 +1036,7 @@ void QListView::paintEvent(QPaintEvent *e) previousRow = row; } - if (const QWidget *widget = d->editorForIndex(*it).editor) { - QRegion itemGeometry(option.rect); - QRegion widgetGeometry(widget->geometry()); - painter.save(); - painter.setClipRegion(itemGeometry.subtracted(widgetGeometry)); - d->delegateForIndex(*it)->paint(&painter, option, *it); - painter.restore(); - } else { - d->delegateForIndex(*it)->paint(&painter, option, *it); - } + d->delegateForIndex(*it)->paint(&painter, option, *it); } #ifndef QT_NO_DRAGANDDROP @@ -1833,6 +1827,14 @@ QAbstractItemView::DropIndicatorPosition QListViewPrivate::position(const QPoint else return QAbstractItemViewPrivate::position(pos, rect, idx); } + +bool QListViewPrivate::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex) +{ + if (viewMode == QListView::ListMode && flow == QListView::LeftToRight) + return static_cast<QListModeViewBase *>(commonListView)->dropOn(event, dropRow, dropCol, dropIndex); + else + return QAbstractItemViewPrivate::dropOn(event, dropRow, dropCol, dropIndex); +} #endif /* @@ -1841,12 +1843,12 @@ QAbstractItemView::DropIndicatorPosition QListViewPrivate::position(const QPoint void QCommonListViewBase::appendHiddenRow(int row) { - dd->hiddenRows.append(dd->model->index(row, 0, qq->rootIndex())); + dd->hiddenRows.insert(dd->model->index(row, 0, qq->rootIndex())); } void QCommonListViewBase::removeHiddenRow(int row) { - dd->hiddenRows.remove(dd->hiddenRows.indexOf(dd->model->index(row, 0, qq->rootIndex()))); + dd->hiddenRows.remove(dd->model->index(row, 0, qq->rootIndex())); } void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step) @@ -1960,7 +1962,13 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) // ignore by default event->ignore(); - QModelIndex index = qq->indexAt(event->pos()); + // can't use indexAt, doesn't account for spacing. + QPoint p = event->pos(); + QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1); + rect.adjust(-dd->spacing(), -dd->spacing(), dd->spacing(), dd->spacing()); + const QVector<QModelIndex> intersectVector = dd->intersectingSet(rect); + QModelIndex index = intersectVector.count() > 0 + ? intersectVector.last() : QModelIndex(); dd->hover = index; if (!dd->droppingOnItself(event, index) && dd->canDecode(event)) { @@ -1968,10 +1976,11 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) if (index.isValid() && dd->showDropIndicator) { QRect rect = qq->visualRect(index); dd->dropIndicatorPosition = position(event->pos(), rect, index); + // if spacing, should try to draw between items, not just next to item. switch (dd->dropIndicatorPosition) { case QAbstractItemView::AboveItem: if (dd->isIndexDropEnabled(index.parent())) { - dd->dropIndicatorRect = QRect(rect.left(), rect.top(), 0, rect.height()); + dd->dropIndicatorRect = QRect(rect.left()-dd->spacing(), rect.top(), 0, rect.height()); event->accept(); } else { dd->dropIndicatorRect = QRect(); @@ -1979,7 +1988,7 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) break; case QAbstractItemView::BelowItem: if (dd->isIndexDropEnabled(index.parent())) { - dd->dropIndicatorRect = QRect(rect.right(), rect.top(), 0, rect.height()); + dd->dropIndicatorRect = QRect(rect.right()+dd->spacing(), rect.top(), 0, rect.height()); event->accept(); } else { dd->dropIndicatorRect = QRect(); @@ -2014,6 +2023,68 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) qq->startAutoScroll(); } +/*! + If the event hasn't already been accepted, determines the index to drop on. + + if (row == -1 && col == -1) + // append to this drop index + else + // place at row, col in drop index + + If it returns true a drop can be done, and dropRow, dropCol and dropIndex reflects the position of the drop. + \internal + */ +bool QListModeViewBase::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex) +{ + if (event->isAccepted()) + return false; + + QModelIndex index; + if (dd->viewport->rect().contains(event->pos())) { + // can't use indexAt, doesn't account for spacing. + QPoint p = event->pos(); + QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1); + rect.adjust(-dd->spacing(), -dd->spacing(), dd->spacing(), dd->spacing()); + const QVector<QModelIndex> intersectVector = dd->intersectingSet(rect); + index = intersectVector.count() > 0 + ? intersectVector.last() : QModelIndex(); + if (!index.isValid()) + index = dd->root; + } + + // If we are allowed to do the drop + if (dd->model->supportedDropActions() & event->dropAction()) { + int row = -1; + int col = -1; + if (index != dd->root) { + dd->dropIndicatorPosition = position(event->pos(), qq->visualRect(index), index); + switch (dd->dropIndicatorPosition) { + case QAbstractItemView::AboveItem: + row = index.row(); + col = index.column(); + index = index.parent(); + break; + case QAbstractItemView::BelowItem: + row = index.row() + 1; + col = index.column(); + index = index.parent(); + break; + case QAbstractItemView::OnItem: + case QAbstractItemView::OnViewport: + break; + } + } else { + dd->dropIndicatorPosition = QAbstractItemView::OnViewport; + } + *dropIndex = index; + *dropRow = row; + *dropCol = col; + if (!dd->droppingOnItself(event, index)) + return true; + } + return false; +} + #endif //QT_NO_DRAGANDDROP void QListModeViewBase::updateVerticalScrollBar(const QSize &step) @@ -2107,7 +2178,7 @@ int QListModeViewBase::verticalOffset() const int value = verticalScrollBar()->value(); if (value >= segmentPositions.count()) return 0; - return segmentPositions.at(value); + return segmentPositions.at(value) - spacing(); } } else if (flow() == QListView::TopToBottom && !flowPositions.isEmpty()) { int value = verticalScrollBar()->value(); @@ -2155,14 +2226,14 @@ void QListModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand) if (horizontal && flow() == QListView::TopToBottom && dx != 0) { int currentValue = qBound(0, horizontalValue, max); int previousValue = qBound(0, currentValue + dx, max); - int currentCoordinate = segmentPositions.at(currentValue); - int previousCoordinate = segmentPositions.at(previousValue); + int currentCoordinate = segmentPositions.at(currentValue) - spacing(); + int previousCoordinate = segmentPositions.at(previousValue) - spacing(); dx = previousCoordinate - currentCoordinate; } else if (vertical && flow() == QListView::LeftToRight && dy != 0) { int currentValue = qBound(0, verticalValue, max); int previousValue = qBound(0, currentValue + dy, max); - int currentCoordinate = segmentPositions.at(currentValue); - int previousCoordinate = segmentPositions.at(previousValue); + int currentCoordinate = segmentPositions.at(currentValue) - spacing(); + int previousCoordinate = segmentPositions.at(previousValue) - spacing(); dy = previousCoordinate - currentCoordinate; } } else { @@ -2330,6 +2401,8 @@ void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info) segmentExtents.append(flowPosition); flowPosition = info.spacing + segStartPosition; segPosition += deltaSegPosition; + if (info.wrap) + segPosition += info.spacing; segmentPositions.append(segPosition); segmentStartRows.append(row); deltaSegPosition = 0; diff --git a/src/gui/itemviews/qlistview_p.h b/src/gui/itemviews/qlistview_p.h index bf7657b..1b71131 100644 --- a/src/gui/itemviews/qlistview_p.h +++ b/src/gui/itemviews/qlistview_p.h @@ -237,6 +237,7 @@ public: // WARNING: Plenty of duplicated code from QAbstractItemView{,Private}. QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; void dragMoveEvent(QDragMoveEvent *e); + bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); #endif private: @@ -364,6 +365,7 @@ public: #ifndef QT_NO_DRAGANDDROP virtual QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; + bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); #endif inline void setGridSize(const QSize &size) { grid = size; } @@ -376,7 +378,10 @@ public: inline bool isSelectionRectVisible() const { return showElasticBand; } inline QModelIndex modelIndex(int row) const { return model->index(row, column, root); } - inline bool isHidden(int row) const { return hiddenRows.contains(model->index(row, 0, root)); } + inline bool isHidden(int row) const { + QModelIndex idx = model->index(row, 0, root); + return isPersistent(idx) && hiddenRows.contains(idx); + } inline bool isHiddenOrDisabled(int row) const { return isHidden(row) || !isIndexEnabled(modelIndex(row)); } inline void removeCurrentAndDisabled(QVector<QModelIndex> *indexes, const QModelIndex ¤t) const { @@ -430,7 +435,7 @@ public: QBasicTimer batchLayoutTimer; // used for hidden items - QVector<QPersistentModelIndex> hiddenRows; + QSet<QPersistentModelIndex> hiddenRows; int column; bool uniformItemSizes; diff --git a/src/gui/itemviews/qstyleditemdelegate.cpp b/src/gui/itemviews/qstyleditemdelegate.cpp index 880f8ab..9ccfb76 100644 --- a/src/gui/itemviews/qstyleditemdelegate.cpp +++ b/src/gui/itemviews/qstyleditemdelegate.cpp @@ -326,7 +326,7 @@ void QStyledItemDelegate::initStyleOption(QStyleOptionViewItem *option, option->displayAlignment = Qt::Alignment(value.toInt()); value = index.data(Qt::ForegroundRole); - if (qVariantCanConvert<QBrush>(value)) + if (value.canConvert<QBrush>()) option->palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value)); if (QStyleOptionViewItemV4 *v4 = qstyleoption_cast<QStyleOptionViewItemV4 *>(option)) { @@ -727,7 +727,8 @@ bool QStyledItemDelegate::editorEvent(QEvent *event, // make sure that we have the right event type if ((event->type() == QEvent::MouseButtonRelease) - || (event->type() == QEvent::MouseButtonDblClick)) { + || (event->type() == QEvent::MouseButtonDblClick) + || (event->type() == QEvent::MouseButtonPress)) { QStyleOptionViewItemV4 viewOpt(option); initStyleOption(&viewOpt, index); QRect checkRect = style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &viewOpt, widget); @@ -735,8 +736,8 @@ bool QStyledItemDelegate::editorEvent(QEvent *event, if (me->button() != Qt::LeftButton || !checkRect.contains(me->pos())) return false; - // eat the double click events inside the check rect - if (event->type() == QEvent::MouseButtonDblClick) + if ((event->type() == QEvent::MouseButtonPress) + || (event->type() == QEvent::MouseButtonDblClick)) return true; } else if (event->type() == QEvent::KeyPress) { diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp index 4492e53..d8fef55 100644 --- a/src/gui/itemviews/qtableview.cpp +++ b/src/gui/itemviews/qtableview.cpp @@ -926,14 +926,7 @@ void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItemV4 q->style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, q); - if (const QWidget *widget = editorForIndex(index).editor) { - painter->save(); - painter->setClipRect(widget->geometry()); - q->itemDelegate(index)->paint(painter, opt, index); - painter->restore(); - } else { - q->itemDelegate(index)->paint(painter, opt, index); - } + q->itemDelegate(index)->paint(painter, opt, index); } /*! @@ -2166,7 +2159,7 @@ int QTableView::sizeHintForRow(int row) const option.rect.setWidth(columnWidth(index.column())); } - QWidget *editor = d->editorForIndex(index).editor; + QWidget *editor = d->editorForIndex(index).widget.data(); if (editor && d->persistent.contains(editor)) { hint = qMax(hint, editor->sizeHint().height()); int min = editor->minimumSize().height(); @@ -2219,7 +2212,7 @@ int QTableView::sizeHintForColumn(int column) const continue; index = d->model->index(logicalRow, column, d->root); - QWidget *editor = d->editorForIndex(index).editor; + QWidget *editor = d->editorForIndex(index).widget.data(); if (editor && d->persistent.contains(editor)) { hint = qMax(hint, editor->sizeHint().width()); int min = editor->minimumSize().width(); diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index b797776..e393902 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -1493,7 +1493,7 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option, // when the row contains an index widget which has focus, // we want to paint the entire row as active bool indexWidgetHasFocus = false; - if ((current.row() == index.row()) && !d->editors.isEmpty()) { + if ((current.row() == index.row()) && !d->editorIndexHash.isEmpty()) { const int r = index.row(); QWidget *fw = QApplication::focusWidget(); for (int c = 0; c < header->count(); ++c) { @@ -1669,14 +1669,7 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option, opt.state = oldState; } - if (const QWidget *widget = d->editorForIndex(modelIndex).editor) { - painter->save(); - painter->setClipRect(widget->geometry()); - d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex); - painter->restore(); - } else { - d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex); - } + d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex); } if (currentRowHasFocus) { @@ -2395,7 +2388,7 @@ void QTreeView::scrollContentsBy(int dx, int dy) int viewCount = d->viewport->height() / itemHeight; int maxDeltaY = qMin(d->viewItems.count(), viewCount); // no need to do a lot of work if we are going to redraw the whole thing anyway - if (qAbs(dy) > qAbs(maxDeltaY) && d->editors.isEmpty()) { + if (qAbs(dy) > qAbs(maxDeltaY) && d->editorIndexHash.isEmpty()) { verticalScrollBar()->update(); d->viewport->update(); return; @@ -2469,11 +2462,9 @@ void QTreeView::rowsInserted(const QModelIndex &parent, int start, int end) } const int parentItem = d->viewIndex(parent); - if (((parentItem != -1) && d->viewItems.at(parentItem).expanded && updatesEnabled()) + if (((parentItem != -1) && d->viewItems.at(parentItem).expanded) || (parent == d->root)) { d->doDelayedItemsLayout(); - } else if ((parentItem != -1) && d->viewItems.at(parentItem).expanded) { - d->doDelayedItemsLayout(); } else if (parentItem != -1 && (d->model->rowCount(parent) == end - start + 1)) { // the parent just went from 0 children to more. update to re-paint the decoration d->viewItems[parentItem].hasChildren = true; @@ -2727,7 +2718,7 @@ int QTreeView::sizeHintForColumn(int column) const continue; // we have no good size hint QModelIndex index = viewItems.at(i).index; index = index.sibling(index.row(), column); - QWidget *editor = d->editorForIndex(index).editor; + QWidget *editor = d->editorForIndex(index).widget.data(); if (editor && d->persistent.contains(editor)) { w = qMax(w, editor->sizeHint().width()); int min = editor->minimumSize().width(); @@ -2791,7 +2782,7 @@ int QTreeView::indexRowSizeHint(const QModelIndex &index) const continue; QModelIndex idx = d->model->index(index.row(), logicalColumn, parent); if (idx.isValid()) { - QWidget *editor = d->editorForIndex(idx).editor; + QWidget *editor = d->editorForIndex(idx).widget.data(); if (editor && d->persistent.contains(editor)) { height = qMax(height, editor->sizeHint().height()); int min = editor->minimumSize().height(); @@ -2870,13 +2861,13 @@ void QTreeViewPrivate::expand(int item, bool emitSignal) if (emitSignal && animationsEnabled) prepareAnimatedOperation(item, QVariantAnimation::Forward); #endif //QT_NO_ANIMATION - QAbstractItemView::State oldState = state; + stateBeforeAnimation = state; q->setState(QAbstractItemView::ExpandingState); const QModelIndex index = viewItems.at(item).index; storeExpanded(index); viewItems[item].expanded = true; layout(item); - q->setState(oldState); + q->setState(stateBeforeAnimation); if (model->canFetchMore(index)) model->fetchMore(index); @@ -2945,7 +2936,7 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal) prepareAnimatedOperation(item, QVariantAnimation::Backward); #endif //QT_NO_ANIMATION - QAbstractItemView::State oldState = state; + stateBeforeAnimation = state; q->setState(QAbstractItemView::CollapsingState); expandedIndexes.erase(it); viewItems[item].expanded = false; @@ -2955,7 +2946,7 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal) index = viewItems[index].parentItem; } removeViewItems(item + 1, total); // collapse - q->setState(oldState); + q->setState(stateBeforeAnimation); if (emitSignal) { emit q->collapsed(modelIndex); @@ -3040,9 +3031,9 @@ QPixmap QTreeViewPrivate::renderTreeToPixmapForAnimation(const QRect &rect) cons //and now let's render the editors the editors QStyleOptionViewItemV4 option = viewOptionsV4(); - for (QList<QEditorInfo>::const_iterator it = editors.constBegin(); it != editors.constEnd(); ++it) { - QWidget *editor = it->editor; - QModelIndex index = it->index; + for (QEditorIndexHash::const_iterator it = editorIndexHash.constBegin(); it != editorIndexHash.constEnd(); ++it) { + QWidget *editor = it.key(); + const QModelIndex &index = it.value(); option.rect = q->visualRect(index); if (option.rect.isValid()) { @@ -3066,7 +3057,7 @@ QPixmap QTreeViewPrivate::renderTreeToPixmapForAnimation(const QRect &rect) cons void QTreeViewPrivate::_q_endAnimatedOperation() { Q_Q(QTreeView); - q->setState(QAbstractItemView::NoState); + q->setState(stateBeforeAnimation); q->updateGeometries(); viewport->update(); } diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index f9c84c1..2629d7f 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -216,7 +216,8 @@ embedded { qcocoaapplicationdelegate_mac_p.h \ qmacgesturerecognizer_mac_p.h \ qmultitouch_mac_p.h \ - qcocoasharedwindowmethods_mac_p.h + qcocoasharedwindowmethods_mac_p.h \ + qcocoaintrospection_p.h OBJECTIVE_SOURCES += \ kernel/qcursor_mac.mm \ @@ -236,7 +237,8 @@ embedded { kernel/qeventdispatcher_mac.mm \ kernel/qcocoawindowcustomthemeframe_mac.mm \ kernel/qmacgesturerecognizer_mac.mm \ - kernel/qmultitouch_mac.mm + kernel/qmultitouch_mac.mm \ + kernel/qcocoaintrospection_mac.mm HEADERS += \ kernel/qt_cocoa_helpers_mac_p.h \ diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 43d5772..d97a57e 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -153,8 +153,6 @@ QT_BEGIN_NAMESPACE Q_CORE_EXPORT void qt_call_post_routines(); -int QApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly, but it's at least 4.0.0 - QApplication::Type qt_appType=QApplication::Tty; QApplicationPrivate *QApplicationPrivate::self = 0; @@ -169,8 +167,8 @@ bool QApplicationPrivate::autoSipEnabled = false; bool QApplicationPrivate::autoSipEnabled = true; #endif -QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type) - : QCoreApplicationPrivate(argc, argv) +QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type, int flags) + : QCoreApplicationPrivate(argc, argv, flags) { application_type = type; qt_appType = type; @@ -715,12 +713,12 @@ void QApplicationPrivate::process_cmdline() */ QApplication::QApplication(int &argc, char **argv) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, 0x040000)) { Q_D(QApplication); d->construct(); } QApplication::QApplication(int &argc, char **argv, int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) -{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;} + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, _internal)) +{ Q_D(QApplication); d->construct(); } /*! @@ -749,12 +747,12 @@ QApplication::QApplication(int &argc, char **argv, int _internal) */ QApplication::QApplication(int &argc, char **argv, bool GUIenabled ) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty, 0x040000)) { Q_D(QApplication); d->construct(); } QApplication::QApplication(int &argc, char **argv, bool GUIenabled , int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty)) -{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;} + : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty, _internal)) +{ Q_D(QApplication); d->construct();} @@ -772,12 +770,12 @@ QApplication::QApplication(int &argc, char **argv, bool GUIenabled , int _intern \c -qws option). */ QApplication::QApplication(int &argc, char **argv, Type type) - : QCoreApplication(*new QApplicationPrivate(argc, argv, type)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, type, 0x040000)) { Q_D(QApplication); d->construct(); } QApplication::QApplication(int &argc, char **argv, Type type , int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, type)) -{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;} + : QCoreApplication(*new QApplicationPrivate(argc, argv, type, _internal)) +{ Q_D(QApplication); d->construct(); } #if defined(Q_WS_X11) && !defined(QT_NO_EGL) static int qt_matchLibraryName(dl_phdr_info *info, size_t, void *data) @@ -883,7 +881,7 @@ static char *aargv[] = { (char*)"unknown", 0 }; This function is only available on X11. */ QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap) - : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient, 0x040000)) { if (! dpy) qWarning("QApplication: Invalid Display* argument"); @@ -892,7 +890,7 @@ QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap) } QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap, int _internal) - : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient, _internal)) { if (! dpy) qWarning("QApplication: Invalid Display* argument"); @@ -917,7 +915,7 @@ QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap, */ QApplication::QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE colormap) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, 0x040000)) { if (! dpy) qWarning("QApplication: Invalid Display* argument"); @@ -927,7 +925,7 @@ QApplication::QApplication(Display *dpy, int &argc, char **argv, QApplication::QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE colormap, int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, _internal)) { if (! dpy) qWarning("QApplication: Invalid Display* argument"); @@ -3732,11 +3730,6 @@ bool QApplication::notify(QObject *receiver, QEvent *e) d->checkReceiverThread(receiver); #endif -#ifdef QT3_SUPPORT - if (e->type() == QEvent::ChildRemoved && !receiver->d_func()->pendingChildInsertedEvents.isEmpty()) - receiver->d_func()->removePendingChildInsertedEvents(static_cast<QChildEvent *>(e)->child()); -#endif // QT3_SUPPORT - // capture the current mouse/keyboard state if(e->spontaneous()) { if (e->type() == QEvent::KeyPress @@ -5839,12 +5832,12 @@ Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window, #ifndef QT_NO_GESTURES QGestureManager* QGestureManager::instance() { - if (QApplicationPrivate *qAppPriv = QApplicationPrivate::instance()) { - if (!qAppPriv->gestureManager) - qAppPriv->gestureManager = new QGestureManager(qApp); - return qAppPriv->gestureManager; - } - return 0; + QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); + if (!qAppPriv) + return 0; + if (!qAppPriv->gestureManager) + qAppPriv->gestureManager = new QGestureManager(qApp); + return qAppPriv->gestureManager; } #endif // QT_NO_GESTURES diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h index 0242582..a790c69 100644 --- a/src/gui/kernel/qapplication.h +++ b/src/gui/kernel/qapplication.h @@ -123,15 +123,15 @@ public: #endif #ifndef qdoc - QApplication(int &argc, char **argv, int = QT_VERSION); - QApplication(int &argc, char **argv, bool GUIenabled, int = QT_VERSION); - QApplication(int &argc, char **argv, Type, int = QT_VERSION); + QApplication(int &argc, char **argv, int = ApplicationFlags); + QApplication(int &argc, char **argv, bool GUIenabled, int = ApplicationFlags); + QApplication(int &argc, char **argv, Type, int = ApplicationFlags); #if defined(Q_WS_X11) - QApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0, int = QT_VERSION); - QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0, int = QT_VERSION); + QApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0, int = ApplicationFlags); + QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0, int = ApplicationFlags); #endif #if defined(Q_OS_SYMBIAN) - QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int = QT_VERSION); + QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int = ApplicationFlags); #endif #endif virtual ~QApplication(); diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index dd819e5..c3f3e74 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -1243,6 +1243,8 @@ void qt_init(QApplicationPrivate *priv, int) // Cocoa application delegate #ifdef QT_MAC_USE_COCOA NSApplication *cocoaApp = [QNSApplication sharedApplication]; + qt_redirectNSApplicationSendEvent(); + QMacCocoaAutoReleasePool pool; NSObject *oldDelegate = [cocoaApp delegate]; QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate]; @@ -2608,25 +2610,26 @@ OSStatus QApplicationPrivate::globalAppleEventProcessor(const AppleEvent *ae, Ap /*! \fn bool QApplication::macEventFilter(EventHandlerCallRef caller, EventRef event) - \warning This virtual function is only implemented under Mac OS X when against Carbon. + \warning This virtual function is only used under Mac OS X, and behaves different + depending on if Qt is based on Carbon or Cocoa. - If you create an application that inherits QApplication and reimplement + For the Carbon port, If you create an application that inherits QApplication and reimplement this function, you get direct access to all Carbon Events that Qt registers for from Mac OS X with this function being called with the \a caller and the \a event. + For the Cocoa port, If you create an application that inherits QApplication and reimplement + this function, you get direct access to all Cocoa Events that Qt receives + from Mac OS X with this function being called with the \a caller being 0 and + the \a event being an NSEvent pointer: + + NSEvent *e = reinterpret_cast<NSEvent *>(event); + Return true if you want to stop the event from being processed. Return false for normal event dispatching. The default implementation returns false. - Cocoa uses a different event system which means this function is NOT CALLED - when building Qt against Cocoa. If you want similar functionality subclass - NSApplication and reimplement the sendEvent: message to handle all the - NSEvents. You also will need to to instantiate your custom NSApplication - before creating a QApplication. See \l - {http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/Reference/Reference.html}{Apple's - NSApplication Reference} for more information. - + \sa macEventFilter(void *nsevent) */ bool QApplication::macEventFilter(EventHandlerCallRef, EventRef) { @@ -3107,11 +3110,7 @@ void onApplicationChangedActivation( bool activated ) } if (!app->activeWindow()) { -#if QT_MAC_USE_COCOA - OSWindowRef wp = [NSApp keyWindow]; -#else - OSWindowRef wp = ActiveNonFloatingWindow(); -#endif + OSWindowRef wp = [NSApp keyWindow]; if (QWidget *tmp_w = qt_mac_find_window(wp)) app->setActiveWindow(tmp_w); } diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index aa3a6d5..18ec0df 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -291,7 +291,7 @@ class Q_GUI_EXPORT QApplicationPrivate : public QCoreApplicationPrivate { Q_DECLARE_PUBLIC(QApplication) public: - QApplicationPrivate(int &argc, char **argv, QApplication::Type type); + QApplicationPrivate(int &argc, char **argv, QApplication::Type type, int flags); ~QApplicationPrivate(); #if defined(Q_WS_X11) @@ -491,8 +491,6 @@ public: static QString styleOverride; - static int app_compile_version; - #ifdef QT_KEYPAD_NAVIGATION static QWidget *oldEditFocus; static Qt::NavigationMode navigationMode; diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index e937918..fc4a7cc 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1389,7 +1389,7 @@ bool QSymbianControl::isControlActive() This function is only available on S60. */ QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, 0x040000)) { Q_D(QApplication); S60->s60ApplicationFactory = factory; @@ -1397,7 +1397,7 @@ QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int } QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, _internal)) { Q_D(QApplication); S60->s60ApplicationFactory = factory; diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 78028eb..26f4ea7 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -207,8 +207,6 @@ static void resolveAygLibs() if (!aygResolved) { aygResolved = true; QSystemLibrary ayglib(QLatin1String("aygshell")); - if (!ayglib.load()) - return; ptrRecognizeGesture = (AygRecognizeGesture) ayglib.resolve("SHRecognizeGesture"); } } @@ -944,29 +942,36 @@ bool qt_nograb() // application no-grab option typedef QHash<QString, int> WinClassNameHash; Q_GLOBAL_STATIC(WinClassNameHash, winclassNames) +// +// If 0 is passed as the widget pointer, register a window class +// for QWidget as default. This is used in QGLTemporaryContext +// during GL initialization, where we don't want to use temporary +// QWidgets or QGLWidgets, neither do we want to have separate code +// to register window classes. +// const QString qt_reg_winclass(QWidget *w) // register window class { - int flags = w->windowFlags(); + int flags = w ? w->windowFlags() : 0; int type = flags & Qt::WindowType_Mask; uint style; bool icon; QString cname; - if (qt_widget_private(w)->isGLWidget) { + if (w && qt_widget_private(w)->isGLWidget) { cname = QLatin1String("QGLWidget"); style = CS_DBLCLKS; #ifndef Q_WS_WINCE style |= CS_OWNDC; #endif icon = true; - } else if (flags & Qt::MSWindowsOwnDC) { + } else if (w && (flags & Qt::MSWindowsOwnDC)) { cname = QLatin1String("QWidgetOwnDC"); style = CS_DBLCLKS; #ifndef Q_WS_WINCE style |= CS_OWNDC; #endif icon = true; - } else if (type == Qt::Tool || type == Qt::ToolTip){ + } else if (w && (type == Qt::Tool || type == Qt::ToolTip)) { style = CS_DBLCLKS; if (w->inherits("QTipLabel") || w->inherits("QAlphaWidget")) { if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP @@ -981,7 +986,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class style |= CS_SAVEBITS; #endif icon = false; - } else if (type == Qt::Popup) { + } else if (w && (type == Qt::Popup)) { cname = QLatin1String("QPopup"); style = CS_DBLCLKS; #ifndef Q_WS_WINCE @@ -1052,7 +1057,10 @@ const QString qt_reg_winclass(QWidget *w) // register window class } wc.hCursor = 0; #ifndef Q_WS_WINCE - wc.hbrBackground = qt_widget_private(w)->isGLWidget ? 0 : (HBRUSH)GetSysColorBrush(COLOR_WINDOW); + HBRUSH brush = 0; + if (w && !qt_widget_private(w)->isGLWidget) + brush = (HBRUSH)GetSysColorBrush(COLOR_WINDOW); + wc.hbrBackground = brush; #else wc.hbrBackground = 0; #endif @@ -1074,8 +1082,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class Q_GUI_EXPORT const QString qt_getRegisteredWndClass() { - QWidget w; - return qt_reg_winclass(&w); + return qt_reg_winclass(0); } static void unregWinClasses() @@ -3676,13 +3683,11 @@ static void initWinTabFunctions() return; QSystemLibrary library(QLatin1String("wintab32")); - if (library.load()) { - ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); - ptrWTGet = (PtrWTGet)library.resolve("WTGetW"); - ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable"); - ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap"); - ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet"); - } + ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); + ptrWTGet = (PtrWTGet)library.resolve("WTGetW"); + ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable"); + ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap"); + ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet"); #endif // Q_OS_WINCE } #endif // QT_NO_TABLETEVENT diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index e7b7ed8..b4cebd7 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -484,11 +484,9 @@ static void* qt_load_library_runtime(const char *library, int vernum, Q_FOREACH(int version, versions) { QLatin1String libName(library); QLibrary xfixesLib(libName, version); - if (xfixesLib.load()) { - void *ptr = xfixesLib.resolve(symbol); - if (ptr) - return ptr; - } + void *ptr = xfixesLib.resolve(symbol); + if (ptr) + return ptr; } return 0; } @@ -1740,6 +1738,9 @@ void qt_init(QApplicationPrivate *priv, int, } else { // Qt controls everything (default) + if (QApplication::testAttribute(Qt::AA_X11InitThreads)) + XInitThreads(); + // Set application name and class char *app_class = 0; if (argv && argv[0]) { @@ -2585,22 +2586,20 @@ void qt_init(QApplicationPrivate *priv, int, #if !defined (Q_OS_IRIX) && !defined (QT_NO_TABLET) QLibrary wacom(QString::fromLatin1("wacomcfg"), 0); // version 0 is the latest release at time of writing this. - if (wacom.load()) { - // NOTE: C casts instead of reinterpret_cast for GCC 3.3.x - ptrWacomConfigInit = (PtrWacomConfigInit)wacom.resolve("WacomConfigInit"); - ptrWacomConfigOpenDevice = (PtrWacomConfigOpenDevice)wacom.resolve("WacomConfigOpenDevice"); - ptrWacomConfigGetRawParam = (PtrWacomConfigGetRawParam)wacom.resolve("WacomConfigGetRawParam"); - ptrWacomConfigCloseDevice = (PtrWacomConfigCloseDevice)wacom.resolve("WacomConfigCloseDevice"); - ptrWacomConfigTerm = (PtrWacomConfigTerm)wacom.resolve("WacomConfigTerm"); - - if (ptrWacomConfigInit == 0 || ptrWacomConfigOpenDevice == 0 || ptrWacomConfigGetRawParam == 0 - || ptrWacomConfigCloseDevice == 0 || ptrWacomConfigTerm == 0) { // either we have all, or we have none. + // NOTE: C casts instead of reinterpret_cast for GCC 3.3.x + ptrWacomConfigInit = (PtrWacomConfigInit)wacom.resolve("WacomConfigInit"); + ptrWacomConfigOpenDevice = (PtrWacomConfigOpenDevice)wacom.resolve("WacomConfigOpenDevice"); + ptrWacomConfigGetRawParam = (PtrWacomConfigGetRawParam)wacom.resolve("WacomConfigGetRawParam"); + ptrWacomConfigCloseDevice = (PtrWacomConfigCloseDevice)wacom.resolve("WacomConfigCloseDevice"); + ptrWacomConfigTerm = (PtrWacomConfigTerm)wacom.resolve("WacomConfigTerm"); + + if (ptrWacomConfigInit == 0 || ptrWacomConfigOpenDevice == 0 || ptrWacomConfigGetRawParam == 0 + || ptrWacomConfigCloseDevice == 0 || ptrWacomConfigTerm == 0) { // either we have all, or we have none. ptrWacomConfigInit = 0; ptrWacomConfigOpenDevice = 0; ptrWacomConfigGetRawParam = 0; ptrWacomConfigCloseDevice = 0; ptrWacomConfigTerm = 0; - } } #endif } diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp index f7c0b6e..8c7c333 100644 --- a/src/gui/kernel/qclipboard.cpp +++ b/src/gui/kernel/qclipboard.cpp @@ -631,7 +631,7 @@ QByteArray QMimeDataWrapper::encodedData(const char *format) const return data->data(QLatin1String(format)); } else{ QVariant variant = data->imageData(); - QImage img = qVariantValue<QImage>(variant); + QImage img = qvariant_cast<QImage>(variant); QByteArray ba; QBuffer buffer(&ba); buffer.open(QIODevice::WriteOnly); diff --git a/src/gui/kernel/qcocoaapplication_mac.mm b/src/gui/kernel/qcocoaapplication_mac.mm index 4962863..9270213 100644 --- a/src/gui/kernel/qcocoaapplication_mac.mm +++ b/src/gui/kernel/qcocoaapplication_mac.mm @@ -78,6 +78,7 @@ #include <private/qcocoaapplication_mac_p.h> #include <private/qcocoaapplicationdelegate_mac_p.h> #include <private/qt_cocoa_helpers_mac_p.h> +#include <private/qcocoaintrospection_p.h> QT_USE_NAMESPACE @@ -116,12 +117,30 @@ QT_USE_NAMESPACE quint64 lower = [event data1]; quint64 upper = [event data2]; QCocoaPostMessageArgs *args = reinterpret_cast<QCocoaPostMessageArgs *>(lower | (upper << 32)); - [args->target performSelector:args->selector]; + // Special case for convenience: if the argument is an NSNumber, we unbox it directly. + // Use NSValue instead if this behaviour is unwanted. + id a1 = ([args->arg1 isKindOfClass:[NSNumber class]]) ? (id)[args->arg1 intValue] : args->arg1; + id a2 = ([args->arg2 isKindOfClass:[NSNumber class]]) ? (id)[args->arg2 intValue] : args->arg2; + switch (args->argCount) { + case 0: + [args->target performSelector:args->selector]; + break; + case 1: + [args->target performSelector:args->selector withObject:a1]; + break; + case 3: + [args->target performSelector:args->selector withObject:a1 withObject:a2]; + break; + } + delete args; } -- (BOOL)qt_sendEvent:(NSEvent *)event +- (BOOL)qt_filterEvent:(NSEvent *)event { + if (qApp->macEventFilter(0, reinterpret_cast<EventRef>(event))) + return true; + if ([event type] == NSApplicationDefined) { switch ([event subtype]) { case QtCocoaEventSubTypePostMessage: @@ -138,20 +157,55 @@ QT_USE_NAMESPACE @implementation QNSApplication -// WARNING: If Qt did not create NSApplication (this can e.g. -// happend if Qt is used as a plugin from a 3rd-party cocoa -// application), QNSApplication::sendEvent will never be called. -// SO DO NOT RELY ON THIS FUNCTION BEING AVAILABLE. -// Plugin developers that _do_ control the NSApplication sub-class -// implementation of the 3rd-party application can call qt_sendEvent -// from the sub-class event handler (like we do here) to work around -// any issues. +- (void)qt_sendEvent_original:(NSEvent *)event +{ + Q_UNUSED(event); + // This method will only be used as a signature + // template for the method we add into NSApplication + // containing the original [NSApplication sendEvent:] implementation +} + +- (void)qt_sendEvent_replacement:(NSEvent *)event +{ + // This method (or its implementation to be precise) will + // be called instead of sendEvent if redirection occurs. + // 'self' will then be an instance of NSApplication + // (and not QNSApplication) + if (![NSApp qt_filterEvent:event]) + [self qt_sendEvent_original:event]; +} + - (void)sendEvent:(NSEvent *)event { - if (![self qt_sendEvent:event]) + // This method will be called if + // no redirection occurs + if (![NSApp qt_filterEvent:event]) [super sendEvent:event]; } @end +QT_BEGIN_NAMESPACE + +void qt_redirectNSApplicationSendEvent() +{ + if ([NSApp isMemberOfClass:[QNSApplication class]]) { + // No need to change implementation since Qt + // already controls a subclass of NSApplication + return; + } + + // Change the implementation of [NSApplication sendEvent] to the + // implementation of qt_sendEvent_replacement found in QNSApplication. + // And keep the old implementation that gets overwritten inside a new + // method 'qt_sendEvent_original' that we add to NSApplication + qt_cocoa_change_implementation( + [NSApplication class], + @selector(sendEvent:), + [QNSApplication class], + @selector(qt_sendEvent_replacement:), + @selector(qt_sendEvent_original:)); + } + +QT_END_NAMESPACE #endif diff --git a/src/gui/kernel/qcocoaapplication_mac_p.h b/src/gui/kernel/qcocoaapplication_mac_p.h index 5569feb..c89ff36 100644 --- a/src/gui/kernel/qcocoaapplication_mac_p.h +++ b/src/gui/kernel/qcocoaapplication_mac_p.h @@ -101,11 +101,17 @@ QT_FORWARD_DECLARE_CLASS(QApplicationPrivate) - (int)QT_MANGLE_NAMESPACE(qt_validModesForFontPanel):(NSFontPanel *)fontPanel; - (void)qt_sendPostedMessage:(NSEvent *)event; -- (BOOL)qt_sendEvent:(NSEvent *)event; +- (BOOL)qt_filterEvent:(NSEvent *)event; @end @interface QNSApplication : NSApplication { } @end +QT_BEGIN_NAMESPACE + +void qt_redirectNSApplicationSendEvent(); + +QT_END_NAMESPACE + #endif diff --git a/src/gui/kernel/qcocoaintrospection_mac.mm b/src/gui/kernel/qcocoaintrospection_mac.mm new file mode 100644 index 0000000..9b536b7 --- /dev/null +++ b/src/gui/kernel/qcocoaintrospection_mac.mm @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/**************************************************************************** +** +** Copyright (c) 2007-2008, Apple, Inc. +** +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** +** * Neither the name of Apple, Inc. nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include <private/qcocoaintrospection_p.h> + +QT_BEGIN_NAMESPACE + +void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel, SEL backupSel) +{ +#ifndef QT_MAC_USE_COCOA + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) +#endif + { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + // The following code replaces the _implementation_ for the selector we want to hack + // (originalSel) with the implementation found in proxyClass. Then it creates + // a new 'backup' method inside baseClass containing the old, original, + // implementation (fakeSel). You can let the proxy implementation of originalSel + // call fakeSel if needed (similar approach to calling a super class implementation). + // fakeSel must also be implemented in proxyClass, as the signature is used + // as template for the method one we add into baseClass. + // NB: You will typically never create any instances of proxyClass; we use it + // only for stealing its contents and put it into baseClass. + if (!replacementSel) + replacementSel = originalSel; + + Method originalMethod = class_getInstanceMethod(baseClass, originalSel); + Method replacementMethod = class_getInstanceMethod(proxyClass, replacementSel); + IMP originalImp = method_setImplementation(originalMethod, method_getImplementation(replacementMethod)); + + if (backupSel) { + Method backupMethod = class_getInstanceMethod(proxyClass, backupSel); + class_addMethod(baseClass, backupSel, originalImp, method_getTypeEncoding(backupMethod)); + } +#endif + } +} + +void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL backupSel) +{ +#ifndef QT_MAC_USE_COCOA + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) +#endif + { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + Method originalMethod = class_getInstanceMethod(baseClass, originalSel); + Method backupMethodInBaseClass = class_getInstanceMethod(baseClass, backupSel); + method_setImplementation(originalMethod, method_getImplementation(backupMethodInBaseClass)); +#endif + } +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qcocoaintrospection_p.h b/src/gui/kernel/qcocoaintrospection_p.h new file mode 100644 index 0000000..b9422e8 --- /dev/null +++ b/src/gui/kernel/qcocoaintrospection_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/**************************************************************************** +** +** Copyright (c) 2007-2008, Apple, Inc. +** +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** +** * Neither the name of Apple, Inc. nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include <qglobal.h> +#import <objc/objc-class.h> + +QT_BEGIN_NAMESPACE + +void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel = 0, SEL backupSel = 0); +void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL backupSel); + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index ddf1a27..970bc0a 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -155,17 +155,6 @@ QT_END_NAMESPACE - (void)sendEvent:(NSEvent *)event { - if ([event type] == NSApplicationDefined) { - switch ([event subtype]) { - case QtCocoaEventSubTypePostMessage: - [NSApp qt_sendPostedMessage:event]; - return; - default: - break; - } - return; - } - QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; // Cocoa can hold onto the window after we've disavowed its knowledge. So, // if we get sent an event afterwards just have it go through the super's diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index a552ce7..8576f52 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -207,6 +207,7 @@ static int qCocoaViewCount = 0; composing = false; sendKeyEvents = true; + fromKeyDownEvent = false; [self setHidden:YES]; return self; } @@ -508,7 +509,7 @@ static int qCocoaViewCount = 0; } // Make sure the opengl context is updated on resize. - if (qwidgetprivate && qwidgetprivate->isGLWidget) { + if (qwidgetprivate && qwidgetprivate->isGLWidget && [self window]) { qwidgetprivate->needWindowChange = true; QEvent event(QEvent::MacGLWindowChange); qApp->sendEvent(qwidget, &event); @@ -532,14 +533,29 @@ static int qCocoaViewCount = 0; if (!qwidget) return; + // We use a different graphics system. if (QApplicationPrivate::graphicsSystem() != 0) { - if (qwidgetprivate->maybeBackingStore()) { - // Drawing is handled on the window level - // See qcocoasharedwindowmethods_mac_p.h - if (!qwidget->testAttribute(Qt::WA_PaintOnScreen)) - return; + + // Qt handles the painting occuring inside the window. + // Cocoa also keeps track of all widgets as NSView and therefore might + // ask for a repainting of a widget even if Qt is already taking care of it. + // + // The only valid reason for Cocoa to call drawRect: is for window manipulation + // (ie. resize, ...). + // + // Qt will then forward the update to the children. + if (qwidget->isWindow()) { + qwidget->update(qwidget->rect()); + qwidgetprivate->syncBackingStore(qwidget->rect()); } + + // Since we don't want to use the native engine, we must exit, however + // widgets that are set to paint on screen, spesifically QGLWidget, + // requires the following code to execute in order to be drawn. + if (!qwidget->testAttribute(Qt::WA_PaintOnScreen)) + return; } + CGContextRef cg = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; qwidgetprivate->hd = cg; CGContextSaveGState(cg); @@ -1203,7 +1219,9 @@ static int qCocoaViewCount = 0; && !(widgetToGetKey->inputMethodHints() & Qt::ImhDigitsOnly || widgetToGetKey->inputMethodHints() & Qt::ImhFormattedNumbersOnly || widgetToGetKey->inputMethodHints() & Qt::ImhHiddenText)) { + fromKeyDownEvent = true; [qt_mac_nativeview_for(widgetToGetKey) interpretKeyEvents:[NSArray arrayWithObject: theEvent]]; + fromKeyDownEvent = false; } if (sendKeyEvents && !composing) { bool keyOK = qt_dispatchKeyEvent(theEvent, widgetToGetKey); @@ -1273,7 +1291,10 @@ static int qCocoaViewCount = 0; }; } - if ([aString length] && composing) { + // When entering characters through Character Viewer or Keyboard Viewer, the text is passed + // through this insertText method. Since we dont receive a keyDown Event in such cases, the + // composing flag will be false. + if (([aString length] && composing) || !fromKeyDownEvent) { // Send the commit string to the widget. composing = false; sendKeyEvents = false; diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h index b6b63ca..511423357 100644 --- a/src/gui/kernel/qcocoaview_mac_p.h +++ b/src/gui/kernel/qcocoaview_mac_p.h @@ -86,6 +86,7 @@ Q_GUI_EXPORT bool composing; int composingLength; bool sendKeyEvents; + bool fromKeyDownEvent; QString *composingText; NSInteger dragEnterSequence; } diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h index 2490d20..ed6b254 100644 --- a/src/gui/kernel/qcursor.h +++ b/src/gui/kernel/qcursor.h @@ -96,6 +96,10 @@ public: QCursor(const QCursor &cursor); ~QCursor(); QCursor &operator=(const QCursor &cursor); +#ifdef Q_COMPILER_RVALUE_REFS + inline QCursor &operator=(QCursor &&other) + { qSwap(d, other.d); return *this; } +#endif operator QVariant() const; Qt::CursorShape shape() const; diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp index 1b2dfe7..f65af9c 100644 --- a/src/gui/kernel/qdesktopwidget_win.cpp +++ b/src/gui/kernel/qdesktopwidget_win.cpp @@ -156,10 +156,8 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that) #ifndef Q_OS_WINCE QSystemLibrary user32Lib(QLatin1String("user32")); - if (user32Lib.load()) { - enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors"); - getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW"); - } + enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors"); + getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW"); if (!enumDisplayMonitors || !getMonitorInfo) { screenCount = GetSystemMetrics(80); // SM_CMONITORS @@ -174,11 +172,9 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that) getMonitorInfo = 0; #else QSystemLibrary coreLib(QLatin1String("coredll")); - if (coreLib.load()) { - // CE >= 4.0 case - enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors"); - getMonitorInfo = (InfoFunc)coreLib.resolve("GetMonitorInfo"); - } + // CE >= 4.0 case + enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors"); + getMonitorInfo = (InfoFunc)coreLib.resolve("GetMonitorInfo"); if ((!enumDisplayMonitors || !getMonitorInfo)) { screenCount = GetSystemMetrics(SM_CMONITORS); diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index eade02e..d2b2098 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -4392,7 +4392,7 @@ void QGestureEvent::accept(QGesture *gesture) of calling \l{QGestureEvent::setAccepted()}{setAccepted(gesture, false)}. Clearing the accept flag indicates that the event receiver does not - want the gesture. Unwanted gestures may be propgated to the parent widget. + want the gesture. Unwanted gestures may be propagated to the parent widget. \sa QGestureEvent::accept() */ diff --git a/src/gui/kernel/qguifunctions_wince.cpp b/src/gui/kernel/qguifunctions_wince.cpp index 377dfe3..6e2ed76 100644 --- a/src/gui/kernel/qguifunctions_wince.cpp +++ b/src/gui/kernel/qguifunctions_wince.cpp @@ -129,8 +129,6 @@ static void resolveAygLibs() if (!aygResolved) { aygResolved = true; QLibrary ayglib(QLatin1String("aygshell")); - if (!ayglib.load()) - return; ptrAygInitDialog = (AygInitDialog) ayglib.resolve("SHInitDialog"); ptrAygFullScreen = (AygFullScreen) ayglib.resolve("SHFullScreen"); ptrAygSHSipInfo = (AygSHSipInfo) ayglib.resolve("SHSipInfo"); diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 50b2354..e14a9198 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -76,7 +76,7 @@ static const MacSpecialKey entries[NumEntries] = { { Qt::Key_Backtab, 0x21E4 }, { Qt::Key_Backspace, 0x232B }, { Qt::Key_Return, 0x21B5 }, - { Qt::Key_Enter, 0x21B5 }, + { Qt::Key_Enter, 0x2324 }, { Qt::Key_Delete, 0x2326 }, { Qt::Key_Home, 0x2196 }, { Qt::Key_End, 0x2198 }, @@ -240,7 +240,7 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni \row \i Paste \i Ctrl+V, Shift+Ins \i Ctrl+V \i Ctrl+V, F18, Shift+Ins \i Ctrl+V, F18, Shift+Ins \i Ctrl+V \row \i Preferences \i \i Ctrl+, \i \i \i (none) \row \i Undo \i Ctrl+Z, Alt+Backspace \i Ctrl+Z \i Ctrl+Z, F14 \i Ctrl+Z, F14 \i Ctrl+Z - \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z, Ctrl+Y \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i (none) + \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i (none) \row \i Back \i Alt+Left, Backspace \i Ctrl+[ \i Alt+Left \i Alt+Left \i (none) \row \i Forward \i Alt+Right, Shift+Backspace \i Ctrl+] \i Alt+Right \i Alt+Right \i (none) \row \i Refresh \i F5 \i F5 \i F5 \i Ctrl+R, F5 \i (none) @@ -718,7 +718,6 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::Close, 1, Qt::CTRL | Qt::Key_W, QApplicationPrivate::KB_Mac}, {QKeySequence::Cut, 1, Qt::CTRL | Qt::Key_X, QApplicationPrivate::KB_All}, {QKeySequence::Redo, 1, Qt::CTRL | Qt::Key_Y, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_S60}, - {QKeySequence::Redo, 0, Qt::CTRL | Qt::Key_Y, QApplicationPrivate::KB_Mac},//different priority from above {QKeySequence::Undo, 1, Qt::CTRL | Qt::Key_Z, QApplicationPrivate::KB_All}, {QKeySequence::Back, 1, Qt::CTRL | Qt::Key_BracketLeft, QApplicationPrivate::KB_Mac}, {QKeySequence::Forward, 1, Qt::CTRL | Qt::Key_BracketRight, QApplicationPrivate::KB_Mac}, @@ -747,7 +746,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::AddTab, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_N, QApplicationPrivate::KB_KDE}, {QKeySequence::SaveAs, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_S, QApplicationPrivate::KB_Gnome | QApplicationPrivate::KB_Mac}, {QKeySequence::Redo, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, - {QKeySequence::Redo, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Mac}, //different priority from above + {QKeySequence::Redo, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Mac}, {QKeySequence::PreviousChild, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, {QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Mac },//different priority from above {QKeySequence::Paste, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Insert, QApplicationPrivate::KB_X11}, diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h index 5a973e3..b47873d 100644 --- a/src/gui/kernel/qkeysequence.h +++ b/src/gui/kernel/qkeysequence.h @@ -179,6 +179,10 @@ public: operator int() const; int operator[](uint i) const; QKeySequence &operator=(const QKeySequence &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QKeySequence &operator=(QKeySequence &&other) + { qSwap(d, other.d); return *this; } +#endif bool operator==(const QKeySequence &other) const; inline bool operator!= (const QKeySequence &other) const { return !(*this == other); } diff --git a/src/gui/kernel/qlayoutitem.cpp b/src/gui/kernel/qlayoutitem.cpp index 6a91d95..d1a82c2 100644 --- a/src/gui/kernel/qlayoutitem.cpp +++ b/src/gui/kernel/qlayoutitem.cpp @@ -516,9 +516,7 @@ bool QWidgetItem::hasHeightForWidth() const { if (isEmpty()) return false; - if (wid->layout()) - return wid->layout()->hasHeightForWidth(); - return wid->sizePolicy().hasHeightForWidth(); + return wid->d_func()->hasHeightForWidth(); } /*! diff --git a/src/gui/kernel/qmacdefines_mac.h b/src/gui/kernel/qmacdefines_mac.h index d767470..d190d23 100644 --- a/src/gui/kernel/qmacdefines_mac.h +++ b/src/gui/kernel/qmacdefines_mac.h @@ -94,12 +94,6 @@ Yes, it is an informative comment ;-) #include <QtCore/qglobal.h> -#undef OLD_DEBUG -#ifdef DEBUG -# define OLD_DEBUG DEBUG -# undef DEBUG -#endif -#define DEBUG 0 #ifdef qDebug # define old_qDebug qDebug # undef qDebug @@ -179,12 +173,6 @@ typedef AERecord AppleEvent; #undef check #endif -#undef DEBUG -#ifdef OLD_DEBUG -# define DEBUG OLD_DEBUG -# undef OLD_DEBUG -#endif - #ifdef old_qDebug # undef qDebug # define qDebug QT_NO_QDEBUG_MACRO diff --git a/src/gui/kernel/qpalette.h b/src/gui/kernel/qpalette.h index f797f86..7b7b41d 100644 --- a/src/gui/kernel/qpalette.h +++ b/src/gui/kernel/qpalette.h @@ -78,6 +78,14 @@ public: QPalette(const QPalette &palette); ~QPalette(); QPalette &operator=(const QPalette &palette); +#ifdef Q_COMPILER_RVALUE_REFS + inline QPalette &operator=(QPalette &&other) + { + resolve_mask = other.resolve_mask; + current_group = other.current_group; + qSwap(d, other.d); return *this; + } +#endif operator QVariant() const; // Do not change the order, the serialization format depends on it diff --git a/src/gui/kernel/qsizepolicy.h b/src/gui/kernel/qsizepolicy.h index ff7b9ee..26cc1e1 100644 --- a/src/gui/kernel/qsizepolicy.h +++ b/src/gui/kernel/qsizepolicy.h @@ -62,12 +62,12 @@ private: HSize = 4, HMask = 0x0f, VMask = HMask << HSize, - CTShift = 9, - CTSize = 5, - WFHShift = CTShift + CTSize, - CTMask = ((0x1 << CTSize) - 1) << CTShift, - UnusedShift = CTShift + CTSize, - UnusedSize = 2 + CTShift = 9, + CTSize = 5, + CTMask = ((0x1 << CTSize) - 1) << CTShift, + WFHShift = CTShift + CTSize, + UnusedShift = WFHShift + 1, + UnusedSize = 1 }; public: @@ -134,6 +134,8 @@ public: void setHeightForWidth(bool b) { data = b ? (data | (1 << 2*HSize)) : (data & ~(1 << 2*HSize)); } bool hasHeightForWidth() const { return data & (1 << 2*HSize); } + void setWidthForHeight(bool b) { data = b ? (data | (1 << (WFHShift))) : (data & ~(1 << (WFHShift))); } + bool hasWidthForHeight() const { return data & (1 << (WFHShift)); } bool operator==(const QSizePolicy& s) const { return data == s.data; } bool operator!=(const QSizePolicy& s) const { return data != s.data; } @@ -200,15 +202,18 @@ private: QSizePolicy(int i) : data(i) { } quint32 data; -/* use bit flags instead, keep it here for improved readability for now +/* Qt5: Use bit flags instead, keep it here for improved readability for now. + We can maybe change it for Qt4, but we'd have to be careful, since the behaviour + is implementation defined. It usually varies between little- and big-endian compilers, but + it might also not vary. quint32 horzPolicy : 4; quint32 vertPolicy : 4; quint32 hfw : 1; quint32 ctype : 5; quint32 wfh : 1; quint32 padding : 1; // we cannot use the highest bit - quint32 horStretch : 8; quint32 verStretch : 8; + quint32 horStretch : 8; */ }; diff --git a/src/gui/kernel/qsizepolicy.qdoc b/src/gui/kernel/qsizepolicy.qdoc index 7cd05c5..f6a350c 100644 --- a/src/gui/kernel/qsizepolicy.qdoc +++ b/src/gui/kernel/qsizepolicy.qdoc @@ -249,7 +249,7 @@ Sets the flag determining whether the widget's preferred height depends on its width, to \a dependent. - \sa hasHeightForWidth() + \sa hasHeightForWidth(), setWidthForHeight() */ /*! @@ -262,6 +262,28 @@ */ /*! + \fn void QSizePolicy::setWidthForHeight(bool dependent) + + Sets the flag determining whether the widget's width + depends on its height, to \a dependent. + + This is only supported for QGraphicsLayout's subclasses. + It is not possible to have a layout with both height-for-width + and width-for-height constraints at the same time. + + \sa hasWidthForHeight(), setHeightForWidth() +*/ + +/*! + \fn bool QSizePolicy::hasWidthForHeight() const + + Returns true if the widget's width depends on its + height; otherwise returns false. + + \sa setWidthForHeight() +*/ + +/*! \fn bool QSizePolicy::operator==(const QSizePolicy &other) const Returns true if this policy is equal to \a other; otherwise diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 7d23abf..88ff1e6 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -469,7 +469,6 @@ void qt_dispatchTabletProximityEvent(const ::TabletProximityRec &proxRec) qt_sendSpontaneousEvent(qApp, &qtabletProximity); } -#ifdef QT_MAC_USE_COCOA // Use this method to keep all the information in the TextSegment. As long as it is ordered // we are in OK shape, and we can influence that ourselves. struct KeyPair @@ -493,69 +492,107 @@ bool operator<(QChar qchar, const KeyPair &entry) return qchar < entry.cocoaKey; } +bool operator<(const Qt::Key &key, const KeyPair &entry) +{ + return key < entry.qtKey; +} + +bool operator<(const KeyPair &entry, const Qt::Key &key) +{ + return entry.qtKey < key; +} + +static bool qtKey2CocoaKeySortLessThan(const KeyPair &entry1, const KeyPair &entry2) +{ + return entry1.qtKey < entry2.qtKey; +} + +static const int NumEntries = 59; +static const KeyPair entries[NumEntries] = { + { NSEnterCharacter, Qt::Key_Enter }, + { NSBackspaceCharacter, Qt::Key_Backspace }, + { NSTabCharacter, Qt::Key_Tab }, + { NSNewlineCharacter, Qt::Key_Return }, + { NSCarriageReturnCharacter, Qt::Key_Return }, + { NSBackTabCharacter, Qt::Key_Backtab }, + { NSDeleteCharacter, Qt::Key_Delete }, + { kEscapeCharCode, Qt::Key_Escape }, + { NSUpArrowFunctionKey, Qt::Key_Up }, + { NSDownArrowFunctionKey, Qt::Key_Down }, + { NSLeftArrowFunctionKey, Qt::Key_Left }, + { NSRightArrowFunctionKey, Qt::Key_Right }, + { NSF1FunctionKey, Qt::Key_F1 }, + { NSF2FunctionKey, Qt::Key_F2 }, + { NSF3FunctionKey, Qt::Key_F3 }, + { NSF4FunctionKey, Qt::Key_F4 }, + { NSF5FunctionKey, Qt::Key_F5 }, + { NSF6FunctionKey, Qt::Key_F6 }, + { NSF7FunctionKey, Qt::Key_F7 }, + { NSF8FunctionKey, Qt::Key_F8 }, + { NSF9FunctionKey, Qt::Key_F8 }, + { NSF10FunctionKey, Qt::Key_F10 }, + { NSF11FunctionKey, Qt::Key_F11 }, + { NSF12FunctionKey, Qt::Key_F12 }, + { NSF13FunctionKey, Qt::Key_F13 }, + { NSF14FunctionKey, Qt::Key_F14 }, + { NSF15FunctionKey, Qt::Key_F15 }, + { NSF16FunctionKey, Qt::Key_F16 }, + { NSF17FunctionKey, Qt::Key_F17 }, + { NSF18FunctionKey, Qt::Key_F18 }, + { NSF19FunctionKey, Qt::Key_F19 }, + { NSF20FunctionKey, Qt::Key_F20 }, + { NSF21FunctionKey, Qt::Key_F21 }, + { NSF22FunctionKey, Qt::Key_F22 }, + { NSF23FunctionKey, Qt::Key_F23 }, + { NSF24FunctionKey, Qt::Key_F24 }, + { NSF25FunctionKey, Qt::Key_F25 }, + { NSF26FunctionKey, Qt::Key_F26 }, + { NSF27FunctionKey, Qt::Key_F27 }, + { NSF28FunctionKey, Qt::Key_F28 }, + { NSF29FunctionKey, Qt::Key_F29 }, + { NSF30FunctionKey, Qt::Key_F30 }, + { NSF31FunctionKey, Qt::Key_F31 }, + { NSF32FunctionKey, Qt::Key_F32 }, + { NSF33FunctionKey, Qt::Key_F33 }, + { NSF34FunctionKey, Qt::Key_F34 }, + { NSF35FunctionKey, Qt::Key_F35 }, + { NSInsertFunctionKey, Qt::Key_Insert }, + { NSDeleteFunctionKey, Qt::Key_Delete }, + { NSHomeFunctionKey, Qt::Key_Home }, + { NSEndFunctionKey, Qt::Key_End }, + { NSPageUpFunctionKey, Qt::Key_PageUp }, + { NSPageDownFunctionKey, Qt::Key_PageDown }, + { NSPrintScreenFunctionKey, Qt::Key_Print }, + { NSScrollLockFunctionKey, Qt::Key_ScrollLock }, + { NSPauseFunctionKey, Qt::Key_Pause }, + { NSSysReqFunctionKey, Qt::Key_SysReq }, + { NSMenuFunctionKey, Qt::Key_Menu }, + { NSHelpFunctionKey, Qt::Key_Help }, +}; +static const KeyPair * const end = entries + NumEntries; + +QChar qtKey2CocoaKey(Qt::Key key) +{ + // The first time this function is called, create a reverse + // looup table sorted on Qt Key rather than Cocoa key: + static QVector<KeyPair> rev_entries(NumEntries); + static bool mustInit = true; + if (mustInit){ + mustInit = false; + for (int i=0; i<NumEntries; ++i) + rev_entries[i] = entries[i]; + qSort(rev_entries.begin(), rev_entries.end(), qtKey2CocoaKeySortLessThan); + } + const QVector<KeyPair>::iterator i + = qBinaryFind(rev_entries.begin(), rev_entries.end(), key); + if (i == rev_entries.end()) + return QChar(); + return i->cocoaKey; +} + +#ifdef QT_MAC_USE_COCOA static Qt::Key cocoaKey2QtKey(QChar keyCode) { - static const int NumEntries = 57; - static const KeyPair entries[NumEntries] = { - { NSEnterCharacter, Qt::Key_Enter }, - { NSTabCharacter, Qt::Key_Tab }, - { NSCarriageReturnCharacter, Qt::Key_Return }, - { NSBackTabCharacter, Qt::Key_Backtab }, - { kEscapeCharCode, Qt::Key_Escape }, - { NSDeleteCharacter, Qt::Key_Backspace }, - { NSUpArrowFunctionKey, Qt::Key_Up }, - { NSDownArrowFunctionKey, Qt::Key_Down }, - { NSLeftArrowFunctionKey, Qt::Key_Left }, - { NSRightArrowFunctionKey, Qt::Key_Right }, - { NSF1FunctionKey, Qt::Key_F1 }, - { NSF2FunctionKey, Qt::Key_F2 }, - { NSF3FunctionKey, Qt::Key_F3 }, - { NSF4FunctionKey, Qt::Key_F4 }, - { NSF5FunctionKey, Qt::Key_F5 }, - { NSF6FunctionKey, Qt::Key_F6 }, - { NSF7FunctionKey, Qt::Key_F7 }, - { NSF8FunctionKey, Qt::Key_F8 }, - { NSF9FunctionKey, Qt::Key_F8 }, - { NSF10FunctionKey, Qt::Key_F10 }, - { NSF11FunctionKey, Qt::Key_F11 }, - { NSF12FunctionKey, Qt::Key_F12 }, - { NSF13FunctionKey, Qt::Key_F13 }, - { NSF14FunctionKey, Qt::Key_F14 }, - { NSF15FunctionKey, Qt::Key_F15 }, - { NSF16FunctionKey, Qt::Key_F16 }, - { NSF17FunctionKey, Qt::Key_F17 }, - { NSF18FunctionKey, Qt::Key_F18 }, - { NSF19FunctionKey, Qt::Key_F19 }, - { NSF20FunctionKey, Qt::Key_F20 }, - { NSF21FunctionKey, Qt::Key_F21 }, - { NSF22FunctionKey, Qt::Key_F22 }, - { NSF23FunctionKey, Qt::Key_F23 }, - { NSF24FunctionKey, Qt::Key_F24 }, - { NSF25FunctionKey, Qt::Key_F25 }, - { NSF26FunctionKey, Qt::Key_F26 }, - { NSF27FunctionKey, Qt::Key_F27 }, - { NSF28FunctionKey, Qt::Key_F28 }, - { NSF29FunctionKey, Qt::Key_F29 }, - { NSF30FunctionKey, Qt::Key_F30 }, - { NSF31FunctionKey, Qt::Key_F31 }, - { NSF32FunctionKey, Qt::Key_F32 }, - { NSF33FunctionKey, Qt::Key_F33 }, - { NSF34FunctionKey, Qt::Key_F34 }, - { NSF35FunctionKey, Qt::Key_F35 }, - { NSInsertFunctionKey, Qt::Key_Insert }, - { NSDeleteFunctionKey, Qt::Key_Delete }, - { NSHomeFunctionKey, Qt::Key_Home }, - { NSEndFunctionKey, Qt::Key_End }, - { NSPageUpFunctionKey, Qt::Key_PageUp }, - { NSPageDownFunctionKey, Qt::Key_PageDown }, - { NSPrintScreenFunctionKey, Qt::Key_Print }, - { NSScrollLockFunctionKey, Qt::Key_ScrollLock }, - { NSPauseFunctionKey, Qt::Key_Pause }, - { NSSysReqFunctionKey, Qt::Key_SysReq }, - { NSMenuFunctionKey, Qt::Key_Menu }, - { NSHelpFunctionKey, Qt::Key_Help }, - }; - static const KeyPair * const end = entries + NumEntries; const KeyPair *i = qBinaryFind(entries, end, keyCode); if (i == end) return Qt::Key(keyCode.unicode()); @@ -1204,7 +1241,7 @@ void qt_mac_replaceDrawRect(void * /*OSWindowRef */window, QWidgetPrivate *widge // We have the original method here. Proceed and swap the methods. method_exchangeImplementations(m1, m0); widget->originalDrawMethod = false; - [window display]; + [theWindow display]; } } @@ -1227,7 +1264,7 @@ void qt_mac_replaceDrawRectOriginal(void * /*OSWindowRef */window, QWidgetPrivat } method_exchangeImplementations(m1, m0); widget->originalDrawMethod = true; - [window display]; + [theWindow display]; } #endif // QT_MAC_USE_COCOA @@ -1297,7 +1334,7 @@ CGContextRef qt_mac_graphicsContextFor(QWidget *widget) CGrafPtr port = GetWindowPort(qt_mac_window_for(widget)); QDBeginCGContext(port, &context); #else - CGContextRef context = reinterpret_cast<CGContextRef>([[qt_mac_window_for(widget) graphicsContext] graphicsPort]); + CGContextRef context = (CGContextRef)[[NSGraphicsContext graphicsContextWithWindow:qt_mac_window_for(widget)] graphicsPort]; #endif return context; } @@ -1426,39 +1463,17 @@ void qt_cocoaChangeOverrideCursor(const QCursor &cursor) [static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursor)) set]; } -// WARNING: If Qt did not create NSApplication (e.g. in case it is -// used as a plugin), and at the same time, there is no window on -// screen (or the window that the event is sendt to becomes hidden etc -// before the event gets delivered), the message will not be performed. -bool qt_cocoaPostMessage(id target, SEL selector) +void qt_cocoaPostMessage(id target, SEL selector, int argCount, id arg1, id arg2) { - if (!target) - return false; - - NSInteger windowNumber = 0; - if (![NSApp isMemberOfClass:[QNSApplication class]]) { - // INVARIANT: Cocoa is not using our NSApplication subclass. That means - // we don't control the main event handler either. So target the event - // for one of the windows on screen: - NSWindow *nswin = [NSApp mainWindow]; - if (!nswin) { - nswin = [NSApp keyWindow]; - if (!nswin) - return false; - } - windowNumber = [nswin windowNumber]; - } - - // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5! + // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5! // That is why we need to split the address in two parts: - QCocoaPostMessageArgs *args = new QCocoaPostMessageArgs(target, selector); + QCocoaPostMessageArgs *args = new QCocoaPostMessageArgs(target, selector, argCount, arg1, arg2); quint32 lower = quintptr(args); quint32 upper = quintptr(args) >> 32; NSEvent *e = [NSEvent otherEventWithType:NSApplicationDefined - location:NSZeroPoint modifierFlags:0 timestamp:0 windowNumber:windowNumber + location:NSZeroPoint modifierFlags:0 timestamp:0 windowNumber:0 context:nil subtype:QtCocoaEventSubTypePostMessage data1:lower data2:upper]; [NSApp postEvent:e atStart:NO]; - return true; } #endif @@ -1497,7 +1512,7 @@ void macDrawRectOnTop(void * /*OSWindowRef */window) NSRect contentRect = [contentView frame]; // Draw a line on top of the already drawn line. // We need to check if we are active or not to use the proper color. - if([window isKeyWindow] || [window isMainWindow]) { + if([theWindow isKeyWindow] || [theWindow isMainWindow]) { [[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0] set]; } else { [[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0] set]; @@ -1517,7 +1532,7 @@ void macSyncDrawingOnFirstInvocation(void * /*OSWindowRef */window) { OSWindowRef theWindow = static_cast<OSWindowRef>(window); NSApplication *application = [NSApplication sharedApplication]; - NSToolbar *toolbar = [window toolbar]; + NSToolbar *toolbar = [theWindow toolbar]; if([application isActive]) { // Launched from finder [toolbar setShowsBaselineSeparator:NO]; diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index c6c2db2..5c23392 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -202,17 +202,25 @@ class QCocoaPostMessageArgs { public: id target; SEL selector; - QCocoaPostMessageArgs(id target, SEL selector) : target(target), selector(selector) + int argCount; + id arg1; + id arg2; + QCocoaPostMessageArgs(id target, SEL selector, int argCount=0, id arg1=0, id arg2=0) + : target(target), selector(selector), argCount(argCount), arg1(arg1), arg2(arg2) { [target retain]; + [arg1 retain]; + [arg2 retain]; } ~QCocoaPostMessageArgs() { + [arg2 release]; + [arg1 release]; [target release]; } }; -bool qt_cocoaPostMessage(id target, SEL selector); +void qt_cocoaPostMessage(id target, SEL selector, int argCount=0, id arg1=0, id arg2=0); #endif #endif diff --git a/src/gui/kernel/qtooltip.cpp b/src/gui/kernel/qtooltip.cpp index c8fcf45..88fdbc6 100644 --- a/src/gui/kernel/qtooltip.cpp +++ b/src/gui/kernel/qtooltip.cpp @@ -353,7 +353,7 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w) #ifndef QT_NO_STYLE_STYLESHEET if (testAttribute(Qt::WA_StyleSheet) || (w && qobject_cast<QStyleSheetStyle *>(w->style()))) { //the stylesheet need to know the real parent - QTipLabel::instance->setProperty("_q_stylesheet_parent", qVariantFromValue(w)); + QTipLabel::instance->setProperty("_q_stylesheet_parent", QVariant::fromValue(w)); //we force the style to be the QStyleSheetStyle, and force to clear the cache as well. QTipLabel::instance->setStyleSheet(QLatin1String("/* */")); diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index dc0dbf4..cffad1d 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -1580,7 +1580,8 @@ QWidget::~QWidget() d->needsFlush = 0; // set all QPointers for this object to zero - QObjectPrivate::clearGuards(this); + if (d->hasGuards) + QObjectPrivate::clearGuards(this); if (d->declarativeData) { QAbstractDeclarativeData::destroyed(d->declarativeData, this); @@ -1808,13 +1809,7 @@ void QWidgetPrivate::syncBackingStore() repaint_sys(dirty); dirty = QRegion(); } else if (QWidgetBackingStore *bs = maybeBackingStore()) { -#ifdef QT_MAC_USE_COCOA - Q_UNUSED(bs); - void qt_mac_set_needs_display(QWidget *, QRegion); - qt_mac_set_needs_display(q_func(), QRegion()); -#else bs->sync(); -#endif } } @@ -1823,13 +1818,7 @@ void QWidgetPrivate::syncBackingStore(const QRegion ®ion) if (paintOnScreen()) repaint_sys(region); else if (QWidgetBackingStore *bs = maybeBackingStore()) { -#ifdef QT_MAC_USE_COCOA - Q_UNUSED(bs); - void qt_mac_set_needs_display(QWidget *, QRegion); - qt_mac_set_needs_display(q_func(), region); -#else bs->sync(q_func(), region); -#endif } } @@ -6578,7 +6567,7 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second) // that can take keyboard focus so that second is inserted after // that last child, and the focus order within first is (more // likely to be) preserved. - QList<QWidget *> l = qFindChildren<QWidget *>(first); + QList<QWidget *> l = first->findChildren<QWidget *>(); for (int i = l.size()-1; i >= 0; --i) { QWidget * next = l.at(i); if (next->window() == fp->window()) { @@ -9738,6 +9727,23 @@ int QWidget::heightForWidth(int w) const return -1; } + +/*! + \internal + + *virtual private* + + This is a bit hackish, but ideally we would have created a virtual function + in the public API (however, too late...) so that subclasses could reimplement + their own function. + Instead we add a virtual function to QWidgetPrivate. + ### Qt5: move to public class and make virtual +*/ +bool QWidgetPrivate::hasHeightForWidth() const +{ + return layout ? layout->hasHeightForWidth() : size_policy.hasHeightForWidth(); +} + /*! \fn QWidget *QWidget::childAt(int x, int y) const diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 941bd68..980f40f 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -898,13 +898,6 @@ protected: Q_DECLARE_OPERATORS_FOR_FLAGS(QWidget::RenderFlags) -#if defined Q_CC_MSVC && _MSC_VER < 1300 -template <> inline QWidget *qobject_cast_helper<QWidget*>(QObject *o, QWidget *) -{ - if (!o || !o->isWidgetType()) return 0; - return (QWidget*)(o); -} -#else template <> inline QWidget *qobject_cast<QWidget*>(QObject *o) { if (!o || !o->isWidgetType()) return 0; @@ -915,7 +908,6 @@ template <> inline const QWidget *qobject_cast<const QWidget*>(const QObject *o) if (!o || !o->isWidgetType()) return 0; return static_cast<const QWidget*>(o); } -#endif inline QWidget *QWidget::childAt(int ax, int ay) const { return childAt(QPoint(ax, ay)); } diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 1e2aa9f..5e41efa 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -226,6 +226,8 @@ static NSDrawer *qt_mac_drawer_for(const QWidget *widget) for (NSWindow *window in windows) { NSArray *drawers = [window drawers]; for (NSDrawer *drawer in drawers) { + if ([drawer contentView] == widgetView) + return drawer; NSArray *views = [[drawer contentView] subviews]; for (NSView *view in views) { if (view == widgetView) @@ -240,6 +242,9 @@ static NSDrawer *qt_mac_drawer_for(const QWidget *widget) static void qt_mac_destructView(OSViewRef view) { #ifdef QT_MAC_USE_COCOA + NSWindow *window = [view window]; + if ([window contentView] == view) + [window setContentView:[[NSView alloc] initWithFrame:[view bounds]]]; [view removeFromSuperview]; [view release]; #else @@ -2294,28 +2299,23 @@ void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWin Q_UNUSED(dialog); data.fstrut_dirty = true; // when we create a toplevel widget, the frame strut should be dirty + OSViewRef nsview = (OSViewRef)data.winid; - OSViewRef window_contentview = qt_mac_get_contentview_for(windowRef); if (!nsview) { - nsview = qt_mac_create_widget(q, this, window_contentview); + nsview = qt_mac_create_widget(q, this, 0); setWinId(WId(nsview)); - } else { - [window_contentview addSubview:nsview]; - } - if (nsview) { - NSRect bounds = [window_contentview bounds]; - [nsview setFrame:bounds]; - [nsview setHidden:NO]; - if (q->testAttribute(Qt::WA_DropSiteRegistered)) - registerDropSite(true); - transferChildren(); - - // Tell Cocoa explicit that we wan't the view to receive key events - // (regardless of focus policy) because this is how it works on other - // platforms (and in the carbon port): - if (!qApp->focusWidget()) - [windowRef makeFirstResponder:nsview]; } + [windowRef setContentView:nsview]; + [nsview setHidden:NO]; + if (q->testAttribute(Qt::WA_DropSiteRegistered)) + registerDropSite(true); + transferChildren(); + + // Tell Cocoa explicit that we wan't the view to receive key events + // (regardless of focus policy) because this is how it works on other + // platforms (and in the carbon port): + if (!qApp->focusWidget()) + [windowRef makeFirstResponder:nsview]; if (topExtra->posFromMove) { updateFrameStrut(); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 4a79dc7..c943bd8 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -542,6 +542,7 @@ public: bool setMinimumSize_helper(int &minw, int &minh); bool setMaximumSize_helper(int &maxw, int &maxh); + virtual bool hasHeightForWidth() const; void setConstraints_sys(); bool pointInsideRectAndMask(const QPoint &) const; QWidget *childAt_helper(const QPoint &, bool) const; diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 4109ed8..91e74b5 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -360,7 +360,9 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de if (!q->testAttribute(Qt::WA_Moved) && !q->testAttribute(Qt::WA_DontShowOnScreen)) data.crect.moveTopLeft(QPoint(clientRect.iTl.iX, clientRect.iTl.iY)); - QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) ); + QScopedPointer<QSymbianControl> control( new QSymbianControl(q) ); + Q_CHECK_PTR(control); + QT_TRAP_THROWING(control->ConstructL(true, desktop)); control->SetMopParent(static_cast<CEikAppUi*>(S60->appUi())); @@ -405,7 +407,9 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create native child widget - QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) ); + QScopedPointer<QSymbianControl> control( new QSymbianControl(q) ); + Q_CHECK_PTR(control); + QT_TRAP_THROWING(control->ConstructL(!parentWidget)); // Symbian windows are always created in an inactive state diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 3d206fd..39ed750 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -1635,8 +1635,6 @@ void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) } } -extern Q_GUI_EXPORT HDC qt_win_display_dc(); - int QWidget::metric(PaintDeviceMetric m) const { Q_D(const QWidget); @@ -1646,7 +1644,7 @@ int QWidget::metric(PaintDeviceMetric m) const } else if (m == PdmHeight) { val = data->crect.height(); } else { - HDC gdc = qt_win_display_dc(); + HDC gdc = GetDC(0); switch (m) { case PdmDpiX: case PdmPhysicalDpiX: @@ -1697,6 +1695,7 @@ int QWidget::metric(PaintDeviceMetric m) const val = 0; qWarning("QWidget::metric: Invalid metric command"); } + ReleaseDC(0, gdc); } return val; } diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp index 16c7f97..2f03bd0 100644 --- a/src/gui/math3d/qmatrix4x4.cpp +++ b/src/gui/math3d/qmatrix4x4.cpp @@ -102,8 +102,6 @@ QMatrix4x4::QMatrix4x4(const qreal *values) \sa optimize() */ -#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC) - /*! \fn QMatrix4x4::QMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix) @@ -112,7 +110,7 @@ QMatrix4x4::QMatrix4x4(const qreal *values) the remaining elements are filled with elements from the identity matrix. - \sa toGenericMatrix(), qGenericMatrixToMatrix4x4() + \sa toGenericMatrix() */ /*! @@ -122,34 +120,32 @@ QMatrix4x4::QMatrix4x4(const qreal *values) top-most M rows of this 4x4 matrix. If N or M is greater than 4, then the remaining elements are filled with elements from the identity matrix. - - \sa qGenericMatrixFromMatrix4x4() */ -#endif - /*! \fn QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix) \relates QMatrix4x4 + \obsolete Returns a 4x4 matrix constructed from the left-most 4 columns and top-most 4 rows of \a matrix. If \a matrix has less than 4 columns or rows, the remaining elements are filled with elements from the identity matrix. - \sa qGenericMatrixFromMatrix4x4() + \sa QMatrix4x4(const QGenericMatrix &) */ /*! \fn QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix) \relates QMatrix4x4 + \obsolete Returns a NxM generic matrix constructed from the left-most N columns and top-most M rows of \a matrix. If N or M is greater than 4, then the remaining elements are filled with elements from the identity matrix. - \sa qGenericMatrixToMatrix4x4(), QMatrix4x4::toGenericMatrix() + \sa QMatrix4x4::toGenericMatrix() */ /*! diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h index 0671fa8..598058c 100644 --- a/src/gui/math3d/qmatrix4x4.h +++ b/src/gui/math3d/qmatrix4x4.h @@ -69,10 +69,10 @@ public: qreal m21, qreal m22, qreal m23, qreal m24, qreal m31, qreal m32, qreal m33, qreal m34, qreal m41, qreal m42, qreal m43, qreal m44); -#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC) + template <int N, int M> explicit QMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix); -#endif + QMatrix4x4(const qreal *values, int cols, int rows); QMatrix4x4(const QTransform& transform); QMatrix4x4(const QMatrix& matrix); @@ -169,10 +169,8 @@ public: QRect mapRect(const QRect& rect) const; QRectF mapRect(const QRectF& rect) const; -#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC) template <int N, int M> QGenericMatrix<N, M, qreal> toGenericMatrix() const; -#endif inline qreal *data(); inline const qreal *data() const { return m[0]; } @@ -223,8 +221,6 @@ inline QMatrix4x4::QMatrix4x4 flagBits = General; } -#if !defined(QT_NO_MEMBER_TEMPLATES) - template <int N, int M> Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4 (const QGenericMatrix<N, M, qreal>& matrix) @@ -261,8 +257,6 @@ QGenericMatrix<N, M, qreal> QMatrix4x4::toGenericMatrix() const return result; } -#endif - inline const qreal& QMatrix4x4::operator()(int aRow, int aColumn) const { Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4); @@ -992,14 +986,15 @@ Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix4x4 &); Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix4x4 &); #endif +#ifdef QT_DEPRECATED template <int N, int M> -QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix) +QT_DEPRECATED QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix) { return QMatrix4x4(matrix.constData(), N, M); } template <int N, int M> -QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix) +QT_DEPRECATED QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix) { QGenericMatrix<N, M, qreal> result; const qreal *m = matrix.constData(); @@ -1016,6 +1011,7 @@ QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix } return result; } +#endif #endif diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h index b657301..efc720b 100644 --- a/src/gui/painting/qbrush.h +++ b/src/gui/painting/qbrush.h @@ -92,6 +92,10 @@ public: ~QBrush(); QBrush &operator=(const QBrush &brush); +#ifdef Q_COMPILER_RVALUE_REFS + inline QBrush &operator=(QBrush &&other) + { qSwap(d, other.d); return *this; } +#endif operator QVariant() const; inline Qt::BrushStyle style() const; diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp index bf03545..72e5833 100644 --- a/src/gui/painting/qoutlinemapper.cpp +++ b/src/gui/painting/qoutlinemapper.cpp @@ -47,8 +47,6 @@ QT_BEGIN_NAMESPACE -static const qreal aliasedCoordinateDelta = 0.5 - 0.015625; - #define qreal_to_fixed_26_6(f) (int(f * 64)) @@ -216,13 +214,6 @@ void QOutlineMapper::endOutline() elements = m_elements_dev.data(); } - if (m_round_coords) { - // round coordinates to match outlines drawn with drawLine_midpoint_i - for (int i = 0; i < m_elements.size(); ++i) - elements[i] = QPointF(qFloor(elements[i].x() + aliasedCoordinateDelta), - qFloor(elements[i].y() + aliasedCoordinateDelta)); - } - controlPointRect = boundingRect(elements, element_count); #ifdef QT_DEBUG_CONVERT diff --git a/src/gui/painting/qoutlinemapper_p.h b/src/gui/painting/qoutlinemapper_p.h index d534f76..fcfc9bf 100644 --- a/src/gui/painting/qoutlinemapper_p.h +++ b/src/gui/painting/qoutlinemapper_p.h @@ -95,8 +95,7 @@ public: m_tags(0), m_contours(0), m_polygon_dev(0), - m_in_clip_elements(false), - m_round_coords(false) + m_in_clip_elements(false) { } @@ -202,8 +201,6 @@ public: QT_FT_Outline *convertPath(const QPainterPath &path); QT_FT_Outline *convertPath(const QVectorPath &path); - void setCoordinateRounding(bool coordinateRounding) { m_round_coords = coordinateRounding; } - inline QPainterPath::ElementType *elementTypes() const { return m_element_types.size() == 0 ? 0 : m_element_types.data(); } public: @@ -237,9 +234,6 @@ public: bool m_valid; bool m_in_clip_elements; - -private: - bool m_round_coords; }; QT_END_NAMESPACE diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp index 3a4c94c..d4a8213 100644 --- a/src/gui/painting/qpaintbuffer.cpp +++ b/src/gui/painting/qpaintbuffer.cpp @@ -130,7 +130,7 @@ QPaintBufferPrivate::~QPaintBufferPrivate() for (int i = 0; i < commands.size(); ++i) { const QPaintBufferCommand &cmd = commands.at(i); if (cmd.id == QPaintBufferPrivate::Cmd_DrawTextItem) - delete reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(variants.at(cmd.offset))); + delete reinterpret_cast<QTextItemIntCopy *>(qvariant_cast<void *>(variants.at(cmd.offset))); } } @@ -330,7 +330,7 @@ QString QPaintBuffer::commandDescription(int command) const break; } case QPaintBufferPrivate::Cmd_SetBrush: { - QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.offset)); + QBrush brush = qvariant_cast<QBrush>(d_ptr->variants.at(cmd.offset)); debug << "Cmd_SetBrush: " << brush; break; } @@ -354,27 +354,27 @@ QString QPaintBuffer::commandDescription(int command) const break; } case QPaintBufferPrivate::Cmd_StrokeVectorPath: { - QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.extra)); + QPen pen = qvariant_cast<QPen>(d_ptr->variants.at(cmd.extra)); debug << "ExCmd_StrokeVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] << "pts/elms:" << cmd.offset << cmd.offset2 << pen; break; } case QPaintBufferPrivate::Cmd_FillVectorPath: { - QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d_ptr->variants.at(cmd.extra)); debug << "ExCmd_FillVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] << "pts/elms:" << cmd.offset << cmd.offset2 << brush; break; } case QPaintBufferPrivate::Cmd_FillRectBrush: { - QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d_ptr->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset); debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush; break; } case QPaintBufferPrivate::Cmd_FillRectColor: { - QColor color = qVariantValue<QColor>(d_ptr->variants.at(cmd.extra)); + QColor color = qvariant_cast<QColor>(d_ptr->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset); debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color; break; } @@ -451,12 +451,12 @@ QString QPaintBuffer::commandDescription(int command) const break; } case QPaintBufferPrivate::Cmd_SetPen: { - QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.offset)); + QPen pen = qvariant_cast<QPen>(d_ptr->variants.at(cmd.offset)); debug << "Cmd_SetPen: " << pen; break; } case QPaintBufferPrivate::Cmd_SetTransform: { - QTransform xform = qVariantValue<QTransform>(d_ptr->variants.at(cmd.offset)); + QTransform xform = qvariant_cast<QTransform>(d_ptr->variants.at(cmd.offset)); debug << "Cmd_SetTransform, offset: " << cmd.offset << xform; break; } @@ -532,7 +532,7 @@ QString QPaintBuffer::commandDescription(int command) const case QPaintBufferPrivate::Cmd_DrawTextItem: { QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1)); - QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d_ptr->variants.at(cmd.offset))); + QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qvariant_cast<void *>(d_ptr->variants.at(cmd.offset))); QTextItemInt &ti = (*tiCopy)(); QString text(ti.text()); @@ -1287,7 +1287,7 @@ void QPaintBufferEngine::drawTextItem(const QPointF &pos, const QTextItem &ti) qDebug() << "QPaintBufferEngine: drawTextItem: pos:" << pos << ti.text(); #endif if (m_stream_raw_text_items) { - QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTextItem, qVariantFromValue<void *>(new QTextItemIntCopy(ti))); + QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTextItem, QVariant::fromValue<void *>(new QTextItemIntCopy(ti))); QFont font(ti.font()); font.setUnderline(false); @@ -1429,7 +1429,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_SetPen: { - QPen pen = qVariantValue<QPen>(d->variants.at(cmd.offset)); + QPen pen = qvariant_cast<QPen>(d->variants.at(cmd.offset)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_SetPen: " << pen; #endif @@ -1437,7 +1437,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_SetBrush: { - QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.offset)); + QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.offset)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_SetBrush: " << brush; #endif @@ -1452,7 +1452,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_SetTransform: { - QTransform xform = qVariantValue<QTransform>(d->variants.at(cmd.offset)); + QTransform xform = qvariant_cast<QTransform>(d->variants.at(cmd.offset)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_SetTransform, offset: " << cmd.offset << xform; #endif @@ -1520,7 +1520,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_StrokeVectorPath: { - QPen pen = qVariantValue<QPen>(d->variants.at(cmd.extra)); + QPen pen = qvariant_cast<QPen>(d->variants.at(cmd.extra)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_StrokeVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] @@ -1531,7 +1531,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillVectorPath: { - QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_FillVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] @@ -1705,7 +1705,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillRectBrush: { - QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush; @@ -1714,7 +1714,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillRectColor: { - QColor color = qVariantValue<QColor>(d->variants.at(cmd.extra)); + QColor color = qvariant_cast<QColor>(d->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color; @@ -1790,7 +1790,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) case QPaintBufferPrivate::Cmd_DrawTextItem: { QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1)); - QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d->variants.at(cmd.offset))); + QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qvariant_cast<void *>(d->variants.at(cmd.offset))); QTextItemInt &ti = (*tiCopy)(); QString text(ti.text()); @@ -1885,7 +1885,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_StrokeVectorPath: { - QPen pen = qVariantValue<QPen>(d->variants.at(cmd.extra)); + QPen pen = qvariant_cast<QPen>(d->variants.at(cmd.extra)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> ExCmd_StrokeVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] @@ -1896,7 +1896,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillVectorPath: { - QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> ExCmd_FillVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] @@ -1907,7 +1907,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillRectBrush: { - QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush; @@ -1916,7 +1916,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillRectColor: { - QColor color = qVariantValue<QColor>(d->variants.at(cmd.extra)); + QColor color = qvariant_cast<QColor>(d->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color; diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 09a87aa..94d7578 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -123,9 +123,6 @@ void dumpClip(int width, int height, const QClipData *clip); // 4 pixels. #define int_dim(pos, dim) (int(pos+dim) - int(pos)) -// use the same rounding as in qrasterizer.cpp (6 bit fixed point) -static const qreal aliasedCoordinateDelta = 0.5 - 0.015625; - #ifdef Q_WS_WIN extern bool qt_cleartype_enabled; #endif @@ -1753,10 +1750,10 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) static inline QRect toNormalizedFillRect(const QRectF &rect) { - int x1 = qRound(rect.x() + aliasedCoordinateDelta); - int y1 = qRound(rect.y() + aliasedCoordinateDelta); - int x2 = qRound(rect.right() + aliasedCoordinateDelta); - int y2 = qRound(rect.bottom() + aliasedCoordinateDelta); + int x1 = qRound(rect.x()); + int y1 = qRound(rect.y()); + int x2 = qRound(rect.right()); + int y2 = qRound(rect.bottom()); if (x2 < x1) qSwap(x1, x2); @@ -2025,7 +2022,6 @@ void QRasterPaintEngine::fillPolygon(const QPointF *points, int pointCount, Poly */ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) { - Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); #ifdef QT_DEBUG_DRAW @@ -2046,9 +2042,7 @@ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, Poly if (mode != PolylineMode) { // Do the fill... if (s->brushData.blend) { - d->outlineMapper->setCoordinateRounding(s->penData.blend && s->flags.fast_pen && s->lastPen.brush().isOpaque()); fillPolygon(points, pointCount, mode); - d->outlineMapper->setCoordinateRounding(false); } } @@ -2100,7 +2094,6 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg if (s->brushData.blend) { // Compose polygon fill.., ensureOutlineMapper(); - d->outlineMapper->setCoordinateRounding(s->penData.blend != 0); d->outlineMapper->beginOutline(mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill); d->outlineMapper->moveTo(*points); const QPoint *p = points; @@ -2114,7 +2107,6 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg ProcessSpans brushBlend = d->getBrushFunc(d->outlineMapper->controlPointRect, &s->brushData); d->rasterize(d->outlineMapper->outline(), brushBlend, &s->brushData, d->rasterBuffer.data()); - d->outlineMapper->setCoordinateRounding(false); } } @@ -2162,13 +2154,11 @@ void QRasterPaintEngine::strokePolygonCosmetic(const QPointF *points, int pointC : LineDrawNormal); int dashOffset = int(s->lastPen.dashOffset()); - const QPointF offs(aliasedCoordinateDelta, aliasedCoordinateDelta); - // Draw all the line segments. for (int i=1; i<pointCount; ++i) { - QPointF lp1 = points[i-1] * s->matrix + offs; - QPointF lp2 = points[i] * s->matrix + offs; + QPointF lp1 = points[i-1] * s->matrix; + QPointF lp2 = points[i] * s->matrix; const QRectF brect(lp1, lp2); ProcessSpans penBlend = d->getPenFunc(brect, &s->penData); @@ -2190,8 +2180,8 @@ void QRasterPaintEngine::strokePolygonCosmetic(const QPointF *points, int pointC // Polygons are implicitly closed. if (needs_closing) { - QPointF lp1 = points[pointCount-1] * s->matrix + offs; - QPointF lp2 = points[0] * s->matrix + offs; + QPointF lp1 = points[pointCount-1] * s->matrix; + QPointF lp2 = points[0] * s->matrix; const QRectF brect(lp1, lp2); ProcessSpans penBlend = d->getPenFunc(brect, &s->penData); @@ -2579,10 +2569,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe int sr_b = qCeil(sr.bottom()) - 1; if (s->matrix.type() <= QTransform::TxScale && !s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) { - // as fillRect will apply the aliased coordinate delta we need to - // subtract it here as we don't use it for image drawing QTransform old = s->matrix; - s->matrix = s->matrix * QTransform::fromTranslate(-aliasedCoordinateDelta, -aliasedCoordinateDelta); // Do whatever fillRect() does, but without premultiplying the color if it's already premultiplied. QRgb color = img.pixel(sr_l, sr_t); @@ -2726,11 +2713,9 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe d->initializeRasterizer(&d->image_filler_xform); d->rasterizer->setAntialiased(s->flags.antialiased); - const QPointF offs = s->flags.antialiased ? QPointF() : QPointF(aliasedCoordinateDelta, aliasedCoordinateDelta); - const QRectF &rect = r.normalized(); - const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f) - offs; - const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f) - offs; + const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f); + const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f); if (s->flags.tx_noshear) d->rasterizer->rasterizeLine(a, b, rect.height() / rect.width()); @@ -2739,13 +2724,12 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe return; } #endif - const qreal offs = s->flags.antialiased ? qreal(0) : aliasedCoordinateDelta; QPainterPath path; path.addRect(r); QTransform m = s->matrix; s->matrix = QTransform(m.m11(), m.m12(), m.m13(), m.m21(), m.m22(), m.m23(), - m.m31() - offs, m.m32() - offs, m.m33()); + m.m31(), m.m32(), m.m33()); fillPath(path, &d->image_filler_xform); s->matrix = m; } else { @@ -3099,6 +3083,7 @@ void QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, } cache->populate(fontEngine, numGlyphs, glyphs, positions); + cache->fillInPendingGlyphs(); const QImage &image = cache->image(); int bpl = image.bytesPerLine(); @@ -3113,13 +3098,19 @@ void QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, int margin = cache->glyphMargin(); - const QFixed offs = QFixed::fromReal(aliasedCoordinateDelta); + bool supportsSubPixelPositions = fontEngine->supportsSubPixelPositions(); const uchar *bits = image.bits(); for (int i=0; i<numGlyphs; ++i) { - const QTextureGlyphCache::Coord &c = cache->coords.value(glyphs[i]); - int x = qFloor(positions[i].x + offs) + c.baseLineX - margin; - int y = qFloor(positions[i].y + offs) - c.baseLineY - margin; + + QFixed subPixelPosition; + if (supportsSubPixelPositions) + subPixelPosition = cache->subPixelPositionForX(positions[i].x); + QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphs[i], subPixelPosition); + const QTextureGlyphCache::Coord &c = cache->coords.value(glyph); + + int x = qFloor(positions[i].x) + c.baseLineX - margin; + int y = qFloor(positions[i].y) - c.baseLineY - margin; // printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n", // c.x, c.y, @@ -3157,16 +3148,14 @@ void QRasterPaintEngine::drawGlyphsS60(const QPointF &p, const QTextItemInt &ti) fe->setFontScale(matrix.m11()); ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - const QFixed aliasDelta = QFixed::fromReal(aliasedCoordinateDelta); - for (int i=0; i<glyphs.size(); ++i) { TOpenFontCharMetrics tmetrics; const TUint8 *glyphBitmapBytes; TSize glyphBitmapSize; fe->getCharacterData(glyphs[i], tmetrics, glyphBitmapBytes, glyphBitmapSize); const glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyphs[i]); - const int x = qFloor(positions[i].x + metrics.x + aliasDelta); - const int y = qFloor(positions[i].y + metrics.y + aliasDelta); + const int x = qFloor(positions[i].x + metrics.x); + const int y = qFloor(positions[i].y + metrics.y); alphaPenBlt(glyphBitmapBytes, glyphBitmapSize.iWidth, 8, x, y, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight); } @@ -3380,7 +3369,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte #if defined(Q_WS_QWS) if (fontEngine->type() == QFontEngine::Box) { - fontEngine->draw(this, qFloor(p.x() + aliasedCoordinateDelta), qFloor(p.y() + aliasedCoordinateDelta), ti); + fontEngine->draw(this, qFloor(p.x()), qFloor(p.y()), ti); return; } @@ -3389,7 +3378,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte || (fontEngine->type() == QFontEngine::Proxy && !(static_cast<QProxyFontEngine *>(fontEngine)->drawAsOutline())) )) { - fontEngine->draw(this, qFloor(p.x() + aliasedCoordinateDelta), qFloor(p.y() + aliasedCoordinateDelta), ti); + fontEngine->draw(this, qFloor(p.x()), qFloor(p.y()), ti); return; } #endif // Q_WS_QWS @@ -3450,7 +3439,6 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte return; } - QFixed offs = QFixed::fromReal(aliasedCoordinateDelta); FT_Face lockedFace = 0; int depth; @@ -3498,8 +3486,8 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte }; alphaPenBlt(glyph->data, pitch, depth, - qFloor(positions[i].x + offs) + glyph->x, - qFloor(positions[i].y + offs) - glyph->y, + qFloor(positions[i].x) + glyph->x, + qFloor(positions[i].y) - glyph->y, glyph->width, glyph->height); } if (lockedFace) @@ -3636,8 +3624,8 @@ void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount) int m11 = int(s->matrix.m11()); int m22 = int(s->matrix.m22()); - int dx = qFloor(s->matrix.dx() + aliasedCoordinateDelta); - int dy = qFloor(s->matrix.dy() + aliasedCoordinateDelta); + int dx = qFloor(s->matrix.dx()); + int dy = qFloor(s->matrix.dy()); for (int i=0; i<lineCount; ++i) { int dashOffset = int(s->lastPen.dashOffset()); if (s->flags.int_xform) { @@ -3741,7 +3729,7 @@ void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount) for (int i=0; i<lineCount; ++i) { int dashOffset = int(s->lastPen.dashOffset()); - QLineF line = (lines[i] * s->matrix).translated(aliasedCoordinateDelta, aliasedCoordinateDelta); + QLineF line = lines[i] * s->matrix; const QRectF brect(QPointF(line.x1(), line.y1()), QPointF(line.x2(), line.y2())); ProcessSpans penBlend = d->getPenFunc(brect, &s->penData); diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 12be93e..8f54a2e 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -61,6 +61,8 @@ #include "qstyle.h" #include "qthread.h" #include "qvarlengtharray.h" +#include "qstatictext.h" +#include "qglyphs.h" #include <private/qfontengine_p.h> #include <private/qpaintengine_p.h> @@ -70,8 +72,8 @@ #include <private/qwidget_p.h> #include <private/qpaintengine_raster_p.h> #include <private/qmath_p.h> -#include <qstatictext.h> #include <private/qstatictext_p.h> +#include <private/qglyphs_p.h> #include <private/qstylehelper_p.h> QT_BEGIN_NAMESPACE @@ -92,7 +94,7 @@ void qt_format_text(const QFont &font, QPainter *painter); static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextCharFormat::UnderlineStyle underlineStyle, - const QTextItem::RenderFlags flags, qreal width, + QTextItem::RenderFlags flags, qreal width, const QTextCharFormat &charFormat); // Helper function to calculate left most position, width and flags for decoration drawing static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray, @@ -162,6 +164,10 @@ static bool qt_painter_thread_test(int devType, const char *what, bool extraCond #endif break; default: +#ifdef Q_WS_X11 + if (QApplication::testAttribute(Qt::AA_X11InitThreads)) + return true; +#endif if (!extraCondition && QThread::currentThread() != qApp->thread()) { qWarning("QPainter: It is not safe to use %s outside the GUI thread", what); return false; @@ -2701,6 +2707,61 @@ QPainterPath QPainter::clipPath() const } /*! + Returns the bounding rectangle of the current clip if there is a clip; + otherwise returns an empty rectangle. Note that the clip region is + given in logical coordinates. + + The bounding rectangle is not guaranteed to be tight. + + \sa setClipRect(), setClipPath(), setClipRegion() + + \since 4.8 + */ + +QRectF QPainter::clipBoundingRect() const +{ + Q_D(const QPainter); + + if (!d->engine) { + qWarning("QPainter::clipBoundingRect: Painter not active"); + return QRectF(); + } + + // Accumulate the bounding box in device space. This is not 100% + // precise, but it fits within the guarantee and it is resonably + // fast. + QRectF bounds; + for (int i=0; i<d->state->clipInfo.size(); ++i) { + QRectF r; + const QPainterClipInfo &info = d->state->clipInfo.at(i); + + if (info.clipType == QPainterClipInfo::RectClip) + r = info.rect; + else if (info.clipType == QPainterClipInfo::RegionClip) + r = info.region.boundingRect(); + else + r = info.path.boundingRect(); + + r = info.matrix.mapRect(r); + + if (i == 0) + bounds = r; + else if (info.operation == Qt::IntersectClip) + bounds &= r; + else if (info.operation == Qt::UniteClip) + bounds |= r; + } + + + // Map the rectangle back into logical space using the inverse + // matrix. + if (!d->txinv) + const_cast<QPainter *>(this)->d_ptr->updateInvMatrix(); + + return d->invMatrix.mapRect(bounds); +} + +/*! \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation) Enables clipping, and sets the clip region to the given \a @@ -5256,7 +5317,7 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm) return; #ifndef QT_NO_DEBUG - qt_painter_thread_test(d->device->devType(), "drawPixmap()"); + qt_painter_thread_test(d->device->devType(), "drawPixmap()", true); #endif if (d->extended) { @@ -5326,7 +5387,7 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) if (!d->engine || pm.isNull()) return; #ifndef QT_NO_DEBUG - qt_painter_thread_test(d->device->devType(), "drawPixmap()"); + qt_painter_thread_test(d->device->devType(), "drawPixmap()", true); #endif qreal x = r.x(); @@ -5711,17 +5772,50 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags); } +/*! + Draws the glyphs represented by \a glyphs at \a position. The \a position gives the + edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font + selected on \a glyphs and at offsets given by the positions in \a glyphs. + + \since 4.8 + + \sa QGlyphs::setFont(), QGlyphs::setPositions(), QGlyphs::setGlyphIndexes() +*/ +void QPainter::drawGlyphs(const QPointF &position, const QGlyphs &glyphs) +{ + Q_D(QPainter); + + QFont oldFont = d->state->font; + d->state->font = glyphs.font(); + + QVector<quint32> glyphIndexes = glyphs.glyphIndexes(); + QVector<QPointF> glyphPositions = glyphs.positions(); + + int count = qMin(glyphIndexes.size(), glyphPositions.size()); + QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count); + for (int i=0; i<count; ++i) + fixedPointPositions[i] = QFixedPoint::fromPointF(position + glyphPositions.at(i)); + + d->drawGlyphs(glyphIndexes.data(), fixedPointPositions.data(), count); + + d->state->font = oldFont; +} void qt_draw_glyphs(QPainter *painter, const quint32 *glyphArray, const QPointF *positionArray, int glyphCount) { + QVarLengthArray<QFixedPoint, 128> positions(glyphCount); + for (int i=0; i<glyphCount; ++i) + positions[i] = QFixedPoint::fromPointF(positionArray[i]); + QPainterPrivate *painter_d = QPainterPrivate::get(painter); - painter_d->drawGlyphs(glyphArray, positionArray, glyphCount); + painter_d->drawGlyphs(const_cast<quint32 *>(glyphArray), positions.data(), glyphCount); } -void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray, - int glyphCount) +void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, int glyphCount) { + Q_Q(QPainter); + updateState(state); QFontEngine *fontEngine = state->font.d->engineForScript(QUnicodeTables::Common); @@ -5736,12 +5830,27 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit fontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx); } - QVarLengthArray<QFixedPoint, 128> positions; + QFixed leftMost; + QFixed rightMost; + QFixed baseLine; for (int i=0; i<glyphCount; ++i) { - QFixedPoint fp = QFixedPoint::fromPointF(positionArray[i]); - positions.append(fp); + glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]); + if (i == 0 || leftMost > positions[i].x) + leftMost = positions[i].x; + + // We don't support glyphs that do not share a common baseline. If this turns out to + // be a relevant use case, then we need to find clusters of glyphs that share a baseline + // and do a drawTextItemDecorations call per cluster. + if (i == 0 || baseLine < positions[i].y) + baseLine = positions[i].y; + + // We use the advance rather than the actual bounds to match the algorithm in drawText() + if (i == 0 || rightMost < positions[i].x + gm.xoff) + rightMost = positions[i].x + gm.xoff; } + QFixed width = rightMost - leftMost; + if (extended != 0) { QStaticTextItem staticTextItem; staticTextItem.color = state->pen.color(); @@ -5749,7 +5858,7 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit staticTextItem.fontEngine = fontEngine; staticTextItem.numGlyphs = glyphCount; staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray)); - staticTextItem.glyphPositions = positions.data(); + staticTextItem.glyphPositions = positions; extended->drawStaticTextItem(&staticTextItem); } else { @@ -5766,7 +5875,7 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit textItem.glyphs.numGlyphs = glyphCount; textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray)); - textItem.glyphs.offsets = positions.data(); + textItem.glyphs.offsets = positions; textItem.glyphs.advances_x = advances.data(); textItem.glyphs.advances_y = advances.data(); textItem.glyphs.justifications = glyphJustifications.data(); @@ -5774,6 +5883,21 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit engine->drawTextItem(QPointF(0, 0), textItem); } + + QTextItemInt::RenderFlags flags; + if (state->font.underline()) + flags |= QTextItemInt::Underline; + if (state->font.overline()) + flags |= QTextItemInt::Overline; + if (state->font.strikeOut()) + flags |= QTextItemInt::StrikeOut; + + drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()), + fontEngine, + (state->font.underline() + ? QTextCharFormat::SingleUnderline + : QTextCharFormat::NoUnderline), + flags, width.toReal(), QTextCharFormat()); } /*! @@ -6309,7 +6433,7 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen) static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextCharFormat::UnderlineStyle underlineStyle, - const QTextItem::RenderFlags flags, qreal width, + QTextItem::RenderFlags flags, qreal width, const QTextCharFormat &charFormat) { if (underlineStyle == QTextCharFormat::NoUnderline @@ -6697,7 +6821,7 @@ void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPo return; #ifndef QT_NO_DEBUG - qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()"); + qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true); #endif qreal sw = pixmap.width(); @@ -7877,7 +8001,7 @@ void qt_format_text(const QFont &fnt, const QRectF &_r, } void qt_format_text(const QFont &fnt, const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect, - int tabstops, int *, int tabarraylen, + int tabstops, int *ta, int tabarraylen, QPainter *painter) { @@ -7997,6 +8121,16 @@ start_lengthVariant: engine.option = *option; } + if (engine.option.tabStop() < 0 && tabstops > 0) + engine.option.setTabStop(tabstops); + + if (engine.option.tabs().isEmpty() && ta) { + QList<qreal> tabs; + for (int i = 0; i < tabarraylen; i++) + tabs.append(qreal(ta[i])); + engine.option.setTabArray(tabs); + } + engine.option.setTextDirection(layout_direction); if (tf & Qt::AlignJustify) engine.option.setAlignment(Qt::AlignJustify); diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index edfb67e..96305e3 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -79,6 +79,7 @@ class QTextItem; class QMatrix; class QTransform; class QStaticText; +class QGlyphs; class QPainterPrivateDeleter; @@ -221,6 +222,8 @@ public: void setClipping(bool enable); bool hasClipping() const; + QRectF clipBoundingRect() const; + void save(); void restore(); @@ -396,6 +399,8 @@ public: void setLayoutDirection(Qt::LayoutDirection direction); Qt::LayoutDirection layoutDirection() const; + void drawGlyphs(const QPointF &position, const QGlyphs &glyphs); + void drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText); inline void drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText); inline void drawStaticText(int left, int top, const QStaticText &staticText); diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index 9362dbe..a61f5ca 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -70,6 +70,7 @@ QT_BEGIN_NAMESPACE class QPaintEngine; class QEmulationPaintEngine; class QPaintEngineEx; +struct QFixedPoint; struct QTLWExtra; @@ -228,7 +229,7 @@ public: void draw_helper(const QPainterPath &path, DrawOperation operation = StrokeAndFillDraw); void drawStretchedGradient(const QPainterPath &path, DrawOperation operation); void drawOpaqueBackground(const QPainterPath &path, DrawOperation operation); - void drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray, int glyphCount); + void drawGlyphs(quint32 *glyphArray, QFixedPoint *positionArray, int glyphCount); void updateMatrix(); void updateInvMatrix(); diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h index 15d83b8..9a7b60a 100644 --- a/src/gui/painting/qpainterpath.h +++ b/src/gui/painting/qpainterpath.h @@ -95,6 +95,10 @@ public: explicit QPainterPath(const QPointF &startPoint); QPainterPath(const QPainterPath &other); QPainterPath &operator=(const QPainterPath &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QPainterPath &operator=(QPainterPath &&other) + { qSwap(d_ptr, other.d_ptr); return *this; } +#endif ~QPainterPath(); void closeSubpath(); diff --git a/src/gui/painting/qpen.h b/src/gui/painting/qpen.h index aff7071..4006112 100644 --- a/src/gui/painting/qpen.h +++ b/src/gui/painting/qpen.h @@ -74,6 +74,10 @@ public: ~QPen(); QPen &operator=(const QPen &pen); +#ifdef Q_COMPILER_RVALUE_REFS + inline QPen &operator=(QPen &&other) + { qSwap(d, other.d); return *this; } +#endif Qt::PenStyle style() const; void setStyle(Qt::PenStyle); diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp index f8f8afb..c92d8d5 100644 --- a/src/gui/painting/qrasterizer.cpp +++ b/src/gui/painting/qrasterizer.cpp @@ -62,8 +62,8 @@ typedef int Q16Dot16; #define SPAN_BUFFER_SIZE 256 -#define COORD_ROUNDING 1 // 0: round up, 1: round down -#define COORD_OFFSET 32 // 26.6, 32 is half a pixel +#define COORD_ROUNDING 0 // 0: round up, 1: round down +#define COORD_OFFSET 0 // 26.6, 32 is half a pixel class QSpanBuffer { public: @@ -718,7 +718,7 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, QPointF pa = a; QPointF pb = b; - QPointF offs = QPointF(qAbs(b.y() - a.y()), qAbs(b.x() - a.x())) * width * 0.5; + QPointF offs = QPointF(qAbs(b.y() - a.y()), qAbs(b.x() - a.x())) * width * 0.5; if (squareCap) offs += QPointF(offs.y(), offs.x()); const QRectF clip(d->clipRect.topLeft() - offs, d->clipRect.bottomRight() + QPoint(1, 1) + offs); diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h index bc4da28..2e42844 100644 --- a/src/gui/painting/qregion.h +++ b/src/gui/painting/qregion.h @@ -81,7 +81,10 @@ public: QRegion(const QBitmap &bitmap); ~QRegion(); QRegion &operator=(const QRegion &); - +#ifdef Q_COMPILER_RVALUE_REFS + inline QRegion &operator=(QRegion &&other) + { qSwap(d, other.d); return *this; } +#endif #ifdef QT3_SUPPORT inline QT3_SUPPORT bool isNull() const { return isEmpty(); } #endif diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index 631a9cf..e992bb2 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -69,8 +69,60 @@ static inline int qt_next_power_of_two(int v) return v; } +int QTextureGlyphCache::calculateSubPixelPositionCount(glyph_t glyph) const +{ + // Test 12 different subpixel positions since it factors into 3*4 so it gives + // the coverage we need. + + QList<QImage> images; + for (int i=0; i<12; ++i) { + QImage img = textureMapForGlyph(glyph, QFixed::fromReal(i / 12.0)); + + if (images.isEmpty()) { + QPainterPath path; + QFixedPoint point; + m_current_fontengine->addGlyphsToPath(&glyph, &point, 1, &path, QTextItem::RenderFlags()); + + // Glyph is space, return 0 to indicate that we need to keep trying + if (path.isEmpty()) + break; + + images.append(img); + } else { + bool found = false; + for (int j=0; j<images.size(); ++j) { + if (images.at(j) == img) { + found = true; + break; + } + } + if (!found) + images.append(img); + } + } + + return images.size(); +} + +QFixed QTextureGlyphCache::subPixelPositionForX(QFixed x) const +{ + if (m_subPixelPositionCount == 0) + return QFixed(); + + QFixed subPixelPosition; + if (x != 0) { + subPixelPosition = x - x.floor(); + QFixed fraction = (subPixelPosition / QFixed::fromReal(1.0 / m_subPixelPositionCount)).floor(); + + // Compensate for precision loss in fixed point to make sure we are always drawing at a subpixel position over + // the lower boundary for the selected rasterization by adding 1/64. + subPixelPosition = fraction / QFixed(m_subPixelPositionCount) + QFixed::fromReal(0.015625); + } + return subPixelPosition; +} + void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs, - const QFixedPoint *) + const QFixedPoint *positions) { #ifdef CACHE_DEBUG printf("Populating with %d glyphs\n", numGlyphs); @@ -81,15 +133,33 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const const int margin = glyphMargin(); const int paddingDoubled = glyphPadding() * 2; - QHash<glyph_t, Coord> listItemCoordinates; + bool supportsSubPixelPositions = fontEngine->supportsSubPixelPositions(); + if (m_subPixelPositionCount == 0) { + if (!supportsSubPixelPositions) { + m_subPixelPositionCount = 1; + } else { + int i = 0; + while (m_subPixelPositionCount == 0 && i < numGlyphs) + m_subPixelPositionCount = calculateSubPixelPositionCount(glyphs[i++]); + } + } + + QHash<GlyphAndSubPixelPosition, Coord> listItemCoordinates; int rowHeight = 0; // check each glyph for its metrics and get the required rowHeight. for (int i=0; i < numGlyphs; ++i) { const glyph_t glyph = glyphs[i]; - if (coords.contains(glyph)) + + QFixed subPixelPosition; + if (supportsSubPixelPositions) { + QFixed x = positions != 0 ? positions[i].x : QFixed(); + subPixelPosition = subPixelPositionForX(x); + } + + if (coords.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition))) continue; - if (listItemCoordinates.contains(glyph)) + if (listItemCoordinates.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition))) continue; glyph_metrics_t metrics = fontEngine->boundingBox(glyph, m_transform); @@ -119,18 +189,23 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const metrics.x.round().truncate(), -metrics.y.truncate() }; // baseline for horizontal scripts - listItemCoordinates.insert(glyph, c); + listItemCoordinates.insert(GlyphAndSubPixelPosition(glyph, subPixelPosition), c); rowHeight = qMax(rowHeight, glyph_height); } if (listItemCoordinates.isEmpty()) return; rowHeight += margin * 2 + paddingDoubled; - if (isNull()) - createCache(QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH, qt_next_power_of_two(rowHeight)); + + if (m_w == 0) { + if (fontEngine->maxCharWidth() <= QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH) + m_w = QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH; + else + m_w = qt_next_power_of_two(fontEngine->maxCharWidth()); + } // now actually use the coords and paint the wanted glyps into cache. - QHash<glyph_t, Coord>::iterator iter = listItemCoordinates.begin(); + QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = listItemCoordinates.begin(); while (iter != listItemCoordinates.end()) { Coord c = iter.value(); @@ -142,29 +217,54 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const m_cy += m_currentRowHeight + paddingDoubled; m_currentRowHeight = 0; // New row } - if (m_cy + c.h > m_h) { - int new_height = m_h*2; - while (new_height < m_cy + c.h) - new_height *= 2; - // if no room in the current texture - realloc a larger texture - resizeTextureData(m_w, new_height); - m_h = new_height; - } c.x = m_cx; c.y = m_cy; - fillTexture(c, iter.key()); coords.insert(iter.key(), c); + m_pendingGlyphs.insert(iter.key(), c); m_cx += c.w + paddingDoubled; ++iter; } +} + +void QTextureGlyphCache::fillInPendingGlyphs() +{ + if (m_pendingGlyphs.isEmpty()) + return; + int requiredHeight = 0; + { + QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = m_pendingGlyphs.begin(); + while (iter != m_pendingGlyphs.end()) { + Coord c = iter.value(); + requiredHeight = qMax(requiredHeight, c.y + c.h); + ++iter; + } + } + + if (requiredHeight > m_h) { + if (isNull()) + createCache(m_w, qt_next_power_of_two(requiredHeight)); + else + resizeCache(m_w, qt_next_power_of_two(requiredHeight)); + } + + { + QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = m_pendingGlyphs.begin(); + while (iter != m_pendingGlyphs.end()) { + GlyphAndSubPixelPosition key = iter.key(); + fillTexture(iter.value(), key.glyph, key.subPixelPosition); + + ++iter; + } + } + m_pendingGlyphs.clear(); } -QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g) const +QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, QFixed subPixelPosition) const { #if defined(Q_WS_X11) if (m_transform.type() > QTransform::TxTranslate) { @@ -197,7 +297,7 @@ QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g) const } else #endif if (m_type == QFontEngineGlyphCache::Raster_RGBMask) - return m_current_fontengine->alphaRGBMapForGlyph(g, glyphMargin(), m_transform); + return m_current_fontengine->alphaRGBMapForGlyph(g, subPixelPosition, glyphMargin(), m_transform); else return m_current_fontengine->alphaMapForGlyph(g, m_transform); @@ -243,9 +343,9 @@ int QImageTextureGlyphCache::glyphMargin() const #endif } -void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g) +void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subPixelPosition) { - QImage mask = textureMapForGlyph(g); + QImage mask = textureMapForGlyph(g, subPixelPosition); #ifdef CACHE_DEBUG printf("fillTexture of %dx%d at %d,%d in the cache of %dx%d\n", c.w, c.h, c.x, c.y, m_image.width(), m_image.height()); diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h index a818978..4131003 100644 --- a/src/gui/painting/qtextureglyphcache_p.h +++ b/src/gui/painting/qtextureglyphcache_p.h @@ -77,11 +77,24 @@ class Q_GUI_EXPORT QTextureGlyphCache : public QFontEngineGlyphCache public: QTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix) : QFontEngineGlyphCache(matrix, type), m_current_fontengine(0), - m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0) + m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0), m_subPixelPositionCount(0) { } virtual ~QTextureGlyphCache() { } + struct GlyphAndSubPixelPosition + { + GlyphAndSubPixelPosition(glyph_t g, QFixed spp) : glyph(g), subPixelPosition(spp) {} + + bool operator==(const GlyphAndSubPixelPosition &other) const + { + return glyph == other.glyph && subPixelPosition == other.subPixelPosition; + } + + glyph_t glyph; + QFixed subPixelPosition; + }; + struct Coord { int x; int y; @@ -94,13 +107,14 @@ public: void populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions); + void fillInPendingGlyphs(); virtual void createTextureData(int width, int height) = 0; virtual void resizeTextureData(int width, int height) = 0; virtual int glyphMargin() const { return 0; } virtual int glyphPadding() const { return 0; } - virtual void fillTexture(const Coord &coord, glyph_t glyph) = 0; + virtual void fillTexture(const Coord &coord, glyph_t glyph, QFixed subPixelPosition) = 0; inline void createCache(int width, int height) { m_w = width; @@ -108,22 +122,40 @@ public: createTextureData(width, height); } - inline bool isNull() const { return m_w <= 0 || m_h <= 0; } + inline void resizeCache(int width, int height) + { + resizeTextureData(width, height); + m_w = width; + m_h = height; + } + + inline bool isNull() const { return m_h == 0; } + + QHash<GlyphAndSubPixelPosition, Coord> coords; - QHash<glyph_t, Coord> coords; + QImage textureMapForGlyph(glyph_t g, QFixed subPixelPosition) const; - QImage textureMapForGlyph(glyph_t g) const; + QFixed subPixelPositionForX(QFixed x) const; protected: + int calculateSubPixelPositionCount(glyph_t) const; + QFontEngine *m_current_fontengine; + QHash<GlyphAndSubPixelPosition, Coord> m_pendingGlyphs; int m_w; // image width int m_h; // image height int m_cx; // current x int m_cy; // current y int m_currentRowHeight; // Height of last row + int m_subPixelPositionCount; // Number of positions within a single pixel for this cache }; +inline uint qHash(const QTextureGlyphCache::GlyphAndSubPixelPosition &g) +{ + return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt(); +} + class Q_GUI_EXPORT QImageTextureGlyphCache : public QTextureGlyphCache { @@ -133,7 +165,7 @@ public: virtual int glyphMargin() const; virtual void createTextureData(int width, int height); virtual void resizeTextureData(int width, int height); - virtual void fillTexture(const Coord &c, glyph_t glyph); + virtual void fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition); inline const QImage &image() const { return m_image; } diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp index eee6bef..6a2cb1e 100644 --- a/src/gui/painting/qwindowsurface_raster.cpp +++ b/src/gui/painting/qwindowsurface_raster.cpp @@ -248,10 +248,6 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi #ifdef Q_WS_MAC -// qDebug() << "Flushing" << widget << rgn << offset; - -// d->image->image.save("flush.png"); - Q_UNUSED(offset); // Get a context for the widget. #ifndef QT_MAC_USE_COCOA @@ -282,20 +278,19 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi CGImageRef subImage = CGImageCreateWithImageInRect(image, area); qt_mac_drawCGImage(context, &area, subImage); + CGImageRelease(subImage); CGImageRelease(image); -// CGSize size = { d->image->image.width(), d->image->image.height() }; -// CGLayerRef layer = CGLayerCreateWithContext(d->image->cg, size, 0); -// CGPoint pt = { 0, 0 }; -// CGContextDrawLayerAtPoint(context, pt, layer); -// CGLayerRelease(layer); - - // Restore context. - CGContextRestoreGState(context); #ifndef QT_MAC_USE_COCOA QDEndCGContext(port, &context); +#else + CGContextFlush(context); #endif + + // Restore context. + CGContextRestoreGState(context); + #endif // Q_WS_MAC #ifdef Q_OS_SYMBIAN diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp index 8bac1f5..d4dcf7d 100644 --- a/src/gui/painting/qwindowsurface_s60.cpp +++ b/src/gui/painting/qwindowsurface_s60.cpp @@ -77,7 +77,8 @@ QS60WindowSurface::QS60WindowSurface(QWidget* widget) } // We create empty CFbsBitmap here -> it will be resized in setGeometry - CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new + CFbsBitmap *bitmap = new CFbsBitmap; // CBase derived object needs check on new + Q_CHECK_PTR(bitmap); qt_symbian_throwIfError( bitmap->Create( TSize(0, 0), mode ) ); QS60PixmapData *data = new QS60PixmapData(QPixmapData::PixmapType); diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp index 306219d..e280a51 100644 --- a/src/gui/styles/qcleanlooksstyle.cpp +++ b/src/gui/styles/qcleanlooksstyle.cpp @@ -3763,6 +3763,7 @@ int QCleanlooksStyle::pixelMetric(PixelMetric metric, const QStyleOption *option break; case PM_MenuBarItemSpacing: ret = 6; + break; case PM_MenuBarHMargin: ret = 0; break; diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index 671a888..556e0f3 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -1642,7 +1642,7 @@ bool QMacStylePrivate::eventFilter(QObject *o, QEvent *e) case QEvent::FocusOut: case QEvent::Show: case QEvent::WindowActivate: { - QList<QPushButton *> list = qFindChildren<QPushButton *>(btn->window()); + QList<QPushButton *> list = btn->window()->findChildren<QPushButton *>(); for (int i = 0; i < list.size(); ++i) { QPushButton *pBtn = list.at(i); if ((e->type() == QEvent::FocusOut @@ -5538,6 +5538,57 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, // hack to work around horrible sizeHint() code in QAbstractSpinBox sz.setHeight(sz.height() - 3); break; + case QStyle::CT_TabWidget: + // the size between the pane and the "contentsRect" (+4,+4) + // (the "contentsRect" is on the inside of the pane) + sz = QWindowsStyle::sizeFromContents(ct, opt, csz, widget); + /** + This is supposed to show the relationship between the tabBar and + the stack widget of a QTabWidget. + Unfortunately ascii is not a good way of representing graphics..... + PS: The '=' line is the painted frame. + + top ---+ + | + | + | + | vvv just outside the painted frame is the "pane" + - -|- - - - - - - - - - <-+ + TAB BAR +=====^============ | +2 pixels + - - -|- - -|- - - - - - - <-+ + | | ^ ^^^ just inside the painted frame is the "contentsRect" + | | | + | overlap | + | | | + bottom ------+ <-+ +14 pixels + | + v + ------------------------------ <- top of stack widget + + + To summarize: + * 2 is the distance between the pane and the contentsRect + * The 14 and the 1's are the distance from the contentsRect to the stack widget. + (same value as used in SE_TabWidgetTabContents) + * overlap is how much the pane should overlap the tab bar + */ + // then add the size between the stackwidget and the "contentsRect" + + if (const QStyleOptionTabWidgetFrame *twf + = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { + QSize extra(0,0); + const int overlap = pixelMetric(PM_TabBarBaseOverlap, opt, widget); + const int gapBetweenTabbarAndStackWidget = 2 + 14 - overlap; + + if (getTabDirection(twf->shape) == kThemeTabNorth || getTabDirection(twf->shape) == kThemeTabSouth) { + extra = QSize(2, gapBetweenTabbarAndStackWidget + 1); + } else { + extra = QSize(gapBetweenTabbarAndStackWidget + 1, 2); + } + sz+= extra; + } + + break; case QStyle::CT_TabBarTab: if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) { const QAquaWidgetSize AquaSize = d->aquaSizeConstrain(opt, widget); diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp index 20d9bd9..4690a71 100644 --- a/src/gui/styles/qplastiquestyle.cpp +++ b/src/gui/styles/qplastiquestyle.cpp @@ -1054,7 +1054,7 @@ void QPlastiqueStylePrivate::drawPartialFrame(QPainter *painter, const QStyleOpt bool reverse = option->direction == Qt::RightToLeft; QStyleOptionFrame frameOpt; #ifndef QT_NO_LINEEDIT - if (QLineEdit *lineedit = qFindChild<QLineEdit *>(widget)) + if (QLineEdit *lineedit = widget->findChild<QLineEdit *>()) frameOpt.initFrom(lineedit); #else Q_UNUSED(widget) diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index 5996032..9116a1e 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -1427,7 +1427,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, bool isScrollBarVisible = false; int scrollBarWidth = 0; - QList<QScrollBar *> scrollBars = qFindChildren<QScrollBar *>(widget); + QList<QScrollBar *> scrollBars = widget->findChildren<QScrollBar *>(); for (int i = 0; i < scrollBars.size(); ++i) { QScrollBar *scrollBar = scrollBars.at(i); if (scrollBar && scrollBar->orientation() == Qt::Vertical) { diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 92e2c81..4be439d 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -2342,7 +2342,7 @@ static QWidget *embeddedWidget(QWidget *w) #ifndef QT_NO_SPINBOX if (QAbstractSpinBox *sb = qobject_cast<QAbstractSpinBox *>(w)) - return qFindChild<QLineEdit *>(sb); + return sb->findChild<QLineEdit *>(); #endif #ifndef QT_NO_SCROLLAREA @@ -2583,7 +2583,7 @@ void QStyleSheetStyle::unsetPalette(QWidget *w) } QVariant oldFont = w->property("_q_styleSheetWidgetFont"); if (oldFont.isValid()) { - w->setFont(qVariantValue<QFont>(oldFont)); + w->setFont(qvariant_cast<QFont>(oldFont)); } if (autoFillDisabledWidgets->contains(w)) { embeddedWidget(w)->setAutoFillBackground(true); @@ -2795,7 +2795,7 @@ void QStyleSheetStyle::polish(QPalette &pal) void QStyleSheetStyle::repolish(QWidget *w) { - QList<const QWidget *> children = qFindChildren<const QWidget *>(w, QString()); + QList<const QWidget *> children = w->findChildren<const QWidget *>(QString()); children.append(w); styleSheetCache->remove(w); updateWidgets(children); @@ -3048,6 +3048,13 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC titleRule.configurePalette(&pal, QPalette::WindowText, QPalette::Window); drawItemText(p, labelRect, alignment, pal, gb->state & State_Enabled, gb->text, QPalette::WindowText); + + if (gb->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*gb); + fropt.rect = labelRect; + drawPrimitive(PE_FrameFocusRect, &fropt, p, w); + } } return; @@ -5074,7 +5081,7 @@ QIcon QStyleSheetStyle::standardIconImplementation(StandardPixmap standardIcon, if (!s.isEmpty()) { QRenderRule rule = renderRule(w, opt); if (rule.hasStyleHint(s)) - return qVariantValue<QIcon>(rule.styleHint(s)); + return qvariant_cast<QIcon>(rule.styleHint(s)); } return baseStyle()->standardIcon(standardIcon, opt, w); } @@ -5092,7 +5099,7 @@ QPixmap QStyleSheetStyle::standardPixmap(StandardPixmap standardPixmap, const QS if (!s.isEmpty()) { QRenderRule rule = renderRule(w, opt); if (rule.hasStyleHint(s)) { - QIcon icon = qVariantValue<QIcon>(rule.styleHint(s)); + QIcon icon = qvariant_cast<QIcon>(rule.styleHint(s)); return icon.pixmap(16, 16); // ###: unhard-code this if someone complains } } @@ -5186,7 +5193,7 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi case SH_ComboBox_PopupFrameStyle: #ifndef QT_NO_COMBOBOX if (qobject_cast<const QComboBox *>(w)) { - QAbstractItemView *view = qFindChild<QAbstractItemView *>(w); + QAbstractItemView *view = w->findChild<QAbstractItemView *>(); if (view) { view->ensurePolished(); QRenderRule subRule = renderRule(view, PseudoElement_None); diff --git a/src/gui/styles/qwindowscestyle.cpp b/src/gui/styles/qwindowscestyle.cpp index b027005..bd7246a 100644 --- a/src/gui/styles/qwindowscestyle.cpp +++ b/src/gui/styles/qwindowscestyle.cpp @@ -2294,6 +2294,7 @@ int QWindowsCEStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QW break; case SH_EtchDisabledText: ret = false; + break; case SH_RequestSoftwareInputPanel: ret = RSIP_OnMouseClick; break; diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp index 720dd6d..d994b9b 100644 --- a/src/gui/styles/qwindowsstyle.cpp +++ b/src/gui/styles/qwindowsstyle.cpp @@ -175,7 +175,7 @@ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e) widget = widget->window(); // Alt has been pressed - find all widgets that care - QList<QWidget *> l = qFindChildren<QWidget *>(widget); + QList<QWidget *> l = widget->findChildren<QWidget *>(); for (int pos=0 ; pos < l.size() ; ++pos) { QWidget *w = l.at(pos); if (w->isWindow() || !w->isVisible() || @@ -198,7 +198,7 @@ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e) // Update state and repaint the menu bars. d->alt_down = false; #ifndef QT_NO_MENUBAR - QList<QMenuBar *> l = qFindChildren<QMenuBar *>(widget); + QList<QMenuBar *> l = widget->findChildren<QMenuBar *>(); for (int i = 0; i < l.size(); ++i) l.at(i)->update(); #endif @@ -1160,7 +1160,7 @@ int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWid if (!menuBar && qobject_cast<const QMenu *>(widget)) { QWidget *w = QApplication::activeWindow(); if (w && w != widget) - menuBar = qFindChild<QMenuBar *>(w); + menuBar = w->findChild<QMenuBar *>(); } // If we paint a menu bar draw underlines if is in the keyboardState if (menuBar) { diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp index 58542e5..bed5b09 100644 --- a/src/gui/styles/qwindowsvistastyle.cpp +++ b/src/gui/styles/qwindowsvistastyle.cpp @@ -842,10 +842,10 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt const QDialogButtonBox *buttonBox = 0; if (qobject_cast<const QMessageBox *> (widget)) - buttonBox = qFindChild<const QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox")); + buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox")); #ifndef QT_NO_INPUTDIALOG else if (qobject_cast<const QInputDialog *> (widget)) - buttonBox = qFindChild<const QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox")); + buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox")); #endif // QT_NO_INPUTDIALOG if (buttonBox) { @@ -2396,14 +2396,14 @@ void QWindowsVistaStyle::polish(QWidget *widget) } } else if (qobject_cast<QMessageBox *> (widget)) { widget->setAttribute(Qt::WA_StyledBackground); - QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox")); + QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox")); if (buttonBox) buttonBox->setContentsMargins(0, 9, 0, 0); } #ifndef QT_NO_INPUTDIALOG else if (qobject_cast<QInputDialog *> (widget)) { widget->setAttribute(Qt::WA_StyledBackground); - QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox")); + QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox")); if (buttonBox) buttonBox->setContentsMargins(0, 9, 0, 0); } @@ -2435,14 +2435,14 @@ void QWindowsVistaStyle::unpolish(QWidget *widget) widget->setAttribute(Qt::WA_Hover, false); else if (qobject_cast<QMessageBox *> (widget)) { widget->setAttribute(Qt::WA_StyledBackground, false); - QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox")); + QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox")); if (buttonBox) buttonBox->setContentsMargins(0, 0, 0, 0); } #ifndef QT_NO_INPUTDIALOG else if (qobject_cast<QInputDialog *> (widget)) { widget->setAttribute(Qt::WA_StyledBackground, false); - QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox")); + QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox")); if (buttonBox) buttonBox->setContentsMargins(0, 0, 0, 0); } diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp index d36011c..7ab1218 100644 --- a/src/gui/styles/qwindowsxpstyle.cpp +++ b/src/gui/styles/qwindowsxpstyle.cpp @@ -4054,7 +4054,7 @@ void QWindowsXPStylePrivate::dumpNativeDIB(int w, int h) bufferPos += sprintf(bufferPos, "\n};\n\n"); printf(bufferDump); - delete bufferDump; + delete[] bufferDump; ++pCount; } } diff --git a/src/gui/symbian/qsymbianevent.cpp b/src/gui/symbian/qsymbianevent.cpp index c341413..a7cfeef 100644 --- a/src/gui/symbian/qsymbianevent.cpp +++ b/src/gui/symbian/qsymbianevent.cpp @@ -40,6 +40,9 @@ ****************************************************************************/ #include "qsymbianevent.h" +#include <qdebug.h> + +#include <w32std.h> QT_BEGIN_NAMESPACE @@ -140,4 +143,34 @@ int QSymbianEvent::resourceChangeType() const return (m_type == ResourceChangeEvent) ? m_eventValue : 0; } +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QSymbianEvent *o) +{ + if (!o) { + dbg << "QSymbianEvent(0x0)"; + return dbg; + } + dbg.nospace() << "QSymbianEvent("; + switch (o->type()) { + case QSymbianEvent::InvalidEvent: + dbg << "InvalidEvent"; + break; + case QSymbianEvent::WindowServerEvent: + dbg << "WindowServerEvent, Type = " << o->windowServerEvent()->Type(); + break; + case QSymbianEvent::CommandEvent: + dbg << "CommandEvent, command = " << o->command(); + break; + case QSymbianEvent::ResourceChangeEvent: + dbg << "ResourceChangeEvent, resourceChangeType = " << o->resourceChangeType(); + break; + default: + dbg << "Unknown event type"; + break; + } + dbg << ")"; + return dbg.space(); +} +#endif + QT_END_NAMESPACE diff --git a/src/gui/symbian/qsymbianevent.h b/src/gui/symbian/qsymbianevent.h index 5cad654..4c9ae65 100644 --- a/src/gui/symbian/qsymbianevent.h +++ b/src/gui/symbian/qsymbianevent.h @@ -95,6 +95,10 @@ inline bool QSymbianEvent::isValid() const return m_type != InvalidEvent; } +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QSymbianEvent *o); +#endif + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index b3d2526..dafc8e7 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -68,6 +68,8 @@ static const QCssKnownValue properties[NumProperties - 1] = { { "-qt-background-role", QtBackgroundRole }, { "-qt-block-indent", QtBlockIndent }, { "-qt-list-indent", QtListIndent }, + { "-qt-list-number-prefix", QtListNumberPrefix }, + { "-qt-list-number-suffix", QtListNumberSuffix }, { "-qt-paragraph-type", QtParagraphType }, { "-qt-style-features", QtStyleFeatures }, { "-qt-table-type", QtTableType }, @@ -403,7 +405,7 @@ int ValueExtractor::lengthValue(const Declaration &decl) if (decl.d->values.count() < 1) return 0; LengthData data = lengthValue(decl.d->values.at(0)); - decl.d->parsed = qVariantFromValue<LengthData>(data); + decl.d->parsed = QVariant::fromValue<LengthData>(data); return lengthValueFromData(data,f); } @@ -435,7 +437,7 @@ void ValueExtractor::lengthValues(const Declaration &decl, int *m) QList<QVariant> v; for (i = 0; i < 4; i++) { - v += qVariantFromValue<LengthData>(datas[i]); + v += QVariant::fromValue<LengthData>(datas[i]); m[i] = lengthValueFromData(datas[i], f); } decl.d->parsed = v; @@ -541,7 +543,7 @@ QSize ValueExtractor::sizeValue(const Declaration &decl) else x[1] = x[0]; QList<QVariant> v; - v << qVariantFromValue<LengthData>(x[0]) << qVariantFromValue<LengthData>(x[1]); + v << QVariant::fromValue<LengthData>(x[0]) << qVariantFromValue<LengthData>(x[1]); decl.d->parsed = v; return QSize(lengthValueFromData(x[0], f), lengthValueFromData(x[1], f)); } @@ -916,7 +918,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord data.width = lengthValue(decl.d->values.at(i)); *width = lengthValueFromData(data.width, f); if (++i >= decl.d->values.count()) { - decl.d->parsed = qVariantFromValue<BorderData>(data); + decl.d->parsed = QVariant::fromValue<BorderData>(data); return; } } @@ -925,7 +927,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord if (data.style != BorderStyle_Unknown) { *style = data.style; if (++i >= decl.d->values.count()) { - decl.d->parsed = qVariantFromValue<BorderData>(data); + decl.d->parsed = QVariant::fromValue<BorderData>(data); return; } } else { @@ -935,7 +937,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord data.color = parseBrushValue(decl.d->values.at(i), pal); *color = brushFromData(data.color, pal); if (data.color.type != BrushData::DependsOnThePalette) - decl.d->parsed = qVariantFromValue<BorderData>(data); + decl.d->parsed = QVariant::fromValue<BorderData>(data); } static void parseShorthandBackgroundProperty(const QVector<Value> &values, BrushData *brush, QString *image, Repeat *repeat, Qt::Alignment *alignment, const QPalette &pal) @@ -1032,16 +1034,8 @@ bool ValueExtractor::extractBackground(QBrush *brush, QString *image, Repeat *re parseShorthandBackgroundProperty(decl.d->values, &brushData, image, repeat, alignment, pal); *brush = brushFromData(brushData, pal); if (brushData.type != BrushData::DependsOnThePalette) { -#if defined Q_CC_MSVC && _MSC_VER <= 1300 - BackgroundData data; - data.brush = brushData; - data.image = *image; - data.repeat = *repeat; - data.alignment = *alignment; -#else BackgroundData data = { brushData, *image, *repeat, *alignment }; -#endif - decl.d->parsed = qVariantFromValue<BackgroundData>(data); + decl.d->parsed = QVariant::fromValue<BackgroundData>(data); } } break; @@ -1319,10 +1313,10 @@ QColor Declaration::colorValue(const QPalette &pal) const ColorData color = parseColorValue(d->values.at(0)); if(color.type == ColorData::Role) { - d->parsed = qVariantFromValue<int>(color.role); + d->parsed = QVariant::fromValue<int>(color.role); return pal.color((QPalette::ColorRole)(color.role)); } else { - d->parsed = qVariantFromValue<QColor>(color.color); + d->parsed = QVariant::fromValue<QColor>(color.color); return color.color; } } @@ -1342,11 +1336,11 @@ QBrush Declaration::brushValue(const QPalette &pal) const BrushData data = parseBrushValue(d->values.at(0), pal); if(data.type == BrushData::Role) { - d->parsed = qVariantFromValue<int>(data.role); + d->parsed = QVariant::fromValue<int>(data.role); return pal.color((QPalette::ColorRole)(data.role)); } else { if (data.type != BrushData::DependsOnThePalette) - d->parsed = qVariantFromValue<QBrush>(data.brush); + d->parsed = QVariant::fromValue<QBrush>(data.brush); return data.brush; } } @@ -1376,11 +1370,11 @@ void Declaration::brushValues(QBrush *c, const QPalette &pal) const continue; BrushData data = parseBrushValue(d->values.at(i), pal); if(data.type == BrushData::Role) { - v += qVariantFromValue<int>(data.role); + v += QVariant::fromValue<int>(data.role); c[i] = pal.color((QPalette::ColorRole)(data.role)); } else { if (data.type != BrushData::DependsOnThePalette) { - v += qVariantFromValue<QBrush>(data.brush); + v += QVariant::fromValue<QBrush>(data.brush); } else { v += QVariant(); } @@ -1453,7 +1447,7 @@ QSize Declaration::sizeValue() const else x[1] = x[0]; QSize size(x[0], x[1]); - d->parsed = qVariantFromValue<QSize>(size); + d->parsed = QVariant::fromValue<QSize>(size); return size; } @@ -1475,7 +1469,7 @@ QRect Declaration::rectValue() const if (args.count() != 4) return QRect(); QRect rect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt()); - d->parsed = qVariantFromValue<QRect>(rect); + d->parsed = QVariant::fromValue<QRect>(rect); return rect; } @@ -1496,10 +1490,10 @@ void Declaration::colorValues(QColor *c, const QPalette &pal) const for (i = 0; i < qMin(d->values.count(), 4); i++) { ColorData color = parseColorValue(d->values.at(i)); if(color.type == ColorData::Role) { - v += qVariantFromValue<int>(color.role); + v += QVariant::fromValue<int>(color.role); c[i] = pal.color((QPalette::ColorRole)(color.role)); } else { - v += qVariantFromValue<QColor>(color.color); + v += QVariant::fromValue<QColor>(color.color); c[i] = color.color; } } @@ -1691,7 +1685,7 @@ QIcon Declaration::iconValue() const i++; } - d->parsed = qVariantFromValue<QIcon>(icon); + d->parsed = QVariant::fromValue<QIcon>(icon); return icon; } diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h index 138d506..ca9688e 100644 --- a/src/gui/text/qcssparser_p.h +++ b/src/gui/text/qcssparser_p.h @@ -178,6 +178,8 @@ enum Property { OutlineBottomRightRadius, FontVariant, TextTransform, + QtListNumberPrefix, + QtListNumberSuffix, NumProperties }; diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h index 2cc41e1..d6f4dc5 100644 --- a/src/gui/text/qfont.h +++ b/src/gui/text/qfont.h @@ -226,7 +226,10 @@ public: bool operator<(const QFont &) const; operator QVariant() const; bool isCopyOf(const QFont &) const; - +#ifdef Q_COMPILER_RVALUE_REFS + inline QFont &operator=(QFont &&other) + { qSwap(d, other.d); return *this; } +#endif #ifdef Q_WS_WIN HFONT handle() const; @@ -315,6 +318,7 @@ private: friend class QPainterReplayer; friend class QPaintBufferEngine; friend class QCommandLinkButtonPrivate; + friend class QFontEngine; #ifndef QT_NO_DATASTREAM friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QFont &); diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h index 470c109..646a8b8 100644 --- a/src/gui/text/qfont_p.h +++ b/src/gui/text/qfont_p.h @@ -192,6 +192,11 @@ public: QFont smallCapsFont() const { return QFont(smallCapsFontPrivate()); } QFontPrivate *smallCapsFontPrivate() const; + static QFontPrivate *get(const QFont &font) + { + return font.d.data(); + } + void resolve(uint mask, const QFontPrivate *other); private: QFontPrivate &operator=(const QFontPrivate &) { return *this; } diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index e6c36a4..2b26638 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -75,10 +75,6 @@ # define FM_DEBUG if (false) qDebug #endif -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) -# define for if(0){}else for -#endif - QT_BEGIN_NAMESPACE #define SMOOTH_SCALABLE 0xffff diff --git a/src/gui/text/qfontdatabase_mac.cpp b/src/gui/text/qfontdatabase_mac.cpp index 5a9fc35..712bdb4 100644 --- a/src/gui/text/qfontdatabase_mac.cpp +++ b/src/gui/text/qfontdatabase_mac.cpp @@ -293,8 +293,12 @@ void QFontDatabase::load(const QFontPrivate *d, int script) // previous versions family_list << QApplication::font().defaultFamily(); +#if defined(QT_MAC_USE_COCOA) + QCFString fontName = NULL, familyName = NULL; +#else ATSFontFamilyRef familyRef = 0; ATSFontRef fontRef = 0; +#endif QMutexLocker locker(fontDatabaseMutex()); QFontDatabasePrivate *db = privateDb(); @@ -304,26 +308,20 @@ void QFontDatabase::load(const QFontPrivate *d, int script) for (int k = 0; k < db->count; ++k) { if (db->families[k]->name.compare(family_list.at(i), Qt::CaseInsensitive) == 0) { QByteArray family_name = db->families[k]->name.toUtf8(); +#if defined(QT_MAC_USE_COCOA) + QCFType<CTFontRef> ctFont = CTFontCreateWithName(QCFString(db->families[k]->name), 12, NULL); + if (ctFont) { + fontName = CTFontCopyFullName(ctFont); + familyName = CTFontCopyFamilyName(ctFont); + goto FamilyFound; + } +#else familyRef = ATSFontFamilyFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault); if (familyRef) { fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault); goto FamilyFound; - } else { -#if defined(QT_MAC_USE_COCOA) - // ATS and CT disagrees on what the family name should be, - // use CT to look up the font if ATS fails. - QCFString familyName = QString::fromAscii(family_name); - QCFType<CTFontRef> CTfontRef = CTFontCreateWithName(familyName, 12, NULL); - QCFType<CTFontDescriptorRef> fontDescriptor = CTFontCopyFontDescriptor(CTfontRef); - QCFString displayName = (CFStringRef)CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontDisplayNameAttribute); - - familyRef = ATSFontFamilyFindFromName(displayName, kATSOptionFlagsDefault); - if (familyRef) { - fontRef = ATSFontFindFromName(displayName, kATSOptionFlagsDefault); - goto FamilyFound; - } -#endif } +#endif } } } @@ -331,92 +329,18 @@ FamilyFound: //fill in the engine's font definition QFontDef fontDef = d->request; //copy.. if(fontDef.pointSize < 0) - fontDef.pointSize = qt_mac_pointsize(fontDef, d->dpi); + fontDef.pointSize = qt_mac_pointsize(fontDef, d->dpi); else - fontDef.pixelSize = qt_mac_pixelsize(fontDef, d->dpi); -#if 0 - ItemCount name_count; - if(ATSUCountFontNames(fontID, &name_count) == noErr && name_count) { - ItemCount actualName_size; - if(ATSUGetIndFontName(fontID, 0, 0, 0, &actualName_size, 0, 0, 0, 0) == noErr && actualName_size) { - QByteArray actualName(actualName_size); - if(ATSUGetIndFontName(fontID, 0, actualName_size, actualName.data(), &actualName_size, 0, 0, 0, 0) == noErr && actualName_size) - fontDef.family = QString::fromUtf8(actualName); - } - } -#else - { - QCFString actualName; - if(ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr) - fontDef.family = actualName; - } -#endif + fontDef.pixelSize = qt_mac_pixelsize(fontDef, d->dpi); #ifdef QT_MAC_USE_COCOA - QFontEngine *engine = new QCoreTextFontEngineMulti(familyRef, fontRef, fontDef, d->kerning); -#elif 1 - QFontEngine *engine = new QFontEngineMacMulti(familyRef, fontRef, fontDef, d->kerning); + fontDef.family = familyName; + QFontEngine *engine = new QCoreTextFontEngineMulti(fontName, fontDef, d->kerning); #else - ATSFontFamilyRef atsFamily = familyRef; - ATSFontFamilyRef atsFontRef = fontRef; - - FMFont fontID; - FMFontFamily fmFamily; - FMFontStyle fntStyle = 0; - fmFamily = FMGetFontFamilyFromATSFontFamilyRef(atsFamily); - if (fmFamily == kInvalidFontFamily) { - // Use the ATSFont then... - fontID = FMGetFontFromATSFontRef(atsFontRef); - } else { - if (fontDef.weight >= QFont::Bold) - fntStyle |= ::bold; - if (fontDef.style != QFont::StyleNormal) - fntStyle |= ::italic; - - FMFontStyle intrinsicStyle; - FMFont fnt = 0; - if (FMGetFontFromFontFamilyInstance(fmFamily, fntStyle, &fnt, &intrinsicStyle) == noErr) - fontID = FMGetATSFontRefFromFont(fnt); - } - - OSStatus status; - - const int maxAttributeCount = 5; - ATSUAttributeTag tags[maxAttributeCount + 1]; - ByteCount sizes[maxAttributeCount + 1]; - ATSUAttributeValuePtr values[maxAttributeCount + 1]; - int attributeCount = 0; - - Fixed size = FixRatio(fontDef.pixelSize, 1); - tags[attributeCount] = kATSUSizeTag; - sizes[attributeCount] = sizeof(size); - values[attributeCount] = &size; - ++attributeCount; - - tags[attributeCount] = kATSUFontTag; - sizes[attributeCount] = sizeof(fontID); - values[attributeCount] = &fontID; - ++attributeCount; - - CGAffineTransform transform = CGAffineTransformIdentity; - if (fontDef.stretch != 100) { - transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); - tags[attributeCount] = kATSUFontMatrixTag; - sizes[attributeCount] = sizeof(transform); - values[attributeCount] = &transform; - ++attributeCount; - } - - ATSUStyle style; - status = ATSUCreateStyle(&style); - Q_ASSERT(status == noErr); - - Q_ASSERT(attributeCount < maxAttributeCount + 1); - status = ATSUSetAttributes(style, attributeCount, tags, sizes, values); - Q_ASSERT(status == noErr); - - QFontEngine *engine = new QFontEngineMac(style, fontID, fontDef, /*multiEngine*/ 0); - ATSUDisposeStyle(style); + QCFString actualName; + if (ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr) + fontDef.family = actualName; + QFontEngine *engine = new QFontEngineMacMulti(familyRef, fontRef, fontDef, d->kerning); #endif d->engineData->engine = engine; engine->ref.ref(); //a ref for the engineData->engine diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 0dfd295..70b7d65 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -185,10 +185,6 @@ QFontEngine::QFontEngine() QFontEngine::~QFontEngine() { - for (QLinkedList<GlyphCacheEntry>::const_iterator it = m_glyphCaches.constBegin(), - end = m_glyphCaches.constEnd(); it != end; ++it) { - delete it->cache; - } m_glyphCaches.clear(); qHBFreeFace(hbFace); } @@ -242,6 +238,24 @@ glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix return metrics; } +QFont QFontEngine::createExplicitFont() const +{ + return createExplicitFontWithName(fontDef.family); +} + +QFont QFontEngine::createExplicitFontWithName(const QString &familyName) const +{ + QFont font(familyName); + font.setStyleStrategy(QFont::NoFontMerging); + font.setWeight(fontDef.weight); + font.setItalic(fontDef.style == QFont::StyleItalic); + if (fontDef.pointSize < 0) + font.setPixelSize(fontDef.pixelSize); + else + font.setPointSizeF(fontDef.pointSize); + return font; +} + QFixed QFontEngine::xHeight() const { QGlyphLayoutArray<8> glyphs; @@ -602,7 +616,7 @@ QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &t) return i; } -QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, int /* margin */, const QTransform &t) +QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed /*subPixelPosition*/, int /* margin */, const QTransform &t) { QImage alphaMask = alphaMapForGlyph(glyph, t); QImage rgbMask(alphaMask.width(), alphaMask.height(), QImage::Format_RGB32); @@ -716,14 +730,16 @@ void QFontEngine::setGlyphCache(void *key, QFontEngineGlyphCache *data) { Q_ASSERT(data); - GlyphCacheEntry entry = { key, data }; + GlyphCacheEntry entry; + entry.context = key; + entry.cache = data; if (m_glyphCaches.contains(entry)) return; // Limit the glyph caches to 4. This covers all 90 degree rotations and limits // memory use when there is continuous or random rotation if (m_glyphCaches.size() == 4) - delete m_glyphCaches.takeLast().cache; + m_glyphCaches.removeLast(); m_glyphCaches.push_front(entry); @@ -732,7 +748,7 @@ void QFontEngine::setGlyphCache(void *key, QFontEngineGlyphCache *data) QFontEngineGlyphCache *QFontEngine::glyphCache(void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const { for (QLinkedList<GlyphCacheEntry>::const_iterator it = m_glyphCaches.constBegin(), end = m_glyphCaches.constEnd(); it != end; ++it) { - QFontEngineGlyphCache *c = it->cache; + QFontEngineGlyphCache *c = it->cache.data(); if (key == it->context && type == c->cacheType() && qtransform_equals_no_translate(c->m_transform, transform)) { diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index a9b25f5..5e86b37 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -763,9 +763,18 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph return g; int load_flags = FT_LOAD_DEFAULT | default_load_flags; + int load_target = default_hint_style == HintLight + ? FT_LOAD_TARGET_LIGHT + : FT_LOAD_TARGET_NORMAL; + if (set->outline_drawing) load_flags = FT_LOAD_NO_BITMAP; + if (default_hint_style == HintNone) + load_flags |= FT_LOAD_NO_HINTING; + else + load_flags |= load_target; + // apply our matrix to this, but note that the metrics will not be affected by this. FT_Face face = lockFace(); FT_Matrix matrix = this->matrix; @@ -1869,10 +1878,10 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g) return img; } -QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, int margin, const QTransform &t) +QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, int margin, const QTransform &t) { if (t.type() > QTransform::TxTranslate) - return QFontEngine::alphaRGBMapForGlyph(g, margin, t); + return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t); lockFace(); @@ -1881,7 +1890,7 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, int margin, const QTransfor Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, glyph_format); if (!glyph) { unlockFace(); - return QFontEngine::alphaRGBMapForGlyph(g, margin, t); + return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t); } QImage img(glyph->width, glyph->height, QImage::Format_RGB32); diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index 2f05a8b..72f7d9f 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -241,7 +241,7 @@ private: virtual void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const; virtual QImage alphaMapForGlyph(glyph_t); - virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t); + virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t); virtual void removeGlyphFromCache(glyph_t glyph); virtual int glyphCount() const; diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index bdf3848..6e524f6 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -143,7 +143,7 @@ void qmacfontengine_gamma_correct(QImage *image) #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 -QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &, const ATSFontRef &atsFontRef, const QFontDef &fontDef, bool kerning) +QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning) : QFontEngineMulti(0) { this->fontDef = fontDef; @@ -159,9 +159,6 @@ QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &, con break; } - QCFString name; - ATSFontGetName(atsFontRef, kATSOptionFlagsDefault, &name); - transform = CGAffineTransformIdentity; if (fontDef.stretch != 100) { transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); @@ -422,8 +419,7 @@ QCoreTextFontEngine::QCoreTextFontEngine(CTFontRef font, const QFontDef &def, synthesisFlags = 0; ctfont = font; CFRetain(ctfont); - ATSFontRef atsfont = CTFontGetPlatformFont(ctfont, 0); - cgFont = CGFontCreateWithPlatformFont(&atsfont); + cgFont = CTFontCopyGraphicsFont(ctfont, NULL); CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctfont); if (fontDef.weight >= QFont::Bold && !(traits & kCTFontBoldTrait)) { synthesisFlags |= SynthesizedBold; @@ -443,8 +439,8 @@ QCoreTextFontEngine::QCoreTextFontEngine(CTFontRef font, const QFontDef &def, QCoreTextFontEngine::~QCoreTextFontEngine() { - CFRelease(ctfont); CFRelease(cgFont); + CFRelease(ctfont); } bool QCoreTextFontEngine::stringToCMap(const QChar *, int, QGlyphLayout *, int *, QTextEngine::ShaperFlags) const @@ -657,7 +653,13 @@ void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *position } } -QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, int margin, bool aa) +QFont QCoreTextFontEngine::createExplicitFont() const +{ + QString familyName = QCFString::toQString(CTFontCopyFamilyName(ctfont)); + return createExplicitFontWithName(familyName); +} + +QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, int /*margin*/, bool aa) { const glyph_metrics_t br = boundingBox(glyph); QImage im(qRound(br.width)+2, qRound(br.height)+2, QImage::Format_RGB32); @@ -690,11 +692,10 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, int margin, bool aa) CGContextSetRGBFillColor(ctx, 1, 1, 1, 1); CGContextSetTextDrawingMode(ctx, kCGTextFill); - ATSFontRef atsfont = CTFontGetPlatformFont(ctfont, 0); - QCFType<CGFontRef> cgFont = CGFontCreateWithPlatformFont(&atsfont); CGContextSetFont(ctx, cgFont); - qreal pos_x = -br.x.toReal()+1, pos_y = im.height()+br.y.toReal(); + qreal pos_x = -br.x.toReal() + subPixelPosition.toReal(); + qreal pos_y = im.height()+br.y.toReal(); CGContextSetTextPosition(ctx, pos_x, pos_y); CGSize advance; @@ -715,7 +716,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, int margin, bool aa) QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph) { - QImage im = imageForGlyph(glyph, 0, false); + QImage im = imageForGlyph(glyph, QFixed(), 0, false); QImage indexed(im.width(), im.height(), QImage::Format_Indexed8); QVector<QRgb> colors(256); @@ -736,12 +737,12 @@ QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph) return indexed; } -QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, int margin, const QTransform &x) +QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPosition, int margin, const QTransform &x) { if (x.type() >= QTransform::TxScale) - return QFontEngine::alphaRGBMapForGlyph(glyph, margin, x); + return QFontEngine::alphaRGBMapForGlyph(glyph, subPixelPosition, margin, x); - QImage im = imageForGlyph(glyph, margin, true); + QImage im = imageForGlyph(glyph, subPixelPosition, margin, true); qmacfontengine_gamma_correct(&im); return im; } @@ -1420,6 +1421,7 @@ static inline unsigned int getChar(const QChar *str, int &i, const int len) return uc; } +// Not used directly for shaping, only used to calculate m_averageCharWidth bool QFontEngineMac::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const { if (!cmap) { @@ -1592,6 +1594,27 @@ static void addGlyphsToPathHelper(ATSUStyle style, glyph_t *glyphs, QFixedPoint DisposeATSCubicClosePathUPP(closePath); } +QFont QFontEngineMac::createExplicitFont() const +{ + FMFont fmFont = FMGetFontFromATSFontRef(fontID); + + FMFontFamily fmFamily; + FMFontStyle fmStyle; + QString familyName; + if (!FMGetFontFamilyInstanceFromFont(fmFont, &fmFamily, &fmStyle)) { + ATSFontFamilyRef familyRef = FMGetATSFontFamilyRefFromFontFamily(fmFamily); + QCFString cfFamilyName;; + ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &cfFamilyName); + familyName = cfFamilyName; + } else { + QCFString cfFontName; + ATSFontGetName(fontID, kATSOptionFlagsDefault, &cfFontName); + familyName = cfFontName; + } + + return createExplicitFontWithName(familyName); +} + void QFontEngineMac::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags) { @@ -1678,7 +1701,7 @@ QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph) return indexed; } -QImage QFontEngineMac::alphaRGBMapForGlyph(glyph_t glyph, int margin, const QTransform &t) +QImage QFontEngineMac::alphaRGBMapForGlyph(glyph_t glyph, QFixed, int margin, const QTransform &t) { QImage im = imageForGlyph(glyph, margin, true); diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 3b91cd8..b3a6c59 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -155,6 +155,7 @@ public: SynthesizedStretch = 0x4 }; virtual int synthesized() const { return 0; } + virtual bool supportsSubPixelPositions() const { return false; } virtual QFixed emSquareSize() const { return ascent(); } @@ -173,6 +174,10 @@ public: #endif virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, QPainterPath *path, QTextItem::RenderFlags flags); + + /* Creates a QFont object to represent this particular QFontEngine */ + virtual QFont createExplicitFont() const; + void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags, QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions); @@ -184,7 +189,7 @@ public: */ virtual QImage alphaMapForGlyph(glyph_t); virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t); - virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t); + virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t); virtual void removeGlyphFromCache(glyph_t); @@ -252,13 +257,14 @@ public: int glyphFormat; protected: + QFont createExplicitFontWithName(const QString &familyName) const; static const QVector<QRgb> &grayPalette(); QFixed lastRightBearing(const QGlyphLayout &glyphs, bool round = false); private: struct GlyphCacheEntry { void *context; - QFontEngineGlyphCache *cache; + QExplicitlySharedDataPointer<QFontEngineGlyphCache> cache; bool operator==(const GlyphCacheEntry &other) { return context == other.context && cache == other.cache; } }; @@ -443,6 +449,7 @@ public: virtual bool canRender(const QChar *string, int len); virtual int synthesized() const { return synthesisFlags; } + virtual bool supportsSubPixelPositions() const { return true; } virtual Type type() const { return QFontEngine::Mac; } @@ -452,13 +459,13 @@ public: virtual bool getSfntTableData(uint /*tag*/, uchar * /*buffer*/, uint * /*length*/) const; virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics); virtual QImage alphaMapForGlyph(glyph_t); - virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t); + virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t); virtual qreal minRightBearing() const; virtual qreal minLeftBearing() const; - + virtual QFont createExplicitFont() const; private: - QImage imageForGlyph(glyph_t glyph, int margin, bool colorful); + QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, int margin, bool colorful); CTFontRef ctfont; CGFontRef cgFont; QCoreTextFontEngineMulti *parentEngine; @@ -470,8 +477,7 @@ private: class QCoreTextFontEngineMulti : public QFontEngineMulti { public: - QCoreTextFontEngineMulti(const ATSFontFamilyRef &atsFamily, const ATSFontRef &atsFontRef, - const QFontDef &fontDef, bool kerning); + QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning); ~QCoreTextFontEngineMulti(); virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, @@ -521,6 +527,8 @@ public: virtual qreal maxCharWidth() const; virtual QFixed averageCharWidth() const; + virtual QFont createExplicitFont() const; + virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags); @@ -539,7 +547,7 @@ public: virtual Properties properties() const; virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics); virtual QImage alphaMapForGlyph(glyph_t); - virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t); + virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t); private: QImage imageForGlyph(glyph_t glyph, int margin, bool colorful); diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp index 5980f20..e9dcfa0 100644 --- a/src/gui/text/qfontengine_s60.cpp +++ b/src/gui/text/qfontengine_s60.cpp @@ -122,7 +122,8 @@ QByteArray QSymbianTypeFaceExtras::getSfntTable(uint tag) const Q_ASSERT(m_trueTypeExtension->HasTrueTypeTable(tag)); TInt error = KErrNone; TInt tableByteLength = 0; - TAny *table = q_check_ptr(m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength)); + TAny *table = m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength); + Q_CHECK_PTR(table); QByteArray result(static_cast<const char*>(table), tableByteLength); m_trueTypeExtension->ReleaseTrueTypeTable(table); return result; @@ -136,8 +137,8 @@ bool QSymbianTypeFaceExtras::getSfntTableData(uint tag, uchar *buffer, uint *len bool result = true; TInt error = KErrNone; TInt tableByteLength; - TAny *table = - q_check_ptr(m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength)); + TAny *table = m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength); + Q_CHECK_PTR(table); if (error != KErrNone) { return false; diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp index ef1b504..3006776 100644 --- a/src/gui/text/qfontengine_win.cpp +++ b/src/gui/text/qfontengine_win.cpp @@ -1254,7 +1254,7 @@ QImage QFontEngineWin::alphaMapForGlyph(glyph_t glyph, const QTransform &xform) #define SPI_GETFONTSMOOTHINGCONTRAST 0x200C #define SPI_SETFONTSMOOTHINGCONTRAST 0x200D -QImage QFontEngineWin::alphaRGBMapForGlyph(glyph_t glyph, int margin, const QTransform &t) +QImage QFontEngineWin::alphaRGBMapForGlyph(glyph_t glyph, QFixed, int margin, const QTransform &t) { HFONT font = hfont; diff --git a/src/gui/text/qfontengine_win_p.h b/src/gui/text/qfontengine_win_p.h index 68b53b5..d86f42e 100644 --- a/src/gui/text/qfontengine_win_p.h +++ b/src/gui/text/qfontengine_win_p.h @@ -104,7 +104,7 @@ public: virtual QImage alphaMapForGlyph(glyph_t t) { return alphaMapForGlyph(t, QTransform()); } virtual QImage alphaMapForGlyph(glyph_t, const QTransform &xform); - virtual QImage alphaRGBMapForGlyph(glyph_t t, int margin, const QTransform &xform); + virtual QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform); #ifndef Q_CC_MINGW virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0); diff --git a/src/gui/text/qfontengine_x11.cpp b/src/gui/text/qfontengine_x11.cpp index b7e4be2..aee21f6 100644 --- a/src/gui/text/qfontengine_x11.cpp +++ b/src/gui/text/qfontengine_x11.cpp @@ -992,7 +992,7 @@ QFontEngineX11FT::QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int s face_id.filename = file_name; face_id.index = face_index; - canUploadGlyphsToServer = qApp->thread() == QThread::currentThread(); + canUploadGlyphsToServer = QApplication::testAttribute(Qt::AA_X11InitThreads) || (qApp->thread() == QThread::currentThread()); subpixelType = Subpixel_None; if (antialias) { diff --git a/src/gui/text/qfontengineglyphcache_p.h b/src/gui/text/qfontengineglyphcache_p.h index 7b82b46..eba16f7 100644 --- a/src/gui/text/qfontengineglyphcache_p.h +++ b/src/gui/text/qfontengineglyphcache_p.h @@ -72,7 +72,7 @@ QT_BEGIN_NAMESPACE -class QFontEngineGlyphCache +class QFontEngineGlyphCache: public QSharedData { public: enum Type { diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index d02e841..f2591ce 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -443,6 +443,21 @@ bool QFontMetrics::inFont(QChar ch) const } /*! + Returns true if the character encoded in UCS-4/UTF-32 is a valid + character in the font; otherwise returns false. +*/ +bool QFontMetrics::inFontUcs4(uint ucs4) const +{ + const int script = QUnicodeTables::script(ucs4); + QFontEngine *engine = d->engineForScript(script); + Q_ASSERT(engine != 0); + if (engine->type() == QFontEngine::Box) + return false; + QString utf16 = QString::fromUcs4(&ucs4, 1); + return engine->canRender(utf16.data(), utf16.length()); +} + +/*! Returns the left bearing of character \a ch in the font. The left bearing is the right-ward distance of the left-most pixel @@ -1315,6 +1330,21 @@ bool QFontMetricsF::inFont(QChar ch) const } /*! + Returns true if the character encoded in UCS-4/UTF-32 is a valid + character in the font; otherwise returns false. +*/ +bool QFontMetricsF::inFontUcs4(uint ucs4) const +{ + const int script = QUnicodeTables::script(ucs4); + QFontEngine *engine = d->engineForScript(script); + Q_ASSERT(engine != 0); + if (engine->type() == QFontEngine::Box) + return false; + QString utf16 = QString::fromUcs4(&ucs4, 1); + return engine->canRender(utf16.data(), utf16.length()); +} + +/*! Returns the left bearing of character \a ch in the font. The left bearing is the right-ward distance of the left-most pixel @@ -1779,7 +1809,7 @@ qreal QFontMetricsF::lineWidth() const Use the boundingRect() function in combination with QString::left() instead. - + \oldcode QRect rect = boundingRect(text, len); \newcode diff --git a/src/gui/text/qfontmetrics.h b/src/gui/text/qfontmetrics.h index 2518b54..5a79429 100644 --- a/src/gui/text/qfontmetrics.h +++ b/src/gui/text/qfontmetrics.h @@ -71,6 +71,10 @@ public: ~QFontMetrics(); QFontMetrics &operator=(const QFontMetrics &); +#ifdef Q_COMPILER_RVALUE_REFS + inline QFontMetrics &operator=(QFontMetrics &&other) + { qSwap(d, other.d); return *this; } +#endif int ascent() const; int descent() const; @@ -85,6 +89,7 @@ public: int averageCharWidth() const; bool inFont(QChar) const; + bool inFontUcs4(uint ucs4) const; int leftBearing(QChar) const; int rightBearing(QChar) const; @@ -148,7 +153,10 @@ public: QFontMetricsF &operator=(const QFontMetricsF &); QFontMetricsF &operator=(const QFontMetrics &); - +#ifdef Q_COMPILER_RVALUE_REFS + inline QFontMetricsF &operator=(QFontMetricsF &&other) + { qSwap(d, other.d); return *this; } +#endif qreal ascent() const; qreal descent() const; qreal height() const; @@ -162,6 +170,7 @@ public: qreal averageCharWidth() const; bool inFont(QChar) const; + bool inFontUcs4(uint ucs4) const; qreal leftBearing(QChar) const; qreal rightBearing(QChar) const; diff --git a/src/gui/text/qglyphs.cpp b/src/gui/text/qglyphs.cpp new file mode 100644 index 0000000..2447752 --- /dev/null +++ b/src/gui/text/qglyphs.cpp @@ -0,0 +1,240 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qglyphs.h" +#include "qglyphs_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QGlyphs + \brief the QGlyphs class provides direct access to the internal glyphs in a font + \since 4.8 + + \ingroup text + \mainclass + + When Qt displays a string of text encoded in Unicode, it will first convert the Unicode points + into a list of glyph indexes and a list of positions based on one or more fonts. The Unicode + representation of the text and the QFont object will in this case serve as a convenient + abstraction that hides the details of what actually takes place when displaying the text + on-screen. For instance, by the time the text actually reaches the screen, it may be represented + by a set of fonts in addition to the one specified by the user, e.g. in case the originally + selected font did not support all the writing systems contained in the text. + + Under certain circumstances, it can be useful as an application developer to have more low-level + control over which glyphs in a specific font are drawn to the screen. This could for instance + be the case in applications that use an external font engine and text shaper together with Qt. + QGlyphs provides an interface to the raw data needed to get text on the screen. It + contains a list of glyph indexes, a position for each glyph and a font. + + It is the user's responsibility to ensure that the selected font actually contains the + provided glyph indexes. + + QTextLayout::glyphs() can be used to convert unicode encoded text into a list of QGlyphs + objects, and QPainter::drawGlyphs() can be used to draw the glyphs. +*/ + + +/*! + Constructs an empty QGlyphs object. +*/ +QGlyphs::QGlyphs() : d(new QGlyphsPrivate) +{ +} + +/*! + Constructs a QGlyphs object which is a copy of \a other. +*/ +QGlyphs::QGlyphs(const QGlyphs &other) +{ + d = other.d; +} + +/*! + Destroys the QGlyphs. +*/ +QGlyphs::~QGlyphs() +{ + // Required for QExplicitlySharedDataPointer +} + +/*! + \internal +*/ +void QGlyphs::detach() +{ + if (d->ref != 1) + d.detach(); +} + +/*! + Assigns \a other to this QGlyphs object. +*/ +QGlyphs &QGlyphs::operator=(const QGlyphs &other) +{ + d = other.d; + return *this; +} + +/*! + Compares \a other to this QGlyphs object. Returns true if the list of glyph indexes, + the list of positions and the font are all equal, otherwise returns false. +*/ +bool QGlyphs::operator==(const QGlyphs &other) const +{ + return ((d == other.d) + || (d->glyphIndexes == other.d->glyphIndexes + && d->glyphPositions == other.d->glyphPositions + && d->font == other.d->font)); +} + +/*! + Compares \a other to this QGlyphs object. Returns true if any of the list of glyph + indexes, the list of positions or the font are different, otherwise returns false. +*/ +bool QGlyphs::operator!=(const QGlyphs &other) const +{ + return !(*this == other); +} + +/*! + \internal + + Adds together the lists of glyph indexes and positions in \a other and this QGlyphs + object and returns the result. The font in the returned QGlyphs will be the same as in + this QGlyphs object. +*/ +QGlyphs QGlyphs::operator+(const QGlyphs &other) const +{ + QGlyphs ret(*this); + ret += other; + return ret; +} + +/*! + \internal + + Appends the glyph indexes and positions in \a other to this QGlyphs object and returns + a reference to the current object. +*/ +QGlyphs &QGlyphs::operator+=(const QGlyphs &other) +{ + detach(); + + d->glyphIndexes += other.d->glyphIndexes; + d->glyphPositions += other.d->glyphPositions; + + return *this; +} + +/*! + Returns the font selected for this QGlyphs object. + + \sa setFont() +*/ +QFont QGlyphs::font() const +{ + return d->font; +} + +/*! + Sets the font in which to look up the glyph indexes to \a font. This must be an explicitly + resolvable font which defines glyphs for the specified glyph indexes. + + \sa font(), setGlyphIndexes() +*/ +void QGlyphs::setFont(const QFont &font) +{ + detach(); + d->font = font; +} + +/*! + Returns the glyph indexes for this QGlyphs object. + + \sa setGlyphIndexes(), setPositions() +*/ +QVector<quint32> QGlyphs::glyphIndexes() const +{ + return d->glyphIndexes; +} + +/*! + Set the glyph indexes for this QGlyphs object to \a glyphIndexes. The glyph indexes must + be valid for the selected font. +*/ +void QGlyphs::setGlyphIndexes(const QVector<quint32> &glyphIndexes) +{ + detach(); + d->glyphIndexes = glyphIndexes; +} + +/*! + Returns the position of the edge of the baseline for each glyph in this set of glyph indexes. +*/ +QVector<QPointF> QGlyphs::positions() const +{ + return d->glyphPositions; +} + +/*! + Sets the positions of the edge of the baseline for each glyph in this set of glyph indexes to + \a positions. +*/ +void QGlyphs::setPositions(const QVector<QPointF> &positions) +{ + detach(); + d->glyphPositions = positions; +} + +/*! + Clears all data in the QGlyphs object. +*/ +void QGlyphs::clear() +{ + detach(); + d->glyphPositions = QVector<QPointF>(); + d->glyphIndexes = QVector<quint32>(); + d->font = QFont(); +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qglyphs.h b/src/gui/text/qglyphs.h new file mode 100644 index 0000000..282ecb4 --- /dev/null +++ b/src/gui/text/qglyphs.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGLYPHS_H +#define QGLYPHS_H + +#include <QtCore/qsharedpointer.h> +#include <QtCore/qvector.h> +#include <QtCore/qpoint.h> +#include <QtGui/qfont.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QGlyphsPrivate; +class Q_GUI_EXPORT QGlyphs +{ +public: + QGlyphs(); + QGlyphs(const QGlyphs &other); + ~QGlyphs(); + + QFont font() const; + void setFont(const QFont &font); + + QVector<quint32> glyphIndexes() const; + void setGlyphIndexes(const QVector<quint32> &glyphIndexes); + + QVector<QPointF> positions() const; + void setPositions(const QVector<QPointF> &positions); + + void clear(); + + QGlyphs &operator=(const QGlyphs &other); + bool operator==(const QGlyphs &other) const; + bool operator!=(const QGlyphs &other) const; + +private: + friend class QGlyphsPrivate; + friend class QTextLine; + + QGlyphs operator+(const QGlyphs &other) const; + QGlyphs &operator+=(const QGlyphs &other); + + void detach(); + QExplicitlySharedDataPointer<QGlyphsPrivate> d; + +}; + +QT_END_NAMESPACE + +QT_END_HEADER + + +#endif // QGLYPHS_H diff --git a/src/gui/text/qglyphs_p.h b/src/gui/text/qglyphs_p.h new file mode 100644 index 0000000..c39f5d0 --- /dev/null +++ b/src/gui/text/qglyphs_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGLYPHS_P_H +#define QGLYPHS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include <qfont.h> +#include "qglyphs.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGlyphsPrivate: public QSharedData +{ +public: + QGlyphsPrivate() + { + } + + QGlyphsPrivate(const QGlyphsPrivate &other) + : QSharedData(other), glyphIndexes(other.glyphIndexes), glyphPositions(other.glyphPositions), font(other.font) + { + } + + QVector<quint32> glyphIndexes; + QVector<QPointF> glyphPositions; + QFont font; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGLYPHS_P_H diff --git a/src/gui/text/qpfutil.cpp b/src/gui/text/qpfutil.cpp index 376f49c..7f8c58e 100644 --- a/src/gui/text/qpfutil.cpp +++ b/src/gui/text/qpfutil.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -static QFontEngineQPF::TagType tagTypes[QFontEngineQPF::NumTags] = { +static const QFontEngineQPF::TagType tagTypes[QFontEngineQPF::NumTags] = { QFontEngineQPF::StringType, // FontName QFontEngineQPF::StringType, // FileName QFontEngineQPF::UInt32Type, // FileIndex diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 5fe0c0c..441a8c8 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -2900,7 +2900,7 @@ QAbstractTextDocumentLayout::PaintContext QTextControl::getPaintContext(QWidget if (widget) style = widget->style(); style->styleHint(QStyle::SH_TextControl_FocusIndicatorTextCharFormat, &opt, widget, &ret); - selection.format = qVariantValue<QTextFormat>(ret.variant).toCharFormat(); + selection.format = qvariant_cast<QTextFormat>(ret.variant).toCharFormat(); } else { QPalette::ColorGroup cg = d->hasFocus ? QPalette::Active : QPalette::Inactive; selection.format.setBackground(ctx.palette.brush(cg, QPalette::Highlight)); diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index c35069f..3aa6795 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -1983,6 +1983,8 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name) if (fi.exists()) { resourceUrl = QUrl::fromLocalFile(fi.absolutePath() + QDir::separator()).resolved(name); + } else if (currentURL.isEmpty()) { + resourceUrl.setScheme(QLatin1String("file")); } } @@ -2600,14 +2602,40 @@ void QTextHtmlExporter::emitBlock(const QTextBlock &block) default: html += QLatin1String("<ul"); // ### should not happen } - html += QLatin1String(" style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px;"); + QString styleString = QString::fromLatin1("margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px;"); if (format.hasProperty(QTextFormat::ListIndent)) { - html += QLatin1String(" -qt-list-indent: "); - html += QString::number(format.indent()); - html += QLatin1Char(';'); + styleString += QLatin1String(" -qt-list-indent: "); + styleString += QString::number(format.indent()); + styleString += QLatin1Char(';'); + } + + if (format.hasProperty(QTextFormat::ListNumberPrefix)) { + QString numberPrefix = format.numberPrefix(); + numberPrefix.replace('"', "\\22"); + numberPrefix.replace('\'', "\\27"); // FIXME: There's a problem in the CSS parser the prevents this from being correctly restored + styleString += QLatin1String(" -qt-list-number-prefix: "); + styleString += QLatin1Char('\''); + styleString += numberPrefix; + styleString += QLatin1Char('\''); + styleString += QLatin1Char(';'); } + if (format.hasProperty(QTextFormat::ListNumberSuffix)) { + if (format.numberSuffix() != QLatin1String(".")) { // this is our default + QString numberSuffix = format.numberSuffix(); + numberSuffix.replace('"', "\\22"); + numberSuffix.replace('\'', "\\27"); // see above + styleString += QLatin1String(" -qt-list-number-suffix: "); + styleString += QLatin1Char('\''); + styleString += numberSuffix; + styleString += QLatin1Char('\''); + styleString += QLatin1Char(';'); + } + } + + html += QLatin1String(" style=\""); + html += styleString; html += QLatin1String("\">"); } diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp index 7c5f973..d2e2c9f 100644 --- a/src/gui/text/qtextdocumentfragment.cpp +++ b/src/gui/text/qtextdocumentfragment.cpp @@ -683,6 +683,10 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processSpecialNodes() QTextListFormat listFmt; listFmt.setStyle(style); + if (!currentNode->textListNumberPrefix.isNull()) + listFmt.setNumberPrefix(currentNode->textListNumberPrefix); + if (!currentNode->textListNumberSuffix.isNull()) + listFmt.setNumberSuffix(currentNode->textListNumberSuffix); ++indent; if (currentNode->hasCssListIndent) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 05de8f5..34d9fa6 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1389,6 +1389,7 @@ void QTextEngine::invalidate() maxWidth = 0; if (specialData) specialData->resolvedFormatIndices.clear(); + feCache.reset(); } void QTextEngine::clearLineData() @@ -1780,6 +1781,13 @@ QFont QTextEngine::font(const QScriptItem &si) const return font; } +QTextEngine::FontEngineCache::FontEngineCache() +{ + reset(); +} + +//we cache the previous results of this function, as calling it numerous times with the same effective +//input is common (and hard to cache at a higher level) QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFixed *descent, QFixed *leading) const { QFontEngine *engine = 0; @@ -1788,28 +1796,47 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix QFont font = fnt; if (hasFormats()) { - QTextCharFormat f = format(&si); - font = f.font(); - - if (block.docHandle() && block.docHandle()->layout()) { - // Make sure we get the right dpi on printers - QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); - if (pdev) - font = QFont(font, pdev); + if (feCache.prevFontEngine && feCache.prevPosition == si.position && feCache.prevLength == length(&si) && feCache.prevScript == script) { + engine = feCache.prevFontEngine; + scaledEngine = feCache.prevScaledFontEngine; } else { - font = font.resolve(fnt); - } - engine = font.d->engineForScript(script); - QTextCharFormat::VerticalAlignment valign = f.verticalAlignment(); - if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) { - if (font.pointSize() != -1) - font.setPointSize((font.pointSize() * 2) / 3); - else - font.setPixelSize((font.pixelSize() * 2) / 3); - scaledEngine = font.d->engineForScript(script); + QTextCharFormat f = format(&si); + font = f.font(); + + if (block.docHandle() && block.docHandle()->layout()) { + // Make sure we get the right dpi on printers + QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); + if (pdev) + font = QFont(font, pdev); + } else { + font = font.resolve(fnt); + } + engine = font.d->engineForScript(script); + QTextCharFormat::VerticalAlignment valign = f.verticalAlignment(); + if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) { + if (font.pointSize() != -1) + font.setPointSize((font.pointSize() * 2) / 3); + else + font.setPixelSize((font.pixelSize() * 2) / 3); + scaledEngine = font.d->engineForScript(script); + } + feCache.prevFontEngine = engine; + feCache.prevScaledFontEngine = scaledEngine; + feCache.prevScript = script; + feCache.prevPosition = si.position; + feCache.prevLength = length(&si); } } else { - engine = font.d->engineForScript(script); + if (feCache.prevFontEngine && feCache.prevScript == script && feCache.prevPosition == -1) + engine = feCache.prevFontEngine; + else { + engine = font.d->engineForScript(script); + feCache.prevFontEngine = engine; + feCache.prevScript = script; + feCache.prevPosition = -1; + feCache.prevLength = -1; + feCache.prevScaledFontEngine = 0; + } } if (si.analysis.flags == QScriptAnalysis::SmallCaps) { @@ -2349,30 +2376,29 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int if (flags & Qt::TextShowMnemonic) { itemize(); + HB_CharAttributes *attributes = const_cast<HB_CharAttributes *>(this->attributes()); + if (!attributes) + return QString(); for (int i = 0; i < layoutData->items.size(); ++i) { QScriptItem &si = layoutData->items[i]; if (!si.num_glyphs) shape(i); - HB_CharAttributes *attributes = const_cast<HB_CharAttributes *>(this->attributes()); - if (!attributes) - return QString(); - unsigned short *logClusters = this->logClusters(&si); QGlyphLayout glyphs = shapedGlyphs(&si); const int end = si.position + length(&si); - for (int i = si.position; i < end - 1; ++i) + for (int i = si.position; i < end - 1; ++i) { if (layoutData->string.at(i) == QLatin1Char('&')) { const int gp = logClusters[i - si.position]; glyphs.attributes[gp].dontPrint = true; attributes[i + 1].charStop = false; attributes[i + 1].whiteSpace = false; attributes[i + 1].lineBreakType = HB_NoBreak; - if (i < end - 1 - && layoutData->string.at(i + 1) == QLatin1Char('&')) + if (layoutData->string.at(i + 1) == QLatin1Char('&')) ++i; } + } } } @@ -2434,7 +2460,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int if (mode == Qt::ElideRight) { QFixed currentWidth; - int pos = 0; + int pos; int nextBreak = 0; do { @@ -2454,7 +2480,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int return layoutData->string.left(pos) + ellipsisText; } else if (mode == Qt::ElideLeft) { QFixed currentWidth; - int pos = layoutData->string.length(); + int pos; int nextBreak = layoutData->string.length(); do { diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 4cbe81f..b5faf20 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -128,7 +128,7 @@ struct Q_AUTOTEST_EXPORT QScriptAnalysis TabOrObject = Tab, Object = 7 }; - unsigned short script : 8; + unsigned short script : 7; unsigned short bidiLevel : 6; // Unicode Bidi algorithm embedding level (0-61) unsigned short flags : 3; inline bool operator == (const QScriptAnalysis &other) const { @@ -385,7 +385,7 @@ struct Q_AUTOTEST_EXPORT QScriptLine QFixed textWidth; QFixed textAdvance; int from; - signed int length : 29; + signed int length : 28; mutable uint justified : 1; mutable uint gridfitted : 1; uint hasTrailingSpaces : 1; @@ -435,7 +435,7 @@ public: uint hasBidi : 1; uint layoutState : 2; uint memory_on_stack : 1; - bool haveCharAttributes; + uint haveCharAttributes : 1; QString string; bool reallocate(int totalGlyphs); }; @@ -556,6 +556,23 @@ public: mutable QScriptLineArray lines; + struct FontEngineCache { + FontEngineCache(); + mutable QFontEngine *prevFontEngine; + mutable QFontEngine *prevScaledFontEngine; + mutable int prevScript; + mutable int prevPosition; + mutable int prevLength; + inline void reset() { + prevFontEngine = 0; + prevScaledFontEngine = 0; + prevScript = -1; + prevPosition = -1; + prevLength = -1; + } + }; + mutable FontEngineCache feCache; + QString text; QFont fnt; QTextBlock block; diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp index 46db253..ffa0ebc 100644 --- a/src/gui/text/qtextformat.cpp +++ b/src/gui/text/qtextformat.cpp @@ -925,7 +925,7 @@ qreal QTextFormat::doubleProperty(int propertyId) const const QVariant prop = d->property(propertyId); if (prop.userType() != QVariant::Double && prop.userType() != QMetaType::Float) return 0.; - return qVariantValue<qreal>(prop); + return qvariant_cast<qreal>(prop); } /*! @@ -1895,7 +1895,7 @@ void QTextBlockFormat::setTabPositions(const QList<QTextOption::Tab> &tabs) QList<QTextOption::Tab>::ConstIterator iter = tabs.constBegin(); while (iter != tabs.constEnd()) { QVariant v; - qVariantSetValue<QTextOption::Tab>(v, *iter); + v.setValue<QTextOption::Tab>(*iter); list.append(v); ++iter; } @@ -1917,7 +1917,7 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const QList<QVariant> variantsList = qvariant_cast<QList<QVariant> >(variant); QList<QVariant>::Iterator iter = variantsList.begin(); while(iter != variantsList.end()) { - answer.append( qVariantValue<QTextOption::Tab>(*iter)); + answer.append( qvariant_cast<QTextOption::Tab>(*iter)); ++iter; } return answer; @@ -2227,6 +2227,44 @@ QTextListFormat::QTextListFormat(const QTextFormat &fmt) \sa setIndent() */ +/*! + \fn void QTextListFormat::setNumberPrefix(const QString &numberPrefix) + \since 4.8 + + Sets the list format's number prefix. This can be used with all + sorted list types. It does not have any effect on unsorted list types. + + \sa numberPrefix() +*/ + +/*! + \fn int QTextListFormat::numberPrefix() const + \since 4.8 + + Returns the list format's number prefix. + + \sa setNumberPrefix() +*/ + +/*! + \fn void QTextListFormat::setNumberSuffix(const QString &numberSuffix) + \since 4.8 + + Sets the list format's number suffix. This can be used with all + sorted list types. It does not have any effect on unsorted list types. + The default suffix is ".". + + \sa numberSuffix() +*/ + +/*! + \fn int QTextListFormat::numberSuffix() const + \since 4.8 + + Returns the list format's number suffix. + + \sa setNumberSuffix() +*/ /*! \class QTextFrameFormat diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h index ecf48a2..bb6e71d 100644 --- a/src/gui/text/qtextformat.h +++ b/src/gui/text/qtextformat.h @@ -202,6 +202,8 @@ public: // list properties ListStyle = 0x3000, ListIndent = 0x3001, + ListNumberPrefix = 0x3002, + ListNumberSuffix = 0x3003, // table and frame properties FrameBorder = 0x4000, @@ -617,6 +619,14 @@ public: inline int indent() const { return intProperty(ListIndent); } + inline void setNumberPrefix(const QString &numberPrefix); + inline QString numberPrefix() const + { return stringProperty(ListNumberPrefix); } + + inline void setNumberSuffix(const QString &numberSuffix); + inline QString numberSuffix() const + { return stringProperty(ListNumberSuffix); } + protected: explicit QTextListFormat(const QTextFormat &fmt); friend class QTextFormat; @@ -628,6 +638,12 @@ inline void QTextListFormat::setStyle(Style astyle) inline void QTextListFormat::setIndent(int aindent) { setProperty(ListIndent, aindent); } +inline void QTextListFormat::setNumberPrefix(const QString &np) +{ setProperty(ListNumberPrefix, np); } + +inline void QTextListFormat::setNumberSuffix(const QString &ns) +{ setProperty(ListNumberSuffix, ns); } + class Q_GUI_EXPORT QTextImageFormat : public QTextCharFormat { public: diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp index e190379..27f647c 100644 --- a/src/gui/text/qtexthtmlparser.cpp +++ b/src/gui/text/qtexthtmlparser.cpp @@ -1324,6 +1324,12 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration> case QCss::ListStyle: setListStyle(decl.d->values); break; + case QCss::QtListNumberPrefix: + textListNumberPrefix = decl.d->values.first().variant.toString(); + break; + case QCss::QtListNumberSuffix: + textListNumberSuffix = decl.d->values.first().variant.toString(); + break; default: break; } } diff --git a/src/gui/text/qtexthtmlparser_p.h b/src/gui/text/qtexthtmlparser_p.h index 94cfa74..20188ab 100644 --- a/src/gui/text/qtexthtmlparser_p.h +++ b/src/gui/text/qtexthtmlparser_p.h @@ -180,6 +180,8 @@ struct QTextHtmlParserNode { uint displayMode : 3; // QTextHtmlElement::DisplayMode uint hasHref : 1; QTextListFormat::Style listStyle; + QString textListNumberPrefix; + QString textListNumberSuffix; QString imageName; qreal imageWidth; qreal imageHeight; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index f432b7e..3f83aee 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -52,6 +52,8 @@ #include "qtextformat_p.h" #include "qstyleoption.h" #include "qpainterpath.h" +#include "qglyphs.h" +#include "qglyphs_p.h" #include <limits.h> #include <qdebug.h> @@ -165,7 +167,7 @@ static QFixed alignLine(QTextEngine *eng, const QScriptLine &line) /*! Returns the inline object's rectangle. - \sa ascent() descent() width() + \sa ascent(), descent(), width() */ QRectF QTextInlineObject::rect() const { @@ -176,7 +178,7 @@ QRectF QTextInlineObject::rect() const /*! Returns the inline object's width. - \sa ascent() descent() rect() + \sa ascent(), descent(), rect() */ qreal QTextInlineObject::width() const { @@ -186,7 +188,7 @@ qreal QTextInlineObject::width() const /*! Returns the inline object's ascent. - \sa descent() width() rect() + \sa descent(), width(), rect() */ qreal QTextInlineObject::ascent() const { @@ -196,7 +198,7 @@ qreal QTextInlineObject::ascent() const /*! Returns the inline object's descent. - \sa ascent() width() rect() + \sa ascent(), width(), rect() */ qreal QTextInlineObject::descent() const { @@ -207,18 +209,17 @@ qreal QTextInlineObject::descent() const Returns the inline object's total height. This is equal to ascent() + descent() + 1. - \sa ascent() descent() width() rect() + \sa ascent(), descent(), width(), rect() */ qreal QTextInlineObject::height() const { return eng->layoutData->items[itm].height().toReal(); } - /*! Sets the inline object's width to \a w. - \sa width() ascent() descent() rect() + \sa width(), ascent(), descent(), rect() */ void QTextInlineObject::setWidth(qreal w) { @@ -228,7 +229,7 @@ void QTextInlineObject::setWidth(qreal w) /*! Sets the inline object's ascent to \a a. - \sa ascent() setDescent() width() rect() + \sa ascent(), setDescent(), width(), rect() */ void QTextInlineObject::setAscent(qreal a) { @@ -238,7 +239,7 @@ void QTextInlineObject::setAscent(qreal a) /*! Sets the inline object's decent to \a d. - \sa descent() setAscent() width() rect() + \sa descent(), setAscent(), width(), rect() */ void QTextInlineObject::setDescent(qreal d) { @@ -246,7 +247,7 @@ void QTextInlineObject::setDescent(qreal d) } /*! - The position of the inline object within the text layout. + The position of the inline object within the text layout. */ int QTextInlineObject::textPosition() const { @@ -254,8 +255,8 @@ int QTextInlineObject::textPosition() const } /*! - Returns an integer describing the format of the inline object - within the text layout. + Returns an integer describing the format of the inline object + within the text layout. */ int QTextInlineObject::formatIndex() const { @@ -263,7 +264,7 @@ int QTextInlineObject::formatIndex() const } /*! - Returns format of the inline object within the text layout. + Returns format of the inline object within the text layout. */ QTextFormat QTextInlineObject::format() const { @@ -273,7 +274,7 @@ QTextFormat QTextInlineObject::format() const } /*! - Returns if the object should be laid out right-to-left or left-to-right. + Returns if the object should be laid out right-to-left or left-to-right. */ Qt::LayoutDirection QTextInlineObject::textDirection() const { @@ -325,7 +326,6 @@ Qt::LayoutDirection QTextInlineObject::textDirection() const boundingRect(), and a minimumWidth() and a maximumWidth(). \sa QStaticText - */ /*! @@ -398,16 +398,19 @@ QTextLayout::~QTextLayout() Sets the layout's font to the given \a font. The layout is invalidated and must be laid out again. - \sa text() + \sa font() */ void QTextLayout::setFont(const QFont &font) { d->fnt = font; + d->feCache.reset(); } /*! Returns the current font that is used for the layout, or a default font if none is set. + + \sa setFont() */ QFont QTextLayout::font() const { @@ -441,10 +444,10 @@ QString QTextLayout::text() const } /*! - Sets the text option structure that controls the layout process to the - given \a option. + Sets the text option structure that controls the layout process to the + given \a option. - \sa textOption() QTextOption + \sa textOption() */ void QTextLayout::setTextOption(const QTextOption &option) { @@ -452,9 +455,9 @@ void QTextLayout::setTextOption(const QTextOption &option) } /*! - Returns the current text option used to control the layout process. + Returns the current text option used to control the layout process. - \sa setTextOption() QTextOption + \sa setTextOption() */ QTextOption QTextLayout::textOption() const { @@ -464,6 +467,8 @@ QTextOption QTextLayout::textOption() const /*! Sets the \a position and \a text of the area in the layout that is processed before editing occurs. + + \sa preeditAreaPosition(), preeditAreaText() */ void QTextLayout::setPreeditArea(int position, const QString &text) { @@ -492,6 +497,8 @@ void QTextLayout::setPreeditArea(int position, const QString &text) /*! Returns the position of the area in the text layout that will be processed before editing occurs. + + \sa preeditAreaText() */ int QTextLayout::preeditAreaPosition() const { @@ -500,6 +507,8 @@ int QTextLayout::preeditAreaPosition() const /*! Returns the text that is inserted in the layout before editing occurs. + + \sa preeditAreaPosition() */ QString QTextLayout::preeditAreaText() const { @@ -508,8 +517,7 @@ QString QTextLayout::preeditAreaText() const /*! - Sets the additional formats supported by the text layout to \a - formatList. + Sets the additional formats supported by the text layout to \a formatList. \sa additionalFormats(), clearAdditionalFormats() */ @@ -535,6 +543,7 @@ void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList) } if (d->block.docHandle()) d->block.docHandle()->documentChange(d->block.position(), d->block.length()); + d->feCache.reset(); } /*! @@ -599,6 +608,8 @@ bool QTextLayout::cacheEnabled() const /*! Begins the layout process. + + \sa endLayout() */ void QTextLayout::beginLayout() { @@ -616,6 +627,8 @@ void QTextLayout::beginLayout() /*! Ends the layout process. + + \sa beginLayout() */ void QTextLayout::endLayout() { @@ -634,35 +647,33 @@ void QTextLayout::endLayout() d->freeMemory(); } -/*! \since 4.4 +/*! + \since 4.4 -Clears the line information in the layout. After having called -this function, lineCount() returns 0. - */ + Clears the line information in the layout. After having called + this function, lineCount() returns 0. +*/ void QTextLayout::clearLayout() { d->clearLineData(); } - /*! Returns the next valid cursor position after \a oldPos that respects the given cursor \a mode. + Returns value of \a oldPos, if \a oldPos is not a valid cursor position. - \sa isValidCursorPosition() previousCursorPosition() + \sa isValidCursorPosition(), previousCursorPosition() */ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const { -// qDebug("looking for next cursor pos for %d", oldPos); const HB_CharAttributes *attributes = d->attributes(); - if (!attributes) - return 0; - int len = d->block.isValid() ? - (d->block.length() - 1) - : d->layoutData->string.length(); - - if (oldPos >= len) + int len = d->block.isValid() ? d->block.length() - 1 + : d->layoutData->string.length(); + Q_ASSERT(len <= d->layoutData->string.length()); + if (!attributes || oldPos < 0 || oldPos >= len) return oldPos; + if (mode == SkipCharacters) { oldPos++; while (oldPos < len && !attributes[oldPos].charStop) @@ -679,22 +690,23 @@ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const while (oldPos < len && d->atSpace(oldPos)) oldPos++; } -// qDebug(" -> %d", oldPos); + return oldPos; } /*! Returns the first valid cursor position before \a oldPos that respects the given cursor \a mode. + Returns value of \a oldPos, if \a oldPos is not a valid cursor position. - \sa isValidCursorPosition() nextCursorPosition() + \sa isValidCursorPosition(), nextCursorPosition() */ int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const { -// qDebug("looking for previous cursor pos for %d", oldPos); const HB_CharAttributes *attributes = d->attributes(); - if (!attributes || oldPos <= 0) - return 0; + if (!attributes || oldPos <= 0 || oldPos > d->layoutData->string.length()) + return oldPos; + if (mode == SkipCharacters) { oldPos--; while (oldPos && !attributes[oldPos].charStop) @@ -712,7 +724,7 @@ int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const oldPos--; } } -// qDebug(" -> %d", oldPos); + return oldPos; } @@ -739,7 +751,6 @@ bool QTextLayout::isValidCursorPosition(int pos) const return attributes[pos].charStop; } - /*! Returns a new text line to be laid out if there is text to be inserted into the layout; otherwise returns an invalid text line. @@ -801,7 +812,7 @@ int QTextLayout::lineCount() const /*! Returns the \a{i}-th line of text in this text layout. - \sa lineCount() lineForTextPosition() + \sa lineCount(), lineForTextPosition() */ QTextLine QTextLayout::lineAt(int i) const { @@ -811,7 +822,7 @@ QTextLine QTextLayout::lineAt(int i) const /*! Returns the line that contains the cursor position specified by \a pos. - \sa isValidCursorPosition() lineAt() + \sa isValidCursorPosition(), lineAt() */ QTextLine QTextLayout::lineForTextPosition(int pos) const { @@ -902,8 +913,9 @@ qreal QTextLayout::maximumWidth() const return d->maxWidth.toReal(); } + /*! - \internal + \internal */ void QTextLayout::setFlags(int flags) { @@ -1028,6 +1040,35 @@ QScriptItem &QTextLineItemIterator::next() return *si; } +static QFixed offsetInLigature(const unsigned short *logClusters, + const QGlyphLayout &glyphs, + int pos, int max, int glyph_pos) +{ + int offsetInCluster = 0; + for (int i = pos - 1; i >= 0; i--) { + if (logClusters[i] == glyph_pos) + offsetInCluster++; + else + break; + } + + // in the case that the offset is inside a (multi-character) glyph, + // interpolate the position. + if (offsetInCluster > 0) { + int clusterLength = 0; + for (int i = pos - offsetInCluster; i < max; i++) { + if (logClusters[i] == glyph_pos) + clusterLength++; + else + break; + } + if (clusterLength) + return glyphs.advances_x[glyph_pos] * offsetInCluster / clusterLength; + } + + return 0; +} + bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selectionWidth) const { *selectionX = *selectionWidth = 0; @@ -1067,8 +1108,19 @@ bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selec swidth += glyphs.effectiveAdvance(g); } - *selectionX = x + soff; - *selectionWidth = swidth; + // If the starting character is in the middle of a ligature, + // selection should only contain the right part of that ligature + // glyph, so we need to get the width of the left part here and + // add it to *selectionX + QFixed leftOffsetInLigature = offsetInLigature(logClusters, glyphs, from, + to, start_glyph); + *selectionX = x + soff + leftOffsetInLigature; + *selectionWidth = swidth - leftOffsetInLigature; + // If the ending character is also part of a ligature, swidth does + // not contain that part yet, we also need to find out the width of + // that left part + *selectionWidth += offsetInLigature(logClusters, glyphs, to, + eng->length(item), end_glyph); } return true; } @@ -1114,9 +1166,26 @@ static inline QRectF clipIfValid(const QRectF &rect, const QRectF &clip) return clip.isValid() ? (rect & clip) : rect; } + /*! - Draws the whole layout on the painter \a p at the position specified by - \a pos. + Returns the glyph indexes and positions for all glyphs in this QTextLayout. This is an + expensive function, and should not be called in a time sensitive context. + + \since 4.8 + + \sa draw(), QPainter::drawGlyphs() +*/ +QList<QGlyphs> QTextLayout::glyphs() const +{ + QList<QGlyphs> glyphs; + for (int i=0; i<d->lines.size(); ++i) + glyphs += QTextLine(i, d).glyphs(-1, -1); + + return glyphs; +} + +/*! + Draws the whole layout on the painter \a p at the position specified by \a pos. The rendered layout includes the given \a selections and is clipped within the rectangle specified by \a clip. */ @@ -1290,12 +1359,12 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRang } /*! - \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition) const - \overload + \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition) const + \overload - Draws a text cursor with the current pen at the given \a position using the - \a painter specified. - The corresponding position within the text is specified by \a cursorPosition. + Draws a text cursor with the current pen at the given \a position using the + \a painter specified. + The corresponding position within the text is specified by \a cursorPosition. */ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition) const { @@ -1303,11 +1372,11 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition } /*! - \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition, int width) const + \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition, int width) const - Draws a text cursor with the current pen and the specified \a width at the given \a position using the - \a painter specified. - The corresponding position within the text is specified by \a cursorPosition. + Draws a text cursor with the current pen and the specified \a width at the given \a position using the + \a painter specified. + The corresponding position within the text is specified by \a cursorPosition. */ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition, int width) const { @@ -1438,7 +1507,7 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition /*! Returns the line's bounding rectangle. - \sa x() y() textLength() width() + \sa x(), y(), textLength(), width() */ QRectF QTextLine::rect() const { @@ -1464,7 +1533,7 @@ QRectF QTextLine::naturalTextRect() const /*! Returns the line's x position. - \sa rect() y() textLength() width() + \sa rect(), y(), textLength(), width() */ qreal QTextLine::x() const { @@ -1474,7 +1543,7 @@ qreal QTextLine::x() const /*! Returns the line's y position. - \sa x() rect() textLength() width() + \sa x(), rect(), textLength(), width() */ qreal QTextLine::y() const { @@ -1484,7 +1553,7 @@ qreal QTextLine::y() const /*! Returns the line's width as specified by the layout() function. - \sa naturalTextWidth() x() y() textLength() rect() + \sa naturalTextWidth(), x(), y(), textLength(), rect() */ qreal QTextLine::width() const { @@ -1495,7 +1564,7 @@ qreal QTextLine::width() const /*! Returns the line's ascent. - \sa descent() height() + \sa descent(), height() */ qreal QTextLine::ascent() const { @@ -1505,7 +1574,7 @@ qreal QTextLine::ascent() const /*! Returns the line's descent. - \sa ascent() height() + \sa ascent(), height() */ qreal QTextLine::descent() const { @@ -1517,7 +1586,7 @@ qreal QTextLine::descent() const if leading is not included. If leading is included, this equals to ascent() + descent() + leading() + 1. - \sa ascent() descent() leading() setLeadingIncluded() + \sa ascent(), descent(), leading(), setLeadingIncluded() */ qreal QTextLine::height() const { @@ -1529,24 +1598,25 @@ qreal QTextLine::height() const Returns the line's leading. - \sa ascent() descent() height() + \sa ascent(), descent(), height() */ qreal QTextLine::leading() const { return eng->lines[i].leading.toReal(); } -/*! \since 4.6 +/*! + \since 4.6 - Includes positive leading into the line's height if \a included is true; - otherwise does not include leading. + Includes positive leading into the line's height if \a included is true; + otherwise does not include leading. - By default, leading is not included. + By default, leading is not included. - Note that negative leading is ignored, it must be handled - in the code using the text lines by letting the lines overlap. + Note that negative leading is ignored, it must be handled + in the code using the text lines by letting the lines overlap. - \sa leadingIncluded() + \sa leadingIncluded() */ void QTextLine::setLeadingIncluded(bool included) @@ -1555,20 +1625,21 @@ void QTextLine::setLeadingIncluded(bool included) } -/*! \since 4.6 +/*! + \since 4.6 - Returns true if positive leading is included into the line's height; otherwise returns false. + Returns true if positive leading is included into the line's height; + otherwise returns false. - By default, leading is not included. + By default, leading is not included. - \sa setLeadingIncluded() + \sa setLeadingIncluded() */ bool QTextLine::leadingIncluded() const { return eng->lines[i].leadingIncluded; } - /*! Returns the width of the line that is occupied by text. This is always \<= to width(), and is the minimum width that could be used @@ -1579,14 +1650,15 @@ qreal QTextLine::naturalTextWidth() const return eng->lines[i].textWidth.toReal(); } -/*! \since 4.7 - Returns the horizontal advance of the text. The advance of the text - is the distance from its position to the next position at which - text would naturally be drawn. +/*! + \since 4.7 + Returns the horizontal advance of the text. The advance of the text + is the distance from its position to the next position at which + text would naturally be drawn. - By adding the advance to the position of the text line and using this - as the position of a second text line, you will be able to position - the two lines side-by-side without gaps in-between. + By adding the advance to the position of the text line and using this + as the position of a second text line, you will be able to position + the two lines side-by-side without gaps in-between. */ qreal QTextLine::horizontalAdvance() const { @@ -1764,7 +1836,8 @@ static inline void addNextCluster(int &pos, int end, QScriptLine &line, int &gly ++line.length; } while (pos < end && logClusters[pos] == glyphPosition); do { // calculate the textWidth for the rest of the current cluster. - line.textWidth += glyphs.advances_x[glyphPosition] * !glyphs.attributes[glyphPosition].dontPrint; + if (!glyphs.attributes[glyphPosition].dontPrint) + line.textWidth += glyphs.advances_x[glyphPosition]; ++glyphPosition; } while (glyphPosition < current.num_glyphs && !glyphs.attributes[glyphPosition].clusterStart); @@ -1842,14 +1915,14 @@ void QTextLine::layout_helper(int maxGlyphs) lbh.currentPosition = qMax(line.from, current.position); end = current.position + eng->length(item); lbh.glyphs = eng->shapedGlyphs(¤t); + QFontEngine *fontEngine = eng->fontEngine(current); + if (lbh.fontEngine != fontEngine) { + lbh.fontEngine = fontEngine; + lbh.minimumRightBearing = qMin(QFixed(), + QFixed::fromReal(fontEngine->minRightBearing())); + } } const QScriptItem ¤t = eng->layoutData->items[item]; - QFontEngine *fontEngine = eng->fontEngine(current); - if (lbh.fontEngine != fontEngine) { - lbh.fontEngine = fontEngine; - lbh.minimumRightBearing = qMin(QFixed(), - QFixed::fromReal(fontEngine->minRightBearing())); - } lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent, current.leading + current.ascent) - qMax(lbh.tmpData.ascent, @@ -2014,9 +2087,10 @@ found: eng->maxWidth += lbh.spaceData.textWidth; if (eng->option.flags() & QTextOption::IncludeTrailingSpaces) line.textWidth += lbh.spaceData.textWidth; - line.length += lbh.spaceData.length; - if (lbh.spaceData.length) + if (lbh.spaceData.length) { + line.length += lbh.spaceData.length; line.hasTrailingSpaces = true; + } line.justified = false; line.gridfitted = false; @@ -2170,6 +2244,151 @@ static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const Q } +namespace { + struct GlyphInfo + { + GlyphInfo(const QGlyphLayout &layout, const QPointF &position, + const QTextItemInt::RenderFlags &renderFlags) + : glyphLayout(layout), itemPosition(position), flags(renderFlags) + { + } + + QGlyphLayout glyphLayout; + QPointF itemPosition; + QTextItem::RenderFlags flags; + }; +} + +/*! + \internal + + Returns the glyph indexes and positions for all glyphs in this QTextLine which reside in + QScriptItems that overlap with the range defined by \a from and \a length. The arguments + specify characters, relative to the text in the layout. Note that it is not possible to + use this function to retrieve a subset of the glyphs in a QScriptItem. + + \since 4.8 + + \sa QTextLayout::glyphs() +*/ +QList<QGlyphs> QTextLine::glyphs(int from, int length) const +{ + const QScriptLine &line = eng->lines[i]; + + if (line.length == 0) + return QList<QGlyphs>(); + + QHash<QFontEngine *, GlyphInfo> glyphLayoutHash; + + QTextLineItemIterator iterator(eng, i); + qreal y = line.y.toReal() + line.base().toReal(); + while (!iterator.atEnd()) { + QScriptItem &si = iterator.next(); + if (si.analysis.flags >= QScriptAnalysis::TabOrObject) + continue; + + QPointF pos(iterator.x.toReal(), y); + if (from >= 0 && length >= 0 && + (from >= si.position + eng->length(&si) || from + length <= si.position)) + continue; + + QFont font = eng->font(si); + + QTextItem::RenderFlags flags; + if (font.overline()) + flags |= QTextItem::Overline; + if (font.underline()) + flags |= QTextItem::Underline; + if (font.strikeOut()) + flags |= QTextItem::StrikeOut; + if (si.analysis.bidiLevel % 2) + flags |= QTextItem::RightToLeft; + + QGlyphLayout glyphLayout = eng->shapedGlyphs(&si).mid(iterator.glyphsStart, + iterator.glyphsEnd - iterator.glyphsStart); + + if (glyphLayout.numGlyphs > 0) { + QFontEngine *mainFontEngine = font.d->engineForScript(si.analysis.script); + if (mainFontEngine->type() == QFontEngine::Multi) { + QFontEngineMulti *multiFontEngine = static_cast<QFontEngineMulti *>(mainFontEngine); + int start = 0; + int end; + int which = glyphLayout.glyphs[0] >> 24; + for (end = 0; end < glyphLayout.numGlyphs; ++end) { + const int e = glyphLayout.glyphs[end] >> 24; + if (e == which) + continue; + + QGlyphLayout subLayout = glyphLayout.mid(start, end - start); + glyphLayoutHash.insertMulti(multiFontEngine->engine(which), + GlyphInfo(subLayout, pos, flags)); + + start = end; + which = e; + } + + QGlyphLayout subLayout = glyphLayout.mid(start, end - start); + glyphLayoutHash.insertMulti(multiFontEngine->engine(which), + GlyphInfo(subLayout, pos, flags)); + + } else { + glyphLayoutHash.insertMulti(mainFontEngine, + GlyphInfo(glyphLayout, pos, flags)); + } + } + } + + QHash<QPair<QFontEngine *, int>, QGlyphs> glyphsHash; + + QList<QFontEngine *> keys = glyphLayoutHash.uniqueKeys(); + for (int i=0; i<keys.size(); ++i) { + QFontEngine *fontEngine = keys.at(i); + + // Make a font for this particular engine + QFont font = fontEngine->createExplicitFont(); + + QList<GlyphInfo> glyphLayouts = glyphLayoutHash.values(fontEngine); + for (int j=0; j<glyphLayouts.size(); ++j) { + const QPointF &pos = glyphLayouts.at(j).itemPosition; + const QGlyphLayout &glyphLayout = glyphLayouts.at(j).glyphLayout; + const QTextItem::RenderFlags &flags = glyphLayouts.at(j).flags; + + font.setOverline(flags.testFlag(QTextItem::Overline)); + font.setUnderline(flags.testFlag(QTextItem::Underline)); + font.setStrikeOut(flags.testFlag(QTextItem::StrikeOut)); + + QVarLengthArray<glyph_t> glyphsArray; + QVarLengthArray<QFixedPoint> positionsArray; + + fontEngine->getGlyphPositions(glyphLayout, QTransform(), flags, glyphsArray, + positionsArray); + Q_ASSERT(glyphsArray.size() == positionsArray.size()); + + QVector<quint32> glyphs; + QVector<QPointF> positions; + for (int i=0; i<glyphsArray.size(); ++i) { + glyphs.append(glyphsArray.at(i) & 0xffffff); + positions.append(positionsArray.at(i).toPointF() + pos); + } + + QGlyphs glyphIndexes; + glyphIndexes.setGlyphIndexes(glyphs); + glyphIndexes.setPositions(positions); + + QPair<QFontEngine *, int> key(fontEngine, int(flags)); + + if (!glyphsHash.contains(key)) + glyphsHash.insert(key, QGlyphs()); + + QGlyphs &target = glyphsHash[key]; + target += glyphIndexes; + target.setFont(font); + } + } + + return glyphsHash.values(); +} + /*! \fn void QTextLine::draw(QPainter *painter, const QPointF &position, const QTextLayout::FormatRange *selection) const @@ -2366,21 +2585,20 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR } /*! - \fn int QTextLine::cursorToX(int cursorPos, Edge edge) const + \fn int QTextLine::cursorToX(int cursorPos, Edge edge) const - \overload + \overload */ - /*! - Converts the cursor position \a cursorPos to the corresponding x position - inside the line, taking account of the \a edge. + Converts the cursor position \a cursorPos to the corresponding x position + inside the line, taking account of the \a edge. - If \a cursorPos is not a valid cursor position, the nearest valid - cursor position will be used instead, and cpos will be modified to - point to this valid cursor position. + If \a cursorPos is not a valid cursor position, the nearest valid + cursor position will be used instead, and cpos will be modified to + point to this valid cursor position. - \sa xToCursor() + \sa xToCursor() */ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const { @@ -2479,14 +2697,6 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const if(pos == l) x += si->width; } else { - int offsetInCluster = 0; - for (int i=pos-1; i >= 0; i--) { - if (logClusters[i] == glyph_pos) - offsetInCluster++; - else - break; - } - if (reverse) { int end = qMin(lineEnd, si->position + l) - si->position; int glyph_end = end == l ? si->num_glyphs : logClusters[end]; @@ -2498,17 +2708,7 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const for (int i = glyph_start; i < glyph_pos; i++) x += glyphs.effectiveAdvance(i); } - if (offsetInCluster > 0) { // in the case that the offset is inside a (multi-character) glyph, interpolate the position. - int clusterLength = 0; - for (int i=pos - offsetInCluster; i < line.length; i++) { - if (logClusters[i] == glyph_pos) - clusterLength++; - else - break; - } - if (clusterLength) - x+= glyphs.advances_x[glyph_pos] * offsetInCluster / clusterLength; - } + x += offsetInLigature(logClusters, glyphs, pos, line.length, glyph_pos); } *cursorPos = pos + si->position; @@ -2516,12 +2716,12 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const } /*! - \fn int QTextLine::xToCursor(qreal x, CursorPosition cpos) const + \fn int QTextLine::xToCursor(qreal x, CursorPosition cpos) const - Converts the x-coordinate \a x, to the nearest matching cursor - position, depending on the cursor position type, \a cpos. + Converts the x-coordinate \a x, to the nearest matching cursor + position, depending on the cursor position type, \a cpos. - \sa cursorToX() + \sa cursorToX() */ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const { diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h index 8c93ed6..32d6d0e 100644 --- a/src/gui/text/qtextlayout.h +++ b/src/gui/text/qtextlayout.h @@ -49,6 +49,7 @@ #include <QtCore/qobject.h> #include <QtGui/qevent.h> #include <QtGui/qtextformat.h> +#include <QtGui/qglyphs.h> QT_BEGIN_HEADER @@ -166,6 +167,8 @@ public: qreal minimumWidth() const; qreal maximumWidth() const; + QList<QGlyphs> glyphs() const; + QTextEngine *engine() const { return d; } void setFlags(int flags); private: @@ -236,7 +239,10 @@ public: private: QTextLine(int line, QTextEngine *e) : i(line), eng(e) {} void layout_helper(int numGlyphs); + QList<QGlyphs> glyphs(int from, int length) const; + friend class QTextLayout; + friend class QTextFragment; int i; QTextEngine *eng; }; diff --git a/src/gui/text/qtextlist.cpp b/src/gui/text/qtextlist.cpp index a0ff520..c312d89 100644 --- a/src/gui/text/qtextlist.cpp +++ b/src/gui/text/qtextlist.cpp @@ -191,6 +191,13 @@ QString QTextList::itemText(const QTextBlock &blockIt) const QString result; const int style = format().style(); + QString numberPrefix; + QString numberSuffix = QLatin1String("."); + + if (format().hasProperty(QTextFormat::ListNumberPrefix)) + numberPrefix = format().numberPrefix(); + if (format().hasProperty(QTextFormat::ListNumberSuffix)) + numberSuffix = format().numberSuffix(); switch (style) { case QTextListFormat::ListDecimal: @@ -232,7 +239,7 @@ QString QTextList::itemText(const QTextBlock &blockIt) const if (q > 0) { int startDigit = i + (i+3)/4; int numDigits; - if (i % 4) { + if (i % 4) { // c[i] == 4|5|9|40|50|90|400|500|900 if ((i-2) % 4) { // c[i] == 4|9|40|90|400|900 => with substraction (IV, IX, XL, XC, ...) @@ -263,8 +270,9 @@ QString QTextList::itemText(const QTextBlock &blockIt) const Q_ASSERT(false); } if (blockIt.textDirection() == Qt::RightToLeft) - return result.prepend(QLatin1Char('.')); - return result + QLatin1Char('.'); + return numberSuffix + result + numberPrefix; + else + return numberPrefix + result + numberSuffix; } /*! diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index ea2ef2d..65fd36e 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -1655,6 +1655,35 @@ QTextBlock::iterator &QTextBlock::iterator::operator--() than the \a other text fragment; otherwise returns false. */ +/*! + Returns the glyphs of this text fragment. The positions of the glyphs are + relative to the position of the QTextBlock's layout. + + \sa QGlyphs, QTextBlock::layout(), QTextLayout::position(), QPainter::drawGlyphs() +*/ +QList<QGlyphs> QTextFragment::glyphs() const +{ + if (!p || !n) + return QList<QGlyphs>(); + + int pos = position(); + int len = length(); + if (len == 0) + return QList<QGlyphs>(); + + int blockNode = p->blockMap().findNode(pos); + + const QTextBlockData *blockData = p->blockMap().fragment(blockNode); + QTextLayout *layout = blockData->layout; + + QList<QGlyphs> ret; + for (int i=0; i<layout->lineCount(); ++i) { + QTextLine textLine = layout->lineAt(i); + ret += textLine.glyphs(pos, len); + } + + return ret; +} /*! Returns the position of this text fragment in the document. diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h index a573a26..332458d 100644 --- a/src/gui/text/qtextobject.h +++ b/src/gui/text/qtextobject.h @@ -44,6 +44,7 @@ #include <QtCore/qobject.h> #include <QtGui/qtextformat.h> +#include <QtGui/qglyphs.h> QT_BEGIN_HEADER @@ -315,6 +316,8 @@ public: int charFormatIndex() const; QString text() const; + QList<QGlyphs> glyphs() const; + private: const QTextDocumentPrivate *p; int n; diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp index 7992de5..04f6913 100644 --- a/src/gui/text/qtextodfwriter.cpp +++ b/src/gui/text/qtextodfwriter.cpp @@ -636,7 +636,15 @@ void QTextOdfWriter::writeListFormat(QXmlStreamWriter &writer, QTextListFormat f || style == QTextListFormat::ListUpperRoman) { writer.writeStartElement(textNS, QString::fromLatin1("list-level-style-number")); writer.writeAttribute(styleNS, QString::fromLatin1("num-format"), bulletChar(style)); - writer.writeAttribute(styleNS, QString::fromLatin1("num-suffix"), QString::fromLatin1(".")); + + if (format.hasProperty(QTextFormat::ListNumberSuffix)) + writer.writeAttribute(styleNS, QString::fromLatin1("num-suffix"), format.numberSuffix()); + else + writer.writeAttribute(styleNS, QString::fromLatin1("num-suffix"), QString::fromLatin1(".")); + + if (format.hasProperty(QTextFormat::ListNumberPrefix)) + writer.writeAttribute(styleNS, QString::fromLatin1("num-prefix"), format.numberPrefix()); + } else { writer.writeStartElement(textNS, QString::fromLatin1("list-level-style-bullet")); writer.writeAttribute(textNS, QString::fromLatin1("bullet-char"), bulletChar(style)); diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index af8daa5..102df4d 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -39,7 +39,9 @@ HEADERS += \ text/qzipwriter_p.h \ text/qtextodfwriter_p.h \ text/qstatictext_p.h \ - text/qstatictext.h + text/qstatictext.h \ + text/qglyphs.h \ + text/qglyphs_p.h SOURCES += \ text/qfont.cpp \ @@ -69,7 +71,8 @@ SOURCES += \ text/qcssparser.cpp \ text/qzip.cpp \ text/qtextodfwriter.cpp \ - text/qstatictext.cpp + text/qstatictext.cpp \ + text/qglyphs.cpp win32 { SOURCES += \ diff --git a/src/gui/widgets/qabstractbutton.cpp b/src/gui/widgets/qabstractbutton.cpp index 995d659..bd66843 100644 --- a/src/gui/widgets/qabstractbutton.cpp +++ b/src/gui/widgets/qabstractbutton.cpp @@ -319,7 +319,7 @@ QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const return group->d_func()->buttonList; #endif - QList<QAbstractButton*>candidates = qFindChildren<QAbstractButton *>(parent); + QList<QAbstractButton*>candidates = parent->findChildren<QAbstractButton *>(); if (autoExclusive) { for (int i = candidates.count() - 1; i >= 0; --i) { QAbstractButton *candidate = candidates.at(i); diff --git a/src/gui/widgets/qcheckbox.cpp b/src/gui/widgets/qcheckbox.cpp index bc0900e..64b47b4 100644 --- a/src/gui/widgets/qcheckbox.cpp +++ b/src/gui/widgets/qcheckbox.cpp @@ -300,6 +300,15 @@ QSize QCheckBox::sizeHint() const return d->sizeHint; } + +/*! + \reimp +*/ +QSize QCheckBox::minimumSizeHint() const +{ + return sizeHint(); +} + /*! \reimp */ diff --git a/src/gui/widgets/qcheckbox.h b/src/gui/widgets/qcheckbox.h index 7b6292d..95da261 100644 --- a/src/gui/widgets/qcheckbox.h +++ b/src/gui/widgets/qcheckbox.h @@ -65,6 +65,7 @@ public: QSize sizeHint() const; + QSize minimumSizeHint() const; void setTristate(bool y = true); bool isTristate() const; diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index 96d2acd..21dd127 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -116,7 +116,7 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt QPalette resolvedpalette = option.palette.resolve(QApplication::palette("QMenu")); QVariant value = index.data(Qt::ForegroundRole); - if (qVariantCanConvert<QBrush>(value)) { + if (value.canConvert<QBrush>()) { resolvedpalette.setBrush(QPalette::WindowText, qvariant_cast<QBrush>(value)); resolvedpalette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(value)); resolvedpalette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value)); @@ -152,7 +152,7 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt menuOption.icon = qvariant_cast<QPixmap>(variant); break; } - if (qVariantCanConvert<QBrush>(index.data(Qt::BackgroundRole))) { + if (index.data(Qt::BackgroundRole).canConvert<QBrush>()) { menuOption.palette.setBrush(QPalette::All, QPalette::Background, qvariant_cast<QBrush>(index.data(Qt::BackgroundRole))); } @@ -369,6 +369,7 @@ void QComboBoxPrivateContainer::timerEvent(QTimerEvent *timerEvent) if (timerEvent->timerId() == adjustSizeTimer.timerId()) { adjustSizeTimer.stop(); if (combo->sizeAdjustPolicy() == QComboBox::AdjustToContents) { + combo->updateGeometry(); combo->adjustSize(); combo->update(); } @@ -1298,7 +1299,7 @@ QComboBox::~QComboBox() By default, this property has a value of 10. \note This property is ignored for non-editable comboboxes in styles that returns - false for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style. + true for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style. */ int QComboBox::maxVisibleItems() const { @@ -2008,11 +2009,18 @@ void QComboBox::setCurrentIndex(int index) void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi) { Q_Q(QComboBox); - bool indexChanged = (mi != currentIndex); + + QModelIndex normalized; + if (mi.column() != modelColumn) + normalized = model->index(mi.row(), modelColumn, mi.parent()); + if (!normalized.isValid()) + normalized = mi; // Fallback to passed index. + + bool indexChanged = (normalized != currentIndex); if (indexChanged) - currentIndex = QPersistentModelIndex(mi); + currentIndex = QPersistentModelIndex(normalized); if (lineEdit) { - QString newText = q->itemText(currentIndex.row()); + QString newText = q->itemText(normalized.row()); if (lineEdit->text() != newText) lineEdit->setText(newText); updateLineEditGeometry(); diff --git a/src/gui/widgets/qcombobox.h b/src/gui/widgets/qcombobox.h index fb9af9f..81a4389 100644 --- a/src/gui/widgets/qcombobox.h +++ b/src/gui/widgets/qcombobox.h @@ -68,7 +68,7 @@ class Q_GUI_EXPORT QComboBox : public QWidget Q_PROPERTY(bool editable READ isEditable WRITE setEditable) Q_PROPERTY(int count READ count) Q_PROPERTY(QString currentText READ currentText) - Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) + Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged USER true) Q_PROPERTY(int maxVisibleItems READ maxVisibleItems WRITE setMaxVisibleItems) Q_PROPERTY(int maxCount READ maxCount WRITE setMaxCount) Q_PROPERTY(InsertPolicy insertPolicy READ insertPolicy WRITE setInsertPolicy) diff --git a/src/gui/widgets/qcombobox_p.h b/src/gui/widgets/qcombobox_p.h index 29a628c..c0727ed 100644 --- a/src/gui/widgets/qcombobox_p.h +++ b/src/gui/widgets/qcombobox_p.h @@ -337,7 +337,7 @@ private: QComboBox *mCombo; }; -class QComboBoxPrivate : public QWidgetPrivate +class Q_AUTOTEST_EXPORT QComboBoxPrivate : public QWidgetPrivate { Q_DECLARE_PUBLIC(QComboBox) public: diff --git a/src/gui/widgets/qdatetimeedit.cpp b/src/gui/widgets/qdatetimeedit.cpp index bd6c577..36a3147 100644 --- a/src/gui/widgets/qdatetimeedit.cpp +++ b/src/gui/widgets/qdatetimeedit.cpp @@ -890,7 +890,13 @@ void QDateTimeEdit::setDisplayFormat(const QString &format) const bool dateShown = (d->sections & DateSections_Mask); Q_ASSERT(dateShown || timeShown); if (timeShown && !dateShown) { + QTime time = d->value.toTime(); setDateRange(d->value.toDate(), d->value.toDate()); + if (d->minimum.toTime() >= d->maximum.toTime()) { + setTimeRange(QDATETIMEEDIT_TIME_MIN, QDATETIMEEDIT_TIME_MAX); + // if the time range became invalid during the adjustment, the time would have been reset + setTime(time); + } } else if (dateShown && !timeShown) { setTimeRange(QDATETIMEEDIT_TIME_MIN, QDATETIMEEDIT_TIME_MAX); d->value = QDateTime(d->value.toDate(), QTime(), d->spec); @@ -1654,6 +1660,15 @@ void QDateTimeEditPrivate::updateTimeSpec() minimum = minimum.toDateTime().toTimeSpec(spec); maximum = maximum.toDateTime().toTimeSpec(spec); value = value.toDateTime().toTimeSpec(spec); + + // time zone changes can lead to 00:00:00 becomes 01:00:00 and 23:59:59 becomes 00:59:59 (invalid range) + const bool dateShown = (sections & QDateTimeEdit::DateSections_Mask); + if (!dateShown) { + if (minimum.toTime() >= maximum.toTime()){ + minimum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MIN, spec); + maximum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MAX, spec); + } + } } void QDateTimeEditPrivate::updateEdit() diff --git a/src/gui/widgets/qdialogbuttonbox.cpp b/src/gui/widgets/qdialogbuttonbox.cpp index 732dbc9..9aea32a 100644 --- a/src/gui/widgets/qdialogbuttonbox.cpp +++ b/src/gui/widgets/qdialogbuttonbox.cpp @@ -1229,7 +1229,7 @@ bool QDialogButtonBox::event(QEvent *event) break; } - foreach (QPushButton *pb, qFindChildren<QPushButton *>(dialog ? dialog : this)) { + foreach (QPushButton *pb, (dialog ? dialog : this)->findChildren<QPushButton *>()) { if (pb->isDefault() && pb != firstAcceptButton) { hasDefault = true; break; diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp index bdbd0b0..f5393a9 100644 --- a/src/gui/widgets/qlabel.cpp +++ b/src/gui/widgets/qlabel.cpp @@ -1071,7 +1071,7 @@ void QLabel::paintEvent(QPaintEvent *) else #endif if (d->isTextLabel) { - QRectF lr = d->layoutRect(); + QRectF lr = d->layoutRect().toAlignedRect(); QStyleOption opt; opt.initFrom(this); #ifndef QT_NO_STYLE_STYLESHEET diff --git a/src/gui/widgets/qlineedit.h b/src/gui/widgets/qlineedit.h index 94e0dbe..667562b 100644 --- a/src/gui/widgets/qlineedit.h +++ b/src/gui/widgets/qlineedit.h @@ -283,6 +283,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_editFocusChange(bool)) #endif Q_PRIVATE_SLOT(d_func(), void _q_selectionChanged()) + Q_PRIVATE_SLOT(d_func(), void _q_updateNeeded(const QRect &)) }; #endif // QT_NO_LINEEDIT diff --git a/src/gui/widgets/qlineedit_p.cpp b/src/gui/widgets/qlineedit_p.cpp index 468c111..d705fa8 100644 --- a/src/gui/widgets/qlineedit_p.cpp +++ b/src/gui/widgets/qlineedit_p.cpp @@ -59,6 +59,13 @@ QT_BEGIN_NAMESPACE const int QLineEditPrivate::verticalMargin(1); const int QLineEditPrivate::horizontalMargin(2); +QRect QLineEditPrivate::adjustedControlRect(const QRect &rect) const +{ + QRect cr = adjustedContentsRect(); + int cix = cr.x() - hscroll + horizontalMargin; + return rect.translated(QPoint(cix, vscroll)); +} + int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const { QRect cr = adjustedContentsRect(); @@ -68,11 +75,7 @@ int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const QRect QLineEditPrivate::cursorRect() const { - QRect cr = adjustedContentsRect(); - int cix = cr.x() - hscroll + horizontalMargin; - QRect crect = control->cursorRect(); - crect.moveTo(crect.topLeft() + QPoint(cix, vscroll)); - return crect; + return adjustedControlRect(control->cursorRect()); } #ifndef QT_NO_COMPLETER @@ -141,6 +144,11 @@ void QLineEditPrivate::_q_selectionChanged() emit q->selectionChanged(); } +void QLineEditPrivate::_q_updateNeeded(const QRect &rect) +{ + q_func()->update(adjustedControlRect(rect)); +} + void QLineEditPrivate::init(const QString& txt) { Q_Q(QLineEdit); @@ -176,7 +184,7 @@ void QLineEditPrivate::init(const QString& txt) q, SLOT(update())); QObject::connect(control, SIGNAL(updateNeeded(QRect)), - q, SLOT(update())); + q, SLOT(_q_updateNeeded(QRect))); QStyleOptionFrameV2 opt; q->initStyleOption(&opt); @@ -216,9 +224,8 @@ void QLineEditPrivate::setCursorVisible(bool visible) if ((bool)cursorVisible == visible) return; cursorVisible = visible; - QRect r = cursorRect(); if (control->inputMask().isEmpty()) - q->update(r); + q->update(cursorRect()); else q->update(); } diff --git a/src/gui/widgets/qlineedit_p.h b/src/gui/widgets/qlineedit_p.h index 7a24cb3..b9f9c0b 100644 --- a/src/gui/widgets/qlineedit_p.h +++ b/src/gui/widgets/qlineedit_p.h @@ -94,6 +94,8 @@ public: #endif void init(const QString&); + QRect adjustedControlRect(const QRect &) const; + int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const; QRect cursorRect() const; void setCursorVisible(bool visible); @@ -129,6 +131,7 @@ public: void _q_editFocusChange(bool); #endif void _q_selectionChanged(); + void _q_updateNeeded(const QRect &); #ifndef QT_NO_COMPLETER void _q_completionHighlighted(QString); #endif diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index 1183be6..4ca11b0 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -1634,7 +1634,7 @@ QMenu *QMainWindow::createPopupMenu() Q_D(QMainWindow); QMenu *menu = 0; #ifndef QT_NO_DOCKWIDGET - QList<QDockWidget *> dockwidgets = qFindChildren<QDockWidget *>(this); + QList<QDockWidget *> dockwidgets = findChildren<QDockWidget *>(); if (dockwidgets.size()) { menu = new QMenu(this); for (int i = 0; i < dockwidgets.size(); ++i) { @@ -1648,7 +1648,7 @@ QMenu *QMainWindow::createPopupMenu() } #endif // QT_NO_DOCKWIDGET #ifndef QT_NO_TOOLBAR - QList<QToolBar *> toolbars = qFindChildren<QToolBar *>(this); + QList<QToolBar *> toolbars = findChildren<QToolBar *>(); if (toolbars.size()) { if (!menu) menu = new QMenu(this); diff --git a/src/gui/widgets/qmdisubwindow.cpp b/src/gui/widgets/qmdisubwindow.cpp index 62d297e..3f4cdc3 100644 --- a/src/gui/widgets/qmdisubwindow.cpp +++ b/src/gui/widgets/qmdisubwindow.cpp @@ -2203,7 +2203,7 @@ void QMdiSubWindowPrivate::setSizeGrip(QSizeGrip *newSizeGrip) void QMdiSubWindowPrivate::setSizeGripVisible(bool visible) const { // See if we can find any size grips - QList<QSizeGrip *> sizeGrips = qFindChildren<QSizeGrip *>(q_func()); + QList<QSizeGrip *> sizeGrips = q_func()->findChildren<QSizeGrip *>(); foreach (QSizeGrip *grip, sizeGrips) grip->setVisible(visible); } @@ -2319,7 +2319,7 @@ void QMdiSubWindow::setWidget(QWidget *widget) widget->setParent(this); #ifndef QT_NO_SIZEGRIP - QSizeGrip *sizeGrip = qFindChild<QSizeGrip *>(widget); + QSizeGrip *sizeGrip = widget->findChild<QSizeGrip *>(); if (sizeGrip) sizeGrip->installEventFilter(this); if (d->sizeGrip) diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 4bea6de..245657a 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -2804,7 +2804,7 @@ void QMenu::mouseMoveEvent(QMouseEvent *e) if (d->sloppyRegion.contains(e->pos())) { d->sloppyAction = action; QMenuPrivate::sloppyDelayTimer = startTimer(style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)*6); - } else { + } else if (action != d->currentAction) { d->setCurrentAction(action, style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)); } } diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm index aaa113b..60023a8 100644 --- a/src/gui/widgets/qmenu_mac.mm +++ b/src/gui/widgets/qmenu_mac.mm @@ -1254,15 +1254,11 @@ QMenuPrivate::QMacMenuPrivate::addAction(QMacMenuAction *action, QMacMenuAction NSString *keySequenceToKeyEqivalent(const QKeySequence &accel) { quint32 accel_key = (accel[0] & ~(Qt::MODIFIER_MASK | Qt::UNICODE_ACCEL)); - extern QChar qt_macSymbolForQtKey(int key); // qkeysequence.cpp - QChar keyEquiv = qt_macSymbolForQtKey(accel_key); - if (keyEquiv.isNull()) { - if (accel_key >= Qt::Key_F1 && accel_key <= Qt::Key_F15) - keyEquiv = (accel_key - Qt::Key_F1) + NSF1FunctionKey; - else - keyEquiv = unichar(QChar(accel_key).toLower().unicode()); - } - return [NSString stringWithCharacters:&keyEquiv.unicode() length:1]; + extern QChar qtKey2CocoaKey(Qt::Key key); + QChar cocoa_key = qtKey2CocoaKey(Qt::Key(accel_key)); + if (cocoa_key.isNull()) + cocoa_key = QChar(accel_key).toLower().unicode(); + return [NSString stringWithCharacters:&cocoa_key.unicode() length:1]; } // return the cocoa modifier mask for the QKeySequence (currently only looks at the first one). @@ -2052,8 +2048,7 @@ bool QMenuBar::macUpdateMenuBar() { #ifdef QT_MAC_USE_COCOA QMacCocoaAutoReleasePool pool; - if (!qt_cocoaPostMessage(getMenuLoader(), @selector(qtUpdateMenubar))) - return QMenuBarPrivate::macUpdateMenuBarImmediatly(); + qt_cocoaPostMessage(getMenuLoader(), @selector(qtUpdateMenubar)); return true; #else return QMenuBarPrivate::macUpdateMenuBarImmediatly(); diff --git a/src/gui/widgets/qmenu_symbian.cpp b/src/gui/widgets/qmenu_symbian.cpp index 83ba15a..652e65c 100644 --- a/src/gui/widgets/qmenu_symbian.cpp +++ b/src/gui/widgets/qmenu_symbian.cpp @@ -264,7 +264,8 @@ void qt_symbian_show_submenu( CEikMenuPane* menuPane, int id) // However if we don't have any items, we still need the item array. Otherwise // menupane will crash. That's why we create item array here manually, and // AddMenuItemL will then use the existing array. - CEikMenuPane::CItemArray* itemArray = q_check_ptr(new CEikMenuPane::CItemArray); + CEikMenuPane::CItemArray* itemArray = new CEikMenuPane::CItemArray; + Q_CHECK_PTR(itemArray); menuPane->SetItemArray(itemArray); menuPane->SetItemArrayOwnedExternally(EFalse); diff --git a/src/gui/widgets/qmenu_wince.cpp b/src/gui/widgets/qmenu_wince.cpp index e088db6..15d0116 100644 --- a/src/gui/widgets/qmenu_wince.cpp +++ b/src/gui/widgets/qmenu_wince.cpp @@ -113,8 +113,6 @@ static void resolveAygLibs() if (!aygResolved) { aygResolved = true; QLibrary aygLib(QLatin1String("aygshell")); - if (!aygLib.load()) - return; ptrCreateMenuBar = (AygCreateMenuBar) aygLib.resolve("SHCreateMenuBar"); ptrEnableSoftKey = (AygEnableSoftKey) aygLib.resolve("SHEnableSoftkey"); } diff --git a/src/gui/widgets/qradiobutton.cpp b/src/gui/widgets/qradiobutton.cpp index 20b6c720..56bd709 100644 --- a/src/gui/widgets/qradiobutton.cpp +++ b/src/gui/widgets/qradiobutton.cpp @@ -207,6 +207,14 @@ QSize QRadioButton::sizeHint() const /*! \reimp */ +QSize QRadioButton::minimumSizeHint() const +{ + return sizeHint(); +} + +/*! + \reimp +*/ bool QRadioButton::hitButton(const QPoint &pos) const { QStyleOptionButton opt; diff --git a/src/gui/widgets/qradiobutton.h b/src/gui/widgets/qradiobutton.h index 887b747..b7031e2 100644 --- a/src/gui/widgets/qradiobutton.h +++ b/src/gui/widgets/qradiobutton.h @@ -62,6 +62,7 @@ public: explicit QRadioButton(const QString &text, QWidget *parent=0); QSize sizeHint() const; + QSize minimumSizeHint() const; protected: bool event(QEvent *e); diff --git a/src/gui/widgets/qsizegrip.cpp b/src/gui/widgets/qsizegrip.cpp index c9d613a..b5b611c 100644 --- a/src/gui/widgets/qsizegrip.cpp +++ b/src/gui/widgets/qsizegrip.cpp @@ -78,15 +78,6 @@ static QWidget *qt_sizegrip_topLevelWidget(QWidget* w) return w; } -static inline bool hasHeightForWidth(QWidget *widget) -{ - if (!widget) - return false; - if (QLayout *layout = widget->layout()) - return layout->hasHeightForWidth(); - return widget->sizePolicy().hasHeightForWidth(); -} - class QSizeGripPrivate : public QWidgetPrivate { Q_DECLARE_PUBLIC(QSizeGrip) @@ -318,7 +309,7 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e) #ifdef Q_WS_X11 // Use a native X11 sizegrip for "real" top-level windows if supported. if (tlw->isWindow() && X11->isSupportedByWM(ATOM(_NET_WM_MOVERESIZE)) - && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw)) { + && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) { XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.message_type = ATOM(_NET_WM_MOVERESIZE); @@ -340,7 +331,7 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e) } #endif // Q_WS_X11 #ifdef Q_WS_WIN - if (tlw->isWindow() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw)) { + if (tlw->isWindow() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) { uint orientation = 0; if (d->atBottom()) orientation = d->atLeft() ? SZ_SIZEBOTTOMLEFT : SZ_SIZEBOTTOMRIGHT; @@ -429,12 +420,12 @@ void QSizeGrip::mouseMoveEvent(QMouseEvent * e) #ifdef Q_WS_X11 if (tlw->isWindow() && X11->isSupportedByWM(ATOM(_NET_WM_MOVERESIZE)) - && tlw->isTopLevel() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw)) + && tlw->isTopLevel() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) return; #endif #ifdef Q_WS_WIN if (tlw->isWindow() && GetSystemMenu(tlw->winId(), FALSE) != 0 && internalWinId() - && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw)) { + && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) { MSG msg; while(PeekMessage(&msg, winId(), WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)); return; diff --git a/src/gui/widgets/qspinbox.cpp b/src/gui/widgets/qspinbox.cpp index 2d871d0..10ce144 100644 --- a/src/gui/widgets/qspinbox.cpp +++ b/src/gui/widgets/qspinbox.cpp @@ -697,6 +697,9 @@ void QDoubleSpinBox::setSuffix(const QString &suffix) d->suffix = suffix; d->updateEdit(); + + d->cachedSizeHint = QSize(); + updateGeometry(); } /*! diff --git a/src/gui/widgets/qsplashscreen.cpp b/src/gui/widgets/qsplashscreen.cpp index 8be0cf8..2b6bfeb 100644 --- a/src/gui/widgets/qsplashscreen.cpp +++ b/src/gui/widgets/qsplashscreen.cpp @@ -64,7 +64,6 @@ public: int currAlign; inline QSplashScreenPrivate(); - void drawContents(); }; /*! @@ -121,10 +120,9 @@ public: perhaps Qt::WindowStaysOnTopHint. */ QSplashScreen::QSplashScreen(const QPixmap &pixmap, Qt::WindowFlags f) - : QWidget(*(new QSplashScreenPrivate()), 0, Qt::SplashScreen | f) + : QWidget(*(new QSplashScreenPrivate()), 0, Qt::SplashScreen | Qt::FramelessWindowHint | f) { - d_func()->pixmap = pixmap; - setPixmap(d_func()->pixmap); // Does an implicit repaint + setPixmap(pixmap); // Does an implicit repaint } /*! @@ -165,7 +163,6 @@ void QSplashScreen::mousePressEvent(QMouseEvent *) */ void QSplashScreen::repaint() { - d_func()->drawContents(); QWidget::repaint(); QApplication::flush(); } @@ -234,23 +231,13 @@ void QSplashScreen::setPixmap(const QPixmap &pixmap) { Q_D(QSplashScreen); - if (pixmap.hasAlpha()) { - QPixmap opaque(pixmap.size()); - QPainter p(&opaque); - p.fillRect(0, 0, pixmap.width(), pixmap.height(), palette().background()); - p.drawPixmap(0, 0, pixmap); - p.end(); - d->pixmap = opaque; - } else { - d->pixmap = pixmap; - } + d->pixmap = pixmap; + setAttribute(Qt::WA_TranslucentBackground, pixmap.hasAlpha()); - QRect r(0, 0, d->pixmap.size().width(), d->pixmap.size().height()); - resize(d->pixmap.size()); + QRect r(QPoint(), d->pixmap.size()); + resize(r.size()); move(QApplication::desktop()->screenGeometry().center() - r.center()); - if (!isVisible()) - d->drawContents(); - else + if (isVisible()) repaint(); } @@ -264,23 +251,6 @@ const QPixmap QSplashScreen::pixmap() const } /*! - \internal -*/ -void QSplashScreenPrivate::drawContents() -{ - Q_Q(QSplashScreen); - QPixmap textPix = pixmap; - if (!textPix.isNull()) { - QPainter painter(&textPix); - painter.initFrom(q); - q->drawContents(&painter); - QPalette p = q->palette(); - p.setBrush(q->backgroundRole(), QBrush(textPix)); - q->setPalette(p); - } -} - -/*! \internal */ inline QSplashScreenPrivate::QSplashScreenPrivate() : currAlign(Qt::AlignLeft) @@ -297,8 +267,7 @@ void QSplashScreen::drawContents(QPainter *painter) { Q_D(QSplashScreen); painter->setPen(d->currColor); - QRect r = rect(); - r.setRect(r.x() + 5, r.y() + 5, r.width() - 10, r.height() - 10); + QRect r = rect().adjusted(5, 5, -5, -5); if (Qt::mightBeRichText(d->currStatus)) { QTextDocument doc; #ifdef QT_NO_TEXTHTMLPARSER @@ -339,6 +308,13 @@ void QSplashScreen::drawContents(QPainter *painter) /*! \reimp */ bool QSplashScreen::event(QEvent *e) { + if (e->type() == QEvent::Paint) { + Q_D(QSplashScreen); + QPainter painter(this); + if (!d->pixmap.isNull()) + painter.drawPixmap(QPoint(), d->pixmap); + drawContents(&painter); + } return QWidget::event(e); } diff --git a/src/gui/widgets/qstackedwidget.cpp b/src/gui/widgets/qstackedwidget.cpp index de8d3e6..57b43b5 100644 --- a/src/gui/widgets/qstackedwidget.cpp +++ b/src/gui/widgets/qstackedwidget.cpp @@ -49,12 +49,54 @@ QT_BEGIN_NAMESPACE +/** + QStackedLayout does not support height for width (simply because it does not reimplement + heightForWidth() and hasHeightForWidth()). That is not possible to fix without breaking + binary compatibility. (QLayout is subject to multiple inheritance). + However, we can fix QStackedWidget by simply using a modified version of QStackedLayout + that reimplements the hfw-related functions: + */ +class QStackedLayoutHFW : public QStackedLayout +{ +public: + QStackedLayoutHFW(QWidget *parent = 0) : QStackedLayout(parent) {} + bool hasHeightForWidth() const; + int heightForWidth(int width) const; +}; + +bool QStackedLayoutHFW::hasHeightForWidth() const +{ + const int n = count(); + + for (int i = 0; i < n; ++i) { + if (QLayoutItem *item = itemAt(i)) { + if (item->hasHeightForWidth()) + return true; + } + } + return false; +} + +int QStackedLayoutHFW::heightForWidth(int width) const +{ + const int n = count(); + + int hfw = 0; + for (int i = 0; i < n; ++i) { + if (QLayoutItem *item = itemAt(i)) { + hfw = qMax(hfw, item->heightForWidth(width)); + } + } + return hfw; +} + + class QStackedWidgetPrivate : public QFramePrivate { Q_DECLARE_PUBLIC(QStackedWidget) public: QStackedWidgetPrivate():layout(0){} - QStackedLayout *layout; + QStackedLayoutHFW *layout; bool blockChildAdd; }; @@ -138,7 +180,7 @@ QStackedWidget::QStackedWidget(QWidget *parent) : QFrame(*new QStackedWidgetPrivate, parent) { Q_D(QStackedWidget); - d->layout = new QStackedLayout(this); + d->layout = new QStackedLayoutHFW(this); connect(d->layout, SIGNAL(widgetRemoved(int)), this, SIGNAL(widgetRemoved(int))); connect(d->layout, SIGNAL(currentChanged(int)), this, SIGNAL(currentChanged(int))); } diff --git a/src/gui/widgets/qtabbar.cpp b/src/gui/widgets/qtabbar.cpp index bbc7e5d..8a470ee 100644 --- a/src/gui/widgets/qtabbar.cpp +++ b/src/gui/widgets/qtabbar.cpp @@ -1292,6 +1292,8 @@ QSize QTabBar::sizeHint() const QSize QTabBar::minimumSizeHint() const { Q_D(const QTabBar); + if (d->layoutDirty) + const_cast<QTabBarPrivate*>(d)->layoutTabs(); if (!d->useScrollButtons) { QRect r; for (int i = 0; i < d->tabList.count(); ++i) @@ -1304,22 +1306,23 @@ QSize QTabBar::minimumSizeHint() const return QSize(d->rightB->sizeHint().width() * 2 + 75, sizeHint().height()); } +// Compute the most-elided possible text, for minimumSizeHint static QString computeElidedText(Qt::TextElideMode mode, const QString &text) { - if (text.length() <= 7) + if (text.length() <= 3) return text; static const QLatin1String Ellipses("..."); QString ret; switch (mode) { case Qt::ElideRight: - ret = text.left(4) + Ellipses; + ret = text.left(2) + Ellipses; break; case Qt::ElideMiddle: - ret = text.left(2) + Ellipses + text.right(2); + ret = text.left(1) + Ellipses + text.right(1); break; case Qt::ElideLeft: - ret = Ellipses + text.right(4); + ret = Ellipses + text.right(2); break; case Qt::ElideNone: ret = text; @@ -1966,7 +1969,7 @@ void QTabBar::keyPressEvent(QKeyEvent *event) event->ignore(); return; } - int offset = event->key() == (isRightToLeft() ? Qt::Key_Right : Qt::Key_Left) ? -1 : 1; + int offset = event->key() == (isRightToLeft() ? Qt::Key_Right : Qt::Key_Left) ? -1 : 1; d->setCurrentNextEnabledIndex(offset); } diff --git a/src/gui/widgets/qtabwidget.cpp b/src/gui/widgets/qtabwidget.cpp index 4a61935..82dfdef 100644 --- a/src/gui/widgets/qtabwidget.cpp +++ b/src/gui/widgets/qtabwidget.cpp @@ -195,6 +195,7 @@ public: void _q_removeTab(int); void _q_tabMoved(int from, int to); void init(); + bool hasHeightForWidth() const; QTabBar *tabs; QStackedWidget *stack; @@ -246,6 +247,15 @@ void QTabWidgetPrivate::init() } +bool QTabWidgetPrivate::hasHeightForWidth() const +{ + bool has = size_policy.hasHeightForWidth(); + if (!has && stack) + has = qt_widget_private(stack)->hasHeightForWidth(); + return has; +} + + /*! Initialize \a option with the values from this QTabWidget. This method is useful for subclasses when they need a QStyleOptionTabWidgetFrame, but don't want to fill @@ -816,8 +826,8 @@ QSize QTabWidget::sizeHint() const { Q_D(const QTabWidget); QSize lc(0, 0), rc(0, 0); - QStyleOption opt(0); - opt.init(this); + QStyleOptionTabWidgetFrameV2 opt; + initStyleOption(&opt); opt.state = QStyle::State_None; if (d->leftCornerWidget) @@ -865,14 +875,58 @@ QSize QTabWidget::minimumSizeHint() const QSize sz = basicSize(d->pos == North || d->pos == South, lc, rc, s, t); - QStyleOption opt(0); - opt.rect = rect(); + QStyleOptionTabWidgetFrameV2 opt; + initStyleOption(&opt); opt.palette = palette(); opt.state = QStyle::State_None; return style()->sizeFromContents(QStyle::CT_TabWidget, &opt, sz, this) .expandedTo(QApplication::globalStrut()); } +/* + \reimp +*/ +int QTabWidget::heightForWidth(int width) const +{ + Q_D(const QTabWidget); + QStyleOptionTabWidgetFrameV2 opt; + initStyleOption(&opt); + opt.state = QStyle::State_None; + + QSize zero(0,0); + const QSize padding = style()->sizeFromContents(QStyle::CT_TabWidget, &opt, zero, this) + .expandedTo(QApplication::globalStrut()); + + QSize lc(0, 0), rc(0, 0); + if (d->leftCornerWidget) + lc = d->leftCornerWidget->sizeHint(); + if(d->rightCornerWidget) + rc = d->rightCornerWidget->sizeHint(); + if (!d->dirty) { + QTabWidget *that = (QTabWidget*)this; + that->setUpLayout(true); + } + QSize t(d->tabs->sizeHint()); + + if(usesScrollButtons()) + t = t.boundedTo(QSize(200,200)); + else + t = t.boundedTo(QApplication::desktop()->size()); + + const bool tabIsHorizontal = (d->pos == North || d->pos == South); + const int contentsWidth = width - padding.width(); + int stackWidth = contentsWidth; + if (!tabIsHorizontal) + stackWidth -= qMax(t.width(), qMax(lc.width(), rc.width())); + + int stackHeight = d->stack->heightForWidth(stackWidth); + QSize s(stackWidth, stackHeight); + + QSize contentSize = basicSize(tabIsHorizontal, lc, rc, s, t); + return (contentSize + padding).expandedTo(QApplication::globalStrut()).height(); +} + + /*! \reimp */ diff --git a/src/gui/widgets/qtabwidget.h b/src/gui/widgets/qtabwidget.h index 68200c8..ee50655 100644 --- a/src/gui/widgets/qtabwidget.h +++ b/src/gui/widgets/qtabwidget.h @@ -129,6 +129,7 @@ public: QSize sizeHint() const; QSize minimumSizeHint() const; + int heightForWidth(int width) const; void setCornerWidget(QWidget * w, Qt::Corner corner = Qt::TopRightCorner); QWidget * cornerWidget(Qt::Corner corner = Qt::TopRightCorner) const; diff --git a/src/gui/widgets/qtoolbutton.cpp b/src/gui/widgets/qtoolbutton.cpp index 1822db8..c18f660 100644 --- a/src/gui/widgets/qtoolbutton.cpp +++ b/src/gui/widgets/qtoolbutton.cpp @@ -394,9 +394,6 @@ void QToolButton::initStyleOption(QStyleOptionToolButton *option) const option->toolButtonStyle = Qt::ToolButtonTextOnly; else if (option->toolButtonStyle != Qt::ToolButtonTextOnly) option->toolButtonStyle = Qt::ToolButtonIconOnly; - } else { - if (d->text.isEmpty() && option->toolButtonStyle != Qt::ToolButtonIconOnly) - option->toolButtonStyle = Qt::ToolButtonIconOnly; } option->pos = pos(); diff --git a/src/gui/widgets/qworkspace.cpp b/src/gui/widgets/qworkspace.cpp index 7180c4d..5cf67a5 100644 --- a/src/gui/widgets/qworkspace.cpp +++ b/src/gui/widgets/qworkspace.cpp @@ -2923,7 +2923,7 @@ void QWorkspaceChild::setActive(bool b) iconw->setActive(act); update(); - QList<QWidget*> wl = qFindChildren<QWidget*>(childWidget); + QList<QWidget*> wl = childWidget->findChildren<QWidget*>(); if (act) { for (int i = 0; i < wl.size(); ++i) { QWidget *w = wl.at(i); diff --git a/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp b/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp index ecd03e5..19f3b3c 100644 --- a/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp +++ b/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp @@ -127,7 +127,7 @@ QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const } } - delete streams; + delete[] streams; } } @@ -201,7 +201,7 @@ QList<int> QAudioDeviceInfoInternal::frequencyList() rc << vr[i].mMaximum; } - delete vr; + delete[] vr; } } @@ -345,7 +345,7 @@ QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode) } } - delete audioDevices; + delete[] audioDevices; } } diff --git a/src/multimedia/video/qvideosurfaceformat.cpp b/src/multimedia/video/qvideosurfaceformat.cpp index 3afbdc9..3ec40e8 100644 --- a/src/multimedia/video/qvideosurfaceformat.cpp +++ b/src/multimedia/video/qvideosurfaceformat.cpp @@ -502,11 +502,11 @@ QList<QByteArray> QVideoSurfaceFormat::propertyNames() const QVariant QVideoSurfaceFormat::property(const char *name) const { if (qstrcmp(name, "handleType") == 0) { - return qVariantFromValue(d->handleType); + return QVariant::fromValue(d->handleType); } else if (qstrcmp(name, "pixelFormat") == 0) { - return qVariantFromValue(d->pixelFormat); + return QVariant::fromValue(d->pixelFormat); } else if (qstrcmp(name, "handleType") == 0) { - return qVariantFromValue(d->handleType); + return QVariant::fromValue(d->handleType); } else if (qstrcmp(name, "frameSize") == 0) { return d->frameSize; } else if (qstrcmp(name, "frameWidth") == 0) { @@ -516,15 +516,15 @@ QVariant QVideoSurfaceFormat::property(const char *name) const } else if (qstrcmp(name, "viewport") == 0) { return d->viewport; } else if (qstrcmp(name, "scanLineDirection") == 0) { - return qVariantFromValue(d->scanLineDirection); + return QVariant::fromValue(d->scanLineDirection); } else if (qstrcmp(name, "frameRate") == 0) { - return qVariantFromValue(d->frameRate); + return QVariant::fromValue(d->frameRate); } else if (qstrcmp(name, "pixelAspectRatio") == 0) { - return qVariantFromValue(d->pixelAspectRatio); + return QVariant::fromValue(d->pixelAspectRatio); } else if (qstrcmp(name, "sizeHint") == 0) { return sizeHint(); } else if (qstrcmp(name, "yCbCrColorSpace") == 0) { - return qVariantFromValue(d->ycbcrColorSpace); + return QVariant::fromValue(d->ycbcrColorSpace); } else { int id = 0; for (; id < d->propertyNames.count() && d->propertyNames.at(id) != name; ++id) {} @@ -546,7 +546,7 @@ void QVideoSurfaceFormat::setProperty(const char *name, const QVariant &value) } else if (qstrcmp(name, "pixelFormat") == 0) { // read only. } else if (qstrcmp(name, "frameSize") == 0) { - if (qVariantCanConvert<QSize>(value)) { + if (value.canConvert<QSize>()) { d->frameSize = qvariant_cast<QSize>(value); d->viewport = QRect(QPoint(0, 0), d->frameSize); } @@ -555,21 +555,21 @@ void QVideoSurfaceFormat::setProperty(const char *name, const QVariant &value) } else if (qstrcmp(name, "frameHeight") == 0) { // read only. } else if (qstrcmp(name, "viewport") == 0) { - if (qVariantCanConvert<QRect>(value)) + if (value.canConvert<QRect>()) d->viewport = qvariant_cast<QRect>(value); } else if (qstrcmp(name, "scanLineDirection") == 0) { - if (qVariantCanConvert<Direction>(value)) + if (value.canConvert<Direction>()) d->scanLineDirection = qvariant_cast<Direction>(value); } else if (qstrcmp(name, "frameRate") == 0) { - if (qVariantCanConvert<qreal>(value)) + if (value.canConvert<qreal>()) d->frameRate = qvariant_cast<qreal>(value); } else if (qstrcmp(name, "pixelAspectRatio") == 0) { - if (qVariantCanConvert<QSize>(value)) + if (value.canConvert<QSize>()) d->pixelAspectRatio = qvariant_cast<QSize>(value); } else if (qstrcmp(name, "sizeHint") == 0) { // read only. } else if (qstrcmp(name, "yCbCrColorSpace") == 0) { - if (qVariantCanConvert<YCbCrColorSpace>(value)) + if (value.canConvert<YCbCrColorSpace>()) d->ycbcrColorSpace = qvariant_cast<YCbCrColorSpace>(value); } else { int id = 0; diff --git a/src/network/access/qfilenetworkreply.cpp b/src/network/access/qfilenetworkreply.cpp index 4ac9a8c..8c0fd17 100644 --- a/src/network/access/qfilenetworkreply.cpp +++ b/src/network/access/qfilenetworkreply.cpp @@ -68,10 +68,9 @@ QFileNetworkReply::QFileNetworkReply(QObject *parent, const QNetworkRequest &req setRequest(req); setUrl(req.url()); setOperation(op); + setFinished(true); QNetworkReply::open(QIODevice::ReadOnly); - qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError"); - QFileNetworkReplyPrivate *d = (QFileNetworkReplyPrivate*) d_func(); QUrl url = req.url(); @@ -141,12 +140,6 @@ QFileNetworkReply::QFileNetworkReply(QObject *parent, const QNetworkRequest &req QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); } - -bool QFileNetworkReplyPrivate::isFinished() const -{ - return true; -} - void QFileNetworkReply::close() { Q_D(QFileNetworkReply); diff --git a/src/network/access/qfilenetworkreply_p.h b/src/network/access/qfilenetworkreply_p.h index 710ec9f..227c775 100644 --- a/src/network/access/qfilenetworkreply_p.h +++ b/src/network/access/qfilenetworkreply_p.h @@ -92,8 +92,6 @@ public: qint64 fileSize; qint64 filePos; - virtual bool isFinished() const; - Q_DECLARE_PUBLIC(QFileNetworkReply) }; diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index ccdbb20..2ab28c7 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -117,6 +117,7 @@ void QHttpNetworkConnectionPrivate::init() { for (int i = 0; i < channelCount; i++) { channels[i].setConnection(this->q_func()); + channels[i].ssl = encrypt; channels[i].init(); } } @@ -530,33 +531,35 @@ void QHttpNetworkConnectionPrivate::fillPipeline(QAbstractSocket *socket) || channels[i].state == QHttpNetworkConnectionChannel::ReadingState)) return; - - //qDebug() << "QHttpNetworkConnectionPrivate::fillPipeline processing highPriorityQueue, size=" << highPriorityQueue.size() << " alreadyPipelined=" << channels[i].alreadyPipelinedRequests.length(); int lengthBefore; while (!highPriorityQueue.isEmpty()) { lengthBefore = channels[i].alreadyPipelinedRequests.length(); fillPipeline(highPriorityQueue, channels[i]); - if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) + if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) { + channels[i].pipelineFlush(); return; + } if (lengthBefore == channels[i].alreadyPipelinedRequests.length()) break; // did not process anything, now do the low prio queue } - //qDebug() << "QHttpNetworkConnectionPrivate::fillPipeline processing lowPriorityQueue, size=" << lowPriorityQueue.size() << " alreadyPipelined=" << channels[i].alreadyPipelinedRequests.length(); while (!lowPriorityQueue.isEmpty()) { lengthBefore = channels[i].alreadyPipelinedRequests.length(); fillPipeline(lowPriorityQueue, channels[i]); - if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) + if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) { + channels[i].pipelineFlush(); return; + } if (lengthBefore == channels[i].alreadyPipelinedRequests.length()) break; // did not process anything } + channels[i].pipelineFlush(); } // returns true when the processing of a queue has been done diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 6437f6f..e39f9ed 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel() : socket(0) + , ssl(false) , state(IdleState) , reply(0) , written(0) @@ -90,11 +91,8 @@ void QHttpNetworkConnectionChannel::init() #else socket = new QTcpSocket; #endif - - // limit the socket read buffer size. we will read everything into - // the QHttpNetworkReply anyway, so let's grow only that and not - // here and there. - socket->setReadBufferSize(64*1024); + // Set by QNAM anyway, but let's be safe here + socket->setProxy(QNetworkProxy::NoProxy); QObject::connect(socket, SIGNAL(bytesWritten(qint64)), this, SLOT(_q_bytesWritten(qint64)), @@ -164,11 +162,12 @@ bool QHttpNetworkConnectionChannel::sendRequest() written = 0; // excluding the header bytesTotal = 0; - reply->d_func()->clear(); - reply->d_func()->connection = connection; - reply->d_func()->connectionChannel = this; - reply->d_func()->autoDecompress = request.d->autoDecompress; - reply->d_func()->pipeliningUsed = false; + QHttpNetworkReplyPrivate *replyPrivate = reply->d_func(); + replyPrivate->clear(); + replyPrivate->connection = connection; + replyPrivate->connectionChannel = this; + replyPrivate->autoDecompress = request.d->autoDecompress; + replyPrivate->pipeliningUsed = false; pendingEncrypt = false; // if the url contains authentication parameters, use the new ones @@ -328,7 +327,6 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() return; } - qint64 bytes = 0; QAbstractSocket::SocketState socketState = socket->state(); // connection might be closed to signal the end of data @@ -349,12 +347,14 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() } // read loop for the response - while (socket->bytesAvailable()) { + qint64 bytes = 0; + qint64 lastBytes = bytes; + do { + lastBytes = bytes; + QHttpNetworkReplyPrivate::ReplyState state = reply->d_func()->state; switch (state) { case QHttpNetworkReplyPrivate::NothingDoneState: { - // only eat whitespace on the first call - eatWhitespace(); state = reply->d_func()->state = QHttpNetworkReplyPrivate::ReadingStatusState; // fallthrough } @@ -378,6 +378,7 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() return; } bytes += headerBytes; + // If headers were parsed successfully now it is the ReadingDataState if (replyPrivate->state == QHttpNetworkReplyPrivate::ReadingDataState) { if (replyPrivate->isGzipped() && replyPrivate->autoDecompress) { // remove the Content-Length from header @@ -392,6 +393,10 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() } if (replyPrivate->shouldEmitSignals()) emit reply->headerChanged(); + // After headerChanged had been emitted + // we can suddenly have a replyPrivate->userProvidedDownloadBuffer + // this is handled in the ReadingDataState however + if (!replyPrivate->expectContent()) { replyPrivate->state = QHttpNetworkReplyPrivate::AllDoneState; allDone(); @@ -412,22 +417,27 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() return; } - if (!replyPrivate->isChunked() && !replyPrivate->autoDecompress - && replyPrivate->bodyLength > 0) { - // bulk files like images should fulfill these properties and - // we can therefore save on memory copying - bytes = replyPrivate->readBodyFast(socket, &replyPrivate->responseData); - replyPrivate->totalProgress += bytes; + if (replyPrivate->userProvidedDownloadBuffer) { + // the user provided a direct buffer where we should put all our data in. + // this only works when we can tell the user the content length and he/she can allocate + // the buffer in that size. + // note that this call will read only from the still buffered data + qint64 haveRead = replyPrivate->readBodyVeryFast(socket, replyPrivate->userProvidedDownloadBuffer + replyPrivate->totalProgress); + bytes += haveRead; + replyPrivate->totalProgress += haveRead; + + // the user will get notified of it via progress signal + emit reply->dataReadProgress(replyPrivate->totalProgress, replyPrivate->bodyLength); + } else if (!replyPrivate->isChunked() && !replyPrivate->autoDecompress + && replyPrivate->bodyLength > 0) { + // bulk files like images should fulfill these properties and + // we can therefore save on memory copying + qint64 haveRead = replyPrivate->readBodyFast(socket, &replyPrivate->responseData); + bytes += haveRead; + replyPrivate->totalProgress += haveRead; if (replyPrivate->shouldEmitSignals()) { - QPointer<QHttpNetworkReply> replyPointer = reply; emit reply->readyRead(); - // make sure that the reply is valid - if (replyPointer.isNull()) - return; emit reply->dataReadProgress(replyPrivate->totalProgress, replyPrivate->bodyLength); - // make sure that the reply is valid - if (replyPointer.isNull()) - return; } } else @@ -435,8 +445,9 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() // use the traditional slower reading (for compressed encoding, chunked encoding, // no content-length etc) QByteDataBuffer byteDatas; - bytes = replyPrivate->readBody(socket, &byteDatas); - if (bytes) { + qint64 haveRead = replyPrivate->readBody(socket, &byteDatas); + if (haveRead) { + bytes += haveRead; if (replyPrivate->autoDecompress) replyPrivate->appendCompressedReplyData(byteDatas); else @@ -445,17 +456,10 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() if (!replyPrivate->autoDecompress) { replyPrivate->totalProgress += bytes; if (replyPrivate->shouldEmitSignals()) { - QPointer<QHttpNetworkReply> replyPointer = reply; // important: At the point of this readyRead(), the byteDatas list must be empty, // else implicit sharing will trigger memcpy when the user is reading data! emit reply->readyRead(); - // make sure that the reply is valid - if (replyPointer.isNull()) - return; emit reply->dataReadProgress(replyPrivate->totalProgress, replyPrivate->bodyLength); - // make sure that the reply is valid - if (replyPointer.isNull()) - return; } } #ifndef QT_NO_COMPRESS @@ -477,7 +481,7 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() default: break; } - } + } while (bytes != lastBytes && reply); } // called when unexpectedly reading a -1 or when data is expected but socket is closed @@ -520,7 +524,7 @@ bool QHttpNetworkConnectionChannel::ensureConnection() if (socketState != QAbstractSocket::ConnectedState) { // connect to the host if not already connected. state = QHttpNetworkConnectionChannel::ConnectingState; - pendingEncrypt = connection->d_func()->encrypt; + pendingEncrypt = ssl; // reset state pipeliningSupported = PipeliningSupportUnknown; @@ -543,23 +547,43 @@ bool QHttpNetworkConnectionChannel::ensureConnection() #ifndef QT_NO_NETWORKPROXY // HTTPS always use transparent proxy. - if (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy && !connection->d_func()->encrypt) { + if (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy && !ssl) { connectHost = connection->d_func()->networkProxy.hostName(); connectPort = connection->d_func()->networkProxy.port(); } #endif - if (connection->d_func()->encrypt) { + if (ssl) { #ifndef QT_NO_OPENSSL QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket); sslSocket->connectToHostEncrypted(connectHost, connectPort); if (ignoreAllSslErrors) sslSocket->ignoreSslErrors(); sslSocket->ignoreSslErrors(ignoreSslErrorsList); + + // limit the socket read buffer size. we will read everything into + // the QHttpNetworkReply anyway, so let's grow only that and not + // here and there. + socket->setReadBufferSize(64*1024); #else connection->d_func()->emitReplyError(socket, reply, QNetworkReply::ProtocolUnknownError); #endif } else { - socket->connectToHost(connectHost, connectPort); + // In case of no proxy we can use the Unbuffered QTcpSocket + if (connection->d_func()->networkProxy.type() == QNetworkProxy::NoProxy + && connection->cacheProxy().type() == QNetworkProxy::NoProxy + && connection->transparentProxy().type() == QNetworkProxy::NoProxy) { + socket->connectToHost(connectHost, connectPort, QIODevice::ReadWrite | QIODevice::Unbuffered); + // For an Unbuffered QTcpSocket, the read buffer size has a special meaning. + socket->setReadBufferSize(1*1024); + + } else { + socket->connectToHost(connectHost, connectPort); + + // limit the socket read buffer size. we will read everything into + // the QHttpNetworkReply anyway, so let's grow only that and not + // here and there. + socket->setReadBufferSize(64*1024); + } } return false; } @@ -589,18 +613,10 @@ bool QHttpNetworkConnectionChannel::expand(bool dataComplete) reply->d_func()->totalProgress += inflated.size(); reply->d_func()->appendUncompressedReplyData(inflated); if (reply->d_func()->shouldEmitSignals()) { - QPointer<QHttpNetworkReply> replyPointer = reply; // important: At the point of this readyRead(), inflated must be cleared, // else implicit sharing will trigger memcpy when the user is reading data! emit reply->readyRead(); - // make sure that the reply is valid - if (replyPointer.isNull()) - return true; emit reply->dataReadProgress(reply->d_func()->totalProgress, 0); - // make sure that the reply is valid - if (replyPointer.isNull()) - return true; - } } } else { @@ -678,10 +694,15 @@ void QHttpNetworkConnectionChannel::allDone() // this was wrong, allDone gets called from that function anyway. } } else if (alreadyPipelinedRequests.isEmpty() && socket->bytesAvailable() > 0) { - eatWhitespace(); // this is weird. we had nothing pipelined but still bytes available. better close it. - if (socket->bytesAvailable() > 0) - close(); + //if (socket->bytesAvailable() > 0) + // close(); + // + // FIXME + // We do not close it anymore now, but should introduce this again after having fixed + // the chunked decoder in QHttpNetworkReply to read the whitespace after the last chunk. + // (Currently this is worked around by readStatus in the QHttpNetworkReply ignoring + // leading whitespace. QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } else if (alreadyPipelinedRequests.isEmpty()) { if (qobject_cast<QHttpNetworkConnection*>(connection)) @@ -728,30 +749,6 @@ void QHttpNetworkConnectionChannel::requeueCurrentlyPipelinedRequests() QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } -void QHttpNetworkConnectionChannel::eatWhitespace() -{ - char c; - do { - qint64 ret = socket->peek(&c, 1); - - // nothing read, fine. - if (ret == 0) - return; - - // EOF from socket? - if (ret == -1) - return; // FIXME, we need to stop processing. however the next stuff done will also do that. - - // read all whitespace and line endings - if (c == 11 || c == '\n' || c == '\r' || c == ' ' || c == 31) { - socket->read(&c, 1); - continue; - } else { - break; - } - } while(true); -} - void QHttpNetworkConnectionChannel::handleStatus() { Q_ASSERT(socket); @@ -813,7 +810,7 @@ bool QHttpNetworkConnectionChannel::resetUploadData() } -void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair) +void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair) { // this is only called for simple GET @@ -826,16 +823,32 @@ void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair) reply->d_func()->pipeliningUsed = true; #ifndef QT_NO_NETWORKPROXY - QByteArray header = QHttpNetworkRequestPrivate::header(request, - (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy)); + pipeline.append(QHttpNetworkRequestPrivate::header(request, + (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy))); #else - QByteArray header = QHttpNetworkRequestPrivate::header(request, false); + pipeline.append(QHttpNetworkRequestPrivate::header(request, false)); #endif - socket->write(header); alreadyPipelinedRequests.append(pair); + + // pipelineFlush() needs to be called at some point afterwards } +void QHttpNetworkConnectionChannel::pipelineFlush() +{ + if (pipeline.isEmpty()) + return; + + // The goal of this is so that we have everything in one TCP packet. + // For the Unbuffered QTcpSocket this is manually needed, the buffered + // QTcpSocket does it automatically. + // Also, sometimes the OS does it for us (Nagle's algorithm) but that + // happens only sometimes. + socket->write(pipeline); + pipeline.clear(); +} + + void QHttpNetworkConnectionChannel::closeAndResendCurrentRequest() { requeueCurrentlyPipelinedRequests(); @@ -868,6 +881,19 @@ bool QHttpNetworkConnectionChannel::isSocketReading() const //private slots void QHttpNetworkConnectionChannel::_q_readyRead() { + // We got a readyRead but no bytes are available.. + // This happens for the Unbuffered QTcpSocket + // Also check if socket is in ConnectedState since + // this function may also be invoked via the event loop. + if (socket->state() == QAbstractSocket::ConnectedState && socket->bytesAvailable() == 0) { + char c; + qint64 ret = socket->peek(&c, 1); + if (ret < 0) { + socket->disconnectFromHost(); + return; + } + } + if (isSocketWaiting() || isSocketReading()) { state = QHttpNetworkConnectionChannel::ReadingState; if (reply) diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 41a896d..4f3a65c 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -99,6 +99,7 @@ public: BusyState = (ConnectingState|WritingState|WaitingState|ReadingState|Wait4AuthState) }; QAbstractSocket *socket; + bool ssl; ChannelState state; QHttpNetworkRequest request; // current request QHttpNetworkReply *reply; // current reply for this request @@ -125,7 +126,11 @@ public: }; PipeliningSupport pipeliningSupported; QList<HttpMessagePair> alreadyPipelinedRequests; - + QByteArray pipeline; // temporary buffer that gets sent to socket in pipelineFlush + void pipelineInto(HttpMessagePair &pair); + void pipelineFlush(); + void requeueCurrentlyPipelinedRequests(); + void detectPipeliningSupport(); QHttpNetworkConnectionChannel(); @@ -145,15 +150,9 @@ public: bool resetUploadData(); // return true if resetting worked or there is no upload data - void pipelineInto(HttpMessagePair &pair); - void requeueCurrentlyPipelinedRequests(); - void detectPipeliningSupport(); - void handleUnexpectedEOF(); void closeAndResendCurrentRequest(); - void eatWhitespace(); - bool isSocketBusy() const; bool isSocketWriting() const; bool isSocketWaiting() const; diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 108ba8a..1c55482 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -119,6 +119,7 @@ void QHttpNetworkReply::setRequest(const QHttpNetworkRequest &request) { Q_D(QHttpNetworkReply); d->request = request; + d->ssl = request.isSsl(); } int QHttpNetworkReply::statusCode() const @@ -195,6 +196,25 @@ void QHttpNetworkReply::setDownstreamLimited(bool dsl) d->connection->d_func()->readMoreLater(this); } +bool QHttpNetworkReply::supportsUserProvidedDownloadBuffer() +{ + Q_D(QHttpNetworkReply); + return (!d->isChunked() && !d->autoDecompress && d->bodyLength > 0); +} + +void QHttpNetworkReply::setUserProvidedDownloadBuffer(char* b) +{ + Q_D(QHttpNetworkReply); + if (supportsUserProvidedDownloadBuffer()) + d->userProvidedDownloadBuffer = b; +} + +char* QHttpNetworkReply::userProvidedDownloadBuffer() +{ + Q_D(QHttpNetworkReply); + return d->userProvidedDownloadBuffer; +} + bool QHttpNetworkReply::isFinished() const { return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState; @@ -207,7 +227,10 @@ bool QHttpNetworkReply::isPipeliningUsed() const QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) - : QHttpNetworkHeaderPrivate(newUrl), state(NothingDoneState), statusCode(100), + : QHttpNetworkHeaderPrivate(newUrl) + , state(NothingDoneState) + , ssl(false) + , statusCode(100), majorVersion(0), minorVersion(0), bodyLength(0), contentRead(0), totalProgress(0), chunkedTransferEncoding(false), connectionCloseEnabled(true), @@ -215,6 +238,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false), autoDecompress(false), responseData(), requestIsPrepared(false) ,pipeliningUsed(false), downstreamLimited(false) + ,userProvidedDownloadBuffer(0) { } @@ -448,6 +472,8 @@ qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket) return -1; // unexpected EOF else if (haveRead == 0) break; // read more later + else if (haveRead == 1 && bytes == 0 && (c == 11 || c == '\n' || c == '\r' || c == ' ' || c == 31)) + continue; // Ignore all whitespace that was trailing froma previous request on that socket bytes++; @@ -623,12 +649,32 @@ bool QHttpNetworkReplyPrivate::isConnectionCloseEnabled() // note this function can only be used for non-chunked, non-compressed with // known content length +qint64 QHttpNetworkReplyPrivate::readBodyVeryFast(QAbstractSocket *socket, char *b) +{ + // This first read is to flush the buffer inside the socket + qint64 haveRead = 0; + haveRead = socket->read(b, bodyLength - contentRead); + if (haveRead == -1) { + return 0; // ### error checking here; + } + contentRead += haveRead; + + if (contentRead == bodyLength) { + state = AllDoneState; + } + + return haveRead; +} + +// note this function can only be used for non-chunked, non-compressed with +// known content length qint64 QHttpNetworkReplyPrivate::readBodyFast(QAbstractSocket *socket, QByteDataBuffer *rb) { + qint64 toBeRead = qMin(socket->bytesAvailable(), bodyLength - contentRead); QByteArray bd; bd.resize(toBeRead); - qint64 haveRead = socket->read(bd.data(), bd.size()); + qint64 haveRead = socket->read(bd.data(), toBeRead); if (haveRead == -1) { bd.clear(); return 0; // ### error checking here; @@ -650,29 +696,34 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QByteDataBuff { qint64 bytes = 0; if (isChunked()) { - bytes += readReplyBodyChunked(socket, out); // chunked transfer encoding (rfc 2616, sec 3.6) - } else if (bodyLength > 0) { // we have a Content-Length + // chunked transfer encoding (rfc 2616, sec 3.6) + bytes += readReplyBodyChunked(socket, out); + } else if (bodyLength > 0) { + // we have a Content-Length bytes += readReplyBodyRaw(socket, out, bodyLength - contentRead); if (contentRead + bytes == bodyLength) state = AllDoneState; } else { + // no content length. just read what's possible bytes += readReplyBodyRaw(socket, out, socket->bytesAvailable()); } contentRead += bytes; return bytes; } -qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QIODevice *in, QByteDataBuffer *out, qint64 size) +qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QAbstractSocket *socket, QByteDataBuffer *out, qint64 size) { + // FIXME get rid of this function and just use readBodyFast and give it socket->bytesAvailable() qint64 bytes = 0; - Q_ASSERT(in); + Q_ASSERT(socket); Q_ASSERT(out); - int toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, in->bytesAvailable())); + int toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, socket->bytesAvailable())); + while (toBeRead > 0) { QByteArray byteData; byteData.resize(toBeRead); - qint64 haveRead = in->read(byteData.data(), byteData.size()); + qint64 haveRead = socket->read(byteData.data(), byteData.size()); if (haveRead <= 0) { // ### error checking here byteData.clear(); @@ -684,25 +735,35 @@ qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QIODevice *in, QByteDataBuffer bytes += haveRead; size -= haveRead; - toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, in->bytesAvailable())); + toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, socket->bytesAvailable())); } return bytes; } -qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QByteDataBuffer *out) +qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QAbstractSocket *socket, QByteDataBuffer *out) { qint64 bytes = 0; - while (in->bytesAvailable()) { // while we can read from input - // if we are done with the current chunk, get the size of the new chunk + while (socket->bytesAvailable()) { if (currentChunkRead >= currentChunkSize) { + // For the first chunk and when we're done with a chunk currentChunkSize = 0; currentChunkRead = 0; if (bytes) { + // After a chunk char crlf[2]; - bytes += in->read(crlf, 2); // read the "\r\n" after the chunk + // read the "\r\n" after the chunk + qint64 haveRead = socket->read(crlf, 2); + // FIXME: This code is slightly broken and not optimal. What if the 2 bytes are not available yet?! + // For nice reasons (the toLong in getChunkSize accepting \n at the beginning + // it right now still works, but we should definitely fix this. + + if (haveRead != 2) + return bytes; // FIXME + bytes += haveRead; } - bytes += getChunkSize(in, ¤tChunkSize); + // Note that chunk size gets stored in currentChunkSize, what is returned is the bytes read + bytes += getChunkSize(socket, ¤tChunkSize); if (currentChunkSize == -1) break; } @@ -712,8 +773,8 @@ qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QByteDataBu break; } - // otherwise, try to read what is missing for this chunk - qint64 haveRead = readReplyBodyRaw (in, out, currentChunkSize - currentChunkRead); + // otherwise, try to begin reading this chunk / to read what is missing for this chunk + qint64 haveRead = readReplyBodyRaw (socket, out, currentChunkSize - currentChunkRead); currentChunkRead += haveRead; bytes += haveRead; @@ -723,22 +784,25 @@ qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QByteDataBu return bytes; } -qint64 QHttpNetworkReplyPrivate::getChunkSize(QIODevice *in, qint64 *chunkSize) +qint64 QHttpNetworkReplyPrivate::getChunkSize(QAbstractSocket *socket, qint64 *chunkSize) { qint64 bytes = 0; char crlf[2]; *chunkSize = -1; - int bytesAvailable = in->bytesAvailable(); + + int bytesAvailable = socket->bytesAvailable(); + // FIXME rewrite to permanent loop without bytesAvailable while (bytesAvailable > bytes) { - qint64 sniffedBytes = in->peek(crlf, 2); + qint64 sniffedBytes = socket->peek(crlf, 2); int fragmentSize = fragment.size(); + // check the next two bytes for a "\r\n", skip blank lines if ((fragmentSize && sniffedBytes == 2 && crlf[0] == '\r' && crlf[1] == '\n') ||(fragmentSize > 1 && fragment.endsWith('\r') && crlf[0] == '\n')) { - bytes += in->read(crlf, 1); // read the \r or \n + bytes += socket->read(crlf, 1); // read the \r or \n if (crlf[0] == '\r') - bytes += in->read(crlf, 1); // read the \n + bytes += socket->read(crlf, 1); // read the \n bool ok = false; // ignore the chunk-extension fragment = fragment.mid(0, fragment.indexOf(';')).trimmed(); @@ -748,10 +812,15 @@ qint64 QHttpNetworkReplyPrivate::getChunkSize(QIODevice *in, qint64 *chunkSize) } else { // read the fragment to the buffer char c = 0; - bytes += in->read(&c, 1); + qint64 haveRead = socket->read(&c, 1); + if (haveRead < 0) { + return -1; // FIXME + } + bytes += haveRead; fragment.append(c); } } + return bytes; } diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 4011c78..02ce248 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -128,6 +128,10 @@ public: QByteArray readAny(); void setDownstreamLimited(bool t); + bool supportsUserProvidedDownloadBuffer(); + void setUserProvidedDownloadBuffer(char*); + char* userProvidedDownloadBuffer(); + bool isFinished() const; bool isPipeliningUsed() const; @@ -147,6 +151,7 @@ Q_SIGNALS: void finished(); void finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail = QString()); void headerChanged(); + // FIXME we need to change this to qint64! void dataReadProgress(int done, int total); void dataSendProgress(qint64 done, qint64 total); @@ -168,15 +173,16 @@ public: qint64 readHeader(QAbstractSocket *socket); void parseHeader(const QByteArray &header); qint64 readBody(QAbstractSocket *socket, QByteDataBuffer *out); + qint64 readBodyVeryFast(QAbstractSocket *socket, char *b); qint64 readBodyFast(QAbstractSocket *socket, QByteDataBuffer *rb); bool findChallenge(bool forProxy, QByteArray &challenge) const; QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const; void clear(); void clearHttpLayerInformation(); - qint64 readReplyBodyRaw(QIODevice *in, QByteDataBuffer *out, qint64 size); - qint64 readReplyBodyChunked(QIODevice *in, QByteDataBuffer *out); - qint64 getChunkSize(QIODevice *in, qint64 *chunkSize); + qint64 readReplyBodyRaw(QAbstractSocket *in, QByteDataBuffer *out, qint64 size); + qint64 readReplyBodyChunked(QAbstractSocket *in, QByteDataBuffer *out); + qint64 getChunkSize(QAbstractSocket *in, qint64 *chunkSize); void appendUncompressedReplyData(QByteArray &qba); void appendUncompressedReplyData(QByteDataBuffer &data); @@ -205,6 +211,7 @@ public: } state; QHttpNetworkRequest request; + bool ssl; int statusCode; int majorVersion; int minorVersion; @@ -234,6 +241,8 @@ public: bool pipeliningUsed; bool downstreamLimited; + + char* userProvidedDownloadBuffer; }; diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp index 639025e..d2f3212 100644 --- a/src/network/access/qhttpnetworkrequest.cpp +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -63,6 +63,7 @@ QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequest pipeliningAllowed = other.pipeliningAllowed; customVerb = other.customVerb; withCredentials = other.withCredentials; + ssl = other.ssl; } QHttpNetworkRequestPrivate::~QHttpNetworkRequestPrivate() @@ -73,6 +74,7 @@ bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &ot { return QHttpNetworkHeaderPrivate::operator==(other) && (operation == other.operation) + && (ssl == other.ssl) && (uploadByteDevice == other.uploadByteDevice); } @@ -199,6 +201,15 @@ void QHttpNetworkRequest::setUrl(const QUrl &url) d->url = url; } +bool QHttpNetworkRequest::isSsl() const +{ + return d->ssl; +} +void QHttpNetworkRequest::setSsl(bool s) +{ + d->ssl = s; +} + qint64 QHttpNetworkRequest::contentLength() const { return d->contentLength(); diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h index 15cab73..123babc 100644 --- a/src/network/access/qhttpnetworkrequest_p.h +++ b/src/network/access/qhttpnetworkrequest_p.h @@ -116,6 +116,9 @@ public: bool withCredentials() const; void setWithCredentials(bool b); + bool isSsl() const; + void setSsl(bool); + void setUploadByteDevice(QNonContiguousByteDevice *bd); QNonContiguousByteDevice* uploadByteDevice() const; @@ -146,6 +149,7 @@ public: bool autoDecompress; bool pipeliningAllowed; bool withCredentials; + bool ssl; }; diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp index 60f7dc6..c3d765b 100644 --- a/src/network/access/qnetworkaccessbackend.cpp +++ b/src/network/access/qnetworkaccessbackend.cpp @@ -146,7 +146,7 @@ QNonContiguousByteDevice* QNetworkAccessBackend::createUploadByteDevice() // and the special backends need to access this. void QNetworkAccessBackend::emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal) { - if (reply->isFinished()) + if (reply->isFinished) return; reply->emitUploadProgress(bytesSent, bytesTotal); } @@ -252,6 +252,17 @@ void QNetworkAccessBackend::writeDownstreamData(QIODevice *data) reply->appendDownstreamData(data); } +// not actually appending data, it was already written to the user buffer +void QNetworkAccessBackend::writeDownstreamDataDownloadBuffer(qint64 bytesReceived, qint64 bytesTotal) +{ + reply->appendDownstreamDataDownloadBuffer(bytesReceived, bytesTotal); +} + +char* QNetworkAccessBackend::getDownloadBuffer(qint64 size) +{ + return reply->getDownloadBuffer(size); +} + QVariant QNetworkAccessBackend::header(QNetworkRequest::KnownHeaders header) const { return reply->q_func()->header(header); diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h index 4fe6de6..9f8a01f 100644 --- a/src/network/access/qnetworkaccessbackend_p.h +++ b/src/network/access/qnetworkaccessbackend_p.h @@ -177,6 +177,10 @@ protected: qint64 nextDownstreamBlockSize() const; void writeDownstreamData(QByteDataBuffer &list); + // not actually appending data, it was already written to the user buffer + void writeDownstreamDataDownloadBuffer(qint64, qint64); + char* getDownloadBuffer(qint64); + public slots: // for task 251801, needs to be a slot to be called asynchronously void writeDownstreamData(QIODevice *data); diff --git a/src/network/access/qnetworkaccessfilebackend.cpp b/src/network/access/qnetworkaccessfilebackend.cpp index 4560153..710c258 100644 --- a/src/network/access/qnetworkaccessfilebackend.cpp +++ b/src/network/access/qnetworkaccessfilebackend.cpp @@ -65,10 +65,15 @@ QNetworkAccessFileBackendFactory::create(QNetworkAccessManager::Operation op, } QUrl url = request.url(); - if (url.scheme() == QLatin1String("qrc") || !url.toLocalFile().isEmpty()) + if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0 || url.isLocalFile()) { return new QNetworkAccessFileBackend; - else if (!url.isEmpty() && url.authority().isEmpty()) { - // check if QFile could, in theory, open this URL + } else if (!url.scheme().isEmpty() && url.authority().isEmpty()) { + // check if QFile could, in theory, open this URL via the file engines + // it has to be in the format: + // prefix:path/to/file + // or prefix:/path/to/file + // + // this construct here must match the one below in open() QFileInfo fi(url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery)); if (fi.exists() || (op == QNetworkAccessManager::PutOperation && fi.dir().exists())) return new QNetworkAccessFileBackend; diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp index 1a59011..da336d0 100644 --- a/src/network/access/qnetworkaccessftpbackend.cpp +++ b/src/network/access/qnetworkaccessftpbackend.cpp @@ -77,7 +77,7 @@ QNetworkAccessFtpBackendFactory::create(QNetworkAccessManager::Operation op, } QUrl url = request.url(); - if (url.scheme() == QLatin1String("ftp")) + if (url.scheme().compare(QLatin1String("ftp"), Qt::CaseInsensitive) == 0) return new QNetworkAccessFtpBackend; return 0; } diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index f617244..8b9a99f 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -542,6 +542,9 @@ void QNetworkAccessHttpBackend::postRequest() break; // can't happen } + bool encrypt = (url().scheme().toLower() == QLatin1String("https")); + httpRequest.setSsl(encrypt); + httpRequest.setUrl(url()); QList<QByteArray> headers = request().rawHeaderList(); @@ -595,7 +598,6 @@ void QNetworkAccessHttpBackend::postRequest() httpReply->ignoreSslErrors(pendingIgnoreSslErrorsList); #endif - connect(httpReply, SIGNAL(readyRead()), SLOT(replyReadyRead())); connect(httpReply, SIGNAL(finished()), SLOT(replyFinished())); connect(httpReply, SIGNAL(finishedWithError(QNetworkReply::NetworkError,QString)), SLOT(httpError(QNetworkReply::NetworkError,QString))); @@ -859,9 +861,33 @@ void QNetworkAccessHttpBackend::replyHeaderChanged() if (!isCachingEnabled()) setCachingEnabled(true); } + + // Check if a download buffer is supported from the HTTP reply + char *buf = 0; + if (httpReply->supportsUserProvidedDownloadBuffer()) { + // Check if a download buffer is supported by the user + buf = getDownloadBuffer(httpReply->contentLength()); + if (buf) { + httpReply->setUserProvidedDownloadBuffer(buf); + // If there is a download buffer we react on the progress signal + connect(httpReply, SIGNAL(dataReadProgress(int,int)), SLOT(replyDownloadProgressSlot(int,int))); + } + } + + // If there is no buffer, we react on the readyRead signal + if (!buf) { + connect(httpReply, SIGNAL(readyRead()), SLOT(replyReadyRead())); + } + metaDataChanged(); } +void QNetworkAccessHttpBackend::replyDownloadProgressSlot(int received, int total) +{ + // we can be sure here that there is a download buffer + writeDownstreamDataDownloadBuffer(received, total); +} + void QNetworkAccessHttpBackend::httpAuthenticationRequired(const QHttpNetworkRequest &, QAuthenticator *auth) { @@ -1169,6 +1195,11 @@ bool QNetworkAccessHttpBackend::canResume() const return false; } + // If we're using a download buffer then we don't support resuming/migration + // right now. Too much trouble. + if (httpReply->userProvidedDownloadBuffer()) + return false; + return true; } diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h index c4c88ae..fb12781 100644 --- a/src/network/access/qnetworkaccesshttpbackend_p.h +++ b/src/network/access/qnetworkaccesshttpbackend_p.h @@ -104,6 +104,7 @@ private slots: void replyReadyRead(); void replyFinished(); void replyHeaderChanged(); + void replyDownloadProgressSlot(int,int); void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth); void httpCacheCredentials(const QHttpNetworkRequest &request, QAuthenticator *auth); void httpError(QNetworkReply::NetworkError error, const QString &errorString); diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index b35c318..234305e 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -450,6 +450,8 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent) : QObject(*new QNetworkAccessManagerPrivate, parent) { ensureInitialized(); + + qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError"); } /*! @@ -944,21 +946,20 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera { Q_D(QNetworkAccessManager); + bool isLocalFile = req.url().isLocalFile(); + // fast path for GET on file:// URLs - // Also if the scheme is empty we consider it a file. // The QNetworkAccessFileBackend will right now only be used // for PUT or qrc:// if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation) - && (req.url().scheme() == QLatin1String("file") - || req.url().scheme().isEmpty())) { + && isLocalFile) { return new QFileNetworkReply(this, req, op); } #ifndef QT_NO_BEARERMANAGEMENT // Return a disabled network reply if network access is disabled. // Except if the scheme is empty or file://. - if (!d->networkAccessible && !(req.url().scheme() == QLatin1String("file") || - req.url().scheme().isEmpty())) { + if (!d->networkAccessible && !isLocalFile) { return new QDisabledNetworkReply(this, req, op); } @@ -992,7 +993,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera if (d->cookieJar) { QList<QNetworkCookie> cookies = d->cookieJar->cookiesForUrl(request.url()); if (!cookies.isEmpty()) - request.setHeader(QNetworkRequest::CookieHeader, qVariantFromValue(cookies)); + request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies)); } } @@ -1000,7 +1001,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera QUrl url = request.url(); QNetworkReplyImpl *reply = new QNetworkReplyImpl(this); #ifndef QT_NO_BEARERMANAGEMENT - if (req.url().scheme() != QLatin1String("file") && !req.url().scheme().isEmpty()) { + if (!isLocalFile) { connect(this, SIGNAL(networkSessionConnected()), reply, SLOT(_q_networkSessionConnected())); } diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index 261ed20..f55f67d 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -49,6 +49,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate() : readBufferMaxSize(0), operation(QNetworkAccessManager::UnknownOperation), errorCode(QNetworkReply::NoError) + , isFinished(false) { // set the default attribute values attributes.insert(QNetworkRequest::ConnectionEncryptedAttribute, false); @@ -462,7 +463,7 @@ QNetworkReply::NetworkError QNetworkReply::error() const */ bool QNetworkReply::isFinished() const { - return d_func()->isFinished(); + return d_func()->isFinished; } /*! @@ -718,6 +719,21 @@ void QNetworkReply::setError(NetworkError errorCode, const QString &errorString) } /*! + \since 4.8 + Sets the reply as \a finished. + + After having this set the replies data must not change. + + \sa isFinished() +*/ +void QNetworkReply::setFinished(bool finished) +{ + Q_D(QNetworkReply); + d->isFinished = finished; +} + + +/*! Sets the URL being processed to be \a url. Normally, the URL matches that of the request that was posted, but for a variety of reasons it can be different (for example, a file path being made diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h index acb7379..b39fd32 100644 --- a/src/network/access/qnetworkreply.h +++ b/src/network/access/qnetworkreply.h @@ -163,6 +163,7 @@ protected: void setOperation(QNetworkAccessManager::Operation operation); void setRequest(const QNetworkRequest &request); void setError(NetworkError errorCode, const QString &errorString); + void setFinished(bool); void setUrl(const QUrl &url); void setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value); void setRawHeader(const QByteArray &headerName, const QByteArray &value); diff --git a/src/network/access/qnetworkreply_p.h b/src/network/access/qnetworkreply_p.h index d7b8ab0..2e2e0bc 100644 --- a/src/network/access/qnetworkreply_p.h +++ b/src/network/access/qnetworkreply_p.h @@ -71,12 +71,11 @@ public: qint64 readBufferMaxSize; QNetworkAccessManager::Operation operation; QNetworkReply::NetworkError errorCode; + bool isFinished; static inline void setManager(QNetworkReply *reply, QNetworkAccessManager *manager) { reply->d_func()->manager = manager; } - virtual bool isFinished() const { return false; } - Q_DECLARE_PUBLIC(QNetworkReply) }; diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 5850494..3a629cf 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -49,10 +49,16 @@ #include "QtNetwork/qnetworksession.h" #include "qnetworkaccesshttpbackend_p.h" #include "qnetworkaccessmanager_p.h" +#include <QVarLengthArray> #include <QtCore/QCoreApplication> QT_BEGIN_NAMESPACE +typedef QSharedPointer<QVarLengthArray<char, 0> > QVarLengthArraySharedPointer; +QT_END_NAMESPACE +Q_DECLARE_METATYPE(QVarLengthArraySharedPointer) + +QT_BEGIN_NAMESPACE inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate() : backend(0), outgoingData(0), outgoingDataBuffer(0), @@ -62,6 +68,8 @@ inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate() bytesDownloaded(0), lastBytesDownloaded(-1), bytesUploaded(-1), preMigrationDownloaded(-1), httpStatusCode(0), state(Idle) + , downloadBuffer(0) + , downloadBufferPosition(0) { } @@ -125,6 +133,10 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead() if (!copyDevice || !q->isOpen()) return; + // FIXME Optimize to use download buffer if it is a QBuffer. + // Needs to be done where sendCacheContents() (?) of HTTP is emitting + // metaDataChanged ? + forever { qint64 bytesToRead = nextDownstreamBlockSize(); if (bytesToRead == 0) @@ -543,8 +555,6 @@ void QNetworkReplyImplPrivate::appendDownstreamDataSignalEmissions() { Q_Q(QNetworkReplyImpl); - QPointer<QNetworkReplyImpl> qq = q; - QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); if (preMigrationDownloaded != Q_INT64_C(-1)) totalSize = totalSize.toLongLong() + preMigrationDownloaded; @@ -555,13 +565,10 @@ void QNetworkReplyImplPrivate::appendDownstreamDataSignalEmissions() // else implicit sharing will trigger memcpy when the user is reading data! emit q->readyRead(); - // hopefully we haven't been deleted here - if (!qq.isNull()) { - resumeNotificationHandling(); - // do we still have room in the buffer? - if (nextDownstreamBlockSize() > 0) - backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); - } + resumeNotificationHandling(); + // do we still have room in the buffer? + if (nextDownstreamBlockSize() > 0) + backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); } // this is used when it was fetched from the cache, right? @@ -596,6 +603,55 @@ void QNetworkReplyImplPrivate::appendDownstreamData(const QByteArray &data) qFatal("QNetworkReplyImplPrivate::appendDownstreamData not implemented"); } +char* QNetworkReplyImplPrivate::getDownloadBuffer(qint64 size) +{ + Q_Q(QNetworkReplyImpl); + + // Check attribute() if allocating a buffer of that size can be allowed + if (!downloadBuffer) { + QVariant bufferAllocationPolicy = request.attribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute); + if (bufferAllocationPolicy.isValid() && bufferAllocationPolicy.toLongLong() >= size) { + downloadBufferArray = QSharedPointer<QVarLengthArray<char, 0> >(new QVarLengthArray<char, 0>()); + downloadBufferArray->reserve(size); + + downloadBuffer = downloadBufferArray->data(); + + q->setAttribute(QNetworkRequest::DownloadBufferAttribute, qVariantFromValue<QSharedPointer<QVarLengthArray<char, 0> > > (downloadBufferArray)); + } + } + + return downloadBuffer; +} + +void QNetworkReplyImplPrivate::appendDownstreamDataDownloadBuffer(qint64 bytesReceived, qint64 bytesTotal) +{ + Q_Q(QNetworkReplyImpl); + if (!q->isOpen()) + return; + + if (cacheEnabled && !cacheSaveDevice) + initCacheSaveDevice(); + + if (cacheSaveDevice && bytesReceived == bytesTotal) { +// if (lastBytesDownloaded == -1) +// lastBytesDownloaded = 0; +// cacheSaveDevice->write(downloadBuffer + lastBytesDownloaded, bytesReceived - lastBytesDownloaded); + + // Write everything in one go if we use a download buffer. might be more performant. + cacheSaveDevice->write(downloadBuffer, bytesTotal); + } + + bytesDownloaded = bytesReceived; + lastBytesDownloaded = bytesReceived; + + // Update the array so our user (e.g. QtWebKit) knows the real size + if (bytesReceived > 0) + downloadBufferArray->resize(bytesReceived); + + emit q->downloadProgress(bytesDownloaded, bytesTotal); + emit q->readyRead(); +} + void QNetworkReplyImplPrivate::finished() { Q_Q(QNetworkReplyImpl); @@ -634,6 +690,8 @@ void QNetworkReplyImplPrivate::finished() resumeNotificationHandling(); state = Finished; + q->setFinished(true); + pendingNotifications.clear(); pauseNotificationHandling(); @@ -704,11 +762,6 @@ void QNetworkReplyImplPrivate::sslErrors(const QList<QSslError> &errors) #endif } -bool QNetworkReplyImplPrivate::isFinished() const -{ - return (state == Finished || state == Aborted); -} - QNetworkReplyImpl::QNetworkReplyImpl(QObject *parent) : QNetworkReply(*new QNetworkReplyImplPrivate, parent) { @@ -743,7 +796,7 @@ void QNetworkReplyImpl::abort() QNetworkReply::close(); if (d->state != QNetworkReplyImplPrivate::Finished) { - // emit signals + // call finished which will emit signals d->error(OperationCanceledError, tr("Operation canceled")); d->finished(); } @@ -771,7 +824,7 @@ void QNetworkReplyImpl::close() QNetworkReply::close(); - // emit signals + // call finished which will emit signals d->error(OperationCanceledError, tr("Operation canceled")); d->finished(); } @@ -790,6 +843,13 @@ bool QNetworkReplyImpl::canReadLine () const */ qint64 QNetworkReplyImpl::bytesAvailable() const { + // Special case for the "zero copy" download buffer + Q_D(const QNetworkReplyImpl); + if (d->downloadBuffer) { + qint64 maxAvail = d->downloadBufferArray->size() - d->downloadBufferPosition; + return QNetworkReply::bytesAvailable() + maxAvail; + } + return QNetworkReply::bytesAvailable() + d_func()->readBuffer.byteAmount(); } @@ -844,8 +904,22 @@ void QNetworkReplyImpl::ignoreSslErrorsImplementation(const QList<QSslError> &er qint64 QNetworkReplyImpl::readData(char *data, qint64 maxlen) { Q_D(QNetworkReplyImpl); + + // Special case code if we have the "zero copy" download buffer + if (d->downloadBuffer) { + qint64 maxAvail = qMin<qint64>(d->downloadBufferArray->size() - d->downloadBufferPosition, maxlen); + if (maxAvail == 0) + return d->state == QNetworkReplyImplPrivate::Finished ? -1 : 0; + // FIXME what about "Aborted" state? + qMemCopy(data, d->downloadBuffer + d->downloadBufferPosition, maxAvail); + d->downloadBufferPosition += maxAvail; + return maxAvail; + } + + if (d->readBuffer.isEmpty()) return d->state == QNetworkReplyImplPrivate::Finished ? -1 : 0; + // FIXME what about "Aborted" state? d->backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); if (maxlen == 1) { diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index 38084bd..2cb3082 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -62,6 +62,7 @@ #include "QtCore/qbuffer.h" #include "private/qringbuffer_p.h" #include "private/qbytedata_p.h" +#include <QVarLengthArray> QT_BEGIN_NAMESPACE @@ -163,14 +164,15 @@ public: void appendDownstreamData(QIODevice *data); void appendDownstreamData(const QByteArray &data); + char* getDownloadBuffer(qint64 size); + void appendDownstreamDataDownloadBuffer(qint64, qint64); + void finished(); void error(QNetworkReply::NetworkError code, const QString &errorString); void metaDataChanged(); void redirectionRequested(const QUrl &target); void sslErrors(const QList<QSslError> &errors); - bool isFinished() const; - QNetworkAccessBackend *backend; QIODevice *outgoingData; QRingBuffer *outgoingDataBuffer; @@ -191,6 +193,7 @@ public: QList<QNetworkProxy> proxyList; #endif + // Used for normal downloading. For "zero copy" the downloadBuffer is used QByteDataBuffer readBuffer; qint64 bytesDownloaded; qint64 lastBytesDownloaded; @@ -202,6 +205,11 @@ public: State state; + // only used when the "zero copy" style is used. Else readBuffer is used. + QSharedPointer< QVarLengthArray<char, 0> > downloadBufferArray; + char* downloadBuffer; + qint64 downloadBufferPosition; + Q_DECLARE_PUBLIC(QNetworkReplyImpl) }; diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index d3084cf..09ec4c2 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -766,7 +766,7 @@ static QVariant parseCookieHeader(const QByteArray &raw) result += parsed; } - return qVariantFromValue(result); + return QVariant::fromValue(result); } static QVariant parseHeaderValue(QNetworkRequest::KnownHeaders header, const QByteArray &value) @@ -799,7 +799,7 @@ static QVariant parseHeaderValue(QNetworkRequest::KnownHeaders header, const QBy return parseCookieHeader(value); case QNetworkRequest::SetCookieHeader: - return qVariantFromValue(QNetworkCookie::parseCookies(value)); + return QVariant::fromValue(QNetworkCookie::parseCookies(value)); default: Q_ASSERT(0); diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 348b0d2..7908182 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -56,9 +56,7 @@ QT_BEGIN_NAMESPACE -#ifndef QT_NO_THREAD Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager) -#endif //#define QHOSTINFO_DEBUG @@ -87,10 +85,8 @@ Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager) \snippet doc/src/snippets/code/src_network_kernel_qhostinfo.cpp 0 - The slot is invoked when the results are ready. (If you use - Qt for Embedded Linux and disabled multithreading support by defining - \c QT_NO_THREAD, lookupHost() will block until the lookup has - finished.) The results are stored in a QHostInfo object. Call + The slot is invoked when the results are ready. The results are + stored in a QHostInfo object. Call addresses() to get the list of IP addresses for the host, and hostName() to get the host name that was looked up. @@ -176,14 +172,6 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, return id; } -#ifdef QT_NO_THREAD - QHostInfo hostInfo = QHostInfoAgent::fromName(name); - hostInfo.setLookupId(id); - QScopedPointer<QHostInfoResult> result(new QHostInfoResult); - QObject::connect(result.data(), SIGNAL(resultsReady(QHostInfo)), - receiver, member, Qt::QueuedConnection); - result.data()->emitResultsReady(hostInfo); -#else QHostInfoLookupManager *manager = theHostInfoLookupManager(); if (manager) { // the application is still alive @@ -204,8 +192,6 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, QObject::connect(&runnable->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); manager->scheduleLookup(runnable); } -#endif - return id; } @@ -216,12 +202,7 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, */ void QHostInfo::abortHostLookup(int id) { -#ifndef QT_NO_THREAD theHostInfoLookupManager()->abortLookup(id); -#else - // we cannot abort if it was non threaded.. the result signal has already been posted - Q_UNUSED(id); -#endif } /*! @@ -422,7 +403,6 @@ void QHostInfo::setErrorString(const QString &str) \sa hostName() */ -#ifndef QT_NO_THREAD QHostInfoRunnable::QHostInfoRunnable(QString hn, int i) : toBeLookedUp(hn), id(i) { setAutoDelete(true); @@ -747,6 +727,4 @@ void QHostInfoCache::clear() cache.clear(); } -#endif // QT_NO_THREAD - QT_END_NAMESPACE diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index 85d14c2..134335f 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -60,8 +60,6 @@ #include "QtCore/qwaitcondition.h" #include "QtCore/qobject.h" #include "QtCore/qpointer.h" - -#ifndef QT_NO_THREAD #include "QtCore/qthread.h" #include "QtCore/qthreadpool.h" #include "QtCore/qmutex.h" @@ -70,7 +68,7 @@ #include "QtCore/qqueue.h" #include <QTime> #include <QCache> -#endif + QT_BEGIN_NAMESPACE @@ -112,7 +110,6 @@ public: int lookupId; }; -#ifndef QT_NO_THREAD // These functions are outside of the QHostInfo class and strictly internal. // Do NOT use them outside of QAbstractSocket. QHostInfo Q_NETWORK_EXPORT qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *member, bool *valid, int *id); @@ -192,8 +189,6 @@ private slots: void waitForThreadPoolDone() { threadPool.waitForDone(); } }; -#endif - QT_END_NAMESPACE #endif // QHOSTINFO_P_H diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index 9e3da61..5ca15a3 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -132,9 +132,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) // Load res_init on demand. static volatile bool triedResolve = false; if (!triedResolve) { -#ifndef QT_NO_THREAD QMutexLocker locker(QMutexPool::globalInstanceGet(&local_res_init)); -#endif if (!triedResolve) { resolveLibrary(); triedResolve = true; diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp index 8241c84..8e28fb3 100644 --- a/src/network/kernel/qhostinfo_win.cpp +++ b/src/network/kernel/qhostinfo_win.cpp @@ -39,11 +39,6 @@ ** ****************************************************************************/ -#if defined Q_CC_MSVC && _MSC_VER <=1300 -//VC.net 2002 support for templates doesn't match some PSDK requirements -#define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0])) -#endif - #include <winsock2.h> #include "qhostinfo_p.h" @@ -115,9 +110,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) // Load res_init on demand. static volatile bool triedResolve = false; if (!triedResolve) { -#ifndef QT_NO_THREAD QMutexLocker locker(QMutexPool::globalInstanceGet(&local_getaddrinfo)); -#endif if (!triedResolve) { resolveLibrary(); triedResolve = true; diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 505db71..66cdffb 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -356,6 +356,10 @@ to enable. \value KeepAliveOption Set this to 1 to enable the SO_KEEPALIVE socket option + \value MulticastTtlOption Set this to an integer value to set IP_MULTICAST_TTL (TTL for multicast datagrams) socket option. + + \value MulticastLoopbackOption Set this to 1 to enable the IP_MULTICAST_LOOP (multicast loopback) socket option. + \sa QAbstractSocket::setSocketOption(), QAbstractSocket::socketOption() */ @@ -466,9 +470,6 @@ QAbstractSocketPrivate::QAbstractSocketPrivate() peerPort(0), socketEngine(0), cachedSocketDescriptor(-1), -#ifdef Q_OS_LINUX - addToBytesAvailable(0), -#endif readBufferMaxSize(0), readBuffer(QABSTRACTSOCKET_BUFFERSIZE), writeBuffer(QABSTRACTSOCKET_BUFFERSIZE), @@ -630,8 +631,9 @@ bool QAbstractSocketPrivate::canReadNotification() // only emit readyRead() when not recursing, and only if there is data available bool hasData = newBytes > 0 #ifndef QT_NO_UDPSOCKET - || (!isBuffered && socketEngine && socketEngine->hasPendingDatagrams()) + || (!isBuffered && socketType != QAbstractSocket::TcpSocket && socketEngine && socketEngine->hasPendingDatagrams()) #endif + || (!isBuffered && socketType == QAbstractSocket::TcpSocket && socketEngine) ; if (!emittedReadyRead && hasData) { @@ -1132,10 +1134,6 @@ bool QAbstractSocketPrivate::readFromSocket() Q_Q(QAbstractSocket); // Find how many bytes we can read from the socket layer. qint64 bytesToRead = socketEngine->bytesAvailable(); -#ifdef Q_OS_LINUX - if (bytesToRead > 0) // ### See setSocketDescriptor() - bytesToRead += addToBytesAvailable; -#endif if (bytesToRead == 0) { // Under heavy load, certain conditions can trigger read notifications // for socket notifiers on which there is no activity. If we continue @@ -1340,10 +1338,6 @@ void QAbstractSocket::connectToHostImplementation(const QString &hostName, quint d->localAddress.clear(); d->peerAddress.clear(); d->peerName = hostName; -#ifdef Q_OS_LINUX - // ### See setSocketDescriptor(). - d->addToBytesAvailable = 0; -#endif if (d->hostLookupId != -1) { QHostInfo::abortHostLookup(d->hostLookupId); d->hostLookupId = -1; @@ -1361,8 +1355,11 @@ void QAbstractSocket::connectToHostImplementation(const QString &hostName, quint } #endif - if (!d_func()->isBuffered) - openMode |= QAbstractSocket::Unbuffered; + if (openMode & QIODevice::Unbuffered) + d->isBuffered = false; // Unbuffered QTcpSocket + else if (!d_func()->isBuffered) + openMode |= QAbstractSocket::Unbuffered; // QUdpSocket + QIODevice::open(openMode); d->state = HostLookupState; emit stateChanged(d->state); @@ -1442,10 +1439,12 @@ qint64 QAbstractSocket::bytesAvailable() const { Q_D(const QAbstractSocket); qint64 available = QIODevice::bytesAvailable(); - if (d->isBuffered) - available += (qint64) d->readBuffer.size(); - else if (d->socketEngine && d->socketEngine->isValid()) + + available += (qint64) d->readBuffer.size(); + + if (!d->isBuffered && d->socketEngine && d->socketEngine->isValid()) available += d->socketEngine->bytesAvailable(); + #if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocket::bytesAvailable() == %llu", available); #endif @@ -1603,17 +1602,6 @@ bool QAbstractSocket::setSocketDescriptor(int socketDescriptor, SocketState sock d->peerAddress = d->socketEngine->peerAddress(); d->cachedSocketDescriptor = socketDescriptor; -#ifdef Q_OS_LINUX - // ### This is a workaround for certain broken Linux kernels, when using - // QTcpSocket with a Unix domain socket. It was introduced around 2.6.9, - // and fixed at some point after that. - // http://archive.linux-usenet.com/index-t-73300.html - // We can provide a better workaround for this: readFromSocket() can loop - // while reading, but this must happen without triggering an implicit - // close because of reading after the socket has closed. - d->addToBytesAvailable = 4096; -#endif - return true; } @@ -1643,6 +1631,14 @@ void QAbstractSocket::setSocketOption(QAbstractSocket::SocketOption option, cons case KeepAliveOption: d_func()->socketEngine->setOption(QAbstractSocketEngine::KeepAliveOption, value.toInt()); break; + + case MulticastTtlOption: + d_func()->socketEngine->setOption(QAbstractSocketEngine::MulticastTtlOption, value.toInt()); + break; + + case MulticastLoopbackOption: + d_func()->socketEngine->setOption(QAbstractSocketEngine::MulticastLoopbackOption, value.toInt()); + break; } } @@ -1672,6 +1668,13 @@ QVariant QAbstractSocket::socketOption(QAbstractSocket::SocketOption option) case KeepAliveOption: ret = d_func()->socketEngine->option(QAbstractSocketEngine::KeepAliveOption); break; + + case MulticastTtlOption: + ret = d_func()->socketEngine->option(QAbstractSocketEngine::MulticastTtlOption); + break; + case MulticastLoopbackOption: + ret = d_func()->socketEngine->option(QAbstractSocketEngine::MulticastLoopbackOption); + break; } if (ret == -1) return QVariant(); @@ -2089,42 +2092,50 @@ bool QAbstractSocket::flush() qint64 QAbstractSocket::readData(char *data, qint64 maxSize) { Q_D(QAbstractSocket); - if (d->socketEngine && !d->socketEngine->isReadNotificationEnabled() && d->socketEngine->isValid()) - d->socketEngine->setReadNotificationEnabled(true); - if (!d->isBuffered) { - if (!d->socketEngine) - return -1; // no socket engine is probably EOF - qint64 readBytes = d->socketEngine->read(data, maxSize); - if (readBytes < 0) { - d->socketError = d->socketEngine->error(); - setErrorString(d->socketEngine->errorString()); - } - if (!d->socketEngine->isReadNotificationEnabled()) - d->socketEngine->setReadNotificationEnabled(true); -#if defined (QABSTRACTSOCKET_DEBUG) - qDebug("QAbstractSocket::readData(%p \"%s\", %lli) == %lld", - data, qt_prettyDebug(data, 32, readBytes).data(), maxSize, - readBytes); -#endif - return readBytes; - } - - if (d->readBuffer.isEmpty()) + // This is for a buffered QTcpSocket + if (d->isBuffered && d->readBuffer.isEmpty()) // if we're still connected, return 0 indicating there may be more data in the future // if we're not connected, return -1 indicating EOF return d->state == QAbstractSocket::ConnectedState ? qint64(0) : qint64(-1); - // If readFromSocket() read data, copy it to its destination. - if (maxSize == 1) { + // short cut for a char read if we have something in the buffer + if (maxSize == 1 && !d->readBuffer.isEmpty()) { *data = d->readBuffer.getChar(); #if defined (QABSTRACTSOCKET_DEBUG) - qDebug("QAbstractSocket::readData(%p '%c (0x%.2x)', 1) == 1", + qDebug("QAbstractSocket::readData(%p '%c (0x%.2x)', 1) == 1 [char buffer]", data, isprint(int(uchar(*data))) ? *data : '?', *data); #endif + if (d->readBuffer.isEmpty() && d->socketEngine) + d->socketEngine->setReadNotificationEnabled(true); return 1; } + // Special case for an Unbuffered QTcpSocket + // Re-filling the buffer. + if (d->socketType == TcpSocket + && !d->isBuffered + && d->readBuffer.size() < maxSize + && d->readBufferMaxSize > 0 + && maxSize < d->readBufferMaxSize + && d->socketEngine) { + // Our buffer is empty and a read() was requested for a byte amount that is smaller + // than the readBufferMaxSize. This means that we should fill our buffer since we want + // such small reads come from the buffer and not always go to the costly socket engine read() + qint64 bytesToRead = d->socketEngine->bytesAvailable(); + if (bytesToRead > 0) { + char *ptr = d->readBuffer.reserve(bytesToRead); + qint64 readBytes = d->socketEngine->read(ptr, bytesToRead); + if (readBytes == -2) { + // No bytes currently available for reading. + d->readBuffer.chop(bytesToRead); + } else { + d->readBuffer.chop(int(bytesToRead - (readBytes < 0 ? qint64(0) : readBytes))); + } + } + } + + // First try to satisfy the read from the buffer qint64 bytesToRead = qMin(qint64(d->readBuffer.size()), maxSize); qint64 readSoFar = 0; while (readSoFar < bytesToRead) { @@ -2136,8 +2147,50 @@ qint64 QAbstractSocket::readData(char *data, qint64 maxSize) d->readBuffer.free(bytesToReadFromThisBlock); } + if (d->socketEngine && !d->socketEngine->isReadNotificationEnabled() && d->socketEngine->isValid()) + d->socketEngine->setReadNotificationEnabled(true); + + if (readSoFar > 0) { + // we read some data from buffer. + // Just return, readyRead will be emitted again #if defined (QABSTRACTSOCKET_DEBUG) - qDebug("QAbstractSocket::readData(%p \"%s\", %lli) == %lld", + qDebug("QAbstractSocket::readData(%p '%c (0x%.2x)', %lli) == %lli [buffer]", + data, isprint(int(uchar(*data))) ? *data : '?', *data, maxSize, readSoFar); +#endif + + if (d->readBuffer.isEmpty() && d->socketEngine) + d->socketEngine->setReadNotificationEnabled(true); + return readSoFar; + } + + // This code path is for Unbuffered QTcpSocket or for connected UDP + + if (!d->isBuffered) { + if (!d->socketEngine) + return -1; // no socket engine is probably EOF + qint64 readBytes = d->socketEngine->read(data, maxSize); + if (readBytes == -2) { + // -2 from the engine means no bytes available (EAGAIN) so read more later + return 0; + } else if (readBytes < 0) { + d->socketError = d->socketEngine->error(); + setErrorString(d->socketEngine->errorString()); + } else if (!d->socketEngine->isReadNotificationEnabled()) { + // Only do this when there was no error + d->socketEngine->setReadNotificationEnabled(true); + } + +#if defined (QABSTRACTSOCKET_DEBUG) + qDebug("QAbstractSocket::readData(%p \"%s\", %lli) == %lld [engine]", + data, qt_prettyDebug(data, 32, readBytes).data(), maxSize, + readBytes); +#endif + return readBytes; + } + + +#if defined (QABSTRACTSOCKET_DEBUG) + qDebug("QAbstractSocket::readData(%p \"%s\", %lli) == %lld [unreachable]", data, qt_prettyDebug(data, qMin<qint64>(32, readSoFar), readSoFar).data(), maxSize, readSoFar); #endif @@ -2162,7 +2215,23 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size) return -1; } - if (!d->isBuffered) { + if (!d->isBuffered && d->socketType == TcpSocket && d->writeBuffer.isEmpty()) { + // This code is for the new Unbuffered QTcpSocket use case + qint64 written = d->socketEngine->write(data, size); + if (written < 0) { + d->socketError = d->socketEngine->error(); + setErrorString(d->socketEngine->errorString()); + return written; + } else if (written < size) { + // Buffer what was not written yet + char *ptr = d->writeBuffer.reserve(size - written); + memcpy(ptr, data + written, size - written); + if (d->socketEngine) + d->socketEngine->setWriteNotificationEnabled(true); + } + return size; // size=actually written + what has been buffered + } else if (!d->isBuffered && d->socketType != TcpSocket) { + // This is for a QUdpSocket that was connect()ed qint64 written = d->socketEngine->write(data, size); if (written < 0) { d->socketError = d->socketEngine->error(); @@ -2181,6 +2250,12 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size) return written; } + // This is the code path for normal buffered QTcpSocket or + // unbuffered QTcpSocket when there was already something in the + // write buffer and therefore we could not do a direct engine write. + // We just write to our write buffer and enable the write notifier + // The write notifier then flush()es the buffer. + char *ptr = d->writeBuffer.reserve(size); if (size == 1) *ptr = *data; diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h index 9e487d2..f610db3 100644 --- a/src/network/socket/qabstractsocket.h +++ b/src/network/socket/qabstractsocket.h @@ -118,7 +118,9 @@ public: }; enum SocketOption { LowDelayOption, // TCP_NODELAY - KeepAliveOption // SO_KEEPALIVE + KeepAliveOption, // SO_KEEPALIVE + MulticastTtlOption, // IP_MULTICAST_TTL + MulticastLoopbackOption // IP_MULTICAST_LOOPBACK }; QAbstractSocket(SocketType socketType, QObject *parent); diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h index b51c301..6c333d3 100644 --- a/src/network/socket/qabstractsocket_p.h +++ b/src/network/socket/qabstractsocket_p.h @@ -138,9 +138,6 @@ public: void setupSocketNotifiers(); bool readFromSocket(); -#ifdef Q_OS_LINUX - qint64 addToBytesAvailable; -#endif qint64 readBufferMaxSize; QRingBuffer readBuffer; QRingBuffer writeBuffer; diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h index 3669852..ec5fbd3 100644 --- a/src/network/socket/qabstractsocketengine_p.h +++ b/src/network/socket/qabstractsocketengine_p.h @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE class QAuthenticator; class QAbstractSocketEnginePrivate; +class QNetworkInterface; class QNetworkProxy; class QAbstractSocketEngineReceiver { @@ -94,7 +95,9 @@ public: BindExclusively, ReceiveOutOfBandData, LowDelayOption, - KeepAliveOption + KeepAliveOption, + MulticastTtlOption, + MulticastLoopbackOption }; virtual bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) = 0; @@ -118,6 +121,13 @@ public: virtual qint64 write(const char *data, qint64 len) = 0; #ifndef QT_NO_UDPSOCKET + virtual bool joinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) = 0; + virtual bool leaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) = 0; + virtual QNetworkInterface multicastInterface() const = 0; + virtual bool setMulticastInterface(const QNetworkInterface &iface) = 0; + virtual qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, quint16 *port = 0) = 0; virtual qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index dfda257..cb0e296 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -45,6 +45,7 @@ #include "qurl.h" #include "qhttp.h" #include "qelapsedtimer.h" +#include "qnetworkinterface.h" #if !defined(QT_NO_NETWORKPROXY) && !defined(QT_NO_HTTP) #include <qdebug.h> @@ -239,6 +240,34 @@ qint64 QHttpSocketEngine::write(const char *data, qint64 len) } #ifndef QT_NO_UDPSOCKET +bool QHttpSocketEngine::joinMulticastGroup(const QHostAddress &, + const QNetworkInterface &) +{ + setError(QAbstractSocket::UnsupportedSocketOperationError, + QLatin1String("Operation on socket is not supported")); + return false; +} + +bool QHttpSocketEngine::leaveMulticastGroup(const QHostAddress &, + const QNetworkInterface &) +{ + setError(QAbstractSocket::UnsupportedSocketOperationError, + QLatin1String("Operation on socket is not supported")); + return false; +} + +QNetworkInterface QHttpSocketEngine::multicastInterface() const +{ + return QNetworkInterface(); +} + +bool QHttpSocketEngine::setMulticastInterface(const QNetworkInterface &) +{ + setError(QAbstractSocket::UnsupportedSocketOperationError, + QLatin1String("Operation on socket is not supported")); + return false; +} + qint64 QHttpSocketEngine::readDatagram(char *, qint64, QHostAddress *, quint16 *) { diff --git a/src/network/socket/qhttpsocketengine_p.h b/src/network/socket/qhttpsocketengine_p.h index 5051def..b68b7117 100644 --- a/src/network/socket/qhttpsocketengine_p.h +++ b/src/network/socket/qhttpsocketengine_p.h @@ -102,6 +102,13 @@ public: qint64 write(const char *data, qint64 len); #ifndef QT_NO_UDPSOCKET + bool joinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &interface); + bool leaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &interface); + QNetworkInterface multicastInterface() const; + bool setMulticastInterface(const QNetworkInterface &iface); + qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, quint16 *port = 0); qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index a169ca0..df73b9c 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -98,6 +98,7 @@ #include <qabstracteventdispatcher.h> #include <qsocketnotifier.h> +#include <qnetworkinterface.h> #include "qnativesocketengine_p.h" #include <private/qthread_p.h> @@ -647,6 +648,51 @@ int QNativeSocketEngine::accept() } /*! + \since 4.8 +*/ +bool QNativeSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::joinMulticastGroup(), false); + Q_CHECK_STATE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::BoundState, false); + Q_CHECK_TYPE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::UdpSocket, false); + return d->nativeJoinMulticastGroup(groupAddress, iface); +} + +/*! + \since 4.8 +*/ +bool QNativeSocketEngine::leaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::leaveMulticastGroup(), false); + Q_CHECK_STATE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::BoundState, false); + Q_CHECK_TYPE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::UdpSocket, false); + return d->nativeLeaveMulticastGroup(groupAddress, iface); +} + +/*! \since 4.8 */ +QNetworkInterface QNativeSocketEngine::multicastInterface() const +{ + Q_D(const QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::multicastInterface(), QNetworkInterface()); + Q_CHECK_TYPE(QNativeSocketEngine::multicastInterface(), QAbstractSocket::UdpSocket, QNetworkInterface()); + return d->nativeMulticastInterface(); +} + + +/*! \since 4.8 */ +bool QNativeSocketEngine::setMulticastInterface(const QNetworkInterface &iface) +{ + Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setMulticastInterface(), false); + Q_CHECK_TYPE(QNativeSocketEngine::setMulticastInterface(), QAbstractSocket::UdpSocket, false); + return d->nativeSetMulticastInterface(iface); +} + +/*! Returns the number of bytes that are currently available for reading. On error, -1 is returned. diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index eca16f6..9baacf0 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -101,6 +101,7 @@ union qt_sockaddr { }; class QNativeSocketEnginePrivate; +class QNetworkInterface; class Q_AUTOTEST_EXPORT QNativeSocketEngine : public QAbstractSocketEngine { @@ -123,6 +124,13 @@ public: int accept(); void close(); + bool joinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + bool leaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + QNetworkInterface multicastInterface() const; + bool setMulticastInterface(const QNetworkInterface &iface); + qint64 bytesAvailable() const; qint64 read(char *data, qint64 maxlen); @@ -237,6 +245,12 @@ public: bool nativeBind(const QHostAddress &address, quint16 port); bool nativeListen(int backlog); int nativeAccept(); + bool nativeJoinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + bool nativeLeaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + QNetworkInterface nativeMulticastInterface() const; + bool nativeSetMulticastInterface(const QNetworkInterface &iface); qint64 nativeBytesAvailable() const; bool nativeHasPendingDatagrams() const; diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index f6bfbac..aa55009 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -46,6 +46,7 @@ #include "qhostaddress.h" #include "qelapsedtimer.h" #include "qvarlengtharray.h" +#include "qnetworkinterface.h" #include <time.h> #include <errno.h> #include <fcntl.h> @@ -247,6 +248,30 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co case QNativeSocketEngine::KeepAliveOption: n = SO_KEEPALIVE; break; + case QNativeSocketEngine::MulticastTtlOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_HOPS; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_TTL; + } + break; + case QNativeSocketEngine::MulticastLoopbackOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_LOOP; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_LOOP; + } + break; } int v = -1; @@ -330,6 +355,30 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt case QNativeSocketEngine::KeepAliveOption: n = SO_KEEPALIVE; break; + case QNativeSocketEngine::MulticastTtlOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_HOPS; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_TTL; + } + break; + case QNativeSocketEngine::MulticastLoopbackOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_LOOP; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_LOOP; + } + break; } return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0; @@ -579,6 +628,171 @@ int QNativeSocketEnginePrivate::nativeAccept() return acceptedDescriptor; } + +static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d, + int how6, + int how4, + const QHostAddress &groupAddress, + const QNetworkInterface &interface) +{ + int level = 0; + int sockOpt = 0; + void *sockArg; + int sockArgSize; + + ip_mreq mreq4; +#ifndef QT_NO_IPV6 + ipv6_mreq mreq6; + + if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + sockOpt = how6; + sockArg = &mreq6; + sockArgSize = sizeof(mreq6); + memset(&mreq6, 0, sizeof(mreq6)); + Q_IPV6ADDR ip6 = groupAddress.toIPv6Address(); + memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6)); + mreq6.ipv6mr_interface = interface.index(); + } else +#endif + if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) { + level = IPPROTO_IP; + sockOpt = how4; + sockArg = &mreq4; + sockArgSize = sizeof(mreq4); + memset(&mreq4, 0, sizeof(mreq4)); + mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address()); + + if (interface.isValid()) { + QList<QNetworkAddressEntry> addressEntries = interface.addressEntries(); + if (!addressEntries.isEmpty()) { + QHostAddress firstIP = addressEntries.first().ip(); + mreq4.imr_interface.s_addr = htonl(firstIP.toIPv4Address()); + } else { + d->setError(QAbstractSocket::NetworkError, + QNativeSocketEnginePrivate::NetworkUnreachableErrorString); + return false; + } + } else { + mreq4.imr_interface.s_addr = INADDR_ANY; + } + } else { + // unreachable + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + QNativeSocketEnginePrivate::ProtocolUnsupportedErrorString); + return false; + } + + int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize); + if (res == -1) { + switch (errno) { + case ENOPROTOOPT: + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + QNativeSocketEnginePrivate::OperationUnsupportedErrorString); + break; + case EADDRNOTAVAIL: + d->setError(QAbstractSocket::SocketAddressNotAvailableError, + QNativeSocketEnginePrivate::AddressNotAvailableErrorString); + break; + default: + d->setError(QAbstractSocket::UnknownSocketError, + QNativeSocketEnginePrivate::UnknownSocketErrorString); + break; + } + return false; + } + return true; +} + +bool QNativeSocketEnginePrivate::nativeJoinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &interface) +{ + return multicastMembershipHelper(this, +#ifndef QT_NO_IPV6 + IPV6_JOIN_GROUP, +#else + 0, +#endif + IP_ADD_MEMBERSHIP, + groupAddress, + interface); +} + +bool QNativeSocketEnginePrivate::nativeLeaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &interface) +{ + return multicastMembershipHelper(this, +#ifndef QT_NO_IPV6 + IPV6_LEAVE_GROUP, +#else + 0, +#endif + IP_DROP_MEMBERSHIP, + groupAddress, + interface); +} + +QNetworkInterface QNativeSocketEnginePrivate::nativeMulticastInterface() const +{ +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + uint v; + QT_SOCKOPTLEN_T sizeofv = sizeof(v); + if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, &sizeofv) == -1) + return QNetworkInterface(); + return QNetworkInterface::interfaceFromIndex(v); + } +#endif + + struct in_addr v = { 0 }; + QT_SOCKOPTLEN_T sizeofv = sizeof(v); + if (::getsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, &sizeofv) == -1) + return QNetworkInterface(); + if (v.s_addr != 0 && sizeofv >= sizeof(v)) { + QHostAddress ipv4(ntohl(v.s_addr)); + QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces(); + for (int i = 0; i < ifaces.count(); ++i) { + const QNetworkInterface &iface = ifaces.at(i); + QList<QNetworkAddressEntry> entries = iface.addressEntries(); + for (int j = 0; j < entries.count(); ++j) { + const QNetworkAddressEntry &entry = entries.at(j); + if (entry.ip() == ipv4) + return iface; + } + } + } + return QNetworkInterface(); +} + +bool QNativeSocketEnginePrivate::nativeSetMulticastInterface(const QNetworkInterface &iface) +{ +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + uint v = iface.index(); + return (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, sizeof(v)) != -1); + } +#endif + + struct in_addr v; + if (iface.isValid()) { + QList<QNetworkAddressEntry> entries = iface.addressEntries(); + for (int i = 0; i < entries.count(); ++i) { + const QNetworkAddressEntry &entry = entries.at(i); + const QHostAddress &ip = entry.ip(); + if (ip.protocol() == QAbstractSocket::IPv4Protocol) { + v.s_addr = htonl(ip.toIPv4Address()); + int r = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, sizeof(v)); + if (r != -1) + return true; + } + } + return false; + } + + v.s_addr = INADDR_ANY; + return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, sizeof(v)) != -1); +} + qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const { int nbytes = 0; @@ -890,7 +1104,7 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) { Q_Q(QNativeSocketEngine); if (!q->isValid()) { - qWarning("QNativeSocketEngine::unbufferedRead: Invalid socket"); + qWarning("QNativeSocketEngine::nativeRead: Invalid socket"); return -1; } diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 477ef45..f952cee 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include <winsock2.h> +#include <ws2tcpip.h> #include "qnativesocketengine_p.h" @@ -47,6 +48,7 @@ #include <qsocketnotifier.h> #include <qdebug.h> #include <qdatetime.h> +#include <qnetworkinterface.h> //#define QNATIVESOCKETENGINE_DEBUG #if defined(QNATIVESOCKETENGINE_DEBUG) @@ -399,6 +401,30 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co case QNativeSocketEngine::KeepAliveOption: n = SO_KEEPALIVE; break; + case QNativeSocketEngine::MulticastTtlOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_HOPS; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_TTL; + } + break; + case QNativeSocketEngine::MulticastLoopbackOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_LOOP; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_LOOP; + } + break; } int v = -1; @@ -459,6 +485,30 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt case QNativeSocketEngine::KeepAliveOption: n = SO_KEEPALIVE; break; + case QNativeSocketEngine::MulticastTtlOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_HOPS; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_TTL; + } + break; + case QNativeSocketEngine::MulticastLoopbackOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_LOOP; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_LOOP; + } + break; } if (::setsockopt(socketDescriptor, level, n, (char*)&v, sizeof(v)) != 0) { @@ -648,8 +698,24 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin } -bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port) +bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &a, quint16 port) { + QHostAddress address = a; + switch (address.protocol()) { + case QAbstractSocket::IPv6Protocol: + if (address.toIPv6Address()[0] == 0xff) { + // binding to a multicast address + address = QHostAddress(QHostAddress::AnyIPv6); + } + break; + case QAbstractSocket::IPv4Protocol: + if ((address.toIPv4Address() & 0xffff0000) == 0xefff0000) { + // binding to a multicast address + address = QHostAddress(QHostAddress::Any); + } + break; + } + struct sockaddr_in sockAddrIPv4; qt_sockaddr_in6 sockAddrIPv6; struct sockaddr *sockAddrPtr = 0; @@ -747,6 +813,159 @@ int QNativeSocketEnginePrivate::nativeAccept() return acceptedDescriptor; } +static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d, + int how6, + int how4, + const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + int level = 0; + int sockOpt = 0; + char *sockArg; + int sockArgSize; + + struct ip_mreq mreq4; +#ifndef QT_NO_IPV6 + struct ipv6_mreq mreq6; + + if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + sockOpt = how6; + sockArg = reinterpret_cast<char *>(&mreq6); + sockArgSize = sizeof(mreq6); + memset(&mreq6, 0, sizeof(mreq6)); + Q_IPV6ADDR ip6 = groupAddress.toIPv6Address(); + memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6)); + mreq6.ipv6mr_interface = iface.index(); + } else +#endif + if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) { + level = IPPROTO_IP; + sockOpt = how4; + sockArg = reinterpret_cast<char *>(&mreq4); + sockArgSize = sizeof(mreq4); + memset(&mreq4, 0, sizeof(mreq4)); + mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address()); + + if (iface.isValid()) { + QList<QNetworkAddressEntry> addressEntries = iface.addressEntries(); + if (!addressEntries.isEmpty()) { + QHostAddress firstIP = addressEntries.first().ip(); + mreq4.imr_interface.s_addr = htonl(firstIP.toIPv4Address()); + } else { + d->setError(QAbstractSocket::NetworkError, + QNativeSocketEnginePrivate::NetworkUnreachableErrorString); + return false; + } + } else { + mreq4.imr_interface.s_addr = INADDR_ANY; + } + } else { + // unreachable + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + QNativeSocketEnginePrivate::ProtocolUnsupportedErrorString); + return false; + } + + int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize); + if (res == -1) { + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + QNativeSocketEnginePrivate::OperationUnsupportedErrorString); + return false; + } + return true; +} + +bool QNativeSocketEnginePrivate::nativeJoinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + return multicastMembershipHelper(this, +#ifndef QT_NO_IPV6 + IPV6_JOIN_GROUP, +#else + 0, +#endif + IP_ADD_MEMBERSHIP, + groupAddress, + iface); +} + +bool QNativeSocketEnginePrivate::nativeLeaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + return multicastMembershipHelper(this, +#ifndef QT_NO_IPV6 + IPV6_LEAVE_GROUP, +#else + 0, +#endif + IP_DROP_MEMBERSHIP, + groupAddress, + iface); +} + +QNetworkInterface QNativeSocketEnginePrivate::nativeMulticastInterface() const +{ +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + uint v; + QT_SOCKOPTLEN_T sizeofv = sizeof(v); + if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &v, &sizeofv) == -1) + return QNetworkInterface(); + return QNetworkInterface::interfaceFromIndex(v); + } +#endif + + struct in_addr v = { 0 }; + QT_SOCKOPTLEN_T sizeofv = sizeof(v); + if (::getsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, &sizeofv) == -1) + return QNetworkInterface(); + if (v.s_addr != 0 && sizeofv >= sizeof(v)) { + QHostAddress ipv4(ntohl(v.s_addr)); + QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces(); + for (int i = 0; i < ifaces.count(); ++i) { + const QNetworkInterface &iface = ifaces.at(i); + if (!(iface.flags() & QNetworkInterface::CanMulticast)) + continue; + QList<QNetworkAddressEntry> entries = iface.addressEntries(); + for (int j = 0; j < entries.count(); ++j) { + const QNetworkAddressEntry &entry = entries.at(j); + if (entry.ip() == ipv4) + return iface; + } + } + } + return QNetworkInterface(); +} + +bool QNativeSocketEnginePrivate::nativeSetMulticastInterface(const QNetworkInterface &iface) +{ +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + uint v = iface.isValid() ? iface.index() : 0; + return (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &v, sizeof(v)) != -1); + } +#endif + + struct in_addr v; + if (iface.isValid()) { + QList<QNetworkAddressEntry> entries = iface.addressEntries(); + for (int i = 0; i < entries.count(); ++i) { + const QNetworkAddressEntry &entry = entries.at(i); + const QHostAddress &ip = entry.ip(); + if (ip.protocol() == QAbstractSocket::IPv4Protocol) { + v.s_addr = htonl(ip.toIPv4Address()); + int r = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, sizeof(v)); + if (r != -1) + return true; + } + } + return false; + } + + v.s_addr = INADDR_ANY; + return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, sizeof(v)) != -1); +} qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const { diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp index f68edfe..17cf5b1 100644 --- a/src/network/socket/qsocks5socketengine.cpp +++ b/src/network/socket/qsocks5socketengine.cpp @@ -56,6 +56,7 @@ #include "qurl.h" #include "qauthenticator.h" #include <qendian.h> +#include <qnetworkinterface.h> QT_BEGIN_NAMESPACE @@ -1544,6 +1545,35 @@ qint64 QSocks5SocketEngine::write(const char *data, qint64 len) } #ifndef QT_NO_UDPSOCKET +bool QSocks5SocketEngine::joinMulticastGroup(const QHostAddress &, + const QNetworkInterface &) +{ + setError(QAbstractSocket::UnsupportedSocketOperationError, + QLatin1String("Operation on socket is not supported")); + return false; +} + +bool QSocks5SocketEngine::leaveMulticastGroup(const QHostAddress &, + const QNetworkInterface &) +{ + setError(QAbstractSocket::UnsupportedSocketOperationError, + QLatin1String("Operation on socket is not supported")); + return false; +} + + +QNetworkInterface QSocks5SocketEngine::multicastInterface() const +{ + return QNetworkInterface(); +} + +bool QSocks5SocketEngine::setMulticastInterface(const QNetworkInterface &) +{ + setError(QAbstractSocket::UnsupportedSocketOperationError, + QLatin1String("Operation on socket is not supported")); + return false; +} + qint64 QSocks5SocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress *addr, quint16 *port) { diff --git a/src/network/socket/qsocks5socketengine_p.h b/src/network/socket/qsocks5socketengine_p.h index 3d35b57..06fcad2 100644 --- a/src/network/socket/qsocks5socketengine_p.h +++ b/src/network/socket/qsocks5socketengine_p.h @@ -92,6 +92,13 @@ public: qint64 write(const char *data, qint64 len); #ifndef QT_NO_UDPSOCKET + bool joinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &interface); + bool leaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &interface); + QNetworkInterface multicastInterface() const; + bool setMulticastInterface(const QNetworkInterface &iface); + qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, quint16 *port = 0); qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp index d5366d3..5d8f4c0 100644 --- a/src/network/socket/qudpsocket.cpp +++ b/src/network/socket/qudpsocket.cpp @@ -77,14 +77,23 @@ \snippet doc/src/snippets/code/src_network_socket_qudpsocket.cpp 0 + QUdpSocket also supports UDP multicast. Use joinMulticastGroup() and + leaveMulticastGroup() to control group membership, and + QAbstractSocket::MulticastTtlOption and + QAbstractSocket::MulticastLoopbackOption to set the TTL and loopback socket + options. Use setMulticastInterface() to control the outgoing interface for + multicast datagrams, and multicastInterface() to query it. + With QUdpSocket, you can also establish a virtual connection to a UDP server using connectToHost() and then use read() and write() to exchange datagrams without specifying the receiver for each datagram. - The \l{network/broadcastsender}{Broadcast Sender} and - \l{network/broadcastreceiver}{Broadcast Receiver} examples - illustrate how to use QUdpSocket in applications. + The \l{network/broadcastsender}{Broadcast Sender}, + \l{network/broadcastreceiver}{Broadcast Receiver}, + \l{network/multicastsender}{Multicast Sender}, and + \l{network/multicastreceiver}{Multicast Receiver} examples illustrate how + to use QUdpSocket in applications. \section1 Symbian Platform Security Requirements @@ -145,6 +154,7 @@ */ #include "qhostaddress.h" +#include "qnetworkinterface.h" #include "qabstractsocket_p.h" #include "qudpsocket.h" @@ -329,6 +339,112 @@ bool QUdpSocket::bind(quint16 port, BindMode mode) } /*! + \since 4.8 + + Joins the the multicast group specified by \a groupAddress on the default + interface chosen by the operating system. The socket must be in BoundState, + otherwise an error occurs. + + This function returns true if successful; otherwise it returns false + and sets the socket error accordingly. + + \sa leaveMulticastGroup() +*/ +bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress) +{ + return joinMulticastGroup(groupAddress, QNetworkInterface()); +} + +/*! + \since 4.8 + \overload + + Joins the multicast group address \a groupAddress on the interface \a + iface. + + \sa leaveMulticastGroup() +*/ +bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + Q_D(QUdpSocket); + QT_CHECK_BOUND("QUdpSocket::joinMulticastGroup()", false); + return d->socketEngine->joinMulticastGroup(groupAddress, iface); +} + +/*! + \since 4.8 + + Leaves the multicast group specified by \a groupAddress on the default + interface chosen by the operating system. The socket must be in BoundState, + otherwise an error occurs. + + This function returns true if successful; otherwise it returns false and + sets the socket error accordingly. + + \sa joinMulticastGroup() +*/ +bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress) +{ + return leaveMulticastGroup(groupAddress, QNetworkInterface()); +} + +/*! + \since 4.8 + \overload + + Leaves the multicast group specified by \a groupAddress on the interface \a + iface. + + \sa joinMulticastGroup() +*/ +bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + QT_CHECK_BOUND("QUdpSocket::leaveMulticastGroup()", false); + return d_func()->socketEngine->leaveMulticastGroup(groupAddress, iface); +} + +/*! + \since 4.8 + + Returns the interface for the outgoing interface for multicast datagrams. + This corresponds to the IP_MULTICAST_IF socket option for IPv4 sockets and + the IPV6_MULTICAST_IF socket option for IPv6 sockets. If no interface has + been previously set, this function returns an invalid QNetworkInterface. + The socket must be in BoundState, otherwise an invalid QNetworkInterface is + returned. + + \sa setMulticastInterface() +*/ +QNetworkInterface QUdpSocket::multicastInterface() const +{ + Q_D(const QUdpSocket); + QT_CHECK_BOUND("QUdpSocket::multicastInterface()", QNetworkInterface()); + return d->socketEngine->multicastInterface(); +} + +/*! + \since 4.8 + + Sets the outgoing interface for multicast datagrams to the interface \a + iface. This corresponds to the IP_MULTICAST_IF socket option for IPv4 + sockets and the IPV6_MULTICAST_IF socket option for IPv6 sockets. The + socket must be in BoundState, otherwise this function does nothing. + + \sa multicastInterface(), joinMulticastGroup(), leaveMulticastGroup() +*/ +void QUdpSocket::setMulticastInterface(const QNetworkInterface &iface) +{ + Q_D(QUdpSocket); + if (!isValid()) { + qWarning("QUdpSocket::setMulticastInterface() called on a QUdpSocket when not in QUdpSocket::BoundState"); + return; + } + d->socketEngine->setMulticastInterface(iface); +} + +/*! Returns true if at least one datagram is waiting to be read; otherwise returns false. diff --git a/src/network/socket/qudpsocket.h b/src/network/socket/qudpsocket.h index f477306..b277d3f 100644 --- a/src/network/socket/qudpsocket.h +++ b/src/network/socket/qudpsocket.h @@ -53,6 +53,7 @@ QT_MODULE(Network) #ifndef QT_NO_UDPSOCKET +class QNetworkInterface; class QUdpSocketPrivate; class Q_NETWORK_EXPORT QUdpSocket : public QAbstractSocket @@ -76,6 +77,16 @@ public: bool bind(quint16 port, BindMode mode); // ### Qt 5: Merge the bind functions + bool joinMulticastGroup(const QHostAddress &groupAddress); + bool joinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + bool leaveMulticastGroup(const QHostAddress &groupAddress); + bool leaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + + QNetworkInterface multicastInterface() const; + void setMulticastInterface(const QNetworkInterface &iface); + bool hasPendingDatagrams() const; qint64 pendingDatagramSize() const; qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *host = 0, quint16 *port = 0); diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 40b3641..4b5f53e 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -46,24 +46,29 @@ #include <QMetaEnum> #endif +// #define QT_GL_SHARED_SHADER_DEBUG QT_BEGIN_NAMESPACE -static void qt_shared_shaders_free(void *data) +class QGLShaderStorage { - delete reinterpret_cast<QGLEngineSharedShaders *>(data); -} +public: + QGLEngineSharedShaders *shadersForThread(const QGLContext *context) { + QGLContextGroupResource<QGLEngineSharedShaders> *&shaders = m_storage.localData(); + if (!shaders) + shaders = new QGLContextGroupResource<QGLEngineSharedShaders>(); + return shaders->value(context); + } + +private: + QThreadStorage<QGLContextGroupResource<QGLEngineSharedShaders> *> m_storage; +}; -Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_shared_shaders, (qt_shared_shaders_free)) +Q_GLOBAL_STATIC(QGLShaderStorage, qt_shader_storage); QGLEngineSharedShaders *QGLEngineSharedShaders::shadersForContext(const QGLContext *context) { - QGLEngineSharedShaders *p = reinterpret_cast<QGLEngineSharedShaders *>(qt_shared_shaders()->value(context)); - if (!p) { - QGLShareContextScope scope(context); - qt_shared_shaders()->insert(context, p = new QGLEngineSharedShaders(context)); - } - return p; + return qt_shader_storage()->shadersForThread(context); } const char* QGLEngineSharedShaders::qShaderSnippets[] = { @@ -170,18 +175,20 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) source.clear(); source.append(qShaderSnippets[MainVertexShader]); source.append(qShaderSnippets[PositionOnlyVertexShader]); - vertexShader = new QGLShader(QGLShader::Vertex, context, this); + vertexShader = new QGLShader(QGLShader::Vertex, context, 0); + shaders.append(vertexShader); if (!vertexShader->compileSourceCode(source)) qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile"); source.clear(); source.append(qShaderSnippets[MainFragmentShader]); source.append(qShaderSnippets[ShockingPinkSrcFragmentShader]); - fragShader = new QGLShader(QGLShader::Fragment, context, this); + fragShader = new QGLShader(QGLShader::Fragment, context, 0); + shaders.append(fragShader); if (!fragShader->compileSourceCode(source)) qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile"); - simpleShaderProg = new QGLShaderProgram(context, this); + simpleShaderProg = new QGLShaderProgram(context, 0); simpleShaderProg->addShader(vertexShader); simpleShaderProg->addShader(fragShader); simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); @@ -198,18 +205,20 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) source.clear(); source.append(qShaderSnippets[MainWithTexCoordsVertexShader]); source.append(qShaderSnippets[UntransformedPositionVertexShader]); - vertexShader = new QGLShader(QGLShader::Vertex, context, this); + vertexShader = new QGLShader(QGLShader::Vertex, context, 0); + shaders.append(vertexShader); if (!vertexShader->compileSourceCode(source)) qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile"); source.clear(); source.append(qShaderSnippets[MainFragmentShader]); source.append(qShaderSnippets[ImageSrcFragmentShader]); - fragShader = new QGLShader(QGLShader::Fragment, context, this); + fragShader = new QGLShader(QGLShader::Fragment, context, 0); + shaders.append(fragShader); if (!fragShader->compileSourceCode(source)) qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile"); - blitShaderProg = new QGLShaderProgram(context, this); + blitShaderProg = new QGLShaderProgram(context, 0); blitShaderProg->addShader(vertexShader); blitShaderProg->addShader(fragShader); blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); @@ -220,13 +229,21 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) << simpleShaderProg->log(); } +#ifdef QT_GL_SHARED_SHADER_DEBUG + qDebug(" -> QGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread()); +#endif } QGLEngineSharedShaders::~QGLEngineSharedShaders() { - QList<QGLEngineShaderProg*>::iterator itr; - for (itr = cachedPrograms.begin(); itr != cachedPrograms.end(); ++itr) - delete *itr; +#ifdef QT_GL_SHARED_SHADER_DEBUG + qDebug(" -> ~QGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread()); +#endif + qDeleteAll(shaders); + shaders.clear(); + + qDeleteAll(cachedPrograms); + cachedPrograms.clear(); if (blitShaderProg) { delete blitShaderProg; @@ -276,7 +293,8 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS source.append(qShaderSnippets[prog.compositionFragShader]); if (prog.maskFragShader) source.append(qShaderSnippets[prog.maskFragShader]); - fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this); + fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), 0); + shaders.append(fragShader); QByteArray description; #if defined(QT_DEBUG) // Name the shader for easier debugging @@ -302,7 +320,8 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS source.clear(); source.append(qShaderSnippets[prog.mainVertexShader]); source.append(qShaderSnippets[prog.positionVertexShader]); - vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this); + vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), 0); + shaders.append(vertexShader); #if defined(QT_DEBUG) // Name the shader for easier debugging description.clear(); @@ -320,7 +339,7 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS newProg = new QGLEngineShaderProg(prog); // If the shader program's not found in the cache, create it now. - newProg->program = new QGLShaderProgram(ctxGuard.context(), this); + newProg->program = new QGLShaderProgram(ctxGuard.context(), 0); newProg->program->addShader(vertexShader); newProg->program->addShader(fragShader); @@ -413,7 +432,6 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context) currentShaderProg(0) { sharedShaders = QGLEngineSharedShaders::shadersForContext(context); - connect(sharedShaders, SIGNAL(shaderProgNeedsChanging()), this, SLOT(shaderProgNeedsChangingSlot())); } QGLEngineShaderManager::~QGLEngineShaderManager() diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 06b96ae..e5ababf 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -259,9 +259,9 @@ static const GLuint QT_PMV_MATRIX_3_ATTR = 5; class QGLEngineShaderProg; -class QGLEngineSharedShaders : public QObject +class QGLEngineSharedShaders { - Q_OBJECT + Q_GADGET public: enum SnippetName { @@ -364,14 +364,12 @@ public: // full. void cleanupCustomStage(QGLCustomShaderStage* stage); -signals: - void shaderProgNeedsChanging(); - private: QGLSharedResourceGuard ctxGuard; QGLShaderProgram *blitShaderProg; QGLShaderProgram *simpleShaderProg; QList<QGLEngineShaderProg*> cachedPrograms; + QList<QGLShader *> shaders; static const char* qShaderSnippets[TotalSnippetCount]; }; @@ -492,9 +490,6 @@ public: QGLEngineSharedShaders* sharedShaders; -private slots: - void shaderProgNeedsChangingSlot() { shaderProgNeedsChanging = true; } - private: QGLContext* ctx; bool shaderProgNeedsChanging; diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/gl2paintengineex/qglgradientcache.cpp index a1495dd..cbd5eb8 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache.cpp +++ b/src/opengl/gl2paintengineex/qglgradientcache.cpp @@ -42,29 +42,33 @@ #include "qglgradientcache_p.h" #include <private/qdrawhelper_p.h> #include <private/qgl_p.h> - +#include <QtCore/qmutex.h> QT_BEGIN_NAMESPACE -static void QGL2GradientCache_free(void *ptr) +class QGL2GradientCacheWrapper { - delete reinterpret_cast<QGL2GradientCache *>(ptr); -} +public: + QGL2GradientCache *cacheForContext(const QGLContext *context) { + QMutexLocker lock(&m_mutex); + return m_resource.value(context); + } -Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_gradient_caches, (QGL2GradientCache_free)) +private: + QGLContextGroupResource<QGL2GradientCache> m_resource; + QMutex m_mutex; +}; + +Q_GLOBAL_STATIC(QGL2GradientCacheWrapper, qt_gradient_caches) QGL2GradientCache *QGL2GradientCache::cacheForContext(const QGLContext *context) { - QGL2GradientCache *p = reinterpret_cast<QGL2GradientCache *>(qt_gradient_caches()->value(context)); - if (!p) { - QGLShareContextScope scope(context); - p = new QGL2GradientCache; - qt_gradient_caches()->insert(context, p); - } - return p; + return qt_gradient_caches()->cacheForContext(context); } -void QGL2GradientCache::cleanCache() { +void QGL2GradientCache::cleanCache() +{ + QMutexLocker lock(&m_mutex); QGLGradientColorTableHash::const_iterator it = cache.constBegin(); for (; it != cache.constEnd(); ++it) { const CacheInfo &cache_info = it.value(); @@ -75,6 +79,7 @@ void QGL2GradientCache::cleanCache() { GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity) { + QMutexLocker lock(&m_mutex); quint64 hash_val = 0; QGradientStops stops = gradient.stops(); @@ -88,7 +93,9 @@ GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity) else { do { const CacheInfo &cache_info = it.value(); - if (cache_info.stops == stops && cache_info.opacity == opacity && cache_info.interpolationMode == gradient.interpolationMode()) { + if (cache_info.stops == stops && cache_info.opacity == opacity + && cache_info.interpolationMode == gradient.interpolationMode()) + { return cache_info.texId; } ++it; diff --git a/src/opengl/gl2paintengineex/qglgradientcache_p.h b/src/opengl/gl2paintengineex/qglgradientcache_p.h index 0a5f846..7e93d87 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache_p.h +++ b/src/opengl/gl2paintengineex/qglgradientcache_p.h @@ -54,6 +54,7 @@ #include <QObject> #include <QtOpenGL/QtOpenGL> #include <private/qgl_p.h> +#include <QtCore/qmutex.h> QT_BEGIN_NAMESPACE @@ -75,22 +76,22 @@ class QGL2GradientCache public: static QGL2GradientCache *cacheForContext(const QGLContext *context); - QGL2GradientCache() { } - ~QGL2GradientCache() {cleanCache();} + QGL2GradientCache(const QGLContext *) {} + ~QGL2GradientCache() { cleanCache(); } GLuint getBuffer(const QGradient &gradient, qreal opacity); inline int paletteSize() const { return 1024; } -protected: +private: inline int maxCacheSize() const { return 60; } inline void generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const; GLuint addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity); - void cleanCache(); QGLGradientColorTableHash cache; + QMutex m_mutex; }; QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 2347e66..d89ef08 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1493,16 +1493,18 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp QOpenGL2PaintEngineState *s = q->state(); + void *cacheKey = const_cast<QGLContext *>(QGLContextPrivate::contextGroup(ctx)->context()); QGLTextureGlyphCache *cache = - (QGLTextureGlyphCache *) staticTextItem->fontEngine->glyphCache(ctx, glyphType, QTransform()); + (QGLTextureGlyphCache *) staticTextItem->fontEngine->glyphCache(cacheKey, glyphType, QTransform()); if (!cache || cache->cacheType() != glyphType) { cache = new QGLTextureGlyphCache(ctx, glyphType, QTransform()); - staticTextItem->fontEngine->setGlyphCache(ctx, cache); + staticTextItem->fontEngine->setGlyphCache(cacheKey, cache); } cache->setPaintEnginePrivate(this); cache->populate(staticTextItem->fontEngine, staticTextItem->numGlyphs, staticTextItem->glyphs, staticTextItem->glyphPositions); + cache->fillInPendingGlyphs(); if (cache->width() == 0 || cache->height() == 0) return; @@ -1549,8 +1551,15 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp vertexCoordinates->clear(); textureCoordinates->clear(); + bool supportsSubPixelPositions = staticTextItem->fontEngine->supportsSubPixelPositions(); for (int i=0; i<staticTextItem->numGlyphs; ++i) { - const QTextureGlyphCache::Coord &c = cache->coords.value(staticTextItem->glyphs[i]); + QFixed subPixelPosition; + if (supportsSubPixelPositions) + subPixelPosition = cache->subPixelPositionForX(staticTextItem->glyphPositions[i].x); + + QTextureGlyphCache::GlyphAndSubPixelPosition glyph(staticTextItem->glyphs[i], subPixelPosition); + + const QTextureGlyphCache::Coord &c = cache->coords.value(glyph); int x = staticTextItem->glyphPositions[i].x.toInt() + c.baseLineX - margin; int y = staticTextItem->glyphPositions[i].y.toInt() - c.baseLineY - margin; diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index 410cf21..3dc7789 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -52,43 +52,41 @@ QT_BEGIN_NAMESPACE extern Q_GUI_EXPORT bool qt_cleartype_enabled; #endif -QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix) +QGLTextureGlyphCache::QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix) : QImageTextureGlyphCache(type, matrix) - , ctx(context) - , m_width(0) - , m_height(0) + , ctx(0) + , pex(0) { - // broken FBO readback is a bug in the SGX 1.3 and 1.4 drivers for the N900 where - // copying between FBO's is broken if the texture is either GL_ALPHA or POT. The - // workaround is to use a system-memory copy of the glyph cache for this device. - // Switching to NPOT and GL_RGBA would both cost a lot more graphics memory and - // be slower, so that is not desireable. - if (!ctx->d_ptr->workaround_brokenFBOReadBack) - glGenFramebuffers(1, &m_fbo); - - connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)), - SLOT(contextDestroyed(const QGLContext*))); +#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG + qDebug(" -> QGLTextureGlyphCache() %p for context %p.", this, ctx); +#endif + setContext(context); } QGLTextureGlyphCache::~QGLTextureGlyphCache() { - if (ctx) { - QGLShareContextScope scope(ctx); - - if (!ctx->d_ptr->workaround_brokenFBOReadBack) - glDeleteFramebuffers(1, &m_fbo); +#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG + qDebug(" -> ~QGLTextureGlyphCache() %p.", this); +#endif +} - if (m_width || m_height) - glDeleteTextures(1, &m_texture); - } +void QGLTextureGlyphCache::setContext(const QGLContext *context) +{ + ctx = context; + m_h = 0; } void QGLTextureGlyphCache::createTextureData(int width, int height) { + if (ctx == 0) { + qWarning("QGLTextureGlyphCache::createTextureData: Called with no context"); + return; + } + // create in QImageTextureGlyphCache baseclass is meant to be called // only to create the initial image and does not preserve the content, // so we don't call when this function is called from resize. - if (ctx->d_ptr->workaround_brokenFBOReadBack && image().isNull()) + if ((pex == 0 || ctx->d_ptr->workaround_brokenFBOReadBack) && image().isNull()) QImageTextureGlyphCache::createTextureData(width, height); // Make the lower glyph texture size 16 x 16. @@ -97,11 +95,12 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) if (height < 16) height = 16; - glGenTextures(1, &m_texture); - glBindTexture(GL_TEXTURE_2D, m_texture); + QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx); + glGenTextures(1, &glyphTexture->m_texture); + glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); - m_width = width; - m_height = height; + glyphTexture->m_width = width; + glyphTexture->m_height = height; QVarLengthArray<uchar> data(width * height); for (int i = 0; i < data.size(); ++i) @@ -118,8 +117,14 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) void QGLTextureGlyphCache::resizeTextureData(int width, int height) { - int oldWidth = m_width; - int oldHeight = m_height; + if (ctx == 0) { + qWarning("QGLTextureGlyphCache::resizeTextureData: Called with no context"); + return; + } + QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx); + + int oldWidth = glyphTexture->m_width; + int oldHeight = glyphTexture->m_height; // Make the lower glyph texture size 16 x 16. if (width < 16) @@ -127,10 +132,10 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) if (height < 16) height = 16; - GLuint oldTexture = m_texture; + GLuint oldTexture = glyphTexture->m_texture; createTextureData(width, height); - - if (ctx->d_ptr->workaround_brokenFBOReadBack) { + + if (pex == 0 || ctx->d_ptr->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::resizeTextureData(width, height); Q_ASSERT(image().depth() == 8); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits()); @@ -141,7 +146,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) // ### the QTextureGlyphCache API needs to be reworked to allow // ### resizeTextureData to fail - glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo); + glBindFramebuffer(GL_FRAMEBUFFER_EXT, glyphTexture->m_fbo); GLuint tmp_texture; glGenTextures(1, &tmp_texture); @@ -196,7 +201,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindTexture(GL_TEXTURE_2D, m_texture); + glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); @@ -211,12 +216,18 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) pex->updateClipScissorTest(); } -void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph) +void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition) { - if (ctx->d_ptr->workaround_brokenFBOReadBack) { - QImageTextureGlyphCache::fillTexture(c, glyph); + if (ctx == 0) { + qWarning("QGLTextureGlyphCache::fillTexture: Called with no context"); + return; + } - glBindTexture(GL_TEXTURE_2D, m_texture); + QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx); + if (pex == 0 || ctx->d_ptr->workaround_brokenFBOReadBack) { + QImageTextureGlyphCache::fillTexture(c, glyph, subPixelPosition); + + glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); const QImage &texture = image(); const uchar *bits = texture.constBits(); bits += c.y * texture.bytesPerLine() + c.x; @@ -224,11 +235,10 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph) glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits); bits += texture.bytesPerLine(); } - return; } - QImage mask = textureMapForGlyph(glyph); + QImage mask = textureMapForGlyph(glyph, subPixelPosition); const int maskWidth = mask.width(); const int maskHeight = mask.height(); @@ -254,7 +264,7 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph) } } - glBindTexture(GL_TEXTURE_2D, m_texture); + glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); if (mask.format() == QImage::Format_RGB32) { glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits()); } else { diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h index 6bcd655..345684d 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h @@ -57,64 +57,85 @@ #include <private/qgl_p.h> #include <qglshaderprogram.h> +// #define QT_GL_TEXTURE_GLYPH_CACHE_DEBUG QT_BEGIN_NAMESPACE class QGL2PaintEngineExPrivate; -class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QObject, public QImageTextureGlyphCache +struct QGLGlyphTexture +{ + QGLGlyphTexture(const QGLContext *ctx) + : m_width(0) + , m_height(0) + { + if (ctx && !ctx->d_ptr->workaround_brokenFBOReadBack) + glGenFramebuffers(1, &m_fbo); + +#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG + qDebug(" -> QGLGlyphTexture() %p for context %p.", this, ctx); +#endif + } + + ~QGLGlyphTexture() { + const QGLContext *ctx = QGLContext::currentContext(); +#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG + qDebug("~QGLGlyphTexture() %p for context %p.", this, ctx); +#endif + // At this point, the context group is made current, so it's safe to + // release resources without a makeCurrent() call + if (ctx) { + if (!ctx->d_ptr->workaround_brokenFBOReadBack) + glDeleteFramebuffers(1, &m_fbo); + if (m_width || m_height) + glDeleteTextures(1, &m_texture); + } + } + + GLuint m_texture; + GLuint m_fbo; + int m_width; + int m_height; +}; + +class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QImageTextureGlyphCache { - Q_OBJECT public: - QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix); + QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix); ~QGLTextureGlyphCache(); virtual void createTextureData(int width, int height); virtual void resizeTextureData(int width, int height); - virtual void fillTexture(const Coord &c, glyph_t glyph); + virtual void fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition); virtual int glyphPadding() const; - inline GLuint texture() const { return m_texture; } + inline GLuint texture() const { + QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this); + QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx); + return glyphTexture ? glyphTexture->m_texture : 0; + } - inline int width() const { return m_width; } - inline int height() const { return m_height; } + inline int width() const { + QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this); + QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx); + return glyphTexture ? glyphTexture->m_width : 0; + } + inline int height() const { + QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this); + QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx); + return glyphTexture ? glyphTexture->m_height : 0; + } inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; } - -public Q_SLOTS: - void contextDestroyed(const QGLContext *context) { - if (context == ctx) { - const QGLContext *nextCtx = qt_gl_transfer_context(ctx); - if (!nextCtx) { - // the context may not be current, so we cannot directly - // destroy the fbo and texture here, but since the context - // is about to be destroyed, the GL server will do the - // clean up for us anyway - m_fbo = 0; - m_texture = 0; - ctx = 0; - } else { - // since the context holding the texture is shared, and - // about to be destroyed, we have to transfer ownership - // of the texture to one of the share contexts - ctx = const_cast<QGLContext *>(nextCtx); - } - } - } + void setContext(const QGLContext *context); + inline const QGLContext *context() const { return ctx; } private: - QGLContext *ctx; + QGLContextGroupResource<QGLGlyphTexture> m_textureResource; + const QGLContext *ctx; QGL2PaintEngineExPrivate *pex; - - GLuint m_texture; - GLuint m_fbo; - - int m_width; - int m_height; - - QGLShaderProgram *m_program; }; QT_END_NAMESPACE diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index 0e82467..c7ca4bc 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -20,6 +20,7 @@ contains(QT_CONFIG, egl):CONFIG += egl HEADERS += qgl.h \ qgl_p.h \ qglcolormap.h \ + qglfunctions.h \ qglpixelbuffer.h \ qglpixelbuffer_p.h \ qglframebufferobject.h \ @@ -29,8 +30,9 @@ HEADERS += qgl.h \ qglbuffer.h \ -SOURCES += qgl.cpp \ +SOURCES += qgl.cpp \ qglcolormap.cpp \ + qglfunctions.cpp \ qglpixelbuffer.cpp \ qglframebufferobject.cpp \ qglextensions.cpp \ diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 15070d4..d9b094e 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -94,6 +94,8 @@ #include <qmutex.h> +// #define QT_GL_CONTEXT_RESOURCE_DEBUG + QT_BEGIN_NAMESPACE #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) @@ -105,6 +107,10 @@ extern const QX11Info *qt_x11Info(const QPaintDevice *pd); #endif struct QGLThreadContext { + ~QGLThreadContext() { + if (context) + context->doneCurrent(); + } QGLContext *context; }; @@ -1657,6 +1663,7 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) #if defined(Q_WS_WIN) dc = 0; win = 0; + threadId = 0; pixelFormatId = 0; cmap = 0; hbitmap = 0; @@ -2062,6 +2069,9 @@ QGLContext::~QGLContext() // remove any textures cached in this context QGLTextureCache::instance()->removeContextTextures(this); + // clean up resources specific to this context + d_ptr->cleanup(); + // clean up resources belonging to this context's group d_ptr->group->cleanupResources(this); QGLSignalProxy::instance()->emitAboutToDestroyContext(this); @@ -2070,6 +2080,10 @@ QGLContext::~QGLContext() void QGLContextPrivate::cleanup() { + QHash<QGLContextResourceBase *, void *>::ConstIterator it; + for (it = m_resources.begin(); it != m_resources.end(); ++it) + it.key()->freeResource(it.value()); + m_resources.clear(); } #define ctx q_ptr @@ -2129,20 +2143,10 @@ void QGLContextPrivate::swapRegion(const QRegion *) GLuint QGLContext::bindTexture(const QString &fileName) { - Q_D(QGLContext); - QGLDDSCache *dds_cache = &(d->group->m_dds_cache); - QGLDDSCache::const_iterator it = dds_cache->constFind(fileName); - if (it != dds_cache->constEnd()) { - glBindTexture(GL_TEXTURE_2D, it.value()); - return it.value(); - } - QGLTexture texture(this); QSize size = texture.bindCompressedTexture(fileName); if (!size.isValid()) return 0; - - dds_cache->insert(fileName, texture.id); return texture.id; } @@ -2582,7 +2586,8 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, const QX11Info *xinfo = qt_x11Info(paintDevice); if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType && xinfo && xinfo->screen() == pixmap.x11Info().screen() - && target == GL_TEXTURE_2D) + && target == GL_TEXTURE_2D + && QApplication::instance()->thread() == QThread::currentThread()) { if (!workaround_brokenTextureFromPixmap_init) { workaround_brokenTextureFromPixmap_init = true; @@ -2803,24 +2808,8 @@ GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, Q */ void QGLContext::deleteTexture(GLuint id) { - Q_D(QGLContext); - if (QGLTextureCache::instance()->remove(this, id)) return; - - // check the DDS cache if the texture wasn't found in the pixmap/image - // cache - QGLDDSCache *dds_cache = &(d->group->m_dds_cache); - QList<QString> ddsKeys = dds_cache->keys(); - for (int i = 0; i < ddsKeys.size(); ++i) { - GLuint texture = dds_cache->value(ddsKeys.at(i)); - if (id == texture) { - dds_cache->remove(ddsKeys.at(i)); - break; - } - } - - // Finally, actually delete the texture ID glDeleteTextures(1, &id); } @@ -3617,12 +3606,90 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) \section1 Threading - It is possible to render into a QGLWidget from another thread, but it - requires that all access to the GL context is safe guarded. The Qt GUI - thread will try to use the context in resizeEvent and paintEvent, so in - order for threaded rendering using a GL widget to work, these functions - need to be intercepted in the GUI thread and handled accordingly in the - application. + As of Qt version 4.8, support for doing threaded GL rendering has + been improved. There are three scenarios that we currently support: + \list + \o 1. Buffer swapping in a thread. + + Swapping buffers in a double buffered context may be a + synchronous, locking call that may be a costly operation in some + GL implementations. Especially so on embedded devices. It's not + optimal to have the CPU idling while the GPU is doing a buffer + swap. In those cases it is possible to do the rendering in the + main thread and do the actual buffer swap in a separate + thread. This can be done with the following steps: + + 1. Call doneCurrent() in the main thread when the rendering is + finished. + + 2. Notify the swapping thread that it can grab the context. + + 3. Make the rendering context current in the swapping thread with + makeCurrent() and then call swapBuffers(). + + 4. Call doneCurrent() in the swapping thread and notify the main + thread that swapping is done. + + Doing this will free up the main thread so that it can continue + with, for example, handling UI events or network requests. Even if + there is a context swap involved, it may be preferable compared to + having the main thread wait while the GPU finishes the swap + operation. Note that this is highly implementation dependent. + + \o 2. Texture uploading in a thread. + + Doing texture uploads in a thread may be very useful for + applications handling large amounts of images that needs to be + displayed, like for instance a photo gallery application. This is + supported in Qt through the existing bindTexture() API. A simple + way of doing this is to create two sharing QGLWidgets. One is made + current in the main GUI thread, while the other is made current in + the texture upload thread. The widget in the uploading thread is + never shown, it is only used for sharing textures with the main + thread. For each texture that is bound via bindTexture(), notify + the main thread so that it can start using the texture. + + \o 3. Using QPainter to draw into a QGLWidget in a thread. + + In Qt 4.8, it is possible to draw into a QGLWidget using a + QPainter in a separate thread. Note that this is also possible for + QGLPixelBuffers and QGLFramebufferObjects. Since this is only + supported in the GL 2 paint engine, OpenGL 2.0 or OpenGL ES 2.0 is + required. + + QGLWidgets can only be created in the main GUI thread. This means + a call to doneCurrent() is necessary to release the GL context + from the main thread, before the widget can be drawn into by + another thread. Also, the main GUI thread will dispatch resize and + paint events to a QGLWidget when the widget is resized, or parts + of it becomes exposed or needs redrawing. It is therefore + necessary to handle those events because the default + implementations inside QGLWidget will try to make the QGLWidget's + context current, which again will interfere with any threads + rendering into the widget. Reimplement QGLWidget::paintEvent() and + QGLWidget::resizeEvent() to notify the rendering thread that a + resize or update is necessary, and be careful not to call the base + class implementation. If you are rendering an animation, it might + not be necessary to handle the paint event at all since the + rendering thread is doing regular updates. Then it would be enough + to reimplement QGLWidget::paintEvent() to do nothing. + + \endlist + + As a general rule when doing threaded rendering: be aware that + binding and releasing contexts in different threads have to be + synchronized by the user. A GL rendering context can only be + current in one thread at any time. If you try to open a QPainter + on a QGLWidget and the widget's rendering context is current in + another thread, it will fail. + + Note that under X11 it is necessary to set the + Qt::AA_X11InitThreads application attribute to make the X11 + library and GLX calls thread safe, otherwise the above scenarios + will fail. + + In addition to this, rendering using raw GL calls in a separate + thread is supported. \e{OpenGL is a trademark of Silicon Graphics, Inc. in the United States and other countries.} @@ -4138,13 +4205,7 @@ bool QGLWidget::event(QEvent *e) } #if defined(Q_WS_X11) - // prevents X errors on some systems, where we get a flush to a - // hidden widget - if (e->type() == QEvent::Hide) { - makeCurrent(); - glFinish(); - doneCurrent(); - } else if (e->type() == QEvent::ParentChange) { + if (e->type() == QEvent::ParentChange) { // if we've reparented a window that has the current context // bound, we need to rebind that context to the new window id if (d->glcx == QGLContext::currentContext()) @@ -5146,24 +5207,24 @@ void QGLWidget::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QM #endif #ifndef QT_OPENGL_ES_1 -Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_2_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_gl_2_engine) #endif #ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QOpenGLPaintEngine>, qt_gl_engine) #endif Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine() { #if defined(QT_OPENGL_ES_1) - return qt_gl_engine(); + return qt_gl_engine()->engine(); #elif defined(QT_OPENGL_ES_2) - return qt_gl_2_engine(); + return qt_gl_2_engine()->engine(); #else if (qt_gl_preferGL2Engine()) - return qt_gl_2_engine(); + return qt_gl_2_engine()->engine(); else - return qt_gl_engine(); + return qt_gl_engine()->engine(); #endif } @@ -5433,13 +5494,23 @@ void QGLContextGroup::removeShare(const QGLContext *context) { group->m_shares.clear(); } -QGLContextResource::QGLContextResource(FreeFunc f) - : free(f), active(0) +QGLContextGroupResourceBase::QGLContextGroupResourceBase() + : active(0) { +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Creating context group resource object %p.", this); +#endif } -QGLContextResource::~QGLContextResource() +QGLContextGroupResourceBase::~QGLContextGroupResourceBase() { +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Deleting context group resource %p. Group size: %d.", this, m_groups.size()); +#endif + for (int i = 0; i < m_groups.size(); ++i) { + m_groups.at(i)->m_resources.remove(this); + active.deref(); + } #ifndef QT_NO_DEBUG if (active != 0) { qWarning("QtOpenGL: Resources are still available at program shutdown.\n" @@ -5449,37 +5520,47 @@ QGLContextResource::~QGLContextResource() #endif } -void QGLContextResource::insert(const QGLContext *key, void *value) +void QGLContextGroupResourceBase::insert(const QGLContext *context, void *value) { - QGLContextGroup *group = QGLContextPrivate::contextGroup(key); +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Inserting context group resource %p for context %p, managed by %p.", value, context, this); +#endif + QGLContextGroup *group = QGLContextPrivate::contextGroup(context); Q_ASSERT(!group->m_resources.contains(this)); group->m_resources.insert(this, value); + m_groups.append(group); active.ref(); } -void *QGLContextResource::value(const QGLContext *key) +void *QGLContextGroupResourceBase::value(const QGLContext *context) { - QGLContextGroup *group = QGLContextPrivate::contextGroup(key); + QGLContextGroup *group = QGLContextPrivate::contextGroup(context); return group->m_resources.value(this, 0); } -void QGLContextResource::cleanup(const QGLContext *ctx, void *value) +void QGLContextGroupResourceBase::cleanup(const QGLContext *ctx, void *value) { +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Cleaning up context group resource %p, for context %p in thread %p.", this, ctx, QThread::currentThread()); +#endif QGLShareContextScope scope(ctx); - free(value); + freeResource(value); active.deref(); + + QGLContextGroup *group = QGLContextPrivate::contextGroup(ctx); + m_groups.removeOne(group); } -void QGLContextGroup::cleanupResources(const QGLContext *ctx) +void QGLContextGroup::cleanupResources(const QGLContext *context) { // If there are still shares, then no cleanup to be done yet. if (m_shares.size() > 1) return; // Iterate over all resources and free each in turn. - QHash<QGLContextResource *, void *>::ConstIterator it; + QHash<QGLContextGroupResourceBase *, void *>::ConstIterator it; for (it = m_resources.begin(); it != m_resources.end(); ++it) - it.key()->cleanup(ctx, it.value()); + it.key()->cleanup(context, it.value()); } QGLSharedResourceGuard::~QGLSharedResourceGuard() diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index f85cad5..2ac4cb6 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -56,7 +56,6 @@ QT_BEGIN_HEADER #if defined(Q_WS_MAC) # include <OpenGL/gl.h> -# include <OpenGL/glu.h> #elif defined(QT_OPENGL_ES_1) # include <GLES/gl.h> #ifndef GL_DOUBLE @@ -75,9 +74,6 @@ typedef GLfloat GLdouble; #endif #else # include <GL/gl.h> -# ifndef QT_LINUXBASE -# include <GL/glu.h> -# endif #endif QT_BEGIN_NAMESPACE @@ -424,6 +420,7 @@ private: friend class QGLPixmapData; friend class QGLPixmapFilterBase; friend class QGLTextureGlyphCache; + friend struct QGLGlyphTexture; friend class QGLContextGroup; friend class QGLSharedResourceGuard; friend class QGLPixmapBlurFilter; @@ -443,6 +440,7 @@ private: friend class QGLWidgetGLPaintDevice; friend class QX11GLPixmapData; friend class QX11GLSharedContexts; + friend class QGLContextResourceBase; private: Q_DISABLE_COPY(QGLContext) }; diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 623eeaf..78f888a 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -217,11 +217,9 @@ public: #endif }; -class QGLContextResource; +class QGLContextGroupResourceBase; class QGLSharedResourceGuard; -typedef QHash<QString, GLuint> QGLDDSCache; - // QGLContextPrivate has the responsibility of creating context groups. // QGLContextPrivate maintains the reference counter and destroys // context groups when needed. @@ -240,22 +238,22 @@ public: static void addShare(const QGLContext *context, const QGLContext *share); static void removeShare(const QGLContext *context); + private: QGLContextGroup(const QGLContext *context); QGLExtensionFuncs m_extensionFuncs; const QGLContext *m_context; // context group's representative QList<const QGLContext *> m_shares; - QHash<QGLContextResource *, void *> m_resources; + QHash<QGLContextGroupResourceBase *, void *> m_resources; QGLSharedResourceGuard *m_guards; // double-linked list of active guards. QAtomicInt m_refs; - QGLDDSCache m_dds_cache; void cleanupResources(const QGLContext *ctx); friend class QGLContext; friend class QGLContextPrivate; - friend class QGLContextResource; + friend class QGLContextGroupResourceBase; }; // Get the context that resources for "ctx" will transfer to once @@ -321,6 +319,8 @@ class QGLTexture; // all the GL2 engine uses: #define QT_GL_VERTEX_ARRAY_TRACKED_COUNT 3 +class QGLContextResourceBase; + class QGLContextPrivate { Q_DECLARE_PUBLIC(QGLContext) @@ -356,6 +356,7 @@ public: QGLCmap* cmap; HBITMAP hbitmap; HDC hbitmap_hdc; + Qt::HANDLE threadId; #endif #ifndef QT_NO_EGL uint ownsEglContext : 1; @@ -416,6 +417,7 @@ public: GLuint current_fbo; GLuint default_fbo; QPaintEngine *active_engine; + QHash<QGLContextResourceBase *, void *> m_resources; bool vertexAttributeArraysEnabledState[QT_GL_VERTEX_ARRAY_TRACKED_COUNT]; @@ -426,7 +428,7 @@ public: #endif #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) - static QGLExtensionFuncs qt_extensionFuncs; + static Q_OPENGL_EXPORT QGLExtensionFuncs qt_extensionFuncs; static Q_OPENGL_EXPORT QGLExtensionFuncs& extensionFuncs(const QGLContext *); #endif @@ -624,24 +626,130 @@ inline GLenum qt_gl_preferredTextureTarget() #endif } -// One resource per group of shared contexts. -class Q_OPENGL_EXPORT QGLContextResource +/* + Base for resources that are shared in a context group. +*/ +class Q_OPENGL_EXPORT QGLContextGroupResourceBase { public: - typedef void (*FreeFunc)(void *); - QGLContextResource(FreeFunc f); - ~QGLContextResource(); - // Set resource 'value' for 'key' and all its shared contexts. - void insert(const QGLContext *key, void *value); - // Return resource for 'key' or a shared context. - void *value(const QGLContext *key); - // Cleanup 'value' in response to a context group being destroyed. - void cleanup(const QGLContext *ctx, void *value); + QGLContextGroupResourceBase(); + virtual ~QGLContextGroupResourceBase(); + void insert(const QGLContext *context, void *value); + void *value(const QGLContext *context); + void cleanup(const QGLContext *context, void *value); + virtual void freeResource(void *value) = 0; + +protected: + QList<QGLContextGroup *> m_groups; + private: - FreeFunc free; QAtomicInt active; }; +/* + The QGLContextGroupResource template is used to manage a resource + for a group of sharing GL contexts. When the last context in the + group is destroyed, or when the QGLContextGroupResource object + itself is destroyed (implies potential context switches), the + resource will be freed. + + The class used as the template class type needs to have a + constructor with the following signature: + T(const QGLContext *); +*/ +template <class T> +class QGLContextGroupResource : public QGLContextGroupResourceBase +{ +public: + ~QGLContextGroupResource() { + for (int i = 0; i < m_groups.size(); ++i) { + const QGLContext *context = m_groups.at(i)->context(); + T *resource = reinterpret_cast<T *>(QGLContextGroupResourceBase::value(context)); + if (resource) { + QGLShareContextScope scope(context); + delete resource; + } + } + } + + T *value(const QGLContext *context) { + T *resource = reinterpret_cast<T *>(QGLContextGroupResourceBase::value(context)); + if (!resource) { + resource = new T(context); + insert(context, resource); + } + return resource; + } + +protected: + void freeResource(void *resource) { + delete reinterpret_cast<T *>(resource); + } +}; + +/* + Base for resources that are context specific. +*/ +class Q_OPENGL_EXPORT QGLContextResourceBase +{ +public: + virtual ~QGLContextResourceBase() { + for (int i = 0; i < m_contexts.size(); ++i) + m_contexts.at(i)->d_ptr->m_resources.remove(this); + } + + void insert(const QGLContext *context, void *value) { + context->d_ptr->m_resources.insert(this, value); + } + + void *value(const QGLContext *context) { + return context->d_ptr->m_resources.value(this, 0); + } + virtual void freeResource(void *value) = 0; + +protected: + QList<const QGLContext *> m_contexts; +}; + +/* + The QGLContextResource template is used to manage a resource for a + single GL context. Just before the context is destroyed (while it's + still the current context), or when the QGLContextResource object + itself is destroyed (implies potential context switches), the + resource will be freed. The class used as the template class type + needs to have a constructor with the following signature: T(const + QGLContext *); +*/ +template <class T> +class QGLContextResource : public QGLContextResourceBase +{ +public: + ~QGLContextResource() { + for (int i = 0; i < m_contexts.size(); ++i) { + const QGLContext *context = m_contexts.at(i); + T *resource = reinterpret_cast<T *>(QGLContextResourceBase::value(context)); + if (resource) { + QGLShareContextScope scope(context); + delete resource; + } + } + } + + T *value(const QGLContext *context) { + T *resource = reinterpret_cast<T *>(QGLContextResourceBase::value(context)); + if (!resource) { + resource = new T(context); + insert(context, resource); + } + return resource; + } + +protected: + void freeResource(void *resource) { + delete reinterpret_cast<T *>(resource); + } +}; + // Put a guard around a GL object identifier and its context. // When the context goes away, a shared context will be used // in its place. If there are no more shared contexts, then @@ -731,6 +839,24 @@ private: int gl_extensions_length; }; + +// this is a class that wraps a QThreadStorage object for storing +// thread local instances of the GL 1 and GL 2 paint engines + +template <class T> +class QGLEngineThreadStorage +{ +public: + QPaintEngine *engine() { + QPaintEngine *&localEngine = storage.localData(); + if (!localEngine) + localEngine = new T; + return localEngine; + } + +private: + QThreadStorage<QPaintEngine *> storage; +}; QT_END_NAMESPACE #endif // QGL_P_H diff --git a/src/opengl/qgl_win.cpp b/src/opengl/qgl_win.cpp index 8eb6177..5f7d4e2 100644 --- a/src/opengl/qgl_win.cpp +++ b/src/opengl/qgl_win.cpp @@ -1261,6 +1261,7 @@ void QGLContext::reset() } d->dc = 0; d->win = 0; + d->threadId = 0; d->pixelFormatId = 0; d->sharing = false; d->valid = false; @@ -1283,8 +1284,9 @@ void QGLContext::makeCurrent() if (d->rc == wglGetCurrentContext() || !d->valid) // already current return; - if (d->win) { + if (d->win && (!d->dc || d->threadId != QThread::currentThreadId())) { d->dc = GetDC(d->win); + d->threadId = QThread::currentThreadId(); if (!d->dc) { qwglError("QGLContext::makeCurrent()", "GetDC()"); return; @@ -1322,6 +1324,7 @@ void QGLContext::doneCurrent() if (d->win && d->dc) { ReleaseDC(d->win, d->dc); d->dc = 0; + d->threadId = 0; } } diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp index 9d28de0..1f7e60a 100644 --- a/src/opengl/qgl_x11egl.cpp +++ b/src/opengl/qgl_x11egl.cpp @@ -97,7 +97,6 @@ QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) XVisualInfo visualInfo; XVisualInfo *vi; int numVisuals; - EGLint id = 0; visualInfo.visualid = QEgl::getCompatibleVisualId(config); vi = XGetVisualInfo(X11->display, VisualIDMask, &visualInfo, &numVisuals); @@ -346,7 +345,7 @@ void QGLWidgetPrivate::recreateEglSurface() // old surface before re-creating a new one. Note: This should not be the case as the // surface should be deleted before the old window id. if (glcx->d_func()->eglSurface != EGL_NO_SURFACE && (currentId != eglSurfaceWindowId)) { - qWarning("EGL surface for deleted window %x was not destroyed", eglSurfaceWindowId); + qWarning("EGL surface for deleted window %lx was not destroyed", eglSurfaceWindowId); glcx->d_func()->destroyEglSurfaceForDevice(); } diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h index 6259cca..6d7449d 100644 --- a/src/opengl/qglextensions_p.h +++ b/src/opengl/qglextensions_p.h @@ -872,10 +872,10 @@ struct QGLExtensionFuncs #endif extern bool qt_resolve_framebufferobject_extensions(QGLContext *ctx); -bool qt_resolve_buffer_extensions(QGLContext *ctx); +bool Q_OPENGL_EXPORT qt_resolve_buffer_extensions(QGLContext *ctx); bool qt_resolve_version_1_3_functions(QGLContext *ctx); -bool qt_resolve_version_2_0_functions(QGLContext *ctx); +bool Q_OPENGL_EXPORT qt_resolve_version_2_0_functions(QGLContext *ctx); bool qt_resolve_stencil_face_extension(QGLContext *ctx); bool qt_resolve_frag_program_extensions(QGLContext *ctx); diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index adbba85..cee950a 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -620,6 +620,13 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, as a texture, you first need to copy from it to a regular framebuffer object using QGLContext::blitFramebuffer(). + \section Threading + + As of Qt 4.8, it's possible to draw into a QGLFramebufferObject + using a QPainter in a separate thread. Note that OpenGL 2.0 or + OpenGL ES 2.0 is required for this to work. Also, under X11, it's + necessary to set the Qt::AA_X11InitThreads application attribute. + \sa {Framebuffer Object Example} */ @@ -988,11 +995,11 @@ QImage QGLFramebufferObject::toImage() const } #if !defined(QT_OPENGL_ES_1) -Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_buffer_2_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_buffer_2_engine) #endif #ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QOpenGLPaintEngine>, qt_buffer_engine) #endif /*! \reimp */ @@ -1006,7 +1013,7 @@ QPaintEngine *QGLFramebufferObject::paintEngine() const #if !defined (QT_OPENGL_ES_2) if (qt_gl_preferGL2Engine()) { #endif - QPaintEngine *engine = qt_buffer_2_engine(); + QPaintEngine *engine = qt_buffer_2_engine()->engine(); if (engine->isActive() && engine->paintDevice() != this) { d->engine = new QGL2PaintEngineEx; return d->engine; @@ -1018,7 +1025,7 @@ QPaintEngine *QGLFramebufferObject::paintEngine() const #endif #if !defined(QT_OPENGL_ES_2) - QPaintEngine *engine = qt_buffer_engine(); + QPaintEngine *engine = qt_buffer_engine()->engine(); if (engine->isActive() && engine->paintDevice() != this) { d->engine = new QOpenGLPaintEngine; return d->engine; diff --git a/src/opengl/qglfunctions.cpp b/src/opengl/qglfunctions.cpp new file mode 100644 index 0000000..8a544c1 --- /dev/null +++ b/src/opengl/qglfunctions.cpp @@ -0,0 +1,3705 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenGL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qglfunctions.h" +#include "qgl_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QGLFunctions + \brief The QGLFunctions class provides cross-platform access to the OpenGL/ES 2.0 API. + \since 4.8 + \ingroup painting-3D + + OpenGL/ES 2.0 defines a subset of the OpenGL specification that is + common across many desktop and embedded OpenGL implementations. + However, it can be difficult to use the functions from that subset + because they need to be resolved manually on desktop systems. + + QGLFunctions provides a guaranteed API that is available on all + OpenGL systems and takes care of function resolution on systems + that need it. The recommended way to use QGLFunctions is by + direct inheritance: + + \code + class MyGLWidget : public QGLWidget, protected QGLFunctions + { + Q_OBJECT + public: + MyGLWidget(QWidget *parent = 0) : QGLWidget(parent) {} + + protected: + void initializeGL(); + void paintGL(); + }; + + void MyGLWidget::initializeGL() + { + initializeGLFunctions(); + } + \endcode + + The \c{paintGL()} function can then use any of the OpenGL/ES 2.0 + functions without explicit resolution, such as glActiveTexture() + in the following example: + + \code + void MyGLWidget::paintGL() + { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, textureId); + ... + } + \endcode + + QGLFunctions can also be used directly for ad-hoc invocation + of OpenGL/ES 2.0 functions on all platforms: + + \code + QGLFunctions glFuncs(QGLContext::currentContext()); + glFuncs.glActiveTexture(GL_TEXTURE1); + \endcode + + QGLFunctions provides wrappers for all OpenGL/ES 2.0 functions, + except those like \c{glDrawArrays()}, \c{glViewport()}, and + \c{glBindTexture()} that don't have portability issues. + + Including the header for QGLFunctions will also define all of + the OpenGL/ES 2.0 macro constants that are not already defined by + the system's OpenGL headers, such as \c{GL_TEXTURE1} above. + + The hasOpenGLFeature() and openGLFeatures() functions can be used + to determine if the OpenGL implementation has a major OpenGL/ES 2.0 + feature. For example, the following checks if non power of two + textures are available: + + \code + QGLFunctions funcs(QGLContext::currentContext()); + bool npot = funcs.hasOpenGLFeature(QGLFunctions::NPOTTextures); + \endcode +*/ + +/*! + \enum QGLFunctions::OpenGLFeature + This enum defines OpenGL/ES 2.0 features that may be optional + on other platforms. + + \value Multitexture glActiveTexture() function is available. + \value Shaders Shader functions are available. + \value Buffers Vertex and index buffer functions are available. + \value Framebuffers Framebuffer object functions are available. + \value BlendColor glBlendColor() is available. + \value BlendEquation glBlendEquation() is available. + \value BlendEquationSeparate glBlendEquationSeparate() is available. + \value BlendFuncSeparate glBlendFuncSeparate() is available. + \value BlendSubtract Blend subtract mode is available. + \value CompressedTextures Compressed texture functions are available. + \value Multisample glSampleCoverage() function is available. + \value StencilSeparate Separate stencil functions are available. + \value NPOTTextures Non power of two textures are available. +*/ + +// Hidden private fields for additional extension data. +struct QGLFunctionsPrivateEx : public QGLFunctionsPrivate +{ + QGLFunctionsPrivateEx(const QGLContext *context = 0) + : QGLFunctionsPrivate(context) + , m_features(-1) {} + + int m_features; +}; + +#if QT_VERSION >= 0x040800 +Q_GLOBAL_STATIC(QGLContextGroupResource<QGLFunctionsPrivateEx>, qt_gl_functions_resource) +#else +static void qt_gl_functions_free(void *data) +{ + delete reinterpret_cast<QGLFunctionsPrivateEx *>(data); +} + +Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_gl_functions_resource, (qt_gl_functions_free)) +#endif +static QGLFunctionsPrivateEx *qt_gl_functions(const QGLContext *context = 0) +{ + if (!context) + context = QGLContext::currentContext(); + Q_ASSERT(context); + QGLFunctionsPrivateEx *funcs = + reinterpret_cast<QGLFunctionsPrivateEx *> + (qt_gl_functions_resource()->value(context)); +#if QT_VERSION < 0x040800 + if (!funcs) { + funcs = new QGLFunctionsPrivateEx(); + qt_gl_functions_resource()->insert(context, funcs); + } +#endif + return funcs; +} + +/*! + Constructs a default function resolver. The resolver cannot + be used until initializeGLFunctions() is called to specify + the context. + + \sa initializeGLFunctions() +*/ +QGLFunctions::QGLFunctions() + : d_ptr(0) +{ +} + +/*! + Constructs a function resolver for \a context. If \a context + is null, then the resolver will be created for the current QGLContext. + + An object constructed in this way can only be used with \a context + and other contexts that share with it. Use initializeGLFunctions() + to change the object's context association. + + \sa initializeGLFunctions() +*/ +QGLFunctions::QGLFunctions(const QGLContext *context) + : d_ptr(qt_gl_functions(context)) +{ +} + +/*! + \fn QGLFunctions::~QGLFunctions() + + Destroys this function resolver. +*/ + +static int qt_gl_resolve_features() +{ +#if defined(QT_OPENGL_ES_2) + return QGLFunctions::Multitexture | + QGLFunctions::Shaders | + QGLFunctions::Buffers | + QGLFunctions::Framebuffers | + QGLFunctions::BlendColor | + QGLFunctions::BlendEquation | + QGLFunctions::BlendEquationSeparate | + QGLFunctions::BlendFuncSeparate | + QGLFunctions::BlendSubtract | + QGLFunctions::CompressedTextures | + QGLFunctions::Multisample | + QGLFunctions::StencilSeparate | + QGLFunctions::NPOTTextures; +#elif defined(QT_OPENGL_ES) + int features = QGLFunctions::Multitexture | + QGLFunctions::Buffers | + QGLFunctions::CompressedTextures | + QGLFunctions::Multisample; + QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); + if (extensions.match("GL_OES_framebuffer_object")) + features |= QGLFunctions::Framebuffers; + if (extensions.match("GL_OES_blend_equation_separate")) + features |= QGLFunctions::BlendEquationSeparate; + if (extensions.match("GL_OES_blend_func_separate")) + features |= QGLFunctions::BlendFuncSeparate; + if (extensions.match("GL_OES_blend_subtract")) + features |= QGLFunctions::BlendSubtract; + if (extensions.match("GL_OES_texture_npot")) + features |= QGLFunctions::NPOTTextures; + return features; +#else + int features = 0; + QGLFormat::OpenGLVersionFlags versions = QGLFormat::openGLVersionFlags(); + QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); + + // Recognize features by extension name. + if (extensions.match("GL_ARB_multitexture")) + features |= QGLFunctions::Multitexture; + if (extensions.match("GL_ARB_shader_objects")) + features |= QGLFunctions::Shaders; + if (extensions.match("GL_EXT_framebuffer_object") || + extensions.match("GL_ARB_framebuffer_object")) + features |= QGLFunctions::Framebuffers; + if (extensions.match("GL_EXT_blend_color")) + features |= QGLFunctions::BlendColor; + if (extensions.match("GL_EXT_blend_equation_separate")) + features |= QGLFunctions::BlendEquationSeparate; + if (extensions.match("GL_EXT_blend_func_separate")) + features |= QGLFunctions::BlendFuncSeparate; + if (extensions.match("GL_EXT_blend_subtract")) + features |= QGLFunctions::BlendSubtract; + if (extensions.match("GL_ARB_texture_compression")) + features |= QGLFunctions::CompressedTextures; + if (extensions.match("GL_ARB_multisample")) + features |= QGLFunctions::Multisample; + if (extensions.match("GL_ARB_texture_non_power_of_two")) + features |= QGLFunctions::NPOTTextures; + + // Recognize features by minimum OpenGL version. + if (versions & QGLFormat::OpenGL_Version_1_2) { + features |= QGLFunctions::BlendColor | + QGLFunctions::BlendEquation; + } + if (versions & QGLFormat::OpenGL_Version_1_3) { + features |= QGLFunctions::Multitexture | + QGLFunctions::CompressedTextures | + QGLFunctions::Multisample; + } + if (versions & QGLFormat::OpenGL_Version_1_4) + features |= QGLFunctions::BlendFuncSeparate; + if (versions & QGLFormat::OpenGL_Version_1_5) + features |= QGLFunctions::Buffers; + if (versions & QGLFormat::OpenGL_Version_2_0) { + features |= QGLFunctions::Shaders | + QGLFunctions::StencilSeparate | + QGLFunctions::BlendEquationSeparate | + QGLFunctions::NPOTTextures; + } + return features; +#endif +} + +/*! + Returns the set of features that are present on this system's + OpenGL implementation. + + It is assumed that the QGLContext associated with this function + resolver is current. + + \sa hasOpenGLFeature() +*/ +QGLFunctions::OpenGLFeatures QGLFunctions::openGLFeatures() const +{ + QGLFunctionsPrivateEx *d = static_cast<QGLFunctionsPrivateEx *>(d_ptr); + if (!d) + return 0; + if (d->m_features == -1) + d->m_features = qt_gl_resolve_features(); + return QGLFunctions::OpenGLFeatures(d->m_features); +} + +/*! + Returns true if \a feature is present on this system's OpenGL + implementation; false otherwise. + + It is assumed that the QGLContext associated with this function + resolver is current. + + \sa openGLFeatures() +*/ +bool QGLFunctions::hasOpenGLFeature(QGLFunctions::OpenGLFeature feature) const +{ + QGLFunctionsPrivateEx *d = static_cast<QGLFunctionsPrivateEx *>(d_ptr); + if (!d) + return false; + if (d->m_features == -1) + d->m_features = qt_gl_resolve_features(); + return (d->m_features & int(feature)) != 0; +} + +/*! + Initializes GL function resolution for \a context. If \a context + is null, then the current QGLContext will be used. + + After calling this function, the QGLFunctions object can only be + used with \a context and other contexts that share with it. + Call initializeGLFunctions() again to change the object's context + association. +*/ +void QGLFunctions::initializeGLFunctions(const QGLContext *context) +{ + d_ptr = qt_gl_functions(context); +} + +/*! + \fn void QGLFunctions::glActiveTexture(GLenum texture) + + Convenience function that calls glActiveTexture(\a texture). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glActiveTexture.xml}{glActiveTexture()}. +*/ + +/*! + \fn void QGLFunctions::glAttachShader(GLuint program, GLuint shader) + + Convenience function that calls glAttachShader(\a program, \a shader). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glAttachShader.xml}{glAttachShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glBindAttribLocation(GLuint program, GLuint index, const char* name) + + Convenience function that calls glBindAttribLocation(\a program, \a index, \a name). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBindAttribLocation.xml}{glBindAttribLocation()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glBindBuffer(GLenum target, GLuint buffer) + + Convenience function that calls glBindBuffer(\a target, \a buffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBindBuffer.xml}{glBindBuffer()}. +*/ + +/*! + \fn void QGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer) + + Convenience function that calls glBindFramebuffer(\a target, \a framebuffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBindFramebuffer.xml}{glBindFramebuffer()}. +*/ + +/*! + \fn void QGLFunctions::glBindRenderbuffer(GLenum target, GLuint renderbuffer) + + Convenience function that calls glBindRenderbuffer(\a target, \a renderbuffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBindRenderbuffer.xml}{glBindRenderbuffer()}. +*/ + +/*! + \fn void QGLFunctions::glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) + + Convenience function that calls glBlendColor(\a red, \a green, \a blue, \a alpha). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendColor.xml}{glBlendColor()}. +*/ + +/*! + \fn void QGLFunctions::glBlendEquation(GLenum mode) + + Convenience function that calls glBlendEquation(\a mode). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendEquation.xml}{glBlendEquation()}. +*/ + +/*! + \fn void QGLFunctions::glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) + + Convenience function that calls glBlendEquationSeparate(\a modeRGB, \a modeAlpha). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendEquationSeparate.xml}{glBlendEquationSeparate()}. +*/ + +/*! + \fn void QGLFunctions::glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) + + Convenience function that calls glBlendFuncSeparate(\a srcRGB, \a dstRGB, \a srcAlpha, \a dstAlpha). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendFuncSeparate.xml}{glBlendFuncSeparate()}. +*/ + +/*! + \fn void QGLFunctions::glBufferData(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage) + + Convenience function that calls glBufferData(\a target, \a size, \a data, \a usage). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBufferData.xml}{glBufferData()}. +*/ + +/*! + \fn void QGLFunctions::glBufferSubData(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data) + + Convenience function that calls glBufferSubData(\a target, \a offset, \a size, \a data). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBufferSubData.xml}{glBufferSubData()}. +*/ + +/*! + \fn GLenum QGLFunctions::glCheckFramebufferStatus(GLenum target) + + Convenience function that calls glCheckFramebufferStatus(\a target). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCheckFramebufferStatus.xml}{glCheckFramebufferStatus()}. +*/ + +/*! + \fn void QGLFunctions::glClearDepthf(GLclampf depth) + + Convenience function that calls glClearDepth(\a depth) on + desktop OpenGL systems and glClearDepthf(\a depth) on + embedded OpenGL/ES systems. + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glClearDepthf.xml}{glClearDepthf()}. +*/ + +/*! + \fn void QGLFunctions::glCompileShader(GLuint shader) + + Convenience function that calls glCompileShader(\a shader). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCompileShader.xml}{glCompileShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) + + Convenience function that calls glCompressedTexImage2D(\a target, \a level, \a internalformat, \a width, \a height, \a border, \a imageSize, \a data). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCompressedTexImage2D.xml}{glCompressedTexImage2D()}. +*/ + +/*! + \fn void QGLFunctions::glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) + + Convenience function that calls glCompressedTexSubImage2D(\a target, \a level, \a xoffset, \a yoffset, \a width, \a height, \a format, \a imageSize, \a data). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCompressedTexSubImage2D.xml}{glCompressedTexSubImage2D()}. +*/ + +/*! + \fn GLuint QGLFunctions::glCreateProgram() + + Convenience function that calls glCreateProgram(). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCreateProgram.xml}{glCreateProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn GLuint QGLFunctions::glCreateShader(GLenum type) + + Convenience function that calls glCreateShader(\a type). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCreateShader.xml}{glCreateShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glDeleteBuffers(GLsizei n, const GLuint* buffers) + + Convenience function that calls glDeleteBuffers(\a n, \a buffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteBuffers.xml}{glDeleteBuffers()}. +*/ + +/*! + \fn void QGLFunctions::glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) + + Convenience function that calls glDeleteFramebuffers(\a n, \a framebuffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteFramebuffers.xml}{glDeleteFramebuffers()}. +*/ + +/*! + \fn void QGLFunctions::glDeleteProgram(GLuint program) + + Convenience function that calls glDeleteProgram(\a program). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteProgram.xml}{glDeleteProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) + + Convenience function that calls glDeleteRenderbuffers(\a n, \a renderbuffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteRenderbuffers.xml}{glDeleteRenderbuffers()}. +*/ + +/*! + \fn void QGLFunctions::glDeleteShader(GLuint shader) + + Convenience function that calls glDeleteShader(\a shader). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteShader.xml}{glDeleteShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glDepthRangef(GLclampf zNear, GLclampf zFar) + + Convenience function that calls glDepthRange(\a zNear, \a zFar) on + desktop OpenGL systems and glDepthRangef(\a zNear, \a zFar) on + embedded OpenGL/ES systems. + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDepthRangef.xml}{glDepthRangef()}. +*/ + +/*! + \fn void QGLFunctions::glDetachShader(GLuint program, GLuint shader) + + Convenience function that calls glDetachShader(\a program, \a shader). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDetachShader.xml}{glDetachShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glDisableVertexAttribArray(GLuint index) + + Convenience function that calls glDisableVertexAttribArray(\a index). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDisableVertexAttribArray.xml}{glDisableVertexAttribArray()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glEnableVertexAttribArray(GLuint index) + + Convenience function that calls glEnableVertexAttribArray(\a index). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glEnableVertexAttribArray.xml}{glEnableVertexAttribArray()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) + + Convenience function that calls glFramebufferRenderbuffer(\a target, \a attachment, \a renderbuffertarget, \a renderbuffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glFramebufferRenderbuffer.xml}{glFramebufferRenderbuffer()}. +*/ + +/*! + \fn void QGLFunctions::glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) + + Convenience function that calls glFramebufferTexture2D(\a target, \a attachment, \a textarget, \a texture, \a level). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glFramebufferTexture2D.xml}{glFramebufferTexture2D()}. +*/ + +/*! + \fn void QGLFunctions::glGenBuffers(GLsizei n, GLuint* buffers) + + Convenience function that calls glGenBuffers(\a n, \a buffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGenBuffers.xml}{glGenBuffers()}. +*/ + +/*! + \fn void QGLFunctions::glGenerateMipmap(GLenum target) + + Convenience function that calls glGenerateMipmap(\a target). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGenerateMipmap.xml}{glGenerateMipmap()}. +*/ + +/*! + \fn void QGLFunctions::glGenFramebuffers(GLsizei n, GLuint* framebuffers) + + Convenience function that calls glGenFramebuffers(\a n, \a framebuffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGenFramebuffers.xml}{glGenFramebuffers()}. +*/ + +/*! + \fn void QGLFunctions::glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) + + Convenience function that calls glGenRenderbuffers(\a n, \a renderbuffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGenRenderbuffers.xml}{glGenRenderbuffers()}. +*/ + +/*! + \fn void QGLFunctions::glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) + + Convenience function that calls glGetActiveAttrib(\a program, \a index, \a bufsize, \a length, \a size, \a type, \a name). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetActiveAttrib.xml}{glGetActiveAttrib()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) + + Convenience function that calls glGetActiveUniform(\a program, \a index, \a bufsize, \a length, \a size, \a type, \a name). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetActiveUniform.xml}{glGetActiveUniform()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) + + Convenience function that calls glGetAttachedShaders(\a program, \a maxcount, \a count, \a shaders). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetAttachedShaders.xml}{glGetAttachedShaders()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn int QGLFunctions::glGetAttribLocation(GLuint program, const char* name) + + Convenience function that calls glGetAttribLocation(\a program, \a name). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetAttribLocation.xml}{glGetAttribLocation()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) + + Convenience function that calls glGetBufferParameteriv(\a target, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetBufferParameteriv.xml}{glGetBufferParameteriv()}. +*/ + +/*! + \fn void QGLFunctions::glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) + + Convenience function that calls glGetFramebufferAttachmentParameteriv(\a target, \a attachment, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetFramebufferAttachmentParameteriv.xml}{glGetFramebufferAttachmentParameteriv()}. +*/ + +/*! + \fn void QGLFunctions::glGetProgramiv(GLuint program, GLenum pname, GLint* params) + + Convenience function that calls glGetProgramiv(\a program, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetProgramiv.xml}{glGetProgramiv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) + + Convenience function that calls glGetProgramInfoLog(\a program, \a bufsize, \a length, \a infolog). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetProgramInfoLog.xml}{glGetProgramInfoLog()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) + + Convenience function that calls glGetRenderbufferParameteriv(\a target, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetRenderbufferParameteriv.xml}{glGetRenderbufferParameteriv()}. +*/ + +/*! + \fn void QGLFunctions::glGetShaderiv(GLuint shader, GLenum pname, GLint* params) + + Convenience function that calls glGetShaderiv(\a shader, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderiv.xml}{glGetShaderiv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) + + Convenience function that calls glGetShaderInfoLog(\a shader, \a bufsize, \a length, \a infolog). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderInfoLog.xml}{glGetShaderInfoLog()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) + + Convenience function that calls glGetShaderPrecisionFormat(\a shadertype, \a precisiontype, \a range, \a precision). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderPrecisionFormat.xml}{glGetShaderPrecisionFormat()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source) + + Convenience function that calls glGetShaderSource(\a shader, \a bufsize, \a length, \a source). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderSource.xml}{glGetShaderSource()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetUniformfv(GLuint program, GLint location, GLfloat* params) + + Convenience function that calls glGetUniformfv(\a program, \a location, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformfv.xml}{glGetUniformfv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetUniformiv(GLuint program, GLint location, GLint* params) + + Convenience function that calls glGetUniformiv(\a program, \a location, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformiv.xml}{glGetUniformiv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn int QGLFunctions::glGetUniformLocation(GLuint program, const char* name) + + Convenience function that calls glGetUniformLocation(\a program, \a name). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformLocation.xml}{glGetUniformLocation()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) + + Convenience function that calls glGetVertexAttribfv(\a index, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribfv.xml}{glGetVertexAttribfv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) + + Convenience function that calls glGetVertexAttribiv(\a index, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribiv.xml}{glGetVertexAttribiv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) + + Convenience function that calls glGetVertexAttribPointerv(\a index, \a pname, \a pointer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribPointerv.xml}{glGetVertexAttribPointerv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn GLboolean QGLFunctions::glIsBuffer(GLuint buffer) + + Convenience function that calls glIsBuffer(\a buffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glIsBuffer.xml}{glIsBuffer()}. +*/ + +/*! + \fn GLboolean QGLFunctions::glIsFramebuffer(GLuint framebuffer) + + Convenience function that calls glIsFramebuffer(\a framebuffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glIsFramebuffer.xml}{glIsFramebuffer()}. +*/ + +/*! + \fn GLboolean QGLFunctions::glIsProgram(GLuint program) + + Convenience function that calls glIsProgram(\a program). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glIsProgram.xml}{glIsProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn GLboolean QGLFunctions::glIsRenderbuffer(GLuint renderbuffer) + + Convenience function that calls glIsRenderbuffer(\a renderbuffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glIsRenderbuffer.xml}{glIsRenderbuffer()}. +*/ + +/*! + \fn GLboolean QGLFunctions::glIsShader(GLuint shader) + + Convenience function that calls glIsShader(\a shader). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glIsShader.xml}{glIsShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glLinkProgram(GLuint program) + + Convenience function that calls glLinkProgram(\a program). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glLinkProgram.xml}{glLinkProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glReleaseShaderCompiler() + + Convenience function that calls glReleaseShaderCompiler(). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glReleaseShaderCompiler.xml}{glReleaseShaderCompiler()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) + + Convenience function that calls glRenderbufferStorage(\a target, \a internalformat, \a width, \a height). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glRenderbufferStorage.xml}{glRenderbufferStorage()}. +*/ + +/*! + \fn void QGLFunctions::glSampleCoverage(GLclampf value, GLboolean invert) + + Convenience function that calls glSampleCoverage(\a value, \a invert). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glSampleCoverage.xml}{glSampleCoverage()}. +*/ + +/*! + \fn void QGLFunctions::glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length) + + Convenience function that calls glShaderBinary(\a n, \a shaders, \a binaryformat, \a binary, \a length). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glShaderBinary.xml}{glShaderBinary()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length) + + Convenience function that calls glShaderSource(\a shader, \a count, \a string, \a length). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glShaderSource.xml}{glShaderSource()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) + + Convenience function that calls glStencilFuncSeparate(\a face, \a func, \a ref, \a mask). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilFuncSeparate.xml}{glStencilFuncSeparate()}. +*/ + +/*! + \fn void QGLFunctions::glStencilMaskSeparate(GLenum face, GLuint mask) + + Convenience function that calls glStencilMaskSeparate(\a face, \a mask). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilMaskSeparate.xml}{glStencilMaskSeparate()}. +*/ + +/*! + \fn void QGLFunctions::glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) + + Convenience function that calls glStencilOpSeparate(\a face, \a fail, \a zfail, \a zpass). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilOpSeparate.xml}{glStencilOpSeparate()}. +*/ + +/*! + \fn void QGLFunctions::glUniform1f(GLint location, GLfloat x) + + Convenience function that calls glUniform1f(\a location, \a x). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1f.xml}{glUniform1f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform1fv(GLint location, GLsizei count, const GLfloat* v) + + Convenience function that calls glUniform1fv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1fv.xml}{glUniform1fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform1i(GLint location, GLint x) + + Convenience function that calls glUniform1i(\a location, \a x). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1i.xml}{glUniform1i()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform1iv(GLint location, GLsizei count, const GLint* v) + + Convenience function that calls glUniform1iv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1iv.xml}{glUniform1iv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform2f(GLint location, GLfloat x, GLfloat y) + + Convenience function that calls glUniform2f(\a location, \a x, \a y). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2f.xml}{glUniform2f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform2fv(GLint location, GLsizei count, const GLfloat* v) + + Convenience function that calls glUniform2fv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2fv.xml}{glUniform2fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform2i(GLint location, GLint x, GLint y) + + Convenience function that calls glUniform2i(\a location, \a x, \a y). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2i.xml}{glUniform2i()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform2iv(GLint location, GLsizei count, const GLint* v) + + Convenience function that calls glUniform2iv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2iv.xml}{glUniform2iv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) + + Convenience function that calls glUniform3f(\a location, \a x, \a y, \a z). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3f.xml}{glUniform3f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform3fv(GLint location, GLsizei count, const GLfloat* v) + + Convenience function that calls glUniform3fv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3fv.xml}{glUniform3fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform3i(GLint location, GLint x, GLint y, GLint z) + + Convenience function that calls glUniform3i(\a location, \a x, \a y, \a z). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3i.xml}{glUniform3i()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform3iv(GLint location, GLsizei count, const GLint* v) + + Convenience function that calls glUniform3iv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3iv.xml}{glUniform3iv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) + + Convenience function that calls glUniform4f(\a location, \a x, \a y, \a z, \a w). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4f.xml}{glUniform4f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform4fv(GLint location, GLsizei count, const GLfloat* v) + + Convenience function that calls glUniform4fv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4fv.xml}{glUniform4fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) + + Convenience function that calls glUniform4i(\a location, \a x, \a y, \a z, \a w). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4i.xml}{glUniform4i()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform4iv(GLint location, GLsizei count, const GLint* v) + + Convenience function that calls glUniform4iv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4iv.xml}{glUniform4iv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + + Convenience function that calls glUniformMatrix2fv(\a location, \a count, \a transpose, \a value). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix2fv.xml}{glUniformMatrix2fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + + Convenience function that calls glUniformMatrix3fv(\a location, \a count, \a transpose, \a value). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix3fv.xml}{glUniformMatrix3fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + + Convenience function that calls glUniformMatrix4fv(\a location, \a count, \a transpose, \a value). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix4fv.xml}{glUniformMatrix4fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUseProgram(GLuint program) + + Convenience function that calls glUseProgram(\a program). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUseProgram.xml}{glUseProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glValidateProgram(GLuint program) + + Convenience function that calls glValidateProgram(\a program). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glValidateProgram.xml}{glValidateProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib1f(GLuint indx, GLfloat x) + + Convenience function that calls glVertexAttrib1f(\a indx, \a x). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib1f.xml}{glVertexAttrib1f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib1fv(GLuint indx, const GLfloat* values) + + Convenience function that calls glVertexAttrib1fv(\a indx, \a values). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib1fv.xml}{glVertexAttrib1fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) + + Convenience function that calls glVertexAttrib2f(\a indx, \a x, \a y). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib2f.xml}{glVertexAttrib2f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib2fv(GLuint indx, const GLfloat* values) + + Convenience function that calls glVertexAttrib2fv(\a indx, \a values). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib2fv.xml}{glVertexAttrib2fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) + + Convenience function that calls glVertexAttrib3f(\a indx, \a x, \a y, \a z). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib3f.xml}{glVertexAttrib3f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib3fv(GLuint indx, const GLfloat* values) + + Convenience function that calls glVertexAttrib3fv(\a indx, \a values). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib3fv.xml}{glVertexAttrib3fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) + + Convenience function that calls glVertexAttrib4f(\a indx, \a x, \a y, \a z, \a w). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib4f.xml}{glVertexAttrib4f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib4fv(GLuint indx, const GLfloat* values) + + Convenience function that calls glVertexAttrib4fv(\a indx, \a values). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib4fv.xml}{glVertexAttrib4fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) + + Convenience function that calls glVertexAttribPointer(\a indx, \a size, \a type, \a normalized, \a stride, \a ptr). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttribPointer.xml}{glVertexAttribPointer()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +#ifndef QT_OPENGL_ES_2 + +static void qglfResolveActiveTexture(GLenum texture) +{ + typedef void (QGLF_APIENTRYP type_glActiveTexture)(GLenum texture); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->activeTexture = (type_glActiveTexture) + context->getProcAddress(QLatin1String("glActiveTexture")); + if (!funcs->activeTexture) { + funcs->activeTexture = (type_glActiveTexture) + context->getProcAddress(QLatin1String("glActiveTextureARB")); + } + + if (funcs->activeTexture) + funcs->activeTexture(texture); + else + funcs->activeTexture = qglfResolveActiveTexture; +} + +static void qglfResolveAttachShader(GLuint program, GLuint shader) +{ + typedef void (QGLF_APIENTRYP type_glAttachShader)(GLuint program, GLuint shader); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->attachShader = (type_glAttachShader) + context->getProcAddress(QLatin1String("glAttachShader")); + if (!funcs->attachShader) { + funcs->attachShader = (type_glAttachShader) + context->getProcAddress(QLatin1String("glAttachObjectARB")); + } + + if (funcs->attachShader) + funcs->attachShader(program, shader); + else + funcs->attachShader = qglfResolveAttachShader; +} + +static void qglfResolveBindAttribLocation(GLuint program, GLuint index, const char* name) +{ + typedef void (QGLF_APIENTRYP type_glBindAttribLocation)(GLuint program, GLuint index, const char* name); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bindAttribLocation = (type_glBindAttribLocation) + context->getProcAddress(QLatin1String("glBindAttribLocation")); + if (!funcs->bindAttribLocation) { + funcs->bindAttribLocation = (type_glBindAttribLocation) + context->getProcAddress(QLatin1String("glBindAttribLocationARB")); + } + + if (funcs->bindAttribLocation) + funcs->bindAttribLocation(program, index, name); + else + funcs->bindAttribLocation = qglfResolveBindAttribLocation; +} + +static void qglfResolveBindBuffer(GLenum target, GLuint buffer) +{ + typedef void (QGLF_APIENTRYP type_glBindBuffer)(GLenum target, GLuint buffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bindBuffer = (type_glBindBuffer) + context->getProcAddress(QLatin1String("glBindBuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->bindBuffer) { + funcs->bindBuffer = (type_glBindBuffer) + context->getProcAddress(QLatin1String("glBindBufferOES")); + } +#endif + if (!funcs->bindBuffer) { + funcs->bindBuffer = (type_glBindBuffer) + context->getProcAddress(QLatin1String("glBindBufferEXT")); + } + if (!funcs->bindBuffer) { + funcs->bindBuffer = (type_glBindBuffer) + context->getProcAddress(QLatin1String("glBindBufferARB")); + } + + if (funcs->bindBuffer) + funcs->bindBuffer(target, buffer); + else + funcs->bindBuffer = qglfResolveBindBuffer; +} + +static void qglfResolveBindFramebuffer(GLenum target, GLuint framebuffer) +{ + typedef void (QGLF_APIENTRYP type_glBindFramebuffer)(GLenum target, GLuint framebuffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bindFramebuffer = (type_glBindFramebuffer) + context->getProcAddress(QLatin1String("glBindFramebuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->bindFramebuffer) { + funcs->bindFramebuffer = (type_glBindFramebuffer) + context->getProcAddress(QLatin1String("glBindFramebufferOES")); + } +#endif + if (!funcs->bindFramebuffer) { + funcs->bindFramebuffer = (type_glBindFramebuffer) + context->getProcAddress(QLatin1String("glBindFramebufferEXT")); + } + if (!funcs->bindFramebuffer) { + funcs->bindFramebuffer = (type_glBindFramebuffer) + context->getProcAddress(QLatin1String("glBindFramebufferARB")); + } + + if (funcs->bindFramebuffer) + funcs->bindFramebuffer(target, framebuffer); + else + funcs->bindFramebuffer = qglfResolveBindFramebuffer; +} + +static void qglfResolveBindRenderbuffer(GLenum target, GLuint renderbuffer) +{ + typedef void (QGLF_APIENTRYP type_glBindRenderbuffer)(GLenum target, GLuint renderbuffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bindRenderbuffer = (type_glBindRenderbuffer) + context->getProcAddress(QLatin1String("glBindRenderbuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->bindRenderbuffer) { + funcs->bindRenderbuffer = (type_glBindRenderbuffer) + context->getProcAddress(QLatin1String("glBindRenderbufferOES")); + } +#endif + if (!funcs->bindRenderbuffer) { + funcs->bindRenderbuffer = (type_glBindRenderbuffer) + context->getProcAddress(QLatin1String("glBindRenderbufferEXT")); + } + if (!funcs->bindRenderbuffer) { + funcs->bindRenderbuffer = (type_glBindRenderbuffer) + context->getProcAddress(QLatin1String("glBindRenderbufferARB")); + } + + if (funcs->bindRenderbuffer) + funcs->bindRenderbuffer(target, renderbuffer); + else + funcs->bindRenderbuffer = qglfResolveBindRenderbuffer; +} + +static void qglfResolveBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + typedef void (QGLF_APIENTRYP type_glBlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->blendColor = (type_glBlendColor) + context->getProcAddress(QLatin1String("glBlendColor")); +#ifdef QT_OPENGL_ES + if (!funcs->blendColor) { + funcs->blendColor = (type_glBlendColor) + context->getProcAddress(QLatin1String("glBlendColorOES")); + } +#endif + if (!funcs->blendColor) { + funcs->blendColor = (type_glBlendColor) + context->getProcAddress(QLatin1String("glBlendColorEXT")); + } + if (!funcs->blendColor) { + funcs->blendColor = (type_glBlendColor) + context->getProcAddress(QLatin1String("glBlendColorARB")); + } + + if (funcs->blendColor) + funcs->blendColor(red, green, blue, alpha); + else + funcs->blendColor = qglfResolveBlendColor; +} + +static void qglfResolveBlendEquation(GLenum mode) +{ + typedef void (QGLF_APIENTRYP type_glBlendEquation)(GLenum mode); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->blendEquation = (type_glBlendEquation) + context->getProcAddress(QLatin1String("glBlendEquation")); +#ifdef QT_OPENGL_ES + if (!funcs->blendEquation) { + funcs->blendEquation = (type_glBlendEquation) + context->getProcAddress(QLatin1String("glBlendEquationOES")); + } +#endif + if (!funcs->blendEquation) { + funcs->blendEquation = (type_glBlendEquation) + context->getProcAddress(QLatin1String("glBlendEquationEXT")); + } + if (!funcs->blendEquation) { + funcs->blendEquation = (type_glBlendEquation) + context->getProcAddress(QLatin1String("glBlendEquationARB")); + } + + if (funcs->blendEquation) + funcs->blendEquation(mode); + else + funcs->blendEquation = qglfResolveBlendEquation; +} + +static void qglfResolveBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +{ + typedef void (QGLF_APIENTRYP type_glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->blendEquationSeparate = (type_glBlendEquationSeparate) + context->getProcAddress(QLatin1String("glBlendEquationSeparate")); +#ifdef QT_OPENGL_ES + if (!funcs->blendEquationSeparate) { + funcs->blendEquationSeparate = (type_glBlendEquationSeparate) + context->getProcAddress(QLatin1String("glBlendEquationSeparateOES")); + } +#endif + if (!funcs->blendEquationSeparate) { + funcs->blendEquationSeparate = (type_glBlendEquationSeparate) + context->getProcAddress(QLatin1String("glBlendEquationSeparateEXT")); + } + if (!funcs->blendEquationSeparate) { + funcs->blendEquationSeparate = (type_glBlendEquationSeparate) + context->getProcAddress(QLatin1String("glBlendEquationSeparateARB")); + } + + if (funcs->blendEquationSeparate) + funcs->blendEquationSeparate(modeRGB, modeAlpha); + else + funcs->blendEquationSeparate = qglfResolveBlendEquationSeparate; +} + +static void qglfResolveBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +{ + typedef void (QGLF_APIENTRYP type_glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->blendFuncSeparate = (type_glBlendFuncSeparate) + context->getProcAddress(QLatin1String("glBlendFuncSeparate")); +#ifdef QT_OPENGL_ES + if (!funcs->blendFuncSeparate) { + funcs->blendFuncSeparate = (type_glBlendFuncSeparate) + context->getProcAddress(QLatin1String("glBlendFuncSeparateOES")); + } +#endif + if (!funcs->blendFuncSeparate) { + funcs->blendFuncSeparate = (type_glBlendFuncSeparate) + context->getProcAddress(QLatin1String("glBlendFuncSeparateEXT")); + } + if (!funcs->blendFuncSeparate) { + funcs->blendFuncSeparate = (type_glBlendFuncSeparate) + context->getProcAddress(QLatin1String("glBlendFuncSeparateARB")); + } + + if (funcs->blendFuncSeparate) + funcs->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); + else + funcs->blendFuncSeparate = qglfResolveBlendFuncSeparate; +} + +static void qglfResolveBufferData(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage) +{ + typedef void (QGLF_APIENTRYP type_glBufferData)(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bufferData = (type_glBufferData) + context->getProcAddress(QLatin1String("glBufferData")); +#ifdef QT_OPENGL_ES + if (!funcs->bufferData) { + funcs->bufferData = (type_glBufferData) + context->getProcAddress(QLatin1String("glBufferDataOES")); + } +#endif + if (!funcs->bufferData) { + funcs->bufferData = (type_glBufferData) + context->getProcAddress(QLatin1String("glBufferDataEXT")); + } + if (!funcs->bufferData) { + funcs->bufferData = (type_glBufferData) + context->getProcAddress(QLatin1String("glBufferDataARB")); + } + + if (funcs->bufferData) + funcs->bufferData(target, size, data, usage); + else + funcs->bufferData = qglfResolveBufferData; +} + +static void qglfResolveBufferSubData(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data) +{ + typedef void (QGLF_APIENTRYP type_glBufferSubData)(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bufferSubData = (type_glBufferSubData) + context->getProcAddress(QLatin1String("glBufferSubData")); +#ifdef QT_OPENGL_ES + if (!funcs->bufferSubData) { + funcs->bufferSubData = (type_glBufferSubData) + context->getProcAddress(QLatin1String("glBufferSubDataOES")); + } +#endif + if (!funcs->bufferSubData) { + funcs->bufferSubData = (type_glBufferSubData) + context->getProcAddress(QLatin1String("glBufferSubDataEXT")); + } + if (!funcs->bufferSubData) { + funcs->bufferSubData = (type_glBufferSubData) + context->getProcAddress(QLatin1String("glBufferSubDataARB")); + } + + if (funcs->bufferSubData) + funcs->bufferSubData(target, offset, size, data); + else + funcs->bufferSubData = qglfResolveBufferSubData; +} + +static GLenum qglfResolveCheckFramebufferStatus(GLenum target) +{ + typedef GLenum (QGLF_APIENTRYP type_glCheckFramebufferStatus)(GLenum target); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->checkFramebufferStatus = (type_glCheckFramebufferStatus) + context->getProcAddress(QLatin1String("glCheckFramebufferStatus")); +#ifdef QT_OPENGL_ES + if (!funcs->checkFramebufferStatus) { + funcs->checkFramebufferStatus = (type_glCheckFramebufferStatus) + context->getProcAddress(QLatin1String("glCheckFramebufferStatusOES")); + } +#endif + if (!funcs->checkFramebufferStatus) { + funcs->checkFramebufferStatus = (type_glCheckFramebufferStatus) + context->getProcAddress(QLatin1String("glCheckFramebufferStatusEXT")); + } + if (!funcs->checkFramebufferStatus) { + funcs->checkFramebufferStatus = (type_glCheckFramebufferStatus) + context->getProcAddress(QLatin1String("glCheckFramebufferStatusARB")); + } + + if (funcs->checkFramebufferStatus) + return funcs->checkFramebufferStatus(target); + funcs->checkFramebufferStatus = qglfResolveCheckFramebufferStatus; + return GLenum(0); +} + +static void qglfResolveCompileShader(GLuint shader) +{ + typedef void (QGLF_APIENTRYP type_glCompileShader)(GLuint shader); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->compileShader = (type_glCompileShader) + context->getProcAddress(QLatin1String("glCompileShader")); + if (!funcs->compileShader) { + funcs->compileShader = (type_glCompileShader) + context->getProcAddress(QLatin1String("glCompileShader")); + } + + if (funcs->compileShader) + funcs->compileShader(shader); + else + funcs->compileShader = qglfResolveCompileShader; +} + +static void qglfResolveCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) +{ + typedef void (QGLF_APIENTRYP type_glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->compressedTexImage2D = (type_glCompressedTexImage2D) + context->getProcAddress(QLatin1String("glCompressedTexImage2D")); +#ifdef QT_OPENGL_ES + if (!funcs->compressedTexImage2D) { + funcs->compressedTexImage2D = (type_glCompressedTexImage2D) + context->getProcAddress(QLatin1String("glCompressedTexImage2DOES")); + } +#endif + if (!funcs->compressedTexImage2D) { + funcs->compressedTexImage2D = (type_glCompressedTexImage2D) + context->getProcAddress(QLatin1String("glCompressedTexImage2DEXT")); + } + if (!funcs->compressedTexImage2D) { + funcs->compressedTexImage2D = (type_glCompressedTexImage2D) + context->getProcAddress(QLatin1String("glCompressedTexImage2DARB")); + } + + if (funcs->compressedTexImage2D) + funcs->compressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); + else + funcs->compressedTexImage2D = qglfResolveCompressedTexImage2D; +} + +static void qglfResolveCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) +{ + typedef void (QGLF_APIENTRYP type_glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->compressedTexSubImage2D = (type_glCompressedTexSubImage2D) + context->getProcAddress(QLatin1String("glCompressedTexSubImage2D")); +#ifdef QT_OPENGL_ES + if (!funcs->compressedTexSubImage2D) { + funcs->compressedTexSubImage2D = (type_glCompressedTexSubImage2D) + context->getProcAddress(QLatin1String("glCompressedTexSubImage2DOES")); + } +#endif + if (!funcs->compressedTexSubImage2D) { + funcs->compressedTexSubImage2D = (type_glCompressedTexSubImage2D) + context->getProcAddress(QLatin1String("glCompressedTexSubImage2DEXT")); + } + if (!funcs->compressedTexSubImage2D) { + funcs->compressedTexSubImage2D = (type_glCompressedTexSubImage2D) + context->getProcAddress(QLatin1String("glCompressedTexSubImage2DARB")); + } + + if (funcs->compressedTexSubImage2D) + funcs->compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); + else + funcs->compressedTexSubImage2D = qglfResolveCompressedTexSubImage2D; +} + +static GLuint qglfResolveCreateProgram() +{ + typedef GLuint (QGLF_APIENTRYP type_glCreateProgram)(); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->createProgram = (type_glCreateProgram) + context->getProcAddress(QLatin1String("glCreateProgram")); + if (!funcs->createProgram) { + funcs->createProgram = (type_glCreateProgram) + context->getProcAddress(QLatin1String("glCreateProgramObjectARB")); + } + + if (funcs->createProgram) + return funcs->createProgram(); + funcs->createProgram = qglfResolveCreateProgram; + return GLuint(0); +} + +static GLuint qglfResolveCreateShader(GLenum type) +{ + typedef GLuint (QGLF_APIENTRYP type_glCreateShader)(GLenum type); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->createShader = (type_glCreateShader) + context->getProcAddress(QLatin1String("glCreateShader")); + if (!funcs->createShader) { + funcs->createShader = (type_glCreateShader) + context->getProcAddress(QLatin1String("glCreateShaderObjectARB")); + } + + if (funcs->createShader) + return funcs->createShader(type); + funcs->createShader = qglfResolveCreateShader; + return GLuint(0); +} + +static void qglfResolveDeleteBuffers(GLsizei n, const GLuint* buffers) +{ + typedef void (QGLF_APIENTRYP type_glDeleteBuffers)(GLsizei n, const GLuint* buffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->deleteBuffers = (type_glDeleteBuffers) + context->getProcAddress(QLatin1String("glDeleteBuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->deleteBuffers) { + funcs->deleteBuffers = (type_glDeleteBuffers) + context->getProcAddress(QLatin1String("glDeleteBuffersOES")); + } +#endif + if (!funcs->deleteBuffers) { + funcs->deleteBuffers = (type_glDeleteBuffers) + context->getProcAddress(QLatin1String("glDeleteBuffersEXT")); + } + if (!funcs->deleteBuffers) { + funcs->deleteBuffers = (type_glDeleteBuffers) + context->getProcAddress(QLatin1String("glDeleteBuffersARB")); + } + + if (funcs->deleteBuffers) + funcs->deleteBuffers(n, buffers); + else + funcs->deleteBuffers = qglfResolveDeleteBuffers; +} + +static void qglfResolveDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) +{ + typedef void (QGLF_APIENTRYP type_glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->deleteFramebuffers = (type_glDeleteFramebuffers) + context->getProcAddress(QLatin1String("glDeleteFramebuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->deleteFramebuffers) { + funcs->deleteFramebuffers = (type_glDeleteFramebuffers) + context->getProcAddress(QLatin1String("glDeleteFramebuffersOES")); + } +#endif + if (!funcs->deleteFramebuffers) { + funcs->deleteFramebuffers = (type_glDeleteFramebuffers) + context->getProcAddress(QLatin1String("glDeleteFramebuffersEXT")); + } + if (!funcs->deleteFramebuffers) { + funcs->deleteFramebuffers = (type_glDeleteFramebuffers) + context->getProcAddress(QLatin1String("glDeleteFramebuffersARB")); + } + + if (funcs->deleteFramebuffers) + funcs->deleteFramebuffers(n, framebuffers); + else + funcs->deleteFramebuffers = qglfResolveDeleteFramebuffers; +} + +static void qglfResolveDeleteProgram(GLuint program) +{ + typedef void (QGLF_APIENTRYP type_glDeleteProgram)(GLuint program); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->deleteProgram = (type_glDeleteProgram) + context->getProcAddress(QLatin1String("glDeleteProgram")); + if (!funcs->deleteProgram) { + funcs->deleteProgram = (type_glDeleteProgram) + context->getProcAddress(QLatin1String("glDeleteObjectARB")); + } + + if (funcs->deleteProgram) + funcs->deleteProgram(program); + else + funcs->deleteProgram = qglfResolveDeleteProgram; +} + +static void qglfResolveDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) +{ + typedef void (QGLF_APIENTRYP type_glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->deleteRenderbuffers = (type_glDeleteRenderbuffers) + context->getProcAddress(QLatin1String("glDeleteRenderbuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->deleteRenderbuffers) { + funcs->deleteRenderbuffers = (type_glDeleteRenderbuffers) + context->getProcAddress(QLatin1String("glDeleteRenderbuffersOES")); + } +#endif + if (!funcs->deleteRenderbuffers) { + funcs->deleteRenderbuffers = (type_glDeleteRenderbuffers) + context->getProcAddress(QLatin1String("glDeleteRenderbuffersEXT")); + } + if (!funcs->deleteRenderbuffers) { + funcs->deleteRenderbuffers = (type_glDeleteRenderbuffers) + context->getProcAddress(QLatin1String("glDeleteRenderbuffersARB")); + } + + if (funcs->deleteRenderbuffers) + funcs->deleteRenderbuffers(n, renderbuffers); + else + funcs->deleteRenderbuffers = qglfResolveDeleteRenderbuffers; +} + +static void qglfResolveDeleteShader(GLuint shader) +{ + typedef void (QGLF_APIENTRYP type_glDeleteShader)(GLuint shader); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->deleteShader = (type_glDeleteShader) + context->getProcAddress(QLatin1String("glDeleteShader")); + if (!funcs->deleteShader) { + funcs->deleteShader = (type_glDeleteShader) + context->getProcAddress(QLatin1String("glDeleteObjectARB")); + } + + if (funcs->deleteShader) + funcs->deleteShader(shader); + else + funcs->deleteShader = qglfResolveDeleteShader; +} + +static void qglfResolveDetachShader(GLuint program, GLuint shader) +{ + typedef void (QGLF_APIENTRYP type_glDetachShader)(GLuint program, GLuint shader); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->detachShader = (type_glDetachShader) + context->getProcAddress(QLatin1String("glDetachShader")); + if (!funcs->detachShader) { + funcs->detachShader = (type_glDetachShader) + context->getProcAddress(QLatin1String("glDetachObjectARB")); + } + + if (funcs->detachShader) + funcs->detachShader(program, shader); + else + funcs->detachShader = qglfResolveDetachShader; +} + +static void qglfResolveDisableVertexAttribArray(GLuint index) +{ + typedef void (QGLF_APIENTRYP type_glDisableVertexAttribArray)(GLuint index); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->disableVertexAttribArray = (type_glDisableVertexAttribArray) + context->getProcAddress(QLatin1String("glDisableVertexAttribArray")); + if (!funcs->disableVertexAttribArray) { + funcs->disableVertexAttribArray = (type_glDisableVertexAttribArray) + context->getProcAddress(QLatin1String("glDisableVertexAttribArrayARB")); + } + + if (funcs->disableVertexAttribArray) + funcs->disableVertexAttribArray(index); + else + funcs->disableVertexAttribArray = qglfResolveDisableVertexAttribArray; +} + +static void qglfResolveEnableVertexAttribArray(GLuint index) +{ + typedef void (QGLF_APIENTRYP type_glEnableVertexAttribArray)(GLuint index); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->enableVertexAttribArray = (type_glEnableVertexAttribArray) + context->getProcAddress(QLatin1String("glEnableVertexAttribArray")); + if (!funcs->enableVertexAttribArray) { + funcs->enableVertexAttribArray = (type_glEnableVertexAttribArray) + context->getProcAddress(QLatin1String("glEnableVertexAttribArrayARB")); + } + + if (funcs->enableVertexAttribArray) + funcs->enableVertexAttribArray(index); + else + funcs->enableVertexAttribArray = qglfResolveEnableVertexAttribArray; +} + +static void qglfResolveFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ + typedef void (QGLF_APIENTRYP type_glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->framebufferRenderbuffer = (type_glFramebufferRenderbuffer) + context->getProcAddress(QLatin1String("glFramebufferRenderbuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->framebufferRenderbuffer) { + funcs->framebufferRenderbuffer = (type_glFramebufferRenderbuffer) + context->getProcAddress(QLatin1String("glFramebufferRenderbufferOES")); + } +#endif + if (!funcs->framebufferRenderbuffer) { + funcs->framebufferRenderbuffer = (type_glFramebufferRenderbuffer) + context->getProcAddress(QLatin1String("glFramebufferRenderbufferEXT")); + } + if (!funcs->framebufferRenderbuffer) { + funcs->framebufferRenderbuffer = (type_glFramebufferRenderbuffer) + context->getProcAddress(QLatin1String("glFramebufferRenderbufferARB")); + } + + if (funcs->framebufferRenderbuffer) + funcs->framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); + else + funcs->framebufferRenderbuffer = qglfResolveFramebufferRenderbuffer; +} + +static void qglfResolveFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + typedef void (QGLF_APIENTRYP type_glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->framebufferTexture2D = (type_glFramebufferTexture2D) + context->getProcAddress(QLatin1String("glFramebufferTexture2D")); +#ifdef QT_OPENGL_ES + if (!funcs->framebufferTexture2D) { + funcs->framebufferTexture2D = (type_glFramebufferTexture2D) + context->getProcAddress(QLatin1String("glFramebufferTexture2DOES")); + } +#endif + if (!funcs->framebufferTexture2D) { + funcs->framebufferTexture2D = (type_glFramebufferTexture2D) + context->getProcAddress(QLatin1String("glFramebufferTexture2DEXT")); + } + if (!funcs->framebufferTexture2D) { + funcs->framebufferTexture2D = (type_glFramebufferTexture2D) + context->getProcAddress(QLatin1String("glFramebufferTexture2DARB")); + } + + if (funcs->framebufferTexture2D) + funcs->framebufferTexture2D(target, attachment, textarget, texture, level); + else + funcs->framebufferTexture2D = qglfResolveFramebufferTexture2D; +} + +static void qglfResolveGenBuffers(GLsizei n, GLuint* buffers) +{ + typedef void (QGLF_APIENTRYP type_glGenBuffers)(GLsizei n, GLuint* buffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->genBuffers = (type_glGenBuffers) + context->getProcAddress(QLatin1String("glGenBuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->genBuffers) { + funcs->genBuffers = (type_glGenBuffers) + context->getProcAddress(QLatin1String("glGenBuffersOES")); + } +#endif + if (!funcs->genBuffers) { + funcs->genBuffers = (type_glGenBuffers) + context->getProcAddress(QLatin1String("glGenBuffersEXT")); + } + if (!funcs->genBuffers) { + funcs->genBuffers = (type_glGenBuffers) + context->getProcAddress(QLatin1String("glGenBuffersARB")); + } + + if (funcs->genBuffers) + funcs->genBuffers(n, buffers); + else + funcs->genBuffers = qglfResolveGenBuffers; +} + +static void qglfResolveGenerateMipmap(GLenum target) +{ + typedef void (QGLF_APIENTRYP type_glGenerateMipmap)(GLenum target); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->generateMipmap = (type_glGenerateMipmap) + context->getProcAddress(QLatin1String("glGenerateMipmap")); +#ifdef QT_OPENGL_ES + if (!funcs->generateMipmap) { + funcs->generateMipmap = (type_glGenerateMipmap) + context->getProcAddress(QLatin1String("glGenerateMipmapOES")); + } +#endif + if (!funcs->generateMipmap) { + funcs->generateMipmap = (type_glGenerateMipmap) + context->getProcAddress(QLatin1String("glGenerateMipmapEXT")); + } + if (!funcs->generateMipmap) { + funcs->generateMipmap = (type_glGenerateMipmap) + context->getProcAddress(QLatin1String("glGenerateMipmapARB")); + } + + if (funcs->generateMipmap) + funcs->generateMipmap(target); + else + funcs->generateMipmap = qglfResolveGenerateMipmap; +} + +static void qglfResolveGenFramebuffers(GLsizei n, GLuint* framebuffers) +{ + typedef void (QGLF_APIENTRYP type_glGenFramebuffers)(GLsizei n, GLuint* framebuffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->genFramebuffers = (type_glGenFramebuffers) + context->getProcAddress(QLatin1String("glGenFramebuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->genFramebuffers) { + funcs->genFramebuffers = (type_glGenFramebuffers) + context->getProcAddress(QLatin1String("glGenFramebuffersOES")); + } +#endif + if (!funcs->genFramebuffers) { + funcs->genFramebuffers = (type_glGenFramebuffers) + context->getProcAddress(QLatin1String("glGenFramebuffersEXT")); + } + if (!funcs->genFramebuffers) { + funcs->genFramebuffers = (type_glGenFramebuffers) + context->getProcAddress(QLatin1String("glGenFramebuffersARB")); + } + + if (funcs->genFramebuffers) + funcs->genFramebuffers(n, framebuffers); + else + funcs->genFramebuffers = qglfResolveGenFramebuffers; +} + +static void qglfResolveGenRenderbuffers(GLsizei n, GLuint* renderbuffers) +{ + typedef void (QGLF_APIENTRYP type_glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->genRenderbuffers = (type_glGenRenderbuffers) + context->getProcAddress(QLatin1String("glGenRenderbuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->genRenderbuffers) { + funcs->genRenderbuffers = (type_glGenRenderbuffers) + context->getProcAddress(QLatin1String("glGenRenderbuffersOES")); + } +#endif + if (!funcs->genRenderbuffers) { + funcs->genRenderbuffers = (type_glGenRenderbuffers) + context->getProcAddress(QLatin1String("glGenRenderbuffersEXT")); + } + if (!funcs->genRenderbuffers) { + funcs->genRenderbuffers = (type_glGenRenderbuffers) + context->getProcAddress(QLatin1String("glGenRenderbuffersARB")); + } + + if (funcs->genRenderbuffers) + funcs->genRenderbuffers(n, renderbuffers); + else + funcs->genRenderbuffers = qglfResolveGenRenderbuffers; +} + +static void qglfResolveGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) +{ + typedef void (QGLF_APIENTRYP type_glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getActiveAttrib = (type_glGetActiveAttrib) + context->getProcAddress(QLatin1String("glGetActiveAttrib")); + if (!funcs->getActiveAttrib) { + funcs->getActiveAttrib = (type_glGetActiveAttrib) + context->getProcAddress(QLatin1String("glGetActiveAttribARB")); + } + + if (funcs->getActiveAttrib) + funcs->getActiveAttrib(program, index, bufsize, length, size, type, name); + else + funcs->getActiveAttrib = qglfResolveGetActiveAttrib; +} + +static void qglfResolveGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) +{ + typedef void (QGLF_APIENTRYP type_glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getActiveUniform = (type_glGetActiveUniform) + context->getProcAddress(QLatin1String("glGetActiveUniform")); + if (!funcs->getActiveUniform) { + funcs->getActiveUniform = (type_glGetActiveUniform) + context->getProcAddress(QLatin1String("glGetActiveUniformARB")); + } + + if (funcs->getActiveUniform) + funcs->getActiveUniform(program, index, bufsize, length, size, type, name); + else + funcs->getActiveUniform = qglfResolveGetActiveUniform; +} + +static void qglfResolveGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) +{ + typedef void (QGLF_APIENTRYP type_glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getAttachedShaders = (type_glGetAttachedShaders) + context->getProcAddress(QLatin1String("glGetAttachedShaders")); + if (!funcs->getAttachedShaders) { + funcs->getAttachedShaders = (type_glGetAttachedShaders) + context->getProcAddress(QLatin1String("glGetAttachedObjectsARB")); + } + + if (funcs->getAttachedShaders) + funcs->getAttachedShaders(program, maxcount, count, shaders); + else + funcs->getAttachedShaders = qglfResolveGetAttachedShaders; +} + +static int qglfResolveGetAttribLocation(GLuint program, const char* name) +{ + typedef int (QGLF_APIENTRYP type_glGetAttribLocation)(GLuint program, const char* name); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getAttribLocation = (type_glGetAttribLocation) + context->getProcAddress(QLatin1String("glGetAttribLocation")); + if (!funcs->getAttribLocation) { + funcs->getAttribLocation = (type_glGetAttribLocation) + context->getProcAddress(QLatin1String("glGetAttribLocationARB")); + } + + if (funcs->getAttribLocation) + return funcs->getAttribLocation(program, name); + funcs->getAttribLocation = qglfResolveGetAttribLocation; + return int(0); +} + +static void qglfResolveGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getBufferParameteriv = (type_glGetBufferParameteriv) + context->getProcAddress(QLatin1String("glGetBufferParameteriv")); +#ifdef QT_OPENGL_ES + if (!funcs->getBufferParameteriv) { + funcs->getBufferParameteriv = (type_glGetBufferParameteriv) + context->getProcAddress(QLatin1String("glGetBufferParameterivOES")); + } +#endif + if (!funcs->getBufferParameteriv) { + funcs->getBufferParameteriv = (type_glGetBufferParameteriv) + context->getProcAddress(QLatin1String("glGetBufferParameterivEXT")); + } + if (!funcs->getBufferParameteriv) { + funcs->getBufferParameteriv = (type_glGetBufferParameteriv) + context->getProcAddress(QLatin1String("glGetBufferParameterivARB")); + } + + if (funcs->getBufferParameteriv) + funcs->getBufferParameteriv(target, pname, params); + else + funcs->getBufferParameteriv = qglfResolveGetBufferParameteriv; +} + +static void qglfResolveGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getFramebufferAttachmentParameteriv = (type_glGetFramebufferAttachmentParameteriv) + context->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameteriv")); +#ifdef QT_OPENGL_ES + if (!funcs->getFramebufferAttachmentParameteriv) { + funcs->getFramebufferAttachmentParameteriv = (type_glGetFramebufferAttachmentParameteriv) + context->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameterivOES")); + } +#endif + if (!funcs->getFramebufferAttachmentParameteriv) { + funcs->getFramebufferAttachmentParameteriv = (type_glGetFramebufferAttachmentParameteriv) + context->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameterivEXT")); + } + if (!funcs->getFramebufferAttachmentParameteriv) { + funcs->getFramebufferAttachmentParameteriv = (type_glGetFramebufferAttachmentParameteriv) + context->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameterivARB")); + } + + if (funcs->getFramebufferAttachmentParameteriv) + funcs->getFramebufferAttachmentParameteriv(target, attachment, pname, params); + else + funcs->getFramebufferAttachmentParameteriv = qglfResolveGetFramebufferAttachmentParameteriv; +} + +static void qglfResolveGetProgramiv(GLuint program, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetProgramiv)(GLuint program, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getProgramiv = (type_glGetProgramiv) + context->getProcAddress(QLatin1String("glGetProgramiv")); + if (!funcs->getProgramiv) { + funcs->getProgramiv = (type_glGetProgramiv) + context->getProcAddress(QLatin1String("glGetObjectParameterivARB")); + } + + if (funcs->getProgramiv) + funcs->getProgramiv(program, pname, params); + else + funcs->getProgramiv = qglfResolveGetProgramiv; +} + +static void qglfResolveGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) +{ + typedef void (QGLF_APIENTRYP type_glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getProgramInfoLog = (type_glGetProgramInfoLog) + context->getProcAddress(QLatin1String("glGetProgramInfoLog")); + if (!funcs->getProgramInfoLog) { + funcs->getProgramInfoLog = (type_glGetProgramInfoLog) + context->getProcAddress(QLatin1String("glGetInfoLogARB")); + } + + if (funcs->getProgramInfoLog) + funcs->getProgramInfoLog(program, bufsize, length, infolog); + else + funcs->getProgramInfoLog = qglfResolveGetProgramInfoLog; +} + +static void qglfResolveGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getRenderbufferParameteriv = (type_glGetRenderbufferParameteriv) + context->getProcAddress(QLatin1String("glGetRenderbufferParameteriv")); +#ifdef QT_OPENGL_ES + if (!funcs->getRenderbufferParameteriv) { + funcs->getRenderbufferParameteriv = (type_glGetRenderbufferParameteriv) + context->getProcAddress(QLatin1String("glGetRenderbufferParameterivOES")); + } +#endif + if (!funcs->getRenderbufferParameteriv) { + funcs->getRenderbufferParameteriv = (type_glGetRenderbufferParameteriv) + context->getProcAddress(QLatin1String("glGetRenderbufferParameterivEXT")); + } + if (!funcs->getRenderbufferParameteriv) { + funcs->getRenderbufferParameteriv = (type_glGetRenderbufferParameteriv) + context->getProcAddress(QLatin1String("glGetRenderbufferParameterivARB")); + } + + if (funcs->getRenderbufferParameteriv) + funcs->getRenderbufferParameteriv(target, pname, params); + else + funcs->getRenderbufferParameteriv = qglfResolveGetRenderbufferParameteriv; +} + +static void qglfResolveGetShaderiv(GLuint shader, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetShaderiv)(GLuint shader, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getShaderiv = (type_glGetShaderiv) + context->getProcAddress(QLatin1String("glGetShaderiv")); + if (!funcs->getShaderiv) { + funcs->getShaderiv = (type_glGetShaderiv) + context->getProcAddress(QLatin1String("glGetObjectParameterivARB")); + } + + if (funcs->getShaderiv) + funcs->getShaderiv(shader, pname, params); + else + funcs->getShaderiv = qglfResolveGetShaderiv; +} + +static void qglfResolveGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) +{ + typedef void (QGLF_APIENTRYP type_glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getShaderInfoLog = (type_glGetShaderInfoLog) + context->getProcAddress(QLatin1String("glGetShaderInfoLog")); + if (!funcs->getShaderInfoLog) { + funcs->getShaderInfoLog = (type_glGetShaderInfoLog) + context->getProcAddress(QLatin1String("glGetInfoLogARB")); + } + + if (funcs->getShaderInfoLog) + funcs->getShaderInfoLog(shader, bufsize, length, infolog); + else + funcs->getShaderInfoLog = qglfResolveGetShaderInfoLog; +} + +static void qglfSpecialGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) +{ + Q_UNUSED(shadertype); + Q_UNUSED(precisiontype); + range[0] = range[1] = precision[0] = 0; +} + +static void qglfResolveGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) +{ + typedef void (QGLF_APIENTRYP type_glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getShaderPrecisionFormat = (type_glGetShaderPrecisionFormat) + context->getProcAddress(QLatin1String("glGetShaderPrecisionFormat")); +#ifdef QT_OPENGL_ES + if (!funcs->getShaderPrecisionFormat) { + funcs->getShaderPrecisionFormat = (type_glGetShaderPrecisionFormat) + context->getProcAddress(QLatin1String("glGetShaderPrecisionFormatOES")); + } +#endif + if (!funcs->getShaderPrecisionFormat) { + funcs->getShaderPrecisionFormat = (type_glGetShaderPrecisionFormat) + context->getProcAddress(QLatin1String("glGetShaderPrecisionFormatEXT")); + } + if (!funcs->getShaderPrecisionFormat) { + funcs->getShaderPrecisionFormat = (type_glGetShaderPrecisionFormat) + context->getProcAddress(QLatin1String("glGetShaderPrecisionFormatARB")); + } + + if (!funcs->getShaderPrecisionFormat) + funcs->getShaderPrecisionFormat = qglfSpecialGetShaderPrecisionFormat; + + funcs->getShaderPrecisionFormat(shadertype, precisiontype, range, precision); +} + +static void qglfResolveGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source) +{ + typedef void (QGLF_APIENTRYP type_glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, char* source); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getShaderSource = (type_glGetShaderSource) + context->getProcAddress(QLatin1String("glGetShaderSource")); + if (!funcs->getShaderSource) { + funcs->getShaderSource = (type_glGetShaderSource) + context->getProcAddress(QLatin1String("glGetShaderSourceARB")); + } + + if (funcs->getShaderSource) + funcs->getShaderSource(shader, bufsize, length, source); + else + funcs->getShaderSource = qglfResolveGetShaderSource; +} + +static void qglfResolveGetUniformfv(GLuint program, GLint location, GLfloat* params) +{ + typedef void (QGLF_APIENTRYP type_glGetUniformfv)(GLuint program, GLint location, GLfloat* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getUniformfv = (type_glGetUniformfv) + context->getProcAddress(QLatin1String("glGetUniformfv")); + if (!funcs->getUniformfv) { + funcs->getUniformfv = (type_glGetUniformfv) + context->getProcAddress(QLatin1String("glGetUniformfvARB")); + } + + if (funcs->getUniformfv) + funcs->getUniformfv(program, location, params); + else + funcs->getUniformfv = qglfResolveGetUniformfv; +} + +static void qglfResolveGetUniformiv(GLuint program, GLint location, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetUniformiv)(GLuint program, GLint location, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getUniformiv = (type_glGetUniformiv) + context->getProcAddress(QLatin1String("glGetUniformiv")); + if (!funcs->getUniformiv) { + funcs->getUniformiv = (type_glGetUniformiv) + context->getProcAddress(QLatin1String("glGetUniformivARB")); + } + + if (funcs->getUniformiv) + funcs->getUniformiv(program, location, params); + else + funcs->getUniformiv = qglfResolveGetUniformiv; +} + +static int qglfResolveGetUniformLocation(GLuint program, const char* name) +{ + typedef int (QGLF_APIENTRYP type_glGetUniformLocation)(GLuint program, const char* name); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getUniformLocation = (type_glGetUniformLocation) + context->getProcAddress(QLatin1String("glGetUniformLocation")); + if (!funcs->getUniformLocation) { + funcs->getUniformLocation = (type_glGetUniformLocation) + context->getProcAddress(QLatin1String("glGetUniformLocationARB")); + } + + if (funcs->getUniformLocation) + return funcs->getUniformLocation(program, name); + funcs->getUniformLocation = qglfResolveGetUniformLocation; + return int(0); +} + +static void qglfResolveGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) +{ + typedef void (QGLF_APIENTRYP type_glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getVertexAttribfv = (type_glGetVertexAttribfv) + context->getProcAddress(QLatin1String("glGetVertexAttribfv")); + if (!funcs->getVertexAttribfv) { + funcs->getVertexAttribfv = (type_glGetVertexAttribfv) + context->getProcAddress(QLatin1String("glGetVertexAttribfvARB")); + } + + if (funcs->getVertexAttribfv) + funcs->getVertexAttribfv(index, pname, params); + else + funcs->getVertexAttribfv = qglfResolveGetVertexAttribfv; +} + +static void qglfResolveGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getVertexAttribiv = (type_glGetVertexAttribiv) + context->getProcAddress(QLatin1String("glGetVertexAttribiv")); + if (!funcs->getVertexAttribiv) { + funcs->getVertexAttribiv = (type_glGetVertexAttribiv) + context->getProcAddress(QLatin1String("glGetVertexAttribivARB")); + } + + if (funcs->getVertexAttribiv) + funcs->getVertexAttribiv(index, pname, params); + else + funcs->getVertexAttribiv = qglfResolveGetVertexAttribiv; +} + +static void qglfResolveGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) +{ + typedef void (QGLF_APIENTRYP type_glGetVertexAttribPointerv)(GLuint index, GLenum pname, void** pointer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getVertexAttribPointerv = (type_glGetVertexAttribPointerv) + context->getProcAddress(QLatin1String("glGetVertexAttribPointerv")); + if (!funcs->getVertexAttribPointerv) { + funcs->getVertexAttribPointerv = (type_glGetVertexAttribPointerv) + context->getProcAddress(QLatin1String("glGetVertexAttribPointervARB")); + } + + if (funcs->getVertexAttribPointerv) + funcs->getVertexAttribPointerv(index, pname, pointer); + else + funcs->getVertexAttribPointerv = qglfResolveGetVertexAttribPointerv; +} + +static GLboolean qglfResolveIsBuffer(GLuint buffer) +{ + typedef GLboolean (QGLF_APIENTRYP type_glIsBuffer)(GLuint buffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->isBuffer = (type_glIsBuffer) + context->getProcAddress(QLatin1String("glIsBuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->isBuffer) { + funcs->isBuffer = (type_glIsBuffer) + context->getProcAddress(QLatin1String("glIsBufferOES")); + } +#endif + if (!funcs->isBuffer) { + funcs->isBuffer = (type_glIsBuffer) + context->getProcAddress(QLatin1String("glIsBufferEXT")); + } + if (!funcs->isBuffer) { + funcs->isBuffer = (type_glIsBuffer) + context->getProcAddress(QLatin1String("glIsBufferARB")); + } + + if (funcs->isBuffer) + return funcs->isBuffer(buffer); + funcs->isBuffer = qglfResolveIsBuffer; + return GLboolean(0); +} + +static GLboolean qglfResolveIsFramebuffer(GLuint framebuffer) +{ + typedef GLboolean (QGLF_APIENTRYP type_glIsFramebuffer)(GLuint framebuffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->isFramebuffer = (type_glIsFramebuffer) + context->getProcAddress(QLatin1String("glIsFramebuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->isFramebuffer) { + funcs->isFramebuffer = (type_glIsFramebuffer) + context->getProcAddress(QLatin1String("glIsFramebufferOES")); + } +#endif + if (!funcs->isFramebuffer) { + funcs->isFramebuffer = (type_glIsFramebuffer) + context->getProcAddress(QLatin1String("glIsFramebufferEXT")); + } + if (!funcs->isFramebuffer) { + funcs->isFramebuffer = (type_glIsFramebuffer) + context->getProcAddress(QLatin1String("glIsFramebufferARB")); + } + + if (funcs->isFramebuffer) + return funcs->isFramebuffer(framebuffer); + funcs->isFramebuffer = qglfResolveIsFramebuffer; + return GLboolean(0); +} + +static GLboolean qglfSpecialIsProgram(GLuint program) +{ + return program != 0; +} + +static GLboolean qglfResolveIsProgram(GLuint program) +{ + typedef GLboolean (QGLF_APIENTRYP type_glIsProgram)(GLuint program); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->isProgram = (type_glIsProgram) + context->getProcAddress(QLatin1String("glIsProgram")); + if (!funcs->isProgram) { + funcs->isProgram = (type_glIsProgram) + context->getProcAddress(QLatin1String("glIsProgramARB")); + } + + if (!funcs->isProgram) + funcs->isProgram = qglfSpecialIsProgram; + + return funcs->isProgram(program); +} + +static GLboolean qglfResolveIsRenderbuffer(GLuint renderbuffer) +{ + typedef GLboolean (QGLF_APIENTRYP type_glIsRenderbuffer)(GLuint renderbuffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->isRenderbuffer = (type_glIsRenderbuffer) + context->getProcAddress(QLatin1String("glIsRenderbuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->isRenderbuffer) { + funcs->isRenderbuffer = (type_glIsRenderbuffer) + context->getProcAddress(QLatin1String("glIsRenderbufferOES")); + } +#endif + if (!funcs->isRenderbuffer) { + funcs->isRenderbuffer = (type_glIsRenderbuffer) + context->getProcAddress(QLatin1String("glIsRenderbufferEXT")); + } + if (!funcs->isRenderbuffer) { + funcs->isRenderbuffer = (type_glIsRenderbuffer) + context->getProcAddress(QLatin1String("glIsRenderbufferARB")); + } + + if (funcs->isRenderbuffer) + return funcs->isRenderbuffer(renderbuffer); + funcs->isRenderbuffer = qglfResolveIsRenderbuffer; + return GLboolean(0); +} + +static GLboolean qglfSpecialIsShader(GLuint shader) +{ + return shader != 0; +} + +static GLboolean qglfResolveIsShader(GLuint shader) +{ + typedef GLboolean (QGLF_APIENTRYP type_glIsShader)(GLuint shader); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->isShader = (type_glIsShader) + context->getProcAddress(QLatin1String("glIsShader")); + if (!funcs->isShader) { + funcs->isShader = (type_glIsShader) + context->getProcAddress(QLatin1String("glIsShaderARB")); + } + + if (!funcs->isShader) + funcs->isShader = qglfSpecialIsShader; + + return funcs->isShader(shader); +} + +static void qglfResolveLinkProgram(GLuint program) +{ + typedef void (QGLF_APIENTRYP type_glLinkProgram)(GLuint program); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->linkProgram = (type_glLinkProgram) + context->getProcAddress(QLatin1String("glLinkProgram")); + if (!funcs->linkProgram) { + funcs->linkProgram = (type_glLinkProgram) + context->getProcAddress(QLatin1String("glLinkProgramARB")); + } + + if (funcs->linkProgram) + funcs->linkProgram(program); + else + funcs->linkProgram = qglfResolveLinkProgram; +} + +static void qglfSpecialReleaseShaderCompiler() +{ +} + +static void qglfResolveReleaseShaderCompiler() +{ + typedef void (QGLF_APIENTRYP type_glReleaseShaderCompiler)(); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->releaseShaderCompiler = (type_glReleaseShaderCompiler) + context->getProcAddress(QLatin1String("glReleaseShaderCompiler")); + if (!funcs->releaseShaderCompiler) { + funcs->releaseShaderCompiler = (type_glReleaseShaderCompiler) + context->getProcAddress(QLatin1String("glReleaseShaderCompilerARB")); + } + + if (!funcs->releaseShaderCompiler) + funcs->releaseShaderCompiler = qglfSpecialReleaseShaderCompiler; + + funcs->releaseShaderCompiler(); +} + +static void qglfResolveRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ + typedef void (QGLF_APIENTRYP type_glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->renderbufferStorage = (type_glRenderbufferStorage) + context->getProcAddress(QLatin1String("glRenderbufferStorage")); +#ifdef QT_OPENGL_ES + if (!funcs->renderbufferStorage) { + funcs->renderbufferStorage = (type_glRenderbufferStorage) + context->getProcAddress(QLatin1String("glRenderbufferStorageOES")); + } +#endif + if (!funcs->renderbufferStorage) { + funcs->renderbufferStorage = (type_glRenderbufferStorage) + context->getProcAddress(QLatin1String("glRenderbufferStorageEXT")); + } + if (!funcs->renderbufferStorage) { + funcs->renderbufferStorage = (type_glRenderbufferStorage) + context->getProcAddress(QLatin1String("glRenderbufferStorageARB")); + } + + if (funcs->renderbufferStorage) + funcs->renderbufferStorage(target, internalformat, width, height); + else + funcs->renderbufferStorage = qglfResolveRenderbufferStorage; +} + +static void qglfResolveSampleCoverage(GLclampf value, GLboolean invert) +{ + typedef void (QGLF_APIENTRYP type_glSampleCoverage)(GLclampf value, GLboolean invert); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->sampleCoverage = (type_glSampleCoverage) + context->getProcAddress(QLatin1String("glSampleCoverage")); +#ifdef QT_OPENGL_ES + if (!funcs->sampleCoverage) { + funcs->sampleCoverage = (type_glSampleCoverage) + context->getProcAddress(QLatin1String("glSampleCoverageOES")); + } +#endif + if (!funcs->sampleCoverage) { + funcs->sampleCoverage = (type_glSampleCoverage) + context->getProcAddress(QLatin1String("glSampleCoverageEXT")); + } + if (!funcs->sampleCoverage) { + funcs->sampleCoverage = (type_glSampleCoverage) + context->getProcAddress(QLatin1String("glSampleCoverageARB")); + } + + if (funcs->sampleCoverage) + funcs->sampleCoverage(value, invert); + else + funcs->sampleCoverage = qglfResolveSampleCoverage; +} + +static void qglfResolveShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length) +{ + typedef void (QGLF_APIENTRYP type_glShaderBinary)(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->shaderBinary = (type_glShaderBinary) + context->getProcAddress(QLatin1String("glShaderBinary")); + if (!funcs->shaderBinary) { + funcs->shaderBinary = (type_glShaderBinary) + context->getProcAddress(QLatin1String("glShaderBinaryARB")); + } + + if (funcs->shaderBinary) + funcs->shaderBinary(n, shaders, binaryformat, binary, length); + else + funcs->shaderBinary = qglfResolveShaderBinary; +} + +static void qglfResolveShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length) +{ + typedef void (QGLF_APIENTRYP type_glShaderSource)(GLuint shader, GLsizei count, const char** string, const GLint* length); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->shaderSource = (type_glShaderSource) + context->getProcAddress(QLatin1String("glShaderSource")); + if (!funcs->shaderSource) { + funcs->shaderSource = (type_glShaderSource) + context->getProcAddress(QLatin1String("glShaderSourceARB")); + } + + if (funcs->shaderSource) + funcs->shaderSource(shader, count, string, length); + else + funcs->shaderSource = qglfResolveShaderSource; +} + +static void qglfResolveStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ + typedef void (QGLF_APIENTRYP type_glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->stencilFuncSeparate = (type_glStencilFuncSeparate) + context->getProcAddress(QLatin1String("glStencilFuncSeparate")); +#ifdef QT_OPENGL_ES + if (!funcs->stencilFuncSeparate) { + funcs->stencilFuncSeparate = (type_glStencilFuncSeparate) + context->getProcAddress(QLatin1String("glStencilFuncSeparateOES")); + } +#endif + if (!funcs->stencilFuncSeparate) { + funcs->stencilFuncSeparate = (type_glStencilFuncSeparate) + context->getProcAddress(QLatin1String("glStencilFuncSeparateEXT")); + } + if (!funcs->stencilFuncSeparate) { + funcs->stencilFuncSeparate = (type_glStencilFuncSeparate) + context->getProcAddress(QLatin1String("glStencilFuncSeparateARB")); + } + + if (funcs->stencilFuncSeparate) + funcs->stencilFuncSeparate(face, func, ref, mask); + else + funcs->stencilFuncSeparate = qglfResolveStencilFuncSeparate; +} + +static void qglfResolveStencilMaskSeparate(GLenum face, GLuint mask) +{ + typedef void (QGLF_APIENTRYP type_glStencilMaskSeparate)(GLenum face, GLuint mask); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->stencilMaskSeparate = (type_glStencilMaskSeparate) + context->getProcAddress(QLatin1String("glStencilMaskSeparate")); +#ifdef QT_OPENGL_ES + if (!funcs->stencilMaskSeparate) { + funcs->stencilMaskSeparate = (type_glStencilMaskSeparate) + context->getProcAddress(QLatin1String("glStencilMaskSeparateOES")); + } +#endif + if (!funcs->stencilMaskSeparate) { + funcs->stencilMaskSeparate = (type_glStencilMaskSeparate) + context->getProcAddress(QLatin1String("glStencilMaskSeparateEXT")); + } + if (!funcs->stencilMaskSeparate) { + funcs->stencilMaskSeparate = (type_glStencilMaskSeparate) + context->getProcAddress(QLatin1String("glStencilMaskSeparateARB")); + } + + if (funcs->stencilMaskSeparate) + funcs->stencilMaskSeparate(face, mask); + else + funcs->stencilMaskSeparate = qglfResolveStencilMaskSeparate; +} + +static void qglfResolveStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + typedef void (QGLF_APIENTRYP type_glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->stencilOpSeparate = (type_glStencilOpSeparate) + context->getProcAddress(QLatin1String("glStencilOpSeparate")); +#ifdef QT_OPENGL_ES + if (!funcs->stencilOpSeparate) { + funcs->stencilOpSeparate = (type_glStencilOpSeparate) + context->getProcAddress(QLatin1String("glStencilOpSeparateOES")); + } +#endif + if (!funcs->stencilOpSeparate) { + funcs->stencilOpSeparate = (type_glStencilOpSeparate) + context->getProcAddress(QLatin1String("glStencilOpSeparateEXT")); + } + if (!funcs->stencilOpSeparate) { + funcs->stencilOpSeparate = (type_glStencilOpSeparate) + context->getProcAddress(QLatin1String("glStencilOpSeparateARB")); + } + + if (funcs->stencilOpSeparate) + funcs->stencilOpSeparate(face, fail, zfail, zpass); + else + funcs->stencilOpSeparate = qglfResolveStencilOpSeparate; +} + +static void qglfResolveUniform1f(GLint location, GLfloat x) +{ + typedef void (QGLF_APIENTRYP type_glUniform1f)(GLint location, GLfloat x); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform1f = (type_glUniform1f) + context->getProcAddress(QLatin1String("glUniform1f")); + if (!funcs->uniform1f) { + funcs->uniform1f = (type_glUniform1f) + context->getProcAddress(QLatin1String("glUniform1fARB")); + } + + if (funcs->uniform1f) + funcs->uniform1f(location, x); + else + funcs->uniform1f = qglfResolveUniform1f; +} + +static void qglfResolveUniform1fv(GLint location, GLsizei count, const GLfloat* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform1fv)(GLint location, GLsizei count, const GLfloat* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform1fv = (type_glUniform1fv) + context->getProcAddress(QLatin1String("glUniform1fv")); + if (!funcs->uniform1fv) { + funcs->uniform1fv = (type_glUniform1fv) + context->getProcAddress(QLatin1String("glUniform1fvARB")); + } + + if (funcs->uniform1fv) + funcs->uniform1fv(location, count, v); + else + funcs->uniform1fv = qglfResolveUniform1fv; +} + +static void qglfResolveUniform1i(GLint location, GLint x) +{ + typedef void (QGLF_APIENTRYP type_glUniform1i)(GLint location, GLint x); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform1i = (type_glUniform1i) + context->getProcAddress(QLatin1String("glUniform1i")); + if (!funcs->uniform1i) { + funcs->uniform1i = (type_glUniform1i) + context->getProcAddress(QLatin1String("glUniform1iARB")); + } + + if (funcs->uniform1i) + funcs->uniform1i(location, x); + else + funcs->uniform1i = qglfResolveUniform1i; +} + +static void qglfResolveUniform1iv(GLint location, GLsizei count, const GLint* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform1iv)(GLint location, GLsizei count, const GLint* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform1iv = (type_glUniform1iv) + context->getProcAddress(QLatin1String("glUniform1iv")); + if (!funcs->uniform1iv) { + funcs->uniform1iv = (type_glUniform1iv) + context->getProcAddress(QLatin1String("glUniform1ivARB")); + } + + if (funcs->uniform1iv) + funcs->uniform1iv(location, count, v); + else + funcs->uniform1iv = qglfResolveUniform1iv; +} + +static void qglfResolveUniform2f(GLint location, GLfloat x, GLfloat y) +{ + typedef void (QGLF_APIENTRYP type_glUniform2f)(GLint location, GLfloat x, GLfloat y); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform2f = (type_glUniform2f) + context->getProcAddress(QLatin1String("glUniform2f")); + if (!funcs->uniform2f) { + funcs->uniform2f = (type_glUniform2f) + context->getProcAddress(QLatin1String("glUniform2fARB")); + } + + if (funcs->uniform2f) + funcs->uniform2f(location, x, y); + else + funcs->uniform2f = qglfResolveUniform2f; +} + +static void qglfResolveUniform2fv(GLint location, GLsizei count, const GLfloat* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform2fv)(GLint location, GLsizei count, const GLfloat* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform2fv = (type_glUniform2fv) + context->getProcAddress(QLatin1String("glUniform2fv")); + if (!funcs->uniform2fv) { + funcs->uniform2fv = (type_glUniform2fv) + context->getProcAddress(QLatin1String("glUniform2fvARB")); + } + + if (funcs->uniform2fv) + funcs->uniform2fv(location, count, v); + else + funcs->uniform2fv = qglfResolveUniform2fv; +} + +static void qglfResolveUniform2i(GLint location, GLint x, GLint y) +{ + typedef void (QGLF_APIENTRYP type_glUniform2i)(GLint location, GLint x, GLint y); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform2i = (type_glUniform2i) + context->getProcAddress(QLatin1String("glUniform2i")); + if (!funcs->uniform2i) { + funcs->uniform2i = (type_glUniform2i) + context->getProcAddress(QLatin1String("glUniform2iARB")); + } + + if (funcs->uniform2i) + funcs->uniform2i(location, x, y); + else + funcs->uniform2i = qglfResolveUniform2i; +} + +static void qglfResolveUniform2iv(GLint location, GLsizei count, const GLint* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform2iv)(GLint location, GLsizei count, const GLint* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform2iv = (type_glUniform2iv) + context->getProcAddress(QLatin1String("glUniform2iv")); + if (!funcs->uniform2iv) { + funcs->uniform2iv = (type_glUniform2iv) + context->getProcAddress(QLatin1String("glUniform2ivARB")); + } + + if (funcs->uniform2iv) + funcs->uniform2iv(location, count, v); + else + funcs->uniform2iv = qglfResolveUniform2iv; +} + +static void qglfResolveUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) +{ + typedef void (QGLF_APIENTRYP type_glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform3f = (type_glUniform3f) + context->getProcAddress(QLatin1String("glUniform3f")); + if (!funcs->uniform3f) { + funcs->uniform3f = (type_glUniform3f) + context->getProcAddress(QLatin1String("glUniform3fARB")); + } + + if (funcs->uniform3f) + funcs->uniform3f(location, x, y, z); + else + funcs->uniform3f = qglfResolveUniform3f; +} + +static void qglfResolveUniform3fv(GLint location, GLsizei count, const GLfloat* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform3fv)(GLint location, GLsizei count, const GLfloat* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform3fv = (type_glUniform3fv) + context->getProcAddress(QLatin1String("glUniform3fv")); + if (!funcs->uniform3fv) { + funcs->uniform3fv = (type_glUniform3fv) + context->getProcAddress(QLatin1String("glUniform3fvARB")); + } + + if (funcs->uniform3fv) + funcs->uniform3fv(location, count, v); + else + funcs->uniform3fv = qglfResolveUniform3fv; +} + +static void qglfResolveUniform3i(GLint location, GLint x, GLint y, GLint z) +{ + typedef void (QGLF_APIENTRYP type_glUniform3i)(GLint location, GLint x, GLint y, GLint z); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform3i = (type_glUniform3i) + context->getProcAddress(QLatin1String("glUniform3i")); + if (!funcs->uniform3i) { + funcs->uniform3i = (type_glUniform3i) + context->getProcAddress(QLatin1String("glUniform3iARB")); + } + + if (funcs->uniform3i) + funcs->uniform3i(location, x, y, z); + else + funcs->uniform3i = qglfResolveUniform3i; +} + +static void qglfResolveUniform3iv(GLint location, GLsizei count, const GLint* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform3iv)(GLint location, GLsizei count, const GLint* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform3iv = (type_glUniform3iv) + context->getProcAddress(QLatin1String("glUniform3iv")); + if (!funcs->uniform3iv) { + funcs->uniform3iv = (type_glUniform3iv) + context->getProcAddress(QLatin1String("glUniform3ivARB")); + } + + if (funcs->uniform3iv) + funcs->uniform3iv(location, count, v); + else + funcs->uniform3iv = qglfResolveUniform3iv; +} + +static void qglfResolveUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + typedef void (QGLF_APIENTRYP type_glUniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform4f = (type_glUniform4f) + context->getProcAddress(QLatin1String("glUniform4f")); + if (!funcs->uniform4f) { + funcs->uniform4f = (type_glUniform4f) + context->getProcAddress(QLatin1String("glUniform4fARB")); + } + + if (funcs->uniform4f) + funcs->uniform4f(location, x, y, z, w); + else + funcs->uniform4f = qglfResolveUniform4f; +} + +static void qglfResolveUniform4fv(GLint location, GLsizei count, const GLfloat* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform4fv)(GLint location, GLsizei count, const GLfloat* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform4fv = (type_glUniform4fv) + context->getProcAddress(QLatin1String("glUniform4fv")); + if (!funcs->uniform4fv) { + funcs->uniform4fv = (type_glUniform4fv) + context->getProcAddress(QLatin1String("glUniform4fvARB")); + } + + if (funcs->uniform4fv) + funcs->uniform4fv(location, count, v); + else + funcs->uniform4fv = qglfResolveUniform4fv; +} + +static void qglfResolveUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) +{ + typedef void (QGLF_APIENTRYP type_glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform4i = (type_glUniform4i) + context->getProcAddress(QLatin1String("glUniform4i")); + if (!funcs->uniform4i) { + funcs->uniform4i = (type_glUniform4i) + context->getProcAddress(QLatin1String("glUniform4iARB")); + } + + if (funcs->uniform4i) + funcs->uniform4i(location, x, y, z, w); + else + funcs->uniform4i = qglfResolveUniform4i; +} + +static void qglfResolveUniform4iv(GLint location, GLsizei count, const GLint* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform4iv)(GLint location, GLsizei count, const GLint* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform4iv = (type_glUniform4iv) + context->getProcAddress(QLatin1String("glUniform4iv")); + if (!funcs->uniform4iv) { + funcs->uniform4iv = (type_glUniform4iv) + context->getProcAddress(QLatin1String("glUniform4ivARB")); + } + + if (funcs->uniform4iv) + funcs->uniform4iv(location, count, v); + else + funcs->uniform4iv = qglfResolveUniform4iv; +} + +static void qglfResolveUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + typedef void (QGLF_APIENTRYP type_glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniformMatrix2fv = (type_glUniformMatrix2fv) + context->getProcAddress(QLatin1String("glUniformMatrix2fv")); + if (!funcs->uniformMatrix2fv) { + funcs->uniformMatrix2fv = (type_glUniformMatrix2fv) + context->getProcAddress(QLatin1String("glUniformMatrix2fvARB")); + } + + if (funcs->uniformMatrix2fv) + funcs->uniformMatrix2fv(location, count, transpose, value); + else + funcs->uniformMatrix2fv = qglfResolveUniformMatrix2fv; +} + +static void qglfResolveUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + typedef void (QGLF_APIENTRYP type_glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniformMatrix3fv = (type_glUniformMatrix3fv) + context->getProcAddress(QLatin1String("glUniformMatrix3fv")); + if (!funcs->uniformMatrix3fv) { + funcs->uniformMatrix3fv = (type_glUniformMatrix3fv) + context->getProcAddress(QLatin1String("glUniformMatrix3fvARB")); + } + + if (funcs->uniformMatrix3fv) + funcs->uniformMatrix3fv(location, count, transpose, value); + else + funcs->uniformMatrix3fv = qglfResolveUniformMatrix3fv; +} + +static void qglfResolveUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + typedef void (QGLF_APIENTRYP type_glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniformMatrix4fv = (type_glUniformMatrix4fv) + context->getProcAddress(QLatin1String("glUniformMatrix4fv")); + if (!funcs->uniformMatrix4fv) { + funcs->uniformMatrix4fv = (type_glUniformMatrix4fv) + context->getProcAddress(QLatin1String("glUniformMatrix4fvARB")); + } + + if (funcs->uniformMatrix4fv) + funcs->uniformMatrix4fv(location, count, transpose, value); + else + funcs->uniformMatrix4fv = qglfResolveUniformMatrix4fv; +} + +static void qglfResolveUseProgram(GLuint program) +{ + typedef void (QGLF_APIENTRYP type_glUseProgram)(GLuint program); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->useProgram = (type_glUseProgram) + context->getProcAddress(QLatin1String("glUseProgram")); + if (!funcs->useProgram) { + funcs->useProgram = (type_glUseProgram) + context->getProcAddress(QLatin1String("glUseProgramObjectARB")); + } + + if (funcs->useProgram) + funcs->useProgram(program); + else + funcs->useProgram = qglfResolveUseProgram; +} + +static void qglfResolveValidateProgram(GLuint program) +{ + typedef void (QGLF_APIENTRYP type_glValidateProgram)(GLuint program); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->validateProgram = (type_glValidateProgram) + context->getProcAddress(QLatin1String("glValidateProgram")); + if (!funcs->validateProgram) { + funcs->validateProgram = (type_glValidateProgram) + context->getProcAddress(QLatin1String("glValidateProgramARB")); + } + + if (funcs->validateProgram) + funcs->validateProgram(program); + else + funcs->validateProgram = qglfResolveValidateProgram; +} + +static void qglfResolveVertexAttrib1f(GLuint indx, GLfloat x) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib1f)(GLuint indx, GLfloat x); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib1f = (type_glVertexAttrib1f) + context->getProcAddress(QLatin1String("glVertexAttrib1f")); + if (!funcs->vertexAttrib1f) { + funcs->vertexAttrib1f = (type_glVertexAttrib1f) + context->getProcAddress(QLatin1String("glVertexAttrib1fARB")); + } + + if (funcs->vertexAttrib1f) + funcs->vertexAttrib1f(indx, x); + else + funcs->vertexAttrib1f = qglfResolveVertexAttrib1f; +} + +static void qglfResolveVertexAttrib1fv(GLuint indx, const GLfloat* values) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib1fv)(GLuint indx, const GLfloat* values); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib1fv = (type_glVertexAttrib1fv) + context->getProcAddress(QLatin1String("glVertexAttrib1fv")); + if (!funcs->vertexAttrib1fv) { + funcs->vertexAttrib1fv = (type_glVertexAttrib1fv) + context->getProcAddress(QLatin1String("glVertexAttrib1fvARB")); + } + + if (funcs->vertexAttrib1fv) + funcs->vertexAttrib1fv(indx, values); + else + funcs->vertexAttrib1fv = qglfResolveVertexAttrib1fv; +} + +static void qglfResolveVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib2f = (type_glVertexAttrib2f) + context->getProcAddress(QLatin1String("glVertexAttrib2f")); + if (!funcs->vertexAttrib2f) { + funcs->vertexAttrib2f = (type_glVertexAttrib2f) + context->getProcAddress(QLatin1String("glVertexAttrib2fARB")); + } + + if (funcs->vertexAttrib2f) + funcs->vertexAttrib2f(indx, x, y); + else + funcs->vertexAttrib2f = qglfResolveVertexAttrib2f; +} + +static void qglfResolveVertexAttrib2fv(GLuint indx, const GLfloat* values) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib2fv)(GLuint indx, const GLfloat* values); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib2fv = (type_glVertexAttrib2fv) + context->getProcAddress(QLatin1String("glVertexAttrib2fv")); + if (!funcs->vertexAttrib2fv) { + funcs->vertexAttrib2fv = (type_glVertexAttrib2fv) + context->getProcAddress(QLatin1String("glVertexAttrib2fvARB")); + } + + if (funcs->vertexAttrib2fv) + funcs->vertexAttrib2fv(indx, values); + else + funcs->vertexAttrib2fv = qglfResolveVertexAttrib2fv; +} + +static void qglfResolveVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib3f = (type_glVertexAttrib3f) + context->getProcAddress(QLatin1String("glVertexAttrib3f")); + if (!funcs->vertexAttrib3f) { + funcs->vertexAttrib3f = (type_glVertexAttrib3f) + context->getProcAddress(QLatin1String("glVertexAttrib3fARB")); + } + + if (funcs->vertexAttrib3f) + funcs->vertexAttrib3f(indx, x, y, z); + else + funcs->vertexAttrib3f = qglfResolveVertexAttrib3f; +} + +static void qglfResolveVertexAttrib3fv(GLuint indx, const GLfloat* values) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib3fv)(GLuint indx, const GLfloat* values); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib3fv = (type_glVertexAttrib3fv) + context->getProcAddress(QLatin1String("glVertexAttrib3fv")); + if (!funcs->vertexAttrib3fv) { + funcs->vertexAttrib3fv = (type_glVertexAttrib3fv) + context->getProcAddress(QLatin1String("glVertexAttrib3fvARB")); + } + + if (funcs->vertexAttrib3fv) + funcs->vertexAttrib3fv(indx, values); + else + funcs->vertexAttrib3fv = qglfResolveVertexAttrib3fv; +} + +static void qglfResolveVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib4f = (type_glVertexAttrib4f) + context->getProcAddress(QLatin1String("glVertexAttrib4f")); + if (!funcs->vertexAttrib4f) { + funcs->vertexAttrib4f = (type_glVertexAttrib4f) + context->getProcAddress(QLatin1String("glVertexAttrib4fARB")); + } + + if (funcs->vertexAttrib4f) + funcs->vertexAttrib4f(indx, x, y, z, w); + else + funcs->vertexAttrib4f = qglfResolveVertexAttrib4f; +} + +static void qglfResolveVertexAttrib4fv(GLuint indx, const GLfloat* values) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib4fv)(GLuint indx, const GLfloat* values); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib4fv = (type_glVertexAttrib4fv) + context->getProcAddress(QLatin1String("glVertexAttrib4fv")); + if (!funcs->vertexAttrib4fv) { + funcs->vertexAttrib4fv = (type_glVertexAttrib4fv) + context->getProcAddress(QLatin1String("glVertexAttrib4fvARB")); + } + + if (funcs->vertexAttrib4fv) + funcs->vertexAttrib4fv(indx, values); + else + funcs->vertexAttrib4fv = qglfResolveVertexAttrib4fv; +} + +static void qglfResolveVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttribPointer = (type_glVertexAttribPointer) + context->getProcAddress(QLatin1String("glVertexAttribPointer")); + if (!funcs->vertexAttribPointer) { + funcs->vertexAttribPointer = (type_glVertexAttribPointer) + context->getProcAddress(QLatin1String("glVertexAttribPointerARB")); + } + + if (funcs->vertexAttribPointer) + funcs->vertexAttribPointer(indx, size, type, normalized, stride, ptr); + else + funcs->vertexAttribPointer = qglfResolveVertexAttribPointer; +} + +#endif // !QT_OPENGL_ES_2 + +QGLFunctionsPrivate::QGLFunctionsPrivate(const QGLContext *) +{ +#ifndef QT_OPENGL_ES_2 + activeTexture = qglfResolveActiveTexture; + attachShader = qglfResolveAttachShader; + bindAttribLocation = qglfResolveBindAttribLocation; + bindBuffer = qglfResolveBindBuffer; + bindFramebuffer = qglfResolveBindFramebuffer; + bindRenderbuffer = qglfResolveBindRenderbuffer; + blendColor = qglfResolveBlendColor; + blendEquation = qglfResolveBlendEquation; + blendEquationSeparate = qglfResolveBlendEquationSeparate; + blendFuncSeparate = qglfResolveBlendFuncSeparate; + bufferData = qglfResolveBufferData; + bufferSubData = qglfResolveBufferSubData; + checkFramebufferStatus = qglfResolveCheckFramebufferStatus; + compileShader = qglfResolveCompileShader; + compressedTexImage2D = qglfResolveCompressedTexImage2D; + compressedTexSubImage2D = qglfResolveCompressedTexSubImage2D; + createProgram = qglfResolveCreateProgram; + createShader = qglfResolveCreateShader; + deleteBuffers = qglfResolveDeleteBuffers; + deleteFramebuffers = qglfResolveDeleteFramebuffers; + deleteProgram = qglfResolveDeleteProgram; + deleteRenderbuffers = qglfResolveDeleteRenderbuffers; + deleteShader = qglfResolveDeleteShader; + detachShader = qglfResolveDetachShader; + disableVertexAttribArray = qglfResolveDisableVertexAttribArray; + enableVertexAttribArray = qglfResolveEnableVertexAttribArray; + framebufferRenderbuffer = qglfResolveFramebufferRenderbuffer; + framebufferTexture2D = qglfResolveFramebufferTexture2D; + genBuffers = qglfResolveGenBuffers; + generateMipmap = qglfResolveGenerateMipmap; + genFramebuffers = qglfResolveGenFramebuffers; + genRenderbuffers = qglfResolveGenRenderbuffers; + getActiveAttrib = qglfResolveGetActiveAttrib; + getActiveUniform = qglfResolveGetActiveUniform; + getAttachedShaders = qglfResolveGetAttachedShaders; + getAttribLocation = qglfResolveGetAttribLocation; + getBufferParameteriv = qglfResolveGetBufferParameteriv; + getFramebufferAttachmentParameteriv = qglfResolveGetFramebufferAttachmentParameteriv; + getProgramiv = qglfResolveGetProgramiv; + getProgramInfoLog = qglfResolveGetProgramInfoLog; + getRenderbufferParameteriv = qglfResolveGetRenderbufferParameteriv; + getShaderiv = qglfResolveGetShaderiv; + getShaderInfoLog = qglfResolveGetShaderInfoLog; + getShaderPrecisionFormat = qglfResolveGetShaderPrecisionFormat; + getShaderSource = qglfResolveGetShaderSource; + getUniformfv = qglfResolveGetUniformfv; + getUniformiv = qglfResolveGetUniformiv; + getUniformLocation = qglfResolveGetUniformLocation; + getVertexAttribfv = qglfResolveGetVertexAttribfv; + getVertexAttribiv = qglfResolveGetVertexAttribiv; + getVertexAttribPointerv = qglfResolveGetVertexAttribPointerv; + isBuffer = qglfResolveIsBuffer; + isFramebuffer = qglfResolveIsFramebuffer; + isProgram = qglfResolveIsProgram; + isRenderbuffer = qglfResolveIsRenderbuffer; + isShader = qglfResolveIsShader; + linkProgram = qglfResolveLinkProgram; + releaseShaderCompiler = qglfResolveReleaseShaderCompiler; + renderbufferStorage = qglfResolveRenderbufferStorage; + sampleCoverage = qglfResolveSampleCoverage; + shaderBinary = qglfResolveShaderBinary; + shaderSource = qglfResolveShaderSource; + stencilFuncSeparate = qglfResolveStencilFuncSeparate; + stencilMaskSeparate = qglfResolveStencilMaskSeparate; + stencilOpSeparate = qglfResolveStencilOpSeparate; + uniform1f = qglfResolveUniform1f; + uniform1fv = qglfResolveUniform1fv; + uniform1i = qglfResolveUniform1i; + uniform1iv = qglfResolveUniform1iv; + uniform2f = qglfResolveUniform2f; + uniform2fv = qglfResolveUniform2fv; + uniform2i = qglfResolveUniform2i; + uniform2iv = qglfResolveUniform2iv; + uniform3f = qglfResolveUniform3f; + uniform3fv = qglfResolveUniform3fv; + uniform3i = qglfResolveUniform3i; + uniform3iv = qglfResolveUniform3iv; + uniform4f = qglfResolveUniform4f; + uniform4fv = qglfResolveUniform4fv; + uniform4i = qglfResolveUniform4i; + uniform4iv = qglfResolveUniform4iv; + uniformMatrix2fv = qglfResolveUniformMatrix2fv; + uniformMatrix3fv = qglfResolveUniformMatrix3fv; + uniformMatrix4fv = qglfResolveUniformMatrix4fv; + useProgram = qglfResolveUseProgram; + validateProgram = qglfResolveValidateProgram; + vertexAttrib1f = qglfResolveVertexAttrib1f; + vertexAttrib1fv = qglfResolveVertexAttrib1fv; + vertexAttrib2f = qglfResolveVertexAttrib2f; + vertexAttrib2fv = qglfResolveVertexAttrib2fv; + vertexAttrib3f = qglfResolveVertexAttrib3f; + vertexAttrib3fv = qglfResolveVertexAttrib3fv; + vertexAttrib4f = qglfResolveVertexAttrib4f; + vertexAttrib4fv = qglfResolveVertexAttrib4fv; + vertexAttribPointer = qglfResolveVertexAttribPointer; +#endif // !QT_OPENGL_ES_2 +} + +QT_END_NAMESPACE diff --git a/src/opengl/qglfunctions.h b/src/opengl/qglfunctions.h new file mode 100644 index 0000000..e06de7f --- /dev/null +++ b/src/opengl/qglfunctions.h @@ -0,0 +1,2290 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenGL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGLFUNCTIONS_H +#define QGLFUNCTIONS_H + +#include <QtOpenGL/qgl.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(OpenGL) + +// Types that aren't defined in all system's gl.h files. +typedef ptrdiff_t qgl_GLintptr; +typedef ptrdiff_t qgl_GLsizeiptr; + +#ifndef Q_WS_MAC +# ifndef QGLF_APIENTRYP +# ifdef QGLF_APIENTRY +# define QGLF_APIENTRYP QGLF_APIENTRY * +# else +# define QGLF_APIENTRY +# define QGLF_APIENTRYP * +# endif +# endif +#else +# define QGLF_APIENTRY +# define QGLF_APIENTRYP * +#endif + +struct QGLFunctionsPrivate; + +// Undefine any macros from GLEW, qglextensions_p.h, etc that +// may interfere with the definition of QGLFunctions. +#undef glActiveTexture +#undef glAttachShader +#undef glBindAttribLocation +#undef glBindBuffer +#undef glBindFramebuffer +#undef glBindRenderbuffer +#undef glBlendColor +#undef glBlendEquation +#undef glBlendEquationSeparate +#undef glBlendFuncSeparate +#undef glBufferData +#undef glBufferSubData +#undef glCheckFramebufferStatus +#undef glClearDepthf +#undef glCompileShader +#undef glCompressedTexImage2D +#undef glCompressedTexSubImage2D +#undef glCreateProgram +#undef glCreateShader +#undef glDeleteBuffers +#undef glDeleteFramebuffers +#undef glDeleteProgram +#undef glDeleteRenderbuffers +#undef glDeleteShader +#undef glDepthRangef +#undef glDetachShader +#undef glDisableVertexAttribArray +#undef glEnableVertexAttribArray +#undef glFramebufferRenderbuffer +#undef glFramebufferTexture2D +#undef glGenBuffers +#undef glGenerateMipmap +#undef glGenFramebuffers +#undef glGenRenderbuffers +#undef glGetActiveAttrib +#undef glGetActiveUniform +#undef glGetAttachedShaders +#undef glGetAttribLocation +#undef glGetBufferParameteriv +#undef glGetFramebufferAttachmentParameteriv +#undef glGetProgramiv +#undef glGetProgramInfoLog +#undef glGetRenderbufferParameteriv +#undef glGetShaderiv +#undef glGetShaderInfoLog +#undef glGetShaderPrecisionFormat +#undef glGetShaderSource +#undef glGetUniformfv +#undef glGetUniformiv +#undef glGetUniformLocation +#undef glGetVertexAttribfv +#undef glGetVertexAttribiv +#undef glGetVertexAttribPointerv +#undef glIsBuffer +#undef glIsFramebuffer +#undef glIsProgram +#undef glIsRenderbuffer +#undef glIsShader +#undef glLinkProgram +#undef glReleaseShaderCompiler +#undef glRenderbufferStorage +#undef glSampleCoverage +#undef glShaderBinary +#undef glShaderSource +#undef glStencilFuncSeparate +#undef glStencilMaskSeparate +#undef glStencilOpSeparate +#undef glUniform1f +#undef glUniform1fv +#undef glUniform1i +#undef glUniform1iv +#undef glUniform2f +#undef glUniform2fv +#undef glUniform2i +#undef glUniform2iv +#undef glUniform3f +#undef glUniform3fv +#undef glUniform3i +#undef glUniform3iv +#undef glUniform4f +#undef glUniform4fv +#undef glUniform4i +#undef glUniform4iv +#undef glUniformMatrix2fv +#undef glUniformMatrix3fv +#undef glUniformMatrix4fv +#undef glUseProgram +#undef glValidateProgram +#undef glVertexAttrib1f +#undef glVertexAttrib1fv +#undef glVertexAttrib2f +#undef glVertexAttrib2fv +#undef glVertexAttrib3f +#undef glVertexAttrib3fv +#undef glVertexAttrib4f +#undef glVertexAttrib4fv +#undef glVertexAttribPointer + +class Q_OPENGL_EXPORT QGLFunctions +{ +public: + QGLFunctions(); + explicit QGLFunctions(const QGLContext *context); + ~QGLFunctions() {} + + enum OpenGLFeature + { + Multitexture = 0x0001, + Shaders = 0x0002, + Buffers = 0x0004, + Framebuffers = 0x0008, + BlendColor = 0x0010, + BlendEquation = 0x0020, + BlendEquationSeparate = 0x0040, + BlendFuncSeparate = 0x0080, + BlendSubtract = 0x0100, + CompressedTextures = 0x0200, + Multisample = 0x0400, + StencilSeparate = 0x0800, + NPOTTextures = 0x1000 + }; + Q_DECLARE_FLAGS(OpenGLFeatures, OpenGLFeature) + + QGLFunctions::OpenGLFeatures openGLFeatures() const; + bool hasOpenGLFeature(QGLFunctions::OpenGLFeature feature) const; + + void initializeGLFunctions(const QGLContext *context = 0); + + void glActiveTexture(GLenum texture); + void glAttachShader(GLuint program, GLuint shader); + void glBindAttribLocation(GLuint program, GLuint index, const char* name); + void glBindBuffer(GLenum target, GLuint buffer); + void glBindFramebuffer(GLenum target, GLuint framebuffer); + void glBindRenderbuffer(GLenum target, GLuint renderbuffer); + void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void glBlendEquation(GLenum mode); + void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); + void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + void glBufferData(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage); + void glBufferSubData(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data); + GLenum glCheckFramebufferStatus(GLenum target); + void glClearDepthf(GLclampf depth); + void glCompileShader(GLuint shader); + void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); + void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); + GLuint glCreateProgram(); + GLuint glCreateShader(GLenum type); + void glDeleteBuffers(GLsizei n, const GLuint* buffers); + void glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers); + void glDeleteProgram(GLuint program); + void glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers); + void glDeleteShader(GLuint shader); + void glDepthRangef(GLclampf zNear, GLclampf zFar); + void glDetachShader(GLuint program, GLuint shader); + void glDisableVertexAttribArray(GLuint index); + void glEnableVertexAttribArray(GLuint index); + void glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + void glGenBuffers(GLsizei n, GLuint* buffers); + void glGenerateMipmap(GLenum target); + void glGenFramebuffers(GLsizei n, GLuint* framebuffers); + void glGenRenderbuffers(GLsizei n, GLuint* renderbuffers); + void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + void glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); + int glGetAttribLocation(GLuint program, const char* name); + void glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params); + void glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params); + void glGetProgramiv(GLuint program, GLenum pname, GLint* params); + void glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog); + void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params); + void glGetShaderiv(GLuint shader, GLenum pname, GLint* params); + void glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog); + void glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); + void glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source); + void glGetUniformfv(GLuint program, GLint location, GLfloat* params); + void glGetUniformiv(GLuint program, GLint location, GLint* params); + int glGetUniformLocation(GLuint program, const char* name); + void glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params); + void glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params); + void glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer); + GLboolean glIsBuffer(GLuint buffer); + GLboolean glIsFramebuffer(GLuint framebuffer); + GLboolean glIsProgram(GLuint program); + GLboolean glIsRenderbuffer(GLuint renderbuffer); + GLboolean glIsShader(GLuint shader); + void glLinkProgram(GLuint program); + void glReleaseShaderCompiler(); + void glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + void glSampleCoverage(GLclampf value, GLboolean invert); + void glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length); + void glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length); + void glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); + void glStencilMaskSeparate(GLenum face, GLuint mask); + void glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); + void glUniform1f(GLint location, GLfloat x); + void glUniform1fv(GLint location, GLsizei count, const GLfloat* v); + void glUniform1i(GLint location, GLint x); + void glUniform1iv(GLint location, GLsizei count, const GLint* v); + void glUniform2f(GLint location, GLfloat x, GLfloat y); + void glUniform2fv(GLint location, GLsizei count, const GLfloat* v); + void glUniform2i(GLint location, GLint x, GLint y); + void glUniform2iv(GLint location, GLsizei count, const GLint* v); + void glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z); + void glUniform3fv(GLint location, GLsizei count, const GLfloat* v); + void glUniform3i(GLint location, GLint x, GLint y, GLint z); + void glUniform3iv(GLint location, GLsizei count, const GLint* v); + void glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void glUniform4fv(GLint location, GLsizei count, const GLfloat* v); + void glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w); + void glUniform4iv(GLint location, GLsizei count, const GLint* v); + void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void glUseProgram(GLuint program); + void glValidateProgram(GLuint program); + void glVertexAttrib1f(GLuint indx, GLfloat x); + void glVertexAttrib1fv(GLuint indx, const GLfloat* values); + void glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y); + void glVertexAttrib2fv(GLuint indx, const GLfloat* values); + void glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z); + void glVertexAttrib3fv(GLuint indx, const GLfloat* values); + void glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void glVertexAttrib4fv(GLuint indx, const GLfloat* values); + void glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr); + +private: + QGLFunctionsPrivate *d_ptr; + static bool isInitialized(const QGLFunctionsPrivate *d) { return d != 0; } +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QGLFunctions::OpenGLFeatures) + +struct QGLFunctionsPrivate +{ + QGLFunctionsPrivate(const QGLContext *context = 0); + +#ifndef QT_OPENGL_ES_2 + void (QGLF_APIENTRYP activeTexture)(GLenum texture); + void (QGLF_APIENTRYP attachShader)(GLuint program, GLuint shader); + void (QGLF_APIENTRYP bindAttribLocation)(GLuint program, GLuint index, const char* name); + void (QGLF_APIENTRYP bindBuffer)(GLenum target, GLuint buffer); + void (QGLF_APIENTRYP bindFramebuffer)(GLenum target, GLuint framebuffer); + void (QGLF_APIENTRYP bindRenderbuffer)(GLenum target, GLuint renderbuffer); + void (QGLF_APIENTRYP blendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void (QGLF_APIENTRYP blendEquation)(GLenum mode); + void (QGLF_APIENTRYP blendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha); + void (QGLF_APIENTRYP blendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + void (QGLF_APIENTRYP bufferData)(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage); + void (QGLF_APIENTRYP bufferSubData)(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data); + GLenum (QGLF_APIENTRYP checkFramebufferStatus)(GLenum target); + void (QGLF_APIENTRYP compileShader)(GLuint shader); + void (QGLF_APIENTRYP compressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); + void (QGLF_APIENTRYP compressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); + GLuint (QGLF_APIENTRYP createProgram)(); + GLuint (QGLF_APIENTRYP createShader)(GLenum type); + void (QGLF_APIENTRYP deleteBuffers)(GLsizei n, const GLuint* buffers); + void (QGLF_APIENTRYP deleteFramebuffers)(GLsizei n, const GLuint* framebuffers); + void (QGLF_APIENTRYP deleteProgram)(GLuint program); + void (QGLF_APIENTRYP deleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers); + void (QGLF_APIENTRYP deleteShader)(GLuint shader); + void (QGLF_APIENTRYP detachShader)(GLuint program, GLuint shader); + void (QGLF_APIENTRYP disableVertexAttribArray)(GLuint index); + void (QGLF_APIENTRYP enableVertexAttribArray)(GLuint index); + void (QGLF_APIENTRYP framebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + void (QGLF_APIENTRYP framebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + void (QGLF_APIENTRYP genBuffers)(GLsizei n, GLuint* buffers); + void (QGLF_APIENTRYP generateMipmap)(GLenum target); + void (QGLF_APIENTRYP genFramebuffers)(GLsizei n, GLuint* framebuffers); + void (QGLF_APIENTRYP genRenderbuffers)(GLsizei n, GLuint* renderbuffers); + void (QGLF_APIENTRYP getActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + void (QGLF_APIENTRYP getActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + void (QGLF_APIENTRYP getAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); + int (QGLF_APIENTRYP getAttribLocation)(GLuint program, const char* name); + void (QGLF_APIENTRYP getBufferParameteriv)(GLenum target, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getProgramiv)(GLuint program, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog); + void (QGLF_APIENTRYP getRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getShaderiv)(GLuint shader, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog); + void (QGLF_APIENTRYP getShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); + void (QGLF_APIENTRYP getShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, char* source); + void (QGLF_APIENTRYP getUniformfv)(GLuint program, GLint location, GLfloat* params); + void (QGLF_APIENTRYP getUniformiv)(GLuint program, GLint location, GLint* params); + int (QGLF_APIENTRYP getUniformLocation)(GLuint program, const char* name); + void (QGLF_APIENTRYP getVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params); + void (QGLF_APIENTRYP getVertexAttribiv)(GLuint index, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getVertexAttribPointerv)(GLuint index, GLenum pname, void** pointer); + GLboolean (QGLF_APIENTRYP isBuffer)(GLuint buffer); + GLboolean (QGLF_APIENTRYP isFramebuffer)(GLuint framebuffer); + GLboolean (QGLF_APIENTRYP isProgram)(GLuint program); + GLboolean (QGLF_APIENTRYP isRenderbuffer)(GLuint renderbuffer); + GLboolean (QGLF_APIENTRYP isShader)(GLuint shader); + void (QGLF_APIENTRYP linkProgram)(GLuint program); + void (QGLF_APIENTRYP releaseShaderCompiler)(); + void (QGLF_APIENTRYP renderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + void (QGLF_APIENTRYP sampleCoverage)(GLclampf value, GLboolean invert); + void (QGLF_APIENTRYP shaderBinary)(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length); + void (QGLF_APIENTRYP shaderSource)(GLuint shader, GLsizei count, const char** string, const GLint* length); + void (QGLF_APIENTRYP stencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask); + void (QGLF_APIENTRYP stencilMaskSeparate)(GLenum face, GLuint mask); + void (QGLF_APIENTRYP stencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); + void (QGLF_APIENTRYP uniform1f)(GLint location, GLfloat x); + void (QGLF_APIENTRYP uniform1fv)(GLint location, GLsizei count, const GLfloat* v); + void (QGLF_APIENTRYP uniform1i)(GLint location, GLint x); + void (QGLF_APIENTRYP uniform1iv)(GLint location, GLsizei count, const GLint* v); + void (QGLF_APIENTRYP uniform2f)(GLint location, GLfloat x, GLfloat y); + void (QGLF_APIENTRYP uniform2fv)(GLint location, GLsizei count, const GLfloat* v); + void (QGLF_APIENTRYP uniform2i)(GLint location, GLint x, GLint y); + void (QGLF_APIENTRYP uniform2iv)(GLint location, GLsizei count, const GLint* v); + void (QGLF_APIENTRYP uniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z); + void (QGLF_APIENTRYP uniform3fv)(GLint location, GLsizei count, const GLfloat* v); + void (QGLF_APIENTRYP uniform3i)(GLint location, GLint x, GLint y, GLint z); + void (QGLF_APIENTRYP uniform3iv)(GLint location, GLsizei count, const GLint* v); + void (QGLF_APIENTRYP uniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (QGLF_APIENTRYP uniform4fv)(GLint location, GLsizei count, const GLfloat* v); + void (QGLF_APIENTRYP uniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w); + void (QGLF_APIENTRYP uniform4iv)(GLint location, GLsizei count, const GLint* v); + void (QGLF_APIENTRYP uniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void (QGLF_APIENTRYP uniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void (QGLF_APIENTRYP uniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void (QGLF_APIENTRYP useProgram)(GLuint program); + void (QGLF_APIENTRYP validateProgram)(GLuint program); + void (QGLF_APIENTRYP vertexAttrib1f)(GLuint indx, GLfloat x); + void (QGLF_APIENTRYP vertexAttrib1fv)(GLuint indx, const GLfloat* values); + void (QGLF_APIENTRYP vertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y); + void (QGLF_APIENTRYP vertexAttrib2fv)(GLuint indx, const GLfloat* values); + void (QGLF_APIENTRYP vertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z); + void (QGLF_APIENTRYP vertexAttrib3fv)(GLuint indx, const GLfloat* values); + void (QGLF_APIENTRYP vertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (QGLF_APIENTRYP vertexAttrib4fv)(GLuint indx, const GLfloat* values); + void (QGLF_APIENTRYP vertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr); +#endif +}; + +inline void QGLFunctions::glActiveTexture(GLenum texture) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glActiveTexture(texture); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->activeTexture(texture); +#endif +} + +inline void QGLFunctions::glAttachShader(GLuint program, GLuint shader) +{ +#if defined(QT_OPENGL_ES_2) + ::glAttachShader(program, shader); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->attachShader(program, shader); +#endif +} + +inline void QGLFunctions::glBindAttribLocation(GLuint program, GLuint index, const char* name) +{ +#if defined(QT_OPENGL_ES_2) + ::glBindAttribLocation(program, index, name); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bindAttribLocation(program, index, name); +#endif +} + +inline void QGLFunctions::glBindBuffer(GLenum target, GLuint buffer) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glBindBuffer(target, buffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bindBuffer(target, buffer); +#endif +} + +inline void QGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer) +{ +#if defined(QT_OPENGL_ES_2) + ::glBindFramebuffer(target, framebuffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bindFramebuffer(target, framebuffer); +#endif +} + +inline void QGLFunctions::glBindRenderbuffer(GLenum target, GLuint renderbuffer) +{ +#if defined(QT_OPENGL_ES_2) + ::glBindRenderbuffer(target, renderbuffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bindRenderbuffer(target, renderbuffer); +#endif +} + +inline void QGLFunctions::glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ +#if defined(QT_OPENGL_ES_2) + ::glBlendColor(red, green, blue, alpha); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->blendColor(red, green, blue, alpha); +#endif +} + +inline void QGLFunctions::glBlendEquation(GLenum mode) +{ +#if defined(QT_OPENGL_ES_2) + ::glBlendEquation(mode); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->blendEquation(mode); +#endif +} + +inline void QGLFunctions::glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +{ +#if defined(QT_OPENGL_ES_2) + ::glBlendEquationSeparate(modeRGB, modeAlpha); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->blendEquationSeparate(modeRGB, modeAlpha); +#endif +} + +inline void QGLFunctions::glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +{ +#if defined(QT_OPENGL_ES_2) + ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); +#endif +} + +inline void QGLFunctions::glBufferData(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glBufferData(target, size, data, usage); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bufferData(target, size, data, usage); +#endif +} + +inline void QGLFunctions::glBufferSubData(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glBufferSubData(target, offset, size, data); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bufferSubData(target, offset, size, data); +#endif +} + +inline GLenum QGLFunctions::glCheckFramebufferStatus(GLenum target) +{ +#if defined(QT_OPENGL_ES_2) + return ::glCheckFramebufferStatus(target); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->checkFramebufferStatus(target); +#endif +} + +inline void QGLFunctions::glClearDepthf(GLclampf depth) +{ +#ifndef QT_OPENGL_ES + ::glClearDepth(depth); +#else + ::glClearDepthf(depth); +#endif +} + +inline void QGLFunctions::glCompileShader(GLuint shader) +{ +#if defined(QT_OPENGL_ES_2) + ::glCompileShader(shader); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->compileShader(shader); +#endif +} + +inline void QGLFunctions::glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->compressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); +#endif +} + +inline void QGLFunctions::glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); +#endif +} + +inline GLuint QGLFunctions::glCreateProgram() +{ +#if defined(QT_OPENGL_ES_2) + return ::glCreateProgram(); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->createProgram(); +#endif +} + +inline GLuint QGLFunctions::glCreateShader(GLenum type) +{ +#if defined(QT_OPENGL_ES_2) + return ::glCreateShader(type); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->createShader(type); +#endif +} + +inline void QGLFunctions::glDeleteBuffers(GLsizei n, const GLuint* buffers) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glDeleteBuffers(n, buffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->deleteBuffers(n, buffers); +#endif +} + +inline void QGLFunctions::glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) +{ +#if defined(QT_OPENGL_ES_2) + ::glDeleteFramebuffers(n, framebuffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->deleteFramebuffers(n, framebuffers); +#endif +} + +inline void QGLFunctions::glDeleteProgram(GLuint program) +{ +#if defined(QT_OPENGL_ES_2) + ::glDeleteProgram(program); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->deleteProgram(program); +#endif +} + +inline void QGLFunctions::glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) +{ +#if defined(QT_OPENGL_ES_2) + ::glDeleteRenderbuffers(n, renderbuffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->deleteRenderbuffers(n, renderbuffers); +#endif +} + +inline void QGLFunctions::glDeleteShader(GLuint shader) +{ +#if defined(QT_OPENGL_ES_2) + ::glDeleteShader(shader); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->deleteShader(shader); +#endif +} + +inline void QGLFunctions::glDepthRangef(GLclampf zNear, GLclampf zFar) +{ +#ifndef QT_OPENGL_ES + ::glDepthRange(zNear, zFar); +#else + ::glDepthRangef(zNear, zFar); +#endif +} + +inline void QGLFunctions::glDetachShader(GLuint program, GLuint shader) +{ +#if defined(QT_OPENGL_ES_2) + ::glDetachShader(program, shader); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->detachShader(program, shader); +#endif +} + +inline void QGLFunctions::glDisableVertexAttribArray(GLuint index) +{ +#if defined(QT_OPENGL_ES_2) + ::glDisableVertexAttribArray(index); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->disableVertexAttribArray(index); +#endif +} + +inline void QGLFunctions::glEnableVertexAttribArray(GLuint index) +{ +#if defined(QT_OPENGL_ES_2) + ::glEnableVertexAttribArray(index); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->enableVertexAttribArray(index); +#endif +} + +inline void QGLFunctions::glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ +#if defined(QT_OPENGL_ES_2) + ::glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); +#endif +} + +inline void QGLFunctions::glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ +#if defined(QT_OPENGL_ES_2) + ::glFramebufferTexture2D(target, attachment, textarget, texture, level); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->framebufferTexture2D(target, attachment, textarget, texture, level); +#endif +} + +inline void QGLFunctions::glGenBuffers(GLsizei n, GLuint* buffers) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glGenBuffers(n, buffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->genBuffers(n, buffers); +#endif +} + +inline void QGLFunctions::glGenerateMipmap(GLenum target) +{ +#if defined(QT_OPENGL_ES_2) + ::glGenerateMipmap(target); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->generateMipmap(target); +#endif +} + +inline void QGLFunctions::glGenFramebuffers(GLsizei n, GLuint* framebuffers) +{ +#if defined(QT_OPENGL_ES_2) + ::glGenFramebuffers(n, framebuffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->genFramebuffers(n, framebuffers); +#endif +} + +inline void QGLFunctions::glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) +{ +#if defined(QT_OPENGL_ES_2) + ::glGenRenderbuffers(n, renderbuffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->genRenderbuffers(n, renderbuffers); +#endif +} + +inline void QGLFunctions::glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetActiveAttrib(program, index, bufsize, length, size, type, name); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getActiveAttrib(program, index, bufsize, length, size, type, name); +#endif +} + +inline void QGLFunctions::glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetActiveUniform(program, index, bufsize, length, size, type, name); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getActiveUniform(program, index, bufsize, length, size, type, name); +#endif +} + +inline void QGLFunctions::glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetAttachedShaders(program, maxcount, count, shaders); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getAttachedShaders(program, maxcount, count, shaders); +#endif +} + +inline int QGLFunctions::glGetAttribLocation(GLuint program, const char* name) +{ +#if defined(QT_OPENGL_ES_2) + return ::glGetAttribLocation(program, name); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->getAttribLocation(program, name); +#endif +} + +inline void QGLFunctions::glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetBufferParameteriv(target, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getBufferParameteriv(target, pname, params); +#endif +} + +inline void QGLFunctions::glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetFramebufferAttachmentParameteriv(target, attachment, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getFramebufferAttachmentParameteriv(target, attachment, pname, params); +#endif +} + +inline void QGLFunctions::glGetProgramiv(GLuint program, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetProgramiv(program, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getProgramiv(program, pname, params); +#endif +} + +inline void QGLFunctions::glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetProgramInfoLog(program, bufsize, length, infolog); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getProgramInfoLog(program, bufsize, length, infolog); +#endif +} + +inline void QGLFunctions::glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetRenderbufferParameteriv(target, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getRenderbufferParameteriv(target, pname, params); +#endif +} + +inline void QGLFunctions::glGetShaderiv(GLuint shader, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetShaderiv(shader, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getShaderiv(shader, pname, params); +#endif +} + +inline void QGLFunctions::glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetShaderInfoLog(shader, bufsize, length, infolog); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getShaderInfoLog(shader, bufsize, length, infolog); +#endif +} + +inline void QGLFunctions::glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getShaderPrecisionFormat(shadertype, precisiontype, range, precision); +#endif +} + +inline void QGLFunctions::glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetShaderSource(shader, bufsize, length, source); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getShaderSource(shader, bufsize, length, source); +#endif +} + +inline void QGLFunctions::glGetUniformfv(GLuint program, GLint location, GLfloat* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetUniformfv(program, location, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getUniformfv(program, location, params); +#endif +} + +inline void QGLFunctions::glGetUniformiv(GLuint program, GLint location, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetUniformiv(program, location, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getUniformiv(program, location, params); +#endif +} + +inline int QGLFunctions::glGetUniformLocation(GLuint program, const char* name) +{ +#if defined(QT_OPENGL_ES_2) + return ::glGetUniformLocation(program, name); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->getUniformLocation(program, name); +#endif +} + +inline void QGLFunctions::glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetVertexAttribfv(index, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getVertexAttribfv(index, pname, params); +#endif +} + +inline void QGLFunctions::glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetVertexAttribiv(index, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getVertexAttribiv(index, pname, params); +#endif +} + +inline void QGLFunctions::glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetVertexAttribPointerv(index, pname, pointer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getVertexAttribPointerv(index, pname, pointer); +#endif +} + +inline GLboolean QGLFunctions::glIsBuffer(GLuint buffer) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + return ::glIsBuffer(buffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->isBuffer(buffer); +#endif +} + +inline GLboolean QGLFunctions::glIsFramebuffer(GLuint framebuffer) +{ +#if defined(QT_OPENGL_ES_2) + return ::glIsFramebuffer(framebuffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->isFramebuffer(framebuffer); +#endif +} + +inline GLboolean QGLFunctions::glIsProgram(GLuint program) +{ +#if defined(QT_OPENGL_ES_2) + return ::glIsProgram(program); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->isProgram(program); +#endif +} + +inline GLboolean QGLFunctions::glIsRenderbuffer(GLuint renderbuffer) +{ +#if defined(QT_OPENGL_ES_2) + return ::glIsRenderbuffer(renderbuffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->isRenderbuffer(renderbuffer); +#endif +} + +inline GLboolean QGLFunctions::glIsShader(GLuint shader) +{ +#if defined(QT_OPENGL_ES_2) + return ::glIsShader(shader); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->isShader(shader); +#endif +} + +inline void QGLFunctions::glLinkProgram(GLuint program) +{ +#if defined(QT_OPENGL_ES_2) + ::glLinkProgram(program); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->linkProgram(program); +#endif +} + +inline void QGLFunctions::glReleaseShaderCompiler() +{ +#if defined(QT_OPENGL_ES_2) + ::glReleaseShaderCompiler(); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->releaseShaderCompiler(); +#endif +} + +inline void QGLFunctions::glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ +#if defined(QT_OPENGL_ES_2) + ::glRenderbufferStorage(target, internalformat, width, height); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->renderbufferStorage(target, internalformat, width, height); +#endif +} + +inline void QGLFunctions::glSampleCoverage(GLclampf value, GLboolean invert) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glSampleCoverage(value, invert); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->sampleCoverage(value, invert); +#endif +} + +inline void QGLFunctions::glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length) +{ +#if defined(QT_OPENGL_ES_2) + ::glShaderBinary(n, shaders, binaryformat, binary, length); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->shaderBinary(n, shaders, binaryformat, binary, length); +#endif +} + +inline void QGLFunctions::glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length) +{ +#if defined(QT_OPENGL_ES_2) + ::glShaderSource(shader, count, string, length); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->shaderSource(shader, count, string, length); +#endif +} + +inline void QGLFunctions::glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ +#if defined(QT_OPENGL_ES_2) + ::glStencilFuncSeparate(face, func, ref, mask); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->stencilFuncSeparate(face, func, ref, mask); +#endif +} + +inline void QGLFunctions::glStencilMaskSeparate(GLenum face, GLuint mask) +{ +#if defined(QT_OPENGL_ES_2) + ::glStencilMaskSeparate(face, mask); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->stencilMaskSeparate(face, mask); +#endif +} + +inline void QGLFunctions::glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ +#if defined(QT_OPENGL_ES_2) + ::glStencilOpSeparate(face, fail, zfail, zpass); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->stencilOpSeparate(face, fail, zfail, zpass); +#endif +} + +inline void QGLFunctions::glUniform1f(GLint location, GLfloat x) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform1f(location, x); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform1f(location, x); +#endif +} + +inline void QGLFunctions::glUniform1fv(GLint location, GLsizei count, const GLfloat* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform1fv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform1fv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform1i(GLint location, GLint x) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform1i(location, x); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform1i(location, x); +#endif +} + +inline void QGLFunctions::glUniform1iv(GLint location, GLsizei count, const GLint* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform1iv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform1iv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform2f(GLint location, GLfloat x, GLfloat y) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform2f(location, x, y); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform2f(location, x, y); +#endif +} + +inline void QGLFunctions::glUniform2fv(GLint location, GLsizei count, const GLfloat* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform2fv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform2fv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform2i(GLint location, GLint x, GLint y) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform2i(location, x, y); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform2i(location, x, y); +#endif +} + +inline void QGLFunctions::glUniform2iv(GLint location, GLsizei count, const GLint* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform2iv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform2iv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform3f(location, x, y, z); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform3f(location, x, y, z); +#endif +} + +inline void QGLFunctions::glUniform3fv(GLint location, GLsizei count, const GLfloat* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform3fv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform3fv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform3i(GLint location, GLint x, GLint y, GLint z) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform3i(location, x, y, z); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform3i(location, x, y, z); +#endif +} + +inline void QGLFunctions::glUniform3iv(GLint location, GLsizei count, const GLint* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform3iv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform3iv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform4f(location, x, y, z, w); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform4f(location, x, y, z, w); +#endif +} + +inline void QGLFunctions::glUniform4fv(GLint location, GLsizei count, const GLfloat* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform4fv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform4fv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform4i(location, x, y, z, w); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform4i(location, x, y, z, w); +#endif +} + +inline void QGLFunctions::glUniform4iv(GLint location, GLsizei count, const GLint* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform4iv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform4iv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniformMatrix2fv(location, count, transpose, value); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniformMatrix2fv(location, count, transpose, value); +#endif +} + +inline void QGLFunctions::glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniformMatrix3fv(location, count, transpose, value); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniformMatrix3fv(location, count, transpose, value); +#endif +} + +inline void QGLFunctions::glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniformMatrix4fv(location, count, transpose, value); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniformMatrix4fv(location, count, transpose, value); +#endif +} + +inline void QGLFunctions::glUseProgram(GLuint program) +{ +#if defined(QT_OPENGL_ES_2) + ::glUseProgram(program); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->useProgram(program); +#endif +} + +inline void QGLFunctions::glValidateProgram(GLuint program) +{ +#if defined(QT_OPENGL_ES_2) + ::glValidateProgram(program); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->validateProgram(program); +#endif +} + +inline void QGLFunctions::glVertexAttrib1f(GLuint indx, GLfloat x) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib1f(indx, x); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib1f(indx, x); +#endif +} + +inline void QGLFunctions::glVertexAttrib1fv(GLuint indx, const GLfloat* values) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib1fv(indx, values); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib1fv(indx, values); +#endif +} + +inline void QGLFunctions::glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib2f(indx, x, y); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib2f(indx, x, y); +#endif +} + +inline void QGLFunctions::glVertexAttrib2fv(GLuint indx, const GLfloat* values) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib2fv(indx, values); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib2fv(indx, values); +#endif +} + +inline void QGLFunctions::glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib3f(indx, x, y, z); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib3f(indx, x, y, z); +#endif +} + +inline void QGLFunctions::glVertexAttrib3fv(GLuint indx, const GLfloat* values) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib3fv(indx, values); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib3fv(indx, values); +#endif +} + +inline void QGLFunctions::glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib4f(indx, x, y, z, w); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib4f(indx, x, y, z, w); +#endif +} + +inline void QGLFunctions::glVertexAttrib4fv(GLuint indx, const GLfloat* values) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib4fv(indx, values); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib4fv(indx, values); +#endif +} + +inline void QGLFunctions::glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttribPointer(indx, size, type, normalized, stride, ptr); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttribPointer(indx, size, type, normalized, stride, ptr); +#endif +} + +#ifndef GL_ACTIVE_ATTRIBUTE_MAX_LENGTH +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#endif +#ifndef GL_ACTIVE_ATTRIBUTES +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#endif +#ifndef GL_ACTIVE_TEXTURE +#define GL_ACTIVE_TEXTURE 0x84E0 +#endif +#ifndef GL_ACTIVE_UNIFORM_MAX_LENGTH +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#endif +#ifndef GL_ACTIVE_UNIFORMS +#define GL_ACTIVE_UNIFORMS 0x8B86 +#endif +#ifndef GL_ALIASED_LINE_WIDTH_RANGE +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#endif +#ifndef GL_ALIASED_POINT_SIZE_RANGE +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#endif +#ifndef GL_ALPHA +#define GL_ALPHA 0x1906 +#endif +#ifndef GL_ALPHA_BITS +#define GL_ALPHA_BITS 0x0D55 +#endif +#ifndef GL_ALWAYS +#define GL_ALWAYS 0x0207 +#endif +#ifndef GL_ARRAY_BUFFER +#define GL_ARRAY_BUFFER 0x8892 +#endif +#ifndef GL_ARRAY_BUFFER_BINDING +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#endif +#ifndef GL_ATTACHED_SHADERS +#define GL_ATTACHED_SHADERS 0x8B85 +#endif +#ifndef GL_BACK +#define GL_BACK 0x0405 +#endif +#ifndef GL_BLEND +#define GL_BLEND 0x0BE2 +#endif +#ifndef GL_BLEND_COLOR +#define GL_BLEND_COLOR 0x8005 +#endif +#ifndef GL_BLEND_DST_ALPHA +#define GL_BLEND_DST_ALPHA 0x80CA +#endif +#ifndef GL_BLEND_DST_RGB +#define GL_BLEND_DST_RGB 0x80C8 +#endif +#ifndef GL_BLEND_EQUATION +#define GL_BLEND_EQUATION 0x8009 +#endif +#ifndef GL_BLEND_EQUATION_ALPHA +#define GL_BLEND_EQUATION_ALPHA 0x883D +#endif +#ifndef GL_BLEND_EQUATION_RGB +#define GL_BLEND_EQUATION_RGB 0x8009 +#endif +#ifndef GL_BLEND_SRC_ALPHA +#define GL_BLEND_SRC_ALPHA 0x80CB +#endif +#ifndef GL_BLEND_SRC_RGB +#define GL_BLEND_SRC_RGB 0x80C9 +#endif +#ifndef GL_BLUE_BITS +#define GL_BLUE_BITS 0x0D54 +#endif +#ifndef GL_BOOL +#define GL_BOOL 0x8B56 +#endif +#ifndef GL_BOOL_VEC2 +#define GL_BOOL_VEC2 0x8B57 +#endif +#ifndef GL_BOOL_VEC3 +#define GL_BOOL_VEC3 0x8B58 +#endif +#ifndef GL_BOOL_VEC4 +#define GL_BOOL_VEC4 0x8B59 +#endif +#ifndef GL_BUFFER_SIZE +#define GL_BUFFER_SIZE 0x8764 +#endif +#ifndef GL_BUFFER_USAGE +#define GL_BUFFER_USAGE 0x8765 +#endif +#ifndef GL_BYTE +#define GL_BYTE 0x1400 +#endif +#ifndef GL_CCW +#define GL_CCW 0x0901 +#endif +#ifndef GL_CLAMP_TO_EDGE +#define GL_CLAMP_TO_EDGE 0x812F +#endif +#ifndef GL_COLOR_ATTACHMENT0 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#endif +#ifndef GL_COLOR_BUFFER_BIT +#define GL_COLOR_BUFFER_BIT 0x00004000 +#endif +#ifndef GL_COLOR_CLEAR_VALUE +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#endif +#ifndef GL_COLOR_WRITEMASK +#define GL_COLOR_WRITEMASK 0x0C23 +#endif +#ifndef GL_COMPILE_STATUS +#define GL_COMPILE_STATUS 0x8B81 +#endif +#ifndef GL_COMPRESSED_TEXTURE_FORMATS +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#endif +#ifndef GL_CONSTANT_ALPHA +#define GL_CONSTANT_ALPHA 0x8003 +#endif +#ifndef GL_CONSTANT_COLOR +#define GL_CONSTANT_COLOR 0x8001 +#endif +#ifndef GL_CULL_FACE +#define GL_CULL_FACE 0x0B44 +#endif +#ifndef GL_CULL_FACE_MODE +#define GL_CULL_FACE_MODE 0x0B45 +#endif +#ifndef GL_CURRENT_PROGRAM +#define GL_CURRENT_PROGRAM 0x8B8D +#endif +#ifndef GL_CURRENT_VERTEX_ATTRIB +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#endif +#ifndef GL_CW +#define GL_CW 0x0900 +#endif +#ifndef GL_DECR +#define GL_DECR 0x1E03 +#endif +#ifndef GL_DECR_WRAP +#define GL_DECR_WRAP 0x8508 +#endif +#ifndef GL_DELETE_STATUS +#define GL_DELETE_STATUS 0x8B80 +#endif +#ifndef GL_DEPTH_ATTACHMENT +#define GL_DEPTH_ATTACHMENT 0x8D00 +#endif +#ifndef GL_DEPTH_BITS +#define GL_DEPTH_BITS 0x0D56 +#endif +#ifndef GL_DEPTH_BUFFER_BIT +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#endif +#ifndef GL_DEPTH_CLEAR_VALUE +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#endif +#ifndef GL_DEPTH_COMPONENT +#define GL_DEPTH_COMPONENT 0x1902 +#endif +#ifndef GL_DEPTH_COMPONENT16 +#define GL_DEPTH_COMPONENT16 0x81A5 +#endif +#ifndef GL_DEPTH_FUNC +#define GL_DEPTH_FUNC 0x0B74 +#endif +#ifndef GL_DEPTH_RANGE +#define GL_DEPTH_RANGE 0x0B70 +#endif +#ifndef GL_DEPTH_TEST +#define GL_DEPTH_TEST 0x0B71 +#endif +#ifndef GL_DEPTH_WRITEMASK +#define GL_DEPTH_WRITEMASK 0x0B72 +#endif +#ifndef GL_DITHER +#define GL_DITHER 0x0BD0 +#endif +#ifndef GL_DONT_CARE +#define GL_DONT_CARE 0x1100 +#endif +#ifndef GL_DST_ALPHA +#define GL_DST_ALPHA 0x0304 +#endif +#ifndef GL_DST_COLOR +#define GL_DST_COLOR 0x0306 +#endif +#ifndef GL_DYNAMIC_DRAW +#define GL_DYNAMIC_DRAW 0x88E8 +#endif +#ifndef GL_ELEMENT_ARRAY_BUFFER +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#endif +#ifndef GL_ELEMENT_ARRAY_BUFFER_BINDING +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#endif +#ifndef GL_EQUAL +#define GL_EQUAL 0x0202 +#endif +#ifndef GL_EXTENSIONS +#define GL_EXTENSIONS 0x1F03 +#endif +#ifndef GL_FALSE +#define GL_FALSE 0 +#endif +#ifndef GL_FASTEST +#define GL_FASTEST 0x1101 +#endif +#ifndef GL_FIXED +#define GL_FIXED 0x140C +#endif +#ifndef GL_FLOAT +#define GL_FLOAT 0x1406 +#endif +#ifndef GL_FLOAT_MAT2 +#define GL_FLOAT_MAT2 0x8B5A +#endif +#ifndef GL_FLOAT_MAT3 +#define GL_FLOAT_MAT3 0x8B5B +#endif +#ifndef GL_FLOAT_MAT4 +#define GL_FLOAT_MAT4 0x8B5C +#endif +#ifndef GL_FLOAT_VEC2 +#define GL_FLOAT_VEC2 0x8B50 +#endif +#ifndef GL_FLOAT_VEC3 +#define GL_FLOAT_VEC3 0x8B51 +#endif +#ifndef GL_FLOAT_VEC4 +#define GL_FLOAT_VEC4 0x8B52 +#endif +#ifndef GL_FRAGMENT_SHADER +#define GL_FRAGMENT_SHADER 0x8B30 +#endif +#ifndef GL_FRAMEBUFFER +#define GL_FRAMEBUFFER 0x8D40 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#endif +#ifndef GL_FRAMEBUFFER_BINDING +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#endif +#ifndef GL_FRAMEBUFFER_COMPLETE +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#endif +#ifndef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#endif +#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#endif +#ifndef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#endif +#ifndef GL_FRAMEBUFFER_UNSUPPORTED +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#endif +#ifndef GL_FRONT +#define GL_FRONT 0x0404 +#endif +#ifndef GL_FRONT_AND_BACK +#define GL_FRONT_AND_BACK 0x0408 +#endif +#ifndef GL_FRONT_FACE +#define GL_FRONT_FACE 0x0B46 +#endif +#ifndef GL_FUNC_ADD +#define GL_FUNC_ADD 0x8006 +#endif +#ifndef GL_FUNC_REVERSE_SUBTRACT +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#endif +#ifndef GL_FUNC_SUBTRACT +#define GL_FUNC_SUBTRACT 0x800A +#endif +#ifndef GL_GENERATE_MIPMAP_HINT +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#endif +#ifndef GL_GEQUAL +#define GL_GEQUAL 0x0206 +#endif +#ifndef GL_GREATER +#define GL_GREATER 0x0204 +#endif +#ifndef GL_GREEN_BITS +#define GL_GREEN_BITS 0x0D53 +#endif +#ifndef GL_HIGH_FLOAT +#define GL_HIGH_FLOAT 0x8DF2 +#endif +#ifndef GL_HIGH_INT +#define GL_HIGH_INT 0x8DF5 +#endif +#ifndef GL_IMPLEMENTATION_COLOR_READ_FORMAT +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#endif +#ifndef GL_IMPLEMENTATION_COLOR_READ_TYPE +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#endif +#ifndef GL_INCR +#define GL_INCR 0x1E02 +#endif +#ifndef GL_INCR_WRAP +#define GL_INCR_WRAP 0x8507 +#endif +#ifndef GL_INFO_LOG_LENGTH +#define GL_INFO_LOG_LENGTH 0x8B84 +#endif +#ifndef GL_INT +#define GL_INT 0x1404 +#endif +#ifndef GL_INT_VEC2 +#define GL_INT_VEC2 0x8B53 +#endif +#ifndef GL_INT_VEC3 +#define GL_INT_VEC3 0x8B54 +#endif +#ifndef GL_INT_VEC4 +#define GL_INT_VEC4 0x8B55 +#endif +#ifndef GL_INVALID_ENUM +#define GL_INVALID_ENUM 0x0500 +#endif +#ifndef GL_INVALID_FRAMEBUFFER_OPERATION +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#endif +#ifndef GL_INVALID_OPERATION +#define GL_INVALID_OPERATION 0x0502 +#endif +#ifndef GL_INVALID_VALUE +#define GL_INVALID_VALUE 0x0501 +#endif +#ifndef GL_INVERT +#define GL_INVERT 0x150A +#endif +#ifndef GL_KEEP +#define GL_KEEP 0x1E00 +#endif +#ifndef GL_LEQUAL +#define GL_LEQUAL 0x0203 +#endif +#ifndef GL_LESS +#define GL_LESS 0x0201 +#endif +#ifndef GL_LINEAR +#define GL_LINEAR 0x2601 +#endif +#ifndef GL_LINEAR_MIPMAP_LINEAR +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#endif +#ifndef GL_LINEAR_MIPMAP_NEAREST +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#endif +#ifndef GL_LINE_LOOP +#define GL_LINE_LOOP 0x0002 +#endif +#ifndef GL_LINES +#define GL_LINES 0x0001 +#endif +#ifndef GL_LINE_STRIP +#define GL_LINE_STRIP 0x0003 +#endif +#ifndef GL_LINE_WIDTH +#define GL_LINE_WIDTH 0x0B21 +#endif +#ifndef GL_LINK_STATUS +#define GL_LINK_STATUS 0x8B82 +#endif +#ifndef GL_LOW_FLOAT +#define GL_LOW_FLOAT 0x8DF0 +#endif +#ifndef GL_LOW_INT +#define GL_LOW_INT 0x8DF3 +#endif +#ifndef GL_LUMINANCE +#define GL_LUMINANCE 0x1909 +#endif +#ifndef GL_LUMINANCE_ALPHA +#define GL_LUMINANCE_ALPHA 0x190A +#endif +#ifndef GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#endif +#ifndef GL_MAX_CUBE_MAP_TEXTURE_SIZE +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#endif +#ifndef GL_MAX_FRAGMENT_UNIFORM_VECTORS +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#endif +#ifndef GL_MAX_RENDERBUFFER_SIZE +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#endif +#ifndef GL_MAX_TEXTURE_IMAGE_UNITS +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#endif +#ifndef GL_MAX_TEXTURE_SIZE +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#endif +#ifndef GL_MAX_VARYING_VECTORS +#define GL_MAX_VARYING_VECTORS 0x8DFC +#endif +#ifndef GL_MAX_VERTEX_ATTRIBS +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#endif +#ifndef GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#endif +#ifndef GL_MAX_VERTEX_UNIFORM_VECTORS +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#endif +#ifndef GL_MAX_VIEWPORT_DIMS +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#endif +#ifndef GL_MEDIUM_FLOAT +#define GL_MEDIUM_FLOAT 0x8DF1 +#endif +#ifndef GL_MEDIUM_INT +#define GL_MEDIUM_INT 0x8DF4 +#endif +#ifndef GL_MIRRORED_REPEAT +#define GL_MIRRORED_REPEAT 0x8370 +#endif +#ifndef GL_NEAREST +#define GL_NEAREST 0x2600 +#endif +#ifndef GL_NEAREST_MIPMAP_LINEAR +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#endif +#ifndef GL_NEAREST_MIPMAP_NEAREST +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#endif +#ifndef GL_NEVER +#define GL_NEVER 0x0200 +#endif +#ifndef GL_NICEST +#define GL_NICEST 0x1102 +#endif +#ifndef GL_NO_ERROR +#define GL_NO_ERROR 0 +#endif +#ifndef GL_NONE +#define GL_NONE 0 +#endif +#ifndef GL_NOTEQUAL +#define GL_NOTEQUAL 0x0205 +#endif +#ifndef GL_NUM_COMPRESSED_TEXTURE_FORMATS +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#endif +#ifndef GL_NUM_SHADER_BINARY_FORMATS +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#endif +#ifndef GL_ONE +#define GL_ONE 1 +#endif +#ifndef GL_ONE_MINUS_CONSTANT_ALPHA +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#endif +#ifndef GL_ONE_MINUS_CONSTANT_COLOR +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#endif +#ifndef GL_ONE_MINUS_DST_ALPHA +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#endif +#ifndef GL_ONE_MINUS_DST_COLOR +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#endif +#ifndef GL_ONE_MINUS_SRC_ALPHA +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#endif +#ifndef GL_ONE_MINUS_SRC_COLOR +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#endif +#ifndef GL_OUT_OF_MEMORY +#define GL_OUT_OF_MEMORY 0x0505 +#endif +#ifndef GL_PACK_ALIGNMENT +#define GL_PACK_ALIGNMENT 0x0D05 +#endif +#ifndef GL_POINTS +#define GL_POINTS 0x0000 +#endif +#ifndef GL_POLYGON_OFFSET_FACTOR +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#endif +#ifndef GL_POLYGON_OFFSET_FILL +#define GL_POLYGON_OFFSET_FILL 0x8037 +#endif +#ifndef GL_POLYGON_OFFSET_UNITS +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#endif +#ifndef GL_RED_BITS +#define GL_RED_BITS 0x0D52 +#endif +#ifndef GL_RENDERBUFFER +#define GL_RENDERBUFFER 0x8D41 +#endif +#ifndef GL_RENDERBUFFER_ALPHA_SIZE +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#endif +#ifndef GL_RENDERBUFFER_BINDING +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#endif +#ifndef GL_RENDERBUFFER_BLUE_SIZE +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#endif +#ifndef GL_RENDERBUFFER_DEPTH_SIZE +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#endif +#ifndef GL_RENDERBUFFER_GREEN_SIZE +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#endif +#ifndef GL_RENDERBUFFER_HEIGHT +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#endif +#ifndef GL_RENDERBUFFER_INTERNAL_FORMAT +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#endif +#ifndef GL_RENDERBUFFER_RED_SIZE +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#endif +#ifndef GL_RENDERBUFFER_STENCIL_SIZE +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#endif +#ifndef GL_RENDERBUFFER_WIDTH +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#endif +#ifndef GL_RENDERER +#define GL_RENDERER 0x1F01 +#endif +#ifndef GL_REPEAT +#define GL_REPEAT 0x2901 +#endif +#ifndef GL_REPLACE +#define GL_REPLACE 0x1E01 +#endif +#ifndef GL_RGB +#define GL_RGB 0x1907 +#endif +#ifndef GL_RGB565 +#define GL_RGB565 0x8D62 +#endif +#ifndef GL_RGB5_A1 +#define GL_RGB5_A1 0x8057 +#endif +#ifndef GL_RGBA +#define GL_RGBA 0x1908 +#endif +#ifndef GL_RGBA4 +#define GL_RGBA4 0x8056 +#endif +#ifndef GL_SAMPLE_ALPHA_TO_COVERAGE +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#endif +#ifndef GL_SAMPLE_BUFFERS +#define GL_SAMPLE_BUFFERS 0x80A8 +#endif +#ifndef GL_SAMPLE_COVERAGE +#define GL_SAMPLE_COVERAGE 0x80A0 +#endif +#ifndef GL_SAMPLE_COVERAGE_INVERT +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#endif +#ifndef GL_SAMPLE_COVERAGE_VALUE +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#endif +#ifndef GL_SAMPLER_2D +#define GL_SAMPLER_2D 0x8B5E +#endif +#ifndef GL_SAMPLER_CUBE +#define GL_SAMPLER_CUBE 0x8B60 +#endif +#ifndef GL_SAMPLES +#define GL_SAMPLES 0x80A9 +#endif +#ifndef GL_SCISSOR_BOX +#define GL_SCISSOR_BOX 0x0C10 +#endif +#ifndef GL_SCISSOR_TEST +#define GL_SCISSOR_TEST 0x0C11 +#endif +#ifndef GL_SHADER_BINARY_FORMATS +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#endif +#ifndef GL_SHADER_COMPILER +#define GL_SHADER_COMPILER 0x8DFA +#endif +#ifndef GL_SHADER_SOURCE_LENGTH +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#endif +#ifndef GL_SHADER_TYPE +#define GL_SHADER_TYPE 0x8B4F +#endif +#ifndef GL_SHADING_LANGUAGE_VERSION +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#endif +#ifndef GL_SHORT +#define GL_SHORT 0x1402 +#endif +#ifndef GL_SRC_ALPHA +#define GL_SRC_ALPHA 0x0302 +#endif +#ifndef GL_SRC_ALPHA_SATURATE +#define GL_SRC_ALPHA_SATURATE 0x0308 +#endif +#ifndef GL_SRC_COLOR +#define GL_SRC_COLOR 0x0300 +#endif +#ifndef GL_STATIC_DRAW +#define GL_STATIC_DRAW 0x88E4 +#endif +#ifndef GL_STENCIL_ATTACHMENT +#define GL_STENCIL_ATTACHMENT 0x8D20 +#endif +#ifndef GL_STENCIL_BACK_FAIL +#define GL_STENCIL_BACK_FAIL 0x8801 +#endif +#ifndef GL_STENCIL_BACK_FUNC +#define GL_STENCIL_BACK_FUNC 0x8800 +#endif +#ifndef GL_STENCIL_BACK_PASS_DEPTH_FAIL +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#endif +#ifndef GL_STENCIL_BACK_PASS_DEPTH_PASS +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#endif +#ifndef GL_STENCIL_BACK_REF +#define GL_STENCIL_BACK_REF 0x8CA3 +#endif +#ifndef GL_STENCIL_BACK_VALUE_MASK +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#endif +#ifndef GL_STENCIL_BACK_WRITEMASK +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#endif +#ifndef GL_STENCIL_BITS +#define GL_STENCIL_BITS 0x0D57 +#endif +#ifndef GL_STENCIL_BUFFER_BIT +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#endif +#ifndef GL_STENCIL_CLEAR_VALUE +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#endif +#ifndef GL_STENCIL_FAIL +#define GL_STENCIL_FAIL 0x0B94 +#endif +#ifndef GL_STENCIL_FUNC +#define GL_STENCIL_FUNC 0x0B92 +#endif +#ifndef GL_STENCIL_INDEX +#define GL_STENCIL_INDEX 0x1901 +#endif +#ifndef GL_STENCIL_INDEX8 +#define GL_STENCIL_INDEX8 0x8D48 +#endif +#ifndef GL_STENCIL_PASS_DEPTH_FAIL +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#endif +#ifndef GL_STENCIL_PASS_DEPTH_PASS +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#endif +#ifndef GL_STENCIL_REF +#define GL_STENCIL_REF 0x0B97 +#endif +#ifndef GL_STENCIL_TEST +#define GL_STENCIL_TEST 0x0B90 +#endif +#ifndef GL_STENCIL_VALUE_MASK +#define GL_STENCIL_VALUE_MASK 0x0B93 +#endif +#ifndef GL_STENCIL_WRITEMASK +#define GL_STENCIL_WRITEMASK 0x0B98 +#endif +#ifndef GL_STREAM_DRAW +#define GL_STREAM_DRAW 0x88E0 +#endif +#ifndef GL_SUBPIXEL_BITS +#define GL_SUBPIXEL_BITS 0x0D50 +#endif +#ifndef GL_TEXTURE0 +#define GL_TEXTURE0 0x84C0 +#endif +#ifndef GL_TEXTURE +#define GL_TEXTURE 0x1702 +#endif +#ifndef GL_TEXTURE10 +#define GL_TEXTURE10 0x84CA +#endif +#ifndef GL_TEXTURE1 +#define GL_TEXTURE1 0x84C1 +#endif +#ifndef GL_TEXTURE11 +#define GL_TEXTURE11 0x84CB +#endif +#ifndef GL_TEXTURE12 +#define GL_TEXTURE12 0x84CC +#endif +#ifndef GL_TEXTURE13 +#define GL_TEXTURE13 0x84CD +#endif +#ifndef GL_TEXTURE14 +#define GL_TEXTURE14 0x84CE +#endif +#ifndef GL_TEXTURE15 +#define GL_TEXTURE15 0x84CF +#endif +#ifndef GL_TEXTURE16 +#define GL_TEXTURE16 0x84D0 +#endif +#ifndef GL_TEXTURE17 +#define GL_TEXTURE17 0x84D1 +#endif +#ifndef GL_TEXTURE18 +#define GL_TEXTURE18 0x84D2 +#endif +#ifndef GL_TEXTURE19 +#define GL_TEXTURE19 0x84D3 +#endif +#ifndef GL_TEXTURE20 +#define GL_TEXTURE20 0x84D4 +#endif +#ifndef GL_TEXTURE2 +#define GL_TEXTURE2 0x84C2 +#endif +#ifndef GL_TEXTURE21 +#define GL_TEXTURE21 0x84D5 +#endif +#ifndef GL_TEXTURE22 +#define GL_TEXTURE22 0x84D6 +#endif +#ifndef GL_TEXTURE23 +#define GL_TEXTURE23 0x84D7 +#endif +#ifndef GL_TEXTURE24 +#define GL_TEXTURE24 0x84D8 +#endif +#ifndef GL_TEXTURE25 +#define GL_TEXTURE25 0x84D9 +#endif +#ifndef GL_TEXTURE26 +#define GL_TEXTURE26 0x84DA +#endif +#ifndef GL_TEXTURE27 +#define GL_TEXTURE27 0x84DB +#endif +#ifndef GL_TEXTURE28 +#define GL_TEXTURE28 0x84DC +#endif +#ifndef GL_TEXTURE29 +#define GL_TEXTURE29 0x84DD +#endif +#ifndef GL_TEXTURE_2D +#define GL_TEXTURE_2D 0x0DE1 +#endif +#ifndef GL_TEXTURE30 +#define GL_TEXTURE30 0x84DE +#endif +#ifndef GL_TEXTURE3 +#define GL_TEXTURE3 0x84C3 +#endif +#ifndef GL_TEXTURE31 +#define GL_TEXTURE31 0x84DF +#endif +#ifndef GL_TEXTURE4 +#define GL_TEXTURE4 0x84C4 +#endif +#ifndef GL_TEXTURE5 +#define GL_TEXTURE5 0x84C5 +#endif +#ifndef GL_TEXTURE6 +#define GL_TEXTURE6 0x84C6 +#endif +#ifndef GL_TEXTURE7 +#define GL_TEXTURE7 0x84C7 +#endif +#ifndef GL_TEXTURE8 +#define GL_TEXTURE8 0x84C8 +#endif +#ifndef GL_TEXTURE9 +#define GL_TEXTURE9 0x84C9 +#endif +#ifndef GL_TEXTURE_BINDING_2D +#define GL_TEXTURE_BINDING_2D 0x8069 +#endif +#ifndef GL_TEXTURE_BINDING_CUBE_MAP +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#endif +#ifndef GL_TEXTURE_CUBE_MAP +#define GL_TEXTURE_CUBE_MAP 0x8513 +#endif +#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_X +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#endif +#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_Y +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#endif +#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_Z +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#endif +#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_X +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#endif +#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_Y +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#endif +#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_Z +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#endif +#ifndef GL_TEXTURE_MAG_FILTER +#define GL_TEXTURE_MAG_FILTER 0x2800 +#endif +#ifndef GL_TEXTURE_MIN_FILTER +#define GL_TEXTURE_MIN_FILTER 0x2801 +#endif +#ifndef GL_TEXTURE_WRAP_S +#define GL_TEXTURE_WRAP_S 0x2802 +#endif +#ifndef GL_TEXTURE_WRAP_T +#define GL_TEXTURE_WRAP_T 0x2803 +#endif +#ifndef GL_TRIANGLE_FAN +#define GL_TRIANGLE_FAN 0x0006 +#endif +#ifndef GL_TRIANGLES +#define GL_TRIANGLES 0x0004 +#endif +#ifndef GL_TRIANGLE_STRIP +#define GL_TRIANGLE_STRIP 0x0005 +#endif +#ifndef GL_TRUE +#define GL_TRUE 1 +#endif +#ifndef GL_UNPACK_ALIGNMENT +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#endif +#ifndef GL_UNSIGNED_BYTE +#define GL_UNSIGNED_BYTE 0x1401 +#endif +#ifndef GL_UNSIGNED_INT +#define GL_UNSIGNED_INT 0x1405 +#endif +#ifndef GL_UNSIGNED_SHORT +#define GL_UNSIGNED_SHORT 0x1403 +#endif +#ifndef GL_UNSIGNED_SHORT_4_4_4_4 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#endif +#ifndef GL_UNSIGNED_SHORT_5_5_5_1 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#endif +#ifndef GL_UNSIGNED_SHORT_5_6_5 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#endif +#ifndef GL_VALIDATE_STATUS +#define GL_VALIDATE_STATUS 0x8B83 +#endif +#ifndef GL_VENDOR +#define GL_VENDOR 0x1F00 +#endif +#ifndef GL_VERSION +#define GL_VERSION 0x1F02 +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_ENABLED +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_NORMALIZED +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_POINTER +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_SIZE +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_STRIDE +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_TYPE +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#endif +#ifndef GL_VERTEX_SHADER +#define GL_VERTEX_SHADER 0x8B31 +#endif +#ifndef GL_VIEWPORT +#define GL_VIEWPORT 0x0BA2 +#endif +#ifndef GL_ZERO +#define GL_ZERO 0 +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index 994947b..2ec345d 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -76,6 +76,14 @@ \endlist + + \section Threading + + As of Qt 4.8, it's possible to render into a QGLPixelBuffer using + a QPainter in a separate thread. Note that OpenGL 2.0 or OpenGL ES + 2.0 is required for this to work. Also, under X11, it's necessary + to set the Qt::AA_X11InitThreads application attribute. + Pbuffers are provided by the OpenGL \c pbuffer extension; call hasOpenGLPbuffer() to find out if the system provides pbuffers. @@ -394,25 +402,25 @@ bool QGLPixelBuffer::isValid() const } #if !defined(QT_OPENGL_ES_1) -Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_buffer_2_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_buffer_2_engine) #endif #ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QOpenGLPaintEngine>, qt_buffer_engine) #endif /*! \reimp */ QPaintEngine *QGLPixelBuffer::paintEngine() const { #if defined(QT_OPENGL_ES_1) - return qt_buffer_engine(); + return qt_buffer_engine()->engine(); #elif defined(QT_OPENGL_ES_2) - return qt_buffer_2_engine(); + return qt_buffer_2_engine()->engine(); #else if (qt_gl_preferGL2Engine()) - return qt_buffer_2_engine(); + return qt_buffer_2_engine()->engine(); else - return qt_buffer_engine(); + return qt_buffer_engine()->engine(); #endif } diff --git a/src/opengl/qglpixelbuffer_win.cpp b/src/opengl/qglpixelbuffer_win.cpp index b55f383..1da0aad 100644 --- a/src/opengl/qglpixelbuffer_win.cpp +++ b/src/opengl/qglpixelbuffer_win.cpp @@ -242,8 +242,7 @@ static void qt_format_to_attrib_list(bool has_render_texture, const QGLFormat &f bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget) { - QGLWidget dmy; - dmy.makeCurrent(); // needed for wglGetProcAddress() to succeed + QGLTemporaryContext tempContext; PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC) wglGetProcAddress("wglCreatePbufferARB"); @@ -257,7 +256,7 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge if (!wglCreatePbufferARB) // assumes that if one can be resolved, all of them can return false; - dc = GetDC(dmy.winId()); + dc = wglGetCurrentDC(); Q_ASSERT(dc); // sample buffers doesn't work in conjunction with the render_texture extension @@ -292,7 +291,6 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge if (num_formats == 0) { qWarning("QGLPixelBuffer: Unable to find a pixel format with pbuffer - giving up."); - ReleaseDC(dmy.winId(), dc); return false; } format = pfiToQGLFormat(dc, pixel_format); @@ -311,12 +309,10 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge has_render_texture = false; if (!pbuf) { qWarning("QGLPixelBuffer: Unable to create pbuffer [w=%d, h=%d] - giving up.", size.width(), size.height()); - ReleaseDC(dmy.winId(), dc); return false; } } - ReleaseDC(dmy.winId(), dc); dc = wglGetPbufferDCARB(pbuf); ctx = wglCreateContext(dc); diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index bfa5ef1..68586c1 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -315,7 +315,7 @@ class QGLBlurTextureCache : public QObject public: static QGLBlurTextureCache *cacheForContext(const QGLContext *context); - QGLBlurTextureCache(); + QGLBlurTextureCache(const QGLContext *); ~QGLBlurTextureCache(); QGLBlurTextureInfo *takeBlurTextureInfo(const QPixmap &pixmap); @@ -336,15 +336,9 @@ private: }; QList<QGLBlurTextureCache *> QGLBlurTextureCache::blurTextureCaches; +Q_GLOBAL_STATIC(QGLContextGroupResource<QGLBlurTextureCache>, qt_blur_texture_caches) -static void QGLBlurTextureCache_free(void *ptr) -{ - delete reinterpret_cast<QGLBlurTextureCache *>(ptr); -} - -Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_blur_texture_caches, (QGLBlurTextureCache_free)) - -QGLBlurTextureCache::QGLBlurTextureCache() +QGLBlurTextureCache::QGLBlurTextureCache(const QGLContext *) : timerId(0) { cache.setMaxCost(4 * 1024 * 1024); @@ -366,12 +360,7 @@ void QGLBlurTextureCache::timerEvent(QTimerEvent *) QGLBlurTextureCache *QGLBlurTextureCache::cacheForContext(const QGLContext *context) { - QGLBlurTextureCache *p = reinterpret_cast<QGLBlurTextureCache *>(qt_blur_texture_caches()->value(context)); - if (!p) { - p = new QGLBlurTextureCache; - qt_blur_texture_caches()->insert(context, p); - } - return p; + return qt_blur_texture_caches()->value(context); } QGLBlurTextureInfo *QGLBlurTextureCache::takeBlurTextureInfo(const QPixmap &pixmap) diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index ef0160c..e97ade8 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -77,7 +77,8 @@ extern int qt_vg_pixmap_serial; static CFbsBitmap* createBlitCopy(CFbsBitmap* bitmap) { - CFbsBitmap *copy = q_check_ptr(new CFbsBitmap); + CFbsBitmap *copy = new CFbsBitmap; + Q_CHECK_PTR(copy); if(!copy) return 0; @@ -228,7 +229,8 @@ void* QVGPixmapData::toNativeType(NativeType type) sgInfo.iSizeInPixels.SetSize(w, h); sgInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface; - RSgImage *sgImage = q_check_ptr(new RSgImage()); + RSgImage *sgImage = new RSgImage(); + Q_CHECK_PTR(sgImage); err = sgImage->Create(sgInfo, NULL, NULL); if (err != KErrNone) { driver.Close(); @@ -270,7 +272,8 @@ void* QVGPixmapData::toNativeType(NativeType type) return reinterpret_cast<void*>(sgImage); #endif } else if (type == QPixmapData::FbsBitmap) { - CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); + CFbsBitmap *bitmap = new CFbsBitmap; + Q_CHECK_PTR(bitmap); if (bitmap) { if (bitmap->Create(TSize(source.width(), source.height()), diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp index 662663d..6eb0617 100644 --- a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp +++ b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp @@ -348,7 +348,7 @@ QVariant QAccessibleTextEdit::invokeMethodEx(QAccessible::Method method, int chi case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods << SetCursorPosition << GetCursorPosition; - return qVariantFromValue(set | qvariant_cast<QSet<QAccessible::Method> >( + return QVariant::fromValue(set | qvariant_cast<QSet<QAccessible::Method> >( QAccessibleWidgetEx::invokeMethodEx(method, child, params))); } case SetCursorPosition: diff --git a/src/plugins/accessible/widgets/rangecontrols.cpp b/src/plugins/accessible/widgets/rangecontrols.cpp index 4cd171b..bf7b561 100644 --- a/src/plugins/accessible/widgets/rangecontrols.cpp +++ b/src/plugins/accessible/widgets/rangecontrols.cpp @@ -233,7 +233,7 @@ QVariant QAccessibleAbstractSpinBox::invokeMethodEx(Method method, int child, co case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods; - return qVariantFromValue(set | qvariant_cast<QSet<QAccessible::Method> >( + return QVariant::fromValue(set | qvariant_cast<QSet<QAccessible::Method> >( QAccessibleWidgetEx::invokeMethodEx(method, child, params))); } default: @@ -814,7 +814,7 @@ QVariant QAccessibleAbstractSlider::invokeMethodEx(Method method, int child, con case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods; - return qVariantFromValue(set | qvariant_cast<QSet<QAccessible::Method> >( + return QVariant::fromValue(set | qvariant_cast<QSet<QAccessible::Method> >( QAccessibleWidgetEx::invokeMethodEx(method, child, params))); } default: diff --git a/src/plugins/accessible/widgets/simplewidgets.cpp b/src/plugins/accessible/widgets/simplewidgets.cpp index f39d538..d8b57af 100644 --- a/src/plugins/accessible/widgets/simplewidgets.cpp +++ b/src/plugins/accessible/widgets/simplewidgets.cpp @@ -732,7 +732,7 @@ QVariant QAccessibleLineEdit::invokeMethodEx(QAccessible::Method method, int chi case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods << SetCursorPosition << GetCursorPosition; - return qVariantFromValue(set | qvariant_cast<QSet<QAccessible::Method> >( + return QVariant::fromValue(set | qvariant_cast<QSet<QAccessible::Method> >( QAccessibleWidgetEx::invokeMethodEx(method, child, params))); } case SetCursorPosition: diff --git a/src/plugins/bearer/connman/qconnmanservice_linux.cpp b/src/plugins/bearer/connman/qconnmanservice_linux.cpp index 549a07a..e94ae5d 100644 --- a/src/plugins/bearer/connman/qconnmanservice_linux.cpp +++ b/src/plugins/bearer/connman/qconnmanservice_linux.cpp @@ -1050,7 +1050,7 @@ QVariantMap QConnmanDeviceInterface::getProperties() bool QConnmanDeviceInterface::setProperty(const QString &name, const QDBusVariant &value) { - QDBusMessage reply = this->call(QLatin1String("SetProperty"),name, qVariantFromValue(value)); + QDBusMessage reply = this->call(QLatin1String("SetProperty"),name, QVariant::fromValue(value)); return true; } @@ -1112,7 +1112,7 @@ quint16 QConnmanDeviceInterface::getScanInterval() bool QConnmanDeviceInterface::setScanInterval(const QString & interval) { // QList<QVariant> args; -// args << qVariantFromValue(name) +// args << QVariant::fromValue(name) // << value.variant(); // QDBusMessage reply = this->callWithArgumentList(QDBus::AutoDetect,QLatin1String("SetProperty"),args); @@ -1135,8 +1135,8 @@ QStringList QConnmanDeviceInterface::getNetworks() bool QConnmanDeviceInterface::setEnabled(bool powered) { QList<QVariant> args; - args << qVariantFromValue(QString("Powered")) - << qVariantFromValue(QDBusVariant(powered)); + args << QVariant::fromValue(QString("Powered")) + << QVariant::fromValue(QDBusVariant(powered)); QDBusMessage reply = this->callWithArgumentList(QDBus::AutoDetect,QLatin1String("SetProperty"),args); return true; diff --git a/src/plugins/gfxdrivers/eglnullws/README b/src/plugins/gfxdrivers/eglnullws/README new file mode 100644 index 0000000..80b88c7 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/README @@ -0,0 +1,48 @@ +EGL NullWS QScreen Driver +========================= + +If your application draws everything within a single full-screen QGLWidget then +you may wish to use this QScreen plugin driver. This driver simply returns 0 +(as a EGLNativeWindowType value) when asked by the QtOpenGl module to create a +native window. Some OpenGL ES implementations (including PowerVR) interpret this +to mean that a full-screen OpenGL context is desired without any windowing +support (NullWS). + +To tell a Qt/Embedded application to use this driver use the -display command +line option or the QWS_DISPLAY environment variable. The following driver +options are supported: + +size=WIDTHxHEIGHT Screen size reported by the driver +format=FORMAT Screen format + +Run with '-display eglnullws:help' to get a full list of options (including a +list of supported format strings). + +If you choose a screen format that is not supported by the hardware then the +QtOpenGl module will write out a list of supported EGL configurations. Use +one of the supported screen formats from this list. + +Using this driver with PowerVR hardware +--------------------------------------- + +Using this plugin with PowerVR hardware should give a significant speedup +compared to running with the Qt powervr driver (with a full-screen QGLWidget). +This is because sacrificing the window system allows less work to be done in +order to get graphics on the screen. Using this driver also avoids the memory +fragmentation issues present in the powervr driver and avoids any direct +dependencies on the deprecated PVR2D API from Imagination Technologies. + +To use this driver ensure you have /etc/powervr.ini with contents similar to +this: + +[default] +WindowSystem=libpvrPVR2D_FLIPWSEGL.so + +This driver will also function with libpvrPVR2D_FRONTWSEGL.so, but that draws +straight into the framebuffer and will therefore cause flickering (it can be +useful for performance testing though). The flip plugin uses triple buffering, +so you will need to set the virtual vertical resolution of your framebuffer to +be three times the physical vertical resolution of your screen. This can be +done with 'fbset -vyres'. Failure to do this can cause system crashes. You +should also ensure that the plugin you choose in powervr.ini is in your library +path (it may just silently default to the flip plugin if not). diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullws.pro b/src/plugins/gfxdrivers/eglnullws/eglnullws.pro new file mode 100644 index 0000000..242ab07 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullws.pro @@ -0,0 +1,18 @@ +TARGET = qeglnullws +include(../../qpluginbase.pri) + +CONFIG += warn_on +QT += opengl + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/gfxdrivers + +target.path = $$[QT_INSTALL_PLUGINS]/gfxdrivers +INSTALLS += target + +HEADERS = eglnullwsscreen.h \ + eglnullwsscreenplugin.h \ + eglnullwswindowsurface.h + +SOURCES = eglnullwsscreen.cpp \ + eglnullwsscreenplugin.cpp \ + eglnullwswindowsurface.cpp diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.cpp b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.cpp new file mode 100644 index 0000000..b8ea5d5 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.cpp @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "eglnullwsscreen.h" +#include "eglnullwswindowsurface.h" +#include "eglnullwsscreenplugin.h" + +#include <QHash> +#include <QDebug> + +namespace +{ + class EGLNullWSScreenSurfaceFunctions : public QGLScreenSurfaceFunctions + { + public: + virtual bool createNativeWindow(QWidget *, EGLNativeWindowType *native) + { *native = 0; return true; } + }; +} + +EGLNullWSScreen::EGLNullWSScreen(int displayId) : QGLScreen(displayId) {} + +EGLNullWSScreen::~EGLNullWSScreen() {} + +bool EGLNullWSScreen::initDevice() +{ + setSurfaceFunctions(new EGLNullWSScreenSurfaceFunctions); + return true; +} + +static const QHash<QString, QImage::Format> formatDictionary() +{ + QHash<QString, QImage::Format> dictionary; + dictionary["rgb32"] = QImage::Format_RGB32; + dictionary["argb32"] = QImage::Format_ARGB32; + dictionary["rgb16"] = QImage::Format_RGB16; + dictionary["rgb666"] = QImage::Format_RGB666; + dictionary["rgb555"] = QImage::Format_RGB555; + dictionary["rgb888"] = QImage::Format_RGB888; + dictionary["rgb444"] = QImage::Format_RGB444; + return dictionary; +} + +static int depthForFormat(QImage::Format format) +{ + switch (format) { + case QImage::Format_RGB32: return 32; + case QImage::Format_ARGB32: return 32; + case QImage::Format_RGB16: return 16; + case QImage::Format_RGB666: return 24; + case QImage::Format_RGB555: return 16; + case QImage::Format_RGB888: return 24; + case QImage::Format_RGB444: return 16; + default: + Q_ASSERT_X(false, "EGLNullWSScreen", "Unknown format"); + return -1; + } +} + +static void printHelp(const QHash<QString, QImage::Format> &formatDictionary) +{ + QByteArray formatsBuf; + QTextStream(&formatsBuf) << QStringList(formatDictionary.keys()).join(", "); + qWarning( + "%s: Valid options are:\n" + "size=WIDTHxHEIGHT Screen size reported by this driver\n" + "format=FORMAT Screen format, where FORMAT is one of the following:\n" + " %s\n", + PluginName, + formatsBuf.constData()); +} + +bool EGLNullWSScreen::connect(const QString &displaySpec) +{ + const QStringList args = displaySpec.section(':', 1).split(':', QString::SkipEmptyParts); + const QHash<QString, QImage::Format> formatDict = formatDictionary(); + Q_FOREACH(const QString arg, args) { + const QString optionName = arg.section('=', 0, 0); + const QString optionArg = arg.section('=', 1); + if (optionName == QLatin1String("size")) { + w = optionArg.section('x', 0, 0).toInt(); + h = optionArg.section('x', 1, 1).toInt(); + } else if (optionName == QLatin1String("format")) { + if (formatDict.contains(optionArg)) + setPixelFormat(formatDict.value(optionArg)); + else + printHelp(formatDict); + } else { + printHelp(formatDict); + } + } + + if (w == 0 || h == 0) { + w = 640; + h = 480; + qWarning("%s: Using default screen size %dx%d", PluginName, w, h); + } + dw = w; + dh = h; + + if (pixelFormat() == QImage::Format_Invalid) { + qWarning("%s: Using default screen format argb32", PluginName); + setPixelFormat(QImage::Format_ARGB32); + } + d = depthForFormat(pixelFormat()); + + static const int Dpi = 120; + static const qreal ScalingFactor = static_cast<qreal>(25.4) / Dpi; + physWidth = qRound(dw * ScalingFactor); + physHeight = qRound(dh * ScalingFactor); + + return true; +} + +void EGLNullWSScreen::disconnect() {} + +void EGLNullWSScreen::shutdownDevice() {} + +void EGLNullWSScreen::setMode(int /*width*/, int /*height*/, int /*depth*/) {} + +void EGLNullWSScreen::blank(bool /*on*/) {} + +void EGLNullWSScreen::exposeRegion(QRegion /*r*/, int /*changing*/) {} + +QWSWindowSurface* EGLNullWSScreen::createSurface(QWidget *widget) const +{ + if (qobject_cast<QGLWidget*>(widget)) { + return new EGLNullWSWindowSurface(widget); + } else { + qWarning("%s: Creating non-GL surface", PluginName); + return QScreen::createSurface(widget); + } +} + +QWSWindowSurface* EGLNullWSScreen::createSurface(const QString &key) const +{ + if (key == QLatin1String("eglnullws")) { + return new EGLNullWSWindowSurface; + } else { + qWarning("%s: Creating non-GL surface", PluginName); + return QScreen::createSurface(key); + } +} diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.h b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.h new file mode 100644 index 0000000..7f794bc --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef EGLNULLWSSCREEN +#define EGLNULLWSSCREEN + +#include <QGLScreen> + +class EGLNullWSScreen : public QGLScreen +{ +public: + EGLNullWSScreen(int displayId); + ~EGLNullWSScreen(); + + bool initDevice(); + bool connect(const QString &displaySpec); + void disconnect(); + void shutdownDevice(); + + void setMode(int width, int height, int depth); + void blank(bool on); + + void exposeRegion(QRegion r, int changing); + + QWSWindowSurface* createSurface(QWidget *widget) const; + QWSWindowSurface* createSurface(const QString &key) const; + + bool hasOpenGL() { return true; } +}; + +#endif // EGLNULLWSSCREEN diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.cpp b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.cpp new file mode 100644 index 0000000..67b3f56 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "eglnullwsscreenplugin.h" +#include "eglnullwsscreen.h" + +#include <QScreenDriverPlugin> +#include <QStringList> + +class EGLNullWSScreenPlugin : public QScreenDriverPlugin +{ +public: + virtual QStringList keys() const; + virtual QScreen *create(const QString& driver, int displayId); +}; + +QStringList EGLNullWSScreenPlugin::keys() const +{ + return QStringList() << QLatin1String(PluginName); +} + +QScreen *EGLNullWSScreenPlugin::create(const QString& driver, int displayId) +{ + return (driver.toLower() == QLatin1String(PluginName) ? + new EGLNullWSScreen(displayId) : 0); +} + +Q_EXPORT_PLUGIN2(qeglnullws, EGLNullWSScreenPlugin) diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.h b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.h new file mode 100644 index 0000000..84f0699 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef EGLNULLWSSCREENPLUGIN_H +#define EGLNULLWSSCREENPLUGIN_H + +const char *const PluginName = "eglnullws"; + +#endif // EGLNULLWSSCREENPLUGIN_H diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.cpp b/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.cpp new file mode 100644 index 0000000..da4b728 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "eglnullwswindowsurface.h" +#include "eglnullwsscreenplugin.h" + +#include <QGLWidget> + +static const QWSWindowSurface::SurfaceFlags Flags + = QWSWindowSurface::RegionReserved | QWSWindowSurface::RegionReserved; + +EGLNullWSWindowSurface::EGLNullWSWindowSurface(QWidget *w) + : + QWSGLWindowSurface(w), + widget(w) +{ + setSurfaceFlags(Flags); +} + +EGLNullWSWindowSurface::EGLNullWSWindowSurface() + : widget(0) +{ + setSurfaceFlags(Flags); +} + +EGLNullWSWindowSurface::~EGLNullWSWindowSurface() {} + +QString EGLNullWSWindowSurface::key() const +{ + return QLatin1String(PluginName); +} + +QPaintDevice *EGLNullWSWindowSurface::paintDevice() +{ + return widget; +} + +bool EGLNullWSWindowSurface::isValid() const +{ + return qobject_cast<QGLWidget *>(window()); +} + +QImage EGLNullWSWindowSurface::image() const +{ + return QImage(); +} diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.h b/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.h new file mode 100644 index 0000000..b730415 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef EGLNULLWSWINDOWSURFACE_H +#define EGLNULLWSWINDOWSURFACE_H + +#include <private/qglwindowsurface_qws_p.h> + +class EGLNullWSWindowSurface : public QWSGLWindowSurface +{ +public: + EGLNullWSWindowSurface(QWidget *widget); + EGLNullWSWindowSurface(); + virtual ~EGLNullWSWindowSurface(); + + virtual QString key() const; + virtual QPaintDevice *paintDevice(); + virtual bool isValid() const; + virtual QImage image() const; + +private: + QWidget *widget; +}; + +#endif // EGLNULLWSWINDOWSURFACE_H diff --git a/src/plugins/gfxdrivers/gfxdrivers.pro b/src/plugins/gfxdrivers/gfxdrivers.pro index d1ee3f2..1f38942 100644 --- a/src/plugins/gfxdrivers/gfxdrivers.pro +++ b/src/plugins/gfxdrivers/gfxdrivers.pro @@ -7,3 +7,4 @@ contains(gfx-plugins, vnc) :SUBDIRS += vnc contains(gfx-plugins, transformed) :SUBDIRS += transformed contains(gfx-plugins, svgalib) :SUBDIRS += svgalib contains(gfx-plugins, powervr) :SUBDIRS += powervr +contains(gfx-plugins, eglnullws) :SUBDIRS += eglnullws diff --git a/src/plugins/qpluginbase.pri b/src/plugins/qpluginbase.pri index 8b119b5..45e3976 100644 --- a/src/plugins/qpluginbase.pri +++ b/src/plugins/qpluginbase.pri @@ -1,6 +1,6 @@ TEMPLATE = lib isEmpty(QT_MAJOR_VERSION) { - VERSION=4.7.0 + VERSION=4.8.0 } else { VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} } diff --git a/src/qbase.pri b/src/qbase.pri index f6af22f..aa7d745 100644 --- a/src/qbase.pri +++ b/src/qbase.pri @@ -4,7 +4,7 @@ INCLUDEPATH *= $$QMAKE_INCDIR_QT/$$TARGET #just for today to have some compat isEmpty(QT_ARCH):!isEmpty(ARCH):QT_ARCH=$$ARCH #another compat that will rot for change #215700 TEMPLATE = lib isEmpty(QT_MAJOR_VERSION) { - VERSION=4.7.0 + VERSION=4.8.0 } else { VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} } diff --git a/src/qt3support/text/q3richtext.cpp b/src/qt3support/text/q3richtext.cpp index 8614076..625dd95 100644 --- a/src/qt3support/text/q3richtext.cpp +++ b/src/qt3support/text/q3richtext.cpp @@ -8079,9 +8079,9 @@ bool Q3TextTable::down(Q3TextCursor *c, Q3TextDocument *&doc, Q3TextParagraph *& break; } } - doc = cell->richText(); if (!cell) return false; + doc = cell->richText(); parag = doc->firstParagraph(); idx = 0; ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); @@ -8117,9 +8117,9 @@ bool Q3TextTable::up(Q3TextCursor *c, Q3TextDocument *&doc, Q3TextParagraph *&pa break; } } - doc = cell->richText(); if (!cell) return false; + doc = cell->richText(); parag = doc->lastParagraph(); idx = parag->length() - 1; ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); diff --git a/src/qt3support/text/q3textstream.h b/src/qt3support/text/q3textstream.h index d0c4f48..0e26e08 100644 --- a/src/qt3support/text/q3textstream.h +++ b/src/qt3support/text/q3textstream.h @@ -272,13 +272,13 @@ private: int arg; // member function argument }; -Q_COMPAT_EXPORT inline Q3TextStream &operator>>( Q3TextStream &s, Q3TSFUNC f ) +Q_COMPAT_EXPORT_INLINE Q3TextStream &operator>>( Q3TextStream &s, Q3TSFUNC f ) { return (*f)( s ); } -Q_COMPAT_EXPORT inline Q3TextStream &operator<<( Q3TextStream &s, Q3TSFUNC f ) +Q_COMPAT_EXPORT_INLINE Q3TextStream &operator<<( Q3TextStream &s, Q3TSFUNC f ) { return (*f)( s ); } -Q_COMPAT_EXPORT inline Q3TextStream &operator<<( Q3TextStream &s, Q3TSManip m ) +Q_COMPAT_EXPORT_INLINE Q3TextStream &operator<<( Q3TextStream &s, Q3TSManip m ) { m.exec(s); return s; } Q_COMPAT_EXPORT Q3TextStream &bin( Q3TextStream &s ); // set bin notation diff --git a/src/qt3support/tools/q3cstring.h b/src/qt3support/tools/q3cstring.h index b280ebc..86a31fa 100644 --- a/src/qt3support/tools/q3cstring.h +++ b/src/qt3support/tools/q3cstring.h @@ -161,75 +161,75 @@ inline Q3CString &Q3CString::setNum(float n, char f, int prec) Q3CString non-member operators *****************************************************************************/ -Q_COMPAT_EXPORT inline bool operator==(const Q3CString &s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator==(const Q3CString &s1, const Q3CString &s2) { return qstrcmp(s1, s2) == 0; } -Q_COMPAT_EXPORT inline bool operator==(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator==(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) == 0; } -Q_COMPAT_EXPORT inline bool operator==(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator==(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) == 0; } -Q_COMPAT_EXPORT inline bool operator!=(const Q3CString &s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator!=(const Q3CString &s1, const Q3CString &s2) { return qstrcmp(s1, s2) != 0; } -Q_COMPAT_EXPORT inline bool operator!=(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator!=(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) != 0; } -Q_COMPAT_EXPORT inline bool operator!=(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator!=(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) != 0; } -Q_COMPAT_EXPORT inline bool operator<(const Q3CString &s1, const Q3CString& s2) +Q_COMPAT_EXPORT_INLINE bool operator<(const Q3CString &s1, const Q3CString& s2) { return qstrcmp(s1, s2) < 0; } -Q_COMPAT_EXPORT inline bool operator<(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator<(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) < 0; } -Q_COMPAT_EXPORT inline bool operator<(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator<(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) < 0; } -Q_COMPAT_EXPORT inline bool operator<=(const Q3CString &s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator<=(const Q3CString &s1, const Q3CString &s2) { return qstrcmp(s1, s2) <= 0; } -Q_COMPAT_EXPORT inline bool operator<=(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator<=(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) <= 0; } -Q_COMPAT_EXPORT inline bool operator<=(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator<=(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) <= 0; } -Q_COMPAT_EXPORT inline bool operator>(const Q3CString &s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator>(const Q3CString &s1, const Q3CString &s2) { return qstrcmp(s1, s2) > 0; } -Q_COMPAT_EXPORT inline bool operator>(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator>(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) > 0; } -Q_COMPAT_EXPORT inline bool operator>(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator>(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) > 0; } -Q_COMPAT_EXPORT inline bool operator>=(const Q3CString &s1, const Q3CString& s2) +Q_COMPAT_EXPORT_INLINE bool operator>=(const Q3CString &s1, const Q3CString& s2) { return qstrcmp(s1, s2) >= 0; } -Q_COMPAT_EXPORT inline bool operator>=(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator>=(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) >= 0; } -Q_COMPAT_EXPORT inline bool operator>=(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator>=(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) >= 0; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const Q3CString &s1, +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const Q3CString &s1, const Q3CString &s2) { Q3CString tmp(s1); tmp += s2; return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const Q3CString &s1, +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const Q3CString &s1, const QByteArray &s2) { QByteArray tmp(s1); tmp += s2; return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const QByteArray &s1, +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const QByteArray &s1, const Q3CString &s2) { QByteArray tmp(s1); @@ -237,28 +237,28 @@ Q_COMPAT_EXPORT inline const Q3CString operator+(const QByteArray &s1, return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const Q3CString &s1, const char *s2) { Q3CString tmp(s1); tmp += s2; return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const char *s1, const Q3CString &s2) { Q3CString tmp(s1); tmp += s2; return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const Q3CString &s1, char c2) +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const Q3CString &s1, char c2) { Q3CString tmp(s1); tmp += c2; return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(char c1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(char c1, const Q3CString &s2) { Q3CString tmp; tmp += c1; diff --git a/src/s60main/qts60main.cpp b/src/s60main/qts60main.cpp index 5fbeea5..c65344b 100644 --- a/src/s60main/qts60main.cpp +++ b/src/s60main/qts60main.cpp @@ -51,7 +51,8 @@ GLDEF_C TInt QtMainWrapper(); */ GLDEF_C TInt E32Main() { - CTrapCleanup *cleanupStack = q_check_ptr(CTrapCleanup::New()); + CTrapCleanup *cleanupStack = CTrapCleanup::New(); + Q_CHECK_PTR(cleanupStack); TInt err = 0; TRAP(err, err = QtMainWrapper()); delete cleanupStack; diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 07aced4..0a669b5 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -1730,7 +1730,7 @@ QVariant QScriptEnginePrivate::toVariant(JSC::ExecState *exec, JSC::JSValue valu return variantValue(value); #ifndef QT_NO_QOBJECT else if (isQObject(value)) - return qVariantFromValue(toQObject(exec, value)); + return QVariant::fromValue(toQObject(exec, value)); #endif else if (isDate(value)) return QVariant(toDateTime(exec, value)); @@ -2454,10 +2454,6 @@ QScriptValue QScriptEngine::newQMetaObject( \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 13 - \warning This function is not available with MSVC 6. Use - qScriptValueFromQMetaObject() instead if you need to support that version - of the compiler. - \sa QScriptEngine::newQMetaObject() */ @@ -2465,14 +2461,17 @@ QScriptValue QScriptEngine::newQMetaObject( \fn QScriptValue qScriptValueFromQMetaObject(QScriptEngine *engine) \since 4.3 \relates QScriptEngine + \obsolete Uses \a engine to create a QScriptValue that represents the Qt class \c{T}. This function is equivalent to - QScriptEngine::scriptValueFromQMetaObject(). It is provided as a - work-around for MSVC 6, which doesn't support member template - functions. + QScriptEngine::scriptValueFromQMetaObject(). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QScriptEngine::newQMetaObject() */ @@ -3002,14 +3001,7 @@ JSC::JSValue QScriptEnginePrivate::create(JSC::ExecState *exec, int type, const case QMetaType::LongLong: return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const qlonglong*>(ptr))); case QMetaType::ULongLong: -#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804 -#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.") - return JSC::jsNumber(exec, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); -#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - return JSC::jsNumber(exec, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); -#else return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const qulonglong*>(ptr))); -#endif case QMetaType::Double: return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const double*>(ptr))); case QMetaType::QString: @@ -3053,7 +3045,7 @@ JSC::JSValue QScriptEnginePrivate::create(JSC::ExecState *exec, int type, const break; #endif case QMetaType::QVariant: - result = jscValueFromVariant(exec, *reinterpret_cast<const QVariant*>(ptr)); + result = eng->newVariant(*reinterpret_cast<const QVariant*>(ptr)); break; default: if (type == qMetaTypeId<QScriptValue>()) { @@ -3771,10 +3763,6 @@ QStringList QScriptEngine::importedExtensions() const to newVariant()); you can change this behavior by installing your own type conversion functions with qScriptRegisterMetaType(). - \warning This function is not available with MSVC 6. Use - qScriptValueFromValue() instead if you need to support that - version of the compiler. - \sa fromScriptValue(), qScriptRegisterMetaType() */ @@ -3788,10 +3776,6 @@ QStringList QScriptEngine::importedExtensions() const description of the built-in type conversion provided by QtScript. - \warning This function is not available with MSVC 6. Use - qScriptValueToValue() or qscriptvalue_cast() instead if you need - to support that version of the compiler. - \sa toScriptValue(), qScriptRegisterMetaType() */ @@ -3799,29 +3783,35 @@ QStringList QScriptEngine::importedExtensions() const \fn QScriptValue qScriptValueFromValue(QScriptEngine *engine, const T &value) \since 4.3 \relates QScriptEngine + \obsolete Creates a QScriptValue using the given \a engine with the given \a value of template type \c{T}. This function is equivalent to QScriptEngine::toScriptValue(). - It is provided as a work-around for MSVC 6, which doesn't support - member template functions. - \sa qScriptValueToValue() + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. + + \sa QScriptEngine::toScriptValue(), qscriptvalue_cast */ /*! \fn T qScriptValueToValue(const QScriptValue &value) \since 4.3 \relates QScriptEngine + \obsolete Returns the given \a value converted to the template type \c{T}. This function is equivalent to QScriptEngine::fromScriptValue(). - It is provided as a work-around for MSVC 6, which doesn't - support member template functions. - \sa qScriptValueFromValue() + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. + + \sa QScriptEngine::fromScriptValue() */ /*! @@ -3840,7 +3830,7 @@ QStringList QScriptEngine::importedExtensions() const \l{Conversion Between QtScript and C++ Types} for more information about the restrictions on types that can be used with QScriptValue. - \sa qScriptValueFromValue() + \sa QScriptEngine::fromScriptValue() */ /*! diff --git a/src/script/api/qscriptengine.h b/src/script/api/qscriptengine.h index 3212ed5..830d477 100644 --- a/src/script/api/qscriptengine.h +++ b/src/script/api/qscriptengine.h @@ -65,13 +65,11 @@ inline QScriptValue qscriptQMetaObjectConstructor(QScriptContext *, QScriptEngin class QRegExp; #endif -#ifndef QT_NO_MEMBER_TEMPLATES template <typename T> inline QScriptValue qScriptValueFromValue(QScriptEngine *, const T &); template <typename T> -inline T qScriptValueToValue(const QScriptValue &); -#endif +inline T qscriptvalue_cast(const QScriptValue &); class QScriptSyntaxCheckResultPrivate; class Q_SCRIPT_EXPORT QScriptSyntaxCheckResult @@ -196,9 +194,7 @@ public: QScriptValue newQMetaObject(const QMetaObject *metaObject, const QScriptValue &ctor = QScriptValue()); -# ifndef QT_NO_MEMBER_TEMPLATES template <class T> QScriptValue scriptValueFromQMetaObject(); -# endif // QT_NO_MEMBER_TEMPLATES #endif // QT_NO_QOBJECT @@ -213,7 +209,6 @@ public: -#ifndef QT_NO_MEMBER_TEMPLATES template <typename T> inline QScriptValue toScriptValue(const T &value) { @@ -222,9 +217,8 @@ public: template <typename T> inline T fromScriptValue(const QScriptValue &value) { - return qScriptValueToValue<T>(value); + return qscriptvalue_cast<T>(value); } -#endif // QT_NO_MEMBER_TEMPLATES void installTranslatorFunctions(const QScriptValue &object = QScriptValue()); @@ -285,19 +279,6 @@ private: }; #ifndef QT_NO_QOBJECT -template <class T> -inline QScriptValue qScriptValueFromQMetaObject( - QScriptEngine *engine -#ifndef qdoc - , T * /* dummy */ = 0 -#endif - ) -{ - typedef QScriptValue(*ConstructPtr)(QScriptContext *, QScriptEngine *, T *); - ConstructPtr cptr = qscriptQMetaObjectConstructor<T>; - return engine->newQMetaObject(&T::staticMetaObject, - engine->newFunction(reinterpret_cast<QScriptEngine::FunctionWithArgSignature>(cptr), 0)); -} #define Q_SCRIPT_DECLARE_QMETAOBJECT(T, _Arg1) \ template<> inline QScriptValue qscriptQMetaObjectConstructor<T>(QScriptContext *ctx, QScriptEngine *eng, T *) \ @@ -311,12 +292,26 @@ template<> inline QScriptValue qscriptQMetaObjectConstructor<T>(QScriptContext * return o; \ } -# ifndef QT_NO_MEMBER_TEMPLATES - template <class T> QScriptValue QScriptEngine::scriptValueFromQMetaObject() - { - return qScriptValueFromQMetaObject<T>(this); - } -# endif // QT_NO_MEMBER_TEMPLATES +template <class T> QScriptValue QScriptEngine::scriptValueFromQMetaObject() +{ + typedef QScriptValue(*ConstructPtr)(QScriptContext *, QScriptEngine *, T *); + ConstructPtr cptr = qscriptQMetaObjectConstructor<T>; + return newQMetaObject(&T::staticMetaObject, + newFunction(reinterpret_cast<FunctionWithArgSignature>(cptr), 0)); +} + +#ifdef QT_DEPRECATED +template <class T> +inline QT_DEPRECATED QScriptValue qScriptValueFromQMetaObject( + QScriptEngine *engine +#ifndef qdoc + , T * /* dummy */ = 0 +#endif + ) +{ + return engine->scriptValueFromQMetaObject<T>(); +} +#endif #endif // QT_NO_QOBJECT @@ -349,11 +344,7 @@ inline bool qscriptvalue_cast_helper(const QScriptValue &value, int type, void * } template<typename T> -T qscriptvalue_cast(const QScriptValue &value -#if !defined qdoc && defined Q_CC_MSVC && _MSC_VER < 1300 -, T * = 0 -#endif - ) +T qscriptvalue_cast(const QScriptValue &value) { T t; const int id = qMetaTypeId<T>(); @@ -366,19 +357,19 @@ T qscriptvalue_cast(const QScriptValue &value return T(); } -#if !defined Q_CC_MSVC || _MSC_VER >= 1300 template <> inline QVariant qscriptvalue_cast<QVariant>(const QScriptValue &value) { return value.toVariant(); } -#endif +#ifdef QT_DEPRECATED template <typename T> -inline T qScriptValueToValue(const QScriptValue &value) +inline QT_DEPRECATED T qScriptValueToValue(const QScriptValue &value) { return qscriptvalue_cast<T>(value); } +#endif inline void qScriptRegisterMetaType_helper(QScriptEngine *eng, int type, QScriptEngine::MarshalFunction mf, @@ -418,7 +409,7 @@ QScriptValue qScriptValueFromSequence(QScriptEngine *eng, const Container &cont) typename Container::const_iterator it; quint32 i; for (it = begin, i = 0; it != end; ++it, ++i) - a.setProperty(i, qScriptValueFromValue(eng, *it)); + a.setProperty(i, eng->toScriptValue(*it)); return a; } @@ -428,11 +419,7 @@ void qScriptValueToSequence(const QScriptValue &value, Container &cont) quint32 len = value.property(QLatin1String("length")).toUInt32(); for (quint32 i = 0; i < len; ++i) { QScriptValue item = value.property(i); -#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET - cont.push_back(qscriptvalue_cast<Container::value_type>(item)); -#else cont.push_back(qscriptvalue_cast<typename Container::value_type>(item)); -#endif } } diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index f6390bb..fbd5d96 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -688,10 +688,6 @@ static bool LessThan(QScriptValue lhs, QScriptValue rhs) return false; case Number: -#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET - if (qIsNaN(lhs.toNumber()) || qIsNaN(rhs.toNumber())) - return false; -#endif return lhs.toNumber() < rhs.toNumber(); case Boolean: @@ -714,13 +710,7 @@ static bool LessThan(QScriptValue lhs, QScriptValue rhs) if (lhs.isString() && rhs.isString()) return lhs.toString() < rhs.toString(); - qsreal n1 = lhs.toNumber(); - qsreal n2 = rhs.toNumber(); -#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET - if (qIsNaN(n1) || qIsNaN(n2)) - return false; -#endif - return n1 < n2; + return lhs.toNumber() < rhs.toNumber(); } static bool Equals(QScriptValue lhs, QScriptValue rhs) diff --git a/src/script/bridge/qscriptclassobject.cpp b/src/script/bridge/qscriptclassobject.cpp index dd229f1..28f7bd1 100644 --- a/src/script/bridge/qscriptclassobject.cpp +++ b/src/script/bridge/qscriptclassobject.cpp @@ -211,7 +211,7 @@ JSC::JSValue JSC_HOST_CALL ClassObjectDelegate::call(JSC::ExecState *exec, JSC:: eng_p->pushContext(exec, thisValue, args, callee); QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame); QScriptValue scriptObject = eng_p->scriptValueFromJSCValue(obj); - QVariant result = scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx)); + QVariant result = scriptClass->extension(QScriptClass::Callable, QVariant::fromValue(ctx)); eng_p->popContext(); eng_p->currentFrame = oldFrame; return QScriptEnginePrivate::jscValueFromVariant(exec, result); @@ -239,7 +239,7 @@ JSC::JSObject* ClassObjectDelegate::construct(JSC::ExecState *exec, JSC::JSObjec QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame); QScriptValue defaultObject = ctx->thisObject(); - QScriptValue result = qvariant_cast<QScriptValue>(scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx))); + QScriptValue result = qvariant_cast<QScriptValue>(scriptClass->extension(QScriptClass::Callable, QVariant::fromValue(ctx))); if (!result.isObject()) result = defaultObject; eng_p->popContext(); @@ -256,7 +256,7 @@ bool ClassObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState *exe QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); QScript::SaveFrameHelper saveFrame(eng_p, exec); args << eng_p->scriptValueFromJSCValue(object) << eng_p->scriptValueFromJSCValue(value); - QVariant result = scriptClass()->extension(QScriptClass::HasInstance, qVariantFromValue(args)); + QVariant result = scriptClass()->extension(QScriptClass::HasInstance, QVariant::fromValue(args)); return result.toBool(); } diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp index 5e4f097..d24f2fe 100644 --- a/src/script/bridge/qscriptqobject.cpp +++ b/src/script/bridge/qscriptqobject.cpp @@ -664,7 +664,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c if (actual.isNumber()) { int ival = QScriptEnginePrivate::toInt32(exec, actual); if (m.valueToKey(ival) != 0) { - qVariantSetValue(v, ival); + v.setValue(ival); converted = true; matchDistance += 10; } @@ -672,7 +672,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c JSC::UString sval = QScriptEnginePrivate::toString(exec, actual); int ival = m.keyToValue(convertToLatin1(sval)); if (ival != -1) { - qVariantSetValue(v, ival); + v.setValue(ival); converted = true; matchDistance += 10; } @@ -1668,7 +1668,7 @@ static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChild(JSC::ExecState *exec QString name; if (args.size() != 0) name = args.at(0).toString(exec); - QObject *child = qFindChild<QObject*>(obj, name); + QObject *child = obj->findChild<QObject*>(name); QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; return engine->newQObject(child, QScriptEngine::QtOwnership, opt); } @@ -1709,10 +1709,10 @@ static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChildren(JSC::ExecState *e } } else { const QString name(args.at(0).toString(exec)); - children = qFindChildren<QObject*>(obj, name); + children = obj->findChildren<QObject*>(name); } } else { - children = qFindChildren<QObject*>(obj, QString()); + children = obj->findChildren<QObject*>(QString()); } // create the result array with the children const int length = children.size(); diff --git a/src/scripttools/debugging/qscriptdebuggercommand.cpp b/src/scripttools/debugging/qscriptdebuggercommand.cpp index fa223ec..5ca0535 100644 --- a/src/scripttools/debugging/qscriptdebuggercommand.cpp +++ b/src/scripttools/debugging/qscriptdebuggercommand.cpp @@ -256,7 +256,7 @@ QScriptBreakpointData QScriptDebuggerCommand::breakpointData() const void QScriptDebuggerCommand::setBreakpointData(const QScriptBreakpointData &data) { Q_D(QScriptDebuggerCommand); - d->attributes[BreakpointData] = qVariantFromValue(data); + d->attributes[BreakpointData] = QVariant::fromValue(data); } QScriptDebuggerValue QScriptDebuggerCommand::scriptValue() const @@ -268,7 +268,7 @@ QScriptDebuggerValue QScriptDebuggerCommand::scriptValue() const void QScriptDebuggerCommand::setScriptValue(const QScriptDebuggerValue &value) { Q_D(QScriptDebuggerCommand); - d->attributes[ScriptValue] = qVariantFromValue(value); + d->attributes[ScriptValue] = QVariant::fromValue(value); } int QScriptDebuggerCommand::contextIndex() const @@ -316,7 +316,7 @@ QScriptDebuggerValue QScriptDebuggerCommand::subordinateScriptValue() const void QScriptDebuggerCommand::setSubordinateScriptValue(const QScriptDebuggerValue &value) { Q_D(QScriptDebuggerCommand); - d->attributes[SubordinateScriptValue] = qVariantFromValue(value); + d->attributes[SubordinateScriptValue] = QVariant::fromValue(value); } int QScriptDebuggerCommand::snapshotId() const diff --git a/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp b/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp index 568af59..7616148 100644 --- a/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp +++ b/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp @@ -229,11 +229,11 @@ QScriptDebuggerResponse QScriptDebuggerCommandExecutor::execute( case QScriptDebuggerCommand::ScriptsCheckpoint: backend->scriptsCheckpoint(); - response.setResult(qVariantFromValue(backend->scriptsDelta())); + response.setResult(QVariant::fromValue(backend->scriptsDelta())); break; case QScriptDebuggerCommand::GetScriptsDelta: - response.setResult(qVariantFromValue(backend->scriptsDelta())); + response.setResult(QVariant::fromValue(backend->scriptsDelta())); break; case QScriptDebuggerCommand::ResolveScript: @@ -302,7 +302,7 @@ QScriptDebuggerResponse QScriptDebuggerCommandExecutor::execute( } break; case QScriptDebuggerCommand::ContextsCheckpoint: { - response.setResult(qVariantFromValue(backend->contextsCheckpoint())); + response.setResult(QVariant::fromValue(backend->contextsCheckpoint())); } break; case QScriptDebuggerCommand::GetPropertyExpressionValue: { @@ -441,7 +441,7 @@ QScriptDebuggerResponse QScriptDebuggerCommandExecutor::execute( result.addedProperties.append(dest); } backend->setIgnoreExceptions(didIgnoreExceptions); - response.setResult(qVariantFromValue(result)); + response.setResult(QVariant::fromValue(result)); } break; case QScriptDebuggerCommand::DeleteScriptObjectSnapshot: { diff --git a/src/scripttools/debugging/qscriptdebuggerconsole.cpp b/src/scripttools/debugging/qscriptdebuggerconsole.cpp index 2f7a998..268b30e 100644 --- a/src/scripttools/debugging/qscriptdebuggerconsole.cpp +++ b/src/scripttools/debugging/qscriptdebuggerconsole.cpp @@ -76,7 +76,7 @@ QT_BEGIN_NAMESPACE static QScriptValue debuggerResponseToScriptValue(QScriptEngine *eng, const QScriptDebuggerResponse &in) { QScriptValue out = eng->newObject(); - out.setProperty(QString::fromLatin1("result"), qScriptValueFromValue(eng, in.result())); + out.setProperty(QString::fromLatin1("result"), eng->toScriptValue(in.result())); out.setProperty(QString::fromLatin1("error"), QScriptValue(eng, in.error())); out.setProperty(QString::fromLatin1("async"), QScriptValue(eng, in.async())); return out; @@ -122,7 +122,7 @@ static QScriptValue breakpointMapToScriptValue(QScriptEngine *eng, const QScript QScriptValue out = eng->newObject(); QScriptBreakpointMap::const_iterator it; for (it = in.constBegin(); it != in.constEnd(); ++it) { - out.setProperty(QString::number(it.key()), qScriptValueFromValue(eng, it.value())); + out.setProperty(QString::number(it.key()), eng->toScriptValue(it.value())); } return out; } @@ -155,7 +155,7 @@ static QScriptValue scriptMapToScriptValue(QScriptEngine *eng, const QScriptScri QScriptValue out = eng->newObject(); QScriptScriptMap::const_iterator it; for (it = in.constBegin(); it != in.constEnd(); ++it) { - out.setProperty(QString::number(it.key()), qScriptValueFromValue(eng, it.value())); + out.setProperty(QString::number(it.key()), eng->toScriptValue(it.value())); } return out; } @@ -175,8 +175,8 @@ static QScriptValue consoleCommandToScriptValue( out.setProperty(QString::fromLatin1("group"), QScriptValue(eng, in->group())); out.setProperty(QString::fromLatin1("shortDescription"), QScriptValue(eng, in->shortDescription())); out.setProperty(QString::fromLatin1("longDescription"), QScriptValue(eng, in->longDescription())); - out.setProperty(QString::fromLatin1("aliases"), qScriptValueFromValue(eng, in->aliases())); - out.setProperty(QString::fromLatin1("seeAlso"), qScriptValueFromValue(eng, in->seeAlso())); + out.setProperty(QString::fromLatin1("aliases"), eng->toScriptValue(in->aliases())); + out.setProperty(QString::fromLatin1("seeAlso"), eng->toScriptValue(in->seeAlso())); return out; } @@ -207,7 +207,7 @@ static QScriptValue consoleCommandGroupMapToScriptValue( QScriptValue out = eng->newObject(); QScriptDebuggerConsoleCommandGroupMap::const_iterator it; for (it = in.constBegin(); it != in.constEnd(); ++it) { - out.setProperty(it.key(), qScriptValueFromValue(eng, it.value())); + out.setProperty(it.key(), eng->toScriptValue(it.value())); } return out; } @@ -238,7 +238,7 @@ static QScriptValue debuggerScriptValuePropertyToScriptValue(QScriptEngine *eng, { QScriptValue out = eng->newObject(); out.setProperty(QString::fromLatin1("name"), QScriptValue(eng, in.name())); - out.setProperty(QString::fromLatin1("value"), qScriptValueFromValue(eng, in.value())); + out.setProperty(QString::fromLatin1("value"), eng->toScriptValue(in.value())); out.setProperty(QString::fromLatin1("valueAsString"), QScriptValue(eng, in.valueAsString())); out.setProperty(QString::fromLatin1("flags"), QScriptValue(eng, static_cast<int>(in.flags()))); return out; diff --git a/src/scripttools/debugging/qscriptdebuggerevent.cpp b/src/scripttools/debugging/qscriptdebuggerevent.cpp index f5f20cf..55df35b 100644 --- a/src/scripttools/debugging/qscriptdebuggerevent.cpp +++ b/src/scripttools/debugging/qscriptdebuggerevent.cpp @@ -216,7 +216,7 @@ QScriptDebuggerValue QScriptDebuggerEvent::scriptValue() const void QScriptDebuggerEvent::setScriptValue(const QScriptDebuggerValue &value) { Q_D(QScriptDebuggerEvent); - d->attributes[Value] = qVariantFromValue(value); + d->attributes[Value] = QVariant::fromValue(value); } void QScriptDebuggerEvent::setNestedEvaluate(bool nested) diff --git a/src/scripttools/debugging/qscriptdebuggerresponse.cpp b/src/scripttools/debugging/qscriptdebuggerresponse.cpp index 0caa3e2..382e604e 100644 --- a/src/scripttools/debugging/qscriptdebuggerresponse.cpp +++ b/src/scripttools/debugging/qscriptdebuggerresponse.cpp @@ -162,49 +162,49 @@ void QScriptDebuggerResponse::setResult(const QString &value) void QScriptDebuggerResponse::setResult(const QScriptBreakpointData &data) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(data); + d->result = QVariant::fromValue(data); } void QScriptDebuggerResponse::setResult(const QScriptBreakpointMap &breakpoints) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(breakpoints); + d->result = QVariant::fromValue(breakpoints); } void QScriptDebuggerResponse::setResult(const QScriptScriptMap &scripts) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(scripts); + d->result = QVariant::fromValue(scripts); } void QScriptDebuggerResponse::setResult(const QScriptScriptData &data) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(data); + d->result = QVariant::fromValue(data); } void QScriptDebuggerResponse::setResult(const QScriptDebuggerValue &value) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(value); + d->result = QVariant::fromValue(value); } void QScriptDebuggerResponse::setResult(const QScriptDebuggerValueList &values) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(values); + d->result = QVariant::fromValue(values); } void QScriptDebuggerResponse::setResult(const QScriptDebuggerValuePropertyList &props) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(props); + d->result = QVariant::fromValue(props); } void QScriptDebuggerResponse::setResult(const QScriptContextInfo &info) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(info); + d->result = QVariant::fromValue(info); } int QScriptDebuggerResponse::resultAsInt() const diff --git a/src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp b/src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp index 117c2d6..83cabfd 100644 --- a/src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp +++ b/src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp @@ -227,7 +227,7 @@ void QScriptDebuggerScriptedConsoleCommandJob::handleResponse( QScriptEngine *engine = d->command->globalObject.engine(); engine->setGlobalObject(d->command->globalObject); QScriptValueList args; - args.append(qScriptValueFromValue(engine, response)); + args.append(engine->toScriptValue(response)); args.append(QScriptValue(engine, commandId)); QScriptDebuggerConsoleGlobalObject *global; global = qobject_cast<QScriptDebuggerConsoleGlobalObject*>(d->command->globalObject.toQObject()); diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index 2261887..a060a01 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -420,10 +420,10 @@ QVariant QMYSQLResult::handle() const { #if MYSQL_VERSION_ID >= 40108 if(d->preparedQuery) - return d->meta ? qVariantFromValue(d->meta) : qVariantFromValue(d->stmt); + return d->meta ? QVariant::fromValue(d->meta) : qVariantFromValue(d->stmt); else #endif - return qVariantFromValue(d->result); + return QVariant::fromValue(d->result); } void QMYSQLResult::cleanup() @@ -1432,7 +1432,7 @@ QSqlRecord QMYSQLDriver::record(const QString& tablename) const QVariant QMYSQLDriver::handle() const { - return qVariantFromValue(d->mysql); + return QVariant::fromValue(d->mysql); } bool QMYSQLDriver::beginTransaction() diff --git a/src/sql/drivers/oci/qsql_oci.cpp b/src/sql/drivers/oci/qsql_oci.cpp index e11cf75..6870055 100644 --- a/src/sql/drivers/oci/qsql_oci.cpp +++ b/src/sql/drivers/oci/qsql_oci.cpp @@ -293,9 +293,9 @@ int QOCIResultPrivate::bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, in SQLT_FLT, indPtr, 0, 0, 0, 0, OCI_DEFAULT); break; case QVariant::UserType: - if (qVariantCanConvert<QOCIRowIdPointer>(val) && !isOutValue(pos)) { + if (val.canConvert<QOCIRowIdPointer>() && !isOutValue(pos)) { // use a const pointer to prevent a detach - const QOCIRowIdPointer rptr = qVariantValue<QOCIRowIdPointer>(val); + const QOCIRowIdPointer rptr = qvariant_cast<QOCIRowIdPointer>(val); r = OCIBindByPos(sql, hbnd, err, pos + 1, // it's an IN value, so const_cast is ok @@ -1364,8 +1364,8 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b break; } case QVariant::UserType: - if (qVariantCanConvert<QOCIRowIdPointer>(val)) { - const QOCIRowIdPointer rptr = qVariantValue<QOCIRowIdPointer>(val); + if (val.canConvert<QOCIRowIdPointer>()) { + const QOCIRowIdPointer rptr = qvariant_cast<QOCIRowIdPointer>(val); *reinterpret_cast<OCIRowid**>(dataPtr) = rptr->id; columns[i].lengths[row] = 0; break; @@ -1704,7 +1704,7 @@ QOCIResult::~QOCIResult() QVariant QOCIResult::handle() const { - return qVariantFromValue(d->sql); + return QVariant::fromValue(d->sql); } bool QOCIResult::reset (const QString& query) @@ -1932,7 +1932,7 @@ QVariant QOCIResult::lastInsertId() const int r = OCIAttrGet(d->sql, OCI_HTYPE_STMT, ptr.constData()->id, 0, OCI_ATTR_ROWID, d->err); if (r == OCI_SUCCESS) - return qVariantFromValue(ptr); + return QVariant::fromValue(ptr); } return QVariant(); } @@ -2534,7 +2534,7 @@ QString QOCIDriver::formatValue(const QSqlField &field, bool trimStrings) const QVariant QOCIDriver::handle() const { - return qVariantFromValue(d->env); + return QVariant::fromValue(d->env); } QString QOCIDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index 66dabfa..3e77779 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -62,15 +62,6 @@ QT_BEGIN_NAMESPACE // undefine this to prevent initial check of the ODBC driver #define ODBC_CHECK_DRIVER -// newer platform SDKs use SQLLEN instead of SQLINTEGER -#if defined(WIN32) && (_MSC_VER < 1300) && !defined(__MINGW64_VERSION_MAJOR) -# define QSQLLEN SQLINTEGER -# define QSQLULEN SQLUINTEGER -#else -# define QSQLLEN SQLLEN -# define QSQLULEN SQLULEN -#endif - static const int COLNAMESIZE = 256; //Map Qt parameter types to ODBC types static const SQLSMALLINT qParamType[4] = { SQL_PARAM_INPUT, SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, SQL_PARAM_INPUT_OUTPUT }; @@ -360,7 +351,7 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni { QString fieldVal; SQLRETURN r = SQL_ERROR; - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; // NB! colSize must be a multiple of 2 for unicode enabled DBs if (colSize <= 0) { @@ -462,10 +453,10 @@ static QVariant qGetBinaryData(SQLHANDLE hStmt, int column) QByteArray fieldVal; SQLSMALLINT colNameLen; SQLSMALLINT colType; - QSQLULEN colSize; + SQLULEN colSize; SQLSMALLINT colScale; SQLSMALLINT nullable; - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; SQLRETURN r = SQL_ERROR; QVarLengthArray<SQLTCHAR> colName(COLNAMESIZE); @@ -499,7 +490,7 @@ static QVariant qGetBinaryData(SQLHANDLE hStmt, int column) break; if (lengthIndicator == SQL_NULL_DATA) return QVariant(QVariant::ByteArray); - if (lengthIndicator > QSQLLEN(colSize) || lengthIndicator == SQL_NO_TOTAL) { + if (lengthIndicator > SQLLEN(colSize) || lengthIndicator == SQL_NO_TOTAL) { read += colSize; colSize = 65536; } else { @@ -517,7 +508,7 @@ static QVariant qGetBinaryData(SQLHANDLE hStmt, int column) static QVariant qGetIntData(SQLHANDLE hStmt, int column, bool isSigned = true) { SQLINTEGER intbuf = 0; - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; SQLRETURN r = SQLGetData(hStmt, column+1, isSigned ? SQL_C_SLONG : SQL_C_ULONG, @@ -537,7 +528,7 @@ static QVariant qGetIntData(SQLHANDLE hStmt, int column, bool isSigned = true) static QVariant qGetDoubleData(SQLHANDLE hStmt, int column) { SQLDOUBLE dblbuf; - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; SQLRETURN r = SQLGetData(hStmt, column+1, SQL_C_DOUBLE, @@ -557,7 +548,7 @@ static QVariant qGetDoubleData(SQLHANDLE hStmt, int column) static QVariant qGetBigIntData(SQLHANDLE hStmt, int column, bool isSigned = true) { SQLBIGINT lngbuf = 0; - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; SQLRETURN r = SQLGetData(hStmt, column+1, isSigned ? SQL_C_SBIGINT : SQL_C_UBIGINT, @@ -601,7 +592,7 @@ static QSqlField qMakeFieldInfo(const QODBCPrivate* p, int i ) { SQLSMALLINT colNameLen; SQLSMALLINT colType; - QSQLULEN colSize; + SQLULEN colSize; SQLSMALLINT colScale; SQLSMALLINT nullable; SQLRETURN r = SQL_ERROR; @@ -621,7 +612,7 @@ static QSqlField qMakeFieldInfo(const QODBCPrivate* p, int i ) return QSqlField(); } - QSQLLEN unsignedFlag = SQL_FALSE; + SQLLEN unsignedFlag = SQL_FALSE; r = SQLColAttribute (p->hStmt, i + 1, SQL_DESC_UNSIGNED, @@ -1146,7 +1137,7 @@ QVariant QODBCResult::data(int field) return d->fieldCache.at(field); SQLRETURN r(0); - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; for (int i = d->fieldCacheIdx; i <= field; ++i) { // some servers do not support fetching column n after we already @@ -1256,7 +1247,7 @@ int QODBCResult::size() int QODBCResult::numRowsAffected() { - QSQLLEN affectedRowCount = 0; + SQLLEN affectedRowCount = 0; SQLRETURN r = SQLRowCount(d->hStmt, &affectedRowCount); if (r == SQL_SUCCESS) return affectedRowCount; @@ -1343,8 +1334,8 @@ bool QODBCResult::exec() SQLCloseCursor(d->hStmt); QList<QByteArray> tmpStorage; // holds temporary buffers - QVarLengthArray<QSQLLEN, 32> indicators(boundValues().count()); - memset(indicators.data(), 0, indicators.size() * sizeof(QSQLLEN)); + QVarLengthArray<SQLLEN, 32> indicators(boundValues().count()); + memset(indicators.data(), 0, indicators.size() * sizeof(SQLLEN)); // bind parameters - only positional binding allowed QVector<QVariant>& values = boundValues(); @@ -1354,7 +1345,7 @@ bool QODBCResult::exec() if (bindValueType(i) & QSql::Out) values[i].detach(); const QVariant &val = values.at(i); - QSQLLEN *ind = &indicators[i]; + SQLLEN *ind = &indicators[i]; if (val.isNull()) *ind = SQL_NULL_DATA; switch (val.type()) { diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 2a4e595..179f7ba 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -279,7 +279,7 @@ QPSQLResult::~QPSQLResult() QVariant QPSQLResult::handle() const { - return qVariantFromValue(d->result); + return QVariant::fromValue(d->result); } void QPSQLResult::cleanup() @@ -706,7 +706,7 @@ QPSQLDriver::~QPSQLDriver() QVariant QPSQLDriver::handle() const { - return qVariantFromValue(d->connection); + return QVariant::fromValue(d->connection); } bool QPSQLDriver::hasFeature(DriverFeature f) const diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp index 4344af4..e5cc614 100644 --- a/src/sql/drivers/sqlite/qsql_sqlite.cpp +++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp @@ -452,7 +452,7 @@ QSqlRecord QSQLiteResult::record() const QVariant QSQLiteResult::handle() const { - return qVariantFromValue(d->stmt); + return QVariant::fromValue(d->stmt); } ///////////////////////////////////////////////////////// @@ -697,7 +697,7 @@ QSqlRecord QSQLiteDriver::record(const QString &tbl) const QVariant QSQLiteDriver::handle() const { - return qVariantFromValue(d->access); + return QVariant::fromValue(d->access); } QString QSQLiteDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const diff --git a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp index ea476e5..89f3ed3 100644 --- a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp +++ b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp @@ -342,7 +342,7 @@ QSqlRecord QSQLite2Result::record() const QVariant QSQLite2Result::handle() const { - return qVariantFromValue(d->currentMachine); + return QVariant::fromValue(d->currentMachine); } ///////////////////////////////////////////////////////// @@ -558,7 +558,7 @@ QSqlRecord QSQLite2Driver::record(const QString &tbl) const QVariant QSQLite2Driver::handle() const { - return qVariantFromValue(d->access); + return QVariant::fromValue(d->access); } QString QSQLite2Driver::escapeIdentifier(const QString &identifier, IdentifierType /*type*/) const diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index 2ab37de..1cf5fde 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -166,7 +166,7 @@ public: static QSqlDatabase database(const QString& name, bool open); static void addDatabase(const QSqlDatabase &db, const QString & name); static void removeDatabase(const QString& name); - static void invalidateDb(const QSqlDatabase &db, const QString &name); + static void invalidateDb(const QSqlDatabase &db, const QString &name, bool doWarn = true); static DriverDict &driverDict(); static void cleanConnections(); }; @@ -200,7 +200,7 @@ void QSqlDatabasePrivate::cleanConnections() QConnectionDict::iterator it = dict->begin(); while (it != dict->end()) { - invalidateDb(it.value(), it.key()); + invalidateDb(it.value(), it.key(), false); ++it; } dict->clear(); @@ -232,9 +232,9 @@ QSqlDatabasePrivate *QSqlDatabasePrivate::shared_null() return &n; } -void QSqlDatabasePrivate::invalidateDb(const QSqlDatabase &db, const QString &name) +void QSqlDatabasePrivate::invalidateDb(const QSqlDatabase &db, const QString &name, bool doWarn) { - if (db.d->ref != 1) { + if (db.d->ref != 1 && doWarn) { qWarning("QSqlDatabasePrivate::removeDatabase: connection '%s' is still in use, " "all queries will cease to work.", name.toLocal8Bit().constData()); db.d->disable(); diff --git a/src/testlib/qabstracttestlogger_p.h b/src/testlib/qabstracttestlogger_p.h index c84f327..a996e88 100644 --- a/src/testlib/qabstracttestlogger_p.h +++ b/src/testlib/qabstracttestlogger_p.h @@ -95,6 +95,8 @@ public: virtual void addMessage(MessageTypes type, const char *message, const char *file = 0, int line = 0) = 0; + virtual void registerRandomSeed(unsigned int seed) = 0; + static void outputString(const char *msg); static bool isTtyOutput(); }; diff --git a/src/testlib/qplaintestlogger.cpp b/src/testlib/qplaintestlogger.cpp index 1a0e737..59248a9 100644 --- a/src/testlib/qplaintestlogger.cpp +++ b/src/testlib/qplaintestlogger.cpp @@ -384,6 +384,7 @@ namespace QTest { } QPlainTestLogger::QPlainTestLogger() +: randomSeed(9), hasRandomSeed(false) { #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) InitializeCriticalSection(&QTest::outputCriticalSection); @@ -415,10 +416,17 @@ void QPlainTestLogger::startLogging() QTest::qt_snprintf(buf, sizeof(buf), "Testing %s\n", QTestResult::currentTestObjectName()); } else { - QTest::qt_snprintf(buf, sizeof(buf), - "********* Start testing of %s *********\n" - "Config: Using QTest library " QTEST_VERSION_STR - ", Qt %s\n", QTestResult::currentTestObjectName(), qVersion()); + if (hasRandomSeed) { + QTest::qt_snprintf(buf, sizeof(buf), + "********* Start testing of %s *********\n" + "Config: Using QTest library " QTEST_VERSION_STR + ", Qt %s, Random seed %d\n", QTestResult::currentTestObjectName(), qVersion(), randomSeed); + } else { + QTest::qt_snprintf(buf, sizeof(buf), + "********* Start testing of %s *********\n" + "Config: Using QTest library " QTEST_VERSION_STR + ", Qt %s\n", QTestResult::currentTestObjectName(), qVersion()); + } } QTest::outputMessage(buf); } @@ -480,4 +488,10 @@ void QPlainTestLogger::addMessage(MessageTypes type, const char *message, QTest::printMessage(QTest::messageType2String(type), message, file, line); } +void QPlainTestLogger::registerRandomSeed(unsigned int seed) +{ + randomSeed = seed; + hasRandomSeed = true; +} + QT_END_NAMESPACE diff --git a/src/testlib/qplaintestlogger_p.h b/src/testlib/qplaintestlogger_p.h index f1f1d4e..9195600 100644 --- a/src/testlib/qplaintestlogger_p.h +++ b/src/testlib/qplaintestlogger_p.h @@ -75,6 +75,10 @@ public: void addMessage(MessageTypes type, const char *message, const char *file = 0, int line = 0); + void registerRandomSeed(unsigned int seed); +private: + unsigned int randomSeed; + bool hasRandomSeed; }; QT_END_NAMESPACE diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index 633d635..aa9b2bd 100644 --- a/src/testlib/qtest.h +++ b/src/testlib/qtest.h @@ -159,7 +159,7 @@ template<> inline char *toString(const QVariant &v) if (!v.isNull()) { vstring.append(','); if (v.canConvert(QVariant::String)) { - vstring.append(qVariantValue<QString>(v).toLatin1()); + vstring.append(qvariant_cast<QString>(v).toLatin1()); } else { vstring.append("<value not representable as string>"); diff --git a/src/testlib/qtest_global.h b/src/testlib/qtest_global.h index a78113a..4dd0cb7 100644 --- a/src/testlib/qtest_global.h +++ b/src/testlib/qtest_global.h @@ -62,7 +62,7 @@ QT_MODULE(Test) # endif #endif -#if (defined (Q_CC_MSVC) && _MSC_VER < 1310) || defined (Q_CC_SUN) || defined (Q_CC_XLC) || (defined (Q_CC_GNU) && (__GNUC__ - 0 < 3)) || defined (Q_CC_NOKIAX86) +#if defined (Q_CC_SUN) || defined (Q_CC_XLC) || (defined (Q_CC_GNU) && (__GNUC__ - 0 < 3)) || defined (Q_CC_NOKIAX86) # define QTEST_NO_SPECIALIZATIONS #endif diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 17f1a6b..aae2786 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -826,25 +826,46 @@ namespace QTest { static QObject *currentTestObject = 0; - static struct TestFunction { - TestFunction():function(0), data(0) {} - ~TestFunction() { delete [] data; } - int function; - char *data; - } *testFuncs; - + class TestFunction { + public: + TestFunction() : function_(-1), data_(0) {} + void set(int function, char *data) { function_ = function; data_ = data; } + char *data() const { return data_; } + int function() const { return function_; } + ~TestFunction() { delete[] data_; } + private: + int function_; + char *data_; + }; /** - * Contains the count of test functions that was supplied - * on the command line, if any. Hence, if lastTestFuncIdx is - * more than zero, those functions should be run instead of + * Contains the list of test functions that was supplied + * on the command line, if any. Hence, if not empty, + * those functions should be run instead of * all appearing in the test case. */ - static int lastTestFuncIdx = -1; + static TestFunction * testFuncs = 0; + static int testFuncCount = 0; + + /** Don't leak testFuncs on exit even on error */ + static struct TestFuncCleanup + { + void cleanup() + { + delete[] testFuncs; + testFuncCount = 0; + testFuncs = 0; + } + + ~TestFuncCleanup() { cleanup(); } + } testFuncCleaner; static int keyDelay = -1; static int mouseDelay = -1; static int eventDelay = -1; + static bool randomOrder = false; static int keyVerbose = -1; + static unsigned int seed = 0; + static bool seedSet = false; #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) static bool noCrashHandler = false; #endif @@ -930,6 +951,43 @@ int Q_TESTLIB_EXPORT defaultKeyDelay() return keyDelay; } +void seedRandom() +{ + static bool randomSeeded = false; + if (!randomSeeded) { + if (!QTest::seedSet) { + QElapsedTimer timer; + timer.start(); + QTest::seed = timer.msecsSinceReference(); + } + qsrand(QTest::seed); + randomSeeded = true; + } +} + +int qTestRandomSeed() +{ + Q_ASSERT(QTest::seedSet); + return QTest::seed; +} + +template<typename T> +void swap(T * array, int pos, int otherPos) +{ + T tmp = array[pos]; + array[pos] = array[otherPos]; + array[otherPos] = tmp; +} + +template<typename T> +static void randomizeList(T * array, int size) +{ + for (int i = 0; i != size; i++) { + int pos = qrand() % size; + swap(array, pos, i); + } +} + static bool isValidSlot(const QMetaMethod &sl) { if (sl.access() != QMetaMethod::Private || !sl.parameterTypes().isEmpty() @@ -971,8 +1029,6 @@ static int qToInt(char *str) static void qParseArgs(int argc, char *argv[]) { - lastTestFuncIdx = -1; - const char *testOptions = " options:\n" " -functions : Returns a list of current testfunctions\n" @@ -985,6 +1041,9 @@ static void qParseArgs(int argc, char *argv[]) " -v1 : Print enter messages for each testfunction\n" " -v2 : Also print out each QVERIFY/QCOMPARE/QTEST\n" " -vs : Print every signal emitted\n" + " -random : Run testcases within each test in random order\n" + " -seed n : Positive integer to be used as seed for -random. If not specified,\n" + " the current time will be used as seed.\n" " -eventdelay ms : Set default delay for mouse and keyboard simulation to ms milliseconds\n" " -keydelay ms : Set default delay for keyboard simulation to ms milliseconds\n" " -mousedelay ms : Set default delay for mouse simulation to ms milliseconds\n" @@ -1100,6 +1159,22 @@ static void qParseArgs(int argc, char *argv[]) #endif } else if (strcmp(argv[i], "-eventcounter") == 0) { QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::EventCounter); + } else if (strcmp(argv[i], "-random") == 0) { + QTest::randomOrder = true; + } else if (strcmp(argv[i], "-seed") == 0) { + bool argumentOk = false; + if (i + 1 < argc) { + char * endpt = 0; + long longSeed = strtol(argv[++i], &endpt, 10); + argumentOk = (*endpt == '\0' && longSeed >= 0); + QTest::seed = longSeed; + } + if (!argumentOk) { + printf("-seed needs an extra positive integer parameter to specify the seed\n"); + exit(1); + } else { + QTest::seedSet = true; + } } else if (strcmp(argv[i], "-minimumvalue") == 0) { if (i + 1 >= argc) { printf("-minimumvalue needs an extra parameter to indicate the minimum time(ms)\n"); @@ -1140,6 +1215,10 @@ static void qParseArgs(int argc, char *argv[]) printf("Unknown option: '%s'\n\n%s", argv[i], testOptions); exit(1); } else { + if (!QTest::testFuncs) { + QTest::testFuncs = new QTest::TestFunction[512]; + } + int colon = -1; char buf[512], *data=0; int off; @@ -1161,17 +1240,16 @@ static void qParseArgs(int argc, char *argv[]) qPrintTestSlots(); exit(1); } - ++QTest::lastTestFuncIdx; - if (!QTest::testFuncs) { - struct Cleanup { ~Cleanup() { delete[] QTest::testFuncs; } }; - static Cleanup cleanup; - QTest::testFuncs = new TestFunction[512]; - } - QTest::testFuncs[QTest::lastTestFuncIdx].function = idx; - QTest::testFuncs[QTest::lastTestFuncIdx].data = data; - QTEST_ASSERT(QTest::lastTestFuncIdx < 512); + testFuncs[testFuncCount].set(idx, data); + testFuncCount++; + QTEST_ASSERT(QTest::testFuncCount < 512); } } + + if (QTest::seedSet && !QTest::randomOrder) { + printf("-seed requires -random\n"); + exit(1); + } } QBenchmarkResult qMedian(const QList<QBenchmarkResult> &container) @@ -1466,9 +1544,11 @@ static void qInvokeTestMethods(QObject *testObject) { const QMetaObject *metaObject = testObject->metaObject(); QTEST_ASSERT(metaObject); - - QTestLog::startLogging(); - + if (QTest::randomOrder) { + QTestLog::startLogging(QTest::seed); + } else { + QTestLog::startLogging(); + } QTestResult::setCurrentTestFunction("initTestCase"); QTestResult::setCurrentTestLocation(QTestResult::DataFunc); QTestTable::globalTestTable(); @@ -1484,21 +1564,31 @@ static void qInvokeTestMethods(QObject *testObject) if(!QTestResult::skipCurrentTest() && !previousFailed) { - if (lastTestFuncIdx >= 0) { - for (int i = 0; i <= lastTestFuncIdx; ++i) { - if (!qInvokeTestMethod(metaObject->method(testFuncs[i].function).signature(), - testFuncs[i].data)) + if (QTest::testFuncs) { + if (QTest::randomOrder) + randomizeList(QTest::testFuncs, QTest::testFuncCount); + for (int i = 0; i != QTest::testFuncCount; i++) { + if (!qInvokeTestMethod(metaObject->method(QTest::testFuncs[i].function()).signature(), + QTest::testFuncs[i].data())) { break; + } } + testFuncCleaner.cleanup(); } else { int methodCount = metaObject->methodCount(); - for (int i = 0; i < methodCount; ++i) { - QMetaMethod slotMethod = metaObject->method(i); - if (!isValidSlot(slotMethod)) + QMetaMethod *testMethods = new QMetaMethod[methodCount]; + for (int i = 0; i != methodCount; i++) + testMethods[i] = metaObject->method(i); + if (QTest::randomOrder) + randomizeList(testMethods, methodCount); + for (int i = 0; i != methodCount; i++) { + if (!isValidSlot(testMethods[i])) continue; - if (!qInvokeTestMethod(slotMethod.signature())) + if (!qInvokeTestMethod(testMethods[i].signature())) break; } + delete[] testMethods; + testMethods = 0; } } @@ -1689,6 +1779,9 @@ int QTest::qExec(QObject *testObject, int argc, char **argv) QTestResult::setCurrentTestObject(metaObject->className()); qParseArgs(argc, argv); + if (QTest::randomOrder) { + seedRandom(); + } #ifdef QTESTLIB_USE_VALGRIND if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) { const QStringList origAppArgs(QCoreApplication::arguments()); diff --git a/src/testlib/qtestlightxmlstreamer.cpp b/src/testlib/qtestlightxmlstreamer.cpp index 0ac9ea8..cc5397a 100644 --- a/src/testlib/qtestlightxmlstreamer.cpp +++ b/src/testlib/qtestlightxmlstreamer.cpp @@ -42,6 +42,7 @@ #include "qtestlightxmlstreamer.h" #include "qtestelement.h" #include "qtestelementattribute.h" +#include "qtestlogger_p.h" #include "QtTest/private/qtestlog_p.h" #include "QtTest/private/qtestresult_p.h" @@ -164,8 +165,13 @@ void QTestLightXmlStreamer::formatBeforeAttributes(const QTestElement *element, void QTestLightXmlStreamer::output(QTestElement *element) const { QTestCharBuffer buf; - QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", + if (logger()->hasRandomSeed()) { + QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n <RandomSeed>%d</RandomSeed>\n", + qVersion(), QTEST_VERSION_STR, logger()->randomSeed() ); + } else { + QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", qVersion(), QTEST_VERSION_STR ); + } outputString(buf.constData()); QTest::qt_asprintf(&buf, "</Environment>\n"); diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp index 398dec5..d58e231 100644 --- a/src/testlib/qtestlog.cpp +++ b/src/testlib/qtestlog.cpp @@ -168,6 +168,29 @@ namespace QTest { } } +void initLogger() +{ + switch (QTest::logMode) { + case QTestLog::Plain: + QTest::testLogger = new QPlainTestLogger; + break; + case QTestLog::XML:{ + if(QTest::flushMode == QTestLog::FLushOn) + QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Complete); + else + QTest::testLogger = new QTestLogger(QTestLogger::TLF_XML); + break; + }case QTestLog::LightXML:{ + if(QTest::flushMode == QTestLog::FLushOn) + QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Light); + else + QTest::testLogger = new QTestLogger(QTestLogger::TLF_LightXml); + break; + }case QTestLog::XunitXML: + QTest::testLogger = new QTestLogger(QTestLogger::TLF_XunitXml); + } +} + } QTestLog::QTestLog() @@ -268,32 +291,20 @@ void QTestLog::addBenchmarkResult(const QBenchmarkResult &result) QTest::testLogger->addBenchmarkResult(result); } -void QTestLog::startLogging() +void QTestLog::startLogging(unsigned int randomSeed) { QTEST_ASSERT(!QTest::testLogger); - - switch (QTest::logMode) { - case QTestLog::Plain: - QTest::testLogger = new QPlainTestLogger; - break; - case QTestLog::XML:{ - if(QTest::flushMode == QTestLog::FLushOn) - QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Complete); - else - QTest::testLogger = new QTestLogger(QTestLogger::TLF_XML); - break; - }case QTestLog::LightXML:{ - if(QTest::flushMode == QTestLog::FLushOn) - QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Light); - else - QTest::testLogger = new QTestLogger(QTestLogger::TLF_LightXml); - break; - }case QTestLog::XunitXML: - QTest::testLogger = new QTestLogger(QTestLogger::TLF_XunitXml); - } - + QTest::initLogger(); + QTest::testLogger->registerRandomSeed(randomSeed); QTest::testLogger->startLogging(); + QTest::oldMessageHandler = qInstallMsgHandler(QTest::messageHandler); +} +void QTestLog::startLogging() +{ + QTEST_ASSERT(!QTest::testLogger); + QTest::initLogger(); + QTest::testLogger->startLogging(); QTest::oldMessageHandler = qInstallMsgHandler(QTest::messageHandler); } diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h index d36ff04..01d39eb 100644 --- a/src/testlib/qtestlog_p.h +++ b/src/testlib/qtestlog_p.h @@ -83,6 +83,7 @@ public: static void info(const char *msg, const char *file, int line); static void startLogging(); + static void startLogging(unsigned int randomSeed); static void stopLogging(); static void setLogMode(LogMode mode); @@ -97,7 +98,6 @@ public: static void setMaxWarnings(int max); static void setFlushMode(FlushMode mode); - private: QTestLog(); ~QTestLog(); diff --git a/src/testlib/qtestlogger.cpp b/src/testlib/qtestlogger.cpp index f0be6be..cab97d1 100644 --- a/src/testlib/qtestlogger.cpp +++ b/src/testlib/qtestlogger.cpp @@ -62,7 +62,8 @@ QTestLogger::QTestLogger(int fm) warningCounter(0), skipCounter(0), systemCounter(0), qdebugCounter(0), qwarnCounter(0), qfatalCounter(0), - infoCounter(0) + infoCounter(0), randomSeed_(0), + hasRandomSeed_(false) { } @@ -133,6 +134,14 @@ void QTestLogger::stopLogging() property->addAttribute(QTest::AI_PropertyValue, qVersion()); properties->addLogElement(property); + if (hasRandomSeed()) { + property = new QTestElement(QTest::LET_Property); + property->addAttribute(QTest::AI_Name, "RandomSeed"); + QTest::qt_snprintf(buf, sizeof(buf), "%i", randomSeed()); + property->addAttribute(QTest::AI_PropertyValue, buf); + properties->addLogElement(property); + } + currentLogElement->addLogElement(properties); currentLogElement->addLogElement(iterator); @@ -420,5 +429,21 @@ int QTestLogger::infoCount() const return infoCounter; } +void QTestLogger::registerRandomSeed(unsigned int seed) +{ + randomSeed_ = seed; + hasRandomSeed_ = true; +} + +unsigned int QTestLogger::randomSeed() const +{ + return randomSeed_; +} + +bool QTestLogger::hasRandomSeed() const +{ + return hasRandomSeed_; +} + QT_END_NAMESPACE diff --git a/src/testlib/qtestlogger_p.h b/src/testlib/qtestlogger_p.h index bb7a358..8932a85 100644 --- a/src/testlib/qtestlogger_p.h +++ b/src/testlib/qtestlogger_p.h @@ -101,6 +101,9 @@ class QTestLogger : public QAbstractTestLogger int qwarnCount() const; int qfatalCount() const; int infoCount() const; + void registerRandomSeed(unsigned int seed); + unsigned int randomSeed() const; + bool hasRandomSeed() const; private: QTestElement *listOfTestcases; @@ -121,6 +124,8 @@ class QTestLogger : public QAbstractTestLogger int qwarnCounter; int qfatalCounter; int infoCounter; + unsigned int randomSeed_; + bool hasRandomSeed_; }; QT_END_NAMESPACE diff --git a/src/testlib/qtestresult.cpp b/src/testlib/qtestresult.cpp index 8c52a82..bbe3e7f 100644 --- a/src/testlib/qtestresult.cpp +++ b/src/testlib/qtestresult.cpp @@ -191,10 +191,13 @@ bool QTestResult::expectFail(const char *dataIndex, const char *comment, QTEST_ASSERT(comment); QTEST_ASSERT(mode > 0); - if (!isExpectFailData(dataIndex)) + if (!isExpectFailData(dataIndex)) { + delete[] comment; return true; // we don't care + } if (QTest::expectFailMode) { + delete[] comment; clearExpectFail(); addFailure("Already expecting a fail", file, line); return false; diff --git a/src/testlib/qtestxmlstreamer.cpp b/src/testlib/qtestxmlstreamer.cpp index f63c221..a6b8376 100644 --- a/src/testlib/qtestxmlstreamer.cpp +++ b/src/testlib/qtestxmlstreamer.cpp @@ -42,6 +42,7 @@ #include "qtestxmlstreamer.h" #include "qtestelement.h" #include "qtestelementattribute.h" +#include "qtestlogger_p.h" #include "QtTest/private/qtestlog_p.h" #include "QtTest/private/qtestresult_p.h" @@ -204,8 +205,13 @@ void QTestXmlStreamer::output(QTestElement *element) const quotedTc.constData()); outputString(buf.constData()); - QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", - qVersion(), QTEST_VERSION_STR ); + if (logger()->hasRandomSeed()) { + QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n <RandomSeed>%d</RandomSeed>\n", + qVersion(), QTEST_VERSION_STR, logger()->randomSeed() ); + } else { + QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", + qVersion(), QTEST_VERSION_STR ); + } outputString(buf.constData()); QTest::qt_asprintf(&buf, "</Environment>\n"); diff --git a/src/testlib/qxmltestlogger.cpp b/src/testlib/qxmltestlogger.cpp index 07e8ef0..2bf7d77 100644 --- a/src/testlib/qxmltestlogger.cpp +++ b/src/testlib/qxmltestlogger.cpp @@ -93,7 +93,7 @@ namespace QTest { QXmlTestLogger::QXmlTestLogger(XmlMode mode ) - :xmlmode(mode) + :xmlmode(mode), randomSeed(0), hasRandomSeed(false) { } @@ -116,11 +116,20 @@ void QXmlTestLogger::startLogging() outputString(buf.constData()); } - QTest::qt_asprintf(&buf, - "<Environment>\n" - " <QtVersion>%s</QtVersion>\n" - " <QTestVersion>"QTEST_VERSION_STR"</QTestVersion>\n" - "</Environment>\n", qVersion()); + if (hasRandomSeed) { + QTest::qt_asprintf(&buf, + "<Environment>\n" + " <QtVersion>%s</QtVersion>\n" + " <QTestVersion>"QTEST_VERSION_STR"</QTestVersion>\n" + " <RandomSeed>%d</RandomSeed>\n" + "</Environment>\n", qVersion(), randomSeed); + } else { + QTest::qt_asprintf(&buf, + "<Environment>\n" + " <QtVersion>%s</QtVersion>\n" + " <QTestVersion>"QTEST_VERSION_STR"</QTestVersion>\n" + "</Environment>\n", qVersion()); + } outputString(buf.constData()); } @@ -441,4 +450,10 @@ int QXmlTestLogger::xmlCdata(QTestCharBuffer* str, char const* src) return allocateStringFn(str, src, QXmlTestLogger::xmlCdata); } +void QXmlTestLogger::registerRandomSeed(unsigned int seed) +{ + randomSeed = seed; + hasRandomSeed = true; +} + QT_END_NAMESPACE diff --git a/src/testlib/qxmltestlogger_p.h b/src/testlib/qxmltestlogger_p.h index ae918dc..82dd8a6 100644 --- a/src/testlib/qxmltestlogger_p.h +++ b/src/testlib/qxmltestlogger_p.h @@ -79,6 +79,8 @@ public: void addMessage(MessageTypes type, const char *message, const char *file = 0, int line = 0); + void registerRandomSeed(unsigned int seed); + static int xmlCdata(QTestCharBuffer *dest, char const* src); static int xmlQuote(QTestCharBuffer *dest, char const* src); static int xmlCdata(QTestCharBuffer *dest, char const* src, size_t n); @@ -86,6 +88,8 @@ public: private: XmlMode xmlmode; + unsigned int randomSeed; + bool hasRandomSeed; }; QT_END_NAMESPACE diff --git a/src/tools/bootstrap/bootstrap.pri b/src/tools/bootstrap/bootstrap.pri index 1aa8121..f48c8c1 100644 --- a/src/tools/bootstrap/bootstrap.pri +++ b/src/tools/bootstrap/bootstrap.pri @@ -22,7 +22,9 @@ DEFINES += \ QT_NO_TEXTSTREAM \ QT_NO_THREAD \ QT_NO_UNICODETABLES \ - QT_NO_USING_NAMESPACE + QT_NO_USING_NAMESPACE \ + QT_NO_DEPRECATED + win32:DEFINES += QT_NODLL INCLUDEPATH += $$QT_BUILD_TREE/include \ diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index ba844ea..27b7336 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -25,7 +25,9 @@ DEFINES += \ QT_NO_TEXTSTREAM \ QT_NO_THREAD \ QT_NO_UNICODETABLES \ - QT_NO_USING_NAMESPACE + QT_NO_USING_NAMESPACE \ + QT_NO_DEPRECATED + win32:DEFINES += QT_NODLL INCLUDEPATH += $$QT_BUILD_TREE/include \ diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp index b06eb7a..a2bc89d 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.cpp +++ b/src/tools/uic/cpp/cppwriteinitialization.cpp @@ -139,13 +139,17 @@ namespace { << indent << "QWidgetList childWidgets;\n"; } - static inline bool isIconFormat44(const DomResourceIcon *i) { + static inline bool iconHasStatePixmaps(const DomResourceIcon *i) { return i->hasElementNormalOff() || i->hasElementNormalOn() || i->hasElementDisabledOff() || i->hasElementDisabledOn() || i->hasElementActiveOff() || i->hasElementActiveOn() || i->hasElementSelectedOff() || i->hasElementSelectedOn(); } + static inline bool isIconFormat44(const DomResourceIcon *i) { + return iconHasStatePixmaps(i) || !i->attributeTheme().isEmpty(); + } + // Check on properties. Filter out empty legacy pixmap/icon properties // as Designer pre 4.4 used to remove missing resource references. // This can no longer be handled by the code as we have 'setIcon(QIcon())' as well as 'QIcon icon' @@ -258,6 +262,9 @@ IconHandle::IconHandle(const DomResourceIcon *domIcon) : int IconHandle::compare(const IconHandle &rhs) const { + if (const int comp = m_domIcon->attributeTheme().compare(rhs.m_domIcon->attributeTheme())) + return comp; + const QString normalOff = m_domIcon->hasElementNormalOff() ? m_domIcon->elementNormalOff()->text() : QString(); const QString rhsNormalOff = rhs.m_domIcon->hasElementNormalOff() ? rhs.m_domIcon->elementNormalOff()->text() : QString(); if (const int comp = normalOff.compare(rhsNormalOff)) @@ -478,7 +485,8 @@ WriteInitialization::WriteInitialization(Uic *uic, bool activateScripts) : m_delayedOut(&m_delayedInitialization, QIODevice::WriteOnly), m_refreshOut(&m_refreshInitialization, QIODevice::WriteOnly), m_actionOut(&m_delayedActionInitialization, QIODevice::WriteOnly), - m_activateScripts(activateScripts), m_layoutWidget(false) + m_activateScripts(activateScripts), m_layoutWidget(false), + m_firstThemeIcon(true) { } @@ -1670,6 +1678,30 @@ QString WriteInitialization::writeFontProperties(const DomFont *f) return fontName; } +// Post 4.4 write resource icon +static void writeResourceIcon(QTextStream &output, + const QString &iconName, + const QString &indent, + const DomResourceIcon *i) +{ + if (i->hasElementNormalOff()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOff()->text(), indent) << "), QSize(), QIcon::Normal, QIcon::Off);\n"; + if (i->hasElementNormalOn()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOn()->text(), indent) << "), QSize(), QIcon::Normal, QIcon::On);\n"; + if (i->hasElementDisabledOff()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementDisabledOff()->text(), indent) << "), QSize(), QIcon::Disabled, QIcon::Off);\n"; + if (i->hasElementDisabledOn()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementDisabledOn()->text(), indent) << "), QSize(), QIcon::Disabled, QIcon::On);\n"; + if (i->hasElementActiveOff()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementActiveOff()->text(), indent) << "), QSize(), QIcon::Active, QIcon::Off);\n"; + if (i->hasElementActiveOn()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementActiveOn()->text(), indent) << "), QSize(), QIcon::Active, QIcon::On);\n"; + if (i->hasElementSelectedOff()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementSelectedOff()->text(), indent) << "), QSize(), QIcon::Selected, QIcon::Off);\n"; + if (i->hasElementSelectedOn()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementSelectedOn()->text(), indent) << "), QSize(), QIcon::Selected, QIcon::On);\n"; +} + QString WriteInitialization::writeIconProperties(const DomResourceIcon *i) { // check cache @@ -1683,25 +1715,41 @@ QString WriteInitialization::writeIconProperties(const DomResourceIcon *i) const QString iconName = m_driver->unique(QLatin1String("icon")); m_iconPropertiesNameMap.insert(IconHandle(i), iconName); if (isIconFormat44(i)) { - const QString pixmap = QLatin1String("QPixmap"); - m_output << m_indent << "QIcon " << iconName << ";\n"; - if (i->hasElementNormalOff()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOff()->text(), m_dindent) << "), QSize(), QIcon::Normal, QIcon::Off);\n"; - if (i->hasElementNormalOn()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOn()->text(), m_dindent) << "), QSize(), QIcon::Normal, QIcon::On);\n"; - if (i->hasElementDisabledOff()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementDisabledOff()->text(), m_dindent) << "), QSize(), QIcon::Disabled, QIcon::Off);\n"; - if (i->hasElementDisabledOn()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementDisabledOn()->text(), m_dindent) << "), QSize(), QIcon::Disabled, QIcon::On);\n"; - if (i->hasElementActiveOff()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementActiveOff()->text(), m_dindent) << "), QSize(), QIcon::Active, QIcon::Off);\n"; - if (i->hasElementActiveOn()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementActiveOn()->text(), m_dindent) << "), QSize(), QIcon::Active, QIcon::On);\n"; - if (i->hasElementSelectedOff()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementSelectedOff()->text(), m_dindent) << "), QSize(), QIcon::Selected, QIcon::Off);\n"; - if (i->hasElementSelectedOn()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementSelectedOn()->text(), m_dindent) << "), QSize(), QIcon::Selected, QIcon::On);\n"; - } else { // pre-4.4 legacy + if (i->attributeTheme().isEmpty()) { + // No theme: Write resource icon as is + m_output << m_indent << "QIcon " << iconName << ";\n"; + writeResourceIcon(m_output, iconName, m_indent, i); + } else { + // Theme: Generate code to check the theme and default to resource + const QString themeIconName = fixString(i->attributeTheme(), QString()); + if (iconHasStatePixmaps(i)) { + // Theme + default state pixmaps: + // Generate code to check the theme and default to state pixmaps + m_output << m_indent << "QIcon " << iconName << ";\n"; + const char themeNameStringVariableC[] = "iconThemeName"; + // Store theme name in a variable + m_output << m_indent; + if (m_firstThemeIcon) { // Declare variable string + m_output << "QString "; + m_firstThemeIcon = false; + } + m_output << themeNameStringVariableC << " = QString::fromUtf8(" + << themeIconName << ");\n"; + m_output << m_indent << "if (QIcon::hasThemeIcon(" + << themeNameStringVariableC + << ")) {\n" + << m_dindent << iconName << " = QIcon::fromTheme(" << themeNameStringVariableC << ");\n" + << m_indent << "} else {\n"; + writeResourceIcon(m_output, iconName, m_dindent, i); + m_output << m_indent << "}\n"; + } else { + // Theme, but no state pixmaps: Construct from theme directly. + m_output << m_indent << "QIcon " << iconName + << "(QIcon::fromTheme(QString::fromUtf8(" + << themeIconName << ")));\n"; + } // Theme, but not state + } // >= 4.4 + } else { // pre-4.4 legacy m_output << m_indent << "const QIcon " << iconName << " = " << pixCall(QLatin1String("QIcon"), i->text())<< ";\n"; } return iconName; diff --git a/src/tools/uic/cpp/cppwriteinitialization.h b/src/tools/uic/cpp/cppwriteinitialization.h index 7507166..b9cf2cd 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.h +++ b/src/tools/uic/cpp/cppwriteinitialization.h @@ -363,6 +363,7 @@ private: const bool m_activateScripts; bool m_layoutWidget; + bool m_firstThemeIcon; }; } // namespace CPP diff --git a/src/tools/uic/ui4.cpp b/src/tools/uic/ui4.cpp index e80523f..1988696 100644 --- a/src/tools/uic/ui4.cpp +++ b/src/tools/uic/ui4.cpp @@ -7745,6 +7745,7 @@ void DomResourceIcon::clear(bool clear_all) if (clear_all) { m_text = QLatin1String(""); + m_has_attr_theme = false; m_has_attr_resource = false; } @@ -7762,6 +7763,7 @@ void DomResourceIcon::clear(bool clear_all) DomResourceIcon::DomResourceIcon() { m_children = 0; + m_has_attr_theme = false; m_has_attr_resource = false; m_text = QLatin1String(""); m_normalOff = 0; @@ -7791,6 +7793,10 @@ void DomResourceIcon::read(QXmlStreamReader &reader) foreach (const QXmlStreamAttribute &attribute, reader.attributes()) { QStringRef name = attribute.name(); + if (name == QLatin1String("theme")) { + setAttributeTheme(attribute.value().toString()); + continue; + } if (name == QLatin1String("resource")) { setAttributeResource(attribute.value().toString()); continue; @@ -7869,6 +7875,8 @@ void DomResourceIcon::read(QXmlStreamReader &reader) #ifdef QUILOADER_QDOM_READ void DomResourceIcon::read(const QDomElement &node) { + if (node.hasAttribute(QLatin1String("theme"))) + setAttributeTheme(node.attribute(QLatin1String("theme"))); if (node.hasAttribute(QLatin1String("resource"))) setAttributeResource(node.attribute(QLatin1String("resource"))); @@ -7938,6 +7946,9 @@ void DomResourceIcon::write(QXmlStreamWriter &writer, const QString &tagName) co { writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("resourceicon") : tagName.toLower()); + if (hasAttributeTheme()) + writer.writeAttribute(QLatin1String("theme"), attributeTheme()); + if (hasAttributeResource()) writer.writeAttribute(QLatin1String("resource"), attributeResource()); diff --git a/src/tools/uic/ui4.h b/src/tools/uic/ui4.h index 1f38f88..a464a89 100644 --- a/src/tools/uic/ui4.h +++ b/src/tools/uic/ui4.h @@ -2809,6 +2809,11 @@ public: inline void setText(const QString &s) { m_text = s; } // attribute accessors + inline bool hasAttributeTheme() const { return m_has_attr_theme; } + inline QString attributeTheme() const { return m_attr_theme; } + inline void setAttributeTheme(const QString& a) { m_attr_theme = a; m_has_attr_theme = true; } + inline void clearAttributeTheme() { m_has_attr_theme = false; } + inline bool hasAttributeResource() const { return m_has_attr_resource; } inline QString attributeResource() const { return m_attr_resource; } inline void setAttributeResource(const QString& a) { m_attr_resource = a; m_has_attr_resource = true; } @@ -2868,6 +2873,9 @@ private: void clear(bool clear_all = true); // attribute data + QString m_attr_theme; + bool m_has_attr_theme; + QString m_attr_resource; bool m_has_attr_resource; diff --git a/src/tools/uic3/converter.cpp b/src/tools/uic3/converter.cpp index 2ee939d..8fac4d1 100644 --- a/src/tools/uic3/converter.cpp +++ b/src/tools/uic3/converter.cpp @@ -864,7 +864,7 @@ DomLayoutItem *Ui3Reader::createLayoutItem(const QDomElement &e) Variant var; var.createSize(0, 0); - QVariant def = qVariantFromValue(var); + QVariant def = QVariant::fromValue(var); Size size = asVariant(DomTool::readProperty(e, QLatin1String("sizeHint"), def)).size; QString sizeType = QLatin1String("QSizePolicy::") + DomTool::readProperty(e, QLatin1String("sizeType"), QLatin1String("Expanding")).toString(); diff --git a/src/tools/uic3/domtool.cpp b/src/tools/uic3/domtool.cpp index 526b41c..cefbbb4 100644 --- a/src/tools/uic3/domtool.cpp +++ b/src/tools/uic3/domtool.cpp @@ -169,7 +169,7 @@ QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValu n3 = n3.nextSibling().toElement(); } var.createRect(x, y, w, h); - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("point")) { QDomElement n3 = e.firstChild().toElement(); int x = 0, y = 0; @@ -181,7 +181,7 @@ QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValu n3 = n3.nextSibling().toElement(); } var.createPoint(x,y); - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("size")) { QDomElement n3 = e.firstChild().toElement(); int w = 0, h = 0; @@ -193,10 +193,10 @@ QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValu n3 = n3.nextSibling().toElement(); } var.createSize(w, h); - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("color")) { var.color = readColor(e); - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("font")) { QDomElement n3 = e.firstChild().toElement(); Font f; @@ -217,7 +217,7 @@ QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValu n3 = n3.nextSibling().toElement(); } var.font = f; - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("string")) { v = QVariant(e.firstChild().toText().data()); QDomElement n = e; @@ -258,10 +258,10 @@ QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValu var.sizePolicy.verstretch = n3.firstChild().toText().data().toInt(); n3 = n3.nextSibling().toElement(); } - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("cursor")) { var.createCursor(e.firstChild().toText().data().toInt()); - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("stringlist")) { QStringList lst; QDomElement n; diff --git a/src/tools/uic3/domtool.h b/src/tools/uic3/domtool.h index ad597a1..8fe0793 100644 --- a/src/tools/uic3/domtool.h +++ b/src/tools/uic3/domtool.h @@ -266,7 +266,7 @@ QT_BEGIN_NAMESPACE inline Variant asVariant(const QVariant &v) { Variant var; - var = qVariantValue<Variant>(v); + var = qvariant_cast<Variant>(v); return var; } diff --git a/src/xmlpatterns/api/quriloader.cpp b/src/xmlpatterns/api/quriloader.cpp index e0a7542..c653661 100644 --- a/src/xmlpatterns/api/quriloader.cpp +++ b/src/xmlpatterns/api/quriloader.cpp @@ -69,7 +69,7 @@ QNetworkReply *URILoader::createRequest(Operation op, const QNetworkRequest &req const QVariant variant(m_variableLoader->valueFor(m_namePool->allocateQName(QString(), name, QString()))); if(!variant.isNull() && variant.userType() == qMetaTypeId<QIODevice *>()) - return new QIODeviceDelegate(qVariantValue<QIODevice *>(variant)); + return new QIODeviceDelegate(qvariant_cast<QIODevice *>(variant)); else { /* If we're entering this code path, the variable URI identified a variable diff --git a/src/xmlpatterns/api/qvariableloader.cpp b/src/xmlpatterns/api/qvariableloader.cpp index 612fa67..648fda4 100644 --- a/src/xmlpatterns/api/qvariableloader.cpp +++ b/src/xmlpatterns/api/qvariableloader.cpp @@ -131,12 +131,12 @@ SequenceType::Ptr VariableLoader::announceExternalVariable(const QXmlName name, return CommonSequenceTypes::ExactlyOneAnyURI; else if(variant.userType() == qMetaTypeId<QXmlQuery>()) { - const QXmlQuery variableQuery(qVariantValue<QXmlQuery>(variant)); + const QXmlQuery variableQuery(qvariant_cast<QXmlQuery>(variant)); return variableQuery.d->expression()->staticType(); } else { - return makeGenericSequenceType(AtomicValue::qtToXDMType(qVariantValue<QXmlItem>(variant)), + return makeGenericSequenceType(AtomicValue::qtToXDMType(qvariant_cast<QXmlItem>(variant)), Cardinality::exactlyOne()); } } @@ -154,12 +154,12 @@ Item::Iterator::Ptr VariableLoader::evaluateSequence(const QXmlName name, return makeSingletonIterator(itemForName(name)); else if(variant.userType() == qMetaTypeId<QXmlQuery>()) { - const QXmlQuery variableQuery(qVariantValue<QXmlQuery>(variant)); + const QXmlQuery variableQuery(qvariant_cast<QXmlQuery>(variant)); return variableQuery.d->expression()->evaluateSequence(DynamicContext::Ptr(new TemporaryTreesRedirectingContext(variableQuery.d->dynamicContext(), context))); } - const QVariant v(qVariantValue<QXmlItem>(variant).toAtomicValue()); + const QVariant v(qvariant_cast<QXmlItem>(variant).toAtomicValue()); switch(v.type()) { @@ -179,7 +179,7 @@ Item VariableLoader::itemForName(const QXmlName &name) const if(variant.userType() == qMetaTypeId<QIODevice *>()) return Item(AnyURI::fromValue(QLatin1String("tag:trolltech.com,2007:QtXmlPatterns:QIODeviceVariable:") + m_namePool->stringForLocalName(name.localName()))); - const QXmlItem item(qVariantValue<QXmlItem>(variant)); + const QXmlItem item(qvariant_cast<QXmlItem>(variant)); if(item.isNode()) return Item::fromPublic(item); @@ -210,8 +210,8 @@ bool VariableLoader::isSameType(const QVariant &v1, return true; /* Ok, we have two QXmlItems. */ - const QXmlItem i1(qVariantValue<QXmlItem>(v1)); - const QXmlItem i2(qVariantValue<QXmlItem>(v2)); + const QXmlItem i1(qvariant_cast<QXmlItem>(v1)); + const QXmlItem i2(qvariant_cast<QXmlItem>(v2)); if(i1.isNode()) { diff --git a/src/xmlpatterns/api/qxmlquery.cpp b/src/xmlpatterns/api/qxmlquery.cpp index 55af49b..4d6a3b6 100644 --- a/src/xmlpatterns/api/qxmlquery.cpp +++ b/src/xmlpatterns/api/qxmlquery.cpp @@ -534,7 +534,7 @@ void QXmlQuery::bindVariable(const QXmlName &name, const QXmlItem &value) } const QPatternist::VariableLoader::Ptr vl(d->variableLoader()); - const QVariant variant(qVariantFromValue(value)); + const QVariant variant(QVariant::fromValue(value)); /* If the type of the variable changed(as opposed to only the value), * we will have to recompile. */ @@ -610,7 +610,7 @@ void QXmlQuery::bindVariable(const QXmlName &name, QIODevice *device) if(device) { - const QVariant variant(qVariantFromValue(device)); + const QVariant variant(QVariant::fromValue(device)); if(vl->invalidationRequired(name, variant)) d->recompileRequired(); @@ -1184,7 +1184,7 @@ void QXmlQuery::bindVariable(const QXmlName &name, const QXmlQuery &query) Q_ASSERT_X(query.isValid(), Q_FUNC_INFO, "The query being bound must be valid."); const QPatternist::VariableLoader::Ptr vl(d->variableLoader()); - const QVariant variant(qVariantFromValue(query)); + const QVariant variant(QVariant::fromValue(query)); if(vl->invalidationRequired(name, variant)) d->recompileRequired(); diff --git a/src/xmlpatterns/data/qatomicvalue.cpp b/src/xmlpatterns/data/qatomicvalue.cpp index c4f3578..5bb9a4f 100644 --- a/src/xmlpatterns/data/qatomicvalue.cpp +++ b/src/xmlpatterns/data/qatomicvalue.cpp @@ -121,7 +121,7 @@ QVariant AtomicValue::toQt(const AtomicValue *const value) || BuiltinTypes::xsHexBinary->xdtTypeMatches(t)) return QVariant(value->as<Base64Binary>()->asByteArray()); else if(BuiltinTypes::xsQName->xdtTypeMatches(t)) - return qVariantFromValue(value->as<QNameValue>()->qName()); + return QVariant::fromValue(value->as<QNameValue>()->qName()); else { /* A type we don't support in Qt. Includes xs:time currently. */ diff --git a/src/xmlpatterns/utils/qautoptr_p.h b/src/xmlpatterns/utils/qautoptr_p.h index 060e7be..173999f 100644 --- a/src/xmlpatterns/utils/qautoptr_p.h +++ b/src/xmlpatterns/utils/qautoptr_p.h @@ -122,7 +122,6 @@ namespace QPatternist return *this; } -#ifndef QT_NO_MEMBER_TEMPLATES template<typename L> operator AutoPtrRef<L>() { @@ -139,7 +138,6 @@ namespace QPatternist inline AutoPtr(AutoPtr<L>& other) : m_ptr(other.release()) { } -#endif inline T *release() { diff --git a/tests/auto/collections/tst_collections.cpp b/tests/auto/collections/tst_collections.cpp index f81535e..0adceee 100644 --- a/tests/auto/collections/tst_collections.cpp +++ b/tests/auto/collections/tst_collections.cpp @@ -3448,27 +3448,16 @@ void tst_Collections::containerTypedefs() testSetContainerTypedefs(QSet<int>()); } -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) -class Key1 -{}; -class T1 -{}; -class T2 -{}; -#else class Key1; class T1; class T2; -#endif void tst_Collections::forwardDeclared() { { typedef QHash<Key1, T1> C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } { typedef QMultiHash<Key1, T1> C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } -#if !defined(Q_CC_MSVC_NET) || _MSC_VER >= 1310 { typedef QMap<Key1, T1> C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } { typedef QMultiMap<Key1, T1> C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } -#endif #if !defined(Q_CC_RVCT) // RVCT can't handle forward declared template parameters if those are used to declare // class members inside templated class. diff --git a/tests/auto/corelib.pro b/tests/auto/corelib.pro index 531fed2..d1d0940 100644 --- a/tests/auto/corelib.pro +++ b/tests/auto/corelib.pro @@ -75,6 +75,7 @@ SUBDIRS=\ qstringbuilder4 \ qstringlist \ qstringmatcher \ + qstringref \ qtconcurrentfilter \ qtconcurrentiteratekernel \ qtconcurrentmap \ diff --git a/tests/auto/gui.pro b/tests/auto/gui.pro index 2d9ea93..c94272c 100644 --- a/tests/auto/gui.pro +++ b/tests/auto/gui.pro @@ -57,6 +57,7 @@ SUBDIRS=\ qfontdialog \ qfontmetrics \ qformlayout \ + qglyphs \ qgraphicsanchorlayout \ qgraphicsanchorlayout1 \ qgraphicseffect \ diff --git a/tests/auto/macnativeevents/expectedeventlist.cpp b/tests/auto/macnativeevents/expectedeventlist.cpp index 0679dcb..82a594b 100644 --- a/tests/auto/macnativeevents/expectedeventlist.cpp +++ b/tests/auto/macnativeevents/expectedeventlist.cpp @@ -49,7 +49,9 @@ ExpectedEventList::ExpectedEventList(QObject *target) : QObject(target), eventCount(0) { target->installEventFilter(this); - debug = !qgetenv("NATIVEDEBUG").isEmpty(); + debug = qgetenv("NATIVEDEBUG").toInt(); + if (debug > 0) + qDebug() << "Debug level sat to:" << debug; } ExpectedEventList::~ExpectedEventList() @@ -104,14 +106,17 @@ void ExpectedEventList::compareMouseEvents(QEvent *received, QEvent *expected) && (e1->globalPos() == e2->globalPos()) && (e1->button() == e2->button()) && (e1->buttons() == e2->buttons()) - && (e1->modifiers() == e2->modifiers())) + && (e1->modifiers() == e2->modifiers())) { + if (debug > 0) + qDebug() << " Received (OK):" << e1 << e1->globalPos(); return; // equal + } // INVARIANT: The two events are not equal. So we fail. Depending // on whether debug mode is no or not, we let QTest fail. Otherwise // we let the test continue for debugging puposes. int eventListNr = eventCount - eventList.size(); - if (!debug) { + if (debug == 0) { qWarning() << "Expected event" << eventListNr << "differs from received event:"; QCOMPARE(e1->pos(), e2->pos()); QCOMPARE(e1->globalPos(), e2->globalPos()); @@ -135,14 +140,17 @@ void ExpectedEventList::compareKeyEvents(QEvent *received, QEvent *expected) if (e1->key() == e2->key() && (e1->modifiers() == e2->modifiers()) && (e1->count() == e2->count()) - && (e1->isAutoRepeat() == e2->isAutoRepeat())) + && (e1->isAutoRepeat() == e2->isAutoRepeat())) { + if (debug > 0) + qDebug() << " Received (OK):" << e1 << QKeySequence(e1->key()).toString(QKeySequence::NativeText); return; // equal + } // INVARIANT: The two events are not equal. So we fail. Depending // on whether debug mode is no or not, we let QTest fail. Otherwise // we let the test continue for debugging puposes. int eventListNr = eventCount - eventList.size(); - if (!debug) { + if (debug == 0) { qWarning() << "Expected event" << eventListNr << "differs from received event:"; QCOMPARE(e1->key(), e2->key()); QCOMPARE(e1->modifiers(), e2->modifiers()); @@ -150,18 +158,19 @@ void ExpectedEventList::compareKeyEvents(QEvent *received, QEvent *expected) QCOMPARE(e1->isAutoRepeat(), e2->isAutoRepeat()); } else { qWarning() << "*** FAIL *** : Expected event" << eventListNr << "differs from received event:"; - qWarning() << "Received:" << e1 << e1->key(); - qWarning() << "Expected:" << e2 << e2->key(); + qWarning() << "Received:" << e1 << QKeySequence(e1->key()).toString(QKeySequence::NativeText); + qWarning() << "Expected:" << e2 << QKeySequence(e2->key()).toString(QKeySequence::NativeText); } } bool ExpectedEventList::eventFilter(QObject *, QEvent *received) { - if (debug) + if (debug > 1) qDebug() << received; if (eventList.isEmpty()) return false; + bool eat = false; QEvent *expected = eventList.first(); if (expected->type() == received->type()) { eventList.removeFirst(); @@ -175,11 +184,13 @@ bool ExpectedEventList::eventFilter(QObject *, QEvent *received) case QEvent::NonClientAreaMouseButtonDblClick: case QEvent::NonClientAreaMouseMove: { compareMouseEvents(received, expected); + eat = true; break; } case QEvent::KeyPress: case QEvent::KeyRelease: { compareKeyEvents(received, expected); + eat = true; break; } case QEvent::Resize: { @@ -198,6 +209,6 @@ bool ExpectedEventList::eventFilter(QObject *, QEvent *received) QAbstractEventDispatcher::instance()->interrupt(); } - return false; + return eat; } diff --git a/tests/auto/macnativeevents/expectedeventlist.h b/tests/auto/macnativeevents/expectedeventlist.h index bd9f358..21eb193 100644 --- a/tests/auto/macnativeevents/expectedeventlist.h +++ b/tests/auto/macnativeevents/expectedeventlist.h @@ -51,7 +51,7 @@ class ExpectedEventList : public QObject { QList<QEvent *> eventList; QBasicTimer timer; - bool debug; + int debug; int eventCount; void timerEvent(QTimerEvent *); diff --git a/tests/auto/macnativeevents/nativeeventlist.cpp b/tests/auto/macnativeevents/nativeeventlist.cpp index 1a90ee0..f730377 100644 --- a/tests/auto/macnativeevents/nativeeventlist.cpp +++ b/tests/auto/macnativeevents/nativeeventlist.cpp @@ -47,7 +47,8 @@ NativeEventList::NativeEventList(int defaultWaitMs) , wait(false) , defaultWaitMs(defaultWaitMs) { - QString multiplier = qgetenv("NATIVEDEBUG"); + debug = qgetenv("NATIVEDEBUG").toInt(); + QString multiplier = qgetenv("NATIVEDEBUGSPEED"); if (!multiplier.isEmpty()) setTimeMultiplier(multiplier.toFloat()); } @@ -61,8 +62,11 @@ NativeEventList::~NativeEventList() void NativeEventList::sendNextEvent() { QNativeEvent *e = eventList.at(currIndex).second; - if (e) + if (e) { + if (debug > 0) + qDebug() << "Sending:" << *e; QNativeInput::sendNativeEvent(*e); + } waitNextEvent(); } diff --git a/tests/auto/macnativeevents/nativeeventlist.h b/tests/auto/macnativeevents/nativeeventlist.h index efcca43..9f9498d 100644 --- a/tests/auto/macnativeevents/nativeeventlist.h +++ b/tests/auto/macnativeevents/nativeeventlist.h @@ -76,6 +76,7 @@ private: int currIndex; bool wait; int defaultWaitMs; + int debug; }; #endif diff --git a/tests/auto/macnativeevents/qnativeevents_mac.cpp b/tests/auto/macnativeevents/qnativeevents_mac.cpp index 6c04bf3..cc12cc9 100644 --- a/tests/auto/macnativeevents/qnativeevents_mac.cpp +++ b/tests/auto/macnativeevents/qnativeevents_mac.cpp @@ -54,11 +54,11 @@ static Qt::KeyboardModifiers getModifiersFromQuartzEvent(CGEventRef inEvent) if (flags & kCGEventFlagMaskShift || flags & kCGEventFlagMaskAlphaShift) m |= Qt::ShiftModifier; if (flags & kCGEventFlagMaskControl) - m |= Qt::MetaModifier; + m |= Qt::ControlModifier; if (flags & kCGEventFlagMaskAlternate) m |= Qt::AltModifier; if (flags & kCGEventFlagMaskCommand) - m |= Qt::ControlModifier; + m |= Qt::MetaModifier; return m; } @@ -67,11 +67,11 @@ static void setModifiersFromQNativeEvent(CGEventRef inEvent, const QNativeEvent CGEventFlags flags = 0; if (event.modifiers.testFlag(Qt::ShiftModifier)) flags |= kCGEventFlagMaskShift; - if (event.modifiers.testFlag(Qt::MetaModifier)) + if (event.modifiers.testFlag(Qt::ControlModifier)) flags |= kCGEventFlagMaskControl; if (event.modifiers.testFlag(Qt::AltModifier)) flags |= kCGEventFlagMaskAlternate; - if (event.modifiers.testFlag(Qt::ControlModifier)) + if (event.modifiers.testFlag(Qt::MetaModifier)) flags |= kCGEventFlagMaskCommand; CGEventSetFlags(inEvent, flags); } diff --git a/tests/auto/macnativeevents/tst_macnativeevents.cpp b/tests/auto/macnativeevents/tst_macnativeevents.cpp index d582417..742267f 100644 --- a/tests/auto/macnativeevents/tst_macnativeevents.cpp +++ b/tests/auto/macnativeevents/tst_macnativeevents.cpp @@ -48,6 +48,7 @@ #include "qnativeevents.h" #include "nativeeventlist.h" #include "expectedeventlist.h" +#include <Carbon/Carbon.h> #ifdef Q_OS_MAC @@ -73,6 +74,10 @@ private slots: void testChildWindowInFrontOfStaysOnTopParentWindow(); #endif void testKeyPressOnToplevel(); + void testModifierShift(); + void testModifierAlt(); + void testModifierCtrl(); + void testModifierCtrlWithDontSwapCtrlAndMeta(); }; void tst_MacNativeEvents::testMouseMoveLocation() @@ -411,6 +416,108 @@ void tst_MacNativeEvents::testKeyPressOnToplevel() QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); } +void tst_MacNativeEvents::testModifierShift() +{ + QWidget w; + w.show(); + + NativeEventList native; + native.append(new QNativeModifierEvent(Qt::ShiftModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::ShiftModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::ShiftModifier)); + native.append(new QNativeModifierEvent(Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier)); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::ShiftModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ShiftModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Shift, Qt::ShiftModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::testModifierAlt() +{ + QWidget w; + w.show(); + + NativeEventList native; + native.append(new QNativeModifierEvent(Qt::AltModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::AltModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::AltModifier)); + native.append(new QNativeModifierEvent(Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier)); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::AltModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::AltModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Alt, Qt::AltModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::testModifierCtrl() +{ + // On Mac, we switch the Command and Control modifier by default, so that Command + // means Meta, and Control means Command. Lets check that this works: + QWidget w; + w.show(); + + QVERIFY(kControlUnicode == QKeySequence(Qt::Key_Meta).toString(QKeySequence::NativeText)[0]); + QVERIFY(kCommandUnicode == QKeySequence(Qt::Key_Control).toString(QKeySequence::NativeText)[0]); + + NativeEventList native; + native.append(new QNativeModifierEvent(Qt::ControlModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::ControlModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::ControlModifier)); + native.append(new QNativeModifierEvent(Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Meta, Qt::NoModifier)); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::MetaModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::MetaModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Meta, Qt::MetaModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::testModifierCtrlWithDontSwapCtrlAndMeta() +{ + // On Mac, we switch the Command and Control modifier by default, so that Command + // means Meta, and Control means Command. Lets check that the flag to swith off + // this behaviour works. While working on this test I realised that we actually + // don't (and never have) respected this flag for raw key events. Only for + // menus, through QKeySequence. I don't want to change this behaviour now, at + // least not until someone complains. So I choose to let the test just stop + // any unintended regressions instead. If we decide to resepect the the flag at one + // point, fix the test. + QCoreApplication::setAttribute(Qt::AA_MacDontSwapCtrlAndMeta); + QWidget w; + w.show(); + + QVERIFY(kCommandUnicode == QKeySequence(Qt::Key_Meta).toString(QKeySequence::NativeText)[0]); + QVERIFY(kControlUnicode == QKeySequence(Qt::Key_Control).toString(QKeySequence::NativeText)[0]); + + NativeEventList native; + native.append(new QNativeModifierEvent(Qt::ControlModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::ControlModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::ControlModifier)); + native.append(new QNativeModifierEvent(Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Meta, Qt::NoModifier)); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::ControlModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ControlModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Meta, Qt::ControlModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); + QCoreApplication::setAttribute(Qt::AA_MacDontSwapCtrlAndMeta, false); +} + #include "tst_macnativeevents.moc" QTEST_MAIN(tst_MacNativeEvents) diff --git a/tests/auto/networkselftest/tst_networkselftest.cpp b/tests/auto/networkselftest/tst_networkselftest.cpp index 752e368..ecbc08c 100644 --- a/tests/auto/networkselftest/tst_networkselftest.cpp +++ b/tests/auto/networkselftest/tst_networkselftest.cpp @@ -42,6 +42,8 @@ #include <QtTest/QtTest> #include <QtNetwork/QtNetwork> +#include <time.h> + #ifdef Q_OS_SYMBIAN // In Symbian OS test data is located in applications private dir // Current path (C:\private\<UID>) contains only ascii chars @@ -72,14 +74,20 @@ private slots: // specific protocol tests void ftpServer(); + void ftpProxyServer(); void imapServer(); void httpServer(); + void httpServerFiles_data(); + void httpServerFiles(); + void httpServerCGI_data(); + void httpServerCGI(); void httpsServer(); void httpProxy(); void httpProxyBasicAuth(); void httpProxyNtlmAuth(); void socks5Proxy(); void socks5ProxyAuth(); + void smbServer(); // ssl supported test void supportsSsl(); @@ -158,7 +166,7 @@ static QString prettyByteArray(const QByteArray &array) static bool doSocketRead(QTcpSocket *socket, int minBytesAvailable, int timeout = 4000) { - QTime timer; + QElapsedTimer timer; timer.start(); forever { if (socket->bytesAvailable() >= minBytesAvailable) @@ -408,6 +416,8 @@ void tst_NetworkSelfTest::remotePortsOpen_data() QTest::newRow("http-proxy-auth-ntlm") << 3130; QTest::newRow("socks5-proxy") << 1080; QTest::newRow("socks5-proxy-auth") << 1081; + QTest::newRow("ftp-proxy") << 2121; + QTest::newRow("smb") << 139; } void tst_NetworkSelfTest::remotePortsOpen() @@ -455,16 +465,43 @@ void tst_NetworkSelfTest::fileLineEndingTest() QVERIFY2(!lineEndingType.compare("LF"), QString("Reference file %1 has %2 as line ending - Git checkout issue !?!").arg(referenceName, lineEndingType).toLocal8Bit()); } -static QList<Chat> ftpChat() +static QList<Chat> ftpChat(const QByteArray &userSuffix = QByteArray()) { return QList<Chat>() << Chat::expect("220") << Chat::discardUntil("\r\n") - << Chat::send("USER anonymous\r\n") + << Chat::send("USER anonymous" + userSuffix + "\r\n") << Chat::expect("331") << Chat::discardUntil("\r\n") << Chat::send("PASS user@hostname\r\n") << Chat::expect("230") << Chat::discardUntil("\r\n") + + << Chat::send("CWD pub\r\n") + << Chat::expect("250") + << Chat::discardUntil("\r\n") + << Chat::send("CWD dir-not-readable\r\n") + << Chat::expect("550") + << Chat::discardUntil("\r\n") + << Chat::send("PWD\r\n") + << Chat::expect("257 \"/pub\"\r\n") + << Chat::send("SIZE file-not-readable.txt\r\n") + << Chat::expect("213 41\r\n") + << Chat::send("CWD qxmlquery\r\n") + << Chat::expect("250") + << Chat::discardUntil("\r\n") + + << Chat::send("CWD /qtest\r\n") + << Chat::expect("250") + << Chat::discardUntil("\r\n") + << Chat::send("SIZE bigfile\r\n") + << Chat::expect("213 519240\r\n") + << Chat::send("SIZE rfc3252\r\n") + << Chat::expect("213 25962\r\n") + << Chat::send("SIZE rfc3252.txt\r\n") + << Chat::expect("213 25962\r\n") +// << Chat::send("SIZE nonASCII/german_\344\366\374\304\326\334\337\r\n") +// << Chat::expect("213 40\r\n") + << Chat::send("QUIT\r\n") << Chat::expect("221") << Chat::discardUntil("\r\n") @@ -476,6 +513,11 @@ void tst_NetworkSelfTest::ftpServer() netChat(21, ftpChat()); } +void tst_NetworkSelfTest::ftpProxyServer() +{ + netChat(2121, ftpChat("@" + QtNetworkSettings::serverName().toLatin1())); +} + void tst_NetworkSelfTest::imapServer() { netChat(143, QList<Chat>() @@ -493,6 +535,14 @@ void tst_NetworkSelfTest::imapServer() void tst_NetworkSelfTest::httpServer() { + QString uniqueExtension; + qsrand(time(0)); +#ifndef Q_OS_WINCE + uniqueExtension = QString("%1%2%3").arg((qulonglong)this).arg(qrand()).arg((qulonglong)time(0)); +#else + uniqueExtension = QString("%1%2").arg((qulonglong)this).arg(qrand()); +#endif + netChat(80, QList<Chat>() // HTTP/0.9 chat: << Chat::send("GET /\r\n") @@ -521,9 +571,185 @@ void tst_NetworkSelfTest::httpServer() << Chat::discardUntil(" ") << Chat::expect("200 ") << Chat::DiscardUntilDisconnect + + // HTTP protected area + << Chat::Reconnect + << Chat::send("GET /qtest/protected/rfc3252.txt HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("401 ") + << Chat::DiscardUntilDisconnect + + << Chat::Reconnect + << Chat::send("HEAD /qtest/protected/rfc3252.txt HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "Authorization: Basic cXNvY2tzdGVzdDpwYXNzd29yZA==\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("200 ") + << Chat::DiscardUntilDisconnect + + // DAV area + << Chat::Reconnect + << Chat::send("HEAD /dav/ HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("200 ") + << Chat::DiscardUntilDisconnect + + // HTTP/1.0 PUT + << Chat::Reconnect + << Chat::send("PUT /dav/networkselftest-" + uniqueExtension.toLatin1() + ".txt HTTP/1.0\r\n" + "Content-Length: 5\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "\r\n" + "Hello") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("201 ") + << Chat::DiscardUntilDisconnect + + // check that the file did get uploaded + << Chat::Reconnect + << Chat::send("HEAD /dav/networkselftest-" + uniqueExtension.toLatin1() + ".txt HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("200 ") + << Chat::discardUntil("\r\nContent-Length: 5\r\n") + << Chat::DiscardUntilDisconnect + + // HTTP/1.0 DELETE + << Chat::Reconnect + << Chat::send("DELETE /dav/networkselftest-" + uniqueExtension.toLatin1() + ".txt HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("204 ") + << Chat::DiscardUntilDisconnect ); } +void tst_NetworkSelfTest::httpServerFiles_data() +{ + QTest::addColumn<QString>("uri"); + QTest::addColumn<int>("size"); + + QTest::newRow("fluke.gif") << "/qtest/fluke.gif" << -1; + QTest::newRow("bigfile") << "/qtest/bigfile" << 519240; + QTest::newRow("rfc3252.txt") << "/qtest/rfc3252.txt" << 25962; + QTest::newRow("protected/rfc3252.txt") << "/qtest/protected/rfc3252.txt" << 25962; + QTest::newRow("completelyEmptyQuery.xq") << "/qtest/qxmlquery/completelyEmptyQuery.xq" << -1; + QTest::newRow("notWellformedViaHttps.xml") << "/qtest/qxmlquery/notWellformedViaHttps.xml" << -1; + QTest::newRow("notWellformed.xml") << "/qtest/qxmlquery/notWellformed.xml" << -1; + QTest::newRow("viaHttp.xq") << "/qtest/qxmlquery/viaHttp.xq" << -1; + QTest::newRow("wellFormedViaHttps.xml") << "/qtest/qxmlquery/wellFormedViaHttps.xml" << -1; + QTest::newRow("wellFormed.xml") << "/qtest/qxmlquery/wellFormed.xml" << -1; +} + +void tst_NetworkSelfTest::httpServerFiles() +{ + QFETCH(QString, uri); + QFETCH(int, size); + + QList<Chat> chat; + chat << Chat::send("HEAD " + QUrl::toPercentEncoding(uri, "/") + " HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "Authorization: Basic cXNvY2tzdGVzdDpwYXNzd29yZA==\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::skipBytes(1) // HTTP/1.0 or 1.1 reply + << Chat::expect(" 200 "); + if (size != -1) + chat << Chat::discardUntil("\r\nContent-Length: " + QByteArray::number(size) + "\r\n"); + chat << Chat::DiscardUntilDisconnect; + netChat(80, chat); +} + +void tst_NetworkSelfTest::httpServerCGI_data() +{ + QTest::addColumn<QByteArray>("request"); + QTest::addColumn<QByteArray>("result"); + QTest::addColumn<QByteArray>("additionalHeader"); + + QTest::newRow("echo.cgi") + << QByteArray("GET /qtest/cgi-bin/echo.cgi?Hello+World HTTP/1.0\r\n" + "Connection: close\r\n" + "\r\n") + << QByteArray("Hello+World") + << QByteArray(); + + QTest::newRow("echo.cgi(POST)") + << QByteArray("POST /qtest/cgi-bin/echo.cgi?Hello+World HTTP/1.0\r\n" + "Connection: close\r\n" + "Content-Length: 15\r\n" + "\r\n" + "Hello, World!\r\n") + << QByteArray("Hello, World!\r\n") + << QByteArray(); + + QTest::newRow("md5sum.cgi") + << QByteArray("POST /qtest/cgi-bin/md5sum.cgi HTTP/1.0\r\n" + "Connection: close\r\n" + "Content-Length: 15\r\n" + "\r\n" + "Hello, World!\r\n") + << QByteArray("29b933a8d9a0fcef0af75f1713f4940e\n") + << QByteArray(); + + QTest::newRow("protected/md5sum.cgi") + << QByteArray("POST /qtest/protected/cgi-bin/md5sum.cgi HTTP/1.0\r\n" + "Connection: close\r\n" + "Authorization: Basic cXNvY2tzdGVzdDpwYXNzd29yZA==\r\n" + "Content-Length: 15\r\n" + "\r\n" + "Hello, World!\r\n") + << QByteArray("29b933a8d9a0fcef0af75f1713f4940e\n") + << QByteArray(); + + QTest::newRow("set-cookie.cgi") + << QByteArray("POST /qtest/cgi-bin/set-cookie.cgi HTTP/1.0\r\n" + "Connection: close\r\n" + "Content-Length: 8\r\n" + "\r\n" + "foo=bar\n") + << QByteArray("Success\n") + << QByteArray("\r\nSet-Cookie: foo=bar\r\n"); +} + +void tst_NetworkSelfTest::httpServerCGI() +{ + QFETCH(QByteArray, request); + QFETCH(QByteArray, result); + QFETCH(QByteArray, additionalHeader); + QList<Chat> chat; + chat << Chat::send(request) + << Chat::expect("HTTP/1.") << Chat::skipBytes(1) + << Chat::expect(" 200 "); + + if (!additionalHeader.isEmpty()) + chat << Chat::discardUntil(additionalHeader); + + chat << Chat::discardUntil("\r\n\r\n") + << Chat::expect(result) + << Chat::RemoteDisconnect; + netChat(80, chat); +} + void tst_NetworkSelfTest::httpsServer() { #ifndef QT_NO_OPENSSL @@ -725,7 +951,63 @@ void tst_NetworkSelfTest::supportsSsl() #ifdef QT_NO_OPENSSL QFAIL("SSL not compiled in"); #else - QVERIFY(QSslSocket::supportsSsl()); + QVERIFY2(QSslSocket::supportsSsl(), "Could not load SSL libraries"); +#endif +} + +void tst_NetworkSelfTest::smbServer() +{ + static const char contents[] = "This is 34 bytes. Do not change..."; +#ifdef Q_OS_WIN + // use Windows's native UNC support to try and open a file on the server + QString filepath = QString("\\\\%1\\testshare\\test.pri").arg(QtNetworkSettings::winServerName()); + FILE *f = fopen(filepath.toLatin1(), "rb"); + QVERIFY2(f, qt_error_string().toLocal8Bit()); + + char buf[128]; + size_t ret = fread(buf, sizeof buf, 1, f); + fclose(f); + + QCOMPARE(ret, strlen(contents)); + QVERIFY(memcmp(buf, contents, strlen(contents)) == 0); +#else + // try to use Samba + QString progname = "smbclient"; + QProcess smbclient; + smbclient.start(progname, QIODevice::ReadOnly); + if (!smbclient.waitForStarted(2000)) + QSKIP("Could not find smbclient (from Samba), cannot continue testing", SkipAll); + if (!smbclient.waitForFinished(2000) || smbclient.exitStatus() != QProcess::NormalExit) + QSKIP("smbclient isn't working, cannot continue testing", SkipAll); + smbclient.close(); + + // try listing the server + smbclient.start(progname, QStringList() << "-g" << "-N" << "-L" << QtNetworkSettings::winServerName(), QIODevice::ReadOnly); + QVERIFY(smbclient.waitForFinished(5000)); + if (smbclient.exitStatus() != QProcess::NormalExit) + QSKIP("smbclient crashed", SkipAll); + QVERIFY2(smbclient.exitCode() == 0, "Test server not found"); + + QByteArray output = smbclient.readAll(); + QVERIFY(output.contains("Disk|testshare|")); + QVERIFY(output.contains("Disk|testsharewritable|")); + QVERIFY(output.contains("Disk|testsharelargefile|")); + qDebug() << "Test server found and shares are correct"; + + // try getting a file + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + env.insert("PAGER", "/bin/cat"); // just in case + smbclient.setProcessEnvironment(env); + smbclient.start(progname, QStringList() << "-N" << "-c" << "more test.pri" + << QString("\\\\%1\\testshare").arg(QtNetworkSettings::winServerName()), QIODevice::ReadOnly); + QVERIFY(smbclient.waitForFinished(5000)); + if (smbclient.exitStatus() != QProcess::NormalExit) + QSKIP("smbclient crashed", SkipAll); + QVERIFY2(smbclient.exitCode() == 0, "File //qt-test-server/testshare/test.pri not found"); + + output = smbclient.readAll(); + QCOMPARE(output.constData(), contents); + qDebug() << "Test file is correct"; #endif } diff --git a/tests/auto/opengl.pro b/tests/auto/opengl.pro index 9b59cd1..6c8e4ca 100644 --- a/tests/auto/opengl.pro +++ b/tests/auto/opengl.pro @@ -3,4 +3,5 @@ SUBDIRS=\ qgl \ qglthreads \ qglbuffer \ + qglfunctions \ diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp index cea259c..713ad08 100644 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp @@ -4073,7 +4073,8 @@ void tst_QAccessibility::accelerators() window->show(); QAccessibleInterface *accLineEdit = QAccessible::queryAccessibleInterface(le); - QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString() + QLatin1String("L")); + QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L")); + QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L")); label->setText(tr("Q &")); QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString()); label->setText(tr("Q &&")); @@ -4081,11 +4082,11 @@ void tst_QAccessibility::accelerators() label->setText(tr("Q && A")); QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString()); label->setText(tr("Q &&&A")); - QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString() + QLatin1String("A")); + QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A")); label->setText(tr("Q &&A")); QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString()); label->setText(tr("Q &A&B")); - QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString() + QLatin1String("A")); + QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A")); #if defined(Q_WS_X11) qt_x11_wait_for_window_manager(window); diff --git a/tests/auto/qbytearray/tst_qbytearray.cpp b/tests/auto/qbytearray/tst_qbytearray.cpp index 07fdbc3..0dc2282 100644 --- a/tests/auto/qbytearray/tst_qbytearray.cpp +++ b/tests/auto/qbytearray/tst_qbytearray.cpp @@ -142,6 +142,8 @@ private slots: void repeated_data() const; void byteRefDetaching() const; + + void reserve(); }; tst_QByteArray::tst_QByteArray() @@ -221,18 +223,18 @@ void tst_QByteArray::qUncompress_data() QTest::addColumn<QByteArray>("in"); QTest::addColumn<QByteArray>("out"); - QTest::newRow("0x00000000") << QByteArray("\x00\x00\x00\x00") << QByteArray(); - QTest::newRow("0x000000ff") << QByteArray("\x00\x00\x00\xff") << QByteArray(); - QTest::newRow("0x3f000000") << QByteArray("\x3f\x00\x00\x00") << QByteArray(); - QTest::newRow("0x3fffffff") << QByteArray("\x3f\xff\xff\xff") << QByteArray(); - QTest::newRow("0x7fffff00") << QByteArray("\x7f\xff\xff\x00") << QByteArray(); - QTest::newRow("0x7fffffff") << QByteArray("\x7f\xff\xff\xff") << QByteArray(); - QTest::newRow("0x80000000") << QByteArray("\x80\x00\x00\x00") << QByteArray(); - QTest::newRow("0x800000ff") << QByteArray("\x80\x00\x00\xff") << QByteArray(); - QTest::newRow("0xcf000000") << QByteArray("\xcf\x00\x00\x00") << QByteArray(); - QTest::newRow("0xcfffffff") << QByteArray("\xcf\xff\xff\xff") << QByteArray(); - QTest::newRow("0xffffff00") << QByteArray("\xff\xff\xff\x00") << QByteArray(); - QTest::newRow("0xffffffff") << QByteArray("\xff\xff\xff\xff") << QByteArray(); + QTest::newRow("0x00000000") << QByteArray("\x00\x00\x00\x00", 4) << QByteArray(); + QTest::newRow("0x000000ff") << QByteArray("\x00\x00\x00\xff", 4) << QByteArray(); + QTest::newRow("0x3f000000") << QByteArray("\x3f\x00\x00\x00", 4) << QByteArray(); + QTest::newRow("0x3fffffff") << QByteArray("\x3f\xff\xff\xff", 4) << QByteArray(); + QTest::newRow("0x7fffff00") << QByteArray("\x7f\xff\xff\x00", 4) << QByteArray(); + QTest::newRow("0x7fffffff") << QByteArray("\x7f\xff\xff\xff", 4) << QByteArray(); + QTest::newRow("0x80000000") << QByteArray("\x80\x00\x00\x00", 4) << QByteArray(); + QTest::newRow("0x800000ff") << QByteArray("\x80\x00\x00\xff", 4) << QByteArray(); + QTest::newRow("0xcf000000") << QByteArray("\xcf\x00\x00\x00", 4) << QByteArray(); + QTest::newRow("0xcfffffff") << QByteArray("\xcf\xff\xff\xff", 4) << QByteArray(); + QTest::newRow("0xffffff00") << QByteArray("\xff\xff\xff\x00", 4) << QByteArray(); + QTest::newRow("0xffffffff") << QByteArray("\xff\xff\xff\xff", 4) << QByteArray(); } void tst_QByteArray::qUncompress() @@ -249,18 +251,10 @@ void tst_QByteArray::qUncompress() #endif QByteArray res; - QT_TRY { - res = ::qUncompress(in); - } QT_CATCH(const std::bad_alloc &) { - res = QByteArray(); - } + res = ::qUncompress(in); QCOMPARE(res, out); - QT_TRY { - res = ::qUncompress(in + "blah"); - } QT_CATCH(const std::bad_alloc &) { - res = QByteArray(); - } + res = ::qUncompress(in + "blah"); QCOMPARE(res, out); } @@ -1516,6 +1510,22 @@ void tst_QByteArray::byteRefDetaching() const } } +void tst_QByteArray::reserve() +{ + int capacity = 100; + QByteArray qba; + qba.reserve(capacity); + QVERIFY(qba.capacity() == capacity); + char *data = qba.data(); + + // FIXME count from 0 to make it fail + for (int i = 1; i < capacity; i++) { + qba.resize(i); + QVERIFY(capacity == qba.capacity()); + QVERIFY(data == qba.data()); + } +} + const char globalChar = '1'; QTEST_APPLESS_MAIN(tst_QByteArray) diff --git a/tests/auto/qcheckbox/tst_qcheckbox.cpp b/tests/auto/qcheckbox/tst_qcheckbox.cpp index d16370c..24d78fe 100644 --- a/tests/auto/qcheckbox/tst_qcheckbox.cpp +++ b/tests/auto/qcheckbox/tst_qcheckbox.cpp @@ -92,6 +92,7 @@ private slots: void setAccel(); void group(); void foregroundRole(); + void minimumSizeHint(); protected slots: void onClicked(); @@ -425,5 +426,11 @@ void tst_QCheckBox::foregroundRole() QVERIFY(testWidget->foregroundRole() == QPalette::WindowText); } +void tst_QCheckBox::minimumSizeHint() +{ + QCheckBox box(tr("CheckBox's sizeHint is the same as it's minimumSizeHint")); + QCOMPARE(box.sizeHint(), box.minimumSizeHint()); +} + QTEST_MAIN(tst_QCheckBox) #include "tst_qcheckbox.moc" diff --git a/tests/auto/qcombobox/tst_qcombobox.cpp b/tests/auto/qcombobox/tst_qcombobox.cpp index 1fcea9e..f00f3ef 100644 --- a/tests/auto/qcombobox/tst_qcombobox.cpp +++ b/tests/auto/qcombobox/tst_qcombobox.cpp @@ -157,6 +157,7 @@ private slots: void keyBoardNavigationWithMouse(); void task_QTBUG_1071_changingFocusEmitsActivated(); void maxVisibleItems(); + void task_QTBUG_10491_currentIndexAndModelColumn(); protected slots: void onEditTextChanged( const QString &newString ); @@ -2553,11 +2554,33 @@ void tst_QComboBox::maxVisibleItems() QAbstractItemView *v = comboBox.view(); int itemHeight = v->visualRect(v->model()->index(0,0)).height(); - if (v->style()->styleHint(QStyle::SH_ComboBox_Popup)) + QListView *lv = qobject_cast<QListView*>(v); + if (lv) + itemHeight += lv->spacing(); + QStyleOptionComboBox opt; + opt.initFrom(&comboBox); + if (!comboBox.style()->styleHint(QStyle::SH_ComboBox_Popup, &opt)) QCOMPARE(v->viewport()->height(), itemHeight * comboBox.maxVisibleItems()); - // QCombobox without a popup does not work, see QTBUG-760 } +void tst_QComboBox::task_QTBUG_10491_currentIndexAndModelColumn() +{ + QComboBox comboBox; + + QStandardItemModel model(4, 4, &comboBox); + for (int i = 0; i < 4; i++){ + model.setItem(i, 0, new QStandardItem(QString("Employee Nr %1").arg(i))); + model.setItem(i, 1, new QStandardItem(QString("Street Nr %1").arg(i))); + model.setItem(i, 2, new QStandardItem(QString("Town Nr %1").arg(i))); + model.setItem(i, 3, new QStandardItem(QString("Phone Nr %1").arg(i))); + } + comboBox.setModel(&model); + comboBox.setModelColumn(0); + + QComboBoxPrivate *d = static_cast<QComboBoxPrivate *>(QComboBoxPrivate::get(&comboBox)); + d->setCurrentIndex(model.index(2, 2)); + QCOMPARE(QModelIndex(d->currentIndex), model.index(2, comboBox.modelColumn())); +} QTEST_MAIN(tst_QComboBox) #include "tst_qcombobox.moc" diff --git a/tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp index 3125258..50b0e0a 100644 --- a/tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp +++ b/tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp @@ -273,6 +273,9 @@ private slots: void task196924(); void focusNextPrevChild(); + + void taskQTBUG_12384_timeSpecShowTimeOnly(); + private: EditorDateEdit* testWidget; QWidget *testFocusWidget; @@ -3420,7 +3423,20 @@ void tst_QDateTimeEdit::focusNextPrevChild() QCOMPARE(edit.currentSection(), QDateTimeEdit::MonthSection); } +void tst_QDateTimeEdit::taskQTBUG_12384_timeSpecShowTimeOnly() +{ + QDateTime time = QDateTime::fromString("20100723 04:02:40", "yyyyMMdd hh:mm:ss"); + time.setTimeSpec(Qt::UTC); + + EditorDateEdit edit; + edit.setDisplayFormat("hh:mm:ss"); + edit.setTimeSpec(Qt::UTC); + edit.setDateTime(time); + QCOMPARE(edit.minimumTime(), QTime(0, 0, 0, 0)); + QCOMPARE(edit.maximumTime(), QTime(23, 59, 59, 999)); + QCOMPARE(edit.time(), time.time()); +} QTEST_MAIN(tst_QDateTimeEdit) #include "tst_qdatetimeedit.moc" diff --git a/tests/auto/qdir/tst_qdir.cpp b/tests/auto/qdir/tst_qdir.cpp index fb83a5a..9678868 100644 --- a/tests/auto/qdir/tst_qdir.cpp +++ b/tests/auto/qdir/tst_qdir.cpp @@ -49,6 +49,11 @@ #include <qregexp.h> #include <qstringlist.h> #include "../network-settings.h" + +#if defined(Q_OS_WIN) +#define _WIN32_WINNT 0x500 +#endif + #include "../../shared/filesystem.h" #if defined(Q_OS_SYMBIAN) @@ -169,6 +174,11 @@ private slots: void updateFileLists(); void detachingOperations(); + +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + void isRoot_data(); + void isRoot(); +#endif }; // Testing get/set functions @@ -802,6 +812,16 @@ void tst_QDir::canonicalPath_data() QTest::newRow("absPath") << appPath + "\\testData\\..\\testData" << appPath + "/testData"; #endif QTest::newRow("nonexistant") << "testd" << QString(); + +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + QTest::newRow("drive:/") << QDir::rootPath() << QDir::rootPath(); + QTest::newRow("drive:\\") << QDir::toNativeSeparators(QDir::rootPath()) << QDir::rootPath(); + QTest::newRow("drive:/./") << QDir::rootPath().append("./") << QDir::rootPath(); + QTest::newRow("drive:/../.. ") << QDir::rootPath().append("../..") << QDir::rootPath(); + QTest::newRow("drive:\\.\\") << QDir::toNativeSeparators(QDir::rootPath().append("./")) << QDir::rootPath(); + QTest::newRow("drive:\\..\\..") << QDir::toNativeSeparators(QDir::rootPath().append("../..")) << QDir::rootPath(); + QTest::newRow("drive:") << QDir().canonicalPath().left(2) << QDir().canonicalPath(); +#endif } void tst_QDir::canonicalPath() @@ -1640,6 +1660,32 @@ void tst_QDir::detachingOperations() QCOMPARE(dir1.sorting(), sorting); } +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) +void tst_QDir::isRoot_data() +{ + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("isRoot"); + + QString test = QDir::rootPath(); + QTest::newRow(QString("rootPath " + test).toLatin1()) << test << true; + test = QDir::rootPath().append("./"); + QTest::newRow(QString("./ appended " + test).toLatin1()) << test << false; + test = QDir(QDir::rootPath().append("./")).canonicalPath(); + QTest::newRow(QString("canonicalPath " + test).toLatin1()) << test << true; + test = QDir::rootPath().left(2); + QTest::newRow(QString("drive relative " + test).toLatin1()) << test << false; +} + +void tst_QDir::isRoot() +{ + QFETCH(QString, path); + QFETCH(bool, isRoot); + + QDir dir(path); + QCOMPARE(dir.isRoot(),isRoot); +} +#endif + QTEST_MAIN(tst_QDir) #include "tst_qdir.moc" diff --git a/tests/auto/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/qfiledialog2/tst_qfiledialog2.cpp index 6299c24..ed4ecb4 100644 --- a/tests/auto/qfiledialog2/tst_qfiledialog2.cpp +++ b/tests/auto/qfiledialog2/tst_qfiledialog2.cpp @@ -548,7 +548,7 @@ void tst_QFileDialog2::task226366_lowerCaseHardDriveWindows() QTest::qWait(200); QTest::keyClick(edit->completer()->popup(), Qt::Key_Down); QTest::qWait(200); - QCOMPARE(edit->text(), QString("C:")); + QCOMPARE(edit->text(), QString("C:/")); QTest::qWait(2000); //i clear my previous selection in the completer QTest::keyClick(edit->completer()->popup(), Qt::Key_Down); @@ -556,7 +556,7 @@ void tst_QFileDialog2::task226366_lowerCaseHardDriveWindows() QTest::keyClick(edit, (char)(Qt::Key_C | Qt::SHIFT)); QTest::qWait(200); QTest::keyClick(edit->completer()->popup(), Qt::Key_Down); - QCOMPARE(edit->text(), QString("C:")); + QCOMPARE(edit->text(), QString("C:/")); } #endif diff --git a/tests/auto/qfileinfo/tst_qfileinfo.cpp b/tests/auto/qfileinfo/tst_qfileinfo.cpp index 208110a..7659a75 100644 --- a/tests/auto/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/qfileinfo/tst_qfileinfo.cpp @@ -46,6 +46,7 @@ #include <qfile.h> #include <qdir.h> #include <qcoreapplication.h> +#include <qlibrary.h> #include <qtemporaryfile.h> #include <qdir.h> #include <qfileinfo.h> @@ -55,7 +56,9 @@ #include <sys/stat.h> #endif #ifdef Q_OS_WIN +#define _WIN32_WINNT 0x500 #include <qt_windows.h> +#include <qlibrary.h> #endif #include <qplatformdefs.h> #include <qdebug.h> @@ -65,6 +68,7 @@ #endif #include "../network-settings.h" #include <private/qfileinfo_p.h> +#include "../../shared/filesystem.h" #if defined(Q_OS_SYMBIAN) # define SRCDIR "" @@ -151,6 +155,9 @@ private slots: void isHidden_data(); void isHidden(); +#if defined(Q_OS_MAC) + void isHiddenFromFinder(); +#endif void isBundle_data(); void isBundle(); @@ -161,6 +168,8 @@ private slots: void refresh(); #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + void ntfsJunctionPointsAndSymlinks_data(); + void ntfsJunctionPointsAndSymlinks(); void brokenShortcut(); #endif @@ -186,6 +195,8 @@ tst_QFileInfo::~tst_QFileInfo() QFile::remove("link.lnk"); QFile::remove("file1"); QFile::remove("dummyfile"); + QFile::remove("simplefile.txt"); + QFile::remove("longFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileName.txt"); #ifdef Q_OS_SYMBIAN QFile::remove("hidden.txt"); QFile::remove("nothidden.txt"); @@ -195,9 +206,17 @@ tst_QFileInfo::~tst_QFileInfo() #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) QDir().rmdir("./.hidden-directory"); + QFile::remove("link_to_tst_qfileinfo"); #endif -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) QDir().rmdir("./hidden-directory"); + QDir().rmdir("abs_symlink"); + QDir().rmdir("rel_symlink"); + QDir().rmdir("junction_pwd"); + QDir().rmdir("junction_root"); + QDir().rmdir("mountpoint"); + QFile::remove("abs_symlink.cpp"); + QFile::remove("rel_symlink.cpp"); #endif } @@ -580,6 +599,25 @@ void tst_QFileInfo::canonicalFilePath() } # endif #endif + +#ifdef Q_OS_WIN + typedef BOOL (WINAPI *PtrCreateSymbolicLink)(LPTSTR, LPTSTR, DWORD); + PtrCreateSymbolicLink ptrCreateSymbolicLink = + (PtrCreateSymbolicLink)QLibrary::resolve(QLatin1String("kernel32"), "CreateSymbolicLink"); + + if (!ptrCreateSymbolicLink || + ptrCreateSymbolicLink((wchar_t*)QString("res").utf16(), (wchar_t*)QString("resources").utf16(), 1) == 0) { + QSKIP("Symbolic links aren't supported by FS", SkipAll); + } + + QString currentPath = QDir::currentPath(); + QCOMPARE(QDir::setCurrent("res"), true); + + QCOMPARE(QFileInfo("file1").canonicalFilePath(), currentPath + "/resources/file1"); + + QCOMPARE(QDir::setCurrent(currentPath), true); + QFile::remove("res"); +#endif } void tst_QFileInfo::fileName_data() @@ -1148,6 +1186,27 @@ void tst_QFileInfo::isHidden() QCOMPARE(fi.isHidden(), isHidden); } +#if defined(Q_OS_MAC) +void tst_QFileInfo::isHiddenFromFinder() +{ + const char *filename = "test_foobar.txt"; + + QFile testFile(filename); + testFile.open(QIODevice::WriteOnly | QIODevice::Append); + testFile.write(QByteArray("world")); + testFile.close(); + + struct stat buf; + stat(filename, &buf); + chflags(filename, buf.st_flags | UF_HIDDEN); + + QFileInfo fi(filename); + QCOMPARE(fi.isHidden(), true); + + testFile.remove(); +} +#endif + void tst_QFileInfo::isBundle_data() { QTest::addColumn<QString>("path"); @@ -1239,6 +1298,115 @@ void tst_QFileInfo::refresh() } #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() +{ + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("isSymLink"); + QTest::addColumn<QString>("linkTarget"); + QTest::addColumn<QString>("canonicalFilePath"); + + QDir pwd; + pwd.mkdir("target"); + + QLibrary kernel32("kernel32"); + typedef BOOLEAN (WINAPI *PtrCreateSymbolicLink)(LPCWSTR, LPCWSTR, DWORD); + PtrCreateSymbolicLink createSymbolicLinkW = 0; + createSymbolicLinkW = (PtrCreateSymbolicLink) kernel32.resolve("CreateSymbolicLinkW"); + if (!createSymbolicLinkW) { + //we need at least one data set for the test not to fail when skipping _data function + QDir target("target"); + QTest::newRow("dummy") << target.path() << false << "" << target.canonicalPath(); + QSKIP("symbolic links not supported by operating system",SkipSingle); + } + { + //Directory symlinks + QDir target("target"); + QVERIFY(target.exists()); + + QString absTarget = QDir::toNativeSeparators(target.absolutePath()); + QString absSymlink = QDir::toNativeSeparators(pwd.absolutePath()).append("\\abs_symlink"); + QString relTarget = "target"; + QString relSymlink = "rel_symlink"; + QString fileInTarget(absTarget); + fileInTarget.append("\\file"); + QString fileInSymlink(absSymlink); + fileInSymlink.append("\\file"); + QFile file(fileInTarget); + file.open(QIODevice::ReadWrite); + file.close(); + + QVERIFY(pwd.exists("abs_symlink") || createSymbolicLinkW((wchar_t*)absSymlink.utf16(),(wchar_t*)absTarget.utf16(),0x1)); + QVERIFY(pwd.exists(relSymlink) || createSymbolicLinkW((wchar_t*)relSymlink.utf16(),(wchar_t*)relTarget.utf16(),0x1)); + QVERIFY(file.exists()); + + QTest::newRow("absolute dir symlink") << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalPath(); + QTest::newRow("relative dir symlink") << relSymlink << true << QDir::fromNativeSeparators(relTarget) << target.canonicalPath(); + QTest::newRow("file in symlink dir") << fileInSymlink << false << "" << target.canonicalPath().append("/file"); + } + { + //File symlinks + QFileInfo target(SRCDIR "tst_qfileinfo.cpp"); + QString absTarget = QDir::toNativeSeparators(target.absoluteFilePath()); + QString absSymlink = QDir::toNativeSeparators(pwd.absolutePath()).append("\\abs_symlink.cpp"); + QString relTarget = QDir::toNativeSeparators(pwd.relativeFilePath(target.absoluteFilePath())); + QString relSymlink = "rel_symlink.cpp"; + QVERIFY(pwd.exists("abs_symlink.cpp") || createSymbolicLinkW((wchar_t*)absSymlink.utf16(),(wchar_t*)absTarget.utf16(),0x0)); + QVERIFY(pwd.exists(relSymlink) || createSymbolicLinkW((wchar_t*)relSymlink.utf16(),(wchar_t*)relTarget.utf16(),0x0)); + + QTest::newRow("absolute file symlink") << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath(); + QTest::newRow("relative file symlink") << relSymlink << true << QDir::fromNativeSeparators(relTarget) << target.canonicalFilePath(); + } + + //Junctions + QString target = "target"; + QString junction = "junction_pwd"; + FileSystem::createNtfsJunction(target, junction); + QFileInfo targetInfo(target); + QTest::newRow("junction_pwd") << junction << true << targetInfo.absoluteFilePath() << targetInfo.canonicalFilePath(); + + QFileInfo fileInJunction(targetInfo.absoluteFilePath().append("/file")); + QFile file(fileInJunction.absoluteFilePath()); + file.open(QIODevice::ReadWrite); + file.close(); + QVERIFY(file.exists()); + QTest::newRow("file in junction") << fileInJunction.absoluteFilePath() << false << "" << fileInJunction.canonicalFilePath(); + + target = QDir::rootPath(); + junction = "junction_root"; + FileSystem::createNtfsJunction(target, junction); + targetInfo.setFile(target); + QTest::newRow("junction_root") << junction << true << targetInfo.absoluteFilePath() << targetInfo.canonicalFilePath(); + + //Mountpoint + typedef BOOLEAN (WINAPI *PtrGetVolumeNameForVolumeMountPointW)(LPCWSTR, LPWSTR, DWORD); + PtrGetVolumeNameForVolumeMountPointW getVolumeNameForVolumeMountPointW = 0; + getVolumeNameForVolumeMountPointW = (PtrGetVolumeNameForVolumeMountPointW) kernel32.resolve("GetVolumeNameForVolumeMountPointW"); + if(getVolumeNameForVolumeMountPointW) + { + wchar_t buffer[MAX_PATH]; + QString rootPath = QDir::toNativeSeparators(QDir::rootPath()); + QVERIFY(getVolumeNameForVolumeMountPointW((wchar_t*)rootPath.utf16(), buffer, MAX_PATH)); + QString rootVolume = QString::fromWCharArray(buffer); + junction = "mountpoint"; + rootVolume.replace("\\\\?\\","\\??\\"); + FileSystem::createNtfsJunction(rootVolume, junction); + QTest::newRow("mountpoint") << junction << true << QDir::fromNativeSeparators(rootPath) << QDir::rootPath(); + } +} + +void tst_QFileInfo::ntfsJunctionPointsAndSymlinks() +{ + QFETCH(QString, path); + QFETCH(bool, isSymLink); + QFETCH(QString, linkTarget); + QFETCH(QString, canonicalFilePath); + + QFileInfo fi(path); + QCOMPARE(fi.isSymLink(), isSymLink); + QCOMPARE(fi.symLinkTarget(), linkTarget); + QCOMPARE(fi.canonicalFilePath(), canonicalFilePath); +} + void tst_QFileInfo::brokenShortcut() { QString linkName("borkenlink.lnk"); diff --git a/tests/auto/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/qfontdatabase/tst_qfontdatabase.cpp index 357b82e..bddd92a 100644 --- a/tests/auto/qfontdatabase/tst_qfontdatabase.cpp +++ b/tests/auto/qfontdatabase/tst_qfontdatabase.cpp @@ -70,6 +70,11 @@ private slots: void fixedPitch_data(); void fixedPitch(); +#ifdef Q_WS_MAC + void trickyFonts_data(); + void trickyFonts(); +#endif + void widthTwoTimes_data(); void widthTwoTimes(); @@ -131,10 +136,16 @@ void tst_QFontDatabase::fixedPitch_data() QTest::newRow( "Times New Roman" ) << QString( "Times New Roman" ) << false; QTest::newRow( "Arial" ) << QString( "Arial" ) << false; - QTest::newRow( "Script" ) << QString( "Script" ) << false; + QTest::newRow( "Andale Mono" ) << QString( "Andale Mono" ) << true; QTest::newRow( "Courier" ) << QString( "Courier" ) << true; QTest::newRow( "Courier New" ) << QString( "Courier New" ) << true; +#ifndef Q_WS_MAC + QTest::newRow( "Script" ) << QString( "Script" ) << false; QTest::newRow( "Lucida Console" ) << QString( "Lucida Console" ) << true; +#else + QTest::newRow( "Menlo" ) << QString( "Menlo" ) << true; + QTest::newRow( "Monaco" ) << QString( "Monaco" ) << true; +#endif } void tst_QFontDatabase::fixedPitch() @@ -156,6 +167,28 @@ void tst_QFontDatabase::fixedPitch() QCOMPARE(fi.fixedPitch(), fixedPitch); } +#ifdef Q_WS_MAC +void tst_QFontDatabase::trickyFonts_data() +{ + QTest::addColumn<QString>("font"); + + QTest::newRow( "Geeza Pro" ) << QString( "Geeza Pro" ); +} + +void tst_QFontDatabase::trickyFonts() +{ + QFETCH(QString, font); + + QFontDatabase fdb; + if (!fdb.families().contains(font)) + QSKIP( "Font not installed", SkipSingle); + + QFont qfont(font); + QFontInfo fi(qfont); + QCOMPARE(fi.family(), font); +} +#endif + void tst_QFontDatabase::widthTwoTimes_data() { QTest::addColumn<QString>("font"); diff --git a/tests/auto/qfontmetrics/qfontmetrics.pro b/tests/auto/qfontmetrics/qfontmetrics.pro index 51a7057..c0dc1ab 100644 --- a/tests/auto/qfontmetrics/qfontmetrics.pro +++ b/tests/auto/qfontmetrics/qfontmetrics.pro @@ -1,4 +1,4 @@ load(qttest_p4) SOURCES += tst_qfontmetrics.cpp - +RESOURCES += testfont.qrc diff --git a/tests/auto/qfontmetrics/testfont.qrc b/tests/auto/qfontmetrics/testfont.qrc new file mode 100644 index 0000000..bc0c0b0 --- /dev/null +++ b/tests/auto/qfontmetrics/testfont.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/fonts"> + <file>ucs4font.ttf</file> + </qresource> +</RCC> diff --git a/tests/auto/qfontmetrics/tst_qfontmetrics.cpp b/tests/auto/qfontmetrics/tst_qfontmetrics.cpp index a22d624..4250415 100644 --- a/tests/auto/qfontmetrics/tst_qfontmetrics.cpp +++ b/tests/auto/qfontmetrics/tst_qfontmetrics.cpp @@ -74,6 +74,7 @@ private slots: void bypassShaping(); void elidedMultiLength(); void elidedMultiLengthF(); + void inFontUcs4(); }; tst_QFontMetrics::tst_QFontMetrics() @@ -266,5 +267,26 @@ void tst_QFontMetrics::elidedMultiLengthF() elidedMultiLength_helper<QFontMetricsF>(); } +void tst_QFontMetrics::inFontUcs4() +{ + int id = QFontDatabase::addApplicationFont(":/fonts/ucs4font.ttf"); + QVERIFY(id >= 0); + + QFont font("QtTestUcs4"); + { + QFontMetrics fm(font); + + QVERIFY(fm.inFontUcs4(0x1D7FF)); + } + + { + QFontMetricsF fm(font); + + QVERIFY(fm.inFontUcs4(0x1D7FF)); + } + + QFontDatabase::removeApplicationFont(id); +} + QTEST_MAIN(tst_QFontMetrics) #include "tst_qfontmetrics.moc" diff --git a/tests/auto/qfontmetrics/ucs4font.ttf b/tests/auto/qfontmetrics/ucs4font.ttf Binary files differnew file mode 100644 index 0000000..31b6997 --- /dev/null +++ b/tests/auto/qfontmetrics/ucs4font.ttf diff --git a/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp b/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp index c53c67a..54463c9 100644 --- a/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp +++ b/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp @@ -47,6 +47,7 @@ #include <qfuturewatcher.h> #include <qtconcurrentrun.h> #include <qtconcurrentmap.h> +#include "../../shared/util.h" #ifndef QT_NO_CONCURRENT_TEST #include <private/qfutureinterface_p.h> @@ -81,6 +82,7 @@ private slots: void incrementalMapResults(); void incrementalFilterResults(); void qfutureSynchornizer(); + void warnRace(); }; QTEST_MAIN(tst_QFutureWatcher) @@ -466,12 +468,12 @@ void tst_QFutureWatcher::toMuchProgress() ProgressObject o; QFutureWatcher<void> f; - f.setFuture((new ProgressEmitterTask())->start()); QObject::connect(&f, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); #ifdef PRINT QObject::connect(&f, SIGNAL(progressValueChanged(int)), &o, SLOT(printProgress(int))); #endif QObject::connect(&f, SIGNAL(progressValueChanged(int)), &o, SLOT(registerProgress(int))); + f.setFuture((new ProgressEmitterTask())->start()); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); @@ -886,6 +888,37 @@ void tst_QFutureWatcher::qfutureSynchornizer() QVERIFY(t.elapsed() < taskCount * 10); } +class DummyObject : public QObject { + Q_OBJECT +public slots: + void dummySlot() {} +public: + static void function(QMutex *m) + { + QMutexLocker lock(m); + } +}; + +void tst_QFutureWatcher::warnRace() +{ +#ifndef Q_OS_MAC //I don't know why it is not working on mac +#ifndef QT_NO_DEBUG + QTest::ignoreMessage(QtWarningMsg, "QFutureWatcher::connect: connecting after calling setFuture() is likely to produce race"); +#endif +#endif + QFutureWatcher<void> watcher; + DummyObject object; + QMutex mutex; + mutex.lock(); + + QFuture<void> future = QtConcurrent::run(DummyObject::function, &mutex); + watcher.setFuture(future); + QTRY_VERIFY(future.isStarted()); + connect(&watcher, SIGNAL(finished()), &object, SLOT(dummySlot())); + mutex.unlock(); + future.waitForFinished(); +} + #include "tst_qfuturewatcher.moc" #else diff --git a/tests/auto/qgl/tst_qgl.cpp b/tests/auto/qgl/tst_qgl.cpp index e411508..dfcfb47 100644 --- a/tests/auto/qgl/tst_qgl.cpp +++ b/tests/auto/qgl/tst_qgl.cpp @@ -1872,11 +1872,10 @@ void tst_QGL::destroyFBOAfterContext() #ifdef QT_BUILD_INTERNAL -class tst_QGLResource : public QObject +class tst_QGLResource { - Q_OBJECT public: - tst_QGLResource(QObject *parent = 0) : QObject(parent) {} + tst_QGLResource(const QGLContext * = 0) {} ~tst_QGLResource() { ++deletions; } static int deletions; @@ -1884,12 +1883,7 @@ public: int tst_QGLResource::deletions = 0; -static void qt_shared_test_free(void *data) -{ - delete reinterpret_cast<tst_QGLResource *>(data); -} - -Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_shared_test, (qt_shared_test_free)) +Q_GLOBAL_STATIC(QGLContextGroupResource<tst_QGLResource>, qt_shared_test) #endif @@ -1909,10 +1903,9 @@ void tst_QGL::shareRegister() guard.setId(3); QVERIFY(guard.id() == 3); - // Add a resource to the first context. - tst_QGLResource *res1 = new tst_QGLResource(); - QVERIFY(!qt_shared_test()->value(glw1->context())); - qt_shared_test()->insert(glw1->context(), res1); + // Request a tst_QGLResource object for the first context. + tst_QGLResource *res1 = qt_shared_test()->value(glw1->context()); + QVERIFY(res1); QVERIFY(qt_shared_test()->value(glw1->context()) == res1); // Create another context that shares with the first. @@ -1951,10 +1944,9 @@ void tst_QGL::shareRegister() QGLSharedResourceGuard guard3(glw3->context()); guard3.setId(5); - // Add a resource to the third context. - tst_QGLResource *res3 = new tst_QGLResource(); - QVERIFY(!qt_shared_test()->value(glw3->context())); - qt_shared_test()->insert(glw3->context(), res3); + // Request a resource to the third context. + tst_QGLResource *res3 = qt_shared_test()->value(glw3->context()); + QVERIFY(res3); QVERIFY(qt_shared_test()->value(glw1->context()) == res1); QVERIFY(qt_shared_test()->value(glw2->context()) == res1); QVERIFY(qt_shared_test()->value(glw3->context()) == res3); diff --git a/tests/auto/qglfunctions/qglfunctions.pro b/tests/auto/qglfunctions/qglfunctions.pro new file mode 100644 index 0000000..aa81547 --- /dev/null +++ b/tests/auto/qglfunctions/qglfunctions.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +requires(contains(QT_CONFIG,opengl)) +QT += opengl + +win32:!wince*: DEFINES += QT_NO_EGL + +SOURCES += tst_qglfunctions.cpp diff --git a/tests/auto/qglfunctions/tst_qglfunctions.cpp b/tests/auto/qglfunctions/tst_qglfunctions.cpp new file mode 100644 index 0000000..73e63b5 --- /dev/null +++ b/tests/auto/qglfunctions/tst_qglfunctions.cpp @@ -0,0 +1,244 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenGL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <QtOpenGL/qglfunctions.h> + +class tst_QGLFunctions : public QObject +{ + Q_OBJECT +public: + tst_QGLFunctions() {} + ~tst_QGLFunctions() {} + +private slots: + void features(); + void multitexture(); + void blendColor(); + +private: + static bool hasExtension(const char *name); +}; + +bool tst_QGLFunctions::hasExtension(const char *name) +{ + QString extensions = + QString::fromLatin1 + (reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); + return extensions.split(QLatin1Char(' ')).contains + (QString::fromLatin1(name)); +} + +// Check that the reported features are consistent with the platform. +void tst_QGLFunctions::features() +{ + // Before being associated with a context, there should be + // no features enabled. + QGLFunctions funcs; + QVERIFY(!funcs.openGLFeatures()); + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::Multitexture)); + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::Shaders)); + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::Buffers)); + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::Framebuffers)); + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::BlendColor)); + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::BlendEquation)); + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::BlendEquationSeparate)); + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::BlendFuncSeparate)); + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::BlendSubtract)); + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::CompressedTextures)); + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::Multisample)); + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::StencilSeparate)); + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::NPOTTextures)); + + // Make a context current. + QGLWidget glw; + if (!glw.isValid()) + QSKIP("Could not create a GL context", SkipAll); + glw.makeCurrent(); + funcs.initializeGLFunctions(); + + // Validate the features against what we expect for this platform. +#if defined(QT_OPENGL_ES_2) + QGLFunctions::OpenGLFeatures allFeatures = + (QGLFunctions::Multitexture | + QGLFunctions::Shaders | + QGLFunctions::Buffers | + QGLFunctions::Framebuffers | + QGLFunctions::BlendColor | + QGLFunctions::BlendEquation | + QGLFunctions::BlendEquationSeparate | + QGLFunctions::BlendFuncSeparate | + QGLFunctions::BlendSubtract | + QGLFunctions::CompressedTextures | + QGLFunctions::Multisample | + QGLFunctions::StencilSeparate | + QGLFunctions::NPOTTextures); + QVERIFY((funcs.openGLFeatures() & allFeatures) == allFeatures); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::Multitexture)); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::Shaders)); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::Buffers)); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::Framebuffers)); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::BlendColor)); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::BlendEquation)); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::BlendEquationSeparate)); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::BlendFuncSeparate)); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::BlendSubtract)); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::CompressedTextures)); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::Multisample)); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::StencilSeparate)); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::NPOTTextures)); +#elif defined(QT_OPENGL_ES) + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::Multitexture)); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::Buffers)); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::CompressedTextures)); + QVERIFY(funcs.hasOpenGLFeature(QGLFunctions::Multisample)); + + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::Shaders)); + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::BlendColor)); + QVERIFY(!funcs.hasOpenGLFeature(QGLFunctions::StencilSeparate)); + + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::Framebuffers), + hasExtension("GL_OES_framebuffer_object")); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::BlendEquationSeparate), + hasExtension("GL_OES_blend_equation_separate")); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::BlendFuncSeparate), + hasExtension("GL_OES_blend_func_separate")); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::BlendSubtract), + hasExtension("GL_OES_blend_subtract")); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::NPOTTextures), + hasExtension("GL_OES_texture_npot")); +#else + // We check for both the extension name and the minimum OpenGL version + // for the feature. This will help us catch situations where a platform + // doesn't list an extension by name but does have the feature by virtue + // of its version number. + QGLFormat::OpenGLVersionFlags versions = QGLFormat::openGLVersionFlags(); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::Multitexture), + hasExtension("GL_ARB_multitexture") || + (versions & QGLFormat::OpenGL_Version_1_3) != 0); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::Shaders), + hasExtension("GL_ARB_shader_objects") || + (versions & QGLFormat::OpenGL_Version_2_0) != 0); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::Buffers), + (versions & QGLFormat::OpenGL_Version_1_5) != 0); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::Framebuffers), + hasExtension("GL_EXT_framebuffer_object") || + hasExtension("GL_ARB_framebuffer_object")); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::BlendColor), + hasExtension("GL_EXT_blend_color") || + (versions & QGLFormat::OpenGL_Version_1_2) != 0); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::BlendEquation), + (versions & QGLFormat::OpenGL_Version_1_2) != 0); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::BlendEquationSeparate), + hasExtension("GL_EXT_blend_equation_separate") || + (versions & QGLFormat::OpenGL_Version_2_0) != 0); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::BlendFuncSeparate), + hasExtension("GL_EXT_blend_func_separate") || + (versions & QGLFormat::OpenGL_Version_1_4) != 0); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::BlendSubtract), + hasExtension("GL_EXT_blend_subtract")); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::CompressedTextures), + hasExtension("GL_ARB_texture_compression") || + (versions & QGLFormat::OpenGL_Version_1_3) != 0); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::Multisample), + hasExtension("GL_ARB_multisample") || + (versions & QGLFormat::OpenGL_Version_1_3) != 0); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::StencilSeparate), + (versions & QGLFormat::OpenGL_Version_2_0) != 0); + QCOMPARE(funcs.hasOpenGLFeature(QGLFunctions::NPOTTextures), + hasExtension("GL_ARB_texture_non_power_of_two") || + (versions & QGLFormat::OpenGL_Version_2_0) != 0); +#endif +} + +// Verify that the multitexture functions appear to resolve and work. +void tst_QGLFunctions::multitexture() +{ + QGLFunctions funcs; + QGLWidget glw; + if (!glw.isValid()) + QSKIP("Could not create a GL context", SkipAll); + glw.makeCurrent(); + funcs.initializeGLFunctions(); + + if (!funcs.hasOpenGLFeature(QGLFunctions::Multitexture)) + QSKIP("Multitexture functions are not supported", SkipSingle); + + funcs.glActiveTexture(GL_TEXTURE1); + + GLint active = 0; + glGetIntegerv(GL_ACTIVE_TEXTURE, &active); + QVERIFY(active == GL_TEXTURE1); + + funcs.glActiveTexture(GL_TEXTURE0); + + active = 0; + glGetIntegerv(GL_ACTIVE_TEXTURE, &active); + QVERIFY(active == GL_TEXTURE0); +} + +// Verify that the glBlendColor() function appears to resolve and work. +void tst_QGLFunctions::blendColor() +{ + QGLFunctions funcs; + QGLWidget glw; + if (!glw.isValid()) + QSKIP("Could not create a GL context", SkipAll); + glw.makeCurrent(); + funcs.initializeGLFunctions(); + + if (!funcs.hasOpenGLFeature(QGLFunctions::BlendColor)) + QSKIP("glBlendColor() is not supported", SkipSingle); + + funcs.glBlendColor(0.0f, 1.0f, 0.0f, 1.0f); + + GLfloat colors[4] = {0.5f, 0.5f, 0.5f, 0.5f}; + glGetFloatv(GL_BLEND_COLOR, colors); + + QCOMPARE(colors[0], 0.0f); + QCOMPARE(colors[1], 1.0f); + QCOMPARE(colors[2], 0.0f); + QCOMPARE(colors[3], 1.0f); +} + +QTEST_MAIN(tst_QGLFunctions) + +#include "tst_qglfunctions.moc" diff --git a/tests/auto/qglthreads/tst_qglthreads.cpp b/tests/auto/qglthreads/tst_qglthreads.cpp index cce3161..38b0dab 100644 --- a/tests/auto/qglthreads/tst_qglthreads.cpp +++ b/tests/auto/qglthreads/tst_qglthreads.cpp @@ -45,10 +45,6 @@ #include <QtOpenGL/QtOpenGL> #include "tst_qglthreads.h" -#ifdef Q_WS_X11 -#include <private/qt_x11_p.h> -#endif - #define RUNNING_TIME 5000 tst_QGLThreads::tst_QGLThreads(QObject *parent) @@ -56,8 +52,6 @@ tst_QGLThreads::tst_QGLThreads(QObject *parent) { } - - /* swapInThread @@ -339,6 +333,7 @@ void renderAScene(int w, int h) class ThreadSafeGLWidget : public QGLWidget { public: + ThreadSafeGLWidget(QWidget *parent = 0) : QGLWidget(parent) {} void paintEvent(QPaintEvent *) { // ignored as we're anyway swapping as fast as we can @@ -426,7 +421,7 @@ void tst_QGLThreads::renderInThread_data() void tst_QGLThreads::renderInThread() { #ifdef Q_OS_MAC - QSKIP("OpenGL threading tests are currently disabled on mac as they were causing reboots", SkipAll); + QSKIP("OpenGL threading tests are currently disabled on Mac as they were causing reboots", SkipAll); #endif QFETCH(bool, resize); @@ -461,15 +456,301 @@ void tst_QGLThreads::renderInThread() QVERIFY(!thread.failure); } +class Device +{ +public: + virtual ~Device() {} + virtual QPaintDevice *realPaintDevice() = 0; + virtual void prepareDevice() {} +}; + +class GLWidgetWrapper : public Device +{ +public: + GLWidgetWrapper() { + widget.resize(150, 150); + widget.show(); + QTest::qWaitForWindowShown(&widget); + widget.doneCurrent(); + } + QPaintDevice *realPaintDevice() { return &widget; } + ThreadSafeGLWidget widget; +}; +class PixmapWrapper : public Device +{ +public: + PixmapWrapper() { pixmap = new QPixmap(512, 512); } + ~PixmapWrapper() { delete pixmap; } + QPaintDevice *realPaintDevice() { return pixmap; } -int main(int argc, char **argv) + QPixmap *pixmap; +}; + +class PixelBufferWrapper : public Device +{ +public: + PixelBufferWrapper() { pbuffer = new QGLPixelBuffer(512, 512); } + ~PixelBufferWrapper() { delete pbuffer; } + QPaintDevice *realPaintDevice() { return pbuffer; } + + QGLPixelBuffer *pbuffer; +}; + + +class FrameBufferObjectWrapper : public Device +{ +public: + FrameBufferObjectWrapper() { + widget.makeCurrent(); + fbo = new QGLFramebufferObject(512, 512); + widget.doneCurrent(); + } + ~FrameBufferObjectWrapper() { delete fbo; } + QPaintDevice *realPaintDevice() { return fbo; } + void prepareDevice() { widget.makeCurrent(); } + + ThreadSafeGLWidget widget; + QGLFramebufferObject *fbo; +}; + + +class ThreadPainter : public QObject +{ + Q_OBJECT +public: + ThreadPainter(Device *pd) : device(pd), fail(true) { + pixmap = QPixmap(40, 40); + pixmap.fill(Qt::green); + QPainter p(&pixmap); + p.drawLine(0, 0, 40, 40); + p.drawLine(0, 40, 40, 0); + } + +public slots: + void draw() { + bool beginFailed = false; + QTime time; + time.start(); + int rotAngle = 10; + device->prepareDevice(); + QPaintDevice *paintDevice = device->realPaintDevice(); + QSize s(paintDevice->width(), paintDevice->height()); + while (time.elapsed() < RUNNING_TIME) { + QPainter p; + if (!p.begin(paintDevice)) { + beginFailed = true; + break; + } + p.translate(s.width()/2, s.height()/2); + p.rotate(rotAngle); + p.translate(-s.width()/2, -s.height()/2); + p.fillRect(0, 0, s.width(), s.height(), Qt::red); + QRect rect(QPoint(0, 0), s); + p.drawPixmap(10, 10, pixmap); + p.drawTiledPixmap(50, 50, 100, 100, pixmap); + p.drawText(rect.center(), "This is a piece of text"); + p.end(); + rotAngle += 2; +#ifdef Q_WS_WIN + Sleep(20); +#else + usleep(20 * 1000); +#endif + } + + fail = beginFailed; + QThread::currentThread()->quit(); + } + + bool failed() { return fail; } + +private: + QPixmap pixmap; + Device *device; + bool fail; +}; + +template <class T> +class PaintThreadManager +{ +public: + PaintThreadManager(int count) : numThreads(count) + { + for (int i=0; i<numThreads; ++i) { + devices.append(new T); + threads.append(new QThread); + painters.append(new ThreadPainter(devices.at(i))); + painters.at(i)->moveToThread(threads.at(i)); + painters.at(i)->connect(threads.at(i), SIGNAL(started()), painters.at(i), SLOT(draw())); + } + } + + ~PaintThreadManager() { + qDeleteAll(threads); + qDeleteAll(painters); + qDeleteAll(devices); + } + + + void start() { + for (int i=0; i<numThreads; ++i) + threads.at(i)->start(); + } + + bool areRunning() { + bool running = false; + for (int i=0; i<numThreads; ++i){ + if (threads.at(i)->isRunning()) + running = true; + } + + return running; + } + + bool failed() { + for (int i=0; i<numThreads; ++i) { + if (painters.at(i)->failed()) + return true; + } + + return false; + } + +private: + QList<QThread *> threads; + QList<Device *> devices; + QList<ThreadPainter *> painters; + int numThreads; +}; + +/* + This test uses QPainter to draw onto different QGLWidgets in + different threads at the same time. The ThreadSafeGLWidget is + necessary to handle paint and resize events that might come from + the main thread at any time while the test is running. The resize + and paint events would cause makeCurrent() calls to be issued from + within the QGLWidget while the widget's context was current in + another thread, which would cause errors. +*/ +void tst_QGLThreads::painterOnGLWidgetInThread() +{ +#ifdef Q_OS_MAC + QSKIP("OpenGL threading tests are currently disabled on Mac as they were causing reboots", SkipAll); +#endif + if (!((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) || + (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0))) { + QSKIP("The OpenGL based threaded QPainter tests requires OpenGL/ES 2.0.", SkipAll); + } + + PaintThreadManager<GLWidgetWrapper> painterThreads(5); + painterThreads.start(); + + while (painterThreads.areRunning()) { + qApp->processEvents(); +#ifdef Q_WS_WIN + Sleep(100); +#else + usleep(100 * 1000); +#endif + } + QVERIFY(!painterThreads.failed()); +} + +/* + This test uses QPainter to draw onto different QPixmaps in + different threads at the same time. +*/ +void tst_QGLThreads::painterOnPixmapInThread() { #ifdef Q_WS_X11 - XInitThreads(); + QSKIP("Drawing text in threads onto X11 drawables currently crashes on some X11 servers.", SkipAll); +#endif + PaintThreadManager<PixmapWrapper> painterThreads(5); + painterThreads.start(); + + while (painterThreads.areRunning()) { + qApp->processEvents(); +#ifdef Q_WS_WIN + Sleep(100); +#else + usleep(100 * 1000); +#endif + } + QVERIFY(!painterThreads.failed()); +} + +/* This test uses QPainter to draw onto different QGLPixelBuffer + objects in different threads at the same time. +*/ +void tst_QGLThreads::painterOnPboInThread() +{ +#ifdef Q_OS_MAC + QSKIP("OpenGL threading tests are currently disabled on Mac as they were causing reboots", SkipAll); +#endif + if (!((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) || + (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0))) { + QSKIP("The OpenGL based threaded QPainter tests requires OpenGL/ES 2.0.", SkipAll); + return; + } + + if (!QGLPixelBuffer::hasOpenGLPbuffers()) { + QSKIP("This system doesn't support pbuffers.", SkipAll); + return; + } + + PaintThreadManager<PixelBufferWrapper> painterThreads(5); + painterThreads.start(); + + while (painterThreads.areRunning()) { + qApp->processEvents(); +#ifdef Q_WS_WIN + Sleep(100); +#else + usleep(100 * 1000); #endif + } + QVERIFY(!painterThreads.failed()); +} +/* This test uses QPainter to draw onto different + QGLFramebufferObjects (bound in a QGLWidget's context) in different + threads at the same time. +*/ +void tst_QGLThreads::painterOnFboInThread() +{ +#ifdef Q_OS_MAC + QSKIP("OpenGL threading tests are currently disabled on Mac as they were causing reboots", SkipAll); +#endif + if (!((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) || + (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0))) { + QSKIP("The OpenGL based threaded QPainter tests requires OpenGL/ES 2.0.", SkipAll); + return; + } + + if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) { + QSKIP("This system doesn't support framebuffer objects.", SkipAll); + return; + } + + PaintThreadManager<FrameBufferObjectWrapper> painterThreads(5); + painterThreads.start(); + + while (painterThreads.areRunning()) { + qApp->processEvents(); +#ifdef Q_WS_WIN + Sleep(100); +#else + usleep(100 * 1000); +#endif + } + QVERIFY(!painterThreads.failed()); +} + +int main(int argc, char **argv) +{ + QApplication::setAttribute(Qt::AA_X11InitThreads); QApplication app(argc, argv); QTEST_DISABLE_KEYPAD_NAVIGATION \ diff --git a/tests/auto/qglthreads/tst_qglthreads.h b/tests/auto/qglthreads/tst_qglthreads.h index 9e97909..a8c2963 100644 --- a/tests/auto/qglthreads/tst_qglthreads.h +++ b/tests/auto/qglthreads/tst_qglthreads.h @@ -56,6 +56,10 @@ private slots: void renderInThread_data(); void renderInThread(); + void painterOnGLWidgetInThread(); + void painterOnPixmapInThread(); + void painterOnPboInThread(); + void painterOnFboInThread(); }; #endif // TST_QGLTHREADS_H diff --git a/tests/auto/qglyphs/qglyphs.pro b/tests/auto/qglyphs/qglyphs.pro new file mode 100644 index 0000000..5084cf9 --- /dev/null +++ b/tests/auto/qglyphs/qglyphs.pro @@ -0,0 +1,11 @@ +load(qttest_p4) +QT = core gui + +SOURCES += \ + tst_qglyphs.cpp + +wince*|symbian*: { + DEFINES += SRCDIR=\\\"\\\" +} else { + DEFINES += SRCDIR=\\\"$$PWD/\\\" +}
\ No newline at end of file diff --git a/tests/auto/qglyphs/test.ttf b/tests/auto/qglyphs/test.ttf Binary files differnew file mode 100644 index 0000000..9043a57 --- /dev/null +++ b/tests/auto/qglyphs/test.ttf diff --git a/tests/auto/qglyphs/tst_qglyphs.cpp b/tests/auto/qglyphs/tst_qglyphs.cpp new file mode 100644 index 0000000..da91063 --- /dev/null +++ b/tests/auto/qglyphs/tst_qglyphs.cpp @@ -0,0 +1,573 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> + +#include <qglyphs.h> +#include <qpainter.h> +#include <qtextlayout.h> +#include <qfontdatabase.h> + +// #define DEBUG_SAVE_IMAGE + +class tst_QGlyphs: public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + void cleanupTestCase(); + + void constructionAndDestruction(); + void copyConstructor(); + void assignment(); + void equalsOperator_data(); + void equalsOperator(); + void textLayoutGlyphIndexes(); + void drawExistingGlyphs(); + void drawNonExistentGlyphs(); + void drawMultiScriptText1(); + void drawMultiScriptText2(); + void drawStruckOutText(); + void drawOverlinedText(); + void drawUnderlinedText(); + void drawRightToLeft(); + void detach(); + +private: + int m_testFontId; + QFont m_testFont; +}; + +Q_DECLARE_METATYPE(QGlyphs); + +void tst_QGlyphs::initTestCase() +{ + m_testFontId = QFontDatabase::addApplicationFont(SRCDIR "test.ttf"); + QVERIFY(m_testFontId >= 0); + + m_testFont = QFont("QtsSpecialTestFont"); + + QCOMPARE(QFontInfo(m_testFont).family(), QString::fromLatin1("QtsSpecialTestFont")); +} + +void tst_QGlyphs::cleanupTestCase() +{ + QFontDatabase::removeApplicationFont(m_testFontId); +} + +void tst_QGlyphs::constructionAndDestruction() +{ + QGlyphs glyphIndexes; +} + +static QGlyphs make_dummy_indexes() +{ + QGlyphs glyphs; + + QVector<quint32> glyphIndexes; + QVector<QPointF> positions; + QFont font; + font.setPointSize(18); + + glyphIndexes.append(1); + glyphIndexes.append(2); + glyphIndexes.append(3); + + positions.append(QPointF(1, 2)); + positions.append(QPointF(3, 4)); + positions.append(QPointF(5, 6)); + + glyphs.setFont(font); + glyphs.setGlyphIndexes(glyphIndexes); + glyphs.setPositions(positions); + + return glyphs; +} + +void tst_QGlyphs::copyConstructor() +{ + QGlyphs glyphs; + + { + QVector<quint32> glyphIndexes; + QVector<QPointF> positions; + QFont font; + font.setPointSize(18); + + glyphIndexes.append(1); + glyphIndexes.append(2); + glyphIndexes.append(3); + + positions.append(QPointF(1, 2)); + positions.append(QPointF(3, 4)); + positions.append(QPointF(5, 6)); + + glyphs.setFont(font); + glyphs.setGlyphIndexes(glyphIndexes); + glyphs.setPositions(positions); + } + + QGlyphs otherGlyphs(glyphs); + QCOMPARE(otherGlyphs.font(), glyphs.font()); + QCOMPARE(glyphs.glyphIndexes(), otherGlyphs.glyphIndexes()); + QCOMPARE(glyphs.positions(), otherGlyphs.positions()); +} + +void tst_QGlyphs::assignment() +{ + QGlyphs glyphs(make_dummy_indexes()); + + QGlyphs otherGlyphs = glyphs; + QCOMPARE(otherGlyphs.font(), glyphs.font()); + QCOMPARE(glyphs.glyphIndexes(), otherGlyphs.glyphIndexes()); + QCOMPARE(glyphs.positions(), otherGlyphs.positions()); +} + +void tst_QGlyphs::equalsOperator_data() +{ + QTest::addColumn<QGlyphs>("one"); + QTest::addColumn<QGlyphs>("two"); + QTest::addColumn<bool>("equals"); + + QGlyphs one(make_dummy_indexes()); + QGlyphs two(make_dummy_indexes()); + + QTest::newRow("Identical") << one << two << true; + + { + QGlyphs busted(two); + + QVector<QPointF> positions = busted.positions(); + positions[2] += QPointF(1, 1); + busted.setPositions(positions); + + QTest::newRow("Different positions") << one << busted << false; + } + + { + QGlyphs busted(two); + QFont font = busted.font(); + font.setPointSize(font.pointSize() * 2); + busted.setFont(font); + + QTest::newRow("Different fonts") << one << busted << false; + } + + { + QGlyphs busted(two); + + QVector<quint32> glyphIndexes = busted.glyphIndexes(); + glyphIndexes[2] += 1; + busted.setGlyphIndexes(glyphIndexes); + + QTest::newRow("Different glyph indexes") << one << busted << false; + } + +} + +void tst_QGlyphs::equalsOperator() +{ + QFETCH(QGlyphs, one); + QFETCH(QGlyphs, two); + QFETCH(bool, equals); + + QCOMPARE(one == two, equals); + QCOMPARE(one != two, !equals); +} + + +void tst_QGlyphs::textLayoutGlyphIndexes() +{ + QString s; + s.append(QLatin1Char('A')); + s.append(QChar(0xe000)); + + QTextLayout layout(s); + layout.setFont(m_testFont); + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + QList<QGlyphs> listOfGlyphs = layout.glyphs(); + QCOMPARE(listOfGlyphs.size(), 1); + + QGlyphs glyphs = listOfGlyphs.at(0); + + QCOMPARE(glyphs.glyphIndexes().size(), 2); + QCOMPARE(glyphs.glyphIndexes().at(0), quint32(2)); + QCOMPARE(glyphs.glyphIndexes().at(1), quint32(1)); +} + +void tst_QGlyphs::drawExistingGlyphs() +{ + QPixmap textLayoutDraw(1000, 1000); + QPixmap drawGlyphs(1000, 1000); + + textLayoutDraw.fill(Qt::white); + drawGlyphs.fill(Qt::white); + + QString s; + s.append(QLatin1Char('A')); + s.append(QChar(0xe000)); + + QTextLayout layout(s); + layout.setFont(m_testFont); + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + { + QPainter p(&textLayoutDraw); + layout.draw(&p, QPointF(50, 50)); + } + + QGlyphs glyphs = layout.glyphs().size() > 0 + ? layout.glyphs().at(0) + : QGlyphs(); + + { + QPainter p(&drawGlyphs); + p.drawGlyphs(QPointF(50, 50), glyphs); + } + +#if defined(DEBUG_SAVE_IMAGE) + textLayoutDraw.save("drawExistingGlyphs_textLayoutDraw.png"); + drawGlyphs.save("drawExistingGlyphs_drawGlyphIndexes.png"); +#endif + + QCOMPARE(textLayoutDraw, drawGlyphs); +} + +void tst_QGlyphs::drawNonExistentGlyphs() +{ + QVector<quint32> glyphIndexes; + glyphIndexes.append(3); + + QVector<QPointF> glyphPositions; + glyphPositions.append(QPointF(0, 0)); + + QGlyphs glyphs; + glyphs.setGlyphIndexes(glyphIndexes); + glyphs.setPositions(glyphPositions); + glyphs.setFont(m_testFont); + + QPixmap image(1000, 1000); + image.fill(Qt::white); + + QPixmap imageBefore = image; + { + QPainter p(&image); + p.drawGlyphs(QPointF(50, 50), glyphs); + } + +#if defined(DEBUG_SAVE_IMAGE) + image.save("drawNonExistentGlyphs.png"); +#endif + + QCOMPARE(image, imageBefore); // Should be unchanged +} + +void tst_QGlyphs::drawMultiScriptText1() +{ + QString text; + text += QChar(0x03D0); // Greek, beta + + QTextLayout textLayout(text); + textLayout.beginLayout(); + textLayout.createLine(); + textLayout.endLayout(); + + QPixmap textLayoutDraw(1000, 1000); + textLayoutDraw.fill(Qt::white); + + QPixmap drawGlyphs(1000, 1000); + drawGlyphs.fill(Qt::white); + + QList<QGlyphs> glyphsList = textLayout.glyphs(); + QCOMPARE(glyphsList.size(), 1); + + { + QPainter p(&textLayoutDraw); + textLayout.draw(&p, QPointF(50, 50)); + } + + { + QPainter p(&drawGlyphs); + foreach (QGlyphs glyphs, glyphsList) + p.drawGlyphs(QPointF(50, 50), glyphs); + } + +#if defined(DEBUG_SAVE_IMAGE) + textLayoutDraw.save("drawMultiScriptText1_textLayoutDraw.png"); + drawGlyphs.save("drawMultiScriptText1_drawGlyphIndexes.png"); +#endif + + QCOMPARE(drawGlyphs, textLayoutDraw); +} + + +void tst_QGlyphs::drawMultiScriptText2() +{ + QString text; + text += QChar(0x0621); // Arabic, Hamza + text += QChar(0x03D0); // Greek, beta + + QTextLayout textLayout(text); + textLayout.beginLayout(); + textLayout.createLine(); + textLayout.endLayout(); + + QPixmap textLayoutDraw(1000, 1000); + textLayoutDraw.fill(Qt::white); + + QPixmap drawGlyphs(1000, 1000); + drawGlyphs.fill(Qt::white); + + QList<QGlyphs> glyphsList = textLayout.glyphs(); + QCOMPARE(glyphsList.size(), 2); + + { + QPainter p(&textLayoutDraw); + textLayout.draw(&p, QPointF(50, 50)); + } + + { + QPainter p(&drawGlyphs); + foreach (QGlyphs glyphs, glyphsList) + p.drawGlyphs(QPointF(50, 50), glyphs); + } + +#if defined(DEBUG_SAVE_IMAGE) + textLayoutDraw.save("drawMultiScriptText2_textLayoutDraw.png"); + drawGlyphs.save("drawMultiScriptText2_drawGlyphIndexes.png"); +#endif + + QCOMPARE(drawGlyphs, textLayoutDraw); +} + +void tst_QGlyphs::detach() +{ + QGlyphs glyphs; + + glyphs.setGlyphIndexes(QVector<quint32>() << 1 << 2 << 3); + + QGlyphs otherGlyphs; + otherGlyphs = glyphs; + + QCOMPARE(otherGlyphs.glyphIndexes(), glyphs.glyphIndexes()); + + otherGlyphs.setGlyphIndexes(QVector<quint32>() << 4 << 5 << 6); + + QCOMPARE(otherGlyphs.glyphIndexes(), QVector<quint32>() << 4 << 5 << 6); + QCOMPARE(glyphs.glyphIndexes(), QVector<quint32>() << 1 << 2 << 3); +} + +void tst_QGlyphs::drawStruckOutText() +{ + QPixmap textLayoutDraw(1000, 1000); + QPixmap drawGlyphs(1000, 1000); + + textLayoutDraw.fill(Qt::white); + drawGlyphs.fill(Qt::white); + + QString s = QString::fromLatin1("Foobar"); + + QFont font; + font.setStrikeOut(true); + + QTextLayout layout(s); + layout.setFont(font); + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + { + QPainter p(&textLayoutDraw); + layout.draw(&p, QPointF(50, 50)); + } + + QGlyphs glyphs = layout.glyphs().size() > 0 + ? layout.glyphs().at(0) + : QGlyphs(); + + { + QPainter p(&drawGlyphs); + p.drawGlyphs(QPointF(50, 50), glyphs); + } + +#if defined(DEBUG_SAVE_IMAGE) + textLayoutDraw.save("drawStruckOutText_textLayoutDraw.png"); + drawGlyphs.save("drawStruckOutText_drawGlyphIndexes.png"); +#endif + + QCOMPARE(textLayoutDraw, drawGlyphs); +} + +void tst_QGlyphs::drawOverlinedText() +{ + QPixmap textLayoutDraw(1000, 1000); + QPixmap drawGlyphs(1000, 1000); + + textLayoutDraw.fill(Qt::white); + drawGlyphs.fill(Qt::white); + + QString s = QString::fromLatin1("Foobar"); + + QFont font; + font.setOverline(true); + + QTextLayout layout(s); + layout.setFont(font); + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + { + QPainter p(&textLayoutDraw); + layout.draw(&p, QPointF(50, 50)); + } + + QGlyphs glyphs = layout.glyphs().size() > 0 + ? layout.glyphs().at(0) + : QGlyphs(); + + { + QPainter p(&drawGlyphs); + p.drawGlyphs(QPointF(50, 50), glyphs); + } + +#if defined(DEBUG_SAVE_IMAGE) + textLayoutDraw.save("drawOverlineText_textLayoutDraw.png"); + drawGlyphs.save("drawOverlineText_drawGlyphIndexes.png"); +#endif + + QCOMPARE(textLayoutDraw, drawGlyphs); +} + +void tst_QGlyphs::drawUnderlinedText() +{ + QPixmap textLayoutDraw(1000, 1000); + QPixmap drawGlyphs(1000, 1000); + + textLayoutDraw.fill(Qt::white); + drawGlyphs.fill(Qt::white); + + QString s = QString::fromLatin1("Foobar"); + + QFont font; + font.setUnderline(true); + + QTextLayout layout(s); + layout.setFont(font); + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + { + QPainter p(&textLayoutDraw); + layout.draw(&p, QPointF(50, 50)); + } + + QGlyphs glyphs = layout.glyphs().size() > 0 + ? layout.glyphs().at(0) + : QGlyphs(); + + { + QPainter p(&drawGlyphs); + p.drawGlyphs(QPointF(50, 50), glyphs); + } + +#if defined(DEBUG_SAVE_IMAGE) + textLayoutDraw.save("drawUnderlineText_textLayoutDraw.png"); + drawGlyphs.save("drawUnderlineText_drawGlyphIndexes.png"); +#endif + + QCOMPARE(textLayoutDraw, drawGlyphs); +} + +void tst_QGlyphs::drawRightToLeft() +{ + QString s; + s.append(QChar(1575)); + s.append(QChar(1578)); + + QPixmap textLayoutDraw(1000, 1000); + QPixmap drawGlyphs(1000, 1000); + + textLayoutDraw.fill(Qt::white); + drawGlyphs.fill(Qt::white); + + QFont font; + font.setUnderline(true); + + QTextLayout layout(s); + layout.setFont(font); + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + { + QPainter p(&textLayoutDraw); + layout.draw(&p, QPointF(50, 50)); + } + + QGlyphs glyphs = layout.glyphs().size() > 0 + ? layout.glyphs().at(0) + : QGlyphs(); + + { + QPainter p(&drawGlyphs); + p.drawGlyphs(QPointF(50, 50), glyphs); + } + +#if defined(DEBUG_SAVE_IMAGE) + textLayoutDraw.save("drawRightToLeft_textLayoutDraw.png"); + drawGlyphs.save("drawRightToLeft_drawGlyphIndexes.png"); +#endif + + QCOMPARE(textLayoutDraw, drawGlyphs); + +} + +QTEST_MAIN(tst_QGlyphs) +#include "tst_qglyphs.moc" + diff --git a/tests/auto/qgraphicsanchorlayout/qgraphicsanchorlayout.pro b/tests/auto/qgraphicsanchorlayout/qgraphicsanchorlayout.pro index 4c065f4..8768425 100644 --- a/tests/auto/qgraphicsanchorlayout/qgraphicsanchorlayout.pro +++ b/tests/auto/qgraphicsanchorlayout/qgraphicsanchorlayout.pro @@ -1,3 +1,3 @@ load(qttest_p4) SOURCES += tst_qgraphicsanchorlayout.cpp - +CONFIG += parallel_test diff --git a/tests/auto/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro b/tests/auto/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro index 27f48e0..90b7878 100644 --- a/tests/auto/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro +++ b/tests/auto/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro @@ -1,3 +1,3 @@ load(qttest_p4) SOURCES += tst_qgraphicsanchorlayout1.cpp - +CONFIG += parallel_test diff --git a/tests/auto/qgraphicseffect/qgraphicseffect.pro b/tests/auto/qgraphicseffect/qgraphicseffect.pro index 7effaca..94b3ce6 100644 --- a/tests/auto/qgraphicseffect/qgraphicseffect.pro +++ b/tests/auto/qgraphicseffect/qgraphicseffect.pro @@ -1,3 +1,3 @@ load(qttest_p4) SOURCES += tst_qgraphicseffect.cpp - +CONFIG += parallel_test diff --git a/tests/auto/qgraphicseffectsource/qgraphicseffectsource.pro b/tests/auto/qgraphicseffectsource/qgraphicseffectsource.pro index d506c6d..5658ad7 100644 --- a/tests/auto/qgraphicseffectsource/qgraphicseffectsource.pro +++ b/tests/auto/qgraphicseffectsource/qgraphicseffectsource.pro @@ -1,3 +1,3 @@ load(qttest_p4) SOURCES += tst_qgraphicseffectsource.cpp - +CONFIG += parallel_test diff --git a/tests/auto/qgraphicsgridlayout/qgraphicsgridlayout.pro b/tests/auto/qgraphicsgridlayout/qgraphicsgridlayout.pro index 97e68bc..d66d639 100644 --- a/tests/auto/qgraphicsgridlayout/qgraphicsgridlayout.pro +++ b/tests/auto/qgraphicsgridlayout/qgraphicsgridlayout.pro @@ -1,4 +1,4 @@ load(qttest_p4) SOURCES += tst_qgraphicsgridlayout.cpp - +CONFIG += parallel_test diff --git a/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp b/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp index 03c1d5b..82af71f 100644 --- a/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp +++ b/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp @@ -78,6 +78,7 @@ private slots: void horizontalSpacing(); void itemAt(); void removeAt(); + void removeItem(); void rowAlignment(); void rowCount(); void rowMaximumHeight(); @@ -108,6 +109,7 @@ private slots: void styleInfoLeak(); void task236367_maxSizeHint(); void heightForWidth(); + void widthForHeight(); }; class RectWidget : public QGraphicsWidget @@ -224,9 +226,10 @@ struct ItemDesc return (*this); } - ItemDesc &heightForWidth(QSizeF (*fnConstraint)(Qt::SizeHint, const QSizeF &)) { + ItemDesc &dynamicConstraint(QSizeF (*fnConstraint)(Qt::SizeHint, const QSizeF &), + Qt::Orientation orientation) { m_fnConstraint = fnConstraint; - m_constraintOrientation = Qt::Vertical; + m_constraintOrientation = orientation; return (*this); } @@ -234,7 +237,7 @@ struct ItemDesc QSizePolicy sp = m_sizePolicy; if (m_fnConstraint) { sp.setHeightForWidth(m_constraintOrientation == Qt::Vertical); - //sp.setWidthForHeight(m_constraintOrientation == Qt::Horizontal); + sp.setWidthForHeight(m_constraintOrientation == Qt::Horizontal); } item->setSizePolicy(sp); @@ -1020,6 +1023,32 @@ void tst_QGraphicsGridLayout::removeAt() delete widget; } +void tst_QGraphicsGridLayout::removeItem() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + + QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window); + scene.addItem(widget); + QGraphicsGridLayout *l = new QGraphicsGridLayout(); + widget->setLayout(l); + + populateLayout(l, 3, 2); + QCOMPARE(l->count(), 6); + l->removeItem(l->itemAt(5)); + l->removeItem(l->itemAt(4)); + QCOMPARE(l->count(), 4); + + // Avoid crashing. Note that the warning message might change in the future. + QTest::ignoreMessage(QtWarningMsg, QString::fromAscii("QGraphicsGridLayout::removeAt: invalid index -1").toLatin1().constData()); + l->removeItem(0); + QCOMPARE(l->count(), 4); + + QTest::ignoreMessage(QtWarningMsg, QString::fromAscii("QGraphicsGridLayout::removeAt: invalid index -1").toLatin1().constData()); + l->removeItem(new QGraphicsWidget); + QCOMPARE(l->count(), 4); +} + // public Qt::Alignment rowAlignment(int row) const void tst_QGraphicsGridLayout::rowAlignment() { @@ -2147,10 +2176,50 @@ void tst_QGraphicsGridLayout::alignment2() static QSizeF hfw1(Qt::SizeHint, const QSizeF &constraint) { QSizeF result(constraint); - if (constraint.width() < 0 && constraint.height() < 0) { + const qreal ch = constraint.height(); + const qreal cw = constraint.width(); + if (cw < 0 && ch < 0) { return QSizeF(50, 400); - } else if (constraint.width() >= 0) { - result.setHeight(20000./constraint.width()); + } else if (cw > 0) { + result.setHeight(20000./cw); + } + return result; +} + +static QSizeF wfh1(Qt::SizeHint, const QSizeF &constraint) +{ + QSizeF result(constraint); + const qreal ch = constraint.height(); + const qreal cw = constraint.width(); + if (cw < 0 && ch < 0) { + return QSizeF(400, 50); + } else if (ch > 0) { + result.setWidth(20000./ch); + } + return result; +} + +static QSizeF wfh2(Qt::SizeHint, const QSizeF &constraint) +{ + QSizeF result(constraint); + const qreal ch = constraint.height(); + const qreal cw = constraint.width(); + if (ch < 0 && cw < 0) + return QSizeF(50, 50); + if (ch >= 0) + result.setWidth(ch); + return result; +} + +static QSizeF hfw3(Qt::SizeHint, const QSizeF &constraint) +{ + QSizeF result(constraint); + const qreal ch = constraint.height(); + const qreal cw = constraint.width(); + if (cw < 0 && ch < 0) { + return QSizeF(10, 10); + } else if (cw > 0) { + result.setHeight(100./cw); } return result; } @@ -2185,7 +2254,7 @@ void tst_QGraphicsGridLayout::geometries_data() ); // change layout height and verify - QTest::newRow("hfw-h401") << (ItemList() + QTest::newRow("hfw-100x401") << (ItemList() << ItemDesc(0,0) .minSize(QSizeF(1,1)) .preferredSize(QSizeF(50,10)) @@ -2202,7 +2271,7 @@ void tst_QGraphicsGridLayout::geometries_data() .minSize(QSizeF(40,40)) .preferredSize(QSizeF(50,400)) .maxSize(QSizeF(500, 500)) - .heightForWidth(hfw1) + .dynamicConstraint(hfw1, Qt::Vertical) ) << QSizeF(100, 401) << (RectList() @@ -2211,7 +2280,7 @@ void tst_QGraphicsGridLayout::geometries_data() ); - QTest::newRow("hfw-h408") << (ItemList() + QTest::newRow("hfw-100x408") << (ItemList() << ItemDesc(0,0) .minSize(QSizeF(1,1)) .preferredSize(QSizeF(50,10)) @@ -2228,7 +2297,7 @@ void tst_QGraphicsGridLayout::geometries_data() .minSize(QSizeF(40,40)) .preferredSize(QSizeF(50,400)) .maxSize(QSizeF(500, 500)) - .heightForWidth(hfw1) + .dynamicConstraint(hfw1, Qt::Vertical) ) << QSizeF(100, 408) << (RectList() @@ -2253,7 +2322,7 @@ void tst_QGraphicsGridLayout::geometries_data() .minSize(QSizeF(40,40)) .preferredSize(QSizeF(50,400)) .maxSize(QSizeF(500, 500)) - .heightForWidth(hfw1) + .dynamicConstraint(hfw1, Qt::Vertical) ) << QSizeF(100, 410) << (RectList() @@ -2261,7 +2330,7 @@ void tst_QGraphicsGridLayout::geometries_data() << QRectF(0, 10, 50,100) << QRectF(50, 10, 50,400) ); - QTest::newRow("hfw-h470") << (ItemList() + QTest::newRow("hfw-100x470") << (ItemList() << ItemDesc(0,0) .minSize(QSizeF(1,1)) .preferredSize(QSizeF(50,10)) @@ -2278,7 +2347,7 @@ void tst_QGraphicsGridLayout::geometries_data() .minSize(QSizeF(40,40)) .preferredSize(QSizeF(50,400)) .maxSize(QSizeF(500, 500)) - .heightForWidth(hfw1) + .dynamicConstraint(hfw1, Qt::Vertical) ) << QSizeF(100, 470) << (RectList() @@ -2288,7 +2357,7 @@ void tst_QGraphicsGridLayout::geometries_data() // change layout width and verify - QTest::newRow("hfw-w100") << (ItemList() + QTest::newRow("hfw-100x401") << (ItemList() << ItemDesc(0,0) .minSize(QSizeF(1,1)) .preferredSize(QSizeF(50,10)) @@ -2305,7 +2374,7 @@ void tst_QGraphicsGridLayout::geometries_data() .minSize(QSizeF(40,40)) .preferredSize(QSizeF(50,400)) .maxSize(QSizeF(5000, 5000)) - .heightForWidth(hfw1) + .dynamicConstraint(hfw1, Qt::Vertical) ) << QSizeF(100, 401) << (RectList() @@ -2313,7 +2382,7 @@ void tst_QGraphicsGridLayout::geometries_data() << QRectF( 0, 1, 50, 100) << QRectF( 50, 1, 50, 400) ); - QTest::newRow("hfw-w160") << (ItemList() + QTest::newRow("hfw-160x400") << (ItemList() << ItemDesc(0,0) .minSize(QSizeF(1,1)) .preferredSize(QSizeF(50,10)) @@ -2330,16 +2399,16 @@ void tst_QGraphicsGridLayout::geometries_data() .minSize(QSizeF(40,40)) .preferredSize(QSizeF(50,400)) .maxSize(QSizeF(5000, 5000)) - .heightForWidth(hfw1) + .dynamicConstraint(hfw1, Qt::Vertical) ) - << QSizeF(160, 401) + << QSizeF(160, 400) << (RectList() << QRectF( 0, 0, 80, 100) << QRectF( 80, 0, 80, 100) << QRectF( 0, 100, 80, 100) << QRectF( 80, 100, 80, 250) ); - QTest::newRow("hfw-w500") << (ItemList() + QTest::newRow("hfw-160x300") << (ItemList() << ItemDesc(0,0) .minSize(QSizeF(1,1)) .preferredSize(QSizeF(50,10)) @@ -2356,12 +2425,145 @@ void tst_QGraphicsGridLayout::geometries_data() .minSize(QSizeF(40,40)) .preferredSize(QSizeF(50,400)) .maxSize(QSizeF(5000, 5000)) - .heightForWidth(hfw1) + .dynamicConstraint(hfw1, Qt::Vertical) + ) + << QSizeF(160, 300) + << (RectList() + << QRectF( 0, 0, 80, 50) << QRectF( 80, 0, 80, 50) + << QRectF( 0, 50, 80, 100) << QRectF( 80, 50, 80, 250) + ); + + QTest::newRow("hfw-20x40") << (ItemList() + << ItemDesc(0,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,50)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(0,1) + .minSize(QSizeF(1,10)) + .preferredSize(QSizeF(50,50)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,50)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,1) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,50)) + .maxSize(QSizeF(100, 100)) + .dynamicConstraint(hfw3, Qt::Vertical) + ) + << QSizeF(20, 40) + << (RectList() + << QRectF(0, 0, 10, 20) << QRectF(10, 0, 10, 20) + << QRectF(0, 20, 10, 20) << QRectF(10, 20, 10, 10) + ); + + QTest::newRow("wfh-300x160") << (ItemList() + << ItemDesc(0,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(10,50)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(0,1) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(10,50)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(10,50)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,1) + .minSize(QSizeF(10,10)) + .preferredSize(QSizeF(400,50)) + .maxSize(QSizeF(5000, 5000)) + .dynamicConstraint(wfh1, Qt::Horizontal) + ) + << QSizeF(300, 160) + << (RectList() + << QRectF( 0, 0, 50, 80) << QRectF( 50, 0, 100, 80) + << QRectF( 0, 80, 50, 80) << QRectF( 50, 80, 250, 80) + ); + + QTest::newRow("wfh-40x20") << (ItemList() + << ItemDesc(0,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,50)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(0,1) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,50)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,0) + // Note, must be 10 in order to match stretching of wfh item + // below (the same stretch makes it easier to test) + .minSize(QSizeF(10,1)) + .preferredSize(QSizeF(50,50)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,1) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,50)) + .maxSize(QSizeF(100, 100)) + .dynamicConstraint(wfh2, Qt::Horizontal) + ) + << QSizeF(40, 20) + << (RectList() + << QRectF(0, 0, 20, 10) << QRectF(20, 0, 20, 10) + << QRectF(0, 10, 20, 10) << QRectF(20, 10, 10, 10) + ); + + QTest::newRow("wfh-400x160") << (ItemList() + << ItemDesc(0,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,50)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(0,1) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,50)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,50)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,1) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(50,50)) + .maxSize(QSizeF(100, 100)) + .dynamicConstraint(wfh2, Qt::Horizontal) + ) + + << QSizeF(400, 160) + << (RectList() + << QRectF(0, 0, 100, 80) << QRectF(100, 0, 100, 80) + << QRectF(0, 80, 100, 80) << QRectF(100, 80, 80, 80) + ); + + QTest::newRow("wfh-160x100") << (ItemList() + << ItemDesc(0,0) + .minSize(QSizeF(1,1)) + // Note, preferred width must be 50 in order to match + // preferred width of wfh item below. + // (The same preferred size makes the stretch the same, and + // makes it easier to test) (The stretch algorithm is a + // blackbox) + .preferredSize(QSizeF(50,50)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(0,1) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(10,50)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,0) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(10,50)) + .maxSize(QSizeF(100, 100)) + << ItemDesc(1,1) + .minSize(QSizeF(1,1)) + .preferredSize(QSizeF(10,50)) + .maxSize(QSizeF(500, 500)) + .dynamicConstraint(wfh2, Qt::Horizontal) ) - << QSizeF(500, 401) + << QSizeF(160, 100) << (RectList() - << QRectF( 0, 0, 100, 100) << QRectF(100, 0, 100, 100) - << QRectF( 0, 100, 100, 100) << QRectF(100, 100, 400, 50) + << QRectF(0, 0, 80, 50) << QRectF( 80, 0, 80, 50) + << QRectF(0, 50, 80, 50) << QRectF( 80, 50, 50, 50) ); } @@ -2434,14 +2636,6 @@ void tst_QGraphicsGridLayout::task236367_maxSizeHint() QCOMPARE(widget->size(), QSizeF(w, h)); } -/* -static qreal hfw(qreal w) -{ - if (w == 0) - return 20000; - return 20000/w; -} -*/ static QSizeF hfw(Qt::SizeHint /*which*/, const QSizeF &constraint) { QSizeF result(constraint); @@ -2458,7 +2652,16 @@ static QSizeF hfw(Qt::SizeHint /*which*/, const QSizeF &constraint) } else if (ch == 0) { result.setWidth(20000); } + return result; +} +static QSizeF wfh(Qt::SizeHint /*which*/, const QSizeF &constraint) +{ + QSizeF result(constraint); + const qreal ch = constraint.height(); + if (ch >= 0) { + result.setWidth(ch); + } return result; } @@ -2509,24 +2712,25 @@ void tst_QGraphicsGridLayout::heightForWidth() layout->setSpacing(0); RectWidget *w00 = new RectWidget; w00->setSizeHint(Qt::MinimumSize, QSizeF(1,1)); - w00->setSizeHint(Qt::PreferredSize, QSizeF(10,10)); + w00->setSizeHint(Qt::PreferredSize, QSizeF(50,50)); w00->setSizeHint(Qt::MaximumSize, QSizeF(100,100)); layout->addItem(w00, 0, 0); RectWidget *w01 = new RectWidget; w01->setSizeHint(Qt::MinimumSize, QSizeF(1,1)); - w01->setSizeHint(Qt::PreferredSize, QSizeF(10,10)); + w01->setSizeHint(Qt::PreferredSize, QSizeF(50,50)); w01->setSizeHint(Qt::MaximumSize, QSizeF(100,100)); layout->addItem(w01, 0, 1); RectWidget *w10 = new RectWidget; w10->setSizeHint(Qt::MinimumSize, QSizeF(1,1)); - w10->setSizeHint(Qt::PreferredSize, QSizeF(10,10)); + w10->setSizeHint(Qt::PreferredSize, QSizeF(50,50)); w10->setSizeHint(Qt::MaximumSize, QSizeF(100,100)); layout->addItem(w10, 1, 0); RectWidget *w11 = new RectWidget; w11->setSizeHint(Qt::MinimumSize, QSizeF(1,1)); + w11->setSizeHint(Qt::PreferredSize, QSizeF(50,400)); w11->setSizeHint(Qt::MaximumSize, QSizeF(30000,30000)); w11->setConstraintFunction(hfw); QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred); @@ -2535,42 +2739,104 @@ void tst_QGraphicsGridLayout::heightForWidth() layout->addItem(w11, 1, 1); QSizeF prefSize = layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, -1)); - QCOMPARE(prefSize, QSizeF(10+200, 10+100)); + QCOMPARE(prefSize, QSizeF(50+50, 50+400)); QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(2, -1)), QSizeF(2, 20001)); - QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(2, -1)), QSizeF(2, 20010)); + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(2, -1)), QSizeF(2, 20050)); QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(2, -1)), QSizeF(2, 20100)); - qreal width1; - qreal width2; - expectedWidth(1, 10, 1, 200, 20, &width1, &width2); - QSizeF expectedSize = hfw(Qt::MinimumSize, QSizeF(width2, -1)) + QSizeF(width1, 1); - QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(20, -1)), expectedSize); - expectedSize.rheight()+=9; - QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(20, -1)), expectedSize); - expectedSize.rheight()+=90; - QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(20, -1)), expectedSize); - - expectedWidth(1, 10, 1, 200, 300, &width1, &width2); - expectedSize = hfw(Qt::MinimumSize, QSizeF(width2, -1)) + QSizeF(width1, 1); - QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(300, -1)), expectedSize); - expectedSize.rheight()+=9; - QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(300, -1)), expectedSize); - // the height of the hfw widget is shorter than the one to the left, which is 100, so - // the total height of the last row is 100 (which leaves the layout height to be 200) - QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(300, -1)), QSizeF(300, 200)); - - // the hfw item is shorter than the item to the left - expectedWidth(1, 10, 1, 200, 500, &width1, &width2); - expectedSize = hfw(Qt::MinimumSize, QSizeF(width2, -1)) + QSizeF(width1, 1); - QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(500, -1)), expectedSize); - expectedSize.rheight()+=9; - QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(500, -1)), expectedSize); + + QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(20, -1)), QSizeF(20, 1 + 2000)); + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(20, -1)), QSizeF(20, 50 + 2000)); + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(20, -1)), QSizeF(20, 100 + 2000)); + + QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(300, -1)), QSizeF(300, 1 + 100)); + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(300, -1)), QSizeF(300, 50 + 100)); + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(300, -1)), QSizeF(300, 100 + 100)); + // the height of the hfw widget is shorter than the one to the left, which is 100, so // the total height of the last row is 100 (which leaves the layout height to be 200) - QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(500, -1)), QSizeF(500, 200)); + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(500, -1)), QSizeF(500, 100 + 100)); + + // hfw item size: (500, 40) -> preferred size is maxed up to preferred size of item w10 (50) + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(600, -1)), QSizeF(600, 50 + 50)); } +void tst_QGraphicsGridLayout::widthForHeight() +{ + QGraphicsWidget *widget = new QGraphicsWidget; + QGraphicsGridLayout *layout = new QGraphicsGridLayout; + widget->setLayout(layout); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + RectWidget *w00 = new RectWidget; + w00->setMinimumSize(1, 1); + w00->setPreferredSize(50, 50); + w00->setMaximumSize(100, 100); + + layout->addItem(w00, 0, 0); + + RectWidget *w01 = new RectWidget; + w01->setMinimumSize(1,1); + w01->setPreferredSize(50,50); + w01->setMaximumSize(100,100); + layout->addItem(w01, 0, 1); + + RectWidget *w10 = new RectWidget; + w10->setMinimumSize(1,1); + w10->setPreferredSize(50,50); + w10->setMaximumSize(100,100); + layout->addItem(w10, 1, 0); + + RectWidget *w11 = new RectWidget; + w11->setMinimumSize(1,1); + w11->setPreferredSize(50, 50); + w11->setMaximumSize(30000,30000); + // This will make sure its always square. + w11->setConstraintFunction(wfh); + QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred); + sp.setWidthForHeight(true); + w11->setSizePolicy(sp); + layout->addItem(w11, 1, 1); + + /* + | 1, 50, 100 | 1, 50, 100 | + -----+--------------+--------------+ + 1| | | + 50| | | + 100| | | + -----|--------------+--------------+ + 1| | | + 50| | WFH | + 100| | | + -----------------------------------+ + */ + + + QSizeF prefSize = layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, -1)); + QCOMPARE(prefSize, QSizeF(50+50, 50+50)); + + // wfh(1): = 1 + QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, 2)), QSizeF(1 + 1, 2)); + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, 2)), QSizeF(50 + 50, 2)); + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, 2)), QSizeF(100 + 100, 2)); + + // wfh(40) = 40 + QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, 80)), QSizeF(1 + 40, 80)); + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, 80)), QSizeF(50 + 50, 80)); + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, 80)), QSizeF(100 + 100, 80)); + + // wfh(80) = 80 + QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, 160)), QSizeF(1 + 80, 160)); + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, 160)), QSizeF(50 + 80, 160)); + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, 160)), QSizeF(100 + 100, 160)); + + // wfh(200) = 200 + QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, 300)), QSizeF(1 + 200, 300)); + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, 300)), QSizeF(50 + 200, 300)); + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, 300)), QSizeF(100 + 200, 300)); + +} QTEST_MAIN(tst_QGraphicsGridLayout) #include "tst_qgraphicsgridlayout.moc" diff --git a/tests/auto/qgraphicsitemanimation/qgraphicsitemanimation.pro b/tests/auto/qgraphicsitemanimation/qgraphicsitemanimation.pro index 6be3bfe..01875c7 100644 --- a/tests/auto/qgraphicsitemanimation/qgraphicsitemanimation.pro +++ b/tests/auto/qgraphicsitemanimation/qgraphicsitemanimation.pro @@ -1,5 +1,5 @@ load(qttest_p4) SOURCES += tst_qgraphicsitemanimation.cpp DEFINES += QT_NO_CAST_TO_ASCII - +CONFIG += parallel_test diff --git a/tests/auto/qgraphicslayout/qgraphicslayout.pro b/tests/auto/qgraphicslayout/qgraphicslayout.pro index 1dc916a..eafd213 100644 --- a/tests/auto/qgraphicslayout/qgraphicslayout.pro +++ b/tests/auto/qgraphicslayout/qgraphicslayout.pro @@ -5,4 +5,4 @@ load(qttest_p4) SOURCES += tst_qgraphicslayout.cpp DEFINES += QT_USE_USING_NAMESPACE - +CONFIG += parallel_test diff --git a/tests/auto/qgraphicslayoutitem/qgraphicslayoutitem.pro b/tests/auto/qgraphicslayoutitem/qgraphicslayoutitem.pro index 6c8bf0c..816224b 100644 --- a/tests/auto/qgraphicslayoutitem/qgraphicslayoutitem.pro +++ b/tests/auto/qgraphicslayoutitem/qgraphicslayoutitem.pro @@ -1,4 +1,4 @@ load(qttest_p4) SOURCES += tst_qgraphicslayoutitem.cpp - +CONFIG += parallel_test diff --git a/tests/auto/qgraphicslinearlayout/qgraphicslinearlayout.pro b/tests/auto/qgraphicslinearlayout/qgraphicslinearlayout.pro index 114e5e9..df5a827 100644 --- a/tests/auto/qgraphicslinearlayout/qgraphicslinearlayout.pro +++ b/tests/auto/qgraphicslinearlayout/qgraphicslinearlayout.pro @@ -1,4 +1,4 @@ load(qttest_p4) SOURCES += tst_qgraphicslinearlayout.cpp - +CONFIG += parallel_test diff --git a/tests/auto/qgraphicsobject/qgraphicsobject.pro b/tests/auto/qgraphicsobject/qgraphicsobject.pro index 965b319..2418845 100644 --- a/tests/auto/qgraphicsobject/qgraphicsobject.pro +++ b/tests/auto/qgraphicsobject/qgraphicsobject.pro @@ -1,2 +1,3 @@ load(qttest_p4) SOURCES += tst_qgraphicsobject.cpp +CONFIG += parallel_test
\ No newline at end of file diff --git a/tests/auto/qgraphicspixmapitem/qgraphicspixmapitem.pro b/tests/auto/qgraphicspixmapitem/qgraphicspixmapitem.pro index f6d6c8f..6b4db95 100644 --- a/tests/auto/qgraphicspixmapitem/qgraphicspixmapitem.pro +++ b/tests/auto/qgraphicspixmapitem/qgraphicspixmapitem.pro @@ -1,4 +1,4 @@ load(qttest_p4) SOURCES += tst_qgraphicspixmapitem.cpp - +CONFIG += parallel_test diff --git a/tests/auto/qgraphicspolygonitem/qgraphicspolygonitem.pro b/tests/auto/qgraphicspolygonitem/qgraphicspolygonitem.pro index d54b78b..4da949b 100644 --- a/tests/auto/qgraphicspolygonitem/qgraphicspolygonitem.pro +++ b/tests/auto/qgraphicspolygonitem/qgraphicspolygonitem.pro @@ -1,4 +1,4 @@ load(qttest_p4) SOURCES += tst_qgraphicspolygonitem.cpp - +CONFIG += parallel_test diff --git a/tests/auto/qgraphicssceneindex/qgraphicssceneindex.pro b/tests/auto/qgraphicssceneindex/qgraphicssceneindex.pro index d1bf3cc..1fdd176 100644 --- a/tests/auto/qgraphicssceneindex/qgraphicssceneindex.pro +++ b/tests/auto/qgraphicssceneindex/qgraphicssceneindex.pro @@ -1,4 +1,4 @@ load(qttest_p4) requires(contains(QT_CONFIG,private_tests)) SOURCES += tst_qgraphicssceneindex.cpp - +CONFIG += parallel_test diff --git a/tests/auto/qgraphicstransform/qgraphicstransform.pro b/tests/auto/qgraphicstransform/qgraphicstransform.pro index 709cff6..67c939e 100644 --- a/tests/auto/qgraphicstransform/qgraphicstransform.pro +++ b/tests/auto/qgraphicstransform/qgraphicstransform.pro @@ -1,2 +1,3 @@ load(qttest_p4) SOURCES += tst_qgraphicstransform.cpp +CONFIG += parallel_test diff --git a/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp index 89f608e..188ed29 100644 --- a/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp +++ b/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp @@ -110,6 +110,8 @@ private Q_SLOTS: void getEmptyWithPipelining(); + void getAndEverythingShouldBePipelined(); + void getAndThenDeleteObject(); void getAndThenDeleteObject_data(); }; @@ -1036,6 +1038,52 @@ void tst_QHttpNetworkConnection::getEmptyWithPipelining() qDeleteAll(replies); } +class GetAndEverythingShouldBePipelinedReceiver : public QObject +{ + Q_OBJECT +public: + int receivedCount; + int requestCount; + GetAndEverythingShouldBePipelinedReceiver(int rq) : receivedCount(0),requestCount(rq) { } +public Q_SLOTS: + void finishedSlot() { + QHttpNetworkReply *reply = (QHttpNetworkReply*) sender(); + receivedCount++; + + if (receivedCount == requestCount) + QTestEventLoop::instance().exitLoop(); + } +}; + +void tst_QHttpNetworkConnection::getAndEverythingShouldBePipelined() +{ + quint16 requestCount = 100; + // use 1 connection. + QHttpNetworkConnection connection(1, QtNetworkSettings::serverName()); + QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"); + QList<QHttpNetworkRequest*> requests; + QList<QHttpNetworkReply*> replies; + + GetAndEverythingShouldBePipelinedReceiver receiver(requestCount); + + for (int i = 0; i < requestCount; i++) { + QHttpNetworkRequest *request = 0; + request = new QHttpNetworkRequest(url, QHttpNetworkRequest::Get); + request->setPipeliningAllowed(true); + requests.append(request); + QHttpNetworkReply *reply = connection.sendRequest(*request); + connect(reply, SIGNAL(finished()), &receiver, SLOT(finishedSlot())); + replies.append(reply); + } + QTestEventLoop::instance().enterLoop(40); + QVERIFY(!QTestEventLoop::instance().timeout()); + + qDeleteAll(requests); + qDeleteAll(replies); + +} + + void tst_QHttpNetworkConnection::getAndThenDeleteObject_data() { QTest::addColumn<bool>("replyFirst"); diff --git a/tests/auto/qimage/tst_qimage.cpp b/tests/auto/qimage/tst_qimage.cpp index b446941..6b8028c 100644 --- a/tests/auto/qimage/tst_qimage.cpp +++ b/tests/auto/qimage/tst_qimage.cpp @@ -59,6 +59,7 @@ #endif Q_DECLARE_METATYPE(QImage::Format) +Q_DECLARE_METATYPE(Qt::GlobalColor) class tst_QImage : public QObject { @@ -140,6 +141,11 @@ private slots: void compareIndexed(); + void fillColor_data(); + void fillColor(); + + void fillColorWithAlpha(); + void rgbSwapped_data(); void rgbSwapped(); }; @@ -1823,6 +1829,112 @@ void tst_QImage::compareIndexed() QCOMPARE(img, imgInverted); } +void tst_QImage::fillColor_data() +{ + QTest::addColumn<QImage::Format>("format"); + QTest::addColumn<Qt::GlobalColor>("color"); + QTest::addColumn<uint>("pixelValue"); + + QTest::newRow("Mono, color0") << QImage::Format_Mono << Qt::color0 << 0u; + QTest::newRow("Mono, color1") << QImage::Format_Mono << Qt::color1 << 1u; + + QTest::newRow("MonoLSB, color0") << QImage::Format_MonoLSB << Qt::color0 << 0u; + QTest::newRow("MonoLSB, color1") << QImage::Format_MonoLSB << Qt::color1 << 1u; + + const char *names[] = { + "Indexed8", + "RGB32", + "ARGB32", + "ARGB32pm", + "RGB16", + "ARGB8565pm", + "RGB666", + "ARGB6666pm", + "RGB555", + "ARGB8555pm", + "RGB888", + "RGB444", + "ARGB4444pm", + 0 + }; + + QImage::Format formats[] = { + QImage::Format_Indexed8, + QImage::Format_RGB32, + QImage::Format_ARGB32, + QImage::Format_ARGB32_Premultiplied, + QImage::Format_RGB16, + QImage::Format_ARGB8565_Premultiplied, + QImage::Format_RGB666, + QImage::Format_ARGB6666_Premultiplied, + QImage::Format_RGB555, + QImage::Format_ARGB8555_Premultiplied, + QImage::Format_RGB888, + QImage::Format_RGB444, + QImage::Format_ARGB4444_Premultiplied + }; + + for (int i=0; names[i] != 0; ++i) { + QByteArray name; + name.append(names[i]).append(", "); + + QTest::newRow(QByteArray(name).append("black").constData()) << formats[i] << Qt::black << 0xff000000; + QTest::newRow(QByteArray(name).append("white").constData()) << formats[i] << Qt::white << 0xffffffff; + QTest::newRow(QByteArray(name).append("red").constData()) << formats[i] << Qt::red << 0xffff0000; + QTest::newRow(QByteArray(name).append("green").constData()) << formats[i] << Qt::green << 0xff00ff00; + QTest::newRow(QByteArray(name).append("blue").constData()) << formats[i] << Qt::blue << 0xff0000ff; + } + + QTest::newRow("RGB16, transparent") << QImage::Format_RGB16 << Qt::transparent << 0xff000000; + QTest::newRow("RGB32, transparent") << QImage::Format_RGB32 << Qt::transparent << 0xff000000; + QTest::newRow("ARGB32, transparent") << QImage::Format_ARGB32 << Qt::transparent << 0x00000000u; + QTest::newRow("ARGB32pm, transparent") << QImage::Format_ARGB32_Premultiplied << Qt::transparent << 0x00000000u; +} + +void tst_QImage::fillColor() +{ + QFETCH(QImage::Format, format); + QFETCH(Qt::GlobalColor, color); + QFETCH(uint, pixelValue); + + QImage image(1, 1, format); + + if (image.depth() == 8) { + QVector<QRgb> table; + table << 0xff000000; + table << 0xffffffff; + table << 0xffff0000; + table << 0xff00ff00; + table << 0xff0000ff; + image.setColorTable(table); + } + + image.fill(color); + if (image.depth() == 1) { + QCOMPARE(image.pixelIndex(0, 0), (int) pixelValue); + } else { + QCOMPARE(image.pixel(0, 0), pixelValue); + } + + image.fill(QColor(color)); + if (image.depth() == 1) { + QCOMPARE(image.pixelIndex(0, 0), (int) pixelValue); + } else { + QCOMPARE(image.pixel(0, 0), pixelValue); + } +} + +void tst_QImage::fillColorWithAlpha() +{ + QImage argb32(1, 1, QImage::Format_ARGB32); + argb32.fill(QColor(255, 0, 0, 127)); + QCOMPARE(argb32.pixel(0, 0), qRgba(255, 0, 0, 127)); + + QImage argb32pm(1, 1, QImage::Format_ARGB32_Premultiplied); + argb32pm.fill(QColor(255, 0, 0, 127)); + QCOMPARE(argb32pm.pixel(0, 0), 0x7f7f0000u); +} + void tst_QImage::rgbSwapped_data() { QTest::addColumn<QImage::Format>("format"); diff --git a/tests/auto/qiodevice/tst_qiodevice.cpp b/tests/auto/qiodevice/tst_qiodevice.cpp index 7048754..0226402 100644 --- a/tests/auto/qiodevice/tst_qiodevice.cpp +++ b/tests/auto/qiodevice/tst_qiodevice.cpp @@ -81,6 +81,8 @@ private slots: void readLine2_data(); void readLine2(); + + void peekBug(); }; // Testing get/set functions @@ -591,5 +593,62 @@ void tst_QIODevice::readLine2() } } + +class PeekBug : public QIODevice { + Q_OBJECT +public: + char alphabet[27]; + qint64 counter; + PeekBug() : QIODevice(), counter(0) { + memcpy(alphabet,"abcdefghijklmnopqrstuvqxyz",27); + }; + qint64 readData(char *data, qint64 maxlen) { + qint64 pos = 0; + while (pos < maxlen) { + *(data + pos) = alphabet[counter]; + pos++; + counter++; + if (counter == 26) + counter = 0; + } + return maxlen; + } + qint64 writeData(const char *data, qint64 maxlen) { + return -1; + } + +}; + +// This is a testcase for the bug fixed with bd287865 +void tst_QIODevice::peekBug() +{ + PeekBug peekBug; + peekBug.open(QIODevice::ReadOnly | QIODevice::Unbuffered); + + char onetwo[2]; + peekBug.peek(onetwo, 2); + QCOMPARE(onetwo[0], 'a'); + QCOMPARE(onetwo[1], 'b'); + + peekBug.read(onetwo, 1); + QCOMPARE(onetwo[0], 'a'); + + peekBug.peek(onetwo, 2); + QCOMPARE(onetwo[0], 'b'); + QCOMPARE(onetwo[1], 'c'); + + peekBug.read(onetwo, 1); + QCOMPARE(onetwo[0], 'b'); + peekBug.read(onetwo, 1); + QCOMPARE(onetwo[0], 'c'); + peekBug.read(onetwo, 1); + QCOMPARE(onetwo[0], 'd'); + + peekBug.peek(onetwo, 2); + QCOMPARE(onetwo[0], 'e'); + QCOMPARE(onetwo[1], 'f'); + +} + QTEST_MAIN(tst_QIODevice) #include "tst_qiodevice.moc" diff --git a/tests/auto/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/qitemdelegate/tst_qitemdelegate.cpp index 2a378fe..97a9b82 100644 --- a/tests/auto/qitemdelegate/tst_qitemdelegate.cpp +++ b/tests/auto/qitemdelegate/tst_qitemdelegate.cpp @@ -235,6 +235,7 @@ private slots: void enterKey(); void task257859_finalizeEdit(); + void QTBUG4435_keepSelectionOnCheck(); }; @@ -1168,6 +1169,31 @@ void tst_QItemDelegate::task257859_finalizeEdit() QTRY_VERIFY(!editor); } +void tst_QItemDelegate::QTBUG4435_keepSelectionOnCheck() +{ + QStandardItemModel model(3, 1); + for (int i = 0; i < 3; ++i) { + QStandardItem *item = new QStandardItem(QLatin1String("Item ") + QString::number(i)); + item->setCheckable(true); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + model.setItem(i, item); + } + QTableView view; + view.setModel(&model); + view.setItemDelegate(new TestItemDelegate); + view.show(); + view.selectAll(); + QTest::qWaitForWindowShown(&view); + QStyleOptionViewItem option; + option.rect = view.visualRect(model.index(0, 0)); + const int checkMargin = qApp->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1; + QPoint pos = qApp->style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &option, 0).center() + + QPoint(checkMargin, 0); + QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, pos); + QTRY_VERIFY(view.selectionModel()->isColumnSelected(0, QModelIndex())); + QCOMPARE(model.item(0)->checkState(), Qt::Checked); +} + // ### _not_ covered: diff --git a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp b/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp index 3b2a716..69b1390 100644 --- a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp +++ b/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp @@ -94,6 +94,11 @@ private slots: void task260134_layoutChangedWithAllSelected(); void QTBUG5671_layoutChangedWithAllSelected(); void QTBUG2804_layoutChangedTreeSelection(); + void deselectRemovedMiddleRange(); + void rangeOperatorLessThan_data(); + void rangeOperatorLessThan(); + + void testDifferentModels(); private: QAbstractItemModel *model; @@ -2353,6 +2358,236 @@ void tst_QItemSelectionModel::QTBUG2804_layoutChangedTreeSelection() QCOMPARE(selModel.selectedIndexes().count(), 4); } +class RemovalObserver : public QObject +{ + Q_OBJECT + QItemSelectionModel *m_itemSelectionModel; +public: + RemovalObserver(QItemSelectionModel *selectionModel) + : m_itemSelectionModel(selectionModel) + { + connect(m_itemSelectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(selectionChanged(QItemSelection, QItemSelection))); + } + +public slots: + void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) + { + foreach(const QModelIndex &index, deselected.indexes()) { + QVERIFY(!m_itemSelectionModel->selection().contains(index)); + } + QVERIFY(m_itemSelectionModel->selection().size() == 2); + } + +}; + +void tst_QItemSelectionModel::deselectRemovedMiddleRange() +{ + QStandardItemModel model(8, 0); + + for (int row = 0; row < 8; ++row) { + static const int column = 0; + QStandardItem *item = new QStandardItem(QString::number(row)); + model.setItem(row, column, item); + } + + QItemSelectionModel selModel(&model); + + selModel.select(QItemSelection(model.index(3, 0), model.index(6, 0)), QItemSelectionModel::Select); + + QVERIFY(selModel.selection().size() == 1); + + RemovalObserver ro(&selModel); + + QSignalSpy spy(&selModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection))); + bool ok = model.removeRows(4, 2); + + QVERIFY(ok); + QVERIFY(spy.size() == 1); +} + +static QStandardItemModel* getModel(QObject *parent) +{ + QStandardItemModel *model = new QStandardItemModel(parent); + + for (int i = 0; i < 4; ++i) { + QStandardItem *parentItem = model->invisibleRootItem(); + QList<QStandardItem*> list; + for (int j = 0; j < 4; ++j) { + list.append(new QStandardItem(QString("item %1, %2").arg(i).arg(j))); + } + parentItem->appendRow(list); + parentItem = list.first(); + for (int j = 0; j < 4; ++j) { + QList<QStandardItem*> list; + for (int k = 0; k < 4; ++k) { + list.append(new QStandardItem(QString("item %1, %2").arg(i).arg(j))); + } + parentItem->appendRow(list); + } + } + return model; +} + +enum Result { + LessThan, + NotLessThan, + NotEqual +}; + +Q_DECLARE_METATYPE(Result); + +void tst_QItemSelectionModel::rangeOperatorLessThan_data() +{ + QTest::addColumn<int>("parent1"); + QTest::addColumn<int>("top1"); + QTest::addColumn<int>("left1"); + QTest::addColumn<int>("bottom1"); + QTest::addColumn<int>("right1"); + QTest::addColumn<int>("parent2"); + QTest::addColumn<int>("top2"); + QTest::addColumn<int>("left2"); + QTest::addColumn<int>("bottom2"); + QTest::addColumn<int>("right2"); + QTest::addColumn<Result>("result"); + + QTest::newRow("lt01") << -1 << 0 << 0 << 3 << 3 + << -1 << 0 << 0 << 3 << 3 << NotLessThan; + + QTest::newRow("lt02") << -1 << 0 << 0 << 2 << 3 + << -1 << 0 << 0 << 3 << 3 << LessThan; + QTest::newRow("lt03") << -1 << 0 << 0 << 3 << 2 + << -1 << 0 << 0 << 3 << 3 << LessThan; + QTest::newRow("lt04") << -1 << 0 << 0 << 2 << 2 + << -1 << 0 << 0 << 3 << 3 << LessThan; + + QTest::newRow("lt05") << -1 << 0 << 0 << 3 << 3 + << -1 << 0 << 0 << 2 << 3 << NotLessThan; + QTest::newRow("lt06") << -1 << 0 << 0 << 3 << 3 + << -1 << 0 << 0 << 3 << 2 << NotLessThan; + QTest::newRow("lt07") << -1 << 0 << 0 << 3 << 3 + << -1 << 0 << 0 << 2 << 2 << NotLessThan; + + QTest::newRow("lt08") << -1 << 0 << 0 << 3 << 3 + << 0 << 0 << 0 << 3 << 3 << NotEqual; + QTest::newRow("lt09") << 1 << 0 << 0 << 3 << 3 + << 0 << 0 << 0 << 3 << 3 << NotEqual; + QTest::newRow("lt10") << 1 << 0 << 0 << 1 << 1 + << 0 << 2 << 2 << 3 << 3 << NotEqual; + QTest::newRow("lt11") << 1 << 2 << 2 << 3 << 3 + << 0 << 0 << 0 << 1 << 1 << NotEqual; + + QTest::newRow("lt12") << -1 << 0 << 0 << 1 << 1 + << -1 << 2 << 2 << 3 << 3 << LessThan; + QTest::newRow("lt13") << -1 << 2 << 2 << 3 << 3 + << -1 << 0 << 0 << 1 << 1 << NotLessThan; + QTest::newRow("lt14") << 1 << 0 << 0 << 1 << 1 + << 1 << 2 << 2 << 3 << 3 << LessThan; + QTest::newRow("lt15") << 1 << 2 << 2 << 3 << 3 + << 1 << 0 << 0 << 1 << 1 << NotLessThan; + + QTest::newRow("lt16") << -1 << 0 << 0 << 2 << 2 + << -1 << 1 << 1 << 3 << 3 << LessThan; + QTest::newRow("lt17") << -1 << 1 << 1 << 3 << 3 + << -1 << 0 << 0 << 2 << 2 << NotLessThan; + QTest::newRow("lt18") << 1 << 0 << 0 << 2 << 2 + << 1 << 1 << 1 << 3 << 3 << LessThan; + QTest::newRow("lt19") << 1 << 1 << 1 << 3 << 3 + << 1 << 0 << 0 << 2 << 2 << NotLessThan; +} + +void tst_QItemSelectionModel::rangeOperatorLessThan() +{ + QStandardItemModel *model1 = getModel(this); + QStandardItemModel *model2 = getModel(this); + + QFETCH(int, parent1); + QFETCH(int, top1); + QFETCH(int, left1); + QFETCH(int, bottom1); + QFETCH(int, right1); + QFETCH(int, parent2); + QFETCH(int, top2); + QFETCH(int, left2); + QFETCH(int, bottom2); + QFETCH(int, right2); + QFETCH(Result, result); + + QModelIndex p1 = model1->index(parent1, 0); + + QModelIndex tl1 = model1->index(top1, left1, p1); + QModelIndex br1 = model1->index(bottom1, right1, p1); + + QItemSelectionRange r1(tl1, br1); + + QModelIndex p2 = model1->index(parent2, 0); + + QModelIndex tl2 = model1->index(top2, left2, p2); + QModelIndex br2 = model1->index(bottom2, right2, p2); + + QItemSelectionRange r2(tl2, br2); + + if (result == LessThan) + QVERIFY(r1 < r2); + else if (result == NotLessThan) + QVERIFY(!(r1 < r2)); + else if (result == NotEqual) + if (!(r1 < r2)) + QVERIFY(r2 < r1); + + // Ranges in different models are always non-equal + + QModelIndex p3 = model2->index(parent1, 0); + + QModelIndex tl3 = model2->index(top1, left1, p3); + QModelIndex br3 = model2->index(bottom1, right1, p3); + + QItemSelectionRange r3(tl3, br3); + + if (!(r1 < r3)) + QVERIFY(r3 < r1); + + if (!(r2 < r3)) + QVERIFY(r3 < r2); + + QModelIndex p4 = model2->index(parent2, 0); + + QModelIndex tl4 = model2->index(top2, left2, p4); + QModelIndex br4 = model2->index(bottom2, right2, p4); + + QItemSelectionRange r4(tl4, br4); + + if (!(r1 < r4)) + QVERIFY(r4 < r1); + + if (!(r2 < r4)) + QVERIFY(r4 < r2); +} + +void tst_QItemSelectionModel::testDifferentModels() +{ + QStandardItemModel model1; + QStandardItemModel model2; + QStandardItem top11("Child1"), top12("Child2"), top13("Child3"); + QStandardItem top21("Child1"), top22("Child2"), top23("Child3"); + + model1.appendColumn(QList<QStandardItem*>() << &top11 << &top12 << &top13); + model2.appendColumn(QList<QStandardItem*>() << &top21 << &top22 << &top23); + + + QModelIndex topIndex1 = model1.index(0, 0); + QModelIndex bottomIndex1 = model1.index(2, 0); + QModelIndex topIndex2 = model2.index(0, 0); + + QItemSelectionRange range(topIndex1, bottomIndex1); + + QVERIFY(range.intersects(QItemSelectionRange(topIndex1, topIndex1))); + QVERIFY(!range.intersects(QItemSelectionRange(topIndex2, topIndex2))); + + QItemSelection newSelection; + QItemSelection::split(range, QItemSelectionRange(topIndex2, topIndex2), &newSelection); + + QVERIFY(newSelection.isEmpty()); +} QTEST_MAIN(tst_QItemSelectionModel) #include "tst_qitemselectionmodel.moc" diff --git a/tests/auto/qlibrary/tst_qlibrary.cpp b/tests/auto/qlibrary/tst_qlibrary.cpp index d4884db..99e6de3 100644 --- a/tests/auto/qlibrary/tst_qlibrary.cpp +++ b/tests/auto/qlibrary/tst_qlibrary.cpp @@ -53,6 +53,7 @@ #define a_VALID false #define so_VALID false #define dll_VALID false +#define DLL_VALID false #if defined(Q_OS_DARWIN) # undef bundle_VALID @@ -88,6 +89,8 @@ #elif defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) # undef dll_VALID # define dll_VALID true +# undef DLL_VALID +# define DLL_VALID true # define SUFFIX ".dll" # define PREFIX "" @@ -200,6 +203,7 @@ void tst_QLibrary::version() VersionFunction fnVersion = (VersionFunction)library.resolve("mylibversion"); QVERIFY(fnVersion); QCOMPARE(fnVersion(), resultversion); + QVERIFY(library.unload()); #else Q_UNUSED(lib); Q_UNUSED(loadversion); @@ -246,6 +250,7 @@ void tst_QLibrary::load() bool ok = library.load(); if ( result ) { QVERIFY( ok ); + QVERIFY(library.unload()); } else { QVERIFY( !ok ); } @@ -335,6 +340,7 @@ void tst_QLibrary::resolve() } else { QVERIFY( func == 0 ); } + library.unload(); } void tst_QLibrary::library_data() @@ -352,6 +358,7 @@ void tst_QLibrary::isLibrary_data() QTest::newRow(".a") << QString("mylib.a") << a_VALID; QTest::newRow(".bundle") << QString("mylib.bundle") << bundle_VALID; QTest::newRow(".dll") << QString("mylib.dll") << dll_VALID; + QTest::newRow(".DLL") << QString("MYLIB.DLL") << DLL_VALID; QTest::newRow(".dl2" ) << QString("mylib.dl2") << false; QTest::newRow(".dylib") << QString("mylib.dylib") << dylib_VALID; QTest::newRow(".sl") << QString("mylib.sl") << sl_VALID; @@ -465,7 +472,9 @@ void tst_QLibrary::errorString() break; } QRegExp re(errorString); - QVERIFY2(re.exactMatch(lib.errorString()), qPrintable(lib.errorString())); + QString libErrorString = lib.errorString(); + QVERIFY(!lib.isLoaded() || lib.unload()); + QVERIFY2(re.exactMatch(libErrorString), qPrintable(libErrorString)); QCOMPARE(ok, success); } @@ -521,6 +530,7 @@ void tst_QLibrary::loadHints() bool ok = library.load(); if ( result ) { QVERIFY( ok ); + QVERIFY(library.unload()); } else { QVERIFY( !ok ); } @@ -556,7 +566,12 @@ void tst_QLibrary::fileName() } QVERIFY(ok); +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + QCOMPARE(lib.fileName().toLower(), expectedFilename.toLower()); +#else QCOMPARE(lib.fileName(), expectedFilename); +#endif + QVERIFY(lib.unload()); } @@ -568,29 +583,42 @@ void tst_QLibrary::multipleInstancesForOneLibrary() QString lib = QDir::currentPath() + "/mylib"; #endif - QLibrary lib1(lib); - QLibrary lib2(lib); - QCOMPARE(lib1.isLoaded(), false); - QCOMPARE(lib2.isLoaded(), false); - lib1.load(); - QCOMPARE(lib1.isLoaded(), true); - QCOMPARE(lib2.isLoaded(), true); - QCOMPARE(lib1.unload(), true); - QCOMPARE(lib1.isLoaded(), false); - QCOMPARE(lib2.isLoaded(), false); - lib1.load(); - lib2.load(); - QCOMPARE(lib1.isLoaded(), true); - QCOMPARE(lib2.isLoaded(), true); - QCOMPARE(lib1.unload(), false); - QCOMPARE(lib1.isLoaded(), true); - QCOMPARE(lib2.isLoaded(), true); - QCOMPARE(lib2.unload(), true); - QCOMPARE(lib1.isLoaded(), false); - QCOMPARE(lib2.isLoaded(), false); + { + QLibrary lib1(lib); + QLibrary lib2(lib); + QCOMPARE(lib1.isLoaded(), false); + QCOMPARE(lib2.isLoaded(), false); + lib1.load(); + QCOMPARE(lib1.isLoaded(), true); + QCOMPARE(lib2.isLoaded(), true); + QCOMPARE(lib1.unload(), true); + QCOMPARE(lib1.isLoaded(), false); + QCOMPARE(lib2.isLoaded(), false); + lib1.load(); + lib2.load(); + QCOMPARE(lib1.isLoaded(), true); + QCOMPARE(lib2.isLoaded(), true); + QCOMPARE(lib1.unload(), false); + QCOMPARE(lib1.isLoaded(), true); + QCOMPARE(lib2.isLoaded(), true); + QCOMPARE(lib2.unload(), true); + QCOMPARE(lib1.isLoaded(), false); + QCOMPARE(lib2.isLoaded(), false); + + // Finally; unload on that is already unloaded + QCOMPARE(lib1.unload(), false); + } - // Finally; unload on that is already unloaded - QCOMPARE(lib1.unload(), false); + //now let's try with a 3rd one that will go out of scope + { + QLibrary lib1(lib); + QCOMPARE(lib1.isLoaded(), false); + lib1.load(); + QCOMPARE(lib1.isLoaded(), true); + } + QLibrary lib2(lib); + //lib2 should be loaded because lib1 was loaded and never unloaded + QCOMPARE(lib2.isLoaded(), true); /* lib1.setLoadHints(QLibrary::ResolveAllSymbolsHint); diff --git a/tests/auto/qlist/tst_qlist.cpp b/tests/auto/qlist/tst_qlist.cpp index ba8aefa..9f6b4a5 100644 --- a/tests/auto/qlist/tst_qlist.cpp +++ b/tests/auto/qlist/tst_qlist.cpp @@ -89,6 +89,8 @@ private slots: void testSTLIterators() const; void testOperators() const; + + void initializeList() const; }; void tst_QList::length() const @@ -662,5 +664,19 @@ void tst_QList::testSTLIterators() const QCOMPARE(*it, QLatin1String("foo")); } +void tst_QList::initializeList() const +{ +#ifdef QT_CXX0X_INITIALIZERLIST + QList<int> v1{2,3,4}; + QCOMPARE(v1, QList<int>() << 2 << 3 << 4); + QCOMPARE(v1, (QList<int>{2,3,4})); + + QList<QList<int>> v2{ v1, {1}, QList<int>(), {2,3,4} }; + QList<QList<int>> v3; + v3 << v1 << (QList<int>() << 1) << QList<int>() << v1; + QCOMPARE(v3, v2); +#endif +} + QTEST_APPLESS_MAIN(tst_QList) #include "tst_qlist.moc" diff --git a/tests/auto/qmatrixnxn/tst_qmatrixnxn.cpp b/tests/auto/qmatrixnxn/tst_qmatrixnxn.cpp index 5709196..22c679a 100644 --- a/tests/auto/qmatrixnxn/tst_qmatrixnxn.cpp +++ b/tests/auto/qmatrixnxn/tst_qmatrixnxn.cpp @@ -2822,10 +2822,9 @@ void tst_QMatrixNxN::convertGeneric() 9.0f, 10.0f, 11.0f, 12.0f, 0.0f, 0.0f, 0.0f, 1.0f }; -#if !defined(QT_NO_MEMBER_TEMPLATES) QMatrix4x4 m4(m1); QVERIFY(isSame(m4, unique4x4)); -#endif + QMatrix4x4 m5 = qGenericMatrixToMatrix4x4(m1); QVERIFY(isSame(m5, unique4x4)); @@ -2835,10 +2834,9 @@ void tst_QMatrixNxN::convertGeneric() 9.0f, 10.0f, 11.0f, 12.0f }; QMatrix4x4 m9(uniqueValues4); -#if !defined(QT_NO_MEMBER_TEMPLATES) + QMatrix4x3 m10 = m9.toGenericMatrix<4, 3>(); QVERIFY(isSame(m10, conv4x4)); -#endif QMatrix4x3 m11 = qGenericMatrixFromMatrix4x4<4, 3>(m9); QVERIFY(isSame(m11, conv4x4)); diff --git a/tests/auto/qmetaobject/tst_qmetaobject.cpp b/tests/auto/qmetaobject/tst_qmetaobject.cpp index 8c2a0f9..1d0980e 100644 --- a/tests/auto/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/qmetaobject/tst_qmetaobject.cpp @@ -155,6 +155,7 @@ private slots: void connectSlotsByName(); void invokeMetaMember(); void invokeQueuedMetaMember(); + void invokeBlockingQueuedMetaMember(); void invokeCustomTypes(); void invokeMetaConstructor(); void invokeTypedefTypes(); @@ -336,6 +337,9 @@ public slots: void testLongLong(qint64 ll1, quint64 ll2); + void moveToThread(QThread *t) + { QObject::moveToThread(t); } + signals: void sig0(); QString sig1(QString s1); @@ -583,6 +587,138 @@ void tst_QMetaObject::invokeQueuedMetaMember() QCOMPARE(obj.slotResult, QString("testLongLong:-1,0")); } +void tst_QMetaObject::invokeBlockingQueuedMetaMember() +{ + QThread t; + t.start(); + QtTestObject obj; + obj.moveToThread(&t); + + QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5"); + QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X"); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, Q_ARG(QString, t1))); + QCOMPARE(obj.slotResult, QString("sl1:1")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl2", Qt::BlockingQueuedConnection, Q_ARG(const QString, t1), Q_ARG(QString, t2))); + QCOMPARE(obj.slotResult, QString("sl2:12")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl3", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3))); + QCOMPARE(obj.slotResult, QString("sl3:123")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl4", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), + Q_ARG(QString, t3), Q_ARG(QString, t4))); + QCOMPARE(obj.slotResult, QString("sl4:1234")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl5", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), + Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, "5"))); + QCOMPARE(obj.slotResult, QString("sl5:12345")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl6", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), + Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6))); + QCOMPARE(obj.slotResult, QString("sl6:123456")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl7", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), + Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6), + Q_ARG(QString, t7))); + QCOMPARE(obj.slotResult, QString("sl7:1234567")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl8", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), + Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6), + Q_ARG(QString, t7), Q_ARG(QString, t8))); + QCOMPARE(obj.slotResult, QString("sl8:12345678")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl9", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), + Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6), + Q_ARG(QString, t7), Q_ARG(QString, t8), Q_ARG(QString, t9))); + QCOMPARE(obj.slotResult, QString("sl9:123456789")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection)); + QCOMPARE(obj.slotResult, QString("sl11")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "testSender", Qt::BlockingQueuedConnection)); + QCOMPARE(obj.slotResult, QString("0x0")); + + QString refStr("whatever"); + QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", Qt::BlockingQueuedConnection, QGenericArgument("QString&", &refStr))); + QCOMPARE(obj.slotResult, QString("testReference:whatever")); + QCOMPARE(refStr, QString("gotcha")); + + qint64 ll1 = -1; + quint64 ll2 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, + "testLongLong", + Qt::BlockingQueuedConnection, + Q_ARG(qint64, ll1), + Q_ARG(quint64, ll2))); + QCOMPARE(obj.slotResult, QString("testLongLong:-1,0")); + + QString exp; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, exp), Q_ARG(QString, "bubu"))); + QCOMPARE(exp, QString("yessir")); + QCOMPARE(obj.slotResult, QString("sl1:bubu")); + + QObject *ptr = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QObject*,ptr))); + QCOMPARE(ptr, (QObject *)&obj); + QCOMPARE(obj.slotResult, QString("sl11")); + // try again with a space: + ptr = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QObject * , ptr))); + QCOMPARE(ptr, (QObject *)&obj); + QCOMPARE(obj.slotResult, QString("sl11")); + + const char *ptr2 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Qt::BlockingQueuedConnection, Q_RETURN_ARG(const char*, ptr2))); + QVERIFY(ptr2 != 0); + QCOMPARE(obj.slotResult, QString("sl12")); + // try again with a space: + ptr2 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Qt::BlockingQueuedConnection, Q_RETURN_ARG(char const * , ptr2))); + QVERIFY(ptr2 != 0); + QCOMPARE(obj.slotResult, QString("sl12")); + + // test w/ template args + QList<QString> returnValue, argument; + argument << QString("one") << QString("two") << QString("three"); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl13", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QList<QString>, returnValue), + Q_ARG(QList<QString>, argument))); + QCOMPARE(returnValue, argument); + QCOMPARE(obj.slotResult, QString("sl13")); + + //test signals + QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::BlockingQueuedConnection)); + QCOMPARE(obj.slotResult, QString("sl0")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::BlockingQueuedConnection, Q_ARG(QString, "baba"))); + QCOMPARE(obj.slotResult, QString("sl1:baba")); + + exp.clear(); + QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, exp), Q_ARG(QString, "hehe"))); + QCOMPARE(exp, QString("yessir")); + QCOMPARE(obj.slotResult, QString("sl1:hehe")); + + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::doesNotExist()"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "doesNotExist", Qt::BlockingQueuedConnection)); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString)(QString)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1(QString)", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg"))); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "sl3", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg"))); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString,QString,QString)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg"), Q_ARG(QString, "arg"), Q_ARG(QString, "arg"))); + + //should not have changed since last test. + QCOMPARE(exp, QString("yessir")); + QCOMPARE(obj.slotResult, QString("sl1:hehe")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "moveToThread", Qt::BlockingQueuedConnection, Q_ARG(QThread*, QThread::currentThread()))); + t.quit(); + QVERIFY(t.wait()); + +} + + void tst_QMetaObject::qtMetaObjectInheritance() { diff --git a/tests/auto/qmetatype/tst_qmetatype.cpp b/tests/auto/qmetatype/tst_qmetatype.cpp index 8558e06..eaa19d0 100644 --- a/tests/auto/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/qmetatype/tst_qmetatype.cpp @@ -160,6 +160,11 @@ void tst_QMetaType::qMetaTypeId() QCOMPARE(::qMetaTypeId<QString>(), int(QMetaType::QString)); QCOMPARE(::qMetaTypeId<int>(), int(QMetaType::Int)); QCOMPARE(::qMetaTypeId<TestSpace::Foo>(), QMetaType::type("TestSpace::Foo")); + + QCOMPARE(::qMetaTypeId<char>(), QMetaType::type("char")); + QCOMPARE(::qMetaTypeId<uchar>(), QMetaType::type("unsigned char")); + QCOMPARE(::qMetaTypeId<signed char>(), QMetaType::type("signed char")); + QCOMPARE(::qMetaTypeId<qint8>(), QMetaType::type("qint8")); } void tst_QMetaType::properties() diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index 306b5f8..2ad4060 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -75,7 +75,8 @@ #include "../network-settings.h" - +typedef QSharedPointer<QVarLengthArray<char, 0> > QVarLengthArraySharedPointer; +Q_DECLARE_METATYPE(QVarLengthArraySharedPointer) Q_DECLARE_METATYPE(QNetworkReply*) Q_DECLARE_METATYPE(QAuthenticator*) Q_DECLARE_METATYPE(QNetworkProxy) @@ -289,6 +290,12 @@ private Q_SLOTS: void symbianOpenCDataUrlCrash(); + void getFromHttpIntoBuffer_data(); + void getFromHttpIntoBuffer(); + + void ioGetFromHttpWithoutContentLength(); + + void ioGetFromHttpBrokenChunkedEncoding(); void qtbug12908compressedHttpReply(); // NOTE: This test must be last! @@ -1173,6 +1180,12 @@ void tst_QNetworkReply::getErrors_data() QTest::addColumn<int>("httpStatusCode"); QTest::addColumn<bool>("dataIsEmpty"); + // empties + QTest::newRow("empty-url") << QString() << int(QNetworkReply::ProtocolUnknownError) << 0 << true; + QTest::newRow("empty-scheme-host") << SRCDIR "/rfc3252.txt" << int(QNetworkReply::ProtocolUnknownError) << 0 << true; + QTest::newRow("empty-scheme") << "//" + QtNetworkSettings::winServerName() + "/testshare/test.pri" + << int(QNetworkReply::ProtocolUnknownError) << 0 << true; + // file: errors QTest::newRow("file-host") << "file://this-host-doesnt-exist.troll.no/foo.txt" #if !defined Q_OS_WIN @@ -3932,6 +3945,7 @@ void tst_QNetworkReply::authorizationError() QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), httpStatusCode); QFETCH(QString, httpBody); + QCOMPARE(qint64(reply->size()), qint64(httpBody.size())); QCOMPARE(QString(reply->readAll()), httpBody); } @@ -4276,6 +4290,92 @@ void tst_QNetworkReply::symbianOpenCDataUrlCrash() QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), qint64(598)); } +void tst_QNetworkReply::getFromHttpIntoBuffer_data() +{ + QTest::addColumn<QUrl>("url"); + + QTest::newRow("rfc-internal") << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"); +} + +void tst_QNetworkReply::getFromHttpIntoBuffer() +{ + QFETCH(QUrl, url); + QNetworkRequest request(url); + request.setAttribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute, 1024*128); // 128 kB + + QNetworkAccessManager manager; + QNetworkReply *reply = manager.get(request); + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY(reply->isFinished()); + + QFile reference(SRCDIR "/rfc3252.txt"); + QVERIFY(reference.open(QIODevice::ReadOnly)); + + QCOMPARE(reference.bytesAvailable(), reply->bytesAvailable()); + QCOMPARE(reference.size(), reply->size()); + + // Compare the memory buffer + QVariant downloadBufferAttribute = reply->attribute(QNetworkRequest::DownloadBufferAttribute); + bool memoryComparison = + (0 == memcmp(static_cast<void*>(reference.readAll().data()), + downloadBufferAttribute.value<QSharedPointer<QVarLengthArray<char, 0> > >()->constData(), reference.size())); + QVERIFY(memoryComparison); + + // Make sure the normal reading works + reference.seek(0); + QCOMPARE(reply->read(42), reference.read(42)); + QCOMPARE(reply->getChar(0), reference.getChar(0)); + QCOMPARE(reply->peek(23), reference.peek(23)); + QCOMPARE(reply->readLine(), reference.readLine()); + QCOMPARE(reference.bytesAvailable(), reply->bytesAvailable()); + QCOMPARE(reply->readAll(), reference.readAll()); + QVERIFY(reply->atEnd()); +} + +// Is handled somewhere else too, introduced this special test to have it more accessible +void tst_QNetworkReply::ioGetFromHttpWithoutContentLength() +{ + QByteArray dataToSend("HTTP/1.0 200 OK\r\n\r\nHALLO! 123!"); + MiniHttpServer server(dataToSend); + server.doClose = true; + + QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort()))); + QNetworkReplyPtr reply = manager.get(request); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(reply->url(), request.url()); + QVERIFY(reply->isFinished()); + QVERIFY(reply->error() == QNetworkReply::NoError); +} + +// Is handled somewhere else too, introduced this special test to have it more accessible +void tst_QNetworkReply::ioGetFromHttpBrokenChunkedEncoding() +{ + // This is wrong chunked encoding because of the X. What actually has to follow is \r\n + // and then the declaration of the final 0 chunk + QByteArray dataToSend("HTTP/1.0 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n3\r\nABCX"); + MiniHttpServer server(dataToSend); + server.doClose = false; // FIXME + + QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort()))); + QNetworkReplyPtr reply = manager.get(request); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(10); + + QEXPECT_FAIL(0, "We should close the socket and not just do nothing", Continue); + QVERIFY(!QTestEventLoop::instance().timeout()); + QEXPECT_FAIL(0, "We should close the socket and not just do nothing", Continue); + QVERIFY(reply->isFinished()); + QCOMPARE(reply->error(), QNetworkReply::NoError); +} + // TODO: // Prepare a gzip that has one chunk that expands to the size mentioned in the bugreport. // Then have a custom HTTP server that waits after this chunk so the returning gets @@ -4301,7 +4401,6 @@ void tst_QNetworkReply::qtbug12908compressedHttpReply() QCOMPARE(reply->error(), QNetworkReply::NoError); } - // NOTE: This test must be last testcase in tst_qnetworkreply! void tst_QNetworkReply::parentingRepliesToTheApp() { diff --git a/tests/auto/qobject/tst_qobject.cpp b/tests/auto/qobject/tst_qobject.cpp index 5f6262e..24cd5a3 100644 --- a/tests/auto/qobject/tst_qobject.cpp +++ b/tests/auto/qobject/tst_qobject.cpp @@ -129,6 +129,12 @@ private slots: void qMetaObjectConnect(); void qMetaObjectDisconnectOne(); void sameName(); + void connectByMetaMethods(); + void connectByMetaMethodSlotInsteadOfSignal(); + void connectConstructorByMetaMethod(); + void disconnectByMetaMethod(); + void disconnectNotSignalMetaMethod(); + protected: }; @@ -663,11 +669,9 @@ void tst_QObject::findChildren() l = qFindChildren<QObject*>(&o, "unnamed"); QCOMPARE(l.size(), 0); -#ifndef QT_NO_MEMBER_TEMPLATES tl = o.findChildren<QTimer *>("t1"); QCOMPARE(tl.size(), 1); QCOMPARE(tl.at(0), &t1); -#endif } @@ -727,6 +731,24 @@ void tst_QObject::connectDisconnectNotify() // Test disconnectNotify for a complete disconnect ((SenderObject*)s)->disconnect((ReceiverObject*)r); + // Obtaining meta methods + int signalIndx = ((SenderObject*)s)->metaObject()->indexOfSignal( + QMetaObject::normalizedSignature(a_signal.toLatin1().constData()+1).constData()); + int methodIndx = ((ReceiverObject*)r)->metaObject()->indexOfMethod( + QMetaObject::normalizedSignature(a_slot.toLatin1().constData()+1).constData()); + QMetaMethod signal = ((SenderObject*)s)->metaObject()->method(signalIndx); + QMetaMethod method = ((ReceiverObject*)r)->metaObject()->method(methodIndx); + + // Test connectNotify when connecting by QMetaMethod + connect( (SenderObject*)s, signal, (ReceiverObject*)r, method ); + QCOMPARE( s->org_signal, s->nw_signal ); + QCOMPARE( s->org_signal.toLatin1(), QMetaObject::normalizedSignature(a_signal.toLatin1().constData()) ); + + // Test disconnectNotify when disconnecting by QMetaMethod + QObject::disconnect( (SenderObject*)s, signal, (ReceiverObject*)r, method ); + QCOMPARE( s->org_signal, s->nw_signal ); + QCOMPARE( s->org_signal.toLatin1(), QMetaObject::normalizedSignature(a_signal.toLatin1().constData()) ); + delete s; delete r; } @@ -1760,9 +1782,12 @@ class SuperObject : public QObject Q_OBJECT public: QObject *theSender; + int theSignalId; + SuperObject() { theSender = 0; + theSignalId = 0; } friend class tst_QObject; @@ -1773,16 +1798,17 @@ public slots: void rememberSender() { theSender = sender(); + theSignalId = senderSignalIndex(); } void deleteAndRememberSender() { delete theSender; - theSender = sender(); + rememberSender(); } signals: + void anotherSignal(); void theSignal(); - }; void tst_QObject::sender() @@ -1790,12 +1816,23 @@ void tst_QObject::sender() { SuperObject sender; SuperObject receiver; + connect(&sender, SIGNAL(anotherSignal()), + &receiver, SLOT(rememberSender())); connect(&sender, SIGNAL(theSignal()), &receiver, SLOT(rememberSender())); QCOMPARE(receiver.sender(), (QObject *)0); + QCOMPARE(receiver.senderSignalIndex(), -1); emit sender.theSignal(); QCOMPARE(receiver.theSender, (QObject *)&sender); QCOMPARE(receiver.sender(), (QObject *)0); + QCOMPARE(receiver.theSignalId, + sender.metaObject()->indexOfSignal("theSignal()")); + QCOMPARE(receiver.senderSignalIndex(), -1); + + emit sender.anotherSignal(); + QCOMPARE(receiver.theSignalId, + sender.metaObject()->indexOfSignal("anotherSignal()")); + QCOMPARE(receiver.senderSignalIndex(), -1); } { @@ -1812,11 +1849,16 @@ void tst_QObject::sender() Qt::DirectConnection); QCOMPARE(receiver->sender(), (QObject *)0); + QCOMPARE(receiver->senderSignalIndex(), -1); receiver->theSender = 0; + receiver->theSignalId = -1; thread.start(); emit sender->theSignal(); QCOMPARE(receiver->theSender, (QObject *) sender); QCOMPARE(receiver->sender(), (QObject *)0); + QCOMPARE(receiver->theSignalId, + sender->metaObject()->indexOfSignal("theSignal()")); + QCOMPARE(receiver->senderSignalIndex(), -1); QVERIFY(thread.wait(10000)); delete receiver; @@ -3610,5 +3652,200 @@ void tst_QObject::sameName() QCOMPARE(c1.s, 4); } +void tst_QObject::connectByMetaMethods() +{ + SenderObject s; + ReceiverObject r; + const QMetaObject *smeta = s.metaObject(); + const QMetaObject *rmeta = r.metaObject(); + int sigIndx = smeta->indexOfSignal(QMetaObject::normalizedSignature("signal1()")); + int slotIndx = rmeta->indexOfSlot(QMetaObject::normalizedSignature("slot1()")); + QVERIFY( sigIndx != -1 ); + QVERIFY( slotIndx != -1 ); + QMetaMethod signal = smeta->method(sigIndx); + QMetaMethod slot = rmeta->method(slotIndx); + + QVERIFY(connect(&s,signal, &r,slot)); + + QVERIFY(!r.called(1)); + s.emitSignal1(); + QVERIFY(r.called(1)); +} + +void tst_QObject::connectByMetaMethodSlotInsteadOfSignal() +{ + SenderObject s; + ReceiverObject r; + const QMetaObject *smeta = s.metaObject(); + const QMetaObject *rmeta = r.metaObject(); + int badIndx = smeta->indexOfSlot(QMetaObject::normalizedSignature("aPublicSlot()")); + int slotIndx = rmeta->indexOfSlot(QMetaObject::normalizedSignature("slot1()")); + QVERIFY( badIndx != -1 ); + QVERIFY( slotIndx != -1 ); + QMetaMethod badMethod = smeta->method(badIndx); + QMetaMethod slot = rmeta->method(slotIndx); + + QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect SenderObject::aPublicSlot() to ReceiverObject::slot1()"); + QVERIFY(!connect(&s,badMethod, &r,slot)); +} + +class Constructable: public QObject +{ + Q_OBJECT + +public: + Q_INVOKABLE Constructable(){} + +}; + +void tst_QObject::connectConstructorByMetaMethod() +{ + Constructable sc; + Constructable rc; + SenderObject s; + ReceiverObject r; + + const QMetaObject cmeta = Constructable::staticMetaObject; + const QMetaObject *smeta = s.metaObject(); + const QMetaObject *rmeta = r.metaObject(); + int constructorIndx = cmeta.indexOfConstructor(QMetaObject::normalizedSignature("Constructable()")); + int sigIndx = smeta->indexOfSignal(QMetaObject::normalizedSignature("signal1()")); + int slotIndx = rmeta->indexOfSlot(QMetaObject::normalizedSignature("slot1()")); + QVERIFY( constructorIndx != -1 ); + QVERIFY( sigIndx != -1 ); + QVERIFY( slotIndx != -1 ); + + QMetaMethod constructor = cmeta.constructor(constructorIndx); + QMetaMethod signal = smeta->method(sigIndx); + QMetaMethod slot = rmeta->method(slotIndx); + + QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect Constructable::Constructable() to ReceiverObject::slot1()"); + QVERIFY(!connect(&sc,constructor, &r,slot)); + QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect SenderObject::signal1() to Constructable::Constructable()"); + QVERIFY(!connect(&s,signal, &rc,constructor)); + QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect Constructable::Constructable() to Constructable::Constructable()"); + QVERIFY(!connect(&sc,constructor, &rc,constructor)); +} + +void tst_QObject::disconnectByMetaMethod() +{ + SenderObject *s = new SenderObject; + ReceiverObject *r1 = new ReceiverObject; + ReceiverObject *r2 = new ReceiverObject; + + QMetaMethod signal1 = s->metaObject()->method( + s->metaObject()->indexOfMethod("signal1()")); + QMetaMethod signal2 = s->metaObject()->method( + s->metaObject()->indexOfMethod("signal2()")); + QMetaMethod signal3 = s->metaObject()->method( + s->metaObject()->indexOfMethod("signal3()")); + QMetaMethod signal4 = s->metaObject()->method( + s->metaObject()->indexOfMethod("signal4()")); + + QMetaMethod slot1 = r1->metaObject()->method( + r1->metaObject()->indexOfMethod("slot1()")); + QMetaMethod slot2 = r1->metaObject()->method( + r1->metaObject()->indexOfMethod("slot2()")); + QMetaMethod slot3 = r1->metaObject()->method( + r1->metaObject()->indexOfMethod("slot3()")); + QMetaMethod slot4 = r1->metaObject()->method( + r1->metaObject()->indexOfMethod("slot4()")); + + connect(s, signal1, r1, slot1); + + s->emitSignal1(); + + QVERIFY(r1->called(1)); + r1->reset(); + + // usual disconnect with all parameters given + bool ret = QObject::disconnect(s, signal1, r1, slot1); + + s->emitSignal1(); + + QVERIFY(!r1->called(1)); + r1->reset(); + + QVERIFY(ret); + ret = QObject::disconnect(s, signal1, r1, slot1); + QVERIFY(!ret); + + r1->reset(); + + connect( s, signal1, r1, slot1 ); + connect( s, signal1, r1, slot2 ); + connect( s, signal1, r1, slot3 ); + connect( s, signal2, r1, slot4 ); + + // disconnect s's signal1() from all slots of r1 + QObject::disconnect(s, signal1, r1, QMetaMethod()); + + s->emitSignal1(); + s->emitSignal2(); + + QVERIFY(!r1->called(1)); + QVERIFY(!r1->called(2)); + QVERIFY(!r1->called(3)); + QVERIFY(r1->called(4)); + r1->reset(); + // make sure all is disconnected again + QObject::disconnect(s, 0, r1, 0); + + connect(s, signal1, r1, slot1); + connect(s, signal1, r2, slot1); + connect(s, signal2, r1, slot2); + connect(s, signal2, r2, slot2); + connect(s, signal3, r1, slot3); + connect(s, signal3, r2, slot3); + + // disconnect signal1() from all receivers + QObject::disconnect(s, signal1, 0, QMetaMethod()); + s->emitSignal1(); + s->emitSignal2(); + s->emitSignal3(); + + QVERIFY(!r1->called(1)); + QVERIFY(!r2->called(1)); + QVERIFY(r1->called(2)); + QVERIFY(r2->called(2)); + QVERIFY(r1->called(2)); + QVERIFY(r2->called(2)); + + r1->reset(); + r2->reset(); + + // disconnect all signals of s from all receivers + QObject::disconnect( s, 0, 0, 0 ); + + connect( s, signal1, r1, slot1 ); + connect( s, signal1, r2, slot1 ); + + // disconnect all signals from slot1 of r1 + QObject::disconnect(s, QMetaMethod(), r1, slot1); + + s->emitSignal1(); + + QVERIFY(!r1->called(1)); + QVERIFY(r2->called(1)); + + delete r2; + delete r1; + delete s; +} + +void tst_QObject::disconnectNotSignalMetaMethod() +{ + SenderObject s; + ReceiverObject r; + + connect(&s, SIGNAL(signal1()), &r, SLOT(slot1())); + + QMetaMethod slot = s.metaObject()->method( + s.metaObject()->indexOfMethod("aPublicSlot()")); + + QTest::ignoreMessage(QtWarningMsg,"Object::disconnect: Attempt to unbind non-signal SenderObject::aPublicSlot()"); + QVERIFY(!QObject::disconnect(&s, slot, &r, QMetaMethod())); +} + QTEST_MAIN(tst_QObject) #include "tst_qobject.moc" diff --git a/tests/auto/qpainter/tst_qpainter.cpp b/tests/auto/qpainter/tst_qpainter.cpp index f358681..9b8444c 100644 --- a/tests/auto/qpainter/tst_qpainter.cpp +++ b/tests/auto/qpainter/tst_qpainter.cpp @@ -168,6 +168,8 @@ private slots: void clippedText(); + void clipBoundingRect(); + void setOpacity_data(); void setOpacity(); @@ -219,6 +221,8 @@ private slots: void drawRect_task215378(); void drawRect_task247505(); + void drawText_subPixelPositionsInRaster_qtbug5053(); + void drawImage_data(); void drawImage(); @@ -1298,7 +1302,7 @@ void tst_QPainter::drawRect2() p.end(); QRect stroke = getPaintedSize(image, Qt::white); - QCOMPARE(stroke.adjusted(1, 1, 0, 0), fill.adjusted(0, 0, 1, 1)); + QCOMPARE(stroke, fill.adjusted(0, 0, 1, 1)); } } @@ -1395,13 +1399,13 @@ void tst_QPainter::drawPath_data() { QPainterPath p; p.addRect(2.25, 2.25, 10, 10); - QTest::newRow("non-aligned rect") << p << QRect(3, 3, 10, 10) << 10 * 10; + QTest::newRow("non-aligned rect") << p << QRect(2, 2, 10, 10) << 10 * 10; } { QPainterPath p; p.addRect(2.25, 2.25, 10.5, 10.5); - QTest::newRow("non-aligned rect 2") << p << QRect(3, 3, 10, 10) << 10 * 10; + QTest::newRow("non-aligned rect 2") << p << QRect(2, 2, 11, 11) << 11 * 11; } { @@ -3506,6 +3510,9 @@ bool verifyOutlineFillConsistency(const QImage &img, QRgb outside, QRgb inside, void tst_QPainter::outlineFillConsistency() { + QSKIP("currently broken...", SkipAll); + return; + QImage dst(256, 256, QImage::Format_ARGB32_Premultiplied); QPolygonF poly; @@ -4522,6 +4529,100 @@ void tst_QPainter::QTBUG5939_attachPainterPrivate() QCOMPARE(widget->deviceTransform, proxy->deviceTransform); } +void tst_QPainter::clipBoundingRect() +{ + QPixmap pix(500, 500); + + QPainter p(&pix); + + // Test a basic rectangle + p.setClipRect(100, 100, 200, 100); + QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); + QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200))); + p.setClipRect(120, 120, 20, 20, Qt::IntersectClip); + QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20))); + QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); + + // Test a basic path + region + QPainterPath path; + path.addRect(100, 100, 200, 100); + p.setClipPath(path); + QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); + QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200))); + p.setClipRegion(QRegion(120, 120, 20, 20), Qt::IntersectClip); + QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20))); + QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); + + p.setClipRect(0, 0, 500, 500); + p.translate(250, 250); + for (int i=0; i<360; ++i) { + p.rotate(1); + p.setClipRect(-100, -100, 200, 200, Qt::IntersectClip); + } + QVERIFY(p.clipBoundingRect().contains(QRectF(-100, -100, 200, 200))); + QVERIFY(!p.clipBoundingRect().contains(QRectF(-250, -250, 500, 500))); + +} + +void tst_QPainter::drawText_subPixelPositionsInRaster_qtbug5053() +{ +#if !defined(Q_WS_MAC) || !defined(QT_MAC_USE_COCOA) + QSKIP("Only Mac/Cocoa supports sub pixel positions in raster engine currently", SkipAll); +#endif + + int w = 10, h = 10; + QImage image(w, h, QImage::Format_RGB32); + image.fill(0xffffffff); + QPainter p(&image); + p.drawText(0, h, "X\\"); + p.end(); + + bool foundNonGrayPixel = false; + const int *bits = (const int *) ((const QImage &) image).bits(); + int bpl = image.bytesPerLine() / 4; + for (int y=0; y<w; ++y) { + for (int x=0; x<h; ++x) { + int r = qRed(bits[x]); + int g = qGreen(bits[x]); + int b = qBlue(bits[x]); + if (r != g || r != b) { + foundNonGrayPixel = true; + break; + } + } + bits += bpl; + } + if (!foundNonGrayPixel) + QSKIP("Font smoothing must be turned on for this test", SkipAll); + + QFontMetricsF fm(qApp->font()); + + QImage baseLine(fm.width(QChar::fromLatin1('e')), fm.height(), QImage::Format_RGB32); + baseLine.fill(Qt::white); + { + QPainter p(&baseLine); + p.drawText(0, fm.ascent(), QString::fromLatin1("e")); + } + + bool foundDifferentRasterization = false; + for (int i=1; i<12; ++i) { + QImage comparison(baseLine.size(), QImage::Format_RGB32); + comparison.fill(Qt::white); + + { + QPainter p(&comparison); + p.drawText(QPointF(i / 12.0, fm.ascent()), QString::fromLatin1("e")); + } + + if (comparison != baseLine) { + foundDifferentRasterization = true; + break; + } + } + + QVERIFY(foundDifferentRasterization); +} + QTEST_MAIN(tst_QPainter) #include "tst_qpainter.moc" diff --git a/tests/auto/qpluginloader/elftest/.gitattributes b/tests/auto/qpluginloader/elftest/.gitattributes new file mode 100644 index 0000000..891192c --- /dev/null +++ b/tests/auto/qpluginloader/elftest/.gitattributes @@ -0,0 +1,10 @@ +corrupt1.elf64.so set -crlf -diff +corrupt2.elf64.so set -crlf -diff +corrupt3.elf64.so set -crlf -diff +debugobj.so set -crlf -diff +garbage1.so set -crlf -diff +garbage2.so set -crlf -diff +garbage3.so set -crlf -diff +garbage4.so set -crlf -diff +garbage5.so set -crlf -diff + diff --git a/tests/auto/qpluginloader/elftest/corrupt1.elf64.so b/tests/auto/qpluginloader/elftest/corrupt1.elf64.so Binary files differnew file mode 100755 index 0000000..12ce736 --- /dev/null +++ b/tests/auto/qpluginloader/elftest/corrupt1.elf64.so diff --git a/tests/auto/qpluginloader/elftest/corrupt2.elf64.so b/tests/auto/qpluginloader/elftest/corrupt2.elf64.so Binary files differnew file mode 100755 index 0000000..11fdc2c --- /dev/null +++ b/tests/auto/qpluginloader/elftest/corrupt2.elf64.so diff --git a/tests/auto/qpluginloader/elftest/corrupt3.elf64.so b/tests/auto/qpluginloader/elftest/corrupt3.elf64.so Binary files differnew file mode 100755 index 0000000..94a2bc3 --- /dev/null +++ b/tests/auto/qpluginloader/elftest/corrupt3.elf64.so diff --git a/tests/auto/qpluginloader/elftest/debugobj.so b/tests/auto/qpluginloader/elftest/debugobj.so Binary files differnew file mode 100644 index 0000000..f0ee056 --- /dev/null +++ b/tests/auto/qpluginloader/elftest/debugobj.so diff --git a/tests/auto/qpluginloader/elftest/garbage1.so b/tests/auto/qpluginloader/elftest/garbage1.so new file mode 100644 index 0000000..0c74530 --- /dev/null +++ b/tests/auto/qpluginloader/elftest/garbage1.so @@ -0,0 +1,4 @@ +pcdL+&&e= +oÒʎIٝmg]!Z +L')t +N(eP)Y8G 6-y"Zk4?^n5$Y=#y
\ No newline at end of file diff --git a/tests/auto/qpluginloader/elftest/garbage2.so b/tests/auto/qpluginloader/elftest/garbage2.so new file mode 100644 index 0000000..c06338e --- /dev/null +++ b/tests/auto/qpluginloader/elftest/garbage2.so @@ -0,0 +1 @@ +v.YtKW3
\ No newline at end of file diff --git a/tests/auto/qpluginloader/elftest/garbage3.so b/tests/auto/qpluginloader/elftest/garbage3.so new file mode 100644 index 0000000..a24c523 --- /dev/null +++ b/tests/auto/qpluginloader/elftest/garbage3.so @@ -0,0 +1 @@ +ȂT-ڥ 쾜i8_xIx=4@[BKS$
\ No newline at end of file diff --git a/tests/auto/qpluginloader/elftest/garbage4.so b/tests/auto/qpluginloader/elftest/garbage4.so new file mode 100644 index 0000000..4f45cf5 --- /dev/null +++ b/tests/auto/qpluginloader/elftest/garbage4.so @@ -0,0 +1 @@ +!\~Uu:9T+91QEǚxng5zh^t'mm*ˈdXH;vw+G
9L0!
\ No newline at end of file diff --git a/tests/auto/qpluginloader/elftest/garbage5.so b/tests/auto/qpluginloader/elftest/garbage5.so new file mode 100644 index 0000000..f8c0a1d --- /dev/null +++ b/tests/auto/qpluginloader/elftest/garbage5.so @@ -0,0 +1,2 @@ +Q +-9
\ No newline at end of file diff --git a/tests/auto/qpluginloader/tst/tst.pro b/tests/auto/qpluginloader/tst/tst.pro index 2d757e7..e270120 100644 --- a/tests/auto/qpluginloader/tst/tst.pro +++ b/tests/auto/qpluginloader/tst/tst.pro @@ -27,3 +27,5 @@ symbian: { DEPLOYMENT += libDep pluginDep } + +DEFINES += SRCDIR=\\\"$$PWD/../\\\" diff --git a/tests/auto/qpluginloader/tst_qpluginloader.cpp b/tests/auto/qpluginloader/tst_qpluginloader.cpp index e913cb5..46fce5e 100644 --- a/tests/auto/qpluginloader/tst_qpluginloader.cpp +++ b/tests/auto/qpluginloader/tst_qpluginloader.cpp @@ -123,6 +123,9 @@ private slots: void loadHints(); void deleteinstanceOnUnload(); void checkingStubsFromDifferentDrives(); + void loadDebugObj(); + void loadCorruptElf(); + void loadGarbage(); }; tst_QPluginLoader::tst_QPluginLoader() @@ -287,12 +290,14 @@ void tst_QPluginLoader::deleteinstanceOnUnload() QSignalSpy spy1(loader1.instance(), SIGNAL(destroyed())); QSignalSpy spy2(loader2.instance(), SIGNAL(destroyed())); - QCOMPARE(loader1.unload(), false); // refcount not reached 0, not really unloaded - QCOMPARE(spy1.count(), 0); - QCOMPARE(spy2.count(), 0); + if (pass == 0) { + QCOMPARE(loader2.unload(), false); // refcount not reached 0, not really unloaded + QCOMPARE(spy1.count(), 0); + QCOMPARE(spy2.count(), 0); + } QCOMPARE(instance1->pluginName(), QLatin1String("Plugin ok")); QCOMPARE(instance2->pluginName(), QLatin1String("Plugin ok")); - QCOMPARE(loader2.unload(), true); // refcount reached 0, did really unload + QVERIFY(loader1.unload()); // refcount reached 0, did really unload QCOMPARE(spy1.count(), 1); QCOMPARE(spy2.count(), 1); } @@ -348,5 +353,54 @@ void tst_QPluginLoader::checkingStubsFromDifferentDrives() #endif//Q_OS_SYMBIAN } +void tst_QPluginLoader::loadDebugObj() +{ +#if defined (__ELF__) + QVERIFY(QFile::exists(SRCDIR "elftest/debugobj.so")); + QPluginLoader lib1(SRCDIR "elftest/debugobj.so"); + QCOMPARE(lib1.load(), false); +#endif +} + +void tst_QPluginLoader::loadCorruptElf() +{ +#if defined (__ELF__) +if (sizeof(void*) == 8) { + QVERIFY(QFile::exists(SRCDIR "elftest/corrupt1.elf64.so")); + + QPluginLoader lib1(SRCDIR "elftest/corrupt1.elf64.so"); + QCOMPARE(lib1.load(), false); + QVERIFY(lib1.errorString().contains("not an ELF object")); + + QPluginLoader lib2(SRCDIR "elftest/corrupt2.elf64.so"); + QCOMPARE(lib2.load(), false); + QVERIFY(lib2.errorString().contains("invalid")); + + QPluginLoader lib3(SRCDIR "elftest/corrupt3.elf64.so"); + QCOMPARE(lib3.load(), false); + QVERIFY(lib3.errorString().contains("invalid")); +} else if (sizeof(void*) == 4) { + QPluginLoader libW(SRCDIR "elftest/corrupt3.elf64.so"); + QCOMPARE(libW.load(), false); + QVERIFY(libW.errorString().contains("architecture")); +} else { + QFAIL("Please port QElfParser to this platform or blacklist this test."); +} +#endif +} + +void tst_QPluginLoader::loadGarbage() +{ +#if defined (Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) + for (int i=0; i<5; i++) { + QPluginLoader lib(QString(SRCDIR "elftest/garbage%1.so").arg(i)); + QCOMPARE(lib.load(), false); +#ifdef SHOW_ERRORS + qDebug() << lib.errorString(); +#endif + } +#endif +} + QTEST_APPLESS_MAIN(tst_QPluginLoader) #include "tst_qpluginloader.moc" diff --git a/tests/auto/qradiobutton/tst_qradiobutton.cpp b/tests/auto/qradiobutton/tst_qradiobutton.cpp index c074496..531ebab 100644 --- a/tests/auto/qradiobutton/tst_qradiobutton.cpp +++ b/tests/auto/qradiobutton/tst_qradiobutton.cpp @@ -58,6 +58,7 @@ public: private slots: void task190739_focus(); + void minimumSizeHint(); private: }; @@ -96,6 +97,11 @@ void tst_QRadioButton::task190739_focus() } +void tst_QRadioButton::minimumSizeHint() +{ + QRadioButton button(tr("QRadioButtons sizeHint is the same as it's minimumSizeHint")); + QCOMPARE(button.sizeHint(), button.minimumSizeHint()); +} QTEST_MAIN(tst_QRadioButton) diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index f96aea6..b035492 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -1914,7 +1914,6 @@ void tst_QScriptEngine::valueConversion() QString snum = qScriptValueToValue<QString>(num); QCOMPARE(snum, QLatin1String("123")); } -#ifndef QT_NO_MEMBER_TEMPLATES { QScriptValue num = eng.toScriptValue(123); QCOMPARE(num.isNumber(), true); @@ -1926,7 +1925,6 @@ void tst_QScriptEngine::valueConversion() QString snum = eng.fromScriptValue<QString>(num); QCOMPARE(snum, QLatin1String("123")); } -#endif { QScriptValue num(&eng, 123); QCOMPARE(qScriptValueToValue<char>(num), char(123)); @@ -2096,6 +2094,38 @@ void tst_QScriptEngine::valueConversion() QVERIFY(!val.isVariant()); QVERIFY(val.isUndefined()); } + // Checking nested QVariants + { + QVariant tmp1; + QVariant tmp2(QMetaType::QVariant, &tmp1); + QVERIFY(QMetaType::Type(tmp2.type()) == QMetaType::QVariant); + + QScriptValue val1 = qScriptValueFromValue(&eng, tmp1); + QScriptValue val2 = qScriptValueFromValue(&eng, tmp2); + QVERIFY(val1.isValid()); + QVERIFY(val2.isValid()); + QVERIFY(val1.isUndefined()); + QVERIFY(!val2.isUndefined()); + QVERIFY(!val1.isVariant()); + QVERIFY(val2.isVariant()); + } + { + QVariant tmp1(123); + QVariant tmp2(QMetaType::QVariant, &tmp1); + QVariant tmp3(QMetaType::QVariant, &tmp2); + QVERIFY(QMetaType::Type(tmp1.type()) == QMetaType::Int); + QVERIFY(QMetaType::Type(tmp2.type()) == QMetaType::QVariant); + QVERIFY(QMetaType::Type(tmp3.type()) == QMetaType::QVariant); + + QScriptValue val1 = qScriptValueFromValue(&eng, tmp2); + QScriptValue val2 = qScriptValueFromValue(&eng, tmp3); + QVERIFY(val1.isValid()); + QVERIFY(val2.isValid()); + QVERIFY(val1.isVariant()); + QVERIFY(val2.isVariant()); + QVERIFY(val1.toVariant().toInt() == 123); + QVERIFY(qScriptValueFromValue(&eng, val2.toVariant()).toVariant().toInt() == 123); + } { QScriptValue val = qScriptValueFromValue(&eng, QVariant(true)); QVERIFY(!val.isVariant()); diff --git a/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp b/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp index 11813d8..0d57f0c 100644 --- a/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp +++ b/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp @@ -1670,6 +1670,7 @@ void tst_QScriptExtQObject::connectAndDisconnect() m_myObject->emitMySignalWithVariantArg(123); QCOMPARE(m_engine->evaluate("gotSignal").toBoolean(), true); QCOMPARE(m_engine->evaluate("signalArgs.length").toNumber(), 1.0); + QVERIFY(m_engine->evaluate("signalArgs[0]").isNumber()); QCOMPARE(m_engine->evaluate("signalArgs[0]").toNumber(), 123.0); QVERIFY(m_engine->evaluate("myObject.mySignalWithVariantArg.disconnect(myHandler)").isUndefined()); @@ -1685,16 +1686,29 @@ void tst_QScriptExtQObject::connectAndDisconnect() QVERIFY(m_engine->evaluate("signalArgs[0]").isUndefined()); QVERIFY(m_engine->evaluate("myObject.mySignalWithScriptEngineArg.disconnect(myHandler)").isUndefined()); - // signal with QVariant arg: argument conversion should work + // signal with QVariant arg: QVariant should be unwrapped only once m_myObject->clearConnectedSignal(); QVERIFY(m_engine->evaluate("myObject.mySignalWithVariantArg.connect(myHandler)").isUndefined()); QCOMPARE(m_myObject->connectedSignal().constData(), SIGNAL(mySignalWithVariantArg(QVariant))); m_engine->evaluate("gotSignal = false"); - m_myObject->emitMySignalWithVariantArg(123); + QVariant tmp(123); + QVariant signalArg(QMetaType::QVariant, &tmp); + m_myObject->emitMySignalWithVariantArg(signalArg); QCOMPARE(m_engine->evaluate("gotSignal").toBoolean(), true); QCOMPARE(m_engine->evaluate("signalArgs.length").toNumber(), 1.0); - QVERIFY(m_engine->evaluate("signalArgs[0]").isNumber()); - QCOMPARE(m_engine->evaluate("signalArgs[0]").toNumber(), 123.0); + QVERIFY(m_engine->evaluate("signalArgs[0]").isVariant()); + QCOMPARE(m_engine->evaluate("signalArgs[0]").toVariant().toDouble(), 123.0); + QVERIFY(m_engine->evaluate("myObject.mySignalWithVariantArg.disconnect(myHandler)").isUndefined()); + + // signal with QVariant arg: with an invalid QVariant + m_myObject->clearConnectedSignal(); + QVERIFY(m_engine->evaluate("myObject.mySignalWithVariantArg.connect(myHandler)").isUndefined()); + QCOMPARE(m_myObject->connectedSignal().constData(), SIGNAL(mySignalWithVariantArg(QVariant))); + m_engine->evaluate("gotSignal = false"); + m_myObject->emitMySignalWithVariantArg(QVariant()); + QCOMPARE(m_engine->evaluate("gotSignal").toBoolean(), true); + QCOMPARE(m_engine->evaluate("signalArgs.length").toNumber(), 1.0); + QVERIFY(m_engine->evaluate("signalArgs[0]").isUndefined()); QVERIFY(m_engine->evaluate("myObject.mySignalWithVariantArg.disconnect(myHandler)").isUndefined()); // signal with argument type that's unknown to the meta-type system diff --git a/tests/auto/qscriptvalue/testgen/testgenerator.cpp b/tests/auto/qscriptvalue/testgen/testgenerator.cpp index a291110..9d7d33d 100644 --- a/tests/auto/qscriptvalue/testgen/testgenerator.cpp +++ b/tests/auto/qscriptvalue/testgen/testgenerator.cpp @@ -162,7 +162,7 @@ static QString generateIsXXXDef(const QString& name, const QList<QString>& list) " initScriptValues();\n"\ "}\n"\ "\n"\ - "static QString %1_array [] = {%2};\n\n"\ + "static QString %1_array[] = {%2};\n\n"\ "void tst_QScriptValue::%1_makeData(const char* expr)\n"\ "{\n"\ " static QSet<QString> %1;\n"\ @@ -193,9 +193,11 @@ static QString generateIsXXXDef(const QString& name, const QList<QString>& list) QStringList set; set.reserve(3 * list.count()); foreach(const QString& t, list) { + if (!set.isEmpty()) + set.append("\","); set.append("\n \""); set.append(escape(t)); - set.append("\","); + set.append("\""); } return result.arg(name, set.join(QString()), QString::number(list.count())); @@ -211,8 +213,8 @@ static QString generateToXXXDef(const QString& name, const QList<QPair<QString, " initScriptValues();\n"\ "}\n"\ "\n"\ - "static QString %1_tagArray [] = {%4};\n\n"\ - "static %2 %1_valueArray [] = {%5};\n\n"\ + "static QString %1_tagArray[] = {%4};\n\n"\ + "static %2 %1_valueArray[] = {%5};\n\n"\ "void tst_QScriptValue::%1_makeData(const char* expr)\n"\ "{\n"\ " static QHash<QString, %2> %1;\n"\ @@ -236,19 +238,23 @@ static QString generateToXXXDef(const QString& name, const QList<QPair<QString, typename QList<QPair<QString, T> >::const_iterator i = list.constBegin(); QStringList tagSet, valueSet; - tagSet.reserve(list.count()); - valueSet.reserve(list.count()); - int tmp = -1; - for(; i != list.constEnd(); ++i) { + tagSet.reserve(4 * list.count()); + valueSet.reserve(3 * list.count()); + for(int lineBreaker = 0; i != list.constEnd(); ++i) { QPair<QString, T> t = *i; t.first = escape(t.first); + if (!valueSet.isEmpty()) { + valueSet.append(QString(",")); + tagSet.append(QString::fromAscii(",")); + } tagSet.append(QString("\n \"")); tagSet.append(t.first); - tagSet.append(QString::fromAscii("\",")); - if (!((++tmp)%2)) + tagSet.append(QString::fromAscii("\"")); + if (!((lineBreaker++)%2)) valueSet.append(QString("\n ")); + else + valueSet.append(QString::fromAscii(" ")); valueSet.append(prepareToInsert<T>(t.second)); - valueSet.append(QString::fromAscii(", ")); } return result.arg(name, typeName<T>(), @@ -268,8 +274,8 @@ QString generateToXXXDef<qsreal>(const QString& name, const QList<QPair<QString, " initScriptValues();\n"\ "}\n"\ "\n"\ - "static QString %1_tagArray [] = {%3};\n"\ - "static %2 %1_valueArray [] = {%4};\n"\ + "static QString %1_tagArray[] = {%3};\n"\ + "static %2 %1_valueArray[] = {%4};\n"\ "void tst_QScriptValue::%1_makeData(const char* expr)\n"\ "{\n"\ " static QHash<QString, %2> %1;\n"\ @@ -299,20 +305,25 @@ QString generateToXXXDef<qsreal>(const QString& name, const QList<QPair<QString, QList<QPair<QString, qsreal> >::const_iterator i = list.constBegin(); QStringList tagSet, valueSet; - tagSet.reserve(list.count()); - valueSet.reserve(list.count()); - int tmp = -1; - for(; i != list.constEnd(); ++i) { + tagSet.reserve(4 * list.count()); + valueSet.reserve(3 * list.count()); + for(int lineBreaker = 0; i != list.constEnd(); ++i) { QPair<QString, qsreal> t = *i; t.first = escape(t.first); + if (!valueSet.isEmpty()) { + valueSet.append(QString(",")); + tagSet.append(QString::fromAscii(",")); + } tagSet.append(QString("\n \"")); tagSet.append(t.first); - tagSet.append(QString::fromAscii("\",")); - if (!((++tmp)%10)) + tagSet.append(QString::fromAscii("\"")); + if (!((lineBreaker++)%10)) valueSet.append(QString("\n ")); + else + valueSet.append(QString::fromAscii(" ")); valueSet.append(prepareToInsert<qsreal>(t.second)); - valueSet.append(QString::fromAscii(", ")); } + // toInteger shouldn't return NaN, so it would be nice to catch the case. QString hook; if (name == "toNumber") { @@ -340,8 +351,8 @@ static QString generateCastDef(const QList<QPair<QString, T> >& list) " initScriptValues();\n"\ "}\n"\ "\n"\ - "static QString qscriptvalue_cast%1_tagArray [] = {%2};\n"\ - "static %1 qscriptvalue_cast%1_valueArray [] = {%3};\n"\ + "static QString qscriptvalue_cast%1_tagArray[] = {%2};\n"\ + "static %1 qscriptvalue_cast%1_valueArray[] = {%3};\n"\ "void tst_QScriptValue::qscriptvalue_cast%1_makeData(const char* expr)\n"\ "{\n"\ " static QHash<QString, %1> value;\n"\ @@ -365,19 +376,23 @@ static QString generateCastDef(const QList<QPair<QString, T> >& list) typename QList<QPair<QString, T> >::const_iterator i = list.constBegin(); QStringList tagSet, valueSet; - tagSet.reserve(list.count()); - valueSet.reserve(list.count()); - int tmp = -1; - for(; i != list.constEnd(); ++i) { + tagSet.reserve(4 * list.count()); + valueSet.reserve(3 * list.count()); + for(int lineBreaker = 0; i != list.constEnd(); ++i) { QPair<QString, T> t = *i; t.first = escape(t.first); + if (!valueSet.isEmpty()) { + valueSet.append(QString(",")); + tagSet.append(QString::fromAscii(",")); + } tagSet.append(QString("\n \"")); tagSet.append(t.first); - tagSet.append(QString::fromAscii("\",")); - if (!((++tmp)%2)) + tagSet.append(QString::fromAscii("\"")); + if (!((lineBreaker++)%2)) valueSet.append(QString("\n ")); + else + valueSet.append(QString::fromAscii(" ")); valueSet.append(prepareToInsert<T>(t.second)); - valueSet.append(QString::fromAscii(", ")); } return result.arg(typeName<T>(), tagSet.join(QString()), valueSet.join(QString()), QString::number(list.count())); } @@ -392,8 +407,8 @@ QString generateCastDef<qsreal>(const QList<QPair<QString, qsreal> >& list) " initScriptValues();\n"\ "}\n"\ "\n"\ - "static QString qscriptvalue_cast%1_tagArray [] = {%2};\n"\ - "static %1 qscriptvalue_cast%1_valueArray [] = {%3};\n"\ + "static QString qscriptvalue_cast%1_tagArray[] = {%2};\n"\ + "static %1 qscriptvalue_cast%1_valueArray[] = {%3};\n"\ "void tst_QScriptValue::qscriptvalue_cast%1_makeData(const char* expr)\n"\ "{\n"\ " static QHash<QString, %1> value;\n"\ @@ -427,19 +442,23 @@ QString generateCastDef<qsreal>(const QList<QPair<QString, qsreal> >& list) QList<QPair<QString, qsreal> >::const_iterator i = list.constBegin(); QStringList tagSet, valueSet; - tagSet.reserve(list.count()); - valueSet.reserve(list.count()); - int tmp = -1; - for(; i != list.constEnd(); ++i) { + tagSet.reserve(4 * list.count()); + valueSet.reserve(3 * list.count()); + for(int lineBreaker = 0; i != list.constEnd(); ++i) { QPair<QString, qsreal> t = *i; t.first = escape(t.first); + if (!valueSet.isEmpty()) { + valueSet.append(QString(",")); + tagSet.append(QString::fromAscii(",")); + } tagSet.append(QString("\n \"")); tagSet.append(t.first); - tagSet.append(QString::fromAscii("\",")); - if (!((++tmp)%10)) + tagSet.append(QString::fromAscii("\"")); + if (!((lineBreaker++)%10)) valueSet.append(QString("\n ")); + else + valueSet.append(QString::fromAscii(" ")); valueSet.append(prepareToInsert<qsreal>(t.second)); - valueSet.append(QString::fromAscii(", ")); } return result.arg(typeName<qsreal>(), tagSet.join(QString()), @@ -457,7 +476,7 @@ static QString generateCompareDef(const QString& comparisionType, const QList<QS " initScriptValues();\n"\ "}\n"\ "\n"\ - "static QString %1_array [] = {%2};\n\n"\ + "static QString %1_array[] = {%2};\n\n"\ "void tst_QScriptValue::%1_makeData(const char *expr)\n"\ "{\n"\ " static QSet<QString> equals;\n"\ @@ -488,9 +507,13 @@ static QString generateCompareDef(const QString& comparisionType, const QList<QS QString result = templ; QStringList set; - set.reserve(tags.count()); + set.reserve(4 * tags.count()); foreach(const QString& tmp, tags) { - set.append("\n \"" + escape(tmp) + "\","); + if (!set.isEmpty()) + set.append(","); + set.append("\n \""); + set.append(escape(tmp)); + set.append("\""); } return result.arg(comparisionType, set.join(""), QString::number(tags.count())); } @@ -500,7 +523,7 @@ static QString generateInitDef(const QVector<QString>& allDataTags) static const QString templ = "void tst_QScriptValue::initScriptValues()\n"\ "{\n"\ " m_values.clear();\n"\ - " if (engine) \n"\ + " if (engine)\n"\ " delete engine;\n"\ " engine = new QScriptEngine;\n"\ "%1\n}\n\n"; diff --git a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp index 83a3388..18480cc 100644 --- a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp +++ b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp @@ -2238,19 +2238,36 @@ void tst_QScriptValue::getSetScope() void tst_QScriptValue::getSetData() { QScriptEngine eng; - QScriptValue object = eng.newObject(); - QVERIFY(!object.data().isValid()); - QScriptValue v1(true); - object.setData(v1); - QVERIFY(object.data().strictlyEquals(v1)); - QScriptValue v2(123); - object.setData(v2); - QVERIFY(object.data().strictlyEquals(v2)); - QScriptValue v3 = eng.newObject(); - object.setData(v3); - QVERIFY(object.data().strictlyEquals(v3)); - object.setData(QScriptValue()); - QVERIFY(!object.data().isValid()); + { + QScriptValue object = eng.newObject(); + QVERIFY(!object.data().isValid()); + QScriptValue v1(true); + object.setData(v1); + QVERIFY(object.data().strictlyEquals(v1)); + QScriptValue v2(123); + object.setData(v2); + QVERIFY(object.data().strictlyEquals(v2)); + QScriptValue v3 = eng.newObject(); + object.setData(v3); + QVERIFY(object.data().strictlyEquals(v3)); + object.setData(QScriptValue()); + QVERIFY(!object.data().isValid()); + } + { + QScriptValue value = eng.undefinedValue(); + QVERIFY(!value.data().isValid()); + QScriptValue v1(true); + value.setData(v1); + QVERIFY(!value.data().isValid()); + QScriptValue v2(123); + value.setData(v2); + QVERIFY(!value.data().isValid()); + QScriptValue v3 = eng.newObject(); + value.setData(v3); + QVERIFY(!value.data().isValid()); + value.setData(QScriptValue()); + QVERIFY(!value.data().isValid()); + } } class TestScriptClass : public QScriptClass diff --git a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp index 6b4904f..5e624e4 100644 --- a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp @@ -732,7 +732,6 @@ void tst_QSharedPointer::objectCast() ptr = baseptr.objectCast<OtherObject>(); QVERIFY(ptr == data); -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION // again: ptr = qobject_cast<OtherObject *>(baseptr); QVERIFY(ptr == data); @@ -740,7 +739,6 @@ void tst_QSharedPointer::objectCast() // again: ptr = qobject_cast<QSharedPointer<OtherObject> >(baseptr); QVERIFY(ptr == data); -#endif } check(); @@ -760,7 +758,6 @@ void tst_QSharedPointer::objectCast() ptr = baseptr.objectCast<const OtherObject>(); QVERIFY(ptr == data); -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION // again: ptr = qobject_cast<const OtherObject *>(baseptr); QVERIFY(ptr == data); @@ -768,7 +765,6 @@ void tst_QSharedPointer::objectCast() // again: ptr = qobject_cast<QSharedPointer<const OtherObject> >(baseptr); QVERIFY(ptr == data); -#endif } check(); @@ -802,7 +798,6 @@ void tst_QSharedPointer::objectCast() QSharedPointer<OtherObject> otherptr = qSharedPointerObjectCast<OtherObject>(weakptr); QVERIFY(otherptr.isNull()); -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION // again: otherptr = qobject_cast<OtherObject *>(weakptr); QVERIFY(otherptr.isNull()); @@ -810,7 +805,6 @@ void tst_QSharedPointer::objectCast() // again: otherptr = qobject_cast<QSharedPointer<OtherObject> >(weakptr); QVERIFY(otherptr.isNull()); -#endif } check(); } @@ -1736,12 +1730,10 @@ void tst_QSharedPointer::invalidConstructs_data() << &QTest::QExternalTest::tryCompileFail << "QSharedPointer<const QObject> baseptr = QSharedPointer<const QObject>(new QObject);\n" "qSharedPointerObjectCast<QCoreApplication>(baseptr);"; -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION QTest::newRow("const-dropping-object-cast2") << &QTest::QExternalTest::tryCompileFail << "QSharedPointer<const QObject> baseptr = QSharedPointer<const QObject>(new QObject);\n" "qobject_cast<QCoreApplication *>(baseptr);"; -#endif // arithmethics through automatic cast operators QTest::newRow("arithmethic1") diff --git a/tests/auto/qstatictext/tst_qstatictext.cpp b/tests/auto/qstatictext/tst_qstatictext.cpp index 68c3ea9..2c07944 100644 --- a/tests/auto/qstatictext/tst_qstatictext.cpp +++ b/tests/auto/qstatictext/tst_qstatictext.cpp @@ -79,8 +79,11 @@ private slots: void rotatedPainter(); void scaledPainter(); void projectedPainter(); +#if 0 + void rotatedScaledAndTranslatedPainter_data(); void rotatedScaledAndTranslatedPainter(); - void transformationChanged(); +#endif + void transformationChanged(); void plainTextVsRichText(); @@ -455,12 +458,26 @@ void tst_QStaticText::projectedPainter() QCOMPARE(imageDrawStaticText, imageDrawText); } +#if 0 +void tst_QStaticText::rotatedScaledAndTranslatedPainter_data() +{ + QTest::addColumn<qreal>("offset"); + + for (int i=0; i<100; ++i) { + qreal offset = 300 + i / 100.; + QTest::newRow(QByteArray::number(offset).constData()) << offset; + } +} + void tst_QStaticText::rotatedScaledAndTranslatedPainter() { + QFETCH(qreal, offset); + QPixmap imageDrawText(1000, 1000); imageDrawText.fill(Qt::white); { QPainter p(&imageDrawText); + p.translate(offset, 0); p.rotate(45.0); p.scale(2.0, 2.0); p.translate(100, 200); @@ -472,6 +489,7 @@ void tst_QStaticText::rotatedScaledAndTranslatedPainter() imageDrawStaticText.fill(Qt::white); { QPainter p(&imageDrawStaticText); + p.translate(offset, 0); p.rotate(45.0); p.scale(2.0, 2.0); p.translate(100, 200); @@ -491,6 +509,7 @@ void tst_QStaticText::rotatedScaledAndTranslatedPainter() QEXPECT_FAIL("", "Graphics system does not support transformed text on this platform", Abort); QCOMPARE(imageDrawStaticText, imageDrawText); } +#endif void tst_QStaticText::transformationChanged() { diff --git a/tests/auto/qstring/tst_qstring.cpp b/tests/auto/qstring/tst_qstring.cpp index ef82769..af6b371 100644 --- a/tests/auto/qstring/tst_qstring.cpp +++ b/tests/auto/qstring/tst_qstring.cpp @@ -57,6 +57,10 @@ Q_DECLARE_METATYPE(qlonglong) //TESTED_CLASS= //TESTED_FILES= +#define CREATE_REF(string) \ + const QString padded = QString::fromLatin1(" %1 ").arg(string); \ + QStringRef ref = padded.midRef(1, padded.size() - 2); + class tst_QString : public QObject { Q_OBJECT @@ -135,6 +139,7 @@ private slots: void leftRef(); void stringRef(); void contains(); + void count(); void lastIndexOf_data(); void lastIndexOf(); void indexOf_data(); @@ -169,6 +174,12 @@ private slots: void fromLatin1Roundtrip(); void toLatin1Roundtrip_data(); void toLatin1Roundtrip(); + void stringRef_toLatin1Roundtrip_data(); + void stringRef_toLatin1Roundtrip(); + void stringRef_utf8_data(); + void stringRef_utf8(); + void stringRef_local8Bit_data(); + void stringRef_local8Bit(); void fromLatin1(); void fromAscii(); void arg(); @@ -1065,12 +1076,14 @@ void tst_QString::indexOf() QFETCH( int, startpos ); QFETCH( bool, bcs ); QFETCH( int, resultpos ); + CREATE_REF(needle); Qt::CaseSensitivity cs = bcs ? Qt::CaseSensitive : Qt::CaseInsensitive; bool needleIsLatin = (QString::fromLatin1(needle.toLatin1()) == needle); QCOMPARE( haystack.indexOf(needle, startpos, cs), resultpos ); + QCOMPARE( haystack.indexOf(ref, startpos, cs), resultpos ); if (needleIsLatin) { QCOMPARE( haystack.indexOf(needle.toLatin1(), startpos, cs), resultpos ); QCOMPARE( haystack.indexOf(needle.toLatin1().data(), startpos, cs), resultpos ); @@ -1098,12 +1111,14 @@ void tst_QString::indexOf() if (cs == Qt::CaseSensitive) { QCOMPARE( haystack.indexOf(needle, startpos), resultpos ); + QCOMPARE( haystack.indexOf(ref, startpos), resultpos ); if (needleIsLatin) { QCOMPARE( haystack.indexOf(needle.toLatin1(), startpos), resultpos ); QCOMPARE( haystack.indexOf(needle.toLatin1().data(), startpos), resultpos ); } if (startpos == 0) { QCOMPARE( haystack.indexOf(needle), resultpos ); + QCOMPARE( haystack.indexOf(ref), resultpos ); if (needleIsLatin) { QCOMPARE( haystack.indexOf(needle.toLatin1()), resultpos ); QCOMPARE( haystack.indexOf(needle.toLatin1().data()), resultpos ); @@ -1112,6 +1127,7 @@ void tst_QString::indexOf() } if (needle.size() == 1) { QCOMPARE(haystack.indexOf(needle.at(0), startpos, cs), resultpos); + QCOMPARE(haystack.indexOf(ref.at(0), startpos, cs), resultpos); } } @@ -1172,14 +1188,17 @@ void tst_QString::indexOf2() QFETCH( QString, haystack ); QFETCH( QString, needle ); QFETCH( int, resultpos ); + CREATE_REF(needle); QByteArray chaystack = haystack.toLatin1(); QByteArray cneedle = needle.toLatin1(); int got; QCOMPARE( haystack.indexOf(needle, 0, Qt::CaseSensitive), resultpos ); + QCOMPARE( haystack.indexOf(ref, 0, Qt::CaseSensitive), resultpos ); QCOMPARE( QStringMatcher(needle, Qt::CaseSensitive).indexIn(haystack, 0), resultpos ); QCOMPARE( haystack.indexOf(needle, 0, Qt::CaseInsensitive), resultpos ); + QCOMPARE( haystack.indexOf(ref, 0, Qt::CaseInsensitive), resultpos ); QCOMPARE( QStringMatcher(needle, Qt::CaseInsensitive).indexIn(haystack, 0), resultpos ); if ( needle.length() > 0 ) { got = haystack.lastIndexOf( needle, -1, Qt::CaseSensitive ); @@ -1246,10 +1265,12 @@ void tst_QString::lastIndexOf() QFETCH(int, from); QFETCH(int, expected); QFETCH(bool, caseSensitive); + CREATE_REF(needle); Qt::CaseSensitivity cs = (caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); QCOMPARE(haystack.lastIndexOf(needle, from, cs), expected); + QCOMPARE(haystack.lastIndexOf(ref, from, cs), expected); QCOMPARE(haystack.lastIndexOf(needle.toLatin1(), from, cs), expected); QCOMPARE(haystack.lastIndexOf(needle.toLatin1().data(), from, cs), expected); @@ -1279,20 +1300,23 @@ void tst_QString::lastIndexOf() if (cs == Qt::CaseSensitive) { QCOMPARE(haystack.lastIndexOf(needle, from), expected); + QCOMPARE(haystack.lastIndexOf(ref, from), expected); QCOMPARE(haystack.lastIndexOf(needle.toLatin1(), from), expected); QCOMPARE(haystack.lastIndexOf(needle.toLatin1().data(), from), expected); if (from == -1) { QCOMPARE(haystack.lastIndexOf(needle), expected); + QCOMPARE(haystack.lastIndexOf(ref), expected); QCOMPARE(haystack.lastIndexOf(needle.toLatin1()), expected); QCOMPARE(haystack.lastIndexOf(needle.toLatin1().data()), expected); } } if (needle.size() == 1) { QCOMPARE(haystack.lastIndexOf(needle.at(0), from), expected); + QCOMPARE(haystack.lastIndexOf(ref.at(0), from), expected); } } -void tst_QString::contains() +void tst_QString::count() { QString a; a="ABCDEFGHIEfGEFG"; // 15 chars @@ -1307,8 +1331,42 @@ void tst_QString::contains() QCOMPARE(a.count( "", Qt::CaseInsensitive), 16); QCOMPARE(a.count(QRegExp("[FG][HI]")),1); QCOMPARE(a.count(QRegExp("[G][HE]")),2); + + CREATE_REF(QLatin1String("FG")); + QCOMPARE(a.count(ref),2); + QCOMPARE(a.count(ref,Qt::CaseInsensitive),3); + QCOMPARE(a.count( QStringRef(), Qt::CaseInsensitive), 16); + QStringRef emptyRef(&a, 0, 0); + QCOMPARE(a.count( emptyRef, Qt::CaseInsensitive), 16); + +} + +void tst_QString::contains() +{ + QString a; + a="ABCDEFGHIEfGEFG"; // 15 chars + QVERIFY(a.contains('A')); + QVERIFY(!a.contains('Z')); + QVERIFY(a.contains('E')); + QVERIFY(a.contains('F')); + QVERIFY(a.contains('F',Qt::CaseInsensitive)); + QVERIFY(a.contains("FG")); + QVERIFY(a.contains("FG",Qt::CaseInsensitive)); + QVERIFY(a.contains( QString(), Qt::CaseInsensitive)); + QVERIFY(a.contains( "", Qt::CaseInsensitive)); + QVERIFY(a.contains(QRegExp("[FG][HI]"))); + QVERIFY(a.contains(QRegExp("[G][HE]"))); + + CREATE_REF(QLatin1String("FG")); + QVERIFY(a.contains(ref)); + QVERIFY(a.contains(ref, Qt::CaseInsensitive)); + QVERIFY(a.contains( QStringRef(), Qt::CaseInsensitive)); + QStringRef emptyRef(&a, 0, 0); + QVERIFY(a.contains(emptyRef, Qt::CaseInsensitive)); + } + void tst_QString::left() { QString a; @@ -2829,6 +2887,14 @@ void tst_QString::startsWith() QVERIFY( !a.startsWith(QChar(), Qt::CaseSensitive) ); QVERIFY( !a.startsWith(QLatin1Char(0), Qt::CaseSensitive) ); +#define TEST_REF_STARTS_WITH(string, yes) { CREATE_REF(string); QCOMPARE(a.startsWith(ref), yes); } + + TEST_REF_STARTS_WITH("A", true); + TEST_REF_STARTS_WITH("AB", true); + TEST_REF_STARTS_WITH("C", false); + TEST_REF_STARTS_WITH("ABCDEF", false); +#undef TEST_REF_STARTS_WITH + a = ""; QVERIFY( a.startsWith("") ); QVERIFY( a.startsWith(QString::null) ); @@ -2854,6 +2920,7 @@ void tst_QString::startsWith() QVERIFY( !a.startsWith(QLatin1Char(0)) ); QVERIFY( !a.startsWith(QLatin1Char('x')) ); QVERIFY( !a.startsWith(QChar()) ); + } void tst_QString::endsWith() @@ -2921,6 +2988,17 @@ void tst_QString::endsWith() QVERIFY( !a.endsWith(QChar(), Qt::CaseSensitive) ); QVERIFY( !a.endsWith(QLatin1Char(0), Qt::CaseSensitive) ); + +#define TEST_REF_ENDS_WITH(string, yes) { CREATE_REF(string); QCOMPARE(a.endsWith(ref), yes); } + TEST_REF_ENDS_WITH(QLatin1String("B"), true); + TEST_REF_ENDS_WITH(QLatin1String("AB"), true); + TEST_REF_ENDS_WITH(QLatin1String("C"), false); + TEST_REF_ENDS_WITH(QLatin1String("ABCDEF"), false); + TEST_REF_ENDS_WITH(QLatin1String(""), true); + TEST_REF_ENDS_WITH(QLatin1String(0), true); + +#undef TEST_REF_STARTS_WITH + a = ""; QVERIFY( a.endsWith("") ); QVERIFY( a.endsWith(QString::null) ); @@ -3056,6 +3134,20 @@ void tst_QString::utf8() QCOMPARE( utf8, QByteArray(res.toUtf8()) ); } +void tst_QString::stringRef_utf8_data() +{ + utf8_data(); +} + +void tst_QString::stringRef_utf8() +{ + QFETCH( QByteArray, utf8 ); + QFETCH( QString, res ); + + QStringRef ref(&res, 0, res.length()); + QCOMPARE( utf8, QByteArray(ref.toUtf8()) ); +} + // copied to tst_QTextCodec::utf8Codec_data() void tst_QString::fromUtf8_data() { @@ -3235,6 +3327,20 @@ void tst_QString::local8Bit() QCOMPARE(local8Bit.toLocal8Bit(), QByteArray(result)); } +void tst_QString::stringRef_local8Bit_data() +{ + local8Bit_data(); +} + +void tst_QString::stringRef_local8Bit() +{ + QFETCH(QString, local8Bit); + QFETCH(QByteArray, result); + + QStringRef ref(&local8Bit, 0, local8Bit.length()); + QCOMPARE(ref.toLocal8Bit(), QByteArray(result)); +} + void tst_QString::fromLatin1Roundtrip_data() { QTest::addColumn<QByteArray>("latin1"); @@ -3338,6 +3444,38 @@ void tst_QString::toLatin1Roundtrip() QCOMPARE(QString::fromLatin1(latin1, latin1.length()), unicodedst); } +void tst_QString::stringRef_toLatin1Roundtrip_data() +{ + toLatin1Roundtrip_data(); +} + +void tst_QString::stringRef_toLatin1Roundtrip() +{ + QFETCH(QByteArray, latin1); + QFETCH(QString, unicodesrc); + QFETCH(QString, unicodedst); + + // QtTest safety check: + Q_ASSERT(latin1.isNull() == unicodesrc.isNull()); + Q_ASSERT(latin1.isEmpty() == unicodesrc.isEmpty()); + Q_ASSERT(latin1.length() == unicodesrc.length()); + Q_ASSERT(latin1.isNull() == unicodedst.isNull()); + Q_ASSERT(latin1.isEmpty() == unicodedst.isEmpty()); + Q_ASSERT(latin1.length() == unicodedst.length()); + + if (!latin1.isEmpty()) + while (latin1.length() < 128) { + latin1 += latin1; + unicodesrc += unicodesrc; + unicodedst += unicodedst; + } + + // toLatin1 + QStringRef src(&unicodesrc, 0, unicodesrc.length()); + QCOMPARE(src.toLatin1().length(), latin1.length()); + QCOMPARE(src.toLatin1(), latin1); +} + void tst_QString::fromLatin1() { QString a; diff --git a/tests/auto/qstringref/qstringref.pro b/tests/auto/qstringref/qstringref.pro new file mode 100644 index 0000000..48e7ddf --- /dev/null +++ b/tests/auto/qstringref/qstringref.pro @@ -0,0 +1,4 @@ +load(qttest_p4) +SOURCES += tst_qstringref.cpp + +QT = core diff --git a/tests/auto/qstringref/tst_qstringref.cpp b/tests/auto/qstringref/tst_qstringref.cpp new file mode 100644 index 0000000..585e14e --- /dev/null +++ b/tests/auto/qstringref/tst_qstringref.cpp @@ -0,0 +1,881 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <qstringlist.h> +#include <qvariant.h> + +#include <qlocale.h> +#include <locale.h> + +Q_DECLARE_METATYPE(qlonglong) + +//TESTED_CLASS= +//TESTED_FILES= + + +class tst_QStringRef : public QObject +{ + Q_OBJECT + +public: + tst_QStringRef(); + virtual ~tst_QStringRef(); + + +public slots: + void init(); + void cleanup(); +private slots: + void endsWith(); + void startsWith(); + void contains(); + void count(); + void lastIndexOf_data(); + void lastIndexOf(); + void indexOf_data(); + void indexOf(); + void indexOf2_data(); + void indexOf2(); + void length_data(); + void length(); + void isEmpty(); + void compare_data(); + void compare(); + void operator_eqeq_nullstring(); +}; + +static QStringRef emptyRef() +{ + static const QString empty(""); + return empty.midRef(0); +} + +#define CREATE_REF(string) \ + const QString padded = QString::fromLatin1(" %1 ").arg(string); \ + QStringRef ref = padded.midRef(1, padded.size() - 2); + +typedef QList<int> IntList; + +Q_DECLARE_METATYPE(QList<QVariant>) +Q_DECLARE_METATYPE(IntList) + +// This next bit is needed for the NAN and INF in string -> number conversion tests +#include <float.h> +#include <limits.h> +#include <math.h> +#if defined(Q_WS_WIN) +# include <windows.h> +// mingw defines NAN and INFINITY to 0/0 and x/0 +# if defined(Q_CC_GNU) +# undef NAN +# undef INFINITY +# else +# define isnan(d) _isnan(d) +# endif +#endif +#if defined(Q_OS_MAC) && !defined isnan +#define isnan(d) __isnand(d) +#endif +#if defined(Q_OS_SOLARIS) +# include <ieeefp.h> +#endif +#if defined(Q_OS_OSF) && (defined(__DECC) || defined(__DECCXX)) +# define INFINITY DBL_INFINITY +# define NAN DBL_QNAN +#endif +#if defined(Q_OS_IRIX) && defined(Q_CC_GNU) +# include <ieeefp.h> +# define isnan(d) isnand(d) +#endif + +enum { + LittleEndian, + BigEndian +#ifdef Q_BYTE_ORDER +# if Q_BYTE_ORDER == Q_BIG_ENDIAN + , ByteOrder = BigEndian +# elif Q_BYTE_ORDER == Q_LITTLE_ENDIAN + , ByteOrder = LittleEndian +# else +# error "undefined byte order" +# endif +}; +#else +}; +static const unsigned int one = 1; +static const bool ByteOrder = ((*((unsigned char *) &one) == 0) ? BigEndian : LittleEndian); +#endif +#if !defined(INFINITY) +static const unsigned char be_inf_bytes[] = { 0x7f, 0xf0, 0, 0, 0, 0, 0,0 }; +static const unsigned char le_inf_bytes[] = { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }; +static inline double inf() +{ + if (ByteOrder == BigEndian) + return *reinterpret_cast<const double *>(be_inf_bytes); + return *reinterpret_cast<const double *>(le_inf_bytes); +} +# define INFINITY (::inf()) +#endif +#if !defined(NAN) +static const unsigned char be_nan_bytes[] = { 0x7f, 0xf8, 0, 0, 0, 0, 0,0 }; +static const unsigned char le_nan_bytes[] = { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f }; +static inline double nan() +{ + if (ByteOrder == BigEndian) + return *reinterpret_cast<const double *>(be_nan_bytes); + return *reinterpret_cast<const double *>(le_nan_bytes); +} +# define NAN (::nan()) +#endif + +tst_QStringRef::tst_QStringRef() +{ +} + +tst_QStringRef::~tst_QStringRef() +{ +} + +void tst_QStringRef::init() +{ +} + +void tst_QStringRef::cleanup() +{ + QLocale::setDefault(QString(QLatin1Char('C'))); +} + +void tst_QStringRef::length_data() +{ + QTest::addColumn<QString>("s1"); + QTest::addColumn<int>("res"); + + QTest::newRow("data0") << QString("Test") << 4; + QTest::newRow("data1") << QString("The quick brown fox jumps over the lazy dog") << 43; + QTest::newRow("data2") << QString() << 0; + QTest::newRow("data3") << QString("A") << 1; + QTest::newRow("data4") << QString("AB") << 2; + QTest::newRow("data5") << QString("AB\n") << 3; + QTest::newRow("data6") << QString("AB\nC") << 4; + QTest::newRow("data7") << QString("\n") << 1; + QTest::newRow("data8") << QString("\nA") << 2; + QTest::newRow("data9") << QString("\nAB") << 3; + QTest::newRow("data10") << QString("\nAB\nCDE") << 7; + QTest::newRow("data11") << QString("shdnftrheid fhgnt gjvnfmd chfugkh bnfhg thgjf vnghturkf chfnguh bjgnfhvygh hnbhgutjfv dhdnjds dcjs d") << 100; + QTest::newRow("data12") << QString("") << 0; +} + + +void tst_QStringRef::length() +{ + QFETCH(QString, s1); + CREATE_REF(s1); + QTEST(ref.length(), "res"); +} + + +void tst_QStringRef::isEmpty() +{ + QStringRef a; + QVERIFY(a.isEmpty()); + QVERIFY(emptyRef().isEmpty()); + CREATE_REF("Not empty"); + QVERIFY(!ref.isEmpty()); +} + +void tst_QStringRef::indexOf_data() +{ + QTest::addColumn<QString>("haystack"); + QTest::addColumn<QString>("needle"); + QTest::addColumn<int>("startpos"); + QTest::addColumn<bool>("bcs"); + QTest::addColumn<int>("resultpos"); + + QTest::newRow("data0") << QString("abc") << QString("a") << 0 << true << 0; + QTest::newRow("data1") << QString("abc") << QString("a") << 0 << false << 0; + QTest::newRow("data2") << QString("abc") << QString("A") << 0 << true << -1; + QTest::newRow("data3") << QString("abc") << QString("A") << 0 << false << 0; + QTest::newRow("data4") << QString("abc") << QString("a") << 1 << true << -1; + QTest::newRow("data5") << QString("abc") << QString("a") << 1 << false << -1; + QTest::newRow("data6") << QString("abc") << QString("A") << 1 << true << -1; + QTest::newRow("data7") << QString("abc") << QString("A") << 1 << false << -1; + QTest::newRow("data8") << QString("abc") << QString("b") << 0 << true << 1; + QTest::newRow("data9") << QString("abc") << QString("b") << 0 << false << 1; + QTest::newRow("data10") << QString("abc") << QString("B") << 0 << true << -1; + QTest::newRow("data11") << QString("abc") << QString("B") << 0 << false << 1; + QTest::newRow("data12") << QString("abc") << QString("b") << 1 << true << 1; + QTest::newRow("data13") << QString("abc") << QString("b") << 1 << false << 1; + QTest::newRow("data14") << QString("abc") << QString("B") << 1 << true << -1; + QTest::newRow("data15") << QString("abc") << QString("B") << 1 << false << 1; + QTest::newRow("data16") << QString("abc") << QString("b") << 2 << true << -1; + QTest::newRow("data17") << QString("abc") << QString("b") << 2 << false << -1; + + QTest::newRow("data20") << QString("ABC") << QString("A") << 0 << true << 0; + QTest::newRow("data21") << QString("ABC") << QString("A") << 0 << false << 0; + QTest::newRow("data22") << QString("ABC") << QString("a") << 0 << true << -1; + QTest::newRow("data23") << QString("ABC") << QString("a") << 0 << false << 0; + QTest::newRow("data24") << QString("ABC") << QString("A") << 1 << true << -1; + QTest::newRow("data25") << QString("ABC") << QString("A") << 1 << false << -1; + QTest::newRow("data26") << QString("ABC") << QString("a") << 1 << true << -1; + QTest::newRow("data27") << QString("ABC") << QString("a") << 1 << false << -1; + QTest::newRow("data28") << QString("ABC") << QString("B") << 0 << true << 1; + QTest::newRow("data29") << QString("ABC") << QString("B") << 0 << false << 1; + QTest::newRow("data30") << QString("ABC") << QString("b") << 0 << true << -1; + QTest::newRow("data31") << QString("ABC") << QString("b") << 0 << false << 1; + QTest::newRow("data32") << QString("ABC") << QString("B") << 1 << true << 1; + QTest::newRow("data33") << QString("ABC") << QString("B") << 1 << false << 1; + QTest::newRow("data34") << QString("ABC") << QString("b") << 1 << true << -1; + QTest::newRow("data35") << QString("ABC") << QString("b") << 1 << false << 1; + QTest::newRow("data36") << QString("ABC") << QString("B") << 2 << true << -1; + QTest::newRow("data37") << QString("ABC") << QString("B") << 2 << false << -1; + + QTest::newRow("data40") << QString("aBc") << QString("bc") << 0 << true << -1; + QTest::newRow("data41") << QString("aBc") << QString("Bc") << 0 << true << 1; + QTest::newRow("data42") << QString("aBc") << QString("bC") << 0 << true << -1; + QTest::newRow("data43") << QString("aBc") << QString("BC") << 0 << true << -1; + QTest::newRow("data44") << QString("aBc") << QString("bc") << 0 << false << 1; + QTest::newRow("data45") << QString("aBc") << QString("Bc") << 0 << false << 1; + QTest::newRow("data46") << QString("aBc") << QString("bC") << 0 << false << 1; + QTest::newRow("data47") << QString("aBc") << QString("BC") << 0 << false << 1; + QTest::newRow("data48") << QString("AbC") << QString("bc") << 0 << true << -1; + QTest::newRow("data49") << QString("AbC") << QString("Bc") << 0 << true << -1; + QTest::newRow("data50") << QString("AbC") << QString("bC") << 0 << true << 1; + QTest::newRow("data51") << QString("AbC") << QString("BC") << 0 << true << -1; + QTest::newRow("data52") << QString("AbC") << QString("bc") << 0 << false << 1; + QTest::newRow("data53") << QString("AbC") << QString("Bc") << 0 << false << 1; + + QTest::newRow("data54") << QString("AbC") << QString("bC") << 0 << false << 1; + QTest::newRow("data55") << QString("AbC") << QString("BC") << 0 << false << 1; + QTest::newRow("data56") << QString("AbC") << QString("BC") << 1 << false << 1; + QTest::newRow("data57") << QString("AbC") << QString("BC") << 2 << false << -1; +#if 0 + QTest::newRow("null-in-null") << QString() << QString() << 0 << false << 0; + QTest::newRow("empty-in-null") << QString() << QString("") << 0 << false << 0; + QTest::newRow("null-in-empty") << QString("") << QString() << 0 << false << 0; + QTest::newRow("empty-in-empty") << QString("") << QString("") << 0 << false << 0; +#endif + + + QString s1 = "abc"; + s1 += QChar(0xb5); + QString s2; + s2 += QChar(0x3bc); + QTest::newRow("data58") << QString(s1) << QString(s2) << 0 << false << 3; + s2.prepend("C"); + QTest::newRow("data59") << QString(s1) << QString(s2) << 0 << false << 2; + + QString veryBigHaystack(500, 'a'); + veryBigHaystack += 'B'; + QTest::newRow("BoyerMooreStressTest") << veryBigHaystack << veryBigHaystack << 0 << true << 0; + QTest::newRow("BoyerMooreStressTest2") << veryBigHaystack + 'c' << veryBigHaystack << 0 << true << 0; + QTest::newRow("BoyerMooreStressTest3") << 'c' + veryBigHaystack << veryBigHaystack << 0 << true << 1; + QTest::newRow("BoyerMooreStressTest4") << veryBigHaystack << veryBigHaystack + 'c' << 0 << true << -1; + QTest::newRow("BoyerMooreStressTest5") << veryBigHaystack << 'c' + veryBigHaystack << 0 << true << -1; + QTest::newRow("BoyerMooreStressTest6") << 'd' + veryBigHaystack << 'c' + veryBigHaystack << 0 << true << -1; + QTest::newRow("BoyerMooreStressTest6") << veryBigHaystack + 'c' << 'c' + veryBigHaystack << 0 << true << -1; + + QTest::newRow("BoyerMooreInsensitiveStressTest") << veryBigHaystack << veryBigHaystack << 0 << false << 0; + +} + +void tst_QStringRef::indexOf() +{ + QFETCH(QString, haystack); + QFETCH(QString, needle); + QFETCH(int, startpos); + QFETCH(bool, bcs); + QFETCH(int, resultpos); + + const QString haystackPadded = QString::fromLatin1(" %1 ").arg(haystack); + const QString needlePadded = QString::fromLatin1(" %1 ").arg(needle); + const QStringRef haystackRef(&haystackPadded, 1, haystack.size()); + const QStringRef needleRef(&needlePadded, 1, needle.size()); + + Qt::CaseSensitivity cs = bcs ? Qt::CaseSensitive : Qt::CaseInsensitive; + + QCOMPARE(haystack.indexOf(needle, startpos, cs), resultpos); + QCOMPARE(haystackRef.indexOf(needle, startpos, cs), resultpos); + QCOMPARE(haystackRef.indexOf(needleRef, startpos, cs), resultpos); + QCOMPARE(haystack.indexOf(needleRef, startpos, cs), resultpos); + + if (cs == Qt::CaseSensitive) { + QCOMPARE(haystack.indexOf(needle, startpos), resultpos); + QCOMPARE(haystackRef.indexOf(needle, startpos), resultpos); + QCOMPARE(haystackRef.indexOf(needleRef, startpos), resultpos); + QCOMPARE(haystack.indexOf(needleRef, startpos), resultpos); + if (startpos == 0) { + QCOMPARE(haystack.indexOf(needle), resultpos); + QCOMPARE(haystackRef.indexOf(needle), resultpos); + QCOMPARE(haystackRef.indexOf(needleRef), resultpos); + QCOMPARE(haystack.indexOf(needleRef), resultpos); + } + } + if (needle.size() == 1) { + QCOMPARE(needle.at(0), needleRef.at(0)); + QCOMPARE(haystack.indexOf(needleRef.at(0), startpos, cs), resultpos); + QCOMPARE(haystackRef.indexOf(needle.at(0), startpos, cs), resultpos); + QCOMPARE(haystackRef.indexOf(needleRef.at(0), startpos, cs), resultpos); + QCOMPARE(haystack.indexOf(needleRef.at(0), startpos ,cs), resultpos); + } +} + +void tst_QStringRef::indexOf2_data() +{ + QTest::addColumn<QString>("haystack"); + QTest::addColumn<QString>("needle"); + QTest::addColumn<int>("resultpos"); + + QTest::newRow("data0") << QString() << QString() << 0; + QTest::newRow("data1") << QString() << QString("") << 0; + QTest::newRow("data2") << QString("") << QString() << 0; + QTest::newRow("data3") << QString("") << QString("") << 0; + QTest::newRow("data4") << QString() << QString("a") << -1; + QTest::newRow("data5") << QString() << QString("abcdefg") << -1; + QTest::newRow("data6") << QString("") << QString("a") << -1; + QTest::newRow("data7") << QString("") << QString("abcdefg") << -1; + + QTest::newRow("data8") << QString("a") << QString() << 0; + QTest::newRow("data9") << QString("a") << QString("") << 0; + QTest::newRow("data10") << QString("a") << QString("a") << 0; + QTest::newRow("data11") << QString("a") << QString("b") << -1; + QTest::newRow("data12") << QString("a") << QString("abcdefg") << -1; + QTest::newRow("data13") << QString("ab") << QString() << 0; + QTest::newRow("data14") << QString("ab") << QString("") << 0; + QTest::newRow("data15") << QString("ab") << QString("a") << 0; + QTest::newRow("data16") << QString("ab") << QString("b") << 1; + QTest::newRow("data17") << QString("ab") << QString("ab") << 0; + QTest::newRow("data18") << QString("ab") << QString("bc") << -1; + QTest::newRow("data19") << QString("ab") << QString("abcdefg") << -1; + + QTest::newRow("data30") << QString("abc") << QString("a") << 0; + QTest::newRow("data31") << QString("abc") << QString("b") << 1; + QTest::newRow("data32") << QString("abc") << QString("c") << 2; + QTest::newRow("data33") << QString("abc") << QString("d") << -1; + QTest::newRow("data34") << QString("abc") << QString("ab") << 0; + QTest::newRow("data35") << QString("abc") << QString("bc") << 1; + QTest::newRow("data36") << QString("abc") << QString("cd") << -1; + QTest::newRow("data37") << QString("abc") << QString("ac") << -1; + + // sizeof(whale) > 32 + QString whale = "a5zby6cx7dw8evf9ug0th1si2rj3qkp4lomn"; + QString minnow = "zby"; + QTest::newRow("data40") << whale << minnow << 2; + QTest::newRow("data41") << (whale + whale) << minnow << 2; + QTest::newRow("data42") << (minnow + whale) << minnow << 0; + QTest::newRow("data43") << whale << whale << 0; + QTest::newRow("data44") << (whale + whale) << whale << 0; + QTest::newRow("data45") << whale << (whale + whale) << -1; + QTest::newRow("data46") << (whale + whale) << (whale + whale) << 0; + QTest::newRow("data47") << (whale + whale) << (whale + minnow) << -1; + QTest::newRow("data48") << (minnow + whale) << whale << (int)minnow.length(); +} + +void tst_QStringRef::indexOf2() +{ + QFETCH(QString, haystack); + QFETCH(QString, needle); + QFETCH(int, resultpos); + + const QString haystackPadded = QString::fromLatin1(" %1 ").arg(haystack); + const QString needlePadded = QString::fromLatin1(" %1 ").arg(needle); + const QStringRef haystackRef(&haystackPadded, 1, haystack.size()); + const QStringRef needleRef(&needlePadded, 1, needle.size()); + + + int got; + + QCOMPARE(haystack.indexOf(needleRef, 0, Qt::CaseSensitive), resultpos); + QCOMPARE(haystackRef.indexOf(needle, 0, Qt::CaseSensitive), resultpos); + QCOMPARE(haystackRef.indexOf(needleRef, 0, Qt::CaseSensitive), resultpos); + QCOMPARE(haystack.indexOf(needleRef, 0, Qt::CaseInsensitive), resultpos); + QCOMPARE(haystackRef.indexOf(needle, 0, Qt::CaseInsensitive), resultpos); + QCOMPARE(haystackRef.indexOf(needleRef, 0, Qt::CaseInsensitive), resultpos); + if (needle.length() > 0) { + got = haystackRef.lastIndexOf(needle, -1, Qt::CaseSensitive); + QVERIFY(got == resultpos || (resultpos >= 0 && got >= resultpos)); + got = haystackRef.lastIndexOf(needle, -1, Qt::CaseInsensitive); + QVERIFY(got == resultpos || (resultpos >= 0 && got >= resultpos)); + + got = haystack.lastIndexOf(needleRef, -1, Qt::CaseSensitive); + QVERIFY(got == resultpos || (resultpos >= 0 && got >= resultpos)); + got = haystack.lastIndexOf(needleRef, -1, Qt::CaseInsensitive); + QVERIFY(got == resultpos || (resultpos >= 0 && got >= resultpos)); + + got = haystackRef.lastIndexOf(needleRef, -1, Qt::CaseSensitive); + QVERIFY(got == resultpos || (resultpos >= 0 && got >= resultpos)); + got = haystackRef.lastIndexOf(needleRef, -1, Qt::CaseInsensitive); + QVERIFY(got == resultpos || (resultpos >= 0 && got >= resultpos)); + } +} + +void tst_QStringRef::lastIndexOf_data() +{ + QTest::addColumn<QString>("haystack"); + QTest::addColumn<QString>("needle"); + QTest::addColumn<int>("from"); + QTest::addColumn<int>("expected"); + QTest::addColumn<bool>("caseSensitive"); + + QString a = "ABCDEFGHIEfGEFG"; + + QTest::newRow("-1") << a << "G" << a.size() - 1 << 14 << true; + QTest::newRow("1") << a << "G" << - 1 << 14 << true; + QTest::newRow("2") << a << "G" << -3 << 11 << true; + QTest::newRow("3") << a << "G" << -5 << 6 << true; + QTest::newRow("4") << a << "G" << 14 << 14 << true; + QTest::newRow("5") << a << "G" << 13 << 11 << true; + QTest::newRow("6") << a << "B" << a.size() - 1 << 1 << true; + QTest::newRow("6") << a << "B" << - 1 << 1 << true; + QTest::newRow("7") << a << "B" << 1 << 1 << true; + QTest::newRow("8") << a << "B" << 0 << -1 << true; + + QTest::newRow("9") << a << "G" << -1 << a.size()-1 << true; + QTest::newRow("10") << a << "G" << a.size()-1 << a.size()-1 << true; + QTest::newRow("11") << a << "G" << a.size() << -1 << true; + QTest::newRow("12") << a << "A" << 0 << 0 << true; + QTest::newRow("13") << a << "A" << -1*a.size() << 0 << true; + + QTest::newRow("15") << a << "efg" << 0 << -1 << false; + QTest::newRow("16") << a << "efg" << a.size() << -1 << false; + QTest::newRow("17") << a << "efg" << -1 * a.size() << -1 << false; + QTest::newRow("19") << a << "efg" << a.size() - 1 << 12 << false; + QTest::newRow("20") << a << "efg" << 12 << 12 << false; + QTest::newRow("21") << a << "efg" << -12 << -1 << false; + QTest::newRow("22") << a << "efg" << 11 << 9 << false; + + QTest::newRow("24") << "" << "asdf" << -1 << -1 << false; + QTest::newRow("25") << "asd" << "asdf" << -1 << -1 << false; + QTest::newRow("26") << "" << QString() << -1 << -1 << false; + + QTest::newRow("27") << a << "" << a.size() << a.size() << false; + QTest::newRow("28") << a << "" << a.size() + 10 << -1 << false; +} + +void tst_QStringRef::lastIndexOf() +{ + QFETCH(QString, haystack); + QFETCH(QString, needle); + QFETCH(int, from); + QFETCH(int, expected); + QFETCH(bool, caseSensitive); + + const QString haystackPadded = QString::fromLatin1(" %1 ").arg(haystack); + const QString needlePadded = QString::fromLatin1(" %1 ").arg(needle); + const QStringRef haystackRef(&haystackPadded, 1, haystack.size()); + const QStringRef needleRef(&needlePadded, 1, needle.size()); + + Qt::CaseSensitivity cs = (caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); + + QCOMPARE(haystack.lastIndexOf(needleRef, from, cs), expected); + QCOMPARE(haystackRef.lastIndexOf(needle, from, cs), expected); + QCOMPARE(haystackRef.lastIndexOf(needleRef, from, cs), expected); + + + if (cs == Qt::CaseSensitive) { + QCOMPARE(haystack.lastIndexOf(needleRef, from), expected); + QCOMPARE(haystackRef.lastIndexOf(needle, from), expected); + QCOMPARE(haystackRef.lastIndexOf(needleRef, from), expected); + + if (from == -1) { + QCOMPARE(haystack.lastIndexOf(needleRef), expected); + QCOMPARE(haystackRef.lastIndexOf(needle), expected); + QCOMPARE(haystackRef.lastIndexOf(needleRef), expected); + + } + } + if (needle.size() == 1) { + QCOMPARE(haystack.lastIndexOf(needleRef.at(0), from), expected); + QCOMPARE(haystackRef.lastIndexOf(needle.at(0), from), expected); + QCOMPARE(haystackRef.lastIndexOf(needleRef.at(0), from), expected); + } +} + +void tst_QStringRef::count() +{ + const QString a = QString::fromLatin1("ABCDEFGHIEfGEFG"); // 15 chars + CREATE_REF(a); + QCOMPARE(ref.count('A'),1); + QCOMPARE(ref.count('Z'),0); + QCOMPARE(ref.count('E'),3); + QCOMPARE(ref.count('F'),2); + QCOMPARE(ref.count('F',Qt::CaseInsensitive),3); + QCOMPARE(ref.count("FG"),2); + QCOMPARE(ref.count("FG",Qt::CaseInsensitive),3); + QCOMPARE(ref.count(QString(), Qt::CaseInsensitive), 16); + QCOMPARE(ref.count("", Qt::CaseInsensitive), 16); +} + +void tst_QStringRef::contains() +{ + const QString a = QString::fromLatin1("ABCDEFGHIEfGEFG"); // 15 chars + CREATE_REF(a); + QVERIFY(ref.contains('A')); + QVERIFY(!ref.contains('Z')); + QVERIFY(ref.contains('E')); + QVERIFY(ref.contains('F')); + QVERIFY(ref.contains('F',Qt::CaseInsensitive)); + QVERIFY(ref.contains("FG")); + QVERIFY(ref.contains(QString("FG").midRef(0))); + const QString ref2 = QString::fromLatin1(" FG "); + QVERIFY(ref.contains(ref2.midRef(1, 2),Qt::CaseInsensitive)); + QVERIFY(ref.contains(QString(), Qt::CaseInsensitive)); + QVERIFY(ref.contains("", Qt::CaseInsensitive)); // apparently +} + +void tst_QStringRef::startsWith() +{ + { + const QString a = QString::fromLatin1("AB"); + CREATE_REF(a); + QVERIFY(ref.startsWith("A")); + QVERIFY(ref.startsWith("AB")); + QVERIFY(!ref.startsWith("C")); + QVERIFY(!ref.startsWith("ABCDEF")); + QVERIFY(ref.startsWith("")); + QVERIFY(ref.startsWith(QString::null)); + QVERIFY(ref.startsWith('A')); + QVERIFY(ref.startsWith(QLatin1Char('A'))); + QVERIFY(ref.startsWith(QChar('A'))); + QVERIFY(!ref.startsWith('C')); + QVERIFY(!ref.startsWith(QChar())); + QVERIFY(!ref.startsWith(QLatin1Char(0))); + + QVERIFY(ref.startsWith(QLatin1String("A"))); + QVERIFY(ref.startsWith(QLatin1String("AB"))); + QVERIFY(!ref.startsWith(QLatin1String("C"))); + QVERIFY(!ref.startsWith(QLatin1String("ABCDEF"))); + QVERIFY(ref.startsWith(QLatin1String(""))); + QVERIFY(ref.startsWith(QLatin1String(0))); + + QVERIFY(ref.startsWith("A", Qt::CaseSensitive)); + QVERIFY(ref.startsWith("A", Qt::CaseInsensitive)); + QVERIFY(!ref.startsWith("a", Qt::CaseSensitive)); + QVERIFY(ref.startsWith("a", Qt::CaseInsensitive)); + QVERIFY(!ref.startsWith("aB", Qt::CaseSensitive)); + QVERIFY(ref.startsWith("aB", Qt::CaseInsensitive)); + QVERIFY(!ref.startsWith("C", Qt::CaseSensitive)); + QVERIFY(!ref.startsWith("C", Qt::CaseInsensitive)); + QVERIFY(!ref.startsWith("c", Qt::CaseSensitive)); + QVERIFY(!ref.startsWith("c", Qt::CaseInsensitive)); + QVERIFY(!ref.startsWith("abcdef", Qt::CaseInsensitive)); + QVERIFY(ref.startsWith("", Qt::CaseInsensitive)); + QVERIFY(ref.startsWith(QString::null, Qt::CaseInsensitive)); + QVERIFY(ref.startsWith('a', Qt::CaseInsensitive)); + QVERIFY(ref.startsWith('A', Qt::CaseInsensitive)); + QVERIFY(ref.startsWith(QLatin1Char('a'), Qt::CaseInsensitive)); + QVERIFY(ref.startsWith(QChar('a'), Qt::CaseInsensitive)); + QVERIFY(!ref.startsWith('c', Qt::CaseInsensitive)); + QVERIFY(!ref.startsWith(QChar(), Qt::CaseInsensitive)); + QVERIFY(!ref.startsWith(QLatin1Char(0), Qt::CaseInsensitive)); + + QVERIFY(ref.startsWith(QLatin1String("A"), Qt::CaseSensitive)); + QVERIFY(ref.startsWith(QLatin1String("A"), Qt::CaseInsensitive)); + QVERIFY(!ref.startsWith(QLatin1String("a"), Qt::CaseSensitive)); + QVERIFY(ref.startsWith(QLatin1String("a"), Qt::CaseInsensitive)); + QVERIFY(!ref.startsWith(QLatin1String("aB"), Qt::CaseSensitive)); + QVERIFY(ref.startsWith(QLatin1String("aB"), Qt::CaseInsensitive)); + QVERIFY(!ref.startsWith(QLatin1String("C"), Qt::CaseSensitive)); + QVERIFY(!ref.startsWith(QLatin1String("C"), Qt::CaseInsensitive)); + QVERIFY(!ref.startsWith(QLatin1String("c"), Qt::CaseSensitive)); + QVERIFY(!ref.startsWith(QLatin1String("c"), Qt::CaseInsensitive)); + QVERIFY(!ref.startsWith(QLatin1String("abcdef"), Qt::CaseInsensitive)); + QVERIFY(ref.startsWith(QLatin1String(""), Qt::CaseInsensitive)); + QVERIFY(ref.startsWith(QLatin1String(0), Qt::CaseInsensitive)); + QVERIFY(ref.startsWith('A', Qt::CaseSensitive)); + QVERIFY(ref.startsWith(QLatin1Char('A'), Qt::CaseSensitive)); + QVERIFY(ref.startsWith(QChar('A'), Qt::CaseSensitive)); + QVERIFY(!ref.startsWith('a', Qt::CaseSensitive)); + QVERIFY(!ref.startsWith(QChar(), Qt::CaseSensitive)); + QVERIFY(!ref.startsWith(QLatin1Char(0), Qt::CaseSensitive)); + } + { + const QString a = QString::fromLatin1(""); + CREATE_REF(a); + QVERIFY(ref.startsWith("")); + QVERIFY(ref.startsWith(QString::null)); + QVERIFY(!ref.startsWith("ABC")); + + QVERIFY(ref.startsWith(QLatin1String(""))); + QVERIFY(ref.startsWith(QLatin1String(0))); + QVERIFY(!ref.startsWith(QLatin1String("ABC"))); + + QVERIFY(!ref.startsWith(QLatin1Char(0))); + QVERIFY(!ref.startsWith(QLatin1Char('x'))); + QVERIFY(!ref.startsWith(QChar())); + } + { + const QStringRef ref; + QVERIFY(!ref.startsWith("")); + QVERIFY(ref.startsWith(QString::null)); + QVERIFY(!ref.startsWith("ABC")); + + QVERIFY(!ref.startsWith(QLatin1String(""))); + QVERIFY(ref.startsWith(QLatin1String(0))); + QVERIFY(!ref.startsWith(QLatin1String("ABC"))); + + QVERIFY(!ref.startsWith(QLatin1Char(0))); + QVERIFY(!ref.startsWith(QLatin1Char('x'))); + QVERIFY(!ref.startsWith(QChar())); + } +} + +void tst_QStringRef::endsWith() +{ + { + const QString a = QString::fromLatin1("AB"); + CREATE_REF(a); + QVERIFY(ref.endsWith("B")); + QVERIFY(ref.endsWith("AB")); + QVERIFY(!ref.endsWith("C")); + QVERIFY(!ref.endsWith("ABCDEF")); + QVERIFY(ref.endsWith("")); + QVERIFY(ref.endsWith(QString::null)); + QVERIFY(ref.endsWith('B')); + QVERIFY(ref.endsWith(QLatin1Char('B'))); + QVERIFY(ref.endsWith(QChar('B'))); + QVERIFY(!ref.endsWith('C')); + QVERIFY(!ref.endsWith(QChar())); + QVERIFY(!ref.endsWith(QLatin1Char(0))); + + QVERIFY(ref.endsWith(QLatin1String("B"))); + QVERIFY(ref.endsWith(QLatin1String("AB"))); + QVERIFY(!ref.endsWith(QLatin1String("C"))); + QVERIFY(!ref.endsWith(QLatin1String("ABCDEF"))); + QVERIFY(ref.endsWith(QLatin1String(""))); + QVERIFY(ref.endsWith(QLatin1String(0))); + + QVERIFY(ref.endsWith("B", Qt::CaseSensitive)); + QVERIFY(ref.endsWith("B", Qt::CaseInsensitive)); + QVERIFY(!ref.endsWith("b", Qt::CaseSensitive)); + QVERIFY(ref.endsWith("b", Qt::CaseInsensitive)); + QVERIFY(!ref.endsWith("aB", Qt::CaseSensitive)); + QVERIFY(ref.endsWith("aB", Qt::CaseInsensitive)); + QVERIFY(!ref.endsWith("C", Qt::CaseSensitive)); + QVERIFY(!ref.endsWith("C", Qt::CaseInsensitive)); + QVERIFY(!ref.endsWith("c", Qt::CaseSensitive)); + QVERIFY(!ref.endsWith("c", Qt::CaseInsensitive)); + QVERIFY(!ref.endsWith("abcdef", Qt::CaseInsensitive)); + QVERIFY(ref.endsWith("", Qt::CaseInsensitive)); + QVERIFY(ref.endsWith(QString::null, Qt::CaseInsensitive)); + QVERIFY(ref.endsWith('b', Qt::CaseInsensitive)); + QVERIFY(ref.endsWith('B', Qt::CaseInsensitive)); + QVERIFY(ref.endsWith(QLatin1Char('b'), Qt::CaseInsensitive)); + QVERIFY(ref.endsWith(QChar('b'), Qt::CaseInsensitive)); + QVERIFY(!ref.endsWith('c', Qt::CaseInsensitive)); + QVERIFY(!ref.endsWith(QChar(), Qt::CaseInsensitive)); + QVERIFY(!ref.endsWith(QLatin1Char(0), Qt::CaseInsensitive)); + + QVERIFY(ref.endsWith(QLatin1String("B"), Qt::CaseSensitive)); + QVERIFY(ref.endsWith(QLatin1String("B"), Qt::CaseInsensitive)); + QVERIFY(!ref.endsWith(QLatin1String("b"), Qt::CaseSensitive)); + QVERIFY(ref.endsWith(QLatin1String("b"), Qt::CaseInsensitive)); + QVERIFY(!ref.endsWith(QLatin1String("aB"), Qt::CaseSensitive)); + QVERIFY(ref.endsWith(QLatin1String("aB"), Qt::CaseInsensitive)); + QVERIFY(!ref.endsWith(QLatin1String("C"), Qt::CaseSensitive)); + QVERIFY(!ref.endsWith(QLatin1String("C"), Qt::CaseInsensitive)); + QVERIFY(!ref.endsWith(QLatin1String("c"), Qt::CaseSensitive)); + QVERIFY(!ref.endsWith(QLatin1String("c"), Qt::CaseInsensitive)); + QVERIFY(!ref.endsWith(QLatin1String("abcdef"), Qt::CaseInsensitive)); + QVERIFY(ref.endsWith(QLatin1String(""), Qt::CaseInsensitive)); + QVERIFY(ref.endsWith(QLatin1String(0), Qt::CaseInsensitive)); + QVERIFY(ref.endsWith('B', Qt::CaseSensitive)); + QVERIFY(ref.endsWith(QLatin1Char('B'), Qt::CaseSensitive)); + QVERIFY(ref.endsWith(QChar('B'), Qt::CaseSensitive)); + QVERIFY(!ref.endsWith('b', Qt::CaseSensitive)); + QVERIFY(!ref.endsWith(QChar(), Qt::CaseSensitive)); + QVERIFY(!ref.endsWith(QLatin1Char(0), Qt::CaseSensitive)); + + } + { + const QString a = QString::fromLatin1(""); + CREATE_REF(a); + QVERIFY(ref.endsWith("")); + QVERIFY(ref.endsWith(QString::null)); + QVERIFY(!ref.endsWith("ABC")); + QVERIFY(!ref.endsWith(QLatin1Char(0))); + QVERIFY(!ref.endsWith(QLatin1Char('x'))); + QVERIFY(!ref.endsWith(QChar())); + + QVERIFY(ref.endsWith(QLatin1String(""))); + QVERIFY(ref.endsWith(QLatin1String(0))); + QVERIFY(!ref.endsWith(QLatin1String("ABC"))); + } + + { + QStringRef ref; + QVERIFY(!ref.endsWith("")); + QVERIFY(ref.endsWith(QString::null)); + QVERIFY(!ref.endsWith("ABC")); + + QVERIFY(!ref.endsWith(QLatin1String(""))); + QVERIFY(ref.endsWith(QLatin1String(0))); + QVERIFY(!ref.endsWith(QLatin1String("ABC"))); + + QVERIFY(!ref.endsWith(QLatin1Char(0))); + QVERIFY(!ref.endsWith(QLatin1Char('x'))); + QVERIFY(!ref.endsWith(QChar())); + } +} + +void tst_QStringRef::operator_eqeq_nullstring() +{ + /* Some of these might not be all that logical but it's the behaviour we've had since 3.0.0 + so we should probably stick with it. */ + + QVERIFY(QStringRef() == ""); + QVERIFY("" == QStringRef()); + + QVERIFY(QString("") == ""); + QVERIFY("" == QString("")); + + QVERIFY(QStringRef().size() == 0); + + QVERIFY(QString("").size() == 0); + + QVERIFY(QStringRef() == QString("")); + QVERIFY(QString("") == QString()); +} + +static inline int sign(int x) +{ + return x == 0 ? 0 : (x < 0 ? -1 : 1); +} + +void tst_QStringRef::compare_data() +{ + QTest::addColumn<QString>("s1"); + QTest::addColumn<QString>("s2"); + QTest::addColumn<int>("csr"); // case sensitive result + QTest::addColumn<int>("cir"); // case insensitive result + + + // null strings + QTest::newRow("data0") << QString("") << QString("") << 0 << 0; + QTest::newRow("data1") << QString("a") << QString("") << 1 << 1; + QTest::newRow("data2") << QString("") << QString("a") << -1 << -1; + + // equal length + QTest::newRow("data3") << QString("abc") << QString("abc") << 0 << 0; + QTest::newRow("data4") << QString("abC") << QString("abc") << -1 << 0; + QTest::newRow("data5") << QString("abc") << QString("abC") << 1 << 0; + + // different length + QTest::newRow("data6") << QString("abcdef") << QString("abc") << 1 << 1; + QTest::newRow("data6") << QString("abCdef") << QString("abc") << -1 << 1; + QTest::newRow("data7") << QString("abc") << QString("abcdef") << -1 << -1; + + QString upper; + upper += QChar(QChar::highSurrogate(0x10400)); + upper += QChar(QChar::lowSurrogate(0x10400)); + QString lower; + lower += QChar(QChar::highSurrogate(0x10428)); + lower += QChar(QChar::lowSurrogate(0x10428)); + QTest::newRow("data8") << upper << lower << -1 << 0; + + // embedded nulls + // These dont work as of now. Its OK that these dont work since \0 is not a valid unicode + /*QTest::newRow("data9") << QString(QByteArray("\0", 1)) << QString(QByteArray("\0", 1)) << 0 << 0; + QTest::newRow("data10") << QString(QByteArray("\0", 1)) << QString("") << 1 << 1; + QTest::newRow("data11") << QString("") << QString(QByteArray("\0", 1)) << -1 << -1; + QTest::newRow("data12") << QString("ab\0c") << QString(QByteArray("ab\0c", 4)) << 0 << 0; + QTest::newRow("data13") << QString(QByteArray("ab\0c", 4)) << QString("abc") << -1 << -1; + QTest::newRow("data14") << QString("abc") << QString(QByteArray("ab\0c", 4)) << 1 << 1;*/ +} + +static bool isLatin(const QString &s) +{ + for (int i = 0; i < s.length(); ++i) + if (s.at(i).unicode() > 0xff) + return false; + return true; +} + +void tst_QStringRef::compare() +{ + QFETCH(QString, s1); + QFETCH(QString, s2); + QFETCH(int, csr); + QFETCH(int, cir); + + QStringRef r1(&s1, 0, s1.length()); + QStringRef r2(&s2, 0, s2.length()); + + QCOMPARE(sign(QString::compare(s1, s2)), csr); + QCOMPARE(sign(QStringRef::compare(r1, r2)), csr); + QCOMPARE(sign(s1.compare(s2)), csr); + QCOMPARE(sign(s1.compare(r2)), csr); + QCOMPARE(sign(r1.compare(r2)), csr); + + QCOMPARE(sign(s1.compare(s2, Qt::CaseSensitive)), csr); + QCOMPARE(sign(s1.compare(s2, Qt::CaseInsensitive)), cir); + QCOMPARE(sign(s1.compare(r2, Qt::CaseSensitive)), csr); + QCOMPARE(sign(s1.compare(r2, Qt::CaseInsensitive)), cir); + QCOMPARE(sign(r1.compare(r2, Qt::CaseSensitive)), csr); + QCOMPARE(sign(r1.compare(r2, Qt::CaseInsensitive)), cir); + + QCOMPARE(sign(QString::compare(s1, s2, Qt::CaseSensitive)), csr); + QCOMPARE(sign(QString::compare(s1, s2, Qt::CaseInsensitive)), cir); + QCOMPARE(sign(QString::compare(s1, r2, Qt::CaseSensitive)), csr); + QCOMPARE(sign(QString::compare(s1, r2, Qt::CaseInsensitive)), cir); + QCOMPARE(sign(QStringRef::compare(r1, r2, Qt::CaseSensitive)), csr); + QCOMPARE(sign(QStringRef::compare(r1, r2, Qt::CaseInsensitive)), cir); + + if (!cir) { + QCOMPARE(s1.toCaseFolded(), s2.toCaseFolded()); + } + + if (isLatin(s2)) { + QCOMPARE(sign(QString::compare(s1, QLatin1String(s2.toLatin1()))), csr); + QCOMPARE(sign(QString::compare(s1, QLatin1String(s2.toLatin1()), Qt::CaseInsensitive)), cir); + QCOMPARE(sign(QStringRef::compare(r1, QLatin1String(s2.toLatin1()))), csr); + QCOMPARE(sign(QStringRef::compare(r1, QLatin1String(s2.toLatin1()), Qt::CaseInsensitive)), cir); + } + + if (isLatin(s1)) { + QCOMPARE(sign(QString::compare(QLatin1String(s1.toLatin1()), s2)), csr); + QCOMPARE(sign(QString::compare(QLatin1String(s1.toLatin1()), s2, Qt::CaseInsensitive)), cir); + } +} + +QTEST_APPLESS_MAIN(tst_QStringRef) + +#include "tst_qstringref.moc" diff --git a/tests/auto/qtabbar/tst_qtabbar.cpp b/tests/auto/qtabbar/tst_qtabbar.cpp index ac3de20..84a6991 100644 --- a/tests/auto/qtabbar/tst_qtabbar.cpp +++ b/tests/auto/qtabbar/tst_qtabbar.cpp @@ -76,6 +76,7 @@ private slots: void setElideMode_data(); void setElideMode(); + void sizeHints(); void setUsesScrollButtons_data(); void setUsesScrollButtons(); @@ -280,6 +281,46 @@ void tst_QTabBar::setElideMode() QTEST(int(tabBar.elideMode()), "expectedMode"); } +void tst_QTabBar::sizeHints() +{ + QTabBar tabBar; + QSKIP("To be fixed on Mac (font size below not large enough) and Linux QWS (probably too large for the screen).", SkipSingle); + tabBar.setFont(QFont("Arial", 10)); + tabBar.addTab("tab 01"); + tabBar.addTab("tab 02"); + tabBar.addTab("tab 03"); + tabBar.addTab("tab 04"); + tabBar.addTab("tab 05"); + tabBar.addTab("tab 06"); + tabBar.addTab("This is tab7"); + tabBar.addTab("This is tab8"); + tabBar.addTab("This is tab9 with a very long title"); + + // No eliding and no scrolling -> tabbar becomes very wide + tabBar.setUsesScrollButtons(false); + tabBar.setElideMode(Qt::ElideNone); +// qDebug() << tabBar.minimumSizeHint() << tabBar.sizeHint(); + QVERIFY(tabBar.minimumSizeHint().width() > 700); + QVERIFY(tabBar.sizeHint().width() > 700); + + // Scrolling enabled -> no reason to become very wide + tabBar.setUsesScrollButtons(true); + // qDebug() << tabBar.minimumSizeHint() << tabBar.sizeHint(); + QVERIFY(tabBar.minimumSizeHint().width() < 200); + QVERIFY(tabBar.sizeHint().width() > 700); // unchanged + + // Eliding enabled -> no reason to become very wide + tabBar.setUsesScrollButtons(false); + tabBar.setElideMode(Qt::ElideRight); +// qDebug() << tabBar.minimumSizeHint() << tabBar.sizeHint(); + QVERIFY(tabBar.minimumSizeHint().width() < 500); + QVERIFY(tabBar.sizeHint().width() > 700); // unchanged + + tabBar.addTab("This is tab10 with a very long title"); + QVERIFY(tabBar.minimumSizeHint().width() < 600); + QVERIFY(tabBar.sizeHint().width() > 700); // unchanged +} + void tst_QTabBar::setUsesScrollButtons_data() { QTest::addColumn<int>("usesArrows"); diff --git a/tests/auto/qtabwidget/tst_qtabwidget.cpp b/tests/auto/qtabwidget/tst_qtabwidget.cpp index 504579f..27581b0 100644 --- a/tests/auto/qtabwidget/tst_qtabwidget.cpp +++ b/tests/auto/qtabwidget/tst_qtabwidget.cpp @@ -45,6 +45,7 @@ #include <qdebug.h> #include <qapplication.h> #include <qlabel.h> +#include <QtGui/qboxlayout.h> //TESTED_CLASS= //TESTED_FILES= @@ -120,6 +121,9 @@ class tst_QTabWidget:public QObject { void clear(); void keyboardNavigation(); void paintEventCount(); + void minimumSizeHint(); + void heightForWidth_data(); + void heightForWidth(); private: int addPage(); @@ -624,6 +628,74 @@ void tst_QTabWidget::paintEventCount() QCOMPARE(tab2->count, 1); } +void tst_QTabWidget::minimumSizeHint() +{ + QTabWidget tw; + QWidget *page = new QWidget; + QVBoxLayout *lay = new QVBoxLayout; + + QLabel *label = new QLabel(QLatin1String("XXgypq lorem ipsum must be long, must be long. lorem ipsumMMMW")); + lay->addWidget(label); + + page->setLayout(lay); + + tw.addTab(page, QLatin1String("page1")); + + tw.show(); + QTest::qWaitForWindowShown(&tw); + tw.resize(tw.minimumSizeHint()); + + QSize minSize = label->minimumSizeHint(); + QSize actSize = label->geometry().size(); + QVERIFY(minSize.width() <= actSize.width()); + QVERIFY(minSize.height() <= actSize.height()); +} + +void tst_QTabWidget::heightForWidth_data() +{ + QTest::addColumn<int>("tabPosition"); + QTest::newRow("West") << int(QTabWidget::West); + QTest::newRow("North") << int(QTabWidget::North); + QTest::newRow("East") << int(QTabWidget::East); + QTest::newRow("South") << int(QTabWidget::South); +} + +void tst_QTabWidget::heightForWidth() +{ + QFETCH(int, tabPosition); + + QWidget *window = new QWidget; + QVBoxLayout *lay = new QVBoxLayout(window); + lay->setMargin(0); + lay->setSpacing(0); + QTabWidget *tabWid = new QTabWidget(window); + QWidget *w = new QWidget; + tabWid->addTab(w, QLatin1String("HFW page")); + tabWid->setTabPosition(QTabWidget::TabPosition(tabPosition)); + QVBoxLayout *lay2 = new QVBoxLayout(w); + QLabel *label = new QLabel("Label with wordwrap turned on makes it trade height for width." + " Make it a really long text so that it spans on several lines" + " when the label is on its narrowest." + " I don't like to repeat myself." + " I don't like to repeat myself." + " I don't like to repeat myself." + " I don't like to repeat myself." + ); + label->setWordWrap(true); + lay2->addWidget(label); + lay2->setMargin(0); + + lay->addWidget(tabWid); + int h = window->heightForWidth(160); + window->resize(160, h); + window->show(); + + QTest::qWaitForWindowShown(window); + QVERIFY(label->height() >= label->heightForWidth(label->width())); + + delete window; +} + QTEST_MAIN(tst_QTabWidget) #include "tst_qtabwidget.moc" diff --git a/tests/auto/qtextlayout/tst_qtextlayout.cpp b/tests/auto/qtextlayout/tst_qtextlayout.cpp index 659ba1a..dcc43d0 100644 --- a/tests/auto/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/qtextlayout/tst_qtextlayout.cpp @@ -85,6 +85,7 @@ private slots: void cursorToXForSetColumns(); void defaultWordSeparators_data(); void defaultWordSeparators(); + void cursorMovementFromInvalidPositions(); void cursorMovementInsideSpaces(); void charWordStopOnLineSeparator(); void xToCursorAtEndOfLine(); @@ -544,6 +545,10 @@ void tst_QTextLayout::defaultWordSeparators_data() QTest::newRow("lineseparator") << QString::fromLatin1("abcd") + QString(QChar::LineSeparator) + QString::fromLatin1("efgh") << 0 << 5; + + QTest::newRow("empty") + << QString() + << 0 << 0; } void tst_QTextLayout::defaultWordSeparators() @@ -557,12 +562,31 @@ void tst_QTextLayout::defaultWordSeparators() QCOMPARE(layout.previousCursorPosition(endPos, QTextLayout::SkipWords), startPos); } +void tst_QTextLayout::cursorMovementFromInvalidPositions() +{ + int badpos = 10000; + + QTextLayout layout("ABC", testFont); + + QCOMPARE(layout.previousCursorPosition(-badpos, QTextLayout::SkipCharacters), -badpos); + QCOMPARE(layout.nextCursorPosition(-badpos, QTextLayout::SkipCharacters), -badpos); + + QCOMPARE(layout.previousCursorPosition(badpos, QTextLayout::SkipCharacters), badpos); + QCOMPARE(layout.nextCursorPosition(badpos, QTextLayout::SkipCharacters), badpos); +} + void tst_QTextLayout::cursorMovementInsideSpaces() { QTextLayout layout("ABC DEF", testFont); QCOMPARE(layout.previousCursorPosition(6, QTextLayout::SkipWords), 0); QCOMPARE(layout.nextCursorPosition(6, QTextLayout::SkipWords), 15); + + + QTextLayout layout2("ABC\t\t\t\t\t\t\t\t\t\t\t\tDEF", testFont); + + QCOMPARE(layout2.previousCursorPosition(6, QTextLayout::SkipWords), 0); + QCOMPARE(layout2.nextCursorPosition(6, QTextLayout::SkipWords), 15); } void tst_QTextLayout::charWordStopOnLineSeparator() diff --git a/tests/auto/qtextlist/tst_qtextlist.cpp b/tests/auto/qtextlist/tst_qtextlist.cpp index 3e92836..8ad0898 100644 --- a/tests/auto/qtextlist/tst_qtextlist.cpp +++ b/tests/auto/qtextlist/tst_qtextlist.cpp @@ -67,6 +67,9 @@ private slots: void item(); void autoNumbering(); void autoNumberingRTL(); + void autoNumberingPrefixAndSuffix(); + void autoNumberingPrefixAndSuffixRTL(); + void autoNumberingPrefixAndSuffixHtmlExportImport(); void romanNumbering(); void romanNumberingLimit(); void formatChange(); @@ -128,6 +131,76 @@ void tst_QTextList::autoNumbering() QVERIFY(cursor.currentList()->itemText(cursor.block()) == "ab."); } +void tst_QTextList::autoNumberingPrefixAndSuffix() +{ + QTextListFormat fmt; + fmt.setStyle(QTextListFormat::ListLowerAlpha); + fmt.setNumberPrefix("-"); + fmt.setNumberSuffix(")"); + QTextList *list = cursor.createList(fmt); + QVERIFY(list); + + for (int i = 0; i < 27; ++i) + cursor.insertBlock(); + + QVERIFY(list->count() == 28); + + QVERIFY(cursor.currentList()); + QVERIFY(cursor.currentList()->itemNumber(cursor.block()) == 27); + QVERIFY(cursor.currentList()->itemText(cursor.block()) == "-ab)"); +} + +void tst_QTextList::autoNumberingPrefixAndSuffixRTL() +{ + QTextBlockFormat bfmt; + bfmt.setLayoutDirection(Qt::RightToLeft); + cursor.setBlockFormat(bfmt); + + QTextListFormat fmt; + fmt.setStyle(QTextListFormat::ListUpperAlpha); + fmt.setNumberPrefix("-"); + fmt.setNumberSuffix("*"); + QTextList *list = cursor.createList(fmt); + QVERIFY(list); + + cursor.insertBlock(); + + QVERIFY(list->count() == 2); + + QVERIFY(cursor.currentList()->itemText(cursor.block()) == "*B-"); +} + +void tst_QTextList::autoNumberingPrefixAndSuffixHtmlExportImport() +{ + QTextListFormat fmt; + fmt.setStyle(QTextListFormat::ListLowerAlpha); + fmt.setNumberPrefix("\""); + fmt.setNumberSuffix("#"); + fmt.setIndent(10); + // FIXME: Would like to test "'" but there's a problem in the css parser (Scanner::preprocess + // is called before the values are being parsed), so the quoting does not work. + QTextList *list = cursor.createList(fmt); + QVERIFY(list); + + for (int i = 0; i < 27; ++i) + cursor.insertBlock(); + + QVERIFY(list->count() == 28); + + QString htmlExport = doc->toHtml(); + QTextDocument importDoc; + importDoc.setHtml(htmlExport); + + QTextCursor importCursor(&importDoc); + for (int i = 0; i < 27; ++i) + importCursor.movePosition(QTextCursor::NextBlock); + + QVERIFY(importCursor.currentList()); + QVERIFY(importCursor.currentList()->itemNumber(importCursor.block()) == 27); + QVERIFY(importCursor.currentList()->itemText(importCursor.block()) == "\"ab#"); + QVERIFY(importCursor.currentList()->format().indent() == 10); +} + void tst_QTextList::autoNumberingRTL() { QTextBlockFormat bfmt; diff --git a/tests/auto/qthreadpool/tst_qthreadpool.cpp b/tests/auto/qthreadpool/tst_qthreadpool.cpp index 7c8b410..cd6070f 100644 --- a/tests/auto/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/qthreadpool/tst_qthreadpool.cpp @@ -89,6 +89,7 @@ private slots: void tryStartPeakThreadCount(); void tryStartCount(); void waitForDone(); + void waitForDoneTimeout(); void destroyingWaitsForTasksToFinish(); void stressTest(); }; @@ -774,6 +775,32 @@ void tst_QThreadPool::waitForDone() } } +void tst_QThreadPool::waitForDoneTimeout() +{ + class BlockedTask : public QRunnable + { + public: + QMutex mutex; + BlockedTask() { setAutoDelete(false); } + + void run() + { + mutex.lock(); + mutex.unlock(); + QTest::qSleep(50); + } + }; + + QThreadPool threadPool; + + BlockedTask *task = new BlockedTask; + task->mutex.lock(); + threadPool.start(task); + QVERIFY(!threadPool.waitForDone(100)); + task->mutex.unlock(); + QVERIFY(threadPool.waitForDone(400)); +} + void tst_QThreadPool::destroyingWaitsForTasksToFinish() { QTime total, pass; diff --git a/tests/auto/qtipc/qsharedmemory/tst_qsharedmemory.cpp b/tests/auto/qtipc/qsharedmemory/tst_qsharedmemory.cpp index 1f65ae7..dc071ab 100644 --- a/tests/auto/qtipc/qsharedmemory/tst_qsharedmemory.cpp +++ b/tests/auto/qtipc/qsharedmemory/tst_qsharedmemory.cpp @@ -225,11 +225,17 @@ void tst_QSharedMemory::key_data() { QTest::addColumn<QString>("constructorKey"); QTest::addColumn<QString>("setKey"); - - QTest::newRow("null, null") << QString() << QString(); - QTest::newRow("null, one") << QString() << QString("one"); - QTest::newRow("one, two") << QString("one") << QString("two"); - QTest::newRow("invalid") << QString("o/e") << QString("t/o"); + QTest::addColumn<QString>("setNativeKey"); + + QTest::newRow("null, null, null") << QString() << QString() << QString(); + QTest::newRow("one, null, null") << QString("one") << QString() << QString(); + QTest::newRow("null, one, null") << QString() << QString("one") << QString(); + QTest::newRow("null, null, one") << QString() << QString() << QString("one"); + QTest::newRow("one, two, null") << QString("one") << QString("two") << QString(); + QTest::newRow("one, null, two") << QString("one") << QString() << QString("two"); + QTest::newRow("null, one, two") << QString() << QString("one") << QString("two"); + QTest::newRow("one, two, three") << QString("one") << QString("two") << QString("three"); + QTest::newRow("invalid") << QString("o/e") << QString("t/o") << QString("|x"); } /*! @@ -239,11 +245,17 @@ void tst_QSharedMemory::key() { QFETCH(QString, constructorKey); QFETCH(QString, setKey); + QFETCH(QString, setNativeKey); QSharedMemory sm(constructorKey); QCOMPARE(sm.key(), constructorKey); + QCOMPARE(sm.nativeKey().isEmpty(), constructorKey.isEmpty()); sm.setKey(setKey); QCOMPARE(sm.key(), setKey); + QCOMPARE(sm.nativeKey().isEmpty(), setKey.isEmpty()); + sm.setNativeKey(setNativeKey); + QVERIFY(sm.key().isNull()); + QCOMPARE(sm.nativeKey(), setNativeKey); QCOMPARE(sm.isAttached(), false); QCOMPARE(sm.error(), QSharedMemory::NoError); @@ -262,7 +274,7 @@ void tst_QSharedMemory::create_data() QTest::addColumn<QSharedMemory::SharedMemoryError>("error"); QTest::newRow("null key") << QString() << 1024 - << false << QSharedMemory::LockError; + << false << QSharedMemory::KeyError; QTest::newRow("-1 size") << QString("negsize") << -1 << false << QSharedMemory::InvalidSize; QTest::newRow("nor size") << QString("norsize") << 1024 @@ -302,7 +314,7 @@ void tst_QSharedMemory::attach_data() QTest::addColumn<bool>("exists"); QTest::addColumn<QSharedMemory::SharedMemoryError>("error"); - QTest::newRow("null key") << QString() << false << QSharedMemory::LockError; + QTest::newRow("null key") << QString() << false << QSharedMemory::KeyError; QTest::newRow("doesn't exists") << QString("doesntexists") << false << QSharedMemory::NotFound; QTest::newRow("already exists") << QString(EXISTING_SHARE) << true << QSharedMemory::NoError; } diff --git a/tests/auto/qudpsocket/tst_qudpsocket.cpp b/tests/auto/qudpsocket/tst_qudpsocket.cpp index abed55c..32fab6b 100644 --- a/tests/auto/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/qudpsocket/tst_qudpsocket.cpp @@ -50,11 +50,13 @@ #include <qhostinfo.h> #include <qmap.h> #include <QNetworkProxy> +#include <QNetworkInterface> #include <qstringlist.h> #include "../network-settings.h" Q_DECLARE_METATYPE(QHostAddress) +Q_DECLARE_METATYPE(QNetworkInterface) //TESTED_CLASS= //TESTED_FILES= @@ -94,6 +96,18 @@ private slots: void outOfProcessConnectedClientServerTest(); void outOfProcessUnconnectedClientServerTest(); void zeroLengthDatagram(); + void multicastTtlOption_data(); + void multicastTtlOption(); + void multicastLoopbackOption_data(); + void multicastLoopbackOption(); + void multicastJoinBeforeBind_data(); + void multicastJoinBeforeBind(); + void multicastLeaveAfterClose_data(); + void multicastLeaveAfterClose(); + void setMulticastInterface_data(); + void setMulticastInterface(); + void multicast_data(); + void multicast(); protected slots: void empty_readyReadSlot(); @@ -844,5 +858,242 @@ void tst_QUdpSocket::zeroLengthDatagram() QCOMPARE(receiver.readDatagram(&buf, 1), qint64(0)); } +void tst_QUdpSocket::multicastTtlOption_data() +{ + QTest::addColumn<QHostAddress>("bindAddress"); + QTest::addColumn<int>("ttl"); + QTest::addColumn<int>("expected"); + + QList<QHostAddress> addresses; + addresses += QHostAddress(QHostAddress::Any); + addresses += QHostAddress(QHostAddress::AnyIPv6); + + foreach (const QHostAddress &address, addresses) { + QTest::newRow(QString("%1 0").arg(address.toString()).toAscii()) << address << 0 << 0; + QTest::newRow(QString("%1 1").arg(address.toString()).toAscii()) << address << 1 << 1; + QTest::newRow(QString("%1 2").arg(address.toString()).toAscii()) << address << 2 << 2; + QTest::newRow(QString("%1 128").arg(address.toString()).toAscii()) << address << 128 << 128; + QTest::newRow(QString("%1 255").arg(address.toString()).toAscii()) << address << 255 << 255; + QTest::newRow(QString("%1 1024").arg(address.toString()).toAscii()) << address << 1024 << 1; + } +} + +void tst_QUdpSocket::multicastTtlOption() +{ + QFETCH_GLOBAL(bool, setProxy); + QFETCH(QHostAddress, bindAddress); + QFETCH(int, ttl); + QFETCH(int, expected); + if (setProxy) { + // UDP multicast does not work with proxies + expected = 0; + } + + QUdpSocket udpSocket; + // bind, but ignore the result, we are only interested in initializing the socket + (void) udpSocket.bind(bindAddress, 0); + udpSocket.setSocketOption(QUdpSocket::MulticastTtlOption, ttl); + QCOMPARE(udpSocket.socketOption(QUdpSocket::MulticastTtlOption).toInt(), expected); +} + +void tst_QUdpSocket::multicastLoopbackOption_data() +{ + QTest::addColumn<QHostAddress>("bindAddress"); + QTest::addColumn<int>("loopback"); + QTest::addColumn<int>("expected"); + + QList<QHostAddress> addresses; + addresses += QHostAddress(QHostAddress::Any); + addresses += QHostAddress(QHostAddress::AnyIPv6); + + foreach (const QHostAddress &address, addresses) { + QTest::newRow(QString("%1 0").arg(address.toString()).toAscii()) << address << 0 << 0; + QTest::newRow(QString("%1 1").arg(address.toString()).toAscii()) << address << 1 << 1; + QTest::newRow(QString("%1 2").arg(address.toString()).toAscii()) << address << 2 << 1; + QTest::newRow(QString("%1 0 again").arg(address.toString()).toAscii()) << address << 0 << 0; + QTest::newRow(QString("%1 2 again").arg(address.toString()).toAscii()) << address << 2 << 1; + QTest::newRow(QString("%1 0 last time").arg(address.toString()).toAscii()) << address << 0 << 0; + QTest::newRow(QString("%1 1 again").arg(address.toString()).toAscii()) << address << 1 << 1; + } +} + +void tst_QUdpSocket::multicastLoopbackOption() +{ + QFETCH_GLOBAL(bool, setProxy); + QFETCH(QHostAddress, bindAddress); + QFETCH(int, loopback); + QFETCH(int, expected); + if (setProxy) { + // UDP multicast does not work with proxies + expected = 0; + } + + QUdpSocket udpSocket; + // bind, but ignore the result, we are only interested in initializing the socket + (void) udpSocket.bind(bindAddress, 0); + udpSocket.setSocketOption(QUdpSocket::MulticastLoopbackOption, loopback); + QCOMPARE(udpSocket.socketOption(QUdpSocket::MulticastLoopbackOption).toInt(), expected); +} + +void tst_QUdpSocket::multicastJoinBeforeBind_data() +{ + QTest::addColumn<QHostAddress>("groupAddress"); + QTest::newRow("valid ipv4 group address") << QHostAddress("239.255.118.62"); + QTest::newRow("invalid ipv4 group address") << QHostAddress(QHostAddress::Broadcast); + QTest::newRow("valid ipv6 group address") << QHostAddress("FF01::114"); + QTest::newRow("invalid ipv6 group address") << QHostAddress(QHostAddress::AnyIPv6); +} + +void tst_QUdpSocket::multicastJoinBeforeBind() +{ + QFETCH(QHostAddress, groupAddress); + + QUdpSocket udpSocket; + // cannot join group before binding + QTest::ignoreMessage(QtWarningMsg, "QUdpSocket::joinMulticastGroup() called on a QUdpSocket when not in QUdpSocket::BoundState"); + QVERIFY(!udpSocket.joinMulticastGroup(groupAddress)); +} + +void tst_QUdpSocket::multicastLeaveAfterClose_data() +{ + QTest::addColumn<QHostAddress>("groupAddress"); + QTest::newRow("valid ipv4 group address") << QHostAddress("239.255.118.62"); + QTest::newRow("valid ipv6 group address") << QHostAddress("FF01::114"); +} + +void tst_QUdpSocket::multicastLeaveAfterClose() +{ + QFETCH_GLOBAL(bool, setProxy); + QFETCH(QHostAddress, groupAddress); + if (setProxy) { + QSKIP("UDP Multicast does not work with proxies", SkipAll); + } + + QUdpSocket udpSocket; + QVERIFY2(udpSocket.bind(groupAddress, 0), + qPrintable(udpSocket.errorString())); + QVERIFY2(udpSocket.joinMulticastGroup(groupAddress), + qPrintable(udpSocket.errorString())); + udpSocket.close(); + QTest::ignoreMessage(QtWarningMsg, "QUdpSocket::leaveMulticastGroup() called on a QUdpSocket when not in QUdpSocket::BoundState"); + QVERIFY(!udpSocket.leaveMulticastGroup(groupAddress)); +} + +void tst_QUdpSocket::setMulticastInterface_data() +{ + QTest::addColumn<QNetworkInterface>("iface"); + QTest::addColumn<QHostAddress>("address"); + QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces(); + foreach (const QNetworkInterface &iface, interfaces) { + foreach (const QNetworkAddressEntry &entry, iface.addressEntries()) { + QTest::newRow(QString("%1:%2").arg(iface.name()).arg(entry.ip().toString()).toAscii()) + << iface + << entry.ip(); + } + } +} + +void tst_QUdpSocket::setMulticastInterface() +{ + QFETCH_GLOBAL(bool, setProxy); + QFETCH(QNetworkInterface, iface); + QFETCH(QHostAddress, address); + + QUdpSocket udpSocket; + // bind initializes the socket + bool bound = udpSocket.bind((address.protocol() == QAbstractSocket::IPv6Protocol + ? QHostAddress(QHostAddress::AnyIPv6) + : QHostAddress(QHostAddress::Any)), + 0); + if (!bound) + QTest::ignoreMessage(QtWarningMsg, "QUdpSocket::setMulticastInterface() called on a QUdpSocket when not in QUdpSocket::BoundState"); + udpSocket.setMulticastInterface(iface); + if (!bound) + QTest::ignoreMessage(QtWarningMsg, "QUdpSocket::multicastInterface() called on a QUdpSocket when not in QUdpSocket::BoundState"); + QNetworkInterface iface2 = udpSocket.multicastInterface(); + if (!setProxy) { + QVERIFY(iface2.isValid()); + QCOMPARE(iface.name(), iface2.name()); + } else { + QVERIFY(!iface2.isValid()); + } +} + +void tst_QUdpSocket::multicast_data() +{ + QHostAddress anyAddress = QHostAddress(QHostAddress::Any); + QHostAddress groupAddress = QHostAddress("239.255.118.62"); + QHostAddress any6Address = QHostAddress(QHostAddress::AnyIPv6); + QHostAddress group6Address = QHostAddress("FF01::114"); + + QTest::addColumn<QHostAddress>("bindAddress"); + QTest::addColumn<bool>("bindResult"); + QTest::addColumn<QHostAddress>("groupAddress"); + QTest::addColumn<bool>("joinResult"); + QTest::newRow("valid bind, group ipv4 address") << anyAddress << true << groupAddress << true; + QTest::newRow("valid bind, invalid group ipv4 address") << anyAddress << true << anyAddress << false; + QTest::newRow("same bind, group ipv4 address") << groupAddress << true << groupAddress << true; + QTest::newRow("valid bind, group ipv6 address") << any6Address << true << group6Address << true; + QTest::newRow("valid bind, invalid group ipv6 address") << any6Address << true << any6Address << false; + QTest::newRow("same bind, group ipv6 address") << group6Address << true << group6Address << true; +} + +void tst_QUdpSocket::multicast() +{ + QFETCH_GLOBAL(bool, setProxy); + QFETCH(QHostAddress, bindAddress); + QFETCH(bool, bindResult); + QFETCH(QHostAddress, groupAddress); + QFETCH(bool, joinResult); + if (setProxy) { + // UDP multicast does not work with proxies + if ((bindAddress.protocol() == QAbstractSocket::IPv4Protocol && (bindAddress.toIPv4Address() & 0xffff0000) == 0xefff0000) + || bindAddress.protocol() == QAbstractSocket::IPv6Protocol) { + // proxy cannot bind to IPv6 or multicast addresses + bindResult = false; + } + joinResult = false; + } + + QUdpSocket receiver; + + // bind first, then verify that we can join the multicast group + QVERIFY2(receiver.bind(bindAddress, 0) == bindResult, + qPrintable(receiver.errorString())); + if (!bindResult) + return; + + QVERIFY2(receiver.joinMulticastGroup(groupAddress) == joinResult, + qPrintable(receiver.errorString())); + if (!joinResult) + return; + + QList<QByteArray> datagrams = QList<QByteArray>() + << QByteArray("0123") + << QByteArray("4567") + << QByteArray("89ab") + << QByteArray("cdef"); + + QUdpSocket sender; + foreach (const QByteArray &datagram, datagrams) { + QCOMPARE(int(sender.writeDatagram(datagram, groupAddress, receiver.localPort())), + int(datagram.size())); + } + + QVERIFY2(receiver.waitForReadyRead(), + qPrintable(receiver.errorString())); + QVERIFY(receiver.hasPendingDatagrams()); + QList<QByteArray> receivedDatagrams; + while (receiver.hasPendingDatagrams()) { + QByteArray datagram; + datagram.resize(receiver.pendingDatagramSize()); + receiver.readDatagram(datagram.data(), datagram.size(), 0, 0); + receivedDatagrams << datagram; + } + QCOMPARE(receivedDatagrams, datagrams); + + QVERIFY2(receiver.leaveMulticastGroup(groupAddress), qPrintable(receiver.errorString())); +} + QTEST_MAIN(tst_QUdpSocket) #include "tst_qudpsocket.moc" diff --git a/tests/auto/qurl/tst_qurl.cpp b/tests/auto/qurl/tst_qurl.cpp index 63f9721..eff4658 100644 --- a/tests/auto/qurl/tst_qurl.cpp +++ b/tests/auto/qurl/tst_qurl.cpp @@ -161,6 +161,8 @@ private slots: void idna_testsuite(); void nameprep_testsuite_data(); void nameprep_testsuite(); + void nameprep_highcodes_data(); + void nameprep_highcodes(); void ace_testsuite_data(); void ace_testsuite(); void std3violations_data(); @@ -315,6 +317,7 @@ void tst_QUrl::constructing() QUrl buildUNC; + buildUNC.setScheme(QString::fromLatin1("file")); buildUNC.setHost(QString::fromLatin1("somehost")); buildUNC.setPath(QString::fromLatin1("somepath")); QCOMPARE(buildUNC.toLocalFile(), QString::fromLatin1("//somehost/somepath")); @@ -1758,7 +1761,15 @@ void tst_QUrl::toLocalFile_data() QTest::newRow("data7") << QString::fromLatin1("file://somehost/") << QString::fromLatin1("//somehost/"); QTest::newRow("data8") << QString::fromLatin1("file://somehost") << QString::fromLatin1("//somehost"); QTest::newRow("data9") << QString::fromLatin1("file:////somehost/somedir/somefile") << QString::fromLatin1("//somehost/somedir/somefile"); + QTest::newRow("data10") << QString::fromLatin1("FILE:/a.txt") << QString::fromLatin1("/a.txt"); + // and some that result in empty (i.e., not local) + QTest::newRow("xdata0") << QString::fromLatin1("/a.txt") << QString(); + QTest::newRow("xdata1") << QString::fromLatin1("//a.txt") << QString(); + QTest::newRow("xdata2") << QString::fromLatin1("///a.txt") << QString(); + QTest::newRow("xdata3") << QString::fromLatin1("foo:/a.txt") << QString(); + QTest::newRow("xdata4") << QString::fromLatin1("foo://a.txt") << QString(); + QTest::newRow("xdata5") << QString::fromLatin1("foo:///a.txt") << QString(); } void tst_QUrl::toLocalFile() @@ -2918,7 +2929,6 @@ void tst_QUrl::nameprep_testsuite_data() << QString() << 0 << 0; QTest::newRow("Case folding 8bit U+00DF (german sharp s)") -// << QString::fromUtf8("\xC3\xDF") ### typo in the original testsuite << QString::fromUtf8("\xC3\x9F") << QString("ss") << QString() << 0 << 0; @@ -2949,7 +2959,8 @@ void tst_QUrl::nameprep_testsuite_data() << QString() << 0 << 0; QTest::newRow("Self-reverting case folding U+01F0 and normalization") - << QString::fromUtf8("\xC7\xF0") +// << QString::fromUtf8("\xC7\xF0") ### typo in the original testsuite + << QString::fromUtf8("\xC7\xB0") << QString::fromUtf8("\xC7\xB0") << QString() << 0 << 0; @@ -3124,13 +3135,13 @@ void tst_QUrl::nameprep_testsuite_data() << QString("Nameprep") << STRINGPREP_NO_UNASSIGNED << STRINGPREP_CONTAINS_UNASSIGNED; QTest::newRow("Larger test (shrinking)") - << QString::fromUtf8("X\xC2\xAD\xC3\xDF\xC4\xB0\xE2\x84\xA1\x6a\xcc\x8c\xc2\xa0\xc2" + << QString::fromUtf8("X\xC2\xAD\xC3\x9F\xC4\xB0\xE2\x84\xA1\x6a\xcc\x8c\xc2\xa0\xc2" "\xaa\xce\xb0\xe2\x80\x80") << QString::fromUtf8("xssi\xcc\x87""tel\xc7\xb0 a\xce\xb0 ") << QString("Nameprep") << 0 << 0; QTest::newRow("Larger test (expanding)") - << QString::fromUtf8("X\xC3\xDF\xe3\x8c\x96\xC4\xB0\xE2\x84\xA1\xE2\x92\x9F\xE3\x8c\x80") + << QString::fromUtf8("X\xC3\x9F\xe3\x8c\x96\xC4\xB0\xE2\x84\xA1\xE2\x92\x9F\xE3\x8c\x80") << QString::fromUtf8("xss\xe3\x82\xad\xe3\x83\xad\xe3\x83\xa1\xe3\x83\xbc\xe3\x83\x88" "\xe3\x83\xab""i\xcc\x87""tel\x28""d\x29\xe3\x82\xa2\xe3\x83\x91" "\xe3\x83\xbc\xe3\x83\x88") @@ -3151,20 +3162,58 @@ void tst_QUrl::nameprep_testsuite() QFETCH(QString, out); QFETCH(QString, profile); - QEXPECT_FAIL("Case folding U+2121 U+33C6 U+1D7BB", - ">0xffff unicode points are not supported", Continue); - QEXPECT_FAIL("Self-reverting case folding U+01F0 and normalization", - "Investigate further", Continue); QEXPECT_FAIL("Left-to-right mark U+200E", "Investigate further", Continue); QEXPECT_FAIL("Deprecated U+202A", "Investigate further", Continue); QEXPECT_FAIL("Language tagging character U+E0001", "Investigate further", Continue); - QEXPECT_FAIL("Larger test (shrinking)", - "Investigate further", Continue); - QEXPECT_FAIL("Larger test (expanding)", - "Investigate further", Continue); + qt_nameprep(&in, 0); + QCOMPARE(in, out); +#endif +} + +void tst_QUrl::nameprep_highcodes_data() +{ + QTest::addColumn<QString>("in"); + QTest::addColumn<QString>("out"); + QTest::addColumn<QString>("profile"); + QTest::addColumn<int>("flags"); + QTest::addColumn<int>("rc"); + + { + QChar st[] = { '-', 0xd801, 0xdc1d, 'a' }; + QChar se[] = { '-', 0xd801, 0xdc45, 'a' }; + QTest::newRow("highcodes (U+1041D)") + << QString(st, sizeof(st)/sizeof(st[0])) + << QString(se, sizeof(se)/sizeof(se[0])) + << QString() << 0 << 0; + } + { + QChar st[] = { 0x011C, 0xd835, 0xdf6e, 0x0110 }; + QChar se[] = { 0x011D, 0x03C9, 0x0111 }; + QTest::newRow("highcodes (U+1D76E)") + << QString(st, sizeof(st)/sizeof(st[0])) + << QString(se, sizeof(se)/sizeof(se[0])) + << QString() << 0 << 0; + } + { + QChar st[] = { 'D', 0xdb40, 0xdc20, 'o', 0xd834, 0xdd7a, '\'', 0x2060, 'h' }; + QChar se[] = { 'd', 'o', '\'', 'h' }; + QTest::newRow("highcodes (D, U+E0020, o, U+1D17A, ', U+2060, h)") + << QString(st, sizeof(st)/sizeof(st[0])) + << QString(se, sizeof(se)/sizeof(se[0])) + << QString() << 0 << 0; + } +} + +void tst_QUrl::nameprep_highcodes() +{ +#ifdef QT_BUILD_INTERNAL + QFETCH(QString, in); + QFETCH(QString, out); + QFETCH(QString, profile); + qt_nameprep(&in, 0); QCOMPARE(in, out); #endif diff --git a/tests/auto/qvector/tst_qvector.cpp b/tests/auto/qvector/tst_qvector.cpp index 2bc8d15..d8dfacf 100644 --- a/tests/auto/qvector/tst_qvector.cpp +++ b/tests/auto/qvector/tst_qvector.cpp @@ -88,6 +88,7 @@ private slots: void outOfMemory(); void QTBUG6416_reserve(); + void initializeList(); }; void tst_QVector::constructors() const @@ -834,5 +835,19 @@ void tst_QVector::QTBUG6416_reserve() QCOMPARE(fooCtor, fooDtor); } +void tst_QVector::initializeList() +{ +#ifdef QT_CXX0X_INITIALIZERLIST + QVector<int> v1{2,3,4}; + QCOMPARE(v1, QVector<int>() << 2 << 3 << 4); + QCOMPARE(v1, (QVector<int>{2,3,4})); + + QVector<QVector<int>> v2{ v1, {1}, QVector<int>(), {2,3,4} }; + QVector<QVector<int>> v3; + v3 << v1 << (QVector<int>() << 1) << QVector<int>() << v1; + QCOMPARE(v3, v2); +#endif +} + QTEST_APPLESS_MAIN(tst_QVector) #include "tst_qvector.moc" diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 098ce3c..902c8ff 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -458,23 +458,15 @@ void tst_QWidget::getSetCheck() QCOMPARE(obj1.minimumWidth(), 0); // A widgets width can never be less than 0 obj1.setMinimumWidth(INT_MAX); #ifndef Q_WS_QWS //QWS doesn't allow toplevels to be bigger than the screen -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - QCOMPARE((long)obj1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium -#else QCOMPARE(obj1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium #endif -#endif child1.setMinimumWidth(0); QCOMPARE(child1.minimumWidth(), 0); child1.setMinimumWidth(INT_MIN); QCOMPARE(child1.minimumWidth(), 0); // A widgets width can never be less than 0 child1.setMinimumWidth(INT_MAX); -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - QCOMPARE((long)child1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium -#else QCOMPARE(child1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium -#endif // int QWidget::minimumHeight() // void QWidget::setMinimumHeight(int) @@ -484,38 +476,24 @@ void tst_QWidget::getSetCheck() QCOMPARE(obj1.minimumHeight(), 0); // A widgets height can never be less than 0 obj1.setMinimumHeight(INT_MAX); #ifndef Q_WS_QWS //QWS doesn't allow toplevels to be bigger than the screen -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - QCOMPARE((long)obj1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium -#else QCOMPARE(obj1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium #endif -#endif child1.setMinimumHeight(0); QCOMPARE(child1.minimumHeight(), 0); child1.setMinimumHeight(INT_MIN); QCOMPARE(child1.minimumHeight(), 0); // A widgets height can never be less than 0 child1.setMinimumHeight(INT_MAX); -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - QCOMPARE((long)child1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium -#else QCOMPARE(child1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium -#endif - - -// int QWidget::maximumWidth() + // int QWidget::maximumWidth() // void QWidget::setMaximumWidth(int) obj1.setMaximumWidth(0); QCOMPARE(obj1.maximumWidth(), 0); obj1.setMaximumWidth(INT_MIN); QCOMPARE(obj1.maximumWidth(), 0); // A widgets width can never be less than 0 obj1.setMaximumWidth(INT_MAX); -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - QCOMPARE((long)obj1.maximumWidth(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX -#else QCOMPARE(obj1.maximumWidth(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX -#endif // int QWidget::maximumHeight() // void QWidget::setMaximumHeight(int) @@ -524,11 +502,7 @@ void tst_QWidget::getSetCheck() obj1.setMaximumHeight(INT_MIN); QCOMPARE(obj1.maximumHeight(), 0); // A widgets height can never be less than 0 obj1.setMaximumHeight(INT_MAX); -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - QCOMPARE((long)obj1.maximumHeight(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX -#else QCOMPARE(obj1.maximumHeight(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX -#endif // back to normal obj1.setMinimumWidth(0); diff --git a/tests/auto/selftests/expected_cmptest.txt b/tests/auto/selftests/expected_cmptest.txt index fd5b486..0beb46b 100644 --- a/tests/auto/selftests/expected_cmptest.txt +++ b/tests/auto/selftests/expected_cmptest.txt @@ -1,5 +1,5 @@ ********* Start testing of tst_Cmptest ********* -Config: Using QTest library 4.7.0, Qt 4.7.0 +Config: Using QTest library 4.8.0, Qt 4.8.0 PASS : tst_Cmptest::initTestCase() PASS : tst_Cmptest::compare_boolfuncs() PASS : tst_Cmptest::compare_pointerfuncs() diff --git a/tests/auto/selftests/expected_crashes_3.txt b/tests/auto/selftests/expected_crashes_3.txt index 3aced25..b7f462a 100644 --- a/tests/auto/selftests/expected_crashes_3.txt +++ b/tests/auto/selftests/expected_crashes_3.txt @@ -1,5 +1,5 @@ ********* Start testing of tst_Crashes ********* -Config: Using QTest library 4.7.0, Qt 4.7.0 +Config: Using QTest library 4.8.0, Qt 4.8.0 PASS : tst_Crashes::initTestCase() QFATAL : tst_Crashes::crash() Received signal 11 FAIL! : tst_Crashes::crash() Received a fatal error. diff --git a/tests/auto/selftests/expected_longstring.txt b/tests/auto/selftests/expected_longstring.txt index 1461bc6..99809a8 100644 --- a/tests/auto/selftests/expected_longstring.txt +++ b/tests/auto/selftests/expected_longstring.txt @@ -1,5 +1,5 @@ ********* Start testing of tst_LongString ********* -Config: Using QTest library 4.7.0, Qt 4.7.0 +Config: Using QTest library 4.8.0, Qt 4.8.0 PASS : tst_LongString::initTestCase() FAIL! : tst_LongString::failWithLongString() Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. diff --git a/tests/auto/selftests/expected_maxwarnings.txt b/tests/auto/selftests/expected_maxwarnings.txt index 908bd5d..165bdda 100644 --- a/tests/auto/selftests/expected_maxwarnings.txt +++ b/tests/auto/selftests/expected_maxwarnings.txt @@ -1,5 +1,5 @@ ********* Start testing of MaxWarnings ********* -Config: Using QTest library 4.7.0, Qt 4.7.0 +Config: Using QTest library 4.8.0, Qt 4.8.0 PASS : MaxWarnings::initTestCase() QWARN : MaxWarnings::warn() 0 QWARN : MaxWarnings::warn() 1 diff --git a/tests/auto/selftests/expected_skip.txt b/tests/auto/selftests/expected_skip.txt index e5bf1ff..4b53a43 100644 --- a/tests/auto/selftests/expected_skip.txt +++ b/tests/auto/selftests/expected_skip.txt @@ -1,5 +1,5 @@ ********* Start testing of tst_Skip ********* -Config: Using QTest library 4.7.0, Qt 4.7.0 +Config: Using QTest library 4.8.0, Qt 4.8.0 PASS : tst_Skip::initTestCase() SKIP : tst_Skip::test() skipping all Loc: [/home/user/depot/qt-git/mainline/tests/auto/selftests/skip/tst_skip.cpp(68)] diff --git a/tests/auto/uic/baseline/icontheme.ui b/tests/auto/uic/baseline/icontheme.ui new file mode 100644 index 0000000..a214635 --- /dev/null +++ b/tests/auto/uic/baseline/icontheme.ui @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Form</class> + <widget class="QWidget" name="Form"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>122</width> + <height>117</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QPushButton" name="fileicon"> + <property name="text"> + <string>fileicon</string> + </property> + <property name="icon"> + <iconset> + <normaloff>image1.png</normaloff>image1.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="fileandthemeicon"> + <property name="text"> + <string>PushButton</string> + </property> + <property name="icon"> + <iconset theme="edit-copy"> + <normaloff>image7.png</normaloff>image7.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="themeicon"> + <property name="text"> + <string>PushButton</string> + </property> + <property name="icon"> + <iconset theme="edit-copy"> + <normaloff/> + </iconset> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/tests/auto/uic/baseline/icontheme.ui.h b/tests/auto/uic/baseline/icontheme.ui.h new file mode 100644 index 0000000..946fff9 --- /dev/null +++ b/tests/auto/uic/baseline/icontheme.ui.h @@ -0,0 +1,95 @@ +/******************************************************************************** +** Form generated from reading UI file 'icontheme.ui' +** +** Created: Thu Sep 2 10:28:19 2010 +** by: Qt User Interface Compiler version 4.8.0 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef ICONTHEME_H +#define ICONTHEME_H + +#include <QtCore/QVariant> +#include <QtGui/QAction> +#include <QtGui/QApplication> +#include <QtGui/QButtonGroup> +#include <QtGui/QHeaderView> +#include <QtGui/QPushButton> +#include <QtGui/QVBoxLayout> +#include <QtGui/QWidget> + +QT_BEGIN_NAMESPACE + +class Ui_Form +{ +public: + QVBoxLayout *verticalLayout; + QPushButton *fileicon; + QPushButton *fileandthemeicon; + QPushButton *themeicon; + + void setupUi(QWidget *Form) + { + if (Form->objectName().isEmpty()) + Form->setObjectName(QString::fromUtf8("Form")); + Form->resize(122, 117); + verticalLayout = new QVBoxLayout(Form); + verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); + fileicon = new QPushButton(Form); + fileicon->setObjectName(QString::fromUtf8("fileicon")); + QIcon icon; + icon.addFile(QString::fromUtf8("image1.png"), QSize(), QIcon::Normal, QIcon::Off); + fileicon->setIcon(icon); + + verticalLayout->addWidget(fileicon); + + fileandthemeicon = new QPushButton(Form); + fileandthemeicon->setObjectName(QString::fromUtf8("fileandthemeicon")); + QIcon icon1; + QString iconThemeName = QString::fromUtf8("edit-copy"); + if (QIcon::hasThemeIcon(iconThemeName)) { + icon1 = QIcon::fromTheme(iconThemeName); + } else { + icon1.addFile(QString::fromUtf8("image7.png"), QSize(), QIcon::Normal, QIcon::Off); + } + fileandthemeicon->setIcon(icon1); + + verticalLayout->addWidget(fileandthemeicon); + + themeicon = new QPushButton(Form); + themeicon->setObjectName(QString::fromUtf8("themeicon")); + QIcon icon2; + iconThemeName = QString::fromUtf8("edit-copy"); + if (QIcon::hasThemeIcon(iconThemeName)) { + icon2 = QIcon::fromTheme(iconThemeName); + } else { + icon2.addFile(QString::fromUtf8(""), QSize(), QIcon::Normal, QIcon::Off); + } + themeicon->setIcon(icon2); + + verticalLayout->addWidget(themeicon); + + + retranslateUi(Form); + + QMetaObject::connectSlotsByName(Form); + } // setupUi + + void retranslateUi(QWidget *Form) + { + Form->setWindowTitle(QApplication::translate("Form", "Form", 0, QApplication::UnicodeUTF8)); + fileicon->setText(QApplication::translate("Form", "fileicon", 0, QApplication::UnicodeUTF8)); + fileandthemeicon->setText(QApplication::translate("Form", "PushButton", 0, QApplication::UnicodeUTF8)); + themeicon->setText(QApplication::translate("Form", "PushButton", 0, QApplication::UnicodeUTF8)); + } // retranslateUi + +}; + +namespace Ui { + class Form: public Ui_Form {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // ICONTHEME_H diff --git a/tests/auto/utf8/tst_utf8.cpp b/tests/auto/utf8/tst_utf8.cpp index 7bbbfab..9b6b8c1 100644 --- a/tests/auto/utf8/tst_utf8.cpp +++ b/tests/auto/utf8/tst_utf8.cpp @@ -210,7 +210,9 @@ void tst_Utf8::invalidUtf8_data() QTest::addColumn<QByteArray>("utf8"); QTest::newRow("1char") << QByteArray("\x80"); - QTest::newRow("2chars") << QByteArray("\xC2\xC0"); + QTest::newRow("2chars-1") << QByteArray("\xC2\xC0"); + QTest::newRow("2chars-2") << QByteArray("\xC3\xDF"); + QTest::newRow("2chars-3") << QByteArray("\xC7\xF0"); QTest::newRow("3chars-1") << QByteArray("\xE0\xA0\xC0"); QTest::newRow("3chars-2") << QByteArray("\xE0\xC0\xA0"); QTest::newRow("4chars-1") << QByteArray("\xF0\x90\x80\xC0"); diff --git a/tests/benchmarks/corelib/io/qfileinfo/main.cpp b/tests/benchmarks/corelib/io/qfileinfo/main.cpp index 025787f..b272bda 100644 --- a/tests/benchmarks/corelib/io/qfileinfo/main.cpp +++ b/tests/benchmarks/corelib/io/qfileinfo/main.cpp @@ -43,15 +43,20 @@ #include <QtTest/QtTest> #include <QtCore/QCoreApplication> #include <QtCore/QFileInfo> +#include <QtCore/QFile> #include "private/qfsfileengine_p.h" +#include "../../../../shared/filesystem.h" class qfileinfo : public QObject { Q_OBJECT private slots: void canonicalFileNamePerformance(); - +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + void symLinkTargetPerformanceLNK(); + void symLinkTargetPerformanceMounpoint(); +#endif void initTestCase(); void cleanupTestCase(); public: @@ -78,6 +83,43 @@ void qfileinfo::canonicalFileNamePerformance() } } +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +void qfileinfo::symLinkTargetPerformanceLNK() +{ + QVERIFY(QFile::link("file","link.lnk")); + QFileInfo info("link.lnk"); + info.setCaching(false); + QVERIFY(info.isSymLink()); + QString linkTarget; + QBENCHMARK { + for(int i=0; i<100; i++) + linkTarget = info.readLink(); + } + QVERIFY(QFile::remove("link.lnk")); +} + +void qfileinfo::symLinkTargetPerformanceMounpoint() +{ + wchar_t buffer[MAX_PATH]; + QString rootPath = QDir::toNativeSeparators(QDir::rootPath()); + QVERIFY(GetVolumeNameForVolumeMountPointW(rootPath.utf16(), buffer, MAX_PATH)); + QString rootVolume = QString::fromWCharArray(buffer); + QString mountpoint = "mountpoint"; + rootVolume.replace("\\\\?\\","\\??\\"); + FileSystem::createNtfsJunction(rootVolume, mountpoint); + + QFileInfo info(mountpoint); + info.setCaching(false); + QVERIFY(info.isSymLink()); + QString linkTarget; + QBENCHMARK { + for(int i=0; i<100; i++) + linkTarget = info.readLink(); + } + QVERIFY(QDir().rmdir(mountpoint)); +} +#endif + QTEST_MAIN(qfileinfo) #include "main.moc" diff --git a/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp index 36399af..ebeea84 100644 --- a/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -71,6 +71,11 @@ private slots: void isRegisteredBuiltin(); void isRegisteredCustom(); void isRegisteredNotRegistered(); + + void constructCoreType_data(); + void constructCoreType(); + void constructCoreTypeCopy_data(); + void constructCoreTypeCopy(); }; tst_QMetaType::tst_QMetaType() @@ -229,5 +234,52 @@ void tst_QMetaType::isRegisteredNotRegistered() } } +void tst_QMetaType::constructCoreType_data() +{ + QTest::addColumn<int>("typeId"); + for (int i = 0; i <= QMetaType::LastCoreType; ++i) + QTest::newRow(QMetaType::typeName(i)) << i; + for (int i = QMetaType::FirstCoreExtType; i <= QMetaType::LastCoreExtType; ++i) + QTest::newRow(QMetaType::typeName(i)) << i; + // GUI types are tested in tst_QGuiMetaType. +} + +// Tests how fast QMetaType can default-construct and destroy a Qt +// core type. The purpose of this benchmark is to measure the overhead +// of using type id-based creation compared to creating the type +// directly (i.e. "T *t = new T(); delete t;"). +void tst_QMetaType::constructCoreType() +{ + QFETCH(int, typeId); + QBENCHMARK { + for (int i = 0; i < 100000; ++i) { + void *data = QMetaType::construct(typeId, (void *)0); + QMetaType::destroy(typeId, data); + } + } +} + +void tst_QMetaType::constructCoreTypeCopy_data() +{ + constructCoreType_data(); +} + +// Tests how fast QMetaType can copy-construct and destroy a Qt core +// type. The purpose of this benchmark is to measure the overhead of +// using type id-based creation compared to creating the type directly +// (i.e. "T *t = new T(other); delete t;"). +void tst_QMetaType::constructCoreTypeCopy() +{ + QFETCH(int, typeId); + QVariant other(typeId, (void *)0); + const void *copy = other.constData(); + QBENCHMARK { + for (int i = 0; i < 100000; ++i) { + void *data = QMetaType::construct(typeId, copy); + QMetaType::destroy(typeId, data); + } + } +} + QTEST_MAIN(tst_QMetaType) #include "tst_qmetatype.moc" diff --git a/tests/benchmarks/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/benchmarks/corelib/kernel/qvariant/tst_qvariant.cpp index 58cec4f..5e19c1b 100644 --- a/tests/benchmarks/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/benchmarks/corelib/kernel/qvariant/tst_qvariant.cpp @@ -71,6 +71,11 @@ private slots: void floatVariantValue(); void rectVariantValue(); void stringVariantValue(); + + void createCoreType_data(); + void createCoreType(); + void createCoreTypeCopy_data(); + void createCoreTypeCopy(); }; void tst_qvariant::testBound() @@ -220,6 +225,48 @@ void tst_qvariant::stringVariantValue() } } +void tst_qvariant::createCoreType_data() +{ + QTest::addColumn<int>("typeId"); + for (int i = 0; i <= QMetaType::LastCoreType; ++i) + QTest::newRow(QMetaType::typeName(i)) << i; + for (int i = QMetaType::FirstCoreExtType; i <= QMetaType::LastCoreExtType; ++i) + QTest::newRow(QMetaType::typeName(i)) << i; +} + +// Tests how fast a Qt core type can be default-constructed by a +// QVariant. The purpose of this benchmark is to measure the overhead +// of creating (and destroying) a QVariant compared to creating the +// type directly. +void tst_qvariant::createCoreType() +{ + QFETCH(int, typeId); + QBENCHMARK { + for (int i = 0; i < ITERATION_COUNT; ++i) + QVariant(typeId, (void *)0); + } +} + +void tst_qvariant::createCoreTypeCopy_data() +{ + createCoreType_data(); +} + +// Tests how fast a Qt core type can be copy-constructed by a +// QVariant. The purpose of this benchmark is to measure the overhead +// of creating (and destroying) a QVariant compared to creating the +// type directly. +void tst_qvariant::createCoreTypeCopy() +{ + QFETCH(int, typeId); + QVariant other(typeId, (void *)0); + const void *copy = other.constData(); + QBENCHMARK { + for (int i = 0; i < ITERATION_COUNT; ++i) + QVariant(typeId, copy); + } +} + QTEST_MAIN(tst_qvariant) #include "tst_qvariant.moc" diff --git a/tests/benchmarks/corelib/thread/qmutex/qmutex.pro b/tests/benchmarks/corelib/thread/qmutex/qmutex.pro new file mode 100644 index 0000000..eda2f11 --- /dev/null +++ b/tests/benchmarks/corelib/thread/qmutex/qmutex.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_bench_qmutex + +SOURCES += tst_qmutex.cpp + diff --git a/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp b/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp new file mode 100644 index 0000000..fded508 --- /dev/null +++ b/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qtest.h> +#include <QtCore> + +#include <math.h> + +//TESTED_FILES= + + +class tst_QMutex : public QObject +{ + Q_OBJECT + +public: + tst_QMutex(); + virtual ~tst_QMutex(); + +private slots: + void noThread_data(); + void noThread(); +}; + +tst_QMutex::tst_QMutex() +{ +} + +tst_QMutex::~tst_QMutex() +{ +} + +void tst_QMutex::noThread_data() +{ + QTest::addColumn<int>("t"); + + QTest::newRow("noLock") << 1; + QTest::newRow("QMutexInline") << 2; + QTest::newRow("QMutex") << 3; + QTest::newRow("QMutexLocker") << 4; +} + +void tst_QMutex::noThread() +{ + volatile int count = 0; + const int N = 5000000; + QMutex mtx; + + QFETCH(int, t); + switch(t) { + case 1: + QBENCHMARK { + count = 0; + for (int i = 0; i < N; i++) { + count++; + } + } + break; + case 2: + QBENCHMARK { + count = 0; + for (int i = 0; i < N; i++) { + mtx.lockInline(); + count++; + mtx.unlockInline(); + } + } + break; + case 3: + QBENCHMARK { + count = 0; + for (int i = 0; i < N; i++) { + mtx.lock(); + count++; + mtx.unlock(); + } + } + break; + case 4: + QBENCHMARK { + count = 0; + for (int i = 0; i < N; i++) { + QMutexLocker locker(&mtx); + count++; + } + } + break; + } + QCOMPARE(int(count), N); +} + +QTEST_MAIN(tst_QMutex) +#include "tst_qmutex.moc" diff --git a/tests/benchmarks/gui/kernel/qguimetatype/qguimetatype.pro b/tests/benchmarks/gui/kernel/qguimetatype/qguimetatype.pro new file mode 100644 index 0000000..7ef99e4 --- /dev/null +++ b/tests/benchmarks/gui/kernel/qguimetatype/qguimetatype.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_bench_qguimetatype + +SOURCES += tst_qguimetatype.cpp + diff --git a/tests/benchmarks/gui/kernel/qguimetatype/tst_qguimetatype.cpp b/tests/benchmarks/gui/kernel/qguimetatype/tst_qguimetatype.cpp new file mode 100644 index 0000000..f94767b --- /dev/null +++ b/tests/benchmarks/gui/kernel/qguimetatype/tst_qguimetatype.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qtest.h> +#include <QtCore/qmetatype.h> + +class tst_QGuiMetaType : public QObject +{ + Q_OBJECT + +public: + tst_QGuiMetaType(); + virtual ~tst_QGuiMetaType(); + +private slots: + void constructGuiType_data(); + void constructGuiType(); + void constructGuiTypeCopy_data(); + void constructGuiTypeCopy(); +}; + +tst_QGuiMetaType::tst_QGuiMetaType() +{ +} + +tst_QGuiMetaType::~tst_QGuiMetaType() +{ +} + +void tst_QGuiMetaType::constructGuiType_data() +{ + QTest::addColumn<int>("typeId"); + for (int i = QMetaType::FirstGuiType; i <= QMetaType::LastGuiType; ++i) + QTest::newRow(QMetaType::typeName(i)) << i; +} + +// Tests how fast QMetaType can default-construct and destroy a Qt GUI +// type. The purpose of this benchmark is to measure the overhead of +// using type id-based creation compared to creating the type directly +// (i.e. "T *t = new T(); delete t;"). +void tst_QGuiMetaType::constructGuiType() +{ + QFETCH(int, typeId); + QBENCHMARK { + for (int i = 0; i < 100000; ++i) { + void *data = QMetaType::construct(typeId, (void *)0); + QMetaType::destroy(typeId, data); + } + } +} + +void tst_QGuiMetaType::constructGuiTypeCopy_data() +{ + constructGuiType_data(); +} + +// Tests how fast QMetaType can copy-construct and destroy a Qt GUI +// type. The purpose of this benchmark is to measure the overhead of +// using type id-based creation compared to creating the type directly +// (i.e. "T *t = new T(other); delete t;"). +void tst_QGuiMetaType::constructGuiTypeCopy() +{ + QFETCH(int, typeId); + QVariant other(typeId, (void *)0); + const void *copy = other.constData(); + QBENCHMARK { + for (int i = 0; i < 100000; ++i) { + void *data = QMetaType::construct(typeId, copy); + QMetaType::destroy(typeId, data); + } + } +} + +QTEST_MAIN(tst_QGuiMetaType) +#include "tst_qguimetatype.moc" diff --git a/tests/benchmarks/gui/kernel/qguivariant/qguivariant.pro b/tests/benchmarks/gui/kernel/qguivariant/qguivariant.pro new file mode 100644 index 0000000..4e05dd7 --- /dev/null +++ b/tests/benchmarks/gui/kernel/qguivariant/qguivariant.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_bench_qguivariant + +SOURCES += tst_qguivariant.cpp + diff --git a/tests/benchmarks/gui/kernel/qguivariant/tst_qguivariant.cpp b/tests/benchmarks/gui/kernel/qguivariant/tst_qguivariant.cpp new file mode 100644 index 0000000..4016be1 --- /dev/null +++ b/tests/benchmarks/gui/kernel/qguivariant/tst_qguivariant.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qtest.h> +#include <QtCore/qvariant.h> + +#define ITERATION_COUNT 1e5 + +class tst_QGuiVariant : public QObject +{ + Q_OBJECT + +public: + tst_QGuiVariant(); + virtual ~tst_QGuiVariant(); + +private slots: + void createGuiType_data(); + void createGuiType(); + void createGuiTypeCopy_data(); + void createGuiTypeCopy(); +}; + +tst_QGuiVariant::tst_QGuiVariant() +{ +} + +tst_QGuiVariant::~tst_QGuiVariant() +{ +} + +void tst_QGuiVariant::createGuiType_data() +{ + QTest::addColumn<int>("typeId"); + for (int i = QMetaType::FirstGuiType; i <= QMetaType::LastGuiType; ++i) + QTest::newRow(QMetaType::typeName(i)) << i; +} + +// Tests how fast a Qt GUI type can be default-constructed by a +// QVariant. The purpose of this benchmark is to measure the overhead +// of creating (and destroying) a QVariant compared to creating the +// type directly. +void tst_QGuiVariant::createGuiType() +{ + QFETCH(int, typeId); + QBENCHMARK { + for (int i = 0; i < ITERATION_COUNT; ++i) + QVariant(typeId, (void *)0); + } +} + +void tst_QGuiVariant::createGuiTypeCopy_data() +{ + createGuiType_data(); +} + +// Tests how fast a Qt GUI type can be copy-constructed by a +// QVariant. The purpose of this benchmark is to measure the overhead +// of creating (and destroying) a QVariant compared to creating the +// type directly. +void tst_QGuiVariant::createGuiTypeCopy() +{ + QFETCH(int, typeId); + QVariant other(typeId, (void *)0); + const void *copy = other.constData(); + QBENCHMARK { + for (int i = 0; i < ITERATION_COUNT; ++i) + QVariant(typeId, copy); + } +} + +QTEST_MAIN(tst_QGuiVariant) +#include "tst_qguivariant.moc" diff --git a/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp index 90ae153..0098d8e 100644 --- a/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -51,6 +51,9 @@ #include "../../../../auto/network-settings.h" +typedef QSharedPointer<QVarLengthArray<char, 0> > QVarLengthArraySharedPointer; +Q_DECLARE_METATYPE(QVarLengthArraySharedPointer) + class TimedSender: public QThread { Q_OBJECT @@ -465,7 +468,8 @@ private slots: void httpUploadPerformance(); void httpDownloadPerformance_data(); void httpDownloadPerformance(); - + void httpDownloadPerformanceDownloadBuffer_data(); + void httpDownloadPerformanceDownloadBuffer(); }; void tst_qnetworkreply::httpLatency() @@ -649,6 +653,72 @@ void tst_qnetworkreply::httpDownloadPerformance() qint64 elapsed = time.elapsed(); qDebug() << "tst_QNetworkReply::httpDownloadPerformance" << elapsed << "msec, " << ((UploadSize/1024.0)/(elapsed/1000.0)) << " kB/sec"; +}; + +class HttpDownloadPerformanceClientDownloadBuffer : QObject { + Q_OBJECT +private: + bool useDownloadBuffer; + QNetworkReply *reply; + qint64 uploadSize; +public: + HttpDownloadPerformanceClientDownloadBuffer (QNetworkReply *reply, bool useDownloadBuffer, qint64 uploadSize) + : useDownloadBuffer(useDownloadBuffer), reply(reply), uploadSize(uploadSize) + { + connect(reply, SIGNAL(finished()), this, SLOT(finishedSlot())); + } + + public slots: + void finishedSlot() { + if (useDownloadBuffer) { + QVariant downloadBufferAttribute = reply->attribute(QNetworkRequest::DownloadBufferAttribute); + QSharedPointer<QVarLengthArray<char, 0> > data = downloadBufferAttribute.value<QSharedPointer<QVarLengthArray<char, 0> > >(); + } else { + // We did not have a download buffer but we still need to benchmark having the data, e.g. reading it all. + char* replyData = (char*) qMalloc(uploadSize); + QVERIFY(reply->read(replyData, uploadSize) == uploadSize); + qFree(replyData); + } + } +}; + +void tst_qnetworkreply::httpDownloadPerformanceDownloadBuffer_data() +{ + QTest::addColumn<bool>("useDownloadBuffer"); + + QTest::newRow("use-download-buffer") << true; + QTest::newRow("do-not-use-download-buffer") << false; +} + +void tst_qnetworkreply::httpDownloadPerformanceDownloadBuffer() +{ + QFETCH(bool, useDownloadBuffer); + + // On my Linux Desktop the results are already visible with 128 kB, however we use this to have good results. +#if defined(Q_OS_SYMBIAN) || defined(Q_WS_WINCE_WM) + // Show some mercy to non-desktop platform/s + enum {UploadSize = 4*1024*1024}; // 4 MB +#else + enum {UploadSize = 32*1024*1024}; // 32 MB +#endif + + HttpDownloadPerformanceServer server(UploadSize, true, false); + + QNetworkRequest request(QUrl("http://127.0.0.1:" + QString::number(server.serverPort()) + "/?bare=1")); + if (useDownloadBuffer) + request.setAttribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute, 1024*1024*128); // 128 MB is max allowed + + QNetworkAccessManager manager; + QNetworkReplyPtr reply = manager.get(request); + + HttpDownloadPerformanceClientDownloadBuffer client(reply, useDownloadBuffer, UploadSize); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); + QBENCHMARK { + QTestEventLoop::instance().enterLoop(40); + QCOMPARE(reply->error(), QNetworkReply::NoError); + QVERIFY(!QTestEventLoop::instance().timeout()); + } } QTEST_MAIN(tst_qnetworkreply) diff --git a/tests/benchmarks/script/qscriptqobject/qscriptqobject.pro b/tests/benchmarks/script/qscriptqobject/qscriptqobject.pro new file mode 100644 index 0000000..30bc447 --- /dev/null +++ b/tests/benchmarks/script/qscriptqobject/qscriptqobject.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_bench_qscriptqobject + +SOURCES += tst_qscriptqobject.cpp + +QT += script diff --git a/tests/benchmarks/script/qscriptqobject/tst_qscriptqobject.cpp b/tests/benchmarks/script/qscriptqobject/tst_qscriptqobject.cpp new file mode 100644 index 0000000..e68db06 --- /dev/null +++ b/tests/benchmarks/script/qscriptqobject/tst_qscriptqobject.cpp @@ -0,0 +1,1237 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qtest.h> +#include <QtGui> +#include <QtScript> + +#define ITERATION_COUNT 1e4 + +struct CustomType +{ + int a; +}; +Q_DECLARE_METATYPE(CustomType) + +class PropertyTestObject : public QObject +{ + Q_OBJECT + Q_ENUMS(EnumType) + Q_FLAGS(FlagsType) + Q_PROPERTY(bool boolProperty READ boolProperty WRITE setBoolProperty) + Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty) + Q_PROPERTY(double doubleProperty READ doubleProperty WRITE setDoubleProperty) + Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty) + Q_PROPERTY(QVariant variantProperty READ variantProperty WRITE setVariantProperty) + Q_PROPERTY(QObject* qobjectProperty READ qobjectProperty WRITE setQObjectProperty) + Q_PROPERTY(CustomType customProperty READ customProperty WRITE setCustomProperty) + Q_PROPERTY(EnumType enumProperty READ enumProperty WRITE setEnumProperty) + Q_PROPERTY(FlagsType flagsProperty READ flagsProperty WRITE setFlagsProperty) +public: + enum EnumType { + NoEnumValue = 0, + FirstEnumValue = 1, + SecondEnumValue = 2, + ThirdEnumValue = 4 + }; + Q_DECLARE_FLAGS(FlagsType, EnumType) + + PropertyTestObject(QObject *parent = 0) + : QObject(parent), + m_boolProperty(false), + m_intProperty(123), + m_doubleProperty(123), + m_stringProperty("hello"), + m_variantProperty(double(123)), + m_qobjectProperty(this), + m_enumProperty(SecondEnumValue), + m_flagsProperty(FirstEnumValue | ThirdEnumValue) + { } + + bool boolProperty() const + { return m_boolProperty; } + void setBoolProperty(bool value) + { m_boolProperty = value; } + + int intProperty() const + { return m_intProperty; } + void setIntProperty(int value) + { m_intProperty = value; } + + int doubleProperty() const + { return m_doubleProperty; } + void setDoubleProperty(double value) + { m_doubleProperty = value; } + + QString stringProperty() const + { return m_stringProperty; } + void setStringProperty(const QString &value) + { m_stringProperty = value; } + + QVariant variantProperty() const + { return m_variantProperty; } + void setVariantProperty(const QVariant &value) + { m_variantProperty = value; } + + QObject *qobjectProperty() const + { return m_qobjectProperty; } + void setQObjectProperty(QObject *qobject) + { m_qobjectProperty = qobject; } + + CustomType customProperty() const + { return m_customProperty; } + void setCustomProperty(const CustomType &value) + { m_customProperty = value; } + + EnumType enumProperty() const + { return m_enumProperty; } + void setEnumProperty(EnumType value) + { m_enumProperty = value; } + + FlagsType flagsProperty() const + { return m_flagsProperty; } + void setFlagsProperty(FlagsType value) + { m_flagsProperty = value; } + +private: + bool m_boolProperty; + int m_intProperty; + double m_doubleProperty; + QString m_stringProperty; + QVariant m_variantProperty; + QObject *m_qobjectProperty; + CustomType m_customProperty; + EnumType m_enumProperty; + FlagsType m_flagsProperty; +}; + +class SlotTestObject : public QObject +{ + Q_OBJECT +public: + SlotTestObject(QObject *parent = 0) + : QObject(parent), + m_string(QString::fromLatin1("hello")), + m_variant(123) + { } + +public Q_SLOTS: + void voidSlot() { } + void boolSlot(bool) { } + void intSlot(int) { } + void doubleSlot(double) { } + void stringSlot(const QString &) { } + void variantSlot(const QVariant &) { } + void qobjectSlot(QObject *) { } + void customTypeSlot(const CustomType &) { } + + bool returnBoolSlot() { return true; } + int returnIntSlot() { return 123; } + double returnDoubleSlot() { return 123.0; } + QString returnStringSlot() { return m_string; } + QVariant returnVariantSlot() { return m_variant; } + QObject *returnQObjectSlot() { return this; } + CustomType returnCustomTypeSlot() { return m_custom; } + + void fourDoubleSlot(double, double, double, double) { } + void sixDoubleSlot(double, double, double, double, double, double) { } + void eightDoubleSlot(double, double, double, double, double, double, double, double) { } + + void fourStringSlot(const QString &, const QString &, const QString &, const QString &) { } + void sixStringSlot(const QString &, const QString &, const QString &, const QString &, + const QString &, const QString &) { } + void eightStringSlot(const QString &, const QString &, const QString &, const QString &, + const QString &, const QString &, const QString &, const QString &) { } + +private: + QString m_string; + QVariant m_variant; + CustomType m_custom; +}; + +class SignalTestObject : public QObject +{ + Q_OBJECT +public: + SignalTestObject(QObject *parent = 0) + : QObject(parent) + { } + + void emitVoidSignal() + { emit voidSignal(); } + void emitBoolSignal(bool value) + { emit boolSignal(value); } + void emitIntSignal(int value) + { emit intSignal(value); } + void emitDoubleSignal(double value) + { emit doubleSignal(value); } + void emitStringSignal(const QString &value) + { emit stringSignal(value); } + void emitVariantSignal(const QVariant &value) + { emit variantSignal(value); } + void emitQObjectSignal(QObject *object) + { emit qobjectSignal(object); } + void emitCustomTypeSignal(const CustomType &value) + { emit customTypeSignal(value); } + +Q_SIGNALS: + void voidSignal(); + void boolSignal(bool); + void intSignal(int); + void doubleSignal(double); + void stringSignal(const QString &); + void variantSignal(const QVariant &); + void qobjectSignal(QObject *); + void customTypeSignal(const CustomType &); +}; + +class OverloadedSlotTestObject : public QObject +{ + Q_OBJECT +public: + OverloadedSlotTestObject(QObject *parent = 0) + : QObject(parent) + { } + +public Q_SLOTS: + void overloadedSlot() { } + void overloadedSlot(bool) { } + void overloadedSlot(double) { } + void overloadedSlot(const QString &) { } +}; + +class QtScriptablePropertyTestObject + : public PropertyTestObject, public QScriptable +{ +}; + +class QtScriptableSlotTestObject + : public SlotTestObject, public QScriptable +{ +}; + +class tst_QScriptQObject : public QObject +{ + Q_OBJECT + +public: + tst_QScriptQObject(); + virtual ~tst_QScriptQObject(); + +private slots: + void initTestCase(); + + void readMetaProperty_data(); + void readMetaProperty(); + + void writeMetaProperty_data(); + void writeMetaProperty(); + + void readDynamicProperty_data(); + void readDynamicProperty(); + + void writeDynamicProperty_data(); + void writeDynamicProperty(); + + void readMethodByName_data(); + void readMethodByName(); + + void readMethodBySignature_data(); + void readMethodBySignature(); + + void readChild_data(); + void readChild(); + + void readOneOfManyChildren_data(); + void readOneOfManyChildren(); + + void readPrototypeProperty_data(); + void readPrototypeProperty(); + + void readScriptProperty_data(); + void readScriptProperty(); + + void readNoSuchProperty_data(); + void readNoSuchProperty(); + + void readAllMetaProperties(); + + void callSlot_data(); + void callSlot(); + + void callOverloadedSlot_data(); + void callOverloadedSlot(); + + void voidSignalHandler(); + void boolSignalHandler(); + void intSignalHandler(); + void doubleSignalHandler(); + void stringSignalHandler(); + void variantSignalHandler(); + void qobjectSignalHandler(); + void customTypeSignalHandler(); + + void readButtonMetaProperty_data(); + void readButtonMetaProperty(); + + void writeButtonMetaProperty_data(); + void writeButtonMetaProperty(); + + void readDynamicButtonProperty_data(); + void readDynamicButtonProperty(); + + void writeDynamicButtonProperty_data(); + void writeDynamicButtonProperty(); + + void readButtonMethodByName_data(); + void readButtonMethodByName(); + + void readButtonMethodBySignature_data(); + void readButtonMethodBySignature(); + + void readButtonChild_data(); + void readButtonChild(); + + void readButtonPrototypeProperty_data(); + void readButtonPrototypeProperty(); + + void readButtonScriptProperty_data(); + void readButtonScriptProperty(); + + void readNoSuchButtonProperty_data(); + void readNoSuchButtonProperty(); + + void callButtonMethod_data(); + void callButtonMethod(); + + void readAllButtonMetaProperties(); + + void readQScriptableMetaProperty_data(); + void readQScriptableMetaProperty(); + + void writeQScriptableMetaProperty_data(); + void writeQScriptableMetaProperty(); + + void callQScriptableSlot_data(); + void callQScriptableSlot(); + +private: + void readMetaProperty_dataHelper(const QMetaObject *mo); + void readMethodByName_dataHelper(const QMetaObject *mo); + void readMethodBySignature_dataHelper(const QMetaObject *mo); + void readAllMetaPropertiesHelper(QObject *o); + + void readPropertyHelper(QScriptEngine &engine, const QScriptValue &object, + const QString &propertyName, const QString &argTemplate = ".%0"); + void writePropertyHelper(QScriptEngine &engine, const QScriptValue &object, + const QString &propertyName, const QScriptValue &value, + const QString &argTemplate = ".%0"); + + void callMethodHelper(QScriptEngine &engine, QObject *object, + const QString &propertyName, const QString &arguments); + void signalHandlerHelper(QScriptEngine &engine, QObject *object, const char *signal); +}; + +tst_QScriptQObject::tst_QScriptQObject() +{ +} + +tst_QScriptQObject::~tst_QScriptQObject() +{ +} + +void tst_QScriptQObject::initTestCase() +{ + qMetaTypeId<CustomType>(); +} + +void tst_QScriptQObject::readMetaProperty_dataHelper(const QMetaObject *mo) +{ + QTest::addColumn<QString>("propertyName"); + + for (int i = 0; i < mo->propertyCount(); ++i) { + QMetaProperty prop = mo->property(i); + if (!qstrcmp(prop.name(), "default")) + continue; // skip reserved word + QTest::newRow(prop.name()) << prop.name(); + } +} + +void tst_QScriptQObject::readMethodByName_dataHelper(const QMetaObject *mo) +{ + QTest::addColumn<QString>("propertyName"); + + QSet<QByteArray> uniqueNames; + for (int i = 0; i < mo->methodCount(); ++i) { + QMetaMethod method = mo->method(i); + if (method.access() == QMetaMethod::Private) + continue; + QByteArray signature = method.signature(); + QByteArray name = signature.left(signature.indexOf('(')); + if (uniqueNames.contains(name)) + continue; + QTest::newRow(name) << QString::fromLatin1(name); + uniqueNames.insert(name); + } +} + +void tst_QScriptQObject::readMethodBySignature_dataHelper(const QMetaObject *mo) +{ + QTest::addColumn<QString>("propertyName"); + + for (int i = 0; i < mo->methodCount(); ++i) { + QMetaMethod method = mo->method(i); + if (method.access() == QMetaMethod::Private) + continue; + QTest::newRow(method.signature()) << QString::fromLatin1(method.signature()); + } +} + +void tst_QScriptQObject::readAllMetaPropertiesHelper(QObject *o) +{ + QString code = QString::fromLatin1( + "(function() {\n" + " for (var i = 0; i < 100; ++i) {\n"); + const QMetaObject *mo = o->metaObject(); + for (int i = 0; i < mo->propertyCount(); ++i) { + QMetaProperty prop = mo->property(i); + if (!qstrcmp(prop.name(), "default")) + continue; // skip reserved word + code.append(QString::fromLatin1(" this.%0;\n").arg(prop.name())); + } + code.append( + " }\n" + "})"); + + QScriptEngine engine; + QScriptValue fun = engine.evaluate(code); + QVERIFY(fun.isFunction()); + + QScriptValue wrapper = engine.newQObject(o); + QBENCHMARK { + fun.call(wrapper); + } + QVERIFY(!engine.hasUncaughtException()); +} + +void tst_QScriptQObject::readPropertyHelper( + QScriptEngine &engine, const QScriptValue &object, + const QString &propertyName, const QString &argTemplate) +{ + QString code = QString::fromLatin1( + "(function() {\n" + " for (var i = 0; i < %0; ++i)\n" + " this%1;\n" + "})").arg(ITERATION_COUNT).arg(argTemplate.arg(propertyName)); + QScriptValue fun = engine.evaluate(code); + QVERIFY(fun.isFunction()); + + QBENCHMARK { + fun.call(object); + } + QVERIFY(!engine.hasUncaughtException()); +} + +void tst_QScriptQObject::writePropertyHelper( + QScriptEngine &engine, const QScriptValue &object, + const QString &propertyName, const QScriptValue &value, + const QString &argTemplate) +{ + QVERIFY(value.isValid()); + QString code = QString::fromLatin1( + "(function(v) {\n" + " for (var i = 0; i < %0; ++i)\n" + " this%1 = v;\n" + "})").arg(ITERATION_COUNT).arg(argTemplate.arg(propertyName)); + QScriptValue fun = engine.evaluate(code); + QVERIFY(fun.isFunction()); + + QScriptValueList args; + args << value; + QBENCHMARK { + fun.call(object, args); + } + QVERIFY(!engine.hasUncaughtException()); +} + +void tst_QScriptQObject::callMethodHelper( + QScriptEngine &engine, QObject *object, + const QString &propertyName, const QString &arguments) +{ + QScriptValue wrapper = engine.newQObject(object); + QScriptValue method = wrapper.property(propertyName); + QVERIFY(method.isFunction()); + + // Generate code that calls the function directly; in this way + // only function call performance is measured, not function lookup + // as well. + QString code = QString::fromLatin1( + "(function(f) {\n" + " for (var i = 0; i < %0; ++i)\n" + " f(%1);\n" + "})").arg(ITERATION_COUNT).arg(arguments); + QScriptValue fun = engine.evaluate(code); + QVERIFY(fun.isFunction()); + + QScriptValueList args; + args << method; + QBENCHMARK { + fun.call(wrapper, args); + } + QVERIFY(!engine.hasUncaughtException()); +} + +void tst_QScriptQObject::signalHandlerHelper( + QScriptEngine &engine, QObject *object, const char *signal) +{ + QScriptValue handler = engine.evaluate("(function(a) { return a; })"); + QVERIFY(handler.isFunction()); + QVERIFY(qScriptConnect(object, signal, QScriptValue(), handler)); +} + +void tst_QScriptQObject::readMetaProperty_data() +{ + readMetaProperty_dataHelper(&PropertyTestObject::staticMetaObject); +} + +// Reads a meta-object-defined property from JS. The purpose of this +// benchmark is to measure the overhead of reading a property from JS +// compared to calling the property getter directly from C++ without +// introspection or value conversion (that's the fastest we could +// possibly hope to get). +void tst_QScriptQObject::readMetaProperty() +{ + QFETCH(QString, propertyName); + + QScriptEngine engine; + PropertyTestObject testObject; + readPropertyHelper(engine, engine.newQObject(&testObject), propertyName); +} + +void tst_QScriptQObject::writeMetaProperty_data() +{ + readMetaProperty_data(); +} + +// Writes a meta-object-defined property from JS. The purpose of this +// benchmark is to measure the overhead of writing a property from JS +// compared to calling the property setter directly from C++ without +// introspection or value conversion (that's the fastest we could +// possibly hope to get). +void tst_QScriptQObject::writeMetaProperty() +{ + QFETCH(QString, propertyName); + + QScriptEngine engine; + PropertyTestObject testObject; + QScriptValue wrapper = engine.newQObject(&testObject); + QScriptValue value = wrapper.property(propertyName); + writePropertyHelper(engine, wrapper, propertyName, value); +} + +void tst_QScriptQObject::readDynamicProperty_data() +{ + QTest::addColumn<QVariant>("value"); + + QTest::newRow("bool") << QVariant(false); + QTest::newRow("int") << QVariant(123); + QTest::newRow("double") << QVariant(double(123.0)); + QTest::newRow("string") << QVariant(QString::fromLatin1("hello")); + QTest::newRow("QObject*") << qVariantFromValue((QObject*)this); + QTest::newRow("CustomType") << qVariantFromValue(CustomType()); +} + +// Reads a dynamic property from JS. The purpose of this benchmark is +// to measure the overhead of reading a dynamic property from JS +// versus calling QObject::property(aDynamicProperty) directly from +// C++. +void tst_QScriptQObject::readDynamicProperty() +{ + QFETCH(QVariant, value); + + QObject testObject; + const char *propertyName = "dynamicProperty"; + testObject.setProperty(propertyName, value); + QVERIFY(testObject.dynamicPropertyNames().contains(propertyName)); + + QScriptEngine engine; + readPropertyHelper(engine, engine.newQObject(&testObject), propertyName); +} + +void tst_QScriptQObject::writeDynamicProperty_data() +{ + readDynamicProperty_data(); +} + +// Writes an existing dynamic property from JS. The purpose of this +// benchmark is to measure the overhead of writing a dynamic property +// from JS versus calling QObject::setProperty(aDynamicProperty, +// aVariant) directly from C++. +void tst_QScriptQObject::writeDynamicProperty() +{ + QFETCH(QVariant, value); + + QObject testObject; + const char *propertyName = "dynamicProperty"; + testObject.setProperty(propertyName, value); + QVERIFY(testObject.dynamicPropertyNames().contains(propertyName)); + + QScriptEngine engine; + writePropertyHelper(engine, engine.newQObject(&testObject), propertyName, + qScriptValueFromValue(&engine, value)); +} + +void tst_QScriptQObject::readMethodByName_data() +{ + readMethodByName_dataHelper(&SlotTestObject::staticMetaObject); +} + +// Reads a meta-object-defined method from JS by name. The purpose of +// this benchmark is to measure the overhead of resolving a method +// from JS (effectively, creating and returning a JS wrapper function +// object for a C++ method). +void tst_QScriptQObject::readMethodByName() +{ + readMetaProperty(); +} + +void tst_QScriptQObject::readMethodBySignature_data() +{ + readMethodBySignature_dataHelper(&SlotTestObject::staticMetaObject); +} + +// Reads a meta-object-defined method from JS by signature. The +// purpose of this benchmark is to measure the overhead of resolving a +// method from JS (effectively, creating and returning a JS wrapper +// function object for a C++ method). +void tst_QScriptQObject::readMethodBySignature() +{ + QFETCH(QString, propertyName); + + QScriptEngine engine; + SlotTestObject testObject; + readPropertyHelper(engine, engine.newQObject(&testObject), propertyName, "['%0']"); +} + +void tst_QScriptQObject::readChild_data() +{ + QTest::addColumn<QString>("propertyName"); + + QTest::newRow("child") << "child"; +} + +// Reads a child object from JS. The purpose of this benchmark is to +// measure the overhead of reading a child object from JS compared to +// calling e.g. qFindChild() directly from C++, when the test object +// is a plain QObject with only one child. +void tst_QScriptQObject::readChild() +{ + QFETCH(QString, propertyName); + + QScriptEngine engine; + QObject testObject; + QObject *child = new QObject(&testObject); + child->setObjectName(propertyName); + readPropertyHelper(engine, engine.newQObject(&testObject), propertyName); +} + +void tst_QScriptQObject::readOneOfManyChildren_data() +{ + QTest::addColumn<QString>("propertyName"); + + QTest::newRow("child0") << "child0"; + QTest::newRow("child50") << "child50"; + QTest::newRow("child99") << "child99"; +} + +// Reads a child object from JS for an object that has many +// children. The purpose of this benchmark is to measure the overhead +// of reading a child object from JS compared to calling +// e.g. qFindChild() directly from C++. +void tst_QScriptQObject::readOneOfManyChildren() +{ + QFETCH(QString, propertyName); + + QScriptEngine engine; + QObject testObject; + for (int i = 0; i < 100; ++i) { + QObject *child = new QObject(&testObject); + child->setObjectName(QString::fromLatin1("child%0").arg(i)); + } + readPropertyHelper(engine, engine.newQObject(&testObject), propertyName); +} + +void tst_QScriptQObject::readPrototypeProperty_data() +{ + QTest::addColumn<QString>("propertyName"); + + // Inherited from Object.prototype. + QTest::newRow("hasOwnProperty") << "hasOwnProperty"; + QTest::newRow("isPrototypeOf") << "isPrototypeOf"; + QTest::newRow("propertyIsEnumerable") << "propertyIsEnumerable"; + QTest::newRow("valueOf") << "valueOf"; +} + +// Reads a property that's inherited from a prototype object. The +// purpose of this benchmark is to measure the overhead of resolving a +// prototype property (i.e., how long it takes the binding to +// determine that the QObject doesn't have the property itself). +void tst_QScriptQObject::readPrototypeProperty() +{ + QFETCH(QString, propertyName); + + QScriptEngine engine; + PropertyTestObject testObject; + readPropertyHelper(engine, engine.newQObject(&testObject), propertyName); +} + +void tst_QScriptQObject::readScriptProperty_data() +{ + QTest::addColumn<QString>("propertyName"); + + QTest::newRow("scriptProperty") << "scriptProperty"; +} + +// Reads a JS (non-Qt) property of a wrapper object. The purpose of +// this benchmark is to measure the overhead of reading a property +// that only exists on the wrapper object, not on the underlying +// QObject. +void tst_QScriptQObject::readScriptProperty() +{ + QFETCH(QString, propertyName); + + QScriptEngine engine; + PropertyTestObject testObject; + QScriptValue wrapper = engine.newQObject(&testObject); + wrapper.setProperty(propertyName, 123); + QVERIFY(wrapper.property(propertyName).isValid()); + QVERIFY(!testObject.property(propertyName.toLatin1()).isValid()); + + readPropertyHelper(engine, wrapper, propertyName); +} + +void tst_QScriptQObject::readNoSuchProperty_data() +{ + QTest::addColumn<QString>("propertyName"); + + QTest::newRow("noSuchProperty") << "noSuchProperty"; +} + +// Reads a non-existing (undefined) property of a wrapper object. The +// purpose of this benchmark is to measure the overhead of reading a +// property that doesn't exist (i.e., how long it takes the binding to +// determine this). +void tst_QScriptQObject::readNoSuchProperty() +{ + readMetaProperty(); +} + +// Reads all meta-object-defined properties from JS. The purpose of +// this benchmark is to measure the overhead of reading different +// properties in sequence, not just the same one repeatedly (like +// readMetaProperty() does). +void tst_QScriptQObject::readAllMetaProperties() +{ + PropertyTestObject testObject; + readAllMetaPropertiesHelper(&testObject); +} + +void tst_QScriptQObject::callSlot_data() +{ + QTest::addColumn<QString>("propertyName"); + QTest::addColumn<QString>("arguments"); + + QTest::newRow("voidSlot()") << "voidSlot" << ""; + + QTest::newRow("boolSlot(true)") << "boolSlot" << "true"; + QTest::newRow("intSlot(123)") << "intSlot" << "123"; + QTest::newRow("doubleSlot(123)") << "doubleSlot" << "123"; + QTest::newRow("stringSlot('hello')") << "stringSlot" << "'hello'"; + QTest::newRow("variantSlot(123)") << "variantSlot" << "123"; + QTest::newRow("qobjectSlot(this)") << "qobjectSlot" << "this"; // assumes 'this' is a QObject + + QTest::newRow("returnBoolSlot()") << "returnBoolSlot" << ""; + QTest::newRow("returnIntSlot()") << "returnIntSlot" << ""; + QTest::newRow("returnDoubleSlot()") << "returnDoubleSlot" << ""; + QTest::newRow("returnStringSlot()") << "returnStringSlot" << ""; + QTest::newRow("returnVariantSlot()") << "returnVariantSlot" << ""; + QTest::newRow("returnQObjectSlot()") << "returnQObjectSlot" << ""; + QTest::newRow("returnCustomTypeSlot()") << "returnCustomTypeSlot" << ""; + + // Implicit conversion. + QTest::newRow("boolSlot(0)") << "boolSlot" << "0"; + QTest::newRow("intSlot('123')") << "intSlot" << "'123'"; + QTest::newRow("doubleSlot('123')") << "doubleSlot" << "'123'"; + QTest::newRow("stringSlot(123)") << "stringSlot" << "123"; + + // Many arguments. + QTest::newRow("fourDoubleSlot(1,2,3,4)") << "fourDoubleSlot" << "1,2,3,4"; + QTest::newRow("sixDoubleSlot(1,2,3,4,5,6)") << "sixDoubleSlot" << "1,2,3,4,5,6"; + QTest::newRow("eightDoubleSlot(1,2,3,4,5,6,7,8)") << "eightDoubleSlot" << "1,2,3,4,5,6,7,8"; + + QTest::newRow("fourStringSlot('a','b','c','d')") << "fourStringSlot" << "'a','b','c','d'"; + QTest::newRow("sixStringSlot('a','b','c','d','e','f')") << "sixStringSlot" << "'a','b','c','d','e','f'"; + QTest::newRow("eightStringSlot('a','b','c','d','e','f','g','h')") << "eightStringSlot" << "'a','b','c','d','e','f','g','h'"; +} + +// Calls a slot from JS. The purpose of this benchmark is to measure +// the overhead of calling a slot from JS compared to calling the slot +// directly from C++ without introspection or value conversion (that's +// the fastest we could possibly hope to get). The slots themselves +// don't do any work. +void tst_QScriptQObject::callSlot() +{ + QFETCH(QString, propertyName); + QFETCH(QString, arguments); + + QScriptEngine engine; + SlotTestObject testObject; + callMethodHelper(engine, &testObject, propertyName, arguments); +} + +void tst_QScriptQObject::callOverloadedSlot_data() +{ + QTest::addColumn<QString>("propertyName"); + QTest::addColumn<QString>("arguments"); + + QTest::newRow("overloadedSlot()") << "overloadedSlot" << ""; + QTest::newRow("overloadedSlot(true)") << "overloadedSlot" << "true"; + QTest::newRow("overloadedSlot(123)") << "overloadedSlot" << "123"; + QTest::newRow("overloadedSlot('hello')") << "overloadedSlot" << "'hello'"; +} + +// Calls an overloaded slot from JS. The purpose of this benchmark is +// to measure the overhead of calling an overloaded slot from JS +// compared to calling the overloaded slot directly from C++ without +// introspection or value conversion (that's the fastest we could +// possibly hope to get). +void tst_QScriptQObject::callOverloadedSlot() +{ + QFETCH(QString, propertyName); + QFETCH(QString, arguments); + + QScriptEngine engine; + OverloadedSlotTestObject testObject; + callMethodHelper(engine, &testObject, propertyName, arguments); +} + +// Benchmarks for JS signal handling. The purpose of these benchmarks +// is to measure the overhead of dispatching a Qt signal to JS code +// compared to a normal C++ signal-to-slot dispatch. + +void tst_QScriptQObject::voidSignalHandler() +{ + SignalTestObject testObject; + QScriptEngine engine; + signalHandlerHelper(engine, &testObject, SIGNAL(voidSignal())); + QBENCHMARK { + for (int i = 0; i < ITERATION_COUNT; ++i) + testObject.emitVoidSignal(); + } +} + +void tst_QScriptQObject::boolSignalHandler() +{ + SignalTestObject testObject; + QScriptEngine engine; + signalHandlerHelper(engine, &testObject, SIGNAL(boolSignal(bool))); + QBENCHMARK { + for (int i = 0; i < ITERATION_COUNT; ++i) + testObject.emitBoolSignal(true); + } +} + +void tst_QScriptQObject::intSignalHandler() +{ + SignalTestObject testObject; + QScriptEngine engine; + signalHandlerHelper(engine, &testObject, SIGNAL(intSignal(int))); + QBENCHMARK { + for (int i = 0; i < ITERATION_COUNT; ++i) + testObject.emitIntSignal(123); + } +} + +void tst_QScriptQObject::doubleSignalHandler() +{ + SignalTestObject testObject; + QScriptEngine engine; + signalHandlerHelper(engine, &testObject, SIGNAL(doubleSignal(double))); + QBENCHMARK { + for (int i = 0; i < ITERATION_COUNT; ++i) + testObject.emitDoubleSignal(123.0); + } +} + +void tst_QScriptQObject::stringSignalHandler() +{ + SignalTestObject testObject; + QScriptEngine engine; + signalHandlerHelper(engine, &testObject, SIGNAL(stringSignal(QString))); + QString value = QString::fromLatin1("hello"); + QBENCHMARK { + for (int i = 0; i < ITERATION_COUNT; ++i) + testObject.emitStringSignal(value); + } +} + +void tst_QScriptQObject::variantSignalHandler() +{ + SignalTestObject testObject; + QScriptEngine engine; + signalHandlerHelper(engine, &testObject, SIGNAL(variantSignal(QVariant))); + QVariant value = 123; + QBENCHMARK { + for (int i = 0; i < ITERATION_COUNT; ++i) + testObject.emitVariantSignal(value); + } +} + +void tst_QScriptQObject::qobjectSignalHandler() +{ + SignalTestObject testObject; + QScriptEngine engine; + signalHandlerHelper(engine, &testObject, SIGNAL(qobjectSignal(QObject*))); + QBENCHMARK { + for (int i = 0; i < ITERATION_COUNT; ++i) + testObject.emitQObjectSignal(this); + } +} + +void tst_QScriptQObject::customTypeSignalHandler() +{ + SignalTestObject testObject; + QScriptEngine engine; + signalHandlerHelper(engine, &testObject, SIGNAL(customTypeSignal(CustomType))); + CustomType value; + QBENCHMARK { + for (int i = 0; i < ITERATION_COUNT; ++i) + testObject.emitCustomTypeSignal(value); + } +} + +void tst_QScriptQObject::readButtonMetaProperty_data() +{ + readMetaProperty_dataHelper(&QPushButton::staticMetaObject); +} + +// Reads a meta-object-defined property from JS. The purpose of this +// benchmark is to measure the overhead of reading a property from JS +// compared to calling the property getter directly from C++ without +// introspection or value conversion (that's the fastest we could +// possibly hope to get). +void tst_QScriptQObject::readButtonMetaProperty() +{ + QFETCH(QString, propertyName); + + QScriptEngine engine; + QPushButton pb; + readPropertyHelper(engine, engine.newQObject(&pb), propertyName); +} + +void tst_QScriptQObject::writeButtonMetaProperty_data() +{ + readButtonMetaProperty_data(); +} + +// Writes a meta-object-defined property from JS. The purpose of this +// benchmark is to measure the overhead of writing a property from JS +// compared to calling the property setter directly from C++ without +// introspection or value conversion (that's the fastest we could +// possibly hope to get). +void tst_QScriptQObject::writeButtonMetaProperty() +{ + QFETCH(QString, propertyName); + + QScriptEngine engine; + QPushButton pb; + QVariant value = pb.property(propertyName.toLatin1()); + writePropertyHelper(engine, engine.newQObject(&pb), propertyName, + qScriptValueFromValue(&engine, value)); +} + +void tst_QScriptQObject::readDynamicButtonProperty_data() +{ + readDynamicProperty_data(); +} + +// Reads a dynamic property from JS. The purpose of this benchmark is +// to measure the overhead of reading a dynamic property from JS +// versus calling QObject::property(aDynamicProperty) directly from +// C++. +void tst_QScriptQObject::readDynamicButtonProperty() +{ + QFETCH(QVariant, value); + + QPushButton pb; + const char *propertyName = "dynamicProperty"; + pb.setProperty(propertyName, value); + QVERIFY(pb.dynamicPropertyNames().contains(propertyName)); + + QScriptEngine engine; + readPropertyHelper(engine, engine.newQObject(&pb), propertyName); +} + +void tst_QScriptQObject::writeDynamicButtonProperty_data() +{ + readDynamicButtonProperty_data(); +} + +// Writes an existing dynamic property from JS. The purpose of this +// benchmark is to measure the overhead of writing a dynamic property +// from JS versus calling QObject::setProperty(aDynamicProperty, +// aVariant) directly from C++. +void tst_QScriptQObject::writeDynamicButtonProperty() +{ + QFETCH(QVariant, value); + + QPushButton pb; + const char *propertyName = "dynamicProperty"; + pb.setProperty(propertyName, value); + QVERIFY(pb.dynamicPropertyNames().contains(propertyName)); + + QScriptEngine engine; + writePropertyHelper(engine, engine.newQObject(&pb), propertyName, + qScriptValueFromValue(&engine, value)); +} + +void tst_QScriptQObject::readButtonMethodByName_data() +{ + readMethodByName_dataHelper(&QPushButton::staticMetaObject); +} + +// Reads a meta-object-defined method from JS by name. The purpose of +// this benchmark is to measure the overhead of resolving a method +// from JS (effectively, creating and returning a JS wrapper function +// object for a C++ method). +void tst_QScriptQObject::readButtonMethodByName() +{ + readButtonMetaProperty(); +} + +void tst_QScriptQObject::readButtonMethodBySignature_data() +{ + readMethodBySignature_dataHelper(&QPushButton::staticMetaObject); +} + +// Reads a meta-object-defined method from JS by signature. The +// purpose of this benchmark is to measure the overhead of resolving a +// method from JS (effectively, creating and returning a JS wrapper +// function object for a C++ method). +void tst_QScriptQObject::readButtonMethodBySignature() +{ + QFETCH(QString, propertyName); + + QScriptEngine engine; + QPushButton pb; + readPropertyHelper(engine, engine.newQObject(&pb), propertyName, "['%0']"); +} + +void tst_QScriptQObject::readButtonChild_data() +{ + QTest::addColumn<QString>("propertyName"); + + QTest::newRow("child") << "child"; +} + +// Reads a child object from JS. The purpose of this benchmark is to +// measure the overhead of reading a child object from JS compared to +// calling e.g. qFindChild() directly from C++. +void tst_QScriptQObject::readButtonChild() +{ + QFETCH(QString, propertyName); + + QScriptEngine engine; + QPushButton pb; + QObject *child = new QObject(&pb); + child->setObjectName(propertyName); + readPropertyHelper(engine, engine.newQObject(&pb), propertyName); +} + +void tst_QScriptQObject::readButtonPrototypeProperty_data() +{ + readPrototypeProperty_data(); +} + +// Reads a property that's inherited from a prototype object. The +// purpose of this benchmark is to measure the overhead of resolving a +// prototype property (i.e., how long does it take the binding to +// determine that the QObject doesn't have the property itself). +void tst_QScriptQObject::readButtonPrototypeProperty() +{ + QFETCH(QString, propertyName); + + QScriptEngine engine; + QPushButton pb; + readPropertyHelper(engine, engine.newQObject(&pb), propertyName); +} + +void tst_QScriptQObject::readButtonScriptProperty_data() +{ + readScriptProperty_data(); +} + +// Reads a JS (non-Qt) property of a wrapper object. The purpose of +// this benchmark is to measure the overhead of reading a property +// that only exists on the wrapper object, not on the underlying +// QObject. +void tst_QScriptQObject::readButtonScriptProperty() +{ + QFETCH(QString, propertyName); + + QScriptEngine engine; + QPushButton pb; + QScriptValue wrapper = engine.newQObject(&pb); + wrapper.setProperty(propertyName, 123); + QVERIFY(wrapper.property(propertyName).isValid()); + QVERIFY(!pb.property(propertyName.toLatin1()).isValid()); + + readPropertyHelper(engine, wrapper, propertyName); +} + +void tst_QScriptQObject::readNoSuchButtonProperty_data() +{ + readNoSuchProperty_data(); +} + +// Reads a non-existing (undefined) property of a wrapper object. The +// purpose of this benchmark is to measure the overhead of reading a +// property that doesn't exist (i.e., how long does it take the +// binding to determine that it doesn't exist). +void tst_QScriptQObject::readNoSuchButtonProperty() +{ + readButtonMetaProperty(); +} + +void tst_QScriptQObject::callButtonMethod_data() +{ + QTest::addColumn<QString>("propertyName"); + QTest::addColumn<QString>("arguments"); + + QTest::newRow("click()") << "click" << ""; + QTest::newRow("animateClick(50)") << "animateClick" << "10"; + QTest::newRow("setChecked(true)") << "setChecked" << "true"; + QTest::newRow("close()") << "close" << ""; + QTest::newRow("setWindowTitle('foo')") << "setWindowTitle" << "'foo'"; +} + +// Calls a slot from JS. The purpose of this benchmark is to measure +// the overhead of calling a slot from JS compared to calling the slot +// directly from C++ without introspection or value conversion (that's +// the fastest we could possibly hope to get). +void tst_QScriptQObject::callButtonMethod() +{ + QFETCH(QString, propertyName); + QFETCH(QString, arguments); + + QScriptEngine engine; + QPushButton pb; + callMethodHelper(engine, &pb, propertyName, arguments); +} + +// Reads all meta-object-defined properties from JS. The purpose of +// this benchmark is to measure the overhead of reading different +// properties in sequence, not just the same one repeatedly (like +// readButtonMetaProperty() does). +void tst_QScriptQObject::readAllButtonMetaProperties() +{ + QPushButton pb; + readAllMetaPropertiesHelper(&pb); +} + +void tst_QScriptQObject::readQScriptableMetaProperty_data() +{ + readMetaProperty_dataHelper(&QtScriptablePropertyTestObject::staticMetaObject); +} + +// Reads a meta-object-defined property from JS for an object that +// subclasses QScriptable. The purpose of this benchmark is to measure +// the overhead compared to reading a property of a non-QScriptable +// (see readMetaProperty()). +void tst_QScriptQObject::readQScriptableMetaProperty() +{ + QFETCH(QString, propertyName); + + QScriptEngine engine; + QtScriptablePropertyTestObject testObject; + readPropertyHelper(engine, engine.newQObject(&testObject), propertyName); +} + +void tst_QScriptQObject::writeQScriptableMetaProperty_data() +{ + readMetaProperty_data(); +} + +// Writes a meta-object-defined property from JS for an object that +// subclasses QScriptable. The purpose of this benchmark is to measure +// the overhead compared to writing a property of a non-QScriptable +// object (see writeMetaProperty()). +void tst_QScriptQObject::writeQScriptableMetaProperty() +{ + QFETCH(QString, propertyName); + + QScriptEngine engine; + QtScriptablePropertyTestObject testObject; + QVariant value = testObject.property(propertyName.toLatin1()); + writePropertyHelper(engine, engine.newQObject(&testObject), propertyName, + qScriptValueFromValue(&engine, value)); +} + +void tst_QScriptQObject::callQScriptableSlot_data() +{ + callSlot_data(); +} + +// Calls a slot from JS for an object that subclasses QScriptable. The +// purpose of this benchmark is to measure the overhead compared to +// calling a slot of a non-QScriptable object (see callSlot()). +void tst_QScriptQObject::callQScriptableSlot() +{ + QFETCH(QString, propertyName); + QFETCH(QString, arguments); + + QScriptEngine engine; + QtScriptableSlotTestObject testObject; + callMethodHelper(engine, &testObject, propertyName, arguments); +} + +QTEST_MAIN(tst_QScriptQObject) +#include "tst_qscriptqobject.moc" diff --git a/tests/shared/filesystem.h b/tests/shared/filesystem.h index 2d46c0d..079a6dc 100644 --- a/tests/shared/filesystem.h +++ b/tests/shared/filesystem.h @@ -48,6 +48,15 @@ #include <QDir> #include <QFile> +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#include <windows.h> +#include <winioctl.h> +#ifndef IO_REPARSE_TAG_MOUNT_POINT +#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) +#endif +#define REPARSE_MOUNTPOINT_HEADER_SIZE 8 +#endif + struct FileSystem { ~FileSystem() @@ -86,6 +95,59 @@ struct FileSystem } return false; } +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + static void createNtfsJunction(QString target, QString linkName) + { + typedef struct { + DWORD ReparseTag; + DWORD ReparseDataLength; + WORD Reserved; + WORD ReparseTargetLength; + WORD ReparseTargetMaximumLength; + WORD Reserved1; + WCHAR ReparseTarget[1]; + } REPARSE_MOUNTPOINT_DATA_BUFFER, *PREPARSE_MOUNTPOINT_DATA_BUFFER; + + char reparseBuffer[MAX_PATH*3]; + HANDLE hFile; + DWORD returnedLength; + wchar_t fileSystem[MAX_PATH] = L""; + PREPARSE_MOUNTPOINT_DATA_BUFFER reparseInfo = (PREPARSE_MOUNTPOINT_DATA_BUFFER) reparseBuffer; + + QFileInfo junctionInfo(linkName); + linkName = QDir::toNativeSeparators(junctionInfo.absoluteFilePath()); + + GetVolumeInformationW( (wchar_t*)linkName.left(3).utf16(), NULL, 0, NULL, NULL, NULL, + fileSystem, sizeof(fileSystem)/sizeof(WCHAR)); + if(QString().fromWCharArray(fileSystem) != "NTFS") + QSKIP("This seems not to be an NTFS volume. Junctions are not allowed.",SkipSingle); + + if (!target.startsWith("\\??\\") && !target.startsWith("\\\\?\\")) { + QFileInfo targetInfo(target); + target = QDir::toNativeSeparators(targetInfo.absoluteFilePath()); + target.prepend("\\??\\"); + if(target.endsWith('\\') && target.at(target.length()-2) != ':') + target.chop(1); + } + QDir().mkdir(linkName); + hFile = CreateFileW( (wchar_t*)linkName.utf16(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL ); + QVERIFY(hFile != INVALID_HANDLE_VALUE ); + + memset( reparseInfo, 0, sizeof( *reparseInfo )); + reparseInfo->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; + reparseInfo->ReparseTargetLength = target.size() * sizeof(wchar_t); + reparseInfo->ReparseTargetMaximumLength = reparseInfo->ReparseTargetLength + sizeof(wchar_t); + target.toWCharArray(reparseInfo->ReparseTarget); + reparseInfo->ReparseDataLength = reparseInfo->ReparseTargetLength + 12; + + bool ioc = DeviceIoControl(hFile, FSCTL_SET_REPARSE_POINT, reparseInfo, + reparseInfo->ReparseDataLength + REPARSE_MOUNTPOINT_HEADER_SIZE, + NULL, 0, &returnedLength, NULL); + CloseHandle( hFile ); + QVERIFY(ioc); + } +#endif private: QDir currentDir; diff --git a/tools/activeqt/testcon/changeproperties.cpp b/tools/activeqt/testcon/changeproperties.cpp index 00a2cab..eca1bf9 100644 --- a/tools/activeqt/testcon/changeproperties.cpp +++ b/tools/activeqt/testcon/changeproperties.cpp @@ -108,7 +108,7 @@ void ChangeProperties::on_buttonSet_clicked() QColor col; col.setNamedColor(editValue->text()); if (col.isValid()) { - value = qVariantFromValue(col); + value = QVariant::fromValue(col); } else { QMessageBox::warning(this, tr("Can't parse input"), tr("Failed to create a color from %1\n" @@ -122,7 +122,7 @@ void ChangeProperties::on_buttonSet_clicked() { QFont fnt; if (fnt.fromString(editValue->text())) { - value = qVariantFromValue(fnt); + value = QVariant::fromValue(fnt); } else { QMessageBox::warning(this, tr("Can't parse input"), tr("Failed to create a font from %1\n" @@ -141,7 +141,7 @@ void ChangeProperties::on_buttonSet_clicked() if (pm.isNull()) return; - value = qVariantFromValue(pm); + value = QVariant::fromValue(pm); } break; case QVariant::Bool: diff --git a/tools/assistant/tools/assistant/aboutdialog.cpp b/tools/assistant/tools/assistant/aboutdialog.cpp index a9bc352..9935a1e 100644 --- a/tools/assistant/tools/assistant/aboutdialog.cpp +++ b/tools/assistant/tools/assistant/aboutdialog.cpp @@ -38,6 +38,9 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + +#include "aboutdialog.h" + #include "helpviewer.h" #include "tracer.h" @@ -51,8 +54,6 @@ #include <QtGui/QMessageBox> #include <QtGui/QDesktopServices> -#include "aboutdialog.h" - QT_BEGIN_NAMESPACE AboutLabel::AboutLabel(QWidget *parent) @@ -96,8 +97,8 @@ QVariant AboutLabel::loadResource(int type, const QUrl &name) void AboutLabel::setSource(const QUrl &url) { TRACE_OBJ - if (url.isValid() && (!AbstractHelpViewer::isLocalUrl(url) - || !AbstractHelpViewer::canOpenPage(url.path()))) { + if (url.isValid() && (!HelpViewer::isLocalUrl(url) + || !HelpViewer::canOpenPage(url.path()))) { if (!QDesktopServices::openUrl(url)) { QMessageBox::warning(this, tr("Warning"), tr("Unable to launch external application.\n"), tr("OK")); diff --git a/tools/assistant/tools/assistant/assistant.pro b/tools/assistant/tools/assistant/assistant.pro index d9aff7a..7f0fdd1 100644 --- a/tools/assistant/tools/assistant/assistant.pro +++ b/tools/assistant/tools/assistant/assistant.pro @@ -12,6 +12,8 @@ DESTDIR = ../../../../bin target.path = $$[QT_INSTALL_BINS] INSTALLS += target DEPENDPATH += ../shared +DEPENDPATH += . +INCLUDEPATH += . # ## Work around a qmake issue when statically linking to # ## not-yet-installed plugins @@ -30,6 +32,7 @@ HEADERS += aboutdialog.h \ filternamedialog.h \ helpenginewrapper.h \ helpviewer.h \ + helpviewer_p.h \ indexwindow.h \ installdialog.h \ mainwindow.h \ @@ -40,12 +43,12 @@ HEADERS += aboutdialog.h \ topicchooser.h \ tracer.h \ xbelsupport.h \ - ../shared/collectionconfiguration.h -contains(QT_CONFIG, webkit) { - HEADERS += helpviewer_qwv.h -} else { - HEADERS += helpviewer_qtb.h - } + ../shared/collectionconfiguration.h \ + openpagesmodel.h \ + globalactions.h \ + openpageswidget.h \ + openpagesmanager.h \ + openpagesswitcher.h win32:HEADERS += remotecontrol_win.h SOURCES += aboutdialog.cpp \ @@ -72,8 +75,13 @@ SOURCES += aboutdialog.cpp \ searchwidget.cpp \ topicchooser.cpp \ xbelsupport.cpp \ - ../shared/collectionconfiguration.cpp - contains(QT_CONFIG, webkit) { + ../shared/collectionconfiguration.cpp \ + openpagesmodel.cpp \ + globalactions.cpp \ + openpageswidget.cpp \ + openpagesmanager.cpp \ + openpagesswitcher.cpp +contains(QT_CONFIG, webkit) { SOURCES += helpviewer_qwv.cpp } else { SOURCES += helpviewer_qtb.cpp diff --git a/tools/assistant/tools/assistant/assistant_images.qrc b/tools/assistant/tools/assistant/assistant_images.qrc index 34918c0..b4f2523 100644 --- a/tools/assistant/tools/assistant/assistant_images.qrc +++ b/tools/assistant/tools/assistant/assistant_images.qrc @@ -1,11 +1,10 @@ <RCC> - <qresource prefix="/trolltech/assistant" > + <qresource prefix="/trolltech/assistant"> <file>images/trolltech-logo.png</file> <file>images/assistant-128.png</file> <file>images/assistant.png</file> <file>images/wrap.png</file> <file>images/bookmark.png</file> -#mac <file>images/mac/addtab.png</file> <file>images/mac/book.png</file> <file>images/mac/closetab.png</file> @@ -19,7 +18,6 @@ <file>images/mac/zoomin.png</file> <file>images/mac/zoomout.png</file> <file>images/mac/resetzoom.png</file> -#win <file>images/win/addtab.png</file> <file>images/win/book.png</file> <file>images/win/closetab.png</file> @@ -33,5 +31,7 @@ <file>images/win/zoomin.png</file> <file>images/win/zoomout.png</file> <file>images/win/resetzoom.png</file> + <file>images/closebutton.png</file> + <file>images/darkclosebutton.png</file> </qresource> </RCC> diff --git a/tools/assistant/tools/assistant/bookmarkfiltermodel.cpp b/tools/assistant/tools/assistant/bookmarkfiltermodel.cpp index 7a7c2e3..fe510a5 100644 --- a/tools/assistant/tools/assistant/bookmarkfiltermodel.cpp +++ b/tools/assistant/tools/assistant/bookmarkfiltermodel.cpp @@ -50,11 +50,30 @@ BookmarkFilterModel::BookmarkFilterModel(QObject *parent) { } -void -BookmarkFilterModel::setSourceModel(QAbstractItemModel *_sourceModel) +void BookmarkFilterModel::setSourceModel(QAbstractItemModel *_sourceModel) { beginResetModel(); + disconnect(sourceModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, + SLOT(changed(QModelIndex, QModelIndex))); + + disconnect(sourceModel, SIGNAL(rowsInserted(QModelIndex, int, int)), + this, SLOT(rowsInserted(QModelIndex, int, int))); + + disconnect(sourceModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), + this, SLOT(rowsAboutToBeRemoved(QModelIndex, int, int))); + disconnect(sourceModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, + SLOT(rowsRemoved(QModelIndex, int, int))); + + disconnect(sourceModel, SIGNAL(layoutAboutToBeChanged()), this, + SLOT(layoutAboutToBeChanged())); + disconnect(sourceModel, SIGNAL(layoutChanged()), this, + SLOT(layoutChanged())); + + disconnect(sourceModel, SIGNAL(modelAboutToBeReset()), this, + SLOT(modelAboutToBeReset())); + disconnect(sourceModel, SIGNAL(modelReset()), this, SLOT(modelReset())); + QAbstractProxyModel::setSourceModel(sourceModel); sourceModel = qobject_cast<BookmarkModel*> (_sourceModel); @@ -79,20 +98,18 @@ BookmarkFilterModel::setSourceModel(QAbstractItemModel *_sourceModel) connect(sourceModel, SIGNAL(modelReset()), this, SLOT(modelReset())); if (sourceModel) - setupCache(sourceModel->index(0, 0, QModelIndex())); + setupCache(sourceModel->index(0, 0, QModelIndex()).parent()); endResetModel(); } -int -BookmarkFilterModel::rowCount(const QModelIndex &index) const +int BookmarkFilterModel::rowCount(const QModelIndex &index) const { Q_UNUSED(index) return cache.count(); } -int -BookmarkFilterModel::columnCount(const QModelIndex &index) const +int BookmarkFilterModel::columnCount(const QModelIndex &index) const { Q_UNUSED(index) if (sourceModel) @@ -100,8 +117,7 @@ BookmarkFilterModel::columnCount(const QModelIndex &index) const return 0; } -QModelIndex -BookmarkFilterModel::mapToSource(const QModelIndex &proxyIndex) const +QModelIndex BookmarkFilterModel::mapToSource(const QModelIndex &proxyIndex) const { const int row = proxyIndex.row(); if (proxyIndex.isValid() && row >= 0 && row < cache.count()) @@ -109,21 +125,19 @@ BookmarkFilterModel::mapToSource(const QModelIndex &proxyIndex) const return QModelIndex(); } -QModelIndex -BookmarkFilterModel::mapFromSource(const QModelIndex &sourceIndex) const +QModelIndex BookmarkFilterModel::mapFromSource(const QModelIndex &sourceIndex) const { return index(cache.indexOf(sourceIndex), 0, QModelIndex()); } -QModelIndex -BookmarkFilterModel::parent(const QModelIndex &child) const +QModelIndex BookmarkFilterModel::parent(const QModelIndex &child) const { Q_UNUSED(child) return QModelIndex(); } -QModelIndex -BookmarkFilterModel::index(int row, int column, const QModelIndex &index) const +QModelIndex BookmarkFilterModel::index(int row, int column, + const QModelIndex &index) const { Q_UNUSED(index) if (row < 0 || column < 0 || cache.count() <= row @@ -133,32 +147,28 @@ BookmarkFilterModel::index(int row, int column, const QModelIndex &index) const return createIndex(row, 0); } -Qt::DropActions -BookmarkFilterModel::supportedDropActions () const +Qt::DropActions BookmarkFilterModel::supportedDropActions () const { if (sourceModel) return sourceModel->supportedDropActions(); return Qt::IgnoreAction; } -Qt::ItemFlags -BookmarkFilterModel::flags(const QModelIndex &index) const +Qt::ItemFlags BookmarkFilterModel::flags(const QModelIndex &index) const { if (sourceModel) return sourceModel->flags(index); return Qt::NoItemFlags; } -QVariant -BookmarkFilterModel::data(const QModelIndex &index, int role) const +QVariant BookmarkFilterModel::data(const QModelIndex &index, int role) const { if (sourceModel) return sourceModel->data(mapToSource(index), role); return QVariant(); } -bool -BookmarkFilterModel::setData(const QModelIndex &index, const QVariant &value, +bool BookmarkFilterModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (sourceModel) @@ -166,37 +176,34 @@ BookmarkFilterModel::setData(const QModelIndex &index, const QVariant &value, return false; } -void -BookmarkFilterModel::filterBookmarks() +void BookmarkFilterModel::filterBookmarks() { if (sourceModel) { beginResetModel(); hideBookmarks = true; - setupCache(sourceModel->index(0, 0, QModelIndex())); + setupCache(sourceModel->index(0, 0, QModelIndex()).parent()); endResetModel(); } } -void -BookmarkFilterModel::filterBookmarkFolders() +void BookmarkFilterModel::filterBookmarkFolders() { if (sourceModel) { beginResetModel(); hideBookmarks = false; - setupCache(sourceModel->index(0, 0, QModelIndex())); + setupCache(sourceModel->index(0, 0, QModelIndex()).parent()); endResetModel(); } } -void -BookmarkFilterModel::changed(const QModelIndex &topLeft, +void BookmarkFilterModel::changed(const QModelIndex &topLeft, const QModelIndex &bottomRight) { emit dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight)); } -void -BookmarkFilterModel::rowsInserted(const QModelIndex &parent, int start, int end) +void BookmarkFilterModel::rowsInserted(const QModelIndex &parent, int start, + int end) { if (!sourceModel) return; @@ -218,15 +225,16 @@ BookmarkFilterModel::rowsInserted(const QModelIndex &parent, int start, int end) const bool isFolder = newIndex.data(UserRoleFolder).toBool(); if ((isFolder && hideBookmarks) || (!isFolder && !hideBookmarks)) { beginInsertRows(mapFromSource(parent), start, end); - cache.insert(cache.indexOf(cachePrevious) + 1, newIndex); + const int index = cache.indexOf(cachePrevious) + 1; + if (cache.value(index, QPersistentModelIndex()) != newIndex) + cache.insert(index, newIndex); endInsertRows(); } } } -void -BookmarkFilterModel::rowsAboutToBeRemoved(const QModelIndex &parent, int start, - int end) +void BookmarkFilterModel::rowsAboutToBeRemoved(const QModelIndex &parent, + int start, int end) { if (!sourceModel) return; @@ -240,8 +248,7 @@ BookmarkFilterModel::rowsAboutToBeRemoved(const QModelIndex &parent, int start, } } -void -BookmarkFilterModel::rowsRemoved(const QModelIndex &/*parent*/, int, int) +void BookmarkFilterModel::rowsRemoved(const QModelIndex &/*parent*/, int, int) { if (cache.contains(indexToRemove)) { cache.removeAll(indexToRemove); @@ -249,41 +256,36 @@ BookmarkFilterModel::rowsRemoved(const QModelIndex &/*parent*/, int, int) } } -void -BookmarkFilterModel::layoutAboutToBeChanged() +void BookmarkFilterModel::layoutAboutToBeChanged() { // TODO: ??? } -void -BookmarkFilterModel::layoutChanged() +void BookmarkFilterModel::layoutChanged() { // TODO: ??? } -void -BookmarkFilterModel::modelAboutToBeReset() +void BookmarkFilterModel::modelAboutToBeReset() { beginResetModel(); } -void -BookmarkFilterModel::modelReset() +void BookmarkFilterModel::modelReset() { if (sourceModel) - setupCache(sourceModel->index(0, 0, QModelIndex())); + setupCache(sourceModel->index(0, 0, QModelIndex()).parent()); endResetModel(); } -void -BookmarkFilterModel::setupCache(const QModelIndex &parent) +void BookmarkFilterModel::setupCache(const QModelIndex &parent) { cache.clear(); - collectItems(parent); + for (int i = 0; i < sourceModel->rowCount(parent); ++i) + collectItems(sourceModel->index(i, 0, parent)); } -void -BookmarkFilterModel::collectItems(const QModelIndex &parent) +void BookmarkFilterModel::collectItems(const QModelIndex &parent) { if (parent.isValid()) { bool isFolder = sourceModel->data(parent, UserRoleFolder).toBool(); @@ -304,14 +306,12 @@ BookmarkTreeModel::BookmarkTreeModel(QObject *parent) { } -int -BookmarkTreeModel::columnCount(const QModelIndex &parent) const +int BookmarkTreeModel::columnCount(const QModelIndex &parent) const { return qMin(1, QSortFilterProxyModel::columnCount(parent)); } -bool -BookmarkTreeModel::filterAcceptsRow(int row, const QModelIndex &parent) const +bool BookmarkTreeModel::filterAcceptsRow(int row, const QModelIndex &parent) const { Q_UNUSED(row) BookmarkModel *model = qobject_cast<BookmarkModel*> (sourceModel()); diff --git a/tools/assistant/tools/assistant/bookmarkmanager.cpp b/tools/assistant/tools/assistant/bookmarkmanager.cpp index 23632b1..7a11ffe 100644 --- a/tools/assistant/tools/assistant/bookmarkmanager.cpp +++ b/tools/assistant/tools/assistant/bookmarkmanager.cpp @@ -53,6 +53,7 @@ #include <QtGui/QKeyEvent> #include <QtGui/QMessageBox> #include <QtGui/QSortFilterProxyModel> +#include <QtGui/QToolBar> QT_BEGIN_NAMESPACE @@ -136,11 +137,18 @@ QWidget* BookmarkManager::bookmarkDockWidget() const return 0; } -void BookmarkManager::takeBookmarksMenu(QMenu* menu) +void BookmarkManager::setBookmarksMenu(QMenu* menu) { TRACE_OBJ bookmarkMenu = menu; - refeshBookmarkMenu(); + refreshBookmarkMenu(); +} + +void BookmarkManager::setBookmarksToolbar(QToolBar *toolBar) +{ + TRACE_OBJ + m_toolBar = toolBar; + refreshBookmarkToolBar(); } // -- public slots @@ -157,7 +165,10 @@ void BookmarkManager::addBookmark(const QString &title, const QString &url) BookmarkManager::BookmarkManager() : typeAndSearch(false) , bookmarkMenu(0) + , m_toolBar(0) , bookmarkModel(new BookmarkModel) + , bookmarkFilterModel(0) + , typeAndSearchModel(0) , bookmarkWidget(new BookmarkWidget) , bookmarkTreeView(new BookmarkTreeView) , bookmarkManagerWidget(0) @@ -186,11 +197,18 @@ BookmarkManager::BookmarkManager() connect(&HelpEngineWrapper::instance(), SIGNAL(setupFinished()), this, SLOT(setupFinished())); connect(bookmarkModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, - SLOT(refeshBookmarkMenu())); + SLOT(refreshBookmarkMenu())); + connect(bookmarkModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this, + SLOT(refreshBookmarkMenu())); + connect(bookmarkModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, + SLOT(refreshBookmarkMenu())); + + connect(bookmarkModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, + SLOT(refreshBookmarkToolBar())); connect(bookmarkModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this, - SLOT(refeshBookmarkMenu())); + SLOT(refreshBookmarkToolBar())); connect(bookmarkModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, - SLOT(refeshBookmarkMenu())); + SLOT(refreshBookmarkToolBar())); } BookmarkManager::~BookmarkManager() @@ -283,7 +301,7 @@ void BookmarkManager::buildBookmarksMenu(const QModelIndex &index, QMenu* menu) return; const QString &text = index.data().toString(); - const QIcon &icon = qVariantValue<QIcon>(index.data(Qt::DecorationRole)); + const QIcon &icon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole)); if (index.data(UserRoleFolder).toBool()) { if (QMenu* subMenu = menu->addMenu(icon, text)) { for (int i = 0; i < bookmarkModel->rowCount(index); ++i) @@ -310,17 +328,20 @@ void BookmarkManager::setupFinished() bookmarkModel->setBookmarks(HelpEngineWrapper::instance().bookmarks()); bookmarkModel->expandFoldersIfNeeeded(bookmarkTreeView); - refeshBookmarkMenu(); + refreshBookmarkMenu(); + refreshBookmarkToolBar(); bookmarkTreeView->hideColumn(1); bookmarkTreeView->header()->setVisible(false); bookmarkTreeView->header()->setStretchLastSection(true); - bookmarkFilterModel = new BookmarkFilterModel(this); + if (!bookmarkFilterModel) + bookmarkFilterModel = new BookmarkFilterModel(this); bookmarkFilterModel->setSourceModel(bookmarkModel); bookmarkFilterModel->filterBookmarkFolders(); - typeAndSearchModel = new QSortFilterProxyModel(this); + if (!typeAndSearchModel) + typeAndSearchModel = new QSortFilterProxyModel(this); typeAndSearchModel->setDynamicSortFilter(true); typeAndSearchModel->setSourceModel(bookmarkFilterModel); } @@ -354,7 +375,7 @@ void BookmarkManager::manageBookmarks() bookmarkManagerWidget->raise(); } -void BookmarkManager::refeshBookmarkMenu() +void BookmarkManager::refreshBookmarkMenu() { TRACE_OBJ if (!bookmarkMenu) @@ -365,11 +386,16 @@ void BookmarkManager::refeshBookmarkMenu() bookmarkMenu->addAction(tr("Manage Bookmarks..."), this, SLOT(manageBookmarks())); bookmarkMenu->addAction(QIcon::fromTheme("bookmark-new"), - tr("Add Bookmark..."), this, SLOT(addBookmark()), - QKeySequence(tr("Ctrl+D"))); + tr("Add Bookmark..."), this, SLOT(addBookmark()), QKeySequence(tr("Ctrl+D"))); + bookmarkMenu->addSeparator(); - const QModelIndex &root = bookmarkModel->index(0, 0, QModelIndex()); + QModelIndex root = bookmarkModel->index(0, 0, QModelIndex()).parent(); + buildBookmarksMenu(bookmarkModel->index(0, 0, root), bookmarkMenu); + + bookmarkMenu->addSeparator(); + + root = bookmarkModel->index(1, 0, QModelIndex()); for (int i = 0; i < bookmarkModel->rowCount(root); ++i) buildBookmarksMenu(bookmarkModel->index(i, 0, root), bookmarkMenu); @@ -377,6 +403,41 @@ void BookmarkManager::refeshBookmarkMenu() SLOT(setSourceFromAction(QAction*))); } +void BookmarkManager::refreshBookmarkToolBar() +{ + TRACE_OBJ + if (!m_toolBar) + return; + + m_toolBar->clear(); + m_toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + + const QModelIndex &root = bookmarkModel->index(0, 0, QModelIndex()); + for (int i = 0; i < bookmarkModel->rowCount(root); ++i) { + const QModelIndex &index = bookmarkModel->index(i, 0, root); + if (index.data(UserRoleFolder).toBool()) { + QToolButton *button = new QToolButton(m_toolBar); + button->setPopupMode(QToolButton::InstantPopup); + button->setText(index.data().toString()); + QMenu *menu = new QMenu(button); + for (int j = 0; j < bookmarkModel->rowCount(index); ++j) + buildBookmarksMenu(bookmarkModel->index(j, 0, index), menu); + connect(menu, SIGNAL(triggered(QAction*)), this, + SLOT(setSourceFromAction(QAction*))); + button->setMenu(menu); + button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + button->setIcon(qvariant_cast<QIcon>(index.data(Qt::DecorationRole))); + QAction *a = m_toolBar->addWidget(button); + a->setText(index.data().toString()); + } else { + QAction *action = m_toolBar->addAction( + qvariant_cast<QIcon>(index.data(Qt::DecorationRole)), + index.data().toString(), this, SLOT(setSourceFromAction())); + action->setData(index.data(UserRoleUrl).toString()); + } + } +} + void BookmarkManager::renameBookmark(const QModelIndex &index) { // check if we should rename the "Bookmarks Menu", bail @@ -388,13 +449,21 @@ void BookmarkManager::renameBookmark(const QModelIndex &index) bookmarkModel->setItemsEditable(false); } -void BookmarkManager::setSourceFromAction(QAction *action) + +void BookmarkManager::setSourceFromAction() { TRACE_OBJ - const QVariant &data = action->data(); + setSourceFromAction(qobject_cast<QAction*> (sender())); +} - if (data.canConvert<QUrl>()) - emit setSource(data.toUrl()); +void BookmarkManager::setSourceFromAction(QAction *action) +{ + TRACE_OBJ + if (action) { + const QVariant &data = action->data(); + if (data.canConvert<QUrl>()) + emit setSource(data.toUrl()); + } } void BookmarkManager::setSourceFromIndex(const QModelIndex &index, bool newTab) diff --git a/tools/assistant/tools/assistant/bookmarkmanager.h b/tools/assistant/tools/assistant/bookmarkmanager.h index c26dad8..ae27b59 100644 --- a/tools/assistant/tools/assistant/bookmarkmanager.h +++ b/tools/assistant/tools/assistant/bookmarkmanager.h @@ -53,6 +53,7 @@ class BookmarkModel; class BookmarkFilterModel; class QKeyEvent; class QSortFilterProxyModel; +class QToolBar; class BookmarkManager : public QObject { @@ -67,7 +68,8 @@ public: static void destroy(); QWidget* bookmarkDockWidget() const; - void takeBookmarksMenu(QMenu* menu); + void setBookmarksMenu(QMenu* menu); + void setBookmarksToolbar(QToolBar *toolBar); public slots: void addBookmark(const QString &title, const QString &url); @@ -92,9 +94,11 @@ private slots: void addBookmark(); void removeBookmark(); void manageBookmarks(); - void refeshBookmarkMenu(); + void refreshBookmarkMenu(); + void refreshBookmarkToolBar(); void renameBookmark(const QModelIndex &index); + void setSourceFromAction(); void setSourceFromAction(QAction *action); void setSourceFromIndex(const QModelIndex &index, bool newTab = false); @@ -110,6 +114,7 @@ private: static BookmarkManager *bookmarkManager; QMenu *bookmarkMenu; + QToolBar *m_toolBar; BookmarkModel *bookmarkModel; BookmarkFilterModel *bookmarkFilterModel; diff --git a/tools/assistant/tools/assistant/bookmarkmodel.cpp b/tools/assistant/tools/assistant/bookmarkmodel.cpp index 4c30b42..320b233 100644 --- a/tools/assistant/tools/assistant/bookmarkmodel.cpp +++ b/tools/assistant/tools/assistant/bookmarkmodel.cpp @@ -48,6 +48,7 @@ #include <QtGui/QStyle> #include <QtGui/QTreeView> +const quint32 VERSION = 0xe53798; const QLatin1String MIMETYPE("application/bookmarks.assistant"); BookmarkModel::BookmarkModel() @@ -68,8 +69,9 @@ BookmarkModel::bookmarks() const { QByteArray ba; QDataStream stream(&ba, QIODevice::WriteOnly); + stream << qint32(VERSION); - const QModelIndex &root = index(0,0, QModelIndex()); + const QModelIndex &root = index(0,0, QModelIndex()).parent(); for (int i = 0; i < rowCount(root); ++i) collectItems(index(i, 0, root), 0, &stream); @@ -87,24 +89,35 @@ BookmarkModel::setBookmarks(const QByteArray &bookmarks) rootItem = new BookmarkItem(DataVector() << tr("Name") << tr("Address") << true); - BookmarkItem* item = new BookmarkItem(DataVector() << tr("Bookmarks Menu") - << QLatin1String("Folder") << true); - rootItem->addChild(item); QStack<BookmarkItem*> parents; - parents.push(item); + QDataStream stream(bookmarks); + + qint32 version; + stream >> version; + if (version < VERSION) { + stream.device()->seek(0); + BookmarkItem* toolbar = new BookmarkItem(DataVector() << tr("Toolbar Menu") + << QLatin1String("Folder") << true); + rootItem->addChild(toolbar); + + BookmarkItem* menu = new BookmarkItem(DataVector() << tr("Bookmarks Menu") + << QLatin1String("Folder") << true); + rootItem->addChild(menu); + parents.push(menu); + } else { + parents.push(rootItem); + } qint32 depth; bool expanded; QString name, url; - QDataStream stream(bookmarks); while (!stream.atEnd()) { stream >> depth >> name >> url >> expanded; - while ((parents.count() - 1) != depth) parents.pop(); - item = new BookmarkItem(DataVector() << name << url << expanded); + BookmarkItem *item = new BookmarkItem(DataVector() << name << url << expanded); if (url == QLatin1String("Folder")) { parents.top()->addChild(item); parents.push(item); @@ -114,11 +127,7 @@ BookmarkModel::setBookmarks(const QByteArray &bookmarks) } cache.clear(); - const QModelIndex &root = index(0,0, QModelIndex()); - - setupCache(root); - cache.insert(static_cast<BookmarkItem*> (root.internalPointer()), root); - + setupCache(index(0,0, QModelIndex().parent())); endResetModel(); } diff --git a/tools/assistant/tools/assistant/centralwidget.cpp b/tools/assistant/tools/assistant/centralwidget.cpp index f42dfdf..a232383 100644 --- a/tools/assistant/tools/assistant/centralwidget.cpp +++ b/tools/assistant/tools/assistant/centralwidget.cpp @@ -38,966 +38,514 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "tracer.h" #include "centralwidget.h" + #include "findwidget.h" #include "helpenginewrapper.h" -#include "searchwidget.h" -#include "mainwindow.h" +#include "helpviewer.h" +#include "openpagesmanager.h" +#include "tracer.h" #include "../shared/collectionconfiguration.h" -#if defined(QT_NO_WEBKIT) -#include "helpviewer_qtb.h" -#else -#include "helpviewer_qwv.h" -#endif // QT_NO_WEBKIT - #include <QtCore/QTimer> -#include <QtGui/QApplication> #include <QtGui/QKeyEvent> -#include <QtGui/QLayout> #include <QtGui/QMenu> -#include <QtGui/QPrinter> -#include <QtGui/QTabBar> -#include <QtGui/QTabWidget> -#include <QtGui/QTextBrowser> -#include <QtGui/QToolButton> #include <QtGui/QPageSetupDialog> #include <QtGui/QPrintDialog> #include <QtGui/QPrintPreviewDialog> +#include <QtGui/QPrinter> +#include <QtGui/QStackedWidget> +#include <QtGui/QTextBrowser> +#include <QtGui/QVBoxLayout> #include <QtHelp/QHelpSearchEngine> QT_BEGIN_NAMESPACE namespace { - HelpViewer* helpViewerFromTabPosition(const QTabWidget *widget, - const QPoint &point) - { - TRACE_OBJ - QTabBar *tabBar = qFindChild<QTabBar*>(widget); - for (int i = 0; i < tabBar->count(); ++i) { - if (tabBar->tabRect(i).contains(point)) - return qobject_cast<HelpViewer*>(widget->widget(i)); - } - return 0; - } CentralWidget *staticCentralWidget = 0; } -// -- CentralWidget +// -- TabBar -CentralWidget::CentralWidget(MainWindow *parent) - : QWidget(parent) - , lastTabPage(0) - , tabWidget(0) - , findWidget(0) - , printer(0) - , usesDefaultCollection(parent->usesDefaultCollection()) - , m_searchWidget(0) +TabBar::TabBar(QWidget *parent) + : QTabBar(parent) { TRACE_OBJ - globalActionList.clear(); - staticCentralWidget = this; - QVBoxLayout *vboxLayout = new QVBoxLayout(this); - QString resourcePath = QLatin1String(":/trolltech/assistant/images/"); - - vboxLayout->setMargin(0); - tabWidget = new QTabWidget(this); -#ifndef Q_OS_MAC - resourcePath.append(QLatin1String("win")); -#else - resourcePath.append(QLatin1String("mac")); - tabWidget->setDocumentMode(true); -#endif - - connect(tabWidget, SIGNAL(currentChanged(int)), this, - SLOT(currentPageChanged(int))); - - QToolButton *newTabButton = new QToolButton(this); - newTabButton->setAutoRaise(true); - newTabButton->setToolTip(tr("Add new page")); - newTabButton->setIcon(QIcon(resourcePath + QLatin1String("/addtab.png"))); - - tabWidget->setCornerWidget(newTabButton, Qt::TopLeftCorner); - connect(newTabButton, SIGNAL(clicked()), this, SLOT(newTab())); - - QToolButton *closeTabButton = new QToolButton(this); - closeTabButton->setEnabled(false); - closeTabButton->setAutoRaise(true); - closeTabButton->setToolTip(tr("Close current page")); - closeTabButton->setIcon(QIcon(resourcePath + QLatin1String("/closetab.png"))); - - tabWidget->setCornerWidget(closeTabButton, Qt::TopRightCorner); - connect(closeTabButton, SIGNAL(clicked()), this, SLOT(closeTab())); - - vboxLayout->addWidget(tabWidget); - - findWidget = new FindWidget(this); - vboxLayout->addWidget(findWidget); - findWidget->hide(); - - connect(findWidget, SIGNAL(findNext()), this, SLOT(findNext())); - connect(findWidget, SIGNAL(findPrevious()), this, SLOT(findPrevious())); - connect(findWidget, SIGNAL(find(QString, bool)), this, - SLOT(find(QString, bool))); - connect(findWidget, SIGNAL(escapePressed()), this, SLOT(activateTab())); - - QTabBar *tabBar = qFindChild<QTabBar*>(tabWidget); - if (tabBar) { - tabBar->installEventFilter(this); - tabBar->setContextMenuPolicy(Qt::CustomContextMenu); - connect(tabBar, SIGNAL(customContextMenuRequested(QPoint)), this, - SLOT(showTabBarContextMenu(QPoint))); - } - -#if defined(QT_NO_WEBKIT) - QPalette p = palette(); - p.setColor(QPalette::Inactive, QPalette::Highlight, - p.color(QPalette::Active, QPalette::Highlight)); - p.setColor(QPalette::Inactive, QPalette::HighlightedText, - p.color(QPalette::Active, QPalette::HighlightedText)); - setPalette(p); +#ifdef Q_OS_MAC + setDocumentMode(true); #endif + setMovable(true); + setShape(QTabBar::RoundedNorth); + setContextMenuPolicy(Qt::CustomContextMenu); + setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred, + QSizePolicy::TabWidget)); + connect(this, SIGNAL(currentChanged(int)), this, SLOT(slotCurrentChanged(int))); + connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(slotTabCloseRequested(int))); + connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, + SLOT(slotCustomContextMenuRequested(QPoint))); } -CentralWidget::~CentralWidget() +TabBar::~TabBar() { TRACE_OBJ -#ifndef QT_NO_PRINTER - delete printer; -#endif - - QStringList zoomFactors; - QStringList currentPages; - bool searchAttached = m_searchWidget->isAttached(); - - int i = searchAttached ? 1 : 0; - for (; i < tabWidget->count(); ++i) { - HelpViewer *viewer = qobject_cast<HelpViewer*>(tabWidget->widget(i)); - if (viewer && viewer->source().isValid()) { - currentPages << viewer->source().toString(); - zoomFactors << QString::number(viewer->scale()); - } - } - - HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); - helpEngine.setLastTabPage(tabWidget->currentIndex()); - helpEngine.setLastShownPages(currentPages); - helpEngine.setSearchWasAttached(searchAttached); - helpEngine.setLastZoomFactors(zoomFactors); } -CentralWidget *CentralWidget::instance() +int TabBar::addNewTab(const QString &title) { TRACE_OBJ - return staticCentralWidget; + const int index = addTab(title); + setTabsClosable(count() > 1); + return index; } -void CentralWidget::newTab() +void TabBar::setCurrent(HelpViewer *viewer) { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); -#if !defined(QT_NO_WEBKIT) - if (viewer && viewer->hasLoadFinished()) -#else - if (viewer) -#endif - setSourceInNewTab(viewer->source()); -} - -void CentralWidget::zoomIn() -{ - TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (viewer) - viewer->scaleUp(); - - if (tabWidget->currentWidget() == m_searchWidget) - m_searchWidget->zoomIn(); + for (int i = 0; i < count(); ++i) { + HelpViewer *data = tabData(i).value<HelpViewer*>(); + if (data == viewer) { + setCurrentIndex(i); + break; + } + } } -void CentralWidget::zoomOut() +void TabBar::removeTabAt(HelpViewer *viewer) { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (viewer) - viewer->scaleDown(); - - if (tabWidget->currentWidget() == m_searchWidget) - m_searchWidget->zoomOut(); + for (int i = 0; i < count(); ++i) { + HelpViewer *data = tabData(i).value<HelpViewer*>(); + if (data == viewer) { + removeTab(i); + break; + } + } + setTabsClosable(count() > 1); } -void CentralWidget::nextPage() +void TabBar::titleChanged() { TRACE_OBJ - int index = tabWidget->currentIndex() + 1; - if (index >= tabWidget->count()) - index = 0; - tabWidget->setCurrentIndex(index); + for (int i = 0; i < count(); ++i) { + HelpViewer *data = tabData(i).value<HelpViewer*>(); + QString title = data->title(); + title.replace(QLatin1Char('&'), QLatin1String("&&")); + setTabText(i, title.isEmpty() ? tr("(Untitled)") : title); + } } -void CentralWidget::resetZoom() +void TabBar::slotCurrentChanged(int index) { TRACE_OBJ - if (HelpViewer *viewer = currentHelpViewer()) - viewer->resetScale(); - - if (tabWidget->currentWidget() == m_searchWidget) - m_searchWidget->resetZoom(); + emit currentTabChanged(tabData(index).value<HelpViewer*>()); } -void CentralWidget::previousPage() +void TabBar::slotTabCloseRequested(int index) { TRACE_OBJ - int index = tabWidget->currentIndex() -1; - if (index < 0) - index = tabWidget->count() -1; - tabWidget->setCurrentIndex(index); + OpenPagesManager::instance()->closePage(tabData(index).value<HelpViewer*>()); } -void CentralWidget::closeTab() +void TabBar::slotCustomContextMenuRequested(const QPoint &pos) { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (!viewer|| tabWidget->count() == 1) + const int tab = tabAt(pos); + if (tab < 0) return; - tabWidget->removeTab(tabWidget->indexOf(viewer)); - QTimer::singleShot(0, viewer, SLOT(deleteLater())); + QMenu menu(QLatin1String(""), this); + menu.addAction(tr("New &Tab"), OpenPagesManager::instance(), SLOT(createPage())); + + const bool enableAction = count() > 1; + QAction *closePage = menu.addAction(tr("&Close Tab")); + closePage->setEnabled(enableAction); + + QAction *closePages = menu.addAction(tr("Close Other Tabs")); + closePages->setEnabled(enableAction); + + menu.addSeparator(); + + HelpViewer *viewer = tabData(tab).value<HelpViewer*>(); + QAction *newBookmark = menu.addAction(tr("Add Bookmark for this Page...")); + const QString &url = viewer->source().toString(); + if (url.isEmpty() || url == QLatin1String("about:blank")) + newBookmark->setEnabled(false); + + QAction *pickedAction = menu.exec(mapToGlobal(pos)); + if (pickedAction == closePage) + slotTabCloseRequested(tab); + else if (pickedAction == closePages) { + for (int i = count() - 1; i >= 0; --i) { + if (i != tab) + slotTabCloseRequested(i); + } + } else if (pickedAction == newBookmark) + emit addBookmark(viewer->title(), url); } -void CentralWidget::setSource(const QUrl &url) +// -- CentralWidget + +CentralWidget::CentralWidget(QWidget *parent) + : QWidget(parent) +#ifndef QT_NO_PRINTER + , m_printer(0) +#endif + , m_findWidget(new FindWidget(this)) + , m_stackedWidget(new QStackedWidget(this)) + , m_tabBar(new TabBar(this)) { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - HelpViewer *lastViewer = - qobject_cast<HelpViewer*>(tabWidget->widget(lastTabPage)); - - if (!viewer && !lastViewer) { - viewer = new HelpViewer(this); - viewer->installEventFilter(this); - lastTabPage = tabWidget->addTab(viewer, QString()); - tabWidget->setCurrentIndex(lastTabPage); - connectSignals(); - } else { - viewer = lastViewer; - } + staticCentralWidget = this; + QVBoxLayout *vboxLayout = new QVBoxLayout(this); - viewer->setSource(url); - currentPageChanged(lastTabPage); - viewer->setFocus(Qt::OtherFocusReason); - tabWidget->setCurrentIndex(lastTabPage); - tabWidget->setTabText(lastTabPage, quoteTabTitle(viewer->documentTitle())); + vboxLayout->setMargin(0); + vboxLayout->setSpacing(0); + vboxLayout->addWidget(m_tabBar); + m_tabBar->setVisible(HelpEngineWrapper::instance().showTabs()); + vboxLayout->addWidget(m_stackedWidget); + vboxLayout->addWidget(m_findWidget); + m_findWidget->hide(); + + connect(m_findWidget, SIGNAL(findNext()), this, SLOT(findNext())); + connect(m_findWidget, SIGNAL(findPrevious()), this, SLOT(findPrevious())); + connect(m_findWidget, SIGNAL(find(QString, bool, bool)), this, + SLOT(find(QString, bool, bool))); + connect(m_findWidget, SIGNAL(escapePressed()), this, SLOT(activateTab())); + connect(m_tabBar, SIGNAL(addBookmark(QString, QString)), this, + SIGNAL(addBookmark(QString, QString))); } -void CentralWidget::setupWidget() +CentralWidget::~CentralWidget() { TRACE_OBJ - HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); - int option = helpEngine.startOption(); - if (option != ShowLastPages) { - QString homePage; - if (option == ShowHomePage) - homePage = helpEngine.homePage(); - else if (option == ShowBlankPage) - homePage = QLatin1String("about:blank"); - setSource(homePage); - } else { - setLastShownPages(); + QStringList zoomFactors; + QStringList currentPages; + for (int i = 0; i < m_stackedWidget->count(); ++i) { + const HelpViewer * const viewer = viewerAt(i); + const QUrl &source = viewer->source(); + if (source.isValid()) { + currentPages << source.toString(); + zoomFactors << QString::number(viewer->scale()); + } } -} -void CentralWidget::setLastShownPages() -{ - TRACE_OBJ HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); - const QStringList &lastShownPageList = helpEngine.lastShownPages(); - const int pageCount = lastShownPageList.count(); - if (pageCount == 0) { - if (usesDefaultCollection) - setSource(QUrl(QLatin1String("help"))); - else - setSource(QUrl(QLatin1String("about:blank"))); - return; - } - QStringList zoomFactors = helpEngine.lastZoomFactors(); - while (zoomFactors.count() < pageCount) - zoomFactors.append(CollectionConfiguration::DefaultZoomFactor); - - const bool searchIsAttached = m_searchWidget->isAttached(); - const bool searchWasAttached = helpEngine.searchWasAttached(); - int tabToShow = helpEngine.lastTabPage(); - if (searchWasAttached && !searchIsAttached && tabToShow != 0) - --tabToShow; - else if (!searchWasAttached && searchIsAttached) - ++tabToShow; - - for (int curTab = 0; curTab < pageCount; ++curTab) { - const QString &curFile = lastShownPageList.at(curTab); - if (helpEngine.findFile(curFile).isValid() - || curFile == QLatin1String("about:blank")) { - setSourceInNewTab(curFile, zoomFactors.at(curTab).toFloat()); - } else if (curTab + searchIsAttached <= tabToShow) - --tabToShow; - } + helpEngine.setLastShownPages(currentPages); + helpEngine.setLastZoomFactors(zoomFactors); + helpEngine.setLastTabPage(m_stackedWidget->currentIndex()); - tabWidget->setCurrentIndex(tabToShow); +#ifndef QT_NO_PRINTER + delete m_printer; +#endif } -bool CentralWidget::hasSelection() const +CentralWidget *CentralWidget::instance() { TRACE_OBJ - const HelpViewer *viewer = currentHelpViewer(); - return viewer ? viewer->hasSelection() : false; + return staticCentralWidget; } QUrl CentralWidget::currentSource() const { TRACE_OBJ - const HelpViewer *viewer = currentHelpViewer(); - if (viewer) - return viewer->source(); - - return QUrl(); + return currentHelpViewer()->source(); } QString CentralWidget::currentTitle() const { TRACE_OBJ - const HelpViewer *viewer = currentHelpViewer(); - if (viewer) - return viewer->documentTitle(); - - return QString(); + return currentHelpViewer()->title(); } -void CentralWidget::copySelection() +bool CentralWidget::hasSelection() const { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (viewer) - viewer->copy(); + return !currentHelpViewer()->selectedText().isEmpty(); } -void CentralWidget::showTextSearch() +bool CentralWidget::isForwardAvailable() const { TRACE_OBJ - findWidget->show(); + return currentHelpViewer()->isForwardAvailable(); } -void CentralWidget::initPrinter() +bool CentralWidget::isBackwardAvailable() const { TRACE_OBJ -#ifndef QT_NO_PRINTER - if (!printer) - printer = new QPrinter(QPrinter::HighResolution); -#endif + return currentHelpViewer()->isBackwardAvailable(); } -void CentralWidget::print() +HelpViewer* CentralWidget::viewerAt(int index) const { TRACE_OBJ -#ifndef QT_NO_PRINTER - HelpViewer *viewer = currentHelpViewer(); - if (!viewer) - return; - - initPrinter(); - - QPrintDialog dlg(printer, this); -#if defined(QT_NO_WEBKIT) - if (viewer->textCursor().hasSelection()) - dlg.addEnabledOption(QAbstractPrintDialog::PrintSelection); -#endif - dlg.addEnabledOption(QAbstractPrintDialog::PrintPageRange); - dlg.addEnabledOption(QAbstractPrintDialog::PrintCollateCopies); - dlg.setWindowTitle(tr("Print Document")); - if (dlg.exec() == QDialog::Accepted) { - viewer->print(printer); - } -#endif + return static_cast<HelpViewer*>(m_stackedWidget->widget(index)); } -void CentralWidget::printPreview() +HelpViewer* CentralWidget::currentHelpViewer() const { TRACE_OBJ -#ifndef QT_NO_PRINTER - initPrinter(); - QPrintPreviewDialog preview(printer, this); - connect(&preview, SIGNAL(paintRequested(QPrinter*)), - SLOT(printPreview(QPrinter*))); - preview.exec(); -#endif + return static_cast<HelpViewer *>(m_stackedWidget->currentWidget()); } -void CentralWidget::printPreview(QPrinter *p) +void CentralWidget::addPage(HelpViewer *page, bool fromSearch) { TRACE_OBJ -#ifndef QT_NO_PRINTER - HelpViewer *viewer = currentHelpViewer(); - if (viewer) - viewer->print(p); -#endif -} + page->installEventFilter(this); + page->setFocus(Qt::OtherFocusReason); + connectSignals(page); + const int index = m_stackedWidget->addWidget(page); + m_tabBar->setTabData(m_tabBar->addNewTab(page->title()), + QVariant::fromValue(viewerAt(index))); + connect (page, SIGNAL(titleChanged()), m_tabBar, SLOT(titleChanged())); -void CentralWidget::pageSetup() -{ - TRACE_OBJ -#ifndef QT_NO_PRINTER - initPrinter(); - QPageSetupDialog dlg(printer); - dlg.exec(); -#endif + if (fromSearch) { + connect(currentHelpViewer(), SIGNAL(loadFinished(bool)), this, + SLOT(highlightSearchTerms())); + } } -bool CentralWidget::isHomeAvailable() const +void CentralWidget::removePage(int index) { TRACE_OBJ - return currentHelpViewer() ? true : false; + const bool currentChanged = index == currentIndex(); + m_tabBar->removeTabAt(viewerAt(index)); + m_stackedWidget->removeWidget(m_stackedWidget->widget(index)); + if (currentChanged) + emit currentViewerChanged(); } -void CentralWidget::home() +int CentralWidget::currentIndex() const { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (viewer) - viewer->home(); + return m_stackedWidget->currentIndex(); } -bool CentralWidget::isForwardAvailable() const +void CentralWidget::setCurrentPage(HelpViewer *page) { TRACE_OBJ - const HelpViewer *viewer = currentHelpViewer(); - if (viewer) - return viewer->isForwardAvailable(); - - return false; + m_tabBar->setCurrent(page); + m_stackedWidget->setCurrentWidget(page); + emit currentViewerChanged(); } -void CentralWidget::forward() +void CentralWidget::connectTabBar() { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (viewer) - viewer->forward(); + connect(m_tabBar, SIGNAL(currentTabChanged(HelpViewer*)), + OpenPagesManager::instance(), SLOT(setCurrentPage(HelpViewer*))); } -bool CentralWidget::isBackwardAvailable() const -{ - TRACE_OBJ - const HelpViewer *viewer = currentHelpViewer(); - if (viewer) - return viewer->isBackwardAvailable(); - - return false; -} +// -- public slots -void CentralWidget::backward() +void CentralWidget::copy() { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (viewer) - viewer->backward(); + currentHelpViewer()->copy(); } - -QList<QAction*> CentralWidget::globalActions() const +void CentralWidget::home() { TRACE_OBJ - return globalActionList; + currentHelpViewer()->home(); } -void CentralWidget::setGlobalActions(const QList<QAction*> &actions) +void CentralWidget::zoomIn() { TRACE_OBJ - globalActionList = actions; + currentHelpViewer()->scaleUp(); } -void CentralWidget::setSourceInNewTab(const QUrl &url, qreal zoom) +void CentralWidget::zoomOut() { TRACE_OBJ - if (HelpViewer *viewer = currentHelpViewer()) { - if (viewer->launchWithExternalApp(url)) - return; - } - - HelpViewer *viewer = new HelpViewer(this, zoom); - viewer->installEventFilter(this); - viewer->setSource(url); - viewer->setFocus(Qt::OtherFocusReason); - tabWidget->setCurrentIndex(tabWidget->addTab(viewer, - quoteTabTitle(viewer->documentTitle()))); - connectSignals(); + currentHelpViewer()->scaleDown(); } -HelpViewer *CentralWidget::newEmptyTab() +void CentralWidget::resetZoom() { TRACE_OBJ - HelpViewer *viewer = new HelpViewer(this); - viewer->installEventFilter(this); - viewer->setFocus(Qt::OtherFocusReason); -#if defined(QT_NO_WEBKIT) - viewer->setDocumentTitle(tr("unknown")); -#endif - tabWidget->setCurrentIndex(tabWidget->addTab(viewer, tr("unknown"))); - - connectSignals(); - return viewer; + currentHelpViewer()->resetScale(); } -void CentralWidget::connectSignals() +void CentralWidget::forward() { TRACE_OBJ - const HelpViewer *viewer = currentHelpViewer(); - if (viewer) { - connect(viewer, SIGNAL(copyAvailable(bool)), this, - SIGNAL(copyAvailable(bool))); - connect(viewer, SIGNAL(forwardAvailable(bool)), this, - SIGNAL(forwardAvailable(bool))); - connect(viewer, SIGNAL(backwardAvailable(bool)), this, - SIGNAL(backwardAvailable(bool))); - connect(viewer, SIGNAL(sourceChanged(QUrl)), this, - SIGNAL(sourceChanged(QUrl))); - connect(viewer, SIGNAL(highlighted(QString)), this, - SIGNAL(highlighted(QString))); - connect(viewer, SIGNAL(sourceChanged(QUrl)), this, - SLOT(setTabTitle(QUrl))); - connect(viewer, SIGNAL(printRequested()), this, SLOT(print())); - } + currentHelpViewer()->forward(); } -HelpViewer* CentralWidget::viewerAt(int index) const +void CentralWidget::nextPage() { TRACE_OBJ - return qobject_cast<HelpViewer*>(tabWidget->widget(index)); + m_stackedWidget->setCurrentIndex((m_stackedWidget->currentIndex() + 1) + % m_stackedWidget->count()); } -HelpViewer* CentralWidget::currentHelpViewer() const +void CentralWidget::backward() { TRACE_OBJ - return qobject_cast<HelpViewer*>(tabWidget->currentWidget()); + currentHelpViewer()->backward(); } -void CentralWidget::activateTab(bool onlyHelpViewer) +void CentralWidget::previousPage() { TRACE_OBJ - if (currentHelpViewer()) { - currentHelpViewer()->setFocus(); - } else { - int idx = 0; - if (onlyHelpViewer) - idx = lastTabPage; - tabWidget->setCurrentIndex(idx); - tabWidget->currentWidget()->setFocus(); - } + m_stackedWidget->setCurrentIndex((m_stackedWidget->currentIndex() - 1) + % m_stackedWidget->count()); } -void CentralWidget::setTabTitle(const QUrl &url) +void CentralWidget::print() { TRACE_OBJ - Q_UNUSED(url) -#if !defined(QT_NO_WEBKIT) - QTabBar *tabBar = qFindChild<QTabBar*>(tabWidget); - for (int tab = 0; tab < tabBar->count(); ++tab) { - HelpViewer *viewer = qobject_cast<HelpViewer*>(tabWidget->widget(tab)); - if (viewer) { - tabWidget->setTabText(tab, - quoteTabTitle(viewer->documentTitle().trimmed())); - } - } -#else - HelpViewer *viewer = currentHelpViewer(); - if (viewer) { - tabWidget->setTabText(lastTabPage, - quoteTabTitle(viewer->documentTitle().trimmed())); - } +#ifndef QT_NO_PRINTER + initPrinter(); + QPrintDialog dlg(m_printer, this); + + if (!currentHelpViewer()->selectedText().isEmpty()) + dlg.addEnabledOption(QAbstractPrintDialog::PrintSelection); + dlg.addEnabledOption(QAbstractPrintDialog::PrintPageRange); + dlg.addEnabledOption(QAbstractPrintDialog::PrintCollateCopies); + dlg.setWindowTitle(tr("Print Document")); + if (dlg.exec() == QDialog::Accepted) + currentHelpViewer()->print(m_printer); #endif } -void CentralWidget::currentPageChanged(int index) +void CentralWidget::pageSetup() { TRACE_OBJ - const HelpViewer *viewer = currentHelpViewer(); - if (viewer) - lastTabPage = index; - - QWidget *widget = tabWidget->cornerWidget(Qt::TopRightCorner); - widget->setEnabled(viewer && enableTabCloseAction()); - - widget = tabWidget->cornerWidget(Qt::TopLeftCorner); - widget->setEnabled(viewer ? true : false); - - emit currentViewerChanged(); +#ifndef QT_NO_PRINTER + initPrinter(); + QPageSetupDialog dlg(m_printer); + dlg.exec(); +#endif } -void CentralWidget::showTabBarContextMenu(const QPoint &point) +void CentralWidget::printPreview() { TRACE_OBJ - HelpViewer *viewer = helpViewerFromTabPosition(tabWidget, point); - if (!viewer) - return; - - QTabBar *tabBar = qFindChild<QTabBar*>(tabWidget); - - QMenu menu(QLatin1String(""), tabBar); - QAction *newPage = menu.addAction(tr("Add New Page")); - - bool enableAction = enableTabCloseAction(); - QAction *closePage = menu.addAction(tr("Close This Page")); - closePage->setEnabled(enableAction); - - QAction *closePages = menu.addAction(tr("Close Other Pages")); - closePages->setEnabled(enableAction); - - menu.addSeparator(); - - QAction *newBookmark = menu.addAction(tr("Add Bookmark for this Page...")); - const QString &url = viewer->source().toString(); - if (url.isEmpty() || url == QLatin1String("about:blank")) - newBookmark->setEnabled(false); - - QAction *pickedAction = menu.exec(tabBar->mapToGlobal(point)); - if (pickedAction == newPage) - setSourceInNewTab(viewer->source()); - - if (pickedAction == closePage) { - tabWidget->removeTab(tabWidget->indexOf(viewer)); - QTimer::singleShot(0, viewer, SLOT(deleteLater())); - } - - if (pickedAction == closePages) { - int currentPage = tabWidget->indexOf(viewer); - for (int i = tabBar->count() -1; i >= 0; --i) { - viewer = qobject_cast<HelpViewer*>(tabWidget->widget(i)); - if (i != currentPage && viewer) { - tabWidget->removeTab(i); - QTimer::singleShot(0, viewer, SLOT(deleteLater())); - - if (i < currentPage) - --currentPage; - } - } - } - - if (pickedAction == newBookmark) - emit addBookmark(viewer->documentTitle(), viewer->source().toString()); +#ifndef QT_NO_PRINTER + initPrinter(); + QPrintPreviewDialog preview(m_printer, this); + connect(&preview, SIGNAL(paintRequested(QPrinter*)), + SLOT(printPreview(QPrinter*))); + preview.exec(); +#endif } -bool CentralWidget::eventFilter(QObject *object, QEvent *e) +void CentralWidget::setSource(const QUrl &url) { TRACE_OBJ - if (e->type() == QEvent::KeyPress) { - QKeyEvent *ke = static_cast<QKeyEvent*>(e); - switch (ke->key()) { - default: { - return QWidget::eventFilter(object, e); - } break; - - case Qt::Key_Backspace: { - HelpViewer *viewer = currentHelpViewer(); - if (viewer == object) { -#if defined(QT_NO_WEBKIT) - if (viewer->isBackwardAvailable()) { -#else - if (viewer->isBackwardAvailable() && !viewer->hasFocus()) { -#endif - viewer->backward(); - return true; - } - } - } break; - } - } - - if (qobject_cast<QTabBar*>(object)) { - const bool dblClick = e->type() == QEvent::MouseButtonDblClick; - if ((e->type() == QEvent::MouseButtonRelease) || dblClick) { - QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(e); - HelpViewer *viewer = helpViewerFromTabPosition(tabWidget, - mouseEvent->pos()); - if (viewer) { - if ((mouseEvent->button() == Qt::MidButton) || dblClick) { - if (availableHelpViewer() > 1) { - tabWidget->removeTab(tabWidget->indexOf(viewer)); - QTimer::singleShot(0, viewer, SLOT(deleteLater())); - currentPageChanged(tabWidget->currentIndex()); - return true; - } - } - } - } - } - - return QWidget::eventFilter(object, e); + HelpViewer *viewer = currentHelpViewer(); + viewer->setSource(url); + viewer->setFocus(Qt::OtherFocusReason); } -void CentralWidget::keyPressEvent(QKeyEvent *e) +void CentralWidget::setSourceFromSearch(const QUrl &url) { TRACE_OBJ - const QString &text = e->text(); - if (text.startsWith(QLatin1Char('/'))) { - if (!findWidget->isVisible()) { - findWidget->showAndClear(); - } else { - findWidget->show(); - } - } else { - QWidget::keyPressEvent(e); - } + connect(currentHelpViewer(), SIGNAL(loadFinished(bool)), this, + SLOT(highlightSearchTerms())); + currentHelpViewer()->setSource(url); + currentHelpViewer()->setFocus(Qt::OtherFocusReason); } void CentralWidget::findNext() { TRACE_OBJ - find(findWidget->text(), true); + find(m_findWidget->text(), true, false); } void CentralWidget::findPrevious() { TRACE_OBJ - find(findWidget->text(), false); + find(m_findWidget->text(), false, false); } -void CentralWidget::find(const QString &ttf, bool forward) +void CentralWidget::find(const QString &ttf, bool forward, bool incremental) { TRACE_OBJ bool found = false; -#if defined(QT_NO_WEBKIT) - found = findInTextBrowser(ttf, forward); -#else - found = findInWebPage(ttf, forward); -#endif + if (HelpViewer *viewer = currentHelpViewer()) { + HelpViewer::FindFlags flags = 0; + if (!forward) + flags |= HelpViewer::FindBackward; + if (m_findWidget->caseSensitive()) + flags |= HelpViewer::FindCaseSensitively; + found = viewer->findText(ttf, flags, incremental, false); + } if (!found && ttf.isEmpty()) found = true; // the line edit is empty, no need to mark it red... - if (!findWidget->isVisible()) - findWidget->show(); - findWidget->setPalette(found); + if (!m_findWidget->isVisible()) + m_findWidget->show(); + m_findWidget->setPalette(found); } -bool CentralWidget::findInWebPage(const QString &ttf, bool forward) +void CentralWidget::activateTab() { TRACE_OBJ -#if !defined(QT_NO_WEBKIT) - if (HelpViewer *viewer = currentHelpViewer()) { - bool found = false; - QWebPage::FindFlags options; - if (!ttf.isEmpty()) { - if (!forward) - options |= QWebPage::FindBackward; - - if (findWidget->caseSensitive()) - options |= QWebPage::FindCaseSensitively; - - found = viewer->findText(ttf, options); - findWidget->setTextWrappedVisible(false); - - if (!found) { - options |= QWebPage::FindWrapsAroundDocument; - found = viewer->findText(ttf, options); - if (found) - findWidget->setTextWrappedVisible(true); - } - } - // force highlighting of all other matches, also when empty (clear) - options = QWebPage::HighlightAllOccurrences; - if (findWidget->caseSensitive()) - options |= QWebPage::FindCaseSensitively; - viewer->findText(QLatin1String(""), options); - viewer->findText(ttf, options); - return found; - } - - // this needs to stay, case for active search results page - return findInTextBrowser(ttf, forward); -#else - Q_UNUSED(ttf); - Q_UNUSED(forward); -#endif - return false; + currentHelpViewer()->setFocus(); } -bool CentralWidget::findInTextBrowser(const QString &ttf, bool forward) +void CentralWidget::showTextSearch() { TRACE_OBJ - QTextBrowser *browser = qobject_cast<QTextBrowser*>(currentHelpViewer()); - if (tabWidget->currentWidget() == m_searchWidget) - browser = qFindChild<QTextBrowser*>(m_searchWidget); - - if (!browser || ttf.isEmpty()) - return false; - - QTextDocument *doc = browser->document(); - QTextCursor cursor = browser->textCursor(); - - if (!doc || cursor.isNull()) - return false; - - QTextDocument::FindFlags options; - - if (cursor.hasSelection()) { - cursor.setPosition(forward ? cursor.position() : cursor.anchor(), - QTextCursor::MoveAnchor); - } - - if (!forward) - options |= QTextDocument::FindBackward; - - if (findWidget->caseSensitive()) - options |= QTextDocument::FindCaseSensitively; - - findWidget->setTextWrappedVisible(false); - - bool found = true; - QTextCursor newCursor = doc->find(ttf, cursor, options); - if (newCursor.isNull()) { - QTextCursor ac(doc); - ac.movePosition(options & QTextDocument::FindBackward - ? QTextCursor::End : QTextCursor::Start); - newCursor = doc->find(ttf, ac, options); - if (newCursor.isNull()) { - found = false; - newCursor = cursor; - } else { - findWidget->setTextWrappedVisible(true); - } - } - browser->setTextCursor(newCursor); - return found; + m_findWidget->show(); } void CentralWidget::updateBrowserFont() { TRACE_OBJ - const bool searchAttached = searchWidgetAttached(); - if (searchAttached) { - HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); - m_searchWidget->setFont(helpEngine.usesBrowserFont() - ? helpEngine.browserFont() : qApp->font()); - } - - const int count = tabWidget->count(); - if (HelpViewer* viewer = viewerAt(count - 1)) { - const QFont &font = viewer->viewerFont(); - for (int i = searchAttached ? 1 : 0; i < count; ++i) - viewerAt(i)->setViewerFont(font); - } -} - -bool CentralWidget::searchWidgetAttached() const -{ - TRACE_OBJ - return m_searchWidget && m_searchWidget->isAttached(); + const int count = m_stackedWidget->count(); + const QFont &font = viewerAt(count - 1)->viewerFont(); + for (int i = 0; i < count; ++i) + viewerAt(i)->setViewerFont(font); } -void CentralWidget::createSearchWidget(QHelpSearchEngine *searchEngine) +void CentralWidget::updateUserInterface() { - TRACE_OBJ - if (m_searchWidget) - return; - - m_searchWidget = new SearchWidget(searchEngine, this); - connect(m_searchWidget, SIGNAL(requestShowLink(QUrl)), this, - SLOT(setSourceFromSearch(QUrl))); - connect(m_searchWidget, SIGNAL(requestShowLinkInNewTab(QUrl)), this, - SLOT(setSourceFromSearchInNewTab(QUrl))); - - HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); - m_searchWidget->setFont(!helpEngine.usesBrowserFont() ? qApp->font() - : helpEngine.browserFont()); + m_tabBar->setVisible(HelpEngineWrapper::instance().showTabs()); } -void CentralWidget::activateSearchWidget(bool updateLastTabPage) -{ - TRACE_OBJ - if (!m_searchWidget) - createSearchWidget(HelpEngineWrapper::instance().searchEngine()); - - if (!m_searchWidget->isAttached()) { - tabWidget->insertTab(0, m_searchWidget, tr("Search")); - m_searchWidget->setAttached(true); +// -- protected - if (updateLastTabPage) - lastTabPage++; - } - - tabWidget->setCurrentWidget(m_searchWidget); - m_searchWidget->setFocus(); -} - -void CentralWidget::removeSearchWidget() +void CentralWidget::keyPressEvent(QKeyEvent *e) { TRACE_OBJ - if (searchWidgetAttached()) { - tabWidget->removeTab(0); - m_searchWidget->setAttached(false); + const QString &text = e->text(); + if (text.startsWith(QLatin1Char('/'))) { + if (!m_findWidget->isVisible()) { + m_findWidget->showAndClear(); + } else { + m_findWidget->show(); + } + } else { + QWidget::keyPressEvent(e); } } -int CentralWidget::availableHelpViewer() const -{ - TRACE_OBJ - int count = tabWidget->count(); - if (searchWidgetAttached()) - count--; - return count; -} - -bool CentralWidget::enableTabCloseAction() const -{ - TRACE_OBJ - int minTabCount = 1; - if (searchWidgetAttached()) - minTabCount = 2; - - return (tabWidget->count() > minTabCount); -} - -QString CentralWidget::quoteTabTitle(const QString &title) const -{ - TRACE_OBJ - QString s = title; - return s.replace(QLatin1Char('&'), QLatin1String("&&")); -} - -void -CentralWidget::setSourceFromSearch(const QUrl &url) +void CentralWidget::focusInEvent(QFocusEvent * /* event */) { TRACE_OBJ - setSource(url); -#if defined(QT_NO_WEBKIT) - highlightSearchTerms(); -#else - connect(currentHelpViewer(), SIGNAL(loadFinished(bool)), this, - SLOT(highlightSearchTerms())); -#endif + // If we have a current help viewer then this is the 'focus proxy', + // otherwise it's the central widget. This is needed, so an embedding + // program can just set the focus to the central widget and it does + // The Right Thing(TM) + QObject *receiver = m_stackedWidget; + if (HelpViewer *viewer = currentHelpViewer()) + receiver = viewer; + QTimer::singleShot(1, receiver, SLOT(setFocus())); } -void -CentralWidget::setSourceFromSearchInNewTab(const QUrl &url) -{ - TRACE_OBJ - setSourceInNewTab(url); -#if defined(QT_NO_WEBKIT) - highlightSearchTerms(); -#else - connect(currentHelpViewer(), SIGNAL(loadFinished(bool)), this, - SLOT(highlightSearchTerms())); -#endif -} +// -- private slots -void -CentralWidget::highlightSearchTerms() +void CentralWidget::highlightSearchTerms() { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (!viewer) - return; - QHelpSearchEngine *searchEngine = HelpEngineWrapper::instance().searchEngine(); QList<QHelpSearchQuery> queryList = searchEngine->query(); @@ -1016,91 +564,73 @@ CentralWidget::highlightSearchTerms() } } -#if defined(QT_NO_WEBKIT) - viewer->viewport()->setUpdatesEnabled(false); - - QTextCharFormat marker; - marker.setForeground(Qt::red); - - QTextCursor firstHit; - - QTextCursor c = viewer->textCursor(); - c.beginEditBlock(); - foreach (const QString& term, terms) { - c.movePosition(QTextCursor::Start); - viewer->setTextCursor(c); - - while (viewer->find(term, QTextDocument::FindWholeWords)) { - QTextCursor hit = viewer->textCursor(); - if (firstHit.isNull() || hit.position() < firstHit.position()) - firstHit = hit; - - hit.mergeCharFormat(marker); - } - } - - if (firstHit.isNull()) { - firstHit = viewer->textCursor(); - firstHit.movePosition(QTextCursor::Start); - } - firstHit.clearSelection(); - c.endEditBlock(); - viewer->setTextCursor(firstHit); - - viewer->viewport()->setUpdatesEnabled(true); -#else - viewer->findText("", QWebPage::HighlightAllOccurrences); - // clears existing selections + HelpViewer *viewer = currentHelpViewer(); foreach (const QString& term, terms) - viewer->findText(term, QWebPage::HighlightAllOccurrences); - + viewer->findText(term, 0, false, true); disconnect(viewer, SIGNAL(loadFinished(bool)), this, SLOT(highlightSearchTerms())); +} + +void CentralWidget::printPreview(QPrinter *p) +{ + TRACE_OBJ +#ifndef QT_NO_PRINTER + currentHelpViewer()->print(p); #endif } +void CentralWidget::handleSourceChanged(const QUrl &url) +{ + TRACE_OBJ + if (sender() == currentHelpViewer()) + emit sourceChanged(url); +} -void CentralWidget::closeOrReloadTabs(const QList<int> &indices, bool tryReload) +// -- private + +void CentralWidget::initPrinter() { TRACE_OBJ - QList<int> sortedIndices = indices; - qSort(sortedIndices); - for (int i = sortedIndices.count(); --i >= 0;) { - const int tab = sortedIndices.at(i); - bool close = true; - if (tryReload) { - HelpViewer *viewer = - qobject_cast<HelpViewer*>(tabWidget->widget(tab)); - if (HelpEngineWrapper::instance().findFile(viewer->source()).isValid()) { - viewer->reload(); - close = false; - } - } - if (close) - closeTabAt(tab); - } - if (availableHelpViewer() == 0) - setSource(QUrl(QLatin1String("about:blank"))); +#ifndef QT_NO_PRINTER + if (!m_printer) + m_printer = new QPrinter(QPrinter::HighResolution); +#endif } -void CentralWidget::closeTabAt(int index) +void CentralWidget::connectSignals(HelpViewer *page) { TRACE_OBJ - HelpViewer *viewer = qobject_cast<HelpViewer*>(tabWidget->widget(index)); - tabWidget->removeTab(index); - QTimer::singleShot(0, viewer, SLOT(deleteLater())); + connect(page, SIGNAL(copyAvailable(bool)), this, + SIGNAL(copyAvailable(bool))); + connect(page, SIGNAL(forwardAvailable(bool)), this, + SIGNAL(forwardAvailable(bool))); + connect(page, SIGNAL(backwardAvailable(bool)), this, + SIGNAL(backwardAvailable(bool))); + connect(page, SIGNAL(sourceChanged(QUrl)), this, + SLOT(handleSourceChanged(QUrl))); + connect(page, SIGNAL(highlighted(QString)), this, + SIGNAL(highlighted(QString))); + connect(page, SIGNAL(printRequested()), this, SLOT(print())); } -QMap<int, QString> CentralWidget::currentSourceFileList() const +bool CentralWidget::eventFilter(QObject *object, QEvent *e) { TRACE_OBJ - QMap<int, QString> sourceList; - for (int i = 0; i < tabWidget->count(); ++i) { - HelpViewer *viewer = qobject_cast<HelpViewer*>(tabWidget->widget(i)); - if (viewer && viewer->source().isValid()) - sourceList.insert(i, viewer->source().host()); + if (e->type() != QEvent::KeyPress) + return QWidget::eventFilter(object, e); + + HelpViewer *viewer = currentHelpViewer(); + QKeyEvent *keyEvent = static_cast<QKeyEvent*> (e); + if (viewer == object && keyEvent->key() == Qt::Key_Backspace) { + if (viewer->isBackwardAvailable()) { +#if !defined(QT_NO_WEBKIT) + // this helps in case there is an html <input> field + if (!viewer->hasFocus()) +#endif + viewer->backward(); + } } - return sourceList; + return QWidget::eventFilter(object, e); } QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/centralwidget.h b/tools/assistant/tools/assistant/centralwidget.h index f286ff7..bcadcf4 100644 --- a/tools/assistant/tools/assistant/centralwidget.h +++ b/tools/assistant/tools/assistant/centralwidget.h @@ -38,80 +38,102 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #ifndef CENTRALWIDGET_H #define CENTRALWIDGET_H #include <QtCore/QUrl> + +#include <QtGui/QTabBar> #include <QtGui/QWidget> QT_BEGIN_NAMESPACE class FindWidget; class HelpViewer; -class MainWindow; -class QHelpSearchEngine; -class QTabWidget; -class SearchWidget; +class QStackedWidget; + +class TabBar : public QTabBar +{ + Q_OBJECT +public: + TabBar(QWidget *parent = 0); + ~TabBar(); + + int addNewTab(const QString &title); + void setCurrent(HelpViewer *viewer); + void removeTabAt(HelpViewer *viewer); + +public slots: + void titleChanged(); + +signals: + void currentTabChanged(HelpViewer *viewer); + void addBookmark(const QString &title, const QString &url); + +private slots: + void slotCurrentChanged(int index); + void slotTabCloseRequested(int index); + void slotCustomContextMenuRequested(const QPoint &pos); +}; class CentralWidget : public QWidget { Q_OBJECT public: - CentralWidget(MainWindow *parent); + CentralWidget(QWidget *parent = 0); ~CentralWidget(); - void setupWidget(); - bool hasSelection() const; + static CentralWidget *instance(); + QUrl currentSource() const; QString currentTitle() const; - bool isHomeAvailable() const; + + bool hasSelection() const; bool isForwardAvailable() const; bool isBackwardAvailable() const; - QList<QAction*> globalActions() const; - void setGlobalActions(const QList<QAction*> &actions); HelpViewer *viewerAt(int index) const; HelpViewer *currentHelpViewer() const; - bool searchWidgetAttached() const; - void createSearchWidget(QHelpSearchEngine *searchEngine); - void activateSearchWidget(bool updateLastTabPage = false); - void removeSearchWidget(); - - int availableHelpViewer() const; - bool enableTabCloseAction() const; + void addPage(HelpViewer *page, bool fromSearch = false); + void removePage(int index); - void closeOrReloadTabs(const QList<int> &indices, bool tryReload); - void closeTabAt(int index); - QMap<int, QString> currentSourceFileList() const; + int currentIndex() const; + void setCurrentPage(HelpViewer *page); - static CentralWidget *instance(); + void connectTabBar(); public slots: + void copy(); + void home(); + void zoomIn(); void zoomOut(); - void nextPage(); void resetZoom(); + + void forward(); + void nextPage(); + + void backward(); void previousPage(); - void copySelection(); - void showTextSearch(); + void print(); void pageSetup(); void printPreview(); - void updateBrowserFont(); - void setSource(const QUrl &url); - void setSourceInNewTab(const QUrl &url, qreal zoom = 0.0); - HelpViewer *newEmptyTab(); - void home(); - void forward(); - void backward(); - void activateTab(bool onlyHelpViewer = false); + void setSource(const QUrl &url); + void setSourceFromSearch(const QUrl &url); void findNext(); void findPrevious(); - void find(const QString &text, bool forward); + void find(const QString &text, bool forward, bool incremental); + + void activateTab(); + void showTextSearch(); + void updateBrowserFont(); + void updateUserInterface(); signals: void currentViewerChanged(); @@ -124,37 +146,25 @@ signals: protected: void keyPressEvent(QKeyEvent *); + void focusInEvent(QFocusEvent *event); private slots: - void newTab(); - void closeTab(); - void setTabTitle(const QUrl& url); - void currentPageChanged(int index); - void showTabBarContextMenu(const QPoint &point); - void printPreview(QPrinter *printer); - void setSourceFromSearch(const QUrl &url); - void setSourceFromSearchInNewTab(const QUrl &url); void highlightSearchTerms(); + void printPreview(QPrinter *printer); + void handleSourceChanged(const QUrl &url); private: - void connectSignals(); - bool eventFilter(QObject *object, QEvent *e); - bool findInWebPage(const QString &ttf, bool forward); - bool findInTextBrowser(const QString &ttf, bool forward); void initPrinter(); - QString quoteTabTitle(const QString &title) const; - void setLastShownPages(); + void connectSignals(HelpViewer *page); + bool eventFilter(QObject *object, QEvent *e); private: - int lastTabPage; - QList<QAction*> globalActionList; - - QTabWidget *tabWidget; - FindWidget *findWidget; - QPrinter *printer; - bool usesDefaultCollection; - - SearchWidget *m_searchWidget; +#ifndef QT_NO_PRINTER + QPrinter *m_printer; +#endif + FindWidget *m_findWidget; + QStackedWidget *m_stackedWidget; + TabBar *m_tabBar; }; QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/contentwindow.cpp b/tools/assistant/tools/assistant/contentwindow.cpp index 8afa1df..d966cf0 100644 --- a/tools/assistant/tools/assistant/contentwindow.cpp +++ b/tools/assistant/tools/assistant/contentwindow.cpp @@ -38,12 +38,14 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "tracer.h" #include "contentwindow.h" + #include "centralwidget.h" #include "helpenginewrapper.h" #include "helpviewer.h" +#include "openpagesmanager.h" +#include "tracer.h" #include <QtGui/QLayout> #include <QtGui/QFocusEvent> @@ -146,8 +148,8 @@ bool ContentWindow::eventFilter(QObject *o, QEvent *e) qobject_cast<QHelpContentModel*>(m_contentWidget->model()); if (contentModel) { QHelpContentItem *itm = contentModel->contentItemAt(index); - if (itm && AbstractHelpViewer::canOpenPage(itm->url().path())) - CentralWidget::instance()->setSourceInNewTab(itm->url()); + if (itm && HelpViewer::canOpenPage(itm->url().path())) + OpenPagesManager::instance()->createPage(itm->url()); } } else if (button == Qt::LeftButton) { itemClicked(index); @@ -172,7 +174,7 @@ void ContentWindow::showContextMenu(const QPoint &pos) QMenu menu; QAction *curTab = menu.addAction(tr("Open Link")); QAction *newTab = menu.addAction(tr("Open Link in New Tab")); - if (!AbstractHelpViewer::canOpenPage(itm->url().path())) + if (!HelpViewer::canOpenPage(itm->url().path())) newTab->setEnabled(false); menu.move(m_contentWidget->mapToGlobal(pos)); @@ -181,7 +183,7 @@ void ContentWindow::showContextMenu(const QPoint &pos) if (curTab == action) emit linkActivated(itm->url()); else if (newTab == action) - CentralWidget::instance()->setSourceInNewTab(itm->url()); + OpenPagesManager::instance()->createPage(itm->url()); } void ContentWindow::itemClicked(const QModelIndex &index) diff --git a/tools/assistant/tools/assistant/contentwindow.h b/tools/assistant/tools/assistant/contentwindow.h index 62855dd..658e74e 100644 --- a/tools/assistant/tools/assistant/contentwindow.h +++ b/tools/assistant/tools/assistant/contentwindow.h @@ -76,7 +76,6 @@ private: void focusInEvent(QFocusEvent *e); void keyPressEvent(QKeyEvent *e); bool eventFilter(QObject *o, QEvent *e); - bool isPdfFile(QHelpContentItem *item) const; QHelpContentWidget * const m_contentWidget; int m_expandDepth; diff --git a/tools/assistant/tools/assistant/doc/assistant.qdocconf b/tools/assistant/tools/assistant/doc/assistant.qdocconf index 3b4b5f8..491f159 100644 --- a/tools/assistant/tools/assistant/doc/assistant.qdocconf +++ b/tools/assistant/tools/assistant/doc/assistant.qdocconf @@ -12,5 +12,5 @@ HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \ "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \ "<td width=\"30%\" align=\"left\">Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)</td>\n" \ "<td width=\"40%\" align=\"center\">Trademarks</td>\n" \ - "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt 4.7.0</div></td>\n" \ + "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt 4.8.0</div></td>\n" \ "</tr></table></div></address>" diff --git a/tools/assistant/tools/assistant/findwidget.cpp b/tools/assistant/tools/assistant/findwidget.cpp index 60318d4..e46be61 100644 --- a/tools/assistant/tools/assistant/findwidget.cpp +++ b/tools/assistant/tools/assistant/findwidget.cpp @@ -203,7 +203,7 @@ void FindWidget::updateButtons() void FindWidget::textChanged(const QString &text) { TRACE_OBJ - emit find(text, true); + emit find(text, true, true); } bool FindWidget::eventFilter(QObject *object, QEvent *e) diff --git a/tools/assistant/tools/assistant/findwidget.h b/tools/assistant/tools/assistant/findwidget.h index cf78003..85e1959 100644 --- a/tools/assistant/tools/assistant/findwidget.h +++ b/tools/assistant/tools/assistant/findwidget.h @@ -67,11 +67,10 @@ public: void setTextWrappedVisible(bool visible); signals: - void escapePressed(); - void findNext(); void findPrevious(); - void find(const QString &text, bool forward); + void escapePressed(); + void find(const QString &text, bool forward, bool incremental); protected: void hideEvent(QHideEvent* event); diff --git a/tools/assistant/tools/assistant/globalactions.cpp b/tools/assistant/tools/assistant/globalactions.cpp new file mode 100644 index 0000000..0eeab21 --- /dev/null +++ b/tools/assistant/tools/assistant/globalactions.cpp @@ -0,0 +1,246 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "globalactions.h" + +#include "centralwidget.h" +#include "helpviewer.h" +#include "tracer.h" + +#include <QtGui/QAction> +#include <QtGui/QMenu> + +#if !defined(QT_NO_WEBKIT) +#include <QtWebKit/QWebHistory> +#endif + +GlobalActions *GlobalActions::instance(QObject *parent) +{ + Q_ASSERT(!m_instance != !parent); + if (!m_instance) + m_instance = new GlobalActions(parent); + return m_instance; +} + +GlobalActions::GlobalActions(QObject *parent) : QObject(parent) +{ + TRACE_OBJ + + // TODO: Put resource path in misc class + QString resourcePath = QLatin1String(":/trolltech/assistant/images/"); +#ifdef Q_OS_MAC + resourcePath.append(QLatin1String("mac")); +#else + resourcePath.append(QLatin1String("win")); +#endif + CentralWidget *centralWidget = CentralWidget::instance(); + + m_backAction = new QAction(tr("&Back"), parent); + m_backAction->setEnabled(false); + m_backAction->setShortcuts(QKeySequence::Back); + m_backAction->setIcon(QIcon(resourcePath + QLatin1String("/previous.png"))); + connect(m_backAction, SIGNAL(triggered()), centralWidget, SLOT(backward())); + m_actionList << m_backAction; + + m_nextAction = new QAction(tr("&Forward"), parent); + m_nextAction->setPriority(QAction::LowPriority); + m_nextAction->setEnabled(false); + m_nextAction->setShortcuts(QKeySequence::Forward); + m_nextAction->setIcon(QIcon(resourcePath + QLatin1String("/next.png"))); + connect(m_nextAction, SIGNAL(triggered()), centralWidget, SLOT(forward())); + m_actionList << m_nextAction; + + setupNavigationMenus(m_backAction, m_nextAction, centralWidget); + + m_homeAction = new QAction(tr("&Home"), parent); + m_homeAction->setShortcut(tr("ALT+Home")); + m_homeAction->setIcon(QIcon(resourcePath + QLatin1String("/home.png"))); + connect(m_homeAction, SIGNAL(triggered()), centralWidget, SLOT(home())); + m_actionList << m_homeAction; + + QAction *separator = new QAction(parent); + separator->setSeparator(true); + m_actionList << separator; + + m_zoomInAction = new QAction(tr("Zoom &in"), parent); + m_zoomInAction->setPriority(QAction::LowPriority); + m_zoomInAction->setIcon(QIcon(resourcePath + QLatin1String("/zoomin.png"))); + m_zoomInAction->setShortcut(QKeySequence::ZoomIn); + connect(m_zoomInAction, SIGNAL(triggered()), centralWidget, SLOT(zoomIn())); + m_actionList << m_zoomInAction; + + m_zoomOutAction = new QAction(tr("Zoom &out"), parent); + m_zoomOutAction->setPriority(QAction::LowPriority); + m_zoomOutAction->setIcon(QIcon(resourcePath + QLatin1String("/zoomout.png"))); + m_zoomOutAction->setShortcut(QKeySequence::ZoomOut); + connect(m_zoomOutAction, SIGNAL(triggered()), centralWidget, SLOT(zoomOut())); + m_actionList << m_zoomOutAction; + + separator = new QAction(parent); + separator->setSeparator(true); + m_actionList << separator; + + m_copyAction = new QAction(tr("&Copy selected Text"), parent); + m_copyAction->setPriority(QAction::LowPriority); + m_copyAction->setIconText("&Copy"); + m_copyAction->setIcon(QIcon(resourcePath + QLatin1String("/editcopy.png"))); + m_copyAction->setShortcuts(QKeySequence::Copy); + m_copyAction->setEnabled(false); + connect(m_copyAction, SIGNAL(triggered()), centralWidget, SLOT(copy())); + m_actionList << m_copyAction; + + m_printAction = new QAction(tr("&Print..."), parent); + m_printAction->setPriority(QAction::LowPriority); + m_printAction->setIcon(QIcon(resourcePath + QLatin1String("/print.png"))); + m_printAction->setShortcut(QKeySequence::Print); + connect(m_printAction, SIGNAL(triggered()), centralWidget, SLOT(print())); + m_actionList << m_printAction; + + m_findAction = new QAction(tr("&Find in Text..."), parent); + m_findAction->setIconText(tr("&Find")); + m_findAction->setIcon(QIcon(resourcePath + QLatin1String("/find.png"))); + m_findAction->setShortcuts(QKeySequence::Find); + connect(m_findAction, SIGNAL(triggered()), centralWidget, SLOT(showTextSearch())); + m_actionList << m_findAction; + +#ifdef Q_WS_X11 + m_backAction->setIcon(QIcon::fromTheme("go-previous" , m_backAction->icon())); + m_nextAction->setIcon(QIcon::fromTheme("go-next" , m_nextAction->icon())); + m_zoomInAction->setIcon(QIcon::fromTheme("zoom-in" , m_zoomInAction->icon())); + m_zoomOutAction->setIcon(QIcon::fromTheme("zoom-out" , m_zoomOutAction->icon())); + m_copyAction->setIcon(QIcon::fromTheme("edit-copy" , m_copyAction->icon())); + m_findAction->setIcon(QIcon::fromTheme("edit-find" , m_findAction->icon())); + m_homeAction->setIcon(QIcon::fromTheme("go-home" , m_homeAction->icon())); + m_printAction->setIcon(QIcon::fromTheme("document-print" , m_printAction->icon())); +#endif +} + +void GlobalActions::updateActions() +{ + TRACE_OBJ + CentralWidget *centralWidget = CentralWidget::instance(); + m_copyAction->setEnabled(centralWidget->hasSelection()); + m_nextAction->setEnabled(centralWidget->isForwardAvailable()); + m_backAction->setEnabled(centralWidget->isBackwardAvailable()); +} + +void GlobalActions::setCopyAvailable(bool available) +{ + TRACE_OBJ + m_copyAction->setEnabled(available); +} + +#if !defined(QT_NO_WEBKIT) + +void GlobalActions::slotAboutToShowBackMenu() +{ + TRACE_OBJ + m_backMenu->clear(); + if (QWebHistory *history = CentralWidget::instance()->currentHelpViewer()->history()) { + const int currentItemIndex = history->currentItemIndex(); + QList<QWebHistoryItem> items = history->backItems(history->count()); + for (int i = items.count() - 1; i >= 0; --i) { + QAction *action = new QAction(this); + action->setText(items.at(i).title()); + action->setData(-1 * (currentItemIndex - i)); + m_backMenu->addAction(action); + } + } +} + +void GlobalActions::slotAboutToShowNextMenu() +{ + TRACE_OBJ + m_nextMenu->clear(); + if (QWebHistory *history = CentralWidget::instance()->currentHelpViewer()->history()) { + const int count = history->count(); + QList<QWebHistoryItem> items = history->forwardItems(count); + for (int i = 0; i < items.count(); ++i) { + QAction *action = new QAction(this); + action->setData(count - i); + action->setText(items.at(i).title()); + m_nextMenu->addAction(action); + } + } +} + +void GlobalActions::slotOpenActionUrl(QAction *action) +{ + TRACE_OBJ + if (HelpViewer* viewer = CentralWidget::instance()->currentHelpViewer()) { + const int offset = action->data().toInt(); + QWebHistory *history = viewer->history(); + if (offset > 0) { + history->goToItem(history->forwardItems(history->count() + - offset + 1).back()); // forward + } else if (offset < 0) { + history->goToItem(history->backItems(-1 * offset).first()); // back + } + } +} + +#endif + +void GlobalActions::setupNavigationMenus(QAction *back, QAction *next, + QWidget *parent) +{ +#if !defined(QT_NO_WEBKIT) + m_backMenu = new QMenu(parent); + connect(m_backMenu, SIGNAL(aboutToShow()), this, + SLOT(slotAboutToShowBackMenu())); + connect(m_backMenu, SIGNAL(triggered(QAction*)), this, + SLOT(slotOpenActionUrl(QAction*))); + back->setMenu(m_backMenu); + + m_nextMenu = new QMenu(parent); + connect(m_nextMenu, SIGNAL(aboutToShow()), this, + SLOT(slotAboutToShowNextMenu())); + connect(m_nextMenu, SIGNAL(triggered(QAction*)), this, + SLOT(slotOpenActionUrl(QAction*))); + next->setMenu(m_nextMenu); +#else + Q_UNUSED(back) + Q_UNUSED(next) + Q_UNUSED(parent) +#endif +} + +GlobalActions *GlobalActions::m_instance = 0; diff --git a/tools/assistant/tools/assistant/globalactions.h b/tools/assistant/tools/assistant/globalactions.h new file mode 100644 index 0000000..ca8d7eb --- /dev/null +++ b/tools/assistant/tools/assistant/globalactions.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GLOBALACTION_H +#define GLOBALACTION_H + +#include <QtCore/QList> +#include <QtCore/QObject> + +QT_BEGIN_NAMESPACE + +class QAction; +class QMenu; + +class GlobalActions : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(GlobalActions) +public: + static GlobalActions *instance(QObject *parent = 0); + + QList<QAction *> actionList() const { return m_actionList; } + QAction *backAction() const { return m_backAction; } + QAction *nextAction() const { return m_nextAction; } + QAction *homeAction() const { return m_homeAction; } + QAction *zoomInAction() const { return m_zoomInAction; } + QAction *zoomOutAction() const { return m_zoomOutAction; } + QAction *copyAction() const { return m_copyAction; } + QAction *printAction() const { return m_printAction; } + QAction *findAction() const { return m_findAction; } + + Q_SLOT void updateActions(); + Q_SLOT void setCopyAvailable(bool available); + +#if !defined(QT_NO_WEBKIT) +private slots: + void slotAboutToShowBackMenu(); + void slotAboutToShowNextMenu(); + void slotOpenActionUrl(QAction *action); +#endif + +private: + void setupNavigationMenus(QAction *back, QAction *next, QWidget *parent); + +private: + GlobalActions(QObject *parent); + + static GlobalActions *m_instance; + + QAction *m_backAction; + QAction *m_nextAction; + QAction *m_homeAction; + QAction *m_zoomInAction; + QAction *m_zoomOutAction; + QAction *m_copyAction; + QAction *m_printAction; + QAction *m_findAction; + + QList<QAction *> m_actionList; + + QMenu *m_backMenu; + QMenu *m_nextMenu; +}; + +QT_END_NAMESPACE + +#endif // GLOBALACTION_H diff --git a/tools/assistant/tools/assistant/helpenginewrapper.cpp b/tools/assistant/tools/assistant/helpenginewrapper.cpp index a53a9ee..8a5bb9c 100644 --- a/tools/assistant/tools/assistant/helpenginewrapper.cpp +++ b/tools/assistant/tools/assistant/helpenginewrapper.cpp @@ -72,6 +72,7 @@ namespace { const QString UseBrowserFontKey(QLatin1String("useBrowserFont")); const QString VersionKey(QString(QLatin1String("qtVersion%1$$$%2")). arg(QLatin1String(QT_VERSION_STR))); + const QString ShowTabsKey(QLatin1String("showTabs")); } // anonymous namespace class TimeoutForwarder : public QObject @@ -147,7 +148,7 @@ HelpEngineWrapper::HelpEngineWrapper(const QString &collectionFile) * because we will start to index them, only to be interupted * by the next request. Also, there is a nasty SQLITE bug that will * cause the application to hang for minutes in that case. - * This call is reverted by initalDocSetupDone(), which must be + * This call is reverted by initialDocSetupDone(), which must be * called after the new docs have been installed. */ disconnect(d->m_helpEngine, SIGNAL(setupFinished()), @@ -569,18 +570,6 @@ void HelpEngineWrapper::setLastTabPage(int lastPage) CollectionConfiguration::setLastTabPage(*d->m_helpEngine, lastPage); } -bool HelpEngineWrapper::searchWasAttached() const -{ - TRACE_OBJ - return d->m_helpEngine->customValue(SearchWasAttachedKey).toBool(); -} - -void HelpEngineWrapper::setSearchWasAttached(bool attached) -{ - TRACE_OBJ - d->m_helpEngine->setCustomValue(SearchWasAttachedKey, attached); -} - int HelpEngineWrapper::startOption() const { TRACE_OBJ @@ -655,7 +644,7 @@ void HelpEngineWrapper::setUseBrowserFont(bool useBrowserFont) const QFont HelpEngineWrapper::appFont() const { TRACE_OBJ - return qVariantValue<QFont>(d->m_helpEngine->customValue(AppFontKey)); + return qvariant_cast<QFont>(d->m_helpEngine->customValue(AppFontKey)); } void HelpEngineWrapper::setAppFont(const QFont &font) @@ -680,7 +669,7 @@ void HelpEngineWrapper::setAppWritingSystem(QFontDatabase::WritingSystem system) const QFont HelpEngineWrapper::browserFont() const { TRACE_OBJ - return qVariantValue<QFont>(d->m_helpEngine->customValue(BrowserFontKey)); + return qvariant_cast<QFont>(d->m_helpEngine->customValue(BrowserFontKey)); } void HelpEngineWrapper::setBrowserFont(const QFont &font) @@ -709,6 +698,17 @@ void HelpEngineWrapper::handleCurrentFilterChanged(const QString &filter) emit currentFilterChanged(filterToReport); } +bool HelpEngineWrapper::showTabs() const +{ + return d->m_helpEngine->customValue(ShowTabsKey, false).toBool(); +} + +void HelpEngineWrapper::setShowTabs(bool show) +{ + d->m_helpEngine->setCustomValue(ShowTabsKey, show); +} + +// -- TimeoutForwarder TimeoutForwarder::TimeoutForwarder(const QString &fileName) : m_fileName(fileName) @@ -722,6 +722,7 @@ void TimeoutForwarder::forward() HelpEngineWrapper::instance().d->qchFileChanged(m_fileName, true); } +// -- HelpEngineWrapperPrivate HelpEngineWrapperPrivate::HelpEngineWrapperPrivate(const QString &collectionFile) : m_helpEngine(new QHelpEngine(collectionFile, this)), @@ -829,7 +830,6 @@ void HelpEngineWrapperPrivate::qchFileChanged(const QString &fileName, m_recentQchUpdates.erase(it); } - QT_END_NAMESPACE #include "helpenginewrapper.moc" diff --git a/tools/assistant/tools/assistant/helpenginewrapper.h b/tools/assistant/tools/assistant/helpenginewrapper.h index c1041b6..7349015 100644 --- a/tools/assistant/tools/assistant/helpenginewrapper.h +++ b/tools/assistant/tools/assistant/helpenginewrapper.h @@ -170,9 +170,6 @@ public: int startOption() const; void setStartOption(int option); - bool searchWasAttached() const; - void setSearchWasAttached(bool attached); - bool hasFontSettings() const; bool usesAppFont() const; void setUseAppFont(bool useAppFont); @@ -187,6 +184,9 @@ public: QFontDatabase::WritingSystem browserWritingSystem() const; void setBrowserWritingSystem(QFontDatabase::WritingSystem system); + bool showTabs() const; + void setShowTabs(bool show); + static const QString TrUnfiltered; signals: diff --git a/tools/assistant/tools/assistant/helpviewer.cpp b/tools/assistant/tools/assistant/helpviewer.cpp index 6499139..2e4b60c 100644 --- a/tools/assistant/tools/assistant/helpviewer.cpp +++ b/tools/assistant/tools/assistant/helpviewer.cpp @@ -38,7 +38,10 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #include "helpviewer.h" +#include "helpviewer_p.h" + #include "helpenginewrapper.h" #include "tracer.h" @@ -49,18 +52,21 @@ #include <QtCore/QUrl> #include <QtGui/QDesktopServices> +#include <QtGui/QMouseEvent> + +#include <QtHelp/QHelpEngineCore> QT_BEGIN_NAMESPACE -const QLatin1String AbstractHelpViewer::DocPath("qthelp://com.trolltech."); +const QString HelpViewer::DocPath = QLatin1String("qthelp://com.trolltech."); -const QString AbstractHelpViewer::AboutBlank = +const QString HelpViewer::AboutBlank = QCoreApplication::translate("HelpViewer", "<title>about:blank</title>"); -const QString AbstractHelpViewer::LocalHelpFile = QLatin1String("qthelp://" +const QString HelpViewer::LocalHelpFile = QLatin1String("qthelp://" "com.trolltech.com.assistantinternal-1.0.0/assistant/assistant.html"); -const QString AbstractHelpViewer::PageNotFoundMessage = +const QString HelpViewer::PageNotFoundMessage = QCoreApplication::translate("HelpViewer", "<title>Error 404...</title><div " "align=\"center\"><br><br><h1>The page could not be found</h1><br><h3>'%1'" "</h3></div>"); @@ -102,17 +108,13 @@ struct ExtensionMap { { 0, 0 } }; -// -- AbstractHelpViewer - -AbstractHelpViewer::AbstractHelpViewer() -{ -} - -AbstractHelpViewer::~AbstractHelpViewer() +HelpViewer::~HelpViewer() { + TRACE_OBJ + delete d; } -bool AbstractHelpViewer::isLocalUrl(const QUrl &url) +bool HelpViewer::isLocalUrl(const QUrl &url) { TRACE_OBJ const QString &scheme = url.scheme(); @@ -124,13 +126,13 @@ bool AbstractHelpViewer::isLocalUrl(const QUrl &url) || scheme == QLatin1String("about"); } -bool AbstractHelpViewer::canOpenPage(const QString &url) +bool HelpViewer::canOpenPage(const QString &url) { TRACE_OBJ return !mimeFromUrl(url).isEmpty(); } -QString AbstractHelpViewer::mimeFromUrl(const QUrl &url) +QString HelpViewer::mimeFromUrl(const QUrl &url) { TRACE_OBJ const QString &path = url.path(); @@ -146,7 +148,7 @@ QString AbstractHelpViewer::mimeFromUrl(const QUrl &url) return QLatin1String(""); } -bool AbstractHelpViewer::launchWithExternalApp(const QUrl &url) +bool HelpViewer::launchWithExternalApp(const QUrl &url) { TRACE_OBJ if (isLocalUrl(url)) { @@ -177,4 +179,43 @@ bool AbstractHelpViewer::launchWithExternalApp(const QUrl &url) return false; } +// -- public slots + +void HelpViewer::home() +{ + TRACE_OBJ + setSource(HelpEngineWrapper::instance().homePage()); +} + +// -- private slots + +void HelpViewer::setLoadStarted() +{ + d->m_loadFinished = false; +} + +void HelpViewer::setLoadFinished(bool ok) +{ + d->m_loadFinished = ok; + emit sourceChanged(source()); +} + +// -- private + +bool HelpViewer::handleForwardBackwardMouseButtons(QMouseEvent *event) +{ + TRACE_OBJ + if (event->button() == Qt::XButton1) { + backward(); + return true; + } + + if (event->button() == Qt::XButton2) { + forward(); + return true; + } + + return false; +} + QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/helpviewer.h b/tools/assistant/tools/assistant/helpviewer.h index def9418..e2aefca 100644 --- a/tools/assistant/tools/assistant/helpviewer.h +++ b/tools/assistant/tools/assistant/helpviewer.h @@ -38,36 +38,69 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #ifndef HELPVIEWER_H #define HELPVIEWER_H +#include <QtCore/qglobal.h> #include <QtCore/QString> +#include <QtCore/QUrl> +#include <QtCore/QVariant> +#include <QtGui/QAction> #include <QtGui/QFont> -QT_BEGIN_NAMESPACE +#if defined(QT_NO_WEBKIT) +#include <QtGui/QTextBrowser> +#else +#include <QtWebKit/QWebView> +#endif -class QMouseEvent; -class QUrl; +QT_BEGIN_NAMESPACE -class AbstractHelpViewer +#if !defined(QT_NO_WEBKIT) +class HelpViewer : public QWebView +#else +class HelpViewer : public QTextBrowser +#endif { + Q_OBJECT + class HelpViewerPrivate; + Q_DISABLE_COPY(HelpViewer) + public: - AbstractHelpViewer(); - virtual ~AbstractHelpViewer(); + enum FindFlag { + FindBackward = 0x01, + FindCaseSensitively = 0x02 + }; + Q_DECLARE_FLAGS(FindFlags, FindFlag) + + HelpViewer(qreal zoom, QWidget *parent = 0); + ~HelpViewer(); + + QFont viewerFont() const; + void setViewerFont(const QFont &font); + + void scaleUp(); + void scaleDown(); + + void resetScale(); + qreal scale() const; - virtual QFont viewerFont() const = 0; - virtual void setViewerFont(const QFont &font) = 0; + QString title() const; + void setTitle(const QString &title); - virtual void scaleUp() = 0; - virtual void scaleDown() = 0; - - virtual void resetScale() = 0; - virtual qreal scale() const = 0; + QUrl source() const; + void setSource(const QUrl &url); - virtual bool handleForwardBackwardMouseButtons(QMouseEvent *e) = 0; + QString selectedText() const; + bool isForwardAvailable() const; + bool isBackwardAvailable() const; - static const QLatin1String DocPath; + bool findText(const QString &text, FindFlags flags, bool incremental, + bool fromSearch); + + static const QString DocPath; static const QString AboutBlank; static const QString LocalHelpFile; static const QString PageNotFoundMessage; @@ -76,8 +109,50 @@ public: static bool canOpenPage(const QString &url); static QString mimeFromUrl(const QUrl &url); static bool launchWithExternalApp(const QUrl &url); + +public slots: + void copy(); + void home(); + + void forward(); + void backward(); + +signals: + void titleChanged(); +#if !defined(QT_NO_WEBKIT) + void copyAvailable(bool yes); + void sourceChanged(const QUrl &url); + void forwardAvailable(bool enabled); + void backwardAvailable(bool enabled); + void highlighted(const QString &link); + void printRequested(); +#else + void loadStarted(); + void loadFinished(bool finished); +#endif + +protected: + void keyPressEvent(QKeyEvent *e); + void wheelEvent(QWheelEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + +private slots: + void actionChanged(); + void setLoadStarted(); + void setLoadFinished(bool ok); + +private: + bool eventFilter(QObject *obj, QEvent *event); + void contextMenuEvent(QContextMenuEvent *event); + QVariant loadResource(int type, const QUrl &name); + bool handleForwardBackwardMouseButtons(QMouseEvent *e); + +private: + HelpViewerPrivate *d; }; QT_END_NAMESPACE +Q_DECLARE_METATYPE(HelpViewer*) #endif // HELPVIEWER_H diff --git a/tools/assistant/tools/assistant/helpviewer_qtb.h b/tools/assistant/tools/assistant/helpviewer_p.h index 58aacd7..d65bab5 100644 --- a/tools/assistant/tools/assistant/helpviewer_qtb.h +++ b/tools/assistant/tools/assistant/helpviewer_p.h @@ -38,76 +38,86 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#ifndef HELPVIEWERQTB_H -#define HELPVIEWERQTB_H -#include "helpviewer.h" +#ifndef HELPVIEWERPRIVATE_H +#define HELPVIEWERPRIVATE_H -#include <QtCore/QUrl> -#include <QtCore/QVariant> +#include "centralwidget.h" +#include "helpviewer.h" +#include "openpagesmanager.h" +#include <QtCore/QObject> +#ifdef QT_NO_WEBKIT #include <QtGui/QTextBrowser> +#endif QT_BEGIN_NAMESPACE -class CentralWidget; -class HelpEngineWrapper; -class QContextMenuEvent; -class QKeyEvent; -class QMouseEvent; - -class HelpViewer : public QTextBrowser, public AbstractHelpViewer +class HelpViewer::HelpViewerPrivate : public QObject { Q_OBJECT public: - explicit HelpViewer(CentralWidget *parent, qreal zoom = 0.0); - ~HelpViewer(); - - QFont viewerFont() const; - void setViewerFont(const QFont &font); - - void scaleUp(); - void scaleDown(); - void resetScale(); - qreal scale() const { return zoomCount; } - - bool handleForwardBackwardMouseButtons(QMouseEvent *e); - - void setSource(const QUrl &url); - - inline bool hasSelection() const - { return textCursor().hasSelection(); } +#ifdef QT_NO_WEBKIT + HelpViewerPrivate(int zoom) + : zoomCount(zoom) + , forceFont(false) + , lastAnchor(QString()) +#else + HelpViewerPrivate() +#endif + { + m_loadFinished = false; + } + +#ifdef QT_NO_WEBKIT + bool hasAnchorAt(QTextBrowser *browser, const QPoint& pos) + { + lastAnchor = browser->anchorAt(pos); + if (lastAnchor.isEmpty()) + return false; + + lastAnchor = browser->source().resolved(lastAnchor).toString(); + if (lastAnchor.at(0) == QLatin1Char('#')) { + QString src = browser->source().toString(); + int hsh = src.indexOf(QLatin1Char('#')); + lastAnchor = (hsh >= 0 ? src.left(hsh) : src) + lastAnchor; + } + return true; + } + + void openLink(bool newPage) + { + if(lastAnchor.isEmpty()) + return; + if (newPage) + OpenPagesManager::instance()->createPage(lastAnchor); + else + CentralWidget::instance()->setSource(lastAnchor); + lastAnchor.clear(); + } + +public slots: + void openLink() + { + openLink(false); + } + + void openLinkInNewPage() + { + openLink(true); + } -public Q_SLOTS: - void home(); - -protected: - void wheelEvent(QWheelEvent *e); - bool eventFilter(QObject *obj, QEvent *event); - -private: - QVariant loadResource(int type, const QUrl &name); - void openLinkInNewTab(const QString &link); - bool hasAnchorAt(const QPoint& pos); - void contextMenuEvent(QContextMenuEvent *e); - void mouseReleaseEvent(QMouseEvent *e); - void keyPressEvent(QKeyEvent *e); - void mousePressEvent(QMouseEvent *e); - -private slots: - void openLinkInNewTab(); - -private: +public: int zoomCount; - bool controlPressed; + bool forceFont; QString lastAnchor; - CentralWidget* parentWidget; - HelpEngineWrapper &helpEngine; +#endif // QT_NO_WEBKIT - bool forceFont; +public: + bool m_loadFinished; }; QT_END_NAMESPACE -#endif // HELPVIEWERQTB_H +#endif // HELPVIEWERPRIVATE_H diff --git a/tools/assistant/tools/assistant/helpviewer_qtb.cpp b/tools/assistant/tools/assistant/helpviewer_qtb.cpp index 7f82b56..af744b7 100644 --- a/tools/assistant/tools/assistant/helpviewer_qtb.cpp +++ b/tools/assistant/tools/assistant/helpviewer_qtb.cpp @@ -38,10 +38,13 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "helpviewer_qtb.h" -#include "centralwidget.h" +#include "helpviewer.h" + +#include "globalactions.h" #include "helpenginewrapper.h" +#include "helpviewer_p.h" +#include "openpagesmanager.h" #include "tracer.h" #include <QtCore/QStringBuilder> @@ -53,34 +56,34 @@ QT_BEGIN_NAMESPACE -HelpViewer::HelpViewer(CentralWidget *parent, qreal zoom) +HelpViewer::HelpViewer(qreal zoom, QWidget *parent) : QTextBrowser(parent) - , zoomCount(zoom) - , controlPressed(false) - , lastAnchor(QString()) - , parentWidget(parent) - , helpEngine(HelpEngineWrapper::instance()) - , forceFont(false) + , d(new HelpViewerPrivate(zoom)) { TRACE_OBJ + QPalette p = palette(); + p.setColor(QPalette::Inactive, QPalette::Highlight, + p.color(QPalette::Active, QPalette::Highlight)); + p.setColor(QPalette::Inactive, QPalette::HighlightedText, + p.color(QPalette::Active, QPalette::HighlightedText)); + setPalette(p); + installEventFilter(this); document()->setDocumentMargin(8); QFont font = viewerFont(); font.setPointSize(int(font.pointSize() + zoom)); setViewerFont(font); -} -HelpViewer::~HelpViewer() -{ - TRACE_OBJ + connect(this, SIGNAL(sourceChanged(QUrl)), this, SIGNAL(titleChanged())); + connect(this, SIGNAL(loadFinished(bool)), this, SLOT(setLoadFinished(bool))); } QFont HelpViewer::viewerFont() const { TRACE_OBJ if (HelpEngineWrapper::instance().usesBrowserFont()) - return helpEngine.browserFont(); + return HelpEngineWrapper::instance().browserFont(); return qApp->font(); } @@ -88,185 +91,183 @@ void HelpViewer::setViewerFont(const QFont &newFont) { TRACE_OBJ if (font() != newFont) { - forceFont = true; + d->forceFont = true; setFont(newFont); - forceFont = false; + d->forceFont = false; } } void HelpViewer::scaleUp() { TRACE_OBJ - if (zoomCount < 10) { - ++zoomCount; - forceFont = true; + if (d->zoomCount < 10) { + d->zoomCount++; + d->forceFont = true; zoomIn(); - forceFont = false; + d->forceFont = false; } } void HelpViewer::scaleDown() { TRACE_OBJ - if (zoomCount > -5) { - --zoomCount; - forceFont = true; + if (d->zoomCount > -5) { + d->zoomCount--; + d->forceFont = true; zoomOut(); - forceFont = false; + d->forceFont = false; } } void HelpViewer::resetScale() { TRACE_OBJ - if (zoomCount != 0) { - forceFont = true; - zoomOut(zoomCount); - forceFont = false; + if (d->zoomCount != 0) { + d->forceFont = true; + zoomOut(d->zoomCount); + d->forceFont = false; } - zoomCount = 0; + d->zoomCount = 0; } -bool HelpViewer::handleForwardBackwardMouseButtons(QMouseEvent *e) +qreal HelpViewer::scale() const { - if (e->button() == Qt::XButton1) { - QTextBrowser::backward(); - return true; - } + TRACE_OBJ + return d->zoomCount; +} - if (e->button() == Qt::XButton2) { - QTextBrowser::forward(); - return true; - } - return false; +QString HelpViewer::title() const +{ + TRACE_OBJ + return documentTitle(); +} + +void HelpViewer::setTitle(const QString &title) +{ + TRACE_OBJ + setDocumentTitle(title); +} + +QUrl HelpViewer::source() const +{ + TRACE_OBJ + return QTextBrowser::source(); } void HelpViewer::setSource(const QUrl &url) { TRACE_OBJ - const QString &string = url.toString(); - if (url.isValid() && string != QLatin1String("help")) { - if (launchWithExternalApp(url)) - return; - - const QUrl &resolvedUrl = helpEngine.findFile(url); - if (resolvedUrl.isValid()) { - QTextBrowser::setSource(resolvedUrl); - return; - } - } + if (launchWithExternalApp(url)) + return; - if (string != QLatin1String("help")) { - QTextBrowser::setSource(url); + emit loadStarted(); + QString string = url.toString(); + const HelpEngineWrapper &engine = HelpEngineWrapper::instance(); + const QUrl &resolvedUrl = (string == QLatin1String("help") ? LocalHelpFile : + engine.findFile(string)); + QTextBrowser::setSource(resolvedUrl); + if (!url.isValid()) { setHtml(string == QLatin1String("about:blank") ? AboutBlank : PageNotFoundMessage.arg(url.toString())); - emit sourceChanged(url); - } else { - QTextBrowser::setSource(LocalHelpFile); } + emit loadFinished(true); } -QVariant HelpViewer::loadResource(int type, const QUrl &name) +QString HelpViewer::selectedText() const { TRACE_OBJ - QByteArray ba; - if (type < 4) { - ba = helpEngine.fileData(name); - if (name.toString().endsWith(QLatin1String(".svg"), Qt::CaseInsensitive)) { - QImage image; - image.loadFromData(ba, "svg"); - if (!image.isNull()) - return image; - } - } - return ba; + return textCursor().selectedText(); } -void HelpViewer::openLinkInNewTab() +bool HelpViewer::isForwardAvailable() const { TRACE_OBJ - if(lastAnchor.isEmpty()) - return; - - parentWidget->setSourceInNewTab(QUrl(lastAnchor)); - lastAnchor.clear(); + return QTextBrowser::isForwardAvailable(); } -void HelpViewer::openLinkInNewTab(const QString &link) +bool HelpViewer::isBackwardAvailable() const { TRACE_OBJ - lastAnchor = link; - openLinkInNewTab(); + return QTextBrowser::isBackwardAvailable(); } -bool HelpViewer::hasAnchorAt(const QPoint& pos) +bool HelpViewer::findText(const QString &text, FindFlags flags, bool incremental, + bool fromSearch) { TRACE_OBJ - lastAnchor = anchorAt(pos); - if (lastAnchor.isEmpty()) + QTextDocument *doc = document(); + QTextCursor cursor = textCursor(); + if (!doc || cursor.isNull()) return false; - lastAnchor = source().resolved(lastAnchor).toString(); - if (lastAnchor.at(0) == QLatin1Char('#')) { - QString src = source().toString(); - int hsh = src.indexOf(QLatin1Char('#')); - lastAnchor = (hsh>=0 ? src.left(hsh) : src) + lastAnchor; + const int position = cursor.selectionStart(); + if (incremental) + cursor.setPosition(position); + + QTextDocument::FindFlags textDocFlags; + if (flags & HelpViewer::FindBackward) + textDocFlags |= QTextDocument::FindBackward; + if (flags & HelpViewer::FindCaseSensitively) + textDocFlags |= QTextDocument::FindCaseSensitively; + + QTextCursor found = doc->find(text, cursor, textDocFlags); + if (found.isNull()) { + if ((flags & HelpViewer::FindBackward) == 0) + cursor.movePosition(QTextCursor::Start); + else + cursor.movePosition(QTextCursor::End); + found = doc->find(text, cursor, textDocFlags); } - return true; -} + if (fromSearch) { + cursor.beginEditBlock(); + viewport()->setUpdatesEnabled(false); -void HelpViewer::contextMenuEvent(QContextMenuEvent *e) -{ - TRACE_OBJ - QMenu menu(QLatin1String(""), 0); + QTextCharFormat marker; + marker.setForeground(Qt::red); + cursor.movePosition(QTextCursor::Start); + setTextCursor(cursor); - QUrl link; - QAction *copyAnchorAction = 0; - if (hasAnchorAt(e->pos())) { - link = anchorAt(e->pos()); - if (link.isRelative()) - link = source().resolved(link); - copyAnchorAction = menu.addAction(tr("Copy &Link Location")); - copyAnchorAction->setEnabled(!link.isEmpty() && link.isValid()); + while (find(text)) { + QTextCursor hit = textCursor(); + hit.mergeCharFormat(marker); + } - menu.addAction(tr("Open Link in New Tab\tCtrl+LMB"), this, - SLOT(openLinkInNewTab())); - menu.addSeparator(); + viewport()->setUpdatesEnabled(true); + cursor.endEditBlock(); } - menu.addActions(parentWidget->globalActions()); - QAction *action = menu.exec(e->globalPos()); - if (action == copyAnchorAction) - QApplication::clipboard()->setText(link.toString()); + + bool cursorIsNull = found.isNull(); + if (cursorIsNull) { + found = textCursor(); + found.setPosition(position); + } + setTextCursor(found); + return !cursorIsNull; } -void HelpViewer::mouseReleaseEvent(QMouseEvent *e) +// -- public slots + +void HelpViewer::copy() { TRACE_OBJ -#ifndef Q_OS_LINUX - if (handleForwardBackwardMouseButtons(e)) - return; -#endif - - controlPressed = e->modifiers() & Qt::ControlModifier; - if ((controlPressed && hasAnchorAt(e->pos())) || - (e->button() == Qt::MidButton && hasAnchorAt(e->pos()))) { - openLinkInNewTab(); - return; - } + QTextBrowser::copy(); +} - QTextBrowser::mouseReleaseEvent(e); +void HelpViewer::forward() +{ + TRACE_OBJ + QTextBrowser::forward(); } -void HelpViewer::mousePressEvent(QMouseEvent *e) +void HelpViewer::backward() { -#ifdef Q_OS_LINUX - if (handleForwardBackwardMouseButtons(e)) - return; -#endif - QTextBrowser::mousePressEvent(e); + TRACE_OBJ + QTextBrowser::backward(); } +// -- protected + void HelpViewer::keyPressEvent(QKeyEvent *e) { TRACE_OBJ @@ -279,11 +280,6 @@ void HelpViewer::keyPressEvent(QKeyEvent *e) QTextBrowser::keyPressEvent(e); } -void HelpViewer::home() -{ - TRACE_OBJ - setSource(helpEngine.homePage()); -} void HelpViewer::wheelEvent(QWheelEvent *e) { @@ -296,12 +292,93 @@ void HelpViewer::wheelEvent(QWheelEvent *e) } } +void HelpViewer::mousePressEvent(QMouseEvent *e) +{ + TRACE_OBJ +#ifdef Q_OS_LINUX + if (handleForwardBackwardMouseButtons(e)) + return; +#endif + + QTextBrowser::mousePressEvent(e); +} + +void HelpViewer::mouseReleaseEvent(QMouseEvent *e) +{ + TRACE_OBJ +#ifndef Q_OS_LINUX + if (handleForwardBackwardMouseButtons(e)) + return; +#endif + + bool controlPressed = e->modifiers() & Qt::ControlModifier; + if ((controlPressed && d->hasAnchorAt(this, e->pos())) || + (e->button() == Qt::MidButton && d->hasAnchorAt(this, e->pos()))) { + d->openLinkInNewPage(); + return; + } + + QTextBrowser::mouseReleaseEvent(e); +} + +// -- private slots + +void HelpViewer::actionChanged() +{ + // stub + TRACE_OBJ +} + +// -- private + bool HelpViewer::eventFilter(QObject *obj, QEvent *event) { TRACE_OBJ - if (event->type() == QEvent::FontChange && !forceFont) + if (event->type() == QEvent::FontChange && !d->forceFont) return true; return QTextBrowser::eventFilter(obj, event); } +void HelpViewer::contextMenuEvent(QContextMenuEvent *event) +{ + TRACE_OBJ + + QMenu menu(QString(), 0); + QUrl link; + QAction *copyAnchorAction = 0; + if (d->hasAnchorAt(this, event->pos())) { + link = anchorAt(event->pos()); + if (link.isRelative()) + link = source().resolved(link); + menu.addAction(tr("Open Link"), d, SLOT(openLink())); + menu.addAction(tr("Open Link in New Tab\tCtrl+LMB"), d, SLOT(openLinkInNewPage())); + + if (!link.isEmpty() && link.isValid()) + copyAnchorAction = menu.addAction(tr("Copy &Link Location")); + } else if (!selectedText().isEmpty()) { + menu.addAction(tr("Copy"), this, SLOT(copy())); + } else { + menu.addAction(tr("Reload"), this, SLOT(reload())); + } + + if (copyAnchorAction == menu.exec(event->globalPos())) + QApplication::clipboard()->setText(link.toString()); +} + +QVariant HelpViewer::loadResource(int type, const QUrl &name) +{ + TRACE_OBJ + QByteArray ba; + if (type < 4) { + ba = HelpEngineWrapper::instance().fileData(name); + if (name.toString().endsWith(QLatin1String(".svg"), Qt::CaseInsensitive)) { + QImage image; + image.loadFromData(ba, "svg"); + if (!image.isNull()) + return image; + } + } + return ba; +} + QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/helpviewer_qwv.cpp b/tools/assistant/tools/assistant/helpviewer_qwv.cpp index 221e1b8..87973c0 100644 --- a/tools/assistant/tools/assistant/helpviewer_qwv.cpp +++ b/tools/assistant/tools/assistant/helpviewer_qwv.cpp @@ -39,25 +39,31 @@ ** ****************************************************************************/ -#include "helpviewer_qwv.h" +#include "helpviewer.h" +#include "helpviewer_p.h" #include "centralwidget.h" #include "helpenginewrapper.h" +#include "openpagesmanager.h" #include "tracer.h" #include <QtCore/QFileInfo> #include <QtCore/QString> -#include <QtCore/QStringBuilder> #include <QtCore/QTimer> +#include <QtGui/QApplication> #include <QtGui/QWheelEvent> +#include <QtHelp/QHelpEngineCore> + #include <QtNetwork/QNetworkAccessManager> #include <QtNetwork/QNetworkReply> #include <QtNetwork/QNetworkRequest> QT_BEGIN_NAMESPACE +// -- HelpNetworkReply + class HelpNetworkReply : public QNetworkReply { public: @@ -109,6 +115,8 @@ qint64 HelpNetworkReply::readData(char *buffer, qint64 maxlen) return len; } +// -- HelpNetworkAccessManager + class HelpNetworkAccessManager : public QNetworkAccessManager { public: @@ -130,15 +138,14 @@ QNetworkReply *HelpNetworkAccessManager::createRequest(Operation /*op*/, { TRACE_OBJ QString url = request.url().toString(); - HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); - + const HelpEngineWrapper &engine = HelpEngineWrapper::instance(); // TODO: For some reason the url to load is already wrong (passed from webkit) // though the css file and the references inside should work that way. One // possible problem might be that the css is loaded at the same level as the // html, thus a path inside the css like (../images/foo.png) might cd out of // the virtual folder - if (!helpEngine.findFile(url).isValid()) { - if (url.startsWith(AbstractHelpViewer::DocPath)) { + if (!engine.findFile(url).isValid()) { + if (url.startsWith(HelpViewer::DocPath)) { QUrl newUrl = request.url(); if (!newUrl.path().startsWith(QLatin1String("/qdoc/"))) { newUrl.setPath(QLatin1String("qdoc") + newUrl.path()); @@ -147,18 +154,20 @@ QNetworkReply *HelpNetworkAccessManager::createRequest(Operation /*op*/, } } - const QString &mimeType = AbstractHelpViewer::mimeFromUrl(url); - const QByteArray &data = helpEngine.findFile(url).isValid() - ? helpEngine.fileData(url) - : AbstractHelpViewer::PageNotFoundMessage.arg(url).toUtf8(); + const QString &mimeType = HelpViewer::mimeFromUrl(url); + const QByteArray &data = engine.findFile(url).isValid() ? engine.fileData(url) + : HelpViewer::PageNotFoundMessage.arg(url).toUtf8(); + return new HelpNetworkReply(request, data, mimeType.isEmpty() ? QLatin1String("application/octet-stream") : mimeType); } +// -- HelpPage + class HelpPage : public QWebPage { public: - HelpPage(CentralWidget *central, QObject *parent); + HelpPage(QObject *parent); protected: virtual QWebPage *createWindow(QWebPage::WebWindowType); @@ -168,7 +177,6 @@ protected: const QNetworkRequest &request, NavigationType type); private: - CentralWidget *centralWidget; bool closeNewTabIfNeeded; friend class HelpViewer; @@ -177,9 +185,8 @@ private: Qt::KeyboardModifiers m_keyboardModifiers; }; -HelpPage::HelpPage(CentralWidget *central, QObject *parent) +HelpPage::HelpPage(QObject *parent) : QWebPage(parent) - , centralWidget(central) , closeNewTabIfNeeded(false) , m_pressedButtons(Qt::NoButton) , m_keyboardModifiers(Qt::NoModifier) @@ -190,9 +197,9 @@ HelpPage::HelpPage(CentralWidget *central, QObject *parent) QWebPage *HelpPage::createWindow(QWebPage::WebWindowType) { TRACE_OBJ - HelpPage* newPage = static_cast<HelpPage*>(centralWidget->newEmptyTab()->page()); - if (newPage) - newPage->closeNewTabIfNeeded = closeNewTabIfNeeded; + HelpPage* newPage = static_cast<HelpPage*>(OpenPagesManager::instance() + ->createPage()->page()); + newPage->closeNewTabIfNeeded = closeNewTabIfNeeded; closeNewTabIfNeeded = false; return newPage; } @@ -217,19 +224,17 @@ bool HelpPage::acceptNavigationRequest(QWebFrame *, closeNewTabIfNeeded = false; const QUrl &url = request.url(); - if (AbstractHelpViewer::launchWithExternalApp(url)) { + if (HelpViewer::launchWithExternalApp(url)) { if (closeNewTab) - QMetaObject::invokeMethod(centralWidget, "closeTab"); + QMetaObject::invokeMethod(OpenPagesManager::instance(), "closeCurrentPage"); return false; } if (type == QWebPage::NavigationTypeLinkClicked - && (m_keyboardModifiers & Qt::ControlModifier - || m_pressedButtons == Qt::MidButton)) { - if (centralWidget->newEmptyTab()) - centralWidget->setSource(url); + && (m_keyboardModifiers & Qt::ControlModifier || m_pressedButtons == Qt::MidButton)) { m_pressedButtons = Qt::NoButton; m_keyboardModifiers = Qt::NoModifier; + OpenPagesManager::instance()->createPage(url); return false; } @@ -243,23 +248,20 @@ bool HelpPage::acceptNavigationRequest(QWebFrame *, // -- HelpViewer -HelpViewer::HelpViewer(CentralWidget *parent, qreal zoom) +HelpViewer::HelpViewer(qreal zoom, QWidget *parent) : QWebView(parent) - , parentWidget(parent) - , loadFinished(false) - , helpEngine(HelpEngineWrapper::instance()) + , d(new HelpViewerPrivate) { TRACE_OBJ setAcceptDrops(false); + settings()->setAttribute(QWebSettings::JavaEnabled, false); + settings()->setAttribute(QWebSettings::PluginsEnabled, false); - setPage(new HelpPage(parent, this)); - + setPage(new HelpPage(this)); page()->setNetworkAccessManager(new HelpNetworkAccessManager(this)); QAction* action = pageAction(QWebPage::OpenLinkInNewWindow); - action->setText(tr("Open Link in New Tab")); - if (!parent) - action->setVisible(false); + action->setText(tr("Open Link in New Page")); pageAction(QWebPage::DownloadLinkToDisk)->setVisible(false); pageAction(QWebPage::DownloadImageToDisk)->setVisible(false); @@ -271,27 +273,23 @@ HelpViewer::HelpViewer(CentralWidget *parent, qreal zoom) SLOT(actionChanged())); connect(pageAction(QWebPage::Forward), SIGNAL(changed()), this, SLOT(actionChanged())); - connect(page(), SIGNAL(linkHovered(QString,QString,QString)), this, + connect(page(), SIGNAL(linkHovered(QString, QString, QString)), this, SIGNAL(highlighted(QString))); connect(this, SIGNAL(urlChanged(QUrl)), this, SIGNAL(sourceChanged(QUrl))); connect(this, SIGNAL(loadStarted()), this, SLOT(setLoadStarted())); connect(this, SIGNAL(loadFinished(bool)), this, SLOT(setLoadFinished(bool))); + connect(this, SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged())); connect(page(), SIGNAL(printRequested(QWebFrame*)), this, SIGNAL(printRequested())); setFont(viewerFont()); setTextSizeMultiplier(zoom == 0.0 ? 1.0 : zoom); } -HelpViewer::~HelpViewer() -{ - TRACE_OBJ -} - QFont HelpViewer::viewerFont() const { TRACE_OBJ - if (helpEngine.usesBrowserFont()) - return helpEngine.browserFont(); + if (HelpEngineWrapper::instance().usesBrowserFont()) + return HelpEngineWrapper::instance().browserFont(); QWebSettings *webSettings = QWebSettings::globalSettings(); return QFont(webSettings->fontFamily(QWebSettings::StandardFont), @@ -324,26 +322,29 @@ void HelpViewer::resetScale() setTextSizeMultiplier(1.0); } -bool HelpViewer::handleForwardBackwardMouseButtons(QMouseEvent *e) +qreal HelpViewer::scale() const { TRACE_OBJ - if (e->button() == Qt::XButton1) { - triggerPageAction(QWebPage::Back); - return true; - } + return textSizeMultiplier(); +} - if (e->button() == Qt::XButton2) { - triggerPageAction(QWebPage::Forward); - return true; - } +QString HelpViewer::title() const +{ + TRACE_OBJ + return QWebView::title(); +} - return false; +void HelpViewer::setTitle(const QString &title) +{ + TRACE_OBJ + Q_UNUSED(title) } QUrl HelpViewer::source() const { + TRACE_OBJ HelpPage *currentPage = static_cast<HelpPage*> (page()); - if (currentPage && !hasLoadFinished()) { + if (currentPage && !d->m_loadFinished) { // see HelpPage::acceptNavigationRequest(...) return currentPage->m_loadingUrl; } @@ -356,44 +357,84 @@ void HelpViewer::setSource(const QUrl &url) load(url.toString() == QLatin1String("help") ? LocalHelpFile : url); } -void HelpViewer::home() +QString HelpViewer::selectedText() const { TRACE_OBJ - setSource(helpEngine.homePage()); + return QWebView::selectedText(); } -void HelpViewer::wheelEvent(QWheelEvent *e) +bool HelpViewer::isForwardAvailable() const { TRACE_OBJ - if (e->modifiers()& Qt::ControlModifier) { - e->accept(); - e->delta() > 0 ? scaleUp() : scaleDown(); - } else { - QWebView::wheelEvent(e); - } + return pageAction(QWebPage::Forward)->isEnabled(); } -void HelpViewer::mouseReleaseEvent(QMouseEvent *e) +bool HelpViewer::isBackwardAvailable() const { TRACE_OBJ -#ifndef Q_OS_LINUX - if (handleForwardBackwardMouseButtons(e)) - return; -#endif + return pageAction(QWebPage::Back)->isEnabled(); +} - QWebView::mouseReleaseEvent(e); +bool HelpViewer::findText(const QString &text, FindFlags flags, bool incremental, + bool fromSearch) +{ + TRACE_OBJ + Q_UNUSED((incremental && fromSearch)) + QWebPage::FindFlags options = QWebPage::FindWrapsAroundDocument; + if (flags & FindBackward) + options |= QWebPage::FindBackward; + if (flags & FindCaseSensitively) + options |= QWebPage::FindCaseSensitively; + + bool found = QWebView::findText(text, options); + options = QWebPage::HighlightAllOccurrences; + QWebView::findText(QLatin1String(""), options); // clear first + QWebView::findText(text, options); // force highlighting of all other matches + return found; } -void HelpViewer::actionChanged() +// -- public slots + +void HelpViewer::copy() { TRACE_OBJ - QAction *a = qobject_cast<QAction *>(sender()); - if (a == pageAction(QWebPage::Copy)) - emit copyAvailable(a->isEnabled()); - else if (a == pageAction(QWebPage::Back)) - emit backwardAvailable(a->isEnabled()); - else if (a == pageAction(QWebPage::Forward)) - emit forwardAvailable(a->isEnabled()); + triggerPageAction(QWebPage::Copy); +} + +void HelpViewer::forward() +{ + TRACE_OBJ + QWebView::forward(); +} + +void HelpViewer::backward() +{ + TRACE_OBJ + back(); +} + +// -- protected + +void HelpViewer::keyPressEvent(QKeyEvent *e) +{ + TRACE_OBJ + // TODO: remove this once we support multiple keysequences per command + if (e->key() == Qt::Key_Insert && e->modifiers() == Qt::CTRL) { + if (!selectedText().isEmpty()) + copy(); + } + QWebView::keyPressEvent(e); +} + +void HelpViewer::wheelEvent(QWheelEvent *event) +{ + TRACE_OBJ + if (event->modifiers()& Qt::ControlModifier) { + event->accept(); + event->delta() > 0 ? scaleUp() : scaleDown(); + } else { + QWebView::wheelEvent(event); + } } void HelpViewer::mousePressEvent(QMouseEvent *event) @@ -404,24 +445,51 @@ void HelpViewer::mousePressEvent(QMouseEvent *event) return; #endif - HelpPage *currentPage = static_cast<HelpPage*>(page()); - if (currentPage) { + if (HelpPage *currentPage = static_cast<HelpPage*> (page())) { currentPage->m_pressedButtons = event->buttons(); currentPage->m_keyboardModifiers = event->modifiers(); } + QWebView::mousePressEvent(event); } -void HelpViewer::setLoadStarted() +void HelpViewer::mouseReleaseEvent(QMouseEvent *event) { - loadFinished = false; + TRACE_OBJ +#ifndef Q_OS_LINUX + if (handleForwardBackwardMouseButtons(event)) + return; +#endif + + QWebView::mouseReleaseEvent(event); +} + +// -- private slots + +void HelpViewer::actionChanged() +{ + TRACE_OBJ + QAction *a = qobject_cast<QAction *>(sender()); + if (a == pageAction(QWebPage::Copy)) + emit copyAvailable(a->isEnabled()); + else if (a == pageAction(QWebPage::Back)) + emit backwardAvailable(a->isEnabled()); + else if (a == pageAction(QWebPage::Forward)) + emit forwardAvailable(a->isEnabled()); +} + +// -- private + +bool HelpViewer::eventFilter(QObject *obj, QEvent *event) +{ + TRACE_OBJ + return QWebView::eventFilter(obj, event); } -void HelpViewer::setLoadFinished(bool ok) +void HelpViewer::contextMenuEvent(QContextMenuEvent *event) { TRACE_OBJ - loadFinished = ok; - emit sourceChanged(url()); + QWebView::contextMenuEvent(event); } QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/helpviewer_qwv.h b/tools/assistant/tools/assistant/helpviewer_qwv.h deleted file mode 100644 index d4a27a2..0000000 --- a/tools/assistant/tools/assistant/helpviewer_qwv.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the Qt Assistant of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef HELPVIEWERQWV_H -#define HELPVIEWERQWV_H - -#include "helpviewer.h" - -#include <QtGui/QAction> -#include <QtWebKit/QWebView> - -QT_BEGIN_NAMESPACE - -class CentralWidget; -class HelpEngineWrapper; -class QMouseEvent; - -class HelpViewer : public QWebView, public AbstractHelpViewer -{ - Q_OBJECT - -public: - explicit HelpViewer(CentralWidget *parent, qreal zoom = 0.0); - ~HelpViewer(); - - QFont viewerFont() const; - void setViewerFont(const QFont &font); - - void scaleUp(); - void scaleDown(); - void resetScale(); - qreal scale() const { return textSizeMultiplier(); } - - bool handleForwardBackwardMouseButtons(QMouseEvent *e); - - QUrl source() const; - void setSource(const QUrl &url); - - inline QString documentTitle() const - { return title(); } - - inline bool hasSelection() const - { return !selectedText().isEmpty(); } // ### this is suboptimal - - inline void copy() - { return triggerPageAction(QWebPage::Copy); } - - inline bool isForwardAvailable() const - { return pageAction(QWebPage::Forward)->isEnabled(); } - inline bool isBackwardAvailable() const - { return pageAction(QWebPage::Back)->isEnabled(); } - inline bool hasLoadFinished() const - { return loadFinished; } - -public Q_SLOTS: - void home(); - void backward() { back(); } - -Q_SIGNALS: - void copyAvailable(bool enabled); - void forwardAvailable(bool enabled); - void backwardAvailable(bool enabled); - void highlighted(const QString &); - void sourceChanged(const QUrl &); - void printRequested(); - -protected: - virtual void wheelEvent(QWheelEvent *); - void mouseReleaseEvent(QMouseEvent *e); - void mousePressEvent(QMouseEvent *event); - -private Q_SLOTS: - void actionChanged(); - void setLoadStarted(); - void setLoadFinished(bool ok); - -private: - CentralWidget* parentWidget; - bool loadFinished; - HelpEngineWrapper &helpEngine; -}; - -QT_END_NAMESPACE - -#endif // HELPVIEWERQWV_H diff --git a/tools/assistant/tools/assistant/images/closebutton.png b/tools/assistant/tools/assistant/images/closebutton.png Binary files differnew file mode 100644 index 0000000..c978cf5 --- /dev/null +++ b/tools/assistant/tools/assistant/images/closebutton.png diff --git a/tools/assistant/tools/assistant/images/darkclosebutton.png b/tools/assistant/tools/assistant/images/darkclosebutton.png Binary files differnew file mode 100644 index 0000000..1077663 --- /dev/null +++ b/tools/assistant/tools/assistant/images/darkclosebutton.png diff --git a/tools/assistant/tools/assistant/indexwindow.cpp b/tools/assistant/tools/assistant/indexwindow.cpp index 63ddbe4..00f61f2 100644 --- a/tools/assistant/tools/assistant/indexwindow.cpp +++ b/tools/assistant/tools/assistant/indexwindow.cpp @@ -38,13 +38,15 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "tracer.h" #include "indexwindow.h" + #include "centralwidget.h" #include "helpenginewrapper.h" #include "helpviewer.h" +#include "openpagesmanager.h" #include "topicchooser.h" +#include "tracer.h" #include <QtGui/QLayout> #include <QtGui/QLabel> @@ -219,10 +221,10 @@ void IndexWindow::open(QHelpIndexWidget* indexWidget, const QModelIndex &index) return; } - if (!AbstractHelpViewer::canOpenPage(url.path())) + if (!HelpViewer::canOpenPage(url.path())) CentralWidget::instance()->setSource(url); else - CentralWidget::instance()->setSourceInNewTab(url); + OpenPagesManager::instance()->createPage(url); } } diff --git a/tools/assistant/tools/assistant/mainwindow.cpp b/tools/assistant/tools/assistant/mainwindow.cpp index 65a58c0..537f867 100644 --- a/tools/assistant/tools/assistant/mainwindow.cpp +++ b/tools/assistant/tools/assistant/mainwindow.cpp @@ -38,57 +38,58 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "tracer.h" #include "mainwindow.h" +#include "aboutdialog.h" #include "bookmarkmanager.h" #include "centralwidget.h" -#include "indexwindow.h" -#include "topicchooser.h" +#include "cmdlineparser.h" #include "contentwindow.h" -#include "preferencesdialog.h" +#include "globalactions.h" #include "helpenginewrapper.h" +#include "indexwindow.h" +#include "openpagesmanager.h" +#include "preferencesdialog.h" +#include "qtdocinstaller.h" #include "remotecontrol.h" -#include "cmdlineparser.h" -#include "aboutdialog.h" #include "searchwidget.h" -#include "qtdocinstaller.h" - -// #define TRACING_REQUESTED +#include "topicchooser.h" +#include "tracer.h" -#include <QtCore/QDir> -#include <QtCore/QTimer> +#include <QtCore/QByteArray> #include <QtCore/QDateTime> #include <QtCore/QDebug> -#include <QtCore/QFileSystemWatcher> +#include <QtCore/QDir> #include <QtCore/QPair> #include <QtCore/QResource> -#include <QtCore/QByteArray> #include <QtCore/QTextStream> -#include <QtCore/QCoreApplication> +#include <QtCore/QTimer> -#include <QtGui/QMenuBar> #include <QtGui/QAction> -#include <QtGui/QToolBar> -#include <QtGui/QStatusBar> +#include <QtGui/QComboBox> +#include <QtGui/QDesktopServices> +#include <QtGui/QDesktopWidget> +#include <QtGui/QDockWidget> +#include <QtGui/QFontDatabase> +#include <QtGui/QFileDialog> #include <QtGui/QLabel> -#include <QtGui/QLineEdit> #include <QtGui/QLayout> -#include <QtGui/QDockWidget> -#include <QtGui/QTreeView> +#include <QtGui/QLineEdit> +#include <QtGui/QMenuBar> #include <QtGui/QMessageBox> -#include <QtGui/QFontDatabase> -#include <QtGui/QComboBox> #include <QtGui/QProgressBar> -#include <QtGui/QDesktopServices> +#include <QtGui/QShortcut> +#include <QtGui/QStatusBar> +#include <QtGui/QToolBar> #include <QtGui/QToolButton> -#include <QtGui/QFileDialog> -#include <QtHelp/QHelpEngineCore> -#include <QtHelp/QHelpSearchEngine> #include <QtHelp/QHelpContentModel> +#include <QtHelp/QHelpEngineCore> #include <QtHelp/QHelpIndexModel> +#include <QtHelp/QHelpSearchEngine> + +#include <cstdlib> QT_BEGIN_NAMESPACE @@ -105,6 +106,7 @@ MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) TRACE_OBJ setToolButtonStyle(Qt::ToolButtonFollowStyle); + setDockOptions(ForceTabbedDocks); // Has no effect; Qt bug? QString collectionFile; if (usesDefaultCollection()) { @@ -115,6 +117,14 @@ MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) } HelpEngineWrapper &helpEngineWrapper = HelpEngineWrapper::instance(collectionFile); + BookmarkManager *bookMarkManager = BookmarkManager::instance(); + + if (!initHelpDB()) { + qDebug("Fatal error: Help engine initialization failed. " + "Error message was: %s\nAssistant will now exit.", + qPrintable(HelpEngineWrapper::instance().error())); + std::exit(1); + } m_centralWidget = new CentralWidget(this); setCentralWidget(m_centralWidget); @@ -131,132 +141,154 @@ MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) contentDock->setWidget(m_contentWindow); addDockWidget(Qt::LeftDockWidgetArea, contentDock); - QDockWidget *bookmarkDock = 0; - if (BookmarkManager *manager = BookmarkManager::instance()) { - bookmarkDock = new QDockWidget(tr("Bookmarks"), this); - bookmarkDock->setObjectName(QLatin1String("BookmarkWindow")); - bookmarkDock->setWidget(m_bookmarkWidget = manager->bookmarkDockWidget()); - addDockWidget(Qt::LeftDockWidgetArea, bookmarkDock); - - connect(manager, SIGNAL(escapePressed()), this, + m_searchWindow = new SearchWidget(helpEngineWrapper.searchEngine()); + m_searchWindow->setFont(!helpEngineWrapper.usesBrowserFont() ? qApp->font() + : helpEngineWrapper.browserFont()); + QDockWidget *searchDock = new QDockWidget(tr("Search"), this); + searchDock->setObjectName(QLatin1String("SearchWindow")); + searchDock->setWidget(m_searchWindow); + addDockWidget(Qt::LeftDockWidgetArea, searchDock); + + QDockWidget *bookmarkDock = new QDockWidget(tr("Bookmarks"), this); + bookmarkDock->setObjectName(QLatin1String("BookmarkWindow")); + bookmarkDock->setWidget(m_bookmarkWidget + = bookMarkManager->bookmarkDockWidget()); + addDockWidget(Qt::LeftDockWidgetArea, bookmarkDock); + + QDockWidget *openPagesDock = new QDockWidget(tr("Open Pages"), this); + openPagesDock->setObjectName(QLatin1String("Open Pages")); + OpenPagesManager *openPagesManager + = OpenPagesManager::createInstance(this, usesDefaultCollection(), m_cmdLine->url()); + openPagesDock->setWidget(openPagesManager->openPagesWidget()); + addDockWidget(Qt::LeftDockWidgetArea, openPagesDock); + + connect(m_centralWidget, SIGNAL(addBookmark(QString, QString)), + bookMarkManager, SLOT(addBookmark(QString, QString))); + connect(bookMarkManager, SIGNAL(escapePressed()), this, SLOT(activateCurrentCentralWidgetTab())); - connect(manager, SIGNAL(setSource(QUrl)), m_centralWidget, + connect(bookMarkManager, SIGNAL(setSource(QUrl)), m_centralWidget, SLOT(setSource(QUrl))); - connect(manager, SIGNAL(setSourceInNewTab(QUrl)), m_centralWidget, - SLOT(setSourceInNewTab(QUrl))); - connect(m_centralWidget, SIGNAL(addBookmark(QString, QString)), manager, - SLOT(addBookmark(QString, QString))); - } + connect(bookMarkManager, SIGNAL(setSourceInNewTab(QUrl)), + openPagesManager, SLOT(createPage(QUrl))); QHelpSearchEngine *searchEngine = helpEngineWrapper.searchEngine(); connect(searchEngine, SIGNAL(indexingStarted()), this, SLOT(indexingStarted())); connect(searchEngine, SIGNAL(indexingFinished()), this, SLOT(indexingFinished())); - m_centralWidget->createSearchWidget(searchEngine); - m_centralWidget->activateSearchWidget(); - QString defWindowTitle = tr("Qt Assistant"); setWindowTitle(defWindowTitle); setupActions(); statusBar()->show(); + m_centralWidget->connectTabBar(); - if (initHelpDB()) { - setupFilterToolbar(); - setupAddressToolbar(); - - const QString windowTitle = helpEngineWrapper.windowTitle(); - setWindowTitle(windowTitle.isEmpty() ? defWindowTitle : windowTitle); - QByteArray iconArray = helpEngineWrapper.applicationIcon(); - if (iconArray.size() > 0) { - QPixmap pix; - pix.loadFromData(iconArray); - QIcon appIcon(pix); - qApp->setWindowIcon(appIcon); - } else { - QIcon appIcon(QLatin1String(":/trolltech/assistant/images/assistant-128.png")); - qApp->setWindowIcon(appIcon); - } + setupFilterToolbar(); + setupAddressToolbar(); - // Show the widget here, otherwise the restore geometry and state won't work - // on x11. - show(); - QByteArray ba(helpEngineWrapper.mainWindow()); - if (!ba.isEmpty()) - restoreState(ba); - - ba = helpEngineWrapper.mainWindowGeometry(); - if (!ba.isEmpty()) { - restoreGeometry(ba); - } else { - tabifyDockWidget(contentDock, indexDock); - if (bookmarkDock) - tabifyDockWidget(indexDock, bookmarkDock); - contentDock->raise(); - resize(QSize(800, 600)); - } + const QString windowTitle = helpEngineWrapper.windowTitle(); + setWindowTitle(windowTitle.isEmpty() ? defWindowTitle : windowTitle); + QByteArray iconArray = helpEngineWrapper.applicationIcon(); + if (iconArray.size() > 0) { + QPixmap pix; + pix.loadFromData(iconArray); + QIcon appIcon(pix); + qApp->setWindowIcon(appIcon); + } else { + QIcon appIcon(QLatin1String(":/trolltech/assistant/images/assistant-128.png")); + qApp->setWindowIcon(appIcon); + } - if (!helpEngineWrapper.hasFontSettings()) { - helpEngineWrapper.setUseAppFont(false); - helpEngineWrapper.setUseBrowserFont(false); - helpEngineWrapper.setAppFont(qApp->font()); - helpEngineWrapper.setAppWritingSystem(QFontDatabase::Latin); - helpEngineWrapper.setBrowserFont(qApp->font()); - helpEngineWrapper.setBrowserWritingSystem(QFontDatabase::Latin); - } else { - updateApplicationFont(); - } + QToolBar *toolBar = addToolBar(tr("Bookmark Toolbar")); + bookMarkManager->setBookmarksToolbar(toolBar); - updateAboutMenuText(); - - QTimer::singleShot(0, this, SLOT(insertLastPages())); - if (m_cmdLine->enableRemoteControl()) - (void)new RemoteControl(this); - - if (m_cmdLine->contents() == CmdLineParser::Show) - showContents(); - else if (m_cmdLine->contents() == CmdLineParser::Hide) - hideContents(); - - if (m_cmdLine->index() == CmdLineParser::Show) - showIndex(); - else if (m_cmdLine->index() == CmdLineParser::Hide) - hideIndex(); - - if (m_cmdLine->bookmarks() == CmdLineParser::Show) - showBookmarksDockWidget(); - else if (m_cmdLine->bookmarks() == CmdLineParser::Hide) - hideBookmarksDockWidget(); - - if (m_cmdLine->search() == CmdLineParser::Show) - showSearch(); - else if (m_cmdLine->search() == CmdLineParser::Hide) - hideSearch(); - - if (m_cmdLine->contents() == CmdLineParser::Activate) - showContents(); - else if (m_cmdLine->index() == CmdLineParser::Activate) - showIndex(); - else if (m_cmdLine->bookmarks() == CmdLineParser::Activate) - showBookmarksDockWidget(); - - if (!m_cmdLine->currentFilter().isEmpty()) { - const QString &curFilter = m_cmdLine->currentFilter(); - if (helpEngineWrapper.customFilters().contains(curFilter)) - helpEngineWrapper.setCurrentFilter(curFilter); - } + // Show the widget here, otherwise the restore geometry and state won't work + // on x11. + show(); - if (usesDefaultCollection()) - QTimer::singleShot(0, this, SLOT(lookForNewQtDocumentation())); - else - checkInitState(); + toolBar->hide(); + toolBarMenu()->addAction(toolBar->toggleViewAction()); + + QByteArray ba(helpEngineWrapper.mainWindow()); + if (!ba.isEmpty()) + restoreState(ba); + + ba = helpEngineWrapper.mainWindowGeometry(); + if (!ba.isEmpty()) { + restoreGeometry(ba); + } else { + tabifyDockWidget(contentDock, indexDock); + tabifyDockWidget(indexDock, bookmarkDock); + tabifyDockWidget(bookmarkDock, openPagesDock); + tabifyDockWidget(openPagesDock, searchDock); + contentDock->raise(); + const QRect screen = QApplication::desktop()->screenGeometry(); + resize(4*screen.width()/5, 4*screen.height()/5); + } - connect(&helpEngineWrapper, SIGNAL(documentationRemoved(QString)), - this, SLOT(documentationRemoved(QString))); - connect(&helpEngineWrapper, SIGNAL(documentationUpdated(QString)), - this, SLOT(documentationUpdated(QString))); + if (!helpEngineWrapper.hasFontSettings()) { + helpEngineWrapper.setUseAppFont(false); + helpEngineWrapper.setUseBrowserFont(false); + helpEngineWrapper.setAppFont(qApp->font()); + helpEngineWrapper.setAppWritingSystem(QFontDatabase::Latin); + helpEngineWrapper.setBrowserFont(qApp->font()); + helpEngineWrapper.setBrowserWritingSystem(QFontDatabase::Latin); + } else { + updateApplicationFont(); } + + updateAboutMenuText(); + + QTimer::singleShot(0, this, SLOT(insertLastPages())); + if (m_cmdLine->enableRemoteControl()) + (void)new RemoteControl(this); + + if (m_cmdLine->contents() == CmdLineParser::Show) + showContents(); + else if (m_cmdLine->contents() == CmdLineParser::Hide) + hideContents(); + + if (m_cmdLine->index() == CmdLineParser::Show) + showIndex(); + else if (m_cmdLine->index() == CmdLineParser::Hide) + hideIndex(); + + if (m_cmdLine->bookmarks() == CmdLineParser::Show) + showBookmarksDockWidget(); + else if (m_cmdLine->bookmarks() == CmdLineParser::Hide) + hideBookmarksDockWidget(); + + if (m_cmdLine->search() == CmdLineParser::Show) + showSearch(); + else if (m_cmdLine->search() == CmdLineParser::Hide) + hideSearch(); + + if (m_cmdLine->contents() == CmdLineParser::Activate) + showContents(); + else if (m_cmdLine->index() == CmdLineParser::Activate) + showIndex(); + else if (m_cmdLine->bookmarks() == CmdLineParser::Activate) + showBookmarksDockWidget(); + + if (!m_cmdLine->currentFilter().isEmpty()) { + const QString &curFilter = m_cmdLine->currentFilter(); + if (helpEngineWrapper.customFilters().contains(curFilter)) + helpEngineWrapper.setCurrentFilter(curFilter); + } + + if (usesDefaultCollection()) + QTimer::singleShot(0, this, SLOT(lookForNewQtDocumentation())); + else + checkInitState(); + + connect(&helpEngineWrapper, SIGNAL(documentationRemoved(QString)), + this, SLOT(documentationRemoved(QString))); + connect(&helpEngineWrapper, SIGNAL(documentationUpdated(QString)), + this, SLOT(documentationUpdated(QString))); + setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North); + GlobalActions::instance()->updateActions(); + if (helpEngineWrapper.addressBarEnabled()) + showNewAddress(); } MainWindow::~MainWindow() @@ -387,11 +419,6 @@ void MainWindow::checkInitState() void MainWindow::insertLastPages() { TRACE_OBJ - if (m_cmdLine->url().isValid()) - m_centralWidget->setSource(m_cmdLine->url()); - else - m_centralWidget->setupWidget(); - if (m_cmdLine->search() == CmdLineParser::Activate) showSearch(); } @@ -409,8 +436,13 @@ void MainWindow::setupActions() QMenu *menu = menuBar()->addMenu(tr("&File")); - m_newTabAction = menu->addAction(tr("New &Tab"), m_centralWidget, SLOT(newTab())); + OpenPagesManager * const openPages = OpenPagesManager::instance(); + m_newTabAction + = menu->addAction(tr("New &Tab"), openPages, SLOT(createPage())); m_newTabAction->setShortcut(QKeySequence::AddTab); + m_closeTabAction = menu->addAction(tr("&Close Tab"), + openPages, SLOT(closeCurrentPage())); + m_closeTabAction->setShortcuts(QKeySequence::Close); menu->addSeparator(); @@ -419,17 +451,10 @@ void MainWindow::setupActions() m_printPreviewAction = menu->addAction(tr("Print Preview..."), m_centralWidget, SLOT(printPreview())); - m_printAction = menu->addAction(tr("&Print..."), m_centralWidget, SLOT(print())); - m_printAction->setPriority(QAction::LowPriority); - m_printAction->setIcon(QIcon(resourcePath + QLatin1String("/print.png"))); - m_printAction->setShortcut(QKeySequence::Print); - + GlobalActions *globalActions = GlobalActions::instance(this); + menu->addAction(globalActions->printAction()); menu->addSeparator(); - m_closeTabAction = menu->addAction(tr("&Close Tab"), m_centralWidget, - SLOT(closeTab())); - m_closeTabAction->setShortcuts(QKeySequence::Close); - QAction *tmp = menu->addAction(QIcon::fromTheme("application-exit"), tr("&Quit"), this, SLOT(close())); tmp->setMenuRole(QAction::QuitRole); @@ -440,19 +465,8 @@ void MainWindow::setupActions() #endif menu = menuBar()->addMenu(tr("&Edit")); - m_copyAction = menu->addAction(tr("&Copy selected Text"), m_centralWidget, - SLOT(copySelection())); - m_copyAction->setPriority(QAction::LowPriority); - m_copyAction->setIconText("&Copy"); - m_copyAction->setIcon(QIcon(resourcePath + QLatin1String("/editcopy.png"))); - m_copyAction->setShortcuts(QKeySequence::Copy); - m_copyAction->setEnabled(false); - - m_findAction = menu->addAction(tr("&Find in Text..."), m_centralWidget, - SLOT(showTextSearch())); - m_findAction->setIconText(tr("&Find")); - m_findAction->setIcon(QIcon(resourcePath + QLatin1String("/find.png"))); - m_findAction->setShortcuts(QKeySequence::Find); + menu->addAction(globalActions->copyAction()); + menu->addAction(globalActions->findAction()); QAction *findNextAction = menu->addAction(tr("Find &Next"), m_centralWidget, SLOT(findNext())); @@ -467,17 +481,8 @@ void MainWindow::setupActions() tmp->setMenuRole(QAction::PreferencesRole); m_viewMenu = menuBar()->addMenu(tr("&View")); - m_zoomInAction = m_viewMenu->addAction(tr("Zoom &in"), m_centralWidget, - SLOT(zoomIn())); - m_zoomInAction->setPriority(QAction::LowPriority); - m_zoomInAction->setIcon(QIcon(resourcePath + QLatin1String("/zoomin.png"))); - m_zoomInAction->setShortcut(QKeySequence::ZoomIn); - - m_zoomOutAction = m_viewMenu->addAction(tr("Zoom &out"), m_centralWidget, - SLOT(zoomOut())); - m_zoomOutAction->setPriority(QAction::LowPriority); - m_zoomOutAction->setIcon(QIcon(resourcePath + QLatin1String("/zoomout.png"))); - m_zoomOutAction->setShortcut(QKeySequence::ZoomOut); + m_viewMenu->addAction(globalActions->zoomInAction()); + m_viewMenu->addAction(globalActions->zoomOutAction()); m_resetZoomAction = m_viewMenu->addAction(tr("Normal &Size"), m_centralWidget, SLOT(resetZoom())); @@ -493,24 +498,15 @@ void MainWindow::setupActions() QKeySequence(tr("ALT+I"))); m_viewMenu->addAction(tr("Bookmarks"), this, SLOT(showBookmarksDockWidget()), QKeySequence(tr("ALT+O"))); - m_viewMenu->addAction(tr("Search"), this, SLOT(showSearchWidget()), + m_viewMenu->addAction(tr("Search"), this, SLOT(showSearch()), QKeySequence(tr("ALT+S"))); + m_viewMenu->addAction(tr("Open Pages"), this, SLOT(showOpenPages()), + QKeySequence(tr("ALT+P"))); menu = menuBar()->addMenu(tr("&Go")); - m_homeAction = menu->addAction(tr("&Home"), m_centralWidget, SLOT(home())); - m_homeAction->setShortcut(tr("ALT+Home")); - m_homeAction->setIcon(QIcon(resourcePath + QLatin1String("/home.png"))); - - m_backAction = menu->addAction(tr("&Back"), m_centralWidget, SLOT(backward())); - m_backAction->setEnabled(false); - m_backAction->setShortcuts(QKeySequence::Back); - m_backAction->setIcon(QIcon(resourcePath + QLatin1String("/previous.png"))); - - m_nextAction = menu->addAction(tr("&Forward"), m_centralWidget, SLOT(forward())); - m_nextAction->setPriority(QAction::LowPriority); - m_nextAction->setEnabled(false); - m_nextAction->setShortcuts(QKeySequence::Forward); - m_nextAction->setIcon(QIcon(resourcePath + QLatin1String("/next.png"))); + menu->addAction(globalActions->homeAction()); + menu->addAction(globalActions->backAction()); + menu->addAction(globalActions->nextAction()); m_syncAction = menu->addAction(tr("Sync with Table of Contents"), this, SLOT(syncContents())); @@ -519,60 +515,52 @@ void MainWindow::setupActions() menu->addSeparator(); - tmp = menu->addAction(tr("Next Page"), m_centralWidget, SLOT(nextPage())); + tmp = menu->addAction(tr("Next Page"), openPages, SLOT(nextPage())); tmp->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Ctrl+Alt+Right")) << QKeySequence(Qt::CTRL + Qt::Key_PageDown)); - tmp = menu->addAction(tr("Previous Page"), m_centralWidget, SLOT(previousPage())); + tmp = menu->addAction(tr("Previous Page"), openPages, SLOT(previousPage())); tmp->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Ctrl+Alt+Left")) << QKeySequence(Qt::CTRL + Qt::Key_PageUp)); - if (BookmarkManager *manager = BookmarkManager::instance()) - manager->takeBookmarksMenu(menuBar()->addMenu(tr("&Bookmarks"))); +#ifdef Q_WS_MAC + QShortcut *sct = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_Tab), this); + connect(sct, SIGNAL(activated()), openPages, SLOT(nextPageWithSwitcher())); + sct = new QShortcut(QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_Tab), this); + connect(sct, SIGNAL(activated()), openPages, SLOT(previousPageWithSwitcher())); +#else + QShortcut *sct = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Tab), this); + connect(sct, SIGNAL(activated()), openPages, SLOT(nextPageWithSwitcher())); + sct = new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Tab), this); + connect(sct, SIGNAL(activated()), openPages, SLOT(previousPageWithSwitcher())); +#endif + + BookmarkManager::instance()->setBookmarksMenu(menuBar()->addMenu(tr("&Bookmarks"))); menu = menuBar()->addMenu(tr("&Help")); m_aboutAction = menu->addAction(tr("About..."), this, SLOT(showAboutDialog())); m_aboutAction->setMenuRole(QAction::AboutRole); #ifdef Q_WS_X11 - m_newTabAction->setIcon(QIcon::fromTheme("tab-new", m_newTabAction->icon())); - m_closeTabAction->setIcon(QIcon::fromTheme("window-close", m_closeTabAction->icon())); - m_backAction->setIcon(QIcon::fromTheme("go-previous" , m_backAction->icon())); - m_nextAction->setIcon(QIcon::fromTheme("go-next" , m_nextAction->icon())); - m_zoomInAction->setIcon(QIcon::fromTheme("zoom-in" , m_zoomInAction->icon())); - m_zoomOutAction->setIcon(QIcon::fromTheme("zoom-out" , m_zoomOutAction->icon())); m_resetZoomAction->setIcon(QIcon::fromTheme("zoom-original" , m_resetZoomAction->icon())); m_syncAction->setIcon(QIcon::fromTheme("view-refresh" , m_syncAction->icon())); - m_copyAction->setIcon(QIcon::fromTheme("edit-copy" , m_copyAction->icon())); - m_findAction->setIcon(QIcon::fromTheme("edit-find" , m_findAction->icon())); - m_homeAction->setIcon(QIcon::fromTheme("go-home" , m_homeAction->icon())); - m_pageSetupAction->setIcon(QIcon::fromTheme("document-page-setup", m_pageSetupAction->icon())); - m_printPreviewAction->setIcon(QIcon::fromTheme("document-print-preview", m_printPreviewAction->icon())); - m_printAction->setIcon(QIcon::fromTheme("document-print" , m_printAction->icon())); - m_aboutAction->setIcon(QIcon::fromTheme("help-about", m_aboutAction->icon())); #endif QToolBar *navigationBar = addToolBar(tr("Navigation Toolbar")); navigationBar->setObjectName(QLatin1String("NavigationToolBar")); - navigationBar->addAction(m_backAction); - navigationBar->addAction(m_nextAction); - navigationBar->addAction(m_homeAction); + navigationBar->addAction(globalActions->backAction()); + navigationBar->addAction(globalActions->nextAction()); + navigationBar->addAction(globalActions->homeAction()); navigationBar->addAction(m_syncAction); - QAction *sep = navigationBar->addSeparator(); - navigationBar->addAction(m_copyAction); - navigationBar->addAction(m_printAction); - navigationBar->addAction(m_findAction); - QAction *sep2 = navigationBar->addSeparator(); - navigationBar->addAction(m_zoomInAction); - navigationBar->addAction(m_zoomOutAction); + navigationBar->addSeparator(); + navigationBar->addAction(globalActions->copyAction()); + navigationBar->addAction(globalActions->printAction()); + navigationBar->addAction(globalActions->findAction()); + navigationBar->addSeparator(); + navigationBar->addAction(globalActions->zoomInAction()); + navigationBar->addAction(globalActions->zoomOutAction()); navigationBar->addAction(m_resetZoomAction); - QList<QAction*> actionList; - actionList << m_backAction << m_nextAction << m_homeAction << sep - << m_zoomInAction << m_zoomOutAction << sep2 << m_copyAction - << m_printAction << m_findAction; - m_centralWidget->setGlobalActions(actionList); - #if defined(Q_WS_MAC) QMenu *windowMenu = new QMenu(tr("&Window"), this); menuBar()->insertMenu(menu->menuAction(), windowMenu); @@ -582,16 +570,14 @@ void MainWindow::setupActions() #endif // content viewer connections - connect(m_centralWidget, SIGNAL(copyAvailable(bool)), this, - SLOT(copyAvailable(bool))); - connect(m_centralWidget, SIGNAL(currentViewerChanged()), this, - SLOT(updateNavigationItems())); - connect(m_centralWidget, SIGNAL(currentViewerChanged()), this, - SLOT(updateTabCloseAction())); - connect(m_centralWidget, SIGNAL(forwardAvailable(bool)), this, - SLOT(updateNavigationItems())); - connect(m_centralWidget, SIGNAL(backwardAvailable(bool)), this, - SLOT(updateNavigationItems())); + connect(m_centralWidget, SIGNAL(copyAvailable(bool)), globalActions, + SLOT(setCopyAvailable(bool))); + connect(m_centralWidget, SIGNAL(currentViewerChanged()), globalActions, + SLOT(updateActions())); + connect(m_centralWidget, SIGNAL(forwardAvailable(bool)), globalActions, + SLOT(updateActions())); + connect(m_centralWidget, SIGNAL(backwardAvailable(bool)), globalActions, + SLOT(updateActions())); connect(m_centralWidget, SIGNAL(highlighted(QString)), statusBar(), SLOT(showMessage(QString))); @@ -609,6 +595,12 @@ void MainWindow::setupActions() connect(m_contentWindow, SIGNAL(escapePressed()), this, SLOT(activateCurrentCentralWidgetTab())); + // search window + connect(m_searchWindow, SIGNAL(requestShowLink(QUrl)), + CentralWidget::instance(), SLOT(setSourceFromSearch(QUrl))); + connect(m_searchWindow, SIGNAL(requestShowLinkInNewTab(QUrl)), + OpenPagesManager::instance(), SLOT(createNewPageFromSearch(QUrl))); + #if defined(QT_NO_PRINTER) m_pageSetupAction->setVisible(false); m_printPreviewAction->setVisible(false); @@ -732,26 +724,6 @@ void MainWindow::gotoAddress() m_centralWidget->setSource(m_addressLineEdit->text()); } -void MainWindow::updateNavigationItems() -{ - TRACE_OBJ - bool hasCurrentViewer = m_centralWidget->isHomeAvailable(); - m_copyAction->setEnabled(m_centralWidget->hasSelection()); - m_homeAction->setEnabled(hasCurrentViewer); - m_syncAction->setEnabled(hasCurrentViewer); - m_printPreviewAction->setEnabled(hasCurrentViewer); - m_printAction->setEnabled(hasCurrentViewer); - m_nextAction->setEnabled(m_centralWidget->isForwardAvailable()); - m_backAction->setEnabled(m_centralWidget->isBackwardAvailable()); - m_newTabAction->setEnabled(hasCurrentViewer); -} - -void MainWindow::updateTabCloseAction() -{ - TRACE_OBJ - m_closeTabAction->setEnabled(m_centralWidget->enableTabCloseAction()); -} - void MainWindow::showTopicChooser(const QMap<QString, QUrl> &links, const QString &keyword) { @@ -770,6 +742,8 @@ void MainWindow::showPreferences() SLOT(updateApplicationFont())); connect(&dia, SIGNAL(updateBrowserFont()), m_centralWidget, SLOT(updateBrowserFont())); + connect(&dia, SIGNAL(updateUserInterface()), m_centralWidget, + SLOT(updateUserInterface())); dia.showDialog(); } @@ -785,12 +759,6 @@ void MainWindow::syncContents() qApp->restoreOverrideCursor(); } -void MainWindow::copyAvailable(bool yes) -{ - TRACE_OBJ - m_copyAction->setEnabled(yes); -} - void MainWindow::showAboutDialog() { TRACE_OBJ @@ -899,15 +867,13 @@ void MainWindow::setBookmarksVisible(bool visible) void MainWindow::showBookmarksDockWidget() { TRACE_OBJ - if (m_bookmarkWidget) - activateDockWidget(m_bookmarkWidget); + activateDockWidget(m_bookmarkWidget); } void MainWindow::hideBookmarksDockWidget() { TRACE_OBJ - if (m_bookmarkWidget) - m_bookmarkWidget->parentWidget()->hide(); + m_bookmarkWidget->parentWidget()->hide(); } void MainWindow::setSearchVisible(bool visible) @@ -922,13 +888,19 @@ void MainWindow::setSearchVisible(bool visible) void MainWindow::showSearch() { TRACE_OBJ - m_centralWidget->activateSearchWidget(); + activateDockWidget(m_searchWindow); +} + +void MainWindow::showOpenPages() +{ + TRACE_OBJ + activateDockWidget(OpenPagesManager::instance()->openPagesWidget()); } void MainWindow::hideSearch() { TRACE_OBJ - m_centralWidget->removeSearchWidget(); + m_searchWindow->parentWidget()->hide(); } void MainWindow::activateDockWidget(QWidget *w) @@ -948,10 +920,7 @@ void MainWindow::setIndexString(const QString &str) void MainWindow::activateCurrentBrowser() { TRACE_OBJ - CentralWidget *cw = CentralWidget::instance(); - if (cw) { - cw->activateTab(true); - } + CentralWidget::instance()->activateTab(); } void MainWindow::activateCurrentCentralWidgetTab() @@ -960,12 +929,6 @@ void MainWindow::activateCurrentCentralWidgetTab() m_centralWidget->activateTab(); } -void MainWindow::showSearchWidget() -{ - TRACE_OBJ - m_centralWidget->activateSearchWidget(true); -} - void MainWindow::updateApplicationFont() { TRACE_OBJ @@ -1087,17 +1050,13 @@ void MainWindow::currentFilterChanged(const QString &filter) void MainWindow::documentationRemoved(const QString &namespaceName) { TRACE_OBJ - CentralWidget* widget = CentralWidget::instance(); - widget->closeOrReloadTabs(widget->currentSourceFileList(). - keys(namespaceName), false); + OpenPagesManager::instance()->closePages(namespaceName); } void MainWindow::documentationUpdated(const QString &namespaceName) { TRACE_OBJ - CentralWidget* widget = CentralWidget::instance(); - widget->closeOrReloadTabs(widget->currentSourceFileList(). - keys(namespaceName), true); + OpenPagesManager::instance()->reloadPages(namespaceName); } void MainWindow::resetQtDocInfo(const QString &component) diff --git a/tools/assistant/tools/assistant/mainwindow.h b/tools/assistant/tools/assistant/mainwindow.h index 8219140..ea4ebd6 100644 --- a/tools/assistant/tools/assistant/mainwindow.h +++ b/tools/assistant/tools/assistant/mainwindow.h @@ -42,24 +42,27 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H +#include <QtCore/QList> #include <QtCore/QUrl> #include <QtGui/QMainWindow> QT_BEGIN_NAMESPACE class QAction; +class QComboBox; class QFileSystemWatcher; class QLineEdit; -class QComboBox; class QMenu; -class IndexWindow; -class QHelpEngineCore; -class QHelpEngine; class CentralWidget; -class ContentWindow; class CmdLineParser; +class ContentWindow; +class IndexWindow; +class OpenPagesWindow; class QtDocInstaller; +class QHelpEngineCore; +class QHelpEngine; +class SearchWidget; class MainWindow : public QMainWindow { @@ -87,7 +90,6 @@ public slots: void setIndexVisible(bool visible); void setBookmarksVisible(bool visible); void setSearchVisible(bool visible); - void showSearchWidget(); void syncContents(); void activateCurrentCentralWidgetTab(); void currentFilterChanged(const QString &filter); @@ -96,14 +98,12 @@ private slots: void showContents(); void showIndex(); void showSearch(); + void showOpenPages(); void insertLastPages(); void gotoAddress(); void showPreferences(); void showNewAddress(); void showAboutDialog(); - void copyAvailable(bool yes); - void updateNavigationItems(); - void updateTabCloseAction(); void showNewAddress(const QUrl &url); void showTopicChooser(const QMap<QString, QUrl> &links, const QString &keyword); void updateApplicationFont(); @@ -144,20 +144,13 @@ private: CentralWidget *m_centralWidget; IndexWindow *m_indexWindow; ContentWindow *m_contentWindow; + SearchWidget *m_searchWindow; QLineEdit *m_addressLineEdit; QComboBox *m_filterCombo; - QAction *m_backAction; - QAction *m_nextAction; - QAction *m_homeAction; QAction *m_syncAction; - QAction *m_copyAction; - QAction *m_findAction; - QAction *m_printAction; QAction *m_printPreviewAction; QAction *m_pageSetupAction; - QAction *m_zoomInAction; - QAction *m_zoomOutAction; QAction *m_resetZoomAction; QAction *m_aboutAction; QAction *m_closeTabAction; diff --git a/tools/assistant/tools/assistant/openpagesmanager.cpp b/tools/assistant/tools/assistant/openpagesmanager.cpp new file mode 100644 index 0000000..3b69b50 --- /dev/null +++ b/tools/assistant/tools/assistant/openpagesmanager.cpp @@ -0,0 +1,377 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "openpagesmanager.h" + +#include "centralwidget.h" +#include "helpenginewrapper.h" +#include "helpviewer.h" +#include "openpagesmodel.h" +#include "openpagesswitcher.h" +#include "openpageswidget.h" +#include "tracer.h" +#include "../shared/collectionconfiguration.h" + +#include <QtGui/QApplication> +#include <QtGui/QTreeView> + +QT_BEGIN_NAMESPACE + +OpenPagesManager *OpenPagesManager::m_instance = 0; + +OpenPagesManager *OpenPagesManager::createInstance(QObject *parent, + bool defaultCollection, const QUrl &cmdLineUrl) +{ + TRACE_OBJ + Q_ASSERT(!m_instance); + m_instance = new OpenPagesManager(parent, defaultCollection, cmdLineUrl); + return m_instance; +} + +OpenPagesManager *OpenPagesManager::instance() +{ + TRACE_OBJ + Q_ASSERT(m_instance); + return m_instance; +} + +OpenPagesManager::OpenPagesManager(QObject *parent, bool defaultCollection, + const QUrl &cmdLineUrl) + : QObject(parent) + , m_model(new OpenPagesModel(this)) + , m_openPagesWidget(0) + , m_openPagesSwitcher(0) +{ + TRACE_OBJ + m_openPagesWidget = new OpenPagesWidget(m_model); + m_openPagesWidget->setFrameStyle(QFrame::NoFrame); + connect(m_openPagesWidget, SIGNAL(setCurrentPage(QModelIndex)), this, + SLOT(setCurrentPage(QModelIndex))); + connect(m_openPagesWidget, SIGNAL(closePage(QModelIndex)), this, + SLOT(closePage(QModelIndex))); + connect(m_openPagesWidget, SIGNAL(closePagesExcept(QModelIndex)), this, + SLOT(closePagesExcept(QModelIndex))); + + m_openPagesSwitcher = new OpenPagesSwitcher(m_model); + connect(m_openPagesSwitcher, SIGNAL(closePage(QModelIndex)), this, + SLOT(closePage(QModelIndex))); + connect(m_openPagesSwitcher, SIGNAL(setCurrentPage(QModelIndex)), this, + SLOT(setCurrentPage(QModelIndex))); + + setupInitialPages(defaultCollection, cmdLineUrl); +} + +OpenPagesManager ::~OpenPagesManager() +{ + TRACE_OBJ + m_instance = 0; + delete m_openPagesSwitcher; +} + +int OpenPagesManager::pageCount() const +{ + TRACE_OBJ + return m_model->rowCount(); +} + +void OpenPagesManager::setupInitialPages(bool defaultCollection, + const QUrl &cmdLineUrl) +{ + TRACE_OBJ + if (cmdLineUrl.isValid()) { + createPage(cmdLineUrl); + return; + } + + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); + int initialPage = 0; + switch (helpEngine.startOption()) { + case ShowHomePage: + m_model->addPage(helpEngine.homePage()); + break; + case ShowBlankPage: + m_model->addPage(QUrl(QLatin1String("about:blank"))); + break; + case ShowLastPages: { + const QStringList &lastShownPageList = helpEngine.lastShownPages(); + const int pageCount = lastShownPageList.count(); + if (pageCount == 0) { + if (defaultCollection) + m_model->addPage(QUrl(QLatin1String("help"))); + else + m_model->addPage(QUrl(QLatin1String("about:blank"))); + } else { + QStringList zoomFactors = helpEngine.lastZoomFactors(); + while (zoomFactors.count() < pageCount) + zoomFactors.append(CollectionConfiguration::DefaultZoomFactor); + initialPage = helpEngine.lastTabPage(); + if (initialPage >= pageCount) { + qWarning("Initial page set to %d, maximum possible value is %d", + initialPage, pageCount - 1); + initialPage = 0; + } + for (int curPage = 0; curPage < pageCount; ++curPage) { + const QString &curFile = lastShownPageList.at(curPage); + if (helpEngine.findFile(curFile).isValid() + || curFile == QLatin1String("about:blank")) { + m_model->addPage(curFile, zoomFactors.at(curPage).toFloat()); + } else if (curPage <= initialPage && initialPage > 0) + --initialPage; + } + } + break; + } + default: + Q_ASSERT(!"Unhandled option"); + } + + if (m_model->rowCount() == 0) + m_model->addPage(helpEngine.homePage()); + for (int i = 0; i < m_model->rowCount(); ++i) + CentralWidget::instance()->addPage(m_model->pageAt(i)); + setCurrentPage(initialPage); + m_openPagesSwitcher->selectCurrentPage(); +} + +HelpViewer *OpenPagesManager::createPage() +{ + TRACE_OBJ + return createPage(QUrl(QLatin1String("about:blank"))); +} + +void OpenPagesManager::closeCurrentPage() +{ + TRACE_OBJ + Q_ASSERT(m_model->rowCount() > 1); + const QModelIndexList selectedIndexes + = m_openPagesWidget->selectionModel()->selectedRows(); + if (selectedIndexes.isEmpty()) + return; + Q_ASSERT(selectedIndexes.count() == 1); + removePage(selectedIndexes.first().row()); +} + +HelpViewer *OpenPagesManager::createPage(const QUrl &url, bool fromSearch) +{ + TRACE_OBJ + if (HelpViewer::launchWithExternalApp(url)) + return 0; + + m_model->addPage(url); + const int index = m_model->rowCount() - 1; + HelpViewer * const page = m_model->pageAt(index); + CentralWidget::instance()->addPage(page, fromSearch); + setCurrentPage(index); + return page; +} + +HelpViewer *OpenPagesManager::createNewPageFromSearch(const QUrl &url) +{ + TRACE_OBJ + return createPage(url, true); +} + +void OpenPagesManager::closePage(HelpViewer *viewer) +{ + TRACE_OBJ + for (int i = 0; i < m_model->rowCount(); ++i) { + if (m_model->pageAt(i) == viewer) { + removePage(i); + break; + } + } +} + +void OpenPagesManager::closePage(const QModelIndex &index) +{ + TRACE_OBJ + if (index.isValid()) + removePage(index.row()); +} + +void OpenPagesManager::closePages(const QString &nameSpace) +{ + TRACE_OBJ + closeOrReloadPages(nameSpace, false); +} + +void OpenPagesManager::reloadPages(const QString &nameSpace) +{ + TRACE_OBJ + closeOrReloadPages(nameSpace, true); + m_openPagesWidget->selectCurrentPage(); +} + +void OpenPagesManager::closeOrReloadPages(const QString &nameSpace, bool tryReload) +{ + TRACE_OBJ + for (int i = m_model->rowCount() - 1; i >= 0; --i) { + HelpViewer *page = m_model->pageAt(i); + if (page->source().host() != nameSpace) + continue; + if (tryReload && HelpEngineWrapper::instance().findFile(page->source()).isValid()) + page->reload(); + else if (m_model->rowCount() == 1) + page->setSource(QUrl(QLatin1String("about:blank"))); + else + removePage(i); + } +} + +bool OpenPagesManager::pagesOpenForNamespace(const QString &nameSpace) const +{ + TRACE_OBJ + for (int i = 0; i < m_model->rowCount(); ++i) + if (m_model->pageAt(i)->source().host() == nameSpace) + return true; + return false; +} + +void OpenPagesManager::setCurrentPage(const QModelIndex &index) +{ + TRACE_OBJ + if (index.isValid()) + setCurrentPage(index.row()); +} + +void OpenPagesManager::setCurrentPage(int index) +{ + TRACE_OBJ + setCurrentPage(m_model->pageAt(index)); +} + +void OpenPagesManager::setCurrentPage(HelpViewer *page) +{ + TRACE_OBJ + CentralWidget::instance()->setCurrentPage(page); + m_openPagesWidget->selectCurrentPage(); +} + +void OpenPagesManager::removePage(int index) +{ + TRACE_OBJ + CentralWidget::instance()->removePage(index); + m_model->removePage(index); + m_openPagesWidget->selectCurrentPage(); +} + + +void OpenPagesManager::closePagesExcept(const QModelIndex &index) +{ + TRACE_OBJ + if (!index.isValid()) + return; + + int i = 0; + HelpViewer *viewer = m_model->pageAt(index.row()); + while (m_model->rowCount() > 1) { + if (m_model->pageAt(i) != viewer) + removePage(i); + else + ++i; + } +} + +QAbstractItemView *OpenPagesManager::openPagesWidget() const +{ + TRACE_OBJ + return m_openPagesWidget; +} + +void OpenPagesManager::nextPage() +{ + TRACE_OBJ + nextOrPreviousPage(1); +} + +void OpenPagesManager::nextPageWithSwitcher() +{ + TRACE_OBJ + if (!m_openPagesSwitcher->isVisible()) { + m_openPagesSwitcher->selectCurrentPage(); + m_openPagesSwitcher->gotoNextPage(); + showSwitcherOrSelectPage(); + } else { + m_openPagesSwitcher->gotoNextPage(); + } +} + +void OpenPagesManager::previousPage() +{ + TRACE_OBJ + nextOrPreviousPage(-1); +} + +void OpenPagesManager::previousPageWithSwitcher() +{ + TRACE_OBJ + if (!m_openPagesSwitcher->isVisible()) { + m_openPagesSwitcher->selectCurrentPage(); + m_openPagesSwitcher->gotoPreviousPage(); + showSwitcherOrSelectPage(); + } else { + m_openPagesSwitcher->gotoPreviousPage(); + } +} + +void OpenPagesManager::nextOrPreviousPage(int offset) +{ + TRACE_OBJ + setCurrentPage((CentralWidget::instance()->currentIndex() + offset + + m_model->rowCount()) % m_model->rowCount()); +} + +void OpenPagesManager::showSwitcherOrSelectPage() const +{ + TRACE_OBJ + if (QApplication::keyboardModifiers() != Qt::NoModifier) { + const int width = CentralWidget::instance()->width(); + const int height = CentralWidget::instance()->height(); + const QPoint p(CentralWidget::instance()->mapToGlobal(QPoint(0, 0))); + m_openPagesSwitcher->move((width - m_openPagesSwitcher->width()) / 2 + p.x(), + (height - m_openPagesSwitcher->height()) / 2 + p.y()); + m_openPagesSwitcher->setVisible(true); + } else { + m_openPagesSwitcher->selectAndHide(); + } +} + +QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/openpagesmanager.h b/tools/assistant/tools/assistant/openpagesmanager.h new file mode 100644 index 0000000..5837392 --- /dev/null +++ b/tools/assistant/tools/assistant/openpagesmanager.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OPENPAGESMANAGER_H +#define OPENPAGESMANAGER_H + +#include <QtCore/QObject> + +QT_BEGIN_NAMESPACE + +class QAbstractItemView; +class QModelIndex; +class QUrl; + +class HelpViewer; +class OpenPagesModel; +class OpenPagesSwitcher; +class OpenPagesWidget; + +class OpenPagesManager : public QObject +{ + Q_OBJECT +public: + static OpenPagesManager *createInstance(QObject *parent, + bool defaultCollection, const QUrl &cmdLineUrl); + static OpenPagesManager *instance(); + + bool pagesOpenForNamespace(const QString &nameSpace) const; + void closePages(const QString &nameSpace); + void reloadPages(const QString &nameSpace); + + QAbstractItemView* openPagesWidget() const; + + int pageCount() const; + void setCurrentPage(int index); + +public slots: + HelpViewer *createPage(const QUrl &url, bool fromSearch = false); + HelpViewer *createNewPageFromSearch(const QUrl &url); + HelpViewer *createPage(); + void closeCurrentPage(); + + void nextPage(); + void nextPageWithSwitcher(); + void previousPage(); + void previousPageWithSwitcher(); + + void closePage(HelpViewer *page); + void setCurrentPage(HelpViewer *page); + +private slots: + void setCurrentPage(const QModelIndex &index); + void closePage(const QModelIndex &index); + void closePagesExcept(const QModelIndex &index); + +private: + OpenPagesManager(QObject *parent, bool defaultCollection, + const QUrl &cmdLineUrl); + ~OpenPagesManager(); + + void setupInitialPages(bool defaultCollection, const QUrl &cmdLineUrl); + void closeOrReloadPages(const QString &nameSpace, bool tryReload); + void removePage(int index); + + void nextOrPreviousPage(int offset); + void showSwitcherOrSelectPage() const; + + OpenPagesModel *m_model; + OpenPagesWidget *m_openPagesWidget; + OpenPagesSwitcher *m_openPagesSwitcher; + + static OpenPagesManager *m_instance; +}; + +QT_END_NAMESPACE + +#endif // OPENPAGESMANAGER_H diff --git a/tools/assistant/tools/assistant/openpagesmodel.cpp b/tools/assistant/tools/assistant/openpagesmodel.cpp new file mode 100644 index 0000000..2663b85 --- /dev/null +++ b/tools/assistant/tools/assistant/openpagesmodel.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "openpagesmodel.h" + +#include "helpenginewrapper.h" +#include "helpviewer.h" +#include "tracer.h" + +#include <QtCore/QStringList> +#include <QtCore/QUrl> + +QT_BEGIN_NAMESPACE + +OpenPagesModel::OpenPagesModel(QObject *parent) : QAbstractTableModel(parent) +{ + TRACE_OBJ +} + +int OpenPagesModel::rowCount(const QModelIndex &parent) const +{ + TRACE_OBJ + return parent.isValid() ? 0 : m_pages.count(); +} + +int OpenPagesModel::columnCount(const QModelIndex &/*parent*/) const +{ + TRACE_OBJ + return 2; +} + +QVariant OpenPagesModel::data(const QModelIndex &index, int role) const +{ + TRACE_OBJ + if (!index.isValid() || index.row() >= rowCount() || index.column() > 0 + || role != Qt::DisplayRole) + return QVariant(); + QString title = m_pages.at(index.row())->title(); + title.replace(QLatin1Char('&'), QLatin1String("&&")); + return title.isEmpty() ? QLatin1String("(Untitled)") : title; +} + +void OpenPagesModel::addPage(const QUrl &url, qreal zoom) +{ + TRACE_OBJ + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + HelpViewer *page = new HelpViewer(zoom); + connect(page, SIGNAL(titleChanged()), this, SLOT(handleTitleChanged())); + m_pages << page; + endInsertRows(); + page->setSource(url); +} + +void OpenPagesModel::removePage(int index) +{ + TRACE_OBJ + Q_ASSERT(index >= 0 && index < rowCount()); + beginRemoveRows(QModelIndex(), index, index); + HelpViewer *page = m_pages.at(index); + m_pages.removeAt(index); + endRemoveRows(); + page->deleteLater(); +} + +HelpViewer *OpenPagesModel::pageAt(int index) const +{ + TRACE_OBJ + Q_ASSERT(index >= 0 && index < rowCount()); + return m_pages.at(index); +} + +void OpenPagesModel::handleTitleChanged() +{ + TRACE_OBJ + HelpViewer *page = static_cast<HelpViewer *>(sender()); + const int row = m_pages.indexOf(page); + Q_ASSERT(row != -1 ); + const QModelIndex &item = index(row, 0); + emit dataChanged(item, item); +} + +QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/openpagesmodel.h b/tools/assistant/tools/assistant/openpagesmodel.h new file mode 100644 index 0000000..64013a6 --- /dev/null +++ b/tools/assistant/tools/assistant/openpagesmodel.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OPENPAGESMODEL_H +#define OPENPAGESMODEL_H + +#include <QtCore/QAbstractTableModel> +#include <QtCore/QList> + +QT_BEGIN_NAMESPACE + +class HelpViewer; +class QUrl; + +class OpenPagesModel : public QAbstractTableModel +{ + Q_OBJECT +public: + OpenPagesModel(QObject *parent); + + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + + void addPage(const QUrl &url, qreal zoom = 0); + void removePage(int index); + HelpViewer *pageAt(int index) const; + +private slots: + void handleTitleChanged(); + +private: + QList<HelpViewer *> m_pages; +}; + +QT_END_NAMESPACE + +#endif // OPENPAGESMODEL_H diff --git a/tools/assistant/tools/assistant/openpagesswitcher.cpp b/tools/assistant/tools/assistant/openpagesswitcher.cpp new file mode 100644 index 0000000..d4b7d82 --- /dev/null +++ b/tools/assistant/tools/assistant/openpagesswitcher.cpp @@ -0,0 +1,194 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "openpagesswitcher.h" + +#include "centralwidget.h" +#include "openpagesmodel.h" +#include "openpageswidget.h" +#include "tracer.h" + +#include <QtCore/QEvent> + +#include <QtGui/QKeyEvent> +#include <QtGui/QVBoxLayout> + +QT_BEGIN_NAMESPACE + +const int gWidth = 300; +const int gHeight = 200; + +OpenPagesSwitcher::OpenPagesSwitcher(OpenPagesModel *model) + : QFrame(0, Qt::Popup) + , m_openPagesModel(model) +{ + TRACE_OBJ + resize(gWidth, gHeight); + + m_openPagesWidget = new OpenPagesWidget(m_openPagesModel); + + // We disable the frame on this list view and use a QFrame around it instead. + // This improves the look with QGTKStyle. +#ifndef Q_WS_MAC + setFrameStyle(m_openPagesWidget->frameStyle()); +#endif + m_openPagesWidget->setFrameStyle(QFrame::NoFrame); + + m_openPagesWidget->allowContextMenu(false); + m_openPagesWidget->installEventFilter(this); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setMargin(0); + layout->addWidget(m_openPagesWidget); + + connect(m_openPagesWidget, SIGNAL(closePage(QModelIndex)), this, + SIGNAL(closePage(QModelIndex))); + connect(m_openPagesWidget, SIGNAL(setCurrentPage(QModelIndex)), this, + SIGNAL(setCurrentPage(QModelIndex))); +} + +OpenPagesSwitcher::~OpenPagesSwitcher() +{ + TRACE_OBJ +} + +void OpenPagesSwitcher::gotoNextPage() +{ + TRACE_OBJ + selectPageUpDown(1); +} + +void OpenPagesSwitcher::gotoPreviousPage() +{ + TRACE_OBJ + selectPageUpDown(-1); +} + +void OpenPagesSwitcher::selectAndHide() +{ + TRACE_OBJ + setVisible(false); + emit setCurrentPage(m_openPagesWidget->currentIndex()); +} + +void OpenPagesSwitcher::selectCurrentPage() +{ + TRACE_OBJ + m_openPagesWidget->selectCurrentPage(); +} + +void OpenPagesSwitcher::setVisible(bool visible) +{ + TRACE_OBJ + QWidget::setVisible(visible); + if (visible) + setFocus(); +} + +void OpenPagesSwitcher::focusInEvent(QFocusEvent *event) +{ + TRACE_OBJ + Q_UNUSED(event) + m_openPagesWidget->setFocus(); +} + +bool OpenPagesSwitcher::eventFilter(QObject *object, QEvent *event) +{ + TRACE_OBJ + if (object == m_openPagesWidget) { + if (event->type() == QEvent::KeyPress) { + QKeyEvent *ke = static_cast<QKeyEvent*>(event); + if (ke->key() == Qt::Key_Escape) { + setVisible(false); + return true; + } + + const int key = ke->key(); + if (key == Qt::Key_Return || key == Qt::Key_Enter || key == Qt::Key_Space) { + emit setCurrentPage(m_openPagesWidget->currentIndex()); + return true; + } + + Qt::KeyboardModifier modifier = Qt::ControlModifier; +#ifdef Q_WS_MAC + modifier = Qt::AltModifier; +#endif + if (key == Qt::Key_Backtab + && (ke->modifiers() == (modifier | Qt::ShiftModifier))) + gotoPreviousPage(); + else if (key == Qt::Key_Tab && (ke->modifiers() == modifier)) + gotoNextPage(); + } else if (event->type() == QEvent::KeyRelease) { + QKeyEvent *ke = static_cast<QKeyEvent*>(event); + if (ke->modifiers() == 0 + /*HACK this is to overcome some event inconsistencies between platforms*/ + || (ke->modifiers() == Qt::AltModifier + && (ke->key() == Qt::Key_Alt || ke->key() == -1))) { + selectAndHide(); + } + } + } + return QWidget::eventFilter(object, event); +} + +void OpenPagesSwitcher::selectPageUpDown(int summand) +{ + TRACE_OBJ + const int pageCount = m_openPagesModel->rowCount(); + if (pageCount < 2) + return; + + const QModelIndexList &list = m_openPagesWidget->selectionModel()->selectedIndexes(); + if (list.isEmpty()) + return; + + QModelIndex index = list.first(); + if (!index.isValid()) + return; + + index = m_openPagesModel->index((index.row() + summand + pageCount) % pageCount, 0); + if (index.isValid()) { + m_openPagesWidget->setCurrentIndex(index); + m_openPagesWidget->scrollTo(index, QAbstractItemView::PositionAtCenter); + } +} + +QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/openpagesswitcher.h b/tools/assistant/tools/assistant/openpagesswitcher.h new file mode 100644 index 0000000..e27db6b --- /dev/null +++ b/tools/assistant/tools/assistant/openpagesswitcher.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OPENPAGESSWITCHER_H +#define OPENPAGESSWITCHER_H + +#include <QtGui/QFrame> + +QT_BEGIN_NAMESPACE + +class OpenPagesModel; +class OpenPagesWidget; +class QModelIndex; + +class OpenPagesSwitcher : public QFrame +{ + Q_OBJECT + +public: + OpenPagesSwitcher(OpenPagesModel *model); + ~OpenPagesSwitcher(); + + void gotoNextPage(); + void gotoPreviousPage(); + + void selectAndHide(); + void selectCurrentPage(); + + void setVisible(bool visible); + void focusInEvent(QFocusEvent *event); + bool eventFilter(QObject *object, QEvent *event); + +signals: + void closePage(const QModelIndex &index); + void setCurrentPage(const QModelIndex &index); + +private: + void selectPageUpDown(int summand); + +private: + OpenPagesModel *m_openPagesModel; + OpenPagesWidget *m_openPagesWidget; +}; + +QT_END_NAMESPACE + +#endif // OPENPAGESSWITCHER_H diff --git a/tools/assistant/tools/assistant/openpageswidget.cpp b/tools/assistant/tools/assistant/openpageswidget.cpp new file mode 100644 index 0000000..b7ac33e --- /dev/null +++ b/tools/assistant/tools/assistant/openpageswidget.cpp @@ -0,0 +1,237 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "openpageswidget.h" + +#include "centralwidget.h" +#include "openpagesmodel.h" +#include "tracer.h" + +#include <QtGui/QApplication> +#include <QtGui/QHeaderView> +#include <QtGui/QKeyEvent> +#include <QtGui/QMouseEvent> +#include <QtGui/QMenu> +#include <QtGui/QPainter> + +#ifdef Q_WS_MAC +#include <qmacstyle_mac.h> +#endif + +QT_BEGIN_NAMESPACE + +OpenPagesDelegate::OpenPagesDelegate(QObject *parent) + : QStyledItemDelegate(parent) +{ + TRACE_OBJ +} + +void OpenPagesDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + TRACE_OBJ + if (option.state & QStyle::State_MouseOver) { + if ((QApplication::mouseButtons() & Qt::LeftButton) == 0) + pressedIndex = QModelIndex(); + QBrush brush = option.palette.alternateBase(); + if (index == pressedIndex) + brush = option.palette.dark(); + painter->fillRect(option.rect, brush); + } + + QStyledItemDelegate::paint(painter, option, index); + + if (index.column() == 1 && index.model()->rowCount() > 1 + && option.state & QStyle::State_MouseOver) { + QIcon icon((option.state & QStyle::State_Selected) + ? ":/trolltech/assistant/images/closebutton.png" + : ":/trolltech/assistant/images/darkclosebutton.png"); + + const QRect iconRect(option.rect.right() - option.rect.height(), + option.rect.top(), option.rect.height(), option.rect.height()); + icon.paint(painter, iconRect, Qt::AlignRight | Qt::AlignVCenter); + } +} + +// -- OpenPagesWidget + +OpenPagesWidget::OpenPagesWidget(OpenPagesModel *model) + : m_allowContextMenu(true) +{ + TRACE_OBJ + setModel(model); + setIndentation(0); + setItemDelegate((m_delegate = new OpenPagesDelegate(this))); + + setTextElideMode(Qt::ElideMiddle); + setAttribute(Qt::WA_MacShowFocusRect, false); + + viewport()->setAttribute(Qt::WA_Hover); + setSelectionBehavior(QAbstractItemView::SelectRows); + setSelectionMode(QAbstractItemView::SingleSelection); + + header()->hide(); + header()->setStretchLastSection(false); + header()->setResizeMode(0, QHeaderView::Stretch); + header()->setResizeMode(1, QHeaderView::Fixed); + header()->resizeSection(1, 18); + + installEventFilter(this); + setUniformRowHeights(true); + setContextMenuPolicy(Qt::CustomContextMenu); + + connect(this, SIGNAL(clicked(QModelIndex)), this, + SLOT(handleClicked(QModelIndex))); + connect(this, SIGNAL(pressed(QModelIndex)), this, + SLOT(handlePressed(QModelIndex))); + connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, + SLOT(contextMenuRequested(QPoint))); +} + +OpenPagesWidget::~OpenPagesWidget() +{ + TRACE_OBJ +} + +void OpenPagesWidget::selectCurrentPage() +{ + TRACE_OBJ + const QModelIndex ¤t = + model()->index(CentralWidget::instance()->currentIndex(), 0); + + QItemSelectionModel * const selModel = selectionModel(); + selModel->select(current, + QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + selModel->clearSelection(); + + setCurrentIndex(current); + scrollTo(currentIndex()); +} + +void OpenPagesWidget::allowContextMenu(bool ok) +{ + TRACE_OBJ + m_allowContextMenu = ok; +} + +void OpenPagesWidget::contextMenuRequested(QPoint pos) +{ + TRACE_OBJ + QModelIndex index = indexAt(pos); + if (!index.isValid() || !m_allowContextMenu) + return; + + if (index.column() == 1) + index = index.sibling(index.row(), 0); + QMenu contextMenu; + QAction *closeEditor = contextMenu.addAction(tr("Close %1").arg(index.data() + .toString())); + QAction *closeOtherEditors = contextMenu.addAction(tr("Close All Except %1") + .arg(index.data().toString())); + + if (model()->rowCount() == 1) { + closeEditor->setEnabled(false); + closeOtherEditors->setEnabled(false); + } + + QAction *action = contextMenu.exec(mapToGlobal(pos)); + if (action == closeEditor) + emit closePage(index); + else if (action == closeOtherEditors) + emit closePagesExcept(index); +} + +void OpenPagesWidget::handlePressed(const QModelIndex &index) +{ + TRACE_OBJ + if (index.column() == 0) + emit setCurrentPage(index); + + if (index.column() == 1) + m_delegate->pressedIndex = index; +} + +void OpenPagesWidget::handleClicked(const QModelIndex &index) +{ + TRACE_OBJ + // implemented here to handle the funky close button and to work around a + // bug in item views where the delegate wouldn't get the QStyle::State_MouseOver + if (index.column() == 1) { + if (model()->rowCount() > 1) + emit closePage(index); + + QWidget *vp = viewport(); + const QPoint &cursorPos = QCursor::pos(); + QMouseEvent e(QEvent::MouseMove, vp->mapFromGlobal(cursorPos), cursorPos, + Qt::NoButton, 0, 0); + QCoreApplication::sendEvent(vp, &e); + } +} + +bool OpenPagesWidget::eventFilter(QObject *obj, QEvent *event) +{ + TRACE_OBJ + if (obj != this) + return QWidget::eventFilter(obj, event); + + if (event->type() == QEvent::KeyPress) { + QKeyEvent *ke = static_cast<QKeyEvent*>(event); + if (currentIndex().isValid() && ke->modifiers() == 0) { + const int key = ke->key(); + if (key == Qt::Key_Return || key == Qt::Key_Enter + || key == Qt::Key_Space) { + emit setCurrentPage(currentIndex()); + } else if ((key == Qt::Key_Delete || key == Qt::Key_Backspace) + && model()->rowCount() > 1) { + emit closePage(currentIndex()); + } + } + } else if (event->type() == QEvent::KeyRelease) { + QKeyEvent *ke = static_cast<QKeyEvent*>(event); + if (ke->modifiers() == 0 + && (ke->key() == Qt::Key_Up || ke->key() == Qt::Key_Down)) { + emit setCurrentPage(currentIndex()); + } + } + return QWidget::eventFilter(obj, event); +} + +QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/openpageswidget.h b/tools/assistant/tools/assistant/openpageswidget.h new file mode 100644 index 0000000..4b972f3 --- /dev/null +++ b/tools/assistant/tools/assistant/openpageswidget.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OPENPAGESWIDGET_H +#define OPENPAGESWIDGET_H + +#include <QtGui/QStyledItemDelegate> +#include <QtGui/QTreeView> + +QT_BEGIN_NAMESPACE + +class OpenPagesModel; + +class OpenPagesDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + explicit OpenPagesDelegate(QObject *parent = 0); + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const; + + mutable QModelIndex pressedIndex; +}; + +class OpenPagesWidget : public QTreeView +{ + Q_OBJECT +public: + OpenPagesWidget(OpenPagesModel *model); + ~OpenPagesWidget(); + + void selectCurrentPage(); + void allowContextMenu(bool ok); + +signals: + void setCurrentPage(const QModelIndex &index); + void closePage(const QModelIndex &index); + void closePagesExcept(const QModelIndex &index); + +private slots: + void contextMenuRequested(QPoint pos); + void handlePressed(const QModelIndex &index); + void handleClicked(const QModelIndex &index); + +private: + bool eventFilter(QObject *obj, QEvent *event); + + bool m_allowContextMenu; + OpenPagesDelegate *m_delegate; +}; + +QT_END_NAMESPACE + +#endif // OPENPAGESWIDGET_H diff --git a/tools/assistant/tools/assistant/preferencesdialog.cpp b/tools/assistant/tools/assistant/preferencesdialog.cpp index 0e1d719..495dad9 100644 --- a/tools/assistant/tools/assistant/preferencesdialog.cpp +++ b/tools/assistant/tools/assistant/preferencesdialog.cpp @@ -45,6 +45,7 @@ #include "fontpanel.h" #include "helpenginewrapper.h" #include "installdialog.h" +#include "openpagesmanager.h" #include "tracer.h" #include <QtCore/QtAlgorithms> @@ -302,15 +303,12 @@ void PreferencesDialog::addDocumentationLocal() void PreferencesDialog::removeDocumentation() { TRACE_OBJ - bool foundBefore = false; - CentralWidget* widget = CentralWidget::instance(); - QMap<int, QString> openedDocList = widget->currentSourceFileList(); - QStringList values(openedDocList.values()); + bool foundBefore = false; QList<QListWidgetItem*> l = m_ui.registeredDocsListWidget->selectedItems(); foreach (QListWidgetItem* item, l) { const QString& ns = item->text(); - if (!foundBefore && values.contains(ns)) { + if (!foundBefore && OpenPagesManager::instance()->pagesOpenForNamespace(ns)) { if (0 == QMessageBox::information(this, tr("Remove Documentation"), tr("Some documents currently opened in Assistant reference the " "documentation you are attempting to remove. Removing the " @@ -320,7 +318,6 @@ void PreferencesDialog::removeDocumentation() } m_unregDocs.append(ns); - m_TabsToClose += openedDocList.keys(ns); delete m_ui.registeredDocsListWidget->takeItem( m_ui.registeredDocsListWidget->row(item)); } @@ -374,14 +371,18 @@ void PreferencesDialog::applyChanges() } } - CentralWidget::instance()->closeOrReloadTabs(m_TabsToClose, false); - - foreach (const QString &doc, m_unregDocs) + foreach (const QString &doc, m_unregDocs) { + OpenPagesManager::instance()->closePages(doc); helpEngine.unregisterDocumentation(doc); + } if (filtersWereChanged || !m_regDocs.isEmpty() || !m_unregDocs.isEmpty()) helpEngine.setupData(); + helpEngine.setShowTabs(m_ui.showTabs->isChecked()); + if (m_showTabs != m_ui.showTabs->isChecked()) + emit updateUserInterface(); + accept(); } @@ -424,13 +425,13 @@ void PreferencesDialog::updateFontSettingsPage() connect(m_browserFontPanel, SIGNAL(toggled(bool)), this, SLOT(browserFontSettingToggled(bool))); - QList<QComboBox*> allCombos = qFindChildren<QComboBox*>(m_appFontPanel); + QList<QComboBox*> allCombos = m_appFontPanel->findChildren<QComboBox*>(); foreach (QComboBox* box, allCombos) { connect(box, SIGNAL(currentIndexChanged(int)), this, SLOT(appFontSettingChanged(int))); } - allCombos = qFindChildren<QComboBox*>(m_browserFontPanel); + allCombos = m_browserFontPanel->findChildren<QComboBox*>(); foreach (QComboBox* box, allCombos) { connect(box, SIGNAL(currentIndexChanged(int)), this, SLOT(browserFontSettingChanged(int))); @@ -473,6 +474,9 @@ void PreferencesDialog::updateOptionsPage() int option = helpEngine.startOption(); m_ui.helpStartComboBox->setCurrentIndex(option); + m_showTabs = helpEngine.showTabs(); + m_ui.showTabs->setChecked(m_showTabs); + connect(m_ui.blankPageButton, SIGNAL(clicked()), this, SLOT(setBlankPage())); connect(m_ui.currentPageButton, SIGNAL(clicked()), this, SLOT(setCurrentPage())); connect(m_ui.defaultPageButton, SIGNAL(clicked()), this, SLOT(setDefaultPage())); diff --git a/tools/assistant/tools/assistant/preferencesdialog.h b/tools/assistant/tools/assistant/preferencesdialog.h index 2894494..22cf8c9 100644 --- a/tools/assistant/tools/assistant/preferencesdialog.h +++ b/tools/assistant/tools/assistant/preferencesdialog.h @@ -81,6 +81,7 @@ private slots: signals: void updateBrowserFont(); void updateApplicationFont(); + void updateUserInterface(); private: void updateFilterPage(); @@ -96,12 +97,12 @@ private: QStringList m_docsBackup; QStringList m_regDocs; QStringList m_unregDocs; - QList<int> m_TabsToClose; FontPanel *m_appFontPanel; FontPanel *m_browserFontPanel; bool m_appFontChanged; bool m_browserFontChanged; HelpEngineWrapper &helpEngine; + bool m_showTabs; }; QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/preferencesdialog.ui b/tools/assistant/tools/assistant/preferencesdialog.ui index 279084d..1c6833a 100644 --- a/tools/assistant/tools/assistant/preferencesdialog.ui +++ b/tools/assistant/tools/assistant/preferencesdialog.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>375</width> - <height>266</height> + <height>275</height> </rect> </property> <property name="windowTitle"> @@ -187,7 +187,7 @@ <attribute name="title"> <string>Options</string> </attribute> - <layout class="QVBoxLayout" name="verticalLayout_2"> + <layout class="QVBoxLayout" name="verticalLayout_3"> <item> <widget class="QGroupBox" name="groupBox_2"> <property name="title"> @@ -310,6 +310,22 @@ </widget> </item> <item> + <widget class="QGroupBox" name="groupBox_3"> + <property name="title"> + <string>Appearance</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QCheckBox" name="showTabs"> + <property name="text"> + <string>Show tabs for each individual page</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> <spacer name="verticalSpacer_2"> <property name="orientation"> <enum>Qt::Vertical</enum> diff --git a/tools/assistant/tools/assistant/remotecontrol.cpp b/tools/assistant/tools/assistant/remotecontrol.cpp index 5ecdd69..06e5602 100644 --- a/tools/assistant/tools/assistant/remotecontrol.cpp +++ b/tools/assistant/tools/assistant/remotecontrol.cpp @@ -38,12 +38,13 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "tracer.h" - #include "remotecontrol.h" -#include "mainwindow.h" + #include "centralwidget.h" #include "helpenginewrapper.h" +#include "mainwindow.h" +#include "openpagesmanager.h" +#include "tracer.h" #include <QtCore/QFile> #include <QtCore/QFileInfo> @@ -323,8 +324,7 @@ void RemoteControl::handleUnregisterCommand(const QString &arg) const QString &absFileName = QFileInfo(arg).absoluteFilePath(); const QString &ns = QHelpEngineCore::namespaceName(absFileName); if (helpEngine.registeredDocumentations().contains(ns)) { - CentralWidget* widget = CentralWidget::instance(); - widget->closeOrReloadTabs(widget->currentSourceFileList().keys(ns), false); + OpenPagesManager::instance()->closePages(ns); if (helpEngine.unregisterDocumentation(ns)) helpEngine.setupData(); } diff --git a/tools/assistant/tools/assistant/searchwidget.cpp b/tools/assistant/tools/assistant/searchwidget.cpp index d83790d..bb5bdeb 100644 --- a/tools/assistant/tools/assistant/searchwidget.cpp +++ b/tools/assistant/tools/assistant/searchwidget.cpp @@ -63,7 +63,6 @@ QT_BEGIN_NAMESPACE SearchWidget::SearchWidget(QHelpSearchEngine *engine, QWidget *parent) : QWidget(parent) , zoomCount(0) - , attached(false) , searchEngine(engine) { TRACE_OBJ @@ -86,7 +85,7 @@ SearchWidget::SearchWidget(QHelpSearchEngine *engine, QWidget *parent) connect(searchEngine, SIGNAL(searchingFinished(int)), this, SLOT(searchingFinished(int))); - QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget); + QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>(); if (browser) // Will be null if lib was configured not to use CLucene. browser->viewport()->installEventFilter(this); } @@ -100,7 +99,7 @@ SearchWidget::~SearchWidget() void SearchWidget::zoomIn() { TRACE_OBJ - QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget); + QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>(); if (browser && zoomCount != 10) { zoomCount++; browser->zoomIn(); @@ -110,7 +109,7 @@ void SearchWidget::zoomIn() void SearchWidget::zoomOut() { TRACE_OBJ - QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget); + QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>(); if (browser && zoomCount != -5) { zoomCount--; browser->zoomOut(); @@ -123,25 +122,13 @@ void SearchWidget::resetZoom() if (zoomCount == 0) return; - QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget); + QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>(); if (browser) { browser->zoomOut(zoomCount); zoomCount = 0; } } -bool SearchWidget::isAttached() const -{ - TRACE_OBJ - return attached; -} - -void SearchWidget::setAttached(bool state) -{ - TRACE_OBJ - attached = state; -} - void SearchWidget::search() const { TRACE_OBJ @@ -165,7 +152,7 @@ void SearchWidget::searchingFinished(int hits) bool SearchWidget::eventFilter(QObject* o, QEvent *e) { TRACE_OBJ - QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget); + QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>(); if (browser && o == browser->viewport() && e->type() == QEvent::MouseButtonRelease){ QMouseEvent *me = static_cast<QMouseEvent*>(e); @@ -196,7 +183,7 @@ void SearchWidget::contextMenuEvent(QContextMenuEvent *contextMenuEvent) QMenu menu; QPoint point = contextMenuEvent->globalPos(); - QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget); + QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>(); if (!browser) return; diff --git a/tools/assistant/tools/assistant/searchwidget.h b/tools/assistant/tools/assistant/searchwidget.h index 750497b..04d3e28 100644 --- a/tools/assistant/tools/assistant/searchwidget.h +++ b/tools/assistant/tools/assistant/searchwidget.h @@ -65,9 +65,6 @@ public: void zoomOut(); void resetZoom(); - bool isAttached() const; - void setAttached(bool state); - signals: void requestShowLink(const QUrl &url); void requestShowLinkInNewTab(const QUrl &url); @@ -84,7 +81,6 @@ private: private: int zoomCount; - bool attached; QHelpSearchEngine *searchEngine; QHelpSearchResultWidget *resultWidget; }; diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index a2c7fe9..7ca5703 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -1933,6 +1933,22 @@ QString Configure::findFileInPaths(const QString &fileName, const QString &paths return QString(); } +static QString mingwPaths(const QString &mingwPath, const QString &pathName) +{ + QString ret; + QDir mingwDir = QFileInfo(mingwPath).dir(); + const QFileInfoList subdirs = mingwDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + for (int i = 0 ;i < subdirs.length(); ++i) { + const QFileInfo &fi = subdirs.at(i); + const QString name = fi.fileName(); + if (name == pathName) + ret += fi.absoluteFilePath() + ';'; + else if (name.contains("mingw")) + ret += fi.absoluteFilePath() + QDir::separator() + pathName + ';'; + } + return ret; +} + bool Configure::findFile(const QString &fileName) { const QString file = fileName.toLower(); @@ -1943,18 +1959,22 @@ bool Configure::findFile(const QString &fileName) QString paths; if (file.endsWith(".h")) { if (!mingwPath.isNull()) { - if (!findFileInPaths(file, mingwPath + QLatin1String("/../include")).isNull()) + if (!findFileInPaths(file, mingwPaths(mingwPath, "include")).isNull()) return true; //now let's try the additional compiler path - QDir mingwLibDir = mingwPath + QLatin1String("/../lib/gcc/mingw32"); - foreach(const QFileInfo &version, mingwLibDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) { - if (!findFileInPaths(file, version.absoluteFilePath() + QLatin1String("/include")).isNull()) - return true; + + const QFileInfoList mingwConfigs = QDir(mingwPath + QLatin1String("/../lib/gcc")).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + for (int i = 0; i < mingwConfigs.length(); ++i) { + const QDir mingwLibDir = mingwConfigs.at(i).absoluteFilePath(); + foreach(const QFileInfo &version, mingwLibDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) { + if (!findFileInPaths(file, version.absoluteFilePath() + QLatin1String("/include")).isNull()) + return true; + } } } paths = QString::fromLocal8Bit(getenv("INCLUDE")); } else if (file.endsWith(".lib") || file.endsWith(".a")) { - if (!mingwPath.isNull() && !findFileInPaths(file, mingwPath + QLatin1String("/../lib")).isNull()) + if (!mingwPath.isNull() && !findFileInPaths(file, mingwPaths(mingwPath, "lib")).isNull()) return true; paths = QString::fromLocal8Bit(getenv("LIB")); } else { @@ -2107,12 +2127,7 @@ bool Configure::checkAvailability(const QString &part) else if (part == "INCREDIBUILD_XGE") available = findFile("BuildConsole.exe") && findFile("xgConsole.exe"); else if (part == "XMLPATTERNS") - { - /* MSVC 6.0 and MSVC 2002/7.0 has too poor C++ support for QtXmlPatterns. */ - return dictionary.value("QMAKESPEC") != "win32-msvc" - && dictionary.value("QMAKESPEC") != "win32-msvc.net" // Leave for now, since we can't be sure if they are using 2002 or 2003 with this spec - && dictionary.value("QMAKESPEC") != "win32-msvc2002" - && dictionary.value("EXCEPTIONS") == "yes"; + available = dictionary.value("EXCEPTIONS") == "yes"; } else if (part == "PHONON") { if (dictionary.contains("XQMAKESPEC") && dictionary["XQMAKESPEC"].startsWith("symbian")) { available = true; @@ -3065,10 +3080,7 @@ void Configure::generateConfigfiles() tmpStream << "/* Machine byte-order */" << endl; tmpStream << "#define Q_BIG_ENDIAN 4321" << endl; tmpStream << "#define Q_LITTLE_ENDIAN 1234" << endl; - if (QSysInfo::ByteOrder == QSysInfo::BigEndian) - tmpStream << "#define Q_BYTE_ORDER Q_BIG_ENDIAN" << endl; - else - tmpStream << "#define Q_BYTE_ORDER Q_LITTLE_ENDIAN" << endl; + tmpStream << "#define Q_BYTE_ORDER Q_LITTLE_ENDIAN" << endl; tmpStream << endl << "// Compile time features" << endl; tmpStream << "#define QT_ARCH_" << dictionary["ARCHITECTURE"].toUpper() << endl; diff --git a/tools/configure/environment.cpp b/tools/configure/environment.cpp index 03fd0cc..9446864 100644 --- a/tools/configure/environment.cpp +++ b/tools/configure/environment.cpp @@ -75,8 +75,6 @@ struct CompilerInfo{ {CC_BORLAND, "Borland C++", 0, "bcc32.exe"}, {CC_MINGW, "MinGW (Minimalist GNU for Windows)", 0, "g++.exe"}, {CC_INTEL, "Intel(R) C++ Compiler for 32-bit applications", 0, "icl.exe"}, // xilink.exe, xilink5.exe, xilink6.exe, xilib.exe - {CC_MSVC6, "Microsoft (R) 32-bit C/C++ Optimizing Compiler (6.x)", "Software\\Microsoft\\VisualStudio\\6.0\\Setup\\Microsoft Visual C++\\ProductDir", "cl.exe"}, // link.exe, lib.exe - {CC_NET2002, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2002 (7.0)", "Software\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir", "cl.exe"}, // link.exe, lib.exe {CC_NET2003, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2003 (7.1)", "Software\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir", "cl.exe"}, // link.exe, lib.exe {CC_NET2005, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2005 (8.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\8.0", "cl.exe"}, // link.exe, lib.exe {CC_NET2008, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2008 (9.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\9.0", "cl.exe"}, // link.exe, lib.exe @@ -118,14 +116,6 @@ QString Environment::detectQMakeSpec() case CC_NET2003: spec = "win32-msvc2003"; break; - case CC_NET2002: - spec = "win32-msvc2002"; - break; - case CC_MSVC4: - case CC_MSVC5: - case CC_MSVC6: - spec = "win32-msvc"; - break; case CC_INTEL: spec = "win32-icc"; break; @@ -152,7 +142,7 @@ QString Environment::detectQMakeSpec() Compiler Environment::detectCompiler() { #ifndef Q_OS_WIN32 - return MSVC6; // Always generate MSVC 6.0 versions on other platforms + return CC_UNKNOWN; // Always generate CC_UNKNOWN on other platforms #else if(detectedCompiler != CC_UNKNOWN) return detectedCompiler; diff --git a/tools/configure/environment.h b/tools/configure/environment.h index 16af8df..9efaea1 100644 --- a/tools/configure/environment.h +++ b/tools/configure/environment.h @@ -50,10 +50,6 @@ enum Compiler { CC_BORLAND = 0x01, CC_MINGW = 0x02, CC_INTEL = 0x03, - CC_MSVC4 = 0x40, - CC_MSVC5 = 0x50, - CC_MSVC6 = 0x60, - CC_NET2002 = 0x70, CC_NET2003 = 0x71, CC_NET2005 = 0x80, CC_NET2008 = 0x90, diff --git a/tools/designer/data/ui4.xsd b/tools/designer/data/ui4.xsd index de4253c..fc9c120 100644 --- a/tools/designer/data/ui4.xsd +++ b/tools/designer/data/ui4.xsd @@ -414,7 +414,7 @@ <xs:complexType name="StringList"> <xs:sequence> - <xs:element name="string" type="xs:string" maxOccurs="unbounded" /> + <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> @@ -434,6 +434,7 @@ <xs:element name="selectedoff" type="ResourcePixmap" minOccurs="0" /> <xs:element name="selectedon" type="ResourcePixmap" minOccurs="0" /> </xs:all> + <xs:attribute name="theme" type="xs:string" /> <xs:attribute name="resource" type="xs:string" /> <!-- pre 4.4 legacy support --> </xs:complexType> diff --git a/tools/designer/src/components/buddyeditor/buddyeditor.cpp b/tools/designer/src/components/buddyeditor/buddyeditor.cpp index e367f9a..4127d7c 100644 --- a/tools/designer/src/components/buddyeditor/buddyeditor.cpp +++ b/tools/designer/src/components/buddyeditor/buddyeditor.cpp @@ -153,13 +153,13 @@ void BuddyEditor::updateBackground() m_updating = true; QList<Connection *> newList; - const LabelList label_list = qFindChildren<QLabel*>(background()); + const LabelList label_list = background()->findChildren<QLabel*>(); foreach (QLabel *label, label_list) { const QString buddy_name = buddy(label, m_formWindow->core()); if (buddy_name.isEmpty()) continue; - const QList<QWidget *> targets = qFindChildren<QWidget*>(background(), buddy_name); + const QList<QWidget *> targets = background()->findChildren<QWidget*>(buddy_name); if (targets.isEmpty()) continue; @@ -238,12 +238,12 @@ void BuddyEditor::setBackground(QWidget *background) clear(); ConnectionEdit::setBackground(background); - const LabelList label_list = qFindChildren<QLabel*>(background); + const LabelList label_list = background->findChildren<QLabel*>(); foreach (QLabel *label, label_list) { const QString buddy_name = buddy(label, m_formWindow->core()); if (buddy_name.isEmpty()) continue; - QWidget *target = qFindChild<QWidget*>(background, buddy_name); + QWidget *target = background->findChild<QWidget*>(buddy_name); if (target == 0) continue; @@ -297,7 +297,7 @@ void BuddyEditor::endConnection(QWidget *target, const QPoint &pos) void BuddyEditor::widgetRemoved(QWidget *widget) { - QList<QWidget*> child_list = qFindChildren<QWidget*>(widget); + QList<QWidget*> child_list = widget->findChildren<QWidget*>(); child_list.prepend(widget); ConnectionSet remove_set; @@ -354,7 +354,7 @@ void BuddyEditor::deleteSelected() void BuddyEditor::autoBuddy() { // Any labels? - LabelList labelList = qFindChildren<QLabel*>(background()); + LabelList labelList = background()->findChildren<QLabel*>(); if (labelList.empty()) return; // Find already used buddies diff --git a/tools/designer/src/components/formeditor/dpi_chooser.cpp b/tools/designer/src/components/formeditor/dpi_chooser.cpp index e79c757..1eadfa5 100644 --- a/tools/designer/src/components/formeditor/dpi_chooser.cpp +++ b/tools/designer/src/components/formeditor/dpi_chooser.cpp @@ -97,13 +97,13 @@ DPI_Chooser::DPI_Chooser(QWidget *parent) : m_systemEntry->description = 0; const struct DPI_Entry *systemEntry = m_systemEntry; //: System resolution - m_predefinedCombo->addItem(tr("System (%1 x %2)").arg(m_systemEntry->dpiX).arg(m_systemEntry->dpiY), qVariantFromValue(systemEntry)); + m_predefinedCombo->addItem(tr("System (%1 x %2)").arg(m_systemEntry->dpiX).arg(m_systemEntry->dpiY), QVariant::fromValue(systemEntry)); // Devices. Exclude the system values as not to duplicate the entries const int predefinedCount = sizeof(dpiEntries)/sizeof(DPI_Entry); const struct DPI_Entry *ecend = dpiEntries + predefinedCount; for (const struct DPI_Entry *it = dpiEntries; it < ecend; ++it) if (it->dpiX != m_systemEntry->dpiX || it->dpiY != m_systemEntry->dpiY) - m_predefinedCombo->addItem(tr(it->description), qVariantFromValue(it)); + m_predefinedCombo->addItem(tr(it->description), QVariant::fromValue(it)); m_predefinedCombo->addItem(tr("User defined")); setFocusProxy(m_predefinedCombo); diff --git a/tools/designer/src/components/formeditor/formeditor.qrc b/tools/designer/src/components/formeditor/formeditor.qrc index 42724dd..e42cc66 100644 --- a/tools/designer/src/components/formeditor/formeditor.qrc +++ b/tools/designer/src/components/formeditor/formeditor.qrc @@ -152,6 +152,7 @@ <file>images/win/textjustify.png</file> <file>images/win/textsuperscript.png</file> <file>images/win/textsubscript.png</file> + <file>images/win/simplifyrichtext.png</file> <file>images/win/back.png</file> <file>images/win/forward.png</file> <file>images/win/down.png</file> @@ -166,6 +167,7 @@ <file>images/mac/textjustify.png</file> <file>images/mac/textsuperscript.png</file> <file>images/mac/textsubscript.png</file> + <file>images/mac/simplifyrichtext.png</file> </qresource> <qresource prefix="/trolltech/brushes"> <file>defaultbrushes.xml</file> diff --git a/tools/designer/src/components/formeditor/formwindow.cpp b/tools/designer/src/components/formeditor/formwindow.cpp index 15775f6..ebf00f9 100644 --- a/tools/designer/src/components/formeditor/formwindow.cpp +++ b/tools/designer/src/components/formeditor/formwindow.cpp @@ -387,7 +387,7 @@ void FormWindow::setCursorToAll(const QCursor &c, QWidget *start) { #ifndef QT_NO_CURSOR start->setCursor(c); - const QWidgetList widgets = qFindChildren<QWidget*>(start); + const QWidgetList widgets = start->findChildren<QWidget*>(); foreach (QWidget *widget, widgets) { if (!qobject_cast<WidgetHandle*>(widget)) { widget->setCursor(c); @@ -945,7 +945,7 @@ bool FormWindow::isMainContainer(const QWidget *w) const void FormWindow::updateChildSelections(QWidget *w) { - const QWidgetList l = qFindChildren<QWidget*>(w); + const QWidgetList l = w->findChildren<QWidget*>(); if (!l.empty()) { const QWidgetList::const_iterator lcend = l.constEnd(); for (QWidgetList::const_iterator it = l.constBegin(); it != lcend; ++it) { @@ -1155,19 +1155,19 @@ bool FormWindow::unify(QObject *w, QString &s, bool changeIt) existingNames.insert(main->objectName()); const QDesignerMetaDataBaseInterface *metaDataBase = core()->metaDataBase(); - const QWidgetList widgetChildren = qFindChildren<QWidget*>(main); + const QWidgetList widgetChildren = main->findChildren<QWidget*>(); if (!widgetChildren.empty()) insertNames(metaDataBase, widgetChildren.constBegin(), widgetChildren.constEnd(), w, existingNames); - const QList<QLayout *> layoutChildren = qFindChildren<QLayout*>(main); + const QList<QLayout *> layoutChildren = main->findChildren<QLayout*>(); if (!layoutChildren.empty()) insertNames(metaDataBase, layoutChildren.constBegin(), layoutChildren.constEnd(), w, existingNames); - const QList<QAction *> actionChildren = qFindChildren<QAction*>(main); + const QList<QAction *> actionChildren = main->findChildren<QAction*>(); if (!actionChildren.empty()) insertNames(metaDataBase, actionChildren.constBegin(), actionChildren.constEnd(), w, existingNames); - const QList<QButtonGroup *> buttonGroupChildren = qFindChildren<QButtonGroup*>(main); + const QList<QButtonGroup *> buttonGroupChildren = main->findChildren<QButtonGroup*>(); if (!buttonGroupChildren.empty()) insertNames(metaDataBase, buttonGroupChildren.constBegin(), buttonGroupChildren.constEnd(), w, existingNames); @@ -1283,7 +1283,7 @@ void FormWindow::resizeWidget(QWidget *widget, const QRect &geometry) void FormWindow::raiseChildSelections(QWidget *w) { - const QWidgetList l = qFindChildren<QWidget*>(w); + const QWidgetList l = w->findChildren<QWidget*>(); if (l.isEmpty()) return; m_selection->raiseList(l); @@ -1344,7 +1344,7 @@ QWidgetList FormWindow::selectedWidgets() const void FormWindow::selectWidgets() { bool selectionChanged = false; - const QWidgetList l = qFindChildren<QWidget*>(mainContainer()); + const QWidgetList l = mainContainer()->findChildren<QWidget*>(); QListIterator <QWidget*> it(l); const QRect selRect(mapToGlobal(m_currRect.topLeft()), m_currRect.size()); while (it.hasNext()) { @@ -1523,7 +1523,7 @@ void ArrowKeyPropertyCommand::init(QWidgetList &l, const ArrowKeyOperation &op) QObjectList ol; foreach(QWidget *w, l) ol.push_back(w); - SetPropertyCommand::init(ol, QLatin1String("geometry"), qVariantFromValue(op)); + SetPropertyCommand::init(ol, QLatin1String("geometry"), QVariant::fromValue(op)); setText(op.resize ? FormWindow::tr("Key Resize") : FormWindow::tr("Key Move")); } @@ -1531,14 +1531,14 @@ void ArrowKeyPropertyCommand::init(QWidgetList &l, const ArrowKeyOperation &op) QVariant ArrowKeyPropertyCommand::mergeValue(const QVariant &newMergeValue) { // Merge move operations of the same arrow key - if (!qVariantCanConvert<ArrowKeyOperation>(newMergeValue)) + if (!newMergeValue.canConvert<ArrowKeyOperation>()) return QVariant(); ArrowKeyOperation mergedOperation = qvariant_cast<ArrowKeyOperation>(newValue()); const ArrowKeyOperation newMergeOperation = qvariant_cast<ArrowKeyOperation>(newMergeValue); if (mergedOperation.resize != newMergeOperation.resize || mergedOperation.arrowKey != newMergeOperation.arrowKey) return QVariant(); mergedOperation.distance += newMergeOperation.distance; - return qVariantFromValue(mergedOperation); + return QVariant::fromValue(mergedOperation); } void FormWindow::handleArrowKeyEvent(int key, Qt::KeyboardModifiers modifiers) @@ -2241,7 +2241,7 @@ QAction *FormWindow::createSelectAncestorSubMenu(QWidget *w) for (int i = 0; i < size; i++) { QWidget *w = parents.at(i); QAction *a = ag->addAction(objectNameOf(w)); - a->setData(qVariantFromValue(w)); + a->setData(QVariant::fromValue(w)); menu->addAction(a); } QAction *ma = new QAction(tr("Select Ancestor"), 0); @@ -2796,7 +2796,7 @@ bool FormWindow::dropDockWidget(QDesignerDnDItemInterface *item, const QPoint &g PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(propertySheet->property(propertySheet->indexOf(dockWidgetAreaName))); e.value = area; QVariant v; - qVariantSetValue(v, e); + v.setValue(e); SetPropertyCommand *cmd = new SetPropertyCommand(this); cmd->init(widget, dockWidgetAreaName, v); m_undoStack.push(cmd); diff --git a/tools/designer/src/components/formeditor/images/mac/simplifyrichtext.png b/tools/designer/src/components/formeditor/images/mac/simplifyrichtext.png Binary files differnew file mode 100644 index 0000000..a48e974 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/simplifyrichtext.png diff --git a/tools/designer/src/components/formeditor/images/win/simplifyrichtext.png b/tools/designer/src/components/formeditor/images/win/simplifyrichtext.png Binary files differnew file mode 100644 index 0000000..e251cf7 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/simplifyrichtext.png diff --git a/tools/designer/src/components/formeditor/qdesigner_resource.cpp b/tools/designer/src/components/formeditor/qdesigner_resource.cpp index 1d78695..a29bc1f 100644 --- a/tools/designer/src/components/formeditor/qdesigner_resource.cpp +++ b/tools/designer/src/components/formeditor/qdesigner_resource.cpp @@ -171,7 +171,7 @@ QDesignerResourceBuilder::QDesignerResourceBuilder(QDesignerFormEditorInterface { } -static inline void setIconPixmap(QIcon::Mode m, QIcon::State s, const QDir &workingDirectory, +static inline void setIconPixmap(QIcon::Mode m, QIcon::State s, const QDir &workingDirectory, QString path, PropertySheetIconValue &icon, const QDesignerLanguageExtension *lang = 0) { @@ -197,12 +197,13 @@ QVariant QDesignerResourceBuilder::loadResource(const QDir &workingDirectory, co m_loadedQrcFiles.insert(QFileInfo(workingDirectory, dp->attributeResource()).absoluteFilePath(), false); #endif } - return qVariantFromValue(pixmap); + return QVariant::fromValue(pixmap); } case DomProperty::IconSet: { PropertySheetIconValue icon; DomResourceIcon *di = property->elementIconSet(); + icon.setTheme(di->attributeTheme()); if (const int flags = iconStateFlags(di)) { // new, post 4.4 format if (flags & NormalOff) setIconPixmap(QIcon::Normal, QIcon::Off, workingDirectory, di->elementNormalOff()->text(), icon, m_lang); @@ -227,7 +228,7 @@ QVariant QDesignerResourceBuilder::loadResource(const QDir &workingDirectory, co m_loadedQrcFiles.insert(QFileInfo(workingDirectory, di->attributeResource()).absoluteFilePath(), false); #endif } - return qVariantFromValue(icon); + return QVariant::fromValue(icon); } default: break; @@ -237,12 +238,12 @@ QVariant QDesignerResourceBuilder::loadResource(const QDir &workingDirectory, co QVariant QDesignerResourceBuilder::toNativeValue(const QVariant &value) const { - if (qVariantCanConvert<PropertySheetPixmapValue>(value)) { + if (value.canConvert<PropertySheetPixmapValue>()) { if (m_pixmapCache) - return m_pixmapCache->pixmap(qVariantValue<PropertySheetPixmapValue>(value)); - } else if (qVariantCanConvert<PropertySheetIconValue>(value)) { + return m_pixmapCache->pixmap(qvariant_cast<PropertySheetPixmapValue>(value)); + } else if (value.canConvert<PropertySheetIconValue>()) { if (m_iconCache) - return m_iconCache->icon(qVariantValue<PropertySheetIconValue>(value)); + return m_iconCache->icon(qvariant_cast<PropertySheetIconValue>(value)); } return value; } @@ -250,7 +251,7 @@ QVariant QDesignerResourceBuilder::toNativeValue(const QVariant &value) const DomProperty *QDesignerResourceBuilder::saveResource(const QDir &workingDirectory, const QVariant &value) const { DomProperty *p = new DomProperty; - if (qVariantCanConvert<PropertySheetPixmapValue>(value)) { + if (value.canConvert<PropertySheetPixmapValue>()) { const PropertySheetPixmapValue pix = qvariant_cast<PropertySheetPixmapValue>(value); DomResourcePixmap *rp = new DomResourcePixmap; const QString pixPath = pix.path(); @@ -275,11 +276,14 @@ DomProperty *QDesignerResourceBuilder::saveResource(const QDir &workingDirectory } p->setElementPixmap(rp); return p; - } else if (qVariantCanConvert<PropertySheetIconValue>(value)) { + } else if (value.canConvert<PropertySheetIconValue>()) { const PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(value); const QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> pixmaps = icon.paths(); - if (!pixmaps.isEmpty()) { + const QString theme = icon.theme(); + if (!pixmaps.isEmpty() || !theme.isEmpty()) { DomResourceIcon *ri = new DomResourceIcon; + if (!theme.isEmpty()) + ri->setAttributeTheme(theme); QMapIterator<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> itPix(pixmaps); while (itPix.hasNext()) { const QIcon::Mode mode = itPix.next().key().first; @@ -331,7 +335,7 @@ DomProperty *QDesignerResourceBuilder::saveResource(const QDir &workingDirectory bool QDesignerResourceBuilder::isResourceType(const QVariant &value) const { - if (qVariantCanConvert<PropertySheetPixmapValue>(value) || qVariantCanConvert<PropertySheetIconValue>(value)) + if (value.canConvert<PropertySheetPixmapValue>() || value.canConvert<PropertySheetIconValue>()) return true; return false; } @@ -364,26 +368,26 @@ QVariant QDesignerTextBuilder::loadText(const DomProperty *text) const if (!translatable) strVal.setTranslatable(translatable); } - return qVariantFromValue(strVal); + return QVariant::fromValue(strVal); } QVariant QDesignerTextBuilder::toNativeValue(const QVariant &value) const { - if (qVariantCanConvert<PropertySheetStringValue>(value)) - return qVariantFromValue(qVariantValue<PropertySheetStringValue>(value).value()); + if (value.canConvert<PropertySheetStringValue>()) + return QVariant::fromValue(qvariant_cast<PropertySheetStringValue>(value).value()); return value; } DomProperty *QDesignerTextBuilder::saveText(const QVariant &value) const { - if (!qVariantCanConvert<PropertySheetStringValue>(value) && !qVariantCanConvert<QString>(value)) + if (!value.canConvert<PropertySheetStringValue>() && !value.canConvert<QString>()) return 0; DomProperty *property = new DomProperty(); DomString *domStr = new DomString(); - if (qVariantCanConvert<PropertySheetStringValue>(value)) { - PropertySheetStringValue str = qVariantValue<PropertySheetStringValue>(value); + if (value.canConvert<PropertySheetStringValue>()) { + PropertySheetStringValue str = qvariant_cast<PropertySheetStringValue>(value); domStr->setText(str.value()); @@ -475,7 +479,7 @@ void QDesignerResource::saveDom(DomUI *ui, QWidget *widget) if (classVar.canConvert(QVariant::String)) classStr = classVar.toString(); else - classStr = qVariantValue<PropertySheetStringValue>(classVar).value(); + classStr = qvariant_cast<PropertySheetStringValue>(classVar).value(); ui->setElementClass(classStr); for (int index = 0; index < m_formWindow->toolCount(); ++index) { @@ -946,7 +950,7 @@ QWidget *QDesignerResource::create(DomWidget *ui_widget, QWidget *parentWidget) w->addAction(a); } else if (QActionGroup *g = m_actionGroups.value(name)) { w->addActions(g->actions()); - } else if (QMenu *menu = qFindChild<QMenu*>(w, name)) { + } else if (QMenu *menu = w->findChild<QMenu*>(name)) { w->addAction(menu->menuAction()); addMenuAction(menu->menuAction()); } @@ -1045,7 +1049,7 @@ static bool readDomEnumerationValue(const DomProperty *p, switch (p->kind()) { case DomProperty::Set: { const QVariant sheetValue = sheet->property(index); - if (qVariantCanConvert<PropertySheetFlagValue>(sheetValue)) { + if (sheetValue.canConvert<PropertySheetFlagValue>()) { const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(sheetValue); bool ok = false; v = f.metaFlags.parseFlags(p->elementSet(), &ok); @@ -1057,7 +1061,7 @@ static bool readDomEnumerationValue(const DomProperty *p, break; case DomProperty::Enum: { const QVariant sheetValue = sheet->property(index); - if (qVariantCanConvert<PropertySheetEnumValue>(sheetValue)) { + if (sheetValue.canConvert<PropertySheetEnumValue>()) { const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(sheetValue); bool ok = false; v = e.metaEnum.parseEnum(p->elementEnum(), &ok); @@ -1110,7 +1114,7 @@ void QDesignerResource::applyProperties(QObject *o, const QList<DomProperty*> &p if (!translatable) keyVal.setTranslatable(translatable); } - v = qVariantFromValue(keyVal); + v = QVariant::fromValue(keyVal); } else { const DomString *str = p->elementString(); PropertySheetStringValue strVal(v.toString()); @@ -1124,7 +1128,7 @@ void QDesignerResource::applyProperties(QObject *o, const QList<DomProperty*> &p if (!translatable) strVal.setTranslatable(translatable); } - v = qVariantFromValue(strVal); + v = QVariant::fromValue(strVal); } } @@ -1135,18 +1139,18 @@ void QDesignerResource::applyProperties(QObject *o, const QList<DomProperty*> &p } else if (dynamicPropertiesAllowed) { QVariant defaultValue = QVariant(v.type()); bool isDefault = (v == defaultValue); - if (qVariantCanConvert<PropertySheetIconValue>(v)) { + if (v.canConvert<PropertySheetIconValue>()) { defaultValue = QVariant(QVariant::Icon); - isDefault = (qVariantValue<PropertySheetIconValue>(v) == PropertySheetIconValue()); - } else if (qVariantCanConvert<PropertySheetPixmapValue>(v)) { + isDefault = (qvariant_cast<PropertySheetIconValue>(v) == PropertySheetIconValue()); + } else if (v.canConvert<PropertySheetPixmapValue>()) { defaultValue = QVariant(QVariant::Pixmap); - isDefault = (qVariantValue<PropertySheetPixmapValue>(v) == PropertySheetPixmapValue()); - } else if (qVariantCanConvert<PropertySheetStringValue>(v)) { + isDefault = (qvariant_cast<PropertySheetPixmapValue>(v) == PropertySheetPixmapValue()); + } else if (v.canConvert<PropertySheetStringValue>()) { defaultValue = QVariant(QVariant::String); - isDefault = (qVariantValue<PropertySheetStringValue>(v) == PropertySheetStringValue()); - } else if (qVariantCanConvert<PropertySheetKeySequenceValue>(v)) { + isDefault = (qvariant_cast<PropertySheetStringValue>(v) == PropertySheetStringValue()); + } else if (v.canConvert<PropertySheetKeySequenceValue>()) { defaultValue = QVariant(QVariant::KeySequence); - isDefault = (qVariantValue<PropertySheetKeySequenceValue>(v) == PropertySheetKeySequenceValue()); + isDefault = (qvariant_cast<PropertySheetKeySequenceValue>(v) == PropertySheetKeySequenceValue()); } if (defaultValue.type() != QVariant::UserType) { const int idx = dynamicSheet->addDynamicProperty(p->attributeName(), defaultValue); @@ -1185,12 +1189,12 @@ QWidget *QDesignerResource::createWidget(const QString &widgetName, QWidget *par if (!qobject_cast<QMenu*>(w) && (!parentWidget || !container)) { m_formWindow->manageWidget(w); if (parentWidget) { - QList<QWidget *> list = qVariantValue<QWidgetList>(parentWidget->property("_q_widgetOrder")); + QList<QWidget *> list = qvariant_cast<QWidgetList>(parentWidget->property("_q_widgetOrder")); list.append(w); - parentWidget->setProperty("_q_widgetOrder", qVariantFromValue(list)); - QList<QWidget *> zOrder = qVariantValue<QWidgetList>(parentWidget->property("_q_zOrder")); + parentWidget->setProperty("_q_widgetOrder", QVariant::fromValue(list)); + QList<QWidget *> zOrder = qvariant_cast<QWidgetList>(parentWidget->property("_q_zOrder")); zOrder.append(w); - parentWidget->setProperty("_q_zOrder", qVariantFromValue(list)); + parentWidget->setProperty("_q_zOrder", QVariant::fromValue(list)); } } else { core()->metaDataBase()->add(w); @@ -1320,7 +1324,7 @@ DomLayout *QDesignerResource::createDom(QLayout *layout, DomLayout *ui_parentLay QDesignerMetaDataBaseItemInterface *item = core()->metaDataBase()->item(layout); if (item == 0) { - layout = qFindChild<QLayout*>(layout); + layout = layout->findChild<QLayout*>(); // refresh the meta database item item = core()->metaDataBase()->item(layout); } @@ -1440,7 +1444,7 @@ void QDesignerResource::applyTabStops(QWidget *widget, DomTabStops *tabStops) QList<QWidget*> tabOrder; foreach (const QString &widgetName, tabStops->elementTabStop()) { - if (QWidget *w = qFindChild<QWidget*>(widget, widgetName)) { + if (QWidget *w = widget->findChild<QWidget*>(widgetName)) { tabOrder.append(w); } } @@ -1605,8 +1609,8 @@ DomWidget *QDesignerResource::saveWidget(QTabWidget *widget, DomWidget *ui_paren // attribute `icon' widget->setCurrentIndex(i); QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), widget); - PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String("currentTabIcon")))); - DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), qVariantFromValue(icon)); + PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String("currentTabIcon")))); + DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), QVariant::fromValue(icon)); if (p) { p->setAttributeName(strings.iconAttribute); ui_attribute_list.append(p); @@ -1620,7 +1624,7 @@ DomWidget *QDesignerResource::saveWidget(QTabWidget *widget, DomWidget *ui_paren // attribute `toolTip' QVariant v = sheet->property(sheet->indexOf(QLatin1String("currentTabToolTip"))); - if (!qVariantValue<PropertySheetStringValue>(v).value().isEmpty()) { + if (!qvariant_cast<PropertySheetStringValue>(v).value().isEmpty()) { p = textBuilder()->saveText(v); if (p) { p->setAttributeName(strings.toolTipAttribute); @@ -1630,7 +1634,7 @@ DomWidget *QDesignerResource::saveWidget(QTabWidget *widget, DomWidget *ui_paren // attribute `whatsThis' v = sheet->property(sheet->indexOf(QLatin1String("currentTabWhatsThis"))); - if (!qVariantValue<PropertySheetStringValue>(v).value().isEmpty()) { + if (!qvariant_cast<PropertySheetStringValue>(v).value().isEmpty()) { p = textBuilder()->saveText(v); if (p) { p->setAttributeName(strings.whatsThisAttribute); @@ -1676,8 +1680,8 @@ DomWidget *QDesignerResource::saveWidget(QToolBox *widget, DomWidget *ui_parentW // attribute `icon' widget->setCurrentIndex(i); QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), widget); - PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String("currentItemIcon")))); - DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), qVariantFromValue(icon)); + PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String("currentItemIcon")))); + DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), QVariant::fromValue(icon)); if (p) { p->setAttributeName(strings.iconAttribute); ui_attribute_list.append(p); @@ -1690,7 +1694,7 @@ DomWidget *QDesignerResource::saveWidget(QToolBox *widget, DomWidget *ui_parentW // attribute `toolTip' QVariant v = sheet->property(sheet->indexOf(QLatin1String("currentItemToolTip"))); - if (!qVariantValue<PropertySheetStringValue>(v).value().isEmpty()) { + if (!qvariant_cast<PropertySheetStringValue>(v).value().isEmpty()) { p = textBuilder()->saveText(v); if (p) { p->setAttributeName(strings.toolTipAttribute); @@ -2209,8 +2213,8 @@ DomProperty *QDesignerResource::createProperty(QObject *object, const QString &p return 0; } - if (qVariantCanConvert<PropertySheetFlagValue>(value)) { - const PropertySheetFlagValue f = qVariantValue<PropertySheetFlagValue>(value); + if (value.canConvert<PropertySheetFlagValue>()) { + const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(value); const QString flagString = f.metaFlags.toString(f.value, DesignerMetaFlags::FullyQualified); if (flagString.isEmpty()) return 0; @@ -2222,8 +2226,8 @@ DomProperty *QDesignerResource::createProperty(QObject *object, const QString &p p->setAttributeName(propertyName); p->setElementSet(flagString); return applyProperStdSetAttribute(object, propertyName, p); - } else if (qVariantCanConvert<PropertySheetEnumValue>(value)) { - const PropertySheetEnumValue e = qVariantValue<PropertySheetEnumValue>(value); + } else if (value.canConvert<PropertySheetEnumValue>()) { + const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(value); bool ok; const QString id = e.metaEnum.toString(e.value, DesignerMetaEnum::FullyQualified, &ok); if (!ok) @@ -2238,8 +2242,8 @@ DomProperty *QDesignerResource::createProperty(QObject *object, const QString &p p->setAttributeName(propertyName); p->setElementEnum(id); return applyProperStdSetAttribute(object, propertyName, p); - } else if (qVariantCanConvert<PropertySheetStringValue>(value)) { - const PropertySheetStringValue strVal = qVariantValue<PropertySheetStringValue>(value); + } else if (value.canConvert<PropertySheetStringValue>()) { + const PropertySheetStringValue strVal = qvariant_cast<PropertySheetStringValue>(value); DomProperty *p = new DomProperty; if (!hasSetter(core(), object, propertyName)) p->setAttributeStdset(0); @@ -2249,8 +2253,8 @@ DomProperty *QDesignerResource::createProperty(QObject *object, const QString &p saveStringProperty(p, strVal); return applyProperStdSetAttribute(object, propertyName, p); - } else if (qVariantCanConvert<PropertySheetKeySequenceValue>(value)) { - const PropertySheetKeySequenceValue keyVal = qVariantValue<PropertySheetKeySequenceValue>(value); + } else if (value.canConvert<PropertySheetKeySequenceValue>()) { + const PropertySheetKeySequenceValue keyVal = qvariant_cast<PropertySheetKeySequenceValue>(value); DomProperty *p = new DomProperty; if (!hasSetter(core(), object, propertyName)) p->setAttributeStdset(0); diff --git a/tools/designer/src/components/formeditor/qmainwindow_container.cpp b/tools/designer/src/components/formeditor/qmainwindow_container.cpp index 9b5326a..ef4ce85 100644 --- a/tools/designer/src/components/formeditor/qmainwindow_container.cpp +++ b/tools/designer/src/components/formeditor/qmainwindow_container.cpp @@ -104,7 +104,7 @@ Qt::DockWidgetArea dockWidgetArea(QDockWidget *me) QList<QLayout*> candidates; if (mw->layout()) { candidates.append(mw->layout()); - candidates += qFindChildren<QLayout*>(mw->layout()); + candidates += mw->layout()->findChildren<QLayout*>(); } foreach (QLayout *l, candidates) { if (l->indexOf(me) != -1) { diff --git a/tools/designer/src/components/objectinspector/objectinspectormodel.cpp b/tools/designer/src/components/objectinspector/objectinspectormodel.cpp index 93e1df1..4bbacdb 100644 --- a/tools/designer/src/components/objectinspector/objectinspectormodel.cpp +++ b/tools/designer/src/components/objectinspector/objectinspectormodel.cpp @@ -273,7 +273,7 @@ namespace qdesigner_internal { void ObjectData::setItems(const StandardItemList &row, const ObjectInspectorIcons &icons) const { - const QVariant object = qVariantFromValue(m_object); + const QVariant object = QVariant::fromValue(m_object); row[ObjectInspectorModel::ObjectNameColumn]->setData(object, DataRole); row[ObjectInspectorModel::ClassNameColumn]->setData(object, DataRole); setItemsDisplayData(row, icons, ClassNameChanged|ObjectNameChanged|ClassIconChanged|TypeChanged|LayoutTypeChanged); diff --git a/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp b/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp index 2300b47..fffdc29 100644 --- a/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp +++ b/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp @@ -163,7 +163,7 @@ void BrushPropertyManager::initializeProperty(QtVariantPropertyManager *vm, QtPr for (int i = 0; i < brushStyleCount; i++) styles.push_back(QCoreApplication::translate("BrushPropertyManager", brushStyles[i])); styleSubProperty->setAttribute(QLatin1String("enumNames"), styles); - styleSubProperty->setAttribute(QLatin1String("enumIcons"), qVariantFromValue(brushStyleIcons())); + styleSubProperty->setAttribute(QLatin1String("enumIcons"), QVariant::fromValue(brushStyleIcons())); m_brushPropertyToStyleSubProperty.insert(property, styleSubProperty); m_brushStyleSubPropertyToProperty.insert(styleSubProperty, property); // color diff --git a/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp b/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp index 9ab2940..8e7312f 100644 --- a/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp +++ b/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp @@ -83,6 +83,7 @@ static const char *validationModesAttributeC = "validationMode"; static const char *superPaletteAttributeC = "superPalette"; static const char *defaultResourceAttributeC = "defaultResource"; static const char *fontAttributeC = "font"; +static const char *themeAttributeC = "theme"; class DesignerFlagPropertyType { @@ -113,13 +114,15 @@ public: void setTextPropertyValidationMode(TextPropertyValidationMode vm); void setRichTextDefaultFont(const QFont &font) { m_richTextDefaultFont = font; } - QFont richTextDefaultFont() const { return m_richTextDefaultFont; } + QFont richTextDefaultFont() const { return m_richTextDefaultFont; } void setSpacing(int spacing); TextPropertyEditor::UpdateMode updateMode() const { return m_editor->updateMode(); } void setUpdateMode(TextPropertyEditor::UpdateMode um) { m_editor->setUpdateMode(um); } + void setIconThemeModeEnabled(bool enable); + public slots: void setText(const QString &text); @@ -132,6 +135,8 @@ private slots: void fileActionActivated(); private: TextPropertyEditor *m_editor; + IconThemeEditor *m_themeEditor; + bool m_iconThemeModeEnabled; QFont m_richTextDefaultFont; QToolButton *m_button; QMenu *m_menu; @@ -144,6 +149,8 @@ private: TextEditor::TextEditor(QDesignerFormEditorInterface *core, QWidget *parent) : QWidget(parent), m_editor(new TextPropertyEditor(this)), + m_themeEditor(new IconThemeEditor(this, false)), + m_iconThemeModeEnabled(false), m_richTextDefaultFont(QApplication::font()), m_button(new QToolButton(this)), m_menu(new QMenu(this)), @@ -152,7 +159,11 @@ TextEditor::TextEditor(QDesignerFormEditorInterface *core, QWidget *parent) : m_layout(new QHBoxLayout(this)), m_core(core) { + m_themeEditor->setVisible(false); + m_button->setVisible(false); + m_layout->addWidget(m_editor); + m_layout->addWidget(m_themeEditor); m_button->setText(tr("...")); m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored); m_button->setFixedWidth(20); @@ -163,9 +174,10 @@ TextEditor::TextEditor(QDesignerFormEditorInterface *core, QWidget *parent) : connect(m_resourceAction, SIGNAL(triggered()), this, SLOT(resourceActionActivated())); connect(m_fileAction, SIGNAL(triggered()), this, SLOT(fileActionActivated())); connect(m_editor, SIGNAL(textChanged(QString)), this, SIGNAL(textChanged(QString))); + connect(m_themeEditor, SIGNAL(edited(QString)), this, SIGNAL(textChanged(QString))); connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClicked())); + setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); - m_button->setVisible(false); setFocusProxy(m_editor); m_menu->addAction(m_resourceAction); @@ -177,6 +189,22 @@ void TextEditor::setSpacing(int spacing) m_layout->setSpacing(spacing); } +void TextEditor::setIconThemeModeEnabled(bool enable) +{ + if (m_iconThemeModeEnabled == enable) + return; // nothing changes + m_iconThemeModeEnabled = enable; + m_editor->setVisible(!enable); + m_themeEditor->setVisible(enable); + if (enable) { + m_themeEditor->setTheme(m_editor->text()); + setFocusProxy(m_themeEditor); + } else { + m_editor->setText(m_themeEditor->theme()); + setFocusProxy(m_editor); + } +} + TextPropertyValidationMode TextEditor::textPropertyValidationMode() const { return m_editor->textPropertyValidationMode(); @@ -199,7 +227,10 @@ void TextEditor::setTextPropertyValidationMode(TextPropertyValidationMode vm) void TextEditor::setText(const QString &text) { - m_editor->setText(text); + if (m_iconThemeModeEnabled) + m_themeEditor->setTheme(text); + else + m_editor->setText(text); } void TextEditor::buttonClicked() @@ -279,6 +310,49 @@ void TextEditor::fileActionActivated() emit textChanged(newText); } +// ------------ ThemeInputDialog + +class IconThemeDialog : public QDialog +{ + Q_OBJECT +public: + static QString getTheme(QWidget *parent, const QString &theme, bool *ok); +private: + IconThemeDialog(QWidget *parent); + IconThemeEditor *m_editor; +}; + +IconThemeDialog::IconThemeDialog(QWidget *parent) + : QDialog(parent) +{ + setWindowTitle(tr("Set Icon From Theme")); + + QVBoxLayout *layout = new QVBoxLayout(this); + QLabel *label = new QLabel(tr("Input icon name from the current theme:"), this); + m_editor = new IconThemeEditor(this); + QDialogButtonBox *buttons = new QDialogButtonBox(this); + buttons->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + + layout->addWidget(label); + layout->addWidget(m_editor); + layout->addWidget(buttons); + + connect(buttons, SIGNAL(accepted()), this, SLOT(accept())); + connect(buttons, SIGNAL(rejected()), this, SLOT(reject())); +} + +QString IconThemeDialog::getTheme(QWidget *parent, const QString &theme, bool *ok) +{ + IconThemeDialog dlg(parent); + dlg.m_editor->setTheme(theme); + if (dlg.exec() == QDialog::Accepted) { + *ok = true; + return dlg.m_editor->theme(); + } + *ok = false; + return QString(); +} + // ------------ PixmapEditor class PixmapEditor : public QWidget { @@ -288,12 +362,15 @@ public: void setSpacing(int spacing); void setPixmapCache(DesignerPixmapCache *cache); + void setIconThemeModeEnabled(bool enabled); public slots: void setPath(const QString &path); + void setTheme(const QString &theme); void setDefaultPixmap(const QPixmap &pixmap); signals: void pathChanged(const QString &path); + void themeChanged(const QString &theme); protected: void contextMenuEvent(QContextMenuEvent *event); @@ -302,32 +379,39 @@ private slots: void defaultActionActivated(); void resourceActionActivated(); void fileActionActivated(); + void themeActionActivated(); void copyActionActivated(); void pasteActionActivated(); void clipboardDataChanged(); private: + void updateLabels(); + bool m_iconThemeModeEnabled; QDesignerFormEditorInterface *m_core; QLabel *m_pixmapLabel; QLabel *m_pathLabel; QToolButton *m_button; QAction *m_resourceAction; QAction *m_fileAction; + QAction *m_themeAction; QAction *m_copyAction; QAction *m_pasteAction; QHBoxLayout *m_layout; QPixmap m_defaultPixmap; QString m_path; + QString m_theme; DesignerPixmapCache *m_pixmapCache; }; PixmapEditor::PixmapEditor(QDesignerFormEditorInterface *core, QWidget *parent) : QWidget(parent), + m_iconThemeModeEnabled(false), m_core(core), m_pixmapLabel(new QLabel(this)), m_pathLabel(new QLabel(this)), m_button(new QToolButton(this)), m_resourceAction(new QAction(tr("Choose Resource..."), this)), m_fileAction(new QAction(tr("Choose File..."), this)), + m_themeAction(new QAction(tr("Set Icon From Theme..."), this)), m_copyAction(new QAction(createIconSet(QLatin1String("editcopy.png")), tr("Copy Path"), this)), m_pasteAction(new QAction(createIconSet(QLatin1String("editpaste.png")), tr("Paste Path"), this)), m_layout(new QHBoxLayout(this)), @@ -345,10 +429,12 @@ PixmapEditor::PixmapEditor(QDesignerFormEditorInterface *core, QWidget *parent) m_pixmapLabel->setFixedWidth(16); m_pixmapLabel->setAlignment(Qt::AlignCenter); m_pathLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); + m_themeAction->setVisible(false); QMenu *menu = new QMenu(this); menu->addAction(m_resourceAction); menu->addAction(m_fileAction); + menu->addAction(m_themeAction); m_button->setMenu(menu); m_button->setText(tr("...")); @@ -356,6 +442,7 @@ PixmapEditor::PixmapEditor(QDesignerFormEditorInterface *core, QWidget *parent) connect(m_button, SIGNAL(clicked()), this, SLOT(defaultActionActivated())); connect(m_resourceAction, SIGNAL(triggered()), this, SLOT(resourceActionActivated())); connect(m_fileAction, SIGNAL(triggered()), this, SLOT(fileActionActivated())); + connect(m_themeAction, SIGNAL(triggered()), this, SLOT(themeActionActivated())); connect(m_copyAction, SIGNAL(triggered()), this, SLOT(copyActionActivated())); connect(m_pasteAction, SIGNAL(triggered()), this, SLOT(pasteActionActivated())); setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored)); @@ -370,6 +457,14 @@ void PixmapEditor::setPixmapCache(DesignerPixmapCache *cache) m_pixmapCache = cache; } +void PixmapEditor::setIconThemeModeEnabled(bool enabled) +{ + if (m_iconThemeModeEnabled == enabled) + return; + m_iconThemeModeEnabled = enabled; + m_themeAction->setVisible(enabled); +} + void PixmapEditor::setSpacing(int spacing) { m_layout->setSpacing(spacing); @@ -378,22 +473,40 @@ void PixmapEditor::setSpacing(int spacing) void PixmapEditor::setPath(const QString &path) { m_path = path; - if (m_path.isEmpty()) { - m_pathLabel->setText(path); - m_pixmapLabel->setPixmap(m_defaultPixmap); - m_copyAction->setEnabled(false); - } else { - m_pathLabel->setText(QFileInfo(m_path).fileName()); - if (m_pixmapCache) - m_pixmapLabel->setPixmap(QIcon(m_pixmapCache->pixmap(PropertySheetPixmapValue(path))).pixmap(16, 16)); + updateLabels(); +} + +void PixmapEditor::setTheme(const QString &theme) +{ + m_theme = theme; + updateLabels(); +} + +void PixmapEditor::updateLabels() +{ + if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(m_theme)) { + m_pixmapLabel->setPixmap(QIcon::fromTheme(m_theme).pixmap(16, 16)); + m_pathLabel->setText(tr("[Theme] %1").arg(m_theme)); m_copyAction->setEnabled(true); + } else { + if (m_path.isEmpty()) { + m_pathLabel->setText(m_path); + m_pixmapLabel->setPixmap(m_defaultPixmap); + m_copyAction->setEnabled(false); + } else { + m_pathLabel->setText(QFileInfo(m_path).fileName()); + if (m_pixmapCache) + m_pixmapLabel->setPixmap(QIcon(m_pixmapCache->pixmap(PropertySheetPixmapValue(m_path))).pixmap(16, 16)); + m_copyAction->setEnabled(true); + } } } void PixmapEditor::setDefaultPixmap(const QPixmap &pixmap) { m_defaultPixmap = QIcon(pixmap).pixmap(16, 16); - if (m_path.isEmpty()) + const bool hasThemeIcon = m_iconThemeModeEnabled && QIcon::hasThemeIcon(m_theme); + if (!hasThemeIcon && m_path.isEmpty()) m_pixmapLabel->setPixmap(m_defaultPixmap); } @@ -408,6 +521,10 @@ void PixmapEditor::contextMenuEvent(QContextMenuEvent *event) void PixmapEditor::defaultActionActivated() { + if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(m_theme)) { + themeActionActivated(); + return; + } // Default to resource const PropertySheetPixmapValue::PixmapSource ps = m_path.isEmpty() ? PropertySheetPixmapValue::ResourcePixmap : PropertySheetPixmapValue::getPixmapSource(m_core, m_path); switch (ps) { @@ -426,6 +543,7 @@ void PixmapEditor::resourceActionActivated() const QString oldPath = m_path; const QString newPath = IconSelector::choosePixmapResource(m_core, m_core->resourceModel(), oldPath, this); if (!newPath.isEmpty() && newPath != oldPath) { + setTheme(QString()); setPath(newPath); emit pathChanged(newPath); } @@ -435,15 +553,30 @@ void PixmapEditor::fileActionActivated() { const QString newPath = IconSelector::choosePixmapFile(m_path, m_core->dialogGui(), this); if (!newPath.isEmpty() && newPath != m_path) { + setTheme(QString()); setPath(newPath); emit pathChanged(newPath); } } +void PixmapEditor::themeActionActivated() +{ + bool ok; + const QString newTheme = IconThemeDialog::getTheme(this, m_theme, &ok); + if (ok && newTheme != m_theme) { + setTheme(newTheme); + setPath(QString()); + emit themeChanged(newTheme); + } +} + void PixmapEditor::copyActionActivated() { QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(m_path); + if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(m_theme)) + clipboard->setText(m_theme); + else + clipboard->setText(m_path); } void PixmapEditor::pasteActionActivated() @@ -455,8 +588,15 @@ void PixmapEditor::pasteActionActivated() QStringList list = text.split(QLatin1Char('\n')); if (list.size() > 0) { text = list.at(0); - setPath(text); - emit pathChanged(text); + if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(text)) { + setTheme(text); + setPath(QString()); + emit themeChanged(text); + } else { + setPath(text); + setTheme(QString()); + emit pathChanged(text); + } } } } @@ -740,7 +880,7 @@ void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVari m_changingSubValue = false; data.val = newValue; QVariant v; - qVariantSetValue(v, data.val); + v.setValue(data.val); variantProperty(flagProperty)->setValue(v); } else if (QtProperty *alignProperty = m_alignHToProperty.value(property, 0)) { const uint v = m_alignValues.value(alignProperty); @@ -763,7 +903,7 @@ void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVari if (v == newValue) return; - variantProperty(stringProperty)->setValue(qVariantFromValue(newValue)); + variantProperty(stringProperty)->setValue(QVariant::fromValue(newValue)); } else if (QtProperty *stringProperty = m_translatableToString.value(property, 0)) { const PropertySheetStringValue v = m_stringValues.value(stringProperty); PropertySheetStringValue newValue = v; @@ -771,7 +911,7 @@ void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVari if (v == newValue) return; - variantProperty(stringProperty)->setValue(qVariantFromValue(newValue)); + variantProperty(stringProperty)->setValue(QVariant::fromValue(newValue)); } else if (QtProperty *stringProperty = m_disambiguationToString.value(property, 0)) { const PropertySheetStringValue v = m_stringValues.value(stringProperty); PropertySheetStringValue newValue = v; @@ -779,7 +919,7 @@ void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVari if (v == newValue) return; - variantProperty(stringProperty)->setValue(qVariantFromValue(newValue)); + variantProperty(stringProperty)->setValue(QVariant::fromValue(newValue)); } else if (QtProperty *keySequenceProperty = m_commentToKeySequence.value(property, 0)) { const PropertySheetKeySequenceValue v = m_keySequenceValues.value(keySequenceProperty); PropertySheetKeySequenceValue newValue = v; @@ -787,7 +927,7 @@ void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVari if (v == newValue) return; - variantProperty(keySequenceProperty)->setValue(qVariantFromValue(newValue)); + variantProperty(keySequenceProperty)->setValue(QVariant::fromValue(newValue)); } else if (QtProperty *keySequenceProperty = m_translatableToKeySequence.value(property, 0)) { const PropertySheetKeySequenceValue v = m_keySequenceValues.value(keySequenceProperty); PropertySheetKeySequenceValue newValue = v; @@ -795,7 +935,7 @@ void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVari if (v == newValue) return; - variantProperty(keySequenceProperty)->setValue(qVariantFromValue(newValue)); + variantProperty(keySequenceProperty)->setValue(QVariant::fromValue(newValue)); } else if (QtProperty *keySequenceProperty = m_disambiguationToKeySequence.value(property, 0)) { const PropertySheetKeySequenceValue v = m_keySequenceValues.value(keySequenceProperty); PropertySheetKeySequenceValue newValue = v; @@ -803,16 +943,21 @@ void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVari if (v == newValue) return; - variantProperty(keySequenceProperty)->setValue(qVariantFromValue(newValue)); + variantProperty(keySequenceProperty)->setValue(QVariant::fromValue(newValue)); } else if (QtProperty *iProperty = m_iconSubPropertyToProperty.value(property, 0)) { QtVariantProperty *iconProperty = variantProperty(iProperty); - PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(iconProperty->value()); - QPair<QIcon::Mode, QIcon::State> pair = m_iconSubPropertyToState.value(property); - icon.setPixmap(pair.first, pair.second, qVariantValue<PropertySheetPixmapValue>(value)); + PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(iconProperty->value()); + QMap<QtProperty *, QPair<QIcon::Mode, QIcon::State> >::ConstIterator itState = m_iconSubPropertyToState.constFind(property); + if (itState != m_iconSubPropertyToState.constEnd()) { + QPair<QIcon::Mode, QIcon::State> pair = m_iconSubPropertyToState.value(property); + icon.setPixmap(pair.first, pair.second, qvariant_cast<PropertySheetPixmapValue>(value)); + } else { // must be theme property + icon.setTheme(value.toString()); + } QtProperty *origSourceOfChange = m_sourceOfChange; if (!origSourceOfChange) m_sourceOfChange = property; - iconProperty->setValue(qVariantFromValue(icon)); + iconProperty->setValue(QVariant::fromValue(icon)); if (!origSourceOfChange) m_sourceOfChange = origSourceOfChange; } else if (m_iconValues.contains(property)) { @@ -859,12 +1004,16 @@ void DesignerPropertyManager::slotPropertyDestroyed(QtProperty *property) m_keySequenceToDisambiguation.remove(keySequenceDisambiguationProperty); m_disambiguationToKeySequence.remove(property); } else if (QtProperty *iconProperty = m_iconSubPropertyToProperty.value(property, 0)) { - QMap<QtProperty *, QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> >::iterator it = - m_propertyToIconSubProperties.find(iconProperty); - QPair<QIcon::Mode, QIcon::State> state = m_iconSubPropertyToState.value(property); - QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> &propertyList = it.value(); - propertyList.remove(state); - m_iconSubPropertyToState.remove(property); + if (m_propertyToTheme.value(iconProperty) == property) { + m_propertyToTheme.remove(iconProperty); + } else { + QMap<QtProperty *, QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> >::iterator it = + m_propertyToIconSubProperties.find(iconProperty); + QPair<QIcon::Mode, QIcon::State> state = m_iconSubPropertyToState.value(property); + QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> &propertyList = it.value(); + propertyList.remove(state); + m_iconSubPropertyToState.remove(property); + } m_iconSubPropertyToProperty.remove(property); } else { m_fontManager.slotPropertyDestroyed(property); @@ -887,6 +1036,7 @@ QStringList DesignerPropertyManager::attributes(int propertyType) const } else if (propertyType == designerStringTypeId() || propertyType == QVariant::String) { list.append(QLatin1String(validationModesAttributeC)); list.append(QLatin1String(fontAttributeC)); + list.append(QLatin1String(themeAttributeC)); } else if (propertyType == QVariant::Palette) { list.append(QLatin1String(superPaletteAttributeC)); } @@ -912,6 +1062,8 @@ int DesignerPropertyManager::attributeType(int propertyType, const QString &attr return QVariant::Int; if (attribute == QLatin1String(fontAttributeC)) return QVariant::Font; + if (attribute == QLatin1String(themeAttributeC)) + return QVariant::Bool; } if (propertyType == QVariant::Palette && attribute == QLatin1String(superPaletteAttributeC)) return QVariant::Palette; @@ -933,7 +1085,7 @@ QVariant DesignerPropertyManager::attributeValue(const QtProperty *property, con PropertyFlagDataMap::const_iterator it = m_flagValues.constFind(prop); if (it != m_flagValues.constEnd()) { QVariant v; - qVariantSetValue(v, it.value().flags); + v.setValue(it.value().flags); return v; } } @@ -949,6 +1101,12 @@ QVariant DesignerPropertyManager::attributeValue(const QtProperty *property, con return it.value(); } + if (attribute == QLatin1String(themeAttributeC)) { + const PropertyBoolMap::const_iterator it = m_stringThemeAttributes.constFind(prop); + if (it != m_stringThemeAttributes.constEnd()) + return it.value(); + } + if (attribute == QLatin1String(superPaletteAttributeC)) { PropertyPaletteDataMap::const_iterator it = m_paletteValues.constFind(prop); if (it != m_paletteValues.constEnd()) @@ -985,7 +1143,7 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, if (value.userType() != designerFlagListTypeId()) return; - const DesignerFlagList flags = qVariantValue<DesignerFlagList>(value); + const DesignerFlagList flags = qvariant_cast<DesignerFlagList>(value); PropertyFlagDataMap::iterator fit = m_flagValues.find(property); FlagData data = fit.value(); if (data.flags == flags) @@ -1022,7 +1180,7 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, fit.value() = data; QVariant v; - qVariantSetValue(v, flags); + v.setValue(flags); emit attributeChanged(property, attribute, v); emit propertyChanged(property); @@ -1057,11 +1215,26 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, it.value() = newValue; emit attributeChanged(property, attribute, newValue); + } else if (attribute == QLatin1String(themeAttributeC) && m_stringThemeAttributes.contains(property)) { + if (value.userType() != QVariant::Bool) + return; + + const PropertyBoolMap::iterator it = m_stringThemeAttributes.find(property); + const bool oldValue = it.value(); + + const bool newValue = value.toBool(); + + if (oldValue == newValue) + return; + + it.value() = newValue; + + emit attributeChanged(property, attribute, newValue); } else if (attribute == QLatin1String(superPaletteAttributeC) && m_paletteValues.contains(property)) { if (value.userType() != QVariant::Palette) return; - QPalette superPalette = qVariantValue<QPalette>(value); + QPalette superPalette = qvariant_cast<QPalette>(value); const PropertyPaletteDataMap::iterator it = m_paletteValues.find(property); PaletteData data = it.value(); @@ -1077,7 +1250,7 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, it.value() = data; QVariant v; - qVariantSetValue(v, superPalette); + v.setValue(superPalette); emit attributeChanged(property, attribute, v); emit propertyChanged(property); @@ -1086,7 +1259,7 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, if (value.userType() != QVariant::Pixmap) return; - QPixmap defaultPixmap = qVariantValue<QPixmap>(value); + QPixmap defaultPixmap = qvariant_cast<QPixmap>(value); const QMap<QtProperty *, QPixmap>::iterator it = m_defaultPixmaps.find(property); QPixmap oldDefaultPixmap = it.value(); @@ -1095,7 +1268,7 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, it.value() = defaultPixmap; - QVariant v = qVariantFromValue(defaultPixmap); + QVariant v = QVariant::fromValue(defaultPixmap); emit attributeChanged(property, attribute, v); emit propertyChanged(property); @@ -1103,7 +1276,7 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, if (value.userType() != QVariant::Icon) return; - QIcon defaultIcon = qVariantValue<QIcon>(value); + QIcon defaultIcon = qvariant_cast<QIcon>(value); const QMap<QtProperty *, QIcon>::iterator it = m_defaultIcons.find(property); QIcon oldDefaultIcon = it.value(); @@ -1124,7 +1297,7 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, } } - QVariant v = qVariantFromValue(defaultIcon); + QVariant v = QVariant::fromValue(defaultIcon); emit attributeChanged(property, attribute, v); emit propertyChanged(property); @@ -1234,7 +1407,11 @@ QString DesignerPropertyManager::valueText(const QtProperty *property) const return inherited; } if (m_iconValues.contains(const_cast<QtProperty *>(property))) { - const PropertySheetIconValue::ModeStateToPixmapMap paths = m_iconValues.value(const_cast<QtProperty *>(property)).paths(); + const PropertySheetIconValue icon = m_iconValues.value(const_cast<QtProperty *>(property)); + const QString theme = icon.theme(); + if (!theme.isEmpty() && QIcon::hasThemeIcon(theme)) + return tr("[Theme] %1").arg(theme); + const PropertySheetIconValue::ModeStateToPixmapMap paths = icon.paths(); const PropertySheetIconValue::ModeStateToPixmapMap::const_iterator it = paths.constFind(qMakePair(QIcon::Normal, QIcon::Off)); if (it == paths.constEnd()) return QString(); @@ -1265,12 +1442,12 @@ QString DesignerPropertyManager::valueText(const QtProperty *property) const return m_stringListValues.value(const_cast<QtProperty *>(property)).join(QLatin1String("; ")); } if (QtVariantPropertyManager::valueType(property) == QVariant::String || QtVariantPropertyManager::valueType(property) == designerStringTypeId()) { - const QString str = (QtVariantPropertyManager::valueType(property) == QVariant::String) ? value(property).toString() : qVariantValue<PropertySheetStringValue>(value(property)).value(); + const QString str = (QtVariantPropertyManager::valueType(property) == QVariant::String) ? value(property).toString() : qvariant_cast<PropertySheetStringValue>(value(property)).value(); const int validationMode = attributeValue(property, QLatin1String(validationModesAttributeC)).toInt(); return TextPropertyEditor::stringToEditorString(str, static_cast<TextPropertyValidationMode>(validationMode)); } if (QtVariantPropertyManager::valueType(property) == designerKeySequenceTypeId()) { - return qVariantValue<PropertySheetKeySequenceValue>(value(property)).value(); + return qvariant_cast<PropertySheetKeySequenceValue>(value(property)).value(); } if (QtVariantPropertyManager::valueType(property) == QVariant::Bool) { return QString(); @@ -1313,13 +1490,13 @@ void DesignerPropertyManager::reloadResourceProperties() } emit propertyChanged(property); - emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(itIcon.value())); + emit QtVariantPropertyManager::valueChanged(property, QVariant::fromValue(itIcon.value())); } QMapIterator<QtProperty *, qdesigner_internal::PropertySheetPixmapValue> itPix(m_pixmapValues); while (itPix.hasNext()) { QtProperty *property = itPix.next().key(); emit propertyChanged(property); - emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(itPix.value())); + emit QtVariantPropertyManager::valueChanged(property, QVariant::fromValue(itPix.value())); } } @@ -1339,6 +1516,8 @@ QIcon DesignerPropertyManager::valueIcon(const QtProperty *property) const qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(formWindow); if (fwb) return fwb->pixmapCache()->pixmap(m_pixmapValues.value(const_cast<QtProperty *>(property))); + } else if (m_stringThemeAttributes.value(const_cast<QtProperty *>(property), false)) { + return QIcon::fromTheme(value(property).toString()); } else { QIcon rc; if (m_brushManager.valueIcon(property, &rc)) @@ -1357,13 +1536,13 @@ QVariant DesignerPropertyManager::value(const QtProperty *property) const if (m_paletteValues.contains(const_cast<QtProperty *>(property))) return m_paletteValues.value(const_cast<QtProperty *>(property)).val; if (m_iconValues.contains(const_cast<QtProperty *>(property))) - return qVariantFromValue(m_iconValues.value(const_cast<QtProperty *>(property))); + return QVariant::fromValue(m_iconValues.value(const_cast<QtProperty *>(property))); if (m_pixmapValues.contains(const_cast<QtProperty *>(property))) - return qVariantFromValue(m_pixmapValues.value(const_cast<QtProperty *>(property))); + return QVariant::fromValue(m_pixmapValues.value(const_cast<QtProperty *>(property))); if (m_stringValues.contains(const_cast<QtProperty *>(property))) - return qVariantFromValue(m_stringValues.value(const_cast<QtProperty *>(property))); + return QVariant::fromValue(m_stringValues.value(const_cast<QtProperty *>(property))); if (m_keySequenceValues.contains(const_cast<QtProperty *>(property))) - return qVariantFromValue(m_keySequenceValues.value(const_cast<QtProperty *>(property))); + return QVariant::fromValue(m_keySequenceValues.value(const_cast<QtProperty *>(property))); if (m_uintValues.contains(const_cast<QtProperty *>(property))) return m_uintValues.value(const_cast<QtProperty *>(property)); if (m_longLongValues.contains(const_cast<QtProperty *>(property))) @@ -1497,7 +1676,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val if (value.userType() != designerStringTypeId()) return; - const PropertySheetStringValue v = qVariantValue<PropertySheetStringValue>(value); + const PropertySheetStringValue v = qvariant_cast<PropertySheetStringValue>(value); const PropertySheetStringValue val = m_stringValues.value(property); @@ -1517,7 +1696,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val m_stringValues[property] = v; - emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(v)); + emit QtVariantPropertyManager::valueChanged(property, QVariant::fromValue(v)); emit propertyChanged(property); return; @@ -1525,7 +1704,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val if (value.userType() != designerKeySequenceTypeId()) return; - const PropertySheetKeySequenceValue v = qVariantValue<PropertySheetKeySequenceValue>(value); + const PropertySheetKeySequenceValue v = qvariant_cast<PropertySheetKeySequenceValue>(value); const PropertySheetKeySequenceValue val = m_keySequenceValues.value(property); @@ -1545,7 +1724,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val m_keySequenceValues[property] = v; - emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(v)); + emit QtVariantPropertyManager::valueChanged(property, QVariant::fromValue(v)); emit propertyChanged(property); return; @@ -1553,7 +1732,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val if (value.type() != QVariant::Palette && !value.canConvert(QVariant::Palette)) return; - QPalette p = qVariantValue<QPalette>(value); + QPalette p = qvariant_cast<QPalette>(value); PaletteData data = m_paletteValues.value(property); @@ -1575,7 +1754,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val if (value.userType() != designerIconTypeId()) return; - const PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(value); + const PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(value); const PropertySheetIconValue oldIcon = m_iconValues.value(property); if (icon == oldIcon) @@ -1600,12 +1779,18 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val QtVariantProperty *subProperty = variantProperty(itSub.value()); bool hasPath = iconPaths.contains(pair); subProperty->setModified(hasPath); - subProperty->setValue(qVariantFromValue(iconPaths.value(pair))); + subProperty->setValue(QVariant::fromValue(iconPaths.value(pair))); subProperty->setAttribute(QLatin1String(defaultResourceAttributeC), defaultIcon.pixmap(16, 16, pair.first, pair.second)); } + QtVariantProperty *themeSubProperty = variantProperty(m_propertyToTheme.value(property)); + if (themeSubProperty) { + const QString theme = icon.theme(); + themeSubProperty->setModified(!theme.isEmpty()); + themeSubProperty->setValue(theme); + } - emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(icon)); + emit QtVariantPropertyManager::valueChanged(property, QVariant::fromValue(icon)); emit propertyChanged(property); QString toolTip; @@ -1620,7 +1805,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val if (value.userType() != designerPixmapTypeId()) return; - const PropertySheetPixmapValue pixmap = qVariantValue<PropertySheetPixmapValue>(value); + const PropertySheetPixmapValue pixmap = qvariant_cast<PropertySheetPixmapValue>(value); const PropertySheetPixmapValue oldPixmap = m_pixmapValues.value(property); if (pixmap == oldPixmap) @@ -1628,7 +1813,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val m_pixmapValues[property] = pixmap; - emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(pixmap)); + emit QtVariantPropertyManager::valueChanged(property, QVariant::fromValue(pixmap)); emit propertyChanged(property); property->setToolTip(pixmap.path()); @@ -1746,9 +1931,9 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val if (QtVariantPropertyManager::valueType(property) == QVariant::String) property->setToolTip(DesignerPropertyManager::value(property).toString()); else if (QtVariantPropertyManager::valueType(property) == designerStringTypeId()) - property->setToolTip(qVariantValue<PropertySheetStringValue>(DesignerPropertyManager::value(property)).value()); + property->setToolTip(qvariant_cast<PropertySheetStringValue>(DesignerPropertyManager::value(property)).value()); else if (QtVariantPropertyManager::valueType(property) == designerKeySequenceTypeId()) - property->setToolTip(qVariantValue<PropertySheetKeySequenceValue>(DesignerPropertyManager::value(property)).value()); + property->setToolTip(qvariant_cast<PropertySheetKeySequenceValue>(DesignerPropertyManager::value(property)).value()); else if (QtVariantPropertyManager::valueType(property) == QVariant::Bool) property->setToolTip(QtVariantPropertyManager::valueText(property)); } @@ -1766,6 +1951,7 @@ void DesignerPropertyManager::initializeProperty(QtProperty *property) case QVariant::String: m_stringAttributes[property] = ValidationSingleLine; m_stringFontAttributes[property] = QApplication::font(); + m_stringThemeAttributes[property] = false; break; case QVariant::UInt: m_uintValues[property] = 0; @@ -1820,6 +2006,13 @@ void DesignerPropertyManager::initializeProperty(QtProperty *property) m_iconValues[property] = PropertySheetIconValue(); m_defaultIcons[property] = QIcon(); + QtVariantProperty *themeProp = addProperty(QVariant::String, tr("Theme")); + themeProp->setAttribute(QLatin1String(themeAttributeC), true); + m_iconSubPropertyToProperty[themeProp] = property; + m_propertyToTheme[property] = themeProp; + m_resetMap[themeProp] = true; + property->addSubProperty(themeProp); + createIconSubProperty(property, QIcon::Normal, QIcon::Off, tr("Normal Off")); createIconSubProperty(property, QIcon::Normal, QIcon::On, tr("Normal On")); createIconSubProperty(property, QIcon::Disabled, QIcon::Off, tr("Disabled Off")); @@ -1833,6 +2026,7 @@ void DesignerPropertyManager::initializeProperty(QtProperty *property) m_stringValues[property] = val; m_stringAttributes[property] = ValidationMultiLine; m_stringFontAttributes[property] = QApplication::font(); + m_stringThemeAttributes[property] = false; QtVariantProperty *translatable = addProperty(QVariant::Bool, tr("translatable")); translatable->setValue(val.translatable()); @@ -1921,37 +2115,43 @@ void DesignerPropertyManager::uninitializeProperty(QtProperty *property) QtProperty *stringComment = m_stringToComment.value(property); if (stringComment) { delete stringComment; - m_stringToComment.remove(stringComment); + m_commentToString.remove(stringComment); } QtProperty *stringTranslatable = m_stringToTranslatable.value(property); if (stringTranslatable) { delete stringTranslatable; - m_stringToTranslatable.remove(stringTranslatable); + m_translatableToString.remove(stringTranslatable); } QtProperty *stringDisambiguation = m_stringToDisambiguation.value(property); if (stringDisambiguation) { delete stringDisambiguation; - m_stringToDisambiguation.remove(stringDisambiguation); + m_disambiguationToString.remove(stringDisambiguation); } QtProperty *keySequenceComment = m_keySequenceToComment.value(property); if (keySequenceComment) { delete keySequenceComment; - m_keySequenceToComment.remove(keySequenceComment); + m_commentToKeySequence.remove(keySequenceComment); } QtProperty *keySequenceTranslatable = m_keySequenceToTranslatable.value(property); if (keySequenceTranslatable) { delete keySequenceTranslatable; - m_keySequenceToTranslatable.remove(keySequenceTranslatable); + m_translatableToKeySequence.remove(keySequenceTranslatable); } QtProperty *keySequenceDisambiguation = m_keySequenceToDisambiguation.value(property); if (keySequenceDisambiguation) { delete keySequenceDisambiguation; - m_keySequenceToDisambiguation.remove(keySequenceDisambiguation); + m_disambiguationToKeySequence.remove(keySequenceDisambiguation); + } + + QtProperty *iconTheme = m_propertyToTheme.value(property); + if (iconTheme) { + delete iconTheme; + m_iconSubPropertyToProperty.remove(iconTheme); } m_propertyToAlignH.remove(property); @@ -2010,15 +2210,20 @@ bool DesignerPropertyManager::resetFontSubProperty(QtProperty *property) bool DesignerPropertyManager::resetIconSubProperty(QtProperty *property) { - if (!m_iconSubPropertyToProperty.contains(property)) - return false; - - if (!m_pixmapValues.contains(property)) + QtProperty *iconProperty = m_iconSubPropertyToProperty.value(property); + if (!iconProperty) return false; - QtVariantProperty *pixmapProperty = variantProperty(property); - pixmapProperty->setValue(qVariantFromValue(PropertySheetPixmapValue())); - return true; + if (m_pixmapValues.contains(property)) { + QtVariantProperty *pixmapProperty = variantProperty(property); + pixmapProperty->setValue(QVariant::fromValue(PropertySheetPixmapValue())); + return true; + } else if (m_propertyToTheme.contains(iconProperty)) { + QtVariantProperty *themeProperty = variantProperty(property); + themeProperty->setValue(QString()); + return true; + } + return false; } // -------- DesignerEditorFactory @@ -2116,6 +2321,10 @@ void DesignerEditorFactory::slotAttributeChanged(QtProperty *property, const QSt const QFont font = qvariant_cast<QFont>(value); applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setRichTextDefaultFont, font); } + if (attribute == QLatin1String(themeAttributeC)) { + const bool themeEnabled = value.toBool(); + applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setIconThemeModeEnabled, themeEnabled); + } } else if (type == QVariant::Palette && attribute == QLatin1String(superPaletteAttributeC)) { const QPalette palette = qvariant_cast<QPalette>(value); applyToEditors(m_palettePropertyToEditors.value(property), &PaletteEditorButton::setSuperPalette, palette); @@ -2131,7 +2340,7 @@ void DesignerEditorFactory::slotPropertyChanged(QtProperty *property) if (!property->isModified()) defaultPixmap = qvariant_cast<QIcon>(manager->attributeValue(property, QLatin1String(defaultResourceAttributeC))).pixmap(16, 16); else if (m_fwb) - defaultPixmap = m_fwb->iconCache()->icon(qVariantValue<PropertySheetIconValue>(manager->value(property))).pixmap(16, 16); + defaultPixmap = m_fwb->iconCache()->icon(qvariant_cast<PropertySheetIconValue>(manager->value(property))).pixmap(16, 16); QList<PixmapEditor *> editors = m_iconPropertyToEditors.value(property); QListIterator<PixmapEditor *> it(editors); while (it.hasNext()) { @@ -2174,14 +2383,18 @@ void DesignerEditorFactory::slotValueChanged(QtProperty *property, const QVarian applyToEditors(m_stringListPropertyToEditors.value(property), &StringListEditorButton::setStringList, value.toStringList()); break; default: - if (type == DesignerPropertyManager::designerIconTypeId()) - applyToEditors(m_iconPropertyToEditors.value(property), &PixmapEditor::setPath, qVariantValue<PropertySheetIconValue>(value).pixmap(QIcon::Normal, QIcon::Off).path()); - else if (type == DesignerPropertyManager::designerPixmapTypeId()) - applyToEditors(m_pixmapPropertyToEditors.value(property), &PixmapEditor::setPath, qVariantValue<PropertySheetPixmapValue>(value).path()); - else if (type == DesignerPropertyManager::designerStringTypeId()) - applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setText, qVariantValue<PropertySheetStringValue>(value).value()); - else if (type == DesignerPropertyManager::designerKeySequenceTypeId()) - applyToEditors(m_keySequencePropertyToEditors.value(property), &QtKeySequenceEdit::setKeySequence, qVariantValue<PropertySheetKeySequenceValue>(value).value()); + if (type == DesignerPropertyManager::designerIconTypeId()) { + PropertySheetIconValue iconValue = qvariant_cast<PropertySheetIconValue>(value); + const QString theme = iconValue.theme(); + applyToEditors(m_iconPropertyToEditors.value(property), &PixmapEditor::setTheme, iconValue.theme()); + applyToEditors(m_iconPropertyToEditors.value(property), &PixmapEditor::setPath, iconValue.pixmap(QIcon::Normal, QIcon::Off).path()); + } else if (type == DesignerPropertyManager::designerPixmapTypeId()) { + applyToEditors(m_pixmapPropertyToEditors.value(property), &PixmapEditor::setPath, qvariant_cast<PropertySheetPixmapValue>(value).path()); + } else if (type == DesignerPropertyManager::designerStringTypeId()) { + applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setText, qvariant_cast<PropertySheetStringValue>(value).value()); + } else if (type == DesignerPropertyManager::designerKeySequenceTypeId()) { + applyToEditors(m_keySequencePropertyToEditors.value(property), &QtKeySequenceEdit::setKeySequence, qvariant_cast<PropertySheetKeySequenceValue>(value).value()); + } break; } } @@ -2215,6 +2428,8 @@ QWidget *DesignerEditorFactory::createEditor(QtVariantPropertyManager *manager, const QVariant richTextDefaultFont = manager->attributeValue(property, QLatin1String(fontAttributeC)); if (richTextDefaultFont.type() == QVariant::Font) ed->setRichTextDefaultFont(qvariant_cast<QFont>(richTextDefaultFont)); + const bool themeEnabled = manager->attributeValue(property, QLatin1String(themeAttributeC)).toBool(); + ed->setIconThemeModeEnabled(themeEnabled); m_stringPropertyToEditors[property].append(ed); m_editorToStringProperty[ed] = property; connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*))); @@ -2308,7 +2523,9 @@ QWidget *DesignerEditorFactory::createEditor(QtVariantPropertyManager *manager, } else if (type == DesignerPropertyManager::designerIconTypeId()) { PixmapEditor *ed = new PixmapEditor(m_core, parent); ed->setPixmapCache(m_fwb->pixmapCache()); + ed->setIconThemeModeEnabled(true); PropertySheetIconValue value = qvariant_cast<PropertySheetIconValue>(manager->value(property)); + ed->setTheme(value.theme()); ed->setPath(value.pixmap(QIcon::Normal, QIcon::Off).path()); QPixmap defaultPixmap; if (!property->isModified()) @@ -2321,10 +2538,11 @@ QWidget *DesignerEditorFactory::createEditor(QtVariantPropertyManager *manager, m_editorToIconProperty[ed] = property; connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*))); connect(ed, SIGNAL(pathChanged(QString)), this, SLOT(slotIconChanged(QString))); + connect(ed, SIGNAL(themeChanged(QString)), this, SLOT(slotIconThemeChanged(QString))); editor = ed; } else if (type == DesignerPropertyManager::designerStringTypeId()) { const TextPropertyValidationMode tvm = static_cast<TextPropertyValidationMode>(manager->attributeValue(property, QLatin1String(validationModesAttributeC)).toInt()); - TextEditor *ed = createTextEditor(parent, tvm, qVariantValue<PropertySheetStringValue>(manager->value(property)).value()); + TextEditor *ed = createTextEditor(parent, tvm, qvariant_cast<PropertySheetStringValue>(manager->value(property)).value()); const QVariant richTextDefaultFont = manager->attributeValue(property, QLatin1String(fontAttributeC)); if (richTextDefaultFont.type() == QVariant::Font) ed->setRichTextDefaultFont(qvariant_cast<QFont>(richTextDefaultFont)); @@ -2335,7 +2553,7 @@ QWidget *DesignerEditorFactory::createEditor(QtVariantPropertyManager *manager, editor = ed; } else if (type == DesignerPropertyManager::designerKeySequenceTypeId()) { QtKeySequenceEdit *ed = new QtKeySequenceEdit(parent); - ed->setKeySequence(qVariantValue<PropertySheetKeySequenceValue>(manager->value(property)).value()); + ed->setKeySequence(qvariant_cast<PropertySheetKeySequenceValue>(manager->value(property)).value()); m_keySequencePropertyToEditors[property].append(ed); m_editorToKeySequenceProperty[ed] = property; connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*))); @@ -2456,12 +2674,12 @@ void DesignerEditorFactory::slotStringTextChanged(const QString &value) QtVariantProperty *varProp = manager->variantProperty(prop); QVariant val = varProp->value(); if (val.userType() == DesignerPropertyManager::designerStringTypeId()) { - PropertySheetStringValue strVal = qVariantValue<PropertySheetStringValue>(val); + PropertySheetStringValue strVal = qvariant_cast<PropertySheetStringValue>(val); strVal.setValue(value); // Disable translation if no translation subproperties exist. if (varProp->subProperties().empty()) strVal.setTranslatable(false); - val = qVariantFromValue(strVal); + val = QVariant::fromValue(strVal); } else { val = QVariant(value); } @@ -2482,11 +2700,11 @@ void DesignerEditorFactory::slotKeySequenceChanged(const QKeySequence &value) QtVariantProperty *varProp = manager->variantProperty(prop); QVariant val = varProp->value(); if (val.userType() == DesignerPropertyManager::designerKeySequenceTypeId()) { - PropertySheetKeySequenceValue keyVal = qVariantValue<PropertySheetKeySequenceValue>(val); + PropertySheetKeySequenceValue keyVal = qvariant_cast<PropertySheetKeySequenceValue>(val); keyVal.setValue(value); - val = qVariantFromValue(keyVal); + val = QVariant::fromValue(keyVal); } else { - val = qVariantFromValue(value); + val = QVariant::fromValue(value); } m_changingPropertyValue = true; manager->variantProperty(prop)->setValue(val); @@ -2497,24 +2715,32 @@ void DesignerEditorFactory::slotKeySequenceChanged(const QKeySequence &value) void DesignerEditorFactory::slotPaletteChanged(const QPalette &value) { - updateManager(this, &m_changingPropertyValue, m_editorToPaletteProperty, qobject_cast<QWidget *>(sender()), qVariantFromValue(value)); + updateManager(this, &m_changingPropertyValue, m_editorToPaletteProperty, qobject_cast<QWidget *>(sender()), QVariant::fromValue(value)); } void DesignerEditorFactory::slotPixmapChanged(const QString &value) { updateManager(this, &m_changingPropertyValue, m_editorToPixmapProperty, qobject_cast<QWidget *>(sender()), - qVariantFromValue(PropertySheetPixmapValue(value))); + QVariant::fromValue(PropertySheetPixmapValue(value))); } void DesignerEditorFactory::slotIconChanged(const QString &value) { updateManager(this, &m_changingPropertyValue, m_editorToIconProperty, qobject_cast<QWidget *>(sender()), - qVariantFromValue(PropertySheetIconValue(PropertySheetPixmapValue(value)))); + QVariant::fromValue(PropertySheetIconValue(PropertySheetPixmapValue(value)))); +} + +void DesignerEditorFactory::slotIconThemeChanged(const QString &value) +{ + PropertySheetIconValue icon; + icon.setTheme(value); + updateManager(this, &m_changingPropertyValue, m_editorToIconProperty, qobject_cast<QWidget *>(sender()), + QVariant::fromValue(icon)); } void DesignerEditorFactory::slotStringListChanged(const QStringList &value) { - updateManager(this, &m_changingPropertyValue, m_editorToStringListProperty, qobject_cast<QWidget *>(sender()), qVariantFromValue(value)); + updateManager(this, &m_changingPropertyValue, m_editorToStringListProperty, qobject_cast<QWidget *>(sender()), QVariant::fromValue(value)); } ResetDecorator::~ResetDecorator() diff --git a/tools/designer/src/components/propertyeditor/designerpropertymanager.h b/tools/designer/src/components/propertyeditor/designerpropertymanager.h index 11f900b..03e3dca 100644 --- a/tools/designer/src/components/propertyeditor/designerpropertymanager.h +++ b/tools/designer/src/components/propertyeditor/designerpropertymanager.h @@ -180,6 +180,7 @@ private: QMap<QtProperty *, QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> > m_propertyToIconSubProperties; QMap<QtProperty *, QPair<QIcon::Mode, QIcon::State> > m_iconSubPropertyToState; PropertyToPropertyMap m_iconSubPropertyToProperty; + PropertyToPropertyMap m_propertyToTheme; QMap<QtProperty *, qdesigner_internal::PropertySheetStringValue> m_stringValues; QMap<QtProperty *, QtProperty *> m_stringToComment; @@ -221,6 +222,7 @@ private: PropertyIntMap m_stringAttributes; typedef QMap<QtProperty *, QFont> PropertyFontMap; PropertyFontMap m_stringFontAttributes; + PropertyBoolMap m_stringThemeAttributes; BrushPropertyManager m_brushManager; FontPropertyManager m_fontManager; @@ -261,6 +263,7 @@ private slots: void slotPaletteChanged(const QPalette &value); void slotPixmapChanged(const QString &value); void slotIconChanged(const QString &value); + void slotIconThemeChanged(const QString &value); void slotUintChanged(const QString &value); void slotLongLongChanged(const QString &value); void slotULongLongChanged(const QString &value); diff --git a/tools/designer/src/components/propertyeditor/fontpropertymanager.cpp b/tools/designer/src/components/propertyeditor/fontpropertymanager.cpp index 9442b01..419834e 100644 --- a/tools/designer/src/components/propertyeditor/fontpropertymanager.cpp +++ b/tools/designer/src/components/propertyeditor/fontpropertymanager.cpp @@ -123,7 +123,7 @@ namespace qdesigner_internal { // This will cause a recursion QtVariantProperty *antialiasing = vm->addProperty(enumTypeId, QCoreApplication::translate("FontPropertyManager", "Antialiasing")); - const QFont font = qVariantValue<QFont>(vm->variantProperty(property)->value()); + const QFont font = qvariant_cast<QFont>(vm->variantProperty(property)->value()); antialiasing->setAttribute(QLatin1String("enumNames"), m_aliasingEnumNames); antialiasing->setValue(antialiasingToIndex(font.styleStrategy())); @@ -196,7 +196,7 @@ namespace qdesigner_internal { mask &= ~flag; font.resolve(mask); - qVariantSetValue(v, font); + v.setValue(font); fontProperty->setValue(v); return true; } @@ -250,13 +250,13 @@ namespace qdesigner_internal { QtVariantProperty *fontProperty = vm->variantProperty(antialiasingProperty); const QFont::StyleStrategy newValue = indexToAntialiasing(value.toInt()); - QFont font = qVariantValue<QFont>(fontProperty->value()); + QFont font = qvariant_cast<QFont>(fontProperty->value()); const QFont::StyleStrategy oldValue = font.styleStrategy(); if (newValue == oldValue) return Unchanged; font.setStyleStrategy(newValue); - fontProperty->setValue(qVariantFromValue(font)); + fontProperty->setValue(QVariant::fromValue(font)); return Changed; } @@ -268,7 +268,7 @@ namespace qdesigner_internal { const PropertyList &subProperties = it.value(); - QFont font = qVariantValue<QFont>(value); + QFont font = qvariant_cast<QFont>(value); const unsigned mask = font.resolve(); const int count = subProperties.size(); @@ -285,7 +285,7 @@ namespace qdesigner_internal { if (QtProperty *antialiasingProperty = m_propertyToAntialiasing.value(property, 0)) { QtVariantProperty *antialiasing = vm->variantProperty(antialiasingProperty); if (antialiasing) { - QFont font = qVariantValue<QFont>(value); + QFont font = qvariant_cast<QFont>(value); antialiasing->setValue(antialiasingToIndex(font.styleStrategy())); } } diff --git a/tools/designer/src/components/propertyeditor/paletteeditor.cpp b/tools/designer/src/components/propertyeditor/paletteeditor.cpp index 067946b..5c4cbcc 100644 --- a/tools/designer/src/components/propertyeditor/paletteeditor.cpp +++ b/tools/designer/src/components/propertyeditor/paletteeditor.cpp @@ -294,7 +294,7 @@ bool PaletteModel::setData(const QModelIndex &index, const QVariant &value, int return false; if (index.column() != 0 && role == BrushRole) { - const QBrush br = qVariantValue<QBrush>(value); + const QBrush br = qvariant_cast<QBrush>(value); const QPalette::ColorRole r = static_cast<QPalette::ColorRole>(index.row()); const QPalette::ColorGroup g = columnToGroup(index.column()); m_palette.setBrush(g, r, br); @@ -336,7 +336,7 @@ bool PaletteModel::setData(const QModelIndex &index, const QVariant &value, int } if (index.column() == 0 && role == Qt::EditRole) { uint mask = m_palette.resolve(); - const bool isMask = qVariantValue<bool>(value); + const bool isMask = qvariant_cast<bool>(value); const int r = index.row(); if (isMask) mask |= (1 << r); @@ -532,13 +532,13 @@ QWidget *ColorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem void ColorDelegate::setEditorData(QWidget *ed, const QModelIndex &index) const { if (index.column() == 0) { - const bool mask = qVariantValue<bool>(index.model()->data(index, Qt::EditRole)); + const bool mask = qvariant_cast<bool>(index.model()->data(index, Qt::EditRole)); RoleEditor *editor = static_cast<RoleEditor *>(ed); editor->setEdited(mask); - const QString colorName = qVariantValue<QString>(index.model()->data(index, Qt::DisplayRole)); + const QString colorName = qvariant_cast<QString>(index.model()->data(index, Qt::DisplayRole)); editor->setLabel(colorName); } else { - const QBrush br = qVariantValue<QBrush>(index.model()->data(index, BrushRole)); + const QBrush br = qvariant_cast<QBrush>(index.model()->data(index, BrushRole)); BrushEditor *editor = static_cast<BrushEditor *>(ed); editor->setBrush(br); } @@ -571,11 +571,11 @@ void ColorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opt, const QModelIndex &index) const { QStyleOptionViewItem option = opt; - const bool mask = qVariantValue<bool>(index.model()->data(index, Qt::EditRole)); + const bool mask = qvariant_cast<bool>(index.model()->data(index, Qt::EditRole)); if (index.column() == 0 && mask) { option.font.setBold(true); } - QBrush br = qVariantValue<QBrush>(index.model()->data(index, BrushRole)); + QBrush br = qvariant_cast<QBrush>(index.model()->data(index, BrushRole)); if (br.style() == Qt::LinearGradientPattern || br.style() == Qt::RadialGradientPattern || br.style() == Qt::ConicalGradientPattern) { diff --git a/tools/designer/src/components/propertyeditor/propertyeditor.cpp b/tools/designer/src/components/propertyeditor/propertyeditor.cpp index a8ca8ad..7296636 100644 --- a/tools/designer/src/components/propertyeditor/propertyeditor.cpp +++ b/tools/designer/src/components/propertyeditor/propertyeditor.cpp @@ -872,12 +872,12 @@ void PropertyEditor::updateBrowserValue(QtVariantProperty *property, const QVari int PropertyEditor::toBrowserType(const QVariant &value, const QString &propertyName) const { - if (qVariantCanConvert<PropertySheetFlagValue>(value)) { + if (value.canConvert<PropertySheetFlagValue>()) { if (m_strings.m_alignmentProperties.contains(propertyName)) return DesignerPropertyManager::designerAlignmentTypeId(); return DesignerPropertyManager::designerFlagTypeId(); } - if (qVariantCanConvert<PropertySheetEnumValue>(value)) + if (value.canConvert<PropertySheetEnumValue>()) return DesignerPropertyManager::enumTypeId(); return value.userType(); @@ -1034,7 +1034,7 @@ void PropertyEditor::setObject(QObject *object) } m_updatingBrowser = true; QVariant v; - qVariantSetValue(v, flags); + v.setValue(flags); property->setAttribute(m_strings.m_flagsAttribute, v); m_updatingBrowser = false; } @@ -1223,7 +1223,7 @@ void PropertyEditor::slotValueChanged(QtProperty *property, const QVariant &valu e.value = e.metaEnum.parseEnum(valName, &ok); Q_ASSERT(ok); QVariant v; - qVariantSetValue(v, e); + v.setValue(e); emitPropertyValueChanged(property->propertyName(), v, true); return; } diff --git a/tools/designer/src/components/signalsloteditor/connectdialog.cpp b/tools/designer/src/components/signalsloteditor/connectdialog.cpp index ff6be16..abd2e83 100644 --- a/tools/designer/src/components/signalsloteditor/connectdialog.cpp +++ b/tools/designer/src/components/signalsloteditor/connectdialog.cpp @@ -231,7 +231,7 @@ void ConnectDialog::populateSlotList(const QString &signal) QFont font = QApplication::font(); font.setItalic(true); - QVariant variantFont = qVariantFromValue(font); + QVariant variantFont = QVariant::fromValue(font); QListWidgetItem *curr = 0; QMap<QString, QString>::ConstIterator itMember = memberToClassName.constBegin(); @@ -271,7 +271,7 @@ void ConnectDialog::populateSignalList() QFont font = QApplication::font(); font.setItalic(true); - QVariant variantFont = qVariantFromValue(font); + QVariant variantFont = QVariant::fromValue(font); QListWidgetItem *curr = 0; QMap<QString, QString>::ConstIterator itMember = memberToClassName.constBegin(); diff --git a/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp b/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp index 8674ac1..09c2233 100644 --- a/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp +++ b/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp @@ -245,7 +245,7 @@ namespace qdesigner_internal { ClassesMemberFunctions reverseClassesMemberFunctions(const QString &obj_name, MemberType member_type, const QString &peer, QDesignerFormWindowInterface *form) { - QObject *object = qFindChild<QObject*>(form, obj_name); + QObject *object = form->findChild<QObject*>(obj_name); if (!object) return ClassesMemberFunctions(); diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditor.cpp b/tools/designer/src/components/signalsloteditor/signalsloteditor.cpp index b801c5e..1d45ef5 100644 --- a/tools/designer/src/components/signalsloteditor/signalsloteditor.cpp +++ b/tools/designer/src/components/signalsloteditor/signalsloteditor.cpp @@ -372,7 +372,7 @@ QObject *SignalSlotEditor::objectByName(QWidget *topLevel, const QString &name) if (topLevel->objectName() == name) object = topLevel; else - object = qFindChild<QObject*>(topLevel, name); + object = topLevel->findChild<QObject*>(name); const QDesignerMetaDataBaseInterface *mdb = formWindow()->core()->metaDataBase(); if (mdb->item(object)) return object; diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp b/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp index 5547761..6cfc286 100644 --- a/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp +++ b/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp @@ -117,7 +117,7 @@ static QStringList objectNameList(QDesignerFormWindowInterface *form) const QDesignerMetaDataBaseInterface *mdb = form->core()->metaDataBase(); // Add managed actions and actions with managed menus - const ActionList actions = qFindChildren<QAction*>(mainContainer); + const ActionList actions = mainContainer->findChildren<QAction*>(); if (!actions.empty()) { const ActionList::const_iterator cend = actions.constEnd(); for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it) { @@ -135,7 +135,7 @@ static QStringList objectNameList(QDesignerFormWindowInterface *form) } // Add managed buttons groups - const ButtonGroupList buttonGroups = qFindChildren<QButtonGroup *>(mainContainer); + const ButtonGroupList buttonGroups = mainContainer->findChildren<QButtonGroup *>(); if (!buttonGroups.empty()) { const ButtonGroupList::const_iterator cend = buttonGroups.constEnd(); for (ButtonGroupList::const_iterator it = buttonGroups.constBegin(); it != cend; ++it) @@ -473,7 +473,7 @@ void InlineEditorModel::addTextList(const QMap<QString, bool> &text_list) insertRows(cnt, text_list.size()); QFont font = QApplication::font(); font.setItalic(true); - QVariant fontVariant = qVariantFromValue(font); + QVariant fontVariant = QVariant::fromValue(font); QMap<QString, bool>::ConstIterator it = text_list.constBegin(); const QMap<QString, bool>::ConstIterator itEnd = text_list.constEnd(); while (it != itEnd) { @@ -658,7 +658,7 @@ QWidget *ConnectionDelegate::createEditor(QWidget *parent, const qdesigner_internal::ClassesMemberFunctions class_list = qdesigner_internal::reverseClassesMemberFunctions(obj_name, type, peer, m_form); - QObject *object = qFindChild<QObject*>(m_form, obj_name); + QObject *object = m_form->findChild<QObject*>(obj_name); inline_editor->addText(type == qdesigner_internal::SignalMember ? tr("<signal>") : tr("<slot>")); foreach (const qdesigner_internal::ClassMemberFunctions &class_info, class_list) { @@ -767,7 +767,7 @@ void SignalSlotEditorWindow::setActiveFormWindow(QDesignerFormWindowInterface *f } } - m_editor = qFindChild<SignalSlotEditor*>(form); + m_editor = form->findChild<SignalSlotEditor*>(); m_model->setEditor(m_editor); if (!m_editor.isNull()) { ConnectionDelegate *delegate diff --git a/tools/designer/src/components/tabordereditor/tabordereditor.cpp b/tools/designer/src/components/tabordereditor/tabordereditor.cpp index 37acabc..f877654 100644 --- a/tools/designer/src/components/tabordereditor/tabordereditor.cpp +++ b/tools/designer/src/components/tabordereditor/tabordereditor.cpp @@ -239,7 +239,7 @@ void TabOrderEditor::initTabOrder() childQueue.append(formWindow()->mainContainer()); while (!childQueue.isEmpty()) { QWidget *child = childQueue.takeFirst(); - childQueue += qVariantValue<QWidgetList>(child->property("_q_widgetOrder")); + childQueue += qvariant_cast<QWidgetList>(child->property("_q_widgetOrder")); if (skipWidget(child)) continue; diff --git a/tools/designer/src/components/taskmenu/button_taskmenu.cpp b/tools/designer/src/components/taskmenu/button_taskmenu.cpp index 6b91c60..e178ebc 100644 --- a/tools/designer/src/components/taskmenu/button_taskmenu.cpp +++ b/tools/designer/src/components/taskmenu/button_taskmenu.cpp @@ -508,7 +508,7 @@ bool ButtonTaskMenu::refreshAssignMenu(const QDesignerFormWindowInterface *fw, i QButtonGroup *bg = *it; if (*it != currentGroup) { QAction *a = new QAction(bg->objectName(), m_assignGroupSubMenu); - a->setData(qVariantFromValue(bg)); + a->setData(QVariant::fromValue(bg)); m_assignActionGroup->addAction(a); m_assignGroupSubMenu->addAction(a); } diff --git a/tools/designer/src/components/taskmenu/inplace_editor.cpp b/tools/designer/src/components/taskmenu/inplace_editor.cpp index 5732500..810df23 100644 --- a/tools/designer/src/components/taskmenu/inplace_editor.cpp +++ b/tools/designer/src/components/taskmenu/inplace_editor.cpp @@ -106,7 +106,7 @@ void TaskMenuInlineEditor::editText() const int index = sheet->indexOf(m_property); if (index == -1) return; - m_value = qVariantValue<PropertySheetStringValue>(sheet->property(index)); + m_value = qvariant_cast<PropertySheetStringValue>(sheet->property(index)); const QString oldValue = m_value.value(); m_editor = new InPlaceEditor(m_widget, m_vm, m_formWindow, oldValue, editRectangle()); @@ -119,9 +119,9 @@ void TaskMenuInlineEditor::updateText(const QString &text) // do not use the cursor selection m_value.setValue(text); if (m_managed) { - m_formWindow->cursor()->setProperty(m_property, qVariantFromValue(m_value)); + m_formWindow->cursor()->setProperty(m_property, QVariant::fromValue(m_value)); } else { - m_formWindow->cursor()->setWidgetProperty(m_widget, m_property, qVariantFromValue(m_value)); + m_formWindow->cursor()->setWidgetProperty(m_widget, m_property, QVariant::fromValue(m_value)); } } diff --git a/tools/designer/src/components/taskmenu/itemlisteditor.cpp b/tools/designer/src/components/taskmenu/itemlisteditor.cpp index 9f8e9c8..b2ca134 100644 --- a/tools/designer/src/components/taskmenu/itemlisteditor.cpp +++ b/tools/designer/src/components/taskmenu/itemlisteditor.cpp @@ -191,8 +191,8 @@ void AbstractItemEditor::propertyChanged(QtProperty *property) return; if ((role == ItemFlagsShadowRole && prop->value().toInt() == (int)QListWidgetItem().flags()) - || (role == Qt::DecorationPropertyRole && !qVariantValue<PropertySheetIconValue>(prop->value()).mask()) - || (role == Qt::FontRole && !qVariantValue<QFont>(prop->value()).resolve())) { + || (role == Qt::DecorationPropertyRole && !qvariant_cast<PropertySheetIconValue>(prop->value()).mask()) + || (role == Qt::FontRole && !qvariant_cast<QFont>(prop->value()).resolve())) { prop->setModified(false); setItemData(role, QVariant()); } else { @@ -202,19 +202,19 @@ void AbstractItemEditor::propertyChanged(QtProperty *property) switch (role) { case Qt::DecorationPropertyRole: - setItemData(Qt::DecorationRole, qVariantFromValue(iconCache()->icon(qVariantValue<PropertySheetIconValue>(prop->value())))); + setItemData(Qt::DecorationRole, QVariant::fromValue(iconCache()->icon(qvariant_cast<PropertySheetIconValue>(prop->value())))); break; case Qt::DisplayPropertyRole: - setItemData(Qt::EditRole, qVariantFromValue(qVariantValue<PropertySheetStringValue>(prop->value()).value())); + setItemData(Qt::EditRole, QVariant::fromValue(qvariant_cast<PropertySheetStringValue>(prop->value()).value())); break; case Qt::ToolTipPropertyRole: - setItemData(Qt::ToolTipRole, qVariantFromValue(qVariantValue<PropertySheetStringValue>(prop->value()).value())); + setItemData(Qt::ToolTipRole, QVariant::fromValue(qvariant_cast<PropertySheetStringValue>(prop->value()).value())); break; case Qt::StatusTipPropertyRole: - setItemData(Qt::StatusTipRole, qVariantFromValue(qVariantValue<PropertySheetStringValue>(prop->value()).value())); + setItemData(Qt::StatusTipRole, QVariant::fromValue(qvariant_cast<PropertySheetStringValue>(prop->value()).value())); break; case Qt::WhatsThisPropertyRole: - setItemData(Qt::WhatsThisRole, qVariantFromValue(qVariantValue<PropertySheetStringValue>(prop->value()).value())); + setItemData(Qt::WhatsThisRole, QVariant::fromValue(qvariant_cast<PropertySheetStringValue>(prop->value()).value())); break; default: break; @@ -236,22 +236,22 @@ void AbstractItemEditor::resetProperty(QtProperty *property) QtVariantProperty *prop = m_propertyManager->variantProperty(property); int role = m_propertyToRole.value(prop); if (role == ItemFlagsShadowRole) - prop->setValue(qVariantFromValue((int)QListWidgetItem().flags())); + prop->setValue(QVariant::fromValue((int)QListWidgetItem().flags())); else prop->setValue(QVariant(prop->valueType(), (void *)0)); prop->setModified(false); setItemData(role, QVariant()); if (role == Qt::DecorationPropertyRole) - setItemData(Qt::DecorationRole, qVariantFromValue(QIcon())); + setItemData(Qt::DecorationRole, QVariant::fromValue(QIcon())); if (role == Qt::DisplayPropertyRole) - setItemData(Qt::EditRole, qVariantFromValue(QString())); + setItemData(Qt::EditRole, QVariant::fromValue(QString())); if (role == Qt::ToolTipPropertyRole) - setItemData(Qt::ToolTipRole, qVariantFromValue(QString())); + setItemData(Qt::ToolTipRole, QVariant::fromValue(QString())); if (role == Qt::StatusTipPropertyRole) - setItemData(Qt::StatusTipRole, qVariantFromValue(QString())); + setItemData(Qt::StatusTipRole, QVariant::fromValue(QString())); if (role == Qt::WhatsThisPropertyRole) - setItemData(Qt::WhatsThisRole, qVariantFromValue(QString())); + setItemData(Qt::WhatsThisRole, QVariant::fromValue(QString())); } void AbstractItemEditor::cacheReloaded() @@ -268,7 +268,7 @@ void AbstractItemEditor::updateBrowser() QVariant val = getItemData(role); if (!val.isValid()) { if (role == ItemFlagsShadowRole) - val = qVariantFromValue((int)QListWidgetItem().flags()); + val = QVariant::fromValue((int)QListWidgetItem().flags()); else val = QVariant((int)prop->value().userType(), (void *)0); prop->setModified(false); @@ -340,7 +340,7 @@ void ItemListEditor::on_newListItemButton_clicked() int row = ui.listWidget->currentRow() + 1; QListWidgetItem *item = new QListWidgetItem(m_newItemText); - item->setData(Qt::DisplayPropertyRole, qVariantFromValue(PropertySheetStringValue(m_newItemText))); + item->setData(Qt::DisplayPropertyRole, QVariant::fromValue(PropertySheetStringValue(m_newItemText))); item->setFlags(item->flags() | Qt::ItemIsEditable); if (row < ui.listWidget->count()) ui.listWidget->insertItem(row, item); @@ -403,15 +403,15 @@ void ItemListEditor::on_listWidget_itemChanged(QListWidgetItem *item) if (m_updatingBrowser) return; - PropertySheetStringValue val = qVariantValue<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole)); + PropertySheetStringValue val = qvariant_cast<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole)); val.setValue(item->text()); BoolBlocker block(m_updatingBrowser); - item->setData(Qt::DisplayPropertyRole, qVariantFromValue(val)); + item->setData(Qt::DisplayPropertyRole, QVariant::fromValue(val)); // The checkState could change, too, but if this signal is connected, // checkState is not in the list anyway, as we are editing a header item. emit itemChanged(ui.listWidget->currentRow(), Qt::DisplayPropertyRole, - qVariantFromValue(val)); + QVariant::fromValue(val)); updateBrowser(); } @@ -438,8 +438,8 @@ void ItemListEditor::setItemData(int role, const QVariant &v) QVariant newValue = v; if (role == Qt::FontRole && newValue.type() == QVariant::Font) { QFont oldFont = ui.listWidget->font(); - QFont newFont = qVariantValue<QFont>(newValue).resolve(oldFont); - newValue = qVariantFromValue(newFont); + QFont newFont = qvariant_cast<QFont>(newValue).resolve(oldFont); + newValue = QVariant::fromValue(newFont); item->setData(role, QVariant()); // force the right font with the current resolve mask is set (item view bug) } item->setData(role, newValue); diff --git a/tools/designer/src/components/taskmenu/tablewidgeteditor.cpp b/tools/designer/src/components/taskmenu/tablewidgeteditor.cpp index 7dd5442..cd8b188 100644 --- a/tools/designer/src/components/taskmenu/tablewidgeteditor.cpp +++ b/tools/designer/src/components/taskmenu/tablewidgeteditor.cpp @@ -152,8 +152,8 @@ void TableWidgetEditor::setItemData(int role, const QVariant &v) QVariant newValue = v; if (role == Qt::FontRole && newValue.type() == QVariant::Font) { QFont oldFont = ui.tableWidget->font(); - QFont newFont = qVariantValue<QFont>(newValue).resolve(oldFont); - newValue = qVariantFromValue(newFont); + QFont newFont = qvariant_cast<QFont>(newValue).resolve(oldFont); + newValue = QVariant::fromValue(newFont); item->setData(role, QVariant()); // force the right font with the current resolve mask is set (item view bug) } item->setData(role, newValue); @@ -179,10 +179,10 @@ void TableWidgetEditor::on_tableWidget_itemChanged(QTableWidgetItem *item) if (m_updatingBrowser) return; - PropertySheetStringValue val = qVariantValue<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole)); + PropertySheetStringValue val = qvariant_cast<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole)); val.setValue(item->text()); BoolBlocker block(m_updatingBrowser); - item->setData(Qt::DisplayPropertyRole, qVariantFromValue(val)); + item->setData(Qt::DisplayPropertyRole, QVariant::fromValue(val)); updateBrowser(); } @@ -317,7 +317,7 @@ void TableWidgetEditor::on_columnEditor_itemInserted(int idx) ui.tableWidget->setColumnCount(columnCount + 1); QTableWidgetItem *newItem = new QTableWidgetItem(m_columnEditor->newItemText()); - newItem->setData(Qt::DisplayPropertyRole, qVariantFromValue(PropertySheetStringValue(m_columnEditor->newItemText()))); + newItem->setData(Qt::DisplayPropertyRole, QVariant::fromValue(PropertySheetStringValue(m_columnEditor->newItemText()))); ui.tableWidget->setHorizontalHeaderItem(columnCount, newItem); moveColumnsLeft(idx, columnCount); @@ -359,7 +359,7 @@ void TableWidgetEditor::on_rowEditor_itemInserted(int idx) ui.tableWidget->setRowCount(rowCount + 1); QTableWidgetItem *newItem = new QTableWidgetItem(m_rowEditor->newItemText()); - newItem->setData(Qt::DisplayPropertyRole, qVariantFromValue(PropertySheetStringValue(m_rowEditor->newItemText()))); + newItem->setData(Qt::DisplayPropertyRole, QVariant::fromValue(PropertySheetStringValue(m_rowEditor->newItemText()))); ui.tableWidget->setVerticalHeaderItem(rowCount, newItem); moveRowsDown(idx, rowCount); diff --git a/tools/designer/src/components/taskmenu/treewidgeteditor.cpp b/tools/designer/src/components/taskmenu/treewidgeteditor.cpp index c4063d1..8fab2ad 100644 --- a/tools/designer/src/components/taskmenu/treewidgeteditor.cpp +++ b/tools/designer/src/components/taskmenu/treewidgeteditor.cpp @@ -171,8 +171,8 @@ void TreeWidgetEditor::setItemData(int role, const QVariant &v) BoolBlocker block(m_updatingBrowser); if (role == Qt::FontRole && newValue.type() == QVariant::Font) { QFont oldFont = ui.treeWidget->font(); - QFont newFont = qVariantValue<QFont>(newValue).resolve(oldFont); - newValue = qVariantFromValue(newFont); + QFont newFont = qvariant_cast<QFont>(newValue).resolve(oldFont); + newValue = QVariant::fromValue(newFont); ui.treeWidget->currentItem()->setData(col, role, QVariant()); // force the right font with the current resolve mask is set (item view bug) } ui.treeWidget->currentItem()->setData(col, role, newValue); @@ -198,7 +198,7 @@ void TreeWidgetEditor::on_newItemButton_clicked() newItem = new QTreeWidgetItem(ui.treeWidget); const QString newItemText = tr("New Item"); newItem->setText(0, newItemText); - newItem->setData(0, Qt::DisplayPropertyRole, qVariantFromValue(PropertySheetStringValue(newItemText))); + newItem->setData(0, Qt::DisplayPropertyRole, QVariant::fromValue(PropertySheetStringValue(newItemText))); newItem->setFlags(newItem->flags() | Qt::ItemIsEditable); ui.treeWidget->blockSignals(false); @@ -217,7 +217,7 @@ void TreeWidgetEditor::on_newSubItemButton_clicked() QTreeWidgetItem *newItem = new QTreeWidgetItem(curItem); const QString newItemText = tr("New Subitem"); newItem->setText(0, newItemText); - newItem->setData(0, Qt::DisplayPropertyRole, qVariantFromValue(PropertySheetStringValue(newItemText))); + newItem->setData(0, Qt::DisplayPropertyRole, QVariant::fromValue(PropertySheetStringValue(newItemText))); newItem->setFlags(newItem->flags() | Qt::ItemIsEditable); ui.treeWidget->blockSignals(false); @@ -408,10 +408,10 @@ void TreeWidgetEditor::on_treeWidget_itemChanged(QTreeWidgetItem *item, int colu if (m_updatingBrowser) return; - PropertySheetStringValue val = qVariantValue<PropertySheetStringValue>(item->data(column, Qt::DisplayPropertyRole)); + PropertySheetStringValue val = qvariant_cast<PropertySheetStringValue>(item->data(column, Qt::DisplayPropertyRole)); val.setValue(item->text(column)); BoolBlocker block(m_updatingBrowser); - item->setData(column, Qt::DisplayPropertyRole, qVariantFromValue(val)); + item->setData(column, Qt::DisplayPropertyRole, QVariant::fromValue(val)); updateBrowser(); } @@ -425,7 +425,7 @@ void TreeWidgetEditor::on_columnEditor_indexChanged(int idx) void TreeWidgetEditor::on_columnEditor_itemChanged(int idx, int role, const QVariant &v) { if (role == Qt::DisplayPropertyRole) - ui.treeWidget->headerItem()->setData(idx, Qt::EditRole, qVariantValue<PropertySheetStringValue>(v).value()); + ui.treeWidget->headerItem()->setData(idx, Qt::EditRole, qvariant_cast<PropertySheetStringValue>(v).value()); ui.treeWidget->headerItem()->setData(idx, role, v); } diff --git a/tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp b/tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp index 25798d3..ac32795 100644 --- a/tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp +++ b/tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp @@ -185,7 +185,7 @@ static QWidget *decorationFromDomWidget(DomUI *dom_ui, QDesignerFormEditorInterf fakeTopLevel->setParent(0, Qt::ToolTip); // Container // Actual widget const DomWidget *domW = dom_ui->elementWidget()->elementWidget().front(); - QWidget *w = qFindChildren<QWidget*>(fakeTopLevel).front(); + QWidget *w = fakeTopLevel->findChildren<QWidget*>().front(); Q_ASSERT(w); // hack begin; // We set _q_dockDrag dynamic property which will be detected in drag enter event of form window. diff --git a/tools/designer/src/designer/qdesigner_settings.cpp b/tools/designer/src/designer/qdesigner_settings.cpp index cc6cec5..9404e50 100644 --- a/tools/designer/src/designer/qdesigner_settings.cpp +++ b/tools/designer/src/designer/qdesigner_settings.cpp @@ -241,7 +241,7 @@ ToolWindowFontSettings QDesignerSettings::toolWindowFont() const fontSettings.m_writingSystem = static_cast<QFontDatabase::WritingSystem>(value(QLatin1String("UI/writingSystem"), QFontDatabase::Any).toInt()); - fontSettings.m_font = qVariantValue<QFont>(value(QLatin1String("UI/font"))); + fontSettings.m_font = qvariant_cast<QFont>(value(QLatin1String("UI/font"))); fontSettings.m_useFont = settings()->value(QLatin1String("UI/useFont"), QVariant(false)).toBool(); return fontSettings; diff --git a/tools/designer/src/lib/sdk/abstractintegration.cpp b/tools/designer/src/lib/sdk/abstractintegration.cpp index c5a60db..3924db6 100644 --- a/tools/designer/src/lib/sdk/abstractintegration.cpp +++ b/tools/designer/src/lib/sdk/abstractintegration.cpp @@ -42,13 +42,64 @@ #include "abstractintegration.h" #include "abstractformeditor.h" +#include <QtCore/QVariant> +#include <QtCore/QSharedPointer> + +QT_BEGIN_NAMESPACE + +// Add 'private' struct as a dynamic property. + +static const char privatePropertyC[] = "_q_integrationprivate"; + +struct QDesignerIntegrationInterfacePrivate { + QDesignerIntegrationInterfacePrivate() : + headerSuffix(QLatin1String(".h")), + headerLowercase(true) {} + + QString headerSuffix; + bool headerLowercase; +}; + +typedef QSharedPointer<QDesignerIntegrationInterfacePrivate> QDesignerIntegrationInterfacePrivatePtr; + +QT_END_NAMESPACE +Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QDesignerIntegrationInterfacePrivatePtr)) QT_BEGIN_NAMESPACE +static QDesignerIntegrationInterfacePrivatePtr integrationD(const QObject *o) +{ + const QVariant property = o->property(privatePropertyC); + Q_ASSERT(qVariantCanConvert<QDesignerIntegrationInterfacePrivatePtr>(property)); + return qvariant_cast<QDesignerIntegrationInterfacePrivatePtr>(property); +} + QDesignerIntegrationInterface::QDesignerIntegrationInterface(QDesignerFormEditorInterface *core, QObject *parent) : QObject(parent), m_core(core) { core->setIntegration(this); + const QDesignerIntegrationInterfacePrivatePtr d(new QDesignerIntegrationInterfacePrivate); + setProperty(privatePropertyC, qVariantFromValue<QDesignerIntegrationInterfacePrivatePtr>(d)); +} + +QString QDesignerIntegrationInterface::headerSuffix() const +{ + return integrationD(this)->headerSuffix; +} + +void QDesignerIntegrationInterface::setHeaderSuffix(const QString &headerSuffix) +{ + integrationD(this)->headerSuffix = headerSuffix; +} + +bool QDesignerIntegrationInterface::isHeaderLowercase() const +{ + return integrationD(this)->headerLowercase; +} + +void QDesignerIntegrationInterface::setHeaderLowercase(bool headerLowercase) +{ + integrationD(this)->headerLowercase = headerLowercase; } QT_END_NAMESPACE diff --git a/tools/designer/src/lib/sdk/abstractintegration.h b/tools/designer/src/lib/sdk/abstractintegration.h index 9b2b856..acac711 100644 --- a/tools/designer/src/lib/sdk/abstractintegration.h +++ b/tools/designer/src/lib/sdk/abstractintegration.h @@ -45,6 +45,7 @@ #include <QtDesigner/sdk_global.h> #include <QtCore/QObject> +#include <QtCore/QString> QT_BEGIN_HEADER @@ -55,6 +56,9 @@ class QDesignerFormEditorInterface; class QDESIGNER_SDK_EXPORT QDesignerIntegrationInterface: public QObject { Q_OBJECT + Q_PROPERTY(QString headerSuffix READ headerSuffix WRITE setHeaderSuffix) + Q_PROPERTY(bool headerLowercase READ isHeaderLowercase WRITE setHeaderLowercase) + public: QDesignerIntegrationInterface(QDesignerFormEditorInterface *core, QObject *parent = 0); @@ -62,6 +66,12 @@ public: virtual QWidget *containerWindow(QWidget *widget) const = 0; + QString headerSuffix() const; + void setHeaderSuffix(const QString &headerSuffix); + + bool isHeaderLowercase() const; + void setHeaderLowercase(bool headerLowerCase); + private: QDesignerFormEditorInterface *m_core; }; diff --git a/tools/designer/src/lib/shared/actioneditor.cpp b/tools/designer/src/lib/shared/actioneditor.cpp index 26ac8a8..9664a22 100644 --- a/tools/designer/src/lib/shared/actioneditor.cpp +++ b/tools/designer/src/lib/shared/actioneditor.cpp @@ -288,7 +288,7 @@ void ActionEditor::setFormWindow(QDesignerFormWindowInterface *formWindow) return; if (m_formWindow != 0) { - const ActionList actionList = qFindChildren<QAction*>(m_formWindow->mainContainer()); + const ActionList actionList = m_formWindow->mainContainer()->findChildren<QAction*>(); foreach (QAction *action, actionList) disconnect(action, SIGNAL(changed()), this, SLOT(slotActionChanged())); } @@ -311,7 +311,7 @@ void ActionEditor::setFormWindow(QDesignerFormWindowInterface *formWindow) m_actionNew->setEnabled(true); m_filterWidget->setEnabled(true); - const ActionList actionList = qFindChildren<QAction*>(formWindow->mainContainer()); + const ActionList actionList = formWindow->mainContainer()->findChildren<QAction*>(); foreach (QAction *action, actionList) if (!action->isSeparator() && core()->metaDataBase()->item(action) != 0) { // Show unless it has a menu. However, listen for change on menu actions also as it might be removed @@ -445,7 +445,6 @@ void ActionEditor::slotNewAction() if (dlg.exec() == QDialog::Accepted) { const ActionData actionData = dlg.actionData(); m_actionView->clearSelection(); - QAction *action = new QAction(formWindow()); action->setObjectName(actionData.name); formWindow()->ensureUniqueObjectName(action); @@ -459,9 +458,9 @@ void ActionEditor::slotNewAction() setInitialProperty(sheet, QLatin1String(checkablePropertyC), QVariant(true)); if (!actionData.keysequence.value().isEmpty()) - setInitialProperty(sheet, QLatin1String(shortcutPropertyC), qVariantFromValue(actionData.keysequence)); + setInitialProperty(sheet, QLatin1String(shortcutPropertyC), QVariant::fromValue(actionData.keysequence)); - sheet->setProperty(sheet->indexOf(QLatin1String(iconPropertyC)), qVariantFromValue(actionData.icon)); + sheet->setProperty(sheet->indexOf(QLatin1String(iconPropertyC)), QVariant::fromValue(actionData.icon)); AddActionCommand *cmd = new AddActionCommand(formWindow()); cmd->init(action); @@ -480,13 +479,13 @@ static inline bool isSameIcon(const QIcon &i1, const QIcon &i2) static QDesignerFormWindowCommand *setIconPropertyCommand(const PropertySheetIconValue &newIcon, QAction *action, QDesignerFormWindowInterface *fw) { const QString iconProperty = QLatin1String(iconPropertyC); - if (newIcon.paths().isEmpty()) { + if (newIcon.isEmpty()) { ResetPropertyCommand *cmd = new ResetPropertyCommand(fw); cmd->init(action, iconProperty); return cmd; } SetPropertyCommand *cmd = new SetPropertyCommand(fw); - cmd->init(action, iconProperty, qVariantFromValue(newIcon)); + cmd->init(action, iconProperty, QVariant::fromValue(newIcon)); return cmd; } @@ -502,7 +501,7 @@ static QDesignerFormWindowCommand *setKeySequencePropertyCommand(const PropertyS return cmd; } SetPropertyCommand *cmd = new SetPropertyCommand(fw); - cmd->init(action, shortcutProperty, qVariantFromValue(ks)); + cmd->init(action, shortcutProperty, QVariant::fromValue(ks)); return cmd; } @@ -528,7 +527,7 @@ static inline QString textPropertyValue(const QDesignerPropertySheetExtension *s { const int index = sheet->indexOf(name); Q_ASSERT(index != -1); - const PropertySheetStringValue ps = qVariantValue<PropertySheetStringValue>(sheet->property(index)); + const PropertySheetStringValue ps = qvariant_cast<PropertySheetStringValue>(sheet->property(index)); return ps.value(); } @@ -545,7 +544,7 @@ void ActionEditor::editAction(QAction *action) oldActionData.name = action->objectName(); oldActionData.text = action->text(); oldActionData.toolTip = textPropertyValue(sheet, QLatin1String(toolTipPropertyC)); - oldActionData.icon = qVariantValue<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String(iconPropertyC)))); + oldActionData.icon = qvariant_cast<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String(iconPropertyC)))); oldActionData.keysequence = ActionModel::actionShortCut(sheet); oldActionData.checkable = action->isCheckable(); dlg.setActionData(oldActionData); @@ -677,7 +676,7 @@ void ActionEditor::resourceImageDropped(const QString &path, QAction *action) QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), action); const PropertySheetIconValue oldIcon = - qVariantValue<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String(iconPropertyC)))); + qvariant_cast<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String(iconPropertyC)))); PropertySheetIconValue newIcon; newIcon.setPixmap(QIcon::Normal, QIcon::Off, PropertySheetPixmapValue(path)); if (newIcon.paths().isEmpty() || newIcon.paths() == oldIcon.paths()) diff --git a/tools/designer/src/lib/shared/actionrepository.cpp b/tools/designer/src/lib/shared/actionrepository.cpp index a54c1e7..40801f2 100644 --- a/tools/designer/src/lib/shared/actionrepository.cpp +++ b/tools/designer/src/lib/shared/actionrepository.cpp @@ -136,7 +136,7 @@ QModelIndex ActionModel::addAction(QAction *action) const Qt::ItemFlags flags = Qt::ItemIsSelectable|Qt::ItemIsDropEnabled|Qt::ItemIsDragEnabled|Qt::ItemIsEnabled; QVariant itemData; - qVariantSetValue(itemData, action); + itemData.setValue(action); for (int i = 0; i < NumColumns; i++) { QStandardItem *item = new QStandardItem; diff --git a/tools/designer/src/lib/shared/connectionedit.cpp b/tools/designer/src/lib/shared/connectionedit.cpp index 0bebe47..fb6cf60 100644 --- a/tools/designer/src/lib/shared/connectionedit.cpp +++ b/tools/designer/src/lib/shared/connectionedit.cpp @@ -1395,7 +1395,7 @@ void ConnectionEdit::widgetRemoved(QWidget *widget) if (m_con_list.empty()) return; - QWidgetList child_list = qFindChildren<QWidget*>(widget); + QWidgetList child_list = widget->findChildren<QWidget*>(); child_list.prepend(widget); const ConnectionSet remove_set = findConnectionsOf(m_con_list, child_list.constBegin(), child_list.constEnd()); @@ -1545,7 +1545,7 @@ void ConnectionEdit::setSource(Connection *con, const QString &obj_name) { QObject *object = 0; if (!obj_name.isEmpty()) { - object = qFindChild<QObject*>(m_bg_widget, obj_name); + object = m_bg_widget->findChild<QObject*>(obj_name); if (object == 0 && m_bg_widget->objectName() == obj_name) object = m_bg_widget; @@ -1559,7 +1559,7 @@ void ConnectionEdit::setTarget(Connection *con, const QString &obj_name) { QObject *object = 0; if (!obj_name.isEmpty()) { - object = qFindChild<QObject*>(m_bg_widget, obj_name); + object = m_bg_widget->findChild<QObject*>(obj_name); if (object == 0 && m_bg_widget->objectName() == obj_name) object = m_bg_widget; diff --git a/tools/designer/src/lib/shared/formlayoutmenu.cpp b/tools/designer/src/lib/shared/formlayoutmenu.cpp index 8d9f9a6..ff909a7 100644 --- a/tools/designer/src/lib/shared/formlayoutmenu.cpp +++ b/tools/designer/src/lib/shared/formlayoutmenu.cpp @@ -432,16 +432,16 @@ static QPair<QWidget *,QWidget *> const QString objectNameProperty = QLatin1String("objectName"); QDesignerPropertySheetExtension *labelSheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), rc.first); int nameIndex = labelSheet->indexOf(objectNameProperty); - labelSheet->setProperty(nameIndex, qVariantFromValue(PropertySheetStringValue(row.labelName))); + labelSheet->setProperty(nameIndex, QVariant::fromValue(PropertySheetStringValue(row.labelName))); labelSheet->setChanged(nameIndex, true); formWindow->ensureUniqueObjectName(rc.first); const int textIndex = labelSheet->indexOf(QLatin1String("text")); - labelSheet->setProperty(textIndex, qVariantFromValue(PropertySheetStringValue(row.labelText))); + labelSheet->setProperty(textIndex, QVariant::fromValue(PropertySheetStringValue(row.labelText))); labelSheet->setChanged(textIndex, true); // Set up properties of the control QDesignerPropertySheetExtension *controlSheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), rc.second); nameIndex = controlSheet->indexOf(objectNameProperty); - controlSheet->setProperty(nameIndex, qVariantFromValue(PropertySheetStringValue(row.fieldName))); + controlSheet->setProperty(nameIndex, QVariant::fromValue(PropertySheetStringValue(row.fieldName))); controlSheet->setChanged(nameIndex, true); formWindow->ensureUniqueObjectName(rc.second); return rc; diff --git a/tools/designer/src/lib/shared/formwindowbase.cpp b/tools/designer/src/lib/shared/formwindowbase.cpp index 5292f5f..7e65d6b 100644 --- a/tools/designer/src/lib/shared/formwindowbase.cpp +++ b/tools/designer/src/lib/shared/formwindowbase.cpp @@ -184,11 +184,11 @@ void FormWindowBase::reloadProperties() const int index = itIndex.next().key(); const QVariant newValue = sheet->property(index); if (qobject_cast<QLabel *>(sheet->object()) && sheet->propertyName(index) == QLatin1String("text")) { - const PropertySheetStringValue newString = qVariantValue<PropertySheetStringValue>(newValue); + const PropertySheetStringValue newString = qvariant_cast<PropertySheetStringValue>(newValue); // optimize a bit, reset only if the text value might contain a reference to qt resources // (however reloading of icons other than taken from resources might not work here) if (newString.value().contains(QLatin1String(":/"))) { - const QVariant resetValue = qVariantFromValue(PropertySheetStringValue()); + const QVariant resetValue = QVariant::fromValue(PropertySheetStringValue()); sheet->setProperty(index, resetValue); } } diff --git a/tools/designer/src/lib/shared/grid.cpp b/tools/designer/src/lib/shared/grid.cpp index 42296e1..67b8d5c 100644 --- a/tools/designer/src/lib/shared/grid.cpp +++ b/tools/designer/src/lib/shared/grid.cpp @@ -71,7 +71,7 @@ template <class T> const QVariantMap::const_iterator it = v.constFind(key); const bool found = it != v.constEnd(); if (found) - value = qVariantValue<T>(it.value()); + value = qvariant_cast<T>(it.value()); return found; } diff --git a/tools/designer/src/lib/shared/iconselector.cpp b/tools/designer/src/lib/shared/iconselector.cpp index 4bb7430..ef20cd2 100644 --- a/tools/designer/src/lib/shared/iconselector.cpp +++ b/tools/designer/src/lib/shared/iconselector.cpp @@ -67,8 +67,12 @@ #include <QtGui/QImageReader> #include <QtGui/QDialogButtonBox> #include <QtGui/QVBoxLayout> +#include <QtGui/QLineEdit> +#include <QtGui/QLabel> +#include <QtGui/QValidator> #include <QtCore/QDebug> + QT_BEGIN_NAMESPACE namespace qdesigner_internal { @@ -181,6 +185,14 @@ LanguageResourceDialog* LanguageResourceDialog::create(QDesignerFormEditorInterf } // ------------ IconSelectorPrivate + +static inline QPixmap emptyPixmap() +{ + QImage img(16, 16, QImage::Format_ARGB32_Premultiplied); + img.fill(0); + return QPixmap::fromImage(img); +} + class IconSelectorPrivate { IconSelector *q_ptr; @@ -201,7 +213,7 @@ public: QMap<QPair<QIcon::Mode, QIcon::State>, int> m_stateToIndex; QMap<int, QPair<QIcon::Mode, QIcon::State> > m_indexToState; - QIcon m_emptyIcon; + const QIcon m_emptyIcon; QComboBox *m_stateComboBox; QToolButton *m_iconButton; QAction *m_resetAction; @@ -215,6 +227,7 @@ public: IconSelectorPrivate::IconSelectorPrivate() : q_ptr(0), + m_emptyIcon(emptyPixmap()), m_stateComboBox(0), m_iconButton(0), m_resetAction(0), @@ -449,10 +462,6 @@ IconSelector::IconSelector(QWidget *parent) : d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Selected, QIcon::Off), tr("Selected Off") ); d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Selected, QIcon::On), tr("Selected On") ); - QImage img(16, 16, QImage::Format_ARGB32_Premultiplied); - img.fill(0); - d_ptr->m_emptyIcon = QIcon(QPixmap::fromImage(img)); - QMenu *setMenu = new QMenu(this); QAction *setResourceAction = new QAction(tr("Choose Resource..."), this); @@ -535,9 +544,112 @@ void IconSelector::setPixmapCache(DesignerPixmapCache *pixmapCache) d_ptr->slotUpdate(); } +// --- IconThemeEditor + +// Validator for theme line edit, accepts empty or non-blank strings. +class BlankSuppressingValidator : public QValidator { +public: + explicit BlankSuppressingValidator(QObject * parent = 0) : QValidator(parent) {} + + virtual State validate(QString &input, int &pos) const { + const int blankPos = input.indexOf(QLatin1Char(' ')); + if (blankPos != -1) { + pos = blankPos; + return Invalid; + } + return Acceptable; + } +}; + +struct IconThemeEditorPrivate { + IconThemeEditorPrivate(); + + const QPixmap m_emptyPixmap; + QLineEdit *m_themeLineEdit; + QLabel *m_themeLabel; +}; + +IconThemeEditorPrivate::IconThemeEditorPrivate() : + m_emptyPixmap(emptyPixmap()), + m_themeLineEdit(new QLineEdit), + m_themeLabel(new QLabel) +{ +} + +IconThemeEditor::IconThemeEditor(QWidget *parent, bool wantResetButton) : + QWidget (parent), d(new IconThemeEditorPrivate) +{ + QHBoxLayout *mainHLayout = new QHBoxLayout; + mainHLayout->setMargin(0); + + // Vertically center theme preview label + d->m_themeLabel->setPixmap(d->m_emptyPixmap); + + QVBoxLayout *themeLabelVLayout = new QVBoxLayout; + d->m_themeLabel->setMargin(1); + themeLabelVLayout->setMargin(0); + themeLabelVLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding)); + themeLabelVLayout->addWidget(d->m_themeLabel); + themeLabelVLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding)); + mainHLayout->addLayout(themeLabelVLayout); + + d->m_themeLineEdit = new QLineEdit; + d->m_themeLineEdit->setValidator(new BlankSuppressingValidator(d->m_themeLineEdit)); + connect(d->m_themeLineEdit, SIGNAL(textChanged(QString)), this, SLOT(slotChanged(QString))); + connect(d->m_themeLineEdit, SIGNAL(textEdited(QString)), this, SIGNAL(edited(QString))); + mainHLayout->addWidget(d->m_themeLineEdit); + + if (wantResetButton) { + QToolButton *themeResetButton = new QToolButton; + themeResetButton->setIcon(createIconSet(QLatin1String("resetproperty.png"))); + connect(themeResetButton, SIGNAL(clicked()), this, SLOT(reset())); + mainHLayout->addWidget(themeResetButton); + } + + setLayout(mainHLayout); + setFocusProxy(d->m_themeLineEdit); +} + +IconThemeEditor::~IconThemeEditor() +{ +} + +void IconThemeEditor::reset() +{ + d->m_themeLineEdit->clear(); + emit edited(QString()); +} + +void IconThemeEditor::slotChanged(const QString &theme) +{ + updatePreview(theme); +} + +void IconThemeEditor::updatePreview(const QString &t) +{ + // Update preview label with icon. + if (t.isEmpty() || !QIcon::hasThemeIcon(t)) { // Empty + const QPixmap *currentPixmap = d->m_themeLabel->pixmap(); + if (currentPixmap == 0 || currentPixmap->serialNumber() != d->m_emptyPixmap.serialNumber()) + d->m_themeLabel->setPixmap(d->m_emptyPixmap); + } else { + const QIcon icon = QIcon::fromTheme(t); + d->m_themeLabel->setPixmap(icon.pixmap(d->m_emptyPixmap.size())); + } +} + +QString IconThemeEditor::theme() const +{ + return d->m_themeLineEdit->text(); +} + +void IconThemeEditor::setTheme(const QString &t) +{ + d->m_themeLineEdit->setText(t); +} + } // qdesigner_internal QT_END_NAMESPACE #include "moc_iconselector_p.cpp" - diff --git a/tools/designer/src/lib/shared/iconselector_p.h b/tools/designer/src/lib/shared/iconselector_p.h index 3373f80..5fa8f80 100644 --- a/tools/designer/src/lib/shared/iconselector_p.h +++ b/tools/designer/src/lib/shared/iconselector_p.h @@ -55,9 +55,12 @@ #define ICONSELECTOR_H #include "shared_global_p.h" + #include <QtGui/QWidget> #include <QtGui/QDialog> +#include <QtCore/QScopedPointer> + QT_BEGIN_NAMESPACE class QtResourceModel; @@ -70,6 +73,7 @@ namespace qdesigner_internal { class DesignerIconCache; class DesignerPixmapCache; class PropertySheetIconValue; +struct IconThemeEditorPrivate; // Resource Dialog that embeds the language-dependent resource widget as returned by the language extension class QDESIGNER_SHARED_EXPORT LanguageResourceDialog : public QDialog @@ -133,6 +137,32 @@ private: Q_PRIVATE_SLOT(d_func(), void slotUpdate()) }; +// IconThemeEditor: Let's the user input theme icon names and shows a preview label. +class QDESIGNER_SHARED_EXPORT IconThemeEditor : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QString theme READ theme WRITE setTheme DESIGNABLE true) +public: + explicit IconThemeEditor(QWidget *parent = 0, bool wantResetButton = true); + virtual ~IconThemeEditor(); + + QString theme() const; + void setTheme(const QString &theme); + +signals: + void edited(const QString &); + +public slots: + void reset(); + +private slots: + void slotChanged(const QString &); + +private: + void updatePreview(const QString &); + + QScopedPointer<IconThemeEditorPrivate> d; +}; } // namespace qdesigner_internal diff --git a/tools/designer/src/lib/shared/layoutinfo.cpp b/tools/designer/src/lib/shared/layoutinfo.cpp index ad2dda4..309aa37 100644 --- a/tools/designer/src/lib/shared/layoutinfo.cpp +++ b/tools/designer/src/lib/shared/layoutinfo.cpp @@ -190,7 +190,7 @@ LayoutInfo::Type LayoutInfo::laidoutWidgetType(const QDesignerFormEditorInterfac } // 3) Some child layout (see below comment about Q3GroupBox) - const QList<QLayout*> childLayouts = qFindChildren<QLayout*>(parentLayout); + const QList<QLayout*> childLayouts = parentLayout->findChildren<QLayout*>(); if (childLayouts.empty()) return NoLayout; const QList<QLayout*>::const_iterator lcend = childLayouts.constEnd(); @@ -244,7 +244,7 @@ QLayout *LayoutInfo::managedLayout(const QDesignerFormEditorInterface *core, QLa * widget->layout() returns an internal VBoxLayout. */ const QDesignerMetaDataBaseItemInterface *item = metaDataBase->item(layout); if (item == 0) { - layout = qFindChild<QLayout*>(layout); + layout = layout->findChild<QLayout*>(); item = metaDataBase->item(layout); } if (!item) diff --git a/tools/designer/src/lib/shared/morphmenu.cpp b/tools/designer/src/lib/shared/morphmenu.cpp index de85d37..80eac0c 100644 --- a/tools/designer/src/lib/shared/morphmenu.cpp +++ b/tools/designer/src/lib/shared/morphmenu.cpp @@ -240,7 +240,7 @@ static QString suggestObjectName(const QString &oldClassName, const QString &new QLabel *buddyLabelOf(QDesignerFormWindowInterface *fw, QWidget *w) { typedef QList<QLabel*> LabelList; - const LabelList labelList = qFindChildren<QLabel*>(fw); + const LabelList labelList = fw->findChildren<QLabel*>(); if (labelList.empty()) return 0; const LabelList::const_iterator cend = labelList.constEnd(); @@ -256,11 +256,11 @@ static void replaceWidgetListDynamicProperty(QWidget *parentWidget, QWidget *oldWidget, QWidget *newWidget, const char *name) { - QWidgetList list = qVariantValue<QWidgetList>(parentWidget->property(name)); + QWidgetList list = qvariant_cast<QWidgetList>(parentWidget->property(name)); const int index = list.indexOf(oldWidget); if (index != -1) { list.replace(index, newWidget); - parentWidget->setProperty(name, qVariantFromValue(list)); + parentWidget->setProperty(name, QVariant::fromValue(list)); } } diff --git a/tools/designer/src/lib/shared/newactiondialog.cpp b/tools/designer/src/lib/shared/newactiondialog.cpp index b411464..e6c95f6 100644 --- a/tools/designer/src/lib/shared/newactiondialog.cpp +++ b/tools/designer/src/lib/shared/newactiondialog.cpp @@ -133,6 +133,7 @@ ActionData NewActionDialog::actionData() const rc.name = actionName(); rc.toolTip = m_ui->tooltipEditor->text(); rc.icon = m_ui->iconSelector->icon(); + rc.icon.setTheme(m_ui->iconThemeEditor->theme()); rc.checkable = m_ui->checkableCheckBox->checkState() == Qt::Checked; rc.keysequence = PropertySheetKeySequenceValue(m_ui->keySequenceEdit->keySequence()); return rc; @@ -142,7 +143,8 @@ void NewActionDialog::setActionData(const ActionData &d) { m_ui->editActionText->setText(d.text); m_ui->editObjectName->setText(d.name); - m_ui->iconSelector->setIcon(d.icon); + m_ui->iconSelector->setIcon(d.icon.unthemed()); + m_ui->iconThemeEditor->setTheme(d.icon.theme()); m_ui->tooltipEditor->setText(d.toolTip); m_ui->keySequenceEdit->setKeySequence(d.keysequence.value()); m_ui->checkableCheckBox->setCheckState(d.checkable ? Qt::Checked : Qt::Unchecked); diff --git a/tools/designer/src/lib/shared/newactiondialog.ui b/tools/designer/src/lib/shared/newactiondialog.ui index f9cafd1..ca5406f 100644 --- a/tools/designer/src/lib/shared/newactiondialog.ui +++ b/tools/designer/src/lib/shared/newactiondialog.ui @@ -42,6 +42,14 @@ *********************************************************************</comment> <class>qdesigner_internal::NewActionDialog</class> <widget class="QDialog" name="qdesigner_internal::NewActionDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>366</width> + <height>270</height> + </rect> + </property> <property name="windowTitle"> <string>New Action...</string> </property> @@ -81,7 +89,7 @@ <item row="1" column="1"> <widget class="QLineEdit" name="editObjectName"/> </item> - <item row="3" column="0"> + <item row="4" column="0"> <widget class="QLabel" name="iconLabel"> <property name="text"> <string>&Icon:</string> @@ -91,7 +99,7 @@ </property> </widget> </item> - <item row="3" column="1"> + <item row="4" column="1"> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="qdesigner_internal::IconSelector" name="iconSelector" native="true"/> @@ -111,31 +119,40 @@ </item> </layout> </item> - <item row="5" column="0"> + <item row="6" column="0"> <widget class="QLabel" name="shortcutLabel"> <property name="text"> - <string>Shortcut:</string> + <string>&Shortcut:</string> + </property> + <property name="buddy"> + <cstring>keySequenceEdit</cstring> </property> </widget> </item> - <item row="4" column="1"> + <item row="5" column="1"> <widget class="QCheckBox" name="checkableCheckBox"> <property name="text"> <string/> </property> </widget> </item> - <item row="4" column="0"> + <item row="5" column="0"> <widget class="QLabel" name="checkableLabel"> <property name="text"> - <string>Checkable:</string> + <string>&Checkable:</string> + </property> + <property name="buddy"> + <cstring>checkableCheckBox</cstring> </property> </widget> </item> <item row="2" column="0"> <widget class="QLabel" name="toolTipLabel"> <property name="text"> - <string>ToolTip:</string> + <string>T&oolTip:</string> + </property> + <property name="buddy"> + <cstring>tooltipEditor</cstring> </property> </widget> </item> @@ -160,7 +177,7 @@ </item> </layout> </item> - <item row="5" column="1"> + <item row="6" column="1"> <layout class="QHBoxLayout" name="keysequenceLayout"> <item> <widget class="QtKeySequenceEdit" name="keySequenceEdit" native="true"> @@ -181,6 +198,19 @@ </item> </layout> </item> + <item row="3" column="0"> + <widget class="QLabel" name="iconThemeLabel"> + <property name="text"> + <string>Icon th&eme:</string> + </property> + <property name="buddy"> + <cstring>iconThemeEditor</cstring> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="qdesigner_internal::IconThemeEditor" name="iconThemeEditor" native="true"/> + </item> </layout> </item> <item> @@ -234,6 +264,12 @@ <header>textpropertyeditor_p.h</header> <container>1</container> </customwidget> + <customwidget> + <class>qdesigner_internal::IconThemeEditor</class> + <extends>QWidget</extends> + <header>iconselector_p.h</header> + <container>1</container> + </customwidget> </customwidgets> <tabstops> <tabstop>editActionText</tabstop> diff --git a/tools/designer/src/lib/shared/qdesigner_command.cpp b/tools/designer/src/lib/shared/qdesigner_command.cpp index 69206df..8c01000 100644 --- a/tools/designer/src/lib/shared/qdesigner_command.cpp +++ b/tools/designer/src/lib/shared/qdesigner_command.cpp @@ -107,23 +107,23 @@ static const char *zOrderPropertyC = "_q_zOrder"; static void addToWidgetListDynamicProperty(QWidget *parentWidget, QWidget *widget, const char *name, int index = -1) { - QWidgetList list = qVariantValue<QWidgetList>(parentWidget->property(name)); + QWidgetList list = qvariant_cast<QWidgetList>(parentWidget->property(name)); list.removeAll(widget); if (index >= 0 && index < list.size()) { list.insert(index, widget); } else { list.append(widget); } - parentWidget->setProperty(name, qVariantFromValue(list)); + parentWidget->setProperty(name, QVariant::fromValue(list)); } static int removeFromWidgetListDynamicProperty(QWidget *parentWidget, QWidget *widget, const char *name) { - QWidgetList list = qVariantValue<QWidgetList>(parentWidget->property(name)); + QWidgetList list = qvariant_cast<QWidgetList>(parentWidget->property(name)); const int firstIndex = list.indexOf(widget); if (firstIndex != -1) { list.removeAll(widget); - parentWidget->setProperty(name, qVariantFromValue(list)); + parentWidget->setProperty(name, QVariant::fromValue(list)); } return firstIndex; } @@ -247,7 +247,7 @@ void InsertWidgetCommand::refreshBuddyLabels() { typedef QList<QLabel*> LabelList; - const LabelList label_list = qFindChildren<QLabel*>(formWindow()); + const LabelList label_list = formWindow()->findChildren<QLabel*>(); if (label_list.empty()) return; @@ -281,7 +281,7 @@ void ChangeZOrderCommand::init(QWidget *widget) setText(QApplication::translate("Command", "Change Z-order of '%1'").arg(widget->objectName())); - m_oldParentZOrder = qVariantValue<QWidgetList>(widget->parentWidget()->property("_q_zOrder")); + m_oldParentZOrder = qvariant_cast<QWidgetList>(widget->parentWidget()->property("_q_zOrder")); const int index = m_oldParentZOrder.indexOf(m_widget); if (index != -1 && index + 1 < m_oldParentZOrder.count()) m_oldPreceding = m_oldParentZOrder.at(index + 1); @@ -289,14 +289,14 @@ void ChangeZOrderCommand::init(QWidget *widget) void ChangeZOrderCommand::redo() { - m_widget->parentWidget()->setProperty("_q_zOrder", qVariantFromValue(reorderWidget(m_oldParentZOrder, m_widget))); + m_widget->parentWidget()->setProperty("_q_zOrder", QVariant::fromValue(reorderWidget(m_oldParentZOrder, m_widget))); reorder(m_widget); } void ChangeZOrderCommand::undo() { - m_widget->parentWidget()->setProperty("_q_zOrder", qVariantFromValue(m_oldParentZOrder)); + m_widget->parentWidget()->setProperty("_q_zOrder", QVariant::fromValue(m_oldParentZOrder)); if (m_oldPreceding) m_widget->stackUnder(m_oldPreceding); @@ -365,7 +365,7 @@ void ManageWidgetCommandHelper::init(const QDesignerFormWindowInterface *fw, QWi m_widget = widget; m_managedChildren.clear(); - const QWidgetList children = qFindChildren<QWidget *>(m_widget); + const QWidgetList children = m_widget->findChildren<QWidget *>(); if (children.empty()) return; @@ -580,8 +580,8 @@ void ReparentWidgetCommand::init(QWidget *widget, QWidget *parentWidget) setText(QApplication::translate("Command", "Reparent '%1'").arg(widget->objectName())); - m_oldParentList = qVariantValue<QWidgetList>(m_oldParentWidget->property("_q_widgetOrder")); - m_oldParentZOrder = qVariantValue<QWidgetList>(m_oldParentWidget->property("_q_zOrder")); + m_oldParentList = qvariant_cast<QWidgetList>(m_oldParentWidget->property("_q_widgetOrder")); + m_oldParentZOrder = qvariant_cast<QWidgetList>(m_oldParentWidget->property("_q_zOrder")); } void ReparentWidgetCommand::redo() @@ -591,19 +591,19 @@ void ReparentWidgetCommand::redo() QWidgetList oldList = m_oldParentList; oldList.removeAll(m_widget); - m_oldParentWidget->setProperty("_q_widgetOrder", qVariantFromValue(oldList)); + m_oldParentWidget->setProperty("_q_widgetOrder", QVariant::fromValue(oldList)); - QWidgetList newList = qVariantValue<QWidgetList>(m_newParentWidget->property("_q_widgetOrder")); + QWidgetList newList = qvariant_cast<QWidgetList>(m_newParentWidget->property("_q_widgetOrder")); newList.append(m_widget); - m_newParentWidget->setProperty("_q_widgetOrder", qVariantFromValue(newList)); + m_newParentWidget->setProperty("_q_widgetOrder", QVariant::fromValue(newList)); QWidgetList oldZOrder = m_oldParentZOrder; oldZOrder.removeAll(m_widget); - m_oldParentWidget->setProperty("_q_zOrder", qVariantFromValue(oldZOrder)); + m_oldParentWidget->setProperty("_q_zOrder", QVariant::fromValue(oldZOrder)); - QWidgetList newZOrder = qVariantValue<QWidgetList>(m_newParentWidget->property("_q_zOrder")); + QWidgetList newZOrder = qvariant_cast<QWidgetList>(m_newParentWidget->property("_q_zOrder")); newZOrder.append(m_widget); - m_newParentWidget->setProperty("_q_zOrder", qVariantFromValue(newZOrder)); + m_newParentWidget->setProperty("_q_zOrder", QVariant::fromValue(newZOrder)); m_widget->show(); core()->objectInspector()->setFormWindow(formWindow()); @@ -614,16 +614,16 @@ void ReparentWidgetCommand::undo() m_widget->setParent(m_oldParentWidget); m_widget->move(m_oldPos); - m_oldParentWidget->setProperty("_q_widgetOrder", qVariantFromValue(m_oldParentList)); + m_oldParentWidget->setProperty("_q_widgetOrder", QVariant::fromValue(m_oldParentList)); - QWidgetList newList = qVariantValue<QWidgetList>(m_newParentWidget->property("_q_widgetOrder")); + QWidgetList newList = qvariant_cast<QWidgetList>(m_newParentWidget->property("_q_widgetOrder")); newList.removeAll(m_widget); - m_newParentWidget->setProperty("_q_widgetOrder", qVariantFromValue(newList)); + m_newParentWidget->setProperty("_q_widgetOrder", QVariant::fromValue(newList)); - m_oldParentWidget->setProperty("_q_zOrder", qVariantFromValue(m_oldParentZOrder)); + m_oldParentWidget->setProperty("_q_zOrder", QVariant::fromValue(m_oldParentZOrder)); - QWidgetList newZOrder = qVariantValue<QWidgetList>(m_newParentWidget->property("_q_zOrder")); - m_newParentWidget->setProperty("_q_zOrder", qVariantFromValue(newZOrder)); + QWidgetList newZOrder = qvariant_cast<QWidgetList>(m_newParentWidget->property("_q_zOrder")); + m_newParentWidget->setProperty("_q_zOrder", QVariant::fromValue(newZOrder)); m_widget->show(); core()->objectInspector()->setFormWindow(formWindow()); @@ -1016,7 +1016,7 @@ void ToolBoxCommand::addPage() QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(formWindow()->core()->extensionManager(), m_toolBox); if (sheet) { qdesigner_internal::PropertySheetStringValue itemText(m_itemText); - sheet->setProperty(sheet->indexOf(QLatin1String("currentItemText")), qVariantFromValue(itemText)); + sheet->setProperty(sheet->indexOf(QLatin1String("currentItemText")), QVariant::fromValue(itemText)); } m_widget->show(); @@ -1176,7 +1176,7 @@ void TabWidgetCommand::addPage() QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(formWindow()->core()->extensionManager(), m_tabWidget); if (sheet) { qdesigner_internal::PropertySheetStringValue itemText(m_itemText); - sheet->setProperty(sheet->indexOf(QLatin1String("currentTabText")), qVariantFromValue(itemText)); + sheet->setProperty(sheet->indexOf(QLatin1String("currentTabText")), QVariant::fromValue(itemText)); } formWindow()->clearSelection(); @@ -2193,7 +2193,7 @@ static void copyRolesFromItem(ItemData *id, const T *item, bool editor) if (editor) copyRoleFromItem<T>(id, ItemFlagsShadowRole, item); else if (item->flags() != defaultFlags) - id->m_properties.insert(ItemFlagsShadowRole, qVariantFromValue((int)item->flags())); + id->m_properties.insert(ItemFlagsShadowRole, QVariant::fromValue((int)item->flags())); } template<class T> @@ -2210,19 +2210,19 @@ static void copyRolesToItem(const ItemData *id, T *item, DesignerIconCache *icon switch (it.key()) { case Qt::DecorationPropertyRole: if (iconCache) - item->setIcon(iconCache->icon(qVariantValue<PropertySheetIconValue>(it.value()))); + item->setIcon(iconCache->icon(qvariant_cast<PropertySheetIconValue>(it.value()))); break; case Qt::DisplayPropertyRole: - item->setText(qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setText(qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; case Qt::ToolTipPropertyRole: - item->setToolTip(qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setToolTip(qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; case Qt::StatusTipPropertyRole: - item->setStatusTip(qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setStatusTip(qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; case Qt::WhatsThisPropertyRole: - item->setWhatsThis(qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setWhatsThis(qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; } } @@ -2267,7 +2267,7 @@ ItemData::ItemData(const QTreeWidgetItem *item, int column) { copyRoleFromItem(this, Qt::EditRole, item, column); PropertySheetStringValue str(item->text(column)); - m_properties.insert(Qt::DisplayPropertyRole, qVariantFromValue(str)); + m_properties.insert(Qt::DisplayPropertyRole, QVariant::fromValue(str)); for (int i = 0; itemRoles[i] != -1; i++) copyRoleFromItem(this, itemRoles[i], item, column); @@ -2282,19 +2282,19 @@ void ItemData::fillTreeItemColumn(QTreeWidgetItem *item, int column, DesignerIco switch (it.key()) { case Qt::DecorationPropertyRole: if (iconCache) - item->setIcon(column, iconCache->icon(qVariantValue<PropertySheetIconValue>(it.value()))); + item->setIcon(column, iconCache->icon(qvariant_cast<PropertySheetIconValue>(it.value()))); break; case Qt::DisplayPropertyRole: - item->setText(column, qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setText(column, qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; case Qt::ToolTipPropertyRole: - item->setToolTip(column, qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setToolTip(column, qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; case Qt::StatusTipPropertyRole: - item->setStatusTip(column, qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setStatusTip(column, qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; case Qt::WhatsThisPropertyRole: - item->setWhatsThis(column, qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setWhatsThis(column, qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; } } @@ -2364,10 +2364,10 @@ void ListContents::applyToComboBox(QComboBox *comboBox, DesignerIconCache *iconC foreach (const ItemData &hash, m_items) { QIcon icon; if (iconCache) - icon = iconCache->icon(qVariantValue<PropertySheetIconValue>( + icon = iconCache->icon(qvariant_cast<PropertySheetIconValue>( hash.m_properties[Qt::DecorationPropertyRole])); QVariant var = hash.m_properties[Qt::DisplayPropertyRole]; - PropertySheetStringValue str = qVariantValue<PropertySheetStringValue>(var); + PropertySheetStringValue str = qvariant_cast<PropertySheetStringValue>(var); comboBox->addItem(icon, str.value()); comboBox->setItemData(comboBox->count() - 1, var, @@ -2407,7 +2407,7 @@ bool TableWidgetContents::nonEmpty(const QTableWidgetItem *item, int headerColum if (item->flags() != defaultFlags) return true; - QString text = qVariantValue<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole)).value(); + QString text = qvariant_cast<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole)).value(); if (!text.isEmpty()) { if (headerColumn < 0 || text != defaultHeaderText(headerColumn)) return true; @@ -2545,7 +2545,7 @@ QTreeWidgetItem *TreeWidgetContents::ItemContents::createTreeItem(DesignerIconCa if (m_itemFlags != -1) { if (editor) - item->setData(0, ItemFlagsShadowRole, qVariantFromValue(m_itemFlags)); + item->setData(0, ItemFlagsShadowRole, QVariant::fromValue(m_itemFlags)); else item->setFlags((Qt::ItemFlags)m_itemFlags); } diff --git a/tools/designer/src/lib/shared/qdesigner_formbuilder.cpp b/tools/designer/src/lib/shared/qdesigner_formbuilder.cpp index 14e0d81..b881589 100644 --- a/tools/designer/src/lib/shared/qdesigner_formbuilder.cpp +++ b/tools/designer/src/lib/shared/qdesigner_formbuilder.cpp @@ -243,7 +243,7 @@ static bool readDomEnumerationValue(const DomProperty *p, if (index == -1) return false; const QVariant sheetValue = sheet->property(index); - if (qVariantCanConvert<PropertySheetFlagValue>(sheetValue)) { + if (sheetValue.canConvert<PropertySheetFlagValue>()) { const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(sheetValue); bool ok = false; v = f.metaFlags.parseFlags(p->elementSet(), &ok); @@ -258,7 +258,7 @@ static bool readDomEnumerationValue(const DomProperty *p, if (index == -1) return false; const QVariant sheetValue = sheet->property(index); - if (qVariantCanConvert<PropertySheetEnumValue>(sheetValue)) { + if (sheetValue.canConvert<PropertySheetEnumValue>()) { const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(sheetValue); bool ok = false; v = e.metaEnum.parseEnum(p->elementEnum(), &ok); diff --git a/tools/designer/src/lib/shared/qdesigner_formwindowcommand.cpp b/tools/designer/src/lib/shared/qdesigner_formwindowcommand.cpp index 490373e..675752e 100644 --- a/tools/designer/src/lib/shared/qdesigner_formwindowcommand.cpp +++ b/tools/designer/src/lib/shared/qdesigner_formwindowcommand.cpp @@ -115,7 +115,7 @@ void QDesignerFormWindowCommand::updateBuddies(QDesignerFormWindowInterface *for typedef QList<QLabel*> LabelList; - const LabelList label_list = qFindChildren<QLabel*>(form); + const LabelList label_list = form->findChildren<QLabel*>(); if (label_list.empty()) return; diff --git a/tools/designer/src/lib/shared/qdesigner_menu.cpp b/tools/designer/src/lib/shared/qdesigner_menu.cpp index 31a226a..3d9fdf1 100644 --- a/tools/designer/src/lib/shared/qdesigner_menu.cpp +++ b/tools/designer/src/lib/shared/qdesigner_menu.cpp @@ -477,7 +477,7 @@ bool QDesignerMenu::handleContextMenuEvent(QWidget *, QContextMenuEvent *event) QMenu menu; QVariant itemData; - qVariantSetValue(itemData, action); + itemData.setValue(action); QAction *addSeparatorAction = menu.addAction(tr("Insert separator")); addSeparatorAction->setData(itemData); @@ -630,7 +630,7 @@ QDesignerMenu *QDesignerMenu::findActivatedMenu() const { QList<QDesignerMenu*> candidates; candidates.append(const_cast<QDesignerMenu*>(this)); - candidates += qFindChildren<QDesignerMenu*>(this); + candidates += findChildren<QDesignerMenu*>(); foreach (QDesignerMenu *m, candidates) { if (m == qApp->activeWindow()) @@ -867,7 +867,7 @@ void QDesignerMenu::closeMenuChain() w = w->parentWidget(); if (w) { - foreach (QMenu *subMenu, qFindChildren<QMenu*>(w)) { + foreach (QMenu *subMenu, w->findChildren<QMenu*>()) { subMenu->hide(); } } @@ -1323,7 +1323,7 @@ QAction *QDesignerMenu::safeActionAt(int index) const void QDesignerMenu::hideSubMenu() { m_lastSubMenuIndex = -1; - foreach (QMenu *subMenu, qFindChildren<QMenu*>(this)) { + foreach (QMenu *subMenu, findChildren<QMenu*>()) { subMenu->hide(); } } diff --git a/tools/designer/src/lib/shared/qdesigner_menubar.cpp b/tools/designer/src/lib/shared/qdesigner_menubar.cpp index 8d53037..b017264 100644 --- a/tools/designer/src/lib/shared/qdesigner_menubar.cpp +++ b/tools/designer/src/lib/shared/qdesigner_menubar.cpp @@ -403,7 +403,7 @@ ActionList QDesignerMenuBar::contextMenuActions() if (QAction *action = safeActionAt(m_currentIndex)) { if (!qobject_cast<SpecialMenuAction*>(action)) { QVariant itemData; - qVariantSetValue(itemData, action); + itemData.setValue(action); QAction *remove_action = new QAction(tr("Remove Menu '%1'").arg(action->menu()->objectName()), 0); remove_action->setData(itemData); diff --git a/tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp b/tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp index eca6615..1fbfccb 100644 --- a/tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp +++ b/tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp @@ -49,6 +49,7 @@ #include <QtDesigner/QDesignerFormWindowInterface> #include <QtDesigner/QDesignerPromotionInterface> #include <QtDesigner/QDesignerWidgetDataBaseItemInterface> +#include <QtDesigner/QDesignerIntegrationInterface> #include <abstractdialoggui_p.h> #include <QtCore/QTimer> @@ -152,8 +153,13 @@ namespace qdesigner_internal { void NewPromotedClassPanel::slotNameChanged(const QString &className) { // Suggest a name if (!className.isEmpty()) { - QString suggestedHeader = className.toLower().replace(QLatin1String("::"), QString(QLatin1Char('_'))); - suggestedHeader += QLatin1String(".h"); + const QChar dot(QLatin1Char('.')); + QString suggestedHeader = m_promotedHeaderLowerCase ? + className.toLower() : className; + suggestedHeader.replace(QLatin1String("::"), QString(QLatin1Char('_'))); + if (!m_promotedHeaderSuffix.startsWith(dot)) + suggestedHeader += dot; + suggestedHeader += m_promotedHeaderSuffix; const bool blocked = m_includeFileEdit->blockSignals(true); m_includeFileEdit->setText(suggestedHeader); @@ -248,6 +254,8 @@ namespace qdesigner_internal { preselectedBaseClass = baseClassNameList.indexOf(QLatin1String("QFrame")); NewPromotedClassPanel *newPromotedClassPanel = new NewPromotedClassPanel(baseClassNameList, preselectedBaseClass); + newPromotedClassPanel->setPromotedHeaderSuffix(core->integration()->headerSuffix()); + newPromotedClassPanel->setPromotedHeaderLowerCase(core->integration()->isHeaderLowercase()); connect(newPromotedClassPanel, SIGNAL(newPromotedClass(PromotionParameters,bool*)), this, SLOT(slotNewPromotedClass(PromotionParameters,bool*))); connect(this, SIGNAL(selectedBaseClassChanged(QString)), newPromotedClassPanel, SLOT(chooseBaseClass(QString))); diff --git a/tools/designer/src/lib/shared/qdesigner_promotiondialog_p.h b/tools/designer/src/lib/shared/qdesigner_promotiondialog_p.h index 1e63d81..f2a2b2a 100644 --- a/tools/designer/src/lib/shared/qdesigner_promotiondialog_p.h +++ b/tools/designer/src/lib/shared/qdesigner_promotiondialog_p.h @@ -84,7 +84,13 @@ namespace qdesigner_internal { int selectedBaseClass = -1, QWidget *parent = 0); - signals: + QString promotedHeaderSuffix() const { return m_promotedHeaderSuffix; } + void setPromotedHeaderSuffix(const QString &s) { m_promotedHeaderSuffix = s; } + + bool isPromotedHeaderLowerCase() const { return m_promotedHeaderLowerCase; } + void setPromotedHeaderLowerCase(bool l) { m_promotedHeaderLowerCase = l; } + + signals: void newPromotedClass(const PromotionParameters &, bool *ok); public slots: @@ -100,6 +106,9 @@ namespace qdesigner_internal { PromotionParameters promotionParameters() const; void enableButtons(); + QString m_promotedHeaderSuffix; + bool m_promotedHeaderLowerCase; + QComboBox *m_baseClassCombo; QLineEdit *m_classNameEdit; QLineEdit *m_includeFileEdit; diff --git a/tools/designer/src/lib/shared/qdesigner_propertycommand.cpp b/tools/designer/src/lib/shared/qdesigner_propertycommand.cpp index 6cc054c..08385b5 100644 --- a/tools/designer/src/lib/shared/qdesigner_propertycommand.cpp +++ b/tools/designer/src/lib/shared/qdesigner_propertycommand.cpp @@ -505,7 +505,7 @@ PropertyHelper::Value applySubProperty(const QVariant &oldValue, const QVariant case QVariant::Size: return PropertyHelper::Value(applySizeSubProperty(oldValue.toSize(), newValue.toSize(), mask), changed); case QVariant::SizePolicy: - return PropertyHelper::Value(qVariantFromValue(applySizePolicySubProperty(qvariant_cast<QSizePolicy>(oldValue), qvariant_cast<QSizePolicy>(newValue), mask)), changed); + return PropertyHelper::Value(QVariant::fromValue(applySizePolicySubProperty(qvariant_cast<QSizePolicy>(oldValue), qvariant_cast<QSizePolicy>(newValue), mask)), changed); case QVariant::Font: { // Changed flag in case of font and palette depends on resolve mask only, not on the passed "changed" value. @@ -524,27 +524,27 @@ PropertyHelper::Value applySubProperty(const QVariant &oldValue, const QVariant // He press reset button for the whole font property. In result whole font properties for both // widgets should be marked as unchanged. QFont font = applyFontSubProperty(qvariant_cast<QFont>(oldValue), qvariant_cast<QFont>(newValue), mask); - return PropertyHelper::Value(qVariantFromValue(font), font.resolve()); + return PropertyHelper::Value(QVariant::fromValue(font), font.resolve()); } case QVariant::Palette: { QPalette palette = applyPaletteSubProperty(qvariant_cast<QPalette>(oldValue), qvariant_cast<QPalette>(newValue), mask); - return PropertyHelper::Value(qVariantFromValue(palette), palette.resolve()); + return PropertyHelper::Value(QVariant::fromValue(palette), palette.resolve()); } default: if (oldValue.userType() == qMetaTypeId<qdesigner_internal::PropertySheetIconValue>()) { PropertySheetIconValue icon = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(oldValue); icon.assign(qvariant_cast<qdesigner_internal::PropertySheetIconValue>(newValue), mask); - return PropertyHelper::Value(qVariantFromValue(icon), icon.mask()); + return PropertyHelper::Value(QVariant::fromValue(icon), icon.mask()); } else if (oldValue.userType() == qMetaTypeId<qdesigner_internal::PropertySheetStringValue>()) { qdesigner_internal::PropertySheetStringValue str = applyStringSubProperty( qvariant_cast<qdesigner_internal::PropertySheetStringValue>(oldValue), qvariant_cast<qdesigner_internal::PropertySheetStringValue>(newValue), mask); - return PropertyHelper::Value(qVariantFromValue(str), changed); + return PropertyHelper::Value(QVariant::fromValue(str), changed); } else if (oldValue.userType() == qMetaTypeId<qdesigner_internal::PropertySheetKeySequenceValue>()) { qdesigner_internal::PropertySheetKeySequenceValue key = applyKeySequenceSubProperty( qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(oldValue), qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(newValue), mask); - return PropertyHelper::Value(qVariantFromValue(key), changed); + return PropertyHelper::Value(QVariant::fromValue(key), changed); } // Enumerations, flags switch (specialProperty) { @@ -552,7 +552,7 @@ PropertyHelper::Value applySubProperty(const QVariant &oldValue, const QVariant qdesigner_internal::PropertySheetFlagValue f = qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(oldValue); f.value = applyAlignmentSubProperty(variantToAlignment(oldValue), variantToAlignment(newValue), mask); QVariant v; - qVariantSetValue(v, f); + v.setValue(f); return PropertyHelper::Value(v, changed); } default: @@ -651,7 +651,7 @@ void PropertyHelper::checkApplyWidgetValue(QDesignerFormWindowInterface *fw, QWi switch (specialProperty) { case SP_MinimumSize: { const QSize size = checkSize(value.toSize()); - qVariantSetValue(value, size); + value.setValue(size); } break; @@ -660,7 +660,7 @@ void PropertyHelper::checkApplyWidgetValue(QDesignerFormWindowInterface *fw, QWi checkSizes(fw, value.toSize(), &fs, &cs); container->setMaximumSize(cs); fw->mainContainer()->setMaximumSize(fs); - qVariantSetValue(value, fs); + value.setValue(fs); } break; @@ -670,7 +670,7 @@ void PropertyHelper::checkApplyWidgetValue(QDesignerFormWindowInterface *fw, QWi checkSizes(fw, r.size(), &fs, &cs); container->resize(cs); r.setSize(fs); - qVariantSetValue(value, r); + value.setValue(r); } break; default: @@ -727,8 +727,8 @@ void PropertyHelper::updateObject(QDesignerFormWindowInterface *fw, const QVaria case OT_Widget: { switch (m_specialProperty) { case SP_ObjectName: { - const QString oldName = qVariantValue<PropertySheetStringValue>(oldValue).value(); - const QString newName = qVariantValue<PropertySheetStringValue>(newValue).value(); + const QString oldName = qvariant_cast<PropertySheetStringValue>(oldValue).value(); + const QString newName = qvariant_cast<PropertySheetStringValue>(newValue).value(); QDesignerFormWindowCommand::updateBuddies(fw, oldName, newName); } break; @@ -751,8 +751,8 @@ void PropertyHelper::updateObject(QDesignerFormWindowInterface *fw, const QVaria case SP_LayoutName: case SP_SpacerName: if (QDesignerIntegration *integr = integration(fw)) { - const QString oldName = qVariantValue<PropertySheetStringValue>(oldValue).value(); - const QString newName = qVariantValue<PropertySheetStringValue>(newValue).value(); + const QString oldName = qvariant_cast<PropertySheetStringValue>(oldValue).value(); + const QString newName = qvariant_cast<PropertySheetStringValue>(newValue).value(); integr->emitObjectNameChanged(fw, m_object, newName, oldName); } break; diff --git a/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp index 086f46d..ee05adf 100644 --- a/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp +++ b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp @@ -290,18 +290,18 @@ bool QDesignerPropertySheetPrivate::isResourceProperty(int index) const void QDesignerPropertySheetPrivate::addResourceProperty(int index, QVariant::Type type) { if (type == QVariant::Pixmap) - m_resourceProperties.insert(index, qVariantFromValue(qdesigner_internal::PropertySheetPixmapValue())); + m_resourceProperties.insert(index, QVariant::fromValue(qdesigner_internal::PropertySheetPixmapValue())); else if (type == QVariant::Icon) - m_resourceProperties.insert(index, qVariantFromValue(qdesigner_internal::PropertySheetIconValue())); + m_resourceProperties.insert(index, QVariant::fromValue(qdesigner_internal::PropertySheetIconValue())); } QVariant QDesignerPropertySheetPrivate::emptyResourceProperty(int index) const { QVariant v = m_resourceProperties.value(index); - if (qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(v)) - return qVariantFromValue(qdesigner_internal::PropertySheetPixmapValue()); - if (qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(v)) - return qVariantFromValue(qdesigner_internal::PropertySheetIconValue()); + if (v.canConvert<qdesigner_internal::PropertySheetPixmapValue>()) + return QVariant::fromValue(qdesigner_internal::PropertySheetPixmapValue()); + if (v.canConvert<qdesigner_internal::PropertySheetIconValue>()) + return QVariant::fromValue(qdesigner_internal::PropertySheetIconValue()); return v; } @@ -320,8 +320,8 @@ void QDesignerPropertySheetPrivate::setResourceProperty(int index, const QVarian Q_ASSERT(isResourceProperty(index)); QVariant &v = m_resourceProperties[index]; - if ((qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(value) && qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(v)) - || (qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(value) && qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(v))) + if ((value.canConvert<qdesigner_internal::PropertySheetPixmapValue>() && v.canConvert<qdesigner_internal::PropertySheetPixmapValue>()) + || (value.canConvert<qdesigner_internal::PropertySheetIconValue>() && v.canConvert<qdesigner_internal::PropertySheetIconValue>())) v = value; } @@ -722,14 +722,14 @@ int QDesignerPropertySheet::addDynamicProperty(const QString &propName, const QV QVariant v = value; if (value.type() == QVariant::Icon) - v = qVariantFromValue(qdesigner_internal::PropertySheetIconValue()); + v = QVariant::fromValue(qdesigner_internal::PropertySheetIconValue()); else if (value.type() == QVariant::Pixmap) - v = qVariantFromValue(qdesigner_internal::PropertySheetPixmapValue()); + v = QVariant::fromValue(qdesigner_internal::PropertySheetPixmapValue()); else if (value.type() == QVariant::String) - v = qVariantFromValue(qdesigner_internal::PropertySheetStringValue(value.toString())); + v = QVariant::fromValue(qdesigner_internal::PropertySheetStringValue(value.toString())); else if (value.type() == QVariant::KeySequence) { - const QKeySequence keySequence = qVariantValue<QKeySequence>(value); - v = qVariantFromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence)); + const QKeySequence keySequence = qvariant_cast<QKeySequence>(value); + v = QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence)); } if (d->m_addIndex.contains(propName)) { @@ -873,9 +873,9 @@ int QDesignerPropertySheet::createFakeProperty(const QString &propertyName, cons info.kind = QDesignerPropertySheetPrivate::FakeProperty; QVariant v = value.isValid() ? value : metaProperty(index); if (v.type() == QVariant::String) - v = qVariantFromValue(qdesigner_internal::PropertySheetStringValue()); + v = QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()); if (v.type() == QVariant::KeySequence) - v = qVariantFromValue(qdesigner_internal::PropertySheetKeySequenceValue()); + v = QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue()); d->m_fakeProperties.insert(index, v); return index; } @@ -1002,17 +1002,17 @@ QVariant QDesignerPropertySheet::property(int index) const value.setValue(strValue); d->setStringProperty(index, value); // cache it } - return qVariantFromValue(value); + return QVariant::fromValue(value); } if (d->isKeySequenceProperty(index)) { - QKeySequence keyValue = qVariantValue<QKeySequence>(metaProperty(index)); + QKeySequence keyValue = qvariant_cast<QKeySequence>(metaProperty(index)); qdesigner_internal::PropertySheetKeySequenceValue value = d->keySequenceProperty(index); if (keyValue != value.value()) { value.setValue(keyValue); d->setKeySequenceProperty(index, value); // cache it } - return qVariantFromValue(value); + return QVariant::fromValue(value); } return metaProperty(index); @@ -1027,12 +1027,12 @@ QVariant QDesignerPropertySheet::metaProperty(int index) const switch (p->kind()) { case QDesignerMetaPropertyInterface::FlagKind: { qdesigner_internal::PropertySheetFlagValue psflags = qdesigner_internal::PropertySheetFlagValue(v.toInt(), designerMetaFlagsFor(p->enumerator())); - qVariantSetValue(v, psflags); + v.setValue(psflags); } break; case QDesignerMetaPropertyInterface::EnumKind: { qdesigner_internal::PropertySheetEnumValue pse = qdesigner_internal::PropertySheetEnumValue(v.toInt(), designerMetaEnumFor(p->enumerator())); - qVariantSetValue(v, pse); + v.setValue(pse); } break; case QDesignerMetaPropertyInterface::OtherKind: @@ -1043,20 +1043,20 @@ QVariant QDesignerPropertySheet::metaProperty(int index) const QVariant QDesignerPropertySheet::resolvePropertyValue(int index, const QVariant &value) const { - if (qVariantCanConvert<qdesigner_internal::PropertySheetEnumValue>(value)) + if (value.canConvert<qdesigner_internal::PropertySheetEnumValue>()) return qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(value).value; - if (qVariantCanConvert<qdesigner_internal::PropertySheetFlagValue>(value)) + if (value.canConvert<qdesigner_internal::PropertySheetFlagValue>()) return qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(value).value; - if (qVariantCanConvert<qdesigner_internal::PropertySheetStringValue>(value)) - return qVariantValue<qdesigner_internal::PropertySheetStringValue>(value).value(); + if (value.canConvert<qdesigner_internal::PropertySheetStringValue>()) + return qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value).value(); - if (qVariantCanConvert<qdesigner_internal::PropertySheetKeySequenceValue>(value)) - return qVariantValue<qdesigner_internal::PropertySheetKeySequenceValue>(value).value(); + if (value.canConvert<qdesigner_internal::PropertySheetKeySequenceValue>()) + return qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(value).value(); - if (qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(value)) { - const QString path = qVariantValue<qdesigner_internal::PropertySheetPixmapValue>(value).path(); + if (value.canConvert<qdesigner_internal::PropertySheetPixmapValue>()) { + const QString path = qvariant_cast<qdesigner_internal::PropertySheetPixmapValue>(value).path(); if (path.isEmpty()) return defaultResourceProperty(index); if (d->m_pixmapCache) { @@ -1064,9 +1064,9 @@ QVariant QDesignerPropertySheet::resolvePropertyValue(int index, const QVariant } } - if (qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(value)) { - const int pathCount = qVariantValue<qdesigner_internal::PropertySheetIconValue>(value).paths().count(); - if (pathCount == 0) + if (value.canConvert<qdesigner_internal::PropertySheetIconValue>()) { + const unsigned mask = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value).mask(); + if (mask == 0) return defaultResourceProperty(index); if (d->m_iconCache) return d->m_iconCache->icon(qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value)); @@ -1082,17 +1082,17 @@ void QDesignerPropertySheet::setFakeProperty(int index, const QVariant &value) QVariant &v = d->m_fakeProperties[index]; // set resource properties also (if we are going to have fake resource properties) - if (qVariantCanConvert<qdesigner_internal::PropertySheetFlagValue>(value) || qVariantCanConvert<qdesigner_internal::PropertySheetEnumValue>(value)) { + if (value.canConvert<qdesigner_internal::PropertySheetFlagValue>() || value.canConvert<qdesigner_internal::PropertySheetEnumValue>()) { v = value; - } else if (qVariantCanConvert<qdesigner_internal::PropertySheetFlagValue>(v)) { + } else if (v.canConvert<qdesigner_internal::PropertySheetFlagValue>()) { qdesigner_internal::PropertySheetFlagValue f = qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(v); f.value = value.toInt(); - qVariantSetValue(v, f); + v.setValue(f); Q_ASSERT(value.type() == QVariant::Int); - } else if (qVariantCanConvert<qdesigner_internal::PropertySheetEnumValue>(v)) { + } else if (v.canConvert<qdesigner_internal::PropertySheetEnumValue>()) { qdesigner_internal::PropertySheetEnumValue e = qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(v); e.value = value.toInt(); - qVariantSetValue(v, e); + v.setValue(e); Q_ASSERT(value.type() == QVariant::Int); } else { v = value; @@ -1139,9 +1139,9 @@ void QDesignerPropertySheet::setProperty(int index, const QVariant &value) if (d->isResourceProperty(index)) d->setResourceProperty(index, value); if (d->isStringProperty(index)) - d->setStringProperty(index, qVariantValue<qdesigner_internal::PropertySheetStringValue>(value)); + d->setStringProperty(index, qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value)); if (d->isKeySequenceProperty(index)) - d->setKeySequenceProperty(index, qVariantValue<qdesigner_internal::PropertySheetKeySequenceValue>(value)); + d->setKeySequenceProperty(index, qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(value)); d->m_object->setProperty(propertyName(index).toUtf8(), resolvePropertyValue(index, value)); if (d->m_object->isWidgetType()) { QWidget *w = qobject_cast<QWidget *>(d->m_object); @@ -1155,26 +1155,26 @@ void QDesignerPropertySheet::setProperty(int index, const QVariant &value) if (d->isResourceProperty(index)) d->setResourceProperty(index, value); if (d->isStringProperty(index)) - d->setStringProperty(index, qVariantValue<qdesigner_internal::PropertySheetStringValue>(value)); + d->setStringProperty(index, qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value)); if (d->isKeySequenceProperty(index)) - d->setKeySequenceProperty(index, qVariantValue<qdesigner_internal::PropertySheetKeySequenceValue>(value)); + d->setKeySequenceProperty(index, qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(value)); const QDesignerMetaPropertyInterface *p = d->m_meta->property(index); p->write(d->m_object, resolvePropertyValue(index, value)); if (qobject_cast<QGroupBox *>(d->m_object) && propertyType(index) == PropertyCheckable) { const int idx = indexOf(QLatin1String("focusPolicy")); if (!isChanged(idx)) { - qdesigner_internal::PropertySheetEnumValue e = qVariantValue<qdesigner_internal::PropertySheetEnumValue>(property(idx)); + qdesigner_internal::PropertySheetEnumValue e = qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(property(idx)); if (value.toBool()) { const QDesignerMetaPropertyInterface *p = d->m_meta->property(idx); p->write(d->m_object, Qt::NoFocus); e.value = Qt::StrongFocus; QVariant v; - qVariantSetValue(v, e); + v.setValue(e); setFakeProperty(idx, v); } else { e.value = Qt::NoFocus; QVariant v; - qVariantSetValue(v, e); + v.setValue(e); setFakeProperty(idx, v); } } @@ -1196,9 +1196,9 @@ bool QDesignerPropertySheet::reset(int index) if (d->invalidIndex(Q_FUNC_INFO, index)) return false; if (d->isStringProperty(index)) - setProperty(index, qVariantFromValue(qdesigner_internal::PropertySheetStringValue())); + setProperty(index, QVariant::fromValue(qdesigner_internal::PropertySheetStringValue())); if (d->isKeySequenceProperty(index)) - setProperty(index, qVariantFromValue(qdesigner_internal::PropertySheetKeySequenceValue())); + setProperty(index, QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue())); if (d->isResourceProperty(index)) { setProperty(index, d->emptyResourceProperty(index)); return true; @@ -1208,10 +1208,10 @@ bool QDesignerPropertySheet::reset(int index) const QVariant defaultValue = d->m_info.value(index).defaultValue; QVariant newValue = defaultValue; if (d->isStringProperty(index)) { - newValue = qVariantFromValue(qdesigner_internal::PropertySheetStringValue(newValue.toString())); + newValue = QVariant::fromValue(qdesigner_internal::PropertySheetStringValue(newValue.toString())); } else if (d->isKeySequenceProperty(index)) { - const QKeySequence keySequence = qVariantValue<QKeySequence>(newValue); - newValue = qVariantFromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence)); + const QKeySequence keySequence = qvariant_cast<QKeySequence>(newValue); + newValue = QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence)); } if (oldValue == newValue) return true; diff --git a/tools/designer/src/lib/shared/qdesigner_tabwidget.cpp b/tools/designer/src/lib/shared/qdesigner_tabwidget.cpp index ecd97fa..461212c 100644 --- a/tools/designer/src/lib/shared/qdesigner_tabwidget.cpp +++ b/tools/designer/src/lib/shared/qdesigner_tabwidget.cpp @@ -134,7 +134,7 @@ QTabBar *QTabWidgetEventFilter::tabBar() const { // QTabWidget::tabBar() accessor is protected, grmbl... if (!m_cachedTabBar) { - const QList<QTabBar *> tabBars = qFindChildren<QTabBar *>(m_tabWidget); + const QList<QTabBar *> tabBars = m_tabWidget->findChildren<QTabBar *>(); Q_ASSERT(tabBars.size() == 1); m_cachedTabBar = tabBars.front(); } @@ -405,13 +405,13 @@ QTabWidgetPropertySheet::QTabWidgetPropertySheet(QTabWidget *object, QObject *pa QDesignerPropertySheet(object, parent), m_tabWidget(object) { - createFakeProperty(QLatin1String(currentTabTextKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue())); + createFakeProperty(QLatin1String(currentTabTextKey), QVariant::fromValue(qdesigner_internal::PropertySheetStringValue())); createFakeProperty(QLatin1String(currentTabNameKey), QString()); - createFakeProperty(QLatin1String(currentTabIconKey), qVariantFromValue(qdesigner_internal::PropertySheetIconValue())); + createFakeProperty(QLatin1String(currentTabIconKey), QVariant::fromValue(qdesigner_internal::PropertySheetIconValue())); if (formWindowBase()) formWindowBase()->addReloadableProperty(this, indexOf(QLatin1String(currentTabIconKey))); - createFakeProperty(QLatin1String(currentTabToolTipKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue())); - createFakeProperty(QLatin1String(currentTabWhatsThisKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue())); + createFakeProperty(QLatin1String(currentTabToolTipKey), QVariant::fromValue(qdesigner_internal::PropertySheetStringValue())); + createFakeProperty(QLatin1String(currentTabWhatsThisKey), QVariant::fromValue(qdesigner_internal::PropertySheetStringValue())); // Prevent the tab widget's drag and drop handling from interfering with Designer's createFakeProperty(QLatin1String(tabMovableKey), QVariant(false)); } @@ -447,22 +447,22 @@ void QTabWidgetPropertySheet::setProperty(int index, const QVariant &value) switch (tabWidgetProperty) { case PropertyCurrentTabText: m_tabWidget->setTabText(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value))); - m_pageToData[currentWidget].text = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value); + m_pageToData[currentWidget].text = qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value); break; case PropertyCurrentTabName: currentWidget->setObjectName(value.toString()); break; case PropertyCurrentTabIcon: m_tabWidget->setTabIcon(currentIndex, qvariant_cast<QIcon>(resolvePropertyValue(index, value))); - m_pageToData[currentWidget].icon = qVariantValue<qdesigner_internal::PropertySheetIconValue>(value); + m_pageToData[currentWidget].icon = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value); break; case PropertyCurrentTabToolTip: m_tabWidget->setTabToolTip(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value))); - m_pageToData[currentWidget].tooltip = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value); + m_pageToData[currentWidget].tooltip = qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value); break; case PropertyCurrentTabWhatsThis: m_tabWidget->setTabWhatsThis(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value))); - m_pageToData[currentWidget].whatsthis = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value); + m_pageToData[currentWidget].whatsthis = qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value); break; case PropertyTabWidgetNone: break; @@ -486,28 +486,28 @@ QVariant QTabWidgetPropertySheet::property(int index) const QWidget *currentWidget = m_tabWidget->currentWidget(); if (!currentWidget) { if (tabWidgetProperty == PropertyCurrentTabIcon) - return qVariantFromValue(qdesigner_internal::PropertySheetIconValue()); + return QVariant::fromValue(qdesigner_internal::PropertySheetIconValue()); if (tabWidgetProperty == PropertyCurrentTabText) - return qVariantFromValue(qdesigner_internal::PropertySheetStringValue()); + return QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()); if (tabWidgetProperty == PropertyCurrentTabToolTip) - return qVariantFromValue(qdesigner_internal::PropertySheetStringValue()); + return QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()); if (tabWidgetProperty == PropertyCurrentTabWhatsThis) - return qVariantFromValue(qdesigner_internal::PropertySheetStringValue()); + return QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()); return QVariant(QString()); } // index-dependent switch (tabWidgetProperty) { case PropertyCurrentTabText: - return qVariantFromValue(m_pageToData.value(currentWidget).text); + return QVariant::fromValue(m_pageToData.value(currentWidget).text); case PropertyCurrentTabName: return currentWidget->objectName(); case PropertyCurrentTabIcon: - return qVariantFromValue(m_pageToData.value(currentWidget).icon); + return QVariant::fromValue(m_pageToData.value(currentWidget).icon); case PropertyCurrentTabToolTip: - return qVariantFromValue(m_pageToData.value(currentWidget).tooltip); + return QVariant::fromValue(m_pageToData.value(currentWidget).tooltip); case PropertyCurrentTabWhatsThis: - return qVariantFromValue(m_pageToData.value(currentWidget).whatsthis); + return QVariant::fromValue(m_pageToData.value(currentWidget).whatsthis); case PropertyTabWidgetNone: break; } diff --git a/tools/designer/src/lib/shared/qdesigner_taskmenu.cpp b/tools/designer/src/lib/shared/qdesigner_taskmenu.cpp index cd95f5b..a607f35 100644 --- a/tools/designer/src/lib/shared/qdesigner_taskmenu.cpp +++ b/tools/designer/src/lib/shared/qdesigner_taskmenu.cpp @@ -132,7 +132,7 @@ static QString objName(const QDesignerFormEditorInterface *core, QObject *object const QString objectNameProperty = QLatin1String("objectName"); const int index = sheet->indexOf(objectNameProperty); const qdesigner_internal::PropertySheetStringValue objectNameValue - = qVariantValue<qdesigner_internal::PropertySheetStringValue>(sheet->property(index)); + = qvariant_cast<qdesigner_internal::PropertySheetStringValue>(sheet->property(index)); return objectNameValue.value(); } @@ -447,7 +447,7 @@ void QDesignerTaskMenu::changeObjectName() const QString objectNameProperty = QLatin1String("objectName"); PropertySheetStringValue objectNameValue; objectNameValue.setValue(newObjectName); - setProperty(fw, CurrentWidgetMode, objectNameProperty, qVariantFromValue(objectNameValue)); + setProperty(fw, CurrentWidgetMode, objectNameProperty, QVariant::fromValue(objectNameValue)); } } } @@ -465,7 +465,7 @@ void QDesignerTaskMenu::changeTextProperty(const QString &propertyName, const QS qDebug() << "** WARNING Invalid property" << propertyName << " passed to changeTextProperty!"; return; } - PropertySheetStringValue textValue = qVariantValue<PropertySheetStringValue>(sheet->property(index)); + PropertySheetStringValue textValue = qvariant_cast<PropertySheetStringValue>(sheet->property(index)); const QString oldText = textValue.value(); // Pop up respective dialog bool accepted = false; @@ -498,7 +498,7 @@ void QDesignerTaskMenu::changeTextProperty(const QString &propertyName, const QS textValue.setValue(newText); - setProperty(fw, pm, propertyName, qVariantFromValue(textValue)); + setProperty(fw, pm, propertyName, QVariant::fromValue(textValue)); } void QDesignerTaskMenu::changeToolTip() @@ -673,7 +673,7 @@ void QDesignerTaskMenu::navigateToSlot(QDesignerFormEditorInterface *core, if (selectSignalDialog.exec() == QDialog::Accepted) { QTreeWidgetItem *selectedItem = dialogUi.signalList->selectedItems().first(); const QString signalSignature = selectedItem->text(0); - const QStringList parameterNames = qVariantValue<QStringList>(selectedItem->data(0, Qt::UserRole)); + const QStringList parameterNames = qvariant_cast<QStringList>(selectedItem->data(0, Qt::UserRole)); // TODO: Check whether signal is connected to slot integr->emitNavigateToSlot(objectName, signalSignature, parameterNames); diff --git a/tools/designer/src/lib/shared/qdesigner_toolbar.cpp b/tools/designer/src/lib/shared/qdesigner_toolbar.cpp index e3bc64c..629c810 100644 --- a/tools/designer/src/lib/shared/qdesigner_toolbar.cpp +++ b/tools/designer/src/lib/shared/qdesigner_toolbar.cpp @@ -146,7 +146,7 @@ ActionList ToolBarEventFilter::contextMenuActions(const QPoint &globalPos) // Insert before if (action && index != 0 && !action->isSeparator()) { QAction *newSeperatorAct = new QAction(tr("Insert Separator before '%1'").arg(action->objectName()), 0); - qVariantSetValue(itemData, action); + itemData.setValue(action); newSeperatorAct->setData(itemData); connect(newSeperatorAct, SIGNAL(triggered()), this, SLOT(slotInsertSeparator())); rc.push_back(newSeperatorAct); @@ -155,7 +155,7 @@ ActionList ToolBarEventFilter::contextMenuActions(const QPoint &globalPos) // Append separator if (actions.empty() || !actions.back()->isSeparator()) { QAction *newSeperatorAct = new QAction(tr("Append Separator"), 0); - qVariantSetValue(itemData, static_cast<QAction*>(0)); + itemData.setValue(static_cast<QAction*>(0)); newSeperatorAct->setData(itemData); connect(newSeperatorAct, SIGNAL(triggered()), this, SLOT(slotInsertSeparator())); rc.push_back(newSeperatorAct); @@ -167,7 +167,7 @@ ActionList ToolBarEventFilter::contextMenuActions(const QPoint &globalPos) // Remove if (action) { QAction *a = new QAction(tr("Remove action '%1'").arg(action->objectName()), 0); - qVariantSetValue(itemData, action); + itemData.setValue(action); a->setData(itemData); connect(a, SIGNAL(triggered()), this, SLOT(slotRemoveSelectedAction())); rc.push_back(a); diff --git a/tools/designer/src/lib/shared/qdesigner_toolbox.cpp b/tools/designer/src/lib/shared/qdesigner_toolbox.cpp index 986bfbe..c0f7c20 100644 --- a/tools/designer/src/lib/shared/qdesigner_toolbox.cpp +++ b/tools/designer/src/lib/shared/qdesigner_toolbox.cpp @@ -260,12 +260,12 @@ QToolBoxWidgetPropertySheet::QToolBoxWidgetPropertySheet(QToolBox *object, QObje QDesignerPropertySheet(object, parent), m_toolBox(object) { - createFakeProperty(QLatin1String(currentItemTextKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue())); + createFakeProperty(QLatin1String(currentItemTextKey), QVariant::fromValue(qdesigner_internal::PropertySheetStringValue())); createFakeProperty(QLatin1String(currentItemNameKey), QString()); - createFakeProperty(QLatin1String(currentItemIconKey), qVariantFromValue(qdesigner_internal::PropertySheetIconValue())); + createFakeProperty(QLatin1String(currentItemIconKey), QVariant::fromValue(qdesigner_internal::PropertySheetIconValue())); if (formWindowBase()) formWindowBase()->addReloadableProperty(this, indexOf(QLatin1String(currentItemIconKey))); - createFakeProperty(QLatin1String(currentItemToolTipKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue())); + createFakeProperty(QLatin1String(currentItemToolTipKey), QVariant::fromValue(qdesigner_internal::PropertySheetStringValue())); createFakeProperty(QLatin1String(tabSpacingKey), QVariant(tabSpacingDefault)); } @@ -306,18 +306,18 @@ void QToolBoxWidgetPropertySheet::setProperty(int index, const QVariant &value) switch (toolBoxProperty) { case PropertyCurrentItemText: m_toolBox->setItemText(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value))); - m_pageToData[currentWidget].text = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value); + m_pageToData[currentWidget].text = qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value); break; case PropertyCurrentItemName: currentWidget->setObjectName(value.toString()); break; case PropertyCurrentItemIcon: m_toolBox->setItemIcon(currentIndex, qvariant_cast<QIcon>(resolvePropertyValue(index, value))); - m_pageToData[currentWidget].icon = qVariantValue<qdesigner_internal::PropertySheetIconValue>(value); + m_pageToData[currentWidget].icon = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value); break; case PropertyCurrentItemToolTip: m_toolBox->setItemToolTip(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value))); - m_pageToData[currentWidget].tooltip = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value); + m_pageToData[currentWidget].tooltip = qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value); break; case PropertyTabSpacing: case PropertyToolBoxNone: @@ -353,24 +353,24 @@ QVariant QToolBoxWidgetPropertySheet::property(int index) const QWidget *currentWidget = m_toolBox->currentWidget(); if (!currentWidget) { if (toolBoxProperty == PropertyCurrentItemIcon) - return qVariantFromValue(qdesigner_internal::PropertySheetIconValue()); + return QVariant::fromValue(qdesigner_internal::PropertySheetIconValue()); if (toolBoxProperty == PropertyCurrentItemText) - return qVariantFromValue(qdesigner_internal::PropertySheetStringValue()); + return QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()); if (toolBoxProperty == PropertyCurrentItemToolTip) - return qVariantFromValue(qdesigner_internal::PropertySheetStringValue()); + return QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()); return QVariant(QString()); } // index-dependent switch (toolBoxProperty) { case PropertyCurrentItemText: - return qVariantFromValue(m_pageToData.value(currentWidget).text); + return QVariant::fromValue(m_pageToData.value(currentWidget).text); case PropertyCurrentItemName: return currentWidget->objectName(); case PropertyCurrentItemIcon: - return qVariantFromValue(m_pageToData.value(currentWidget).icon); + return QVariant::fromValue(m_pageToData.value(currentWidget).icon); case PropertyCurrentItemToolTip: - return qVariantFromValue(m_pageToData.value(currentWidget).tooltip); + return QVariant::fromValue(m_pageToData.value(currentWidget).tooltip); case PropertyTabSpacing: case PropertyToolBoxNone: break; diff --git a/tools/designer/src/lib/shared/qdesigner_utils.cpp b/tools/designer/src/lib/shared/qdesigner_utils.cpp index 3bd0704..bd89c53 100644 --- a/tools/designer/src/lib/shared/qdesigner_utils.cpp +++ b/tools/designer/src/lib/shared/qdesigner_utils.cpp @@ -52,15 +52,16 @@ #include <QtDesigner/QDesignerTaskMenuExtension> #include <QtDesigner/QExtensionManager> -#include <QtGui/QIcon> -#include <QtGui/QPixmap> #include <QtCore/QDir> - -#include <QtGui/QApplication> #include <QtCore/QProcess> #include <QtCore/QLibraryInfo> #include <QtCore/QDebug> #include <QtCore/QQueue> +#include <QtCore/QSharedData> + +#include <QtGui/QApplication> +#include <QtGui/QIcon> +#include <QtGui/QPixmap> #include <QtGui/QListWidget> #include <QtGui/QTreeWidget> #include <QtGui/QTableWidget> @@ -82,8 +83,8 @@ namespace qdesigner_internal for (int c = 0; c < item->columnCount(); c++) { const QVariant v = item->data(c, Qt::DecorationPropertyRole); - if (qVariantCanConvert<PropertySheetIconValue>(v)) - item->setIcon(c, iconCache->icon(qVariantValue<PropertySheetIconValue>(v))); + if (v.canConvert<PropertySheetIconValue>()) + item->setIcon(c, iconCache->icon(qvariant_cast<PropertySheetIconValue>(v))); } } @@ -93,8 +94,8 @@ namespace qdesigner_internal return; const QVariant v = item->data(Qt::DecorationPropertyRole); - if (qVariantCanConvert<PropertySheetIconValue>(v)) - item->setIcon(iconCache->icon(qVariantValue<PropertySheetIconValue>(v))); + if (v.canConvert<PropertySheetIconValue>()) + item->setIcon(iconCache->icon(qvariant_cast<PropertySheetIconValue>(v))); } void reloadTableItem(DesignerIconCache *iconCache, QTableWidgetItem *item) @@ -103,8 +104,8 @@ namespace qdesigner_internal return; const QVariant v = item->data(Qt::DecorationPropertyRole); - if (qVariantCanConvert<PropertySheetIconValue>(v)) - item->setIcon(iconCache->icon(qVariantValue<PropertySheetIconValue>(v))); + if (v.canConvert<PropertySheetIconValue>()) + item->setIcon(iconCache->icon(qvariant_cast<PropertySheetIconValue>(v))); } void reloadIconResources(DesignerIconCache *iconCache, QObject *object) @@ -115,8 +116,8 @@ namespace qdesigner_internal } else if (QComboBox *comboBox = qobject_cast<QComboBox *>(object)) { for (int i = 0; i < comboBox->count(); i++) { const QVariant v = comboBox->itemData(i, Qt::DecorationPropertyRole); - if (qVariantCanConvert<PropertySheetIconValue>(v)) { - QIcon icon = iconCache->icon(qVariantValue<PropertySheetIconValue>(v)); + if (v.canConvert<PropertySheetIconValue>()) { + QIcon icon = iconCache->icon(qvariant_cast<PropertySheetIconValue>(v)); comboBox->setItemIcon(i, icon); comboBox->setItemData(i, icon); } @@ -314,24 +315,51 @@ namespace qdesigner_internal } // ---------- PropertySheetIconValue - PropertySheetIconValue::PropertySheetIconValue(const PropertySheetPixmapValue &pixmap) + + class PropertySheetIconValueData : public QSharedData { + public: + PropertySheetIconValue::ModeStateToPixmapMap m_paths; + QString m_theme; + }; + + PropertySheetIconValue::PropertySheetIconValue(const PropertySheetPixmapValue &pixmap) : + m_data(new PropertySheetIconValueData) { setPixmap(QIcon::Normal, QIcon::Off, pixmap); } - PropertySheetIconValue::PropertySheetIconValue() + PropertySheetIconValue::PropertySheetIconValue() : + m_data(new PropertySheetIconValueData) + { + } + + PropertySheetIconValue::~PropertySheetIconValue() { } + PropertySheetIconValue::PropertySheetIconValue(const PropertySheetIconValue &rhs) : + m_data(rhs.m_data) + { + } + + PropertySheetIconValue &PropertySheetIconValue::operator=(const PropertySheetIconValue &rhs) + { + if (this != &rhs) + m_data.operator=(rhs.m_data); + return *this; + } + bool PropertySheetIconValue::equals(const PropertySheetIconValue &rhs) const { - return m_paths == rhs.m_paths; + return m_data->m_theme == rhs.m_data->m_theme && m_data->m_paths == rhs.m_data->m_paths; } bool PropertySheetIconValue::operator<(const PropertySheetIconValue &other) const { - QMapIterator<ModeStateKey, PropertySheetPixmapValue> itThis(m_paths); - QMapIterator<ModeStateKey, PropertySheetPixmapValue> itOther(other.m_paths); + if (const int themeCmp = m_data->m_theme.compare(other.m_data->m_theme)) + return themeCmp < 0; + QMapIterator<ModeStateKey, PropertySheetPixmapValue> itThis(m_data->m_paths); + QMapIterator<ModeStateKey, PropertySheetPixmapValue> itOther(other.m_data->m_paths); while (itThis.hasNext() && itOther.hasNext()) { const ModeStateKey thisPair = itThis.next().key(); const ModeStateKey otherPair = itOther.next().key(); @@ -350,19 +378,34 @@ namespace qdesigner_internal return false; } + bool PropertySheetIconValue::isEmpty() const + { + return m_data->m_theme.isEmpty() && m_data->m_paths.isEmpty(); + } + + QString PropertySheetIconValue::theme() const + { + return m_data->m_theme; + } + + void PropertySheetIconValue::setTheme(const QString &t) + { + m_data->m_theme = t; + } + PropertySheetPixmapValue PropertySheetIconValue::pixmap(QIcon::Mode mode, QIcon::State state) const { const ModeStateKey pair = qMakePair(mode, state); - return m_paths.value(pair); + return m_data->m_paths.value(pair); } void PropertySheetIconValue::setPixmap(QIcon::Mode mode, QIcon::State state, const PropertySheetPixmapValue &pixmap) { const ModeStateKey pair = qMakePair(mode, state); if (pixmap.path().isEmpty()) - m_paths.remove(pair); + m_data->m_paths.remove(pair); else - m_paths.insert(pair, pixmap); + m_data->m_paths.insert(pair, pixmap); } QPixmap DesignerPixmapCache::pixmap(const PropertySheetPixmapValue &value) const @@ -388,16 +431,28 @@ namespace qdesigner_internal QIcon DesignerIconCache::icon(const PropertySheetIconValue &value) const { + typedef PropertySheetIconValue::ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt; + QMap<PropertySheetIconValue, QIcon>::const_iterator it = m_cache.constFind(value); if (it != m_cache.constEnd()) return it.value(); + // Match on the theme first if it is available. + if (!value.theme().isEmpty()) { + const QString theme = value.theme(); + if (QIcon::hasThemeIcon(theme)) { + const QIcon themeIcon = QIcon::fromTheme(theme); + m_cache.insert(value, themeIcon); + return themeIcon; + } + } + QIcon icon; - QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> paths = value.paths(); - QMapIterator<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> itPath(paths); - while (itPath.hasNext()) { - QPair<QIcon::Mode, QIcon::State> pair = itPath.next().key(); - icon.addFile(itPath.value().path(), QSize(), pair.first, pair.second); + const PropertySheetIconValue::ModeStateToPixmapMap &paths = value.paths(); + const ModeStateToPixmapMapConstIt cend = paths.constEnd(); + for (ModeStateToPixmapMapConstIt it = paths.constBegin(); it != cend; ++it) { + const QPair<QIcon::Mode, QIcon::State> pair = it.key(); + icon.addFile(it.value().path(), QSize(), pair.first, pair.second); } m_cache.insert(value, icon); return icon; @@ -547,50 +602,75 @@ namespace qdesigner_internal && (m_translatable == rhs.m_translatable) && (m_disambiguation == rhs.m_disambiguation) && (m_comment == rhs.m_comment); } - class StateMap + + /* IconSubPropertyMask: Assign each icon sub-property (pixmaps for the + * various states/modes and the theme) a flag bit (see QFont) so that they + * can be handled individually when assigning property values to + * multiselections in the set-property-commands (that is, do not clobber + * other subproperties when assigning just one). + * Provide back-and-forth mapping functions for the icon states. */ + + enum IconSubPropertyMask { + NormalOffIconMask = 0x01, + NormalOnIconMask = 0x02, + DisabledOffIconMask = 0x04, + DisabledOnIconMask = 0x08, + ActiveOffIconMask = 0x10, + ActiveOnIconMask = 0x20, + SelectedOffIconMask = 0x40, + SelectedOnIconMask = 0x80, + ThemeIconMask = 0x10000 + }; + + static inline uint iconStateToSubPropertyFlag(QIcon::Mode mode, QIcon::State state) { - public: - StateMap() - { - m_stateToFlag.insert(qMakePair(QIcon::Normal, QIcon::Off), 0x01); - m_stateToFlag.insert(qMakePair(QIcon::Normal, QIcon::On), 0x02); - m_stateToFlag.insert(qMakePair(QIcon::Disabled, QIcon::Off), 0x04); - m_stateToFlag.insert(qMakePair(QIcon::Disabled, QIcon::On), 0x08); - m_stateToFlag.insert(qMakePair(QIcon::Active, QIcon::Off), 0x10); - m_stateToFlag.insert(qMakePair(QIcon::Active, QIcon::On), 0x20); - m_stateToFlag.insert(qMakePair(QIcon::Selected, QIcon::Off), 0x40); - m_stateToFlag.insert(qMakePair(QIcon::Selected, QIcon::On), 0x80); - - m_flagToState.insert(0x01, qMakePair(QIcon::Normal, QIcon::Off)); - m_flagToState.insert(0x02, qMakePair(QIcon::Normal, QIcon::On)); - m_flagToState.insert(0x04, qMakePair(QIcon::Disabled, QIcon::Off)); - m_flagToState.insert(0x08, qMakePair(QIcon::Disabled, QIcon::On)); - m_flagToState.insert(0x10, qMakePair(QIcon::Active, QIcon::Off)); - m_flagToState.insert(0x20, qMakePair(QIcon::Active, QIcon::On)); - m_flagToState.insert(0x40, qMakePair(QIcon::Selected, QIcon::Off)); - m_flagToState.insert(0x80, qMakePair(QIcon::Selected, QIcon::On)); - } - uint flag(const QPair<QIcon::Mode, QIcon::State> &pair) const - { - return m_stateToFlag.value(pair); + switch (mode) { + case QIcon::Disabled: + return state == QIcon::On ? DisabledOnIconMask : DisabledOffIconMask; + case QIcon::Active: + return state == QIcon::On ? ActiveOnIconMask : ActiveOffIconMask; + case QIcon::Selected: + return state == QIcon::On ? SelectedOnIconMask : SelectedOffIconMask; + case QIcon::Normal: + break; } - QPair<QIcon::Mode, QIcon::State> state(uint flag) const - { - return m_flagToState.value(flag); + return state == QIcon::On ? NormalOnIconMask : NormalOffIconMask; + } + + static inline QPair<QIcon::Mode, QIcon::State> subPropertyFlagToIconModeState(unsigned flag) + { + switch (flag) { + case NormalOnIconMask: + return qMakePair(QIcon::Normal, QIcon::On); + case DisabledOffIconMask: + return qMakePair(QIcon::Disabled, QIcon::Off); + case DisabledOnIconMask: + return qMakePair(QIcon::Disabled, QIcon::On); + case ActiveOffIconMask: + return qMakePair(QIcon::Active, QIcon::Off); + case ActiveOnIconMask: + return qMakePair(QIcon::Active, QIcon::On); + case SelectedOffIconMask: + return qMakePair(QIcon::Selected, QIcon::Off); + case SelectedOnIconMask: + return qMakePair(QIcon::Selected, QIcon::On); + case NormalOffIconMask: + default: + break; } - private: - QMap<QPair<QIcon::Mode, QIcon::State>, uint > m_stateToFlag; - QMap<uint, QPair<QIcon::Mode, QIcon::State> > m_flagToState; - }; - - Q_GLOBAL_STATIC(StateMap, stateMap) + return qMakePair(QIcon::Normal, QIcon::Off); + } uint PropertySheetIconValue::mask() const { + typedef ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt; + uint flags = 0; - QMapIterator<ModeStateKey, PropertySheetPixmapValue> itPath(m_paths); - while (itPath.hasNext()) - flags |= stateMap()->flag(itPath.next().key()); + const ModeStateToPixmapMapConstIt cend = m_data->m_paths.constEnd(); + for (ModeStateToPixmapMapConstIt it = m_data->m_paths.constBegin(); it != cend; ++it) + flags |= iconStateToSubPropertyFlag(it.key().first, it.key().second); + if (!m_data->m_theme.isEmpty()) + flags |= ThemeIconMask; return flags; } @@ -598,30 +678,64 @@ namespace qdesigner_internal { uint diffMask = mask() | other.mask(); for (int i = 0; i < 8; i++) { - uint flag = 1 << i; + const uint flag = 1 << i; if (diffMask & flag) { // if state is set in both icons, compare the values - const ModeStateKey state = stateMap()->state(flag); + const QPair<QIcon::Mode, QIcon::State> state = subPropertyFlagToIconModeState(flag); if (pixmap(state.first, state.second) == other.pixmap(state.first, state.second)) diffMask &= ~flag; } } + if ((diffMask & ThemeIconMask) && theme() == other.theme()) + diffMask &= ~ThemeIconMask; return diffMask; } + PropertySheetIconValue PropertySheetIconValue::themed() const + { + PropertySheetIconValue rc(*this); + rc.m_data->m_paths.clear(); + return rc; + } + + PropertySheetIconValue PropertySheetIconValue::unthemed() const + { + PropertySheetIconValue rc(*this); + rc.m_data->m_theme.clear(); + return rc; + } + void PropertySheetIconValue::assign(const PropertySheetIconValue &other, uint mask) { for (int i = 0; i < 8; i++) { uint flag = 1 << i; if (mask & flag) { - const ModeStateKey state = stateMap()->state(flag); + const ModeStateKey state = subPropertyFlagToIconModeState(flag); setPixmap(state.first, state.second, other.pixmap(state.first, state.second)); } } + if (mask & ThemeIconMask) + setTheme(other.theme()); } - PropertySheetIconValue::ModeStateToPixmapMap PropertySheetIconValue::paths() const + const PropertySheetIconValue::ModeStateToPixmapMap &PropertySheetIconValue::paths() const { - return m_paths; + return m_data->m_paths; + } + + QDESIGNER_SHARED_EXPORT QDebug operator<<(QDebug d, const PropertySheetIconValue &p) + { + typedef PropertySheetIconValue::ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt; + + QDebug nospace = d.nospace(); + nospace << "PropertySheetIconValue theme='" << p.theme() << "' "; + + const PropertySheetIconValue::ModeStateToPixmapMap &paths = p.paths(); + const ModeStateToPixmapMapConstIt cend = paths.constEnd(); + for (ModeStateToPixmapMapConstIt it = paths.constBegin(); it != cend; ++it) + nospace << " mode=" << it.key().first << ",state=" << it.key().second + << ",'" << it.value().path() << '\''; + nospace << " mask=0x" << QString::number(p.mask(), 16); + return d; } QDESIGNER_SHARED_EXPORT QDesignerFormWindowCommand *createTextPropertyCommand(const QString &propertyName, const QString &text, QObject *object, QDesignerFormWindowInterface *fw) diff --git a/tools/designer/src/lib/shared/qdesigner_utils_p.h b/tools/designer/src/lib/shared/qdesigner_utils_p.h index fac0697..b310208 100644 --- a/tools/designer/src/lib/shared/qdesigner_utils_p.h +++ b/tools/designer/src/lib/shared/qdesigner_utils_p.h @@ -58,6 +58,7 @@ #include <QtDesigner/QDesignerFormWindowInterface> #include <QtCore/QVariant> +#include <QtCore/QSharedDataPointer> #include <QtCore/QMap> #include <QtGui/QMainWindow> #include <QtGui/QIcon> @@ -65,6 +66,8 @@ QT_BEGIN_NAMESPACE +class QDebug; + namespace qdesigner_internal { class QDesignerFormWindowCommand; class DesignerIconCache; @@ -252,16 +255,26 @@ private: // -------------- IconValue: Returned by the property sheet for icons +class PropertySheetIconValueData; + class QDESIGNER_SHARED_EXPORT PropertySheetIconValue { public: PropertySheetIconValue(const PropertySheetPixmapValue &pixmap); PropertySheetIconValue(); + ~PropertySheetIconValue(); + PropertySheetIconValue(const PropertySheetIconValue &); + PropertySheetIconValue &operator=(const PropertySheetIconValue &); bool operator==(const PropertySheetIconValue &other) const { return equals(other); } bool operator!=(const PropertySheetIconValue &other) const { return !equals(other); } bool operator<(const PropertySheetIconValue &other) const; + bool isEmpty() const; + + QString theme() const; + void setTheme(const QString &); + PropertySheetPixmapValue pixmap(QIcon::Mode mode, QIcon::State state) const; void setPixmap(QIcon::Mode mode, QIcon::State state, const PropertySheetPixmapValue &path); // passing the empty path resets the pixmap @@ -269,17 +282,22 @@ class QDESIGNER_SHARED_EXPORT PropertySheetIconValue uint compare(const PropertySheetIconValue &other) const; void assign(const PropertySheetIconValue &other, uint mask); + // Convenience accessors to get themed/unthemed icons. + PropertySheetIconValue themed() const; + PropertySheetIconValue unthemed() const; + typedef QPair<QIcon::Mode, QIcon::State> ModeStateKey; typedef QMap<ModeStateKey, PropertySheetPixmapValue> ModeStateToPixmapMap; - ModeStateToPixmapMap paths() const; + const ModeStateToPixmapMap &paths() const; private: bool equals(const PropertySheetIconValue &rhs) const; - - ModeStateToPixmapMap m_paths; + QSharedDataPointer<PropertySheetIconValueData> m_data; }; +QDESIGNER_SHARED_EXPORT QDebug operator<<(QDebug, const PropertySheetIconValue &); + class QDESIGNER_SHARED_EXPORT DesignerPixmapCache : public QObject { Q_OBJECT @@ -432,15 +450,15 @@ namespace Utils { inline int valueOf(const QVariant &value, bool *ok = 0) { - if (qVariantCanConvert<PropertySheetEnumValue>(value)) { + if (value.canConvert<PropertySheetEnumValue>()) { if (ok) *ok = true; - return qVariantValue<PropertySheetEnumValue>(value).value; + return qvariant_cast<PropertySheetEnumValue>(value).value; } - else if (qVariantCanConvert<PropertySheetFlagValue>(value)) { + else if (value.canConvert<PropertySheetFlagValue>()) { if (ok) *ok = true; - return qVariantValue<PropertySheetFlagValue>(value).value; + return qvariant_cast<PropertySheetFlagValue>(value).value; } return value.toInt(ok); } diff --git a/tools/designer/src/lib/shared/richtexteditor.cpp b/tools/designer/src/lib/shared/richtexteditor.cpp index ec7c2e5..b5a2618 100644 --- a/tools/designer/src/lib/shared/richtexteditor.cpp +++ b/tools/designer/src/lib/shared/richtexteditor.cpp @@ -52,6 +52,9 @@ #include <QtCore/QList> #include <QtCore/QMap> #include <QtCore/QPointer> +#include <QtCore/QXmlStreamReader> +#include <QtCore/QXmlStreamWriter> +#include <QtCore/QXmlStreamAttributes> #include <QtGui/QAction> #include <QtGui/QColorDialog> @@ -74,28 +77,129 @@ QT_BEGIN_NAMESPACE -static const char *RichTextDialogC = "RichTextDialog"; -static const char *Geometry = "Geometry"; +static const char RichTextDialogGroupC[] = "RichTextDialog"; +static const char GeometryKeyC[] = "Geometry"; +static const char TabKeyC[] = "Tab"; + +const bool simplifyRichTextDefault = true; namespace qdesigner_internal { +// Richtext simplification filter helpers: Elements to be discarded +static inline bool filterElement(const QStringRef &name) +{ + return name != QLatin1String("meta") && name != QLatin1String("style"); +} + +// Richtext simplification filter helpers: Filter attributes of elements +static inline void filterAttributes(const QStringRef &name, + QXmlStreamAttributes *atts, + bool *paragraphAlignmentFound) +{ + typedef QXmlStreamAttributes::iterator AttributeIt; + + if (atts->isEmpty()) + return; + + // No style attributes for <body> + if (name == QLatin1String("body")) { + atts->clear(); + return; + } + + // Clean out everything except 'align' for 'p' + if (name == QLatin1String("p")) { + for (AttributeIt it = atts->begin(); it != atts->end(); ) { + if (it->name() == QLatin1String("align")) { + ++it; + *paragraphAlignmentFound = true; + } else { + it = atts->erase(it); + } + } + return; + } +} + +// Richtext simplification filter helpers: Check for blank QStringRef. +static inline bool isWhiteSpace(const QStringRef &in) +{ + const int count = in.size(); + for (int i = 0; i < count; i++) + if (!in.at(i).isSpace()) + return false; + return true; +} + +// Richtext simplification filter: Remove hard-coded font settings, +// <style> elements, <p> attributes other than 'align' and +// and unnecessary meta-information. +QString simplifyRichTextFilter(const QString &in, bool *isPlainTextPtr = 0) +{ + unsigned elementCount = 0; + bool paragraphAlignmentFound = false; + QString out; + QXmlStreamReader reader(in); + QXmlStreamWriter writer(&out); + writer.setAutoFormatting(false); + writer.setAutoFormattingIndent(0); + + while (!reader.atEnd()) { + switch (reader.readNext()) { + case QXmlStreamReader::StartElement: + elementCount++; + if (filterElement(reader.name())) { + const QStringRef name = reader.name(); + QXmlStreamAttributes attributes = reader.attributes(); + filterAttributes(name, &attributes, ¶graphAlignmentFound); + writer.writeStartElement(name.toString()); + if (!attributes.isEmpty()) + writer.writeAttributes(attributes); + } else { + reader.readElementText(); // Skip away all nested elements and characters. + } + break; + case QXmlStreamReader::Characters: + if (!isWhiteSpace(reader.text())) + writer.writeCharacters(reader.text().toString()); + break; + case QXmlStreamReader::EndElement: + writer.writeEndElement(); + break; + default: + break; + } + } + // Check for plain text (no spans, just <html><head><body><p>) + if (isPlainTextPtr) + *isPlainTextPtr = !paragraphAlignmentFound && elementCount == 4u; // + return out; +} + class RichTextEditor : public QTextEdit { Q_OBJECT public: - RichTextEditor(QWidget *parent = 0); - void setDefaultFont(const QFont &font); + explicit RichTextEditor(QWidget *parent = 0); + void setDefaultFont(QFont font); QToolBar *createToolBar(QDesignerFormEditorInterface *core, QWidget *parent = 0); + bool simplifyRichText() const { return m_simplifyRichText; } + public slots: void setFontBold(bool b); void setFontPointSize(double); void setText(const QString &text); + void setSimplifyRichText(bool v); QString text(Qt::TextFormat format) const; signals: void stateChanged(); + void simplifyRichTextChanged(bool); + +private: + bool m_simplifyRichText; }; class AddLinkDialog : public QDialog @@ -303,6 +407,7 @@ private: QAction *m_align_justify_action; QAction *m_link_action; QAction *m_image_action; + QAction *m_simplify_richtext_action; ColorAction *m_color_action; QComboBox *m_font_size_input; @@ -432,6 +537,17 @@ RichTextEditorToolBar::RichTextEditorToolBar(QDesignerFormEditorInterface *core, this, SLOT(colorChanged(QColor))); addAction(m_color_action); + addSeparator(); + + // Simplify rich text + m_simplify_richtext_action + = createCheckableAction(createIconSet(QLatin1String("simplifyrichtext.png")), + tr("Simplify Rich Text"), m_editor, SLOT(setSimplifyRichText(bool))); + m_simplify_richtext_action->setChecked(m_editor->simplifyRichText()); + connect(m_editor, SIGNAL(simplifyRichTextChanged(bool)), + m_simplify_richtext_action, SLOT(setChecked(bool))); + addAction(m_simplify_richtext_action); + connect(editor, SIGNAL(textChanged()), this, SLOT(updateActions())); connect(editor, SIGNAL(stateChanged()), this, SLOT(updateActions())); @@ -551,7 +667,7 @@ void RichTextEditorToolBar::updateActions() } RichTextEditor::RichTextEditor(QWidget *parent) - : QTextEdit(parent) + : QTextEdit(parent), m_simplifyRichText(simplifyRichTextDefault) { connect(this, SIGNAL(currentCharFormatChanged(QTextCharFormat)), this, SIGNAL(stateChanged())); @@ -579,14 +695,31 @@ void RichTextEditor::setFontPointSize(double d) void RichTextEditor::setText(const QString &text) { + if (Qt::mightBeRichText(text)) setHtml(text); else setPlainText(text); } -void RichTextEditor::setDefaultFont(const QFont &font) +void RichTextEditor::setSimplifyRichText(bool v) { + if (v != m_simplifyRichText) { + m_simplifyRichText = v; + emit simplifyRichTextChanged(v); + } +} + +void RichTextEditor::setDefaultFont(QFont font) +{ + // Some default fonts on Windows have a default size of 7.8, + // which results in complicated rich text generated by toHtml(). + // Use an integer value. + const int pointSize = qRound(font.pointSizeF()); + if (pointSize > 0 && !qFuzzyCompare(qreal(pointSize), font.pointSizeF())) { + font.setPointSize(pointSize); + } + document()->setDefaultFont(font); if (font.pointSize() > 0) setFontPointSize(font.pointSize()); @@ -602,15 +735,16 @@ QString RichTextEditor::text(Qt::TextFormat format) const case Qt::PlainText: return toPlainText(); case Qt::RichText: - return toHtml(); + return m_simplifyRichText ? simplifyRichTextFilter(toHtml()) : toHtml(); case Qt::AutoText: break; } const QString html = toHtml(); - const QString plain = toPlainText(); - QTextEdit tester; - tester.setPlainText(plain); - return tester.toHtml() == html ? plain : html; + bool isPlainText; + const QString simplifiedHtml = simplifyRichTextFilter(html, &isPlainText); + if (isPlainText) + return toPlainText(); + return m_simplifyRichText ? simplifiedHtml : html; } RichTextEditorDialog::RichTextEditorDialog(QDesignerFormEditorInterface *core, QWidget *parent) : @@ -619,15 +753,25 @@ RichTextEditorDialog::RichTextEditorDialog(QDesignerFormEditorInterface *core, Q m_text_edit(new HtmlTextEdit), m_tab_widget(new QTabWidget), m_state(Clean), - m_core(core) + m_core(core), + m_initialTab(RichTextIndex) { setWindowTitle(tr("Edit text")); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + // Read settings + const QDesignerSettingsInterface *settings = core->settingsManager(); + const QString rootKey = QLatin1String(RichTextDialogGroupC) + QLatin1Char('/'); + const QByteArray lastGeometry = settings->value(rootKey + QLatin1String(GeometryKeyC)).toByteArray(); + const int initialTab = settings->value(rootKey + QLatin1String(TabKeyC), QVariant(m_initialTab)).toInt(); + if (initialTab == RichTextIndex || initialTab == SourceIndex) + m_initialTab = initialTab; + m_text_edit->setAcceptRichText(false); new HtmlHighlighter(m_text_edit); connect(m_editor, SIGNAL(textChanged()), this, SLOT(richTextChanged())); + connect(m_editor, SIGNAL(simplifyRichTextChanged(bool)), this, SLOT(richTextChanged())); connect(m_text_edit, SIGNAL(textChanged()), this, SLOT(sourceChanged())); // The toolbar needs to be created after the RichTextEditor @@ -661,32 +805,33 @@ RichTextEditorDialog::RichTextEditorDialog(QDesignerFormEditorInterface *core, Q layout->addWidget(m_tab_widget); layout->addWidget(buttonBox); - m_editor->setFocus(); - - QDesignerSettingsInterface *settings = core->settingsManager(); - settings->beginGroup(QLatin1String(RichTextDialogC)); - - if (settings->contains(QLatin1String(Geometry))) - restoreGeometry(settings->value(QLatin1String(Geometry)).toByteArray()); - - settings->endGroup(); + if (!lastGeometry.isEmpty()) + restoreGeometry(lastGeometry); } RichTextEditorDialog::~RichTextEditorDialog() { QDesignerSettingsInterface *settings = m_core->settingsManager(); - settings->beginGroup(QLatin1String(RichTextDialogC)); + settings->beginGroup(QLatin1String(RichTextDialogGroupC)); - settings->setValue(QLatin1String(Geometry), saveGeometry()); + settings->setValue(QLatin1String(GeometryKeyC), saveGeometry()); + settings->setValue(QLatin1String(TabKeyC), m_tab_widget->currentIndex()); settings->endGroup(); } int RichTextEditorDialog::showDialog() { - m_tab_widget->setCurrentIndex(0); - m_editor->selectAll(); - m_editor->setFocus(); - + m_tab_widget->setCurrentIndex(m_initialTab); + switch (m_initialTab) { + case RichTextIndex: + m_editor->selectAll(); + m_editor->setFocus(); + break; + case SourceIndex: + m_text_edit->selectAll(); + m_text_edit->setFocus(); + break; + } return exec(); } @@ -697,6 +842,9 @@ void RichTextEditorDialog::setDefaultFont(const QFont &font) void RichTextEditorDialog::setText(const QString &text) { + // Generally simplify rich text unless verbose text is found. + const bool isSimplifiedRichText = !text.startsWith("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">"); + m_editor->setSimplifyRichText(isSimplifiedRichText); m_editor->setText(text); m_text_edit->setPlainText(text); m_state = Clean; diff --git a/tools/designer/src/lib/shared/richtexteditor_p.h b/tools/designer/src/lib/shared/richtexteditor_p.h index 44023ef..116ecb4 100644 --- a/tools/designer/src/lib/shared/richtexteditor_p.h +++ b/tools/designer/src/lib/shared/richtexteditor_p.h @@ -93,6 +93,7 @@ private: QTabWidget *m_tab_widget; State m_state; QDesignerFormEditorInterface *m_core; + int m_initialTab; }; } // namespace qdesigner_internal diff --git a/tools/designer/src/lib/shared/stylesheeteditor.cpp b/tools/designer/src/lib/shared/stylesheeteditor.cpp index e809447..bee5210 100644 --- a/tools/designer/src/lib/shared/stylesheeteditor.cpp +++ b/tools/designer/src/lib/shared/stylesheeteditor.cpp @@ -394,14 +394,14 @@ StyleSheetPropertyEditorDialog::StyleSheetPropertyEditorDialog(QWidget *parent, qt_extension<QDesignerPropertySheetExtension*>(m_fw->core()->extensionManager(), m_widget); Q_ASSERT(sheet != 0); const int index = sheet->indexOf(QLatin1String(styleSheetProperty)); - const PropertySheetStringValue value = qVariantValue<PropertySheetStringValue>(sheet->property(index)); + const PropertySheetStringValue value = qvariant_cast<PropertySheetStringValue>(sheet->property(index)); setText(value.value()); } void StyleSheetPropertyEditorDialog::applyStyleSheet() { const PropertySheetStringValue value(text(), false); - m_fw->cursor()->setWidgetProperty(m_widget, QLatin1String(styleSheetProperty), qVariantFromValue(value)); + m_fw->cursor()->setWidgetProperty(m_widget, QLatin1String(styleSheetProperty), QVariant::fromValue(value)); } } // namespace qdesigner_internal diff --git a/tools/designer/src/lib/shared/widgetfactory.cpp b/tools/designer/src/lib/shared/widgetfactory.cpp index c7b13a1..d686052 100644 --- a/tools/designer/src/lib/shared/widgetfactory.cpp +++ b/tools/designer/src/lib/shared/widgetfactory.cpp @@ -782,7 +782,7 @@ void WidgetFactory::applyStyleToTopLevel(QStyle *style, QWidget *widget) widget->setStyle(style); widget->setPalette(standardPalette); - const QWidgetList lst = qFindChildren<QWidget*>(widget); + const QWidgetList lst = widget->findChildren<QWidget*>(); const QWidgetList::const_iterator cend = lst.constEnd(); for (QWidgetList::const_iterator it = lst.constBegin(); it != cend; ++it) (*it)->setStyle(style); diff --git a/tools/designer/src/lib/shared/zoomwidget.cpp b/tools/designer/src/lib/shared/zoomwidget.cpp index f5d7434..5cf4ea2 100644 --- a/tools/designer/src/lib/shared/zoomwidget.cpp +++ b/tools/designer/src/lib/shared/zoomwidget.cpp @@ -328,7 +328,7 @@ void ZoomWidget::setWidget(QWidget *w, Qt::WindowFlags wFlags) scene().removeItem(m_proxy); if (QWidget *w = m_proxy->widget()) { // remove the event filter - if (QObject *evf = qFindChild<QObject*>(w, QLatin1String(zoomedEventFilterRedirectorNameC))) + if (QObject *evf = w->findChild<QObject*>(QLatin1String(zoomedEventFilterRedirectorNameC))) w->removeEventFilter(evf); } m_proxy->deleteLater(); diff --git a/tools/designer/src/lib/uilib/abstractformbuilder.cpp b/tools/designer/src/lib/uilib/abstractformbuilder.cpp index 6f009e3..ad2aa05 100644 --- a/tools/designer/src/lib/uilib/abstractformbuilder.cpp +++ b/tools/designer/src/lib/uilib/abstractformbuilder.cpp @@ -341,7 +341,7 @@ QWidget *QAbstractFormBuilder::create(DomWidget *ui_widget, QWidget *parentWidge w->addAction(a); } else if (QActionGroup *g = m_actionGroups.value(name)) { w->addActions(g->actions()); - } else if (QMenu *menu = qFindChild<QMenu*>(w, name)) { + } else if (QMenu *menu = w->findChild<QMenu*>(name)) { w->addAction(menu->menuAction()); addMenuAction(menu->menuAction()); } @@ -363,9 +363,9 @@ QWidget *QAbstractFormBuilder::create(DomWidget *ui_widget, QWidget *parentWidge const QStringList zOrderNames = ui_widget->elementZOrder(); if (!zOrderNames.isEmpty()) { - QList<QWidget *> zOrder = qVariantValue<QWidgetList>(w->property("_q_zOrder")); + QList<QWidget *> zOrder = qvariant_cast<QWidgetList>(w->property("_q_zOrder")); foreach (const QString &widgetName, zOrderNames) { - if (QWidget *child = qFindChild<QWidget*>(w, widgetName)) { + if (QWidget *child = w->findChild<QWidget*>(widgetName)) { if (child->parentWidget() == w) { zOrder.removeAll(child); zOrder.append(child); @@ -373,7 +373,7 @@ QWidget *QAbstractFormBuilder::create(DomWidget *ui_widget, QWidget *parentWidge } } } - w->setProperty("_q_zOrder", qVariantFromValue(zOrder)); + w->setProperty("_q_zOrder", QVariant::fromValue(zOrder)); } return w; @@ -1287,7 +1287,7 @@ DomWidget *QAbstractFormBuilder::createDom(QWidget *widget, DomWidget *ui_parent { QList<QObject *> childObjects = widget->children(); - const QList<QWidget *> list = qVariantValue<QWidgetList>(widget->property("_q_widgetOrder")); + const QList<QWidget *> list = qvariant_cast<QWidgetList>(widget->property("_q_widgetOrder")); foreach (QWidget *w, list) { if (childObjects.contains(w)) { children.append(w); @@ -1296,7 +1296,7 @@ DomWidget *QAbstractFormBuilder::createDom(QWidget *widget, DomWidget *ui_parent } children += childObjects; - const QList<QWidget *> zOrder = qVariantValue<QWidgetList>(widget->property("_q_zOrder")); + const QList<QWidget *> zOrder = qvariant_cast<QWidgetList>(widget->property("_q_zOrder")); if (list != zOrder) { QStringList zOrderList; QListIterator<QWidget* > itZOrder(zOrder); @@ -1603,14 +1603,14 @@ void QAbstractFormBuilder::applyTabStops(QWidget *widget, DomTabStops *tabStops) for (int i=0; i<l.size(); ++i) { const QString name = l.at(i); - QWidget *child = qFindChild<QWidget*>(widget, name); + QWidget *child = widget->findChild<QWidget*>(name); if (!child) { uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "While applying tab stops: The widget '%1' could not be found.").arg(name)); continue; } if (i == 0) { - lastWidget = qFindChild<QWidget*>(widget, name); + lastWidget = widget->findChild<QWidget*>(name); continue; } else if (!child || !lastWidget) { continue; @@ -1618,7 +1618,7 @@ void QAbstractFormBuilder::applyTabStops(QWidget *widget, DomTabStops *tabStops) QWidget::setTabOrder(lastWidget, child); - lastWidget = qFindChild<QWidget*>(widget, name); + lastWidget = widget->findChild<QWidget*>(name); } } @@ -1747,7 +1747,7 @@ static void loadItemProps(QAbstractFormBuilder *abstractFormBuilder, T *item, if ((p = properties.value(it.second))) { v = formBuilder->textBuilder()->loadText(p); QVariant nativeValue = formBuilder->textBuilder()->toNativeValue(v); - item->setData(it.first.first, qVariantValue<QString>(nativeValue)); + item->setData(it.first.first, qvariant_cast<QString>(nativeValue)); item->setData(it.first.second, v); } @@ -1759,7 +1759,7 @@ static void loadItemProps(QAbstractFormBuilder *abstractFormBuilder, T *item, if ((p = properties.value(strings.iconAttribute))) { v = formBuilder->resourceBuilder()->loadResource(formBuilder->workingDirectory(), p); QVariant nativeValue = formBuilder->resourceBuilder()->toNativeValue(v); - item->setIcon(qVariantValue<QIcon>(nativeValue)); + item->setIcon(qvariant_cast<QIcon>(nativeValue)); item->setData(Qt::DecorationPropertyRole, v); } } @@ -1855,7 +1855,7 @@ static void loadItemProps(QAbstractFormBuilder *abstractFormBuilder, QTableWidge if ((p = properties.value(it.second))) { v = formBuilder->textBuilder()->loadText(p); QVariant nativeValue = formBuilder->textBuilder()->toNativeValue(v); - item->setData(it.first.first, qVariantValue<QString>(nativeValue)); + item->setData(it.first.first, qvariant_cast<QString>(nativeValue)); item->setData(it.first.second, v); } @@ -1867,7 +1867,7 @@ static void loadItemProps(QAbstractFormBuilder *abstractFormBuilder, QTableWidge if ((p = properties.value(strings.iconAttribute))) { v = formBuilder->resourceBuilder()->loadResource(formBuilder->workingDirectory(), p); QVariant nativeValue = formBuilder->resourceBuilder()->toNativeValue(v); - item->setIcon(qVariantValue<QIcon>(nativeValue)); + item->setIcon(qvariant_cast<QIcon>(nativeValue)); item->setData(Qt::DecorationPropertyRole, v); } } @@ -1885,7 +1885,7 @@ static void loadItemProps(QAbstractFormBuilder *abstractFormBuilder, QListWidget if ((p = properties.value(it.second))) { v = formBuilder->textBuilder()->loadText(p); QVariant nativeValue = formBuilder->textBuilder()->toNativeValue(v); - item->setData(it.first.first, qVariantValue<QString>(nativeValue)); + item->setData(it.first.first, qvariant_cast<QString>(nativeValue)); item->setData(it.first.second, v); } @@ -1897,7 +1897,7 @@ static void loadItemProps(QAbstractFormBuilder *abstractFormBuilder, QListWidget if ((p = properties.value(strings.iconAttribute))) { v = formBuilder->resourceBuilder()->loadResource(formBuilder->workingDirectory(), p); QVariant nativeValue = formBuilder->resourceBuilder()->toNativeValue(v); - item->setIcon(qVariantValue<QIcon>(nativeValue)); + item->setIcon(qvariant_cast<QIcon>(nativeValue)); item->setData(Qt::DecorationPropertyRole, v); } } @@ -2337,14 +2337,14 @@ void QAbstractFormBuilder::loadTreeWidgetExtraInfo(DomWidget *ui_widget, QTreeWi if ((p = properties.value(it.second))) { v = textBuilder()->loadText(p); QVariant nativeValue = textBuilder()->toNativeValue(v); - treeWidget->headerItem()->setData(i, it.first.first, qVariantValue<QString>(nativeValue)); + treeWidget->headerItem()->setData(i, it.first.first, qvariant_cast<QString>(nativeValue)); treeWidget->headerItem()->setData(i, it.first.second, v); } if ((p = properties.value(strings.iconAttribute))) { v = resourceBuilder()->loadResource(workingDirectory(), p); QVariant nativeValue = resourceBuilder()->toNativeValue(v); - treeWidget->headerItem()->setIcon(i, qVariantValue<QIcon>(nativeValue)); + treeWidget->headerItem()->setIcon(i, qvariant_cast<QIcon>(nativeValue)); treeWidget->headerItem()->setData(i, Qt::DecorationPropertyRole, v); } } @@ -2374,14 +2374,14 @@ void QAbstractFormBuilder::loadTreeWidgetExtraInfo(DomWidget *ui_widget, QTreeWi col++; QVariant textV = textBuilder()->loadText(property); QVariant nativeValue = textBuilder()->toNativeValue(textV); - currentItem->setText(col, qVariantValue<QString>(nativeValue)); + currentItem->setText(col, qvariant_cast<QString>(nativeValue)); currentItem->setData(col, Qt::DisplayPropertyRole, textV); } else if (col >= 0) { if (property->attributeName() == strings.iconAttribute) { QVariant v = resourceBuilder()->loadResource(workingDirectory(), property); if (v.isValid()) { QVariant nativeValue = resourceBuilder()->toNativeValue(v); - currentItem->setIcon(col, qVariantValue<QIcon>(nativeValue)); + currentItem->setIcon(col, qvariant_cast<QIcon>(nativeValue)); currentItem->setData(col, Qt::DecorationPropertyRole, v); } } else { @@ -2397,7 +2397,7 @@ void QAbstractFormBuilder::loadTreeWidgetExtraInfo(DomWidget *ui_widget, QTreeWi if (rolePair.first >= 0) { QVariant textV = textBuilder()->loadText(property); QVariant nativeValue = textBuilder()->toNativeValue(textV); - currentItem->setData(col, rolePair.first, qVariantValue<QString>(nativeValue)); + currentItem->setData(col, rolePair.first, qvariant_cast<QString>(nativeValue)); currentItem->setData(col, rolePair.second, textV); } } @@ -2475,13 +2475,13 @@ void QAbstractFormBuilder::loadComboBoxExtraInfo(DomWidget *ui_widget, QComboBox p = properties.value(strings.textAttribute); if (p && p->elementString()) { textData = textBuilder()->loadText(p); - text = qVariantValue<QString>(textBuilder()->toNativeValue(textData)); + text = qvariant_cast<QString>(textBuilder()->toNativeValue(textData)); } p = properties.value(strings.iconAttribute); if (p) { iconData = resourceBuilder()->loadResource(workingDirectory(), p); - icon = qVariantValue<QIcon>(resourceBuilder()->toNativeValue(iconData)); + icon = qvariant_cast<QIcon>(resourceBuilder()->toNativeValue(iconData)); } comboBox->addItem(icon, text); diff --git a/tools/designer/src/lib/uilib/formbuilder.cpp b/tools/designer/src/lib/uilib/formbuilder.cpp index c97daac..c7d4e90 100644 --- a/tools/designer/src/lib/uilib/formbuilder.cpp +++ b/tools/designer/src/lib/uilib/formbuilder.cpp @@ -319,7 +319,7 @@ QWidget *QFormBuilder::widgetByName(QWidget *topLevel, const QString &name) if (topLevel->objectName() == name) return topLevel; - return qFindChild<QWidget*>(topLevel, name); + return topLevel->findChild<QWidget*>(name); } static QObject *objectByName(QWidget *topLevel, const QString &name) @@ -328,7 +328,7 @@ static QObject *objectByName(QWidget *topLevel, const QString &name) if (topLevel->objectName() == name) return topLevel; - return qFindChild<QObject*>(topLevel, name); + return topLevel->findChild<QObject*>(name); } /*! diff --git a/tools/designer/src/lib/uilib/formbuilderextra.cpp b/tools/designer/src/lib/uilib/formbuilderextra.cpp index 6c3357f..0747974 100644 --- a/tools/designer/src/lib/uilib/formbuilderextra.cpp +++ b/tools/designer/src/lib/uilib/formbuilderextra.cpp @@ -136,7 +136,7 @@ bool QFormBuilderExtra::applyBuddy(const QString &buddyName, BuddyMode applyMode return false; } - const QWidgetList widgets = qFindChildren<QWidget*>(label->topLevelWidget(), buddyName); + const QWidgetList widgets = label->topLevelWidget()->findChildren<QWidget*>(buddyName); if (widgets.empty()) { label->setBuddy(0); return false; diff --git a/tools/designer/src/lib/uilib/properties.cpp b/tools/designer/src/lib/uilib/properties.cpp index 615aa8a..b660dc4 100644 --- a/tools/designer/src/lib/uilib/properties.cpp +++ b/tools/designer/src/lib/uilib/properties.cpp @@ -78,7 +78,7 @@ QVariant domPropertyToVariant(QAbstractFormBuilder *afb,const QMetaObject *meta, case DomProperty::String: { const int index = meta->indexOfProperty(p->attributeName().toUtf8()); if (index != -1 && meta->property(index).type() == QVariant::KeySequence) - return qVariantFromValue(QKeySequence(p->elementString()->text())); + return QVariant::fromValue(QKeySequence(p->elementString()->text())); } break; @@ -96,7 +96,7 @@ QVariant domPropertyToVariant(QAbstractFormBuilder *afb,const QMetaObject *meta, afb->setupColorGroup(palette, QPalette::Disabled, dom->elementDisabled()); palette.setCurrentColorGroup(QPalette::Active); - return qVariantFromValue(palette); + return QVariant::fromValue(palette); } case DomProperty::Set: { @@ -135,7 +135,7 @@ QVariant domPropertyToVariant(QAbstractFormBuilder *afb,const QMetaObject *meta, return QVariant(e.keyToValue(enumValue.toUtf8())); } case DomProperty::Brush: - return qVariantFromValue(afb->setupBrush(p->elementBrush())); + return QVariant::fromValue(afb->setupBrush(p->elementBrush())); default: if (afb->resourceBuilder()->isResourceProperty(p)) { return afb->resourceBuilder()->loadResource(afb->workingDirectory(), p); @@ -212,7 +212,7 @@ QVariant domPropertyToVariant(const DomProperty *p) case DomProperty::Char: { const DomChar *character = p->elementChar(); const QChar c(character->elementUnicode()); - return qVariantFromValue(c); + return QVariant::fromValue(c); } case DomProperty::Color: { @@ -220,7 +220,7 @@ QVariant domPropertyToVariant(const DomProperty *p) QColor c(color->elementRed(), color->elementGreen(), color->elementBlue()); if (color->hasAttributeAlpha()) c.setAlpha(color->attributeAlpha()); - return qVariantFromValue(c); + return QVariant::fromValue(c); } case DomProperty::Font: { @@ -248,7 +248,7 @@ QVariant domPropertyToVariant(const DomProperty *p) if (font->hasElementStyleStrategy()) { f.setStyleStrategy(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QFont::StyleStrategy>("styleStrategy", font->elementStyleStrategy().toLatin1())); } - return qVariantFromValue(f); + return QVariant::fromValue(f); } case DomProperty::Date: { @@ -275,15 +275,15 @@ QVariant domPropertyToVariant(const DomProperty *p) #ifndef QT_NO_CURSOR case DomProperty::Cursor: - return qVariantFromValue(QCursor(static_cast<Qt::CursorShape>(p->elementCursor()))); + return QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(p->elementCursor()))); case DomProperty::CursorShape: - return qVariantFromValue(QCursor(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, Qt::CursorShape>("cursorShape", p->elementCursorShape().toLatin1()))); + return QVariant::fromValue(QCursor(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, Qt::CursorShape>("cursorShape", p->elementCursorShape().toLatin1()))); #endif case DomProperty::Locale: { const DomLocale *locale = p->elementLocale(); - return qVariantFromValue(QLocale(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QLocale::Language>("language", locale->attributeLanguage().toLatin1()), + return QVariant::fromValue(QLocale(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QLocale::Language>("language", locale->attributeLanguage().toLatin1()), enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QLocale::Country>("country", locale->attributeCountry().toLatin1()))); } case DomProperty::SizePolicy: { @@ -309,7 +309,7 @@ QVariant domPropertyToVariant(const DomProperty *p) sizePolicy.setVerticalPolicy(sp); } - return qVariantFromValue(sizePolicy); + return QVariant::fromValue(sizePolicy); } case DomProperty::StringList: diff --git a/tools/designer/src/lib/uilib/resourcebuilder.cpp b/tools/designer/src/lib/uilib/resourcebuilder.cpp index 810bea0..03e2a66 100644 --- a/tools/designer/src/lib/uilib/resourcebuilder.cpp +++ b/tools/designer/src/lib/uilib/resourcebuilder.cpp @@ -44,6 +44,7 @@ #include <QtCore/QVariant> #include <QtCore/QFileInfo> #include <QtCore/QDir> +#include <QtCore/QDebug> #include <QtGui/QPixmap> #include <QtGui/QIcon> @@ -53,6 +54,8 @@ QT_BEGIN_NAMESPACE namespace QFormInternal { #endif +enum { themeDebug = 0 }; + QResourceBuilder::QResourceBuilder() { @@ -91,10 +94,18 @@ QVariant QResourceBuilder::loadResource(const QDir &workingDirectory, const DomP case DomProperty::Pixmap: { const DomResourcePixmap *dpx = property->elementPixmap(); QPixmap pixmap(QFileInfo(workingDirectory, dpx->text()).absoluteFilePath()); - return qVariantFromValue(pixmap); + return QVariant::fromValue(pixmap); } case DomProperty::IconSet: { const DomResourceIcon *dpi = property->elementIconSet(); + if (!dpi->attributeTheme().isEmpty()) { + const QString theme = dpi->attributeTheme(); + const bool known = QIcon::hasThemeIcon(theme); + if (themeDebug) + qDebug("Theme %s known %d", qPrintable(theme), known); + if (known) + return qVariantFromValue(QIcon::fromTheme(dpi->attributeTheme())); + } // non-empty theme if (const int flags = iconStateFlags(dpi)) { // new, post 4.4 format QIcon icon; if (flags & NormalOff) @@ -113,10 +124,10 @@ QVariant QResourceBuilder::loadResource(const QDir &workingDirectory, const DomP icon.addFile(QFileInfo(workingDirectory, dpi->elementSelectedOff()->text()).absoluteFilePath(), QSize(), QIcon::Selected, QIcon::Off); if (flags & SelectedOn) icon.addFile(QFileInfo(workingDirectory, dpi->elementSelectedOn()->text()).absoluteFilePath(), QSize(), QIcon::Selected, QIcon::On); - return qVariantFromValue(icon); + return QVariant::fromValue(icon); } else { // 4.3 legacy const QIcon icon(QFileInfo(workingDirectory, dpi->text()).absoluteFilePath()); - return qVariantFromValue(icon); + return QVariant::fromValue(icon); } } break; diff --git a/tools/designer/src/lib/uilib/ui4.cpp b/tools/designer/src/lib/uilib/ui4.cpp index c13bd59..98974e6 100644 --- a/tools/designer/src/lib/uilib/ui4.cpp +++ b/tools/designer/src/lib/uilib/ui4.cpp @@ -7745,6 +7745,7 @@ void DomResourceIcon::clear(bool clear_all) if (clear_all) { m_text = QLatin1String(""); + m_has_attr_theme = false; m_has_attr_resource = false; } @@ -7762,6 +7763,7 @@ void DomResourceIcon::clear(bool clear_all) DomResourceIcon::DomResourceIcon() { m_children = 0; + m_has_attr_theme = false; m_has_attr_resource = false; m_text = QLatin1String(""); m_normalOff = 0; @@ -7791,6 +7793,10 @@ void DomResourceIcon::read(QXmlStreamReader &reader) foreach (const QXmlStreamAttribute &attribute, reader.attributes()) { QStringRef name = attribute.name(); + if (name == QLatin1String("theme")) { + setAttributeTheme(attribute.value().toString()); + continue; + } if (name == QLatin1String("resource")) { setAttributeResource(attribute.value().toString()); continue; @@ -7869,6 +7875,8 @@ void DomResourceIcon::read(QXmlStreamReader &reader) #ifdef QUILOADER_QDOM_READ void DomResourceIcon::read(const QDomElement &node) { + if (node.hasAttribute(QLatin1String("theme"))) + setAttributeTheme(node.attribute(QLatin1String("theme"))); if (node.hasAttribute(QLatin1String("resource"))) setAttributeResource(node.attribute(QLatin1String("resource"))); @@ -7938,6 +7946,9 @@ void DomResourceIcon::write(QXmlStreamWriter &writer, const QString &tagName) co { writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("resourceicon") : tagName.toLower()); + if (hasAttributeTheme()) + writer.writeAttribute(QLatin1String("theme"), attributeTheme()); + if (hasAttributeResource()) writer.writeAttribute(QLatin1String("resource"), attributeResource()); diff --git a/tools/designer/src/lib/uilib/ui4_p.h b/tools/designer/src/lib/uilib/ui4_p.h index 1f38f88..a464a89 100644 --- a/tools/designer/src/lib/uilib/ui4_p.h +++ b/tools/designer/src/lib/uilib/ui4_p.h @@ -2809,6 +2809,11 @@ public: inline void setText(const QString &s) { m_text = s; } // attribute accessors + inline bool hasAttributeTheme() const { return m_has_attr_theme; } + inline QString attributeTheme() const { return m_attr_theme; } + inline void setAttributeTheme(const QString& a) { m_attr_theme = a; m_has_attr_theme = true; } + inline void clearAttributeTheme() { m_has_attr_theme = false; } + inline bool hasAttributeResource() const { return m_has_attr_resource; } inline QString attributeResource() const { return m_attr_resource; } inline void setAttributeResource(const QString& a) { m_attr_resource = a; m_has_attr_resource = true; } @@ -2868,6 +2873,9 @@ private: void clear(bool clear_all = true); // attribute data + QString m_attr_theme; + bool m_has_attr_theme; + QString m_attr_resource; bool m_has_attr_resource; diff --git a/tools/designer/src/uitools/quiloader.cpp b/tools/designer/src/uitools/quiloader.cpp index c7e7829..411059e 100644 --- a/tools/designer/src/uitools/quiloader.cpp +++ b/tools/designer/src/uitools/quiloader.cpp @@ -102,27 +102,27 @@ QVariant TranslatingTextBuilder::loadText(const DomProperty *text) const if (str->hasAttributeNotr()) { const QString notr = str->attributeNotr(); if (notr == QLatin1String("true") || notr == QLatin1String("yes")) - return qVariantFromValue(str->text()); + return QVariant::fromValue(str->text()); } QUiTranslatableStringValue strVal; strVal.setValue(str->text().toUtf8()); if (str->hasAttributeComment()) strVal.setComment(str->attributeComment().toUtf8()); - return qVariantFromValue(strVal); + return QVariant::fromValue(strVal); } QVariant TranslatingTextBuilder::toNativeValue(const QVariant &value) const { - if (qVariantCanConvert<QUiTranslatableStringValue>(value)) { - QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(value); + if (value.canConvert<QUiTranslatableStringValue>()) { + QUiTranslatableStringValue tsv = qvariant_cast<QUiTranslatableStringValue>(value); if (!m_trEnabled) return QString::fromUtf8(tsv.value().data()); - return qVariantFromValue( + return QVariant::fromValue( QApplication::translate(m_className, tsv.value(), tsv.comment(), QCoreApplication::UnicodeUTF8)); } - if (qVariantCanConvert<QString>(value)) - return qVariantFromValue(qVariantValue<QString>(value)); + if (value.canConvert<QString>()) + return QVariant::fromValue(qvariant_cast<QString>(value)); return value; } @@ -150,7 +150,7 @@ static void recursiveReTranslate(QTreeWidgetItem *item, const QByteArray &class_ for (unsigned j = 0; irs[j].shadowRole >= 0; j++) { QVariant v = item->data(i, irs[j].shadowRole); if (v.isValid()) { - QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v); + QUiTranslatableStringValue tsv = qvariant_cast<QUiTranslatableStringValue>(v); const QString text = QApplication::translate(class_name, tsv.value(), tsv.comment(), QCoreApplication::UnicodeUTF8); @@ -172,7 +172,7 @@ static void reTranslateWidgetItem(T *item, const QByteArray &class_name) for (unsigned j = 0; irs[j].shadowRole >= 0; j++) { QVariant v = item->data(irs[j].shadowRole); if (v.isValid()) { - QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v); + QUiTranslatableStringValue tsv = qvariant_cast<QUiTranslatableStringValue>(v); const QString text = QApplication::translate(class_name, tsv.value(), tsv.comment(), QCoreApplication::UnicodeUTF8); @@ -191,7 +191,7 @@ static void reTranslateTableItem(QTableWidgetItem *item, const QByteArray &class do { \ QVariant v = mainWidget->widget(i)->property(propName); \ if (v.isValid()) { \ - QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v); \ + QUiTranslatableStringValue tsv = qvariant_cast<QUiTranslatableStringValue>(v); \ const QString text = QApplication::translate(m_className, \ tsv.value(), tsv.comment(), \ QCoreApplication::UnicodeUTF8); \ @@ -217,7 +217,7 @@ public: if (prop.startsWith(PROP_GENERIC_PREFIX)) { const QByteArray propName = prop.mid(sizeof(PROP_GENERIC_PREFIX) - 1); const QUiTranslatableStringValue tsv = - qVariantValue<QUiTranslatableStringValue>(o->property(prop)); + qvariant_cast<QUiTranslatableStringValue>(o->property(prop)); const QString text = QApplication::translate(m_className, tsv.value(), tsv.comment(), QCoreApplication::UnicodeUTF8); @@ -273,7 +273,7 @@ public: for (int i = 0; i < cnt; ++i) { const QVariant v = combow->itemData(i, Qt::DisplayPropertyRole); if (v.isValid()) { - QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v); + QUiTranslatableStringValue tsv = qvariant_cast<QUiTranslatableStringValue>(v); const QString text = QApplication::translate(m_className, tsv.value(), tsv.comment(), QCoreApplication::UnicodeUTF8); @@ -430,7 +430,7 @@ void FormBuilderPrivate::applyProperties(QObject *o, const QList<DomProperty*> & continue; const QByteArray name = p->attributeName().toUtf8(); if (dynamicTr) { - o->setProperty(PROP_GENERIC_PREFIX + name, qVariantFromValue(strVal)); + o->setProperty(PROP_GENERIC_PREFIX + name, QVariant::fromValue(strVal)); anyTrs = trEnabled; } o->setProperty(name, text); @@ -489,7 +489,7 @@ QWidget *FormBuilderPrivate::create(DomWidget *ui_widget, QWidget *parentWidget) const QString text = convertTranslatable(p##attribute, m_class, &strVal); \ if (!text.isEmpty()) { \ if (dynamicTr) \ - mainWidget->widget(i)->setProperty(propName, qVariantFromValue(strVal)); \ + mainWidget->widget(i)->setProperty(propName, QVariant::fromValue(strVal)); \ mainWidget->setter(i, text); \ } \ } \ diff --git a/tools/linguist/linguist/formpreviewview.cpp b/tools/linguist/linguist/formpreviewview.cpp index f360a16..3f3f82a 100644 --- a/tools/linguist/linguist/formpreviewview.cpp +++ b/tools/linguist/linguist/formpreviewview.cpp @@ -83,7 +83,7 @@ static bool operator==(const QUiTranslatableStringValue &tsv1, const QUiTranslat target.type = _type; \ target.target._target; \ target.prop._prop; \ - (*targets)[qVariantValue<QUiTranslatableStringValue>(_tsv)].append(target); \ + (*targets)[qvariant_cast<QUiTranslatableStringValue>(_tsv)].append(target); \ } while (0) static void registerTreeItem(QTreeWidgetItem *item, TargetsHash *targets) @@ -350,14 +350,14 @@ static void highlightAction(QAction *a, bool on) if (on) { if (!bak.isValid()) { QFont fnt = qApp->font(); - a->setProperty(FONT_BACKUP_PROP, qVariantFromValue(a->font().resolve(fnt))); + a->setProperty(FONT_BACKUP_PROP, QVariant::fromValue(a->font().resolve(fnt))); fnt.setBold(true); fnt.setItalic(true); a->setFont(fnt); } } else { if (bak.isValid()) { - a->setFont(qVariantValue<QFont>(bak)); + a->setFont(qvariant_cast<QFont>(bak)); a->setProperty(FONT_BACKUP_PROP, QVariant()); } } @@ -374,8 +374,8 @@ static void highlightWidget(QWidget *w, bool on) foreach (QObject *co, w->children()) if (QWidget *cw = qobject_cast<QWidget *>(co)) cw->setPalette(cw->palette().resolve(pal)); - w->setProperty(PALETTE_BACKUP_PROP, qVariantFromValue(w->palette().resolve(pal))); - w->setProperty(AUTOFILL_BACKUP_PROP, qVariantFromValue(w->autoFillBackground())); + w->setProperty(PALETTE_BACKUP_PROP, QVariant::fromValue(w->palette().resolve(pal))); + w->setProperty(AUTOFILL_BACKUP_PROP, QVariant::fromValue(w->autoFillBackground())); QColor col1 = pal.color(QPalette::Dark); QColor col2 = pal.color(QPalette::Light); pal.setColor(QPalette::Base, col1); @@ -390,8 +390,8 @@ static void highlightWidget(QWidget *w, bool on) } } else { if (bak.isValid()) { - w->setPalette(qVariantValue<QPalette>(bak)); - w->setAutoFillBackground(qVariantValue<bool>(w->property(AUTOFILL_BACKUP_PROP))); + w->setPalette(qvariant_cast<QPalette>(bak)); + w->setAutoFillBackground(qvariant_cast<bool>(w->property(AUTOFILL_BACKUP_PROP))); w->setProperty(PALETTE_BACKUP_PROP, QVariant()); w->setProperty(AUTOFILL_BACKUP_PROP, QVariant()); } diff --git a/tools/linguist/linguist/mainwindow.cpp b/tools/linguist/linguist/mainwindow.cpp index 18baa24..8520cf7 100644 --- a/tools/linguist/linguist/mainwindow.cpp +++ b/tools/linguist/linguist/mainwindow.cpp @@ -187,7 +187,7 @@ private: static const QVariant &pxObsolete() { static const QVariant v = - qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_obsolete.png"))); + QVariant::fromValue(QPixmap(QLatin1String(":/images/s_check_obsolete.png"))); return v; } diff --git a/tools/linguist/linguist/messagemodel.cpp b/tools/linguist/linguist/messagemodel.cpp index 39ba9fd..36202ab 100644 --- a/tools/linguist/linguist/messagemodel.cpp +++ b/tools/linguist/linguist/messagemodel.cpp @@ -1231,17 +1231,17 @@ int MessageModel::columnCount(const QModelIndex &) const QVariant MessageModel::data(const QModelIndex &index, int role) const { static QVariant pxOn = - qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_on.png"))); + QVariant::fromValue(QPixmap(QLatin1String(":/images/s_check_on.png"))); static QVariant pxOff = - qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_off.png"))); + QVariant::fromValue(QPixmap(QLatin1String(":/images/s_check_off.png"))); static QVariant pxObsolete = - qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_obsolete.png"))); + QVariant::fromValue(QPixmap(QLatin1String(":/images/s_check_obsolete.png"))); static QVariant pxDanger = - qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_danger.png"))); + QVariant::fromValue(QPixmap(QLatin1String(":/images/s_check_danger.png"))); static QVariant pxWarning = - qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_warning.png"))); + QVariant::fromValue(QPixmap(QLatin1String(":/images/s_check_warning.png"))); static QVariant pxEmpty = - qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_empty.png"))); + QVariant::fromValue(QPixmap(QLatin1String(":/images/s_check_empty.png"))); int row = index.row(); int column = index.column() - 1; diff --git a/tools/makeqpf/mainwindow.cpp b/tools/makeqpf/mainwindow.cpp index 166a193..ae723f5 100644 --- a/tools/makeqpf/mainwindow.cpp +++ b/tools/makeqpf/mainwindow.cpp @@ -199,7 +199,7 @@ void MainWindow::on_generate_clicked() if (item->checkState() != Qt::Checked) continue; - QPF::CharacterRange range = qVariantValue<QPF::CharacterRange>(item->data(Qt::UserRole)); + QPF::CharacterRange range = qvariant_cast<QPF::CharacterRange>(item->data(Qt::UserRole)); ranges.append(range); } } @@ -297,7 +297,7 @@ void MainWindow::populateCharacterRanges() item->setText(text); item->setCheckState(Qt::Checked); - item->setData(Qt::UserRole, qVariantFromValue(range)); + item->setData(Qt::UserRole, QVariant::fromValue(range)); } } diff --git a/tools/qdbus/qdbus/qdbus.cpp b/tools/qdbus/qdbus/qdbus.cpp index ce18cb9..c93288c 100644 --- a/tools/qdbus/qdbus/qdbus.cpp +++ b/tools/qdbus/qdbus/qdbus.cpp @@ -324,7 +324,7 @@ static int placeCall(const QString &service, const QString &path, const QString if (id == int(QMetaType::UChar)) { // special case: QVariant::convert doesn't convert to/from // UChar because it can't decide if it's a character or a number - p = qVariantFromValue<uchar>(p.toUInt()); + p = QVariant::fromValue<uchar>(p.toUInt()); } else if (id < int(QMetaType::User) && id != int(QVariant::Map)) { p.convert(QVariant::Type(id)); if (p.type() == QVariant::Invalid) { @@ -334,7 +334,7 @@ static int placeCall(const QString &service, const QString &path, const QString } } else if (id == qMetaTypeId<QDBusVariant>()) { QDBusVariant tmp(p); - p = qVariantFromValue(tmp); + p = QVariant::fromValue(tmp); } else if (id == qMetaTypeId<QDBusObjectPath>()) { QDBusObjectPath path(argument); if (path.path().isNull()) { @@ -342,7 +342,7 @@ static int placeCall(const QString &service, const QString &path, const QString qPrintable(argument)); return 1; } - p = qVariantFromValue(path); + p = QVariant::fromValue(path); } else if (id == qMetaTypeId<QDBusSignature>()) { QDBusSignature sig(argument); if (sig.signature().isNull()) { @@ -350,7 +350,7 @@ static int placeCall(const QString &service, const QString &path, const QString qPrintable(argument)); return 1; } - p = qVariantFromValue(sig); + p = QVariant::fromValue(sig); } else { fprintf(stderr, "Sorry, can't pass arg of type '%s'.\n", types.at(i).constData()); diff --git a/tools/qdbus/qdbusviewer/qdbusviewer.cpp b/tools/qdbus/qdbusviewer/qdbusviewer.cpp index 9878aff..9bc5a15 100644 --- a/tools/qdbus/qdbusviewer/qdbusviewer.cpp +++ b/tools/qdbus/qdbusviewer/qdbusviewer.cpp @@ -217,7 +217,7 @@ void QDBusViewer::setProperty(const BusSignature &sig) QDBusMessage message = QDBusMessage::createMethodCall(sig.mService, sig.mPath, QLatin1String("org.freedesktop.DBus.Properties"), QLatin1String("Set")); QList<QVariant> arguments; - arguments << sig.mInterface << sig.mName << qVariantFromValue(QDBusVariant(value)); + arguments << sig.mInterface << sig.mName << QVariant::fromValue(QDBusVariant(value)); message.setArguments(arguments); c.callWithCallback(message, this, SLOT(dumpMessage(QDBusMessage))); @@ -283,7 +283,7 @@ void QDBusViewer::callMethod(const BusSignature &sig) // interface wants a variant for (int i = 0; i < args.count(); ++i) { if (types.at(i) == qMetaTypeId<QDBusVariant>()) - args[i] = qVariantFromValue(QDBusVariant(args.at(i))); + args[i] = QVariant::fromValue(QDBusVariant(args.at(i))); } QDBusMessage message = QDBusMessage::createMethodCall(sig.mService, sig.mPath, sig.mInterface, diff --git a/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp b/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp index d9343e3..31667dc 100644 --- a/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp +++ b/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp @@ -617,7 +617,7 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf if (property.access != QDBusIntrospection::Property::Read) { hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << endl << " { setProperty(\"" << property.name - << "\", qVariantFromValue(value)); }" << endl; + << "\", QVariant::fromValue(value)); }" << endl; } hs << endl; @@ -660,7 +660,7 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf if (!method.inputArgs.isEmpty()) { hs << " argumentList"; for (int argPos = 0; argPos < method.inputArgs.count(); ++argPos) - hs << " << qVariantFromValue(" << argNames.at(argPos) << ')'; + hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; hs << ";" << endl; } @@ -693,7 +693,7 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf if (!method.inputArgs.isEmpty()) { hs << " argumentList"; for (argPos = 0; argPos < method.inputArgs.count(); ++argPos) - hs << " << qVariantFromValue(" << argNames.at(argPos) << ')'; + hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; hs << ";" << endl; } @@ -940,7 +940,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << endl << "{" << endl << " // set the value of property " << property.name << endl - << " parent()->setProperty(\"" << property.name << "\", qVariantFromValue(value"; + << " parent()->setProperty(\"" << property.name << "\", QVariant::fromValue(value"; if (constRefType.contains(QLatin1String("QDBusVariant"))) cs << ".variant()"; cs << "));" << endl diff --git a/tools/qdoc3/doc/qdoc-manual.qdocconf b/tools/qdoc3/doc/qdoc-manual.qdocconf index 26fd09c..5a725b9 100644 --- a/tools/qdoc3/doc/qdoc-manual.qdocconf +++ b/tools/qdoc3/doc/qdoc-manual.qdocconf @@ -32,7 +32,7 @@ HTML.postheader = "<table border=\"0\" cellpadding=\"0\" cellspacing=\"5\" widt "<td class=\"postheader\" valign=\"center\">" \ "<a href=\"01-qdoc-manual.html\">" \ "<font color=\"#004faf\">Home: QDoc Manual</font></a> ·" \ - "<a href=\"http://qt.nokia.com/doc/4.7\">" \ + "<a href=\"http://qt.nokia.com/doc/4.8\">" \ "<font color=\"#004faf\"> Qt Reference Documentation</font></a>" \ "</td>\n" \ "</tr></table>" diff --git a/tools/qdoc3/test/assistant.qdocconf b/tools/qdoc3/test/assistant.qdocconf index 836c4bf..bb98db4 100644 --- a/tools/qdoc3/test/assistant.qdocconf +++ b/tools/qdoc3/test/assistant.qdocconf @@ -6,14 +6,14 @@ include(qt-defines.qdocconf) project = Qt Assistant description = Qt Assistant Manual -url = http://doc.qt.nokia.com/4.7/ +url = http://doc.qt.nokia.com/4.8/ indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Assistant qhp.Assistant.file = assistant.qhp -qhp.Assistant.namespace = com.trolltech.assistant.470 +qhp.Assistant.namespace = com.trolltech.assistant.480 qhp.Assistant.virtualFolder = qdoc qhp.Assistant.indexTitle = Qt Assistant Manual qhp.Assistant.extraFiles = images/bg_l.png \ @@ -50,7 +50,7 @@ qhp.Assistant.extraFiles = images/bg_l.png \ style/style_ie8.css \ style/style.css -qhp.Assistant.filterAttributes = qt 4.7.0 tools assistant +qhp.Assistant.filterAttributes = qt 4.8.0 tools assistant qhp.Assistant.customFilters.Assistant.name = Qt Assistant Manual qhp.Assistant.customFilters.Assistant.filterAttributes = qt tools assistant qhp.Assistant.subprojects = manual examples diff --git a/tools/qdoc3/test/designer.qdocconf b/tools/qdoc3/test/designer.qdocconf index 9136619..448ed23 100644 --- a/tools/qdoc3/test/designer.qdocconf +++ b/tools/qdoc3/test/designer.qdocconf @@ -6,7 +6,7 @@ include(qt-defines.qdocconf) project = Qt Designer description = Qt Designer Manual -url = http://doc.qt.nokia.com/4.7/ +url = http://doc.qt.nokia.com/4.8/ indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index @@ -50,7 +50,7 @@ qhp.Designer.extraFiles = images/bg_l.png \ style/style_ie8.css \ style/style.css -qhp.Designer.filterAttributes = qt 4.7.0 tools designer +qhp.Designer.filterAttributes = qt 4.8.0 tools designer qhp.Designer.customFilters.Designer.name = Qt Designer Manual qhp.Designer.customFilters.Designer.filterAttributes = qt tools designer qhp.Designer.subprojects = manual examples diff --git a/tools/qdoc3/test/linguist.qdocconf b/tools/qdoc3/test/linguist.qdocconf index 696802a..7c4b938 100644 --- a/tools/qdoc3/test/linguist.qdocconf +++ b/tools/qdoc3/test/linguist.qdocconf @@ -6,14 +6,14 @@ include(qt-defines.qdocconf) project = Qt Linguist description = Qt Linguist Manual -url = http://doc.qt.nokia.com/4.7/ +url = http://doc.qt.nokia.com/4.8/ indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Linguist qhp.Linguist.file = linguist.qhp -qhp.Linguist.namespace = com.trolltech.linguist.470 +qhp.Linguist.namespace = com.trolltech.linguist.480 qhp.Linguist.virtualFolder = qdoc qhp.Linguist.indexTitle = Qt Linguist Manual qhp.Linguist.extraFiles = images/bg_l.png \ @@ -50,7 +50,7 @@ qhp.Linguist.extraFiles = images/bg_l.png \ style/style_ie8.css \ style/style.css -qhp.Linguist.filterAttributes = qt 4.7.0 tools linguist +qhp.Linguist.filterAttributes = qt 4.8.0 tools linguist qhp.Linguist.customFilters.Linguist.name = Qt Linguist Manual qhp.Linguist.customFilters.Linguist.filterAttributes = qt tools linguist qhp.Linguist.subprojects = manual examples diff --git a/tools/qdoc3/test/qmake.qdocconf b/tools/qdoc3/test/qmake.qdocconf index 8125166..56e7f96 100644 --- a/tools/qdoc3/test/qmake.qdocconf +++ b/tools/qdoc3/test/qmake.qdocconf @@ -6,14 +6,14 @@ include(qt-defines.qdocconf) project = QMake description = QMake Manual -url = http://qt.nokia.com/doc/4.7 +url = http://qt.nokia.com/doc/4.8 indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = qmake qhp.qmake.file = qmake.qhp -qhp.qmake.namespace = com.trolltech.qmake.470 +qhp.qmake.namespace = com.trolltech.qmake.480 qhp.qmake.virtualFolder = qdoc qhp.qmake.indexTitle = QMake Manual qhp.qmake.extraFiles = images/bg_l.png \ @@ -50,7 +50,7 @@ qhp.qmake.extraFiles = images/bg_l.png \ style/style_ie8.css \ style/style.css -qhp.qmake.filterAttributes = qt 4.7.0 tools qmake +qhp.qmake.filterAttributes = qt 4.8.0 tools qmake qhp.qmake.customFilters.qmake.name = qmake Manual qhp.qmake.customFilters.qmake.filterAttributes = qt tools qmake qhp.qmake.subprojects = manual diff --git a/tools/qdoc3/test/qt-build-docs.qdocconf b/tools/qdoc3/test/qt-build-docs.qdocconf index 639585c..6a06a8c 100644 --- a/tools/qdoc3/test/qt-build-docs.qdocconf +++ b/tools/qdoc3/test/qt-build-docs.qdocconf @@ -6,7 +6,7 @@ include(qt-defines.qdocconf) project = Qt description = Qt Reference Documentation -url = http://qt.nokia.com/doc/4.7 +url = http://qt.nokia.com/doc/4.8 sourceencoding = UTF-8 outputencoding = UTF-8 @@ -15,7 +15,7 @@ naturallanguage = en_US qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.470 +qhp.Qt.namespace = com.trolltech.qt.480 qhp.Qt.virtualFolder = qdoc qhp.Qt.indexTitle = Qt Reference Documentation qhp.Qt.indexRoot = @@ -59,9 +59,9 @@ qhp.Qt.extraFiles = index.html \ -qhp.Qt.filterAttributes = qt 4.7.0 qtrefdoc -qhp.Qt.customFilters.Qt.name = Qt 4.7.0 -qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.0 +qhp.Qt.filterAttributes = qt 4.8.0 qtrefdoc +qhp.Qt.customFilters.Qt.name = Qt 4.8.0 +qhp.Qt.customFilters.Qt.filterAttributes = qt 4.8.0 qhp.Qt.subprojects = classes overviews examples qhp.Qt.subprojects.classes.title = Classes qhp.Qt.subprojects.classes.indexTitle = Qt's Classes diff --git a/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf b/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf index a983faa..d932dfb 100644 --- a/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf +++ b/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf @@ -6,7 +6,7 @@ include(qt-defines.qdocconf) project = Qt description = Qt Reference Documentation -url = http://qt.nokia.com/doc/zh_CN/4.7 +url = http://qt.nokia.com/doc/zh_CN/4.8 sourceencoding = UTF-8 outputencoding = UTF-8 @@ -17,15 +17,15 @@ indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.470 +qhp.Qt.namespace = com.trolltech.qt.480 qhp.Qt.virtualFolder = qdoc qhp.Qt.title = 教程 qhp.Qt.indexTitle = 教程 qhp.Qt.selectors = fake:example -qhp.Qt.filterAttributes = qt 4.7.0 qtrefdoc zh_CN -qhp.Qt.customFilters.Qt.name = Qt 4.7.0 -qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.0 +qhp.Qt.filterAttributes = qt 4.8.0 qtrefdoc zh_CN +qhp.Qt.customFilters.Qt.name = Qt 4.8.0 +qhp.Qt.customFilters.Qt.filterAttributes = qt 4.8.0 # Files not referenced in any qdoc file (last four are needed by qtdemo) # See also extraimages.HTML diff --git a/tools/qdoc3/test/qt-html-templates.qdocconf b/tools/qdoc3/test/qt-html-templates.qdocconf index b716f7c..b3bf764 100644 --- a/tools/qdoc3/test/qt-html-templates.qdocconf +++ b/tools/qdoc3/test/qt-html-templates.qdocconf @@ -21,7 +21,7 @@ HTML.postheader = " <div class=\"header\" id=\"qtdocheader\">\n" \ " </div>\n" \ " <div id=\"shortCut\">\n" \ " <ul>\n" \ - " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">Qt 4.7</a></span></li>\n" \ + " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">Qt 4.8</a></span></li>\n" \ " <li class=\"shortCut-topleft-active\"><a href=\"http://doc.qt.nokia.com\">ALL VERSIONS" \ " </a></li>\n" \ " </ul>\n" \ @@ -175,4 +175,4 @@ HTML.footer = "" \ " </form>\n" \ " </div>\n" \ " <div id=\"blurpage\">\n" \ - " </div>\n"
\ No newline at end of file + " </div>\n" diff --git a/tools/qdoc3/test/qt-html-templates_zh_CN.qdocconf b/tools/qdoc3/test/qt-html-templates_zh_CN.qdocconf index 5c4bfa9..b91530f 100644 --- a/tools/qdoc3/test/qt-html-templates_zh_CN.qdocconf +++ b/tools/qdoc3/test/qt-html-templates_zh_CN.qdocconf @@ -27,7 +27,7 @@ HTML.postheader = " <div class=\"header\" id=\"qtdocheader\">\n" \ " </div>\n" \ " <div id=\"shortCut\">\n" \ " <ul>\n" \ - " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">Qt 4.7</a></span></li>\n" \ + " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">Qt 4.8</a></span></li>\n" \ " <li class=\"shortCut-topleft-active\"><a href=\"http://qt.nokia.com/doc/\">ALL VERSIONS" \ " </a></li>\n" \ " </ul>\n" \ diff --git a/tools/qdoc3/test/qt.qdocconf b/tools/qdoc3/test/qt.qdocconf index 215e0d6..f50cb69 100644 --- a/tools/qdoc3/test/qt.qdocconf +++ b/tools/qdoc3/test/qt.qdocconf @@ -8,7 +8,7 @@ project = Qt versionsym = version = %VERSION% description = Qt Reference Documentation -url = http://qt.nokia.com/doc/4.7 +url = http://qt.nokia.com/doc/4.8 sourceencoding = UTF-8 outputencoding = UTF-8 @@ -17,7 +17,7 @@ naturallanguage = en_US qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.470 +qhp.Qt.namespace = com.trolltech.qt.480 qhp.Qt.virtualFolder = qdoc qhp.Qt.indexTitle = Qt Reference Documentation qhp.Qt.indexRoot = @@ -59,9 +59,9 @@ qhp.Qt.extraFiles = index.html \ style/style_ie8.css \ style/style.css -qhp.Qt.filterAttributes = qt 4.7.0 qtrefdoc -qhp.Qt.customFilters.Qt.name = Qt 4.7.0 -qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.0 +qhp.Qt.filterAttributes = qt 4.8.0 qtrefdoc +qhp.Qt.customFilters.Qt.name = Qt 4.8.0 +qhp.Qt.customFilters.Qt.filterAttributes = qt 4.8.0 qhp.Qt.subprojects = classes overviews examples qhp.Qt.subprojects.classes.title = Classes qhp.Qt.subprojects.classes.indexTitle = Qt's Classes diff --git a/tools/qdoc3/test/qt_zh_CN.qdocconf b/tools/qdoc3/test/qt_zh_CN.qdocconf index 5bf8171..7b49315 100644 --- a/tools/qdoc3/test/qt_zh_CN.qdocconf +++ b/tools/qdoc3/test/qt_zh_CN.qdocconf @@ -8,7 +8,7 @@ project = Qt versionsym = version = %VERSION% description = Qt Reference Documentation -url = http://qt.nokia.com/doc/zh_CN/4.7 +url = http://qt.nokia.com/doc/zh_CN/4.8 sourceencoding = UTF-8 outputencoding = UTF-8 @@ -19,15 +19,15 @@ indexes = $QTDIR/doc/html/qt.index qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.470 +qhp.Qt.namespace = com.trolltech.qt.480 qhp.Qt.virtualFolder = qdoc qhp.Qt.title = 教程 qhp.Qt.indexTitle = 教程 qhp.Qt.selectors = fake:example -qhp.Qt.filterAttributes = qt 4.7.0 qtrefdoc zh_CN -qhp.Qt.customFilters.Qt.name = Qt 4.7.0 -qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.0 +qhp.Qt.filterAttributes = qt 4.8.0 qtrefdoc zh_CN +qhp.Qt.customFilters.Qt.name = Qt 4.8.0 +qhp.Qt.customFilters.Qt.filterAttributes = qt 4.8.0 # Files not referenced in any qdoc file (last four are needed by qtdemo) # See also extraimages.HTML diff --git a/tools/qtconfig/mainwindow.cpp b/tools/qtconfig/mainwindow.cpp index 9675f99..0d6b4da 100644 --- a/tools/qtconfig/mainwindow.cpp +++ b/tools/qtconfig/mainwindow.cpp @@ -63,6 +63,7 @@ #include <QInputContext> #include <QInputContextFactory> #include <QtDebug> +#include <QPixmap> #include <stdlib.h> @@ -202,6 +203,7 @@ MainWindow::MainWindow() { modified = true; desktopThemeName = tr("Desktop Settings (Default)"); + setIcon(QPixmap(":/trolltech/qtconfig/images/appicon.png")); QStringList gstyles = QStyleFactory::keys(); gstyles.sort(); gstylecombo->addItem(desktopThemeName); diff --git a/tools/shared/qtpropertybrowser/qtvariantproperty.cpp b/tools/shared/qtpropertybrowser/qtvariantproperty.cpp index b16fac3..948fa1e 100644 --- a/tools/shared/qtpropertybrowser/qtvariantproperty.cpp +++ b/tools/shared/qtpropertybrowser/qtvariantproperty.cpp @@ -549,7 +549,7 @@ void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, con void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QKeySequence &val) { QVariant v; - qVariantSetValue(v, val); + v.setValue(val); valueChanged(property, v); } @@ -636,7 +636,7 @@ void QtVariantPropertyManagerPrivate::slotEnumIconsChanged(QtProperty *property, { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { QVariant v; - qVariantSetValue(v, enumIcons); + v.setValue(enumIcons); emit q_ptr->attributeChanged(varProp, m_enumIconsAttribute, v); } } @@ -1488,7 +1488,7 @@ QVariant QtVariantPropertyManager::attributeValue(const QtProperty *property, co return enumManager->enumNames(internProp); if (attribute == d_ptr->m_enumIconsAttribute) { QVariant v; - qVariantSetValue(v, enumManager->enumIcons(internProp)); + v.setValue(enumManager->enumIcons(internProp)); return v; } return QVariant(); @@ -1568,73 +1568,73 @@ void QtVariantPropertyManager::setValue(QtProperty *property, const QVariant &va QtAbstractPropertyManager *manager = internProp->propertyManager(); if (QtIntPropertyManager *intManager = qobject_cast<QtIntPropertyManager *>(manager)) { - intManager->setValue(internProp, qVariantValue<int>(val)); + intManager->setValue(internProp, qvariant_cast<int>(val)); return; } else if (QtDoublePropertyManager *doubleManager = qobject_cast<QtDoublePropertyManager *>(manager)) { - doubleManager->setValue(internProp, qVariantValue<double>(val)); + doubleManager->setValue(internProp, qvariant_cast<double>(val)); return; } else if (QtBoolPropertyManager *boolManager = qobject_cast<QtBoolPropertyManager *>(manager)) { - boolManager->setValue(internProp, qVariantValue<bool>(val)); + boolManager->setValue(internProp, qvariant_cast<bool>(val)); return; } else if (QtStringPropertyManager *stringManager = qobject_cast<QtStringPropertyManager *>(manager)) { - stringManager->setValue(internProp, qVariantValue<QString>(val)); + stringManager->setValue(internProp, qvariant_cast<QString>(val)); return; } else if (QtDatePropertyManager *dateManager = qobject_cast<QtDatePropertyManager *>(manager)) { - dateManager->setValue(internProp, qVariantValue<QDate>(val)); + dateManager->setValue(internProp, qvariant_cast<QDate>(val)); return; } else if (QtTimePropertyManager *timeManager = qobject_cast<QtTimePropertyManager *>(manager)) { - timeManager->setValue(internProp, qVariantValue<QTime>(val)); + timeManager->setValue(internProp, qvariant_cast<QTime>(val)); return; } else if (QtDateTimePropertyManager *dateTimeManager = qobject_cast<QtDateTimePropertyManager *>(manager)) { - dateTimeManager->setValue(internProp, qVariantValue<QDateTime>(val)); + dateTimeManager->setValue(internProp, qvariant_cast<QDateTime>(val)); return; } else if (QtKeySequencePropertyManager *keySequenceManager = qobject_cast<QtKeySequencePropertyManager *>(manager)) { - keySequenceManager->setValue(internProp, qVariantValue<QKeySequence>(val)); + keySequenceManager->setValue(internProp, qvariant_cast<QKeySequence>(val)); return; } else if (QtCharPropertyManager *charManager = qobject_cast<QtCharPropertyManager *>(manager)) { - charManager->setValue(internProp, qVariantValue<QChar>(val)); + charManager->setValue(internProp, qvariant_cast<QChar>(val)); return; } else if (QtLocalePropertyManager *localeManager = qobject_cast<QtLocalePropertyManager *>(manager)) { - localeManager->setValue(internProp, qVariantValue<QLocale>(val)); + localeManager->setValue(internProp, qvariant_cast<QLocale>(val)); return; } else if (QtPointPropertyManager *pointManager = qobject_cast<QtPointPropertyManager *>(manager)) { - pointManager->setValue(internProp, qVariantValue<QPoint>(val)); + pointManager->setValue(internProp, qvariant_cast<QPoint>(val)); return; } else if (QtPointFPropertyManager *pointFManager = qobject_cast<QtPointFPropertyManager *>(manager)) { - pointFManager->setValue(internProp, qVariantValue<QPointF>(val)); + pointFManager->setValue(internProp, qvariant_cast<QPointF>(val)); return; } else if (QtSizePropertyManager *sizeManager = qobject_cast<QtSizePropertyManager *>(manager)) { - sizeManager->setValue(internProp, qVariantValue<QSize>(val)); + sizeManager->setValue(internProp, qvariant_cast<QSize>(val)); return; } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast<QtSizeFPropertyManager *>(manager)) { - sizeFManager->setValue(internProp, qVariantValue<QSizeF>(val)); + sizeFManager->setValue(internProp, qvariant_cast<QSizeF>(val)); return; } else if (QtRectPropertyManager *rectManager = qobject_cast<QtRectPropertyManager *>(manager)) { - rectManager->setValue(internProp, qVariantValue<QRect>(val)); + rectManager->setValue(internProp, qvariant_cast<QRect>(val)); return; } else if (QtRectFPropertyManager *rectFManager = qobject_cast<QtRectFPropertyManager *>(manager)) { - rectFManager->setValue(internProp, qVariantValue<QRectF>(val)); + rectFManager->setValue(internProp, qvariant_cast<QRectF>(val)); return; } else if (QtColorPropertyManager *colorManager = qobject_cast<QtColorPropertyManager *>(manager)) { - colorManager->setValue(internProp, qVariantValue<QColor>(val)); + colorManager->setValue(internProp, qvariant_cast<QColor>(val)); return; } else if (QtEnumPropertyManager *enumManager = qobject_cast<QtEnumPropertyManager *>(manager)) { - enumManager->setValue(internProp, qVariantValue<int>(val)); + enumManager->setValue(internProp, qvariant_cast<int>(val)); return; } else if (QtSizePolicyPropertyManager *sizePolicyManager = qobject_cast<QtSizePolicyPropertyManager *>(manager)) { - sizePolicyManager->setValue(internProp, qVariantValue<QSizePolicy>(val)); + sizePolicyManager->setValue(internProp, qvariant_cast<QSizePolicy>(val)); return; } else if (QtFontPropertyManager *fontManager = qobject_cast<QtFontPropertyManager *>(manager)) { - fontManager->setValue(internProp, qVariantValue<QFont>(val)); + fontManager->setValue(internProp, qvariant_cast<QFont>(val)); return; #ifndef QT_NO_CURSOR } else if (QtCursorPropertyManager *cursorManager = qobject_cast<QtCursorPropertyManager *>(manager)) { - cursorManager->setValue(internProp, qVariantValue<QCursor>(val)); + cursorManager->setValue(internProp, qvariant_cast<QCursor>(val)); return; #endif } else if (QtFlagPropertyManager *flagManager = qobject_cast<QtFlagPropertyManager *>(manager)) { - flagManager->setValue(internProp, qVariantValue<int>(val)); + flagManager->setValue(internProp, qvariant_cast<int>(val)); return; } } @@ -1672,69 +1672,69 @@ void QtVariantPropertyManager::setAttribute(QtProperty *property, QtAbstractPropertyManager *manager = internProp->propertyManager(); if (QtIntPropertyManager *intManager = qobject_cast<QtIntPropertyManager *>(manager)) { if (attribute == d_ptr->m_maximumAttribute) - intManager->setMaximum(internProp, qVariantValue<int>(value)); + intManager->setMaximum(internProp, qvariant_cast<int>(value)); else if (attribute == d_ptr->m_minimumAttribute) - intManager->setMinimum(internProp, qVariantValue<int>(value)); + intManager->setMinimum(internProp, qvariant_cast<int>(value)); else if (attribute == d_ptr->m_singleStepAttribute) - intManager->setSingleStep(internProp, qVariantValue<int>(value)); + intManager->setSingleStep(internProp, qvariant_cast<int>(value)); return; } else if (QtDoublePropertyManager *doubleManager = qobject_cast<QtDoublePropertyManager *>(manager)) { if (attribute == d_ptr->m_maximumAttribute) - doubleManager->setMaximum(internProp, qVariantValue<double>(value)); + doubleManager->setMaximum(internProp, qvariant_cast<double>(value)); if (attribute == d_ptr->m_minimumAttribute) - doubleManager->setMinimum(internProp, qVariantValue<double>(value)); + doubleManager->setMinimum(internProp, qvariant_cast<double>(value)); if (attribute == d_ptr->m_singleStepAttribute) - doubleManager->setSingleStep(internProp, qVariantValue<double>(value)); + doubleManager->setSingleStep(internProp, qvariant_cast<double>(value)); if (attribute == d_ptr->m_decimalsAttribute) - doubleManager->setDecimals(internProp, qVariantValue<int>(value)); + doubleManager->setDecimals(internProp, qvariant_cast<int>(value)); return; } else if (QtStringPropertyManager *stringManager = qobject_cast<QtStringPropertyManager *>(manager)) { if (attribute == d_ptr->m_regExpAttribute) - stringManager->setRegExp(internProp, qVariantValue<QRegExp>(value)); + stringManager->setRegExp(internProp, qvariant_cast<QRegExp>(value)); return; } else if (QtDatePropertyManager *dateManager = qobject_cast<QtDatePropertyManager *>(manager)) { if (attribute == d_ptr->m_maximumAttribute) - dateManager->setMaximum(internProp, qVariantValue<QDate>(value)); + dateManager->setMaximum(internProp, qvariant_cast<QDate>(value)); if (attribute == d_ptr->m_minimumAttribute) - dateManager->setMinimum(internProp, qVariantValue<QDate>(value)); + dateManager->setMinimum(internProp, qvariant_cast<QDate>(value)); return; } else if (QtPointFPropertyManager *pointFManager = qobject_cast<QtPointFPropertyManager *>(manager)) { if (attribute == d_ptr->m_decimalsAttribute) - pointFManager->setDecimals(internProp, qVariantValue<int>(value)); + pointFManager->setDecimals(internProp, qvariant_cast<int>(value)); return; } else if (QtSizePropertyManager *sizeManager = qobject_cast<QtSizePropertyManager *>(manager)) { if (attribute == d_ptr->m_maximumAttribute) - sizeManager->setMaximum(internProp, qVariantValue<QSize>(value)); + sizeManager->setMaximum(internProp, qvariant_cast<QSize>(value)); if (attribute == d_ptr->m_minimumAttribute) - sizeManager->setMinimum(internProp, qVariantValue<QSize>(value)); + sizeManager->setMinimum(internProp, qvariant_cast<QSize>(value)); return; } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast<QtSizeFPropertyManager *>(manager)) { if (attribute == d_ptr->m_maximumAttribute) - sizeFManager->setMaximum(internProp, qVariantValue<QSizeF>(value)); + sizeFManager->setMaximum(internProp, qvariant_cast<QSizeF>(value)); if (attribute == d_ptr->m_minimumAttribute) - sizeFManager->setMinimum(internProp, qVariantValue<QSizeF>(value)); + sizeFManager->setMinimum(internProp, qvariant_cast<QSizeF>(value)); if (attribute == d_ptr->m_decimalsAttribute) - sizeFManager->setDecimals(internProp, qVariantValue<int>(value)); + sizeFManager->setDecimals(internProp, qvariant_cast<int>(value)); return; } else if (QtRectPropertyManager *rectManager = qobject_cast<QtRectPropertyManager *>(manager)) { if (attribute == d_ptr->m_constraintAttribute) - rectManager->setConstraint(internProp, qVariantValue<QRect>(value)); + rectManager->setConstraint(internProp, qvariant_cast<QRect>(value)); return; } else if (QtRectFPropertyManager *rectFManager = qobject_cast<QtRectFPropertyManager *>(manager)) { if (attribute == d_ptr->m_constraintAttribute) - rectFManager->setConstraint(internProp, qVariantValue<QRectF>(value)); + rectFManager->setConstraint(internProp, qvariant_cast<QRectF>(value)); if (attribute == d_ptr->m_decimalsAttribute) - rectFManager->setDecimals(internProp, qVariantValue<int>(value)); + rectFManager->setDecimals(internProp, qvariant_cast<int>(value)); return; } else if (QtEnumPropertyManager *enumManager = qobject_cast<QtEnumPropertyManager *>(manager)) { if (attribute == d_ptr->m_enumNamesAttribute) - enumManager->setEnumNames(internProp, qVariantValue<QStringList>(value)); + enumManager->setEnumNames(internProp, qvariant_cast<QStringList>(value)); if (attribute == d_ptr->m_enumIconsAttribute) - enumManager->setEnumIcons(internProp, qVariantValue<QtIconMap>(value)); + enumManager->setEnumIcons(internProp, qvariant_cast<QtIconMap>(value)); return; } else if (QtFlagPropertyManager *flagManager = qobject_cast<QtFlagPropertyManager *>(manager)) { if (attribute == d_ptr->m_flagNamesAttribute) - flagManager->setFlagNames(internProp, qVariantValue<QStringList>(value)); + flagManager->setFlagNames(internProp, qvariant_cast<QStringList>(value)); return; } } @@ -1997,87 +1997,87 @@ QtVariantEditorFactory::~QtVariantEditorFactory() */ void QtVariantEditorFactory::connectPropertyManager(QtVariantPropertyManager *manager) { - QList<QtIntPropertyManager *> intPropertyManagers = qFindChildren<QtIntPropertyManager *>(manager); + QList<QtIntPropertyManager *> intPropertyManagers = manager->findChildren<QtIntPropertyManager *>(); QListIterator<QtIntPropertyManager *> itInt(intPropertyManagers); while (itInt.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itInt.next()); - QList<QtDoublePropertyManager *> doublePropertyManagers = qFindChildren<QtDoublePropertyManager *>(manager); + QList<QtDoublePropertyManager *> doublePropertyManagers = manager->findChildren<QtDoublePropertyManager *>(); QListIterator<QtDoublePropertyManager *> itDouble(doublePropertyManagers); while (itDouble.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itDouble.next()); - QList<QtBoolPropertyManager *> boolPropertyManagers = qFindChildren<QtBoolPropertyManager *>(manager); + QList<QtBoolPropertyManager *> boolPropertyManagers = manager->findChildren<QtBoolPropertyManager *>(); QListIterator<QtBoolPropertyManager *> itBool(boolPropertyManagers); while (itBool.hasNext()) d_ptr->m_checkBoxFactory->addPropertyManager(itBool.next()); - QList<QtStringPropertyManager *> stringPropertyManagers = qFindChildren<QtStringPropertyManager *>(manager); + QList<QtStringPropertyManager *> stringPropertyManagers = manager->findChildren<QtStringPropertyManager *>(); QListIterator<QtStringPropertyManager *> itString(stringPropertyManagers); while (itString.hasNext()) d_ptr->m_lineEditFactory->addPropertyManager(itString.next()); - QList<QtDatePropertyManager *> datePropertyManagers = qFindChildren<QtDatePropertyManager *>(manager); + QList<QtDatePropertyManager *> datePropertyManagers = manager->findChildren<QtDatePropertyManager *>(); QListIterator<QtDatePropertyManager *> itDate(datePropertyManagers); while (itDate.hasNext()) d_ptr->m_dateEditFactory->addPropertyManager(itDate.next()); - QList<QtTimePropertyManager *> timePropertyManagers = qFindChildren<QtTimePropertyManager *>(manager); + QList<QtTimePropertyManager *> timePropertyManagers = manager->findChildren<QtTimePropertyManager *>(); QListIterator<QtTimePropertyManager *> itTime(timePropertyManagers); while (itTime.hasNext()) d_ptr->m_timeEditFactory->addPropertyManager(itTime.next()); - QList<QtDateTimePropertyManager *> dateTimePropertyManagers = qFindChildren<QtDateTimePropertyManager *>(manager); + QList<QtDateTimePropertyManager *> dateTimePropertyManagers = manager->findChildren<QtDateTimePropertyManager *>(); QListIterator<QtDateTimePropertyManager *> itDateTime(dateTimePropertyManagers); while (itDateTime.hasNext()) d_ptr->m_dateTimeEditFactory->addPropertyManager(itDateTime.next()); - QList<QtKeySequencePropertyManager *> keySequencePropertyManagers = qFindChildren<QtKeySequencePropertyManager *>(manager); + QList<QtKeySequencePropertyManager *> keySequencePropertyManagers = manager->findChildren<QtKeySequencePropertyManager *>(); QListIterator<QtKeySequencePropertyManager *> itKeySequence(keySequencePropertyManagers); while (itKeySequence.hasNext()) d_ptr->m_keySequenceEditorFactory->addPropertyManager(itKeySequence.next()); - QList<QtCharPropertyManager *> charPropertyManagers = qFindChildren<QtCharPropertyManager *>(manager); + QList<QtCharPropertyManager *> charPropertyManagers = manager->findChildren<QtCharPropertyManager *>(); QListIterator<QtCharPropertyManager *> itChar(charPropertyManagers); while (itChar.hasNext()) d_ptr->m_charEditorFactory->addPropertyManager(itChar.next()); - QList<QtLocalePropertyManager *> localePropertyManagers = qFindChildren<QtLocalePropertyManager *>(manager); + QList<QtLocalePropertyManager *> localePropertyManagers = manager->findChildren<QtLocalePropertyManager *>(); QListIterator<QtLocalePropertyManager *> itLocale(localePropertyManagers); while (itLocale.hasNext()) d_ptr->m_comboBoxFactory->addPropertyManager(itLocale.next()->subEnumPropertyManager()); - QList<QtPointPropertyManager *> pointPropertyManagers = qFindChildren<QtPointPropertyManager *>(manager); + QList<QtPointPropertyManager *> pointPropertyManagers = manager->findChildren<QtPointPropertyManager *>(); QListIterator<QtPointPropertyManager *> itPoint(pointPropertyManagers); while (itPoint.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itPoint.next()->subIntPropertyManager()); - QList<QtPointFPropertyManager *> pointFPropertyManagers = qFindChildren<QtPointFPropertyManager *>(manager); + QList<QtPointFPropertyManager *> pointFPropertyManagers = manager->findChildren<QtPointFPropertyManager *>(); QListIterator<QtPointFPropertyManager *> itPointF(pointFPropertyManagers); while (itPointF.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itPointF.next()->subDoublePropertyManager()); - QList<QtSizePropertyManager *> sizePropertyManagers = qFindChildren<QtSizePropertyManager *>(manager); + QList<QtSizePropertyManager *> sizePropertyManagers = manager->findChildren<QtSizePropertyManager *>(); QListIterator<QtSizePropertyManager *> itSize(sizePropertyManagers); while (itSize.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itSize.next()->subIntPropertyManager()); - QList<QtSizeFPropertyManager *> sizeFPropertyManagers = qFindChildren<QtSizeFPropertyManager *>(manager); + QList<QtSizeFPropertyManager *> sizeFPropertyManagers = manager->findChildren<QtSizeFPropertyManager *>(); QListIterator<QtSizeFPropertyManager *> itSizeF(sizeFPropertyManagers); while (itSizeF.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itSizeF.next()->subDoublePropertyManager()); - QList<QtRectPropertyManager *> rectPropertyManagers = qFindChildren<QtRectPropertyManager *>(manager); + QList<QtRectPropertyManager *> rectPropertyManagers = manager->findChildren<QtRectPropertyManager *>(); QListIterator<QtRectPropertyManager *> itRect(rectPropertyManagers); while (itRect.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itRect.next()->subIntPropertyManager()); - QList<QtRectFPropertyManager *> rectFPropertyManagers = qFindChildren<QtRectFPropertyManager *>(manager); + QList<QtRectFPropertyManager *> rectFPropertyManagers = manager->findChildren<QtRectFPropertyManager *>(); QListIterator<QtRectFPropertyManager *> itRectF(rectFPropertyManagers); while (itRectF.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itRectF.next()->subDoublePropertyManager()); - QList<QtColorPropertyManager *> colorPropertyManagers = qFindChildren<QtColorPropertyManager *>(manager); + QList<QtColorPropertyManager *> colorPropertyManagers = manager->findChildren<QtColorPropertyManager *>(); QListIterator<QtColorPropertyManager *> itColor(colorPropertyManagers); while (itColor.hasNext()) { QtColorPropertyManager *manager = itColor.next(); @@ -2085,12 +2085,12 @@ void QtVariantEditorFactory::connectPropertyManager(QtVariantPropertyManager *ma d_ptr->m_spinBoxFactory->addPropertyManager(manager->subIntPropertyManager()); } - QList<QtEnumPropertyManager *> enumPropertyManagers = qFindChildren<QtEnumPropertyManager *>(manager); + QList<QtEnumPropertyManager *> enumPropertyManagers = manager->findChildren<QtEnumPropertyManager *>(); QListIterator<QtEnumPropertyManager *> itEnum(enumPropertyManagers); while (itEnum.hasNext()) d_ptr->m_comboBoxFactory->addPropertyManager(itEnum.next()); - QList<QtSizePolicyPropertyManager *> sizePolicyPropertyManagers = qFindChildren<QtSizePolicyPropertyManager *>(manager); + QList<QtSizePolicyPropertyManager *> sizePolicyPropertyManagers = manager->findChildren<QtSizePolicyPropertyManager *>(); QListIterator<QtSizePolicyPropertyManager *> itSizePolicy(sizePolicyPropertyManagers); while (itSizePolicy.hasNext()) { QtSizePolicyPropertyManager *manager = itSizePolicy.next(); @@ -2098,7 +2098,7 @@ void QtVariantEditorFactory::connectPropertyManager(QtVariantPropertyManager *ma d_ptr->m_comboBoxFactory->addPropertyManager(manager->subEnumPropertyManager()); } - QList<QtFontPropertyManager *> fontPropertyManagers = qFindChildren<QtFontPropertyManager *>(manager); + QList<QtFontPropertyManager *> fontPropertyManagers = manager->findChildren<QtFontPropertyManager *>(); QListIterator<QtFontPropertyManager *> itFont(fontPropertyManagers); while (itFont.hasNext()) { QtFontPropertyManager *manager = itFont.next(); @@ -2108,12 +2108,12 @@ void QtVariantEditorFactory::connectPropertyManager(QtVariantPropertyManager *ma d_ptr->m_checkBoxFactory->addPropertyManager(manager->subBoolPropertyManager()); } - QList<QtCursorPropertyManager *> cursorPropertyManagers = qFindChildren<QtCursorPropertyManager *>(manager); + QList<QtCursorPropertyManager *> cursorPropertyManagers = manager->findChildren<QtCursorPropertyManager *>(); QListIterator<QtCursorPropertyManager *> itCursor(cursorPropertyManagers); while (itCursor.hasNext()) d_ptr->m_cursorEditorFactory->addPropertyManager(itCursor.next()); - QList<QtFlagPropertyManager *> flagPropertyManagers = qFindChildren<QtFlagPropertyManager *>(manager); + QList<QtFlagPropertyManager *> flagPropertyManagers = manager->findChildren<QtFlagPropertyManager *>(); QListIterator<QtFlagPropertyManager *> itFlag(flagPropertyManagers); while (itFlag.hasNext()) d_ptr->m_checkBoxFactory->addPropertyManager(itFlag.next()->subBoolPropertyManager()); @@ -2141,87 +2141,87 @@ QWidget *QtVariantEditorFactory::createEditor(QtVariantPropertyManager *manager, */ void QtVariantEditorFactory::disconnectPropertyManager(QtVariantPropertyManager *manager) { - QList<QtIntPropertyManager *> intPropertyManagers = qFindChildren<QtIntPropertyManager *>(manager); + QList<QtIntPropertyManager *> intPropertyManagers = manager->findChildren<QtIntPropertyManager *>(); QListIterator<QtIntPropertyManager *> itInt(intPropertyManagers); while (itInt.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itInt.next()); - QList<QtDoublePropertyManager *> doublePropertyManagers = qFindChildren<QtDoublePropertyManager *>(manager); + QList<QtDoublePropertyManager *> doublePropertyManagers = manager->findChildren<QtDoublePropertyManager *>(); QListIterator<QtDoublePropertyManager *> itDouble(doublePropertyManagers); while (itDouble.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itDouble.next()); - QList<QtBoolPropertyManager *> boolPropertyManagers = qFindChildren<QtBoolPropertyManager *>(manager); + QList<QtBoolPropertyManager *> boolPropertyManagers = manager->findChildren<QtBoolPropertyManager *>(); QListIterator<QtBoolPropertyManager *> itBool(boolPropertyManagers); while (itBool.hasNext()) d_ptr->m_checkBoxFactory->removePropertyManager(itBool.next()); - QList<QtStringPropertyManager *> stringPropertyManagers = qFindChildren<QtStringPropertyManager *>(manager); + QList<QtStringPropertyManager *> stringPropertyManagers = manager->findChildren<QtStringPropertyManager *>(); QListIterator<QtStringPropertyManager *> itString(stringPropertyManagers); while (itString.hasNext()) d_ptr->m_lineEditFactory->removePropertyManager(itString.next()); - QList<QtDatePropertyManager *> datePropertyManagers = qFindChildren<QtDatePropertyManager *>(manager); + QList<QtDatePropertyManager *> datePropertyManagers = manager->findChildren<QtDatePropertyManager *>(); QListIterator<QtDatePropertyManager *> itDate(datePropertyManagers); while (itDate.hasNext()) d_ptr->m_dateEditFactory->removePropertyManager(itDate.next()); - QList<QtTimePropertyManager *> timePropertyManagers = qFindChildren<QtTimePropertyManager *>(manager); + QList<QtTimePropertyManager *> timePropertyManagers = manager->findChildren<QtTimePropertyManager *>(); QListIterator<QtTimePropertyManager *> itTime(timePropertyManagers); while (itTime.hasNext()) d_ptr->m_timeEditFactory->removePropertyManager(itTime.next()); - QList<QtDateTimePropertyManager *> dateTimePropertyManagers = qFindChildren<QtDateTimePropertyManager *>(manager); + QList<QtDateTimePropertyManager *> dateTimePropertyManagers = manager->findChildren<QtDateTimePropertyManager *>(); QListIterator<QtDateTimePropertyManager *> itDateTime(dateTimePropertyManagers); while (itDateTime.hasNext()) d_ptr->m_dateTimeEditFactory->removePropertyManager(itDateTime.next()); - QList<QtKeySequencePropertyManager *> keySequencePropertyManagers = qFindChildren<QtKeySequencePropertyManager *>(manager); + QList<QtKeySequencePropertyManager *> keySequencePropertyManagers = manager->findChildren<QtKeySequencePropertyManager *>(); QListIterator<QtKeySequencePropertyManager *> itKeySequence(keySequencePropertyManagers); while (itKeySequence.hasNext()) d_ptr->m_keySequenceEditorFactory->removePropertyManager(itKeySequence.next()); - QList<QtCharPropertyManager *> charPropertyManagers = qFindChildren<QtCharPropertyManager *>(manager); + QList<QtCharPropertyManager *> charPropertyManagers = manager->findChildren<QtCharPropertyManager *>(); QListIterator<QtCharPropertyManager *> itChar(charPropertyManagers); while (itChar.hasNext()) d_ptr->m_charEditorFactory->removePropertyManager(itChar.next()); - QList<QtLocalePropertyManager *> localePropertyManagers = qFindChildren<QtLocalePropertyManager *>(manager); + QList<QtLocalePropertyManager *> localePropertyManagers = manager->findChildren<QtLocalePropertyManager *>(); QListIterator<QtLocalePropertyManager *> itLocale(localePropertyManagers); while (itLocale.hasNext()) d_ptr->m_comboBoxFactory->removePropertyManager(itLocale.next()->subEnumPropertyManager()); - QList<QtPointPropertyManager *> pointPropertyManagers = qFindChildren<QtPointPropertyManager *>(manager); + QList<QtPointPropertyManager *> pointPropertyManagers = manager->findChildren<QtPointPropertyManager *>(); QListIterator<QtPointPropertyManager *> itPoint(pointPropertyManagers); while (itPoint.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itPoint.next()->subIntPropertyManager()); - QList<QtPointFPropertyManager *> pointFPropertyManagers = qFindChildren<QtPointFPropertyManager *>(manager); + QList<QtPointFPropertyManager *> pointFPropertyManagers = manager->findChildren<QtPointFPropertyManager *>(); QListIterator<QtPointFPropertyManager *> itPointF(pointFPropertyManagers); while (itPointF.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itPointF.next()->subDoublePropertyManager()); - QList<QtSizePropertyManager *> sizePropertyManagers = qFindChildren<QtSizePropertyManager *>(manager); + QList<QtSizePropertyManager *> sizePropertyManagers = manager->findChildren<QtSizePropertyManager *>(); QListIterator<QtSizePropertyManager *> itSize(sizePropertyManagers); while (itSize.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itSize.next()->subIntPropertyManager()); - QList<QtSizeFPropertyManager *> sizeFPropertyManagers = qFindChildren<QtSizeFPropertyManager *>(manager); + QList<QtSizeFPropertyManager *> sizeFPropertyManagers = manager->findChildren<QtSizeFPropertyManager *>(); QListIterator<QtSizeFPropertyManager *> itSizeF(sizeFPropertyManagers); while (itSizeF.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itSizeF.next()->subDoublePropertyManager()); - QList<QtRectPropertyManager *> rectPropertyManagers = qFindChildren<QtRectPropertyManager *>(manager); + QList<QtRectPropertyManager *> rectPropertyManagers = manager->findChildren<QtRectPropertyManager *>(); QListIterator<QtRectPropertyManager *> itRect(rectPropertyManagers); while (itRect.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itRect.next()->subIntPropertyManager()); - QList<QtRectFPropertyManager *> rectFPropertyManagers = qFindChildren<QtRectFPropertyManager *>(manager); + QList<QtRectFPropertyManager *> rectFPropertyManagers = manager->findChildren<QtRectFPropertyManager *>(); QListIterator<QtRectFPropertyManager *> itRectF(rectFPropertyManagers); while (itRectF.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itRectF.next()->subDoublePropertyManager()); - QList<QtColorPropertyManager *> colorPropertyManagers = qFindChildren<QtColorPropertyManager *>(manager); + QList<QtColorPropertyManager *> colorPropertyManagers = manager->findChildren<QtColorPropertyManager *>(); QListIterator<QtColorPropertyManager *> itColor(colorPropertyManagers); while (itColor.hasNext()) { QtColorPropertyManager *manager = itColor.next(); @@ -2229,12 +2229,12 @@ void QtVariantEditorFactory::disconnectPropertyManager(QtVariantPropertyManager d_ptr->m_spinBoxFactory->removePropertyManager(manager->subIntPropertyManager()); } - QList<QtEnumPropertyManager *> enumPropertyManagers = qFindChildren<QtEnumPropertyManager *>(manager); + QList<QtEnumPropertyManager *> enumPropertyManagers = manager->findChildren<QtEnumPropertyManager *>(); QListIterator<QtEnumPropertyManager *> itEnum(enumPropertyManagers); while (itEnum.hasNext()) d_ptr->m_comboBoxFactory->removePropertyManager(itEnum.next()); - QList<QtSizePolicyPropertyManager *> sizePolicyPropertyManagers = qFindChildren<QtSizePolicyPropertyManager *>(manager); + QList<QtSizePolicyPropertyManager *> sizePolicyPropertyManagers = manager->findChildren<QtSizePolicyPropertyManager *>(); QListIterator<QtSizePolicyPropertyManager *> itSizePolicy(sizePolicyPropertyManagers); while (itSizePolicy.hasNext()) { QtSizePolicyPropertyManager *manager = itSizePolicy.next(); @@ -2242,7 +2242,7 @@ void QtVariantEditorFactory::disconnectPropertyManager(QtVariantPropertyManager d_ptr->m_comboBoxFactory->removePropertyManager(manager->subEnumPropertyManager()); } - QList<QtFontPropertyManager *> fontPropertyManagers = qFindChildren<QtFontPropertyManager *>(manager); + QList<QtFontPropertyManager *> fontPropertyManagers = manager->findChildren<QtFontPropertyManager *>(); QListIterator<QtFontPropertyManager *> itFont(fontPropertyManagers); while (itFont.hasNext()) { QtFontPropertyManager *manager = itFont.next(); @@ -2252,12 +2252,12 @@ void QtVariantEditorFactory::disconnectPropertyManager(QtVariantPropertyManager d_ptr->m_checkBoxFactory->removePropertyManager(manager->subBoolPropertyManager()); } - QList<QtCursorPropertyManager *> cursorPropertyManagers = qFindChildren<QtCursorPropertyManager *>(manager); + QList<QtCursorPropertyManager *> cursorPropertyManagers = manager->findChildren<QtCursorPropertyManager *>(); QListIterator<QtCursorPropertyManager *> itCursor(cursorPropertyManagers); while (itCursor.hasNext()) d_ptr->m_cursorEditorFactory->removePropertyManager(itCursor.next()); - QList<QtFlagPropertyManager *> flagPropertyManagers = qFindChildren<QtFlagPropertyManager *>(manager); + QList<QtFlagPropertyManager *> flagPropertyManagers = manager->findChildren<QtFlagPropertyManager *>(); QListIterator<QtFlagPropertyManager *> itFlag(flagPropertyManagers); while (itFlag.hasNext()) d_ptr->m_checkBoxFactory->removePropertyManager(itFlag.next()->subBoolPropertyManager()); diff --git a/tools/xmlpatterns/main.cpp b/tools/xmlpatterns/main.cpp index b0e9e67..8479de7 100644 --- a/tools/xmlpatterns/main.cpp +++ b/tools/xmlpatterns/main.cpp @@ -145,14 +145,14 @@ protected: } /* The value.isNull() check ensures we can bind variables whose value is an empty string. */ - return qVariantFromValue(Parameter(name, value.isNull() ? QString(QLatin1String("")) : value )); + return QVariant::fromValue(Parameter(name, value.isNull() ? QString(QLatin1String("")) : value )); } else if(arg.name() == QLatin1String("output")) { QFile *const f = new QFile(input); if(f->open(QIODevice::WriteOnly)) - return qVariantFromValue(static_cast<QIODevice *>(f)); + return QVariant::fromValue(static_cast<QIODevice *>(f)); else { message(QXmlPatternistCLI::tr("Failed to open file %1 for writing: %2").arg(f->fileName(), f->errorString())); @@ -168,7 +168,7 @@ protected: return QVariant(); } else - return qVariantFromValue(name); + return QVariant::fromValue(name); } else return QApplicationArgumentParser::convertToValue(arg, input); @@ -200,7 +200,7 @@ protected: out->open(stdout, QIODevice::WriteOnly); #endif - return qVariantFromValue(static_cast<QIODevice *>(out)); + return QVariant::fromValue(static_cast<QIODevice *>(out)); } else return QApplicationArgumentParser::defaultValue(argument); @@ -317,7 +317,7 @@ int main(int argc, char **argv) QXmlQuery query(lang, namePool); - query.setInitialTemplateName(qVariantValue<QXmlName>(parser.value(initialTemplateName))); + query.setInitialTemplateName(qvariant_cast<QXmlName>(parser.value(initialTemplateName))); /* Bind external variables. */ { @@ -329,7 +329,7 @@ int main(int argc, char **argv) for(int i = 0; i < len; ++i) { - const Parameter p(qVariantValue<Parameter>(parameters.at(i))); + const Parameter p(qvariant_cast<Parameter>(parameters.at(i))); if(usedParameters.contains(p.first)) { @@ -359,7 +359,7 @@ int main(int argc, char **argv) query.setQuery(effectiveURI); - const QPatternist::AutoPtr<QIODevice> outDevice(qVariantValue<QIODevice *>(parser.value(output))); + const QPatternist::AutoPtr<QIODevice> outDevice(qvariant_cast<QIODevice *>(parser.value(output))); Q_ASSERT(outDevice); Q_ASSERT(outDevice->isWritable()); diff --git a/translations/translations.pro b/translations/translations.pro index cdaf04a..14c1177 100644 --- a/translations/translations.pro +++ b/translations/translations.pro @@ -6,7 +6,7 @@ contains(TEMPLATE_PREFIX, vc):vcproj = 1 TEMPLATE = app TARGET = qm_phony_target -CONFIG -= qt separate_debug_info sis_targets +CONFIG -= qt separate_debug_info gdb_dwarf_index sis_targets CONFIG += no_icon QT = LIBS = |