aboutsummaryrefslogtreecommitdiffstats
path: root/examples/quick
diff options
context:
space:
mode:
authorMohammadHossein Qanbari <[email protected]>2024-08-23 17:12:51 +0200
committerMohammadHossein Qanbari <[email protected]>2024-09-02 22:46:58 +0200
commit8330154be6401569450b97512b6718b0f31d6eaf (patch)
treefc7736297b321a2592dcaf59f7e7e1edc7cbe8fe /examples/quick
parent2f9e1e55766af3123189ccddbfa63139ecf53fec (diff)
QML Previewer Example: Add Error List and Line Numbers
Implement LineNumberArea to display line numbers, based on the Code Editor Example documentation. Introduce QListView with ErrorListModel to show errors and warnings. Double-clicking an error in the list moves the code editor's cursor to the corresponding position. Update shortcut functionality to work only on platforms where the feature is available. Related code has been modified accordingly. Fixes: QTBUG-128227 Pick-to: 6.8 Change-Id: Icb66280a5360b015280afc756f8a827247a2ebaf Reviewed-by: Jan Arve Sæther <[email protected]>
Diffstat (limited to 'examples/quick')
-rw-r--r--examples/quick/quickwidgets/qmlpreviewer/CMakeLists.txt10
-rw-r--r--examples/quick/quickwidgets/qmlpreviewer/models/errorlistmodel.cpp46
-rw-r--r--examples/quick/quickwidgets/qmlpreviewer/models/errorlistmodel.h37
-rw-r--r--examples/quick/quickwidgets/qmlpreviewer/utility/syntaxhighlighter.cpp2
-rw-r--r--examples/quick/quickwidgets/qmlpreviewer/widgets/codeeditor.cpp105
-rw-r--r--examples/quick/quickwidgets/qmlpreviewer/widgets/codeeditor.h34
-rw-r--r--examples/quick/quickwidgets/qmlpreviewer/widgets/editorwidget.cpp18
-rw-r--r--examples/quick/quickwidgets/qmlpreviewer/widgets/editorwidget.h1
-rw-r--r--examples/quick/quickwidgets/qmlpreviewer/widgets/linenumberarea.cpp20
-rw-r--r--examples/quick/quickwidgets/qmlpreviewer/widgets/linenumberarea.h27
-rw-r--r--examples/quick/quickwidgets/qmlpreviewer/widgets/mainwindow.cpp55
-rw-r--r--examples/quick/quickwidgets/qmlpreviewer/widgets/mainwindow.h5
-rw-r--r--examples/quick/quickwidgets/qmlpreviewer/widgets/previewwidget.cpp94
-rw-r--r--examples/quick/quickwidgets/qmlpreviewer/widgets/previewwidget.h39
14 files changed, 453 insertions, 40 deletions
diff --git a/examples/quick/quickwidgets/qmlpreviewer/CMakeLists.txt b/examples/quick/quickwidgets/qmlpreviewer/CMakeLists.txt
index 5361679456..f196019de6 100644
--- a/examples/quick/quickwidgets/qmlpreviewer/CMakeLists.txt
+++ b/examples/quick/quickwidgets/qmlpreviewer/CMakeLists.txt
@@ -12,11 +12,15 @@ qt_standard_project_setup(REQUIRES 6.8)
qt_add_executable(${PROJECT_NAME} WIN32 MACOSX_BUNDLE
main.cpp
- widgets/mainwindow.h widgets/mainwindow.cpp
- widgets/editorwidget.h widgets/editorwidget.cpp
- widgets/patheditwidget.h widgets/patheditwidget.cpp
+ models/errorlistmodel.h models/errorlistmodel.cpp
states/statecontroller.h states/statecontroller.cpp
utility/syntaxhighlighter.h utility/syntaxhighlighter.cpp
+ widgets/codeeditor.h widgets/codeeditor.cpp
+ widgets/editorwidget.h widgets/editorwidget.cpp
+ widgets/linenumberarea.h widgets/linenumberarea.cpp
+ widgets/mainwindow.h widgets/mainwindow.cpp
+ widgets/patheditwidget.h widgets/patheditwidget.cpp
+ widgets/previewwidget.h widgets/previewwidget.cpp
)
include(resources.cmake)
diff --git a/examples/quick/quickwidgets/qmlpreviewer/models/errorlistmodel.cpp b/examples/quick/quickwidgets/qmlpreviewer/models/errorlistmodel.cpp
new file mode 100644
index 0000000000..59b65585ce
--- /dev/null
+++ b/examples/quick/quickwidgets/qmlpreviewer/models/errorlistmodel.cpp
@@ -0,0 +1,46 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "errorlistmodel.h"
+
+#include <QQmlError>
+
+ErrorListModel::ErrorListModel(QObject *parent)
+ : QAbstractListModel{parent}
+{}
+
+bool ErrorListModel::isIndexValid(const QModelIndex &index) const
+{
+ return index.isValid() && (0 <= index.row()) && (index.row() < rowCount());
+}
+
+void ErrorListModel::setErrorList(const QList<QQmlError> &errorList)
+{
+ beginResetModel();
+ m_errorList = errorList;
+ endResetModel();
+}
+
+void ErrorListModel::selectIndex(const QModelIndex &index)
+{
+ if (!isIndexValid(index))
+ return;
+ const QQmlError &error = m_errorList.at(index.row());
+ emit errorPositionSelected(error.line(), error.column());
+}
+
+int ErrorListModel::rowCount(const QModelIndex &parent) const
+{
+ return m_errorList.size();
+}
+
+QVariant ErrorListModel::data(const QModelIndex &index, int role) const
+{
+ if ((role != Qt::DisplayRole) && (role != Qt::EditRole))
+ return QVariant{};
+
+ if (!isIndexValid(index))
+ return QVariant{};
+
+ return m_errorList.at(index.row()).toString();
+}
diff --git a/examples/quick/quickwidgets/qmlpreviewer/models/errorlistmodel.h b/examples/quick/quickwidgets/qmlpreviewer/models/errorlistmodel.h
new file mode 100644
index 0000000000..b2970d5e96
--- /dev/null
+++ b/examples/quick/quickwidgets/qmlpreviewer/models/errorlistmodel.h
@@ -0,0 +1,37 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef ERRORLISTMODEL_H
+#define ERRORLISTMODEL_H
+
+#include <QAbstractListModel>
+
+class QQmlError;
+
+class ErrorListModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ explicit ErrorListModel(QObject *parent = nullptr);
+
+ void setErrorList(const QList<QQmlError> &errorList);
+
+private:
+ bool isIndexValid(const QModelIndex &index) const;
+
+ // QAbstractItemModel interface
+ int rowCount(const QModelIndex &parent = QModelIndex{}) const final;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const final;
+
+signals:
+ void errorPositionSelected(int line, int column);
+
+public slots:
+ void selectIndex(const QModelIndex &index);
+
+private:
+ QList<QQmlError> m_errorList;
+};
+
+#endif // ERRORLISTMODEL_H
diff --git a/examples/quick/quickwidgets/qmlpreviewer/utility/syntaxhighlighter.cpp b/examples/quick/quickwidgets/qmlpreviewer/utility/syntaxhighlighter.cpp
index 190a6c5889..248bf3f8be 100644
--- a/examples/quick/quickwidgets/qmlpreviewer/utility/syntaxhighlighter.cpp
+++ b/examples/quick/quickwidgets/qmlpreviewer/utility/syntaxhighlighter.cpp
@@ -15,7 +15,7 @@ void SyntaxHighlighter::highlightBlock(const QString &text)
setFormat(0, text.length(), QColor{214, 207 , 154});
// import keyword
- QRegularExpression regex{"^\\bimport\\b"};
+ QRegularExpression regex{"^\\bimport\\b||^\\s*property\\b"};
QRegularExpressionMatchIterator it = regex.globalMatchView(text);
while (it.hasNext()) {
QRegularExpressionMatch match = it.next();
diff --git a/examples/quick/quickwidgets/qmlpreviewer/widgets/codeeditor.cpp b/examples/quick/quickwidgets/qmlpreviewer/widgets/codeeditor.cpp
new file mode 100644
index 0000000000..fa505df115
--- /dev/null
+++ b/examples/quick/quickwidgets/qmlpreviewer/widgets/codeeditor.cpp
@@ -0,0 +1,105 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "codeeditor.h"
+#include "linenumberarea.h"
+
+#include <QPainter>
+#include <QTextBlock>
+
+CodeEditor::CodeEditor(QWidget *parent)
+ : QPlainTextEdit{parent}
+ , m_lineNumberArea{new LineNumberArea{this}}
+{
+ setupConnections();
+ updateLineNumberAreaWidth();
+ highlightCurrentLine();
+}
+
+void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
+{
+ const QRect eventRect = event->rect();
+
+ QPainter painter{m_lineNumberArea};
+ painter.fillRect(eventRect, palette().color(QPalette::AlternateBase));
+
+ QTextBlock block = firstVisibleBlock();
+ int blockNumber = block.blockNumber();
+ qreal top = blockBoundingGeometry(block).translated(contentOffset()).top();
+ qreal bottom = top + blockBoundingRect(block).height();
+
+ while (block.isVisible() && (top <= eventRect.bottom()) && (blockNumber < blockCount())) {
+ if (block.isVisible() && (bottom >= eventRect.top())) {
+ const QString number = QString::number(blockNumber + 1);
+ painter.setPen(palette().color(QPalette::Text));
+ painter.drawText(0, qRound(top), m_lineNumberArea->width() - 5, fontMetrics().height(),
+ Qt::AlignRight, number);
+ }
+
+ block = block.next();
+ top = bottom;
+ bottom = top + blockBoundingRect(block).height();
+ ++blockNumber;
+ }
+}
+
+int CodeEditor::lineNumberAreaWidth() const
+{
+ int digits = 1;
+ int max = qMax(1, blockCount());
+ while (max >= 10) {
+ max /= 10;
+ ++digits;
+ }
+
+ const int space = 9 + fontMetrics().horizontalAdvance('9') * digits;
+ return space;
+}
+
+void CodeEditor::setupConnections()
+{
+ connect(this, &CodeEditor::blockCountChanged, this, &CodeEditor::updateLineNumberAreaWidth);
+ connect(this, &CodeEditor::updateRequest, this, &CodeEditor::updateLineNumberArea);
+ connect(this, &CodeEditor::cursorPositionChanged, this, &CodeEditor::highlightCurrentLine);
+}
+
+void CodeEditor::resizeEvent(QResizeEvent *event)
+{
+ QPlainTextEdit::resizeEvent(event);
+
+ const QRect rect = contentsRect();
+ m_lineNumberArea->setGeometry(rect.left(), rect.top(), lineNumberAreaWidth(), rect.height());
+}
+
+void CodeEditor::updateLineNumberArea(const QRect &rect, int dy)
+{
+ if (dy)
+ m_lineNumberArea->scroll(0, dy);
+ else
+ m_lineNumberArea->update(0, rect.y(), m_lineNumberArea->width(), rect.height());
+
+ if (rect.contains(viewport()->rect()))
+ updateLineNumberAreaWidth();
+}
+
+void CodeEditor::updateLineNumberAreaWidth()
+{
+ setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
+}
+
+void CodeEditor::highlightCurrentLine()
+{
+ QList<QTextEdit::ExtraSelection> extraSelections;
+
+ if (!isReadOnly()) {
+ QTextEdit::ExtraSelection selection;
+ selection.format.setBackground(palette().color(QPalette::AlternateBase));
+ selection.format.setProperty(QTextFormat::FullWidthSelection, true);
+ selection.cursor = textCursor();
+ selection.cursor.clearSelection();
+
+ extraSelections.append(selection);
+ }
+
+ setExtraSelections(extraSelections);
+}
diff --git a/examples/quick/quickwidgets/qmlpreviewer/widgets/codeeditor.h b/examples/quick/quickwidgets/qmlpreviewer/widgets/codeeditor.h
new file mode 100644
index 0000000000..a952c29378
--- /dev/null
+++ b/examples/quick/quickwidgets/qmlpreviewer/widgets/codeeditor.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef CODEEDITOR_H
+#define CODEEDITOR_H
+
+#include <QPlainTextEdit>
+
+class LineNumberArea;
+
+class CodeEditor : public QPlainTextEdit
+{
+ Q_OBJECT
+
+public:
+ CodeEditor(QWidget *parent = nullptr);
+
+ void lineNumberAreaPaintEvent(QPaintEvent *event);
+ int lineNumberAreaWidth() const;
+
+private:
+ void setupConnections();
+ void resizeEvent(QResizeEvent *event) final;
+
+private slots:
+ void updateLineNumberArea(const QRect &rect, int dy);
+ void updateLineNumberAreaWidth();
+ void highlightCurrentLine();
+
+private:
+ LineNumberArea *m_lineNumberArea = nullptr;
+};
+
+#endif // CODEEDITOR_H
diff --git a/examples/quick/quickwidgets/qmlpreviewer/widgets/editorwidget.cpp b/examples/quick/quickwidgets/qmlpreviewer/widgets/editorwidget.cpp
index f35e6c0c2d..c77fd5fa70 100644
--- a/examples/quick/quickwidgets/qmlpreviewer/widgets/editorwidget.cpp
+++ b/examples/quick/quickwidgets/qmlpreviewer/widgets/editorwidget.cpp
@@ -2,13 +2,13 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "editorwidget.h"
+#include "codeeditor.h"
#include "patheditwidget.h"
#include "../states/statecontroller.h"
#include "../utility/syntaxhighlighter.h"
#include <QFile>
#include <QMessageBox>
-#include <QPlainTextEdit>
#include <QPushButton>
#include <QVBoxLayout>
@@ -34,7 +34,7 @@ static inline QByteArray loadFromFile(const QString &filePath)
EditorWidget::EditorWidget(QWidget *parent)
: QWidget{parent}
, m_pathEdit{new PathEditWidget}
- , m_editor{new QPlainTextEdit}
+ , m_editor{new CodeEditor}
, m_saveButton{new QPushButton}
, m_reloadButton{new QPushButton}
, m_closeButton{new QPushButton}
@@ -146,6 +146,19 @@ void EditorWidget::reloadFile()
m_mutex.unlock();
}
+void EditorWidget::moveCursorTo(int line, int column)
+{
+ if (line < 1 || column < 1)
+ return;
+
+ QTextCursor cursor = m_editor->textCursor();
+ cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, line - 1);
+ cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, column - 1);
+ m_editor->setTextCursor(cursor);
+ m_editor->setFocus();
+}
+
void EditorWidget::initUI()
{
QHBoxLayout *actionsLayout = new QHBoxLayout;
@@ -160,6 +173,7 @@ void EditorWidget::initUI()
layout->setContentsMargins(0,0,0,0);
setLayout(layout);
+ m_editor->setCursorWidth(2);
m_editor->setPlaceholderText(tr("Write code or open a file"));
m_saveButton->setText(tr("Save"));
m_saveButton->setEnabled(false);
diff --git a/examples/quick/quickwidgets/qmlpreviewer/widgets/editorwidget.h b/examples/quick/quickwidgets/qmlpreviewer/widgets/editorwidget.h
index 46c5730b5c..939f008dec 100644
--- a/examples/quick/quickwidgets/qmlpreviewer/widgets/editorwidget.h
+++ b/examples/quick/quickwidgets/qmlpreviewer/widgets/editorwidget.h
@@ -24,6 +24,7 @@ public slots:
void saveFile();
void closeFile();
void reloadFile();
+ void moveCursorTo(int line, int column);
private:
void initUI();
diff --git a/examples/quick/quickwidgets/qmlpreviewer/widgets/linenumberarea.cpp b/examples/quick/quickwidgets/qmlpreviewer/widgets/linenumberarea.cpp
new file mode 100644
index 0000000000..fba36d2b2e
--- /dev/null
+++ b/examples/quick/quickwidgets/qmlpreviewer/widgets/linenumberarea.cpp
@@ -0,0 +1,20 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "linenumberarea.h"
+#include "codeeditor.h"
+
+LineNumberArea::LineNumberArea(CodeEditor *editor)
+ : QWidget{editor}
+ , m_codeEditor{editor}
+{}
+
+QSize LineNumberArea::sizeHint() const
+{
+ return QSize{m_codeEditor->lineNumberAreaWidth(), 0};
+}
+
+void LineNumberArea::paintEvent(QPaintEvent *event)
+{
+ m_codeEditor->lineNumberAreaPaintEvent(event);
+}
diff --git a/examples/quick/quickwidgets/qmlpreviewer/widgets/linenumberarea.h b/examples/quick/quickwidgets/qmlpreviewer/widgets/linenumberarea.h
new file mode 100644
index 0000000000..2ba6fb9d58
--- /dev/null
+++ b/examples/quick/quickwidgets/qmlpreviewer/widgets/linenumberarea.h
@@ -0,0 +1,27 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef LINENUMBERAREA_H
+#define LINENUMBERAREA_H
+
+#include <QWidget>
+
+class CodeEditor;
+
+class LineNumberArea : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit LineNumberArea(CodeEditor *editor);
+
+ QSize sizeHint() const final;
+
+private:
+ void paintEvent(QPaintEvent *event) final;
+
+private:
+ CodeEditor *m_codeEditor = nullptr;
+};
+
+#endif // LINENUMBERAREA_H
diff --git a/examples/quick/quickwidgets/qmlpreviewer/widgets/mainwindow.cpp b/examples/quick/quickwidgets/qmlpreviewer/widgets/mainwindow.cpp
index eb27720280..339379e127 100644
--- a/examples/quick/quickwidgets/qmlpreviewer/widgets/mainwindow.cpp
+++ b/examples/quick/quickwidgets/qmlpreviewer/widgets/mainwindow.cpp
@@ -3,27 +3,19 @@
#include "mainwindow.h"
#include "editorwidget.h"
+#include "previewwidget.h"
#include "../states/statecontroller.h"
+#include <QCloseEvent>
#include <QFileSystemWatcher>
#include <QLayout>
#include <QMenuBar>
#include <QMessageBox>
-#include <QQmlEngine>
-#include <QQuickWidget>
-
-namespace {
-static constexpr auto QUIT_SHORTCUT = QKeySequence::Quit;
-static constexpr auto OPEN_SHORTCUT = QKeySequence::Open;
-static constexpr auto SAVE_SHORTCUT = QKeySequence::Save;
-static constexpr auto CLOSE_SHORTCUT = QKeySequence::Close;
-static constexpr auto RELOAD_SHORTCUT = Qt::CTRL | Qt::Key_R;
-}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, m_editorWidget{new EditorWidget}
- , m_previewWidget{new QQuickWidget}
+ , m_previewWidget{new PreviewWidget}
, m_fileWatcher{new QFileSystemWatcher}
{
setWindowIcon(QIcon(":/resources/logo.png"));
@@ -51,8 +43,6 @@ void MainWindow::initUI()
centralWidget->setLayout(horizontalLayout);
horizontalLayout->addWidget(m_editorWidget, 1);
-
- m_previewWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
horizontalLayout->addWidget(m_previewWidget, 1);
}
@@ -61,21 +51,24 @@ void MainWindow::initMenuBar()
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
m_openAction = fileMenu->addAction(tr("&Open"));
- m_openAction->setShortcut(OPEN_SHORTCUT);
m_saveAction = fileMenu->addAction(tr("&Save"));
- m_saveAction->setShortcut(SAVE_SHORTCUT);
m_saveAction->setEnabled(false);
m_closeAction = fileMenu->addAction(tr("&Close"));
- m_closeAction->setShortcut(CLOSE_SHORTCUT);
m_closeAction->setEnabled(false);
m_reloadAction = fileMenu->addAction(tr("&Reload"));
- m_reloadAction->setShortcut(::RELOAD_SHORTCUT);
m_reloadAction->setEnabled(false);
fileMenu->addSeparator();
- QAction *quitAction = fileMenu->addAction(tr("&Quit"));
- quitAction->setShortcut(QUIT_SHORTCUT);
+ m_quitAction = fileMenu->addAction(tr("&Quit"));
+
+#if QT_CONFIG(shortcut)
+ m_openAction->setShortcut(QKeySequence::Open);
+ m_saveAction->setShortcut(QKeySequence::Save);
+ m_closeAction->setShortcut(QKeySequence::Close);
+ m_reloadAction->setShortcut(Qt::CTRL | Qt::Key_R);
+ m_quitAction->setShortcut(QKeySequence::Quit);
+#endif
}
void MainWindow::setupConnections()
@@ -84,6 +77,8 @@ void MainWindow::setupConnections()
&MainWindow::onAppStateChanged);
connect(m_fileWatcher, &QFileSystemWatcher::fileChanged, this, &MainWindow::onFileChanged);
connect(menuBar(), &QMenuBar::triggered, this, &MainWindow::onMenuBarTriggered);
+ connect(m_previewWidget, &PreviewWidget::errorPositionSelected, m_editorWidget,
+ &EditorWidget::moveCursorTo);
}
void MainWindow::closeEvent(QCloseEvent *event)
@@ -112,11 +107,10 @@ void MainWindow::onAppStateChanged(int oldState, int newState)
{
switch (newState) {
case StateController::InitState:
- if (!m_previewWidget->source().isEmpty()) {
- m_previewWidget->engine()->clearComponentCache();
+ if (!m_previewWidget->sourcePath().isEmpty()) {
if (const QStringList files = m_fileWatcher->files(); !files.isEmpty())
m_fileWatcher->removePaths(files);
- m_previewWidget->setSource(QUrl{});
+ m_previewWidget->setSourcePath(QString{});
}
m_saveAction->setEnabled(false);
m_closeAction->setEnabled(false);
@@ -124,11 +118,10 @@ void MainWindow::onAppStateChanged(int oldState, int newState)
break;
case StateController::OpenState:
- m_previewWidget->engine()->clearComponentCache();
if (const QStringList files = m_fileWatcher->files(); !files.isEmpty())
m_fileWatcher->removePaths(files);
m_fileWatcher->addPath(StateController::instance()->filePath());
- m_previewWidget->setSource(QUrl::fromLocalFile(StateController::instance()->filePath()));
+ m_previewWidget->setSourcePath(StateController::instance()->filePath());
m_saveAction->setEnabled(false);
m_closeAction->setEnabled(true);
m_reloadAction->setEnabled(false);
@@ -169,22 +162,20 @@ void MainWindow::onFileChanged(const QString &path)
}
m_editorWidget->updateEditor();
- m_previewWidget->engine()->clearComponentCache();
- m_previewWidget->setSource(QUrl::fromLocalFile(path));
+ m_previewWidget->setSourcePath(path);
stateController->setDirty(false);
}
void MainWindow::onMenuBarTriggered(QAction *action)
{
- const QKeySequence shortcut = action->shortcut();
- if (shortcut == OPEN_SHORTCUT)
+ if (action == m_openAction)
m_editorWidget->openFile();
- else if (shortcut == SAVE_SHORTCUT)
+ else if (action == m_saveAction)
m_editorWidget->saveFile();
- else if (shortcut == CLOSE_SHORTCUT)
+ else if (action == m_closeAction)
m_editorWidget->closeFile();
- else if (shortcut == RELOAD_SHORTCUT)
+ else if (action == m_reloadAction)
m_editorWidget->reloadFile();
- else if (shortcut == QUIT_SHORTCUT)
+ else if (action == m_quitAction)
QCoreApplication::quit();
}
diff --git a/examples/quick/quickwidgets/qmlpreviewer/widgets/mainwindow.h b/examples/quick/quickwidgets/qmlpreviewer/widgets/mainwindow.h
index 89cbb6c332..22ce63d34b 100644
--- a/examples/quick/quickwidgets/qmlpreviewer/widgets/mainwindow.h
+++ b/examples/quick/quickwidgets/qmlpreviewer/widgets/mainwindow.h
@@ -6,8 +6,8 @@
#include <QMainWindow>
+class PreviewWidget;
class EditorWidget;
-class QQuickWidget;
class QFileSystemWatcher;
class MainWindow : public QMainWindow
@@ -31,11 +31,12 @@ private slots:
private:
EditorWidget *m_editorWidget = nullptr;
- QQuickWidget *m_previewWidget = nullptr;
+ PreviewWidget *m_previewWidget = nullptr;
QFileSystemWatcher *m_fileWatcher = nullptr;
QAction *m_openAction = nullptr;
QAction *m_saveAction = nullptr;
QAction *m_closeAction = nullptr;
QAction *m_reloadAction = nullptr;
+ QAction *m_quitAction = nullptr;
};
#endif // MAINWINDOW_H
diff --git a/examples/quick/quickwidgets/qmlpreviewer/widgets/previewwidget.cpp b/examples/quick/quickwidgets/qmlpreviewer/widgets/previewwidget.cpp
new file mode 100644
index 0000000000..c75b07b37a
--- /dev/null
+++ b/examples/quick/quickwidgets/qmlpreviewer/widgets/previewwidget.cpp
@@ -0,0 +1,94 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "previewwidget.h"
+#include "../states/statecontroller.h"
+
+#include <QListView>
+#include <QQmlEngine>
+#include <QQuickWidget>
+#include <QSplitter>
+#include <QVBoxLayout>
+
+PreviewWidget::PreviewWidget(QWidget *parent)
+ : QWidget{parent}
+ , m_errorListModel{this}
+ , m_errorListView{new QListView}
+ , m_quickWidget{new QQuickWidget}
+{
+ initUI();
+ setupConnections();
+}
+
+QString PreviewWidget::sourcePath() const
+{
+ return m_quickWidget->source().toString();
+}
+
+void PreviewWidget::setSourcePath(const QString &path)
+{
+ m_quickWidget->engine()->clearComponentCache();
+ m_quickWidget->setSource(QUrl::fromLocalFile(path));
+}
+
+void PreviewWidget::initUI()
+{
+ m_errorListView->setModel(&m_errorListModel);
+ m_errorListView->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ m_errorListView->setWordWrap(true);
+ m_errorListView->setSpacing(4);
+
+ m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
+
+ QSizePolicy sizePolicy = m_quickWidget->sizePolicy();
+ sizePolicy.setVerticalStretch(1);
+ m_quickWidget->setSizePolicy(sizePolicy);
+
+ QSplitter *splitter = new QSplitter{this};
+ splitter->setOrientation(Qt::Vertical);
+ splitter->addWidget(m_quickWidget);
+ splitter->addWidget(m_errorListView);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(splitter);
+ setLayout(layout);
+}
+
+void PreviewWidget::setupConnections()
+{
+ connect(StateController::instance(), &StateController::stateChanged, this,
+ &PreviewWidget::onAppStateChanged);
+ connect(m_quickWidget, &QQuickWidget::statusChanged, this,
+ &PreviewWidget::onQuickWidetStatusChanged);
+ connect(m_errorListView, &QAbstractItemView::doubleClicked, &m_errorListModel,
+ &ErrorListModel::selectIndex);
+ connect(&m_errorListModel, &ErrorListModel::errorPositionSelected, this,
+ &PreviewWidget::errorPositionSelected);
+}
+
+void PreviewWidget::onAppStateChanged(int oldState, int newState)
+{
+ Q_UNUSED(oldState);
+
+ switch (newState) {
+ case StateController::InitState:
+ m_errorListModel.setErrorList({});
+ break;
+
+ default:
+ break;
+ }
+}
+
+void PreviewWidget::onQuickWidetStatusChanged(int status)
+{
+ switch (status) {
+ case QQuickWidget::Error:
+ m_errorListModel.setErrorList(m_quickWidget->errors());
+ break;
+ default:
+ m_errorListModel.setErrorList({});
+ break;
+ }
+}
diff --git a/examples/quick/quickwidgets/qmlpreviewer/widgets/previewwidget.h b/examples/quick/quickwidgets/qmlpreviewer/widgets/previewwidget.h
new file mode 100644
index 0000000000..16b739a900
--- /dev/null
+++ b/examples/quick/quickwidgets/qmlpreviewer/widgets/previewwidget.h
@@ -0,0 +1,39 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef PREVIEWWIDGET_H
+#define PREVIEWWIDGET_H
+
+#include "../models/errorlistmodel.h"
+#include <QWidget>
+
+class QListView;
+class QQuickWidget;
+
+class PreviewWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit PreviewWidget(QWidget *parent = nullptr);
+
+ QString sourcePath() const;
+ void setSourcePath(const QString &path);
+
+private:
+ void initUI();
+ void setupConnections();
+
+signals:
+ void errorPositionSelected(int line, int column);
+
+private slots:
+ void onAppStateChanged(int oldState, int newState);
+ void onQuickWidetStatusChanged(int status);
+
+private:
+ ErrorListModel m_errorListModel;
+ QListView *m_errorListView = nullptr;
+ QQuickWidget *m_quickWidget = nullptr;
+};
+
+#endif // PREVIEWWIDGET_H