summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dist/changes-4.7.028
-rw-r--r--doc/src/development/developing-on-mac.qdoc5
-rw-r--r--doc/src/frameworks-technologies/accessible.qdoc3
-rw-r--r--doc/src/frameworks-technologies/dbus-adaptors.qdoc3
-rw-r--r--doc/src/frameworks-technologies/phonon.qdoc2
-rw-r--r--doc/src/getting-started/known-issues.qdoc10
-rw-r--r--doc/src/howtos/HWacceleration.qdoc15
-rw-r--r--doc/src/howtos/accelerators.qdoc1
-rw-r--r--doc/src/howtos/appicon.qdoc1
-rw-r--r--doc/src/howtos/guibooks.qdoc1
-rw-r--r--doc/src/howtos/qtdesigner.qdoc1
-rw-r--r--doc/src/howtos/restoring-geometry.qdoc2
-rw-r--r--doc/src/howtos/session.qdoc2
-rw-r--r--doc/src/howtos/sharedlibrary.qdoc2
-rw-r--r--doc/src/howtos/timers.qdoc2
-rw-r--r--doc/src/overviews.qdoc19
-rw-r--r--doc/src/platforms/platform-notes.qdoc2
-rw-r--r--doc/src/sql-programming/qsqldatatype-table.qdoc21
-rw-r--r--doc/src/sql-programming/sql-driver.qdoc2
-rw-r--r--doc/src/sql-programming/sql-programming.qdoc6
-rw-r--r--doc/src/widgets-and-layouts/styles.qdoc12
-rw-r--r--doc/src/widgets-and-layouts/widgets.qdoc202
-rw-r--r--doc/src/windows-and-dialogs/mainwindow.qdoc14
-rw-r--r--examples/declarative/dial/content/Dial.qml6
-rw-r--r--examples/declarative/dial/dial-example.qml10
-rw-r--r--examples/network/bearermonitor/bearermonitor.cpp3
-rw-r--r--examples/network/bearermonitor/sessionwidget.cpp12
-rw-r--r--examples/network/bearermonitor/sessionwidget.h5
-rw-r--r--examples/network/bearermonitor/sessionwidget.ui2
-rw-r--r--src/gui/image/qicon.cpp23
-rw-r--r--src/gui/kernel/qcocoawindowdelegate_mac.mm21
-rw-r--r--src/gui/kernel/qt_mac_p.h2
-rw-r--r--src/gui/kernel/qwidget.cpp22
-rw-r--r--src/gui/kernel/qwidget_p.h8
-rw-r--r--src/gui/styles/qgtkpainter.cpp16
-rw-r--r--src/gui/styles/qstylehelper.cpp74
-rw-r--r--src/plugins/bearer/symbian/qnetworksession_impl.cpp403
-rw-r--r--src/plugins/bearer/symbian/qnetworksession_impl.h15
-rw-r--r--src/plugins/bearer/symbian/symbianengine.cpp248
-rw-r--r--src/plugins/bearer/symbian/symbianengine.h27
-rw-r--r--tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp7
-rw-r--r--tests/auto/qnetworksession/lackey/main.cpp24
-rw-r--r--tests/auto/qnetworksession/test/tst_qnetworksession.cpp391
-rw-r--r--tests/manual/bearerex/bearerex.cpp18
44 files changed, 1044 insertions, 649 deletions
diff --git a/dist/changes-4.7.0 b/dist/changes-4.7.0
index 6bf7ea5..1e3a69c 100644
--- a/dist/changes-4.7.0
+++ b/dist/changes-4.7.0
@@ -33,7 +33,6 @@ New features
- QNetworkSession, QNetworkConfiguration, QNetworkConfigurationManager
* New bearer management classes added.
-
Third party components
----------------------
@@ -68,6 +67,9 @@ QtGui
functions, and replaced them with setCopyCount(), copyCount() and
supportsMultipleCopies().
+ - QPrintDialog/QPrinter
+ * Added support for printing the current page.
+
- QCommonStyle
* Fixed a bug that led to missing text pixels in QTabBar when using
small font sizes. (QTBUG-7137)
@@ -76,12 +78,30 @@ QtGui
* Fixed rendering bugs when scrolling graphics items with drop
shadows.
+ - QGraphicsItem
+ * [QTBUG-8112] itemChange() is now called when transformation
+ properties change (setRotation, setScale, setTransformOriginPoint).
+
+ - QGraphicsTextItem
+ * [QTBUG-7333] Fixed keyboard shortcuts not being triggered when the
+ the item has focus and something else has the same shortcut sequence.
+
+ - QGraphicsView
+ * [QTBUG-7438] Fixed viewport cursor getting reset when releasing
+ the mouse.
+
- QImage
- * [QTBUG-9640] Prevented unneccessary copy in
- QImage::setAlphaChannel().
- * Added QImage::bitPlaneCount(). (QTBUG-7982)
+ * [QTBUG-9640] Prevented unneccessary copy in QImage::setAlphaChannel().
+ * [QTBUG-7982] Added QImage::bitPlaneCount().
+
+ - QPicture
+ * [QTBUG-4974] Printing QPictures containing text to a high resolution
+ QPrinter would in many cases cause incorrect character spacing.
- QPainter
+ * Added QPainter::drawPixmapFragments(), which makes it possible to draw
+ pixmaps, or sub-rectangles of pixmaps, at various positions with
+ different scale, opacity and rotation.
* [QTBUG-10018] Fixed image drawing inconsistencies when drawing
1x1 source rects with rotating / shear / perspective transforms.
* Optimized various blending and rendering operations for ARM
diff --git a/doc/src/development/developing-on-mac.qdoc b/doc/src/development/developing-on-mac.qdoc
index 785858f..0c0af79 100644
--- a/doc/src/development/developing-on-mac.qdoc
+++ b/doc/src/development/developing-on-mac.qdoc
@@ -41,9 +41,8 @@
/*!
\page developing-on-mac.html
- \title Developing Qt Applications on Mac OS X
- \brief A overview of items to be aware of when developing Qt applications
- on Mac OS X
+ \title Developing Qt Applications for Mac OS X
+ \brief Information for developing Qt applications for Mac OS X
\ingroup platform-specific
\tableofcontents
diff --git a/doc/src/frameworks-technologies/accessible.qdoc b/doc/src/frameworks-technologies/accessible.qdoc
index 35f1c75..0aff214 100644
--- a/doc/src/frameworks-technologies/accessible.qdoc
+++ b/doc/src/frameworks-technologies/accessible.qdoc
@@ -47,7 +47,10 @@
/*!
\page accessible.html
\title Accessibility
+ \brief How to make your applications accessible to those with disabilities.
+
\ingroup technology-apis
+ \ingroup best-practices
\tableofcontents
diff --git a/doc/src/frameworks-technologies/dbus-adaptors.qdoc b/doc/src/frameworks-technologies/dbus-adaptors.qdoc
index 11c5998..3dd0e4d 100644
--- a/doc/src/frameworks-technologies/dbus-adaptors.qdoc
+++ b/doc/src/frameworks-technologies/dbus-adaptors.qdoc
@@ -42,8 +42,9 @@
/*!
\page usingadaptors.html
\title Using QtDBus Adaptors
- \ingroup technology-apis
+ \brief How to create and use DBus adaptors in Qt.
+ \ingroup technology-apis
\ingroup best-practices
Adaptors are special classes that are attached to any QObject-derived class
diff --git a/doc/src/frameworks-technologies/phonon.qdoc b/doc/src/frameworks-technologies/phonon.qdoc
index 61d7926..61b906e 100644
--- a/doc/src/frameworks-technologies/phonon.qdoc
+++ b/doc/src/frameworks-technologies/phonon.qdoc
@@ -42,7 +42,9 @@
/*!
\page phonon-overview.html
\title Phonon multimedia framework
+ \brief Using the Phonon multimedia framework in Qt.
\ingroup technology-apis
+ \ingroup best-practices
\tableofcontents
diff --git a/doc/src/getting-started/known-issues.qdoc b/doc/src/getting-started/known-issues.qdoc
index b73e15d..cedebf9 100644
--- a/doc/src/getting-started/known-issues.qdoc
+++ b/doc/src/getting-started/known-issues.qdoc
@@ -41,15 +41,15 @@
/*!
\page known-issues.html
- \title Known Issues in %VERSION%
+ \title Known Issues in this Qt Version
\ingroup platform-specific
- \brief A summary of known issues in Qt %VERSION% at the time of release.
+ \brief A summary of known issues in this Qt version at the time of release.
- An up-to-date list of known issues with Qt %VERSION% can be found via the
+ An up-to-date list of known issues can be found at
\l{http://bugreports.qt.nokia.com/}{Qt Bug Tracker}.
- For a list list of known bugs in Qt %VERSION%, see the \l{Task Tracker}
- on the Qt website.
+ For a list list of known bugs, see the \l{Task Tracker} at the Qt
+ website.
An overview of known issues may also be found at:
\l{http://qt.gitorious.org/qt/pages/QtKnownIssues}
diff --git a/doc/src/howtos/HWacceleration.qdoc b/doc/src/howtos/HWacceleration.qdoc
index fbc657c..c7b1a72 100644
--- a/doc/src/howtos/HWacceleration.qdoc
+++ b/doc/src/howtos/HWacceleration.qdoc
@@ -41,17 +41,20 @@
/*!
\page HWAcc_rendering.html
- \title Using hardware acceleration on embedded platforms.
+ \title Hardware Acceleration &amp Embedded Platforms.
+ \brief How to use hardware acceleration for fast rendering.
\ingroup best-practices
\section1 Abstract
+
This document describes how to use hardware acceleration for fast
- rendering on embedded platforms supported by Qt. In short, it explains
- how the graphics pipeline works. Since there might be differences to
- how the APIs are being used on different embedded platforms, a table
- links to documentation dedicated to platform specific documentation
- for each supported hardware acceleration API.
+ rendering on embedded platforms supported by Qt. In short, it
+ explains how the graphics pipeline works. Since there might be
+ differences to how the APIs are being used on different embedded
+ platforms, a table links to documentation dedicated to platform
+ specific documentation for each supported hardware acceleration
+ API.
\input platforms/emb-hardwareacceleration.qdocinc
diff --git a/doc/src/howtos/accelerators.qdoc b/doc/src/howtos/accelerators.qdoc
index 65f1def..b6ef5c2 100644
--- a/doc/src/howtos/accelerators.qdoc
+++ b/doc/src/howtos/accelerators.qdoc
@@ -42,6 +42,7 @@
/*!
\page accelerators.html
\title Standard Accelerator Keys
+ \brief Recommended accelerator keys.
\ingroup best-practices
diff --git a/doc/src/howtos/appicon.qdoc b/doc/src/howtos/appicon.qdoc
index dd39509..9377961 100644
--- a/doc/src/howtos/appicon.qdoc
+++ b/doc/src/howtos/appicon.qdoc
@@ -42,6 +42,7 @@
/*!
\page appicon.html
\title Setting the Application Icon
+ \brief How to set your application's icon.
\ingroup best-practices
diff --git a/doc/src/howtos/guibooks.qdoc b/doc/src/howtos/guibooks.qdoc
index 1a70670..bccfbe6 100644
--- a/doc/src/howtos/guibooks.qdoc
+++ b/doc/src/howtos/guibooks.qdoc
@@ -43,6 +43,7 @@
\page guibooks.html
\title Books about GUI Design
\ingroup best-practices
+ \brief Some recommended books about GUI design.
This is not a comprehensive list -- there are many other books worth
buying. Here we mention just a few user interface books that don't
diff --git a/doc/src/howtos/qtdesigner.qdoc b/doc/src/howtos/qtdesigner.qdoc
index 2dd7fcf..92041f0 100644
--- a/doc/src/howtos/qtdesigner.qdoc
+++ b/doc/src/howtos/qtdesigner.qdoc
@@ -42,6 +42,7 @@
/*!
\page qtdesigner-components.html
\title Creating and Using Components for Qt Designer
+ \brief How to create and use custom widget plugins.
\ingroup best-practices
\tableofcontents
diff --git a/doc/src/howtos/restoring-geometry.qdoc b/doc/src/howtos/restoring-geometry.qdoc
index 36c5e4f..e72b993 100644
--- a/doc/src/howtos/restoring-geometry.qdoc
+++ b/doc/src/howtos/restoring-geometry.qdoc
@@ -42,7 +42,7 @@
/*!
\page restoring-geometry.html
\title Restoring a Window's Geometry
-
+ \brief How to save &amp restore window geometry.
\ingroup best-practices
This document describes how to save and restore a \l{Window
diff --git a/doc/src/howtos/session.qdoc b/doc/src/howtos/session.qdoc
index e2e87a8..f53af04 100644
--- a/doc/src/howtos/session.qdoc
+++ b/doc/src/howtos/session.qdoc
@@ -42,7 +42,7 @@
/*!
\page session.html
\title Session Management
-
+ \brief How to do session management with Qt.
\ingroup best-practices
A \e session is a group of running applications, each of which has a
diff --git a/doc/src/howtos/sharedlibrary.qdoc b/doc/src/howtos/sharedlibrary.qdoc
index 70fc4db..ed803ed 100644
--- a/doc/src/howtos/sharedlibrary.qdoc
+++ b/doc/src/howtos/sharedlibrary.qdoc
@@ -42,7 +42,7 @@
/*!
\page sharedlibrary.html
\title Creating Shared Libraries
-
+ \brief How to create shared libraries.
\ingroup best-practices
The following sections list certain things that should be taken into
diff --git a/doc/src/howtos/timers.qdoc b/doc/src/howtos/timers.qdoc
index cfc2fb4..b001916 100644
--- a/doc/src/howtos/timers.qdoc
+++ b/doc/src/howtos/timers.qdoc
@@ -42,7 +42,7 @@
/*!
\page timers.html
\title Timers
- \brief How to use timers in your application.
+ \brief How to use Qt timers in your application.
\ingroup best-practices
diff --git a/doc/src/overviews.qdoc b/doc/src/overviews.qdoc
index 0b82388..c3c59af 100644
--- a/doc/src/overviews.qdoc
+++ b/doc/src/overviews.qdoc
@@ -117,13 +117,28 @@
*/
/*!
+ \group qt-sql
+ \title Using SQL in Qt
+ \brief Qt API's for using SQL.
+ \ingroup technology-apis
+ \ingroup best-practices
+
+ These pages document Qt's API's for using SQL database systems
+ in Qt applications.
+
+ \generatelist{related}
+*/
+
+/*!
\group best-practices
\title How-To's and Best Practices
\brief How-To Guides and Best Practices
- These documents provide guidelines and best practices explaining
- how to use Qt to solve specific technical problems.
+ These documents provide guidelines and best practices for using Qt
+ to solve specific technical problems. They are listed
+ alphabetically by the first word in the title, so scan the entire
+ list to find what you want.
\generatelist{related}
*/
diff --git a/doc/src/platforms/platform-notes.qdoc b/doc/src/platforms/platform-notes.qdoc
index 8f5b6a5..16e0c0f 100644
--- a/doc/src/platforms/platform-notes.qdoc
+++ b/doc/src/platforms/platform-notes.qdoc
@@ -517,7 +517,7 @@
Note that some modules rely on other modules. If your application uses
QtXmlPatterns, QtWebkit or QtScript it may still require \c NetworkServices
- \o as these modules rely on QtNetwork to go online.
+ as these modules rely on QtNetwork to go online.
For more information see the documentation of the individual Qt classes. If
a class does not mention Symbian capabilities, it requires none.
diff --git a/doc/src/sql-programming/qsqldatatype-table.qdoc b/doc/src/sql-programming/qsqldatatype-table.qdoc
index fc961f5..fb5fb49 100644
--- a/doc/src/sql-programming/qsqldatatype-table.qdoc
+++ b/doc/src/sql-programming/qsqldatatype-table.qdoc
@@ -41,19 +41,20 @@
/*!
\page sql-types.html
- \title Recommended Use of Data Types in Databases
+ \title Data Types for Qt-supported Database Systems
+ \brief Recommended data types for database systems
- \ingroup best-practices
+ \ingroup qt-sql
- \section1 Recommended Use of Types in Qt Supported Databases
+ \section1 Data Types for Qt Supported Database Systems
- This table shows the recommended data types used when extracting data
- from the databases supported in Qt. It is important to note that the
- types used in Qt are not necessarily valid as input to the specific
- database. One example could be that a double would work perfectly as
- input for floating point records in a database, but not necessarily
- as a storage format for output from the database since it would be stored
- with 64-bit precision in C++.
+ This table shows the recommended data types for extracting data from
+ the databases supported in Qt. Note that types used in Qt are not
+ necessarily valid as input types to a specific database
+ system. e.g., A double might work perfectly as input for floating
+ point records in a particular database, but not necessarily as a
+ storage format for output from that database, because it would be
+ stored with 64-bit precision in C++.
\tableofcontents
diff --git a/doc/src/sql-programming/sql-driver.qdoc b/doc/src/sql-programming/sql-driver.qdoc
index 6bccd83..f0e4e52 100644
--- a/doc/src/sql-programming/sql-driver.qdoc
+++ b/doc/src/sql-programming/sql-driver.qdoc
@@ -44,7 +44,7 @@
\title SQL Database Drivers
\brief How to configure and install QtSql drivers for supported databases.
- \ingroup best-practices
+ \ingroup qt-sql
The QtSql module uses driver \l{How to Create Qt
Plugins}{plugins} to communicate with the different database
diff --git a/doc/src/sql-programming/sql-programming.qdoc b/doc/src/sql-programming/sql-programming.qdoc
index f1f3e5e..b34810c 100644
--- a/doc/src/sql-programming/sql-programming.qdoc
+++ b/doc/src/sql-programming/sql-programming.qdoc
@@ -49,6 +49,7 @@
/*!
\page sql-programming.html
\title SQL Programming
+ \ingroup qt-sql
\nextpage Connecting to Databases
\brief Database integration for Qt applications.
@@ -118,6 +119,7 @@
/*!
\page sql-connecting.html
\title Connecting to Databases
+ \ingroup qt-sql
\contentspage SQL Programming
\previouspage SQL Programming
@@ -187,6 +189,7 @@
/*!
\page sql-sqlstatements.html
\title Executing SQL Statements
+ \ingroup qt-sql
\previouspage Connecting to Databases
\contentspage SQL Programming
@@ -337,6 +340,7 @@
/*!
\page sql-model.html
\title Using the SQL Model Classes
+ \ingroup qt-sql
\previouspage Executing SQL Statements
\contentspage SQL Programming
@@ -483,6 +487,7 @@
/*!
\page sql-presenting.html
\title Presenting Data in a Table View
+ \ingroup qt-sql
\previouspage Using the SQL Model Classes
\contentspage SQL Programming
@@ -587,6 +592,7 @@
/*!
\page sql-forms.html
\title Creating Data-Aware Forms
+ \ingroup qt-sql
\previouspage Presenting Data in a Table View
\contentspage SQL Programming
diff --git a/doc/src/widgets-and-layouts/styles.qdoc b/doc/src/widgets-and-layouts/styles.qdoc
index b4bec8c..31dfe40 100644
--- a/doc/src/widgets-and-layouts/styles.qdoc
+++ b/doc/src/widgets-and-layouts/styles.qdoc
@@ -47,15 +47,9 @@
/*!
\page style-reference.html
- \title Implementing Styles and Style Aware Widgets
+ \title Styles and Style Aware Widgets
\ingroup qt-gui-concepts
- \brief An overview of styles and the styling of widgets.
-
- \ingroup frameworks-technologies
-
- \previouspage Widget Classes
- \contentspage Widgets and Layouts
- \nextpage {Qt Style Sheets}{Style sheets}
+ \brief Styles and the styling of widgets.
Styles (classes that inherit QStyle) draw on behalf of widgets
and encapsulate the look and feel of a GUI. The QStyle class is
@@ -91,8 +85,6 @@
current style. This document shows how widgets draw themselves
and which possibilities the style gives them.
- \tableofcontents
-
\section1 Classes for Widget Styling
These classes are used to customize an application's appearance and
diff --git a/doc/src/widgets-and-layouts/widgets.qdoc b/doc/src/widgets-and-layouts/widgets.qdoc
index ac0bf77..9fe2d69 100644
--- a/doc/src/widgets-and-layouts/widgets.qdoc
+++ b/doc/src/widgets-and-layouts/widgets.qdoc
@@ -40,131 +40,121 @@
****************************************************************************/
/*!
- \page widgets-and-layouts.html
- \title Widgets and Layouts
- \ingroup qt-gui-concepts
-
- \ingroup frameworks-technologies
-
- \nextpage Widget Classes
-
- The primary elements for designing user interfaces in Qt are widgets and layouts.
-
- \section1 Widgets
-
- \l{Widget Classes}{Widgets} can display data and status information, receive
- user input, and provide a container for other widgets that should be grouped
- together. A widget that is not embedded in a parent widget is called a
- \l{Application Windows and Dialogs}{window}.
-
- \image parent-child-widgets.png A parent widget containing various child widgets.
-
- The QWidget class provides the basic capability to render to the screen, and to
- handle user input events. All UI elements that Qt provides are either subclasses
- of QWidget, or are used in connection with a QWidget subclass. Creating custom
- widgets is done by subclassing QWidget or a suitable subclass and reimplementing
- the virtual event handlers.
-
- \section1 Layouts
-
- \l{Layout Management}{Layouts} are an elegant and flexible way to automatically
- arrange child widgets within their container. Each widget reports its size requirements
- to the layout through the \l{QWidget::}{sizeHint} and \l{QWidget::}{sizePolicy}
- properties, and the layout distributes the available space accordingly.
-
- \table
- \row
- \o \image qgridlayout-with-5-children.png
- \o \image qformlayout-with-6-children.png
- \endtable
-
- \l{Qt Designer Manual}{\QD} is a powerful tool for interactively creating and
- arranging widgets in layouts.
-
- \section1 Widget Styles
-
- \l{Implementing Styles and Style Aware Widgets}{Styles} draw on behalf of widgets
- and encapsulate the look and feel of a GUI. Qt's built-in widgets use the QStyle
- class to perform nearly all of their drawing, ensuring that they look exactly like
- the equivalent native widgets.
+ \page widgets-and-layouts.html
+ \title Widgets and Layouts
+ \ingroup qt-gui-concepts
+ \brief The primary elements for designing user interfaces in Qt.
+
+ \section1 Widgets
+
+ Widgets are the primary elements for creating user interfaces in Qt.
+ \l{Widget Classes}{Widgets} can display data and status information,
+ receive user input, and provide a container for other widgets that
+ should be grouped together. A widget that is not embedded in a
+ parent widget is called a \l{Application Windows and
+ Dialogs}{window}.
+
+ \image parent-child-widgets.png A parent widget containing various child widgets.
+
+ The QWidget class provides the basic capability to render to the
+ screen, and to handle user input events. All UI elements that Qt
+ provides are either subclasses of QWidget, or are used in connection
+ with a QWidget subclass. Creating custom widgets is done by
+ subclassing QWidget or a suitable subclass and reimplementing the
+ virtual event handlers.
+
+ \section1 Layouts
+
+ \l{Layout Management}{Layouts} are an elegant and flexible way to
+ automatically arrange child widgets within their container. Each
+ widget reports its size requirements to the layout through the
+ \l{QWidget::}{sizeHint} and \l{QWidget::}{sizePolicy} properties,
+ and the layout distributes the available space accordingly.
+
+ \table
+ \row
+ \o \image qgridlayout-with-5-children.png
+ \o \image qformlayout-with-6-children.png
+ \endtable
+
+ \l{Qt Designer Manual}{\QD} is a powerful tool for interactively creating and
+ arranging widgets in layouts.
+
+ \section1 Widget Styles
+
+ \l{Implementing Styles and Style Aware Widgets}{Styles} draw on
+ behalf of widgets and encapsulate the look and feel of a GUI. Qt's
+ built-in widgets use the QStyle class to perform nearly all of their
+ drawing, ensuring that they look exactly like the equivalent native
+ widgets.
- \table
- \row
- \o \image windowsxp-tabwidget.png
- \o \image plastique-tabwidget.png
- \o \image macintosh-tabwidget.png
- \endtable
-
- \l{Qt Style Sheets} are a powerful mechanism that allows you to customize the
- appearance of widgets, in addition to what is already possible by subclassing QStyle.
-*/
-
-/*!
- \page widget-classes.html
- \title Widget Classes
+ \table
+ \row
+ \o \image windowsxp-tabwidget.png
+ \o \image plastique-tabwidget.png
+ \o \image macintosh-tabwidget.png
+ \endtable
- \contentspage Widgets and Layouts
- \nextpage Layout Management
+ \l{Qt Style Sheets} are a powerful mechanism that allows you to customize the
+ appearance of widgets, in addition to what is already possible by subclassing QStyle.
- Below you find a list of all widget classes in Qt. You can also browse the
- widget classes Qt provides in the various supported styles in the
- \l{Qt Widget Gallery}.
+ \section1 The Widget Classes
- \tableofcontents
+ The following sections list the widget classes. See the \l{Qt Widget
+ Gallery} for some examples.
- \section1 Basic Widgets
+ \section2 Basic Widgets
- These basic widgets (controls), such as buttons, comboboxes and scroll bars, are
- designed for direct use.
+ These basic widgets (controls), e.g. buttons, comboboxes and
+ scroll bars, are designed for direct use.
- \table
- \row
- \o \image windows-label.png
- \o \image windowsvista-pushbutton.png
- \o \image gtk-progressbar.png
- \row
- \o \image plastique-combobox.png
- \o \image macintosh-radiobutton.png
- \o \image cde-lineedit.png
- \endtable
+ \table
+ \row
+ \o \image windows-label.png
+ \o \image windowsvista-pushbutton.png
+ \o \image gtk-progressbar.png
+ \row
+ \o \image plastique-combobox.png
+ \o \image macintosh-radiobutton.png
+ \o \image cde-lineedit.png
+ \endtable
- \annotatedlist basicwidgets
+ \annotatedlist basicwidgets
- \section1 Advanced Widgets
+ \section2 Advanced Widgets
- Advanced GUI widgets such as tab widgets and progress bars provide more
- complex user interface controls.
+ Advanced GUI widgets, e.g. tab widgets and progress bars, provide
+ more complex user interface controls.
- \table
- \row
- \o \image windowsxp-treeview.png
- \o \image gtk-calendarwidget.png
- \o \image qundoview.png
- \endtable
+ \table
+ \row
+ \o \image windowsxp-treeview.png
+ \o \image gtk-calendarwidget.png
+ \o \image qundoview.png
+ \endtable
- \annotatedlist advanced
+ \annotatedlist advanced
- \table
- \row
- \o \image windowsvista-tabwidget.png
- \o \image macintosh-groupbox.png
- \endtable
+ \table
+ \row
+ \o \image windowsvista-tabwidget.png
+ \o \image macintosh-groupbox.png
+ \endtable
- \section1 Organizer Widgets
+ \section2 Organizer Widgets
- Classes like splitters, tab bars, button groups, etc are used to
- organize and group GUI primitives into more complex applications or
- dialogs.
+ Classes like splitters, tab bars, button groups, etc are used for
+ organizing and grouping GUI primitives into more complex
+ applications and dialogs.
- \annotatedlist organizers
+ \annotatedlist organizers
- \section1 Abstract Widget Classes
+ \section2 Abstract Widget Classes
- Abstract widget classes usable through subclassing. They are generally
- not usable in themselves, but provide functionality that can be used
- by inheriting these classes.
+ The abstract widget classes are base classes. They are not usable as
+ standalone classes but provide functionality when they are subclassed.
- \annotatedlist abstractwidgets
+ \annotatedlist abstractwidgets
*/
/*!
diff --git a/doc/src/windows-and-dialogs/mainwindow.qdoc b/doc/src/windows-and-dialogs/mainwindow.qdoc
index b282dab..c1e66d9 100644
--- a/doc/src/windows-and-dialogs/mainwindow.qdoc
+++ b/doc/src/windows-and-dialogs/mainwindow.qdoc
@@ -46,12 +46,11 @@
/*!
\page application-windows.html
- \title Application Windows and Dialogs
+ \title Window and Dialog Widgets
+ \brief Windows and Dialogs in Qt.
\ingroup qt-gui-concepts
\ingroup frameworks-technologies
- \nextpage The Application Main Window
-
A \l{Widgets Tutorial}{widget} that is not embedded in a parent widget is called a window.
Usually, windows have a frame and a title bar, although it is also possible to create
windows without such decoration using suitable window flags). In Qt, QMainWindow
@@ -165,12 +164,9 @@
/*!
\page mainwindow.html
- \title The Application Main Window
- \brief Everything you need for a typical modern main application window,
- including menus, toolbars, workspace, etc.
-
- \contentspage Application Windows and Dialogs
- \nextpage Dialog Windows
+ \title Application Main Window
+ \ingroup qt-gui-concepts
+ \brief Creating the application window.
\tableofcontents
diff --git a/examples/declarative/dial/content/Dial.qml b/examples/declarative/dial/content/Dial.qml
index f9ab3e3..6f24801 100644
--- a/examples/declarative/dial/content/Dial.qml
+++ b/examples/declarative/dial/content/Dial.qml
@@ -8,6 +8,7 @@ Item {
Image { source: "background.png" }
+//! [needle_shadow]
Image {
x: 93
y: 35
@@ -17,6 +18,8 @@ Item {
angle: needleRotation.angle
}
}
+//! [needle_shadow]
+//! [needle]
Image {
id: needle
x: 95; y: 33
@@ -33,5 +36,8 @@ Item {
}
}
}
+//! [needle]
+//! [overlay]
Image { x: 21; y: 18; source: "overlay.png" }
+//! [overlay]
}
diff --git a/examples/declarative/dial/dial-example.qml b/examples/declarative/dial/dial-example.qml
index 2e102b0..900954f 100644
--- a/examples/declarative/dial/dial-example.qml
+++ b/examples/declarative/dial/dial-example.qml
@@ -1,6 +1,7 @@
import Qt 4.7
import "content"
+//! [0]
Rectangle {
color: "#545454"
width: 300; height: 300
@@ -14,7 +15,10 @@ Rectangle {
Rectangle {
id: container
- anchors { bottom: parent.bottom; left: parent.left; right: parent.right; leftMargin: 20; rightMargin: 20; bottomMargin: 10 }
+ anchors { bottom: parent.bottom; left: parent.left
+ right: parent.right; leftMargin: 20; rightMargin: 20
+ bottomMargin: 10
+ }
height: 16
radius: 8
@@ -37,8 +41,10 @@ Rectangle {
MouseArea {
anchors.fill: parent
- drag.target: parent; drag.axis: Drag.XAxis; drag.minimumX: 2; drag.maximumX: container.width - 32
+ drag.target: parent; drag.axis: Drag.XAxis
+ drag.minimumX: 2; drag.maximumX: container.width - 32
}
}
}
}
+//! [0] \ No newline at end of file
diff --git a/examples/network/bearermonitor/bearermonitor.cpp b/examples/network/bearermonitor/bearermonitor.cpp
index 4a6c6ff..0d98eff 100644
--- a/examples/network/bearermonitor/bearermonitor.cpp
+++ b/examples/network/bearermonitor/bearermonitor.cpp
@@ -255,6 +255,7 @@ void BearerMonitor::onlineStateChanged(bool isOnline)
void BearerMonitor::registerNetwork()
{
QTreeWidgetItem *item = treeWidget->currentItem();
+ if (!item) return;
QNetworkConfiguration configuration =
manager.configurationFromIdentifier(item->data(0, Qt::UserRole).toString());
@@ -276,6 +277,7 @@ void BearerMonitor::registerNetwork()
void BearerMonitor::unregisterNetwork()
{
QTreeWidgetItem *item = treeWidget->currentItem();
+ if (!item) return;
QNetworkConfiguration configuration =
manager.configurationFromIdentifier(item->data(0, Qt::UserRole).toString());
@@ -384,6 +386,7 @@ void BearerMonitor::createSessionFor(QTreeWidgetItem *item)
void BearerMonitor::createNewSession()
{
QTreeWidgetItem *item = treeWidget->currentItem();
+ if (!item) return;
createSessionFor(item);
}
diff --git a/examples/network/bearermonitor/sessionwidget.cpp b/examples/network/bearermonitor/sessionwidget.cpp
index 443f4b2..3a8e5ea 100644
--- a/examples/network/bearermonitor/sessionwidget.cpp
+++ b/examples/network/bearermonitor/sessionwidget.cpp
@@ -59,7 +59,7 @@ SessionWidget::SessionWidget(const QNetworkConfiguration &config, QWidget *paren
connect(session, SIGNAL(stateChanged(QNetworkSession::State)),
this, SLOT(updateSession()));
connect(session, SIGNAL(error(QNetworkSession::SessionError)),
- this, SLOT(updateSession()));
+ this, SLOT(updateSessionError(QNetworkSession::SessionError)));
updateSession();
@@ -105,7 +105,6 @@ void SessionWidget::deleteSession()
void SessionWidget::updateSession()
{
updateSessionState(session->state());
- updateSessionError(session->error());
if (session->state() == QNetworkSession::Connected)
statsTimer = startTimer(1000);
@@ -128,12 +127,14 @@ void SessionWidget::updateSession()
void SessionWidget::openSession()
{
+ clearError();
session->open();
updateSession();
}
void SessionWidget::openSyncSession()
{
+ clearError();
session->open();
session->waitForOpened();
updateSession();
@@ -141,12 +142,14 @@ void SessionWidget::openSyncSession()
void SessionWidget::closeSession()
{
+ clearError();
session->close();
updateSession();
}
void SessionWidget::stopSession()
{
+ clearError();
session->stop();
updateSession();
}
@@ -195,3 +198,8 @@ void SessionWidget::updateSessionError(QNetworkSession::SessionError error)
errorString->setText(session->errorString());
}
+void SessionWidget::clearError()
+{
+ lastError->clear();
+ errorString->clear();
+}
diff --git a/examples/network/bearermonitor/sessionwidget.h b/examples/network/bearermonitor/sessionwidget.h
index 5e9d62c..b299b47 100644
--- a/examples/network/bearermonitor/sessionwidget.h
+++ b/examples/network/bearermonitor/sessionwidget.h
@@ -63,7 +63,7 @@ public:
private:
void updateSessionState(QNetworkSession::State state);
- void updateSessionError(QNetworkSession::SessionError error);
+ void clearError();
private Q_SLOTS:
void openSession();
@@ -71,9 +71,12 @@ private Q_SLOTS:
void closeSession();
void stopSession();
void updateSession();
+ void updateSessionError(QNetworkSession::SessionError error);
#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
void deleteSession();
#endif
+
+
private:
QNetworkSession *session;
int statsTimer;
diff --git a/examples/network/bearermonitor/sessionwidget.ui b/examples/network/bearermonitor/sessionwidget.ui
index 45135f5..56a2d0e 100644
--- a/examples/network/bearermonitor/sessionwidget.ui
+++ b/examples/network/bearermonitor/sessionwidget.ui
@@ -195,7 +195,7 @@
<item>
<widget class="QLabel" name="errorStringLabel">
<property name="text">
- <string>Error String</string>
+ <string>Error String:</string>
</property>
</widget>
</item>
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 891b1db..9f1eea2 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -261,16 +261,19 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St
if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
actualSize.scale(size, Qt::KeepAspectRatio);
- QString key = QLatin1String("$qt_icon_")
- + QString::number(pm.cacheKey())
- + QString::number(pe->mode)
- + QString::number(QApplication::palette().cacheKey())
- + QLatin1Char('_')
- + QString::number(actualSize.width())
- + QLatin1Char('_')
- + QString::number(actualSize.height())
- + QLatin1Char('_');
-
+ int digits = sizeof(qint64)/sizeof(QChar);
+ quint64 tkey = pm.cacheKey(),
+ tmode = pe->mode,
+ tpalkey = QApplication::palette().cacheKey(),
+ twidth = actualSize.width(),
+ theight = actualSize.height();
+
+ QString key = QLatin1Literal("qt_")
+ % QString::fromRawData((QChar*)&tkey, digits)
+ % QString::fromRawData((QChar*)&tmode, digits)
+ % QString::fromRawData((QChar*)&tpalkey, digits)
+ % QString::fromRawData((QChar*)&twidth, digits)
+ % QString::fromRawData((QChar*)&theight, digits);
if (mode == QIcon::Active) {
if (QPixmapCache::find(key + QString::number(mode), pm))
diff --git a/src/gui/kernel/qcocoawindowdelegate_mac.mm b/src/gui/kernel/qcocoawindowdelegate_mac.mm
index 24498f8..2b9cf85 100644
--- a/src/gui/kernel/qcocoawindowdelegate_mac.mm
+++ b/src/gui/kernel/qcocoawindowdelegate_mac.mm
@@ -202,6 +202,11 @@ static void cleanupCocoaWindowDelegate()
QWindowStateChangeEvent e(Qt::WindowStates(widgetData->window_state
& ~Qt::WindowMaximized));
qt_sendSpontaneousEvent(qwidget, &e);
+ } else {
+ widgetData->window_state = widgetData->window_state & ~Qt::WindowMaximized;
+ QWindowStateChangeEvent e(Qt::WindowStates(widgetData->window_state
+ | Qt::WindowMaximized));
+ qt_sendSpontaneousEvent(qwidget, &e);
}
NSRect rect = [[window contentView] frame];
const QSize newSize(rect.size.width, rect.size.height);
@@ -305,9 +310,19 @@ static void cleanupCocoaWindowDelegate()
Q_UNUSED(newFrame);
// saving the current window geometry before the window is maximized
QWidget *qwidget = m_windowHash->value(window);
- if (qwidget->isWindow() && !(qwidget->windowState() & Qt::WindowMaximized)) {
- QWidgetPrivate *widgetPrivate = qt_widget_private(qwidget);
- widgetPrivate->topData()->normalGeometry = qwidget->geometry();
+ QWidgetPrivate *widgetPrivate = qt_widget_private(qwidget);
+ if (qwidget->isWindow()) {
+ if(qwidget->windowState() & Qt::WindowMaximized) {
+ // Restoring
+ widgetPrivate->topData()->wasMaximized = false;
+ } else {
+ // Maximizing
+ widgetPrivate->topData()->normalGeometry = qwidget->geometry();
+ // If the window was maximized we need to update the coordinates since now it will start at 0,0.
+ // We do this in a special field that is only used when not restoring but manually resizing the window.
+ // Since the coordinates are fixed we just set a boolean flag.
+ widgetPrivate->topData()->wasMaximized = true;
+ }
}
return YES;
}
diff --git a/src/gui/kernel/qt_mac_p.h b/src/gui/kernel/qt_mac_p.h
index 3341ce1..ca9541a 100644
--- a/src/gui/kernel/qt_mac_p.h
+++ b/src/gui/kernel/qt_mac_p.h
@@ -57,7 +57,9 @@
#ifdef __OBJC__
#include <Cocoa/Cocoa.h>
+#ifdef QT_MAC_USE_COCOA
#include <objc/runtime.h>
+#endif // QT_MAC_USE_COCOA
#endif
#include <CoreServices/CoreServices.h>
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 4a9fa94..1f2cd8c 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -1581,6 +1581,11 @@ void QWidgetPrivate::createTLExtra()
x->inTopLevelResize = false;
x->inRepaint = false;
x->embedded = 0;
+#ifdef Q_WS_MAC
+#ifdef QT_MAC_USE_COCOA
+ x->wasMaximized = false;
+#endif // QT_MAC_USE_COCOA
+#endif // Q_WS_MAC
createTLSysExtra();
#ifdef QWIDGET_EXTRA_DEBUG
static int count = 0;
@@ -6720,6 +6725,18 @@ void QWidget::setGeometry(const QRect &r)
*/
QByteArray QWidget::saveGeometry() const
{
+#ifdef QT_MAC_USE_COCOA
+ // We check if the window was maximized during this invocation. If so, we need to record the
+ // starting position as 0,0.
+ Q_D(const QWidget);
+ QRect newFramePosition = frameGeometry();
+ QRect newNormalPosition = normalGeometry();
+ if(d->topData()->wasMaximized && !(windowState() & Qt::WindowMaximized)) {
+ // Change the starting position
+ newFramePosition.moveTo(0, 0);
+ newNormalPosition.moveTo(0, 0);
+ }
+#endif // QT_MAC_USE_COCOA
QByteArray array;
QDataStream stream(&array, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_4_0);
@@ -6729,8 +6746,13 @@ QByteArray QWidget::saveGeometry() const
stream << magicNumber
<< majorVersion
<< minorVersion
+#ifdef QT_MAC_USE_COCOA
+ << newFramePosition
+ << newNormalPosition
+#else
<< frameGeometry()
<< normalGeometry()
+#endif // QT_MAC_USE_COCOA
<< qint32(QApplication::desktop()->screenNumber(this))
<< quint8(windowState() & Qt::WindowMaximized)
<< quint8(windowState() & Qt::WindowFullScreen);
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index cad60b5..3f494d8 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -170,6 +170,14 @@ struct QTLWExtra {
WindowGroupRef group;
IconRef windowIcon; // the current window icon, if set with setWindowIcon_sys.
quint32 savedWindowAttributesFromMaximized; // Saved attributes from when the calling updateMaximizeButton_sys()
+#ifdef QT_MAC_USE_COCOA
+ // This value is just to make sure we maximize and restore to the right location, yet we allow apps to be maximized and
+ // manually resized.
+ // The name is misleading, since this is set when maximizing the window. It is a hint to saveGeometry(..) to record the
+ // starting position as 0,0 instead of the normal starting position.
+ bool wasMaximized;
+#endif // QT_MAC_USE_COCOA
+
#elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS
#ifndef QT_NO_QWS_MANAGER
QWSManager *qwsManager;
diff --git a/src/gui/styles/qgtkpainter.cpp b/src/gui/styles/qgtkpainter.cpp
index 1f68f2f..a6686e2 100644
--- a/src/gui/styles/qgtkpainter.cpp
+++ b/src/gui/styles/qgtkpainter.cpp
@@ -154,9 +154,21 @@ QGtkPainter::QGtkPainter(QPainter *_painter)
static QString uniqueName(const QString &key, GtkStateType state, GtkShadowType shadow,
const QSize &size, GtkWidget *widget = 0)
{
+
+ int digits = sizeof(qint64)/sizeof(QChar);
+ quint64 tstate= state,
+ tshadow = shadow,
+ twidth = size.width(),
+ theight = size.height(),
+ twidget = quint64(widget);
+
// Note the widget arg should ideally use the widget path, though would compromise performance
- QString tmp = QString(QLS("%0-%1-%2-%3x%4-%5")).arg(key).arg(uint(state)).arg(shadow)
- .arg(size.width()).arg(size.height()).arg(quintptr(widget));
+ QString tmp = key
+ % QString::fromRawData((QChar*)&tstate, digits)
+ % QString::fromRawData((QChar*)&tshadow, digits)
+ % QString::fromRawData((QChar*)&twidth, digits)
+ % QString::fromRawData((QChar*)&theight, digits)
+ % QString::fromRawData((QChar*)&twidget, digits);
return tmp;
}
diff --git a/src/gui/styles/qstylehelper.cpp b/src/gui/styles/qstylehelper.cpp
index 296c51c..22f2014 100644
--- a/src/gui/styles/qstylehelper.cpp
+++ b/src/gui/styles/qstylehelper.cpp
@@ -58,67 +58,35 @@
QT_BEGIN_NAMESPACE
-// internal helper. Converts an integer value to an unique string token
-template <typename T>
-struct HexString
-{
- inline HexString(const T t)
- : val(t)
- {}
-
- inline void write(QChar *&dest) const
- {
- const ushort hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
- const char *c = reinterpret_cast<const char *>(&val);
- for (uint i = 0; i < sizeof(T); ++i) {
- *dest++ = hexChars[*c & 0xf];
- *dest++ = hexChars[(*c & 0xf0) >> 4];
- ++c;
- }
- }
-
- const T val;
-};
-
-// specialization to enable fast concatenating of our string tokens to a string
-template <typename T>
-struct QConcatenable<HexString<T> >
-{
- typedef HexString<T> type;
- enum { ExactSize = true };
- static int size(const HexString<T> &str) { return sizeof(str.val) * 2; }
- static inline void appendTo(const HexString<T> &str, QChar *&out) { str.write(out); }
-};
-
namespace QStyleHelper {
QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size)
{
const QStyleOptionComplex *complexOption = qstyleoption_cast<const QStyleOptionComplex *>(option);
-
- QString tmp = key
- % QLatin1Char('-')
- % HexString<uint>(option->state)
- % QLatin1Char('-')
- % HexString<uint>(option->direction)
- % QLatin1Char('-')
- % HexString<uint>(complexOption ? uint(complexOption->activeSubControls) : 0u)
- % QLatin1Char('-')
- % HexString<quint64>(option->palette.cacheKey())
- % QLatin1Char('-')
- % HexString<uint>(size.width())
- % QLatin1Char('x')
- % HexString<uint>(size.height());
+ int digits = sizeof(qint64)/sizeof(QChar);
+ quint64 state = option->state,
+ direction = option->direction,
+ subcontrols = (complexOption ? uint(complexOption->activeSubControls) : 0u),
+ palettekey = option->palette.cacheKey(),
+ width = size.width(),
+ height = size.height();
+
+ QString tmp = key % QString::fromRawData((QChar*)&state, digits)
+ % QString::fromRawData((QChar*)&direction, digits)
+ % QString::fromRawData((QChar*)&subcontrols, digits)
+ % QString::fromRawData((QChar*)&palettekey, digits)
+ % QString::fromRawData((QChar*)&width, digits)
+ % QString::fromRawData((QChar*)&height, digits);
#ifndef QT_NO_SPINBOX
if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
- tmp = tmp
- % QLatin1Char('-')
- % HexString<uint>(spinBox->buttonSymbols)
- % QLatin1Char('-')
- % HexString<uint>(spinBox->stepEnabled)
- % QLatin1Char('-')
- % QLatin1Char(spinBox->frame ? '1' : '0');
+ quint64 buttonsymbols = spinBox->buttonSymbols,
+ stepEnabled = spinBox->stepEnabled,
+ frame = spinBox->frame;
+
+ tmp = tmp % QString::fromRawData((QChar*)&buttonsymbols, digits)
+ % QString::fromRawData((QChar*)&stepEnabled, digits)
+ % QString::fromRawData((QChar*)&frame, digits);
}
#endif // QT_NO_SPINBOX
return tmp;
diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
index 5fc0edb..3cd18fb 100644
--- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp
+++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
@@ -53,15 +53,17 @@
QT_BEGIN_NAMESPACE
QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine)
- : CActive(CActive::EPriorityStandard), engine(engine), ipConnectionNotifier(0),
- iError(QNetworkSession::UnknownSessionError),
- iALREnabled(0), iConnectInBackground(false)
+ : CActive(CActive::EPriorityUserInput), engine(engine),
+ ipConnectionNotifier(0), iHandleStateNotificationsFromManager(false),
+ iFirstSync(true), iStoppedByUser(false), iClosedByUser(false), iDeprecatedConnectionId(0),
+ iError(QNetworkSession::UnknownSessionError), iALREnabled(0), iConnectInBackground(false)
{
CActiveScheduler::Add(this);
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
iMobility = NULL;
#endif
+
TRAP_IGNORE(iConnectionMonitor.ConnectL());
}
@@ -90,18 +92,72 @@ QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl()
// Close global 'Open C' RConnection
setdefaultif(0);
-
- iConnectionMonitor.CancelNotifications();
+
iConnectionMonitor.Close();
}
+void QNetworkSessionPrivateImpl::configurationStateChanged(TUint32 accessPointId, TUint32 connMonId, QNetworkSession::State newState)
+{
+ if (iHandleStateNotificationsFromManager) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "configurationStateChanged from manager for IAP : " << QString::number(accessPointId)
+ << "configurationStateChanged connMon ID : " << QString::number(connMonId)
+ << " : to a state: " << newState
+ << " whereas my current state is: " << state;
+#endif
+ if (connMonId == iDeprecatedConnectionId) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "however status update from manager ignored because it related to already closed connection.";
+#endif
+ return;
+ }
+ this->newState(newState, accessPointId);
+ }
+}
+
+void QNetworkSessionPrivateImpl::configurationRemoved(QNetworkConfigurationPrivatePointer config)
+{
+ if (!publicConfig.isValid())
+ return;
+
+ SymbianNetworkConfigurationPrivate *symbianConfig = toSymbianConfig(config);
+
+ symbianConfig->mutex.lock();
+ TUint32 configNumericId = symbianConfig->numericId;
+ symbianConfig->mutex.unlock();
+
+ symbianConfig = toSymbianConfig(privateConfiguration(publicConfig));
+
+ symbianConfig->mutex.lock();
+ TUint32 publicNumericId = symbianConfig->numericId;
+ symbianConfig->mutex.unlock();
+
+ if (configNumericId == publicNumericId) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "configurationRemoved IAP: " << QString::number(publicNumericId) << " : going to State: Invalid";
+#endif
+ this->newState(QNetworkSession::Invalid, publicNumericId);
+ }
+}
+
void QNetworkSessionPrivateImpl::syncStateWithInterface()
{
if (!publicConfig.isValid())
return;
- // Start monitoring changes in IAP states
- TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this));
+ if (iFirstSync && publicConfig.isValid()) {
+ QObject::connect(engine, SIGNAL(configurationStateChanged(TUint32, TUint32, QNetworkSession::State)),
+ this, SLOT(configurationStateChanged(TUint32, TUint32, QNetworkSession::State)));
+ // Listen to configuration removals, so that in case the configuration
+ // this session is based on is removed, session knows to enter Invalid -state.
+ QObject::connect(engine, SIGNAL(configurationRemoved(QNetworkConfigurationPrivatePointer)),
+ this, SLOT(configurationRemoved(QNetworkConfigurationPrivatePointer)));
+ }
+ // Start listening IAP state changes from QNetworkConfigurationManagerPrivate
+ iHandleStateNotificationsFromManager = true;
// Check open connections to see if there is already
// an open connection to selected IAP or SNAP
@@ -137,11 +193,8 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface()
}
if (state != QNetworkSession::Connected) {
- // There were no open connections to used IAP or SNAP
- if (iError == QNetworkSession::InvalidConfigurationError) {
- newState(QNetworkSession::Invalid);
- } else if ((publicConfig.state() & QNetworkConfiguration::Discovered) ==
- QNetworkConfiguration::Discovered) {
+ if ((publicConfig.state() & QNetworkConfiguration::Discovered) ==
+ QNetworkConfiguration::Discovered) {
newState(QNetworkSession::Disconnected);
} else {
newState(QNetworkSession::NotAvailable);
@@ -245,13 +298,18 @@ QNetworkSession::SessionError QNetworkSessionPrivateImpl::error() const
void QNetworkSessionPrivateImpl::open()
{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "open() called, session state is: " << state << " and isOpen is: "
+ << isOpen;
+#endif
if (isOpen || (state == QNetworkSession::Connecting)) {
return;
}
-
- // Cancel notifications from RConnectionMonitor
+
+ // Stop handling IAP state change signals from QNetworkConfigurationManagerPrivate
// => RConnection::ProgressNotification will be used for IAP/SNAP monitoring
- iConnectionMonitor.CancelNotifications();
+ iHandleStateNotificationsFromManager = false;
// Configuration may have been invalidated after session creation by platform
// (e.g. configuration has been deleted).
@@ -259,19 +317,25 @@ void QNetworkSessionPrivateImpl::open()
newState(QNetworkSession::Invalid);
iError = QNetworkSession::InvalidConfigurationError;
emit QNetworkSessionPrivate::error(iError);
- syncStateWithInterface();
return;
}
- // If opening a (un)defined configuration, session emits error and enters
- // NotAvailable -state.
- if (publicConfig.state() == QNetworkConfiguration::Undefined ||
- publicConfig.state() == QNetworkConfiguration::Defined) {
+ // If opening a undefined configuration, session emits error and enters
+ // NotAvailable -state. Note that we will try ones in 'defined' state to avoid excessive
+ // need for WLAN scans (via updateConfigurations()), because user may have walked
+ // into a WLAN range, but periodic background scan has not occurred yet -->
+ // we don't want to force application to make frequent updateConfigurations() calls
+ // to be able to try if e.g. home WLAN is available.
+ if (publicConfig.state() == QNetworkConfiguration::Undefined) {
newState(QNetworkSession::NotAvailable);
iError = QNetworkSession::InvalidConfigurationError;
emit QNetworkSessionPrivate::error(iError);
return;
}
-
+ // Clear possible previous states
+ iStoppedByUser = false;
+ iClosedByUser = false;
+ iDeprecatedConnectionId = 0;
+
TInt error = iSocketServ.Connect();
if (error != KErrNone) {
// Could not open RSocketServ
@@ -446,16 +510,18 @@ TUint QNetworkSessionPrivateImpl::iapClientCount(TUint aIAPId) const
void QNetworkSessionPrivateImpl::close(bool allowSignals)
{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "close() called, session state is: " << state << " and isOpen is : "
+ << isOpen;
+#endif
if (!isOpen) {
return;
}
-
- SymbianNetworkConfigurationPrivate *symbianConfig =
- toSymbianConfig(privateConfiguration(activeConfig));
-
- symbianConfig->mutex.lock();
- TUint activeIap = symbianConfig->numericId;
- symbianConfig->mutex.unlock();
+ // Mark this session as closed-by-user so that we are able to report
+ // distinguish between stop() and close() state transitions
+ // when reporting.
+ iClosedByUser = true;
isOpen = false;
activeConfig = QNetworkConfiguration();
@@ -469,8 +535,10 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals)
}
#endif
- if (ipConnectionNotifier) {
+ if (ipConnectionNotifier && !iHandleStateNotificationsFromManager) {
ipConnectionNotifier->StopNotifications();
+ // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate
+ iHandleStateNotificationsFromManager = true;
}
iConnection.Close();
@@ -479,29 +547,31 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals)
// Close global 'Open C' RConnection
setdefaultif(0);
-#ifdef Q_CC_NOKIAX86
- if ((allowSignals && iapClientCount(activeIap) <= 0) ||
-#else
- if ((allowSignals && iapClientCount(activeIap) <= 1) ||
-#endif
- (publicConfig.type() == QNetworkConfiguration::UserChoice)) {
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
newState(QNetworkSession::Closing);
+ newState(QNetworkSession::Disconnected);
}
- syncStateWithInterface();
if (allowSignals) {
- if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
- newState(QNetworkSession::Disconnected);
- }
emit closed();
}
}
void QNetworkSessionPrivateImpl::stop()
{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "stop() called, session state is: " << state << " and isOpen is : "
+ << isOpen;
+#endif
if (!isOpen &&
publicConfig.isValid() &&
publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "since session is not open, using RConnectionMonitor to stop() the interface";
+#endif
+ iStoppedByUser = true;
// If the publicConfig is type of IAP, enumerate through connections at
// connection monitor. If publicConfig is active in that list, stop it.
// Otherwise there is nothing to stop. Note: because this QNetworkSession is not open,
@@ -515,7 +585,7 @@ void QNetworkSessionPrivateImpl::stop()
}
TUint numSubConnections; // Not used but needed by GetConnectionInfo i/f
TUint connectionId;
- for (TInt i = 1; i <= count; ++i) {
+ for (TUint i = 1; i <= count; ++i) {
// Get (connection monitor's assigned) connection ID
TInt ret = iConnectionMonitor.GetConnectionInfo(i, connectionId, numSubConnections);
if (ret == KErrNone) {
@@ -532,11 +602,25 @@ void QNetworkSessionPrivateImpl::stop()
ETrue);
}
}
+ // Enter disconnected state right away since the session is not even open.
+ // Symbian^3 connection monitor does not emit KLinkLayerClosed when
+ // connection is stopped via connection monitor.
+ newState(QNetworkSession::Disconnected);
}
} else if (isOpen) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "since session is open, using RConnection to stop() the interface";
+#endif
// Since we are open, use RConnection to stop the interface
isOpen = false;
+ iStoppedByUser = true;
newState(QNetworkSession::Closing);
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate
+ iHandleStateNotificationsFromManager = true;
+ }
iConnection.Stop(RConnection::EStopAuthoritative);
isOpen = true;
close(false);
@@ -654,6 +738,10 @@ void QNetworkSessionPrivateImpl::NewCarrierActive(TAccessPointInfo /*aNewAPInfo*
void QNetworkSessionPrivateImpl::Error(TInt /*aError*/)
{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "roaming Error() occured";
+#endif
if (isOpen) {
isOpen = false;
activeConfig = QNetworkConfiguration();
@@ -671,6 +759,11 @@ void QNetworkSessionPrivateImpl::Error(TInt /*aError*/)
// changes immediately to Disconnected.
newState(QNetworkSession::Disconnected);
emit closed();
+ } else if (iStoppedByUser) {
+ // If the user of this session has called the stop() and
+ // configuration is based on internet SNAP, this needs to be
+ // done here because platform might roam.
+ newState(QNetworkSession::Disconnected);
}
}
#endif
@@ -975,7 +1068,12 @@ void QNetworkSessionPrivateImpl::RunL()
isOpen = false;
activeConfig = QNetworkConfiguration();
serviceConfig = QNetworkConfiguration();
- iError = QNetworkSession::UnknownSessionError;
+ if (publicConfig.state() == QNetworkConfiguration::Undefined ||
+ publicConfig.state() == QNetworkConfiguration::Defined) {
+ iError = QNetworkSession::InvalidConfigurationError;
+ } else {
+ iError = QNetworkSession::UnknownSessionError;
+ }
emit QNetworkSessionPrivate::error(iError);
Cancel();
if (ipConnectionNotifier) {
@@ -991,8 +1089,16 @@ void QNetworkSessionPrivateImpl::DoCancel()
iConnection.Close();
}
+// Enters newState if feasible according to current state.
+// AccessPointId may be given as parameter. If it is zero, state-change is assumed to
+// concern this session's configuration. If non-zero, the configuration is looked up
+// and checked if it matches the configuration this session is based on.
bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint accessPointId)
{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "NEW STATE, IAP ID : " << QString::number(accessPointId) << " , newState : " << QString::number(newState);
+#endif
// Make sure that activeConfig is always updated when SNAP is signaled to be
// connected.
if (isOpen && publicConfig.type() == QNetworkConfiguration::ServiceNetwork &&
@@ -1027,9 +1133,29 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint
if (state == QNetworkSession::Roaming && newState == QNetworkSession::Connecting) {
return false;
}
+
+ // Make sure that Connected state is not reported when Connection is
+ // already Closing.
+ // Note: Stopping connection results sometimes KLinkLayerOpen
+ // to be reported first (just before KLinkLayerClosed).
+ if (state == QNetworkSession::Closing && newState == QNetworkSession::Connected) {
+ return false;
+ }
+
+ // Make sure that some lagging 'closing' state-changes do not overwrite
+ // if we are already disconnected or closed.
+ if (state == QNetworkSession::Disconnected && newState == QNetworkSession::Closing) {
+ return false;
+ }
bool emitSessionClosed = false;
- if (isOpen && state == QNetworkSession::Connected && newState == QNetworkSession::Disconnected) {
+
+ // If we abruptly go down and user hasn't closed the session, we've been aborted.
+ // Note that session may be in 'closing' state and not in 'connected' state, because
+ // depending on platform the platform may report KConfigDaemonStartingDeregistration
+ // event before KLinkLayerClosed
+ if ((isOpen && state == QNetworkSession::Connected && newState == QNetworkSession::Disconnected) ||
+ (isOpen && !iClosedByUser && newState == QNetworkSession::Disconnected)) {
// Active & Connected state should change directly to Disconnected state
// only when something forces connection to close (eg. when another
// application or session stops connection or when network drops
@@ -1043,14 +1169,17 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint
if (ipConnectionNotifier) {
ipConnectionNotifier->StopNotifications();
}
- // Start monitoring changes in IAP states
- TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this));
+ // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate
+ iHandleStateNotificationsFromManager = true;
emitSessionClosed = true; // Emit SessionClosed after state change has been reported
}
bool retVal = false;
if (accessPointId == 0) {
state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed A to: " << state;
+#endif
emit stateChanged(state);
retVal = true;
} else {
@@ -1063,6 +1192,9 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint
configLocker.unlock();
state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed B to: " << state;
+#endif
emit stateChanged(state);
retVal = true;
}
@@ -1075,6 +1207,9 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint
configLocker.unlock();
state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed C to: " << state;
+#endif
emit stateChanged(state);
retVal = true;
}
@@ -1087,21 +1222,14 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint
QMutexLocker configLocker(&symbianConfig->mutex);
if (symbianConfig->numericId == accessPointId) {
- if (newState == QNetworkSession::Connected) {
- // Make sure that when AccessPoint is reported to be Connected
- // also state of the related configuration changes to Active.
- symbianConfig->state = QNetworkConfiguration::Active;
- configLocker.unlock();
-
+ if (newState != QNetworkSession::Disconnected) {
state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed D to: " << state;
+#endif
emit stateChanged(state);
retVal = true;
} else {
- if (newState == QNetworkSession::Disconnected) {
- // Make sure that when AccessPoint is reported to be disconnected
- // also state of the related configuration changes from Active to Defined.
- symbianConfig->state = QNetworkConfiguration::Defined;
- }
QNetworkConfiguration config = bestConfigFromSNAP(publicConfig);
if ((config.state() == QNetworkConfiguration::Defined) ||
(config.state() == QNetworkConfiguration::Discovered)) {
@@ -1109,8 +1237,21 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint
configLocker.unlock();
state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed E to: " << state;
+#endif
emit stateChanged(state);
retVal = true;
+ } else if (config.state() == QNetworkConfiguration::Active) {
+ // Connection to used IAP was closed, but there is another
+ // IAP that's active in used SNAP
+ // => Change state back to Connected
+ state = QNetworkSession::Connected;
+ emit stateChanged(state);
+ retVal = true;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed F to: " << state;
+#endif
}
}
}
@@ -1121,6 +1262,19 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint
if (emitSessionClosed) {
emit closed();
}
+ if (state == QNetworkSession::Disconnected) {
+ // The connection has gone down, and processing of status updates must be
+ // stopped. Depending on platform, there may come 'connecting/connected' states
+ // considerably later (almost a second). Connection id is an increasing
+ // number, so this does not affect next _real_ 'conneting/connected' states.
+
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(publicConfig));
+
+ symbianConfig->mutex.lock();
+ iDeprecatedConnectionId = symbianConfig->connectionId;
+ symbianConfig->mutex.unlock();
+ }
return retVal;
}
@@ -1129,6 +1283,9 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne
TInt aError,
TUint accessPointId)
{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << QString::number(accessPointId) << " , status : " << QString::number(aConnectionStatus);
+#endif
switch (aConnectionStatus)
{
// Connection unitialised
@@ -1167,6 +1324,7 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne
case KCsdGotLoginInfo:
break;
+ case KConfigDaemonStartingRegistration:
// Creating connection (e.g. GPRS activation)
case KCsdStartingConnect:
case KCsdFinishedConnect:
@@ -1193,6 +1351,7 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne
case KDataTransferTemporarilyBlocked:
break;
+ case KConfigDaemonStartingDeregistration:
// Hangup or GRPS deactivation
case KConnectionStartingClose:
newState(QNetworkSession::Closing,accessPointId);
@@ -1200,137 +1359,27 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne
// Connection closed
case KConnectionClosed:
- break;
-
case KLinkLayerClosed:
newState(QNetworkSession::Disconnected,accessPointId);
+ // Report manager about this to make sure this event
+ // is received by all interseted parties (mediated by
+ // manager because it does always receive all events from
+ // connection monitor).
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "reporting disconnection to manager.";
+#endif
+ if (publicConfig.isValid()) {
+ engine->configurationStateChangeReport(toSymbianConfig(privateConfiguration(publicConfig))->numericId, QNetworkSession::Disconnected);
+ }
break;
-
// Unhandled state
default:
break;
}
}
-void QNetworkSessionPrivateImpl::EventL(const CConnMonEventBase& aEvent)
-{
- switch (aEvent.EventType())
- {
- case EConnMonConnectionStatusChange:
- {
- CConnMonConnectionStatusChange* realEvent;
- realEvent = (CConnMonConnectionStatusChange*) &aEvent;
-
- TUint connectionId = realEvent->ConnectionId();
- TInt connectionStatus = realEvent->ConnectionStatus();
-
- // Try to Find IAP Id using connection Id
- TUint apId = 0;
- if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
- QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
- for (int i = 0; i < subConfigurations.count(); i++ ) {
- SymbianNetworkConfigurationPrivate *symbianConfig =
- toSymbianConfig(privateConfiguration(subConfigurations[i]));
-
- QMutexLocker configLocker(&symbianConfig->mutex);
-
- if (symbianConfig->connectionId == connectionId) {
- apId = symbianConfig->numericId;
- break;
- }
- }
- } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
- SymbianNetworkConfigurationPrivate *symbianConfig =
- toSymbianConfig(privateConfiguration(publicConfig));
-
- symbianConfig->mutex.lock();
- if (symbianConfig->connectionId == connectionId)
- apId = symbianConfig->numericId;
- symbianConfig->mutex.unlock();
- }
-
- if (apId > 0) {
- handleSymbianConnectionStatusChange(connectionStatus, KErrNone, apId);
- }
- }
- break;
-
- case EConnMonCreateConnection:
- {
- CConnMonCreateConnection* realEvent;
- realEvent = (CConnMonCreateConnection*) &aEvent;
- TUint apId;
- TUint connectionId = realEvent->ConnectionId();
- TRequestStatus status;
- iConnectionMonitor.GetUintAttribute(connectionId, 0, KIAPId, apId, status);
- User::WaitForRequest(status);
- if (status.Int() == KErrNone) {
- // Store connection id to related AccessPoint Configuration
- if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
- QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
- for (int i = 0; i < subConfigurations.count(); i++ ) {
- SymbianNetworkConfigurationPrivate *symbianConfig =
- toSymbianConfig(privateConfiguration(subConfigurations[i]));
-
- QMutexLocker configLocker(&symbianConfig->mutex);
-
- if (symbianConfig->numericId == apId) {
- symbianConfig->connectionId = connectionId;
- break;
- }
- }
- } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
- SymbianNetworkConfigurationPrivate *symbianConfig =
- toSymbianConfig(privateConfiguration(publicConfig));
-
- symbianConfig->mutex.lock();
- if (symbianConfig->numericId == apId)
- symbianConfig->connectionId = connectionId;
- symbianConfig->mutex.unlock();
- }
- }
- }
- break;
-
- case EConnMonDeleteConnection:
- {
- CConnMonDeleteConnection* realEvent;
- realEvent = (CConnMonDeleteConnection*) &aEvent;
- TUint connectionId = realEvent->ConnectionId();
- // Remove connection id from related AccessPoint Configuration
- if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
- QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
- for (int i = 0; i < subConfigurations.count(); i++ ) {
- SymbianNetworkConfigurationPrivate *symbianConfig =
- toSymbianConfig(privateConfiguration(subConfigurations[i]));
-
- QMutexLocker configLocker(&symbianConfig->mutex);
-
- if (symbianConfig->connectionId == connectionId) {
- symbianConfig->connectionId = 0;
- break;
- }
- }
- } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
- SymbianNetworkConfigurationPrivate *symbianConfig =
- toSymbianConfig(privateConfiguration(publicConfig));
-
- symbianConfig->mutex.lock();
- if (symbianConfig->connectionId == connectionId)
- symbianConfig->connectionId = 0;
- symbianConfig->mutex.unlock();
- }
- }
- break;
-
- default:
- // For unrecognized events
- break;
- }
-}
-
-ConnectionProgressNotifier::ConnectionProgressNotifier(QNetworkSessionPrivateImpl &owner, RConnection &connection)
- : CActive(CActive::EPriorityStandard), iOwner(owner), iConnection(connection)
+ConnectionProgressNotifier::ConnectionProgressNotifier(QNetworkSessionPrivateImpl& owner, RConnection& connection)
+ : CActive(CActive::EPriorityUserInput), iOwner(owner), iConnection(connection)
{
CActiveScheduler::Add(this);
}
diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h
index 7116519..9767293 100644
--- a/src/plugins/bearer/symbian/qnetworksession_impl.h
+++ b/src/plugins/bearer/symbian/qnetworksession_impl.h
@@ -75,9 +75,8 @@ class SymbianEngine;
class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive,
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
- public MMobilityProtocolResp,
+ public MMobilityProtocolResp
#endif
- public MConnectionMonitorObserver
{
Q_OBJECT
public:
@@ -130,8 +129,9 @@ protected: // From CActive
void RunL();
void DoCancel();
-private: // MConnectionMonitorObserver
- void EventL(const CConnMonEventBase& aEvent);
+private Q_SLOTS:
+ void configurationStateChanged(TUint32 accessPointId, TUint32 connMonId, QNetworkSession::State newState);
+ void configurationRemoved(QNetworkConfigurationPrivatePointer config);
private:
TUint iapClientCount(TUint aIAPId) const;
@@ -157,6 +157,13 @@ private: // data
mutable RConnection iConnection;
mutable RConnectionMonitor iConnectionMonitor;
ConnectionProgressNotifier* ipConnectionNotifier;
+
+ bool iHandleStateNotificationsFromManager;
+ bool iFirstSync;
+ bool iStoppedByUser;
+ bool iClosedByUser;
+ TUint32 iDeprecatedConnectionId;
+
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
CActiveCommsMobilityApiExt* iMobility;
#endif
diff --git a/src/plugins/bearer/symbian/symbianengine.cpp b/src/plugins/bearer/symbian/symbianengine.cpp
index 8e9675e..cea8b67 100644
--- a/src/plugins/bearer/symbian/symbianengine.cpp
+++ b/src/plugins/bearer/symbian/symbianengine.cpp
@@ -45,14 +45,14 @@
#include <commdb.h>
#include <cdbcols.h>
#include <d32dbms.h>
+#include <nifvar.h>
#include <QEventLoop>
#include <QTimer>
#include <QTime> // For randgen seeding
#include <QtCore> // For randgen seeding
-// #define QT_BEARERMGMT_CONFIGMGR_DEBUG
-#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
#include <QDebug>
#endif
@@ -73,7 +73,9 @@
QT_BEGIN_NAMESPACE
-static const int KValueThatWillBeAddedToSNAPId = 1000;
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ static const int KValueThatWillBeAddedToSNAPId = 1000;
+#endif
static const int KUserChoiceIAPId = 0;
SymbianNetworkConfigurationPrivate::SymbianNetworkConfigurationPrivate()
@@ -657,26 +659,34 @@ void SymbianEngine::updateActiveAccessPoints()
iConnectionMonitor.GetConnectionCount(connectionCount, status);
User::WaitForRequest(status);
- // Go through all connections and set state of related IAPs to Active
+ // Go through all connections and set state of related IAPs to Active.
+ // Status needs to be checked carefully, because ConnMon lists also e.g.
+ // WLAN connections that are being currently tried --> we don't want to
+ // state these as active.
TUint connectionId;
TUint subConnectionCount;
TUint apId;
+ TInt connectionStatus;
if (status.Int() == KErrNone) {
for (TUint i = 1; i <= connectionCount; i++) {
iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount);
iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
User::WaitForRequest(status);
QString ident = QString::number(qHash(apId));
-
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
if (ptr) {
- online = true;
- inactiveConfigs.removeOne(ident);
+ iConnectionMonitor.GetIntAttribute(connectionId, subConnectionCount, KConnectionStatus, connectionStatus, status);
+ User::WaitForRequest(status);
+ if (connectionStatus == KLinkLayerOpen) {
+ online = true;
+ inactiveConfigs.removeOne(ident);
- toSymbianConfig(ptr)->connectionId = connectionId;
+ QMutexLocker configLocker(&ptr->mutex);
+ toSymbianConfig(ptr)->connectionId = connectionId;
- // Configuration is Active
- changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
+ // Configuration is Active
+ changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
+ }
}
}
}
@@ -733,12 +743,12 @@ void SymbianEngine::accessPointScanningReady(TBool scanSuccessful, TConnMonIapIn
}
}
- // Make sure that state of rest of the IAPs won't be Discovered or Active
+ // Make sure that state of rest of the IAPs won't be Active
foreach (const QString &iface, unavailableConfigs) {
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
if (ptr) {
// Configuration is Defined
- changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Defined);
+ changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered);
}
}
}
@@ -894,21 +904,22 @@ void SymbianEngine::RunL()
QMutexLocker locker(&mutex);
if (iIgnoringUpdates) {
-#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
- qDebug("CommsDB event handling postponed (postpone-timer running because IAPs/SNAPs were updated very recently).");
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug("QNCM CommsDB event handling postponed (postpone-timer running because IAPs/SNAPs were updated very recently).");
#endif
return;
}
if (iStatus != KErrCancel) {
RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int());
+
switch (event) {
case RDbNotifier::EUnlock: /** All read locks have been removed. */
case RDbNotifier::ECommit: /** A transaction has been committed. */
case RDbNotifier::ERollback: /** A transaction has been rolled back */
case RDbNotifier::ERecover: /** The database has been recovered */
-#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
- qDebug("CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug("QNCM CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
#endif
iIgnoringUpdates = true;
// Other events than ECommit get lower priority. In practice with those events,
@@ -957,73 +968,95 @@ void SymbianEngine::DoCancel()
ipCommsDB->CancelRequestNotification();
}
-
void SymbianEngine::EventL(const CConnMonEventBase& aEvent)
{
QMutexLocker locker(&mutex);
switch (aEvent.EventType()) {
- case EConnMonCreateConnection:
+ case EConnMonConnectionStatusChange:
{
- CConnMonCreateConnection* realEvent;
- realEvent = (CConnMonCreateConnection*) &aEvent;
- TUint subConnectionCount = 0;
- TUint apId;
- TUint connectionId = realEvent->ConnectionId();
- TRequestStatus status;
- iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
- User::WaitForRequest(status);
- QString ident = QString::number(qHash(apId));
-
- QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
- if (ptr) {
- toSymbianConfig(ptr)->connectionId = connectionId;
- // Configuration is Active
- if (changeConfigurationStateTo(ptr, QNetworkConfiguration::Active))
- updateStatesToSnaps();
-
- if (!iOnline) {
- iOnline = true;
-
- locker.unlock();
- emit this->onlineStateChanged(iOnline);
- locker.relock();
+ CConnMonConnectionStatusChange* realEvent;
+ realEvent = (CConnMonConnectionStatusChange*) &aEvent;
+ TInt connectionStatus = realEvent->ConnectionStatus();
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNCM Connection status : " << QString::number(connectionStatus) << " , connection monitor Id : " << realEvent->ConnectionId();
+#endif
+ if (connectionStatus == KConfigDaemonStartingRegistration) {
+ TUint connectionId = realEvent->ConnectionId();
+ TUint subConnectionCount = 0;
+ TUint apId;
+ TRequestStatus status;
+ iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ QString ident = QString::number(qHash(apId));
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+ if (ptr) {
+ QMutexLocker configLocker(&ptr->mutex);
+ toSymbianConfig(ptr)->connectionId = connectionId;
+ emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Connecting);
}
- }
- }
- break;
-
- case EConnMonDeleteConnection:
- {
- CConnMonDeleteConnection* realEvent;
- realEvent = (CConnMonDeleteConnection*) &aEvent;
- TUint connectionId = realEvent->ConnectionId();
-
- QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
- if (ptr) {
- toSymbianConfig(ptr)->connectionId = 0;
- // Configuration is either Defined or Discovered
- if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered))
- updateStatesToSnaps();
- }
-
- bool online = false;
- foreach (const QString &iface, accessPointConfigurations.keys()) {
- QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
- if (ptr->state == QNetworkConfiguration::Active) {
- online = true;
- break;
+ } else if (connectionStatus == KLinkLayerOpen) {
+ // Connection has been successfully opened
+ TUint connectionId = realEvent->ConnectionId();
+ TUint subConnectionCount = 0;
+ TUint apId;
+ TRequestStatus status;
+ iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ QString ident = QString::number(qHash(apId));
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+ if (ptr) {
+ QMutexLocker configLocker(&ptr->mutex);
+ toSymbianConfig(ptr)->connectionId = connectionId;
+ // Configuration is Active
+ if (changeConfigurationStateTo(ptr, QNetworkConfiguration::Active)) {
+ updateStatesToSnaps();
+ }
+ emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Connected);
+ if (!iOnline) {
+ iOnline = true;
+ emit this->onlineStateChanged(iOnline);
+ }
}
- }
- if (iOnline != online) {
- iOnline = online;
+ } else if (connectionStatus == KConfigDaemonStartingDeregistration) {
+ TUint connectionId = realEvent->ConnectionId();
+ QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
+ if (ptr) {
+ QMutexLocker configLocker(&ptr->mutex);
+ emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Closing);
+ }
+ } else if (connectionStatus == KLinkLayerClosed ||
+ connectionStatus == KConnectionClosed) {
+ // Connection has been closed. Which of the above events is reported, depends on the Symbian
+ // platform.
+ TUint connectionId = realEvent->ConnectionId();
+ QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
+ if (ptr) {
+ // Configuration is either Defined or Discovered
+ if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) {
+ updateStatesToSnaps();
+ }
- locker.unlock();
- emit this->onlineStateChanged(iOnline);
- locker.relock();
+ QMutexLocker configLocker(&ptr->mutex);
+ emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Disconnected);
+ }
+
+ bool online = false;
+ foreach (const QString &iface, accessPointConfigurations.keys()) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
+ QMutexLocker configLocker(&ptr->mutex);
+ if (ptr->state == QNetworkConfiguration::Active) {
+ online = true;
+ break;
+ }
+ }
+ if (iOnline != online) {
+ iOnline = online;
+ emit this->onlineStateChanged(iOnline);
+ }
}
}
- break;
+ break;
case EConnMonIapAvailabilityChange:
{
@@ -1051,21 +1084,78 @@ void SymbianEngine::EventL(const CConnMonEventBase& aEvent)
}
break;
+ case EConnMonCreateConnection:
+ {
+ // This event is caught to keep connection monitor IDs up-to-date.
+ CConnMonCreateConnection* realEvent;
+ realEvent = (CConnMonCreateConnection*) &aEvent;
+ TUint subConnectionCount = 0;
+ TUint apId;
+ TUint connectionId = realEvent->ConnectionId();
+ TRequestStatus status;
+ iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ QString ident = QString::number(qHash(apId));
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+ if (ptr) {
+ QMutexLocker configLocker(&ptr->mutex);
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNCM updating connection monitor ID : from, to, whose: " << toSymbianConfig(ptr)->connectionId << connectionId << ptr->name;
+#endif
+ toSymbianConfig(ptr)->connectionId = connectionId;
+ }
+ }
+ break;
default:
// For unrecognized events
break;
}
}
-// Waits for 1..4 seconds.
+// Sessions may use this function to report configuration state changes,
+// because on some Symbian platforms (especially Symbian^3) all state changes are not
+// reported by the RConnectionMonitor, in particular in relation to stop() call,
+// whereas they _are_ reported on RConnection progress notifier used by sessions --> centralize
+// this data here so that other sessions may benefit from it too (not all sessions necessarily have
+// RConnection progress notifiers available but they relay on having e.g. disconnected information from
+// manager). Currently only 'Disconnected' state is of interest because it has proven to be troublesome.
+void SymbianEngine::configurationStateChangeReport(TUint32 accessPointId, QNetworkSession::State newState)
+{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNCM A session reported state change for IAP ID: " << accessPointId << " whose new state is: " << newState;
+#endif
+ switch (newState) {
+ case QNetworkSession::Disconnected:
+ {
+ QString ident = QString::number(qHash(accessPointId));
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+ if (ptr) {
+ // Configuration is either Defined or Discovered
+ if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) {
+ updateStatesToSnaps();
+ }
+
+ QMutexLocker configLocker(&ptr->mutex);
+ emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId,
+ toSymbianConfig(ptr)->connectionId,
+ QNetworkSession::Disconnected);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+// Waits for 2..6 seconds.
void SymbianEngine::waitRandomTime()
{
- iTimeToWait = (qAbs(qrand()) % 5) * 1000;
- if (iTimeToWait < 1000) {
- iTimeToWait = 1000;
+ iTimeToWait = (qAbs(qrand()) % 7) * 1000;
+ if (iTimeToWait < 2000) {
+ iTimeToWait = 2000;
}
-#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
- qDebug("QNetworkConfigurationManager waiting random time: %d ms", iTimeToWait);
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug("QNCM waiting random time: %d ms", iTimeToWait);
#endif
QTimer::singleShot(iTimeToWait, iIgnoreEventLoop, SLOT(quit()));
iIgnoreEventLoop->exec();
@@ -1076,11 +1166,11 @@ QNetworkConfigurationPrivatePointer SymbianEngine::dataByConnectionId(TUint aCon
QMutexLocker locker(&mutex);
QNetworkConfiguration item;
-
QHash<QString, QNetworkConfigurationPrivatePointer>::const_iterator i =
accessPointConfigurations.constBegin();
while (i != accessPointConfigurations.constEnd()) {
QNetworkConfigurationPrivatePointer ptr = i.value();
+ QMutexLocker configLocker(&ptr->mutex);
if (toSymbianConfig(ptr)->connectionId == aConnectionId)
return ptr;
diff --git a/src/plugins/bearer/symbian/symbianengine.h b/src/plugins/bearer/symbian/symbianengine.h
index afb37de..7d565db 100644
--- a/src/plugins/bearer/symbian/symbianengine.h
+++ b/src/plugins/bearer/symbian/symbianengine.h
@@ -52,6 +52,9 @@
#include <cmmanager.h>
#endif
+// Uncomment and compile QtBearer to gain detailed state tracing
+// #define QT_BEARERMGMT_SYMBIAN_DEBUG
+
class CCommsDatabase;
class QEventLoop;
@@ -90,7 +93,18 @@ public:
Bearer bearer;
+ // So called IAP id from the platform. Remains constant as long as the
+ // platform is aware of the configuration ie. it is stored in the databases
+ // --> does not depend on whether connections are currently open or not.
+ // In practice is the same for the lifetime of the QNetworkConfiguration.
TUint32 numericId;
+ // So called connection id, or connection monitor ID. A dynamic ID assigned
+ // by RConnectionMonitor whenever a new connection is opened. ConnectionID and
+ // numericId/IAP id have 1-to-1 mapping during the lifetime of the connection at
+ // connection monitor. Notably however it changes whenever a new connection to
+ // a given IAP is created. In a sense it is constant during the time the
+ // configuration remains between states Discovered..Active..Discovered, do not
+ // however relay on this.
TUint connectionId;
};
@@ -124,6 +138,9 @@ public:
Q_SIGNALS:
void onlineStateChanged(bool isOnline);
+ void configurationStateChanged(TUint32 accessPointId, TUint32 connMonId,
+ QNetworkSession::State newState);
+
public Q_SLOTS:
void updateConfigurations();
@@ -157,12 +174,17 @@ private:
void startMonitoringIAPData(TUint32 aIapId);
QNetworkConfigurationPrivatePointer dataByConnectionId(TUint aConnectionId);
-protected: // From CActive
+protected:
+ // From CActive
void RunL();
void DoCancel();
-private: // MConnectionMonitorObserver
+private:
+ // MConnectionMonitorObserver
void EventL(const CConnMonEventBase& aEvent);
+ // For QNetworkSessionPrivate to indicate about state changes
+ void configurationStateChangeReport(TUint32 accessPointId,
+ QNetworkSession::State newState);
private: // Data
bool iFirstUpdate;
@@ -181,6 +203,7 @@ private: // Data
friend class QNetworkSessionPrivate;
friend class AccessPointsAvailabilityScanner;
+ friend class QNetworkSessionPrivateImpl;
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
RCmManager iCmManager;
diff --git a/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp b/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp
index ce3acb7..a3cccb2 100644
--- a/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp
+++ b/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp
@@ -45,6 +45,13 @@
#include <QtNetwork/qnetworkconfiguration.h>
#include <QtNetwork/qnetworkconfigmanager.h>
+/*
+ Although this unit test doesn't use QNetworkAccessManager
+ this include is used to ensure that bearer continues to compile against
+ Qt 4.7+ which has a QNetworkConfiguration enabled QNetworkAccessManager
+*/
+#include <QNetworkAccessManager>
+
#if defined(Q_WS_MAEMO_6) || defined(Q_WS_MAEMO_5)
#include <stdio.h>
#include <iapconf.h>
diff --git a/tests/auto/qnetworksession/lackey/main.cpp b/tests/auto/qnetworksession/lackey/main.cpp
index 8759b52..ec2fad9 100644
--- a/tests/auto/qnetworksession/lackey/main.cpp
+++ b/tests/auto/qnetworksession/lackey/main.cpp
@@ -47,6 +47,8 @@
#include <QtNetwork/qnetworkconfigmanager.h>
#include <QtNetwork/qnetworksession.h>
+#include <QEventLoop>
+#include <QTimer>
#include <QDebug>
QT_USE_NAMESPACE
@@ -60,15 +62,14 @@ int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
- // Cannot read/write to processes on WinCE or Symbian.
- // Easiest alternative is to use sockets for IPC.
-
- QLocalSocket oopSocket;
-
- oopSocket.connectToServer("tst_qnetworksession");
- oopSocket.waitForConnected(-1);
-
+ // Update configurations so that everything is up to date for this process too.
+ // Event loop is used to wait for awhile.
QNetworkConfigurationManager manager;
+ manager.updateConfigurations();
+ QEventLoop iIgnoreEventLoop;
+ QTimer::singleShot(3000, &iIgnoreEventLoop, SLOT(quit()));
+ iIgnoreEventLoop.exec();
+
QList<QNetworkConfiguration> discovered =
manager.allConfigurations(QNetworkConfiguration::Discovered);
@@ -82,6 +83,13 @@ int main(int argc, char** argv)
return NO_DISCOVERED_CONFIGURATIONS_ERROR;
}
+ // Cannot read/write to processes on WinCE or Symbian.
+ // Easiest alternative is to use sockets for IPC.
+ QLocalSocket oopSocket;
+
+ oopSocket.connectToServer("tst_qnetworksession");
+ oopSocket.waitForConnected(-1);
+
qDebug() << "Lackey started";
QNetworkSession *session = 0;
diff --git a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp
index 23cdc6a..934a50e 100644
--- a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp
+++ b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp
@@ -100,6 +100,7 @@ private slots:
private:
QNetworkConfigurationManager manager;
+ QMap<QString, bool> testsToRun;
int inProcessSessionManagementCount;
@@ -117,6 +118,7 @@ private:
bool openSession(QNetworkSession *session);
bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration = true);
void updateConfigurations();
+void printConfigurations();
QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfiguration::Type configType);
void tst_QNetworkSession::initTestCase()
@@ -125,7 +127,19 @@ void tst_QNetworkSession::initTestCase()
qRegisterMetaType<QNetworkSession::SessionError>("QNetworkSession::SessionError");
qRegisterMetaType<QNetworkConfiguration>("QNetworkConfiguration");
qRegisterMetaType<QNetworkConfiguration::Type>("QNetworkConfiguration::Type");
-
+
+ // If you wish to skip tests, set value as false. This is often very convinient because tests are so lengthy.
+ // Better way still would be to make this readable from a file.
+ testsToRun["robustnessBombing"] = true;
+ testsToRun["outOfProcessSession"] = true;
+ testsToRun["invalidSession"] = true;
+ testsToRun["repeatedOpenClose"] = true;
+ testsToRun["roamingErrorCodes"] = true;
+ testsToRun["sessionStop"] = true;
+ testsToRun["sessionProperties"] = true;
+ testsToRun["userChoiceSession"] = true;
+ testsToRun["sessionOpenCloseStop"] = true;
+
#if defined(Q_WS_MAEMO_6) || defined(Q_WS_MAEMO_5)
iapconf = new Maemo::IAPConf("007");
iapconf->setValue("ipv4_type", "AUTO");
@@ -238,6 +252,10 @@ void tst_QNetworkSession::cleanupTestCase()
// Robustness test for calling interfaces in nonsense order / with nonsense parameters
void tst_QNetworkSession::robustnessBombing()
{
+ if (!testsToRun["robustnessBombing"]) {
+ QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);
+ }
+
QNetworkConfigurationManager mgr;
QNetworkSession testSession(mgr.defaultConfiguration());
// Should not reset even session is not opened
@@ -245,15 +263,14 @@ void tst_QNetworkSession::robustnessBombing()
testSession.accept();
testSession.ignore();
testSession.reject();
- quint64 temp;
- temp = testSession.bytesWritten();
- temp = testSession.bytesReceived();
- temp = testSession.activeTime();
}
void tst_QNetworkSession::invalidSession()
-{
+{
+ if (!testsToRun["invalidSession"]) {
+ QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);
+ }
// 1. Verify that session created with invalid configuration remains in invalid state
QNetworkSession session(QNetworkConfiguration(), 0);
QVERIFY(!session.isOpen());
@@ -270,11 +287,24 @@ void tst_QNetworkSession::invalidSession()
QVERIFY(error == QNetworkSession::InvalidConfigurationError);
QVERIFY(session.error() == QNetworkSession::InvalidConfigurationError);
QVERIFY(session.state() == QNetworkSession::Invalid);
-
+
#ifdef QNETWORKSESSION_MANUAL_TESTS
+
+ QNetworkConfiguration invalidatedConfig = suitableConfiguration("WLAN",QNetworkConfiguration::InternetAccessPoint);
+ if (invalidatedConfig.isValid()) {
+ // 3. Verify that invalidating a session after its successfully configured works
+ QNetworkSession invalidatedSession(invalidatedConfig);
+ qDebug() << "Delete the WLAN IAP from phone now (waiting 60 seconds): " << invalidatedConfig.name();
+ QTest::qWait(60000);
+ QVERIFY(!invalidatedConfig.isValid());
+ QVERIFY(invalidatedSession.state() == QNetworkSession::Invalid);
+ qDebug() << "Add the WLAN IAP back (waiting 60 seconds): " << invalidatedConfig.name();
+ QTest::qWait(60000);
+ }
+
QNetworkConfiguration definedConfig = suitableConfiguration("WLAN",QNetworkConfiguration::InternetAccessPoint);
if (definedConfig.isValid()) {
- // 3. Verify that opening a session with defined configuration emits error and enters notavailable-state
+ // 4. Verify that opening a session with defined configuration emits error and enters notavailable-state
// TODO these timer waits should be changed to waiting appropriate signals, now these wait excessively
qDebug() << "Shutdown WLAN IAP (waiting 60 seconds): " << definedConfig.name();
QTest::qWait(60000);
@@ -283,43 +313,27 @@ void tst_QNetworkSession::invalidSession()
QNetworkSession definedSession(definedConfig);
QSignalSpy errorSpy(&definedSession, SIGNAL(error(QNetworkSession::SessionError)));
QNetworkSession::SessionError sessionError;
+ updateConfigurations();
definedSession.open();
+#ifdef Q_OS_SYMBIAN
+ // On symbian, the connection opening is tried even with defined state.
+ qDebug("Waiting for 10 seconds to all signals to propagate.");
+ QTest::qWait(10000);
+#endif
+ updateConfigurations();
QVERIFY(definedConfig.isValid()); // Session remains valid
QVERIFY(definedSession.state() == QNetworkSession::NotAvailable); // State is not available because WLAN is not in coverage
QVERIFY(!errorSpy.isEmpty()); // Session tells with error about invalidated configuration
sessionError = qvariant_cast<QNetworkSession::SessionError> (errorSpy.first().at(0));
- qDebug() << "Error code is: " << sessionError;
QVERIFY(sessionError == QNetworkSession::InvalidConfigurationError);
-
qDebug() << "Turn the WLAN IAP back on (waiting 60 seconds): " << definedConfig.name();
QTest::qWait(60000);
- updateConfigurations();
-
+ updateConfigurations();
QVERIFY(definedConfig.state() == QNetworkConfiguration::Discovered);
}
-
- QNetworkConfiguration invalidatedConfig = suitableConfiguration("WLAN",QNetworkConfiguration::InternetAccessPoint);
- if (invalidatedConfig.isValid()) {
- // 4. Verify that invalidating a session after its successfully configured works
- QNetworkSession invalidatedSession(invalidatedConfig);
- QSignalSpy errorSpy(&invalidatedSession, SIGNAL(error(QNetworkSession::SessionError)));
- QNetworkSession::SessionError sessionError;
-
- qDebug() << "Delete the WLAN IAP from phone now (waiting 60 seconds): " << invalidatedConfig.name();
- QTest::qWait(60000);
-
- invalidatedSession.open();
- QVERIFY(!invalidatedConfig.isValid());
- QVERIFY(invalidatedSession.state() == QNetworkSession::Invalid);
- QVERIFY(!errorSpy.isEmpty());
-
- sessionError = qvariant_cast<QNetworkSession::SessionError> (errorSpy.first().at(0));
- QVERIFY(sessionError == QNetworkSession::InvalidConfigurationError);
- qDebug() << "Add the WLAN IAP back (waiting 60 seconds): " << invalidatedConfig.name();
- QTest::qWait(60000);
- }
+
#endif
}
@@ -337,12 +351,12 @@ void tst_QNetworkSession::sessionProperties_data()
void tst_QNetworkSession::sessionProperties()
{
+ if (!testsToRun["sessionProperties"]) {
+ QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);
+ }
QFETCH(QNetworkConfiguration, configuration);
-
QNetworkSession session(configuration);
-
QVERIFY(session.configuration() == configuration);
-
QStringList validBearerNames = QStringList() << QLatin1String("Unknown")
<< QLatin1String("Ethernet")
<< QLatin1String("WLAN")
@@ -356,9 +370,6 @@ void tst_QNetworkSession::sessionProperties()
if (!configuration.isValid()) {
QVERIFY(configuration.bearerName().isEmpty());
} else {
- qDebug() << "Type:" << configuration.type()
- << "Bearer:" << configuration.bearerName();
-
switch (configuration.type())
{
case QNetworkConfiguration::ServiceNetwork:
@@ -374,9 +385,7 @@ void tst_QNetworkSession::sessionProperties()
// QNetworkSession::interface() should return an invalid interface unless
// session is in the connected state.
- qDebug() << "Session state:" << session.state();
#ifndef QT_NO_NETWORKINTERFACE
- qDebug() << "Session iface:" << session.interface().isValid() << session.interface().name();
#if !(defined(Q_OS_SYMBIAN) && defined(__WINS__))
// On Symbian emulator, the support for data bearers is limited
QCOMPARE(session.state() == QNetworkSession::Connected, session.interface().isValid());
@@ -420,7 +429,12 @@ void tst_QNetworkSession::repeatedOpenClose_data() {
}
// Tests repeated-open close.
-void tst_QNetworkSession::repeatedOpenClose() {
+void tst_QNetworkSession::repeatedOpenClose()
+{
+ if (!testsToRun["repeatedOpenClose"]) {
+ QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);
+ }
+
QFETCH(QString, bearerType);
QFETCH(QNetworkConfiguration::Type, configurationType);
QFETCH(int, repeatTimes);
@@ -436,13 +450,20 @@ void tst_QNetworkSession::repeatedOpenClose() {
!closeSession(&permanentSession)) {
QSKIP("Unable to open/close session, skipping this round of repeated open-close test.", SkipSingle);
}
- for (int i = repeatTimes; i > 0; i--) {
+ for (int i = 0; i < repeatTimes; i++) {
+ qDebug() << "Opening, loop number " << i;
QVERIFY(openSession(&permanentSession));
+ qDebug() << "Closing, loop number, then waiting 5 seconds: " << i;
QVERIFY(closeSession(&permanentSession));
+ QTest::qWait(5000);
}
}
-void tst_QNetworkSession::roamingErrorCodes() {
+void tst_QNetworkSession::roamingErrorCodes()
+{
+ if (!testsToRun["roamingErrorCodes"]) {
+ QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);
+ }
#ifndef Q_OS_SYMBIAN
QSKIP("Roaming supported on Symbian.", SkipAll);
#else
@@ -466,41 +487,11 @@ void tst_QNetworkSession::roamingErrorCodes() {
adminIapSession.stop(); // requires NetworkControl capabilities
QTRY_VERIFY(!errorSpy.isEmpty()); // wait for error signals
QNetworkSession::SessionError error = qvariant_cast<QNetworkSession::SessionError>(errorSpy.first().at(0));
+ QTest::qWait(2000); // Wait for a moment to all platform signals to propagate
QVERIFY(error == QNetworkSession::SessionAbortedError);
QVERIFY(iapSession.state() == QNetworkSession::Disconnected);
QVERIFY(adminIapSession.state() == QNetworkSession::Disconnected);
#endif // Q_OS_SYMBIAN
-
-#ifdef QNETWORKSESSION_MANUAL_TESTS
- // Check for roaming error.
- // Case requires that you have controllable WLAN in Internet SNAP (only).
- QNetworkConfiguration snapConfig = suitableConfiguration("bearer_not_relevant_with_snaps", QNetworkConfiguration::ServiceNetwork);
- if (!snapConfig.isValid()) {
- QSKIP("No SNAP accessible, skipping test.", SkipAll);
- }
- QNetworkSession snapSession(snapConfig);
- QVERIFY(openSession(&snapSession));
- QSignalSpy errorSpySnap(&snapSession, SIGNAL(error(QNetworkSession::SessionError)));
- qDebug("Disconnect the WLAN now");
- QTRY_VERIFY(!errorSpySnap.isEmpty()); // wait for error signals
- QVERIFY(errorSpySnap.count() == 1);
- error = qvariant_cast<QNetworkSession::SessionError>(errorSpySnap.first().at(0));
- qDebug() << "Error received when turning off wlan on SNAP: " << error;
- QVERIFY(error == QNetworkSession::RoamingError);
-
- qDebug("Connect the WLAN now");
- QTest::qWait(60000); // Wait for WLAN to get up
- QNetworkConfiguration wlanIapConfig2 = suitableConfiguration("WLAN", QNetworkConfiguration::InternetAccessPoint);
- QNetworkSession iapSession2(wlanIapConfig2);
- QVERIFY(openSession(&iapSession2));
- QSignalSpy errorSpy2(&iapSession2, SIGNAL(error(QNetworkSession::SessionError)));
- qDebug("Disconnect the WLAN now");
- QTRY_VERIFY(!errorSpy2.isEmpty()); // wait for error signals
- QVERIFY(errorSpy2.count() == 1);
- error = qvariant_cast<QNetworkSession::SessionError>(errorSpy2.first().at(0));
- QVERIFY(error == QNetworkSession::SessionAbortedError);
- QVERIFY(iapSession2.state() == QNetworkSession::Disconnected);
-#endif
}
@@ -515,6 +506,9 @@ void tst_QNetworkSession::sessionStop_data() {
void tst_QNetworkSession::sessionStop()
{
+ if (!testsToRun["sessionStop"]) {
+ QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);
+ }
#ifndef Q_OS_SYMBIAN
QSKIP("Testcase contains mainly Symbian specific checks, because it is only platform to really support interface (IAP-level) Stop.", SkipAll);
#endif
@@ -522,6 +516,9 @@ void tst_QNetworkSession::sessionStop()
QFETCH(QNetworkConfiguration::Type, configurationType);
int configWaitdelayInMs = 2000;
+
+ updateConfigurations();
+ printConfigurations();
QNetworkConfiguration config = suitableConfiguration(bearerType, configurationType);
if (!config.isValid()) {
@@ -539,6 +536,9 @@ void tst_QNetworkSession::sessionStop()
QSignalSpy closedSessionStateChangedSpy(&closedSession, SIGNAL(stateChanged(QNetworkSession::State)));
QSignalSpy closedErrorSpy(&closedSession, SIGNAL(error(QNetworkSession::SessionError)));
+ QSignalSpy openedSessionClosedSpy(&openedSession, SIGNAL(closed()));
+ QSignalSpy openedSessionStateChangedSpy(&openedSession, SIGNAL(stateChanged(QNetworkSession::State)));
+
QSignalSpy innocentSessionClosedSpy(&innocentSession, SIGNAL(closed()));
QSignalSpy innocentSessionStateChangedSpy(&innocentSession, SIGNAL(stateChanged(QNetworkSession::State)));
QSignalSpy innocentErrorSpy(&innocentSession, SIGNAL(error(QNetworkSession::SessionError)));
@@ -554,10 +554,18 @@ void tst_QNetworkSession::sessionStop()
closedSessionClosedSpy.clear();
closedSessionStateChangedSpy.clear();
closedErrorSpy.clear();
+ openedSessionStateChangedSpy.clear();
+ openedSessionClosedSpy.clear();
+
openedSession.stop();
- QVERIFY(openedSession.state() == QNetworkSession::Disconnected);
+ qDebug("Waiting for %d ms to get all configurationChange signals from platform.", configWaitdelayInMs);
QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
+
+ // First to closing, then to disconnected
+ QVERIFY(openedSessionStateChangedSpy.count() == 2);
+ QVERIFY(!openedSessionClosedSpy.isEmpty());
+ QVERIFY(openedSession.state() == QNetworkSession::Disconnected);
QVERIFY(config.state() != QNetworkConfiguration::Active);
// 2. Verify that stopping a session based on non-connected configuration does nothing
@@ -583,18 +591,20 @@ void tst_QNetworkSession::sessionStop()
// 3. Check that stopping a opened session affects also other opened session based on the same configuration.
if (config.type() == QNetworkConfiguration::InternetAccessPoint) {
qDebug("----------3. Check that stopping a opened session affects also other opened session based on the same configuration.");
+
QVERIFY(openSession(&openedSession));
QVERIFY(openSession(&innocentSession));
-
+
configChangeSpy.clear();
innocentSessionClosedSpy.clear();
innocentSessionStateChangedSpy.clear();
innocentErrorSpy.clear();
-
+
openedSession.stop();
qDebug("Waiting for %d ms to get all configurationChange signals from platform.", configWaitdelayInMs);
QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
-
+ QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
+
QVERIFY(!innocentSessionClosedSpy.isEmpty());
QVERIFY(!innocentSessionStateChangedSpy.isEmpty());
QVERIFY(!innocentErrorSpy.isEmpty());
@@ -614,14 +624,19 @@ void tst_QNetworkSession::sessionStop()
if (config.type() == QNetworkConfiguration::ServiceNetwork) {
qDebug("----------4. Skip for SNAP configuration.");
} else if (config.type() == QNetworkConfiguration::InternetAccessPoint) {
- qDebug("----------4. Check that stopping a non-opened session stops the other session based on the same configuration");
- QVERIFY(openSession(&innocentSession));
+ qDebug("----------4. Check that stopping a non-opened session stops the other session based on the same configuration");
+ qDebug("----------4.1 Opening innocent session");
+ QVERIFY(openSession(&innocentSession));
qDebug("Waiting for %d ms after open to make sure all platform indications are propagated", configWaitdelayInMs);
QTest::qWait(configWaitdelayInMs);
+ qDebug("----------4.2 Calling closedSession.stop()");
closedSession.stop();
qDebug("Waiting for %d ms to get all configurationChange signals from platform..", configWaitdelayInMs);
QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
+ QTest::qWait(configWaitdelayInMs);
+ QTest::qWait(configWaitdelayInMs);
+
QVERIFY(!innocentSessionClosedSpy.isEmpty());
QVERIFY(!innocentSessionStateChangedSpy.isEmpty());
QVERIFY(!innocentErrorSpy.isEmpty());
@@ -653,6 +668,9 @@ void tst_QNetworkSession::userChoiceSession_data()
void tst_QNetworkSession::userChoiceSession()
{
+ if (!testsToRun["userChoiceSession"]) {
+ QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);
+ }
QFETCH(QNetworkConfiguration, configuration);
QVERIFY(configuration.type() == QNetworkConfiguration::UserChoice);
@@ -682,7 +700,20 @@ void tst_QNetworkSession::userChoiceSession()
session.open();
+#if defined(Q_OS_SYMBIAN)
+ // Opening & closing multiple connections in a row sometimes
+ // results hanging of connection opening on Symbian devices
+ // => If first open fails, wait a moment and try again.
+ if (!session.waitForOpened()) {
+ qDebug("**** Session open Timeout - Wait 5 seconds and try once again ****");
+ session.close();
+ QTest::qWait(5000); // Wait a while before trying to open session again
+ session.open();
+ session.waitForOpened();
+ }
+#else
session.waitForOpened();
+#endif
if (session.isOpen())
QVERIFY(!sessionOpenedSpy.isEmpty() || !errorSpy.isEmpty());
@@ -786,6 +817,9 @@ void tst_QNetworkSession::sessionOpenCloseStop_data()
void tst_QNetworkSession::sessionOpenCloseStop()
{
+ if (!testsToRun["sessionOpenCloseStop"]) {
+ QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);
+ }
QFETCH(QNetworkConfiguration, configuration);
QFETCH(bool, forceSessionStop);
@@ -818,7 +852,20 @@ void tst_QNetworkSession::sessionOpenCloseStop()
session.open();
+#if defined(Q_OS_SYMBIAN)
+ // Opening & closing multiple connections in a row sometimes
+ // results hanging of connection opening on Symbian devices
+ // => If first open fails, wait a moment and try again.
+ if (!session.waitForOpened()) {
+ qDebug("**** Session open Timeout - Wait 5 seconds and try once again ****");
+ session.close();
+ QTest::qWait(5000); // Wait a while before trying to open session again
+ session.open();
+ session.waitForOpened();
+ }
+#else
session.waitForOpened();
+#endif
if (session.isOpen())
QVERIFY(!sessionOpenedSpy.isEmpty() || !errorSpy.isEmpty());
@@ -894,26 +941,30 @@ void tst_QNetworkSession::sessionOpenCloseStop()
QVERIFY(session.error() == QNetworkSession::UnknownSessionError);
session2.open();
-
+
QTRY_VERIFY(!sessionOpenedSpy2.isEmpty() || !errorSpy2.isEmpty());
+ if (errorSpy2.isEmpty()) {
+ QVERIFY(session2.isOpen());
+ QVERIFY(session2.state() == QNetworkSession::Connected);
+ }
QVERIFY(session.isOpen());
- QVERIFY(session2.isOpen());
QVERIFY(session.state() == QNetworkSession::Connected);
- QVERIFY(session2.state() == QNetworkSession::Connected);
#ifndef QT_NO_NETWORKINTERFACE
#if !(defined(Q_OS_SYMBIAN) && defined(__WINS__))
// On Symbian emulator, the support for data bearers is limited
QVERIFY(session.interface().isValid());
#endif
- QCOMPARE(session.interface().hardwareAddress(), session2.interface().hardwareAddress());
- QCOMPARE(session.interface().index(), session2.interface().index());
+ if (errorSpy2.isEmpty()) {
+ QCOMPARE(session.interface().hardwareAddress(), session2.interface().hardwareAddress());
+ QCOMPARE(session.interface().index(), session2.interface().index());
+ }
#endif
}
sessionOpenedSpy2.clear();
- if (forceSessionStop) {
+ if (forceSessionStop && session2.isOpen()) {
// Test forcing the second session to stop the interface.
QNetworkSession::State previousState = session.state();
#ifdef Q_CC_NOKIAX86
@@ -922,15 +973,17 @@ void tst_QNetworkSession::sessionOpenCloseStop()
#else
bool expectStateChange = previousState != QNetworkSession::Disconnected;
#endif
-
session2.stop();
+ // QNetworkSession::stop() must result either closed() signal
+ // or error() signal
QTRY_VERIFY(!sessionClosedSpy2.isEmpty() || !errorSpy2.isEmpty());
-
QVERIFY(!session2.isOpen());
if (!errorSpy2.isEmpty()) {
- QVERIFY(!errorSpy.isEmpty());
+ // QNetworkSession::stop() resulted error() signal for session2
+ // => also session should emit error() signal
+ QTRY_VERIFY(!errorSpy.isEmpty());
// check for SessionAbortedError
QNetworkSession::SessionError error =
@@ -950,9 +1003,12 @@ void tst_QNetworkSession::sessionOpenCloseStop()
QVERIFY(errorSpy.isEmpty());
QVERIFY(errorSpy2.isEmpty());
-
+
+ // Wait for Disconnected state
+ QTRY_NOOP(session2.state() == QNetworkSession::Disconnected);
+
if (expectStateChange)
- QTRY_VERIFY(stateChangedSpy2.count() >= 2 || !errorSpy2.isEmpty());
+ QTRY_VERIFY(stateChangedSpy2.count() >= 1 || !errorSpy2.isEmpty());
if (!errorSpy2.isEmpty()) {
QVERIFY(session2.state() == previousState);
@@ -996,16 +1052,29 @@ void tst_QNetworkSession::sessionOpenCloseStop()
state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(3).at(0));
QVERIFY(state == QNetworkSession::Disconnected);
+
+ QTRY_VERIFY(session.state() == QNetworkSession::Roaming ||
+ session.state() == QNetworkSession::Connected ||
+ session.state() == QNetworkSession::Disconnected);
+
QTRY_VERIFY(stateChangedSpy.count() > 0);
- state = qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(0).at(0));
+ state = qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(stateChangedSpy.count() - 1).at(0));
+
if (state == QNetworkSession::Roaming) {
- QTRY_VERIFY(!errorSpy.isEmpty() || stateChangedSpy.count() > 1);
- if (stateChangedSpy.count() > 1 &&
- qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(1).at(0)) ==
- QNetworkSession::Connected) {
- roamedSuccessfully = true;
+ QTRY_VERIFY(session.state() == QNetworkSession::Connected);
+ QTRY_VERIFY(session2.state() == QNetworkSession::Connected);
+ roamedSuccessfully = true;
+ } else if (state == QNetworkSession::Disconnected) {
+ QTRY_VERIFY(!errorSpy.isEmpty());
+ QTRY_VERIFY(session2.state() == QNetworkSession::Disconnected);
+ } else if (state == QNetworkSession::Connected) {
+ QTRY_VERIFY(errorSpy.isEmpty());
+ if (stateChangedSpy.count() > 1) {
+ state = qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(stateChangedSpy.count() - 2).at(0));
+ QVERIFY(state == QNetworkSession::Roaming);
}
- }
+ roamedSuccessfully = true;
+ }
if (roamedSuccessfully) {
QString configId = session.sessionProperty("ActiveConfiguration").toString();
@@ -1013,37 +1082,36 @@ void tst_QNetworkSession::sessionOpenCloseStop()
QNetworkSession session3(config);
QSignalSpy errorSpy3(&session3, SIGNAL(error(QNetworkSession::SessionError)));
QSignalSpy sessionOpenedSpy3(&session3, SIGNAL(opened()));
-
session3.open();
- session3.waitForOpened();
-
+ session3.waitForOpened();
if (session.isOpen())
QVERIFY(!sessionOpenedSpy3.isEmpty() || !errorSpy3.isEmpty());
-
session.stop();
-
QTRY_VERIFY(session.state() == QNetworkSession::Disconnected);
- QTRY_VERIFY(session3.state() == QNetworkSession::Disconnected);
}
#ifndef Q_CC_NOKIAX86
if (!roamedSuccessfully)
QVERIFY(!errorSpy.isEmpty());
#endif
} else {
- QCOMPARE(stateChangedSpy2.count(), 2);
-
- QNetworkSession::State state =
- qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(0).at(0));
- QVERIFY(state == QNetworkSession::Closing);
-
- state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(1).at(0));
- QVERIFY(state == QNetworkSession::Disconnected);
+ QTest::qWait(2000); // Wait awhile to get all signals from platform
+
+ if (stateChangedSpy2.count() == 2) {
+ QNetworkSession::State state =
+ qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(0).at(0));
+ QVERIFY(state == QNetworkSession::Closing);
+ state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(1).at(0));
+ QVERIFY(state == QNetworkSession::Disconnected);
+ } else { // Assume .count() == 1
+ QCOMPARE(stateChangedSpy2.count(), 1);
+ QNetworkSession::State state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(0).at(0));
+ // Symbian version dependant.
+ QVERIFY(state == QNetworkSession::Disconnected);
+ }
}
QTRY_VERIFY(!sessionClosedSpy.isEmpty());
-
QTRY_VERIFY(session.state() == QNetworkSession::Disconnected);
- QTRY_VERIFY(session2.state() == QNetworkSession::Disconnected);
}
QVERIFY(errorSpy2.isEmpty());
@@ -1062,7 +1130,7 @@ void tst_QNetworkSession::sessionOpenCloseStop()
QVERIFY(!session.isOpen());
#endif
QVERIFY(!session2.isOpen());
- } else {
+ } else if (session2.isOpen()) {
// Test closing the second session.
{
int stateChangedCountBeforeClose = stateChangedSpy2.count();
@@ -1161,11 +1229,15 @@ QDebug operator<<(QDebug debug, const QList<QNetworkConfiguration> &list)
// at Discovered -state.
void tst_QNetworkSession::outOfProcessSession()
{
- qDebug() << "START";
-
+ if (!testsToRun["outOfProcessSession"]) {
+ QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);
+ }
#if defined(Q_OS_SYMBIAN) && defined(__WINS__)
QSKIP("Symbian emulator does not support two [QR]PRocesses linking a dll (QtBearer.dll) with global writeable static data.", SkipAll);
#endif
+ updateConfigurations();
+ QTest::qWait(2000);
+
QNetworkConfigurationManager manager;
// Create a QNetworkConfigurationManager to detect configuration changes made in Lackey. This
// is actually the essence of this testcase - to check that platform mediates/reflects changes
@@ -1182,16 +1254,15 @@ void tst_QNetworkSession::outOfProcessSession()
QLocalServer::removeServer("tst_qnetworksession");
oopServer.listen("tst_qnetworksession");
- qDebug() << "starting lackey";
QProcess lackey;
lackey.start("lackey/lackey");
qDebug() << lackey.error() << lackey.errorString();
QVERIFY(lackey.waitForStarted());
- qDebug() << "waiting for connection";
+
QVERIFY(oopServer.waitForNewConnection(-1));
QLocalSocket *oopSocket = oopServer.nextPendingConnection();
- qDebug() << "got connection";
+
do {
QByteArray output;
@@ -1258,7 +1329,6 @@ void tst_QNetworkSession::outOfProcessSession()
default:
QSKIP("Lackey failed", SkipAll);
}
- qDebug("STOP");
}
// A convinience / helper function for testcases. Return the first matching configuration.
@@ -1269,6 +1339,7 @@ QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfigur
// 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) {
@@ -1277,8 +1348,7 @@ QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfigur
}
QList<QNetworkConfiguration> discoveredConfigs = mgr.allConfigurations(QNetworkConfiguration::Discovered);
foreach(QNetworkConfiguration config, discoveredConfigs) {
- if ((config.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
- // qDebug() << "Dumping config because is active: " << config.name();
+ 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();
@@ -1315,9 +1385,23 @@ void updateConfigurations()
QTRY_NOOP(updateSpy.count() == 1);
}
+// A convinience-function: updates and prints all available confiurations and their states
+void printConfigurations()
+{
+ QNetworkConfigurationManager manager;
+ QList<QNetworkConfiguration> allConfigs =
+ manager.allConfigurations();
+ qDebug("tst_QNetworkSession::printConfigurations QNetworkConfigurationManager gives following configurations: ");
+ foreach(QNetworkConfiguration config, allConfigs) {
+ qDebug() << "Name of the configuration: " << config.name();
+ qDebug() << "State of the configuration: " << config.state();
+ }
+}
+
// A convinience function for test-cases: opens the given configuration and return
// true if it was done gracefully.
bool openSession(QNetworkSession *session) {
+ bool result = true;
QNetworkConfigurationManager mgr;
QSignalSpy openedSpy(session, SIGNAL(opened()));
QSignalSpy stateChangeSpy(session, SIGNAL(stateChanged(QNetworkSession::State)));
@@ -1327,43 +1411,57 @@ bool openSession(QNetworkSession *session) {
// active by some other session
QNetworkConfiguration::StateFlags configInitState = session->configuration().state();
QNetworkSession::State sessionInitState = session->state();
+ qDebug() << "tst_QNetworkSession::openSession() name of the configuration to be opened: " << session->configuration().name();
+ qDebug() << "tst_QNetworkSession::openSession() state of the configuration to be opened: " << session->configuration().state();
+ qDebug() << "tst_QNetworkSession::openSession() state of the session to be opened: " << session->state();
if (session->isOpen() ||
!session->sessionProperty("ActiveConfiguration").toString().isEmpty()) {
qDebug("tst_QNetworkSession::openSession() failure: session was already open / active.");
- return false;
+ result = false;
} else {
session->open();
session->waitForOpened(120000); // Bringing interfaces up and down may take time at platform
}
+ QTest::qWait(5000); // Wait a moment to ensure all signals are propagated
// Check that connection opening went by the book. Add checks here if more strictness needed.
if (!session->isOpen()) {
qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::open() failed.");
- return false;
+ result = false;
}
if (openedSpy.count() != 1) {
qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::opened() - signal not received.");
- return false;
+ result = false;
}
if (!errorSpy.isEmpty()) {
qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::error() - signal was detected.");
- return false;
+ result = false;
}
if (sessionInitState != QNetworkSession::Connected &&
stateChangeSpy.isEmpty()) {
qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::stateChanged() - signals not detected.");
- return false;
+ result = false;
}
if (configInitState != QNetworkConfiguration::Active &&
configChangeSpy.isEmpty()) {
qDebug("tst_QNetworkSession::openSession() failure: QNetworkConfigurationManager::configurationChanged() - signals not detected.");
- return false;
+ result = false;
}
if (session->configuration().state() != QNetworkConfiguration::Active) {
qDebug("tst_QNetworkSession::openSession() failure: session's configuration is not in 'Active' -state.");
- return false;
+ qDebug() << "tst_QNetworkSession::openSession() state is: " << session->configuration().state();
+ result = false;
+ }
+ if (result == false) {
+ qDebug() << "tst_QNetworkSession::openSession() opening session failed.";
+ } else {
+ qDebug() << "tst_QNetworkSession::openSession() opening session succeeded.";
}
- return true;
+ qDebug() << "tst_QNetworkSession::openSession() name of the configuration is: " << session->configuration().name();
+ qDebug() << "tst_QNetworkSession::openSession() configuration state is: " << session->configuration().state();
+ qDebug() << "tst_QNetworkSession::openSession() session state is: " << session->state();
+
+ return result;
}
// Helper function for closing opened session. Performs checks that
@@ -1376,6 +1474,11 @@ bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration) {
qDebug("tst_QNetworkSession::closeSession() failure: NULL session given");
return false;
}
+
+ qDebug() << "tst_QNetworkSession::closeSession() name of the configuration to be closed: " << session->configuration().name();
+ qDebug() << "tst_QNetworkSession::closeSession() state of the configuration to be closed: " << session->configuration().state();
+ qDebug() << "tst_QNetworkSession::closeSession() state of the session to be closed: " << session->state();
+
if (session->state() != QNetworkSession::Connected ||
!session->isOpen()) {
qDebug("tst_QNetworkSession::closeSession() failure: session is not opened.");
@@ -1387,38 +1490,48 @@ bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration) {
QSignalSpy sessionErrorSpy(session, SIGNAL(error(QNetworkSession::SessionError)));
QSignalSpy configChangeSpy(&mgr, SIGNAL(configurationChanged(QNetworkConfiguration)));
+ bool result = true;
session->close();
+ QTest::qWait(5000); // Wait a moment so that all signals are propagated
if (!sessionErrorSpy.isEmpty()) {
qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession::error() received.");
- return false;
+ result = false;
}
if (sessionClosedSpy.count() != 1) {
qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession::closed() signal not received.");
- return false;
+ result = false;
}
if (lastSessionOnConfiguration &&
sessionStateChangedSpy.isEmpty()) {
qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession::stateChanged() signals not received.");
- return false;
+ result = false;
}
if (lastSessionOnConfiguration &&
session->state() != QNetworkSession::Disconnected) {
qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession is not in Disconnected -state");
- return false;
+ result = false;
}
QTRY_NOOP(!configChangeSpy.isEmpty());
if (lastSessionOnConfiguration &&
configChangeSpy.isEmpty()) {
qDebug("tst_QNetworkSession::closeSession() failure: QNetworkConfigurationManager::configurationChanged() - signal not detected.");
- return false;
+ result = false;
}
if (lastSessionOnConfiguration &&
session->configuration().state() == QNetworkConfiguration::Active) {
qDebug("tst_QNetworkSession::closeSession() failure: session's configuration is still in active state.");
- return false;
+ result = false;
}
- return true;
+ if (result == false) {
+ qDebug() << "tst_QNetworkSession::closeSession() closing session failed.";
+ } else {
+ qDebug() << "tst_QNetworkSession::closeSession() closing session succeeded.";
+ }
+ qDebug() << "tst_QNetworkSession::closeSession() name of the configuration is: " << session->configuration().name();
+ qDebug() << "tst_QNetworkSession::closeSession() configuration state is: " << session->configuration().state();
+ qDebug() << "tst_QNetworkSession::closeSession() session state is: " << session->state();
+ return result;
}
void tst_QNetworkSession::sessionAutoClose_data()
diff --git a/tests/manual/bearerex/bearerex.cpp b/tests/manual/bearerex/bearerex.cpp
index 19246a2..bf60dd1 100644
--- a/tests/manual/bearerex/bearerex.cpp
+++ b/tests/manual/bearerex/bearerex.cpp
@@ -300,8 +300,12 @@ SessionTab::SessionTab(QNetworkConfiguration* apNetworkConfiguration,
SessionTab::~SessionTab()
{
+ // Need to be nulled, because modal dialogs may return after destruction of this object and
+ // use already released resources.
delete m_NetworkSession;
+ m_NetworkSession = NULL;
delete m_http;
+ m_http = NULL;
}
void SessionTab::on_createQHttpButton_clicked()
@@ -551,10 +555,16 @@ void SessionTab::done(bool error)
msgBox.setText(QString("HTTP request finished successfully.\nReceived ")+QString::number(result.length())+QString(" bytes."));
}
msgBox.exec();
-
- sentRecDataLineEdit->setText(QString::number(m_NetworkSession->bytesWritten())+
- QString(" / ")+
- QString::number(m_NetworkSession->bytesReceived()));
+ // Check if the networksession still exists - it may have gone after returning from
+ // the modal dialog (in the case that app has been closed, and deleting QHttp will
+ // trigger the done() invokation).
+ if (m_NetworkSession) {
+ sentRecDataLineEdit->setText(QString::number(m_NetworkSession->bytesWritten())+
+ QString(" / ")+
+ QString::number(m_NetworkSession->bytesReceived()));
+ } else {
+ sentRecDataLineEdit->setText("Data amounts not available.");
+ }
}
// End of file