Merge "Merge remote-tracking branch 'origin/5.4' into dev" into refs/staging/dev

This commit is contained in:
Frederik Gladhorn 2014-10-27 13:22:37 +01:00 committed by The Qt Project
commit af3bd5037a
163 changed files with 2573 additions and 1628 deletions

12
dist/changes-5.4.0 vendored
View File

@ -31,3 +31,15 @@ QtSql
- qsql ibase: fix memory corruption due to LONG being 4 bytes in firebird.
- QSqlDriver::dbmsType(): New method reports DBMS type. Especially useful when using ODBC.
****************************************************************************
* Platform Specific Changes *
****************************************************************************
OS X
----
- OS X 10.6 is no longer supported.
- OS X 10.10 is now supported.
- QMacStyle has been updated with better OS 10.10 support.
- The Qt binary packages are now configured with C++11 enabled.

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
@ -46,6 +46,7 @@
#include <QtWidgets/QScrollBar>
#include <QtWidgets/QStyle>
#include <QtWidgets/QToolButton>
#include <QtWidgets/QMessageBox>
#include <QtNetwork/QSslCipher>
SslClient::SslClient(QWidget *parent)
@ -96,6 +97,8 @@ void SslClient::secureConnect()
this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
connect(socket, SIGNAL(encrypted()),
this, SLOT(socketEncrypted()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(socketError(QAbstractSocket::SocketError)));
connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(sslErrors(QList<QSslError>)));
connect(socket, SIGNAL(readyRead()),
@ -118,8 +121,6 @@ void SslClient::socketStateChanged(QAbstractSocket::SocketState state)
form->cipherLabel->setText(tr("<none>"));
if (padLock)
padLock->hide();
socket->deleteLater();
socket = 0;
}
}
@ -180,6 +181,11 @@ void SslClient::sendData()
form->sessionInput->clear();
}
void SslClient::socketError(QAbstractSocket::SocketError error)
{
QMessageBox::critical(this, tr("Connection error"), socket->errorString());
}
void SslClient::sslErrors(const QList<QSslError> &errors)
{
QDialog errorDialog(this);

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
@ -65,6 +65,7 @@ private slots:
void socketEncrypted();
void socketReadyRead();
void sendData();
void socketError(QAbstractSocket::SocketError error);
void sslErrors(const QList<QSslError> &errors);
void displayCertificateInfo();

View File

@ -75,26 +75,31 @@ int main( int argc, char ** argv )
+ QLatin1Char('/') + getGlString(topLevelGlWidget.context()->functions(), GL_RENDERER);
const bool supportsThreading = !glInfo.contains(QLatin1String("nouveau"), Qt::CaseInsensitive)
&& !glInfo.contains(QLatin1String("ANGLE"), Qt::CaseInsensitive);
&& !glInfo.contains(QLatin1String("ANGLE"), Qt::CaseInsensitive)
&& !glInfo.contains(QLatin1String("llvmpipe"), Qt::CaseInsensitive);
const QString toolTip = supportsThreading ? glInfo : glInfo + QStringLiteral("\ndoes not support threaded OpenGL.");
topLevelGlWidget.setToolTip(toolTip);
QScopedPointer<MainWindow> mw1;
QScopedPointer<MainWindow> mw2;
if (supportsThreading && !QApplication::arguments().contains(QStringLiteral("--single"))) {
pos += QPoint(100, 100);
mw1.reset(new MainWindow);
mw1->setToolTip(toolTip);
mw1->move(pos);
mw1->setWindowTitle(QStringLiteral("Threaded QOpenGLWidget example #1"));
mw1->show();
pos += QPoint(100, 100);
mw2.reset(new MainWindow);
mw2->setToolTip(toolTip);
mw2->move(pos);
mw2->setWindowTitle(QStringLiteral("Threaded QOpenGLWidget example #2"));
mw2->show();
if (!QApplication::arguments().contains(QStringLiteral("--single"))) {
if (supportsThreading) {
pos += QPoint(100, 100);
mw1.reset(new MainWindow);
mw1->setToolTip(toolTip);
mw1->move(pos);
mw1->setWindowTitle(QStringLiteral("Threaded QOpenGLWidget example #1"));
mw1->show();
pos += QPoint(100, 100);
mw2.reset(new MainWindow);
mw2->setToolTip(toolTip);
mw2->move(pos);
mw2->setWindowTitle(QStringLiteral("Threaded QOpenGLWidget example #2"));
mw2->show();
} else {
qWarning() << toolTip;
}
}
return a.exec();

View File

@ -474,7 +474,11 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool)
<< attrTag("Condition", condition)
<< valueTag(tool.Configuration.PrimaryOutput);
}
if (!tool.Configuration.PrimaryOutputExtension.isEmpty()) {
xml<< tag("TargetExt")
<< attrTag("Condition", condition)
<< valueTag(tool.Configuration.PrimaryOutputExtension);
}
if ( tool.Configuration.linker.IgnoreImportLibrary != unset) {
xml<< tag("IgnoreImportLibrary")
<< attrTag("Condition", condition)
@ -696,7 +700,11 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool)
<< attrTag("Condition", condition)
<< valueTag(config.PrimaryOutput);
}
if (!config.PrimaryOutputExtension.isEmpty()) {
xml << tag("TargetExt")
<< attrTag("Condition", condition)
<< valueTag(config.PrimaryOutputExtension);
}
if (config.linker.IgnoreImportLibrary != unset) {
xml << tag("IgnoreImportLibrary")
<< attrTag("Condition", condition)

View File

@ -2398,7 +2398,11 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info)
if (!CustomBuildTool.Description.isEmpty())
CustomBuildTool.Description += ", ";
CustomBuildTool.Description += cmd_name;
// Execute custom build steps in an environment variable scope to prevent unwanted
// side effects for downstream build steps
CustomBuildTool.CommandLine += QLatin1String("setlocal");
CustomBuildTool.CommandLine += VCToolBase::fixCommandLine(cmd.trimmed());
CustomBuildTool.CommandLine += QLatin1String("endlocal");
int space = cmd.indexOf(' ');
QFileInfo finf(cmd.left(space));
if (CustomBuildTool.ToolPath.isEmpty())

View File

@ -887,6 +887,7 @@ public:
QString ConfigurationName;
QString OutputDirectory;
QString PrimaryOutput;
QString PrimaryOutputExtension;
QString ProgramDatabase;
QString PlatformToolSet;
triState RegisterOutput;

View File

@ -405,6 +405,21 @@ QString VcprojGenerator::retrievePlatformToolSet() const
}
}
bool VcprojGenerator::isStandardSuffix(const QString &suffix) const
{
if (!project->values("QMAKE_APP_FLAG").isEmpty()) {
if (suffix.compare("exe", Qt::CaseInsensitive) == 0)
return true;
} else if (project->isActiveConfig("shared")) {
if (suffix.compare("dll", Qt::CaseInsensitive) == 0)
return true;
} else {
if (suffix.compare("lib", Qt::CaseInsensitive) == 0)
return true;
}
return false;
}
ProStringList VcprojGenerator::collectDependencies(QMakeProject *proj, QHash<QString, QString> &projLookup,
QHash<QString, QString> &projGuids,
QHash<VcsolutionDepend *, QStringList> &extraSubdirs,
@ -993,12 +1008,12 @@ void VcprojGenerator::initConfiguration()
if (conf.CompilerVersion >= NET2010) {
conf.PlatformToolSet = retrievePlatformToolSet();
// The target name could have been changed.
conf.PrimaryOutput = project->first("TARGET").toQString();
if (!conf.PrimaryOutput.isEmpty() && project->first("TEMPLATE") == "vclib"
&& project->isActiveConfig("shared")) {
conf.PrimaryOutput.append(project->first("TARGET_VERSION_EXT").toQString());
}
const QFileInfo targetInfo = fileInfo(project->first("MSVCPROJ_TARGET").toQString());
conf.PrimaryOutput = targetInfo.completeBaseName();
const QString targetSuffix = targetInfo.suffix();
if (!isStandardSuffix(targetSuffix))
conf.PrimaryOutputExtension = '.' + targetSuffix;
}
if (conf.CompilerVersion >= NET2012) {

View File

@ -137,6 +137,7 @@ private:
const ProStringList &allDependencies = ProStringList());
QUuid increaseUUID(const QUuid &id);
QString retrievePlatformToolSet() const;
bool isStandardSuffix(const QString &suffix) const;
friend class VCFilter;
};

View File

