- Deprecate qGenericMatrixFromMatrix4x4 and qGenericMatrixToMatrix4x4
- QListView diverses optimisations [QTBUG-11438]
- QTreeWidget/QListWidget: use localeAwareCompare for string comparisons [QTBUG-10839]
+ - PNG image I/O: Much improved support for text annotations, including iTXt fields.
+ - QRawFont and QGlyphRun are introduced for low-level text rendering. [QTBUG-18252]
+ - QFont: hintingPreference() is introduced to control hinting in font rendering and
+ subpixel positioning of glyphs for Windows, Mac OS X and X11/raster. [QTBUG-10615]
+ - Subpixel positioned text layout is supported in raster and OpenGL paint engines.
+ - QFont: styleName() is added to allow selecting fonts with irregular style names
+ like UltraLight. [QTBUG-19366]
+ - Visual text cursor movement behavior is added to QTextEdit and QLineEdit controls,
+ which can be used as an optional mode for bi-directional text editing. [QTBUG-13859]
QtNetwork
---------
Qt for Linux/X11
----------------
-
+ - Now takes font hinting settings from GConf by default if running in
+ GNOME desktop.
+ - Various fixes to FontConfig font matching code to make it consistent
+ with other X11 programs. [QTBUG-2148, QTBUG-19947, QTBUG-14269]
Qt for Windows
--------------
-
+ - DirectWrite experimental text shaping engine is added with subpixel
+ positioning support. [QTBUG-12678]
Qt for Mac OS X
---------------
-
+ - raster graphics system is now made as the default paint engine for
+ Mac OS X. [QTBUG-12615]
+ - HarfBuzz can now be used as an optional text layout engine on Mac OS X.
+ [QTBUG-17728]
Qt for Embedded Linux
---------------------
\example painting/affine
\title Affine Transformations
- In this demo we show Qt's ability to perform affine transformations
+ In this example we show Qt's ability to perform affine transformations
on painting operations.
\image affine-demo.png
/*!
\example sql/books
- \title Books Demonstration
+ \title Books
- The Books demonstration shows how Qt's SQL classes can be used with the model/view
+ The Books example shows how Qt's SQL classes can be used with the model/view
framework to create rich user interfaces for information stored in a database.
\image books-demo.png
****************************************************************************/
/*!
- \example embedded/styledemo
+ \example embedded/styleexample
\title Embedded Styles
\image styledemo-demo.png
\section2 4.2 Qt Documentation
- Qt 4.7 comes with 17 examples and 2 Demonstrations for model/view.
+ Qt 5.0 comes with 19 examples for model/view.
The examples can be found on the \l{Item Views Examples} page.
\table
\o QStandardItemModel
\o
\row
+ \o Interview
+ \o Multiple
+ \o Custom item model
+ \o Multiple views
+ \row
\o Pixelator
\o QTableView
\o Custom table model
\o QStandardItemModel
\o Custom delegate that uses a spin box as a cell editor
\row
+ \o Spreadsheet
+ \o {2, 1} QTableView
+ \o Custom delegates
+ \row
\o Star Delegate
\o {2, 1} QTableWidget
\o Comprehensive custom delegate example.
\endtable
- \l{Qt Demonstrations}{Demonstrations} are similar to examples except that no
- walkthrough is provided for the code. Demonstrations are typically more
- feature rich than examples.
-
- \list
- \o The \bold Interview demonstration shows the same model and
- selection being shared between three different views.
- \o The \bold Spreadsheet demonstration illustrates the use of a
- table view as a spreadsheet, using custom delegates to render
- each item according to the type of data it contains.
- \endlist
-
A \l{Model/View Programming}{reference document} for model/view technology
is also available.
*/
-Qt is supplied with a number of example applications and demonstrations that
-have been written to provide developers with examples of the Qt API in use,
+Qt is supplied with a number of example applications that have been
+written to provide developers with examples of the Qt API in use,
highlight good programming practice, and showcase features found in each of
Qt's core technologies.
-The example and demo launcher can be used to explore the different categories
-available. It provides an overview of each example, lets you view the
-documentation in Qt Assistant, and is able to launch examples and demos.
-Documentation for examples can be found in the Tutorials and Examples section
+Documentation for examples can be found in the Examples section
of the Qt documentation.
-
-
-Finding the Qt Examples and Demos launcher
-==========================================
-
-On Windows:
-
-The launcher can be accessed via the Windows Start menu. Select the menu
-entry entitled "Qt Examples and Demos" entry in the submenu containing
-the Qt tools.
-
-On Mac OS X:
-
-For the binary distribution, the qtdemo executable is installed in the
-/Developer/Applications/Qt directory. For the source distribution, it is
-installed alongside the other Qt tools on the path specified when Qt is
-configured.
-
-On Unix/Linux:
-
-The qtdemo executable is installed alongside the other Qt tools on the path
-specified when Qt is configured.
-
-On all platforms:
-
-The source code for the launcher can be found in the demos/qtdemo directory
-in the Qt package. This example is built at the same time as the Qt libraries,
-tools, examples, and demonstrations.
TEMPLATE = subdirs
-SUBDIRS = styledemo raycasting flickable digiflip
+SUBDIRS = styleexample raycasting flickable digiflip
SUBDIRS += lightmaps
SUBDIRS += flightinfo
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
- Q_INIT_RESOURCE(styledemo);
+ Q_INIT_RESOURCE(styleexample);
app.setApplicationName("style");
app.setOrganizationName("Nokia");
HEADERS += stylewidget.h
FORMS += stylewidget.ui
SOURCES += main.cpp stylewidget.cpp
-RESOURCES += styledemo.qrc
+RESOURCES += styleexample.qrc
-target.path = $$[QT_INSTALL_DEMOS]/qtbase/embedded/styledemo
+target.path = $$[QT_INSTALL_EXAMPLES]/qtbase/embedded/styleexample
sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS *.pro *.html
-sources.path = $$[QT_INSTALL_DEMOS]/qtbase/embedded/styledemo
+sources.path = $$[QT_INSTALL_EXAMPLES]/qtbase/embedded/styleexample
INSTALLS += target sources
symbian {
TARGET.UID3 = 0xA000A63F
- CONFIG += qt_demo
+ CONFIG += qt_example
}
QT += widgets widgets
</layout>
</widget>
<resources>
- <include location="StyleDemo.qrc"/>
+ <include location="styleexample.qrc"/>
</resources>
<connections>
<connection>
layout->addWidget(vSplitter);
setLayout(layout);
- setWindowTitle(tr("Chip Demo"));
+ setWindowTitle(tr("Chip Example"));
}
void MainWindow::populateScene()
view.setBackgroundBrush(QPixmap(":/No-Ones-Laughing-3.jpg"));
view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
view.show();
- view.setWindowTitle("Embedded Dialogs Demo");
+ view.setWindowTitle("Embedded Dialogs Example");
return app.exec();
}
#include <qdebug.h>
static const char * const message =
- "<p><b>Qt Main Window Demo</b></p>"
+ "<p><b>Qt Main Window Example</b></p>"
"<p>This is a demonstration of the QMainWindow, QToolBar and "
"QDockWidget classes.</p>"
: QMainWindow(parent, flags)
{
setObjectName("MainWindow");
- setWindowTitle("Qt Main Window Demo");
+ setWindowTitle("Qt Main Window Example");
center = new QTextEdit(this);
center->setReadOnly(true);
// defaults
view->reset();
vectorType->setChecked(true);
- textEditor->setText("Qt Affine Transformation Demo");
+ textEditor->setText("Qt Affine Transformation Example");
textEditor->setEnabled(false);
animateButton->animateClick();
<html>
-<h1>Demo for composition modes</h1>
+<h1>Example for composition modes</h1>
<p>
- This demo shows some of the more advanced composition modes supported by Qt.
+ This example shows some of the more advanced composition modes supported by Qt.
</p>
<p>
-<html><head><meta name="qrichtext" content="1" /><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>QTextEdit Demonstration</title><style type="text/css">
+<html><head><meta name="qrichtext" content="1" /><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>QTextEdit Example</title><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;">
<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:20pt; font-weight:600;">QTextEdit</span></p>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">The QTextEdit widget is an advanced editor that supports formatted rich text. It can be used to display HTML and other rich document formats. Internally, QTextEdit uses the QTextDocument class to describe both the high-level structure of each document and the low-level formatting of paragraphs.</span></p>
-<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">If you are viewing this document in the <span style=" font-style:italic;">textedit</span> demo, you can edit this document to explore Qt's rich text editing features. We have included some comments in each of the following sections to encourage you to experiment. </p>
+<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">If you are viewing this document in the <span style=" font-style:italic;">textedit</span> example, you can edit this document to explore Qt's rich text editing features. We have included some comments in each of the following sections to encourage you to experiment. </p>
<p style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; font-weight:600;"><span style=" font-size:16pt;">Font and Paragraph Styles</span></p>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">QTextEdit supports </span><span style=" font-size:11pt; font-weight:600;">bold</span><span style=" font-size:11pt;">, </span><span style=" font-size:11pt; font-style:italic;">italic</span><span style=" font-size:11pt;">, and </span><span style=" font-size:11pt; text-decoration: underline;">underlined</span><span style=" font-size:11pt;"> font styles, and can display </span><span style=" font-size:11pt; font-weight:600; color:#00007f;">multicolored</span><span style=" font-size:11pt;"> </span><span style=" font-size:11pt; font-weight:600; color:#aa0000;">text</span><span style=" font-size:11pt;">. Font families such as </span><span style=" font-family:'Times'; font-size:11pt; font-weight:600;">Times New Roman</span><span style=" font-size:11pt;"> and </span><span style=" font-family:'Courier'; font-size:11pt; font-weight:600;">Courier</span><span style=" font-size:11pt;"> can also be used directly. </span><span style=" font-size:11pt; font-style:italic;">If you place the cursor in a region of styled text, the controls in the tool bars will change to reflect the current style.</span></p>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">Paragraphs can be formatted so that the text is left-aligned, right-aligned, centered, or fully justified.</p>
QMAKE_LIBDIR += $$QMAKE_LIBDIR_QT
# Topological ordering of modules based on their QT.<module>.depends variable
-QT = $$resolve_depends($$QT, "QT.")
+QT = $$sort_depends(QT, "QT.")
QT_DEPENDS=
DataPath,
TranslationsPath,
SettingsPath,
- DemosPath,
ExamplesPath,
ImportsPath
};
E_SPRINTF, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION,
E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_ESCAPE_EXPAND,
E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, E_REPLACE,
- E_SIZE, E_GENERATE_UID, E_RESOLVE_DEPENDS };
+ E_SIZE, E_GENERATE_UID, E_SORT_DEPENDS, E_RESOLVE_DEPENDS };
QMap<QString, ExpandFunc> qmake_expandFunctions()
{
static QMap<QString, ExpandFunc> *qmake_expand_functions = 0;
qmake_expand_functions->insert("replace", E_REPLACE);
qmake_expand_functions->insert("size", E_SIZE);
qmake_expand_functions->insert("generate_uid", E_GENERATE_UID);
+ qmake_expand_functions->insert("sort_depends", E_SORT_DEPENDS);
qmake_expand_functions->insert("resolve_depends", E_RESOLVE_DEPENDS);
}
return *qmake_expand_functions;
// defined in symbian generator
extern QString generate_test_uid(const QString& target);
-
-void calculateDeps(QStringList &sortedList, const QString &item, const QString &prefix,
- QStringList &org, QMap<QString, QStringList> &place)
-{
- if (sortedList.contains(item))
- return;
-
- foreach(QString dep, place.value(prefix + item + ".depends")) {
- calculateDeps(sortedList, dep, prefix, org, place);
- if (org.isEmpty())
- break;
- }
-
- if (org.contains(item)) {
- sortedList += item;
- org.removeAll(item);
- }
-}
-
-QStringList
-QMakeProject::resolveDepends(const QStringList &deps, const QString &prefix,
- QMap<QString, QStringList> &place)
+static void
+populateDeps(const QStringList &deps, const QString &prefix,
+ QHash<QString, QSet<QString> > &dependencies, QHash<QString, QStringList> &dependees,
+ QStringList &rootSet, QMap<QString, QStringList> &place)
{
- QStringList sortedList;
- QStringList org = deps;
- foreach(QString item, deps) {
- calculateDeps(sortedList, item, prefix, org, place);
- if (org.isEmpty())
- break;
- }
- return sortedList;
+ foreach (const QString &item, deps)
+ if (!dependencies.contains(item)) {
+ QSet<QString> &dset = dependencies[item]; // Always create entry
+ QStringList depends = place.value(prefix + item + ".depends");
+ if (depends.isEmpty()) {
+ rootSet << item;
+ } else {
+ foreach (const QString &dep, depends) {
+ dset.insert(dep);
+ dependees[dep] << item;
+ }
+ populateDeps(depends, prefix, dependencies, dependees, rootSet, place);
+ }
+ }
}
QStringList
ret += generate_test_uid(args.first());
}
break;
+ case E_SORT_DEPENDS:
case E_RESOLVE_DEPENDS: {
if(args.count() < 1 || args.count() > 2) {
- fprintf(stderr, "%s:%d: resolve_depends(var, prefix) requires one or two arguments.\n",
- parser.file.toLatin1().constData(), parser.line_no);
+ fprintf(stderr, "%s:%d: %s(var, prefix) requires one or two arguments.\n",
+ parser.file.toLatin1().constData(), parser.line_no, func.toLatin1().constData());
} else {
- ret += resolveDepends(args[0].split(QString(Option::field_sep)),
- (args.count() != 2 ? QString() : args[1]),
- place);
+ QHash<QString, QSet<QString> > dependencies;
+ QHash<QString, QStringList> dependees;
+ QStringList rootSet;
+
+ QStringList orgList = values(args[0], place);
+ populateDeps(orgList, (args.count() != 2 ? QString() : args[1]),
+ dependencies, dependees, rootSet, place);
+
+ for (int i = 0; i < rootSet.size(); ++i) {
+ const QString &item = rootSet.at(i);
+ if ((func_t == E_RESOLVE_DEPENDS) || orgList.contains(item))
+ ret.prepend(item);
+ foreach (const QString &dep, dependees[item]) {
+ QSet<QString> &dset = dependencies[dep];
+ dset.remove(item);
+ if (dset.isEmpty())
+ rootSet << dep;
+ }
+ }
}
break; }
default: {
QStringList doVariableReplaceExpand(const QString &str, QMap<QString, QStringList> &place, bool *ok=0);
void init(QMakeProperty *, const QMap<QString, QStringList> *);
QStringList &values(const QString &v, QMap<QString, QStringList> &place);
- QStringList resolveDepends(const QStringList &deps, const QString &prefix, QMap<QString, QStringList> &place);
void validateModes();
public:
else if(v == "QT_INSTALL_EXAMPLES")
return QLibraryInfo::location(QLibraryInfo::ExamplesPath);
else if(v == "QT_INSTALL_DEMOS")
- return QLibraryInfo::location(QLibraryInfo::DemosPath);
+ return QLibraryInfo::location(QLibraryInfo::ExamplesPath);
else if(v == "QMAKE_MKSPECS")
return qmake_mkspec_paths().join(Option::dirlist_sep);
else if(v == "QMAKE_VERSION")
qlist.cpp \
qlinkedlist.cpp \
qlocale.cpp \
+ qlocale_tools.cpp \
qmalloc.cpp \
qmap.cpp \
qmetatype.cpp \
qlist.h \
qlinkedlist.h \
qlocale.h \
+ qlocale_tools_p.h \
qmalloc.h \
qmap.h \
qmetatype.h \
generators/win32 \
generators/mac \
generators/symbian \
+ generators/integrity \
$$QT_SOURCE_TREE/include \
$$QT_SOURCE_TREE/include/QtCore \
$$QT_SOURCE_TREE/include/QtCore/$$QT_VERSION \
****************************************************************************/
#include "qtconcurrentexception.h"
+#include "QtCore/qshareddata.h"
#ifndef QT_NO_QFUTURE
#ifndef QT_NO_EXCEPTIONS
namespace internal {
-class Base
+class Base : public QSharedData
{
public:
Base(Exception *exception)
- : exception(exception), refCount(1), hasThrown(false) { }
+ : exception(exception), hasThrown(false) { }
~Base() { delete exception; }
Exception *exception;
- QAtomicInt refCount;
bool hasThrown;
};
ExceptionHolder::ExceptionHolder(const ExceptionHolder &other)
: base(other.base)
-{
- base->refCount.ref();
-}
+{}
void ExceptionHolder::operator=(const ExceptionHolder &other)
{
- if (base == other.base)
- return;
-
- if (base->refCount.deref() == false)
- delete base;
-
base = other.base;
- base->refCount.ref();
}
ExceptionHolder::~ExceptionHolder()
-{
- if (base->refCount.deref() == 0)
- delete base;
-}
+{}
Exception *ExceptionHolder::exception() const
{
#ifndef QT_NO_QFUTURE
#include <QtCore/qatomic.h>
+#include <QtCore/qshareddata.h>
#ifndef QT_NO_EXCEPTIONS
# include <exception>
void operator=(const ExceptionHolder &other);
~ExceptionHolder();
Exception *exception() const;
- Base *base;
+ QExplicitlySharedDataPointer<Base> base;
};
class Q_CORE_EXPORT ExceptionStore
\sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11, Q_WS_QWS
*/
+/*!
+ \macro QT_DISABLE_DEPRECATED_BEFORE
+ \relates <QtGlobal>
+
+ This macro can be defined in the project file to disable functions deprecated in
+ a specified version of Qt or any earlier version. The default version number is 5.0,
+ meaning that functions deprecated in or before Qt 5.0 will not be included.
+
+ Examples:
+ When using a future release of Qt 5, set QT_DISABLE_DEPRECATED_BEFORE=0x050100 to
+ disable functions deprecated in Qt 5.1 and earlier. In any release, set
+ QT_DISABLE_DEPRECATED_BEFORE=0x000000 to enable any functions, including the ones
+ deprecated in Qt 5.0
+ */
+
#if defined(QT_BUILD_QMAKE)
// needed to bootstrap qmake
static const unsigned int qt_one = 1;
*/
#define QT_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
+#ifndef QT_DISABLE_DEPRECATED_BEFORE
+#define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(5, 0, 0)
+#endif
+
+/*
+ QT_DEPRECATED_SINCE(major, minor) evaluates as true if the Qt version is greater than
+ the deprecation point specified.
+
+ Use it to specify from which version of Qt a function or class has been deprecated
+
+ Example:
+ #if QT_DEPRECATED_SINCE(5,1)
+ QT_DEPRECATED void deprecatedFunction(); //function deprecated sine Qt 5.1
+ #endif
+ */
+#define QT_DEPRECATED_SINCE(major, minor) (QT_VERSION_CHECK(major, minor, 0) > QT_DISABLE_DEPRECATED_BEFORE)
+
#define QT_PACKAGEDATE_STR "YYYY-MM-DD"
#define QT_PACKAGE_TAG ""
# endif
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404
/* C++0x features supported in GCC 4.4: */
+# define Q_COMPILER_UNICODE_STRINGS
# define Q_COMPILER_VARIADIC_TEMPLATES
# define Q_COMPILER_AUTO_TYPE
# define Q_COMPILER_EXTERN_TEMPLATES
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
/* C++0x features supported in GCC 4.5: */
# define Q_COMPILER_LAMBDA
-# define Q_COMPILER_UNICODE_STRINGS
# endif
+# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
+ /* C++0x features supported in GCC 4.6: */
+# define Q_COMPILER_CONSTEXPR
+# endif
+
# endif
/* IBM compiler versions are a bit messy. There are actually two products:
#error "Compiler doesn't support the bool type"
#endif
+
/*
Constant bool values
*/
# define QT_FASTCALL
#endif
+#ifdef Q_COMPILER_CONSTEXPR
+# define Q_DECL_CONSTEXPR constexpr
+#else
+# define Q_DECL_CONSTEXPR
+#endif
+
//defines the type for the WNDPROC on windows
//the alignment needs to be forced for sse2 to not crash with mingw
#if defined(Q_OS_WIN)
typedef int QNoImplicitBoolCast;
-#if defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_MIPS) && (defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_WINCE))) || defined(QT_ARCH_SH) || defined(QT_ARCH_SH4A)
-#define QT_NO_FPU
-#endif
-
// This logic must match the one in qmetatype.h
#if defined(QT_COORD_TYPE)
typedef QT_COORD_TYPE qreal;
*/
template <typename T>
-inline T qAbs(const T &t) { return t >= 0 ? t : -t; }
+Q_DECL_CONSTEXPR inline T qAbs(const T &t) { return t >= 0 ? t : -t; }
-inline int qRound(qreal d)
+Q_DECL_CONSTEXPR inline int qRound(qreal d)
{ return d >= qreal(0.0) ? int(d + qreal(0.5)) : int(d - int(d-1) + qreal(0.5)) + int(d-1); }
#if defined(QT_NO_FPU) || defined(QT_ARCH_ARM) || defined(QT_ARCH_WINDOWSCE) || defined(QT_ARCH_SYMBIAN)
-inline qint64 qRound64(double d)
+Q_DECL_CONSTEXPR inline qint64 qRound64(double d)
{ return d >= 0.0 ? qint64(d + 0.5) : qint64(d - qreal(qint64(d-1)) + 0.5) + qint64(d-1); }
#else
-inline qint64 qRound64(qreal d)
+Q_DECL_CONSTEXPR inline qint64 qRound64(qreal d)
{ return d >= qreal(0.0) ? qint64(d + qreal(0.5)) : qint64(d - qreal(qint64(d-1)) + qreal(0.5)) + qint64(d-1); }
#endif
template <typename T>
-inline const T &qMin(const T &a, const T &b) { if (a < b) return a; return b; }
+Q_DECL_CONSTEXPR inline const T &qMin(const T &a, const T &b) { return (a < b) ? a : b; }
template <typename T>
-inline const T &qMax(const T &a, const T &b) { if (a < b) return b; return a; }
+Q_DECL_CONSTEXPR inline const T &qMax(const T &a, const T &b) { return (a < b) ? b : a; }
template <typename T>
-inline const T &qBound(const T &min, const T &val, const T &max)
+Q_DECL_CONSTEXPR inline const T &qBound(const T &min, const T &val, const T &max)
{ return qMax(min, qMin(max, val)); }
/*
inline bool operator!=(bool b1, QBool b2) { return !b1 != !b2; }
inline bool operator!=(QBool b1, QBool b2) { return !b1 != !b2; }
-static inline bool qFuzzyCompare(double p1, double p2)
+Q_DECL_CONSTEXPR static inline bool qFuzzyCompare(double p1, double p2)
{
return (qAbs(p1 - p2) <= 0.000000000001 * qMin(qAbs(p1), qAbs(p2)));
}
-static inline bool qFuzzyCompare(float p1, float p2)
+Q_DECL_CONSTEXPR static inline bool qFuzzyCompare(float p1, float p2)
{
return (qAbs(p1 - p2) <= 0.00001f * qMin(qAbs(p1), qAbs(p2)));
}
/*!
\internal
*/
-static inline bool qFuzzyIsNull(double d)
+Q_DECL_CONSTEXPR static inline bool qFuzzyIsNull(double d)
{
return qAbs(d) <= 0.000000000001;
}
/*!
\internal
*/
-static inline bool qFuzzyIsNull(float f)
+Q_DECL_CONSTEXPR static inline bool qFuzzyIsNull(float f)
{
return qAbs(f) <= 0.00001f;
}
int i;
public:
typedef Enum enum_type;
- inline QFlags(const QFlags &f) : i(f.i) {}
- inline QFlags(Enum f) : i(f) {}
- inline QFlags(Zero = 0) : i(0) {}
+ Q_DECL_CONSTEXPR inline QFlags(const QFlags &f) : i(f.i) {}
+ Q_DECL_CONSTEXPR inline QFlags(Enum f) : i(f) {}
+ Q_DECL_CONSTEXPR inline QFlags(Zero = 0) : i(0) {}
inline QFlags(QFlag f) : i(f) {}
inline QFlags &operator=(const QFlags &f) { i = f.i; return *this; }
inline QFlags &operator^=(QFlags f) { i ^= f.i; return *this; }
inline QFlags &operator^=(Enum f) { i ^= f; return *this; }
- inline operator int() const { return i; }
+ Q_DECL_CONSTEXPR inline operator int() const { return i; }
- inline QFlags operator|(QFlags f) const { QFlags g; g.i = i | f.i; return g; }
- inline QFlags operator|(Enum f) const { QFlags g; g.i = i | f; return g; }
- inline QFlags operator^(QFlags f) const { QFlags g; g.i = i ^ f.i; return g; }
- inline QFlags operator^(Enum f) const { QFlags g; g.i = i ^ f; return g; }
- inline QFlags operator&(int mask) const { QFlags g; g.i = i & mask; return g; }
- inline QFlags operator&(uint mask) const { QFlags g; g.i = i & mask; return g; }
- inline QFlags operator&(Enum f) const { QFlags g; g.i = i & f; return g; }
- inline QFlags operator~() const { QFlags g; g.i = ~i; return g; }
+ Q_DECL_CONSTEXPR inline QFlags operator|(QFlags f) const { return QFlags(Enum(i | f.i)); }
+ Q_DECL_CONSTEXPR inline QFlags operator|(Enum f) const { return QFlags(Enum(i | f)); }
+ Q_DECL_CONSTEXPR inline QFlags operator^(QFlags f) const { return QFlags(Enum(i ^ f.i)); }
+ Q_DECL_CONSTEXPR inline QFlags operator^(Enum f) const { return QFlags(Enum(i ^ f)); }
+ Q_DECL_CONSTEXPR inline QFlags operator&(int mask) const { return QFlags(Enum(i & mask)); }
+ Q_DECL_CONSTEXPR inline QFlags operator&(uint mask) const { return QFlags(Enum(i & mask)); }
+ Q_DECL_CONSTEXPR inline QFlags operator&(Enum f) const { return QFlags(Enum(i & f)); }
+ Q_DECL_CONSTEXPR inline QFlags operator~() const { return QFlags(Enum(~i)); }
- inline bool operator!() const { return !i; }
+ Q_DECL_CONSTEXPR inline bool operator!() const { return !i; }
inline bool testFlag(Enum f) const { return (i & f) == f && (f != 0 || i == int(f) ); }
};
{ return QIncompatibleFlag(int(f1) | f2); }
#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \
-inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) \
+Q_DECL_CONSTEXPR inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) \
{ return QFlags<Flags::enum_type>(f1) | f2; } \
-inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) \
+Q_DECL_CONSTEXPR inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) \
{ return f2 | f1; } Q_DECLARE_INCOMPATIBLE_FLAGS(Flags)
path = QT_CONFIGURE_EXAMPLES_PATH;
break;
#endif
-#ifdef QT_CONFIGURE_DEMOS_PATH
- case DemosPath:
- path = QT_CONFIGURE_DEMOS_PATH;
- break;
-#endif
default:
break;
}
case ExamplesPath:
key = QLatin1String("Examples");
break;
- case DemosPath:
- key = QLatin1String("Demos");
- break;
default:
break;
}
\value TranslationsPath The location of translation information for Qt strings.
\value SettingsPath The location for Qt settings.
\value ExamplesPath The location for examples upon install.
- \value DemosPath The location for demos upon install.
\sa location()
*/
DataPath,
TranslationsPath,
SettingsPath,
- DemosPath,
ExamplesPath,
ImportsPath
};
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** 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.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** 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.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
// call overhead.
QObjectPrivate *d = receiver->d_func();
QThreadData *threadData = d->threadData;
- ++threadData->loopLevel;
+
+ // Exception-safety without try/catch
+ struct Incrementer {
+ int &variable;
+ inline Incrementer(int &variable) : variable(variable)
+ { ++variable; }
+ inline ~Incrementer()
+ { --variable; }
+ };
+ Incrementer inc(threadData->loopLevel);
#ifdef QT_JAMBI_BUILD
int deleteWatch = 0;
#endif
bool returnValue;
- QT_TRY {
- returnValue = notify(receiver, event);
- } QT_CATCH (...) {
- --threadData->loopLevel;
- QT_RETHROW;
- }
+ returnValue = notify(receiver, event);
#ifdef QT_JAMBI_BUILD
// Restore the previous state if the object was not deleted..
}
QObjectPrivate::resetDeleteWatch(d, oldDeleteWatch, deleteWatch);
#endif
- --threadData->loopLevel;
return returnValue;
}
int &i = (!event_type && !receiver) ? data->postEventList.startOffset : startOffset;
data->postEventList.insertionOffset = data->postEventList.size();
+ // Exception-safe cleaning up without the need for a try/catch block
+ struct CleanUp {
+ QObject *receiver;
+ int event_type;
+ QThreadData *data;
+ bool exceptionCaught;
+
+ inline CleanUp(QObject *receiver, int event_type, QThreadData *data) :
+ receiver(receiver), event_type(event_type), data(data), exceptionCaught(true)
+ {}
+ inline ~CleanUp()
+ {
+ if (exceptionCaught) {
+ // since we were interrupted, we need another pass to make sure we clean everything up
+ data->canWait = false;
+ }
+
+ --data->postEventList.recursion;
+ if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
+ data->eventDispatcher->wakeUp();
+
+ // clear the global list, i.e. remove everything that was
+ // delivered.
+ if (!event_type && !receiver && data->postEventList.startOffset >= 0) {
+ const QPostEventList::iterator it = data->postEventList.begin();
+ data->postEventList.erase(it, it + data->postEventList.startOffset);
+ data->postEventList.insertionOffset -= data->postEventList.startOffset;
+ Q_ASSERT(data->postEventList.insertionOffset >= 0);
+ data->postEventList.startOffset = 0;
+ }
+ }
+ };
+ CleanUp cleanup(receiver, event_type, data);
+
while (i < data->postEventList.size()) {
// avoid live-lock
if (i >= data->postEventList.insertionOffset)
// first, we diddle the event so that we can deliver
// it, and that no one will try to touch it later.
pe.event->posted = false;
- QEvent * e = pe.event;
+ QScopedPointer<QEvent> e(pe.event);
QObject * r = pe.receiver;
--r->d_func()->postedEvents;
// for the next event.
const_cast<QPostEvent &>(pe).event = 0;
- locker.unlock();
- // after all that work, it's time to deliver the event.
-#ifdef QT_NO_EXCEPTIONS
- QCoreApplication::sendEvent(r, e);
-#else
- try {
- QCoreApplication::sendEvent(r, e);
- } catch (...) {
- delete e;
- locker.relock();
-
- // since we were interrupted, we need another pass to make sure we clean everything up
- data->canWait = false;
-
- // uglehack: copied from below
- --data->postEventList.recursion;
- if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
- data->eventDispatcher->wakeUp();
- throw; // rethrow
- }
-#endif
+ struct MutexUnlocker
+ {
+ QMutexLocker &m;
+ MutexUnlocker(QMutexLocker &m) : m(m) { m.unlock(); }
+ ~MutexUnlocker() { m.relock(); }
+ };
+ MutexUnlocker unlocker(locker);
- delete e;
- locker.relock();
+ // after all that work, it's time to deliver the event.
+ QCoreApplication::sendEvent(r, e.data());
// careful when adding anything below this point - the
// sendEvent() call might invalidate any invariants this
// function depends on.
}
- --data->postEventList.recursion;
- if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
- data->eventDispatcher->wakeUp();
-
- // clear the global list, i.e. remove everything that was
- // delivered.
- if (!event_type && !receiver && data->postEventList.startOffset >= 0) {
- const QPostEventList::iterator it = data->postEventList.begin();
- data->postEventList.erase(it, it + data->postEventList.startOffset);
- data->postEventList.insertionOffset -= data->postEventList.startOffset;
- Q_ASSERT(data->postEventList.insertionOffset >= 0);
- data->postEventList.startOffset = 0;
- }
+ cleanup.exceptionCaught = false;
}
/*!
qWarning("QEventLoop::exec: instance %p has already called exec()", this);
return -1;
}
- d->inExec = true;
- d->exit = false;
- ++d->threadData->loopLevel;
- d->threadData->eventLoops.push(this);
- locker.unlock();
+
+ struct LoopReference {
+ QEventLoopPrivate *d;
+ QMutexLocker &locker;
+
+ bool exceptionCaught;
+ LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true)
+ {
+ d->inExec = true;
+ d->exit = false;
+ ++d->threadData->loopLevel;
+ d->threadData->eventLoops.push(d->q_func());
+ locker.unlock();
+ }
+
+ ~LoopReference()
+ {
+ if (exceptionCaught) {
+ qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
+ "exceptions from an event handler is not supported in Qt. You must\n"
+ "reimplement QApplication::notify() and catch all exceptions there.\n");
+ }
+ locker.relock();
+ QEventLoop *eventLoop = d->threadData->eventLoops.pop();
+ Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error");
+ Q_UNUSED(eventLoop); // --release warning
+ d->inExec = false;
+ --d->threadData->loopLevel;
+ }
+ };
+ LoopReference ref(d, locker);
// remove posted quit events when entering a new event loop
QCoreApplication *app = QCoreApplication::instance();
if (app && app->thread() == thread())
QCoreApplication::removePostedEvents(app, QEvent::Quit);
-#if defined(QT_NO_EXCEPTIONS)
while (!d->exit)
processEvents(flags | WaitForMoreEvents | EventLoopExec);
-#else
- try {
- while (!d->exit)
- processEvents(flags | WaitForMoreEvents | EventLoopExec);
- } catch (...) {
- qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
- "exceptions from an event handler is not supported in Qt. You must\n"
- "reimplement QApplication::notify() and catch all exceptions there.\n");
-
- // copied from below
- locker.relock();
- QEventLoop *eventLoop = d->threadData->eventLoops.pop();
- Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error");
- Q_UNUSED(eventLoop); // --release warning
- d->inExec = false;
- --d->threadData->loopLevel;
-
- throw;
- }
-#endif
-
- // copied above
- locker.relock();
- QEventLoop *eventLoop = d->threadData->eventLoops.pop();
- Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error");
- Q_UNUSED(eventLoop); // --release warning
- d->inExec = false;
- --d->threadData->loopLevel;
+ ref.exceptionCaught = false;
return d->returnCode;
}
}
}
+struct QConnectionSenderSwitcher {
+ QObject *receiver;
+ QObjectPrivate::Sender *previousSender;
+ QObjectPrivate::Sender currentSender;
+ bool switched;
+
+ inline QConnectionSenderSwitcher() : switched(false) {}
+
+ inline QConnectionSenderSwitcher(QObject *receiver, QObject *sender, int signal_absolute_id)
+ {
+ switchSender(receiver, sender, signal_absolute_id);
+ }
+
+ inline void switchSender(QObject *receiver, QObject *sender, int signal_absolute_id)
+ {
+ this->receiver = receiver;
+ currentSender.sender = sender;
+ currentSender.signal = signal_absolute_id;
+ currentSender.ref = 1;
+ previousSender = QObjectPrivate::setCurrentSender(receiver, ¤tSender);
+ switched = true;
+ }
+
+ inline ~QConnectionSenderSwitcher()
+ {
+ if (switched)
+ QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender);
+ }
+private:
+ Q_DISABLE_COPY(QConnectionSenderSwitcher)
+};
+
+
void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0;
void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0;
void (*QAbstractDeclarativeData::objectNameChanged)(QAbstractDeclarativeData *, QObject *) = 0;
d_func()->inEventHandler = false;
#endif
QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e);
- QObjectPrivate::Sender currentSender;
- currentSender.sender = const_cast<QObject*>(mce->sender());
- currentSender.signal = mce->signalId();
- currentSender.ref = 1;
- QObjectPrivate::Sender * const previousSender =
- QObjectPrivate::setCurrentSender(this, ¤tSender);
-#if defined(QT_NO_EXCEPTIONS)
+
+ QConnectionSenderSwitcher sw(this, const_cast<QObject*>(mce->sender()), mce->signalId());
+
mce->placeMetaCall(this);
-#else
- QT_TRY {
- mce->placeMetaCall(this);
- } QT_CATCH(...) {
- QObjectPrivate::resetCurrentSender(this, ¤tSender, previousSender);
- QT_RETHROW;
- }
-#endif
- QObjectPrivate::resetCurrentSender(this, ¤tSender, previousSender);
break;
}
type &= Qt::UniqueConnection - 1;
}
- QObjectPrivate::Connection *c = new QObjectPrivate::Connection;
+ QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection);
c->sender = s;
c->receiver = r;
c->method_relative = method_index;
c->nextConnectionList = 0;
c->callFunction = callFunction;
- QT_TRY {
- QObjectPrivate::get(s)->addConnection(signal_index, c);
- } QT_CATCH(...) {
- delete c;
- QT_RETHROW;
- }
+ QObjectPrivate::get(s)->addConnection(signal_index, c.data());
c->prev = &(QObjectPrivate::get(r)->senders);
c->next = *c->prev;
- *c->prev = c;
+ *c->prev = c.data();
if (c->next)
c->next->prev = &c->next;
sender_d->connectedSignals[signal_index >> 5] |= (1 << (signal_index & 0x1f));
}
+ c.take(); // stop tracking
return true;
}
Qt::HANDLE currentThreadId = QThread::currentThreadId();
+ {
QMutexLocker locker(signalSlotLock(sender));
- QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;
- if (!connectionLists) {
+ struct ConnectionListsRef {
+ QObjectConnectionListVector *connectionLists;
+ ConnectionListsRef(QObjectConnectionListVector *connectionLists) : connectionLists(connectionLists)
+ {
+ if (connectionLists)
+ ++connectionLists->inUse;
+ }
+ ~ConnectionListsRef()
+ {
+ if (!connectionLists)
+ return;
+
+ --connectionLists->inUse;
+ Q_ASSERT(connectionLists->inUse >= 0);
+ if (connectionLists->orphaned) {
+ if (!connectionLists->inUse)
+ delete connectionLists;
+ }
+ }
+
+ QObjectConnectionListVector *operator->() const { return connectionLists; }
+ };
+ ConnectionListsRef connectionLists = sender->d_func()->connectionLists;
+ if (!connectionLists.connectionLists) {
locker.unlock();
if (qt_signal_spy_callback_set.signal_end_callback != 0)
qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index);
return;
}
- ++connectionLists->inUse;
-
const QObjectPrivate::ConnectionList *list;
if (signal_index < connectionLists->count())
#endif
}
- QObjectPrivate::Sender currentSender;
- QObjectPrivate::Sender *previousSender = 0;
+ QConnectionSenderSwitcher sw;
+
if (receiverInSameThread) {
- currentSender.sender = sender;
- currentSender.signal = signal_absolute_index;
- currentSender.ref = 1;
- previousSender = QObjectPrivate::setCurrentSender(receiver, ¤tSender);
+ sw.switchSender(receiver, sender, signal_absolute_index);
}
const QObjectPrivate::StaticMetaCallFunction callFunction = c->callFunction;
const int method_relative = c->method_relative;
argv ? argv : empty_argv);
}
-#if defined(QT_NO_EXCEPTIONS)
metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
-#else
- QT_TRY {
- metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
- } QT_CATCH(...) {
- locker.relock();
- if (receiverInSameThread)
- QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender);
-
- --connectionLists->inUse;
- Q_ASSERT(connectionLists->inUse >= 0);
- if (connectionLists->orphaned && !connectionLists->inUse)
- delete connectionLists;
- QT_RETHROW;
- }
-#endif
if (qt_signal_spy_callback_set.slot_end_callback != 0)
qt_signal_spy_callback_set.slot_end_callback(receiver, method);
locker.relock();
}
- if (receiverInSameThread)
- QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender);
-
if (connectionLists->orphaned)
break;
} while (c != last && (c = c->nextConnectionList) != 0);
//start over for all signals;
((list = &connectionLists->allsignals), true));
- --connectionLists->inUse;
- Q_ASSERT(connectionLists->inUse >= 0);
- if (connectionLists->orphaned) {
- if (!connectionLists->inUse)
- delete connectionLists;
- } else if (connectionLists->dirty) {
- sender->d_func()->cleanConnectionLists();
}
- locker.unlock();
-
if (qt_signal_spy_callback_set.signal_end_callback != 0)
qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index);
inline bool isSharedWith(const QByteArray &other) const { return d == other.d; }
void clear();
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
- const char at(int i) const;
- const char operator[](int i) const;
- const char operator[](uint i) const;
-#else
char at(int i) const;
char operator[](int i) const;
char operator[](uint i) const;
-#endif
QByteRef operator[](int i);
QByteRef operator[](uint i);
inline int QByteArray::size() const
{ return d->size; }
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
-inline const char QByteArray::at(int i) const
-{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
-inline const char QByteArray::operator[](int i) const
-{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
-inline const char QByteArray::operator[](uint i) const
-{ Q_ASSERT(i < uint(size())); return d->data[i]; }
-#else
inline char QByteArray::at(int i) const
{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
inline char QByteArray::operator[](int i) const
{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
inline char QByteArray::operator[](uint i) const
{ Q_ASSERT(i < uint(size())); return d->data[i]; }
-#endif
inline bool QByteArray::isEmpty() const
{ return d->size == 0; }
: a(array),i(idx) {}
friend class QByteArray;
public:
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
- inline operator const char() const
- { return i < a.d->size ? a.d->data[i] : char(0); }
-#else
inline operator char() const
{ return i < a.d->size ? a.d->data[i] : char(0); }
-#endif
inline QByteRef &operator=(char c)
{ if (i >= a.d->size) a.expand(i); else a.detach();
a.d->data[i] = c; return *this; }
\sa toLatin1(), unicode(), QTextCodec::codecForCStrings()
*/
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
-const char QChar::toAscii() const
-#else
char QChar::toAscii() const
-#endif
{
#ifndef QT_NO_CODEC_FOR_C_STRINGS
if (QTextCodec::codecForCStrings())
{
public:
inline explicit QLatin1Char(char c) : ch(c) {}
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
- inline const char toLatin1() const { return ch; }
- inline const ushort unicode() const { return ushort(uchar(ch)); }
-#else
inline char toLatin1() const { return ch; }
inline ushort unicode() const { return ushort(uchar(ch)); }
-#endif
private:
char ch;
UnicodeVersion unicodeVersion() const;
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
- const char toAscii() const;
- inline const char toLatin1() const;
- inline const ushort unicode() const { return ucs; }
-#else
char toAscii() const;
inline char toLatin1() const;
inline ushort unicode() const { return ucs; }
-#endif
-#ifdef Q_NO_PACKED_REFERENCE
- inline ushort &unicode() { return const_cast<ushort&>(ucs); }
-#else
inline ushort &unicode() { return ucs; }
-#endif
static QChar fromAscii(char c);
static QChar fromLatin1(char c);
inline QChar::QChar() : ucs(0) {}
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
-inline const char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); }
-#else
inline char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); }
-#endif
inline QChar QChar::fromLatin1(char c) { return QChar(ushort(uchar(c))); }
inline QChar::QChar(uchar c, uchar r) : ucs(ushort((r << 8) | c)){}
if (b - n >= 2 * d->alloc / 3) {
// we have enough space. Just not at the end -> move it.
e -= b;
- ::memcpy(d->array, d->array + b, e * sizeof(void *));
+ ::memmove(d->array, d->array + b, e * sizeof(void *));
d->begin = 0;
} else {
realloc(grow(d->alloc + n));
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QtPrivate::RefCount
+ \internal
+
+ QRefCount implements atomic ref counting for Qt's shared classes. It behaves very similar
+ to QAtomicInt, but ignores negative ref counts.
+
+ This can be used to allow to implement e.g. const read-only QStringData objects. QString::shared_null and
+ the qs(...) macro make use of this feature.
+*/
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QREFCOUNT_H
+#define QREFCOUNT_H
+
+#include <QtCore/qatomic.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+namespace QtPrivate
+{
+
+class RefCount
+{
+public:
+ inline void ref() {
+ if (atomic >= 0)
+ atomic.ref();
+ }
+
+ inline bool deref() {
+ if (atomic < 0)
+ return true;
+ return atomic.deref();
+ }
+
+ inline bool operator==(int value) const
+ { return atomic.operator ==(value); }
+ inline bool operator!=(int value) const
+ { return atomic.operator !=(value); }
+ inline bool operator!() const
+ { return atomic.operator !(); }
+ inline operator int() const
+ { return atomic.operator int(); }
+ inline RefCount &operator=(int value)
+ { atomic = value; return *this; }
+
+ QBasicAtomicInt atomic;
+};
+
+#define Q_REFCOUNT_INITIALIZER(a) { Q_BASIC_ATOMIC_INITIALIZER(a) }
+
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
\section1 More Efficient String Construction
+ Many strings are known at compile time. But the trivial
+ constructor QString("Hello"), will convert the string literal
+ to a QString using the codecForCStrings(). To avoid this one
+ can use the QStringLiteral macro to directly create the required
+ data at compile time. Constructing a QString out of the literal
+ does then not cause any overhead at runtime.
+
+ A slightly less efficient way is to use QLatin1String. This class wraps
+ a C string literal, precalculates it length at compile time and can
+ then be used for faster comparison with QStrings and conversion to
+ QStrings than a regular C string literal.
+
Using the QString \c{'+'} operator, it is easy to construct a
complex string from multiple substrings. You will often write code
like this:
where \e{n > 2}, there can be as many as \e{n - 1} calls to the
memory allocator.
- Second, QLatin1String does not store its length internally but
- calls qstrlen() when it needs to know its length.
-
In 4.6, an internal template class \c{QStringBuilder} has been
added along with a few helper functions. This class is marked
internal and does not appear in the documentation, because you
then called \e{once} to get the required space, and the substrings
are copied into it one by one.
- \c{QLatin1Literal} is a second internal class that can replace
- QLatin1String, which can't be changed for compatibility reasons.
- \c{QLatin1Literal} stores its length, thereby saving time when
- \c{QStringBuilder} computes the amount of memory required for the
- final string.
-
Additional efficiency is gained by inlining and reduced reference
counting (the QString created from a \c{QStringBuilder} typically
has a ref count of 1, whereas QString::append() needs an extra
\sa split()
*/
-QString::Data QString::shared_null = { Q_BASIC_ATOMIC_INITIALIZER(1),
- 0, 0, shared_null.array, 0, 0, 0, 0, 0, {0} };
-QString::Data QString::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1),
- 0, 0, shared_empty.array, 0, 0, 0, 0, 0, {0} };
+const QConstStringData<1> QString::shared_null = { { Q_REFCOUNT_INITIALIZER(-1), 0, 0, false, { 0 } }, { 0 } };
+const QConstStringData<1> QString::shared_empty = { { Q_REFCOUNT_INITIALIZER(-1), 0, 0, false, { 0 } }, { 0 } };
int QString::grow(int size)
{
QString::QString(const QChar *unicode, int size)
{
if (!unicode) {
- d = &shared_null;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_null.str);
} else if (size <= 0) {
- d = &shared_empty;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_empty.str);
} else {
- d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar));
Q_CHECK_PTR(d);
- d->ref = 1;
- d->alloc = d->size = size;
- d->clean = d->simpletext = d->righttoleft = d->capacity = 0;
- d->data = d->array;
- memcpy(d->array, unicode, size * sizeof(QChar));
- d->array[size] = '\0';
+ *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } };
+ memcpy(d->data(), unicode, size * sizeof(QChar));
+ d->data()[size] = '\0';
}
}
QString::QString(const QChar *unicode)
{
if (!unicode) {
- d = &shared_null;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_null.str);
} else {
int size = 0;
while (unicode[size] != 0)
++size;
if (!size) {
- d = &shared_empty;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_empty.str);
} else {
- d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar));
Q_CHECK_PTR(d);
- d->ref = 1;
- d->alloc = d->size = size;
- d->clean = d->simpletext = d->righttoleft = d->capacity = 0;
- d->data = d->array;
- memcpy(d->array, unicode, size * sizeof(QChar));
- d->array[size] = '\0';
+ *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } };
+ memcpy(d->data(), unicode, size * sizeof(QChar));
+ d->data()[size] = '\0';
}
}
}
QString::QString(int size, QChar ch)
{
if (size <= 0) {
- d = &shared_empty;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_empty.str);
} else {
- d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar));
Q_CHECK_PTR(d);
- d->ref = 1;
- d->alloc = d->size = size;
- d->clean = d->simpletext = d->righttoleft = d->capacity = 0;
- d->data = d->array;
- d->array[size] = '\0';
- ushort *i = d->array + size;
- ushort *b = d->array;
+ *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } };
+ d->data()[size] = '\0';
+ ushort *i = d->data() + size;
+ ushort *b = d->data();
const ushort value = ch.unicode();
while (i != b)
*--i = value;
*/
QString::QString(int size, Qt::Initialization)
{
- d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar));
Q_CHECK_PTR(d);
- d->ref = 1;
- d->alloc = d->size = size;
- d->clean = d->simpletext = d->righttoleft = d->capacity = 0;
- d->data = d->array;
- d->array[size] = '\0';
+ *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } };
+ d->data()[size] = '\0';
}
/*! \fn QString::QString(const QLatin1String &str)
*/
QString::QString(QChar ch)
{
- void *buf = qMalloc(sizeof(Data) + sizeof(QChar));
- Q_CHECK_PTR(buf);
- d = reinterpret_cast<Data *>(buf);
- d->ref = 1;
- d->alloc = d->size = 1;
- d->clean = d->simpletext = d->righttoleft = d->capacity = 0;
- d->data = d->array;
- d->array[0] = ch.unicode();
- d->array[1] = '\0';
+ d = (Data *) qMalloc(sizeof(Data) + 2*sizeof(QChar));
+ Q_CHECK_PTR(d);
+ *d = (Data) { Q_REFCOUNT_INITIALIZER(1), 1, 1, false, { 0 } };
+ d->data()[0] = ch.unicode();
+ d->data()[1] = '\0';
}
/*! \fn QString::QString(const QByteArray &ba)
if (size < 0)
size = 0;
- if (size == 0 && !d->capacity) {
- Data *x = &shared_empty;
- x->ref.ref();
+ if (d->offset && d->ref == 1 && size < d->size) {
+ d->size = size;
+ return;
+ }
+
+ if (size == 0 && !d->capacityReserved) {
+ Data *x = const_cast<Data *>(&shared_empty.str);
if (!d->ref.deref())
QString::free(d);
d = x;
} else {
if (d->ref != 1 || size > d->alloc ||
- (!d->capacity && size < d->size && size < d->alloc >> 1))
+ (!d->capacityReserved && size < d->size && size < d->alloc >> 1))
realloc(grow(size));
if (d->alloc >= size) {
d->size = size;
- if (d->data == d->array) {
- d->array[size] = '\0';
- }
+ d->data()[size] = '\0';
}
}
}
// ### Qt 5: rename reallocData() to avoid confusion. 197625
void QString::realloc(int alloc)
{
- if (d->ref != 1 || d->data != d->array) {
- Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc * sizeof(QChar)));
+ if (d->ref != 1 || d->offset) {
+ Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + (alloc+1) * sizeof(QChar)));
Q_CHECK_PTR(x);
- x->size = qMin(alloc, d->size);
- ::memcpy(x->array, d->data, x->size * sizeof(QChar));
- x->array[x->size] = 0;
- x->ref = 1;
- x->alloc = alloc;
- x->clean = d->clean;
- x->simpletext = d->simpletext;
- x->righttoleft = d->righttoleft;
- x->capacity = d->capacity;
- x->data = x->array;
+ *x = (Data){ Q_REFCOUNT_INITIALIZER(1), qMin(alloc, d->size), alloc, d->capacityReserved, { 0 } };
+ ::memcpy(x->data(), d->data(), x->size * sizeof(QChar));
+ x->data()[x->size] = 0;
if (!d->ref.deref())
QString::free(d);
d = x;
} else {
- Data *p = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar)));
+ Data *p = static_cast<Data *>(qRealloc(d, sizeof(Data) + (alloc+1) * sizeof(QChar)));
Q_CHECK_PTR(p);
d = p;
d->alloc = alloc;
- d->data = d->array;
+ d->offset = 0;
}
}
int sz = d->size;
resize(qMax(i + 1, sz));
if (d->size - 1 > sz) {
- ushort *n = d->data + d->size - 1;
- ushort *e = d->data + sz;
+ ushort *n = d->data() + d->size - 1;
+ ushort *e = d->data() + sz;
while (n != e)
* --n = ' ';
}
int len = qstrlen(str.latin1());
expand(qMax(d->size, i) + len - 1);
- ::memmove(d->data + i + len, d->data + i, (d->size - i - len) * sizeof(QChar));
+ ::memmove(d->data() + i + len, d->data() + i, (d->size - i - len) * sizeof(QChar));
for (int j = 0; j < len; ++j)
- d->data[i + j] = s[j];
+ d->data()[i + j] = s[j];
return *this;
}
return *this;
const ushort *s = (const ushort *)unicode;
- if (s >= d->data && s < d->data + d->alloc) {
+ if (s >= d->data() && s < d->data() + d->alloc) {
// Part of me - take a copy
ushort *tmp = static_cast<ushort *>(qMalloc(size * sizeof(QChar)));
Q_CHECK_PTR(tmp);
expand(qMax(d->size, i) + size - 1);
- ::memmove(d->data + i + size, d->data + i, (d->size - i - size) * sizeof(QChar));
- memcpy(d->data + i, s, size * sizeof(QChar));
+ ::memmove(d->data() + i + size, d->data() + i, (d->size - i - size) * sizeof(QChar));
+ memcpy(d->data() + i, s, size * sizeof(QChar));
return *this;
}
if (i < 0)
return *this;
expand(qMax(i, d->size));
- ::memmove(d->data + i + 1, d->data + i, (d->size - i) * sizeof(QChar));
- d->data[i] = ch.unicode();
+ ::memmove(d->data() + i + 1, d->data() + i, (d->size - i) * sizeof(QChar));
+ d->data()[i] = ch.unicode();
return *this;
}
*/
QString &QString::append(const QString &str)
{
- if (str.d != &shared_null) {
- if (d == &shared_null) {
+ if (str.d != &shared_null.str) {
+ if (d == &shared_null.str) {
operator=(str);
} else {
if (d->ref != 1 || d->size + str.d->size > d->alloc)
realloc(grow(d->size + str.d->size));
- memcpy(d->data + d->size, str.d->data, str.d->size * sizeof(QChar));
+ memcpy(d->data() + d->size, str.d->data(), str.d->size * sizeof(QChar));
d->size += str.d->size;
- d->data[d->size] = '\0';
+ d->data()[d->size] = '\0';
}
}
return *this;
int len = qstrlen((char *)s);
if (d->ref != 1 || d->size + len > d->alloc)
realloc(grow(d->size + len));
- ushort *i = d->data + d->size;
+ ushort *i = d->data() + d->size;
while ((*i++ = *s++))
;
d->size += len;
{
if (d->ref != 1 || d->size + 1 > d->alloc)
realloc(grow(d->size + 1));
- d->data[d->size++] = ch.unicode();
- d->data[d->size] = '\0';
+ d->data()[d->size++] = ch.unicode();
+ d->data()[d->size] = '\0';
return *this;
}
resize(pos); // truncate
} else if (len > 0) {
detach();
- memmove(d->data + pos, d->data + pos + len,
+ memmove(d->data() + pos, d->data() + pos + len,
(d->size - pos - len + 1) * sizeof(ushort));
d->size -= len;
}
ushort c = ch.unicode();
if (cs == Qt::CaseSensitive) {
while (i < d->size)
- if (d->data[i] == ch)
+ if (d->data()[i] == ch)
remove(i, 1);
else
i++;
} else {
c = foldCase(c);
while (i < d->size)
- if (foldCase(d->data[i]) == c)
+ if (foldCase(d->data()[i]) == c)
remove(i, 1);
else
i++;
*/
void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen)
{
- // copy *after in case it lies inside our own d->data area
+ // copy *after in case it lies inside our own d->data() area
// (which we could possibly invalidate via a realloc or corrupt via memcpy operations.)
QChar *afterBuffer = const_cast<QChar *>(after);
- if (after >= reinterpret_cast<QChar *>(d->data) && after < reinterpret_cast<QChar *>(d->data) + d->size) {
+ if (after >= reinterpret_cast<QChar *>(d->data()) && after < reinterpret_cast<QChar *>(d->data()) + d->size) {
afterBuffer = static_cast<QChar *>(qMalloc(alen*sizeof(QChar)));
Q_CHECK_PTR(afterBuffer);
::memcpy(afterBuffer, after, alen*sizeof(QChar));
// replace in place
detach();
for (int i = 0; i < nIndices; ++i)
- memcpy(d->data + indices[i], afterBuffer, alen * sizeof(QChar));
+ memcpy(d->data() + indices[i], afterBuffer, alen * sizeof(QChar));
} else if (alen < blen) {
// replace from front
detach();
uint to = indices[0];
if (alen)
- memcpy(d->data+to, after, alen*sizeof(QChar));
+ memcpy(d->data()+to, after, alen*sizeof(QChar));
to += alen;
uint movestart = indices[0] + blen;
for (int i = 1; i < nIndices; ++i) {
int msize = indices[i] - movestart;
if (msize > 0) {
- memmove(d->data + to, d->data + movestart, msize * sizeof(QChar));
+ memmove(d->data() + to, d->data() + movestart, msize * sizeof(QChar));
to += msize;
}
if (alen) {
- memcpy(d->data + to, afterBuffer, alen*sizeof(QChar));
+ memcpy(d->data() + to, afterBuffer, alen*sizeof(QChar));
to += alen;
}
movestart = indices[i] + blen;
}
int msize = d->size - movestart;
if (msize > 0)
- memmove(d->data + to, d->data + movestart, msize * sizeof(QChar));
+ memmove(d->data() + to, d->data() + movestart, msize * sizeof(QChar));
resize(d->size - nIndices*(blen-alen));
} else {
// replace from back
int movestart = indices[nIndices] + blen;
int insertstart = indices[nIndices] + nIndices*(alen-blen);
int moveto = insertstart + alen;
- memmove(d->data + moveto, d->data + movestart,
+ memmove(d->data() + moveto, d->data() + movestart,
(moveend - movestart)*sizeof(QChar));
- memcpy(d->data + insertstart, afterBuffer, alen*sizeof(QChar));
+ memcpy(d->data() + insertstart, afterBuffer, alen*sizeof(QChar));
moveend = movestart-blen;
}
}
return remove(ch, cs);
if (after.d->size == 1)
- return replace(ch, after.d->data[0], cs);
+ return replace(ch, after.d->data()[0], cs);
if (d->size == 0)
return *this;
uint pos = 0;
if (cs == Qt::CaseSensitive) {
while (pos < 1023 && index < d->size) {
- if (d->data[index] == cc)
+ if (d->data()[index] == cc)
indices[pos++] = index;
index++;
}
} else {
while (pos < 1023 && index < d->size) {
- if (QChar::toCaseFolded(d->data[index]) == cc)
+ if (QChar::toCaseFolded(d->data()[index]) == cc)
indices[pos++] = index;
index++;
}
ushort b = before.unicode();
if (d->size) {
detach();
- ushort *i = d->data;
+ ushort *i = d->data();
const ushort *e = i + d->size;
if (cs == Qt::CaseSensitive) {
for (; i != e; ++i)
const QString &after,
Qt::CaseSensitivity cs)
{
- int blen = qstrlen(before.latin1());
+ int blen = before.size();
QVarLengthArray<ushort> b(blen);
for (int i = 0; i < blen; ++i)
b[i] = (uchar)before.latin1()[i];
const QLatin1String &after,
Qt::CaseSensitivity cs)
{
- int alen = qstrlen(after.latin1());
+ int alen = after.size();
QVarLengthArray<ushort> a(alen);
for (int i = 0; i < alen; ++i)
a[i] = (uchar)after.latin1()[i];
*/
QString &QString::replace(QChar c, const QLatin1String &after, Qt::CaseSensitivity cs)
{
- int alen = qstrlen(after.latin1());
+ int alen = after.size();
QVarLengthArray<ushort> a(alen);
for (int i = 0; i < alen; ++i)
a[i] = (uchar)after.latin1()[i];
if (d->size != other.d->size)
return false;
- return qMemEquals(d->data, other.d->data, d->size);
+ return qMemEquals(d->data(), other.d->data(), d->size);
}
/*!
*/
bool QString::operator==(const QLatin1String &other) const
{
- const ushort *uc = d->data;
- const ushort *e = uc + d->size;
- const uchar *c = (uchar *)other.latin1();
+ if (d->size != other.size())
+ return false;
- if (!c)
+ if (!other.size())
return isEmpty();
- while (*c) {
- if (uc == e || *uc != *c)
+ const ushort *uc = d->data();
+ const ushort *e = uc + d->size;
+ const uchar *c = (uchar *)other.latin1();
+
+ while (uc < e) {
+ if (*uc != *c)
return false;
++uc;
++c;
}
- return (uc == e);
+ return true;
}
/*! \fn bool QString::operator==(const QByteArray &other) const
*/
bool QString::operator<(const QLatin1String &other) const
{
- const ushort *uc = d->data;
- const ushort *e = uc + d->size;
const uchar *c = (uchar *) other.latin1();
-
if (!c || *c == 0)
return false;
- while (*c) {
- if (uc == e || *uc != *c)
+ const ushort *uc = d->data();
+ const ushort *e = uc + qMin(d->size, other.size());
+
+ while (uc < e) {
+ if (*uc != *c)
break;
++uc;
++c;
}
- return (uc == e ? *c : *uc < *c);
+ return (uc == (d->data() + d->size) ? *c : *uc < *c);
}
/*! \fn bool QString::operator<(const QByteArray &other) const
*/
bool QString::operator>(const QLatin1String &other) const
{
- const ushort *uc = d->data;;
- const ushort *e = uc + d->size;
const uchar *c = (uchar *) other.latin1();
-
if (!c || *c == '\0')
return !isEmpty();
- while (*c) {
- if (uc == e || *uc != *c)
+ const ushort *uc = d->data();;
+ const ushort *e = uc + qMin(d->size, other.size());
+
+ while (uc < e) {
+ if (*uc != *c)
break;
++uc;
++c;
}
- return (uc == e ? false : *uc > *c);
+ return (uc == (d->data() + d->size) ? false : *uc > *c);
}
/*! \fn bool QString::operator>(const QByteArray &other) const
{
const int sl = str.d->size;
if (sl == 1)
- return lastIndexOf(QChar(str.d->data[0]), from, cs);
+ return lastIndexOf(QChar(str.d->data()[0]), from, cs);
const int l = d->size;
if (from < 0)
if (from > delta)
from = delta;
- return lastIndexOfHelper(d->data, from, str.d->data, str.d->size, cs);
+ return lastIndexOfHelper(d->data(), from, str.d->data(), str.d->size, cs);
}
/*!
*/
int QString::lastIndexOf(const QLatin1String &str, int from, Qt::CaseSensitivity cs) const
{
- const int sl = qstrlen(str.latin1());
+ const int sl = str.size();
if (sl == 1)
return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs);
for (int i = 0; i < sl; ++i)
s[i] = str.latin1()[i];
- return lastIndexOfHelper(d->data, from, s.data(), sl, cs);
+ return lastIndexOfHelper(d->data(), from, s.data(), sl, cs);
}
/*!
if (from > delta)
from = delta;
- return lastIndexOfHelper(d->data, from, reinterpret_cast<const ushort*>(str.unicode()),
+ return lastIndexOfHelper(d->data(), from, reinterpret_cast<const ushort*>(str.unicode()),
str.size(), cs);
}
while (i < pos) {
int copyend = replacements[i].pos;
int size = copyend - copystart;
- memcpy(uc, d->data + copystart, size * sizeof(QChar));
+ memcpy(uc, d->data() + copystart, size * sizeof(QChar));
uc += size;
- memcpy(uc, after.d->data, al * sizeof(QChar));
+ memcpy(uc, after.d->data(), al * sizeof(QChar));
uc += al;
copystart = copyend + replacements[i].length;
i++;
}
- memcpy(uc, d->data + copystart, (d->size - copystart) * sizeof(QChar));
+ memcpy(uc, d->data() + copystart, (d->size - copystart) * sizeof(QChar));
newstring.resize(newlen);
*this = newstring;
caretMode = QRegExp::CaretWontMatch;
{
if (n >= d->size || n < 0)
return *this;
- return QString((const QChar*) d->data, n);
+ return QString((const QChar*) d->data(), n);
}
/*!
{
if (n >= d->size || n < 0)
return *this;
- return QString((const QChar*) d->data + d->size - n, n);
+ return QString((const QChar*) d->data() + d->size - n, n);
}
/*!
QString QString::mid(int position, int n) const
{
- if (d == &shared_null || position >= d->size)
+ if (d == &shared_null.str || position >= d->size)
return QString();
if (n < 0)
n = d->size - position;
n = d->size - position;
if (position == 0 && n == d->size)
return *this;
- return QString((const QChar*) d->data + position, n);
+ return QString((const QChar*) d->data() + position, n);
}
/*!
{
return d->size
&& (cs == Qt::CaseSensitive
- ? d->data[0] == c
- : foldCase(d->data[0]) == foldCase(c.unicode()));
+ ? d->data()[0] == c
+ : foldCase(d->data()[0]) == foldCase(c.unicode()));
}
/*!
{
return d->size
&& (cs == Qt::CaseSensitive
- ? d->data[d->size - 1] == c
- : foldCase(d->data[d->size - 1]) == foldCase(c.unicode()));
+ ? d->data()[d->size - 1] == c
+ : foldCase(d->data()[d->size - 1]) == foldCase(c.unicode()));
}
/*! \fn const char *QString::ascii() const
return toLatin1_helper(unicode(), length());
}
-// ### Qt 5: Change the return type of at least toAscii(),
-// toLatin1() and unicode() such that the use of Q_COMPILER_MANGLES_RETURN_TYPE
-// isn't necessary in the header. See task 177402.
-
/*!
Returns an 8-bit representation of the string as a QByteArray.
{
Data *d;
if (!str) {
- d = &shared_null;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_null.str);
} else if (size == 0 || (!*str && size < 0)) {
- d = &shared_empty;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_empty.str);
} else {
if (size < 0)
size = qstrlen(str);
- d = static_cast<Data *>(qMalloc(sizeof(Data) + size * sizeof(QChar)));
+ d = static_cast<Data *>(qMalloc(sizeof(Data) + (size+1) * sizeof(QChar)));
Q_CHECK_PTR(d);
- d->ref = 1;
- d->alloc = d->size = size;
- d->clean = d->simpletext = d->righttoleft = d->capacity = 0;
- d->data = d->array;
- d->array[size] = '\0';
- ushort *dst = d->data;
+ *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } };
+ d->data()[size] = '\0';
+ ushort *dst = d->data();
/* SIMD:
* Unpacking with SSE has been shown to improve performance on recent CPUs
* The same method gives no improvement with NEON.
if (codecForCStrings) {
Data *d;
if (!str) {
- d = &shared_null;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_null.str);
} else if (size == 0 || (!*str && size < 0)) {
- d = &shared_empty;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_empty.str);
} else {
if (size < 0)
size = qstrlen(str);
if (!str)
return QString();
if (size == 0 || (!*str && size < 0))
- return QLatin1String("");
+ return QString(shared_empty);
#if !defined(QT_NO_TEXTCODEC)
if (size < 0)
size = qstrlen(str);
{
resize(size);
if (unicode && size)
- memcpy(d->data, unicode, size * sizeof(QChar));
+ memcpy(d->data(), unicode, size * sizeof(QChar));
return *this;
}
if (d->size == 0)
return *this;
- const QChar * const start = reinterpret_cast<QChar *>(d->data);
+ const QChar * const start = reinterpret_cast<QChar *>(d->data());
const QChar *from = start;
const QChar *fromEnd = start + d->size;
forever {
break;
if (++from == fromEnd) {
// All-whitespace string
- shared_empty.ref.ref();
- return QString(&shared_empty, 0);
+ return QString(shared_empty);
}
}
// This loop needs no underflow check, as we already determined that
// of already simplified characters - at least one, obviously -
// without a trailing space.
QString result((fromEnd - from) + copyCount, Qt::Uninitialized);
- QChar *to = reinterpret_cast<QChar *>(result.d->data);
+ QChar *to = reinterpret_cast<QChar *>(result.d->data());
::memcpy(to, copyFrom, copyCount * 2);
to += copyCount;
fromEnd--;
}
done:
*to++ = ch;
- result.truncate(to - reinterpret_cast<QChar *>(result.d->data));
+ result.truncate(to - reinterpret_cast<QChar *>(result.d->data()));
return result;
}
{
if (d->size == 0)
return *this;
- const QChar *s = (const QChar*)d->data;
+ const QChar *s = (const QChar*)d->data();
if (!s->isSpace() && !s[d->size-1].isSpace())
return *this;
int start = 0;
}
int l = end - start + 1;
if (l <= 0) {
- shared_empty.ref.ref();
- return QString(&shared_empty, 0);
+ return QString(shared_empty);
}
return QString(s + start, l);
}
{
resize(size < 0 ? d->size : size);
if (d->size) {
- QChar *i = (QChar*)d->data + d->size;
- QChar *b = (QChar*)d->data;
+ QChar *i = (QChar*)d->data() + d->size;
+ QChar *b = (QChar*)d->data();
while (i != b)
*--i = ch;
}
{
if (cs == Qt::CaseSensitive)
return ucstrcmp(constData(), length(), other.constData(), other.length());
- return ucstricmp(d->data, d->data + d->size, other.d->data, other.d->data + other.d->size);
+ return ucstricmp(d->data(), d->data() + d->size, other.d->data(), other.d->data() + other.d->size);
}
/*!
const ushort *QString::utf16() const
{
- if (d->data != d->array) {
- QString *that = const_cast<QString*>(this);
- that->realloc(); // ensure '\\0'-termination for ::fromRawData strings
- return that->d->data;
- }
- return d->array;
+ if (d->offset)
+ const_cast<QString*>(this)->realloc(); // ensure '\\0'-termination for ::fromRawData strings
+ return d->data();
}
/*!
if (padlen > 0) {
result.resize(len+padlen);
if (len)
- memcpy(result.d->data, d->data, sizeof(QChar)*len);
- QChar *uc = (QChar*)result.d->data + len;
+ memcpy(result.d->data(), d->data(), sizeof(QChar)*len);
+ QChar *uc = (QChar*)result.d->data() + len;
while (padlen--)
* uc++ = fill;
} else {
int padlen = width - len;
if (padlen > 0) {
result.resize(len+padlen);
- QChar *uc = (QChar*)result.d->data;
+ QChar *uc = (QChar*)result.d->data();
while (padlen--)
* uc++ = fill;
if (len)
- memcpy(uc, d->data, sizeof(QChar)*len);
+ memcpy(uc, d->data(), sizeof(QChar)*len);
} else {
if (truncate)
result = left(width);
QString QString::toLower() const
{
- const ushort *p = d->data;
+ const ushort *p = d->data();
if (!p)
return *this;
if (!d->size)
}
#endif
- const ushort *e = d->data + d->size;
+ const ushort *e = d->data() + d->size;
// this avoids one out of bounds check in the loop
if (QChar(*p).isLowSurrogate())
const QUnicodeTables::Properties *prop = qGetProp(c);
if (prop->lowerCaseDiff || prop->lowerCaseSpecial) {
QString s(d->size, Qt::Uninitialized);
- memcpy(s.d->data, d->data, (p - d->data)*sizeof(ushort));
- ushort *pp = s.d->data + (p - d->data);
+ memcpy(s.d->data(), d->data(), (p - d->data())*sizeof(ushort));
+ ushort *pp = s.d->data() + (p - d->data());
while (p < e) {
uint c = *p;
if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate())
c = QChar::surrogateToUcs4(*(p - 1), c);
prop = qGetProp(c);
if (prop->lowerCaseSpecial) {
- int pos = pp - s.d->data;
+ int pos = pp - s.d->data();
s.resize(s.d->size + SPECIAL_CASE_MAX_LEN);
- pp = s.d->data + pos;
+ pp = s.d->data() + pos;
const ushort *specialCase = specialCaseMap + prop->lowerCaseDiff;
while (*specialCase)
*pp++ = *specialCase++;
}
++p;
}
- s.truncate(pp - s.d->data);
+ s.truncate(pp - s.d->data());
return s;
}
++p;
if (!d->size)
return *this;
- const ushort *p = d->data;
+ const ushort *p = d->data();
if (!p)
return *this;
- const ushort *e = d->data + d->size;
+ const ushort *e = d->data() + d->size;
uint last = 0;
while (p < e) {
if (folded != *p) {
QString s(*this);
s.detach();
- ushort *pp = s.d->data + (p - d->data);
- const ushort *ppe = s.d->data + s.d->size;
- last = pp > s.d->data ? *(pp - 1) : 0;
+ ushort *pp = s.d->data() + (p - d->data());
+ const ushort *ppe = s.d->data() + s.d->size;
+ last = pp > s.d->data() ? *(pp - 1) : 0;
while (pp < ppe) {
*pp = foldCase(*pp, last);
++pp;
QString QString::toUpper() const
{
- const ushort *p = d->data;
+ const ushort *p = d->data();
if (!p)
return *this;
if (!d->size)
}
#endif
- const ushort *e = d->data + d->size;
+ const ushort *e = d->data() + d->size;
// this avoids one out of bounds check in the loop
if (QChar(*p).isLowSurrogate())
const QUnicodeTables::Properties *prop = qGetProp(c);
if (prop->upperCaseDiff || prop->upperCaseSpecial) {
QString s(d->size, Qt::Uninitialized);
- memcpy(s.d->data, d->data, (p - d->data)*sizeof(ushort));
- ushort *pp = s.d->data + (p - d->data);
+ memcpy(s.d->data(), d->data(), (p - d->data())*sizeof(ushort));
+ ushort *pp = s.d->data() + (p - d->data());
while (p < e) {
uint c = *p;
if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate())
c = QChar::surrogateToUcs4(*(p - 1), c);
prop = qGetProp(c);
if (prop->upperCaseSpecial) {
- int pos = pp - s.d->data;
+ int pos = pp - s.d->data();
s.resize(s.d->size + SPECIAL_CASE_MAX_LEN);
- pp = s.d->data + pos;
+ pp = s.d->data() + pos;
const ushort *specialCase = specialCaseMap + prop->upperCaseDiff;
while (*specialCase)
*pp++ = *specialCase++;
}
++p;
}
- s.truncate(pp - s.d->data);
+ s.truncate(pp - s.d->data());
return s;
}
++p;
if (result.d->alloc != resultSize)
return QString(); // not enough memory
- memcpy(result.d->data, d->data, d->size * sizeof(ushort));
+ memcpy(result.d->data(), d->data(), d->size * sizeof(ushort));
int sizeSoFar = d->size;
- ushort *end = result.d->data + sizeSoFar;
+ ushort *end = result.d->data() + sizeSoFar;
const int halfResultSize = resultSize >> 1;
while (sizeSoFar <= halfResultSize) {
- memcpy(end, result.d->data, sizeSoFar * sizeof(ushort));
+ memcpy(end, result.d->data(), sizeSoFar * sizeof(ushort));
end += sizeSoFar;
sizeSoFar <<= 1;
}
- memcpy(end, result.d->data, (resultSize - sizeSoFar) * sizeof(ushort));
- result.d->data[resultSize] = '\0';
+ memcpy(end, result.d->data(), (resultSize - sizeSoFar) * sizeof(ushort));
+ result.d->data()[resultSize] = '\0';
result.d->size = resultSize;
return result;
}
{
QString result;
QMap<int, int> numbersUsed;
- const QChar *uc = (const QChar *) d->data;
+ const QChar *uc = (const QChar *) d->data();
const int len = d->size;
const int end = len - 1;
int lastNumber = -1;
return result;
}
-static bool isStringRightToLeft(const ushort *p, const ushort *end)
-{
- bool righttoleft = false;
- while (p < end) {
- switch(QChar::direction(*p))
- {
- case QChar::DirL:
- goto end;
- case QChar::DirR:
- case QChar::DirAL:
- righttoleft = true;
- goto end;
- default:
- break;
- }
- ++p;
- }
- end:
- return righttoleft;
-}
-/*! \internal
- */
-void QString::updateProperties() const
+/*! \fn bool QString::isSimpleText() const
+
+ \internal
+*/
+bool QString::isSimpleText() const
{
- ushort *p = d->data;
- ushort *end = p + d->size;
- d->simpletext = true;
+ const ushort *p = d->data();
+ const ushort * const end = p + d->size;
while (p < end) {
ushort uc = *p;
// sort out regions of complex text formatting
if (uc > 0x058f && (uc < 0x1100 || uc > 0xfb0f)) {
- d->simpletext = false;
+ return false;
}
p++;
}
- d->righttoleft = isStringRightToLeft(d->data, d->data + d->size);
- d->clean = true;
-}
-
-bool QString::isRightToLeft() const
-{
- return isStringRightToLeft(d->data, d->data + d->size);
+ return true;
}
-/*! \fn bool QString::isSimpleText() const
-
- \internal
-*/
-
/*! \fn bool QString::isRightToLeft() const
Returns true if the string is read right to left.
*/
-
+bool QString::isRightToLeft() const
+{
+ const ushort *p = d->data();
+ const ushort * const end = p + d->size;
+ while (p < end) {
+ switch(QChar::direction(*p))
+ {
+ case QChar::DirL:
+ return false;
+ case QChar::DirR:
+ case QChar::DirAL:
+ return true;
+ default:
+ break;
+ }
+ ++p;
+ }
+ return false;
+}
/*! \fn QChar *QString::data()
QString QString::fromRawData(const QChar *unicode, int size)
{
Data *x = static_cast<Data *>(qMalloc(sizeof(Data)));
+ *x = (Data){ Q_REFCOUNT_INITIALIZER(1), size, 0, false, { 0 } };
Q_CHECK_PTR(x);
if (unicode) {
- x->data = (ushort *)unicode;
+ x->offset = (const ushort *)unicode - (x->d + sizeof(qptrdiff)/sizeof(ushort));
} else {
- x->data = x->array;
size = 0;
}
- x->ref = 1;
- x->alloc = x->size = size;
- *x->array = '\0';
- x->clean = x->simpletext = x->righttoleft = x->capacity = 0;
return QString(x, 0);
}
*/
QString &QString::setRawData(const QChar *unicode, int size)
{
- if (d->ref != 1 || (d->data == d->array && d->alloc)) {
+ if (d->ref != 1 || d->alloc) {
*this = fromRawData(unicode, size);
} else {
if (unicode) {
- d->data = (ushort *)unicode;
+ d->size = size;
+ d->offset = (const ushort *)unicode - (d->d + sizeof(qptrdiff)/sizeof(ushort));
} else {
- d->data = d->array;
- size = 0;
+ d->offset = 0;
+ d->size = 0;
}
- d->alloc = d->size = size;
- *d->array = '\0';
- d->clean = d->simpletext = d->righttoleft = d->capacity = 0;
}
return *this;
}
\snippet doc/src/snippets/code/src_corelib_tools_qstring.cpp 6
- \sa QString, QLatin1Char
+ \sa QString, QLatin1Char, QStringLiteral
*/
/*! \fn QLatin1String::QLatin1String(const char *str)
}
}
} else {
- str = QLatin1String("");
+ str = QString(QLatin1String(""));
}
}
return in;
QStringRef QString::midRef(int position, int n) const
{
- if (d == &shared_null || position >= d->size)
+ if (d == &shared_null.str || position >= d->size)
return QStringRef();
if (n < 0)
n = d->size - position;
*/
int QStringRef::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const
{
- const int sl = qstrlen(str.latin1());
+ const int sl = str.size();
if (sl == 1)
return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs);
int from, Qt::CaseSensitivity cs)
{
const char *latin1 = needle.latin1();
- int len = qstrlen(latin1);
+ int len = needle.size();
QVarLengthArray<ushort> s(len);
for (int i = 0; i < len; ++i)
s[i] = latin1[i];
return !needle.latin1();
if (haystackLen == 0)
return !needle.latin1() || *needle.latin1() == 0;
- const int slen = qstrlen(needle.latin1());
+ const int slen = needle.size();
if (slen > haystackLen)
return false;
const ushort *data = reinterpret_cast<const ushort*>(haystack);
return !needle.latin1();
if (haystackLen == 0)
return !needle.latin1() || *needle.latin1() == 0;
- const int slen = qstrlen(needle.latin1());
+ const int slen = needle.size();
int pos = haystackLen - slen;
if (pos < 0)
return false;
return v;
}
+/*!
+ \macro QStringLiteral(str)
+ \relates QString
+
+ The macro generates the data for a QString out of \a str at compile time if the compiler supports it.
+ Creating a QString from it is free in this case, and the generated string data is stored in
+ the read-only segment of the compiled object file.
+
+ Using QStringLiteral instead of a double quoted ascii literal can significantly speed up creation
+ of QString's from data known at compile time.
+
+ If the compiler is c++0x enabled the string \a str can actually contain unicode data.
+
+ For compilers not supporting the creation of compile time strings, QStringLiteral will fall back to
+ QLatin1String.
+*/
+
QT_END_NAMESPACE
#include <QtCore/qchar.h>
#include <QtCore/qbytearray.h>
-#include <QtCore/qatomic.h>
+#include <QtCore/qrefcount.h>
#include <QtCore/qnamespace.h>
#ifndef QT_NO_STL
class QStringRef;
template <typename T> class QVector;
+struct QStringData {
+ QtPrivate::RefCount ref;
+ int size;
+ uint alloc : 31;
+ uint capacityReserved : 1;
+ union {
+ qptrdiff offset; // will always work as we add/subtract from a ushort ptr
+ ushort d[sizeof(qptrdiff)/sizeof(ushort)];
+ };
+ inline ushort *data() { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; }
+ inline const ushort *data() const { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; }
+};
+
+template<int N> struct QConstStringData;
+template<int N> struct QConstStringDataPtr
+{
+ const QConstStringData<N> *ptr;
+};
+
+#if defined(Q_COMPILER_UNICODE_STRINGS)
+template<int n> struct QConstStringData
+{
+ const QStringData str;
+ const char16_t data[n];
+};
+#define QT_QSTRING_UNICODE_MARKER u""
+
+#elif defined(Q_OS_WIN) || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) || defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536)
+// wchar_t is 2 bytes
+template<int n> struct QConstStringData
+{
+ const QStringData str;
+ const wchar_t data[n];
+};
+#define QT_QSTRING_UNICODE_MARKER L""
+
+#else
+template<int n> struct QConstStringData
+{
+ const QStringData str;
+ const ushort data[n];
+};
+#endif
+
+#if defined(QT_QSTRING_UNICODE_MARKER)
+# if defined(Q_COMPILER_LAMBDA)
+# define QStringLiteral(str) ([]() { \
+ enum { Size = sizeof(QT_QSTRING_UNICODE_MARKER str)/2 }; \
+ static const QConstStringData<Size> qstring_literal = \
+ { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, QT_QSTRING_UNICODE_MARKER str }; \
+ QConstStringDataPtr<Size> holder = { &qstring_literal }; \
+ return holder; }())
+
+# elif defined(Q_CC_GNU)
+// We need to create a QStringData in the .rodata section of memory
+// and the only way to do that is to create a "static const" variable.
+// To do that, we need the __extension__ {( )} trick which only GCC supports
+
+# define QStringLiteral(str) \
+ __extension__ ({ \
+ enum { Size = sizeof(QT_QSTRING_UNICODE_MARKER str)/2 }; \
+ static const QConstStringData<Size> qstring_literal = \
+ { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, QT_QSTRING_UNICODE_MARKER str }; \
+ QConstStringDataPtr<Size> holder = { &qstring_literal }; \
+ holder; })
+# endif
+#endif
+
+#ifndef QStringLiteral
+// no lambdas, not GCC, or GCC in C++98 mode with 4-byte wchar_t
+// fallback, uses QLatin1String as next best options
+
+# define QStringLiteral(str) QLatin1String(str)
+#endif
+
class Q_CORE_EXPORT QString
{
public:
+ typedef QStringData Data;
+
inline QString();
QString(const QChar *unicode, int size); // Qt5: don't cap size < 0
explicit QString(const QChar *unicode); // Qt5: merge with the above
int capacity() const;
inline void reserve(int size);
- inline void squeeze() { if (d->size < d->alloc || d->ref != 1) realloc(); d->capacity = 0;}
+ inline void squeeze() { if (d->size < d->alloc || d->ref != 1) realloc(); d->capacityReserved = false;}
inline const QChar *unicode() const;
inline QChar *data();
inline QString &operator+=(QChar c) {
if (d->ref != 1 || d->size + 1 > d->alloc)
realloc(grow(d->size + 1));
- d->data[d->size++] = c.unicode();
- d->data[d->size] = '\0';
+ d->data()[d->size++] = c.unicode();
+ d->data()[d->size] = '\0';
return *this;
}
// compatibility
struct Null { };
static const Null null;
- inline QString(const Null &): d(&shared_null) { d->ref.ref(); }
+ inline QString(const Null &): d(const_cast<Data *>(&shared_null.str)) {}
inline QString &operator=(const Null &) { *this = QString(); return *this; }
- inline bool isNull() const { return d == &shared_null; }
+ inline bool isNull() const { return d == &shared_null.str; }
- bool isSimpleText() const { if (!d->clean) updateProperties(); return d->simpletext; }
+ bool isSimpleText() const;
bool isRightToLeft() const;
QString(int size, Qt::Initialization);
+ template <int n>
+ inline QString(const QConstStringData<n> &dd) : d(const_cast<QStringData *>(&dd.str)) {}
+ template <int N>
+ Q_DECL_CONSTEXPR inline QString(QConstStringDataPtr<N> dd) : d(const_cast<QStringData *>(&dd.ptr->str)) {}
private:
#if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED)
QString &operator=(const QByteArray &a);
#endif
- struct Data {
- QBasicAtomicInt ref;
- int alloc, size;
- ushort *data; // QT5: put that after the bit field to fill alignment gap; don't use sizeof any more then
- ushort clean : 1;
- ushort simpletext : 1;
- ushort righttoleft : 1;
- ushort capacity : 1;
- ushort reserved : 11;
- // ### Qt5: try to ensure that "array" is aligned to 16 bytes on both 32- and 64-bit
- ushort array[1];
- };
- static Data shared_null;
- static Data shared_empty;
+ static const QConstStringData<1> shared_null;
+ static const QConstStringData<1> shared_empty;
Data *d;
- QString(Data *dd, int /*dummy*/) : d(dd) {}
+ inline QString(Data *dd, int /*dummy*/) : d(dd) {}
+
#ifndef QT_NO_TEXTCODEC
static QTextCodec *codecForCStrings;
#endif
class Q_CORE_EXPORT QLatin1String
{
public:
- inline explicit QLatin1String(const char *s) : chars(s) {}
- inline QLatin1String &operator=(const QLatin1String &other)
- { chars = other.chars; return *this; }
+ inline explicit QLatin1String(const char *s) : m_size(s ? strlen(s) : 0), m_data(s) {}
- inline const char *latin1() const { return chars; }
+ inline const char *latin1() const { return m_data; }
+ inline int size() const { return m_size; }
+ inline const char *data() const { return m_data; }
inline bool operator==(const QString &s) const
{ return s == *this; }
inline QT_ASCII_CAST_WARN bool operator>=(const char *s) const
{ return QString::fromAscii(s) <= *this; }
private:
- const char *chars;
+ int m_size;
+ const char *m_data;
};
+// Qt 4.x compatibility
+typedef QLatin1String QLatin1Literal;
inline QString::QString(const QLatin1String &aLatin1) : d(fromLatin1_helper(aLatin1.latin1()))
inline int QString::length() const
{ return d->size; }
inline const QChar QString::at(int i) const
-{ Q_ASSERT(uint(i) < uint(size())); return d->data[i]; }
+{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; }
inline const QChar QString::operator[](int i) const
-{ Q_ASSERT(uint(i) < uint(size())); return d->data[i]; }
+{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; }
inline const QChar QString::operator[](uint i) const
-{ Q_ASSERT(i < uint(size())); return d->data[i]; }
+{ Q_ASSERT(i < uint(size())); return d->data()[i]; }
inline bool QString::isEmpty() const
{ return d->size == 0; }
inline const QChar *QString::unicode() const
-{ return reinterpret_cast<const QChar*>(d->data); }
+{ return reinterpret_cast<const QChar*>(d->data()); }
inline const QChar *QString::data() const
-{ return reinterpret_cast<const QChar*>(d->data); }
+{ return reinterpret_cast<const QChar*>(d->data()); }
inline QChar *QString::data()
-{ detach(); return reinterpret_cast<QChar*>(d->data); }
+{ detach(); return reinterpret_cast<QChar*>(d->data()); }
inline const QChar *QString::constData() const
-{ return reinterpret_cast<const QChar*>(d->data); }
+{ return reinterpret_cast<const QChar*>(d->data()); }
inline void QString::detach()
-{ if (d->ref != 1 || d->data != d->array) realloc(); }
+{ if (d->ref != 1 || d->offset) realloc(); }
inline bool QString::isDetached() const
{ return d->ref == 1; }
inline QString &QString::operator=(const QLatin1String &s)
// all this is not documented: We just say "like QChar" and let it be.
inline operator QChar() const
- { return i < s.d->size ? s.d->data[i] : 0; }
+ { return i < s.d->size ? s.d->data()[i] : 0; }
inline QCharRef &operator=(const QChar &c)
{ if (i >= s.d->size) s.expand(i); else s.detach();
- s.d->data[i] = c.unicode(); return *this; }
+ s.d->data()[i] = c.unicode(); return *this; }
// An operator= for each QChar cast constructors
#ifndef QT_NO_CAST_FROM_ASCII
inline void setCell(uchar cell);
inline void setRow(uchar row);
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
- const char toAscii() const { return QChar(*this).toAscii(); }
- const char toLatin1() const { return QChar(*this).toLatin1(); }
- const ushort unicode() const { return QChar(*this).unicode(); }
-#else
char toAscii() const { return QChar(*this).toAscii(); }
char toLatin1() const { return QChar(*this).toLatin1(); }
ushort unicode() const { return QChar(*this).unicode(); }
-#endif
ushort& unicode() { return s.data()[i].unicode(); }
};
inline void QCharRef::setCell(uchar acell) { QChar(*this).setCell(acell); }
-inline QString::QString() : d(&shared_null) { d->ref.ref(); }
+inline QString::QString() : d(const_cast<Data *>(&shared_null.str)) {}
inline QString::~QString() { if (!d->ref.deref()) free(d); }
-inline void QString::reserve(int asize) { if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacity = 1;}
+inline void QString::reserve(int asize) { if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacityReserved = true;}
inline QString &QString::setUtf16(const ushort *autf16, int asize)
{ return setUnicode(reinterpret_cast<const QChar *>(autf16), asize); }
inline QCharRef QString::operator[](int i)
inline QCharRef QString::operator[](uint i)
{ return QCharRef(*this, i); }
inline QString::iterator QString::begin()
-{ detach(); return reinterpret_cast<QChar*>(d->data); }
+{ detach(); return reinterpret_cast<QChar*>(d->data()); }
inline QString::const_iterator QString::begin() const
-{ return reinterpret_cast<const QChar*>(d->data); }
+{ return reinterpret_cast<const QChar*>(d->data()); }
inline QString::const_iterator QString::constBegin() const
-{ return reinterpret_cast<const QChar*>(d->data); }
+{ return reinterpret_cast<const QChar*>(d->data()); }
inline QString::iterator QString::end()
-{ detach(); return reinterpret_cast<QChar*>(d->data + d->size); }
+{ detach(); return reinterpret_cast<QChar*>(d->data() + d->size); }
inline QString::const_iterator QString::end() const
-{ return reinterpret_cast<const QChar*>(d->data + d->size); }
+{ return reinterpret_cast<const QChar*>(d->data() + d->size); }
inline QString::const_iterator QString::constEnd() const
-{ return reinterpret_cast<const QChar*>(d->data + d->size); }
+{ return reinterpret_cast<const QChar*>(d->data() + d->size); }
inline QBool QString::contains(const QString &s, Qt::CaseSensitivity cs) const
{ return QBool(indexOf(s, 0, cs) != -1); }
inline QBool QString::contains(const QStringRef &s, Qt::CaseSensitivity cs) const
inline const QChar *unicode() const {
if (!m_string)
- return reinterpret_cast<const QChar *>(QString::shared_null.data);
+ return reinterpret_cast<const QChar *>(QString::shared_null.str.data());
return m_string->unicode() + m_position;
}
inline const QChar *data() const { return unicode(); }
{ return QBool(indexOf(s, 0, cs) != -1); }
-
QT_END_NAMESPACE
QT_END_HEADER
QT_BEGIN_NAMESPACE
/*!
- \class QLatin1Literal
- \internal
- \reentrant
- \since 4.6
-
- \brief The QLatin1Literal class provides a thin wrapper around string
- literals used in source code.
-
- \ingroup tools
- \ingroup shared
- \ingroup string-processing
-
-
- Unlike \c QLatin1String, a \c QLatin1Literal can retrieve its size
- without iterating over the literal.
-
- The main use of \c QLatin1Literal is in conjunction with \c QStringBuilder
- to reduce the number of reallocations needed to build up a string from
- smaller chunks.
-
- \sa QStringBuilder, QLatin1String, QString, QStringRef
-*/
-
-/*! \fn int QLatin1Literal::size() const
-
- Returns the number of characters in the literal \e{excluding} the trailing
- NULL char.
-*/
-
-/*! \fn QLatin1Literal::QLatin1Literal(const char str)
-
- Constructs a new literal from the string \a str.
-*/
-
-/*! \fn const char *QLatin1Literal::data() const
-
- Returns a pointer to the first character of the string literal.
- The string literal is terminated by a NUL character.
-*/
-
-/*!
\class QStringBuilder
\internal
\reentrant
The QStringBuilder class is not to be used explicitly in user
code. Instances of the class are created as return values of the
operator%() function, acting on objects of type QString,
- QLatin1String, QLatin1Literal, QStringRef, QChar, QCharRef,
+ QLatin1String, QStringRef, QChar, QCharRef,
QLatin1Char, and \c char.
Concatenating strings with operator%() generally yields better
if there are three or more of them, and performs equally well in other
cases.
- \sa QLatin1Literal, QString
+ \sa QLatin1String, QString
*/
/*! \fn QStringBuilder::QStringBuilder(const A &a, const B &b)
takes a QString parameter.
This function is usable with arguments of type \c QString,
- \c QLatin1String, \c QLatin1Literal, \c QStringRef,
+ \c QLatin1String, \c QStringRef,
\c QChar, \c QCharRef, \c QLatin1Char, and \c char.
*/
/*!
\fn operator QStringBuilder::QString() const
- Converts the \c QLatin1Literal into a \c QString object.
+ Converts the \c QLatin1String into a \c QString object.
*/
/*! \internal
QT_MODULE(Core)
-// ### Qt 5: merge with QLatin1String
-class QLatin1Literal
-{
-public:
- int size() const { return m_size; }
- const char *data() const { return m_data; }
-
- template <int N>
- QLatin1Literal(const char (&str)[N])
- : m_size(N - 1), m_data(str) {}
-
-private:
- const int m_size;
- const char * const m_data;
-};
-
struct Q_CORE_EXPORT QAbstractConcatenable
{
protected:
typedef QLatin1String type;
typedef QString ConvertTo;
enum { ExactSize = true };
- static int size(const QLatin1String &a) { return qstrlen(a.latin1()); }
+ static int size(const QLatin1String &a) { return a.size(); }
static inline void appendTo(const QLatin1String &a, QChar *&out)
{
- for (const char *s = a.latin1(); *s; )
- *out++ = QLatin1Char(*s++);
- }
- static inline void appendTo(const QLatin1String &a, char *&out)
- {
- for (const char *s = a.latin1(); *s; )
- *out++ = *s++;
- }
-};
-
-template <> struct QConcatenable<QLatin1Literal>
-{
- typedef QLatin1Literal type;
- typedef QString ConvertTo;
- enum { ExactSize = true };
- static int size(const QLatin1Literal &a) { return a.size(); }
- static inline void appendTo(const QLatin1Literal &a, QChar *&out)
- {
for (const char *s = a.data(); *s; )
*out++ = QLatin1Char(*s++);
}
- static inline void appendTo(const QLatin1Literal &a, char *&out)
+ static inline void appendTo(const QLatin1String &a, char *&out)
{
for (const char *s = a.data(); *s; )
*out++ = *s++;
#endif
};
+template <int N> struct QConcatenable<QConstStringDataPtr<N> > : private QAbstractConcatenable
+{
+ typedef QConstStringDataPtr<N> type;
+ typedef QString ConvertTo;
+ enum { ExactSize = true };
+ static int size(const type &) { return N; }
+ static inline void appendTo(const type &a, QChar *&out)
+ {
+ memcpy(out, reinterpret_cast<const char*>(a.ptr->data), sizeof(QChar) * N);
+ out += N;
+ }
+#ifndef QT_NO_CAST_TO_ASCII
+ static inline QT_ASCII_CAST_WARN void appendTo(const type &a, char *&out)
+ { convertToAscii(a.ptr->data, N, out); }
+#endif
+};
+
template <> struct QConcatenable<QStringRef> : private QAbstractConcatenable
{
typedef QStringRef type;
inline QStringList(const QStringList &l) : QList<QString>(l) { }
inline QStringList(const QList<QString> &l) : QList<QString>(l) { }
#ifdef Q_COMPILER_INITIALIZER_LISTS
- inline QStringList(std::initializer_list<QString> args) : QList(args) { }
+ inline QStringList(std::initializer_list<QString> args) : QList<QString>(args) { }
#endif
inline void sort();
tools/qrect.h \
tools/qregexp.h \
tools/qringbuffer_p.h \
+ tools/qrefcount.h \
tools/qscopedpointer.h \
tools/qscopedpointer_p.h \
tools/qscopedvaluerollback.h \
tools/qcontiguouscache.cpp \
tools/qrect.cpp \
tools/qregexp.cpp \
+ tools/qrefcount.cpp \
tools/qshareddata.cpp \
tools/qsharedpointer.cpp \
tools/qsimd.cpp \
bool qdbus_loadLibDBus()
{
+#ifdef QT_BUILD_INTERNAL
+ // this is to simulate a library load failure for our autotest suite.
+ if (!qgetenv("QT_SIMULATE_DBUS_LIBFAIL").isEmpty())
+ return false;
+#endif
+
static volatile bool triedToLoadLibrary = false;
#ifndef QT_NO_THREAD
QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&qdbus_resolve_me));
if (!instance) {
qWarning("QDBusConnection: %s D-Bus connection created before QCoreApplication. Application may misbehave.",
type == SessionBus ? "session" : type == SystemBus ? "system" : "generic");
- } else {
+ } else if (QDBusConnectionPrivate::d(*this)) {
QDBusConnectionPrivate::d(*this)->moveToThread(instance->thread());
}
}
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** 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.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** 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.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
\o \inlineimage qpainter-compositiondemo.png
\o
- \bold {Composition Modes Demo}
+ \bold {Composition Modes Example}
The \l {painting/composition}{Composition Modes} example, available in
Qt's examples directory, allows you to experiment with the various
qreal x = p.x();
qreal y = p.y();
+ bool rtl = ti.flags & QTextItem::RightToLeft;
+ if (rtl)
+ x += ti.width.toReal();
+
int start = 0;
int end, i;
for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
ti2.width += ti.glyphs.effectiveAdvance(i);
}
+ if (rtl)
+ x -= ti2.width.toReal();
+
d->engine->drawTextItem(QPointF(x, y), ti2);
+ if (!rtl)
+ x += ti2.width.toReal();
+
// reset the high byte for all glyphs and advance to the next sub-string
const int hi = which << 24;
for (i = start; i < end; ++i) {
glyphs.glyphs[i] = hi | glyphs.glyphs[i];
}
- x += ti2.width.toReal();
// change engine
start = end;
ti2.width += ti.glyphs.effectiveAdvance(i);
}
+ if (rtl)
+ x -= ti2.width.toReal();
+
if (d->extended)
d->extended->drawTextItem(QPointF(x, y), ti2);
else
Key(const QString &styleString);
Key() : style(QFont::StyleNormal),
weight(QFont::Normal), stretch(0) { }
- Key(const Key &o) : styleName(o.styleName), style(o.style),
- weight(o.weight), stretch(o.stretch) { }
- QString styleName;
+ Key(const Key &o) : style(o.style), weight(o.weight), stretch(o.stretch) { }
uint style : 2;
signed int weight : 8;
signed int stretch : 12;
bool operator==(const Key & other) {
- return styleName == other.styleName && style == other.style &&
- weight == other.weight &&
- (stretch == 0 || other.stretch == 0 || stretch == other.stretch);
+ return (style == other.style && weight == other.weight &&
+ (stretch == 0 || other.stretch == 0 || stretch == other.stretch));
}
bool operator!=(const Key &other) {
return !operator==(other);
bool smoothScalable : 1;
signed int count : 30;
QtFontSize *pixelSizes;
+ QString styleName;
#ifdef Q_WS_X11
const char *weightName;
};
QtFontStyle::Key::Key(const QString &styleString)
- : styleName(styleString), style(QFont::StyleNormal), weight(QFont::Normal), stretch(0)
+ : style(QFont::StyleNormal), weight(QFont::Normal), stretch(0)
{
weight = getFontWeight(styleString);
int count;
QtFontStyle **styles;
- QtFontStyle *style(const QtFontStyle::Key &, bool = false);
+ QtFontStyle *style(const QtFontStyle::Key &, const QString & = QString(), bool = false);
};
-QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, bool create)
+QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, const QString &styleName, bool create)
{
int pos = 0;
if (count) {
+ // if styleName for searching first if possible
+ if (!styleName.isEmpty()) {
+ for (; pos < count; pos++) {
+ if (styles[pos]->styleName == styleName)
+ return styles[pos];
+ }
+ }
int low = 0;
int high = count;
pos = count / 2;
}
QtFontStyle *style = new QtFontStyle(key);
+ style->styleName = styleName;
memmove(styles + pos + 1, styles + pos, (count-pos)*sizeof(QtFontStyle *));
styles[pos] = style;
count++;
}
QtFontFoundry *foundry = f->foundry(QString::fromLatin1(foundryname), true);
- QtFontStyle *style = foundry->style(styleKey, true);
+ QtFontStyle *style = foundry->style(styleKey, QString(), true);
style->smoothScalable = (pixelSize == 0);
style->antialiased = antialiased;
QtFontSize *size = style->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true);
}
#endif
-static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey)
+static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey,
+ const QString &styleName = QString())
{
int best = 0;
int dist = 0xffff;
for ( int i = 0; i < foundry->count; i++ ) {
QtFontStyle *style = foundry->styles[i];
- if (!styleKey.styleName.isEmpty() && styleKey.styleName == style->key.styleName) {
+ if (!styleName.isEmpty() && styleName == style->styleName) {
dist = 0;
best = i;
break;
for (int k = 0; k < foundry->count; k++) {
QtFontStyle::Key ke(foundry->styles[k]->key);
ke.stretch = 0;
- allStyles.style(ke, true);
+ allStyles.style(ke, foundry->styles[k]->styleName, true);
}
}
}
for (int i = 0; i < allStyles.count; i++) {
- l.append(allStyles.styles[i]->key.styleName.isEmpty() ?
+ l.append(allStyles.styles[i]->styleName.isEmpty() ?
styleStringHelper(allStyles.styles[i]->key.weight,
(QFont::Style)allStyles.styles[i]->key.style) :
- allStyles.styles[i]->key.styleName);
+ allStyles.styles[i]->styleName);
}
return l;
}
QtFontFoundry *foundry = f->foundries[j];
if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
for (int k = 0; k < foundry->count; k++)
- if ((style.isEmpty() || foundry->styles[k]->key == styleKey)
+ if ((style.isEmpty() ||
+ foundry->styles[k]->styleName == style ||
+ foundry->styles[k]->key == styleKey)
&& foundry->styles[k]->bitmapScalable && !foundry->styles[k]->smoothScalable) {
bitmapScalable = true;
goto end;
QtFontFoundry *foundry = f->foundries[j];
if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
for (int k = 0; k < foundry->count; k++)
- if ((style.isEmpty() || foundry->styles[k]->key == styleKey) && foundry->styles[k]->smoothScalable) {
+ if ((style.isEmpty() ||
+ foundry->styles[k]->styleName == style ||
+ foundry->styles[k]->key == styleKey) && foundry->styles[k]->smoothScalable) {
smoothScalable = true;
goto end;
}
\sa smoothSizes(), standardSizes()
*/
QList<int> QFontDatabase::pointSizes(const QString &family,
- const QString &style)
+ const QString &styleName)
{
#if defined(Q_WS_WIN)
// windows and macosx are always smoothly scalable
Q_UNUSED(family);
- Q_UNUSED(style);
+ Q_UNUSED(styleName);
return standardSizes();
#else
bool smoothScalable = false;
QT_PREPEND_NAMESPACE(load)(familyName);
- QtFontStyle::Key styleKey(style);
+ QtFontStyle::Key styleKey(styleName);
QList<int> sizes;
for (int j = 0; j < fam->count; j++) {
QtFontFoundry *foundry = fam->foundries[j];
if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
- QtFontStyle *style = foundry->style(styleKey);
+ QtFontStyle *style = foundry->style(styleKey, styleName);
if (!style) continue;
if (style->smoothScalable) {
QtFontFoundry *foundry = f->foundries[j];
if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
for (int k = 0; k < foundry->count; k++)
- allStyles.style(foundry->styles[k]->key, true);
+ allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
}
}
QtFontStyle::Key styleKey(style);
- QtFontStyle *s = bestStyle(&allStyles, styleKey);
+ QtFontStyle *s = bestStyle(&allStyles, styleKey, style);
if (!s) // no styles found?
return QGuiApplication::font();
- if (s->key.styleName.isEmpty()) {
- QFont fnt(family, pointSize, s->key.weight);
- fnt.setStyle((QFont::Style)s->key.style);
- return fnt;
- } else {
- // found a perfect match
- QFont fnt(family, pointSize);
- fnt.setStyleName(s->key.styleName);
- return fnt;
- }
+
+ QFont fnt(family, pointSize, s->key.weight);
+ fnt.setStyle((QFont::Style)s->key.style);
+ if (!s->styleName.isEmpty())
+ fnt.setStyleName(s->styleName);
+ return fnt;
}
\sa pointSizes(), standardSizes()
*/
QList<int> QFontDatabase::smoothSizes(const QString &family,
- const QString &style)
+ const QString &styleName)
{
#ifdef Q_WS_WIN
Q_UNUSED(family);
- Q_UNUSED(style);
+ Q_UNUSED(styleName);
return QFontDatabase::standardSizes();
#else
bool smoothScalable = false;
QT_PREPEND_NAMESPACE(load)(familyName);
- QtFontStyle::Key styleKey(style);
+ QtFontStyle::Key styleKey(styleName);
QList<int> sizes;
for (int j = 0; j < fam->count; j++) {
QtFontFoundry *foundry = fam->foundries[j];
if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
- QtFontStyle *style = foundry->style(styleKey);
+ QtFontStyle *style = foundry->style(styleKey, styleName);
if (!style) continue;
if (style->smoothScalable) {
QtFontFoundry *foundry = f->foundries[j];
if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
for (int k = 0; k < foundry->count; k++)
- allStyles.style(foundry->styles[k]->key, true);
+ allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
}
}
QtFontStyle::Key styleKey(style);
- QtFontStyle *s = allStyles.style(styleKey);
+ QtFontStyle *s = allStyles.style(styleKey, style);
return s && s->key.style == QFont::StyleItalic;
}
if (foundryName.isEmpty() ||
foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
for (int k = 0; k < foundry->count; k++)
- allStyles.style(foundry->styles[k]->key, true);
+ allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
}
}
QtFontStyle::Key styleKey(style);
- QtFontStyle *s = allStyles.style(styleKey);
+ QtFontStyle *s = allStyles.style(styleKey, style);
return s && s->key.weight >= QFont::Bold;
}
if (foundryName.isEmpty() ||
foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
for (int k = 0; k < foundry->count; k++)
- allStyles.style(foundry->styles[k]->key, true);
+ allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
}
}
QtFontStyle::Key styleKey(style);
- QtFontStyle *s = allStyles.style(styleKey);
+ QtFontStyle *s = allStyles.style(styleKey, style);
return s ? s->key.weight : -1;
}
}
QtFontFoundry *foundry = f->foundry(foundryname, true);
- QtFontStyle *fontStyle = foundry->style(styleKey, true);
+ QtFontStyle *fontStyle = foundry->style(styleKey, QString(), true);
fontStyle->smoothScalable = scalable;
fontStyle->antialiased = antialiased;
QtFontSize *size = fontStyle->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true);
html += QLatin1Char('>');
if (block.begin().atEnd())
- html += "<br />";
+ html += QLatin1String("<br />");
QTextBlock::Iterator it = block.begin();
if (fragmentMarkers && !it.atEnd() && block == doc->begin())
bool isSocketWaiting() const;
bool isSocketReading() const;
- friend class QNetworkAccessHttpBackend;
-
protected slots:
void _q_receiveReply();
void _q_bytesWritten(qint64 bytes); // proceed sending
+++ /dev/null
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtNetwork module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** 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.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//#define QNETWORKACCESSHTTPBACKEND_DEBUG
-
-#include "qnetworkaccesshttpbackend_p.h"
-#include "qnetworkaccessmanager_p.h"
-#include "qnetworkaccesscache_p.h"
-#include "qabstractnetworkcache.h"
-#include "qnetworkrequest.h"
-#include "qnetworkreply.h"
-#include "QtNetwork/private/qnetworksession_p.h"
-#include "qnetworkrequest_p.h"
-#include "qnetworkcookie_p.h"
-#include "QtCore/qdatetime.h"
-#include "QtCore/qelapsedtimer.h"
-#include "QtNetwork/qsslconfiguration.h"
-#include "qhttpthreaddelegate_p.h"
-#include "qthread.h"
-
-#ifndef QT_NO_HTTP
-
-#include <string.h> // for strchr
-
-Q_DECLARE_METATYPE(QSharedPointer<char>)
-
-QT_BEGIN_NAMESPACE
-
-class QNetworkProxy;
-
-static inline bool isSeparator(register char c)
-{
- static const char separators[] = "()<>@,;:\\\"/[]?={}";
- return isLWS(c) || strchr(separators, c) != 0;
-}
-
-// ### merge with nextField in cookiejar.cpp
-static QHash<QByteArray, QByteArray> parseHttpOptionHeader(const QByteArray &header)
-{
- // The HTTP header is of the form:
- // header = #1(directives)
- // directives = token | value-directive
- // value-directive = token "=" (token | quoted-string)
- QHash<QByteArray, QByteArray> result;
-
- int pos = 0;
- while (true) {
- // skip spaces
- pos = nextNonWhitespace(header, pos);
- if (pos == header.length())
- return result; // end of parsing
-
- // pos points to a non-whitespace
- int comma = header.indexOf(',', pos);
- int equal = header.indexOf('=', pos);
- if (comma == pos || equal == pos)
- // huh? Broken header.
- return result;
-
- // The key name is delimited by either a comma, an equal sign or the end
- // of the header, whichever comes first
- int end = comma;
- if (end == -1)
- end = header.length();
- if (equal != -1 && end > equal)
- end = equal; // equal sign comes before comma/end
- QByteArray key = QByteArray(header.constData() + pos, end - pos).trimmed().toLower();
- pos = end + 1;
-
- if (uint(equal) < uint(comma)) {
- // case: token "=" (token | quoted-string)
- // skip spaces
- pos = nextNonWhitespace(header, pos);
- if (pos == header.length())
- // huh? Broken header
- return result;
-
- QByteArray value;
- value.reserve(header.length() - pos);
- if (header.at(pos) == '"') {
- // case: quoted-string
- // quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
- // qdtext = <any TEXT except <">>
- // quoted-pair = "\" CHAR
- ++pos;
- while (pos < header.length()) {
- register char c = header.at(pos);
- if (c == '"') {
- // end of quoted text
- break;
- } else if (c == '\\') {
- ++pos;
- if (pos >= header.length())
- // broken header
- return result;
- c = header.at(pos);
- }
-
- value += c;
- ++pos;
- }
- } else {
- // case: token
- while (pos < header.length()) {
- register char c = header.at(pos);
- if (isSeparator(c))
- break;
- value += c;
- ++pos;
- }
- }
-
- result.insert(key, value);
-
- // find the comma now:
- comma = header.indexOf(',', pos);
- if (comma == -1)
- return result; // end of parsing
- pos = comma + 1;
- } else {
- // case: token
- // key is already set
- result.insert(key, QByteArray());
- }
- }
-}
-
-QNetworkAccessBackend *
-QNetworkAccessHttpBackendFactory::create(QNetworkAccessManager::Operation op,
- const QNetworkRequest &request) const
-{
- // check the operation
- switch (op) {
- case QNetworkAccessManager::GetOperation:
- case QNetworkAccessManager::PostOperation:
- case QNetworkAccessManager::HeadOperation:
- case QNetworkAccessManager::PutOperation:
- case QNetworkAccessManager::DeleteOperation:
- case QNetworkAccessManager::CustomOperation:
- break;
-
- default:
- // no, we can't handle this request
- return 0;
- }
-
- QUrl url = request.url();
- QString scheme = url.scheme().toLower();
- if (scheme == QLatin1String("http") || scheme == QLatin1String("https"))
- return new QNetworkAccessHttpBackend;
-
- return 0;
-}
-
-QNetworkAccessHttpBackend::QNetworkAccessHttpBackend()
- : QNetworkAccessBackend()
- , statusCode(0)
- , pendingDownloadDataEmissions(new QAtomicInt())
- , pendingDownloadProgressEmissions(new QAtomicInt())
- , loadingFromCache(false)
- , usingZerocopyDownloadBuffer(false)
-#ifndef QT_NO_OPENSSL
- , pendingSslConfiguration(0), pendingIgnoreAllSslErrors(false)
-#endif
- , resumeOffset(0)
-{
-}
-
-QNetworkAccessHttpBackend::~QNetworkAccessHttpBackend()
-{
- // This will do nothing if the request was already finished or aborted
- emit abortHttpRequest();
-
-#ifndef QT_NO_OPENSSL
- delete pendingSslConfiguration;
-#endif
-}
-
-/*
- For a given httpRequest
- 1) If AlwaysNetwork, return
- 2) If we have a cache entry for this url populate headers so the server can return 304
- 3) Calculate if response_is_fresh and if so send the cache and set loadedFromCache to true
- */
-bool QNetworkAccessHttpBackend::loadFromCacheIfAllowed(QHttpNetworkRequest &httpRequest)
-{
- QNetworkRequest::CacheLoadControl CacheLoadControlAttribute =
- (QNetworkRequest::CacheLoadControl)request().attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt();
- if (CacheLoadControlAttribute == QNetworkRequest::AlwaysNetwork) {
- // If the request does not already specify preferred cache-control
- // force reload from the network and tell any caching proxy servers to reload too
- if (!request().rawHeaderList().contains("Cache-Control")) {
- httpRequest.setHeaderField("Cache-Control", "no-cache");
- httpRequest.setHeaderField("Pragma", "no-cache");
- }
- return false;
- }
-
- // The disk cache API does not currently support partial content retrieval.
- // That is why we don't use the disk cache for any such requests.
- if (request().hasRawHeader("Range"))
- return false;
-
- QAbstractNetworkCache *nc = networkCache();
- if (!nc)
- return false; // no local cache
-
- QNetworkCacheMetaData metaData = nc->metaData(url());
- if (!metaData.isValid())
- return false; // not in cache
-
- if (!metaData.saveToDisk())
- return false;
-
- QNetworkHeadersPrivate cacheHeaders;
- QNetworkHeadersPrivate::RawHeadersList::ConstIterator it;
- cacheHeaders.setAllRawHeaders(metaData.rawHeaders());
-
- it = cacheHeaders.findRawHeader("etag");
- if (it != cacheHeaders.rawHeaders.constEnd())
- httpRequest.setHeaderField("If-None-Match", it->second);
-
- QDateTime lastModified = metaData.lastModified();
- if (lastModified.isValid())
- httpRequest.setHeaderField("If-Modified-Since", QNetworkHeadersPrivate::toHttpDate(lastModified));
-
- it = cacheHeaders.findRawHeader("Cache-Control");
- if (it != cacheHeaders.rawHeaders.constEnd()) {
- QHash<QByteArray, QByteArray> cacheControl = parseHttpOptionHeader(it->second);
- if (cacheControl.contains("must-revalidate"))
- return false;
- }
-
- QDateTime currentDateTime = QDateTime::currentDateTime();
- QDateTime expirationDate = metaData.expirationDate();
-
-#if 0
- /*
- * age_value
- * is the value of Age: header received by the cache with
- * this response.
- * date_value
- * is the value of the origin server's Date: header
- * request_time
- * is the (local) time when the cache made the request
- * that resulted in this cached response
- * response_time
- * is the (local) time when the cache received the
- * response
- * now
- * is the current (local) time
- */
- int age_value = 0;
- it = cacheHeaders.findRawHeader("age");
- if (it != cacheHeaders.rawHeaders.constEnd())
- age_value = it->second.toInt();
-
- QDateTime dateHeader;
- int date_value = 0;
- it = cacheHeaders.findRawHeader("date");
- if (it != cacheHeaders.rawHeaders.constEnd()) {
- dateHeader = QNetworkHeadersPrivate::fromHttpDate(it->second);
- date_value = dateHeader.toTime_t();
- }
-
- int now = currentDateTime.toUTC().toTime_t();
- int request_time = now;
- int response_time = now;
-
- // Algorithm from RFC 2616 section 13.2.3
- int apparent_age = qMax(0, response_time - date_value);
- int corrected_received_age = qMax(apparent_age, age_value);
- int response_delay = response_time - request_time;
- int corrected_initial_age = corrected_received_age + response_delay;
- int resident_time = now - response_time;
- int current_age = corrected_initial_age + resident_time;
-
- // RFC 2616 13.2.4 Expiration Calculations
- if (!expirationDate.isValid()) {
- if (lastModified.isValid()) {
- int diff = currentDateTime.secsTo(lastModified);
- expirationDate = lastModified;
- expirationDate.addSecs(diff / 10);
- if (httpRequest.headerField("Warning").isEmpty()) {
- QDateTime dt;
- dt.setTime_t(current_age);
- if (dt.daysTo(currentDateTime) > 1)
- httpRequest.setHeaderField("Warning", "113");
- }
- }
- }
-
- // the cache-saving code below sets the expirationDate with date+max_age
- // if "max-age" is present, or to Expires otherwise
- int freshness_lifetime = dateHeader.secsTo(expirationDate);
- bool response_is_fresh = (freshness_lifetime > current_age);
-#else
- bool response_is_fresh = currentDateTime.secsTo(expirationDate) >= 0;
-#endif
-
- if (!response_is_fresh)
- return false;
-
-#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
- qDebug() << "response_is_fresh" << CacheLoadControlAttribute;
-#endif
- return sendCacheContents(metaData);
-}
-
-static QHttpNetworkRequest::Priority convert(const QNetworkRequest::Priority& prio)
-{
- switch (prio) {
- case QNetworkRequest::LowPriority:
- return QHttpNetworkRequest::LowPriority;
- case QNetworkRequest::HighPriority:
- return QHttpNetworkRequest::HighPriority;
- case QNetworkRequest::NormalPriority:
- default:
- return QHttpNetworkRequest::NormalPriority;
- }
-}
-
-void QNetworkAccessHttpBackend::postRequest()
-{
- QThread *thread = 0;
- if (isSynchronous()) {
- // A synchronous HTTP request uses its own thread
- thread = new QThread();
- QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
- thread->start();
- } else if (!manager->httpThread) {
- // We use the manager-global thread.
- // At some point we could switch to having multiple threads if it makes sense.
- manager->httpThread = new QThread();
- QObject::connect(manager->httpThread, SIGNAL(finished()), manager->httpThread, SLOT(deleteLater()));
- manager->httpThread->start();
-#ifndef QT_NO_NETWORKPROXY
- qRegisterMetaType<QNetworkProxy>("QNetworkProxy");
-#endif
-#ifndef QT_NO_OPENSSL
- qRegisterMetaType<QList<QSslError> >("QList<QSslError>");
- qRegisterMetaType<QSslConfiguration>("QSslConfiguration");
-#endif
- qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >("QList<QPair<QByteArray,QByteArray> >");
- qRegisterMetaType<QHttpNetworkRequest>("QHttpNetworkRequest");
- qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
- qRegisterMetaType<QSharedPointer<char> >("QSharedPointer<char>");
-
- thread = manager->httpThread;
- } else {
- // Asynchronous request, thread already exists
- thread = manager->httpThread;
- }
-
- QUrl url = request().url();
- httpRequest.setUrl(url);
-
- bool ssl = url.scheme().toLower() == QLatin1String("https");
- setAttribute(QNetworkRequest::ConnectionEncryptedAttribute, ssl);
- httpRequest.setSsl(ssl);
-
-
-#ifndef QT_NO_NETWORKPROXY
- QNetworkProxy transparentProxy, cacheProxy;
-
- foreach (const QNetworkProxy &p, proxyList()) {
- // use the first proxy that works
- // for non-encrypted connections, any transparent or HTTP proxy
- // for encrypted, only transparent proxies
- if (!ssl
- && (p.capabilities() & QNetworkProxy::CachingCapability)
- && (p.type() == QNetworkProxy::HttpProxy ||
- p.type() == QNetworkProxy::HttpCachingProxy)) {
- cacheProxy = p;
- transparentProxy = QNetworkProxy::NoProxy;
- break;
- }
- if (p.isTransparentProxy()) {
- transparentProxy = p;
- cacheProxy = QNetworkProxy::NoProxy;
- break;
- }
- }
-
- // check if at least one of the proxies
- if (transparentProxy.type() == QNetworkProxy::DefaultProxy &&
- cacheProxy.type() == QNetworkProxy::DefaultProxy) {
- // unsuitable proxies
- QMetaObject::invokeMethod(this, "error", isSynchronous() ? Qt::DirectConnection : Qt::QueuedConnection,
- Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProxyNotFoundError),
- Q_ARG(QString, tr("No suitable proxy found")));
- QMetaObject::invokeMethod(this, "finished", isSynchronous() ? Qt::DirectConnection : Qt::QueuedConnection);
- return;
- }
-#endif
-
-
- bool loadedFromCache = false;
- httpRequest.setPriority(convert(request().priority()));
-
- switch (operation()) {
- case QNetworkAccessManager::GetOperation:
- httpRequest.setOperation(QHttpNetworkRequest::Get);
- loadedFromCache = loadFromCacheIfAllowed(httpRequest);
- break;
-
- case QNetworkAccessManager::HeadOperation:
- httpRequest.setOperation(QHttpNetworkRequest::Head);
- loadedFromCache = loadFromCacheIfAllowed(httpRequest);
- break;
-
- case QNetworkAccessManager::PostOperation:
- invalidateCache();
- httpRequest.setOperation(QHttpNetworkRequest::Post);
- createUploadByteDevice();
- break;
-
- case QNetworkAccessManager::PutOperation:
- invalidateCache();
- httpRequest.setOperation(QHttpNetworkRequest::Put);
- createUploadByteDevice();
- break;
-
- case QNetworkAccessManager::DeleteOperation:
- invalidateCache();
- httpRequest.setOperation(QHttpNetworkRequest::Delete);
- break;
-
- case QNetworkAccessManager::CustomOperation:
- invalidateCache(); // for safety reasons, we don't know what the operation does
- httpRequest.setOperation(QHttpNetworkRequest::Custom);
- createUploadByteDevice();
- httpRequest.setCustomVerb(request().attribute(
- QNetworkRequest::CustomVerbAttribute).toByteArray());
- break;
-
- default:
- break; // can't happen
- }
-
- if (loadedFromCache) {
- // commented this out since it will be called later anyway
- // by copyFinished()
- //QNetworkAccessBackend::finished();
- return; // no need to send the request! :)
- }
-
- QList<QByteArray> headers = request().rawHeaderList();
- if (resumeOffset != 0) {
- if (headers.contains("Range")) {
- // Need to adjust resume offset for user specified range
-
- headers.removeOne("Range");
-
- // We've already verified that requestRange starts with "bytes=", see canResume.
- QByteArray requestRange = request().rawHeader("Range").mid(6);
-
- int index = requestRange.indexOf('-');
-
- quint64 requestStartOffset = requestRange.left(index).toULongLong();
- quint64 requestEndOffset = requestRange.mid(index + 1).toULongLong();
-
- requestRange = "bytes=" + QByteArray::number(resumeOffset + requestStartOffset) +
- '-' + QByteArray::number(requestEndOffset);
-
- httpRequest.setHeaderField("Range", requestRange);
- } else {
- httpRequest.setHeaderField("Range", "bytes=" + QByteArray::number(resumeOffset) + '-');
- }
- }
-
- foreach (const QByteArray &header, headers)
- httpRequest.setHeaderField(header, request().rawHeader(header));
-
- if (request().attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool() == true)
- httpRequest.setPipeliningAllowed(true);
-
- if (static_cast<QNetworkRequest::LoadControl>
- (request().attribute(QNetworkRequest::AuthenticationReuseAttribute,
- QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Manual)
- httpRequest.setWithCredentials(false);
-
-
- // Create the HTTP thread delegate
- QHttpThreadDelegate *delegate = new QHttpThreadDelegate;
-#ifndef Q_NO_BEARERMANAGEMENT
- QVariant v(property("_q_networksession"));
- if (v.isValid())
- delegate->networkSession = qvariant_cast<QSharedPointer<QNetworkSession> >(v);
-#endif
-
- // For the synchronous HTTP, this is the normal way the delegate gets deleted
- // For the asynchronous HTTP this is a safety measure, the delegate deletes itself when HTTP is finished
- connect(thread, SIGNAL(finished()), delegate, SLOT(deleteLater()));
-
- // Set the properties it needs
- delegate->httpRequest = httpRequest;
-#ifndef QT_NO_NETWORKPROXY
- delegate->cacheProxy = cacheProxy;
- delegate->transparentProxy = transparentProxy;
-#endif
- delegate->ssl = ssl;
-#ifndef QT_NO_OPENSSL
- if (ssl)
- delegate->incomingSslConfiguration = request().sslConfiguration();
-#endif
-
- // Do we use synchronous HTTP?
- delegate->synchronous = isSynchronous();
-
- // The authentication manager is used to avoid the BlockingQueuedConnection communication
- // from HTTP thread to user thread in some cases.
- delegate->authenticationManager = manager->authenticationManager;
-
- if (!isSynchronous()) {
- // Tell our zerocopy policy to the delegate
- delegate->downloadBufferMaximumSize =
- request().attribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute).toLongLong();
-
- // These atomic integers are used for signal compression
- delegate->pendingDownloadData = pendingDownloadDataEmissions;
- delegate->pendingDownloadProgress = pendingDownloadProgressEmissions;
-
- // Connect the signals of the delegate to us
- connect(delegate, SIGNAL(downloadData(QByteArray)),
- this, SLOT(replyDownloadData(QByteArray)),
- Qt::QueuedConnection);
- connect(delegate, SIGNAL(downloadFinished()),
- this, SLOT(replyFinished()),
- Qt::QueuedConnection);
- connect(delegate, SIGNAL(downloadMetaData(QList<QPair<QByteArray,QByteArray> >,int,QString,bool,QSharedPointer<char>,qint64)),
- this, SLOT(replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >,int,QString,bool,QSharedPointer<char>,qint64)),
- Qt::QueuedConnection);
- connect(delegate, SIGNAL(downloadProgress(qint64,qint64)),
- this, SLOT(replyDownloadProgressSlot(qint64,qint64)),
- Qt::QueuedConnection);
- connect(delegate, SIGNAL(error(QNetworkReply::NetworkError,QString)),
- this, SLOT(httpError(QNetworkReply::NetworkError, const QString)),
- Qt::QueuedConnection);
-#ifndef QT_NO_OPENSSL
- connect(delegate, SIGNAL(sslConfigurationChanged(QSslConfiguration)),
- this, SLOT(replySslConfigurationChanged(QSslConfiguration)),
- Qt::QueuedConnection);
-#endif
- // Those need to report back, therefire BlockingQueuedConnection
- connect(delegate, SIGNAL(authenticationRequired(QHttpNetworkRequest,QAuthenticator*)),
- this, SLOT(httpAuthenticationRequired(QHttpNetworkRequest,QAuthenticator*)),
- Qt::BlockingQueuedConnection);
-#ifndef QT_NO_NETWORKPROXY
- connect (delegate, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
- this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
- Qt::BlockingQueuedConnection);
-#endif
-#ifndef QT_NO_OPENSSL
- connect(delegate, SIGNAL(sslErrors(QList<QSslError>,bool*,QList<QSslError>*)),
- this, SLOT(replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *)),
- Qt::BlockingQueuedConnection);
-#endif
- // This signal we will use to start the request.
- connect(this, SIGNAL(startHttpRequest()), delegate, SLOT(startRequest()));
- connect(this, SIGNAL(abortHttpRequest()), delegate, SLOT(abortRequest()));
-
- if (uploadByteDevice) {
- QNonContiguousByteDeviceThreadForwardImpl *forwardUploadDevice =
- new QNonContiguousByteDeviceThreadForwardImpl(uploadByteDevice->atEnd(), uploadByteDevice->size());
- if (uploadByteDevice->isResetDisabled())
- forwardUploadDevice->disableReset();
- forwardUploadDevice->setParent(delegate); // needed to make sure it is moved on moveToThread()
- delegate->httpRequest.setUploadByteDevice(forwardUploadDevice);
-
- // From main thread to user thread:
- QObject::connect(this, SIGNAL(haveUploadData(QByteArray, bool, qint64)),
- forwardUploadDevice, SLOT(haveDataSlot(QByteArray, bool, qint64)), Qt::QueuedConnection);
- QObject::connect(uploadByteDevice.data(), SIGNAL(readyRead()),
- forwardUploadDevice, SIGNAL(readyRead()),
- Qt::QueuedConnection);
-
- // From http thread to user thread:
- QObject::connect(forwardUploadDevice, SIGNAL(wantData(qint64)),
- this, SLOT(wantUploadDataSlot(qint64)));
- QObject::connect(forwardUploadDevice, SIGNAL(processedData(qint64)),
- this, SLOT(sentUploadDataSlot(qint64)));
- connect(forwardUploadDevice, SIGNAL(resetData(bool*)),
- this, SLOT(resetUploadDataSlot(bool*)),
- Qt::BlockingQueuedConnection); // this is the only one with BlockingQueued!
- }
- } else if (isSynchronous()) {
- connect(this, SIGNAL(startHttpRequestSynchronously()), delegate, SLOT(startRequestSynchronously()), Qt::BlockingQueuedConnection);
-
- if (uploadByteDevice) {
- // For the synchronous HTTP use case the use thread (this one here) is blocked
- // so we cannot use the asynchronous upload architecture.
- // We therefore won't use the QNonContiguousByteDeviceThreadForwardImpl but directly
- // use the uploadByteDevice provided to us by the QNetworkReplyImpl.
- // The code that is in QNetworkReplyImplPrivate::setup() makes sure it is safe to use from a thread
- // since it only wraps a QRingBuffer
- delegate->httpRequest.setUploadByteDevice(uploadByteDevice.data());
- }
- }
-
-
- // Move the delegate to the http thread
- delegate->moveToThread(thread);
- // This call automatically moves the uploadDevice too for the asynchronous case.
-
- // Send an signal to the delegate so it starts working in the other thread
- if (isSynchronous()) {
- emit startHttpRequestSynchronously(); // This one is BlockingQueuedConnection, so it will return when all work is done
-
- if (delegate->incomingErrorCode != QNetworkReply::NoError) {
- replyDownloadMetaData
- (delegate->incomingHeaders,
- delegate->incomingStatusCode,
- delegate->incomingReasonPhrase,
- delegate->isPipeliningUsed,
- QSharedPointer<char>(),
- delegate->incomingContentLength);
- httpError(delegate->incomingErrorCode, delegate->incomingErrorDetail);
- } else {
- replyDownloadMetaData
- (delegate->incomingHeaders,
- delegate->incomingStatusCode,
- delegate->incomingReasonPhrase,
- delegate->isPipeliningUsed,
- QSharedPointer<char>(),
- delegate->incomingContentLength);
- replyDownloadData(delegate->synchronousDownloadData);
- }
-
- // End the thread. It will delete itself from the finished() signal
- thread->quit();
-
- finished();
- } else {
- emit startHttpRequest(); // Signal to the HTTP thread and go back to user.
- }
-}
-
-void QNetworkAccessHttpBackend::invalidateCache()
-{
- QAbstractNetworkCache *nc = networkCache();
- if (nc)
- nc->remove(url());
-}
-
-void QNetworkAccessHttpBackend::open()
-{
- postRequest();
-}
-
-void QNetworkAccessHttpBackend::closeDownstreamChannel()
-{
- // FIXME Maybe we can get rid of this whole architecture part
-}
-
-void QNetworkAccessHttpBackend::downstreamReadyWrite()
-{
- // FIXME Maybe we can get rid of this whole architecture part
-}
-
-void QNetworkAccessHttpBackend::setDownstreamLimited(bool b)
-{
- Q_UNUSED(b);
- // We know that readBuffer maximum size limiting is broken since quite a while.
- // The task to fix this is QTBUG-15065
-}
-
-void QNetworkAccessHttpBackend::replyDownloadData(QByteArray d)
-{
- int pendingSignals = (int)pendingDownloadDataEmissions->fetchAndAddAcquire(-1) - 1;
-
- if (pendingSignals > 0) {
- // Some more signal emissions to this slot are pending.
- // Instead of writing the downstream data, we wait
- // and do it in the next call we get
- // (signal comppression)
- pendingDownloadData.append(d);
- return;
- }
-
- pendingDownloadData.append(d);
- d.clear();
- // We need to usa a copy for calling writeDownstreamData as we could
- // possibly recurse into this this function when we call
- // appendDownstreamDataSignalEmissions because the user might call
- // processEvents() or spin an event loop when this occur.
- QByteDataBuffer pendingDownloadDataCopy = pendingDownloadData;
- pendingDownloadData.clear();
- writeDownstreamData(pendingDownloadDataCopy);
-}
-
-void QNetworkAccessHttpBackend::replyFinished()
-{
- // We are already loading from cache, we still however
- // got this signal because it was posted already
- if (loadingFromCache)
- return;
-
- finished();
-}
-
-void QNetworkAccessHttpBackend::checkForRedirect(const int statusCode)
-{
- switch (statusCode) {
- case 301: // Moved Permanently
- case 302: // Found
- case 303: // See Other
- case 307: // Temporary Redirect
- // What do we do about the caching of the HTML note?
- // The response to a 303 MUST NOT be cached, while the response to
- // all of the others is cacheable if the headers indicate it to be
- QByteArray header = rawHeader("location");
- QUrl url = QUrl::fromEncoded(header);
- if (!url.isValid())
- url = QUrl(QLatin1String(header));
- redirectionRequested(url);
- }
-}
-
-void QNetworkAccessHttpBackend::replyDownloadMetaData
- (QList<QPair<QByteArray,QByteArray> > hm,
- int sc,QString rp,bool pu,
- QSharedPointer<char> db,
- qint64 contentLength)
-{
- statusCode = sc;
- reasonPhrase = rp;
-
- // Download buffer
- if (!db.isNull()) {
- reply->setDownloadBuffer(db, contentLength);
- usingZerocopyDownloadBuffer = true;
- } else {
- usingZerocopyDownloadBuffer = false;
- }
-
- setAttribute(QNetworkRequest::HttpPipeliningWasUsedAttribute, pu);
-
- // reconstruct the HTTP header
- QList<QPair<QByteArray, QByteArray> > headerMap = hm;
- QList<QPair<QByteArray, QByteArray> >::ConstIterator it = headerMap.constBegin(),
- end = headerMap.constEnd();
- QByteArray header;
-
- for (; it != end; ++it) {
- QByteArray value = rawHeader(it->first);
- if (!value.isEmpty()) {
- if (qstricmp(it->first.constData(), "set-cookie") == 0)
- value += '\n';
- else
- value += ", ";
- }
- value += it->second;
- setRawHeader(it->first, value);
- }
-
- setAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode);
- setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase);
-
- // is it a redirection?
- checkForRedirect(statusCode);
-
- if (statusCode >= 500 && statusCode < 600) {
- QAbstractNetworkCache *nc = networkCache();
- if (nc) {
- QNetworkCacheMetaData metaData = nc->metaData(url());
- QNetworkHeadersPrivate cacheHeaders;
- cacheHeaders.setAllRawHeaders(metaData.rawHeaders());
- QNetworkHeadersPrivate::RawHeadersList::ConstIterator it;
- it = cacheHeaders.findRawHeader("Cache-Control");
- bool mustReValidate = false;
- if (it != cacheHeaders.rawHeaders.constEnd()) {
- QHash<QByteArray, QByteArray> cacheControl = parseHttpOptionHeader(it->second);
- if (cacheControl.contains("must-revalidate"))
- mustReValidate = true;
- }
- if (!mustReValidate && sendCacheContents(metaData))
- return;
- }
- }
-
- if (statusCode == 304) {
-#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
- qDebug() << "Received a 304 from" << url();
-#endif
- QAbstractNetworkCache *nc = networkCache();
- if (nc) {
- QNetworkCacheMetaData oldMetaData = nc->metaData(url());
- QNetworkCacheMetaData metaData = fetchCacheMetaData(oldMetaData);
- if (oldMetaData != metaData)
- nc->updateMetaData(metaData);
- if (sendCacheContents(metaData))
- return;
- }
- }
-
-
- if (statusCode != 304 && statusCode != 303) {
- if (!isCachingEnabled())
- setCachingEnabled(true);
- }
-
- metaDataChanged();
-}
-
-void QNetworkAccessHttpBackend::replyDownloadProgressSlot(qint64 received, qint64 total)
-{
- // we can be sure here that there is a download buffer
-
- int pendingSignals = (int)pendingDownloadProgressEmissions->fetchAndAddAcquire(-1) - 1;
- if (pendingSignals > 0) {
- // Let's ignore this signal and look at the next one coming in
- // (signal comppression)
- return;
- }
-
- // Now do the actual notification of new bytes
- writeDownstreamDataDownloadBuffer(received, total);
-}
-
-void QNetworkAccessHttpBackend::httpAuthenticationRequired(const QHttpNetworkRequest &,
- QAuthenticator *auth)
-{
- authenticationRequired(auth);
-}
-
-void QNetworkAccessHttpBackend::httpError(QNetworkReply::NetworkError errorCode,
- const QString &errorString)
-{
-#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
- qDebug() << "http error!" << errorCode << errorString;
-#endif
-
- error(errorCode, errorString);
-}
-
-#ifndef QT_NO_OPENSSL
-void QNetworkAccessHttpBackend::replySslErrors(
- const QList<QSslError> &list, bool *ignoreAll, QList<QSslError> *toBeIgnored)
-{
- // Go to generic backend
- sslErrors(list);
- // Check if the callback set any ignore and return this here to http thread
- if (pendingIgnoreAllSslErrors)
- *ignoreAll = true;
- if (!pendingIgnoreSslErrorsList.isEmpty())
- *toBeIgnored = pendingIgnoreSslErrorsList;
-}
-
-void QNetworkAccessHttpBackend::replySslConfigurationChanged(const QSslConfiguration &c)
-{
- // Receiving the used SSL configuration from the HTTP thread
- if (pendingSslConfiguration)
- *pendingSslConfiguration = c;
- else if (!c.isNull())
- pendingSslConfiguration = new QSslConfiguration(c);
-}
-#endif
-
-// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
-void QNetworkAccessHttpBackend::resetUploadDataSlot(bool *r)
-{
- *r = uploadByteDevice->reset();
-}
-
-// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
-void QNetworkAccessHttpBackend::sentUploadDataSlot(qint64 amount)
-{
- uploadByteDevice->advanceReadPointer(amount);
-}
-
-// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
-void QNetworkAccessHttpBackend::wantUploadDataSlot(qint64 maxSize)
-{
- // call readPointer
- qint64 currentUploadDataLength = 0;
- char *data = const_cast<char*>(uploadByteDevice->readPointer(maxSize, currentUploadDataLength));
- // Let's make a copy of this data
- QByteArray dataArray(data, currentUploadDataLength);
-
- // Communicate back to HTTP thread
- emit haveUploadData(dataArray, uploadByteDevice->atEnd(), uploadByteDevice->size());
-}
-
-/*
- A simple web page that can be used to test us: http://www.procata.com/cachetest/
- */
-bool QNetworkAccessHttpBackend::sendCacheContents(const QNetworkCacheMetaData &metaData)
-{
- setCachingEnabled(false);
- if (!metaData.isValid())
- return false;
-
- QAbstractNetworkCache *nc = networkCache();
- Q_ASSERT(nc);
- QIODevice *contents = nc->data(url());
- if (!contents) {
-#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
- qDebug() << "Can not send cache, the contents are 0" << url();
-#endif
- return false;
- }
- contents->setParent(this);
-
- QNetworkCacheMetaData::AttributesMap attributes = metaData.attributes();
- int status = attributes.value(QNetworkRequest::HttpStatusCodeAttribute).toInt();
- if (status < 100)
- status = 200; // fake it
-
- setAttribute(QNetworkRequest::HttpStatusCodeAttribute, status);
- setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, attributes.value(QNetworkRequest::HttpReasonPhraseAttribute));
- setAttribute(QNetworkRequest::SourceIsFromCacheAttribute, true);
-
- QNetworkCacheMetaData::RawHeaderList rawHeaders = metaData.rawHeaders();
- QNetworkCacheMetaData::RawHeaderList::ConstIterator it = rawHeaders.constBegin(),
- end = rawHeaders.constEnd();
- for ( ; it != end; ++it)
- setRawHeader(it->first, it->second);
-
- checkForRedirect(status);
-
- // This needs to be emitted in the event loop because it can be reached at
- // the direct code path of qnam.get(...) before the user has a chance
- // to connect any signals.
- QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection);
- qRegisterMetaType<QIODevice*>("QIODevice*");
- QMetaObject::invokeMethod(this, "writeDownstreamData", Qt::QueuedConnection, Q_ARG(QIODevice*, contents));
-
-
-#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
- qDebug() << "Successfully sent cache:" << url() << contents->size() << "bytes";
-#endif
-
- // Set the following flag so we can ignore some signals from HTTP thread
- // that would still come
- loadingFromCache = true;
- return true;
-}
-
-void QNetworkAccessHttpBackend::copyFinished(QIODevice *dev)
-{
- delete dev;
- finished();
-}
-
-#ifndef QT_NO_OPENSSL
-void QNetworkAccessHttpBackend::ignoreSslErrors()
-{
- pendingIgnoreAllSslErrors = true;
-}
-
-void QNetworkAccessHttpBackend::ignoreSslErrors(const QList<QSslError> &errors)
-{
- // the pending list is set if QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors)
- // is called before QNetworkAccessManager::get() (or post(), etc.)
- pendingIgnoreSslErrorsList = errors;
-}
-
-void QNetworkAccessHttpBackend::fetchSslConfiguration(QSslConfiguration &config) const
-{
- if (pendingSslConfiguration)
- config = *pendingSslConfiguration;
- else
- config = request().sslConfiguration();
-}
-
-void QNetworkAccessHttpBackend::setSslConfiguration(const QSslConfiguration &newconfig)
-{
- // Setting a SSL configuration on a reply is not supported. The user needs to set
- // her/his QSslConfiguration on the QNetworkRequest.
- Q_UNUSED(newconfig);
-}
-#endif
-
-QNetworkCacheMetaData QNetworkAccessHttpBackend::fetchCacheMetaData(const QNetworkCacheMetaData &oldMetaData) const
-{
- QNetworkCacheMetaData metaData = oldMetaData;
-
- QNetworkHeadersPrivate cacheHeaders;
- cacheHeaders.setAllRawHeaders(metaData.rawHeaders());
- QNetworkHeadersPrivate::RawHeadersList::ConstIterator it;
-
- QList<QByteArray> newHeaders = rawHeaderList();
- foreach (QByteArray header, newHeaders) {
- QByteArray originalHeader = header;
- header = header.toLower();
- bool hop_by_hop =
- (header == "connection"
- || header == "keep-alive"
- || header == "proxy-authenticate"
- || header == "proxy-authorization"
- || header == "te"
- || header == "trailers"
- || header == "transfer-encoding"
- || header == "upgrade");
- if (hop_by_hop)
- continue;
-
- // we are currently not using the date header to determine the expiration time of a page,
- // but only the "Expires", "max-age" and "s-maxage" headers, see
- // QNetworkAccessHttpBackend::validateCache() and below ("metaData.setExpirationDate()").
- if (header == "date")
- continue;
-
- // Don't store Warning 1xx headers
- if (header == "warning") {
- QByteArray v = rawHeader(header);
- if (v.length() == 3
- && v[0] == '1'
- && v[1] >= '0' && v[1] <= '9'
- && v[2] >= '0' && v[2] <= '9')
- continue;
- }
-
- it = cacheHeaders.findRawHeader(header);
- if (it != cacheHeaders.rawHeaders.constEnd()) {
- // Match the behavior of Firefox and assume Cache-Control: "no-transform"
- if (header == "content-encoding"
- || header == "content-range"
- || header == "content-type")
- continue;
-
- // For MS servers that send "Content-Length: 0" on 304 responses
- // ignore this too
- if (header == "content-length")
- continue;
- }
-
-#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
- QByteArray n = rawHeader(header);
- QByteArray o;
- if (it != cacheHeaders.rawHeaders.constEnd())
- o = (*it).second;
- if (n != o && header != "date") {
- qDebug() << "replacing" << header;
- qDebug() << "new" << n;
- qDebug() << "old" << o;
- }
-#endif
- cacheHeaders.setRawHeader(originalHeader, rawHeader(header));
- }
- metaData.setRawHeaders(cacheHeaders.rawHeaders);
-
- bool checkExpired = true;
-
- QHash<QByteArray, QByteArray> cacheControl;
- it = cacheHeaders.findRawHeader("Cache-Control");
- if (it != cacheHeaders.rawHeaders.constEnd()) {
- cacheControl = parseHttpOptionHeader(it->second);
- QByteArray maxAge = cacheControl.value("max-age");
- if (!maxAge.isEmpty()) {
- checkExpired = false;
- QDateTime dt = QDateTime::currentDateTime();
- dt = dt.addSecs(maxAge.toInt());
- metaData.setExpirationDate(dt);
- }
- }
- if (checkExpired) {
- it = cacheHeaders.findRawHeader("expires");
- if (it != cacheHeaders.rawHeaders.constEnd()) {
- QDateTime expiredDateTime = QNetworkHeadersPrivate::fromHttpDate(it->second);
- metaData.setExpirationDate(expiredDateTime);
- }
- }
-
- it = cacheHeaders.findRawHeader("last-modified");
- if (it != cacheHeaders.rawHeaders.constEnd())
- metaData.setLastModified(QNetworkHeadersPrivate::fromHttpDate(it->second));
-
- bool canDiskCache;
- // only cache GET replies by default, all other replies (POST, PUT, DELETE)
- // are not cacheable by default (according to RFC 2616 section 9)
- if (httpRequest.operation() == QHttpNetworkRequest::Get) {
-
- canDiskCache = true;
- // 14.32
- // HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client
- // had sent "Cache-Control: no-cache".
- it = cacheHeaders.findRawHeader("pragma");
- if (it != cacheHeaders.rawHeaders.constEnd()
- && it->second == "no-cache")
- canDiskCache = false;
-
- // HTTP/1.1. Check the Cache-Control header
- if (cacheControl.contains("no-cache"))
- canDiskCache = false;
- else if (cacheControl.contains("no-store"))
- canDiskCache = false;
-
- // responses to POST might be cacheable
- } else if (httpRequest.operation() == QHttpNetworkRequest::Post) {
-
- canDiskCache = false;
- // some pages contain "expires:" and "cache-control: no-cache" field,
- // so we only might cache POST requests if we get "cache-control: max-age ..."
- if (cacheControl.contains("max-age"))
- canDiskCache = true;
-
- // responses to PUT and DELETE are not cacheable
- } else {
- canDiskCache = false;
- }
-
- metaData.setSaveToDisk(canDiskCache);
- QNetworkCacheMetaData::AttributesMap attributes;
- if (statusCode != 304) {
- // update the status code
- attributes.insert(QNetworkRequest::HttpStatusCodeAttribute, statusCode);
- attributes.insert(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase);
- } else {
- // this is a redirection, keep the attributes intact
- attributes = oldMetaData.attributes();
- }
- metaData.setAttributes(attributes);
- return metaData;
-}
-
-bool QNetworkAccessHttpBackend::canResume() const
-{
- // Only GET operation supports resuming.
- if (operation() != QNetworkAccessManager::GetOperation)
- return false;
-
- // Can only resume if server/resource supports Range header.
- QByteArray acceptRangesheaderName("Accept-Ranges");
- if (!hasRawHeader(acceptRangesheaderName) || rawHeader(acceptRangesheaderName) == "none")
- return false;
-
- // We only support resuming for byte ranges.
- if (request().hasRawHeader("Range")) {
- QByteArray range = request().rawHeader("Range");
- if (!range.startsWith("bytes="))
- return false;
- }
-
- // If we're using a download buffer then we don't support resuming/migration
- // right now. Too much trouble.
- if (usingZerocopyDownloadBuffer)
- return false;
-
- return true;
-}
-
-void QNetworkAccessHttpBackend::setResumeOffset(quint64 offset)
-{
- resumeOffset = offset;
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_HTTP
+++ /dev/null
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtNetwork module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** 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.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QNETWORKACCESSHTTPBACKEND_P_H
-#define QNETWORKACCESSHTTPBACKEND_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of the Network Access API. This header file may change from
-// version to version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qhttpnetworkconnection_p.h"
-#include "qnetworkaccessbackend_p.h"
-#include "qnetworkrequest.h"
-#include "qnetworkreply.h"
-#include "qabstractsocket.h"
-
-#include "QtCore/qpointer.h"
-#include "QtCore/qdatetime.h"
-#include "QtCore/qsharedpointer.h"
-#include "qatomic.h"
-
-#ifndef QT_NO_HTTP
-
-QT_BEGIN_NAMESPACE
-
-class QNetworkAccessCachedHttpConnection;
-
-class QNetworkAccessHttpBackendIODevice;
-
-class QNetworkAccessHttpBackend: public QNetworkAccessBackend
-{
- Q_OBJECT
-public:
- QNetworkAccessHttpBackend();
- virtual ~QNetworkAccessHttpBackend();
-
- virtual void open();
- virtual void closeDownstreamChannel();
-
- virtual void downstreamReadyWrite();
- virtual void setDownstreamLimited(bool b);
-
- virtual void copyFinished(QIODevice *);
-#ifndef QT_NO_OPENSSL
- virtual void ignoreSslErrors();
- virtual void ignoreSslErrors(const QList<QSslError> &errors);
-
- virtual void fetchSslConfiguration(QSslConfiguration &configuration) const;
- virtual void setSslConfiguration(const QSslConfiguration &configuration);
-#endif
- QNetworkCacheMetaData fetchCacheMetaData(const QNetworkCacheMetaData &metaData) const;
-
- // we return true since HTTP needs to send PUT/POST data again after having authenticated
- bool needsResetableUploadData() { return true; }
-
- bool canResume() const;
- void setResumeOffset(quint64 offset);
-
-signals:
- // To HTTP thread:
- void startHttpRequest();
- void abortHttpRequest();
-
- void startHttpRequestSynchronously();
-
- void haveUploadData(QByteArray dataArray, bool dataAtEnd, qint64 dataSize);
-private slots:
- // From HTTP thread:
- void replyDownloadData(QByteArray);
- void replyFinished();
- void replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >,int,QString,bool,QSharedPointer<char>,qint64);
- void replyDownloadProgressSlot(qint64,qint64);
- void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth);
- void httpError(QNetworkReply::NetworkError error, const QString &errorString);
-#ifndef QT_NO_OPENSSL
- void replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *);
- void replySslConfigurationChanged(const QSslConfiguration&);
-#endif
-
- // From QNonContiguousByteDeviceThreadForwardImpl in HTTP thread:
- void resetUploadDataSlot(bool *r);
- void wantUploadDataSlot(qint64);
- void sentUploadDataSlot(qint64);
-
- bool sendCacheContents(const QNetworkCacheMetaData &metaData);
-
-private:
- QHttpNetworkRequest httpRequest; // There is also a copy in the HTTP thread
- int statusCode;
- QString reasonPhrase;
- // Will be increased by HTTP thread:
- QSharedPointer<QAtomicInt> pendingDownloadDataEmissions;
- QSharedPointer<QAtomicInt> pendingDownloadProgressEmissions;
- bool loadingFromCache;
- QByteDataBuffer pendingDownloadData;
- bool usingZerocopyDownloadBuffer;
-
-#ifndef QT_NO_OPENSSL
- QSslConfiguration *pendingSslConfiguration;
- bool pendingIgnoreAllSslErrors;
- QList<QSslError> pendingIgnoreSslErrorsList;
-#endif
-
- quint64 resumeOffset;
-
- bool loadFromCacheIfAllowed(QHttpNetworkRequest &httpRequest);
- void invalidateCache();
- void postRequest();
- void readFromHttp();
- void checkForRedirect(const int statusCode);
-};
-
-class QNetworkAccessHttpBackendFactory : public QNetworkAccessBackendFactory
-{
-public:
- virtual QNetworkAccessBackend *create(QNetworkAccessManager::Operation op,
- const QNetworkRequest &request) const;
-};
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_HTTP
-
-#endif
#include "QtNetwork/qnetworksession.h"
#include "QtNetwork/private/qsharednetworksession_p.h"
-#include "qnetworkaccesshttpbackend_p.h"
#include "qnetworkaccessftpbackend_p.h"
#include "qnetworkaccessfilebackend_p.h"
#include "qnetworkaccessdebugpipebackend_p.h"
private:
friend class QNetworkReplyImplPrivate;
- friend class QNetworkAccessHttpBackend;
friend class QNetworkReplyHttpImpl;
Q_DECLARE_PRIVATE(QNetworkAccessManager)
header and contains a QList<QNetworkCookie> representing the
cookies sent by the server to be stored locally.
+ \value UserAgentHeader The User-Agent header sent by HTTP clients.
+
+ \value ServerHeader The Server header received by HTTP clients.
+
\sa header(), setHeader(), rawHeader(), setRawHeader()
*/
case QNetworkRequest::ContentDispositionHeader:
return "Content-Disposition";
+ case QNetworkRequest::UserAgentHeader:
+ return "User-Agent";
+
+ case QNetworkRequest::ServerHeader:
+ return "Server";
+
// no default:
// if new values are added, this will generate a compiler warning
}
case QNetworkRequest::ContentTypeHeader:
case QNetworkRequest::ContentLengthHeader:
case QNetworkRequest::ContentDispositionHeader:
+ case QNetworkRequest::UserAgentHeader:
+ case QNetworkRequest::ServerHeader:
return value.toByteArray();
case QNetworkRequest::LocationHeader:
case 's':
if (qstricmp(headerName.constData(), "set-cookie") == 0)
return QNetworkRequest::SetCookieHeader;
+ else if (qstricmp(headerName.constData(), "server") == 0)
+ return QNetworkRequest::ServerHeader;
+ break;
+
+ case 'u':
+ if (qstricmp(headerName.constData(), "user-agent") == 0)
+ return QNetworkRequest::UserAgentHeader;
break;
}
{
// header is always a valid value
switch (header) {
+ case QNetworkRequest::UserAgentHeader:
+ case QNetworkRequest::ServerHeader:
case QNetworkRequest::ContentTypeHeader:
// copy exactly, convert to QString
return QString::fromLatin1(value);
LastModifiedHeader,
CookieHeader,
SetCookieHeader,
- ContentDispositionHeader // added for QMultipartMessage
+ ContentDispositionHeader, // added for QMultipartMessage
+ UserAgentHeader,
+ ServerHeader
};
enum Attribute {
HttpStatusCodeAttribute,
iterator.remove();
hostInfo.setLookupId(postponed->id);
postponed->resultEmitter.emitResultsReady(hostInfo);
+ delete postponed;
}
}
}
QT_BEGIN_NAMESPACE
// forward declaration
-static QMap<QString, QString> _q_mapFromX509Name(X509_NAME *name);
+static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name);
/*!
Constructs a QSslCertificate by reading \a format encoded data
return QCryptographicHash::hash(toDer(), algorithm);
}
-static QString _q_SubjectInfoToString(QSslCertificate::SubjectInfo info)
+static QByteArray _q_SubjectInfoToString(QSslCertificate::SubjectInfo info)
{
- QString str;
+ QByteArray str;
switch (info) {
- case QSslCertificate::Organization: str = QLatin1String("O"); break;
- case QSslCertificate::CommonName: str = QLatin1String("CN"); break;
- case QSslCertificate::LocalityName: str = QLatin1String("L"); break;
- case QSslCertificate::OrganizationalUnitName: str = QLatin1String("OU"); break;
- case QSslCertificate::CountryName: str = QLatin1String("C"); break;
- case QSslCertificate::StateOrProvinceName: str = QLatin1String("ST"); break;
- case QSslCertificate::DistinguishedNameQualifier: str = QLatin1String("dnQualifier"); break;
- case QSslCertificate::SerialNumber: str = QLatin1String("serialNumber"); break;
- case QSslCertificate::EmailAddress: str = QLatin1String("emailAddress"); break;
+ case QSslCertificate::Organization: str = QByteArray("O"); break;
+ case QSslCertificate::CommonName: str = QByteArray("CN"); break;
+ case QSslCertificate::LocalityName: str = QByteArray("L"); break;
+ case QSslCertificate::OrganizationalUnitName: str = QByteArray("OU"); break;
+ case QSslCertificate::CountryName: str = QByteArray("C"); break;
+ case QSslCertificate::StateOrProvinceName: str = QByteArray("ST"); break;
+ case QSslCertificate::DistinguishedNameQualifier: str = QByteArray("dnQualifier"); break;
+ case QSslCertificate::SerialNumber: str = QByteArray("serialNumber"); break;
+ case QSslCertificate::EmailAddress: str = QByteArray("emailAddress"); break;
}
return str;
}
}
/*!
- Returns the issuer information for \a tag from the certificate,
- or an empty string if there is no information for \a tag in the
+ Returns the issuer information for \a attribute from the certificate,
+ or an empty string if there is no information for \a attribute in the
certificate.
\sa subjectInfo()
*/
-QStringList QSslCertificate::issuerInfo(const QByteArray &tag) const
+QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const
{
// lazy init
if (d->issuerInfo.isEmpty() && d->x509)
d->issuerInfo =
_q_mapFromX509Name(q_X509_get_issuer_name(d->x509));
- return d->issuerInfo.values(QString::fromLatin1(tag));
+ return d->issuerInfo.values(attribute);
}
/*!
}
/*!
- Returns the subject information for \a tag, or an empty string if
- there is no information for \a tag in the certificate.
+ Returns the subject information for \a attribute, or an empty string if
+ there is no information for \a attribute in the certificate.
\sa issuerInfo()
*/
-QStringList QSslCertificate::subjectInfo(const QByteArray &tag) const
+QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const
{
// lazy init
if (d->subjectInfo.isEmpty() && d->x509)
d->subjectInfo =
_q_mapFromX509Name(q_X509_get_subject_name(d->x509));
- return d->subjectInfo.values(QString::fromLatin1(tag));
+ return d->subjectInfo.values(attribute);
+}
+
+/*!
+ Returns a list of the attributes that have values in the subject
+ information of this certificate. The information associated
+ with a given attribute can be accessed using the subjectInfo()
+ method. Note that this list may include the OIDs for any
+ elements that are not known by the SSL backend.
+
+ \sa subjectInfo()
+*/
+QList<QByteArray> QSslCertificate::subjectInfoAttributes() const
+{
+ // lazy init
+ if (d->subjectInfo.isEmpty() && d->x509)
+ d->subjectInfo =
+ _q_mapFromX509Name(q_X509_get_subject_name(d->x509));
+
+ return d->subjectInfo.uniqueKeys();
+}
+
+/*!
+ Returns a list of the attributes that have values in the issuer
+ information of this certificate. The information associated
+ with a given attribute can be accessed using the issuerInfo()
+ method. Note that this list may include the OIDs for any
+ elements that are not known by the SSL backend.
+
+ \sa subjectInfo()
+*/
+QList<QByteArray> QSslCertificate::issuerInfoAttributes() const
+{
+ // lazy init
+ if (d->issuerInfo.isEmpty() && d->x509)
+ d->issuerInfo =
+ _q_mapFromX509Name(q_X509_get_issuer_name(d->x509));
+
+ return d->issuerInfo.uniqueKeys();
}
/*!
return result;
}
-static QMap<QString, QString> _q_mapFromX509Name(X509_NAME *name)
+QByteArray QSslCertificatePrivate::asn1ObjectName(ASN1_OBJECT *object)
{
- QMap<QString, QString> info;
+ int nid = q_OBJ_obj2nid(object);
+ if (nid != NID_undef)
+ return QByteArray(q_OBJ_nid2sn(nid));
+
+ // This is used for unknown info so we get the OID as text
+ char buf[80];
+ q_i2t_ASN1_OBJECT(buf, sizeof(buf), object);
+
+ return QByteArray(buf);
+}
+
+static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name)
+{
+ QMap<QByteArray, QString> info;
for (int i = 0; i < q_X509_NAME_entry_count(name); ++i) {
X509_NAME_ENTRY *e = q_X509_NAME_get_entry(name, i);
- const char *obj = q_OBJ_nid2sn(q_OBJ_obj2nid(q_X509_NAME_ENTRY_get_object(e)));
+
+ QByteArray name = QSslCertificatePrivate::asn1ObjectName(q_X509_NAME_ENTRY_get_object(e));
unsigned char *data = 0;
int size = q_ASN1_STRING_to_UTF8(&data, q_X509_NAME_ENTRY_get_data(e));
- info.insertMulti(QString::fromUtf8(obj), QString::fromUtf8((char*)data, size));
+ info.insertMulti(name, QString::fromUtf8((char*)data, size));
q_CRYPTO_free(data);
}
+
return info;
}
QByteArray serialNumber() const;
QByteArray digest(QCryptographicHash::Algorithm algorithm = QCryptographicHash::Md5) const;
QStringList issuerInfo(SubjectInfo info) const;
- QStringList issuerInfo(const QByteArray &tag) const;
+ QStringList issuerInfo(const QByteArray &attribute) const;
QStringList subjectInfo(SubjectInfo info) const;
- QStringList subjectInfo(const QByteArray &tag) const;
+ QStringList subjectInfo(const QByteArray &attribute) const;
+ QList<QByteArray> subjectInfoAttributes() const;
+ QList<QByteArray> issuerInfoAttributes() const;
QMultiMap<QSsl::AlternateNameEntryType, QString> alternateSubjectNames() const;
QDateTime effectiveDate() const;
QDateTime expiryDate() const;
QByteArray versionString;
QByteArray serialNumberString;
- QMap<QString, QString> issuerInfo;
- QMap<QString, QString> subjectInfo;
+ QMap<QByteArray, QString> issuerInfo;
+ QMap<QByteArray, QString> subjectInfo;
QDateTime notValidAfter;
QDateTime notValidBefore;
void init(const QByteArray &data, QSsl::EncodingFormat format);
+ static QByteArray asn1ObjectName(ASN1_OBJECT *object);
static QByteArray QByteArray_from_X509(X509 *x509, QSsl::EncodingFormat format);
static QByteArray text_from_X509(X509 *x509);
static QSslCertificate QSslCertificate_from_X509(X509 *x509);
}
/*!
+ Returns the version number of the SSL library in use. Note that
+ this is the version of the library in use at run-time not compile
+ time. If no SSL support is available then this will return an
+ undefined value.
+*/
+long QSslSocket::sslLibraryVersionNumber()
+{
+ return QSslSocketPrivate::sslLibraryVersionNumber();
+}
+
+/*!
+ Returns the version string of the SSL library in use. Note that
+ this is the version of the library in use at run-time not compile
+ time. If no SSL support is available then this will return an empty value.
+*/
+QString QSslSocket::sslLibraryVersionString()
+{
+ return QSslSocketPrivate::sslLibraryVersionString();
+}
+
+/*!
Starts a delayed SSL handshake for a client connection. This
function can be called when the socket is in the \l ConnectedState
but still in the \l UnencryptedMode. If it is not yet connected,
QList<QSslError> sslErrors() const;
static bool supportsSsl();
+ static long sslLibraryVersionNumber();
+ static QString sslLibraryVersionString();
+
void ignoreSslErrors(const QList<QSslError> &errors);
public Q_SLOTS:
ensureCiphersAndCertsLoaded();
}
+long QSslSocketPrivate::sslLibraryVersionNumber()
+{
+ return q_SSLeay();
+}
+
+QString QSslSocketPrivate::sslLibraryVersionString()
+{
+ if (!supportsSsl())
+ return QString();
+
+ const char *versionString = q_SSLeay_version(SSLEAY_VERSION);
+ if (!versionString)
+ return QString();
+
+ return QString::fromLatin1(versionString);
+}
+
/*!
\internal
DEFINEFUNC(int, EVP_PKEY_type, int a, a, return NID_undef, return)
DEFINEFUNC2(int, i2d_X509, X509 *a, a, unsigned char **b, b, return -1, return)
DEFINEFUNC(const char *, OBJ_nid2sn, int a, a, return 0, return)
+DEFINEFUNC(const char *, OBJ_nid2ln, int a, a, return 0, return)
+DEFINEFUNC3(int, i2t_ASN1_OBJECT, char *a, a, int b, b, ASN1_OBJECT *c, c, return -1, return)
+
+
DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return)
#ifdef SSLEAY_MACROS
DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG)
DEFINEFUNC3(int, SSL_CTX_load_verify_locations, SSL_CTX *ctx, ctx, const char *CAfile, CAfile, const char *CApath, CApath, return 0, return)
DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return)
+DEFINEFUNC(const char *, SSLeay_version, int a, a, return 0, return)
#ifdef Q_OS_SYMBIAN
#define RESOLVEFUNC(func, ordinal, lib) \
RESOLVEFUNC(EVP_PKEY_new)
RESOLVEFUNC(EVP_PKEY_type)
RESOLVEFUNC(OBJ_nid2sn)
+ RESOLVEFUNC(OBJ_nid2ln)
+ RESOLVEFUNC(i2t_ASN1_OBJECT)
RESOLVEFUNC(OBJ_obj2nid)
#ifdef SSLEAY_MACROS // ### verify
RESOLVEFUNC(PEM_ASN1_read_bio)
RESOLVEFUNC(OPENSSL_add_all_algorithms_conf)
RESOLVEFUNC(SSL_CTX_load_verify_locations)
RESOLVEFUNC(SSLeay)
+ RESOLVEFUNC(SSLeay_version)
#endif // Q_OS_SYMBIAN
symbolsResolved = true;
delete libs.first;
EVP_PKEY *q_EVP_PKEY_new();
int q_i2d_X509(X509 *a, unsigned char **b);
const char *q_OBJ_nid2sn(int a);
+const char *q_OBJ_nid2ln(int a);
+int q_i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *obj);
int q_OBJ_obj2nid(const ASN1_OBJECT *a);
#ifdef SSLEAY_MACROS
// ### verify
void q_OPENSSL_add_all_algorithms_conf();
int q_SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath);
long q_SSLeay();
+const char *q_SSLeay_version(int type);
// Helper function
class QDateTime;
bool allowRootCertOnDemandLoading;
static bool supportsSsl();
+ static long sslLibraryVersionNumber();
+ static QString sslLibraryVersionString();
static void ensureInitialized();
static void deinitialize();
static QList<QSslCipher> defaultCiphers();
#ifndef QT_NO_DBUS
QT_BEGIN_NAMESPACE
-static QDBusConnection dbusConnection = QDBusConnection::systemBus();
-
QOfonoManagerInterface::QOfonoManagerInterface( QObject *parent)
: QDBusAbstractInterface(QLatin1String(OFONO_SERVICE),
QOfonoDBusHelper *helper;
helper = new QOfonoDBusHelper(this);
- dbusConnection.connect(QLatin1String(OFONO_SERVICE),
+ QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
QLatin1String(OFONO_MANAGER_PATH),
QLatin1String(OFONO_MANAGER_INTERFACE),
QLatin1String("PropertyChanged"),
QOfonoDBusHelper *helper;
helper = new QOfonoDBusHelper(this);
- dbusConnection.connect(QLatin1String(OFONO_SERVICE),
+ QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
this->path(),
QLatin1String(OFONO_MODEM_INTERFACE),
QLatin1String("PropertyChanged"),
QOfonoDBusHelper *helper;
helper = new QOfonoDBusHelper(this);
- dbusConnection.connect(QLatin1String(OFONO_SERVICE),
+ QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
this->path(),
QLatin1String(OFONO_NETWORK_REGISTRATION_INTERFACE),
QLatin1String("PropertyChanged"),
QOfonoDBusHelper *helper;
helper = new QOfonoDBusHelper(this);
- dbusConnection.connect(QLatin1String(OFONO_SERVICE),
+ QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
this->path(),
QLatin1String(OFONO_NETWORK_OPERATOR_INTERFACE),
QLatin1String("PropertyChanged"),
QOfonoDBusHelper *helper;
helper = new QOfonoDBusHelper(this);
- dbusConnection.connect(QLatin1String(OFONO_SERVICE),
+ QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
this->path(),
QLatin1String(OFONO_SIM_MANAGER_INTERFACE),
QLatin1String("PropertyChanged"),
QOfonoDBusHelper *helper;
helper = new QOfonoDBusHelper(this);
- dbusConnection.connect(QLatin1String(OFONO_SERVICE),
+ QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
this->path(),
QLatin1String(OFONO_DATA_CONNECTION_MANAGER_INTERFACE),
QLatin1String("PropertyChanged"),
QOfonoDBusHelper *helper;
helper = new QOfonoDBusHelper(this);
- dbusConnection.connect(QLatin1String(OFONO_SERVICE),
+ QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
this->path(),
QLatin1String(OFONO_DATA_CONTEXT_INTERFACE),
QLatin1String("PropertyChanged"),
QOfonoDBusHelper *helper;
helper = new QOfonoDBusHelper(this);
- dbusConnection.connect(QLatin1String(OFONO_SERVICE),
+ QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
this->path(),
QLatin1String(OFONO_SMS_MANAGER_INTERFACE),
QLatin1String("PropertyChanged"),
Simulator:
----------
-configure -qpa -xplatform qws/macx-iphonesimulator-g++ -arch i386 -developer-build -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations
+configure -qpa -xplatform qws/macx-iphonesimulator-g++ -arch i386 -developer-build -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake docs -nomake examples -nomake translations
Device:
-------
-configure -qpa -xplatform qws/macx-iphonedevice-g++ -arch armv7 -developer-build -release -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations
+configure -qpa -xplatform qws/macx-iphonedevice-g++ -arch armv7 -developer-build -release -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake docs -nomake examples -nomake translations
2) XCode setup:
- there are examples in the examples subdirectory of the platform plugin
#include "wayland-xcomposite-client-protocol.h"
#include <X11/extensions/Xcomposite.h>
+#include "qwaylandxcompositeeglintegration.h"
+#include "windowmanager_integration/qwaylandwindowmanagerintegration.h"
#include <QtCore/QDebug>
QWaylandXCompositeEGLWindow *that = static_cast<QWaylandXCompositeEGLWindow *>(data);
that->m_waitingForSync = false;
}
+
+void QWaylandXCompositeEGLWindow::requestActivateWindow()
+{
+#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
+ mDisplay->windowManagerIntegration()->authenticateWithToken();
+#endif
+
+ QWaylandWindow::requestActivateWindow();
+}
WindowType windowType() const;
void setGeometry(const QRect &rect);
+ void requestActivateWindow();
EGLSurface eglSurface() const;
QByteArray authToken = token;
if (authToken.isEmpty())
authToken = qgetenv("WL_AUTHENTICATION_TOKEN");
- if (mWaylandWindowManager)
+
+ if (mWaylandWindowManager && !authToken.isEmpty()) {
wl_windowmanager_authenticate_with_token(mWaylandWindowManager, authToken.constData());
+ }
}
void QWaylandWindowManagerIntegration::wlHandleOnScreenVisibilityChange(void *data, struct wl_windowmanager *wl_windowmanager, int visible)
{
Q_UNUSED(data);
Q_UNUSED(wl_windowmanager);
- QEvent evt(visible != 0 ? QEvent::ApplicationActivated : QEvent::ApplicationDeactivated);
-
+ QEvent evt(visible != 0 ? QEvent::ApplicationActivate : QEvent::ApplicationDeactivate);
QCoreApplication::sendEvent(QCoreApplication::instance(), &evt);
-
- qDebug() << "OnScreenVisibility" << (visible != 0);
}
void QWaylandWindowManagerIntegration::wlHandleScreenOrientationChange(void *data, struct wl_windowmanager *wl_windowmanager, int screenOrientation)
{
BeforeFirstRow = -1,
AfterLastRow = -2
-#ifdef QT3_SUPPORT
- , BeforeFirst = BeforeFirstRow,
- AfterLast = AfterLastRow
-#endif
};
enum ParamTypeFlag
HighPrecision = 0
};
-
-#ifdef QT3_SUPPORT
- enum Op {
- None = -1,
- Insert = 0,
- Update = 1,
- Delete = 2
- };
-
- enum Confirm {
- Cancel = -1,
- No = 0,
- Yes = 1
- };
-#endif
}
Q_DECLARE_OPERATORS_FOR_FLAGS(QSql::ParamType)
return d->driver && d->driver != d->shared_null()->driver;
}
-#ifdef QT3_SUPPORT
-/*!
- Use query.record() instead.
-*/
-QSqlRecord QSqlDatabase::record(const QSqlQuery& query) const
-{ return query.record(); }
-
-/*!
- Use query.record() instead.
-*/
-QSqlRecord QSqlDatabase::recordInfo(const QSqlQuery& query) const
-{ return query.record(); }
-
-/*!
- \fn QSqlRecord QSqlDatabase::recordInfo(const QString& tablename) const
-
- Use record() instead.
-*/
-#endif
-
/*!
Clones the database connection \a other and and stores it as \a
connectionName. All the settings from the original database, e.g.
#include <QtCore/qstring.h>
#include <QtSql/qsql.h>
-#ifdef QT3_SUPPORT
-#include <QtSql/qsqlrecord.h>
-#endif
QT_BEGIN_HEADER
QStringList tables(QSql::TableType type = QSql::Tables) const;
QSqlIndex primaryIndex(const QString& tablename) const;
QSqlRecord record(const QString& tablename) const;
-#ifdef QT3_SUPPORT
- QT3_SUPPORT QSqlRecord record(const QSqlQuery& query) const;
- inline QT3_SUPPORT QSqlRecord recordInfo(const QString& tablename) const
- { return record(tablename); }
- QT3_SUPPORT QSqlRecord recordInfo(const QSqlQuery& query) const;
-#endif
QSqlQuery exec(const QString& query = QString()) const;
QSqlError lastError() const;
bool isValid() const;
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtSql/qsql.h>
-#ifdef QT3_SUPPORT
-#include <QtSql/qsqlquery.h>
-#endif
QT_BEGIN_HEADER
virtual QStringList tables(QSql::TableType tableType) const;
virtual QSqlIndex primaryIndex(const QString &tableName) const;
virtual QSqlRecord record(const QString &tableName) const;
-#ifdef QT3_SUPPORT
- inline QT3_SUPPORT QSqlRecord record(const QSqlQuery& query) const
- { return query.record(); }
- inline QT3_SUPPORT QSqlRecord recordInfo(const QString& tablename) const
- { return record(tablename); }
- inline QT3_SUPPORT QSqlRecord recordInfo(const QSqlQuery& query) const
- { return query.record(); }
- inline QT3_SUPPORT QString nullText() const { return QLatin1String("NULL"); }
- inline QT3_SUPPORT QString formatValue(const QSqlField *field, bool trimStrings = false) const
- { return field ? formatValue(*field, trimStrings) : QString(); }
-#endif
virtual QString formatValue(const QSqlField& field, bool trimStrings = false) const;
virtual QString escapeIdentifier(const QString &identifier, IdentifierType type) const;
StatementError,
TransactionError,
UnknownError
-#ifdef QT3_SUPPORT
- , None = NoError,
- Connection = ConnectionError,
- Statement = StatementError,
- Transaction = TransactionError,
- Unknown = UnknownError
-#endif
};
QSqlError( const QString& driverText = QString(),
const QString& databaseText = QString(),
bool isGenerated() const;
bool isValid() const;
-#ifdef QT3_SUPPORT
- inline QT3_SUPPORT void setNull() { clear(); }
-#endif
-
private:
void detach();
QVariant val;
sorts[i] = desc;
}
-#ifdef QT3_SUPPORT
-
-/*!
- Returns a comma-separated list of all the index's field names as a
- string. This string is suitable, for example, for generating a
- SQL SELECT statement. Only generated fields are included in the
- list (see \l{isGenerated()}). If a \a prefix is specified, e.g. a
- table name, it is prepended before all field names in the form:
-
- "\a{prefix}.<fieldname>"
-
- If \a sep is specified, each field is separated by \a sep. If \a
- verbose is true (the default), each field contains a suffix
- indicating an ASCending or DESCending sort order.
-*/
-
-QString QSqlIndex::toString(const QString& prefix, const QString& sep, bool verbose) const
-{
- QString s;
- bool comma = false;
- for (int i = 0; i < count(); ++i) {
- if(comma)
- s += sep + QLatin1Char(' ');
- s += createField(i, prefix, verbose);
- comma = true;
- }
- return s;
-}
-
-/*!
- Returns a list of all the index's field names. Only generated
- fields are included in the list (see \l{isGenerated()}). If a \a
- prefix is specified, e.g. a table name, all fields are prefixed in
- the form:
-
- "\a{prefix}.<fieldname>"
-
- If \a verbose is true (the default), each field contains a suffix
- indicating an ASCending or DESCending sort order.
-
- Note that if you want to iterate over the list, you should iterate
- over a copy, e.g.
- \snippet doc/src/snippets/code/src_sql_kernel_qsqlindex.cpp 0
-
-*/
-QStringList QSqlIndex::toStringList(const QString& prefix, bool verbose) const
-{
- QStringList s;
- for (int i = 0; i < count(); ++i)
- s += createField(i, prefix, verbose);
- return s;
-}
-#endif
-
/*! \internal
Creates a string representing the field number \a i using prefix \a
bool isDescending(int i) const;
void setDescending(int i, bool desc);
-#ifdef QT3_SUPPORT
- QT3_SUPPORT QString toString(const QString &prefix = QString(),
- const QString &sep = QLatin1String(","),
- bool verbose = true) const;
- QT3_SUPPORT QStringList toStringList(const QString& prefix = QString(),
- bool verbose = true) const;
-#endif
-
private:
QString createField(int i, const QString& prefix, bool verbose) const;
QString cursor;
bool seek(int i, bool relative = false);
bool next();
bool previous();
-#ifdef QT3_SUPPORT
- inline QT3_SUPPORT bool prev() { return previous(); }
-#endif
bool first();
bool last();
return -1;
}
-#ifdef QT3_SUPPORT
-/*!
- \obsolete
- Use field() instead
-*/
-const QSqlField* QSqlRecord::fieldPtr(int index) const
-{
- if (!d->contains(index))
- return 0;
-
- return &d->fields.at(index);
-}
-
-/*!
- \obsolete
- Use field() instead
-*/
-
-const QSqlField* QSqlRecord::fieldPtr(const QString& name) const
-{
- int i = indexOf(name);
- if (!d->contains(i))
- return 0;
-
- return &d->fields.at(i);
-}
-#endif //QT3_SUPPORT
-
/*!
Returns the field at position \a index. If the position is out of
range, an empty field is returned.
return d->fields.value(index).isGenerated();
}
-#ifdef QT3_SUPPORT
-/*!
- Returns a list of all the record's field names as a string
- separated by \a sep.
-
- In the unlikely event that you used this function in Qt 3, you
- can simulate it using the rest of the QSqlRecord public API.
-*/
-
-QString QSqlRecord::toString(const QString& prefix, const QString& sep) const
-{
- QString pflist;
- bool comma = false;
- for (int i = 0; i < count(); ++i) {
- if (!d->fields.value(i).isGenerated()) {
- if (comma)
- pflist += sep + QLatin1Char(' ');
- pflist += d->createField(i, prefix);
- comma = true;
- }
- }
- return pflist;
-}
-
-/*!
- Returns a list of all the record's field names, each having the
- prefix \a prefix.
-
- In the unlikely event that you used this function in Qt 3, you
- can simulate it using the rest of the QSqlRecord public API.
-*/
-
-QStringList QSqlRecord::toStringList(const QString& prefix) const
-{
- QStringList s;
- for (int i = 0; i < count(); ++i) {
- if (!d->fields.value(i).isGenerated())
- s += d->createField(i, prefix);
- }
- return s;
-}
-#endif // QT3_SUPPORT
-
/*!
Returns the number of fields in the record.
void setGenerated(const QString& name, bool generated);
void setGenerated(int i, bool generated);
-#ifdef QT3_SUPPORT
- QT3_SUPPORT const QSqlField* fieldPtr(int i) const;
- QT3_SUPPORT const QSqlField* fieldPtr(const QString& name) const;
- inline QT3_SUPPORT int position(const QString& name) const { return indexOf(name); }
- QT3_SUPPORT QString toString(const QString& prefix = QString(),
- const QString& sep = QLatin1String(",")) const;
- QT3_SUPPORT QStringList toStringList(const QString& prefix = QString()) const;
-#endif
-
void append(const QSqlField& field);
void replace(int pos, const QSqlField& field);
void insert(int pos, const QSqlField& field);
enum BindingSyntax {
PositionalBinding,
NamedBinding
-#ifdef QT3_SUPPORT
- , BindByPosition = PositionalBinding,
- BindByName = NamedBinding
-#endif
};
explicit QSqlResult(const QSqlDriver * db);
QtFontFoundry *foundry = family->foundry(foundry_name, true);
QtFontStyle::Key styleKey;
- styleKey.styleName = style_name;
+ QString styleName = style_name;
if(QCFType<CFDictionaryRef> styles = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute)) {
if(CFNumberRef weight = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontWeightTrait)) {
Q_ASSERT(CFNumberIsFloatType(weight));
}
}
- QtFontStyle *style = foundry->style(styleKey, true);
+ QtFontStyle *style = foundry->style(styleKey, styleName, true);
style->smoothScalable = true;
if(QCFType<CFNumberRef> size = (CFNumberRef)CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) {
//qDebug() << "WHEE";
QtFontFamily *family = db->family(familyName, true);
QtFontFoundry *foundry = family->foundry(QString(), true);
- QtFontStyle *style = foundry->style(styleKey, true);
+ QtFontStyle *style = foundry->style(styleKey, QString(), true);
style->pixelSize(0, true);
style->smoothScalable = true;
avgCharWidth = QFixed::fromReal(width * fontDef.pixelSize / emSize);
} else
avgCharWidth = QFontEngine::averageCharWidth();
-
- ctMaxCharWidth = ctMinLeftBearing = ctMinRightBearing = 0;
- QByteArray hheaTable = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a'));
- if (hheaTable.size() >= 16) {
- quint16 width = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(hheaTable.constData() + 10));
- ctMaxCharWidth = width * fontDef.pixelSize / emSize;
- qint16 bearing = qFromBigEndian<qint16>(reinterpret_cast<const uchar *>(hheaTable.constData() + 12));
- ctMinLeftBearing = bearing * fontDef.pixelSize / emSize;
- bearing = qFromBigEndian<qint16>(reinterpret_cast<const uchar *>(hheaTable.constData() + 14));
- ctMinRightBearing = bearing * fontDef.pixelSize / emSize;
- }
}
bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
qreal QCoreTextFontEngine::maxCharWidth() const
{
- return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
- ? qRound(ctMaxCharWidth) : ctMaxCharWidth;
+ return 0;
}
qreal QCoreTextFontEngine::minLeftBearing() const
{
- return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
- ? qRound(ctMinLeftBearing) : ctMinLeftBearing;
+ return 0;
}
qreal QCoreTextFontEngine::minRightBearing() const
{
- return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
- ? qRound(ctMinRightBearing) : ctMinLeftBearing;
+ return 0;
}
void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight)
int synthesisFlags;
CGAffineTransform transform;
QFixed avgCharWidth;
- qreal ctMaxCharWidth;
- qreal ctMinLeftBearing;
- qreal ctMinRightBearing;
friend class QCoreTextFontEngineMulti;
};
QtFontFamily *family = privateDb()->family(familyName, true);
family->fixedPitch = faceAttrib.IsMonoWidth();
QtFontFoundry *foundry = family->foundry(QString(), true);
- QtFontStyle *style = foundry->style(styleKey, true);
+ QtFontStyle *style = foundry->style(styleKey, QString(), true);
style->smoothScalable = typefaceSupport.iIsScalable;
style->pixelSize(0, true);
family->english_name = getEnglishName(familyName);
QtFontFoundry *foundry = family->foundry(foundryName, true);
- QtFontStyle *style = foundry->style(styleKey, true);
+ QtFontStyle *style = foundry->style(styleKey, QString(), true);
style->smoothScalable = scalable;
style->pixelSize( size, TRUE);
if (styleKey.weight <= QFont::DemiBold) {
QtFontStyle::Key key(styleKey);
key.weight = QFont::Bold;
- QtFontStyle *style = foundry->style(key, true);
+ QtFontStyle *style = foundry->style(key, QString(), true);
style->smoothScalable = scalable;
style->pixelSize( size, TRUE);
}
if (styleKey.style != QFont::StyleItalic) {
QtFontStyle::Key key(styleKey);
key.style = QFont::StyleItalic;
- QtFontStyle *style = foundry->style(key, true);
+ QtFontStyle *style = foundry->style(key, QString(), true);
style->smoothScalable = scalable;
style->pixelSize( size, TRUE);
}
QtFontStyle::Key key(styleKey);
key.weight = QFont::Bold;
key.style = QFont::StyleItalic;
- QtFontStyle *style = foundry->style(key, true);
+ QtFontStyle *style = foundry->style(key, QString(), true);
style->smoothScalable = scalable;
style->pixelSize( size, TRUE);
}
family->fontFileIndex = -1;
family->symbol_checked = true;
QtFontFoundry *foundry = family->foundry(QLatin1String(foundryName), true);
- QtFontStyle *style = foundry->style(styleKey, true);
+ QtFontStyle *style = foundry->style(styleKey, QString(), true);
delete [] style->weightName;
style->weightName = qstrdup(tokens[Weight]);
family->fontFileIndex = index_value;
QtFontStyle::Key styleKey;
- styleKey.styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString();
+ QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString();
styleKey.style = (slant_value == FC_SLANT_ITALIC)
? QFont::StyleItalic
: ((slant_value == FC_SLANT_OBLIQUE)
QtFontFoundry *foundry
= family->foundry(foundry_value ? QString::fromUtf8((const char *)foundry_value) : QString(), true);
- QtFontStyle *style = foundry->style(styleKey, true);
+ QtFontStyle *style = foundry->style(styleKey, styleName, true);
if (spacing_value < FC_MONO)
family->fixedPitch = false;
for (int i = 0; i < 4; ++i) {
styleKey.style = (i%2) ? QFont::StyleNormal : QFont::StyleItalic;
styleKey.weight = (i > 1) ? QFont::Bold : QFont::Normal;
- QtFontStyle *style = foundry->style(styleKey, true);
+ QtFontStyle *style = foundry->style(styleKey, QString(), true);
style->smoothScalable = true;
QtFontSize *size = style->pixelSize(SMOOTH_SCALABLE, true);
QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true);
if (equiv) continue;
// let's fake one...
- equiv = foundry->style(key, true);
+ equiv = foundry->style(key, QString(), true);
equiv->smoothScalable = true;
QtFontSize *equiv_size = equiv->pixelSize(SMOOTH_SCALABLE, true);
d->inputDevice->setTextModeEnabled(false);
}
-#ifdef QT3_SUPPORT
-/*!
- Use the QXmlInputSource(QIODevice *) constructor instead, with
- the device used by \a stream.
-
- \sa QTextStream::device()
-*/
-QXmlInputSource::QXmlInputSource(QTextStream& stream)
-{
- init();
- d->inputStream = &stream;
-}
-
-/*!
- Use QXmlInputSource(&\a file) instead.
-*/
-QXmlInputSource::QXmlInputSource(QFile& file)
-{
- init();
- d->inputDevice = &file;
-}
-#endif
-
/*!
Destructor.
*/
static const ushort EndOfData;
static const ushort EndOfDocument;
-#ifdef QT3_SUPPORT
- QT3_SUPPORT_CONSTRUCTOR QXmlInputSource(QFile& file);
- QT3_SUPPORT_CONSTRUCTOR QXmlInputSource(QTextStream& stream);
-#endif
-
protected:
virtual QString fromRawData(const QByteArray &data, bool beginning = false);
@ignore_for_qt_begin_header_check = ( "qiconset.h", "qconfig.h", "qconfig-dist.h", "qconfig-large.h", "qconfig-medium.h", "qconfig-minimal.h", "qconfig-small.h", "qfeatures.h", "qt_windows.h" );
@ignore_for_qt_begin_namespace_check = ( "qconfig.h", "qconfig-dist.h", "qconfig-large.h", "qconfig-medium.h", "qconfig-minimal.h", "qconfig-small.h", "qfeatures.h", "qatomic_arch.h", "qatomic_windowsce.h", "qt_windows.h", "qatomic_macosx.h" );
@ignore_for_qt_module_check = ( "$modules{QtCore}/arch", "$modules{QtCore}/global", "$modules{QtTest}", "$modules{QtDBus}" );
-# Modules and programs, and their dependencies.
+# Module dependencies.
+# Every module that is required to build this module should have one entry.
# Each of the module version specifiers can take one of the following values:
# - A specific Git revision.
-# - "LATEST_REVISION", to always test against the latest revision.
-# - "LATEST_RELEASE", to always test against the latest public release.
-# - "THIS_REPOSITORY", to indicate that the module is in this repository.
+# - any git symbolic ref resolvable from the module's repository (e.g. "refs/heads/master" to track master branch)
+#
%dependencies = (
- "QtCore" => {
- },
- "QtOpenGL" => {
- "QtCore" => "THIS_REPOSITORY",
- "QtGui" => "THIS_REPOSITORY",
- "QtWidgets" => "THIS_REPOSITORY",
- },
- "QtXml" => {
- "QtCore" => "THIS_REPOSITORY",
- },
- "QtNetwork" => {
- "QtCore" => "THIS_REPOSITORY",
- },
- "QtTest" => {
- "QtCore" => "THIS_REPOSITORY",
- },
- "QtDBus" => {
- "QtCore" => "THIS_REPOSITORY",
- "QtXml" => "THIS_REPOSITORY",
- },
- "QtSql" => {
- "QtCore" => "THIS_REPOSITORY",
- },
- "QtGui" => {
- "QtCore" => "THIS_REPOSITORY",
- },
- "QtWidgets" => {
- "QtCore" => "THIS_REPOSITORY",
- "QtGui" => "THIS_REPOSITORY",
- },
- "QtUiTools" => {
- "QtCore" => "THIS_REPOSITORY",
- "QtGui" => "THIS_REPOSITORY",
- "QtWidgets" => "THIS_REPOSITORY",
- },
- "QtPlatformSupport" => {
- "QtCore" => "THIS_REPOSITORY",
- "QtGui" => "THIS_REPOSITORY",
- },
);
qdbusabstractadaptor \
qdbusabstractinterface \
qdbusconnection \
+ qdbusconnection_no_bus \
qdbuscontext \
qdbusinterface \
qdbuslocalcalls \
// QCOMPARE(test->actionText(QAccessible::Press, QAccessible::Name, 0), QString("Press"));
// test->release();
-// // test splitted menu toolbutton
+// // test split menu toolbutton
// QVERIFY(QAccessible::queryAccessibleInterface(&splitToolButton, &test));
// QCOMPARE(test->childCount(), 2);
// QCOMPARE(test->role(0), QAccessible::ButtonDropDown);
QTest::newRow( "18" ) << QByteArray("aBc") << QByteArray("BC") << 0 << -1;
// task 203692
- static const char h19[] = {'x', 0x00, 0xe7, 0x25, 0x1c, 0x0a};
+ static const char h19[] = {'x', 0x00, (char)0xe7, 0x25, 0x1c, 0x0a};
static const char n19[] = {0x00, 0x00, 0x01, 0x00};
QTest::newRow( "19" ) << QByteArray(h19, sizeof(h19))
<< QByteArray(n19, sizeof(n19)) << 0 << -1;
QTest::newRow( "24" ) << QByteArray("aBc") << QByteArray("BC") << 0 << -1;
// task 203692
- static const char h25[] = {0x00, 0xbc, 0x03, 0x10, 0x0a };
+ static const char h25[] = {0x00, (char)0xbc, 0x03, 0x10, 0x0a };
static const char n25[] = {0x00, 0x00, 0x01, 0x00};
QTest::newRow( "25" ) << QByteArray(h25, sizeof(h25))
<< QByteArray(n25, sizeof(n25)) << 0 << -1;
--- /dev/null
+load(qttest_p4)
+QT = core
+
+contains(QT_CONFIG,dbus): {
+ SOURCES += tst_qdbusconnection_no_bus.cpp
+ QT += dbus
+} else {
+ SOURCES += ../qdbusmarshall/dummy.cpp
+}
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qcoreapplication.h>
+#include <qdebug.h>
+
+#include <QtTest/QtTest>
+#include <QtDBus/QtDBus>
+
+#include <stdlib.h>
+
+/* This test uses an appless main, to ensure that no D-Bus stuff is implicitly done
+ It also sets the magic "QT_SIMULATE_DBUS_LIBFAIL" env variable, that is only available
+ in developer builds. That env variable simulates a D-Bus library load fail.
+
+ In no case should the QDBus module crash because D-Bus libs couldn't be loaded */
+
+class tst_QDBusConnectionNoBus : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QDBusConnectionNoBus()
+ {
+ ::setenv("DBUS_SESSION_BUS_ADDRESS", "unix:abstract=/tmp/does_not_exist", 1);
+ ::setenv("QT_SIMULATE_DBUS_LIBFAIL", "1", 1);
+ }
+
+private slots:
+ void connectToBus();
+};
+
+
+void tst_QDBusConnectionNoBus::connectToBus()
+{
+ int argc = 0;
+ QCoreApplication app(argc, 0);
+
+ QDBusConnection con = QDBusConnection::sessionBus();
+
+ QVERIFY(true); // if we didn't crash here, the test passed :)
+}
+
+QTEST_APPLESS_MAIN(tst_QDBusConnectionNoBus)
+
+#include "tst_qdbusconnection_no_bus.moc"
+
void testFlag() const;
void testFlagZeroFlag() const;
void testFlagMultiBits() const;
+ void constExpr();
};
void tst_QFlags::testFlag() const
}
}
+template <int N, typename T> bool verifyConstExpr(T n) { return n == N; }
+
+void tst_QFlags::constExpr()
+{
+#ifdef Q_COMPILER_CONSTEXPR
+ Qt::MouseButtons btn = Qt::LeftButton | Qt::RightButton;
+ switch (btn) {
+ case Qt::LeftButton: QVERIFY(false); break;
+ case Qt::RightButton: QVERIFY(false); break;
+ case Qt::LeftButton | Qt::RightButton: QVERIFY(true); break;
+ default: QVERIFY(false);
+ }
+
+ QVERIFY(verifyConstExpr<(Qt::LeftButton | Qt::RightButton) & Qt::LeftButton>(Qt::LeftButton));
+ QVERIFY(verifyConstExpr<(Qt::LeftButton | Qt::RightButton) & Qt::MiddleButton>(0));
+ QVERIFY(verifyConstExpr<(Qt::LeftButton | Qt::RightButton) | Qt::MiddleButton>(Qt::LeftButton | Qt::RightButton | Qt::MiddleButton));
+ QVERIFY(verifyConstExpr<~(Qt::LeftButton | Qt::RightButton)>(~(Qt::LeftButton | Qt::RightButton)));
+ QVERIFY(verifyConstExpr<Qt::MouseButtons(Qt::LeftButton) ^ Qt::RightButton>(Qt::LeftButton ^ Qt::RightButton));
+ QVERIFY(verifyConstExpr<Qt::MouseButtons(0)>(0));
+ QVERIFY(verifyConstExpr<Qt::MouseButtons(Qt::RightButton) & 0xff>(Qt::RightButton));
+ QVERIFY(verifyConstExpr<Qt::MouseButtons(Qt::RightButton) | 0xff>(0xff));
+
+ QVERIFY(!verifyConstExpr<Qt::RightButton>(!Qt::MouseButtons(Qt::LeftButton)));
+#endif
+}
+
+
QTEST_MAIN(tst_QFlags)
#include "tst_qflags.moc"
{
int count = testWidget->count();
- // Boundry Checking
+ // Boundary Checking
testWidget->addItem(0);
QCOMPARE(testWidget->count(), count);
{
int count = testWidget->count();
- // Boundry Checking
+ // Boundary Checking
testWidget->addItems(QStringList());
QCOMPARE(testWidget->count(), count);
void tst_QListWidget::openPersistentEditor()
{
- // Boundry checking
+ // Boundary checking
testWidget->openPersistentEditor(0);
QListWidgetItem *item = new QListWidgetItem(QString("%1").arg(testWidget->count()));
testWidget->openPersistentEditor(item);
QTest::qWait(1000);
#endif
- // Boundry checking
+ // Boundary checking
int childCount = testWidget->viewport()->children().count();
testWidget->closePersistentEditor(0);
QListWidgetItem *item = new QListWidgetItem(QString("%1").arg(testWidget->count()));
void tst_QListWidget::setItemHidden()
{
- // Boundry checking
+ // Boundary checking
testWidget->setItemHidden(0, true);
testWidget->setItemHidden(0, false);
for (int i = 0; i < fill; ++i)
testWidget->addItem(QString("%1").arg(i));
- // Boundry checking
+ // Boundary checking
testWidget->setCurrentItem((QListWidgetItem *)0);
QCOMPARE((QListWidgetItem *)0, testWidget->currentItem());
QListWidgetItem item;
for (int i = 0; i < fill; ++i)
testWidget->addItem(QString("%1").arg(i));
- // Boundry checking
+ // Boundary checking
testWidget->setCurrentRow(-1);
QCOMPARE(-1, testWidget->currentRow());
testWidget->setCurrentRow(testWidget->count());
void tst_QListWidget::editItem()
{
- // Boundry checking
+ // Boundary checking
testWidget->editItem(0);
QListWidgetItem *item = new QListWidgetItem(QString("%1").arg(testWidget->count()));
testWidget->editItem(item);
{
// This really just tests that the items that are returned are converted from index's to items correctly.
- // Boundry checking
+ // Boundary checking
QCOMPARE(testWidget->findItems("GirlsCanWearJeansAndCutTheirHairShort", Qt::MatchExactly).count(), 0);
populate();
/*!
Test plan:
- insertItem (all flavours and combinations)
+ insertItem (all flavors and combinations)
removing menu items
clearing the menu
releaseThread();
waitForThread();
- // mutex has been explicity relocked via QMutexLocker
+ // mutex has been explicitly relocked via QMutexLocker
QVERIFY(!thread->mutex.tryLock());
releaseThread();
void dontInsertPartialContentIntoTheCache();
+ void httpUserAgent();
+
// NOTE: This test must be last!
void parentingRepliesToTheApp();
};
// only compare when the header is set.
if (reply->header(QNetworkRequest::ContentLengthHeader).isValid())
QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), reference.size());
+
+ // We know our internal server is apache..
+ if (qstrcmp(QTest::currentDataTag(), "success-internal") == 0)
+ QVERIFY(reply->header(QNetworkRequest::ServerHeader).toString().contains("Apache"));
+
QCOMPARE(reply->readAll(), reference.readAll());
}
QNetworkRequest request(QUrl::fromLocalFile(file.fileName()));
QNetworkReplyPtr reply = manager.get(request);
- QVERIFY(reply->isFinished()); // a file should immediatly be done
+ QVERIFY(reply->isFinished()); // a file should immediately be done
DataReader reader(reply);
connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
void tst_QNetworkReply::ioGetFromHttpWithAuthSynchronous()
{
// verify that we do not enter an endless loop with synchronous calls and wrong credentials
- // the case when we succed with the login is tested in ioGetFromHttpWithAuth()
+ // the case when we succeed with the login is tested in ioGetFromHttpWithAuth()
QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfcs-auth/rfc3252.txt"));
request.setAttribute(
void tst_QNetworkReply::ioGetFromHttpWithProxyAuthSynchronous()
{
// verify that we do not enter an endless loop with synchronous calls and wrong credentials
- // the case when we succed with the login is tested in ioGetFromHttpWithAuth()
+ // the case when we succeed with the login is tested in ioGetFromHttpWithAuth()
QNetworkProxy proxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"));
QCOMPARE(reply->error(), QNetworkReply::OperationCanceledError);
QVERIFY(reply->isFinished());
- // Abort immediatly after the get()
+ // Abort immediately after the get()
QNetworkReplyPtr reply2 = manager.get(request);
connect(reply2, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
reply2->abort();
QCOMPARE(memoryCache->m_insertedUrls.count(), 0);
}
+void tst_QNetworkReply::httpUserAgent()
+{
+ QByteArray response("HTTP/1.0 200 OK\r\n\r\n");
+ MiniHttpServer server(response);
+ server.doClose = true;
+
+ QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort())));
+ request.setHeader(QNetworkRequest::UserAgentHeader, "abcDEFghi");
+ QNetworkReplyPtr reply = manager.get(request);
+
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(10);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY(reply->isFinished());
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+ QVERIFY(server.receivedData.contains("\r\nUser-Agent: abcDEFghi\r\n"));
+}
+
+
// NOTE: This test must be last testcase in tst_qnetworkreply!
void tst_QNetworkReply::parentingRepliesToTheApp()
{
}
}
-// A convinience / helper function for testcases. Return the first matching configuration.
+// A convenience / helper function for testcases. Return the first matching configuration.
// Ignores configurations in other than 'discovered' -state. Returns invalid (QNetworkConfiguration())
// if none found.
QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfiguration::Type configType) {
-
+
// Refresh configurations and derive configurations matching given parameters.
QNetworkConfigurationManager mgr;
QSignalSpy updateSpy(&mgr, SIGNAL(updateCompleted()));
-
+
mgr.updateConfigurations();
QTRY_NOOP(updateSpy.count() == 1);
if (updateSpy.count() != 1) {
}
QList<QNetworkConfiguration> discoveredConfigs = mgr.allConfigurations(QNetworkConfiguration::Discovered);
foreach(QNetworkConfiguration config, discoveredConfigs) {
- if ((config.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ if ((config.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
discoveredConfigs.removeOne(config);
} else if (config.type() != configType) {
// qDebug() << "Dumping config because type (IAP/SNAP) mismatches: " << config.name();
discoveredConfigs.removeOne(config);
} else if ((config.type() == QNetworkConfiguration::InternetAccessPoint) &&
- bearerType == "cellular") { // 'cellular' bearertype is for convinience
+ bearerType == "cellular") { // 'cellular' bearertype is for convenience
if (config.bearerName() != "2G" &&
config.bearerName() != "CDMA2000" &&
config.bearerName() != "WCDMA" &&
}
}
-// A convinience-function: updates configurations and waits that they are updated.
-void updateConfigurations()
+// A convenience-function: updates configurations and waits that they are updated.
+void updateConfigurations()
{
QNetworkConfigurationManager mgr;
QSignalSpy updateSpy(&mgr, SIGNAL(updateCompleted()));
QTRY_NOOP(updateSpy.count() == 1);
}
-// A convinience-function: updates and prints all available confiurations and their states
+// A convenience-function: updates and prints all available confiurations and their states
void printConfigurations()
{
QNetworkConfigurationManager manager;
}
}
-// A convinience function for test-cases: opens the given configuration and return
+// A convenience function for test-cases: opens the given configuration and return
// true if it was done gracefully.
bool openSession(QNetworkSession *session) {
bool result = true;
return result;
}
-// Helper function for closing opened session. Performs checks that
+// Helper function for closing opened session. Performs checks that
// session is closed gradefully (e.g. signals). Function does not delete
// the session. The lastSessionOnConfiguration (true by default) is used to
-// tell if there are more sessions open, basing on same configration. This
+// tell if there are more sessions open, basing on same configuration. This
// impacts the checks made.
bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration) {
if (!session) {
releaseThread();
waitForThread();
- // lock has been explicity relocked via QReadLocker
+ // lock has been explicitly relocked via QReadLocker
QVERIFY(!thread->lock.tryLockForWrite());
releaseThread();
/*
- A writer aquires a read-lock, a reader locks
+ A writer acquires a read-lock, a reader locks
the writer releases the lock, the reader gets the lock
*/
void tst_QReadWriteLock::readLockBlockRelease()
}
/*
- writer1 aquires a read-lock, writer2 blocks,
+ writer1 acquires a read-lock, writer2 blocks,
writer1 releases the lock, writer2 gets the lock
*/
void tst_QReadWriteLock::writeLockBlockRelease()
QVERIFY(threadDone);
}
/*
- Two readers aquire a read-lock, one writer attempts a write block,
+ Two readers acquire a read-lock, one writer attempts a write block,
the readers release their locks, the writer gets the lock.
*/
void tst_QReadWriteLock::multipleReadersBlockRelease()
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIIGTTCCBTWgAwIBAgIQEdaGfQ9bnSLsmQJm4rWlBjANBgkqhkiG9w0BAQUFADCB
+vjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2Ug
+YXQgaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykwNjE4MDYGA1UEAxMv
+VmVyaVNpZ24gQ2xhc3MgMyBFeHRlbmRlZCBWYWxpZGF0aW9uIFNTTCBTR0MgQ0Ew
+HhcNMDkwOTE1MDAwMDAwWhcNMTExMTA5MjM1OTU5WjCCAQAxEzARBgsrBgEEAYI3
+PAIBAxMCR0IxGzAZBgNVBA8TElYxLjAsIENsYXVzZSA1LihiKTERMA8GA1UEBRMI
+U0MwNDU1NTExCzAJBgNVBAYTAkdCMRAwDgYDVQQRFAdFSDMgNlVZMRAwDgYDVQQI
+EwdMb3RoaWFuMRIwEAYDVQQHFAlFZGluYnVyZ2gxFjAUBgNVBAkUDTM0IEZldHRl
+cyBSb3cxLTArBgNVBAoUJFRoZSBSb3lhbCBCYW5rIG9mIFNjb3RsYW5kIEdyb3Vw
+IFBsYzEVMBMGA1UECxQMV2ViIFNlcnZpY2VzMRYwFAYDVQQDFA13d3cubndvbGIu
+Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw4bRz9mxrbicnYun
+uYoobkfDBjmmJKpSDBbcZCsZDWyLsLvoZh2Ez6Ux9GAbf4m5pLoIQnzQORy40NAt
+bNDFhMJV0Iq65ju8qdYaUaWUdrxkLiwrIsiZwUMgcDOwdOvgO4qTev2OjkQg6syj
+J+3HTaRrqekfrV5RvBNZ8vPVXK3cWERykzxwqXHwr9QL/n3wqDn4hCOb11Ic2rUf
+H9TcPvxv7eFFnGL4ZJ3EU83tE/CmOYgz086BUDBKSvOHqHt2QWiPN/tHAgwfHYKj
+eYCMWM21G0rDugeN+urZN+p364kO+VygBxnNIPSr/ZY+4DCdjaKGe8sOJdvI6ip5
+4a1q3QIDAQABo4ICADCCAfwwCQYDVR0TBAIwADAdBgNVHQ4EFgQUX5AjzSTKUsk2
+KfB+nbH+CODuafAwCwYDVR0PBAQDAgWgMD4GA1UdHwQ3MDUwM6AxoC+GLWh0dHA6
+Ly9FVkludGwtY3JsLnZlcmlzaWduLmNvbS9FVkludGwyMDA2LmNybDBEBgNVHSAE
+PTA7MDkGC2CGSAGG+EUBBxcGMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LnZl
+cmlzaWduLmNvbS9ycGEwNAYDVR0lBC0wKwYIKwYBBQUHAwEGCCsGAQUFBwMCBglg
+hkgBhvhCBAEGCisGAQQBgjcKAwMwHwYDVR0jBBgwFoAUTkPIHXbvN1N6T/JYb5Tz
+OOLVvd8wdgYIKwYBBQUHAQEEajBoMCsGCCsGAQUFBzABhh9odHRwOi8vRVZJbnRs
+LW9jc3AudmVyaXNpZ24uY29tMDkGCCsGAQUFBzAChi1odHRwOi8vRVZJbnRsLWFp
+YS52ZXJpc2lnbi5jb20vRVZJbnRsMjAwNi5jZXIwbgYIKwYBBQUHAQwEYjBgoV6g
+XDBaMFgwVhYJaW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUS2u5KJYGDLvQUjibKaxL
+B4shBRgwJhYkaHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nbzEuZ2lmMA0G
+CSqGSIb3DQEBBQUAA4IBAQCT64k2YepUu257B3pA4pjbKr/dmlOztUYS/IAtlJpo
+As+R+T9dohGP+4liqHtlMMSKPRnwmSCj/KucJJ9UnIC89D3bVAP1Drvk5+gTwGZ5
+JkqPQqZsfEaeihmf8iu9stkYSQxMJcr24S4VEiGt2rdHhESq0OUel4SkMhlmSp5P
+sZxqX1HByBJnsF4bcvIY3C4eTrso5awqNgomGhxizJWmK8/sdEcys82SHgSjG4Bp
+05gUpXQrLTqWXDDOg5Uy745Gc8TpgqW1ZfpGg7EkjJX7EhBSKF0/2cNKVYUE9bnO
+VGd7vK10NOhK7Uk9CkDALK+MvIIkxmRBmAFuQ4D+eqNF
+-----END CERTIFICATE-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 11 (0xb)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: CN=Westpoint Certificate Test CA, ST=Lancashire, C=UK/emailAddress=ca@example.com, O=Westpoint Certificate Test Root Certification Authority
+ Validity
+ Not Before: Jun 26 19:36:40 2011 GMT
+ Not After : Jun 23 19:36:40 2021 GMT
+ Subject: CN=example.com/emailAddress=test@example.com/favouriteDrink=tequila
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:a5:88:9c:fd:1b:8d:26:90:7d:ed:b2:66:14:09:
+ 88:9f:c5:96:87:97:84:33:db:fd:a9:32:20:d0:4d:
+ 03:ce:34:a6:b3:e2:db:33:27:e5:5b:09:3b:6f:49:
+ 36:c8:99:63:88:4c:33:f2:55:bc:04:02:07:50:59:
+ 6a:34:52:4c:83:74:cb:d5:54:b5:a9:41:91:07:0e:
+ cf:50:3b:87:09:a5:5f:d8:71:f3:ee:d8:10:6d:5c:
+ 5d:69:ab:dc:98:d7:1a:38:63:c6:15:4e:d7:31:19:
+ 96:4c:db:be:d3:32:9d:ad:8b:1d:85:1b:aa:cf:d1:
+ b1:a4:ce:bf:5a:0f:30:a0:63
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Authority Information Access:
+ OCSP - URI:http://ocsp.example.com:8888/
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 21:55:2f:82:17:e6:8c:2c:39:af:2a:ce:b7:83:7f:cf:76:ce:
+ 25:39:b5:08:3c:9b:33:a2:9b:f7:3f:df:7d:67:7b:11:c7:e3:
+ ac:6f:59:c0:4f:25:3b:6d:3c:ec:3e:c2:0d:4c:a4:43:dd:4f:
+ c4:4c:5a:67:9d:a9:7a:91:c3:48:ed:40:5e:4d:6f:18:46:38:
+ 9c:e2:9a:7f:c9:d8:26:0c:35:fa:60:87:67:45:56:42:81:ba:
+ 4b:b6:03:6f:6c:7d:d1:f9:78:a1:08:9e:4a:f1:00:07:4b:ca:
+ ec:a4:1d:26:ad:63:46:63:5f:b2:64:2e:d3:cd:80:35:87:4f:
+ c4:16:1a:91:97:50:95:16:31:c5:97:49:70:19:68:a9:a8:6c:
+ 0f:c3:5b:8f:6a:1f:3f:e7:3b:ba:48:76:2c:b0:8d:b3:de:ce:
+ 7b:c7:bf:0f:80:34:7c:73:d5:d6:45:63:83:02:c5:4d:73:9b:
+ 66:8a:3a:66:dc:0c:9f:75:1a:a7:15:d1:1d:7f:12:af:f4:5d:
+ 9c:80:99:55:9b:26:69:ec:76:11:fe:4e:65:f7:57:7d:32:bb:
+ 9a:25:51:76:f5:68:99:2a:d2:a5:53:17:87:b6:ad:08:f1:24:
+ db:6f:45:07:d2:f1:60:50:ac:a0:d0:b7:0b:45:aa:e2:27:38:
+ 1f:4c:41:a3
+-----BEGIN CERTIFICATE-----
+MIIDOzCCAiOgAwIBAgIBCzANBgkqhkiG9w0BAQUFADCBqzEmMCQGA1UEAxMdV2Vz
+dHBvaW50IENlcnRpZmljYXRlIFRlc3QgQ0ExEzARBgNVBAgTCkxhbmNhc2hpcmUx
+CzAJBgNVBAYTAlVLMR0wGwYJKoZIhvcNAQkBFg5jYUBleGFtcGxlLmNvbTFAMD4G
+A1UEChM3V2VzdHBvaW50IENlcnRpZmljYXRlIFRlc3QgUm9vdCBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eTAeFw0xMTA2MjYxOTM2NDBaFw0yMTA2MjMxOTM2NDBaMFAx
+FDASBgNVBAMTC2V4YW1wbGUuY29tMR8wHQYJKoZIhvcNAQkBFhB0ZXN0QGV4YW1w
+bGUuY29tMRcwFQYKCZImiZPyLGQBBRMHdGVxdWlsYTCBnzANBgkqhkiG9w0BAQEF
+AAOBjQAwgYkCgYEApYic/RuNJpB97bJmFAmIn8WWh5eEM9v9qTIg0E0DzjSms+Lb
+MyflWwk7b0k2yJljiEwz8lW8BAIHUFlqNFJMg3TL1VS1qUGRBw7PUDuHCaVf2HHz
+7tgQbVxdaavcmNcaOGPGFU7XMRmWTNu+0zKdrYsdhRuqz9GxpM6/Wg8woGMCAwEA
+AaNIMEYwCQYDVR0TBAIwADA5BggrBgEFBQcBAQQtMCswKQYIKwYBBQUHMAGGHWh0
+dHA6Ly9vY3NwLmV4YW1wbGUuY29tOjg4ODgvMA0GCSqGSIb3DQEBBQUAA4IBAQAh
+VS+CF+aMLDmvKs63g3/Pds4lObUIPJszopv3P999Z3sRx+Osb1nATyU7bTzsPsIN
+TKRD3U/ETFpnnal6kcNI7UBeTW8YRjic4pp/ydgmDDX6YIdnRVZCgbpLtgNvbH3R
++XihCJ5K8QAHS8rspB0mrWNGY1+yZC7TzYA1h0/EFhqRl1CVFjHFl0lwGWipqGwP
+w1uPah8/5zu6SHYssI2z3s57x78PgDR8c9XWRWODAsVNc5tmijpm3AyfdRqnFdEd
+fxKv9F2cgJlVmyZp7HYR/k5l91d9MruaJVF29WiZKtKlUxeHtq0I8STbb0UH0vFg
+UKyg0LcLRariJzgfTEGj
+-----END CERTIFICATE-----
void blacklistedCertificates();
void toText();
void multipleCommonNames();
+ void subjectAndIssuerAttributes();
// ### add tests for certificate bundles (multiple certificates concatenated into a single
// structure); both PEM and DER formatted
QVERIFY(commonNames.contains(QString("www2.example.com")));
}
+void tst_QSslCertificate::subjectAndIssuerAttributes()
+{
+ QList<QSslCertificate> certList =
+ QSslCertificate::fromPath(SRCDIR "more-certificates/test-cn-with-drink-cert.pem");
+ QVERIFY2(certList.count() > 0, "Please run this test from the source directory");
+
+ QList<QByteArray> attributes = certList[0].subjectInfoAttributes();
+ QVERIFY(attributes.contains(QByteArray("favouriteDrink")));
+ attributes.clear();
+
+ certList = QSslCertificate::fromPath(SRCDIR "more-certificates/natwest-banking.pem");
+ QVERIFY2(certList.count() > 0, "Please run this test from the source directory");
+
+ attributes = certList[0].subjectInfoAttributes();
+ QVERIFY(attributes.contains(QByteArray("1.3.6.1.4.1.311.60.2.1.3")));
+}
+
#endif // QT_NO_OPENSSL
QTEST_MAIN(tst_QSslCertificate)
void writeBigChunk();
void blacklistedCertificates();
void setEmptyDefaultConfiguration();
+ void versionAccessors();
static void exitLoop()
{
QVERIFY2(!socket->waitForEncrypted(4000), qPrintable(socket->errorString()));
}
+void tst_QSslSocket::versionAccessors()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ qDebug() << QSslSocket::sslLibraryVersionString();
+ qDebug() << QString::number(QSslSocket::sslLibraryVersionNumber(), 16);
+}
+
#endif // QT_NO_OPENSSL
QTEST_MAIN(tst_QSslSocket)
void QTBUG9281_arg_locale();
void toUpperLower_icu();
+ void literals();
};
typedef QList<int> IntList;
// the cleanup function will restore the default locale
}
+void tst_QString::literals()
+{
+#if defined(QT_QSTRING_UNICODE_MARKER) && (defined(Q_COMPILER_LAMBDA) || defined(Q_CC_GNU))
+ QString str(QStringLiteral("abcd"));
+
+ QVERIFY(str.length() == 4);
+ QVERIFY(str == QLatin1String("abcd"));
+ QVERIFY(str.data_ptr()->ref == -1);
+ QVERIFY(str.data_ptr()->offset == 0);
+
+ const QChar *s = str.constData();
+ QString str2 = str;
+ QVERIFY(str2.constData() == s);
+
+ // detach on non const access
+ QVERIFY(str.data() != s);
+
+ QVERIFY(str2.constData() == s);
+ QVERIFY(str2.data() != s);
+
+#else
+ QSKIP("Only tested on c++0x compliant compiler or gcc", SkipAll);
+#endif
+}
+
QTEST_APPLESS_MAIN(tst_QString)
window2->setStyleSheet("");
qApp->setStyle(0);
- qApp->setStyleSheet("may_insanity_prevail { }"); // app has styleshet
+ qApp->setStyleSheet("may_insanity_prevail { }"); // app has stylesheet
QCOMPARE(window1->style(), qApp->style());
QCOMPARE(window1->style()->metaObject()->className(), "QStyleSheetStyle");
QCOMPARE(widget1->style()->metaObject()->className(), "QStyleSheetStyle"); // check the child
start.append("?>");
}
- /* When 0xEFBFBF is preceeded by what seems to be an arbitrary character,
+ /* When 0xEFBFBF is preceded by what seems to be an arbitrary character,
* QTextCodec fails to flag it. */
{
QByteArray start("B");
cursor.setPosition(6); // somewhere in the long paragraph.
cursor.select(QTextCursor::LineUnderCursor);
- // since we are not yet layed-out, we expect the whole paragraph to be selected.
+ // since we are not yet laid-out, we expect the whole paragraph to be selected.
QCOMPARE(cursor.position(), 77);
QCOMPARE(cursor.anchor(), 4);
}
QT += core-private gui-private
HEADERS +=
SOURCES += tst_qtextlayout.cpp
+DEFINES += QT_COMPILES_IN_HARFBUZZ
INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/harfbuzz/src
symbian {
{
QVector<QString> myvec;
- // TODO: is this guarenteed? seems a safe assumption, but I suppose preallocation of a
+ // TODO: is this guaranteed? seems a safe assumption, but I suppose preallocation of a
// few items isn't an entirely unforseeable possibility.
QVERIFY(myvec.capacity() == 0);
CHECK_PAGE_INIT(11, 10, 11, 10, 10, 10);
// Now, turn on the option and check that they're called at the
- // appropiate times (which aren't the same).
+ // appropriate times (which aren't the same).
wizard.setOption(QWizard::IndependentPages, true);
CHECK_PAGE_INIT(11, 10, 11, 10, 10, 10);
releaseThread();
waitForThread();
- // lock has been explicity relocked via QWriteLocker
+ // lock has been explicitly relocked via QWriteLocker
QVERIFY(!thread->lock.tryLockForWrite());
releaseThread();
// At this point w has a windowsurface but it's completely covered by
// the directpainter so nothing will be painted here and the
- // windowsurface contains unitialized data.
+ // windowsurface contains uninitialized data.
QApplication::processEvents();
QCOMPARE(p.allocatedRegion(), QRegion(r));
QCOMPARE(w.visibleRegion(), QRegion());
- fillWindowSurface(&w, Qt::black); // fill with "unitialized" data
+ fillWindowSurface(&w, Qt::black); // fill with "uninitialized" data
p.setRegion(QRegion());
QApplication::processEvents();
QCOMPARE(p.allocatedRegion(), QRegion(r));
QCOMPARE(w.visibleRegion(), QRegion());
- fillWindowSurface(&w, Qt::black); // fill with "unitialized" data
+ fillWindowSurface(&w, Qt::black); // fill with "uninitialized" data
p.setRegion(QRegion());
QFETCH(QString, str);
- // second and third time we call this it shoud FAIL
+ // second and third time we call this it should FAIL
QCOMPARE(str, QString("hello0"));
printf("test2 end\n");
**
****************************************************************************/
/*
- * This programm takes a *.ui file and an output dir as argument in order to
+ * This program takes a *.ui file and an output dir as argument in order to
* create a screenshot of the widget defined in the ui file.
*
* The screenshot is saved in the output dir (default current dir), ".png" is
void tst_qurl::qmlPropertyWriteUseCase()
{
- QUrl base("file:///home/user/qt/demos/declarative/samegame/SamegameCore/");
+ QUrl base("file:///home/user/qt/examples/declarative/samegame/SamegameCore/");
QString str("pics/redStar.png");
QBENCHMARK {
}
# install
-target.path = $$[QT_INSTALL_DEMOS]/chip
+target.path = $$[QT_INSTALL_EXAMPLES]/qtbase/graphicsview/chip
sources.files = $$SOURCES $$HEADERS $$RESOURCES *.png *.pro *.html *.doc images
-sources.path = $$[QT_INSTALL_DEMOS]/chip
+sources.path = $$[QT_INSTALL_EXAMPLES]/qtbase/graphicsview/chip
INSTALLS += target sources
layout->addWidget(view);
setLayout(layout);
- setWindowTitle(tr("Chip Demo"));
+ setWindowTitle(tr("Chip Example"));
}
void MainWindow::populateScene()
populateScene();
setScene(scene);
- setWindowTitle(tr("Chip Demo"));
+ setWindowTitle(tr("Chip Example"));
}
void ChipTester::setAntialias(bool enabled)
void httpDownloadPerformance();
void httpDownloadPerformanceDownloadBuffer_data();
void httpDownloadPerformanceDownloadBuffer();
+ void httpsRequestChain();
};
void tst_qnetworkreply::httpLatency()
}
}
+
+class HttpsRequestChainHelper : public QObject {
+ Q_OBJECT
+public:
+ QList<QNetworkRequest> requestList;
+
+ QElapsedTimer timeOneRequest;
+ QList<qint64> timeList;
+
+ QElapsedTimer globalTime;
+
+ QNetworkAccessManager manager;
+
+ HttpsRequestChainHelper() {
+ }
+public slots:
+ void doNextRequest() {
+ // all requests done
+ if (requestList.isEmpty()) {
+ QTestEventLoop::instance().exitLoop();
+ return;
+ }
+
+ if (qobject_cast<QNetworkReply*>(sender()) == 0) {
+ // first start after DNS lookup, start timer
+ globalTime.start();
+ }
+ QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
+ if (reply) {
+ QVERIFY(reply->error() == QNetworkReply::NoError);
+ qDebug() << "time =" << timeOneRequest.elapsed() << "ms";
+ timeList.append(timeOneRequest.elapsed());
+ }
+
+ QNetworkRequest request = requestList.takeFirst();
+ timeOneRequest.restart();
+ reply = manager.get(request);
+ QObject::connect(reply, SIGNAL(sslErrors( const QList<QSslError> &)), reply, SLOT(ignoreSslErrors()));
+ QObject::connect(reply, SIGNAL(finished()), this, SLOT(doNextRequest()));
+ }
+
+};
+
+void tst_qnetworkreply::httpsRequestChain()
+{
+ int count = 10;
+
+ QNetworkRequest request(QUrl("https://" + QtNetworkSettings::serverName() + "/fluke.gif"));
+ //QNetworkRequest request(QUrl("https://www.nokia.com/robots.txt"));
+ // Disable keep-alive so we have the full re-connecting of TCP.
+ request.setRawHeader("Connection", "close");
+
+ HttpsRequestChainHelper helper;
+ for (int i = 0; i < count; i++)
+ helper.requestList.append(request);
+
+ // Warm up DNS cache and then immediatly start HTTP
+ QHostInfo::lookupHost(QtNetworkSettings::serverName(), &helper, SLOT(doNextRequest()));
+ //QHostInfo::lookupHost("www.nokia.com", &helper, SLOT(doNextRequest()));
+
+ // we can use QBENCHMARK_ONCE when we find out how to make it really run once.
+ // there is still a warmup-run :(
+
+ //QBENCHMARK_ONCE {
+ QTestEventLoop::instance().enterLoop(40);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ //}
+
+ qint64 elapsed = helper.globalTime.elapsed();
+
+ qint64 average = (elapsed / count);
+
+ qSort(helper.timeList);
+ qint64 median = helper.timeList.at(5);
+
+ qDebug() << "Total:" << elapsed << " Average:" << average << " Median:" << median;
+
+}
+
+
+
QTEST_MAIN(tst_qnetworkreply)
#include "tst_qnetworkreply.moc"