ドキュメントビューア

JSON、テキスト、PDFファイルを表示、印刷するためのウィジェットアプリケーションです。

Document Viewerは、静的および動的なツールバー、メニュー、アクションを備えたQMainWindow 。さらに、ウィジェット・ベースのアプリケーションにおける以下の機能も紹介します:

  • QSettings を使用して、ユーザー設定を照会および保存し、以前に開いたファイルの履歴を管理する。
  • ウィジェットにカーソルを置いたときのカーソル動作の制御。
  • 動的にロードされるプラグインの作成

アプリケーションとメイン・ウィンドウの作成

アプリケーションとそのメイン・ウィンドウはmain.cpp で構築されます。main()関数は、QCommandLineParser を使用して、コマンド行引数(helpversion、およびオプションの位置引数file)を処理します。ユーザーがアプリケーションの起動時にファイルへのパスを指定した場合、メイン・ウィンドウはそのファイルを開きます:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QCoreApplication::setOrganizationName("QtProject"_L1);
    QCoreApplication::setApplicationName("DocumentViewer"_L1);
    QCoreApplication::setApplicationVersion("1.0"_L1);

    QCommandLineParser parser;
    parser.setApplicationDescription(QApplication::translate("main",
                                                     "A viewer for JSON, PDF and text files"));
    parser.addHelpOption();
    parser.addVersionOption();
    parser.addPositionalArgument("File"_L1, QApplication::translate("main",
                                                                    "JSON, PDF or text file to open"));
    parser.process(app);

    const QStringList &positionalArguments = parser.positionalArguments();
    const QString &fileName = (positionalArguments.count() > 0) ? positionalArguments.at(0)
                                                                : QString();

    MainWindow w;

    // Start application only if plugins are available
    if (!w.hasPlugins()) {
        QMessageBox::critical(nullptr,
                              "No viewer plugins found"_L1,
                              "Unable to load viewer plugins. Exiting application."_L1);
        return 1;
    }

    w.show();
    if (!fileName.isEmpty())
        w.openFile(fileName);

    return app.exec();
}

MainWindowクラス

MainWindow クラスは、メニュー、アクション、ツールバーを備えたアプリケーション画面を提供します。ファイルを開くことができ、そのコンテンツ・タイプを自動的に検出します。また、QSettings を使用して、以前に開いたファイルのリストを保持し、起動時に設定を保存して再読み込みします。MainWindowは、コンテンツ・タイプに基づいて、開かれたファイルに適したビューアを作成し、ドキュメントの印刷をサポートします。

MainWindow のコンストラクタは、Qt Designer で作成されたユーザー インターフェイスを初期化します。mainwindow.ui ファイルの左側にはQTabWidget があり、ブックマークとサムネイルが表示されます。右側には、ファイルの内容を表示するためのQScrollArea があります。

ViewerFactoryクラス

ViewerFactory クラスは、既知のファイルタイプのビューアを管理します。これらのビューアはプラグインとして実装されます。ViewerFactoryのインスタンスが作成されると、ビューエリアとメインウィンドウへのポインタがコンストラクタに渡されます:

m_factory.reset(new ViewerFactory(ui->viewArea, this));

ViewerFactory は、構築時に利用可能なすべてのプラグインをロードします。ViewerFactory は、ロードされたプラグイン、その名前、およびサポートされる MIME タイプを照会するためのパブリック API を提供します:

    using ViewerList = QList<AbstractViewer *>;
    QStringList viewerNames(bool showDefault = false) const;
    ViewerList viewers() const;
    AbstractViewer *findViewer(const QString &viewerName) const;
    AbstractViewer *defaultViewer() const;
    QStringList supportedMimeTypes() const;

viewer() 関数は、引数として渡されたQFile を開くのに適したプラグインへのポインタを返します:

m_viewer = m_factory->viewer(file);

アプリケーション設定にビューア用のセクションが含まれている場合、それはビューアの仮想restoreState() 関数に渡されます:

