From 8c7a54bccebe1afb70a0eb36ada92cd2396bd786 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 15 Jun 2010 11:38:09 +0200 Subject: [PATCH 1/5] VCS[Subversion]: Remove LANG=C setting as it breaks the log output. Task-number: QTCREATORBUG-1623 --- src/plugins/subversion/subversionplugin.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp index 824fec09be0..4776aab912b 100644 --- a/src/plugins/subversion/subversionplugin.cpp +++ b/src/plugins/subversion/subversionplugin.cpp @@ -1062,9 +1062,6 @@ SubversionResponse SubversionPlugin::runSvn(const QString &workingDir, Utils::SynchronousProcess process; if (!workingDir.isEmpty()) process.setWorkingDirectory(workingDir); - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - env.insert(QLatin1String("LANG"), QString(QLatin1Char('C'))); - process.setProcessEnvironment(env); process.setTimeout(timeOut); process.setStdOutCodec(outputCodec); From b8c78764e2d905da4adab7b1c6ad18aa1b77dbe3 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 15 Jun 2010 11:41:43 +0200 Subject: [PATCH 2/5] VCS[Mercurial]: Remove LANG=C setting as it breaks the log output. Task-number: QTCREATORBUG-1623 --- src/plugins/mercurial/mercurialclient.cpp | 2 -- src/plugins/mercurial/mercurialjobrunner.cpp | 13 ------------- src/plugins/mercurial/mercurialjobrunner.h | 3 --- 3 files changed, 18 deletions(-) diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp index 85eb7f4b43e..3db6b7a7f85 100644 --- a/src/plugins/mercurial/mercurialclient.cpp +++ b/src/plugins/mercurial/mercurialclient.cpp @@ -121,8 +121,6 @@ bool MercurialClient::executeHgSynchronously(const QString &workingDir, QProcess hgProcess; if (!workingDir.isEmpty()) hgProcess.setWorkingDirectory(workingDir); - MercurialJobRunner::setProcessEnvironment(hgProcess); - const MercurialSettings &settings = MercurialPlugin::instance()->settings(); const QString binary = settings.binary(); const QStringList arguments = settings.standardArguments() + args; diff --git a/src/plugins/mercurial/mercurialjobrunner.cpp b/src/plugins/mercurial/mercurialjobrunner.cpp index 54f343c122d..e92e73c5e79 100644 --- a/src/plugins/mercurial/mercurialjobrunner.cpp +++ b/src/plugins/mercurial/mercurialjobrunner.cpp @@ -162,16 +162,6 @@ QString MercurialJobRunner::msgTimeout(int timeoutSeconds) return tr("Timed out after %1s waiting for mercurial process to finish.").arg(timeoutSeconds); } -// Set environment for a hg process to run in locale "C". Note that there appears -// to be a bug in hg that causes special characters to be garbled when running -// in a different language, which seems to be independent from the encoding. -void MercurialJobRunner::setProcessEnvironment(QProcess &p) -{ - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - env.insert(QLatin1String("LANG"), QString(QLatin1Char('C'))); - p.setProcessEnvironment(env); -} - void MercurialJobRunner::task(const QSharedPointer &job) { HgTask *taskData = job.data(); @@ -203,9 +193,6 @@ void MercurialJobRunner::task(const QSharedPointer &job) qDebug() << Q_FUNC_INFO << "Repository root is " << taskData->repositoryRoot(); QProcess hgProcess; - hgProcess.setWorkingDirectory(taskData->repositoryRoot()); - MercurialJobRunner::setProcessEnvironment(hgProcess); - hgProcess.start(binary, args); if (!hgProcess.waitForStarted()) { diff --git a/src/plugins/mercurial/mercurialjobrunner.h b/src/plugins/mercurial/mercurialjobrunner.h index df6f1f79d63..ef9c7856c8f 100644 --- a/src/plugins/mercurial/mercurialjobrunner.h +++ b/src/plugins/mercurial/mercurialjobrunner.h @@ -99,9 +99,6 @@ public: static QString msgStartFailed(const QString &binary, const QString &why); static QString msgTimeout(int timeoutSeconds); - // Set environment for a hg process to run in locale "C" - static void setProcessEnvironment(QProcess &p); - protected: void run(); From c44a0e5999e874a1514af522e092a54b3c511779 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 15 Jun 2010 11:57:05 +0200 Subject: [PATCH 3/5] VCS[Mercurial]: Working directory not set for asynchronous commands. Task-number: QTCREATORBUG-1503 --- src/plugins/mercurial/mercurialjobrunner.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/mercurial/mercurialjobrunner.cpp b/src/plugins/mercurial/mercurialjobrunner.cpp index e92e73c5e79..185856a16db 100644 --- a/src/plugins/mercurial/mercurialjobrunner.cpp +++ b/src/plugins/mercurial/mercurialjobrunner.cpp @@ -193,6 +193,8 @@ void MercurialJobRunner::task(const QSharedPointer &job) qDebug() << Q_FUNC_INFO << "Repository root is " << taskData->repositoryRoot(); QProcess hgProcess; + if (!taskData->repositoryRoot().isEmpty()) + hgProcess.setWorkingDirectory(taskData->repositoryRoot()); hgProcess.start(binary, args); if (!hgProcess.waitForStarted()) { From a6e5298591ff2da1482b8e4a81b3aed85d74ee6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Tue, 15 Jun 2010 10:44:07 +0200 Subject: [PATCH 4/5] Fixed handling of text wrapping and a text layout corner case Due to using QTextCursor::columnNumber() instead of QTextCursor::positionInBlock(), a lot of code would not work correctly when used with wrapped lines. In addition, there was an issue with columnNumber() returning 0 right after inserting a character before the last character of a line. Reviewed-by: mae --- src/libs/cplusplus/MatchingText.cpp | 4 ++-- src/plugins/cppeditor/cppquickfix.cpp | 2 +- src/plugins/debugger/watchutils.cpp | 4 ++-- src/plugins/fakevim/fakevimhandler.cpp | 4 ++-- src/plugins/qmlinspector/components/expressionquerywidget.cpp | 2 +- src/plugins/qmljseditor/qmlexpressionundercursor.cpp | 2 +- src/plugins/qmljseditor/qmljscodecompletion.cpp | 2 +- src/plugins/qmljseditor/qmljseditor.cpp | 2 +- src/plugins/texteditor/tabsettings.cpp | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libs/cplusplus/MatchingText.cpp b/src/libs/cplusplus/MatchingText.cpp index a20d2371ac5..55b3a6e6e7a 100644 --- a/src/libs/cplusplus/MatchingText.cpp +++ b/src/libs/cplusplus/MatchingText.cpp @@ -107,7 +107,7 @@ QString MatchingText::insertMatchingBrace(const QTextCursor &cursor, const QStri QTextDocument *doc = tc.document(); QString text = textToProcess; - const QString blockText = tc.block().text().mid(tc.columnNumber()); + const QString blockText = tc.block().text().mid(tc.positionInBlock()); const int length = qMin(blockText.length(), textToProcess.length()); const QChar previousChar = doc->characterAt(tc.selectionEnd() - 1); @@ -217,7 +217,7 @@ QString MatchingText::insertParagraphSeparator(const QTextCursor &tc) const if (tk[index - 1].isNot(T_LBRACE)) return QString(); // nothing to do. - const QString textBlock = tc.block().text().mid(tc.columnNumber()).trimmed(); + const QString textBlock = tc.block().text().mid(tc.positionInBlock()).trimmed(); if (! textBlock.isEmpty()) return QString(); diff --git a/src/plugins/cppeditor/cppquickfix.cpp b/src/plugins/cppeditor/cppquickfix.cpp index 553d443e1c9..714ba6e12a2 100644 --- a/src/plugins/cppeditor/cppquickfix.cpp +++ b/src/plugins/cppeditor/cppquickfix.cpp @@ -74,7 +74,7 @@ public: { _nodes.clear(); _line = cursor.blockNumber() + 1; - _column = cursor.columnNumber() + 1; + _column = cursor.positionInBlock() + 1; accept(_doc->translationUnit()->ast()); return _nodes; } diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp index 46a69895206..99a440e9c32 100644 --- a/src/plugins/debugger/watchutils.cpp +++ b/src/plugins/debugger/watchutils.cpp @@ -747,11 +747,11 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos, // Fetch the expression's code. CPlusPlus::ExpressionUnderCursor expressionUnderCursor; expr = expressionUnderCursor(tc); - *column = tc.columnNumber(); + *column = tc.positionInBlock(); *line = tc.blockNumber(); } else { const QTextCursor tc = plaintext->textCursor(); - *column = tc.columnNumber(); + *column = tc.positionInBlock(); *line = tc.blockNumber(); } diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 22256898c4e..c8df9217b9e 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -1464,8 +1464,8 @@ void FakeVimHandler::Private::updateSelection() } else if (isVisualBlockMode()) { QTextCursor tc = m_tc; tc.setPosition(anchorPos); - int anchorColumn = tc.columnNumber(); - int cursorColumn = m_tc.columnNumber(); + int anchorColumn = tc.positionInBlock(); + int cursorColumn = m_tc.positionInBlock(); int anchorRow = tc.blockNumber(); int cursorRow = m_tc.blockNumber(); int startColumn = qMin(anchorColumn, cursorColumn); diff --git a/src/plugins/qmlinspector/components/expressionquerywidget.cpp b/src/plugins/qmlinspector/components/expressionquerywidget.cpp index 9888980ef56..e3f8a0bf19d 100644 --- a/src/plugins/qmlinspector/components/expressionquerywidget.cpp +++ b/src/plugins/qmlinspector/components/expressionquerywidget.cpp @@ -283,7 +283,7 @@ bool ExpressionQueryWidget::eventFilter(QObject *obj, QEvent *event) bool atLastLine = !(cursor.block().next().isValid()); if (!atLastLine) return true; - if (cursor.columnNumber() <= m_prompt.count()) + if (cursor.positionInBlock() <= m_prompt.count()) return true; cursor.deletePreviousChar(); m_expr = cursor.block().text().mid(m_prompt.count()); diff --git a/src/plugins/qmljseditor/qmlexpressionundercursor.cpp b/src/plugins/qmljseditor/qmlexpressionundercursor.cpp index d5a82a5eccb..d6b2604eb4f 100644 --- a/src/plugins/qmljseditor/qmlexpressionundercursor.cpp +++ b/src/plugins/qmljseditor/qmlexpressionundercursor.cpp @@ -102,7 +102,7 @@ public: _cursor = cursor; QTextBlock block = _cursor.block(); - const QString blockText = block.text().left(cursor.columnNumber()); + const QString blockText = block.text().left(cursor.positionInBlock()); scanner.setScanComments(false); const QList tokens = scanner(blockText, startState(block)); diff --git a/src/plugins/qmljseditor/qmljscodecompletion.cpp b/src/plugins/qmljseditor/qmljscodecompletion.cpp index 2c67687259a..01e0228ab30 100644 --- a/src/plugins/qmljseditor/qmljscodecompletion.cpp +++ b/src/plugins/qmljseditor/qmljscodecompletion.cpp @@ -513,7 +513,7 @@ bool CodeCompletion::triggersCompletion(TextEditor::ITextEditable *editor) QTextCursor tc = ed->textCursor(); QTextBlock block = tc.block(); - const int column = tc.columnNumber(); + const int column = tc.positionInBlock(); const int blockState = qMax(0, block.previous().userState()) & 0xff; const QString blockText = block.text(); diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index f8e92136d12..b06e4791a27 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -1130,7 +1130,7 @@ bool QmlJSTextEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, co Scanner tokenize; const QList tokens = tokenize(blockText, blockState); - const int pos = cursor.columnNumber(); + const int pos = cursor.positionInBlock(); int tokenIndex = 0; for (; tokenIndex < tokens.size(); ++tokenIndex) { diff --git a/src/plugins/texteditor/tabsettings.cpp b/src/plugins/texteditor/tabsettings.cpp index 20e80446634..9c7864a9cbd 100644 --- a/src/plugins/texteditor/tabsettings.cpp +++ b/src/plugins/texteditor/tabsettings.cpp @@ -192,7 +192,7 @@ bool TabSettings::tabShouldIndent(const QTextDocument *document, QTextCursor cur return true; if (document->characterAt(tc.position()).isSpace()) { tc.movePosition(QTextCursor::WordRight); - if (tc.columnNumber() >= cursor.columnNumber()) { + if (tc.positionInBlock() >= cursor.positionInBlock()) { if (suggestedPosition) *suggestedPosition = tc.position(); // Suggest position after whitespace if (m_tabKeyBehavior == TabLeadingWhitespaceIndents) From 83dba068ce27a2f74301abce8facab0bb2035c91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Tue, 15 Jun 2010 12:07:15 +0200 Subject: [PATCH 5/5] Avoid triggering indent for electric characters in comments and strings In comments and strings, electric characters have no syntactical significance and the unnecessary automatic reindent can be annoying. Reviewed-by: Erik Verbruggen --- src/plugins/cppeditor/cppeditor.cpp | 34 +++++++- src/plugins/cppeditor/cppeditor.h | 1 + src/plugins/qmljseditor/qmljseditor.cpp | 99 +++++++++++++---------- src/plugins/qmljseditor/qmljseditor.h | 1 + src/plugins/texteditor/basetexteditor.cpp | 7 +- src/plugins/texteditor/basetexteditor.h | 1 + 6 files changed, 100 insertions(+), 43 deletions(-) diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 1b4e59c82c0..4db9047e77f 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -1588,6 +1588,38 @@ bool CPPEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, return true; } +bool CPPEditor::contextAllowsElectricCharacters(const QTextCursor &cursor) const +{ + CPlusPlus::TokenUnderCursor tokenUnderCursor; + const SimpleToken tk = tokenUnderCursor(cursor); + + // XXX Duplicated from CPPEditor::isInComment to avoid tokenizing twice + if (tk.isComment()) { + const int pos = cursor.selectionEnd() - cursor.block().position(); + + if (pos == tk.end()) { + if (tk.is(T_CPP_COMMENT) || tk.is(T_CPP_DOXY_COMMENT)) + return false; + + const int state = cursor.block().userState() & 0xFF; + if (state > 0) + return false; + } + + if (pos < tk.end()) + return false; + } + else if (tk.is(T_STRING_LITERAL) || tk.is(T_WIDE_STRING_LITERAL) + || tk.is(T_CHAR_LITERAL) || tk.is(T_WIDE_CHAR_LITERAL)) { + + const int pos = cursor.selectionEnd() - cursor.block().position(); + if (pos <= tk.end()) + return false; + } + + return true; +} + bool CPPEditor::isInComment(const QTextCursor &cursor) const { CPlusPlus::TokenUnderCursor tokenUnderCursor; @@ -1729,7 +1761,7 @@ void CPPEditor::contextMenuEvent(QContextMenuEvent *e) // ### enable // updateSemanticInfo(m_semanticHighlighter->semanticInfo(currentSource())); - QMenu *menu = new QMenu(); + QMenu *menu = new QMenu; Core::ActionManager *am = Core::ICore::instance()->actionManager(); Core::ActionContainer *mcontext = am->actionContainer(CppEditor::Constants::M_CONTEXT); diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index 35ba10f759d..fb5758c5840 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -221,6 +221,7 @@ protected: virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert = QString()) const; + virtual bool contextAllowsElectricCharacters(const QTextCursor &cursor) const; virtual bool isInComment(const QTextCursor &cursor) const; diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index b06e4791a27..d56368a042a 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -1096,6 +1096,34 @@ static bool isCompleteStringLiteral(const QStringRef &text) return false; } +static Token tokenUnderCursor(const QTextCursor &cursor) +{ + const QString blockText = cursor.block().text(); + const int blockState = blockStartState(cursor.block()); + + Scanner tokenize; + const QList tokens = tokenize(blockText, blockState); + const int pos = cursor.positionInBlock(); + + int tokenIndex = 0; + for (; tokenIndex < tokens.size(); ++tokenIndex) { + const Token &token = tokens.at(tokenIndex); + + if (token.is(Token::Comment) || token.is(Token::String)) { + if (pos > token.begin() && pos <= token.end()) + break; + } else { + if (pos >= token.begin() && pos < token.end()) + break; + } + } + + if (tokenIndex != tokens.size()) + return tokens.at(tokenIndex); + + return Token(); +} + bool QmlJSTextEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert) const { QChar ch; @@ -1125,56 +1153,45 @@ bool QmlJSTextEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, co return false; } // end of switch - const QString blockText = cursor.block().text(); - const int blockState = blockStartState(cursor.block()); + const Token token = tokenUnderCursor(cursor); + switch (token.kind) { + case Token::Comment: + return false; - Scanner tokenize; - const QList tokens = tokenize(blockText, blockState); - const int pos = cursor.positionInBlock(); + case Token::String: { + const QString blockText = cursor.block().text(); + const QStringRef tokenText = blockText.midRef(token.offset, token.length); + const QChar quote = tokenText.at(0); - int tokenIndex = 0; - for (; tokenIndex < tokens.size(); ++tokenIndex) { - const Token &token = tokens.at(tokenIndex); - - if (pos >= token.begin()) { - if (pos < token.end()) - break; - - else if (pos == token.end() && (token.is(Token::Comment) || - token.is(Token::String))) - break; - } - } - - if (tokenIndex != tokens.size()) { - const Token &token = tokens.at(tokenIndex); - - switch (token.kind) { - case Token::Comment: - return false; - - case Token::String: { - const QStringRef tokenText = blockText.midRef(token.offset, token.length); - const QChar quote = tokenText.at(0); - - if (ch != quote || isCompleteStringLiteral(tokenText)) - break; - - return false; - } - - default: + if (ch != quote || isCompleteStringLiteral(tokenText)) break; - } // end of switch + + return false; } + default: + break; + } // end of switch + return true; } -bool QmlJSTextEditor::isInComment(const QTextCursor &) const +bool QmlJSTextEditor::contextAllowsElectricCharacters(const QTextCursor &cursor) const { - // ### implement me - return false; + Token token = tokenUnderCursor(cursor); + qDebug() << cursor.positionInBlock() << token.begin() << token.end(); + switch (token.kind) { + case Token::Comment: + case Token::String: + return false; + default: + return true; + } +} + +bool QmlJSTextEditor::isInComment(const QTextCursor &cursor) const +{ + return tokenUnderCursor(cursor).is(Token::Comment); } QString QmlJSTextEditor::insertMatchingBrace(const QTextCursor &tc, const QString &text, QChar, int *skippedChars) const diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h index cb1edfcf28d..5d24fdd3835 100644 --- a/src/plugins/qmljseditor/qmljseditor.h +++ b/src/plugins/qmljseditor/qmljseditor.h @@ -245,6 +245,7 @@ protected: //// brace matching virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert = QString()) const; + virtual bool contextAllowsElectricCharacters(const QTextCursor &cursor) const; virtual bool isInComment(const QTextCursor &cursor) const; virtual QString insertMatchingBrace(const QTextCursor &tc, const QString &text, QChar la, int *skippedChars) const; virtual QString insertParagraphSeparator(const QTextCursor &tc) const; diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 90858bb4d59..601e64555cb 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -1332,7 +1332,7 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e) cursor.insertText(autoText); cursor.setPosition(pos); } - if (!electricChar.isNull()) + if (!electricChar.isNull() && contextAllowsElectricCharacters(cursor)) indent(document(), cursor, electricChar); if (doEditBlock) @@ -3856,6 +3856,11 @@ bool BaseTextEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, return false; } +bool BaseTextEditor::contextAllowsElectricCharacters(const QTextCursor &cursor) const +{ + return contextAllowsAutoParentheses(cursor); +} + bool BaseTextEditor::isInComment(const QTextCursor &cursor) const { Q_UNUSED(cursor); diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h index 066ec0d8a08..14d52b466ca 100644 --- a/src/plugins/texteditor/basetexteditor.h +++ b/src/plugins/texteditor/basetexteditor.h @@ -403,6 +403,7 @@ protected: virtual void reindent(QTextDocument *doc, const QTextCursor &cursor); virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert = QString()) const; + virtual bool contextAllowsElectricCharacters(const QTextCursor &cursor) const; // Returns true if the cursor is inside a comment. virtual bool isInComment(const QTextCursor &cursor) const;