summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java15
-rw-r--r--src/android/java/version.xml2
-rw-r--r--src/corelib/animation/qvariantanimation.cpp3
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp31
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineoption.cpp7
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser.cpp79
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser_main.cpp83
-rw-r--r--src/corelib/doc/src/threads.qdoc5
-rw-r--r--src/corelib/global/qcompilerdetection.h5
-rw-r--r--src/corelib/global/qglobal.cpp2
-rw-r--r--src/corelib/global/qglobal.h2
-rw-r--r--src/corelib/global/qlogging.cpp50
-rw-r--r--src/corelib/io/qdir.cpp4
-rw-r--r--src/corelib/io/qsettings.cpp3
-rw-r--r--src/corelib/io/qstandardpaths_unix.cpp11
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp2
-rw-r--r--src/corelib/kernel/qcorecmdlineargs_p.h7
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp5
-rw-r--r--src/corelib/kernel/qmetatype.cpp65
-rw-r--r--src/corelib/kernel/qmetatype.h102
-rw-r--r--src/corelib/kernel/qobjectdefs.h2
-rw-r--r--src/corelib/kernel/qsharedmemory_android.cpp4
-rw-r--r--src/corelib/kernel/qsystemsemaphore_android.cpp3
-rw-r--r--src/corelib/tools/qcommandlineoption.cpp25
-rw-r--r--src/corelib/tools/qcommandlineparser.cpp92
-rw-r--r--src/corelib/tools/qdatetime.cpp1716
-rw-r--r--src/corelib/tools/qdatetime_p.h208
-rw-r--r--src/corelib/tools/qdatetimeparser.cpp1769
-rw-r--r--src/corelib/tools/qdatetimeparser_p.h272
-rw-r--r--src/corelib/tools/qlist.h7
-rw-r--r--src/corelib/tools/qlocale.cpp1
-rw-r--r--src/corelib/tools/qmap.cpp42
-rw-r--r--src/corelib/tools/qmap.h62
-rw-r--r--src/corelib/tools/qstringlist.cpp12
-rw-r--r--src/corelib/tools/tools.pri2
-rw-r--r--src/dbus/qdbusmetaobject.cpp2
-rw-r--r--src/gui/kernel/qplatformtheme.h4
-rw-r--r--src/gui/opengl/qopenglfunctions_1_0.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_1_1.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_1_2.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_1_3.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_1_4.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_1_5.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_2_0.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_2_1.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_3_0.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_3_1.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_3_2_compatibility.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_3_2_core.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_3_3_compatibility.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_3_3_core.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_4_0_compatibility.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_4_0_core.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_4_1_compatibility.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_4_1_core.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_4_2_compatibility.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_4_2_core.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_4_3_compatibility.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_4_3_core.cpp6
-rw-r--r--src/gui/opengl/qopenglfunctions_es2.cpp4
-rw-r--r--src/gui/painting/qpainter.cpp12
-rw-r--r--src/gui/text/qfontdatabase.cpp3
-rw-r--r--src/gui/text/qfontdatabase.h4
-rw-r--r--src/gui/text/qfontdatabase_qpa.cpp5
-rw-r--r--src/gui/text/qfontengine.cpp39
-rw-r--r--src/gui/text/qfontengine_ft.cpp3
-rw-r--r--src/gui/text/qfontengine_ft_p.h4
-rw-r--r--src/gui/text/qfontengine_p.h11
-rw-r--r--src/gui/text/qfontengine_qpa.cpp5
-rw-r--r--src/gui/text/qharfbuzzng.cpp730
-rw-r--r--src/gui/text/qharfbuzzng_p.h85
-rw-r--r--src/gui/text/qtextengine.cpp309
-rw-r--r--src/gui/text/qtextengine_p.h5
-rw-r--r--src/gui/text/text.pri9
-rw-r--r--src/network/kernel/qdnslookup_android.cpp3
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp2
-rw-r--r--src/opengl/qgl.cpp8
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h1
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h1
-rw-r--r--src/plugins/platforms/android/src/androidjniinput.cpp15
-rw-r--r--src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp1
-rw-r--r--src/plugins/platforms/android/src/qandroidplatformintegration.cpp7
-rw-r--r--src/plugins/platforms/android/src/qandroidplatformintegration.h2
-rw-r--r--src/plugins/platforms/android/src/qandroidplatformtheme.cpp71
-rw-r--r--src/plugins/platforms/android/src/qandroidplatformtheme.h8
-rw-r--r--src/plugins/platforms/kms/qkmsscreen.cpp2
-rw-r--r--src/plugins/platforms/windows/array.h5
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp62
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.h7
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp68
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.cpp11
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.h10
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h3
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp11
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp12
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp66
-rw-r--r--src/printsupport/dialogs/qprintdialog_unix.cpp21
-rw-r--r--src/printsupport/kernel/qcups.cpp92
-rw-r--r--src/printsupport/kernel/qcups_p.h23
-rw-r--r--src/printsupport/kernel/qprintengine_win.cpp10
-rw-r--r--src/printsupport/widgets/qcupsjobwidget.cpp171
-rw-r--r--src/printsupport/widgets/qcupsjobwidget.ui108
-rw-r--r--src/printsupport/widgets/qcupsjobwidget_p.h104
-rw-r--r--src/printsupport/widgets/widgets.pri9
-rw-r--r--src/tools/moc/main.cpp420
-rw-r--r--src/tools/moc/moc.cpp2
-rw-r--r--src/tools/moc/preprocessor.cpp7
-rw-r--r--src/tools/moc/preprocessor.h1
-rw-r--r--src/tools/qdoc/generator.cpp63
-rw-r--r--src/tools/qdoc/qdocdatabase.cpp14
-rw-r--r--src/tools/qdoc/qdocindexfiles.cpp3
-rw-r--r--src/widgets/kernel/qapplication.cpp3
-rw-r--r--src/widgets/kernel/qapplication_qpa.cpp10
-rw-r--r--src/widgets/kernel/qwidget.cpp33
-rw-r--r--src/widgets/kernel/qwidget.h9
-rw-r--r--src/widgets/styles/qandroidstyle.cpp353
-rw-r--r--src/widgets/styles/qandroidstyle_p.h22
-rw-r--r--src/widgets/styles/qcommonstyle_p.h12
-rw-r--r--src/widgets/widgets/qabstractspinbox.cpp2
-rw-r--r--src/widgets/widgets/qdatetimeedit_p.h2
124 files changed, 5160 insertions, 2794 deletions
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
index fd0c6b14e3..83ed1582bf 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
@@ -82,7 +82,7 @@ import android.view.ActionMode.Callback;
public class QtActivity extends Activity
{
private final static int MINISTRO_INSTALL_REQUEST_CODE = 0xf3ee; // request code used to know when Ministro instalation is finished
- private static final int MINISTRO_API_LEVEL = 3; // Ministro api level (check IMinistro.aidl file)
+ private static final int MINISTRO_API_LEVEL = 4; // Ministro api level (check IMinistro.aidl file)
private static final int NECESSITAS_API_LEVEL = 2; // Necessitas api level used by platform plugin
private static final int QT_VERSION = 0x050100; // This app requires at least Qt version 5.1.0
@@ -119,7 +119,7 @@ public class QtActivity extends Activity
// and must be separated with "\t"
// e.g "-param1\t-param2=value2\t-param3\tvalue3"
- private static final String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_STYLE=0\t";
+ private String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_STYLE=1\t";
// use this variable to add any environment variables to your application.
// the env vars must be separated with "\t"
// e.g. "ENV_VAR1=1\tENV_VAR2=2\t"
@@ -127,7 +127,14 @@ public class QtActivity extends Activity
// * QT_USE_ANDROID_NATIVE_STYLE - 1 to use the android widget style if available,
// note that the android style plugin in Qt 5.1 is not fully functional.
+ private static final String QT_ANDROID_THEME = "light"; // sets the default theme to light. Possible values are:
+ // * "" - for the device default dark theme
+ // * "light" - for the device default light theme
+ // * "holo" - for the holo dark theme
+ // * "holo_light" - for the holo light theme
+
private static final int INCOMPATIBLE_MINISTRO_VERSION = 1; // Incompatible Ministro version. Ministro needs to be upgraded.
+ private static final String DISPLAY_DPI_KEY = "display.dpi";
private static final int BUFFER_SIZE = 1024;
private ActivityInfo m_activityInfo = null; // activity info object, used to access the libs and the strings
@@ -246,6 +253,7 @@ public class QtActivity extends Activity
parameters.putString(APPLICATION_PARAMETERS_KEY, APPLICATION_PARAMETERS);
parameters.putStringArray(SOURCES_KEY, m_sources);
parameters.putString(REPOSITORY_KEY, m_repository);
+ parameters.putInt(DISPLAY_DPI_KEY, QtActivity.this.getResources().getDisplayMetrics().densityDpi);
m_service.requestLoader(m_ministroCallback, parameters);
}
} catch (RemoteException e) {
@@ -671,7 +679,8 @@ public class QtActivity extends Activity
QtApplication.invokeDelegateMethod(QtApplication.onCreate, savedInstanceState);
return;
}
-
+ ENVIRONMENT_VARIABLES += "\tQT_ANDROID_THEME=" + QT_ANDROID_THEME
+ + "/\tQT_ANDROID_THEME_DISPLAY_DPI=" + getResources().getDisplayMetrics().densityDpi + "\t";
requestWindowFeature(Window.FEATURE_NO_TITLE);
try {
m_activityInfo = getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
diff --git a/src/android/java/version.xml b/src/android/java/version.xml
index e709357ba6..bdcf915c06 100644
--- a/src/android/java/version.xml
+++ b/src/android/java/version.xml
@@ -1,4 +1,4 @@
-<version value="5">
+<version value="5.2">
<ignore>
<file>AndroidManifest.xml</file>
<file>libs.xml</file>
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp
index f69d9dd8de..951b4bd05d 100644
--- a/src/corelib/animation/qvariantanimation.cpp
+++ b/src/corelib/animation/qvariantanimation.cpp
@@ -101,6 +101,7 @@ QT_BEGIN_NAMESPACE
\list
\li \l{QMetaType::}{Int}
+ \li \l{QMetaType::}{UInt}
\li \l{QMetaType::}{Double}
\li \l{QMetaType::}{Float}
\li \l{QMetaType::}{QLine}
@@ -470,6 +471,8 @@ QVariantAnimation::Interpolator QVariantAnimationPrivate::getInterpolator(int in
{
case QMetaType::Int:
return castToInterpolator(_q_interpolateVariant<int>);
+ case QMetaType::UInt:
+ return castToInterpolator(_q_interpolateVariant<uint>);
case QMetaType::Double:
return castToInterpolator(_q_interpolateVariant<double>);
case QMetaType::Float:
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp
index 4437313f0a..cb1346f74c 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp
@@ -112,3 +112,34 @@ id = qMetaTypeId<MyStruct>(); // compile error if MyStruct not declared
typedef QString CustomString;
qRegisterMetaType<CustomString>("CustomString");
//! [9]
+
+//! [10]
+
+#include <deque>
+
+Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::deque)
+
+void someFunc()
+{
+ std::deque<QFile*> container;
+ QVariant var = QVariant::fromValue(container);
+ // ...
+}
+
+//! [10]
+
+//! [11]
+
+#include <unordered_list>
+
+Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(std::unordered_map)
+
+void someFunc()
+{
+ std::unordered_map<int, bool> container;
+ QVariant var = QVariant::fromValue(container);
+ // ...
+}
+
+//! [11]
+
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineoption.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineoption.cpp
index d4c745215f..67d5f41b38 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineoption.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineoption.cpp
@@ -38,7 +38,14 @@
**
****************************************************************************/
+#include <QCommandLineOption>
+
+int main()
+{
+
//! [0]
QCommandLineOption verboseOption("verbose", "Verbose mode. Prints out more information.");
QCommandLineOption outputOption(QStringList() << "o" << "output", "Write generated data into <file>.", "file");
//! [0]
+
+}
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser.cpp
index 569cb6af80..0ec45e04a7 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser.cpp
@@ -38,11 +38,32 @@
**
****************************************************************************/
+#include <qcommandlineparser.h>
+
+int main(int argc, char **argv)
+{
+
+{
+QCommandLineParser parser;
//! [0]
bool verbose = parser.isSet("verbose");
//! [0]
+}
+{
//! [1]
+QCoreApplication app(argc, argv);
+QCommandLineParser parser;
+QCommandLineOption verboseOption("verbose");
+parser.addOption(verboseOption);
+parser.process(app);
+bool verbose = parser.isSet(verboseOption);
+//! [1]
+}
+
+{
+QCommandLineParser parser;
+//! [2]
// Usage: image-editor file
//
// Arguments:
@@ -62,9 +83,14 @@ parser.addPositionalArgument("urls", QCoreApplication::translate("main", "URLs t
// destination Destination directory.
parser.addPositionalArgument("source", QCoreApplication::translate("main", "Source file to copy."));
parser.addPositionalArgument("destination", QCoreApplication::translate("main", "Destination directory."));
-//! [1]
-
//! [2]
+}
+
+{
+//! [3]
+QCoreApplication app(argc, argv);
+QCommandLineParser parser;
+
parser.addPositionalArgument("command", "The command to execute.");
// Call parse() to find out the positional arguments.
@@ -80,6 +106,7 @@ if (command == "resize") {
// ...
}
+/*
This code results in context-dependent help:
$ tool --help
@@ -96,46 +123,16 @@ Options:
Arguments:
resize Resize the object to a new size.
-
-//! [2]
-
+*/
//! [3]
-int main(int argc, char *argv[])
-{
- QCoreApplication app(argc, argv);
- app.setApplicationName("my-copy-program");
- app.setApplicationVersion("1.0");
-
- QCommandLineParser parser;
- parser.addHelpOption("Test helper");
- parser.addVersionOption();
- parser.addRemainingArgument("source", QCoreApplication::translate("main", "Source file to copy."));
- parser.addRemainingArgument("destination", QCoreApplication::translate("main", "Destination directory."));
-
- // A boolean option with a single name (-p)
- QCommandLineOption showProgressOption("p", QCoreApplication::translate("main", "Show progress during copy"));
- parser.addOption(showProgressOption);
-
- // A boolean option with multiple names (-f, --force)
- QCommandLineOption forceOption(QStringList() << "f" << "force", "Overwrite existing files.");
- parser.addOption(forceOption);
-
- // An option with a value
- QCommandLineOption targetDirectoryOption(QStringList() << "t" << "target-directory",
- QCoreApplication::translate("main", "Copy all source files into <directory>."),
- QCoreApplication::translate("main", "directory"));
- parser.addOption(targetDirectoryOption);
-
- // Process the actual command line arguments given by the user
- parser.process(app);
-
- const QStringList args = parser.remainingArguments();
- // source is args.at(0), destination is args.at(1)
+}
- bool showProgress = parser.isSet(showProgressOption);
- bool force = parser.isSet(forceOption);
- QString targetDir = parser.value(targetDirectoryOption);
- // ...
+{
+//! [4]
+QCommandLineParser parser;
+parser.setApplicationDescription(QCoreApplication::translate("main", "The best application in the world"));
+parser.addHelpOption();
+//! [4]
}
-//! [3]
+}
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser_main.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser_main.cpp
new file mode 100644
index 0000000000..46b4274301
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser_main.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 David Faure <faure@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation 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 Digia Plc 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 <qcommandlineparser.h>
+
+//! [0]
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+ QCoreApplication::setApplicationName("my-copy-program");
+ QCoreApplication::setApplicationVersion("1.0");
+
+ QCommandLineParser parser;
+ parser.setApplicationDescription("Test helper");
+ parser.addHelpOption();
+ parser.addVersionOption();
+ parser.addPositionalArgument("source", QCoreApplication::translate("main", "Source file to copy."));
+ parser.addPositionalArgument("destination", QCoreApplication::translate("main", "Destination directory."));
+
+ // A boolean option with a single name (-p)
+ QCommandLineOption showProgressOption("p", QCoreApplication::translate("main", "Show progress during copy"));
+ parser.addOption(showProgressOption);
+
+ // A boolean option with multiple names (-f, --force)
+ QCommandLineOption forceOption(QStringList() << "f" << "force", "Overwrite existing files.");
+ parser.addOption(forceOption);
+
+ // An option with a value
+ QCommandLineOption targetDirectoryOption(QStringList() << "t" << "target-directory",
+ QCoreApplication::translate("main", "Copy all source files into <directory>."),
+ QCoreApplication::translate("main", "directory"));
+ parser.addOption(targetDirectoryOption);
+
+ // Process the actual command line arguments given by the user
+ parser.process(app);
+
+ const QStringList args = parser.positionalArguments();
+ // source is args.at(0), destination is args.at(1)
+
+ bool showProgress = parser.isSet(showProgressOption);
+ bool force = parser.isSet(forceOption);
+ QString targetDir = parser.value(targetDirectoryOption);
+ // ...
+}
+
+//! [0]
diff --git a/src/corelib/doc/src/threads.qdoc b/src/corelib/doc/src/threads.qdoc
index 160b717715..67a986d73e 100644
--- a/src/corelib/doc/src/threads.qdoc
+++ b/src/corelib/doc/src/threads.qdoc
@@ -655,11 +655,6 @@
separate QImages, but the two threads cannot paint onto the same
QImage at the same time.
- Note that on X11 systems without FontConfig support, Qt cannot
- render text outside of the GUI thread. You can use the
- QFontDatabase::supportsThreadedFontRendering() function to detect
- whether or not font rendering can be used outside the GUI thread.
-
\section1 Threads and Rich Text Processing
The QTextDocument, QTextCursor, and \l{richtext.html}{all related classes} are reentrant.
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 5b6639d56b..dbedfe5ddd 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -441,6 +441,7 @@
* N2346 Q_COMPILER_DEFAULT_MEMBERS
* N2346 Q_COMPILER_DELETE_MEMBERS
* N1986 Q_COMPILER_DELEGATING_CONSTRUCTORS
+ * N2437 Q_COMPILER_EXPLICIT_CONVERSIONS
* N3206 N3272 Q_COMPILER_EXPLICIT_OVERRIDES (v0.9 and above only)
* N1987 Q_COMPILER_EXTERN_TEMPLATES
* N2540 Q_COMPILER_INHERITING_CONSTRUCTORS
@@ -554,6 +555,9 @@
# if __has_feature(cxx_delegating_constructors)
# define Q_COMPILER_DELEGATING_CONSTRUCTORS
# endif
+# if __has_feature(cxx_explicit_conversions)
+# define Q_COMPILER_EXPLICIT_CONVERSIONS
+# endif
# if __has_feature(cxx_override_control)
# define Q_COMPILER_EXPLICIT_OVERRIDES
# endif
@@ -639,6 +643,7 @@
# endif
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
/* C++11 features supported in GCC 4.5: */
+# define Q_COMPILER_EXPLICIT_CONVERSIONS
# define Q_COMPILER_LAMBDA
# define Q_COMPILER_RAW_STRINGS
# endif
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 9656f4b68a..9ce820afff 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -2300,7 +2300,7 @@ bool qunsetenv(const char *varName)
#endif
}
-#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD)
+#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0)
# if defined(Q_OS_INTEGRITY) && defined(__GHS_VERSION_NUMBER) && (__GHS_VERSION_NUMBER < 500)
// older versions of INTEGRITY used a long instead of a uint for the seed.
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index e72ea792dd..d3db3b9dde 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -196,6 +196,8 @@ typedef quint64 qulonglong;
# define QT_POINTER_SIZE 8
# elif defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
# define QT_POINTER_SIZE 4
+# elif defined(Q_OS_ANDROID)
+# define QT_POINTER_SIZE 4 // ### Add auto-detection to Windows configure
# endif
#endif
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index a37fc15b61..c791a22765 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -84,6 +84,33 @@ static bool isFatal(QtMsgType msgType)
return false;
}
+#ifdef Q_OS_WIN
+
+// Do we have stderr for QDebug? - Either there is a console or we are running
+// with redirected stderr.
+# ifndef Q_OS_WINCE
+static inline bool hasStdErr()
+{
+ if (GetConsoleWindow())
+ return true;
+ STARTUPINFO info;
+ GetStartupInfo(&info);
+ return (info.dwFlags & STARTF_USESTDHANDLES) && info.hStdError
+ && info.hStdError != INVALID_HANDLE_VALUE;
+}
+# endif // !Q_OS_WINCE
+
+bool qWinLogToStderr()
+{
+# ifndef Q_OS_WINCE
+ static const bool result = hasStdErr();
+ return result;
+# else
+ return false;
+# endif
+}
+#endif // Q_OS_WIN
+
/*!
\class QMessageLogContext
\inmodule QtCore
@@ -114,11 +141,6 @@ static bool isFatal(QtMsgType msgType)
\sa QMessageLogContext, qDebug(), qWarning(), qCritical(), qFatal()
*/
-#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
-// defined in qcoreapplication_win.cpp
-extern bool usingWinMain;
-#endif
-
#ifdef Q_OS_WIN
static inline void convert_to_wchar_t_elided(wchar_t *d, size_t space, const char *s) Q_DECL_NOEXCEPT
{
@@ -159,11 +181,11 @@ static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap) Q_DECL
convert_to_wchar_t_elided(emergency_bufL, sizeof emergency_buf, emergency_buf);
OutputDebugStringW(emergency_bufL);
# else
- if (usingWinMain) {
- OutputDebugStringA(emergency_buf);
- } else {
+ if (qWinLogToStderr()) {
fprintf(stderr, "%s", emergency_buf);
fflush(stderr);
+ } else {
+ OutputDebugStringA(emergency_buf);
}
# endif
#else
@@ -683,7 +705,7 @@ void QMessagePattern::setPattern(const QString &pattern)
OutputDebugString(reinterpret_cast<const wchar_t*>(error.utf16()));
if (0)
#elif defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
- if (usingWinMain) {
+ if (!qWinLogToStderr()) {
OutputDebugString(reinterpret_cast<const wchar_t*>(error.utf16()));
} else
#endif
@@ -850,8 +872,9 @@ static void android_default_message_handler(QtMsgType type,
case QtFatalMsg: priority = ANDROID_LOG_FATAL; break;
};
- __android_log_print(priority, "Qt", "%s:%d (%s): %s", qPrintable(context.file), context.line,
- qPrintable(context.function), qPrintable(message));
+ __android_log_print(priority, "Qt", "%s:%d (%s): %s",
+ context.file, context.line,
+ context.function, qPrintable(message));
}
#endif //Q_OS_ANDROID
@@ -864,10 +887,7 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con
QString logMessage = qMessageFormatString(type, context, buf);
#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
-#if !defined(Q_OS_WINCE)
- if (usingWinMain)
-#endif
- {
+ if (!qWinLogToStderr()) {
OutputDebugString(reinterpret_cast<const wchar_t *>(logMessage.utf16()));
return;
}
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index c984f28bd0..33cda4a447 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -214,10 +214,10 @@ class QDirSortItemComparator
int qt_cmp_si_sort_flags;
public:
QDirSortItemComparator(int flags) : qt_cmp_si_sort_flags(flags) {}
- bool operator()(const QDirSortItem &, const QDirSortItem &);
+ bool operator()(const QDirSortItem &, const QDirSortItem &) const;
};
-bool QDirSortItemComparator::operator()(const QDirSortItem &n1, const QDirSortItem &n2)
+bool QDirSortItemComparator::operator()(const QDirSortItem &n1, const QDirSortItem &n2) const
{
const QDirSortItem* f1 = &n1;
const QDirSortItem* f2 = &n2;
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index 22eda87c36..ebcaf062e3 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -72,6 +72,7 @@
# include <ioLib.h>
#endif
+#include <algorithm>
#include <stdlib.h>
#ifdef Q_OS_WIN // for homedirpath reading from registry
@@ -1905,7 +1906,7 @@ bool QConfFileSettingsPrivate::writeIniFile(QIODevice &device, const ParsedSetti
sections.reserve(sectionCount);
for (i = iniMap.constBegin(); i != iniMap.constEnd(); ++i)
sections.append(QSettingsIniKey(i.key(), i.value().position));
- qSort(sections);
+ std::sort(sections.begin(), sections.end());
bool writeError = false;
for (int j = 0; !writeError && j < sectionCount; ++j) {
diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp
index 1c9fa278cd..61e2e03a3d 100644
--- a/src/corelib/io/qstandardpaths_unix.cpp
+++ b/src/corelib/io/qstandardpaths_unix.cpp
@@ -257,6 +257,17 @@ static QStringList xdgDataDirs()
dirs.append(QString::fromLatin1("/usr/share"));
} else {
dirs = xdgDataDirsEnv.split(QLatin1Char(':'));
+ // Normalize paths
+ for (int i = 0; i < dirs.count(); i++)
+ dirs[i] = QDir::cleanPath(dirs.at(i));
+
+ // Remove duplicates from the list, there's no use for duplicated
+ // paths in XDG_DATA_DIRS - if it's not found in the given
+ // directory the first time, it won't be there the second time.
+ // Plus duplicate paths causes problems for example for mimetypes,
+ // where duplicate paths here lead to duplicated mime types returned
+ // for a file, eg "text/plain,text/plain" instead of "text/plain"
+ dirs.removeDuplicates();
}
return dirs;
}
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
index 93e45d3984..3e2fd6a689 100644
--- a/src/corelib/kernel/qcoreapplication_win.cpp
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -54,7 +54,6 @@
QT_BEGIN_NAMESPACE
-bool usingWinMain = false; // whether the qWinMain() is used or not
int appCmdShow = 0;
Q_CORE_EXPORT HINSTANCE qWinAppInst() // get Windows app handle
@@ -147,7 +146,6 @@ void qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
return;
}
already_called = true;
- usingWinMain = true;
// Create command line
argv = qWinCmdLine<char>(cmdParam, int(strlen(cmdParam)), argc);
diff --git a/src/corelib/kernel/qcorecmdlineargs_p.h b/src/corelib/kernel/qcorecmdlineargs_p.h
index 17a03a5b2d..f2b109facd 100644
--- a/src/corelib/kernel/qcorecmdlineargs_p.h
+++ b/src/corelib/kernel/qcorecmdlineargs_p.h
@@ -83,7 +83,7 @@ static QVector<Char*> qWinCmdLine(Char *cmdParam, int length, int &argc)
if (*p && p < p_end) { // arg starts
int quote;
Char *start, *r;
- if (*p == Char('\"') || *p == Char('\'')) { // " or ' quote
+ if (*p == Char('\"')) {
quote = *p;
start = ++p;
} else {
@@ -101,10 +101,11 @@ static QVector<Char*> qWinCmdLine(Char *cmdParam, int length, int &argc)
}
}
if (*p == '\\') { // escape char?
- if (*(p+1) == quote)
+ // testing by looking at argc, argv shows that it only escapes quotes and backslashes
+ if (p < p_end && (*(p+1) == Char('\"') || *(p+1) == Char('\\')))
p++;
} else {
- if (!quote && (*p == Char('\"') || *p == Char('\''))) { // " or ' quote
+ if (!quote && (*p == Char('\"'))) {
quote = *p++;
continue;
} else if (QChar((short)(*p)).isSpace() && !quote)
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
index 4c727f9d3d..ac57454169 100644
--- a/src/corelib/kernel/qmetaobjectbuilder.cpp
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -510,7 +510,7 @@ QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray& signature)
{
int index = d->methods.size();
d->methods.append(QMetaMethodBuilderPrivate
- (QMetaMethod::Signal, signature, QByteArray("void"), QMetaMethod::Protected));
+ (QMetaMethod::Signal, signature, QByteArray("void"), QMetaMethod::Public));
return QMetaMethodBuilder(this, index);
}
@@ -2005,8 +2005,7 @@ void QMetaMethodBuilder::setTag(const QByteArray& value)
/*!
Returns the access specification of this method (private, protected,
or public). The default value is QMetaMethod::Public for methods,
- slots, and constructors. The default value is QMetaMethod::Protected
- for signals.
+ slots, signals and constructors.
\sa setAccess()
*/
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 17fbbda720..2ab6681bb9 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -141,6 +141,40 @@ struct DefinedTypesFilter {
*/
/*!
+ \macro Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(Container)
+ \relates QMetaType
+
+ This macro makes the container \a Container known to QMetaType as a sequential
+ container. This makes it possible to put an instance of Container<T> into
+ a QVariant, if T itself is known to QMetaType.
+
+ Note that all of the Qt sequential containers already have built-in
+ support, and it is not necessary to use this macro with them. The
+ std::vector and std::list containers also have built-in support.
+
+ This example shows a typical use of Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE():
+
+ \snippet code/src_corelib_kernel_qmetatype.cpp 10
+*/
+
+/*!
+ \macro Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(Container)
+ \relates QMetaType
+
+ This macro makes the container \a Container known to QMetaType as an associative
+ container. This makes it possible to put an instance of Container<T, U> into
+ a QVariant, if T and U are themselves known to QMetaType.
+
+ Note that all of the Qt associative containers already have built-in
+ support, and it is not necessary to use this macro with them. The
+ std::map container also has built-in support.
+
+ This example shows a typical use of Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE():
+
+ \snippet code/src_corelib_kernel_qmetatype.cpp 11
+*/
+
+/*!
\enum QMetaType::Type
These are the built-in types supported by QMetaType:
@@ -2085,37 +2119,6 @@ const QMetaObject *QMetaType::metaObjectForType(int type)
\sa Q_DECLARE_METATYPE(), QMetaType::type()
*/
-/*!
- \fn bool qRegisterSequentialConverter()
- \relates QMetaType
- \since 5.2
-
- Registers a sequential container so that it can be converted to
- a QVariantList. If compilation fails, then you probably forgot to
- Q_DECLARE_METATYPE the value type.
-
- Note that it is not necessary to call this method for Qt containers (QList,
- QVector etc) or for std::vector or std::list. Such containers are automatically
- registered by Qt.
-
- \sa QVariant::canConvert()
-*/
-
-/*!
- \fn bool qRegisterAssociativeConverter()
- \relates QMetaType
- \since 5.2
-
- Registers an associative container so that it can be converted to
- a QVariantHash or QVariantMap. If the key_type and mapped_type of the container
- was not declared with Q_DECLARE_METATYPE(), compilation will fail.
-
- Note that it is not necessary to call this method for Qt containers (QHash,
- QMap etc) or for std::map. Such containers are automatically registered by Qt.
-
- \sa QVariant::canConvert()
-*/
-
namespace {
class TypeInfo {
template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 6b1a988fce..bd4963e4f1 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -1331,33 +1331,12 @@ namespace QtPrivate
enum { Value = false };
};
-#define QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE(CONTAINER) \
- template<typename T> \
- struct IsSequentialContainer<CONTAINER<T> > \
- { \
- enum { Value = true }; \
- };
- QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE)
- QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE(std::vector)
- QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE(std::list)
-
template<typename T>
struct IsAssociativeContainer
{
enum { Value = false };
};
-#define QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(CONTAINER) \
- template<typename T, typename U> \
- struct IsAssociativeContainer<CONTAINER<T, U> > \
- { \
- enum { Value = true }; \
- };
- QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(QHash)
- QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(QMap)
- QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(std::map)
-
-
template<typename T, bool = QtPrivate::IsSequentialContainer<T>::Value>
struct SequentialContainerConverterHelper
{
@@ -1763,6 +1742,13 @@ struct QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \
return newId; \
} \
}; \
+namespace QtPrivate { \
+template<typename T> \
+struct IsSequentialContainer<SINGLE_ARG_TEMPLATE<T> > \
+{ \
+ enum { Value = true }; \
+}; \
+} \
QT_END_NAMESPACE
#define Q_DECLARE_METATYPE_TEMPLATE_2ARG(DOUBLE_ARG_TEMPLATE) \
@@ -1851,7 +1837,7 @@ struct QMetaTypeId< SMART_POINTER<T> > \
};\
QT_END_NAMESPACE
-#define Q_DECLARE_METATYPE_TEMPLATE_1ARG_ITER(TEMPLATENAME) \
+#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER(TEMPLATENAME) \
QT_BEGIN_NAMESPACE \
template <class T> class TEMPLATENAME; \
QT_END_NAMESPACE \
@@ -1859,25 +1845,42 @@ QT_END_NAMESPACE
QT_END_NAMESPACE
-QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(Q_DECLARE_METATYPE_TEMPLATE_1ARG_ITER)
+QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER)
+
+#undef Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER
-#undef Q_DECLARE_METATYPE_TEMPLATE_1ARG_ITER
+#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE Q_DECLARE_METATYPE_TEMPLATE_1ARG
-Q_DECLARE_METATYPE_TEMPLATE_1ARG(std::vector)
-Q_DECLARE_METATYPE_TEMPLATE_1ARG(std::list)
+Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::vector)
+Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::list)
-#define Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER(TEMPLATENAME, CPPTYPE) \
+#define Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER(TEMPLATENAME, CPPTYPE) \
QT_BEGIN_NAMESPACE \
template <class T1, class T2> CPPTYPE TEMPLATENAME; \
QT_END_NAMESPACE \
- Q_DECLARE_METATYPE_TEMPLATE_2ARG(TEMPLATENAME)
-QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER)
+QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER)
#undef Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER
+#define Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(TEMPLATENAME) \
+ QT_BEGIN_NAMESPACE \
+ namespace QtPrivate { \
+ template<typename T, typename U> \
+ struct IsAssociativeContainer<TEMPLATENAME<T, U> > \
+ { \
+ enum { Value = true }; \
+ }; \
+ } \
+ QT_END_NAMESPACE \
+ Q_DECLARE_METATYPE_TEMPLATE_2ARG(TEMPLATENAME)
+
+Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QHash)
+Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QMap)
+Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(std::map)
+
+Q_DECLARE_METATYPE_TEMPLATE_2ARG(QPair)
Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::pair)
-Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::map)
#define Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER(TEMPLATENAME) \
Q_DECLARE_SMART_POINTER_METATYPE(TEMPLATENAME)
@@ -2009,45 +2012,6 @@ inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter(int id)
return true;
}
-
-#ifndef Q_QDOC
-template<typename T>
-#endif
-bool qRegisterSequentialConverter()
-{
- Q_STATIC_ASSERT_X(QMetaTypeId2<typename T::value_type>::Defined,
- "The value_type of a sequential container must itself be a metatype.");
- const int id = qMetaTypeId<T>();
- const int toId = qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>();
- if (QMetaType::hasRegisteredConverterFunction(id, toId))
- return true;
-
- static const QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> o;
- static const QtPrivate::ConverterFunctor<T,
- QtMetaTypePrivate::QSequentialIterableImpl,
- QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> > f(o);
- return QMetaType::registerConverterFunction(&f, id, toId);
-}
-
-template<typename T>
-bool qRegisterAssociativeConverter()
-{
- Q_STATIC_ASSERT_X(QMetaTypeId2<typename T::key_type>::Defined
- && QMetaTypeId2<typename T::mapped_type>::Defined,
- "The key_type and mapped_type of an associative container must themselves be metatypes.");
-
- const int id = qMetaTypeId<T>();
- const int toId = qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>();
- if (QMetaType::hasRegisteredConverterFunction(id, toId))
- return true;
- static const QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> o;
- static const QtPrivate::ConverterFunctor<T,
- QtMetaTypePrivate::QAssociativeIterableImpl,
- QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> > f(o);
-
- return QMetaType::registerConverterFunction(&f, id, toId);
-}
-
QT_END_NAMESPACE
#endif // QMETATYPE_H
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index c489344b10..dd10e70609 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -125,7 +125,7 @@ class QString;
/* qmake ignore Q_OBJECT */
#define Q_OBJECT_CHECK \
- template <typename T> inline void qt_check_for_QOBJECT_macro(const T &_q_argument) const \
+ template <typename ThisObject> inline void qt_check_for_QOBJECT_macro(const ThisObject &_q_argument) const \
{ int i = qYouForgotTheQ_OBJECT_Macro(this, &_q_argument); i = i + 1; }
template <typename T>
diff --git a/src/corelib/kernel/qsharedmemory_android.cpp b/src/corelib/kernel/qsharedmemory_android.cpp
index 56466eae03..33ebb6966a 100644
--- a/src/corelib/kernel/qsharedmemory_android.cpp
+++ b/src/corelib/kernel/qsharedmemory_android.cpp
@@ -57,6 +57,7 @@ QSharedMemoryPrivate::QSharedMemoryPrivate()
void QSharedMemoryPrivate::setErrorString(const QString &function)
{
+ Q_UNUSED(function);
qWarning() << Q_FUNC_INFO << "Not yet implemented on Android";
}
@@ -71,6 +72,7 @@ key_t QSharedMemoryPrivate::handle()
#if !(defined(QT_NO_SHAREDMEMORY) && defined(QT_NO_SYSTEMSEMAPHORE))
int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName)
{
+ Q_UNUSED(fileName);
qWarning() << Q_FUNC_INFO << "Not yet implemented on Android";
return 0;
}
@@ -86,12 +88,14 @@ bool QSharedMemoryPrivate::cleanHandle()
bool QSharedMemoryPrivate::create(int size)
{
+ Q_UNUSED(size);
qWarning() << Q_FUNC_INFO << "Not yet implemented on Android";
return false;
}
bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
{
+ Q_UNUSED(mode);
qWarning() << Q_FUNC_INFO << "Not yet implemented on Android";
return false;
}
diff --git a/src/corelib/kernel/qsystemsemaphore_android.cpp b/src/corelib/kernel/qsystemsemaphore_android.cpp
index 8158fdb2ed..6251cd822a 100644
--- a/src/corelib/kernel/qsystemsemaphore_android.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_android.cpp
@@ -56,11 +56,13 @@ QSystemSemaphorePrivate::QSystemSemaphorePrivate() :
void QSystemSemaphorePrivate::setErrorString(const QString &function)
{
+ Q_UNUSED(function);
qWarning() << Q_FUNC_INFO << "Not yet implemented on Android";
}
key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
{
+ Q_UNUSED(mode);
qWarning() << Q_FUNC_INFO << "Not yet implemented on Android";
return -1;
}
@@ -72,6 +74,7 @@ void QSystemSemaphorePrivate::cleanHandle()
bool QSystemSemaphorePrivate::modifySemaphore(int count)
{
+ Q_UNUSED(count);
qWarning() << Q_FUNC_INFO << "Not yet implemented on Android";
return false;
}
diff --git a/src/corelib/tools/qcommandlineoption.cpp b/src/corelib/tools/qcommandlineoption.cpp
index 4f9e166587..b30f7d25b4 100644
--- a/src/corelib/tools/qcommandlineoption.cpp
+++ b/src/corelib/tools/qcommandlineoption.cpp
@@ -193,18 +193,21 @@ void QCommandLineOptionPrivate::setNames(const QStringList &nameList)
{
names.clear();
if (nameList.isEmpty())
- qWarning("Options must have at least one name");
+ qWarning("QCommandLineOption: Options must have at least one name");
foreach (const QString &name, nameList) {
- if (name.isEmpty())
- qWarning("Option names cannot be empty");
- else if (name.startsWith(QLatin1Char('-')))
- qWarning("Option names cannot start with a '-'");
- else if (name.startsWith(QLatin1Char('/')))
- qWarning("Option names cannot start with a '/'");
- else if (name.contains(QLatin1Char('=')))
- qWarning("Option names cannot contain a '='");
- else
- names.append(name);
+ if (name.isEmpty()) {
+ qWarning("QCommandLineOption: Option names cannot be empty");
+ } else {
+ const QChar c = name.at(0);
+ if (c == QLatin1Char('-'))
+ qWarning("QCommandLineOption: Option names cannot start with a '-'");
+ else if (c == QLatin1Char('/'))
+ qWarning("QCommandLineOption: Option names cannot start with a '/'");
+ else if (name.contains(QLatin1Char('=')))
+ qWarning("QCommandLineOption: Option names cannot contain a '='");
+ else
+ names.append(name);
+ }
}
}
diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp
index ae6079ab0b..e2e410c059 100644
--- a/src/corelib/tools/qcommandlineparser.cpp
+++ b/src/corelib/tools/qcommandlineparser.cpp
@@ -52,9 +52,6 @@ QT_BEGIN_NAMESPACE
typedef QHash<QString, int> NameHash_t;
-// Special value for "not found" when doing hash lookups.
-static const NameHash_t::mapped_type optionNotFound = ~0;
-
class QCommandLineParserPrivate
{
public:
@@ -122,12 +119,12 @@ public:
QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
{
- const NameHash_t::mapped_type optionOffset = nameHash.value(optionName, optionNotFound);
- if (optionOffset == optionNotFound) {
+ const NameHash_t::const_iterator it = nameHash.find(optionName);
+ if (it == nameHash.end()) {
qWarning("QCommandLineParser: option not defined: \"%s\"", qPrintable(optionName));
return QStringList();
}
- return commandLineOptionList.at(optionOffset).names();
+ return commandLineOptionList.at(*it).names();
}
/*!
@@ -160,7 +157,7 @@ QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
passing \c{-v} on the command line. In the default parsing mode, short options
can be written in a compact form, for instance \c{-abc} is equivalent to \c{-a -b -c}.
The parsing mode for can be set to ParseAsLongOptions, in which case \c{-abc}
- will be parsed as the long option \a{abc}.
+ will be parsed as the long option \c{abc}.
Long options are more than one letter long and cannot be compacted together.
The long option \c{verbose} would be passed as \c{--verbose} or \c{-verbose}.
@@ -180,7 +177,7 @@ QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
as one of its names, and handling the option explicitly.
Example:
- \snippet code/src_corelib_tools_qcommandlineparser.cpp 3
+ \snippet code/src_corelib_tools_qcommandlineparser_main.cpp 0
Known limitation: the parsing of Qt options inside QCoreApplication and subclasses
happens before QCommandLineParser exists, so it can't take it into account. This
@@ -297,10 +294,7 @@ QCommandLineOption QCommandLineParser::addVersionOption()
which will be displayed when this option is used.
Example:
- \code
- setApplicationDescription(QCoreApplication::translate("main", "The best application in the world"));
- addHelpOption();
- \endcode
+ \snippet code/src_corelib_tools_qcommandlineparser_main.cpp 0
Returns the option instance, which can be used to call isSet().
*/
@@ -319,8 +313,6 @@ QCommandLineOption QCommandLineParser::addHelpOption()
/*!
Sets the application \a description shown by helpText().
- Most applications don't need to call this directly, addHelpOption()
- also sets the application description.
*/
void QCommandLineParser::setApplicationDescription(const QString &description)
{
@@ -328,8 +320,7 @@ void QCommandLineParser::setApplicationDescription(const QString &description)
}
/*!
- Returns the application description set in setApplicationDescription()
- or addHelpOption().
+ Returns the application description set in setApplicationDescription().
*/
QString QCommandLineParser::applicationDescription() const
{
@@ -344,7 +335,7 @@ QString QCommandLineParser::applicationDescription() const
the \a name will be appended.
Example:
- \snippet code/src_corelib_tools_qcommandlineparser.cpp 1
+ \snippet code/src_corelib_tools_qcommandlineparser.cpp 2
\sa addHelpOption(), helpText()
*/
@@ -366,7 +357,7 @@ void QCommandLineParser::addPositionalArgument(const QString &name, const QStrin
accordingly.
Example:
- \snippet code/src_corelib_tools_qcommandlineparser.cpp 2
+ \snippet code/src_corelib_tools_qcommandlineparser.cpp 3
*/
void QCommandLineParser::clearPositionalArguments()
{
@@ -376,7 +367,7 @@ void QCommandLineParser::clearPositionalArguments()
/*!
Parses the command line \a arguments.
- Most programs don't need to call this, a simple call to process(app) is enough.
+ Most programs don't need to call this, a simple call to process() is enough.
parse() is more low-level, and only does the parsing. The application will have to
take care of the error handling, using errorText() if parse() returns false.
@@ -388,7 +379,7 @@ void QCommandLineParser::clearPositionalArguments()
Don't forget that \a arguments must start with the name of the executable (ignored, though).
- Return false in case of a parse error (unknown option or missing value); returns true otherwise.
+ Returns false in case of a parse error (unknown option or missing value); returns true otherwise.
\sa process()
*/
@@ -415,10 +406,13 @@ QString QCommandLineParser::errorText() const
/*!
Processes the command line \a arguments.
- This means both parsing them, and handling the builtin options,
- \c{--version} if addVersionOption was called, \c{--help} if addHelpOption was called,
- as well as giving an error on unknown option names.
- In each of these three cases, the current process will then stop, using the exit() function.
+ In addition to parsing the options (like parse()), this function also handles the builtin
+ options and handles errors.
+
+ The builtin options are \c{--version} if addVersionOption was called and \c{--help} if addHelpOption was called.
+
+ When invoking one of these options, or when an error happens (for instance an unknown option was
+ passed), the current process will then stop, using the exit() function.
\sa QCoreApplication::arguments(), parse()
*/
@@ -426,16 +420,16 @@ void QCommandLineParser::process(const QStringList &arguments)
{
if (!d->parse(arguments)) {
fprintf(stderr, "%s\n", qPrintable(errorText()));
- ::exit(1);
+ ::exit(EXIT_FAILURE);
}
if (d->builtinVersionOption && isSet(QStringLiteral("version"))) {
printf("%s %s\n", qPrintable(QCoreApplication::applicationName()), qPrintable(QCoreApplication::applicationVersion()));
- ::exit(0);
+ ::exit(EXIT_SUCCESS);
}
if (d->builtinHelpOption && isSet(QStringLiteral("help")))
- showHelp(0);
+ showHelp(EXIT_SUCCESS);
}
/*!
@@ -517,17 +511,13 @@ bool QCommandLineParserPrivate::parseOptionValue(const QString &optionName, cons
/*!
\internal
- Parse the list of arguments \a arguments.
+ Parse the list of arguments \a args, and fills in
+ optionNames, optionValuesHash, unknownOptionNames, positionalArguments, and errorText.
Any results from a previous parse operation are removed.
+
The parser will not look for further options once it encounters the option
\c{--}; this does not include when \c{--} follows an option that requires a value.
-
- Options that were successfully recognized, and their values, are
- removed from the input list. If \c m_bRemoveUnknownLongNames is
- \c true, unrecognized options are removed and placed into a list of
- unknown option names. Anything left over is placed into a list of
- leftover arguments.
*/
bool QCommandLineParserPrivate::parse(const QStringList &args)
{
@@ -632,8 +622,6 @@ bool QCommandLineParserPrivate::parse(const QStringList &args)
Returns true if the option \a name was set, false otherwise.
- This is the recommended way to check for options with no values.
-
The name provided can be any long or short name of any option that was
added with \c addOption(). All the options names are treated as being
equivalent. If the name is not recognized or that option was not present,
@@ -671,7 +659,7 @@ bool QCommandLineParser::isSet(const QString &name) const
An empty string is returned if the option does not take a value.
- \sa values()
+ \sa values(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
*/
QString QCommandLineParser::value(const QString &optionName) const
@@ -700,14 +688,15 @@ QString QCommandLineParser::value(const QString &optionName) const
An empty list is returned if the option does not take a value.
- \sa value()
+ \sa value(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
*/
QStringList QCommandLineParser::values(const QString &optionName) const
{
d->checkParsed("values");
- const NameHash_t::mapped_type optionOffset = d->nameHash.value(optionName, optionNotFound);
- if (optionOffset != optionNotFound) {
+ const NameHash_t::const_iterator it = d->nameHash.find(optionName);
+ if (it != d->nameHash.end()) {
+ const int optionOffset = *it;
QStringList values = d->optionValuesHash.value(optionOffset);
if (values.isEmpty())
values = d->commandLineOptionList.at(optionOffset).defaultValues();
@@ -720,7 +709,14 @@ QStringList QCommandLineParser::values(const QString &optionName) const
/*!
\overload
+ Checks whether the \a option was passed to the application.
+
Returns true if the \a option was set, false otherwise.
+
+ This is the recommended way to check for options with no values.
+
+ Example:
+ \snippet code/src_corelib_tools_qcommandlineparser.cpp 1
*/
bool QCommandLineParser::isSet(const QCommandLineOption &option) const
{
@@ -731,6 +727,14 @@ bool QCommandLineParser::isSet(const QCommandLineOption &option) const
\overload
Returns the option value found for the given \a option, or
an empty string if not found.
+
+ For options found by the parser, the last value found for
+ that option is returned. If the option wasn't specified on the command line,
+ the default value is returned.
+
+ An empty string is returned if the option does not take a value.
+
+ \sa values(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
*/
QString QCommandLineParser::value(const QCommandLineOption &option) const
{
@@ -741,6 +745,14 @@ QString QCommandLineParser::value(const QCommandLineOption &option) const
\overload
Returns a list of option values found for the given \a option,
or an empty list if not found.
+
+ For options found by the parser, the list will contain an entry for
+ each time the option was encountered by the parser. If the option wasn't
+ specified on the command line, the default values are returned.
+
+ An empty list is returned if the option does not take a value.
+
+ \sa value(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
*/
QStringList QCommandLineParser::values(const QCommandLineOption &option) const
{
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index ab5a516e8a..6c8fb85233 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -41,6 +41,7 @@
#include "qplatformdefs.h"
#include "private/qdatetime_p.h"
+#include "private/qdatetimeparser_p.h"
#include "qdatastream.h"
#include "qset.h"
@@ -61,15 +62,6 @@
# endif
#endif
-//#define QDATETIMEPARSER_DEBUG
-#if defined (QDATETIMEPARSER_DEBUG) && !defined(QT_NO_DEBUG_STREAM)
-# define QDTPDEBUG qDebug() << QString("%1:%2").arg(__FILE__).arg(__LINE__)
-# define QDTPDEBUGN qDebug
-#else
-# define QDTPDEBUG if (false) qDebug()
-# define QDTPDEBUGN if (false) qDebug
-#endif
-
#if defined(Q_OS_MAC)
#include <private/qcore_mac_p.h>
#endif
@@ -4460,1710 +4452,4 @@ uint qHash(const QTime &key, uint seed) Q_DECL_NOTHROW
return qHash(QTime(0, 0, 0, 0).msecsTo(key), seed);
}
-#ifndef QT_BOOTSTRAPPED
-
-/*!
- \internal
- Gets the digit from a datetime. E.g.
-
- QDateTime var(QDate(2004, 02, 02));
- int digit = getDigit(var, Year);
- // digit = 2004
-*/
-
-int QDateTimeParser::getDigit(const QDateTime &t, int index) const
-{
- if (index < 0 || index >= sectionNodes.size()) {
-#ifndef QT_NO_DATESTRING
- qWarning("QDateTimeParser::getDigit() Internal error (%s %d)",
- qPrintable(t.toString()), index);
-#else
- qWarning("QDateTimeParser::getDigit() Internal error (%d)", index);
-#endif
- return -1;
- }
- const SectionNode &node = sectionNodes.at(index);
- switch (node.type) {
- case Hour24Section: case Hour12Section: return t.time().hour();
- case MinuteSection: return t.time().minute();
- case SecondSection: return t.time().second();
- case MSecSection: return t.time().msec();
- case YearSection2Digits:
- case YearSection: return t.date().year();
- case MonthSection: return t.date().month();
- case DaySection: return t.date().day();
- case DayOfWeekSectionShort:
- case DayOfWeekSectionLong: return t.date().day();
- case AmPmSection: return t.time().hour() > 11 ? 1 : 0;
-
- default: break;
- }
-
-#ifndef QT_NO_DATESTRING
- qWarning("QDateTimeParser::getDigit() Internal error 2 (%s %d)",
- qPrintable(t.toString()), index);
-#else
- qWarning("QDateTimeParser::getDigit() Internal error 2 (%d)", index);
-#endif
- return -1;
-}
-
-/*!
- \internal
- Sets a digit in a datetime. E.g.
-
- QDateTime var(QDate(2004, 02, 02));
- int digit = getDigit(var, Year);
- // digit = 2004
- setDigit(&var, Year, 2005);
- digit = getDigit(var, Year);
- // digit = 2005
-*/
-
-bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
-{
- if (index < 0 || index >= sectionNodes.size()) {
-#ifndef QT_NO_DATESTRING
- qWarning("QDateTimeParser::setDigit() Internal error (%s %d %d)",
- qPrintable(v.toString()), index, newVal);
-#else
- qWarning("QDateTimeParser::setDigit() Internal error (%d %d)", index, newVal);
-#endif
- return false;
- }
- const SectionNode &node = sectionNodes.at(index);
-
- int year, month, day, hour, minute, second, msec;
- year = v.date().year();
- month = v.date().month();
- day = v.date().day();
- hour = v.time().hour();
- minute = v.time().minute();
- second = v.time().second();
- msec = v.time().msec();
-
- switch (node.type) {
- case Hour24Section: case Hour12Section: hour = newVal; break;
- case MinuteSection: minute = newVal; break;
- case SecondSection: second = newVal; break;
- case MSecSection: msec = newVal; break;
- case YearSection2Digits:
- case YearSection: year = newVal; break;
- case MonthSection: month = newVal; break;
- case DaySection:
- case DayOfWeekSectionShort:
- case DayOfWeekSectionLong:
- if (newVal > 31) {
- // have to keep legacy behavior. setting the
- // date to 32 should return false. Setting it
- // to 31 for february should return true
- return false;
- }
- day = newVal;
- break;
- case AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break;
- default:
- qWarning("QDateTimeParser::setDigit() Internal error (%s)",
- qPrintable(sectionName(node.type)));
- break;
- }
-
- if (!(node.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong))) {
- if (day < cachedDay)
- day = cachedDay;
- const int max = QDate(year, month, 1).daysInMonth();
- if (day > max) {
- day = max;
- }
- }
- if (QDate::isValid(year, month, day) && QTime::isValid(hour, minute, second, msec)) {
- v = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
- return true;
- }
- return false;
-}
-
-
-
-/*!
- \
-
- Returns the absolute maximum for a section
-*/
-
-int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
-{
- const SectionNode &sn = sectionNode(s);
- switch (sn.type) {
- case Hour24Section:
- case Hour12Section: return 23; // this is special-cased in
- // parseSection. We want it to be
- // 23 for the stepBy case.
- case MinuteSection:
- case SecondSection: return 59;
- case MSecSection: return 999;
- case YearSection2Digits:
- case YearSection: return 9999; // sectionMaxSize will prevent
- // people from typing in a larger
- // number in count == 2 sections.
- // stepBy() will work on real years anyway
- case MonthSection: return 12;
- case DaySection:
- case DayOfWeekSectionShort:
- case DayOfWeekSectionLong: return cur.isValid() ? cur.date().daysInMonth() : 31;
- case AmPmSection: return 1;
- default: break;
- }
- qWarning("QDateTimeParser::absoluteMax() Internal error (%s)",
- qPrintable(sectionName(sn.type)));
- return -1;
-}
-
-/*!
- \internal
-
- Returns the absolute minimum for a section
-*/
-
-int QDateTimeParser::absoluteMin(int s) const
-{
- const SectionNode &sn = sectionNode(s);
- switch (sn.type) {
- case Hour24Section:
- case Hour12Section:
- case MinuteSection:
- case SecondSection:
- case MSecSection:
- case YearSection2Digits:
- case YearSection: return 0;
- case MonthSection:
- case DaySection:
- case DayOfWeekSectionShort:
- case DayOfWeekSectionLong: return 1;
- case AmPmSection: return 0;
- default: break;
- }
- qWarning("QDateTimeParser::absoluteMin() Internal error (%s, %0x)",
- qPrintable(sectionName(sn.type)), sn.type);
- return -1;
-}
-
-/*!
- \internal
-
- Returns the sectionNode for the Section \a s.
-*/
-
-const QDateTimeParser::SectionNode &QDateTimeParser::sectionNode(int sectionIndex) const
-{
- if (sectionIndex < 0) {
- switch (sectionIndex) {
- case FirstSectionIndex:
- return first;
- case LastSectionIndex:
- return last;
- case NoSectionIndex:
- return none;
- }
- } else if (sectionIndex < sectionNodes.size()) {
- return sectionNodes.at(sectionIndex);
- }
-
- qWarning("QDateTimeParser::sectionNode() Internal error (%d)",
- sectionIndex);
- return none;
-}
-
-QDateTimeParser::Section QDateTimeParser::sectionType(int sectionIndex) const
-{
- return sectionNode(sectionIndex).type;
-}
-
-
-/*!
- \internal
-
- Returns the starting position for section \a s.
-*/
-
-int QDateTimeParser::sectionPos(int sectionIndex) const
-{
- return sectionPos(sectionNode(sectionIndex));
-}
-
-int QDateTimeParser::sectionPos(const SectionNode &sn) const
-{
- switch (sn.type) {
- case FirstSection: return 0;
- case LastSection: return displayText().size() - 1;
- default: break;
- }
- if (sn.pos == -1) {
- qWarning("QDateTimeParser::sectionPos Internal error (%s)", qPrintable(sectionName(sn.type)));
- return -1;
- }
- return sn.pos;
-}
-
-
-/*!
- \internal
-
- helper function for parseFormat. removes quotes that are
- not escaped and removes the escaping on those that are escaped
-
-*/
-
-static QString unquote(const QString &str)
-{
- const QChar quote(QLatin1Char('\''));
- const QChar slash(QLatin1Char('\\'));
- const QChar zero(QLatin1Char('0'));
- QString ret;
- QChar status(zero);
- const int max = str.size();
- for (int i=0; i<max; ++i) {
- if (str.at(i) == quote) {
- if (status != quote) {
- status = quote;
- } else if (!ret.isEmpty() && str.at(i - 1) == slash) {
- ret[ret.size() - 1] = quote;
- } else {
- status = zero;
- }
- } else {
- ret += str.at(i);
- }
- }
- return ret;
-}
-/*!
- \internal
-
- Parses the format \a newFormat. If successful, returns true and
- sets up the format. Else keeps the old format and returns false.
-
-*/
-
-static inline int countRepeat(const QString &str, int index, int maxCount)
-{
- int count = 1;
- const QChar ch(str.at(index));
- const int max = qMin(index + maxCount, str.size());
- while (index + count < max && str.at(index + count) == ch) {
- ++count;
- }
- return count;
-}
-
-static inline void appendSeparator(QStringList *list, const QString &string, int from, int size, int lastQuote)
-{
- QString str(string.mid(from, size));
- if (lastQuote >= from)
- str = unquote(str);
- list->append(str);
-}
-
-
-bool QDateTimeParser::parseFormat(const QString &newFormat)
-{
- const QLatin1Char quote('\'');
- const QLatin1Char slash('\\');
- const QLatin1Char zero('0');
- if (newFormat == displayFormat && !newFormat.isEmpty()) {
- return true;
- }
-
- QDTPDEBUGN("parseFormat: %s", newFormat.toLatin1().constData());
-
- QVector<SectionNode> newSectionNodes;
- Sections newDisplay = 0;
- QStringList newSeparators;
- int i, index = 0;
- int add = 0;
- QChar status(zero);
- const int max = newFormat.size();
- int lastQuote = -1;
- for (i = 0; i<max; ++i) {
- if (newFormat.at(i) == quote) {
- lastQuote = i;
- ++add;
- if (status != quote) {
- status = quote;
- } else if (newFormat.at(i - 1) != slash) {
- status = zero;
- }
- } else if (status != quote) {
- const char sect = newFormat.at(i).toLatin1();
- switch (sect) {
- case 'H':
- case 'h':
- if (parserType != QVariant::Date) {
- const Section hour = (sect == 'h') ? Hour12Section : Hour24Section;
- const SectionNode sn = { hour, i - add, countRepeat(newFormat, i, 2), 0 };
- newSectionNodes.append(sn);
- appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
- i += sn.count - 1;
- index = i + 1;
- newDisplay |= hour;
- }
- break;
- case 'm':
- if (parserType != QVariant::Date) {
- const SectionNode sn = { MinuteSection, i - add, countRepeat(newFormat, i, 2), 0 };
- newSectionNodes.append(sn);
- appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
- i += sn.count - 1;
- index = i + 1;
- newDisplay |= MinuteSection;
- }
- break;
- case 's':
- if (parserType != QVariant::Date) {
- const SectionNode sn = { SecondSection, i - add, countRepeat(newFormat, i, 2), 0 };
- newSectionNodes.append(sn);
- appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
- i += sn.count - 1;
- index = i + 1;
- newDisplay |= SecondSection;
- }
- break;
-
- case 'z':
- if (parserType != QVariant::Date) {
- const SectionNode sn = { MSecSection, i - add, countRepeat(newFormat, i, 3) < 3 ? 1 : 3, 0 };
- newSectionNodes.append(sn);
- appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
- i += sn.count - 1;
- index = i + 1;
- newDisplay |= MSecSection;
- }
- break;
- case 'A':
- case 'a':
- if (parserType != QVariant::Date) {
- const bool cap = (sect == 'A');
- const SectionNode sn = { AmPmSection, i - add, (cap ? 1 : 0), 0 };
- newSectionNodes.append(sn);
- appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
- newDisplay |= AmPmSection;
- if (i + 1 < newFormat.size()
- && newFormat.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) {
- ++i;
- }
- index = i + 1;
- }
- break;
- case 'y':
- if (parserType != QVariant::Time) {
- const int repeat = countRepeat(newFormat, i, 4);
- if (repeat >= 2) {
- const SectionNode sn = { repeat == 4 ? YearSection : YearSection2Digits,
- i - add, repeat == 4 ? 4 : 2, 0 };
- newSectionNodes.append(sn);
- appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
- i += sn.count - 1;
- index = i + 1;
- newDisplay |= sn.type;
- }
- }
- break;
- case 'M':
- if (parserType != QVariant::Time) {
- const SectionNode sn = { MonthSection, i - add, countRepeat(newFormat, i, 4), 0 };
- newSectionNodes.append(sn);
- newSeparators.append(unquote(newFormat.mid(index, i - index)));
- i += sn.count - 1;
- index = i + 1;
- newDisplay |= MonthSection;
- }
- break;
- case 'd':
- if (parserType != QVariant::Time) {
- const int repeat = countRepeat(newFormat, i, 4);
- const Section sectionType = (repeat == 4 ? DayOfWeekSectionLong
- : (repeat == 3 ? DayOfWeekSectionShort : DaySection));
- const SectionNode sn = { sectionType, i - add, repeat, 0 };
- newSectionNodes.append(sn);
- appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
- i += sn.count - 1;
- index = i + 1;
- newDisplay |= sn.type;
- }
- break;
-
- default:
- break;
- }
- }
- }
- if (newSectionNodes.isEmpty() && context == DateTimeEdit) {
- return false;
- }
-
- if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) {
- const int max = newSectionNodes.size();
- for (int i=0; i<max; ++i) {
- SectionNode &node = newSectionNodes[i];
- if (node.type == Hour12Section)
- node.type = Hour24Section;
- }
- }
-
- if (index < newFormat.size()) {
- appendSeparator(&newSeparators, newFormat, index, index - max, lastQuote);
- } else {
- newSeparators.append(QString());
- }
-
- displayFormat = newFormat;
- separators = newSeparators;
- sectionNodes = newSectionNodes;
- display = newDisplay;
- last.pos = -1;
-
-// for (int i=0; i<sectionNodes.size(); ++i) {
-// QDTPDEBUG << sectionName(sectionNodes.at(i).type) << sectionNodes.at(i).count;
-// }
-
- QDTPDEBUG << newFormat << displayFormat;
- QDTPDEBUGN("separators:\n'%s'", separators.join(QLatin1String("\n")).toLatin1().constData());
-
- return true;
-}
-
-/*!
- \internal
-
- Returns the size of section \a s.
-*/
-
-int QDateTimeParser::sectionSize(int sectionIndex) const
-{
- if (sectionIndex < 0)
- return 0;
-
- if (sectionIndex >= sectionNodes.size()) {
- qWarning("QDateTimeParser::sectionSize Internal error (%d)", sectionIndex);
- return -1;
- }
-
- if (sectionIndex == sectionNodes.size() - 1) {
- // In some cases there is a difference between displayText() and text.
- // e.g. when text is 2000/01/31 and displayText() is "2000/2/31" - text
- // is the previous value and displayText() is the new value.
- // The size difference is always due to leading zeroes.
- int sizeAdjustment = 0;
- if (displayText().size() != text.size()) {
- // Any zeroes added before this section will affect our size.
- int preceedingZeroesAdded = 0;
- if (sectionNodes.size() > 1 && context == DateTimeEdit) {
- for (QVector<SectionNode>::ConstIterator sectionIt = sectionNodes.constBegin();
- sectionIt != sectionNodes.constBegin() + sectionIndex; ++sectionIt) {
- preceedingZeroesAdded += sectionIt->zeroesAdded;
- }
- }
- sizeAdjustment = preceedingZeroesAdded;
- }
-
- return displayText().size() + sizeAdjustment - sectionPos(sectionIndex) - separators.last().size();
- } else {
- return sectionPos(sectionIndex + 1) - sectionPos(sectionIndex)
- - separators.at(sectionIndex + 1).size();
- }
-}
-
-
-int QDateTimeParser::sectionMaxSize(Section s, int count) const
-{
-#ifndef QT_NO_TEXTDATE
- int mcount = 12;
-#endif
-
- switch (s) {
- case FirstSection:
- case NoSection:
- case LastSection: return 0;
-
- case AmPmSection: {
- const int lowerMax = qMin(getAmPmText(AmText, LowerCase).size(),
- getAmPmText(PmText, LowerCase).size());
- const int upperMax = qMin(getAmPmText(AmText, UpperCase).size(),
- getAmPmText(PmText, UpperCase).size());
- return qMin(4, qMin(lowerMax, upperMax));
- }
-
- case Hour24Section:
- case Hour12Section:
- case MinuteSection:
- case SecondSection:
- case DaySection: return 2;
- case DayOfWeekSectionShort:
- case DayOfWeekSectionLong:
-#ifdef QT_NO_TEXTDATE
- return 2;
-#else
- mcount = 7;
- // fall through
-#endif
- case MonthSection:
- if (count <= 2)
- return 2;
-
-#ifdef QT_NO_TEXTDATE
- return 2;
-#else
- {
- int ret = 0;
- const QLocale l = locale();
- for (int i=1; i<=mcount; ++i) {
- const QString str = (s == MonthSection
- ? l.monthName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat)
- : l.dayName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat));
- ret = qMax(str.size(), ret);
- }
- return ret;
- }
-#endif
- case MSecSection: return 3;
- case YearSection: return 4;
- case YearSection2Digits: return 2;
-
- case CalendarPopupSection:
- case Internal:
- case TimeSectionMask:
- case DateSectionMask:
- qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s",
- sectionName(s).toLatin1().constData());
-
- case NoSectionIndex:
- case FirstSectionIndex:
- case LastSectionIndex:
- case CalendarPopupIndex:
- // these cases can't happen
- break;
- }
- return -1;
-}
-
-
-int QDateTimeParser::sectionMaxSize(int index) const
-{
- const SectionNode &sn = sectionNode(index);
- return sectionMaxSize(sn.type, sn.count);
-}
-
-/*!
- \internal
-
- Returns the text of section \a s. This function operates on the
- arg text rather than edit->text().
-*/
-
-
-QString QDateTimeParser::sectionText(const QString &text, int sectionIndex, int index) const
-{
- const SectionNode &sn = sectionNode(sectionIndex);
- switch (sn.type) {
- case NoSectionIndex:
- case FirstSectionIndex:
- case LastSectionIndex:
- return QString();
- default: break;
- }
-
- return text.mid(index, sectionSize(sectionIndex));
-}
-
-QString QDateTimeParser::sectionText(int sectionIndex) const
-{
- const SectionNode &sn = sectionNode(sectionIndex);
- switch (sn.type) {
- case NoSectionIndex:
- case FirstSectionIndex:
- case LastSectionIndex:
- return QString();
- default: break;
- }
-
- return displayText().mid(sn.pos, sectionSize(sectionIndex));
-}
-
-
-#ifndef QT_NO_TEXTDATE
-/*!
- \internal:skipToNextSection
-
- Parses the part of \a text that corresponds to \a s and returns
- the value of that field. Sets *stateptr to the right state if
- stateptr != 0.
-*/
-
-int QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
- QString &text, int &cursorPosition, int index,
- State &state, int *usedptr) const
-{
- state = Invalid;
- int num = 0;
- const SectionNode &sn = sectionNode(sectionIndex);
- if ((sn.type & Internal) == Internal) {
- qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
- qPrintable(sectionName(sn.type)), sectionIndex);
- return -1;
- }
-
- const int sectionmaxsize = sectionMaxSize(sectionIndex);
- QString sectiontext = text.mid(index, sectionmaxsize);
- int sectiontextSize = sectiontext.size();
-
- QDTPDEBUG << "sectionValue for" << sectionName(sn.type)
- << "with text" << text << "and st" << sectiontext
- << text.mid(index, sectionmaxsize)
- << index;
-
- int used = 0;
- switch (sn.type) {
- case AmPmSection: {
- const int ampm = findAmPm(sectiontext, sectionIndex, &used);
- switch (ampm) {
- case AM: // sectiontext == AM
- case PM: // sectiontext == PM
- num = ampm;
- state = Acceptable;
- break;
- case PossibleAM: // sectiontext => AM
- case PossiblePM: // sectiontext => PM
- num = ampm - 2;
- state = Intermediate;
- break;
- case PossibleBoth: // sectiontext => AM|PM
- num = 0;
- state = Intermediate;
- break;
- case Neither:
- state = Invalid;
- QDTPDEBUG << "invalid because findAmPm(" << sectiontext << ") returned -1";
- break;
- default:
- QDTPDEBUGN("This should never happen (findAmPm returned %d)", ampm);
- break;
- }
- if (state != Invalid) {
- QString str = text;
- text.replace(index, used, sectiontext.left(used));
- }
- break; }
- case MonthSection:
- case DayOfWeekSectionShort:
- case DayOfWeekSectionLong:
- if (sn.count >= 3) {
- if (sn.type == MonthSection) {
- int min = 1;
- const QDate minDate = getMinimum().date();
- if (currentValue.date().year() == minDate.year()) {
- min = minDate.month();
- }
- num = findMonth(sectiontext.toLower(), min, sectionIndex, &sectiontext, &used);
- } else {
- num = findDay(sectiontext.toLower(), 1, sectionIndex, &sectiontext, &used);
- }
-
- if (num != -1) {
- state = (used == sectiontext.size() ? Acceptable : Intermediate);
- QString str = text;
- text.replace(index, used, sectiontext.left(used));
- } else {
- state = Intermediate;
- }
- break; }
- // fall through
- case DaySection:
- case YearSection:
- case YearSection2Digits:
- case Hour12Section:
- case Hour24Section:
- case MinuteSection:
- case SecondSection:
- case MSecSection: {
- if (sectiontextSize == 0) {
- num = 0;
- used = 0;
- state = Intermediate;
- } else {
- const int absMax = absoluteMax(sectionIndex);
- QLocale loc;
- bool ok = true;
- int last = -1;
- used = -1;
-
- QString digitsStr(sectiontext);
- for (int i = 0; i < sectiontextSize; ++i) {
- if (digitsStr.at(i).isSpace()) {
- sectiontextSize = i;
- break;
- }
- }
-
- const int max = qMin(sectionmaxsize, sectiontextSize);
- for (int digits = max; digits >= 1; --digits) {
- digitsStr.truncate(digits);
- int tmp = (int)loc.toUInt(digitsStr, &ok);
- if (ok && sn.type == Hour12Section) {
- if (tmp > 12) {
- tmp = -1;
- ok = false;
- } else if (tmp == 12) {
- tmp = 0;
- }
- }
- if (ok && tmp <= absMax) {
- QDTPDEBUG << sectiontext.left(digits) << tmp << digits;
- last = tmp;
- used = digits;
- break;
- }
- }
-
- if (last == -1) {
- QChar first(sectiontext.at(0));
- if (separators.at(sectionIndex + 1).startsWith(first)) {
- used = 0;
- state = Intermediate;
- } else {
- state = Invalid;
- QDTPDEBUG << "invalid because" << sectiontext << "can't become a uint" << last << ok;
- }
- } else {
- num += last;
- const FieldInfo fi = fieldInfo(sectionIndex);
- const bool done = (used == sectionmaxsize);
- if (!done && fi & Fraction) { // typing 2 in a zzz field should be .200, not .002
- for (int i=used; i<sectionmaxsize; ++i) {
- num *= 10;
- }
- }
- const int absMin = absoluteMin(sectionIndex);
- if (num < absMin) {
- state = done ? Invalid : Intermediate;
- if (done)
- QDTPDEBUG << "invalid because" << num << "is less than absoluteMin" << absMin;
- } else if (num > absMax) {
- state = Intermediate;
- } else if (!done && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) {
- if (skipToNextSection(sectionIndex, currentValue, digitsStr)) {
- state = Acceptable;
- const int missingZeroes = sectionmaxsize - digitsStr.size();
- text.insert(index, QString().fill(QLatin1Char('0'), missingZeroes));
- used = sectionmaxsize;
- cursorPosition += missingZeroes;
- ++(const_cast<QDateTimeParser*>(this)->sectionNodes[sectionIndex].zeroesAdded);
- } else {
- state = Intermediate;;
- }
- } else {
- state = Acceptable;
- }
- }
- }
- break; }
- default:
- qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
- qPrintable(sectionName(sn.type)), sectionIndex);
- return -1;
- }
-
- if (usedptr)
- *usedptr = used;
-
- return (state != Invalid ? num : -1);
-}
-#endif // QT_NO_TEXTDATE
-
-#ifndef QT_NO_DATESTRING
-/*!
- \internal
-*/
-
-QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPosition,
- const QDateTime &currentValue, bool fixup) const
-{
- const QDateTime minimum = getMinimum();
- const QDateTime maximum = getMaximum();
-
- State state = Acceptable;
-
- QDateTime newCurrentValue;
- int pos = 0;
- bool conflicts = false;
- const int sectionNodesCount = sectionNodes.size();
-
- QDTPDEBUG << "parse" << input;
- {
- int year, month, day, hour12, hour, minute, second, msec, ampm, dayofweek, year2digits;
- getDateFromJulianDay(currentValue.date().toJulianDay(), &year, &month, &day);
- year2digits = year % 100;
- hour = currentValue.time().hour();
- hour12 = -1;
- minute = currentValue.time().minute();
- second = currentValue.time().second();
- msec = currentValue.time().msec();
- dayofweek = currentValue.date().dayOfWeek();
-
- ampm = -1;
- Sections isSet = NoSection;
- int num;
- State tmpstate;
-
- for (int index=0; state != Invalid && index<sectionNodesCount; ++index) {
- if (QStringRef(&input, pos, separators.at(index).size()) != separators.at(index)) {
- QDTPDEBUG << "invalid because" << input.mid(pos, separators.at(index).size())
- << "!=" << separators.at(index)
- << index << pos << currentSectionIndex;
- state = Invalid;
- goto end;
- }
- pos += separators.at(index).size();
- sectionNodes[index].pos = pos;
- int *current = 0;
- const SectionNode sn = sectionNodes.at(index);
- int used;
-
- num = parseSection(currentValue, index, input, cursorPosition, pos, tmpstate, &used);
- QDTPDEBUG << "sectionValue" << sectionName(sectionType(index)) << input
- << "pos" << pos << "used" << used << stateName(tmpstate);
- if (fixup && tmpstate == Intermediate && used < sn.count) {
- const FieldInfo fi = fieldInfo(index);
- if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) {
- const QString newText = QString::fromLatin1("%1").arg(num, sn.count, 10, QLatin1Char('0'));
- input.replace(pos, used, newText);
- used = sn.count;
- }
- }
- pos += qMax(0, used);
-
- state = qMin<State>(state, tmpstate);
- if (state == Intermediate && context == FromString) {
- state = Invalid;
- break;
- }
-
- QDTPDEBUG << index << sectionName(sectionType(index)) << "is set to"
- << pos << "state is" << stateName(state);
-
-
- if (state != Invalid) {
- switch (sn.type) {
- case Hour24Section: current = &hour; break;
- case Hour12Section: current = &hour12; break;
- case MinuteSection: current = &minute; break;
- case SecondSection: current = &second; break;
- case MSecSection: current = &msec; break;
- case YearSection: current = &year; break;
- case YearSection2Digits: current = &year2digits; break;
- case MonthSection: current = &month; break;
- case DayOfWeekSectionShort:
- case DayOfWeekSectionLong: current = &dayofweek; break;
- case DaySection: current = &day; num = qMax<int>(1, num); break;
- case AmPmSection: current = &ampm; break;
- default:
- qWarning("QDateTimeParser::parse Internal error (%s)",
- qPrintable(sectionName(sn.type)));
- break;
- }
- if (!current) {
- qWarning("QDateTimeParser::parse Internal error 2");
- return StateNode();
- }
- if (isSet & sn.type && *current != num) {
- QDTPDEBUG << "CONFLICT " << sectionName(sn.type) << *current << num;
- conflicts = true;
- if (index != currentSectionIndex || num == -1) {
- continue;
- }
- }
- if (num != -1)
- *current = num;
- isSet |= sn.type;
- }
- }
-
- if (state != Invalid && QStringRef(&input, pos, input.size() - pos) != separators.last()) {
- QDTPDEBUG << "invalid because" << input.mid(pos)
- << "!=" << separators.last() << pos;
- state = Invalid;
- }
-
- if (state != Invalid) {
- if (parserType != QVariant::Time) {
- if (year % 100 != year2digits) {
- switch (isSet & (YearSection2Digits|YearSection)) {
- case YearSection2Digits:
- year = (year / 100) * 100;
- year += year2digits;
- break;
- case ((uint)YearSection2Digits|(uint)YearSection): {
- conflicts = true;
- const SectionNode &sn = sectionNode(currentSectionIndex);
- if (sn.type == YearSection2Digits) {
- year = (year / 100) * 100;
- year += year2digits;
- }
- break; }
- default:
- break;
- }
- }
-
- const QDate date(year, month, day);
- const int diff = dayofweek - date.dayOfWeek();
- if (diff != 0 && state == Acceptable && isSet & (DayOfWeekSectionShort|DayOfWeekSectionLong)) {
- conflicts = isSet & DaySection;
- const SectionNode &sn = sectionNode(currentSectionIndex);
- if (sn.type & (DayOfWeekSectionShort|DayOfWeekSectionLong) || currentSectionIndex == -1) {
- // dayofweek should be preferred
- day += diff;
- if (day <= 0) {
- day += 7;
- } else if (day > date.daysInMonth()) {
- day -= 7;
- }
- QDTPDEBUG << year << month << day << dayofweek
- << diff << QDate(year, month, day).dayOfWeek();
- }
- }
- bool needfixday = false;
- if (sectionType(currentSectionIndex) & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong)) {
- cachedDay = day;
- } else if (cachedDay > day) {
- day = cachedDay;
- needfixday = true;
- }
-
- if (!QDate::isValid(year, month, day)) {
- if (day < 32) {
- cachedDay = day;
- }
- if (day > 28 && QDate::isValid(year, month, 1)) {
- needfixday = true;
- }
- }
- if (needfixday) {
- if (context == FromString) {
- state = Invalid;
- goto end;
- }
- if (state == Acceptable && fixday) {
- day = qMin<int>(day, QDate(year, month, 1).daysInMonth());
-
- const QLocale loc = locale();
- for (int i=0; i<sectionNodesCount; ++i) {
- const Section thisSectionType = sectionType(i);
- if (thisSectionType & (DaySection)) {
- input.replace(sectionPos(i), sectionSize(i), loc.toString(day));
- } else if (thisSectionType & (DayOfWeekSectionShort|DayOfWeekSectionLong)) {
- const int dayOfWeek = QDate(year, month, day).dayOfWeek();
- const QLocale::FormatType dayFormat = (thisSectionType == DayOfWeekSectionShort
- ? QLocale::ShortFormat : QLocale::LongFormat);
- const QString dayName(loc.dayName(dayOfWeek, dayFormat));
- input.replace(sectionPos(i), sectionSize(i), dayName);
- }
- }
- } else {
- state = qMin(Intermediate, state);
- }
- }
- }
-
- if (parserType != QVariant::Date) {
- if (isSet & Hour12Section) {
- const bool hasHour = isSet & Hour24Section;
- if (ampm == -1) {
- if (hasHour) {
- ampm = (hour < 12 ? 0 : 1);
- } else {
- ampm = 0; // no way to tell if this is am or pm so I assume am
- }
- }
- hour12 = (ampm == 0 ? hour12 % 12 : (hour12 % 12) + 12);
- if (!hasHour) {
- hour = hour12;
- } else if (hour != hour12) {
- conflicts = true;
- }
- } else if (ampm != -1) {
- if (!(isSet & (Hour24Section))) {
- hour = (12 * ampm); // special case. Only ap section
- } else if ((ampm == 0) != (hour < 12)) {
- conflicts = true;
- }
- }
-
- }
-
- newCurrentValue = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
- QDTPDEBUG << year << month << day << hour << minute << second << msec;
- }
- QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(),
- newCurrentValue.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")).toLatin1().constData(),
- stateName(state).toLatin1().constData());
- }
-end:
- if (newCurrentValue.isValid()) {
- if (context != FromString && state != Invalid && newCurrentValue < minimum) {
- const QLatin1Char space(' ');
- if (newCurrentValue >= minimum)
- qWarning("QDateTimeParser::parse Internal error 3 (%s %s)",
- qPrintable(newCurrentValue.toString()), qPrintable(minimum.toString()));
-
- bool done = false;
- state = Invalid;
- for (int i=0; i<sectionNodesCount && !done; ++i) {
- const SectionNode &sn = sectionNodes.at(i);
- QString t = sectionText(input, i, sn.pos).toLower();
- if ((t.size() < sectionMaxSize(i) && (((int)fieldInfo(i) & (FixedWidth|Numeric)) != Numeric))
- || t.contains(space)) {
- switch (sn.type) {
- case AmPmSection:
- switch (findAmPm(t, i)) {
- case AM:
- case PM:
- state = Acceptable;
- done = true;
- break;
- case Neither:
- state = Invalid;
- done = true;
- break;
- case PossibleAM:
- case PossiblePM:
- case PossibleBoth: {
- const QDateTime copy(newCurrentValue.addSecs(12 * 60 * 60));
- if (copy >= minimum && copy <= maximum) {
- state = Intermediate;
- done = true;
- }
- break; }
- }
- case MonthSection:
- if (sn.count >= 3) {
- int tmp = newCurrentValue.date().month();
- // I know the first possible month makes the date too early
- while ((tmp = findMonth(t, tmp + 1, i)) != -1) {
- const QDateTime copy(newCurrentValue.addMonths(tmp - newCurrentValue.date().month()));
- if (copy >= minimum && copy <= maximum)
- break; // break out of while
- }
- if (tmp == -1) {
- break;
- }
- state = Intermediate;
- done = true;
- break;
- }
- // fallthrough
- default: {
- int toMin;
- int toMax;
-
- if (sn.type & TimeSectionMask) {
- if (newCurrentValue.daysTo(minimum) != 0) {
- break;
- }
- toMin = newCurrentValue.time().msecsTo(minimum.time());
- if (newCurrentValue.daysTo(maximum) > 0) {
- toMax = -1; // can't get to max
- } else {
- toMax = newCurrentValue.time().msecsTo(maximum.time());
- }
- } else {
- toMin = newCurrentValue.daysTo(minimum);
- toMax = newCurrentValue.daysTo(maximum);
- }
- const int maxChange = QDateTimeParser::maxChange(i);
- if (toMin > maxChange) {
- QDTPDEBUG << "invalid because toMin > maxChange" << toMin
- << maxChange << t << newCurrentValue << minimum;
- state = Invalid;
- done = true;
- break;
- } else if (toMax > maxChange) {
- toMax = -1; // can't get to max
- }
-
- const int min = getDigit(minimum, i);
- if (min == -1) {
- qWarning("QDateTimeParser::parse Internal error 4 (%s)",
- qPrintable(sectionName(sn.type)));
- state = Invalid;
- done = true;
- break;
- }
-
- int max = toMax != -1 ? getDigit(maximum, i) : absoluteMax(i, newCurrentValue);
- int pos = cursorPosition - sn.pos;
- if (pos < 0 || pos >= t.size())
- pos = -1;
- if (!potentialValue(t.simplified(), min, max, i, newCurrentValue, pos)) {
- QDTPDEBUG << "invalid because potentialValue(" << t.simplified() << min << max
- << sectionName(sn.type) << "returned" << toMax << toMin << pos;
- state = Invalid;
- done = true;
- break;
- }
- state = Intermediate;
- done = true;
- break; }
- }
- }
- }
- } else {
- if (context == FromString) {
- // optimization
- Q_ASSERT(getMaximum().date().toJulianDay() == 4642999);
- if (newCurrentValue.date().toJulianDay() > 4642999)
- state = Invalid;
- } else {
- if (newCurrentValue > getMaximum())
- state = Invalid;
- }
-
- QDTPDEBUG << "not checking intermediate because newCurrentValue is" << newCurrentValue << getMinimum() << getMaximum();
- }
- }
- StateNode node;
- node.input = input;
- node.state = state;
- node.conflicts = conflicts;
- node.value = newCurrentValue.toTimeSpec(spec);
- text = input;
- return node;
-}
-#endif // QT_NO_DATESTRING
-
-#ifndef QT_NO_TEXTDATE
-/*!
- \internal
- finds the first possible monthname that \a str1 can
- match. Starting from \a index; str should already by lowered
-*/
-
-int QDateTimeParser::findMonth(const QString &str1, int startMonth, int sectionIndex,
- QString *usedMonth, int *used) const
-{
- int bestMatch = -1;
- int bestCount = 0;
- if (!str1.isEmpty()) {
- const SectionNode &sn = sectionNode(sectionIndex);
- if (sn.type != MonthSection) {
- qWarning("QDateTimeParser::findMonth Internal error");
- return -1;
- }
-
- QLocale::FormatType type = sn.count == 3 ? QLocale::ShortFormat : QLocale::LongFormat;
- QLocale l = locale();
-
- for (int month=startMonth; month<=12; ++month) {
- QString str2 = l.monthName(month, type).toLower();
-
- if (str1.startsWith(str2)) {
- if (used) {
- QDTPDEBUG << "used is set to" << str2.size();
- *used = str2.size();
- }
- if (usedMonth)
- *usedMonth = l.monthName(month, type);
-
- return month;
- }
- if (context == FromString)
- continue;
-
- const int limit = qMin(str1.size(), str2.size());
-
- QDTPDEBUG << "limit is" << limit << str1 << str2;
- bool equal = true;
- for (int i=0; i<limit; ++i) {
- if (str1.at(i) != str2.at(i)) {
- equal = false;
- if (i > bestCount) {
- bestCount = i;
- bestMatch = month;
- }
- break;
- }
- }
- if (equal) {
- if (used)
- *used = limit;
- if (usedMonth)
- *usedMonth = l.monthName(month, type);
- return month;
- }
- }
- if (usedMonth && bestMatch != -1)
- *usedMonth = l.monthName(bestMatch, type);
- }
- if (used) {
- QDTPDEBUG << "used is set to" << bestCount;
- *used = bestCount;
- }
- return bestMatch;
-}
-
-int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex, QString *usedDay, int *used) const
-{
- int bestMatch = -1;
- int bestCount = 0;
- if (!str1.isEmpty()) {
- const SectionNode &sn = sectionNode(sectionIndex);
- if (!(sn.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong))) {
- qWarning("QDateTimeParser::findDay Internal error");
- return -1;
- }
- const QLocale l = locale();
- for (int day=startDay; day<=7; ++day) {
- const QString str2 = l.dayName(day, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat);
-
- if (str1.startsWith(str2.toLower())) {
- if (used)
- *used = str2.size();
- if (usedDay) {
- *usedDay = str2;
- }
- return day;
- }
- if (context == FromString)
- continue;
-
- const int limit = qMin(str1.size(), str2.size());
- bool found = true;
- for (int i=0; i<limit; ++i) {
- if (str1.at(i) != str2.at(i) && !str1.at(i).isSpace()) {
- if (i > bestCount) {
- bestCount = i;
- bestMatch = day;
- }
- found = false;
- break;
- }
-
- }
- if (found) {
- if (used)
- *used = limit;
- if (usedDay)
- *usedDay = str2;
-
- return day;
- }
- }
- if (usedDay && bestMatch != -1) {
- *usedDay = l.dayName(bestMatch, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat);
- }
- }
- if (used)
- *used = bestCount;
-
- return bestMatch;
-}
-#endif // QT_NO_TEXTDATE
-
-/*!
- \internal
-
- returns
- 0 if str == QDateTimeEdit::tr("AM")
- 1 if str == QDateTimeEdit::tr("PM")
- 2 if str can become QDateTimeEdit::tr("AM")
- 3 if str can become QDateTimeEdit::tr("PM")
- 4 if str can become QDateTimeEdit::tr("PM") and can become QDateTimeEdit::tr("AM")
- -1 can't become anything sensible
-
-*/
-
-int QDateTimeParser::findAmPm(QString &str, int index, int *used) const
-{
- const SectionNode &s = sectionNode(index);
- if (s.type != AmPmSection) {
- qWarning("QDateTimeParser::findAmPm Internal error");
- return -1;
- }
- if (used)
- *used = str.size();
- if (str.trimmed().isEmpty()) {
- return PossibleBoth;
- }
- const QLatin1Char space(' ');
- int size = sectionMaxSize(index);
-
- enum {
- amindex = 0,
- pmindex = 1
- };
- QString ampm[2];
- ampm[amindex] = getAmPmText(AmText, s.count == 1 ? UpperCase : LowerCase);
- ampm[pmindex] = getAmPmText(PmText, s.count == 1 ? UpperCase : LowerCase);
- for (int i=0; i<2; ++i)
- ampm[i].truncate(size);
-
- QDTPDEBUG << "findAmPm" << str << ampm[0] << ampm[1];
-
- if (str.indexOf(ampm[amindex], 0, Qt::CaseInsensitive) == 0) {
- str = ampm[amindex];
- return AM;
- } else if (str.indexOf(ampm[pmindex], 0, Qt::CaseInsensitive) == 0) {
- str = ampm[pmindex];
- return PM;
- } else if (context == FromString || (str.count(space) == 0 && str.size() >= size)) {
- return Neither;
- }
- size = qMin(size, str.size());
-
- bool broken[2] = {false, false};
- for (int i=0; i<size; ++i) {
- if (str.at(i) != space) {
- for (int j=0; j<2; ++j) {
- if (!broken[j]) {
- int index = ampm[j].indexOf(str.at(i));
- QDTPDEBUG << "looking for" << str.at(i)
- << "in" << ampm[j] << "and got" << index;
- if (index == -1) {
- if (str.at(i).category() == QChar::Letter_Uppercase) {
- index = ampm[j].indexOf(str.at(i).toLower());
- QDTPDEBUG << "trying with" << str.at(i).toLower()
- << "in" << ampm[j] << "and got" << index;
- } else if (str.at(i).category() == QChar::Letter_Lowercase) {
- index = ampm[j].indexOf(str.at(i).toUpper());
- QDTPDEBUG << "trying with" << str.at(i).toUpper()
- << "in" << ampm[j] << "and got" << index;
- }
- if (index == -1) {
- broken[j] = true;
- if (broken[amindex] && broken[pmindex]) {
- QDTPDEBUG << str << "didn't make it";
- return Neither;
- }
- continue;
- } else {
- str[i] = ampm[j].at(index); // fix case
- }
- }
- ampm[j].remove(index, 1);
- }
- }
- }
- }
- if (!broken[pmindex] && !broken[amindex])
- return PossibleBoth;
- return (!broken[amindex] ? PossibleAM : PossiblePM);
-}
-
-/*!
- \internal
- Max number of units that can be changed by this section.
-*/
-
-int QDateTimeParser::maxChange(int index) const
-{
- const SectionNode &sn = sectionNode(index);
- switch (sn.type) {
- // Time. unit is msec
- case MSecSection: return 999;
- case SecondSection: return 59 * 1000;
- case MinuteSection: return 59 * 60 * 1000;
- case Hour24Section: case Hour12Section: return 59 * 60 * 60 * 1000;
-
- // Date. unit is day
- case DayOfWeekSectionShort:
- case DayOfWeekSectionLong: return 7;
- case DaySection: return 30;
- case MonthSection: return 365 - 31;
- case YearSection: return 9999 * 365;
- case YearSection2Digits: return 100 * 365;
- default:
- qWarning("QDateTimeParser::maxChange() Internal error (%s)",
- qPrintable(sectionName(sectionType(index))));
- }
-
- return -1;
-}
-
-QDateTimeParser::FieldInfo QDateTimeParser::fieldInfo(int index) const
-{
- FieldInfo ret = 0;
- const SectionNode &sn = sectionNode(index);
- const Section s = sn.type;
- switch (s) {
- case MSecSection:
- ret |= Fraction;
- // fallthrough
- case SecondSection:
- case MinuteSection:
- case Hour24Section:
- case Hour12Section:
- case YearSection:
- case YearSection2Digits:
- ret |= Numeric;
- if (s != YearSection) {
- ret |= AllowPartial;
- }
- if (sn.count != 1) {
- ret |= FixedWidth;
- }
- break;
- case MonthSection:
- case DaySection:
- switch (sn.count) {
- case 2:
- ret |= FixedWidth;
- // fallthrough
- case 1:
- ret |= (Numeric|AllowPartial);
- break;
- }
- break;
- case DayOfWeekSectionShort:
- case DayOfWeekSectionLong:
- if (sn.count == 3)
- ret |= FixedWidth;
- break;
- case AmPmSection:
- ret |= FixedWidth;
- break;
- default:
- qWarning("QDateTimeParser::fieldInfo Internal error 2 (%d %s %d)",
- index, qPrintable(sectionName(sn.type)), sn.count);
- break;
- }
- return ret;
-}
-
-/*!
- \internal
-
- Get a number that str can become which is between min
- and max or -1 if this is not possible.
-*/
-
-
-QString QDateTimeParser::sectionFormat(int index) const
-{
- const SectionNode &sn = sectionNode(index);
- return sectionFormat(sn.type, sn.count);
-}
-
-QString QDateTimeParser::sectionFormat(Section s, int count) const
-{
- QChar fillChar;
- switch (s) {
- case AmPmSection: return count == 1 ? QLatin1String("AP") : QLatin1String("ap");
- case MSecSection: fillChar = QLatin1Char('z'); break;
- case SecondSection: fillChar = QLatin1Char('s'); break;
- case MinuteSection: fillChar = QLatin1Char('m'); break;
- case Hour24Section: fillChar = QLatin1Char('H'); break;
- case Hour12Section: fillChar = QLatin1Char('h'); break;
- case DayOfWeekSectionShort:
- case DayOfWeekSectionLong:
- case DaySection: fillChar = QLatin1Char('d'); break;
- case MonthSection: fillChar = QLatin1Char('M'); break;
- case YearSection2Digits:
- case YearSection: fillChar = QLatin1Char('y'); break;
- default:
- qWarning("QDateTimeParser::sectionFormat Internal error (%s)",
- qPrintable(sectionName(s)));
- return QString();
- }
- if (fillChar.isNull()) {
- qWarning("QDateTimeParser::sectionFormat Internal error 2");
- return QString();
- }
-
- QString str;
- str.fill(fillChar, count);
- return str;
-}
-
-
-/*!
- \internal
-
- Returns true if str can be modified to represent a
- number that is within min and max.
-*/
-
-bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int index,
- const QDateTime &currentValue, int insert) const
-{
- if (str.isEmpty()) {
- return true;
- }
- const int size = sectionMaxSize(index);
- int val = (int)locale().toUInt(str);
- const SectionNode &sn = sectionNode(index);
- if (sn.type == YearSection2Digits) {
- val += currentValue.date().year() - (currentValue.date().year() % 100);
- }
- if (val >= min && val <= max && str.size() == size) {
- return true;
- } else if (val > max) {
- return false;
- } else if (str.size() == size && val < min) {
- return false;
- }
-
- const int len = size - str.size();
- for (int i=0; i<len; ++i) {
- for (int j=0; j<10; ++j) {
- if (potentialValue(str + QLatin1Char('0' + j), min, max, index, currentValue, insert)) {
- return true;
- } else if (insert >= 0) {
- QString tmp = str;
- tmp.insert(insert, QLatin1Char('0' + j));
- if (potentialValue(tmp, min, max, index, currentValue, insert))
- return true;
- }
- }
- }
-
- return false;
-}
-
-bool QDateTimeParser::skipToNextSection(int index, const QDateTime &current, const QString &text) const
-{
- Q_ASSERT(current >= getMinimum() && current <= getMaximum());
-
- const SectionNode &node = sectionNode(index);
- Q_ASSERT(text.size() < sectionMaxSize(index));
-
- const QDateTime maximum = getMaximum();
- const QDateTime minimum = getMinimum();
- QDateTime tmp = current;
- int min = absoluteMin(index);
- setDigit(tmp, index, min);
- if (tmp < minimum) {
- min = getDigit(minimum, index);
- }
-
- int max = absoluteMax(index, current);
- setDigit(tmp, index, max);
- if (tmp > maximum) {
- max = getDigit(maximum, index);
- }
- int pos = cursorPosition() - node.pos;
- if (pos < 0 || pos >= text.size())
- pos = -1;
-
- const bool potential = potentialValue(text, min, max, index, current, pos);
- return !potential;
-
- /* If the value potentially can become another valid entry we
- * don't want to skip to the next. E.g. In a M field (month
- * without leading 0 if you type 1 we don't want to autoskip but
- * if you type 3 we do
- */
-}
-
-/*!
- \internal
- For debugging. Returns the name of the section \a s.
-*/
-
-QString QDateTimeParser::sectionName(int s) const
-{
- switch (s) {
- case QDateTimeParser::AmPmSection: return QLatin1String("AmPmSection");
- case QDateTimeParser::DaySection: return QLatin1String("DaySection");
- case QDateTimeParser::DayOfWeekSectionShort: return QLatin1String("DayOfWeekSectionShort");
- case QDateTimeParser::DayOfWeekSectionLong: return QLatin1String("DayOfWeekSectionLong");
- case QDateTimeParser::Hour24Section: return QLatin1String("Hour24Section");
- case QDateTimeParser::Hour12Section: return QLatin1String("Hour12Section");
- case QDateTimeParser::MSecSection: return QLatin1String("MSecSection");
- case QDateTimeParser::MinuteSection: return QLatin1String("MinuteSection");
- case QDateTimeParser::MonthSection: return QLatin1String("MonthSection");
- case QDateTimeParser::SecondSection: return QLatin1String("SecondSection");
- case QDateTimeParser::YearSection: return QLatin1String("YearSection");
- case QDateTimeParser::YearSection2Digits: return QLatin1String("YearSection2Digits");
- case QDateTimeParser::NoSection: return QLatin1String("NoSection");
- case QDateTimeParser::FirstSection: return QLatin1String("FirstSection");
- case QDateTimeParser::LastSection: return QLatin1String("LastSection");
- default: return QLatin1String("Unknown section ") + QString::number(s);
- }
-}
-
-/*!
- \internal
- For debugging. Returns the name of the state \a s.
-*/
-
-QString QDateTimeParser::stateName(int s) const
-{
- switch (s) {
- case Invalid: return QLatin1String("Invalid");
- case Intermediate: return QLatin1String("Intermediate");
- case Acceptable: return QLatin1String("Acceptable");
- default: return QLatin1String("Unknown state ") + QString::number(s);
- }
-}
-
-#ifndef QT_NO_DATESTRING
-bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const
-{
- QDateTime val(QDate(1900, 1, 1), QDATETIMEEDIT_TIME_MIN);
- QString text = t;
- int copy = -1;
- const StateNode tmp = parse(text, copy, val, false);
- if (tmp.state != Acceptable || tmp.conflicts) {
- return false;
- }
- if (time) {
- const QTime t = tmp.value.time();
- if (!t.isValid()) {
- return false;
- }
- *time = t;
- }
-
- if (date) {
- const QDate d = tmp.value.date();
- if (!d.isValid()) {
- return false;
- }
- *date = d;
- }
- return true;
-}
-#endif // QT_NO_DATESTRING
-
-QDateTime QDateTimeParser::getMinimum() const
-{
- return QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, spec);
-}
-
-QDateTime QDateTimeParser::getMaximum() const
-{
- return QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, spec);
-}
-
-QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const
-{
- if (ap == AmText) {
- return (cs == UpperCase ? QLatin1String("AM") : QLatin1String("am"));
- } else {
- return (cs == UpperCase ? QLatin1String("PM") : QLatin1String("pm"));
- }
-}
-
-/*
- \internal
-
- I give arg2 preference because arg1 is always a QDateTime.
-*/
-
-bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2)
-{
- return (s1.type == s2.type) && (s1.pos == s2.pos) && (s1.count == s2.count);
-}
-
-#endif // QT_BOOTSTRAPPED
-
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/tools/qdatetime_p.h
index f3abcf02d8..d466637eb0 100644
--- a/src/corelib/tools/qdatetime_p.h
+++ b/src/corelib/tools/qdatetime_p.h
@@ -56,23 +56,6 @@
#include "qplatformdefs.h"
#include "QtCore/qatomic.h"
#include "QtCore/qdatetime.h"
-#include "QtCore/qstringlist.h"
-#include "QtCore/qlocale.h"
-#ifndef QT_BOOTSTRAPPED
-# include "QtCore/qvariant.h"
-#endif
-#include "QtCore/qvector.h"
-
-
-#define QDATETIMEEDIT_TIME_MIN QTime(0, 0, 0, 0)
-#define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999)
-#define QDATETIMEEDIT_DATE_MIN QDate(100, 1, 1)
-#define QDATETIMEEDIT_COMPAT_DATE_MIN QDate(1752, 9, 14)
-#define QDATETIMEEDIT_DATE_MAX QDate(7999, 12, 31)
-#define QDATETIMEEDIT_DATETIME_MIN QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN)
-#define QDATETIMEEDIT_COMPAT_DATETIME_MIN QDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN, QDATETIMEEDIT_TIME_MIN)
-#define QDATETIMEEDIT_DATETIME_MAX QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX)
-#define QDATETIMEEDIT_DATE_INITIAL QDate(2000, 1, 1)
QT_BEGIN_NAMESPACE
@@ -108,197 +91,6 @@ public:
static inline qint64 maxJd() { return QDate::maxJd(); }
};
-#ifndef QT_BOOTSTRAPPED
-
-class Q_CORE_EXPORT QDateTimeParser
-{
-public:
- enum Context {
- FromString,
- DateTimeEdit
- };
- QDateTimeParser(QVariant::Type t, Context ctx)
- : currentSectionIndex(-1), display(0), cachedDay(-1), parserType(t),
- fixday(false), spec(Qt::LocalTime), context(ctx)
- {
- defaultLocale = QLocale::system();
- first.type = FirstSection;
- first.pos = -1;
- first.count = -1;
- first.zeroesAdded = 0;
- last.type = FirstSection;
- last.pos = -1;
- last.count = -1;
- last.zeroesAdded = 0;
- none.type = NoSection;
- none.pos = -1;
- none.count = -1;
- none.zeroesAdded = 0;
- }
- virtual ~QDateTimeParser() {}
- enum {
- Neither = -1,
- AM = 0,
- PM = 1,
- PossibleAM = 2,
- PossiblePM = 3,
- PossibleBoth = 4
- };
-
- enum Section {
- NoSection = 0x00000,
- AmPmSection = 0x00001,
- MSecSection = 0x00002,
- SecondSection = 0x00004,
- MinuteSection = 0x00008,
- Hour12Section = 0x00010,
- Hour24Section = 0x00020,
- TimeSectionMask = (AmPmSection|MSecSection|SecondSection|MinuteSection|Hour12Section|Hour24Section),
- Internal = 0x10000,
- DaySection = 0x00100,
- MonthSection = 0x00200,
- YearSection = 0x00400,
- YearSection2Digits = 0x00800,
- DayOfWeekSectionShort = 0x01000,
- DayOfWeekSectionLong = 0x20000,
- DateSectionMask = (DaySection|MonthSection|YearSection|YearSection2Digits|DayOfWeekSectionShort|DayOfWeekSectionLong),
- FirstSection = 0x02000|Internal,
- LastSection = 0x04000|Internal,
- CalendarPopupSection = 0x08000|Internal,
-
- NoSectionIndex = -1,
- FirstSectionIndex = -2,
- LastSectionIndex = -3,
- CalendarPopupIndex = -4
- }; // duplicated from qdatetimeedit.h
- Q_DECLARE_FLAGS(Sections, Section)
-
- struct SectionNode {
- Section type;
- mutable int pos;
- int count;
- int zeroesAdded;
- };
-
- enum State { // duplicated from QValidator
- Invalid,
- Intermediate,
- Acceptable
- };
-
- struct StateNode {
- StateNode() : state(Invalid), conflicts(false) {}
- QString input;
- State state;
- bool conflicts;
- QDateTime value;
- };
-
- enum AmPm {
- AmText,
- PmText
- };
-
- enum Case {
- UpperCase,
- LowerCase
- };
-
-#ifndef QT_NO_DATESTRING
- StateNode parse(QString &input, int &cursorPosition, const QDateTime &currentValue, bool fixup) const;
-#endif
- int sectionMaxSize(int index) const;
- int sectionSize(int index) const;
- int sectionMaxSize(Section s, int count) const;
- int sectionPos(int index) const;
- int sectionPos(const SectionNode &sn) const;
-
- const SectionNode &sectionNode(int index) const;
- Section sectionType(int index) const;
- QString sectionText(int sectionIndex) const;
- QString sectionText(const QString &text, int sectionIndex, int index) const;
- int getDigit(const QDateTime &dt, int index) const;
- bool setDigit(QDateTime &t, int index, int newval) const;
- int parseSection(const QDateTime &currentValue, int sectionIndex, QString &txt, int &cursorPosition,
- int index, QDateTimeParser::State &state, int *used = 0) const;
- int absoluteMax(int index, const QDateTime &value = QDateTime()) const;
- int absoluteMin(int index) const;
- bool parseFormat(const QString &format);
-#ifndef QT_NO_DATESTRING
- bool fromString(const QString &text, QDate *date, QTime *time) const;
-#endif
-
-#ifndef QT_NO_TEXTDATE
- int findMonth(const QString &str1, int monthstart, int sectionIndex,
- QString *monthName = 0, int *used = 0) const;
- int findDay(const QString &str1, int intDaystart, int sectionIndex,
- QString *dayName = 0, int *used = 0) const;
-#endif
- int findAmPm(QString &str1, int index, int *used = 0) const;
- int maxChange(int s) const;
- bool potentialValue(const QString &str, int min, int max, int index,
- const QDateTime &currentValue, int insert) const;
- bool skipToNextSection(int section, const QDateTime &current, const QString &sectionText) const;
- QString sectionName(int s) const;
- QString stateName(int s) const;
-
- QString sectionFormat(int index) const;
- QString sectionFormat(Section s, int count) const;
-
- enum FieldInfoFlag {
- Numeric = 0x01,
- FixedWidth = 0x02,
- AllowPartial = 0x04,
- Fraction = 0x08
- };
- Q_DECLARE_FLAGS(FieldInfo, FieldInfoFlag)
-
- FieldInfo fieldInfo(int index) const;
-
- virtual QDateTime getMinimum() const;
- virtual QDateTime getMaximum() const;
- virtual int cursorPosition() const { return -1; }
- virtual QString displayText() const { return text; }
- virtual QString getAmPmText(AmPm ap, Case cs) const;
- virtual QLocale locale() const { return defaultLocale; }
-
- mutable int currentSectionIndex;
- Sections display;
- /*
- This stores the stores the most recently selected day.
- It is useful when considering the following scenario:
-
- 1. Date is: 31/01/2000
- 2. User increments month: 29/02/2000
- 3. User increments month: 31/03/2000
-
- At step 1, cachedDay stores 31. At step 2, the 31 is invalid for February, so the cachedDay is not updated.
- At step 3, the the month is changed to March, for which 31 is a valid day. Since 29 < 31, the day is set to cachedDay.
- This is good for when users have selected their desired day and are scrolling up or down in the month or year section
- and do not want smaller months (or non-leap years) to alter the day that they chose.
- */
- mutable int cachedDay;
- mutable QString text;
- QVector<SectionNode> sectionNodes;
- SectionNode first, last, none, popup;
- QStringList separators;
- QString displayFormat;
- QLocale defaultLocale;
- QVariant::Type parserType;
-
- bool fixday;
-
- Qt::TimeSpec spec; // spec if used by QDateTimeEdit
- Context context;
-};
-
-Q_CORE_EXPORT bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2);
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::Sections)
-Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::FieldInfo)
-
-#endif // QT_BOOTSTRAPPED
-
QT_END_NAMESPACE
#endif // QDATETIME_P_H
diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp
new file mode 100644
index 0000000000..5da0305a69
--- /dev/null
+++ b/src/corelib/tools/qdatetimeparser.cpp
@@ -0,0 +1,1769 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "private/qdatetimeparser_p.h"
+
+#include "qdatastream.h"
+#include "qset.h"
+#include "qlocale.h"
+#include "qdatetime.h"
+#include "qregexp.h"
+#include "qdebug.h"
+
+//#define QDATETIMEPARSER_DEBUG
+#if defined (QDATETIMEPARSER_DEBUG) && !defined(QT_NO_DEBUG_STREAM)
+# define QDTPDEBUG qDebug() << QString("%1:%2").arg(__FILE__).arg(__LINE__)
+# define QDTPDEBUGN qDebug
+#else
+# define QDTPDEBUG if (false) qDebug()
+# define QDTPDEBUGN if (false) qDebug
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_BOOTSTRAPPED
+
+/*!
+ \internal
+ Gets the digit from a datetime. E.g.
+
+ QDateTime var(QDate(2004, 02, 02));
+ int digit = getDigit(var, Year);
+ // digit = 2004
+*/
+
+int QDateTimeParser::getDigit(const QDateTime &t, int index) const
+{
+ if (index < 0 || index >= sectionNodes.size()) {
+#ifndef QT_NO_DATESTRING
+ qWarning("QDateTimeParser::getDigit() Internal error (%s %d)",
+ qPrintable(t.toString()), index);
+#else
+ qWarning("QDateTimeParser::getDigit() Internal error (%d)", index);
+#endif
+ return -1;
+ }
+ const SectionNode &node = sectionNodes.at(index);
+ switch (node.type) {
+ case Hour24Section: case Hour12Section: return t.time().hour();
+ case MinuteSection: return t.time().minute();
+ case SecondSection: return t.time().second();
+ case MSecSection: return t.time().msec();
+ case YearSection2Digits:
+ case YearSection: return t.date().year();
+ case MonthSection: return t.date().month();
+ case DaySection: return t.date().day();
+ case DayOfWeekSectionShort:
+ case DayOfWeekSectionLong: return t.date().day();
+ case AmPmSection: return t.time().hour() > 11 ? 1 : 0;
+
+ default: break;
+ }
+
+#ifndef QT_NO_DATESTRING
+ qWarning("QDateTimeParser::getDigit() Internal error 2 (%s %d)",
+ qPrintable(t.toString()), index);
+#else
+ qWarning("QDateTimeParser::getDigit() Internal error 2 (%d)", index);
+#endif
+ return -1;
+}
+
+/*!
+ \internal
+ Sets a digit in a datetime. E.g.
+
+ QDateTime var(QDate(2004, 02, 02));
+ int digit = getDigit(var, Year);
+ // digit = 2004
+ setDigit(&var, Year, 2005);
+ digit = getDigit(var, Year);
+ // digit = 2005
+*/
+
+bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
+{
+ if (index < 0 || index >= sectionNodes.size()) {
+#ifndef QT_NO_DATESTRING
+ qWarning("QDateTimeParser::setDigit() Internal error (%s %d %d)",
+ qPrintable(v.toString()), index, newVal);
+#else
+ qWarning("QDateTimeParser::setDigit() Internal error (%d %d)", index, newVal);
+#endif
+ return false;
+ }
+ const SectionNode &node = sectionNodes.at(index);
+
+ int year, month, day, hour, minute, second, msec;
+ year = v.date().year();
+ month = v.date().month();
+ day = v.date().day();
+ hour = v.time().hour();
+ minute = v.time().minute();
+ second = v.time().second();
+ msec = v.time().msec();
+
+ switch (node.type) {
+ case Hour24Section: case Hour12Section: hour = newVal; break;
+ case MinuteSection: minute = newVal; break;
+ case SecondSection: second = newVal; break;
+ case MSecSection: msec = newVal; break;
+ case YearSection2Digits:
+ case YearSection: year = newVal; break;
+ case MonthSection: month = newVal; break;
+ case DaySection:
+ case DayOfWeekSectionShort:
+ case DayOfWeekSectionLong:
+ if (newVal > 31) {
+ // have to keep legacy behavior. setting the
+ // date to 32 should return false. Setting it
+ // to 31 for february should return true
+ return false;
+ }
+ day = newVal;
+ break;
+ case AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break;
+ default:
+ qWarning("QDateTimeParser::setDigit() Internal error (%s)",
+ qPrintable(sectionName(node.type)));
+ break;
+ }
+
+ if (!(node.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong))) {
+ if (day < cachedDay)
+ day = cachedDay;
+ const int max = QDate(year, month, 1).daysInMonth();
+ if (day > max) {
+ day = max;
+ }
+ }
+ if (QDate::isValid(year, month, day) && QTime::isValid(hour, minute, second, msec)) {
+ v = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
+ return true;
+ }
+ return false;
+}
+
+
+
+/*!
+ \
+
+ Returns the absolute maximum for a section
+*/
+
+int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
+{
+ const SectionNode &sn = sectionNode(s);
+ switch (sn.type) {
+ case Hour24Section:
+ case Hour12Section: return 23; // this is special-cased in
+ // parseSection. We want it to be
+ // 23 for the stepBy case.
+ case MinuteSection:
+ case SecondSection: return 59;
+ case MSecSection: return 999;
+ case YearSection2Digits:
+ case YearSection: return 9999; // sectionMaxSize will prevent
+ // people from typing in a larger
+ // number in count == 2 sections.
+ // stepBy() will work on real years anyway
+ case MonthSection: return 12;
+ case DaySection:
+ case DayOfWeekSectionShort:
+ case DayOfWeekSectionLong: return cur.isValid() ? cur.date().daysInMonth() : 31;
+ case AmPmSection: return 1;
+ default: break;
+ }
+ qWarning("QDateTimeParser::absoluteMax() Internal error (%s)",
+ qPrintable(sectionName(sn.type)));
+ return -1;
+}
+
+/*!
+ \internal
+
+ Returns the absolute minimum for a section
+*/
+
+int QDateTimeParser::absoluteMin(int s) const
+{
+ const SectionNode &sn = sectionNode(s);
+ switch (sn.type) {
+ case Hour24Section:
+ case Hour12Section:
+ case MinuteSection:
+ case SecondSection:
+ case MSecSection:
+ case YearSection2Digits:
+ case YearSection: return 0;
+ case MonthSection:
+ case DaySection:
+ case DayOfWeekSectionShort:
+ case DayOfWeekSectionLong: return 1;
+ case AmPmSection: return 0;
+ default: break;
+ }
+ qWarning("QDateTimeParser::absoluteMin() Internal error (%s, %0x)",
+ qPrintable(sectionName(sn.type)), sn.type);
+ return -1;
+}
+
+/*!
+ \internal
+
+ Returns the sectionNode for the Section \a s.
+*/
+
+const QDateTimeParser::SectionNode &QDateTimeParser::sectionNode(int sectionIndex) const
+{
+ if (sectionIndex < 0) {
+ switch (sectionIndex) {
+ case FirstSectionIndex:
+ return first;
+ case LastSectionIndex:
+ return last;
+ case NoSectionIndex:
+ return none;
+ }
+ } else if (sectionIndex < sectionNodes.size()) {
+ return sectionNodes.at(sectionIndex);
+ }
+
+ qWarning("QDateTimeParser::sectionNode() Internal error (%d)",
+ sectionIndex);
+ return none;
+}
+
+QDateTimeParser::Section QDateTimeParser::sectionType(int sectionIndex) const
+{
+ return sectionNode(sectionIndex).type;
+}
+
+
+/*!
+ \internal
+
+ Returns the starting position for section \a s.
+*/
+
+int QDateTimeParser::sectionPos(int sectionIndex) const
+{
+ return sectionPos(sectionNode(sectionIndex));
+}
+
+int QDateTimeParser::sectionPos(const SectionNode &sn) const
+{
+ switch (sn.type) {
+ case FirstSection: return 0;
+ case LastSection: return displayText().size() - 1;
+ default: break;
+ }
+ if (sn.pos == -1) {
+ qWarning("QDateTimeParser::sectionPos Internal error (%s)", qPrintable(sectionName(sn.type)));
+ return -1;
+ }
+ return sn.pos;
+}
+
+
+/*!
+ \internal
+
+ helper function for parseFormat. removes quotes that are
+ not escaped and removes the escaping on those that are escaped
+
+*/
+
+static QString unquote(const QString &str)
+{
+ const QChar quote(QLatin1Char('\''));
+ const QChar slash(QLatin1Char('\\'));
+ const QChar zero(QLatin1Char('0'));
+ QString ret;
+ QChar status(zero);
+ const int max = str.size();
+ for (int i=0; i<max; ++i) {
+ if (str.at(i) == quote) {
+ if (status != quote) {
+ status = quote;
+ } else if (!ret.isEmpty() && str.at(i - 1) == slash) {
+ ret[ret.size() - 1] = quote;
+ } else {
+ status = zero;
+ }
+ } else {
+ ret += str.at(i);
+ }
+ }
+ return ret;
+}
+/*!
+ \internal
+
+ Parses the format \a newFormat. If successful, returns true and
+ sets up the format. Else keeps the old format and returns false.
+
+*/
+
+static inline int countRepeat(const QString &str, int index, int maxCount)
+{
+ int count = 1;
+ const QChar ch(str.at(index));
+ const int max = qMin(index + maxCount, str.size());
+ while (index + count < max && str.at(index + count) == ch) {
+ ++count;
+ }
+ return count;
+}
+
+static inline void appendSeparator(QStringList *list, const QString &string, int from, int size, int lastQuote)
+{
+ QString str(string.mid(from, size));
+ if (lastQuote >= from)
+ str = unquote(str);
+ list->append(str);
+}
+
+
+bool QDateTimeParser::parseFormat(const QString &newFormat)
+{
+ const QLatin1Char quote('\'');
+ const QLatin1Char slash('\\');
+ const QLatin1Char zero('0');
+ if (newFormat == displayFormat && !newFormat.isEmpty()) {
+ return true;
+ }
+
+ QDTPDEBUGN("parseFormat: %s", newFormat.toLatin1().constData());
+
+ QVector<SectionNode> newSectionNodes;
+ Sections newDisplay = 0;
+ QStringList newSeparators;
+ int i, index = 0;
+ int add = 0;
+ QChar status(zero);
+ const int max = newFormat.size();
+ int lastQuote = -1;
+ for (i = 0; i<max; ++i) {
+ if (newFormat.at(i) == quote) {
+ lastQuote = i;
+ ++add;
+ if (status != quote) {
+ status = quote;
+ } else if (newFormat.at(i - 1) != slash) {
+ status = zero;
+ }
+ } else if (status != quote) {
+ const char sect = newFormat.at(i).toLatin1();
+ switch (sect) {
+ case 'H':
+ case 'h':
+ if (parserType != QVariant::Date) {
+ const Section hour = (sect == 'h') ? Hour12Section : Hour24Section;
+ const SectionNode sn = { hour, i - add, countRepeat(newFormat, i, 2), 0 };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= hour;
+ }
+ break;
+ case 'm':
+ if (parserType != QVariant::Date) {
+ const SectionNode sn = { MinuteSection, i - add, countRepeat(newFormat, i, 2), 0 };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= MinuteSection;
+ }
+ break;
+ case 's':
+ if (parserType != QVariant::Date) {
+ const SectionNode sn = { SecondSection, i - add, countRepeat(newFormat, i, 2), 0 };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= SecondSection;
+ }
+ break;
+
+ case 'z':
+ if (parserType != QVariant::Date) {
+ const SectionNode sn = { MSecSection, i - add, countRepeat(newFormat, i, 3) < 3 ? 1 : 3, 0 };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= MSecSection;
+ }
+ break;
+ case 'A':
+ case 'a':
+ if (parserType != QVariant::Date) {
+ const bool cap = (sect == 'A');
+ const SectionNode sn = { AmPmSection, i - add, (cap ? 1 : 0), 0 };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ newDisplay |= AmPmSection;
+ if (i + 1 < newFormat.size()
+ && newFormat.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) {
+ ++i;
+ }
+ index = i + 1;
+ }
+ break;
+ case 'y':
+ if (parserType != QVariant::Time) {
+ const int repeat = countRepeat(newFormat, i, 4);
+ if (repeat >= 2) {
+ const SectionNode sn = { repeat == 4 ? YearSection : YearSection2Digits,
+ i - add, repeat == 4 ? 4 : 2, 0 };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= sn.type;
+ }
+ }
+ break;
+ case 'M':
+ if (parserType != QVariant::Time) {
+ const SectionNode sn = { MonthSection, i - add, countRepeat(newFormat, i, 4), 0 };
+ newSectionNodes.append(sn);
+ newSeparators.append(unquote(newFormat.mid(index, i - index)));
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= MonthSection;
+ }
+ break;
+ case 'd':
+ if (parserType != QVariant::Time) {
+ const int repeat = countRepeat(newFormat, i, 4);
+ const Section sectionType = (repeat == 4 ? DayOfWeekSectionLong
+ : (repeat == 3 ? DayOfWeekSectionShort : DaySection));
+ const SectionNode sn = { sectionType, i - add, repeat, 0 };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= sn.type;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ if (newSectionNodes.isEmpty() && context == DateTimeEdit) {
+ return false;
+ }
+
+ if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) {
+ const int max = newSectionNodes.size();
+ for (int i=0; i<max; ++i) {
+ SectionNode &node = newSectionNodes[i];
+ if (node.type == Hour12Section)
+ node.type = Hour24Section;
+ }
+ }
+
+ if (index < newFormat.size()) {
+ appendSeparator(&newSeparators, newFormat, index, index - max, lastQuote);
+ } else {
+ newSeparators.append(QString());
+ }
+
+ displayFormat = newFormat;
+ separators = newSeparators;
+ sectionNodes = newSectionNodes;
+ display = newDisplay;
+ last.pos = -1;
+
+// for (int i=0; i<sectionNodes.size(); ++i) {
+// QDTPDEBUG << sectionName(sectionNodes.at(i).type) << sectionNodes.at(i).count;
+// }
+
+ QDTPDEBUG << newFormat << displayFormat;
+ QDTPDEBUGN("separators:\n'%s'", separators.join(QLatin1String("\n")).toLatin1().constData());
+
+ return true;
+}
+
+/*!
+ \internal
+
+ Returns the size of section \a s.
+*/
+
+int QDateTimeParser::sectionSize(int sectionIndex) const
+{
+ if (sectionIndex < 0)
+ return 0;
+
+ if (sectionIndex >= sectionNodes.size()) {
+ qWarning("QDateTimeParser::sectionSize Internal error (%d)", sectionIndex);
+ return -1;
+ }
+
+ if (sectionIndex == sectionNodes.size() - 1) {
+ // In some cases there is a difference between displayText() and text.
+ // e.g. when text is 2000/01/31 and displayText() is "2000/2/31" - text
+ // is the previous value and displayText() is the new value.
+ // The size difference is always due to leading zeroes.
+ int sizeAdjustment = 0;
+ if (displayText().size() != text.size()) {
+ // Any zeroes added before this section will affect our size.
+ int preceedingZeroesAdded = 0;
+ if (sectionNodes.size() > 1 && context == DateTimeEdit) {
+ for (QVector<SectionNode>::ConstIterator sectionIt = sectionNodes.constBegin();
+ sectionIt != sectionNodes.constBegin() + sectionIndex; ++sectionIt) {
+ preceedingZeroesAdded += sectionIt->zeroesAdded;
+ }
+ }
+ sizeAdjustment = preceedingZeroesAdded;
+ }
+
+ return displayText().size() + sizeAdjustment - sectionPos(sectionIndex) - separators.last().size();
+ } else {
+ return sectionPos(sectionIndex + 1) - sectionPos(sectionIndex)
+ - separators.at(sectionIndex + 1).size();
+ }
+}
+
+
+int QDateTimeParser::sectionMaxSize(Section s, int count) const
+{
+#ifndef QT_NO_TEXTDATE
+ int mcount = 12;
+#endif
+
+ switch (s) {
+ case FirstSection:
+ case NoSection:
+ case LastSection: return 0;
+
+ case AmPmSection: {
+ const int lowerMax = qMin(getAmPmText(AmText, LowerCase).size(),
+ getAmPmText(PmText, LowerCase).size());
+ const int upperMax = qMin(getAmPmText(AmText, UpperCase).size(),
+ getAmPmText(PmText, UpperCase).size());
+ return qMin(4, qMin(lowerMax, upperMax));
+ }
+
+ case Hour24Section:
+ case Hour12Section:
+ case MinuteSection:
+ case SecondSection:
+ case DaySection: return 2;
+ case DayOfWeekSectionShort:
+ case DayOfWeekSectionLong:
+#ifdef QT_NO_TEXTDATE
+ return 2;
+#else
+ mcount = 7;
+ // fall through
+#endif
+ case MonthSection:
+ if (count <= 2)
+ return 2;
+
+#ifdef QT_NO_TEXTDATE
+ return 2;
+#else
+ {
+ int ret = 0;
+ const QLocale l = locale();
+ for (int i=1; i<=mcount; ++i) {
+ const QString str = (s == MonthSection
+ ? l.monthName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat)
+ : l.dayName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat));
+ ret = qMax(str.size(), ret);
+ }
+ return ret;
+ }
+#endif
+ case MSecSection: return 3;
+ case YearSection: return 4;
+ case YearSection2Digits: return 2;
+
+ case CalendarPopupSection:
+ case Internal:
+ case TimeSectionMask:
+ case DateSectionMask:
+ qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s",
+ sectionName(s).toLatin1().constData());
+
+ case NoSectionIndex:
+ case FirstSectionIndex:
+ case LastSectionIndex:
+ case CalendarPopupIndex:
+ // these cases can't happen
+ break;
+ }
+ return -1;
+}
+
+
+int QDateTimeParser::sectionMaxSize(int index) const
+{
+ const SectionNode &sn = sectionNode(index);
+ return sectionMaxSize(sn.type, sn.count);
+}
+
+/*!
+ \internal
+
+ Returns the text of section \a s. This function operates on the
+ arg text rather than edit->text().
+*/
+
+
+QString QDateTimeParser::sectionText(const QString &text, int sectionIndex, int index) const
+{
+ const SectionNode &sn = sectionNode(sectionIndex);
+ switch (sn.type) {
+ case NoSectionIndex:
+ case FirstSectionIndex:
+ case LastSectionIndex:
+ return QString();
+ default: break;
+ }
+
+ return text.mid(index, sectionSize(sectionIndex));
+}
+
+QString QDateTimeParser::sectionText(int sectionIndex) const
+{
+ const SectionNode &sn = sectionNode(sectionIndex);
+ switch (sn.type) {
+ case NoSectionIndex:
+ case FirstSectionIndex:
+ case LastSectionIndex:
+ return QString();
+ default: break;
+ }
+
+ return displayText().mid(sn.pos, sectionSize(sectionIndex));
+}
+
+
+#ifndef QT_NO_TEXTDATE
+/*!
+ \internal:skipToNextSection
+
+ Parses the part of \a text that corresponds to \a s and returns
+ the value of that field. Sets *stateptr to the right state if
+ stateptr != 0.
+*/
+
+int QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
+ QString &text, int &cursorPosition, int index,
+ State &state, int *usedptr) const
+{
+ state = Invalid;
+ int num = 0;
+ const SectionNode &sn = sectionNode(sectionIndex);
+ if ((sn.type & Internal) == Internal) {
+ qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
+ qPrintable(sectionName(sn.type)), sectionIndex);
+ return -1;
+ }
+
+ const int sectionmaxsize = sectionMaxSize(sectionIndex);
+ QString sectiontext = text.mid(index, sectionmaxsize);
+ int sectiontextSize = sectiontext.size();
+
+ QDTPDEBUG << "sectionValue for" << sectionName(sn.type)
+ << "with text" << text << "and st" << sectiontext
+ << text.mid(index, sectionmaxsize)
+ << index;
+
+ int used = 0;
+ switch (sn.type) {
+ case AmPmSection: {
+ const int ampm = findAmPm(sectiontext, sectionIndex, &used);
+ switch (ampm) {
+ case AM: // sectiontext == AM
+ case PM: // sectiontext == PM
+ num = ampm;
+ state = Acceptable;
+ break;
+ case PossibleAM: // sectiontext => AM
+ case PossiblePM: // sectiontext => PM
+ num = ampm - 2;
+ state = Intermediate;
+ break;
+ case PossibleBoth: // sectiontext => AM|PM
+ num = 0;
+ state = Intermediate;
+ break;
+ case Neither:
+ state = Invalid;
+ QDTPDEBUG << "invalid because findAmPm(" << sectiontext << ") returned -1";
+ break;
+ default:
+ QDTPDEBUGN("This should never happen (findAmPm returned %d)", ampm);
+ break;
+ }
+ if (state != Invalid) {
+ QString str = text;
+ text.replace(index, used, sectiontext.left(used));
+ }
+ break; }
+ case MonthSection:
+ case DayOfWeekSectionShort:
+ case DayOfWeekSectionLong:
+ if (sn.count >= 3) {
+ if (sn.type == MonthSection) {
+ int min = 1;
+ const QDate minDate = getMinimum().date();
+ if (currentValue.date().year() == minDate.year()) {
+ min = minDate.month();
+ }
+ num = findMonth(sectiontext.toLower(), min, sectionIndex, &sectiontext, &used);
+ } else {
+ num = findDay(sectiontext.toLower(), 1, sectionIndex, &sectiontext, &used);
+ }
+
+ if (num != -1) {
+ state = (used == sectiontext.size() ? Acceptable : Intermediate);
+ QString str = text;
+ text.replace(index, used, sectiontext.left(used));
+ } else {
+ state = Intermediate;
+ }
+ break; }
+ // fall through
+ case DaySection:
+ case YearSection:
+ case YearSection2Digits:
+ case Hour12Section:
+ case Hour24Section:
+ case MinuteSection:
+ case SecondSection:
+ case MSecSection: {
+ if (sectiontextSize == 0) {
+ num = 0;
+ used = 0;
+ state = Intermediate;
+ } else {
+ const int absMax = absoluteMax(sectionIndex);
+ QLocale loc;
+ bool ok = true;
+ int last = -1;
+ used = -1;
+
+ QString digitsStr(sectiontext);
+ for (int i = 0; i < sectiontextSize; ++i) {
+ if (digitsStr.at(i).isSpace()) {
+ sectiontextSize = i;
+ break;
+ }
+ }
+
+ const int max = qMin(sectionmaxsize, sectiontextSize);
+ for (int digits = max; digits >= 1; --digits) {
+ digitsStr.truncate(digits);
+ int tmp = (int)loc.toUInt(digitsStr, &ok);
+ if (ok && sn.type == Hour12Section) {
+ if (tmp > 12) {
+ tmp = -1;
+ ok = false;
+ } else if (tmp == 12) {
+ tmp = 0;
+ }
+ }
+ if (ok && tmp <= absMax) {
+ QDTPDEBUG << sectiontext.left(digits) << tmp << digits;
+ last = tmp;
+ used = digits;
+ break;
+ }
+ }
+
+ if (last == -1) {
+ QChar first(sectiontext.at(0));
+ if (separators.at(sectionIndex + 1).startsWith(first)) {
+ used = 0;
+ state = Intermediate;
+ } else {
+ state = Invalid;
+ QDTPDEBUG << "invalid because" << sectiontext << "can't become a uint" << last << ok;
+ }
+ } else {
+ num += last;
+ const FieldInfo fi = fieldInfo(sectionIndex);
+ const bool done = (used == sectionmaxsize);
+ if (!done && fi & Fraction) { // typing 2 in a zzz field should be .200, not .002
+ for (int i=used; i<sectionmaxsize; ++i) {
+ num *= 10;
+ }
+ }
+ const int absMin = absoluteMin(sectionIndex);
+ if (num < absMin) {
+ state = done ? Invalid : Intermediate;
+ if (done)
+ QDTPDEBUG << "invalid because" << num << "is less than absoluteMin" << absMin;
+ } else if (num > absMax) {
+ state = Intermediate;
+ } else if (!done && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) {
+ if (skipToNextSection(sectionIndex, currentValue, digitsStr)) {
+ state = Acceptable;
+ const int missingZeroes = sectionmaxsize - digitsStr.size();
+ text.insert(index, QString().fill(QLatin1Char('0'), missingZeroes));
+ used = sectionmaxsize;
+ cursorPosition += missingZeroes;
+ ++(const_cast<QDateTimeParser*>(this)->sectionNodes[sectionIndex].zeroesAdded);
+ } else {
+ state = Intermediate;;
+ }
+ } else {
+ state = Acceptable;
+ }
+ }
+ }
+ break; }
+ default:
+ qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
+ qPrintable(sectionName(sn.type)), sectionIndex);
+ return -1;
+ }
+
+ if (usedptr)
+ *usedptr = used;
+
+ return (state != Invalid ? num : -1);
+}
+#endif // QT_NO_TEXTDATE
+
+#ifndef QT_NO_DATESTRING
+/*!
+ \internal
+*/
+
+QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPosition,
+ const QDateTime &currentValue, bool fixup) const
+{
+ const QDateTime minimum = getMinimum();
+ const QDateTime maximum = getMaximum();
+
+ State state = Acceptable;
+
+ QDateTime newCurrentValue;
+ int pos = 0;
+ bool conflicts = false;
+ const int sectionNodesCount = sectionNodes.size();
+
+ QDTPDEBUG << "parse" << input;
+ {
+ int year, month, day, hour12, hour, minute, second, msec, ampm, dayofweek, year2digits;
+ currentValue.date().getDate(&year, &month, &day);
+ year2digits = year % 100;
+ hour = currentValue.time().hour();
+ hour12 = -1;
+ minute = currentValue.time().minute();
+ second = currentValue.time().second();
+ msec = currentValue.time().msec();
+ dayofweek = currentValue.date().dayOfWeek();
+
+ ampm = -1;
+ Sections isSet = NoSection;
+ int num;
+ State tmpstate;
+
+ for (int index=0; state != Invalid && index<sectionNodesCount; ++index) {
+ if (QStringRef(&input, pos, separators.at(index).size()) != separators.at(index)) {
+ QDTPDEBUG << "invalid because" << input.mid(pos, separators.at(index).size())
+ << "!=" << separators.at(index)
+ << index << pos << currentSectionIndex;
+ state = Invalid;
+ goto end;
+ }
+ pos += separators.at(index).size();
+ sectionNodes[index].pos = pos;
+ int *current = 0;
+ const SectionNode sn = sectionNodes.at(index);
+ int used;
+
+ num = parseSection(currentValue, index, input, cursorPosition, pos, tmpstate, &used);
+ QDTPDEBUG << "sectionValue" << sectionName(sectionType(index)) << input
+ << "pos" << pos << "used" << used << stateName(tmpstate);
+ if (fixup && tmpstate == Intermediate && used < sn.count) {
+ const FieldInfo fi = fieldInfo(index);
+ if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) {
+ const QString newText = QString::fromLatin1("%1").arg(num, sn.count, 10, QLatin1Char('0'));
+ input.replace(pos, used, newText);
+ used = sn.count;
+ }
+ }
+ pos += qMax(0, used);
+
+ state = qMin<State>(state, tmpstate);
+ if (state == Intermediate && context == FromString) {
+ state = Invalid;
+ break;
+ }
+
+ QDTPDEBUG << index << sectionName(sectionType(index)) << "is set to"
+ << pos << "state is" << stateName(state);
+
+
+ if (state != Invalid) {
+ switch (sn.type) {
+ case Hour24Section: current = &hour; break;
+ case Hour12Section: current = &hour12; break;
+ case MinuteSection: current = &minute; break;
+ case SecondSection: current = &second; break;
+ case MSecSection: current = &msec; break;
+ case YearSection: current = &year; break;
+ case YearSection2Digits: current = &year2digits; break;
+ case MonthSection: current = &month; break;
+ case DayOfWeekSectionShort:
+ case DayOfWeekSectionLong: current = &dayofweek; break;
+ case DaySection: current = &day; num = qMax<int>(1, num); break;
+ case AmPmSection: current = &ampm; break;
+ default:
+ qWarning("QDateTimeParser::parse Internal error (%s)",
+ qPrintable(sectionName(sn.type)));
+ break;
+ }
+ if (!current) {
+ qWarning("QDateTimeParser::parse Internal error 2");
+ return StateNode();
+ }
+ if (isSet & sn.type && *current != num) {
+ QDTPDEBUG << "CONFLICT " << sectionName(sn.type) << *current << num;
+ conflicts = true;
+ if (index != currentSectionIndex || num == -1) {
+ continue;
+ }
+ }
+ if (num != -1)
+ *current = num;
+ isSet |= sn.type;
+ }
+ }
+
+ if (state != Invalid && QStringRef(&input, pos, input.size() - pos) != separators.last()) {
+ QDTPDEBUG << "invalid because" << input.mid(pos)
+ << "!=" << separators.last() << pos;
+ state = Invalid;
+ }
+
+ if (state != Invalid) {
+ if (parserType != QVariant::Time) {
+ if (year % 100 != year2digits) {
+ switch (isSet & (YearSection2Digits|YearSection)) {
+ case YearSection2Digits:
+ year = (year / 100) * 100;
+ year += year2digits;
+ break;
+ case ((uint)YearSection2Digits|(uint)YearSection): {
+ conflicts = true;
+ const SectionNode &sn = sectionNode(currentSectionIndex);
+ if (sn.type == YearSection2Digits) {
+ year = (year / 100) * 100;
+ year += year2digits;
+ }
+ break; }
+ default:
+ break;
+ }
+ }
+
+ const QDate date(year, month, day);
+ const int diff = dayofweek - date.dayOfWeek();
+ if (diff != 0 && state == Acceptable && isSet & (DayOfWeekSectionShort|DayOfWeekSectionLong)) {
+ conflicts = isSet & DaySection;
+ const SectionNode &sn = sectionNode(currentSectionIndex);
+ if (sn.type & (DayOfWeekSectionShort|DayOfWeekSectionLong) || currentSectionIndex == -1) {
+ // dayofweek should be preferred
+ day += diff;
+ if (day <= 0) {
+ day += 7;
+ } else if (day > date.daysInMonth()) {
+ day -= 7;
+ }
+ QDTPDEBUG << year << month << day << dayofweek
+ << diff << QDate(year, month, day).dayOfWeek();
+ }
+ }
+ bool needfixday = false;
+ if (sectionType(currentSectionIndex) & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong)) {
+ cachedDay = day;
+ } else if (cachedDay > day) {
+ day = cachedDay;
+ needfixday = true;
+ }
+
+ if (!QDate::isValid(year, month, day)) {
+ if (day < 32) {
+ cachedDay = day;
+ }
+ if (day > 28 && QDate::isValid(year, month, 1)) {
+ needfixday = true;
+ }
+ }
+ if (needfixday) {
+ if (context == FromString) {
+ state = Invalid;
+ goto end;
+ }
+ if (state == Acceptable && fixday) {
+ day = qMin<int>(day, QDate(year, month, 1).daysInMonth());
+
+ const QLocale loc = locale();
+ for (int i=0; i<sectionNodesCount; ++i) {
+ const Section thisSectionType = sectionType(i);
+ if (thisSectionType & (DaySection)) {
+ input.replace(sectionPos(i), sectionSize(i), loc.toString(day));
+ } else if (thisSectionType & (DayOfWeekSectionShort|DayOfWeekSectionLong)) {
+ const int dayOfWeek = QDate(year, month, day).dayOfWeek();
+ const QLocale::FormatType dayFormat = (thisSectionType == DayOfWeekSectionShort
+ ? QLocale::ShortFormat : QLocale::LongFormat);
+ const QString dayName(loc.dayName(dayOfWeek, dayFormat));
+ input.replace(sectionPos(i), sectionSize(i), dayName);
+ }
+ }
+ } else {
+ state = qMin(Intermediate, state);
+ }
+ }
+ }
+
+ if (parserType != QVariant::Date) {
+ if (isSet & Hour12Section) {
+ const bool hasHour = isSet & Hour24Section;
+ if (ampm == -1) {
+ if (hasHour) {
+ ampm = (hour < 12 ? 0 : 1);
+ } else {
+ ampm = 0; // no way to tell if this is am or pm so I assume am
+ }
+ }
+ hour12 = (ampm == 0 ? hour12 % 12 : (hour12 % 12) + 12);
+ if (!hasHour) {
+ hour = hour12;
+ } else if (hour != hour12) {
+ conflicts = true;
+ }
+ } else if (ampm != -1) {
+ if (!(isSet & (Hour24Section))) {
+ hour = (12 * ampm); // special case. Only ap section
+ } else if ((ampm == 0) != (hour < 12)) {
+ conflicts = true;
+ }
+ }
+
+ }
+
+ newCurrentValue = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
+ QDTPDEBUG << year << month << day << hour << minute << second << msec;
+ }
+ QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(),
+ newCurrentValue.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")).toLatin1().constData(),
+ stateName(state).toLatin1().constData());
+ }
+end:
+ if (newCurrentValue.isValid()) {
+ if (context != FromString && state != Invalid && newCurrentValue < minimum) {
+ const QLatin1Char space(' ');
+ if (newCurrentValue >= minimum)
+ qWarning("QDateTimeParser::parse Internal error 3 (%s %s)",
+ qPrintable(newCurrentValue.toString()), qPrintable(minimum.toString()));
+
+ bool done = false;
+ state = Invalid;
+ for (int i=0; i<sectionNodesCount && !done; ++i) {
+ const SectionNode &sn = sectionNodes.at(i);
+ QString t = sectionText(input, i, sn.pos).toLower();
+ if ((t.size() < sectionMaxSize(i) && (((int)fieldInfo(i) & (FixedWidth|Numeric)) != Numeric))
+ || t.contains(space)) {
+ switch (sn.type) {
+ case AmPmSection:
+ switch (findAmPm(t, i)) {
+ case AM:
+ case PM:
+ state = Acceptable;
+ done = true;
+ break;
+ case Neither:
+ state = Invalid;
+ done = true;
+ break;
+ case PossibleAM:
+ case PossiblePM:
+ case PossibleBoth: {
+ const QDateTime copy(newCurrentValue.addSecs(12 * 60 * 60));
+ if (copy >= minimum && copy <= maximum) {
+ state = Intermediate;
+ done = true;
+ }
+ break; }
+ }
+ case MonthSection:
+ if (sn.count >= 3) {
+ int tmp = newCurrentValue.date().month();
+ // I know the first possible month makes the date too early
+ while ((tmp = findMonth(t, tmp + 1, i)) != -1) {
+ const QDateTime copy(newCurrentValue.addMonths(tmp - newCurrentValue.date().month()));
+ if (copy >= minimum && copy <= maximum)
+ break; // break out of while
+ }
+ if (tmp == -1) {
+ break;
+ }
+ state = Intermediate;
+ done = true;
+ break;
+ }
+ // fallthrough
+ default: {
+ int toMin;
+ int toMax;
+
+ if (sn.type & TimeSectionMask) {
+ if (newCurrentValue.daysTo(minimum) != 0) {
+ break;
+ }
+ toMin = newCurrentValue.time().msecsTo(minimum.time());
+ if (newCurrentValue.daysTo(maximum) > 0) {
+ toMax = -1; // can't get to max
+ } else {
+ toMax = newCurrentValue.time().msecsTo(maximum.time());
+ }
+ } else {
+ toMin = newCurrentValue.daysTo(minimum);
+ toMax = newCurrentValue.daysTo(maximum);
+ }
+ const int maxChange = QDateTimeParser::maxChange(i);
+ if (toMin > maxChange) {
+ QDTPDEBUG << "invalid because toMin > maxChange" << toMin
+ << maxChange << t << newCurrentValue << minimum;
+ state = Invalid;
+ done = true;
+ break;
+ } else if (toMax > maxChange) {
+ toMax = -1; // can't get to max
+ }
+
+ const int min = getDigit(minimum, i);
+ if (min == -1) {
+ qWarning("QDateTimeParser::parse Internal error 4 (%s)",
+ qPrintable(sectionName(sn.type)));
+ state = Invalid;
+ done = true;
+ break;
+ }
+
+ int max = toMax != -1 ? getDigit(maximum, i) : absoluteMax(i, newCurrentValue);
+ int pos = cursorPosition - sn.pos;
+ if (pos < 0 || pos >= t.size())
+ pos = -1;
+ if (!potentialValue(t.simplified(), min, max, i, newCurrentValue, pos)) {
+ QDTPDEBUG << "invalid because potentialValue(" << t.simplified() << min << max
+ << sectionName(sn.type) << "returned" << toMax << toMin << pos;
+ state = Invalid;
+ done = true;
+ break;
+ }
+ state = Intermediate;
+ done = true;
+ break; }
+ }
+ }
+ }
+ } else {
+ if (context == FromString) {
+ // optimization
+ Q_ASSERT(getMaximum().date().toJulianDay() == 4642999);
+ if (newCurrentValue.date().toJulianDay() > 4642999)
+ state = Invalid;
+ } else {
+ if (newCurrentValue > getMaximum())
+ state = Invalid;
+ }
+
+ QDTPDEBUG << "not checking intermediate because newCurrentValue is" << newCurrentValue << getMinimum() << getMaximum();
+ }
+ }
+ StateNode node;
+ node.input = input;
+ node.state = state;
+ node.conflicts = conflicts;
+ node.value = newCurrentValue.toTimeSpec(spec);
+ text = input;
+ return node;
+}
+#endif // QT_NO_DATESTRING
+
+#ifndef QT_NO_TEXTDATE
+/*!
+ \internal
+ finds the first possible monthname that \a str1 can
+ match. Starting from \a index; str should already by lowered
+*/
+
+int QDateTimeParser::findMonth(const QString &str1, int startMonth, int sectionIndex,
+ QString *usedMonth, int *used) const
+{
+ int bestMatch = -1;
+ int bestCount = 0;
+ if (!str1.isEmpty()) {
+ const SectionNode &sn = sectionNode(sectionIndex);
+ if (sn.type != MonthSection) {
+ qWarning("QDateTimeParser::findMonth Internal error");
+ return -1;
+ }
+
+ QLocale::FormatType type = sn.count == 3 ? QLocale::ShortFormat : QLocale::LongFormat;
+ QLocale l = locale();
+
+ for (int month=startMonth; month<=12; ++month) {
+ QString str2 = l.monthName(month, type).toLower();
+
+ if (str1.startsWith(str2)) {
+ if (used) {
+ QDTPDEBUG << "used is set to" << str2.size();
+ *used = str2.size();
+ }
+ if (usedMonth)
+ *usedMonth = l.monthName(month, type);
+
+ return month;
+ }
+ if (context == FromString)
+ continue;
+
+ const int limit = qMin(str1.size(), str2.size());
+
+ QDTPDEBUG << "limit is" << limit << str1 << str2;
+ bool equal = true;
+ for (int i=0; i<limit; ++i) {
+ if (str1.at(i) != str2.at(i)) {
+ equal = false;
+ if (i > bestCount) {
+ bestCount = i;
+ bestMatch = month;
+ }
+ break;
+ }
+ }
+ if (equal) {
+ if (used)
+ *used = limit;
+ if (usedMonth)
+ *usedMonth = l.monthName(month, type);
+ return month;
+ }
+ }
+ if (usedMonth && bestMatch != -1)
+ *usedMonth = l.monthName(bestMatch, type);
+ }
+ if (used) {
+ QDTPDEBUG << "used is set to" << bestCount;
+ *used = bestCount;
+ }
+ return bestMatch;
+}
+
+int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex, QString *usedDay, int *used) const
+{
+ int bestMatch = -1;
+ int bestCount = 0;
+ if (!str1.isEmpty()) {
+ const SectionNode &sn = sectionNode(sectionIndex);
+ if (!(sn.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong))) {
+ qWarning("QDateTimeParser::findDay Internal error");
+ return -1;
+ }
+ const QLocale l = locale();
+ for (int day=startDay; day<=7; ++day) {
+ const QString str2 = l.dayName(day, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat);
+
+ if (str1.startsWith(str2.toLower())) {
+ if (used)
+ *used = str2.size();
+ if (usedDay) {
+ *usedDay = str2;
+ }
+ return day;
+ }
+ if (context == FromString)
+ continue;
+
+ const int limit = qMin(str1.size(), str2.size());
+ bool found = true;
+ for (int i=0; i<limit; ++i) {
+ if (str1.at(i) != str2.at(i) && !str1.at(i).isSpace()) {
+ if (i > bestCount) {
+ bestCount = i;
+ bestMatch = day;
+ }
+ found = false;
+ break;
+ }
+
+ }
+ if (found) {
+ if (used)
+ *used = limit;
+ if (usedDay)
+ *usedDay = str2;
+
+ return day;
+ }
+ }
+ if (usedDay && bestMatch != -1) {
+ *usedDay = l.dayName(bestMatch, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat);
+ }
+ }
+ if (used)
+ *used = bestCount;
+
+ return bestMatch;
+}
+#endif // QT_NO_TEXTDATE
+
+/*!
+ \internal
+
+ returns
+ 0 if str == QDateTimeEdit::tr("AM")
+ 1 if str == QDateTimeEdit::tr("PM")
+ 2 if str can become QDateTimeEdit::tr("AM")
+ 3 if str can become QDateTimeEdit::tr("PM")
+ 4 if str can become QDateTimeEdit::tr("PM") and can become QDateTimeEdit::tr("AM")
+ -1 can't become anything sensible
+
+*/
+
+int QDateTimeParser::findAmPm(QString &str, int index, int *used) const
+{
+ const SectionNode &s = sectionNode(index);
+ if (s.type != AmPmSection) {
+ qWarning("QDateTimeParser::findAmPm Internal error");
+ return -1;
+ }
+ if (used)
+ *used = str.size();
+ if (str.trimmed().isEmpty()) {
+ return PossibleBoth;
+ }
+ const QLatin1Char space(' ');
+ int size = sectionMaxSize(index);
+
+ enum {
+ amindex = 0,
+ pmindex = 1
+ };
+ QString ampm[2];
+ ampm[amindex] = getAmPmText(AmText, s.count == 1 ? UpperCase : LowerCase);
+ ampm[pmindex] = getAmPmText(PmText, s.count == 1 ? UpperCase : LowerCase);
+ for (int i=0; i<2; ++i)
+ ampm[i].truncate(size);
+
+ QDTPDEBUG << "findAmPm" << str << ampm[0] << ampm[1];
+
+ if (str.indexOf(ampm[amindex], 0, Qt::CaseInsensitive) == 0) {
+ str = ampm[amindex];
+ return AM;
+ } else if (str.indexOf(ampm[pmindex], 0, Qt::CaseInsensitive) == 0) {
+ str = ampm[pmindex];
+ return PM;
+ } else if (context == FromString || (str.count(space) == 0 && str.size() >= size)) {
+ return Neither;
+ }
+ size = qMin(size, str.size());
+
+ bool broken[2] = {false, false};
+ for (int i=0; i<size; ++i) {
+ if (str.at(i) != space) {
+ for (int j=0; j<2; ++j) {
+ if (!broken[j]) {
+ int index = ampm[j].indexOf(str.at(i));
+ QDTPDEBUG << "looking for" << str.at(i)
+ << "in" << ampm[j] << "and got" << index;
+ if (index == -1) {
+ if (str.at(i).category() == QChar::Letter_Uppercase) {
+ index = ampm[j].indexOf(str.at(i).toLower());
+ QDTPDEBUG << "trying with" << str.at(i).toLower()
+ << "in" << ampm[j] << "and got" << index;
+ } else if (str.at(i).category() == QChar::Letter_Lowercase) {
+ index = ampm[j].indexOf(str.at(i).toUpper());
+ QDTPDEBUG << "trying with" << str.at(i).toUpper()
+ << "in" << ampm[j] << "and got" << index;
+ }
+ if (index == -1) {
+ broken[j] = true;
+ if (broken[amindex] && broken[pmindex]) {
+ QDTPDEBUG << str << "didn't make it";
+ return Neither;
+ }
+ continue;
+ } else {
+ str[i] = ampm[j].at(index); // fix case
+ }
+ }
+ ampm[j].remove(index, 1);
+ }
+ }
+ }
+ }
+ if (!broken[pmindex] && !broken[amindex])
+ return PossibleBoth;
+ return (!broken[amindex] ? PossibleAM : PossiblePM);
+}
+
+/*!
+ \internal
+ Max number of units that can be changed by this section.
+*/
+
+int QDateTimeParser::maxChange(int index) const
+{
+ const SectionNode &sn = sectionNode(index);
+ switch (sn.type) {
+ // Time. unit is msec
+ case MSecSection: return 999;
+ case SecondSection: return 59 * 1000;
+ case MinuteSection: return 59 * 60 * 1000;
+ case Hour24Section: case Hour12Section: return 59 * 60 * 60 * 1000;
+
+ // Date. unit is day
+ case DayOfWeekSectionShort:
+ case DayOfWeekSectionLong: return 7;
+ case DaySection: return 30;
+ case MonthSection: return 365 - 31;
+ case YearSection: return 9999 * 365;
+ case YearSection2Digits: return 100 * 365;
+ default:
+ qWarning("QDateTimeParser::maxChange() Internal error (%s)",
+ qPrintable(sectionName(sectionType(index))));
+ }
+
+ return -1;
+}
+
+QDateTimeParser::FieldInfo QDateTimeParser::fieldInfo(int index) const
+{
+ FieldInfo ret = 0;
+ const SectionNode &sn = sectionNode(index);
+ const Section s = sn.type;
+ switch (s) {
+ case MSecSection:
+ ret |= Fraction;
+ // fallthrough
+ case SecondSection:
+ case MinuteSection:
+ case Hour24Section:
+ case Hour12Section:
+ case YearSection:
+ case YearSection2Digits:
+ ret |= Numeric;
+ if (s != YearSection) {
+ ret |= AllowPartial;
+ }
+ if (sn.count != 1) {
+ ret |= FixedWidth;
+ }
+ break;
+ case MonthSection:
+ case DaySection:
+ switch (sn.count) {
+ case 2:
+ ret |= FixedWidth;
+ // fallthrough
+ case 1:
+ ret |= (Numeric|AllowPartial);
+ break;
+ }
+ break;
+ case DayOfWeekSectionShort:
+ case DayOfWeekSectionLong:
+ if (sn.count == 3)
+ ret |= FixedWidth;
+ break;
+ case AmPmSection:
+ ret |= FixedWidth;
+ break;
+ default:
+ qWarning("QDateTimeParser::fieldInfo Internal error 2 (%d %s %d)",
+ index, qPrintable(sectionName(sn.type)), sn.count);
+ break;
+ }
+ return ret;
+}
+
+/*!
+ \internal
+
+ Get a number that str can become which is between min
+ and max or -1 if this is not possible.
+*/
+
+
+QString QDateTimeParser::sectionFormat(int index) const
+{
+ const SectionNode &sn = sectionNode(index);
+ return sectionFormat(sn.type, sn.count);
+}
+
+QString QDateTimeParser::sectionFormat(Section s, int count) const
+{
+ QChar fillChar;
+ switch (s) {
+ case AmPmSection: return count == 1 ? QLatin1String("AP") : QLatin1String("ap");
+ case MSecSection: fillChar = QLatin1Char('z'); break;
+ case SecondSection: fillChar = QLatin1Char('s'); break;
+ case MinuteSection: fillChar = QLatin1Char('m'); break;
+ case Hour24Section: fillChar = QLatin1Char('H'); break;
+ case Hour12Section: fillChar = QLatin1Char('h'); break;
+ case DayOfWeekSectionShort:
+ case DayOfWeekSectionLong:
+ case DaySection: fillChar = QLatin1Char('d'); break;
+ case MonthSection: fillChar = QLatin1Char('M'); break;
+ case YearSection2Digits:
+ case YearSection: fillChar = QLatin1Char('y'); break;
+ default:
+ qWarning("QDateTimeParser::sectionFormat Internal error (%s)",
+ qPrintable(sectionName(s)));
+ return QString();
+ }
+ if (fillChar.isNull()) {
+ qWarning("QDateTimeParser::sectionFormat Internal error 2");
+ return QString();
+ }
+
+ QString str;
+ str.fill(fillChar, count);
+ return str;
+}
+
+
+/*!
+ \internal
+
+ Returns true if str can be modified to represent a
+ number that is within min and max.
+*/
+
+bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int index,
+ const QDateTime &currentValue, int insert) const
+{
+ if (str.isEmpty()) {
+ return true;
+ }
+ const int size = sectionMaxSize(index);
+ int val = (int)locale().toUInt(str);
+ const SectionNode &sn = sectionNode(index);
+ if (sn.type == YearSection2Digits) {
+ val += currentValue.date().year() - (currentValue.date().year() % 100);
+ }
+ if (val >= min && val <= max && str.size() == size) {
+ return true;
+ } else if (val > max) {
+ return false;
+ } else if (str.size() == size && val < min) {
+ return false;
+ }
+
+ const int len = size - str.size();
+ for (int i=0; i<len; ++i) {
+ for (int j=0; j<10; ++j) {
+ if (potentialValue(str + QLatin1Char('0' + j), min, max, index, currentValue, insert)) {
+ return true;
+ } else if (insert >= 0) {
+ QString tmp = str;
+ tmp.insert(insert, QLatin1Char('0' + j));
+ if (potentialValue(tmp, min, max, index, currentValue, insert))
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool QDateTimeParser::skipToNextSection(int index, const QDateTime &current, const QString &text) const
+{
+ Q_ASSERT(current >= getMinimum() && current <= getMaximum());
+
+ const SectionNode &node = sectionNode(index);
+ Q_ASSERT(text.size() < sectionMaxSize(index));
+
+ const QDateTime maximum = getMaximum();
+ const QDateTime minimum = getMinimum();
+ QDateTime tmp = current;
+ int min = absoluteMin(index);
+ setDigit(tmp, index, min);
+ if (tmp < minimum) {
+ min = getDigit(minimum, index);
+ }
+
+ int max = absoluteMax(index, current);
+ setDigit(tmp, index, max);
+ if (tmp > maximum) {
+ max = getDigit(maximum, index);
+ }
+ int pos = cursorPosition() - node.pos;
+ if (pos < 0 || pos >= text.size())
+ pos = -1;
+
+ const bool potential = potentialValue(text, min, max, index, current, pos);
+ return !potential;
+
+ /* If the value potentially can become another valid entry we
+ * don't want to skip to the next. E.g. In a M field (month
+ * without leading 0 if you type 1 we don't want to autoskip but
+ * if you type 3 we do
+ */
+}
+
+/*!
+ \internal
+ For debugging. Returns the name of the section \a s.
+*/
+
+QString QDateTimeParser::sectionName(int s) const
+{
+ switch (s) {
+ case QDateTimeParser::AmPmSection: return QLatin1String("AmPmSection");
+ case QDateTimeParser::DaySection: return QLatin1String("DaySection");
+ case QDateTimeParser::DayOfWeekSectionShort: return QLatin1String("DayOfWeekSectionShort");
+ case QDateTimeParser::DayOfWeekSectionLong: return QLatin1String("DayOfWeekSectionLong");
+ case QDateTimeParser::Hour24Section: return QLatin1String("Hour24Section");
+ case QDateTimeParser::Hour12Section: return QLatin1String("Hour12Section");
+ case QDateTimeParser::MSecSection: return QLatin1String("MSecSection");
+ case QDateTimeParser::MinuteSection: return QLatin1String("MinuteSection");
+ case QDateTimeParser::MonthSection: return QLatin1String("MonthSection");
+ case QDateTimeParser::SecondSection: return QLatin1String("SecondSection");
+ case QDateTimeParser::YearSection: return QLatin1String("YearSection");
+ case QDateTimeParser::YearSection2Digits: return QLatin1String("YearSection2Digits");
+ case QDateTimeParser::NoSection: return QLatin1String("NoSection");
+ case QDateTimeParser::FirstSection: return QLatin1String("FirstSection");
+ case QDateTimeParser::LastSection: return QLatin1String("LastSection");
+ default: return QLatin1String("Unknown section ") + QString::number(s);
+ }
+}
+
+/*!
+ \internal
+ For debugging. Returns the name of the state \a s.
+*/
+
+QString QDateTimeParser::stateName(int s) const
+{
+ switch (s) {
+ case Invalid: return QLatin1String("Invalid");
+ case Intermediate: return QLatin1String("Intermediate");
+ case Acceptable: return QLatin1String("Acceptable");
+ default: return QLatin1String("Unknown state ") + QString::number(s);
+ }
+}
+
+#ifndef QT_NO_DATESTRING
+bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const
+{
+ QDateTime val(QDate(1900, 1, 1), QDATETIMEEDIT_TIME_MIN);
+ QString text = t;
+ int copy = -1;
+ const StateNode tmp = parse(text, copy, val, false);
+ if (tmp.state != Acceptable || tmp.conflicts) {
+ return false;
+ }
+ if (time) {
+ const QTime t = tmp.value.time();
+ if (!t.isValid()) {
+ return false;
+ }
+ *time = t;
+ }
+
+ if (date) {
+ const QDate d = tmp.value.date();
+ if (!d.isValid()) {
+ return false;
+ }
+ *date = d;
+ }
+ return true;
+}
+#endif // QT_NO_DATESTRING
+
+QDateTime QDateTimeParser::getMinimum() const
+{
+ return QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, spec);
+}
+
+QDateTime QDateTimeParser::getMaximum() const
+{
+ return QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, spec);
+}
+
+QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const
+{
+ if (ap == AmText) {
+ return (cs == UpperCase ? QLatin1String("AM") : QLatin1String("am"));
+ } else {
+ return (cs == UpperCase ? QLatin1String("PM") : QLatin1String("pm"));
+ }
+}
+
+/*
+ \internal
+
+ I give arg2 preference because arg1 is always a QDateTime.
+*/
+
+bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2)
+{
+ return (s1.type == s2.type) && (s1.pos == s2.pos) && (s1.count == s2.count);
+}
+
+#endif // QT_BOOTSTRAPPED
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/tools/qdatetimeparser_p.h
new file mode 100644
index 0000000000..2b4f59a23a
--- /dev/null
+++ b/src/corelib/tools/qdatetimeparser_p.h
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDATETIMEPARSER_P_H
+#define QDATETIMEPARSER_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 "qplatformdefs.h"
+#include "QtCore/qatomic.h"
+#include "QtCore/qdatetime.h"
+#include "QtCore/qstringlist.h"
+#include "QtCore/qlocale.h"
+#ifndef QT_BOOTSTRAPPED
+# include "QtCore/qvariant.h"
+#endif
+#include "QtCore/qvector.h"
+
+
+#define QDATETIMEEDIT_TIME_MIN QTime(0, 0, 0, 0)
+#define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999)
+#define QDATETIMEEDIT_DATE_MIN QDate(100, 1, 1)
+#define QDATETIMEEDIT_COMPAT_DATE_MIN QDate(1752, 9, 14)
+#define QDATETIMEEDIT_DATE_MAX QDate(7999, 12, 31)
+#define QDATETIMEEDIT_DATETIME_MIN QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN)
+#define QDATETIMEEDIT_COMPAT_DATETIME_MIN QDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN, QDATETIMEEDIT_TIME_MIN)
+#define QDATETIMEEDIT_DATETIME_MAX QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX)
+#define QDATETIMEEDIT_DATE_INITIAL QDate(2000, 1, 1)
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_BOOTSTRAPPED
+
+class Q_CORE_EXPORT QDateTimeParser
+{
+public:
+ enum Context {
+ FromString,
+ DateTimeEdit
+ };
+ QDateTimeParser(QVariant::Type t, Context ctx)
+ : currentSectionIndex(-1), display(0), cachedDay(-1), parserType(t),
+ fixday(false), spec(Qt::LocalTime), context(ctx)
+ {
+ defaultLocale = QLocale::system();
+ first.type = FirstSection;
+ first.pos = -1;
+ first.count = -1;
+ first.zeroesAdded = 0;
+ last.type = FirstSection;
+ last.pos = -1;
+ last.count = -1;
+ last.zeroesAdded = 0;
+ none.type = NoSection;
+ none.pos = -1;
+ none.count = -1;
+ none.zeroesAdded = 0;
+ }
+ virtual ~QDateTimeParser() {}
+ enum {
+ Neither = -1,
+ AM = 0,
+ PM = 1,
+ PossibleAM = 2,
+ PossiblePM = 3,
+ PossibleBoth = 4
+ };
+
+ enum Section {
+ NoSection = 0x00000,
+ AmPmSection = 0x00001,
+ MSecSection = 0x00002,
+ SecondSection = 0x00004,
+ MinuteSection = 0x00008,
+ Hour12Section = 0x00010,
+ Hour24Section = 0x00020,
+ TimeSectionMask = (AmPmSection|MSecSection|SecondSection|MinuteSection|Hour12Section|Hour24Section),
+ Internal = 0x10000,
+ DaySection = 0x00100,
+ MonthSection = 0x00200,
+ YearSection = 0x00400,
+ YearSection2Digits = 0x00800,
+ DayOfWeekSectionShort = 0x01000,
+ DayOfWeekSectionLong = 0x20000,
+ DateSectionMask = (DaySection|MonthSection|YearSection|YearSection2Digits|DayOfWeekSectionShort|DayOfWeekSectionLong),
+ FirstSection = 0x02000|Internal,
+ LastSection = 0x04000|Internal,
+ CalendarPopupSection = 0x08000|Internal,
+
+ NoSectionIndex = -1,
+ FirstSectionIndex = -2,
+ LastSectionIndex = -3,
+ CalendarPopupIndex = -4
+ }; // duplicated from qdatetimeedit.h
+ Q_DECLARE_FLAGS(Sections, Section)
+
+ struct SectionNode {
+ Section type;
+ mutable int pos;
+ int count;
+ int zeroesAdded;
+ };
+
+ enum State { // duplicated from QValidator
+ Invalid,
+ Intermediate,
+ Acceptable
+ };
+
+ struct StateNode {
+ StateNode() : state(Invalid), conflicts(false) {}
+ QString input;
+ State state;
+ bool conflicts;
+ QDateTime value;
+ };
+
+ enum AmPm {
+ AmText,
+ PmText
+ };
+
+ enum Case {
+ UpperCase,
+ LowerCase
+ };
+
+#ifndef QT_NO_DATESTRING
+ StateNode parse(QString &input, int &cursorPosition, const QDateTime &currentValue, bool fixup) const;
+#endif
+ int sectionMaxSize(int index) const;
+ int sectionSize(int index) const;
+ int sectionMaxSize(Section s, int count) const;
+ int sectionPos(int index) const;
+ int sectionPos(const SectionNode &sn) const;
+
+ const SectionNode &sectionNode(int index) const;
+ Section sectionType(int index) const;
+ QString sectionText(int sectionIndex) const;
+ QString sectionText(const QString &text, int sectionIndex, int index) const;
+ int getDigit(const QDateTime &dt, int index) const;
+ bool setDigit(QDateTime &t, int index, int newval) const;
+ int parseSection(const QDateTime &currentValue, int sectionIndex, QString &txt, int &cursorPosition,
+ int index, QDateTimeParser::State &state, int *used = 0) const;
+ int absoluteMax(int index, const QDateTime &value = QDateTime()) const;
+ int absoluteMin(int index) const;
+ bool parseFormat(const QString &format);
+#ifndef QT_NO_DATESTRING
+ bool fromString(const QString &text, QDate *date, QTime *time) const;
+#endif
+
+#ifndef QT_NO_TEXTDATE
+ int findMonth(const QString &str1, int monthstart, int sectionIndex,
+ QString *monthName = 0, int *used = 0) const;
+ int findDay(const QString &str1, int intDaystart, int sectionIndex,
+ QString *dayName = 0, int *used = 0) const;
+#endif
+ int findAmPm(QString &str1, int index, int *used = 0) const;
+ int maxChange(int s) const;
+ bool potentialValue(const QString &str, int min, int max, int index,
+ const QDateTime &currentValue, int insert) const;
+ bool skipToNextSection(int section, const QDateTime &current, const QString &sectionText) const;
+ QString sectionName(int s) const;
+ QString stateName(int s) const;
+
+ QString sectionFormat(int index) const;
+ QString sectionFormat(Section s, int count) const;
+
+ enum FieldInfoFlag {
+ Numeric = 0x01,
+ FixedWidth = 0x02,
+ AllowPartial = 0x04,
+ Fraction = 0x08
+ };
+ Q_DECLARE_FLAGS(FieldInfo, FieldInfoFlag)
+
+ FieldInfo fieldInfo(int index) const;
+
+ virtual QDateTime getMinimum() const;
+ virtual QDateTime getMaximum() const;
+ virtual int cursorPosition() const { return -1; }
+ virtual QString displayText() const { return text; }
+ virtual QString getAmPmText(AmPm ap, Case cs) const;
+ virtual QLocale locale() const { return defaultLocale; }
+
+ mutable int currentSectionIndex;
+ Sections display;
+ /*
+ This stores the stores the most recently selected day.
+ It is useful when considering the following scenario:
+
+ 1. Date is: 31/01/2000
+ 2. User increments month: 29/02/2000
+ 3. User increments month: 31/03/2000
+
+ At step 1, cachedDay stores 31. At step 2, the 31 is invalid for February, so the cachedDay is not updated.
+ At step 3, the the month is changed to March, for which 31 is a valid day. Since 29 < 31, the day is set to cachedDay.
+ This is good for when users have selected their desired day and are scrolling up or down in the month or year section
+ and do not want smaller months (or non-leap years) to alter the day that they chose.
+ */
+ mutable int cachedDay;
+ mutable QString text;
+ QVector<SectionNode> sectionNodes;
+ SectionNode first, last, none, popup;
+ QStringList separators;
+ QString displayFormat;
+ QLocale defaultLocale;
+ QVariant::Type parserType;
+
+ bool fixday;
+
+ Qt::TimeSpec spec; // spec if used by QDateTimeEdit
+ Context context;
+};
+
+Q_CORE_EXPORT bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2);
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::Sections)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::FieldInfo)
+
+#endif // QT_BOOTSTRAPPED
+
+QT_END_NAMESPACE
+
+#endif // QDATETIME_P_H
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index c81968dce1..b795bbc86e 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -48,6 +48,7 @@
#include <iterator>
#include <list>
+#include <algorithm>
#ifdef Q_COMPILER_INITIALIZER_LISTS
#include <initializer_list>
#endif
@@ -123,7 +124,7 @@ public:
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QList(std::initializer_list<T> args)
: d(const_cast<QListData::Data *>(&QListData::shared_null))
- { qCopy(args.begin(), args.end(), std::back_inserter(*this)); }
+ { std::copy(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); }
@@ -332,9 +333,9 @@ public:
static QList<T> fromSet(const QSet<T> &set);
static inline QList<T> fromStdList(const std::list<T> &list)
- { QList<T> tmp; qCopy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; }
+ { QList<T> tmp; std::copy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; }
inline std::list<T> toStdList() const
- { std::list<T> tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
+ { std::list<T> tmp; std::copy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
private:
Node *detach_helper_grow(int i, int n);
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 060b220a4a..fb233c0640 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -55,6 +55,7 @@
#include "qlocale_p.h"
#include "qlocale_tools_p.h"
#include "qdatetime_p.h"
+#include "qdatetimeparser_p.h"
#include "qnamespace.h"
#include "qdatetime.h"
#include "qstringlist.h"
diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp
index e5de4a1bfd..71b90bcada 100644
--- a/src/corelib/tools/qmap.cpp
+++ b/src/corelib/tools/qmap.cpp
@@ -879,6 +879,48 @@ void QMapDataBase::freeData(QMapDataBase *d)
\sa constBegin(), end()
*/
+/*! \fn const Key &QMap::firstKey() const
+
+ Returns a reference to the smallest key in the map.
+ This function assumes that the map is not empty.
+
+ \sa lastKey(), first(), isEmpty()
+*/
+
+/*! \fn const Key &QMap::lastKey() const
+
+ Returns a reference to the largest key in the map.
+ This function assumes that the map is not empty.
+
+ \sa firstKey(), last(), isEmpty()
+*/
+
+/*! \fn T &QMap::first()
+
+ Returns a reference to the first value in the map, that is the value mapped
+ to the smallest key. This function assumes that the map is not empty.
+
+ \sa last(), firstKey(), isEmpty()
+*/
+
+/*! \fn const T &QMap::first() const
+
+ \overload
+*/
+
+/*! \fn T &QMap::last()
+
+ Returns a reference to the last value in the map, that is the value mapped
+ to the largest key. This function assumes that the map is not empty.
+
+ \sa first(), lastKey(), isEmpty()
+*/
+
+/*! \fn const T &QMap::last() const
+
+ \overload
+*/
+
/*! \fn QMap::iterator QMap::erase(iterator pos)
Removes the (key, value) pair pointed to by the iterator \a pos
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index c030a76666..29e8f9b140 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -140,32 +140,32 @@ template <class Key, class T>
inline QMapNode<Key, T> *QMapNode<Key, T>::lowerBound(const Key &akey)
{
QMapNode<Key, T> *n = this;
- QMapNode<Key, T> *last = 0;
+ QMapNode<Key, T> *lastNode = 0;
while (n) {
if (!qMapLessThanKey(n->key, akey)) {
- last = n;
+ lastNode = n;
n = n->leftNode();
} else {
n = n->rightNode();
}
}
- return last;
+ return lastNode;
}
template <class Key, class T>
inline QMapNode<Key, T> *QMapNode<Key, T>::upperBound(const Key &akey)
{
QMapNode<Key, T> *n = this;
- QMapNode<Key, T> *last = 0;
+ QMapNode<Key, T> *lastNode = 0;
while (n) {
if (qMapLessThanKey(akey, n->key)) {
- last = n;
+ lastNode = n;
n = n->leftNode();
} else {
n = n->rightNode();
}
}
- return last;
+ return lastNode;
}
@@ -206,7 +206,7 @@ struct QMapData : public QMapDataBase
void deleteNode(Node *z);
Node *findNode(const Key &akey) const;
- void nodeRange(const Key &akey, Node **first, Node **last);
+ void nodeRange(const Key &akey, Node **firstNode, Node **lastNode);
Node *createNode(const Key &k, const T &v, Node *parent = 0, bool left = false)
{
@@ -296,7 +296,7 @@ QMapNode<Key, T> *QMapData<Key, T>::findNode(const Key &akey) const
template <class Key, class T>
-void QMapData<Key, T>::nodeRange(const Key &akey, QMapNode<Key, T> **first, QMapNode<Key, T> **last)
+void QMapData<Key, T>::nodeRange(const Key &akey, QMapNode<Key, T> **firstNode, QMapNode<Key, T> **lastNode)
{
Node *n = root();
Node *l = end();
@@ -307,16 +307,16 @@ void QMapData<Key, T>::nodeRange(const Key &akey, QMapNode<Key, T> **first, QMap
} else if (qMapLessThanKey(n->key, akey)) {
n = n->rightNode();
} else {
- *first = n->leftNode()->lowerBound(akey);
- if (!*first)
- *first = n;
- *last = n->rightNode()->upperBound(akey);
- if (!*last)
- *last = l;
+ *firstNode = n->leftNode()->lowerBound(akey);
+ if (!*firstNode)
+ *firstNode = n;
+ *lastNode = n->rightNode()->upperBound(akey);
+ if (!*lastNode)
+ *lastNode = l;
return;
}
}
- *first = *last = l;
+ *firstNode = *lastNode = l;
}
@@ -395,6 +395,14 @@ public:
QList<T> values(const Key &key) const;
int count(const Key &key) const;
+ inline const Key &firstKey() const { Q_ASSERT(!isEmpty()); return constBegin().key(); }
+ inline const Key &lastKey() const { Q_ASSERT(!isEmpty()); return (constEnd() - 1).key(); }
+
+ inline T &first() { Q_ASSERT(!isEmpty()); return *begin(); }
+ inline const T &first() const { Q_ASSERT(!isEmpty()); return *constBegin(); }
+ inline T &last() { Q_ASSERT(!isEmpty()); return *(end() - 1); }
+ inline const T &last() const { Q_ASSERT(!isEmpty()); return *(constEnd() - 1); }
+
class const_iterator;
class iterator
@@ -633,12 +641,12 @@ Q_INLINE_TEMPLATE int QMap<Key, T>::count(const Key &akey) const
Node *lastNode;
d->nodeRange(akey, &firstNode, &lastNode);
- const_iterator first(firstNode);
- const const_iterator last(lastNode);
+ const_iterator ci_first(firstNode);
+ const const_iterator ci_last(lastNode);
int cnt = 0;
- while (first != last) {
+ while (ci_first != ci_last) {
++cnt;
- ++first;
+ ++ci_first;
}
return cnt;
}
@@ -655,12 +663,12 @@ Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insert(const Key
detach();
Node *n = d->root();
Node *y = d->end();
- Node *last = 0;
+ Node *lastNode = 0;
bool left = true;
while (n) {
y = n;
if (!qMapLessThanKey(n->key, akey)) {
- last = n;
+ lastNode = n;
left = true;
n = n->leftNode();
} else {
@@ -668,9 +676,9 @@ Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insert(const Key
n = n->rightNode();
}
}
- if (last && !qMapLessThanKey(akey, last->key)) {
- last->value = avalue;
- return iterator(last);
+ if (lastNode && !qMapLessThanKey(akey, lastNode->key)) {
+ lastNode->value = avalue;
+ return iterator(lastNode);
}
Node *z = d->createNode(akey, avalue, y, left);
return iterator(z);
@@ -852,9 +860,9 @@ template <class Key, class T>
QPair<typename QMap<Key, T>::iterator, typename QMap<Key, T>::iterator> QMap<Key, T>::equal_range(const Key &akey)
{
detach();
- Node *first, *last;
- d->nodeRange(akey, &first, &last);
- return QPair<iterator, iterator>(iterator(first), iterator(last));
+ Node *firstNode, *lastNode;
+ d->nodeRange(akey, &firstNode, &lastNode);
+ return QPair<iterator, iterator>(iterator(firstNode), iterator(lastNode));
}
#ifdef Q_MAP_DEBUG
diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp
index a5559a181b..870ac23028 100644
--- a/src/corelib/tools/qstringlist.cpp
+++ b/src/corelib/tools/qstringlist.cpp
@@ -43,6 +43,8 @@
#include <qset.h>
#include <qregularexpression.h>
+#include <algorithm>
+
QT_BEGIN_NAMESPACE
/*! \typedef QStringListIterator
@@ -222,8 +224,8 @@ QT_BEGIN_NAMESPACE
If \a cs is \l Qt::CaseSensitive (the default), the string comparison
is case sensitive; otherwise the comparison is case insensitive.
- Sorting is performed using Qt's qSort() algorithm,
- which operates in \l{linear-logarithmic time}, i.e. O(\e{n} log \e{n}).
+ Sorting is performed using the STL's std::sort() algorithm,
+ which averages \l{linear-logarithmic time}, i.e. O(\e{n} log \e{n}).
If you want to sort your strings in an arbitrary order, consider
using the QMap class. For example, you could use a QMap<QString,
@@ -231,8 +233,6 @@ QT_BEGIN_NAMESPACE
being lower-case versions of the strings, and the values being the
strings), or a QMap<int, QString> to sort the strings by some
integer index.
-
- \sa qSort()
*/
static inline bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
@@ -243,9 +243,9 @@ static inline bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
void QtPrivate::QStringList_sort(QStringList *that, Qt::CaseSensitivity cs)
{
if (cs == Qt::CaseSensitive)
- qSort(that->begin(), that->end());
+ std::sort(that->begin(), that->end());
else
- qSort(that->begin(), that->end(), caseInsensitiveLessThan);
+ std::sort(that->begin(), that->end(), caseInsensitiveLessThan);
}
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index 8aab53998b..2f3697acb8 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -18,6 +18,7 @@ HEADERS += \
tools/qcryptographichash.h \
tools/qdatetime.h \
tools/qdatetime_p.h \
+ tools/qdatetimeparser_p.h \
tools/qeasingcurve.h \
tools/qfreelist_p.h \
tools/qhash.h \
@@ -75,6 +76,7 @@ SOURCES += \
tools/qcommandlineparser.cpp \
tools/qcryptographichash.cpp \
tools/qdatetime.cpp \
+ tools/qdatetimeparser.cpp \
tools/qeasingcurve.cpp \
tools/qelapsedtimer.cpp \
tools/qfreelist.cpp \
diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp
index 127cf6658c..51c0b27668 100644
--- a/src/dbus/qdbusmetaobject.cpp
+++ b/src/dbus/qdbusmetaobject.cpp
@@ -348,7 +348,7 @@ void QDBusMetaObjectGenerator::parseSignals()
prototype.append(')');
// meta method flags
- mm.flags = AccessProtected | MethodSignal | MethodScriptable;
+ mm.flags = AccessPublic | MethodSignal | MethodScriptable;
// add
signals_.insert(QMetaObject::normalizedSignature(prototype), mm);
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
index 3eb103b7e0..710e36ae42 100644
--- a/src/gui/kernel/qplatformtheme.h
+++ b/src/gui/kernel/qplatformtheme.h
@@ -120,6 +120,8 @@ public:
ToolTipPalette,
ToolButtonPalette,
ButtonPalette,
+ CheckBoxPalette,
+ RadioButtonPalette,
HeaderPalette,
ComboBoxPalette,
ItemViewPalette,
@@ -147,6 +149,8 @@ public:
MdiSubWindowTitleFont,
DockWidgetTitleFont,
PushButtonFont,
+ CheckBoxFont,
+ RadioButtonFont,
ToolButtonFont,
ItemViewFont,
ListViewFont,
diff --git a/src/gui/opengl/qopenglfunctions_1_0.cpp b/src/gui/opengl/qopenglfunctions_1_0.cpp
index b618dcb5cf..f368bda76d 100644
--- a/src/gui/opengl/qopenglfunctions_1_0.cpp
+++ b/src/gui/opengl/qopenglfunctions_1_0.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_1_0 class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_1_0 class provides all functions for OpenGL 1.0 specification.
+
+ This class is a wrapper for functions from OpenGL 1.0 specification.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_1_1.cpp b/src/gui/opengl/qopenglfunctions_1_1.cpp
index bf032b5cf9..d101c5c406 100644
--- a/src/gui/opengl/qopenglfunctions_1_1.cpp
+++ b/src/gui/opengl/qopenglfunctions_1_1.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_1_1 class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_1_1 class provides all functions for OpenGL 1.1 specification.
+
+ This class is a wrapper for functions from OpenGL 1.1 specification.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_1_2.cpp b/src/gui/opengl/qopenglfunctions_1_2.cpp
index 2b14900680..1c6ad1ddff 100644
--- a/src/gui/opengl/qopenglfunctions_1_2.cpp
+++ b/src/gui/opengl/qopenglfunctions_1_2.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_1_2 class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_1_2 class provides all functions for OpenGL 1.2 specification.
+
+ This class is a wrapper for functions from OpenGL 1.2 specification.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_1_3.cpp b/src/gui/opengl/qopenglfunctions_1_3.cpp
index 94605f8638..aef3789f9a 100644
--- a/src/gui/opengl/qopenglfunctions_1_3.cpp
+++ b/src/gui/opengl/qopenglfunctions_1_3.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_1_3 class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_1_3 class provides all functions for OpenGL 1.3 specification.
+
+ This class is a wrapper for functions from OpenGL 1.3 specification.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_1_4.cpp b/src/gui/opengl/qopenglfunctions_1_4.cpp
index e3035eeb55..24b4c0ba7a 100644
--- a/src/gui/opengl/qopenglfunctions_1_4.cpp
+++ b/src/gui/opengl/qopenglfunctions_1_4.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_1_4 class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_1_4 class provides all functions for OpenGL 1.4 specification.
+
+ This class is a wrapper for functions from OpenGL 1.4 specification.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_1_5.cpp b/src/gui/opengl/qopenglfunctions_1_5.cpp
index 581ed14aac..b5a9486629 100644
--- a/src/gui/opengl/qopenglfunctions_1_5.cpp
+++ b/src/gui/opengl/qopenglfunctions_1_5.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_1_5 class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_1_5 class provides all functions for OpenGL 1.5 specification.
+
+ This class is a wrapper for functions from OpenGL 1.5 specification.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_2_0.cpp b/src/gui/opengl/qopenglfunctions_2_0.cpp
index 2736d4a030..0645750858 100644
--- a/src/gui/opengl/qopenglfunctions_2_0.cpp
+++ b/src/gui/opengl/qopenglfunctions_2_0.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_2_0 class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_2_0 class provides all functions for OpenGL 2.0 specification.
+
+ This class is a wrapper for functions from OpenGL 2.0 specification.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_2_1.cpp b/src/gui/opengl/qopenglfunctions_2_1.cpp
index ed94131e33..133f3bf0cb 100644
--- a/src/gui/opengl/qopenglfunctions_2_1.cpp
+++ b/src/gui/opengl/qopenglfunctions_2_1.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_2_1 class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_2_1 class provides all functions for OpenGL 2.1 specification.
+
+ This class is a wrapper for functions from OpenGL 2.1 specification.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_3_0.cpp b/src/gui/opengl/qopenglfunctions_3_0.cpp
index e80235b957..ae56b50b31 100644
--- a/src/gui/opengl/qopenglfunctions_3_0.cpp
+++ b/src/gui/opengl/qopenglfunctions_3_0.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_3_0 class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_3_0 class provides all functions for OpenGL 3.0 specification.
+
+ This class is a wrapper for functions from OpenGL 3.0 specification.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_3_1.cpp b/src/gui/opengl/qopenglfunctions_3_1.cpp
index ab48658bfc..5014fdb62c 100644
--- a/src/gui/opengl/qopenglfunctions_3_1.cpp
+++ b/src/gui/opengl/qopenglfunctions_3_1.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_3_1 class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_3_1 class provides all functions for OpenGL 3.1 specification.
+
+ This class is a wrapper for functions from OpenGL 3.1 specification.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_3_2_compatibility.cpp b/src/gui/opengl/qopenglfunctions_3_2_compatibility.cpp
index 171b7454f4..a6de8fd0fe 100644
--- a/src/gui/opengl/qopenglfunctions_3_2_compatibility.cpp
+++ b/src/gui/opengl/qopenglfunctions_3_2_compatibility.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_3_2_Compatibility class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_3_2_Compatibility class provides all functions for OpenGL 3.2 compatibility profile.
+
+ This class is a wrapper for functions from OpenGL 3.2 compatibility profile.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_3_2_core.cpp b/src/gui/opengl/qopenglfunctions_3_2_core.cpp
index 48dec29962..2c41d3a5fe 100644
--- a/src/gui/opengl/qopenglfunctions_3_2_core.cpp
+++ b/src/gui/opengl/qopenglfunctions_3_2_core.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_3_2_Core class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_3_2_Core class provides all functions for OpenGL 3.2 core profile.
+
+ This class is a wrapper for functions from OpenGL 3.2 core profile.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_3_3_compatibility.cpp b/src/gui/opengl/qopenglfunctions_3_3_compatibility.cpp
index 8bebc7d0bc..dc36eba1ad 100644
--- a/src/gui/opengl/qopenglfunctions_3_3_compatibility.cpp
+++ b/src/gui/opengl/qopenglfunctions_3_3_compatibility.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_3_3_Compatibility class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_3_3_Compatibility class provides all functions for OpenGL 3.3 compatibility profile.
+
+ This class is a wrapper for functions from OpenGL 3.3 compatibility profile.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_3_3_core.cpp b/src/gui/opengl/qopenglfunctions_3_3_core.cpp
index 941f9c38b6..5a1e238d0e 100644
--- a/src/gui/opengl/qopenglfunctions_3_3_core.cpp
+++ b/src/gui/opengl/qopenglfunctions_3_3_core.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_3_3_Core class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_3_3_Core class provides all functions for OpenGL 3.3 core profile.
+
+ This class is a wrapper for functions from OpenGL 3.3 core profile.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_4_0_compatibility.cpp b/src/gui/opengl/qopenglfunctions_4_0_compatibility.cpp
index 7ab0688084..7affa43da1 100644
--- a/src/gui/opengl/qopenglfunctions_4_0_compatibility.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_0_compatibility.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_4_0_Compatibility class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_4_0_Compatibility class provides all functions for OpenGL 4.0 compatibility profile.
+
+ This class is a wrapper for functions from OpenGL 4.0 compatibility profile.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_4_0_core.cpp b/src/gui/opengl/qopenglfunctions_4_0_core.cpp
index a4bf66a44b..5e8bd8d6a5 100644
--- a/src/gui/opengl/qopenglfunctions_4_0_core.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_0_core.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_4_0_Core class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_4_0_Core class provides all functions for OpenGL 4.0 core profile.
+
+ This class is a wrapper for functions from OpenGL 4.0 core profile.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_4_1_compatibility.cpp b/src/gui/opengl/qopenglfunctions_4_1_compatibility.cpp
index a0ea4a052a..44e937557a 100644
--- a/src/gui/opengl/qopenglfunctions_4_1_compatibility.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_1_compatibility.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_4_1_Compatibility class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_4_1_Compatibility class provides all functions for OpenGL 4.1 compatibility profile.
+
+ This class is a wrapper for functions from OpenGL 4.1 compatibility profile.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_4_1_core.cpp b/src/gui/opengl/qopenglfunctions_4_1_core.cpp
index 474397bb1f..04fcc78d5d 100644
--- a/src/gui/opengl/qopenglfunctions_4_1_core.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_1_core.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_4_1_Core class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_4_1_Core class provides all functions for OpenGL 4.1 core profile.
+
+ This class is a wrapper for functions from OpenGL 4.1 core profile.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_4_2_compatibility.cpp b/src/gui/opengl/qopenglfunctions_4_2_compatibility.cpp
index 6d19fff92b..1329327f3e 100644
--- a/src/gui/opengl/qopenglfunctions_4_2_compatibility.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_2_compatibility.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_4_2_Compatibility class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_4_2_Compatibility class provides all functions for OpenGL 4.2 compatibility profile.
+
+ This class is a wrapper for functions from OpenGL 4.2 compatibility profile.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_4_2_core.cpp b/src/gui/opengl/qopenglfunctions_4_2_core.cpp
index 51ba3e8097..652d5810c5 100644
--- a/src/gui/opengl/qopenglfunctions_4_2_core.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_2_core.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_4_2_Core class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_4_2_Core class provides all functions for OpenGL 4.2 core profile.
+
+ This class is a wrapper for functions from OpenGL 4.2 core profile.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_4_3_compatibility.cpp b/src/gui/opengl/qopenglfunctions_4_3_compatibility.cpp
index de6cc185c6..19fffc8f2e 100644
--- a/src/gui/opengl/qopenglfunctions_4_3_compatibility.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_3_compatibility.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_4_3_Compatibility class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_4_3_Compatibility class provides all functions for OpenGL 4.3 compatibility profile.
+
+ This class is a wrapper for functions from OpenGL 4.3 compatibility profile.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_4_3_core.cpp b/src/gui/opengl/qopenglfunctions_4_3_core.cpp
index 29fc8368aa..b9659eeb88 100644
--- a/src/gui/opengl/qopenglfunctions_4_3_core.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_3_core.cpp
@@ -58,7 +58,11 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
\since 5.1
\wrapper
- \brief The QOpenGLFunctions_4_3_Core class provides all functions for this version and profile of OpenGL.
+ \brief The QOpenGLFunctions_4_3_Core class provides all functions for OpenGL 4.3 core profile.
+
+ This class is a wrapper for functions from OpenGL 4.3 core profile.
+ See reference pages on \l {http://www.opengl.org/sdk/docs/}{opengl.org}
+ for function documentation.
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/opengl/qopenglfunctions_es2.cpp b/src/gui/opengl/qopenglfunctions_es2.cpp
index 20a4b50994..5e0efbd02e 100644
--- a/src/gui/opengl/qopenglfunctions_es2.cpp
+++ b/src/gui/opengl/qopenglfunctions_es2.cpp
@@ -51,6 +51,10 @@ QT_BEGIN_NAMESPACE
\wrapper
\brief The QOpenGLFunctions_ES2 class provides all functions for OpenGL ES 2
+ This class is a wrapper for OpenGL ES 2 functions. See reference pages on
+ \l {http://www.khronos.org/opengles/sdk/docs/man/}{khronos.org} for
+ function documentation.
+
\sa QAbstractOpenGLFunctions
*/
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index d36a2d46f8..b315017d6d 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -5052,7 +5052,7 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
return;
#ifndef QT_NO_DEBUG
- qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
+ qt_painter_thread_test(d->device->devType(), "drawPixmap()");
#endif
if (d->extended) {
@@ -5123,7 +5123,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()", true);
+ qt_painter_thread_test(d->device->devType(), "drawPixmap()");
#endif
qreal x = r.x();
@@ -6349,12 +6349,6 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText
if (!engine)
return;
-#ifndef QT_NO_DEBUG
- qt_painter_thread_test(device->devType(),
- "text and fonts",
- QFontDatabase::supportsThreadedFontRendering());
-#endif
-
QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
if (!extended && state->bgMode == Qt::OpaqueMode) {
@@ -6618,7 +6612,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()", true);
+ qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()");
#endif
qreal sw = pixmap.width();
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 6da103e931..6703f66e29 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -2167,12 +2167,15 @@ QFont QFontDatabase::systemFont(QFontDatabase::SystemFont type)
/*!
\fn bool QFontDatabase::supportsThreadedFontRendering()
\since 4.4
+ \deprecated
Returns true if font rendering is supported outside the GUI
thread, false otherwise. In other words, a return value of false
means that all QPainter::drawText() calls outside the GUI thread
will not produce readable output.
+ As of 5.0, always returns true.
+
\sa {Thread-Support in Qt Modules#Painting In Threads}{Painting In Threads}
*/
diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h
index bd603c3c4a..4e8f718962 100644
--- a/src/gui/text/qfontdatabase.h
+++ b/src/gui/text/qfontdatabase.h
@@ -150,7 +150,9 @@ public:
static bool removeApplicationFont(int id);
static bool removeAllApplicationFonts();
- static bool supportsThreadedFontRendering();
+#if QT_DEPRECATED_SINCE(5, 2)
+ QT_DEPRECATED static inline bool supportsThreadedFontRendering() { return true; }
+#endif
static QFont systemFont(SystemFont type);
diff --git a/src/gui/text/qfontdatabase_qpa.cpp b/src/gui/text/qfontdatabase_qpa.cpp
index 8e6ad7cd97..0e9c21799b 100644
--- a/src/gui/text/qfontdatabase_qpa.cpp
+++ b/src/gui/text/qfontdatabase_qpa.cpp
@@ -267,11 +267,6 @@ bool QFontDatabase::removeAllApplicationFonts()
return true;
}
-bool QFontDatabase::supportsThreadedFontRendering()
-{
- return true;
-}
-
/*!
\internal
*/
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 9e6b8d6ffd..88a24b5e6a 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -48,6 +48,11 @@
#include "qvarlengtharray.h"
#include <qmath.h>
#include <qendian.h>
+
+#ifdef QT_ENABLE_HARFBUZZ_NG
+# include "qharfbuzzng_p.h"
+# include <harfbuzz/hb-ot.h>
+#endif
#include <private/qharfbuzz_p.h>
#include <algorithm>
@@ -73,6 +78,10 @@ static inline bool qtransform_equals_no_translate(const QTransform &a, const QTr
// Harfbuzz helper functions
+#ifdef QT_ENABLE_HARFBUZZ_NG
+bool useHarfbuzzNG = qgetenv("QT_HARFBUZZ") != "old";
+#endif
+
Q_STATIC_ASSERT(sizeof(HB_Glyph) == sizeof(glyph_t));
Q_STATIC_ASSERT(sizeof(HB_Fixed) == sizeof(QFixed));
@@ -197,7 +206,7 @@ Q_AUTOTEST_EXPORT QList<QFontEngine *> QFontEngine_stopCollectingEngines()
// QFontEngine
QFontEngine::QFontEngine()
- : QObject(), ref(0),
+ : ref(0),
font_(0), font_destroy_func(0),
face_(0), face_destroy_func(0)
{
@@ -253,6 +262,10 @@ QFixed QFontEngine::underlinePosition() const
void *QFontEngine::harfbuzzFont() const
{
+#ifdef QT_ENABLE_HARFBUZZ_NG
+ if (useHarfbuzzNG)
+ qFatal("Called QFontEngine::harfbuzzFont() in Harfbuzz-NG mode!");
+#endif
if (!font_) {
HB_FontRec *hbFont = (HB_FontRec *) malloc(sizeof(HB_FontRec));
Q_CHECK_PTR(hbFont);
@@ -277,6 +290,10 @@ void *QFontEngine::harfbuzzFont() const
void *QFontEngine::harfbuzzFace() const
{
+#ifdef QT_ENABLE_HARFBUZZ_NG
+ if (useHarfbuzzNG)
+ qFatal("Called QFontEngine::harfbuzzFace() in Harfbuzz-NG mode!");
+#endif
if (!face_) {
HB_Face hbFace = qHBNewFace(const_cast<QFontEngine *>(this), hb_getSFntTable);
Q_CHECK_PTR(hbFace);
@@ -292,6 +309,26 @@ void *QFontEngine::harfbuzzFace() const
bool QFontEngine::supportsScript(QChar::Script script) const
{
+#ifdef QT_ENABLE_HARFBUZZ_NG
+ if (useHarfbuzzNG) {
+ bool ret = false;
+ if (hb_face_t *face = hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this))) {
+ hb_tag_t script_tag_1, script_tag_2;
+ hb_ot_tags_from_script(hb_qt_script_to_script(script), &script_tag_1, &script_tag_2);
+
+ unsigned int script_index = -1;
+ ret = hb_ot_layout_table_find_script(face, HB_OT_TAG_GSUB, script_tag_1, &script_index);
+ if (!ret) {
+ ret = hb_ot_layout_table_find_script(face, HB_OT_TAG_GSUB, script_tag_2, &script_index);
+ if (!ret && script_tag_2 != HB_OT_TAG_DEFAULT_SCRIPT)
+ ret = hb_ot_layout_table_find_script(face, HB_OT_TAG_GSUB, HB_OT_TAG_DEFAULT_SCRIPT, &script_index);
+ }
+
+ hb_face_destroy(face);
+ }
+ return ret;
+ }
+#endif
HB_Face hbFace = (HB_Face)harfbuzzFace();
return hbFace->supported_scripts[script_to_hbscript(script)];
}
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index cad9b02f41..61f4781e3f 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -631,8 +631,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
#endif
defaultFormat = Format_None;
embeddedbitmap = false;
- const QByteArray env = qgetenv("QT_NO_FT_CACHE");
- cacheEnabled = env.isEmpty() || env.toInt() == 0;
+ cacheEnabled = qEnvironmentVariableIsSet("QT_USE_FT_CACHE");
m_subPixelPositionCount = 4;
}
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index 084ef6cea3..e64fec2f27 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -63,10 +63,6 @@
#include <unistd.h>
#endif
-#ifndef QT_NO_FONTCONFIG
-#include <fontconfig/fontconfig.h>
-#endif
-
#include <qmutex.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 4427000d03..1a6862898d 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -86,9 +86,8 @@ enum HB_Compat_Error {
typedef void (*qt_destroy_func_t) (void *user_data);
-class Q_GUI_EXPORT QFontEngine : public QObject
+class Q_GUI_EXPORT QFontEngine
{
- Q_OBJECT
public:
enum Type {
Box,
@@ -300,9 +299,13 @@ public:
QImage currentlyLockedAlphaMap;
int m_subPixelPositionCount; // Number of positions within a single pixel for this cache
+ inline QVariant userData() const { return m_userData; }
+
protected:
QFixed lastRightBearing(const QGlyphLayout &glyphs, bool round = false);
+ inline void setUserData(const QVariant &userData) { m_userData = userData; }
+
private:
struct GlyphCacheEntry {
const void *context;
@@ -311,6 +314,9 @@ private:
};
mutable QLinkedList<GlyphCacheEntry> m_glyphCaches;
+
+private:
+ QVariant m_userData;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QFontEngine::ShaperFlags)
@@ -368,7 +374,6 @@ private:
class Q_GUI_EXPORT QFontEngineMulti : public QFontEngine
{
- Q_OBJECT
public:
explicit QFontEngineMulti(int engineCount);
~QFontEngineMulti();
diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp
index 0a730abcac..9b21d61aad 100644
--- a/src/gui/text/qfontengine_qpa.cpp
+++ b/src/gui/text/qfontengine_qpa.cpp
@@ -687,7 +687,6 @@ void QFontEngineMultiQPA::init(QFontEngine *fe)
engines[0] = fe;
fe->ref.ref();
fontDef = engines[0]->fontDef;
- setObjectName(QStringLiteral("QFontEngineMultiQPA"));
cache_cost = fe->cache_cost;
}
@@ -754,7 +753,9 @@ QFontEngine* QFontEngineMultiQPA::createMultiFontEngine(QFontEngine *fe, int scr
QFontCache::EngineCache::Iterator it = fc->engineCache.find(key),
end = fc->engineCache.end();
while (it != end && it.key() == key) {
- QFontEngineMulti *cachedEngine = qobject_cast<QFontEngineMulti *>(it.value().data);
+ QFontEngineMulti *cachedEngine = 0;
+ if (it.value().data->type() == QFontEngine::Multi)
+ cachedEngine = static_cast<QFontEngineMulti *>(it.value().data);
if (faceIsLocal || (cachedEngine && fe == cachedEngine->engine(0))) {
engine = cachedEngine;
fc->updateHitCountAndTimeStamp(it.value());
diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp
new file mode 100644
index 0000000000..96a1cff889
--- /dev/null
+++ b/src/gui/text/qharfbuzzng.cpp
@@ -0,0 +1,730 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2013 Konstantin Ritt
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qharfbuzzng_p.h"
+
+#include <qstring.h>
+#include <qvector.h>
+
+#include "qfontengine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+// Unicode routines
+
+static const hb_script_t _qtscript_to_hbscript[] = {
+ HB_SCRIPT_UNKNOWN,
+ HB_SCRIPT_INHERITED,
+ HB_SCRIPT_COMMON,
+
+ HB_SCRIPT_LATIN,
+ HB_SCRIPT_GREEK,
+ HB_SCRIPT_CYRILLIC,
+ HB_SCRIPT_ARMENIAN,
+ HB_SCRIPT_HEBREW,
+ HB_SCRIPT_ARABIC,
+ HB_SCRIPT_SYRIAC,
+ HB_SCRIPT_THAANA,
+ HB_SCRIPT_DEVANAGARI,
+ HB_SCRIPT_BENGALI,
+ HB_SCRIPT_GURMUKHI,
+ HB_SCRIPT_GUJARATI,
+ HB_SCRIPT_ORIYA,
+ HB_SCRIPT_TAMIL,
+ HB_SCRIPT_TELUGU,
+ HB_SCRIPT_KANNADA,
+ HB_SCRIPT_MALAYALAM,
+ HB_SCRIPT_SINHALA,
+ HB_SCRIPT_THAI,
+ HB_SCRIPT_LAO,
+ HB_SCRIPT_TIBETAN,
+ HB_SCRIPT_MYANMAR,
+ HB_SCRIPT_GEORGIAN,
+ HB_SCRIPT_HANGUL,
+ HB_SCRIPT_ETHIOPIC,
+ HB_SCRIPT_CHEROKEE,
+ HB_SCRIPT_CANADIAN_ABORIGINAL,
+ HB_SCRIPT_OGHAM,
+ HB_SCRIPT_RUNIC,
+ HB_SCRIPT_KHMER,
+ HB_SCRIPT_MONGOLIAN,
+ HB_SCRIPT_HIRAGANA,
+ HB_SCRIPT_KATAKANA,
+ HB_SCRIPT_BOPOMOFO,
+ HB_SCRIPT_HAN,
+ HB_SCRIPT_YI,
+ HB_SCRIPT_OLD_ITALIC,
+ HB_SCRIPT_GOTHIC,
+ HB_SCRIPT_DESERET,
+ HB_SCRIPT_TAGALOG,
+ HB_SCRIPT_HANUNOO,
+ HB_SCRIPT_BUHID,
+ HB_SCRIPT_TAGBANWA,
+ HB_SCRIPT_COPTIC,
+ HB_SCRIPT_LIMBU,
+ HB_SCRIPT_TAI_LE,
+ HB_SCRIPT_LINEAR_B,
+ HB_SCRIPT_UGARITIC,
+ HB_SCRIPT_SHAVIAN,
+ HB_SCRIPT_OSMANYA,
+ HB_SCRIPT_CYPRIOT,
+ HB_SCRIPT_BRAILLE,
+ HB_SCRIPT_BUGINESE,
+ HB_SCRIPT_NEW_TAI_LUE,
+ HB_SCRIPT_GLAGOLITIC,
+ HB_SCRIPT_TIFINAGH,
+ HB_SCRIPT_SYLOTI_NAGRI,
+ HB_SCRIPT_OLD_PERSIAN,
+ HB_SCRIPT_KHAROSHTHI,
+ HB_SCRIPT_BALINESE,
+ HB_SCRIPT_CUNEIFORM,
+ HB_SCRIPT_PHOENICIAN,
+ HB_SCRIPT_PHAGS_PA,
+ HB_SCRIPT_NKO,
+ HB_SCRIPT_SUNDANESE,
+ HB_SCRIPT_LEPCHA,
+ HB_SCRIPT_OL_CHIKI,
+ HB_SCRIPT_VAI,
+ HB_SCRIPT_SAURASHTRA,
+ HB_SCRIPT_KAYAH_LI,
+ HB_SCRIPT_REJANG,
+ HB_SCRIPT_LYCIAN,
+ HB_SCRIPT_CARIAN,
+ HB_SCRIPT_LYDIAN,
+ HB_SCRIPT_CHAM,
+ HB_SCRIPT_TAI_THAM,
+ HB_SCRIPT_TAI_VIET,
+ HB_SCRIPT_AVESTAN,
+ HB_SCRIPT_EGYPTIAN_HIEROGLYPHS,
+ HB_SCRIPT_SAMARITAN,
+ HB_SCRIPT_LISU,
+ HB_SCRIPT_BAMUM,
+ HB_SCRIPT_JAVANESE,
+ HB_SCRIPT_MEETEI_MAYEK,
+ HB_SCRIPT_IMPERIAL_ARAMAIC,
+ HB_SCRIPT_OLD_SOUTH_ARABIAN,
+ HB_SCRIPT_INSCRIPTIONAL_PARTHIAN,
+ HB_SCRIPT_INSCRIPTIONAL_PAHLAVI,
+ HB_SCRIPT_OLD_TURKIC,
+ HB_SCRIPT_KAITHI,
+ HB_SCRIPT_BATAK,
+ HB_SCRIPT_BRAHMI,
+ HB_SCRIPT_MANDAIC,
+ HB_SCRIPT_CHAKMA,
+ HB_SCRIPT_MEROITIC_CURSIVE,
+ HB_SCRIPT_MEROITIC_HIEROGLYPHS,
+ HB_SCRIPT_MIAO,
+ HB_SCRIPT_SHARADA,
+ HB_SCRIPT_SORA_SOMPENG,
+ HB_SCRIPT_TAKRI
+};
+Q_STATIC_ASSERT(QChar::ScriptCount == sizeof(_qtscript_to_hbscript) / sizeof(_qtscript_to_hbscript[0]));
+
+hb_script_t hb_qt_script_to_script(QChar::Script script)
+{
+ return _qtscript_to_hbscript[script];
+}
+
+QChar::Script hb_qt_script_from_script(hb_script_t script)
+{
+ uint i = QChar::ScriptCount - 1;
+ while (i > QChar::Script_Unknown && _qtscript_to_hbscript[i] != script)
+ --i;
+ return QChar::Script(i);
+}
+
+
+static hb_unicode_combining_class_t
+_hb_qt_unicode_combining_class(hb_unicode_funcs_t * /*ufuncs*/,
+ hb_codepoint_t unicode,
+ void * /*user_data*/)
+{
+ return hb_unicode_combining_class_t(QChar::combiningClass(unicode));
+}
+
+static unsigned int
+_hb_qt_unicode_eastasian_width(hb_unicode_funcs_t * /*ufuncs*/,
+ hb_codepoint_t /*unicode*/,
+ void * /*user_data*/)
+{
+ qCritical("hb_qt_unicode_eastasian_width: not implemented!");
+ return 1;
+}
+
+static const hb_unicode_general_category_t _qtcategory_to_hbcategory[] = {
+ HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK, // Mn
+ HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK, // Mc
+ HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK, // Me
+
+ HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER, // Nd
+ HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER, // Nl
+ HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER, // No
+
+ HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR, // Zs
+ HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR, // Zl
+ HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR, // Zp
+
+ HB_UNICODE_GENERAL_CATEGORY_CONTROL, // Cc
+ HB_UNICODE_GENERAL_CATEGORY_FORMAT, // Cf
+ HB_UNICODE_GENERAL_CATEGORY_SURROGATE, // Cs
+ HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE, // Co
+ HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED, // Cn
+
+ HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER, // Lu
+ HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER, // Ll
+ HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER, // Lt
+ HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER, // Lm
+ HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER, // Lo
+
+ HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION, // Pc
+ HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION, // Pd
+ HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION, // Ps
+ HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION, // Pe
+ HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION, // Pi
+ HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION, // Pf
+ HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION, // Po
+
+ HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL, // Sm
+ HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL, // Sc
+ HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL, // Sk
+ HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL // So
+};
+
+static hb_unicode_general_category_t
+_hb_qt_unicode_general_category(hb_unicode_funcs_t * /*ufuncs*/,
+ hb_codepoint_t unicode,
+ void * /*user_data*/)
+{
+ return _qtcategory_to_hbcategory[QChar::category(unicode)];
+}
+
+static hb_codepoint_t
+_hb_qt_unicode_mirroring(hb_unicode_funcs_t * /*ufuncs*/,
+ hb_codepoint_t unicode,
+ void * /*user_data*/)
+{
+ return QChar::mirroredChar(unicode);
+}
+
+static hb_script_t
+_hb_qt_unicode_script(hb_unicode_funcs_t * /*ufuncs*/,
+ hb_codepoint_t unicode,
+ void * /*user_data*/)
+{
+ return _qtscript_to_hbscript[QChar::script(unicode)];
+}
+
+static hb_bool_t
+_hb_qt_unicode_compose(hb_unicode_funcs_t * /*ufuncs*/,
+ hb_codepoint_t a, hb_codepoint_t b,
+ hb_codepoint_t *ab,
+ void * /*user_data*/)
+{
+ // ### optimize
+ QString s = QString::fromUcs4(&a, 1) + QString::fromUcs4(&b, 1);
+ QString normalized = s.normalized(QString::NormalizationForm_C);
+ if (normalized.isEmpty())
+ return false;
+
+ QVector<uint> ucs4str = normalized.toUcs4();
+ if (ucs4str.size() == 1) {
+ *ab = ucs4str.at(0);
+ return true;
+ }
+
+ return false;
+}
+
+static hb_bool_t
+_hb_qt_unicode_decompose(hb_unicode_funcs_t * /*ufuncs*/,
+ hb_codepoint_t ab,
+ hb_codepoint_t *a, hb_codepoint_t *b,
+ void * /*user_data*/)
+{
+ // ### optimize
+ if (QChar::decompositionTag(ab) != QChar::Canonical) // !NFD
+ return false;
+
+ QString normalized = QChar::decomposition(ab);
+ Q_ASSERT(!normalized.isEmpty());
+
+ const QVector<uint> ucs4str = normalized.toUcs4();
+ Q_ASSERT(ucs4str.size() <= HB_UNICODE_MAX_DECOMPOSITION_LEN);
+
+ if (ucs4str.size() == 1) {
+ *a = ucs4str.at(0);
+ *b = 0;
+ return *a != ab;
+ }
+
+ if (ucs4str.size() == 2) {
+ *a = ucs4str.at(0);
+ *b = ucs4str.at(1);
+
+ // Here's the ugly part: if ab decomposes to a single character and
+ // that character decomposes again, we have to detect that and undo
+ // the second part :-(
+ QString recomposed = normalized.normalized(QString::NormalizationForm_C);
+ if (recomposed.isEmpty() || recomposed == normalized)
+ return false;
+
+ hb_codepoint_t c = recomposed.toUcs4().at(0);
+ if (c != *a && c != ab) {
+ *a = c;
+ *b = 0;
+ }
+ return true;
+ }
+
+ // If decomposed to more than two characters, take the last one,
+ // and recompose the rest to get the first component
+ *b = ucs4str.last();
+ normalized.chop(1);
+ QString recomposed = normalized.normalized(QString::NormalizationForm_C);
+ if (recomposed.isEmpty() || recomposed == normalized)
+ return false;
+
+ // We expect that recomposed has exactly one character now
+ *a = recomposed.toUcs4().at(0);
+
+ return true;
+}
+
+static unsigned int
+_hb_qt_unicode_decompose_compatibility(hb_unicode_funcs_t * /*ufuncs*/,
+ hb_codepoint_t u,
+ hb_codepoint_t *decomposed,
+ void * /*user_data*/)
+{
+ if (QChar::decompositionTag(u) == QChar::NoDecomposition) // !NFKD
+ return 0;
+
+ const QString normalized = QChar::decomposition(u);
+
+ uint outlen = 0;
+
+ // ### replace with QCharIterator
+ const ushort *p = reinterpret_cast<const ushort *>(normalized.unicode());
+ const ushort *const e = p + normalized.size();
+ for ( ; p != e; ++p) {
+ uint ucs4 = *p;
+ if (QChar::isHighSurrogate(ucs4) && p + 1 != e && QChar::isLowSurrogate(p[1]))
+ ucs4 = QChar::surrogateToUcs4(ucs4, *++p);
+ Q_ASSERT(outlen < HB_UNICODE_MAX_DECOMPOSITION_LEN);
+ decomposed[outlen++] = ucs4;
+ }
+
+ return outlen;
+}
+
+
+struct _hb_unicode_funcs_t {
+ _hb_unicode_funcs_t()
+ {
+ funcs = hb_unicode_funcs_create(NULL);
+ hb_unicode_funcs_set_combining_class_func(funcs, _hb_qt_unicode_combining_class, NULL, NULL);
+ hb_unicode_funcs_set_eastasian_width_func(funcs, _hb_qt_unicode_eastasian_width, NULL, NULL);
+ hb_unicode_funcs_set_general_category_func(funcs, _hb_qt_unicode_general_category, NULL, NULL);
+ hb_unicode_funcs_set_mirroring_func(funcs, _hb_qt_unicode_mirroring, NULL, NULL);
+ hb_unicode_funcs_set_script_func(funcs, _hb_qt_unicode_script, NULL, NULL);
+ hb_unicode_funcs_set_compose_func(funcs, _hb_qt_unicode_compose, NULL, NULL);
+ hb_unicode_funcs_set_decompose_func(funcs, _hb_qt_unicode_decompose, NULL, NULL);
+ hb_unicode_funcs_set_decompose_compatibility_func(funcs, _hb_qt_unicode_decompose_compatibility, NULL, NULL);
+ }
+ ~_hb_unicode_funcs_t()
+ {
+ hb_unicode_funcs_destroy(funcs);
+ }
+
+ hb_unicode_funcs_t *funcs;
+};
+
+Q_GLOBAL_STATIC(_hb_unicode_funcs_t, qt_ufuncs)
+
+hb_unicode_funcs_t *hb_qt_get_unicode_funcs()
+{
+ return qt_ufuncs()->funcs;
+}
+
+
+// Font routines
+
+static hb_bool_t
+_hb_qt_font_get_glyph(hb_font_t * /*font*/, void *font_data,
+ hb_codepoint_t unicode, hb_codepoint_t /*variation_selector*/,
+ hb_codepoint_t *glyph,
+ void * /*user_data*/)
+{
+ QFontEngine *fe = (QFontEngine *)font_data;
+ Q_ASSERT(fe);
+
+ glyph_t glyphs[2] = { 0, 0 };
+
+ QGlyphLayout g;
+ g.numGlyphs = 2;
+ g.glyphs = glyphs;
+
+ QChar chars[4];
+ int numChars = 0;
+ if (Q_UNLIKELY(QChar::requiresSurrogates(unicode))) {
+ chars[numChars++] = QChar(QChar::highSurrogate(unicode));
+ chars[numChars++] = QChar(QChar::lowSurrogate(unicode));
+ } else {
+ chars[numChars++] = QChar(unicode);
+ }
+#if 0
+ if (Q_UNLIKELY(variation_selector != 0)) {
+ if (Q_UNLIKELY(QChar::requiresSurrogates(variation_selector))) {
+ chars[numChars++] = QChar(QChar::highSurrogate(variation_selector));
+ chars[numChars++] = QChar(QChar::lowSurrogate(variation_selector));
+ } else {
+ chars[numChars++] = QChar(variation_selector);
+ }
+ }
+#endif
+
+ int numGlyphs = g.numGlyphs;
+ bool ok = fe->stringToCMap(chars, numChars, &g, &numGlyphs, QFontEngine::GlyphIndicesOnly);
+ Q_ASSERT(ok); Q_UNUSED(ok)
+
+ *glyph = g.glyphs[0];
+
+ return true;
+}
+
+static hb_position_t
+_hb_qt_font_get_glyph_h_advance(hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ void * /*user_data*/)
+{
+ QFontEngine *fe = (QFontEngine *)font_data;
+ Q_ASSERT(fe);
+
+ QFixed advance_x;
+ QFixed advance_y;
+
+ QGlyphLayout g;
+ g.numGlyphs = 1;
+ g.glyphs = &glyph;
+ g.advances_x = &advance_x;
+ g.advances_y = &advance_y;
+
+ fe->recalcAdvances(&g, QFontEngine::ShaperFlags(hb_qt_font_get_use_design_metrics(font)));
+
+ return g.advances_x[0].value();
+}
+
+static hb_position_t
+_hb_qt_font_get_glyph_v_advance(hb_font_t * /*font*/, void * /*font_data*/,
+ hb_codepoint_t /*glyph*/,
+ void * /*user_data*/)
+{
+ qCritical("hb_qt_font_get_glyph_v_advance: vertical writing isn't supported!");
+ return 0;
+}
+
+static hb_bool_t
+_hb_qt_font_get_glyph_h_origin(hb_font_t * /*font*/, void * /*font_data*/,
+ hb_codepoint_t /*glyph*/,
+ hb_position_t * /*x*/, hb_position_t * /*y*/,
+ void * /*user_data*/)
+{
+ return true; // we always work in the horizontal coordinates
+}
+
+static hb_bool_t
+_hb_qt_font_get_glyph_v_origin(hb_font_t * /*font*/, void * /*font_data*/,
+ hb_codepoint_t /*glyph*/,
+ hb_position_t * /*x*/, hb_position_t * /*y*/,
+ void * /*user_data*/)
+{
+ qCritical("hb_qt_get_glyph_v_origin: vertical writing isn't supported!");
+ return false;
+}
+
+static hb_position_t
+_hb_qt_font_get_glyph_h_kerning(hb_font_t *font, void *font_data,
+ hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+ void * /*user_data*/)
+{
+ QFontEngine *fe = (QFontEngine *)font_data;
+ Q_ASSERT(fe);
+
+ glyph_t glyphs[2] = { first_glyph, second_glyph };
+ QFixed advance_x;
+ QFixed advance_y;
+
+ QGlyphLayout g;
+ g.numGlyphs = 2;
+ g.glyphs = glyphs;
+ g.advances_x = &advance_x;
+ g.advances_y = &advance_y;
+
+ fe->doKerning(&g, QFontEngine::ShaperFlags(hb_qt_font_get_use_design_metrics(font)));
+
+ return g.advances_x[0].value();
+}
+
+static hb_position_t
+_hb_qt_font_get_glyph_v_kerning(hb_font_t * /*font*/, void * /*font_data*/,
+ hb_codepoint_t /*first_glyph*/, hb_codepoint_t /*second_glyph*/,
+ void * /*user_data*/)
+{
+ qCritical("hb_qt_get_glyph_v_kerning: vertical writing isn't supported!");
+ return 0;
+}
+
+static hb_bool_t
+_hb_qt_font_get_glyph_extents(hb_font_t * /*font*/, void *font_data,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ void * /*user_data*/)
+{
+ QFontEngine *fe = (QFontEngine *)font_data;
+ Q_ASSERT(fe);
+
+ glyph_metrics_t gm = fe->boundingBox(glyph);
+
+ extents->x_bearing = gm.x.value();
+ extents->y_bearing = gm.y.value();
+ extents->width = gm.width.value();
+ extents->height = gm.height.value();
+
+ return true;
+}
+
+static hb_bool_t
+_hb_qt_font_get_glyph_contour_point(hb_font_t * /*font*/, void *font_data,
+ hb_codepoint_t glyph,
+ unsigned int point_index, hb_position_t *x, hb_position_t *y,
+ void * /*user_data*/)
+{
+ QFontEngine *fe = (QFontEngine *)font_data;
+ Q_ASSERT(fe);
+
+ QFixed xpos, ypos;
+ quint32 numPoints = 1;
+ if (Q_LIKELY(fe->getPointInOutline(glyph, 0, point_index, &xpos, &ypos, &numPoints) == 0)) {
+ *x = xpos.value();
+ *y = ypos.value();
+ return true;
+ }
+
+ *x = *y = 0;
+ return false;
+}
+
+static hb_bool_t
+_hb_qt_font_get_glyph_name(hb_font_t * /*font*/, void * /*font_data*/,
+ hb_codepoint_t /*glyph*/,
+ char *name, unsigned int size,
+ void * /*user_data*/)
+{
+ qCritical("hb_qt_font_get_glyph_name: not implemented!");
+ if (size)
+ *name = '\0';
+ return false;
+}
+
+static hb_bool_t
+_hb_qt_font_get_glyph_from_name(hb_font_t * /*font*/, void * /*font_data*/,
+ const char * /*name*/, int /*len*/,
+ hb_codepoint_t *glyph,
+ void * /*user_data*/)
+{
+ qCritical("hb_qt_font_get_glyph_from_name: not implemented!");
+ *glyph = 0;
+ return false;
+}
+
+
+static hb_user_data_key_t _useDesignMetricsKey;
+
+void hb_qt_font_set_use_design_metrics(hb_font_t *font, uint value)
+{
+ hb_font_set_user_data(font, &_useDesignMetricsKey, (void *)value, NULL, true);
+}
+
+uint hb_qt_font_get_use_design_metrics(hb_font_t *font)
+{
+ return uint(hb_font_get_user_data(font, &_useDesignMetricsKey));
+}
+
+
+struct _hb_qt_font_funcs_t {
+ _hb_qt_font_funcs_t()
+ {
+ funcs = hb_font_funcs_create();
+ hb_font_funcs_set_glyph_func(funcs, _hb_qt_font_get_glyph, NULL, NULL);
+ hb_font_funcs_set_glyph_h_advance_func(funcs, _hb_qt_font_get_glyph_h_advance, NULL, NULL);
+ hb_font_funcs_set_glyph_v_advance_func(funcs, _hb_qt_font_get_glyph_v_advance, NULL, NULL);
+ hb_font_funcs_set_glyph_h_origin_func(funcs, _hb_qt_font_get_glyph_h_origin, NULL, NULL);
+ hb_font_funcs_set_glyph_v_origin_func(funcs, _hb_qt_font_get_glyph_v_origin, NULL, NULL);
+ hb_font_funcs_set_glyph_h_kerning_func(funcs, _hb_qt_font_get_glyph_h_kerning, NULL, NULL);
+ hb_font_funcs_set_glyph_v_kerning_func(funcs, _hb_qt_font_get_glyph_v_kerning, NULL, NULL);
+ hb_font_funcs_set_glyph_extents_func(funcs, _hb_qt_font_get_glyph_extents, NULL, NULL);
+ hb_font_funcs_set_glyph_contour_point_func(funcs, _hb_qt_font_get_glyph_contour_point, NULL, NULL);
+ hb_font_funcs_set_glyph_name_func(funcs, _hb_qt_font_get_glyph_name, NULL, NULL);
+ hb_font_funcs_set_glyph_from_name_func(funcs, _hb_qt_font_get_glyph_from_name, NULL, NULL);
+ }
+ ~_hb_qt_font_funcs_t()
+ {
+ hb_font_funcs_destroy(funcs);
+ }
+
+ hb_font_funcs_t *funcs;
+};
+
+Q_GLOBAL_STATIC(_hb_qt_font_funcs_t, qt_ffuncs)
+
+hb_font_funcs_t *hb_qt_get_font_funcs()
+{
+ return qt_ffuncs()->funcs;
+}
+
+
+static hb_blob_t *
+_hb_qt_get_font_table(hb_face_t * /*face*/, hb_tag_t tag, void *user_data)
+{
+ QFontEngine *fe = (QFontEngine *)user_data;
+ Q_ASSERT(fe);
+
+ uint length = 0;
+ if (Q_UNLIKELY(!fe->getSfntTableData(tag, 0, &length) || length == 0))
+ return hb_blob_get_empty();
+
+ char *buffer = (char *)malloc(length);
+ Q_CHECK_PTR(buffer);
+
+ if (Q_UNLIKELY(!fe->getSfntTableData(tag, reinterpret_cast<uchar *>(buffer), &length)))
+ length = 0;
+
+ return hb_blob_create(const_cast<const char *>(buffer), length,
+ HB_MEMORY_MODE_WRITABLE,
+ buffer, free);
+}
+
+static inline hb_face_t *
+_hb_qt_face_create(QFontEngine *fe)
+{
+ hb_face_t *face;
+
+ face = hb_face_create_for_tables(_hb_qt_get_font_table, (void *)fe, NULL);
+ if (Q_UNLIKELY(hb_face_is_immutable(face))) {
+ hb_face_destroy(face);
+ return NULL;
+ }
+
+ hb_face_set_index(face, fe->faceId().index);
+ hb_face_set_upem(face, fe->emSquareSize().truncate());
+
+ return face;
+}
+
+static void
+_hb_qt_face_release(void *user_data)
+{
+ if (Q_LIKELY(user_data))
+ hb_face_destroy((hb_face_t *)user_data);
+}
+
+hb_face_t *hb_qt_face_get_for_engine(QFontEngine *fe)
+{
+ if (Q_UNLIKELY(!fe->face_)) {
+ fe->face_ = _hb_qt_face_create(fe);
+ if (Q_UNLIKELY(!fe->face_))
+ return NULL;
+ fe->face_destroy_func = _hb_qt_face_release;
+ }
+
+ return hb_face_reference((hb_face_t *)fe->face_);
+}
+
+
+static inline hb_font_t *
+_hb_qt_font_create(QFontEngine *fe)
+{
+ Q_ASSERT(fe);
+
+ hb_face_t *face = hb_qt_face_get_for_engine(fe);
+ if (Q_UNLIKELY(!face))
+ return NULL;
+
+ hb_font_t *font = hb_font_create(face);
+
+ hb_face_destroy(face); // ref-ed in hb_qt_face_get_for_engine()
+
+ if (Q_UNLIKELY(hb_font_is_immutable(font))) {
+ hb_font_destroy(font);
+ return NULL;
+ }
+
+ const int y_ppem = fe->fontDef.pixelSize;
+ const int x_ppem = (fe->fontDef.pixelSize * fe->fontDef.stretch) / 100;
+
+ hb_font_set_funcs(font, hb_qt_get_font_funcs(), (void *)fe, NULL);
+ hb_font_set_scale(font, QFixed(x_ppem).value(), -QFixed(y_ppem).value());
+ hb_font_set_ppem(font, x_ppem, y_ppem);
+
+ return font;
+}
+
+static void
+_hb_qt_font_release(void *user_data)
+{
+ if (Q_LIKELY(user_data))
+ hb_font_destroy((hb_font_t *)user_data);
+}
+
+hb_font_t *hb_qt_font_get_for_engine(QFontEngine *fe)
+{
+ if (Q_UNLIKELY(!fe->font_)) {
+ fe->font_ = _hb_qt_font_create(fe);
+ if (Q_UNLIKELY(!fe->font_))
+ return NULL;
+ fe->font_destroy_func = _hb_qt_font_release;
+ }
+
+ return hb_font_reference((hb_font_t *)fe->font_);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qharfbuzzng_p.h b/src/gui/text/qharfbuzzng_p.h
new file mode 100644
index 0000000000..10cac69875
--- /dev/null
+++ b/src/gui/text/qharfbuzzng_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2013 Konstantin Ritt
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHARFBUZZNG_P_H
+#define QHARFBUZZNG_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qchar.h>
+
+#include <harfbuzz/hb.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFontEngine;
+
+// Unicode
+
+Q_GUI_EXPORT hb_script_t hb_qt_script_to_script(QChar::Script script);
+Q_GUI_EXPORT QChar::Script hb_qt_script_from_script(hb_script_t script);
+
+Q_GUI_EXPORT hb_unicode_funcs_t *hb_qt_get_unicode_funcs();
+
+
+// Font
+
+Q_GUI_EXPORT hb_font_funcs_t *hb_qt_get_font_funcs();
+
+Q_GUI_EXPORT hb_face_t *hb_qt_face_get_for_engine(QFontEngine *fe);
+Q_GUI_EXPORT hb_font_t *hb_qt_font_get_for_engine(QFontEngine *fe);
+
+Q_GUI_EXPORT void hb_qt_font_set_use_design_metrics(hb_font_t *font, uint value);
+Q_GUI_EXPORT uint hb_qt_font_get_use_design_metrics(hb_font_t *font);
+
+QT_END_NAMESPACE
+
+#endif // QHARFBUZZNG_P_H
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 7a12b241e8..c690fed996 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -868,6 +868,9 @@ void QTextEngine::shapeLine(const QScriptLine &line)
}
}
+#ifdef QT_ENABLE_HARFBUZZ_NG
+extern bool useHarfbuzzNG; // defined in qfontengine.cpp
+#endif
void QTextEngine::shapeText(int item) const
{
@@ -883,9 +886,6 @@ void QTextEngine::shapeText(int item) const
const ushort *string = reinterpret_cast<const ushort *>(layoutData->string.constData()) + si.position;
const int itemLength = length(item);
- if (!ensureSpace(itemLength))
- return; // ### report OOM error somehow
-
QString casedString;
if (si.analysis.flags && si.analysis.flags <= QScriptAnalysis::SmallCaps) {
casedString.resize(itemLength);
@@ -910,8 +910,61 @@ void QTextEngine::shapeText(int item) const
string = reinterpret_cast<const ushort *>(casedString.constData());
}
+ if (!ensureSpace(itemLength)) {
+ Q_UNREACHABLE(); // ### report OOM error somehow
+ return;
+ }
+
QFontEngine *fontEngine = this->fontEngine(si, &si.ascent, &si.descent, &si.leading);
+ // split up the item into parts that come from different font engines
+ QVector<uint> itemBoundaries;
+ itemBoundaries.reserve(16);
+ // k * 2 entries, array[k] == index in string, array[k + 1] == index in glyphs
+ itemBoundaries.append(0);
+ itemBoundaries.append(0);
+
+ if (fontEngine->type() == QFontEngine::Multi) {
+ // ask the font engine to find out which glyphs (as an index in the specific font)
+ // to use for the text in one item.
+ QGlyphLayout initialGlyphs = availableGlyphs(&si);
+
+ int nGlyphs = initialGlyphs.numGlyphs;
+ QFontEngine::ShaperFlags shaperFlags(QFontEngine::GlyphIndicesOnly);
+ if (si.analysis.bidiLevel % 2)
+ shaperFlags |= QFontEngine::RightToLeft;
+
+ if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags)) {
+ nGlyphs = qMax(nGlyphs, itemLength); // ### needed for QFontEngine::stringToCMap() to not fail twice
+ if (!ensureSpace(nGlyphs)) {
+ Q_UNREACHABLE(); // ### report OOM error somehow
+ return;
+ }
+ initialGlyphs = availableGlyphs(&si);
+ if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags)) {
+ Q_UNREACHABLE(); // ### if this happens there is a bug in the fontengine
+ return;
+ }
+ }
+
+ uint lastEngine = 0;
+ for (int i = 0, glyph_pos = 0; i < itemLength; ++i, ++glyph_pos) {
+ const uint engineIdx = initialGlyphs.glyphs[glyph_pos] >> 24;
+ if (lastEngine != engineIdx && glyph_pos > 0) {
+ itemBoundaries.append(i);
+ itemBoundaries.append(glyph_pos);
+
+ lastEngine = engineIdx;
+ QFontEngine *actualFontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx);
+ si.ascent = qMax(actualFontEngine->ascent(), si.ascent);
+ si.descent = qMax(actualFontEngine->descent(), si.descent);
+ si.leading = qMax(actualFontEngine->leading(), si.leading);
+ }
+ if (QChar::isHighSurrogate(string[i]) && i + 1 < itemLength && QChar::isLowSurrogate(string[i + 1]))
+ ++i;
+ }
+ }
+
bool kerningEnabled;
bool letterSpacingIsAbsolute;
QFixed letterSpacing, wordSpacing;
@@ -935,9 +988,18 @@ void QTextEngine::shapeText(int item) const
letterSpacing *= font.d->dpi / qt_defaultDpiY();
}
- si.num_glyphs = shapeTextWithHarfbuzz(si, string, itemLength, fontEngine, kerningEnabled);
- if (!si.num_glyphs)
- return; // ### report shaping errors somehow
+#ifdef QT_ENABLE_HARFBUZZ_NG
+ if (useHarfbuzzNG)
+ si.num_glyphs = shapeTextWithHarfbuzzNG(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled);
+ else
+#endif
+ si.num_glyphs = shapeTextWithHarfbuzz(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled);
+ if (si.num_glyphs == 0) {
+ Q_UNREACHABLE(); // ### report shaping errors somehow
+ return;
+ }
+
+
layoutData->used += si.num_glyphs;
QGlyphLayout glyphs = shapedGlyphs(&si);
@@ -987,6 +1049,163 @@ static inline void moveGlyphData(const QGlyphLayout &destination, const QGlyphLa
}
}
+#ifdef QT_ENABLE_HARFBUZZ_NG
+
+QT_BEGIN_INCLUDE_NAMESPACE
+
+#include "qharfbuzzng_p.h"
+
+QT_END_INCLUDE_NAMESPACE
+
+int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const
+{
+ hb_buffer_t *buffer = hb_buffer_create();
+ hb_buffer_set_unicode_funcs(buffer, hb_qt_get_unicode_funcs());
+ hb_buffer_pre_allocate(buffer, itemLength);
+ if (!hb_buffer_allocation_successful(buffer)) {
+ hb_buffer_destroy(buffer);
+ return 0;
+ }
+
+ hb_segment_properties_t props = HB_SEGMENT_PROPERTIES_DEFAULT;
+ props.direction = si.analysis.bidiLevel % 2 ? HB_DIRECTION_RTL : HB_DIRECTION_LTR;
+ props.script = hb_qt_script_to_script(QChar::Script(si.analysis.script));
+ // ### props.language = hb_language_get_default_for_script(props.script);
+
+ uint glyphs_shaped = 0;
+ int remaining_glyphs = itemLength;
+
+ for (int k = 0; k < itemBoundaries.size(); k += 2) { // for the +2, see the comment at the definition of itemBoundaries
+ uint item_pos = itemBoundaries[k];
+ uint item_length = itemLength;
+ uint item_glyph_pos = itemBoundaries[k + 1];
+ if (k + 3 < itemBoundaries.size())
+ item_length = itemBoundaries[k + 2];
+ item_length -= item_pos;
+
+ QFontEngine *actualFontEngine = fontEngine;
+ uint engineIdx = 0;
+ if (fontEngine->type() == QFontEngine::Multi) {
+ engineIdx = availableGlyphs(&si).glyphs[glyphs_shaped] >> 24;
+ actualFontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx);
+ }
+
+
+ // prepare buffer
+ hb_buffer_clear_contents(buffer);
+ hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16_t *>(string) + item_pos, item_length, 0, item_length);
+
+ hb_buffer_set_segment_properties(buffer, &props);
+ hb_buffer_guess_segment_properties(buffer);
+
+ uint buffer_flags = HB_BUFFER_FLAG_DEFAULT;
+ // Symbol encoding used to encode various crap in the 32..255 character code range,
+ // and thus might override U+00AD [SHY]; avoid hiding default ignorables
+ if (actualFontEngine->symbol)
+ buffer_flags |= HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES;
+ hb_buffer_set_flags(buffer, hb_buffer_flags_t(buffer_flags));
+
+ const uint num_codes = hb_buffer_get_length(buffer);
+ {
+ // adjust clusters
+ hb_glyph_info_t *infos = hb_buffer_get_glyph_infos(buffer, 0);
+ const ushort *uc = string + item_pos;
+ for (uint i = 0, code_pos = 0; i < item_length; ++i, ++code_pos) {
+ if (QChar::isHighSurrogate(uc[i]) && i + 1 < item_length && QChar::isLowSurrogate(uc[i + 1]))
+ ++i;
+ infos[code_pos].cluster = code_pos + item_glyph_pos;
+ }
+ }
+
+
+ // shape
+ bool shapedOk = false;
+ if (hb_font_t *hb_font = hb_qt_font_get_for_engine(actualFontEngine)) {
+ hb_qt_font_set_use_design_metrics(hb_font, option.useDesignMetrics() ? uint(QFontEngine::DesignMetrics) : 0); // ###
+
+ const hb_feature_t features[1] = {
+ { HB_TAG('k','e','r','n'), !!kerningEnabled, 0, -1 }
+ };
+ const int num_features = 1;
+ shapedOk = hb_shape_full(hb_font, buffer, features, num_features, 0);
+
+ hb_font_destroy(hb_font);
+ }
+ if (!shapedOk) {
+ hb_buffer_destroy(buffer);
+ return 0;
+ }
+
+ if (si.analysis.bidiLevel % 2)
+ hb_buffer_reverse(buffer);
+
+
+ remaining_glyphs -= num_codes;
+
+ // ensure we have enough space for shaped glyphs and metrics
+ const uint num_glyphs = hb_buffer_get_length(buffer);
+ if (num_glyphs == 0 || !ensureSpace(glyphs_shaped + num_glyphs + remaining_glyphs)) {
+ hb_buffer_destroy(buffer);
+ return 0;
+ }
+
+ // fetch the shaped glyphs and metrics
+ QGlyphLayout g = availableGlyphs(&si).mid(glyphs_shaped, num_glyphs);
+ if (num_glyphs > num_codes)
+ moveGlyphData(g.mid(num_glyphs), g.mid(num_codes), remaining_glyphs);
+ ushort *log_clusters = logClusters(&si) + item_pos;
+
+ hb_glyph_info_t *infos = hb_buffer_get_glyph_infos(buffer, 0);
+ hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer, 0);
+ uint last_cluster = -1;
+ for (uint i = 0; i < num_glyphs; ++i) {
+ g.glyphs[i] = infos[i].codepoint;
+ log_clusters[i] = infos[i].cluster;
+
+ g.advances_x[i] = QFixed::fromFixed(positions[i].x_advance);
+ g.advances_y[i] = QFixed::fromFixed(positions[i].y_advance);
+ g.offsets[i].x = QFixed::fromFixed(positions[i].x_offset);
+ g.offsets[i].y = QFixed::fromFixed(positions[i].y_offset);
+
+ if (infos[i].cluster != last_cluster) {
+ last_cluster = infos[i].cluster;
+ g.attributes[i].clusterStart = true;
+ }
+ }
+
+ {
+ // adjust clusters
+ uint glyph_pos = 0;
+ for (uint i = 0; i < item_length; ++i) {
+ if (i + item_pos != infos[glyph_pos].cluster) {
+ for (uint j = glyph_pos + 1; j < num_glyphs; ++j) {
+ if (i + item_pos <= infos[j].cluster) {
+ if (i + item_pos == infos[j].cluster)
+ glyph_pos = j;
+ break;
+ }
+ }
+ }
+ log_clusters[i] = glyph_pos + item_glyph_pos;
+ }
+ }
+
+ if (engineIdx != 0) {
+ for (quint32 i = 0; i < num_glyphs; ++i)
+ g.glyphs[i] |= (engineIdx << 24);
+ }
+
+ glyphs_shaped += num_glyphs;
+ }
+
+ hb_buffer_destroy(buffer);
+
+ return glyphs_shaped;
+}
+
+#endif // QT_ENABLE_HARFBUZZ_NG
+
+
QT_BEGIN_INCLUDE_NAMESPACE
#include <private/qharfbuzz_p.h>
@@ -998,22 +1217,7 @@ Q_STATIC_ASSERT(sizeof(HB_GlyphAttributes) == sizeof(QGlyphAttributes));
Q_STATIC_ASSERT(sizeof(HB_Fixed) == sizeof(QFixed));
Q_STATIC_ASSERT(sizeof(HB_FixedPoint) == sizeof(QFixedPoint));
-// ask the font engine to find out which glyphs (as an index in the specific font) to use for the text in one item.
-static bool stringToGlyphs(HB_ShaperItem *item, QGlyphLayout *glyphs, QFontEngine *fontEngine)
-{
- int nGlyphs = item->num_glyphs;
-
- QFontEngine::ShaperFlags shaperFlags(QFontEngine::GlyphIndicesOnly);
- if (item->item.bidiLevel % 2)
- shaperFlags |= QFontEngine::RightToLeft;
-
- bool result = fontEngine->stringToCMap(reinterpret_cast<const QChar *>(item->string + item->item.pos), item->item.length, glyphs, &nGlyphs, shaperFlags);
- item->num_glyphs = nGlyphs;
- glyphs->numGlyphs = nGlyphs;
- return result;
-}
-
-int QTextEngine::shapeTextWithHarfbuzz(QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, bool kerningEnabled) const
+int QTextEngine::shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const
{
HB_ShaperItem entire_shaper_item;
memset(&entire_shaper_item, 0, sizeof(entire_shaper_item));
@@ -1030,45 +1234,13 @@ int QTextEngine::shapeTextWithHarfbuzz(QScriptItem &si, const ushort *string, in
if (option.useDesignMetrics())
entire_shaper_item.shaperFlags |= HB_ShaperFlag_UseDesignMetrics;
- entire_shaper_item.num_glyphs = itemLength;
-
- QGlyphLayout initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs);
-
- if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, fontEngine)) {
- if (!ensureSpace(entire_shaper_item.num_glyphs))
- return 0;
- initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs);
- if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, fontEngine)) {
- // ############ if this happens there's a bug in the fontengine
- return 0;
- }
+ // ensure we are not asserting in HB_HeuristicSetGlyphAttributes()
+ entire_shaper_item.num_glyphs = 0;
+ for (int i = 0; i < itemLength; ++i, ++entire_shaper_item.num_glyphs) {
+ if (QChar::isHighSurrogate(string[i]) && i + 1 < itemLength && QChar::isLowSurrogate(string[i + 1]))
+ ++i;
}
- // split up the item into parts that come from different font engines.
- QVarLengthArray<int> itemBoundaries(2);
- // k * 2 entries, array[k] == index in string, array[k + 1] == index in glyphs
- itemBoundaries[0] = entire_shaper_item.item.pos;
- itemBoundaries[1] = 0;
-
- if (fontEngine->type() == QFontEngine::Multi) {
- uint lastEngine = 0;
- int charIdx = entire_shaper_item.item.pos;
- const int stringEnd = charIdx + entire_shaper_item.item.length;
- for (quint32 i = 0; i < entire_shaper_item.num_glyphs; ++i, ++charIdx) {
- uint engineIdx = initialGlyphs.glyphs[i] >> 24;
- if (engineIdx != lastEngine && i > 0) {
- itemBoundaries.append(charIdx);
- itemBoundaries.append(i);
- }
- lastEngine = engineIdx;
- if (QChar::isHighSurrogate(entire_shaper_item.string[charIdx])
- && charIdx < stringEnd - 1
- && QChar::isLowSurrogate(entire_shaper_item.string[charIdx + 1]))
- ++charIdx;
- }
- }
-
-
int remaining_glyphs = entire_shaper_item.num_glyphs;
int glyph_pos = 0;
@@ -1093,18 +1265,14 @@ int QTextEngine::shapeTextWithHarfbuzz(QScriptItem &si, const ushort *string, in
uint engineIdx = 0;
if (fontEngine->type() == QFontEngine::Multi) {
engineIdx = uint(availableGlyphs(&si).glyphs[glyph_pos] >> 24);
-
actualFontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx);
- si.ascent = qMax(actualFontEngine->ascent(), si.ascent);
- si.descent = qMax(actualFontEngine->descent(), si.descent);
- si.leading = qMax(actualFontEngine->leading(), si.leading);
+
+ shaper_item.glyphIndicesPresent = true;
}
shaper_item.font = (HB_Font)actualFontEngine->harfbuzzFont();
shaper_item.face = (HB_Face)actualFontEngine->harfbuzzFace();
- shaper_item.glyphIndicesPresent = true;
-
remaining_glyphs -= shaper_item.initialGlyphCount;
do {
@@ -1366,13 +1534,22 @@ void QTextEngine::itemize() const
analysis->flags = QScriptAnalysis::None;
break;
}
- analysis->script = hbscript_to_script(script_to_hbscript(analysis->script)); // retain the old behavior
+#ifndef QT_ENABLE_HARFBUZZ_NG
+ analysis->script = hbscript_to_script(script_to_hbscript(analysis->script));
+#endif
++uc;
++analysis;
}
if (option.flags() & QTextOption::ShowLineAndParagraphSeparators) {
(analysis-1)->flags = QScriptAnalysis::LineOrParagraphSeparator; // to exclude it from width
}
+#ifdef QT_ENABLE_HARFBUZZ_NG
+ if (!useHarfbuzzNG) {
+ analysis = scriptAnalysis.data();
+ for (int i = 0; i < length; ++i)
+ analysis[i].script = hbscript_to_script(script_to_hbscript(analysis[i].script));
+ }
+#endif
Itemizer itemizer(layoutData->string, scriptAnalysis.data(), layoutData->items);
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index b3ab9a42d8..fb71ab40b8 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -668,7 +668,10 @@ private:
void setBoundary(int strPos) const;
void addRequiredBoundaries() const;
void shapeText(int item) const;
- int shapeTextWithHarfbuzz(QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, bool kerningEnabled) const;
+#ifdef QT_ENABLE_HARFBUZZ_NG
+ int shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const;
+#endif
+ int shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const;
void splitItem(int item, int pos) const;
int endOfLine(int lineNum);
diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri
index e9ea2a3f83..59a6f346e2 100644
--- a/src/gui/text/text.pri
+++ b/src/gui/text/text.pri
@@ -84,3 +84,12 @@ SOURCES += \
HEADERS += \
text/qplatformfontdatabase.h
+
+contains(QT_CONFIG, harfbuzz)|contains(QT_CONFIG, system-harfbuzz) {
+ DEFINES += QT_ENABLE_HARFBUZZ_NG
+
+ include($$PWD/../../3rdparty/harfbuzz.pri)
+
+ SOURCES += text/qharfbuzzng.cpp
+ HEADERS += text/qharfbuzzng_p.h
+}
diff --git a/src/network/kernel/qdnslookup_android.cpp b/src/network/kernel/qdnslookup_android.cpp
index ed12c02bbf..dff81dba0c 100644
--- a/src/network/kernel/qdnslookup_android.cpp
+++ b/src/network/kernel/qdnslookup_android.cpp
@@ -45,6 +45,9 @@ QT_BEGIN_NAMESPACE
void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, QDnsLookupReply *reply)
{
+ Q_UNUSED(requestType);
+ Q_UNUSED(requestName);
+ Q_UNUSED(reply);
qWarning() << Q_FUNC_INFO << "Not yet supported on Android";
reply->error = QDnsLookup::ResolverError;
reply->errorString = tr("Not yet supported on Android");
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 4c94c4dbb9..e076f2b4bf 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -741,7 +741,7 @@ QNetworkInterface QNativeSocketEnginePrivate::nativeMulticastInterface() const
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)) {
+ if (v.s_addr != 0 && sizeofv >= QT_SOCKOPTLEN_T(sizeof(v))) {
QHostAddress ipv4(ntohl(v.s_addr));
QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
for (int i = 0; i < ifaces.count(); ++i) {
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 3f496a4ffc..f1ce2cfae3 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -4467,13 +4467,13 @@ void QGLWidget::renderText(double x, double y, double z, const QString &str, con
int width = d->glcx->device()->width();
int height = d->glcx->device()->height();
- GLdouble model[4][4], proj[4][4];
+ GLdouble model[4 * 4], proj[4 * 4];
GLint view[4];
- glGetDoublev(GL_MODELVIEW_MATRIX, &model[0][0]);
- glGetDoublev(GL_PROJECTION_MATRIX, &proj[0][0]);
+ glGetDoublev(GL_MODELVIEW_MATRIX, &model[0]);
+ glGetDoublev(GL_PROJECTION_MATRIX, &proj[0]);
glGetIntegerv(GL_VIEWPORT, &view[0]);
GLdouble win_x = 0, win_y = 0, win_z = 0;
- qgluProject(x, y, z, &model[0][0], &proj[0][0], &view[0],
+ qgluProject(x, y, z, &model[0], &proj[0], &view[0],
&win_x, &win_y, &win_z);
win_y = height - win_y; // y is inverted
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h b/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h
index d895da35bf..2d93d236e5 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h
@@ -49,7 +49,6 @@ QT_BEGIN_NAMESPACE
class QFontEngineMultiFontConfig : public QFontEngineMultiQPA
{
- Q_OBJECT
public:
explicit QFontEngineMultiFontConfig(QFontEngine *fe, int script);
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
index 577bb25e95..7ef9f0dfbb 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
@@ -57,7 +57,6 @@ QT_BEGIN_NAMESPACE
class QRawFontPrivate;
class QCoreTextFontEngine : public QFontEngine
{
- Q_OBJECT
public:
QCoreTextFontEngine(CTFontRef font, const QFontDef &def);
QCoreTextFontEngine(CGFontRef font, const QFontDef &def);
diff --git a/src/plugins/platforms/android/src/androidjniinput.cpp b/src/plugins/platforms/android/src/androidjniinput.cpp
index b31e74bb52..4a2d87d6a4 100644
--- a/src/plugins/platforms/android/src/androidjniinput.cpp
+++ b/src/plugins/platforms/android/src/androidjniinput.cpp
@@ -222,24 +222,11 @@ namespace QtAndroidInput
m_touchPoints.push_back(touchPoint);
}
- static void touchEnd(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint action)
+ static void touchEnd(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint /*action*/)
{
if (m_touchPoints.isEmpty())
return;
- QEvent::Type eventType = QEvent::None;
- switch (action) {
- case 0:
- eventType = QEvent::TouchBegin;
- break;
- case 1:
- eventType = QEvent::TouchUpdate;
- break;
- case 2:
- eventType = QEvent::TouchEnd;
- break;
- }
-
QAndroidPlatformIntegration *platformIntegration = QtAndroid::androidPlatformIntegration();
QTouchDevice *touchDevice = platformIntegration->touchDevice();
if (touchDevice == 0) {
diff --git a/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp b/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp
index 5a35310111..c6e3035476 100644
--- a/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp
+++ b/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp
@@ -98,6 +98,7 @@ QDpi QEglFSAndroidHooks::logicalDpi() const
EGLNativeWindowType QEglFSAndroidHooks::createNativeWindow(const QSize &size, const QSurfaceFormat &format)
{
Q_UNUSED(size);
+ Q_UNUSED(format);
ANativeWindow *window = QtAndroid::nativeWindow();
if (window != 0)
ANativeWindow_acquire(window);
diff --git a/src/plugins/platforms/android/src/qandroidplatformintegration.cpp b/src/plugins/platforms/android/src/qandroidplatformintegration.cpp
index 286d4cc7f2..d7ed3499af 100644
--- a/src/plugins/platforms/android/src/qandroidplatformintegration.cpp
+++ b/src/plugins/platforms/android/src/qandroidplatformintegration.cpp
@@ -82,7 +82,10 @@ void *QAndroidPlatformNativeInterface::nativeResourceForIntegration(const QByteA
return QtAndroid::javaVM();
if (resource == "QtActivity")
return QtAndroid::activity();
-
+ if (resource == "AndroidStylePalettes")
+ return &m_palettes;
+ if (resource == "AndroidStyleFonts")
+ return &m_fonts;
return 0;
}
@@ -246,7 +249,7 @@ QStringList QAndroidPlatformIntegration::themeNames() const
QPlatformTheme *QAndroidPlatformIntegration::createPlatformTheme(const QString &name) const
{
if (androidThemeName == name)
- return new QAndroidPlatformTheme;
+ return new QAndroidPlatformTheme(m_androidPlatformNativeInterface);
return 0;
}
diff --git a/src/plugins/platforms/android/src/qandroidplatformintegration.h b/src/plugins/platforms/android/src/qandroidplatformintegration.h
index 83d7028665..20aa52cf22 100644
--- a/src/plugins/platforms/android/src/qandroidplatformintegration.h
+++ b/src/plugins/platforms/android/src/qandroidplatformintegration.h
@@ -71,6 +71,8 @@ class QAndroidPlatformNativeInterface: public QPlatformNativeInterface
{
public:
void *nativeResourceForIntegration(const QByteArray &resource);
+ QHash<int, QPalette> m_palettes;
+ QHash<int, QFont> m_fonts;
};
class QAndroidPlatformIntegration
diff --git a/src/plugins/platforms/android/src/qandroidplatformtheme.cpp b/src/plugins/platforms/android/src/qandroidplatformtheme.cpp
index 25f2ade11a..9e08440eed 100644
--- a/src/plugins/platforms/android/src/qandroidplatformtheme.cpp
+++ b/src/plugins/platforms/android/src/qandroidplatformtheme.cpp
@@ -45,6 +45,12 @@
#include "qandroidplatformmenuitem.h"
#include <QVariant>
#include <QFileInfo>
+#include <qandroidplatformintegration.h>
+
+QAndroidPlatformTheme::QAndroidPlatformTheme(QAndroidPlatformNativeInterface *androidPlatformNativeInterface)
+{
+ m_androidPlatformNativeInterface = androidPlatformNativeInterface;
+}
QPlatformMenuBar *QAndroidPlatformTheme::createPlatformMenuBar() const
{
@@ -61,13 +67,76 @@ QPlatformMenuItem *QAndroidPlatformTheme::createPlatformMenuItem() const
return new QAndroidPlatformMenuItem;
}
+static inline int paletteType(QPlatformTheme::Palette type)
+{
+ switch (type) {
+ case QPlatformTheme::ToolButtonPalette:
+ case QPlatformTheme::ButtonPalette:
+ return QPlatformTheme::ButtonPalette;
+
+ case QPlatformTheme::CheckBoxPalette:
+ return QPlatformTheme::CheckBoxPalette;
+
+ case QPlatformTheme::RadioButtonPalette:
+ return QPlatformTheme::RadioButtonPalette;
+
+ case QPlatformTheme::ComboBoxPalette:
+ return QPlatformTheme::ComboBoxPalette;
+
+ case QPlatformTheme::TextEditPalette:
+ case QPlatformTheme::TextLineEditPalette:
+ return QPlatformTheme::TextLineEditPalette;
+
+ case QPlatformTheme::ItemViewPalette:
+ return QPlatformTheme::ItemViewPalette;
+
+ default:
+ return QPlatformTheme::SystemPalette;
+ }
+}
+
+const QPalette *QAndroidPlatformTheme::palette(Palette type) const
+{
+ QHash<int, QPalette>::const_iterator it = m_androidPlatformNativeInterface->m_palettes.find(paletteType(type));
+ if (it != m_androidPlatformNativeInterface->m_palettes.end())
+ return &(it.value());
+ return 0;
+}
+
+static inline int fontType(QPlatformTheme::Font type)
+{
+ switch (type) {
+ case QPlatformTheme::LabelFont:
+ return QPlatformTheme::SystemFont;
+
+ case QPlatformTheme::ToolButtonFont:
+ return QPlatformTheme::PushButtonFont;
+
+ default:
+ return type;
+ }
+}
+
+const QFont *QAndroidPlatformTheme::font(Font type) const
+{
+ QHash<int, QFont>::const_iterator it = m_androidPlatformNativeInterface->m_fonts.find(fontType(type));
+ if (it != m_androidPlatformNativeInterface->m_fonts.end())
+ return &(it.value());
+ return 0;
+}
+
+static const QLatin1String STYLES_PATH("/data/data/org.kde.necessitas.ministro/files/dl/style/");
+static const QLatin1String STYLE_FILE("/style.json");
+
QVariant QAndroidPlatformTheme::themeHint(ThemeHint hint) const
{
switch (hint) {
case StyleNames:
if (qgetenv("QT_USE_ANDROID_NATIVE_STYLE").toInt()
&& (!qgetenv("MINISTRO_ANDROID_STYLE_PATH").isEmpty()
- || QFileInfo("/data/data/org.kde.necessitas.ministro/files/qt/style/style.json").exists())) {
+ || QFileInfo(STYLES_PATH
+ + QLatin1String(qgetenv("QT_ANDROID_THEME_DISPLAY_DPI"))
+ + STYLE_FILE).exists())) {
return QStringList("android");
}
return QStringList("fusion");
diff --git a/src/plugins/platforms/android/src/qandroidplatformtheme.h b/src/plugins/platforms/android/src/qandroidplatformtheme.h
index 263878ee16..15d2cb2000 100644
--- a/src/plugins/platforms/android/src/qandroidplatformtheme.h
+++ b/src/plugins/platforms/android/src/qandroidplatformtheme.h
@@ -43,14 +43,20 @@
#define QANDROIDPLATFORMTHEME_H
#include <qpa/qplatformtheme.h>
-
+class QAndroidPlatformNativeInterface;
class QAndroidPlatformTheme: public QPlatformTheme
{
public:
+ QAndroidPlatformTheme(QAndroidPlatformNativeInterface * androidPlatformNativeInterface);
virtual QPlatformMenuBar *createPlatformMenuBar() const;
virtual QPlatformMenu *createPlatformMenu() const;
virtual QPlatformMenuItem *createPlatformMenuItem() const;
+ virtual const QPalette *palette(Palette type = SystemPalette) const;
+ virtual const QFont *font(Font type = SystemFont) const;
virtual QVariant themeHint(ThemeHint hint) const;
+
+private:
+ QAndroidPlatformNativeInterface * m_androidPlatformNativeInterface;
};
#endif // QANDROIDPLATFORMTHEME_H
diff --git a/src/plugins/platforms/kms/qkmsscreen.cpp b/src/plugins/platforms/kms/qkmsscreen.cpp
index 892f7bb01f..fcbf6805d7 100644
--- a/src/plugins/platforms/kms/qkmsscreen.cpp
+++ b/src/plugins/platforms/kms/qkmsscreen.cpp
@@ -131,7 +131,7 @@ void QKmsScreen::initializeScreenMode()
}
}
if (!mode)
- mode = mode = &builtin_1024x768;
+ mode = &builtin_1024x768;
drmModeEncoder *encoder = drmModeGetEncoder(m_device->fd(), connector->encoders[0]);
if (encoder == 0)
diff --git a/src/plugins/platforms/windows/array.h b/src/plugins/platforms/windows/array.h
index 74759231f4..9b7e3a0acb 100644
--- a/src/plugins/platforms/windows/array.h
+++ b/src/plugins/platforms/windows/array.h
@@ -42,7 +42,8 @@
#ifndef ARRAY_H
#define ARRAY_H
-#include <QtCore/QtAlgorithms>
+#include <QtCore/QtGlobal>
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -86,7 +87,7 @@ public:
const T *oldData = data;
data = new T[capacity];
if (oldData) {
- qCopy(oldData, oldData + m_size, data);
+ std::copy(oldData, oldData + m_size, data);
delete [] oldData;
}
m_capacity = capacity;
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 0e6c49aedb..b46b7a1d23 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -452,7 +452,8 @@ class QWindowsNativeDialogBase : public QObject
Q_OBJECT
public:
virtual void setWindowTitle(const QString &title) = 0;
- virtual void exec(HWND owner = 0) = 0;
+ bool executed() const { return m_executed; }
+ void exec(HWND owner = 0) { doExec(owner); m_executed = true; }
signals:
void accepted();
@@ -462,7 +463,12 @@ public slots:
virtual void close() = 0;
protected:
- QWindowsNativeDialogBase() {}
+ QWindowsNativeDialogBase() : m_executed(false) {}
+
+private:
+ virtual void doExec(HWND owner = 0) = 0;
+
+ bool m_executed;
};
/*!
@@ -492,18 +498,11 @@ QWindowsDialogHelperBase<BaseClass>::QWindowsDialogHelperBase() :
template <class BaseClass>
QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::nativeDialog() const
{
- if (!m_nativeDialog) {
+ if (m_nativeDialog.isNull()) {
qWarning("%s invoked with no native dialog present.", __FUNCTION__);
return 0;
}
- return m_nativeDialog;
-}
-
-template <class BaseClass>
-void QWindowsDialogHelperBase<BaseClass>::deleteNativeDialog()
-{
- delete m_nativeDialog;
- m_nativeDialog = 0;
+ return m_nativeDialog.data();
}
template <class BaseClass>
@@ -515,10 +514,11 @@ void QWindowsDialogHelperBase<BaseClass>::timerEvent(QTimerEvent *)
template <class BaseClass>
QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::ensureNativeDialog()
{
- // Create dialog and apply common settings.
- if (!m_nativeDialog)
- m_nativeDialog = createNativeDialog();
- return m_nativeDialog;
+ // Create dialog and apply common settings. Check "executed" flag as well
+ // since for example IFileDialog::Show() works only once.
+ if (m_nativeDialog.isNull() || m_nativeDialog->executed())
+ m_nativeDialog = QWindowsNativeDialogBasePtr(createNativeDialog());
+ return m_nativeDialog.data();
}
/*!
@@ -533,18 +533,22 @@ QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::ensureNativeDialo
class QWindowsDialogThread : public QThread
{
public:
- QWindowsDialogThread(QPlatformDialogHelper *h) : m_helper(h) {}
+ typedef QSharedPointer<QWindowsNativeDialogBase> QWindowsNativeDialogBasePtr;
+
+ explicit QWindowsDialogThread(const QWindowsNativeDialogBasePtr &d, HWND owner)
+ : m_dialog(d), m_owner(owner) {}
void run();
private:
- QPlatformDialogHelper *m_helper;
+ const QWindowsNativeDialogBasePtr m_dialog;
+ const HWND m_owner;
};
void QWindowsDialogThread::run()
{
if (QWindowsContext::verboseDialogs)
qDebug(">%s" , __FUNCTION__);
- m_helper->exec();
+ m_dialog->exec(m_owner);
deleteLater();
if (QWindowsContext::verboseDialogs)
qDebug("<%s" , __FUNCTION__);
@@ -563,7 +567,7 @@ bool QWindowsDialogHelperBase<BaseClass>::show(Qt::WindowFlags,
}
if (QWindowsContext::verboseDialogs)
qDebug("%s modal=%d native=%p parent=%p" ,
- __FUNCTION__, modal, m_nativeDialog, m_ownerWindow);
+ __FUNCTION__, modal, m_nativeDialog.data(), m_ownerWindow);
if (!modal && !supportsNonModalDialog(parent))
return false; // Was it changed in-between?
if (!ensureNativeDialog())
@@ -583,7 +587,8 @@ bool QWindowsDialogHelperBase<BaseClass>::show(Qt::WindowFlags,
template <class BaseClass>
void QWindowsDialogHelperBase<BaseClass>::startDialogThread()
{
- QWindowsDialogThread *thread = new QWindowsDialogThread(this);
+ Q_ASSERT(!m_nativeDialog.isNull());
+ QWindowsDialogThread *thread = new QWindowsDialogThread(m_nativeDialog, m_ownerWindow);
thread->start();
stopTimer();
}
@@ -613,7 +618,7 @@ void QWindowsDialogHelperBase<BaseClass>::exec()
stopTimer();
if (QWindowsNativeDialogBase *nd = nativeDialog()) {
nd->exec(m_ownerWindow);
- deleteNativeDialog();
+ m_nativeDialog.clear();
}
}
@@ -810,7 +815,7 @@ public:
inline void setDirectory(const QString &directory);
inline void updateDirectory() { setDirectory(m_data.directory().toLocalFile()); }
inline QString directory() const;
- virtual void exec(HWND owner = 0);
+ virtual void doExec(HWND owner = 0);
virtual void setNameFilters(const QStringList &f);
inline void selectNameFilter(const QString &filter);
inline void updateSelectedNameFilter() { selectNameFilter(m_data.selectedNameFilter()); }
@@ -947,10 +952,12 @@ QString QWindowsNativeFileDialogBase::directory() const
return QString();
}
-void QWindowsNativeFileDialogBase::exec(HWND owner)
+void QWindowsNativeFileDialogBase::doExec(HWND owner)
{
if (QWindowsContext::verboseDialogs)
qDebug(">%s on %p", __FUNCTION__, (void *)owner);
+ // Show() blocks until the user closes the dialog, the dialog window
+ // gets a WM_CLOSE or the parent window is destroyed.
const HRESULT hr = m_fileDialog->Show(owner);
QWindowsDialogs::eatMouseMove();
if (QWindowsContext::verboseDialogs)
@@ -1611,7 +1618,7 @@ public:
static QWindowsXpNativeFileDialog *create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data);
virtual void setWindowTitle(const QString &t) { m_title = t; }
- virtual void exec(HWND owner = 0);
+ virtual void doExec(HWND owner = 0);
virtual QPlatformDialogHelper::DialogCode result() const { return m_result; }
int existingDirCallback(HWND hwnd, UINT uMsg, LPARAM lParam);
@@ -1662,7 +1669,7 @@ QWindowsXpNativeFileDialog::QWindowsXpNativeFileDialog(const OptionsPtr &options
setWindowTitle(m_options->windowTitle());
}
-void QWindowsXpNativeFileDialog::exec(HWND owner)
+void QWindowsXpNativeFileDialog::doExec(HWND owner)
{
int selectedFilterIndex = -1;
const QList<QUrl> selectedFiles =
@@ -1948,13 +1955,14 @@ public:
explicit QWindowsNativeColorDialog(const SharedPointerColor &color);
virtual void setWindowTitle(const QString &) {}
- virtual void exec(HWND owner = 0);
virtual QPlatformDialogHelper::DialogCode result() const { return m_code; }
public slots:
virtual void close() {}
private:
+ virtual void doExec(HWND owner = 0);
+
COLORREF m_customColors[CustomColorCount];
QPlatformDialogHelper::DialogCode m_code;
SharedPointerColor m_color;
@@ -1966,7 +1974,7 @@ QWindowsNativeColorDialog::QWindowsNativeColorDialog(const SharedPointerColor &c
std::fill(m_customColors, m_customColors + 16, COLORREF(0));
}
-void QWindowsNativeColorDialog::exec(HWND owner)
+void QWindowsNativeColorDialog::doExec(HWND owner)
{
typedef BOOL (WINAPI *ChooseColorWType)(LPCHOOSECOLORW);
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
index c0ee60cc1e..1501b02bd9 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.h
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
@@ -46,6 +46,7 @@
#include <qpa/qplatformdialoghelper.h>
#include <qpa/qplatformtheme.h>
#include <QtCore/QStringList>
+#include <QtCore/QSharedPointer>
QT_BEGIN_NAMESPACE
@@ -64,8 +65,9 @@ namespace QWindowsDialogs
template <class BaseClass>
class QWindowsDialogHelperBase : public BaseClass
{
+ Q_DISABLE_COPY(QWindowsDialogHelperBase)
public:
- ~QWindowsDialogHelperBase() { deleteNativeDialog(); }
+ typedef QSharedPointer<QWindowsNativeDialogBase> QWindowsNativeDialogBasePtr;
virtual void exec();
virtual bool show(Qt::WindowFlags windowFlags,
@@ -79,7 +81,6 @@ protected:
QWindowsDialogHelperBase();
QWindowsNativeDialogBase *nativeDialog() const;
inline bool hasNativeDialog() const { return m_nativeDialog; }
- void deleteNativeDialog();
void timerEvent(QTimerEvent *);
private:
@@ -88,7 +89,7 @@ private:
inline void startDialogThread();
inline void stopTimer();
- QWindowsNativeDialogBase *m_nativeDialog;
+ QWindowsNativeDialogBasePtr m_nativeDialog;
HWND m_ownerWindow;
int m_timerId;
};
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index a6bce6502b..22be4418a9 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -1759,7 +1759,6 @@ QFontEngine *QWindowsFontDatabase::createEngine(int script, const QFontDef &requ
QFontEngine *fe = 0;
if (!useDirectWrite) {
QWindowsFontEngine *few = new QWindowsFontEngine(request.family, hfont, stockFont, lf, data);
- few->setObjectName(QStringLiteral("QWindowsFontEngine_") + request.family);
if (preferClearTypeAA)
few->glyphFormat = QFontEngineGlyphCache::Raster_RGBMask;
@@ -1788,7 +1787,6 @@ QFontEngine *QWindowsFontDatabase::createEngine(int script, const QFontDef &requ
request.pixelSize,
data);
fedw->initFontInfo(request, dpi, directWriteFont);
- fedw->setObjectName(QStringLiteral("QWindowsFontEngineDirectWrite_") + request.family);
fe = fedw;
} else {
qErrnoWarning("%s: CreateFontFace failed", __FUNCTION__);
@@ -1806,7 +1804,6 @@ QFontEngine *QWindowsFontDatabase::createEngine(int script, const QFontDef &requ
QStringList list = family_list;
list.append(extraFonts);
QFontEngine *mfe = new QWindowsMultiFontEngine(fe, list);
- mfe->setObjectName(QStringLiteral("QWindowsMultiFontEngine_") + request.family);
mfe->fontDef = fe->fontDef;
fe = mfe;
}
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
index 6037c201ac..9be0ff9d55 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
@@ -54,6 +54,9 @@
#include <QtGui/QFontDatabase>
#include <wchar.h>
+#ifdef Q_OS_WINCE
+#include <QtEndian>
+#endif
QT_BEGIN_NAMESPACE
@@ -271,6 +274,12 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet,
continue;
fontCache.insert(fontName, fontFile);
settings.setValue(fontName, fontFile);
+
+ if (localizedName(fontName)) {
+ QString englishFontName = getEnglishName(fontName);
+ fontCache.insert(englishFontName, fontFile);
+ settings.setValue(englishFontName, fontFile);
+ }
}
value = fontCache.value(faceName);
@@ -283,7 +292,11 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet,
return false;
if (!QDir::isAbsolutePath(value))
+#ifndef Q_OS_WINCE
value.prepend(QFile::decodeName(qgetenv("windir") + "\\Fonts\\"));
+#else
+ value.prepend(QFile::decodeName("/Windows/"));
+#endif
QPlatformFontDatabase::registerFont(faceName, QString(), foundryName, weight, style, stretch,
antialias, scalable, size, fixed, writingSystems, createFontFile(value, index));
@@ -307,6 +320,24 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet,
return true;
}
+#ifdef Q_OS_WINCE
+static QByteArray getFntTable(HFONT hfont, uint tag)
+{
+ HDC hdc = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(hdc, hfont);
+ quint32 t = qFromBigEndian<quint32>(tag);
+ QByteArray buffer;
+
+ DWORD length = GetFontData(hdc, t, 0, NULL, 0);
+ if (length != GDI_ERROR) {
+ buffer.resize(length);
+ GetFontData(hdc, t, 0, reinterpret_cast<uchar *>(buffer.data()), length);
+ }
+ SelectObject(hdc, oldFont);
+ return buffer;
+}
+#endif
+
static int CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric,
int type, LPARAM namesSetIn)
{
@@ -316,7 +347,33 @@ static int CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric,
+ QString::fromWCharArray(f->elfFullName);
const uchar charSet = f->elfLogFont.lfCharSet;
+#ifndef Q_OS_WINCE
const FONTSIGNATURE signature = textmetric->ntmFontSig;
+#else
+ FONTSIGNATURE signature;
+ QByteArray table;
+
+ if (type & TRUETYPE_FONTTYPE) {
+ HFONT hfont = CreateFontIndirect(&f->elfLogFont);
+ table = getFntTable(hfont, MAKE_TAG('O', 'S', '/', '2'));
+ DeleteObject((HGDIOBJ)hfont);
+ }
+
+ if (table.length() >= 86) {
+ // See also qfontdatabase_mac.cpp, offsets taken from OS/2 table in the TrueType spec
+ uchar *tableData = reinterpret_cast<uchar *>(table.data());
+
+ signature.fsUsb[0] = qFromBigEndian<quint32>(tableData + 42);
+ signature.fsUsb[1] = qFromBigEndian<quint32>(tableData + 46);
+ signature.fsUsb[2] = qFromBigEndian<quint32>(tableData + 50);
+ signature.fsUsb[3] = qFromBigEndian<quint32>(tableData + 54);
+
+ signature.fsCsb[0] = qFromBigEndian<quint32>(tableData + 78);
+ signature.fsCsb[1] = qFromBigEndian<quint32>(tableData + 82);
+ } else {
+ memset(&signature, 0, sizeof(signature));
+ }
+#endif
// NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is
// identical to a TEXTMETRIC except for the last four members, which we don't use
@@ -501,6 +558,17 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF
default:
result << QString::fromLatin1("Arial");
}
+
+#ifdef Q_OS_WINCE
+ QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\FontLink\\SystemLink"), QSettings::NativeFormat);
+ const QStringList fontList = settings.value(family).toStringList();
+ foreach (const QString &fallback, fontList) {
+ const int sep = fallback.indexOf(QLatin1Char(','));
+ if (sep > 0)
+ result << fallback.mid(sep + 1);
+ }
+#endif
+
if (QWindowsContext::verboseFonts)
qDebug() << __FUNCTION__ << family << style << styleHint
<< script << result << m_families;
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp
index 64457f4b67..ac57a1b396 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp
@@ -336,6 +336,13 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name,
if (!resolvedGetCharWidthI)
resolveGetCharWidthI();
+
+ // ### Properties accessed by QWin32PrintEngine (QtPrintSupport)
+ QVariantMap userData;
+ userData.insert(QStringLiteral("logFont"), QVariant::fromValue(m_logfont));
+ userData.insert(QStringLiteral("hFont"), QVariant::fromValue(hfont));
+ userData.insert(QStringLiteral("trueType"), QVariant(bool(ttf)));
+ setUserData(userData);
}
QWindowsFontEngine::~QWindowsFontEngine()
@@ -1366,7 +1373,7 @@ void QWindowsMultiFontEngine::loadEngine(int at)
#endif
{
QWindowsFontEngine *fe = static_cast<QWindowsFontEngine*>(fontEngine);
- lf = fe->logFont();
+ lf = fe->m_logfont;
data = fe->fontEngineData();
}
@@ -1391,8 +1398,6 @@ void QWindowsMultiFontEngine::loadEngine(int at)
QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace,
fontEngine->fontDef.pixelSize,
data);
- fedw->setObjectName(QStringLiteral("QWindowsFontEngineDirectWrite_") + fontEngine->fontDef.family);
-
fedw->fontDef = fontDef;
fedw->ref.ref();
engines[at] = fedw;
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h
index 60ff61fcb9..d783b6048c 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.h
+++ b/src/plugins/platforms/windows/qwindowsfontengine.h
@@ -68,10 +68,7 @@ class QWindowsFontEngineData;
class QWindowsFontEngine : public QFontEngine
{
- Q_OBJECT
- Q_PROPERTY(HFONT hFont READ hFont STORED false)
- Q_PROPERTY(LOGFONT logFont READ logFont STORED false)
- Q_PROPERTY(bool trueType READ trueType STORED false)
+ friend class QWindowsMultiFontEngine;
public:
QWindowsFontEngine(const QString &name, HFONT, bool, LOGFONT,
@@ -137,11 +134,6 @@ public:
const QSharedPointer<QWindowsFontEngineData> &fontEngineData() const { return m_fontEngineData; }
- // Properties accessed by QWin32PrintEngine (Qt Print Support)
- LOGFONT logFont() const { return m_logfont; }
- HFONT hFont() const { return hfont; }
- bool trueType() const { return ttf; }
-
void setUniqueFamilyName(const QString &newName) { uniqueFamilyName = newName; }
private:
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
index ab14cb49eb..57a6a3ba1d 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
@@ -61,7 +61,6 @@ QT_BEGIN_NAMESPACE
class QWindowsFontEngineDirectWrite : public QFontEngine
{
- Q_OBJECT
public:
explicit QWindowsFontEngineDirectWrite(IDWriteFontFace *directWriteFontFace,
qreal pixelSize,
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 5287b79ac3..a84d30de0f 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -56,6 +56,8 @@
#include <QtGui/QPalette>
#include <QtGui/QGuiApplication>
+#include <algorithm>
+
QT_BEGIN_NAMESPACE
static inline QByteArray debugComposition(int lParam)
@@ -583,8 +585,8 @@ int QWindowsInputContext::reconvertString(RECONVERTSTRING *reconv)
reconv->dwTargetStrLen = reconv->dwCompStrLen;
reconv->dwTargetStrOffset = reconv->dwCompStrOffset;
ushort *pastReconv = reinterpret_cast<ushort *>(reconv + 1);
- qCopy(surroundingText.utf16(), surroundingText.utf16() + surroundingText.size(),
- pastReconv);
+ std::copy(surroundingText.utf16(), surroundingText.utf16() + surroundingText.size(),
+ pastReconv);
return memSize;
}
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 754d7a0288..5f1f9cf149 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -342,6 +342,8 @@ static inline unsigned parseOptions(const QStringList &paramList)
}
} else if (param == QLatin1String("gl=gdi")) {
options |= QWindowsIntegration::DisableArb;
+ } else if (param == QLatin1String("mousefromtouch")) {
+ options |= QWindowsIntegration::PassOsMouseEventsSynthesizedFromTouch;
}
}
return options;
@@ -557,13 +559,15 @@ QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) co
break;
case QPlatformIntegration::UseRtlExtensions:
return QVariant(d->m_context.useRTLExtensions());
-#ifdef Q_OS_WINCE
case QPlatformIntegration::SynthesizeMouseFromTouchEvents:
+#ifdef Q_OS_WINCE
// We do not want Qt to synthesize mouse events as Windows also does that.
// Alternatively, Windows-generated touch mouse events can be identified and
// ignored by checking GetMessageExtraInfo() for MI_WP_SIGNATURE (0xFF515700).
return false;
-#endif // Q_OS_WINCE
+#else // Q_OS_WINCE
+ return QVariant(!(d->m_options & PassOsMouseEventsSynthesizedFromTouch));
+#endif // !Q_OS_WINCE
default:
break;
}
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index ca484415be..b3854d673a 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -58,7 +58,8 @@ public:
FontDatabaseNative = 0x2,
DisableArb = 0x4,
NoNativeDialogs = 0x8,
- XpNativeDialogs = 0x10
+ XpNativeDialogs = 0x10,
+ PassOsMouseEventsSynthesizedFromTouch = 0x20 // Pass OS-generated mouse events from touch.
};
explicit QWindowsIntegration(const QStringList &paramList);
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index 43286eadf3..3782b7e020 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -169,10 +169,13 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
#ifndef Q_OS_WINCE
// Check for events synthesized from touch. Lower byte is touch index, 0 means pen.
- const quint64 extraInfo = GetMessageExtraInfo();
- const bool fromTouch = (extraInfo & signatureMask) == miWpSignature && (extraInfo & 0xff);
- if (fromTouch)
- return false;
+ static const bool passSynthesizedMouseEvents = QWindowsIntegration::instance()->options() & QWindowsIntegration::PassOsMouseEventsSynthesizedFromTouch;
+ if (!passSynthesizedMouseEvents) {
+ const quint64 extraInfo = GetMessageExtraInfo();
+ const bool fromTouch = (extraInfo & signatureMask) == miWpSignature && (extraInfo & 0xff);
+ if (fromTouch)
+ return false;
+ }
#endif // !Q_OS_WINCE
const QPoint winEventPosition(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index 49fdfc15b8..eb1bbd1ab0 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -57,7 +57,9 @@
#else
# include <commctrl.h>
# include <objbase.h>
-# include <commoncontrols.h>
+# ifndef Q_CC_MINGW
+# include <commoncontrols.h>
+# endif
# include <shellapi.h>
#endif
@@ -677,7 +679,7 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
static QCache<QString, FakePointer<int> > dirIconEntryCache(1000);
static QMutex mx;
- static int defaultFolderIIcon = 0;
+ static int defaultFolderIIcon = -1;
const bool useDefaultFolderIcon = iconOptions & QPlatformTheme::DontUseCustomDirectoryIcons;
QPixmap pixmap;
@@ -693,8 +695,8 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
bool cacheableDirIcon = fileInfo.isDir() && !fileInfo.isRoot();
if (cacheableDirIcon) {
QMutexLocker locker(&mx);
- int iIcon = (useDefaultFolderIcon && defaultFolderIIcon) ? defaultFolderIIcon
- : **dirIconEntryCache.object(filePath);
+ int iIcon = (useDefaultFolderIcon && defaultFolderIIcon >= 0) ? defaultFolderIIcon
+ : **dirIconEntryCache.object(filePath);
if (iIcon) {
QPixmapCache::find(dirIconPixmapCacheKey(iIcon, iconSize, requestedImageListSize), pixmap);
if (pixmap.isNull()) // Let's keep both caches in sync
@@ -726,7 +728,7 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
if (val && info.hIcon) {
QString key;
if (cacheableDirIcon) {
- if (useDefaultFolderIcon && !defaultFolderIIcon)
+ if (useDefaultFolderIcon && defaultFolderIIcon < 0)
defaultFolderIIcon = info.iIcon;
//using the unique icon index provided by windows save us from duplicate keys
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index 99e9932847..72299d5a9a 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -66,30 +66,28 @@
# include <stdio.h>
#endif
+#include <algorithm>
+
QT_BEGIN_NAMESPACE
-class QXcbResourceMap : public QMap<QByteArray, QXcbNativeInterface::ResourceType>
+// return QXcbNativeInterface::ResourceType for the key.
+static int resourceType(const QByteArray &key)
{
-public:
- QXcbResourceMap()
- :QMap<QByteArray, QXcbNativeInterface::ResourceType>()
- {
- insert("display",QXcbNativeInterface::Display);
- insert("egldisplay",QXcbNativeInterface::EglDisplay);
- insert("connection",QXcbNativeInterface::Connection);
- insert("screen",QXcbNativeInterface::Screen);
- insert("eglcontext",QXcbNativeInterface::EglContext);
- insert("glxcontext",QXcbNativeInterface::GLXContext);
- insert("apptime",QXcbNativeInterface::AppTime);
- insert("appusertime",QXcbNativeInterface::AppUserTime);
- insert("hintstyle", QXcbNativeInterface::ScreenHintStyle);
- insert("startupid", QXcbNativeInterface::StartupId);
- insert(QByteArrayLiteral("traywindow"), QXcbNativeInterface::TrayWindow);
- insert(QByteArrayLiteral("gettimestamp"), QXcbNativeInterface::GetTimestamp);
- }
-};
-
-Q_GLOBAL_STATIC(QXcbResourceMap, qXcbResourceMap)
+ static const QByteArray names[] = { // match QXcbNativeInterface::ResourceType
+ QByteArrayLiteral("display"), QByteArrayLiteral("egldisplay"),
+ QByteArrayLiteral("connection"), QByteArrayLiteral("screen"),
+ QByteArrayLiteral("graphicsdevice"), QByteArrayLiteral("eglcontext"),
+ QByteArrayLiteral("glxcontext"), QByteArrayLiteral("apptime"),
+ QByteArrayLiteral("appusertime"), QByteArrayLiteral("hintstyle"),
+ QByteArrayLiteral("startupid"), QByteArrayLiteral("traywindow"),
+ QByteArrayLiteral("gettimestamp")
+ };
+ const QByteArray *end = names + sizeof(names) / sizeof(names[0]);
+ const QByteArray *result = std::find(names, end, key);
+ if (result == end)
+ result = std::find(names, end, key.toLower());
+ return int(result - names);
+}
QXcbNativeInterface::QXcbNativeInterface() :
m_genericEventFilterType(QByteArrayLiteral("xcb_generic_event_t"))
@@ -136,13 +134,8 @@ QRect QXcbNativeInterface::systemTrayWindowGlobalGeometry(const QWindow *window)
void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString)
{
- QByteArray lowerCaseResource = resourceString.toLower();
- if (!qXcbResourceMap()->contains(lowerCaseResource))
- return 0;
-
- ResourceType resource = qXcbResourceMap()->value(lowerCaseResource);
void *result = 0;
- switch (resource) {
+ switch (resourceType(resourceString)) {
case StartupId:
result = startupId();
break;
@@ -155,13 +148,8 @@ void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resour
void *QXcbNativeInterface::nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context)
{
- QByteArray lowerCaseResource = resourceString.toLower();
- if (!qXcbResourceMap()->contains(lowerCaseResource))
- return 0;
-
- ResourceType resource = qXcbResourceMap()->value(lowerCaseResource);
void *result = 0;
- switch(resource) {
+ switch (resourceType(resourceString)) {
case EglContext:
result = eglContextForContext(context);
break;
@@ -177,12 +165,9 @@ void *QXcbNativeInterface::nativeResourceForContext(const QByteArray &resourceSt
void *QXcbNativeInterface::nativeResourceForScreen(const QByteArray &resource, QScreen *screen)
{
- const QXcbResourceMap::const_iterator it = qXcbResourceMap()->constFind(resource.toLower());
- if (it == qXcbResourceMap()->constEnd() || !screen->handle())
- return 0;
void *result = 0;
const QXcbScreen *xcbScreen = static_cast<QXcbScreen *>(screen->handle());
- switch (it.value()) {
+ switch (resourceType(resource)) {
case Display:
#ifdef XCB_USE_XLIB
result = xcbScreen->connection()->xlib_display();
@@ -212,13 +197,8 @@ void *QXcbNativeInterface::nativeResourceForScreen(const QByteArray &resource, Q
void *QXcbNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window)
{
- QByteArray lowerCaseResource = resourceString.toLower();
- if (!qXcbResourceMap()->contains(lowerCaseResource))
- return 0;
-
- ResourceType resource = qXcbResourceMap()->value(lowerCaseResource);
void *result = 0;
- switch(resource) {
+ switch (resourceType(resourceString)) {
case Display:
result = displayForWindow(window);
break;
diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp
index 961cfd9613..3b45410e6f 100644
--- a/src/printsupport/dialogs/qprintdialog_unix.cpp
+++ b/src/printsupport/dialogs/qprintdialog_unix.cpp
@@ -64,6 +64,7 @@
#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
# include <private/qcups_p.h>
+# include "qcupsjobwidget_p.h"
#else
# include <QtCore/qlibrary.h>
# include <private/qprintengine_pdf_p.h>
@@ -127,6 +128,9 @@ protected:
private:
Ui::QPrintPropertiesWidget widget;
QDialogButtonBox *m_buttons;
+#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
+ QCupsJobWidget *m_jobOptions;
+#endif
};
class QUnixPrintWidgetPrivate;
@@ -237,6 +241,13 @@ QPrintPropertiesDialog::QPrintPropertiesDialog(QAbstractPrintDialog *parent)
connect(m_buttons->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(accept()));
connect(m_buttons->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject()));
+
+#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
+ if (QCUPSSupport::isAvailable()) {
+ m_jobOptions = new QCupsJobWidget();
+ widget.tabs->addTab(m_jobOptions, tr("Job Options"));
+ }
+#endif
}
QPrintPropertiesDialog::~QPrintPropertiesDialog()
@@ -246,11 +257,21 @@ QPrintPropertiesDialog::~QPrintPropertiesDialog()
void QPrintPropertiesDialog::applyPrinterProperties(QPrinter *p)
{
widget.pageSetup->setPrinter(p);
+#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
+ if (QCUPSSupport::isAvailable()) {
+ m_jobOptions->setPrinter(p);
+ }
+#endif
}
void QPrintPropertiesDialog::setupPrinter() const
{
widget.pageSetup->setupPrinter();
+#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
+ if (QCUPSSupport::isAvailable()) {
+ m_jobOptions->setupPrinter();
+ }
+#endif
}
void QPrintPropertiesDialog::selectPrinter()
diff --git a/src/printsupport/kernel/qcups.cpp b/src/printsupport/kernel/qcups.cpp
index 49a97e327c..332245cc21 100644
--- a/src/printsupport/kernel/qcups.cpp
+++ b/src/printsupport/kernel/qcups.cpp
@@ -342,6 +342,97 @@ QStringList QCUPSSupport::options() const
return list;
}
+QStringList QCUPSSupport::cupsOptionsList(QPrinter *printer)
+{
+ return printer->printEngine()->property(PPK_CupsOptions).toStringList();
+}
+
+void QCUPSSupport::setCupsOptions(QPrinter *printer, const QStringList &cupsOptions)
+{
+ printer->printEngine()->setProperty(PPK_CupsOptions, QVariant(cupsOptions));
+}
+
+void QCUPSSupport::setCupsOption(QStringList &cupsOptions, const QString &option, const QString &value)
+{
+ if (cupsOptions.contains(option)) {
+ cupsOptions.replace(cupsOptions.indexOf(option) + 1, value);
+ } else {
+ cupsOptions.append(option);
+ cupsOptions.append(value);
+ }
+}
+
+void QCUPSSupport::setJobHold(QPrinter *printer, const JobHoldUntil jobHold, const QTime &holdUntilTime)
+{
+ QStringList cupsOptions = cupsOptionsList(printer);
+
+ switch (jobHold) {
+ case NoHold: //default
+ break;
+ case Indefinite:
+ setCupsOption(cupsOptions,
+ QStringLiteral("job-hold-until"),
+ QStringLiteral("indefinite"));
+ break;
+ case DayTime:
+ setCupsOption(cupsOptions,
+ QStringLiteral("job-hold-until"),
+ QStringLiteral("day-time"));
+ break;
+ case Night:
+ setCupsOption(cupsOptions,
+ QStringLiteral("job-hold-until"),
+ QStringLiteral("night"));
+ break;
+ case SecondShift:
+ setCupsOption(cupsOptions,
+ QStringLiteral("job-hold-until"),
+ QStringLiteral("second-shift"));
+ break;
+ case ThirdShift:
+ setCupsOption(cupsOptions,
+ QStringLiteral("job-hold-until"),
+ QStringLiteral("third-shift"));
+ break;
+ case Weekend:
+ setCupsOption(cupsOptions,
+ QStringLiteral("job-hold-until"),
+ QStringLiteral("weekend"));
+ break;
+ case SpecificTime:
+ if (holdUntilTime.isNull()) {
+ setJobHold(printer, NoHold);
+ return;
+ }
+ // CUPS expects the time in UTC, user has entered in local time, so get the UTS equivalent
+ QDateTime localDateTime = QDateTime::currentDateTime();
+ // Check if time is for tomorrow in case of DST change overnight
+ if (holdUntilTime < localDateTime.time())
+ localDateTime.addDays(1);
+ localDateTime.setTime(holdUntilTime);
+ setCupsOption(cupsOptions,
+ QStringLiteral("job-hold-until"),
+ localDateTime.toUTC().time().toString(QStringLiteral("HH:mm")));
+ break;
+ }
+
+ setCupsOptions(printer, cupsOptions);
+}
+
+void QCUPSSupport::setJobBilling(QPrinter *printer, const QString &jobBilling)
+{
+ QStringList cupsOptions = cupsOptionsList(printer);
+ setCupsOption(cupsOptions, QStringLiteral("job-billing"), jobBilling);
+ setCupsOptions(printer, cupsOptions);
+}
+
+void QCUPSSupport::setJobPriority(QPrinter *printer, int priority)
+{
+ QStringList cupsOptions = cupsOptionsList(printer);
+ setCupsOption(cupsOptions, QStringLiteral("job-priority"), QString::number(priority));
+ setCupsOptions(printer, cupsOptions);
+}
+
bool QCUPSSupport::printerHasPPD(const char *printerName)
{
if (!isAvailable())
@@ -511,7 +602,6 @@ QList<QPair<QString, QSizeF> > QCUPSSupport::getCupsPrinterPaperSizesWithNames(i
return result;
}
-
QT_END_NAMESPACE
#endif // QT_NO_CUPS
diff --git a/src/printsupport/kernel/qcups_p.h b/src/printsupport/kernel/qcups_p.h
index 0828f582a3..58608ea1f1 100644
--- a/src/printsupport/kernel/qcups_p.h
+++ b/src/printsupport/kernel/qcups_p.h
@@ -56,6 +56,7 @@
#include "QtCore/qstringlist.h"
#include "QtCore/qpair.h"
#include "QtPrintSupport/qprinter.h"
+#include "QtCore/qdatetime.h"
#ifndef QT_NO_CUPS
#include <QtCore/qlibrary.h>
@@ -90,6 +91,18 @@ public:
QCUPSSupport();
~QCUPSSupport();
+ // Enum for values of job-hold-until option
+ enum JobHoldUntil {
+ NoHold = 0, //CUPS Default
+ Indefinite,
+ DayTime,
+ Night,
+ SecondShift,
+ ThirdShift,
+ Weekend,
+ SpecificTime
+ };
+
static bool isAvailable();
static int cupsVersion() { return isAvailable() ? CUPS_VERSION_MAJOR*10000+CUPS_VERSION_MINOR*100+CUPS_VERSION_PATCH : 0; }
int availablePrintersCount() const;
@@ -111,6 +124,14 @@ public:
QStringList options() const;
+ static QStringList cupsOptionsList(QPrinter *printer);
+ static void setCupsOptions(QPrinter *printer, const QStringList &cupsOptions);
+ static void setCupsOption(QStringList &cupsOptions, const QString &option, const QString &value);
+
+ static void setJobHold(QPrinter *printer, const JobHoldUntil jobHold = NoHold, const QTime &holdUntilTime = QTime());
+ static void setJobBilling(QPrinter *printer, const QString &jobBilling = QString());
+ static void setJobPriority(QPrinter *printer, int priority = 50);
+
static bool printerHasPPD(const char *printerName);
QString unicodeString(const char *s);
@@ -139,6 +160,8 @@ private:
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QCUPSSupport::JobHoldUntil)
+
#endif // QT_NO_CUPS
#endif
diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp
index 36dd7ecb0c..acaa32304e 100644
--- a/src/printsupport/kernel/qprintengine_win.cpp
+++ b/src/printsupport/kernel/qprintengine_win.cpp
@@ -364,8 +364,9 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem
|| ti.fontEngine->type() != QFontEngine::Win;
if (!fallBack) {
- const QVariant hFontV = ti.fontEngine->property("hFont");
- const QVariant logFontV = ti.fontEngine->property("logFont");
+ const QVariantMap userData = ti.fontEngine->userData().toMap();
+ const QVariant hFontV = userData.value(QStringLiteral("hFont"));
+ const QVariant logFontV = userData.value(QStringLiteral("logFont"));
if (hFontV.canConvert<HFONT>() && logFontV.canConvert<LOGFONT>()) {
const HFONT hfont = hFontV.value<HFONT>();
const LOGFONT logFont = logFontV.value<LOGFONT>();
@@ -1806,8 +1807,9 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h
bool ttf = false;
if (ti.fontEngine->type() == QFontEngine::Win) {
- const QVariant hfontV = ti.fontEngine->property("hFont");
- const QVariant ttfV = ti.fontEngine->property("trueType");
+ const QVariantMap userData = ti.fontEngine->userData().toMap();
+ const QVariant hfontV = userData.value(QStringLiteral("hFont"));
+ const QVariant ttfV = userData.value(QStringLiteral("trueType"));
if (ttfV.type() == QVariant::Bool && hfontV.canConvert<HFONT>()) {
hfont = hfontV.value<HFONT>();
ttf = ttfV.toBool();
diff --git a/src/printsupport/widgets/qcupsjobwidget.cpp b/src/printsupport/widgets/qcupsjobwidget.cpp
new file mode 100644
index 0000000000..28fb8e859b
--- /dev/null
+++ b/src/printsupport/widgets/qcupsjobwidget.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPrintSupport module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qcupsjobwidget_p.h"
+
+#include <QCheckBox>
+#include <QDateTime>
+#include <QFontDatabase>
+#include <QLabel>
+#include <QLayout>
+#include <QTime>
+#include <QTableWidget>
+#include <QTableWidgetItem>
+#include <QHeaderView>
+#include <QPrinter>
+#include <QPrintEngine>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ \class QCupsJobWidget
+
+ A widget to add to QPrintDialog to enable extra CUPS options
+ such as Job Scheduling, Job Priority or Job Billing
+ \ingroup printing
+ \inmodule QtPrintSupport
+ */
+
+QCupsJobWidget::QCupsJobWidget(QWidget *parent)
+ : QWidget(parent)
+{
+ m_ui.setupUi(this);
+ //set all the default values
+ //TODO restore last used values
+ initJobHold();
+ initJobBilling();
+ initJobPriority();
+}
+
+QCupsJobWidget::~QCupsJobWidget()
+{
+}
+
+void QCupsJobWidget::setPrinter(QPrinter *printer)
+{
+ m_printer = printer;
+}
+
+void QCupsJobWidget::setupPrinter()
+{
+ QCUPSSupport::setJobHold(m_printer, jobHold(), jobHoldTime());
+ QCUPSSupport::setJobBilling(m_printer, jobBilling());
+ QCUPSSupport::setJobPriority(m_printer, jobPriority());
+}
+
+void QCupsJobWidget::initJobHold()
+{
+ m_ui.jobHoldComboBox->addItem(tr("Print Immediately"), QVariant::fromValue(QCUPSSupport::NoHold));
+ m_ui.jobHoldComboBox->addItem(tr("Hold Indefinitely"), QVariant::fromValue(QCUPSSupport::Indefinite));
+ m_ui.jobHoldComboBox->addItem(tr("Day (06:00 to 17:59)"), QVariant::fromValue(QCUPSSupport::DayTime));
+ m_ui.jobHoldComboBox->addItem(tr("Night (18:00 to 05:59)"), QVariant::fromValue(QCUPSSupport::Night));
+ m_ui.jobHoldComboBox->addItem(tr("Second Shift (16:00 to 23:59)"), QVariant::fromValue(QCUPSSupport::SecondShift));
+ m_ui.jobHoldComboBox->addItem(tr("Third Shift (00:00 to 07:59)"), QVariant::fromValue(QCUPSSupport::ThirdShift));
+ m_ui.jobHoldComboBox->addItem(tr("Weekend (Saturday to Sunday)"), QVariant::fromValue(QCUPSSupport::Weekend));
+ m_ui.jobHoldComboBox->addItem(tr("Specific Time"), QVariant::fromValue(QCUPSSupport::SpecificTime));
+
+ connect(m_ui.jobHoldComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleJobHoldTime()));
+
+ setJobHold(QCUPSSupport::NoHold, QTime());
+ toggleJobHoldTime();
+}
+
+void QCupsJobWidget::setJobHold(QCUPSSupport::JobHoldUntil jobHold, const QTime &holdUntilTime)
+{
+ if (jobHold == QCUPSSupport::SpecificTime && holdUntilTime.isNull()) {
+ jobHold = QCUPSSupport::NoHold;
+ toggleJobHoldTime();
+ }
+ m_ui.jobHoldComboBox->setCurrentIndex(m_ui.jobHoldComboBox->findData(QVariant::fromValue(jobHold)));
+ m_ui.jobHoldTimeEdit->setTime(holdUntilTime);
+}
+
+QCUPSSupport::JobHoldUntil QCupsJobWidget::jobHold() const
+{
+ return m_ui.jobHoldComboBox->itemData(m_ui.jobHoldComboBox->currentIndex()).value<QCUPSSupport::JobHoldUntil>();
+}
+
+void QCupsJobWidget::toggleJobHoldTime()
+{
+ if (jobHold() == QCUPSSupport::SpecificTime)
+ m_ui.jobHoldTimeEdit->setEnabled(true);
+ else
+ m_ui.jobHoldTimeEdit->setEnabled(false);
+}
+
+QTime QCupsJobWidget::jobHoldTime() const
+{
+ return m_ui.jobHoldTimeEdit->time();
+}
+
+void QCupsJobWidget::initJobBilling()
+{
+ setJobBilling(QString());
+}
+
+void QCupsJobWidget::setJobBilling(const QString &jobBilling)
+{
+ m_ui.jobBillingLineEdit->insert(jobBilling);
+}
+
+QString QCupsJobWidget::jobBilling() const
+{
+ return m_ui.jobBillingLineEdit->text();
+}
+
+void QCupsJobWidget::initJobPriority()
+{
+ setJobPriority(50);
+}
+
+void QCupsJobWidget::setJobPriority(int jobPriority)
+{
+ m_ui.jobPrioritySpinBox->setValue(jobPriority);
+}
+
+int QCupsJobWidget::jobPriority() const
+{
+ return m_ui.jobPrioritySpinBox->value();
+}
+
+QT_END_NAMESPACE
diff --git a/src/printsupport/widgets/qcupsjobwidget.ui b/src/printsupport/widgets/qcupsjobwidget.ui
new file mode 100644
index 0000000000..2c03ef843a
--- /dev/null
+++ b/src/printsupport/widgets/qcupsjobwidget.ui
@@ -0,0 +1,108 @@
+<ui version="4.0" >
+ <class>QCupsJobWidget</class>
+ <widget class="QWidget" name="QCupsJobWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>294</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Job</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3" >
+ <item row="0" column="0" >
+ <widget class="QGroupBox" name="jobControlGroupBox" >
+ <property name="title" >
+ <string>Job Control</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="jobHoldLabel" >
+ <property name="text" >
+ <string>Scheduled printing:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="2" >
+ <widget class="QComboBox" name="jobHoldComboBox" />
+ </item>
+ <item row="0" column="3" >
+ <widget class="QTimeEdit" name="jobHoldTimeEdit" />
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="jobBillingLabel" >
+ <property name="text" >
+ <string>Billing information:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" colspan="3" >
+ <widget class="QLineEdit" name="jobBillingLineEdit" />
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="jobPriorityLabel" >
+ <property name="text" >
+ <string>Job priority:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QSpinBox" name="jobPrioritySpinBox" >
+ <property name="maximum" >
+ <number>100</number>
+ </property>
+ <property name="value" >
+ <number>50</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2" colspan="2" >
+ <spacer name="horizontalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>180</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="3" column="1" >
+ <spacer name="verticalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>20</width>
+ <height>35</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <spacer name="verticalSpacer_3" >
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>20</width>
+ <height>13</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/printsupport/widgets/qcupsjobwidget_p.h b/src/printsupport/widgets/qcupsjobwidget_p.h
new file mode 100644
index 0000000000..b0f276b251
--- /dev/null
+++ b/src/printsupport/widgets/qcupsjobwidget_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPrintSupport module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QCUPSJOBWIDGET_P_H
+#define QCUPSJOBWIDGET_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
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+//
+
+#include <ui_qcupsjobwidget.h>
+#include <private/qcups_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+class QTime;
+class QPrinter;
+
+class QCupsJobWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit QCupsJobWidget(QWidget *parent = 0);
+ ~QCupsJobWidget();
+ void setPrinter(QPrinter *printer);
+ void setupPrinter();
+
+private Q_SLOTS:
+ void toggleJobHoldTime();
+
+private:
+
+ void setJobHold(QCUPSSupport::JobHoldUntil jobHold = QCUPSSupport::NoHold, const QTime &holdUntilTime = QTime());
+ QCUPSSupport::JobHoldUntil jobHold() const;
+ QTime jobHoldTime() const;
+
+ void setJobBilling(const QString &jobBilling = QString());
+ QString jobBilling() const;
+
+ void setJobPriority(int priority = 50);
+ int jobPriority() const;
+
+ void initJobHold();
+ void initJobBilling();
+ void initJobPriority();
+
+ QPrinter *m_printer;
+ Ui::QCupsJobWidget m_ui;
+
+ Q_DISABLE_COPY(QCupsJobWidget)
+};
+
+QT_END_NAMESPACE
+
+#endif // QCUPSJOBWIDGET_P_H
diff --git a/src/printsupport/widgets/widgets.pri b/src/printsupport/widgets/widgets.pri
index 40eb306623..8e5cb12a6d 100644
--- a/src/printsupport/widgets/widgets.pri
+++ b/src/printsupport/widgets/widgets.pri
@@ -1,2 +1,11 @@
HEADERS += widgets/qprintpreviewwidget.h
SOURCES += widgets/qprintpreviewwidget.cpp
+
+unix:!mac:contains(QT_CONFIG, cups): {
+ HEADERS += widgets/qcupsjobwidget_p.h
+ SOURCES += widgets/qcupsjobwidget.cpp
+ FORMS += widgets/qcupsjobwidget.ui
+
+ INCLUDEPATH += $$PWD
+}
+
diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp
index 431c8dd46c..d5218571f5 100644
--- a/src/tools/moc/main.cpp
+++ b/src/tools/moc/main.cpp
@@ -50,6 +50,10 @@
#include <stdlib.h>
#include <ctype.h>
+#include <qcoreapplication.h>
+#include <qcommandlineoption.h>
+#include <qcommandlineparser.h>
+
QT_BEGIN_NAMESPACE
/*
@@ -63,10 +67,10 @@ QT_BEGIN_NAMESPACE
/tmp/abc, xyz/klm -> /tmp/abc
*/
-static QByteArray combinePath(const QByteArray &infile, const QByteArray &outfile)
+static QByteArray combinePath(const QString &infile, const QString &outfile)
{
- QFileInfo inFileInfo(QDir::current(), QFile::decodeName(infile));
- QFileInfo outFileInfo(QDir::current(), QFile::decodeName(outfile));
+ QFileInfo inFileInfo(QDir::current(), infile);
+ QFileInfo outFileInfo(QDir::current(), outfile);
const QByteArray relativePath = QFile::encodeName(outFileInfo.dir().relativeFilePath(inFileInfo.filePath()));
#ifdef Q_OS_WIN
// It's a system limitation.
@@ -83,21 +87,6 @@ void error(const char *msg = "Invalid argument")
{
if (msg)
fprintf(stderr, "moc: %s\n", msg);
- fprintf(stderr, "Usage: moc [options] <header-file>\n"
- " -o<file> write output to file rather than stdout\n"
- " -I<dir> add dir to the include path for header files\n"
- " -E preprocess only; do not generate meta object code\n"
- " -D<macro>[=<def>] define macro, with optional definition\n"
- " -U<macro> undefine macro\n"
- " -i do not generate an #include statement\n"
- " -p<path> path prefix for included file\n"
- " -f[<file>] force #include, optional file name (overwrite default)\n"
- " -b<file> prepend #include <file> (preserve default include)\n"
- " -nn do not display notes\n"
- " -nw do not display warnings\n"
- " @<file> read additional options from file\n"
- " -v display version of moc\n");
- exit(1);
}
@@ -161,9 +150,43 @@ QByteArray composePreprocessorOutput(const Symbols &symbols) {
return output;
}
+static QStringList argumentsFromCommandLineAndFile(const QStringList &arguments)
+{
+ QStringList allArguments = arguments;
+ int n = 0;
+ while (n < allArguments.count()) {
+ // "@file" doesn't start with a '-' so we can't use QCommandLineParser for it
+ if (arguments.at(n).startsWith(QLatin1Char('@'))) {
+ QString optionsFile = arguments.at(n);
+ optionsFile.remove(0, 1);
+ if (optionsFile.isEmpty()) {
+ error("The @ option requires an input file");
+ return QStringList();
+ }
+ QFile f(optionsFile);
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ error("Cannot open options file specified with @");
+ return QStringList();
+ }
+ allArguments.removeAt(n);
+ while (!f.atEnd()) {
+ QString line = QString::fromLocal8Bit(f.readLine().trimmed());
+ if (!line.isEmpty())
+ allArguments.insert(n++, line);
+ }
+ } else {
+ ++n;
+ }
+ }
+ return allArguments;
+}
+
-int runMoc(int _argc, char **_argv)
+int runMoc(int argc, char **argv)
{
+ QCoreApplication app(argc, argv);
+ QCoreApplication::setApplicationVersion(QString::fromLatin1(QT_VERSION_STR));
+
bool autoInclude = true;
bool defaultInclude = true;
Preprocessor pp;
@@ -178,199 +201,165 @@ int runMoc(int _argc, char **_argv)
dummyVariadicFunctionMacro.arguments += Symbol(0, PP_IDENTIFIER, "__VA_ARGS__");
pp.macros["__attribute__"] = dummyVariadicFunctionMacro;
- QByteArray filename;
- QByteArray output;
- FILE *in = 0;
+ QString filename;
+ QString output;
+ QFile in;
FILE *out = 0;
- bool ignoreConflictingOptions = false;
-
- QVector<QByteArray> argv;
- argv.resize(_argc - 1);
- for (int n = 1; n < _argc; ++n)
- argv[n - 1] = _argv[n];
- int argc = argv.count();
- for (int n = 0; n < argv.count(); ++n) {
- if (argv.at(n).startsWith('@')) {
- QByteArray optionsFile = argv.at(n);
- optionsFile.remove(0, 1);
- if (optionsFile.isEmpty())
- error("The @ option requires an input file");
- QFile f(QString::fromLatin1(optionsFile.constData()));
- if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
- error("Cannot open options file specified with @");
- argv.remove(n);
- while (!f.atEnd()) {
- QByteArray line = f.readLine().trimmed();
- if (!line.isEmpty())
- argv.insert(n++, line);
- }
- }
+ // Note that moc isn't translated.
+ // If you use this code as an example for a translated app, make sure to translate the strings.
+ QCommandLineParser parser;
+ parser.setApplicationDescription(QStringLiteral("Qt Meta Object Compiler version %1 (Qt %2)")
+ .arg(mocOutputRevision).arg(QString::fromLatin1(QT_VERSION_STR)));
+ parser.addHelpOption();
+ parser.addVersionOption();
+
+ QCommandLineOption outputOption(QStringLiteral("o"));
+ outputOption.setDescription(QStringLiteral("Write output to file rather than stdout."));
+ outputOption.setValueName(QStringLiteral("file"));
+ parser.addOption(outputOption);
+
+ QCommandLineOption includePathOption(QStringLiteral("I"));
+ includePathOption.setDescription(QStringLiteral("Add dir to the include path for header files."));
+ includePathOption.setValueName(QStringLiteral("dir"));
+ parser.addOption(includePathOption);
+
+ QCommandLineOption macFrameworkOption(QStringLiteral("F"));
+ macFrameworkOption.setDescription(QStringLiteral("Add Mac framework to the include path for header files."));
+ macFrameworkOption.setValueName(QStringLiteral("framework"));
+ parser.addOption(macFrameworkOption);
+
+ QCommandLineOption preprocessOption(QStringLiteral("E"));
+ preprocessOption.setDescription(QStringLiteral("Preprocess only; do not generate meta object code."));
+ parser.addOption(preprocessOption);
+
+ QCommandLineOption defineOption(QStringLiteral("D"));
+ defineOption.setDescription(QStringLiteral("Define macro, with optional definition."));
+ defineOption.setValueName(QStringLiteral("macro[=def]"));
+ parser.addOption(defineOption);
+
+ QCommandLineOption undefineOption(QStringLiteral("U"));
+ undefineOption.setDescription(QStringLiteral("Undefine macro."));
+ undefineOption.setValueName(QStringLiteral("macro"));
+ parser.addOption(undefineOption);
+
+ QCommandLineOption noIncludeOption(QStringLiteral("i"));
+ noIncludeOption.setDescription(QStringLiteral("Do not generate an #include statement."));
+ parser.addOption(noIncludeOption);
+
+ QCommandLineOption pathPrefixOption(QStringLiteral("p"));
+ pathPrefixOption.setDescription(QStringLiteral("Path prefix for included file."));
+ pathPrefixOption.setValueName(QStringLiteral("path"));
+ parser.addOption(pathPrefixOption);
+
+ QCommandLineOption forceIncludeOption(QStringLiteral("f"));
+ forceIncludeOption.setDescription(QStringLiteral("Force #include [optional <file>] (overwrite default)."));
+ forceIncludeOption.setValueName(QStringLiteral("file"));
+ parser.addOption(forceIncludeOption);
+
+ QCommandLineOption prependIncludeOption(QStringLiteral("b"));
+ prependIncludeOption.setDescription(QStringLiteral("Prepend #include <file> (preserve default include)."));
+ prependIncludeOption.setValueName(QStringLiteral("file"));
+ parser.addOption(prependIncludeOption);
+
+ QCommandLineOption noNotesWarningsCompatOption(QStringLiteral("n"));
+ noNotesWarningsCompatOption.setDescription(QStringLiteral("Do not display notes (-nn) or warnings (-nw). Compatibility option."));
+ noNotesWarningsCompatOption.setValueName(QStringLiteral("which"));
+ parser.addOption(noNotesWarningsCompatOption);
+
+ QCommandLineOption noNotesOption(QStringLiteral("no-notes"));
+ noNotesOption.setDescription(QStringLiteral("Do not display notes."));
+ parser.addOption(noNotesOption);
+
+ QCommandLineOption noWarningsOption(QStringLiteral("no-warnings"));
+ noWarningsOption.setDescription(QStringLiteral("Do not display warnings (implies --no-notes)."));
+ parser.addOption(noWarningsOption);
+
+ QCommandLineOption ignoreConflictsOption(QStringLiteral("ignore-option-clashes"));
+ ignoreConflictsOption.setDescription(QStringLiteral("Ignore all options that conflict with compilers, like -pthread conflicting with moc's -p option."));
+ parser.addOption(ignoreConflictsOption);
+
+ parser.addPositionalArgument(QStringLiteral("[header-file]"),
+ QStringLiteral("Header file to read from, otherwise stdin."));
+ parser.addPositionalArgument(QStringLiteral("[@option-file]"),
+ QStringLiteral("Read additional options from option-file."));
+
+ const QStringList arguments = argumentsFromCommandLineAndFile(app.arguments());
+
+ parser.process(arguments);
+
+ const QStringList files = parser.positionalArguments();
+ if (files.count() > 1) {
+ error("Too many input files specified");
+ parser.showHelp(1);
+ } else if (!files.isEmpty()) {
+ filename = files.first();
}
- argc = argv.count();
-
- for (int n = 0; n < argc; ++n) {
- QByteArray arg(argv[n]);
- if (arg[0] != '-') {
- if (filename.isEmpty()) {
- filename = arg;
- continue;
- }
- error("Too many input files specified");
- }
- QByteArray opt = arg.mid(1);
- bool more = (opt.size() > 1);
- switch (opt[0]) {
- case 'o': // output redirection
- if (!more) {
- if (!(n < argc-1))
- error("Missing output file name");
- output = argv[++n];
- } else
- output = opt.mid(1);
- break;
- case 'E': // only preprocessor
- pp.preprocessOnly = true;
- break;
- case 'i': // no #include statement
- if (more)
- error();
- moc.noInclude = true;
- autoInclude = false;
- break;
- case 'f': // produce #include statement
- if (ignoreConflictingOptions)
- break;
- moc.noInclude = false;
+ const bool ignoreConflictingOptions = parser.isSet(ignoreConflictsOption);
+ output = parser.value(outputOption);
+ pp.preprocessOnly = parser.isSet(preprocessOption);
+ if (parser.isSet(noIncludeOption)) {
+ moc.noInclude = true;
+ autoInclude = false;
+ }
+ if (!ignoreConflictingOptions) {
+ if (parser.isSet(forceIncludeOption)) {
+ moc.noInclude = false;
autoInclude = false;
- if (opt[1]) { // -fsomething.h
- moc.includeFiles.append(opt.mid(1));
+ foreach (const QString &include, parser.values(forceIncludeOption)) {
+ moc.includeFiles.append(QFile::encodeName(include));
defaultInclude = false;
- }
- break;
- case 'b':
- if (ignoreConflictingOptions)
- break;
- if (!more) {
- if (!(n < argc-1))
- error("Missing file name for the -b option.");
- moc.includeFiles.prepend(argv[++n]);
- } else if (opt[1]) {
- moc.includeFiles.prepend(opt.mid(1));
- }
- break;
- case 'p': // include file path
- if (ignoreConflictingOptions)
- break;
- if (!more) {
- if (!(n < argc-1))
- error("Missing path name for the -p option.");
- moc.includePath = argv[++n];
- } else {
- moc.includePath = opt.mid(1);
- }
- break;
- case 'I': // produce #include statement
- if (!more) {
- if (!(n < argc-1))
- error("Missing path name for the -I option.");
- pp.includes += Preprocessor::IncludePath(argv[++n]);
- } else {
- pp.includes += Preprocessor::IncludePath(opt.mid(1));
- }
- break;
- case 'F': // minimalistic framework support for the mac
- if (!more) {
- if (!(n < argc-1))
- error("Missing path name for the -F option.");
- Preprocessor::IncludePath p(argv[++n]);
- p.isFrameworkPath = true;
- pp.includes += p;
- } else {
- Preprocessor::IncludePath p(opt.mid(1));
- p.isFrameworkPath = true;
- pp.includes += p;
- }
- break;
- case 'D': // define macro
- {
- QByteArray name;
- QByteArray value("1");
- if (!more) {
- if (n < argc-1)
- name = argv[++n];
- } else
- name = opt.mid(1);
- int eq = name.indexOf('=');
- if (eq >= 0) {
- value = name.mid(eq + 1);
- name = name.left(eq);
- }
- if (name.isEmpty())
- error("Missing macro name");
- Macro macro;
- macro.symbols += Symbol(0, PP_IDENTIFIER, value);
- pp.macros.insert(name, macro);
-
- }
- break;
- case 'U':
- {
- QByteArray macro;
- if (!more) {
- if (n < argc-1)
- macro = argv[++n];
- } else
- macro = opt.mid(1);
- if (macro.isEmpty())
- error("Missing macro name");
- pp.macros.remove(macro);
-
- }
- break;
- case 'v': // version number
- if (more && opt != "version")
- error();
- fprintf(stderr, "Qt Meta Object Compiler version %d (Qt %s)\n",
- mocOutputRevision, QT_VERSION_STR);
- return 1;
- case 'n': // don't display warnings
- if (ignoreConflictingOptions)
- break;
- if (opt == "nw")
- moc.displayWarnings = moc.displayNotes = false;
- else if (opt == "nn")
- moc.displayNotes = false;
- else
- error();
- break;
- case 'h': // help
- if (more && opt != "help")
- error();
- else
- error(0); // 0 means usage only
- break;
- case '-':
- if (more && arg == "--ignore-option-clashes") {
- // -- ignore all following moc specific options that conflict
- // with for example gcc, like -pthread conflicting with moc's
- // -p option.
- ignoreConflictingOptions = true;
- break;
- }
- // fall through
- default:
- error();
+ }
}
+ foreach (const QString &include, parser.values(prependIncludeOption))
+ moc.includeFiles.prepend(QFile::encodeName(include));
+ if (parser.isSet(pathPrefixOption))
+ moc.includePath = QFile::encodeName(parser.value(pathPrefixOption));
}
-
+ foreach (const QString &path, parser.values(includePathOption))
+ pp.includes += Preprocessor::IncludePath(QFile::encodeName(path));
+ foreach (const QString &path, parser.values(macFrameworkOption)) {
+ // minimalistic framework support for the mac
+ Preprocessor::IncludePath p(QFile::encodeName(path));
+ p.isFrameworkPath = true;
+ pp.includes += p;
+ }
+ foreach (const QString &arg, parser.values(defineOption)) {
+ QByteArray name = arg.toLocal8Bit();
+ QByteArray value("1");
+ int eq = name.indexOf('=');
+ if (eq >= 0) {
+ value = name.mid(eq + 1);
+ name = name.left(eq);
+ }
+ if (name.isEmpty()) {
+ error("Missing macro name");
+ parser.showHelp(1);
+ }
+ Macro macro;
+ macro.symbols += Symbol(0, PP_IDENTIFIER, value);
+ pp.macros.insert(name, macro);
+ }
+ foreach (const QString &arg, parser.values(undefineOption)) {
+ QByteArray macro = arg.toLocal8Bit();
+ if (macro.isEmpty()) {
+ error("Missing macro name");
+ parser.showHelp(1);
+ }
+ pp.macros.remove(macro);
+ }
+ const QStringList noNotesCompatValues = parser.values(noNotesWarningsCompatOption);
+ if (parser.isSet(noNotesOption) || noNotesCompatValues.contains(QStringLiteral("n")))
+ moc.displayNotes = false;
+ if (parser.isSet(noWarningsOption) || noNotesCompatValues.contains(QStringLiteral("w")))
+ moc.displayWarnings = moc.displayNotes = false;
if (autoInclude) {
- int spos = filename.lastIndexOf(QDir::separator().toLatin1());
- int ppos = filename.lastIndexOf('.');
+ int spos = filename.lastIndexOf(QDir::separator());
+ int ppos = filename.lastIndexOf(QLatin1Char('.'));
// spos >= -1 && ppos > spos => ppos >= 0
- moc.noInclude = (ppos > spos && tolower(filename[ppos + 1]) != 'h');
+ moc.noInclude = (ppos > spos && filename[ppos + 1].toLower() != QLatin1Char('h'));
}
if (defaultInclude) {
if (moc.includePath.isEmpty()) {
@@ -378,7 +367,7 @@ int runMoc(int _argc, char **_argv)
if (output.size())
moc.includeFiles.append(combinePath(filename, output));
else
- moc.includeFiles.append(filename);
+ moc.includeFiles.append(QFile::encodeName(filename));
}
} else {
moc.includeFiles.append(combinePath(filename, filename));
@@ -386,27 +375,22 @@ int runMoc(int _argc, char **_argv)
}
if (filename.isEmpty()) {
- filename = "standard input";
- in = stdin;
+ filename = QStringLiteral("standard input");
+ in.open(stdin, QIODevice::ReadOnly);
} else {
-#if defined(_MSC_VER) && _MSC_VER >= 1400
- if (fopen_s(&in, filename.data(), "rb")) {
-#else
- in = fopen(filename.data(), "rb");
- if (!in) {
-#endif
- fprintf(stderr, "moc: %s: No such file\n", filename.constData());
+ in.setFileName(filename);
+ if (!in.open(QIODevice::ReadOnly)) {
+ fprintf(stderr, "moc: %s: No such file\n", qPrintable(filename));
return 1;
}
- moc.filename = filename;
+ moc.filename = filename.toLocal8Bit();
}
- moc.currentFilenames.push(filename);
+ moc.currentFilenames.push(filename.toLocal8Bit());
moc.includes = pp.includes;
// 1. preprocess
- moc.symbols = pp.preprocessed(moc.filename, in);
- fclose(in);
+ moc.symbols = pp.preprocessed(moc.filename, &in);
if (!pp.preprocessOnly) {
// 2. parse
@@ -417,13 +401,13 @@ int runMoc(int _argc, char **_argv)
if (output.size()) { // output file specified
#if defined(_MSC_VER) && _MSC_VER >= 1400
- if (fopen_s(&out, output.data(), "w"))
+ if (fopen_s(&out, QFile::encodeName(output).constData(), "w"))
#else
- out = fopen(output.data(), "w"); // create output file
+ out = fopen(QFile::encodeName(output).constData(), "w"); // create output file
if (!out)
#endif
{
- fprintf(stderr, "moc: Cannot create %s\n", output.constData());
+ fprintf(stderr, "moc: Cannot create %s\n", QFile::encodeName(output).constData());
return 1;
}
} else { // use stdout
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index fd1d2155fc..648723ebc1 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -988,7 +988,7 @@ void Moc::parseSignals(ClassDef *def)
prev();
}
FunctionDef funcDef;
- funcDef.access = FunctionDef::Protected;
+ funcDef.access = FunctionDef::Public;
parseFunction(&funcDef);
if (funcDef.isVirtual)
warning("Signals cannot be declared virtual");
diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
index 06758e67bd..3615262b67 100644
--- a/src/tools/moc/preprocessor.cpp
+++ b/src/tools/moc/preprocessor.cpp
@@ -1172,13 +1172,6 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
currentFilenames.pop();
}
-Symbols Preprocessor::preprocessed(const QByteArray &filename, FILE *file)
-{
- QFile qfile;
- qfile.open(file, QFile::ReadOnly);
- return preprocessed(filename, &qfile);
-}
-
Symbols Preprocessor::preprocessed(const QByteArray &filename, QIODevice *file)
{
QByteArray input = file->readAll();
diff --git a/src/tools/moc/preprocessor.h b/src/tools/moc/preprocessor.h
index 72d02a3292..dc7c98de85 100644
--- a/src/tools/moc/preprocessor.h
+++ b/src/tools/moc/preprocessor.h
@@ -75,7 +75,6 @@ public:
QList<QByteArray> frameworks;
QSet<QByteArray> preprocessedIncludes;
Macros macros;
- Symbols preprocessed(const QByteArray &filename, FILE *file);
Symbols preprocessed(const QByteArray &filename, QIODevice *device);
void parseDefineArguments(Macro *m);
diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp
index 5583600bf6..cfea6235d3 100644
--- a/src/tools/qdoc/generator.cpp
+++ b/src/tools/qdoc/generator.cpp
@@ -314,34 +314,12 @@ QString Generator::fileBase(const Node *node) const
return fileBase(ncn->currentChild());
}
- if (node->hasBaseName()) {
- //qDebug() << "RETURNING:" << node->baseName();
+ if (node->hasBaseName())
return node->baseName();
- }
QString base;
- const Node *p = node;
-
- forever {
- const Node *pp = p->parent();
- base.prepend(p->name());
- if (!p->qmlModuleIdentifier().isEmpty())
- base.prepend(p->qmlModuleIdentifier()+QChar('-'));
- /*
- To avoid file name conflicts in the html directory,
- we prepend a prefix (by default, "qml-") to the file name of QML
- element doc files.
- */
- if ((p->subType() == Node::QmlClass) ||
- (p->subType() == Node::QmlBasicType)) {
- base.prepend(outputPrefix(QLatin1String("QML")));
- }
- if (!pp || pp->name().isEmpty() || pp->type() == Node::Document)
- break;
- base.prepend(QLatin1Char('-'));
- p = pp;
- }
if (node->type() == Node::Document) {
+ base = node->name();
if (node->subType() == Node::Collision) {
const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node);
if (ncn->currentChild())
@@ -352,17 +330,42 @@ QString Generator::fileBase(const Node *node) const
if (base.endsWith(".html"))
base.truncate(base.length() - 5);
- if (node->subType() == Node::QmlModule) {
- base.prepend("qmlmodule-");
+ if (node->isQmlNode()) {
+ if (!node->qmlModuleName().isEmpty()) {
+ base.prepend(node->qmlModuleName() + QLatin1Char('-'));
+ /*
+ To avoid file name conflicts in the html directory,
+ we prepend a prefix (by default, "qml-") to the file name of QML
+ element doc files.
+ */
+ if ((node->subType() == Node::QmlClass) || (node->subType() == Node::QmlBasicType)) {
+ base.prepend(outputPrefix(QLatin1String("QML")));
+ }
+ }
+ }
+ else if (node->subType() == Node::QmlModule) {
+ base.append("-qmlmodule");
}
- if (node->subType() == Node::Module) {
+ else if (node->subType() == Node::Module) {
base.append("-module");
}
- if (node->isExample() || node->isExampleFile())
+ if (node->isExample() || node->isExampleFile()) {
base.prepend(project.toLower() + QLatin1Char('-'));
- if (node->isExample())
+ }
+ if (node->isExample()) {
base.append(QLatin1String("-example"));
-
+ }
+ }
+ else {
+ const Node *p = node;
+ forever {
+ const Node *pp = p->parent();
+ base.prepend(p->name());
+ if (!pp || pp->name().isEmpty() || pp->type() == Node::Document)
+ break;
+ base.prepend(QLatin1Char('-'));
+ p = pp;
+ }
}
// the code below is effectively equivalent to:
diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp
index a1e06c8020..f1a92c2eb3 100644
--- a/src/tools/qdoc/qdocdatabase.cpp
+++ b/src/tools/qdoc/qdocdatabase.cpp
@@ -190,17 +190,19 @@ DocNode* QDocDatabase::findQmlModule(const QString& name)
QStringList dotSplit;
QStringList blankSplit = name.split(QLatin1Char(' '));
QString qmid = blankSplit[0];
+ QString qmlModuleName = qmid;
if (blankSplit.size() > 1) {
dotSplit = blankSplit[1].split(QLatin1Char('.'));
qmid += dotSplit[0];
}
DocNode* dn = 0;
- if (qmlModules_.contains(qmid))
- return qmlModules_.value(qmid);
- dn = new DocNode(tree_->root(), name, Node::QmlModule, Node::OverviewPage);
+ if (qmlModules_.contains(qmlModuleName))
+ return qmlModules_.value(qmlModuleName);
+ dn = new DocNode(tree_->root(), qmlModuleName, Node::QmlModule, Node::OverviewPage);
dn->markNotSeen();
dn->setQmlModuleInfo(name);
- qmlModules_.insert(qmid,dn);
+ qmlModules_.insert(qmlModuleName,dn);
+ masterMap_.insert(qmlModuleName,dn);
masterMap_.insert(qmid,dn);
masterMap_.insert(dn->name(),dn);
return dn;
@@ -923,8 +925,10 @@ const DocNode* QDocDatabase::findDocNodeByTitle(const QString& title, const Node
if (j != docNodesByTitle_.constEnd() && j.key() == i.key()) {
QList<Location> internalLocations;
while (j != docNodesByTitle_.constEnd()) {
- if (j.key() == i.key() && j.value()->url().isEmpty())
+ if (j.key() == i.key() && j.value()->url().isEmpty()) {
internalLocations.append(j.value()->location());
+ break; // Just report one duplicate for now.
+ }
++j;
}
if (internalLocations.size() > 0) {
diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp
index 3283e978f4..cb387a9452 100644
--- a/src/tools/qdoc/qdocindexfiles.cpp
+++ b/src/tools/qdoc/qdocindexfiles.cpp
@@ -195,7 +195,8 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
qcn->setTitle(element.attribute("title"));
QString qmlModuleName = element.attribute("qml-module-name");
QString qmlModuleVersion = element.attribute("qml-module-version");
- qdb_->addToQmlModule(qmlModuleName + " " + qmlModuleVersion, qcn);
+ if (!qmlModuleName.isEmpty())
+ qdb_->addToQmlModule(qmlModuleName + " " + qmlModuleVersion, qcn);
QString qmlFullBaseName = element.attribute("qml-base-type");
if (!qmlFullBaseName.isEmpty())
qcn->setQmlBaseName(qmlFullBaseName);
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index af3d134a5a..a8d13c64ee 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -1073,7 +1073,10 @@ void QApplication::setStyle(QStyle *style)
if (QApplicationPrivate::set_pal) {
QApplication::setPalette(*QApplicationPrivate::set_pal);
} else if (QApplicationPrivate::sys_pal) {
+ clearSystemPalette();
+ initSystemPalette();
QApplicationPrivate::initializeWidgetPaletteHash();
+ QApplicationPrivate::initializeWidgetFontHash();
QApplicationPrivate::setPalette_helper(*QApplicationPrivate::sys_pal, /*className=*/0, /*clearWidgetPaletteHash=*/false);
} else if (!QApplicationPrivate::sys_pal) {
// Initialize the sys_pal if it hasn't happened yet...
diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp
index 0fc065e74b..1f8e950d00 100644
--- a/src/widgets/kernel/qapplication_qpa.cpp
+++ b/src/widgets/kernel/qapplication_qpa.cpp
@@ -275,8 +275,12 @@ void QApplicationPrivate::initializeWidgetPaletteHash()
QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme();
if (!platformTheme)
return;
+ qt_app_palettes_hash()->clear();
+
setPossiblePalette(platformTheme->palette(QPlatformTheme::ToolButtonPalette), "QToolButton");
setPossiblePalette(platformTheme->palette(QPlatformTheme::ButtonPalette), "QAbstractButton");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::CheckBoxPalette), "QCheckBox");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::RadioButtonPalette), "QRadioButton");
setPossiblePalette(platformTheme->palette(QPlatformTheme::HeaderPalette), "QHeaderView");
setPossiblePalette(platformTheme->palette(QPlatformTheme::ItemViewPalette), "QAbstractItemView");
setPossiblePalette(platformTheme->palette(QPlatformTheme::MessageBoxLabelPelette), "QMessageBoxLabel");
@@ -296,6 +300,8 @@ void QApplicationPrivate::initializeWidgetFontHash()
if (!theme)
return;
FontHash *fontHash = qt_app_fonts_hash();
+ fontHash->clear();
+
if (const QFont *font = theme->font(QPlatformTheme::MenuFont))
fontHash->insert(QByteArrayLiteral("QMenu"), *font);
if (const QFont *font = theme->font(QPlatformTheme::MenuBarFont))
@@ -318,6 +324,10 @@ void QApplicationPrivate::initializeWidgetFontHash()
fontHash->insert(QByteArrayLiteral("QDockWidgetTitle"), *font);
if (const QFont *font = theme->font(QPlatformTheme::PushButtonFont))
fontHash->insert(QByteArrayLiteral("QPushButton"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::CheckBoxFont))
+ fontHash->insert(QByteArrayLiteral("QCheckBox"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::RadioButtonFont))
+ fontHash->insert(QByteArrayLiteral("QRadioButton"), *font);
if (const QFont *font = theme->font(QPlatformTheme::ToolButtonFont))
fontHash->insert(QByteArrayLiteral("QToolButton"), *font);
if (const QFont *font = theme->font(QPlatformTheme::ItemViewFont))
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 5532b04b22..eea44300e8 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -5601,6 +5601,15 @@ void QWidgetPrivate::setWindowIconText_helper(const QString &title)
setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, q));
}
+/*!
+ \fn void QWidget::windowIconTextChanged(const QString &iconText)
+
+ This signal is emitted when the window's icon text has changed, with the
+ new \a iconText as an argument.
+
+ \since 5.2
+*/
+
void QWidget::setWindowIconText(const QString &iconText)
{
if (QWidget::windowIconText() == iconText)
@@ -5612,8 +5621,19 @@ void QWidget::setWindowIconText(const QString &iconText)
QEvent e(QEvent::IconTextChange);
QApplication::sendEvent(this, &e);
+
+ emit windowIconTextChanged(iconText);
}
+/*!
+ \fn void QWidget::windowTitleChanged(const QString &title)
+
+ This signal is emitted when the window's title has changed, with the
+ new \a title as an argument.
+
+ \since 5.2
+*/
+
void QWidget::setWindowTitle(const QString &title)
{
if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull())
@@ -5625,6 +5645,8 @@ void QWidget::setWindowTitle(const QString &title)
QEvent e(QEvent::WindowTitleChange);
QApplication::sendEvent(this, &e);
+
+ emit windowTitleChanged(title);
}
@@ -5661,6 +5683,15 @@ void QWidgetPrivate::setWindowIcon_helper()
}
}
+/*!
+ \fn void QWidget::windowIconChanged(const QIcon &icon)
+
+ This signal is emitted when the window's icon has changed, with the
+ new \a icon as an argument.
+
+ \since 5.2
+*/
+
void QWidget::setWindowIcon(const QIcon &icon)
{
Q_D(QWidget);
@@ -5674,6 +5705,8 @@ void QWidget::setWindowIcon(const QIcon &icon)
d->setWindowIcon_sys();
d->setWindowIcon_helper();
+
+ emit windowIconChanged(icon);
}
diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h
index f579dbb9cd..a9eeaa5470 100644
--- a/src/widgets/kernel/qwidget.h
+++ b/src/widgets/kernel/qwidget.h
@@ -171,9 +171,9 @@ class Q_WIDGETS_EXPORT QWidget : public QObject, public QPaintDevice
Q_PROPERTY(QSize sizeHint READ sizeHint)
Q_PROPERTY(QSize minimumSizeHint READ minimumSizeHint)
Q_PROPERTY(bool acceptDrops READ acceptDrops WRITE setAcceptDrops)
- Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle DESIGNABLE isWindow)
- Q_PROPERTY(QIcon windowIcon READ windowIcon WRITE setWindowIcon DESIGNABLE isWindow)
- Q_PROPERTY(QString windowIconText READ windowIconText WRITE setWindowIconText DESIGNABLE isWindow)
+ Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle NOTIFY windowTitleChanged DESIGNABLE isWindow)
+ Q_PROPERTY(QIcon windowIcon READ windowIcon WRITE setWindowIcon NOTIFY windowIconChanged DESIGNABLE isWindow)
+ Q_PROPERTY(QString windowIconText READ windowIconText WRITE setWindowIconText NOTIFY windowIconTextChanged DESIGNABLE isWindow)
Q_PROPERTY(double windowOpacity READ windowOpacity WRITE setWindowOpacity DESIGNABLE isWindow)
Q_PROPERTY(bool windowModified READ isWindowModified WRITE setWindowModified DESIGNABLE isWindow)
#ifndef QT_NO_TOOLTIP
@@ -599,6 +599,9 @@ public:
friend class QDesktopScreenWidget;
Q_SIGNALS:
+ void windowTitleChanged(const QString &title);
+ void windowIconChanged(const QIcon &icon);
+ void windowIconTextChanged(const QString &iconText);
void customContextMenuRequested(const QPoint &pos);
protected:
diff --git a/src/widgets/styles/qandroidstyle.cpp b/src/widgets/styles/qandroidstyle.cpp
index d82a06987a..afd6c3024c 100644
--- a/src/widgets/styles/qandroidstyle.cpp
+++ b/src/widgets/styles/qandroidstyle.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
+** Copyright (C) 2013 BogDan Vatra <bogdan@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -54,9 +54,12 @@
#include <QPainter>
#include <QJsonDocument>
#include <QJsonObject>
-
#include <QDebug>
+#include <QGuiApplication>
+#include <qpa/qplatformnativeinterface.h>
+#include <qpa/qplatformtheme.h>
+
QT_BEGIN_NAMESPACE
namespace {
@@ -71,16 +74,69 @@ namespace {
const quint32 TRANSPARENT_COLOR = 0;
}
+static int fontType(const QString &androidControl)
+{
+ if (androidControl == QLatin1String("textViewStyle"))
+ return QPlatformTheme::SystemFont;
+ else if (androidControl == QLatin1String("buttonStyle"))
+ return QPlatformTheme::PushButtonFont;
+ else if (androidControl == QLatin1String("checkboxStyle"))
+ return QPlatformTheme::CheckBoxFont;
+ else if (androidControl == QLatin1String("radioButtonStyle"))
+ return QPlatformTheme::RadioButtonFont;
+ else if (androidControl == QLatin1String("simple_list_item_single_choice"))
+ return QPlatformTheme::ItemViewFont;
+ else if (androidControl == QLatin1String("simple_spinner_dropdown_item"))
+ return QPlatformTheme::ComboMenuItemFont;
+ else if (androidControl == QLatin1String("spinnerStyle"))
+ return QPlatformTheme::ComboLineEditFont;
+ else if (androidControl == QLatin1String("simple_list_item"))
+ return QPlatformTheme::ListViewFont;
+ return -1;
+}
+
+static int paletteType(const QString &androidControl)
+{
+ if (androidControl == QLatin1String("textViewStyle"))
+ return QPlatformTheme::SystemPalette;
+ else if (androidControl == QLatin1String("buttonStyle"))
+ return QPlatformTheme::ButtonPalette;
+ else if (androidControl == QLatin1String("checkboxStyle"))
+ return QPlatformTheme::CheckBoxPalette;
+ else if (androidControl == QLatin1String("radioButtonStyle"))
+ return QPlatformTheme::RadioButtonPalette;
+ else if (androidControl == QLatin1String("simple_list_item_single_choice"))
+ return QPlatformTheme::ItemViewPalette;
+ else if (androidControl == QLatin1String("editTextStyle"))
+ return QPlatformTheme::TextLineEditPalette;
+ else if (androidControl == QLatin1String("spinnerStyle"))
+ return QPlatformTheme::ComboBoxPalette;
+ return -1;
+}
QAndroidStyle::QAndroidStyle()
- : QCommonStyle()
+ : QFusionStyle()
{
+ QPixmapCache::clear();
QString stylePath(QLatin1String(qgetenv("MINISTRO_ANDROID_STYLE_PATH")));
+ const QLatin1Char slashChar('/');
+ if (!stylePath.isEmpty() && !stylePath.endsWith(slashChar))
+ stylePath += slashChar;
+
+ QString androidTheme = QLatin1String(qgetenv("QT_ANDROID_THEME"));
+ if (!androidTheme.isEmpty() && !androidTheme.endsWith(slashChar))
+ androidTheme += slashChar;
if (stylePath.isEmpty())
- stylePath = QLatin1String("/data/data/org.kde.necessitas.ministro/files/qt/style/");
+ {
+ stylePath = QLatin1String("/data/data/org.kde.necessitas.ministro/files/dl/style/")
+ + QLatin1String(qgetenv("QT_ANDROID_THEME_DISPLAY_DPI")) + slashChar;
+ }
Q_ASSERT(!stylePath.isEmpty());
+ if (!androidTheme.isEmpty() && QFileInfo(stylePath + androidTheme + QLatin1String("style.json")).exists())
+ stylePath += androidTheme;
+
QFile f(stylePath + QLatin1String("style.json"));
if (!f.open(QIODevice::ReadOnly))
return;
@@ -97,6 +153,12 @@ QAndroidStyle::QAndroidStyle()
return;
}
+ QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
+
+ QHash<int, QPalette> * palettes = reinterpret_cast<QHash<int, QPalette> *>(nativeInterface->nativeResourceForIntegration("AndroidStylePalettes"));
+ QHash<int, QFont> * fonts = reinterpret_cast<QHash<int, QFont> *>(nativeInterface->nativeResourceForIntegration("AndroidStyleFonts"));
+ palettes->clear();
+ fonts->clear();
QJsonObject object = document.object();
for (QJsonObject::const_iterator objectIterator = object.constBegin();
objectIterator != object.constEnd();
@@ -110,10 +172,13 @@ QAndroidStyle::QAndroidStyle()
QJsonObject item = value.toObject();
QJsonObject::const_iterator attributeIterator = item.find(QLatin1String("qtClass"));
+ QString qtClassName;
if (attributeIterator != item.constEnd()) {
// The item has palette and font information for a specific Qt Class (e.g. QWidget, QPushButton, etc.)
- const QString qtClassName = attributeIterator.value().toString();
-
+ qtClassName = attributeIterator.value().toString();
+ }
+ const int ft = fontType(key);
+ if (ft > -1 || !qtClassName.isEmpty()) {
// Extract font information
QFont font;
@@ -147,11 +212,25 @@ QAndroidStyle::QAndroidStyle()
}
font.setStyleHint(styleHint, QFont::PreferMatch);
}
- QApplication::setFont(font, qtClassName.toUtf8());
+ if (!qtClassName.isEmpty())
+ QApplication::setFont(font, qtClassName.toUtf8());
+ if (ft>-1)
+ fonts->insert(ft, font);
// Extract font information
+ }
+ const int pt = paletteType(key);
+ if (pt > -1 || !qtClassName.isEmpty()) {
// Extract palette information
QPalette palette;
+ attributeIterator = item.find(QLatin1String("defaultTextColorPrimary"));
+ if (attributeIterator != item.constEnd())
+ palette.setColor(QPalette::WindowText, QRgb(int(attributeIterator.value().toDouble())));
+
+ attributeIterator = item.find(QLatin1String("defaultBackgroundColor"));
+ if (attributeIterator != item.constEnd())
+ palette.setColor(QPalette::Background, QRgb(int(attributeIterator.value().toDouble())));
+
attributeIterator = item.find(QLatin1String("TextAppearance_textColor"));
if (attributeIterator != item.constEnd())
setPaletteColor(attributeIterator.value().toObject().toVariantMap(), palette, QPalette::WindowText);
@@ -163,10 +242,12 @@ QAndroidStyle::QAndroidStyle()
attributeIterator = item.find(QLatin1String("TextAppearance_textColorHighlight"));
if (attributeIterator != item.constEnd())
palette.setColor(QPalette::Highlight, QRgb(int(attributeIterator.value().toDouble())));
- palette.setColor(QPalette::Window, Qt::black);
- QApplication::setPalette(palette, qtClassName.toUtf8());
+
if (QLatin1String("QWidget") == qtClassName)
m_standardPalette = palette;
+
+ if (pt > -1)
+ palettes->insert(pt, palette);
// Extract palette information
}
QAndroidStyle::ItemType itemType = qtControl(key);
@@ -201,10 +282,6 @@ QAndroidStyle::QAndroidStyle()
break;
}
}
- QApplication::setPalette(QApplication::palette("simple_list_item"), "QListView");
- QApplication::setFont(QApplication::font("simple_list_item"), "QListView");
- QApplication::setPalette(QApplication::palette("simple_list_item"), "QAbstractItemView");
- QApplication::setFont(QApplication::font("simple_list_item"), "QAbstractItemView");
}
QAndroidStyle::~QAndroidStyle()
@@ -318,8 +395,6 @@ QAndroidStyle::ItemType QAndroidStyle::qtControl(QStyle::ComplexControl control)
return QC_Combobox;
case CC_Slider:
return QC_Slider;
- case CC_GroupBox:
- return QC_View;
default:
return QC_UnknownType;
}
@@ -340,6 +415,8 @@ QAndroidStyle::ItemType QAndroidStyle::qtControl(QStyle::ContentsType contentsTy
return QC_ProgressBar;
case CT_Slider:
return QC_Slider;
+ case CT_ScrollBar:
+ return QC_Slider;
case CT_TabWidget:
return QC_Tab;
case CT_TabBarTab:
@@ -383,6 +460,9 @@ QAndroidStyle::ItemType QAndroidStyle::qtControl(QStyle::ControlElement controlE
case CE_ComboBoxLabel:
return QC_Combobox;
+ case CE_ShapedFrame:
+ return QC_View;
+
default:
return QC_UnknownType;
}
@@ -438,7 +518,7 @@ void QAndroidStyle::drawPrimitive(PrimitiveElement pe,
if (it != m_androidControlsHash.end())
it.value()->drawControl(opt, p, w);
else
- QCommonStyle::drawPrimitive(pe, opt, p, w);
+ QFusionStyle::drawPrimitive(pe, opt, p, w);
}
@@ -452,16 +532,17 @@ void QAndroidStyle::drawControl(QStyle::ControlElement element,
? m_androidControlsHash.find(itemType)
: m_androidControlsHash.end();
if (it != m_androidControlsHash.end()) {
- it.value()->drawControl(opt, p, w);
+ AndroidControl *androidControl = it.value();
+ androidControl->drawControl(opt, p, w);
switch (itemType) {
case QC_Button:
if (const QStyleOptionButton *buttonOption =
qstyleoption_cast<const QStyleOptionButton *>(opt)) {
- QMargins padding = it.value()->padding();
- QStyleOptionButton copy (*buttonOption);
+ QMargins padding = androidControl->padding();
+ QStyleOptionButton copy(*buttonOption);
copy.rect.adjust(padding.left(), padding.top(), -padding.right(), -padding.bottom());
- QCommonStyle::drawControl(CE_PushButtonLabel, &copy, p, w);
+ QFusionStyle::drawControl(CE_PushButtonLabel, &copy, p, w);
}
break;
case QC_Checkbox:
@@ -472,26 +553,24 @@ void QAndroidStyle::drawControl(QStyle::ControlElement element,
QStyleOptionButton subopt(*btn);
subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents
: SE_CheckBoxContents, btn, w);
- QCommonStyle::drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, p, w);
+ QFusionStyle::drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, p, w);
}
break;
case QC_Combobox:
if (const QStyleOptionComboBox *comboboxOption =
qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
- QMargins padding = it.value()->padding();
+ QMargins padding = androidControl->padding();
QStyleOptionComboBox copy (*comboboxOption);
copy.rect.adjust(padding.left(), padding.top(), -padding.right(), -padding.bottom());
- p->setFont(QApplication::font("simple_spinner_item"));
- p->setPen(QApplication::palette("QPushButton").color(QPalette::Active, QPalette::Text));
- QCommonStyle::drawControl(CE_ComboBoxLabel, comboboxOption, p, w);
+ QFusionStyle::drawControl(CE_ComboBoxLabel, comboboxOption, p, w);
}
break;
default:
break;
}
+ } else {
+ QFusionStyle::drawControl(element, opt, p, w);
}
- else
- QCommonStyle::drawControl(element, opt, p, w);
}
QRect QAndroidStyle::subElementRect(SubElement subElement,
@@ -504,7 +583,7 @@ QRect QAndroidStyle::subElementRect(SubElement subElement,
: m_androidControlsHash.end();
if (it != m_androidControlsHash.end())
return it.value()->subElementRect(subElement, option, widget);
- return QCommonStyle::subElementRect(subElement, option, widget);
+ return QFusionStyle::subElementRect(subElement, option, widget);
}
void QAndroidStyle::drawComplexControl(ComplexControl cc,
@@ -519,7 +598,7 @@ void QAndroidStyle::drawComplexControl(ComplexControl cc,
if (it != m_androidControlsHash.end())
it.value()->drawControl(opt, p, widget);
else
- QCommonStyle::drawComplexControl(cc, opt, p, widget);
+ QFusionStyle::drawComplexControl(cc, opt, p, widget);
}
QStyle::SubControl QAndroidStyle::hitTestComplexControl(ComplexControl cc,
@@ -549,7 +628,7 @@ QStyle::SubControl QAndroidStyle::hitTestComplexControl(ComplexControl cc,
break;
}
}
- return QCommonStyle::hitTestComplexControl(cc, opt, pt, widget);
+ return QFusionStyle::hitTestComplexControl(cc, opt, pt, widget);
}
QRect QAndroidStyle::subControlRect(ComplexControl cc,
@@ -563,7 +642,8 @@ QRect QAndroidStyle::subControlRect(ComplexControl cc,
: m_androidControlsHash.end();
if (it != m_androidControlsHash.end())
return it.value()->subControlRect(opt, sc, widget);
- return QCommonStyle::subControlRect(cc, opt, sc, widget);
+
+ return QFusionStyle::subControlRect(cc, opt, sc, widget);
}
int QAndroidStyle::pixelMetric(PixelMetric metric, const QStyleOption *option,
@@ -575,9 +655,10 @@ int QAndroidStyle::pixelMetric(PixelMetric metric, const QStyleOption *option,
case PM_FocusFrameHMargin:
case PM_ComboBoxFrameWidth:
case PM_SpinBoxFrameWidth:
+ case PM_ScrollBarExtent:
return 0;
default:
- return QCommonStyle::pixelMetric(metric, option, widget);
+ return QFusionStyle::pixelMetric(metric, option, widget);
}
}
@@ -587,7 +668,7 @@ QSize QAndroidStyle::sizeFromContents(ContentsType ct,
const QSize &contentsSize,
const QWidget *w) const
{
- QSize sz=QCommonStyle::sizeFromContents(ct, opt, contentsSize, w);
+ QSize sz = QFusionStyle::sizeFromContents(ct, opt, contentsSize, w);
const ItemType itemType = qtControl(ct);
AndroidControlsHash::const_iterator it = itemType != QC_UnknownType
? m_androidControlsHash.find(itemType)
@@ -601,14 +682,28 @@ QPixmap QAndroidStyle::standardPixmap(StandardPixmap standardPixmap,
const QStyleOption *opt,
const QWidget *widget) const
{
- return QCommonStyle::standardPixmap(standardPixmap, opt, widget);
+ return QFusionStyle::standardPixmap(standardPixmap, opt, widget);
}
QPixmap QAndroidStyle::generatedIconPixmap(QIcon::Mode iconMode,
const QPixmap &pixmap,
const QStyleOption *opt) const
{
- return QCommonStyle::generatedIconPixmap(iconMode, pixmap, opt);
+ return QFusionStyle::generatedIconPixmap(iconMode, pixmap, opt);
+}
+
+int QAndroidStyle::styleHint(QStyle::StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const
+{
+ switch (hint) {
+ case SH_Slider_AbsoluteSetButtons:
+ return 1;
+
+ case SH_RequestSoftwareInputPanel:
+ return RSIP_OnMouseClick;
+
+ default:
+ return QFusionStyle::styleHint(hint,option, widget, returnData);
+ }
}
QPalette QAndroidStyle::standardPalette() const
@@ -616,6 +711,16 @@ QPalette QAndroidStyle::standardPalette() const
return m_standardPalette;
}
+void QAndroidStyle::polish(QWidget *widget)
+{
+ widget->setAttribute(Qt::WA_StyledBackground, true);
+}
+
+void QAndroidStyle::unpolish(QWidget *widget)
+{
+ widget->setAttribute(Qt::WA_StyledBackground, false);
+}
+
QAndroidStyle::AndroidDrawable::AndroidDrawable(const QVariantMap &drawable,
QAndroidStyle::ItemType itemType)
{
@@ -678,6 +783,13 @@ QMargins QAndroidStyle::AndroidDrawable::extractMargins(const QVariantMap &value
return m;
}
+void QAndroidStyle::AndroidDrawable::setPaddingLeftToSizeWidth()
+{
+ QSize sz = size();
+ if (m_padding.isNull() && !sz.isNull())
+ m_padding.setLeft(sz.width());
+}
+
QAndroidStyle::AndroidImageDrawable::AndroidImageDrawable(const QVariantMap &drawable,
QAndroidStyle::ItemType itemType)
@@ -867,6 +979,8 @@ void QAndroidStyle::Android9PatchDrawable::draw(QPainter * painter, const QStyle
i <= numXDivs && src.left() < bitmapWidth;
i++, xIsStretchable = !xIsStretchable) {
color = m_chunkData.colors[colorIndex++];
+ if (color != TRANSPARENT_COLOR)
+ color = NO_COLOR;
if (i == numXDivs) {
src.setRight(bitmapWidth);
dst.setRight(bounds.right());
@@ -904,7 +1018,7 @@ void QAndroidStyle::Android9PatchDrawable::draw(QPainter * painter, const QStyle
if (color == TRANSPARENT_COLOR)
goto nextDiv;
if (color != NO_COLOR)
- painter->fillRect(dst, (QRgb)color);
+ painter->fillRect(dst, QRgb(color));
else
painter->drawPixmap(dst, pixmap, src);
nextDiv:
@@ -930,7 +1044,7 @@ QAndroidStyle::AndroidGradientDrawable::AndroidGradientDrawable(const QVariantMa
QVariantList positions = drawable.value(QLatin1String("positions")).toList();
int min=colors.size() < positions.size() ? colors.size() : positions.size();
for (int i = 0; i < min; i++)
- m_gradient.setColorAt(positions.at(i).toDouble(), (QRgb)colors.at(i).toInt());
+ m_gradient.setColorAt(positions.at(i).toDouble(), QRgb(colors.at(i).toInt()));
QByteArray orientation=drawable.value(QLatin1String("orientation")).toByteArray();
if (orientation == "TOP_BOTTOM") // draw the gradient from the top to the bottom
@@ -1106,33 +1220,33 @@ const QAndroidStyle::AndroidDrawable* QAndroidStyle::AndroidStateDrawable::bestA
foreach (const StateType & state, m_states) {
if (int(opt->state) == state.first)
return state.second;
- uint cost = 0;
+ uint cost = 1;
int difference = int(opt->state^state.first);
if (difference & QStyle::State_Active)
- cost += 1000;
+ cost <<= 1;
if (difference & QStyle::State_Enabled)
- cost += 1000;
+ cost <<= 1;
- if ((m_itemType == QC_Button || m_itemType == QC_EditText) && (difference & QStyle::State_Raised))
- cost += 1000;
+ if (difference & QStyle::State_Raised)
+ cost <<= 1;
- if ((m_itemType == QC_Button || m_itemType == QC_EditText) && (difference & QStyle::State_Sunken))
- cost += 1000;
+ if (difference & QStyle::State_Sunken)
+ cost <<= 1;
if (difference & QStyle::State_Off)
- cost += 1000;
+ cost <<= 1;
if (difference & QStyle::State_On)
- cost += 1000;
+ cost <<= 1;
if (difference & QStyle::State_HasFocus)
- cost += 1000;
+ cost <<= 1;
if (difference & QStyle::State_Selected)
- cost += 1000;
+ cost <<= 1;
if (cost < bestCost) {
bestCost = cost;
@@ -1144,21 +1258,30 @@ const QAndroidStyle::AndroidDrawable* QAndroidStyle::AndroidStateDrawable::bestA
int QAndroidStyle::AndroidStateDrawable::extractState(const QVariantMap &value)
{
- int state = QStyle::State_None;
+ int state = QStyle::State_Enabled | QStyle::State_Active;;
foreach (const QString key, value.keys()) {
bool val = value.value(key).toString() == QLatin1String("true");
- if (key == QLatin1String("enabled") && val) {
- state |= QStyle::State_Enabled;
+ if (key == QLatin1String("enabled")) {
+ if (val)
+ state |= QStyle::State_Enabled;
+ else
+ state &= ~QStyle::State_Enabled;
continue;
}
- if (key == QLatin1String("window_focused") && val) {
- state |= QStyle::State_Active;
+ if (key == QLatin1String("window_focused")) {
+ if (val)
+ state |= QStyle::State_Active;
+ else
+ state &= ~QStyle::State_Active;
continue;
}
- if (key == QLatin1String("focused") && val) {
- state |= QStyle::State_HasFocus;
+ if (key == QLatin1String("focused")) {
+ if (val)
+ state |= QStyle::State_HasFocus;
+ else
+ state &= ~QStyle::State_HasFocus;
continue;
}
@@ -1168,33 +1291,48 @@ int QAndroidStyle::AndroidStateDrawable::extractState(const QVariantMap &value)
}
if (key == QLatin1String("pressed")) {
- state |= val ? QStyle::State_Raised : QStyle::State_Sunken;
- state |= QStyle::State_Enabled | QStyle::State_HasFocus;
+ state |= val ? QStyle::State_Sunken : QStyle::State_Raised;
continue;
}
- if (key == QLatin1String("selected") && val) {
- state |= QStyle::State_Selected;
- state |= QStyle::State_Enabled | QStyle::State_HasFocus;
+ if (key == QLatin1String("selected")) {
+ if (val)
+ state |= QStyle::State_Selected;
+ else
+ state &= ~QStyle::State_Selected;
continue;
}
- if (key == QLatin1String("active") && val) {
- state |= QStyle::State_Active;
+ if (key == QLatin1String("active")) {
+ if (val)
+ state |= QStyle::State_Active;
+ else
+ state &= ~QStyle::State_Active;
continue;
}
- // Keep misspelling for compatibility
- if (key == QLatin1String("backgroud") && val)
+ if (key == QLatin1String("multiline"))
+ return 0;
+
+ if (key == QLatin1String("background") && val)
return -1;
}
return state;
}
+void QAndroidStyle::AndroidStateDrawable::setPaddingLeftToSizeWidth()
+{
+ foreach (const StateType type, m_states)
+ const_cast<AndroidDrawable *>(type.second)->setPaddingLeftToSizeWidth();
+}
+
QAndroidStyle::AndroidLayerDrawable::AndroidLayerDrawable(const QVariantMap &drawable,
QAndroidStyle::ItemType itemType)
: AndroidDrawable(drawable, itemType)
{
+ m_id = 0;
+ m_factor = 1;
+ m_orientation = Qt::Horizontal;
QVariantList layers = drawable.value(QLatin1String("layers")).toList();
foreach (QVariant layer, layers) {
QVariantMap layerMap = layer.toMap();
@@ -1219,10 +1357,29 @@ QAndroidStyle::AndroidDrawableType QAndroidStyle::AndroidLayerDrawable::type() c
return QAndroidStyle::Layer;
}
+void QAndroidStyle::AndroidLayerDrawable::setFactor(int id, double factor, Qt::Orientation orientation)
+{
+ m_id = id;
+ m_factor = factor;
+ m_orientation = orientation;
+}
+
void QAndroidStyle::AndroidLayerDrawable::draw(QPainter *painter, const QStyleOption *opt) const
{
foreach (const LayerType &layer, m_layers)
- layer.second->draw(painter, opt);
+ {
+ if (layer.first == m_id)
+ {
+ QStyleOption copy(*opt);
+ if (m_orientation == Qt::Horizontal)
+ copy.rect.setWidth(copy.rect.width()*m_factor);
+ else
+ copy.rect.setHeight(copy.rect.height()*m_factor);
+ layer.second->draw(painter, &copy);
+ } else {
+ layer.second->draw(painter, opt);
+ }
+ }
}
QAndroidStyle::AndroidDrawable *QAndroidStyle::AndroidLayerDrawable::layer(int id) const
@@ -1274,17 +1431,47 @@ QAndroidStyle::AndroidControl::~AndroidControl()
void QAndroidStyle::AndroidControl::drawControl(const QStyleOption *opt, QPainter *p, const QWidget * /* w */)
{
- if (m_background)
+ if (m_background) {
m_background->draw(p, opt);
+ } else {
+ if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
+ if ((frame->state & State_Sunken) || (frame->state & State_Raised)) {
+ qDrawShadePanel(p, frame->rect, frame->palette, frame->state & State_Sunken,
+ frame->lineWidth);
+ } else {
+ qDrawPlainRect(p, frame->rect, frame->palette.foreground().color(), frame->lineWidth);
+ }
+ } else {
+ if (const QStyleOptionFocusRect *fropt = qstyleoption_cast<const QStyleOptionFocusRect *>(opt)) {
+ QColor bg = fropt->backgroundColor;
+ QPen oldPen = p->pen();
+ if (bg.isValid()) {
+ int h, s, v;
+ bg.getHsv(&h, &s, &v);
+ if (v >= 128)
+ p->setPen(Qt::black);
+ else
+ p->setPen(Qt::white);
+ } else {
+ p->setPen(opt->palette.foreground().color());
+ }
+ QRect focusRect = opt->rect.adjusted(1, 1, -1, -1);
+ p->drawRect(focusRect.adjusted(0, 0, -1, -1)); //draw pen inclusive
+ p->setPen(oldPen);
+ } else {
+ p->fillRect(opt->rect, opt->palette.brush(QPalette::Background));
+ }
+ }
+ }
}
QRect QAndroidStyle::AndroidControl::subElementRect(QStyle::SubElement /* subElement */,
const QStyleOption *option,
const QWidget * /* widget */) const
{
- if (const AndroidDrawable *drawable=m_background) {
+ if (const AndroidDrawable *drawable = backgroundDrawable()) {
if (drawable->type() == State)
- drawable = static_cast<const AndroidStateDrawable *>(m_background)->bestAndroidStateMatch(option);
+ drawable = static_cast<const AndroidStateDrawable *>(backgroundDrawable())->bestAndroidStateMatch(option);
const QMargins &padding = drawable->padding();
@@ -1315,10 +1502,10 @@ QSize QAndroidStyle::AndroidControl::sizeFromContents(const QStyleOption *opt,
const QWidget * /* w */) const
{
QSize sz;
- if (const AndroidDrawable *drawable=m_background) {
+ if (const AndroidDrawable *drawable = backgroundDrawable()) {
if (drawable->type() == State)
- drawable = static_cast<const AndroidStateDrawable*>(m_background)->bestAndroidStateMatch(opt);
+ drawable = static_cast<const AndroidStateDrawable*>(backgroundDrawable())->bestAndroidStateMatch(opt);
const QMargins &padding = drawable->padding();
sz.setWidth(padding.left() + padding.right());
sz.setHeight(padding.top() + padding.bottom());
@@ -1346,6 +1533,11 @@ QMargins QAndroidStyle::AndroidControl::padding()
return QMargins();
}
+const QAndroidStyle::AndroidDrawable *QAndroidStyle::AndroidControl::backgroundDrawable() const
+{
+ return m_background;
+}
+
QAndroidStyle::AndroidCompoundButtonControl::AndroidCompoundButtonControl(const QVariantMap &control,
ItemType itemType)
: AndroidControl(control, itemType)
@@ -1355,6 +1547,7 @@ QAndroidStyle::AndroidCompoundButtonControl::AndroidCompoundButtonControl(const
m_button = AndroidDrawable::fromMap(it.value().toMap(), itemType);
else
m_button = 0;
+ const_cast<AndroidDrawable *>(m_button)->setPaddingLeftToSizeWidth();
}
QAndroidStyle::AndroidCompoundButtonControl::~AndroidCompoundButtonControl()
@@ -1371,6 +1564,11 @@ void QAndroidStyle::AndroidCompoundButtonControl::drawControl(const QStyleOption
m_button->draw(p, opt);
}
+const QAndroidStyle::AndroidDrawable *QAndroidStyle::AndroidCompoundButtonControl::backgroundDrawable() const
+{
+ return m_background ? m_background : m_button;
+}
+
QAndroidStyle::AndroidProgressBarControl::AndroidProgressBarControl(const QVariantMap &control,
ItemType itemType)
: AndroidControl(control, itemType)
@@ -1429,8 +1627,11 @@ void QAndroidStyle::AndroidProgressBarControl::drawControl(const QStyleOption *o
if (m_progressDrawable->type() == QAndroidStyle::Layer) {
QAndroidStyle::AndroidDrawable *clipDrawable = static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->layer(m_progressId);
if (clipDrawable->type() == QAndroidStyle::Clip)
- static_cast<QAndroidStyle::AndroidClipDrawable *>(clipDrawable)->setFactor(double(progressBarV2.progress/(progressBarV2.maximum-progressBarV2.minimum)),
+ static_cast<QAndroidStyle::AndroidClipDrawable *>(clipDrawable)->setFactor(double(progressBarV2.progress)/double(progressBarV2.maximum-progressBarV2.minimum),
progressBarV2.orientation);
+ else
+ static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->setFactor(m_progressId,double(progressBarV2.progress)/double(progressBarV2.maximum-progressBarV2.minimum),
+ progressBarV2.orientation);
}
m_progressDrawable->draw(p, option);
}
@@ -1523,11 +1724,13 @@ void QAndroidStyle::AndroidSeekBarControl::drawControl(const QStyleOption *optio
if (const QStyleOptionSlider *styleOption =
qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- double factor = double(styleOption->sliderPosition/(styleOption->maximum-styleOption->minimum));
+ double factor = double(styleOption->sliderPosition)/double(styleOption->maximum-styleOption->minimum);
if (m_progressDrawable->type()==QAndroidStyle::Layer) {
QAndroidStyle::AndroidDrawable *clipDrawable = static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->layer(m_progressId);
if (clipDrawable->type() == QAndroidStyle::Clip)
static_cast<QAndroidStyle::AndroidClipDrawable *>(clipDrawable)->setFactor(factor, styleOption->orientation);
+ else
+ static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->setFactor(m_progressId, factor, styleOption->orientation);
}
const AndroidDrawable *drawable=m_seekBarThumb;
if (drawable->type() == State)
@@ -1535,12 +1738,12 @@ void QAndroidStyle::AndroidSeekBarControl::drawControl(const QStyleOption *optio
QStyleOption copy(*option);
copy.rect.setY((copy.rect.height()-m_minSize.height())/2);
copy.rect.setHeight(m_minSize.height());
- copy.rect.setWidth(copy.rect.width()-drawable->size().width());
- copy.rect.translate(drawable->size().width()/2,0);
+ copy.rect.setWidth(copy.rect.width() - drawable->size().width());
+ copy.rect.translate(drawable->size().width()/2, 0);
m_progressDrawable->draw(p, &copy);
if (styleOption->orientation == Qt::Vertical)
qCritical() << "Vertical slider are not supported";
- int pos = (double(copy.rect.width()*factor - drawable->size().width()) / 2);
+ int pos = copy.rect.width()*factor - drawable->size().width()/2;
copy.rect.translate(pos, 0);
copy.rect.setSize(drawable->size());
m_seekBarThumb->draw(p, &copy);
diff --git a/src/widgets/styles/qandroidstyle_p.h b/src/widgets/styles/qandroidstyle_p.h
index 2d9abd65c5..d64e37b9db 100644
--- a/src/widgets/styles/qandroidstyle_p.h
+++ b/src/widgets/styles/qandroidstyle_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
+** Copyright (C) 2013 BogDan Vatra <bogdan@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -55,15 +55,15 @@
#include <QtCore/QList>
#include <QtCore/QMargins>
-#include <QtWidgets/QCommonStyle>
#include <QtCore/QHash>
#include <QtCore/QVariantMap>
+#include "qfusionstyle_p.h"
QT_BEGIN_NAMESPACE
#if !defined(QT_NO_STYLE_ANDROID)
-class Q_WIDGETS_EXPORT QAndroidStyle : public QCommonStyle
+class Q_WIDGETS_EXPORT QAndroidStyle : public QFusionStyle
{
Q_OBJECT
@@ -86,7 +86,7 @@ public:
QC_TabButton,
QC_RatingIndicator,
QC_SearchBox,
- QC_CustomCOntrol=0xf00,
+ QC_CustomControl=0xf00,
QC_ControlMask=0xfff
};
@@ -131,6 +131,7 @@ public:
virtual QSize size() const;
static AndroidDrawable *fromMap(const QVariantMap &drawable, ItemType itemType);
static QMargins extractMargins(const QVariantMap &value);
+ virtual void setPaddingLeftToSizeWidth();
protected:
ItemType m_itemType;
QMargins m_padding;
@@ -226,6 +227,7 @@ public:
virtual void draw(QPainter *painter, const QStyleOption *opt) const;
inline const AndroidDrawable *bestAndroidStateMatch(const QStyleOption *opt) const;
static int extractState(const QVariantMap &value);
+ virtual void setPaddingLeftToSizeWidth();
private:
typedef QPair<int, const AndroidDrawable *> StateType;
@@ -238,12 +240,16 @@ public:
AndroidLayerDrawable(const QVariantMap &drawable, QAndroidStyle::ItemType itemType);
~AndroidLayerDrawable();
virtual AndroidDrawableType type() const;
+ virtual void setFactor(int id, double factor, Qt::Orientation orientation);
virtual void draw(QPainter *painter, const QStyleOption *opt) const;
AndroidDrawable *layer(int id) const;
QSize size() const;
private:
typedef QPair<int, AndroidDrawable *> LayerType;
QList<LayerType> m_layers;
+ int m_id;
+ double m_factor;
+ Qt::Orientation m_orientation;
};
class AndroidControl
@@ -263,6 +269,7 @@ public:
const QWidget *w) const;
virtual QMargins padding();
protected:
+ virtual const AndroidDrawable * backgroundDrawable() const;
const AndroidDrawable *m_background;
QSize m_minSize;
QSize m_maxSize;
@@ -276,6 +283,7 @@ public:
virtual void drawControl(const QStyleOption *opt, QPainter *p, const QWidget *w);
protected:
+ virtual const AndroidDrawable * backgroundDrawable() const;
const AndroidDrawable *m_button;
};
@@ -356,7 +364,13 @@ public:
virtual QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap,
const QStyleOption *opt) const;
+ int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0,
+ QStyleHintReturn *returnData = 0) const;
+
virtual QPalette standardPalette() const;
+ void polish(QWidget *widget);
+ void unpolish(QWidget *widget);
+
private:
Q_DISABLE_COPY(QAndroidStyle)
static ItemType qtControl(QStyle::ComplexControl control);
diff --git a/src/widgets/styles/qcommonstyle_p.h b/src/widgets/styles/qcommonstyle_p.h
index 979c2a5548..8f8a97a2dc 100644
--- a/src/widgets/styles/qcommonstyle_p.h
+++ b/src/widgets/styles/qcommonstyle_p.h
@@ -92,19 +92,19 @@ public:
mutable QRect decorationRect, displayRect, checkRect;
mutable QStyleOptionViewItem *cachedOption;
bool isViewItemCached(const QStyleOptionViewItem &option) const {
- return cachedOption && (option.rect == cachedOption->rect
- && option.direction == cachedOption->direction
+ return cachedOption && (option.widget == cachedOption->widget
+ && option.index == cachedOption->index
&& option.state == cachedOption->state
+ && option.rect == cachedOption->rect
+ && option.text == cachedOption->text
+ && option.direction == cachedOption->direction
&& option.displayAlignment == cachedOption->displayAlignment
&& option.decorationAlignment == cachedOption->decorationAlignment
&& option.decorationPosition == cachedOption->decorationPosition
&& option.decorationSize == cachedOption->decorationSize
- && option.font == cachedOption->font
&& option.features == cachedOption->features
- && option.widget == cachedOption->widget
- && option.index == cachedOption->index
&& option.icon.isNull() == cachedOption->icon.isNull()
- && option.text == cachedOption->text
+ && option.font == cachedOption->font
&& option.viewItemPosition == cachedOption->viewItemPosition);
}
#endif
diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp
index 288375fe28..0355578327 100644
--- a/src/widgets/widgets/qabstractspinbox.cpp
+++ b/src/widgets/widgets/qabstractspinbox.cpp
@@ -41,7 +41,7 @@
#include <qplatformdefs.h>
#include <private/qabstractspinbox_p.h>
-#include <private/qdatetime_p.h>
+#include <private/qdatetimeparser_p.h>
#include <private/qlineedit_p.h>
#include <qabstractspinbox.h>
diff --git a/src/widgets/widgets/qdatetimeedit_p.h b/src/widgets/widgets/qdatetimeedit_p.h
index 143979d4bc..3174ec9bde 100644
--- a/src/widgets/widgets/qdatetimeedit_p.h
+++ b/src/widgets/widgets/qdatetimeedit_p.h
@@ -61,7 +61,7 @@
#include "QtWidgets/qlabel.h"
#include "QtWidgets/qdatetimeedit.h"
#include "private/qabstractspinbox_p.h"
-#include "private/qdatetime_p.h"
+#include "private/qdatetimeparser_p.h"
#include "qdebug.h"