summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/assistant/tools/assistant/bookmarkmanager.cpp5
-rw-r--r--tools/assistant/tools/assistant/mainwindow.cpp16
-rw-r--r--tools/configure/configureapp.cpp27
-rw-r--r--tools/configure/environment.cpp4
-rw-r--r--tools/designer/src/components/formeditor/formwindowmanager.cpp4
-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/designer/qdesigner_actions.cpp10
-rw-r--r--tools/designer/src/lib/shared/qtresourceview.cpp3
-rw-r--r--tools/linguist/linguist/mainwindow.cpp44
-rw-r--r--tools/qdoc3/helpprojectwriter.cpp61
-rw-r--r--tools/qdoc3/htmlgenerator.cpp2
-rw-r--r--tools/qdoc3/node.h8
-rw-r--r--tools/qdoc3/tree.cpp78
-rw-r--r--tools/runonphone/main.cpp49
-rw-r--r--tools/runonphone/symbianutils/launcher.cpp83
-rw-r--r--tools/runonphone/symbianutils/launcher.h15
-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/trksignalhandler.cpp11
-rw-r--r--tools/shared/windows/registry.cpp2
23 files changed, 686 insertions, 171 deletions
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/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 0aca545..0b14cba 100644
--- a/tools/configure/configureapp.cpp
+++ b/tools/configure/configureapp.cpp
@@ -1886,7 +1886,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")) {
@@ -1978,7 +1978,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");
@@ -3508,14 +3508,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 {
@@ -3523,7 +3524,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";
}
@@ -3567,8 +3569,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;
@@ -3578,18 +3580,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..74bebb2 100644
--- a/tools/configure/environment.cpp
+++ b/tools/configure/environment.cpp
@@ -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/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/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/designer/qdesigner_actions.cpp b/tools/designer/src/designer/qdesigner_actions.cpp
index 887ba98..6776351 100644
--- a/tools/designer/src/designer/qdesigner_actions.cpp
+++ b/tools/designer/src/designer/qdesigner_actions.cpp
@@ -200,9 +200,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());
@@ -490,13 +496,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/lib/shared/qtresourceview.cpp b/tools/designer/src/lib/shared/qtresourceview.cpp
index 859f239..3c7010c 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);
diff --git a/tools/linguist/linguist/mainwindow.cpp b/tools/linguist/linguist/mainwindow.cpp
index 321fe8c..7d73596 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")));
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..cd3da3e 100644
--- a/tools/qdoc3/htmlgenerator.cpp
+++ b/tools/qdoc3/htmlgenerator.cpp
@@ -405,7 +405,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 */,
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/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/runonphone/main.cpp b/tools/runonphone/main.cpp
index af08777..80e5e34 100644
--- a/tools/runonphone/main.cpp
+++ b/tools/runonphone/main.cpp
@@ -44,6 +44,7 @@
#include <QStringList>
#include <QScopedPointer>
#include <QTimer>
+#include <QFileInfo>
#include "symbianutils/trkutils.h"
#include "symbianutils/trkdevice.h"
#include "symbianutils/launcher.h"
@@ -51,9 +52,9 @@
#include "trksignalhandler.h"
#include "serenum.h"
-void printUsage(QTextStream& outstream)
+void printUsage(QTextStream& outstream, QString exeName)
{
- outstream << "runtest [options] <program> [program arguments]" << 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
@@ -61,7 +62,9 @@ void printUsage(QTextStream& outstream)
<< "-v, --verbose show debugging output" << endl
<< "-q, --quiet hide progress messages" << 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;
}
int main(int argc, char *argv[])
@@ -86,22 +89,22 @@ int main(int argc, char *argv[])
return 1;
}
QString param = args.at(i+1);
- if(arg.compare("--portname", Qt::CaseSensitive) == 0
+ if (arg.compare("--portname", Qt::CaseSensitive) == 0
|| arg.compare("-p", Qt::CaseSensitive) == 0) {
serialPortName = param;
i++;
}
- else if(arg.compare("--portfriendlyname", Qt::CaseSensitive) == 0
+ else if (arg.compare("--portfriendlyname", Qt::CaseSensitive) == 0
|| arg.compare("-f", Qt::CaseSensitive) == 0) {
serialPortFriendlyName = param;
i++;
}
- else if(arg.compare("--sis", Qt::CaseSensitive) == 0
+ else if (arg.compare("--sis", Qt::CaseSensitive) == 0
|| arg.compare("-s", Qt::CaseSensitive) == 0) {
sisFile = param;
i++;
}
- else if(arg.compare("--timeout", Qt::CaseSensitive) == 0
+ else if (arg.compare("--timeout", Qt::CaseSensitive) == 0
|| arg.compare("-t", Qt::CaseSensitive) == 0) {
bool ok;
timeout = param.toInt(&ok);
@@ -111,10 +114,10 @@ int main(int argc, char *argv[])
}
i++;
}
- else if(arg.compare("--verbose", Qt::CaseSensitive) == 0
+ else if (arg.compare("--verbose", Qt::CaseSensitive) == 0
|| arg.compare("-v", Qt::CaseSensitive) == 0)
loglevel=2;
- else if(arg.compare("--quiet", Qt::CaseSensitive) == 0
+ else if (arg.compare("--quiet", Qt::CaseSensitive) == 0
|| arg.compare("-q", Qt::CaseSensitive) == 0)
loglevel=0;
else
@@ -128,8 +131,8 @@ int main(int argc, char *argv[])
}
}
- if(exeFile.isEmpty()) {
- printUsage(outstream);
+ if (exeFile.isEmpty() && sisFile.isEmpty()) {
+ printUsage(outstream, args[0]);
return 1;
}
@@ -161,24 +164,26 @@ int main(int argc, char *argv[])
}
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");
}
+ 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 (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)
launcher->setVerbose(1);
diff --git a/tools/runonphone/symbianutils/launcher.cpp b/tools/runonphone/symbianutils/launcher.cpp
index 408829b..92b494a 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>
@@ -100,12 +101,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;
}
@@ -214,11 +218,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()));
@@ -266,6 +265,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 +293,7 @@ void Launcher::terminate()
case Connecting:
case WaitingForTrk:
setState(Disconnected);
- emit finished();
+ handleFinished();
break;
}
}
@@ -446,7 +452,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,11 +461,13 @@ 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();
}
}
@@ -586,7 +594,7 @@ void Launcher::handleWaitForFinished(const TrkResult &result)
{
logMessage(" FINISHED: " + stringFromArray(result.data));
setState(Disconnected);
- emit finished();
+ handleFinished();
}
void Launcher::handleSupportMask(const TrkResult &result)
@@ -704,18 +712,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 +741,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..c47285c 100644
--- a/tools/runonphone/symbianutils/launcher.h
+++ b/tools/runonphone/symbianutils/launcher.h
@@ -97,7 +97,7 @@ public:
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 +109,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,6 +128,7 @@ 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);
@@ -135,6 +145,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();
@@ -167,6 +179,7 @@ private:
void copyFileToRemote();
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/trksignalhandler.cpp b/tools/runonphone/trksignalhandler.cpp
index 18a2c0c..2abf91f 100644
--- a/tools/runonphone/trksignalhandler.cpp
+++ b/tools/runonphone/trksignalhandler.cpp
@@ -54,6 +54,7 @@ private:
QTextStream out;
QTextStream err;
int loglevel;
+ int lastpercent;
};
void TrkSignalHandler::copyingStarted()
@@ -131,7 +132,12 @@ void TrkSignalHandler::applicationOutputReceived(const QString &output)
void TrkSignalHandler::copyProgress(int percent)
{
if (d->loglevel > 0) {
- d->out << percent << "% ";
+ 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)
d->out << endl;
@@ -167,7 +173,8 @@ void TrkSignalHandler::timeout()
TrkSignalHandlerPrivate::TrkSignalHandlerPrivate()
: out(stdout),
err(stderr),
- loglevel(0)
+ loglevel(0),
+ lastpercent(0)
{
}
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;
}