@ -55,6 +55,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.ResultReceiver;
import android.text.method.MetaKeyKeyListener;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
@ -660,6 +661,22 @@ public class QtActivityDelegate
m_applicationParameters += "\t-qmljsdebugger=" + qmljsdebugger;
}
if (extras.containsKey("extraenvvars")) {
try {
m_environmentVariables += "\t" + new String(Base64.decode(extras.getString("extraenvvars"), Base64.DEFAULT), "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
}
if (extras.containsKey("extraappparams")) {
try {
m_applicationParameters += "\t" + new String(Base64.decode(extras.getString("extraappparams"), Base64.DEFAULT), "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
}
if (null == m_surfaces)
onCreate(null);
String nativeLibraryDir = QtNativeLibrariesDir.nativeLibrariesDir(m_activity);

View File

@ -445,6 +445,8 @@ QTextCodec *QIcuCodec::codecForNameUnlocked(const char *name)
// backwards compatibility with Qt 4.x
if (!qstrcmp(name, "CP949"))
name = "windows-949";
else if (!qstrcmp(name, "Apple Roman"))
name = "macintosh";
// these are broken data in ICU 4.4, and can't be resolved even though they are aliases to tis-620
if (!qstrcmp(name, "windows-874-2000")
|| !qstrcmp(name, "windows-874")

View File

@ -346,13 +346,13 @@ QTextCodec::ConverterState::~ConverterState()
The supported encodings are:
\list
\li Apple Roman
\li \l{Big5 Text Codec}{Big5}
\li \l{Big5-HKSCS Text Codec}{Big5-HKSCS}
\li CP949
\li \l{EUC-JP Text Codec}{EUC-JP}
\li \l{EUC-KR Text Codec}{EUC-KR}
\li \l{GBK Text Codec}{GB18030-0}
\li \l{GBK Text Codec}{GB18030}
\li HP-ROMAN8
\li IBM 850
\li IBM 866
\li IBM 874
@ -360,10 +360,9 @@ QTextCodec::ConverterState::~ConverterState()
\li ISO 8859-1 to 10
\li ISO 8859-13 to 16
\li Iscii-Bng, Dev, Gjr, Knd, Mlm, Ori, Pnj, Tlg, and Tml
\li JIS X 0201
\li JIS X 0208
\li KOI8-R
\li KOI8-U
\li Macintosh
\li \l{Shift-JIS Text Codec}{Shift-JIS}
\li TIS-620
\li \l{TSCII Text Codec}{TSCII}

View File

@ -159,11 +159,10 @@
\value AA_UseHighDpiPixmaps Make QIcon::pixmap() generate high-dpi pixmaps
that can be larger than the requested size. Such pixmaps will have
devicePixelRatio set to a value higher than 1.
After setting this attribute application code that uses pixmap
sizes in layout geometry calculations should typically divide by
QPixmap::devicePixelRatio() to get device-independent layout geometry.
devicePixelRatio set to a value higher than 1. After setting this
attribute application code that uses pixmap sizes in layout geometry
calculations should typically divide by QPixmap::devicePixelRatio()
to get device-independent layout geometry.
\value AA_ForceRasterWidgets Make top-level widgets use pure raster surfaces,
and do not support non-native GL-based child widgets.
@ -183,7 +182,7 @@
\l{http://www.mesa3d.org/llvmpipe.html}{Mesa llvmpipe}, providing
OpenGL 2.1. The value may have no effect if no such OpenGL
implementation is available. The default name of this library is
QtSoftwareOpenGL.dll and can be overridden by setting the environment
opengl32sw.dll and can be overridden by setting the environment
variable \e QT_OPENGL_DLL. See the platform-specific pages, for
instance \l{Qt for Windows}, for more information. This value has
been added in Qt 5.4.
@ -191,7 +190,8 @@
\value AA_ShareOpenGLContexts Enables resource sharing between the OpenGL
contexts used by classes like QOpenGLWidget and QQuickWidget. This
allows sharing OpenGL resources, like textures, between QOpenGLWidget
instances that belong to different top-level windows.
instances that belong to different top-level windows. This value has
been added in Qt 5.4.
The following values are obsolete:

View File

@ -206,6 +206,13 @@ QAbstractFileEngine *QFilePrivate::engine() const
directory usually is not writable, but it is still possible to
create files in it.
Qt's understanding of file permissions is limited, which affects especially
the \l QFile::setPermissions() function. On Windows, Qt will set only the
legacy read-only flag, and that only when none of the Write* flags are
passed. Qt does not manipulate access control lists (ACLs), which makes this
function mostly useless for NTFS volumes. It may still be of use for USB
sticks that use VFAT file systems. POSIX ACLs are not manipulated, either.
\sa QTextStream, QDataStream, QFileInfo, QDir, {The Qt Resource System}
*/
@ -1063,9 +1070,12 @@ QFile::permissions(const QString &fileName)
/*!
Sets the permissions for the file to the \a permissions specified.
Returns \c true if successful, or false if the permissions cannot be
Returns \c true if successful, or \c false if the permissions cannot be
modified.
\warning This function does not manipulate ACLs, which may limit its
effectiveness.
\sa permissions(), setFileName()
*/

View File

@ -648,9 +648,12 @@ QFile::Permissions QFileDevice::permissions() const
/*!
Sets the permissions for the file to the \a permissions specified.
Returns \c true if successful, or false if the permissions cannot be
Returns \c true if successful, or \c false if the permissions cannot be
modified.
\warning This function does not manipulate ACLs, which may limit its
effectiveness.
\sa permissions()
*/
bool QFileDevice::setPermissions(Permissions permissions)

View File

@ -61,13 +61,15 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
\brief The QLoggingCategory class represents a category, or 'area' in the
logging infrastructure.
QLoggingCategory represents a certain logging category - identified
by a string - at runtime. Whether a category should be actually logged or
not can be checked with the \l isEnabled() methods.
QLoggingCategory represents a certain logging category - identified by a
string - at runtime. A category can be configured to enable or disable
logging of messages per message type. Whether a message type is enabled or
not can be checked with the \l isDebugEnabled(), \l isWarningEnabled(), and
\l isCriticalEnabled() methods.
All objects are meant to be configured by a common registry (see also
\l{Configuring Categories}). Different objects can also represent the same
category. It's therefore not recommended to export objects across module
category. It is therefore not recommended to export objects across module
boundaries, nor to manipulate the objects directly, nor to inherit from
QLoggingCategory.
@ -110,8 +112,9 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
\section2 Logging Rules
Logging rules allow to enable or disable logging for categories in a flexible
way. Rules are specified in text, where every line must have the format
Logging rules allow logging for categories to be enabled or disabled in a
flexible way. Rules are specified in text, where every line must have the
format
\code
<category>[.<type>] = true|false
@ -120,12 +123,12 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
\c <category> is the name of the category, potentially with \c{*} as a
wildcard symbol as the first or last character (or at both positions).
The optional \c <type> must be either \c debug, \c warning, or \c critical.
Lines that do not fit to his scheme are ignored.
Lines that do not fit this scheme are ignored.
Rules are evaluated in text order, from first to last. That is, if two rules
apply to a category/type, the rule that comes later is applied.
Rules can be set via \l setFilterRules(). Since Qt 5.3 logging rules can also
Rules can be set via \l setFilterRules(). Since Qt 5.3, logging rules can also
be set in the \c QT_LOGGING_RULES environment variable, and
are automatically loaded from the \c [Rules] section of a logging
configuration file. Such configuration files are looked up in the QtProject
@ -168,13 +171,13 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
\section2 Installing a Custom Filter
As a lower-level alternative to the text rules you can also implement a
As a lower-level alternative to the text rules, you can also implement a
custom filter via \l installFilter(). All filter rules are ignored in this
case.
\section1 Printing the Category
Use the \c %{category} place holder to print the category in the default
Use the \c %{category} placeholder to print the category in the default
message handler:
\snippet qloggingcategory/main.cpp 3

View File

@ -2112,6 +2112,21 @@ namespace QtPrivate {
};
}
namespace QtMetaTypePrivate {
inline Q_DECL_CONSTEXPR bool isBuiltinSequentialType(int typeId)
{
return typeId == qMetaTypeId<QStringList>()
|| typeId == qMetaTypeId<QByteArrayList>()
|| typeId == qMetaTypeId<QVariantList>();
}
inline Q_DECL_CONSTEXPR bool isBuiltinAssociativeType(int typeId)
{
return typeId == qMetaTypeId<QVariantHash>()
|| typeId == qMetaTypeId<QVariantMap>();
}
} // QtMetaTypePrivate
QT_END_NAMESPACE
#endif // QMETATYPE_H

View File

@ -1086,6 +1086,11 @@ void QTranslatorPrivate::clear()
\a disambiguation). If none is found, also tries (\a context, \a
sourceText, ""). If that still fails, returns a null string.
\note Incomplete translations may result in unexpected behavior:
If no translation for (\a context, \a sourceText, "")
is provided, the method might in this case actually return a
translation for a different \a disambiguation.
If \a n is not -1, it is used to choose an appropriate form for
the translation (e.g. "%n file found" vs. "%n files found").

View File

@ -3632,11 +3632,13 @@ QSequentialIterable::const_iterator::const_iterator(const const_iterator &other)
QSequentialIterable::const_iterator&
QSequentialIterable::const_iterator::operator=(const const_iterator &other)
{
if (!m_impl.equal(other.m_impl)) {
m_impl = other.m_impl;
ref = other.ref;
other.ref->ref();
if (!ref->deref()) {
m_impl.destroyIter();
delete ref;
}
ref->ref();
m_impl = other.m_impl;
ref = other.ref;
return *this;
}
@ -3941,11 +3943,13 @@ QAssociativeIterable::const_iterator::const_iterator(const const_iterator &other
QAssociativeIterable::const_iterator&
QAssociativeIterable::const_iterator::operator=(const const_iterator &other)
{
if (!m_impl.equal(other.m_impl)) {
m_impl = other.m_impl;
ref = other.ref;
other.ref->ref();
if (!ref->deref()) {
m_impl.destroyIter();
delete ref;
}
ref->ref();
m_impl = other.m_impl;
ref = other.ref;
return *this;
}

View File

@ -736,7 +736,7 @@ namespace QtPrivate {
{
static QVariantList invoke(const QVariant &v)
{
if (v.userType() == qMetaTypeId<QStringList>() || v.userType() == qMetaTypeId<QByteArrayList>() || QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) {
if (QtMetaTypePrivate::isBuiltinSequentialType(v.userType()) || QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) {
QSequentialIterable iter = QVariantValueHelperInterface<QSequentialIterable>::invoke(v);
QVariantList l;
l.reserve(iter.size());
@ -752,7 +752,7 @@ namespace QtPrivate {
{
static QVariantHash invoke(const QVariant &v)
{
if (QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
if (QtMetaTypePrivate::isBuiltinAssociativeType(v.userType()) || QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
QVariantHash l;
l.reserve(iter.size());
@ -768,7 +768,7 @@ namespace QtPrivate {
{
static QVariantMap invoke(const QVariant &v)
{
if (QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
if (QtMetaTypePrivate::isBuiltinAssociativeType(v.userType()) || QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
QVariantMap l;
for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)

View File

@ -166,6 +166,7 @@ QT_BEGIN_NAMESPACE
\value playsSound The object produces sound when interacted with.
\value pressed The object is pressed.
\value readOnly The object can usually be edited, but is explicitly set to read-only.
\value searchEdit The object is a line edit that is the input for search queries.
\value selectable The object is selectable.
\value selectableText The object has text which can be selected. This is different from selectable which refers to the object's children.
\value selected The object is selected, this is independent of text selection.

View File

@ -185,6 +185,8 @@ public:
quint64 selectableText : 1;
quint64 supportsAutoCompletion : 1;
quint64 searchEdit : 1;
// quint64 horizontal : 1;
// quint64 vertical : 1;
// quint64 invalidEntry : 1;

View File

@ -223,6 +223,7 @@ QIconTheme::QIconTheme(const QString &themeName)
// Parent themes provide fallbacks for missing icons
m_parents = indexReader.value(
QLatin1String("Icon Theme/Inherits")).toStringList();
m_parents.removeAll(QString());
// Ensure a default platform fallback for all themes
if (m_parents.isEmpty()) {

View File

@ -877,15 +877,22 @@ QString QImageReader::fileName() const
/*!
\since 4.2
This is an image format specific function that sets the quality
level of the image to \a quality. For image formats that do not
support setting the quality, this value is ignored.
Sets the quality setting of the image format to \a quality.
The value range of \a quality depends on the image format. For
example, the "jpeg" format supports a quality range from 0 (low
quality, high compression) to 100 (high quality, low compression).
Some image formats, in particular lossy ones, entail a tradeoff between a)
visual quality of the resulting image, and b) decoding execution time.
This function sets the level of that tradeoff for image formats that
support it.
\sa quality()
In case of scaled image reading, the quality setting may also influence the
tradeoff level between visual quality and execution speed of the scaling
algorithm.
The value range of \a quality depends on the image format. For example,
the "jpeg" format supports a quality range from 0 (low visual quality) to
100 (high visual quality).
\sa quality() setScaledSize()
*/
void QImageReader::setQuality(int quality)
{
@ -895,7 +902,7 @@ void QImageReader::setQuality(int quality)
/*!
\since 4.2
Returns the quality level of the image.
Returns the quality setting of the image format.
\sa setQuality()
*/

View File

@ -434,13 +434,16 @@ QString QImageWriter::fileName() const
}
/*!
This is an image format specific function that sets the quality
level of the image to \a quality. For image formats that do not
support setting the quality, this value is ignored.
Sets the quality setting of the image format to \a quality.
The value range of \a quality depends on the image format. For
example, the "jpeg" format supports a quality range from 0 (low
quality, high compression) to 100 (high quality, low compression).
Some image formats, in particular lossy ones, entail a tradeoff between a)
visual quality of the resulting image, and b) encoding execution time and
compression level. This function sets the level of that tradeoff for image
formats that support it. For other formats, this value is ignored.
The value range of \a quality depends on the image format. For example,
the "jpeg" format supports a quality range from 0 (low visual quality, high
compression) to 100 (high visual quality, low compression).
\sa quality()
*/
@ -450,7 +453,7 @@ void QImageWriter::setQuality(int quality)
}
/*!
Returns the quality level of the image.
Returns the quality setting of the image format.
\sa setQuality()
*/

View File

@ -1630,8 +1630,9 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
QWindowSystemInterfacePrivate::ApplicationStateChangedEvent * changeEvent = static_cast<QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *>(e);
QGuiApplicationPrivate::setApplicationState(changeEvent->newState, changeEvent->forcePropagate); }
break;
case QWindowSystemInterfacePrivate::FlushEvents:
QWindowSystemInterface::deferredFlushWindowSystemEvents();
case QWindowSystemInterfacePrivate::FlushEvents: {
QWindowSystemInterfacePrivate::FlushEventsEvent *flushEventsEvent = static_cast<QWindowSystemInterfacePrivate::FlushEventsEvent *>(e);
QWindowSystemInterface::deferredFlushWindowSystemEvents(flushEventsEvent->flags); }
break;
case QWindowSystemInterfacePrivate::Close:
QGuiApplicationPrivate::processCloseEvent(

View File

@ -526,16 +526,16 @@ void QWindowSystemInterface::handleExposeEvent(QWindow *tlw, const QRegion &regi
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
void QWindowSystemInterface::deferredFlushWindowSystemEvents()
void QWindowSystemInterface::deferredFlushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_ASSERT(QThread::currentThread() == QGuiApplication::instance()->thread());
QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex);
flushWindowSystemEvents();
flushWindowSystemEvents(flags);
QWindowSystemInterfacePrivate::eventsFlushed.wakeOne();
}
void QWindowSystemInterface::flushWindowSystemEvents()
void QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
{
const int count = QWindowSystemInterfacePrivate::windowSystemEventQueue.count();
if (!count)
@ -549,11 +549,11 @@ void QWindowSystemInterface::flushWindowSystemEvents()
}
if (QThread::currentThread() != QGuiApplication::instance()->thread()) {
QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex);
QWindowSystemInterfacePrivate::FlushEventsEvent *e = new QWindowSystemInterfacePrivate::FlushEventsEvent();
QWindowSystemInterfacePrivate::FlushEventsEvent *e = new QWindowSystemInterfacePrivate::FlushEventsEvent(flags);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
QWindowSystemInterfacePrivate::eventsFlushed.wait(&QWindowSystemInterfacePrivate::flushEventMutex);
} else {
sendWindowSystemEvents(QEventLoop::AllEvents);
sendWindowSystemEvents(flags);
}
}

View File

@ -208,8 +208,8 @@ public:
// For event dispatcher implementations
static bool sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags);
static void setSynchronousWindowsSystemEvents(bool enable);
static void flushWindowSystemEvents();
static void deferredFlushWindowSystemEvents();
static void flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents);
static void deferredFlushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags);
static int windowSystemEventsQueued();
};

View File

@ -187,9 +187,11 @@ public:
class FlushEventsEvent : public WindowSystemEvent {
public:
FlushEventsEvent()
FlushEventsEvent(QEventLoop::ProcessEventsFlags f = QEventLoop::AllEvents)
: WindowSystemEvent(FlushEvents)
, flags(f)
{ }
QEventLoop::ProcessEventsFlags flags;
};
class UserEvent : public WindowSystemEvent {

View File

@ -36,6 +36,23 @@
QT_BEGIN_NAMESPACE
/*!
* \class QOpenGLPixelTransferOptions
*
* \brief The QOpenGLPixelTransferOptions class describes the pixel storage
* modes that affect the unpacking of pixels during texture upload.
*/
/*!
* \fn QOpenGLPixelTransferOptions & QOpenGLPixelTransferOptions::operator=(QOpenGLPixelTransferOptions &&other)
* \internal
*/
/*!
* \fn void QOpenGLPixelTransferOptions::swap(QOpenGLPixelTransferOptions &other)
* \internal
*/
class QOpenGLPixelTransferOptionsData : public QSharedData
{
public:
@ -60,16 +77,25 @@ public:
bool swapBytes;
};
/*!
* Constructs a new QOpenGLPixelTransferOptions instance with the default settings.
*/
QOpenGLPixelTransferOptions::QOpenGLPixelTransferOptions()
: data(new QOpenGLPixelTransferOptionsData)
{
}
/*!
* \internal
*/
QOpenGLPixelTransferOptions::QOpenGLPixelTransferOptions(const QOpenGLPixelTransferOptions &rhs)
: data(rhs.data)
{
}
/*!
* \internal
*/
QOpenGLPixelTransferOptions &QOpenGLPixelTransferOptions::operator=(const QOpenGLPixelTransferOptions &rhs)
{
if (this != &rhs)
@ -77,85 +103,152 @@ QOpenGLPixelTransferOptions &QOpenGLPixelTransferOptions::operator=(const QOpenG
return *this;
}
/*!
* Destructor.
*/
QOpenGLPixelTransferOptions::~QOpenGLPixelTransferOptions()
{
}
/*!
* Sets the \a alignment requirements for each pixel row. Corresponds to \c GL_UNPACK_ALIGNMENT.
* The default value is 4, as specified by OpenGL.
*/
void QOpenGLPixelTransferOptions::setAlignment(int alignment)
{
data->alignment = alignment;
}
/*!
* \return the current alignment requirement for each pixel row.
*/
int QOpenGLPixelTransferOptions::alignment() const
{
return data->alignment;
}
/*!
* Sets the number of images that are skipped to \a skipImages.
* Corresponds to \c GL_UNPACK_SKIP_IMAGES. Equivalent to incrementing the pointer
* passed to QOpenGLTexture::setData(). The default value is 0.
*/
void QOpenGLPixelTransferOptions::setSkipImages(int skipImages)
{
data->skipImages = skipImages;
}
/*!
* \return the number of images that are skipped.
*/
int QOpenGLPixelTransferOptions::skipImages() const
{
return data->skipImages;
}
/*!
* Sets the number of rows that are skipped to \a skipRows.
* Corresponds to \c GL_UNPACK_SKIP_ROWS. Equivalent to incrementing the pointer
* passed to QOpenGLTexture::setData(). The default value is 0.
*/
void QOpenGLPixelTransferOptions::setSkipRows(int skipRows)
{
data->skipRows = skipRows;
}
/*!
* \return the number of rows that are skipped.
*/
int QOpenGLPixelTransferOptions::skipRows() const
{
return data->skipRows;
}
/*!
* Sets the number of pixels that are skipped to \a skipPixels.
* Corresponds to \c GL_UNPACK_SKIP_PIXELS. Equivalent to incrementing the pointer
* passed to QOpenGLTexture::setData(). The default value is 0.
*/
void QOpenGLPixelTransferOptions::setSkipPixels(int skipPixels)
{
data->skipPixels = skipPixels;
}
/*!
* \return the number of pixels that are skipped.
*/
int QOpenGLPixelTransferOptions::skipPixels() const
{
return data->skipPixels;
}
/*!
* Sets the image height for 3D textures to \a imageHeight.
* Corresponds to \c GL_UNPACK_IMAGE_HEIGHT.
* The default value is 0.
*/
void QOpenGLPixelTransferOptions::setImageHeight(int imageHeight)
{
data->imageHeight = imageHeight;
}
/*!
* \return the currently set image height.
*/
int QOpenGLPixelTransferOptions::imageHeight() const
{
return data->imageHeight;
}
/*!
* Sets the number of pixels in a row to \a rowLength.
* Corresponds to \c GL_UNPACK_ROW_LENGTH.
* The default value is 0.
*/
void QOpenGLPixelTransferOptions::setRowLength(int rowLength)
{
data->rowLength = rowLength;
}
/*!
* \return the currently set row length.
*/
int QOpenGLPixelTransferOptions::rowLength() const
{
return data->rowLength;
}
/*!
* \a lsbFirst specifies if bits within a byte are ordered from least to most significat.
* The default value is \c false, meaning that the first bit in each byte is the
* most significant one. This is significant for bitmap data only.
* Corresponds to \c GL_UNPACK_LSB_FIRST.
*/
void QOpenGLPixelTransferOptions::setLeastSignificantByteFirst(bool lsbFirst)
{
data->lsbFirst = lsbFirst;
}
/*!
* \return \c true if bits within a byte are ordered from least to most significant.
*/
bool QOpenGLPixelTransferOptions::isLeastSignificantBitFirst() const
{
return data->lsbFirst;
}
/*!
* \a swapBytes specifies if the byte ordering for multibyte components is reversed.
* The default value is \c false.
* Corresponds to \c GL_UNPACK_SWAP_BYTES.
*/
void QOpenGLPixelTransferOptions::setSwapBytesEnabled(bool swapBytes)
{
data->swapBytes = swapBytes;
}
/*!
* \return \c true if the byte ordering for multibyte components is reversed.
*/
bool QOpenGLPixelTransferOptions::isSwapBytesEnabled() const
{
return data->swapBytes;

View File

@ -240,7 +240,7 @@ void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height)
QOpenGLShaderProgram *blitProgram = 0;
if (pex == 0) {
if (m_blitProgram == 0) {
m_blitProgram = new QOpenGLShaderProgram(ctx);
m_blitProgram = new QOpenGLShaderProgram;
const bool isCoreProfile = ctx->format().profile() == QSurfaceFormat::CoreProfile;
{
@ -444,6 +444,9 @@ void QOpenGLTextureGlyphCache::clear()
m_textureResource->free();
m_textureResource = 0;
delete m_blitProgram;
m_blitProgram = 0;
m_w = 0;
m_h = 0;
m_cx = 0;

View File

@ -1347,6 +1347,8 @@ void QPdfEngine::setPen()
int pdfJoinStyle = 0;
switch(d->pen.joinStyle()) {
case Qt::MiterJoin:
case Qt::SvgMiterJoin:
*d->currentPage << d->pen.miterLimit() << "M ";
pdfJoinStyle = 0;
break;
case Qt::BevelJoin:
@ -2081,8 +2083,10 @@ int QPdfEnginePrivate::writeImage(const QByteArray &data, int width, int height,
}
if (maskObject > 0)
xprintf("/Mask %d 0 R\n", maskObject);
if (softMaskObject > 0)
if (softMaskObject > 0) {
xprintf("/SMask %d 0 R\n", softMaskObject);
xprintf("/Decode [1 0 1 0 1 0]\n");
}
int lenobj = requestObject();
xprintf("/Length %d 0 R\n", lenobj);

View File

@ -1014,8 +1014,8 @@ void QFont::setStyle(Style style)
}
/*!
Returns the weight of the font which is one of the enumerated
values from \l{QFont::Weight}.
Returns the weight of the font, using the same scale as the
\l{QFont::Weight} enumeration.
\sa setWeight(), Weight, QFontInfo
*/
@ -1028,8 +1028,8 @@ int QFont::weight() const
\enum QFont::Weight
Qt uses a weighting scale from 0 to 99 similar to, but not the
same as, the scales used in Windows or CSS. A weight of 0 is
ultralight, whilst 99 will be extremely black.
same as, the scales used in Windows or CSS. A weight of 0 will be
thin, whilst 99 will be extremely black.
This enum contains the predefined font weights:
@ -1041,8 +1041,8 @@ int QFont::weight() const
*/
/*!
Sets the weight the font to \a weight, which should be a value
from the \l QFont::Weight enumeration.
Sets the weight of the font to \a weight, using the scale defined by
\l QFont::Weight enumeration.
\sa weight(), QFontInfo
*/

View File

@ -91,9 +91,10 @@ static int getFontWeight(const QString &weightString)
// order of "expense".
//
// A simple string test is the cheapest, so let's do that first.
if (s == QLatin1String("medium") ||
s == QLatin1String("normal"))
if (s == QLatin1String("normal"))
return QFont::Normal;
if (s == QLatin1String("medium"))
return qt_mediumFontWeight;
if (s == QLatin1String("bold"))
return QFont::Bold;
if (s == QLatin1String("demibold") || s == QLatin1String("demi bold"))
@ -102,6 +103,10 @@ static int getFontWeight(const QString &weightString)
return QFont::Black;
if (s == QLatin1String("light"))
return QFont::Light;
if (s == QLatin1String("thin"))
return qt_thinFontWeight;
if (s == QLatin1String("extralight"))
return qt_extralightFontWeight;
// Next up, let's see if contains() matches: slightly more expensive, but
// still fast enough.

View File

@ -1062,6 +1062,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
(format == Format_A8 ? (info.width + 3) & ~3 : info.width * 4));
glyph_buffer_size = pitch * info.height;
glyph_buffer = new uchar[glyph_buffer_size];
memset(glyph_buffer, 0, glyph_buffer_size);
if (slot->format == FT_GLYPH_FORMAT_OUTLINE) {
FT_Bitmap bitmap;

View File

@ -78,6 +78,10 @@ enum HB_Compat_Error {
typedef void (*qt_destroy_func_t) (void *user_data);
typedef bool (*qt_get_font_table_func_t) (void *user_data, uint tag, uchar *buffer, uint *length);
const QFont::Weight qt_mediumFontWeight = static_cast<QFont::Weight>(57);
const QFont::Weight qt_extralightFontWeight = static_cast<QFont::Weight>(12);
const QFont::Weight qt_thinFontWeight = static_cast<QFont::Weight>(0);
class Q_GUI_EXPORT QFontEngine
{
public:

View File

@ -1289,7 +1289,7 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData,
if (rowIsIdenticalToPrevious && item != itemAt(row - 1, column, orientation))
rowIsIdenticalToPrevious = false;
if (item)
if (item && !item->isIgnored())
rowIsEmpty = false;
}

View File

@ -295,6 +295,7 @@ public:
virtual QLayoutPolicy::Policy sizePolicy(Qt::Orientation orientation) const = 0;
virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const = 0;
virtual bool isIgnored() const { return false; }
virtual void setGeometry(const QRectF &rect) = 0;
/*

View File

@ -1169,7 +1169,7 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData
setCachingEnabled(true);
}
metaDataChanged();
_q_metaDataChanged();
}
void QNetworkReplyHttpImplPrivate::replyDownloadProgressSlot(qint64 bytesReceived, qint64 bytesTotal)
@ -1362,7 +1362,7 @@ bool QNetworkReplyHttpImplPrivate::sendCacheContents(const QNetworkCacheMetaData
// This needs to be emitted in the event loop because it can be reached at
// the direct code path of qnam.get(...) before the user has a chance
// to connect any signals.
QMetaObject::invokeMethod(q, "metaDataChanged", Qt::QueuedConnection);
QMetaObject::invokeMethod(q, "_q_metaDataChanged", Qt::QueuedConnection);
QMetaObject::invokeMethod(q, "_q_cacheLoadReadyRead", Qt::QueuedConnection);
@ -1991,7 +1991,7 @@ void QNetworkReplyHttpImplPrivate::error(QNetworkReplyImpl::NetworkError code, c
emit q->error(code);
}
void QNetworkReplyHttpImplPrivate::metaDataChanged()
void QNetworkReplyHttpImplPrivate::_q_metaDataChanged()
{
// FIXME merge this with replyDownloadMetaData(); ?

View File

@ -124,6 +124,7 @@ public:
Q_PRIVATE_SLOT(d_func(), void uploadByteDeviceReadyReadSlot())
Q_PRIVATE_SLOT(d_func(), void emitReplyUploadProgress(qint64, qint64))
Q_PRIVATE_SLOT(d_func(), void _q_cacheSaveDeviceAboutToClose())
Q_PRIVATE_SLOT(d_func(), void _q_metaDataChanged())
#ifndef QT_NO_SSL
@ -175,7 +176,7 @@ public:
void finished();
void error(QNetworkReply::NetworkError code, const QString &errorString);
void _q_error(QNetworkReply::NetworkError code, const QString &errorString);
void metaDataChanged();
void _q_metaDataChanged();
void checkForRedirect(const int statusCode);

View File

@ -245,7 +245,7 @@ void QNetworkReplyNSURLConnectionImpl::readyReadOutgoingData()
Q_UNUSED(connection)
QNetworkReply::NetworkError qtError = QNetworkReply::UnknownNetworkError;
if ([error domain] == NSURLErrorDomain) {
if ([[error domain] isEqualToString:NSURLErrorDomain]) {
switch ([error code]) {
case NSURLErrorTimedOut: qtError = QNetworkReply::TimeoutError; break;
case NSURLErrorUnsupportedURL: qtError = QNetworkReply::ProtocolUnknownError; break;
@ -260,6 +260,7 @@ void QNetworkReplyNSURLConnectionImpl::readyReadOutgoingData()
}
replyprivate->setError(qtError, QString::fromNSString([error localizedDescription]));
replyprivate->setFinished();
}
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)aResponse

View File

@ -248,7 +248,7 @@ determining the feature support:
\li Linux uses the \l {http://projects.gnome.org/NetworkManager}{NetworkManager}
and \l {http://connman.net/}{ConnMan} / \l {http://ofono.org/}{oFono} APIs
which support interface notifications and starting and stopping of network
interfaces.
interfaces. Network Manager version 0.9 and above is supported.
\row
\li Windows\unicode{0xAE} XP
\li This platform supports interface notifications without active polling.

View File

@ -1140,7 +1140,7 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
int err = WSAGetLastError();
if (ret == SOCKET_ERROR && err != WSAEMSGSIZE) {
WS_ERROR_DEBUG(err);
if (err == WSAECONNRESET) {
if (err == WSAECONNRESET || err == WSAENETRESET) {
// Discard error message to prevent QAbstractSocket from
// getting this message repeatedly after reenabling the
// notifiers.

View File

@ -119,12 +119,12 @@ QT_BEGIN_NAMESPACE
a TLS 1.0 Client Hello, enabling TLSv1_0 and SSLv3 connections.
On the server side, this will enable both SSLv3 and TLSv1_0 connections.
\value SecureProtocols The default option, using protocols known to be secure;
currently behaves like TlsV1SslV3.
currently behaves similar to TlsV1Ssl3 except denying SSLv3 connections that does
not upgrade to TLS.
\note most servers using SSL understand both versions (2 and 3),
but it is recommended to use the latest version only for security
reasons. However, SSL and TLS are not compatible with each other:
if you get unexpected handshake failures, verify that you chose
\note most servers understand both SSL and TLS, but it is recommended to use
TLS only for security reasons. However, SSL and TLS are not compatible with
each other: if you get unexpected handshake failures, verify that you chose
the correct setting for your protocol.
*/

View File

@ -139,8 +139,11 @@ init_context:
case QSsl::SslV3:
sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv3_client_method() : q_SSLv3_server_method());
break;
case QSsl::SecureProtocols: // SslV2 will be disabled below
case QSsl::TlsV1SslV3: // SslV2 will be disabled below
case QSsl::SecureProtocols:
// SSLv2 and SSLv3 will be disabled by SSL options
// But we need q_SSLv23_server_method() otherwise AnyProtocol will be unable to connect on Win32.
case QSsl::TlsV1SslV3:
// SSLv2 will will be disabled by SSL options
case QSsl::AnyProtocol:
default:
sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());

View File

@ -280,8 +280,10 @@ int q_X509Callback(int ok, X509_STORE_CTX *ctx)
long QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
{
long options;
if (protocol == QSsl::TlsV1SslV3 || protocol == QSsl::SecureProtocols)
if (protocol == QSsl::TlsV1SslV3)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2;
else if (protocol == QSsl::SecureProtocols)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
else
options = SSL_OP_ALL;

View File

@ -267,7 +267,7 @@ void QEGLPlatformCursorUpdater::update(const QPoint &pos, const QRegion &rgn)
{
m_active = false;
QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(pos), rgn);
QWindowSystemInterface::flushWindowSystemEvents();
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
}
void QEGLPlatformCursorUpdater::scheduleUpdate(const QPoint &pos, const QRegion &rgn)

View File

@ -277,10 +277,16 @@ QStringList QBasicFontDatabase::addTTFile(const QByteArray &fontData, const QByt
if (os2->usWeightClass == 0)
;
else if (os2->usWeightClass < 150)
weight = qt_thinFontWeight;
else if (os2->usWeightClass < 250)
weight = qt_extralightFontWeight;
else if (os2->usWeightClass < 350)
weight = QFont::Light;
else if (os2->usWeightClass < 450)
weight = QFont::Normal;
else if (os2->usWeightClass < 550)
weight = qt_mediumFontWeight;
else if (os2->usWeightClass < 650)
weight = QFont::DemiBold;
else if (os2->usWeightClass < 750)
@ -290,10 +296,16 @@ QStringList QBasicFontDatabase::addTTFile(const QByteArray &fontData, const QByt
if (os2->panose[2] >= 2) {
int w = os2->panose[2];
if (w <= 3)
if (w <= 1)
weight = qt_thinFontWeight;
else if (w <= 2)
weight = qt_extralightFontWeight;
else if (w <= 3)
weight = QFont::Light;
else if (w <= 5)
weight = QFont::Normal;
else if (w <= 6)
weight = qt_mediumFontWeight;
else if (w <= 7)
weight = QFont::DemiBold;
else if (w <= 8)

View File

@ -294,10 +294,16 @@ static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
fd->weight = QFont::Bold;
else if (normalizedWeight >= 0.3)
fd->weight = QFont::DemiBold;
else if (normalizedWeight >= 0.2)
fd->weight = qt_mediumFontWeight;
else if (normalizedWeight == 0.0)
fd->weight = QFont::Normal;
else if (normalizedWeight <= -0.4)
fd->weight = QFont::Light;
else if (normalizedWeight <= -0.6)
fd->weight = qt_extralightFontWeight;
else if (normalizedWeight <= -0.8)
fd->weight = qt_thinFontWeight;
}
}
if (CFNumberRef italic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSlantTrait)) {

View File

@ -577,9 +577,10 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition
cgflags);
Q_ASSERT(ctx);
CGContextSetFontSize(ctx, fontDef.pixelSize);
CGContextSetShouldAntialias(ctx, (aa || fontDef.pointSize > antialiasingThreshold)
&& !(fontDef.styleStrategy & QFont::NoAntialias));
CGContextSetShouldSmoothFonts(ctx, aa);
const bool antialias = (aa || fontDef.pointSize > antialiasingThreshold) && !(fontDef.styleStrategy & QFont::NoAntialias);
CGContextSetShouldAntialias(ctx, antialias);
const bool smoothing = antialias && !(fontDef.styleStrategy & QFont::NoSubpixelAntialias);
CGContextSetShouldSmoothFonts(ctx, smoothing);
CGAffineTransform cgMatrix = CGAffineTransformIdentity;

View File

@ -166,10 +166,7 @@ QNetworkSession::State QAndroidBearerEngine::sessionStateForId(const QString &id
const QMutexLocker configLocker(&ptr->mutex);
// Don't re-order...
if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
return (m_connectivityManager->isActiveNetworkMetered()
|| m_connectivityManager->getActiveNetworkInfo().isRoaming())
? QNetworkSession::Roaming
: QNetworkSession::Connected;
return QNetworkSession::Connected;
} else if ((ptr->state & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) {
return QNetworkSession::Disconnected;
} else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
@ -267,6 +264,10 @@ void QAndroidBearerEngine::updateConfigurations()
QMutexLocker locker(&mutex);
QStringList oldKeys = accessPointConfigurations.keys();
QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
if (interfaces.isEmpty())
interfaces = QNetworkInterface::allInterfaces();
// Create a configuration for each of the main types (WiFi, Mobile, Bluetooth, WiMax, Ethernet)
foreach (const AndroidNetworkInfo &netInfo, m_connectivityManager->getAllNetworkInfo()) {
@ -279,14 +280,13 @@ void QAndroidBearerEngine::updateConfigurations()
QNetworkConfiguration::BearerType bearerType = getBearerType(netInfo);
QNetworkConfiguration::StateFlag state;
QString interfaceName;
QNetworkConfiguration::StateFlag state = QNetworkConfiguration::Defined;
if (netInfo.isAvailable()) {
if (netInfo.isConnected()) {
state = QNetworkConfiguration::Active;
// Attempt to map an interface to this configuration
const QList<QNetworkInterface> &interfaces = QNetworkInterface::allInterfaces();
foreach (const QNetworkInterface &interface, interfaces) {
while (!interfaces.isEmpty()) {
QNetworkInterface interface = interfaces.takeFirst();
// ignore loopback interface
if (!interface.isValid())
continue;
@ -297,22 +297,17 @@ void QAndroidBearerEngine::updateConfigurations()
// look for an active interface...
if (interface.flags() & QNetworkInterface::IsRunning
&& !interface.addressEntries().isEmpty()) {
interfaceName = interface.humanReadableName();
if (interfaceName.isEmpty())
interfaceName = interface.name();
state = QNetworkConfiguration::Active;
interfaceName = interface.name();
break;
}
}
} else if (netInfo.isConnectedOrConnecting()) {
state = QNetworkConfiguration::Undefined;
} else {
state = QNetworkConfiguration::Discovered;
}
} else {
state = QNetworkConfiguration::Defined;
}
const uint identifier = qHash(QLatin1String("android:") + name);
const QString id = QString::number(identifier);
const QString key = QString(QLatin1String("android:%1:%2")).arg(name).arg(interfaceName);
const QString id = QString::number(qHash(key));
m_configurationInterface[id] = interfaceName;
oldKeys.removeAll(id);
if (accessPointConfigurations.contains(id)) {
@ -347,12 +342,6 @@ void QAndroidBearerEngine::updateConfigurations()
ptr->state = state;
changed = true;
}
QString &oldIfName = m_configurationInterface[id];
if (oldIfName != interfaceName) {
oldIfName = interfaceName;
changed = true;
}
} // Unlock configuration
if (changed) {
@ -369,8 +358,6 @@ void QAndroidBearerEngine::updateConfigurations()
ptr->type = QNetworkConfiguration::InternetAccessPoint;
ptr->bearerType = bearerType;
accessPointConfigurations.insert(id, ptr);
m_configurationInterface.insert(id, interfaceName);
locker.unlock();
Q_EMIT configurationAdded(ptr);
locker.relock();

View File

@ -83,6 +83,7 @@ public:
private Q_SLOTS:
void doRequestUpdate();
void networksChanged();
void checkDisconnect();
private:
bool isWifiReady(const QString &dev);
@ -95,6 +96,7 @@ private:
QScanThread *scanThread;
quint64 getBytes(const QString &interfaceName,bool b);
QString disconnectedInterfaceString;
protected:
void startNetworkChangeLoop();

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@ -62,8 +62,6 @@ extern "C" { // Otherwise it won't find CWKeychain* symbols at link time
#include <net/if.h>
#include <ifaddrs.h>
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_NA)
@interface QT_MANGLE_NAMESPACE(QNSListener) : NSObject
{
NSNotificationCenter *notificationCenter;
@ -544,20 +542,44 @@ void QCoreWlanEngine::disconnectFromId(const QString &id)
QMutexLocker locker(&mutex);
QString interfaceString = getInterfaceFromId(id);
if (interfaceString.isEmpty()) {
locker.unlock();
emit connectionError(id, DisconnectionError);
return;
}
NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
CWInterface *wifiInterface =
[CWInterface interfaceWithName: QCFString::toNSString(interfaceString)];
disconnectedInterfaceString = interfaceString;
[wifiInterface disassociate];
if (wifiInterface.serviceActive) {
locker.unlock();
emit connectionError(id, DisconnectionError);
locker.relock();
}
QTimer::singleShot(1000, this,SLOT(checkDisconnect()));
[autoreleasepool release];
}
void QCoreWlanEngine::checkDisconnect()
{
QMutexLocker locker(&mutex);
if (!disconnectedInterfaceString.isEmpty()) {
NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
CWInterface *wifiInterface =
[CWInterface interfaceWithName: QCFString::toNSString(disconnectedInterfaceString)];
const QString networkSsid = QCFString::toQString([wifiInterface ssid]);
if (!networkSsid.isEmpty()) {
const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkSsid));
locker.unlock();
emit connectionError(id, DisconnectionError);
locker.relock();
}
[autoreleasepool release];
disconnectedInterfaceString.clear();
}
}
void QCoreWlanEngine::requestUpdate()
{
scanThread->getUserConfigurations();
@ -862,7 +884,3 @@ quint64 QCoreWlanEngine::getBytes(const QString &interfaceName, bool b)
}
QT_END_NAMESPACE
#else // QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE
#include "qcorewlanengine_10_6.mm"
#endif

View File

@ -1,922 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <SystemConfiguration/SCNetworkConfiguration.h>
@interface QT_MANGLE_NAMESPACE(QNSListener) : NSObject
{
NSNotificationCenter *notificationCenter;
CWInterface *currentInterface;
QCoreWlanEngine *engine;
NSLock *locker;
}
- (void)notificationHandler:(NSNotification *)notification;
- (void)remove;
- (void)setEngine:(QCoreWlanEngine *)coreEngine;
- (QCoreWlanEngine *)engine;
- (void)dealloc;
@property (assign) QCoreWlanEngine* engine;
@end
@implementation QT_MANGLE_NAMESPACE(QNSListener)
- (id) init
{
[locker lock];
NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
notificationCenter = [NSNotificationCenter defaultCenter];
currentInterface = [CWInterface interfaceWithName:nil];
[notificationCenter addObserver:self selector:@selector(notificationHandler:) name:kCWPowerDidChangeNotification object:nil];
[locker unlock];
[autoreleasepool release];
return self;
}
-(void)dealloc
{
[super dealloc];
}
-(void)setEngine:(QCoreWlanEngine *)coreEngine
{
[locker lock];
if(!engine)
engine = coreEngine;
[locker unlock];
}
-(QCoreWlanEngine *)engine
{
return engine;
}
-(void)remove
{
[locker lock];
[notificationCenter removeObserver:self];
[locker unlock];
}
- (void)notificationHandler:(NSNotification *)notification
{
Q_UNUSED(notification);
engine->requestUpdate();
}
@end
static QT_MANGLE_NAMESPACE(QNSListener) *listener = 0;
QT_BEGIN_NAMESPACE
void networkChangeCallback(SCDynamicStoreRef/* store*/, CFArrayRef changedKeys, void *info)
{
for ( long i = 0; i < CFArrayGetCount(changedKeys); i++) {
QString changed = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(changedKeys, i));
if( changed.contains("/Network/Global/IPv4")) {
QCoreWlanEngine* wlanEngine = static_cast<QCoreWlanEngine*>(info);
wlanEngine->requestUpdate();
}
}
return;
}
QScanThread::QScanThread(QObject *parent)
:QThread(parent)
{
}
QScanThread::~QScanThread()
{
}
void QScanThread::quit()
{
wait();
}
void QScanThread::run()
{
NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
QStringList found;
mutex.lock();
CWInterface *currentInterface = [CWInterface interfaceWithName: QCFString::toNSString(interfaceName)];
mutex.unlock();
if([currentInterface power]) {
NSError *err = nil;
NSDictionary *parametersDict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCWScanKeyMerge,
[NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType,
[NSNumber numberWithInteger:100], kCWScanKeyRestTime, nil];
NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err];
CWNetwork *apNetwork;
if (!err) {
for(uint row=0; row < [apArray count]; row++ ) {
apNetwork = [apArray objectAtIndex:row];
const QString networkSsid = QCFString::toQString([apNetwork ssid]);
const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkSsid));
found.append(id);
QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined;
bool known = isKnownSsid(networkSsid);
if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) {
if( networkSsid == QCFString::toQString( [currentInterface ssid])) {
state = QNetworkConfiguration::Active;
}
}
if(state == QNetworkConfiguration::Undefined) {
if(known) {
state = QNetworkConfiguration::Discovered;
} else {
state = QNetworkConfiguration::Undefined;
}
}
QNetworkConfiguration::Purpose purpose = QNetworkConfiguration::UnknownPurpose;
if([[apNetwork securityMode] intValue] == kCWSecurityModeOpen) {
purpose = QNetworkConfiguration::PublicPurpose;
} else {
purpose = QNetworkConfiguration::PrivatePurpose;
}
found.append(foundNetwork(id, networkSsid, state, interfaceName, purpose));
}
}
}
// add known configurations that are not around.
QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
while (i.hasNext()) {
i.next();
QString networkName = i.key();
const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkName));
if(!found.contains(id)) {
QString networkSsid = getSsidFromNetworkName(networkName);
const QString ssidId = QString::number(qHash(QLatin1String("corewlan:") + networkSsid));
QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined;
QString interfaceName;
QMapIterator<QString, QString> ij(i.value());
while (ij.hasNext()) {
ij.next();
interfaceName = ij.value();
}
if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) {
if( networkSsid == QCFString::toQString([currentInterface ssid])) {
state = QNetworkConfiguration::Active;
}
}
if(state == QNetworkConfiguration::Undefined) {
if( userProfiles.contains(networkName)
&& found.contains(ssidId)) {
state = QNetworkConfiguration::Discovered;
}
}
if(state == QNetworkConfiguration::Undefined) {
state = QNetworkConfiguration::Defined;
}
found.append(foundNetwork(id, networkName, state, interfaceName, QNetworkConfiguration::UnknownPurpose));
}
}
emit networksChanged();
[autoreleasepool release];
}
QStringList QScanThread::foundNetwork(const QString &id, const QString &name, const QNetworkConfiguration::StateFlags state, const QString &interfaceName, const QNetworkConfiguration::Purpose purpose)
{
QStringList found;
QMutexLocker locker(&mutex);
QNetworkConfigurationPrivate *ptr = new QNetworkConfigurationPrivate;
ptr->name = name;
ptr->isValid = true;
ptr->id = id;
ptr->state = state;
ptr->type = QNetworkConfiguration::InternetAccessPoint;
ptr->bearerType = QNetworkConfiguration::BearerWLAN;
ptr->purpose = purpose;
fetchedConfigurations.append( ptr);
configurationInterface.insert(ptr->id, interfaceName);
locker.unlock();
locker.relock();
found.append(id);
return found;
}
QList<QNetworkConfigurationPrivate *> QScanThread::getConfigurations()
{
QMutexLocker locker(&mutex);
QList<QNetworkConfigurationPrivate *> foundConfigurations = fetchedConfigurations;
fetchedConfigurations.clear();
return foundConfigurations;
}
void QScanThread::getUserConfigurations()
{
QMutexLocker locker(&mutex);
NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
userProfiles.clear();
NSArray *wifiInterfaces = [CWInterface supportedInterfaces];
for(uint row=0; row < [wifiInterfaces count]; row++ ) {
CWInterface *wifiInterface = [CWInterface interfaceWithName: [wifiInterfaces objectAtIndex:row]];
if ( ![wifiInterface power] )
continue;
NSString *nsInterfaceName = [wifiInterface name];
// add user configured system networks
SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, (CFStringRef)@"Qt corewlan", nil, nil);
NSDictionary * airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", nsInterfaceName]);
CFRelease(dynRef);
if(airportPlist != nil) {
NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"];
NSArray *thisSsidarray = [prefNetDict valueForKey:@"SSID_STR"];
for(NSString *ssidkey in thisSsidarray) {
QString thisSsid = QCFString::toQString(ssidkey);
if(!userProfiles.contains(thisSsid)) {
QMap <QString,QString> map;
map.insert(thisSsid, QCFString::toQString(nsInterfaceName));
userProfiles.insert(thisSsid, map);
}
}
CFRelease(airportPlist);
}
// 802.1X user profiles
QString userProfilePath = QDir::homePath() + "/Library/Preferences/com.apple.eap.profiles.plist";
NSDictionary* eapDict = [[[NSDictionary alloc] initWithContentsOfFile: QCFString::toNSString(userProfilePath)] autorelease];
if(eapDict != nil) {
NSString *profileStr= @"Profiles";
NSString *nameStr = @"UserDefinedName";
NSString *networkSsidStr = @"Wireless Network";
for (id profileKey in eapDict) {
if ([profileStr isEqualToString:profileKey]) {
NSDictionary *itemDict = [eapDict objectForKey:profileKey];
for (id itemKey in itemDict) {
NSInteger dictSize = [itemKey count];
id objects[dictSize];
id keys[dictSize];
[itemKey getObjects:objects andKeys:keys];
QString networkName;
QString ssid;
for(int i = 0; i < dictSize; i++) {
if([nameStr isEqualToString:keys[i]]) {
networkName = QCFString::toQString(objects[i]);
}
if([networkSsidStr isEqualToString:keys[i]]) {
ssid = QCFString::toQString(objects[i]);
}
if(!userProfiles.contains(networkName)
&& !ssid.isEmpty()) {
QMap<QString,QString> map;
map.insert(ssid, QCFString::toQString(nsInterfaceName));
userProfiles.insert(networkName, map);
}
}
}
}
}
}
}
[autoreleasepool release];
}
QString QScanThread::getSsidFromNetworkName(const QString &name)
{
QMutexLocker locker(&mutex);
QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
while (i.hasNext()) {
i.next();
QMap<QString,QString> map = i.value();
QMapIterator<QString, QString> ij(i.value());
while (ij.hasNext()) {
ij.next();
const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") +i.key()));
if(name == i.key() || name == networkNameHash) {
return ij.key();
}
}
}
return QString();
}
QString QScanThread::getNetworkNameFromSsid(const QString &ssid)
{
QMutexLocker locker(&mutex);
QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
while (i.hasNext()) {
i.next();
QMap<QString,QString> map = i.value();
QMapIterator<QString, QString> ij(i.value());
while (ij.hasNext()) {
ij.next();
if(ij.key() == ssid) {
return i.key();
}
}
}
return QString();
}
bool QScanThread::isKnownSsid(const QString &ssid)
{
QMutexLocker locker(&mutex);
QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
while (i.hasNext()) {
i.next();
QMap<QString,QString> map = i.value();
if(map.keys().contains(ssid)) {
return true;
}
}
return false;
}
QCoreWlanEngine::QCoreWlanEngine(QObject *parent)
: QBearerEngineImpl(parent), scanThread(0)
{
scanThread = new QScanThread(this);
connect(scanThread, SIGNAL(networksChanged()),
this, SLOT(networksChanged()));
}
QCoreWlanEngine::~QCoreWlanEngine()
{
scanThread->terminate();
scanThread->wait();
while (!foundConfigurations.isEmpty())
delete foundConfigurations.takeFirst();
[listener remove];
[listener release];
}
void QCoreWlanEngine::initialize()
{
QMutexLocker locker(&mutex);
NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
if([[CWInterface supportedInterfaces] count] > 0 && !listener) {
listener = [[QT_MANGLE_NAMESPACE(QNSListener) alloc] init];
listener.engine = this;
hasWifi = true;
} else {
hasWifi = false;
}
storeSession = NULL;
startNetworkChangeLoop();
[autoreleasepool release];
}
QString QCoreWlanEngine::getInterfaceFromId(const QString &id)
{
QMutexLocker locker(&mutex);
return scanThread->configurationInterface.value(id);
}
bool QCoreWlanEngine::hasIdentifier(const QString &id)
{
QMutexLocker locker(&mutex);
return scanThread->configurationInterface.contains(id);
}
void QCoreWlanEngine::connectToId(const QString &id)
{
QMutexLocker locker(&mutex);
NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
QString interfaceString = getInterfaceFromId(id);
CWInterface *wifiInterface =
[CWInterface interfaceWithName: QCFString::toNSString(interfaceString)];
if ([wifiInterface power]) {
NSError *err = nil;
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0];
QString wantedSsid;
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
const QString idHash = QString::number(qHash(QLatin1String("corewlan:") + ptr->name));
const QString idHash2 = QString::number(qHash(QLatin1String("corewlan:") + scanThread->getNetworkNameFromSsid(ptr->name)));
bool using8021X = false;
if (idHash2 != id) {
NSArray *array = [CW8021XProfile allUser8021XProfiles];
for (NSUInteger i = 0; i < [array count]; ++i) {
const QString networkNameHashCheck = QString::number(qHash(QLatin1String("corewlan:") + QCFString::toQString([[array objectAtIndex:i] userDefinedName])));
const QString ssidHash = QString::number(qHash(QLatin1String("corewlan:") + QCFString::toQString([[array objectAtIndex:i] ssid])));
if (id == networkNameHashCheck || id == ssidHash) {
const QString thisName = scanThread->getSsidFromNetworkName(id);
if (thisName.isEmpty())
wantedSsid = id;
else
wantedSsid = thisName;
[params setValue: [array objectAtIndex:i] forKey:kCWAssocKey8021XProfile];
using8021X = true;
break;
}
}
}
if (!using8021X) {
QString wantedNetwork;
QMapIterator<QString, QMap<QString,QString> > i(scanThread->userProfiles);
while (i.hasNext()) {
i.next();
wantedNetwork = i.key();
const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") + wantedNetwork));
if (id == networkNameHash) {
wantedSsid = scanThread->getSsidFromNetworkName(wantedNetwork);
break;
}
}
}
NSDictionary *scanParameters = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCWScanKeyMerge,
[NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType,
[NSNumber numberWithInteger:100], kCWScanKeyRestTime,
QCFString::toNSString(wantedSsid), kCWScanKeySSID,
nil];
NSArray *scanArray = [wifiInterface scanForNetworksWithParameters:scanParameters error:&err];
if(!err) {
for(uint row=0; row < [scanArray count]; row++ ) {
CWNetwork *apNetwork = [scanArray objectAtIndex:row];
if(wantedSsid == QCFString::toQString([apNetwork ssid])) {
if(!using8021X) {
SecKeychainAttribute attributes[3];
NSString *account = [apNetwork ssid];
NSString *keyKind = @"AirPort network password";
NSString *keyName = account;
attributes[0].tag = kSecAccountItemAttr;
attributes[0].data = (void *)[account UTF8String];
attributes[0].length = [account length];
attributes[1].tag = kSecDescriptionItemAttr;
attributes[1].data = (void *)[keyKind UTF8String];
attributes[1].length = [keyKind length];
attributes[2].tag = kSecLabelItemAttr;
attributes[2].data = (void *)[keyName UTF8String];
attributes[2].length = [keyName length];
SecKeychainAttributeList attributeList = {3,attributes};
SecKeychainSearchRef searchRef;
SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributeList, &searchRef);
NSString *password = @"";
SecKeychainItemRef searchItem;
if (SecKeychainSearchCopyNext(searchRef, &searchItem) == noErr) {
UInt32 realPasswordLength;
SecKeychainAttribute attributesW[8];
attributesW[0].tag = kSecAccountItemAttr;
SecKeychainAttributeList listW = {1,attributesW};
char *realPassword;
OSStatus status = SecKeychainItemCopyContent(searchItem, NULL, &listW, &realPasswordLength,(void **)&realPassword);
if (status == noErr) {
if (realPassword != NULL) {
QByteArray pBuf;
pBuf.resize(realPasswordLength);
pBuf.prepend(realPassword);
pBuf.insert(realPasswordLength,'\0');
password = [NSString stringWithUTF8String:pBuf];
}
SecKeychainItemFreeContent(&listW, realPassword);
}
CFRelease(searchItem);
} else {
qDebug() << "SecKeychainSearchCopyNext error";
}
[params setValue: password forKey: kCWAssocKeyPassphrase];
} // end using8021X
bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err];
if(!err) {
if(!result) {
emit connectionError(id, ConnectError);
} else {
return;
}
} else {
qDebug() <<"associate ERROR"<< QCFString::toQString([err localizedDescription ]);
}
}
} //end scan network
} else {
qDebug() <<"scan ERROR"<< QCFString::toQString([err localizedDescription ]);
}
emit connectionError(id, InterfaceLookupError);
}
locker.unlock();
emit connectionError(id, InterfaceLookupError);
[autoreleasepool release];
}
void QCoreWlanEngine::disconnectFromId(const QString &id)
{
QMutexLocker locker(&mutex);
QString interfaceString = getInterfaceFromId(id);
NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
CWInterface *wifiInterface =
[CWInterface interfaceWithName: QCFString::toNSString(interfaceString)];
[wifiInterface disassociate];
if ([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) {
locker.unlock();
emit connectionError(id, DisconnectionError);
locker.relock();
}
[autoreleasepool release];
}
void QCoreWlanEngine::requestUpdate()
{
scanThread->getUserConfigurations();
doRequestUpdate();
}
void QCoreWlanEngine::doRequestUpdate()
{
QMutexLocker locker(&mutex);
NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
NSArray *wifiInterfaces = [CWInterface supportedInterfaces];
for (uint row = 0; row < [wifiInterfaces count]; ++row) {
scanThread->interfaceName = QCFString::toQString([wifiInterfaces objectAtIndex:row]);
scanThread->start();
}
locker.unlock();
if ([wifiInterfaces count] == 0)
networksChanged();
[autoreleasepool release];
}
bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName)
{
QMutexLocker locker(&mutex);
bool haswifi = false;
if(hasWifi) {
NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
CWInterface *defaultInterface = [CWInterface interfaceWithName: QCFString::toNSString(wifiDeviceName)];
if([defaultInterface power]) {
haswifi = true;
}
[autoreleasepool release];
}
return haswifi;
}
QNetworkSession::State QCoreWlanEngine::sessionStateForId(const QString &id)
{
QMutexLocker locker(&mutex);
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
if (!ptr)
return QNetworkSession::Invalid;
if (!ptr->isValid) {
return QNetworkSession::Invalid;
} else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
return QNetworkSession::Connected;
} else if ((ptr->state & QNetworkConfiguration::Discovered) ==
QNetworkConfiguration::Discovered) {
return QNetworkSession::Disconnected;
} else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
return QNetworkSession::NotAvailable;
} else if ((ptr->state & QNetworkConfiguration::Undefined) ==
QNetworkConfiguration::Undefined) {
return QNetworkSession::NotAvailable;
}
return QNetworkSession::Invalid;
}
QNetworkConfigurationManager::Capabilities QCoreWlanEngine::capabilities() const
{
return QNetworkConfigurationManager::ForcedRoaming;
}
void QCoreWlanEngine::startNetworkChangeLoop()
{
SCDynamicStoreContext dynStoreContext = { 0, this/*(void *)storeSession*/, NULL, NULL, NULL };
storeSession = SCDynamicStoreCreate(NULL,
CFSTR("networkChangeCallback"),
networkChangeCallback,
&dynStoreContext);
if (!storeSession ) {
qWarning() << "could not open dynamic store: error:" << SCErrorString(SCError());
return;
}
CFMutableArrayRef notificationKeys;
notificationKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
CFMutableArrayRef patternsArray;
patternsArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
CFStringRef storeKey;
storeKey = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
kSCDynamicStoreDomainState,
kSCEntNetIPv4);
CFArrayAppendValue(notificationKeys, storeKey);
CFRelease(storeKey);
storeKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
kSCDynamicStoreDomainState,
kSCCompAnyRegex,
kSCEntNetIPv4);
CFArrayAppendValue(patternsArray, storeKey);
CFRelease(storeKey);
if (!SCDynamicStoreSetNotificationKeys(storeSession , notificationKeys, patternsArray)) {
qWarning() << "register notification error:"<< SCErrorString(SCError());
CFRelease(storeSession );
CFRelease(notificationKeys);
CFRelease(patternsArray);
return;
}
CFRelease(notificationKeys);
CFRelease(patternsArray);
runloopSource = SCDynamicStoreCreateRunLoopSource(NULL, storeSession , 0);
if (!runloopSource) {
qWarning() << "runloop source error:"<< SCErrorString(SCError());
CFRelease(storeSession );
return;
}
CFRunLoopAddSource(CFRunLoopGetCurrent(), runloopSource, kCFRunLoopDefaultMode);
return;
}
QNetworkSessionPrivate *QCoreWlanEngine::createSessionBackend()
{
return new QNetworkSessionPrivateImpl;
}
QNetworkConfigurationPrivatePointer QCoreWlanEngine::defaultConfiguration()
{
return QNetworkConfigurationPrivatePointer();
}
bool QCoreWlanEngine::requiresPolling() const
{
return true;
}
void QCoreWlanEngine::networksChanged()
{
QMutexLocker locker(&mutex);
QStringList previous = accessPointConfigurations.keys();
QList<QNetworkConfigurationPrivate *> foundConfigurations = scanThread->getConfigurations();
while (!foundConfigurations.isEmpty()) {
QNetworkConfigurationPrivate *cpPriv = foundConfigurations.takeFirst();
previous.removeAll(cpPriv->id);
if (accessPointConfigurations.contains(cpPriv->id)) {
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(cpPriv->id);
bool changed = false;
ptr->mutex.lock();
if (ptr->isValid != cpPriv->isValid) {
ptr->isValid = cpPriv->isValid;
changed = true;
}
if (ptr->name != cpPriv->name) {
ptr->name = cpPriv->name;
changed = true;
}
if (ptr->bearerType != cpPriv->bearerType) {
ptr->bearerType = cpPriv->bearerType;
changed = true;
}
if (ptr->state != cpPriv->state) {
ptr->state = cpPriv->state;
changed = true;
}
ptr->mutex.unlock();
if (changed) {
locker.unlock();
emit configurationChanged(ptr);
locker.relock();
}
delete cpPriv;
} else {
QNetworkConfigurationPrivatePointer ptr(cpPriv);
accessPointConfigurations.insert(ptr->id, ptr);
locker.unlock();
emit configurationAdded(ptr);
locker.relock();
}
}
while (!previous.isEmpty()) {
QNetworkConfigurationPrivatePointer ptr =
accessPointConfigurations.take(previous.takeFirst());
locker.unlock();
emit configurationRemoved(ptr);
locker.relock();
}
locker.unlock();
emit updateCompleted();
}
quint64 QCoreWlanEngine::bytesWritten(const QString &id)
{
QMutexLocker locker(&mutex);
const QString interfaceStr = getInterfaceFromId(id);
return getBytes(interfaceStr,false);
}
quint64 QCoreWlanEngine::bytesReceived(const QString &id)
{
QMutexLocker locker(&mutex);
const QString interfaceStr = getInterfaceFromId(id);
return getBytes(interfaceStr,true);
}
quint64 QCoreWlanEngine::startTime(const QString &identifier)
{
QMutexLocker locker(&mutex);
NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
quint64 timestamp = 0;
NSString *filePath = @"/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist";
NSDictionary* plistDict = [[[NSDictionary alloc] initWithContentsOfFile:filePath] autorelease];
if(plistDict == nil)
return timestamp;
NSString *input = @"KnownNetworks";
NSString *timeStampStr = @"_timeStamp";
NSString *ssidStr = @"SSID_STR";
for (id key in plistDict) {
if ([input isEqualToString:key]) {
NSDictionary *knownNetworksDict = [plistDict objectForKey:key];
if(knownNetworksDict == nil)
return timestamp;
for (id networkKey in knownNetworksDict) {
bool isFound = false;
NSDictionary *itemDict = [knownNetworksDict objectForKey:networkKey];
if(itemDict == nil)
return timestamp;
NSInteger dictSize = [itemDict count];
id objects[dictSize];
id keys[dictSize];
[itemDict getObjects:objects andKeys:keys];
bool ok = false;
for(int i = 0; i < dictSize; i++) {
if([ssidStr isEqualToString:keys[i]]) {
const QString ident = QString::number(qHash(QLatin1String("corewlan:") + QCFString::toQString(objects[i])));
if(ident == identifier) {
ok = true;
}
}
if(ok && [timeStampStr isEqualToString:keys[i]]) {
timestamp = (quint64)[objects[i] timeIntervalSince1970];
isFound = true;
break;
}
}
if(isFound)
break;
}
}
}
[autoreleasepool release];
return timestamp;
}
quint64 QCoreWlanEngine::getBytes(const QString &interfaceName, bool b)
{
struct ifaddrs *ifAddressList, *ifAddress;
struct if_data *if_data;
quint64 bytes = 0;
ifAddressList = nil;
if(getifaddrs(&ifAddressList) == 0) {
for(ifAddress = ifAddressList; ifAddress; ifAddress = ifAddress->ifa_next) {
if(interfaceName == ifAddress->ifa_name) {
if_data = (struct if_data*)ifAddress->ifa_data;
if(b) {
bytes = if_data->ifi_ibytes;
break;
} else {
bytes = if_data->ifi_obytes;
break;
}
}
}
freeifaddrs(ifAddressList);
}
return bytes;
}
QT_END_NAMESPACE

View File

@ -55,25 +55,21 @@ QT_BEGIN_NAMESPACE
QNetworkManagerEngine::QNetworkManagerEngine(QObject *parent)
: QBearerEngineImpl(parent),
interface(new QNetworkManagerInterface(this)),
systemSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE_SYSTEM_SETTINGS, this)),
userSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE_USER_SETTINGS, this))
managerInterface(new QNetworkManagerInterface(this)),
systemSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE, this)),
userSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE, this))
{
if (!interface->isValid())
if (!managerInterface->isValid())
return;
interface->setConnections();
connect(interface, SIGNAL(deviceAdded(QDBusObjectPath)),
managerInterface->setConnections();
connect(managerInterface, SIGNAL(deviceAdded(QDBusObjectPath)),
this, SLOT(deviceAdded(QDBusObjectPath)));
connect(interface, SIGNAL(deviceRemoved(QDBusObjectPath)),
connect(managerInterface, SIGNAL(deviceRemoved(QDBusObjectPath)),
this, SLOT(deviceRemoved(QDBusObjectPath)));
#if 0
connect(interface, SIGNAL(stateChanged(QString,quint32)),
this, SIGNAL(configurationsChanged()));
#endif
connect(interface, SIGNAL(activationFinished(QDBusPendingCallWatcher*)),
connect(managerInterface, SIGNAL(activationFinished(QDBusPendingCallWatcher*)),
this, SLOT(activationFinished(QDBusPendingCallWatcher*)));
connect(interface, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)),
connect(managerInterface, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)),
this, SLOT(interfacePropertiesChanged(QString,QMap<QString,QVariant>)));
qDBusRegisterMetaType<QNmSettingsMap>();
@ -100,52 +96,56 @@ void QNetworkManagerEngine::initialize()
QMutexLocker locker(&mutex);
// Get current list of access points.
foreach (const QDBusObjectPath &devicePath, interface->getDevices()) {
foreach (const QDBusObjectPath &devicePath, managerInterface->getDevices()) {
locker.unlock();
deviceAdded(devicePath);
deviceAdded(devicePath); //add all accesspoints
locker.relock();
}
// Get connections.
foreach (const QDBusObjectPath &settingsPath, systemSettings->listConnections()) {
locker.unlock();
newConnection(settingsPath, systemSettings);
if (!hasIdentifier(settingsPath.path()))
newConnection(settingsPath, systemSettings); //add system connection configs
locker.relock();
}
foreach (const QDBusObjectPath &settingsPath, userSettings->listConnections()) {
locker.unlock();
newConnection(settingsPath, userSettings);
if (!hasIdentifier(settingsPath.path()))
newConnection(settingsPath, userSettings);
locker.relock();
}
// Get active connections.
foreach (const QDBusObjectPath &acPath, interface->activeConnections()) {
foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) {
QNetworkManagerConnectionActive *activeConnection =
new QNetworkManagerConnectionActive(acPath.path());
new QNetworkManagerConnectionActive(acPath.path(),this);
activeConnections.insert(acPath.path(), activeConnection);
activeConnection->setConnections();
connect(activeConnection, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)),
this, SLOT(activeConnectionPropertiesChanged(QString,QMap<QString,QVariant>)));
}
Q_EMIT updateCompleted();
}
bool QNetworkManagerEngine::networkManagerAvailable() const
{
QMutexLocker locker(&mutex);
return interface->isValid();
return managerInterface->isValid();
}
QString QNetworkManagerEngine::getInterfaceFromId(const QString &id)
{
QMutexLocker locker(&mutex);
foreach (const QDBusObjectPath &acPath, interface->activeConnections()) {
foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) {
QNetworkManagerConnectionActive activeConnection(acPath.path());
const QString identifier = QString::number(qHash(activeConnection.serviceName() + ' ' +
activeConnection.connection().path()));
const QString identifier = activeConnection.connection().path();
if (id == identifier) {
QList<QDBusObjectPath> devices = activeConnection.devices();
@ -161,24 +161,11 @@ QString QNetworkManagerEngine::getInterfaceFromId(const QString &id)
return QString();
}
bool QNetworkManagerEngine::hasIdentifier(const QString &id)
{
QMutexLocker locker(&mutex);
if (connectionFromId(id))
return true;
for (int i = 0; i < accessPoints.count(); ++i) {
QNetworkManagerInterfaceAccessPoint *accessPoint = accessPoints.at(i);
const QString identifier =
QString::number(qHash(accessPoint->connectionInterface()->path()));
if (id == identifier)
return true;
}
return false;
return accessPointConfigurations.contains(id);
}
void QNetworkManagerEngine::connectToId(const QString &id)
@ -194,18 +181,17 @@ void QNetworkManagerEngine::connectToId(const QString &id)
const QString connectionType = map.value("connection").value("type").toString();
QString dbusDevicePath;
foreach (const QDBusObjectPath &devicePath, interface->getDevices()) {
foreach (const QDBusObjectPath &devicePath, managerInterface->getDevices()) {
QNetworkManagerInterfaceDevice device(devicePath.path());
if (device.deviceType() == DEVICE_TYPE_802_3_ETHERNET &&
if (device.deviceType() == DEVICE_TYPE_ETHERNET &&
connectionType == QLatin1String("802-3-ethernet")) {
dbusDevicePath = devicePath.path();
break;
} else if (device.deviceType() == DEVICE_TYPE_802_11_WIRELESS &&
} else if (device.deviceType() == DEVICE_TYPE_WIFI &&
connectionType == QLatin1String("802-11-wireless")) {
dbusDevicePath = devicePath.path();
break;
}
else if (device.deviceType() == DEVICE_TYPE_GSM &&
} else if (device.deviceType() == DEVICE_TYPE_MODEM &&
connectionType == QLatin1String("gsm")) {
dbusDevicePath = devicePath.path();
break;
@ -214,29 +200,52 @@ void QNetworkManagerEngine::connectToId(const QString &id)
const QString service = connection->connectionInterface()->service();
const QString settingsPath = connection->connectionInterface()->path();
QString specificPath = configuredAccessPoints.key(settingsPath);
interface->activateConnection(service, QDBusObjectPath(settingsPath),
QDBusObjectPath(dbusDevicePath), QDBusObjectPath("/"));
if (specificPath.isEmpty())
specificPath = "/";
managerInterface->activateConnection(service, QDBusObjectPath(settingsPath),
QDBusObjectPath(dbusDevicePath), QDBusObjectPath(specificPath));
}
void QNetworkManagerEngine::disconnectFromId(const QString &id)
{
QMutexLocker locker(&mutex);
foreach (const QDBusObjectPath &acPath, interface->activeConnections()) {
QNetworkManagerSettingsConnection *connection = connectionFromId(id);
QNmSettingsMap map = connection->getSettings();
bool connectionAutoconnect = map.value("connection").value("autoconnect",true).toBool(); //if not present is true !!
if (connectionAutoconnect) { //autoconnect connections will simply be reconnected by nm
emit connectionError(id, QBearerEngineImpl::OperationNotSupported);
return;
}
foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) {
QNetworkManagerConnectionActive activeConnection(acPath.path());
const QString identifier = QString::number(qHash(activeConnection.serviceName() + ' ' +
activeConnection.connection().path()));
const QString identifier = activeConnection.connection().path();
if (id == identifier && accessPointConfigurations.contains(id)) {
interface->deactivateConnection(acPath);
managerInterface->deactivateConnection(acPath);
break;
}
}
}
void QNetworkManagerEngine::requestUpdate()
{
if (managerInterface->wirelessEnabled()) {
QHashIterator<QString, QNetworkManagerInterfaceDeviceWireless *> i(wirelessDevices);
while (i.hasNext()) {
i.next();
i.value()->requestScan();
}
}
QMetaObject::invokeMethod(this, "updateCompleted", Qt::QueuedConnection);
}
void QNetworkManagerEngine::scanFinished()
{
QMetaObject::invokeMethod(this, "updateCompleted", Qt::QueuedConnection);
}
@ -244,9 +253,8 @@ void QNetworkManagerEngine::requestUpdate()
void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path,
const QMap<QString, QVariant> &properties)
{
QMutexLocker locker(&mutex);
Q_UNUSED(path)
QMutexLocker locker(&mutex);
QMapIterator<QString, QVariant> i(properties);
while (i.hasNext()) {
@ -269,7 +277,7 @@ void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path,
QNetworkManagerConnectionActive *activeConnection =
this->activeConnections.value(acPath.path());
if (!activeConnection) {
activeConnection = new QNetworkManagerConnectionActive(acPath.path());
activeConnection = new QNetworkManagerConnectionActive(acPath.path(),this);
this->activeConnections.insert(acPath.path(), activeConnection);
activeConnection->setConnections();
@ -277,15 +285,14 @@ void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path,
this, SLOT(activeConnectionPropertiesChanged(QString,QMap<QString,QVariant>)));
}
const QString id = QString::number(qHash(activeConnection->serviceName() + ' ' +
activeConnection->connection().path()));
const QString id = activeConnection->connection().path();
identifiers.removeOne(id);
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
if (ptr) {
ptr->mutex.lock();
if (activeConnection->state() == 2 &&
if (activeConnection->state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED &&
ptr->state != QNetworkConfiguration::Active) {
ptr->state = QNetworkConfiguration::Active;
ptr->mutex.unlock();
@ -303,13 +310,13 @@ void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path,
delete this->activeConnections.take(priorActiveConnections.takeFirst());
while (!identifiers.isEmpty()) {
// These configurations are not active
QNetworkConfigurationPrivatePointer ptr =
accessPointConfigurations.value(identifiers.takeFirst());
ptr->mutex.lock();
if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
ptr->state = QNetworkConfiguration::Discovered;
QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined;
ptr->state = (flag | QNetworkConfiguration::Discovered);
ptr->mutex.unlock();
locker.unlock();
@ -335,15 +342,14 @@ void QNetworkManagerEngine::activeConnectionPropertiesChanged(const QString &pat
if (!activeConnection)
return;
const QString id = QString::number(qHash(activeConnection->serviceName() + ' ' +
activeConnection->connection().path()));
const QString id = activeConnection->connection().path();
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
if (ptr) {
ptr->mutex.lock();
if (activeConnection->state() == 2 &&
if (activeConnection->state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED &&
ptr->state != QNetworkConfiguration::Active) {
ptr->state = QNetworkConfiguration::Active;
ptr->state |= QNetworkConfiguration::Active;
ptr->mutex.unlock();
locker.unlock();
@ -355,34 +361,63 @@ void QNetworkManagerEngine::activeConnectionPropertiesChanged(const QString &pat
}
}
void QNetworkManagerEngine::devicePropertiesChanged(const QString &path,
const QMap<QString, QVariant> &properties)
void QNetworkManagerEngine::devicePropertiesChanged(const QString &/*path*/,quint32 /*state*/)
{
Q_UNUSED(path);
Q_UNUSED(properties);
// Q_UNUSED(path);
// Q_UNUSED(state)
}
void QNetworkManagerEngine::deviceConnectionsChanged(const QStringList &activeConnectionsList)
{
QMutexLocker locker(&mutex);
for (int i = 0; i < connections.count(); ++i) {
if (activeConnectionsList.contains(connections.at(i)->connectionInterface()->path()))
continue;
const QString settingsPath = connections.at(i)->connectionInterface()->path();
QNetworkConfigurationPrivatePointer ptr =
accessPointConfigurations.value(settingsPath);
ptr->mutex.lock();
QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined;
ptr->state = (flag | QNetworkConfiguration::Discovered);
ptr->mutex.unlock();
locker.unlock();
emit configurationChanged(ptr);
locker.relock();
Q_EMIT updateCompleted();
}
}
void QNetworkManagerEngine::deviceAdded(const QDBusObjectPath &path)
{
QNetworkManagerInterfaceDevice device(path.path());
if (device.deviceType() == DEVICE_TYPE_802_11_WIRELESS) {
QMutexLocker locker(&mutex);
QNetworkManagerInterfaceDevice *iDevice;
iDevice = new QNetworkManagerInterfaceDevice(path.path(),this);
connect(iDevice,SIGNAL(connectionsChanged(QStringList)),
this,SLOT(deviceConnectionsChanged(QStringList)));
connect(iDevice,SIGNAL(stateChanged(QString,quint32)),
this,SLOT(devicePropertiesChanged(QString,quint32)));
iDevice->setConnections();
interfaceDevices.insert(path.path(),iDevice);
if (iDevice->deviceType() == DEVICE_TYPE_WIFI) {
QNetworkManagerInterfaceDeviceWireless *wirelessDevice =
new QNetworkManagerInterfaceDeviceWireless(device.connectionInterface()->path());
new QNetworkManagerInterfaceDeviceWireless(iDevice->connectionInterface()->path(),this);
wirelessDevice->setConnections();
connect(wirelessDevice, SIGNAL(accessPointAdded(QString,QDBusObjectPath)),
this, SLOT(newAccessPoint(QString,QDBusObjectPath)));
connect(wirelessDevice, SIGNAL(accessPointRemoved(QString,QDBusObjectPath)),
this, SLOT(removeAccessPoint(QString,QDBusObjectPath)));
connect(wirelessDevice, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)),
this, SLOT(devicePropertiesChanged(QString,QMap<QString,QVariant>)));
connect(wirelessDevice, SIGNAL(accessPointAdded(QString)),
this, SLOT(newAccessPoint(QString)));
connect(wirelessDevice, SIGNAL(accessPointRemoved(QString)),
this, SLOT(removeAccessPoint(QString)));
connect(wirelessDevice,SIGNAL(scanDone()),this,SLOT(scanFinished()));
foreach (const QDBusObjectPath &apPath, wirelessDevice->getAccessPoints())
newAccessPoint(QString(), apPath);
newAccessPoint(apPath.path());
mutex.lock();
wirelessDevices.insert(path.path(), wirelessDevice);
mutex.unlock();
}
}
@ -390,47 +425,73 @@ void QNetworkManagerEngine::deviceRemoved(const QDBusObjectPath &path)
{
QMutexLocker locker(&mutex);
delete wirelessDevices.take(path.path());
if (interfaceDevices.contains(path.path())) {
locker.unlock();
delete interfaceDevices.take(path.path());
locker.relock();
}
if (wirelessDevices.contains(path.path())) {
locker.unlock();
delete wirelessDevices.take(path.path());
locker.relock();
}
}
void QNetworkManagerEngine::newConnection(const QDBusObjectPath &path,
QNetworkManagerSettings *settings)
{
QMutexLocker locker(&mutex);
if (!settings)
settings = qobject_cast<QNetworkManagerSettings *>(sender());
if (!settings)
return;
settings->deleteLater();
QNetworkManagerSettingsConnection *connection =
new QNetworkManagerSettingsConnection(settings->connectionInterface()->service(),
path.path());
path.path(),this);
QString apPath;
for (int i = 0; i < accessPoints.count(); ++i) {
if (connection->getSsid() == accessPoints.at(i)->ssid()) {
// remove the corresponding accesspoint from configurations
apPath = accessPoints.at(i)->connectionInterface()->path();
QNetworkConfigurationPrivatePointer ptr
= accessPointConfigurations.take(apPath);
if (ptr) {
locker.unlock();
emit configurationRemoved(ptr);
locker.relock();
}
}
}
connections.append(connection);
connect(connection, SIGNAL(removed(QString)), this, SLOT(removeConnection(QString)));
connect(connection, SIGNAL(updated(QNmSettingsMap)),
this, SLOT(updateConnection(QNmSettingsMap)));
connect(connection,SIGNAL(removed(QString)),this,SLOT(removeConnection(QString)));
connect(connection,SIGNAL(updated()),this,SLOT(updateConnection()));
connection->setConnections();
const QString service = connection->connectionInterface()->service();
const QString settingsPath = connection->connectionInterface()->path();
if (connection->getType() == DEVICE_TYPE_WIFI
&& !configuredAccessPoints.contains(settingsPath))
configuredAccessPoints.insert(apPath,settingsPath);
QNetworkConfigurationPrivate *cpPriv =
parseConnection(service, settingsPath, connection->getSettings());
parseConnection(settingsPath, connection->getSettings());
// Check if connection is active.
foreach (const QDBusObjectPath &acPath, interface->activeConnections()) {
foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) {
QNetworkManagerConnectionActive activeConnection(acPath.path());
if (activeConnection.serviceName() == service &&
if (activeConnection.defaultRoute() &&
activeConnection.connection().path() == settingsPath &&
activeConnection.state() == 2) {
activeConnection.state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
cpPriv->state |= QNetworkConfiguration::Active;
break;
}
}
QNetworkConfigurationPrivatePointer ptr(cpPriv);
accessPointConfigurations.insert(ptr->id, ptr);
@ -442,27 +503,34 @@ void QNetworkManagerEngine::removeConnection(const QString &path)
{
QMutexLocker locker(&mutex);
Q_UNUSED(path)
QNetworkManagerSettingsConnection *connection =
qobject_cast<QNetworkManagerSettingsConnection *>(sender());
if (!connection)
return;
connection->deleteLater();
connections.removeAll(connection);
const QString id = QString::number(qHash(connection->connectionInterface()->service() + ' ' +
connection->connectionInterface()->path()));
const QString id = path;
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(id);
connection->deleteLater();
locker.unlock();
emit configurationRemoved(ptr);
if (ptr) {
locker.unlock();
emit configurationRemoved(ptr);
locker.relock();
}
// add base AP back into configurations
QMapIterator<QString, QString> i(configuredAccessPoints);
while (i.hasNext()) {
i.next();
if (i.value() == path) {
newAccessPoint(i.key());
}
}
}
void QNetworkManagerEngine::updateConnection(const QNmSettingsMap &settings)
void QNetworkManagerEngine::updateConnection()
{
QMutexLocker locker(&mutex);
@ -471,17 +539,16 @@ void QNetworkManagerEngine::updateConnection(const QNmSettingsMap &settings)
if (!connection)
return;
const QString service = connection->connectionInterface()->service();
connection->deleteLater();
const QString settingsPath = connection->connectionInterface()->path();
QNetworkConfigurationPrivate *cpPriv = parseConnection(service, settingsPath, settings);
QNetworkConfigurationPrivate *cpPriv = parseConnection(settingsPath, connection->getSettings());
// Check if connection is active.
foreach (const QDBusObjectPath &acPath, interface->activeConnections()) {
foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) {
QNetworkManagerConnectionActive activeConnection(acPath.path());
if (activeConnection.serviceName() == service &&
activeConnection.connection().path() == settingsPath &&
if (activeConnection.connection().path() == settingsPath &&
activeConnection.state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
cpPriv->state |= QNetworkConfiguration::Active;
break;
@ -501,6 +568,7 @@ void QNetworkManagerEngine::updateConnection(const QNmSettingsMap &settings)
locker.unlock();
emit configurationChanged(ptr);
locker.relock();
delete cpPriv;
}
@ -508,21 +576,22 @@ void QNetworkManagerEngine::activationFinished(QDBusPendingCallWatcher *watcher)
{
QMutexLocker locker(&mutex);
watcher->deleteLater();
QDBusPendingReply<QDBusObjectPath> reply(*watcher);
if (!reply.isError()) {
QDBusObjectPath result = reply.value();
QNetworkManagerConnectionActive activeConnection(result.path());
const QString id = QString::number(qHash(activeConnection.serviceName() + ' ' +
activeConnection.connection().path()));
const QString id = activeConnection.connection().path();
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
if (ptr) {
ptr->mutex.lock();
if (activeConnection.state() == 2 &&
if (activeConnection.state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED &&
ptr->state != QNetworkConfiguration::Active) {
ptr->state = QNetworkConfiguration::Active;
ptr->state |= QNetworkConfiguration::Active;
ptr->mutex.unlock();
locker.unlock();
@ -535,42 +604,41 @@ void QNetworkManagerEngine::activationFinished(QDBusPendingCallWatcher *watcher)
}
}
void QNetworkManagerEngine::newAccessPoint(const QString &path, const QDBusObjectPath &objectPath)
void QNetworkManagerEngine::newAccessPoint(const QString &path)
{
QMutexLocker locker(&mutex);
Q_UNUSED(path)
QNetworkManagerInterfaceAccessPoint *accessPoint =
new QNetworkManagerInterfaceAccessPoint(objectPath.path());
accessPoints.append(accessPoint);
new QNetworkManagerInterfaceAccessPoint(path,this);
accessPoint->setConnections();
connect(accessPoint, SIGNAL(propertiesChanged(QMap<QString,QVariant>)),
this, SLOT(updateAccessPoint(QMap<QString,QVariant>)));
// Check if configuration for this SSID already exists.
bool okToAdd = true;
for (int i = 0; i < accessPoints.count(); ++i) {
if (accessPoint != accessPoints.at(i) &&
accessPoint->ssid() == accessPoints.at(i)->ssid()) {
return;
if (accessPoints.at(i)->connectionInterface()->path() == path) {
okToAdd = false;
}
}
if (okToAdd) {
accessPoints.append(accessPoint);
accessPoint->setConnections();
connect(accessPoint, SIGNAL(propertiesChanged(QMap<QString,QVariant>)),
this, SLOT(updateAccessPoint(QMap<QString,QVariant>)));
}
// Check if configuration exists for connection.
if (!accessPoint->ssid().isEmpty()) {
for (int i = 0; i < connections.count(); ++i) {
QNetworkManagerSettingsConnection *connection = connections.at(i);
const QString settingsPath = connection->connectionInterface()->path();
if (accessPoint->ssid() == connection->getSsid()) {
const QString service = connection->connectionInterface()->service();
const QString settingsPath = connection->connectionInterface()->path();
const QString connectionId = QString::number(qHash(service + ' ' + settingsPath));
if (!configuredAccessPoints.contains(path)) {
configuredAccessPoints.insert(path,settingsPath);
}
QNetworkConfigurationPrivatePointer ptr =
accessPointConfigurations.value(connectionId);
accessPointConfigurations.value(settingsPath);
ptr->mutex.lock();
ptr->state = QNetworkConfiguration::Discovered;
QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined;
ptr->state = (flag | QNetworkConfiguration::Discovered);
ptr->mutex.unlock();
locker.unlock();
@ -585,9 +653,9 @@ void QNetworkManagerEngine::newAccessPoint(const QString &path, const QDBusObjec
ptr->name = accessPoint->ssid();
ptr->isValid = true;
ptr->id = QString::number(qHash(objectPath.path()));
ptr->id = path;
ptr->type = QNetworkConfiguration::InternetAccessPoint;
if(accessPoint->flags() == NM_802_11_AP_FLAGS_PRIVACY) {
if (accessPoint->flags() == NM_802_11_AP_FLAGS_PRIVACY) {
ptr->purpose = QNetworkConfiguration::PrivatePurpose;
} else {
ptr->purpose = QNetworkConfiguration::PublicPurpose;
@ -601,30 +669,24 @@ void QNetworkManagerEngine::newAccessPoint(const QString &path, const QDBusObjec
emit configurationAdded(ptr);
}
void QNetworkManagerEngine::removeAccessPoint(const QString &path,
const QDBusObjectPath &objectPath)
void QNetworkManagerEngine::removeAccessPoint(const QString &path)
{
QMutexLocker locker(&mutex);
Q_UNUSED(path)
for (int i = 0; i < accessPoints.count(); ++i) {
QNetworkManagerInterfaceAccessPoint *accessPoint = accessPoints.at(i);
if (accessPoint->connectionInterface()->path() == objectPath.path()) {
if (accessPoint->connectionInterface()->path() == path) {
accessPoints.removeOne(accessPoint);
if (configuredAccessPoints.contains(accessPoint)) {
if (configuredAccessPoints.contains(accessPoint->connectionInterface()->path())) {
// find connection and change state to Defined
configuredAccessPoints.removeOne(accessPoint);
configuredAccessPoints.remove(accessPoint->connectionInterface()->path());
for (int i = 0; i < connections.count(); ++i) {
QNetworkManagerSettingsConnection *connection = connections.at(i);
if (accessPoint->ssid() == connection->getSsid()) {
const QString service = connection->connectionInterface()->service();
if (accessPoint->ssid() == connection->getSsid()) {//might not have bssid yet
const QString settingsPath = connection->connectionInterface()->path();
const QString connectionId =
QString::number(qHash(service + ' ' + settingsPath));
const QString connectionId = settingsPath;
QNetworkConfigurationPrivatePointer ptr =
accessPointConfigurations.value(connectionId);
@ -640,17 +702,17 @@ void QNetworkManagerEngine::removeAccessPoint(const QString &path,
}
} else {
QNetworkConfigurationPrivatePointer ptr =
accessPointConfigurations.take(QString::number(qHash(objectPath.path())));
accessPointConfigurations.take(path);
if (ptr) {
locker.unlock();
locker.unlock();
emit configurationRemoved(ptr);
locker.relock();
}
}
delete accessPoint;
break;
}
}
@ -666,19 +728,19 @@ void QNetworkManagerEngine::updateAccessPoint(const QMap<QString, QVariant> &map
qobject_cast<QNetworkManagerInterfaceAccessPoint *>(sender());
if (!accessPoint)
return;
accessPoint->deleteLater();
for (int i = 0; i < connections.count(); ++i) {
QNetworkManagerSettingsConnection *connection = connections.at(i);
if (accessPoint->ssid() == connection->getSsid()) {
const QString service = connection->connectionInterface()->service();
const QString settingsPath = connection->connectionInterface()->path();
const QString connectionId = QString::number(qHash(service + ' ' + settingsPath));
const QString connectionId = settingsPath;
QNetworkConfigurationPrivatePointer ptr =
accessPointConfigurations.value(connectionId);
ptr->mutex.lock();
ptr->state = QNetworkConfiguration::Discovered;
QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined;
ptr->state = (flag | QNetworkConfiguration::Discovered);
ptr->mutex.unlock();
locker.unlock();
@ -688,14 +750,16 @@ void QNetworkManagerEngine::updateAccessPoint(const QMap<QString, QVariant> &map
}
}
QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QString &service,
const QString &settingsPath,
QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QString &settingsPath,
const QNmSettingsMap &map)
{
// Q_UNUSED(service);
QMutexLocker locker(&mutex);
QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate;
cpPriv->name = map.value("connection").value("id").toString();
cpPriv->isValid = true;
cpPriv->id = QString::number(qHash(service + ' ' + settingsPath));
cpPriv->id = settingsPath;
cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
cpPriv->purpose = QNetworkConfiguration::PublicPurpose;
@ -708,15 +772,14 @@ QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QStri
cpPriv->bearerType = QNetworkConfiguration::BearerEthernet;
cpPriv->purpose = QNetworkConfiguration::PublicPurpose;
foreach (const QDBusObjectPath &devicePath, interface->getDevices()) {
foreach (const QDBusObjectPath &devicePath, managerInterface->getDevices()) {
QNetworkManagerInterfaceDevice device(devicePath.path());
if (device.deviceType() == DEVICE_TYPE_802_3_ETHERNET) {
if (device.deviceType() == DEVICE_TYPE_ETHERNET) {
QNetworkManagerInterfaceDeviceWired wiredDevice(device.connectionInterface()->path());
if (wiredDevice.carrier()) {
cpPriv->state |= QNetworkConfiguration::Discovered;
break;
}
}
}
} else if (connectionType == QLatin1String("802-11-wireless")) {
@ -724,35 +787,57 @@ QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QStri
const QString connectionSsid = map.value("802-11-wireless").value("ssid").toString();
const QString connectionSecurity = map.value("802-11-wireless").value("security").toString();
if(!connectionSecurity.isEmpty()) {
if (!connectionSecurity.isEmpty()) {
cpPriv->purpose = QNetworkConfiguration::PrivatePurpose;
} else {
cpPriv->purpose = QNetworkConfiguration::PublicPurpose;
}
for (int i = 0; i < accessPoints.count(); ++i) {
if (connectionSsid == accessPoints.at(i)->ssid()) {
if (connectionSsid == accessPoints.at(i)->ssid()
&& map.value("802-11-wireless").value("seen-bssids").toStringList().contains(accessPoints.at(i)->hwAddress())) {
cpPriv->state |= QNetworkConfiguration::Discovered;
if (!configuredAccessPoints.contains(accessPoints.at(i))) {
configuredAccessPoints.append(accessPoints.at(i));
if (!configuredAccessPoints.contains(accessPoints.at(i)->connectionInterface()->path())) {
configuredAccessPoints.insert(accessPoints.at(i)->connectionInterface()->path(),settingsPath);
const QString accessPointId =
QString::number(qHash(accessPoints.at(i)->connectionInterface()->path()));
const QString accessPointId = accessPoints.at(i)->connectionInterface()->path();
QNetworkConfigurationPrivatePointer ptr =
accessPointConfigurations.take(accessPointId);
if (ptr) {
mutex.unlock();
locker.unlock();
emit configurationRemoved(ptr);
mutex.lock();
locker.relock();
}
}
break;
}
}
} else if (connectionType == "gsm") {
cpPriv->bearerType = QNetworkConfiguration::Bearer2G;
} else if (connectionType == "cdma") {
cpPriv->bearerType = QNetworkConfiguration::BearerCDMA2000;
} else if (connectionType == QLatin1String("gsm")) {
foreach (const QDBusObjectPath &devicePath, managerInterface->getDevices()) {
QNetworkManagerInterfaceDevice device(devicePath.path());
if (device.deviceType() == DEVICE_TYPE_MODEM) {
QNetworkManagerInterfaceDeviceModem deviceModem(device.connectionInterface()->path(),this);
switch (deviceModem.currentCapabilities()) {
case 2:
cpPriv->bearerType = QNetworkConfiguration::Bearer2G;
break;
case 4:
cpPriv->bearerType = QNetworkConfiguration::Bearer3G;
break;
case 8:
cpPriv->bearerType = QNetworkConfiguration::Bearer4G;
break;
default:
cpPriv->bearerType = QNetworkConfiguration::BearerUnknown;
break;
};
}
}
cpPriv->purpose = QNetworkConfiguration::PrivatePurpose;
cpPriv->state |= QNetworkConfiguration::Discovered;
}
return cpPriv;
@ -762,12 +847,7 @@ QNetworkManagerSettingsConnection *QNetworkManagerEngine::connectionFromId(const
{
for (int i = 0; i < connections.count(); ++i) {
QNetworkManagerSettingsConnection *connection = connections.at(i);
const QString service = connection->connectionInterface()->service();
const QString settingsPath = connection->connectionInterface()->path();
const QString identifier = QString::number(qHash(service + ' ' + settingsPath));
if (id == identifier)
if (id == connection->connectionInterface()->path())
return connection;
}
@ -789,8 +869,7 @@ QNetworkSession::State QNetworkManagerEngine::sessionStateForId(const QString &i
foreach (const QString &acPath, activeConnections.keys()) {
QNetworkManagerConnectionActive *activeConnection = activeConnections.value(acPath);
const QString identifier = QString::number(qHash(activeConnection->serviceName() + ' ' +
activeConnection->connection().path()));
const QString identifier = activeConnection->connection().path();
if (id == identifier) {
switch (activeConnection->state()) {
@ -884,7 +963,8 @@ quint64 QNetworkManagerEngine::startTime(const QString &id)
QNetworkConfigurationManager::Capabilities QNetworkManagerEngine::capabilities() const
{
return QNetworkConfigurationManager::ForcedRoaming |
QNetworkConfigurationManager::CanStartAndStopInterfaces;
QNetworkConfigurationManager::DataStatistics |
QNetworkConfigurationManager::CanStartAndStopInterfaces;
}
QNetworkSessionPrivate *QNetworkManagerEngine::createSessionBackend()

View File

@ -93,36 +93,37 @@ private Q_SLOTS:
const QMap<QString, QVariant> &properties);
void activeConnectionPropertiesChanged(const QString &path,
const QMap<QString, QVariant> &properties);
void devicePropertiesChanged(const QString &path,
const QMap<QString, QVariant> &properties);
void devicePropertiesChanged(const QString &path, quint32);
void deviceAdded(const QDBusObjectPath &path);
void deviceRemoved(const QDBusObjectPath &path);
void newConnection(const QDBusObjectPath &path, QNetworkManagerSettings *settings = 0);
void removeConnection(const QString &path);
void updateConnection(const QNmSettingsMap &settings);
void updateConnection();
void activationFinished(QDBusPendingCallWatcher *watcher);
void deviceConnectionsChanged(const QStringList &activeConnectionsList);
void newAccessPoint(const QString &path, const QDBusObjectPath &objectPath);
void removeAccessPoint(const QString &path, const QDBusObjectPath &objectPath);
void newAccessPoint(const QString &path);
void removeAccessPoint(const QString &path);
void updateAccessPoint(const QMap<QString, QVariant> &map);
void scanFinished();
private:
QNetworkConfigurationPrivate *parseConnection(const QString &service,
const QString &settingsPath,
QNetworkConfigurationPrivate *parseConnection(const QString &settingsPath,
const QNmSettingsMap &map);
QNetworkManagerSettingsConnection *connectionFromId(const QString &id) const;
private:
QNetworkManagerInterface *interface;
QNetworkManagerInterface *managerInterface;
QNetworkManagerSettings *systemSettings;
QNetworkManagerSettings *userSettings;
QHash<QString, QNetworkManagerInterfaceDeviceWireless *> wirelessDevices;
QHash<QString, QNetworkManagerConnectionActive *> activeConnections;
QList<QNetworkManagerSettingsConnection *> connections;
QList<QNetworkManagerInterfaceAccessPoint *> accessPoints;
QList<QNetworkManagerInterfaceAccessPoint *> configuredAccessPoints;
QHash<QString, QNetworkManagerInterfaceDevice *> interfaceDevices;
QMap<QString,QString> configuredAccessPoints; //ap, settings path
};
QT_END_NAMESPACE

View File

@ -97,21 +97,21 @@ bool QNetworkManagerInterface::setConnections()
QDBusConnection dbusConnection = QDBusConnection::systemBus();
bool allOk = false;
if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
if (dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
QLatin1String(NM_DBUS_PATH),
QLatin1String(NM_DBUS_INTERFACE),
QLatin1String("PropertiesChanged"),
nmDBusHelper,SLOT(slotPropertiesChanged(QMap<QString,QVariant>)))) {
allOk = true;
}
if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
if (dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
QLatin1String(NM_DBUS_PATH),
QLatin1String(NM_DBUS_INTERFACE),
QLatin1String("DeviceAdded"),
this,SIGNAL(deviceAdded(QDBusObjectPath)))) {
allOk = true;
}
if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
if (dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
QLatin1String(NM_DBUS_PATH),
QLatin1String(NM_DBUS_INTERFACE),
QLatin1String("DeviceRemoved"),
@ -133,18 +133,17 @@ QList <QDBusObjectPath> QNetworkManagerInterface::getDevices() const
return reply.value();
}
void QNetworkManagerInterface::activateConnection( const QString &serviceName,
void QNetworkManagerInterface::activateConnection( const QString &,
QDBusObjectPath connectionPath,
QDBusObjectPath devicePath,
QDBusObjectPath specificObject)
{
QDBusPendingCall pendingCall = d->connectionInterface->asyncCall(QLatin1String("ActivateConnection"),
QVariant(serviceName),
QVariant::fromValue(connectionPath),
QVariant::fromValue(devicePath),
QVariant::fromValue(specificObject));
QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(pendingCall, this);
QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(pendingCall);
connect(callWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
this, SIGNAL(activationFinished(QDBusPendingCallWatcher*)));
}
@ -323,18 +322,31 @@ bool QNetworkManagerInterfaceDevice::setConnections()
if(!isValid() )
return false;
bool allOk = false;
bool allOk = true;
delete nmDBusHelper;
nmDBusHelper = new QNmDBusHelper(this);
connect(nmDBusHelper,SIGNAL(pathForStateChanged(QString,quint32)),
this, SIGNAL(stateChanged(QString,quint32)));
if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE),
d->path,
QLatin1String(NM_DBUS_INTERFACE_DEVICE),
QLatin1String("StateChanged"),
nmDBusHelper,SLOT(deviceStateChanged(quint32)))) {
allOk = true;
allOk = false;
}
connect(nmDBusHelper, SIGNAL(pathForConnectionsChanged(QStringList)),
this,SIGNAL(connectionsChanged(QStringList)));
if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE),
d->path,
QLatin1String(NM_DBUS_INTERFACE_ACCESS_POINT),
QLatin1String("PropertiesChanged"),
nmDBusHelper,SLOT(slotPropertiesChanged(QMap<QString,QVariant>))) ) {
allOk = false;
}
return allOk;
}
@ -415,18 +427,18 @@ bool QNetworkManagerInterfaceDeviceWired::setConnections()
if(!isValid() )
return false;
bool allOk = false;
bool allOk = true;
delete nmDBusHelper;
nmDBusHelper = new QNmDBusHelper(this);
connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap<QString,QVariant>)),
this,SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)));
if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE),
if (!QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE),
d->path,
QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRED),
QLatin1String("PropertiesChanged"),
nmDBusHelper,SLOT(slotPropertiesChanged(QMap<QString,QVariant>))) ) {
allOk = true;
allOk = false;
}
return allOk;
}
@ -492,44 +504,50 @@ bool QNetworkManagerInterfaceDeviceWireless::setConnections()
return false;
QDBusConnection dbusConnection = QDBusConnection::systemBus();
bool allOk = false;
bool allOk = true;
delete nmDBusHelper;
nmDBusHelper = new QNmDBusHelper(this);
connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap<QString,QVariant>)),
this,SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)));
connect(nmDBusHelper, SIGNAL(pathForAccessPointAdded(QString,QDBusObjectPath)),
this,SIGNAL(accessPointAdded(QString,QDBusObjectPath)));
connect(nmDBusHelper, SIGNAL(pathForAccessPointAdded(QString)),
this,SIGNAL(accessPointAdded(QString)));
connect(nmDBusHelper, SIGNAL(pathForAccessPointRemoved(QString,QDBusObjectPath)),
this,SIGNAL(accessPointRemoved(QString,QDBusObjectPath)));
connect(nmDBusHelper, SIGNAL(pathForAccessPointRemoved(QString)),
this,SIGNAL(accessPointRemoved(QString)));
if(!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
d->path,
QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS),
QLatin1String("AccessPointAdded"),
nmDBusHelper, SLOT(slotAccessPointAdded(QDBusObjectPath)))) {
allOk = true;
allOk = false;
}
if(!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
d->path,
QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS),
QLatin1String("AccessPointRemoved"),
nmDBusHelper, SLOT(slotAccessPointRemoved(QDBusObjectPath)))) {
allOk = true;
allOk = false;
}
if(!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
d->path,
QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS),
QLatin1String("PropertiesChanged"),
nmDBusHelper,SLOT(slotPropertiesChanged(QMap<QString,QVariant>)))) {
allOk = true;
allOk = false;
}
if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
d->path,
QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS),
QLatin1String("ScanDone"),
this, SLOT(scanIsDone()))) {
allOk = false;
}
return allOk;
}
@ -569,6 +587,89 @@ quint32 QNetworkManagerInterfaceDeviceWireless::wirelessCapabilities() const
return d->connectionInterface->property("WirelelessCapabilities").toUInt();
}
void QNetworkManagerInterfaceDeviceWireless::scanIsDone()
{
Q_EMIT scanDone();
}
void QNetworkManagerInterfaceDeviceWireless::requestScan()
{
d->connectionInterface->asyncCall(QLatin1String("RequestScan"));
}
class QNetworkManagerInterfaceDeviceModemPrivate
{
public:
QDBusInterface *connectionInterface;
QString path;
bool valid;
};
QNetworkManagerInterfaceDeviceModem::QNetworkManagerInterfaceDeviceModem(const QString &ifaceDevicePath, QObject *parent)
: QObject(parent), nmDBusHelper(0)
{
d = new QNetworkManagerInterfaceDeviceModemPrivate();
d->path = ifaceDevicePath;
d->connectionInterface = new QDBusInterface(QLatin1String(NM_DBUS_SERVICE),
d->path,
QLatin1String(NM_DBUS_INTERFACE_DEVICE_MODEM),
QDBusConnection::systemBus(), parent);
if (!d->connectionInterface->isValid()) {
d->valid = false;
return;
}
d->valid = true;
}
QNetworkManagerInterfaceDeviceModem::~QNetworkManagerInterfaceDeviceModem()
{
delete d->connectionInterface;
delete d;
}
bool QNetworkManagerInterfaceDeviceModem::isValid()
{
return d->valid;
}
bool QNetworkManagerInterfaceDeviceModem::setConnections()
{
if (!isValid() )
return false;
bool allOk = true;
delete nmDBusHelper;
nmDBusHelper = new QNmDBusHelper(this);
connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap<QString,QVariant>)),
this,SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)));
if (!QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE),
d->path,
QLatin1String(NM_DBUS_INTERFACE_DEVICE_MODEM),
QLatin1String("PropertiesChanged"),
nmDBusHelper,SLOT(slotDevicePropertiesChanged(QMap<QString,QVariant>))) ) {
allOk = false;
}
return allOk;
}
QDBusInterface *QNetworkManagerInterfaceDeviceModem::connectionInterface() const
{
return d->connectionInterface;
}
quint32 QNetworkManagerInterfaceDeviceModem::modemCapabilities() const
{
return d->connectionInterface->property("ModemCapabilities").toUInt();
}
quint32 QNetworkManagerInterfaceDeviceModem::currentCapabilities() const
{
return d->connectionInterface->property("CurrentCapabilities").toUInt();
}
class QNetworkManagerSettingsPrivate
{
public:
@ -606,12 +707,14 @@ bool QNetworkManagerSettings::isValid()
bool QNetworkManagerSettings::setConnections()
{
bool allOk = false;
bool allOk = true;
if (!QDBusConnection::systemBus().connect(d->path, QLatin1String(NM_DBUS_PATH_SETTINGS),
QLatin1String(NM_DBUS_IFACE_SETTINGS), QLatin1String("NewConnection"),
this, SIGNAL(newConnection(QDBusObjectPath)))) {
allOk = true;
if (!QDBusConnection::systemBus().connect(d->path,
QLatin1String(NM_DBUS_PATH_SETTINGS),
QLatin1String(NM_DBUS_IFACE_SETTINGS),
QLatin1String("NewConnection"),
this, SIGNAL(newConnection(QDBusObjectPath)))) {
allOk = false;
}
return allOk;
@ -623,6 +726,14 @@ QList <QDBusObjectPath> QNetworkManagerSettings::listConnections()
return reply.value();
}
QString QNetworkManagerSettings::getConnectionByUuid(const QString &uuid)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(uuid);
QDBusReply<QDBusObjectPath > reply = d->connectionInterface->callWithArgumentList(QDBus::Block,QLatin1String("GetConnectionByUuid"), argumentList);
return reply.value().path();
}
QDBusInterface *QNetworkManagerSettings::connectionInterface() const
{
return d->connectionInterface;
@ -676,13 +787,13 @@ bool QNetworkManagerSettingsConnection::setConnections()
return false;
QDBusConnection dbusConnection = QDBusConnection::systemBus();
bool allOk = false;
if(!dbusConnection.connect(d->service, d->path,
QLatin1String(NM_DBUS_IFACE_SETTINGS_CONNECTION), QLatin1String("Updated"),
this, SIGNAL(updated(QNmSettingsMap)))) {
allOk = true;
} else {
QDBusError error = dbusConnection.lastError();
bool allOk = true;
if (!dbusConnection.connect(d->service,
d->path,
QLatin1String(NM_DBUS_IFACE_SETTINGS_CONNECTION),
QLatin1String("Updated"),
this, SIGNAL(updated()))) {
allOk = false;
}
delete nmDBusHelper;
@ -690,12 +801,13 @@ bool QNetworkManagerSettingsConnection::setConnections()
connect(nmDBusHelper, SIGNAL(pathForSettingsRemoved(QString)),
this,SIGNAL(removed(QString)));
if (!dbusConnection.connect(d->service, d->path,
QLatin1String(NM_DBUS_IFACE_SETTINGS_CONNECTION), QLatin1String("Removed"),
nmDBusHelper, SIGNAL(slotSettingsRemoved()))) {
allOk = true;
if (!dbusConnection.connect(d->service,
d->path,
QLatin1String(NM_DBUS_IFACE_SETTINGS_CONNECTION),
QLatin1String("Removed"),
nmDBusHelper, SIGNAL(slotSettingsRemoved()))) {
allOk = false;
}
return allOk;
}
@ -717,9 +829,9 @@ NMDeviceType QNetworkManagerSettingsConnection::getType()
d->settingsMap.value(QLatin1String("connection")).value(QLatin1String("type")).toString();
if (devType == QLatin1String("802-3-ethernet"))
return DEVICE_TYPE_802_3_ETHERNET;
return DEVICE_TYPE_ETHERNET;
else if (devType == QLatin1String("802-11-wireless"))
return DEVICE_TYPE_802_11_WIRELESS;
return DEVICE_TYPE_WIFI;
else
return DEVICE_TYPE_UNKNOWN;
}
@ -766,10 +878,10 @@ QString QNetworkManagerSettingsConnection::getMacAddress()
{
NMDeviceType type = getType();
if (type == DEVICE_TYPE_802_3_ETHERNET) {
if (type == DEVICE_TYPE_ETHERNET) {
return d->settingsMap.value(QLatin1String("802-3-ethernet"))
.value(QLatin1String("mac-address")).toString();
} else if (type == DEVICE_TYPE_802_11_WIRELESS) {
} else if (type == DEVICE_TYPE_WIFI) {
return d->settingsMap.value(QLatin1String("802-11-wireless"))
.value(QLatin1String("mac-address")).toString();
} else {
@ -779,7 +891,7 @@ QString QNetworkManagerSettingsConnection::getMacAddress()
QStringList QNetworkManagerSettingsConnection::getSeenBssids()
{
if (getType() == DEVICE_TYPE_802_11_WIRELESS) {
if (getType() == DEVICE_TYPE_WIFI) {
return d->settingsMap.value(QLatin1String("802-11-wireless"))
.value(QLatin1String("seen-bssids")).toStringList();
} else {
@ -795,7 +907,7 @@ public:
bool valid;
};
QNetworkManagerConnectionActive::QNetworkManagerConnectionActive( const QString &activeConnectionObjectPath, QObject *parent)
QNetworkManagerConnectionActive::QNetworkManagerConnectionActive(const QString &activeConnectionObjectPath, QObject *parent)
: QObject(parent), nmDBusHelper(0)
{
d = new QNetworkManagerConnectionActivePrivate();
@ -827,17 +939,18 @@ bool QNetworkManagerConnectionActive::setConnections()
if(!isValid() )
return false;
bool allOk = false;
bool allOk = true;
delete nmDBusHelper;
nmDBusHelper = new QNmDBusHelper(this);
connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap<QString,QVariant>)),
this,SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)));
if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE),
if (!QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE),
d->path,
QLatin1String(NM_DBUS_INTERFACE_ACTIVE_CONNECTION),
QLatin1String("PropertiesChanged"),
nmDBusHelper,SLOT(slotPropertiesChanged(QMap<QString,QVariant>))) ) {
allOk = true;
nmDBusHelper,SLOT(activeConnectionPropertiesChanged(QMap<QString,QVariant>))) ) {
allOk = false;
}
return allOk;
@ -848,11 +961,6 @@ QDBusInterface *QNetworkManagerConnectionActive::connectionInterface() const
return d->connectionInterface;
}
QString QNetworkManagerConnectionActive::serviceName() const
{
return d->connectionInterface->property("ServiceName").toString();
}
QDBusObjectPath QNetworkManagerConnectionActive::connection() const
{
QVariant prop = d->connectionInterface->property("Connection");

View File

@ -64,31 +64,32 @@
typedef enum NMDeviceType
{
DEVICE_TYPE_UNKNOWN = 0,
DEVICE_TYPE_802_3_ETHERNET,
DEVICE_TYPE_802_11_WIRELESS,
DEVICE_TYPE_GSM,
DEVICE_TYPE_CDMA
DEVICE_TYPE_ETHERNET,
DEVICE_TYPE_WIFI,
DEVICE_TYPE_MODEM = 8
} NMDeviceType;
typedef enum
{
NM_DEVICE_STATE_UNKNOWN = 0,
NM_DEVICE_STATE_UNMANAGED,
NM_DEVICE_STATE_UNAVAILABLE,
NM_DEVICE_STATE_DISCONNECTED,
NM_DEVICE_STATE_PREPARE,
NM_DEVICE_STATE_CONFIG,
NM_DEVICE_STATE_NEED_AUTH,
NM_DEVICE_STATE_IP_CONFIG,
NM_DEVICE_STATE_ACTIVATED,
NM_DEVICE_STATE_FAILED
NM_DEVICE_STATE_UNMANAGED = 10,
NM_DEVICE_STATE_UNAVAILABLE = 20,
NM_DEVICE_STATE_DISCONNECTED = 30,
NM_DEVICE_STATE_PREPARE = 40,
NM_DEVICE_STATE_CONFIG = 50,
NM_DEVICE_STATE_NEED_AUTH = 60,
NM_DEVICE_STATE_IP_CONFIG = 70,
NM_DEVICE_STATE_ACTIVATED = 100,
NM_DEVICE_STATE_DEACTIVATING = 110,
NM_DEVICE_STATE_FAILED = 120
} NMDeviceState;
typedef enum
{
NM_ACTIVE_CONNECTION_STATE_UNKNOWN = 0,
NM_ACTIVE_CONNECTION_STATE_ACTIVATING,
NM_ACTIVE_CONNECTION_STATE_ACTIVATED
NM_ACTIVE_CONNECTION_STATE_ACTIVATED,
NM_ACTIVE_CONNECTION_STATE_DEACTIVATED
} NMActiveConnectionState;
#define NM_DBUS_SERVICE "org.freedesktop.NetworkManager"
@ -98,13 +99,14 @@ typedef enum
#define NM_DBUS_INTERFACE_DEVICE NM_DBUS_INTERFACE ".Device"
#define NM_DBUS_INTERFACE_DEVICE_WIRED NM_DBUS_INTERFACE_DEVICE ".Wired"
#define NM_DBUS_INTERFACE_DEVICE_WIRELESS NM_DBUS_INTERFACE_DEVICE ".Wireless"
#define NM_DBUS_INTERFACE_DEVICE_MODEM NM_DBUS_INTERFACE_DEVICE ".Modem"
#define NM_DBUS_PATH_ACCESS_POINT NM_DBUS_PATH "/AccessPoint"
#define NM_DBUS_INTERFACE_ACCESS_POINT NM_DBUS_INTERFACE ".AccessPoint"
#define NM_DBUS_PATH_SETTINGS "/org/freedesktop/NetworkManagerSettings"
#define NM_DBUS_PATH_SETTINGS "/org/freedesktop/NetworkManager/Settings"
#define NM_DBUS_IFACE_SETTINGS_CONNECTION "org.freedesktop.NetworkManagerSettings.Connection"
#define NM_DBUS_IFACE_SETTINGS "org.freedesktop.NetworkManagerSettings"
#define NM_DBUS_IFACE_SETTINGS_CONNECTION "org.freedesktop.NetworkManager.Settings.Connection"
#define NM_DBUS_IFACE_SETTINGS "org.freedesktop.NetworkManager.Settings"
#define NM_DBUS_INTERFACE_ACTIVE_CONNECTION NM_DBUS_INTERFACE ".Connection.Active"
#define NM_DBUS_INTERFACE_IP4_CONFIG NM_DBUS_INTERFACE ".IP4Config"
@ -256,7 +258,8 @@ public:
Q_SIGNALS:
void stateChanged(const QString &, quint32);
void propertiesChanged(const QString &, QMap<QString,QVariant>);
void connectionsChanged(QStringList);
private:
QNetworkManagerInterfaceDevicePrivate *d;
QNmDBusHelper *nmDBusHelper;
@ -320,15 +323,55 @@ public:
bool setConnections();
bool isValid();
void requestScan();
Q_SIGNALS:
void propertiesChanged( const QString &, QMap<QString,QVariant>);
void accessPointAdded(const QString &,QDBusObjectPath);
void accessPointRemoved(const QString &,QDBusObjectPath);
void accessPointAdded(const QString &);
void accessPointRemoved(const QString &);
void scanDone();
private Q_SLOTS:
void scanIsDone();
private:
QNetworkManagerInterfaceDeviceWirelessPrivate *d;
QNmDBusHelper *nmDBusHelper;
};
class QNetworkManagerInterfaceDeviceModemPrivate;
class QNetworkManagerInterfaceDeviceModem : public QObject
{
Q_OBJECT
public:
enum ModemCapability {
None = 0x0,
Pots = 0x1,
Cmda_Edvo = 0x2,
Gsm_Umts = 0x4,
Lte = 0x08
};
explicit QNetworkManagerInterfaceDeviceModem(const QString &ifaceDevicePath,
QObject *parent = 0);
~QNetworkManagerInterfaceDeviceModem();
QDBusObjectPath path() const;
QDBusInterface *connectionInterface() const;
bool setConnections();
bool isValid();
quint32 modemCapabilities() const;
quint32 currentCapabilities() const;
Q_SIGNALS:
void propertiesChanged( const QString &, QMap<QString,QVariant>);
private:
QNetworkManagerInterfaceDeviceModemPrivate *d;
QNmDBusHelper *nmDBusHelper;
};
class QNetworkManagerSettingsPrivate;
class QNetworkManagerSettings : public QObject
{
@ -341,6 +384,7 @@ public:
QDBusInterface *connectionInterface() const;
QList <QDBusObjectPath> listConnections();
QString getConnectionByUuid(const QString &uuid);
bool setConnections();
bool isValid();
@ -375,7 +419,7 @@ public:
Q_SIGNALS:
void updated(const QNmSettingsMap &settings);
void updated();
void removed(const QString &path);
private:

View File

@ -60,7 +60,7 @@ QNmDBusHelper::~QNmDBusHelper()
void QNmDBusHelper::deviceStateChanged(quint32 state)
{
QDBusMessage msg = this->message();
if(state == NM_DEVICE_STATE_ACTIVATED
if (state == NM_DEVICE_STATE_ACTIVATED
|| state == NM_DEVICE_STATE_DISCONNECTED
|| state == NM_DEVICE_STATE_UNAVAILABLE
|| state == NM_DEVICE_STATE_FAILED) {
@ -70,18 +70,14 @@ void QNmDBusHelper::deviceStateChanged(quint32 state)
void QNmDBusHelper::slotAccessPointAdded(QDBusObjectPath path)
{
if(path.path().length() > 2) {
QDBusMessage msg = this->message();
emit pathForAccessPointAdded(msg.path(), path);
}
if (path.path().length() > 2)
emit pathForAccessPointAdded(path.path());
}
void QNmDBusHelper::slotAccessPointRemoved(QDBusObjectPath path)
{
if(path.path().length() > 2) {
QDBusMessage msg = this->message();
emit pathForAccessPointRemoved(msg.path(), path);
}
if (path.path().length() > 2)
emit pathForAccessPointRemoved(path.path());
}
void QNmDBusHelper::slotPropertiesChanged(QMap<QString,QVariant> map)
@ -90,23 +86,29 @@ void QNmDBusHelper::slotPropertiesChanged(QMap<QString,QVariant> map)
QMapIterator<QString, QVariant> i(map);
while (i.hasNext()) {
i.next();
if( i.key() == "State") { //state only applies to device interfaces
if (i.key() == QStringLiteral("State")) {
quint32 state = i.value().toUInt();
if( state == NM_DEVICE_STATE_ACTIVATED
if (state == NM_DEVICE_STATE_ACTIVATED
|| state == NM_DEVICE_STATE_DISCONNECTED
|| state == NM_DEVICE_STATE_UNAVAILABLE
|| state == NM_DEVICE_STATE_FAILED) {
emit pathForPropertiesChanged( msg.path(), map);
emit pathForPropertiesChanged(msg.path(), map);
}
} else if( i.key() == "ActiveAccessPoint") {
} else if (i.key() == QStringLiteral("ActiveAccessPoint")) {
emit pathForPropertiesChanged(msg.path(), map);
// qWarning() << __PRETTY_FUNCTION__ << i.key() << ": " << i.value().value<QDBusObjectPath>().path();
// } else if( i.key() == "Strength")
// qWarning() << __PRETTY_FUNCTION__ << i.key() << ": " << i.value().toUInt();
// else
// qWarning() << __PRETTY_FUNCTION__ << i.key() << ": " << i.value();
} else if (i.key() == "ActiveConnections") {
} else if (i.key() == QStringLiteral("ActiveConnections")) {
emit pathForPropertiesChanged(msg.path(), map);
} else if (i.key() == QStringLiteral("AvailableConnections")) {
const QDBusArgument &dbusArgs = i.value().value<QDBusArgument>();
QDBusObjectPath path;
QStringList paths;
dbusArgs.beginArray();
while (!dbusArgs.atEnd()) {
dbusArgs >> path;
paths << path.path();
}
dbusArgs.endArray();
emit pathForConnectionsChanged(paths);
}
}
}
@ -117,6 +119,22 @@ void QNmDBusHelper::slotSettingsRemoved()
emit pathForSettingsRemoved(msg.path());
}
void QNmDBusHelper::activeConnectionPropertiesChanged(QMap<QString,QVariant> map)
{
QDBusMessage msg = this->message();
QMapIterator<QString, QVariant> i(map);
while (i.hasNext()) {
i.next();
if (i.key() == QStringLiteral("State")) {
quint32 state = i.value().toUInt();
if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED
|| state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
emit pathForPropertiesChanged(msg.path(), map);
}
}
}
}
QT_END_NAMESPACE
#endif // QT_NO_DBUS

View File

@ -51,17 +51,19 @@ class QNmDBusHelper: public QObject, protected QDBusContext
public slots:
void deviceStateChanged(quint32);
void slotAccessPointAdded( QDBusObjectPath );
void slotAccessPointRemoved( QDBusObjectPath );
void slotPropertiesChanged( QMap<QString,QVariant>);
void slotAccessPointAdded(QDBusObjectPath);
void slotAccessPointRemoved(QDBusObjectPath);
void slotPropertiesChanged(QMap<QString,QVariant>);
void slotSettingsRemoved();
void activeConnectionPropertiesChanged(QMap<QString,QVariant>);
Q_SIGNALS:
void pathForStateChanged(const QString &, quint32);
void pathForAccessPointAdded(const QString &, QDBusObjectPath );
void pathForAccessPointRemoved(const QString &, QDBusObjectPath );
void pathForAccessPointAdded(const QString &);
void pathForAccessPointRemoved(const QString &);
void pathForPropertiesChanged(const QString &, QMap<QString,QVariant>);
void pathForSettingsRemoved(const QString &);
void pathForConnectionsChanged(const QStringList &pathsList);
};
QT_END_NAMESPACE

View File

@ -70,6 +70,7 @@ namespace QCocoaAccessible {
*/
NSString *macRole(QAccessibleInterface *interface);
NSString *macSubrole(QAccessibleInterface *interface);
bool shouldBeIgnored(QAccessibleInterface *interface);
NSArray *unignoredChildren(QAccessibleInterface *interface);
NSString *getTranslatedAction(const QString &qtAction);

View File

@ -162,7 +162,7 @@ static void populateRoleMap()
}
/*
Returns a Mac accessibility role for the given interface, or
Returns a Cocoa accessibility role for the given interface, or
NSAccessibilityUnknownRole if no role mapping is found.
*/
NSString *macRole(QAccessibleInterface *interface)
@ -190,13 +190,24 @@ NSString *macRole(QAccessibleInterface *interface)
}
/*
Mac accessibility supports ignoring elements, which means that
Returns a Cocoa sub role for the given interface.
*/
NSString *macSubrole(QAccessibleInterface *interface)
{
QAccessible::State s = interface->state();
if (s.searchEdit)
return NSAccessibilitySearchFieldSubrole;
return nil;
}
/*
Cocoa accessibility supports ignoring elements, which means that
the elements are still present in the accessibility tree but is
not used by the screen reader.
*/
bool shouldBeIgnored(QAccessibleInterface *interface)
{
// Mac accessibility does not have an attribute that corresponds to the Invisible/Offscreen
// Cocoa accessibility does not have an attribute that corresponds to the Invisible/Offscreen
// state. Ignore interfaces with those flags set.
const QAccessible::State state = interface->state();
if (state.invisible ||

View File

@ -135,6 +135,7 @@
defaultAttributes = [[NSArray alloc] initWithObjects:
NSAccessibilityRoleAttribute,
NSAccessibilityRoleDescriptionAttribute,
NSAccessibilitySubroleAttribute,
NSAccessibilityChildrenAttribute,
NSAccessibilityFocusedAttribute,
NSAccessibilityParentAttribute,
@ -221,6 +222,8 @@
if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
return role;
} else if ([attribute isEqualToString:NSAccessibilitySubroleAttribute]) {
return QCocoaAccessible::macSubrole(iface);
} else if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
return NSAccessibilityRoleDescription(role, nil);
} else if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {

View File

@ -396,7 +396,7 @@ static void cleanupCocoaApplicationDelegate()
*/
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive, true /*forcePropagate*/);
return NO;
return YES;
}
- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate

View File

@ -132,7 +132,7 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o)
QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacInternalPasteboardMime::MIME_DND);
m_drag->mimeData()->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray("dummy"));
dragBoard.setMimeData(m_drag->mimeData());
dragBoard.setMimeData(m_drag->mimeData(), QMacPasteboard::LazyRequest);
NSPoint event_location = [m_lastEvent locationInWindow];
NSPoint local_point = [m_lastView convertPoint:event_location fromView:nil];

