-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add a split view for code document
The right view shows the TreeSitter tree, like in the inspector view. Related-to KDAB#62
- Loading branch information
Showing
7 changed files
with
206 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
/* | ||
This file is part of Knut. | ||
SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> | ||
SPDX-License-Identifier: GPL-3.0-only | ||
Contact KDAB at <info@kdab.com> for commercial licensing options. | ||
*/ | ||
|
||
#include "codeview.h" | ||
#include "core/logger.h" | ||
#include "core/textdocument.h" | ||
#include "guisettings.h" | ||
#include "treesitter/languages.h" | ||
#include "treesitter/predicates.h" | ||
#include "treesittertreemodel.h" | ||
|
||
#include <QCheckBox> | ||
#include <QPlainTextEdit> | ||
#include <QSplitter> | ||
#include <QTreeView> | ||
#include <QVBoxLayout> | ||
|
||
namespace Gui { | ||
|
||
CodeView::CodeView(QWidget *parent) | ||
: TextView(parent) | ||
, m_parser(nullptr) | ||
{ | ||
auto *action = new QAction(tr("Show TreeSitter Explorer")); | ||
action->setCheckable(true); | ||
action->setChecked(false); | ||
GuiSettings::setIcon(action, ":/gui/file-tree.png"); | ||
connect(action, &QAction::triggered, this, &CodeView::toggleTreeView); | ||
addAction(action); | ||
} | ||
|
||
void CodeView::setDocument(Core::TextDocument *document) | ||
{ | ||
TextView::setDocument(document); | ||
|
||
m_treeView = new QTreeView(this); | ||
m_showUnnamed = new QCheckBox(tr("Show unnamed nodes"), this); | ||
|
||
auto *splitter = new QSplitter(Qt::Horizontal, this); | ||
splitter->addWidget(document->textEdit()); | ||
splitter->setCollapsible(0, false); | ||
|
||
QWidget *rightWidget = new QWidget; | ||
QVBoxLayout *vbox = new QVBoxLayout(rightWidget); | ||
vbox->setContentsMargins({}); | ||
vbox->addWidget(m_treeView); | ||
vbox->addWidget(m_showUnnamed); | ||
splitter->addWidget(rightWidget); | ||
|
||
layout()->addWidget(splitter); | ||
|
||
// By default, the treesitter view is not visible | ||
rightWidget->setVisible(false); | ||
} | ||
|
||
void CodeView::toggleTreeView() | ||
{ | ||
Q_ASSERT(m_treeView && document()); | ||
initializeCodeModel(); | ||
m_treeView->parentWidget()->setVisible(!m_treeView->isVisible()); | ||
} | ||
|
||
void CodeView::toggleUnnamedNodes() | ||
{ | ||
// technically the text didn't change, but this will force | ||
// a complete re-parse and re-build of the entire tree. | ||
changeText(); | ||
} | ||
|
||
void CodeView::initializeCodeModel() | ||
{ | ||
if (m_treemodel) | ||
return; | ||
|
||
m_treemodel = new TreeSitterTreeModel(this); | ||
m_treeView->setModel(m_treemodel); | ||
m_parser = treesitter::Parser::getLanguage(document()->type()); | ||
connect(document(), &Core::TextDocument::textChanged, this, &CodeView::changeText); | ||
connect(document(), &Core::TextDocument::positionChanged, this, &CodeView::changeCursor); | ||
connect(m_treeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &CodeView::changeTreeSelection); | ||
connect(m_showUnnamed, &QCheckBox::toggled, this, &CodeView::toggleUnnamedNodes); | ||
|
||
changeCursor(); | ||
changeText(); | ||
} | ||
|
||
void CodeView::changeText() | ||
{ | ||
QString text; | ||
{ | ||
Core::LoggerDisabler disableLogging; | ||
text = document()->text(); | ||
} | ||
auto tree = m_parser.parseString(text); | ||
if (tree.has_value()) { | ||
m_treemodel->setTree(std::move(tree.value()), makePredicates(), m_showUnnamed->isChecked()); | ||
m_treeView->expandAll(); | ||
for (int i = 0; i < 2; i++) { | ||
m_treeView->resizeColumnToContents(i); | ||
} | ||
} | ||
} | ||
|
||
void CodeView::changeCursor() | ||
{ | ||
int position; | ||
{ | ||
Core::LoggerDisabler disableLogging; | ||
position = document()->position(); | ||
} | ||
m_treemodel->setCursorPosition(position); | ||
} | ||
|
||
void CodeView::changeTreeSelection(const QModelIndex ¤t) | ||
{ | ||
const auto node = m_treemodel->tsNode(current); | ||
if (node.has_value()) { | ||
Core::LoggerDisabler disableLogging; | ||
document()->selectRegion(node->startPosition(), node->endPosition()); | ||
} | ||
} | ||
|
||
std::unique_ptr<treesitter::Predicates> CodeView::makePredicates() | ||
{ | ||
Q_ASSERT(document()); | ||
// No need to always log the call to TextDocument::text | ||
Core::LoggerDisabler disabler; | ||
return std::make_unique<treesitter::Predicates>(document()->text()); | ||
} | ||
|
||
} // namespace Gui |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* | ||
This file is part of Knut. | ||
SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> | ||
SPDX-License-Identifier: GPL-3.0-only | ||
Contact KDAB at <info@kdab.com> for commercial licensing options. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include "textview.h" | ||
#include "treesitter/parser.h" | ||
|
||
class QTreeView; | ||
class QCheckBox; | ||
|
||
namespace treesitter { | ||
class Predicates; | ||
} | ||
|
||
namespace Gui { | ||
|
||
class TreeSitterTreeModel; | ||
|
||
class CodeView : public TextView | ||
{ | ||
Q_OBJECT | ||
|
||
public: | ||
explicit CodeView(QWidget *parent = nullptr); | ||
|
||
void setDocument(Core::TextDocument *document) override; | ||
|
||
private: | ||
void toggleTreeView(); | ||
void toggleUnnamedNodes(); | ||
|
||
void initializeCodeModel(); | ||
void changeText(); | ||
void changeCursor(); | ||
void changeTreeSelection(const QModelIndex ¤t); | ||
std::unique_ptr<treesitter::Predicates> makePredicates(); | ||
|
||
QTreeView *m_treeView = nullptr; | ||
QCheckBox *m_showUnnamed = nullptr; | ||
treesitter::Parser m_parser; | ||
TreeSitterTreeModel *m_treemodel = nullptr; | ||
}; | ||
|
||
} // namespace Gui |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters