Commits

zjes committed b4e7333

Add code navigation

  • Participants
  • Parent commits bb62b7f

Comments (0)

Files changed (15)

bin/python3/srv.zip

Binary file modified.

src/Editors/IEditor.h

     void closeEditor();
     void errorListChanged(QAbstractTableModel*);
     void editorModificationChanged(Editors::IEditor*,bool);
+    void jumpToFileOffset(const QString& file, int offset);
 public slots:
     virtual bool save() = 0;
     virtual bool load() = 0;

src/Editors/ITextEditor.h

     virtual void replaceAll(const QString& text, const QString& repl) = 0;
     virtual void startIncrementalFind() = 0;
     virtual void jumpToLine(int line) = 0;
+    virtual void jumpToOffset(int offset) = 0;
 
     virtual void setThemeName(const QString& name) = 0;
 };

src/EditorsManager/EditorsContainer.cpp

 #include "FindDialog.h"
 #include "HistoryNavigate.h"
 #include "Settings.h"
+#include "Editors/FileProperty.h"
 
 namespace EditorsManager {
 
 void EditorsContainer::openFileOffset(const QString& fileName, int offset)
 {
     if (!_openedEditors.contains(fileName)){
+        if (offset){
+            Editors::FileProperty prop(fileName);
+            prop.setCursorPos(offset);
+        }
         Editors::IEditor * edt = NULL;
         if (isTextFile(fileName)) {
             EditorType etype = typeByFileName(fileName);
         _stack.prepend(fileName);
         edt->load();
         connect(edt, SIGNAL(editorModificationChanged(Editors::IEditor*,bool)), SIGNAL(editorModificationChanged(Editors::IEditor*,bool)));
+        connect(edt, SIGNAL(jumpToFileOffset(QString,int)), this, SLOT(openFileOffset(QString,int)));
         _openedEditors[fileName] = edt;
         emit editorOpened(edt);
     }
     activateEditor(_openedEditors[fileName]);
+    if (offset){
+        Editors::ITextEditor* ed = qobject_cast<Editors::ITextEditor*>(_openedEditors[fileName]);
+        if (ed)
+            ed->jumpToOffset(offset);
+    }
 }
 
 EditorsContainer::EditorType EditorsContainer::typeByFileName(const QString& fileName)

src/PythonCode/IPythonCode.h

     virtual void codeComplit(const QString& fileName, const QString& cnt, int pos) = 0;
     virtual void errorList(const QString& fileName, const QString & content) = 0;
     virtual void close() = 0;
+    virtual void findDeclaration(const QString& fileName, const QString& cnt, int pos) = 0;
 signals:
     void systemError(const QString& logString);
     void errors(const QString& fileName, const QList<ErrorItem>& items);
     void complitition(const QString& fileName, int pos, const QString& word, const QList<Completition>& items);
+    void declaration(const QString& fileName, int offset, const QString& word, const QString& url, int wbegin, int wend);
 };
 
 }

src/PythonCode/PythonCode.cpp

     );
 }
 
+void PythonCode::findDeclaration(const QString& fileName, const QString& cnt, int pos)
+{
+    sendAsyncRequest(
+        createRequest(
+            "findDeclaration",
+            "Rope",
+            QVariantList() << fileName
+                << cnt
+                << pos
+        )
+    );
+}
+
+
 void PythonCode::onRunError(QProcess::ProcessError err)
 {
     qDebug() << err;
         parseAndEmitErrorList(items);
     if (name == "codeComplit")
         parseAndEmitCodeComplit(items);
+    if (name == "findDeclaration")
+        parseAndEmitDeclaration(items);
 }
 
 void PythonCode::parseAndEmitErrorList(const QDomNodeList& items)
     emit complitition(fileName, pos, word, clist);
 }
 
