summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-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
33 files changed, 2499 insertions, 2184 deletions
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 \