summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorJørgen Lind <jorgen.lind@nokia.com>2010-04-21 12:22:24 (GMT)
committerJørgen Lind <jorgen.lind@nokia.com>2010-04-21 12:22:24 (GMT)
commit51dca5f8afc3aa619a3bb62858db78a85cc3ecef (patch)
treedfc1fb65b6a8e5e429f1701992548f8a0425decb /tools
parent6f5ad5dcab8e6f702894c4fa5c016d9837375626 (diff)
parentc74dac2a0ef5d1b428c4da4e48fab05f9886233a (diff)
downloadQt-51dca5f8afc3aa619a3bb62858db78a85cc3ecef.zip
Qt-51dca5f8afc3aa619a3bb62858db78a85cc3ecef.tar.gz
Qt-51dca5f8afc3aa619a3bb62858db78a85cc3ecef.tar.bz2
Merge remote branch 'origin/4.7' into lighthouse
Conflicts: configure src/gui/kernel/qapplication.cpp src/gui/painting/qbackingstore.cpp src/opengl/qgl.cpp src/opengl/qgl_p.h src/plugins/plugins.pro tests/auto/declarative/qdeclarativedom/data/importlib/sublib/qmldir tools/tools.pro
Diffstat (limited to 'tools')
-rw-r--r--tools/assistant/lib/fulltextsearch/qclucene-config_p.h14
-rw-r--r--tools/assistant/lib/fulltextsearch/qclucene_global_p.h2
-rw-r--r--tools/assistant/lib/qhelpprojectdata.cpp28
-rw-r--r--tools/assistant/tools/assistant/assistant.pro2
-rw-r--r--tools/assistant/tools/assistant/bookmarkmanager.cpp5
-rw-r--r--tools/assistant/tools/assistant/helpviewer.cpp58
-rw-r--r--tools/assistant/tools/assistant/helpviewer.h4
-rw-r--r--tools/assistant/tools/assistant/helpviewer_qtb.cpp36
-rw-r--r--tools/assistant/tools/assistant/helpviewer_qtb.h3
-rw-r--r--tools/assistant/tools/assistant/helpviewer_qwv.cpp53
-rw-r--r--tools/assistant/tools/assistant/helpviewer_qwv.h2
-rw-r--r--tools/assistant/tools/assistant/mainwindow.cpp16
-rw-r--r--tools/configure/configureapp.cpp38
-rw-r--r--tools/configure/environment.cpp6
-rw-r--r--tools/designer/src/components/formeditor/formeditor.qrc1
-rw-r--r--tools/designer/src/components/formeditor/formwindowmanager.cpp4
-rw-r--r--tools/designer/src/components/formeditor/images/cleartext.pngbin0 -> 760 bytes
-rw-r--r--tools/designer/src/components/formeditor/qdesigner_resource.cpp61
-rw-r--r--tools/designer/src/components/formeditor/qdesigner_resource.h4
-rw-r--r--tools/designer/src/components/propertyeditor/brushpropertymanager.cpp18
-rw-r--r--tools/designer/src/components/propertyeditor/propertyeditor.cpp67
-rw-r--r--tools/designer/src/components/propertyeditor/propertyeditor.h5
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox.cpp5
-rw-r--r--tools/designer/src/designer/designer.pro6
-rw-r--r--tools/designer/src/designer/mainwindow.cpp20
-rw-r--r--tools/designer/src/designer/qdesigner_actions.cpp29
-rw-r--r--tools/designer/src/designer/qdesigner_actions.h4
-rw-r--r--tools/designer/src/designer/qdesigner_workbench.cpp1
-rw-r--r--tools/designer/src/lib/shared/filterwidget.cpp160
-rw-r--r--tools/designer/src/lib/shared/filterwidget_p.h52
-rw-r--r--tools/designer/src/lib/shared/qdesigner_propertysheet.cpp22
-rw-r--r--tools/designer/src/lib/shared/qtresourceview.cpp5
-rw-r--r--tools/linguist/linguist.pro4
-rw-r--r--tools/linguist/linguist/mainwindow.cpp46
-rw-r--r--tools/linguist/linguist/messagemodel.cpp2
-rw-r--r--tools/linguist/lupdate/cpp.cpp97
-rw-r--r--tools/linguist/lupdate/lupdate.pro2
-rw-r--r--tools/linguist/lupdate/main.cpp3
-rw-r--r--tools/linguist/shared/numerus.cpp65
-rw-r--r--tools/linguist/shared/po.cpp472
-rw-r--r--tools/linguist/shared/qm.cpp4
-rw-r--r--tools/linguist/shared/translator.cpp19
-rw-r--r--tools/linguist/shared/translator.h2
-rw-r--r--tools/linguist/shared/xliff.cpp2
-rw-r--r--tools/qdbus/qdbus.pro3
-rw-r--r--tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp5
-rw-r--r--tools/qdoc3/codemarker.cpp2
-rw-r--r--tools/qdoc3/codemarker.h24
-rw-r--r--tools/qdoc3/config.cpp7
-rw-r--r--tools/qdoc3/config.h4
-rw-r--r--tools/qdoc3/cppcodemarker.cpp76
-rw-r--r--tools/qdoc3/doc/examples/main.cpp2
-rw-r--r--tools/qdoc3/doc/qdoc-manual.qdoc106
-rw-r--r--tools/qdoc3/generator.cpp77
-rw-r--r--tools/qdoc3/generator.h4
-rw-r--r--tools/qdoc3/helpprojectwriter.cpp61
-rw-r--r--tools/qdoc3/htmlgenerator.cpp279
-rw-r--r--tools/qdoc3/htmlgenerator.h3
-rw-r--r--tools/qdoc3/location.cpp2
-rw-r--r--tools/qdoc3/node.cpp22
-rw-r--r--tools/qdoc3/node.h8
-rw-r--r--tools/qdoc3/qscodemarker.cpp18
-rw-r--r--tools/qdoc3/test/assistant.qdocconf3
-rw-r--r--tools/qdoc3/test/designer.qdocconf3
-rw-r--r--tools/qdoc3/test/jambi.qdocconf3
-rw-r--r--tools/qdoc3/test/linguist.qdocconf3
-rw-r--r--tools/qdoc3/test/qdeclarative.qdocconf3
-rw-r--r--tools/qdoc3/test/qmake.qdocconf3
-rw-r--r--tools/qdoc3/test/qt-build-docs.qdocconf35
-rw-r--r--tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf33
-rw-r--r--tools/qdoc3/test/qt-defines.qdocconf44
-rw-r--r--tools/qdoc3/test/qt-html-templates.qdocconf168
-rw-r--r--tools/qdoc3/test/qt-webxml.qdocconf3
-rw-r--r--tools/qdoc3/test/qt.qdocconf33
-rw-r--r--tools/qdoc3/test/qt_zh_CN.qdocconf33
-rw-r--r--tools/qdoc3/test/scripts/functions.js60
-rw-r--r--tools/qdoc3/test/scripts/jquery.js152
-rw-r--r--tools/qdoc3/test/style/style.css946
-rw-r--r--tools/qdoc3/test/style/style_ie6.css54
-rw-r--r--tools/qdoc3/test/style/style_ie7.css19
-rw-r--r--tools/qdoc3/test/style/style_ie8.css0
-rw-r--r--tools/qdoc3/tree.cpp78
-rw-r--r--tools/qml/Info_mac.plist16
-rw-r--r--tools/qml/content/Browser.qml62
-rw-r--r--tools/qml/deviceorientation.h1
-rw-r--r--tools/qml/deviceorientation_maemo.cpp13
-rw-r--r--tools/qml/main.cpp48
-rw-r--r--tools/qml/qdeclarativefolderlistmodel.cpp2
-rw-r--r--tools/qml/qdeclarativetester.cpp (renamed from tools/qml/qfxtester.cpp)45
-rw-r--r--tools/qml/qdeclarativetester.h (renamed from tools/qml/qfxtester.h)6
-rw-r--r--tools/qml/qml.pri29
-rw-r--r--tools/qml/qml.pro43
-rw-r--r--tools/qml/qmlruntime.cpp301
-rw-r--r--tools/qml/qmlruntime.h12
-rw-r--r--tools/qtestlib/wince/cetest/cetcpsyncconnection.cpp21
-rw-r--r--tools/qtestlib/wince/cetest/cetcpsyncconnection.h3
-rw-r--r--tools/qtestlib/wince/cetest/cetest.pro2
-rw-r--r--tools/qtestlib/wince/cetest/qmake_include.pri2
-rw-r--r--tools/qttracereplay/main.cpp99
-rw-r--r--tools/runonphone/main.cpp159
-rw-r--r--tools/runonphone/runonphone.pro3
-rw-r--r--tools/runonphone/serenum_stub.cpp2
-rw-r--r--tools/runonphone/serenum_unix.cpp71
-rw-r--r--tools/runonphone/symbianutils/launcher.cpp246
-rw-r--r--tools/runonphone/symbianutils/launcher.h23
-rw-r--r--tools/runonphone/symbianutils/symbiandevicemanager.cpp194
-rw-r--r--tools/runonphone/symbianutils/symbiandevicemanager.h47
-rw-r--r--tools/runonphone/symbianutils/trkdevice.cpp111
-rw-r--r--tools/runonphone/symbianutils/trkdevice.h11
-rw-r--r--tools/runonphone/symbianutils/trkutils.h53
-rw-r--r--tools/runonphone/trksignalhandler.cpp41
-rw-r--r--tools/shared/windows/registry.cpp2
-rw-r--r--tools/tools.pro48
113 files changed, 4340 insertions, 1204 deletions
diff --git a/tools/assistant/lib/fulltextsearch/qclucene-config_p.h b/tools/assistant/lib/fulltextsearch/qclucene-config_p.h
index 0c70718..387d64d 100644
--- a/tools/assistant/lib/fulltextsearch/qclucene-config_p.h
+++ b/tools/assistant/lib/fulltextsearch/qclucene-config_p.h
@@ -314,14 +314,12 @@ configure.
#define _CL_HAVE_SYS_TYPES_H 1
#endif
-// Do not use the tchar.h that ships with mingw, this causes the qt build to
-// fail (211547, 211401, etc...), reuse the replacement as with any other compiler
-// #if defined(__MINGW32__)
-// /* Define to 1 if you have the <tchar.h> header file. */
-// # ifndef _CL_HAVE_TCHAR_H
-// # define _CL_HAVE_TCHAR_H 1
-// # endif
-// #endif
+#if defined(__MINGW32__)
+ /* Define to 1 if you have the <tchar.h> header file. */
+ # ifndef _CL_HAVE_TCHAR_H
+ # define _CL_HAVE_TCHAR_H 1
+ # endif
+#endif
#if defined(__MINGW32__) || defined(__SUNPRO_CC) || defined(__SUNPRO_C)
/* Define to 1 if you have the `tell' function. */
diff --git a/tools/assistant/lib/fulltextsearch/qclucene_global_p.h b/tools/assistant/lib/fulltextsearch/qclucene_global_p.h
index f4b744d..206725b 100644
--- a/tools/assistant/lib/fulltextsearch/qclucene_global_p.h
+++ b/tools/assistant/lib/fulltextsearch/qclucene_global_p.h
@@ -36,7 +36,7 @@
#include <QtCore/QChar>
#include <QtCore/QString>
-#if !defined(_MSC_VER) && defined(_CL_HAVE_WCHAR_H) && defined(_CL_HAVE_WCHAR_T)
+#if !defined(_MSC_VER) && !defined(__MINGW32__) && defined(_CL_HAVE_WCHAR_H) && defined(_CL_HAVE_WCHAR_T)
# if !defined(TCHAR)
# define TCHAR wchar_t
# endif
diff --git a/tools/assistant/lib/qhelpprojectdata.cpp b/tools/assistant/lib/qhelpprojectdata.cpp
index 83491a0..b0faf0c 100644
--- a/tools/assistant/lib/qhelpprojectdata.cpp
+++ b/tools/assistant/lib/qhelpprojectdata.cpp
@@ -47,6 +47,7 @@
#include <QtCore/QStack>
#include <QtCore/QMap>
#include <QtCore/QRegExp>
+#include <QtCore/QUrl>
#include <QtCore/QVariant>
#include <QtXml/QXmlStreamReader>
@@ -77,6 +78,7 @@ private:
void readFiles();
void raiseUnknownTokenError();
void addMatchingFiles(const QString &pattern);
+ bool hasValidSyntax(const QString &nameSpace, const QString &vFolder) const;
QMap<QString, QStringList> dirEntriesCache;
};
@@ -115,16 +117,14 @@ void QHelpProjectDataPrivate::readProject()
if (isStartElement()) {
if (name() == QLatin1String("virtualFolder")) {
virtualFolder = readElementText();
- if (virtualFolder.contains(QLatin1String("/")))
+ if (!hasValidSyntax(QLatin1String("test"), virtualFolder))
raiseError(QCoreApplication::translate("QHelpProject",
- "A virtual folder must not contain "
- "a \'/\' character!"));
+ "Virtual folder has invalid syntax."));
} else if (name() == QLatin1String("namespace")) {
namespaceName = readElementText();
- if (namespaceName.contains(QLatin1String("/")))
+ if (!hasValidSyntax(namespaceName, QLatin1String("test")))
raiseError(QCoreApplication::translate("QHelpProject",
- "A namespace must not contain a "
- "\'/\' character!"));
+ "Namespace has invalid syntax."));
} else if (name() == QLatin1String("customFilter")) {
readCustomFilter();
} else if (name() == QLatin1String("filterSection")) {
@@ -318,6 +318,22 @@ void QHelpProjectDataPrivate::addMatchingFiles(const QString &pattern)
filterSectionList.last().addFile(pattern);
}
+bool QHelpProjectDataPrivate::hasValidSyntax(const QString &nameSpace,
+ const QString &vFolder) const
+{
+ const QLatin1Char slash('/');
+ if (nameSpace.contains(slash) || vFolder.contains(slash))
+ return false;
+ QUrl url;
+ const QLatin1String scheme("qthelp");
+ url.setScheme(scheme);
+ url.setHost(nameSpace);
+ url.setPath(vFolder);
+
+ const QString expectedUrl(scheme + QLatin1String("://") + nameSpace + slash + vFolder);
+ return url.isValid() && url.toString() == expectedUrl;
+}
+
/*!
\internal
\class QHelpProjectData
diff --git a/tools/assistant/tools/assistant/assistant.pro b/tools/assistant/tools/assistant/assistant.pro
index bc4d495..eb8cc51 100644
--- a/tools/assistant/tools/assistant/assistant.pro
+++ b/tools/assistant/tools/assistant/assistant.pro
@@ -15,7 +15,7 @@ DEPENDPATH += ../shared
# ## Work around a qmake issue when statically linking to
# ## not-yet-installed plugins
-LIBS += -L$$QT_BUILD_TREE/plugins/sqldrivers
+QMAKE_LIBDIR += $$QT_BUILD_TREE/plugins/sqldrivers
HEADERS += aboutdialog.h \
bookmarkdialog.h \
bookmarkfiltermodel.h \
diff --git a/tools/assistant/tools/assistant/bookmarkmanager.cpp b/tools/assistant/tools/assistant/bookmarkmanager.cpp
index b9a1b0e..4bc7027 100644
--- a/tools/assistant/tools/assistant/bookmarkmanager.cpp
+++ b/tools/assistant/tools/assistant/bookmarkmanager.cpp
@@ -363,8 +363,9 @@ void BookmarkManager::refeshBookmarkMenu()
bookmarkMenu->addAction(tr("Manage Bookmarks..."), this,
SLOT(manageBookmarks()));
- bookmarkMenu->addAction(tr("Add Bookmark..."), this, SLOT(addBookmark()),
- QKeySequence(tr("Ctrl+D")));
+ bookmarkMenu->addAction(QIcon::fromTheme("bookmark-new"),
+ tr("Add Bookmark..."), this, SLOT(addBookmark()),
+ QKeySequence(tr("Ctrl+D")));
bookmarkMenu->addSeparator();
const QModelIndex &root = bookmarkModel->index(0, 0, QModelIndex());
diff --git a/tools/assistant/tools/assistant/helpviewer.cpp b/tools/assistant/tools/assistant/helpviewer.cpp
index 9b06400..0c51a02 100644
--- a/tools/assistant/tools/assistant/helpviewer.cpp
+++ b/tools/assistant/tools/assistant/helpviewer.cpp
@@ -63,6 +63,45 @@ QString AbstractHelpViewer::PageNotFoundMessage =
"align=\"center\"><br><br><h1>The page could not be found</h1><br><h3>'%1'"
"</h3></div>");
+struct ExtensionMap {
+ const char *extension;
+ const char *mimeType;
+} extensionMap[] = {
+ { ".bmp", "image/bmp" },
+ { ".css", "text/css" },
+ { ".gif", "image/gif" },
+ { ".html", "text/html" },
+ { ".htm", "text/html" },
+ { ".ico", "image/x-icon" },
+ { ".jpeg", "image/jpeg" },
+ { ".jpg", "image/jpeg" },
+ { ".js", "application/x-javascript" },
+ { ".mng", "video/x-mng" },
+ { ".pbm", "image/x-portable-bitmap" },
+ { ".pgm", "image/x-portable-graymap" },
+ { ".pdf", "application/pdf" },
+ { ".png", "image/png" },
+ { ".ppm", "image/x-portable-pixmap" },
+ { ".rss", "application/rss+xml" },
+ { ".svg", "image/svg+xml" },
+ { ".svgz", "image/svg+xml" },
+ { ".text", "text/plain" },
+ { ".tif", "image/tiff" },
+ { ".tiff", "image/tiff" },
+ { ".txt", "text/plain" },
+ { ".xbm", "image/x-xbitmap" },
+ { ".xml", "text/xml" },
+ { ".xpm", "image/x-xpm" },
+ { ".xsl", "text/xsl" },
+ { ".xhtml", "application/xhtml+xml" },
+ { ".wml", "text/vnd.wap.wml" },
+ { ".wmlc", "application/vnd.wap.wmlc" },
+ { "about:blank", 0 },
+ { 0, 0 }
+};
+
+// -- AbstractHelpViewer
+
AbstractHelpViewer::AbstractHelpViewer()
{
}
@@ -86,9 +125,22 @@ bool AbstractHelpViewer::isLocalUrl(const QUrl &url)
bool AbstractHelpViewer::canOpenPage(const QString &url)
{
TRACE_OBJ
- return url.endsWith(QLatin1String(".html"), Qt::CaseInsensitive)
- || url.endsWith(QLatin1String(".htm"), Qt::CaseInsensitive)
- || url == QLatin1String("about:blank");
+ return !mimeFromUrl(url).isEmpty();
+}
+
+QString AbstractHelpViewer::mimeFromUrl(const QString &url)
+{
+ TRACE_OBJ
+ const int index = url.lastIndexOf(QLatin1Char('.'));
+ const QByteArray &ext = url.mid(index).toUtf8().toLower();
+
+ const ExtensionMap *e = extensionMap;
+ while (e->extension) {
+ if (ext == e->extension)
+ return QLatin1String(e->mimeType);
+ ++e;
+ }
+ return QLatin1String("");
}
bool AbstractHelpViewer::launchWithExternalApp(const QUrl &url)
diff --git a/tools/assistant/tools/assistant/helpviewer.h b/tools/assistant/tools/assistant/helpviewer.h
index 9e8f5f4..6f1f48d 100644
--- a/tools/assistant/tools/assistant/helpviewer.h
+++ b/tools/assistant/tools/assistant/helpviewer.h
@@ -47,6 +47,7 @@
QT_BEGIN_NAMESPACE
+class QMouseEvent;
class QUrl;
class AbstractHelpViewer
@@ -64,12 +65,15 @@ public:
virtual void resetScale() = 0;
virtual qreal scale() const = 0;
+ virtual bool handleForwardBackwardMouseButtons(QMouseEvent *e) = 0;
+
static QString AboutBlank;
static QString LocalHelpFile;
static QString PageNotFoundMessage;
static bool isLocalUrl(const QUrl &url);
static bool canOpenPage(const QString &url);
+ static QString mimeFromUrl(const QString &url);
static bool launchWithExternalApp(const QUrl &url);
};
diff --git a/tools/assistant/tools/assistant/helpviewer_qtb.cpp b/tools/assistant/tools/assistant/helpviewer_qtb.cpp
index 07b89eb..7f82b56 100644
--- a/tools/assistant/tools/assistant/helpviewer_qtb.cpp
+++ b/tools/assistant/tools/assistant/helpviewer_qtb.cpp
@@ -127,6 +127,20 @@ void HelpViewer::resetScale()
zoomCount = 0;
}
+bool HelpViewer::handleForwardBackwardMouseButtons(QMouseEvent *e)
+{
+ if (e->button() == Qt::XButton1) {
+ QTextBrowser::backward();
+ return true;
+ }
+
+ if (e->button() == Qt::XButton2) {
+ QTextBrowser::forward();
+ return true;
+ }
+ return false;
+}
+
void HelpViewer::setSource(const QUrl &url)
{
TRACE_OBJ
@@ -229,15 +243,10 @@ void HelpViewer::contextMenuEvent(QContextMenuEvent *e)
void HelpViewer::mouseReleaseEvent(QMouseEvent *e)
{
TRACE_OBJ
- if (e->button() == Qt::XButton1) {
- QTextBrowser::backward();
- return;
- }
-
- if (e->button() == Qt::XButton2) {
- QTextBrowser::forward();
+#ifndef Q_OS_LINUX
+ if (handleForwardBackwardMouseButtons(e))
return;
- }
+#endif
controlPressed = e->modifiers() & Qt::ControlModifier;
if ((controlPressed && hasAnchorAt(e->pos())) ||
@@ -249,6 +258,15 @@ void HelpViewer::mouseReleaseEvent(QMouseEvent *e)
QTextBrowser::mouseReleaseEvent(e);
}
+void HelpViewer::mousePressEvent(QMouseEvent *e)
+{
+#ifdef Q_OS_LINUX
+ if (handleForwardBackwardMouseButtons(e))
+ return;
+#endif
+ QTextBrowser::mousePressEvent(e);
+}
+
void HelpViewer::keyPressEvent(QKeyEvent *e)
{
TRACE_OBJ
@@ -285,3 +303,5 @@ bool HelpViewer::eventFilter(QObject *obj, QEvent *event)
return true;
return QTextBrowser::eventFilter(obj, event);
}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/helpviewer_qtb.h b/tools/assistant/tools/assistant/helpviewer_qtb.h
index a05782c..acb734b 100644
--- a/tools/assistant/tools/assistant/helpviewer_qtb.h
+++ b/tools/assistant/tools/assistant/helpviewer_qtb.h
@@ -72,6 +72,8 @@ public:
void resetScale();
qreal scale() const { return zoomCount; }
+ bool handleForwardBackwardMouseButtons(QMouseEvent *e);
+
void setSource(const QUrl &url);
inline bool hasSelection() const
@@ -91,6 +93,7 @@ private:
void contextMenuEvent(QContextMenuEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
void keyPressEvent(QKeyEvent *e);
+ void mousePressEvent(QMouseEvent *e);
private slots:
void openLinkInNewTab();
diff --git a/tools/assistant/tools/assistant/helpviewer_qwv.cpp b/tools/assistant/tools/assistant/helpviewer_qwv.cpp
index 582d013..db1cd58 100644
--- a/tools/assistant/tools/assistant/helpviewer_qwv.cpp
+++ b/tools/assistant/tools/assistant/helpviewer_qwv.cpp
@@ -129,26 +129,15 @@ QNetworkReply *HelpNetworkAccessManager::createRequest(Operation /*op*/,
const QNetworkRequest &request, QIODevice* /*outgoingData*/)
{
TRACE_OBJ
- const QUrl& url = request.url();
- QString mimeType = url.toString();
- if (mimeType.endsWith(QLatin1String(".svg"))
- || mimeType.endsWith(QLatin1String(".svgz"))) {
- mimeType = QLatin1String("image/svg+xml");
- } else if (mimeType.endsWith(QLatin1String(".css"))) {
- mimeType = QLatin1String("text/css");
- } else if (mimeType.endsWith(QLatin1String(".js"))) {
- mimeType = QLatin1String("text/javascript");
- } else if (mimeType.endsWith(QLatin1String(".txt"))) {
- mimeType = QLatin1String("text/plain");
- } else {
- mimeType = QLatin1String("text/html");
- }
-
+ const QUrl &url = request.url();
+ const QString &mimeType = AbstractHelpViewer::mimeFromUrl(url.toString());
+
HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
const QByteArray &data = helpEngine.findFile(url).isValid()
? helpEngine.fileData(url)
: AbstractHelpViewer::PageNotFoundMessage.arg(url.toString()).toUtf8();
- return new HelpNetworkReply(request, data, mimeType);
+ return new HelpNetworkReply(request, data, mimeType.isEmpty()
+ ? QLatin1String("application/octet-stream") : mimeType);
}
class HelpPage : public QWebPage
@@ -312,6 +301,22 @@ void HelpViewer::resetScale()
setTextSizeMultiplier(1.0);
}
+bool HelpViewer::handleForwardBackwardMouseButtons(QMouseEvent *e)
+{
+ TRACE_OBJ
+ if (e->button() == Qt::XButton1) {
+ triggerPageAction(QWebPage::Back);
+ return true;
+ }
+
+ if (e->button() == Qt::XButton2) {
+ triggerPageAction(QWebPage::Forward);
+ return true;
+ }
+
+ return false;
+}
+
void HelpViewer::setSource(const QUrl &url)
{
TRACE_OBJ
@@ -339,15 +344,10 @@ void HelpViewer::wheelEvent(QWheelEvent *e)
void HelpViewer::mouseReleaseEvent(QMouseEvent *e)
{
TRACE_OBJ
- if (e->button() == Qt::XButton1) {
- triggerPageAction(QWebPage::Back);
+#ifndef Q_OS_LINUX
+ if (handleForwardBackwardMouseButtons(e))
return;
- }
-
- if (e->button() == Qt::XButton2) {
- triggerPageAction(QWebPage::Forward);
- return;
- }
+#endif
QWebView::mouseReleaseEvent(e);
}
@@ -367,6 +367,11 @@ void HelpViewer::actionChanged()
void HelpViewer::mousePressEvent(QMouseEvent *event)
{
TRACE_OBJ
+#ifdef Q_OS_LINUX
+ if (handleForwardBackwardMouseButtons(event))
+ return;
+#endif
+
HelpPage *currentPage = static_cast<HelpPage*>(page());
if (currentPage) {
currentPage->m_pressedButtons = event->buttons();
diff --git a/tools/assistant/tools/assistant/helpviewer_qwv.h b/tools/assistant/tools/assistant/helpviewer_qwv.h
index 41ee553..a2c0389 100644
--- a/tools/assistant/tools/assistant/helpviewer_qwv.h
+++ b/tools/assistant/tools/assistant/helpviewer_qwv.h
@@ -69,6 +69,8 @@ public:
void resetScale();
qreal scale() const { return textSizeMultiplier(); }
+ bool handleForwardBackwardMouseButtons(QMouseEvent *e);
+
void setSource(const QUrl &url);
inline QUrl source() const { return url(); }
diff --git a/tools/assistant/tools/assistant/mainwindow.cpp b/tools/assistant/tools/assistant/mainwindow.cpp
index c403aa7..913e342 100644
--- a/tools/assistant/tools/assistant/mainwindow.cpp
+++ b/tools/assistant/tools/assistant/mainwindow.cpp
@@ -409,6 +409,11 @@ void MainWindow::setupActions()
QMenu *menu = menuBar()->addMenu(tr("&File"));
+ m_newTabAction = menu->addAction(tr("New &Tab"), m_centralWidget, SLOT(newTab()));
+ m_newTabAction->setShortcut(QKeySequence::AddTab);
+
+ menu->addSeparator();
+
m_pageSetupAction = menu->addAction(tr("Page Set&up..."), m_centralWidget,
SLOT(pageSetup()));
m_printPreviewAction = menu->addAction(tr("Print Preview..."), m_centralWidget,
@@ -421,14 +426,12 @@ void MainWindow::setupActions()
menu->addSeparator();
- m_newTabAction = menu->addAction(tr("New &Tab"), m_centralWidget, SLOT(newTab()));
- m_newTabAction->setShortcut(QKeySequence::AddTab);
-
m_closeTabAction = menu->addAction(tr("&Close Tab"), m_centralWidget,
SLOT(closeTab()));
m_closeTabAction->setShortcuts(QKeySequence::Close);
- QAction *tmp = menu->addAction(tr("&Quit"), this, SLOT(close()));
+ QAction *tmp = menu->addAction(QIcon::fromTheme("application-exit"),
+ tr("&Quit"), this, SLOT(close()));
tmp->setMenuRole(QAction::QuitRole);
#ifdef Q_OS_WIN
tmp->setShortcut(QKeySequence(tr("CTRL+Q")));
@@ -532,6 +535,8 @@ void MainWindow::setupActions()
m_aboutAction->setMenuRole(QAction::AboutRole);
#ifdef Q_WS_X11
+ m_newTabAction->setIcon(QIcon::fromTheme("tab-new", m_newTabAction->icon()));
+ m_closeTabAction->setIcon(QIcon::fromTheme("window-close", m_closeTabAction->icon()));
m_backAction->setIcon(QIcon::fromTheme("go-previous" , m_backAction->icon()));
m_nextAction->setIcon(QIcon::fromTheme("go-next" , m_nextAction->icon()));
m_zoomInAction->setIcon(QIcon::fromTheme("zoom-in" , m_zoomInAction->icon()));
@@ -541,7 +546,10 @@ void MainWindow::setupActions()
m_copyAction->setIcon(QIcon::fromTheme("edit-copy" , m_copyAction->icon()));
m_findAction->setIcon(QIcon::fromTheme("edit-find" , m_findAction->icon()));
m_homeAction->setIcon(QIcon::fromTheme("go-home" , m_homeAction->icon()));
+ m_pageSetupAction->setIcon(QIcon::fromTheme("document-page-setup", m_pageSetupAction->icon()));
+ m_printPreviewAction->setIcon(QIcon::fromTheme("document-print-preview", m_printPreviewAction->icon()));
m_printAction->setIcon(QIcon::fromTheme("document-print" , m_printAction->icon()));
+ m_aboutAction->setIcon(QIcon::fromTheme("help-about", m_aboutAction->icon()));
#endif
QToolBar *navigationBar = addToolBar(tr("Navigation Toolbar"));
diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
index 8a47991..687f8a1 100644
--- a/tools/configure/configureapp.cpp
+++ b/tools/configure/configureapp.cpp
@@ -973,6 +973,10 @@ void Configure::parseCmdLine()
if(i==argCount)
break;
dictionary[ "QT_LIBINFIX" ] = configCmdLine.at(i);
+ if (dictionary.contains("XQMAKESPEC") && dictionary["XQMAKESPEC"].startsWith("symbian")) {
+ dictionary[ "QT_INSTALL_PLUGINS" ] =
+ QString("\\resource\\qt%1\\plugins").arg(dictionary[ "QT_LIBINFIX" ]);
+ }
} else if( configCmdLine.at(i) == "-D" ) {
++i;
if (i==argCount)
@@ -1523,7 +1527,6 @@ void Configure::applySpecSpecifics()
dictionary[ "QT_ICONV" ] = "no";
dictionary["DECORATIONS"] = "default windows styled";
- dictionary[ "QMAKEADDITIONALARGS" ] = "-unix";
}
}
@@ -1882,7 +1885,7 @@ bool Configure::findFile( const QString &fileName )
const QString file = fileName.toLower();
const QString pathEnvVar = QString::fromLocal8Bit(getenv("PATH"));
const QString mingwPath = dictionary["QMAKESPEC"].endsWith("-g++") ?
- findFileInPaths("mingw32-g++.exe", pathEnvVar) : QString();
+ findFileInPaths("g++.exe", pathEnvVar) : QString();
QString paths;
if (file.endsWith(".h")) {
@@ -1974,7 +1977,7 @@ bool Configure::checkAvailability(const QString &part)
{
bool available = false;
if (part == "STYLE_WINDOWSXP")
- available = (findFile("uxtheme.h"));
+ available = findFile("uxtheme.h");
else if (part == "ZLIB")
available = findFile("zlib.h");
@@ -3037,6 +3040,10 @@ void Configure::generateConfigfiles()
if(dictionary["S60"] == "no") qconfigList += "QT_NO_S60";
if(dictionary["NATIVE_GESTURES"] == "no") qconfigList += "QT_NO_NATIVE_GESTURES";
+ if(dictionary["OPENGL_ES_CM"] == "no" &&
+ dictionary["OPENGL_ES_2"] == "no" &&
+ dictionary["OPENVG"] == "no") qconfigList += "QT_NO_EGL";
+
if(dictionary["OPENGL_ES_CM"] == "yes" ||
dictionary["OPENGL_ES_2"] == "yes") qconfigList += "QT_OPENGL_ES";
@@ -3063,6 +3070,8 @@ void Configure::generateConfigfiles()
qconfigList += "QT_NO_CRASHHANDLER";
qconfigList += "QT_NO_PRINTER";
qconfigList += "QT_NO_SYSTEMTRAYICON";
+ if (dictionary.contains("QT_LIBINFIX"))
+ tmpStream << QString("#define QT_LIBINFIX \"%1\"").arg(dictionary["QT_LIBINFIX"]) << endl;
}
qconfigList.sort();
@@ -3502,14 +3511,15 @@ void Configure::buildQmake()
args += makefile;
cout << "Creating qmake..." << endl;
- int exitCode = 0;
- if( exitCode = Environment::execute(args, QStringList(), QStringList()) ) {
+ int exitCode = Environment::execute(args, QStringList(), QStringList());
+ if( exitCode ) {
args.clear();
args += dictionary[ "MAKE" ];
args += "-f";
args += makefile;
args += "clean";
- if( exitCode = Environment::execute(args, QStringList(), QStringList())) {
+ exitCode = Environment::execute(args, QStringList(), QStringList());
+ if(exitCode) {
cout << "Cleaning qmake failed, return code " << exitCode << endl << endl;
dictionary[ "DONE" ] = "error";
} else {
@@ -3517,7 +3527,8 @@ void Configure::buildQmake()
args += dictionary[ "MAKE" ];
args += "-f";
args += makefile;
- if (exitCode = Environment::execute(args, QStringList(), QStringList())) {
+ exitCode = Environment::execute(args, QStringList(), QStringList());
+ if (exitCode) {
cout << "Building qmake failed, return code " << exitCode << endl << endl;
dictionary[ "DONE" ] = "error";
}
@@ -3561,8 +3572,8 @@ void Configure::buildHostTools()
QDir().mkpath(toolBuildPath);
QDir::setCurrent(toolSourcePath);
- int exitCode = 0;
- if (exitCode = Environment::execute(args, QStringList(), QStringList())) {
+ int exitCode = Environment::execute(args, QStringList(), QStringList());
+ if (exitCode) {
cout << "qmake failed, return code " << exitCode << endl << endl;
dictionary["DONE"] = "error";
break;
@@ -3572,18 +3583,21 @@ void Configure::buildHostTools()
args.clear();
args += dictionary["MAKE"];
QDir::setCurrent(toolBuildPath);
- if (exitCode = Environment::execute(args, QStringList(), QStringList())) {
+ exitCode = Environment::execute(args, QStringList(), QStringList());
+ if (exitCode) {
args.clear();
args += dictionary["MAKE"];
args += "clean";
- if(exitCode = Environment::execute(args, QStringList(), QStringList())) {
+ exitCode = Environment::execute(args, QStringList(), QStringList());
+ if(exitCode) {
cout << "Cleaning " << hostToolsDirs.at(i) << " failed, return code " << exitCode << endl << endl;
dictionary["DONE"] = "error";
break;
} else {
args.clear();
args += dictionary["MAKE"];
- if (exitCode = Environment::execute(args, QStringList(), QStringList())) {
+ exitCode = Environment::execute(args, QStringList(), QStringList());
+ if (exitCode) {
cout << "Building " << hostToolsDirs.at(i) << " failed, return code " << exitCode << endl << endl;
dictionary["DONE"] = "error";
break;
diff --git a/tools/configure/environment.cpp b/tools/configure/environment.cpp
index e93f9a0..60b8dcc 100644
--- a/tools/configure/environment.cpp
+++ b/tools/configure/environment.cpp
@@ -73,7 +73,7 @@ struct CompilerInfo{
} compiler_info[] = {
// The compilers here are sorted in a reversed-preferred order
{CC_BORLAND, "Borland C++", 0, "bcc32.exe"},
- {CC_MINGW, "MinGW (Minimalist GNU for Windows)", 0, "mingw32-gcc.exe"},
+ {CC_MINGW, "MinGW (Minimalist GNU for Windows)", 0, "g++.exe"},
{CC_INTEL, "Intel(R) C++ Compiler for 32-bit applications", 0, "icl.exe"}, // xilink.exe, xilink5.exe, xilink6.exe, xilib.exe
{CC_MSVC6, "Microsoft (R) 32-bit C/C++ Optimizing Compiler (6.x)", "Software\\Microsoft\\VisualStudio\\6.0\\Setup\\Microsoft Visual C++\\ProductDir", "cl.exe"}, // link.exe, lib.exe
{CC_NET2002, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2002 (7.0)", "Software\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir", "cl.exe"}, // link.exe, lib.exe
@@ -357,7 +357,7 @@ int Environment::execute(QStringList arguments, const QStringList &additionalEnv
QString args = qt_create_commandline(program, arguments);
QByteArray envlist = qt_create_environment(fullEnv);
- DWORD exitCode = -1;
+ DWORD exitCode = DWORD(-1);
PROCESS_INFORMATION procInfo;
memset(&procInfo, 0, sizeof(procInfo));
@@ -378,7 +378,7 @@ int Environment::execute(QStringList arguments, const QStringList &additionalEnv
}
- if (exitCode == -1) {
+ if (exitCode == DWORD(-1)) {
switch(GetLastError()) {
case E2BIG:
cerr << "execute: Argument list exceeds 1024 bytes" << endl;
diff --git a/tools/designer/src/components/formeditor/formeditor.qrc b/tools/designer/src/components/formeditor/formeditor.qrc
index 83cc9c7..6510814 100644
--- a/tools/designer/src/components/formeditor/formeditor.qrc
+++ b/tools/designer/src/components/formeditor/formeditor.qrc
@@ -63,6 +63,7 @@
<file>images/qtlogo.png</file>
<file>images/qt3logo.png</file>
<file>images/resetproperty.png</file>
+ <file>images/cleartext.png</file>
<file>images/sort.png</file>
<file>images/edit.png</file>
<file>images/reload.png</file>
diff --git a/tools/designer/src/components/formeditor/formwindowmanager.cpp b/tools/designer/src/components/formeditor/formwindowmanager.cpp
index 88b4ac5..ce809ff 100644
--- a/tools/designer/src/components/formeditor/formwindowmanager.cpp
+++ b/tools/designer/src/components/formeditor/formwindowmanager.cpp
@@ -523,10 +523,11 @@ void FormWindowManager::setupActions()
connect(m_actionShowFormWindowSettingsDialog, SIGNAL(triggered()), this, SLOT(slotActionShowFormWindowSettingsDialog()));
m_actionShowFormWindowSettingsDialog->setEnabled(false);
-
+#ifdef Q_WS_X11
m_actionCopy->setIcon(QIcon::fromTheme("edit-copy", m_actionCopy->icon()));
m_actionCut->setIcon(QIcon::fromTheme("edit-cut", m_actionCut->icon()));
m_actionPaste->setIcon(QIcon::fromTheme("edit-paste", m_actionPaste->icon()));
+ m_actionDelete->setIcon(QIcon::fromTheme("edit-delete", m_actionDelete->icon()));
// These do not currently exist, but will allow theme authors to fill in the gaps
m_actionBreakLayout->setIcon(QIcon::fromTheme("designer-break-layout", m_actionBreakLayout->icon()));
@@ -536,6 +537,7 @@ void FormWindowManager::setupActions()
m_actionSplitHorizontal->setIcon(QIcon::fromTheme("designer-split-horizontal", m_actionSplitHorizontal->icon()));
m_actionSplitVertical->setIcon(QIcon::fromTheme("designer-split-vertical", m_actionSplitVertical->icon()));
m_actionAdjustSize->setIcon(QIcon::fromTheme("designer-adjust-size", m_actionAdjustSize->icon()));
+#endif
}
void FormWindowManager::slotActionCutActivated()
diff --git a/tools/designer/src/components/formeditor/images/cleartext.png b/tools/designer/src/components/formeditor/images/cleartext.png
new file mode 100644
index 0000000..74133ba
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cleartext.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/qdesigner_resource.cpp b/tools/designer/src/components/formeditor/qdesigner_resource.cpp
index b659179..1d78695 100644
--- a/tools/designer/src/components/formeditor/qdesigner_resource.cpp
+++ b/tools/designer/src/components/formeditor/qdesigner_resource.cpp
@@ -53,7 +53,6 @@
#include "qtresourcemodel_p.h"
#include "qmdiarea_container.h"
#include "qwizard_container.h"
-#include "itemview_propertysheet.h"
#include "layout_propertysheet.h"
#include <ui4_p.h>
@@ -106,8 +105,6 @@
#include <QtGui/QMenuBar>
#include <QtGui/QFileDialog>
#include <QtGui/QHeaderView>
-#include <QtGui/QTreeView>
-#include <QtGui/QTableView>
#include <QtGui/QWizardPage>
#include <private/qlayoutengine_p.h>
@@ -1275,10 +1272,6 @@ DomWidget *QDesignerResource::createDom(QWidget *widget, DomWidget *ui_parentWid
w = saveWidget(dockWidget, ui_parentWidget);
else if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), widget))
w = saveWidget(widget, container, ui_parentWidget);
- else if (QTreeView *treeView = qobject_cast<QTreeView*>(widget))
- w = saveWidget(treeView, ui_parentWidget);
- else if (QTableView *tableView = qobject_cast<QTableView*>(widget))
- w = saveWidget(tableView, ui_parentWidget);
else if (QWizardPage *wizardPage = qobject_cast<QWizardPage*>(widget))
w = saveWidget(wizardPage, ui_parentWidget);
else
@@ -1553,60 +1546,6 @@ DomWidget *QDesignerResource::saveWidget(QDesignerDockWidget *dockWidget, DomWid
return ui_widget;
}
-DomWidget *QDesignerResource::saveWidget(QTreeView *treeView, DomWidget *ui_parentWidget)
-{
- DomWidget *ui_widget = QAbstractFormBuilder::createDom(treeView, ui_parentWidget, true);
-
- QDesignerPropertySheetExtension *sheet
- = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), treeView);
- ItemViewPropertySheet *itemViewSheet = static_cast<ItemViewPropertySheet*>(sheet);
-
- if (itemViewSheet) {
- QHash<QString,QString> nameMap = itemViewSheet->propertyNameMap();
- foreach (const QString &fakeName, nameMap.keys()) {
- int index = itemViewSheet->indexOf(fakeName);
- if (sheet->isChanged(index)) {
- DomProperty *domAttr = createProperty(treeView->header(), nameMap.value(fakeName),
- itemViewSheet->property(index));
- domAttr->setAttributeName(fakeName);
- ui_widget->setElementAttribute(ui_widget->elementAttribute() << domAttr);
- }
- }
- }
-
- return ui_widget;
-}
-
-DomWidget *QDesignerResource::saveWidget(QTableView *tableView, DomWidget *ui_parentWidget)
-{
- DomWidget *ui_widget = QAbstractFormBuilder::createDom(tableView, ui_parentWidget, true);
-
- QDesignerPropertySheetExtension *sheet
- = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), tableView);
- ItemViewPropertySheet *itemViewSheet = static_cast<ItemViewPropertySheet*>(sheet);
-
- if (itemViewSheet) {
- QHash<QString,QString> nameMap = itemViewSheet->propertyNameMap();
- foreach (const QString &fakeName, nameMap.keys()) {
- int index = itemViewSheet->indexOf(fakeName);
- if (sheet->isChanged(index)) {
- DomProperty *domAttr;
- if (fakeName.startsWith(QLatin1String("horizontal"))) {
- domAttr = createProperty(tableView->horizontalHeader(), nameMap.value(fakeName),
- itemViewSheet->property(index));
- } else {
- domAttr = createProperty(tableView->verticalHeader(), nameMap.value(fakeName),
- itemViewSheet->property(index));
- }
- domAttr->setAttributeName(fakeName);
- ui_widget->setElementAttribute(ui_widget->elementAttribute() << domAttr);
- }
- }
- }
-
- return ui_widget;
-}
-
static void saveStringProperty(DomProperty *property, const PropertySheetStringValue &value)
{
DomString *str = new DomString();
diff --git a/tools/designer/src/components/formeditor/qdesigner_resource.h b/tools/designer/src/components/formeditor/qdesigner_resource.h
index 33b5b88..47dd263 100644
--- a/tools/designer/src/components/formeditor/qdesigner_resource.h
+++ b/tools/designer/src/components/formeditor/qdesigner_resource.h
@@ -64,8 +64,6 @@ class QTabWidget;
class QStackedWidget;
class QToolBox;
class QToolBar;
-class QTreeView;
-class QTableView;
class QDesignerDockWidget;
class QLayoutWidget;
class QWizardPage;
@@ -138,8 +136,6 @@ protected:
DomWidget *saveWidget(QWidget *widget, QDesignerContainerExtension *container, DomWidget *ui_parentWidget);
DomWidget *saveWidget(QToolBar *toolBar, DomWidget *ui_parentWidget);
DomWidget *saveWidget(QDesignerDockWidget *dockWidget, DomWidget *ui_parentWidget);
- DomWidget *saveWidget(QTreeView *treeView, DomWidget *ui_parentWidget);
- DomWidget *saveWidget(QTableView *tableView, DomWidget *ui_parentWidget);
DomWidget *saveWidget(QWizardPage *wizardPage, DomWidget *ui_parentWidget);
virtual DomCustomWidgets *saveCustomWidgets();
diff --git a/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp b/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp
index 6e9a698..2300b47 100644
--- a/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp
+++ b/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp
@@ -119,21 +119,31 @@ Qt::BrushStyle BrushPropertyManager::brushStyleIndexToStyle(int brushStyleIndex)
return Qt::NoBrush;
}
+
+typedef QMap<int, QIcon> EnumIndexIconMap;
+
+static void clearBrushIcons();
+Q_GLOBAL_STATIC_WITH_INITIALIZER(EnumIndexIconMap, brushIcons, qAddPostRoutine(clearBrushIcons))
+
+static void clearBrushIcons()
+{
+ brushIcons()->clear();
+}
+
const BrushPropertyManager::EnumIndexIconMap &BrushPropertyManager::brushStyleIcons()
{
// Create a map of icons for the brush style editor
- static EnumIndexIconMap rc;
- if (rc.empty()) {
+ if (brushIcons()->empty()) {
const int brushStyleCount = sizeof(brushStyles)/sizeof(const char *);
QBrush brush(Qt::black);
const QIcon solidIcon = QtPropertyBrowserUtils::brushValueIcon(brush);
for (int i = 0; i < brushStyleCount; i++) {
const Qt::BrushStyle style = brushStyleIndexToStyle(i);
brush.setStyle(style);
- rc.insert(i, QtPropertyBrowserUtils::brushValueIcon(brush));
+ brushIcons()->insert(i, QtPropertyBrowserUtils::brushValueIcon(brush));
}
}
- return rc;
+ return *(brushIcons());
}
QString BrushPropertyManager::brushStyleIndexToString(int brushStyleIndex)
diff --git a/tools/designer/src/components/propertyeditor/propertyeditor.cpp b/tools/designer/src/components/propertyeditor/propertyeditor.cpp
index 512cc82..86d7bdf 100644
--- a/tools/designer/src/components/propertyeditor/propertyeditor.cpp
+++ b/tools/designer/src/components/propertyeditor/propertyeditor.cpp
@@ -79,6 +79,7 @@
#include <QtGui/QToolButton>
#include <QtGui/QActionGroup>
#include <QtGui/QLabel>
+#include <QtGui/QPainter>
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
@@ -98,6 +99,53 @@ QT_BEGIN_NAMESPACE
// ---------------------------------------------------------------------------------
namespace qdesigner_internal {
+
+// ----------- ElidingLabel
+// QLabel does not support text eliding so we need a helper class
+
+class ElidingLabel : public QWidget
+{
+public:
+ ElidingLabel(const QString &text = QString(), QWidget *parent = 0)
+ : QWidget(parent),
+ m_text(text),
+ m_mode(Qt::ElideRight) {
+ setContentsMargins(3, 2, 3, 2);
+ }
+ QSize sizeHint() const;
+ void paintEvent(QPaintEvent *e);
+ void setText(const QString &text) {
+ m_text = text;
+ updateGeometry();
+ }
+ void setElidemode(Qt::TextElideMode mode) {
+ m_mode = mode;
+ updateGeometry();
+ }
+private:
+ QString m_text;
+ Qt::TextElideMode m_mode;
+};
+
+QSize ElidingLabel::sizeHint() const
+{
+ QSize size = fontMetrics().boundingRect(m_text).size();
+ size += QSize(contentsMargins().left() + contentsMargins().right(),
+ contentsMargins().top() + contentsMargins().bottom());
+ return size;
+}
+
+void ElidingLabel::paintEvent(QPaintEvent *e) {
+ QPainter painter(this);
+ painter.setPen(QColor(0, 0, 0, 60));
+ painter.setBrush(QColor(255, 255, 255, 40));
+ painter.drawRect(rect().adjusted(0, 0, -1, -1));
+ painter.setPen(palette().windowText().color());
+ painter.drawText(contentsRect(), Qt::AlignLeft,
+ fontMetrics().elidedText(m_text, Qt::ElideRight, width(), 0));
+}
+
+
// ----------- PropertyEditor::Strings
PropertyEditor::Strings::Strings() :
@@ -186,7 +234,7 @@ PropertyEditor::PropertyEditor(QDesignerFormEditorInterface *core, QWidget *pare
m_coloringAction(new QAction(createIconSet(QLatin1String("color.png")), tr("Color Groups"), this)),
m_treeAction(new QAction(tr("Tree View"), this)),
m_buttonAction(new QAction(tr("Drop Down Button View"), this)),
- m_classLabel(new QLabel),
+ m_classLabel(new ElidingLabel),
m_sorting(false),
m_coloring(false),
m_brightness(false)
@@ -223,11 +271,6 @@ PropertyEditor::PropertyEditor(QDesignerFormEditorInterface *core, QWidget *pare
actionGroup->addAction(m_buttonAction);
connect(actionGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotViewTriggered(QAction*)));
- QWidget *classWidget = new QWidget;
- QHBoxLayout *l = new QHBoxLayout(classWidget);
- l->setContentsMargins(5, 0, 5, 0);
- l->addWidget(m_classLabel);
-
// Add actions
QActionGroup *addDynamicActionGroup = new QActionGroup(this);
connect(addDynamicActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotAddDynamicProperty(QAction*)));
@@ -269,7 +312,6 @@ PropertyEditor::PropertyEditor(QDesignerFormEditorInterface *core, QWidget *pare
#endif
// Assemble toolbar
QToolBar *toolBar = new QToolBar;
- toolBar->addWidget(classWidget);
toolBar->addWidget(m_filterWidget);
toolBar->addWidget(createDropDownButton(m_addDynamicAction));
toolBar->addAction(m_removeDynamicAction);
@@ -292,6 +334,8 @@ PropertyEditor::PropertyEditor(QDesignerFormEditorInterface *core, QWidget *pare
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(toolBar);
+ layout->addWidget(m_classLabel);
+ layout->addSpacerItem(new QSpacerItem(0,1));
layout->addWidget(m_stackedWidget);
layout->setMargin(0);
layout->setSpacing(0);
@@ -778,9 +822,14 @@ void PropertyEditor::updateToolBarLabel()
className = realClassName(m_object);
}
- QString classLabelText = objectName;
- classLabelText += QLatin1Char('\n');
+ m_classLabel->setVisible(!objectName.isEmpty() || !className.isEmpty());
+ m_classLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+
+ QString classLabelText;
+ if (!objectName.isEmpty())
+ classLabelText += objectName + QLatin1String(" : ");
classLabelText += className;
+
m_classLabel->setText(classLabelText);
m_classLabel->setToolTip(tr("Object: %1\nClass: %2").arg(objectName).arg(className));
}
diff --git a/tools/designer/src/components/propertyeditor/propertyeditor.h b/tools/designer/src/components/propertyeditor/propertyeditor.h
index 5869c94..f0ea94f 100644
--- a/tools/designer/src/components/propertyeditor/propertyeditor.h
+++ b/tools/designer/src/components/propertyeditor/propertyeditor.h
@@ -62,9 +62,7 @@ class QtTreePropertyBrowser;
class QtProperty;
class QtVariantProperty;
class QtBrowserItem;
-
class QStackedWidget;
-class QLabel;
namespace qdesigner_internal {
@@ -72,6 +70,7 @@ class StringProperty;
class DesignerPropertyManager;
class DesignerEditorFactory;
class FilterWidget;
+class ElidingLabel;
class QT_PROPERTYEDITOR_EXPORT PropertyEditor: public QDesignerPropertyEditor
{
@@ -186,7 +185,7 @@ private:
QAction *m_coloringAction;
QAction *m_treeAction;
QAction *m_buttonAction;
- QLabel *m_classLabel;
+ ElidingLabel *m_classLabel;
bool m_sorting;
bool m_coloring;
diff --git a/tools/designer/src/components/widgetbox/widgetbox.cpp b/tools/designer/src/components/widgetbox/widgetbox.cpp
index 512d6ba..091135a 100644
--- a/tools/designer/src/components/widgetbox/widgetbox.cpp
+++ b/tools/designer/src/components/widgetbox/widgetbox.cpp
@@ -74,7 +74,10 @@ WidgetBox::WidgetBox(QDesignerFormEditorInterface *core, QWidget *parent, Qt::Wi
FilterWidget *filterWidget = new FilterWidget(0, FilterWidget::LayoutAlignNone);
filterWidget->setRefuseFocus(true);
connect(filterWidget, SIGNAL(filterChanged(QString)), m_view, SLOT(filter(QString)));
- l->addWidget(filterWidget);
+
+ QToolBar *toolBar = new QToolBar(this);
+ toolBar->addWidget(filterWidget);
+ l->addWidget(toolBar);
// View
connect(m_view, SIGNAL(pressed(QString,QString,QPoint)),
diff --git a/tools/designer/src/designer/designer.pro b/tools/designer/src/designer/designer.pro
index 2050c72..8590c7b 100644
--- a/tools/designer/src/designer/designer.pro
+++ b/tools/designer/src/designer/designer.pro
@@ -14,10 +14,8 @@ INCLUDEPATH += \
../lib/uilib \
extra
-LIBS += -L../../lib \
- -L../../../../lib \
- -lQtDesignerComponents \
- -lQtDesigner
+QMAKE_LIBDIR += ../../lib ../../../../lib
+LIBS += -lQtDesignerComponents -lQtDesigner
RESOURCES += designer.qrc
diff --git a/tools/designer/src/designer/mainwindow.cpp b/tools/designer/src/designer/mainwindow.cpp
index c27e2b4..86bc47e 100644
--- a/tools/designer/src/designer/mainwindow.cpp
+++ b/tools/designer/src/designer/mainwindow.cpp
@@ -75,7 +75,7 @@ static void addActionsToToolBar(const ActionList &actions, QToolBar *t)
const ActionList::const_iterator cend = actions.constEnd();
for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it) {
QAction *action = *it;
- if (!action->icon().isNull())
+ if (action->property(QDesignerActions::defaultToolbarPropertyName).toBool())
t->addAction(action);
}
}
@@ -113,6 +113,8 @@ void MainWindowBase::closeEvent(QCloseEvent *e)
QList<QToolBar *> MainWindowBase::createToolBars(const QDesignerActions *actions, bool singleToolBar)
{
+ // Note that whenever you want to add a new tool bar here, you also have to update the default
+ // action groups added to the toolbar manager in the mainwindow constructor
QList<QToolBar *> rc;
if (singleToolBar) {
//: Not currently used (main tool bar)
@@ -252,6 +254,22 @@ ToolBarManager::ToolBarManager(QMainWindow *configureableMainWindow,
m_manager->addAction(action, dockTitle);
}
+ QString category(tr("File"));
+ foreach(QAction *action, actions->fileActions()->actions())
+ m_manager->addAction(action, category);
+
+ category = tr("Edit");
+ foreach(QAction *action, actions->editActions()->actions())
+ m_manager->addAction(action, category);
+
+ category = tr("Tools");
+ foreach(QAction *action, actions->toolActions()->actions())
+ m_manager->addAction(action, category);
+
+ category = tr("Form");
+ foreach(QAction *action, actions->formActions()->actions())
+ m_manager->addAction(action, category);
+
m_manager->addAction(m_configureAction, tr("Toolbars"));
updateToolBarMenu();
}
diff --git a/tools/designer/src/designer/qdesigner_actions.cpp b/tools/designer/src/designer/qdesigner_actions.cpp
index 887ba98..a593a76 100644
--- a/tools/designer/src/designer/qdesigner_actions.cpp
+++ b/tools/designer/src/designer/qdesigner_actions.cpp
@@ -107,6 +107,8 @@ QT_BEGIN_NAMESPACE
using namespace qdesigner_internal;
+const char *QDesignerActions::defaultToolbarPropertyName = "__qt_defaultToolBarAction";
+
//#ifdef Q_WS_MAC
# define NONMODAL_PREVIEW
//#endif
@@ -200,9 +202,15 @@ QDesignerActions::QDesignerActions(QDesignerWorkbench *workbench)
#endif
m_previewManager(0)
{
+#ifdef Q_WS_X11
m_newFormAction->setIcon(QIcon::fromTheme("document-new", m_newFormAction->icon()));
m_openFormAction->setIcon(QIcon::fromTheme("document-open", m_openFormAction->icon()));
m_saveFormAction->setIcon(QIcon::fromTheme("document-save", m_saveFormAction->icon()));
+ m_saveFormAsAction->setIcon(QIcon::fromTheme("document-save-as", m_saveFormAsAction->icon()));
+ m_printPreviewAction->setIcon(QIcon::fromTheme("document-print", m_printPreviewAction->icon()));
+ m_closeFormAction->setIcon(QIcon::fromTheme("window-close", m_closeFormAction->icon()));
+ m_quitAction->setIcon(QIcon::fromTheme("application-exit", m_quitAction->icon()));
+#endif
Q_ASSERT(m_core != 0);
qdesigner_internal::QDesignerFormWindowManager *ifwm = qobject_cast<qdesigner_internal::QDesignerFormWindowManager *>(m_core->formWindowManager());
@@ -230,6 +238,10 @@ QDesignerActions::QDesignerActions(QDesignerWorkbench *workbench)
m_helpActions = createHelpActions();
+ m_newFormAction->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ m_openFormAction->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ m_saveFormAction->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+
QDesignerFormWindowManagerInterface *formWindowManager = m_core->formWindowManager();
Q_ASSERT(formWindowManager != 0);
@@ -316,6 +328,9 @@ QDesignerActions::QDesignerActions(QDesignerWorkbench *workbench)
m_editActions->addAction(formWindowManager->actionLower());
m_editActions->addAction(formWindowManager->actionRaise());
+ formWindowManager->actionLower()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionRaise()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+
//
// edit mode actions
//
@@ -343,6 +358,7 @@ QDesignerActions::QDesignerActions(QDesignerWorkbench *workbench)
if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
if (QAction *action = formEditorPlugin->action()) {
m_toolActions->addAction(action);
+ action->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
action->setCheckable(true);
}
}
@@ -370,6 +386,15 @@ QDesignerActions::QDesignerActions(QDesignerWorkbench *workbench)
m_formActions->addAction(formWindowManager->actionSimplifyLayout());
m_formActions->addAction(createSeparator(this));
+ formWindowManager->actionHorizontalLayout()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionVerticalLayout()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionSplitHorizontal()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionSplitVertical()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionGridLayout()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionFormLayout()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionBreakLayout()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionAdjustSize()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+
m_previewFormAction->setShortcut(tr("CTRL+R"));
m_formActions->addAction(m_previewFormAction);
connect(m_previewManager, SIGNAL(firstPreviewOpened()), this, SLOT(updateCloseAction()));
@@ -490,13 +515,13 @@ QAction *QDesignerActions::createRecentFilesMenu()
}
updateRecentFileActions();
menu->addSeparator();
- act = new QAction(tr("Clear &Menu"), this);
+ act = new QAction(QIcon::fromTheme("edit-clear"), tr("Clear &Menu"), this);
act->setObjectName(QLatin1String("__qt_action_clear_menu_"));
connect(act, SIGNAL(triggered()), this, SLOT(clearRecentFiles()));
m_recentFilesActions->addAction(act);
menu->addAction(act);
- act = new QAction(tr("&Recent Forms"), this);
+ act = new QAction(QIcon::fromTheme("document-open-recent"), tr("&Recent Forms"), this);
act->setMenu(menu);
return act;
}
diff --git a/tools/designer/src/designer/qdesigner_actions.h b/tools/designer/src/designer/qdesigner_actions.h
index 9dfcef1..d8f9e42 100644
--- a/tools/designer/src/designer/qdesigner_actions.h
+++ b/tools/designer/src/designer/qdesigner_actions.h
@@ -113,6 +113,10 @@ public:
QString uiExtension() const;
+ // Boolean dynamic property set on actions to
+ // show them in the default toolbar layout
+ static const char *defaultToolbarPropertyName;
+
public slots:
void activeFormWindowChanged(QDesignerFormWindowInterface *formWindow);
void createForm();
diff --git a/tools/designer/src/designer/qdesigner_workbench.cpp b/tools/designer/src/designer/qdesigner_workbench.cpp
index b65ce7e..168c468 100644
--- a/tools/designer/src/designer/qdesigner_workbench.cpp
+++ b/tools/designer/src/designer/qdesigner_workbench.cpp
@@ -419,6 +419,7 @@ void QDesignerWorkbench::switchToDockedMode()
m_mode = DockedMode;
const QDesignerSettings settings(m_core);
m_dockedMainWindow = new DockedMainWindow(this, m_toolbarMenu, m_toolWindows);
+ m_dockedMainWindow->setUnifiedTitleAndToolBarOnMac(true);
m_dockedMainWindow->setCloseEventPolicy(MainWindowBase::EmitCloseEventSignal);
connect(m_dockedMainWindow, SIGNAL(closeEventReceived(QCloseEvent*)), this, SLOT(handleCloseEvent(QCloseEvent*)));
connect(m_dockedMainWindow, SIGNAL(fileDropped(QString)), this, SLOT(slotFileDropped(QString)));
diff --git a/tools/designer/src/lib/shared/filterwidget.cpp b/tools/designer/src/lib/shared/filterwidget.cpp
index 6c73a08..f485346 100644
--- a/tools/designer/src/lib/shared/filterwidget.cpp
+++ b/tools/designer/src/lib/shared/filterwidget.cpp
@@ -44,13 +44,17 @@
#include <QtGui/QVBoxLayout>
#include <QtGui/QHBoxLayout>
-#include <QtGui/QPushButton>
#include <QtGui/QLineEdit>
#include <QtGui/QFocusEvent>
#include <QtGui/QPalette>
#include <QtGui/QCursor>
+#include <QtGui/QToolButton>
+#include <QtGui/QPainter>
+#include <QtGui/QStyle>
+#include <QtGui/QStyleOption>
#include <QtCore/QDebug>
+#include <QtCore/QPropertyAnimation>
enum { debugFilter = 0 };
@@ -61,12 +65,44 @@ namespace qdesigner_internal {
HintLineEdit::HintLineEdit(QWidget *parent) :
QLineEdit(parent),
m_defaultFocusPolicy(focusPolicy()),
- m_hintColor(QColor(0xbbbbbb)),
- m_refuseFocus(false),
- m_showingHintText(false)
+ m_refuseFocus(false)
{
}
+IconButton::IconButton(QWidget *parent)
+ : QToolButton(parent)
+{
+ setCursor(Qt::ArrowCursor);
+}
+
+void IconButton::paintEvent(QPaintEvent *)
+{
+ QPainter painter(this);
+ // Note isDown should really use the active state but in most styles
+ // this has no proper feedback
+ QPixmap iconpixmap = icon().pixmap(ICONBUTTON_SIZE, ICONBUTTON_SIZE, isDown() ?
+ QIcon::Selected : QIcon::Normal);
+ QRect pixmapRect = QRect(0, 0, iconpixmap.width(), iconpixmap.height());
+ pixmapRect.moveCenter(rect().center());
+ painter.setOpacity(m_fader);
+ painter.drawPixmap(pixmapRect, iconpixmap);
+}
+
+void IconButton::animateShow(bool visible)
+{
+ if (visible) {
+ QPropertyAnimation *animation = new QPropertyAnimation(this, "fader");
+ animation->setDuration(160);
+ animation->setEndValue(1.0);
+ animation->start(QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ QPropertyAnimation *animation = new QPropertyAnimation(this, "fader");
+ animation->setDuration(160);
+ animation->setEndValue(0.0);
+ animation->start(QAbstractAnimation::DeleteWhenStopped);
+ }
+}
+
bool HintLineEdit::refuseFocus() const
{
return m_refuseFocus;
@@ -111,92 +147,53 @@ void HintLineEdit::focusInEvent(QFocusEvent *e)
}
}
- hideHintText();
QLineEdit::focusInEvent(e);
}
-void HintLineEdit::focusOutEvent(QFocusEvent *e)
-{
- if (debugFilter)
- qDebug() << Q_FUNC_INFO;
- // Focus out: Switch to displaying the hint text unless there is user input
- showHintText();
- QLineEdit::focusOutEvent(e);
-}
-
-QString HintLineEdit::hintText() const
+// ------------------- FilterWidget
+FilterWidget::FilterWidget(QWidget *parent, LayoutMode lm) :
+ QWidget(parent),
+ m_editor(new HintLineEdit(this)),
+ m_button(new IconButton(m_editor)),
+ m_buttonwidth(0)
{
- return m_hintText;
-}
+ m_editor->setPlaceholderText(tr("Filter"));
-void HintLineEdit::setHintText(const QString &ht)
-{
- if (ht == m_hintText)
- return;
- hideHintText();
- m_hintText = ht;
- if (!hasFocus() && !ht.isEmpty())
- showHintText();
-}
+ // Let the style determine minimum height for our widget
+ QSize size(ICONBUTTON_SIZE + 2, ICONBUTTON_SIZE + 2);
-void HintLineEdit::showHintText(bool force)
-{
- if (m_showingHintText || m_hintText.isEmpty())
- return;
- if (force || text().isEmpty()) {
- m_showingHintText = true;
- setText(m_hintText);
- setTextColor(m_hintColor, &m_textColor);
- }
-}
-void HintLineEdit::hideHintText()
-{
- if (m_showingHintText && !m_hintText.isEmpty()) {
- m_showingHintText = false;
- setText(QString());
- setTextColor(m_textColor);
+ // Note KDE does not reserve space for the highlight color
+ if (style()->inherits("OxygenStyle")) {
+ size = size.expandedTo(QSize(24, 0));
}
-}
-bool HintLineEdit::isShowingHintText() const
-{
- return m_showingHintText;
-}
-
-QString HintLineEdit::typedText() const
-{
- return m_showingHintText ? QString() : text();
-}
+ // Make room for clear icon
+ QMargins margins = m_editor->textMargins();
+ if (layoutDirection() == Qt::LeftToRight)
+ margins.setRight(size.width());
+ else
+ margins.setLeft(size.width());
-void HintLineEdit::setTextColor(const QColor &newColor, QColor *oldColor)
-{
- QPalette pal = palette();
- if (oldColor)
- *oldColor = pal.color(QPalette::Text);
- pal.setColor(QPalette::Text, newColor);
- setPalette(pal);}
+ m_editor->setTextMargins(margins);
-// ------------------- FilterWidget
-FilterWidget::FilterWidget(QWidget *parent, LayoutMode lm) :
- QWidget(parent),
- m_button(new QPushButton),
- m_editor(new HintLineEdit)
-{
- m_editor->setHintText(tr("<Filter>"));
QHBoxLayout *l = new QHBoxLayout(this);
l->setMargin(0);
l->setSpacing(0);
-
if (lm == LayoutAlignRight)
l->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
l->addWidget(m_editor);
- m_button->setIcon(createIconSet(QLatin1String("resetproperty.png")));
- m_button->setIconSize(QSize(8, 8));
- m_button->setFlat(true);
- l->addWidget(m_button);
+ // KDE has custom icons for this. Notice that icon namings are counter intuitive
+ // If these icons are not avaiable we use the freedesktop standard name before
+ // falling back to a bundled resource
+ QIcon icon = QIcon::fromTheme(layoutDirection() == Qt::LeftToRight ?
+ QLatin1String("edit-clear-locationbar-rtl") :
+ QLatin1String("edit-clear-locationbar-ltr"),
+ QIcon::fromTheme("edit-clear", createIconSet(QLatin1String("cleartext.png"))));
+ m_button->setIcon(icon);
+ m_button->setToolTip(tr("Clear text"));
connect(m_button, SIGNAL(clicked()), this, SLOT(reset()));
connect(m_editor, SIGNAL(textChanged(QString)), this, SLOT(checkButton(QString)));
connect(m_editor, SIGNAL(textEdited(QString)), this, SIGNAL(filterChanged(QString)));
@@ -204,25 +201,38 @@ FilterWidget::FilterWidget(QWidget *parent, LayoutMode lm) :
QString FilterWidget::text() const
{
- return m_editor->typedText();
+ return m_editor->text();
}
void FilterWidget::checkButton(const QString &)
{
- m_button->setEnabled(!text().isEmpty());
+ m_button->animateShow(!m_editor->text().isEmpty());
}
void FilterWidget::reset()
{
if (debugFilter)
qDebug() << Q_FUNC_INFO;
- if (!text().isEmpty()) {
+
+ if (!m_editor->text().isEmpty()) {
// Editor has lost focus once this is pressed
- m_editor->showHintText(true);
+ m_editor->clear();
emit filterChanged(QString());
}
}
+void FilterWidget::resizeEvent(QResizeEvent *)
+{
+ QRect contentRect = m_editor->rect();
+ if (layoutDirection() == Qt::LeftToRight) {
+ const int iconoffset = m_editor->textMargins().right() + 4;
+ m_button->setGeometry(contentRect.adjusted(m_editor->width() - iconoffset, 0, 0, 0));
+ } else {
+ const int iconoffset = m_editor->textMargins().left() + 4;
+ m_button->setGeometry(contentRect.adjusted(0, 0, -m_editor->width() + iconoffset, 0));
+ }
+}
+
bool FilterWidget::refuseFocus() const
{
return m_editor->refuseFocus();
diff --git a/tools/designer/src/lib/shared/filterwidget_p.h b/tools/designer/src/lib/shared/filterwidget_p.h
index 025d708..423b30e 100644
--- a/tools/designer/src/lib/shared/filterwidget_p.h
+++ b/tools/designer/src/lib/shared/filterwidget_p.h
@@ -58,58 +58,55 @@
#include <QtGui/QWidget>
#include <QtGui/QLineEdit>
#include <QtGui/QColor>
+#include <QtGui/QToolButton>
QT_BEGIN_NAMESPACE
-class QPushButton;
+class QToolButton;
namespace qdesigner_internal {
-/* A line edit that displays a grayed hintText (like "Type Here to Filter")
- * when not focused and empty. When connecting to the changed signals and
- * querying text, one has to be aware that the text is set to that hint
- * text if isShowingHintText() returns true (that is, does not contain
- * valid user input). This widget should never have initial focus
+/* This widget should never have initial focus
* (ie, be the first widget of a dialog, else, the hint cannot be displayed.
* For situations, where it is the only focusable control (widget box),
* there is a special "refuseFocus()" mode, in which it clears the focus
* policy and focusses explicitly on click (note that setting Qt::ClickFocus
* is not sufficient for that as an ActivationFocus will occur). */
+#define ICONBUTTON_SIZE 16
+
class QDESIGNER_SHARED_EXPORT HintLineEdit : public QLineEdit {
Q_OBJECT
public:
explicit HintLineEdit(QWidget *parent = 0);
- QString hintText() const;
-
- bool isShowingHintText() const;
-
- // Convenience for accessing the text that returns "" in case of isShowingHintText().
- QString typedText() const;
-
bool refuseFocus() const;
void setRefuseFocus(bool v);
-public slots:
- void setHintText(const QString &ht);
- void showHintText(bool force = false);
- void hideHintText();
-
protected:
virtual void mousePressEvent(QMouseEvent *event);
virtual void focusInEvent(QFocusEvent *e);
- virtual void focusOutEvent(QFocusEvent *e);
private:
- void setTextColor(const QColor &newColor, QColor *oldColor = 0);
-
const Qt::FocusPolicy m_defaultFocusPolicy;
- const QColor m_hintColor;
- QColor m_textColor;
bool m_refuseFocus;
- QString m_hintText;
- bool m_showingHintText;
+};
+
+// IconButton: This is a simple helper class that represents clickable icons
+
+class IconButton: public QToolButton
+{
+ Q_OBJECT
+ Q_PROPERTY(float fader READ fader WRITE setFader)
+public:
+ IconButton(QWidget *parent);
+ void paintEvent(QPaintEvent *event);
+ float fader() { return m_fader; }
+ void setFader(float value) { m_fader = value; update(); }
+ void animateShow(bool visible);
+
+private:
+ float m_fader;
};
// FilterWidget: For filtering item views, with reset button Uses HintLineEdit.
@@ -128,7 +125,7 @@ public:
explicit FilterWidget(QWidget *parent = 0, LayoutMode lm = LayoutAlignRight);
QString text() const;
-
+ void resizeEvent(QResizeEvent *);
bool refuseFocus() const; // see HintLineEdit
void setRefuseFocus(bool v);
@@ -142,8 +139,9 @@ private slots:
void checkButton(const QString &text);
private:
- QPushButton *m_button;
HintLineEdit *m_editor;
+ IconButton *m_button;
+ int m_buttonwidth;
};
} // namespace qdesigner_internal
diff --git a/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp
index 77ab2a6..08fedd2 100644
--- a/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp
+++ b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp
@@ -722,10 +722,11 @@ int QDesignerPropertySheet::addDynamicProperty(const QString &propName, const QV
else if (value.type() == QVariant::Pixmap)
v = qVariantFromValue(qdesigner_internal::PropertySheetPixmapValue());
else if (value.type() == QVariant::String)
- v = qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
- else if (value.type() == QVariant::KeySequence)
- v = qVariantFromValue(qdesigner_internal::PropertySheetKeySequenceValue());
-
+ v = qVariantFromValue(qdesigner_internal::PropertySheetStringValue(value.toString()));
+ else if (value.type() == QVariant::KeySequence) {
+ const QKeySequence keySequence = qVariantValue<QKeySequence>(value);
+ v = qVariantFromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence));
+ }
if (d->m_addIndex.contains(propName)) {
const int idx = d->m_addIndex.value(propName);
@@ -1130,7 +1131,7 @@ void QDesignerPropertySheet::setProperty(int index, const QVariant &value)
}
}
- if (isDynamicProperty(index)) {
+ if (isDynamicProperty(index) || isDefaultDynamicProperty(index)) {
if (d->isResourceProperty(index))
d->setResourceProperty(index, value);
if (d->isStringProperty(index))
@@ -1200,10 +1201,17 @@ bool QDesignerPropertySheet::reset(int index)
} else if (isDynamic(index)) {
const QString propName = propertyName(index);
const QVariant oldValue = d->m_addProperties.value(index);
- const QVariant newValue = d->m_info.value(index).defaultValue;
+ const QVariant defaultValue = d->m_info.value(index).defaultValue;
+ QVariant newValue = defaultValue;
+ if (d->isStringProperty(index)) {
+ newValue = qVariantFromValue(qdesigner_internal::PropertySheetStringValue(newValue.toString()));
+ } else if (d->isKeySequenceProperty(index)) {
+ const QKeySequence keySequence = qVariantValue<QKeySequence>(newValue);
+ newValue = qVariantFromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence));
+ }
if (oldValue == newValue)
return true;
- d->m_object->setProperty(propName.toUtf8(), newValue);
+ d->m_object->setProperty(propName.toUtf8(), defaultValue);
d->m_addProperties[index] = newValue;
return true;
} else if (!d->m_info.value(index).defaultValue.isNull()) {
diff --git a/tools/designer/src/lib/shared/qtresourceview.cpp b/tools/designer/src/lib/shared/qtresourceview.cpp
index 859f239..18fd07b 100644
--- a/tools/designer/src/lib/shared/qtresourceview.cpp
+++ b/tools/designer/src/lib/shared/qtresourceview.cpp
@@ -377,7 +377,8 @@ void QtResourceViewPrivate::createPaths()
if (!m_resourceModel)
return;
- const QString root(QLatin1Char(':'));
+ // Resource root up until 4.6 was ':', changed to ":/" as of 4.7
+ const QString root(QLatin1String(":/"));
QMap<QString, QString> contents = m_resourceModel->contents();
QMapIterator<QString, QString> itContents(contents);
@@ -420,7 +421,7 @@ void QtResourceViewPrivate::filterOutResources()
// 3) we hide these items which has pathToVisible value false.
const bool matchAll = m_filterPattern.isEmpty();
- const QString root(QLatin1Char(':'));
+ const QString root(QLatin1String(":/"));
QQueue<QString> pathQueue;
pathQueue.enqueue(root);
diff --git a/tools/linguist/linguist.pro b/tools/linguist/linguist.pro
index e1c8a63..248c89e 100644
--- a/tools/linguist/linguist.pro
+++ b/tools/linguist/linguist.pro
@@ -1,8 +1,6 @@
TEMPLATE = subdirs
SUBDIRS = \
- linguist \
lrelease \
lupdate \
lconvert
-CONFIG += ordered
-
+!no-png:!contains(QT_CONFIG, no-gui):SUBDIRS += linguist
diff --git a/tools/linguist/linguist/mainwindow.cpp b/tools/linguist/linguist/mainwindow.cpp
index 321fe8c..1611699 100644
--- a/tools/linguist/linguist/mainwindow.cpp
+++ b/tools/linguist/linguist/mainwindow.cpp
@@ -1810,28 +1810,50 @@ QString MainWindow::friendlyString(const QString& str)
return f.simplified();
}
+static inline void setThemeIcon(QAction *action, const char *name, const char *fallback)
+{
+ const QIcon fallbackIcon(MainWindow::resourcePrefix() + QLatin1String(fallback));
+#ifdef Q_WS_X11
+ action->setIcon(QIcon::fromTheme(QLatin1String(name), fallbackIcon));
+#else
+ Q_UNUSED(name)
+ action->setIcon(fallbackIcon);
+#endif
+}
+
void MainWindow::setupMenuBar()
{
+ // There are no fallback icons for these
+#ifdef Q_WS_X11
+ m_ui.menuRecentlyOpenedFiles->setIcon(QIcon::fromTheme(QLatin1String("document-open-recent")));
+ m_ui.actionCloseAll->setIcon(QIcon::fromTheme(QLatin1String("window-close")));
+ m_ui.actionExit->setIcon(QIcon::fromTheme(QLatin1String("application-exit")));
+ m_ui.actionSelectAll->setIcon(QIcon::fromTheme(QLatin1String("edit-select-all")));
+#endif
+
+ // Prefer theme icons when available for these actions
+ setThemeIcon(m_ui.actionOpen, "document-open", "/fileopen.png");
+ setThemeIcon(m_ui.actionOpenAux, "document-open", "/fileopen.png");
+ setThemeIcon(m_ui.actionSave, "document-save", "/filesave.png");
+ setThemeIcon(m_ui.actionSaveAll, "document-save", "/filesave.png");
+ setThemeIcon(m_ui.actionPrint, "document-print", "/print.png");
+ setThemeIcon(m_ui.actionRedo, "edit-redo", "/redo.png");
+ setThemeIcon(m_ui.actionUndo, "edit-undo", "/undo.png");
+ setThemeIcon(m_ui.actionCut, "edit-cut", "/editcut.png");
+ setThemeIcon(m_ui.actionCopy, "edit-copy", "/editcopy.png");
+ setThemeIcon(m_ui.actionPaste, "edit-paste", "/editpaste.png");
+ setThemeIcon(m_ui.actionFind, "edit-find", "/searchfind.png");
+
+ // No well defined theme icons for these actions
m_ui.actionAccelerators->setIcon(QIcon(resourcePrefix() + QLatin1String("/accelerator.png")));
m_ui.actionOpenPhraseBook->setIcon(QIcon(resourcePrefix() + QLatin1String("/book.png")));
m_ui.actionDoneAndNext->setIcon(QIcon(resourcePrefix() + QLatin1String("/doneandnext.png")));
- m_ui.actionCopy->setIcon(QIcon(resourcePrefix() + QLatin1String("/editcopy.png")));
- m_ui.actionCut->setIcon(QIcon(resourcePrefix() + QLatin1String("/editcut.png")));
- m_ui.actionPaste->setIcon(QIcon(resourcePrefix() + QLatin1String("/editpaste.png")));
- m_ui.actionOpen->setIcon(QIcon(resourcePrefix() + QLatin1String("/fileopen.png")));
- m_ui.actionOpenAux->setIcon(QIcon(resourcePrefix() + QLatin1String("/fileopen.png")));
- m_ui.actionSaveAll->setIcon(QIcon(resourcePrefix() + QLatin1String("/filesave.png")));
- m_ui.actionSave->setIcon(QIcon(resourcePrefix() + QLatin1String("/filesave.png")));
m_ui.actionNext->setIcon(QIcon(resourcePrefix() + QLatin1String("/next.png")));
m_ui.actionNextUnfinished->setIcon(QIcon(resourcePrefix() + QLatin1String("/nextunfinished.png")));
m_ui.actionPhraseMatches->setIcon(QIcon(resourcePrefix() + QLatin1String("/phrase.png")));
m_ui.actionEndingPunctuation->setIcon(QIcon(resourcePrefix() + QLatin1String("/punctuation.png")));
m_ui.actionPrev->setIcon(QIcon(resourcePrefix() + QLatin1String("/prev.png")));
m_ui.actionPrevUnfinished->setIcon(QIcon(resourcePrefix() + QLatin1String("/prevunfinished.png")));
- m_ui.actionPrint->setIcon(QIcon(resourcePrefix() + QLatin1String("/print.png")));
- m_ui.actionRedo->setIcon(QIcon(resourcePrefix() + QLatin1String("/redo.png")));
- m_ui.actionFind->setIcon(QIcon(resourcePrefix() + QLatin1String("/searchfind.png")));
- m_ui.actionUndo->setIcon(QIcon(resourcePrefix() + QLatin1String("/undo.png")));
m_ui.actionPlaceMarkerMatches->setIcon(QIcon(resourcePrefix() + QLatin1String("/validateplacemarkers.png")));
m_ui.actionWhatsThis->setIcon(QIcon(resourcePrefix() + QLatin1String("/whatsthis.png")));
@@ -2370,7 +2392,7 @@ static bool haveMnemonic(const QString &str)
// because we get a lot of false positives.
if (c != '&' && c != ' ' && QChar(c).isPrint()) {
const ushort *pp = p;
- for (; *p < 256 && ::isalpha(*p); p++) ;
+ for (; *p < 256 && isalpha(*p); p++) ;
if (pp == p || *p != ';')
return true;
// This looks like a HTML &entity;, so ignore it. As a HTML string
diff --git a/tools/linguist/linguist/messagemodel.cpp b/tools/linguist/linguist/messagemodel.cpp
index 4e2b473..39ba9fd 100644
--- a/tools/linguist/linguist/messagemodel.cpp
+++ b/tools/linguist/linguist/messagemodel.cpp
@@ -402,7 +402,7 @@ bool DataModel::setLanguageAndCountry(QLocale::Language lang, QLocale::Country c
if (lang == QLocale::C || uint(lang) > uint(QLocale::LastLanguage)) // XXX does this make any sense?
lang = QLocale::English;
QByteArray rules;
- bool ok = getNumerusInfo(lang, country, &rules, &m_numerusForms);
+ bool ok = getNumerusInfo(lang, country, &rules, &m_numerusForms, 0);
m_localizedLanguage = QCoreApplication::translate("MessageEditor", QLocale::languageToString(lang).toAscii());
m_countRefNeeds.clear();
for (int i = 0; i < rules.size(); ++i) {
diff --git a/tools/linguist/lupdate/cpp.cpp b/tools/linguist/lupdate/cpp.cpp
index 2d5620e..db4bbca 100644
--- a/tools/linguist/lupdate/cpp.cpp
+++ b/tools/linguist/lupdate/cpp.cpp
@@ -65,47 +65,44 @@ static QString MagicComment(QLatin1String("TRANSLATOR"));
class HashString {
public:
- HashString() : m_hashed(false) {}
- explicit HashString(const QString &str) : m_str(str), m_hashed(false) {}
- void setValue(const QString &str) { m_str = str; m_hashed = false; }
+ HashString() : m_hash(0x80000000) {}
+ explicit HashString(const QString &str) : m_str(str), m_hash(0x80000000) {}
+ void setValue(const QString &str) { m_str = str; m_hash = 0x80000000; }
const QString &value() const { return m_str; }
bool operator==(const HashString &other) const { return m_str == other.m_str; }
private:
QString m_str;
+ // qHash() of a QString is only 28 bits wide, so we can use
+ // the highest bit(s) as the "hash valid" flag.
mutable uint m_hash;
- mutable bool m_hashed;
friend uint qHash(const HashString &str);
};
uint qHash(const HashString &str)
{
- if (!str.m_hashed) {
- str.m_hashed = true;
+ if (str.m_hash & 0x80000000)
str.m_hash = qHash(str.m_str);
- }
return str.m_hash;
}
class HashStringList {
public:
- explicit HashStringList(const QList<HashString> &list) : m_list(list), m_hashed(false) {}
+ explicit HashStringList(const QList<HashString> &list) : m_list(list), m_hash(0x80000000) {}
const QList<HashString> &value() const { return m_list; }
bool operator==(const HashStringList &other) const { return m_list == other.m_list; }
private:
QList<HashString> m_list;
mutable uint m_hash;
- mutable bool m_hashed;
friend uint qHash(const HashStringList &list);
};
uint qHash(const HashStringList &list)
{
- if (!list.m_hashed) {
- list.m_hashed = true;
+ if (list.m_hash & 0x80000000) {
uint hash = 0;
foreach (const HashString &qs, list.m_list) {
- hash ^= qHash(qs) ^ 0xa09df22f;
- hash = (hash << 13) | (hash >> 19);
+ hash ^= qHash(qs) ^ 0x0ad9f526;
+ hash = ((hash << 13) & 0x0fffffff) | (hash >> 15);
}
list.m_hash = hash;
}
@@ -215,13 +212,15 @@ public:
private:
struct IfdefState {
IfdefState() {}
- IfdefState(int _braceDepth, int _parenDepth) :
+ IfdefState(int _bracketDepth, int _braceDepth, int _parenDepth) :
+ bracketDepth(_bracketDepth),
braceDepth(_braceDepth),
parenDepth(_parenDepth),
elseLine(-1)
{}
SavedState state;
+ int bracketDepth, bracketDepth1st;
int braceDepth, braceDepth1st;
int parenDepth, parenDepth1st;
int elseLine;
@@ -280,14 +279,14 @@ private:
enum {
Tok_Eof, Tok_class, Tok_friend, Tok_namespace, Tok_using, Tok_return,
- Tok_tr = 10, Tok_trUtf8, Tok_translate, Tok_translateUtf8, Tok_trid,
- Tok_Q_OBJECT = 20, Tok_Q_DECLARE_TR_FUNCTIONS,
+ Tok_tr, Tok_trUtf8, Tok_translate, Tok_translateUtf8, Tok_trid,
+ Tok_Q_OBJECT, Tok_Q_DECLARE_TR_FUNCTIONS,
Tok_Ident, Tok_Comment, Tok_String, Tok_Arrow, Tok_Colon, Tok_ColonColon,
- Tok_Equals,
- Tok_LeftBrace = 30, Tok_RightBrace, Tok_LeftParen, Tok_RightParen, Tok_Comma, Tok_Semicolon,
- Tok_Null = 40, Tok_Integer,
- Tok_QuotedInclude = 50, Tok_AngledInclude,
- Tok_Other = 99
+ Tok_Equals, Tok_LeftBracket, Tok_RightBracket,
+ Tok_LeftBrace, Tok_RightBrace, Tok_LeftParen, Tok_RightParen, Tok_Comma, Tok_Semicolon,
+ Tok_Null, Tok_Integer,
+ Tok_QuotedInclude, Tok_AngledInclude,
+ Tok_Other
};
// Tokenizer state
@@ -299,10 +298,12 @@ private:
QString yyWord;
qlonglong yyInteger;
QStack<IfdefState> yyIfdefStack;
+ int yyBracketDepth;
int yyBraceDepth;
int yyParenDepth;
int yyLineNo;
int yyCurLineNo;
+ int yyBracketLineNo;
int yyBraceLineNo;
int yyParenLineNo;
@@ -339,9 +340,11 @@ CppParser::CppParser(ParseResults *_results)
results = new ParseResults;
directInclude = false;
}
+ yyBracketDepth = 0;
yyBraceDepth = 0;
yyParenDepth = 0;
yyCurLineNo = 1;
+ yyBracketLineNo = 1;
yyBraceLineNo = 1;
yyParenLineNo = 1;
yyAtNewline = true;
@@ -568,7 +571,7 @@ uint CppParser::getToken()
yyCh = getChar();
if (yyCh == 'f') {
// if, ifdef, ifndef
- yyIfdefStack.push(IfdefState(yyBraceDepth, yyParenDepth));
+ yyIfdefStack.push(IfdefState(yyBracketDepth, yyBraceDepth, yyParenDepth));
yyCh = getChar();
} else if (yyCh == 'n') {
// include
@@ -607,16 +610,20 @@ uint CppParser::getToken()
if (!yyIfdefStack.isEmpty()) {
IfdefState &is = yyIfdefStack.top();
if (is.elseLine != -1) {
- if (yyBraceDepth != is.braceDepth1st || yyParenDepth != is.parenDepth1st)
- qWarning("%s:%d: Parenthesis/brace mismatch between "
+ if (yyBracketDepth != is.bracketDepth1st
+ || yyBraceDepth != is.braceDepth1st
+ || yyParenDepth != is.parenDepth1st)
+ qWarning("%s:%d: Parenthesis/bracket/brace mismatch between "
"#if and #else branches; using #if branch\n",
qPrintable(yyFileName), is.elseLine);
} else {
+ is.bracketDepth1st = yyBracketDepth;
is.braceDepth1st = yyBraceDepth;
is.parenDepth1st = yyParenDepth;
saveState(&is.state);
}
is.elseLine = yyLineNo;
+ yyBracketDepth = is.bracketDepth;
yyBraceDepth = is.braceDepth;
yyParenDepth = is.parenDepth;
}
@@ -626,10 +633,13 @@ uint CppParser::getToken()
if (!yyIfdefStack.isEmpty()) {
IfdefState is = yyIfdefStack.pop();
if (is.elseLine != -1) {
- if (yyBraceDepth != is.braceDepth1st || yyParenDepth != is.parenDepth1st)
+ if (yyBracketDepth != is.bracketDepth1st
+ || yyBraceDepth != is.braceDepth1st
+ || yyParenDepth != is.parenDepth1st)
qWarning("%s:%d: Parenthesis/brace mismatch between "
"#if and #else branches; using #if branch\n",
qPrintable(yyFileName), is.elseLine);
+ yyBracketDepth = is.bracketDepth1st;
yyBraceDepth = is.braceDepth1st;
yyParenDepth = is.parenDepth1st;
loadState(&is.state);
@@ -902,6 +912,21 @@ uint CppParser::getToken()
yyParenDepth--;
yyCh = getChar();
return Tok_RightParen;
+ case '[':
+ if (yyBracketDepth == 0)
+ yyBracketLineNo = yyCurLineNo;
+ yyBracketDepth++;
+ yyCh = getChar();
+ return Tok_LeftBracket;
+ case ']':
+ if (yyBracketDepth == 0)
+ qWarning("%s:%d: Excess closing bracket in C++ code"
+ " (or abuse of the C++ preprocessor)\n",
+ qPrintable(yyFileName), yyCurLineNo);
+ else
+ yyBracketDepth--;
+ yyCh = getChar();
+ return Tok_RightBracket;
case ',':
yyCh = getChar();
return Tok_Comma;
@@ -1537,6 +1562,12 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions)
yyCh = getChar();
yyTok = getToken();
while (yyTok != Tok_Eof) {
+ // these are array indexing operations. we ignore them entirely
+ // so they don't confuse our scoping of static initializers.
+ // we enter the loop by either reading a left bracket or by an
+ // #else popping the state.
+ while (yyBracketDepth)
+ yyTok = getToken();
//qDebug() << "TOKEN: " << yyTok;
switch (yyTok) {
case Tok_QuotedInclude: {
@@ -2004,9 +2035,14 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions)
} else {
context = comment.left(k);
comment.remove(0, k + 1);
- recordMessage(yyLineNo, context, QString(), comment, extracomment,
- QString(), TranslatorMessage::ExtraData(), false, false);
+ TranslatorMessage msg(
+ transcode(context, false), QString(),
+ transcode(comment, false), QString(),
+ yyFileName, yyLineNo, QStringList(),
+ TranslatorMessage::Finished, false);
+ msg.setExtraComment(transcode(extracomment.simplified(), false));
extracomment.clear();
+ tor->append(msg);
tor->setExtras(extra);
extra.clear();
}
@@ -2077,6 +2113,9 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions)
default:
if (!yyParenDepth)
prospectiveContext.clear();
+ // fallthrough
+ case Tok_Equals: // for static initializers; other cases make no difference
+ case Tok_RightBracket: // ignoring indexing; same reason
case_default:
yyTok = getToken();
break;
@@ -2091,6 +2130,10 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions)
qWarning("%s:%d: Unbalanced opening parenthesis in C++ code"
" (or abuse of the C++ preprocessor)\n",
qPrintable(yyFileName), yyParenLineNo);
+ else if (yyBracketDepth != 0)
+ qWarning("%s:%d: Unbalanced opening bracket in C++ code"
+ " (or abuse of the C++ preprocessor)\n",
+ qPrintable(yyFileName), yyBracketLineNo);
}
const ParseResults *CppParser::recordResults(bool isHeader)
diff --git a/tools/linguist/lupdate/lupdate.pro b/tools/linguist/lupdate/lupdate.pro
index 1f88931..3ed909a 100644
--- a/tools/linguist/lupdate/lupdate.pro
+++ b/tools/linguist/lupdate/lupdate.pro
@@ -16,7 +16,7 @@ include(../shared/formats.pri)
include(../shared/proparser.pri)
include($$QT_SOURCE_TREE/src/declarative/qml/parser/parser.pri)
-INCLUDEPATH += $$QT_SOURCE_TREE/src/declarative/qml
+INCLUDEPATH += $$QT_SOURCE_TREE/src/declarative/qml $$QT_BUILD_TREE/include/QtDeclarative
SOURCES += \
main.cpp \
diff --git a/tools/linguist/lupdate/main.cpp b/tools/linguist/lupdate/main.cpp
index 0003baa..6c9157a 100644
--- a/tools/linguist/lupdate/main.cpp
+++ b/tools/linguist/lupdate/main.cpp
@@ -409,7 +409,7 @@ static void processProjects(
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
- m_defaultExtensions = QLatin1String("ui,c,c++,cc,cpp,cxx,ch,h,h++,hh,hpp,hxx");
+ m_defaultExtensions = QLatin1String("java,jui,ui,c,c++,cc,cpp,cxx,ch,h,h++,hh,hpp,hxx,js,qs,qml");
QStringList args = app.arguments();
QStringList tsFileNames;
@@ -634,6 +634,7 @@ int main(int argc, char **argv)
sourceFiles << fn;
if (!fn.endsWith(QLatin1String(".java"))
+ && !fn.endsWith(QLatin1String(".jui"))
&& !fn.endsWith(QLatin1String(".ui"))
&& !fn.endsWith(QLatin1String(".js"))
&& !fn.endsWith(QLatin1String(".qs"))
diff --git a/tools/linguist/shared/numerus.cpp b/tools/linguist/shared/numerus.cpp
index d45dfed..6066732 100644
--- a/tools/linguist/shared/numerus.cpp
+++ b/tools/linguist/shared/numerus.cpp
@@ -64,7 +64,7 @@ static const uchar icelandicRules[] =
static const uchar irishStyleRules[] =
{ Q_EQ, 1, Q_NEWRULE,
Q_EQ, 2 };
-static const uchar slovakRules[] =
+static const uchar slovakStyleRules[] =
{ Q_EQ, 1, Q_NEWRULE,
Q_BETWEEN, 2, 4 };
static const uchar macedonianRules[] =
@@ -100,7 +100,7 @@ static const uchar arabicRules[] =
Q_EQ, 1, Q_NEWRULE,
Q_EQ, 2, Q_NEWRULE,
Q_MOD_100 | Q_BETWEEN, 3, 10, Q_NEWRULE,
- Q_MOD_100 | Q_NOT | Q_BETWEEN, 0, 2 };
+ Q_MOD_100 | Q_GEQ, 11 };
static const uchar tagalogRules[] =
{ Q_LEQ, 1, Q_NEWRULE,
Q_MOD_10 | Q_EQ, 4, Q_OR, Q_MOD_10 | Q_EQ, 6, Q_OR, Q_MOD_10 | Q_EQ, 9 };
@@ -114,7 +114,7 @@ static const char * const frenchStyleForms[] = { "Singular", "Plural", 0 };
static const char * const icelandicForms[] = { "Singular", "Plural", 0 };
static const char * const latvianForms[] = { "Singular", "Plural", "Nullar", 0 };
static const char * const irishStyleForms[] = { "Singular", "Dual", "Plural", 0 };
-static const char * const slovakForms[] = { "Singular", "Paucal", "Plural", 0 };
+static const char * const slovakStyleForms[] = { "Singular", "Paucal", "Plural", 0 };
static const char * const macedonianForms[] = { "Singular", "Dual", "Plural", 0 };
static const char * const lithuanianForms[] = { "Singular", "Paucal", "Plural", 0 };
static const char * const russianStyleForms[] = { "Singular", "Dual", "Plural", 0 };
@@ -279,7 +279,7 @@ static const QLocale::Language irishStyleLanguages[] = {
QLocale::Sanskrit,
EOL
};
-static const QLocale::Language slovakLanguages[] = { QLocale::Slovak, QLocale::Czech, EOL };
+static const QLocale::Language slovakStyleLanguages[] = { QLocale::Slovak, QLocale::Czech, EOL };
static const QLocale::Language macedonianLanguage[] = { QLocale::Macedonian, EOL };
static const QLocale::Language lithuanianLanguage[] = { QLocale::Lithuanian, EOL };
static const QLocale::Language russianStyleLanguages[] = {
@@ -318,28 +318,45 @@ struct NumerusTableEntry {
const char * const *forms;
const QLocale::Language *languages;
const QLocale::Country *countries;
+ const char * const gettextRules;
};
static const NumerusTableEntry numerusTable[] = {
- { 0, 0, japaneseStyleForms, japaneseStyleLanguages, 0 },
- { englishStyleRules, sizeof(englishStyleRules), englishStyleForms, englishStyleLanguages, 0 },
+ { 0, 0, japaneseStyleForms, japaneseStyleLanguages, 0, "nplurals=1; plural=0;" },
+ { englishStyleRules, sizeof(englishStyleRules), englishStyleForms, englishStyleLanguages, 0,
+ "nplurals=2; plural=(n != 1);" },
{ frenchStyleRules, sizeof(frenchStyleRules), frenchStyleForms, frenchStyleLanguages,
- frenchStyleCountries },
- { latvianRules, sizeof(latvianRules), latvianForms, latvianLanguage, 0 },
- { icelandicRules, sizeof(icelandicRules), icelandicForms, icelandicLanguage, 0 },
- { irishStyleRules, sizeof(irishStyleRules), irishStyleForms, irishStyleLanguages, 0 },
- { slovakRules, sizeof(slovakRules), slovakForms, slovakLanguages, 0 },
- { macedonianRules, sizeof(macedonianRules), macedonianForms, macedonianLanguage, 0 },
- { lithuanianRules, sizeof(lithuanianRules), lithuanianForms, lithuanianLanguage, 0 },
- { russianStyleRules, sizeof(russianStyleRules), russianStyleForms, russianStyleLanguages, 0 },
- { polishRules, sizeof(polishRules), polishForms, polishLanguage, 0 },
- { romanianRules, sizeof(romanianRules), romanianForms, romanianLanguages, 0 },
- { slovenianRules, sizeof(slovenianRules), slovenianForms, slovenianLanguage, 0 },
- { malteseRules, sizeof(malteseRules), malteseForms, malteseLanguage, 0 },
- { welshRules, sizeof(welshRules), welshForms, welshLanguage, 0 },
- { arabicRules, sizeof(arabicRules), arabicForms, arabicLanguage, 0 },
- { tagalogRules, sizeof(tagalogRules), tagalogForms, tagalogLanguage, 0 },
- { catalanRules, sizeof(catalanRules), catalanForms, catalanLanguage, 0 }
+ frenchStyleCountries, "nplurals=2; plural=(n > 1);" },
+ { latvianRules, sizeof(latvianRules), latvianForms, latvianLanguage, 0,
+ "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);" },
+ { icelandicRules, sizeof(icelandicRules), icelandicForms, icelandicLanguage, 0,
+ "nplurals=2; plural=(n%10==1 && n%100!=11 ? 0 : 1);" },
+ { irishStyleRules, sizeof(irishStyleRules), irishStyleForms, irishStyleLanguages, 0,
+ "nplurals=3; plural=(n==1 ? 0 : n==2 ? 1 : 2);" },
+ { slovakStyleRules, sizeof(slovakStyleRules), slovakStyleForms, slovakStyleLanguages, 0,
+ "nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2);" },
+ { macedonianRules, sizeof(macedonianRules), macedonianForms, macedonianLanguage, 0,
+ "nplurals=3; plural=(n%100==1 ? 0 : n%100==2 ? 1 : 2);" },
+ { lithuanianRules, sizeof(lithuanianRules), lithuanianForms, lithuanianLanguage, 0,
+ "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);" },
+ { russianStyleRules, sizeof(russianStyleRules), russianStyleForms, russianStyleLanguages, 0,
+ "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" },
+ { polishRules, sizeof(polishRules), polishForms, polishLanguage, 0,
+ "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" },
+ { romanianRules, sizeof(romanianRules), romanianForms, romanianLanguages, 0,
+ "nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);" },
+ { slovenianRules, sizeof(slovenianRules), slovenianForms, slovenianLanguage, 0,
+ "nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);" },
+ { malteseRules, sizeof(malteseRules), malteseForms, malteseLanguage, 0,
+ "nplurals=4; plural=(n==1 ? 0 : (n==0 || (n%100>=1 && n%100<=10)) ? 1 : (n%100>=11 && n%100<=19) ? 2 : 3);" },
+ { welshRules, sizeof(welshRules), welshForms, welshLanguage, 0,
+ "nplurals=5; plural=(n==0 ? 0 : n==1 ? 1 : (n>=2 && n<=5) ? 2 : n==6 ? 3 : 4);" },
+ { arabicRules, sizeof(arabicRules), arabicForms, arabicLanguage, 0,
+ "nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : (n%100>=3 && n%100<=10) ? 3 : n%100>=11 ? 4 : 5);" },
+ { tagalogRules, sizeof(tagalogRules), tagalogForms, tagalogLanguage, 0,
+ "nplurals=3; plural=(n==1 ? 0 : (n%10==4 || n%10==6 || n%10== 9) ? 1 : 2);" },
+ { catalanRules, sizeof(catalanRules), catalanForms, catalanLanguage, 0,
+ "nplurals=3; plural=(n==1 ? 0 : (n==11 || n/1000==11 || n/1000000==11 || n/1000000000==11) ? 1 : 2);" },
};
static const int NumerusTableSize = sizeof(numerusTable) / sizeof(numerusTable[0]);
@@ -352,7 +369,7 @@ static const uchar magic[MagicLength] = {
};
bool getNumerusInfo(QLocale::Language language, QLocale::Country country,
- QByteArray *rules, QStringList *forms)
+ QByteArray *rules, QStringList *forms, const char **gettextRules)
{
while (true) {
for (int i = 0; i < NumerusTableSize; ++i) {
@@ -365,6 +382,8 @@ bool getNumerusInfo(QLocale::Language language, QLocale::Country country,
*rules = QByteArray::fromRawData(reinterpret_cast<const char *>(entry.rules),
entry.rulesSize);
}
+ if (gettextRules)
+ *gettextRules = entry.gettextRules;
if (forms) {
forms->clear();
for (int k = 0; entry.forms[k]; ++k)
diff --git a/tools/linguist/shared/po.cpp b/tools/linguist/shared/po.cpp
index 3354d61..99a8751 100644
--- a/tools/linguist/shared/po.cpp
+++ b/tools/linguist/shared/po.cpp
@@ -45,6 +45,7 @@
#include <QtCore/QIODevice>
#include <QtCore/QHash>
#include <QtCore/QString>
+#include <QtCore/QTextCodec>
#include <QtCore/QTextStream>
#include <ctype.h>
@@ -201,55 +202,54 @@ public:
public:
- QString id;
- QString context;
- QString tscomment;
- QString oldTscomment;
- QString lineNumber;
- QString fileName;
- QString references;
- QString translatorComments;
- QString automaticComments;
- QString msgId;
- QString oldMsgId;
- QStringList msgStr;
+ QByteArray id;
+ QByteArray context;
+ QByteArray tscomment;
+ QByteArray oldTscomment;
+ QByteArray lineNumber;
+ QByteArray fileName;
+ QByteArray references;
+ QByteArray translatorComments;
+ QByteArray automaticComments;
+ QByteArray msgId;
+ QByteArray oldMsgId;
+ QList<QByteArray> msgStr;
bool isPlural;
bool isFuzzy;
QHash<QString, QString> extra;
};
-static bool isTranslationLine(const QString &line)
+static bool isTranslationLine(const QByteArray &line)
{
- return line.startsWith(QLatin1String("#~ msgstr"))
- || line.startsWith(QLatin1String("msgstr"));
+ return line.startsWith("#~ msgstr") || line.startsWith("msgstr");
}
-static QString slurpEscapedString(const QStringList &lines, int & l,
- int offset, const QString &prefix, ConversionData &cd)
+static QByteArray slurpEscapedString(const QList<QByteArray> &lines, int &l,
+ int offset, const QByteArray &prefix, ConversionData &cd)
{
- QString msg;
+ QByteArray msg;
int stoff;
for (; l < lines.size(); ++l) {
- const QString &line = lines.at(l);
+ const QByteArray &line = lines.at(l);
if (line.isEmpty() || !line.startsWith(prefix))
break;
- while (line[offset].isSpace()) // No length check, as string has no trailing spaces.
+ while (isspace(line[offset])) // No length check, as string has no trailing spaces.
offset++;
- if (line[offset].unicode() != '"')
+ if (line[offset] != '"')
break;
offset++;
forever {
if (offset == line.length())
goto premature_eol;
- ushort c = line[offset++].unicode();
+ uchar c = line[offset++];
if (c == '"') {
if (offset == line.length())
break;
- while (line[offset].isSpace())
+ while (isspace(line[offset]))
offset++;
- if (line[offset++].unicode() != '"') {
+ if (line[offset++] != '"') {
cd.appendError(QString::fromLatin1(
"PO parsing error: extra characters on line %1.")
.arg(l + 1));
@@ -260,34 +260,34 @@ static QString slurpEscapedString(const QStringList &lines, int & l,
if (c == '\\') {
if (offset == line.length())
goto premature_eol;
- c = line[offset++].unicode();
+ c = line[offset++];
switch (c) {
case 'r':
- msg += QLatin1Char('\r'); // Maybe just throw it away?
+ msg += '\r'; // Maybe just throw it away?
break;
case 'n':
- msg += QLatin1Char('\n');
+ msg += '\n';
break;
case 't':
- msg += QLatin1Char('\t');
+ msg += '\t';
break;
case 'v':
- msg += QLatin1Char('\v');
+ msg += '\v';
break;
case 'a':
- msg += QLatin1Char('\a');
+ msg += '\a';
break;
case 'b':
- msg += QLatin1Char('\b');
+ msg += '\b';
break;
case 'f':
- msg += QLatin1Char('\f');
+ msg += '\f';
break;
case '"':
- msg += QLatin1Char('"');
+ msg += '"';
break;
case '\\':
- msg += QLatin1Char('\\');
+ msg += '\\';
break;
case '0':
case '1':
@@ -298,28 +298,28 @@ static QString slurpEscapedString(const QStringList &lines, int & l,
case '6':
case '7':
stoff = offset - 1;
- while ((c = line[offset].unicode()) >= '0' && c <= '7')
+ while ((c = line[offset]) >= '0' && c <= '7')
if (++offset == line.length())
goto premature_eol;
- msg += QChar(line.mid(stoff, offset - stoff).toUInt(0, 8));
+ msg += line.mid(stoff, offset - stoff).toUInt(0, 8);
break;
case 'x':
stoff = offset;
- while (isxdigit(line[offset].unicode()))
+ while (isxdigit(line[offset]))
if (++offset == line.length())
goto premature_eol;
- msg += QChar(line.mid(stoff, offset - stoff).toUInt(0, 16));
+ msg += line.mid(stoff, offset - stoff).toUInt(0, 16);
break;
default:
cd.appendError(QString::fromLatin1(
"PO parsing error: invalid escape '\\%1' (line %2).")
- .arg(QChar(c)).arg(l + 1));
- msg += QLatin1Char('\\');
- msg += QChar(c);
+ .arg(QChar((uint)c)).arg(l + 1));
+ msg += '\\';
+ msg += c;
break;
}
} else {
- msg += QChar(c);
+ msg += c;
}
}
offset = prefix.size();
@@ -330,36 +330,61 @@ static QString slurpEscapedString(const QStringList &lines, int & l,
premature_eol:
cd.appendError(QString::fromLatin1(
"PO parsing error: premature end of line %1.").arg(l + 1));
- return QString();
+ return QByteArray();
}
-static void slurpComment(QString &msg, const QStringList &lines, int & l)
+static void slurpComment(QByteArray &msg, const QList<QByteArray> &lines, int & l)
{
- const QChar newline = QLatin1Char('\n');
- QString prefix = lines.at(l);
+ QByteArray prefix = lines.at(l);
for (int i = 1; ; i++) {
- if (prefix.at(i).unicode() != ' ') {
+ if (prefix.at(i) != ' ') {
prefix.truncate(i);
break;
}
}
for (; l < lines.size(); ++l) {
- const QString &line = lines.at(l);
+ const QByteArray &line = lines.at(l);
if (line.startsWith(prefix))
msg += line.mid(prefix.size());
- else if (line != QLatin1String("#"))
+ else if (line != "#")
break;
- msg += newline;
+ msg += '\n';
}
--l;
}
+static QString makePoHeader(const QString &str)
+{
+ return QLatin1String("po-header-") + str.toLower().replace(QLatin1Char('-'), QLatin1Char('_'));
+}
+
+static QByteArray QByteArrayList_join(const QList<QByteArray> &that, char sep)
+{
+ int totalLength = 0;
+ const int size = that.size();
+
+ for (int i = 0; i < size; ++i)
+ totalLength += that.at(i).size();
+
+ if (size > 0)
+ totalLength += size - 1;
+
+ QByteArray res;
+ if (totalLength == 0)
+ return res;
+ res.reserve(totalLength);
+ for (int i = 0; i < that.size(); ++i) {
+ if (i)
+ res += sep;
+ res += that.at(i);
+ }
+ return res;
+}
+
bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd)
{
- const QChar quote = QLatin1Char('"');
- const QChar newline = QLatin1Char('\n');
- QTextStream in(&dev);
- in.setCodec(cd.m_codecForSource.isEmpty() ? QByteArray("UTF-8") : cd.m_codecForSource);
+ QTextCodec *codec = QTextCodec::codecForName(
+ cd.m_codecForSource.isEmpty() ? QByteArray("UTF-8") : cd.m_codecForSource);
bool error = false;
// format of a .po file entry:
@@ -380,25 +405,23 @@ bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd)
// ...
// we need line based lookahead below.
- QStringList lines;
- while (!in.atEnd())
- lines.append(in.readLine().trimmed());
- lines.append(QString());
+ QList<QByteArray> lines;
+ while (!dev.atEnd())
+ lines.append(dev.readLine().trimmed());
+ lines.append(QByteArray());
- int l = 0;
+ int l = 0, lastCmtLine = -1;
PoItem item;
for (; l != lines.size(); ++l) {
- QString line = lines.at(l);
+ QByteArray line = lines.at(l);
if (line.isEmpty())
continue;
if (isTranslationLine(line)) {
- bool isObsolete = line.startsWith(QLatin1String("#~ msgstr"));
- const QString prefix = QLatin1String(isObsolete ? "#~ " : "");
+ bool isObsolete = line.startsWith("#~ msgstr");
+ const QByteArray prefix = isObsolete ? "#~ " : "";
while (true) {
- int idx = line.indexOf(QLatin1Char(' '), prefix.length());
- QString str = slurpEscapedString(lines, l, idx, prefix, cd);
- str.replace(QChar(Translator::TextVariantSeparator),
- QChar(Translator::BinaryVariantSeparator));
+ int idx = line.indexOf(' ', prefix.length());
+ QByteArray str = slurpEscapedString(lines, l, idx, prefix, cd);
item.msgStr.append(str);
if (l + 1 >= lines.size() || !isTranslationLine(lines.at(l + 1)))
break;
@@ -406,31 +429,109 @@ bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd)
line = lines.at(l);
}
if (item.msgId.isEmpty()) {
- QRegExp rx(QLatin1String("\\bX-Language: ([^\n]*)\n"));
- int idx = rx.indexIn(item.msgStr.first());
- if (idx >= 0) {
- translator.setLanguageCode(rx.cap(1));
- item.msgStr.first().remove(idx, rx.matchedLength());
+ QHash<QString, QByteArray> extras;
+ QList<QByteArray> hdrOrder;
+ QByteArray pluralForms;
+ foreach (const QByteArray &hdr, item.msgStr.first().split('\n')) {
+ if (hdr.isEmpty())
+ continue;
+ int idx = hdr.indexOf(':');
+ if (idx < 0) {
+ cd.appendError(QString::fromLatin1("Unexpected PO header format '%1'\n")
+ .arg(QString::fromLatin1(hdr)));
+ error = true;
+ break;
+ }
+ QByteArray hdrName = hdr.left(idx).trimmed();
+ QByteArray hdrValue = hdr.mid(idx + 1).trimmed();
+ hdrOrder << hdrName;
+ if (hdrName == "X-Language") {
+ translator.setLanguageCode(QString::fromLatin1(hdrValue));
+ } else if (hdrName == "X-Source-Language") {
+ translator.setSourceLanguageCode(QString::fromLatin1(hdrValue));
+ } else if (hdrName == "Plural-Forms") {
+ pluralForms = hdrValue;
+ } else if (hdrName == "MIME-Version") {
+ // just assume it is 1.0
+ } else if (hdrName == "Content-Type") {
+ if (cd.m_codecForSource.isEmpty()) {
+ if (!hdrValue.startsWith("text/plain; charset=")) {
+ cd.appendError(QString::fromLatin1("Unexpected Content-Type header '%1'\n")
+ .arg(QString::fromLatin1(hdrValue)));
+ error = true;
+ // This will avoid a flood of conversion errors.
+ codec = QTextCodec::codecForName("latin1");
+ } else {
+ QByteArray cod = hdrValue.mid(20);
+ QTextCodec *cdc = QTextCodec::codecForName(cod);
+ if (!cdc) {
+ cd.appendError(QString::fromLatin1("Unsupported codec '%1'\n")
+ .arg(QString::fromLatin1(cod)));
+ error = true;
+ // This will avoid a flood of conversion errors.
+ codec = QTextCodec::codecForName("latin1");
+ } else {
+ codec = cdc;
+ }
+ }
+ }
+ } else if (hdrName == "Content-Transfer-Encoding") {
+ if (hdrValue != "8bit") {
+ cd.appendError(QString::fromLatin1("Unexpected Content-Transfer-Encoding '%1'\n")
+ .arg(QString::fromLatin1(hdrValue)));
+ return false;
+ }
+ } else if (hdrName == "X-Virgin-Header") {
+ // legacy
+ } else {
+ extras[makePoHeader(QString::fromLatin1(hdrName))] = hdrValue;
+ }
}
- QRegExp rx2(QLatin1String("\\bX-Source-Language: ([^\n]*)\n"));
- int idx2 = rx2.indexIn(item.msgStr.first());
- if (idx2 >= 0) {
- translator.setSourceLanguageCode(rx2.cap(1));
- item.msgStr.first().remove(idx2, rx2.matchedLength());
+ if (!pluralForms.isEmpty()) {
+ if (translator.languageCode().isEmpty()) {
+ extras[makePoHeader(QLatin1String("Plural-Forms"))] = pluralForms;
+ } else {
+ // FIXME: have fun with making a consistency check ...
+ }
}
- if (item.msgStr.first().indexOf(
- QRegExp(QLatin1String("\\bX-Virgin-Header:[^\n]*\n"))) >= 0) {
- item = PoItem();
- continue;
+ // Eliminate the field if only headers we added are present in standard order.
+ // Keep in sync with savePO
+ static const char * const dfltHdrs[] = {
+ "MIME-Version", "Content-Type", "Content-Transfer-Encoding",
+ "Plural-Forms", "X-Language", "X-Source-Language"
+ };
+ uint cdh = 0;
+ for (int cho = 0; cho < hdrOrder.length(); cho++) {
+ for (;; cdh++) {
+ if (cdh == sizeof(dfltHdrs)/sizeof(dfltHdrs[0])) {
+ extras[QLatin1String("po-headers")] =
+ QByteArrayList_join(hdrOrder, ',');
+ goto doneho;
+ }
+ if (hdrOrder.at(cho) == dfltHdrs[cdh]) {
+ cdh++;
+ break;
+ }
+ }
}
+ doneho:
+ if (lastCmtLine != -1)
+ extras[QLatin1String("po-header_comment")] =
+ QByteArrayList_join(lines.mid(0, lastCmtLine + 1), '\n');
+ for (QHash<QString, QByteArray>::ConstIterator it = extras.constBegin(),
+ end = extras.constEnd();
+ it != end; ++it)
+ translator.setExtra(it.key(), codec->toUnicode(it.value()));
+ item = PoItem();
+ continue;
}
// build translator message
TranslatorMessage msg;
- msg.setContext(item.context);
+ msg.setContext(codec->toUnicode(item.context));
if (!item.references.isEmpty()) {
foreach (const QString &ref,
- item.references.split(QRegExp(QLatin1String("\\s")),
- QString::SkipEmptyParts)) {
+ codec->toUnicode(item.references).split(
+ QRegExp(QLatin1String("\\s")), QString::SkipEmptyParts)) {
int pos = ref.lastIndexOf(QLatin1Char(':'));
if (pos != -1)
msg.addReference(ref.left(pos), ref.mid(pos + 1).toInt());
@@ -438,18 +539,25 @@ bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd)
} else if (isObsolete) {
msg.setFileName(QLatin1String(MAGIC_OBSOLETE_REFERENCE));
}
- msg.setId(item.id);
- msg.setSourceText(item.msgId);
- msg.setOldSourceText(item.oldMsgId);
- msg.setComment(item.tscomment);
- msg.setOldComment(item.oldTscomment);
- msg.setExtraComment(item.automaticComments);
- msg.setTranslatorComment(item.translatorComments);
+ msg.setId(codec->toUnicode(item.id));
+ msg.setSourceText(codec->toUnicode(item.msgId));
+ msg.setOldSourceText(codec->toUnicode(item.oldMsgId));
+ msg.setComment(codec->toUnicode(item.tscomment));
+ msg.setOldComment(codec->toUnicode(item.oldTscomment));
+ msg.setExtraComment(codec->toUnicode(item.automaticComments));
+ msg.setTranslatorComment(codec->toUnicode(item.translatorComments));
msg.setPlural(item.isPlural || item.msgStr.size() > 1);
- msg.setTranslations(item.msgStr);
+ QStringList translations;
+ foreach (const QByteArray &bstr, item.msgStr) {
+ QString str = codec->toUnicode(bstr);
+ str.replace(QChar(Translator::TextVariantSeparator),
+ QChar(Translator::BinaryVariantSeparator));
+ translations << str;
+ }
+ msg.setTranslations(translations);
if (isObsolete)
msg.setType(TranslatorMessage::Obsolete);
- else if (item.isFuzzy)
+ else if (item.isFuzzy || (!msg.sourceText().isEmpty() && !msg.isTranslated()))
msg.setType(TranslatorMessage::Unfinished);
else
msg.setType(TranslatorMessage::Finished);
@@ -460,18 +568,19 @@ bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd)
//qDebug() << flags << msg.m_extra;
translator.append(msg);
item = PoItem();
- } else if (line.startsWith(QLatin1Char('#'))) {
- switch(line.size() < 2 ? 0 : line.at(1).unicode()) {
+ } else if (line.startsWith('#')) {
+ switch (line.size() < 2 ? 0 : line.at(1)) {
case ':':
item.references += line.mid(3);
- item.references += newline;
+ item.references += '\n';
break;
case ',': {
QStringList flags =
- line.mid(2).split(QRegExp(QLatin1String("[, ]")),
- QString::SkipEmptyParts);
+ QString::fromLatin1(line.mid(2)).split(
+ QRegExp(QLatin1String("[, ]")), QString::SkipEmptyParts);
if (flags.removeOne(QLatin1String("fuzzy")))
item.isFuzzy = true;
+ flags.removeOne(QLatin1String("qt-format"));
TranslatorMessage::ExtraData::const_iterator it =
item.extra.find(QLatin1String("po-flags"));
if (it != item.extra.end())
@@ -481,103 +590,130 @@ bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd)
break;
}
case 0:
- item.translatorComments += newline;
+ item.translatorComments += '\n';
break;
case ' ':
slurpComment(item.translatorComments, lines, l);
break;
case '.':
- if (line.startsWith(QLatin1String("#. ts-context "))) {
+ if (line.startsWith("#. ts-context ")) {
item.context = line.mid(14);
- } else if (line.startsWith(QLatin1String("#. ts-id "))) {
+ } else if (line.startsWith("#. ts-id ")) {
item.id = line.mid(9);
} else {
item.automaticComments += line.mid(3);
- item.automaticComments += newline;
+ item.automaticComments += '\n';
}
break;
case '|':
- if (line.startsWith(QLatin1String("#| msgid "))) {
- item.oldMsgId = slurpEscapedString(lines, l, 9, QLatin1String("#| "), cd);
- } else if (line.startsWith(QLatin1String("#| msgid_plural "))) {
- QString extra = slurpEscapedString(lines, l, 16, QLatin1String("#| "), cd);
+ if (line.startsWith("#| msgid ")) {
+ item.oldMsgId = slurpEscapedString(lines, l, 9, "#| ", cd);
+ } else if (line.startsWith("#| msgid_plural ")) {
+ QByteArray extra = slurpEscapedString(lines, l, 16, "#| ", cd);
if (extra != item.oldMsgId)
- item.extra[QLatin1String("po-old_msgid_plural")] = extra;
- } else if (line.startsWith(QLatin1String("#| msgctxt "))) {
- item.oldTscomment = slurpEscapedString(lines, l, 11, QLatin1String("#| "), cd);
+ item.extra[QLatin1String("po-old_msgid_plural")] =
+ codec->toUnicode(extra);
+ } else if (line.startsWith("#| msgctxt ")) {
+ item.oldTscomment = slurpEscapedString(lines, l, 11, "#| ", cd);
} else {
cd.appendError(QString(QLatin1String("PO-format parse error in line %1: '%2'\n"))
- .arg(l + 1).arg(lines[l]));
+ .arg(l + 1).arg(codec->toUnicode(lines[l])));
error = true;
}
break;
case '~':
- if (line.startsWith(QLatin1String("#~ msgid "))) {
- item.msgId = slurpEscapedString(lines, l, 9, QLatin1String("#~ "), cd);
- } else if (line.startsWith(QLatin1String("#~ msgid_plural "))) {
- QString extra = slurpEscapedString(lines, l, 16, QLatin1String("#~ "), cd);
+ if (line.startsWith("#~ msgid ")) {
+ item.msgId = slurpEscapedString(lines, l, 9, "#~ ", cd);
+ } else if (line.startsWith("#~ msgid_plural ")) {
+ QByteArray extra = slurpEscapedString(lines, l, 16, "#~ ", cd);
if (extra != item.msgId)
- item.extra[QLatin1String("po-msgid_plural")] = extra;
+ item.extra[QLatin1String("po-msgid_plural")] =
+ codec->toUnicode(extra);
item.isPlural = true;
- } else if (line.startsWith(QLatin1String("#~ msgctxt "))) {
- item.tscomment = slurpEscapedString(lines, l, 11, QLatin1String("#~ "), cd);
+ } else if (line.startsWith("#~ msgctxt ")) {
+ item.tscomment = slurpEscapedString(lines, l, 11, "#~ ", cd);
} else {
cd.appendError(QString(QLatin1String("PO-format parse error in line %1: '%2'\n"))
- .arg(l + 1).arg(lines[l]));
+ .arg(l + 1).arg(codec->toUnicode(lines[l])));
error = true;
}
break;
default:
cd.appendError(QString(QLatin1String("PO-format parse error in line %1: '%2'\n"))
- .arg(l + 1).arg(lines[l]));
+ .arg(l + 1).arg(codec->toUnicode(lines[l])));
error = true;
break;
}
- } else if (line.startsWith(QLatin1String("msgctxt "))) {
- item.tscomment = slurpEscapedString(lines, l, 8, QString(), cd);
- } else if (line.startsWith(QLatin1String("msgid "))) {
- item.msgId = slurpEscapedString(lines, l, 6, QString(), cd);
- } else if (line.startsWith(QLatin1String("msgid_plural "))) {
- QString extra = slurpEscapedString(lines, l, 13, QString(), cd);
+ lastCmtLine = l;
+ } else if (line.startsWith("msgctxt ")) {
+ item.tscomment = slurpEscapedString(lines, l, 8, QByteArray(), cd);
+ } else if (line.startsWith("msgid ")) {
+ item.msgId = slurpEscapedString(lines, l, 6, QByteArray(), cd);
+ } else if (line.startsWith("msgid_plural ")) {
+ QByteArray extra = slurpEscapedString(lines, l, 13, QByteArray(), cd);
if (extra != item.msgId)
- item.extra[QLatin1String("po-msgid_plural")] = extra;
+ item.extra[QLatin1String("po-msgid_plural")] = codec->toUnicode(extra);
item.isPlural = true;
} else {
cd.appendError(QString(QLatin1String("PO-format error in line %1: '%2'\n"))
- .arg(l + 1).arg(lines[l]));
+ .arg(l + 1).arg(codec->toUnicode(lines[l])));
error = true;
}
}
return !error && cd.errors().isEmpty();
}
+static void addPoHeader(Translator::ExtraData &headers, QStringList &hdrOrder,
+ const char *name, const QString &value)
+{
+ QString qName = QLatin1String(name);
+ if (!hdrOrder.contains(qName))
+ hdrOrder << qName;
+ headers[makePoHeader(qName)] = value;
+}
+
bool savePO(const Translator &translator, QIODevice &dev, ConversionData &cd)
{
+ QString str_format = QLatin1String("-format");
+
bool ok = true;
QTextStream out(&dev);
out.setCodec(cd.m_outputCodec.isEmpty() ? QByteArray("UTF-8") : cd.m_outputCodec);
- bool first = true;
- if (translator.messages().isEmpty() || !translator.messages().first().sourceText().isEmpty()) {
- out <<
- "# SOME DESCRIPTIVE TITLE.\n"
- "# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n"
- "# This file is distributed under the same license as the PACKAGE package.\n"
- "# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n"
- "#\n"
- "#, fuzzy\n"
- "msgid \"\"\n"
- "msgstr \"\"\n"
- "\"X-Virgin-Header: remove this line if you change anything in the header.\\n\"\n";
- if (!translator.languageCode().isEmpty())
- out << "\"X-Language: " << translator.languageCode() << "\\n\"\n";
- if (!translator.sourceLanguageCode().isEmpty())
- out << "\"X-Source-Language: " << translator.sourceLanguageCode() << "\\n\"\n";
- first = false;
+ QString cmt = translator.extra(QLatin1String("po-header_comment"));
+ if (!cmt.isEmpty())
+ out << cmt << '\n';
+ out << "msgid \"\"\n";
+ Translator::ExtraData headers = translator.extras();
+ QStringList hdrOrder = translator.extra(QLatin1String("po-headers")).split(
+ QLatin1Char(','), QString::SkipEmptyParts);
+ // Keep in sync with loadPO
+ addPoHeader(headers, hdrOrder, "MIME-Version", QLatin1String("1.0"));
+ addPoHeader(headers, hdrOrder, "Content-Type",
+ QLatin1String("text/plain; charset=" + out.codec()->name()));
+ addPoHeader(headers, hdrOrder, "Content-Transfer-Encoding", QLatin1String("8bit"));
+ if (!translator.languageCode().isEmpty()) {
+ QLocale::Language l;
+ QLocale::Country c;
+ Translator::languageAndCountry(translator.languageCode(), &l, &c);
+ const char *gettextRules;
+ if (getNumerusInfo(l, c, 0, 0, &gettextRules))
+ addPoHeader(headers, hdrOrder, "Plural-Forms", QLatin1String(gettextRules));
+ addPoHeader(headers, hdrOrder, "X-Language", translator.languageCode());
}
+ if (!translator.sourceLanguageCode().isEmpty())
+ addPoHeader(headers, hdrOrder, "X-Source-Language", translator.sourceLanguageCode());
+ QString hdrStr;
+ foreach (const QString &hdr, hdrOrder) {
+ hdrStr += hdr;
+ hdrStr += QLatin1String(": ");
+ hdrStr += headers.value(makePoHeader(hdr));
+ hdrStr += QLatin1Char('\n');
+ }
+ out << poEscapedString(QString(), QString::fromLatin1("msgstr"), true, hdrStr);
+
foreach (const TranslatorMessage &msg, translator.messages()) {
- if (!first)
- out << endl;
+ out << endl;
if (!msg.translatorComment().isEmpty())
out << poEscapedLines(QLatin1String("#"), true, msg.translatorComment());
@@ -599,16 +735,36 @@ bool savePO(const Translator &translator, QIODevice &dev, ConversionData &cd)
}
bool noWrap = false;
+ bool skipFormat = false;
QStringList flags;
- if (msg.type() == TranslatorMessage::Unfinished)
+ if (msg.type() == TranslatorMessage::Unfinished && msg.isTranslated())
flags.append(QLatin1String("fuzzy"));
TranslatorMessage::ExtraData::const_iterator itr =
msg.extras().find(QLatin1String("po-flags"));
if (itr != msg.extras().end()) {
- if (itr->split(QLatin1String(", ")).contains(QLatin1String("no-wrap")))
+ QStringList atoms = itr->split(QLatin1String(", "));
+ foreach (const QString &atom, atoms)
+ if (atom.endsWith(str_format)) {
+ skipFormat = true;
+ break;
+ }
+ if (atoms.contains(QLatin1String("no-wrap")))
noWrap = true;
flags.append(*itr);
}
+ if (!skipFormat) {
+ QString source = msg.sourceText();
+ // This is fuzzy logic, as we don't know whether the string is
+ // actually used with QString::arg().
+ for (int off = 0; (off = source.indexOf(QLatin1Char('%'), off)) >= 0; ) {
+ if (++off >= source.length())
+ break;
+ if (source.at(off) == QLatin1Char('n') || source.at(off).isDigit()) {
+ flags.append(QLatin1String("qt-format"));
+ break;
+ }
+ }
+ }
if (!flags.isEmpty())
out << "#, " << flags.join(QLatin1String(", ")) << '\n';
@@ -626,11 +782,8 @@ bool savePO(const Translator &translator, QIODevice &dev, ConversionData &cd)
out << poEscapedString(prefix, QLatin1String("msgid"), noWrap, msg.sourceText());
if (!msg.isPlural()) {
QString transl = msg.translation();
- if (first) {
- transl.remove(QRegExp(QLatin1String("\\bX-Language:[^\n]*\n")));
- if (!translator.languageCode().isEmpty())
- transl += QLatin1String("X-Language: ") + translator.languageCode() + QLatin1Char('\n');
- }
+ transl.replace(QChar(Translator::BinaryVariantSeparator),
+ QChar(Translator::TextVariantSeparator));
out << poEscapedString(prefix, QLatin1String("msgstr"), noWrap, transl);
} else {
QString plural = msg.extra(QLatin1String("po-msgid_plural"));
@@ -646,11 +799,17 @@ bool savePO(const Translator &translator, QIODevice &dev, ConversionData &cd)
str);
}
}
- first = false;
}
return ok;
}
+static bool savePOT(const Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ Translator ttor = translator;
+ ttor.dropTranslations();
+ return savePO(ttor, dev, cd);
+}
+
int initPO()
{
Translator::FileFormat format;
@@ -661,6 +820,13 @@ int initPO()
format.fileType = Translator::FileFormat::TranslationSource;
format.priority = 1;
Translator::registerFileFormat(format);
+ format.extension = QLatin1String("pot");
+ format.description = QObject::tr("GNU Gettext localization template files");
+ format.loader = &loadPO;
+ format.saver = &savePOT;
+ format.fileType = Translator::FileFormat::TranslationSource;
+ format.priority = -1;
+ Translator::registerFileFormat(format);
return 1;
}
diff --git a/tools/linguist/shared/qm.cpp b/tools/linguist/shared/qm.cpp
index de1284f..e2c4f4a 100644
--- a/tools/linguist/shared/qm.cpp
+++ b/tools/linguist/shared/qm.cpp
@@ -564,7 +564,7 @@ bool loadQM(Translator &translator, QIODevice &dev, ConversionData &cd)
Translator::languageAndCountry(translator.languageCode(), &l, &c);
QStringList numerusForms;
bool guessPlurals = true;
- if (getNumerusInfo(l, c, 0, &numerusForms))
+ if (getNumerusInfo(l, c, 0, &numerusForms, 0))
guessPlurals = (numerusForms.count() == 1);
QString context, contextUtf8;
@@ -704,7 +704,7 @@ static bool saveQM(const Translator &translator, QIODevice &dev, ConversionData
QLocale::Country c;
Translator::languageAndCountry(translator.languageCode(), &l, &c);
QByteArray rules;
- if (getNumerusInfo(l, c, &rules, 0))
+ if (getNumerusInfo(l, c, &rules, 0, 0))
releaser.setNumerusRules(rules);
releaser.setCodecName(translator.codecName());
diff --git a/tools/linguist/shared/translator.cpp b/tools/linguist/shared/translator.cpp
index 4331ce6..c86a9dd 100644
--- a/tools/linguist/shared/translator.cpp
+++ b/tools/linguist/shared/translator.cpp
@@ -45,8 +45,13 @@
#include <stdio.h>
#ifdef Q_OS_WIN
-#include <io.h> // required for _setmode, to avoid _O_TEXT streams...
-#include <fcntl.h> // for _O_BINARY
+// required for _setmode, to avoid _O_TEXT streams...
+# ifdef Q_OS_WINCE
+# include <stdlib.h>
+# else
+# include <io.h> // for _setmode
+# include <fcntl.h> // for _O_BINARY
+# endif
#endif
#include <QtCore/QDebug>
@@ -213,7 +218,11 @@ bool Translator::load(const QString &filename, ConversionData &cd, const QString
if (filename.isEmpty() || filename == QLatin1String("-")) {
#ifdef Q_OS_WIN
// QFile is broken for text files
+# ifdef Q_OS_WINCE
+ ::_setmode(stdin, _O_BINARY);
+# else
::_setmode(0, _O_BINARY);
+# endif
#endif
if (!file.open(stdin, QIODevice::ReadOnly)) {
cd.appendError(QString::fromLatin1("Cannot open stdin!? (%1)")
@@ -253,7 +262,11 @@ bool Translator::save(const QString &filename, ConversionData &cd, const QString
if (filename.isEmpty() || filename == QLatin1String("-")) {
#ifdef Q_OS_WIN
// QFile is broken for text files
+# ifdef Q_OS_WINCE
+ ::_setmode(stdout, _O_BINARY);
+# else
::_setmode(1, _O_BINARY);
+# endif
#endif
if (!file.open(stdout, QIODevice::WriteOnly)) {
cd.appendError(QString::fromLatin1("Cannot open stdout!? (%1)")
@@ -652,7 +665,7 @@ void Translator::normalizeTranslations(ConversionData &cd)
int numPlurals = 1;
if (l != QLocale::C) {
QStringList forms;
- if (getNumerusInfo(l, c, 0, &forms))
+ if (getNumerusInfo(l, c, 0, &forms, 0))
numPlurals = forms.count(); // includes singular
}
for (int i = 0; i < m_messages.count(); ++i) {
diff --git a/tools/linguist/shared/translator.h b/tools/linguist/shared/translator.h
index 0b88c07..bb199f0 100644
--- a/tools/linguist/shared/translator.h
+++ b/tools/linguist/shared/translator.h
@@ -233,7 +233,7 @@ private:
};
bool getNumerusInfo(QLocale::Language language, QLocale::Country country,
- QByteArray *rules, QStringList *forms);
+ QByteArray *rules, QStringList *forms, const char **gettextRules);
/*
This is a quick hack. The proper way to handle this would be
diff --git a/tools/linguist/shared/xliff.cpp b/tools/linguist/shared/xliff.cpp
index 20303ec..6411426 100644
--- a/tools/linguist/shared/xliff.cpp
+++ b/tools/linguist/shared/xliff.cpp
@@ -503,6 +503,8 @@ bool XLIFFHandler::startElement(const QString& namespaceURI,
m_language.replace(QLatin1Char('-'), QLatin1Char('_'));
m_sourceLanguage = atts.value(QLatin1String("source-language"));
m_sourceLanguage.replace(QLatin1Char('-'), QLatin1Char('_'));
+ if (m_sourceLanguage == QLatin1String("en"))
+ m_sourceLanguage.clear();
} else if (localName == QLatin1String("group")) {
if (atts.value(QLatin1String("restype")) == QLatin1String(restypeContext)) {
m_context = atts.value(QLatin1String("resname"));
diff --git a/tools/qdbus/qdbus.pro b/tools/qdbus/qdbus.pro
index 01cd246..a264882 100644
--- a/tools/qdbus/qdbus.pro
+++ b/tools/qdbus/qdbus.pro
@@ -1,2 +1,3 @@
TEMPLATE = subdirs
-SUBDIRS = qdbus qdbusxml2cpp qdbuscpp2xml qdbusviewer
+SUBDIRS = qdbus qdbusxml2cpp qdbuscpp2xml
+!contains(QT_CONFIG, no-gui): SUBDIRS += qdbusviewer
diff --git a/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp b/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp
index 8251e2c..d9343e3 100644
--- a/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp
+++ b/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp
@@ -53,14 +53,9 @@
#include "private/qdbusmetaobject_p.h"
#include "private/qdbusintrospection_p.h"
-#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
-#ifdef Q_WS_WIN
-#include <process.h>
-#endif
-
#define PROGRAMNAME "qdbusxml2cpp"
#define PROGRAMVERSION "0.7"
#define PROGRAMCOPYRIGHT "Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)."
diff --git a/tools/qdoc3/codemarker.cpp b/tools/qdoc3/codemarker.cpp
index 15f2c2d..818a91f 100644
--- a/tools/qdoc3/codemarker.cpp
+++ b/tools/qdoc3/codemarker.cpp
@@ -457,7 +457,7 @@ bool CodeMarker::insertReimpFunc(FastSection& fs, Node* node, Status status)
void CodeMarker::append(QList<Section>& sectionList, const FastSection& fs)
{
if (!fs.isEmpty()) {
- Section section(fs.name,fs.singularMember,fs.pluralMember);
+ Section section(fs.name,fs.divClass,fs.singularMember,fs.pluralMember);
section.members = fs.memberMap.values();
section.reimpMembers = fs.reimpMemberMap.values();
section.inherited = fs.inherited;
diff --git a/tools/qdoc3/codemarker.h b/tools/qdoc3/codemarker.h
index 1b21753..aab8a9c 100644
--- a/tools/qdoc3/codemarker.h
+++ b/tools/qdoc3/codemarker.h
@@ -58,6 +58,7 @@ class Tree;
struct Section
{
QString name;
+ QString divClass;
QString singularMember;
QString pluralMember;
NodeList members;
@@ -66,9 +67,11 @@ struct Section
Section() { }
Section(const QString& name0,
+ const QString& divClass0,
const QString& singularMember0,
const QString& pluralMember0)
- : name(name0),
+ : name(name0),
+ divClass(divClass0),
singularMember(singularMember0),
pluralMember(pluralMember0) { }
void appendMember(Node* node) { members.append(node); }
@@ -79,6 +82,7 @@ struct FastSection
{
const InnerNode *innerNode;
QString name;
+ QString divClass;
QString singularMember;
QString pluralMember;
QMap<QString, Node *> memberMap;
@@ -86,20 +90,30 @@ struct FastSection
QList<QPair<ClassNode *, int> > inherited;
FastSection(const InnerNode *innerNode0,
- const QString& name0 = "",
- const QString& singularMember0 = "member",
- const QString& pluralMember0 = "members")
+ const QString& name0,
+ const QString& divClass0,
+ const QString& singularMember0,
+ const QString& pluralMember0)
: innerNode(innerNode0),
name(name0),
+ divClass(divClass0),
singularMember(singularMember0),
pluralMember(pluralMember0) { }
bool isEmpty() const {
- return (memberMap.isEmpty() && inherited.isEmpty() &&
+ return (memberMap.isEmpty() &&
+ inherited.isEmpty() &&
reimpMemberMap.isEmpty());
}
};
+#if 0
+ const QString& name0 = "",
+ const QString& divClass0 = "",
+ const QString& singularMember0 = "member",
+ const QString& pluralMember0 = "members")
+#endif
+
class CodeMarker
{
public:
diff --git a/tools/qdoc3/config.cpp b/tools/qdoc3/config.cpp
index 3150f28..4d1c378 100644
--- a/tools/qdoc3/config.cpp
+++ b/tools/qdoc3/config.cpp
@@ -528,8 +528,11 @@ QString Config::findFile(const Location& location,
{
QStringList::ConstIterator e = fileExtensions.begin();
while (e != fileExtensions.end()) {
- QString filePath = findFile(location, files, dirs, fileBase + "." + *e,
- userFriendlyFilePath);
+ QString filePath = findFile(location,
+ files,
+ dirs,
+ fileBase + "." + *e,
+ userFriendlyFilePath);
if (!filePath.isEmpty())
return filePath;
++e;
diff --git a/tools/qdoc3/config.h b/tools/qdoc3/config.h
index 6f23469..980d1fb 100644
--- a/tools/qdoc3/config.h
+++ b/tools/qdoc3/config.h
@@ -149,12 +149,16 @@ class Config
#define CONFIG_PROJECT "project"
#define CONFIG_QHP "qhp"
#define CONFIG_QUOTINGINFORMATION "quotinginformation"
+#define CONFIG_SCRIPTDIRS "scriptdirs"
+#define CONFIG_SCRIPTS "scripts"
#define CONFIG_SLOW "slow"
#define CONFIG_SHOWINTERNAL "showinternal"
#define CONFIG_SOURCEDIRS "sourcedirs"
#define CONFIG_SOURCEENCODING "sourceencoding"
#define CONFIG_SOURCES "sources"
#define CONFIG_SPURIOUS "spurious"
+#define CONFIG_STYLEDIRS "styledirs"
+#define CONFIG_STYLES "styles"
#define CONFIG_STYLESHEETS "stylesheets"
#define CONFIG_TABSIZE "tabsize"
#define CONFIG_TAGFILE "tagfile"
diff --git a/tools/qdoc3/cppcodemarker.cpp b/tools/qdoc3/cppcodemarker.cpp
index 3ff6ebe..c4ee054 100644
--- a/tools/qdoc3/cppcodemarker.cpp
+++ b/tools/qdoc3/cppcodemarker.cpp
@@ -482,55 +482,66 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
if (style == Summary) {
FastSection privateFunctions(classe,
"Private Functions",
+ "",
"private function",
"private functions");
- FastSection privateSlots(classe, "Private Slots", "private slot", "private slots");
- FastSection privateTypes(classe, "Private Types", "private type", "private types");
+ FastSection privateSlots(classe, "Private Slots", "", "private slot", "private slots");
+ FastSection privateTypes(classe, "Private Types", "", "private type", "private types");
FastSection protectedFunctions(classe,
"Protected Functions",
+ "",
"protected function",
"protected functions");
FastSection protectedSlots(classe,
"Protected Slots",
+ "",
"protected slot",
"protected slots");
FastSection protectedTypes(classe,
"Protected Types",
+ "",
"protected type",
"protected types");
FastSection protectedVariables(classe,
"Protected Variables",
+ "",
"protected type",
"protected variables");
FastSection publicFunctions(classe,
"Public Functions",
+ "",
"public function",
"public functions");
- FastSection publicSignals(classe, "Signals", "signal", "signals");
- FastSection publicSlots(classe, "Public Slots", "public slot", "public slots");
- FastSection publicTypes(classe, "Public Types", "public type", "public types");
+ FastSection publicSignals(classe, "Signals", "", "signal", "signals");
+ FastSection publicSlots(classe, "Public Slots", "", "public slot", "public slots");
+ FastSection publicTypes(classe, "Public Types", "", "public type", "public types");
FastSection publicVariables(classe,
"Public Variables",
- "public type",
+ "",
+ "public variable",
"public variables");
- FastSection properties(classe, "Properties", "property", "properties");
+ FastSection properties(classe, "Properties", "", "property", "properties");
FastSection relatedNonMembers(classe,
"Related Non-Members",
+ "",
"related non-member",
"related non-members");
FastSection staticPrivateMembers(classe,
"Static Private Members",
+ "",
"static private member",
"static private members");
FastSection staticProtectedMembers(classe,
"Static Protected Members",
+ "",
"static protected member",
"static protected members");
FastSection staticPublicMembers(classe,
"Static Public Members",
+ "",
"static public member",
"static public members");
- FastSection macros(inner, "Macros", "macro", "macros");
+ FastSection macros(inner, "Macros", "", "macro", "macros");
NodeList::ConstIterator r = classe->relatedNodes().begin();
while (r != classe->relatedNodes().end()) {
@@ -666,12 +677,12 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
append(sections, macros);
}
else if (style == Detailed) {
- FastSection memberFunctions(classe,"Member Function Documentation");
- FastSection memberTypes(classe,"Member Type Documentation");
- FastSection memberVariables(classe,"Member Variable Documentation");
- FastSection properties(classe,"Property Documentation");
- FastSection relatedNonMembers(classe,"Related Non-Members");
- FastSection macros(classe,"Macro Documentation");
+ FastSection memberFunctions(classe,"Member Function Documentation","func","member","members");
+ FastSection memberTypes(classe,"Member Type Documentation","types","member","members");
+ FastSection memberVariables(classe,"Member Variable Documentation","vars","member","members");
+ FastSection properties(classe,"Property Documentation","prop","member","members");
+ FastSection relatedNonMembers(classe,"Related Non-Members","relnonmem","member","members");
+ FastSection macros(classe,"Macro Documentation","macros","member","members");
NodeList::ConstIterator r = classe->relatedNodes().begin();
while (r != classe->relatedNodes().end()) {
@@ -717,7 +728,7 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
append(sections, macros);
}
else {
- FastSection all(classe);
+ FastSection all(classe,"","","member","members");
QStack<const ClassNode *> stack;
stack.push(classe);
@@ -747,25 +758,29 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
if (style == Summary || style == Detailed) {
FastSection namespaces(inner,
"Namespaces",
+ style == Detailed ? "nmspace" : "",
"namespace",
"namespaces");
FastSection classes(inner,
"Classes",
+ style == Detailed ? "classes" : "",
"class",
"classes");
FastSection types(inner,
- style == Summary ?
- "Types" : "Type Documentation",
+ style == Summary ? "Types" : "Type Documentation",
+ style == Detailed ? "types" : "",
"type",
"types");
FastSection functions(inner,
style == Summary ?
"Functions" : "Function Documentation",
+ style == Detailed ? "func" : "",
"function",
"functions");
FastSection macros(inner,
style == Summary ?
"Macros" : "Macro Documentation",
+ style == Detailed ? "macros" : "",
"macro",
"macros");
@@ -1116,26 +1131,32 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode,
if (style == Summary) {
FastSection qmlproperties(qmlClassNode,
"Properties",
+ "",
"property",
"properties");
FastSection qmlattachedproperties(qmlClassNode,
"Attached Properties",
+ "",
"property",
"properties");
FastSection qmlsignals(qmlClassNode,
- "Signals",
- "signal",
- "signals");
+ "Signals",
+ "",
+ "signal",
+ "signals");
FastSection qmlattachedsignals(qmlClassNode,
"Attached Signals",
+ "",
"signal",
"signals");
FastSection qmlmethods(qmlClassNode,
"Methods",
+ "",
"method",
"methods");
FastSection qmlattachedmethods(qmlClassNode,
"Attached Methods",
+ "",
"method",
"methods");
@@ -1179,12 +1200,15 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode,
append(sections,qmlattachedmethods);
}
else if (style == Detailed) {
- FastSection qmlproperties(qmlClassNode, "Property Documentation");
- FastSection qmlattachedproperties(qmlClassNode,"Attached Property Documentation");
- FastSection qmlsignals(qmlClassNode,"Signal Documentation");
- FastSection qmlattachedsignals(qmlClassNode,"Attached Signal Documentation");
- FastSection qmlmethods(qmlClassNode,"Method Documentation");
- FastSection qmlattachedmethods(qmlClassNode,"Attached Method Documentation");
+ FastSection qmlproperties(qmlClassNode, "Property Documentation","qmlprop","member","members");
+ FastSection qmlattachedproperties(qmlClassNode,"Attached Property Documentation","qmlattprop",
+ "member","members");
+ FastSection qmlsignals(qmlClassNode,"Signal Documentation","qmlsig","member","members");
+ FastSection qmlattachedsignals(qmlClassNode,"Attached Signal Documentation","qmlattsig",
+ "member","members");
+ FastSection qmlmethods(qmlClassNode,"Method Documentation","qmlmeth","member","members");
+ FastSection qmlattachedmethods(qmlClassNode,"Attached Method Documentation","qmlattmeth",
+ "member","members");
NodeList::ConstIterator c = qmlClassNode->childNodes().begin();
while (c != qmlClassNode->childNodes().end()) {
if ((*c)->subType() == Node::QmlPropertyGroup) {
diff --git a/tools/qdoc3/doc/examples/main.cpp b/tools/qdoc3/doc/examples/main.cpp
index e2cf6c5..e439d3e 100644
--- a/tools/qdoc3/doc/examples/main.cpp
+++ b/tools/qdoc3/doc/examples/main.cpp
@@ -46,7 +46,7 @@ int main(int argc, char *argv[])
{
QApplication app(argc, argv);
- QPushButton *hello("Hello world!");
+ QPushButton hello("Hello world!");
hello.resize(100, 30);
hello.show();
diff --git a/tools/qdoc3/doc/qdoc-manual.qdoc b/tools/qdoc3/doc/qdoc-manual.qdoc
index e2f670c..482af46 100644
--- a/tools/qdoc3/doc/qdoc-manual.qdoc
+++ b/tools/qdoc3/doc/qdoc-manual.qdoc
@@ -78,10 +78,10 @@
\endlist
\o \l{QDoc Configuration}
\list
- \o \l{General Variables}
+ \o \l{General Configuration Variables}
\o \l{Creating Help Project Files}
- \o \l{C++ Specific Variables}
- \o \l{HTML Specific Variables}
+ \o \l{C++ Specific Configuration Variables}
+ \o \l{HTML Specific Configuration Variables}
\o \l{Supporting Derived Projects}
\o \l{QDoc Compatibility}
\o \l{qt.qdocconf}
@@ -1425,6 +1425,7 @@
\quotefromfile examples/main.cpp
+ \skipto QApplication
\printline QApplication
This line includes the QApplication class
@@ -1652,6 +1653,7 @@
can press and release.
\quotefromfile examples/main.cpp
+ \skipto QApplication
\skipline QApplication
\printline QPushButton
@@ -6974,7 +6976,7 @@
\page 21-0-qdoc-configuration.html
\previouspage Title Commands
\contentspage QDoc Manual - Table of Contents
- \nextpage General Variables
+ \nextpage General Configuration Variables
\title QDoc Configuration
@@ -7094,9 +7096,9 @@
\section2 Categories
\list
- \o \l {General Variables}
- \o \l {C++ Specific Variables}
- \o \l {HTML Specific Variables}
+ \o \l {General Configuration Variables}
+ \o \l {C++ Specific Configuration Variables}
+ \o \l {HTML Specific Configuration Variables}
\endlist
\section1 Configuration File Examples
@@ -7133,7 +7135,7 @@
\contentspage QDoc Manual - Table of Contents
\nextpage Creating Help Project Files
- \title General Variables
+ \title General Configuration Variables
With the general QDoc configuration variables, you can define
where QDoc will find the various source files it needs to generate
@@ -7215,7 +7217,7 @@
QDoc originally used a hard-coded value of four spaces for
code indentation to ensure that code snippets could be easily
distinguished from surrounding text. Since we can use
- \l{HTML Specific Variables#HTML.stylesheets}{stylesheets} to
+ \l{HTML Specific Configuration Variables#HTML.stylesheets}{stylesheets} to
adjust the appearance of certain types of HTML elements, this
level of indentation is not always required.
@@ -7572,7 +7574,7 @@
\code
header.fileextensions += *.H
\endcode
-
+
\warning The above assignment may not work as described.
See also \l headerdirs.
@@ -7730,6 +7732,27 @@
bold font, and that \\raisedaster renders a '*'.
\row
+ \o \bold naturallanguage \target naturallanguage
+ \o \bold {The \c naturallanguage variable specifies the natural
+ language used for the documentation generated by qdoc.}
+
+ For example:
+
+ \code
+ naturallanguage = zh-Hans
+ \endcode
+
+ By default, the natural language is \c en for compatibility
+ with legacy documentation.
+
+ qdoc will add the natural language information to the HTML
+ it generates, using the \c lang and \c xml:lang attributes.
+
+ See also \l sourceencoding, \l outputencoding,
+ \l{http://www.w3.org/TR/xhtml1/#C_7}{C.7. The lang and xml:lang Attributes} and
+ \l{http://www.w3.org/TR/i18n-html-tech-lang/#ri20040429.113217290}{Best Practice 13: Using Hans and Hant codes}.
+
+ \row
\o \bold outputdir \target outputdir
\o \bold {The \c outputdir variable specifies the directory
where QDoc will put the generated documentation.}
@@ -7754,6 +7777,31 @@
directory, all files from the previous run will be lost.
\row
+ \o \bold outputencoding \target outputencoding
+ \o \bold {The \c outputencoding variable specifies the encoding
+ used for the documentation generated by qdoc.}
+
+ For example:
+
+ \code
+ outputencoding = UTF-8
+ \endcode
+
+ By default, the output encoding is \c ISO-8859-1 (Latin1) for
+ compatibility with legacy documentation. When generating
+ documentation for some languages, particularly non-European
+ languages, this is not sufficient and an encoding such as UTF-8
+ is required.
+
+ qdoc will encode HTML using this encoding and generate the
+ correct declarations to indicate to browsers which encoding
+ is being used. The \l naturallanguage configuration variable
+ should also be specified to provide browsers with a complete
+ set of character encoding and language information.
+
+ See also \l outputencoding and \l naturallanguage.
+
+ \row
\o \bold outputformats \target outputformats
\o \bold {The \c outputformats variable specifies the format of
the generated documentation.}
@@ -7831,6 +7879,30 @@
See also \l sources and \l sources.fileextensions.
\row
+ \o \bold sourceencoding \target sourceencoding
+ \o \bold {The \c sourceencoding variable specifies the encoding
+ used for the source code and documentation.}
+
+ For example:
+
+ \code
+ sourceencoding = UTF-8
+ \endcode
+
+ By default, the source encoding is \c ISO-8859-1 (Latin1) for
+ compatibility with legacy documentation. For some languages,
+ particularly non-European languages, this is not sufficient
+ and an encoding such as UTF-8 is required.
+
+ Although qdoc will use the encoding to read source and
+ documentation files, limitations of C++ compilers may prevent
+ you from using non-ASCII characters in source code comments.
+ In cases like these, it is possible to write API documentation
+ completely in documentation files.
+
+ See also \l naturallanguage and \l outputencoding.
+
+ \row
\o \bold sources \target sources
\o \bold {The \c sources variable allows you to specify
individual source files in addition to those located in the
@@ -7973,9 +8045,9 @@
/*!
\page 22-creating-help-project-files.html
- \previouspage General Variables
+ \previouspage General Configuration Variables
\contentspage QDoc Manual - Table of Contents
- \nextpage C++ Specific Variables
+ \nextpage C++ Specific Configuration Variables
\title Creating Help Project Files
@@ -8023,9 +8095,9 @@
\page 23-qdoc-configuration-cppvariables.html
\previouspage Creating Help Project Files
\contentspage QDoc Manual - Table of Contents
- \nextpage HTML Specific Variables
+ \nextpage HTML Specific Configuration Variables
- \title C++ Specific Variables
+ \title C++ Specific Configuration Variables
The C++ specific configuration variables are provided to avoid
erroneous documentation due to non-standard C++ constructs.
@@ -8159,11 +8231,11 @@
/*!
\page 24-qdoc-configuration-htmlvariables.html
- \previouspage C++ Specific Variables
+ \previouspage C++ Specific Configuration Variables
\contentspage QDoc Manual - Table of Contents
\nextpage Supporting Derived Projects
- \title HTML Specific Variables
+ \title HTML Specific Configuration Variables
The HTML specific configuration variables define the generated
documentation's style, or define the contents of the
@@ -8289,7 +8361,7 @@
/*!
\page 25-qdoc-configuration-derivedprojects.html
- \previouspage HTML Specific Variables
+ \previouspage HTML Specific Configuration Variables
\contentspage QDoc Manual - Table of Contents
\nextpage QDoc Compatibility
diff --git a/tools/qdoc3/generator.cpp b/tools/qdoc3/generator.cpp
index 0c6497b..24219a1 100644
--- a/tools/qdoc3/generator.cpp
+++ b/tools/qdoc3/generator.cpp
@@ -66,6 +66,10 @@ QStringList Generator::imageFiles;
QStringList Generator::imageDirs;
QStringList Generator::exampleDirs;
QStringList Generator::exampleImgExts;
+QStringList Generator::scriptFiles;
+QStringList Generator::scriptDirs;
+QStringList Generator::styleFiles;
+QStringList Generator::styleDirs;
QString Generator::outDir;
QString Generator::project;
@@ -124,10 +128,20 @@ void Generator::initialize(const Config &config)
if (!dirInfo.mkdir(outDir + "/images/used-in-examples"))
config.lastLocation().fatal(tr("Cannot create output directory '%1'")
.arg(outDir + "/images/used-in-examples"));
+ if (!dirInfo.mkdir(outDir + "/scripts"))
+ config.lastLocation().fatal(tr("Cannot create output directory '%1'")
+ .arg(outDir + "/scripts"));
+ if (!dirInfo.mkdir(outDir + "/style"))
+ config.lastLocation().fatal(tr("Cannot create output directory '%1'")
+ .arg(outDir + "/style"));
}
imageFiles = config.getStringList(CONFIG_IMAGES);
imageDirs = config.getStringList(CONFIG_IMAGEDIRS);
+ scriptFiles = config.getStringList(CONFIG_SCRIPTS);
+ scriptDirs = config.getStringList(CONFIG_SCRIPTDIRS);
+ styleFiles = config.getStringList(CONFIG_STYLES);
+ styleDirs = config.getStringList(CONFIG_STYLEDIRS);
exampleDirs = config.getStringList(CONFIG_EXAMPLEDIRS);
exampleImgExts = config.getStringList(CONFIG_EXAMPLES + Config::dot +
CONFIG_IMAGEEXTENSIONS);
@@ -165,6 +179,47 @@ void Generator::initialize(const Config &config)
"/images");
++e;
}
+
+ QStringList noExts;
+ QStringList scripts =
+ config.getStringList(CONFIG_SCRIPTS+Config::dot+(*g)->format());
+ e = scripts.begin();
+ while (e != scripts.end()) {
+ QString userFriendlyFilePath;
+ QString filePath = Config::findFile(config.lastLocation(),
+ scriptFiles,
+ scriptDirs,
+ *e,
+ noExts,
+ userFriendlyFilePath);
+ if (!filePath.isEmpty())
+ Config::copyFile(config.lastLocation(),
+ filePath,
+ userFriendlyFilePath,
+ (*g)->outputDir() +
+ "/scripts");
+ ++e;
+ }
+
+ QStringList styles =
+ config.getStringList(CONFIG_STYLES+Config::dot+(*g)->format());
+ e = styles.begin();
+ while (e != styles.end()) {
+ QString userFriendlyFilePath;
+ QString filePath = Config::findFile(config.lastLocation(),
+ styleFiles,
+ styleDirs,
+ *e,
+ noExts,
+ userFriendlyFilePath);
+ if (!filePath.isEmpty())
+ Config::copyFile(config.lastLocation(),
+ filePath,
+ userFriendlyFilePath,
+ (*g)->outputDir() +
+ "/style");
+ ++e;
+ }
}
++g;
}
@@ -322,11 +377,11 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
bool quiet = false;
if (node->type() == Node::Function) {
-#if 0
+#if 0
const FunctionNode *func = (const FunctionNode *) node;
if (func->isOverload() && func->metaness() != FunctionNode::Ctor)
generateOverload(node, marker);
-#endif
+#endif
}
else if (node->type() == Node::Fake) {
const FakeNode *fake = static_cast<const FakeNode *>(node);
@@ -347,7 +402,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
if (func->reimplementedFrom() != 0)
generateReimplementedFrom(func, marker);
}
-
+
if (!generateText(node->doc().body(), node, marker))
if (node->isReimp())
return;
@@ -452,7 +507,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
// Now we put this at the top, before the other text.
if (func->reimplementedFrom() != 0)
generateReimplementedFrom(func, marker);
-#endif
+#endif
}
}
@@ -544,7 +599,7 @@ void Generator::generateInheritedBy(const ClassNode *classe,
example is being formatted. It outputs the list of source
files comprising the example, and the list of images used
by the example. The images are copied into a subtree of
- \c{...doc/html/images/used-in-examples/...}
+ \c{...doc/html/images/used-in-examples/...}
*/
void Generator::generateFileList(const FakeNode* fake,
CodeMarker* marker,
@@ -946,7 +1001,7 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
}
++c;
}
- if (!exceptions)
+ if (!exceptions)
text << ".";
else if (threadSafeness == Node::Reentrant) {
if (nonreentrant.isEmpty()) {
@@ -1033,7 +1088,7 @@ void Generator::generateOverload(const Node *node, CodeMarker *marker)
text << Atom::ParaLeft
<< "This function overloads ";
QString t = node->name() + "()";
- text << Atom::AutoLink << t
+ text << Atom::AutoLink << t
<< Atom::ParaRight;
generateText(text, node, marker);
}
@@ -1194,14 +1249,14 @@ void Generator::appendSortedQmlNames(Text& text,
QMap<QString,Text> classMap;
int index = 0;
-#ifdef DEBUG_MULTIPLE QDOCCONF_FILES
+#ifdef DEBUG_MULTIPLE_QDOCCONF_FILES
qDebug() << "Generator::appendSortedQmlNames():" << base->name() << "is inherited by...";
-#endif
+#endif
for (int i = 0; i < subs.size(); ++i) {
Text t;
-#ifdef DEBUG_MULTIPLE QDOCCONF_FILES
+#ifdef DEBUG_MULTIPLE_QDOCCONF_FILES
qDebug() << " " << subs[i]->name();
-#endif
+#endif
appendFullName(t, subs[i], base, marker);
classMap[t.toString().toLower()] = t;
}
diff --git a/tools/qdoc3/generator.h b/tools/qdoc3/generator.h
index 30d9af4..326a247 100644
--- a/tools/qdoc3/generator.h
+++ b/tools/qdoc3/generator.h
@@ -191,6 +191,10 @@ class Generator
static QStringList imageDirs;
static QStringList exampleDirs;
static QStringList exampleImgExts;
+ static QStringList scriptFiles;
+ static QStringList scriptDirs;
+ static QStringList styleFiles;
+ static QStringList styleDirs;
static QString outDir;
static QString project;
};
diff --git a/tools/qdoc3/helpprojectwriter.cpp b/tools/qdoc3/helpprojectwriter.cpp
index 71810e4..edba097 100644
--- a/tools/qdoc3/helpprojectwriter.cpp
+++ b/tools/qdoc3/helpprojectwriter.cpp
@@ -41,6 +41,7 @@
#include <QHash>
#include <QMap>
+#include <qdebug.h>
#include "atom.h"
#include "helpprojectwriter.h"
@@ -116,6 +117,11 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList
typeHash["property"] = Node::Property;
typeHash["variable"] = Node::Variable;
typeHash["target"] = Node::Target;
+#ifdef QDOC_QML
+ typeHash["qmlproperty"] = Node::QmlProperty;
+ typeHash["qmlsignal"] = Node::QmlSignal;
+ typeHash["qmlmethod"] = Node::QmlMethod;
+#endif
QHash<QString, Node::SubType> subTypeHash;
subTypeHash["example"] = Node::Example;
@@ -127,6 +133,8 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList
subTypeHash["externalpage"] = Node::ExternalPage;
#ifdef QDOC_QML
subTypeHash["qmlclass"] = Node::QmlClass;
+ subTypeHash["qmlpropertygroup"] = Node::QmlPropertyGroup;
+ subTypeHash["qmlbasictype"] = Node::QmlBasicType;
#endif
QSet<Node::SubType> allSubTypes = QSet<Node::SubType>::fromList(subTypeHash.values());
@@ -176,7 +184,13 @@ QStringList HelpProjectWriter::keywordDetails(const Node *node) const
{
QStringList details;
- if (node->parent() && !node->parent()->name().isEmpty()) {
+ if (node->type() == Node::QmlProperty) {
+ // "name"
+ details << node->name();
+ // "id"
+ details << node->parent()->parent()->name()+"::"+node->name();
+ }
+ else if (node->parent() && !node->parent()->name().isEmpty()) {
// "name"
if (node->type() == Node::Enum || node->type() == Node::Typedef)
details << node->parent()->name()+"::"+node->name();
@@ -184,29 +198,29 @@ QStringList HelpProjectWriter::keywordDetails(const Node *node) const
details << node->name();
// "id"
details << node->parent()->name()+"::"+node->name();
- } else if (node->type() == Node::Fake) {
+ }
+ else if (node->type() == Node::Fake) {
const FakeNode *fake = static_cast<const FakeNode *>(node);
-#ifdef QDOC_QML
if (fake->subType() == Node::QmlClass) {
details << (QmlClassNode::qmlOnly ? fake->name() : fake->fullTitle());
details << "QML." + fake->name();
- } else
-#endif
- {
+ }
+ else {
details << fake->fullTitle();
details << fake->fullTitle();
}
- } else {
+ }
+ else {
details << node->name();
details << node->name();
}
details << tree->fullDocumentLocation(node);
-
return details;
}
bool HelpProjectWriter::generateSection(HelpProject &project,
- QXmlStreamWriter & /* writer */, const Node *node)
+ QXmlStreamWriter & /* writer */,
+ const Node *node)
{
if (!node->url().isEmpty())
return false;
@@ -225,9 +239,10 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
if (node->type() == Node::Fake) {
const FakeNode *fake = static_cast<const FakeNode *>(node);
objName = fake->fullTitle();
- } else
+ }
+ else
objName = tree->fullDocumentName(node);
-
+
// Only add nodes to the set for each subproject if they match a selector.
// Those that match will be listed in the table of contents.
@@ -289,6 +304,9 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
break;
case Node::Property:
+ case Node::QmlProperty:
+ case Node::QmlSignal:
+ case Node::QmlMethod:
project.keywords.append(keywordDetails(node));
break;
@@ -399,7 +417,7 @@ void HelpProjectWriter::generateSections(HelpProject &project,
{
if (!generateSection(project, writer, node))
return;
-
+
if (node->isInnerNode()) {
const InnerNode *inner = static_cast<const InnerNode *>(node);
@@ -408,8 +426,23 @@ void HelpProjectWriter::generateSections(HelpProject &project,
foreach (const Node *node, inner->childNodes()) {
if (node->access() == Node::Private)
continue;
- if (node->type() == Node::Fake)
- childMap[static_cast<const FakeNode *>(node)->fullTitle()] = node;
+ if (node->type() == Node::Fake) {
+ /*
+ Don't visit QML property group nodes,
+ but visit their children, which are all
+ QML property nodes.
+ */
+ if (node->subType() == Node::QmlPropertyGroup) {
+ const InnerNode* inner = static_cast<const InnerNode*>(node);
+ foreach (const Node* n, inner->childNodes()) {
+ if (n->access() == Node::Private)
+ continue;
+ childMap[tree->fullDocumentName(n)] = n;
+ }
+ }
+ else
+ childMap[static_cast<const FakeNode *>(node)->fullTitle()] = node;
+ }
else {
if (node->type() == Node::Function) {
const FunctionNode *funcNode = static_cast<const FunctionNode *>(node);
diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp
index c1e3678..a5dc7b7 100644
--- a/tools/qdoc3/htmlgenerator.cpp
+++ b/tools/qdoc3/htmlgenerator.cpp
@@ -333,6 +333,7 @@ QString HtmlGenerator::format()
*/
void HtmlGenerator::generateTree(const Tree *tree, CodeMarker *marker)
{
+#if 0
// Copy the stylesheets from the directory containing the qdocconf file.
// ### This should be changed to use a special directory in doc/src.
QStringList::ConstIterator styleIter = stylesheets.begin();
@@ -342,7 +343,7 @@ void HtmlGenerator::generateTree(const Tree *tree, CodeMarker *marker)
Config::copyFile(Location(), filePath, filePath, outputDir());
++styleIter;
}
-
+#endif
myTree = tree;
nonCompatClasses.clear();
mainClasses.clear();
@@ -405,7 +406,9 @@ void HtmlGenerator::generateTree(const Tree *tree, CodeMarker *marker)
generateIndex(fileBase, projectUrl, projectDescription);
generatePageIndex(outputDir() + "/" + fileBase + ".pageindex", marker);
+ //qDebug() << "start helpProjectWriter->generate(myTree)";
helpProjectWriter->generate(myTree);
+ //qDebug() << "end helpProjectWriter->generate(myTree)";
}
void HtmlGenerator::startText(const Node * /* relative */,
@@ -694,7 +697,7 @@ int HtmlGenerator::generateAtom(const Atom *atom,
QList<Section> sections;
QList<Section>::ConstIterator s;
for (int i=0; i<LastSinceType; ++i)
- sections.append(Section(sinceTitle(i),QString(),QString()));
+ sections.append(Section(sinceTitle(i),QString(),QString(),QString()));
NodeMultiMap::const_iterator n = nsmap.value().constBegin();
while (n != nsmap.value().constEnd()) {
@@ -899,17 +902,14 @@ int HtmlGenerator::generateAtom(const Atom *atom,
else if (atom->string() == ATOM_LIST_VALUE) {
threeColumnEnumValueTable = isThreeColumnEnumValueTable(atom);
if (threeColumnEnumValueTable) {
- out() << "<p><table class=\"valuelist\" border=\"1\" cellpadding=\"2\" "
- << "cellspacing=\"1\" width=\"100%\">\n"
- << "<tr><th width=\"25%\">Constant</th>"
- << "<th width=\"15%\">Value</th>"
- << "<th width=\"60%\">Description</th></tr>\n";
+ out() << "<p><table class=\"valuelist\">"
+ << "<tr><th>Constant</th>"
+ << "<th>Value</th>"
+ << "<th>Description</th></tr>\n";
}
else {
- out() << "<p><table class=\"valuelist\" border=\"1\" cellpadding=\"2\" "
- << "cellspacing=\"1\" width=\"40%\">\n"
- << "<tr><th width=\"60%\">Constant</th><th "
- << "width=\"40%\">Value</th></tr>\n";
+ out() << "<p><table class=\"valuelist\">"
+ << "<tr><th>Constant</th><th>Value</th></tr>\n";
}
}
else {
@@ -1084,16 +1084,13 @@ int HtmlGenerator::generateAtom(const Atom *atom,
if (!atom->string().isEmpty()) {
if (atom->string().contains("%"))
out() << "<p><table class=\"generic\" width=\"" << atom->string() << "\" "
- << "align=\"center\" cellpadding=\"2\" "
- << "cellspacing=\"1\" border=\"0\">\n";
+ << "align=\"center\">\n";
else {
- out() << "<p><table class=\"generic\" align=\"center\" cellpadding=\"2\" "
- << "cellspacing=\"1\" border=\"0\">\n";
+ out() << "<p><table class=\"generic\" align=\"center\">\n";
}
}
else {
- out() << "<p><table class=\"generic\" align=\"center\" cellpadding=\"2\" "
- << "cellspacing=\"1\" border=\"0\">\n";
+ out() << "<p><table class=\"generic\" align=\"center\">\n";
}
numTableRows = 0;
break;
@@ -1259,6 +1256,8 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
}
generateHeader(title, inner, marker, true);
+ sections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay);
+ generateTableOfContents(inner,marker,&sections);
generateTitle(title, subtitleText, SmallSubTitle, inner, marker);
#ifdef QDOC_QML
@@ -1302,7 +1301,9 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
bool needOtherSection = false;
- sections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay);
+ /*
+ sections is built above for the call to generateTableOfContents().
+ */
s = sections.begin();
while (s != sections.end()) {
if (s->members.isEmpty() && s->reimpMembers.isEmpty()) {
@@ -1354,8 +1355,10 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
if (!inner->doc().isEmpty()) {
out() << "<hr />\n"
+ << "<div class=\"descr\"/>\n" // QTBUG-9504
<< "<h2>" << "Detailed Description" << "</h2>\n";
generateBody(inner, marker);
+ out() << "</div>\n"; // QTBUG-9504
generateAlsoList(inner, marker);
}
@@ -1363,6 +1366,8 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
s = sections.begin();
while (s != sections.end()) {
out() << "<hr />\n";
+ if (!(*s).divClass.isEmpty())
+ out() << "<div class=\"" << (*s).divClass << "\"/>\n"; // QTBUG-9504
out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
NodeList::ConstIterator m = (*s).members.begin();
@@ -1412,6 +1417,8 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
}
++m;
}
+ if (!(*s).divClass.isEmpty())
+ out() << "</div>\n"; // QTBUG-9504
++s;
}
generateFooter(inner);
@@ -1460,6 +1467,14 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
}
generateHeader(htmlTitle, fake, marker, true);
+
+ /*
+ Generate the TOC for the new doc format.
+ Don't generate a TOC for the home page.
+ */
+ if (fake->name() != QString("index.html"))
+ generateTableOfContents(fake,marker,0);
+
generateTitle(fullTitle,
Text() << fake->subTitle(),
subTitleSize,
@@ -1472,10 +1487,12 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
generateStatus(fake, marker);
if (moduleNamespaceMap.contains(fake->name())) {
+ out() << "<a name=\"" << registerRef("namespaces") << "\"></a>\n";
out() << "<h2>Namespaces</h2>\n";
generateAnnotatedList(fake, marker, moduleNamespaceMap[fake->name()]);
}
if (moduleClassMap.contains(fake->name())) {
+ out() << "<a name=\"" << registerRef("classes") << "\"></a>\n";
out() << "<h2>Classes</h2>\n";
generateAnnotatedList(fake, marker, moduleClassMap[fake->name()]);
}
@@ -1583,10 +1600,14 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
Text brief = fake->doc().briefText();
if (fake->subType() == Node::Module && !brief.isEmpty()) {
out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
+ out() << "<div class=\"descr\"/>\n"; // QTBUG-9504
out() << "<h2>" << "Detailed Description" << "</h2>\n";
}
+ else
+ out() << "<div class=\"descr\"/>\n"; // QTBUG-9504
generateBody(fake, marker);
+ out() << "</div>\n"; // QTBUG-9504
generateAlsoList(fake, marker);
if (!fake->groupMembers().isEmpty()) {
@@ -1645,13 +1666,79 @@ QString HtmlGenerator::fileExtension(const Node * /* node */) const
return "html";
}
+#if 0
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <title>Qt Reference Documentation</title>
+ <link rel="stylesheet" type="text/css" href="style/style.css" />
+ <!--[if IE]>
+ <meta name="MSSmartTagsPreventParsing" content="true">
+ <meta http-equiv="imagetoolbar" content="no">
+ <![endif]-->
+ <!--[if lt IE 7]>
+ <link rel="stylesheet" type="text/css" href="style/style_ie6.css">
+ <![endif]-->
+ <!--[if IE 7]>
+ <link rel="stylesheet" type="text/css" href="style/style_ie7.css">
+ <![endif]-->
+ <!--[if IE 8]>
+ <link rel="stylesheet" type="text/css" href="style/style_ie8.css">
+ <![endif]-->
+
+ <script src="scripts/jquery.js" type="text/javascript"></script>
+
+</head>
+#endif
+
void HtmlGenerator::generateHeader(const QString& title,
const Node *node,
CodeMarker *marker,
bool mainPage)
{
out() << QString("<?xml version=\"1.0\" encoding=\"%1\"?>\n").arg(outputEncoding);
-
+ out() << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
+ out() << "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
+ out() << "<head>\n";
+ out() << " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
+ QString shortVersion;
+ shortVersion = project + " " + shortVersion + ": ";
+ if (node && !node->doc().location().isEmpty())
+ out() << "<!-- " << node->doc().location().fileName() << " -->\n";
+
+ shortVersion = myTree->version();
+ if (shortVersion.count(QChar('.')) == 2)
+ shortVersion.truncate(shortVersion.lastIndexOf(QChar('.')));
+ if (!shortVersion.isEmpty()) {
+ if (project == "QSA")
+ shortVersion = "QSA " + shortVersion + ": ";
+ else
+ shortVersion = "Qt " + shortVersion + ": ";
+ }
+
+ out() << " <title>" << shortVersion << protectEnc(title) << "</title>\n";
+
+ //out() << " <title>Qt Reference Documentation</title>";
+ out() << " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style.css\" />\n";
+ out() << " <!--[if IE]>\n";
+ out() << " <meta name=\"MSSmartTagsPreventParsing\" content=\"true\">\n";
+ out() << " <meta http-equiv=\"imagetoolbar\" content=\"no\">\n";
+ out() << " <![endif]-->\n";
+ out() << " <!--[if lt IE 7]>\n";
+ out() << " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie6.css\">\n";
+ out() << " <![endif]-->\n";
+ out() << " <!--[if IE 7]>\n";
+ out() << " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie7.css\">\n";
+ out() << " <![endif]-->\n";
+ out() << " <!--[if IE 8]>\n";
+ out() << " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie8.css\">\n";
+ out() << " <![endif]-->\n";
+ out() << " <script src=\"scripts/jquery.js\" type=\"text/javascript\"></script>\n";
+ out() << " <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n";
+ out() << "</head>\n";
+
+#if 0
out() << "<!DOCTYPE html\n"
" PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"DTD/xhtml1-strict.dtd\">\n";
out() << QString("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"%1\" lang=\"%1\">\n").arg(naturalLanguage);
@@ -1783,14 +1870,16 @@ void HtmlGenerator::generateHeader(const QString& title,
}
out() << "</head>\n"
- "<body>\n";
+ #endif
+ out() << "<body class=\"\">\n";
if (mainPage)
generateMacRef(node, marker);
out() << QString(postHeader).replace("\\" + COMMAND_VERSION, myTree->version());
-
+#if 0
if (node && !node->links().empty())
out() << "<p>\n" << navigationLinks << "</p>\n";
+#endif
}
void HtmlGenerator::generateTitle(const QString& title,
@@ -1799,7 +1888,8 @@ void HtmlGenerator::generateTitle(const QString& title,
const Node *relative,
CodeMarker *marker)
{
- out() << "<h1 class=\"title\">" << protectEnc(title);
+ if (!title.isEmpty())
+ out() << "<h1 class=\"title\">" << protectEnc(title);
if (!subTitle.isEmpty()) {
out() << "<br />";
if (subTitleSize == SmallSubTitle)
@@ -1809,7 +1899,8 @@ void HtmlGenerator::generateTitle(const QString& title,
generateText(subTitle, relative, marker);
out() << "</span>\n";
}
- out() << "</h1>\n";
+ if (!title.isEmpty())
+ out() << "</h1>\n";
}
void HtmlGenerator::generateFooter(const Node *node)
@@ -1849,6 +1940,9 @@ void HtmlGenerator::generateIncludes(const InnerNode *inner, CodeMarker *marker)
}
}
+/*!
+ Generates a table of contents begining at \a node.
+ */
void HtmlGenerator::generateTableOfContents(const Node *node,
CodeMarker *marker,
Doc::SectioningUnit sectioningUnit,
@@ -1856,6 +1950,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node,
const Node *relative)
{
+ return;
if (!node->doc().hasTableOfContents())
return;
QList<Atom *> toc = node->doc().tableOfContents();
@@ -1930,6 +2025,102 @@ void HtmlGenerator::generateTableOfContents(const Node *node,
inLink = false;
}
+/*!
+ Revised for the new doc format.
+ Generates a table of contents begining at \a node.
+ */
+void HtmlGenerator::generateTableOfContents(const Node *node,
+ CodeMarker *marker,
+ QList<Section>* sections)
+{
+ QList<Atom*> toc;
+ if (node->doc().hasTableOfContents())
+ toc = node->doc().tableOfContents();
+ if (toc.isEmpty() && !sections && (node->subType() != Node::Module))
+ return;
+
+ QStringList sectionNumber;
+ int detailsBase = 0;
+
+ // disable nested links in table of contents
+ inContents = true;
+ inLink = true;
+
+ out() << "<div class=\"toc\">\n";
+ out() << "<h3>Table of Contents</h3>\n";
+ sectionNumber.append("1");
+ out() << "<ul class=\"level" << sectionNumber.size() << "\">\n";
+
+ if (node->subType() == Node::Module) {
+ if (moduleNamespaceMap.contains(node->name())) {
+ out() << "<li><a href=\"#" << registerRef("namespaces") << "\">Namespaces</a></li>\n";
+ }
+ if (moduleClassMap.contains(node->name())) {
+ out() << "<li><a href=\"#" << registerRef("classes") << "\">Classes</a></li>\n";
+ }
+ out() << "<li><a href=\"#" << registerRef("details") << "\">Detailed Description</a></li>\n";
+ for (int i = 0; i < toc.size(); ++i) {
+ if (toc.at(i)->string().toInt() == 1) {
+ detailsBase = 1;
+ break;
+ }
+ }
+ }
+ else if (sections && (node->type() == Node::Class)) {
+ QList<Section>::ConstIterator s = sections->begin();
+ while (s != sections->end()) {
+ if (!s->members.isEmpty() || !s->reimpMembers.isEmpty()) {
+ out() << "<li><a href=\"#"
+ << registerRef((*s).pluralMember)
+ << "\">" << (*s).name
+ << "</a></li>\n";
+ }
+ ++s;
+ }
+ out() << "<li><a href=\"#" << registerRef("details") << "\">Detailed Description</a></li>\n";
+ for (int i = 0; i < toc.size(); ++i) {
+ if (toc.at(i)->string().toInt() == 1) {
+ detailsBase = 1;
+ break;
+ }
+ }
+ }
+
+ for (int i = 0; i < toc.size(); ++i) {
+ Atom *atom = toc.at(i);
+ int nextLevel = atom->string().toInt() + detailsBase;
+ if (sectionNumber.size() < nextLevel) {
+ do {
+ sectionNumber.append("1");
+ out() << "<ul class=\"level" << sectionNumber.size() << "\">\n";
+ } while (sectionNumber.size() < nextLevel);
+ }
+ else {
+ while (sectionNumber.size() > nextLevel) {
+ out() << "</ul>\n";
+ sectionNumber.removeLast();
+ }
+ sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1);
+ }
+ int numAtoms;
+ Text headingText = Text::sectionHeading(atom);
+ out() << "<li>";
+ out() << "<a href=\""
+ << "#"
+ << Doc::canonicalTitle(headingText.toString())
+ << "\">";
+ generateAtomList(headingText.firstAtom(), node, marker, true, numAtoms);
+ out() << "</a></li>\n";
+ }
+ while (!sectionNumber.isEmpty()) {
+ out() << "</ul>\n";
+ sectionNumber.removeLast();
+ }
+ out() << "</div>\n";
+ inContents = false;
+ inLink = false;
+}
+
#if 0
void HtmlGenerator::generateNavigationBar(const NavigationBar& bar,
const Node *node,
@@ -2113,8 +2304,7 @@ void HtmlGenerator::generateAnnotatedList(const Node *relative,
CodeMarker *marker,
const NodeMap &nodeMap)
{
- out() << "<p><table width=\"100%\" class=\"annotated\" cellpadding=\"2\" "
- << "cellspacing=\"1\" border=\"0\">\n";
+ out() << "<p><table class=\"annotated\">\n";
int row = 0;
foreach (const QString &name, nodeMap.keys()) {
@@ -2164,7 +2354,7 @@ void HtmlGenerator::generateCompactList(const Node *relative,
QString commonPrefix)
{
const int NumParagraphs = 37; // '0' to '9', 'A' to 'Z', '_'
- const int NumColumns = 4; // number of columns in the result
+ const int NumColumns = 3; // number of columns in the result
if (classMap.isEmpty())
return;
@@ -2299,7 +2489,7 @@ void HtmlGenerator::generateCompactList(const Node *relative,
}
firstOffset[NumColumns] = classMap.count();
- out() << "<p><table class=\"generic\" width=\"100%\">\n";
+ out() << "<p><table class=\"generic\">\n";
for (k = 0; k < numRows; k++) {
out() << "<tr>\n";
for (i = 0; i < NumColumns; i++) {
@@ -2638,15 +2828,12 @@ void HtmlGenerator::generateSection(const NodeList& nl,
name_alignment = false;
}
if (name_alignment) {
- out() << "<table class=\"alignedsummary\" border=\"0\" cellpadding=\"0\" "
- << "cellspacing=\"0\" width=\"100%\">\n";
+ out() << "<table class=\"alignedsummary\">\n";
}
else {
if (twoColumn)
- out() << "<p><table class=\"propsummary\" width=\"100%\" "
- << "border=\"0\" cellpadding=\"0\""
- << " cellspacing=\"0\">\n"
- << "<tr><td width=\"45%\" valign=\"top\">";
+ out() << "<p><table class=\"propsummary\">\n"
+ << "<tr><td valign=\"top\">";
out() << "<ul>\n";
}
@@ -2703,15 +2890,12 @@ void HtmlGenerator::generateSectionList(const Section& section,
name_alignment = false;
}
if (name_alignment) {
- out() << "<table class=\"alignedsummary\" border=\"0\" cellpadding=\"0\" "
- << "cellspacing=\"0\" width=\"100%\">\n";
+ out() << "<table class=\"alignedsummary\">\n";
}
else {
if (twoColumn)
- out() << "<p><table class=\"propsummary\" width=\"100%\" "
- << "border=\"0\" cellpadding=\"0\""
- << " cellspacing=\"0\">\n"
- << "<tr><td width=\"45%\" valign=\"top\">";
+ out() << "<p><table class=\"propsummary\">\n"
+ << "<tr><td valign=\"top\">";
out() << "<ul>\n";
}
@@ -3008,9 +3192,8 @@ void HtmlGenerator::generateSectionList(const Section& section,
twoColumn = (section.members.count() >= 5);
}
if (twoColumn)
- out() << "<p><table class=\"generic\" width=\"100%\" border=\"0\" "
- << "cellpadding=\"0\" cellspacing=\"0\">\n"
- << "<tr><td width=\"45%\" valign=\"top\">";
+ out() << "<p><table class=\"generic\">\n"
+ << "<tr><td valign=\"top\">";
out() << "<ul>\n";
int i = 0;
@@ -4193,7 +4376,7 @@ QT_END_NAMESPACE
#ifdef QDOC_QML
/*!
- Generates the summary for for the \a section. Only used for
+ Generates the summary for the \a section. Only used for
sections of QML element documentation.
Currently handles only the QML property group.
@@ -4210,9 +4393,8 @@ void HtmlGenerator::generateQmlSummary(const Section& section,
twoColumn = (count >= 5);
}
if (twoColumn)
- out() << "<p><table width=\"100%\" border=\"0\" cellpadding=\"0\""
- " cellspacing=\"0\">\n"
- << "<tr><td width=\"45%\" valign=\"top\">";
+ out() << "<p><table class=\"qmlsummary\">\n"
+ << "<tr><td valign=\"top\">";
out() << "<ul>\n";
int row = 0;
@@ -4247,7 +4429,7 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node,
const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node);
NodeList::ConstIterator p = qpgn->childNodes().begin();
out() << "<div class=\"qmlproto\">";
- out() << "<table width=\"100%\" class=\"qmlname\">";
+ out() << "<table class=\"qmlname\">";
while (p != qpgn->childNodes().end()) {
if ((*p)->type() == Node::QmlProperty) {
@@ -4264,8 +4446,7 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node,
<< "<div class=\"qmlitem\">"
<< "<div class=\"qmlproto\">"
<< "<table class=\"qmlname\">"
- << "<tr><td><font color=\"green\">"
- << "default</font></td></tr>";
+ << "<tr><td>default</td></tr>";
}
}
++p;
diff --git a/tools/qdoc3/htmlgenerator.h b/tools/qdoc3/htmlgenerator.h
index 8fe0331..559c968 100644
--- a/tools/qdoc3/htmlgenerator.h
+++ b/tools/qdoc3/htmlgenerator.h
@@ -153,6 +153,9 @@ class HtmlGenerator : public PageGenerator
Doc::SectioningUnit sectioningUnit,
int numColumns,
const Node *relative = 0);
+ void generateTableOfContents(const Node *node,
+ CodeMarker *marker,
+ QList<Section>* sections = 0);
QString generateListOfAllMemberFile(const InnerNode *inner, CodeMarker *marker);
QString generateLowStatusMemberFile(const InnerNode *inner,
CodeMarker *marker,
diff --git a/tools/qdoc3/location.cpp b/tools/qdoc3/location.cpp
index 19625da..dee87d1 100644
--- a/tools/qdoc3/location.cpp
+++ b/tools/qdoc3/location.cpp
@@ -265,6 +265,8 @@ void Location::error(const QString& message, const QString& details) const
void Location::fatal(const QString& message, const QString& details) const
{
emitMessage(Error, message, details);
+ information(message);
+ information(details);
information("Aborting");
exit(EXIT_FAILURE);
}
diff --git a/tools/qdoc3/node.cpp b/tools/qdoc3/node.cpp
index d60ff73..a2bd948 100644
--- a/tools/qdoc3/node.cpp
+++ b/tools/qdoc3/node.cpp
@@ -415,7 +415,7 @@ void InnerNode::normalizeOverloads()
/*!
*/
-void InnerNode::removeFromRelated()
+void InnerNode::removeFromRelated()
{
while (!related.isEmpty()) {
Node *p = static_cast<Node *>(related.takeFirst());
@@ -456,7 +456,7 @@ const Node *InnerNode::findNode(const QString& name, Type type) const
}
/*!
- Find the function node in this node that has the given \a name.
+ Find the function node in this node that has the given \a name.
*/
const FunctionNode *InnerNode::findFunctionNode(const QString& name) const
{
@@ -973,7 +973,7 @@ Parameter::Parameter(const Parameter& p)
/*!
Assigning Parameter \a p to this Parameter copies the
- strings across.
+ strings across.
*/
Parameter& Parameter::operator=(const Parameter& p)
{
@@ -1297,9 +1297,9 @@ QmlClassNode::QmlClassNode(InnerNode *parent,
*/
QmlClassNode::~QmlClassNode()
{
-#ifdef DEBUG_MULTIPLE QDOCCONF_FILES
+#ifdef DEBUG_MULTIPLE_QDOCCONF_FILES
qDebug() << "Deleting QmlClassNode:" << name();
-#endif
+#endif
}
/*!
@@ -1319,7 +1319,7 @@ void QmlClassNode::clear()
*/
QString QmlClassNode::fileBase() const
{
-#if 0
+#if 0
if (Node::fileBase() == "item")
qDebug() << "FILEBASE: qmlitem" << name();
return "qml_" + Node::fileBase();
@@ -1334,9 +1334,9 @@ QString QmlClassNode::fileBase() const
void QmlClassNode::addInheritedBy(const QString& base, Node* sub)
{
inheritedBy.insert(base,sub);
-#ifdef DEBUG_MULTIPLE QDOCCONF_FILES
+#ifdef DEBUG_MULTIPLE_QDOCCONF_FILES
qDebug() << "QmlClassNode::addInheritedBy(): insert" << base << sub->name() << inheritedBy.size();
-#endif
+#endif
}
/*!
@@ -1347,10 +1347,10 @@ void QmlClassNode::subclasses(const QString& base, NodeList& subs)
subs.clear();
if (inheritedBy.count(base) > 0) {
subs = inheritedBy.values(base);
-#ifdef DEBUG_MULTIPLE QDOCCONF_FILES
+#ifdef DEBUG_MULTIPLE_QDOCCONF_FILES
qDebug() << "QmlClassNode::subclasses():" << inheritedBy.count(base) << base
<< "subs:" << subs.size() << "total size:" << inheritedBy.size();
-#endif
+#endif
}
}
@@ -1368,7 +1368,7 @@ QmlBasicTypeNode::QmlBasicTypeNode(InnerNode *parent,
/*!
Constructor for the Qml property group node. \a parent is
- always a QmlClassNode.
+ always a QmlClassNode.
*/
QmlPropGroupNode::QmlPropGroupNode(QmlClassNode* parent,
const QString& name,
diff --git a/tools/qdoc3/node.h b/tools/qdoc3/node.h
index 1017813..215a7ae 100644
--- a/tools/qdoc3/node.h
+++ b/tools/qdoc3/node.h
@@ -163,6 +163,7 @@ class Node
virtual bool isInnerNode() const = 0;
virtual bool isReimp() const { return false; }
virtual bool isFunction() const { return false; }
+ virtual bool isQmlNode() const { return false; }
Type type() const { return typ; }
virtual SubType subType() const { return NoSubType; }
InnerNode *parent() const { return par; }
@@ -380,6 +381,7 @@ class QmlClassNode : public FakeNode
const QString& name,
const ClassNode* cn);
virtual ~QmlClassNode();
+ virtual bool isQmlNode() const { return true; }
const ClassNode* classNode() const { return cnode; }
virtual QString fileBase() const;
@@ -401,6 +403,7 @@ class QmlBasicTypeNode : public FakeNode
QmlBasicTypeNode(InnerNode *parent,
const QString& name);
virtual ~QmlBasicTypeNode() { }
+ virtual bool isQmlNode() const { return true; }
};
class QmlPropGroupNode : public FakeNode
@@ -410,6 +413,7 @@ class QmlPropGroupNode : public FakeNode
const QString& name,
bool attached);
virtual ~QmlPropGroupNode() { }
+ virtual bool isQmlNode() const { return true; }
const QString& element() const { return parent()->name(); }
void setDefault() { isdefault = true; }
@@ -441,6 +445,7 @@ class QmlPropertyNode : public LeafNode
bool isDesignable() const { return fromTrool(des,false); }
bool isWritable() const { return fromTrool(wri,true); }
bool isAttached() const { return att; }
+ virtual bool isQmlNode() const { return true; }
const QString& element() const { return static_cast<QmlPropGroupNode*>(parent())->element(); }
@@ -609,6 +614,9 @@ class FunctionNode : public LeafNode
QString signature(bool values = false) const;
const QString& element() const { return parent()->name(); }
bool isAttached() const { return att; }
+ virtual bool isQmlNode() const {
+ return ((type() == QmlSignal) || (type() == QmlMethod));
+ }
void debug() const;
diff --git a/tools/qdoc3/qscodemarker.cpp b/tools/qdoc3/qscodemarker.cpp
index 89c9c5c..d4b8e80 100644
--- a/tools/qdoc3/qscodemarker.cpp
+++ b/tools/qdoc3/qscodemarker.cpp
@@ -279,11 +279,11 @@ QList<Section> QsCodeMarker::sections( const InnerNode *inner, SynopsisStyle sty
const ClassNode *classe = static_cast<const ClassNode *>(inner);
if ( style == Summary ) {
- FastSection enums(classe, "Enums", "enum", "enums");
- FastSection functions(classe, "Functions", "function", "functions");
- FastSection readOnlyProperties(classe, "Read-Only Properties", "property", "properties");
- FastSection signalz(classe, "Signals", "signal", "signals");
- FastSection writableProperties(classe, "Writable Properties", "property", "properties");
+ FastSection enums(classe, "Enums", "", "enum", "enums");
+ FastSection functions(classe, "Functions", "", "function", "functions");
+ FastSection readOnlyProperties(classe, "", "Read-Only Properties", "property", "properties");
+ FastSection signalz(classe, "Signals", "", "signal", "signals");
+ FastSection writableProperties(classe, "", "Writable Properties", "property", "properties");
QStack<const ClassNode *> stack;
stack.push( classe );
@@ -328,9 +328,9 @@ QList<Section> QsCodeMarker::sections( const InnerNode *inner, SynopsisStyle sty
append( sections, functions );
append( sections, signalz );
} else if ( style == Detailed ) {
- FastSection enums( classe, "Enum Documentation" );
- FastSection functionsAndSignals( classe, "Function and Signal Documentation" );
- FastSection properties( classe, "Property Documentation" );
+ FastSection enums( classe, "Enum Documentation", "", "member", "members");
+ FastSection functionsAndSignals( classe, "Function and Signal Documentation", "", "member", "members");
+ FastSection properties( classe, "Property Documentation", "", "member", "members");
NodeList::ConstIterator c = classe->childNodes().begin();
while ( c != classe->childNodes().end() ) {
@@ -349,7 +349,7 @@ QList<Section> QsCodeMarker::sections( const InnerNode *inner, SynopsisStyle sty
append( sections, properties );
append( sections, functionsAndSignals );
} else { // ( style == SeparateList )
- FastSection all( classe );
+ FastSection all(classe, "", "", "member", "members");
QStack<const ClassNode *> stack;
stack.push( classe );
diff --git a/tools/qdoc3/test/assistant.qdocconf b/tools/qdoc3/test/assistant.qdocconf
index 63455f1..5308afd 100644
--- a/tools/qdoc3/test/assistant.qdocconf
+++ b/tools/qdoc3/test/assistant.qdocconf
@@ -40,6 +40,7 @@ exampledirs = $QT_SOURCE_TREE \
$QT_SOURCE_TREE/examples \
$QT_SOURCE_TREE/doc/src
-imagedirs = $QT_SOURCE_TREE/doc/src/images
+imagedirs = $QT_SOURCE_TREE/doc/src/images \
+ $QT_SOURCE_TREE/doc/src/template/images
outputdir = $QT_BUILD_TREE/doc-build/html-assistant
base = file:$QT_BUILD_TREE/doc-build/html-assistant
diff --git a/tools/qdoc3/test/designer.qdocconf b/tools/qdoc3/test/designer.qdocconf
index b0c88f1..2eb3d96 100644
--- a/tools/qdoc3/test/designer.qdocconf
+++ b/tools/qdoc3/test/designer.qdocconf
@@ -46,6 +46,7 @@ exampledirs = $QT_SOURCE_TREE \
$QT_SOURCE_TREE/examples \
$QT_SOURCE_TREE/doc/src
-imagedirs = $QT_SOURCE_TREE/doc/src/images
+imagedirs = $QT_SOURCE_TREE/doc/src/images \
+ $QT_SOURCE_TREE/doc/src/template/images
outputdir = $QT_BUILD_TREE/doc-build/html-designer
base = file:$QT_BUILD_TREE/doc-build/html-designer
diff --git a/tools/qdoc3/test/jambi.qdocconf b/tools/qdoc3/test/jambi.qdocconf
index 04bb51b..aa87826 100644
--- a/tools/qdoc3/test/jambi.qdocconf
+++ b/tools/qdoc3/test/jambi.qdocconf
@@ -16,7 +16,8 @@ outputdir = $JAMBI/doc/html/com/trolltech/qt
imagedirs = $QTDIR/doc/src/images \
$QTDIR/examples \
$JAMBI/doc/src/images \
- ../doc/src/images
+ ../doc/src/images \
+ $QTDIR/doc/src/template/images
extraimages.javadoc = qt-logo \
qt-logo.png
diff --git a/tools/qdoc3/test/linguist.qdocconf b/tools/qdoc3/test/linguist.qdocconf
index 6acd2c6..ac536be 100644
--- a/tools/qdoc3/test/linguist.qdocconf
+++ b/tools/qdoc3/test/linguist.qdocconf
@@ -42,6 +42,7 @@ exampledirs = $QT_SOURCE_TREE \
$QT_SOURCE_TREE/examples \
$QT_SOURCE_TREE/doc/src
-imagedirs = $QT_SOURCE_TREE/doc/src/images
+imagedirs = $QT_SOURCE_TREE/doc/src/images \
+ $QT_SOURCE_TREE/doc/src/template/images
outputdir = $QT_BUILD_TREE/doc-build/html-linguist
base = file:$QT_BUILD_TREE/doc-build/html-linguist
diff --git a/tools/qdoc3/test/qdeclarative.qdocconf b/tools/qdoc3/test/qdeclarative.qdocconf
index e5b883a..03514c1 100644
--- a/tools/qdoc3/test/qdeclarative.qdocconf
+++ b/tools/qdoc3/test/qdeclarative.qdocconf
@@ -58,7 +58,8 @@ exampledirs = $QT_SOURCE_TREE/doc/src \
$QT_SOURCE_TREE/src/3rdparty/webkit/WebKit/qt/docs
imagedirs = $QT_SOURCE_TREE/doc/src/images \
$QT_SOURCE_TREE/examples \
- $QT_SOURCE_TREE/doc/src/declarative/pics
+ $QT_SOURCE_TREE/doc/src/declarative/pics \
+ $QT_SOURCE_TREE/doc/src/template/images
outputdir = $QT_BUILD_TREE/doc-build/html-qml
tagfile = $QT_BUILD_TREE/doc-build/html-qml/qt.tags
base = file:$QT_BUILD_TREE/doc/html-qml
diff --git a/tools/qdoc3/test/qmake.qdocconf b/tools/qdoc3/test/qmake.qdocconf
index 76e7012..bd47028 100644
--- a/tools/qdoc3/test/qmake.qdocconf
+++ b/tools/qdoc3/test/qmake.qdocconf
@@ -35,6 +35,7 @@ exampledirs = $QT_SOURCE_TREE \
$QT_SOURCE_TREE/examples \
$QT_SOURCE_TREE/doc/src
-imagedirs = $QT_SOURCE_TREE/doc/src/images
+imagedirs = $QT_SOURCE_TREE/doc/src/images \
+ $QT_SOURCE_TREE/doc/src/template/images
outputdir = $QT_BUILD_TREE/doc-build/html-qmake
base = file:$QT_BUILD_TREE/doc-build/html-qmake
diff --git a/tools/qdoc3/test/qt-build-docs.qdocconf b/tools/qdoc3/test/qt-build-docs.qdocconf
index fb2c3c1..dbff4e2 100644
--- a/tools/qdoc3/test/qt-build-docs.qdocconf
+++ b/tools/qdoc3/test/qt-build-docs.qdocconf
@@ -18,17 +18,45 @@ qhp.Qt.file = qt.qhp
qhp.Qt.namespace = com.trolltech.qt.470
qhp.Qt.virtualFolder = qdoc
qhp.Qt.indexTitle = Qt Reference Documentation
-qhp.Qt.indexRoot =
# Files not referenced in any qdoc file (last four are needed by qtdemo)
# See also extraimages.HTML
-qhp.Qt.extraFiles = classic.css \
+qhp.Qt.extraFiles = index.html \
+ style/style.css \
+ scripts/functions.js \
+ scripts/jquery.js \
+ images/api_examples.png \
+ images/api_lookup.png \
+ images/api_topics.png \
+ images/bg_ll.png \
+ images/bg_l_blank.png \
+ images/bg_l.png \
+ images/bg_lr.png \
+ images/bg_r.png \
+ images/bg_ul_blank.png \
+ images/bg_ul.png \
+ images/bg_ur_blank.png \
+ images/bg_ur.png \
+ images/breadcrumb.png \
+ images/bullet_dn.png \
+ images/bullet_gt.png \
+ images/feedbackground.png \
+ images/form_bg.png \
+ images/horBar.png \
+ images/page_bg.png \
+ images/print.png \
+ images/qt_guide.png \
images/qt-logo.png \
+ images/qt_ref_doc.png \
+ images/qt_tools.png \
+ images/sep.png \
+ images/sprites-combined.png \
images/taskmenuextension-example.png \
images/coloreditorfactoryimage.png \
images/dynamiclayouts-example.png \
images/stylesheet-coffee-plastique.png
+
qhp.Qt.filterAttributes = qt 4.7.0 qtrefdoc
qhp.Qt.customFilters.Qt.name = Qt 4.7.0
qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.0
@@ -106,7 +134,8 @@ exampledirs = $QT_SOURCE_TREE/doc/src \
$QT_SOURCE_TREE/src/3rdparty/webkit/WebKit/qt/docs
imagedirs = $QT_SOURCE_TREE/doc/src/images \
$QT_SOURCE_TREE/examples \
- $QT_SOURCE_TREE/doc/src/declarative/pics
+ $QT_SOURCE_TREE/doc/src/declarative/pics \
+ $QT_SOURCE_TREE/doc/src/template/images
outputdir = $QT_BUILD_TREE/doc/html
tagfile = $QT_BUILD_TREE/doc/html/qt.tags
base = file:$QT_BUILD_TREE/doc/html
diff --git a/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf b/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf
index 7a77f54..461c069 100644
--- a/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf
+++ b/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf
@@ -29,8 +29,36 @@ qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.0
# Files not referenced in any qdoc file (last four are needed by qtdemo)
# See also extraimages.HTML
-qhp.Qt.extraFiles = classic.css \
+qhp.Qt.extraFiles = index.html \
+ style/style.css \
+ scripts/functions.js \
+ scripts/jquery.js \
+ images/api_examples.png \
+ images/api_lookup.png \
+ images/api_topics.png \
+ images/bg_ll.png \
+ images/bg_l_blank.png \
+ images/bg_l.png \
+ images/bg_lr.png \
+ images/bg_r.png \
+ images/bg_ul_blank.png \
+ images/bg_ul.png \
+ images/bg_ur_blank.png \
+ images/bg_ur.png \
+ images/breadcrumb.png \
+ images/bullet_dn.png \
+ images/bullet_gt.png \
+ images/feedbackground.png \
+ images/form_bg.png \
+ images/horBar.png \
+ images/page_bg.png \
+ images/print.png \
+ images/qt_guide.png \
images/qt-logo.png \
+ images/qt_ref_doc.png \
+ images/qt_tools.png \
+ images/sep.png \
+ images/sprites-combined.png \
images/taskmenuextension-example.png \
images/coloreditorfactoryimage.png \
images/dynamiclayouts-example.png \
@@ -76,7 +104,8 @@ exampledirs = $QT_SOURCE_TREE/doc/src \
$QT_SOURCE_TREE/qmake/examples \
$QT_SOURCE_TREE/src/3rdparty/webkit/WebKit/qt/docs
imagedirs = $QT_SOURCE_TREE/doc/src/images \
- $QT_SOURCE_TREE/examples
+ $QT_SOURCE_TREE/examples \
+ $QT_SOURCE_TREE/doc/src/template/images
outputdir = $QT_BUILD_TREE/doc/html_zh_CN
tagfile = $QT_BUILD_TREE/doc/html_zh_CN/qt.tags
base = file:$QT_BUILD_TREE/doc/html_zh_CN
diff --git a/tools/qdoc3/test/qt-defines.qdocconf b/tools/qdoc3/test/qt-defines.qdocconf
index b22727f..7449ac3 100644
--- a/tools/qdoc3/test/qt-defines.qdocconf
+++ b/tools/qdoc3/test/qt-defines.qdocconf
@@ -19,8 +19,50 @@ codeindent = 1
# See also qhp.Qt.extraFiles
extraimages.HTML = qt-logo \
trolltech-logo \
+ api_examples.png \
+ bg_ll.png \
+ bg_ul_blank.png \
+ bullet_gt.png \
+ horBar.png \
+ qt_ref_doc.png \
+ api_lookup.png \
+ bg_ll_blank.png \
+ bg_ur.png \
+ bullet_sq.png \
+ bullet_dn.png \
+ bullet_up.png \
+ page_bg.png \
+ qt_tools.png \
+ api_topics.png \
+ bg_lr.png \
+ bg_ur_blank.png \
+ content_bg.png \
+ print.png \
+ sep.png \
+ bg_l.png \
+ bg_r.png \
+ box_bg.png \
+ feedbackground.png \
+ qt_guide.png \
+ sprites-combined.png \
+ bg_l_blank.png \
+ bg_ul.png \
+ breadcrumb.png \
+ form_bg.png \
+ qt_icon.png \
taskmenuextension-example.png \
coloreditorfactoryimage.png \
dynamiclayouts-example.png \
stylesheet-coffee-plastique.png
- \ No newline at end of file
+
+# This stuff is used by the new doc format.
+scriptdirs = $QT_SOURCE_TREE/doc/src/template/scripts
+styledirs = $QT_SOURCE_TREE/doc/src/template/style
+
+scripts.HTML = functions.js \
+ jquery.js
+
+styles.HTML = style.css \
+ style_ie6.css \
+ style_ie7.css \
+ style_ie8.css
diff --git a/tools/qdoc3/test/qt-html-templates.qdocconf b/tools/qdoc3/test/qt-html-templates.qdocconf
index 60d6b61..67a25f3 100644
--- a/tools/qdoc3/test/qt-html-templates.qdocconf
+++ b/tools/qdoc3/test/qt-html-templates.qdocconf
@@ -1,25 +1,145 @@
-HTML.stylesheets = classic.css
-HTML.postheader = "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n" \
- "<tr>\n" \
- "<td align=\"left\" valign=\"top\" width=\"32\">" \
- "<a href=\"http://qt.nokia.com/\"><img src=\"images/qt-logo.png\" align=\"left\" border=\"0\" /></a>" \
- "</td>\n" \
- "<td width=\"1\">&nbsp;&nbsp;</td>" \
- "<td class=\"postheader\" valign=\"center\">" \
- "<a href=\"index.html\">" \
- "<font color=\"#004faf\">Home</font></a>&nbsp;&middot;" \
- " <a href=\"classes.html\">" \
- "<font color=\"#004faf\">All&nbsp;Classes</font></a>&nbsp;&middot;" \
- " <a href=\"functions.html\">" \
- "<font color=\"#004faf\">All&nbsp;Functions</font></a>&nbsp;&middot;" \
- " <a href=\"overviews.html\">" \
- "<font color=\"#004faf\">Overviews</font></a>" \
- "</td>" \
- "</tr></table>"
+HTML.stylesheets = style/style.css
+HTML.postheader = " <div class=\"header\" id=\"qtdocheader\">\n" \
+ " <div id=\"nav-logo\">\n" \
+ " <a href=\"index.html\">Home</a></div>\n" \
+ " <a href=\"#\" class=\"qtref\"><span>Qt Reference Documentation</span></a>\n" \
+ " <div id=\"nav-topright\">\n" \
+ " <ul>\n" \
+ " <li class=\"nav-topright-home\"><a href=\"http://qt.nokia.com/\">Qt HOME</a></li>\n" \
+ " <li class=\"nav-topright-dev\"><a href=\"http://qt.nokia.com/developer\">DEV</a></li>\n" \
+ " <li class=\"nav-topright-labs\"><a href=\"http://labs.qt.nokia.com/blogs/\">LABS</a></li>\n" \
+ " <li class=\"nav-topright-doc nav-topright-doc-active\"><a href=\"http://doc.qt.nokia.com/\">\n" \
+ " DOC</a></li>\n" \
+ " <li class=\"nav-topright-blog\"><a href=\"http://blog.qt.nokia.com/\">BLOG</a></li>\n" \
+ " <li class=\"nav-topright-shop\"><a title=\"SHOP\" href=\"http://shop.qt.nokia.com\">SHOP</a></li>\n" \
+ " </ul>\n" \
+ " </div>\n" \
+ " <div id=\"shortCut\">\n" \
+ " <ul>\n" \
+ " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">VERSION 4.7</a></span></li>\n" \
+ " <li class=\"shortCut-topleft-active\"><a href=\"http://qt.nokia.com/doc/\">ALL QT VERSIONS" \
+ " </a></li>\n" \
+ " </ul>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " <div class=\"wrapper\">\n" \
+ " <div class=\"hd\">\n" \
+ " <span></span>\n" \
+ " </div>\n" \
+ " <div class=\"bd group\">\n" \
+ " <div class=\"sidebar\">\n" \
+ " <div class=\"searchlabel\">\n" \
+ " Search index:</div>\n" \
+ " <div class=\"search\">\n" \
+ " <form id=\"qtdocsearch\" action=\"#\">\n" \
+ " <fieldset>\n" \
+ " <input type=\"text\" name=\"searchstring\" id=\"searchstring\" value=\"\" onkeyup=\"doSearch(this.value);\" />\n" \
+ " </fieldset>\n" \
+ " </form>\n" \
+ " </div>\n" \
+ " <div class=\"box first bottombar\" id=\"lookup\">\n" \
+ " <h2>\n" \
+ " API Lookup</h2>\n" \
+ " <div class=\"list\">\n" \
+ " <ul>\n" \
+ " <li><a href=\"modules.html\">All modules</a></li>\n" \
+ " <li><a href=\"classes.html\">All classes</a></li>\n" \
+ " <li><a href=\"functions.html\">All functions</a></li>\n" \
+ " <li><a href=\"platform-specific.html\">Platform specifics</a></li>\n" \
+ " </ul>\n" \
+ " </div>\n" \
+ " <div class=\"live\">\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " <div class=\"box bottombar\" id=\"topics\">\n" \
+ " <h2>\n" \
+ " API Topics</h2>\n" \
+ " <div class=\"list\">\n" \
+ " <ul>\n" \
+ " <li><a href=\"object.html\">QObject model</a></li>\n" \
+ " <li><a href=\"eventsandfilters.html\">Events, signals &amp; slots</a></li>\n" \
+ " <li><a href=\"paintsystem.html\">Graphics &amp; Paint system</a></li>\n" \
+ " <li><a href=\"declarativeui.html\">Qt Quick</a></li>\n" \
+ " <li><a href=\"widgets-and-layouts.html\">Widget style &amp; layout</a></li>\n" \
+ " </ul>\n" \
+ " </div>\n" \
+ " <div class=\"live\">\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " <div class=\"box\" id=\"examples\">\n" \
+ " <h2>\n" \
+ " API Examples</h2>\n" \
+ " <div class=\"list\">\n" \
+ " <ul>\n" \
+ " <li><a href=\"examples.html\">All examples</a></li>\n" \
+ " <li><a href=\"tutorials.html\">All tutorials</a></li>\n" \
+ " <li><a href=\"#\">Qt Quick examples</a></li>\n" \
+ " <li><a href=\"#\">Desktop examples</a></li>\n" \
+ " <li><a href=\"#\">Device examples</a></li>\n" \
+ " </ul>\n" \
+ " </div>\n" \
+ " <div class=\"live\">\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " <div class=\"wrap\">\n" \
+ " <div class=\"toolbar\">\n" \
+ " <div class=\"breadcrumb toolblock\">\n" \
+ " <ul>\n" \
+ " <li class=\"first\"><a href=\"index.html\">Home</a></li>\n" \
+ " <!-- Bread crumbs goes here -->\n" \
+ " </ul>\n" \
+ " </div>\n" \
+ " <div class=\"toolbuttons toolblock\">\n" \
+ " <ul>\n" \
+ " <li id=\"smallA\" class=\"t_button\">A</li>\n" \
+ " <li id=\"medA\" class=\"t_button active\">A</li>\n" \
+ " <li id=\"bigA\" class=\"t_button\">A</li>\n" \
+ " <li id=\"print\" class=\"t_button\"><a href=\"javascript:this.print();\">\n" \
+ " <img src=\"images/sep.png\" /><img id=\"printIcon\" src=\"images/print.png\" alt=\"Print this page\" /></a></li>\n" \
+ " </ul>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " <div class=\"content\">\n"
-HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \
- "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \
- "<td width=\"40%\" align=\"left\">Copyright &copy; 2010 Nokia Corporation and/or its subsidiary(-ies)</td>\n" \
- "<td width=\"20%\" align=\"center\"><a href=\"trademarks.html\">Trademarks</a></td>\n" \
- "<td width=\"40%\" align=\"right\"><div align=\"right\">Qt \\version</div></td>\n" \
- "</tr></table></div></address>"
+HTML.footer = " </div>\n" \
+ " <div class=\"feedback t_button\" onclick=\"\$(\'#feedbackBox\').show();\$(\'#blurpage\').show()\">\n" \
+ " [+] Documentation Feedback</div>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " <div class=\"ft\">\n" \
+ " <span></span>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " <div class=\"footer\">\n" \
+ " <p>\n" \
+ " <acronym title=\"Copyright\">&copy;</acronym> 2008-2010 Nokia Corporation and/or its\n" \
+ " subsidiaries. Nokia, Qt and their respective logos are trademarks of Nokia Corporation>\n" \
+ " in Finland and/or other countries worldwide.</p>\n" \
+ " <p>\n" \
+ " All other trademarks are property of their respective owners. <a title=\"Privacy Policy\"\n" \
+ " href=\"http://qt.nokia.com/about/privacy-policy\">Privacy Policy</a></p>\n" \
+ " </div>\n" \
+ " <div id=\"feedbackBox\">\n" \
+ " <form action=\"#\">\n" \
+ " <div id=\"feedcloseX\">\n" \
+ " <a href=\"#\" onclick=\"\$(\'#feedbackBox\').hide();\$(\'#blurpage\').hide()\">X</a>\n" \
+ " </div>\n" \
+ " <textarea id=\"feedbox\" rows=\"5\" cols=\"40\">Please submit you feedback...</textarea>\n" \
+ " <input id=\"feedsubmit\" type=\"submit\" onclick=\"\$(\'#feedbackBox\').hide();\$(\'#blurpage\').hide()\"\n" \
+ " name=\"feedback\" />\n" \
+ " </form>\n" \
+ " </div>\n" \
+ " <div id=\"blurpage\">\n" \
+ " </div>\n" \
+ " <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n" \
+ "<script type=\"text/javascript\">\n" \
+ " var _gaq = _gaq || [];\n" \
+ " _gaq.push([\'_setAccount\', \'UA-4457116-5\']);\n" \
+ " _gaq.push([\'_trackPageview\']);\n" \
+ " (function() {\n" \
+ " var ga = document.createElement(\'script\'); ga.type = \'text/javascript\'; ga.async = true;\n" \
+ " ga.src = (\'https:\' == document.location.protocol ? \'https://ssl\' : \'http://www\') + \'.google-analytics.com/ga.js\';\n" \
+ " var s = document.getElementsByTagName(\'script\')[0]; s.parentNode.insertBefore(ga, s);\n" \
+ " })();\n" \
+ "</script>\n"
diff --git a/tools/qdoc3/test/qt-webxml.qdocconf b/tools/qdoc3/test/qt-webxml.qdocconf
index 3ad0457..80ced42 100644
--- a/tools/qdoc3/test/qt-webxml.qdocconf
+++ b/tools/qdoc3/test/qt-webxml.qdocconf
@@ -2,7 +2,8 @@ include(qt.qdocconf)
quotinginformation = true
imagedirs = $QTDIR/doc/src/images \
- $QTDIR/examples
+ $QTDIR/examples \
+ $QTDIR/doc/src/template/images
outputdir = $QTDIR/doc/webxml
outputformats = WebXML
diff --git a/tools/qdoc3/test/qt.qdocconf b/tools/qdoc3/test/qt.qdocconf
index d8b9136..cc3e436 100644
--- a/tools/qdoc3/test/qt.qdocconf
+++ b/tools/qdoc3/test/qt.qdocconf
@@ -24,8 +24,36 @@ qhp.Qt.indexRoot =
# Files not referenced in any qdoc file (last four are needed by qtdemo)
# See also extraimages.HTML
-qhp.Qt.extraFiles = classic.css \
+qhp.Qt.extraFiles = index.html \
+ style/style.css \
+ scripts/functions.js \
+ scripts/jquery.js \
+ images/api_examples.png \
+ images/api_lookup.png \
+ images/api_topics.png \
+ images/bg_ll.png \
+ images/bg_l_blank.png \
+ images/bg_l.png \
+ images/bg_lr.png \
+ images/bg_r.png \
+ images/bg_ul_blank.png \
+ images/bg_ul.png \
+ images/bg_ur_blank.png \
+ images/bg_ur.png \
+ images/breadcrumb.png \
+ images/bullet_dn.png \
+ images/bullet_gt.png \
+ images/feedbackground.png \
+ images/form_bg.png \
+ images/horBar.png \
+ images/page_bg.png \
+ images/print.png \
+ images/qt_guide.png \
images/qt-logo.png \
+ images/qt_ref_doc.png \
+ images/qt_tools.png \
+ images/sep.png \
+ images/sprites-combined.png \
images/taskmenuextension-example.png \
images/coloreditorfactoryimage.png \
images/dynamiclayouts-example.png \
@@ -108,7 +136,8 @@ exampledirs = $QTDIR/doc/src \
$QTDIR/src/3rdparty/webkit/WebKit/qt/docs
imagedirs = $QTDIR/doc/src/images \
$QTDIR/examples \
- $QTDIR/doc/src/declarative/pics
+ $QTDIR/doc/src/declarative/pics \
+ $QTDIR/doc/src/template/images
outputdir = $QTDIR/doc/html
tagfile = $QTDIR/doc/html/qt.tags
base = file:$QTDIR/doc/html
diff --git a/tools/qdoc3/test/qt_zh_CN.qdocconf b/tools/qdoc3/test/qt_zh_CN.qdocconf
index 8c7e64a..c5d2c88 100644
--- a/tools/qdoc3/test/qt_zh_CN.qdocconf
+++ b/tools/qdoc3/test/qt_zh_CN.qdocconf
@@ -31,8 +31,36 @@ qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.0
# Files not referenced in any qdoc file (last four are needed by qtdemo)
# See also extraimages.HTML
-qhp.Qt.extraFiles = classic.css \
+qhp.Qt.extraFiles = index.html \
+ style/style.css \
+ scripts/functions.js \
+ scripts/jquery.js \
+ images/api_examples.png \
+ images/api_lookup.png \
+ images/api_topics.png \
+ images/bg_ll.png \
+ images/bg_l_blank.png \
+ images/bg_l.png \
+ images/bg_lr.png \
+ images/bg_r.png \
+ images/bg_ul_blank.png \
+ images/bg_ul.png \
+ images/bg_ur_blank.png \
+ images/bg_ur.png \
+ images/breadcrumb.png \
+ images/bullet_dn.png \
+ images/bullet_gt.png \
+ images/feedbackground.png \
+ images/form_bg.png \
+ images/horBar.png \
+ images/page_bg.png \
+ images/print.png \
+ images/qt_guide.png \
images/qt-logo.png \
+ images/qt_ref_doc.png \
+ images/qt_tools.png \
+ images/sep.png \
+ images/sprites-combined.png \
images/taskmenuextension-example.png \
images/coloreditorfactoryimage.png \
images/dynamiclayouts-example.png \
@@ -78,7 +106,8 @@ exampledirs = $QTDIR/doc/src \
$QTDIR/qmake/examples \
$QTDIR/src/3rdparty/webkit/WebKit/qt/docs
imagedirs = $QTDIR/doc/src/images \
- $QTDIR/examples
+ $QTDIR/examples \
+ $QTDIR/doc/src/template/images
outputdir = $QTDIR/doc/html_zh_CN
tagfile = $QTDIR/doc/html_zh_CN/qt.tags
base = file:$QTDIR/doc/html_zh_CN
diff --git a/tools/qdoc3/test/scripts/functions.js b/tools/qdoc3/test/scripts/functions.js
new file mode 100644
index 0000000..0135427
--- /dev/null
+++ b/tools/qdoc3/test/scripts/functions.js
@@ -0,0 +1,60 @@
+
+/* START non link areas where cursor should change to pointing hand */
+$('.t_button').mouseover(function() {
+ $('.t_button').css('cursor','pointer');
+ /*document.getElementById(this.id).style.cursor='pointer';*/
+});
+
+/* END non link areas */
+$('#smallA').click(function() {
+ $('.content .heading,.content h1, .content h2, .content h3, .content p, .content li, .content table').css('font-size','smaller');
+ $('.t_button').removeClass('active')
+ $(this).addClass('active')
+});
+
+$('#medA').click(function() {
+ $('.content .heading').css('font','600 16px/1 Arial');
+ $('.content h1').css('font','600 18px/1.2 Arial');
+ $('.content h2').css('font','600 16px/1.2 Arial');
+ $('.content h3').css('font','600 14px/1.2 Arial');
+ $('.content p').css('font','13px/20px Verdana');
+ $('.content li').css('font','400 13px/1 Verdana');
+ $('.content li').css('line-height','14px');
+ $('.content table').css('font','13px/1.2 Verdana');
+ $('.content .heading').css('font','600 16px/1 Arial');
+ $('.content .indexboxcont li').css('font','600 13px/1 Verdana');
+ $('.t_button').removeClass('active')
+ $(this).addClass('active')
+});
+
+$('#bigA').click(function() {
+ $('.content .heading,.content h1, .content h2, .content h3, .content p, .content li, .content table').css('font-size','large');
+ $('.content .heading,.content h1, .content h2, .content h3, .content p, .content li, .content table').css('line-height','25px');
+ $('.t_button').removeClass('active')
+ $(this).addClass('active')
+});
+
+function doSearch(str){
+
+if (str.length>3)
+ {
+ alert('start search');
+ // document.getElementById("refWrapper").innerHTML="";
+ return;
+ }
+ else
+ return;
+
+// var url="indexSearch.php";
+// url=url+"?q="+str;
+ // url=url+"&sid="+Math.random();
+ // var url="http://localhost:8983/solr/select?";
+ // url=url+"&q="+str;
+ // url=url+"&fq=&start=0&rows=10&fl=&qt=&wt=&explainOther=&hl.fl=";
+
+ // $.get(url, function(data){
+ // alert(data);
+ // document.getElementById("refWrapper").innerHTML=data;
+ //});
+
+} \ No newline at end of file
diff --git a/tools/qdoc3/test/scripts/jquery.js b/tools/qdoc3/test/scripts/jquery.js
new file mode 100644
index 0000000..0c7294c
--- /dev/null
+++ b/tools/qdoc3/test/scripts/jquery.js
@@ -0,0 +1,152 @@
+/*!
+ * jQuery JavaScript Library v1.4.1
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Mon Jan 25 19:43:33 2010 -0500
+ */
+(function(z,v){function la(){if(!c.isReady){try{r.documentElement.doScroll("left")}catch(a){setTimeout(la,1);return}c.ready()}}function Ma(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,i){var j=a.length;if(typeof b==="object"){for(var n in b)X(a,n,b[n],f,e,d);return a}if(d!==v){f=!i&&f&&c.isFunction(d);for(n=0;n<j;n++)e(a[n],b,f?d.call(a[n],n,e(a[n],b)):d,i);return a}return j?
+e(a[0],b):null}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function ma(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function na(a){var b,d=[],f=[],e=arguments,i,j,n,o,m,s,x=c.extend({},c.data(this,"events").live);if(!(a.button&&a.type==="click")){for(o in x){j=x[o];if(j.live===a.type||j.altLive&&c.inArray(a.type,j.altLive)>-1){i=j.data;i.beforeFilter&&i.beforeFilter[a.type]&&!i.beforeFilter[a.type](a)||f.push(j.selector)}else delete x[o]}i=c(a.target).closest(f,
+a.currentTarget);m=0;for(s=i.length;m<s;m++)for(o in x){j=x[o];n=i[m].elem;f=null;if(i[m].selector===j.selector){if(j.live==="mouseenter"||j.live==="mouseleave")f=c(a.relatedTarget).closest(j.selector)[0];if(!f||f!==n)d.push({elem:n,fn:j})}}m=0;for(s=d.length;m<s;m++){i=d[m];a.currentTarget=i.elem;a.data=i.fn.data;if(i.fn.apply(i.elem,e)===false){b=false;break}}return b}}function oa(a,b){return"live."+(a?a+".":"")+b.replace(/\./g,"`").replace(/ /g,"&")}function pa(a){return!a||!a.parentNode||a.parentNode.nodeType===
+11}function qa(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var i in f)for(var j in f[i])c.event.add(this,i,f[i][j],f[i][j].data)}}})}function ra(a,b,d){var f,e,i;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&a[0].indexOf("<option")<0&&(c.support.checkClone||!sa.test(a[0]))){e=true;if(i=c.fragments[a[0]])if(i!==1)f=i}if(!f){b=b&&b[0]?b[0].ownerDocument||b[0]:r;f=b.createDocumentFragment();
+c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=i?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(ta.concat.apply([],ta.slice(0,b)),function(){d[this]=a});return d}function ua(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Na=z.jQuery,Oa=z.$,r=z.document,S,Pa=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Qa=/^.[^:#\[\.,]*$/,Ra=/\S/,Sa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Ta=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,O=navigator.userAgent,
+va=false,P=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,Q=Array.prototype.slice,wa=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(typeof a==="string")if((d=Pa.exec(a))&&(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:r;if(a=Ta.exec(a))if(c.isPlainObject(b)){a=[r.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=ra([d[1]],
+[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}}else{if(b=r.getElementById(d[2])){if(b.id!==d[2])return S.find(a);this.length=1;this[0]=b}this.context=r;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=r;a=r.getElementsByTagName(a)}else return!b||b.jquery?(b||S).find(a):c(b).find(a);else if(c.isFunction(a))return S.ready(a);if(a.selector!==v){this.selector=a.selector;this.context=a.context}return c.isArray(a)?this.setArray(a):c.makeArray(a,
+this)},selector:"",jquery:"1.4.1",length:0,size:function(){return this.length},toArray:function(){return Q.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){a=c(a||null);a.prevObject=this;a.context=this.context;if(b==="find")a.selector=this.selector+(this.selector?" ":"")+d;else if(b)a.selector=this.selector+"."+b+"("+d+")";return a},setArray:function(a){this.length=0;ba.apply(this,a);return this},each:function(a,b){return c.each(this,
+a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(r,c);else P&&P.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(Q.apply(this,arguments),"slice",Q.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};
+c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,i,j,n;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(i in e){j=a[i];n=e[i];if(a!==n)if(f&&n&&(c.isPlainObject(n)||c.isArray(n))){j=j&&(c.isPlainObject(j)||c.isArray(j))?j:c.isArray(n)?[]:{};a[i]=c.extend(f,j,n)}else if(n!==v)a[i]=n}return a};c.extend({noConflict:function(a){z.$=
+Oa;if(a)z.jQuery=Na;return c},isReady:false,ready:function(){if(!c.isReady){if(!r.body)return setTimeout(c.ready,13);c.isReady=true;if(P){for(var a,b=0;a=P[b++];)a.call(r,c);P=null}c.fn.triggerHandler&&c(r).triggerHandler("ready")}},bindReady:function(){if(!va){va=true;if(r.readyState==="complete")return c.ready();if(r.addEventListener){r.addEventListener("DOMContentLoaded",L,false);z.addEventListener("load",c.ready,false)}else if(r.attachEvent){r.attachEvent("onreadystatechange",L);z.attachEvent("onload",
+c.ready);var a=false;try{a=z.frameElement==null}catch(b){}r.documentElement.doScroll&&a&&la()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,"isPrototypeOf"))return false;var b;for(b in a);return b===v||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;
+return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return z.JSON&&z.JSON.parse?z.JSON.parse(a):(new Function("return "+a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Ra.test(a)){var b=r.getElementsByTagName("head")[0]||
+r.documentElement,d=r.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(r.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,i=a.length,j=i===v||c.isFunction(a);if(d)if(j)for(f in a){if(b.apply(a[f],d)===false)break}else for(;e<i;){if(b.apply(a[e++],d)===false)break}else if(j)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=
+a[0];e<i&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Sa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==
+v;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,i=a.length;e<i;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,i=0,j=a.length;i<j;i++){e=b(a[i],i,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=v}else if(b&&!c.isFunction(b)){d=b;b=v}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},
+uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});O=c.uaMatch(O);if(O.browser){c.browser[O.browser]=true;c.browser.version=O.version}if(c.browser.webkit)c.browser.safari=true;if(wa)c.inArray=function(a,b){return wa.call(b,a)};S=c(r);if(r.addEventListener)L=function(){r.removeEventListener("DOMContentLoaded",
+L,false);c.ready()};else if(r.attachEvent)L=function(){if(r.readyState==="complete"){r.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=r.documentElement,b=r.createElement("script"),d=r.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var e=d.getElementsByTagName("*"),i=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!i)){c.support=
+{leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(i.getAttribute("style")),hrefNormalized:i.getAttribute("href")==="/a",opacity:/^0.55$/.test(i.style.opacity),cssFloat:!!i.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:r.createElement("select").appendChild(r.createElement("option")).selected,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};
+b.type="text/javascript";try{b.appendChild(r.createTextNode("window."+f+"=1;"))}catch(j){}a.insertBefore(b,a.firstChild);if(z[f]){c.support.scriptEval=true;delete z[f]}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function n(){c.support.noCloneEvent=false;d.detachEvent("onclick",n)});d.cloneNode(true).fireEvent("onclick")}d=r.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=r.createDocumentFragment();a.appendChild(d.firstChild);
+c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var n=r.createElement("div");n.style.width=n.style.paddingLeft="1px";r.body.appendChild(n);c.boxModel=c.support.boxModel=n.offsetWidth===2;r.body.removeChild(n).style.display="none"});a=function(n){var o=r.createElement("div");n="on"+n;var m=n in o;if(!m){o.setAttribute(n,"return;");m=typeof o[n]==="function"}return m};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=i=null}})();c.props=
+{"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ua=0,xa={},Va={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==z?xa:a;var f=a[G],e=c.cache;if(!b&&!f)return null;f||(f=++Ua);if(typeof b==="object"){a[G]=f;e=e[f]=c.extend(true,
+{},b)}else e=e[f]?e[f]:typeof d==="undefined"?Va:(e[f]={});if(d!==v){a[G]=f;e[b]=d}return typeof b==="string"?e[b]:e}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==z?xa:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{try{delete a[G]}catch(i){a.removeAttribute&&a.removeAttribute(G)}delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,
+a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===v){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===v&&this.length)f=c.data(this[0],a);return f===v&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);
+return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===v)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||
+a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var ya=/[\n\t]/g,ca=/\s+/,Wa=/\r/g,Xa=/href|src|style/,Ya=/(button|input)/i,Za=/(button|input|object|select|textarea)/i,$a=/^(a|area)$/i,za=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(o){var m=
+c(this);m.addClass(a.call(this,o,m.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className)for(var i=" "+e.className+" ",j=0,n=b.length;j<n;j++){if(i.indexOf(" "+b[j]+" ")<0)e.className+=" "+b[j]}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(o){var m=c(this);m.removeClass(a.call(this,o,m.attr("class")))});if(a&&typeof a==="string"||a===v)for(var b=(a||"").split(ca),
+d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var i=(" "+e.className+" ").replace(ya," "),j=0,n=b.length;j<n;j++)i=i.replace(" "+b[j]+" "," ");e.className=i.substring(1,i.length-1)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var i=c(this);i.toggleClass(a.call(this,e,i.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,i=0,j=c(this),n=b,o=
+a.split(ca);e=o[i++];){n=f?n:!j.hasClass(e);j[n?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(ya," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===v){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||
+{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var i=b?d:0;for(d=b?d+1:e.length;i<d;i++){var j=e[i];if(j.selected){a=c(j).val();if(b)return a;f.push(a)}}return f}if(za.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Wa,"")}return v}var n=c.isFunction(a);return this.each(function(o){var m=c(this),s=a;if(this.nodeType===1){if(n)s=a.call(this,o,m.val());
+if(typeof s==="number")s+="";if(c.isArray(s)&&za.test(this.type))this.checked=c.inArray(m.val(),s)>=0;else if(c.nodeName(this,"select")){var x=c.makeArray(s);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),x)>=0});if(!x.length)this.selectedIndex=-1}else this.value=s}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return v;if(f&&b in c.attrFn)return c(a)[b](d);
+f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==v;b=f&&c.props[b]||b;if(a.nodeType===1){var i=Xa.test(b);if(b in a&&f&&!i){if(e){b==="type"&&Ya.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:Za.test(a.nodeName)||$a.test(a.nodeName)&&a.href?0:v;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=
+""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&i?a.getAttribute(b,2):a.getAttribute(b);return a===null?v:a}return c.style(a,b,d)}});var ab=function(a){return a.replace(/[^\w\s\.\|`]/g,function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==z&&!a.frameElement)a=z;if(!d.guid)d.guid=c.guid++;if(f!==v){d=c.proxy(d);d.data=f}var e=c.data(a,"events")||c.data(a,"events",{}),i=c.data(a,"handle"),j;if(!i){j=
+function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(j.elem,arguments):v};i=c.data(a,"handle",j)}if(i){i.elem=a;b=b.split(/\s+/);for(var n,o=0;n=b[o++];){var m=n.split(".");n=m.shift();if(o>1){d=c.proxy(d);if(f!==v)d.data=f}d.type=m.slice(0).sort().join(".");var s=e[n],x=this.special[n]||{};if(!s){s=e[n]={};if(!x.setup||x.setup.call(a,f,m,d)===false)if(a.addEventListener)a.addEventListener(n,i,false);else a.attachEvent&&a.attachEvent("on"+n,i)}if(x.add)if((m=x.add.call(a,
+d,f,m,s))&&c.isFunction(m)){m.guid=m.guid||d.guid;m.data=m.data||d.data;m.type=m.type||d.type;d=m}s[d.guid]=d;this.global[n]=true}a=null}}},global:{},remove:function(a,b,d){if(!(a.nodeType===3||a.nodeType===8)){var f=c.data(a,"events"),e,i,j;if(f){if(b===v||typeof b==="string"&&b.charAt(0)===".")for(i in f)this.remove(a,i+(b||""));else{if(b.type){d=b.handler;b=b.type}b=b.split(/\s+/);for(var n=0;i=b[n++];){var o=i.split(".");i=o.shift();var m=!o.length,s=c.map(o.slice(0).sort(),ab);s=new RegExp("(^|\\.)"+
+s.join("\\.(?:.*\\.)?")+"(\\.|$)");var x=this.special[i]||{};if(f[i]){if(d){j=f[i][d.guid];delete f[i][d.guid]}else for(var A in f[i])if(m||s.test(f[i][A].type))delete f[i][A];x.remove&&x.remove.call(a,o,j);for(e in f[i])break;if(!e){if(!x.teardown||x.teardown.call(a,o)===false)if(a.removeEventListener)a.removeEventListener(i,c.data(a,"handle"),false);else a.detachEvent&&a.detachEvent("on"+i,c.data(a,"handle"));e=null;delete f[i]}}}}for(e in f)break;if(!e){if(A=c.data(a,"handle"))A.elem=null;c.removeData(a,
+"events");c.removeData(a,"handle")}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();this.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return v;a.result=v;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,
+b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(i){}if(!a.isPropagationStopped()&&f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){d=a.target;var j;if(!(c.nodeName(d,"a")&&e==="click")&&!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()])){try{if(d[e]){if(j=d["on"+e])d["on"+e]=null;this.triggered=true;d[e]()}}catch(n){}if(j)d["on"+e]=j;this.triggered=false}}},handle:function(a){var b,
+d;a=arguments[0]=c.event.fix(a||z.event);a.currentTarget=this;d=a.type.split(".");a.type=d.shift();b=!d.length&&!a.exclusive;var f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)");d=(c.data(this,"events")||{})[a.type];for(var e in d){var i=d[e];if(b||f.test(i.type)){a.handler=i;a.data=i.data;i=i.apply(this,arguments);if(i!==v){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||r;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=r.documentElement;d=r.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
+d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==v)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a,b){c.extend(a,b||{});a.guid+=b.selector+b.live;b.liveProxy=a;c.event.add(this,b.live,na,b)},remove:function(a){if(a.length){var b=
+0,d=new RegExp("(^|\\.)"+a[0]+"(\\.|$)");c.each(c.data(this,"events").live||{},function(){d.test(this.type)&&b++});b<1&&c.event.remove(this,a[0],na)}},special:{}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};
+c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y};var Aa=function(a){for(var b=
+a.relatedTarget;b&&b!==this;)try{b=b.parentNode}catch(d){break}if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}},Ba=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ba:Aa,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ba:Aa)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(a,b,d){if(this.nodeName.toLowerCase()!==
+"form"){c.event.add(this,"click.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="submit"||i==="image")&&c(e).closest("form").length)return ma("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="text"||i==="password")&&c(e).closest("form").length&&f.keyCode===13)return ma("submit",this,arguments)})}else return false},remove:function(a,b){c.event.remove(this,"click.specialSubmit"+(b?"."+b.guid:""));c.event.remove(this,
+"keypress.specialSubmit"+(b?"."+b.guid:""))}};if(!c.support.changeBubbles){var da=/textarea|input|select/i;function Ca(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d}function ea(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Ca(d);if(a.type!=="focusout"||
+d.type!=="radio")c.data(d,"_change_data",e);if(!(f===v||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}}c.event.special.change={filters:{focusout:ea,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return ea.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return ea.call(this,a)},beforeactivate:function(a){a=
+a.target;a.nodeName.toLowerCase()==="input"&&a.type==="radio"&&c.data(a,"_change_data",Ca(a))}},setup:function(a,b,d){for(var f in T)c.event.add(this,f+".specialChange."+d.guid,T[f]);return da.test(this.nodeName)},remove:function(a,b){for(var d in T)c.event.remove(this,d+".specialChange"+(b?"."+b.guid:""),T[d]);return da.test(this.nodeName)}};var T=c.event.special.change.filters}r.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,
+f)}c.event.special[b]={setup:function(){this.addEventListener(a,d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var i in d)this[b](i,f,d[i],e);return this}if(c.isFunction(f)){e=f;f=v}var j=b==="one"?c.proxy(e,function(n){c(this).unbind(n,j);return e.apply(this,arguments)}):e;return d==="unload"&&b!=="one"?this.one(d,f,e):this.each(function(){c.event.add(this,d,j,f)})}});c.fn.extend({unbind:function(a,
+b){if(typeof a==="object"&&!a.preventDefault){for(var d in a)this.unbind(d,a[d]);return this}return this.each(function(){c.event.remove(this,a,b)})},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+
+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e){var i,j=0;if(c.isFunction(f)){e=f;f=v}for(d=(d||"").split(/\s+/);(i=d[j++])!=null;){i=i==="focus"?"focusin":i==="blur"?"focusout":i==="hover"?d.push("mouseleave")&&"mouseenter":i;b==="live"?c(this.context).bind(oa(i,this.selector),{data:f,selector:this.selector,
+live:i},e):c(this.context).unbind(oa(i,this.selector),e?{guid:e.guid+this.selector+i}:null)}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});z.attachEvent&&!z.addEventListener&&z.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});
+(function(){function a(g){for(var h="",k,l=0;g[l];l++){k=g[l];if(k.nodeType===3||k.nodeType===4)h+=k.nodeValue;else if(k.nodeType!==8)h+=a(k.childNodes)}return h}function b(g,h,k,l,q,p){q=0;for(var u=l.length;q<u;q++){var t=l[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===k){y=l[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=k;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}l[q]=y}}}function d(g,h,k,l,q,p){q=0;for(var u=l.length;q<u;q++){var t=l[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===
+k){y=l[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=k;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(o.filter(h,[t]).length>0){y=t;break}}t=t[g]}l[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,i=Object.prototype.toString,j=false,n=true;[0,0].sort(function(){n=false;return 0});var o=function(g,h,k,l){k=k||[];var q=h=h||r;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||
+typeof g!=="string")return k;for(var p=[],u,t,y,R,H=true,M=w(h),I=g;(f.exec(""),u=f.exec(I))!==null;){I=u[3];p.push(u[1]);if(u[2]){R=u[3];break}}if(p.length>1&&s.exec(g))if(p.length===2&&m.relative[p[0]])t=fa(p[0]+p[1],h);else for(t=m.relative[p[0]]?[h]:o(p.shift(),h);p.length;){g=p.shift();if(m.relative[g])g+=p.shift();t=fa(g,t)}else{if(!l&&p.length>1&&h.nodeType===9&&!M&&m.match.ID.test(p[0])&&!m.match.ID.test(p[p.length-1])){u=o.find(p.shift(),h,M);h=u.expr?o.filter(u.expr,u.set)[0]:u.set[0]}if(h){u=
+l?{expr:p.pop(),set:A(l)}:o.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=u.expr?o.filter(u.expr,u.set):u.set;if(p.length>0)y=A(t);else H=false;for(;p.length;){var D=p.pop();u=D;if(m.relative[D])u=p.pop();else D="";if(u==null)u=h;m.relative[D](y,u,M)}}else y=[]}y||(y=t);y||o.error(D||g);if(i.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))k.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&
+y[g].nodeType===1&&k.push(t[g]);else k.push.apply(k,y);else A(y,k);if(R){o(R,q,k,l);o.uniqueSort(k)}return k};o.uniqueSort=function(g){if(C){j=n;g.sort(C);if(j)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};o.matches=function(g,h){return o(g,null,null,h)};o.find=function(g,h,k){var l,q;if(!g)return[];for(var p=0,u=m.order.length;p<u;p++){var t=m.order[p];if(q=m.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");l=m.find[t](q,
+h,k);if(l!=null){g=g.replace(m.match[t],"");break}}}}l||(l=h.getElementsByTagName("*"));return{set:l,expr:g}};o.filter=function(g,h,k,l){for(var q=g,p=[],u=h,t,y,R=h&&h[0]&&w(h[0]);g&&h.length;){for(var H in m.filter)if((t=m.leftMatch[H].exec(g))!=null&&t[2]){var M=m.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-1)!=="\\"){if(u===p)p=[];if(m.preFilter[H])if(t=m.preFilter[H](t,u,k,p,l,R)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=u[U])!=null;U++)if(D){I=M(D,t,U,u);var Da=
+l^!!I;if(k&&I!=null)if(Da)y=true;else u[U]=false;else if(Da){p.push(D);y=true}}if(I!==v){k||(u=p);g=g.replace(m.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)o.error(g);else break;q=g}return u};o.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var m=o.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
+TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},relative:{"+":function(g,h){var k=typeof h==="string",l=k&&!/\W/.test(h);k=k&&!l;if(l)h=h.toLowerCase();l=0;for(var q=g.length,
+p;l<q;l++)if(p=g[l]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[l]=k||p&&p.nodeName.toLowerCase()===h?p||false:p===h}k&&o.filter(h,g,true)},">":function(g,h){var k=typeof h==="string";if(k&&!/\W/.test(h)){h=h.toLowerCase();for(var l=0,q=g.length;l<q;l++){var p=g[l];if(p){k=p.parentNode;g[l]=k.nodeName.toLowerCase()===h?k:false}}}else{l=0;for(q=g.length;l<q;l++)if(p=g[l])g[l]=k?p.parentNode:p.parentNode===h;k&&o.filter(h,g,true)}},"":function(g,h,k){var l=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=
+h=h.toLowerCase();q=b}q("parentNode",h,l,g,p,k)},"~":function(g,h,k){var l=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,l,g,p,k)}},find:{ID:function(g,h,k){if(typeof h.getElementById!=="undefined"&&!k)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var k=[];h=h.getElementsByName(g[1]);for(var l=0,q=h.length;l<q;l++)h[l].getAttribute("name")===g[1]&&k.push(h[l]);return k.length===0?null:k}},
+TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,k,l,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var u;(u=h[p])!=null;p++)if(u)if(q^(u.className&&(" "+u.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))k||l.push(u);else if(k)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&
+"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,k,l,q,p){h=g[1].replace(/\\/g,"");if(!p&&m.attrMap[h])g[1]=m.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,k,l,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=o(g[3],null,null,h);else{g=o.filter(g[3],h,k,true^q);k||l.push.apply(l,g);return false}else if(m.match.POS.test(g[0])||m.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);
+return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,k){return!!o(k[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===
+g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,h){return h===0},last:function(g,h,k,l){return h===l.length-1},even:function(g,h){return h%2===
+0},odd:function(g,h){return h%2===1},lt:function(g,h,k){return h<k[3]-0},gt:function(g,h,k){return h>k[3]-0},nth:function(g,h,k){return k[3]-0===h},eq:function(g,h,k){return k[3]-0===h}},filter:{PSEUDO:function(g,h,k,l){var q=h[1],p=m.filters[q];if(p)return p(g,k,h,l);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=h[3];k=0;for(l=h.length;k<l;k++)if(h[k]===g)return false;return true}else o.error("Syntax error, unrecognized expression: "+
+q)},CHILD:function(g,h){var k=h[1],l=g;switch(k){case "only":case "first":for(;l=l.previousSibling;)if(l.nodeType===1)return false;if(k==="first")return true;l=g;case "last":for(;l=l.nextSibling;)if(l.nodeType===1)return false;return true;case "nth":k=h[2];var q=h[3];if(k===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var u=0;for(l=p.firstChild;l;l=l.nextSibling)if(l.nodeType===1)l.nodeIndex=++u;p.sizcache=h}g=g.nodeIndex-q;return k===0?g===0:g%k===0&&g/k>=
+0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var k=h[1];g=m.attrHandle[k]?m.attrHandle[k](g):g[k]!=null?g[k]:g.getAttribute(k);k=g+"";var l=h[2];h=h[4];return g==null?l==="!=":l==="="?k===h:l==="*="?k.indexOf(h)>=0:l==="~="?(" "+k+" ").indexOf(h)>=0:!h?k&&g!==false:l==="!="?k!==h:l==="^="?
+k.indexOf(h)===0:l==="$="?k.substr(k.length-h.length)===h:l==="|="?k===h||k.substr(0,h.length+1)===h+"-":false},POS:function(g,h,k,l){var q=m.setFilters[h[2]];if(q)return q(g,k,h,l)}}},s=m.match.POS;for(var x in m.match){m.match[x]=new RegExp(m.match[x].source+/(?![^\[]*\])(?![^\(]*\))/.source);m.leftMatch[x]=new RegExp(/(^(?:.|\r|\n)*?)/.source+m.match[x].source.replace(/\\(\d+)/g,function(g,h){return"\\"+(h-0+1)}))}var A=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};
+try{Array.prototype.slice.call(r.documentElement.childNodes,0)}catch(B){A=function(g,h){h=h||[];if(i.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var k=0,l=g.length;k<l;k++)h.push(g[k]);else for(k=0;g[k];k++)h.push(g[k]);return h}}var C;if(r.documentElement.compareDocumentPosition)C=function(g,h){if(!g.compareDocumentPosition||!h.compareDocumentPosition){if(g==h)j=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===
+h?0:1;if(g===0)j=true;return g};else if("sourceIndex"in r.documentElement)C=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)j=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)j=true;return g};else if(r.createRange)C=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)j=true;return g.ownerDocument?-1:1}var k=g.ownerDocument.createRange(),l=h.ownerDocument.createRange();k.setStart(g,0);k.setEnd(g,0);l.setStart(h,0);l.setEnd(h,0);g=k.compareBoundaryPoints(Range.START_TO_END,
+l);if(g===0)j=true;return g};(function(){var g=r.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var k=r.documentElement;k.insertBefore(g,k.firstChild);if(r.getElementById(h)){m.find.ID=function(l,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(l[1]))?q.id===l[1]||typeof q.getAttributeNode!=="undefined"&&q.getAttributeNode("id").nodeValue===l[1]?[q]:v:[]};m.filter.ID=function(l,q){var p=typeof l.getAttributeNode!=="undefined"&&l.getAttributeNode("id");
+return l.nodeType===1&&p&&p.nodeValue===q}}k.removeChild(g);k=g=null})();(function(){var g=r.createElement("div");g.appendChild(r.createComment(""));if(g.getElementsByTagName("*").length>0)m.find.TAG=function(h,k){k=k.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var l=0;k[l];l++)k[l].nodeType===1&&h.push(k[l]);k=h}return k};g.innerHTML="<a href='#'></a>";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")m.attrHandle.href=function(h){return h.getAttribute("href",
+2)};g=null})();r.querySelectorAll&&function(){var g=o,h=r.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){o=function(l,q,p,u){q=q||r;if(!u&&q.nodeType===9&&!w(q))try{return A(q.querySelectorAll(l),p)}catch(t){}return g(l,q,p,u)};for(var k in g)o[k]=g[k];h=null}}();(function(){var g=r.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===
+0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){m.order.splice(1,0,"CLASS");m.find.CLASS=function(h,k,l){if(typeof k.getElementsByClassName!=="undefined"&&!l)return k.getElementsByClassName(h[1])};g=null}}})();var E=r.compareDocumentPosition?function(g,h){return g.compareDocumentPosition(h)&16}:function(g,h){return g!==h&&(g.contains?g.contains(h):true)},w=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},fa=function(g,h){var k=[],
+l="",q;for(h=h.nodeType?[h]:h;q=m.match.PSEUDO.exec(g);){l+=q[0];g=g.replace(m.match.PSEUDO,"")}g=m.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)o(g,h[q],k);return o.filter(l,k)};c.find=o;c.expr=o.selectors;c.expr[":"]=c.expr.filters;c.unique=o.uniqueSort;c.getText=a;c.isXMLDoc=w;c.contains=E})();var bb=/Until$/,cb=/^(?:parents|prevUntil|prevAll)/,db=/,/;Q=Array.prototype.slice;var Ea=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,i){return!!b.call(e,i,e)===d});else if(b.nodeType)return c.grep(a,
+function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Qa.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;c.find(a,this[f],b);if(f>0)for(var i=d;i<b.length;i++)for(var j=0;j<d;j++)if(b[j]===b[i]){b.splice(i--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=
+0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ea(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ea(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,i={},j;if(f&&a.length){e=0;for(var n=a.length;e<n;e++){j=a[e];i[j]||(i[j]=c.expr.match.POS.test(j)?c(j,b||this.context):j)}for(;f&&f.ownerDocument&&f!==b;){for(j in i){e=i[j];if(e.jquery?e.index(f)>
+-1:c(f).is(e)){d.push({selector:j,elem:f});delete i[j]}}f=f.parentNode}}return d}var o=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(m,s){for(;s&&s.ownerDocument&&s!==b;){if(o?o.index(s)>-1:c(s).is(a))return s;s=s.parentNode}return null})},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),
+a);return this.pushStack(pa(a[0])||pa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},
+nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);bb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):
+e;if((this.length>1||db.test(f))&&cb.test(a))e=e.reverse();return this.pushStack(e,a,Q.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===v||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==
+b&&d.push(a);return d}});var Fa=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ga=/(<([\w:]+)[^>]*?)\/>/g,eb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,Ha=/<([\w:]+)/,fb=/<tbody/i,gb=/<|&\w+;/,sa=/checked\s*(?:[^=]|=\s*.checked.)/i,Ia=function(a,b,d){return eb.test(d)?a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],
+col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==v)return this.empty().append((this[0]&&this[0].ownerDocument||r).createTextNode(a));return c.getText(this)},
+wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?
+d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,
+false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&
+!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Fa,"").replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){qa(this,b);qa(this.find("*"),b.find("*"))}return b},html:function(a){if(a===v)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Fa,""):null;else if(typeof a==="string"&&!/<script/i.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(Ha.exec(a)||
+["",""])[1].toLowerCase()]){a=a.replace(Ga,Ia);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var i=c(this),j=i.html();i.empty().append(function(){return a.call(this,e,j)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,
+b,f))});else a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(s){return c.nodeName(s,"table")?s.getElementsByTagName("tbody")[0]||s.appendChild(s.ownerDocument.createElement("tbody")):s}var e,i,j=a[0],n=[];if(!c.support.checkClone&&arguments.length===3&&typeof j===
+"string"&&sa.test(j))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(j))return this.each(function(s){var x=c(this);a[0]=j.call(this,s,b?x.html():v);x.domManip(a,b,d)});if(this[0]){e=a[0]&&a[0].parentNode&&a[0].parentNode.nodeType===11?{fragment:a[0].parentNode}:ra(a,this,n);if(i=e.fragment.firstChild){b=b&&c.nodeName(i,"tr");for(var o=0,m=this.length;o<m;o++)d.call(b?f(this[o],i):this[o],e.cacheable||this.length>1||o>0?e.fragment.cloneNode(true):e.fragment)}n&&c.each(n,
+Ma)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);for(var e=0,i=d.length;e<i;e++){var j=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),j);f=f.concat(j)}return this.pushStack(f,a,d.selector)}});c.each({remove:function(a,b){if(!a||c.filter(a,[this]).length){if(!b&&this.nodeType===1){c.cleanData(this.getElementsByTagName("*"));c.cleanData([this])}this.parentNode&&
+this.parentNode.removeChild(this)}},empty:function(){for(this.nodeType===1&&c.cleanData(this.getElementsByTagName("*"));this.firstChild;)this.removeChild(this.firstChild)}},function(a,b){c.fn[a]=function(){return this.each(b,arguments)}});c.extend({clean:function(a,b,d,f){b=b||r;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||r;var e=[];c.each(a,function(i,j){if(typeof j==="number")j+="";if(j){if(typeof j==="string"&&!gb.test(j))j=b.createTextNode(j);else if(typeof j===
+"string"){j=j.replace(Ga,Ia);var n=(Ha.exec(j)||["",""])[1].toLowerCase(),o=F[n]||F._default,m=o[0];i=b.createElement("div");for(i.innerHTML=o[1]+j+o[2];m--;)i=i.lastChild;if(!c.support.tbody){m=fb.test(j);n=n==="table"&&!m?i.firstChild&&i.firstChild.childNodes:o[1]==="<table>"&&!m?i.childNodes:[];for(o=n.length-1;o>=0;--o)c.nodeName(n[o],"tbody")&&!n[o].childNodes.length&&n[o].parentNode.removeChild(n[o])}!c.support.leadingWhitespace&&V.test(j)&&i.insertBefore(b.createTextNode(V.exec(j)[0]),i.firstChild);
+j=c.makeArray(i.childNodes)}if(j.nodeType)e.push(j);else e=c.merge(e,j)}});if(d)for(a=0;e[a];a++)if(f&&c.nodeName(e[a],"script")&&(!e[a].type||e[a].type.toLowerCase()==="text/javascript"))f.push(e[a].parentNode?e[a].parentNode.removeChild(e[a]):e[a]);else{e[a].nodeType===1&&e.splice.apply(e,[a+1,0].concat(c.makeArray(e[a].getElementsByTagName("script"))));d.appendChild(e[a])}return e},cleanData:function(a){for(var b=0,d;(d=a[b])!=null;b++){c.event.remove(d);c.removeData(d)}}});var hb=/z-?index|font-?weight|opacity|zoom|line-?height/i,
+Ja=/alpha\([^)]*\)/,Ka=/opacity=([^)]*)/,ga=/float/i,ha=/-([a-z])/ig,ib=/([A-Z])/g,jb=/^-?\d+(?:px)?$/i,kb=/^-?\d/,lb={position:"absolute",visibility:"hidden",display:"block"},mb=["Left","Right"],nb=["Top","Bottom"],ob=r.defaultView&&r.defaultView.getComputedStyle,La=c.support.cssFloat?"cssFloat":"styleFloat",ia=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===v)return c.curCSS(d,f);if(typeof e==="number"&&!hb.test(f))e+="px";c.style(d,f,e)})};
+c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return v;if((b==="width"||b==="height")&&parseFloat(d)<0)d=v;var f=a.style||a,e=d!==v;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=Ja.test(a)?a.replace(Ja,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Ka.exec(f.filter)[1])/100+"":""}if(ga.test(b))b=La;b=b.replace(ha,ia);if(e)f[b]=d;return f[b]},css:function(a,
+b,d,f){if(b==="width"||b==="height"){var e,i=b==="width"?mb:nb;function j(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(i,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,"border"+this+"Width",true))||0})}a.offsetWidth!==0?j():c.swap(a,lb,j);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&
+a.currentStyle){f=Ka.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ga.test(b))b=La;if(!d&&e&&e[b])f=e[b];else if(ob){if(ga.test(b))b="float";b=b.replace(ib,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ha,ia);f=a.currentStyle[b]||a.currentStyle[d];if(!jb.test(f)&&kb.test(f)){b=e.left;var i=a.runtimeStyle.left;a.runtimeStyle.left=
+a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=i}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var pb=
+J(),qb=/<script(.|\s)*?\/script>/gi,rb=/select|textarea/i,sb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ja=/\?/,tb=/(\?|&)_=.*?(&|$)/,ub=/^(\w+:)?\/\/([^\/?#]+)/,vb=/%20/g;c.fn.extend({_load:c.fn.load,load:function(a,b,d){if(typeof a!=="string")return this._load(a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=
+c.param(b,c.ajaxSettings.traditional);f="POST"}var i=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(j,n){if(n==="success"||n==="notmodified")i.html(e?c("<div />").append(j.responseText.replace(qb,"")).find(e):j.responseText);d&&i.each(d,[j.responseText,n,j])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&
+(this.checked||rb.test(this.nodeName)||sb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,
+b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:z.XMLHttpRequest&&(z.location.protocol!=="file:"||!z.ActiveXObject)?function(){return new z.XMLHttpRequest}:
+function(){try{return new z.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&e.success.call(o,n,j,w);e.global&&f("ajaxSuccess",[w,e])}function d(){e.complete&&e.complete.call(o,w,j);e.global&&f("ajaxComplete",[w,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}
+function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),i,j,n,o=a&&a.context||e,m=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(m==="GET")N.test(e.url)||(e.url+=(ja.test(e.url)?"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||
+N.test(e.url))){i=e.jsonpCallback||"jsonp"+pb++;if(e.data)e.data=(e.data+"").replace(N,"="+i+"$1");e.url=e.url.replace(N,"="+i+"$1");e.dataType="script";z[i]=z[i]||function(q){n=q;b();d();z[i]=v;try{delete z[i]}catch(p){}A&&A.removeChild(B)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===false&&m==="GET"){var s=J(),x=e.url.replace(tb,"$1_="+s+"$2");e.url=x+(x===e.url?(ja.test(e.url)?"&":"?")+"_="+s:"")}if(e.data&&m==="GET")e.url+=(ja.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&
+c.event.trigger("ajaxStart");s=(s=ub.exec(e.url))&&(s[1]&&s[1]!==location.protocol||s[2]!==location.host);if(e.dataType==="script"&&m==="GET"&&s){var A=r.getElementsByTagName("head")[0]||r.documentElement,B=r.createElement("script");B.src=e.url;if(e.scriptCharset)B.charset=e.scriptCharset;if(!i){var C=false;B.onload=B.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;b();d();B.onload=B.onreadystatechange=null;A&&B.parentNode&&
+A.removeChild(B)}}}A.insertBefore(B,A.firstChild);return v}var E=false,w=e.xhr();if(w){e.username?w.open(m,e.url,e.async,e.username,e.password):w.open(m,e.url,e.async);try{if(e.data||a&&a.contentType)w.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[e.url]);c.etag[e.url]&&w.setRequestHeader("If-None-Match",c.etag[e.url])}s||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",
+e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(fa){}if(e.beforeSend&&e.beforeSend.call(o,w,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");w.abort();return false}e.global&&f("ajaxSend",[w,e]);var g=w.onreadystatechange=function(q){if(!w||w.readyState===0||q==="abort"){E||d();E=true;if(w)w.onreadystatechange=c.noop}else if(!E&&w&&(w.readyState===4||q==="timeout")){E=true;w.onreadystatechange=c.noop;j=q==="timeout"?"timeout":!c.httpSuccess(w)?
+"error":e.ifModified&&c.httpNotModified(w,e.url)?"notmodified":"success";var p;if(j==="success")try{n=c.httpData(w,e.dataType,e)}catch(u){j="parsererror";p=u}if(j==="success"||j==="notmodified")i||b();else c.handleError(e,w,j,p);d();q==="timeout"&&w.abort();if(e.async)w=null}};try{var h=w.abort;w.abort=function(){w&&h.call(w);g("abort")}}catch(k){}e.async&&e.timeout>0&&setTimeout(function(){w&&!E&&g("timeout")},e.timeout);try{w.send(m==="POST"||m==="PUT"||m==="DELETE"?e.data:null)}catch(l){c.handleError(e,
+w,null,l);d()}e.async||g();return w}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=
+f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(j,n){if(c.isArray(n))c.each(n,
+function(o,m){b?f(j,m):d(j+"["+(typeof m==="object"||c.isArray(m)?o:"")+"]",m)});else!b&&n!=null&&typeof n==="object"?c.each(n,function(o,m){d(j+"["+o+"]",m)}):f(j,n)}function f(j,n){n=c.isFunction(n)?n():n;e[e.length]=encodeURIComponent(j)+"="+encodeURIComponent(n)}var e=[];if(b===v)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var i in a)d(i,a[i]);return e.join("&").replace(vb,"+")}});var ka={},wb=/toggle|show|hide/,xb=/^([+-]=)?([\d+-.]+)(.*)$/,
+W,ta=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(ka[d])f=ka[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();
+ka[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&
+c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var i=c.extend({},e),j,n=this.nodeType===1&&c(this).is(":hidden"),
+o=this;for(j in a){var m=j.replace(ha,ia);if(j!==m){a[m]=a[j];delete a[j];j=m}if(a[j]==="hide"&&n||a[j]==="show"&&!n)return i.complete.call(this);if((j==="height"||j==="width")&&this.style){i.display=c.css(this,"display");i.overflow=this.style.overflow}if(c.isArray(a[j])){(i.specialEasing=i.specialEasing||{})[j]=a[j][1];a[j]=a[j][0]}}if(i.overflow!=null)this.style.overflow="hidden";i.curAnim=c.extend({},a);c.each(a,function(s,x){var A=new c.fx(o,i,s);if(wb.test(x))A[x==="toggle"?n?"show":"hide":x](a);
+else{var B=xb.exec(x),C=A.cur(true)||0;if(B){x=parseFloat(B[2]);var E=B[3]||"px";if(E!=="px"){o.style[s]=(x||1)+E;C=(x||1)/A.cur(true)*C;o.style[s]=C+E}if(B[1])x=(B[1]==="-="?-1:1)*x+C;A.custom(C,x,E)}else A.custom(C,x,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",
+1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration==="number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,
+b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==
+null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(i){return e.step(i)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop===
+"width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=
+this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=
+c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=
+null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in r.documentElement?function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),
+f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=this[0];if(a)return this.each(function(s){c.offset.setOffset(this,a,s)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=
+b,e=b.ownerDocument,i,j=e.documentElement,n=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var o=b.offsetTop,m=b.offsetLeft;(b=b.parentNode)&&b!==n&&b!==j;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;i=e?e.getComputedStyle(b,null):b.currentStyle;o-=b.scrollTop;m-=b.scrollLeft;if(b===d){o+=b.offsetTop;m+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){o+=parseFloat(i.borderTopWidth)||
+0;m+=parseFloat(i.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&i.overflow!=="visible"){o+=parseFloat(i.borderTopWidth)||0;m+=parseFloat(i.borderLeftWidth)||0}f=i}if(f.position==="relative"||f.position==="static"){o+=n.offsetTop;m+=n.offsetLeft}if(c.offset.supportsFixedPosition&&f.position==="fixed"){o+=Math.max(j.scrollTop,n.scrollTop);m+=Math.max(j.scrollLeft,n.scrollLeft)}return{top:o,left:m}};c.offset={initialize:function(){var a=r.body,b=r.createElement("div"),
+d,f,e,i=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild);
+d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i;a.removeChild(b);c.offset.initialize=c.noop},
+bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),i=parseInt(c.curCSS(a,"top",true),10)||0,j=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,d,e);d={top:b.top-e.top+i,left:b.left-
+e.left+j};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=
+this.offsetParent||r.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],i;if(!e)return null;if(f!==v)return this.each(function(){if(i=ua(this))i.scrollTo(!a?f:c(i).scrollLeft(),a?f:c(i).scrollTop());else this[d]=f});else return(i=ua(e))?"pageXOffset"in i?i[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&i.document.documentElement[d]||i.document.body[d]:e[d]}});
+c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(i){var j=c(this);j[d](f.call(this,i,j[d]()))});return"scrollTo"in e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||
+e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===v?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});z.jQuery=z.$=c})(window);
diff --git a/tools/qdoc3/test/style/style.css b/tools/qdoc3/test/style/style.css
new file mode 100644
index 0000000..1ed49fa
--- /dev/null
+++ b/tools/qdoc3/test/style/style.css
@@ -0,0 +1,946 @@
+@media screen
+{
+ html
+ {
+ color: #000000;
+ background: #FFFFFF;
+ }
+ body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, button, textarea, p, blockquote, th, td
+ {
+ margin: 0;
+ padding: 0;
+ }
+ table
+ {
+ border-collapse: collapse;
+ border-spacing: 0;
+ }
+ fieldset, img
+ {
+ border: 0;
+ }
+ address, caption, cite, code, dfn, em, strong, th, var, optgroup
+ {
+ font-style: inherit;
+ font-weight: inherit;
+ }
+ del, ins
+ {
+ text-decoration: none;
+ }
+ li
+ {
+ list-style: none;
+ }
+ caption, th
+ {
+ text-align: left;
+ }
+ h1, h2, h3, h4, h5, h6
+ {
+ font-size: 100%;
+ font-weight: normal;
+ }
+ q:before, q:after
+ {
+ content: '';
+ }
+ abbr, acronym
+ {
+ border: 0;
+ font-variant: normal;
+ }
+ sup
+ {
+ vertical-align: baseline;
+ }
+ sub
+ {
+ vertical-align: baseline;
+ }
+ legend
+ {
+ color: #000000;
+ }
+ input, button, textarea, select, optgroup, option
+ {
+ font-family: inherit;
+ font-size: inherit;
+ font-style: inherit;
+ font-weight: inherit;
+ }
+ input, button, textarea, select
+ {
+ font-size: 100%;
+ }
+ /* Page style */
+ html
+ {
+ background-color: #e5e5e5;
+ }
+ body
+ {
+ background: #e6e7e8 url(../images/page_bg.png) repeat-x 0 0;
+ font: normal 13px/1.2 Verdana;
+ color: #363534;
+ }
+ strong
+ {
+ font-weight: bold;
+ }
+ em
+ {
+ font-style: italic;
+ }
+ .header, .footer, .wrapper
+ {
+ min-width: 600px;
+ max-width: 1500px;
+ margin: 0 30px;
+ }
+ .wrapper
+ {
+ background: url(../images/bg_r.png) repeat-y 100% 0;
+ }
+ .wrapper .hd
+ {
+ padding-left: 216px;
+ height: 15px;
+ background: url(../images/bg_ul.png) no-repeat 0 0;
+ overflow: hidden;
+ }
+ .offline .wrapper .hd
+ {
+ background: url(../images/bg_ul_blank.png) no-repeat 0 0;
+ }
+ .wrapper .hd span
+ {
+ height: 15px;
+ display: block;
+ background: url(../images/bg_ur.png) no-repeat 100% 0;
+ overflow: hidden;
+ }
+ .offline .wrapper .hd span
+ {
+ /* background: url(../images/bg_ur_blank.png) no-repeat 100% 0; */
+ }
+ .wrapper .bd
+ {
+ background: url(../images/bg_l.png) repeat-y 0 0;
+ position: relative;
+ }
+ .offline .wrapper .bd
+ {
+ background: url(../images/bg_l_blank.png) repeat-y 0 0;
+ }
+ .wrapper .ft
+ {
+ padding-left: 216px;
+ height: 15px;
+ background: url(../images/bg_ll.png) no-repeat 0 0;
+ overflow: hidden;
+ }
+ .offline .wrapper .ft
+ {
+ background: url(../images/bg_ll_blank.png) no-repeat 0 0;
+ }
+ .wrapper .ft span
+ {
+ height: 15px;
+ display: block;
+ background: url(../images/bg_lr.png) no-repeat 100% 0;
+ overflow: hidden;
+ }
+ .header, .footer
+ {
+ display: block;
+ clear: both;
+ overflow: hidden;
+ }
+ .header
+ {
+ height: 115px;
+ position: relative;
+ }
+ .header .icon
+ {
+ position: absolute;
+ top: 13px;
+ left: 0;
+ }
+ .header .qtref
+ {
+ position: absolute;
+ top: 28px;
+ left: 88px;
+ width: 302px;
+ height: 22px;
+ }
+ .header .qtref span
+ {
+ display: block;
+ width: 302px;
+ height: 22px;
+ text-indent: -999em;
+ background: url(../images/header.png) no-repeat 0 0;
+ }
+ /* header elements */
+ #nav-topright
+ {
+ height: 70px;
+ }
+
+ #nav-topright ul
+ {
+ list-style-type: none;
+ float: right;
+ width: 370px;
+ margin-top: 11px;
+ }
+
+ #nav-topright li
+ {
+ display: inline-block;
+ margin-right: 20px;
+ float: left;
+ }
+
+ #nav-topright li.nav-topright-last
+ {
+ margin-right: 0;
+ }
+
+ #nav-topright li a
+ {
+ background: transparent url(../images/sprites-combined.png) no-repeat;
+ height: 18px;
+ display: block;
+ overflow: hidden;
+ text-indent: -9999px;
+ }
+
+ #nav-topright li.nav-topright-home a
+ {
+ width: 65px;
+ background-position: -2px -91px;
+ }
+
+ #nav-topright li.nav-topright-home a:hover
+ {
+ background-position: -2px -117px;
+ }
+
+
+ #nav-topright li.nav-topright-dev a
+ {
+ width: 30px;
+ background-position: -76px -91px;
+ }
+
+ #nav-topright li.nav-topright-dev a:hover
+ {
+ background-position: -76px -117px;
+ }
+
+
+ #nav-topright li.nav-topright-labs a
+ {
+ width: 40px;
+ background-position: -114px -91px;
+ }
+
+ #nav-topright li.nav-topright-labs a:hover
+ {
+ background-position: -114px -117px;
+ }
+
+ #nav-topright li.nav-topright-doc a
+ {
+ width: 32px;
+ background-position: -162px -91px;
+ }
+
+ #nav-topright li.nav-topright-doc a:hover, #nav-topright li.nav-topright-doc-active a
+ {
+ background-position: -162px -117px;
+ }
+
+ #nav-topright li.nav-topright-blog a
+ {
+ width: 40px;
+ background-position: -203px -91px;
+ }
+
+ #nav-topright li.nav-topright-blog a:hover, #nav-topright li.nav-topright-blog-active a
+ {
+ background-position: -203px -117px;
+ }
+
+ #nav-topright li.nav-topright-shop a
+ {
+ width: 40px;
+ background-position: -252px -91px;
+ }
+
+ #nav-topright li.nav-topright-shop a:hover, #nav-topright li.nav-topright-shop-active a
+ {
+ background-position: -252px -117px;
+ }
+
+ #nav-logo
+ {
+ background: transparent url( "../images/sprites-combined.png" ) no-repeat 0 -225px;
+ left: -3px;
+ position: absolute;
+ width: 75px;
+ height: 75px;
+ top: 13px;
+ }
+ #nav-logo a
+ {
+ width: 75px;
+ height: 75px;
+ display: block;
+ text-indent: -9999px;
+ overflow: hidden;
+ }
+ /* Clearing */
+ .header:after, .footer:after, .breadcrumb:after, .wrap .content:after, .group:after
+ {
+ content: ".";
+ display: block;
+ height: 0;
+ clear: both;
+ visibility: hidden;
+ }
+ /* ^ Clearing */
+
+
+
+ .shortCut-topleft-inactive
+ {
+ padding-left: 3px;
+ background: transparent url( "../images/sprites-combined.png" ) no-repeat 0px -58px;
+ height: 20px;
+ width: 93px;
+ }
+ .shortCut-topleft-inactive span
+ {
+ font-variant: normal;
+ }
+ #shortCut
+ {
+ padding-top: 10px;
+ font-weight: bolder;
+ color: #b0adab;
+ }
+ #shortCut ul
+ {
+ list-style-type: none;
+ float: left;
+ width: 347px;
+ margin-left: 100px;
+ }
+ #shortCut li
+ {
+ display: inline-block;
+ margin-right: 25px;
+ float: left;
+ white-space: nowrap;
+ }
+ #shortCut li a
+ {
+ color: #b0adab;
+ text-decoration: none;
+ }
+ #shortCut li a:hover
+ {
+ color: #44a51c;
+ text-decoration: none;
+ }
+
+ /* end of header elements */
+
+ /* menu element */
+ .sidebar
+ {
+ float: left;
+ margin-left: 5px;
+ width: 200px;
+ font-size: 11px;
+ }
+ .sidebar a
+ {
+ color: #00732f;
+ text-decoration: none;
+ }
+ .offline .sidebar, .offline .feedback
+ {
+ display: none;
+ }
+ .sidebar .searchlabel
+ {
+ padding: 0 0 2px 17px;
+ font: normal bold 11px/1.2 Verdana;
+ }
+ .sidebar .search
+ {
+ padding: 0 15px 0 16px;
+ }
+ .sidebar .search form
+ {
+ width: 167px;
+ height: 21px;
+ padding: 2px 0 0 5px;
+ background: url(../images/form_bg.png) no-repeat 0 0;
+ }
+ .sidebar .search form fieldset input#searchstring
+ {
+ width: 158px;
+ height: 19px;
+ padding: 0;
+ border: none;
+ outline: none;
+ font: 13px/1.2 Verdana;
+ }
+ .sidebar .box
+ {
+ padding: 17px 15px 5px 16px;
+ }
+ .sidebar .box .first
+ {
+ background-image: none;
+ }
+ .sidebar .box h2
+ {
+ font: normal 18px/1.2 Arial;
+ padding: 15px 0 0 40px;
+ min-height: 32px;
+ }
+ .sidebar .box#lookup h2
+ {
+ background: url(../images/api_lookup.png) no-repeat 0 0;
+ }
+ .sidebar .box#topics h2
+ {
+ background: url(../images/api_topics.png) no-repeat 0 0;
+ }
+ .sidebar .box#examples h2
+ {
+ background: url(../images/api_examples.png) no-repeat 0 0;
+ }
+ .sidebar .box .list
+ {
+ display: block;
+ }
+ .sidebar .box .live
+ {
+ display: none;
+ height: 100px;
+ overflow: auto;
+ }
+ .list li a:hover, .live li a:hover
+ {
+ text-decoration: underline;
+ }
+ .sidebar .box ul li
+ {
+ padding-left: 12px;
+ background: url(../images/bullet_gt.png) no-repeat 0 5px;
+ margin-bottom: 15px;
+ }
+ .sidebar .bottombar
+ {
+ background: url(../images/box_bg.png) repeat-x 0 bottom;
+ }
+ /* content elements */
+ .wrap
+ {
+ overflow: hidden;
+ }
+ .offline .wrap
+ {
+ margin: 0 5px 0 5px;
+ }
+ /* tool bar */
+ .wrap .toolbar
+ {
+ background-color: #fafafa;
+ border-bottom: 1px solid #d1d1d1;
+ height: 20px;
+ margin-left: 3px;
+ margin-right: 5px;
+ position: relative;
+ }
+ .wrap .toolbar .toolblock
+ {
+ position: absolute;
+ }
+ .wrap .toolbar .breadcrumb
+ {
+ font-size: 11px;
+ line-height: 1;
+ padding: 0 0 10px 21px;
+ height: 10px;
+ }
+ .wrap .toolbar .toolbuttons
+ {
+ padding: 0 0 10px 21px;
+ right: 5px;
+ vertical-align: top;
+ overflow: hidden;
+ }
+ .wrap .toolbar .toolbuttons .active
+ {
+ color: #00732F;
+ }
+ .wrap .toolbar .toolbuttons ul
+ {
+ float: right;
+ }
+ .wrap .toolbar .toolbuttons li
+ {
+ float: left;
+ text-indent: -10px;
+ margin-top: -5px;
+ margin-right: 15px;
+ font-weight: bold;
+ color: #B0ADAB;
+ }
+ #smallA
+ {
+ font-size: 10pt;
+ }
+ #medA
+ {
+ font-size: 12pt;
+ }
+ #bigA
+ {
+ font-size: 14pt;
+ }
+ #smallA:hover, #medA:hover, #bigA:hover
+ {
+ color: #00732F;
+ }
+ #print
+ {
+ font-size: 14pt;
+ line-height: 20pt;
+ }
+ #printIcon
+ {
+ margin-left: 5px;
+ }
+ /* bread crumbs */
+ .wrap .breadcrumb ul li
+ {
+ float: left;
+ background: url(../images/breadcrumb.png) no-repeat 0 3px;
+ padding-left: 15px;
+ margin-left: 15px;
+ font-weight: bold;
+ }
+ .wrap .breadcrumb ul li.last
+ {
+ font-weight: normal;
+ }
+ .wrap .breadcrumb ul li.first
+ {
+ background-image: none;
+ padding-left: 0;
+ margin-left: 0;
+ }
+ .wrap .content
+ {
+ padding: 30px;
+ position: relative;
+ }
+ /* text elements */
+ .heading
+ {
+ font: normal 600 16px/1.0 Arial;
+ padding-bottom: 15px;
+ }
+
+ .subtitle
+ {
+ font-size: 13px;
+ }
+
+ .small-subtitle
+ {
+ font-size: 13px;
+ }
+
+ .wrap .content h1
+ {
+ font: 600 18px/1.2 Arial;
+ padding-bottom: 15px;
+ }
+ .wrap .content h2
+ {
+ font: 600 16px/1.2 Arial;
+ }
+ .wrap .content h3
+ {
+ font: 600 14px/1.2 Arial;
+ }
+ .wrap .content p
+ {
+ line-height:20px;
+ padding:10px 5px 10px 5px;
+ }
+ .wrap .content ul
+ {
+ padding-left: 25px;
+ }
+ .wrap .content li
+ {
+ padding-left: 12px;
+ background: url(../images/bullet_sq.png) no-repeat 0 5px;
+ font: normal 400 10pt/1 Verdana;
+ margin-bottom: 10px;
+ line-height: 14px;
+ }
+ a
+ {
+ color: #00732F;
+ text-decoration: none;
+ }
+ a:hover
+ {
+ color: #4c0033;
+ text-decoration: underline;
+ }
+ .content a:visited
+ {
+ color: #4c0033;
+ text-decoration: none;
+ }
+ .offline .wrap .content
+ {
+ padding-top: 15px;
+ }
+ .footer
+ {
+ min-height: 100px;
+ color: #797775;
+ font: normal 9px/1 Verdana;
+ text-align: center;
+ padding-top: 40px;
+ }
+ .feedback
+ {
+ float: right;
+ padding-right: 10px;
+ font: normal 8px/1 Verdana;
+ color: #B0ADAB;
+ }
+ .feedback:hover
+ {
+ float: right;
+ font: normal 8px/1 Verdana;
+ color: #00732F;
+ text-decoration: underline;
+ }
+ hr
+ {
+ background-color: #e0e0e0;
+ height: 1px;
+ width: 100%;
+ text-align: left;
+ margin: 15px 0px 15px 0px;
+ }
+
+ .content .alignedsummary
+ {
+ margin: 15px;
+ }
+ /* tables */
+ table, pre
+ {
+ -moz-border-radius: 7px 7px 7px 7px;
+ background-color: #F6F6F6;
+ border: 1px solid #E6E6E6;
+ border-collapse: separate;
+ font-size: 11px;
+ min-width: 395px;
+ margin-bottom: 25px;
+ }
+ thead{margin-top: 5px;}
+ th{ padding: 3px 15px 3px 15px;}
+ td{padding: 3px 15px 3px 20px;}
+ table tr.odd
+ {
+ border-left: 1px solid #E6E6E6;
+ background-color: #F6F6F6;
+ color: #66666E;
+ }
+ table tr.even
+ {
+ border-left: 1px solid #E6E6E6;
+ background-color: #ffffff;
+ color: #66666E;
+ }
+ table tr.odd:hover
+ {
+ background-color: #E6E6E6;
+ }
+ table tr.even:hover
+ {
+ background-color: #E6E6E6;
+ }
+ span.comment
+ {
+ color: #8B0000;
+ font-style: italic;
+ }
+ span.string, span.char
+ {
+ color: #254117;
+ }
+ pre
+ {
+ -moz-border-radius:7px 7px 7px 7px;
+ background-color:#F6F6F6;
+ border:1px solid #DDDDDD;
+ margin:0 20px 10px 10px;
+ padding:20px 15px 20px 20px;
+ overflow-x:auto;
+ }
+ .qmltype
+ {
+ text-align: center;
+ font-size: 160%;
+ }
+ .qmlreadonly
+ {
+ float: right;
+ color: #254117;
+ }
+ #feedbackBox
+ {
+ display:none;
+ -moz-border-radius:7px 7px 7px 7px;
+ border:1px solid #DDDDDD;
+ position:fixed;
+ top:100px;
+ left: 33%;
+ height: 190px;
+ width: 400px;
+ padding: 5px;
+ background-color: #e6e7e8;
+ z-index: 4;
+ }
+ #feedcloseX a
+ {
+ display:inline;
+ padding: 5px 5px 0 0;
+ margin-bottom:3px;
+ color: #363534;
+ font-weight:600;
+ float: right;
+ text-decoration: none;
+ }
+ #feedbox
+ /* here */
+ {
+ display:inline;
+ width: 370px;
+ height: 120px;
+ margin:0px 25px 10px 15px;
+ }
+ #feedsubmit
+ {
+ display:inline;
+ float:right;
+ margin:4px 32px 0 0;
+ }
+ #blurpage
+ {
+ display: none;
+ position: fixed;
+ float: none;
+ top: 0px;
+ left: 0px;
+ right: 0px;
+ bottom: 0px;
+ background: transparent url(../images/feedbackground.png) 0 0;
+ z-index: 3;
+ }
+ .toc
+ {
+ float: right;
+ -moz-border-radius:7px 7px 7px 7px;
+ background-color:#F6F6F6;
+ border:1px solid #DDDDDD;
+ margin:0 20px 10px 10px;
+ padding:20px 15px 20px 20px;
+ height: auto;
+ width: 200px;
+ }
+
+ .toc ul
+ {
+ float: left;
+ padding: 15px;
+
+ }
+
+
+ .content .toc li
+ {
+ font: normal 12px/1.2 Verdana;
+ background: url(../images/bullet_dn.png) no-repeat 0 5px;
+ }
+
+ .relpage
+ {
+ -moz-border-radius: 7px 7px 7px 7px;
+ border: 1px solid #DDDDDD;
+ padding: 25px 25px;
+ clear:both;
+ }
+ .relpage ul
+ {
+ float: none;
+ padding: 15px;
+ }
+ .content .relpage li
+ {
+ font: normal 11px/1.2 Verdana;
+ }
+ /* edit */
+ h3.fn, span.fn
+ {
+ background-color: #F6F6F6;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #E6E6E6;
+ font-weight: bold;
+ /* padding: 6px 0px 6px 10px;*/
+ /* margin: 42px 0px 0px 0px;*/
+ }
+ /* edit */
+
+ .indexbox
+ {
+ width: 100%;
+ }
+ .content .indexboxcont li
+ {
+ font: normal 600 13px/1 Verdana;
+ }
+
+ /* .indexbox a
+ {
+ color: #00732f;
+ text-decoration: none;
+ }*/
+ .indexbox a:hover, .indexbox a:visited:hover
+ {
+ color: #4c0033;
+ text-decoration: underline;
+ }
+ .indexbox a:visited
+ {
+ color: #00732f;
+ text-decoration: none;
+ }
+
+ .indexboxcont
+ {
+ display: block;
+ }
+
+ .indexboxbar
+ {
+ background: transparent url( "../images/horBar.png" ) repeat-x left bottom;
+ margin-bottom: 25px;
+ }
+
+ .indexboxcont .section
+ {
+ display: inline-block;
+ width: 49%;
+ *width:42%;
+ _width:42%;
+ padding:0 2% 0 1%;
+ vertical-align:top;
+}
+
+ .indexboxcont .indexIcon
+ {
+ width: 11%;
+ *width:18%;
+ _width:18%;
+ overflow:hidden;
+}
+ .indexboxcont .section p
+ {
+ padding-top: 20px;
+ padding-bottom: 20px;
+ }
+
+ .indexboxcont .sectionlist
+ {
+ display: inline-block;
+ width: 33%;
+ margin-right: -2px;
+ vertical-align: top;
+ padding: 0;
+ }
+ .tricol
+ {
+
+ }
+ .indexboxcont .sectionlist ul
+ {
+ padding-left: 15px;
+ margin-bottom: 20px;
+ }
+/*
+ .indexboxcont .sectionlist ul li
+ {
+ line-height: 12px;
+ }
+*/
+ .lastcol
+ {
+ display: inline-block;
+ vertical-align: top;
+ padding: 0;
+ max-width: 25%;
+ }
+
+ .tricol .lastcol
+ {
+ margin-left:-6px;
+ }
+
+ /*.toc ul*/
+
+ /* end page elements */
+}
+/* end of screen media */
+
+/* start of print media */
+
+@media print
+{
+ .header, .footer, .toolbar, .feedback, .wrapper .hd, .wrapper .bd .sidebar, .wrapper .ft
+ {
+ display: none;
+ background: none;
+ }
+ .content
+ {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ background: none;
+ display: block;
+ }
+}
+/* end of print media */
diff --git a/tools/qdoc3/test/style/style_ie6.css b/tools/qdoc3/test/style/style_ie6.css
new file mode 100644
index 0000000..16fb850
--- /dev/null
+++ b/tools/qdoc3/test/style/style_ie6.css
@@ -0,0 +1,54 @@
+.indexbox, .indexboxcont, .group {
+ zoom: 1;
+ height: 1%;
+}
+
+.sidebar {
+ margin-left: 3px;
+ width: 199px;
+ overflow: hidden;
+}
+
+.sidebar .search form {
+ position: relative;
+}
+
+.sidebar .search form fieldset {
+ position: absolute;
+ margin-top: -1px;
+}
+
+.sidebar .search form input#searchstring {
+ border: 1px solid #fff;
+ height: 18px;
+}
+
+.wrap {
+ zoom: 1;
+}
+
+.content,
+.toolbar {
+ zoom: 1;
+ margin-left: -3px;
+ position: relative;
+}
+
+.indexbox {
+ clear: both;
+}
+
+.indexboxcont .section {
+ zoom: 1;
+ float: left;
+}
+
+.indexboxcont .sectionlist {
+ zoom: 1;
+ float: left;
+}
+
+.wrap .toolbar .toolbuttons li {
+ text-indent: 0;
+ margin-right: 8px;
+} \ No newline at end of file
diff --git a/tools/qdoc3/test/style/style_ie7.css b/tools/qdoc3/test/style/style_ie7.css
new file mode 100644
index 0000000..afbff5f
--- /dev/null
+++ b/tools/qdoc3/test/style/style_ie7.css
@@ -0,0 +1,19 @@
+.indexbox, .indexboxcont, .group {
+ min-height: 1px;
+}
+
+.sidebar .search form input#searchstring {
+ border: 1px solid #fff;
+ height: 17px;
+}
+
+
+.indexboxcont .section {
+ zoom: 1;
+ float: left;
+}
+
+.indexboxcont .sectionlist {
+ zoom: 1;
+ float: left;
+}
diff --git a/tools/qdoc3/test/style/style_ie8.css b/tools/qdoc3/test/style/style_ie8.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/qdoc3/test/style/style_ie8.css
diff --git a/tools/qdoc3/tree.cpp b/tools/qdoc3/tree.cpp
index 7dcc8c3..31bbf54 100644
--- a/tools/qdoc3/tree.cpp
+++ b/tools/qdoc3/tree.cpp
@@ -1121,6 +1121,15 @@ bool Tree::generateIndexSection(QXmlStreamWriter &writer,
case Node::Target:
nodeName = "target";
break;
+ case Node::QmlProperty:
+ nodeName = "qmlproperty";
+ break;
+ case Node::QmlSignal:
+ nodeName = "qmlsignal";
+ break;
+ case Node::QmlMethod:
+ nodeName = "qmlmethod";
+ break;
default:
return false;
}
@@ -1210,7 +1219,7 @@ bool Tree::generateIndexSection(QXmlStreamWriter &writer,
if (fullName != objName)
writer.writeAttribute("fullname", fullName);
writer.writeAttribute("href", fullDocumentLocation(node));
- if (node->type() != Node::Fake)
+ if ((node->type() != Node::Fake) && (!node->isQmlNode()))
writer.writeAttribute("location", node->location().fileName());
switch (node->type()) {
@@ -1265,6 +1274,12 @@ bool Tree::generateIndexSection(QXmlStreamWriter &writer,
case Node::ExternalPage:
writer.writeAttribute("subtype", "externalpage");
break;
+ case Node::QmlClass:
+ writer.writeAttribute("subtype", "qmlclass");
+ break;
+ case Node::QmlBasicType:
+ writer.writeAttribute("subtype", "qmlbasictype");
+ break;
default:
break;
}
@@ -1337,6 +1352,12 @@ bool Tree::generateIndexSection(QXmlStreamWriter &writer,
}
break;
+ case Node::QmlProperty:
+ {
+ const QmlPropertyNode *qpn = static_cast<const QmlPropertyNode*>(node);
+ writer.writeAttribute("type", qpn->dataType());
+ }
+ break;
case Node::Property:
{
const PropertyNode *propertyNode = static_cast<const PropertyNode*>(node);
@@ -1524,9 +1545,22 @@ void Tree::generateIndexSections(QXmlStreamWriter &writer,
if (node->isInnerNode()) {
const InnerNode *inner = static_cast<const InnerNode *>(node);
- // Recurse to write an element for this child node and all its children.
- foreach (const Node *child, inner->childNodes())
- generateIndexSections(writer, child, generateInternalNodes);
+ foreach (const Node *child, inner->childNodes()) {
+ /*
+ Don't generate anything for a QML property group node.
+ It is just a place holder for a collection of QML property
+ nodes. Recurse to its children, which are the QML property
+ nodes.
+ */
+ if (child->subType() == Node::QmlPropertyGroup) {
+ const InnerNode *pgn = static_cast<const InnerNode*>(child);
+ foreach (const Node *c, pgn->childNodes()) {
+ generateIndexSections(writer, c, generateInternalNodes);
+ }
+ }
+ else
+ generateIndexSections(writer, child, generateInternalNodes);
+ }
/*
foreach (const Node *child, inner->relatedNodes()) {
@@ -1931,9 +1965,23 @@ QString Tree::fullDocumentLocation(const Node *node) const
if ((parentNode = node->relates()))
parentName = fullDocumentLocation(node->relates());
- else if ((parentNode = node->parent()))
- parentName = fullDocumentLocation(node->parent());
-
+ else if ((parentNode = node->parent())) {
+ if (parentNode->subType() == Node::QmlPropertyGroup) {
+ parentNode = parentNode->parent();
+ parentName = "qml-" + parentNode->fileBase() + ".html";
+ }
+ else
+ parentName = fullDocumentLocation(node->parent());
+ }
+#if 0
+ if (node->type() == Node::QmlProperty) {
+ qDebug() << "Node::QmlProperty:" << node->name()
+ << "parentName:" << parentName;
+ if (parentNode)
+ qDebug() << "PARENT NODE" << parentNode->type()
+ << parentNode->subType() << parentNode->name();
+ }
+#endif
switch (node->type()) {
case Node::Class:
case Node::Namespace:
@@ -1980,6 +2028,15 @@ QString Tree::fullDocumentLocation(const Node *node) const
case Node::Property:
anchorRef = "#" + node->name() + "-prop";
break;
+ case Node::QmlProperty:
+ anchorRef = "#" + node->name() + "-prop";
+ break;
+ case Node::QmlSignal:
+ anchorRef = "#" + node->name() + "-signal";
+ break;
+ case Node::QmlMethod:
+ anchorRef = "#" + node->name() + "-method";
+ break;
case Node::Variable:
anchorRef = "#" + node->name() + "-var";
break;
@@ -2019,6 +2076,8 @@ QString Tree::fullDocumentLocation(const Node *node) const
}
/*!
+ Construct the full document name for \a node and return the
+ name.
*/
QString Tree::fullDocumentName(const Node *node) const
{
@@ -2029,10 +2088,11 @@ QString Tree::fullDocumentName(const Node *node) const
const Node *n = node;
do {
- if (!n->name().isEmpty())
+ if (!n->name().isEmpty() &&
+ ((n->type() != Node::Fake) || (n->subType() != Node::QmlPropertyGroup)))
pieces.insert(0, n->name());
- if (n->type() == Node::Fake)
+ if ((n->type() == Node::Fake) && (n->subType() != Node::QmlPropertyGroup))
break;
// Examine the parent node if one exists.
diff --git a/tools/qml/Info_mac.plist b/tools/qml/Info_mac.plist
new file mode 100644
index 0000000..ce4ebe3
--- /dev/null
+++ b/tools/qml/Info_mac.plist
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.1">
+<dict>
+ <key>CFBundleIdentifier</key>
+ <string>com.nokia.qt.qml</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Created by Qt/QMake</string>
+ <key>CFBundleSignature</key>
+ <string>@TYPEINFO@</string>
+ <key>CFBundleExecutable</key>
+ <string>@EXECUTABLE@</string>
+</dict>
+</plist>
diff --git a/tools/qml/content/Browser.qml b/tools/qml/content/Browser.qml
index 62996ef..8882d5a 100644
--- a/tools/qml/content/Browser.qml
+++ b/tools/qml/content/Browser.qml
@@ -3,8 +3,8 @@ import Qt 4.6
Rectangle {
id: root
property bool keyPressed: false
- property var folders: folders1
- property var view: view1
+ property variant folders: folders1
+ property variant view: view1
width: 320
height: 480
color: palette.window
@@ -22,38 +22,36 @@ Rectangle {
SystemPalette { id: palette }
- Script {
- function down(path) {
- if (folders == folders1) {
- view = view2
- folders = folders2;
- view1.state = "exitLeft";
- } else {
- view = view1
- folders = folders1;
- view2.state = "exitLeft";
- }
- view.x = root.width;
- view.state = "current";
- view.focus = true;
- folders.folder = path;
+ function down(path) {
+ if (folders == folders1) {
+ view = view2
+ folders = folders2;
+ view1.state = "exitLeft";
+ } else {
+ view = view1
+ folders = folders1;
+ view2.state = "exitLeft";
}
- function up() {
- var path = folders.parentFolder;
- if (folders == folders1) {
- view = view2
- folders = folders2;
- view1.state = "exitRight";
- } else {
- view = view1
- folders = folders1;
- view2.state = "exitRight";
- }
- view.x = -root.width;
- view.state = "current";
- view.focus = true;
- folders.folder = path;
+ view.x = root.width;
+ view.state = "current";
+ view.focus = true;
+ folders.folder = path;
+ }
+ function up() {
+ var path = folders.parentFolder;
+ if (folders == folders1) {
+ view = view2
+ folders = folders2;
+ view1.state = "exitRight";
+ } else {
+ view = view1
+ folders = folders1;
+ view2.state = "exitRight";
}
+ view.x = -root.width;
+ view.state = "current";
+ view.focus = true;
+ folders.folder = path;
}
Component {
diff --git a/tools/qml/deviceorientation.h b/tools/qml/deviceorientation.h
index c8125cd..d209005 100644
--- a/tools/qml/deviceorientation.h
+++ b/tools/qml/deviceorientation.h
@@ -50,6 +50,7 @@ class DeviceOrientationPrivate;
class DeviceOrientation : public QObject
{
Q_OBJECT
+ Q_ENUMS(Orientation)
public:
enum Orientation { UnknownOrientation, Portrait, Landscape };
virtual Orientation orientation() const = 0;
diff --git a/tools/qml/deviceorientation_maemo.cpp b/tools/qml/deviceorientation_maemo.cpp
index fa2c6e5..9f12f3d 100644
--- a/tools/qml/deviceorientation_maemo.cpp
+++ b/tools/qml/deviceorientation_maemo.cpp
@@ -50,6 +50,10 @@ public:
MaemoOrientation()
: DeviceOrientation(),m_current(Portrait), m_lastSeen(Portrait), m_lastSeenCount(0)
{
+ m_current = get();
+ if (m_current == UnknownOrientation)
+ m_current = Portrait;
+
startTimer(100);
}
@@ -57,14 +61,7 @@ public:
return m_current;
}
- void setOrientation(Orientation orient) {
- //XXX maybe better to just ignore
- if (orient != m_current) {
- m_current = orient;
- emit orientationChanged();
- }
- }
-
+ void setOrientation(Orientation) { }
protected:
virtual void timerEvent(QTimerEvent *)
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
index a4de339..45c2b85 100644
--- a/tools/qml/main.cpp
+++ b/tools/qml/main.cpp
@@ -41,12 +41,13 @@
#include "qdeclarative.h"
#include "qmlruntime.h"
+#include "qdeclarativeengine.h"
#include <QWidget>
#include <QDir>
#include <QApplication>
#include <QTranslator>
#include <QDebug>
-#include "qfxtester.h"
+#include "qdeclarativetester.h"
#include "qdeclarativefolderlistmodel.h"
QT_USE_NAMESPACE
@@ -100,7 +101,9 @@ void usage()
qWarning(" -dragthreshold <size> .................... set mouse drag threshold size");
qWarning(" -netcache <size> ......................... set disk cache to size bytes");
qWarning(" -translation <translationfile> ........... set the language to run in");
- qWarning(" -L <directory> ........................... prepend to the library search path");
+ qWarning(" -I <directory> ........................... prepend to the module import search path,");
+ qWarning(" display path if <directory> is empty");
+ qWarning(" -P <directory> ........................... prepend to the plugin search path");
qWarning(" -opengl .................................. use a QGLWidget for the viewport");
qWarning(" -script <path> ........................... set the script to use");
qWarning(" -scriptopts <options>|help ............... set the script options to use");
@@ -118,6 +121,8 @@ void scriptOptsUsage()
qWarning(" play ..................................... playback an existing script");
qWarning(" testimages ............................... record images or compare images on playback");
qWarning(" testerror ................................ test 'error' property of root item on playback");
+ qWarning(" snapshot ................................. file being recorded is static,");
+ qWarning(" only one frame will be recorded or tested");
qWarning(" exitoncomplete ........................... cleanly exit the viewer on script completion");
qWarning(" exitonfailure ............................ immediately exit the viewer on script failure");
qWarning(" saveonexit ............................... save recording on viewer exit");
@@ -165,7 +170,8 @@ int main(int argc, char ** argv)
QString dither = "none";
QString recordfile;
QStringList recordargs;
- QStringList libraries;
+ QStringList imports;
+ QStringList plugins;
QString skin;
QString script;
QString scriptopts;
@@ -237,9 +243,19 @@ int main(int argc, char ** argv)
useGL = true;
} else if (arg == "-qmlbrowser") {
useNativeFileBrowser = false;
- } else if (arg == "-L") {
+ } else if (arg == "-I" || arg == "-L") {
+ if (arg == "-L")
+ fprintf(stderr, "-L option provided for compatibility only, use -I instead\n");
+ if (lastArg) {
+ QDeclarativeEngine tmpEngine;
+ QString paths = tmpEngine.importPathList().join(QLatin1String(":"));
+ fprintf(stderr, "Current search path: %s\n", paths.toLocal8Bit().constData());
+ return 0;
+ }
+ imports << QString(argv[++i]);
+ } else if (arg == "-P") {
if (lastArg) usage();
- libraries << QString(argv[++i]);
+ plugins << QString(argv[++i]);
} else if (arg == "-script") {
if (lastArg) usage();
script = QString(argv[++i]);
@@ -295,6 +311,8 @@ int main(int argc, char ** argv)
scriptOptions |= QDeclarativeViewer::ExitOnFailure;
} else if (option == QLatin1String("saveonexit")) {
scriptOptions |= QDeclarativeViewer::SaveOnExit;
+ } else if (option == QLatin1String("snapshot")) {
+ scriptOptions |= QDeclarativeViewer::Snapshot;
} else {
scriptOptsUsage();
}
@@ -313,9 +331,12 @@ int main(int argc, char ** argv)
viewer.addLibraryPath(QCoreApplication::applicationDirPath());
- foreach (QString lib, libraries)
+ foreach (QString lib, imports)
viewer.addLibraryPath(lib);
+ foreach (QString plugin, plugins)
+ viewer.addPluginPath(plugin);
+
viewer.setNetworkCacheSize(cache);
viewer.setRecordFile(recordfile);
if (resizeview)
@@ -342,6 +363,21 @@ int main(int argc, char ** argv)
viewer.setUseNativeFileBrowser(useNativeFileBrowser);
if (fullScreen && maximized)
qWarning() << "Both -fullscreen and -maximized specified. Using -fullscreen.";
+
+ if (fileName.isEmpty()) {
+ QFile qmlapp(QLatin1String("qmlapp"));
+ if (qmlapp.exists() && qmlapp.open(QFile::ReadOnly)) {
+ QString content = QString::fromUtf8(qmlapp.readAll());
+ qmlapp.close();
+
+ int newline = content.indexOf(QLatin1Char('\n'));
+ if (newline >= 0)
+ fileName = content.left(newline);
+ else
+ fileName = content;
+ }
+ }
+
if (!fileName.isEmpty()) {
viewer.open(fileName);
fullScreen ? viewer.showFullScreen() : maximized ? viewer.showMaximized() : viewer.show();
diff --git a/tools/qml/qdeclarativefolderlistmodel.cpp b/tools/qml/qdeclarativefolderlistmodel.cpp
index 58bf59b..d36033d 100644
--- a/tools/qml/qdeclarativefolderlistmodel.cpp
+++ b/tools/qml/qdeclarativefolderlistmodel.cpp
@@ -413,7 +413,7 @@ void QDeclarativeFolderListModel::setShowOnlyReadable(bool on)
void QDeclarativeFolderListModel::registerTypes()
{
- QML_REGISTER_TYPE(Qt,4,6,FolderListModel,QDeclarativeFolderListModel);
+ qmlRegisterType<QDeclarativeFolderListModel>("Qt",4,6,"FolderListModel");
}
QT_END_NAMESPACE
diff --git a/tools/qml/qfxtester.cpp b/tools/qml/qdeclarativetester.cpp
index 638a3c9..11fa22f 100644
--- a/tools/qml/qfxtester.cpp
+++ b/tools/qml/qdeclarativetester.cpp
@@ -39,7 +39,7 @@
**
****************************************************************************/
-#include <qfxtester.h>
+#include <qdeclarativetester.h>
#include <QDebug>
#include <QApplication>
#include <qdeclarativeview.h>
@@ -240,6 +240,8 @@ void QDeclarativeTester::save()
void QDeclarativeTester::updateCurrentTime(int msec)
{
QDeclarativeItemPrivate::setConsistentTime(msec);
+ if (!testscript && msec > 16 && options & QDeclarativeViewer::Snapshot)
+ return;
QImage img(m_view->width(), m_view->height(), QImage::Format_RGB32);
@@ -249,11 +251,13 @@ void QDeclarativeTester::updateCurrentTime(int msec)
m_view->render(&p);
}
+ bool snapshot = msec == 16 && options & QDeclarativeViewer::Snapshot;
+
FrameEvent fe;
fe.msec = msec;
if (msec == 0 || !(options & QDeclarativeViewer::TestImages)) {
// Skip first frame, skip if not doing images
- } else if (0 == (m_savedFrameEvents.count() % 60)) {
+ } else if (0 == (m_savedFrameEvents.count() % 60) || snapshot) {
fe.image = img;
} else {
QCryptographicHash hash(QCryptographicHash::Md5);
@@ -311,9 +315,9 @@ void QDeclarativeTester::updateCurrentTime(int msec)
} else if (frame->msec() == msec) {
if (!frame->hash().isEmpty() && frame->hash().toUtf8() != fe.hash.toHex()) {
if (options & QDeclarativeViewer::TestImages && !(options & QDeclarativeViewer::Record)) {
- qWarning() << "QDeclarativeTester: Mismatched frame hash. Seen:"
- << fe.hash.toHex() << "Expected:"
- << frame->hash().toUtf8();
+ qWarning() << "QDeclarativeTester: Mismatched frame hash at" << msec
+ << ". Seen:" << fe.hash.toHex()
+ << "Expected:" << frame->hash().toUtf8();
imagefailure();
}
}
@@ -328,6 +332,24 @@ void QDeclarativeTester::updateCurrentTime(int msec)
qWarning() << "QDeclarativeTester: Image mismatch. Reject saved to:"
<< reject;
img.save(reject);
+ bool doDiff = (goodImage.size() == img.size());
+ if (doDiff) {
+ QImage diffimg(m_view->width(), m_view->height(), QImage::Format_RGB32);
+ diffimg.fill(qRgb(255,255,255));
+ QPainter p(&diffimg);
+ int diffCount = 0;
+ for (int x = 0; x < img.width(); ++x) {
+ for (int y = 0; y < img.height(); ++y) {
+ if (goodImage.pixel(x,y) != img.pixel(x,y)) {
+ ++diffCount;
+ p.drawPoint(x,y);
+ }
+ }
+ }
+ QString diff(frame->image().toLocalFile() + ".diff.png");
+ diffimg.save(diff);
+ qWarning().nospace() << " Diff (" << diffCount << " pixels differed) saved to: " << diff;
+ }
imagefailure();
}
}
@@ -366,16 +388,19 @@ void QDeclarativeTester::updateCurrentTime(int msec)
filterEvents = true;
- if (testscript && testscript->count() <= testscriptidx)
+ if (testscript && testscript->count() <= testscriptidx) {
+ //if (msec == 16) //for a snapshot, leave it up long enough to see
+ // (void)::sleep(1);
complete();
+ }
}
void QDeclarativeTester::registerTypes()
{
- QML_REGISTER_TYPE(Qt.VisualTest, 4,6, VisualTest, QDeclarativeVisualTest);
- QML_REGISTER_TYPE(Qt.VisualTest, 4,6, Frame, QDeclarativeVisualTestFrame);
- QML_REGISTER_TYPE(Qt.VisualTest, 4,6, Mouse, QDeclarativeVisualTestMouse);
- QML_REGISTER_TYPE(Qt.VisualTest, 4,6, Key, QDeclarativeVisualTestKey);
+ qmlRegisterType<QDeclarativeVisualTest>("Qt.VisualTest", 4,6, "VisualTest");
+ qmlRegisterType<QDeclarativeVisualTestFrame>("Qt.VisualTest", 4,6, "Frame");
+ qmlRegisterType<QDeclarativeVisualTestMouse>("Qt.VisualTest", 4,6, "Mouse");
+ qmlRegisterType<QDeclarativeVisualTestKey>("Qt.VisualTest", 4,6, "Key");
}
QT_END_NAMESPACE
diff --git a/tools/qml/qfxtester.h b/tools/qml/qdeclarativetester.h
index 6521409..d49c9b8 100644
--- a/tools/qml/qfxtester.h
+++ b/tools/qml/qdeclarativetester.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QFXTESTER_H
-#define QFXTESTER_H
+#ifndef QDECLARATIVETESTER_H
+#define QDECLARATIVETESTER_H
#include <QEvent>
#include <QMouseEvent>
@@ -283,4 +283,4 @@ private:
QT_END_NAMESPACE
-#endif // QFXTESTER_H
+#endif // QDECLARATIVETESTER_H
diff --git a/tools/qml/qml.pri b/tools/qml/qml.pri
new file mode 100644
index 0000000..c48e919
--- /dev/null
+++ b/tools/qml/qml.pri
@@ -0,0 +1,29 @@
+QT += declarative script network sql
+contains(QT_CONFIG, opengl) {
+ QT += opengl
+ DEFINES += GL_SUPPORTED
+}
+
+INCLUDEPATH += $$PWD
+
+HEADERS += $$PWD/qmlruntime.h \
+ $$PWD/proxysettings.h \
+ $$PWD/qdeclarativetester.h \
+ $$PWD/deviceorientation.h \
+ $$PWD/qdeclarativefolderlistmodel.h
+SOURCES += $$PWD/qmlruntime.cpp \
+ $$PWD/proxysettings.cpp \
+ $$PWD/qdeclarativetester.cpp \
+ $$PWD/qdeclarativefolderlistmodel.cpp
+
+RESOURCES = $$PWD/qmlruntime.qrc
+maemo5 {
+ SOURCES += $$PWD/deviceorientation_maemo.cpp
+} else {
+ SOURCES += $$PWD/deviceorientation.cpp
+}
+FORMS = $$PWD/recopts.ui \
+ $$PWD/proxysettings.ui
+
+include(../shared/deviceskin/deviceskin.pri)
+
diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro
index a7eb6f5..869907f 100644
--- a/tools/qml/qml.pro
+++ b/tools/qml/qml.pro
@@ -1,40 +1,15 @@
TEMPLATE = app
-CONFIG += qt \
- uic
+CONFIG += qt uic
DESTDIR = ../../bin
-QT += declarative \
- script \
- network \
- sql
-contains(QT_CONFIG, opengl) {
- QT += opengl
- DEFINES += GL_SUPPORTED
-}
+include(qml.pri)
+
+SOURCES += main.cpp
-# Input
-HEADERS += qmlruntime.h \
- proxysettings.h \
- qfxtester.h \
- deviceorientation.h \
- qdeclarativefolderlistmodel.h
-SOURCES += main.cpp \
- qmlruntime.cpp \
- proxysettings.cpp \
- qfxtester.cpp \
- qdeclarativefolderlistmodel.cpp
-RESOURCES = qmlruntime.qrc
-maemo5 {
- SOURCES += deviceorientation_maemo.cpp
-} else {
- SOURCES += deviceorientation.cpp
-}
-FORMS = recopts.ui \
- proxysettings.ui
INCLUDEPATH += ../../include/QtDeclarative
INCLUDEPATH += ../../src/declarative/util
INCLUDEPATH += ../../src/declarative/graphicsitems
-include(../shared/deviceskin/deviceskin.pri)
+
target.path = $$[QT_INSTALL_BINS]
INSTALLS += target
@@ -53,8 +28,12 @@ QT += scripttools \
symbian {
# TARGET.UID3 =
include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri)
+ INCLUDEPATH += $$QT_SOURCE_TREE/examples/network/qftp/
TARGET.EPOCHEAPSIZE = 0x20000 0x2000000
- HEADERS += $$QT_SOURCE_TREE/examples/network/qftp/sym_iap_util.h
LIBS += -lesock -lcommdb -lconnmon -linsock
- TARGET.CAPABILITY = "All -TCB"
+ TARGET.CAPABILITY = NetworkServices ReadUserData
+}
+mac {
+ QMAKE_INFO_PLIST=Info_mac.plist
+ TARGET=Qml
}
diff --git a/tools/qml/qmlruntime.cpp b/tools/qml/qmlruntime.cpp
index 7da3f5a..53409c1 100644
--- a/tools/qml/qmlruntime.cpp
+++ b/tools/qml/qmlruntime.cpp
@@ -51,16 +51,10 @@
#include <qdeclarativeengine.h>
#include <qdeclarativenetworkaccessmanagerfactory.h>
#include "qdeclarative.h"
-#include <private/qperformancelog_p_p.h>
#include <private/qabstractanimation_p.h>
#include <QAbstractAnimation>
#include "deviceskin.h"
-#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 3))
-#include <private/qzipreader_p.h>
-#define QDECLARATIVEVIEWER_ZIP_SUPPORT
-#endif
-
#include <QSettings>
#include <QXmlStreamReader>
#include <QBuffer>
@@ -96,7 +90,7 @@
#include <QGLWidget>
#endif
-#include <qfxtester.h>
+#include <qdeclarativetester.h>
#if defined (Q_OS_SYMBIAN)
#define SYMBIAN_NETWORK_INIT
@@ -113,33 +107,47 @@
QT_BEGIN_NAMESPACE
-class Screen : public QObject
+class Runtime : public QObject
{
Q_OBJECT
- Q_PROPERTY(Orientation orientation READ orientation NOTIFY orientationChanged)
- Q_ENUMS(Orientation)
+ Q_PROPERTY(bool isActiveWindow READ isActiveWindow NOTIFY isActiveWindowChanged)
+ Q_PROPERTY(DeviceOrientation::Orientation orientation READ orientation NOTIFY orientationChanged)
public:
- Screen(QObject *parent=0) : QObject(parent) {
- connect(DeviceOrientation::instance(), SIGNAL(orientationChanged()),
- this, SIGNAL(orientationChanged()));
+ static Runtime* instance()
+ {
+ static Runtime *instance = 0;
+ if (!instance)
+ instance = new Runtime;
+ return instance;
+ }
+
+ bool isActiveWindow() const { return activeWindow; }
+ void setActiveWindow(bool active)
+ {
+ if (active == activeWindow)
+ return;
+ activeWindow = active;
+ emit isActiveWindowChanged();
}
- enum Orientation { UnknownOrientation = DeviceOrientation::UnknownOrientation,
- Portrait = DeviceOrientation::Portrait,
- Landscape = DeviceOrientation::Landscape };
- Orientation orientation() const { return Orientation(DeviceOrientation::instance()->orientation()); }
+ DeviceOrientation::Orientation orientation() const { return DeviceOrientation::instance()->orientation(); }
-signals:
+Q_SIGNALS:
+ void isActiveWindowChanged();
void orientationChanged();
-};
-QT_END_NAMESPACE
+private:
+ Runtime(QObject *parent=0) : QObject(parent), activeWindow(false)
+ {
+ connect(DeviceOrientation::instance(), SIGNAL(orientationChanged()),
+ this, SIGNAL(orientationChanged()));
+ }
-QML_DECLARE_TYPE(Screen)
+ bool activeWindow;
+};
-QT_BEGIN_NAMESPACE
class SizedMenuBar : public QMenuBar
{
@@ -351,30 +359,10 @@ private:
class NetworkAccessManagerFactory : public QDeclarativeNetworkAccessManagerFactory
{
public:
- NetworkAccessManagerFactory() : cookieJar(0), cacheSize(0) {}
- ~NetworkAccessManagerFactory() {
- delete cookieJar;
- }
+ NetworkAccessManagerFactory() : cacheSize(0) {}
+ ~NetworkAccessManagerFactory() {}
- QNetworkAccessManager *create(QObject *parent) {
- QMutexLocker lock(&mutex);
- QNetworkAccessManager *manager = new QNetworkAccessManager(parent);
- if (!cookieJar)
- cookieJar = new PersistentCookieJar(0);
- manager->setCookieJar(cookieJar);
- cookieJar->setParent(0);
- setupProxy(manager);
- if (cacheSize > 0) {
- QNetworkDiskCache *cache = new QNetworkDiskCache;
- cache->setCacheDirectory(QDir::tempPath()+QLatin1String("/qml-duiviewer-network-cache"));
- cache->setMaximumCacheSize(cacheSize);
- manager->setCache(cache);
- } else {
- manager->setCache(0);
- }
- qDebug() << "created new network access manager for" << parent;
- return manager;
- }
+ QNetworkAccessManager *create(QObject *parent);
void setupProxy(QNetworkAccessManager *nam)
{
@@ -419,11 +407,41 @@ public:
}
}
- PersistentCookieJar *cookieJar;
+ static PersistentCookieJar *cookieJar;
QMutex mutex;
int cacheSize;
};
+PersistentCookieJar *NetworkAccessManagerFactory::cookieJar = 0;
+
+static void cleanup_cookieJar()
+{
+ delete NetworkAccessManagerFactory::cookieJar;
+ NetworkAccessManagerFactory::cookieJar = 0;
+}
+
+QNetworkAccessManager *NetworkAccessManagerFactory::create(QObject *parent)
+{
+ QMutexLocker lock(&mutex);
+ QNetworkAccessManager *manager = new QNetworkAccessManager(parent);
+ if (!cookieJar) {
+ qAddPostRoutine(cleanup_cookieJar);
+ cookieJar = new PersistentCookieJar(0);
+ }
+ manager->setCookieJar(cookieJar);
+ cookieJar->setParent(0);
+ setupProxy(manager);
+ if (cacheSize > 0) {
+ QNetworkDiskCache *cache = new QNetworkDiskCache;
+ cache->setCacheDirectory(QDir::tempPath()+QLatin1String("/qml-duiviewer-network-cache"));
+ cache->setMaximumCacheSize(cacheSize);
+ manager->setCache(cache);
+ } else {
+ manager->setCache(0);
+ }
+ qDebug() << "created new network access manager for" << parent;
+ return manager;
+}
QString QDeclarativeViewer::getVideoFileName()
{
@@ -447,6 +465,8 @@ QDeclarativeViewer::QDeclarativeViewer(QWidget *parent, Qt::WindowFlags flags)
, portraitOrientation(0), landscapeOrientation(0)
, m_scriptOptions(0), tester(0), useQmlFileBrowser(true)
{
+ QDeclarativeViewer::registerTypes();
+
devicemode = false;
skin = 0;
canvas = 0;
@@ -530,6 +550,11 @@ QMenuBar *QDeclarativeViewer::menuBar() const
return mb;
}
+QDeclarativeView *QDeclarativeViewer::view() const
+{
+ return canvas;
+}
+
void QDeclarativeViewer::createMenu(QMenuBar *menu, QMenu *flatmenu)
{
QObject *parent = flatmenu ? (QObject*)flatmenu : (QObject*)menu;
@@ -861,122 +886,26 @@ void QDeclarativeViewer::addLibraryPath(const QString& lib)
canvas->engine()->addImportPath(lib);
}
-void QDeclarativeViewer::reload()
-{
- openQml(currentFileOrUrl);
-}
-
-void QDeclarativeViewer::open(const QString& doc)
-{
-#ifdef QDECLARATIVEVIEWER_ZIP_SUPPORT
- if (doc.endsWith(".wgt",Qt::CaseInsensitive)
- || doc.endsWith(".wgz",Qt::CaseInsensitive)
- || doc.endsWith(".zip",Qt::CaseInsensitive))
- openWgt(doc);
- else
-#endif
- openQml(doc);
-}
-
-void QDeclarativeViewer::openWgt(const QString& doc)
-{
-#ifdef QDECLARATIVEVIEWER_ZIP_SUPPORT
- // XXX This functionality could be migrated to QDeclarativeView once refined
-
- QUrl url(doc);
- if (url.isRelative())
- url = QUrl::fromLocalFile(doc);
- delete canvas->rootObject();
- canvas->engine()->clearComponentCache();
- QNetworkAccessManager * nam = canvas->engine()->networkAccessManager();
- wgtreply = nam->get(QNetworkRequest(url));
- connect(wgtreply,SIGNAL(finished()),this,SLOT(unpackWgt()));
-#endif
-}
-
-#ifdef QDECLARATIVEVIEWER_ZIP_SUPPORT
-static void removeRecursive(const QString& dirname)
+void QDeclarativeViewer::addPluginPath(const QString& plugin)
{
- QDir dir(dirname);
- QFileInfoList entries(dir.entryInfoList(QDir::Dirs|QDir::Files|QDir::NoDotAndDotDot));
- for (int i = 0; i < entries.count(); ++i)
- if (entries[i].isDir())
- removeRecursive(entries[i].filePath());
- else
- dir.remove(entries[i].fileName());
- QDir().rmdir(dirname);
+ canvas->engine()->addPluginPath(plugin);
}
-#endif
-void QDeclarativeViewer::unpackWgt()
+void QDeclarativeViewer::reload()
{
-#ifdef QDECLARATIVEVIEWER_ZIP_SUPPORT
- QByteArray all = wgtreply->readAll();
- QBuffer buf(&all);
- buf.open(QIODevice::ReadOnly);
- QZipReader zip(&buf);
- /*
- for (int i=0; i<zip.count(); ++i) {
- QZipReader::FileInfo info = zip.entryInfoAt(i);
- qDebug() << "zip:" << info.filePath;
- }
- */
- wgtdir = QDir::tempPath()+QDir::separator()+QLatin1String("qml-wgt");
- removeRecursive(wgtdir);
- QDir().mkpath(wgtdir);
- zip.extractAll(wgtdir);
-
- QString rootfile;
-
- if (wgtreply->header(QNetworkRequest::ContentTypeHeader).toString() == "application/widget" || wgtreply->url().path().endsWith(".wgt",Qt::CaseInsensitive)) {
- // W3C Draft http://www.w3.org/TR/2009/CR-widgets-20091201
- QFile configfile(wgtdir+QDir::separator()+"config.xml");
- if (configfile.open(QIODevice::ReadOnly)) {
- QXmlStreamReader config(&configfile);
- if (config.readNextStartElement() && config.name() == "widget") {
- while (config.readNextStartElement()) {
- if (config.name() == "content") {
- rootfile = wgtdir + QDir::separator();
- rootfile += config.attributes().value(QLatin1String("src"));
- }
- // XXX process other config
-
- config.skipCurrentElement();
- }
- }
- } else {
- qWarning("No config.xml found - non-standard WGT file");
- }
- if (rootfile.isEmpty()) {
- QString def = wgtdir+QDir::separator()+"index.qml";
- if (QFile::exists(def))
- rootfile = def;
- }
- } else {
- // Just find index.qml, preferably at the root
- for (int i=0; i<zip.count(); ++i) {
- QZipReader::FileInfo info = zip.entryInfoAt(i);
- if (info.filePath.compare(QLatin1String("index.qml"),Qt::CaseInsensitive)==0)
- rootfile = wgtdir+QDir::separator()+info.filePath;
- if (rootfile.isEmpty() && info.filePath.endsWith("/index.qml",Qt::CaseInsensitive))
- rootfile = wgtdir+QDir::separator()+info.filePath;
- }
- }
-
- openQml(rootfile);
-#endif
+ open(currentFileOrUrl);
}
void QDeclarativeViewer::openFile()
{
QString cur = canvas->source().toLocalFile();
if (useQmlFileBrowser) {
- openQml("qrc:/content/Browser.qml");
+ open("qrc:/content/Browser.qml");
} else {
QString fileName = QFileDialog::getOpenFileName(this, tr("Open QML file"), cur, tr("QML Files (*.qml)"));
if (!fileName.isEmpty()) {
QFileInfo fi(fileName);
- openQml(fi.absoluteFilePath());
+ open(fi.absoluteFilePath());
}
}
}
@@ -986,16 +915,30 @@ void QDeclarativeViewer::statusChanged()
if (canvas->status() == QDeclarativeView::Error && tester)
tester->executefailure();
- if (canvas->status() == QDeclarativeView::Ready)
- resize(sizeHint());
+ if (canvas->status() == QDeclarativeView::Ready) {
+ if (!skin) {
+ canvas->updateGeometry();
+ if (mb)
+ mb->updateGeometry();
+ if (!isFullScreen() && !isMaximized())
+ resize(sizeHint());
+ } else {
+ if (scaleSkin)
+ canvas->resize(canvas->sizeHint());
+ else {
+ canvas->setFixedSize(skin->standardScreenSize());
+ canvas->resize(skin->standardScreenSize());
+ }
+ }
+ }
}
void QDeclarativeViewer::launch(const QString& file_or_url)
{
- QMetaObject::invokeMethod(this, "openQml", Qt::QueuedConnection, Q_ARG(QString, file_or_url));
+ QMetaObject::invokeMethod(this, "open", Qt::QueuedConnection, Q_ARG(QString, file_or_url));
}
-void QDeclarativeViewer::openQml(const QString& file_or_url)
+bool QDeclarativeViewer::open(const QString& file_or_url)
{
currentFileOrUrl = file_or_url;
@@ -1007,7 +950,7 @@ void QDeclarativeViewer::openQml(const QString& file_or_url)
url = QUrl(file_or_url);
setWindowTitle(tr("%1 - Qt Declarative UI Viewer").arg(file_or_url));
- if (!m_script.isEmpty())
+ if (!m_script.isEmpty())
tester = new QDeclarativeTester(m_script, m_scriptOptions, canvas);
delete canvas->rootObject();
@@ -1020,13 +963,15 @@ void QDeclarativeViewer::openQml(const QString& file_or_url)
ctxt->setContextProperty("qmlViewerFolder", QDir::currentPath());
#endif
+ ctxt->setContextProperty("runtime", Runtime::instance());
+
QString fileName = url.toLocalFile();
if (!fileName.isEmpty()) {
QFileInfo fi(fileName);
if (fi.exists()) {
if (fi.suffix().toLower() != QLatin1String("qml")) {
qWarning() << "qml cannot open non-QML file" << fileName;
- return;
+ return false;
}
QDir dir(fi.path()+"/dummydata", "*.qml");
@@ -1057,7 +1002,7 @@ void QDeclarativeViewer::openQml(const QString& file_or_url)
}
} else {
qWarning() << "qml cannot find file:" << fileName;
- return;
+ return false;
}
}
@@ -1068,24 +1013,7 @@ void QDeclarativeViewer::openQml(const QString& file_or_url)
qWarning() << "Wall startup time:" << t.elapsed();
- if (!skin) {
- canvas->updateGeometry();
- if (mb)
- mb->updateGeometry();
- if (!isFullScreen() && !isMaximized())
- resize(sizeHint());
- } else {
- if (scaleSkin)
- canvas->resize(canvas->sizeHint());
- else {
- canvas->setFixedSize(skin->standardScreenSize());
- canvas->resize(skin->standardScreenSize());
- }
- }
-
-#ifdef QTOPIA
- show();
-#endif
+ return true;
}
void QDeclarativeViewer::startNetwork()
@@ -1211,7 +1139,6 @@ void QDeclarativeViewer::keyPressEvent(QKeyEvent *event)
<< "F5 - reload QML\n"
<< "F6 - show object tree\n"
<< "F7 - show timing\n"
- << "F8 - show performance (if available)\n"
<< "F9 - toggle video recording\n"
<< "F10 - toggle orientation\n"
<< "device keys: 0=quit, 1..8=F1..F8"
@@ -1223,9 +1150,6 @@ void QDeclarativeViewer::keyPressEvent(QKeyEvent *event)
takeSnapShot();
} else if (event->key() == Qt::Key_F5 || (event->key() == Qt::Key_5 && devicemode)) {
reload();
- } else if (event->key() == Qt::Key_F8 || (event->key() == Qt::Key_8 && devicemode)) {
- QPerformanceLog::displayData();
- QPerformanceLog::clear();
} else if (event->key() == Qt::Key_F9 || (event->key() == Qt::Key_9 && devicemode)) {
toggleRecording();
} else if (event->key() == Qt::Key_F10) {
@@ -1240,6 +1164,16 @@ void QDeclarativeViewer::keyPressEvent(QKeyEvent *event)
QWidget::keyPressEvent(event);
}
+bool QDeclarativeViewer::event(QEvent *event)
+{
+ if (event->type() == QEvent::WindowActivate) {
+ Runtime::instance()->setActiveWindow(true);
+ } else if (event->type() == QEvent::WindowDeactivate) {
+ Runtime::instance()->setActiveWindow(false);
+ }
+ return QWidget::event(event);
+}
+
void QDeclarativeViewer::senseImageMagick()
{
QProcess proc;
@@ -1444,10 +1378,15 @@ void QDeclarativeViewer::setUseGL(bool useGL)
#ifdef GL_SUPPORTED
if (useGL) {
QGLFormat format = QGLFormat::defaultFormat();
+#ifdef Q_WS_MAC
+ format.setSampleBuffers(true);
+#else
format.setSampleBuffers(false);
+#endif
QGLWidget *glWidget = new QGLWidget(format);
glWidget->setAutoFillBackground(false);
+
canvas->setViewport(glWidget);
}
#endif
@@ -1460,7 +1399,13 @@ void QDeclarativeViewer::setUseNativeFileBrowser(bool use)
void QDeclarativeViewer::registerTypes()
{
- QML_REGISTER_TYPE(QDeclarativeViewer, 1, 0, Screen, Screen);
+ static bool registered = false;
+
+ if (!registered) {
+ // registering only for exposing the DeviceOrientation::Orientation enum
+ qmlRegisterUncreatableType<DeviceOrientation>("Qt",4,6,"Orientation");
+ registered = true;
+ }
}
QT_END_NAMESPACE
diff --git a/tools/qml/qmlruntime.h b/tools/qml/qmlruntime.h
index 01777bd..2089dda 100644
--- a/tools/qml/qmlruntime.h
+++ b/tools/qml/qmlruntime.h
@@ -81,7 +81,8 @@ public:
TestErrorProperty = 0x00000008,
SaveOnExit = 0x00000010,
ExitOnComplete = 0x00000020,
- ExitOnFailure = 0x00000040
+ ExitOnFailure = 0x00000040,
+ Snapshot = 0x00000080
};
Q_DECLARE_FLAGS(ScriptOptions, ScriptOption)
void setScript(const QString &s) { m_script = s; }
@@ -96,6 +97,7 @@ public:
void setDeviceKeys(bool);
void setNetworkCacheSize(int size);
void addLibraryPath(const QString& lib);
+ void addPluginPath(const QString& plugin);
void setUseGL(bool use);
void setUseNativeFileBrowser(bool);
@@ -103,11 +105,11 @@ public:
QMenuBar *menuBar() const;
+ QDeclarativeView *view() const;
+
public slots:
void sceneResized(QSize size);
- void open(const QString&);
- void openWgt(const QString&);
- void openQml(const QString&);
+ bool open(const QString&);
void openFile();
void reload();
void takeSnapShot();
@@ -124,6 +126,7 @@ public slots:
protected:
virtual void keyPressEvent(QKeyEvent *);
+ virtual bool event(QEvent *);
void createMenu(QMenuBar *menu, QMenu *flatmenu);
@@ -139,7 +142,6 @@ private slots:
void toggleOrientation();
void startNetwork();
void toggleFullScreen();
- void unpackWgt();
private:
QString getVideoFileName();
diff --git a/tools/qtestlib/wince/cetest/cetcpsyncconnection.cpp b/tools/qtestlib/wince/cetest/cetcpsyncconnection.cpp
index 99219f3..5494194 100644
--- a/tools/qtestlib/wince/cetest/cetcpsyncconnection.cpp
+++ b/tools/qtestlib/wince/cetest/cetcpsyncconnection.cpp
@@ -198,3 +198,24 @@ bool CeTcpSyncConnection::fileCreationTime(const QString &fileName, FILETIME* de
file.remove();
return result;
}
+
+bool CeTcpSyncConnection::resetDevice()
+{
+ qWarning("CeTcpSyncConnection::resetDevice not implemented");
+ return false;
+}
+
+bool CeTcpSyncConnection::toggleDevicePower(int *returnValue)
+{
+ Q_UNUSED(returnValue);
+ qWarning("CeTcpSyncConnection::toggleDevicePower not implemented");
+ return false;
+}
+
+bool CeTcpSyncConnection::setDeviceAwake(bool activate, int *returnValue)
+{
+ Q_UNUSED(activate);
+ Q_UNUSED(returnValue);
+ qWarning("CeTcpSyncConnection::setDeviceAwake not implemented");
+ return false;
+}
diff --git a/tools/qtestlib/wince/cetest/cetcpsyncconnection.h b/tools/qtestlib/wince/cetest/cetcpsyncconnection.h
index 77539cc..e603efc 100644
--- a/tools/qtestlib/wince/cetest/cetcpsyncconnection.h
+++ b/tools/qtestlib/wince/cetest/cetcpsyncconnection.h
@@ -75,6 +75,9 @@ public:
bool createDirectory(const QString&, bool deleteBefore=false);
bool execute(QString program, QString arguments = QString(), int timeout = -1, int *returnValue = NULL);
+ bool resetDevice();
+ bool toggleDevicePower(int *returnValue = NULL);
+ bool setDeviceAwake(bool activate, int *returnValue = NULL);
private:
bool connected;
};
diff --git a/tools/qtestlib/wince/cetest/cetest.pro b/tools/qtestlib/wince/cetest/cetest.pro
index 2773fe4..82747da 100644
--- a/tools/qtestlib/wince/cetest/cetest.pro
+++ b/tools/qtestlib/wince/cetest/cetest.pro
@@ -36,8 +36,6 @@ HEADERS += \
SOURCES += \
remoteconnection.cpp \
deployment.cpp \
- symbian/epocroot.cpp \
- windows/registry.cpp \
main.cpp
LIBS += ole32.lib advapi32.lib
diff --git a/tools/qtestlib/wince/cetest/qmake_include.pri b/tools/qtestlib/wince/cetest/qmake_include.pri
index 8b415b0..35fbc64 100644
--- a/tools/qtestlib/wince/cetest/qmake_include.pri
+++ b/tools/qtestlib/wince/cetest/qmake_include.pri
@@ -5,7 +5,9 @@ SOURCES += \
$$QT_SOURCE_TREE/qmake/option.cpp \
$$QT_SOURCE_TREE/qmake/project.cpp \
$$QT_SOURCE_TREE/qmake/property.cpp \
+ $$QT_SOURCE_TREE/qmake/generators/metamakefile.cpp \
$$QT_SOURCE_TREE/qmake/generators/symbian/initprojectdeploy_symbian.cpp \
$$QT_SOURCE_TREE/tools/shared/symbian/epocroot.cpp \
$$QT_SOURCE_TREE/tools/shared/windows/registry.cpp
+DEFINES += QT_QMAKE_PARSER_ONLY
diff --git a/tools/qttracereplay/main.cpp b/tools/qttracereplay/main.cpp
index be7906b..101d512 100644
--- a/tools/qttracereplay/main.cpp
+++ b/tools/qttracereplay/main.cpp
@@ -49,7 +49,7 @@ class ReplayWidget : public QWidget
{
Q_OBJECT
public:
- ReplayWidget(const QString &filename, int from, int to, bool single);
+ ReplayWidget(const QString &filename, int from, int to, bool single, int frame);
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
@@ -66,27 +66,96 @@ public:
QTime timer;
QList<uint> visibleUpdates;
- QList<uint> iterationTimes;
+
+ QVector<uint> iterationTimes;
QString filename;
int from;
int to;
bool single;
+
+ int frame;
+ int currentCommand;
};
void ReplayWidget::updateRect()
{
- if (!visibleUpdates.isEmpty())
+ if (frame >= 0 && !updates.isEmpty())
+ update(updates.at(frame));
+ else if (!visibleUpdates.isEmpty())
update(updates.at(visibleUpdates.at(currentFrame)));
}
+const int singleFrameRepeatsPerCommand = 100;
+const int singleFrameIterations = 4;
+
void ReplayWidget::paintEvent(QPaintEvent *)
{
QPainter p(this);
+ QTimer::singleShot(0, this, SLOT(updateRect()));
+
// p.setClipRegion(frames.at(currentFrame).updateRegion);
+ if (frame >= 0) {
+ int start = buffer.frameStartIndex(frame);
+ int end = buffer.frameEndIndex(frame);
+
+ iterationTimes.resize(end - start);
+
+ int saveRestoreStackDepth = buffer.processCommands(&p, start, start + currentCommand);
+
+ for (int i = 0; i < saveRestoreStackDepth; ++i)
+ p.restore();
+
+ const int repeats = currentIteration >= 3 ? singleFrameRepeatsPerCommand : 1;
+
+ ++currentFrame;
+ if (currentFrame == repeats) {
+ currentFrame = 0;
+ if (currentIteration >= 3) {
+ iterationTimes[currentCommand - 1] = qMin(iterationTimes[currentCommand - 1], uint(timer.elapsed()));
+ timer.restart();
+ }
+
+ if (currentIteration >= singleFrameIterations + 3) {
+ printf(" # | ms | description\n");
+ printf("------+---------+------------------------------------------------------------\n");
+
+ qSort(iterationTimes);
+
+ int sum = 0;
+ for (int i = 0; i < iterationTimes.size(); ++i) {
+ int delta = iterationTimes.at(i);
+ if (i > 0)
+ delta -= iterationTimes.at(i-1);
+ sum += delta;
+ qreal deltaF = delta / qreal(repeats);
+ printf("%.5d | %.5f | %s\n", i, deltaF, qPrintable(buffer.commandDescription(start + i)));
+ }
+ printf("Total | %.5f | Total frame time\n", sum / qreal(repeats));
+ deleteLater();
+ return;
+ }
+
+ if (start + currentCommand >= end) {
+ currentCommand = 1;
+ ++currentIteration;
+ if (currentIteration == 3) {
+ timer.start();
+ iterationTimes.fill(uint(-1));
+ }
+ if (currentIteration >= 3 && currentIteration < singleFrameIterations + 3)
+ printf("Profiling iteration %d of %d\n", currentIteration - 2, singleFrameIterations);
+ } else {
+ ++currentCommand;
+ }
+ }
+
+ return;
+ }
+
buffer.draw(&p, visibleUpdates.at(currentFrame));
++currentFrame;
@@ -138,11 +207,9 @@ void ReplayWidget::paintEvent(QPaintEvent *)
}
}
}
-
- QTimer::singleShot(0, this, SLOT(updateRect()));
}
-void ReplayWidget::resizeEvent(QResizeEvent *event)
+void ReplayWidget::resizeEvent(QResizeEvent *)
{
visibleUpdates.clear();
@@ -162,13 +229,15 @@ void ReplayWidget::resizeEvent(QResizeEvent *event)
}
-ReplayWidget::ReplayWidget(const QString &filename_, int from_, int to_, bool single_)
+ReplayWidget::ReplayWidget(const QString &filename_, int from_, int to_, bool single_, int frame_)
: currentFrame(0)
, currentIteration(0)
, filename(filename_)
, from(from_)
, to(to_)
, single(single_)
+ , frame(frame_)
+ , currentCommand(1)
{
setWindowTitle(filename);
QFile file(filename);
@@ -216,7 +285,8 @@ int main(int argc, char **argv)
printf("Usage:\n > %s [OPTIONS] [traceFile]\n", argv[0]);
printf("OPTIONS\n"
" --range=from-to to specify a frame range.\n"
- " --singlerun to do only one run (without statistics)\n");
+ " --singlerun to do only one run (without statistics)\n"
+ " --instrumentframe=frame to instrument a single frame\n");
return 1;
}
@@ -228,6 +298,8 @@ int main(int argc, char **argv)
bool single = false;
+ int frame = -1;
+
int from = 0;
int to = -1;
for (int i = 1; i < app.arguments().size() - 1; ++i) {
@@ -253,13 +325,22 @@ int main(int argc, char **argv)
}
} else if (arg == QLatin1String("--singlerun")) {
single = true;
+ } else if (arg.startsWith(QLatin1String("--instrumentframe="))) {
+ QString rest = arg.mid(18);
+ bool ok = false;
+ int frameCandidate = rest.toInt(&ok);
+ if (ok) {
+ frame = frameCandidate;
+ } else {
+ printf("ERROR: malformed syntax in argument %s\n", qPrintable(arg));
+ }
} else {
printf("Unrecognized argument: %s\n", qPrintable(arg));
return 1;
}
}
- ReplayWidget *widget = new ReplayWidget(app.arguments().last(), from, to, single);
+ ReplayWidget *widget = new ReplayWidget(app.arguments().last(), from, to, single, frame);
if (!widget->updates.isEmpty()) {
widget->show();
diff --git a/tools/runonphone/main.cpp b/tools/runonphone/main.cpp
index 1a5cdee..37e4548 100644
--- a/tools/runonphone/main.cpp
+++ b/tools/runonphone/main.cpp
@@ -44,26 +44,31 @@
#include <QStringList>
#include <QScopedPointer>
#include <QTimer>
-#include "trkutils.h"
-#include "trkdevice.h"
-#include "launcher.h"
+#include <QFileInfo>
+#include "symbianutils/trkutils.h"
+#include "symbianutils/trkdevice.h"
+#include "symbianutils/launcher.h"
#include "trksignalhandler.h"
#include "serenum.h"
-void printUsage(QTextStream& outstream)
+void printUsage(QTextStream& outstream, QString exeName)
{
- outstream << "runtest [options] <program> [program arguments]" << endl
- << "-s, --sis <file> specify sis file to install" << endl
- << "-p, --portname <COMx> specify COM port to use by device name" << endl
- << "-f, --portfriendlyname <substring> specify COM port to use by friendly name" << endl
- << "-t, --timeout <milliseconds> terminate test if timeout occurs" << endl
- << "-v, --verbose show debugging output" << endl
- << "-q, --quiet hide progress messages" << endl
+ outstream << exeName << " [options] [program] [program arguments]" << endl
+ << "-s, --sis <file> specify sis file to install" << endl
+ << "-p, --portname <COMx> specify COM port to use by device name" << endl
+ << "-f, --portfriendlyname <substring> specify COM port to use by friendly name" << endl
+ << "-t, --timeout <milliseconds> terminate test if timeout occurs" << endl
+ << "-v, --verbose show debugging output" << endl
+ << "-q, --quiet hide progress messages" << endl
+ << "-d, --download <remote file> <local file> copy file from phone to PC after running test" << endl
<< endl
- << "USB COM ports can usually be autodetected" << endl;
+ << "USB COM ports can usually be autodetected, use -p or -f to force a specific port." << endl
+ << "If using System TRK, it is possible to copy the program directly to sys/bin on the phone." << endl
+ << "-s can be used with both System and Application TRK to install the program" << endl;
}
+#define CHECK_PARAMETER_EXISTS if(!it.hasNext()) { printUsage(outstream, args[0]); return 1; }
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
@@ -76,110 +81,116 @@ int main(int argc, char *argv[])
QStringList args = QCoreApplication::arguments();
QTextStream outstream(stdout);
QTextStream errstream(stderr);
+ QString downloadRemoteFile;
+ QString downloadLocalFile;
int loglevel=1;
int timeout=0;
- for (int i=1;i<args.size();i++) {
- QString arg = args.at(i);
+ QListIterator<QString> it(args);
+ it.next(); //skip name of program
+ while (it.hasNext()) {
+ QString arg = it.next();
+
if (arg.startsWith("-")) {
- if (args.size() < i+2) {
- errstream << "Command line missing argument parameters" << endl;
- return 1;
+ if (arg == "--portname" || arg == "-p") {
+ CHECK_PARAMETER_EXISTS
+ serialPortName = it.next();
}
- QString param = args.at(i+1);
- if(arg.compare("--portname", Qt::CaseSensitive) == 0
- || arg.compare("-p", Qt::CaseSensitive) == 0) {
- serialPortName = param;
- i++;
+ else if (arg == "--portfriendlyname" || arg == "-f") {
+ CHECK_PARAMETER_EXISTS
+ serialPortFriendlyName = it.next();
}
- else if(arg.compare("--portfriendlyname", Qt::CaseSensitive) == 0
- || arg.compare("-f", Qt::CaseSensitive) == 0) {
- serialPortFriendlyName = param;
- i++;
+ else if (arg == "--sis" || arg == "-s") {
+ CHECK_PARAMETER_EXISTS
+ sisFile = it.next();
}
- else if(arg.compare("--sis", Qt::CaseSensitive) == 0
- || arg.compare("-s", Qt::CaseSensitive) == 0) {
- sisFile = param;
- i++;
+ else if (arg == "--download" || arg == "-d") {
+ CHECK_PARAMETER_EXISTS
+ downloadRemoteFile = it.next();
+ CHECK_PARAMETER_EXISTS
+ downloadLocalFile = it.next();
}
- else if(arg.compare("--timeout", Qt::CaseSensitive) == 0
- || arg.compare("-t", Qt::CaseSensitive) == 0) {
+ else if (arg == "--timeout" || arg == "-t") {
+ CHECK_PARAMETER_EXISTS
bool ok;
- timeout = param.toInt(&ok);
+ timeout = it.next().toInt(&ok);
if (!ok) {
errstream << "Timeout must be specified in milliseconds" << endl;
return 1;
}
- i++;
}
- else if(arg.compare("--verbose", Qt::CaseSensitive) == 0
- || arg.compare("-v", Qt::CaseSensitive) == 0)
+ else if (arg == "--verbose" || arg == "-v")
loglevel=2;
- else if(arg.compare("--quiet", Qt::CaseSensitive) == 0
- || arg.compare("-q", Qt::CaseSensitive) == 0)
+ else if (arg == "--quiet" || arg == "-q")
loglevel=0;
else
errstream << "unknown command line option " << arg << endl;
} else {
exeFile = arg;
- i++;
- for(;i<args.size();i++) {
- cmdLine.append(args.at(i));
+ while(it.hasNext()) {
+ cmdLine.append(it.next());
}
}
}
- if(exeFile.isEmpty()) {
- printUsage(outstream);
+ if (exeFile.isEmpty() && sisFile.isEmpty() &&
+ (downloadLocalFile.isEmpty() || downloadRemoteFile.isEmpty())) {
+ printUsage(outstream, args[0]);
return 1;
}
- if(serialPortName.isEmpty()) {
- if(loglevel > 0)
+ if (serialPortName.isEmpty()) {
+ if (loglevel > 0)
outstream << "Detecting serial ports" << endl;
- QList <SerialPortId> ports = enumerateSerialPorts();
- foreach(SerialPortId id, ports) {
- if(loglevel > 0)
+ foreach (const SerialPortId &id, enumerateSerialPorts()) {
+ if (loglevel > 0)
outstream << "Port Name: " << id.portName << ", "
<< "Friendly Name:" << id.friendlyName << endl;
- if(serialPortName.isEmpty()) {
- if(!id.friendlyName.isEmpty() &&
- serialPortFriendlyName.isEmpty() &&
- (id.friendlyName.contains("symbian", Qt::CaseInsensitive) ||
- id.friendlyName.contains("s60", Qt::CaseInsensitive) ||
- id.friendlyName.contains("nokia", Qt::CaseInsensitive)))
- serialPortName = id.portName;
- else if (!id.friendlyName.isEmpty() &&
- !serialPortFriendlyName.isEmpty() &&
- id.friendlyName.contains(serialPortFriendlyName))
- serialPortName = id.portName;
+ if (!id.friendlyName.isEmpty()
+ && serialPortFriendlyName.isEmpty()
+ && (id.friendlyName.contains("symbian", Qt::CaseInsensitive)
+ || id.friendlyName.contains("s60", Qt::CaseInsensitive)
+ || id.friendlyName.contains("nokia", Qt::CaseInsensitive))) {
+ serialPortName = id.portName;
+ break;
+ } else if (!id.friendlyName.isEmpty()
+ && !serialPortFriendlyName.isEmpty()
+ && id.friendlyName.contains(serialPortFriendlyName)) {
+ serialPortName = id.portName;
+ break;
}
}
- if(serialPortName.isEmpty()) {
+ if (serialPortName.isEmpty()) {
errstream << "No phone found, ensure USB cable is connected or specify manually with -p" << endl;
return 1;
}
}
QScopedPointer<trk::Launcher> launcher;
-
- if(sisFile.isEmpty()) {
- launcher.reset(new trk::Launcher(trk::Launcher::ActionCopyRun));
- launcher->setCopyFileName(exeFile, QString("c:\\sys\\bin\\") + exeFile);
- errstream << "System TRK required to copy EXE, use --sis if using Application TRK" << endl;
- } else {
- launcher.reset(new trk::Launcher(trk::Launcher::ActionCopyInstallRun));
- launcher->addStartupActions(trk::Launcher::ActionInstall);
+ launcher.reset(new trk::Launcher(trk::Launcher::ActionPingOnly));
+ QFileInfo info(exeFile);
+ if (!sisFile.isEmpty()) {
+ launcher->addStartupActions(trk::Launcher::ActionCopyInstall);
launcher->setCopyFileName(sisFile, "c:\\data\\testtemp.sis");
launcher->setInstallFileName("c:\\data\\testtemp.sis");
}
- if(loglevel > 0)
+ else if (info.exists()) {
+ launcher->addStartupActions(trk::Launcher::ActionCopy);
+ launcher->setCopyFileName(exeFile, QString("c:\\sys\\bin\\") + info.fileName());
+ }
+ if (!exeFile.isEmpty()) {
+ launcher->addStartupActions(trk::Launcher::ActionRun);
+ launcher->setFileName(QString("c:\\sys\\bin\\") + info.fileName());
+ launcher->setCommandLineArgs(cmdLine);
+ }
+ if (!downloadRemoteFile.isEmpty() && !downloadLocalFile.isEmpty()) {
+ launcher->addStartupActions(trk::Launcher::ActionDownload);
+ launcher->setDownloadFileName(downloadRemoteFile, downloadLocalFile);
+ }
+ if (loglevel > 0)
outstream << "Connecting to target via " << serialPortName << endl;
launcher->setTrkServerName(serialPortName);
- launcher->setFileName(QString("c:\\sys\\bin\\") + exeFile);
- launcher->setCommandLineArgs(cmdLine);
-
- if(loglevel > 1)
+ if (loglevel > 1)
launcher->setVerbose(1);
TrkSignalHandler handler;
@@ -212,7 +223,7 @@ int main(int argc, char *argv[])
}
QString errorMessage;
- if(!launcher->startServer(&errorMessage)) {
+ if (!launcher->startServer(&errorMessage)) {
errstream << errorMessage << endl;
return 1;
}
diff --git a/tools/runonphone/runonphone.pro b/tools/runonphone/runonphone.pro
index 7bed3e5..0c63723 100644
--- a/tools/runonphone/runonphone.pro
+++ b/tools/runonphone/runonphone.pro
@@ -22,7 +22,10 @@ windows {
}
else:unix:!symbian {
SOURCES += serenum_unix.cpp
+ LIBS += -lusb
}
else {
SOURCES += serenum_stub.cpp
}
+
+
diff --git a/tools/runonphone/serenum_stub.cpp b/tools/runonphone/serenum_stub.cpp
index f39765e..6f0e1ef 100644
--- a/tools/runonphone/serenum_stub.cpp
+++ b/tools/runonphone/serenum_stub.cpp
@@ -47,7 +47,7 @@
QList<SerialPortId> enumerateSerialPorts()
{
QList<SerialPortId> list;
- qWarning() << "enumerateSerialPorts not implemented" << endl;
+ qWarning() << "enumerateSerialPorts not implemented";
return list;
}
diff --git a/tools/runonphone/serenum_unix.cpp b/tools/runonphone/serenum_unix.cpp
index ca6c437..b6f0293 100644
--- a/tools/runonphone/serenum_unix.cpp
+++ b/tools/runonphone/serenum_unix.cpp
@@ -46,13 +46,80 @@
#include <QFileInfo>
#include <QDir>
+#include <usb.h>
+
QList<SerialPortId> enumerateSerialPorts()
{
+ QList<QString> eligableInterfaces;
QList<SerialPortId> list;
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+
+ for (struct usb_bus *bus = usb_get_busses(); bus; bus = bus->next) {
+ for (struct usb_device *device = bus->devices; device; device = device->next) {
+ for (int n = 0; n < device->descriptor.bNumConfigurations; ++n) {
+ struct usb_config_descriptor &usbConfig =device->config[n];
+ QList<int> usableInterfaces;
+ for (int m = 0; m < usbConfig.bNumInterfaces; ++m) {
+ for (int o = 0; o < usbConfig.interface[m].num_altsetting; ++o) {
+ struct usb_interface_descriptor &descriptor = usbConfig.interface[m].altsetting[o];
+ if (descriptor.bInterfaceClass != 2 // "Communication"
+ || descriptor.bInterfaceSubClass != 2 // Abstract (modem)
+ || descriptor.bInterfaceProtocol != 255) // Vendor Specific
+ continue;
+
+ unsigned char *buf = descriptor.extra;
+ unsigned int size = descriptor.extralen;
+ while (size >= 2 * sizeof(u_int8_t)) {
+ // for Communication devices there is a slave interface for the actual
+ // data transmission.
+ // the extra info stores that as a index for the interface
+ if (buf[0] >= 5 && buf[1] == 36 && buf[2] == 6) { // CDC Union
+ for (int i = 4; i < buf[0]; i++)
+ usableInterfaces.append((int) buf[i]);
+ }
+ size -= buf[0];
+ buf += buf[0];
+ }
+ }
+ }
+
+ // second loop to find the actual data interface.
+ foreach (int i, usableInterfaces) {
+ for (int m = 0; m < usbConfig.bNumInterfaces; ++m) {
+ for (int o = 0; o < usbConfig.interface[m].num_altsetting; ++o) {
+ struct usb_interface_descriptor &descriptor = usbConfig.interface[m].altsetting[o];
+ if (descriptor.bInterfaceNumber != i)
+ continue;
+ if (descriptor.bInterfaceClass == 10) { // "CDC Data"
+ // qDebug() << " found the data port"
+ // << "bus:" << bus->dirname
+ // << "device" << device->filename
+ // << "interface" << descriptor.bInterfaceNumber;
+ eligableInterfaces << QString("if%1").arg(QString::number(i), 2, QChar('0')); // fix!
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
QDir dir("/dev/serial/by-id/");
- QFileInfoList ports(dir.entryInfoList());
- foreach(QFileInfo info, ports) {
+ foreach (const QFileInfo &info, dir.entryInfoList()) {
if (!info.isDir()) {
+ bool usable = eligableInterfaces.isEmpty();
+ foreach (const QString &iface, eligableInterfaces) {
+ if (info.fileName().contains(iface)) {
+ usable = true;
+ break;
+ }
+ }
+ if (!usable)
+ continue;
+
SerialPortId id;
id.friendlyName = info.fileName();
id.portName = info.canonicalFilePath();
diff --git a/tools/runonphone/symbianutils/launcher.cpp b/tools/runonphone/symbianutils/launcher.cpp
index 408829b..fa509e7 100644
--- a/tools/runonphone/symbianutils/launcher.cpp
+++ b/tools/runonphone/symbianutils/launcher.cpp
@@ -44,6 +44,7 @@
#include "trkutils_p.h"
#include "trkdevice.h"
#include "bluetoothlistener.h"
+#include "symbiandevicemanager.h"
#include <QtCore/QTimer>
#include <QtCore/QDateTime>
@@ -53,6 +54,8 @@
#include <QtCore/QFile>
#include <QtCore/QScopedPointer>
+#include <cstdio>
+
namespace trk {
struct LauncherPrivate {
@@ -61,7 +64,8 @@ struct LauncherPrivate {
QString destinationFileName;
uint copyFileHandle;
QScopedPointer<QByteArray> data;
- int position;
+ qint64 position;
+ QScopedPointer<QFile> localFile;
};
explicit LauncherPrivate(const TrkDevicePtr &d);
@@ -75,6 +79,7 @@ struct LauncherPrivate {
Session m_session; // global-ish data (process id, target information)
CopyState m_copyState;
+ CopyState m_downloadState;
QString m_fileName;
QStringList m_commandLineArgs;
QString m_installFileName;
@@ -100,12 +105,15 @@ Launcher::Launcher(Actions startupActions,
d(new LauncherPrivate(dev))
{
d->m_startupActions = startupActions;
- connect(d->m_device.data(), SIGNAL(messageReceived(trk::TrkResult)), this, SLOT(handleResult(trk::TrkResult)));
- connect(this, SIGNAL(finished()), d->m_device.data(), SLOT(close()));
+ connect(d->m_device.data(), SIGNAL(messageReceived(trk::TrkResult)), this, SLOT(handleResult(trk::TrkResult)));
}
Launcher::~Launcher()
{
+ // Destroyed before protocol was through: Close
+ if (d->m_closeDevice && d->m_device->isOpen())
+ d->m_device->close();
+ emit destroyed(d->m_device->port());
logMessage("Shutting down.\n");
delete d;
}
@@ -154,6 +162,12 @@ void Launcher::setCopyFileName(const QString &srcName, const QString &dstName)
d->m_copyState.destinationFileName = dstName;
}
+void Launcher::setDownloadFileName(const QString &srcName, const QString &dstName)
+{
+ d->m_downloadState.sourceFileName = srcName;
+ d->m_downloadState.destinationFileName = dstName;
+}
+
void Launcher::setInstallFileName(const QString &name)
{
d->m_installFileName = name;
@@ -189,10 +203,26 @@ bool Launcher::startServer(QString *errorMessage)
{
errorMessage->clear();
if (d->m_verbose) {
- const QString msg = QString::fromLatin1("Port=%1 Executable=%2 Arguments=%3 Package=%4 Remote Package=%5 Install file=%6")
- .arg(trkServerName(), d->m_fileName,
- d->m_commandLineArgs.join(QString(QLatin1Char(' '))),
- d->m_copyState.sourceFileName, d->m_copyState.destinationFileName, d->m_installFileName);
+ QString msg;
+ QTextStream str(&msg);
+ str.setIntegerBase(16);
+ str << "Actions=0x" << d->m_startupActions;
+ str.setIntegerBase(10);
+ str << " Port=" << trkServerName();
+ if (!d->m_fileName.isEmpty())
+ str << " Executable=" << d->m_fileName;
+ if (!d->m_commandLineArgs.isEmpty())
+ str << " Arguments= " << d->m_commandLineArgs.join(QString(QLatin1Char(' ')));
+ if (!d->m_copyState.sourceFileName.isEmpty())
+ str << " Package/Source=" << d->m_copyState.sourceFileName;
+ if (!d->m_copyState.destinationFileName.isEmpty())
+ str << " Remote Package/Destination=" << d->m_copyState.destinationFileName;
+ if (!d->m_downloadState.sourceFileName.isEmpty())
+ str << " Source=" << d->m_downloadState.sourceFileName;
+ if (!d->m_downloadState.destinationFileName.isEmpty())
+ str << " Destination=" << d->m_downloadState.destinationFileName;
+ if (!d->m_installFileName.isEmpty())
+ str << " Install file=" << d->m_installFileName;
logMessage(msg);
}
if (d->m_startupActions & ActionCopy) {
@@ -214,11 +244,6 @@ bool Launcher::startServer(QString *errorMessage)
}
if (!d->m_device->isOpen() && !d->m_device->open(errorMessage))
return false;
- if (d->m_closeDevice) {
- connect(this, SIGNAL(finished()), d->m_device.data(), SLOT(close()));
- } else {
- disconnect(this, SIGNAL(finished()), d->m_device.data(), 0);
- }
setState(Connecting);
// Set up the temporary 'waiting' state if we do not get immediate connection
QTimer::singleShot(1000, this, SLOT(slotWaitingForTrk()));
@@ -252,6 +277,8 @@ void Launcher::handleConnect(const TrkResult &result)
installRemotePackageSilently();
else if (d->m_startupActions & ActionRun)
startInferiorIfNeeded();
+ else if (d->m_startupActions & ActionDownload)
+ copyFileFromRemote();
}
void Launcher::setVerbose(int v)
@@ -266,6 +293,13 @@ void Launcher::logMessage(const QString &msg)
qDebug() << "LAUNCHER: " << qPrintable(msg);
}
+void Launcher::handleFinished()
+{
+ if (d->m_closeDevice)
+ d->m_device->close();
+ emit finished();
+}
+
void Launcher::terminate()
{
switch (state()) {
@@ -287,7 +321,7 @@ void Launcher::terminate()
case Connecting:
case WaitingForTrk:
setState(Disconnected);
- emit finished();
+ handleFinished();
break;
}
}
@@ -410,7 +444,7 @@ void Launcher::handleResult(const TrkResult &result)
if (itemType == 0 // process
&& result.data.size() >= 10
&& d->m_session.pid == extractInt(result.data.data() + 6)) {
- disconnectTrk();
+ copyFileFromRemote();
}
break;
}
@@ -446,7 +480,7 @@ void Launcher::handleTrkVersion(const TrkResult &result)
if (result.errorCode() || result.data.size() < 5) {
if (d->m_startupActions == ActionPingOnly) {
setState(Disconnected);
- emit finished();
+ handleFinished();
}
return;
}
@@ -455,31 +489,109 @@ void Launcher::handleTrkVersion(const TrkResult &result)
d->m_session.trkAppVersion.protocolMajor = result.data.at(3);
d->m_session.trkAppVersion.protocolMinor = result.data.at(4);
setState(DeviceDescriptionReceived);
+ const QString msg = deviceDescription();
+ emit deviceDescriptionReceived(trkServerName(), msg);
// Ping mode: Log & Terminate
if (d->m_startupActions == ActionPingOnly) {
- qWarning("%s", qPrintable(deviceDescription()));
+ qWarning("%s", qPrintable(msg));
setState(Disconnected);
- emit finished();
+ handleFinished();
}
}
+static inline QString msgCannotOpenRemoteFile(const QString &fileName, const QString &message)
+{
+ return Launcher::tr("Cannot open remote file '%1': %2").arg(fileName, message);
+}
+
+static inline QString msgCannotOpenLocalFile(const QString &fileName, const QString &message)
+{
+ return Launcher::tr("Cannot open '%1': %2").arg(fileName, message);
+}
+
void Launcher::handleFileCreation(const TrkResult &result)
{
if (result.errorCode() || result.data.size() < 6) {
- emit canNotCreateFile(d->m_copyState.destinationFileName, result.errorString());
+ const QString msg = msgCannotOpenRemoteFile(d->m_copyState.destinationFileName, result.errorString());
+ logMessage(msg);
+ emit canNotCreateFile(d->m_copyState.destinationFileName, msg);
disconnectTrk();
return;
}
const char *data = result.data.data();
d->m_copyState.copyFileHandle = extractInt(data + 2);
- QFile file(d->m_copyState.sourceFileName);
- file.open(QIODevice::ReadOnly);
- d->m_copyState.data.reset(new QByteArray(file.readAll()));
+ const QString localFileName = d->m_copyState.sourceFileName;
+ QFile file(localFileName);
d->m_copyState.position = 0;
+ if (!file.open(QIODevice::ReadOnly)) {
+ const QString msg = msgCannotOpenLocalFile(localFileName, file.errorString());
+ logMessage(msg);
+ emit canNotOpenLocalFile(localFileName, msg);
+ closeRemoteFile(true);
+ disconnectTrk();
+ return;
+ }
+ d->m_copyState.data.reset(new QByteArray(file.readAll()));
file.close();
continueCopying();
}
+void Launcher::handleFileOpened(const TrkResult &result)
+{
+ if (result.errorCode() || result.data.size() < 6) {
+ const QString msg = msgCannotOpenRemoteFile(d->m_downloadState.sourceFileName, result.errorString());
+ logMessage(msg);
+ emit canNotOpenFile(d->m_downloadState.sourceFileName, msg);
+ disconnectTrk();
+ return;
+ }
+ d->m_downloadState.position = 0;
+ const QString localFileName = d->m_downloadState.destinationFileName;
+ bool opened = false;
+ if (localFileName == QLatin1String("-")) {
+ d->m_downloadState.localFile.reset(new QFile);
+ opened = d->m_downloadState.localFile->open(stdout, QFile::WriteOnly);
+ } else {
+ d->m_downloadState.localFile.reset(new QFile(localFileName));
+ opened = d->m_downloadState.localFile->open(QFile::WriteOnly | QFile::Truncate);
+ }
+ if (!opened) {
+ const QString msg = msgCannotOpenLocalFile(localFileName, d->m_downloadState.localFile->errorString());
+ logMessage(msg);
+ emit canNotOpenLocalFile(localFileName, msg);
+ closeRemoteFile(true);
+ disconnectTrk();
+ }
+ continueReading();
+}
+
+void Launcher::continueReading()
+{
+ QByteArray ba;
+ appendInt(&ba, d->m_downloadState.copyFileHandle, TargetByteOrder);
+ appendShort(&ba, 2048, TargetByteOrder);
+ d->m_device->sendTrkMessage(TrkReadFile, TrkCallback(this, &Launcher::handleRead), ba);
+}
+
+void Launcher::handleRead(const TrkResult &result)
+{
+ if (result.errorCode() || result.data.size() < 4) {
+ d->m_downloadState.localFile->close();
+ closeRemoteFile(true);
+ disconnectTrk();
+ } else {
+ int length = extractShort(result.data.data() + 2);
+ //TRK doesn't tell us the file length, so we need to keep reading until it returns 0 length
+ if (length > 0) {
+ d->m_downloadState.localFile->write(result.data.data() + 4, length);
+ continueReading();
+ } else {
+ closeRemoteFile(true);
+ disconnectTrk();
+ }
+ }
+}
+
void Launcher::handleCopy(const TrkResult &result)
{
if (result.errorCode() || result.data.size() < 4) {
@@ -493,13 +605,14 @@ void Launcher::handleCopy(const TrkResult &result)
void Launcher::continueCopying(uint lastCopiedBlockSize)
{
- int size = d->m_copyState.data->length();
+ qint64 size = d->m_copyState.data->length();
d->m_copyState.position += lastCopiedBlockSize;
if (size == 0)
emit copyProgress(100);
else {
- int percent = qMin((d->m_copyState.position*100)/size, 100);
- emit copyProgress(percent);
+ const qint64 hundred = 100;
+ const qint64 percent = qMin( (d->m_copyState.position * hundred) / size, hundred);
+ emit copyProgress(static_cast<int>(percent));
}
if (d->m_copyState.position < size) {
QByteArray ba;
@@ -532,6 +645,8 @@ void Launcher::handleFileCopied(const TrkResult &result)
installRemotePackageSilently();
else if (d->m_startupActions & ActionRun)
startInferiorIfNeeded();
+ else if (d->m_startupActions & ActionDownload)
+ copyFileFromRemote();
else
disconnectTrk();
}
@@ -586,7 +701,7 @@ void Launcher::handleWaitForFinished(const TrkResult &result)
{
logMessage(" FINISHED: " + stringFromArray(result.data));
setState(Disconnected);
- emit finished();
+ handleFinished();
}
void Launcher::handleSupportMask(const TrkResult &result)
@@ -595,17 +710,18 @@ void Launcher::handleSupportMask(const TrkResult &result)
return;
const char *data = result.data.data() + 1;
- QString str = QLatin1String("SUPPORTED: ");
- for (int i = 0; i < 32; ++i) {
- //str.append(" [" + formatByte(data[i]) + "]: ");
- for (int j = 0; j < 8; ++j) {
- if (data[i] & (1 << j)) {
- str.append(QString::number(i * 8 + j, 16));
- str.append(QLatin1Char(' '));
+ if (d->m_verbose > 1) {
+ QString str = QLatin1String("SUPPORTED: ");
+ for (int i = 0; i < 32; ++i) {
+ for (int j = 0; j < 8; ++j) {
+ if (data[i] & (1 << j)) {
+ str.append(QString::number(i * 8 + j, 16));
+ str.append(QLatin1Char(' '));
+ }
}
}
+ logMessage(str);
}
- logMessage(str);
}
void Launcher::cleanUp()
@@ -669,11 +785,20 @@ void Launcher::copyFileToRemote()
{
emit copyingStarted();
QByteArray ba;
- ba.append(char(10));
+ ba.append(char(10)); //kDSFileOpenWrite | kDSFileOpenBinary
appendString(&ba, d->m_copyState.destinationFileName.toLocal8Bit(), TargetByteOrder, false);
d->m_device->sendTrkMessage(TrkOpenFile, TrkCallback(this, &Launcher::handleFileCreation), ba);
}
+void Launcher::copyFileFromRemote()
+{
+ emit copyingStarted();
+ QByteArray ba;
+ ba.append(char(9)); //kDSFileOpenRead | kDSFileOpenBinary
+ appendString(&ba, d->m_downloadState.sourceFileName.toLocal8Bit(), TargetByteOrder, false);
+ d->m_device->sendTrkMessage(TrkOpenFile, TrkCallback(this, &Launcher::handleFileOpened), ba);
+}
+
void Launcher::installRemotePackageSilently()
{
emit installingStarted();
@@ -694,6 +819,8 @@ void Launcher::handleInstallPackageFinished(const TrkResult &result)
}
if (d->m_startupActions & ActionRun) {
startInferiorIfNeeded();
+ } else if (d->m_startupActions & ActionDownload) {
+ copyFileFromRemote();
} else {
disconnectTrk();
}
@@ -704,18 +831,14 @@ QByteArray Launcher::startProcessMessage(const QString &executable,
{
// It's not started yet
QByteArray ba;
- appendShort(&ba, 0, TargetByteOrder); // create new process
+ appendShort(&ba, 0, TargetByteOrder); // create new process (kDSOSProcessItem)
ba.append(char(0)); // options - currently unused
- if(arguments.isEmpty()) {
- appendString(&ba, executable.toLocal8Bit(), TargetByteOrder);
- return ba;
- }
- // Append full command line as one string (leading length information).
- QByteArray commandLineBa;
- commandLineBa.append(executable.toLocal8Bit());
- commandLineBa.append('\0');
- commandLineBa.append(arguments.join(QString(QLatin1Char(' '))).toLocal8Bit());
- appendString(&ba, commandLineBa, TargetByteOrder);
+ // One string consisting of binary terminated by '\0' and arguments terminated by '\0'
+ QByteArray commandLineBa = executable.toLocal8Bit();
+ commandLineBa.append(char(0));
+ if (!arguments.isEmpty())
+ commandLineBa.append(arguments.join(QString(QLatin1Char(' '))).toLocal8Bit());
+ appendString(&ba, commandLineBa, TargetByteOrder, true);
return ba;
}
@@ -737,4 +860,37 @@ void Launcher::resumeProcess(uint pid, uint tid)
appendInt(&ba, tid, BigEndian);
d->m_device->sendTrkMessage(TrkContinue, TrkCallback(), ba, "CONTINUE");
}
+
+// Acquire a device from SymbianDeviceManager, return 0 if not available.
+Launcher *Launcher::acquireFromDeviceManager(const QString &serverName,
+ QObject *parent,
+ QString *errorMessage)
+{
+ SymbianUtils::SymbianDeviceManager *sdm = SymbianUtils::SymbianDeviceManager::instance();
+ const QSharedPointer<trk::TrkDevice> device = sdm->acquireDevice(serverName);
+ if (device.isNull()) {
+ *errorMessage = tr("Unable to acquire a device for port '%1'. It appears to be in use.").arg(serverName);
+ return 0;
+ }
+ // Wire release signal.
+ Launcher *rc = new Launcher(trk::Launcher::ActionPingOnly, device, parent);
+ connect(rc, SIGNAL(deviceDescriptionReceived(QString,QString)),
+ sdm, SLOT(setAdditionalInformation(QString,QString)));
+ connect(rc, SIGNAL(destroyed(QString)), sdm, SLOT(releaseDevice(QString)));
+ return rc;
+}
+
+// Preliminary release of device, disconnecting the signal.
+void Launcher::releaseToDeviceManager(Launcher *launcher)
+{
+ SymbianUtils::SymbianDeviceManager *sdm = SymbianUtils::SymbianDeviceManager::instance();
+ // Disentangle launcher and its device, remove connection from destroyed
+ launcher->setCloseDevice(false);
+ TrkDevice *device = launcher->trkDevice().data();
+ launcher->disconnect(device);
+ device->disconnect(launcher);
+ launcher->disconnect(sdm);
+ sdm->releaseDevice(launcher->trkServerName());
+}
+
} // namespace trk
diff --git a/tools/runonphone/symbianutils/launcher.h b/tools/runonphone/symbianutils/launcher.h
index 2b23fd8..6db69d0 100644
--- a/tools/runonphone/symbianutils/launcher.h
+++ b/tools/runonphone/symbianutils/launcher.h
@@ -69,6 +69,7 @@ public:
ActionInstall = 0x2,
ActionCopyInstall = ActionCopy | ActionInstall,
ActionRun = 0x4,
+ ActionDownload = 0x8,
ActionCopyRun = ActionCopy | ActionRun,
ActionInstallRun = ActionInstall | ActionRun,
ActionCopyInstallRun = ActionCopy | ActionInstall | ActionRun
@@ -94,10 +95,11 @@ public:
QString trkServerName() const;
void setFileName(const QString &name);
void setCopyFileName(const QString &srcName, const QString &dstName);
+ void setDownloadFileName(const QString &srcName, const QString &dstName);
void setInstallFileName(const QString &name);
void setCommandLineArgs(const QStringList &args);
bool startServer(QString *errorMessage);
- void setVerbose(int v);
+ void setVerbose(int v);
void setSerialFrame(bool b);
bool serialFrame() const;
// Close device or leave it open
@@ -109,6 +111,15 @@ public:
// becomes valid after successful execution of ActionPingOnly
QString deviceDescription(unsigned verbose = 0u) const;
+ // Acquire a device from SymbianDeviceManager, return 0 if not available.
+ // The device will be released on destruction.
+ static Launcher *acquireFromDeviceManager(const QString &serverName,
+ QObject *parent,
+ QString *errorMessage);
+ // Preliminary release of device, disconnecting the signal.
+ static void releaseToDeviceManager(Launcher *l);
+
+ // Create Trk message to start a process.
static QByteArray startProcessMessage(const QString &executable,
const QStringList &arguments);
// Parse a TrkNotifyStopped message
@@ -119,9 +130,12 @@ public:
static QString msgStopped(uint pid, uint tid, uint address, const QString &why);
signals:
+ void deviceDescriptionReceived(const QString &port, const QString &description);
void copyingStarted();
void canNotConnect(const QString &errorMessage);
void canNotCreateFile(const QString &filename, const QString &errorMessage);
+ void canNotOpenFile(const QString &filename, const QString &errorMessage);
+ void canNotOpenLocalFile(const QString &filename, const QString &errorMessage);
void canNotWriteFile(const QString &filename, const QString &errorMessage);
void canNotCloseFile(const QString &filename, const QString &errorMessage);
void installingStarted();
@@ -135,6 +149,8 @@ signals:
void copyProgress(int percent);
void stateChanged(int);
void processStopped(uint pc, uint pid, uint tid, const QString& reason);
+ // Emitted by the destructor, for releasing devices of SymbianDeviceManager by name
+ void destroyed(const QString &serverName);
public slots:
void terminate();
@@ -152,8 +168,11 @@ private:
void handleRemoteProcessKilled(const TrkResult &result);
void handleConnect(const TrkResult &result);
void handleFileCreation(const TrkResult &result);
+ void handleFileOpened(const TrkResult &result);
void handleCopy(const TrkResult &result);
+ void handleRead(const TrkResult &result);
void continueCopying(uint lastCopiedBlockSize = 0);
+ void continueReading();
void closeRemoteFile(bool failed = false);
void handleFileCopied(const TrkResult &result);
void handleInstallPackageFinished(const TrkResult &result);
@@ -165,8 +184,10 @@ private:
void handleTrkVersion(const TrkResult &result);
void copyFileToRemote();
+ void copyFileFromRemote();
void installRemotePackageSilently();
void startInferiorIfNeeded();
+ void handleFinished();
void logMessage(const QString &msg);
void setState(State s);
diff --git a/tools/runonphone/symbianutils/symbiandevicemanager.cpp b/tools/runonphone/symbianutils/symbiandevicemanager.cpp
index f663816..8877ea1 100644
--- a/tools/runonphone/symbianutils/symbiandevicemanager.cpp
+++ b/tools/runonphone/symbianutils/symbiandevicemanager.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "symbiandevicemanager.h"
+#include "trkdevice.h"
#include <QtCore/QSettings>
#include <QtCore/QStringList>
@@ -48,6 +49,7 @@
#include <QtCore/QTextStream>
#include <QtCore/QSharedData>
#include <QtCore/QScopedPointer>
+#include <QtCore/QSignalMapper>
namespace SymbianUtils {
@@ -61,19 +63,51 @@ const char *SymbianDeviceManager::linuxBlueToothDeviceRootC = "/dev/rfcomm";
// ------------- SymbianDevice
class SymbianDeviceData : public QSharedData {
public:
- SymbianDeviceData() : type(SerialPortCommunication) {}
+ SymbianDeviceData();
+ ~SymbianDeviceData();
+
+ inline bool isOpen() const { return !device.isNull() && device->isOpen(); }
+ void forcedClose();
QString portName;
QString friendlyName;
QString deviceDesc;
QString manufacturer;
+ QString additionalInformation;
+
DeviceCommunicationType type;
+ QSharedPointer<trk::TrkDevice> device;
+ bool deviceAcquired;
};
+SymbianDeviceData::SymbianDeviceData() :
+ type(SerialPortCommunication),
+ deviceAcquired(false)
+{
+}
+
+SymbianDeviceData::~SymbianDeviceData()
+{
+ forcedClose();
+}
+
+void SymbianDeviceData::forcedClose()
+{
+ // Close the device when unplugging. Should devices be in 'acquired' state,
+ // their owners should hit on write failures.
+ // Apart from the <shared item> destructor, also called by the devicemanager
+ // to ensure it also happens if other shared instances are still around.
+ if (isOpen()) {
+ if (deviceAcquired)
+ qWarning("Device on '%s' unplugged while an operation is in progress.",
+ qPrintable(portName));
+ device->close();
+ }
+}
+
SymbianDevice::SymbianDevice(SymbianDeviceData *data) :
m_data(data)
{
-
}
SymbianDevice::SymbianDevice() :
@@ -96,6 +130,11 @@ SymbianDevice::~SymbianDevice()
{
}
+void SymbianDevice::forcedClose()
+{
+ m_data->forcedClose();
+}
+
QString SymbianDevice::portName() const
{
return m_data->portName;
@@ -106,6 +145,51 @@ QString SymbianDevice::friendlyName() const
return m_data->friendlyName;
}
+QString SymbianDevice::additionalInformation() const
+{
+ return m_data->additionalInformation;
+}
+
+void SymbianDevice::setAdditionalInformation(const QString &a)
+{
+ m_data->additionalInformation = a;
+}
+
+SymbianDevice::TrkDevicePtr SymbianDevice::acquireDevice()
+{
+ if (debug)
+ qDebug() << "SymbianDevice::acquireDevice" << m_data->portName
+ << "acquired: " << m_data->deviceAcquired << " open: " << isOpen();
+ if (isNull() || m_data->deviceAcquired)
+ return TrkDevicePtr();
+ if (m_data->device.isNull()) {
+ m_data->device = TrkDevicePtr(new trk::TrkDevice);
+ m_data->device->setPort(m_data->portName);
+ m_data->device->setSerialFrame(m_data->type == SerialPortCommunication);
+ }
+ m_data->deviceAcquired = true;
+ return m_data->device;
+}
+
+void SymbianDevice::releaseDevice(TrkDevicePtr *ptr /* = 0 */)
+{
+ if (debug)
+ qDebug() << "SymbianDevice::releaseDevice" << m_data->portName
+ << " open: " << isOpen();
+ if (m_data->deviceAcquired) {
+ if (m_data->device->isOpen())
+ m_data->device->clearWriteQueue();
+ // Release if a valid pointer was passed in.
+ if (ptr && !ptr->isNull()) {
+ ptr->data()->disconnect();
+ *ptr = TrkDevicePtr();
+ }
+ m_data->deviceAcquired = false;
+ } else {
+ qWarning("Internal error: Attempt to release device that is not acquired.");
+ }
+}
+
QString SymbianDevice::deviceDesc() const
{
return m_data->deviceDesc;
@@ -123,7 +207,12 @@ DeviceCommunicationType SymbianDevice::type() const
bool SymbianDevice::isNull() const
{
- return !m_data->portName.isEmpty();
+ return m_data->portName.isEmpty();
+}
+
+bool SymbianDevice::isOpen() const
+{
+ return m_data->isOpen();
}
QString SymbianDevice::toString() const
@@ -158,7 +247,7 @@ int SymbianDevice::compare(const SymbianDevice &rhs) const
return 0;
}
-QDebug operator<<(QDebug d, const SymbianDevice &cd)
+SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDevice &cd)
{
d.nospace() << cd.toString();
return d;
@@ -166,10 +255,11 @@ QDebug operator<<(QDebug d, const SymbianDevice &cd)
// ------------- SymbianDeviceManagerPrivate
struct SymbianDeviceManagerPrivate {
- SymbianDeviceManagerPrivate() : m_initialized(false) {}
+ SymbianDeviceManagerPrivate() : m_initialized(false), m_destroyReleaseMapper(0) {}
bool m_initialized;
SymbianDeviceManager::SymbianDeviceList m_devices;
+ QSignalMapper *m_destroyReleaseMapper;
};
SymbianDeviceManager::SymbianDeviceManager(QObject *parent) :
@@ -185,8 +275,7 @@ SymbianDeviceManager::~SymbianDeviceManager()
SymbianDeviceManager::SymbianDeviceList SymbianDeviceManager::devices() const
{
- if (!d->m_initialized)
- const_cast<SymbianDeviceManager*>(this)->update(false);
+ ensureInitialized();
return d->m_devices;
}
@@ -194,6 +283,7 @@ QString SymbianDeviceManager::toString() const
{
QString rc;
QTextStream str(&rc);
+ str << d->m_devices.size() << " devices:\n";
const int count = d->m_devices.size();
for (int i = 0; i < count; i++) {
str << '#' << i << ' ';
@@ -203,13 +293,37 @@ QString SymbianDeviceManager::toString() const
return rc;
}
+int SymbianDeviceManager::findByPortName(const QString &p) const
+{
+ ensureInitialized();
+ const int count = d->m_devices.size();
+ for (int i = 0; i < count; i++)
+ if (d->m_devices.at(i).portName() == p)
+ return i;
+ return -1;
+}
+
QString SymbianDeviceManager::friendlyNameForPort(const QString &port) const
{
- foreach (const SymbianDevice &device, d->m_devices) {
- if (device.portName() == port)
- return device.friendlyName();
- }
- return QString();
+ const int idx = findByPortName(port);
+ return idx == -1 ? QString() : d->m_devices.at(idx).friendlyName();
+}
+
+SymbianDeviceManager::TrkDevicePtr
+ SymbianDeviceManager::acquireDevice(const QString &port)
+{
+ ensureInitialized();
+ const int idx = findByPortName(port);
+ if (idx == -1) {
+ qWarning("Attempt to acquire device '%s' that does not exist.", qPrintable(port));
+ if (debug)
+ qDebug() << *this;
+ return TrkDevicePtr();
+ }
+ const TrkDevicePtr rc = d->m_devices[idx].acquireDevice();
+ if (debug)
+ qDebug() << "SymbianDeviceManager::acquireDevice" << port << " returns " << !rc.isNull();
+ return rc;
}
void SymbianDeviceManager::update()
@@ -217,12 +331,38 @@ void SymbianDeviceManager::update()
update(true);
}
+void SymbianDeviceManager::releaseDevice(const QString &port)
+{
+ const int idx = findByPortName(port);
+ if (debug)
+ qDebug() << "SymbianDeviceManager::releaseDevice" << port << idx << sender();
+ if (idx != -1) {
+ d->m_devices[idx].releaseDevice();
+ } else {
+ qWarning("Attempt to release non-existing device %s.", qPrintable(port));
+ }
+}
+
+void SymbianDeviceManager::setAdditionalInformation(const QString &port, const QString &ai)
+{
+ const int idx = findByPortName(port);
+ if (idx != -1)
+ d->m_devices[idx].setAdditionalInformation(ai);
+}
+
+void SymbianDeviceManager::ensureInitialized() const
+{
+ if (!d->m_initialized) // Flag is set in update()
+ const_cast<SymbianDeviceManager*>(this)->update(false);
+}
+
void SymbianDeviceManager::update(bool emitSignals)
{
+ static int n = 0;
typedef SymbianDeviceList::iterator SymbianDeviceListIterator;
if (debug)
- qDebug(">SerialDeviceLister::update(%d)\n%s", int(emitSignals),
+ qDebug(">SerialDeviceLister::update(#%d, signals=%d)\n%s", n++, int(emitSignals),
qPrintable(toString()));
d->m_initialized = true;
@@ -230,8 +370,11 @@ void SymbianDeviceManager::update(bool emitSignals)
SymbianDeviceList newDevices = serialPorts() + blueToothDevices();
if (newDevices.size() > 1)
qStableSort(newDevices.begin(), newDevices.end());
- if (d->m_devices == newDevices) // Happy, nothing changed.
+ if (d->m_devices == newDevices) { // Happy, nothing changed.
+ if (debug)
+ qDebug("<SerialDeviceLister::update: unchanged\n");
return;
+ }
// Merge the lists and emit the respective added/removed signals, assuming
// no one can plug a different device on the same port at the speed of lightning
if (!d->m_devices.isEmpty()) {
@@ -240,7 +383,8 @@ void SymbianDeviceManager::update(bool emitSignals)
if (newDevices.contains(*oldIt)) {
++oldIt;
} else {
- const SymbianDevice toBeDeleted = *oldIt;
+ SymbianDevice toBeDeleted = *oldIt;
+ toBeDeleted.forcedClose();
oldIt = d->m_devices.erase(oldIt);
if (emitSignals)
emit deviceRemoved(toBeDeleted);
@@ -301,16 +445,30 @@ SymbianDeviceManager::SymbianDeviceList SymbianDeviceManager::blueToothDevices()
// Bluetooth devices are created on connection. List the existing ones
// or at least the first one.
const QString prefix = QLatin1String(linuxBlueToothDeviceRootC);
- const QString friendlyFormat = QLatin1String("Bluetooth device (%1)");
+ const QString blueToothfriendlyFormat = QLatin1String("Bluetooth device (%1)");
for (int d = 0; d < 4; d++) {
QScopedPointer<SymbianDeviceData> device(new SymbianDeviceData);
device->type = BlueToothCommunication;
device->portName = prefix + QString::number(d);
if (d == 0 || QFileInfo(device->portName).exists()) {
- device->friendlyName = friendlyFormat.arg(device->portName);
+ device->friendlyName = blueToothfriendlyFormat.arg(device->portName);
rc.push_back(SymbianDevice(device.take()));
}
}
+ // New kernel versions support /dev/ttyUSB0, /dev/ttyUSB1. Trk responds
+ // on the latter (usually), try first.
+ static const char *usbTtyDevices[] = { "/dev/ttyUSB1", "/dev/ttyUSB0" };
+ const int usbTtyCount = sizeof(usbTtyDevices)/sizeof(const char *);
+ for (int d = 0; d < usbTtyCount; d++) {
+ const QString ttyUSBDevice = QLatin1String(usbTtyDevices[d]);
+ if (QFileInfo(ttyUSBDevice).exists()) {
+ SymbianDeviceData *device = new SymbianDeviceData;
+ device->type = SerialPortCommunication;
+ device->portName = ttyUSBDevice;
+ device->friendlyName = QString::fromLatin1("USB/Serial device (%1)").arg(device->portName);
+ rc.push_back(SymbianDevice(device));
+ }
+ }
#endif
return rc;
}
@@ -322,7 +480,7 @@ SymbianDeviceManager *SymbianDeviceManager::instance()
return symbianDeviceManager();
}
-QDebug operator<<(QDebug d, const SymbianDeviceManager &sdm)
+SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDeviceManager &sdm)
{
d.nospace() << sdm.toString();
return d;
diff --git a/tools/runonphone/symbianutils/symbiandevicemanager.h b/tools/runonphone/symbianutils/symbiandevicemanager.h
index dcf131a..180173d 100644
--- a/tools/runonphone/symbianutils/symbiandevicemanager.h
+++ b/tools/runonphone/symbianutils/symbiandevicemanager.h
@@ -46,12 +46,17 @@
#include <QtCore/QObject>
#include <QtCore/QExplicitlySharedDataPointer>
+#include <QtCore/QSharedPointer>
QT_BEGIN_NAMESPACE
class QDebug;
class QTextStream;
QT_END_NAMESPACE
+namespace trk {
+ class TrkDevice;
+}
+
namespace SymbianUtils {
struct SymbianDeviceManagerPrivate;
@@ -62,11 +67,16 @@ enum DeviceCommunicationType {
BlueToothCommunication = 1
};
-// SymbianDevice, explicitly shared.
+// SymbianDevice: Explicitly shared device data and a TrkDevice
+// instance that can be acquired (exclusively) for use.
+// A device removal from the manager will result in the
+// device being closed.
class SYMBIANUTILS_EXPORT SymbianDevice {
explicit SymbianDevice(SymbianDeviceData *data);
friend class SymbianDeviceManager;
public:
+ typedef QSharedPointer<trk::TrkDevice> TrkDevicePtr;
+
SymbianDevice();
SymbianDevice(const SymbianDevice &rhs);
SymbianDevice &operator=(const SymbianDevice &rhs);
@@ -77,6 +87,17 @@ public:
bool isNull() const;
QString portName() const;
QString friendlyName() const;
+ QString additionalInformation() const;
+ void setAdditionalInformation(const QString &);
+
+ // Acquire: Mark the device as 'out' and return a shared pointer
+ // unless it is already in use by another owner. The result should not
+ // be passed on further.
+ TrkDevicePtr acquireDevice();
+ // Give back a device and mark it as 'free'.
+ void releaseDevice(TrkDevicePtr *ptr = 0);
+
+ bool isOpen() const;
// Windows only.
QString deviceDesc() const;
@@ -86,10 +107,12 @@ public:
QString toString() const;
private:
+ void forcedClose();
+
QExplicitlySharedDataPointer<SymbianDeviceData> m_data;
};
-QDebug operator<<(QDebug d, const SymbianDevice &);
+SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDevice &);
inline bool operator==(const SymbianDevice &d1, const SymbianDevice &d2)
{ return d1.compare(d2) == 0; }
@@ -100,13 +123,15 @@ inline bool operator<(const SymbianDevice &d1, const SymbianDevice &d2)
/* SymbianDeviceManager: Singleton that maintains a list of Symbian devices.
* and emits change signals.
- * On Windows, the update slot must be connected to a signal
- * emitted from an event handler listening for WM_DEVICECHANGE. */
+ * On Windows, the update slot must be connected to a [delayed] signal
+ * emitted from an event handler listening for WM_DEVICECHANGE.
+ * Device removal will result in the device being closed. */
class SYMBIANUTILS_EXPORT SymbianDeviceManager : public QObject
{
Q_OBJECT
public:
typedef QList<SymbianDevice> SymbianDeviceList;
+ typedef QSharedPointer<trk::TrkDevice> TrkDevicePtr;
static const char *linuxBlueToothDeviceRootC;
@@ -120,17 +145,25 @@ public:
SymbianDeviceList devices() const;
QString toString() const;
+ // Acquire a device for use. See releaseDevice().
+ TrkDevicePtr acquireDevice(const QString &port);
+
+ int findByPortName(const QString &p) const;
QString friendlyNameForPort(const QString &port) const;
public slots:
void update();
+ // Relase a device, make it available for further use.
+ void releaseDevice(const QString &port);
+ void setAdditionalInformation(const QString &port, const QString &ai);
signals:
- void deviceRemoved(const SymbianDevice &d);
- void deviceAdded(const SymbianDevice &d);
+ void deviceRemoved(const SymbianUtils::SymbianDevice &d);
+ void deviceAdded(const SymbianUtils::SymbianDevice &d);
void updated();
private:
+ void ensureInitialized() const;
void update(bool emitSignals);
SymbianDeviceList serialPorts() const;
SymbianDeviceList blueToothDevices() const;
@@ -138,7 +171,7 @@ private:
SymbianDeviceManagerPrivate *d;
};
-QDebug operator<<(QDebug d, const SymbianDeviceManager &);
+SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDeviceManager &);
} // namespace SymbianUtils
diff --git a/tools/runonphone/symbianutils/trkdevice.cpp b/tools/runonphone/symbianutils/trkdevice.cpp
index b327ab3..bd24300 100644
--- a/tools/runonphone/symbianutils/trkdevice.cpp
+++ b/tools/runonphone/symbianutils/trkdevice.cpp
@@ -52,6 +52,7 @@
#include <QtCore/QMutex>
#include <QtCore/QWaitCondition>
#include <QtCore/QSharedPointer>
+#include <QtCore/QScopedPointer>
#include <QtCore/QMetaType>
#ifdef Q_OS_WIN
@@ -102,6 +103,11 @@ QString winErrorMessage(unsigned long error)
enum { verboseTrk = 0 };
+static inline QString msgAccessingClosedDevice(const QString &msg)
+{
+ return QString::fromLatin1("Error: Attempt to access device '%1', which is closed.").arg(msg);
+}
+
namespace trk {
///////////////////////////////////////////////////////////////////////
@@ -155,10 +161,11 @@ namespace trk {
///////////////////////////////////////////////////////////////////////
class TrkWriteQueue
-{
+{
Q_DISABLE_COPY(TrkWriteQueue)
public:
explicit TrkWriteQueue();
+ void clear();
// Enqueue messages.
void queueTrkMessage(byte code, TrkCallback callback,
@@ -208,13 +215,24 @@ TrkWriteQueue::TrkWriteQueue() :
{
}
+void TrkWriteQueue::clear()
+{
+ m_trkWriteToken = 0;
+ m_trkWriteBusy = false;
+ m_trkWriteQueue.clear();
+ const int discarded = m_writtenTrkMessages.size();
+ m_writtenTrkMessages.clear();
+ if (verboseTrk)
+ qDebug() << "TrkWriteQueue::clear: discarded " << discarded;
+}
+
byte TrkWriteQueue::nextTrkWriteToken()
{
++m_trkWriteToken;
if (m_trkWriteToken == 0)
++m_trkWriteToken;
if (verboseTrk)
- qDebug() << "Write token: " << m_trkWriteToken;
+ qDebug() << "nextTrkWriteToken:" << m_trkWriteToken;
return m_trkWriteToken;
}
@@ -349,7 +367,7 @@ class WriterThread : public QThread
{
Q_OBJECT
Q_DISABLE_COPY(WriterThread)
-public:
+public:
explicit WriterThread(const QSharedPointer<DeviceContext> &context);
// Enqueue messages.
@@ -357,6 +375,8 @@ public:
const QByteArray &data, const QVariant &cookie);
void queueTrkInitialPing();
+ void clearWriteQueue();
+
// Call this from the device read notification with the results.
void slotHandleResult(const TrkResult &result);
@@ -374,7 +394,7 @@ public slots:
private slots:
void invokeNoopMessage(const trk::TrkMessage &);
-private:
+private:
bool write(const QByteArray &data, QString *errorMessage);
inline int writePendingMessage();
@@ -462,6 +482,7 @@ void WriterThread::terminate()
m_waitCondition.wakeAll();
wait();
m_terminate = false;
+ m_queue.clear();
}
#ifdef Q_OS_WIN
@@ -561,6 +582,13 @@ void WriterThread::queueTrkMessage(byte code, TrkCallback callback,
tryWrite();
}
+void WriterThread::clearWriteQueue()
+{
+ m_dataMutex.lock();
+ m_queue.clear();
+ m_dataMutex.unlock();
+}
+
void WriterThread::queueTrkInitialPing()
{
m_dataMutex.lock();
@@ -592,6 +620,8 @@ class ReaderThreadBase : public QThread
Q_DISABLE_COPY(ReaderThreadBase)
public:
+ int bytesPending() const { return m_trkReadBuffer.size(); }
+
signals:
void messageReceived(const trk::TrkResult &result, const QByteArray &rawData);
@@ -692,7 +722,7 @@ int WinReaderThread::tryRead()
if (!ClearCommError(m_context->device, NULL, &comStat)){
emit error(QString::fromLatin1("ClearCommError failed: %1").arg(winErrorMessage(GetLastError())));
return -7;
- }
+ }
const DWORD bytesToRead = qMax(DWORD(1), qMin(comStat.cbInQue, DWORD(BufSize)));
// Trigger read
DWORD bytesRead = 0;
@@ -708,7 +738,7 @@ int WinReaderThread::tryRead()
if (readError != ERROR_IO_PENDING) {
emit error(QString::fromLatin1("Read error: %1").arg(winErrorMessage(readError)));
return -1;
- }
+ }
// Wait for either termination or data
const DWORD wr = WaitForMultipleObjects(HandleCount, m_handles, false, INFINITE);
if (wr == WAIT_FAILED) {
@@ -783,7 +813,7 @@ private:
int m_terminatePipeFileDescriptors[2];
};
-UnixReaderThread::UnixReaderThread(const QSharedPointer<DeviceContext> &context) :
+UnixReaderThread::UnixReaderThread(const QSharedPointer<DeviceContext> &context) :
ReaderThreadBase(context)
{
m_terminatePipeFileDescriptors[0] = m_terminatePipeFileDescriptors[1] = -1;
@@ -877,8 +907,8 @@ struct TrkDevicePrivate
TrkDevicePrivate();
QSharedPointer<DeviceContext> deviceContext;
- QSharedPointer<WriterThread> writerThread;
- QSharedPointer<ReaderThread> readerThread;
+ QScopedPointer<WriterThread> writerThread;
+ QScopedPointer<ReaderThread> readerThread;
QByteArray trkReadBuffer;
int verbose;
@@ -917,14 +947,14 @@ TrkDevice::~TrkDevice()
bool TrkDevice::open(QString *errorMessage)
{
- if (d->verbose)
+ if (d->verbose || verboseTrk)
qDebug() << "Opening" << port() << "is open: " << isOpen() << " serialFrame=" << serialFrame();
+ if (isOpen())
+ return true;
if (d->port.isEmpty()) {
*errorMessage = QLatin1String("Internal error: No port set on TrkDevice");
return false;
}
-
- close();
#ifdef Q_OS_WIN
const QString fullPort = QLatin1String("\\\\.\\") + d->port;
d->deviceContext->device = CreateFile(reinterpret_cast<const WCHAR*>(fullPort.utf16()),
@@ -975,7 +1005,7 @@ bool TrkDevice::open(QString *errorMessage)
return false;
}
#endif
- d->readerThread = QSharedPointer<ReaderThread>(new ReaderThread(d->deviceContext));
+ d->readerThread.reset(new ReaderThread(d->deviceContext));
connect(d->readerThread.data(), SIGNAL(error(QString)), this, SLOT(emitError(QString)),
Qt::QueuedConnection);
connect(d->readerThread.data(), SIGNAL(messageReceived(trk::TrkResult,QByteArray)),
@@ -983,18 +1013,22 @@ bool TrkDevice::open(QString *errorMessage)
Qt::QueuedConnection);
d->readerThread->start();
- d->writerThread = QSharedPointer<WriterThread>(new WriterThread(d->deviceContext));
+ d->writerThread.reset(new WriterThread(d->deviceContext));
connect(d->writerThread.data(), SIGNAL(error(QString)), this, SLOT(emitError(QString)),
- Qt::QueuedConnection);
- d->writerThread->start();
+ Qt::QueuedConnection);
+ d->writerThread->start();
- if (d->verbose)
- qDebug() << "Opened" << d->port;
+ if (d->verbose || verboseTrk)
+ qDebug() << "Opened" << d->port << d->readerThread.data() << d->writerThread.data();
return true;
}
void TrkDevice::close()
{
+ if (verboseTrk)
+ qDebug() << "close" << d->port << " is open: " << isOpen()
+ << " read pending " << (d->readerThread.isNull() ? 0 : d->readerThread->bytesPending())
+ << sender();
if (!isOpen())
return;
if (d->readerThread)
@@ -1010,6 +1044,7 @@ void TrkDevice::close()
#else
d->deviceContext->file.close();
#endif
+
if (d->verbose)
emitLogMessage("Close");
}
@@ -1030,6 +1065,8 @@ QString TrkDevice::port() const
void TrkDevice::setPort(const QString &p)
{
+ if (verboseTrk)
+ qDebug() << "setPort" << p;
d->port = p;
}
@@ -1045,6 +1082,8 @@ bool TrkDevice::serialFrame() const
void TrkDevice::setSerialFrame(bool f)
{
+ if (verboseTrk)
+ qDebug() << "setSerialFrame" << f;
d->deviceContext->serialFrame = f;
}
@@ -1060,12 +1099,14 @@ void TrkDevice::setVerbose(int b)
void TrkDevice::slotMessageReceived(const trk::TrkResult &result, const QByteArray &rawData)
{
- d->writerThread->slotHandleResult(result);
- if (d->verbose > 1)
- qDebug() << "Received: " << result.toString();
- emit messageReceived(result);
- if (!rawData.isEmpty())
- emit rawDataReceived(rawData);
+ if (isOpen()) { // Might receive bytes after closing due to queued connections.
+ d->writerThread->slotHandleResult(result);
+ if (d->verbose > 1)
+ qDebug() << "Received: " << result.toString();
+ emit messageReceived(result);
+ if (!rawData.isEmpty())
+ emit rawDataReceived(rawData);
+ }
}
void TrkDevice::emitError(const QString &s)
@@ -1075,15 +1116,27 @@ void TrkDevice::emitError(const QString &s)
emit error(s);
}
+void TrkDevice::clearWriteQueue()
+{
+ if (isOpen())
+ d->writerThread->clearWriteQueue();
+}
+
void TrkDevice::sendTrkMessage(byte code, TrkCallback callback,
const QByteArray &data, const QVariant &cookie)
{
+ if (!isOpen()) {
+ emitError(msgAccessingClosedDevice(d->port));
+ return;
+ }
if (!d->writerThread.isNull()) {
if (d->verbose > 1) {
- QByteArray msg = "Sending: ";
+ QByteArray msg = "Sending: 0x";
msg += QByteArray::number(code, 16);
msg += ": ";
msg += stringFromArray(data).toLatin1();
+ if (cookie.isValid())
+ msg += " Cookie: " + cookie.toString().toLatin1();
qDebug("%s", msg.data());
}
d->writerThread->queueTrkMessage(code, callback, data, cookie);
@@ -1092,12 +1145,20 @@ void TrkDevice::sendTrkMessage(byte code, TrkCallback callback,
void TrkDevice::sendTrkInitialPing()
{
+ if (!isOpen()) {
+ emitError(msgAccessingClosedDevice(d->port));
+ return;
+ }
if (!d->writerThread.isNull())
d->writerThread->queueTrkInitialPing();
}
bool TrkDevice::sendTrkAck(byte token)
{
+ if (!isOpen()) {
+ emitError(msgAccessingClosedDevice(d->port));
+ return false;
+ }
if (d->writerThread.isNull())
return false;
// The acknowledgement must not be queued!
diff --git a/tools/runonphone/symbianutils/trkdevice.h b/tools/runonphone/symbianutils/trkdevice.h
index 78012fd..1021a7d 100644
--- a/tools/runonphone/symbianutils/trkdevice.h
+++ b/tools/runonphone/symbianutils/trkdevice.h
@@ -64,12 +64,14 @@ struct TrkDevicePrivate;
* Trk communications. Provides synchronous write and asynchronous
* read operation.
* The serialFrames property specifies whether packets are encapsulated in
- * "0x90 <length>" frames, which is currently the case for serial ports.
+ * "0x90 <length>" frames, which is currently the case for serial ports.
* Contains a write message queue allowing
* for queueing messages with a notification callback. If the message receives
* an ACK, the callback is invoked.
- * The special message TRK_WRITE_QUEUE_NOOP_CODE code can be used for synchronisation.
- * The respective message will not be sent, the callback is just invoked. */
+ * The special message TRK_WRITE_QUEUE_NOOP_CODE code can be used for synchronization.
+ * The respective message will not be sent, the callback is just invoked.
+ * Note that calling open/close in quick succession can cause crashes
+ * due to the use of queused signals. */
enum { TRK_WRITE_QUEUE_NOOP_CODE = 0x7f };
@@ -111,6 +113,9 @@ public:
// Send an Ack synchronously, bypassing the queue
bool sendTrkAck(unsigned char token);
+public slots:
+ void clearWriteQueue();
+
signals:
void messageReceived(const trk::TrkResult &result);
// Emitted with the contents of messages enclosed in 07e, not for log output
diff --git a/tools/runonphone/symbianutils/trkutils.h b/tools/runonphone/symbianutils/trkutils.h
index 3a485c7..553fc7d 100644
--- a/tools/runonphone/symbianutils/trkutils.h
+++ b/tools/runonphone/symbianutils/trkutils.h
@@ -43,6 +43,7 @@
#define DEBUGGER_TRK_UTILS
#include "symbianutils_global.h"
+
#include <QtCore/QByteArray>
#include <QtCore/QHash>
#include <QtCore/QStringList>
@@ -57,33 +58,81 @@ namespace trk {
typedef unsigned char byte;
enum Command {
+ //meta commands
TrkPing = 0x00,
TrkConnect = 0x01,
TrkDisconnect = 0x02,
+ TrkReset = 0x03,
TrkVersions = 0x04,
TrkSupported = 0x05,
TrkCpuType = 0x06,
+ TrkConfigTransport = 0x07,
+ TrkVersions2 = 0x08,
TrkHostVersions = 0x09,
+
+ //state commands
+ TrkReadMemory = 0x10,
+ TrkWriteMemory = 0x11,
+ TrkReadRegisters = 0x12,
+ TrkWriteRegisters = 0x13,
+ TrkFillMemory = 0x14,
+ TrkCopyMemory = 0x15,
+ TrkFlushCache = 0x16,
+
+ //execution commands
TrkContinue = 0x18,
+ TrkStep = 0x19,
+ TrkStop = 0x1a,
+ TrkSetBreak = 0x1b,
+ TrkClearBreak = 0x1c,
+ TrkDownload = 0x1d,
+ TrkModifyBreakThread = 0x1e,
+
+ //host -> target IO management
+ TrkNotifyFileInput = 0x20,
+ TrkBlockFileIo = 0x21,
+
+ //host -> target os commands
TrkCreateItem = 0x40,
TrkDeleteItem = 0x41,
+ TrkReadInfo = 0x42,
+ TrkWriteInfo = 0x43,
TrkWriteFile = 0x48,
+ TrkReadFile = 0x49,
TrkOpenFile = 0x4a,
TrkCloseFile = 0x4b,
+ TrkPositionFile = 0x4c,
TrkInstallFile = 0x4d,
TrkInstallFile2 = 0x4e,
+ TrkPhoneSwVersion = 0x4f,
+ TrkPhoneName = 0x50,
+ TrkVersions3 = 0x51,
+
+ //replies
TrkNotifyAck = 0x80,
TrkNotifyNak = 0xff,
+
+ //target -> host notification
TrkNotifyStopped = 0x90,
TrkNotifyException = 0x91,
TrkNotifyInternalError = 0x92,
+ TrkNotifyStopped2 = 0x94,
+
+ //target -> host OS notification
TrkNotifyCreated = 0xa0,
TrkNotifyDeleted = 0xa1,
TrkNotifyProcessorStarted = 0xa2,
TrkNotifyProcessorStandBy = 0xa6,
- TrkNotifyProcessorReset = 0xa7
+ TrkNotifyProcessorReset = 0xa7,
+
+ //target -> host support commands (these are defined but not implemented in TRK)
+ TrkDSWriteFile = 0xd0,
+ TrkDSReadFile = 0xd1,
+ TrkDSOpenFile = 0xd2,
+ TrkDSCloseFile = 0xd3,
+ TrkDSPositionFile = 0xd4
};
inline byte extractByte(const char *data) { return *data; }
@@ -118,7 +167,7 @@ struct SYMBIANUTILS_EXPORT Library
struct SYMBIANUTILS_EXPORT TrkAppVersion
{
TrkAppVersion();
- void reset();
+ void reset();
int trkMajor;
int trkMinor;
diff --git a/tools/runonphone/trksignalhandler.cpp b/tools/runonphone/trksignalhandler.cpp
index 4fa79f1..2abf91f 100644
--- a/tools/runonphone/trksignalhandler.cpp
+++ b/tools/runonphone/trksignalhandler.cpp
@@ -54,17 +54,18 @@ private:
QTextStream out;
QTextStream err;
int loglevel;
+ int lastpercent;
};
void TrkSignalHandler::copyingStarted()
{
- if(d->loglevel > 0)
+ if (d->loglevel > 0)
d->out << "Copying..." << endl;
}
void TrkSignalHandler::canNotConnect(const QString &errorMessage)
{
- d->err << "Cannot Connect - " << errorMessage << endl;
+ d->err << "Cannot connect - " << errorMessage << endl;
}
void TrkSignalHandler::canNotCreateFile(const QString &filename, const QString &errorMessage)
@@ -84,7 +85,7 @@ void TrkSignalHandler::canNotCloseFile(const QString &filename, const QString &e
void TrkSignalHandler::installingStarted()
{
- if(d->loglevel > 0)
+ if (d->loglevel > 0)
d->out << "Installing..." << endl;
}
@@ -95,19 +96,19 @@ void TrkSignalHandler::canNotInstall(const QString &packageFilename, const QStri
void TrkSignalHandler::installingFinished()
{
- if(d->loglevel > 0)
+ if (d->loglevel > 0)
d->out << "Installing finished" << endl;
}
void TrkSignalHandler::startingApplication()
{
- if(d->loglevel > 0)
+ if (d->loglevel > 0)
d->out << "Starting app..." << endl;
}
void TrkSignalHandler::applicationRunning(uint pid)
{
- if(d->loglevel > 0)
+ if (d->loglevel > 0)
d->out << "Running..." << endl;
}
@@ -118,29 +119,34 @@ void TrkSignalHandler::canNotRun(const QString &errorMessage)
void TrkSignalHandler::finished()
{
- if(d->loglevel > 0)
+ if (d->loglevel > 0)
d->out << "Done." << endl;
QCoreApplication::quit();
}
void TrkSignalHandler::applicationOutputReceived(const QString &output)
{
- d->out << output;
+ d->out << output << flush;
}
void TrkSignalHandler::copyProgress(int percent)
{
- if(d->loglevel > 0) {
- d->out << percent << "% ";
+ if (d->loglevel > 0) {
+ if (d->lastpercent == 0)
+ d->out << "[ ]\r[" << flush;
+ while (percent > d->lastpercent) {
+ d->out << QLatin1Char('#');
+ d->lastpercent+=2; //because typical console is 80 chars wide
+ }
d->out.flush();
- if(percent==100)
+ if (percent==100)
d->out << endl;
}
}
void TrkSignalHandler::stateChanged(int state)
{
- if(d->loglevel > 1)
+ if (d->loglevel > 1)
d->out << "State" << state << endl;
}
@@ -164,10 +170,11 @@ void TrkSignalHandler::timeout()
emit terminate();
}
-TrkSignalHandlerPrivate::TrkSignalHandlerPrivate() :
- out(stdout),
- err(stderr),
- loglevel(0)
+TrkSignalHandlerPrivate::TrkSignalHandlerPrivate()
+ : out(stdout),
+ err(stderr),
+ loglevel(0),
+ lastpercent(0)
{
}
@@ -179,8 +186,8 @@ TrkSignalHandlerPrivate::~TrkSignalHandlerPrivate()
}
TrkSignalHandler::TrkSignalHandler()
+ : d(new TrkSignalHandlerPrivate())
{
- d = new TrkSignalHandlerPrivate();
}
TrkSignalHandler::~TrkSignalHandler()
diff --git a/tools/shared/windows/registry.cpp b/tools/shared/windows/registry.cpp
index d342d78..67d9b56 100644
--- a/tools/shared/windows/registry.cpp
+++ b/tools/shared/windows/registry.cpp
@@ -148,7 +148,7 @@ QString readRegistryKey(HKEY parentHandle, const QString &rSubkey)
}
default:
- qWarning("QSettings: unknown data %d type in windows registry", dataType);
+ qWarning("QSettings: unknown data %u type in windows registry", quint32(dataType));
break;
}
diff --git a/tools/tools.pro b/tools/tools.pro
index 47146e5..03d01a0 100644
--- a/tools/tools.pro
+++ b/tools/tools.pro
@@ -1,34 +1,42 @@
TEMPLATE = subdirs
-no-png {
- message("Some graphics-related tools are unavailable without PNG support")
-} else {
- SUBDIRS += assistant \
- pixeltool \
- porting \
- qtestlib \
- qttracereplay
- contains(QT_EDITION, Console) {
- SUBDIRS += designer/src/uitools # Linguist depends on this
- } else {
- SUBDIRS += designer
- }
- SUBDIRS += linguist
- symbian: SUBDIRS = designer
- wince*: SUBDIRS = qtestlib designer
- unix:!mac:!embedded:!embedded_lite:contains(QT_CONFIG, qt3support):SUBDIRS += qtconfig
- win32:!wince*:SUBDIRS += activeqt
+!contains(QT_CONFIG, no-gui) {
+ no-png {
+ message("Some graphics-related tools are unavailable without PNG support")
+ } else {
+ symbian {
+ SUBDIRS = designer
+ } else:wince* {
+ SUBDIRS = qtestlib designer
+ } else {
+ SUBDIRS = assistant \
+ pixeltool \
+ porting \
+ qtestlib \
+ qttracereplay
+ contains(QT_EDITION, Console) {
+ SUBDIRS += designer/src/uitools # Linguist depends on this
+ } else {
+ SUBDIRS += designer
+ }
+ }
+ unix:!mac:!embedded:!embedded_lite:contains(QT_CONFIG, qt3support):SUBDIRS += qtconfig
+ win32:!wince*:SUBDIRS += activeqt
+ }
+ contains(QT_CONFIG, declarative):SUBDIRS += qml
}
+!wince*:!symbian:SUBDIRS += linguist
+
mac {
SUBDIRS += macdeployqt
}
embedded:SUBDIRS += kmap2qmap
-contains(QT_CONFIG, declarative):SUBDIRS += qml
contains(QT_CONFIG, dbus):SUBDIRS += qdbus
-!wince*:contains(QT_CONFIG, xmlpatterns): SUBDIRS += xmlpatterns xmlpatternsvalidator
+# We don't need these command line utilities on embedded platforms.
+!wince*:!symbian:contains(QT_CONFIG, xmlpatterns): SUBDIRS += xmlpatterns xmlpatternsvalidator
embedded: SUBDIRS += makeqpf
!wince*:!cross_compile:SUBDIRS += qdoc3