forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/4.9'
Change-Id: Ieed07c7fd0f422f8e1a96877c07916c7c1c1816e
This commit is contained in:
@@ -221,7 +221,7 @@ CppTools::CursorInfo::Range toCursorInfoRange(const SourceRangeContainer &source
|
||||
const SourceLocationContainer &end = sourceRange.end;
|
||||
const unsigned length = end.column - start.column;
|
||||
|
||||
return CppTools::CursorInfo::Range(start.line, start.column, length);
|
||||
return {start.line, start.column, length};
|
||||
}
|
||||
|
||||
static
|
||||
|
@@ -39,6 +39,7 @@ class ClangCompletionAssistInterface;
|
||||
class ClangCompletionContextAnalyzer
|
||||
{
|
||||
public:
|
||||
ClangCompletionContextAnalyzer() = delete;
|
||||
ClangCompletionContextAnalyzer(const ClangCompletionAssistInterface *assistInterface,
|
||||
CPlusPlus::LanguageFeatures languageFeatures);
|
||||
void analyze();
|
||||
@@ -61,8 +62,6 @@ public:
|
||||
bool addSnippets() const { return m_addSnippets; }
|
||||
|
||||
private:
|
||||
ClangCompletionContextAnalyzer();
|
||||
|
||||
int startOfFunctionCall(int endOfExpression) const;
|
||||
|
||||
void setActionAndClangPosition(CompletionAction action,
|
||||
|
@@ -91,7 +91,7 @@ QChar selectionEndChar(const QChar startSymbol)
|
||||
return QLatin1Char('"');
|
||||
if (startSymbol == '<')
|
||||
return QLatin1Char('>');
|
||||
return QChar();
|
||||
return {};
|
||||
}
|
||||
|
||||
void selectToLocationEnd(QTextCursor &cursor)
|
||||
|
@@ -386,10 +386,14 @@ private:
|
||||
|
||||
static int widthLimit()
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
||||
auto screen = QGuiApplication::screenAt(QCursor::pos());
|
||||
if (!screen)
|
||||
screen = QGuiApplication::primaryScreen();
|
||||
return screen->availableGeometry().width() / 2;
|
||||
#else
|
||||
return QApplication::desktop()->availableGeometry(QCursor::pos()).width() / 2;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
|
@@ -209,12 +209,12 @@ TextEditor::BlockRange
|
||||
toTextEditorBlock(QTextDocument *textDocument,
|
||||
const ClangBackEnd::SourceRangeContainer &sourceRangeContainer)
|
||||
{
|
||||
return TextEditor::BlockRange(::Utils::Text::positionInText(textDocument,
|
||||
sourceRangeContainer.start.line,
|
||||
sourceRangeContainer.start.column),
|
||||
::Utils::Text::positionInText(textDocument,
|
||||
sourceRangeContainer.end.line,
|
||||
sourceRangeContainer.end.column));
|
||||
return {::Utils::Text::positionInText(textDocument,
|
||||
sourceRangeContainer.start.line,
|
||||
sourceRangeContainer.start.column),
|
||||
::Utils::Text::positionInText(textDocument,
|
||||
sourceRangeContainer.end.line,
|
||||
sourceRangeContainer.end.column)};
|
||||
}
|
||||
|
||||
QList<TextEditor::BlockRange>
|
||||
|
@@ -35,6 +35,8 @@
|
||||
#include <utils/textutils.h>
|
||||
#include <utils/algorithm.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
@@ -199,7 +201,7 @@ void ClangFollowSymbol::findLink(const CppTools::CursorInEditor &data,
|
||||
if (m_watcher)
|
||||
m_watcher->cancel();
|
||||
|
||||
m_watcher.reset(new FutureSymbolWatcher());
|
||||
m_watcher = std::make_unique<FutureSymbolWatcher>();
|
||||
|
||||
QObject::connect(m_watcher.get(), &FutureSymbolWatcher::finished, [=, filePath=data.filePath(),
|
||||
callback=std::move(processLinkCallback)]() mutable {
|
||||
|
@@ -138,10 +138,7 @@ TextEditor::HighlightingResult toHighlightingResult(
|
||||
{
|
||||
const auto textStyles = toTextStyles(tokenInfo.types);
|
||||
|
||||
return TextEditor::HighlightingResult(tokenInfo.line,
|
||||
tokenInfo.column,
|
||||
tokenInfo.length,
|
||||
textStyles);
|
||||
return {tokenInfo.line, tokenInfo.column, tokenInfo.length, textStyles};
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
@@ -233,8 +233,8 @@ bool OverviewModel::isGenerated(const QModelIndex &) const
|
||||
auto item = static_cast<TokenTreeItem *>(itemForIndex(sourceIndex));
|
||||
if (!item)
|
||||
return {};
|
||||
return ::Utils::LineColumn(static_cast<int>(item->token.line),
|
||||
static_cast<int>(item->token.column));
|
||||
return {static_cast<int>(item->token.line),
|
||||
static_cast<int>(item->token.column)};
|
||||
}
|
||||
|
||||
OverviewModel::Range OverviewModel::rangeFromIndex(const QModelIndex &sourceIndex) const
|
||||
|
@@ -408,6 +408,36 @@ int ClangFormatBaseIndenter::indentBeforeCursor(const QTextBlock &block,
|
||||
return cursorPositionInEditor;
|
||||
}
|
||||
|
||||
static bool doNotIndentInContext(QTextDocument *doc, int pos)
|
||||
{
|
||||
const QChar character = doc->characterAt(pos);
|
||||
const QTextBlock currentBlock = doc->findBlock(pos);
|
||||
const QString text = currentBlock.text().left(pos - currentBlock.position());
|
||||
switch (character.toLatin1()) {
|
||||
default:
|
||||
break;
|
||||
case ':':
|
||||
// Do not indent when it's the first ':' and it's not the 'case' line.
|
||||
if (text.contains(QLatin1String("case")) || text.contains(QLatin1String("default"))
|
||||
|| text.contains(QLatin1String("public")) || text.contains(QLatin1String("private"))
|
||||
|| text.contains(QLatin1String("protected")) || text.contains(QLatin1String("signals"))
|
||||
|| text.contains(QLatin1String("Q_SIGNALS"))) {
|
||||
return false;
|
||||
}
|
||||
if (pos > 0 && doc->characterAt(pos - 1) != ':')
|
||||
return true;
|
||||
break;
|
||||
case '<':
|
||||
case '>':
|
||||
// "<<" and ">>" could be problematic
|
||||
if (pos > 0 && doc->characterAt(pos - 1) == character)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
|
||||
const QChar &typedChar,
|
||||
int cursorPositionInEditor)
|
||||
@@ -416,12 +446,21 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
|
||||
const int blockPosition = currentBlock.position();
|
||||
trimFirstNonEmptyBlock(currentBlock);
|
||||
|
||||
if (typedChar != QChar::Null && cursorPositionInEditor > 0
|
||||
&& m_doc->characterAt(cursorPositionInEditor - 1) == typedChar
|
||||
&& doNotIndentInContext(m_doc, cursorPositionInEditor - 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (formatWhileTyping()
|
||||
&& (cursorPositionInEditor == -1 || cursorPositionInEditor >= blockPosition)) {
|
||||
&& (cursorPositionInEditor == -1 || cursorPositionInEditor >= blockPosition)
|
||||
&& (typedChar == QChar::Null || typedChar == ';' || typedChar == '}')) {
|
||||
// Format before current position only in case the cursor is inside the indented block.
|
||||
// So if cursor position is less then the block position then the current line is before
|
||||
// the indented block - don't trigger extra formatting in this case.
|
||||
// cursorPositionInEditor == -1 means the consition matches automatically.
|
||||
|
||||
// Format only before newline or complete statement not to break code.
|
||||
if (cursorPositionInEditor >= 0)
|
||||
cursorPositionInEditor += currentBlock.position() - blockPosition;
|
||||
else
|
||||
|
@@ -462,6 +462,8 @@ static int formatRange(QTextDocument *doc,
|
||||
bool CppEditorDocument::save(QString *errorString, const QString &fileName, bool autoSave)
|
||||
{
|
||||
if (indenter()->formatOnSave()) {
|
||||
QTextCursor cursor(document());
|
||||
cursor.joinPreviousEditBlock();
|
||||
auto *layout = qobject_cast<TextEditor::TextDocumentLayout *>(document()->documentLayout());
|
||||
const int documentRevision = layout->lastSaveRevision;
|
||||
|
||||
@@ -483,6 +485,7 @@ bool CppEditorDocument::save(QString *errorString, const QString &fileName, bool
|
||||
}
|
||||
if (editedRange.first != -1)
|
||||
formatRange(document(), indenter(), editedRange, tabSettings());
|
||||
cursor.endEditBlock();
|
||||
}
|
||||
|
||||
return TextEditor::TextDocument::save(errorString, fileName, autoSave);
|
||||
|
@@ -624,11 +624,15 @@ void DebuggerToolTipWidget::computeSize()
|
||||
// Add a bit of space to account for tooltip border, and not
|
||||
// touch the border of the screen.
|
||||
QPoint pos(x(), y());
|
||||
QTC_ASSERT(QApplication::desktop(), return);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
||||
auto screen = QGuiApplication::screenAt(pos);
|
||||
if (!screen)
|
||||
screen = QGuiApplication::primaryScreen();
|
||||
QRect desktopRect = screen->availableGeometry();
|
||||
#else
|
||||
QTC_ASSERT(QApplication::desktop(), return);
|
||||
QRect desktopRect = QApplication::desktop()->availableGeometry();
|
||||
#endif
|
||||
const int maxWidth = desktopRect.right() - pos.x() - 5 - 5;
|
||||
const int maxHeight = desktopRect.bottom() - pos.y() - 5 - 5;
|
||||
|
||||
|
@@ -164,7 +164,9 @@ PerfProfilerTool::PerfProfilerTool(QObject *parent) :
|
||||
m_filterMenu = new QMenu(m_filterButton);
|
||||
m_aggregateButton = new QToolButton;
|
||||
m_recordedLabel = new QLabel;
|
||||
m_recordedLabel->setProperty("panelwidget", true);
|
||||
m_delayLabel = new QLabel;
|
||||
m_delayLabel->setProperty("panelwidget", true);
|
||||
|
||||
m_perspective.setAboutToActivateCallback([this]() { createViews(); });
|
||||
}
|
||||
|
@@ -82,10 +82,6 @@ QVariantList PerfTimelineModel::labels() const
|
||||
sample.insert(QLatin1String("id"), PerfEvent::LastSpecialTypeId);
|
||||
result << sample;
|
||||
|
||||
QVariantMap kernel;
|
||||
kernel.insert(QLatin1String("description"), tr("[kernel]"));
|
||||
result << kernel;
|
||||
|
||||
const PerfProfilerTraceManager *manager = traceManager();
|
||||
const bool aggregated = manager->aggregateAddresses();
|
||||
for (int i = 0; i < m_locationOrder.length(); ++i) {
|
||||
|
@@ -185,7 +185,11 @@ bool BuildStepList::removeStep(int position)
|
||||
|
||||
void BuildStepList::moveStepUp(int position)
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
|
||||
m_steps.swapItemsAt(position - 1, position);
|
||||
#else
|
||||
m_steps.swap(position - 1, position);
|
||||
#endif
|
||||
emit stepMoved(position, position - 1);
|
||||
}
|
||||
|
||||
|
@@ -171,7 +171,28 @@ bool QmakePriFileNode::removeSubProject(const QString &proFilePath)
|
||||
bool QmakePriFileNode::addFiles(const QStringList &filePaths, QStringList *notAdded)
|
||||
{
|
||||
QmakePriFile *pri = priFile();
|
||||
return pri ? pri->addFiles(filePaths, notAdded) : false;
|
||||
if (!pri)
|
||||
return false;
|
||||
QList<Node *> matchingNodes = findNodes([filePaths](const Node *n) {
|
||||
return n->nodeType() == NodeType::File && filePaths.contains(n->filePath().toString());
|
||||
});
|
||||
matchingNodes = filtered(matchingNodes, [](const Node *n) {
|
||||
for (const Node *parent = n->parentFolderNode(); parent;
|
||||
parent = parent->parentFolderNode()) {
|
||||
if (dynamic_cast<const ResourceEditor::ResourceTopLevelNode *>(parent))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
QStringList alreadyPresentFiles = transform<QStringList>(matchingNodes,
|
||||
[](const Node *n) { return n->filePath().toString(); });
|
||||
alreadyPresentFiles.removeDuplicates();
|
||||
QStringList actualFilePaths = filePaths;
|
||||
for (const QString &e : alreadyPresentFiles)
|
||||
actualFilePaths.removeOne(e);
|
||||
if (notAdded)
|
||||
*notAdded = alreadyPresentFiles;
|
||||
return pri->addFiles(actualFilePaths, notAdded);
|
||||
}
|
||||
|
||||
bool QmakePriFileNode::removeFiles(const QStringList &filePaths, QStringList *notRemoved)
|
||||
|
@@ -213,9 +213,7 @@ QmlProfilerTool::QmlProfilerTool()
|
||||
this, &QmlProfilerTool::toggleVisibleFeature);
|
||||
|
||||
d->m_timeLabel = new QLabel();
|
||||
QPalette palette;
|
||||
palette.setColor(QPalette::WindowText, Qt::white);
|
||||
d->m_timeLabel->setPalette(palette);
|
||||
d->m_timeLabel->setProperty("panelwidget", true);
|
||||
d->m_timeLabel->setIndent(10);
|
||||
updateTimeDisplay();
|
||||
connect(d->m_timeLabel, &QObject::destroyed, &d->m_recordingTimer, &QTimer::stop);
|
||||
|
@@ -121,6 +121,11 @@ Highlighter::Definition Highlighter::definitionForFileName(const QString &fileNa
|
||||
return highlightRepository()->definitionForFileName(fileName);
|
||||
}
|
||||
|
||||
Highlighter::Definition Highlighter::definitionForName(const QString &name)
|
||||
{
|
||||
return highlightRepository()->definitionForName(name);
|
||||
}
|
||||
|
||||
Highlighter::Definitions Highlighter::definitionsForDocument(const TextDocument *document)
|
||||
{
|
||||
const Utils::MimeType mimeType = Utils::mimeTypeForName(document->mimeType());
|
||||
|
@@ -46,6 +46,7 @@ public:
|
||||
static Definition definitionForDocument(const TextDocument *document);
|
||||
static Definition definitionForMimeType(const QString &mimeType);
|
||||
static Definition definitionForFileName(const QString &fileName);
|
||||
static Definition definitionForName(const QString &name);
|
||||
|
||||
static Definitions definitionsForDocument(const TextDocument *document);
|
||||
static Definitions definitionsForMimeType(const QString &mimeType);
|
||||
|
@@ -611,7 +611,7 @@ public:
|
||||
void updateCodeFoldingVisible();
|
||||
|
||||
void reconfigure();
|
||||
void updateSyntaxInfoBar(bool showInfo);
|
||||
void updateSyntaxInfoBar(const Highlighter::Definitions &definitions, const QString &fileName);
|
||||
void configureGenericHighlighter(const KSyntaxHighlighting::Definition &definition);
|
||||
|
||||
public:
|
||||
@@ -3274,27 +3274,43 @@ void TextEditorWidgetPrivate::reconfigure()
|
||||
q->configureGenericHighlighter();
|
||||
}
|
||||
|
||||
void TextEditorWidgetPrivate::updateSyntaxInfoBar(bool showInfo)
|
||||
void TextEditorWidgetPrivate::updateSyntaxInfoBar(const Highlighter::Definitions &definitions,
|
||||
const QString &fileName)
|
||||
{
|
||||
Id id(Constants::INFO_SYNTAX_DEFINITION);
|
||||
Id missing(Constants::INFO_MISSING_SYNTAX_DEFINITION);
|
||||
Id multiple(Constants::INFO_MULTIPLE_SYNTAX_DEFINITIONS);
|
||||
InfoBar *infoBar = m_document->infoBar();
|
||||
|
||||
if (showInfo) {
|
||||
InfoBarEntry info(id,
|
||||
BaseTextEditor::tr(
|
||||
"A highlight definition was not found for this file. "
|
||||
"Would you like to update highlight definition files?"),
|
||||
if (definitions.isEmpty() && infoBar->canInfoBeAdded(missing)
|
||||
&& !TextEditorSettings::highlighterSettings().isIgnoredFilePattern(fileName)) {
|
||||
InfoBarEntry info(missing,
|
||||
BaseTextEditor::tr("A highlight definition was not found for this file. "
|
||||
"Would you like to update highlight definition files?"),
|
||||
InfoBarEntry::GlobalSuppressionEnabled);
|
||||
info.setCustomButtonInfo(BaseTextEditor::tr("Update Definitions"), [&]() {
|
||||
m_document->infoBar()->removeInfo(id);
|
||||
info.setCustomButtonInfo(BaseTextEditor::tr("Update Definitions"), [missing, this]() {
|
||||
m_document->infoBar()->removeInfo(missing);
|
||||
Highlighter::updateDefinitions([widget = QPointer<TextEditorWidget>(q)]() {
|
||||
if (widget)
|
||||
widget->configureGenericHighlighter();
|
||||
});
|
||||
});
|
||||
|
||||
infoBar->removeInfo(multiple);
|
||||
infoBar->addInfo(info);
|
||||
} else if (definitions.size() > 1) {
|
||||
InfoBarEntry info(multiple,
|
||||
BaseTextEditor::tr("More than one highlight definition was found for this file. "
|
||||
"Which one should be used to highlight this file?"));
|
||||
info.setComboInfo(Utils::transform(definitions, &Highlighter::Definition::name),
|
||||
[this](const QString &definition) {
|
||||
this->configureGenericHighlighter(Highlighter::definitionForName(definition));
|
||||
});
|
||||
|
||||
infoBar->removeInfo(missing);
|
||||
infoBar->addInfo(info);
|
||||
} else {
|
||||
infoBar->removeInfo(id);
|
||||
infoBar->removeInfo(multiple);
|
||||
infoBar->removeInfo(missing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8236,7 +8252,11 @@ void TextEditorWidgetPrivate::updateTabStops()
|
||||
// to be set as an int. A work around is to access directly the QTextOption.
|
||||
qreal charWidth = QFontMetricsF(q->font()).width(QLatin1Char(' '));
|
||||
QTextOption option = q->document()->defaultTextOption();
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
||||
option.setTabStopDistance(charWidth * m_document->tabSettings().m_tabSize);
|
||||
#else
|
||||
option.setTabStop(charWidth * m_document->tabSettings().m_tabSize);
|
||||
#endif
|
||||
q->document()->setDefaultTextOption(option);
|
||||
}
|
||||
|
||||
@@ -8514,11 +8534,10 @@ QString TextEditorWidget::textAt(int from, int to) const
|
||||
|
||||
void TextEditorWidget::configureGenericHighlighter()
|
||||
{
|
||||
const Highlighter::Definition definition = Highlighter::definitionForDocument(textDocument());
|
||||
d->configureGenericHighlighter(definition);
|
||||
d->updateSyntaxInfoBar(!definition.isValid()
|
||||
&& !TextEditorSettings::highlighterSettings().isIgnoredFilePattern(
|
||||
textDocument()->filePath().fileName()));
|
||||
const Highlighter::Definitions definitions = Highlighter::definitionsForDocument(textDocument());
|
||||
d->configureGenericHighlighter(definitions.isEmpty() ? Highlighter::Definition()
|
||||
: definitions.first());
|
||||
d->updateSyntaxInfoBar(definitions, textDocument()->filePath().fileName());
|
||||
}
|
||||
|
||||
int TextEditorWidget::blockNumberForVisibleRow(int row) const
|
||||
|
@@ -188,7 +188,8 @@ const char GOTO_NEXT_WORD_WITH_SELECTION[] = "TextEditor.GotoNextWordWithSelecti
|
||||
const char GOTO_PREVIOUS_WORD_CAMEL_CASE_WITH_SELECTION[] = "TextEditor.GotoPreviousWordCamelCaseWithSelection";
|
||||
const char GOTO_NEXT_WORD_CAMEL_CASE_WITH_SELECTION[] = "TextEditor.GotoNextWordCamelCaseWithSelection";
|
||||
const char C_TEXTEDITOR_MIMETYPE_TEXT[] = "text/plain";
|
||||
const char INFO_SYNTAX_DEFINITION[] = "TextEditor.InfoSyntaxDefinition";
|
||||
const char INFO_MISSING_SYNTAX_DEFINITION[] = "TextEditor.InfoSyntaxDefinition";
|
||||
const char INFO_MULTIPLE_SYNTAX_DEFINITIONS[] = "TextEditor.InfoMultipleSyntaxDefinitions";
|
||||
const char TASK_OPEN_FILE[] = "TextEditor.Task.OpenFile";
|
||||
const char CIRCULAR_PASTE[] = "TextEditor.CircularPaste";
|
||||
const char SWITCH_UTF8BOM[] = "TextEditor.SwitchUtf8bom";
|
||||
|
Reference in New Issue
Block a user