From df16c1b68723a015c96dd1c66442d2ca310855ef Mon Sep 17 00:00:00 2001 From: Roberto Raggi <roberto.raggi@nokia.com> Date: Wed, 22 Apr 2009 15:21:04 +0200 Subject: [PATCH] Initial work on the DUI editor-plugin. --- src/plugins/duieditor/DuiEditor.mimetypes.xml | 8 + src/plugins/duieditor/DuiEditor.pluginspec | 25 + src/plugins/duieditor/duicodecompletion.cpp | 151 ++++++ src/plugins/duieditor/duicodecompletion.h | 43 ++ src/plugins/duieditor/duieditor.cpp | 432 ++++++++++++++++++ src/plugins/duieditor/duieditor.h | 127 +++++ src/plugins/duieditor/duieditor.pro | 29 ++ .../duieditor/duieditoractionhandler.cpp | 100 ++++ .../duieditor/duieditoractionhandler.h | 58 +++ src/plugins/duieditor/duieditorconstants.h | 46 ++ src/plugins/duieditor/duieditorfactory.cpp | 83 ++++ src/plugins/duieditor/duieditorfactory.h | 73 +++ src/plugins/duieditor/duieditorplugin.cpp | 163 +++++++ src/plugins/duieditor/duieditorplugin.h | 82 ++++ src/plugins/duieditor/duihighlighter.cpp | 110 +++++ src/plugins/duieditor/duihighlighter.h | 64 +++ src/plugins/plugins.pro | 5 + .../qscripthighlighter/qscripthighlighter.cpp | 11 +- .../qscripthighlighter/qscripthighlighter.h | 4 + 19 files changed, 1612 insertions(+), 2 deletions(-) create mode 100644 src/plugins/duieditor/DuiEditor.mimetypes.xml create mode 100644 src/plugins/duieditor/DuiEditor.pluginspec create mode 100644 src/plugins/duieditor/duicodecompletion.cpp create mode 100644 src/plugins/duieditor/duicodecompletion.h create mode 100644 src/plugins/duieditor/duieditor.cpp create mode 100644 src/plugins/duieditor/duieditor.h create mode 100644 src/plugins/duieditor/duieditor.pro create mode 100644 src/plugins/duieditor/duieditoractionhandler.cpp create mode 100644 src/plugins/duieditor/duieditoractionhandler.h create mode 100644 src/plugins/duieditor/duieditorconstants.h create mode 100644 src/plugins/duieditor/duieditorfactory.cpp create mode 100644 src/plugins/duieditor/duieditorfactory.h create mode 100644 src/plugins/duieditor/duieditorplugin.cpp create mode 100644 src/plugins/duieditor/duieditorplugin.h create mode 100644 src/plugins/duieditor/duihighlighter.cpp create mode 100644 src/plugins/duieditor/duihighlighter.h diff --git a/src/plugins/duieditor/DuiEditor.mimetypes.xml b/src/plugins/duieditor/DuiEditor.mimetypes.xml new file mode 100644 index 00000000000..a5e9425e2d5 --- /dev/null +++ b/src/plugins/duieditor/DuiEditor.mimetypes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0"?> +<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'> + <mime-type type="application/x-dui"> + <sub-class-of type="text/plain"/> + <comment>DUI file</comment> + <glob pattern="*.dui"/> + </mime-type> +</mime-info> diff --git a/src/plugins/duieditor/DuiEditor.pluginspec b/src/plugins/duieditor/DuiEditor.pluginspec new file mode 100644 index 00000000000..989651ddaea --- /dev/null +++ b/src/plugins/duieditor/DuiEditor.pluginspec @@ -0,0 +1,25 @@ +<plugin name="DuiEditor" version="1.1.80" compatVersion="1.1.80"> + <vendor>Nokia Corporation</vendor> + <copyright>(C) 2008-2009 Nokia Corporation</copyright> + <license> +Commercial Usage + +Licensees holding valid Qt Commercial licenses may use this plugin in +accordance with the Qt Commercial License Agreement provided with the +Software or, alternatively, in accordance with the terms contained in +a written agreement between you and Nokia. + +GNU Lesser General Public License Usage + +Alternatively, this plugin may be used under the terms of the GNU Lesser +General Public License version 2.1 as published by the Free Software +Foundation. Please review the following information to +ensure the GNU Lesser General Public License version 2.1 requirements +will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.</license> + <description>Editor for DUI.</description> + <url>http://www.qtsoftware.com</url> + <dependencyList> + <dependency name="Core" version="1.1.80"/> + <dependency name="TextEditor" version="1.1.80"/> + </dependencyList> +</plugin> diff --git a/src/plugins/duieditor/duicodecompletion.cpp b/src/plugins/duieditor/duicodecompletion.cpp new file mode 100644 index 00000000000..6dbbce8e9d5 --- /dev/null +++ b/src/plugins/duieditor/duicodecompletion.cpp @@ -0,0 +1,151 @@ + +#include "duicodecompletion.h" +#include "duieditor.h" +#include <texteditor/basetexteditor.h> +#include <QtDebug> + +using namespace DuiEditor::Internal; + +DuiCodeCompletion::DuiCodeCompletion(QObject *parent) + : TextEditor::ICompletionCollector(parent), + m_editor(0), + m_startPosition(0), + m_caseSensitivity(Qt::CaseSensitive) +{ } + +DuiCodeCompletion::~DuiCodeCompletion() +{ } + +Qt::CaseSensitivity DuiCodeCompletion::caseSensitivity() const +{ return m_caseSensitivity; } + +void DuiCodeCompletion::setCaseSensitivity(Qt::CaseSensitivity caseSensitivity) +{ m_caseSensitivity = caseSensitivity; } + +bool DuiCodeCompletion::supportsEditor(TextEditor::ITextEditable *editor) +{ + if (qobject_cast<ScriptEditor *>(editor->widget())) + return true; + + return false; +} + +bool DuiCodeCompletion::triggersCompletion(TextEditor::ITextEditable *) +{ return false; } + +int DuiCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) +{ + m_editor = editor; + + ScriptEditor *edit = qobject_cast<ScriptEditor *>(m_editor->widget()); + if (! edit) + return -1; + + int pos = editor->position(); + + while (editor->characterAt(pos - 1).isLetterOrNumber() || editor->characterAt(pos - 1) == QLatin1Char('_')) + --pos; + + m_startPosition = pos; + m_completions.clear(); + + foreach (const QString &word, edit->words()) { + TextEditor::CompletionItem item(this); + item.m_text = word; + m_completions.append(item); + } + + return pos; +} + +void DuiCodeCompletion::completions(QList<TextEditor::CompletionItem> *completions) +{ + // ### FIXME: this code needs to be generalized. + + const int length = m_editor->position() - m_startPosition; + + if (length == 0) + *completions = m_completions; + else if (length > 0) { + const QString key = m_editor->textAt(m_startPosition, length); + + /* + * This code builds a regular expression in order to more intelligently match + * camel-case style. This means upper-case characters will be rewritten as follows: + * + * A => [a-z0-9_]*A (for any but the first capital letter) + * + * Meaning it allows any sequence of lower-case characters to preceed an + * upper-case character. So for example gAC matches getActionController. + */ + QString keyRegExp; + keyRegExp += QLatin1Char('^'); + bool first = true; + foreach (const QChar &c, key) { + if (c.isUpper() && !first) { + keyRegExp += QLatin1String("[a-z0-9_]*"); + keyRegExp += c; + } else if (m_caseSensitivity == Qt::CaseInsensitive && c.isLower()) { + keyRegExp += QLatin1Char('['); + keyRegExp += c; + keyRegExp += c.toUpper(); + keyRegExp += QLatin1Char(']'); + } else { + keyRegExp += QRegExp::escape(c); + } + first = false; + } + const QRegExp regExp(keyRegExp, Qt::CaseSensitive); + + foreach (TextEditor::CompletionItem item, m_completions) { + if (regExp.indexIn(item.m_text) == 0) { + item.m_relevance = (key.length() > 0 && + item.m_text.startsWith(key, Qt::CaseInsensitive)) ? 1 : 0; + (*completions) << item; + } + } + } +} + +void DuiCodeCompletion::complete(const TextEditor::CompletionItem &item) +{ + const QString toInsert = item.m_text; + const int length = m_editor->position() - m_startPosition; + m_editor->setCurPos(m_startPosition); + m_editor->replace(length, toInsert); +} + +bool DuiCodeCompletion::partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems) +{ + if (completionItems.count() == 1) { + complete(completionItems.first()); + return true; + } else { + // Compute common prefix + QString firstKey = completionItems.first().m_text; + QString lastKey = completionItems.last().m_text; + const int length = qMin(firstKey.length(), lastKey.length()); + firstKey.truncate(length); + lastKey.truncate(length); + + while (firstKey != lastKey) { + firstKey.chop(1); + lastKey.chop(1); + } + + int typedLength = m_editor->position() - m_startPosition; + if (!firstKey.isEmpty() && firstKey.length() > typedLength) { + m_editor->setCurPos(m_startPosition); + m_editor->replace(typedLength, firstKey); + } + } + return false; +} + +void DuiCodeCompletion::cleanup() +{ + m_editor = 0; + m_startPosition = 0; + m_completions.clear(); +} + diff --git a/src/plugins/duieditor/duicodecompletion.h b/src/plugins/duieditor/duicodecompletion.h new file mode 100644 index 00000000000..dbd91b15cfb --- /dev/null +++ b/src/plugins/duieditor/duicodecompletion.h @@ -0,0 +1,43 @@ +#ifndef DUICODECOMPLETION_H +#define DUICODECOMPLETION_H + +#include <texteditor/icompletioncollector.h> + +namespace TextEditor { +class ITextEditable; +} + +namespace DuiEditor { +namespace Internal { + +class DuiCodeCompletion: public TextEditor::ICompletionCollector +{ + Q_OBJECT + +public: + DuiCodeCompletion(QObject *parent = 0); + virtual ~DuiCodeCompletion(); + + Qt::CaseSensitivity caseSensitivity() const; + void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity); + + virtual bool supportsEditor(TextEditor::ITextEditable *editor); + virtual bool triggersCompletion(TextEditor::ITextEditable *editor); + virtual int startCompletion(TextEditor::ITextEditable *editor); + virtual void completions(QList<TextEditor::CompletionItem> *completions); + virtual void complete(const TextEditor::CompletionItem &item); + virtual bool partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems); + virtual void cleanup(); + +private: + TextEditor::ITextEditable *m_editor; + int m_startPosition; + QList<TextEditor::CompletionItem> m_completions; + Qt::CaseSensitivity m_caseSensitivity; +}; + + +} // end of namespace Internal +} // end of namespace DuiEditor + +#endif // DUICODECOMPLETION_H diff --git a/src/plugins/duieditor/duieditor.cpp b/src/plugins/duieditor/duieditor.cpp new file mode 100644 index 00000000000..ec658d9ac67 --- /dev/null +++ b/src/plugins/duieditor/duieditor.cpp @@ -0,0 +1,432 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#include "duieditor.h" +#include "duieditorconstants.h" +#include "duihighlighter.h" +#include "duieditorplugin.h" + +#include "parser/javascriptengine_p.h" +#include "parser/javascriptparser_p.h" +#include "parser/javascriptlexer_p.h" +#include "parser/javascriptnodepool_p.h" +#include "parser/javascriptastvisitor_p.h" +#include "parser/javascriptast_p.h" + +#include <indenter.h> + +#include <coreplugin/icore.h> +#include <coreplugin/actionmanager/actionmanager.h> +#include <texteditor/basetextdocument.h> +#include <texteditor/fontsettings.h> +#include <texteditor/textblockiterator.h> +#include <texteditor/texteditorconstants.h> +#include <texteditor/texteditorsettings.h> + +#include <QtCore/QTimer> +#include <QtCore/QtDebug> + +#include <QtGui/QMenu> +#include <QtGui/QComboBox> + +enum { + UPDATE_DOCUMENT_DEFAULT_INTERVAL = 250 +}; + +using namespace JavaScript::AST; + + +namespace DuiEditor { +namespace Internal { + +class FindDeclarations: protected Visitor +{ + QList<Declaration> declarations; + +public: + QList<Declaration> accept(JavaScript::AST::Node *node) + { + JavaScript::AST::Node::acceptChild(node, this); + return declarations; + } + +protected: + using Visitor::visit; + + virtual bool visit(FunctionExpression *) + { + return false; + } + + virtual bool visit(FunctionDeclaration *ast) + { + if (! ast->name) + return false; + + QString text = ast->name->asString(); + + text += QLatin1Char('('); + for (FormalParameterList *it = ast->formals; it; it = it->next) { + if (it->name) + text += it->name->asString(); + + if (it->next) + text += QLatin1String(", "); + } + + text += QLatin1Char(')'); + + Declaration d; + d.text = text; +#if 0 // ### FIXME + d.startLine = ast->startLine; + d.startColumn = ast->startColumn; + d.endLine = ast->endLine; + d.endColumn = ast->endColumn; +#endif + + declarations.append(d); + + return false; + } + + virtual bool visit(VariableDeclaration *ast) + { + if (! ast->name) + return false; + + Declaration d; + d.text = ast->name->asString(); +#if 0 // ### FIXME + d.startLine= ast->startLine; + d.startColumn = ast->startColumn; + d.endLine = ast->endLine; + d.endColumn = ast->endColumn; +#endif + declarations.append(d); + return false; + } +}; + +ScriptEditorEditable::ScriptEditorEditable(ScriptEditor *editor, const QList<int>& context) + : BaseTextEditorEditable(editor), m_context(context) +{ +} + +ScriptEditor::ScriptEditor(const Context &context, + QWidget *parent) : + TextEditor::BaseTextEditor(parent), + m_context(context), + m_methodCombo(0) +{ + setParenthesesMatchingEnabled(true); + setMarksVisible(true); + setCodeFoldingSupported(true); + setCodeFoldingVisible(true); + setMimeType(DuiEditor::Constants::C_DUIEDITOR_MIMETYPE); + + m_updateDocumentTimer = new QTimer(this); + m_updateDocumentTimer->setInterval(UPDATE_DOCUMENT_DEFAULT_INTERVAL); + m_updateDocumentTimer->setSingleShot(true); + + connect(m_updateDocumentTimer, SIGNAL(timeout()), this, SLOT(updateDocumentNow())); + + connect(this, SIGNAL(textChanged()), this, SLOT(updateDocument())); + + baseTextDocument()->setSyntaxHighlighter(new DuiHighlighter); +} + +ScriptEditor::~ScriptEditor() +{ +} + +QList<Declaration> ScriptEditor::declarations() const +{ return m_declarations; } + +QStringList ScriptEditor::words() const +{ return m_words; } + +Core::IEditor *ScriptEditorEditable::duplicate(QWidget *parent) +{ + ScriptEditor *newEditor = new ScriptEditor(m_context, parent); + newEditor->duplicateFrom(editor()); + DuiEditorPlugin::instance()->initializeEditor(newEditor); + return newEditor->editableInterface(); +} + +const char *ScriptEditorEditable::kind() const +{ + return DuiEditor::Constants::C_DUIEDITOR; +} + +ScriptEditor::Context ScriptEditorEditable::context() const +{ + return m_context; +} + +void ScriptEditor::updateDocument() +{ + m_updateDocumentTimer->start(UPDATE_DOCUMENT_DEFAULT_INTERVAL); +} + +void ScriptEditor::updateDocumentNow() +{ + // ### move in the parser thread. + + m_updateDocumentTimer->stop(); + + const QString fileName = file()->fileName(); + const QString code = toPlainText(); + + JavaScriptParser parser; + JavaScriptEnginePrivate driver; + + JavaScript::NodePool nodePool(fileName, &driver); + driver.setNodePool(&nodePool); + + JavaScript::Lexer lexer(&driver); + lexer.setCode(code, /*line = */ 1); + driver.setLexer(&lexer); + + if (parser.parse(&driver)) { + FindDeclarations decls; + m_declarations = decls.accept(driver.ast()); + + m_words.clear(); + foreach (const JavaScriptNameIdImpl &id, driver.literals()) + m_words.append(id.asString()); + + QStringList items; + items.append(tr("<Select Symbol>")); + + foreach (Declaration decl, m_declarations) + items.append(decl.text); + + m_methodCombo->clear(); + m_methodCombo->addItems(items); + updateMethodBoxIndex(); + } + + QList<QTextEdit::ExtraSelection> selections; + + QTextCharFormat errorFormat; + errorFormat.setUnderlineColor(Qt::red); + errorFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline); + + QTextEdit::ExtraSelection sel; + + foreach (const JavaScriptParser::DiagnosticMessage &d, parser.diagnosticMessages()) { + if (d.isWarning()) + continue; + + int line = d.line; + int column = d.column; + + if (column == 0) + column = 1; + + QTextCursor c(document()->findBlockByNumber(line - 1)); + sel.cursor = c; + sel.cursor.setPosition(c.position() + column - 1); + sel.cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + sel.format = errorFormat; + + selections.append(sel); + } + + setExtraSelections(CodeWarningsSelection, selections); +} + +void ScriptEditor::jumpToMethod(int index) +{ + if (index) { + Declaration d = m_declarations.at(index - 1); + gotoLine(d.startLine, d.startColumn - 1); + setFocus(); + } +} + +void ScriptEditor::updateMethodBoxIndex() +{ + int line = 0, column = 0; + convertPosition(position(), &line, &column); + + int currentSymbolIndex = 0; + + int index = 0; + while (index < m_declarations.size()) { + const Declaration &d = m_declarations.at(index++); + + if (line < d.startLine) + break; + else + currentSymbolIndex = index; + } + + m_methodCombo->setCurrentIndex(currentSymbolIndex); +} + +void ScriptEditor::updateMethodBoxToolTip() +{ +} + +void ScriptEditor::updateFileName() +{ +} + +void ScriptEditor::setFontSettings(const TextEditor::FontSettings &fs) +{ + TextEditor::BaseTextEditor::setFontSettings(fs); + DuiHighlighter *highlighter = qobject_cast<DuiHighlighter*>(baseTextDocument()->syntaxHighlighter()); + if (!highlighter) + return; + + static QVector<QString> categories; + if (categories.isEmpty()) { + categories << QLatin1String(TextEditor::Constants::C_NUMBER) + << QLatin1String(TextEditor::Constants::C_STRING) + << QLatin1String(TextEditor::Constants::C_TYPE) + << QLatin1String(TextEditor::Constants::C_KEYWORD) + << QLatin1String(TextEditor::Constants::C_PREPROCESSOR) + << QLatin1String(TextEditor::Constants::C_LABEL) + << QLatin1String(TextEditor::Constants::C_COMMENT); + } + + highlighter->setFormats(fs.toTextCharFormats(categories)); + highlighter->rehighlight(); +} + +bool ScriptEditor::isElectricCharacter(const QChar &ch) const +{ + if (ch == QLatin1Char('{') || ch == QLatin1Char('}')) + return true; + return false; +} + + // Indent a code line based on previous +template <class Iterator> +static void indentScriptBlock(const TextEditor::TabSettings &ts, + const QTextBlock &block, + const Iterator &programBegin, + const Iterator &programEnd, + QChar typedChar) +{ + typedef typename SharedTools::Indenter<Iterator> Indenter ; + Indenter &indenter = Indenter::instance(); + indenter.setTabSize(ts.m_tabSize); + indenter.setIndentSize(ts.m_indentSize); + const TextEditor::TextBlockIterator current(block); + const int indent = indenter.indentForBottomLine(current, programBegin, + programEnd, typedChar); + ts.indentLine(block, indent); +} + +void ScriptEditor::indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar) +{ +#if 0 + const TextEditor::TextBlockIterator begin(doc->begin()); + const TextEditor::TextBlockIterator end(block.next()); + indentScriptBlock(tabSettings(), block, begin, end, typedChar); +#else + Q_UNUSED(doc) + Q_UNUSED(typedChar) + + TextEditor::TabSettings ts = tabSettings(); + const int tabSize = qMax(1, ts.m_tabSize); + + int indent = 0; + QTextBlock it = block.previous(); + for (; it.isValid(); it = it.previous()) { + const QString blockText = it.text(); + + if (! blockText.isEmpty()) { + for (int i = 0; i < blockText.length(); ++i) { + const QChar ch = blockText.at(i); + + if (ch == QLatin1Char('\t')) + indent += (indent + tabSize) % tabSize; + else if (ch.isSpace()) + ++indent; + else + break; + } + + break; + } + } + ts.indentLine(block, indent); +#endif +} + +TextEditor::BaseTextEditorEditable *ScriptEditor::createEditableInterface() +{ + ScriptEditorEditable *editable = new ScriptEditorEditable(this, m_context); + createToolBar(editable); + return editable; +} + +void ScriptEditor::createToolBar(ScriptEditorEditable *editable) +{ + m_methodCombo = new QComboBox; + m_methodCombo->setMinimumContentsLength(22); + //m_methodCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents); + + // Make the combo box prefer to expand + QSizePolicy policy = m_methodCombo->sizePolicy(); + policy.setHorizontalPolicy(QSizePolicy::Expanding); + m_methodCombo->setSizePolicy(policy); + + connect(m_methodCombo, SIGNAL(activated(int)), this, SLOT(jumpToMethod(int))); + connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateMethodBoxIndex())); + connect(m_methodCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMethodBoxToolTip())); + + connect(file(), SIGNAL(changed()), this, SLOT(updateFileName())); + + QToolBar *toolBar = editable->toolBar(); + + QList<QAction*> actions = toolBar->actions(); + toolBar->insertWidget(actions.first(), m_methodCombo); +} + +void ScriptEditor::contextMenuEvent(QContextMenuEvent *e) +{ + QMenu *menu = createStandardContextMenu(); + + if (Core::ActionContainer *mcontext = Core::ICore::instance()->actionManager()->actionContainer(DuiEditor::Constants::M_CONTEXT)) { + QMenu *contextMenu = mcontext->menu(); + foreach (QAction *action, contextMenu->actions()) + menu->addAction(action); + } + + menu->exec(e->globalPos()); + delete menu; +} + +} // namespace Internal +} // namespace DuiEditor diff --git a/src/plugins/duieditor/duieditor.h b/src/plugins/duieditor/duieditor.h new file mode 100644 index 00000000000..7d7a8284817 --- /dev/null +++ b/src/plugins/duieditor/duieditor.h @@ -0,0 +1,127 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#ifndef DUIDITORW_H +#define DUIDITORW_H + +#include <texteditor/basetexteditor.h> + +QT_BEGIN_NAMESPACE +class QComboBox; +class QTimer; +QT_END_NAMESPACE + +namespace Core { + class ICore; +} + +namespace DuiEditor { +namespace Internal { + +class DuiHighlighter; + +class ScriptEditor; + +class ScriptEditorEditable : public TextEditor::BaseTextEditorEditable +{ +public: + ScriptEditorEditable(ScriptEditor *, const QList<int> &); + QList<int> context() const; + + bool duplicateSupported() const { return true; } + Core::IEditor *duplicate(QWidget *parent); + const char *kind() const; + +private: + QList<int> m_context; +}; + + +struct Declaration +{ + QString text; + int startLine; + int startColumn; + int endLine; + int endColumn; + + Declaration() + : startLine(0), + startColumn(0), + endLine(0), + endColumn(0) + { } +}; + +class ScriptEditor : public TextEditor::BaseTextEditor +{ + Q_OBJECT + +public: + typedef QList<int> Context; + + ScriptEditor(const Context &context, + QWidget *parent = 0); + ~ScriptEditor(); + + QList<Declaration> declarations() const; + QStringList words() const; + +public slots: + virtual void setFontSettings(const TextEditor::FontSettings &); + +private slots: + void updateDocument(); + void updateDocumentNow(); + void jumpToMethod(int index); + void updateMethodBoxIndex(); + void updateMethodBoxToolTip(); + void updateFileName(); + +protected: + void contextMenuEvent(QContextMenuEvent *e); + TextEditor::BaseTextEditorEditable *createEditableInterface(); + void createToolBar(ScriptEditorEditable *editable); + +private: + virtual bool isElectricCharacter(const QChar &ch) const; + virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar); + + const Context m_context; + + QTimer *m_updateDocumentTimer; + QComboBox *m_methodCombo; + QList<Declaration> m_declarations; + QStringList m_words; +}; + +} // namespace Internal +} // namespace DuiEditor + +#endif // DUIDITORW_H diff --git a/src/plugins/duieditor/duieditor.pro b/src/plugins/duieditor/duieditor.pro new file mode 100644 index 00000000000..4af552b625b --- /dev/null +++ b/src/plugins/duieditor/duieditor.pro @@ -0,0 +1,29 @@ +TEMPLATE = lib +TARGET = DuiEditor +QT += script + +include(../../qworkbenchplugin.pri) +include(../../plugins/coreplugin/coreplugin.pri) +include(../../plugins/texteditor/texteditor.pri) +include(../../shared/qscripthighlighter/qscripthighlighter.pri) +include(../../shared/indenter/indenter.pri) +include($$(QTDIR_DUI)/src/declarative/qml/parser/parser.pri) + +INCLUDEPATH += $$(QTDIR_DUI)/src/declarative/qml # FIXME: remove me + +HEADERS += duieditor.h \ +duieditorfactory.h \ +duieditorplugin.h \ +duihighlighter.h \ +duieditoractionhandler.h \ +duicodecompletion.h \ +duieditorconstants.h + +SOURCES += duieditor.cpp \ +duieditorfactory.cpp \ +duieditorplugin.cpp \ +duihighlighter.cpp \ +duieditoractionhandler.cpp \ +duicodecompletion.cpp + +RESOURCES += duieditor.qrc diff --git a/src/plugins/duieditor/duieditoractionhandler.cpp b/src/plugins/duieditor/duieditoractionhandler.cpp new file mode 100644 index 00000000000..23e437faea4 --- /dev/null +++ b/src/plugins/duieditor/duieditoractionhandler.cpp @@ -0,0 +1,100 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#include "duieditoractionhandler.h" +#include "duieditorconstants.h" +#include "duieditor.h" + +#include <coreplugin/icore.h> +#include <coreplugin/actionmanager/actionmanager.h> +#include <coreplugin/scriptmanager/scriptmanager.h> + +#include <QtCore/QDebug> +#include <QtGui/QAction> +#include <QtGui/QMainWindow> +#include <QtGui/QMessageBox> + +static QAction *actionFromId(const QString &id) +{ + Core::Command *cmd = Core::ICore::instance()->actionManager()->command(id); + if (!cmd) + return 0; + return cmd->action(); +} + +namespace DuiEditor { +namespace Internal { + +DuiEditorActionHandler::DuiEditorActionHandler() + : TextEditor::TextEditorActionHandler(QLatin1String(DuiEditor::Constants::C_DUIEDITOR), + Format), + m_runAction(0) +{ +} + +void DuiEditorActionHandler::createActions() +{ + TextEditor::TextEditorActionHandler::createActions(); + m_runAction = actionFromId(QLatin1String(DuiEditor::Constants::RUN)); + connect(m_runAction, SIGNAL(triggered()), this, SLOT(run())); +} + + +void DuiEditorActionHandler::run() +{ + typedef Core::ScriptManager::Stack Stack; + if (!currentEditor()) + return; + + const QString script = currentEditor()->toPlainText(); + + // run + Stack errorStack; + QString errorMessage; + if (Core::ICore::instance()->scriptManager()->runScript(script, &errorMessage, &errorStack)) + return; + + // try to find a suitable error line in the stack + // ignoring 0 and other files (todo: open other files?) + int errorLineNumber = 0; + if (const int numFrames = errorStack.size()) { + for (int f = 0; f < numFrames; f++) { + if (errorStack[f].lineNumber && errorStack[f].fileName.isEmpty()) { + errorLineNumber = errorStack[f].lineNumber; + break; + } + } + } + if (errorLineNumber) + currentEditor()->gotoLine(errorLineNumber); + QMessageBox::critical(Core::ICore::instance()->mainWindow(), tr("Qt Script Error"), errorMessage); +} + +} // namespace Internal +} // namespace DuiEditor diff --git a/src/plugins/duieditor/duieditoractionhandler.h b/src/plugins/duieditor/duieditoractionhandler.h new file mode 100644 index 00000000000..13300515f87 --- /dev/null +++ b/src/plugins/duieditor/duieditoractionhandler.h @@ -0,0 +1,58 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#ifndef DUIDITORACTIONHANDLER_H +#define DUIDITORACTIONHANDLER_H + +#include <texteditor/texteditoractionhandler.h> + +namespace DuiEditor { +namespace Internal { + +class DuiEditorActionHandler : public TextEditor::TextEditorActionHandler +{ + Q_OBJECT + +public: + DuiEditorActionHandler(); + +private: + virtual void createActions(); + +private slots: + void run(); + +private: + QAction *m_runAction; +}; + +} // namespace Internal +} // namespace DuiEditor + +#endif // DUIDITORACTIONHANDLER_H diff --git a/src/plugins/duieditor/duieditorconstants.h b/src/plugins/duieditor/duieditorconstants.h new file mode 100644 index 00000000000..0c24f88854c --- /dev/null +++ b/src/plugins/duieditor/duieditorconstants.h @@ -0,0 +1,46 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#ifndef DUIEDITOR_CONSTANTS_H +#define DUIEDITOR_CONSTANTS_H + +namespace DuiEditor { +namespace Constants { + +const char * const M_CONTEXT = "DUI Editor.ContextMenu"; +const char * const RUN = "DuiEditor.Run"; +const char * const RUN_SEP = "DuiEditor.Run.Separator"; +const char * const C_DUIEDITOR = "DUI Editor"; + +const char * const C_DUIEDITOR_MIMETYPE = "application/x-dui"; + +} // namespace Constants +} // namespace DuiEditor + +#endif // DUIEDITOR_CONSTANTS_H diff --git a/src/plugins/duieditor/duieditorfactory.cpp b/src/plugins/duieditor/duieditorfactory.cpp new file mode 100644 index 00000000000..1cc4fac6d2c --- /dev/null +++ b/src/plugins/duieditor/duieditorfactory.cpp @@ -0,0 +1,83 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#include "duieditorfactory.h" +#include "duieditor.h" +#include "duieditoractionhandler.h" +#include "duieditorconstants.h" +#include "duieditorplugin.h" + +#include <coreplugin/editormanager/editormanager.h> + +#include <QtCore/QFileInfo> +#include <QtCore/QDebug> + +using namespace DuiEditor::Internal; +using namespace DuiEditor::Constants; + +DuiEditorFactory::DuiEditorFactory(const Context &context, QObject *parent) + : Core::IEditorFactory(parent), + m_kind(QLatin1String(C_DUIEDITOR)), + m_mimeTypes(QLatin1String(DuiEditor::Constants::C_DUIEDITOR_MIMETYPE)), + m_context(context), + m_actionHandler(new DuiEditorActionHandler) +{ +} + +DuiEditorFactory::~DuiEditorFactory() +{ + delete m_actionHandler; +} + +QString DuiEditorFactory::kind() const +{ + return m_kind; +} + +Core::IFile *DuiEditorFactory::open(const QString &fileName) +{ + Core::IEditor *iface = Core::EditorManager::instance()->openEditor(fileName, kind()); + if (!iface) { + qWarning() << "DuiEditorFactory::open: openEditor failed for " << fileName; + return 0; + } + return iface->file(); +} + +Core::IEditor *DuiEditorFactory::createEditor(QWidget *parent) +{ + ScriptEditor *rc = new ScriptEditor(m_context, parent); + DuiEditorPlugin::instance()->initializeEditor(rc); + return rc->editableInterface(); +} + +QStringList DuiEditorFactory::mimeTypes() const +{ + return m_mimeTypes; +} diff --git a/src/plugins/duieditor/duieditorfactory.h b/src/plugins/duieditor/duieditorfactory.h new file mode 100644 index 00000000000..e5e33d8e220 --- /dev/null +++ b/src/plugins/duieditor/duieditorfactory.h @@ -0,0 +1,73 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#ifndef RDUIEDITORFACTORY_H +#define RDUIEDITORFACTORY_H + +#include <coreplugin/editormanager/ieditorfactory.h> + +#include <QtCore/QStringList> + +namespace TextEditor { +class TextEditorActionHandler; +} + +namespace DuiEditor { +namespace Internal { + +class DuiEditorActionHandler; + +class DuiEditorFactory : public Core::IEditorFactory +{ + Q_OBJECT + +public: + typedef QList<int> Context; + + DuiEditorFactory(const Context &context, QObject *parent); + ~DuiEditorFactory(); + + virtual QStringList mimeTypes() const; + // IEditorFactory + QString kind() const; + Core::IFile *open(const QString &fileName); + Core::IEditor *createEditor(QWidget *parent); + +private: + const QString m_kind; + const QStringList m_mimeTypes; + const Context m_context; + + TextEditor::TextEditorActionHandler *m_actionHandler; +}; + +} // namespace Internal +} // namespace DuiEditor + +#endif // RDUIEDITORFACTORY_H diff --git a/src/plugins/duieditor/duieditorplugin.cpp b/src/plugins/duieditor/duieditorplugin.cpp new file mode 100644 index 00000000000..aa93f12b9e6 --- /dev/null +++ b/src/plugins/duieditor/duieditorplugin.cpp @@ -0,0 +1,163 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#include "duieditorplugin.h" + +#include "qscripthighlighter.h" +#include "duieditor.h" +#include "duieditorconstants.h" +#include "duieditorfactory.h" +#include "duicodecompletion.h" + +#include <coreplugin/icore.h> +#include <coreplugin/coreconstants.h> +#include <coreplugin/mimedatabase.h> +#include <coreplugin/uniqueidmanager.h> +#include <coreplugin/actionmanager/actionmanager.h> +#include <extensionsystem/pluginmanager.h> +#include <texteditor/fontsettings.h> +#include <texteditor/storagesettings.h> +#include <texteditor/texteditorconstants.h> +#include <texteditor/texteditorsettings.h> +#include <texteditor/textfilewizard.h> +#include <texteditor/texteditoractionhandler.h> +#include <texteditor/completionsupport.h> +#include <utils/qtcassert.h> + +#include <QtCore/QtPlugin> +#include <QtCore/QDebug> +#include <QtCore/QSettings> +#include <QtGui/QAction> + +using namespace DuiEditor::Internal; +using namespace DuiEditor::Constants; + +DuiEditorPlugin *DuiEditorPlugin::m_instance = 0; + +DuiEditorPlugin::DuiEditorPlugin() : + m_wizard(0), + m_editor(0), + m_actionHandler(0), + m_completion(0) +{ + m_instance = this; +} + +DuiEditorPlugin::~DuiEditorPlugin() +{ + removeObject(m_editor); + removeObject(m_wizard); + delete m_actionHandler; + m_instance = 0; +} + +bool DuiEditorPlugin::initialize(const QStringList & /*arguments*/, QString *error_message) +{ + typedef SharedTools::QScriptHighlighter QScriptHighlighter; + + Core::ICore *core = Core::ICore::instance(); + if (!core->mimeDatabase()->addMimeTypes(QLatin1String(":/duieditor/DuiEditor.mimetypes.xml"), error_message)) + return false; + m_scriptcontext << core->uniqueIDManager()->uniqueIdentifier(DuiEditor::Constants::C_DUIEDITOR); + m_context = m_scriptcontext; + m_context << core->uniqueIDManager()->uniqueIdentifier(TextEditor::Constants::C_TEXTEDITOR); + + registerActions(); + + m_editor = new DuiEditorFactory(m_context, this); + addObject(m_editor); + + Core::BaseFileWizardParameters wizardParameters(Core::IWizard::FileWizard); + wizardParameters.setDescription(tr("Qt Script file")); + wizardParameters.setName(tr("Qt Script file")); + wizardParameters.setCategory(QLatin1String("Qt")); + wizardParameters.setTrCategory(tr("Qt")); + m_wizard = new TextEditor::TextFileWizard(QLatin1String(DuiEditor::Constants::C_DUIEDITOR_MIMETYPE), + QLatin1String(DuiEditor::Constants::C_DUIEDITOR), + QLatin1String("dui$"), + wizardParameters, this); + addObject(m_wizard); + + m_actionHandler = new TextEditor::TextEditorActionHandler(DuiEditor::Constants::C_DUIEDITOR, + TextEditor::TextEditorActionHandler::Format + | TextEditor::TextEditorActionHandler::UnCommentSelection + | TextEditor::TextEditorActionHandler::UnCollapseAll); + + m_completion = new DuiCodeCompletion(); + addAutoReleasedObject(m_completion); + + // Restore settings + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup(QLatin1String("CppTools")); // ### FIXME: + settings->beginGroup(QLatin1String("Completion")); + const bool caseSensitive = settings->value(QLatin1String("CaseSensitive"), true).toBool(); + m_completion->setCaseSensitivity(caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); + settings->endGroup(); + settings->endGroup(); + + error_message->clear(); + + return true; +} + +void DuiEditorPlugin::extensionsInitialized() +{ + m_actionHandler->initializeActions(); +} + +void DuiEditorPlugin::initializeEditor(DuiEditor::Internal::ScriptEditor *editor) +{ + QTC_ASSERT(m_instance, /**/); + + m_actionHandler->setupActions(editor); + + TextEditor::TextEditorSettings::instance()->initializeEditor(editor); + + // auto completion + connect(editor, SIGNAL(requestAutoCompletion(ITextEditable*, bool)), + TextEditor::Internal::CompletionSupport::instance(), SLOT(autoComplete(ITextEditable*, bool))); +} + +void DuiEditorPlugin::registerActions() +{ + Core::ActionManager *am = Core::ICore::instance()->actionManager(); + Core::ActionContainer *mcontext = am->createMenu(DuiEditor::Constants::M_CONTEXT); + + QAction *action = new QAction(this); + action->setSeparator(true); + Core::Command *cmd = am->registerAction(action, DuiEditor::Constants::RUN_SEP, m_scriptcontext); + mcontext->addAction(cmd, Core::Constants::G_DEFAULT_THREE); + + action = new QAction(tr("Run"), this); + cmd = am->registerAction(action, DuiEditor::Constants::RUN, m_scriptcontext); + cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+R"))); + mcontext->addAction(cmd, Core::Constants::G_DEFAULT_THREE); +} + +Q_EXPORT_PLUGIN(DuiEditorPlugin) diff --git a/src/plugins/duieditor/duieditorplugin.h b/src/plugins/duieditor/duieditorplugin.h new file mode 100644 index 00000000000..5429a878eb4 --- /dev/null +++ b/src/plugins/duieditor/duieditorplugin.h @@ -0,0 +1,82 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#ifndef DUIEDITORPLUGIN_H +#define DUIEDITORPLUGIN_H + +#include <extensionsystem/iplugin.h> + +namespace TextEditor { +class TextFileWizard; +class TextEditorActionHandler; +} // namespace TextEditor + +namespace DuiEditor { +namespace Internal { + +class DuiEditorFactory; +class DuiCodeCompletion; +class ScriptEditor; + +class DuiEditorPlugin : public ExtensionSystem::IPlugin +{ + Q_OBJECT + +public: + DuiEditorPlugin(); + virtual ~DuiEditorPlugin(); + + // IPlugin + bool initialize(const QStringList &arguments, QString *errorMessage = 0); + void extensionsInitialized(); + + static DuiEditorPlugin *instance() + { return m_instance; } + + void initializeEditor(ScriptEditor *editor); + +private: + void registerActions(); + + static DuiEditorPlugin *m_instance; + + typedef QList<int> Context; + Context m_context; + Context m_scriptcontext; + + TextEditor::TextFileWizard *m_wizard; + DuiEditorFactory *m_editor; + TextEditor::TextEditorActionHandler *m_actionHandler; + DuiCodeCompletion *m_completion; +}; + +} // namespace Internal +} // namespace DuiEditor + +#endif // DUIEDITORPLUGIN_H diff --git a/src/plugins/duieditor/duihighlighter.cpp b/src/plugins/duieditor/duihighlighter.cpp new file mode 100644 index 00000000000..7c8d3ec5980 --- /dev/null +++ b/src/plugins/duieditor/duihighlighter.cpp @@ -0,0 +1,110 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#include "duihighlighter.h" + +#include <utils/qtcassert.h> + +namespace DuiEditor { +namespace Internal { + +DuiHighlighter::DuiHighlighter(QTextDocument *parent) : + SharedTools::QScriptHighlighter(parent) +{ + setDuiEnabled(true); + m_currentBlockParentheses.reserve(20); + m_braceDepth = 0; +} + +int DuiHighlighter::onBlockStart() +{ + m_currentBlockParentheses.clear(); + m_braceDepth = 0; + + int state = 0; + int previousState = previousBlockState(); + if (previousState != -1) { + state = previousState & 0xff; + m_braceDepth = previousState >> 8; + } + + return state; +} + +void DuiHighlighter::onOpeningParenthesis(QChar parenthesis, int pos) +{ + if (parenthesis == QLatin1Char('{')) + ++m_braceDepth; + m_currentBlockParentheses.push_back(Parenthesis(Parenthesis::Opened, parenthesis, pos)); +} + +void DuiHighlighter::onClosingParenthesis(QChar parenthesis, int pos) +{ + if (parenthesis == QLatin1Char('}')) + --m_braceDepth; + m_currentBlockParentheses.push_back(Parenthesis(Parenthesis::Closed, parenthesis, pos)); +} + +void DuiHighlighter::onBlockEnd(int state, int firstNonSpace) +{ + typedef TextEditor::TextBlockUserData TextEditorBlockData; + + setCurrentBlockState((m_braceDepth << 8) | state); + + // Set block data parentheses. Force creation of block data unless empty + TextEditorBlockData *blockData = 0; + + if (QTextBlockUserData *userData = currentBlockUserData()) + blockData = static_cast<TextEditorBlockData *>(userData); + + if (!blockData && !m_currentBlockParentheses.empty()) { + blockData = new TextEditorBlockData; + setCurrentBlockUserData(blockData); + } + if (blockData) { + blockData->setParentheses(m_currentBlockParentheses); + blockData->setClosingCollapseMode(TextEditor::TextBlockUserData::NoClosingCollapse); + blockData->setCollapseMode(TextEditor::TextBlockUserData::NoCollapse); + } + if (!m_currentBlockParentheses.isEmpty()) { + QTC_ASSERT(blockData, return); + int collapse = Parenthesis::collapseAtPos(m_currentBlockParentheses); + if (collapse >= 0) { + if (collapse == firstNonSpace) + blockData->setCollapseMode(TextEditor::TextBlockUserData::CollapseThis); + else + blockData->setCollapseMode(TextEditor::TextBlockUserData::CollapseAfter); + } + if (Parenthesis::hasClosingCollapse(m_currentBlockParentheses)) + blockData->setClosingCollapseMode(TextEditor::TextBlockUserData::NoClosingCollapse); + } +} + +} // namespace Internal +} // namespace DuiEditor diff --git a/src/plugins/duieditor/duihighlighter.h b/src/plugins/duieditor/duihighlighter.h new file mode 100644 index 00000000000..3994d36bd3b --- /dev/null +++ b/src/plugins/duieditor/duihighlighter.h @@ -0,0 +1,64 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#ifndef DUISYNTAXHIGHLIGHTER_H +#define DUISYNTAXHIGHLIGHTER_H + +#include "qscripthighlighter.h" +#include <texteditor/basetexteditor.h> + +namespace DuiEditor { +namespace Internal { + +// Highlighter for Scripts that stores +// the parentheses encountered in the block data +// for parentheses matching to work. + +class DuiHighlighter : public SharedTools::QScriptHighlighter +{ + Q_OBJECT +public: + DuiHighlighter(QTextDocument *parent = 0); + +private: + virtual int onBlockStart(); + virtual void onOpeningParenthesis(QChar parenthesis, int pos); + virtual void onClosingParenthesis(QChar parenthesis, int pos); + virtual void onBlockEnd(int state, int firstNonSpace); + + typedef TextEditor::Parenthesis Parenthesis; + typedef TextEditor::Parentheses Parentheses; + Parentheses m_currentBlockParentheses; + int m_braceDepth; +}; + +} // namespace Internal +} // namespace DuiEditor + +#endif // DUISYNTAXHIGHLIGHTER_H diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 3b06779d980..388a8c53bc7 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -24,6 +24,7 @@ SUBDIRS = plugin_coreplugin \ plugin_help \ # plugin_regexp \ # don't know what to do with this plugin_qtscripteditor \ + plugin_duieditor \ plugin_cpaster \ plugin_cmakeprojectmanager \ plugin_fakevim \ @@ -139,6 +140,10 @@ plugin_qtscripteditor.subdir = qtscripteditor plugin_qtscripteditor.depends = plugin_texteditor plugin_qtscripteditor.depends += plugin_coreplugin +plugin_duieditor.subdir = duieditor +plugin_duieditor.depends = plugin_texteditor +plugin_duieditor.depends += plugin_coreplugin + plugin_cpaster.subdir = cpaster plugin_cpaster.depends += plugin_texteditor plugin_cpaster.depends += plugin_coreplugin diff --git a/src/shared/qscripthighlighter/qscripthighlighter.cpp b/src/shared/qscripthighlighter/qscripthighlighter.cpp index 5b07644e01c..f56ccd6dcea 100644 --- a/src/shared/qscripthighlighter/qscripthighlighter.cpp +++ b/src/shared/qscripthighlighter/qscripthighlighter.cpp @@ -105,11 +105,18 @@ static const QSet<QString> &qscriptKeywords() { namespace SharedTools { QScriptHighlighter::QScriptHighlighter(QTextDocument *parent) - : QSyntaxHighlighter(parent) + : QSyntaxHighlighter(parent), + m_duiEnabled(false) { setFormats(defaultFormats()); } +bool QScriptHighlighter::isDuiEnabled() const +{ return m_duiEnabled; } + +void QScriptHighlighter::setDuiEnabled(bool enabled) +{ m_duiEnabled = enabled; } + void QScriptHighlighter::highlightBlock(const QString &text) { // states @@ -428,7 +435,7 @@ void QScriptHighlighter::highlightKeyword(int currentPos, const QString &buffer) if (buffer.isEmpty()) return; - if (buffer.at(0) == QLatin1Char('Q')) { + if (m_duiEnabled && buffer.at(0).isUpper() || (! m_duiEnabled && buffer.at(0) == QLatin1Char('Q'))) { setFormat(currentPos - buffer.length(), buffer.length(), m_formats[TypeFormat]); } else { if (qscriptKeywords().contains(buffer)) diff --git a/src/shared/qscripthighlighter/qscripthighlighter.h b/src/shared/qscripthighlighter/qscripthighlighter.h index 5b0f1587dea..51c4932d5df 100644 --- a/src/shared/qscripthighlighter/qscripthighlighter.h +++ b/src/shared/qscripthighlighter/qscripthighlighter.h @@ -46,6 +46,9 @@ public: KeywordFormat, PreProcessorFormat, LabelFormat, CommentFormat, NumFormats }; + bool isDuiEnabled() const; + void setDuiEnabled(bool enabled); + // MS VC 6 compatible, still. void setFormats(const QVector<QTextCharFormat> &s); static const QVector<QTextCharFormat> &defaultFormats(); @@ -61,6 +64,7 @@ private: void highlightKeyword(int currentPos, const QString &buffer); + bool m_duiEnabled; QTextCharFormat m_formats[NumFormats]; }; -- GitLab