+void PythonCode::parseAndEmitDeclaration(const QDomNodeList& items)
+{
+    QString fileName = items.at(0).firstChild().toText().nodeValue();
+    QDomElement comp = items.at(1).childNodes().at(0).toElement();
+    int offset = comp.attribute("offset").toInt();
+    int wbegin = comp.attribute("wbegin").toInt();
+    int wend = comp.attribute("wend").toInt();
+    QString url = comp.firstChild().toText().nodeValue();
+
+    emit declaration(fileName, offset, "", url, wbegin, wend);
+}
+
 IPythonCode::CompletitionType PythonCode::getType(const QString & named)
 {
     if (named == "function")

src/PythonCode/PythonCode.h

     virtual void init(const QString& interpret, const QString& projectPath, const QString& mainScript, const QString& projectFile, const QStringList& extraPathes);
     virtual void codeComplit(const QString& fileName, const QString& cnt, int pos);
     virtual void errorList(const QString& fileName, const QString & content);
+    virtual void findDeclaration(const QString& fileName, const QString& cnt, int pos);
     virtual void close();
 private:
     void sendSyncRequest(const QString& req);
     void parseAndEmitSignal(const QString& name, const QDomNodeList& items);
     void parseAndEmitErrorList(const QDomNodeList& items);
     void parseAndEmitCodeComplit(const QDomNodeList& items);
+    void parseAndEmitDeclaration(const QDomNodeList& items);
     IPythonCode::CompletitionType getType(const QString & named);
 private slots:
     void onRunError(QProcess::ProcessError);

src/PythonEditor/PythonCompliter.cpp

     if (_python){
         connect(_python, SIGNAL(errors(QString,QList<ErrorItem>)), SLOT(onErrors(QString,QList<ErrorItem>)));
         connect(_python, SIGNAL(complitition(QString,int,QString,QList<Completition>)), SLOT(onComplit(QString,int,QString,QList<Completition>)));
+        connect(_python, SIGNAL(declaration(QString,int,QString,QString,int,int)), SLOT(onDeclaration(QString,int,QString,QString,int,int)));
     }
     if (reload && _python)
         checkErrors();
     return _list->popup()->isVisible();
 }
 
+void PythonCompliter::findDeclaration(int pos)
+{
+    if (_python)
+        _python->findDeclaration(_editor->fileName(), _editor->content(), pos);
+}
+
+void PythonCompliter::onDeclaration(const QString& fileName, int offset, const QString& word, const QString& url, int wbegin, int wend)
+{
+    if (fileName != _editor->fileName())
+        return;
+    _editor->declaration(wbegin, wend, offset, url);
+}
+
 }

src/PythonEditor/PythonCompliter.h

     void showComplit(int pos);
     void hide();
     bool isVisible();
+    void findDeclaration(int pos);
 public slots:
     void onErrors(const QString& fileName, const QList<ErrorItem>& items);
     void onComplit(const QString& fileName, int pos, const QString& word, const QList<Completition>& items);
+    void onDeclaration(const QString& fileName, int offset, const QString& word, const QString& url, int wbegin, int wend);
     void initPyCode();
     void checkErrors();
 private:

src/PythonEditor/PythonEditorWidget.cpp

     _updateErrorsTimer.start();
 }
 
+void PythonEditorWidget::mouseMoveEvent(QMouseEvent *e)
+{
+    if (e->modifiers() & Qt::ControlModifier){
+        QTextCursor cur = cursorForPosition(e->pos());
+        int pos = cur.position();
+        cur.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
+        cur.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+        if (cur.selectedText() != _codeDecl.wordHight){
+            _codeDecl.wordHight = cur.selectedText();
+            _compliter->findDeclaration(pos);
+        }
+    }
+    TextEditor::TextEditorWidget::mouseMoveEvent(e);
+}
+
+void PythonEditorWidget::declaration(int wordBegin, int wordEnd, int offset, const QString& url)
+{
+    viewport()->setCursor(Qt::IBeamCursor);
+    setExtraSelections(LinkKind, QList<QTextEdit::ExtraSelection>());
+    _codeDecl.file = "";
+    _codeDecl.offset = _codeDecl.wbegin = _codeDecl.wend = -1;
+    if (url.isEmpty())
+        return;
+
+    QTextCursor cur = textCursor();
+    cur.setPosition(wordBegin);
+    cur.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, wordEnd-wordBegin);
+
+    if (cur.selectedText() == _codeDecl.wordHight){
+        _codeDecl.file = url;
+        _codeDecl.offset = offset;
+        _codeDecl.wbegin = wordBegin;
+        _codeDecl.wend = wordEnd;
+        QList<QTextEdit::ExtraSelection> extra;
+        QTextEdit::ExtraSelection sel;
+        sel.format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
+        sel.cursor = cur;
+        extra.append(sel);
+        setExtraSelections(LinkKind, extra);
+
+        viewport()->setCursor(Qt::PointingHandCursor);
+    }
+}
+
+void PythonEditorWidget::keyReleaseEvent(QKeyEvent *e)
+{
+    if (e->key() == Qt::Key_Control){
+        setExtraSelections(LinkKind, QList<QTextEdit::ExtraSelection>());
+        viewport()->setCursor(Qt::IBeamCursor);
+    }
+    TextEditor::TextEditorWidget::keyReleaseEvent(e);
+}
+
+void PythonEditorWidget::mousePressEvent(QMouseEvent *e)
+{
+    QTextCursor cur = cursorForPosition(e->pos());
+    if (cur.position() >=  _codeDecl.wbegin && cur.position() <= _codeDecl.wend && (e->modifiers() & Qt::ControlModifier)){
+        emit jumpToFileOffset(_codeDecl.file, _codeDecl.offset);
+        e->isAccepted();
+        return;
+    }
+    TextEditor::TextEditorWidget::mousePressEvent(e);
+}
+
+void PythonEditorWidget::focusOutEvent(QFocusEvent *e)
+{
+    setExtraSelections(LinkKind, QList<QTextEdit::ExtraSelection>());
+    viewport()->setCursor(Qt::IBeamCursor);
+}
+
 }