void MainWindow::restoreViewerSettings()
{
    if (!m_viewer)
        return;

    QSettings settings;
    settings.beginGroup(settingsViewers);
    QByteArray viewerSettings = settings.value(m_viewer->viewerName(), QByteArray()).toByteArray();
    settings.endGroup();
    if (!viewerSettings.isEmpty())
        m_viewer->restoreState(viewerSettings);
}

次に、標準のUIアセットがビューアに渡され、ビューアの表示ウィジェットが表示されるようにメインスクロールエリアが設定されます:

    m_viewer->initViewer(ui->actionBack, ui->actionForward, ui->menuHelp->menuAction(), ui->tabWidget);
    restoreViewerSettings();
    ui->scrollArea->setWidget(m_viewer->widget());
    return true;
}

AbstractViewerクラス

AbstractViewer は、ドキュメントを表示、保存、印刷するための一般化されたAPIを提供します。ドキュメントとビューアの両方のプロパティを問い合わせることができます:

  • 文書に内容はあるか?
  • 文書に内容はあるか?
  • 概要(サムネイルやブックマーク)はサポートされていますか?

AbstractViewerは、派生クラスがメインウィンドウ上にアクションやメニューを作成するためのプロテクトメソッドを提供します。これらのアセットをメインウィンドウに表示するために、アセットがメインウィンドウの親になります。AbstractViewerは、作成したUIアセットの削除と破棄を行います。シグナルとスロットを実装するために、QObject を継承しています。

シグナル

void uiInitialized();

このシグナルは、ビューアがメインウィンドウ上のUIアセットに関するすべての必要な情報を受け取った後に発行されます。

void printingEnabledChanged(bool enabled);

このシグナルは、ドキュメントの印刷が有効または無効になったときに発行されます。これは、新しいドキュメントが正常に読み込まれた後、または例えばすべてのコンテンツが削除された後に発生します。

void printStatusChanged(AbstractViewer::PrintStatus status);

印刷処理を開始した後、このシグナルはその進行状況の変化を通知する。

void documentLoaded(const QString &fileName);

このシグナルは、ドキュメントが正常に読み込まれたことをアプリケーションに通知します。

TxtViewerクラス

TxtViewer は、AbstractViewerを継承したシンプルなテキストビューアです。テキストファイルの編集、コピー/カット&ペースト、印刷、変更の保存をサポートしています。

JsonViewerクラス

JsonViewer は、JSON ファイルを に表示します。内部的には、ファイルの内容を にロードし、それを使用してカスタムツリーモデルに を入力します。QTreeView QJsonDocument JsonItemModel

JSONビューアプラグインは、QAbstractItemModel から継承されたカスタムアイテムモデルを実装する方法を示しています。JsonTreeItem クラスは、JSONデータを操作し、それを基礎となるQJsonDocument に伝搬するための基本的なAPIを提供します。

JsonViewer は、ドキュメントの最上位オブジェクトをナビゲーションのブックマークとして使用します。他のノード(キーと値)は、追加のブックマークとして追加したり、ブックマークリストから削除することができます。QLineEdit は、JSONツリーをナビゲートする検索フィールドとして使用されます。

PdfViewer クラス

PdfViewer クラス(とプラグイン)は、PDF Viewer Widget Exampleのフォークです。これは、ドキュメントをスムーズにフリックするためのQScroller の使用を示しています。

その他の関連クラス

HoverWatcherクラス

HoverWatcher クラスは、マウスをウィジェットの上に置くとオーバーライドカーソルを設定し、離れると元に戻します。同じウィジェットに複数のHoverWatcherインスタンスが生成されるのを防ぐため、ウィジェットごとにシングルトンとして実装されています。

HoverWatcher はQObject を継承し、QWidget をインスタンスの親として監視します。ホバーイベントを消費せずにインターセプトするイベントフィルタをインストールします:

