Qt ウィジェット - テキストビューアプラグインの例
メニュー、ツールバー、ステータスバーを備えたウィジェットの例です。
テキストビューアの例は、汎用のドキュメントビューアのプラグインの形で、QPlainTextEdit を中心に構築されたテキストエディタです。
TxtViewer
AbstractViewer
AbstractViewer
は、ビューワとメインウィンドウ間のインタラクションのフレームワークを提供します。このアプリケーションは、 、 、 のエントリーをメニューバーに提供します。File Edit Help
メイン・ウィンドウの下部にあるステータス・バーには、アプリケーションがユーザーに提供するメッセージが表示される。
最近開いたファイルはFile メニューに表示されます。この例では、一度に1つのファイルしかロードできません。
クラス定義
class TxtViewer : public ViewerInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.DocumentViewer.ViewerInterface" FILE "txtviewer.json") Q_INTERFACES(ViewerInterface)
クラス定義は、シグナルとスロットを処理するQ_OBJECT
マクロで始まります。その後に、プラグインの登録に必要なQ_PLUGIN_METADATA
とQ_INTERFACES
マクロが続きます。
このクラスはViewerInterface
を継承し、AbstractViewer
を継承します。ViewerInterface
クラスは、メイン・ウィンドウ・アプリケーションとプラグインの間のインターフェイスを提供するために使用されます。
QPluginLoader
また、プラグインのキーを含むtxtviewer.jsonファイルが必要です:
{ "Keys": [ "txtviewer" ] } public: TxtViewer(); ~TxtViewer() override; void init(QFile *file, QWidget *parent, QMainWindow *mainWindow) override; QString viewerName() const override { return QLatin1StringView(staticMetaObject.className()); }; QStringList supportedMimeTypes() const override; bool saveDocument() override { return saveFile(m_file.get()); }; bool saveDocumentAs() override; bool hasContent() const override; QByteArray saveState() const override { return {}; } bool restoreState(QByteArray &) override { return true; } bool supportsOverview() const override { return false; } #ifdef QT_DOCUMENTVIEWER_PRINTSUPPORT protected: void printDocument(QPrinter *printer) const override; #endif // QT_DOCUMENTVIEWER_PRINTSUPPORT private slots: void setupTxtUi(); private: void openFile(); bool saveFile (QFile *file); QPlainTextEdit *m_textEdit; };
このクラスはコンストラクタを定義していないので、引数のない標準的なコンストラクタしか利用できません。デストラクタを含む他のすべての関数は、ViewerInterface
の仮想関数を再実装しています。これらは、メイン・アプリケーションとデータ、情報、命令を交換するために使用されます。
設定を保存したり復元したりする機能は実装されていません。supportsOverview
関数は常にfalse
を返し、サムネイル・ナビゲーション用のウィンドウを表示する必要がないことをメイン・アプリケーションに伝えます。
TxtViewerクラスの実装
#include "txtviewer.h" #include <QFileDialog> #include <QMainWindow> #include <QMenu> #include <QMenuBar> #include <QPlainTextEdit> #include <QScrollBar> #include <QToolBar> #include <QGuiApplication> #include <QPainter> #include <QTextDocument> #include <QDir> #ifdef QT_DOCUMENTVIEWER_PRINTSUPPORT #include <QPrinter> #include <QPrintDialog> #endif using namespace Qt::StringLiterals; TxtViewer::TxtViewer() { connect(this, &AbstractViewer::uiInitialized, this, &TxtViewer::setupTxtUi); } TxtViewer::~TxtViewer() = default; void TxtViewer::init(QFile *file, QWidget *parent, QMainWindow *mainWindow) { AbstractViewer::init(file, new QPlainTextEdit(parent), mainWindow); m_textEdit = qobject_cast<QPlainTextEdit *>(widget()); } QStringList TxtViewer::supportedMimeTypes() const { return {"text/plain"_L1}; } void TxtViewer::setupTxtUi() { QMenu *editMenu = addMenu(tr("&Edit")); QToolBar *editToolBar = addToolBar(tr("Edit")); #ifndef QT_NO_CLIPBOARD const QIcon cutIcon = QIcon::fromTheme("edit-cut"_L1, QIcon(":/demos/documentviewer/images/cut.png"_L1)); QAction *cutAct = new QAction(cutIcon, tr("Cu&t"), this); cutAct->setShortcuts(QKeySequence::Cut); cutAct->setStatusTip(tr("Cut the current selection's contents to the " "clipboard")); connect(cutAct, &QAction::triggered, m_textEdit, &QPlainTextEdit::cut); editMenu->addAction(cutAct); editToolBar->addAction(cutAct); const QIcon copyIcon = QIcon::fromTheme("edit-copy"_L1, QIcon(":/demos/documentviewer/images/copy.png"_L1)); QAction *copyAct = new QAction(copyIcon, tr("&Copy"), this); copyAct->setShortcuts(QKeySequence::Copy); copyAct->setStatusTip(tr("Copy the current selection's contents to the " "clipboard")); connect(copyAct, &QAction::triggered, m_textEdit, &QPlainTextEdit::copy); editMenu->addAction(copyAct); editToolBar->addAction(copyAct); const QIcon pasteIcon = QIcon::fromTheme("edit-paste"_L1, QIcon(":/demos/documentviewer/images/paste.png"_L1)); QAction *pasteAct = new QAction(pasteIcon, tr("&Paste"), this); pasteAct->setShortcuts(QKeySequence::Paste); pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current " "selection")); connect(pasteAct, &QAction::triggered, m_textEdit, &QPlainTextEdit::paste); editMenu->addAction(pasteAct); editToolBar->addAction(pasteAct); menuBar()->addSeparator(); cutAct->setEnabled(false); copyAct->setEnabled(false); connect(m_textEdit, &QPlainTextEdit::copyAvailable, cutAct, &QAction::setEnabled); connect(m_textEdit, &QPlainTextEdit::copyAvailable, copyAct, &QAction::setEnabled); #endif // !QT_NO_CLIPBOARD openFile(); connect(m_textEdit, &QPlainTextEdit::textChanged, this, [&](){ maybeSetPrintingEnabled(hasContent()); }); connect(m_uiAssets.back, &QAction::triggered, m_textEdit, [&](){ auto *bar = m_textEdit->verticalScrollBar(); if (bar->value() > bar->minimum()) bar->setValue(bar->value() - 1); }); connect(m_uiAssets.forward, &QAction::triggered, m_textEdit, [&](){ auto *bar = m_textEdit->verticalScrollBar(); if (bar->value() < bar->maximum()) bar->setValue(bar->value() + 1); }); }
TxtViewer
で使用されるすべてのクラスにアクセスするために必要なヘッダーファイルから始めます。また、txtviewer.h
もインクルードします。
QPrinter
と は、コンパイル・システムで印刷サポートが有効になっている場合にのみインクルードされます。QPrintDialog
なぜこれらのヘッダーをmainwindow.h
に含めないのか不思議に思うかもしれません。その理由は、別のヘッダーファイルから複数の大きなヘッダーをインクルードすると、パフォーマンスが急速に低下する可能性があるからです。しかし、他のヘッダー・ファイルから厳密に必要なヘッダー・ファイルだけをインクルードするのは、一般的に良い考えです。
実装は空のデストラクタで始まる。完全に省略することもできる。コード読者に、デストラクタでは何もする必要がないことを示すために、空で実装するのはよい習慣です。
デストラクタの後には、3つの引数をとる初期化関数が続く:
file
オープンして表示するファイルへのポインタ。parent
エディターが配置されるQWidget
。mainWindow
メニューとメニュー・バーが処理されるアプリケーションのメイン・ウィンドウへのポインタ。
この関数は、AbstractViwer
の基本 init 関数を呼び出します。新しいQPlainTextEdit ウィジェットが作成され、ファイルの内容が表示されます。そして、TxtViewer
のセットアップ関数がベース・クラスのuiInitializedシグナルに接続されます。
次の関数は、テキスト・ビューワがサポートする MIME タイプのリストを返します。プレーンテキストのみがサポートされる。
最後の初期化関数は、メニュー、アイコン、ボタン、ツールチップのようなビューア固有のUIコンポーネントを追加します。AbstractViewer
、これらのコンポーネントがアプリケーションのメインウィンドウから削除されるようにします。
void TxtViewer::openFile() { const QString type = tr("open"); if (!m_file->open(QFile::ReadOnly | QFile::Text)) { statusMessage(tr("Cannot read file %1:\n%2.") .arg(QDir::toNativeSeparators(m_file->fileName()), m_file->errorString()), type); return; } QTextStream in(m_file.get()); #ifndef QT_NO_CURSOR QGuiApplication::setOverrideCursor(Qt::WaitCursor); #endif if (!m_textEdit->toPlainText().isEmpty()) { m_textEdit->clear(); disablePrinting(); } m_textEdit->setPlainText(in.readAll()); #ifndef QT_NO_CURSOR QGuiApplication::restoreOverrideCursor(); #endif statusMessage(tr("File %1 loaded.") .arg(QDir::toNativeSeparators(m_file->fileName())), type); maybeEnablePrinting(); }
openFile
ファイルをオープンし、その内容を に転送し、オープンが成功したかどうかに応じて、ユーザーにステータス・メッセージを表示します。QPlainTextEdit
bool TxtViewer::hasContent() const { return (!m_textEdit->toPlainText().isEmpty()); } #ifdef QT_DOCUMENTVIEWER_PRINTSUPPORT void TxtViewer::printDocument(QPrinter *printer) const { if (!hasContent()) return; m_textEdit->print(printer); } #endif // QT_DOCUMENTVIEWER_PRINTSUPPORT bool TxtViewer::saveFile(QFile *file) { QString errorMessage; QGuiApplication::setOverrideCursor(Qt::WaitCursor); if (file->open(QFile::WriteOnly | QFile::Text)) { QTextStream out(file); out << m_textEdit->toPlainText(); } else { errorMessage = tr("Cannot open file %1 for writing:\n%2.") .arg(QDir::toNativeSeparators(file->fileName())), file->errorString(); } QGuiApplication::restoreOverrideCursor(); if (!errorMessage.isEmpty()) { statusMessage(errorMessage); return false; } statusMessage(tr("File %1 saved") .arg(QDir::toNativeSeparators(file->fileName()))); return true; } bool TxtViewer::saveDocumentAs() { QFileDialog dialog(mainWindow()); dialog.setWindowModality(Qt::WindowModal); dialog.setAcceptMode(QFileDialog::AcceptSave); if (dialog.exec() != QDialog::Accepted) return false; const QStringList &files = dialog.selectedFiles(); if (files.isEmpty()) return false; //newFile(); m_file->setFileName(files.first()); return saveDocument(); }
次に再実装された関数は、ビューア・プラグインが実際にコンテンツを表示しているかどうかをメイン・アプリケーションに伝えます。
コンパイルシステムで印刷がサポートされている場合、次のセクションでそれを実装する。
最後の2つの再実装は、現在のファイルを保存したり、新しい名前で保存したりする機能を提供する。
©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 ここで提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。