View File

@ -391,6 +391,9 @@ void QCocoaPrintDevice::loadDuplexModes() const
// If still no result, or not added in PPD, then add None
if (m_duplexModes.size() == 0 || !m_duplexModes.contains(QPrint::DuplexNone))
m_duplexModes.append(QPrint::DuplexNone);
// If have both modes, then can support DuplexAuto
if (m_duplexModes.contains(QPrint::DuplexLongSide) && m_duplexModes.contains(QPrint::DuplexShortSide))
m_duplexModes.append(QPrint::DuplexAuto);
m_haveDuplexModes = true;
}

View File

@ -187,6 +187,14 @@ void QCocoaSystemTrayIcon::cleanup()
m_sys = 0;
}
static bool heightCompareFunction (QSize a, QSize b) { return (a.height() < b.height()); }
static QList<QSize> sortByHeight(const QList<QSize> sizes)
{
QList<QSize> sorted = sizes;
std::sort(sorted.begin(), sorted.end(), heightCompareFunction);
return sorted;
}
void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
{
if (!m_sys)
@ -196,16 +204,62 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
const bool menuVisible = m_sys->item->menu && m_sys->item->menuVisible;
CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
const short scale = hgt - 4;
// The reccomended maximum title bar icon height is 18 points
// (device independent pixels). The menu height on past and
// current OS X versions is 22 points. Provide some future-proofing
// by deriving the icon height from the menu height.
const int padding = 4;
const int menuHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
const int maxImageHeight = menuHeight - padding;
QPixmap pm = m_sys->item->icon.pixmap(QSize(scale, scale),
menuVisible ? QIcon::Selected : QIcon::Normal);
if (pm.isNull()) {
pm = QPixmap(scale, scale);
pm.fill(Qt::transparent);
// Select pixmap based on the device pixel height. Ideally we would use
// the devicePixelRatio of the target screen, but that value is not
// known until draw time. Use qApp->devicePixelRatio, which returns the
// devicePixelRatio for the "best" screen on the system.
qreal devicePixelRatio = qApp->devicePixelRatio();
const int maxPixmapHeight = maxImageHeight * devicePixelRatio;
const QIcon::Mode mode = menuVisible ? QIcon::Selected : QIcon::Normal;
QSize selectedSize;
Q_FOREACH (const QSize& size, sortByHeight(icon.availableSizes(mode))) {
// Select a pixmap based on the height. We want the largest pixmap
// with a height smaller or equal to maxPixmapHeight. The pixmap
// may rectangular; assume it has a reasonable size. If there is
// not suitable pixmap use the smallest one the icon can provide.
if (size.height() <= maxPixmapHeight) {
selectedSize = size;
} else {
if (!selectedSize.isValid())
selectedSize = size;
break;
}
}
NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm));
QPixmap pixmap = icon.pixmap(selectedSize, mode);
// Draw a low-resolution icon if there is not enough pixels for a retina
// icon. This prevents showing a small icon on retina displays.
if (devicePixelRatio > 1.0 && selectedSize.height() < maxPixmapHeight / 2)
devicePixelRatio = 1.0;
// Scale large pixmaps to fit the available menu bar area.
if (pixmap.height() > maxPixmapHeight)
pixmap = pixmap.scaledToHeight(maxPixmapHeight, Qt::SmoothTransformation);
// The icon will be stretched over the full height of the menu bar
// therefore we create a second pixmap which has the full height
QSize fullHeightSize(!pixmap.isNull() ? pixmap.width():
menuHeight * devicePixelRatio,
menuHeight * devicePixelRatio);
QPixmap fullHeightPixmap(fullHeightSize);
fullHeightPixmap.fill(Qt::transparent);
if (!pixmap.isNull()) {
QPainter p(&fullHeightPixmap);
QRect r = pixmap.rect();
r.moveCenter(fullHeightPixmap.rect().center());
p.drawPixmap(r, pixmap);
}
NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(fullHeightPixmap));
[(NSImageView*)[[m_sys->item item] view] setImage: nsimage];
[nsimage release];
}
@ -327,18 +381,7 @@ QT_END_NAMESPACE
Q_UNUSED(notification);
down = NO;
CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
const short scale = hgt - 4;
QPixmap pm = parent->icon.pixmap(QSize(scale, scale), QIcon::Normal);
if (pm.isNull()) {
pm = QPixmap(scale, scale);
pm.fill(Qt::transparent);
}
NSImage *nsaltimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm));
[self setImage: nsaltimage];
[nsaltimage release];
parent->systray->updateIcon(parent->icon);
parent->menuVisible = false;
[self setNeedsDisplay:YES];
@ -350,18 +393,7 @@ QT_END_NAMESPACE
int clickCount = [mouseEvent clickCount];
[self setNeedsDisplay:YES];
CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
const short scale = hgt - 4;
QPixmap pm = parent->icon.pixmap(QSize(scale, scale),
parent->menuVisible ? QIcon::Selected : QIcon::Normal);
if (pm.isNull()) {
pm = QPixmap(scale, scale);
pm.fill(Qt::transparent);
}
NSImage *nsaltimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm));
[self setImage: nsaltimage];
[nsaltimage release];
parent->systray->updateIcon(parent->icon);
if (clickCount == 2) {
[self menuTrackingDone:nil];

View File

@ -699,7 +699,7 @@ void QCocoaWindow::setVisible(bool visible)
exposeWindow();
if (m_nsWindow) {
QWindowSystemInterface::flushWindowSystemEvents();
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
// setWindowState might have been called while the window was hidden and
// will not change the NSWindow state in that case. Sync up here:
@ -1009,9 +1009,12 @@ void QCocoaWindow::raise()
[parentNSWindow addChildWindow:m_nsWindow ordered:NSWindowAbove];
} else {
[m_nsWindow orderFront: m_nsWindow];
ProcessSerialNumber psn;
GetCurrentProcess(&psn);
SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly);
static bool raiseProcess = qt_mac_resolveOption(true, "QT_MAC_SET_RAISE_PROCESS");
if (raiseProcess) {
ProcessSerialNumber psn;
GetCurrentProcess(&psn);
SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly);
}
}
}
}

