RedPanda-CPP/RedPandaIDE/editor.h

411 lines
14 KiB
C
Raw Normal View History

2021-12-26 23:18:28 +08:00
/*
* Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
2021-04-06 23:10:57 +08:00
#ifndef EDITOR_H
#define EDITOR_H
#include <QObject>
#include <utils.h>
#include <QTabWidget>
2023-01-11 16:22:26 +08:00
#include "qsynedit/qsynedit.h"
#include "colorscheme.h"
2021-06-23 22:38:02 +08:00
#include "common.h"
2021-08-23 10:16:06 +08:00
#include "parser/cppparser.h"
2021-08-29 00:48:23 +08:00
#include "widgets/codecompletionpopup.h"
#include "widgets/headercompletionpopup.h"
2021-04-06 23:10:57 +08:00
2021-09-30 21:25:48 +08:00
#define USER_CODE_IN_INSERT_POS "%INSERT%"
#define USER_CODE_IN_REPL_POS_BEGIN "%REPL_BEGIN%"
#define USER_CODE_IN_REPL_POS_END "%REPL_END%"
class Project;
2021-09-30 21:25:48 +08:00
struct TabStop {
int x;
int endX;
int y;
};
using PTabStop = std::shared_ptr<TabStop>;
2021-04-11 21:33:08 +08:00
class SaveException: public std::exception {
public:
explicit SaveException(const QString& reason);
explicit SaveException(const QString&& reason);
// exception interface
const QString& reason() const noexcept;
public:
const char *what() const noexcept override;
private:
QString mReason;
QByteArray mReasonBuffer;
2021-04-11 21:33:08 +08:00
};
2023-01-11 16:22:26 +08:00
class Editor : public QSynedit::QSynEdit
2021-04-06 23:10:57 +08:00
{
Q_OBJECT
public:
2021-12-02 18:29:37 +08:00
enum class LastSymbolType {
Identifier,
2021-12-03 11:40:05 +08:00
ScopeResolutionOperator, //'::'
ObjectMemberOperator, //'.'
PointerMemberOperator, //'->'
PointerToMemberOfObjectOperator, //'.*'
PointerToMemberOfPointerOperator, //'->*'
2021-12-02 18:29:37 +08:00
MatchingBracket,
BracketMatched,
MatchingParenthesis,
ParenthesisMatched,
2021-12-03 11:40:05 +08:00
TildeSign, // '~'
AsteriskSign, // '*'
AmpersandSign, // '&'
MatchingAngleQuotation,
AngleQuotationMatched,
2021-12-02 18:29:37 +08:00
None
};
2021-04-29 20:54:44 +08:00
enum MarginNumber {
LineNumberMargin = 0,
MarkerMargin = 1,
FoldMargin = 2,
};
enum MarkerNumber {
BreakpointMarker,
ErrorMarker,
WarningMarker
};
2021-06-22 13:24:26 +08:00
enum class QuoteStatus {
NotQuote,
SingleQuote,
SingleQuoteEscape,
DoubleQuote,
DoubleQuoteEscape,
RawString,
RawStringNoEscape
};
2021-08-25 08:48:33 +08:00
enum class WordPurpose {
wpCompletion, // walk backwards over words, array, functions, parents, no forward movement
wpEvaluation, // walk backwards over words, array, functions, parents, forwards over words, array
wpHeaderCompletion, // walk backwards over path
wpHeaderCompletionStart, // walk backwards over path, including start '<' or '"'
wpDirective, // preprocessor
wpJavadoc, //javadoc
wpInformation // walk backwards over words, array, functions, parents, forwards over words
};
2021-08-29 17:23:40 +08:00
enum class TipType {
Preprocessor, // cursor hovers above preprocessor line
Identifier, // cursor hovers above identifier
Selection, // cursor hovers above selection
None, // mouseover not allowed
Error //Cursor hovers above error line/item;
};
2021-06-23 22:38:02 +08:00
struct SyntaxIssue {
int col;
int endCol;
int startChar;
int endChar;
CompileIssueType issueType;
QString token;
QString hint;
};
using PSyntaxIssue = std::shared_ptr<SyntaxIssue>;
using SyntaxIssueList = QVector<PSyntaxIssue>;
using PSyntaxIssueList = std::shared_ptr<SyntaxIssueList>;
explicit Editor(QWidget *parent);
2021-04-09 17:48:25 +08:00
explicit Editor(QWidget *parent, const QString& filename,
const QByteArray& encoding,
Project* pProject, bool isNew,QTabWidget* parentPageControl);
2021-04-06 23:10:57 +08:00
2021-04-07 22:44:08 +08:00
~Editor();
//tell the compiler to prohibit copy/moving editor objects ( we should only use pointers to the editor object)
Editor(const Editor&) = delete;
Editor(const Editor&&) = delete;
Editor& operator=(const Editor&) = delete;
Editor& operator=(const Editor&&) = delete;
2021-04-11 21:33:08 +08:00
const QByteArray& encodingOption() const noexcept;
void setEncodingOption(const QByteArray& encoding) noexcept;
const QByteArray& fileEncoding() const noexcept;
void convertToEncoding(const QByteArray& encoding);
2021-04-11 21:33:08 +08:00
const QString& filename() const noexcept;
2021-04-11 21:33:08 +08:00
bool inProject() const noexcept;
bool isNew() const noexcept;
2021-04-06 23:10:57 +08:00
void loadFile(QString filename = "");
void saveFile(QString filename);
2021-04-09 10:08:05 +08:00
bool save(bool force=false, bool reparse=true);
bool saveAs(const QString& name="", bool fromProject = false);
void activate();
2021-04-06 23:10:57 +08:00
2021-04-11 21:33:08 +08:00
QTabWidget* pageControl() noexcept;
void setPageControl(QTabWidget* newPageControl);
void updateCaption(const QString& newCaption=QString());
2021-06-07 11:02:03 +08:00
void applySettings();
void applyColorScheme(const QString& schemeName);
void copyToClipboard() override;
void cutToClipboard() override;
void copyAsHTML();
void setCaretPosition(int line,int aChar);
void setCaretPositionAndActivate(int line,int aChar);
2021-06-23 22:38:02 +08:00
void addSyntaxIssues(int line, int startChar, int endChar, CompileIssueType errorType, const QString& hint);
2021-06-23 22:38:02 +08:00
void clearSyntaxIssues();
void gotoNextSyntaxIssue();
void gotoPrevSyntaxIssue();
bool hasPrevSyntaxIssue() const;
bool hasNextSyntaxIssue() const;
PSyntaxIssueList getSyntaxIssuesAtLine(int line);
2022-09-25 09:55:18 +08:00
PSyntaxIssue getSyntaxIssueAtPosition(const QSynedit::BufferCoord& pos);
int gutterClickedLine() const;
void toggleBreakpoint(int line);
void clearBreakpoints();
bool hasBreakpoint(int line);
void addBookmark(int line);
2021-10-21 17:31:25 +08:00
void removeBookmark(int line);
bool hasBookmark(int line) const;
void clearBookmarks();
2021-07-26 00:22:08 +08:00
void removeBreakpointFocus();
void modifyBreakpointProperty(int line);
2021-07-26 18:22:09 +08:00
void setActiveBreakpointFocus(int Line, bool setFocus=true);
2022-09-25 09:55:18 +08:00
QString getPreviousWordAtPositionForSuggestion(const QSynedit::BufferCoord& p);
QString getPreviousWordAtPositionForCompleteFunctionDefinition(const QSynedit::BufferCoord& p);
void reformat(bool doReparse=true);
2021-09-02 12:14:02 +08:00
void checkSyntaxInBack();
2022-09-25 09:55:18 +08:00
void gotoDeclaration(const QSynedit::BufferCoord& pos);
void gotoDefinition(const QSynedit::BufferCoord& pos);
void reparse(bool resetParser);
2021-10-03 17:18:43 +08:00
void reparseTodo();
2021-09-16 23:51:05 +08:00
void insertString(const QString& value, bool moveCursor);
2021-09-30 21:25:48 +08:00
void insertCodeSnippet(const QString& code);
2021-10-07 07:52:20 +08:00
void print();
void exportAsRTF(const QString& rtfFilename);
void exportAsHTML(const QString& htmlFilename);
void resetBreakpoints();
2021-11-08 14:51:20 +08:00
bool notParsed();
void insertLine();
void deleteWord();
void deleteToWordStart();
void deleteToWordEnd();
void deleteLine();
void duplicateLine();
void deleteToEOL();
void deleteToBOL();
void gotoBlockStart();
void gotoBlockEnd();
2021-12-04 10:02:07 +08:00
QStringList getOwnerExpressionAndMemberAtPositionForCompletion(
2022-09-25 09:55:18 +08:00
const QSynedit::BufferCoord& pos,
2021-12-04 10:02:07 +08:00
QString& memberOperator,
QStringList& memberExpression);
2022-09-25 09:55:18 +08:00
QString getWordForCompletionSearch(const QSynedit::BufferCoord& pos,bool permitTilde);
QStringList getExpressionAtPosition(
2022-09-25 09:55:18 +08:00
const QSynedit::BufferCoord& pos);
void resetBookmarks();
2021-12-01 23:41:14 +08:00
const PCppParser &parser() const;
2021-08-23 17:27:17 +08:00
void tab() override;
signals:
void renamed(const QString& oldName, const QString& newName, bool firstSave);
2022-02-15 17:22:44 +08:00
void fileSaved(const QString& filename, bool inProject);
2021-09-02 12:14:02 +08:00
private slots:
2022-09-27 14:01:38 +08:00
void onStatusChanged(QSynedit::StatusChanges changes);
void onGutterClicked(Qt::MouseButton button, int x, int y, int line);
2021-08-29 22:08:43 +08:00
void onTipEvalValueReady(const QString& value);
2021-09-02 12:14:02 +08:00
void onLinesDeleted(int first,int count);
void onLinesInserted(int first,int count);
void onFunctionTipsTimer();
private:
bool isBraceChar(QChar ch);
bool shouldOpenInReadonly();
2021-06-22 23:00:34 +08:00
QChar getCurrentChar();
2021-06-22 13:24:26 +08:00
bool handleSymbolCompletion(QChar key);
2021-06-22 23:00:34 +08:00
bool handleParentheseCompletion();
bool handleParentheseSkip();
bool handleBracketCompletion();
bool handleBracketSkip();
bool handleMultilineCommentCompletion();
bool handleBraceCompletion();
bool handleBraceSkip();
bool handleSingleQuoteCompletion();
bool handleDoubleQuoteCompletion();
bool handleGlobalIncludeCompletion();
bool handleGlobalIncludeSkip();
2021-08-25 08:48:33 +08:00
2021-08-26 20:18:20 +08:00
bool handleCodeCompletion(QChar key);
2021-08-23 10:16:06 +08:00
void initParser();
void undoSymbolCompletion(int pos);
2021-06-22 13:24:26 +08:00
QuoteStatus getQuoteStatus();
void showCompletion(const QString& preWord, bool autoComplete, CodeCompletionType type);
void showHeaderCompletion(bool autoComplete, bool forceShow=false);
2021-08-25 08:48:33 +08:00
2021-08-26 11:58:29 +08:00
bool testInFunc(int x,int y);
2021-08-26 17:48:23 +08:00
void completionInsert(bool appendFunc=false);
void headerCompletionInsert();
2021-08-26 17:48:23 +08:00
bool onCompletionKeyPressed(QKeyEvent* event);
bool onHeaderCompletionKeyPressed(QKeyEvent* event);
bool onCompletionInputMethod(QInputMethodEvent *event);
2021-08-26 17:48:23 +08:00
2022-09-25 09:55:18 +08:00
TipType getTipType(QPoint point, QSynedit::BufferCoord& pos);
2021-08-29 17:23:40 +08:00
void cancelHint();
QString getFileHint(const QString& s, bool fromNext);
QString getParserHint(const QStringList& expression,const QString& s, int line);
2021-08-29 22:08:43 +08:00
void showDebugHint(const QString& s,int line);
QString getErrorHint(const PSyntaxIssue& issue);
2022-07-04 11:39:06 +08:00
QString getHintForFunction(const PStatement& statement,
2021-08-29 17:23:40 +08:00
const QString& filename, int line);
void updateFunctionTip(bool showTip);
2021-10-01 21:16:22 +08:00
void clearUserCodeInTabStops();
2021-10-02 10:05:48 +08:00
void popUserCodeInTabStops();
2022-12-10 21:23:49 +08:00
void onExportedFormatToken(QSynedit::PSyntaxer syntaxer, int Line, int column, const QString& token,
2022-12-10 20:45:13 +08:00
QSynedit::PTokenAttribute &attr);
void onScrollBarValueChanged();
2022-10-28 09:47:34 +08:00
static PCppParser sharedParser(ParserLanguage language);
2021-04-06 23:10:57 +08:00
private:
QByteArray mEncodingOption; // the encoding type set by the user
QByteArray mFileEncoding; // the real encoding of the file (auto detected)
2021-04-06 23:10:57 +08:00
QString mFilename;
QTabWidget* mParentPageControl;
Project* mProject;
2021-04-06 23:10:57 +08:00
bool mIsNew;
2021-06-23 22:38:02 +08:00
QMap<int,PSyntaxIssueList> mSyntaxIssues;
QColor mSyntaxErrorColor;
2021-07-26 00:22:08 +08:00
QColor mSyntaxWarningColor;
QColor mActiveBreakpointForegroundColor;
QColor mActiveBreakpointBackgroundColor;
QColor mBreakpointForegroundColor;
QColor mBreakpointBackgroundColor;
QColor mCurrentHighlighWordForeground;
QColor mCurrentHighlighWordBackground;
int mSyntaxErrorLine;
2021-06-24 20:43:09 +08:00
int mLineCount;
int mGutterClickedLine;
QSet<int> mBreakpointLines;
2021-10-21 17:31:25 +08:00
QSet<int> mBookmarkLines;
2021-07-26 00:22:08 +08:00
int mActiveBreakpointLine;
2021-08-23 10:16:06 +08:00
PCppParser mParser;
2021-08-29 00:48:23 +08:00
std::shared_ptr<CodeCompletionPopup> mCompletionPopup;
std::shared_ptr<HeaderCompletionPopup> mHeaderCompletionPopup;
2021-08-25 08:48:33 +08:00
int mLastIdCharPressed;
2021-08-25 23:53:35 +08:00
bool mUseCppSyntax;
2021-08-29 17:23:40 +08:00
QString mCurrentWord;
2021-08-29 22:08:43 +08:00
QString mCurrentDebugTipWord;
2021-08-29 17:23:40 +08:00
TipType mCurrentTipType;
QString mOldHighlightedWord;
QString mCurrentHighlightedWord;
QDateTime mHideTime;
2021-04-09 17:48:25 +08:00
bool mSaving;
bool mCurrentLineModified;
2021-09-30 21:25:48 +08:00
int mXOffsetSince;
int mTabStopBegin;
int mTabStopEnd;
int mTabStopY;
bool mCanAutoSave;
2021-09-30 21:25:48 +08:00
QString mLineBeforeTabStop;
QString mLineAfterTabStop;
QList<PTabStop> mUserCodeInTabStops;
2022-09-25 09:55:18 +08:00
QSynedit::BufferCoord mHighlightCharPos1;
QSynedit::BufferCoord mHighlightCharPos2;
std::shared_ptr<QHash<StatementKind, std::shared_ptr<ColorSchemeItem> > > mStatementColors;
QTimer mFunctionTipTimer;
int mHoverModifiedLine;
2021-09-30 21:25:48 +08:00
2022-10-28 09:47:34 +08:00
static QHash<ParserLanguage,std::weak_ptr<CppParser>> mSharedParsers;
2021-04-09 17:48:25 +08:00
// QWidget interface
protected:
void wheelEvent(QWheelEvent *event) override;
void focusInEvent(QFocusEvent *event) override;
void focusOutEvent(QFocusEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
// SynEdit interface
protected:
void onGutterPaint(QPainter &painter, int aLine, int X, int Y) override;
2022-09-27 14:01:38 +08:00
void onGetEditingAreas(int Line, QSynedit::EditingAreaList &areaList) override;
// SynEdit interface
protected:
bool onGetSpecialLineColors(int Line, QColor &foreground, QColor &backgroundColor) override;
2021-08-28 09:01:40 +08:00
// SynEdit interface
protected:
2022-12-10 20:45:13 +08:00
void onPreparePaintHighlightToken(int line, int aChar, const QString &token, QSynedit::PTokenAttribute attr, QSynedit::FontStyles &style, QColor &foreground, QColor &background) override;
2021-08-29 17:23:40 +08:00
// QObject interface
public:
bool event(QEvent *event) override;
// QWidget interface
void setProject(Project* pProject);
2021-09-10 12:37:02 +08:00
bool useCppSyntax() const;
void setUseCppSyntax(bool newUseCppSyntax);
const std::shared_ptr<QHash<StatementKind, std::shared_ptr<ColorSchemeItem> > > &statementColors() const;
void setStatementColors(const std::shared_ptr<QHash<StatementKind, std::shared_ptr<ColorSchemeItem> > > &newStatementColors);
const QDateTime &hideTime() const;
void setHideTime(const QDateTime &newHideTime);
bool canAutoSave() const;
void setCanAutoSave(bool newCanAutoSave);
protected:
void mouseReleaseEvent(QMouseEvent *event) override;
void inputMethodEvent(QInputMethodEvent *) override;
2021-10-04 22:32:34 +08:00
void closeEvent(QCloseEvent *event) override;
// QWidget interface
protected:
void showEvent(QShowEvent *event) override;
void hideEvent(QHideEvent *event) override;
// QWidget interface
protected:
void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;
2021-04-06 23:10:57 +08:00
};
2023-01-11 16:22:26 +08:00
QString getWordAtPosition(QSynedit::QSynEdit* editor,
2022-09-25 09:55:18 +08:00
const QSynedit::BufferCoord& p,
QSynedit::BufferCoord& pWordBegin,
QSynedit::BufferCoord& pWordEnd,
Editor::WordPurpose purpose);
2021-04-06 23:10:57 +08:00
#endif // EDITOR_H