Merge remote-tracking branch 'origin/4.4'

Conflicts:
	qtcreator.pri

Change-Id: Ibb67815f6bb33a4c5ddc33b71f9c436624685e11
This commit is contained in:
Eike Ziller
2017-07-10 09:59:56 +02:00
86 changed files with 965 additions and 529 deletions

View File

@@ -8,7 +8,7 @@ The standalone binary packages support the following platforms:
* Windows 7 or later
* (K)Ubuntu Linux 16.04 (64-bit) or later
* macOS 10.8 or later
* macOS 10.10 or later
## Compiling Qt Creator

View File

@@ -1160,10 +1160,160 @@
mode, select \uicontrol Edit > \uicontrol Advanced >
\uicontrol {Use Vim-style Editing} or press \key {Alt+V,Alt+V}.
\section1 Supported Modes and Commands
In the \uicontrol FakeVim mode, most keystrokes in the main editor will be
intercepted and interpreted in a way that resembles Vim. Documentation for
Vim is not included in \QC. For more information on using Vim, see
\l{http://www.vim.org/docs.php}{Documentation} on the Vim web site.
intercepted and interpreted in a way that resembles Vim. Most of the
supported commands can be followed by a motion command or executed in visual
mode, or they work with registers or can be prefixed with a number of
repetitions.
The following sections describe the commands emulated in the supported modes
and how they diverge from Vim in functionality:
\list
\li Normal
\li Visual
\li Command line (:)
\li Insert and replace
\endlist
For more information on using Vim, see \l{http://www.vim.org/docs.php}
{Documentation} on the Vim web site.
\section2 Normal and Visual Modes
\list
\li Basic movement, such as \c h/j/k/l, \c <C-U>, \c <C-D>, \c <C-F>,
\c <C-B>, \c gg, \c G, \c 0, \c ^, \c $
\li Word movement, such as \c w, \c e, \c b
\li \e Inner/a movement, such as \c ciw, \c 3daw, ya{
\li \c f and \c t movement
\li \c [ and \c ] movement
\li { and } paragraph movement
\li Delete/change/yank/paste with register
\li Undo and redo
\li \c <C-A> and \c <C-X> increase or decrease a number in decimal,
octal, or hexadecimal format (for example \c 128<C-A> on or before
\c "0x0ff" changes it to \c "0x17f")
\li \c . repeats the last change
\li \c /search, \c ?search, \c *, \c #, \c n, \c N - most of regular
expression syntax is used in Vim except that \c \< and \c \> are
the same as \c {\b} in QRegExp
\li \c @ and \c q (macro recording and execution) special keys are saved
as \c <S-Left>
\li Marks
\li \c gv goes to last visual selection; can differ if text is edited
around it
\li Indentation using \c =, \c <<, \c >>, with movement, count, and in
visual mode
\li \e {to upper/lower}, such as \c ~, \c gU, \c gu
\li \c i, \c a, \c o, \c I, \c A, and \c O enter insert mode
\li Scroll window, such as \c zt, \c zb, \c zz
\li Wrap line movement, such as \c gj, \c gk, \c g0, \c g^, \c g$
\endlist
\section2 Command Line Mode
\list
\li \c :map, \c :unmap, \c :inoremap, and so on
\li \c :source provides very basic line-by-line sourcing of vimrc files
\li \c :substitute substitutes an expression in a range
\li \c :'<,'>!cmd filters through an external command (for example,
sorts the lines in a file with \c :%!sort)
\li \c :.!cmd inserts the standard output of an external command
\li \c :read
\li \c :yank, \c :delete, \c :change
\li \c :move, \c :join
\li \c :20 goes to an address
\li \c :history
\li \c :registers, \c :display
\li \c :nohlsearch
\li \c :undo, \c :redo
\li \c :normal
\li \c :<, \c :>
\endlist
\section2 Insert Mode
\list
\li \c <C-O> executes a single command and returns to insert mode
\li \c <C-V> inserts a raw character
\li \c <insert> toggles replace mode
\endlist
\section2 Options
Use \c {:set ...} to set the following options:
\list
\li \c autoindent
\li \c clipboard
\li \c backspace
\li \c expandtab
\li \c hlsearch
\li \c ignorecase
\li \c incsearch
\li \c indent
\li \c iskeyword
\li \c scrolloff
\li \c shiftwidth
\li \c showcmd
\li \c smartcase
\li \c smartindent
\li \c smarttab
\li \c startofline
\li \c tabstop
\li \c tildeop
\li \c wrapscan
\endlist
\section2 Vimrc Example
\code
" highlight matched
set hlsearch
" case insensitive search
set ignorecase
set smartcase
" search while typing
set incsearch
" wrap-around when searching
set wrapscan
" show pressed keys in lower right corner
set showcmd
" tab -> spaces
set expandtab
set tabstop=4
set shiftwidth=4
" keep a 5 line buffer for the cursor from top/bottom of window
set scrolloff=5
" X11 clipboard
set clipboard=unnamed
" use ~ with movement
set tildeop
" mappings
nnoremap ; :
inoremap jj <Esc>
" clear highlighted search term on space
noremap <silent> <Space> :nohls<CR>
" reselect visual block after indent
vnoremap < <gv
vnoremap > >gv
" MOVE LINE/BLOCK
nnoremap <C-S-J> :m+<CR>==
nnoremap <C-S-K> :m-2<CR>==
inoremap <C-S-J> <Esc>:m+<CR>==gi
inoremap <C-S-K> <Esc>:m-2<CR>==gi
vnoremap <C-S-J> :m'>+<CR>gv=gv
vnoremap <C-S-K> :m-2<CR>gv=gv
\endcode
\section1 Mapping FakeVim Commands
To map commands entered on the \uicontrol FakeVim command line to actions
of the \QC core, select \uicontrol Tools > \uicontrol Options >
@@ -1174,6 +1324,8 @@
\uicontrol {User Command Mapping}. The user command mapped to the shortcut
is executed by FakeVim as if you were typing it (as when replaying a macro).
\section1 Specifying FakeVim Options
To make changes to the Vim-style settings, select \uicontrol Tools >
\uicontrol Options > \uicontrol FakeVim > \uicontrol General.
@@ -1189,6 +1341,8 @@
\uicontrol Options > \uicontrol {Text Editor} > \uicontrol {Fonts & Color}.
In the \uicontrol {Color Scheme} list, select \uicontrol {Vim (dark)}.
\section1 Quitting FakeVim Mode
To quit the FakeVim mode, unselect \uicontrol Tools > \uicontrol Options >
\uicontrol FakeVim > \uicontrol {Use FakeVim} or press \key {Alt+V,Alt+V}.

View File

@@ -97,7 +97,7 @@
\endlist
\li \macos 10.8 or later with the following:
\li \macos 10.10 or later with the following:
\list

View File

@@ -8,6 +8,7 @@ Product {
version: qtc.qtcreator_version
property bool install: true
property string installDir
property string installSourceBase
property stringList installTags: type
property string fileName: FileInfo.fileName(sourceDirectory) + ".qbs"
property bool useNonGuiPchFile: false
@@ -37,6 +38,7 @@ Product {
fileTagsFilter: installTags
qbs.install: install
qbs.installDir: installDir
qbs.installSourceBase: installSourceBase
}
Group {

View File

@@ -4,7 +4,7 @@ import qbs.FileInfo
Project {
name: "Qt Creator"
minimumQbsVersion: "1.6.0"
minimumQbsVersion: "1.7.0"
property string minimumMacosVersion: "10.8"
property bool withAutotests: qbs.buildVariant === "debug"
property path ide_source_tree: path

View File

@@ -577,6 +577,8 @@ class DumperBase:
#warn("TARGS: %s %s" % (typename, targs))
res = []
for item in targs[::-1]:
if len(item) == 0:
continue
c = ord(item[0])
if c in (45, 46) or (c >= 48 and c < 58): # '-', '.' or digit.
if item.find('.') > -1:

View File

@@ -253,6 +253,6 @@
<key>CFBundleShortVersionString</key>
<string>@SHORT_VERSION@</string>
<key>LSMinimumSystemVersion</key>
<string>10.8</string>
<string>@MACOSX_DEPLOYMENT_TARGET@</string>
</dict>
</plist>

View File

@@ -53,7 +53,12 @@ win32 {
INSTALLS += icns
}
}
QMAKE_INFO_PLIST = Info.plist
infoplist = $$cat($$PWD/Info.plist, blob)
infoplist = $$replace(infoplist, @MACOSX_DEPLOYMENT_TARGET@, $$QMAKE_MACOSX_DEPLOYMENT_TARGET)
write_file($$OUT_PWD/Info.plist, infoplist)
QMAKE_INFO_PLIST = $$OUT_PWD/Info.plist
}
target.path = $$INSTALL_APP_PATH

View File

@@ -20,7 +20,9 @@ QtcProduct {
targetName: qtc.ide_app_target
version: qtc.qtcreator_version
installDir: qtc.ide_bin_path
installDir: bundle.isBundle ? qtc.ide_app_path : qtc.ide_bin_path
installTags: bundle.isBundle ? ["bundle.content"] : base
installSourceBase: bundle.isBundle ? buildDirectory : base
property bool qtcRunnable: true
cpp.rpaths: qbs.targetOS.contains("macos") ? ["@executable_path/../Frameworks"]
@@ -72,11 +74,4 @@ QtcProduct {
"../shared/qtlockedfile/qtlockedfile_win.cpp"
]
}
Group {
condition: qbs.targetOS.contains("macos")
fileTagsFilter: ["aggregate_infoplist", "pkginfo", "compiled_assetcatalog"]
qbs.install: true
qbs.installSourceBase: product.buildDirectory
}
}

View File

@@ -952,7 +952,7 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
return this;
}
if (ClassOrNamespace *e = nestedType(name, origin))
if (ClassOrNamespace *e = nestedType(name, processed, origin))
return e;
if (_templateId) {
@@ -1074,7 +1074,9 @@ ClassOrNamespace *ClassOrNamespace::findOrCreateNestedAnonymousType(
}
}
ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespace *origin)
ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
QSet<ClassOrNamespace *> *processed,
ClassOrNamespace *origin)
{
Q_ASSERT(name != 0);
Q_ASSERT(name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId());
@@ -1184,11 +1186,11 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
instantiation->_name = templId;
instantiation->_templateId = templId;
QSet<ClassOrNamespace *> processed;
QSet<ClassOrNamespace *> otherProcessed;
while (!origin->_symbols.isEmpty() && origin->_symbols[0]->isBlock()) {
if (processed.contains(origin))
if (otherProcessed.contains(origin))
break;
processed.insert(origin);
otherProcessed.insert(origin);
origin = origin->parent();
}
@@ -1310,7 +1312,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
// Another template that uses the dependent name.
// Ex.: template <class T> class A : public B<T> {};
if (baseTemplId->identifier() != templId->identifier())
baseBinding = nestedType(baseName, origin);
baseBinding = nestedType(baseName, processed, origin);
} else if (const QualifiedNameId *qBaseName = baseName->asQualifiedNameId()) {
// Qualified names in general.
// Ex.: template <class T> class A : public B<T>::Type {};
@@ -1361,7 +1363,8 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
}
if (binding) {
ClassOrNamespace * baseBinding = binding->lookupType(baseName);
ClassOrNamespace * baseBinding
= binding->lookupType_helper(baseName, processed, true, this);
if (baseBinding && !knownUsings.contains(baseBinding))
reference->addUsing(baseBinding);
}
@@ -1518,7 +1521,8 @@ ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name, ClassOrNa
return findOrCreateType(q->base(), origin)->findOrCreateType(q->name(), origin, clazz);
} else if (name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) {
ClassOrNamespace *e = nestedType(name, origin);
QSet<ClassOrNamespace *> processed;
ClassOrNamespace *e = nestedType(name, &processed, origin);
if (! e) {
e = _factory->allocClassOrNamespace(this);

View File

@@ -121,7 +121,8 @@ private:
ClassOrNamespace *findBlock_helper(Block *block, QSet<ClassOrNamespace *> *processed,
bool searchInEnclosingScope);
ClassOrNamespace *nestedType(const Name *name, ClassOrNamespace *origin);
ClassOrNamespace *nestedType(const Name *name, QSet<ClassOrNamespace *> *processed,
ClassOrNamespace *origin);
void instantiateNestedClasses(ClassOrNamespace *enclosingTemplateClass,
Clone &cloner,

View File

@@ -27,6 +27,7 @@
#include "algorithm.h"
#include "qtcassert.h"
#include "stringutils.h"
#include <QAbstractButton>
#include <QApplication>
@@ -532,7 +533,7 @@ void FancyMainWindow::addDockActionsToMenu(QMenu *menu)
Utils::sort(actions, [](const QAction *action1, const QAction *action2) {
QTC_ASSERT(action1, return true);
QTC_ASSERT(action2, return false);
return action1->text().toLower() < action2->text().toLower();
return stripAccelerator(action1->text()).toLower() < stripAccelerator(action2->text()).toLower();
});
foreach (QAction *action, actions)
menu->addAction(action);

View File

@@ -238,4 +238,12 @@ QTCREATOR_UTILS_EXPORT QString expandMacros(const QString &str, AbstractMacroExp
return ret;
}
QTCREATOR_UTILS_EXPORT QString stripAccelerator(const QString &text)
{
QString res = text;
for (int index = res.indexOf('&'); index != -1; index = res.indexOf('&', index + 1))
res.remove(index, 1);
return res;
}
} // namespace Utils

View File

@@ -50,6 +50,9 @@ QTCREATOR_UTILS_EXPORT QString commonPath(const QStringList &files);
// If path is not sub of home path, or when running on Windows, returns the input
QTCREATOR_UTILS_EXPORT QString withTildeHomePath(const QString &path);
// Removes first unescaped ampersand in text
QTCREATOR_UTILS_EXPORT QString stripAccelerator(const QString &text);
class QTCREATOR_UTILS_EXPORT AbstractMacroExpander
{
public:

View File

@@ -104,9 +104,11 @@ IDevice::Ptr AndroidDevice::clone() const
return IDevice::Ptr(new AndroidDevice(*this));
}
Connection AndroidDevice::toolControlChannel(const ControlChannelHint &) const
QUrl AndroidDevice::toolControlChannel(const ControlChannelHint &) const
{
return HostName("localhost");
QUrl url;
url.setHost("localhost");
return url;
}
} // namespace Internal

View File

@@ -47,7 +47,7 @@ public:
Utils::OsType osType() const override;
ProjectExplorer::IDevice::Ptr clone() const override;
ProjectExplorer::Connection toolControlChannel(const ControlChannelHint &) const override;
QUrl toolControlChannel(const ControlChannelHint &) const override;
protected:
friend class AndroidDeviceFactory;

View File

@@ -456,7 +456,7 @@ void QtTestOutputReader::sendFinishMessage(bool isFunction)
{
TestResultPtr testResult = TestResultPtr(createDefaultResult());
testResult->setResult(Result::MessageTestCaseEnd);
if (m_duration.isEmpty()) {
if (!m_duration.isEmpty()) {
testResult->setDescription(isFunction ? tr("Execution took %1 ms.").arg(m_duration)
: tr("Test execution took %1 ms.").arg(m_duration));
} else {

View File

@@ -51,6 +51,7 @@ ArtisticStyleOptionsPageWidget::ArtisticStyleOptionsPageWidget(ArtisticStyleSett
ui->specificConfigFile->setExpectedKind(Utils::PathChooser::File);
ui->specificConfigFile->setPromptDialogFilter(tr("AStyle (*.astylerc)"));
ui->command->setExpectedKind(Utils::PathChooser::ExistingCommand);
ui->command->setCommandVersionArguments({"--version"});
ui->command->setPromptDialogTitle(BeautifierPlugin::msgCommandPromptDialogTitle(
ArtisticStyle::tr(Constants::ArtisticStyle::DISPLAY_NAME)));
connect(ui->command, &Utils::PathChooser::validChanged, ui->options, &QWidget::setEnabled);

View File

@@ -201,9 +201,11 @@ bool BeautifierPlugin::initialize(const QStringList &arguments, QString *errorSt
void BeautifierPlugin::extensionsInitialized()
{
m_tools << new ArtisticStyle::ArtisticStyle(this);
m_tools << new ClangFormat::ClangFormat(this);
m_tools << new Uncrustify::Uncrustify(this);
m_tools = {
new ArtisticStyle::ArtisticStyle(this),
new ClangFormat::ClangFormat(this),
new Uncrustify::Uncrustify(this)
};
QStringList toolIds;
toolIds.reserve(m_tools.count());
@@ -228,11 +230,6 @@ void BeautifierPlugin::extensionsInitialized()
this, &BeautifierPlugin::autoFormatOnSave);
}
ExtensionSystem::IPlugin::ShutdownFlag BeautifierPlugin::aboutToShutdown()
{
return SynchronousShutdown;
}
void BeautifierPlugin::updateActions(Core::IEditor *editor)
{
for (BeautifierAbstractTool *tool : m_tools)

View File

@@ -74,7 +74,6 @@ class BeautifierPlugin : public ExtensionSystem::IPlugin
public:
bool initialize(const QStringList &arguments, QString *errorString) override;
void extensionsInitialized() override;
ShutdownFlag aboutToShutdown() override;
void formatCurrentFile(const Command &command, int startPos = -1, int endPos = 0);

View File

@@ -49,6 +49,7 @@ ClangFormatOptionsPageWidget::ClangFormatOptionsPageWidget(ClangFormatSettings *
ui->predefinedStyle->addItems(m_settings->predefinedStyles());
ui->fallbackStyle->addItems(m_settings->fallbackStyles());
ui->command->setExpectedKind(Utils::PathChooser::ExistingCommand);
ui->command->setCommandVersionArguments({"--version"});
ui->command->setPromptDialogTitle(
BeautifierPlugin::msgCommandPromptDialogTitle("Clang Format"));
connect(ui->command, &Utils::PathChooser::validChanged, ui->options, &QWidget::setEnabled);

View File

@@ -28,6 +28,7 @@
#include "beautifierconstants.h"
#include <coreplugin/icore.h>
#include <utils/algorithm.h>
#include <utils/mimetypes/mimedatabase.h>
namespace Beautifier {
@@ -99,11 +100,7 @@ QList<Utils::MimeType> GeneralSettings::autoFormatMime() const
QString GeneralSettings::autoFormatMimeAsString() const
{
QStringList types;
types.reserve(m_autoFormatMime.count());
for (auto t : m_autoFormatMime)
types << t.name();
return types.join("; ");
return Utils::transform(m_autoFormatMime, &Utils::MimeType::name).join("; ");
}
void GeneralSettings::setAutoFormatMime(const QList<Utils::MimeType> &autoFormatMime)

View File

@@ -54,6 +54,7 @@ UncrustifyOptionsPageWidget::UncrustifyOptionsPageWidget(UncrustifySettings *set
ui->uncrusifyFilePath->setPromptDialogFilter(tr("Uncrustify file (*.cfg)"));
ui->command->setExpectedKind(Utils::PathChooser::ExistingCommand);
ui->command->setCommandVersionArguments({"--version"});
ui->command->setPromptDialogTitle(BeautifierPlugin::msgCommandPromptDialogTitle(
Uncrustify::tr(Constants::Uncrustify::DISPLAY_NAME)));
connect(ui->command, &Utils::PathChooser::validChanged, ui->options, &QWidget::setEnabled);

View File

@@ -30,6 +30,7 @@
#include <coreplugin/id.h>
#include <utils/hostosinfo.h>
#include <utils/stringutils.h>
#include <QAction>
#include <QRegExp>
@@ -263,9 +264,8 @@ QString Action::description() const
{
if (!m_defaultText.isEmpty())
return m_defaultText;
if (action()) {
QString text = action()->text();
text.remove(QRegExp(QLatin1String("&(?!&)")));
if (QAction *act = action()) {
const QString text = Utils::stripAccelerator(act->text());
if (!text.isEmpty())
return text;
}

View File

@@ -28,6 +28,8 @@
#include "ioptionspage.h"
#include <utils/stringutils.h>
#include <QCheckBox>
#include <QGroupBox>
#include <QIcon>
@@ -165,18 +167,14 @@ bool Core::IOptionsPage::matches(const QString &searchKeyWord) const
return false;
// find common subwidgets
foreach (const QLabel *label, widget->findChildren<QLabel *>())
m_keywords << label->text();
m_keywords << Utils::stripAccelerator(label->text());
foreach (const QCheckBox *checkbox, widget->findChildren<QCheckBox *>())
m_keywords << checkbox->text();
m_keywords << Utils::stripAccelerator(checkbox->text());
foreach (const QPushButton *pushButton, widget->findChildren<QPushButton *>())
m_keywords << pushButton->text();
m_keywords << Utils::stripAccelerator(pushButton->text());
foreach (const QGroupBox *groupBox, widget->findChildren<QGroupBox *>())
m_keywords << groupBox->title();
m_keywords << Utils::stripAccelerator(groupBox->title());
// clean up accelerators
QMutableStringListIterator it(m_keywords);
while (it.hasNext())
it.next().remove(QLatin1Char('&'));
m_keywordsInitialized = true;
}
foreach (const QString &keyword, m_keywords)

View File

@@ -35,6 +35,7 @@
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <utils/stringutils.h>
#include <QDir>
#include <QFileInfo>
@@ -211,7 +212,7 @@ void ReadOnlyFilesDialogPrivate::promptFailWarning(const QStringList &files, Rea
switch (type) {
case ReadOnlyFilesDialog::RO_OpenVCS: {
if (IVersionControl *vc = versionControls[file]) {
const QString openText = vc->vcsOpenText().remove(QLatin1Char('&'));
const QString openText = Utils::stripAccelerator(vc->vcsOpenText());
title = tr("Failed to %1 File").arg(openText);
message = tr("%1 file %2 from version control system %3 failed.")
.arg(openText)
@@ -411,9 +412,9 @@ void ReadOnlyFilesDialogPrivate::initDialog(const QStringList &fileNames)
&& versionControlForFile->openSupportMode(fileName) != IVersionControl::NoOpen;
if (fileManagedByVCS) {
const QString vcsOpenTextForFile =
versionControlForFile->vcsOpenText().remove(QLatin1Char('&'));
Utils::stripAccelerator(versionControlForFile->vcsOpenText());
const QString vcsMakeWritableTextforFile =
versionControlForFile->vcsMakeWritableText().remove(QLatin1Char('&'));
Utils::stripAccelerator(versionControlForFile->vcsMakeWritableText());
if (!useVCS) {
vcsOpenTextForAll = vcsOpenTextForFile;
vcsMakeWritableTextForAll = vcsMakeWritableTextforFile;

View File

@@ -28,6 +28,7 @@
#include <coreplugin/actionmanager/command.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
#include <QAction>
@@ -66,7 +67,6 @@ QList<LocatorFilterEntry> CommandLocator::matchesFor(QFutureInterface<LocatorFil
QList<LocatorFilterEntry> betterEntries;
// Get active, enabled actions matching text, store in list.
// Reference via index in extraInfo.
const QChar ampersand = QLatin1Char('&');
const Qt::CaseSensitivity entryCaseSensitivity = caseSensitivity(entry);
const int count = d->commands.size();
for (int i = 0; i < count; i++) {
@@ -77,8 +77,7 @@ QList<LocatorFilterEntry> CommandLocator::matchesFor(QFutureInterface<LocatorFil
QAction *action = d->commands.at(i)->action();
if (action && action->isEnabled()) {
QString text = action->text();
text.remove(ampersand);
const QString text = Utils::stripAccelerator(action->text());
const int index = text.indexOf(entry, 0, entryCaseSensitivity);
if (index >= 0) {
LocatorFilterEntry filterEntry(this, text, QVariant(i));

View File

@@ -99,6 +99,14 @@ private:
QColor mBackgroundColor;
};
class CompletionDelegate : public SearchResultTreeItemDelegate
{
public:
CompletionDelegate(QObject *parent);
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
};
class CompletionList : public Utils::TreeView
{
public:
@@ -115,6 +123,9 @@ public:
void keyPressEvent(QKeyEvent *event);
bool eventFilter(QObject *watched, QEvent *event);
private:
QMetaObject::Connection m_updateSizeConnection;
};
class TopLeftLocatorPopup : public LocatorPopup
@@ -234,7 +245,7 @@ void LocatorModel::addEntries(const QList<LocatorFilterEntry> &entries)
CompletionList::CompletionList(QWidget *parent)
: Utils::TreeView(parent)
{
setItemDelegate(new SearchResultTreeItemDelegate(0, this));
setItemDelegate(new CompletionDelegate(this));
setRootIsDecorated(false);
setUniformRowHeights(true);
header()->hide();
@@ -247,23 +258,29 @@ CompletionList::CompletionList(QWidget *parent)
if (verticalScrollBar())
verticalScrollBar()->setAttribute(Qt::WA_MacMiniSize);
}
const QStyleOptionViewItem &option = viewOptions();
const QSize shint = itemDelegate()->sizeHint(option, QModelIndex());
setFixedHeight(shint.height() * 17 + frameWidth() * 2);
installEventFilter(this);
}
void CompletionList::setModel(QAbstractItemModel *newModel)
{
const auto updateSize = [this] {
if (model() && model()->rowCount() > 0) {
const QStyleOptionViewItem &option = viewOptions();
const QSize shint = itemDelegate()->sizeHint(option, model()->index(0, 0));
setFixedHeight(shint.height() * 17 + frameWidth() * 2);
disconnect(m_updateSizeConnection);
}
};
if (model()) {
disconnect(model(), &QAbstractItemModel::columnsInserted,
this, &CompletionList::resizeHeaders);
disconnect(model(), 0, this, 0);
}
QTreeView::setModel(newModel);
if (newModel) {
connect(newModel, &QAbstractItemModel::columnsInserted,
this, &CompletionList::resizeHeaders);
m_updateSizeConnection = connect(newModel, &QAbstractItemModel::rowsInserted,
this, updateSize);
}
}
@@ -276,7 +293,8 @@ void TopLeftLocatorPopup::updateGeometry()
{
QTC_ASSERT(parentWidget(), return);
const QSize size = preferredSize();
const QRect rect(parentWidget()->mapToGlobal(QPoint(0, -size.height())), size);
const int border = m_tree->frameWidth();
const QRect rect(parentWidget()->mapToGlobal(QPoint(-border, -size.height() - border)), size);
setGeometry(rect);
LocatorPopup::updateGeometry();
}
@@ -318,10 +336,11 @@ void LocatorPopup::updateWindow()
bool LocatorPopup::event(QEvent *event)
{
if (event->type() == QEvent::ParentChange) {
if (event->type() == QEvent::ParentChange)
updateWindow();
} else if (event->type() == QEvent::Show)
updateGeometry();
// completion list resizes after first items are shown --> LayoutRequest
else if (event->type() == QEvent::Show || event->type() == QEvent::LayoutRequest)
QTimer::singleShot(0, this, &LocatorPopup::updateGeometry);
return QWidget::event(event);
}
@@ -343,7 +362,8 @@ QSize LocatorPopup::preferredSize()
void TopLeftLocatorPopup::inputLostFocus()
{
hide();
if (!isActiveWindow())
hide();
}
void LocatorPopup::inputLostFocus()
@@ -361,7 +381,8 @@ LocatorPopup::LocatorPopup(LocatorWidget *locatorWidget, QWidget *parent)
m_tree(new CompletionList(this)),
m_inputWidget(locatorWidget)
{
m_tree->setFrameStyle(QFrame::NoFrame);
if (Utils::HostOsInfo::isMacHost())
m_tree->setFrameStyle(QFrame::NoFrame); // tool tip already includes a frame
m_tree->setModel(locatorWidget->model());
auto layout = new QVBoxLayout;
@@ -374,7 +395,8 @@ LocatorPopup::LocatorPopup(LocatorWidget *locatorWidget, QWidget *parent)
connect(locatorWidget, &LocatorWidget::parentChanged, this, &LocatorPopup::updateWindow);
connect(locatorWidget, &LocatorWidget::showPopup, this, &LocatorPopup::show);
connect(locatorWidget, &LocatorWidget::hidePopup, this, &LocatorPopup::close);
connect(locatorWidget, &LocatorWidget::lostFocus, this, &LocatorPopup::inputLostFocus);
connect(locatorWidget, &LocatorWidget::lostFocus, this, &LocatorPopup::inputLostFocus,
Qt::QueuedConnection);
connect(locatorWidget, &LocatorWidget::selectRow, m_tree, [this](int row) {
m_tree->setCurrentIndex(m_tree->model()->index(row, 0));
});
@@ -893,5 +915,15 @@ LocatorPopup *createLocatorPopup(Locator *locator, QWidget *parent)
return popup;
}
CompletionDelegate::CompletionDelegate(QObject *parent)
: SearchResultTreeItemDelegate(0, parent)
{
}
QSize CompletionDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return SearchResultTreeItemDelegate::sizeHint(option, index) + QSize(0, 2);
}
} // namespace Internal
} // namespace Core

View File

@@ -122,11 +122,11 @@ protected:
virtual void inputLostFocus();
QPointer<QWidget> m_window;
CompletionList *m_tree;
private:
void updateWindow();
CompletionList *m_tree;
LocatorWidget *m_inputWidget;
};

View File

@@ -51,6 +51,8 @@ PluginDialog::PluginDialog(QWidget *parent)
: QDialog(parent),
m_view(new ExtensionSystem::PluginView(this))
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
QVBoxLayout *vl = new QVBoxLayout(this);
auto filterLayout = new QHBoxLayout;

View File

@@ -1352,6 +1352,7 @@ void DebuggerEngine::quitDebugger()
switch (state()) {
case InferiorStopOk:
case InferiorStopFailed:
case InferiorUnrunnable:
d->queueShutdownInferior();
break;
case InferiorRunOk:
@@ -1368,6 +1369,7 @@ void DebuggerEngine::quitDebugger()
notifyEngineRunFailed();
break;
case EngineShutdownRequested:
case InferiorShutdownRequested:
break;
case EngineRunFailed:
case DebuggerFinished:
@@ -1924,7 +1926,7 @@ void DebuggerEngine::validateExecutable()
}
if (warnOnInappropriateDebugger) {
AsynchronousMessageBox::information(tr("Warning"),
tr("The selected debugger may be inappropiate for the inferior.\n"
tr("The selected debugger may be inappropriate for the inferior.\n"
"Examining symbols and setting breakpoints by file name and line number "
"may fail.\n")
+ '\n' + detailedWarning);

View File

@@ -2179,9 +2179,8 @@ void DebuggerPluginPrivate::attachToQmlPort()
if (device) {
QSsh::SshConnectionParameters sshParameters = device->sshParameters();
rp.remoteChannel = QString("%1:%2").arg(sshParameters.host).arg(sshParameters.port);
Connection toolControl = device->toolControlChannel(IDevice::QmlControlChannel);
QTC_ASSERT(toolControl.is<HostName>(), return);
rp.qmlServer.host = toolControl.as<HostName>().host();
QUrl toolControl = device->toolControlChannel(IDevice::QmlControlChannel);
rp.qmlServer.host = toolControl.host();
}
rp.qmlServer.port = Utils::Port(dlg.port());
rp.startMode = AttachToRemoteProcess;

View File

@@ -278,7 +278,12 @@ static bool fixupParameters(DebuggerRunParameters &rp, RunControl *runControl, Q
// Extract as much as possible from available RunConfiguration.
if (runConfig->runnable().is<StandardRunnable>()) {
// FIXME: Needed for core dump which stores the executable in inferior, but not in runConfig
// executable.
const QString prevExecutable = rp.inferior.executable;
rp.inferior = runConfig->runnable().as<StandardRunnable>();
if (rp.inferior.executable.isEmpty())
rp.inferior.executable = prevExecutable;
rp.useTerminal = rp.inferior.runMode == ApplicationLauncher::Console;
// Normalize to work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch'...)
rp.inferior.workingDirectory = FileUtils::normalizePathName(rp.inferior.workingDirectory);
@@ -675,6 +680,8 @@ RunConfiguration *dummyRunConfigForKit(ProjectExplorer::Kit *kit)
Target *target = nullptr;
if (project) {
target = project->target(kit);
if (!target)
target = project->createTarget(kit);
} else {
project = new DummyProject;
target = project->createTarget(kit);
@@ -702,6 +709,11 @@ GdbServerPortsGatherer::GdbServerPortsGatherer(RunControl *runControl)
: RunWorker(runControl)
{
setDisplayName("GdbServerPortsGatherer");
connect(&m_portsGatherer, &DeviceUsedPortsGatherer::error,
this, &RunWorker::reportFailure);
connect(&m_portsGatherer, &DeviceUsedPortsGatherer::portListReady,
this, &GdbServerPortsGatherer::handlePortListReady);
}
GdbServerPortsGatherer::~GdbServerPortsGatherer()
@@ -711,36 +723,34 @@ GdbServerPortsGatherer::~GdbServerPortsGatherer()
void GdbServerPortsGatherer::start()
{
appendMessage(tr("Checking available ports..."), NormalMessageFormat);
connect(&m_portsGatherer, &DeviceUsedPortsGatherer::error, this, [this](const QString &msg) {
reportFailure(msg);
});
connect(&m_portsGatherer, &DeviceUsedPortsGatherer::portListReady, this, [this] {
Utils::PortList portList = device()->freePorts();
appendMessage(tr("Found %1 free ports").arg(portList.count()), NormalMessageFormat);
if (m_useGdbServer) {
m_gdbServerPort = m_portsGatherer.getNextFreePort(&portList);
if (!m_gdbServerPort.isValid()) {
reportFailure(tr("Not enough free ports on device for C++ debugging."));
return;
}
}
if (m_useQmlServer) {
m_qmlServerPort = m_portsGatherer.getNextFreePort(&portList);
if (!m_qmlServerPort.isValid()) {
reportFailure(tr("Not enough free ports on device for QML debugging."));
return;
}
}
reportStarted();
});
m_portsGatherer.start(device());
}
void GdbServerPortsGatherer::handlePortListReady()
{
Utils::PortList portList = device()->freePorts();
appendMessage(tr("Found %1 free ports").arg(portList.count()), NormalMessageFormat);
if (m_useGdbServer) {
m_gdbServerPort = m_portsGatherer.getNextFreePort(&portList);
if (!m_gdbServerPort.isValid()) {
reportFailure(tr("Not enough free ports on device for C++ debugging."));
return;
}
}
if (m_useQmlServer) {
m_qmlServerPort = m_portsGatherer.getNextFreePort(&portList);
if (!m_qmlServerPort.isValid()) {
reportFailure(tr("Not enough free ports on device for QML debugging."));
return;
}
}
reportStarted();
}
// GdbServerRunner
GdbServerRunner::GdbServerRunner(RunControl *runControl)
: RunWorker(runControl)
GdbServerRunner::GdbServerRunner(RunControl *runControl, GdbServerPortsGatherer *portsGatherer)
: SimpleTargetRunner(runControl), m_portsGatherer(portsGatherer)
{
setDisplayName("GdbServerRunner");
}
@@ -751,19 +761,18 @@ GdbServerRunner::~GdbServerRunner()
void GdbServerRunner::start()
{
auto portsGatherer = runControl()->worker<GdbServerPortsGatherer>();
QTC_ASSERT(portsGatherer, reportFailure(); return);
QTC_ASSERT(m_portsGatherer, reportFailure(); return);
StandardRunnable r = runnable().as<StandardRunnable>();
QStringList args = QtcProcess::splitArgs(r.commandLineArguments, OsTypeLinux);
QString command;
const bool isQmlDebugging = portsGatherer->useQmlServer();
const bool isCppDebugging = portsGatherer->useGdbServer();
const bool isQmlDebugging = m_portsGatherer->useQmlServer();
const bool isCppDebugging = m_portsGatherer->useGdbServer();
if (isQmlDebugging) {
args.prepend(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices,
portsGatherer->qmlServerPort()));
m_portsGatherer->qmlServerPort()));
}
if (isQmlDebugging && !isCppDebugging) {
@@ -774,27 +783,16 @@ void GdbServerRunner::start()
command = "gdbserver";
args.clear();
args.append(QString("--multi"));
args.append(QString(":%1").arg(portsGatherer->gdbServerPort().number()));
args.append(QString(":%1").arg(m_portsGatherer->gdbServerPort().number()));
}
r.executable = command;
r.commandLineArguments = QtcProcess::joinArgs(args, OsTypeLinux);
connect(&m_gdbServer, &ApplicationLauncher::error, this, [this] {
reportFailure(tr("GDBserver start failed"));
});
connect(&m_gdbServer, &ApplicationLauncher::remoteProcessStarted, this, [this] {
appendMessage(tr("GDBserver started") + '\n', NormalMessageFormat);
reportStarted();
});
setRunnable(r);
appendMessage(tr("Starting GDBserver...") + '\n', NormalMessageFormat);
m_gdbServer.start(r, device());
}
appendMessage(tr("Starting GDBserver..."), NormalMessageFormat);
void GdbServerRunner::stop()
{
m_gdbServer.stop();
reportStopped();
SimpleTargetRunner::start();
}
} // namespace Debugger

View File

@@ -111,7 +111,8 @@ public:
Utils::Port qmlServerPort() const { return m_qmlServerPort; }
private:
void start();
void start() override;
void handlePortListReady();
ProjectExplorer::DeviceUsedPortsGatherer m_portsGatherer;
bool m_useGdbServer = false;
@@ -120,19 +121,19 @@ private:
Utils::Port m_qmlServerPort;
};
class DEBUGGER_EXPORT GdbServerRunner : public ProjectExplorer::RunWorker
class DEBUGGER_EXPORT GdbServerRunner : public ProjectExplorer::SimpleTargetRunner
{
Q_OBJECT
public:
explicit GdbServerRunner(ProjectExplorer::RunControl *runControl);
explicit GdbServerRunner(ProjectExplorer::RunControl *runControl,
GdbServerPortsGatherer *portsGatherer);
~GdbServerRunner();
private:
void start() override;
void stop() override;
ProjectExplorer::ApplicationLauncher m_gdbServer;
GdbServerPortsGatherer *m_portsGatherer;
};
extern DEBUGGER_EXPORT const char GdbServerRunnerWorkerId[];

View File

@@ -3536,6 +3536,8 @@ void GdbEngine::handleRegisterListValues(const DebuggerResponse &response)
QString chunk = list.at(i);
if (chunk.startsWith(' '))
chunk.remove(0, 1);
if (chunk.startsWith('<') || chunk.startsWith('{')) // <unavailable>, {v4_float=...
continue;
if (chunk.startsWith("0x"))
chunk.remove(0, 2);
QTC_ASSERT(chunk.size() == 8, continue);

View File

@@ -28,6 +28,8 @@
#include <coreplugin/icontext.h>
#include <utils/stringutils.h>
#include <QDesignerOptionsPageInterface>
#include <QCoreApplication>
@@ -116,7 +118,7 @@ bool SettingsPageProvider::matches(const QString &searchKeyWord) const
if (m_keywords.isEmpty()) {
m_keywords.reserve(itemCount);
for (size_t i = 0; i < itemCount; ++i)
m_keywords << QCoreApplication::translate(uitext[i].context, uitext[i].value).remove(QLatin1Char('&'));
m_keywords << Utils::stripAccelerator(QCoreApplication::translate(uitext[i].context, uitext[i].value));
}
foreach (const QString &key, m_keywords) {
if (key.contains(searchKeyWord, Qt::CaseInsensitive))

View File

@@ -34,7 +34,10 @@
#include <coreplugin/minisplitter.h>
#include <texteditor/displaysettings.h>
#include <texteditor/fontsettings.h>
#include <texteditor/marginsettings.h>
#include <texteditor/syntaxhighlighter.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
#include <texteditor/texteditorsettings.h>
@@ -120,6 +123,8 @@ DescriptionEditorWidget::DescriptionEditorWidget(QWidget *parent)
m_context->setWidget(this);
m_context->setContext(Core::Context(Constants::C_DIFF_EDITOR_DESCRIPTION));
Core::ICore::addContextObject(m_context);
textDocument()->setSyntaxHighlighter(new SyntaxHighlighter);
}
DescriptionEditorWidget::~DescriptionEditorWidget()
@@ -194,7 +199,9 @@ void DescriptionEditorWidget::highlightCurrentContents()
QTextEdit::ExtraSelection sel;
sel.cursor = m_currentCursor;
sel.cursor.select(QTextCursor::LineUnderCursor);
sel.format.setFontUnderline(true);
sel.format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
const QColor textColor = TextEditorSettings::fontSettings().formatFor(C_TEXT).foreground();
sel.format.setUnderlineColor(textColor.isValid() ? textColor : palette().color(QPalette::Foreground));
setExtraSelections(TextEditorWidget::OtherSelection,
QList<QTextEdit::ExtraSelection>() << sel);
}

View File

@@ -70,7 +70,7 @@ protected:
// inside reload() (for synchronous reload)
// or later (for asynchronous reload)
virtual void reload() = 0;
virtual void reloadFinished(bool success);
void reloadFinished(bool success);
void setDiffFiles(const QList<FileData> &diffFileList,
const QString &baseDirectory = QString(),

View File

@@ -205,7 +205,7 @@ QString DiffEditorDocument::fallbackSaveAsPath() const
bool DiffEditorDocument::isSaveAsAllowed() const
{
return !isReloading();
return state() == LoadOK;
}
bool DiffEditorDocument::save(QString *errorString, const QString &fileName, bool autoSave)
@@ -213,7 +213,7 @@ bool DiffEditorDocument::save(QString *errorString, const QString &fileName, boo
Q_UNUSED(errorString)
Q_UNUSED(autoSave)
if (isReloading())
if (state() != LoadOK)
return false;
const bool ok = write(fileName, format(), plainText(), errorString);
@@ -337,7 +337,7 @@ QString DiffEditorDocument::plainText() const
void DiffEditorDocument::beginReload()
{
emit aboutToReload();
m_isReloading = true;
m_state = Reloading;
emit changed();
const bool blocked = blockSignals(true);
setDiffFiles(QList<FileData>(), QString());
@@ -347,7 +347,7 @@ void DiffEditorDocument::beginReload()
void DiffEditorDocument::endReload(bool success)
{
m_isReloading = false;
m_state = success ? LoadOK : LoadFailed;
emit changed();
emit reloadFinished(success);
}

View File

@@ -46,6 +46,12 @@ public:
DiffEditorController *controller() const;
enum State {
LoadOK,
Reloading,
LoadFailed
};
QString makePatch(int fileIndex, int chunkIndex,
bool revert, bool addPrefix = false,
const QString &overriddenFileName = QString()) const;
@@ -76,7 +82,7 @@ public:
bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override;
OpenResult open(QString *errorString, const QString &fileName,
const QString &realFileName) override;
bool isReloading() const { return m_isReloading; }
State state() const { return m_state; }
void beginReload();
void endReload(bool success);
@@ -100,7 +106,7 @@ private:
int m_contextLineCount;
bool m_isContextLineCountForced;
bool m_ignoreWhitespace;
bool m_isReloading = false;
State m_state = LoadOK;
friend class ::DiffEditor::DiffEditorController;
};

View File

@@ -78,7 +78,7 @@ void DiffEditorWidgetController::setDocument(DiffEditorDocument *document)
disconnect(m_document, &IDocument::reloadFinished, this, &DiffEditorWidgetController::hideProgress);
}
const bool wasRunning = m_document && m_document->isReloading();
const bool wasRunning = m_document && m_document->state() == DiffEditorDocument::Reloading;
m_document = document;
@@ -87,7 +87,7 @@ void DiffEditorWidgetController::setDocument(DiffEditorDocument *document)
connect(m_document, &IDocument::reloadFinished, this, &DiffEditorWidgetController::hideProgress);
}
const bool isRunning = m_document && m_document->isReloading();
const bool isRunning = m_document && m_document->state() == DiffEditorDocument::Reloading;
if (wasRunning == isRunning)
return;

View File

@@ -25,10 +25,13 @@
#include "diffutils.h"
#include "differ.h"
#include "texteditor/fontsettings.h"
#include <QFutureInterfaceBase>
#include <QRegularExpression>
#include <QStringList>
#include <QTextStream>
#include "texteditor/fontsettings.h"
namespace DiffEditor {
@@ -808,7 +811,8 @@ static FileData readDiffHeaderAndChunks(QStringRef headerAndChunks,
}
static QList<FileData> readDiffPatch(QStringRef patch,
bool *ok)
bool *ok,
QFutureInterfaceBase *jobController)
{
const QRegularExpression diffRegExp("(?:\\n|^)" // new line of the beginning of a patch
"(" // either
@@ -835,6 +839,9 @@ static QList<FileData> readDiffPatch(QStringRef patch,
readOk = true;
int lastPos = -1;
do {
if (jobController && jobController->isCanceled())
return QList<FileData>();
int pos = diffMatch.capturedStart();
if (lastPos >= 0) {
QStringRef headerAndChunks = patch.mid(lastPos,
@@ -1031,7 +1038,8 @@ static FileData readCopyRenameChunks(QStringRef copyRenameChunks,
return fileData;
}
static QList<FileData> readGitPatch(QStringRef patch, bool *ok)
static QList<FileData> readGitPatch(QStringRef patch, bool *ok,
QFutureInterfaceBase *jobController)
{
const QRegularExpression simpleGitRegExp(
@@ -1127,6 +1135,9 @@ static QList<FileData> readGitPatch(QStringRef patch, bool *ok)
};
do {
if (jobController && jobController->isCanceled())
return QList<FileData>();
collectFileData();
if (!readOk)
break;
@@ -1168,12 +1179,17 @@ static QList<FileData> readGitPatch(QStringRef patch, bool *ok)
return fileDataList;
}
QList<FileData> DiffUtils::readPatch(const QString &patch, bool *ok)
QList<FileData> DiffUtils::readPatch(const QString &patch, bool *ok,
QFutureInterfaceBase *jobController)
{
bool readOk = false;
QList<FileData> fileDataList;
if (jobController) {
jobController->setProgressRange(0, 1);
jobController->setProgressValue(0);
}
QStringRef croppedPatch(&patch);
// Crop e.g. "-- \n2.10.2.windows.1\n\n" at end of file
const QRegularExpression formatPatchEndingRegExp("(\\n-- \\n\\S*\\n\\n$)");
@@ -1181,9 +1197,9 @@ QList<FileData> DiffUtils::readPatch(const QString &patch, bool *ok)
if (match.hasMatch())
croppedPatch = croppedPatch.left(match.capturedStart() + 1);
fileDataList = readGitPatch(croppedPatch, &readOk);
fileDataList = readGitPatch(croppedPatch, &readOk, jobController);
if (!readOk)
fileDataList = readDiffPatch(croppedPatch, &readOk);
fileDataList = readDiffPatch(croppedPatch, &readOk, jobController);
if (ok)
*ok = readOk;

View File

@@ -30,6 +30,10 @@
#include <QString>
#include <QMap>
QT_BEGIN_NAMESPACE
class QFutureInterfaceBase;
QT_END_NAMESPACE
namespace TextEditor { class FontSettings; }
namespace DiffEditor {
@@ -150,7 +154,8 @@ public:
static QString makePatch(const QList<FileData> &fileDataList,
unsigned formatFlags = 0);
static QList<FileData> readPatch(const QString &patch,
bool *ok = 0);
bool *ok = 0,
QFutureInterfaceBase *jobController = nullptr);
};
} // namespace DiffEditor

View File

@@ -117,15 +117,26 @@ void UnifiedView::setDocument(DiffEditorDocument *document)
{
QTC_ASSERT(m_widget, return);
m_widget->setDocument(document);
if (document && document->isReloading())
if (!document)
return;
switch (document->state()) {
case DiffEditorDocument::Reloading:
m_widget->clear(tr("Waiting for data..."));
break;
case DiffEditorDocument::LoadFailed:
m_widget->clear(tr("Retrieving data failed."));
break;
default:
break;
}
}
void UnifiedView::beginOperation()
{
QTC_ASSERT(m_widget, return);
DiffEditorDocument *document = m_widget->diffDocument();
if (document && !document->isReloading())
if (document && document->state() == DiffEditorDocument::LoadOK)
m_widget->saveState();
m_widget->clear(tr("Waiting for data..."));
}
@@ -142,7 +153,7 @@ void UnifiedView::endOperation(bool success)
if (success)
m_widget->restoreState();
else
m_widget->clear(tr("Failed"));
m_widget->clear(tr("Retrieving data failed."));
}
void UnifiedView::setCurrentDiffFileIndex(int index)
@@ -192,15 +203,26 @@ void SideBySideView::setDocument(DiffEditorDocument *document)
{
QTC_ASSERT(m_widget, return);
m_widget->setDocument(document);
if (document && document->isReloading())
if (!document)
return;
switch (document->state()) {
case DiffEditorDocument::Reloading:
m_widget->clear(tr("Waiting for data..."));
break;
case DiffEditorDocument::LoadFailed:
m_widget->clear(tr("Retrieving data failed."));
break;
default:
break;
}
}
void SideBySideView::beginOperation()
{
QTC_ASSERT(m_widget, return);
DiffEditorDocument *document = m_widget->diffDocument();
if (document && !document->isReloading())
if (document && document->state() == DiffEditorDocument::LoadOK)
m_widget->saveState();
m_widget->clear(tr("Waiting for data..."));
}
@@ -223,7 +245,7 @@ void SideBySideView::endOperation(bool success)
if (success)
m_widget->restoreState();
else
m_widget->clear(tr("Failed"));
m_widget->clear(tr("Retrieving data failed."));
}
void SideBySideView::setSync(bool sync)

View File

@@ -615,7 +615,7 @@ void SideBySideDiffEditorWidget::setDiff(const QList<FileData> &diffFileList,
m_controller.m_contextFileData = diffFileList;
if (m_controller.m_contextFileData.isEmpty()) {
const QString msg = tr("No difference");
const QString msg = tr("No difference.");
m_leftEditor->setPlainText(msg);
m_rightEditor->setPlainText(msg);
} else {

View File

@@ -2141,6 +2141,8 @@ public:
bool handleExShiftCommand(const ExCommand &cmd);
bool handleExSourceCommand(const ExCommand &cmd);
bool handleExSubstituteCommand(const ExCommand &cmd);
bool handleExTabNextCommand(const ExCommand &cmd);
bool handleExTabPreviousCommand(const ExCommand &cmd);
bool handleExWriteCommand(const ExCommand &cmd);
bool handleExEchoCommand(const ExCommand &cmd);
@@ -5561,6 +5563,24 @@ bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd)
return true;
}
bool FakeVimHandler::Private::handleExTabNextCommand(const ExCommand &cmd)
{
if (cmd.cmd != "tabnext" && cmd.cmd != "tabn")
return false;
emit q->tabNextRequested(q);
return true;
}
bool FakeVimHandler::Private::handleExTabPreviousCommand(const ExCommand &cmd)
{
if (cmd.cmd != "tabprevious" && cmd.cmd != "tabp")
return false;
emit q->tabPreviousRequested(q);
return true;
}
bool FakeVimHandler::Private::handleExMapCommand(const ExCommand &cmd0) // :map
{
QByteArray modes;
@@ -6212,6 +6232,8 @@ bool FakeVimHandler::Private::handleExCommandHelper(ExCommand &cmd)
|| handleExShiftCommand(cmd)
|| handleExSourceCommand(cmd)
|| handleExSubstituteCommand(cmd)
|| handleExTabNextCommand(cmd)
|| handleExTabPreviousCommand(cmd)
|| handleExWriteCommand(cmd)
|| handleExEchoCommand(cmd);
}

View File

@@ -157,6 +157,8 @@ signals:
void fold(FakeVimHandler *self, int depth, bool fold);
void foldGoTo(FakeVimHandler *self, int count, bool current);
void jumpToGlobalMark(FakeVimHandler *handler, QChar mark, bool backTickMode, const QString &fileName);
void tabNextRequested(FakeVimHandler *self);
void tabPreviousRequested(FakeVimHandler *self);
public:
class Private;

View File

@@ -1802,6 +1802,11 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor)
connect(ICore::instance(), &ICore::saveSettingsRequested,
this, &FakeVimPluginPrivate::writeSettings);
connect(handler, &FakeVimHandler::tabNextRequested,
this, [this] { triggerAction(Core::Constants::GOTONEXTINHISTORY); });
connect(handler, &FakeVimHandler::tabPreviousRequested,
this, [this] { triggerAction(Core::Constants::GOTOPREVINHISTORY); });
handler->setCurrentFileName(editor->document()->filePath().toString());
handler->installEventFilter();

View File

@@ -55,6 +55,7 @@
#include <utils/temporaryfile.h>
#include <vcsbase/submitfilemodel.h>
#include <vcsbase/vcsbasediffeditorcontroller.h>
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsbaseeditorconfig.h>
#include <vcsbase/vcsbaseplugin.h>
@@ -110,75 +111,31 @@ const unsigned silentFlags = unsigned(VcsCommand::SuppressCommandLogging
| VcsCommand::SuppressStdErr
| VcsCommand::SuppressFailMessage);
/////////////////////////////////////
class BaseController : public DiffEditorController
class GitDiffEditorController : public VcsBaseDiffEditorController
{
Q_OBJECT
public:
BaseController(IDocument *document, const QString &dir);
~BaseController();
void runCommand(const QList<QStringList> &args, QTextCodec *codec = 0);
private:
virtual void processOutput(const QString &output);
GitDiffEditorController(IDocument *document, const QString &workingDirectory);
protected:
void processDiff(const QString &output, const QString &startupFile = QString());
void runCommand(const QList<QStringList> &args, QTextCodec *codec = nullptr);
QStringList addConfigurationArguments(const QStringList &args) const;
QStringList addHeadWhenCommandInProgress() const;
const QString m_directory;
private:
QPointer<VcsCommand> m_command;
};
BaseController::BaseController(IDocument *document, const QString &dir) :
DiffEditorController(document),
m_directory(dir),
m_command(0)
{ }
BaseController::~BaseController()
GitDiffEditorController::GitDiffEditorController(IDocument *document, const QString &workingDirectory) :
VcsBaseDiffEditorController(document, GitPlugin::client(), workingDirectory)
{
if (m_command)
m_command->cancel();
}
void BaseController::runCommand(const QList<QStringList> &args, QTextCodec *codec)
void GitDiffEditorController::runCommand(const QList<QStringList> &args, QTextCodec *codec)
{
if (m_command) {
m_command->disconnect();
m_command->cancel();
}
m_command = new VcsCommand(m_directory, GitPlugin::client()->processEnvironment());
m_command->setCodec(codec ? codec : EditorManager::defaultTextCodec());
connect(m_command.data(), &VcsCommand::stdOutText, this, &BaseController::processOutput);
connect(m_command.data(), &VcsCommand::finished, this, &BaseController::reloadFinished);
m_command->addFlags(diffExecutionFlags());
for (const QStringList &arg : args) {
QTC_ASSERT(!arg.isEmpty(), continue);
m_command->addJob(GitPlugin::client()->vcsBinary(), arg, GitPlugin::client()->vcsTimeoutS());
}
m_command->execute();
VcsBaseDiffEditorController::runCommand(args, diffExecutionFlags(), codec);
}
void BaseController::processDiff(const QString &output, const QString &startupFile)
{
m_command.clear();
bool ok;
QList<FileData> fileDataList = DiffUtils::readPatch(output, &ok);
setDiffFiles(fileDataList, m_directory, startupFile);
}
QStringList BaseController::addConfigurationArguments(const QStringList &args) const
QStringList GitDiffEditorController::addConfigurationArguments(const QStringList &args) const
{
QTC_ASSERT(!args.isEmpty(), return args);
@@ -196,28 +153,23 @@ QStringList BaseController::addConfigurationArguments(const QStringList &args) c
return realArgs;
}
void BaseController::processOutput(const QString &output)
{
processDiff(output);
}
QStringList BaseController::addHeadWhenCommandInProgress() const
QStringList GitDiffEditorController::addHeadWhenCommandInProgress() const
{
// This is workaround for lack of support for merge commits and resolving conflicts,
// we compare the current state of working tree to the HEAD of current branch
// instead of showing unsupported combined diff format.
GitClient::CommandInProgress commandInProgress = GitPlugin::client()->checkCommandInProgress(m_directory);
GitClient::CommandInProgress commandInProgress = GitPlugin::client()->checkCommandInProgress(workingDirectory());
if (commandInProgress != GitClient::NoCommand)
return {HEAD};
return QStringList();
}
class RepositoryDiffController : public BaseController
class RepositoryDiffController : public GitDiffEditorController
{
Q_OBJECT
public:
RepositoryDiffController(IDocument *document, const QString &dir) :
BaseController(document, dir)
GitDiffEditorController(document, dir)
{ }
void reload() override;
@@ -230,12 +182,12 @@ void RepositoryDiffController::reload()
runCommand(QList<QStringList>() << addConfigurationArguments(args));
}
class FileDiffController : public BaseController
class FileDiffController : public GitDiffEditorController
{
Q_OBJECT
public:
FileDiffController(IDocument *document, const QString &dir, const QString &fileName) :
BaseController(document, dir),
GitDiffEditorController(document, dir),
m_fileName(fileName)
{ }
@@ -254,13 +206,13 @@ void FileDiffController::reload()
runCommand(QList<QStringList>() << addConfigurationArguments(args));
}
class FileListDiffController : public BaseController
class FileListDiffController : public GitDiffEditorController
{
Q_OBJECT
public:
FileListDiffController(IDocument *document, const QString &dir,
const QStringList &stagedFiles, const QStringList &unstagedFiles) :
BaseController(document, dir),
GitDiffEditorController(document, dir),
m_stagedFiles(stagedFiles),
m_unstagedFiles(unstagedFiles)
{ }
@@ -291,13 +243,13 @@ void FileListDiffController::reload()
runCommand(argLists);
}
class ProjectDiffController : public BaseController
class ProjectDiffController : public GitDiffEditorController
{
Q_OBJECT
public:
ProjectDiffController(IDocument *document, const QString &dir,
const QStringList &projectPaths) :
BaseController(document, dir),
GitDiffEditorController(document, dir),
m_projectPaths(projectPaths)
{ }
@@ -314,13 +266,13 @@ void ProjectDiffController::reload()
runCommand(QList<QStringList>() << addConfigurationArguments(args));
}
class BranchDiffController : public BaseController
class BranchDiffController : public GitDiffEditorController
{
Q_OBJECT
public:
BranchDiffController(IDocument *document, const QString &dir,
const QString &branch) :
BaseController(document, dir),
GitDiffEditorController(document, dir),
m_branch(branch)
{ }
@@ -337,19 +289,18 @@ void BranchDiffController::reload()
runCommand(QList<QStringList>() << addConfigurationArguments(args));
}
class ShowController : public BaseController
class ShowController : public GitDiffEditorController
{
Q_OBJECT
public:
ShowController(IDocument *document, const QString &dir, const QString &id) :
BaseController(document, dir),
GitDiffEditorController(document, dir),
m_id(id),
m_state(Idle)
{ }
void reload() override;
void processOutput(const QString &output) override;
void reloadFinished(bool success) override;
void processCommandOutput(const QString &output) override;
private:
const QString m_id;
@@ -359,34 +310,27 @@ private:
void ShowController::reload()
{
const QStringList args = {"show", "-s", noColorOption, showFormatC, m_id};
// stage 1
m_state = GettingDescription;
runCommand(QList<QStringList>() << args, GitPlugin::client()->encoding(m_directory, "i18n.commitEncoding"));
const QStringList args = {"show", "-s", noColorOption, showFormatC, m_id};
runCommand(QList<QStringList>() << args, GitPlugin::client()->encoding(workingDirectory(), "i18n.commitEncoding"));
setStartupFile(VcsBasePlugin::source(document()));
}
void ShowController::processOutput(const QString &output)
void ShowController::processCommandOutput(const QString &output)
{
QTC_ASSERT(m_state != Idle, return);
if (m_state == GettingDescription)
setDescription(GitPlugin::client()->extendedShowDescription(m_directory, output));
else if (m_state == GettingDiff)
processDiff(output, VcsBasePlugin::source(document()));
}
void ShowController::reloadFinished(bool success)
{
QTC_ASSERT(m_state != Idle, return);
if (m_state == GettingDescription && success) {
if (m_state == GettingDescription) {
setDescription(GitPlugin::client()->extendedShowDescription(workingDirectory(), output));
// stage 2
m_state = GettingDiff;
const QStringList args = {"show", "--format=format:", // omit header, already generated
noColorOption, decorateOption, m_id};
m_state = GettingDiff;
runCommand(QList<QStringList>() << addConfigurationArguments(args));
return;
} else if (m_state == GettingDiff) {
m_state = Idle;
GitDiffEditorController::processCommandOutput(output);
}
m_state = Idle;
BaseController::reloadFinished(success);
}
///////////////////////////////

View File

@@ -382,7 +382,7 @@ IosQmlProfilerSupport::IosQmlProfilerSupport(RunControl *runControl)
void IosQmlProfilerSupport::start()
{
UrlConnection serverUrl;
QUrl serverUrl;
QTcpServer server;
QTC_ASSERT(server.listen(QHostAddress::LocalHost)
|| server.listen(QHostAddress::LocalHostIPv6), return);

View File

@@ -403,7 +403,9 @@ void AppOutputPane::updateBehaviorSettings()
void AppOutputPane::createNewOutputWindow(RunControl *rc)
{
connect(rc, &RunControl::aboutToStart,
this, &AppOutputPane::slotRunControlStarted);
this, &AppOutputPane::slotRunControlChanged);
connect(rc, &RunControl::started,
this, &AppOutputPane::slotRunControlChanged);
connect(rc, &RunControl::finished,
this, &AppOutputPane::slotRunControlFinished);
connect(rc, &RunControl::applicationProcessHandleChanged,
@@ -620,9 +622,7 @@ void AppOutputPane::projectRemoved()
void AppOutputPane::enableDefaultButtons()
{
const RunControl *rc = currentRunControl();
const bool isRunning = rc && rc->isRunning();
enableButtons(rc, isRunning);
enableButtons(currentRunControl());
}
void AppOutputPane::zoomIn()
@@ -643,10 +643,11 @@ void AppOutputPane::zoomOut()
m_zoom = m_runControlTabs.first().window->fontZoom();
}
void AppOutputPane::enableButtons(const RunControl *rc, bool isRunning)
void AppOutputPane::enableButtons(const RunControl *rc)
{
if (rc) {
m_reRunButton->setEnabled(!isRunning && rc->supportsReRunning());
const bool isRunning = rc->isRunning();
m_reRunButton->setEnabled(rc->isStopped() && rc->supportsReRunning());
m_reRunButton->setIcon(rc->icon().icon());
m_stopAction->setEnabled(isRunning);
if (isRunning && debuggerPlugin() && rc->applicationProcessHandle().isValid()) {
@@ -681,8 +682,7 @@ void AppOutputPane::tabChanged(int i)
{
const int index = indexOf(m_tabWidget->widget(i));
if (i != -1 && index != -1) {
const RunControl *rc = m_runControlTabs.at(index).runControl;
enableButtons(rc, rc->isRunning());
enableButtons(m_runControlTabs.at(index).runControl);
} else {
enableDefaultButtons();
}
@@ -705,11 +705,11 @@ void AppOutputPane::contextMenuRequested(const QPoint &pos, int index)
}
}
void AppOutputPane::slotRunControlStarted()
void AppOutputPane::slotRunControlChanged()
{
RunControl *current = currentRunControl();
if (current && current == sender())
enableButtons(current, true); // RunControl::isRunning() cannot be trusted in signal handler.
enableButtons(current); // RunControl::isRunning() cannot be trusted in signal handler.
}
void AppOutputPane::slotRunControlFinished()
@@ -736,7 +736,7 @@ void AppOutputPane::slotRunControlFinished2(RunControl *sender)
<< " current " << current << m_runControlTabs.size();
if (current && current == sender)
enableButtons(current, false); // RunControl::isRunning() cannot be trusted in signal handler.
enableButtons(current);
ProjectExplorerPlugin::instance()->updateRunActions();

View File

@@ -107,7 +107,7 @@ private:
void attachToRunControl();
void tabChanged(int);
void contextMenuRequested(const QPoint &pos, int index);
void slotRunControlStarted();
void slotRunControlChanged();
void slotRunControlFinished();
void slotRunControlFinished2(ProjectExplorer::RunControl *sender);
@@ -118,7 +118,7 @@ private:
void zoomIn();
void zoomOut();
void enableButtons(const RunControl *rc, bool isRunning);
void enableButtons(const RunControl *rc);
class RunControlTab {
public:

View File

@@ -137,9 +137,11 @@ DeviceEnvironmentFetcher::Ptr DesktopDevice::environmentFetcher() const
return DeviceEnvironmentFetcher::Ptr(new DesktopDeviceEnvironmentFetcher());
}
Connection DesktopDevice::toolControlChannel(const ControlChannelHint &) const
QUrl DesktopDevice::toolControlChannel(const ControlChannelHint &) const
{
return HostName("localhost");
QUrl url;
url.setHost("localhost");
return url;
}
Utils::OsType DesktopDevice::osType() const

View File

@@ -52,7 +52,7 @@ public:
DeviceProcess *createProcess(QObject *parent) const override;
DeviceProcessSignalOperation::Ptr signalOperation() const override;
DeviceEnvironmentFetcher::Ptr environmentFetcher() const override;
Connection toolControlChannel(const ControlChannelHint &) const override;
QUrl toolControlChannel(const ControlChannelHint &) const override;
Utils::OsType osType() const override;
IDevice::Ptr clone() const override;

View File

@@ -411,9 +411,11 @@ void IDevice::setSshParameters(const QSsh::SshConnectionParameters &sshParameter
d->sshParameters.hostKeyDatabase = DeviceManager::instance()->hostKeyDatabase();
}
Connection IDevice::toolControlChannel(const ControlChannelHint &) const
QUrl IDevice::toolControlChannel(const ControlChannelHint &) const
{
return HostName(d->sshParameters.host);
QUrl url;
url.setHost(d->sshParameters.host);
return url;
}
void IDevice::setFreePorts(const Utils::PortList &freePorts)
@@ -470,8 +472,4 @@ DeviceEnvironmentFetcher::DeviceEnvironmentFetcher()
{
}
void *HostName::staticTypeId = &HostName::staticTypeId;
void *UrlConnection::staticTypeId = &UrlConnection::staticTypeId;
} // namespace ProjectExplorer

View File

@@ -189,7 +189,7 @@ public:
void setSshParameters(const QSsh::SshConnectionParameters &sshParameters);
enum ControlChannelHint { QmlControlChannel };
virtual Connection toolControlChannel(const ControlChannelHint &) const;
virtual QUrl toolControlChannel(const ControlChannelHint &) const;
Utils::PortList freePorts() const;
void setFreePorts(const Utils::PortList &freePorts);

View File

@@ -1156,7 +1156,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
SessionManager::save();
});
connect(qApp, &QApplication::applicationStateChanged, this, [](Qt::ApplicationState state) {
if (state == Qt::ApplicationActive)
if (!dd->m_shuttingDown && state == Qt::ApplicationActive)
dd->updateWelcomePage();
});

View File

@@ -45,7 +45,6 @@
#include <coreplugin/icore.h>
#include <coreplugin/icontext.h>
#include <coreplugin/messagemanager.h>
#include <QDir>
#include <QPushButton>
@@ -688,7 +687,6 @@ public:
QString displayName;
Runnable runnable;
IDevice::ConstPtr device;
Connection connection;
Core::Id runMode;
Utils::Icon icon;
const QPointer<RunConfiguration> runConfiguration; // Not owned.
@@ -773,11 +771,6 @@ void RunControl::registerWorkerCreator(Core::Id id, const WorkerCreator &workerC
Q_UNUSED(keys);
}
QList<QPointer<RunWorker> > RunControl::workers() const
{
return d->m_workers;
}
RunWorker *RunControl::createWorker(Core::Id id)
{
auto keys = theWorkerCreators().keys();
@@ -985,16 +978,6 @@ void RunControl::setRunnable(const Runnable &runnable)
d->runnable = runnable;
}
const Connection &RunControl::connection() const
{
return d->connection;
}
void RunControl::setConnection(const Connection &connection)
{
d->connection = connection;
}
QString RunControl::displayName() const
{
return d->displayName;
@@ -1117,6 +1100,11 @@ bool RunControl::isStopping() const
return d->state == RunControlState::Stopping;
}
bool RunControl::isStopped() const
{
return d->state == RunControlState::Stopped;
}
/*!
Prompts to terminate the application with the \gui {Do not ask again}
checkbox.
@@ -1207,7 +1195,6 @@ void RunControlPrivate::setState(RunControlState newState)
void RunControlPrivate::debugMessage(const QString &msg)
{
Core::MessageManager::write(msg, Core::MessageManager::Silent);
qCDebug(statesLog()) << msg;
}
@@ -1487,11 +1474,6 @@ const Runnable &RunWorker::runnable() const
return d->runControl->runnable();
}
const Connection &RunWorker::connection() const
{
return d->runControl->connection();
}
Core::Id RunWorker::runMode() const
{
return d->runControl->runMode();

View File

@@ -198,44 +198,6 @@ private:
std::unique_ptr<Concept> d;
};
class PROJECTEXPLORER_EXPORT Connection
{
struct Concept
{
virtual ~Concept() {}
virtual Concept *clone() const = 0;
virtual void *typeId() const = 0;
};
template <class T>
struct Model : public Concept
{
Model(const T &data) : m_data(data) { }
Concept *clone() const override { return new Model(*this); }
void *typeId() const override { return T::staticTypeId; }
T m_data;
};
public:
Connection() = default;
Connection(const Connection &other) : d(other.d ? other.d->clone() : nullptr) { }
Connection(Connection &&other) /* MSVC 2013 doesn't want = default */ : d(std::move(other.d)) {}
template <class T> Connection(const T &data) : d(new Model<T>(data)) {}
void operator=(Connection other) { d = std::move(other.d); }
template <class T> bool is() const {
return d.get() && (d.get()->typeId() == T::staticTypeId);
}
template <class T> const T &as() const {
return static_cast<Model<T> *>(d.get())->m_data;
}
private:
std::unique_ptr<Concept> d;
};
// Documentation inside.
class PROJECTEXPLORER_EXPORT RunConfiguration : public ProjectConfiguration
{
@@ -387,7 +349,6 @@ public:
void appendMessage(const QString &msg, Utils::OutputFormat format);
IDevice::ConstPtr device() const;
const Runnable &runnable() const;
const Connection &connection() const;
Core::Id runMode() const;
// States
@@ -446,6 +407,7 @@ public:
bool isRunning() const;
bool isStarting() const;
bool isStopping() const;
bool isStopped() const;
void setIcon(const Utils::Icon &icon);
Utils::Icon icon() const;
@@ -465,33 +427,14 @@ public:
const Runnable &runnable() const;
void setRunnable(const Runnable &runnable);
const Connection &connection() const;
void setConnection(const Connection &connection);
virtual void appendMessage(const QString &msg, Utils::OutputFormat format);
virtual void bringApplicationToForeground();
virtual void notifyRemoteSetupDone(Utils::Port) {} // FIXME: Replace by ToolRunner functionality
virtual void notifyRemoteSetupFailed(const QString &) {} // Same.
virtual void notifyRemoteFinished() {} // Same.
static bool showPromptToStopDialog(const QString &title, const QString &text,
const QString &stopButtonText = QString(),
const QString &cancelButtonText = QString(),
bool *prompt = nullptr);
QList<QPointer<RunWorker>> workers() const;
template <class T> T *worker() const {
for (const QPointer<RunWorker> &worker : workers()) {
if (worker) {
if (auto res = qobject_cast<T *>(worker.data()))
return res;
}
}
return nullptr;
}
RunWorker *createWorker(Core::Id id);
using WorkerCreator = std::function<RunWorker *(RunControl *)>;

View File

@@ -41,22 +41,8 @@ bool operator==(const StandardRunnable &r1, const StandardRunnable &r2)
void *StandardRunnable::staticTypeId = &StandardRunnable::staticTypeId;
UrlConnection UrlConnection::fromHost(const QString &host)
{
UrlConnection connection;
connection.setHost(host);
return connection;
}
UrlConnection UrlConnection::localHostWithoutPort()
{
QUrl serverUrl;
QTcpServer server;
serverUrl.setHost(server.serverAddress().toString());
return UrlConnection(serverUrl);
}
UrlConnection UrlConnection::localHostAndFreePort()
QUrl urlFromLocalHostAndFreePort()
{
QUrl serverUrl;
QTcpServer server;
@@ -64,17 +50,22 @@ UrlConnection UrlConnection::localHostAndFreePort()
serverUrl.setHost(server.serverAddress().toString());
serverUrl.setPort(server.serverPort());
}
return UrlConnection(serverUrl);
return serverUrl;
}
UrlConnection UrlConnection::localSocket()
QUrl urlFromLocalSocket()
{
QUrl serverUrl;
serverUrl.setScheme(socketScheme());
serverUrl.setScheme(urlSocketScheme());
Utils::TemporaryFile file("qmlprofiler-freesocket");
if (file.open())
serverUrl.setPath(file.fileName());
return UrlConnection(serverUrl);
return serverUrl;
}
QString urlSocketScheme()
{
return QString("socket");
}
} // namespace ProjectExplorer

View File

@@ -53,32 +53,8 @@ public:
PROJECTEXPLORER_EXPORT bool operator==(const StandardRunnable &r1, const StandardRunnable &r2);
class PROJECTEXPLORER_EXPORT HostName
{
public:
explicit HostName(const QString &host) : m_host(host) {}
QString host() const { return m_host; }
static void *staticTypeId;
private:
QString m_host;
};
class PROJECTEXPLORER_EXPORT UrlConnection : public QUrl
{
public:
UrlConnection() {}
explicit UrlConnection(const QUrl &url) : QUrl(url) {}
static UrlConnection fromHost(const QString &host);
static UrlConnection localHostAndFreePort();
static UrlConnection localHostWithoutPort();
static UrlConnection localSocket();
static QString socketScheme() { return QLatin1String("socket"); }
static void *staticTypeId;
};
PROJECTEXPLORER_EXPORT QUrl urlFromLocalHostAndFreePort();
PROJECTEXPLORER_EXPORT QUrl urlFromLocalSocket();
PROJECTEXPLORER_EXPORT QString urlSocketScheme();
} // namespace ProjectExplorer

View File

@@ -88,7 +88,7 @@ void RubberBandSelectionManipulator::select(SelectionType selectionType)
if (!m_beginFormEditorItem)
return;
QList<QGraphicsItem*> itemList = m_editorView->scene()->items(m_selectionRectangleElement.rect(), Qt::IntersectsItemShape);
QList<QGraphicsItem*> itemList = m_editorView->scene()->items(m_selectionRectangleElement.rect(), Qt::ContainsItemBoundingRect);
QList<QmlItemNode> newNodeList;
foreach (QGraphicsItem* item, itemList)
@@ -97,7 +97,6 @@ void RubberBandSelectionManipulator::select(SelectionType selectionType)
if (formEditorItem
&& formEditorItem->qmlItemNode().isValid()
&& m_beginFormEditorItem->childItems().contains(formEditorItem)
&& formEditorItem->qmlItemNode().instanceIsMovable()
&& formEditorItem->qmlItemNode().modelIsMovable()
&& !formEditorItem->qmlItemNode().instanceIsInLayoutable())

View File

@@ -95,9 +95,13 @@ void SingleSelectionManipulator::select(SelectionType selectionType)
}
break;
case InvertSelection: {
if (selectedNode.isValid()
&& !m_oldSelectionList.contains(selectedNode))
nodeList.append(selectedNode);
nodeList.append(m_oldSelectionList);
if (selectedNode.isValid()) {
if (!m_oldSelectionList.contains(selectedNode))
nodeList.append(selectedNode);
else
nodeList.removeAll(selectedNode);
}
}
}

View File

@@ -71,7 +71,7 @@ static inline bool isSupportedAttachedProperties(const QString &propertyName)
static inline QStringList supportedVersionsList()
{
static const QStringList list = {
"2.0", "2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "2.7", "2.8"
"2.0", "2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "2.7", "2.8", "2.9"
};
return list;
}

View File

@@ -271,10 +271,7 @@ void QmlProfilerRunner::setServerUrl(const QUrl &serverUrl)
QUrl QmlProfilerRunner::serverUrl() const
{
QVariant recordedServer = recordedData(QmlServerUrl);
if (recordedServer.isValid())
return recordedServer.toUrl();
QTC_ASSERT(connection().is<UrlConnection>(), return QUrl());
return connection().as<UrlConnection>();
return recordedServer.toUrl();
}
//
@@ -289,12 +286,12 @@ static QUrl localServerUrl(RunControl *runControl)
const QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(kit);
if (version) {
if (version->qtVersion() >= QtSupport::QtVersionNumber(5, 6, 0))
serverUrl = UrlConnection::localSocket();
serverUrl = urlFromLocalSocket();
else
serverUrl = UrlConnection::localHostAndFreePort();
serverUrl = urlFromLocalHostAndFreePort();
} else {
qWarning("Running QML profiler on Kit without Qt version?");
serverUrl = UrlConnection::localHostAndFreePort();
serverUrl = urlFromLocalHostAndFreePort();
}
return serverUrl;
}

View File

@@ -580,9 +580,8 @@ void QmlProfilerTool::attachToWaitingApplication()
IDevice::ConstPtr device = DeviceKitInformation::device(kit);
QTC_ASSERT(device, return);
Connection toolControl = device->toolControlChannel(IDevice::QmlControlChannel);
QTC_ASSERT(toolControl.is<HostName>(), return);
serverUrl.setHost(toolControl.as<HostName>().host());
QUrl toolControl = device->toolControlChannel(IDevice::QmlControlChannel);
serverUrl.setHost(toolControl.host());
serverUrl.setPort(port);
Debugger::selectPerspective(Constants::QmlProfilerPerspectiveId);

View File

@@ -80,7 +80,7 @@ void LocalQmlProfilerRunnerTest::testRunner1()
QTRY_COMPARE_WITH_TIMEOUT(runCount, 1, 10000);
QTRY_VERIFY_WITH_TIMEOUT(!running, 10000);
serverUrl = UrlConnection::localSocket();
serverUrl = urlFromLocalSocket();
debuggee.executable = QCoreApplication::applicationFilePath();
// comma is used to specify a test function. In this case, an invalid one.
@@ -97,7 +97,7 @@ void LocalQmlProfilerRunnerTest::testRunner2()
QTRY_VERIFY_WITH_TIMEOUT(!running, 10000);
debuggee.commandLineArguments.clear();
serverUrl = UrlConnection::localHostAndFreePort();
serverUrl = urlFromLocalHostAndFreePort();
start();
@@ -119,7 +119,7 @@ void LocalQmlProfilerRunnerTest::testRunner4()
void LocalQmlProfilerRunnerTest::testFindFreePort()
{
QUrl serverUrl = UrlConnection::localHostAndFreePort();
QUrl serverUrl = urlFromLocalHostAndFreePort();
QVERIFY(serverUrl.port() != -1);
QVERIFY(!serverUrl.host().isEmpty());
QTcpServer server;
@@ -128,7 +128,7 @@ void LocalQmlProfilerRunnerTest::testFindFreePort()
void LocalQmlProfilerRunnerTest::testFindFreeSocket()
{
QUrl serverUrl = UrlConnection::localSocket();
QUrl serverUrl = urlFromLocalSocket();
QString socket = serverUrl.path();
QVERIFY(!socket.isEmpty());
QVERIFY(!QFile::exists(socket));

View File

@@ -55,7 +55,7 @@ private:
int runCount = 0;
ProjectExplorer::RunControl *runControl = nullptr;
ProjectExplorer::StandardRunnable debuggee;
ProjectExplorer::UrlConnection serverUrl;
QUrl serverUrl;
};
} // namespace Internal

View File

@@ -70,12 +70,12 @@ void QmlProfilerClientManagerTest::testConnectionFailure_data()
QTest::addColumn<QmlProfilerStateManager *>("stateManager");
QVarLengthArray<QmlProfilerStateManager *> stateManagers({nullptr, &stateManager});
QUrl localUrl = UrlConnection::localHostAndFreePort();
QUrl localUrl = urlFromLocalHostAndFreePort();
QTest::addColumn<QUrl>("serverUrl");
QVarLengthArray<QString> hosts({"", "/-/|\\-\\|/-", localUrl.host()});
QVarLengthArray<int> ports({-1, 5, localUrl.port()});
QVarLengthArray<QString> sockets({"", "/-/|\\-\\|/-", UrlConnection::localSocket().path()});
QVarLengthArray<QString> sockets({"", "/-/|\\-\\|/-", urlFromLocalSocket().path()});
foreach (QmlProfilerModelManager *modelManager, modelManagers) {
foreach (QmlProfilerStateManager *stateManager, stateManagers) {
@@ -101,7 +101,7 @@ void QmlProfilerClientManagerTest::testConnectionFailure_data()
.arg(0)
.arg(socket);
QUrl url;
url.setScheme(ProjectExplorer::UrlConnection::socketScheme());
url.setScheme(urlSocketScheme());
url.setPath(socket);
QTest::newRow(tag.toLatin1().constData()) << modelManager << stateManager << url;
}
@@ -175,7 +175,7 @@ void QmlProfilerClientManagerTest::testUnresponsiveTcp()
clientManager.setProfilerStateManager(&stateManager);
clientManager.setModelManager(&modelManager);
QUrl serverUrl = UrlConnection::localHostAndFreePort();
QUrl serverUrl = urlFromLocalHostAndFreePort();
QTcpServer server;
server.listen(QHostAddress(serverUrl.host()), serverUrl.port());
@@ -204,7 +204,7 @@ void QmlProfilerClientManagerTest::testUnresponsiveLocal()
clientManager.setProfilerStateManager(&stateManager);
clientManager.setModelManager(&modelManager);
QUrl socketUrl = UrlConnection::localSocket();
QUrl socketUrl = urlFromLocalSocket();
QLocalSocket socket;
QSignalSpy connectionSpy(&socket, SIGNAL(connected()));
@@ -256,7 +256,7 @@ void QmlProfilerClientManagerTest::testResponsiveTcp()
{
QFETCH(quint32, flushInterval);
QUrl serverUrl = UrlConnection::localHostAndFreePort();
QUrl serverUrl = urlFromLocalHostAndFreePort();
QSignalSpy openedSpy(&clientManager, SIGNAL(connectionOpened()));
QSignalSpy closedSpy(&clientManager, SIGNAL(connectionClosed()));
@@ -315,7 +315,7 @@ void QmlProfilerClientManagerTest::testResponsiveLocal()
{
QFETCH(quint32, flushInterval);
QUrl socketUrl = UrlConnection::localSocket();
QUrl socketUrl = urlFromLocalSocket();
QSignalSpy openedSpy(&clientManager, SIGNAL(connectionOpened()));
QSignalSpy closedSpy(&clientManager, SIGNAL(connectionClosed()));
@@ -380,7 +380,7 @@ void QmlProfilerClientManagerTest::testInvalidData()
clientManager.setProfilerStateManager(&stateManager);
clientManager.setModelManager(&modelManager);
QUrl serverUrl = UrlConnection::localHostAndFreePort();
QUrl serverUrl = urlFromLocalHostAndFreePort();
bool dataSent = false;
QTcpServer server;
@@ -411,7 +411,7 @@ void QmlProfilerClientManagerTest::testInvalidData()
void QmlProfilerClientManagerTest::testStopRecording()
{
QUrl socketUrl = UrlConnection::localSocket();
QUrl socketUrl = urlFromLocalSocket();
{
QmlProfilerClientManager clientManager;

View File

@@ -45,11 +45,11 @@ using namespace Utils;
namespace Qnx {
namespace Internal {
class QnxAnalyzeeRunner : public ProjectExplorer::SimpleTargetRunner
class QnxAnalyzeeRunner : public SimpleTargetRunner
{
public:
QnxAnalyzeeRunner(ProjectExplorer::RunControl *runControl)
: SimpleTargetRunner(runControl)
QnxAnalyzeeRunner(RunControl *runControl, PortsGatherer *portsGatherer)
: SimpleTargetRunner(runControl), m_portsGatherer(portsGatherer)
{
setDisplayName("QnxAnalyzeeRunner");
}
@@ -57,8 +57,7 @@ public:
private:
void start() override
{
auto portsGatherer = runControl()->worker<PortsGatherer>();
Utils::Port port = portsGatherer->findPort();
Utils::Port port = m_portsGatherer->findPort();
auto r = runnable().as<StandardRunnable>();
if (!r.commandLineArguments.isEmpty())
@@ -70,6 +69,8 @@ private:
SimpleTargetRunner::start();
}
PortsGatherer *m_portsGatherer;
};
@@ -85,7 +86,7 @@ QnxQmlProfilerSupport::QnxQmlProfilerSupport(RunControl *runControl)
auto portsGatherer = new PortsGatherer(runControl);
auto debuggeeRunner = new QnxAnalyzeeRunner(runControl);
auto debuggeeRunner = new QnxAnalyzeeRunner(runControl, portsGatherer);
debuggeeRunner->addDependency(portsGatherer);
auto slog2InfoRunner = new Slog2InfoRunner(runControl);

View File

@@ -56,8 +56,8 @@ namespace Internal {
class QnxDebuggeeRunner : public ProjectExplorer::SimpleTargetRunner
{
public:
QnxDebuggeeRunner(ProjectExplorer::RunControl *runControl)
: SimpleTargetRunner(runControl)
QnxDebuggeeRunner(RunControl *runControl, GdbServerPortsGatherer *portsGatherer)
: SimpleTargetRunner(runControl), m_portsGatherer(portsGatherer)
{
setDisplayName("QnxDebuggeeRunner");
}
@@ -65,24 +65,24 @@ public:
private:
void start() override
{
auto portsGatherer = runControl()->worker<GdbServerPortsGatherer>();
StandardRunnable r = runnable().as<StandardRunnable>();
QStringList arguments;
if (portsGatherer->useGdbServer()) {
Utils::Port pdebugPort = portsGatherer->gdbServerPort();
if (m_portsGatherer->useGdbServer()) {
Utils::Port pdebugPort = m_portsGatherer->gdbServerPort();
r.executable = Constants::QNX_DEBUG_EXECUTABLE;
arguments.append(pdebugPort.toString());
}
if (portsGatherer->useQmlServer()) {
if (m_portsGatherer->useQmlServer()) {
arguments.append(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices,
portsGatherer->qmlServerPort()));
m_portsGatherer->qmlServerPort()));
}
arguments.append(Utils::QtcProcess::splitArgs(r.commandLineArguments));
r.commandLineArguments = Utils::QtcProcess::joinArgs(arguments);
SimpleTargetRunner::start();
}
GdbServerPortsGatherer *m_portsGatherer;
};
@@ -94,12 +94,12 @@ QnxDebugSupport::QnxDebugSupport(RunControl *runControl)
setDisplayName("QnxDebugSupport");
appendMessage(tr("Preparing remote side..."), Utils::LogMessageFormat);
auto portsGatherer = new GdbServerPortsGatherer(runControl);
portsGatherer->setUseGdbServer(isCppDebugging());
portsGatherer->setUseQmlServer(isQmlDebugging());
m_portsGatherer = new GdbServerPortsGatherer(runControl);
m_portsGatherer->setUseGdbServer(isCppDebugging());
m_portsGatherer->setUseQmlServer(isQmlDebugging());
auto debuggeeRunner = new QnxDebuggeeRunner(runControl);
debuggeeRunner->addDependency(portsGatherer);
auto debuggeeRunner = new QnxDebuggeeRunner(runControl, m_portsGatherer);
debuggeeRunner->addDependency(m_portsGatherer);
auto slog2InfoRunner = new Slog2InfoRunner(runControl);
slog2InfoRunner->addDependency(debuggeeRunner);
@@ -109,8 +109,7 @@ QnxDebugSupport::QnxDebugSupport(RunControl *runControl)
void QnxDebugSupport::start()
{
auto portsGatherer = runControl()->worker<GdbServerPortsGatherer>();
Utils::Port pdebugPort = portsGatherer->gdbServerPort();
Utils::Port pdebugPort = m_portsGatherer->gdbServerPort();
auto runConfig = qobject_cast<QnxRunConfiguration *>(runControl()->runConfiguration());
QTC_ASSERT(runConfig, return);
@@ -128,7 +127,7 @@ void QnxDebugSupport::start()
if (isQmlDebugging()) {
params.qmlServer.host = device()->sshParameters().host;
params.qmlServer.port = portsGatherer->qmlServerPort();
params.qmlServer.port = m_portsGatherer->qmlServerPort();
params.inferior.commandLineArguments.replace("%qml_port%", params.qmlServer.port.toString());
}

View File

@@ -40,6 +40,8 @@ public:
private:
void start() override;
void stop() override;
Debugger::GdbServerPortsGatherer *m_portsGatherer;
};
} // namespace Internal

View File

@@ -52,12 +52,12 @@ LinuxDeviceDebugSupport::LinuxDeviceDebugSupport(RunControl *runControl)
{
setDisplayName("LinuxDeviceDebugSupport");
auto portsGatherer = new GdbServerPortsGatherer(runControl);
portsGatherer->setUseGdbServer(isCppDebugging());
portsGatherer->setUseQmlServer(isQmlDebugging());
m_portsGatherer = new GdbServerPortsGatherer(runControl);
m_portsGatherer->setUseGdbServer(isCppDebugging());
m_portsGatherer->setUseQmlServer(isQmlDebugging());
auto gdbServer = new GdbServerRunner(runControl);
gdbServer->addDependency(portsGatherer);
auto gdbServer = new GdbServerRunner(runControl, m_portsGatherer);
gdbServer->addDependency(m_portsGatherer);
addDependency(gdbServer);
@@ -75,12 +75,9 @@ void LinuxDeviceDebugSupport::start()
return;
}
auto portsGatherer = runControl()->worker<GdbServerPortsGatherer>();
QTC_ASSERT(portsGatherer, reportFailure(); return);
const QString host = device()->sshParameters().host;
const Port gdbServerPort = portsGatherer->gdbServerPort();
const Port qmlServerPort = portsGatherer->qmlServerPort();
const Port gdbServerPort = m_portsGatherer->gdbServerPort();
const Port qmlServerPort = m_portsGatherer->qmlServerPort();
DebuggerStartParameters params;
params.startMode = AttachToRemoteServer;

View File

@@ -43,6 +43,7 @@ private:
protected:
QString m_symbolFile;
Debugger::GdbServerPortsGatherer *m_portsGatherer = nullptr;
};
} // namespace RemoteLinux

View File

@@ -30,6 +30,7 @@
#include <vcsbase/vcscommand.h>
#include <vcsbase/vcsbaseconstants.h>
#include <vcsbase/vcsbasediffeditorcontroller.h>
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsbaseeditorconfig.h>
#include <vcsbase/vcsbaseplugin.h>
@@ -167,46 +168,40 @@ QStringList SubversionClient::escapeFiles(const QStringList &files)
return Utils::transform(files, &SubversionClient::escapeFile);
}
class DiffController : public DiffEditorController
class SubversionDiffEditorController : public VcsBaseDiffEditorController
{
Q_OBJECT
public:
DiffController(IDocument *document, const SubversionClient *client, const QString &directory);
SubversionDiffEditorController(IDocument *document,
const QString &workingDirectory);
void setFilesList(const QStringList &filesList);
void setChangeNumber(int changeNumber);
protected:
void reload() override;
private slots:
void slotTextualDiffOutputReceived(const QString &contents);
void processCommandOutput(const QString &output) override;
private:
QString getDescription() const;
void postCollectTextualDiffOutput();
QProcessEnvironment processEnvironment() const;
void requestDescription();
void requestDiff();
const SubversionClient *m_client;
QString m_workingDirectory;
enum State { Idle, GettingDescription, GettingDiff };
State m_state;
QStringList m_filesList;
int m_changeNumber = 0;
};
DiffController::DiffController(IDocument *document, const SubversionClient *client, const QString &directory) :
DiffEditorController(document),
m_client(client),
m_workingDirectory(directory)
SubversionDiffEditorController::SubversionDiffEditorController(
IDocument *document,
const QString &workingDirectory)
: VcsBaseDiffEditorController(document, SubversionPlugin::instance()->client(), workingDirectory)
, m_state(Idle)
{
forceContextLineCount(3); // SVN can not change that when using internal diff
}
QProcessEnvironment DiffController::processEnvironment() const
{
return m_client->processEnvironment();
}
void DiffController::setFilesList(const QStringList &filesList)
void SubversionDiffEditorController::setFilesList(const QStringList &filesList)
{
if (isReloading())
return;
@@ -214,7 +209,7 @@ void DiffController::setFilesList(const QStringList &filesList)
m_filesList = SubversionClient::escapeFiles(filesList);
}
void DiffController::setChangeNumber(int changeNumber)
void SubversionDiffEditorController::setChangeNumber(int changeNumber)
{
if (isReloading())
return;
@@ -222,33 +217,24 @@ void DiffController::setChangeNumber(int changeNumber)
m_changeNumber = qMax(changeNumber, 0);
}
QString DiffController::getDescription() const
void SubversionDiffEditorController::requestDescription()
{
m_state = GettingDescription;
QStringList args(QLatin1String("log"));
args << SubversionClient::addAuthenticationOptions(m_client->settings());
args << SubversionClient::addAuthenticationOptions(client()->settings());
args << QLatin1String("-r");
args << QString::number(m_changeNumber);
const SubversionResponse logResponse =
SubversionPlugin::instance()->runSvn(m_workingDirectory, args,
m_client->vcsTimeoutS(),
VcsCommand::SshPasswordPrompt);
if (logResponse.error)
return QString();
return logResponse.stdOut;
runCommand(QList<QStringList>() << args, VcsCommand::SshPasswordPrompt);
}
void DiffController::postCollectTextualDiffOutput()
void SubversionDiffEditorController::requestDiff()
{
auto command = new VcsCommand(m_workingDirectory, processEnvironment());
command->setCodec(EditorManager::defaultTextCodec());
connect(command, &VcsCommand::stdOutText, this, &DiffController::slotTextualDiffOutputReceived);
// command->addFlags(diffExecutionFlags());
m_state = GettingDiff;
QStringList args;
args << QLatin1String("diff");
args << m_client->addAuthenticationOptions(m_client->settings());
args << SubversionClient::addAuthenticationOptions(client()->settings());
args << QLatin1String("--internal-diff");
if (ignoreWhitespace())
args << QLatin1String("-x") << QLatin1String("-uw");
@@ -258,40 +244,43 @@ void DiffController::postCollectTextualDiffOutput()
} else {
args << m_filesList;
}
command->addJob(m_client->vcsBinary(), args, m_client->vcsTimeoutS());
command->execute();
runCommand(QList<QStringList>() << args, 0);
}
void DiffController::slotTextualDiffOutputReceived(const QString &contents)
void SubversionDiffEditorController::reload()
{
bool ok;
QList<FileData> fileDataList
= DiffUtils::readPatch(contents, &ok);
setDiffFiles(fileDataList, m_workingDirectory);
reloadFinished(true);
if (m_changeNumber) {
requestDescription();
} else {
requestDiff();
}
}
void DiffController::reload()
void SubversionDiffEditorController::processCommandOutput(const QString &output)
{
const QString description = m_changeNumber
? getDescription() : QString();
postCollectTextualDiffOutput();
setDescription(description);
QTC_ASSERT(m_state != Idle, return);
if (m_state == GettingDescription) {
setDescription(output);
requestDiff();
} else if (m_state == GettingDiff) {
m_state = Idle;
VcsBaseDiffEditorController::processCommandOutput(output);
}
}
DiffController *SubversionClient::findOrCreateDiffEditor(const QString &documentId,
SubversionDiffEditorController *SubversionClient::findOrCreateDiffEditor(const QString &documentId,
const QString &source,
const QString &title,
const QString &workingDirectory) const
{
IDocument *document = DiffEditorController::findOrCreateDocument(documentId, title);
DiffController *controller = qobject_cast<DiffController *>(
SubversionDiffEditorController *controller = qobject_cast<SubversionDiffEditorController *>(
DiffEditorController::controller(document));
if (!controller)
controller = new DiffController(document, this, workingDirectory);
controller = new SubversionDiffEditorController(document, workingDirectory);
VcsBasePlugin::setSource(document, source);
EditorManager::activateEditorForDocument(document);
return controller;
}
@@ -304,7 +293,7 @@ void SubversionClient::diff(const QString &workingDirectory, const QStringList &
+ QLatin1String(".Diff.") + VcsBaseEditor::getTitleId(workingDirectory, files);
const QString title = vcsEditorTitle(vcsCmdString, documentId);
DiffController *controller = findOrCreateDiffEditor(documentId, workingDirectory, title,
SubversionDiffEditorController *controller = findOrCreateDiffEditor(documentId, workingDirectory, title,
workingDirectory);
controller->setFilesList(files);
controller->requestReload();
@@ -335,7 +324,7 @@ void SubversionClient::describe(const QString &workingDirectory, int changeNumbe
QStringList(),
QString::number(changeNumber));
DiffController *controller = findOrCreateDiffEditor(documentId, workingDirectory, title, workingDirectory);
SubversionDiffEditorController *controller = findOrCreateDiffEditor(documentId, workingDirectory, title, workingDirectory);
controller->setChangeNumber(changeNumber);
controller->requestReload();
}

View File

@@ -35,7 +35,7 @@ namespace Subversion {
namespace Internal {
class SubversionSettings;
class DiffController;
class SubversionDiffEditorController;
class SubversionClient : public VcsBase::VcsBaseClient
{
@@ -78,7 +78,7 @@ protected:
Core::Id vcsEditorKind(VcsCommandTag cmd) const override;
private:
DiffController *findOrCreateDiffEditor(const QString &documentId, const QString &source,
SubversionDiffEditorController *findOrCreateDiffEditor(const QString &documentId, const QString &source,
const QString &title, const QString &workingDirectory) const;
mutable Utils::FileName m_svnVersionBinary;

View File

@@ -819,6 +819,11 @@ QTextCharFormat SyntaxHighlighter::formatForCategory(int category) const
return d->formats.at(category);
}
void SyntaxHighlighter::highlightBlock(const QString &text)
{
formatSpaces(text);
}
void SyntaxHighlighterPrivate::updateFormats(const FontSettings &fontSettings)
{
for (const auto &pair : Utils::asConst(formatCategories))

View File

@@ -78,7 +78,10 @@ protected:
void setDefaultTextFormatCategories();
void setTextFormatCategories(int count, std::function<TextStyle(int)> formatMapping);
QTextCharFormat formatForCategory(int categoryIndex) const;
virtual void highlightBlock(const QString &text) = 0;
// implement in subclasses
// default implementation highlights whitespace
virtual void highlightBlock(const QString &text);
void setFormat(int start, int count, const QTextCharFormat &format);
void setFormat(int start, int count, const QColor &color);

View File

@@ -27,7 +27,8 @@ HEADERS += vcsbase_global.h \
vcsbaseclientsettings.h \
vcsbaseeditorconfig.h \
submitfieldwidget.h \
submiteditorwidget.h
submiteditorwidget.h \
vcsbasediffeditorcontroller.h
SOURCES += vcsplugin.cpp \
vcsbaseplugin.cpp \
@@ -54,7 +55,8 @@ SOURCES += vcsplugin.cpp \
vcsbaseclientsettings.cpp \
vcsbaseeditorconfig.cpp \
submitfieldwidget.cpp \
submiteditorwidget.cpp
submiteditorwidget.cpp \
vcsbasediffeditorcontroller.cpp
RESOURCES += vcsbase.qrc

View File

@@ -12,6 +12,7 @@ QtcPlugin {
Depends { name: "TextEditor" }
Depends { name: "ProjectExplorer" }
Depends { name: "CppTools" }
Depends { name: "DiffEditor" }
pluginRecommends: [
"CodePaster"
@@ -53,6 +54,8 @@ QtcPlugin {
"vcsbaseclientsettings.cpp",
"vcsbaseclientsettings.h",
"vcsbaseconstants.h",
"vcsbasediffeditorcontroller.cpp",
"vcsbasediffeditorcontroller.h",
"vcsbaseeditor.cpp",
"vcsbaseeditor.h",
"vcsbaseeditorconfig.cpp",

View File

@@ -8,6 +8,7 @@ QTC_PLUGIN_DEPENDS += \
coreplugin \
texteditor \
projectexplorer \
cpptools
cpptools \
diffeditor
QTC_PLUGIN_RECOMMENDS += \
cpaster

View File

@@ -0,0 +1,197 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "vcsbasediffeditorcontroller.h"
#include "vcsbaseclient.h"
#include "vcscommand.h"
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <diffeditor/diffutils.h>
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
#include <QPointer>
using namespace DiffEditor;
using namespace Core;
namespace VcsBase {
static void readPatch(QFutureInterface<QList<FileData>> &futureInterface,
const QString &patch)
{
bool ok;
const QList<FileData> &fileDataList = DiffUtils::readPatch(patch, &ok, &futureInterface);
futureInterface.reportResult(fileDataList);
}
class VcsBaseDiffEditorControllerPrivate
{
public:
VcsBaseDiffEditorControllerPrivate(VcsBaseDiffEditorController *controller,
VcsBaseClientImpl *client,
const QString &workingDirectory);
~VcsBaseDiffEditorControllerPrivate();
void processingFinished();
void processDiff(const QString &patch);
void cancelReload();
void commandFinished(bool success);
VcsBaseDiffEditorController *q;
VcsBaseClientImpl *m_client;
const QString m_directory;
QString m_startupFile;
QString m_output;
QPointer<VcsCommand> m_command;
QFutureWatcher<QList<FileData>> m_processWatcher;
};
VcsBaseDiffEditorControllerPrivate::VcsBaseDiffEditorControllerPrivate(VcsBaseDiffEditorController *controller,
VcsBaseClientImpl *client,
const QString &workingDirectory)
: q(controller)
, m_client(client)
, m_directory(workingDirectory)
{
QObject::connect(&m_processWatcher, &QFutureWatcher<QList<FileData>>::finished, q,
[this] () { processingFinished(); });
}
VcsBaseDiffEditorControllerPrivate::~VcsBaseDiffEditorControllerPrivate()
{
cancelReload();
}
void VcsBaseDiffEditorControllerPrivate::processingFinished()
{
bool success = !m_processWatcher.future().isCanceled();
const QList<FileData> fileDataList = success
? m_processWatcher.future().result() : QList<FileData>();
q->setDiffFiles(fileDataList, q->workingDirectory(), q->startupFile());
q->reloadFinished(success);
}
void VcsBaseDiffEditorControllerPrivate::processDiff(const QString &patch)
{
m_processWatcher.setFuture(Utils::runAsync(&readPatch, patch));
ProgressManager::addTask(m_processWatcher.future(),
q->tr("Processing diff"), "DiffEditor");
}
void VcsBaseDiffEditorControllerPrivate::cancelReload()
{
if (m_command) {
m_command->disconnect();
m_command->cancel();
m_command.clear();
}
if (m_processWatcher.future().isRunning()) {
m_processWatcher.future().cancel();
m_processWatcher.setFuture(QFuture<QList<FileData>>());
}
m_output = QString();
}
void VcsBaseDiffEditorControllerPrivate::commandFinished(bool success)
{
if (m_command)
m_command.clear();
if (!success) {
cancelReload();
q->reloadFinished(success);
return;
}
q->processCommandOutput(m_output);
}
/////////////////////
VcsBaseDiffEditorController::VcsBaseDiffEditorController(IDocument *document,
VcsBaseClientImpl *client,
const QString &workingDirectory)
: DiffEditorController(document)
, d(new VcsBaseDiffEditorControllerPrivate(this, client, workingDirectory))
{
}
VcsBaseDiffEditorController::~VcsBaseDiffEditorController()
{
delete d;
}
void VcsBaseDiffEditorController::runCommand(const QList<QStringList> &args, unsigned flags, QTextCodec *codec)
{
d->cancelReload();
d->m_command = new VcsCommand(workingDirectory(), d->m_client->processEnvironment());
d->m_command->setCodec(codec ? codec : EditorManager::defaultTextCodec());
connect(d->m_command.data(), &VcsCommand::stdOutText, this,
[this] (const QString &output) { d->m_output = output; });
connect(d->m_command.data(), &VcsCommand::finished, this,
[this] (bool success) { d->commandFinished(success); });
d->m_command->addFlags(flags);
for (const QStringList &arg : args) {
QTC_ASSERT(!arg.isEmpty(), continue);
d->m_command->addJob(d->m_client->vcsBinary(), arg, d->m_client->vcsTimeoutS());
}
d->m_command->execute();
}
void VcsBaseDiffEditorController::processCommandOutput(const QString &output)
{
d->processDiff(output);
}
VcsBaseClientImpl *VcsBaseDiffEditorController::client() const
{
return d->m_client;
}
QString VcsBaseDiffEditorController::workingDirectory() const
{
return d->m_directory;
}
void VcsBaseDiffEditorController::setStartupFile(const QString &startupFile)
{
d->m_startupFile = startupFile;
}
QString VcsBaseDiffEditorController::startupFile() const
{
return d->m_startupFile;
}
} // namespace VcsBase

View File

@@ -0,0 +1,62 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "vcsbase_global.h"
#include <diffeditor/diffeditorcontroller.h>
namespace Core { class IDocument; }
namespace VcsBase {
class VcsBaseClientImpl;
class VcsBaseDiffEditorControllerPrivate;
class VCSBASE_EXPORT VcsBaseDiffEditorController : public DiffEditor::DiffEditorController
{
Q_OBJECT
public:
VcsBaseDiffEditorController(Core::IDocument *document,
VcsBaseClientImpl *client,
const QString &workingDirectory);
~VcsBaseDiffEditorController();
protected:
void runCommand(const QList<QStringList> &args, unsigned flags, QTextCodec *codec = nullptr);
virtual void processCommandOutput(const QString &output);
VcsBaseClientImpl *client() const;
QString workingDirectory() const;
void setStartupFile(const QString &startupFile);
QString startupFile() const;
private:
friend class VcsBaseDiffEditorControllerPrivate;
VcsBaseDiffEditorControllerPrivate *d;
};
} //namespace VcsBase

View File

@@ -28,6 +28,21 @@ defineTest(versionIsAtLeast) {
return(false)
}
defineTest(versionIsEqual) {
actual_major_version = $$extractMajorVersion($$1)
actual_minor_version = $$extractMinorVersion($$1)
required_min_major_version = $$2
required_min_minor_version = $$3
isEqual(actual_major_version, $$required_min_major_version) {
isEqual(actual_minor_version, $$required_min_minor_version) {
return(true)
}
}
return(false)
}
defineReplace(findLLVMVersionFromLibDir) {
libdir = $$1
version_dirs = $$files($$libdir/clang/*)
@@ -102,9 +117,13 @@ LIBCLANG_LIBS += $${CLANG_LIB}
QTC_NO_CLANG_LIBTOOLING=$$(QTC_NO_CLANG_LIBTOOLING)
isEmpty(QTC_NO_CLANG_LIBTOOLING) {
!contains(QMAKE_DEFAULT_LIBDIRS, $$LLVM_LIBDIR): LIBTOOLING_LIBS = -L$${LLVM_LIBDIR}
LIBTOOLING_LIBS += $$CLANGTOOLING_LIBS $$LLVM_STATIC_LIBS
contains(QMAKE_DEFAULT_INCDIRS, $$LLVM_INCLUDEPATH): LLVM_INCLUDEPATH =
versionIsEqual($$LLVM_VERSION, 3, 9) {
!contains(QMAKE_DEFAULT_LIBDIRS, $$LLVM_LIBDIR): LIBTOOLING_LIBS = -L$${LLVM_LIBDIR}
LIBTOOLING_LIBS += $$CLANGTOOLING_LIBS $$LLVM_STATIC_LIBS
contains(QMAKE_DEFAULT_INCDIRS, $$LLVM_INCLUDEPATH): LLVM_INCLUDEPATH =
} else {
warning("Clang LibTooling is disabled because only version 3.9 is supported.")
}
} else {
warning("Clang LibTooling is disabled.")
}

View File

@@ -80,6 +80,8 @@ private slots:
void testWithTildeHomePath();
void testMacroExpander_data();
void testMacroExpander();
void testStripAccelerator();
void testStripAccelerator_data();
private:
TestMacroExpander mx;
@@ -176,6 +178,30 @@ void tst_StringUtils::testMacroExpander()
QCOMPARE(in, out);
}
void tst_StringUtils::testStripAccelerator()
{
QFETCH(QString, expected);
QCOMPARE(Utils::stripAccelerator(QTest::currentDataTag()), expected);
}
void tst_StringUtils::testStripAccelerator_data()
{
QTest::addColumn<QString>("expected");
QTest::newRow("Test") << "Test";
QTest::newRow("&Test") << "Test";
QTest::newRow("&&Test") << "&Test";
QTest::newRow("T&est") << "Test";
QTest::newRow("&Te&&st") << "Te&st";
QTest::newRow("T&e&st") << "Test";
QTest::newRow("T&&est") << "T&est";
QTest::newRow("T&&e&st") << "T&est";
QTest::newRow("T&&&est") << "T&est";
QTest::newRow("Tes&t") << "Test";
QTest::newRow("Test&") << "Test";
}
QTEST_MAIN(tst_StringUtils)
#include "tst_stringutils.moc"