src/PythonEditor/PythonEditorWidget.h

     virtual TextEditor::Highlighter* hightlighter();
     void setErrors(const QList<PythonCode::IPythonCode::ErrorItem>& items);
     QAbstractTableModel* errorListModel();
+    void declaration(int wordBegin, int wordEnd, int offset, const QString& url);
 public slots:
     virtual bool reset();
     virtual void checkIssues();
 protected:
     virtual void paintEvent(QPaintEvent *e);
     virtual void keyPressEvent(QKeyEvent *e);
+    virtual void keyReleaseEvent(QKeyEvent *e);
+    virtual void mouseMoveEvent(QMouseEvent *e);
+    virtual void mousePressEvent(QMouseEvent *e);
+    virtual void focusOutEvent(QFocusEvent *e);
 private slots:
     void onTextChanged();
 protected slots:
     bool _isSample;
     QTimer _updateErrorsTimer;
     QColor _identColor;
+    struct CodeDecl {
+        QString wordHight;
+        QString file;
+        int offset;
+        int wbegin;
+        int wend;
+    } _codeDecl;
 };
 
 }

src/TextEditor/TextEditorImpl.cpp

     connect(_widget, SIGNAL(undoAvailable(bool)), this, SIGNAL(undoAvailable(bool)));
     connect(_widget, SIGNAL(modificationChanged(bool)), this, SLOT(onModificationChanged(bool)));
     connect(_widget, SIGNAL(errorListChanged(QAbstractTableModel*)), this, SIGNAL(errorListChanged(QAbstractTableModel*)));
+    connect(_widget, SIGNAL(jumpToFileOffset(QString,int)), this, SIGNAL(jumpToFileOffset(QString,int)));
 }
 
 TextEditorImpl::~TextEditorImpl()
     _widget->jump(line);
 }
 
+void TextEditorImpl::jumpToOffset(int offset)
+{
+    _widget->jumpOffset(offset);
+}
+
 void TextEditorImpl::reset()
 {
     _widget->reset();

src/TextEditor/TextEditorImpl.h

     virtual void saveState();
     virtual QAbstractTableModel* errorListModel();
     virtual void jumpToLine(int line);
+    virtual void jumpToOffset(int offset);
 
     virtual void setThemeName(const QString& name);
 protected:

src/TextEditor/TextEditorWidget.cpp

     QList<QTextEdit::ExtraSelection> all;
     all += _extraSelections[LineExtraKind];
     all += _extraSelections[BracesExtraKind];
+    all += _extraSelections[LinkKind];
     QPlainTextEdit::setExtraSelections(all);
 }
 

src/TextEditor/TextEditorWidget.h

     void foldingChanged(const QList<FoldInfo>& folds);
     void pasteAvailable(bool);
     void errorListChanged(QAbstractTableModel*);
+    void jumpToFileOffset(const QString& file, int offset);
 private slots:
     void highlightCurrentLine();
     void onClipboardChanged();
     virtual void paintEvent(QPaintEvent *e);
     virtual bool event(QEvent *e);
 private:
-    enum ExtraKind {
-        BracesExtraKind,
-        LineExtraKind,
-        HiddenBlock
-    };
     void indentOrUnindent(bool doIndent);
     void handleHomeKey(bool anchor);
     bool isOpenBrace(const QChar& chr);
     int foundNextBrace(const QChar& chr);
     int foundPrevBrace(const QChar& chr);
     void showBracesMatches(int found, int off = 0);
-    void setExtraSelections(ExtraKind kind, const QList<QTextEdit::ExtraSelection>& sels);
 protected:
+    enum ExtraKind {
+        BracesExtraKind,
+        LineExtraKind,
+        HiddenBlock,
+        LinkKind
+    };
+    void setExtraSelections(ExtraKind kind, const QList<QTextEdit::ExtraSelection>& sels);
     Highlighter * _highlighter;
 private:
     TextEditorMargine *_margine;