diff options
Diffstat (limited to 'src/libs/3rdparty/syntax-highlighting/examples/codeeditor.cpp')
-rw-r--r-- | src/libs/3rdparty/syntax-highlighting/examples/codeeditor.cpp | 358 |
1 files changed, 0 insertions, 358 deletions
diff --git a/src/libs/3rdparty/syntax-highlighting/examples/codeeditor.cpp b/src/libs/3rdparty/syntax-highlighting/examples/codeeditor.cpp deleted file mode 100644 index 88f315462d..0000000000 --- a/src/libs/3rdparty/syntax-highlighting/examples/codeeditor.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/* - Copyright (C) 2016 Volker Krause <vkrause@kde.org> - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "codeeditor.h" - -#include <definition.h> -#include <foldingregion.h> -#include <syntaxhighlighter.h> -#include <theme.h> - -#include <QApplication> -#include <QDebug> -#include <QFile> -#include <QFileDialog> -#include <QFontDatabase> -#include <QMenu> -#include <QPainter> -#include <QPalette> - -class CodeEditorSidebar : public QWidget -{ - Q_OBJECT -public: - explicit CodeEditorSidebar(CodeEditor *editor); - QSize sizeHint() const Q_DECL_OVERRIDE; - -protected: - void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; - void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; - -private: - CodeEditor *m_codeEditor; -}; - -CodeEditorSidebar::CodeEditorSidebar(CodeEditor *editor) : - QWidget(editor), - m_codeEditor(editor) -{ -} - -QSize CodeEditorSidebar::sizeHint() const -{ - return QSize(m_codeEditor->sidebarWidth(), 0); -} - -void CodeEditorSidebar::paintEvent(QPaintEvent *event) -{ - m_codeEditor->sidebarPaintEvent(event); -} - -void CodeEditorSidebar::mouseReleaseEvent(QMouseEvent *event) -{ - if (event->x() >= width() - m_codeEditor->fontMetrics().lineSpacing()) { - auto block = m_codeEditor->blockAtPosition(event->y()); - if (!block.isValid() || !m_codeEditor->isFoldable(block)) - return; - m_codeEditor->toggleFold(block); - } - QWidget::mouseReleaseEvent(event); -} - - -CodeEditor::CodeEditor(QWidget *parent) : - QPlainTextEdit(parent), - m_highlighter(new KSyntaxHighlighting::SyntaxHighlighter(document())), - m_sideBar(new CodeEditorSidebar(this)) -{ - setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); - - setTheme((palette().color(QPalette::Base).lightness() < 128) - ? m_repository.defaultTheme(KSyntaxHighlighting::Repository::DarkTheme) - : m_repository.defaultTheme(KSyntaxHighlighting::Repository::LightTheme)); - - connect(this, &QPlainTextEdit::blockCountChanged, this, &CodeEditor::updateSidebarGeometry); - connect(this, &QPlainTextEdit::updateRequest, this, &CodeEditor::updateSidebarArea); - connect(this, &QPlainTextEdit::cursorPositionChanged, this, &CodeEditor::highlightCurrentLine); - - updateSidebarGeometry(); - highlightCurrentLine(); -} - -CodeEditor::~CodeEditor() -{ -} - -void CodeEditor::openFile(const QString& fileName) -{ - QFile f(fileName); - if (!f.open(QFile::ReadOnly)) { - qWarning() << "Failed to open" << fileName << ":" << f.errorString(); - return; - } - - clear(); - - const auto def = m_repository.definitionForFileName(fileName); - m_highlighter->setDefinition(def); - - setWindowTitle(fileName); - setPlainText(QString::fromUtf8(f.readAll())); -} - -void CodeEditor::contextMenuEvent(QContextMenuEvent *event) -{ - auto menu = createStandardContextMenu(event->pos()); - menu->addSeparator(); - auto openAction = menu->addAction(QStringLiteral("Open File...")); - connect(openAction, &QAction::triggered, this, [this]() { - const auto fileName = QFileDialog::getOpenFileName(this, QStringLiteral("Open File")); - if (!fileName.isEmpty()) - openFile(fileName); - }); - - // syntax selection - auto hlActionGroup = new QActionGroup(menu); - hlActionGroup->setExclusive(true); - auto hlGroupMenu = menu->addMenu(QStringLiteral("Syntax")); - QMenu *hlSubMenu = hlGroupMenu; - QString currentGroup; - foreach (const auto &def, m_repository.definitions()) { - if (def.isHidden()) - continue; - if (currentGroup != def.section()) { - currentGroup = def.section(); - hlSubMenu = hlGroupMenu->addMenu(def.translatedSection()); - } - - Q_ASSERT(hlSubMenu); - auto action = hlSubMenu->addAction(def.translatedName()); - action->setCheckable(true); - action->setData(def.name()); - hlActionGroup->addAction(action); - if (def.name() == m_highlighter->definition().name()) - action->setChecked(true); - } - connect(hlActionGroup, &QActionGroup::triggered, this, [this](QAction *action) { - const auto defName = action->data().toString(); - const auto def = m_repository.definitionForName(defName); - m_highlighter->setDefinition(def); - }); - - // theme selection - auto themeGroup = new QActionGroup(menu); - themeGroup->setExclusive(true); - auto themeMenu = menu->addMenu(QStringLiteral("Theme")); - foreach (const auto &theme, m_repository.themes()) { - auto action = themeMenu->addAction(theme.translatedName()); - action->setCheckable(true); - action->setData(theme.name()); - themeGroup->addAction(action); - if (theme.name() == m_highlighter->theme().name()) - action->setChecked(true); - } - connect(themeGroup, &QActionGroup::triggered, this, [this](QAction *action) { - const auto themeName = action->data().toString(); - const auto theme = m_repository.theme(themeName); - setTheme(theme); - }); - - menu->exec(event->globalPos()); - delete menu; -} - -void CodeEditor::resizeEvent(QResizeEvent *event) -{ - QPlainTextEdit::resizeEvent(event); - updateSidebarGeometry(); -} - -void CodeEditor::setTheme(const KSyntaxHighlighting::Theme &theme) -{ - auto pal = qApp->palette(); - if (theme.isValid()) { - pal.setColor(QPalette::Base, theme.editorColor(KSyntaxHighlighting::Theme::BackgroundColor)); - pal.setColor(QPalette::Text, theme.textColor(KSyntaxHighlighting::Theme::Normal)); - pal.setColor(QPalette::Highlight, theme.editorColor(KSyntaxHighlighting::Theme::TextSelection)); - } - setPalette(pal); - - m_highlighter->setTheme(theme); - m_highlighter->rehighlight(); - highlightCurrentLine(); -} - -int CodeEditor::sidebarWidth() const -{ - int digits = 1; - auto count = blockCount(); - while (count >= 10) { - ++digits; - count /= 10; - } - return 4 + fontMetrics().width(QLatin1Char('9')) * digits + fontMetrics().lineSpacing(); -} - -void CodeEditor::sidebarPaintEvent(QPaintEvent *event) -{ - QPainter painter(m_sideBar); - painter.fillRect(event->rect(), m_highlighter->theme().editorColor(KSyntaxHighlighting::Theme::IconBorder)); - - auto block = firstVisibleBlock(); - auto blockNumber = block.blockNumber(); - int top = blockBoundingGeometry(block).translated(contentOffset()).top(); - int bottom = top + blockBoundingRect(block).height(); - const int currentBlockNumber = textCursor().blockNumber(); - - const auto foldingMarkerSize = fontMetrics().lineSpacing(); - - while (block.isValid() && top <= event->rect().bottom()) { - if (block.isVisible() && bottom >= event->rect().top()) { - const auto number = QString::number(blockNumber + 1); - painter.setPen(m_highlighter->theme().editorColor( - (blockNumber == currentBlockNumber) ? KSyntaxHighlighting::Theme::CurrentLineNumber - : KSyntaxHighlighting::Theme::LineNumbers)); - painter.drawText(0, top, m_sideBar->width() - 2 - foldingMarkerSize, fontMetrics().height(), Qt::AlignRight, number); - } - - // folding marker - if (block.isVisible() && isFoldable(block)) { - QPolygonF polygon; - if (isFolded(block)) { - polygon << QPointF(foldingMarkerSize * 0.4, foldingMarkerSize * 0.25); - polygon << QPointF(foldingMarkerSize * 0.4, foldingMarkerSize * 0.75); - polygon << QPointF(foldingMarkerSize * 0.8, foldingMarkerSize * 0.5); - } else { - polygon << QPointF(foldingMarkerSize * 0.25, foldingMarkerSize * 0.4); - polygon << QPointF(foldingMarkerSize * 0.75, foldingMarkerSize * 0.4); - polygon << QPointF(foldingMarkerSize * 0.5, foldingMarkerSize * 0.8); - } - painter.save(); - painter.setRenderHint(QPainter::Antialiasing); - painter.setPen(Qt::NoPen); - painter.setBrush(QColor(m_highlighter->theme().editorColor(KSyntaxHighlighting::Theme::CodeFolding))); - painter.translate(m_sideBar->width() - foldingMarkerSize, top); - painter.drawPolygon(polygon); - painter.restore(); - } - - block = block.next(); - top = bottom; - bottom = top + blockBoundingRect(block).height(); - ++blockNumber; - } -} - -void CodeEditor::updateSidebarGeometry() -{ - setViewportMargins(sidebarWidth(), 0, 0, 0); - const auto r = contentsRect(); - m_sideBar->setGeometry(QRect(r.left(), r.top(), sidebarWidth(), r.height())); -} - -void CodeEditor::updateSidebarArea(const QRect& rect, int dy) -{ - if (dy) - m_sideBar->scroll(0, dy); - else - m_sideBar->update(0, rect.y(), m_sideBar->width(), rect.height()); -} - -void CodeEditor::highlightCurrentLine() -{ - QTextEdit::ExtraSelection selection; - selection.format.setBackground(QColor(m_highlighter->theme().editorColor(KSyntaxHighlighting::Theme::CurrentLine))); - selection.format.setProperty(QTextFormat::FullWidthSelection, true); - selection.cursor = textCursor(); - selection.cursor.clearSelection(); - - QList<QTextEdit::ExtraSelection> extraSelections; - extraSelections.append(selection); - setExtraSelections(extraSelections); -} - -QTextBlock CodeEditor::blockAtPosition(int y) const -{ - auto block = firstVisibleBlock(); - if (!block.isValid()) - return QTextBlock(); - - int top = blockBoundingGeometry(block).translated(contentOffset()).top(); - int bottom = top + blockBoundingRect(block).height(); - do { - if (top <= y && y <= bottom) - return block; - block = block.next(); - top = bottom; - bottom = top + blockBoundingRect(block).height(); - } while (block.isValid()); - return QTextBlock(); -} - -bool CodeEditor::isFoldable(const QTextBlock &block) const -{ - return m_highlighter->startsFoldingRegion(block); -} - -bool CodeEditor::isFolded(const QTextBlock &block) const -{ - if (!block.isValid()) - return false; - const auto nextBlock = block.next(); - if (!nextBlock.isValid()) - return false; - return !nextBlock.isVisible(); -} - -void CodeEditor::toggleFold(const QTextBlock &startBlock) -{ - // we also want to fold the last line of the region, therefore the ".next()" - const auto endBlock = m_highlighter->findFoldingRegionEnd(startBlock).next(); - - if (isFolded(startBlock)) { - // unfold - auto block = startBlock.next(); - while (block.isValid() && !block.isVisible()) { - block.setVisible(true); - block.setLineCount(block.layout()->lineCount()); - block = block.next(); - } - - } else { - // fold - auto block = startBlock.next(); - while (block.isValid() && block != endBlock) { - block.setVisible(false); - block.setLineCount(0); - block = block.next(); - } - } - - // redraw document - document()->markContentsDirty(startBlock.position(), endBlock.position() - startBlock.position() + 1); - - // update scrollbars - emit document()->documentLayout()->documentSizeChanged(document()->documentLayout()->documentSize()); -} - -#include "codeeditor.moc" |