View File

@ -43,15 +43,25 @@
QT_BEGIN_NAMESPACE
class QMacMimeData;
class QMacPasteboard
{
public:
enum DataRequestType { EagerRequest, LazyRequest };
private:
struct Promise {
Promise() : itemId(0), convertor(0) { }
Promise(int itemId, QMacInternalPasteboardMime *c, QString m, QVariant d, int o=0) : itemId(itemId), offset(o), convertor(c), mime(m), data(d) { }
static Promise eagerPromise(int itemId, QMacInternalPasteboardMime *c, QString m, QMacMimeData *d, int o = 0);
static Promise lazyPromise(int itemId, QMacInternalPasteboardMime *c, QString m, QMacMimeData *d, int o = 0);
Promise(int itemId, QMacInternalPasteboardMime *c, QString m, QMacMimeData *md, int o, DataRequestType drt);
int itemId, offset;
QMacInternalPasteboardMime *convertor;
QString mime;
QVariant data;
QPointer<QMacMimeData> mimeData;
QVariant variantData;
DataRequestType dataRequestType;
};
QList<Promise> promises;
@ -72,7 +82,8 @@ public:
PasteboardRef pasteBoard() const;
QMimeData *mimeData() const;
void setMimeData(QMimeData *mime);
void setMimeData(QMimeData *mime, DataRequestType dataRequestType = EagerRequest);
QStringList formats() const;
bool hasFormat(const QString &format) const;

View File

@ -64,6 +64,26 @@ QT_BEGIN_NAMESPACE
QMacPasteboard code
*****************************************************************************/
class QMacMimeData : public QMimeData
{
public:
QVariant variantData(const QString &mime) { return retrieveData(mime, QVariant::Invalid); }
private:
QMacMimeData();
};
QMacPasteboard::Promise::Promise(int itemId, QMacInternalPasteboardMime *c, QString m, QMacMimeData *md, int o, DataRequestType drt)
: itemId(itemId), offset(o), convertor(c), mime(m), dataRequestType(drt)
{
// Request the data from the application immediately for eager requests.
if (dataRequestType == QMacPasteboard::EagerRequest) {
variantData = md->variantData(m);
mimeData = 0;
} else {
mimeData = md;
}
}
QMacPasteboard::QMacPasteboard(PasteboardRef p, uchar mt)
{
mac_mime_source = false;
@ -103,6 +123,11 @@ QMacPasteboard::~QMacPasteboard()
// commit all promises for paste after exit close
for (int i = 0; i < promises.count(); ++i) {
const Promise &promise = promises.at(i);
// At this point app teardown has started and control is somewhere in the Q[Core]Application
// destructor. Skip "lazy" promises where the application has not provided data;
// the application will generally not be in a state to provide it.
if (promise.dataRequestType == LazyRequest)
continue;
QCFString flavor = QCFString(promise.convertor->flavorFor(promise.mime));
NSInteger pbItemId = promise.itemId;
promiseKeeper(paste, reinterpret_cast<PasteboardItemID>(pbItemId), flavor, this);
@ -155,7 +180,17 @@ OSStatus QMacPasteboard::promiseKeeper(PasteboardRef paste, PasteboardItemID id,
qPrintable(flavorAsQString), qPrintable(promise.convertor->convertorName()), promise.offset);
#endif
QList<QByteArray> md = promise.convertor->convertFromMime(promise.mime, promise.data, flavorAsQString);
// Get the promise data. If this is a "lazy" promise call variantData()
// to request the data from the application.
QVariant promiseData;
if (promise.dataRequestType == LazyRequest) {
if (!promise.mimeData.isNull())
promiseData = promise.mimeData->variantData(promise.mime);
} else {
promiseData = promise.variantData;
}
QList<QByteArray> md = promise.convertor->convertFromMime(promise.mime, promiseData, flavorAsQString);
if (md.size() <= promise.offset)
return cantGetFlavorErr;
const QByteArray &ba = md[promise.offset];
@ -266,16 +301,8 @@ QMimeData
return mime;
}
class QMacMimeData : public QMimeData
{
public:
QVariant variantData(const QString &mime) { return retrieveData(mime, QVariant::Invalid); }
private:
QMacMimeData();
};
void
QMacPasteboard::setMimeData(QMimeData *mime_src)
QMacPasteboard::setMimeData(QMimeData *mime_src, DataRequestType dataRequestType)
{
if (!paste)
return;
@ -312,12 +339,17 @@ QMacPasteboard::setMimeData(QMimeData *mime_src)
continue;
QString flavor(c->flavorFor(mimeType));
if (!flavor.isEmpty()) {
QVariant mimeData = static_cast<QMacMimeData*>(mime_src)->variantData(mimeType);
QMacMimeData *mimeData = static_cast<QMacMimeData*>(mime_src);
int numItems = c->count(mime_src);
for (int item = 0; item < numItems; ++item) {
const NSInteger itemID = item+1; //id starts at 1
promises.append(QMacPasteboard::Promise(itemID, c, mimeType, mimeData, item));
//QMacPasteboard::Promise promise = (dataRequestType == QMacPasteboard::EagerRequest) ?
// QMacPasteboard::Promise::eagerPromise(itemID, c, mimeType, mimeData, item) :
// QMacPasteboard::Promise::lazyPromise(itemID, c, mimeType, mimeData, item);
QMacPasteboard::Promise promise(itemID, c, mimeType, mimeData, item, dataRequestType);
promises.append(promise);
PasteboardPutItemFlavor(paste, reinterpret_cast<PasteboardItemID>(itemID), QCFString(flavor), 0, kPasteboardFlavorNoFlags);
#ifdef DEBUG_PASTEBOARD
qDebug(" - adding %d %s [%s] <%s> [%d]",

View File

@ -361,8 +361,12 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
// Send a geometry change event to Qt, if it's ready to handle events
if (!m_platformWindow->m_inConstructor) {
QWindowSystemInterface::handleGeometryChange(m_window, geometry);
m_platformWindow->updateExposedGeometry();
QWindowSystemInterface::flushWindowSystemEvents();
// Do not send incorrect exposes in case the window is not even visible yet.
// We might get here as a result of a resize() from QWidget's show(), for instance.
if (m_platformWindow->window()->isVisible()) {
m_platformWindow->updateExposedGeometry();
QWindowSystemInterface::flushWindowSystemEvents();
}
}
}
@ -420,10 +424,12 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
#pragma clang diagnostic ignored "-Wobjc-method-access"
enum { NSWindowOcclusionStateVisible = 1UL << 1 };
#endif
// Older versions managed in -[QNSView viewDidMoveToWindow].
// Support QWidgetAction in NSMenu. Mavericks only sends this notification.
// Ideally we should support this in Qt as well, in order to disable animations
// when the window is occluded.
if ((NSUInteger)[self.window occlusionState] & NSWindowOcclusionStateVisible)
m_platformWindow->exposeWindow();
else
m_platformWindow->obscureWindow();
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9
#pragma clang diagnostic pop
#endif
@ -686,7 +692,23 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
m_platformWindow->m_forwardWindow = 0;
}
[targetView convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
NSPoint globalPos = [NSEvent mouseLocation];
if ([self.window parentWindow]
&& (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp)) {
// QToolBar can be implemented as a child window on top of its main window
// (with a borderless NSWindow). If an option "unified toolbar" set on the main window,
// it's possible to drag such a window using this toolbar.
// While handling mouse drag events, QToolBar moves the window (QWidget::move).
// In such a combination [NSEvent mouseLocation] is very different from the
// real event location and as a result a window will move chaotically.
NSPoint winPoint = [theEvent locationInWindow];
NSRect tmpRect = NSMakeRect(winPoint.x, winPoint.y, 1., 1.);
tmpRect = [[theEvent window] convertRectToScreen:tmpRect];
globalPos = tmpRect.origin;
}
[targetView convertFromScreen:globalPos toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
ulong timestamp = [theEvent timestamp] * 1000;
QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
@ -699,6 +721,10 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
- (void)handleFrameStrutMouseEvent:(NSEvent *)theEvent
{
// get m_buttons in sync
// Don't send frme strut events if we are in the middle of a mouse drag.
if (m_buttons != Qt::NoButton)
return;
NSEventType ty = [theEvent type];
switch (ty) {
case NSLeftMouseDown:
@ -710,6 +736,12 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
case NSRightMouseDown:
m_frameStrutButtons |= Qt::RightButton;
break;
case NSLeftMouseDragged:
m_frameStrutButtons |= Qt::LeftButton;
break;
case NSRightMouseDragged:
m_frameStrutButtons |= Qt::RightButton;
break;
case NSRightMouseUp:
m_frameStrutButtons &= ~Qt::RightButton;
break;
@ -1337,10 +1369,6 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
}
QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, currentWheelModifiers, ph);
if (momentumPhase == NSEventPhaseEnded || momentumPhase == NSEventPhaseCancelled || momentumPhase == NSEventPhaseNone) {
currentWheelModifiers = Qt::NoModifier;
}
} else
#endif
{
@ -1806,6 +1834,19 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
return NO;
}
- (BOOL)wantsPeriodicDraggingUpdates
{
// From the documentation:
//
// "If the destination returns NO, these messages are sent only when the mouse moves
// or a modifier flag changes. Otherwise the destination gets the default behavior,
// where it receives periodic dragging-updated messages even if nothing changes."
//
// We do not want these constant drag update events while mouse is stationary,
// since we do all animations (autoscroll) with timers.
return NO;
}
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
return [self handleDrag : sender];

View File

@ -457,9 +457,6 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va
break;
case PPK_CustomBase:
break;
case PPK_Duplex:
// TODO Add support using PMSetDuplex / PMGetDuplex
break;
case PPK_FontEmbedding:
break;
case PPK_PageOrder:
@ -503,6 +500,29 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va
case PPK_DocumentName:
PMPrintSettingsSetJobName(d->settings(), QCFString(value.toString()));
break;
case PPK_Duplex: {
QPrint::DuplexMode mode = QPrint::DuplexMode(value.toInt());
if (mode == property(PPK_Duplex).toInt() || !d->m_printDevice->supportedDuplexModes().contains(mode))
break;
switch (mode) {
case QPrinter::DuplexNone:
PMSetDuplex(d->settings(), kPMDuplexNone);
break;
case QPrinter::DuplexAuto:
PMSetDuplex(d->settings(), d->m_pageLayout.orientation() == QPageLayout::Landscape ? kPMDuplexTumble : kPMDuplexNoTumble);
break;
case QPrinter::DuplexLongSide:
PMSetDuplex(d->settings(), kPMDuplexNoTumble);
break;
case QPrinter::DuplexShortSide:
PMSetDuplex(d->settings(), kPMDuplexTumble);
break;
default:
// Don't change
break;
}
break;
}
case PPK_FullPage:
if (value.toBool())
d->m_pageLayout.setMode(QPageLayout::FullPageMode);
@ -602,10 +622,6 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const
case PPK_CustomBase:
// Special case, leave null
break;
case PPK_Duplex:
// TODO Add support using PMSetDuplex / PMGetDuplex
ret = QPrinter::DuplexNone;
break;
case PPK_FontEmbedding:
ret = false;
break;
@ -647,6 +663,23 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const
ret = QCFString::toQString(name);
break;
}
case PPK_Duplex: {
PMDuplexMode mode = kPMDuplexNone;
PMGetDuplex(d->settings(), &mode);
switch (mode) {
case kPMDuplexNoTumble:
ret = QPrinter::DuplexLongSide;
break;
case kPMDuplexTumble:
ret = QPrinter::DuplexShortSide;
break;
case kPMDuplexNone:
default:
ret = QPrinter::DuplexNone;
break;
}
break;
}
case PPK_FullPage:
ret = d->m_pageLayout.mode() == QPageLayout::FullPageMode;
break;

View File

@ -259,10 +259,16 @@ static void __attribute__((noinline, noreturn)) user_main_trampoline()
NSArray *arguments = [[NSProcessInfo processInfo] arguments];
int argc = arguments.count;
char **argv = new char*[argc];
for (int i = 0; i < argc; ++i) {
NSString *arg = [arguments objectAtIndex:i];
argv[i] = reinterpret_cast<char *>(malloc([arg lengthOfBytesUsingEncoding:[NSString defaultCStringEncoding]]));
strcpy(argv[i], [arg cStringUsingEncoding:[NSString defaultCStringEncoding]]);
NSStringEncoding cStringEncoding = [NSString defaultCStringEncoding];
unsigned int bufferSize = [arg lengthOfBytesUsingEncoding:cStringEncoding] + 1;
argv[i] = reinterpret_cast<char *>(malloc(bufferSize));
if (![arg getCString:argv[i] maxLength:bufferSize encoding:cStringEncoding])
qFatal("Could not convert argv[%d] to C string", i);
}
int exitCode = qtmn(argc, argv);

View File

@ -152,6 +152,9 @@
if (state.disabled)
traits |= UIAccessibilityTraitNotEnabled;
if (state.searchEdit)
traits |= UIAccessibilityTraitSearchField;
if (iface->role() == QAccessible::Button)
traits |= UIAccessibilityTraitButton;

View File

@ -48,6 +48,13 @@
#include <QtCore/QDebug>
#include <QtCore/QScopedArrayPointer>
static void initResources()
{
#if !defined (Q_OS_WINCE) && !defined (QT_NO_IMAGEFORMAT_PNG)
Q_INIT_RESOURCE(cursors);
#endif
}
QT_BEGIN_NAMESPACE
Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0);
@ -568,6 +575,11 @@ QWindowsWindowCursor QWindowsCursor::pixmapWindowCursor(const QCursor &c)
return it.value();
}
QWindowsCursor::QWindowsCursor()
{
initResources();
}
/*!
\brief Set a cursor on a window.

View File

@ -91,7 +91,7 @@ public:
CursorSuppressed // Cursor suppressed by touch interaction (Windows 8).
};
QWindowsCursor() {}
QWindowsCursor();
void changeCursor(QCursor * widgetCursor, QWindow * widget) Q_DECL_OVERRIDE;
QPoint pos() const Q_DECL_OVERRIDE;

View File

@ -1149,6 +1149,13 @@ void QWindowsWindow::updateTransientParent() const
#endif // !Q_OS_WINCE
}
static inline bool testShowWithoutActivating(const QWindow *window)
{
// QWidget-attribute Qt::WA_ShowWithoutActivating .
const QVariant showWithoutActivating = window->property("_q_showWithoutActivating");
return showWithoutActivating.isValid() && showWithoutActivating.toBool();
}
// partially from QWidgetPrivate::show_sys()
void QWindowsWindow::show_sys() const
{
@ -1180,7 +1187,7 @@ void QWindowsWindow::show_sys() const
} // Qt::WindowMaximized
} // !Qt::WindowMinimized
}
if (type == Qt::Popup || type == Qt::ToolTip || type == Qt::Tool)
if (type == Qt::Popup || type == Qt::ToolTip || type == Qt::Tool || testShowWithoutActivating(w))
sm = SW_SHOWNOACTIVATE;
if (w->windowState() & Qt::WindowMaximized)

View File

@ -910,6 +910,18 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
if (qtKey == baseQtKey || qtKey == 0)
continue;
// catch only more specific shortcuts, i.e. Ctrl+Shift+= also generates Ctrl++ and +,
// but Ctrl++ is more specific than +, so we should skip the last one
bool ambiguous = false;
foreach (int shortcut, result) {
if (int(shortcut & ~Qt::KeyboardModifierMask) == qtKey && (shortcut & mods) == mods) {
ambiguous = true;
break;
}
}
if (ambiguous)
continue;
result += (qtKey + mods);
}
}

View File

@ -85,6 +85,12 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v
// Get the named page size from the printer if supported
d->setPageSize(d->m_printDevice.supportedPageSize(value.toString()));
break;
case PPK_Duplex: {
QPrint::DuplexMode mode = QPrint::DuplexMode(value.toInt());
if (mode != d->duplex && d->m_printDevice.supportedDuplexModes().contains(mode))
d->duplex = mode;
break;
}
case PPK_PrinterName:
d->changePrinter(value.toString());
break;

View File

@ -387,6 +387,9 @@ void QPpdPrintDevice::loadDuplexModes() const
// If still no result, or not added in PPD, then add None
if (m_duplexModes.size() == 0 || !m_duplexModes.contains(QPrint::DuplexNone))
m_duplexModes.append(QPrint::DuplexNone);
// If have both modes, then can support DuplexAuto
if (m_duplexModes.contains(QPrint::DuplexLongSide) && m_duplexModes.contains(QPrint::DuplexShortSide))
m_duplexModes.append(QPrint::DuplexAuto);
m_haveDuplexModes = true;
}

View File

@ -271,7 +271,7 @@ QMarginsF QWindowsPrintDevice::printableMargins(const QPageSize &pageSize,
const qreal rightMargin = physicalWidth - leftMargin - printableWidth;
const qreal bottomMargin = physicalHeight - topMargin - printableHeight;
margins = QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin);
ReleaseDC(NULL, pDC);
DeleteDC(pDC);
}
return margins;
}
@ -280,11 +280,11 @@ void QWindowsPrintDevice::loadResolutions() const
{
DWORD resCount = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_ENUMRESOLUTIONS, NULL, NULL);
if (int(resCount) > 0) {
QScopedArrayPointer<LONG> resolutions(new LONG[resCount*sizeof(LONG)]);
QScopedArrayPointer<LONG> resolutions(new LONG[resCount*2]);
// Get the details and match the default paper size
if (DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_ENUMRESOLUTIONS, (LPWSTR)resolutions.data(), NULL) == resCount) {
for (int i = 0; i < int(resCount); ++i)
m_resolutions.append(resolutions[i]);
for (int i = 0; i < int(resCount * 2); i += 2)
m_resolutions.append(resolutions[i+1]);
}
}
m_haveResolutions = true;
@ -378,6 +378,7 @@ void QWindowsPrintDevice::loadDuplexModes() const
DWORD duplex = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_DUPLEX, NULL, NULL);
if (int(duplex) == 1) {
// TODO Assume if duplex flag supports both modes
m_duplexModes.append(QPrint::DuplexAuto);
m_duplexModes.append(QPrint::DuplexLongSide);
m_duplexModes.append(QPrint::DuplexShortSide);
}

View File

@ -734,10 +734,7 @@ void QWin32PrintEnginePrivate::strokePath_dev(const QPainterPath &path, const QC
else if (pen.joinStyle() == Qt::RoundJoin)
joinStyle = PS_JOIN_ROUND;
bool cosmetic = qt_pen_is_cosmetic(pen, q->state->renderHints());
HPEN pen = ExtCreatePen((cosmetic ? PS_COSMETIC : PS_GEOMETRIC)
| PS_SOLID | capStyle | joinStyle,
HPEN pen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | capStyle | joinStyle,
(penWidth == 0) ? 1 : penWidth, &brush, 0, 0);
HGDIOBJ old_pen = SelectObject(hdc, pen);
@ -1006,9 +1003,6 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
// The following keys are settings that are unsupported by the Windows PrintEngine
case PPK_CustomBase:
break;
case PPK_Duplex:
// TODO Add support using DEVMODE.dmDuplex
break;
case PPK_FontEmbedding:
break;
case PPK_PageOrder:
@ -1049,6 +1043,33 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
d->docName = value.toString();
break;
case PPK_Duplex: {
if (!d->devMode)
break;
QPrint::DuplexMode mode = QPrint::DuplexMode(value.toInt());
if (mode == property(PPK_Duplex).toInt() || !d->m_printDevice.supportedDuplexModes().contains(mode))
break;
switch (mode) {
case QPrinter::DuplexNone:
d->devMode->dmDuplex = DMDUP_SIMPLEX;
break;
case QPrinter::DuplexAuto:
d->devMode->dmDuplex = d->m_pageLayout.orientation() == QPageLayout::Landscape ? DMDUP_HORIZONTAL : DMDUP_VERTICAL;
break;
case QPrinter::DuplexLongSide:
d->devMode->dmDuplex = DMDUP_VERTICAL;
break;
case QPrinter::DuplexShortSide:
d->devMode->dmDuplex = DMDUP_HORIZONTAL;
break;
default:
// Don't change
break;
}
d->doReinit();
break;
}
case PPK_FullPage:
if (value.toBool())
d->m_pageLayout.setMode(QPageLayout::FullPageMode);
@ -1263,10 +1284,6 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const
// The following keys are settings that are unsupported by the Windows PrintEngine
// Return sensible default values to ensure consistent behavior across platforms
case PPK_Duplex:
// TODO Add support using DEVMODE.dmDuplex
value = QPrinter::DuplexNone;
break;
case PPK_FontEmbedding:
value = false;
break;
@ -1303,6 +1320,26 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const
value = d->docName;
break;
case PPK_Duplex: {
if (!d->devMode) {
value = QPrinter::DuplexNone;
} else {
switch (d->devMode->dmDuplex) {
case DMDUP_VERTICAL:
value = QPrinter::DuplexLongSide;
break;
case DMDUP_HORIZONTAL:
value = QPrinter::DuplexShortSide;
break;
case DMDUP_SIMPLEX:
default:
value = QPrinter::DuplexNone;
break;
}
}
break;
}
case PPK_FullPage:
value = d->m_pageLayout.mode() == QPageLayout::FullPageMode;
break;

View File

@ -1678,9 +1678,11 @@ bool QPrinter::fontEmbeddingEnabled() const
/*!
\since 4.2
\obsolete Use setDuplex() instead.
Enables double sided printing if \a doubleSided is true; otherwise disables it.
Currently this option is only supported on X11.
\sa setDuplex()
*/
void QPrinter::setDoubleSidedPrinting(bool doubleSided)
{
@ -1691,9 +1693,11 @@ void QPrinter::setDoubleSidedPrinting(bool doubleSided)
/*!
\since 4.2
\obsolete Use duplex() instead.
Returns \c true if double side printing is enabled.
Currently this option is only supported on X11.
\sa duplex()
*/
bool QPrinter::doubleSidedPrinting() const
{
@ -1705,7 +1709,7 @@ bool QPrinter::doubleSidedPrinting() const
Enables double sided printing based on the \a duplex mode.
Currently this option is only supported on X11.
\sa duplex()
*/
void QPrinter::setDuplex(DuplexMode duplex)
{
@ -1718,7 +1722,7 @@ void QPrinter::setDuplex(DuplexMode duplex)
Returns the current duplex mode.
Currently this option is only supported on X11.
\sa setDuplex()
*/
QPrinter::DuplexMode QPrinter::duplex() const
{

View File

@ -352,6 +352,33 @@ QList<int> QPrinterInfo::supportedResolutions() const
return d->m_printDevice.supportedResolutions();
}
/*!
Returns the default duplex mode of this printer.
\since 5.4
*/
QPrinter::DuplexMode QPrinterInfo::defaultDuplexMode() const
{
Q_D(const QPrinterInfo);
return QPrinter::DuplexMode(d->m_printDevice.defaultDuplexMode());
}
/*!
Returns a list of duplex modes supported by this printer.
\since 5.4
*/
QList<QPrinter::DuplexMode> QPrinterInfo::supportedDuplexModes() const
{
Q_D(const QPrinterInfo);
QList<QPrinter::DuplexMode> list;
foreach (QPrint::DuplexMode mode, d->m_printDevice.supportedDuplexModes())
list << QPrinter::DuplexMode(mode);
return list;
}
/*!
Returns a list of all the available Printer Names on this system.

View File

@ -82,6 +82,9 @@ public:
QList<int> supportedResolutions() const;
QPrinter::DuplexMode defaultDuplexMode() const;
QList<QPrinter::DuplexMode> supportedDuplexModes() const;
static QStringList availablePrinterNames();
static QList<QPrinterInfo> availablePrinters();

View File

@ -1503,15 +1503,18 @@ QSql::NumericalPrecisionPolicy QSqlDatabase::numericalPrecisionPolicy() const
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QSqlDatabase &d)
{
QDebugStateSaver saver(dbg);
dbg.nospace();
dbg.noquote();
if (!d.isValid()) {
dbg.nospace() << "QSqlDatabase(invalid)";
return dbg.space();
dbg << "QSqlDatabase(invalid)";
return dbg;
}
dbg.nospace() << "QSqlDatabase(driver=\"" << d.driverName() << "\", database=\""
<< d.databaseName() << "\", host=\"" << d.hostName() << "\", port=" << d.port()
<< ", user=\"" << d.userName() << "\", open=" << d.isOpen() << ")";
return dbg.space();
dbg << "QSqlDatabase(driver=\"" << d.driverName() << "\", database=\""
<< d.databaseName() << "\", host=\"" << d.hostName() << "\", port=" << d.port()
<< ", user=\"" << d.userName() << "\", open=" << d.isOpen() << ')';
return dbg;
}
#endif

View File

@ -39,9 +39,11 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QSqlError &s)
{
dbg.nospace() << "QSqlError(" << s.nativeErrorCode() << ", " << s.driverText() <<
", " << s.databaseText() << ')';
return dbg.space();
QDebugStateSaver saver(dbg);
dbg.nospace();
dbg << "QSqlError(" << s.nativeErrorCode() << ", " << s.driverText()
<< ", " << s.databaseText() << ')';
return dbg;
}
#endif

View File

@ -509,21 +509,24 @@ bool QSqlField::isValid() const
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QSqlField &f)
{
dbg.nospace() << "QSqlField(" << f.name() << ", " << QMetaType::typeName(f.type());
QDebugStateSaver saver(dbg);
dbg.nospace();
dbg << "QSqlField(" << f.name() << ", " << QMetaType::typeName(f.type());
if (f.length() >= 0)
dbg.nospace() << ", length: " << f.length();
dbg << ", length: " << f.length();
if (f.precision() >= 0)
dbg.nospace() << ", precision: " << f.precision();
dbg << ", precision: " << f.precision();
if (f.requiredStatus() != QSqlField::Unknown)
dbg.nospace() << ", required: "
<< (f.requiredStatus() == QSqlField::Required ? "yes" : "no");
dbg.nospace() << ", generated: " << (f.isGenerated() ? "yes" : "no");
dbg << ", required: "
<< (f.requiredStatus() == QSqlField::Required ? "yes" : "no");
dbg << ", generated: " << (f.isGenerated() ? "yes" : "no");
if (f.typeID() >= 0)
dbg.nospace() << ", typeID: " << f.typeID();
dbg << ", typeID: " << f.typeID();
if (!f.defaultValue().isNull())
dbg.nospace() << ", auto-value: \"" << f.defaultValue() << '\"';
dbg.nospace() << ')';
return dbg.space();
dbg << ", defaultValue: \"" << f.defaultValue() << '\"';
dbg << ", autoValue: " << f.isAutoValue()
<< ", readOnly: " << f.isReadOnly() << ')';
return dbg;
}
#endif

View File

@ -509,9 +509,16 @@ void QSqlRecord::detach()
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QSqlRecord &r)
{
dbg << "QSqlRecord(" << r.count() << ')';
for (int i = 0; i < r.count(); ++i)
dbg << '\n' << QString::fromLatin1("%1:").arg(i, 2) << r.field(i) << r.value(i).toString();
QDebugStateSaver saver(dbg);
dbg.nospace();
const int count = r.count();
dbg << "QSqlRecord(" << count << ')';
for (int i = 0; i < count; ++i) {
dbg.nospace();
dbg << '\n' << qSetFieldWidth(2) << right << i << left << qSetFieldWidth(0) << ':';
dbg.space();
dbg << r.field(i) << r.value(i).toString();
}
return dbg;
}
#endif

View File

@ -2367,6 +2367,7 @@ static LONG WINAPI windowsFaultHandler(struct _EXCEPTION_POINTERS *exInfo)
static void initEnvironment()
{
qputenv("QT_LOGGING_TO_CONSOLE", "1");
qputenv("QT_QTESTLIB_RUNNING", "1");
}
/*!

View File

@ -1057,6 +1057,12 @@ bool RCCResourceLibrary::writeInitializer()
QByteArray initResources = "qInitResources";
initResources += initName;
// Work around -Wmissing-declarations warnings.
writeString("int ");
writeMangleNamespaceFunction(initResources);
writeString("();\n");
writeString("int ");
writeMangleNamespaceFunction(initResources);
writeString("()\n{\n");
@ -1073,6 +1079,12 @@ bool RCCResourceLibrary::writeInitializer()
//cleanup
QByteArray cleanResources = "qCleanupResources";
cleanResources += initName;
// Work around -Wmissing-declarations warnings.
writeString("int ");
writeMangleNamespaceFunction(cleanResources);
writeString("();\n");
writeString("int ");
writeMangleNamespaceFunction(cleanResources);
writeString("()\n{\n");

View File

@ -322,6 +322,7 @@ void QFontDialogPrivate::init()
familyList->setFocus();
retranslateStrings();
sampleEdit->setObjectName(QLatin1String("qt_fontDialog_sampleEdit"));
}
/*!

View File

@ -653,10 +653,7 @@ HFONT QVistaHelper::getCaptionFont(HANDLE hTheme)
{
LOGFONT lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0 } };
if (!hTheme)
pGetThemeSysFont(hTheme, WIZ_TMT_CAPTIONFONT, &lf);
else
{
if (!hTheme || FAILED(pGetThemeSysFont(hTheme, WIZ_TMT_CAPTIONFONT, &lf))) {
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, false);

View File

@ -45,7 +45,7 @@
CustomStyle::CustomStyle()
{
//! [0]
QSpinBox *spinBox = qobject_cast<QSpinBox *>(widget);
const QSpinBox *spinBox = qobject_cast<const QSpinBox *>(widget);
if (spinBox) {
//! [0] //! [1]
}

View File

@ -49,7 +49,7 @@ class CustomStyle : public QProxyStyle
Q_OBJECT
public:
CustomStyle()
CustomStyle();
~CustomStyle() {}
void drawPrimitive(PrimitiveElement element, const QStyleOption *option,

View File

@ -1,2 +1,3 @@
QT += widgets
HEADERS += customstyle.h
SOURCES += customstyle.cpp main.cpp

View File

@ -39,7 +39,7 @@
****************************************************************************/
//! [using a custom style]
#include <QtGui>
#include <QtWidgets>
#include "customstyle.h"

View File

@ -38,7 +38,7 @@
**
****************************************************************************/
#include <QtGui>
#include <QtWidgets>
#include "customviewstyle.h"

View File

@ -38,9 +38,29 @@
#include "qgraphicslayoutitem_p.h"
#include "qgraphicslayout_p.h"
#include "qgraphicswidget.h"
#include <private/qgraphicswidget_p.h>
QT_BEGIN_NAMESPACE
bool QGraphicsGridLayoutEngineItem::isHidden() const
{
if (QGraphicsItem *item = q_layoutItem->graphicsItem())
return QGraphicsItemPrivate::get(item)->explicitlyHidden;
return false;
}
/*!
\internal
If this returns true, the layout will arrange just as if the item was never added to the layout.
(Note that this shouldn't lead to a "double spacing" where the item was hidden)
### Qt6: Move to QGraphicsLayoutItem and make virtual
*/
bool QGraphicsGridLayoutEngineItem::isIgnored() const
{
return isHidden() && !q_layoutItem->sizePolicy().retainSizeWhenHidden();
}
/*
returns \c true if the size policy returns \c true for either hasHeightForWidth()
or hasWidthForHeight()

View File

@ -82,6 +82,10 @@ public:
return q_layoutItem->effectiveSizeHint(which, constraint);
}
bool isHidden() const;
virtual bool isIgnored() const Q_DECL_OVERRIDE;
virtual void setGeometry(const QRectF &rect) Q_DECL_OVERRIDE
{
q_layoutItem->setGeometry(rect);

Some files were not shown because too many files have changed in this diff Show More