HoverWatcher::HoverWatcher(QWidget *watched)
    : QObject(watched), m_watched(watched)
{
    Q_ASSERT(watched);
    m_cursorShapes[Entered].emplace(Qt::OpenHandCursor);
    m_cursorShapes[MousePress].emplace(Qt::ClosedHandCursor);
    m_cursorShapes[MouseRelease].emplace(Qt::OpenHandCursor);
    // no default for Left => restore override cursor
    m_watched->installEventFilter(this);
}

HoverAction enumは、HoverWatcherが反応するアクションをリストしています:

    enum HoverAction {
        Entered,
        MousePress,
        MouseRelease,
        Left,
        Ignore
    };

静的関数は、ウォッチャーを作成したり、特定のQWidget に対してウォッチャーの存在をチェックしたり、ウォッチャーを解除したりします:

    static HoverWatcher *watcher(QWidget *watched);
    static const HoverWatcher *watcher(const QWidget *watched);
    static bool hasWatcher(QWidget *widget);
    static void dismiss(QWidget *watched);

カーソル形状は、各HoverActionに対して設定または解除することができます。関連するカーソル形状がない場合、アクションがトリガーされると、アプリケーションのオーバーライドカーソルが復元されます。

public slots:
    void setCursorShape(HoverAction type, Qt::CursorShape shape);
    void unSetCursorShape(HoverAction type);

mouseButtons プロパティは、MousePress アクションを考慮するマウスボタンを保持します:

    void setMouseButtons(Qt::MouseButtons buttons);
    void setMouseButton(Qt::MouseButton button, bool enable);

アクション固有のシグナルは、アクションを処理した後に発せられる:

signals:
    void entered();
    void mousePressed();
    void mouseReleased();
    void left();

一般的なシグナルは、処理されたアクションを引数として渡します:

void hoverAction(HoverAction action);
RecentFilesクラス

RecentFiles は、最近開いたファイルのリストを管理することに特化した 。QStringList

RecentFilesは、単一のファイルまたは複数のファイルを一度に追加するスロットを持っています。パスが存在し、開くことができるファイルを指している場合、エントリが最近開いたファイルのリストに追加されます。ファイルがすでにリストにある場合、そのファイルは元の位置から取り除かれ、一番上に追加される。

public slots:
    void addFile(const QString &fileName) { addFile(fileName, EmitPolicy::EmitWhenChanged); }
    void addFiles(const QStringList &fileNames);

ファイルは、名前またはインデックスによってリストから削除される:

    void removeFile(const QString &fileName) { removeFile(m_files.indexOf(fileName)); }
    void removeFile(qsizetype index) {removeFile(index, RemoveReason::Other); }

QSettings からの保存と復元を実行するスロット:

    void saveSettings(QSettings &settings, const QString &key) const;
    bool restoreFromSettings(QSettings &settings, const QString &key);

設定をリストアする場合、存在しないファイルは無視されます。maxFiles プロパティは、保存する最近のファイルの最大量を保持します(デフォルトは10)。

qsizetype maxFiles();
void setMaxFiles(qsizetype maxFiles);

RecentFiles は、ファイルを受け入れる前に、そのファイルが読み込めるかどうかを確認します。

RecentFileMenu クラス

RecentFileMenu は、RecentFilesオブジェクトをサブメニューとして表示することに特化した 。QMenu

コンストラクタは、親クラス(QObject )へのポインタと、表示するRecentFilesオブジェクトへのポインタを受け取ります。fileOpened() シグナルは、ユーザが最近のファイルを選択したときに発生し、引数としてファイルの絶対パスを渡します。

注: RecentFileMenu は、親ウィジェットか、コンストラクタに渡されたRecentFiles オブジェクトによって破棄されます。

class RecentFileMenu : public QMenu
{
    Q_OBJECT

public:
    explicit RecentFileMenu(QWidget *parent, RecentFiles *recent);

signals:
    void fileOpened(const QString &fileName);
    ...
};

プロジェクト例 @ code.qt.io

©2024 The Qt Company Ltd. 本文書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。