summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libs/utils/fileutils.cpp58
-rw-r--r--src/libs/utils/fileutils.h1
-rw-r--r--src/libs/utils/function.cpp12
-rw-r--r--src/libs/utils/function.h4
-rw-r--r--src/libs/utils/pathchooser.cpp5
-rw-r--r--src/libs/utils/pathchooser.h3
-rw-r--r--src/libs/utils/winutils.cpp48
-rw-r--r--src/plugins/android/androidconfigurations.cpp1
-rw-r--r--src/plugins/android/androiddeployqtstep.cpp2
-rw-r--r--src/plugins/android/androiddeploystep.cpp2
-rw-r--r--src/plugins/android/androidpackagecreationstep.cpp4
-rw-r--r--src/plugins/clearcase/settingspage.cpp3
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp9
-rw-r--r--src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp7
-rw-r--r--src/plugins/coreplugin/basefilewizard.cpp12
-rw-r--r--src/plugins/coreplugin/dialogs/settingsdialog.cpp2
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.cpp67
-rw-r--r--src/plugins/coreplugin/icore.cpp4
-rw-r--r--src/plugins/cppeditor/cppeditor.cpp20
-rw-r--r--src/plugins/cppeditor/cppeditor.h4
-rw-r--r--src/plugins/cppeditor/cppeditorplugin.cpp2
-rw-r--r--src/plugins/cppeditor/cppeditorplugin.h4
-rw-r--r--src/plugins/cppeditor/cppfollowsymbolundercursor.cpp77
-rw-r--r--src/plugins/cppeditor/cppincludehierarchymodel.cpp4
-rw-r--r--src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp78
-rw-r--r--src/plugins/cppeditor/cppvirtualfunctionassistprovider.h25
-rw-r--r--src/plugins/cppeditor/cppvirtualfunctionproposalitem.h1
-rw-r--r--src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp287
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.cpp10
-rw-r--r--src/plugins/debugger/cdb/cdbengine.cpp6
-rw-r--r--src/plugins/debugger/debugger.pro8
-rw-r--r--src/plugins/debugger/debugger.qbs4
-rw-r--r--src/plugins/debugger/debuggerdialogs.cpp6
-rw-r--r--src/plugins/debugger/debuggerengine.cpp4
-rw-r--r--src/plugins/debugger/debuggeritem.cpp352
-rw-r--r--src/plugins/debugger/debuggeritem.h104
-rw-r--r--src/plugins/debugger/debuggeritemmanager.cpp403
-rw-r--r--src/plugins/debugger/debuggeritemmanager.h96
-rw-r--r--src/plugins/debugger/debuggeritemmodel.cpp304
-rw-r--r--src/plugins/debugger/debuggeritemmodel.h92
-rw-r--r--src/plugins/debugger/debuggerkitconfigwidget.cpp1129
-rw-r--r--src/plugins/debugger/debuggerkitconfigwidget.h91
-rw-r--r--src/plugins/debugger/debuggerkitinformation.cpp479
-rw-r--r--src/plugins/debugger/debuggerkitinformation.h101
-rw-r--r--src/plugins/debugger/debuggeroptionspage.cpp337
-rw-r--r--src/plugins/debugger/debuggeroptionspage.h90
-rw-r--r--src/plugins/debugger/debuggerplugin.cpp2
-rw-r--r--src/plugins/debugger/debuggerrunner.cpp11
-rw-r--r--src/plugins/debugger/gdb/gdbengine.cpp53
-rw-r--r--src/plugins/debugger/gdb/gdbengine.h1
-rw-r--r--src/plugins/debugger/lldb/lldbengine.cpp47
-rw-r--r--src/plugins/debugger/pdb/pdbengine.cpp2
-rw-r--r--src/plugins/debugger/qml/qmlengine.cpp2
-rw-r--r--src/plugins/debugger/qml/qmlinspectoragent.cpp3
-rw-r--r--src/plugins/debugger/watchdata.cpp3
-rw-r--r--src/plugins/debugger/watchwindow.cpp2
-rw-r--r--src/plugins/fakevim/fakevimhandler.cpp29
-rw-r--r--src/plugins/git/gerrit/gerritdialog.cpp2
-rw-r--r--src/plugins/git/gerrit/gerritpushdialog.cpp4
-rw-r--r--src/plugins/git/gitclient.cpp4
-rw-r--r--src/plugins/ios/iosconfigurations.cpp1
-rw-r--r--src/plugins/ios/iosdevice.cpp6
-rw-r--r--src/plugins/locator/executefilter.cpp5
-rw-r--r--src/plugins/projectexplorer/abi.cpp18
-rw-r--r--src/plugins/projectexplorer/abi.h2
-rw-r--r--src/plugins/projectexplorer/applicationlauncher.cpp15
-rw-r--r--src/plugins/projectexplorer/copytaskhandler.cpp4
-rw-r--r--src/plugins/projectexplorer/customparserconfigdialog.cpp2
-rw-r--r--src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp12
-rw-r--r--src/plugins/projectexplorer/foldernavigationwidget.cpp22
-rw-r--r--src/plugins/projectexplorer/foldernavigationwidget.h1
-rw-r--r--src/plugins/projectexplorer/kitinformationconfigwidget.cpp2
-rw-r--r--src/plugins/projectexplorer/msvcparser.cpp10
-rw-r--r--src/plugins/projectexplorer/projectwelcomepage.cpp14
-rw-r--r--src/plugins/projectexplorer/targetsettingspanel.cpp2
-rw-r--r--src/plugins/projectexplorer/taskwindow.cpp16
-rw-r--r--src/plugins/qbsprojectmanager/qbsproject.cpp11
-rw-r--r--src/plugins/qmldesigner/components/componentcore/tabviewdesigneraction.cpp2
-rw-r--r--src/plugins/qmldesigner/components/debugview/debugview.cpp4
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/qml/ItemsView.qml1
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/qml/ItemsViewStyle.qml2
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/qml/Scrollbar.qml21
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/qml/SectionView.qml32
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp10
-rw-r--r--src/plugins/qmldesigner/components/resources/scrollbar.css31
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/HorizontalScrollBar.qml10
-rw-r--r--src/plugins/qmldesigner/componentsplugin/Controls/ButtonSpecifics.qml2
-rw-r--r--src/plugins/qmldesigner/componentsplugin/Controls/CheckBoxSpecifics.qml6
-rw-r--r--src/plugins/qmldesigner/componentsplugin/Controls/TextAreaSpecifics.qml4
-rw-r--r--src/plugins/qmldesigner/componentsplugin/Controls/TextFieldSpecifics.qml2
-rw-r--r--src/plugins/qmlprofiler/qmlprofilereventview.cpp2
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp12
-rw-r--r--src/plugins/qnx/blackberryapplicationrunner.cpp86
-rw-r--r--src/plugins/qnx/blackberryapplicationrunner.h4
-rw-r--r--src/plugins/qnx/blackberryconfiguration.cpp1
-rw-r--r--src/plugins/qnx/blackberrydebugsupport.cpp2
-rw-r--r--src/plugins/qnx/blackberrydebugtokenrequestdialog.cpp2
-rw-r--r--src/plugins/qnx/blackberrydeviceconfigurationwidget.cpp2
-rw-r--r--src/plugins/qnx/blackberrydeviceconfigurationwizardpages.cpp6
-rw-r--r--src/plugins/qnx/blackberrydeviceconnection.cpp3
-rw-r--r--src/plugins/qnx/blackberrydeviceconnectionmanager.cpp4
-rw-r--r--src/plugins/qnx/blackberrydeviceconnectionmanager.h1
-rw-r--r--src/plugins/qnx/blackberryruncontrol.cpp34
-rw-r--r--src/plugins/qnx/blackberryruncontrol.h6
-rw-r--r--src/plugins/qnx/blackberrysetupwizard.cpp4
-rw-r--r--src/plugins/qt4projectmanager/librarydetailscontroller.cpp1
-rw-r--r--src/plugins/qt4projectmanager/qmakestep.cpp5
-rw-r--r--src/plugins/qt4projectmanager/wizards/qtquickapp.cpp32
-rw-r--r--src/plugins/qtsupport/baseqtversion.cpp10
-rw-r--r--src/plugins/qtsupport/gettingstartedwelcomepage.cpp5
-rw-r--r--src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp2
-rw-r--r--src/plugins/remotelinux/remotelinuxsignaloperation.cpp3
-rw-r--r--src/plugins/texteditor/behaviorsettingswidget.cpp7
-rw-r--r--src/plugins/valgrind/memcheck/memcheckrunner.cpp4
-rw-r--r--src/plugins/welcome/welcomeplugin.cpp13
-rw-r--r--src/tools/qtcreatorcrashhandler/crashhandlerdialog.cpp2
116 files changed, 2887 insertions, 2163 deletions
diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp
index 80ef5bc5ff..ef3b5c5e77 100644
--- a/src/libs/utils/fileutils.cpp
+++ b/src/libs/utils/fileutils.cpp
@@ -38,6 +38,10 @@
#include <QDateTime>
#include <QMessageBox>
+#ifdef Q_OS_WIN
+#include <qt_windows.h>
+#endif
+
namespace Utils {
/*! \class Utils::FileUtils
@@ -237,6 +241,60 @@ bool FileUtils::makeWritable(const FileName &path)
return QFile::setPermissions(fileName, QFile::permissions(fileName) | QFile::WriteUser);
}
+#ifdef Q_OS_WIN
+static QString getShortPathName(const QString &name)
+{
+ if (name.isEmpty())
+ return name;
+
+ // Determine length, then convert.
+ const LPCTSTR nameC = reinterpret_cast<LPCTSTR>(name.utf16()); // MinGW
+ const DWORD length = GetShortPathNameW(nameC, NULL, 0);
+ if (length == 0)
+ return name;
+ QScopedArrayPointer<TCHAR> buffer(new TCHAR[length]);
+ GetShortPathNameW(nameC, buffer.data(), length);
+ const QString rc = QString::fromUtf16(reinterpret_cast<const ushort *>(buffer.data()), length - 1);
+ return rc;
+}
+
+static QString getLongPathName(const QString &name)
+{
+ if (name.isEmpty())
+ return name;
+
+ // Determine length, then convert.
+ const LPCTSTR nameC = reinterpret_cast<LPCTSTR>(name.utf16()); // MinGW
+ const DWORD length = GetLongPathNameW(nameC, NULL, 0);
+ if (length == 0)
+ return name;
+ QScopedArrayPointer<TCHAR> buffer(new TCHAR[length]);
+ GetLongPathNameW(nameC, buffer.data(), length);
+ const QString rc = QString::fromUtf16(reinterpret_cast<const ushort *>(buffer.data()), length - 1);
+ return rc;
+}
+#endif // Q_OS_WIN
+
+// makes sure that capitalization of directories is canonical on Windows.
+// This mimics the logic in QDeclarative_isFileCaseCorrect
+QString FileUtils::normalizePathName(const QString &name)
+{
+#ifdef Q_OS_WIN
+ QString canonicalName = getShortPathName(name);
+ if (canonicalName.isEmpty())
+ return name;
+ canonicalName = getLongPathName(canonicalName);
+ if (canonicalName.isEmpty())
+ return name;
+ // Upper case drive letter
+ if (canonicalName.size() > 2 && canonicalName.at(1) == QLatin1Char(':'))
+ canonicalName[0] = canonicalName.at(0).toUpper();
+ return canonicalName;
+#else // Filesystem is case-insensitive only on Windows
+ return name;
+#endif
+}
+
QByteArray FileReader::fetchQrc(const QString &fileName)
{
QTC_ASSERT(fileName.startsWith(QLatin1Char(':')), return QByteArray());
diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h
index 0cf1db64b1..0b19a913fb 100644
--- a/src/libs/utils/fileutils.h
+++ b/src/libs/utils/fileutils.h
@@ -98,6 +98,7 @@ public:
static QString shortNativePath(const FileName &path);
static QString fileSystemFriendlyName(const QString &name);
static bool makeWritable(const FileName &path);
+ static QString normalizePathName(const QString &name);
};
class QTCREATOR_UTILS_EXPORT FileReader
diff --git a/src/libs/utils/function.cpp b/src/libs/utils/function.cpp
index 68370976d8..45f02f776d 100644
--- a/src/libs/utils/function.cpp
+++ b/src/libs/utils/function.cpp
@@ -41,7 +41,7 @@ void functionUser(Utils::function<int()> generator, Utils::function<void(int)> c
struct GenFunctor
{
- int operator()() { return 29; }
+ int operator()() const { return 29; }
};
struct ConsumerFunctor
@@ -49,6 +49,13 @@ struct ConsumerFunctor
void operator()(int) {}
};
+struct ConsumerFunctor2
+{
+ ConsumerFunctor2() : i(0) { }
+ int i;
+ void operator()(int j) { i = j; }
+};
+
int generatorF()
{
return 42;
@@ -64,6 +71,9 @@ void test()
{
functionUser(GenFunctor(), ConsumerFunctor());
functionUser(&generatorF, &consumerF);
+ ConsumerFunctor2 f2;
+ GenFunctor g2;
+ functionUser(Utils::cref(g2), Utils::ref(f2));
}
} // end namespace
diff --git a/src/libs/utils/function.h b/src/libs/utils/function.h
index d6dbc2f999..52938f385e 100644
--- a/src/libs/utils/function.h
+++ b/src/libs/utils/function.h
@@ -39,9 +39,9 @@
# ifdef __GNUC__
# include <tr1/functional>
# endif
-namespace Utils { using std::tr1::function; }
+namespace Utils { using std::tr1::function; using std::tr1::ref; using std::tr1::cref; }
#else
-namespace Utils { using std::function; }
+namespace Utils { using std::function; using std::ref; using std::cref; }
#endif
#endif // QTC_FUNCTION_H
diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp
index 9305680ad5..d6e3a59301 100644
--- a/src/libs/utils/pathchooser.cpp
+++ b/src/libs/utils/pathchooser.cpp
@@ -654,6 +654,11 @@ void PathChooser::installLineEditVersionToolTip(QLineEdit *le, const QStringList
ef->setArguments(arguments);
}
+void PathChooser::setHistoryCompleter(const QString &historyKey)
+{
+ d->m_lineEdit->setHistoryCompleter(historyKey);
+}
+
QStringList PathChooser::commandVersionArguments() const
{
return d->m_binaryVersionToolTipEventFilter ?
diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h
index 2dc33c0c9d..483c94e576 100644
--- a/src/libs/utils/pathchooser.h
+++ b/src/libs/utils/pathchooser.h
@@ -128,6 +128,9 @@ public:
// Install a tooltip on lineedits used for binaries showing the version.
static void installLineEditVersionToolTip(QLineEdit *le, const QStringList &arguments);
+ // Enable a history completer with a history of entries.
+ void setHistoryCompleter(const QString &historyKey);
+
bool isReadOnly() const;
void setReadOnly(bool b);
diff --git a/src/libs/utils/winutils.cpp b/src/libs/utils/winutils.cpp
index cf54a24d4f..59daad82df 100644
--- a/src/libs/utils/winutils.cpp
+++ b/src/libs/utils/winutils.cpp
@@ -129,54 +129,6 @@ QTCREATOR_UTILS_EXPORT QString winGetDLLVersion(WinDLLVersionType t,
return rc;
}
-QTCREATOR_UTILS_EXPORT QString getShortPathName(const QString &name)
-{
- if (name.isEmpty())
- return name;
-
- // Determine length, then convert.
- const LPCTSTR nameC = reinterpret_cast<LPCTSTR>(name.utf16()); // MinGW
- const DWORD length = GetShortPathNameW(nameC, NULL, 0);
- if (length == 0)
- return name;
- QScopedArrayPointer<TCHAR> buffer(new TCHAR[length]);
- GetShortPathNameW(nameC, buffer.data(), length);
- const QString rc = QString::fromUtf16(reinterpret_cast<const ushort *>(buffer.data()), length - 1);
- return rc;
-}
-
-QTCREATOR_UTILS_EXPORT QString getLongPathName(const QString &name)
-{
- if (name.isEmpty())
- return name;
-
- // Determine length, then convert.
- const LPCTSTR nameC = reinterpret_cast<LPCTSTR>(name.utf16()); // MinGW
- const DWORD length = GetLongPathNameW(nameC, NULL, 0);
- if (length == 0)
- return name;
- QScopedArrayPointer<TCHAR> buffer(new TCHAR[length]);
- GetLongPathNameW(nameC, buffer.data(), length);
- const QString rc = QString::fromUtf16(reinterpret_cast<const ushort *>(buffer.data()), length - 1);
- return rc;
-}
-
-// makes sure that capitalization of directories is canonical.
-// This mimics the logic in QDeclarative_isFileCaseCorrect
-QTCREATOR_UTILS_EXPORT QString normalizePathName(const QString &name)
-{
- QString canonicalName = getShortPathName(name);
- if (canonicalName.isEmpty())
- return name;
- canonicalName = getLongPathName(canonicalName);
- if (canonicalName.isEmpty())
- return name;
- // Upper case drive letter
- if (canonicalName.size() > 2 && canonicalName.at(1) == QLatin1Char(':'))
- canonicalName[0] = canonicalName.at(0).toUpper();
- return canonicalName;
-}
-
QTCREATOR_UTILS_EXPORT bool winIs64BitSystem()
{
SYSTEM_INFO systemInfo;
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
index 80d1c9451a..ee39135f5d 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -44,6 +44,7 @@
#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/toolchainmanager.h>
#include <projectexplorer/session.h>
+#include <debugger/debuggeritemmanager.h>
#include <debugger/debuggerkitinformation.h>
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp
index 405f317ef5..75e39a6f9e 100644
--- a/src/plugins/android/androiddeployqtstep.cpp
+++ b/src/plugins/android/androiddeployqtstep.cpp
@@ -336,7 +336,7 @@ void AndroidDeployQtStep::runCommand(const QString &program, const QStringList &
QString mainMessage = tr("Packaging Error: Command '%1 %2' failed.")
.arg(program).arg(arguments.join(QLatin1String(" ")));
if (buildProc.error() != QProcess::UnknownError)
- mainMessage += tr(" Reason: %1").arg(buildProc.errorString());
+ mainMessage += QLatin1Char(' ') + tr("Reason: %1").arg(buildProc.errorString());
else
mainMessage += tr("Exit code: %1").arg(buildProc.exitCode());
emit addOutput(mainMessage, BuildStep::ErrorMessageOutput);
diff --git a/src/plugins/android/androiddeploystep.cpp b/src/plugins/android/androiddeploystep.cpp
index d8264898d8..dcdb8968ff 100644
--- a/src/plugins/android/androiddeploystep.cpp
+++ b/src/plugins/android/androiddeploystep.cpp
@@ -239,7 +239,7 @@ bool AndroidDeployStep::runCommand(QProcess *buildProc,
QString mainMessage = tr("Packaging Error: Command '%1 %2' failed.")
.arg(program).arg(arguments.join(QLatin1String(" ")));
if (buildProc->error() != QProcess::UnknownError)
- mainMessage += tr(" Reason: %1").arg(buildProc->errorString());
+ mainMessage += QLatin1Char(' ') + tr("Reason: %1").arg(buildProc->errorString());
else
mainMessage += tr("Exit code: %1").arg(buildProc->exitCode());
writeOutput(mainMessage, BuildStep::ErrorMessageOutput);
diff --git a/src/plugins/android/androidpackagecreationstep.cpp b/src/plugins/android/androidpackagecreationstep.cpp
index 285f7b3ee5..a72b9ac695 100644
--- a/src/plugins/android/androidpackagecreationstep.cpp
+++ b/src/plugins/android/androidpackagecreationstep.cpp
@@ -613,7 +613,7 @@ bool AndroidPackageCreationStep::createPackage()
emit addOutput(tr("Copy Qt app & libs to Android package ..."), MessageOutput);
QStringList build;
- build << QLatin1String("-silent");
+ // build << QLatin1String("-silent"); //TODO depends on ant 1.9.0, enabled, not *now*
build << QLatin1String("clean");
QFile::remove(m_gdbServerDestination.toString());
if (m_signPackageForRun) {
@@ -803,7 +803,7 @@ bool AndroidPackageCreationStep::runCommand(QProcess *buildProc
QString mainMessage = tr("Packaging Error: Command '%1 %2' failed.")
.arg(program).arg(arguments.join(QLatin1String(" ")));
if (buildProc->error() != QProcess::UnknownError)
- mainMessage += tr(" Reason: %1").arg(buildProc->errorString());
+ mainMessage += QLatin1Char(' ') + tr("Reason: %1").arg(buildProc->errorString());
else
mainMessage += tr("Exit code: %1").arg(buildProc->exitCode());
raiseError(mainMessage);
diff --git a/src/plugins/clearcase/settingspage.cpp b/src/plugins/clearcase/settingspage.cpp
index 983dac4845..2dc0ad0019 100644
--- a/src/plugins/clearcase/settingspage.cpp
+++ b/src/plugins/clearcase/settingspage.cpp
@@ -86,7 +86,8 @@ void SettingsPageWidget::setSettings(const ClearCaseSettings &s)
} else {
QString diffWarning = tr("In order to use External diff, 'diff' command needs to be accessible.");
if (HostOsInfo::isWindowsHost()) {
- diffWarning.append(tr(" DiffUtils is available for free download "
+ diffWarning += QLatin1Char(' ');
+ diffWarning.append(tr("DiffUtils is available for free download "
"<a href=\"http://gnuwin32.sourceforge.net/packages/diffutils.htm\">here</a>. "
"Please extract it to a directory in your PATH."));
}
diff --git a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp
index a68a919c1d..f3a49624e9 100644
--- a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp
@@ -455,7 +455,7 @@ ShadowBuildPage::ShadowBuildPage(CMakeOpenProjectWizard *cmakeWizard, bool chang
QLabel *label = new QLabel(this);
label->setWordWrap(true);
if (change)
- label->setText(tr("Please enter the directory in which you want to build your project. "));
+ label->setText(tr("Please enter the directory in which you want to build your project.") + QLatin1Char(' '));
else
label->setText(tr("Please enter the directory in which you want to build your project. "
"Qt Creator recommends to not use the source directory for building. "
@@ -507,13 +507,14 @@ void ChooseCMakePage::updateErrorText()
} else {
QString text = tr("Specify the path to the CMake executable. No CMake executable was found in the path.");
if (!cmakeExecutable.isEmpty()) {
+ text += QLatin1Char(' ');
QFileInfo fi(cmakeExecutable);
if (!fi.exists())
- text += tr(" The CMake executable (%1) does not exist.").arg(cmakeExecutable);
+ text += tr("The CMake executable (%1) does not exist.").arg(cmakeExecutable);
else if (!fi.isExecutable())
- text += tr(" The path %1 is not an executable.").arg(cmakeExecutable);
+ text += tr("The path %1 is not an executable.").arg(cmakeExecutable);
else
- text += tr(" The path %1 is not a valid CMake executable.").arg(cmakeExecutable);
+ text += tr("The path %1 is not a valid CMake executable.").arg(cmakeExecutable);
}
m_cmakeLabel->setText(text);
}
diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp
index e256fbe4f0..50e5a4d6af 100644
--- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp
@@ -193,7 +193,12 @@ QString CMakeRunConfiguration::defaultDisplayName() const
{
if (m_title.isEmpty())
return tr("Run CMake kit");
- return m_title + (m_enabled ? QString() : tr(" (disabled)"));
+ QString result = m_title;
+ if (!m_enabled) {
+ result += QLatin1Char(' ');
+ result += tr("(disabled)");
+ }
+ return result;
}
QWidget *CMakeRunConfiguration::createConfigurationWidget()
diff --git a/src/plugins/coreplugin/basefilewizard.cpp b/src/plugins/coreplugin/basefilewizard.cpp
index bb26839348..9ba83657a5 100644
--- a/src/plugins/coreplugin/basefilewizard.cpp
+++ b/src/plugins/coreplugin/basefilewizard.cpp
@@ -407,9 +407,9 @@ BaseFileWizard::OverwriteResult BaseFileWizard::promptOverwrite(GeneratedFiles *
QStringList existingFiles;
bool oddStuffFound = false;
- static const QString readOnlyMsg = tr(" [read only]");
- static const QString directoryMsg = tr(" [folder]");
- static const QString symLinkMsg = tr(" [symbolic link]");
+ static const QString readOnlyMsg = tr("[read only]");
+ static const QString directoryMsg = tr("[folder]");
+ static const QString symLinkMsg = tr("[symbolic link]");
foreach (const GeneratedFile &file, *files) {
const QFileInfo fi(file.path());
@@ -432,17 +432,17 @@ BaseFileWizard::OverwriteResult BaseFileWizard::promptOverwrite(GeneratedFiles *
do {
if (fi.isDir()) {
oddStuffFound = true;
- fileNamesMsgPart += directoryMsg;
+ fileNamesMsgPart += QLatin1Char(' ') + directoryMsg;
break;
}
if (fi.isSymLink()) {
oddStuffFound = true;
- fileNamesMsgPart += symLinkMsg;
+ fileNamesMsgPart += QLatin1Char(' ') + symLinkMsg;
break;
}
if (!fi.isWritable()) {
oddStuffFound = true;
- fileNamesMsgPart += readOnlyMsg;
+ fileNamesMsgPart += QLatin1Char(' ') + readOnlyMsg;
}
} while (false);
}
diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.cpp b/src/plugins/coreplugin/dialogs/settingsdialog.cpp
index bb6783bcda..4593488c1b 100644
--- a/src/plugins/coreplugin/dialogs/settingsdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/settingsdialog.cpp
@@ -400,6 +400,8 @@ void SettingsDialog::createGui()
mainGridLayout->setColumnStretch(1, 4);
setLayout(mainGridLayout);
setMinimumSize(1000, 550);
+ if (Utils::HostOsInfo::isMacHost())
+ setMinimumHeight(minimumHeight() * 1.1);
}
SettingsDialog::~SettingsDialog()
diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp
index 93a7c3c739..073b89dc5b 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.cpp
+++ b/src/plugins/coreplugin/editormanager/editormanager.cpp
@@ -854,10 +854,13 @@ static void setFocusToEditorViewAndUnmaximizePanes(EditorView *view)
void EditorManager::doEscapeKeyFocusMoveMagic()
{
// use cases to cover:
- // 1. if app focus is in mode or external window without editor view (e.g. Projects, ext. Help)
- // activate & raise the current editor view (can be external)
- // if that is in edit mode
- // activate edit mode and unmaximize output pane
+ // 1. if app focus is in mode or external window without editor view (e.g. Design, Projects, ext. Help)
+ // if there are extra views (e.g. output)
+ // hide them
+ // otherwise
+ // activate & raise the current editor view (can be external)
+ // if that is in edit mode
+ // activate edit mode and unmaximize output pane
// 2. if app focus is in external window with editor view
// hide find if necessary
// 2. if app focus is in mode with editor view
@@ -874,44 +877,54 @@ void EditorManager::doEscapeKeyFocusMoveMagic()
// otherwise (i.e. mode is edit mode)
// hide extra views (find, help, output)
+ QWidget *activeWindow = qApp->activeWindow();
+ if (!activeWindow)
+ return;
+ QWidget *focus = qApp->focusWidget();
EditorView *editorView = currentEditorView();
- bool editorViewActive = (qApp->focusWidget() == editorView->focusWidget());
+ bool editorViewActive = (focus && focus == editorView->focusWidget());
bool editorViewVisible = editorView->isVisible();
- if (!editorViewActive && editorViewVisible) {
- setFocusToEditorViewAndUnmaximizePanes(editorView);
- return;
- }
- if (!editorViewActive && !editorViewVisible) {
- // assumption is that editorView is in main window then
- ModeManager::activateMode(Id(Constants::MODE_EDIT));
- QTC_CHECK(editorView->isVisible());
- setFocusToEditorViewAndUnmaximizePanes(editorView);
- return;
- }
- if (editorViewActive) {
- QTC_CHECK(editorViewVisible);
+
+ if (!( editorViewVisible && !editorViewActive && editorView->window() == activeWindow )) {
bool stuffHidden = false;
QWidget *findPane = FindToolBarPlaceHolder::getCurrent();
- if (findPane && findPane->isVisibleTo(editorView)) {
+ if (findPane && findPane->isVisible() && findPane->window() == activeWindow) {
findPane->hide();
stuffHidden = true;
}
QWidget *outputPane = OutputPanePlaceHolder::getCurrent();
- if (outputPane && outputPane->isVisibleTo(editorView)) {
+ if (outputPane && outputPane->isVisible() && outputPane->window() == activeWindow) {
OutputPaneManager::instance()->slotHide();
stuffHidden = true;
}
QWidget *rightPane = RightPanePlaceHolder::current();
- if (rightPane && rightPane->isVisibleTo(editorView)) {
+ if (rightPane && rightPane->isVisible() && rightPane->window() == activeWindow) {
RightPaneWidget::instance()->setShown(false);
stuffHidden = true;
}
- if (!stuffHidden && editorView->window() == ICore::mainWindow()) {
- // we are in a editor view and there's nothing to hide, switch to edit
- ModeManager::activateMode(Id(Constants::MODE_EDIT));
- // next call works only because editor views in main window are shared between modes
- setFocusToEditorViewAndUnmaximizePanes(editorView);
- }
+ if (stuffHidden)
+ return;
+ }
+
+ if (!editorViewActive && editorViewVisible) {
+ setFocusToEditorViewAndUnmaximizePanes(editorView);
+ return;
+ }
+
+ if (!editorViewActive && !editorViewVisible) {
+ // assumption is that editorView is in main window then
+ ModeManager::activateMode(Id(Constants::MODE_EDIT));
+ QTC_CHECK(editorView->isVisible());
+ setFocusToEditorViewAndUnmaximizePanes(editorView);
+ return;
+ }
+
+ if (editorView->window() == ICore::mainWindow()) {
+ // we are in a editor view and there's nothing to hide, switch to edit
+ ModeManager::activateMode(Id(Constants::MODE_EDIT));
+ QTC_CHECK(editorView->isVisible());
+ // next call works only because editor views in main window are shared between modes
+ setFocusToEditorViewAndUnmaximizePanes(editorView);
}
}
diff --git a/src/plugins/coreplugin/icore.cpp b/src/plugins/coreplugin/icore.cpp
index 7564a59f02..a226c2b609 100644
--- a/src/plugins/coreplugin/icore.cpp
+++ b/src/plugins/coreplugin/icore.cpp
@@ -415,7 +415,9 @@ static QString compilerString()
#elif defined(Q_CC_GNU)
return QLatin1String("GCC " ) + QLatin1String(__VERSION__);
#elif defined(Q_CC_MSVC)
- if (_MSC_VER >= 1500) // 1500: MSVC 2008, 1600: MSVC 2010, ...
+ if (_MSC_VER >= 1800) // 1800: MSVC 2013 (yearly release cycle)
+ return QLatin1String("MSVC ") + QString::number(2008 + ((_MSC_VER / 100) - 13));
+ if (_MSC_VER >= 1500) // 1500: MSVC 2008, 1600: MSVC 2010, ... (2-year release cycle)
return QLatin1String("MSVC ") + QString::number(2008 + 2 * ((_MSC_VER / 100) - 15));
#endif
return QLatin1String("<unknown compiler>");
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 0604edde96..fe072bde82 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -518,6 +518,7 @@ CPPEditorWidget::CPPEditorWidget(QWidget *parent)
, m_objcEnabled(false)
, m_commentsSettings(CppTools::CppToolsSettings::instance()->commentsSettings())
, m_followSymbolUnderCursor(new FollowSymbolUnderCursor(this))
+ , m_preprocessorButton(0)
{
qRegisterMetaType<SemanticInfo>("CppTools::SemanticInfo");
@@ -647,10 +648,13 @@ void CPPEditorWidget::createToolBar(CPPEditor *editor)
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateUses()));
connect(this, SIGNAL(textChanged()), this, SLOT(updateUses()));
- QToolButton *hashButton = new QToolButton(this);
- hashButton->setText(QLatin1String("#"));
- connect(hashButton, SIGNAL(clicked()), this, SLOT(showPreProcessorWidget()));
- editor->insertExtraToolBarWidget(TextEditor::BaseTextEditor::Left, hashButton);
+ m_preprocessorButton = new QToolButton(this);
+ m_preprocessorButton->setText(QLatin1String("#"));
+ Core::Command *cmd = Core::ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG);
+ connect(cmd, SIGNAL(keySequenceChanged()), this, SLOT(updatePreprocessorButtonTooltip()));
+ updatePreprocessorButtonTooltip();
+ connect(m_preprocessorButton, SIGNAL(clicked()), this, SLOT(showPreProcessorWidget()));
+ editor->insertExtraToolBarWidget(TextEditor::BaseTextEditor::Left, m_preprocessorButton);
editor->insertExtraToolBarWidget(TextEditor::BaseTextEditor::Left, m_outlineCombo);
}
@@ -1012,6 +1016,14 @@ void CPPEditorWidget::onContentsChanged(int position, int charsRemoved, int char
updateUses();
}
+void CPPEditorWidget::updatePreprocessorButtonTooltip()
+{
+ QTC_ASSERT(m_preprocessorButton, return);
+ Core::Command *cmd = Core::ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG);
+ QTC_ASSERT(cmd, return);
+ m_preprocessorButton->setToolTip(cmd->action()->toolTip());
+}
+
void CPPEditorWidget::jumpToOutlineElement(int index)
{
QModelIndex modelIndex = m_outlineCombo->view()->currentIndex();
diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h
index ae1f57e31b..ba3b58ccee 100644
--- a/src/plugins/cppeditor/cppeditor.h
+++ b/src/plugins/cppeditor/cppeditor.h
@@ -50,6 +50,7 @@
QT_BEGIN_NAMESPACE
class QComboBox;
class QSortFilterProxyModel;
+class QToolButton;
QT_END_NAMESPACE
namespace CPlusPlus {
@@ -175,6 +176,7 @@ private Q_SLOTS:
void onFunctionDeclDefLinkFound(QSharedPointer<FunctionDeclDefLink> link);
void onDocumentUpdated();
void onContentsChanged(int position, int charsRemoved, int charsAdded);
+ void updatePreprocessorButtonTooltip();
void updateSemanticInfo(const CppTools::SemanticInfo &semanticInfo);
void highlightSymbolUsages(int from, int to);
@@ -258,7 +260,7 @@ private:
CppTools::CommentsSettings m_commentsSettings;
QScopedPointer<FollowSymbolUnderCursor> m_followSymbolUnderCursor;
- QString m_preProcessorAdditions;
+ QToolButton *m_preprocessorButton;
};
} // namespace Internal
diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp
index b9c66de4a1..d7dd630a43 100644
--- a/src/plugins/cppeditor/cppeditorplugin.cpp
+++ b/src/plugins/cppeditor/cppeditorplugin.cpp
@@ -210,7 +210,7 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err
contextMenu->addAction(cmd);
cppToolsMenu->addAction(cmd);
- QAction *openPreprocessorDialog = new QAction(tr("Additional Preprocessor Directives"), this);
+ QAction *openPreprocessorDialog = new QAction(tr("Additional Preprocessor Directives..."), this);
cmd = ActionManager::registerAction(openPreprocessorDialog,
Constants::OPEN_PREPROCESSOR_DIALOG, context);
cmd->setDefaultKeySequence(QKeySequence());
diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h
index 33e32593f4..c9e6f5e873 100644
--- a/src/plugins/cppeditor/cppeditorplugin.h
+++ b/src/plugins/cppeditor/cppeditorplugin.h
@@ -138,6 +138,10 @@ private slots:
void test_FollowSymbolUnderCursor_virtualFunctionCall_allOverrides();
void test_FollowSymbolUnderCursor_virtualFunctionCall_possibleOverrides1();
void test_FollowSymbolUnderCursor_virtualFunctionCall_possibleOverrides2();
+ void test_FollowSymbolUnderCursor_virtualFunctionCall_fallbackToDeclaration();
+ void test_FollowSymbolUnderCursor_virtualFunctionCall_itemOrder();
+ void test_FollowSymbolUnderCursor_virtualFunctionCall_onDotMemberAccessOfReferenceTypes();
+ void test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDotMemberAccessOfNonReferenceType();
void test_FollowSymbolUnderCursor_virtualFunctionCall_notOnQualified();
void test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDeclaration();
void test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDefinition();
diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
index ad4a8c3012..0b6cd23a6d 100644
--- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
+++ b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
@@ -55,35 +55,57 @@ typedef BaseTextEditorWidget::Link Link;
namespace {
-bool lookupVirtualFunctionOverrides(const QString &expression, Function *function, Scope *scope,
+bool lookupVirtualFunctionOverrides(TypeOfExpression &typeOfExpression,
+ const Document::Ptr &document,
+ const Function *function,
+ Scope *scope,
const Snapshot &snapshot)
{
- if (expression.isEmpty() || !function || !scope || scope->isClass() || snapshot.isEmpty())
+ if (!document || !function || !scope || scope->isClass() || snapshot.isEmpty())
+ return false;
+
+ ExpressionAST *expressionAST = typeOfExpression.expressionAST();
+ if (!expressionAST)
+ return false;
+ CallAST *callAST = expressionAST->asCall();
+ if (!callAST)
+ return false;
+ ExpressionAST *baseExpressionAST = callAST->base_expression;
+ if (!baseExpressionAST)
return false;
bool result = false;
- Document::Ptr expressionDocument = documentForExpression(expression.toUtf8());
- if (ExpressionAST *expressionAST = extractExpressionAST(expressionDocument)) {
- if (CallAST *callAST = expressionAST->asCall()) {
- if (ExpressionAST *baseExpressionAST = callAST->base_expression) {
- if (IdExpressionAST *idExpressionAST = baseExpressionAST->asIdExpression()) {
- NameAST *name = idExpressionAST->name;
- result = name && !name->asQualifiedName();
- } else if (MemberAccessAST *memberAccessAST = baseExpressionAST->asMemberAccess()) {
- NameAST *name = memberAccessAST->member_name;
- const bool nameIsQualified = name && name->asQualifiedName();
-
- TranslationUnit *unit = expressionDocument->translationUnit();
- QTC_ASSERT(unit, return false);
- const int tokenKind = unit->tokenKind(memberAccessAST->access_token);
- result = tokenKind == T_ARROW && !nameIsQualified;
+ if (IdExpressionAST *idExpressionAST = baseExpressionAST->asIdExpression()) {
+ NameAST *name = idExpressionAST->name;
+ const bool nameIsQualified = name && name->asQualifiedName();
+ result = !nameIsQualified && FunctionHelper::isVirtualFunction(function, snapshot);
+ } else if (MemberAccessAST *memberAccessAST = baseExpressionAST->asMemberAccess()) {
+ NameAST *name = memberAccessAST->member_name;
+ const bool nameIsQualified = name && name->asQualifiedName();
+ if (!nameIsQualified && FunctionHelper::isVirtualFunction(function, snapshot)) {
+ const Document::Ptr expressionDocument
+ = typeOfExpression.context().expressionDocument();
+ QTC_ASSERT(expressionDocument, return false);
+ TranslationUnit *unit = expressionDocument->translationUnit();
+ QTC_ASSERT(unit, return false);
+ const int accessTokenKind = unit->tokenKind(memberAccessAST->access_token);
+
+ if (accessTokenKind == T_ARROW) {
+ result = true;
+ } else if (accessTokenKind == T_DOT) {
+ const QList<LookupItem> items = typeOfExpression.reference(
+ memberAccessAST->base_expression, document, scope);
+ if (!items.isEmpty()) {
+ const LookupItem item = items.first();
+ if (Symbol *declaration = item.declaration())
+ result = declaration->type()->isReferenceType();
}
}
}
}
- return result && FunctionHelper::isVirtualFunction(function, snapshot);
+ return result;
}
Link findMacroLink_helper(const QByteArray &name, Document::Ptr doc, const Snapshot &snapshot,
@@ -530,16 +552,27 @@ BaseTextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &
// Consider to show a pop-up displaying overrides for the function
Function *function = symbol->type()->asFunctionType();
- if (lookupVirtualFunctionOverrides(expression, function, scope, snapshot)) {
+ if (lookupVirtualFunctionOverrides(typeOfExpression, doc, function, scope, snapshot)) {
Class *klass = symbolFinder->findMatchingClassDeclaration(function, snapshot);
QTC_CHECK(klass);
- if (m_virtualFunctionAssistProvider->configure(klass, function, snapshot,
- inNextSplit)) {
+ VirtualFunctionAssistProvider::Parameters params;
+ params.startClass = klass;
+ params.function = function;
+ params.snapshot = snapshot;
+ params.cursorPosition = cursor.position();
+ params.openInNextSplit = inNextSplit;
+
+ if (m_virtualFunctionAssistProvider->configure(params)) {
m_widget->invokeAssist(TextEditor::FollowSymbol,
m_virtualFunctionAssistProvider);
}
- return Link();
+
+ // Ensure a valid link text, so the symbol name will be underlined on Ctrl+Hover.
+ Link link;
+ link.linkTextStart = beginOfToken;
+ link.linkTextEnd = endOfToken;
+ return link;
}
if (resolveTarget) {
diff --git a/src/plugins/cppeditor/cppincludehierarchymodel.cpp b/src/plugins/cppeditor/cppincludehierarchymodel.cpp
index 7b6909f617..7709bed2d5 100644
--- a/src/plugins/cppeditor/cppincludehierarchymodel.cpp
+++ b/src/plugins/cppeditor/cppincludehierarchymodel.cpp
@@ -117,11 +117,11 @@ QVariant CppIncludeHierarchyModel::data(const QModelIndex &index, int role) cons
if (role == Qt::DisplayRole) {
if ((item == m_includesItem && m_includesItem->childCount() == 0)
|| (item == m_includedByItem && m_includedByItem->childCount() == 0)) {
- return QString(item->fileName() + tr(" (none)"));
+ return QString(item->fileName() + QLatin1Char(' ') + tr("(none)"));
}
if (item->isCyclic())
- return QString(item->fileName() + tr(" (cyclic)"));
+ return QString(item->fileName() + QLatin1Char(' ') + tr("(cyclic)"));
return item->fileName();
}
diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
index 5f44589885..76d6cc0d17 100644
--- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
+++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
@@ -40,6 +40,8 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
+#include <cpptools/symbolfinder.h>
+
#include <texteditor/codeassist/basicproposalitemlistmodel.h>
#include <texteditor/codeassist/genericproposal.h>
#include <texteditor/codeassist/genericproposalwidget.h>
@@ -107,16 +109,13 @@ private:
class VirtualFunctionsAssistProcessor : public IAssistProcessor
{
public:
- VirtualFunctionsAssistProcessor(const VirtualFunctionAssistProvider *provider)
- : m_startClass(provider->startClass())
- , m_function(provider->function())
- , m_snapshot(provider->snapshot())
- , m_openInNextSplit(provider->openInNextSplit())
+ VirtualFunctionsAssistProcessor(const VirtualFunctionAssistProvider::Parameters &params)
+ : m_params(params)
{}
- IAssistProposal *immediateProposal(const TextEditor::IAssistInterface *interface)
+ IAssistProposal *immediateProposal(const TextEditor::IAssistInterface *)
{
- QTC_ASSERT(m_function, return 0);
+ QTC_ASSERT(m_params.function, return 0);
BasicProposalItem *hintItem = new VirtualFunctionProposalItem(CPPEditorWidget::Link());
hintItem->setText(QCoreApplication::translate("VirtualFunctionsAssistProcessor",
@@ -124,69 +123,67 @@ public:
hintItem->setOrder(-1000);
QList<BasicProposalItem *> items;
- items << itemFromSymbol(m_function, m_function);
+ items << itemFromSymbol(maybeDefinitionFor(m_params.function));
items << hintItem;
- return new VirtualFunctionProposal(interface->position(),
+ return new VirtualFunctionProposal(m_params.cursorPosition,
new BasicProposalItemListModel(items),
- m_openInNextSplit);
+ m_params.openInNextSplit);
}
- IAssistProposal *perform(const IAssistInterface *interface)
+ IAssistProposal *perform(const IAssistInterface *)
{
- if (!interface)
- return 0;
+ QTC_ASSERT(m_params.startClass, return 0);
+ QTC_ASSERT(m_params.function, return 0);
+ QTC_ASSERT(!m_params.snapshot.isEmpty(), return 0);
- QTC_ASSERT(m_startClass, return 0);
- QTC_ASSERT(m_function, return 0);
- QTC_ASSERT(!m_snapshot.isEmpty(), return 0);
+ const QList<Symbol *> overrides
+ = FunctionHelper::overrides(m_params.startClass, m_params.function, m_params.snapshot);
+ if (overrides.isEmpty())
+ return 0;
- const QList<Symbol *> overrides = FunctionHelper::overrides(m_startClass, m_function,
- m_snapshot);
QList<BasicProposalItem *> items;
foreach (Symbol *symbol, overrides)
- items << itemFromSymbol(symbol, m_function);
+ items << itemFromSymbol(maybeDefinitionFor(symbol));
+ items.first()->setOrder(1000); // Ensure top position for function of static type
- return new VirtualFunctionProposal(interface->position(),
+ return new VirtualFunctionProposal(m_params.cursorPosition,
new BasicProposalItemListModel(items),
- m_openInNextSplit);
+ m_params.openInNextSplit);
}
- BasicProposalItem *itemFromSymbol(Symbol *symbol, Symbol *firstSymbol) const
+private:
+ Symbol *maybeDefinitionFor(Symbol *symbol)
+ {
+ if (Function *definition = m_finder.findMatchingDefinition(symbol, m_params.snapshot))
+ return definition;
+ return symbol;
+ }
+
+ BasicProposalItem *itemFromSymbol(Symbol *symbol) const
{
const QString text = m_overview.prettyName(LookupContext::fullyQualifiedName(symbol));
const CPPEditorWidget::Link link = CPPEditorWidget::linkToSymbol(symbol);
- BasicProposalItem *item = new VirtualFunctionProposalItem(link, m_openInNextSplit);
+ BasicProposalItem *item = new VirtualFunctionProposalItem(link, m_params.openInNextSplit);
item->setText(text);
item->setIcon(m_icons.iconForSymbol(symbol));
- if (symbol == firstSymbol)
- item->setOrder(1000); // Ensure top position for function of static type
return item;
}
-private:
- Class *m_startClass;
- Function *m_function;
- Snapshot m_snapshot;
- bool m_openInNextSplit;
+ VirtualFunctionAssistProvider::Parameters m_params;
Overview m_overview;
Icons m_icons;
+ CppTools::SymbolFinder m_finder;
};
VirtualFunctionAssistProvider::VirtualFunctionAssistProvider()
- : m_function(0)
- , m_openInNextSplit(false)
{
}
-bool VirtualFunctionAssistProvider::configure(Class *startClass, Function *function,
- const Snapshot &snapshot, bool openInNextSplit)
+bool VirtualFunctionAssistProvider::configure(const Parameters &parameters)
{
- m_startClass = startClass;
- m_function = function;
- m_snapshot = snapshot;
- m_openInNextSplit = openInNextSplit;
+ m_params = parameters;
return true;
}
@@ -202,7 +199,7 @@ bool VirtualFunctionAssistProvider::supportsEditor(const Core::Id &editorId) con
IAssistProcessor *VirtualFunctionAssistProvider::createProcessor() const
{
- return new VirtualFunctionsAssistProcessor(this);
+ return new VirtualFunctionsAssistProcessor(m_params);
}
enum VirtualType { Virtual, PureVirtual };
@@ -263,9 +260,6 @@ QList<Symbol *> FunctionHelper::overrides(Class *startClass, Function *function,
const Name *referenceName = function->name();
QTC_ASSERT(referenceName && referenceType.isValid(), return result);
- // Add itself
- result << function;
-
// Find overrides
CppEditor::Internal::CppClass cppClass = CppClass(startClass);
cppClass.lookupDerived(startClass, snapshot);
diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h
index c634b4ed44..b5ff42d846 100644
--- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h
+++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h
@@ -35,6 +35,8 @@
#include <cplusplus/CppDocument.h>
#include <cplusplus/Symbols.h>
+#include <QTextCursor>
+
namespace CppEditor {
namespace Internal {
@@ -43,22 +45,25 @@ class VirtualFunctionAssistProvider : public TextEditor::IAssistProvider
public:
VirtualFunctionAssistProvider();
- virtual bool configure(CPlusPlus::Class *startClass, CPlusPlus::Function *function,
- const CPlusPlus::Snapshot &snapshot, bool openInNextSplit);
- CPlusPlus::Class *startClass() const { return m_startClass; }
- CPlusPlus::Function *function() const { return m_function; }
- CPlusPlus::Snapshot snapshot() const { return m_snapshot; }
- bool openInNextSplit() const { return m_openInNextSplit; }
+ struct Parameters {
+ Parameters() : startClass(0), function(0), cursorPosition(-1), openInNextSplit(false) {}
+
+ CPlusPlus::Class *startClass;
+ CPlusPlus::Function *function;
+ CPlusPlus::Snapshot snapshot;
+ int cursorPosition;
+ bool openInNextSplit;
+ };
+
+ virtual bool configure(const Parameters &parameters);
+ Parameters params() const { return m_params; }
bool isAsynchronous() const;
bool supportsEditor(const Core::Id &editorId) const;
TextEditor::IAssistProcessor *createProcessor() const;
private:
- CPlusPlus::Class *m_startClass;
- CPlusPlus::Function *m_function;
- CPlusPlus::Snapshot m_snapshot;
- bool m_openInNextSplit;
+ Parameters m_params;
};
class FunctionHelper
diff --git a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h b/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h
index 7d09c9db2c..44cf50dcc9 100644
--- a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h
+++ b/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h
@@ -41,6 +41,7 @@ public:
VirtualFunctionProposalItem(const TextEditor::BaseTextEditorWidget::Link &link,
bool openInSplit = true);
void apply(TextEditor::BaseTextEditor * /* editor */, int /* basePosition */) const;
+ TextEditor::BaseTextEditorWidget::Link link() const { return m_link; } // Exposed for tests
private:
TextEditor::BaseTextEditorWidget::Link m_link;
diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
index 19f33336ae..2a2c754e63 100644
--- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
+++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
@@ -31,6 +31,7 @@
#include "cppeditorplugin.h"
#include "cppelementevaluator.h"
#include "cppvirtualfunctionassistprovider.h"
+#include "cppvirtualfunctionproposalitem.h"
#include <texteditor/codeassist/iassistproposal.h>
#include <texteditor/codeassist/iassistprocessor.h>
@@ -59,6 +60,35 @@ using namespace CppTools;
using namespace TextEditor;
using namespace Core;
+class OverrideItem {
+public:
+ OverrideItem() : line(0) {}
+ OverrideItem(const QString &text, int line = 0) : text(text), line(line) {}
+ bool isValid() { return line != 0; }
+
+ QString text;
+ int line;
+};
+typedef QList<OverrideItem> OverrideItemList;
+Q_DECLARE_METATYPE(OverrideItem)
+
+inline bool operator==(const OverrideItem &lhs, const OverrideItem &rhs)
+{
+ return lhs.text == rhs.text && lhs.line == rhs.line;
+}
+
+QT_BEGIN_NAMESPACE
+namespace QTest {
+template<> char *toString(const OverrideItem &data)
+{
+ QByteArray ba = "OverrideItem(";
+ ba += data.text.toLatin1() + ", " + QByteArray::number(data.line);
+ ba += ")";
+ return qstrdup(ba.data());
+}
+}
+QT_END_NAMESPACE
+
namespace {
/// A fake virtual functions assist provider that runs processor->perform() already in configure()
@@ -72,14 +102,13 @@ public:
// Invoke the processor already here to calculate the proposals. Return false in order to
// indicate that configure failed, so the actual code assist invocation leading to a pop-up
// will not happen.
- bool configure(CPlusPlus::Class *startClass, CPlusPlus::Function *function,
- const CPlusPlus::Snapshot &snapshot, bool openInNextSplit)
+ bool configure(const VirtualFunctionAssistProvider::Parameters &params)
{
- VirtualFunctionAssistProvider::configure(startClass, function, snapshot, openInNextSplit);
+ VirtualFunctionAssistProvider::configure(params);
IAssistProcessor *processor = createProcessor();
- IAssistInterface *assistInterface = m_editorWidget->createAssistInterface(FollowSymbol,
- ExplicitlyInvoked);
+ IAssistInterface *assistInterface
+ = m_editorWidget->createAssistInterface(FollowSymbol, ExplicitlyInvoked);
IAssistProposal *immediateProposal = processor->immediateProposal(assistInterface);
IAssistProposal *finalProposal = processor->perform(assistInterface);
@@ -89,27 +118,36 @@ public:
return false;
}
- static QStringList itemList(IAssistProposalModel *imodel)
+ static OverrideItemList itemList(IAssistProposalModel *imodel)
{
- QStringList immediateItems;
+ OverrideItemList result;
BasicProposalItemListModel *model = dynamic_cast<BasicProposalItemListModel *>(imodel);
if (!model)
- return immediateItems;
+ return result;
+
+ // Mimic relevant GenericProposalWidget::showProposal() calls
+ model->removeDuplicates();
+ model->reset();
if (model->isSortable(QString()))
model->sort(QString());
- model->removeDuplicates();
for (int i = 0, size = model->size(); i < size; ++i) {
+ VirtualFunctionProposalItem *item
+ = dynamic_cast<VirtualFunctionProposalItem *>(model->proposalItem(i));
+
const QString text = model->text(i);
- immediateItems.append(text);
+ const int line = item->link().targetLine;
+// Uncomment for updating/generating reference data:
+// qDebug("<< OverrideItem(QLatin1String(\"%s\"), %d)", qPrintable(text), line);
+ result << OverrideItem(text, line);
}
- return immediateItems;
+ return result;
}
public:
- QStringList m_immediateItems;
- QStringList m_finalItems;
+ OverrideItemList m_immediateItems;
+ OverrideItemList m_finalItems;
private:
CPPEditorWidget *m_editorWidget;
@@ -199,11 +237,11 @@ public:
};
TestCase(CppEditorAction action, const QByteArray &source,
- const QStringList &expectedVirtualFunctionImmediateProposal = QStringList(),
- const QStringList &expectedVirtualFunctionFinalProposal = QStringList());
+ const OverrideItemList &expectedVirtualFunctionImmediateProposal = OverrideItemList(),
+ const OverrideItemList &expectedVirtualFunctionFinalProposal = OverrideItemList());
TestCase(CppEditorAction action, const QList<TestDocumentPtr> theTestFiles,
- const QStringList &expectedVirtualSymbolsImmediateProposal = QStringList(),
- const QStringList &expectedVirtualSymbolsFinalProposal = QStringList());
+ const OverrideItemList &expectedVirtualFunctionImmediateProposal = OverrideItemList(),
+ const OverrideItemList &expectedVirtualFunctionFinalProposal = OverrideItemList());
~TestCase();
void run(bool expectedFail = false);
@@ -220,18 +258,18 @@ private:
private:
CppEditorAction m_action;
QList<TestDocumentPtr> m_testFiles;
- QStringList m_expectedVirtualSymbolsImmediateProposal; // for virtual functions
- QStringList m_expectedVirtualSymbolsFinalProposals; // for virtual functions
+ OverrideItemList m_expectedVirtualFunctionImmediateProposal;
+ OverrideItemList m_expectedVirtualFunctionFinalProposals;
};
/// Convenience function for creating a TestDocument.
/// See TestDocument.
TestCase::TestCase(CppEditorAction action, const QByteArray &source,
- const QStringList &expectedVirtualFunctionImmediateProposal,
- const QStringList &expectedVirtualFunctionFinalProposal)
+ const OverrideItemList &expectedVirtualFunctionImmediateProposal,
+ const OverrideItemList &expectedVirtualFunctionFinalProposal)
: m_action(action)
- , m_expectedVirtualSymbolsImmediateProposal(expectedVirtualFunctionImmediateProposal)
- , m_expectedVirtualSymbolsFinalProposals(expectedVirtualFunctionFinalProposal)
+ , m_expectedVirtualFunctionImmediateProposal(expectedVirtualFunctionImmediateProposal)
+ , m_expectedVirtualFunctionFinalProposals(expectedVirtualFunctionFinalProposal)
{
m_testFiles << TestDocument::create(source, QLatin1String("file.cpp"));
init();
@@ -242,12 +280,12 @@ TestCase::TestCase(CppEditorAction action, const QByteArray &source,
/// Exactly one test document must be provided that contains '$', the target position marker.
/// It can be the same document.
TestCase::TestCase(CppEditorAction action, const QList<TestDocumentPtr> theTestFiles,
- const QStringList &expectedVirtualSymbolsImmediateProposal,
- const QStringList &expectedVirtualSymbolsFinalProposal)
+ const OverrideItemList &expectedVirtualFunctionImmediateProposal,
+ const OverrideItemList &expectedVirtualFunctionFinalProposal)
: m_action(action)
, m_testFiles(theTestFiles)
- , m_expectedVirtualSymbolsImmediateProposal(expectedVirtualSymbolsImmediateProposal)
- , m_expectedVirtualSymbolsFinalProposals(expectedVirtualSymbolsFinalProposal)
+ , m_expectedVirtualFunctionImmediateProposal(expectedVirtualFunctionImmediateProposal)
+ , m_expectedVirtualFunctionFinalProposals(expectedVirtualFunctionFinalProposal)
{
init();
}
@@ -365,8 +403,8 @@ void TestCase::run(bool expectedFail)
// qDebug() << "Initial line:" << initialTestFile->editor->currentLine();
// qDebug() << "Initial column:" << initialTestFile->editor->currentColumn() - 1;
- QStringList immediateVirtualSymbolResults;
- QStringList finalVirtualSymbolResults;
+ OverrideItemList immediateVirtualSymbolResults;
+ OverrideItemList finalVirtualSymbolResults;
// Trigger the action
switch (m_action) {
@@ -416,8 +454,8 @@ void TestCase::run(bool expectedFail)
// qDebug() << immediateVirtualSymbolResults;
// qDebug() << finalVirtualSymbolResults;
- QCOMPARE(immediateVirtualSymbolResults, m_expectedVirtualSymbolsImmediateProposal);
- QCOMPARE(finalVirtualSymbolResults, m_expectedVirtualSymbolsFinalProposals);
+ QCOMPARE(immediateVirtualSymbolResults, m_expectedVirtualFunctionImmediateProposal);
+ QCOMPARE(finalVirtualSymbolResults, m_expectedVirtualFunctionFinalProposals);
}
} // anonymous namespace
@@ -1232,22 +1270,19 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_allOverri
"struct CD2 : C { void virt(); };\n"
"void CD2::virt() {}\n"
"\n"
- "int f(A *o)\n"
- "{\n"
- " o->$@virt();\n"
+ "int f(A *o) { o->$@virt(); }\n"
"}\n"
;
- const QStringList immediateResults = QStringList()
- << QLatin1String("A::virt")
- << QLatin1String("...searching overrides");
- const QStringList finalResults = QStringList()
- << QLatin1String("A::virt")
- << QLatin1String("A::virt") // TODO: Double entry
- << QLatin1String("B::virt")
- << QLatin1String("C::virt")
- << QLatin1String("CD1::virt")
- << QLatin1String("CD2::virt");
+ const OverrideItemList immediateResults = OverrideItemList()
+ << OverrideItem(QLatin1String("A::virt"), 2)
+ << OverrideItem(QLatin1String("...searching overrides"));
+ const OverrideItemList finalResults = OverrideItemList()
+ << OverrideItem(QLatin1String("A::virt"), 2)
+ << OverrideItem(QLatin1String("B::virt"), 5)
+ << OverrideItem(QLatin1String("C::virt"), 8)
+ << OverrideItem(QLatin1String("CD1::virt"), 11)
+ << OverrideItem(QLatin1String("CD2::virt"), 14);
TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults);
test.run();
@@ -1272,21 +1307,18 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_possibleO
"struct CD2 : C { void virt(); };\n"
"void CD2::virt() {}\n"
"\n"
- "int f(B *o)\n"
- "{\n"
- " o->$@virt();\n"
+ "int f(B *o) { o->$@virt(); }\n"
"}\n"
;
- const QStringList immediateResults = QStringList()
- << QLatin1String("B::virt")
- << QLatin1String("...searching overrides");
- const QStringList finalResults = QStringList()
- << QLatin1String("B::virt")
- << QLatin1String("B::virt") // Double entry
- << QLatin1String("C::virt")
- << QLatin1String("CD1::virt")
- << QLatin1String("CD2::virt");
+ const OverrideItemList immediateResults = OverrideItemList()
+ << OverrideItem(QLatin1String("B::virt"), 5)
+ << OverrideItem(QLatin1String("...searching overrides"));
+ const OverrideItemList finalResults = OverrideItemList()
+ << OverrideItem(QLatin1String("B::virt"), 5)
+ << OverrideItem(QLatin1String("C::virt"), 8)
+ << OverrideItem(QLatin1String("CD1::virt"), 11)
+ << OverrideItem(QLatin1String("CD2::virt"), 14);
TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults);
test.run();
@@ -1296,40 +1328,121 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_possibleO
void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_possibleOverrides2()
{
const QByteArray source =
- "struct A { virtual void f(); };\n"
- "void A::f() {}\n"
+ "struct A { virtual void virt(); };\n"
+ "void A::virt() {}\n"
+ "\n"
+ "struct B : public A { void virt(); };\n"
+ "void B::virt() {}\n"
+ "\n"
+ "struct C : public B { void g() { virt$@(); } }; \n"
+ "\n"
+ "struct D : public C { void virt(); };\n"
+ "void D::virt() {}\n"
+ ;
+
+ const OverrideItemList immediateResults = OverrideItemList()
+ << OverrideItem(QLatin1String("B::virt"), 5)
+ << OverrideItem(QLatin1String("...searching overrides"));
+ const OverrideItemList finalResults = OverrideItemList()
+ << OverrideItem(QLatin1String("B::virt"), 5)
+ << OverrideItem(QLatin1String("D::virt"), 10);
+
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults);
+ test.run();
+}
+
+/// Check: If no definition is found, fallback to the declaration.
+void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_fallbackToDeclaration()
+{
+ const QByteArray source =
+ "struct A { virtual void virt(); };\n"
+ "\n"
+ "int f(A *o) { o->$@virt(); }\n"
+ ;
+
+ const OverrideItemList immediateResults = OverrideItemList()
+ << OverrideItem(QLatin1String("A::virt"), 1)
+ << OverrideItem(QLatin1String("...searching overrides"));
+ const OverrideItemList finalResults = OverrideItemList()
+ << OverrideItem(QLatin1String("A::virt"), 1);
+
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults);
+ test.run();
+}
+
+/// Check: Ensure that the first entry in the final results is the same as the first in the
+/// immediate results.
+void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_itemOrder()
+{
+ const QByteArray source =
+ "struct C { virtual void virt() = 0; };\n"
+ "void C::virt() {}\n"
"\n"
- "struct B : public A { void f(); };\n"
- "void B::f() {}\n"
+ "struct B : C { void virt(); };\n"
+ "void B::virt() {}\n"
"\n"
- "struct C : public B { void g() { f$@(); } }; \n"
+ "struct A : B { void virt(); };\n"
+ "void A::virt() {}\n"
+ "\n"
+ "int f(C *o) { o->$@virt(); }\n"
+ ;
+
+ const OverrideItemList immediateResults = OverrideItemList()
+ << OverrideItem(QLatin1String("C::virt"), 2)
+ << OverrideItem(QLatin1String("...searching overrides"));
+ const OverrideItemList finalResults = OverrideItemList()
+ << OverrideItem(QLatin1String("C::virt"), 2)
+ << OverrideItem(QLatin1String("A::virt"), 8)
+ << OverrideItem(QLatin1String("B::virt"), 5);
+
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults);
+ test.run();
+}
+
+/// Check: Trigger on a.virt() if a is of type &A.
+void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_onDotMemberAccessOfReferenceTypes()
+{
+ const QByteArray source =
+ "struct A { virtual void virt() = 0; };\n"
+ "void A::virt() {}\n"
"\n"
- "struct D : public C { void f(); };\n"
- "void D::f() {}\n"
+ "void client(A &o) { o.$@virt(); }\n"
;
- const QStringList immediateResults = QStringList()
- << QLatin1String("B::f")
- << QLatin1String("...searching overrides");
- const QStringList finalResults = QStringList()
- << QLatin1String("B::f")
- << QLatin1String("B::f")
- << QLatin1String("D::f");
+ const OverrideItemList immediateResults = OverrideItemList()
+ << OverrideItem(QLatin1String("A::virt"), 2)
+ << OverrideItem(QLatin1String("...searching overrides"));
+ const OverrideItemList finalResults = OverrideItemList()
+ << OverrideItem(QLatin1String("A::virt"), 2);
TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults);
test.run();
}
+/// Check: Do not trigger on a.virt() if a is of type A.
+void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDotMemberAccessOfNonReferenceType()
+{
+ const QByteArray source =
+ "struct A { virtual void virt(); };\n"
+ "void A::$virt() {}\n"
+ "\n"
+ "void client(A o) { o.@virt(); }\n"
+ ;
+
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
+ test.run();
+}
+
/// Check: Do not trigger on qualified function calls.
void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnQualified()
{
const QByteArray source =
- "struct A { virtual void f(); };\n"
- "void A::$f() {}\n"
+ "struct A { virtual void virt(); };\n"
+ "void A::$virt() {}\n"
"\n"
"struct B : public A {\n"
- " void f();\n"
- " void g() { A::@f(); }\n"
+ " void virt();\n"
+ " void g() { A::@virt(); }\n"
"};\n"
;
@@ -1341,11 +1454,11 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnQual
void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDeclaration()
{
const QByteArray source =
- "struct A { virtual void f(); };\n"
- "void A::f() {}\n"
+ "struct A { virtual void virt(); };\n"
+ "void A::virt() {}\n"
"\n"
- "struct B : public A { void f@(); };\n"
- "void B::$f() {}\n"
+ "struct B : public A { void virt@(); };\n"
+ "void B::$virt() {}\n"
;
TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
@@ -1356,11 +1469,11 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDecl
void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDefinition()
{
const QByteArray source =
- "struct A { virtual void f(); };\n"
- "void A::f() {}\n"
+ "struct A { virtual void virt(); };\n"
+ "void A::virt() {}\n"
"\n"
- "struct B : public A { void $f(); };\n"
- "void B::@f() {}\n"
+ "struct B : public A { void $virt(); };\n"
+ "void B::@virt() {}\n"
;
TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
@@ -1370,13 +1483,13 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDefi
void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnNonPointerNonReference()
{
const QByteArray source =
- "struct A { virtual void f(); };\n"
- "void A::f() {}\n"
+ "struct A { virtual void virt(); };\n"
+ "void A::virt() {}\n"
"\n"
- "struct B : public A { void f(); };\n"
- "void B::$f() {}\n"
+ "struct B : public A { void virt(); };\n"
+ "void B::$virt() {}\n"
"\n"
- "void client(B b) { b.@f(); }\n"
+ "void client(B b) { b.@virt(); }\n"
;
TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp
index ff69f7746a..b720645032 100644
--- a/src/plugins/cpptools/cpptoolsplugin.cpp
+++ b/src/plugins/cpptools/cpptoolsplugin.cpp
@@ -51,11 +51,9 @@
#include <coreplugin/vcsmanager.h>
#include <cppeditor/cppeditorconstants.h>
+#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
-#ifdef Q_OS_WIN
-#include <utils/winutils.h>
-#endif
#include <QtPlugin>
#include <QFileInfo>
@@ -352,11 +350,7 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader)
foreach (const QString &candidateDir, candidateDirs) {
foreach (const QString &candidateFileName, candidateFileNames) {
const QString candidateFilePath = candidateDir + QLatin1Char('/') + candidateFileName;
-#ifdef Q_OS_WIN
- const QString normalized = Utils::normalizePathName(candidateFilePath);
-#else
- const QString normalized = candidateFilePath;
-#endif
+ const QString normalized = Utils::FileUtils::normalizePathName(candidateFilePath);
const QFileInfo candidateFi(normalized);
if (candidateFi.isFile()) {
m_headerSourceMapping[fi.absoluteFilePath()] = candidateFi.absoluteFilePath();
diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp
index 52331b4e18..5376b4c914 100644
--- a/src/plugins/debugger/cdb/cdbengine.cpp
+++ b/src/plugins/debugger/cdb/cdbengine.cpp
@@ -2879,11 +2879,7 @@ CdbEngine::NormalizedSourceFileName CdbEngine::sourceMapNormalizeFileNameFromDeb
const QString fileName = cdbSourcePathMapping(QDir::toNativeSeparators(f), m_sourcePathMappings,
DebuggerToSource);
// Up/lower case normalization according to Windows.
-#ifdef Q_OS_WIN
- QString normalized = Utils::normalizePathName(fileName);
-#else
- QString normalized = fileName;
-#endif
+ const QString normalized = Utils::FileUtils::normalizePathName(fileName);
if (debugSourceMapping)
qDebug(" sourceMapNormalizeFileNameFromDebugger %s->%s", qPrintable(fileName), qPrintable(normalized));
// Check if it really exists, that is normalize worked and QFileInfo confirms it.
diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro
index ce31216535..7798cf0bfe 100644
--- a/src/plugins/debugger/debugger.pro
+++ b/src/plugins/debugger/debugger.pro
@@ -24,9 +24,13 @@ HEADERS += \
debuggercore.h \
debuggerconstants.h \
debuggerinternalconstants.h \
+ debuggeritem.h \
+ debuggeritemmanager.h \
+ debuggeritemmodel.h \
debuggerdialogs.h \
debuggerengine.h \
debuggermainwindow.h \
+ debuggeroptionspage.h \
debuggerplugin.h \
debuggerprotocol.h \
debuggerrunconfigurationaspect.h \
@@ -80,12 +84,16 @@ SOURCES += \
debuggeractions.cpp \
debuggerdialogs.cpp \
debuggerengine.cpp \
+ debuggeritem.cpp \
+ debuggeritemmanager.cpp \
+ debuggeritemmodel.cpp \
debuggermainwindow.cpp \
debuggerplugin.cpp \
debuggerprotocol.cpp \
debuggerrunconfigurationaspect.cpp \
debuggerrunner.cpp \
debuggerstreamops.cpp \
+ debuggeroptionspage.cpp \
debuggerkitconfigwidget.cpp \
debuggerkitinformation.cpp \
disassembleragent.cpp \
diff --git a/src/plugins/debugger/debugger.qbs b/src/plugins/debugger/debugger.qbs
index 9032e84660..709dc128c3 100644
--- a/src/plugins/debugger/debugger.qbs
+++ b/src/plugins/debugger/debugger.qbs
@@ -40,9 +40,13 @@ QtcPlugin {
"debuggerdialogs.cpp", "debuggerdialogs.h",
"debuggerengine.cpp", "debuggerengine.h",
"debuggerinternalconstants.h",
+ "debuggeritem.cpp", "debuggeritem.h",
+ "debuggeritemmanager.cpp", "debuggeritemmanager.h",
+ "debuggeritemmodel.cpp", "debuggeritemmodel.h",
"debuggerkitconfigwidget.cpp", "debuggerkitconfigwidget.h",
"debuggerkitinformation.cpp", "debuggerkitinformation.h",
"debuggermainwindow.cpp", "debuggermainwindow.h",
+ "debuggeroptionspage.cpp", "debuggeroptionspage.h",
"debuggerplugin.cpp", "debuggerplugin.h",
"debuggerprotocol.cpp", "debuggerprotocol.h",
"debuggerruncontrolfactory.h",
diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp
index 13f292de99..b1db49211d 100644
--- a/src/plugins/debugger/debuggerdialogs.cpp
+++ b/src/plugins/debugger/debuggerdialogs.cpp
@@ -248,7 +248,7 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent)
d->localExecutablePathChooser = new PathChooser(this);
d->localExecutablePathChooser->setExpectedKind(PathChooser::File);
d->localExecutablePathChooser->setPromptDialogTitle(tr("Select Executable"));
- d->localExecutablePathChooser->lineEdit()->setHistoryCompleter(QLatin1String("LocalExecutable"));
+ d->localExecutablePathChooser->setHistoryCompleter(QLatin1String("LocalExecutable"));
d->arguments = new FancyLineEdit(this);
d->arguments->setHistoryCompleter(QLatin1String("CommandlineArguments"));
@@ -256,7 +256,7 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent)
d->workingDirectory = new PathChooser(this);
d->workingDirectory->setExpectedKind(PathChooser::ExistingDirectory);
d->workingDirectory->setPromptDialogTitle(tr("Select Working Directory"));
- d->workingDirectory->lineEdit()->setHistoryCompleter(QLatin1String("WorkingDirectory"));
+ d->workingDirectory->setHistoryCompleter(QLatin1String("WorkingDirectory"));
d->runInTerminalCheckBox = new QCheckBox(this);
@@ -633,7 +633,7 @@ AddressDialog::AddressDialog(QWidget *parent) :
setWindowTitle(tr("Select Start Address"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
QHBoxLayout *hLayout = new QHBoxLayout;
- hLayout->addWidget(new QLabel(tr("Enter an address: ")));
+ hLayout->addWidget(new QLabel(tr("Enter an address:") + QLatin1Char(' ')));
hLayout->addWidget(m_lineEdit);
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->addLayout(hLayout);
diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
index 71b196a710..2bbea66f5b 100644
--- a/src/plugins/debugger/debuggerengine.cpp
+++ b/src/plugins/debugger/debuggerengine.cpp
@@ -1676,9 +1676,9 @@ QString DebuggerEngine::msgInterrupted()
void DebuggerEngine::showStoppedBySignalMessageBox(QString meaning, QString name)
{
if (name.isEmpty())
- name = tr(" <Unknown> ", "name");
+ name = QLatin1Char(' ') + tr("<Unknown>", "name") + QLatin1Char(' ');
if (meaning.isEmpty())
- meaning = tr(" <Unknown> ", "meaning");
+ meaning = QLatin1Char(' ') + tr("<Unknown>", "meaning") + QLatin1Char(' ');
const QString msg = tr("<p>The inferior stopped because it received a "
"signal from the Operating System.<p>"
"<table><tr><td>Signal name : </td><td>%1</td></tr>"
diff --git a/src/plugins/debugger/debuggeritem.cpp b/src/plugins/debugger/debuggeritem.cpp
new file mode 100644
index 0000000000..0768d2ecdd
--- /dev/null
+++ b/src/plugins/debugger/debuggeritem.cpp
@@ -0,0 +1,352 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "debuggerkitinformation.h"
+#include "debuggerkitconfigwidget.h"
+#include "debuggeroptionspage.h"
+
+#include <projectexplorer/abi.h>
+#include <utils/fileutils.h>
+
+#include <QProcess>
+#include <QUuid>
+
+using namespace Debugger::Internal;
+using namespace ProjectExplorer;
+using namespace Utils;
+
+static const char DEBUGGER_INFORMATION_COMMAND[] = "Binary";
+static const char DEBUGGER_INFORMATION_DISPLAYNAME[] = "DisplayName";
+static const char DEBUGGER_INFORMATION_ID[] = "Id";
+static const char DEBUGGER_INFORMATION_ENGINETYPE[] = "EngineType";
+static const char DEBUGGER_INFORMATION_AUTODETECTED[] = "AutoDetected";
+static const char DEBUGGER_INFORMATION_ABIS[] = "Abis";
+
+namespace Debugger {
+
+// --------------------------------------------------------------------------
+// DebuggerItem
+// --------------------------------------------------------------------------
+
+DebuggerItem::DebuggerItem()
+{
+ m_id = QUuid::createUuid().toString();
+ m_engineType = NoEngineType;
+ m_isAutoDetected = false;
+}
+
+DebuggerItem::DebuggerItem(const QVariant &id)
+{
+ m_id = id;
+ m_engineType = NoEngineType;
+ m_isAutoDetected = false;
+}
+
+DebuggerItem::DebuggerItem(const QVariantMap &data)
+{
+ m_command = FileName::fromUserInput(data.value(QLatin1String(DEBUGGER_INFORMATION_COMMAND)).toString());
+ m_id = data.value(QLatin1String(DEBUGGER_INFORMATION_ID)).toString();
+ m_displayName = data.value(QLatin1String(DEBUGGER_INFORMATION_DISPLAYNAME)).toString();
+ m_isAutoDetected = data.value(QLatin1String(DEBUGGER_INFORMATION_AUTODETECTED), false).toBool();
+ m_engineType = DebuggerEngineType(data.value(QLatin1String(DEBUGGER_INFORMATION_ENGINETYPE),
+ static_cast<int>(NoEngineType)).toInt());
+
+ foreach (const QString &a, data.value(QLatin1String(DEBUGGER_INFORMATION_ABIS)).toStringList()) {
+ Abi abi(a);
+ if (abi.isValid())
+ m_abis.append(abi);
+ }
+}
+
+void DebuggerItem::reinitializeFromFile()
+{
+ QProcess proc;
+ proc.start(m_command.toString(), QStringList() << QLatin1String("--version"));
+ proc.waitForStarted();
+ proc.waitForFinished();
+ QByteArray ba = proc.readAll();
+ if (ba.contains("gdb")) {
+ m_engineType = GdbEngineType;
+ const char needle[] = "This GDB was configured as \"";
+ // E.g. "--host=i686-pc-linux-gnu --target=arm-unknown-nto-qnx6.5.0".
+ // or "i686-linux-gnu"
+ int pos1 = ba.indexOf(needle);
+ if (pos1 != -1) {
+ pos1 += int(sizeof(needle));
+ int pos2 = ba.indexOf('"', pos1 + 1);
+ QByteArray target = ba.mid(pos1, pos2 - pos1);
+ int pos3 = target.indexOf("--target=");
+ if (pos3 >= 0)
+ target = target.mid(pos3 + 9);
+ m_abis.append(Abi::abiFromTargetTriplet(QString::fromLatin1(target)));
+ } else {
+ // Fallback.
+ m_abis = Abi::abisOfBinary(m_command); // FIXME: Wrong.
+ }
+ return;
+ }
+ if (ba.contains("lldb") || ba.startsWith("LLDB")) {
+ m_engineType = LldbEngineType;
+ m_abis = Abi::abisOfBinary(m_command);
+ return;
+ }
+ if (ba.startsWith("Python")) {
+ m_engineType = PdbEngineType;
+ return;
+ }
+ m_engineType = NoEngineType;
+}
+
+QString DebuggerItem::engineTypeName() const
+{
+ switch (m_engineType) {
+ case Debugger::NoEngineType:
+ return DebuggerOptionsPage::tr("Not recognized");
+ case Debugger::GdbEngineType:
+ return QLatin1String("GDB");
+ case Debugger::CdbEngineType:
+ return QLatin1String("CDB");
+ case Debugger::LldbEngineType:
+ return QLatin1String("LLDB");
+ default:
+ return QString();
+ }
+}
+
+QStringList DebuggerItem::abiNames() const
+{
+ QStringList list;
+ foreach (const Abi &abi, m_abis)
+ list.append(abi.toString());
+ return list;
+}
+
+bool DebuggerItem::operator==(const DebuggerItem &other) const
+{
+ return m_id == other.m_id
+ && m_displayName == other.m_displayName
+ && m_isAutoDetected == other.m_isAutoDetected
+ && m_command == other.m_command;
+}
+
+QVariantMap DebuggerItem::toMap() const
+{
+ QVariantMap data;
+ data.insert(QLatin1String(DEBUGGER_INFORMATION_DISPLAYNAME), m_displayName);
+ data.insert(QLatin1String(DEBUGGER_INFORMATION_ID), m_id);
+ data.insert(QLatin1String(DEBUGGER_INFORMATION_COMMAND), m_command.toUserOutput());
+ data.insert(QLatin1String(DEBUGGER_INFORMATION_ENGINETYPE), int(m_engineType));
+ data.insert(QLatin1String(DEBUGGER_INFORMATION_AUTODETECTED), m_isAutoDetected);
+ data.insert(QLatin1String(DEBUGGER_INFORMATION_ABIS), abiNames());
+ return data;
+}
+
+void DebuggerItem::setDisplayName(const QString &displayName)
+{
+ m_displayName = displayName;
+}
+
+void DebuggerItem::setEngineType(const DebuggerEngineType &engineType)
+{
+ m_engineType = engineType;
+}
+
+void DebuggerItem::setCommand(const Utils::FileName &command)
+{
+ m_command = command;
+}
+
+void DebuggerItem::setAutoDetected(bool isAutoDetected)
+{
+ m_isAutoDetected = isAutoDetected;
+}
+
+void DebuggerItem::setAbis(const QList<ProjectExplorer::Abi> &abis)
+{
+ m_abis = abis;
+}
+
+void DebuggerItem::setAbi(const Abi &abi)
+{
+ m_abis.clear();
+ m_abis.append(abi);
+}
+
+static DebuggerItem::MatchLevel matchSingle(const Abi &debuggerAbi, const Abi &targetAbi)
+{
+ if (debuggerAbi.architecture() != Abi::UnknownArchitecture
+ && debuggerAbi.architecture() != targetAbi.architecture())
+ return DebuggerItem::DoesNotMatch;
+
+ if (debuggerAbi.os() != Abi::UnknownOS
+ && debuggerAbi.os() != targetAbi.os())
+ return DebuggerItem::DoesNotMatch;
+
+ if (debuggerAbi.binaryFormat() != Abi::UnknownFormat
+ && debuggerAbi.binaryFormat() != targetAbi.binaryFormat())
+ return DebuggerItem::DoesNotMatch;
+
+ if (debuggerAbi.os() == Abi::WindowsOS) {
+ if (debuggerAbi.osFlavor() == Abi::WindowsMSysFlavor && targetAbi.osFlavor() != Abi::WindowsMSysFlavor)
+ return DebuggerItem::DoesNotMatch;
+ if (debuggerAbi.osFlavor() != Abi::WindowsMSysFlavor && targetAbi.osFlavor() == Abi::WindowsMSysFlavor)
+ return DebuggerItem::DoesNotMatch;
+ }
+
+ if (debuggerAbi.wordWidth() == 64 && targetAbi.wordWidth() == 32)
+ return DebuggerItem::MatchesSomewhat;
+ if (debuggerAbi.wordWidth() != 0 && debuggerAbi.wordWidth() != targetAbi.wordWidth())
+ return DebuggerItem::DoesNotMatch;
+
+ return DebuggerItem::MatchesPerfectly;
+}
+
+DebuggerItem::MatchLevel DebuggerItem::matchTarget(const Abi &targetAbi) const
+{
+ MatchLevel bestMatch = DoesNotMatch;
+ foreach (const Abi &debuggerAbi, m_abis) {
+ MatchLevel currentMatch = matchSingle(debuggerAbi, targetAbi);
+ if (currentMatch > bestMatch)
+ bestMatch = currentMatch;
+ }
+ return bestMatch;
+}
+
+bool Debugger::DebuggerItem::isValid() const
+{
+ return !m_id.isNull();
+}
+
+} // namespace Debugger;
+
+#ifdef WITH_TESTS
+
+# include <QTest>
+# include "debuggerplugin.h"
+
+void Debugger::DebuggerPlugin::testDebuggerMatching_data()
+{
+ QTest::addColumn<QStringList>("debugger");
+ QTest::addColumn<QString>("target");
+ QTest::addColumn<int>("result");
+
+ QTest::newRow("Invalid data")
+ << QStringList()
+ << QString()
+ << int(DebuggerItem::DoesNotMatch);
+ QTest::newRow("Invalid debugger")
+ << QStringList()
+ << QString::fromLatin1("x86-linux-generic-elf-32bit")
+ << int(DebuggerItem::DoesNotMatch);
+ QTest::newRow("Invalid target")
+ << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
+ << QString()
+ << int(DebuggerItem::DoesNotMatch);
+
+ QTest::newRow("Fuzzy match 1")
+ << (QStringList() << QLatin1String("unknown-unknown-unknown-unknown-0bit"))
+ << QString::fromLatin1("x86-linux-generic-elf-32bit")
+ << int(DebuggerItem::MatchesPerfectly); // Is this the expected behavior?
+ QTest::newRow("Fuzzy match 2")
+ << (QStringList() << QLatin1String("unknown-unknown-unknown-unknown-0bit"))
+ << QString::fromLatin1("arm-windows-msys-pe-64bit")
+ << int(DebuggerItem::MatchesPerfectly); // Is this the expected behavior?
+
+ QTest::newRow("Architecture mismatch")
+ << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
+ << QString::fromLatin1("arm-linux-generic-elf-32bit")
+ << int(DebuggerItem::DoesNotMatch);
+ QTest::newRow("OS mismatch")
+ << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
+ << QString::fromLatin1("x86-macosx-generic-elf-32bit")
+ << int(DebuggerItem::DoesNotMatch);
+ QTest::newRow("Format mismatch")
+ << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
+ << QString::fromLatin1("x86-linux-generic-pe-32bit")
+ << int(DebuggerItem::DoesNotMatch);
+
+ QTest::newRow("Linux perfect match")
+ << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
+ << QString::fromLatin1("x86-linux-generic-elf-32bit")
+ << int(DebuggerItem::MatchesPerfectly);
+ QTest::newRow("Linux match")
+ << (QStringList() << QLatin1String("x86-linux-generic-elf-64bit"))
+ << QString::fromLatin1("x86-linux-generic-elf-32bit")
+ << int(DebuggerItem::MatchesSomewhat);
+
+ QTest::newRow("Windows perfect match 1")
+ << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
+ << QString::fromLatin1("x86-windows-msvc2013-pe-64bit")
+ << int(DebuggerItem::MatchesPerfectly);
+ QTest::newRow("Windows perfect match 2")
+ << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
+ << QString::fromLatin1("x86-windows-msvc2012-pe-64bit")
+ << int(DebuggerItem::MatchesPerfectly);
+ QTest::newRow("Windows match 1")
+ << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
+ << QString::fromLatin1("x86-windows-msvc2013-pe-32bit")
+ << int(DebuggerItem::MatchesSomewhat);
+ QTest::newRow("Windows match 2")
+ << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
+ << QString::fromLatin1("x86-windows-msvc2012-pe-32bit")
+ << int(DebuggerItem::MatchesSomewhat);
+ QTest::newRow("Windows mismatch on word size")
+ << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-32bit"))
+ << QString::fromLatin1("x86-windows-msvc2013-pe-64bit")
+ << int(DebuggerItem::DoesNotMatch);
+ QTest::newRow("Windows mismatch on osflavor 1")
+ << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-32bit"))
+ << QString::fromLatin1("x86-windows-msys-pe-64bit")
+ << int(DebuggerItem::DoesNotMatch);
+ QTest::newRow("Windows mismatch on osflavor 2")
+ << (QStringList() << QLatin1String("x86-windows-msys-pe-32bit"))
+ << QString::fromLatin1("x86-windows-msvc2010-pe-64bit")
+ << int(DebuggerItem::DoesNotMatch);
+}
+
+void Debugger::DebuggerPlugin::testDebuggerMatching()
+{
+ QFETCH(QStringList, debugger);
+ QFETCH(QString, target);
+ QFETCH(int, result);
+
+ DebuggerItem::MatchLevel expectedLevel = static_cast<DebuggerItem::MatchLevel>(result);
+
+ QList<Abi> debuggerAbis;
+ foreach (const QString &abi, debugger)
+ debuggerAbis << Abi(abi);
+
+ DebuggerItem item;
+ item.setAbis(debuggerAbis);
+
+ DebuggerItem::MatchLevel level = item.matchTarget(Abi(target));
+
+ QCOMPARE(expectedLevel, level);
+}
+#endif
diff --git a/src/plugins/debugger/debuggeritem.h b/src/plugins/debugger/debuggeritem.h
new file mode 100644
index 0000000000..14219471e9
--- /dev/null
+++ b/src/plugins/debugger/debuggeritem.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef DEBUGGER_DEBUGGERITEM_H
+#define DEBUGGER_DEBUGGERITEM_H
+
+#include "debugger_global.h"
+#include "debuggerconstants.h"
+
+#include <projectexplorer/abi.h>
+
+#include <utils/fileutils.h>
+
+#include <QList>
+#include <QVariant>
+
+namespace Debugger {
+
+namespace Internal { class DebuggerItemModel; }
+
+// -----------------------------------------------------------------------
+// DebuggerItem
+// -----------------------------------------------------------------------
+
+class DEBUGGER_EXPORT DebuggerItem
+{
+public:
+ DebuggerItem();
+ DebuggerItem(const QVariantMap &data);
+
+ bool canClone() const { return true; }
+ bool isValid() const;
+ QString engineTypeName() const;
+
+ QVariantMap toMap() const;
+ void reinitializeFromFile();
+
+ QVariant id() const { return m_id; }
+
+ QString displayName() const { return m_displayName; }
+ void setDisplayName(const QString &displayName);
+
+ DebuggerEngineType engineType() const { return m_engineType; }
+ void setEngineType(const DebuggerEngineType &engineType);
+
+ Utils::FileName command() const { return m_command; }
+ void setCommand(const Utils::FileName &command);
+
+ bool isAutoDetected() const { return m_isAutoDetected; }
+ void setAutoDetected(bool isAutoDetected);
+
+ QList<ProjectExplorer::Abi> abis() const { return m_abis; }
+ void setAbis(const QList<ProjectExplorer::Abi> &abis);
+ void setAbi(const ProjectExplorer::Abi &abi);
+
+ enum MatchLevel { DoesNotMatch, MatchesSomewhat, MatchesPerfectly };
+ MatchLevel matchTarget(const ProjectExplorer::Abi &targetAbi) const;
+
+ QStringList abiNames() const;
+
+ bool operator==(const DebuggerItem &other) const;
+
+private:
+ DebuggerItem(const QVariant &id);
+
+ QVariant m_id;
+ QString m_displayName;
+ DebuggerEngineType m_engineType;
+ Utils::FileName m_command;
+ bool m_isAutoDetected;
+ QList<ProjectExplorer::Abi> m_abis;
+
+ friend class Internal::DebuggerItemModel;
+};
+
+} // namespace Debugger
+
+#endif // DEBUGGER_DEBUGGERITEM_H
diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp
new file mode 100644
index 0000000000..fcca5d8eac
--- /dev/null
+++ b/src/plugins/debugger/debuggeritemmanager.cpp
@@ -0,0 +1,403 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "debuggeritemmanager.h"
+
+#include "debuggeritemmodel.h"
+#include "debuggerkitinformation.h"
+
+#include <coreplugin/icore.h>
+
+#include <utils/environment.h>
+#include <utils/fileutils.h>
+#include <utils/persistentsettings.h>
+#include <utils/qtcassert.h>
+
+#include <QDebug>
+#include <QDir>
+#include <QFileInfo>
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace Debugger {
+
+static const char DEBUGGER_COUNT_KEY[] = "DebuggerItem.Count";
+static const char DEBUGGER_DATA_KEY[] = "DebuggerItem.";
+static const char DEBUGGER_LEGACY_FILENAME[] = "/qtcreator/profiles.xml";
+static const char DEBUGGER_FILE_VERSION_KEY[] = "Version";
+static const char DEBUGGER_FILENAME[] = "/qtcreator/debuggers.xml";
+
+// --------------------------------------------------------------------------
+// DebuggerItemManager
+// --------------------------------------------------------------------------
+
+static DebuggerItemManager *m_instance = 0;
+
+static FileName userSettingsFileName()
+{
+ QFileInfo settingsLocation(Core::ICore::settings()->fileName());
+ return FileName::fromString(settingsLocation.absolutePath() + QLatin1String(DEBUGGER_FILENAME));
+}
+
+static void readDebuggers(const FileName &fileName, bool isSystem)
+{
+ PersistentSettingsReader reader;
+ if (!reader.load(fileName))
+ return;
+ QVariantMap data = reader.restoreValues();
+
+ // Check version
+ int version = data.value(QLatin1String(DEBUGGER_FILE_VERSION_KEY), 0).toInt();
+ if (version < 1)
+ return;
+
+ int count = data.value(QLatin1String(DEBUGGER_COUNT_KEY), 0).toInt();
+ for (int i = 0; i < count; ++i) {
+ const QString key = QString::fromLatin1(DEBUGGER_DATA_KEY) + QString::number(i);
+ if (!data.contains(key))
+ continue;
+ const QVariantMap dbMap = data.value(key).toMap();
+ DebuggerItem item(dbMap);
+ if (isSystem) {
+ item.setAutoDetected(true);
+ // SDK debuggers are always considered to be up-to-date, so no need to recheck them.
+ } else {
+ // User settings.
+ if (item.isAutoDetected() && (!item.isValid() || item.engineType() == NoEngineType)) {
+ qWarning() << QString::fromLatin1("DebuggerItem \"%1\" (%2) dropped since it is not valid")
+ .arg(item.command().toString()).arg(item.id().toString());
+ continue;
+ }
+ }
+ DebuggerItemManager::registerDebugger(item);
+ }
+}
+
+QList<DebuggerItem> DebuggerItemManager::m_debuggers;
+PersistentSettingsWriter * DebuggerItemManager::m_writer = 0;
+
+DebuggerItemManager::DebuggerItemManager(QObject *parent)
+ : QObject(parent)
+{
+ m_instance = this;
+ m_writer = new PersistentSettingsWriter(userSettingsFileName(), QLatin1String("QtCreatorDebugger"));
+ connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()),
+ this, SLOT(saveDebuggers()));
+}
+
+QObject *DebuggerItemManager::instance()
+{
+ return m_instance;
+}
+
+DebuggerItemManager::~DebuggerItemManager()
+{
+ disconnect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()),
+ this, SLOT(saveDebuggers()));
+ delete m_writer;
+}
+
+QList<DebuggerItem> DebuggerItemManager::debuggers()
+{
+ return m_debuggers;
+}
+
+void DebuggerItemManager::autoDetectCdbDebuggers()
+{
+ QList<FileName> cdbs;
+
+ QStringList programDirs;
+ programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles")));
+ programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles(x86)")));
+ programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramW6432")));
+
+ foreach (const QString &dirName, programDirs) {
+ if (dirName.isEmpty())
+ continue;
+ QDir dir(dirName);
+ // Windows SDK's starting from version 8 live in
+ // "ProgramDir\Windows Kits\<version>"
+ const QString windowsKitsFolderName = QLatin1String("Windows Kits");
+ if (dir.exists(windowsKitsFolderName)) {
+ QDir windowKitsFolder = dir;
+ if (windowKitsFolder.cd(windowsKitsFolderName)) {
+ // Check in reverse order (latest first)
+ const QFileInfoList kitFolders =
+ windowKitsFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot,
+ QDir::Time | QDir::Reversed);
+ foreach (const QFileInfo &kitFolderFi, kitFolders) {
+ const QString path = kitFolderFi.absoluteFilePath();
+ const QFileInfo cdb32(path + QLatin1String("/Debuggers/x86/cdb.exe"));
+ if (cdb32.isExecutable())
+ cdbs.append(FileName::fromString(cdb32.absoluteFilePath()));
+ const QFileInfo cdb64(path + QLatin1String("/Debuggers/x64/cdb.exe"));
+ if (cdb64.isExecutable())
+ cdbs.append(FileName::fromString(cdb64.absoluteFilePath()));
+ }
+ }
+ }
+
+ // Pre Windows SDK 8: Check 'Debugging Tools for Windows'
+ foreach (const QFileInfo &fi, dir.entryInfoList(QStringList(QLatin1String("Debugging Tools for Windows*")),
+ QDir::Dirs | QDir::NoDotAndDotDot)) {
+ FileName filePath(fi);
+ filePath.appendPath(QLatin1String("cdb.exe"));
+ if (!cdbs.contains(filePath))
+ cdbs.append(filePath);
+ }
+ }
+
+ foreach (const FileName &cdb, cdbs) {
+ if (findByCommand(cdb))
+ continue;
+ DebuggerItem item;
+ item.setAutoDetected(true);
+ item.setAbis(Abi::abisOfBinary(cdb));
+ item.setCommand(cdb);
+ item.setEngineType(CdbEngineType);
+ item.setDisplayName(uniqueDisplayName(tr("Auto-detected CDB at %1").arg(cdb.toUserOutput())));
+ addDebugger(item);
+ }
+}
+
+void DebuggerItemManager::autoDetectGdbOrLldbDebuggers()
+{
+ QStringList filters;
+ filters.append(QLatin1String("gdb-i686-pc-mingw32"));
+ filters.append(QLatin1String("gdb"));
+ filters.append(QLatin1String("lldb"));
+ filters.append(QLatin1String("lldb-*"));
+
+// DebuggerItem result;
+// result.setAutoDetected(true);
+// result.setDisplayName(tr("Auto-detected for Tool Chain %1").arg(tc->displayName()));
+ /*
+ // Check suggestions from the SDK.
+ Environment env = Environment::systemEnvironment();
+ if (tc) {
+ tc->addToEnvironment(env); // Find MinGW gdb in toolchain environment.
+ QString path = tc->suggestedDebugger().toString();
+ if (!path.isEmpty()) {
+ const QFileInfo fi(path);
+ if (!fi.isAbsolute())
+ path = env.searchInPath(path);
+ result.command = FileName::fromString(path);
+ result.engineType = engineTypeFromBinary(path);
+ return maybeAddDebugger(result, false);
+ }
+ }
+ */
+
+ QFileInfoList suspects;
+
+ QStringList path = Environment::systemEnvironment().path();
+ foreach (const QString &base, path) {
+ QDir dir(base);
+ dir.setNameFilters(filters);
+ suspects += dir.entryInfoList();
+ }
+
+ foreach (const QFileInfo &fi, suspects) {
+ if (fi.exists()) {
+ FileName command = FileName::fromString(fi.absoluteFilePath());
+ if (findByCommand(command))
+ continue;
+ DebuggerItem item;
+ item.setCommand(command);
+ item.reinitializeFromFile();
+ //: %1: Debugger engine type (GDB, LLDB, CDB...), %2: Path
+ item.setDisplayName(tr("System %1 at %2")
+ .arg(item.engineTypeName()).arg(QDir::toNativeSeparators(fi.absoluteFilePath())));
+ item.setAutoDetected(true);
+ addDebugger(item);
+ }
+ }
+}
+
+void DebuggerItemManager::readLegacyDebuggers()
+{
+ QFileInfo settingsLocation(Core::ICore::settings()->fileName());
+ FileName legacyKits = FileName::fromString(settingsLocation.absolutePath() + QLatin1String(DEBUGGER_LEGACY_FILENAME));
+
+ PersistentSettingsReader reader;
+ if (!reader.load(legacyKits))
+ return;
+
+ foreach (const QVariant &v, reader.restoreValues()) {
+ QVariantMap data1 = v.toMap();
+ QString kitName = data1.value(QLatin1String("PE.Profile.Name")).toString();
+ QVariantMap data2 = data1.value(QLatin1String("PE.Profile.Data")).toMap();
+ QVariant v3 = data2.value(DebuggerKitInformation::id().toString());
+ QString fn;
+ if (v3.type() == QVariant::String)
+ fn = v3.toString();
+ else
+ fn = v3.toMap().value(QLatin1String("Binary")).toString();
+ if (fn.isEmpty())
+ continue;
+ if (fn.startsWith(QLatin1Char('{')))
+ continue;
+ if (fn == QLatin1String("auto"))
+ continue;
+ FileName command = FileName::fromUserInput(fn);
+ if (findByCommand(command))
+ continue;
+ DebuggerItem item;
+ item.setCommand(command);
+ item.setAutoDetected(true);
+ item.reinitializeFromFile();
+ item.setDisplayName(tr("Extracted from Kit %1").arg(kitName));
+ addDebugger(item);
+ }
+}
+
+const DebuggerItem *DebuggerItemManager::findByCommand(const FileName &command)
+{
+ foreach (const DebuggerItem &item, m_debuggers)
+ if (item.command() == command)
+ return &item;
+
+ return 0;
+}
+
+const DebuggerItem *DebuggerItemManager::findById(const QVariant &id)
+{
+ foreach (const DebuggerItem &item, m_debuggers)
+ if (item.id() == id)
+ return &item;
+
+ return 0;
+}
+
+void DebuggerItemManager::restoreDebuggers()
+{
+ // Read debuggers from SDK
+ QFileInfo systemSettingsFile(Core::ICore::settings(QSettings::SystemScope)->fileName());
+ readDebuggers(FileName::fromString(systemSettingsFile.absolutePath() + QLatin1String(DEBUGGER_FILENAME)), true);
+
+ // Read all debuggers from user file.
+ readDebuggers(userSettingsFileName(), false);
+
+ // Auto detect current.
+ autoDetectCdbDebuggers();
+ autoDetectGdbOrLldbDebuggers();
+
+ // Add debuggers from pre-3.x profiles.xml
+ readLegacyDebuggers();
+}
+
+void DebuggerItemManager::saveDebuggers()
+{
+ QTC_ASSERT(m_writer, return);
+ QVariantMap data;
+ data.insert(QLatin1String(DEBUGGER_FILE_VERSION_KEY), 1);
+
+ int count = 0;
+ foreach (const DebuggerItem &item, m_debuggers) {
+ if (item.isValid() && item.engineType() != NoEngineType) {
+ QVariantMap tmp = item.toMap();
+ if (tmp.isEmpty())
+ continue;
+ data.insert(QString::fromLatin1(DEBUGGER_DATA_KEY) + QString::number(count), tmp);
+ ++count;
+ }
+ }
+ data.insert(QLatin1String(DEBUGGER_COUNT_KEY), count);
+ m_writer->save(data, Core::ICore::mainWindow());
+
+ // Do not save default debuggers as they are set by the SDK.
+}
+
+QVariant DebuggerItemManager::registerDebugger(const DebuggerItem &item)
+{
+ QTC_ASSERT(!findById(item.id()), return item.id());
+
+ return addDebugger(item);
+}
+
+void DebuggerItemManager::deregisterDebugger(const DebuggerItem &item)
+{
+ QTC_ASSERT(!item.command().isEmpty(), return);
+ QTC_ASSERT(!item.displayName().isEmpty(), return);
+ QTC_ASSERT(item.engineType() != NoEngineType, return);
+
+ if (findById(item.id()))
+ removeDebugger(item.id());
+}
+
+QVariant DebuggerItemManager::addDebugger(const DebuggerItem &item)
+{
+ QTC_ASSERT(item.id().isValid(), return QVariant());
+ m_debuggers.append(item);
+ QVariant id = item.id();
+ emit m_instance->debuggerAdded(id);
+ return id;
+}
+
+void DebuggerItemManager::removeDebugger(const QVariant &id)
+{
+ bool ok = false;
+ for (int i = 0, n = m_debuggers.size(); i != n; ++i) {
+ if (m_debuggers.at(i).id() == id) {
+ emit m_instance->aboutToRemoveDebugger(id);
+ m_debuggers.removeAt(i);
+ emit m_instance->debuggerRemoved(id);
+ ok = true;
+ break;
+ }
+ }
+
+ QTC_ASSERT(ok, return);
+}
+
+QString DebuggerItemManager::uniqueDisplayName(const QString &base)
+{
+ foreach (const DebuggerItem &item, m_debuggers)
+ if (item.displayName() == base)
+ return uniqueDisplayName(base + QLatin1String(" (1)"));
+
+ return base;
+}
+
+void DebuggerItemManager::setItemData(const QVariant &id, const QString &displayName, const FileName &fileName)
+{
+ for (int i = 0, n = m_debuggers.size(); i != n; ++i) {
+ DebuggerItem &item = m_debuggers[i];
+ if (item.id() == id) {
+ item.setDisplayName(displayName);
+ item.setCommand(fileName);
+ item.reinitializeFromFile();
+ emit m_instance->debuggerUpdated(id);
+ break;
+ }
+ }
+}
+
+} // namespace Debugger;
diff --git a/src/plugins/debugger/debuggeritemmanager.h b/src/plugins/debugger/debuggeritemmanager.h
new file mode 100644
index 0000000000..27ad45614b
--- /dev/null
+++ b/src/plugins/debugger/debuggeritemmanager.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef DEBUGGER_DEBUGGERITEMMANAGER_H
+#define DEBUGGER_DEBUGGERITEMMANAGER_H
+
+#include "debugger_global.h"
+#include "debuggeritem.h"
+#include "debuggeritemmodel.h"
+
+#include <QList>
+#include <QObject>
+#include <QString>
+
+namespace Utils { class PersistentSettingsWriter; }
+
+namespace Debugger {
+
+// -----------------------------------------------------------------------
+// DebuggerItemManager
+// -----------------------------------------------------------------------
+
+class DEBUGGER_EXPORT DebuggerItemManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ static QObject *instance();
+ ~DebuggerItemManager();
+
+ static QList<DebuggerItem> debuggers();
+
+ static QVariant registerDebugger(const DebuggerItem &item);
+ static void deregisterDebugger(const DebuggerItem &item);
+ static void setItemData(const QVariant &id, const QString& displayName, const Utils::FileName &fileName);
+
+ static const DebuggerItem *findByCommand(const Utils::FileName &command);
+ static const DebuggerItem *findById(const QVariant &id);
+
+ static void restoreDebuggers();
+ static QString uniqueDisplayName(const QString &base);
+
+ static void removeDebugger(const QVariant &id);
+ static QVariant addDebugger(const DebuggerItem &item);
+
+signals:
+ void debuggerAdded(const QVariant &id);
+ void aboutToRemoveDebugger(const QVariant &id);
+ void debuggerRemoved(const QVariant &id);
+ void debuggerUpdated(const QVariant &id);
+
+public slots:
+ void saveDebuggers();
+
+private:
+ explicit DebuggerItemManager(QObject *parent = 0);
+ static void autoDetectGdbOrLldbDebuggers();
+ static void autoDetectCdbDebuggers();
+ static void readLegacyDebuggers();
+
+ static Utils::PersistentSettingsWriter *m_writer;
+ static QList<DebuggerItem> m_debuggers;
+
+ friend class Internal::DebuggerItemModel;
+ friend class DebuggerPlugin; // Enable constrcutor for DebuggerPlugin
+};
+
+} // namespace Debugger
+
+#endif // DEBUGGER_DEBUGGERITEMMANAGER_H
diff --git a/src/plugins/debugger/debuggeritemmodel.cpp b/src/plugins/debugger/debuggeritemmodel.cpp
new file mode 100644
index 0000000000..2adb8d75d4
--- /dev/null
+++ b/src/plugins/debugger/debuggeritemmodel.cpp
@@ -0,0 +1,304 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "debuggeritemmodel.h"
+
+#include "debuggeritem.h"
+#include "debuggeritemmanager.h"
+
+#include <utils/qtcassert.h>
+
+namespace Debugger {
+namespace Internal {
+
+static QList<QStandardItem *> describeItem(const DebuggerItem &item)
+{
+ QList<QStandardItem *> row;
+ row.append(new QStandardItem(item.displayName()));
+ row.append(new QStandardItem(item.command().toUserOutput()));
+ row.append(new QStandardItem(item.engineTypeName()));
+ row.at(0)->setData(item.id());
+ row.at(0)->setData(item.abiNames(), Qt::UserRole + 2);
+ row.at(0)->setEditable(false);
+ row.at(1)->setEditable(false);
+ row.at(1)->setData(item.toMap());
+ row.at(2)->setEditable(false);
+ row.at(2)->setData(static_cast<int>(item.engineType()));
+ row.at(0)->setSelectable(true);
+ row.at(1)->setSelectable(true);
+ row.at(2)->setSelectable(true);
+ return row;
+}
+
+static QList<QStandardItem *> createRow(const QString &display)
+{
+ QList<QStandardItem *> row;
+ row.append(new QStandardItem(display));
+ row.append(new QStandardItem());
+ row.append(new QStandardItem());
+ row.at(0)->setEditable(false);
+ row.at(1)->setEditable(false);
+ row.at(2)->setEditable(false);
+ row.at(0)->setSelectable(false);
+ row.at(1)->setSelectable(false);
+ row.at(2)->setSelectable(false);
+ return row;
+}
+
+// --------------------------------------------------------------------------
+// DebuggerItemModel
+// --------------------------------------------------------------------------
+
+DebuggerItemModel::DebuggerItemModel(QObject *parent)
+ : QStandardItemModel(parent)
+{
+ setColumnCount(3);
+
+ QList<QStandardItem *> row = createRow(tr("Auto-detected"));
+ m_autoRoot = row.at(0);
+ appendRow(row);
+
+ row = createRow(tr("Manual"));
+ m_manualRoot = row.at(0);
+ appendRow(row);
+
+ foreach (const DebuggerItem &item, DebuggerItemManager::debuggers())
+ addDebuggerStandardItem(item, false);
+
+ QObject *manager = DebuggerItemManager::instance();
+ connect(manager, SIGNAL(debuggerAdded(QVariant)),
+ this, SLOT(onDebuggerAdded(QVariant)));
+ connect(manager, SIGNAL(debuggerUpdated(QVariant)),
+ this, SLOT(onDebuggerUpdate(QVariant)));
+ connect(manager, SIGNAL(debuggerRemoved(QVariant)),
+ this, SLOT(onDebuggerRemoval(QVariant)));
+}
+
+QVariant DebuggerItemModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
+ switch (section) {
+ case 0:
+ return tr("Name");
+ case 1:
+ return tr("Path");
+ case 2:
+ return tr("Type");
+ }
+ }
+ return QVariant();
+}
+
+bool DebuggerItemModel::addDebuggerStandardItem(const DebuggerItem &item, bool changed)
+{
+ if (findStandardItemById(item.id()))
+ return false;
+
+ QList<QStandardItem *> row = describeItem(item);
+ foreach (QStandardItem *cell, row) {
+ QFont font = cell->font();
+ font.setBold(changed);
+ cell->setFont(font);
+ }
+ (item.isAutoDetected() ? m_autoRoot : m_manualRoot)->appendRow(row);
+ return true;
+}
+
+bool DebuggerItemModel::removeDebuggerStandardItem(const QVariant &id)
+{
+ QStandardItem *sitem = findStandardItemById(id);
+ QTC_ASSERT(sitem, return false);
+ QStandardItem *parent = sitem->parent();
+ QTC_ASSERT(parent, return false);
+ // This will trigger a change of m_currentDebugger via changing the
+ // view selection.
+ parent->removeRow(sitem->row());
+ return true;
+}
+
+bool DebuggerItemModel::updateDebuggerStandardItem(const DebuggerItem &item, bool changed)
+{
+ QStandardItem *sitem = findStandardItemById(item.id());
+ QTC_ASSERT(sitem, return false);
+ QStandardItem *parent = sitem->parent();
+ QTC_ASSERT(parent, return false);
+ int row = sitem->row();
+ QFont font = sitem->font();
+ font.setBold(changed);
+ parent->child(row, 0)->setData(item.displayName(), Qt::DisplayRole);
+ parent->child(row, 0)->setFont(font);
+ parent->child(row, 1)->setData(item.command().toUserOutput(), Qt::DisplayRole);
+ parent->child(row, 1)->setFont(font);
+ parent->child(row, 2)->setData(item.engineTypeName(), Qt::DisplayRole);
+ parent->child(row, 2)->setData(static_cast<int>(item.engineType()));
+ parent->child(row, 2)->setFont(font);
+ return true;
+}
+
+DebuggerItem DebuggerItemModel::debuggerItem(QStandardItem *sitem) const
+{
+ DebuggerItem item = DebuggerItem(QVariant());
+ if (sitem && sitem->parent()) {
+ item.setAutoDetected(sitem->parent() == m_autoRoot);
+
+ QStandardItem *i = sitem->parent()->child(sitem->row(), 0);
+ item.m_id = i->data();
+ item.setDisplayName(i->data(Qt::DisplayRole).toString());
+
+ QStringList abis = i->data(Qt::UserRole + 2).toStringList();
+ QList<ProjectExplorer::Abi> abiList;
+ foreach (const QString &abi, abis)
+ abiList << ProjectExplorer::Abi(abi);
+ item.setAbis(abiList);
+
+ i = sitem->parent()->child(sitem->row(), 1);
+ item.setCommand(Utils::FileName::fromUserInput(i->data(Qt::DisplayRole).toString()));
+
+ i = sitem->parent()->child(sitem->row(), 2);
+ item.setEngineType(static_cast<DebuggerEngineType>(i->data().toInt()));
+ }
+ return item;
+}
+
+QList<DebuggerItem> DebuggerItemModel::debuggerItems() const
+{
+ QList<DebuggerItem> result;
+ for (int i = 0, n = m_autoRoot->rowCount(); i != n; ++i)
+ result << debuggerItem(m_autoRoot->child(i));
+ for (int i = 0, n = m_manualRoot->rowCount(); i != n; ++i)
+ result << debuggerItem(m_manualRoot->child(i));
+ return result;
+}
+
+QStandardItem *DebuggerItemModel::currentStandardItem() const
+{
+ return findStandardItemById(m_currentDebugger);
+}
+
+QStandardItem *DebuggerItemModel::findStandardItemById(const QVariant &id) const
+{
+ for (int i = 0, n = m_autoRoot->rowCount(); i != n; ++i) {
+ QStandardItem *sitem = m_autoRoot->child(i);
+ if (sitem->data() == id)
+ return sitem;
+ }
+ for (int i = 0, n = m_manualRoot->rowCount(); i != n; ++i) {
+ QStandardItem *sitem = m_manualRoot->child(i);
+ if (sitem->data() == id)
+ return sitem;
+ }
+ return 0;
+}
+
+QModelIndex DebuggerItemModel::currentIndex() const
+{
+ QStandardItem *current = currentStandardItem();
+ return current ? current->index() : QModelIndex();
+}
+
+QModelIndex DebuggerItemModel::lastIndex() const
+{
+ int n = m_manualRoot->rowCount();
+ QStandardItem *current = m_manualRoot->child(n - 1);
+ return current ? current->index() : QModelIndex();
+}
+
+void DebuggerItemModel::onDebuggerAdded(const QVariant &id)
+{
+ const DebuggerItem *item = DebuggerItemManager::findById(id);
+ QTC_ASSERT(item, return);
+ if (!addDebuggerStandardItem(*item, false))
+ updateDebuggerStandardItem(*item, false); // already had it added, so just update it.
+}
+
+void DebuggerItemModel::onDebuggerUpdate(const QVariant &id)
+{
+ const DebuggerItem *item = DebuggerItemManager::findById(id);
+ QTC_ASSERT(item, return);
+ updateDebuggerStandardItem(*item, false);
+}
+
+void DebuggerItemModel::onDebuggerRemoval(const QVariant &id)
+{
+ removeDebuggerStandardItem(id);
+}
+
+void DebuggerItemModel::addDebugger(const DebuggerItem &item)
+{
+ addDebuggerStandardItem(item, true);
+}
+
+void DebuggerItemModel::removeDebugger(const QVariant &id)
+{
+ if (!removeDebuggerStandardItem(id)) // Nothing there!
+ return;
+
+ if (DebuggerItemManager::findById(id))
+ m_removedItems.append(id);
+}
+
+void DebuggerItemModel::updateDebugger(const DebuggerItem &item)
+{
+ updateDebuggerStandardItem(item, true);
+}
+
+void DebuggerItemModel::apply()
+{
+ foreach (const QVariant &id, m_removedItems) {
+ const DebuggerItem *item = DebuggerItemManager::findById(id);
+ QTC_CHECK(item);
+ DebuggerItemManager::deregisterDebugger(*item);
+ }
+
+ foreach (const DebuggerItem &item, debuggerItems()) {
+ const DebuggerItem *managed = DebuggerItemManager::findById(item.id());
+ if (managed) {
+ if (*managed == item)
+ continue;
+ else
+ DebuggerItemManager::setItemData(item.id(), item.displayName(), item.command());
+ } else {
+ DebuggerItemManager::registerDebugger(item);
+ }
+ }
+}
+
+void DebuggerItemModel::setCurrentIndex(const QModelIndex &index)
+{
+ QStandardItem *sit = itemFromIndex(index);
+ m_currentDebugger = sit ? sit->data() : QVariant();
+}
+
+DebuggerItem DebuggerItemModel::currentDebugger() const
+{
+ return debuggerItem(currentStandardItem());
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/debuggeritemmodel.h b/src/plugins/debugger/debuggeritemmodel.h
new file mode 100644
index 0000000000..1f26169625
--- /dev/null
+++ b/src/plugins/debugger/debuggeritemmodel.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef DEBUGGER_DEBUGGERITEMMODEL_H
+#define DEBUGGER_DEBUGGERITEMMODEL_H
+
+#include "debuggeritem.h"
+
+#include <QStandardItemModel>
+#include <QVariant>
+
+namespace Debugger {
+namespace Internal {
+
+// -----------------------------------------------------------------------
+// DebuggerItemModel
+//------------------------------------------------------------------------
+
+class DebuggerItemModel : public QStandardItemModel
+{
+ Q_OBJECT
+
+public:
+ DebuggerItemModel(QObject *parent = 0);
+
+ QModelIndex currentIndex() const;
+ QModelIndex lastIndex() const;
+ void setCurrentIndex(const QModelIndex &index);
+ QVariant currentDebuggerId() const { return m_currentDebugger; }
+ DebuggerItem currentDebugger() const;
+ void addDebugger(const DebuggerItem &item);
+ void removeDebugger(const QVariant &id);
+ void updateDebugger(const DebuggerItem &item);
+
+ void apply();
+
+private slots:
+ void onDebuggerAdded(const QVariant &id);
+ void onDebuggerUpdate(const QVariant &id);
+ void onDebuggerRemoval(const QVariant &id);
+
+private:
+ QStandardItem *currentStandardItem() const;
+ QStandardItem *findStandardItemById(const QVariant &id) const;
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+
+ bool addDebuggerStandardItem(const DebuggerItem &item, bool changed);
+ bool removeDebuggerStandardItem(const QVariant &id);
+ bool updateDebuggerStandardItem(const DebuggerItem &item, bool changed);
+
+ DebuggerItem debuggerItem(QStandardItem *sitem) const;
+ QList<DebuggerItem> debuggerItems() const;
+
+ QVariant m_currentDebugger;
+
+ QStandardItem *m_autoRoot;
+ QStandardItem *m_manualRoot;
+ QStringList removed;
+
+ QList<QVariant> m_removedItems;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_DEBUGGERITEMMODEL_H
diff --git a/src/plugins/debugger/debuggerkitconfigwidget.cpp b/src/plugins/debugger/debuggerkitconfigwidget.cpp
index 9d9f0b23a9..9ced9edf69 100644
--- a/src/plugins/debugger/debuggerkitconfigwidget.cpp
+++ b/src/plugins/debugger/debuggerkitconfigwidget.cpp
@@ -29,6 +29,10 @@
#include "debuggerkitconfigwidget.h"
+#include "debuggeritemmanager.h"
+#include "debuggeritemmodel.h"
+#include "debuggerkitinformation.h"
+
#include <coreplugin/icore.h>
#include <projectexplorer/abi.h>
@@ -64,816 +68,10 @@ using namespace Utils;
using namespace Debugger::Internal;
namespace Debugger {
-
-static const char debuggingToolsWikiLinkC[] = "http://qt-project.org/wiki/Qt_Creator_Windows_Debugging";
-
-static const char DEBUGGER_DATA_KEY[] = "DebuggerItem.";
-static const char DEBUGGER_COUNT_KEY[] = "DebuggerItem.Count";
-static const char DEBUGGER_FILE_VERSION_KEY[] = "Version";
-static const char DEBUGGER_FILENAME[] = "/qtcreator/debuggers.xml";
-static const char DEBUGGER_LEGACY_FILENAME[] = "/qtcreator/profiles.xml";
-
-// --------------------------------------------------------------------------
-// DebuggerKitInformation
-// --------------------------------------------------------------------------
-
-DebuggerKitInformation::DebuggerKitInformation()
-{
- setObjectName(QLatin1String("DebuggerKitInformation"));
- setId(DebuggerKitInformation::id());
- setPriority(28000);
-}
-
-QVariant DebuggerKitInformation::defaultValue(Kit *k) const
-{
- ToolChain *tc = ToolChainKitInformation::toolChain(k);
- QTC_ASSERT(tc, return QVariant());
-
- const Abi toolChainAbi = tc->targetAbi();
- foreach (const DebuggerItem &item, DebuggerItemManager::debuggers())
- foreach (const Abi targetAbi, item.abis())
- if (targetAbi.isCompatibleWith(toolChainAbi))
- return item.id();
-
- return QVariant();
-}
-
-void DebuggerKitInformation::setup(Kit *k)
-{
- // Get one of the available debugger matching the kit's toolchain.
- const ToolChain *tc = ToolChainKitInformation::toolChain(k);
- const Abi toolChainAbi = tc ? tc->targetAbi() : Abi::hostAbi();
-
- // This can be anything (Id, binary path, "auto")
- const QVariant rawId = k->value(DebuggerKitInformation::id());
-
- enum {
- NotDetected, DetectedAutomatically, DetectedByFile, DetectedById
- } detection = NotDetected;
- DebuggerEngineType autoEngine = NoEngineType;
- FileName fileName;
-
- // With 3.0 we have:
- // <value type="QString" key="Debugger.Information">{75ecf347-f221-44c3-b613-ea1d29929cd4}</value>
- // Before we had:
- // <valuemap type="QVariantMap" key="Debugger.Information">
- // <value type="QString" key="Binary">/data/dev/debugger/gdb-git/gdb/gdb</value>
- // <value type="int" key="EngineType">1</value>
- // </valuemap>
- // Or for force auto-detected CDB
- // <valuemap type="QVariantMap" key="Debugger.Information">
- // <value type="QString" key="Binary">auto</value>
- // <value type="int" key="EngineType">4</value>
- // </valuemap>
-
- if (rawId.isNull()) {
- // Initial setup of a kit
- detection = NotDetected;
- } else if (rawId.type() == QVariant::String) {
- detection = DetectedById;
- } else {
- QMap<QString, QVariant> map = rawId.toMap();
- QString binary = map.value(QLatin1String("Binary")).toString();
- if (binary == QLatin1String("auto")) {
- detection = DetectedAutomatically;
- autoEngine = DebuggerEngineType(map.value(QLatin1String("EngineType")).toInt());
- } else {
- detection = DetectedByFile;
- fileName = FileName::fromUserInput(binary);
- }
- }
-
- const DebuggerItem *bestItem = 0;
- DebuggerItem::MatchLevel bestLevel = DebuggerItem::DoesNotMatch;
- foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) {
- const DebuggerItem *goodItem = 0;
- if (detection == DetectedById && item.id() == rawId)
- goodItem = &item;
- if (detection == DetectedByFile && item.command() == fileName)
- goodItem = &item;
- if (detection == DetectedAutomatically && item.engineType() == autoEngine)
- goodItem = &item;
-
- if (goodItem) {
- DebuggerItem::MatchLevel level = goodItem->matchTarget(toolChainAbi);
- if (level > bestLevel) {
- bestLevel = level;
- bestItem = goodItem;
- }
- }
- }
-
- // If we have an existing debugger with matching id _and_
- // matching target ABI we are fine.
- if (bestItem) {
- k->setValue(DebuggerKitInformation::id(), bestItem->id());
- return;
- }
-
- // We didn't find an existing debugger that matched by whatever
- // data we found in the kit (i.e. no id, filename, "auto")
- // (or what we found did not match ABI-wise)
- // Let's try to pick one with matching ABI.
- QVariant bestId;
- bestLevel = DebuggerItem::DoesNotMatch;
- foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) {
- DebuggerItem::MatchLevel level = item.matchTarget(toolChainAbi);
- if (level > bestLevel) {
- bestLevel = level;
- bestId = item.id();
- }
- }
-
- k->setValue(DebuggerKitInformation::id(), bestId);
-}
-
-
-// This handles the upgrade path from 2.8 to 3.0
-void DebuggerKitInformation::fix(Kit *k)
-{
- // This can be Id, binary path, but not "auto" anymore.
- const QVariant rawId = k->value(DebuggerKitInformation::id());
-
- if (rawId.isNull()) // No debugger set, that is fine.
- return;
-
- if (rawId.type() == QVariant::String) {
- if (!DebuggerItemManager::findById(rawId)) {
- qWarning("Unknown debugger id %s in kit %s",
- qPrintable(rawId.toString()), qPrintable(k->displayName()));
- k->setValue(DebuggerKitInformation::id(), QVariant());
- }
- return; // All fine (now).
- }
-
- QMap<QString, QVariant> map = rawId.toMap();
- QString binary = map.value(QLatin1String("Binary")).toString();
- if (binary == QLatin1String("auto")) {
- // This should not happen as "auto" is handled by setup() already.
- QTC_CHECK(false);
- k->setValue(DebuggerKitInformation::id(), QVariant());
- return;
- }
-
- FileName fileName = FileName::fromUserInput(binary);
- const DebuggerItem *item = DebuggerItemManager::findByCommand(fileName);
- if (!item) {
- qWarning("Debugger command %s invalid in kit %s",
- qPrintable(binary), qPrintable(k->displayName()));
- k->setValue(DebuggerKitInformation::id(), QVariant());
- return;
- }
-
- k->setValue(DebuggerKitInformation::id(), item->id());
-}
-
-// Check the configuration errors and return a flag mask. Provide a quick check and
-// a verbose one with a list of errors.
-
-enum DebuggerConfigurationErrors {
- NoDebugger = 0x1,
- DebuggerNotFound = 0x2,
- DebuggerNotExecutable = 0x4,
- DebuggerNeedsAbsolutePath = 0x8
-};
-
-static unsigned debuggerConfigurationErrors(const Kit *k)
-{
- QTC_ASSERT(k, return NoDebugger);
-
- const DebuggerItem *item = DebuggerKitInformation::debugger(k);
- if (!item)
- return NoDebugger;
-
- if (item->command().isEmpty())
- return NoDebugger;
-
- unsigned result = 0;
- const QFileInfo fi = item->command().toFileInfo();
- if (!fi.exists() || fi.isDir())
- result |= DebuggerNotFound;
- else if (!fi.isExecutable())
- result |= DebuggerNotExecutable;
-
- if (!fi.exists() || fi.isDir()) {
- if (item->engineType() == NoEngineType)
- return NoDebugger;
-
- // We need an absolute path to be able to locate Python on Windows.
- if (item->engineType() == GdbEngineType)
- if (const ToolChain *tc = ToolChainKitInformation::toolChain(k))
- if (tc->targetAbi().os() == Abi::WindowsOS && !fi.isAbsolute())
- result |= DebuggerNeedsAbsolutePath;
- }
- return result;
-}
-
-const DebuggerItem *DebuggerKitInformation::debugger(const Kit *kit)
-{
- QTC_ASSERT(kit, return 0);
- const QVariant id = kit->value(DebuggerKitInformation::id());
- return DebuggerItemManager::findById(id);
-}
-
-bool DebuggerKitInformation::isValidDebugger(const Kit *k)
-{
- return debuggerConfigurationErrors(k) == 0;
-}
-
-QList<Task> DebuggerKitInformation::validateDebugger(const Kit *k)
-{
- QList<Task> result;
-
- const unsigned errors = debuggerConfigurationErrors(k);
- if (!errors)
- return result;
-
- QString path;
- if (const DebuggerItem *item = debugger(k))
- path = item->command().toUserOutput();
-
- const Core::Id id = ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM;
- if (errors & NoDebugger)
- result << Task(Task::Warning, tr("No debugger set up."), FileName(), -1, id);
-
- if (errors & DebuggerNotFound)
- result << Task(Task::Error, tr("Debugger '%1' not found.").arg(path),
- FileName(), -1, id);
- if (errors & DebuggerNotExecutable)
- result << Task(Task::Error, tr("Debugger '%1' not executable.").arg(path), FileName(), -1, id);
-
- if (errors & DebuggerNeedsAbsolutePath) {
- const QString message =
- tr("The debugger location must be given as an "
- "absolute path (%1).").arg(path);
- result << Task(Task::Error, message, FileName(), -1, id);
- }
- return result;
-}
-
-KitConfigWidget *DebuggerKitInformation::createConfigWidget(Kit *k) const
-{
- return new Internal::DebuggerKitConfigWidget(k, this);
-}
-
-KitInformation::ItemList DebuggerKitInformation::toUserOutput(const Kit *k) const
-{
- return ItemList() << qMakePair(tr("Debugger"), displayString(k));
-}
-
-FileName DebuggerKitInformation::debuggerCommand(const ProjectExplorer::Kit *k)
-{
- const DebuggerItem *item = debugger(k);
- QTC_ASSERT(item, return FileName());
- return item->command();
-}
-
-DebuggerEngineType DebuggerKitInformation::engineType(const ProjectExplorer::Kit *k)
-{
- const DebuggerItem *item = debugger(k);
- QTC_ASSERT(item, return NoEngineType);
- return item->engineType();
-}
-
-QString DebuggerKitInformation::displayString(const Kit *k)
-{
- const DebuggerItem *item = debugger(k);
- if (!item)
- return tr("No Debugger");
- QString binary = item->command().toUserOutput();
- QString name = tr("%1 Engine").arg(item->engineTypeName());
- return binary.isEmpty() ? tr("%1 <None>").arg(name) : tr("%1 using \"%2\"").arg(name, binary);
-}
-
-void DebuggerKitInformation::setDebugger(Kit *k, const QVariant &id)
-{
- // Only register reasonably complete debuggers.
- QTC_ASSERT(DebuggerItemManager::findById(id), return);
- k->setValue(DebuggerKitInformation::id(), id);
-}
-
-Core::Id DebuggerKitInformation::id()
-{
- return "Debugger.Information";
-}
-
-// --------------------------------------------------------------------------
-// DebuggerItemManager
-// --------------------------------------------------------------------------
-
-static DebuggerItemManager *m_instance = 0;
-
-static FileName userSettingsFileName()
-{
- QFileInfo settingsLocation(Core::ICore::settings()->fileName());
- return FileName::fromString(settingsLocation.absolutePath() + QLatin1String(DEBUGGER_FILENAME));
-}
-
-static void readDebuggers(const FileName &fileName, bool isSystem)
-{
- PersistentSettingsReader reader;
- if (!reader.load(fileName))
- return;
- QVariantMap data = reader.restoreValues();
-
- // Check version
- int version = data.value(QLatin1String(DEBUGGER_FILE_VERSION_KEY), 0).toInt();
- if (version < 1)
- return;
-
- int count = data.value(QLatin1String(DEBUGGER_COUNT_KEY), 0).toInt();
- for (int i = 0; i < count; ++i) {
- const QString key = QString::fromLatin1(DEBUGGER_DATA_KEY) + QString::number(i);
- if (!data.contains(key))
- continue;
- const QVariantMap dbMap = data.value(key).toMap();
- DebuggerItem item;
- item.fromMap(dbMap);
- if (isSystem) {
- item.setAutoDetected(true);
- // SDK debuggers are always considered to be up-to-date, so no need to recheck them.
- } else {
- // User settings.
- if (item.isAutoDetected() && !item.isValid()) {
- qWarning() << QString::fromLatin1("DebuggerItem \"%1\" (%2) dropped since it is not valid")
- .arg(item.command().toString()).arg(item.id().toString());
- continue;
- }
- }
- DebuggerItemManager::registerDebugger(item);
- }
-}
-
-QList<DebuggerItem> DebuggerItemManager::m_debuggers;
-DebuggerItemModel* DebuggerItemManager::m_model = 0;
-PersistentSettingsWriter * DebuggerItemManager::m_writer = 0;
-
-DebuggerItemManager::DebuggerItemManager(QObject *parent)
- : QObject(parent)
-{
- m_instance = this;
- m_writer = new PersistentSettingsWriter(userSettingsFileName(), QLatin1String("QtCreatorDebugger"));
- m_model = new Debugger::Internal::DebuggerItemModel(this);
- connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()),
- this, SLOT(saveDebuggers()));
-}
-
-QObject *DebuggerItemManager::instance()
-{
- return m_instance;
-}
-
-DebuggerItemManager::~DebuggerItemManager()
-{
- disconnect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()),
- this, SLOT(saveDebuggers()));
- delete m_writer;
-}
-
-QList<DebuggerItem> DebuggerItemManager::debuggers()
-{
- return m_debuggers;
-}
-
-DebuggerItemModel *DebuggerItemManager::model()
-{
- return m_model;
-}
-
-void DebuggerItemManager::autoDetectCdbDebuggers()
-{
- QList<FileName> cdbs;
-
- QStringList programDirs;
- programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles")));
- programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles(x86)")));
- programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramW6432")));
-
- foreach (const QString &dirName, programDirs) {
- if (dirName.isEmpty())
- continue;
- QDir dir(dirName);
- // Windows SDK's starting from version 8 live in
- // "ProgramDir\Windows Kits\<version>"
- const QString windowsKitsFolderName = QLatin1String("Windows Kits");
- if (dir.exists(windowsKitsFolderName)) {
- QDir windowKitsFolder = dir;
- if (windowKitsFolder.cd(windowsKitsFolderName)) {
- // Check in reverse order (latest first)
- const QFileInfoList kitFolders =
- windowKitsFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot,
- QDir::Time | QDir::Reversed);
- foreach (const QFileInfo &kitFolderFi, kitFolders) {
- const QString path = kitFolderFi.absoluteFilePath();
- const QFileInfo cdb32(path + QLatin1String("/Debuggers/x86/cdb.exe"));
- if (cdb32.isExecutable())
- cdbs.append(FileName::fromString(cdb32.absoluteFilePath()));
- const QFileInfo cdb64(path + QLatin1String("/Debuggers/x64/cdb.exe"));
- if (cdb64.isExecutable())
- cdbs.append(FileName::fromString(cdb64.absoluteFilePath()));
- }
- }
- }
-
- // Pre Windows SDK 8: Check 'Debugging Tools for Windows'
- foreach (const QFileInfo &fi, dir.entryInfoList(QStringList(QLatin1String("Debugging Tools for Windows*")),
- QDir::Dirs | QDir::NoDotAndDotDot)) {
- FileName filePath(fi);
- filePath.appendPath(QLatin1String("cdb.exe"));
- if (!cdbs.contains(filePath))
- cdbs.append(filePath);
- }
- }
-
- foreach (const FileName &cdb, cdbs) {
- if (findByCommand(cdb))
- continue;
- DebuggerItem item;
- item.setAutoDetected(true);
- item.setAbis(Abi::abisOfBinary(cdb));
- item.setCommand(cdb);
- item.setEngineType(CdbEngineType);
- item.setDisplayName(uniqueDisplayName(tr("Auto-detected CDB at %1").arg(cdb.toUserOutput())));
- addDebugger(item);
- }
-}
-
-void DebuggerItemManager::autoDetectGdbOrLldbDebuggers()
-{
- QStringList filters;
- filters.append(QLatin1String("gdb-i686-pc-mingw32"));
- filters.append(QLatin1String("gdb"));
- filters.append(QLatin1String("lldb"));
- filters.append(QLatin1String("lldb-*"));
-
-// DebuggerItem result;
-// result.setAutoDetected(true);
-// result.setDisplayName(tr("Auto-detected for Tool Chain %1").arg(tc->displayName()));
- /*
- // Check suggestions from the SDK.
- Environment env = Environment::systemEnvironment();
- if (tc) {
- tc->addToEnvironment(env); // Find MinGW gdb in toolchain environment.
- QString path = tc->suggestedDebugger().toString();
- if (!path.isEmpty()) {
- const QFileInfo fi(path);
- if (!fi.isAbsolute())
- path = env.searchInPath(path);
- result.command = FileName::fromString(path);
- result.engineType = engineTypeFromBinary(path);
- return maybeAddDebugger(result, false);
- }
- }
- */
-
- QFileInfoList suspects;
-
- QStringList path = Environment::systemEnvironment().path();
- foreach (const QString &base, path) {
- QDir dir(base);
- dir.setNameFilters(filters);
- suspects += dir.entryInfoList();
- }
-
- foreach (const QFileInfo &fi, suspects) {
- if (fi.exists()) {
- FileName command = FileName::fromString(fi.absoluteFilePath());
- if (findByCommand(command))
- continue;
- DebuggerItem item;
- item.setCommand(command);
- item.reinitializeFromFile();
- //: %1: Debugger engine type (GDB, LLDB, CDB...), %2: Path
- item.setDisplayName(tr("System %1 at %2")
- .arg(item.engineTypeName()).arg(QDir::toNativeSeparators(fi.absoluteFilePath())));
- item.setAutoDetected(true);
- addDebugger(item);
- }
- }
-}
-
-void DebuggerItemManager::readLegacyDebuggers()
-{
- QFileInfo settingsLocation(Core::ICore::settings()->fileName());
- FileName legacyKits = FileName::fromString(settingsLocation.absolutePath() + QLatin1String(DEBUGGER_LEGACY_FILENAME));
-
- PersistentSettingsReader reader;
- if (!reader.load(legacyKits))
- return;
-
- foreach (const QVariant &v, reader.restoreValues()) {
- QVariantMap data1 = v.toMap();
- QString kitName = data1.value(QLatin1String("PE.Profile.Name")).toString();
- QVariantMap data2 = data1.value(QLatin1String("PE.Profile.Data")).toMap();
- QVariant v3 = data2.value(DebuggerKitInformation::id().toString());
- QString fn;
- if (v3.type() == QVariant::String)
- fn = v3.toString();
- else
- fn = v3.toMap().value(QLatin1String("Binary")).toString();
- if (fn.isEmpty())
- continue;
- if (fn.startsWith(QLatin1Char('{')))
- continue;
- if (fn == QLatin1String("auto"))
- continue;
- FileName command = FileName::fromUserInput(fn);
- if (findByCommand(command))
- continue;
- DebuggerItem item;
- item.setCommand(command);
- item.setAutoDetected(true);
- item.reinitializeFromFile();
- item.setDisplayName(tr("Extracted from Kit %1").arg(kitName));
- addDebugger(item);
- }
-}
-
-const DebuggerItem *DebuggerItemManager::findByCommand(const FileName &command)
-{
- foreach (const DebuggerItem &item, m_debuggers)
- if (item.command() == command)
- return &item;
-
- return 0;
-}
-
-const DebuggerItem *DebuggerItemManager::findById(const QVariant &id)
-{
- foreach (const DebuggerItem &item, m_debuggers)
- if (item.id() == id)
- return &item;
-
- return 0;
-}
-
-void DebuggerItemManager::restoreDebuggers()
-{
- // Read debuggers from SDK
- QFileInfo systemSettingsFile(Core::ICore::settings(QSettings::SystemScope)->fileName());
- readDebuggers(FileName::fromString(systemSettingsFile.absolutePath() + QLatin1String(DEBUGGER_FILENAME)), true);
-
- // Read all debuggers from user file.
- readDebuggers(userSettingsFileName(), false);
-
- // Auto detect current.
- autoDetectCdbDebuggers();
- autoDetectGdbOrLldbDebuggers();
-
- // Add debuggers from pre-3.x profiles.xml
- readLegacyDebuggers();
-}
-
-void DebuggerItemManager::saveDebuggers()
-{
- QTC_ASSERT(m_writer, return);
- QVariantMap data;
- data.insert(QLatin1String(DEBUGGER_FILE_VERSION_KEY), 1);
-
- int count = 0;
- foreach (const DebuggerItem &item, m_debuggers) {
- if (item.isValid()) {
- QVariantMap tmp = item.toMap();
- if (tmp.isEmpty())
- continue;
- data.insert(QString::fromLatin1(DEBUGGER_DATA_KEY) + QString::number(count), tmp);
- ++count;
- }
- }
- data.insert(QLatin1String(DEBUGGER_COUNT_KEY), count);
- m_writer->save(data, Core::ICore::mainWindow());
-
- // Do not save default debuggers as they are set by the SDK.
-}
-
-QVariant DebuggerItemManager::registerDebugger(const DebuggerItem &item)
-{
- if (findByCommand(item.command()))
- return item.id();
-
- return addDebugger(item);
-}
-
-void DebuggerItemManager::deregisterDebugger(const DebuggerItem &item)
-{
- if (findByCommand(item.command()))
- removeDebugger(item.id());
-}
-
-QVariant DebuggerItemManager::addDebugger(const DebuggerItem& item0)
-{
- DebuggerItem item = item0;
- QTC_ASSERT(!item.command().isEmpty(), return QVariant());
- QTC_ASSERT(!item.displayName().isEmpty(), return QVariant());
- QTC_ASSERT(item.engineType() != NoEngineType, return QVariant());
- if (item.id().isNull())
- item.setId(QUuid::createUuid().toString());
- m_debuggers.append(item);
- m_model->addDebugger(item);
- return item.id();
-}
-
-void DebuggerItemManager::removeDebugger(const QVariant &id)
-{
- bool ok = false;
- for (int i = 0, n = m_debuggers.size(); i != n; ++i) {
- if (m_debuggers.at(i).id() == id) {
- m_debuggers.removeAt(i);
- ok = true;
- break;
- }
- }
-
- QTC_ASSERT(ok, return);
- m_model->removeDebugger(id);
-}
-
-QString DebuggerItemManager::uniqueDisplayName(const QString &base)
-{
- foreach (const DebuggerItem &item, m_debuggers)
- if (item.displayName() == base)
- return uniqueDisplayName(base + QLatin1String(" (1)"));
-
- return base;
-}
-
-void DebuggerItemManager::setItemData(const QVariant &id, const QString &displayName, const FileName &fileName)
-{
- for (int i = 0, n = m_debuggers.size(); i != n; ++i) {
- DebuggerItem &item = m_debuggers[i];
- if (item.id() == id) {
- item.setDisplayName(displayName);
- item.setCommand(fileName);
- item.reinitializeFromFile();
- emit m_model->updateDebugger(item.id());
- break;
- }
- }
-}
-
namespace Internal {
-static QList<QStandardItem *> describeItem(const DebuggerItem &item)
-{
- QList<QStandardItem *> row;
- row.append(new QStandardItem(item.displayName()));
- row.append(new QStandardItem(item.command().toUserOutput()));
- row.append(new QStandardItem(item.engineTypeName()));
- row.at(0)->setData(item.id());
- row.at(0)->setEditable(false);
- row.at(1)->setEditable(false);
- row.at(2)->setEditable(false);
- row.at(0)->setSelectable(true);
- row.at(1)->setSelectable(true);
- row.at(2)->setSelectable(true);
- return row;
-}
-
-static QList<QStandardItem *> createRow(const QString &display)
-{
- QList<QStandardItem *> row;
- row.append(new QStandardItem(display));
- row.append(new QStandardItem());
- row.append(new QStandardItem());
- row.at(0)->setEditable(false);
- row.at(1)->setEditable(false);
- row.at(2)->setEditable(false);
- row.at(0)->setSelectable(false);
- row.at(1)->setSelectable(false);
- row.at(2)->setSelectable(false);
- return row;
-}
-
class DebuggerItemConfigWidget;
-// --------------------------------------------------------------------------
-// DebuggerItemModel
-// --------------------------------------------------------------------------
-
-DebuggerItemModel::DebuggerItemModel(QObject *parent)
- : QStandardItemModel(parent)
-{
- setColumnCount(3);
-
- QList<QStandardItem *> row = createRow(tr("Auto-detected"));
- m_autoRoot = row.at(0);
- appendRow(row);
-
- row = createRow(tr("Manual"));
- m_manualRoot = row.at(0);
- appendRow(row);
-}
-
-QVariant DebuggerItemModel::headerData(int section, Qt::Orientation orientation, int role) const
-{
- if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
- switch (section) {
- case 0:
- return tr("Name");
- case 1:
- return tr("Path");
- case 2:
- return tr("Type");
- }
- }
- return QVariant();
-}
-
-QStandardItem *DebuggerItemModel::currentStandardItem() const
-{
- return findStandardItemById(m_currentDebugger);
-}
-
-QStandardItem *DebuggerItemModel::findStandardItemById(const QVariant &id) const
-{
- for (int i = 0, n = m_autoRoot->rowCount(); i != n; ++i) {
- QStandardItem *sitem = m_autoRoot->child(i);
- if (sitem->data() == id)
- return sitem;
- }
- for (int i = 0, n = m_manualRoot->rowCount(); i != n; ++i) {
- QStandardItem *sitem = m_manualRoot->child(i);
- if (sitem->data() == id)
- return sitem;
- }
- return 0;
-}
-
-QModelIndex DebuggerItemModel::currentIndex() const
-{
- QStandardItem *current = currentStandardItem();
- return current ? current->index() : QModelIndex();
-}
-
-QModelIndex DebuggerItemModel::lastIndex() const
-{
- int n = m_manualRoot->rowCount();
- QStandardItem *current = m_manualRoot->child(n - 1);
- return current ? current->index() : QModelIndex();
-}
-
-void DebuggerItemModel::markCurrentDirty()
-{
- QStandardItem *sitem = currentStandardItem();
- QTC_ASSERT(sitem, return);
- QFont font = sitem->font();
- font.setBold(true);
- sitem->setFont(font);
-}
-
-void DebuggerItemModel::addDebugger(const DebuggerItem &item0)
-{
- DebuggerItem item = item0;
- if (item.id().isNull())
- item.setId(QUuid::createUuid().toString());
- QList<QStandardItem *> row = describeItem(item);
- (item.isAutoDetected() ? m_autoRoot : m_manualRoot)->appendRow(row);
- emit debuggerAdded(item.id(), item.displayName());
-}
-
-void DebuggerItemModel::removeDebugger(const QVariant &id)
-{
- QStandardItem *sitem = findStandardItemById(id);
- QTC_ASSERT(sitem, return);
- QStandardItem *parent = sitem->parent();
- QTC_ASSERT(parent, return);
- // This will trigger a change of m_currentDebugger via changing the
- // view selection.
- parent->removeRow(sitem->row());
- emit debuggerRemoved(id);
-}
-
-void DebuggerItemModel::updateDebugger(const QVariant &id)
-{
- QList<DebuggerItem> debuggers = DebuggerItemManager::debuggers();
- for (int i = 0, n = debuggers.size(); i != n; ++i) {
- DebuggerItem &item = debuggers[i];
- if (item.id() == id) {
- QStandardItem *sitem = findStandardItemById(id);
- QTC_ASSERT(sitem, return);
- QStandardItem *parent = sitem->parent();
- QTC_ASSERT(parent, return);
- int row = sitem->row();
- QFont font = sitem->font();
- font.setBold(false);
- parent->child(row, 0)->setData(item.displayName(), Qt::DisplayRole);
- parent->child(row, 0)->setFont(font);
- parent->child(row, 1)->setData(item.command().toUserOutput(), Qt::DisplayRole);
- parent->child(row, 1)->setFont(font);
- parent->child(row, 2)->setData(item.engineTypeName(), Qt::DisplayRole);
- parent->child(row, 2)->setFont(font);
- emit debuggerUpdated(id, item.displayName());
- return;
- }
- }
-}
-
-void DebuggerItemModel::setCurrentIndex(const QModelIndex &index)
-{
- QStandardItem *sit = itemFromIndex(index);
- m_currentDebugger = sit ? sit->data() : QVariant();
-}
-
// -----------------------------------------------------------------------
// DebuggerKitConfigWidget
// -----------------------------------------------------------------------
@@ -881,9 +79,6 @@ void DebuggerItemModel::setCurrentIndex(const QModelIndex &index)
DebuggerKitConfigWidget::DebuggerKitConfigWidget(Kit *workingCopy, const KitInformation *ki)
: KitConfigWidget(workingCopy, ki)
{
- DebuggerItemModel *model = DebuggerItemManager::model();
- QTC_CHECK(model);
-
m_comboBox = new QComboBox;
m_comboBox->setEnabled(true);
m_comboBox->setToolTip(toolTip());
@@ -898,11 +93,12 @@ DebuggerKitConfigWidget::DebuggerKitConfigWidget(Kit *workingCopy, const KitInfo
m_manageButton->setContentsMargins(0, 0, 0, 0);
connect(m_manageButton, SIGNAL(clicked()), this, SLOT(manageDebuggers()));
- connect(model, SIGNAL(debuggerAdded(QVariant,QString)),
- this, SLOT(onDebuggerAdded(QVariant,QString)));
- connect(model, SIGNAL(debuggerUpdated(QVariant,QString)),
- this, SLOT(onDebuggerUpdated(QVariant,QString)));
- connect(model, SIGNAL(debuggerRemoved(QVariant)),
+ QObject *manager = DebuggerItemManager::instance();
+ connect(manager, SIGNAL(debuggerAdded(QVariant)),
+ this, SLOT(onDebuggerAdded(QVariant)));
+ connect(manager, SIGNAL(debuggerUpdated(QVariant)),
+ this, SLOT(onDebuggerUpdated(QVariant)));
+ connect(manager, SIGNAL(debuggerRemoved(QVariant)),
this, SLOT(onDebuggerRemoved(QVariant)));
}
@@ -957,20 +153,22 @@ void DebuggerKitConfigWidget::currentDebuggerChanged(int)
m_kit->setValue(DebuggerKitInformation::id(), id);
}
-void DebuggerKitConfigWidget::onDebuggerAdded(const QVariant &id, const QString &displayName)
+void DebuggerKitConfigWidget::onDebuggerAdded(const QVariant &id)
{
- m_comboBox->setEnabled(true);
- m_comboBox->addItem(displayName, id);
+ const DebuggerItem *item = DebuggerItemManager::findById(id);
+ QTC_ASSERT(item, return);
+ m_comboBox->addItem(item->displayName(), id);
updateComboBox(id);
}
-void DebuggerKitConfigWidget::onDebuggerUpdated(const QVariant &id, const QString &displayName)
+void DebuggerKitConfigWidget::onDebuggerUpdated(const QVariant &id)
{
- m_comboBox->setEnabled(true);
+ const DebuggerItem *item = DebuggerItemManager::findById(id);
+ QTC_ASSERT(item, return);
const int pos = indexOf(id);
if (pos < 0)
return;
- m_comboBox->setItemText(pos, displayName);
+ m_comboBox->setItemText(pos, item->displayName());
}
void DebuggerKitConfigWidget::onDebuggerRemoved(const QVariant &id)
@@ -1007,296 +205,5 @@ void DebuggerKitConfigWidget::updateComboBox(const QVariant &id)
m_comboBox->setCurrentIndex(0);
}
-// -----------------------------------------------------------------------
-// DebuggerItemConfigWidget
-// -----------------------------------------------------------------------
-
-class DebuggerItemConfigWidget : public QWidget
-{
- Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::DebuggerItemConfigWidget)
-public:
- explicit DebuggerItemConfigWidget();
- void loadItem();
- void saveItem();
- void connectDirty();
- void disconnectDirty();
-
-private:
- QLineEdit *m_displayNameLineEdit;
- QLabel *m_cdbLabel;
- PathChooser *m_binaryChooser;
- QLineEdit *m_abis;
-};
-
-DebuggerItemConfigWidget::DebuggerItemConfigWidget()
-{
- m_displayNameLineEdit = new QLineEdit(this);
-
- m_binaryChooser = new PathChooser(this);
- m_binaryChooser->setExpectedKind(PathChooser::ExistingCommand);
- m_binaryChooser->setMinimumWidth(400);
-
- m_cdbLabel = new QLabel(this);
- m_cdbLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
- m_cdbLabel->setOpenExternalLinks(true);
-
- m_abis = new QLineEdit(this);
- m_abis->setEnabled(false);
-
- QFormLayout *formLayout = new QFormLayout(this);
- formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
- formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit);
-// formLayout->addRow(new QLabel(tr("Type:")), m_engineTypeComboBox);
- formLayout->addRow(m_cdbLabel);
- formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser);
- formLayout->addRow(new QLabel(tr("ABIs:")), m_abis);
-
- connectDirty();
-}
-
-void DebuggerItemConfigWidget::connectDirty()
-{
- DebuggerItemModel *model = DebuggerItemManager::model();
- connect(m_displayNameLineEdit, SIGNAL(textChanged(QString)),
- model, SLOT(markCurrentDirty()));
- connect(m_binaryChooser, SIGNAL(changed(QString)),
- model, SLOT(markCurrentDirty()));
-}
-
-void DebuggerItemConfigWidget::disconnectDirty()
-{
- DebuggerItemModel *model = DebuggerItemManager::model();
- disconnect(m_displayNameLineEdit, SIGNAL(textChanged(QString)),
- model, SLOT(markCurrentDirty()));
- disconnect(m_binaryChooser, SIGNAL(changed(QString)),
- model, SLOT(markCurrentDirty()));
-}
-
-void DebuggerItemConfigWidget::loadItem()
-{
- DebuggerItemModel *model = DebuggerItemManager::model();
- const DebuggerItem *item = DebuggerItemManager::findById(model->m_currentDebugger);
- if (!item)
- return;
-
- disconnectDirty();
- m_displayNameLineEdit->setEnabled(!item->isAutoDetected());
- m_displayNameLineEdit->setText(item->displayName());
-
- m_binaryChooser->setEnabled(!item->isAutoDetected());
- m_binaryChooser->setFileName(item->command());
- connectDirty();
-
- QString text;
- QString versionCommand;
- if (item->engineType() == CdbEngineType) {
-#ifdef Q_OS_WIN
- const bool is64bit = winIs64BitSystem();
-#else
- const bool is64bit = false;
-#endif
- const QString versionString = is64bit ? tr("64-bit version") : tr("32-bit version");
- //: Label text for path configuration. %2 is "x-bit version".
- text = tr("<html><body><p>Specify the path to the "
- "<a href=\"%1\">Windows Console Debugger executable</a>"
- " (%2) here.</p>""</body></html>").
- arg(QLatin1String(debuggingToolsWikiLinkC), versionString);
- versionCommand = QLatin1String("-version");
- } else {
- versionCommand = QLatin1String("--version");
- }
-
- m_cdbLabel->setText(text);
- m_cdbLabel->setVisible(!text.isEmpty());
- m_binaryChooser->setCommandVersionArguments(QStringList(versionCommand));
-
- m_abis->setText(item->abiNames().join(QLatin1String(", ")));
-}
-
-void DebuggerItemConfigWidget::saveItem()
-{
- DebuggerItemModel *model = DebuggerItemManager::model();
- const DebuggerItem *item = DebuggerItemManager::findById(model->m_currentDebugger);
- QTC_ASSERT(item, return);
- DebuggerItemManager::setItemData(item->id(), m_displayNameLineEdit->text(),
- m_binaryChooser->fileName());
-}
-
-// --------------------------------------------------------------------------
-// DebuggerOptionsPage
-// --------------------------------------------------------------------------
-
-DebuggerOptionsPage::DebuggerOptionsPage()
-{
- m_model = 0;
- m_debuggerView = 0;
- m_container = 0;
- m_addButton = 0;
- m_cloneButton = 0;
- m_delButton = 0;
-
- setId(ProjectExplorer::Constants::DEBUGGER_SETTINGS_PAGE_ID);
- setDisplayName(tr("Debuggers"));
- setCategory(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY);
- setDisplayCategory(QCoreApplication::translate("ProjectExplorer",
- ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_TR_CATEGORY));
- setCategoryIcon(QLatin1String(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY_ICON));
-}
-
-QWidget *DebuggerOptionsPage::createPage(QWidget *parent)
-{
- m_configWidget = new QWidget(parent);
-
- m_addButton = new QPushButton(tr("Add"), m_configWidget);
- m_cloneButton = new QPushButton(tr("Clone"), m_configWidget);
- m_delButton = new QPushButton(tr("Remove"), m_configWidget);
-
- m_container = new DetailsWidget(m_configWidget);
- m_container->setState(DetailsWidget::NoSummary);
- m_container->setVisible(false);
-
- m_model = DebuggerItemManager::model();
-
- m_debuggerView = new QTreeView(m_configWidget);
- m_debuggerView->setModel(m_model);
- m_debuggerView->setUniformRowHeights(true);
- m_debuggerView->setSelectionMode(QAbstractItemView::SingleSelection);
- m_debuggerView->setSelectionBehavior(QAbstractItemView::SelectRows);
- m_debuggerView->expandAll();
-
- QHeaderView *header = m_debuggerView->header();
- header->setStretchLastSection(false);
- header->setResizeMode(0, QHeaderView::ResizeToContents);
- header->setResizeMode(1, QHeaderView::ResizeToContents);
- header->setResizeMode(2, QHeaderView::Stretch);
-
- QVBoxLayout *buttonLayout = new QVBoxLayout();
- buttonLayout->setSpacing(6);
- buttonLayout->setContentsMargins(0, 0, 0, 0);
- buttonLayout->addWidget(m_addButton);
- buttonLayout->addWidget(m_cloneButton);
- buttonLayout->addWidget(m_delButton);
- buttonLayout->addItem(new QSpacerItem(10, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
-
- QVBoxLayout *verticalLayout = new QVBoxLayout();
- verticalLayout->addWidget(m_debuggerView);
- verticalLayout->addWidget(m_container);
-
- QHBoxLayout *horizontalLayout = new QHBoxLayout(m_configWidget);
- horizontalLayout->addLayout(verticalLayout);
- horizontalLayout->addLayout(buttonLayout);
-
- connect(m_debuggerView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
- this, SLOT(debuggerSelectionChanged()));
-
- connect(m_addButton, SIGNAL(clicked()), this, SLOT(addDebugger()), Qt::QueuedConnection);
- connect(m_cloneButton, SIGNAL(clicked()), this, SLOT(cloneDebugger()), Qt::QueuedConnection);
- connect(m_delButton, SIGNAL(clicked()), this, SLOT(removeDebugger()), Qt::QueuedConnection);
-
- m_searchKeywords = tr("Debuggers");
-
- m_itemConfigWidget = new DebuggerItemConfigWidget;
- m_container->setWidget(m_itemConfigWidget);
-
- updateState();
-
- return m_configWidget;
-}
-
-void DebuggerOptionsPage::apply()
-{
- m_itemConfigWidget->saveItem();
- debuggerModelChanged();
-}
-
-void DebuggerOptionsPage::cloneDebugger()
-{
- const DebuggerItem *item = DebuggerItemManager::findById(m_model->currentDebugger());
- QTC_ASSERT(item, return);
- DebuggerItem newItem;
- newItem.setCommand(item->command());
- newItem.setEngineType(item->engineType());
- newItem.setAbis(item->abis());
- newItem.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("Clone of %1").arg(item->displayName())));
- newItem.setAutoDetected(false);
- DebuggerItemManager::addDebugger(newItem);
- m_debuggerView->setCurrentIndex(m_model->lastIndex());
-}
-
-void DebuggerOptionsPage::addDebugger()
-{
- DebuggerItem item;
- item.setEngineType(NoEngineType);
- item.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("New Debugger")));
- item.setAutoDetected(false);
- DebuggerItemManager::addDebugger(item);
- m_debuggerView->setCurrentIndex(m_model->lastIndex());
-}
-
-void DebuggerOptionsPage::removeDebugger()
-{
- QVariant id = m_model->currentDebugger();
- DebuggerItemManager::removeDebugger(id);
- m_debuggerView->setCurrentIndex(m_model->lastIndex());
-}
-
-void DebuggerOptionsPage::finish()
-{
- // Deleted by settingsdialog.
- m_configWidget = 0;
-
- // Children of m_configWidget.
- m_container = 0;
- m_debuggerView = 0;
- m_addButton = 0;
- m_cloneButton = 0;
- m_delButton = 0;
-}
-
-bool DebuggerOptionsPage::matches(const QString &s) const
-{
- return m_searchKeywords.contains(s, Qt::CaseInsensitive);
-}
-
-void DebuggerOptionsPage::debuggerSelectionChanged()
-{
- QTC_ASSERT(m_container, return);
-
- QModelIndex mi = m_debuggerView->currentIndex();
- mi = mi.sibling(mi.row(), 0);
- m_model->setCurrentIndex(mi);
-
- m_itemConfigWidget->loadItem();
- m_container->setVisible(m_model->m_currentDebugger.isValid());
- updateState();
-}
-
-void DebuggerOptionsPage::debuggerModelChanged()
-{
- QTC_ASSERT(m_container, return);
-
- m_itemConfigWidget->loadItem();
- m_container->setVisible(m_model->m_currentDebugger.isValid());
- m_debuggerView->setCurrentIndex(m_model->currentIndex());
- updateState();
-}
-
-void DebuggerOptionsPage::updateState()
-{
- if (!m_cloneButton)
- return;
-
- bool canCopy = false;
- bool canDelete = false;
-
- if (const DebuggerItem *item = DebuggerItemManager::findById(m_model->m_currentDebugger)) {
- canCopy = item->isValid() && item->canClone();
- canDelete = !item->isAutoDetected();
- canDelete = true; // Do we want to remove auto-detected items?
- }
- m_cloneButton->setEnabled(canCopy);
- m_delButton->setEnabled(canDelete);
-}
-
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/debuggerkitconfigwidget.h b/src/plugins/debugger/debuggerkitconfigwidget.h
index f2ab06695f..e126f513f9 100644
--- a/src/plugins/debugger/debuggerkitconfigwidget.h
+++ b/src/plugins/debugger/debuggerkitconfigwidget.h
@@ -30,7 +30,7 @@
#ifndef DEBUGGER_DEBUGGERKITCONFIGWIDGET_H
#define DEBUGGER_DEBUGGERKITCONFIGWIDGET_H
-#include "debuggerkitinformation.h"
+#include "debuggeritemmodel.h"
#include <coreplugin/dialogs/ioptionspage.h>
#include <projectexplorer/kitconfigwidget.h>
@@ -52,52 +52,6 @@ QT_END_NAMESPACE
namespace Debugger {
namespace Internal {
-class DebuggerItemConfigWidget;
-class DebuggerKitConfigWidget;
-
-// -----------------------------------------------------------------------
-// DebuggerItemModel
-//------------------------------------------------------------------------
-class DebuggerItemModel : public QStandardItemModel
-{
- Q_OBJECT
-
-public:
- DebuggerItemModel(QObject *parent);
-
- QModelIndex currentIndex() const;
- QModelIndex lastIndex() const;
- void setCurrentIndex(const QModelIndex &index);
- QVariant currentDebugger() const { return m_currentDebugger; }
- void addDebugger(const DebuggerItem &item);
- void removeDebugger(const QVariant &id);
- void updateDebugger(const QVariant &id);
-
-public slots:
- void markCurrentDirty();
-
-signals:
- void debuggerAdded(const QVariant &id, const QString &display);
- void debuggerUpdated(const QVariant &id, const QString &display);
- void debuggerRemoved(const QVariant &id);
-
-private:
- friend class Debugger::DebuggerKitInformation;
- friend class DebuggerKitConfigWidget;
- friend class DebuggerItemConfigWidget;
- friend class DebuggerOptionsPage;
-
- QStandardItem *currentStandardItem() const;
- QStandardItem *findStandardItemById(const QVariant &id) const;
- QVariant headerData(int section, Qt::Orientation orientation, int role) const;
-
- QVariant m_currentDebugger;
-
- QStandardItem *m_autoRoot;
- QStandardItem *m_manualRoot;
- QStringList removed;
-};
-
// -----------------------------------------------------------------------
// DebuggerKitConfigWidget
// -----------------------------------------------------------------------
@@ -121,8 +75,8 @@ public:
private slots:
void manageDebuggers();
void currentDebuggerChanged(int idx);
- void onDebuggerAdded(const QVariant &id, const QString &displayName);
- void onDebuggerUpdated(const QVariant &id, const QString &displayName);
+ void onDebuggerAdded(const QVariant &id);
+ void onDebuggerUpdated(const QVariant &id);
void onDebuggerRemoved(const QVariant &id);
private:
@@ -135,44 +89,7 @@ private:
QPushButton *m_manageButton;
};
-// --------------------------------------------------------------------------
-// DebuggerOptionsPage
-// --------------------------------------------------------------------------
-
-class DebuggerOptionsPage : public Core::IOptionsPage
-{
- Q_OBJECT
-
-public:
- DebuggerOptionsPage();
-
- QWidget *createPage(QWidget *parent);
- void apply();
- void finish();
- bool matches(const QString &) const;
-
-private slots:
- void debuggerSelectionChanged();
- void debuggerModelChanged();
- void updateState();
- void cloneDebugger();
- void addDebugger();
- void removeDebugger();
-
-private:
- QWidget *m_configWidget;
- QString m_searchKeywords;
-
- DebuggerItemModel *m_model;
- DebuggerItemConfigWidget *m_itemConfigWidget;
- QTreeView *m_debuggerView;
- Utils::DetailsWidget *m_container;
- QPushButton *m_addButton;
- QPushButton *m_cloneButton;
- QPushButton *m_delButton;
-};
-
} // namespace Internal
} // namespace Debugger
-#endif // DEBUGGER_DEBUGGERKITINFORMATION_H
+#endif // DEBUGGER_DEBUGGERKITCONFIGWIDGET_H
diff --git a/src/plugins/debugger/debuggerkitinformation.cpp b/src/plugins/debugger/debuggerkitinformation.cpp
index 30ca4f2c23..7ee98c619d 100644
--- a/src/plugins/debugger/debuggerkitinformation.cpp
+++ b/src/plugins/debugger/debuggerkitinformation.cpp
@@ -28,312 +28,305 @@
****************************************************************************/
#include "debuggerkitinformation.h"
+
+#include "debuggeritemmanager.h"
#include "debuggerkitconfigwidget.h"
-#include <projectexplorer/abi.h>
+#include "projectexplorer/toolchain.h"
+#include "projectexplorer/projectexplorerconstants.h"
+
#include <utils/fileutils.h>
+#include <utils/qtcassert.h>
-#include <QProcess>
+#include <QFileInfo>
-using namespace Debugger::Internal;
using namespace ProjectExplorer;
using namespace Utils;
-static const char DEBUGGER_INFORMATION_COMMAND[] = "Binary";
-static const char DEBUGGER_INFORMATION_DISPLAYNAME[] = "DisplayName";
-static const char DEBUGGER_INFORMATION_ID[] = "Id";
-static const char DEBUGGER_INFORMATION_ENGINETYPE[] = "EngineType";
-static const char DEBUGGER_INFORMATION_AUTODETECTED[] = "AutoDetected";
-static const char DEBUGGER_INFORMATION_ABIS[] = "Abis";
-
namespace Debugger {
// --------------------------------------------------------------------------
-// DebuggerItem
+// DebuggerKitInformation
// --------------------------------------------------------------------------
-DebuggerItem::DebuggerItem()
+DebuggerKitInformation::DebuggerKitInformation()
{
- m_engineType = NoEngineType;
- m_isAutoDetected = false;
+ setObjectName(QLatin1String("DebuggerKitInformation"));
+ setId(DebuggerKitInformation::id());
+ setPriority(28000);
}
-void DebuggerItem::reinitializeFromFile()
+QVariant DebuggerKitInformation::defaultValue(Kit *k) const
{
- QProcess proc;
- proc.start(m_command.toString(), QStringList() << QLatin1String("--version"));
- proc.waitForStarted();
- proc.waitForFinished();
- QByteArray ba = proc.readAll();
- if (ba.contains("gdb")) {
- m_engineType = GdbEngineType;
- const char needle[] = "This GDB was configured as \"";
- // E.g. "--host=i686-pc-linux-gnu --target=arm-unknown-nto-qnx6.5.0".
- // or "i686-linux-gnu"
- int pos1 = ba.indexOf(needle);
- if (pos1 != -1) {
- pos1 += int(sizeof(needle));
- int pos2 = ba.indexOf('"', pos1 + 1);
- QByteArray target = ba.mid(pos1, pos2 - pos1);
- int pos3 = target.indexOf("--target=");
- if (pos3 >= 0)
- target = target.mid(pos3 + 9);
- m_abis.append(Abi::abiFromTargetTriplet(QString::fromLatin1(target)));
+ ToolChain *tc = ToolChainKitInformation::toolChain(k);
+ QTC_ASSERT(tc, return QVariant());
+
+ const Abi toolChainAbi = tc->targetAbi();
+ foreach (const DebuggerItem &item, DebuggerItemManager::debuggers())
+ foreach (const Abi targetAbi, item.abis())
+ if (targetAbi.isCompatibleWith(toolChainAbi))
+ return item.id();
+
+ return QVariant();
+}
+
+void DebuggerKitInformation::setup(Kit *k)
+{
+ // Get one of the available debugger matching the kit's toolchain.
+ const ToolChain *tc = ToolChainKitInformation::toolChain(k);
+ const Abi toolChainAbi = tc ? tc->targetAbi() : Abi::hostAbi();
+
+ // This can be anything (Id, binary path, "auto")
+ const QVariant rawId = k->value(DebuggerKitInformation::id());
+
+ enum {
+ NotDetected, DetectedAutomatically, DetectedByFile, DetectedById
+ } detection = NotDetected;
+ DebuggerEngineType autoEngine = NoEngineType;
+ FileName fileName;
+
+ // With 3.0 we have:
+ // <value type="QString" key="Debugger.Information">{75ecf347-f221-44c3-b613-ea1d29929cd4}</value>
+ // Before we had:
+ // <valuemap type="QVariantMap" key="Debugger.Information">
+ // <value type="QString" key="Binary">/data/dev/debugger/gdb-git/gdb/gdb</value>
+ // <value type="int" key="EngineType">1</value>
+ // </valuemap>
+ // Or for force auto-detected CDB
+ // <valuemap type="QVariantMap" key="Debugger.Information">
+ // <value type="QString" key="Binary">auto</value>
+ // <value type="int" key="EngineType">4</value>
+ // </valuemap>
+
+ if (rawId.isNull()) {
+ // Initial setup of a kit
+ detection = NotDetected;
+ } else if (rawId.type() == QVariant::String) {
+ detection = DetectedById;
+ } else {
+ QMap<QString, QVariant> map = rawId.toMap();
+ QString binary = map.value(QLatin1String("Binary")).toString();
+ if (binary == QLatin1String("auto")) {
+ detection = DetectedAutomatically;
+ autoEngine = DebuggerEngineType(map.value(QLatin1String("EngineType")).toInt());
} else {
- // Fallback.
- m_abis = Abi::abisOfBinary(m_command); // FIXME: Wrong.
+ detection = DetectedByFile;
+ fileName = FileName::fromUserInput(binary);
}
- return;
}
- if (ba.contains("lldb") || ba.startsWith("LLDB")) {
- m_engineType = LldbEngineType;
- m_abis = Abi::abisOfBinary(m_command);
- return;
+
+ const DebuggerItem *bestItem = 0;
+ DebuggerItem::MatchLevel bestLevel = DebuggerItem::DoesNotMatch;
+ foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) {
+ const DebuggerItem *goodItem = 0;
+ if (detection == DetectedById && item.id() == rawId)
+ goodItem = &item;
+ if (detection == DetectedByFile && item.command() == fileName)
+ goodItem = &item;
+ if (detection == DetectedAutomatically && item.engineType() == autoEngine)
+ goodItem = &item;
+
+ if (goodItem) {
+ DebuggerItem::MatchLevel level = goodItem->matchTarget(toolChainAbi);
+ if (level > bestLevel) {
+ bestLevel = level;
+ bestItem = goodItem;
+ }
+ }
}
- if (ba.startsWith("Python")) {
- m_engineType = PdbEngineType;
+
+ // If we have an existing debugger with matching id _and_
+ // matching target ABI we are fine.
+ if (bestItem) {
+ k->setValue(DebuggerKitInformation::id(), bestItem->id());
return;
}
- m_engineType = NoEngineType;
-}
-QString DebuggerItem::engineTypeName() const
-{
- switch (m_engineType) {
- case Debugger::NoEngineType:
- return DebuggerOptionsPage::tr("Not recognized");
- case Debugger::GdbEngineType:
- return QLatin1String("GDB");
- case Debugger::CdbEngineType:
- return QLatin1String("CDB");
- case Debugger::LldbEngineType:
- return QLatin1String("LLDB");
- default:
- return QString();
+ // We didn't find an existing debugger that matched by whatever
+ // data we found in the kit (i.e. no id, filename, "auto")
+ // (or what we found did not match ABI-wise)
+ // Let's try to pick one with matching ABI.
+ QVariant bestId;
+ bestLevel = DebuggerItem::DoesNotMatch;
+ foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) {
+ DebuggerItem::MatchLevel level = item.matchTarget(toolChainAbi);
+ if (level > bestLevel) {
+ bestLevel = level;
+ bestId = item.id();
+ }
}
-}
-QStringList DebuggerItem::abiNames() const
-{
- QStringList list;
- foreach (const Abi &abi, m_abis)
- list.append(abi.toString());
- return list;
+ k->setValue(DebuggerKitInformation::id(), bestId);
}
-QVariantMap DebuggerItem::toMap() const
-{
- QVariantMap data;
- data.insert(QLatin1String(DEBUGGER_INFORMATION_DISPLAYNAME), m_displayName);
- data.insert(QLatin1String(DEBUGGER_INFORMATION_ID), m_id);
- data.insert(QLatin1String(DEBUGGER_INFORMATION_COMMAND), m_command.toUserOutput());
- data.insert(QLatin1String(DEBUGGER_INFORMATION_ENGINETYPE), int(m_engineType));
- data.insert(QLatin1String(DEBUGGER_INFORMATION_AUTODETECTED), m_isAutoDetected);
- data.insert(QLatin1String(DEBUGGER_INFORMATION_ABIS), abiNames());
- return data;
-}
-void DebuggerItem::fromMap(const QVariantMap &data)
+// This handles the upgrade path from 2.8 to 3.0
+void DebuggerKitInformation::fix(Kit *k)
{
- m_command = FileName::fromUserInput(data.value(QLatin1String(DEBUGGER_INFORMATION_COMMAND)).toString());
- m_id = data.value(QLatin1String(DEBUGGER_INFORMATION_ID)).toString();
- m_displayName = data.value(QLatin1String(DEBUGGER_INFORMATION_DISPLAYNAME)).toString();
- m_isAutoDetected = data.value(QLatin1String(DEBUGGER_INFORMATION_AUTODETECTED)).toBool();
- m_engineType = DebuggerEngineType(data.value(QLatin1String(DEBUGGER_INFORMATION_ENGINETYPE)).toInt());
-
- m_abis.clear();
- foreach (const QString &a, data.value(QLatin1String(DEBUGGER_INFORMATION_ABIS)).toStringList()) {
- Abi abi(a);
- if (abi.isValid())
- m_abis.append(abi);
+ // This can be Id, binary path, but not "auto" anymore.
+ const QVariant rawId = k->value(DebuggerKitInformation::id());
+
+ if (rawId.isNull()) // No debugger set, that is fine.
+ return;
+
+ if (rawId.type() == QVariant::String) {
+ if (!DebuggerItemManager::findById(rawId)) {
+ qWarning("Unknown debugger id %s in kit %s",
+ qPrintable(rawId.toString()), qPrintable(k->displayName()));
+ k->setValue(DebuggerKitInformation::id(), QVariant());
+ }
+ return; // All fine (now).
}
-}
-void DebuggerItem::setId(const QVariant &id)
-{
- m_id = id;
+ QMap<QString, QVariant> map = rawId.toMap();
+ QString binary = map.value(QLatin1String("Binary")).toString();
+ if (binary == QLatin1String("auto")) {
+ // This should not happen as "auto" is handled by setup() already.
+ QTC_CHECK(false);
+ k->setValue(DebuggerKitInformation::id(), QVariant());
+ return;
+ }
+
+ FileName fileName = FileName::fromUserInput(binary);
+ const DebuggerItem *item = DebuggerItemManager::findByCommand(fileName);
+ if (!item) {
+ qWarning("Debugger command %s invalid in kit %s",
+ qPrintable(binary), qPrintable(k->displayName()));
+ k->setValue(DebuggerKitInformation::id(), QVariant());
+ return;
+ }
+
+ k->setValue(DebuggerKitInformation::id(), item->id());
}
-void DebuggerItem::setDisplayName(const QString &displayName)
+// Check the configuration errors and return a flag mask. Provide a quick check and
+// a verbose one with a list of errors.
+
+enum DebuggerConfigurationErrors {
+ NoDebugger = 0x1,
+ DebuggerNotFound = 0x2,
+ DebuggerNotExecutable = 0x4,
+ DebuggerNeedsAbsolutePath = 0x8
+};
+
+static unsigned debuggerConfigurationErrors(const Kit *k)
{
- m_displayName = displayName;
+ QTC_ASSERT(k, return NoDebugger);
+
+ const DebuggerItem *item = DebuggerKitInformation::debugger(k);
+ if (!item)
+ return NoDebugger;
+
+ if (item->command().isEmpty())
+ return NoDebugger;
+
+ unsigned result = 0;
+ const QFileInfo fi = item->command().toFileInfo();
+ if (!fi.exists() || fi.isDir())
+ result |= DebuggerNotFound;
+ else if (!fi.isExecutable())
+ result |= DebuggerNotExecutable;
+
+ if (!fi.exists() || fi.isDir()) {
+ if (item->engineType() == NoEngineType)
+ return NoDebugger;
+
+ // We need an absolute path to be able to locate Python on Windows.
+ if (item->engineType() == GdbEngineType)
+ if (const ToolChain *tc = ToolChainKitInformation::toolChain(k))
+ if (tc->targetAbi().os() == Abi::WindowsOS && !fi.isAbsolute())
+ result |= DebuggerNeedsAbsolutePath;
+ }
+ return result;
}
-void DebuggerItem::setEngineType(const DebuggerEngineType &engineType)
+const DebuggerItem *DebuggerKitInformation::debugger(const Kit *kit)
{
- m_engineType = engineType;
+ QTC_ASSERT(kit, return 0);
+ const QVariant id = kit->value(DebuggerKitInformation::id());
+ return DebuggerItemManager::findById(id);
}
-void DebuggerItem::setCommand(const Utils::FileName &command)
+bool DebuggerKitInformation::isValidDebugger(const Kit *k)
{
- m_command = command;
+ return debuggerConfigurationErrors(k) == 0;
}
-void DebuggerItem::setAutoDetected(bool isAutoDetected)
+QList<Task> DebuggerKitInformation::validateDebugger(const Kit *k)
{
- m_isAutoDetected = isAutoDetected;
+ QList<Task> result;
+
+ const unsigned errors = debuggerConfigurationErrors(k);
+ if (!errors)
+ return result;
+
+ QString path;
+ if (const DebuggerItem *item = debugger(k))
+ path = item->command().toUserOutput();
+
+ const Core::Id id = ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM;
+ if (errors & NoDebugger)
+ result << Task(Task::Warning, tr("No debugger set up."), FileName(), -1, id);
+
+ if (errors & DebuggerNotFound)
+ result << Task(Task::Error, tr("Debugger '%1' not found.").arg(path),
+ FileName(), -1, id);
+ if (errors & DebuggerNotExecutable)
+ result << Task(Task::Error, tr("Debugger '%1' not executable.").arg(path), FileName(), -1, id);
+
+ if (errors & DebuggerNeedsAbsolutePath) {
+ const QString message =
+ tr("The debugger location must be given as an "
+ "absolute path (%1).").arg(path);
+ result << Task(Task::Error, message, FileName(), -1, id);
+ }
+ return result;
}
-void DebuggerItem::setAbis(const QList<ProjectExplorer::Abi> &abis)
+KitConfigWidget *DebuggerKitInformation::createConfigWidget(Kit *k) const
{
- m_abis = abis;
+ return new Internal::DebuggerKitConfigWidget(k, this);
}
-void DebuggerItem::setAbi(const Abi &abi)
+KitInformation::ItemList DebuggerKitInformation::toUserOutput(const Kit *k) const
{
- m_abis.clear();
- m_abis.append(abi);
+ return ItemList() << qMakePair(tr("Debugger"), displayString(k));
}
-static DebuggerItem::MatchLevel matchSingle(const Abi &debuggerAbi, const Abi &targetAbi)
+FileName DebuggerKitInformation::debuggerCommand(const ProjectExplorer::Kit *k)
{
- if (debuggerAbi.architecture() != Abi::UnknownArchitecture
- && debuggerAbi.architecture() != targetAbi.architecture())
- return DebuggerItem::DoesNotMatch;
-
- if (debuggerAbi.os() != Abi::UnknownOS
- && debuggerAbi.os() != targetAbi.os())
- return DebuggerItem::DoesNotMatch;
-
- if (debuggerAbi.binaryFormat() != Abi::UnknownFormat
- && debuggerAbi.binaryFormat() != targetAbi.binaryFormat())
- return DebuggerItem::DoesNotMatch;
-
- if (debuggerAbi.os() == Abi::WindowsOS) {
- if (debuggerAbi.osFlavor() == Abi::WindowsMSysFlavor && targetAbi.osFlavor() != Abi::WindowsMSysFlavor)
- return DebuggerItem::DoesNotMatch;
- if (debuggerAbi.osFlavor() != Abi::WindowsMSysFlavor && targetAbi.osFlavor() == Abi::WindowsMSysFlavor)
- return DebuggerItem::DoesNotMatch;
- }
-
- if (debuggerAbi.wordWidth() == 64 && targetAbi.wordWidth() == 32)
- return DebuggerItem::MatchesSomewhat;
- if (debuggerAbi.wordWidth() != 0 && debuggerAbi.wordWidth() != targetAbi.wordWidth())
- return DebuggerItem::DoesNotMatch;
-
- return DebuggerItem::MatchesPerfectly;
+ const DebuggerItem *item = debugger(k);
+ QTC_ASSERT(item, return FileName());
+ return item->command();
}
-DebuggerItem::MatchLevel DebuggerItem::matchTarget(const Abi &targetAbi) const
+DebuggerEngineType DebuggerKitInformation::engineType(const ProjectExplorer::Kit *k)
{
- MatchLevel bestMatch = DoesNotMatch;
- foreach (const Abi &debuggerAbi, m_abis) {
- MatchLevel currentMatch = matchSingle(debuggerAbi, targetAbi);
- if (currentMatch > bestMatch)
- bestMatch = currentMatch;
- }
- return bestMatch;
+ const DebuggerItem *item = debugger(k);
+ QTC_ASSERT(item, return NoEngineType);
+ return item->engineType();
}
-bool Debugger::DebuggerItem::isValid() const
+QString DebuggerKitInformation::displayString(const Kit *k)
{
- return m_engineType != NoEngineType;
+ const DebuggerItem *item = debugger(k);
+ if (!item)
+ return tr("No Debugger");
+ QString binary = item->command().toUserOutput();
+ QString name = tr("%1 Engine").arg(item->engineTypeName());
+ return binary.isEmpty() ? tr("%1 <None>").arg(name) : tr("%1 using \"%2\"").arg(name, binary);
}
-} // namespace Debugger;
-
-#ifdef WITH_TESTS
-
-# include <QTest>
-# include "debuggerplugin.h"
-
-void Debugger::DebuggerPlugin::testDebuggerMatching_data()
+void DebuggerKitInformation::setDebugger(Kit *k, const QVariant &id)
{
- QTest::addColumn<QStringList>("debugger");
- QTest::addColumn<QString>("target");
- QTest::addColumn<int>("result");
-
- QTest::newRow("Invalid data")
- << QStringList()
- << QString()
- << int(DebuggerItem::DoesNotMatch);
- QTest::newRow("Invalid debugger")
- << QStringList()
- << QString::fromLatin1("x86-linux-generic-elf-32bit")
- << int(DebuggerItem::DoesNotMatch);
- QTest::newRow("Invalid target")
- << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
- << QString()
- << int(DebuggerItem::DoesNotMatch);
-
- QTest::newRow("Fuzzy match 1")
- << (QStringList() << QLatin1String("unknown-unknown-unknown-unknown-0bit"))
- << QString::fromLatin1("x86-linux-generic-elf-32bit")
- << int(DebuggerItem::MatchesPerfectly); // Is this the expected behavior?
- QTest::newRow("Fuzzy match 2")
- << (QStringList() << QLatin1String("unknown-unknown-unknown-unknown-0bit"))
- << QString::fromLatin1("arm-windows-msys-pe-64bit")
- << int(DebuggerItem::MatchesPerfectly); // Is this the expected behavior?
-
- QTest::newRow("Architecture mismatch")
- << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
- << QString::fromLatin1("arm-linux-generic-elf-32bit")
- << int(DebuggerItem::DoesNotMatch);
- QTest::newRow("OS mismatch")
- << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
- << QString::fromLatin1("x86-macosx-generic-elf-32bit")
- << int(DebuggerItem::DoesNotMatch);
- QTest::newRow("Format mismatch")
- << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
- << QString::fromLatin1("x86-linux-generic-pe-32bit")
- << int(DebuggerItem::DoesNotMatch);
-
- QTest::newRow("Linux perfect match")
- << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
- << QString::fromLatin1("x86-linux-generic-elf-32bit")
- << int(DebuggerItem::MatchesPerfectly);
- QTest::newRow("Linux match")
- << (QStringList() << QLatin1String("x86-linux-generic-elf-64bit"))
- << QString::fromLatin1("x86-linux-generic-elf-32bit")
- << int(DebuggerItem::MatchesSomewhat);
-
- QTest::newRow("Windows perfect match 1")
- << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
- << QString::fromLatin1("x86-windows-msvc2013-pe-64bit")
- << int(DebuggerItem::MatchesPerfectly);
- QTest::newRow("Windows perfect match 2")
- << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
- << QString::fromLatin1("x86-windows-msvc2012-pe-64bit")
- << int(DebuggerItem::MatchesPerfectly);
- QTest::newRow("Windows match 1")
- << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
- << QString::fromLatin1("x86-windows-msvc2013-pe-32bit")
- << int(DebuggerItem::MatchesSomewhat);
- QTest::newRow("Windows match 2")
- << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
- << QString::fromLatin1("x86-windows-msvc2012-pe-32bit")
- << int(DebuggerItem::MatchesSomewhat);
- QTest::newRow("Windows mismatch on word size")
- << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-32bit"))
- << QString::fromLatin1("x86-windows-msvc2013-pe-64bit")
- << int(DebuggerItem::DoesNotMatch);
- QTest::newRow("Windows mismatch on osflavor 1")
- << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-32bit"))
- << QString::fromLatin1("x86-windows-msys-pe-64bit")
- << int(DebuggerItem::DoesNotMatch);
- QTest::newRow("Windows mismatch on osflavor 2")
- << (QStringList() << QLatin1String("x86-windows-msys-pe-32bit"))
- << QString::fromLatin1("x86-windows-msvc2010-pe-64bit")
- << int(DebuggerItem::DoesNotMatch);
+ // Only register reasonably complete debuggers.
+ QTC_ASSERT(DebuggerItemManager::findById(id), return);
+ k->setValue(DebuggerKitInformation::id(), id);
}
-void Debugger::DebuggerPlugin::testDebuggerMatching()
+Core::Id DebuggerKitInformation::id()
{
- QFETCH(QStringList, debugger);
- QFETCH(QString, target);
- QFETCH(int, result);
-
- DebuggerItem::MatchLevel expectedLevel = static_cast<DebuggerItem::MatchLevel>(result);
-
- QList<Abi> debuggerAbis;
- foreach (const QString &abi, debugger)
- debuggerAbis << Abi(abi);
-
- DebuggerItem item;
- item.setAbis(debuggerAbis);
-
- DebuggerItem::MatchLevel level = item.matchTarget(Abi(target));
-
- QCOMPARE(expectedLevel, level);
+ return "Debugger.Information";
}
-#endif
+
+} // namespace Debugger
diff --git a/src/plugins/debugger/debuggerkitinformation.h b/src/plugins/debugger/debuggerkitinformation.h
index dfdf6350a4..3e03e19d2e 100644
--- a/src/plugins/debugger/debuggerkitinformation.h
+++ b/src/plugins/debugger/debuggerkitinformation.h
@@ -32,6 +32,7 @@
#include "debugger_global.h"
#include "debuggerconstants.h"
+#include "debuggeritem.h"
#include <projectexplorer/abi.h>
#include <projectexplorer/kitinformation.h>
@@ -40,106 +41,6 @@
namespace Debugger {
-namespace Internal { class DebuggerItemModel; }
-
-// -----------------------------------------------------------------------
-// DebuggerItem
-// -----------------------------------------------------------------------
-
-class DEBUGGER_EXPORT DebuggerItem
-{
-public:
- DebuggerItem();
-
- bool canClone() const { return true; }
- bool isValid() const;
- QString engineTypeName() const;
-
- QVariantMap toMap() const;
- void fromMap(const QVariantMap &data);
- void reinitializeFromFile();
-
- QVariant id() const { return m_id; }
-
- QString displayName() const { return m_displayName; }
- void setDisplayName(const QString &displayName);
-
- DebuggerEngineType engineType() const { return m_engineType; }
- void setEngineType(const DebuggerEngineType &engineType);
-
- Utils::FileName command() const { return m_command; }
- void setCommand(const Utils::FileName &command);
-
- bool isAutoDetected() const { return m_isAutoDetected; }
- void setAutoDetected(bool isAutoDetected);
-
- QList<ProjectExplorer::Abi> abis() const { return m_abis; }
- void setAbis(const QList<ProjectExplorer::Abi> &abis);
- void setAbi(const ProjectExplorer::Abi &abi);
-
- enum MatchLevel { DoesNotMatch, MatchesSomewhat, MatchesPerfectly };
- MatchLevel matchTarget(const ProjectExplorer::Abi &targetAbi) const;
-
- QStringList abiNames() const;
-
-private:
- friend class Debugger::Internal::DebuggerItemModel;
- friend class DebuggerItemManager;
- void setId(const QVariant &id);
-
- QVariant m_id;
- QString m_displayName;
- DebuggerEngineType m_engineType;
- Utils::FileName m_command;
- bool m_isAutoDetected;
- QList<ProjectExplorer::Abi> m_abis;
-};
-
-// -----------------------------------------------------------------------
-// DebuggerItemManager
-// -----------------------------------------------------------------------
-
-class DEBUGGER_EXPORT DebuggerItemManager : public QObject
-{
- Q_OBJECT
-
-public:
- static QObject *instance();
- ~DebuggerItemManager();
-
- static QList<DebuggerItem> debuggers();
- static Debugger::Internal::DebuggerItemModel *model();
-
- static QVariant registerDebugger(const DebuggerItem &item);
- static void deregisterDebugger(const DebuggerItem &item);
-
- static const DebuggerItem *findByCommand(const Utils::FileName &command);
- static const DebuggerItem *findById(const QVariant &id);
-
- static void restoreDebuggers();
- static QString uniqueDisplayName(const QString &base);
- static void setItemData(const QVariant &id, const QString& displayName, const Utils::FileName &fileName);
-
- static void removeDebugger(const QVariant &id);
- static QVariant addDebugger(const DebuggerItem &item);
-
-public slots:
- void saveDebuggers();
-
-private:
- explicit DebuggerItemManager(QObject *parent = 0);
- static void autoDetectGdbOrLldbDebuggers();
- static void autoDetectCdbDebuggers();
- static void readLegacyDebuggers();
-
- static Utils::PersistentSettingsWriter *m_writer;
- static QList<DebuggerItem> m_debuggers;
- static Debugger::Internal::DebuggerItemModel *m_model;
-
- friend class Internal::DebuggerItemModel;
- friend class DebuggerPlugin; // Enable constrcutor for DebuggerPlugin
-};
-
class DEBUGGER_EXPORT DebuggerKitInformation : public ProjectExplorer::KitInformation
{
Q_OBJECT
diff --git a/src/plugins/debugger/debuggeroptionspage.cpp b/src/plugins/debugger/debuggeroptionspage.cpp
new file mode 100644
index 0000000000..884edf439f
--- /dev/null
+++ b/src/plugins/debugger/debuggeroptionspage.cpp
@@ -0,0 +1,337 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "debuggeroptionspage.h"
+
+#include "debuggeritemmanager.h"
+#include "debuggeritemmodel.h"
+
+#include <projectexplorer/projectexplorerconstants.h>
+
+#include <utils/detailswidget.h>
+#include <utils/pathchooser.h>
+#include <utils/qtcassert.h>
+
+#include <QFormLayout>
+#include <QHeaderView>
+#include <QLabel>
+#include <QLineEdit>
+#include <QObject>
+#include <QPushButton>
+#include <QTreeView>
+#include <QWidget>
+
+using namespace Utils;
+
+namespace Debugger {
+namespace Internal {
+
+static const char debuggingToolsWikiLinkC[] = "http://qt-project.org/wiki/Qt_Creator_Windows_Debugging";
+
+// -----------------------------------------------------------------------
+// DebuggerItemConfigWidget
+// -----------------------------------------------------------------------
+
+class DebuggerItemConfigWidget : public QWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::DebuggerItemConfigWidget)
+
+public:
+ explicit DebuggerItemConfigWidget(DebuggerItemModel *model);
+ void setItem(const DebuggerItem &item);
+ void apply();
+
+private:
+ QLineEdit *m_displayNameLineEdit;
+ QLabel *m_cdbLabel;
+ PathChooser *m_binaryChooser;
+ QLineEdit *m_abis;
+ DebuggerItemModel *m_model;
+};
+
+DebuggerItemConfigWidget::DebuggerItemConfigWidget(DebuggerItemModel *model) :
+ m_model(model)
+{
+ QTC_CHECK(model);
+
+ m_displayNameLineEdit = new QLineEdit(this);
+
+ m_binaryChooser = new PathChooser(this);
+ m_binaryChooser->setExpectedKind(PathChooser::ExistingCommand);
+ m_binaryChooser->setMinimumWidth(400);
+ m_binaryChooser->setHistoryCompleter(QLatin1String("DebuggerPaths"));
+
+ m_cdbLabel = new QLabel(this);
+ m_cdbLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ m_cdbLabel->setOpenExternalLinks(true);
+
+ m_abis = new QLineEdit(this);
+ m_abis->setEnabled(false);
+
+ QFormLayout *formLayout = new QFormLayout(this);
+ formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
+ formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit);
+// formLayout->addRow(new QLabel(tr("Type:")), m_engineTypeComboBox);
+ formLayout->addRow(m_cdbLabel);
+ formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser);
+ formLayout->addRow(new QLabel(tr("ABIs:")), m_abis);
+}
+
+void DebuggerItemConfigWidget::setItem(const DebuggerItem &item)
+{
+ m_displayNameLineEdit->setEnabled(!item.isAutoDetected());
+ m_displayNameLineEdit->setText(item.displayName());
+
+ m_binaryChooser->setEnabled(!item.isAutoDetected());
+ m_binaryChooser->setFileName(item.command());
+
+ QString text;
+ QString versionCommand;
+ if (item.engineType() == CdbEngineType) {
+#ifdef Q_OS_WIN
+ const bool is64bit = winIs64BitSystem();
+#else
+ const bool is64bit = false;
+#endif
+ const QString versionString = is64bit ? tr("64-bit version") : tr("32-bit version");
+ //: Label text for path configuration. %2 is "x-bit version".
+ text = tr("<html><body><p>Specify the path to the "
+ "<a href=\"%1\">Windows Console Debugger executable</a>"
+ " (%2) here.</p>""</body></html>").
+ arg(QLatin1String(debuggingToolsWikiLinkC), versionString);
+ versionCommand = QLatin1String("-version");
+ } else {
+ versionCommand = QLatin1String("--version");
+ }
+
+ m_cdbLabel->setText(text);
+ m_cdbLabel->setVisible(!text.isEmpty());
+ m_binaryChooser->setCommandVersionArguments(QStringList(versionCommand));
+
+ m_abis->setText(item.abiNames().join(QLatin1String(", ")));
+}
+
+void DebuggerItemConfigWidget::apply()
+{
+ DebuggerItem item = m_model->currentDebugger();
+ QTC_ASSERT(item.isValid(), return);
+
+ item.setDisplayName(m_displayNameLineEdit->text());
+ item.setCommand(m_binaryChooser->fileName());
+ item.reinitializeFromFile();
+ m_model->updateDebugger(item);
+}
+
+// --------------------------------------------------------------------------
+// DebuggerOptionsPage
+// --------------------------------------------------------------------------
+
+DebuggerOptionsPage::DebuggerOptionsPage()
+{
+ m_model = 0;
+ m_debuggerView = 0;
+ m_container = 0;
+ m_addButton = 0;
+ m_cloneButton = 0;
+ m_delButton = 0;
+
+ setId(ProjectExplorer::Constants::DEBUGGER_SETTINGS_PAGE_ID);
+ setDisplayName(tr("Debuggers"));
+ setCategory(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY);
+ setDisplayCategory(QCoreApplication::translate("ProjectExplorer",
+ ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_TR_CATEGORY));
+ setCategoryIcon(QLatin1String(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY_ICON));
+}
+
+QWidget *DebuggerOptionsPage::createPage(QWidget *parent)
+{
+ m_configWidget = new QWidget(parent);
+
+ m_addButton = new QPushButton(tr("Add"), m_configWidget);
+ m_cloneButton = new QPushButton(tr("Clone"), m_configWidget);
+ m_delButton = new QPushButton(tr("Remove"), m_configWidget);
+
+ m_container = new DetailsWidget(m_configWidget);
+ m_container->setState(DetailsWidget::NoSummary);
+ m_container->setVisible(false);
+
+ m_model = new DebuggerItemModel(parent);
+
+ m_debuggerView = new QTreeView(m_configWidget);
+ m_debuggerView->setModel(m_model);
+ m_debuggerView->setUniformRowHeights(true);
+ m_debuggerView->setSelectionMode(QAbstractItemView::SingleSelection);
+ m_debuggerView->setSelectionBehavior(QAbstractItemView::SelectRows);
+ m_debuggerView->expandAll();
+
+ QHeaderView *header = m_debuggerView->header();
+ header->setStretchLastSection(false);
+ header->setResizeMode(0, QHeaderView::ResizeToContents);
+ header->setResizeMode(1, QHeaderView::ResizeToContents);
+ header->setResizeMode(2, QHeaderView::Stretch);
+
+ QVBoxLayout *buttonLayout = new QVBoxLayout();
+ buttonLayout->setSpacing(6);
+ buttonLayout->setContentsMargins(0, 0, 0, 0);
+ buttonLayout->addWidget(m_addButton);
+ buttonLayout->addWidget(m_cloneButton);
+ buttonLayout->addWidget(m_delButton);
+ buttonLayout->addItem(new QSpacerItem(10, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
+
+ QVBoxLayout *verticalLayout = new QVBoxLayout();
+ verticalLayout->addWidget(m_debuggerView);
+ verticalLayout->addWidget(m_container);
+
+ QHBoxLayout *horizontalLayout = new QHBoxLayout(m_configWidget);
+ horizontalLayout->addLayout(verticalLayout);
+ horizontalLayout->addLayout(buttonLayout);
+
+ connect(m_debuggerView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
+ this, SLOT(debuggerSelectionChanged()));
+
+ connect(m_addButton, SIGNAL(clicked()), this, SLOT(addDebugger()), Qt::QueuedConnection);
+ connect(m_cloneButton, SIGNAL(clicked()), this, SLOT(cloneDebugger()), Qt::QueuedConnection);
+ connect(m_delButton, SIGNAL(clicked()), this, SLOT(removeDebugger()), Qt::QueuedConnection);
+
+ m_searchKeywords = tr("Debuggers");
+
+ m_itemConfigWidget = new DebuggerItemConfigWidget(m_model);
+ m_container->setWidget(m_itemConfigWidget);
+
+ updateState();
+
+ return m_configWidget;
+}
+
+void DebuggerOptionsPage::apply()
+{
+ m_itemConfigWidget->apply();
+ m_model->apply();
+}
+
+void DebuggerOptionsPage::cloneDebugger()
+{
+ DebuggerItem item = m_model->currentDebugger();
+ if (!item.isValid())
+ return;
+
+ DebuggerItem newItem;
+ newItem.setCommand(item.command());
+ newItem.setEngineType(item.engineType());
+ newItem.setAbis(item.abis());
+ newItem.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("Clone of %1").arg(item.displayName())));
+ newItem.setAutoDetected(false);
+ m_model->addDebugger(newItem);
+ m_debuggerView->setCurrentIndex(m_model->lastIndex());
+}
+
+void DebuggerOptionsPage::addDebugger()
+{
+ DebuggerItem item;
+ item.setEngineType(NoEngineType);
+ item.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("New Debugger")));
+ item.setAutoDetected(false);
+ m_model->addDebugger(item);
+ m_debuggerView->setCurrentIndex(m_model->lastIndex());
+}
+
+void DebuggerOptionsPage::removeDebugger()
+{
+ QVariant id = m_model->currentDebuggerId();
+ m_model->removeDebugger(id);
+ m_debuggerView->setCurrentIndex(m_model->lastIndex());
+}
+
+void DebuggerOptionsPage::finish()
+{
+ // Deleted by settingsdialog.
+ m_configWidget = 0;
+
+ // Children of m_configWidget.
+ m_container = 0;
+ m_debuggerView = 0;
+ m_addButton = 0;
+ m_cloneButton = 0;
+ m_delButton = 0;
+}
+
+bool DebuggerOptionsPage::matches(const QString &s) const
+{
+ return m_searchKeywords.contains(s, Qt::CaseInsensitive);
+}
+
+void DebuggerOptionsPage::debuggerSelectionChanged()
+{
+ QTC_ASSERT(m_container, return);
+
+ QModelIndex mi = m_debuggerView->currentIndex();
+ mi = mi.sibling(mi.row(), 0);
+ m_model->setCurrentIndex(mi);
+
+ DebuggerItem item = m_model->currentDebugger();
+
+ m_itemConfigWidget->setItem(item);
+ m_container->setVisible(item.isValid());
+ updateState();
+}
+
+void DebuggerOptionsPage::debuggerModelChanged()
+{
+ QTC_ASSERT(m_container, return);
+
+ QVariant id = m_model->currentDebuggerId();
+ const DebuggerItem *item = DebuggerItemManager::findById(id);
+ if (!item)
+ return;
+
+ m_itemConfigWidget->setItem(*item);
+ m_container->setVisible(m_model->currentDebuggerId().isValid());
+ m_debuggerView->setCurrentIndex(m_model->currentIndex());
+ updateState();
+}
+
+void DebuggerOptionsPage::updateState()
+{
+ if (!m_cloneButton)
+ return;
+
+ bool canCopy = false;
+ bool canDelete = false;
+
+ DebuggerItem item = m_model->currentDebugger();
+
+ canCopy = item.isValid() && item.canClone();
+ canDelete = !item.isAutoDetected();
+
+ m_cloneButton->setEnabled(canCopy);
+ m_delButton->setEnabled(canDelete);
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/debuggeroptionspage.h b/src/plugins/debugger/debuggeroptionspage.h
new file mode 100644
index 0000000000..fd1782f4b4
--- /dev/null
+++ b/src/plugins/debugger/debuggeroptionspage.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef DEBUGGER_DEBUGGEROPTIONSPAGE_H
+#define DEBUGGER_DEBUGGEROPTIONSPAGE_H
+
+#include <coreplugin/dialogs/ioptionspage.h>
+
+QT_BEGIN_NAMESPACE
+class QPushButton;
+class QTreeView;
+class QWidget;
+QT_END_NAMESPACE
+
+namespace Utils { class DetailsWidget; }
+
+namespace Debugger {
+namespace Internal {
+
+class DebuggerItemModel;
+class DebuggerItemConfigWidget;
+class DebuggerKitConfigWidget;
+
+// --------------------------------------------------------------------------
+// DebuggerOptionsPage
+// --------------------------------------------------------------------------
+
+class DebuggerOptionsPage : public Core::IOptionsPage
+{
+ Q_OBJECT
+
+public:
+ DebuggerOptionsPage();
+
+ QWidget *createPage(QWidget *parent);
+ void apply();
+ void finish();
+ bool matches(const QString &) const;
+
+private slots:
+ void debuggerSelectionChanged();
+ void debuggerModelChanged();
+ void updateState();
+ void cloneDebugger();
+ void addDebugger();
+ void removeDebugger();
+
+private:
+ QWidget *m_configWidget;
+ QString m_searchKeywords;
+
+ DebuggerItemModel *m_model;
+ DebuggerItemConfigWidget *m_itemConfigWidget;
+ QTreeView *m_debuggerView;
+ Utils::DetailsWidget *m_container;
+ QPushButton *m_addButton;
+ QPushButton *m_cloneButton;
+ QPushButton *m_delButton;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_DEBUGGEROPTIONSPAGE_H
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index a01bdc9b63..67953afcfc 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -36,11 +36,13 @@
#include "debuggerkitconfigwidget.h"
#include "debuggerdialogs.h"
#include "debuggerengine.h"
+#include "debuggeritemmanager.h"
#include "debuggermainwindow.h"
#include "debuggerrunner.h"
#include "debuggerrunconfigurationaspect.h"
#include "debuggerruncontrolfactory.h"
#include "debuggerstringutils.h"
+#include "debuggeroptionspage.h"
#include "debuggerkitinformation.h"
#include "memoryagent.h"
#include "breakhandler.h"
diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp
index a7d33fdb5e..59c2158dcf 100644
--- a/src/plugins/debugger/debuggerrunner.cpp
+++ b/src/plugins/debugger/debuggerrunner.cpp
@@ -43,7 +43,6 @@
#ifdef Q_OS_WIN
# include "shared/peutils.h"
-# include <utils/winutils.h>
#endif
#include <projectexplorer/localapplicationrunconfiguration.h> // For LocalApplication*
@@ -55,6 +54,7 @@
#include <projectexplorer/taskhub.h>
#include <utils/checkablemessagebox.h>
+#include <utils/fileutils.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <coreplugin/icore.h>
@@ -344,12 +344,9 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu
if (!fillParameters(&sp, kit, errorMessage))
return sp;
sp.environment = environment->environment();
- sp.workingDirectory = rc->workingDirectory();
-#if defined(Q_OS_WIN)
- // Work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch' ...)
- sp.workingDirectory = normalizePathName(sp.workingDirectory);
-#endif
+ // Normalize to work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch'...)
+ sp.workingDirectory = FileUtils::normalizePathName(rc->workingDirectory());
sp.executable = rc->executable();
if (sp.executable.isEmpty())
@@ -385,7 +382,7 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu
|| server.listen(QHostAddress::LocalHostIPv6);
if (!canListen) {
if (errorMessage)
- *errorMessage = DebuggerPlugin::tr("Not enough free ports for QML debugging. ");
+ *errorMessage = DebuggerPlugin::tr("Not enough free ports for QML debugging.") + QLatin1Char(' ');
return sp;
}
sp.qmlServerAddress = server.serverAddress().toString();
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 7e8febf779..9341d1d74e 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -277,7 +277,7 @@ QString GdbEngine::errorMessage(QProcess::ProcessError error)
return tr("The gdb process failed to start. Either the "
"invoked program \"%1\" is missing, or you may have insufficient "
"permissions to invoke the program.\n%2")
- .arg(m_gdb, gdbProc()->errorString());
+ .arg(m_gdb, m_gdbProc->errorString());
case QProcess::Crashed:
if (targetState() == DebuggerFinished)
return tr("The gdb process crashed some time after starting "
@@ -296,15 +296,10 @@ QString GdbEngine::errorMessage(QProcess::ProcessError error)
return tr("An error occurred when attempting to read from "
"the gdb process. For example, the process may not be running.");
default:
- return tr("An unknown error in the gdb process occurred. ");
+ return tr("An unknown error in the gdb process occurred.");
}
}
-GdbProcess *GdbEngine::gdbProc() const
-{
- return m_gdbProc;
-}
-
#if 0
static void dump(const char *first, const char *middle, const QString & to)
{
@@ -338,7 +333,7 @@ static inline QString msgWinException(const QByteArray &data, unsigned *exCodeIn
const quint64 address = data.mid(addressPos).trimmed().toULongLong(0, 0);
QString rc;
QTextStream str(&rc);
- str << GdbEngine::tr("An exception was triggered: ");
+ str << GdbEngine::tr("An exception was triggered:") << ' ';
formatWindowsException(exCode, address, 0, 0, 0, str);
str << '.';
return rc;
@@ -794,7 +789,7 @@ void GdbEngine::handleResponse(const QByteArray &buff)
void GdbEngine::readGdbStandardError()
{
- QByteArray err = gdbProc()->readAllStandardError();
+ QByteArray err = m_gdbProc->readAllStandardError();
showMessage(_("UNEXPECTED GDB STDERR: " + err));
if (err == "Undefined command: \"bb\". Try \"help\".\n")
return;
@@ -810,7 +805,7 @@ void GdbEngine::readGdbStandardOutput()
int newstart = 0;
int scan = m_inbuffer.size();
- QByteArray out = gdbProc()->readAllStandardOutput();
+ QByteArray out = m_gdbProc->readAllStandardOutput();
m_inbuffer.append(out);
// This can trigger when a dialog starts a nested event loop.
@@ -974,7 +969,7 @@ void GdbEngine::flushCommand(const GdbCommand &cmd0)
return;
}
- QTC_ASSERT(gdbProc()->state() == QProcess::Running, return);
+ QTC_ASSERT(m_gdbProc->state() == QProcess::Running, return);
const int token = ++currentToken();
@@ -1055,7 +1050,7 @@ void GdbEngine::commandTimeout()
if (mb->exec() == QMessageBox::Ok) {
showMessage(_("KILLING DEBUGGER AS REQUESTED BY USER"));
// This is an undefined state, so we just pull the emergency brake.
- gdbProc()->kill();
+ m_gdbProc->kill();
} else {
showMessage(_("CONTINUE DEBUGGER AS REQUESTED BY USER"));
}
@@ -2044,9 +2039,9 @@ void GdbEngine::notifyAdapterShutdownOk()
{
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
showMessage(_("INITIATE GDBENGINE SHUTDOWN IN STATE %1, PROC: %2")
- .arg(lastGoodState()).arg(gdbProc()->state()));
+ .arg(lastGoodState()).arg(m_gdbProc->state()));
m_commandsDoneCallback = 0;
- switch (gdbProc()->state()) {
+ switch (m_gdbProc->state()) {
case QProcess::Running:
postCommand("-gdb-exit", GdbEngine::ExitRequest, CB(handleGdbExit));
break;
@@ -2056,7 +2051,7 @@ void GdbEngine::notifyAdapterShutdownOk()
break;
case QProcess::Starting:
showMessage(_("GDB NOT REALLY RUNNING; KILLING IT"));
- gdbProc()->kill();
+ m_gdbProc->kill();
notifyEngineShutdownFailed();
break;
}
@@ -2073,7 +2068,7 @@ void GdbEngine::handleGdbExit(const GdbResponse &response)
QString::fromLocal8Bit(response.data["msg"].data()));
qDebug() << (_("GDB WON'T EXIT (%1); KILLING IT").arg(msg));
showMessage(_("GDB WON'T EXIT (%1); KILLING IT").arg(msg));
- gdbProc()->kill();
+ m_gdbProc->kill();
}
}
@@ -4758,7 +4753,7 @@ void GdbEngine::startGdb(const QStringList &args)
foreach (int test, m_testCases)
showMessage(_("ENABLING TEST CASE: " + QByteArray::number(test)));
- gdbProc()->disconnect(); // From any previous runs
+ m_gdbProc->disconnect(); // From any previous runs
const DebuggerStartParameters &sp = startParameters();
m_gdb = gdbBinary(sp);
@@ -4783,19 +4778,19 @@ void GdbEngine::startGdb(const QStringList &args)
}
gdbArgs += args;
- connect(gdbProc(), SIGNAL(error(QProcess::ProcessError)),
+ connect(m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
SLOT(handleGdbError(QProcess::ProcessError)));
- connect(gdbProc(), SIGNAL(finished(int,QProcess::ExitStatus)),
+ connect(m_gdbProc, SIGNAL(finished(int,QProcess::ExitStatus)),
SLOT(handleGdbFinished(int,QProcess::ExitStatus)));
- connect(gdbProc(), SIGNAL(readyReadStandardOutput()),
+ connect(m_gdbProc, SIGNAL(readyReadStandardOutput()),
SLOT(readGdbStandardOutput()));
- connect(gdbProc(), SIGNAL(readyReadStandardError()),
+ connect(m_gdbProc, SIGNAL(readyReadStandardError()),
SLOT(readGdbStandardError()));
showMessage(_("STARTING ") + m_gdb + _(" ") + gdbArgs.join(_(" ")));
- gdbProc()->start(m_gdb, gdbArgs);
+ m_gdbProc->start(m_gdb, gdbArgs);
- if (!gdbProc()->waitForStarted()) {
+ if (!m_gdbProc->waitForStarted()) {
handleGdbStartFailed();
const QString msg = errorMessage(QProcess::FailedToStart);
handleAdapterStartFailed(msg);
@@ -5009,7 +5004,7 @@ void GdbEngine::handleGdbError(QProcess::ProcessError error)
case QProcess::WriteError:
case QProcess::Timedout:
default:
- //gdbProc()->kill();
+ //m_gdbProc->kill();
//notifyEngineIll();
showMessageBox(QMessageBox::Critical, tr("GDB I/O Error"), msg);
break;
@@ -5050,8 +5045,8 @@ void GdbEngine::abortDebugger()
if (targetState() == DebuggerFinished) {
// We already tried. Try harder.
showMessage(_("ABORTING DEBUGGER. SECOND TIME."));
- QTC_ASSERT(gdbProc(), return);
- gdbProc()->kill();
+ QTC_ASSERT(m_gdbProc, return);
+ m_gdbProc->kill();
} else {
// Be friendly the first time. This will change targetState().
showMessage(_("ABORTING DEBUGGER. FIRST TIME."));
@@ -5215,7 +5210,7 @@ void GdbEngine::handleBreakOnQFatal(const GdbResponse &response)
void GdbEngine::notifyInferiorSetupFailed(const QString &msg)
{
- showStatusMessage(tr("Failed to start application: ") + msg);
+ showStatusMessage(tr("Failed to start application:") + QLatin1Char(' ') + msg);
if (state() == EngineSetupFailed) {
showMessage(_("INFERIOR START FAILED, BUT ADAPTER DIED ALREADY"));
return; // Adapter crashed meanwhile, so this notification is meaningless.
@@ -5240,7 +5235,7 @@ void GdbEngine::handleAdapterCrashed(const QString &msg)
notifyEngineIll();
// No point in being friendly here ...
- gdbProc()->kill();
+ m_gdbProc->kill();
if (!msg.isEmpty())
showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), msg);
@@ -5385,7 +5380,7 @@ bool GdbEngine::attemptQuickStart() const
void GdbEngine::write(const QByteArray &data)
{
- gdbProc()->write(data);
+ m_gdbProc->write(data);
}
bool GdbEngine::prepareCommand()
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index fd278d51ae..592be2b0a9 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -649,7 +649,6 @@ protected:
// Convenience Functions
//
QString errorMessage(QProcess::ProcessError error);
- GdbProcess *gdbProc() const;
void showExecutionError(const QString &message);
static QByteArray tooltipIName(const QString &exp);
diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp
index 9526e5e608..46dfd62aef 100644
--- a/src/plugins/debugger/lldb/lldbengine.cpp
+++ b/src/plugins/debugger/lldb/lldbengine.cpp
@@ -110,8 +110,8 @@ void LldbEngine::runCommand(const Command &command)
QTC_ASSERT(m_lldbProc.state() == QProcess::Running, notifyEngineIll());
++m_lastToken;
QByteArray token = QByteArray::number(m_lastToken);
- QByteArray cmd = "db {'cmd':'" + command.function + "',"
- + command.args + "'token':" + token + "}\n";
+ QByteArray cmd = "{\"cmd\":\"" + command.function + "\","
+ + command.args + "\"token\":" + token + "}\n";
showMessage(_(token + cmd), LogInput);
m_lldbProc.write(cmd);
}
@@ -156,7 +156,7 @@ void LldbEngine::setupEngine()
m_lldbProc.start(_("python"), args);
if (!m_lldbProc.waitForStarted()) {
- const QString msg = tr("Unable to start LLDB '%1': %2")
+ const QString msg = tr("Unable to start LLDB \"%1\": %2")
.arg(m_lldbCmd, m_lldbProc.errorString());
notifyEngineSetupFailed();
showMessage(_("ADAPTER START FAILED"));
@@ -645,7 +645,7 @@ bool LldbEngine::setToolTipExpression(const QPoint &mousePos,
}
if (!hasLetterOrNumber(exp)) {
- QToolTip::showText(m_toolTipPos, tr("'%1' contains no identifier.").arg(exp));
+ QToolTip::showText(m_toolTipPos, tr("\"%1\" contains no identifier.").arg(exp));
return true;
}
@@ -665,7 +665,7 @@ bool LldbEngine::setToolTipExpression(const QPoint &mousePos,
if (hasSideEffects(exp)) {
QToolTip::showText(m_toolTipPos,
- tr("Cowardly refusing to evaluate expression '%1' "
+ tr("Cowardly refusing to evaluate expression \"%1\" "
"with potential side effects.").arg(exp));
return true;
}
@@ -794,7 +794,7 @@ QString LldbEngine::errorMessage(QProcess::ProcessError error) const
switch (error) {
case QProcess::FailedToStart:
return tr("The LLDB process failed to start. Either the "
- "invoked program '%1' is missing, or you may have insufficient "
+ "invoked program \"%1\" is missing, or you may have insufficient "
"permissions to invoke the program.")
.arg(m_lldbCmd);
case QProcess::Crashed:
@@ -812,7 +812,7 @@ QString LldbEngine::errorMessage(QProcess::ProcessError error) const
return tr("An error occurred when attempting to read from "
"the Lldb process. For example, the process may not be running.");
default:
- return tr("An unknown error in the Lldb process occurred. ");
+ return tr("An unknown error in the Lldb process occurred.") + QLatin1Char(' ');
}
}
@@ -836,15 +836,14 @@ void LldbEngine::readLldbStandardError()
void LldbEngine::readLldbStandardOutput()
{
QByteArray out = m_lldbProc.readAllStandardOutput();
- //showMessage(_("Lldb stdout: " + out));
- showMessage(_(out), LogDebug);
+ showMessage(_("Lldb stdout: " + out));
m_inbuffer.append(out);
while (true) {
- int pos = m_inbuffer.indexOf("@\n");
+ int pos = m_inbuffer.indexOf('\n');
if (pos == -1)
break;
QByteArray response = m_inbuffer.left(pos).trimmed();
- m_inbuffer = m_inbuffer.mid(pos + 2);
+ m_inbuffer = m_inbuffer.mid(pos + 1);
emit outputReady(response);
}
}
@@ -856,12 +855,12 @@ void LldbEngine::requestUpdateWatchers()
while (it.hasNext()) {
it.next();
QHash<QByteArray, QByteArray> hash;
- hash["iname"] = "'watch." + QByteArray::number(it.value()) + '\'';
- hash["exp"] = '\'' + it.key().toHex() + '\'';
+ hash["iname"] = "\"watch." + QByteArray::number(it.value()) + '"';
+ hash["exp"] = '"' + it.key().toHex() + '"';
watcherData.append(Command::toData(hash));
}
Command cmd("setWatchers");
- cmd.args.append("'watchers':" + Command::toData(watcherData) + ',');
+ cmd.args.append("\"watchers\":" + Command::toData(watcherData) + ',');
runCommand(cmd);
}
@@ -1117,9 +1116,9 @@ DebuggerEngine *createLldbEngine(const DebuggerStartParameters &startParameters)
const LldbEngine::Command &LldbEngine::Command::argHelper(const char *name, const QByteArray &data) const
{
- args.append('\'');
+ args.append('"');
args.append(name);
- args.append("':");
+ args.append("\":");
args.append(data);
args.append(",");
return *this;
@@ -1144,7 +1143,7 @@ QByteArray LldbEngine::Command::toData(const QHash<QByteArray, QByteArray> &valu
it.next();
if (!res.isEmpty())
res.append(',');
- res += '\'' + it.key() + "':" + it.value();
+ res += '"' + it.key() + "\":" + it.value();
}
return '{' + res + '}';
}
@@ -1176,20 +1175,20 @@ const LldbEngine::Command &LldbEngine::Command::arg(const char *name, const QByt
const LldbEngine::Command &LldbEngine::Command::arg(const char *name, const char *value) const
{
- args.append('\'');
+ args.append('"');
args.append(name);
- args.append("':'");
+ args.append("\":\"");
args.append(value);
- args.append("',");
+ args.append("\",");
return *this;
}
const LldbEngine::Command &LldbEngine::Command::beginList(const char *name) const
{
if (name) {
- args += '\'';
+ args += '"';
args += name;
- args += "':";
+ args += "\":";
}
args += '[';
return *this;
@@ -1205,9 +1204,9 @@ void LldbEngine::Command::endList() const
const LldbEngine::Command &LldbEngine::Command::beginGroup(const char *name) const
{
if (name) {
- args += '\'';
+ args += '"';
args += name;
- args += "':";
+ args += "\":";
}
args += '{';
return *this;
diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp
index 702bd1cefa..71453f46f0 100644
--- a/src/plugins/debugger/pdb/pdbengine.cpp
+++ b/src/plugins/debugger/pdb/pdbengine.cpp
@@ -596,7 +596,7 @@ QString PdbEngine::errorMessage(QProcess::ProcessError error) const
return tr("An error occurred when attempting to read from "
"the Pdb process. For example, the process may not be running.");
default:
- return tr("An unknown error in the Pdb process occurred. ");
+ return tr("An unknown error in the Pdb process occurred.") + QLatin1Char(' ');
}
}
diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp
index 89929350c7..4308c42c48 100644
--- a/src/plugins/debugger/qml/qmlengine.cpp
+++ b/src/plugins/debugger/qml/qmlengine.cpp
@@ -1167,7 +1167,7 @@ void QmlEngine::updateCurrentContext()
QmlJS::ConsoleManagerInterface *consoleManager = qmlConsoleManager();
if (consoleManager)
- consoleManager->setContext(tr("Context: ").append(context));
+ consoleManager->setContext(tr("Context:") + QLatin1Char(' ') + context);
}
void QmlEngine::appendDebugOutput(QtMsgType type, const QString &message,
diff --git a/src/plugins/debugger/qml/qmlinspectoragent.cpp b/src/plugins/debugger/qml/qmlinspectoragent.cpp
index 68974bf9d4..c1e4f41b4f 100644
--- a/src/plugins/debugger/qml/qmlinspectoragent.cpp
+++ b/src/plugins/debugger/qml/qmlinspectoragent.cpp
@@ -454,7 +454,8 @@ void QmlInspectorAgent::onResult(quint32 queryId, const QVariant &value,
} else if (type == "SET_BINDING_R"
|| type == "RESET_BINDING_R"
|| type == "SET_METHOD_BODY_R") {
- QString msg = QLatin1String(type) + tr("Success: ");
+ QString msg = QLatin1String(type) + tr("Success:");
+ msg += QLatin1Char(' ');
msg += value.toBool() ? QLatin1Char('1') : QLatin1Char('0');
if (!value.toBool())
emit automaticUpdateFailed();
diff --git a/src/plugins/debugger/watchdata.cpp b/src/plugins/debugger/watchdata.cpp
index 8cad1a3c13..cead6220a3 100644
--- a/src/plugins/debugger/watchdata.cpp
+++ b/src/plugins/debugger/watchdata.cpp
@@ -392,7 +392,8 @@ QString WatchData::toToolTip() const
}
if (val.size() > 1000) {
val.truncate(1000);
- val += tr(" ... <cut off>");
+ val += QLatin1Char(' ');
+ val += tr("... <cut off>");
}
formatToolTipRow(str, tr("Value"), val);
if (address)
diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp
index 1619cfeb2f..7539387542 100644
--- a/src/plugins/debugger/watchwindow.cpp
+++ b/src/plugins/debugger/watchwindow.cpp
@@ -649,7 +649,7 @@ void WatchTreeView::contextMenuEvent(QContextMenuEvent *ev)
QString msg = (individualFormat == -1 && typeFormat != -1)
? tr("Use Format for Type (Currently %1)")
.arg(alternativeFormats.at(typeFormat))
- : tr("Use Display Format Based on Type ");
+ : tr("Use Display Format Based on Type") + QLatin1Char(' ');
clearIndividualFormatAction = formatMenu.addAction(spacer + msg);
clearIndividualFormatAction->setCheckable(true);
clearIndividualFormatAction->setChecked(individualFormat == -1);
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index 59a65c0ac2..5c3050f81d 100644
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -1576,7 +1576,6 @@ public:
QTextBlock previousLine(const QTextBlock &block) const; // previous line (respects wrapped parts)
int linesOnScreen() const;
- int columnsOnScreen() const;
int linesInDocument() const;
// The following use all zero-based counting.
@@ -3673,9 +3672,12 @@ bool FakeVimHandler::Private::handleMovement(const Input &input)
setCursorPosition(&m_cursor, pos);
handleStartOfLine();
} else if (g.gflag && input.is('m')) {
- moveToStartOfLine();
- moveRight(qMin(columnsOnScreen() / 2, rightDist()) - 1);
- setTargetColumn();
+ const QPoint pos(EDITOR(viewport()->width()) / 2, EDITOR(cursorRect(m_cursor)).y());
+ QTextCursor tc = EDITOR(cursorForPosition(pos));
+ if (!tc.isNull()) {
+ m_cursor = tc;
+ setTargetColumn();
+ }
} else if (input.is('M')) {
m_cursor = EDITOR(cursorForPosition(QPoint(0, EDITOR(height()) / 2)));
handleStartOfLine();
@@ -5397,7 +5399,7 @@ bool FakeVimHandler::Private::handleExSetCommand(const ExCommand &cmd)
if (!error.isEmpty())
showMessage(MessageError, error);
} else {
- showMessage(MessageError, FakeVimHandler::tr("Unknown option: ") + cmd.args);
+ showMessage(MessageError, FakeVimHandler::tr("Unknown option:") + QLatin1Char(' ') + cmd.args);
}
updateMiniBuffer();
updateEditor();
@@ -6370,25 +6372,16 @@ int FakeVimHandler::Private::cursorLineOnScreen() const
{
if (!editor())
return 0;
- QRect rect = EDITOR(cursorRect());
- return rect.y() / rect.height();
+ const QRect rect = EDITOR(cursorRect(m_cursor));
+ return rect.height() > 0 ? rect.y() / rect.height() : 0;
}
int FakeVimHandler::Private::linesOnScreen() const
{
if (!editor())
return 1;
- QRect rect = EDITOR(cursorRect());
- return EDITOR(viewport()->height()) / rect.height();
-}
-
-int FakeVimHandler::Private::columnsOnScreen() const
-{
- if (!editor())
- return 1;
- QRect rect = EDITOR(cursorRect());
- // qDebug() << "WID: " << EDITOR(width()) << "RECT: " << rect;
- return EDITOR(viewport()->width()) / rect.width();
+ const int h = EDITOR(cursorRect(m_cursor)).height();
+ return h > 0 ? EDITOR(viewport()->height()) / h : 1;
}
int FakeVimHandler::Private::cursorLine() const
diff --git a/src/plugins/git/gerrit/gerritdialog.cpp b/src/plugins/git/gerrit/gerritdialog.cpp
index 27f84d55be..8859af24e7 100644
--- a/src/plugins/git/gerrit/gerritdialog.cpp
+++ b/src/plugins/git/gerrit/gerritdialog.cpp
@@ -101,7 +101,7 @@ GerritDialog::GerritDialog(const QSharedPointer<GerritParameters> &p,
, m_filterLineEdit(new Utils::FilterLineEdit)
, m_repositoryChooser(new Utils::PathChooser)
, m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Close))
- , m_repositoryChooserLabel(new QLabel(tr("Apply in: "), this))
+ , m_repositoryChooserLabel(new QLabel(tr("Apply in:") + QLatin1Char(' '), this))
, m_fetchRunning(false)
{
setWindowTitle(tr("Gerrit %1@%2").arg(p->user, p->host));
diff --git a/src/plugins/git/gerrit/gerritpushdialog.cpp b/src/plugins/git/gerrit/gerritpushdialog.cpp
index 4cba759995..c8b0537a22 100644
--- a/src/plugins/git/gerrit/gerritpushdialog.cpp
+++ b/src/plugins/git/gerrit/gerritpushdialog.cpp
@@ -37,6 +37,7 @@
#include <QDateTime>
#include <QDir>
+#include <QRegExpValidator>
namespace Gerrit {
namespace Internal {
@@ -156,6 +157,9 @@ GerritPushDialog::GerritPushDialog(const QString &workingDir, const QString &rev
connect(m_ui->branchComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setChangeRange()));
setRemoteBranches();
m_ui->reviewersLineEdit->setText(reviewerList);
+
+ m_ui->topicLineEdit->setValidator(new QRegExpValidator(QRegExp(QLatin1String("^\\S+$")), this));
+
m_valid = true;
}
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 764ba726b0..416c29e5d3 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -2767,7 +2767,7 @@ void GitClient::continuePreviousGitCommand(const QString &workingDirectory,
== GitClient::StatusChanged;
}
if (!hasChanges)
- msgBoxText.prepend(tr("No changes found. "));
+ msgBoxText.prepend(tr("No changes found.") + QLatin1Char(' '));
QMessageBox msgBox(QMessageBox::Question, msgBoxTitle, msgBoxText,
QMessageBox::NoButton, Core::ICore::mainWindow());
if (hasChanges || isRebase)
@@ -2808,7 +2808,7 @@ QString GitClient::extendedShowDescription(const QString &workingDirectory, cons
if (branchCount > 20) {
const int leave = 10;
//: Displayed after the untranslated message "Branches: branch1, branch2 'and %n more'" in git show.
- moreBranches = tr(" and %n more", 0, branchCount - leave);
+ moreBranches = QLatin1Char(' ') + tr("and %n more", 0, branchCount - leave);
branches.erase(branches.begin() + leave, branches.end());
}
if (!branches.isEmpty()) {
diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp
index ebfca0293f..1eaa690bc9 100644
--- a/src/plugins/ios/iosconfigurations.cpp
+++ b/src/plugins/ios/iosconfigurations.cpp
@@ -42,6 +42,7 @@
#include <projectexplorer/toolchain.h>
#include <projectexplorer/gcctoolchain.h>
#include <projectexplorer/projectexplorerconstants.h>
+#include <debugger/debuggeritemmanager.h>
#include <debugger/debuggerkitinformation.h>
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
diff --git a/src/plugins/ios/iosdevice.cpp b/src/plugins/ios/iosdevice.cpp
index d258d34991..524eff4728 100644
--- a/src/plugins/ios/iosdevice.cpp
+++ b/src/plugins/ios/iosdevice.cpp
@@ -33,6 +33,7 @@
#include "iostoolhandler.h"
#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/kitinformation.h>
+#include <coreplugin/helpmanager.h>
#include <QCoreApplication>
#include <QVariant>
@@ -318,11 +319,12 @@ void IosDeviceManager::deviceInfo(IosToolHandler *, const QString &uid,
mBox.setText(tr("An iOS device in user mode has been detected."));
mBox.setInformativeText(tr("Do you want to see how to set it up for development?"));
mBox.setStandardButtons(QMessageBox::NoAll | QMessageBox::No | QMessageBox::Yes);
- mBox.setDefaultButton(QMessageBox::No);
+ mBox.setDefaultButton(QMessageBox::Yes);
int ret = mBox.exec();
switch (ret) {
case QMessageBox::Yes:
- // open doc
+ Core::HelpManager::handleHelpRequest(
+ QLatin1String("qthelp://org.qt-project.qtcreator/doc/creator-developing-ios.html"));
break;
case QMessageBox::No:
newDev->m_ignoreDevice = true;
diff --git a/src/plugins/locator/executefilter.cpp b/src/plugins/locator/executefilter.cpp
index 4b4ef46b0b..20e940a1d7 100644
--- a/src/plugins/locator/executefilter.cpp
+++ b/src/plugins/locator/executefilter.cpp
@@ -168,6 +168,11 @@ void ExecuteFilter::runHeadCommand()
m_process->setCommand(fullPath, d.arguments);
m_process->start();
m_process->closeWriteChannel();
+ if (!m_process->waitForStarted(1000)) {
+ MessageManager::write(tr("Could not start process: %1").arg(m_process->errorString()));
+ m_taskQueue.dequeue();
+ runHeadCommand();
+ }
}
}
diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp
index b0c45aa001..aafe96ccd9 100644
--- a/src/plugins/projectexplorer/abi.cpp
+++ b/src/plugins/projectexplorer/abi.cpp
@@ -311,18 +311,19 @@ Abi::Abi(const Architecture &a, const OS &o,
m_osFlavor = UnknownFlavor;
break;
case ProjectExplorer::Abi::LinuxOS:
- if (m_osFlavor < GenericLinuxFlavor || m_osFlavor > MaemoLinuxFlavor)
+ if (m_osFlavor < GenericLinuxFlavor || m_osFlavor > AndroidLinuxFlavor)
m_osFlavor = UnknownFlavor;
break;
case ProjectExplorer::Abi::BsdOS:
- m_osFlavor = FreeBsdFlavor;
+ if (m_osFlavor < FreeBsdFlavor || m_osFlavor > OpenBsdFlavor)
+ m_osFlavor = UnknownFlavor;
break;
case ProjectExplorer::Abi::MacOS:
if (m_osFlavor < GenericMacFlavor || m_osFlavor > GenericMacFlavor)
m_osFlavor = UnknownFlavor;
break;
case ProjectExplorer::Abi::UnixOS:
- if (m_osFlavor < GenericUnixFlavor || m_osFlavor > GenericUnixFlavor)
+ if (m_osFlavor < GenericUnixFlavor || m_osFlavor > SolarisUnixFlavor)
m_osFlavor = UnknownFlavor;
break;
case ProjectExplorer::Abi::WindowsOS:
@@ -387,10 +388,6 @@ Abi::Abi(const QString &abiString) :
m_osFlavor = NetBsdFlavor;
else if (abiParts.at(2) == QLatin1String("openbsd") && m_os == BsdOS)
m_osFlavor = OpenBsdFlavor;
- else if (abiParts.at(2) == QLatin1String("maemo") && m_os == LinuxOS)
- m_osFlavor = MaemoLinuxFlavor;
- else if (abiParts.at(2) == QLatin1String("harmattan") && m_os == LinuxOS)
- m_osFlavor = HarmattanLinuxFlavor;
else if (abiParts.at(2) == QLatin1String("generic") && m_os == MacOS)
m_osFlavor = GenericMacFlavor;
else if (abiParts.at(2) == QLatin1String("generic") && m_os == UnixOS)
@@ -637,10 +634,6 @@ QString Abi::toString(const OSFlavor &of)
return QLatin1String("netbsd");
case ProjectExplorer::Abi::OpenBsdFlavor:
return QLatin1String("openbsd");
- case ProjectExplorer::Abi::MaemoLinuxFlavor:
- return QLatin1String("maemo");
- case ProjectExplorer::Abi::HarmattanLinuxFlavor:
- return QLatin1String("harmattan");
case ProjectExplorer::Abi::GenericMacFlavor:
return QLatin1String("generic");
case ProjectExplorer::Abi::GenericUnixFlavor:
@@ -698,8 +691,7 @@ QList<Abi::OSFlavor> Abi::flavorsForOs(const Abi::OS &o)
case BsdOS:
return result << FreeBsdFlavor << OpenBsdFlavor << NetBsdFlavor << UnknownFlavor;
case LinuxOS:
- return result << GenericLinuxFlavor << HarmattanLinuxFlavor << MaemoLinuxFlavor
- << AndroidLinuxFlavor << UnknownFlavor;
+ return result << GenericLinuxFlavor << AndroidLinuxFlavor << UnknownFlavor;
case MacOS:
return result << GenericMacFlavor << UnknownFlavor;
case UnixOS:
diff --git a/src/plugins/projectexplorer/abi.h b/src/plugins/projectexplorer/abi.h
index 473918b918..e7e7a9669e 100644
--- a/src/plugins/projectexplorer/abi.h
+++ b/src/plugins/projectexplorer/abi.h
@@ -73,8 +73,6 @@ public:
// Linux
GenericLinuxFlavor,
AndroidLinuxFlavor,
- HarmattanLinuxFlavor,
- MaemoLinuxFlavor,
// Mac
GenericMacFlavor,
diff --git a/src/plugins/projectexplorer/applicationlauncher.cpp b/src/plugins/projectexplorer/applicationlauncher.cpp
index a3667fbece..e04b94731d 100644
--- a/src/plugins/projectexplorer/applicationlauncher.cpp
+++ b/src/plugins/projectexplorer/applicationlauncher.cpp
@@ -35,10 +35,8 @@
#include <coreplugin/icore.h>
#include <utils/consoleprocess.h>
+#include <utils/fileutils.h>
#include <utils/qtcprocess.h>
-#ifdef Q_OS_WIN
-#include <utils/winutils.h>
-#endif
#include <QTextCodec>
@@ -131,19 +129,10 @@ ApplicationLauncher::~ApplicationLauncher()
void ApplicationLauncher::setWorkingDirectory(const QString &dir)
{
-#ifdef Q_OS_WIN
// Work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch' ...)
- const QString fixedPath = Utils::normalizePathName(dir);
-#else
-# define fixedPath dir
-#endif
-
+ const QString fixedPath = Utils::FileUtils::normalizePathName(dir);
d->m_guiProcess.setWorkingDirectory(fixedPath);
d->m_consoleProcess.setWorkingDirectory(fixedPath);
-
-#ifndef Q_OS_WIN
-# undef fixedPath
-#endif
}
void ApplicationLauncher::setEnvironment(const Utils::Environment &env)
diff --git a/src/plugins/projectexplorer/copytaskhandler.cpp b/src/plugins/projectexplorer/copytaskhandler.cpp
index 58c3f691ad..1b641a7ce1 100644
--- a/src/plugins/projectexplorer/copytaskhandler.cpp
+++ b/src/plugins/projectexplorer/copytaskhandler.cpp
@@ -45,11 +45,11 @@ void CopyTaskHandler::handle(const ProjectExplorer::Task &task)
switch (task.type) {
case Task::Error:
//: Task is of type: error
- type = tr("error: ");
+ type = tr("error:") + QLatin1Char(' ');
break;
case Task::Warning:
//: Task is of type: warning
- type = tr("warning: ");
+ type = tr("warning:") + QLatin1Char(' ');
break;
default:
break;
diff --git a/src/plugins/projectexplorer/customparserconfigdialog.cpp b/src/plugins/projectexplorer/customparserconfigdialog.cpp
index b45c745c8f..2a6c0f7202 100644
--- a/src/plugins/projectexplorer/customparserconfigdialog.cpp
+++ b/src/plugins/projectexplorer/customparserconfigdialog.cpp
@@ -147,7 +147,7 @@ void CustomParserConfigDialog::changed()
int pos = rx.indexIn(ui->errorMessage->text());
if (rx.isEmpty() || !rx.isValid() || pos < 0) {
- QString error = QLatin1String("<font color=\"red\">") + tr("Not applicable: ");
+ QString error = QLatin1String("<font color=\"red\">") + tr("Not applicable:") + QLatin1Char(' ');
if (rx.isEmpty())
error += tr("Pattern is empty.");
else if (!rx.isValid())
diff --git a/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp b/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp
index c2d736b3f5..719739bce2 100644
--- a/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp
+++ b/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp
@@ -85,14 +85,16 @@ void DesktopProcessSignalOperation::appendMsgCannotKill(int pid, const QString &
{
if (!m_errorMessage.isEmpty())
m_errorMessage += QChar::fromLatin1('\n');
- m_errorMessage += tr("Cannot kill process with pid %1: %3 ").arg(pid).arg(why);
+ m_errorMessage += tr("Cannot kill process with pid %1: %3").arg(pid).arg(why);
+ m_errorMessage += QLatin1Char(' ');
}
void DesktopProcessSignalOperation::appendMsgCannotInterrupt(int pid, const QString &why)
{
if (!m_errorMessage.isEmpty())
m_errorMessage += QChar::fromLatin1('\n');
- m_errorMessage += tr("Cannot interrupt process with pid %1: %3 ").arg(pid).arg(why);
+ m_errorMessage += tr("Cannot interrupt process with pid %1: %3").arg(pid).arg(why);
+ m_errorMessage += QLatin1Char(' ');
}
void DesktopProcessSignalOperation::killProcessSilently(int pid)
@@ -165,8 +167,8 @@ GDB 32bit | Api | Api | N/A | Win32
m_specialInterrupt == Win64Interrupt && creatorIs64Bit ||
m_specialInterrupt == Win32Interrupt && !creatorIs64Bit) {
if (!DebugBreakProcess(inferior)) {
- appendMsgCannotInterrupt(pid, tr("DebugBreakProcess failed: ")
- + Utils::winErrorMessage(GetLastError()));
+ appendMsgCannotInterrupt(pid, tr("DebugBreakProcess failed:")
+ + QLatin1Char(' ') + Utils::winErrorMessage(GetLastError()));
}
} else if (m_specialInterrupt == Win32Interrupt || m_specialInterrupt == Win64Interrupt) {
QString executable = QCoreApplication::applicationDirPath();
@@ -189,7 +191,7 @@ GDB 32bit | Api | Api | N/A | Win32
break;
default:
appendMsgCannotInterrupt(pid, QDir::toNativeSeparators(executable)
- + tr(" could not break the process."));
+ + QLatin1Char(' ') + tr("could not break the process."));
break;
}
}
diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp
index 6aad3a6b20..4e26ef1101 100644
--- a/src/plugins/projectexplorer/foldernavigationwidget.cpp
+++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp
@@ -158,6 +158,8 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent)
this, SLOT(slotOpenItem(QModelIndex)));
connect(m_filterHiddenFilesAction, SIGNAL(toggled(bool)), this, SLOT(setHiddenFilesFilter(bool)));
connect(m_toggleSync, SIGNAL(clicked(bool)), this, SLOT(toggleAutoSynchronization()));
+ connect(m_filterModel, SIGNAL(layoutChanged()),
+ this, SLOT(ensureCurrentIndex()));
}
void FolderNavigationWidget::toggleAutoSynchronization()
@@ -225,10 +227,17 @@ bool FolderNavigationWidget::setCurrentDirectory(const QString &directory)
setCurrentTitle(QString(), QString());
return false;
}
- m_listView->setRootIndex(m_filterModel->mapFromSource(index));
+ QModelIndex oldRootIndex = m_listView->rootIndex();
+ QModelIndex newRootIndex = m_filterModel->mapFromSource(index);
+ m_listView->setRootIndex(newRootIndex);
const QDir current(QDir::cleanPath(newDirectory));
setCurrentTitle(current.dirName(),
QDir::toNativeSeparators(current.absolutePath()));
+ if (oldRootIndex.parent() == newRootIndex) { // cdUp, so select the old directory
+ m_listView->setCurrentIndex(oldRootIndex);
+ m_listView->scrollTo(oldRootIndex, QAbstractItemView::EnsureVisible);
+ }
+
return !directory.isEmpty();
}
@@ -365,6 +374,17 @@ bool FolderNavigationWidget::hiddenFilesFilter() const
return m_filterHiddenFilesAction->isChecked();
}
+void FolderNavigationWidget::ensureCurrentIndex()
+{
+ QModelIndex index = m_listView->currentIndex();
+ if (!index.isValid()
+ || index.parent() != m_listView->rootIndex()) {
+ index = m_listView->rootIndex().child(0, 0);
+ m_listView->setCurrentIndex(index);
+ }
+ m_listView->scrollTo(index);
+}
+
// --------------------FolderNavigationWidgetFactory
FolderNavigationWidgetFactory::FolderNavigationWidgetFactory()
{
diff --git a/src/plugins/projectexplorer/foldernavigationwidget.h b/src/plugins/projectexplorer/foldernavigationwidget.h
index 6b6aaed266..f99a9262e8 100644
--- a/src/plugins/projectexplorer/foldernavigationwidget.h
+++ b/src/plugins/projectexplorer/foldernavigationwidget.h
@@ -70,6 +70,7 @@ private slots:
void setCurrentFile(const QString &filePath);
void slotOpenItem(const QModelIndex &viewIndex);
void setHiddenFilesFilter(bool filter);
+ void ensureCurrentIndex();
protected:
virtual void contextMenuEvent(QContextMenuEvent *ev);
diff --git a/src/plugins/projectexplorer/kitinformationconfigwidget.cpp b/src/plugins/projectexplorer/kitinformationconfigwidget.cpp
index d3a43ba096..7c5ac9bcad 100644
--- a/src/plugins/projectexplorer/kitinformationconfigwidget.cpp
+++ b/src/plugins/projectexplorer/kitinformationconfigwidget.cpp
@@ -89,7 +89,7 @@ void SysRootInformationConfigWidget::refresh()
void SysRootInformationConfigWidget::makeReadOnly()
{
- m_chooser->setReadOnly(true);
+ m_chooser->setEnabled(false);
}
QWidget *SysRootInformationConfigWidget::mainWidget() const
diff --git a/src/plugins/projectexplorer/msvcparser.cpp b/src/plugins/projectexplorer/msvcparser.cpp
index 0bc41b7b84..653d9e30f7 100644
--- a/src/plugins/projectexplorer/msvcparser.cpp
+++ b/src/plugins/projectexplorer/msvcparser.cpp
@@ -31,9 +31,7 @@
#include "projectexplorerconstants.h"
#include <utils/qtcassert.h>
-#ifdef Q_OS_WIN
-#include <utils/winutils.h>
-#endif
+#include <utils/fileutils.h>
static const char FILE_POS_PATTERN[] = "(cl|LINK|.+) : ";
static const char ERROR_PATTERN[] = "[A-Z]+\\d\\d\\d\\d ?:";
@@ -58,11 +56,7 @@ static QPair<Utils::FileName, int> parseFileName(const QString &input)
}
}
}
-#ifdef Q_OS_WIN
- const QString normalized = Utils::normalizePathName(fileName);
-#else
- const QString normalized = fileName;
-#endif
+ const QString normalized = Utils::FileUtils::normalizePathName(fileName);
return qMakePair(Utils::FileName::fromUserInput(normalized), linenumber);
}
diff --git a/src/plugins/projectexplorer/projectwelcomepage.cpp b/src/plugins/projectexplorer/projectwelcomepage.cpp
index db71fccfa8..fa2b24a995 100644
--- a/src/plugins/projectexplorer/projectwelcomepage.cpp
+++ b/src/plugins/projectexplorer/projectwelcomepage.cpp
@@ -29,8 +29,6 @@
#include "projectwelcomepage.h"
-#include <utils/stringutils.h>
-
#include <QQmlContext>
#include <QQmlEngine>
#include <QFileInfo>
@@ -42,9 +40,8 @@
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/sessiondialog.h>
-#ifdef Q_OS_WIN
-#include <utils/winutils.h>
-#endif
+#include <utils/fileutils.h>
+#include <utils/stringutils.h>
namespace ProjectExplorer {
namespace Internal {
@@ -225,12 +222,9 @@ void ProjectWelcomePage::facilitateQml(QQmlEngine *engine)
QUrl ProjectWelcomePage::pageLocation() const
{
- QString resourcePath = Core::ICore::resourcePath();
-#ifdef Q_OS_WIN
// normalize paths so QML doesn't freak out if it's wrongly capitalized on Windows
- resourcePath = Utils::normalizePathName(resourcePath);
-#endif
- return QUrl::fromLocalFile(resourcePath + QLatin1String("/welcomescreen/develop.qml"));
+ const QString resourcePath = Utils::FileUtils::normalizePathName(Core::ICore::resourcePath());
+ return QUrl::fromLocalFile(resourcePath + QLatin1String("/welcomescreen/develop.qml"));
}
ProjectWelcomePage::Id ProjectWelcomePage::id() const
diff --git a/src/plugins/projectexplorer/targetsettingspanel.cpp b/src/plugins/projectexplorer/targetsettingspanel.cpp
index 504871cb5b..95a99377a0 100644
--- a/src/plugins/projectexplorer/targetsettingspanel.cpp
+++ b/src/plugins/projectexplorer/targetsettingspanel.cpp
@@ -418,7 +418,7 @@ Target *TargetSettingsPanelWidget::cloneTarget(Target *sourceTarget, Kit *k)
if (!runconfigurationError.isEmpty()) {
if (!error.isEmpty())
error.append(QLatin1Char('\n'));
- error += tr("Run configurations ")
+ error += tr("Run configurations") + QLatin1Char(' ')
+ runconfigurationError.join(QLatin1String("\n"));
}
diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp
index ce094aeff8..34ab0c6d01 100644
--- a/src/plugins/projectexplorer/taskwindow.cpp
+++ b/src/plugins/projectexplorer/taskwindow.cpp
@@ -48,6 +48,7 @@
#include <QStyledItemDelegate>
#include <QMenu>
#include <QToolButton>
+#include <QScrollBar>
namespace {
const int ELLIPSIS_GRADIENT_WIDTH = 16;
@@ -74,6 +75,8 @@ class TaskDelegate : public QStyledItemDelegate
{
Q_OBJECT
+ friend class TaskView; // for using Positions::minimumSize()
+
public:
TaskDelegate(QObject * parent = 0);
~TaskDelegate();
@@ -126,11 +129,11 @@ private:
int right() const { return m_totalWidth - ITEM_MARGIN; }
int bottom() const { return m_bottom; }
int firstLineHeight() const { return m_fontHeight + 1; }
- int minimumHeight() const { return taskIconHeight() + 2 * ITEM_MARGIN; }
+ static int minimumHeight() { return taskIconHeight() + 2 * ITEM_MARGIN; }
int taskIconLeft() const { return left(); }
- int taskIconWidth() const { return TASK_ICON_SIZE; }
- int taskIconHeight() const { return TASK_ICON_SIZE; }
+ static int taskIconWidth() { return TASK_ICON_SIZE; }
+ static int taskIconHeight() { return TASK_ICON_SIZE; }
int taskIconRight() const { return taskIconLeft() + taskIconWidth(); }
QRect taskIcon() const { return QRect(taskIconLeft(), top(), taskIconWidth(), taskIconHeight()); }
@@ -169,6 +172,13 @@ TaskView::TaskView(QWidget *parent)
{
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+
+ QFontMetrics fm(font());
+ int vStepSize = fm.height() + 3;
+ if (vStepSize < TaskDelegate::Positions::minimumHeight())
+ vStepSize = TaskDelegate::Positions::minimumHeight();
+
+ verticalScrollBar()->setSingleStep(vStepSize);
}
TaskView::~TaskView()
diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp
index 03f5c72654..970626a241 100644
--- a/src/plugins/qbsprojectmanager/qbsproject.cpp
+++ b/src/plugins/qbsprojectmanager/qbsproject.cpp
@@ -412,7 +412,14 @@ void QbsProject::parse(const QVariantMap &config, const Environment &env, const
QTC_ASSERT(!dir.isNull(), return);
qbs::SetupProjectParameters params;
- params.setBuildConfiguration(config);
+ QVariantMap baseConfig;
+ QVariantMap userConfig = config;
+ QString specialKey = QLatin1String(Constants::QBS_CONFIG_PROFILE_KEY);
+ baseConfig.insert(specialKey, userConfig.take(specialKey));
+ specialKey = QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY);
+ baseConfig.insert(specialKey, userConfig.take(specialKey));
+ params.setBuildConfiguration(baseConfig);
+ params.setOverriddenValues(userConfig);
qbs::ErrorInfo err = params.expandBuildConfiguration(m_manager->settings());
if (err.hasError()) {
generateErrors(err);
@@ -423,7 +430,7 @@ void QbsProject::parse(const QVariantMap &config, const Environment &env, const
const qbs::Project &currentProject = qbsProject();
if (!m_forceParsing
&& currentProject.isValid()
- && currentProject.projectConfiguration() == params.buildConfiguration()) {
+ && currentProject.projectConfiguration() == params.finalBuildConfigurationTree()) {
QHash<QString, QString> usedEnv = currentProject.usedEnvironment();
bool canSkip = true;
for (QHash<QString, QString>::const_iterator i = usedEnv.constBegin();
diff --git a/src/plugins/qmldesigner/components/componentcore/tabviewdesigneraction.cpp b/src/plugins/qmldesigner/components/componentcore/tabviewdesigneraction.cpp
index 9a04a2cec3..82411e6b98 100644
--- a/src/plugins/qmldesigner/components/componentcore/tabviewdesigneraction.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/tabviewdesigneraction.cpp
@@ -151,7 +151,7 @@ void TabViewDesignerAction::addNewTab()
QString newFilePath = directoryPath +QLatin1String("/") + tabName + QLatin1String(".qml");
if (QFileInfo(newFilePath).exists()) {
- QMessageBox::warning(Core::ICore::mainWindow(), tr("Name Error"), tr("Component already exists."));
+ QMessageBox::warning(Core::ICore::mainWindow(), tr("Naming Error"), tr("Component already exists."));
} else {
bool fileCreated = createFile(newFilePath);
diff --git a/src/plugins/qmldesigner/components/debugview/debugview.cpp b/src/plugins/qmldesigner/components/debugview/debugview.cpp
index 2b7823ccbe..013b4a2f56 100644
--- a/src/plugins/qmldesigner/components/debugview/debugview.cpp
+++ b/src/plugins/qmldesigner/components/debugview/debugview.cpp
@@ -147,8 +147,8 @@ void DebugView::nodeIdChanged(const ModelNode &node, const QString &newId, const
QString string;
message.setString(&string);
message << node;
- message << tr("New Id: ") << newId << lineBreak;
- message << tr("Old Id: ") << oldId << lineBreak;
+ message << tr("New Id:") << ' ' << newId << lineBreak;
+ message << tr("Old Id:") << ' ' << oldId << lineBreak;
log(tr("Node id changed:"), string);
}
}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsView.qml b/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsView.qml
index 793d7ea7f0..697d3a95a8 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsView.qml
+++ b/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsView.qml
@@ -223,6 +223,7 @@ content position out of scope regarding the scrollbar. */
anchors.bottom: parent.bottom
anchors.bottomMargin: 1
anchors.right: parent.right
+ anchors.rightMargin: 2
width: (itemsFlickable.contentHeight > itemsFlickable.height)? 11:0
Scrollbar {
diff --git a/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsViewStyle.qml b/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsViewStyle.qml
index e5f29de94c..c112ffa50f 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsViewStyle.qml
+++ b/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsViewStyle.qml
@@ -61,7 +61,7 @@ Item {
property int textWidth: 95
property int textHeight: 15
- property int cellHorizontalMargin: 5
+ property int cellHorizontalMargin: 4
property int cellVerticalSpacing: 7
property int cellVerticalMargin: 10
diff --git a/src/plugins/qmldesigner/components/itemlibrary/qml/Scrollbar.qml b/src/plugins/qmldesigner/components/itemlibrary/qml/Scrollbar.qml
index 33bc50fc80..23adc86abb 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/qml/Scrollbar.qml
+++ b/src/plugins/qmldesigner/components/itemlibrary/qml/Scrollbar.qml
@@ -39,11 +39,11 @@ Item {
property variant flickable
function scroll(delta) {
- handle.y = Math.max(0, Math.min(scrollHeight, handle.y + delta))
+ handle.y = Math.max(2, Math.min(scrollHeight, handle.y + delta))
}
function reset() {
- handle.y = 0
+ handle.y = 2
}
// internal
@@ -62,8 +62,7 @@ Item {
anchors.bottom: parent.bottom
anchors.bottomMargin: 3
anchors.horizontalCenter: parent.horizontalCenter
- width: 6
- radius: 3
+ width: 10
color: style.scrollbarColor
border.width: 1
border.color: style.scrollbarBorderColor
@@ -77,7 +76,7 @@ Item {
flickable.contentY / (flickable.contentHeight - flickable.height),
1)
else
- handle.y = 0
+ handle.y = 2
handle.updateFlickable = true
}
@@ -109,6 +108,7 @@ Item {
Item {
id: handle
+ y: 2
anchors.left: parent.left
anchors.right: parent.right
@@ -125,27 +125,20 @@ Item {
width: parent.height
height: parent.width
y: -height - 2
- x: -2
rotation: 90
transformOrigin: Item.BottomLeft
border.color: style.scrollbarBorderColor
border.width: 1
- radius: 3
-
- gradient: Gradient {
- GradientStop { position: 0.15; color: style.scrollbarGradientStartColor }
- GradientStop { position: 0.78; color: style.scrollbarGradientMiddleColor }
- GradientStop { position: 0.80; color: style.scrollbarGradientEndColor }
- }
+ color: style.sectionTitleBackgroundColor
}
MouseArea {
anchors.fill: parent
drag.target: parent
drag.axis: "YAxis"
- drag.minimumY: 0
+ drag.minimumY: 2
drag.maximumY: scrollHeight
}
}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/qml/SectionView.qml b/src/plugins/qmldesigner/components/itemlibrary/qml/SectionView.qml
index 5a43d7de75..bfc324ebe4 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/qml/SectionView.qml
+++ b/src/plugins/qmldesigner/components/itemlibrary/qml/SectionView.qml
@@ -28,6 +28,7 @@
****************************************************************************/
import QtQuick 2.1
+import QtQuick.Controls 1.0 as Controls
// view displaying one item library section including its grid
@@ -114,12 +115,27 @@ Column {
width: parent.width
height: style.sectionTitleHeight
- color: style.sectionTitleBackgroundColor
+ gradient: Gradient {
+ GradientStop {color: '#555' ; position: 0}
+ GradientStop {color: '#444' ; position: 1}
+ }
+
+ Rectangle {
+ color:"#333"
+ width: parent.width
+ height: 1
+ }
+
+ Rectangle {
+ color: "#333"
+ anchors.bottom: parent.bottom
+ width: parent.width
+ height: 1
+ }
Item {
id: arrow
- Rectangle { y: 0; x: 0; height: 1; width: 11; color: style.sectionArrowColor }
Rectangle { y: 1; x: 1; height: 1; width: 9; color: style.sectionArrowColor }
Rectangle { y: 2; x: 2; height: 1; width: 7; color: style.sectionArrowColor }
Rectangle { y: 3; x: 3; height: 1; width: 5; color: style.sectionArrowColor }
@@ -127,25 +143,26 @@ Column {
Rectangle { y: 5; x: 5; height: 1; width: 1; color: style.sectionArrowColor }
anchors.left: parent.left
- anchors.leftMargin: 10
+ anchors.leftMargin: 4
anchors.verticalCenter: parent.verticalCenter
width: 11
height: 6
transformOrigin: Item.Center
}
- Text {
+ Controls.Label {
id: text
anchors.verticalCenter: parent.verticalCenter
anchors.left: arrow.right
- anchors.leftMargin: 12
+ anchors.leftMargin: 4
text: sectionName // to be set by model
color: style.sectionTitleTextColor
elide: Text.ElideMiddle
font.bold: true
- renderType: Text.NativeRendering
+ style: Text.Sunken
+ styleColor: "#292929"
}
MouseArea {
id: mouseArea
@@ -161,6 +178,9 @@ Column {
Item {
id: gridFrame
+ Behavior on opacity { NumberAnimation{easing.type: Easing.Linear ; duration: 80} }
+ Behavior on height { NumberAnimation{easing.type: Easing.OutCubic ; duration: 140} }
+
function toggleExpanded() {
state = ((state == "")? "shrunk":"")
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
index 05b2511778..67376a966b 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
@@ -44,9 +44,7 @@
#include <qmljs/qmljssimplereader.h>
-#ifdef Q_OS_WIN
-#include <utils/winutils.h>
-#endif
+#include <utils/fileutils.h>
enum {
debug = false
@@ -95,12 +93,8 @@ static QObject *variantToQObject(const QVariant &value)
static QString applicationDirPath()
{
-#ifdef Q_OS_WIN
// normalize paths so QML doesn't freak out if it's wrongly capitalized on Windows
- return Utils::normalizePathName(QCoreApplication::applicationDirPath());
-#else
- return QCoreApplication::applicationDirPath();
-#endif
+ return Utils::FileUtils::normalizePathName(QCoreApplication::applicationDirPath());
}
#ifdef Q_OS_MAC
diff --git a/src/plugins/qmldesigner/components/resources/scrollbar.css b/src/plugins/qmldesigner/components/resources/scrollbar.css
index 34e8af8acb..661c987cb9 100644
--- a/src/plugins/qmldesigner/components/resources/scrollbar.css
+++ b/src/plugins/qmldesigner/components/resources/scrollbar.css
@@ -1,26 +1,21 @@
QScrollBar:vertical {
- border-image: url(:/qmldesigner/images/scrollbar-borderimage-vertical.png);
- border-left: 0;
- border-right: 0;
- border-top: 3;
- border-bottom: 3;
+ background-color: #444444;
+ border: 1px solid #333333;
margin-top: 3;
margin-bottom: 3;
width: 10;
}
QScrollBar::handle:vertical {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0,
- stop: 0.20 #888888,
- stop: 0.23 #656565,
- stop: 0.85 #393939);
+ background-color: #656565;
margin-top: -5;
margin-bottom: -5;
min-height: 18px;
width: 8px;
border: 1px solid #313131;
- border-radius: 4px;
border-width: 1;
+ margin-left: -1;
+ margin-right: -1;
}
QScrollBar::add-line:vertical {
@@ -49,28 +44,24 @@
}
QScrollBar:horizontal {
- border-image: url(:/qmldesigner/images/scrollbar-borderimage-horizontal.png);
- border-left: 3;
- border-right: 3;
- border-top: 0;
- border-bottom: 0;
+ background-color: #444444;
+ border: 1px solid #333333;
margin-left: 3;
margin-right: 3;
height: 10;
}
QScrollBar::handle:horizontal {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0.20 #888888,
- stop: 0.23 #656565,
- stop: 0.85 #393939);
+ background-color: #656565;
+
margin-left: -5;
margin-right: -5;
min-width: 18px;
height: 8px;
border: 1px solid #313131;
- border-radius: 4px;
border-width: 1;
+ margin-top: -1;
+ margin-bottom: -1;
}
QScrollBar::add-line:horizontal {
diff --git a/src/plugins/qmldesigner/components/stateseditor/HorizontalScrollBar.qml b/src/plugins/qmldesigner/components/stateseditor/HorizontalScrollBar.qml
index a1077e7ead..08479b6a70 100644
--- a/src/plugins/qmldesigner/components/stateseditor/HorizontalScrollBar.qml
+++ b/src/plugins/qmldesigner/components/stateseditor/HorizontalScrollBar.qml
@@ -55,9 +55,8 @@ Item {
Rectangle {
id: groove
width: parent.width - 4
- height: 6
+ height: 10
color: "#444444"
- radius: 3
border.width: 1
border.color: "#333333"
anchors.right: parent.right
@@ -95,13 +94,8 @@ Item {
y:0
border.color: "#333333"
border.width: 1
- radius: 3
- gradient: Gradient {
- GradientStop { position: 0.20; color: "#888888" }
- GradientStop { position: 0.23; color: "#656565" }
- GradientStop { position: 0.85; color: "#393939" }
- }
+ color: "#656565"
MouseArea {
property int dragging:0;
diff --git a/src/plugins/qmldesigner/componentsplugin/Controls/ButtonSpecifics.qml b/src/plugins/qmldesigner/componentsplugin/Controls/ButtonSpecifics.qml
index 4633c06fc3..f02154a92a 100644
--- a/src/plugins/qmldesigner/componentsplugin/Controls/ButtonSpecifics.qml
+++ b/src/plugins/qmldesigner/componentsplugin/Controls/ButtonSpecifics.qml
@@ -135,7 +135,7 @@ Column {
Label {
text: qsTr("Focus on press")
- toolTip: "Determines whether the check box gets focus if pressed."
+ toolTip: "Determines whether the button gets focus if pressed."
}
SecondColumnLayout {
diff --git a/src/plugins/qmldesigner/componentsplugin/Controls/CheckBoxSpecifics.qml b/src/plugins/qmldesigner/componentsplugin/Controls/CheckBoxSpecifics.qml
index 7ec2cfd91d..6384c65e01 100644
--- a/src/plugins/qmldesigner/componentsplugin/Controls/CheckBoxSpecifics.qml
+++ b/src/plugins/qmldesigner/componentsplugin/Controls/CheckBoxSpecifics.qml
@@ -44,7 +44,7 @@ Column {
Label {
text: qsTr("Text")
- toolTip: qsTr("The text shown on the check button")
+ toolTip: qsTr("The text shown on the check box")
}
SecondColumnLayout {
@@ -59,7 +59,7 @@ Column {
Label {
text: qsTr("Checked")
- toolTip: qsTr("The state of the check button")
+ toolTip: qsTr("The state of the check box")
}
SecondColumnLayout {
@@ -75,7 +75,7 @@ Column {
Label {
text: qsTr("Focus on press")
- toolTip: "Determines whether the check box gets focus if pressed."
+ toolTip: qsTr("Determines whether the check box gets focus if pressed.")
}
SecondColumnLayout {
diff --git a/src/plugins/qmldesigner/componentsplugin/Controls/TextAreaSpecifics.qml b/src/plugins/qmldesigner/componentsplugin/Controls/TextAreaSpecifics.qml
index 9bd9a5c56c..7c031333ee 100644
--- a/src/plugins/qmldesigner/componentsplugin/Controls/TextAreaSpecifics.qml
+++ b/src/plugins/qmldesigner/componentsplugin/Controls/TextAreaSpecifics.qml
@@ -58,7 +58,7 @@ Column {
Label {
text: qsTr("Text")
- toolTip: qsTr("The text shown on the button")
+ toolTip: qsTr("The text shown on the text area")
}
SecondColumnLayout {
@@ -73,7 +73,7 @@ Column {
Label {
text: qsTr("Read only")
- toolTip: qsTr("Determines whether the text field is read only.")
+ toolTip: qsTr("Determines whether the text area is read only.")
}
SecondColumnLayout {
diff --git a/src/plugins/qmldesigner/componentsplugin/Controls/TextFieldSpecifics.qml b/src/plugins/qmldesigner/componentsplugin/Controls/TextFieldSpecifics.qml
index 7bad915625..4967a34021 100644
--- a/src/plugins/qmldesigner/componentsplugin/Controls/TextFieldSpecifics.qml
+++ b/src/plugins/qmldesigner/componentsplugin/Controls/TextFieldSpecifics.qml
@@ -44,7 +44,7 @@ Column {
Label {
text: qsTr("Text")
- toolTip: qsTr("The text shown on the button")
+ toolTip: qsTr("The text shown on the text field")
}
SecondColumnLayout {
diff --git a/src/plugins/qmlprofiler/qmlprofilereventview.cpp b/src/plugins/qmlprofiler/qmlprofilereventview.cpp
index 01d8504510..6790478a52 100644
--- a/src/plugins/qmlprofiler/qmlprofilereventview.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilereventview.cpp
@@ -524,7 +524,7 @@ void QmlProfilerEventsMainView::parseModelProxy()
QString toolTipText;
if (event.eventType == Binding) {
if (event.bindingType == (int)OptimizedBinding) {
- typeString = typeString + tr(" (Opt)");
+ typeString = typeString + QLatin1Char(' ') + tr("(Opt)");
toolTipText = tr("Binding is evaluated by the optimized engine.");
} else if (event.bindingType == (int)V8Binding) {
toolTipText = tr("Binding not optimized (e.g. has side effects or assignments,\n"
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
index f133d802b9..2d17f24d5b 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
@@ -37,11 +37,13 @@
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
#include <projectexplorer/target.h>
-#include <utils/qtcprocess.h>
#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtoutputformatter.h>
#include <qtsupport/qtsupportconstants.h>
+#include <utils/fileutils.h>
+#include <utils/qtcprocess.h>
+
#ifdef Q_OS_WIN
#include <utils/winutils.h>
#endif
@@ -159,13 +161,7 @@ QString QmlProjectRunConfiguration::workingDirectory() const
is exactly like the capitalization on disk.*/
QString QmlProjectRunConfiguration::canonicalCapsPath(const QString &fileName)
{
- QString canonicalPath = QFileInfo(fileName).canonicalFilePath();
-
-#if defined(Q_OS_WIN)
- canonicalPath = Utils::normalizePathName(canonicalPath);
-#endif
-
- return canonicalPath;
+ return Utils::FileUtils::normalizePathName(QFileInfo(fileName).canonicalFilePath());
}
diff --git a/src/plugins/qnx/blackberryapplicationrunner.cpp b/src/plugins/qnx/blackberryapplicationrunner.cpp
index 7e2ed84025..8178f2b3af 100644
--- a/src/plugins/qnx/blackberryapplicationrunner.cpp
+++ b/src/plugins/qnx/blackberryapplicationrunner.cpp
@@ -32,6 +32,7 @@
#include "blackberryapplicationrunner.h"
#include "blackberrydeployconfiguration.h"
+#include "blackberrydeviceconnectionmanager.h"
#include "blackberryrunconfiguration.h"
#include "blackberrylogprocessrunner.h"
#include "qnxconstants.h"
@@ -94,28 +95,17 @@ BlackBerryApplicationRunner::BlackBerryApplicationRunner(bool debugMode, BlackBe
void BlackBerryApplicationRunner::start()
{
- QStringList args;
- args << QLatin1String("-launchApp");
- if (m_debugMode)
- args << QLatin1String("-debugNative");
- args << QLatin1String("-device") << m_sshParams.host;
- if (!m_sshParams.password.isEmpty())
- args << QLatin1String("-password") << m_sshParams.password;
- args << QDir::toNativeSeparators(m_barPackage);
-
- if (!m_launchProcess) {
- m_launchProcess = new QProcess(this);
- connect(m_launchProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStandardError()));
- connect(m_launchProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStandardOutput()));
- connect(m_launchProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
- this, SLOT(startFinished(int,QProcess::ExitStatus)));
-
- m_launchProcess->setEnvironment(m_environment.toStringList());
+ if (!BlackBerryDeviceConnectionManager::instance()->isConnected(m_device->id())) {
+ connect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(deviceConnected()),
+ this, SLOT(launchApplication()));
+ connect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(deviceDisconnected(Core::Id)),
+ this, SLOT(disconnectFromDeviceSignals(Core::Id)));
+ connect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(connectionOutput(Core::Id,QString)),
+ this, SLOT(displayConnectionOutput(Core::Id,QString)));
+ BlackBerryDeviceConnectionManager::instance()->connectDevice(m_device->id());
+ } else {
+ launchApplication();
}
-
- m_launchProcess->start(m_deployCmd, args);
- m_runningStateTimer->start();
- m_running = true;
}
void BlackBerryApplicationRunner::startLogProcessRunner()
@@ -130,6 +120,17 @@ void BlackBerryApplicationRunner::startLogProcessRunner()
m_logProcessRunner->start();
}
+void BlackBerryApplicationRunner::displayConnectionOutput(Core::Id deviceId, const QString &msg)
+{
+ if (deviceId != m_device->id())
+ return;
+
+ if (msg.contains(QLatin1String("Info:")))
+ emit output(msg, Utils::StdOutFormat);
+ else if (msg.contains(QLatin1String("Error:")))
+ emit output(msg, Utils::StdErrFormat);
+}
+
void BlackBerryApplicationRunner::startFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
if (exitCode == 0 && exitStatus == QProcess::NormalExit && m_pid > -1) {
@@ -214,6 +215,18 @@ void BlackBerryApplicationRunner::readStandardError()
}
}
+void BlackBerryApplicationRunner::disconnectFromDeviceSignals(Core::Id deviceId)
+{
+ if (m_device->id() == deviceId) {
+ disconnect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(deviceConnected()),
+ this, SLOT(launchApplication()));
+ disconnect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(deviceDisconnected(Core::Id)),
+ this, SLOT(disconnectFromDeviceSignals(Core::Id)));
+ disconnect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(connectionOutput(Core::Id,QString)),
+ this, SLOT(displayConnectionOutput(Core::Id,QString)));
+ }
+}
+
void BlackBerryApplicationRunner::setPid(qint64 pid)
{
m_pid = pid;
@@ -224,6 +237,37 @@ void BlackBerryApplicationRunner::setApplicationId(const QString &applicationId)
m_appId = applicationId;
}
+void BlackBerryApplicationRunner::launchApplication()
+{
+ // If original device connection fails before launching, this method maybe triggered
+ // if any other device is connected(?)
+ if (!BlackBerryDeviceConnectionManager::instance()->isConnected(m_device->id()))
+ return;
+
+ QStringList args;
+ args << QLatin1String("-launchApp");
+ if (m_debugMode)
+ args << QLatin1String("-debugNative");
+ args << QLatin1String("-device") << m_sshParams.host;
+ if (!m_sshParams.password.isEmpty())
+ args << QLatin1String("-password") << m_sshParams.password;
+ args << QDir::toNativeSeparators(m_barPackage);
+
+ if (!m_launchProcess) {
+ m_launchProcess = new QProcess(this);
+ connect(m_launchProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStandardError()));
+ connect(m_launchProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStandardOutput()));
+ connect(m_launchProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
+ this, SLOT(startFinished(int,QProcess::ExitStatus)));
+
+ m_launchProcess->setEnvironment(m_environment.toStringList());
+ }
+
+ m_launchProcess->start(m_deployCmd, args);
+ m_runningStateTimer->start();
+ m_running = true;
+}
+
void BlackBerryApplicationRunner::startRunningStateTimer()
{
if (m_running)
diff --git a/src/plugins/qnx/blackberryapplicationrunner.h b/src/plugins/qnx/blackberryapplicationrunner.h
index 9f257066d4..3ba06a4785 100644
--- a/src/plugins/qnx/blackberryapplicationrunner.h
+++ b/src/plugins/qnx/blackberryapplicationrunner.h
@@ -82,6 +82,7 @@ private slots:
void readStandardOutput();
void readStandardError();
+ void disconnectFromDeviceSignals(Core::Id deviceId);
void startRunningStateTimer();
void determineRunningState();
void readRunningStateStandardOutput();
@@ -89,8 +90,11 @@ private slots:
void setPid(qint64 pid);
void setApplicationId(const QString &applicationId);
+ void launchApplication();
void startLogProcessRunner();
+ void displayConnectionOutput(Core::Id deviceId, const QString &output);
+
private:
void reset();
diff --git a/src/plugins/qnx/blackberryconfiguration.cpp b/src/plugins/qnx/blackberryconfiguration.cpp
index 78b01a30d8..cc45468e53 100644
--- a/src/plugins/qnx/blackberryconfiguration.cpp
+++ b/src/plugins/qnx/blackberryconfiguration.cpp
@@ -45,6 +45,7 @@
#include <qt4projectmanager/qmakekitinformation.h>
+#include <debugger/debuggeritemmanager.h>
#include <debugger/debuggerkitinformation.h>
#include <QFileInfo>
diff --git a/src/plugins/qnx/blackberrydebugsupport.cpp b/src/plugins/qnx/blackberrydebugsupport.cpp
index e0ae83c181..cbd48c5b4f 100644
--- a/src/plugins/qnx/blackberrydebugsupport.cpp
+++ b/src/plugins/qnx/blackberrydebugsupport.cpp
@@ -51,8 +51,8 @@ BlackBerryDebugSupport::BlackBerryDebugSupport(BlackBerryRunConfiguration *runCo
this, SLOT(handleDebuggerStateChanged(Debugger::DebuggerState)));
connect(m_runner, SIGNAL(started()), this, SLOT(handleStarted()));
- connect(m_runner, SIGNAL(started()), m_runner, SLOT(checkSlog2Info()));
connect(m_runner, SIGNAL(startFailed(QString)), this, SLOT(handleStartFailed(QString)));
+ connect(m_runner, SIGNAL(started()), m_runner, SLOT(checkSlog2Info()));
connect(m_runner, SIGNAL(output(QString,Utils::OutputFormat)),
this, SLOT(handleApplicationOutput(QString,Utils::OutputFormat)));
diff --git a/src/plugins/qnx/blackberrydebugtokenrequestdialog.cpp b/src/plugins/qnx/blackberrydebugtokenrequestdialog.cpp
index d4011d246b..37d8a199e2 100644
--- a/src/plugins/qnx/blackberrydebugtokenrequestdialog.cpp
+++ b/src/plugins/qnx/blackberrydebugtokenrequestdialog.cpp
@@ -191,7 +191,7 @@ void BlackBerryDebugTokenRequestDialog::expandPath()
void BlackBerryDebugTokenRequestDialog::debugTokenArrived(int status)
{
- QString errorString = tr("Failed to request debug token: ");
+ QString errorString = tr("Failed to request debug token:") + QLatin1Char(' ');
switch (status) {
case BlackBerryDebugTokenRequester::Success:
diff --git a/src/plugins/qnx/blackberrydeviceconfigurationwidget.cpp b/src/plugins/qnx/blackberrydeviceconfigurationwidget.cpp
index 76c02a3303..cb762f41de 100644
--- a/src/plugins/qnx/blackberrydeviceconfigurationwidget.cpp
+++ b/src/plugins/qnx/blackberrydeviceconfigurationwidget.cpp
@@ -165,7 +165,7 @@ void BlackBerryDeviceConfigurationWidget::uploadFinished(int status)
{
progressDialog->hide();
- QString errorString = tr("Failed to upload debug token: ");
+ QString errorString = tr("Failed to upload debug token:") + QLatin1Char(' ');
switch (status) {
case BlackBerryDebugTokenUploader::Success:
diff --git a/src/plugins/qnx/blackberrydeviceconfigurationwizardpages.cpp b/src/plugins/qnx/blackberrydeviceconfigurationwizardpages.cpp
index 342a2bd93f..96b4c48687 100644
--- a/src/plugins/qnx/blackberrydeviceconfigurationwizardpages.cpp
+++ b/src/plugins/qnx/blackberrydeviceconfigurationwizardpages.cpp
@@ -290,7 +290,8 @@ void BlackBerryDeviceConfigurationWizardQueryPage::sshKeysGenerationFailed(const
if (m_state != GeneratingSshKey)
return;
- QString message = tr("Failed generating SSH key needed for securing connection to a device. Error: ");
+ QString message = tr("Failed generating SSH key needed for securing connection to a device. Error:");
+ message += QLatin1Char(' ');
message.append(error);
setState(Done, message);
}
@@ -310,7 +311,8 @@ void BlackBerryDeviceConfigurationWizardQueryPage::processSshKeys(const QByteArr
if (! BlackBerryDeviceConnectionManager::instance()->hasValidSSHKeys()) {
QString error;
if (!BlackBerryDeviceConnectionManager::instance()->setSSHKeys(privateKey, publicKey, &error)) {
- QString message = tr("Failed saving SSH key needed for securing connection to a device. Error: ");
+ QString message = tr("Failed saving SSH key needed for securing connection to a device. Error:");
+ message += QLatin1Char(' ');
message.append(error);
setState(Done, message);
return;
diff --git a/src/plugins/qnx/blackberrydeviceconnection.cpp b/src/plugins/qnx/blackberrydeviceconnection.cpp
index 9b80986370..3db96567a5 100644
--- a/src/plugins/qnx/blackberrydeviceconnection.cpp
+++ b/src/plugins/qnx/blackberrydeviceconnection.cpp
@@ -62,8 +62,7 @@ BlackBerryDeviceConnection::BlackBerryDeviceConnection() :
void BlackBerryDeviceConnection::connectDevice(const ProjectExplorer::IDevice::ConstPtr &device)
{
Utils::Environment env = Utils::Environment::systemEnvironment();
- foreach (const Utils::EnvironmentItem &item, BlackBerryConfigurationManager::instance().defaultQnxEnv())
- env.appendOrSet(item.name, item.value);
+ env.modify(BlackBerryConfigurationManager::instance().defaultQnxEnv());
m_process->setEnvironment(env.toStringList());
diff --git a/src/plugins/qnx/blackberrydeviceconnectionmanager.cpp b/src/plugins/qnx/blackberrydeviceconnectionmanager.cpp
index fa549d70db..ad0c308295 100644
--- a/src/plugins/qnx/blackberrydeviceconnectionmanager.cpp
+++ b/src/plugins/qnx/blackberrydeviceconnectionmanager.cpp
@@ -278,9 +278,11 @@ void BlackBerryDeviceConnectionManager::handleDeviceDisconnected()
QTC_ASSERT(connection, return);
QList<Core::Id> disconnectedDevices = m_connections.values(connection);
- foreach (Core::Id id, disconnectedDevices)
+ foreach (Core::Id id, disconnectedDevices) {
ProjectExplorer::DeviceManager::instance()->setDeviceState(id,
ProjectExplorer::IDevice::DeviceDisconnected);
+ emit deviceDisconnected(id);
+ }
}
void BlackBerryDeviceConnectionManager::handleDeviceAboutToConnect()
diff --git a/src/plugins/qnx/blackberrydeviceconnectionmanager.h b/src/plugins/qnx/blackberrydeviceconnectionmanager.h
index a211f505e9..b9a5e10909 100644
--- a/src/plugins/qnx/blackberrydeviceconnectionmanager.h
+++ b/src/plugins/qnx/blackberrydeviceconnectionmanager.h
@@ -69,6 +69,7 @@ signals:
void connectionOutput(Core::Id deviceId, const QString &output);
void deviceAboutToConnect(Core::Id deviceId);
void deviceConnected();
+ void deviceDisconnected(Core::Id deviceId);
public slots:
void connectDevice(Core::Id deviceId);
diff --git a/src/plugins/qnx/blackberryruncontrol.cpp b/src/plugins/qnx/blackberryruncontrol.cpp
index f372452bc7..564329fa57 100644
--- a/src/plugins/qnx/blackberryruncontrol.cpp
+++ b/src/plugins/qnx/blackberryruncontrol.cpp
@@ -34,8 +34,6 @@
#include "blackberryrunconfiguration.h"
#include "blackberrydeviceconnectionmanager.h"
-#include <projectexplorer/target.h>
-
#include <QIcon>
#include <QTimer>
@@ -45,7 +43,6 @@ using namespace Qnx::Internal;
BlackBerryRunControl::BlackBerryRunControl(BlackBerryRunConfiguration *runConfiguration)
: ProjectExplorer::RunControl(runConfiguration, ProjectExplorer::NormalRunMode)
{
- m_device = BlackBerryDeviceConfiguration::device(runConfiguration->target()->kit());
m_runner = new BlackBerryApplicationRunner(false, runConfiguration, this);
connect(m_runner, SIGNAL(started()), this, SIGNAL(started()));
@@ -57,7 +54,7 @@ BlackBerryRunControl::BlackBerryRunControl(BlackBerryRunConfiguration *runConfig
void BlackBerryRunControl::start()
{
- checkDeviceConnection();
+ m_runner->start();
}
ProjectExplorer::RunControl::StopResult BlackBerryRunControl::stop()
@@ -79,32 +76,3 @@ void BlackBerryRunControl::handleStartFailed(const QString &message)
{
appendMessage(message, Utils::StdErrFormat);
}
-
-void BlackBerryRunControl::handleDeviceConnected()
-{
- m_runner->start();
-}
-
-void BlackBerryRunControl::displayConnectionOutput(Core::Id deviceId, const QString &output)
-{
- if (deviceId != m_device->id())
- return;
-
- if (output.contains(QLatin1String("Info:")))
- appendMessage(output, Utils::StdOutFormat);
- else if (output.contains(QLatin1String("Error:")))
- appendMessage(output, Utils::StdErrFormat);
-}
-
-void BlackBerryRunControl::checkDeviceConnection()
-{
- if (!BlackBerryDeviceConnectionManager::instance()->isConnected(m_device->id())) {
- connect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(deviceConnected()),
- this, SLOT(handleDeviceConnected()));
- connect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(connectionOutput(Core::Id,QString)),
- this, SLOT(displayConnectionOutput(Core::Id,QString)));
- BlackBerryDeviceConnectionManager::instance()->connectDevice(m_device->id());
- } else {
- m_runner->start();
- }
-}
diff --git a/src/plugins/qnx/blackberryruncontrol.h b/src/plugins/qnx/blackberryruncontrol.h
index 787add054b..ab061407d0 100644
--- a/src/plugins/qnx/blackberryruncontrol.h
+++ b/src/plugins/qnx/blackberryruncontrol.h
@@ -32,8 +32,6 @@
#ifndef QNX_INTERNAL_BLACKBERRYRUNCONTROL_H
#define QNX_INTERNAL_BLACKBERRYRUNCONTROL_H
-#include "blackberrydeviceconfiguration.h"
-
#include <projectexplorer/runconfiguration.h>
namespace QmakeProjectManager {
@@ -60,13 +58,9 @@ public:
private slots:
void handleStartFailed(const QString &message);
- void handleDeviceConnected();
- void displayConnectionOutput(Core::Id deviceId, const QString &output);
- void checkDeviceConnection();
private:
BlackBerryApplicationRunner *m_runner;
- BlackBerryDeviceConfiguration::ConstPtr m_device;
};
} // namespace Internal
diff --git a/src/plugins/qnx/blackberrysetupwizard.cpp b/src/plugins/qnx/blackberrysetupwizard.cpp
index 43cc73a7c0..e5214b0a0f 100644
--- a/src/plugins/qnx/blackberrysetupwizard.cpp
+++ b/src/plugins/qnx/blackberrysetupwizard.cpp
@@ -176,7 +176,7 @@ void BlackBerrySetupWizard::certificateCreated(int status)
void BlackBerrySetupWizard::debugTokenArrived(int status)
{
- QString errorString = tr("Failed to request debug token: ");
+ QString errorString = tr("Failed to request debug token:") + QLatin1Char(' ');
switch (status) {
case BlackBerryDebugTokenRequester::Success:
@@ -222,7 +222,7 @@ void BlackBerrySetupWizard::debugTokenArrived(int status)
void BlackBerrySetupWizard::uploaderFinished(int status)
{
- QString errorString = tr("Failed to upload debug token: ");
+ QString errorString = tr("Failed to upload debug token:") + QLatin1Char(' ');
switch (status) {
case BlackBerryDebugTokenUploader::Success:
diff --git a/src/plugins/qt4projectmanager/librarydetailscontroller.cpp b/src/plugins/qt4projectmanager/librarydetailscontroller.cpp
index 7253684966..3f79461f3c 100644
--- a/src/plugins/qt4projectmanager/librarydetailscontroller.cpp
+++ b/src/plugins/qt4projectmanager/librarydetailscontroller.cpp
@@ -103,7 +103,6 @@ LibraryDetailsController::LibraryDetailsController(
}
}
}
-
setPlatformsVisible(true);
setLinkageGroupVisible(true);
setMacLibraryGroupVisible(true);
diff --git a/src/plugins/qt4projectmanager/qmakestep.cpp b/src/plugins/qt4projectmanager/qmakestep.cpp
index 5331ece972..0980c48982 100644
--- a/src/plugins/qt4projectmanager/qmakestep.cpp
+++ b/src/plugins/qt4projectmanager/qmakestep.cpp
@@ -166,11 +166,6 @@ QStringList QMakeStep::deducedArguments()
ProjectExplorer::Abi targetAbi;
if (tc)
targetAbi = tc->targetAbi();
- if ((HostOsInfo::isWindowsHost() || HostOsInfo::isMacHost())
- && (targetAbi.osFlavor() == ProjectExplorer::Abi::HarmattanLinuxFlavor
- || targetAbi.osFlavor() == ProjectExplorer::Abi::MaemoLinuxFlavor)) {
- arguments << QLatin1String("-unix");
- }
// explicitly add architecture to CONFIG
if ((targetAbi.os() == ProjectExplorer::Abi::MacOS)
diff --git a/src/plugins/qt4projectmanager/wizards/qtquickapp.cpp b/src/plugins/qt4projectmanager/wizards/qtquickapp.cpp
index b252083f89..5965088f25 100644
--- a/src/plugins/qt4projectmanager/wizards/qtquickapp.cpp
+++ b/src/plugins/qt4projectmanager/wizards/qtquickapp.cpp
@@ -29,6 +29,9 @@
#include "qtquickapp.h"
+#include <utils/qtcassert.h>
+
+#include <QDebug>
#include <QDir>
#include <QFile>
#include <QTextStream>
@@ -113,15 +116,25 @@ QString QtQuickApp::originsRoot() const
switch (m_componentSet) {
case QtQuickControls10: return templatesRoot() + QLatin1String("qtquick2controls/");
case QtQuick20Components: return templatesRoot() + QLatin1String("qtquick2app/");
- default: break;
+ case QtQuick10Components: return templatesRoot() + QLatin1String("qtquick1app/");
}
- return templatesRoot() + QLatin1String("qtquickapp/");
+ qWarning() << "QtQuickApp::originsRoot() - unhandled component set"
+ << m_componentSet;
+ return QString();
}
QString QtQuickApp::mainWindowClassName() const
{
- return QLatin1String("QmlApplicationViewer");
+ switch (m_componentSet) {
+ case QtQuickControls10: return QLatin1String("QtQuick2ControlsApplicationViewer");
+ case QtQuick20Components: return QLatin1String("QtQuick2ApplicationViewer");
+ case QtQuick10Components: return QLatin1String("QtQuick1ApplicationViewer");
+ }
+
+ qWarning() << "QtQuickApp::mainWindowClassName() - unhandled component set"
+ << m_componentSet;
+ return QString();
}
bool QtQuickApp::adaptCurrentMainCppTemplateLine(QString &line) const
@@ -174,12 +187,15 @@ bool QtQuickApp::useExistingMainQml() const
QString QtQuickApp::appViewerBaseName() const
{
- if (m_componentSet == QtQuick20Components) {
- return QLatin1String("qtquick2applicationviewer");
- } else if (m_componentSet == QtQuickControls10) {
- return QLatin1String("qtquick2controlsapplicationviewer");
+ switch (m_componentSet) {
+ case QtQuickControls10: return QLatin1String("qtquick2controlsapplicationviewer");
+ case QtQuick20Components: return QLatin1String("qtquick2applicationviewer");
+ case QtQuick10Components: return QLatin1String("qtquick1applicationviewer");
}
- return QLatin1String("qmlapplicationviewer");
+
+ qWarning() << "QtQuickApp::appViewerBaseName() - unhandled component set"
+ << m_componentSet;
+ return QString();
}
QString QtQuickApp::fileName(QtQuickApp::ExtendedFileType type) const
diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp
index ced6d1defe..7e08dc3493 100644
--- a/src/plugins/qtsupport/baseqtversion.cpp
+++ b/src/plugins/qtsupport/baseqtversion.cpp
@@ -1475,16 +1475,6 @@ bool BaseQtVersion::isQmlDebuggingSupported(QString *reason) const
if (!needsQmlDebuggingLibrary() || hasQmlDebuggingLibrary())
return true;
- if (!qtAbis().isEmpty()) {
- Abi abi = qtAbis().first();
- if (abi.osFlavor() == Abi::MaemoLinuxFlavor) {
- if (reason)
- reason->clear();
- // *reason = QCoreApplication::translate("BaseQtVersion", "Qml debugging on device not yet supported.");
- return false;
- }
- }
-
if (!isValid()) {
if (reason)
*reason = QCoreApplication::translate("BaseQtVersion", "Invalid Qt version.");
diff --git a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp
index a514b0d3b0..54d4ea1123 100644
--- a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp
+++ b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp
@@ -241,11 +241,8 @@ QString ExamplesWelcomePage::title() const
QUrl ExamplesWelcomePage::pageLocation() const
{
- QString resourcePath = Core::ICore::resourcePath();
-#ifdef Q_OS_WIN
// normalize paths so QML doesn't freak out if it's wrongly capitalized on Windows
- resourcePath = Utils::normalizePathName(resourcePath);
-#endif
+ const QString resourcePath = Utils::FileUtils::normalizePathName(Core::ICore::resourcePath());
if (m_showExamples)
return QUrl::fromLocalFile(resourcePath + QLatin1String("/welcomescreen/examples.qml"));
else
diff --git a/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp b/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp
index 015a2ea6d0..a4b26fef31 100644
--- a/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp
+++ b/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp
@@ -102,7 +102,7 @@ QList<Core::Id> RemoteLinuxRunConfigurationFactory::availableCreationIds(Target
QString RemoteLinuxRunConfigurationFactory::displayNameForId(const Core::Id id) const
{
return QFileInfo(pathFromId(id)).completeBaseName()
- + tr(" (on Remote Generic Linux Host)");
+ + QLatin1Char(' ') + tr("(on Remote Generic Linux Host)");
}
RunConfiguration *RemoteLinuxRunConfigurationFactory::doCreate(Target *parent, const Core::Id id)
diff --git a/src/plugins/remotelinux/remotelinuxsignaloperation.cpp b/src/plugins/remotelinux/remotelinuxsignaloperation.cpp
index bdfb67a787..e3f96e2713 100644
--- a/src/plugins/remotelinux/remotelinuxsignaloperation.cpp
+++ b/src/plugins/remotelinux/remotelinuxsignaloperation.cpp
@@ -120,7 +120,8 @@ void RemoteLinuxSignalOperation::runnerProcessFinished()
if (m_runner->processExitStatus() != QSsh::SshRemoteProcess::NormalExit) {
m_errorMessage = m_runner->processErrorString();
} else if (m_runner->processExitCode() != 0) {
- m_errorMessage = tr("Exit code is %1. stderr: ").arg(m_runner->processExitCode())
+ m_errorMessage = tr("Exit code is %1. stderr:").arg(m_runner->processExitCode())
+ + QLatin1Char(' ')
+ QString::fromLatin1(m_runner->readAllStandardError());
}
finish();
diff --git a/src/plugins/texteditor/behaviorsettingswidget.cpp b/src/plugins/texteditor/behaviorsettingswidget.cpp
index b21c709c21..044b2a328d 100644
--- a/src/plugins/texteditor/behaviorsettingswidget.cpp
+++ b/src/plugins/texteditor/behaviorsettingswidget.cpp
@@ -77,6 +77,13 @@ BehaviorSettingsWidget::BehaviorSettingsWidget(QWidget *parent)
d->m_codecs.append(codec);
}
+ // Qt5 doesn't list the system locale (QTBUG-34283), so add it manually
+ const QString system(QLatin1String("System"));
+ if (d->m_ui.encodingBox->findText(system) == -1) {
+ d->m_ui.encodingBox->insertItem(0, system);
+ d->m_codecs.prepend(QTextCodec::codecForLocale());
+ }
+
connect(d->m_ui.autoIndent, SIGNAL(toggled(bool)),
this, SLOT(slotTypingSettingsChanged()));
connect(d->m_ui.smartBackspaceBehavior, SIGNAL(currentIndexChanged(int)),
diff --git a/src/plugins/valgrind/memcheck/memcheckrunner.cpp b/src/plugins/valgrind/memcheck/memcheckrunner.cpp
index 6827f6b47d..91033203f6 100644
--- a/src/plugins/valgrind/memcheck/memcheckrunner.cpp
+++ b/src/plugins/valgrind/memcheck/memcheckrunner.cpp
@@ -168,14 +168,14 @@ bool MemcheckRunner::start()
}
bool check = d->xmlServer.listen(hostAddr);
- if (!check) emit processErrorReceived( tr("XmlServer on %1: ").arg(ip) + d->xmlServer.errorString(), QProcess::FailedToStart );
+ if (!check) emit processErrorReceived( tr("XmlServer on %1:").arg(ip) + QLatin1Char(' ') + d->xmlServer.errorString(), QProcess::FailedToStart );
QTC_ASSERT(check, return false);
d->xmlServer.setMaxPendingConnections(1);
const quint16 xmlPortNumber = d->xmlServer.serverPort();
connect(&d->xmlServer, SIGNAL(newConnection()), SLOT(xmlSocketConnected()));
check = d->logServer.listen(hostAddr);
- if (!check) emit processErrorReceived( tr("LogServer on %1: ").arg(ip) + d->logServer.errorString(), QProcess::FailedToStart );
+ if (!check) emit processErrorReceived( tr("LogServer on %1:").arg(ip) + QLatin1Char(' ') + d->logServer.errorString(), QProcess::FailedToStart );
QTC_ASSERT(check, return false);
d->logServer.setMaxPendingConnections(1);
const quint16 logPortNumber = d->logServer.serverPort();
diff --git a/src/plugins/welcome/welcomeplugin.cpp b/src/plugins/welcome/welcomeplugin.cpp
index 202645a5d4..da1aa21fb3 100644
--- a/src/plugins/welcome/welcomeplugin.cpp
+++ b/src/plugins/welcome/welcomeplugin.cpp
@@ -40,6 +40,7 @@
#include <projectexplorer/projectexplorer.h>
+#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <utils/styledbar.h>
#include <utils/iwelcomepage.h>
@@ -208,22 +209,14 @@ void WelcomeMode::facilitateQml(QQmlEngine * /*engine*/)
static QString applicationDirPath()
{
-#ifdef Q_OS_WIN
// normalize paths so QML doesn't freak out if it's wrongly capitalized on Windows
- return Utils::normalizePathName(QCoreApplication::applicationDirPath());
-#else
- return QCoreApplication::applicationDirPath();
-#endif
+ return Utils::FileUtils::normalizePathName(QCoreApplication::applicationDirPath());
}
static QString resourcePath()
{
-#ifdef Q_OS_WIN
// normalize paths so QML doesn't freak out if it's wrongly capitalized on Windows
- return Utils::normalizePathName(Core::ICore::resourcePath());
-#else
- return Core::ICore::resourcePath();
-#endif
+ return Utils::FileUtils::normalizePathName(Core::ICore::resourcePath());
}
void WelcomeMode::initPlugins()
diff --git a/src/tools/qtcreatorcrashhandler/crashhandlerdialog.cpp b/src/tools/qtcreatorcrashhandler/crashhandlerdialog.cpp
index 90b131f313..f95755bbdd 100644
--- a/src/tools/qtcreatorcrashhandler/crashhandlerdialog.cpp
+++ b/src/tools/qtcreatorcrashhandler/crashhandlerdialog.cpp
@@ -134,7 +134,7 @@ void CrashHandlerDialog::setApplicationInfo(const QString &signalName)
QString revision;
#ifdef IDE_REVISION
- revision = tr(" from revision %1").arg(QString::fromLatin1(Core::Constants::IDE_REVISION_STR).left(10));
+ revision = QLatin1Char(' ') + tr("from revision %1").arg(QString::fromLatin1(Core::Constants::IDE_REVISION_STR).left(10));
#endif
const QString versionInformation = tr(
"%1 %2%3, built on %4 at %5, based on Qt %6 (%7 bit)\n")