シンプルなテキストビューアの例

Qt Assistant をアプリケーションのカスタマイズヘルプビューアとして使用する。

この例では、Qt Assistant をカスタムアプリケーションのカスタマイズヘルプビューアとして使用する方法を示します。これは2つの段階で行われます。まず、ドキュメントを作成し、Qt Assistant をカスタマイズします。次に、Qt Assistant を起動し、制御する機能をアプリケーションに追加します。

Simple Text Viewerアプリケーションは、ユーザーが既存のファイルを選択して閲覧できるようにします。このアプリケーションは、メインウィンドウのメニューバーの「ヘルプ」メニューから、またはアプリケーションのファイル検索ダイアログの「ヘルプ」ボタンをクリックすることで、独自のカスタムドキュメントを提供します。

このサンプルは4つのクラスで構成されています:

  • Assistant は、 を起動する機能を提供します。Qt Assistant
  • MainWindow はメイン・アプリケーション・ウィンドウです。
  • FindFileDialog ワイルドカードを使ってファイルを検索します。
  • TextEdit HTML ドキュメントで参照される画像が適切に表示されるようにするリッチテキストブラウザを提供します。

注意: ここでは、Qt Assistant をシンプル・テキスト・ビューワー・アプリケーション用にカスタマイズされたヘルプ・ビューワーとして動作させるという、主要な問題に関連する実装部分についてのみコメントします。

ドキュメントの作成とカスタマイズQt Assistant

HTMLページの形で実際のドキュメントを作成する方法は、この例の範囲ではありません。一般的に、HTMLページは手で書くか、qdocやDoxygenのようなドキュメントツールの助けを借りて生成することができます。この例では、HTMLファイルはすでに作成されていると仮定します。したがって、あとはQt Assistant 、ヘルプ情報の構成と表示方法を指示するだけです。

ドキュメントの整理Qt Assistant

プレーンなHTMLファイルには、特定のトピックに関するテキストやドキュメントが含まれているだけで、通常、複数のHTMLドキュメントが互いにどのように関連しているか、どの順番で読むことになっているかといった情報は含まれていません。欠けているのは、情報の一部を見つけるために多くのドキュメントをブラウズすることなく、特定のヘルプ・コンテンツに素早くアクセスするための索引と目次です。

ドキュメントを整理し、Qt Assistant 、Qt Helpプロジェクト(.qhp)ファイルを作成する必要があります。プロジェクトファイルの最初の、そして最も重要な部分は、名前空間の定義です。名前空間は一意でなければならず、Qt Assistant のページURLの最初の部分になります。さらに、ドキュメントセットの共通フォルダとして機能する仮想フォルダを設定する必要があります。これは、2つの異なる名前空間で識別される2つのドキュメント・セットが、1つの大きな仮想フォルダーにあるため、HTMLファイルを相互参照できることを意味します。しかし、この例では、利用可能なドキュメント・セットは1つだけなので、仮想フォルダーの名前と機能は重要ではありません。

<?xml version="1.0" encoding="UTF-8"?>
<QtHelpProject version="1.0">
  <namespace>org.qt-project.examples.simpletextviewer</namespace>
  <virtualFolder>doc</virtualFolder>

次のステップは、フィルター・セクションを定義することです。フィルター・セクションには、目次、インデックス、すべてのドキュメント・ファイルの完全なリストが含まれ、任意の数のフィルター属性を割り当てることができます。フィルター属性は、自由に選択できる普通の文字列です。Qt Assistant 、ユーザーはこれらの属性を参照するカスタム・フィルターを定義することができます。フィルター・セクションの属性がカスタム・フィルターの属性と一致すれば、ドキュメントが表示されます。そうでなければ、Qt Assistant 、ドキュメントは非表示になります。

繰り返しになりますが、ドキュメント・セットは1つしかないので、Qt Assistant のフィルタリング機能は必要なく、したがってフィルタ属性は省略できます。

さて、目次を作りましょう。テーブルのアイテムは、section タグによって定義されます。このタグには、アイテムのタイトルと実際のページへのリンクの属性が含まれています。セクション・タグは無限に入れ子にすることができますが、実際的な理由から、3、4レベルより深く入れ子にすることは推奨されません。この例では、目次に次のようなアウトラインを使いたいと思います:

  • シンプル・テキスト・ビューア
    • ファイル検索
      • ファイルダイアログ
      • ワイルドカード・マッチング
      • ブラウズ
    • ファイルを開く

ヘルプ・プロジェクト・ファイルでは、アウトラインは次のように表されます:

<filterSection>
  <toc>
    <section title="Simple Text Viewer" ref="index.html">
      <section title="Find File" ref="findfile.html">
        <section title="File Dialog" ref="filedialog.html"/>
        <section title="Wildcard Matching" ref="wildcardmatching.html"/>
        <section title="Browse" ref="browse.html"/>
      </section>
      <section title="Open File" ref="openfile.html"/>
    </section>
  </toc>

目次が定義されたら、すべての索引キーワードをリストアップします:

<keywords>
  <keyword name="Display" ref="index.html"/>
  <keyword name="Rich text" ref="index.html"/>
  <keyword name="Plain text" ref="index.html"/>
  <keyword name="Find" ref="findfile.html"/>
  <keyword name="File menu" ref="findfile.html"/>
  <keyword name="File name" ref="filedialog.html"/>
  <keyword name="File dialog" ref="filedialog.html"/>
  <keyword name="File globbing" ref="wildcardmatching.html"/>
  <keyword name="Wildcard matching" ref="wildcardmatching.html"/>
  <keyword name="Wildcard syntax" ref="wildcardmatching.html"/>
  <keyword name="Browse" ref="browse.html"/>
  <keyword name="Directory" ref="browse.html"/>
  <keyword name="Open" ref="openfile.html"/>
  <keyword name="Select" ref="openfile.html"/>
</keywords>

最後のステップとして、ドキュメントを構成するすべてのファイルをリストアップしなければなりません。ここで注意すべき重要な点は、画像ファイルや、スタイルシートが使われている場合はそれも含めて、すべてのファイルをリストアップしなければならないということです。

    <files>
      <file>browse.html</file>
      <file>filedialog.html</file>
      <file>findfile.html</file>
      <file>index.html</file>
      <file>intro.html</file>
      <file>openfile.html</file>
      <file>wildcardmatching.html</file>
      <file>images/browse.png</file>
      <file>images/fadedfilemenu.png</file>
      <file>images/filedialog.png</file>
      <file>images/handbook.png</file>
      <file>images/mainwindow.png</file>
      <file>images/open.png</file>
      <file>images/wildcard.png</file>
    </files>
  </filterSection>
</QtHelpProject>

これでヘルププロジェクトファイルは完成です。出来上がったドキュメントをQt Assistant で見たい場合は、Qt圧縮ヘルプファイルを生成し、Qt Assistant のデフォルトヘルプコレクションに登録する必要があります。

qhelpgenerator simpletextviewer.qhp -o simpletextviewer.qch
assistant -register simpletextviewer.qch

Qt Assistant を起動すると、Qt ドキュメントの横に Simple Text Viewer ドキュメントが表示されます。これはテスト目的であれば問題ありませんが、最終バージョンではQt Assistant にシンプルテキストビューアのドキュメントだけを表示させたいと思います。

カスタマイズQt Assistant

Qt Assistant にシンプルテキストビューアのドキュメントだけを表示させる最も簡単な方法は、独自のヘルプコレクションファイルを作成することです。コレクションファイルは圧縮されたヘルプファイルに似たバイナリ形式で保存され、ヘルプコレクションプロジェクトファイル(*.qhcp)から生成されます。コレクションファイルの助けを借りて、Qt Assistant で提供される外観やいくつかの機能をカスタマイズすることができます。

まず、ウィンドウのタイトルとアイコンを変更します。Qt Assistant" を表示する代わりに、"Simple Text Viewer" を表示することで、ヘルプビューアが実際に我々のアプリケーションに属していることが、ユーザーにとってより明確になります。

<?xml version="1.0" encoding="UTF-8"?>
<QHelpCollectionProject version="1.0">
<assistant>
    <title>Simple Text Viewer</title>
    <applicationIcon>images/handbook.png</applicationIcon>
    <cacheDirectory>QtProject/SimpleTextViewer</cacheDirectory>

cacheDirectory タグは、全文検索用のキャッシュファイルや設定ファイルが保存されるユーザーデータディレクトリのサブディレクトリを指定します(Qt Help Collection Filesを参照)。

この後、Qt Assistant が初めて起動したときに表示されるページを、新しい設定で設定します。URL は、Qt Help プロジェクトファイルで定義された名前空間と仮想フォルダ、そして実際のページファイル名で構成されます。

<startPage>qthelp://org.qt-project.examples.simpletextviewer/doc/index.html</startPage>

次に、"About "メニュー項目の名前を "About Simple Text Viewer "に変更します。aboutダイアログの内容も、aboutテキストやアイコンの元となるファイルを指定することで変更されます。

<aboutMenuText>
    <text>About Simple Text Viewer</text>
</aboutMenuText>
<aboutDialog>
    <file>about.txt</file>
    <icon>images/icon.png</icon>
</aboutDialog>

Qt Assistant は、環境設定ダイアログを使って、ドキュメントを追加したり削除したりすることができます。この機能は、 をより多くのアプリケーションの中心的なヘルプビューアとして使用する場合に便利ですが、私たちのケースでは、ユーザーがドキュメントを削除できないようにしたいのです。そこで、Qt Assistant 環境設定ダイアログの「ドキュメント」タブを非表示にします。

アドレスバーは、このような小さなドキュメントのセットにはあまり関係ないので、これもオフにします。フィルター属性を持たないフィルターセクションを1つだけ持つことで、Qt Assistant のフィルター機能を無効にすることもできます。

    <enableDocumentationManager>false</enableDocumentationManager>
    <enableAddressBar>false</enableAddressBar>
    <enableFilterFunctionality>false</enableFilterFunctionality>
</assistant>

テスト用に、圧縮ヘルプ・ファイルを生成し、Qt Assistant のデフォルト・ヘルプ・コレクションに登録しました。次の行で、同じ結果が得られます。唯一の重要な違いは、圧縮ヘルプ・ファイルをデフォルト・コレクションではなく、独自のコレクション・ファイルに登録することです。

  <docFiles>
    <generate>
        <file>
            <input>simpletextviewer.qhp</input>
            <output>simpletextviewer.qch</output>
            </file>
        </generate>
    <register>
        <file>simpletextviewer.qch</file>
        </register>
    </docFiles>
</QHelpCollectionProject>

最後のステップとして、ヘルプ・コレクション・プロジェクト・ファイルからバイナリ・コレクション・ファイルを生成する必要があります。これは、qhelpgenerator ツールを実行して行います。

qhelpgenerator simpletextviewer.qhcp -o simpletextviewer.qhc

Qt Assistant で行ったすべてのカスタマイズをテストするために、コマンドラインにコ レクションファイル名を追加します:

assistant -collectionFile simpletextviewer.qhc

アシスタント・クラスによるQt Assistant の制御

まず、リモート・アプリケーションからQt Assistant を起動して操作する方法を見ていきます。そのために、Assistant というクラスを作成します。

このクラスは、ドキュメントのページを表示するためのパブリック関数と、Qt Assistant が起動していることを確認するためのプライベート・ヘルパー関数を提供します。

Qt Assistant の起動は、startAssistant() 関数の中で、単に QProcess を作成して起動することで行います。プロセスがすでに実行されている場合、関数はすぐに戻ります。そうでない場合は、プロセスをセットアップして開始する必要があります。

bool Assistant::startAssistant()
{
    if (m_process.isNull()) {
        m_process.reset(new QProcess);
        QObject::connect(m_process.data(), &QProcess::finished,
                         m_process.data(), [this](int exitCode, QProcess::ExitStatus status) {
            finished(exitCode, status);
        });
    }

    if (m_process->state() != QProcess::Running) {
        QString app = QLibraryInfo::path(QLibraryInfo::BinariesPath);
#ifndef Q_OS_DARWIN
        app += "/assistant"_L1;
#else
        app += "/Assistant.app/Contents/MacOS/Assistant"_L1;
#endif

        const QString collectionDirectory = documentationDirectory();
        if (collectionDirectory.isEmpty()) {
            showError(tr("The documentation directory cannot be found"));
            return false;
        }

        const QStringList args{"-collectionFile"_L1,
                               collectionDirectory + "/simpletextviewer.qhc"_L1,
                               "-enableRemoteControl"_L1};

        m_process->start(app, args);

        if (!m_process->waitForStarted(3000)) {
            showError(tr("Unable to launch Qt Assistant (%1): %2")
                      .arg(QDir::toNativeSeparators(app), m_process->errorString()));
            return false;
        }
    }
    return true;
}

プロセスを開始するには、Qt Assistant の実行ファイル名と、Qt Assistant をカスタマイズモードで実行するためのコマンドライン引数が必要です。実行可能ファイル名はプラットフォームに依存するため少し厄介ですが、幸いmacOSでのみ異なります。

表示されるドキュメントは、Qt Assistant を起動する際に-collectionFile コマンドライン引数を使用して変更できます。オプションなしで起動すると、Qt Assistant はデフォルトのドキュメントを表示します。Qt がインストールされている場合、Qt Assistant のデフォルト・ドキュメント・セットには、Qt のリファレンス・ドキュメントと、Qt Designerqmake のような Qt に付属するツールが含まれています。

この例では、プロセスのコマンドラインオプションにアプリケーション固有のコレクションファイルを渡すことで、デフォルトのドキュメントセットをカスタムドキュメントに置き換えます。

最後の引数として、-enableRemoteControl を追加し、Qt Assistantstdin チャンネルをリッスンし、ドキュメントの特定のページを表示するなどのコマンドを受け付けるようにします。それからプロセスを開始し、実際に実行されるまで待ちます。何らかの理由でQt Assistant が開始できない場合、startAssistant() はfalseを返します。

showDocumentation() の実装は簡単である。まず、Qt Assistant が実行中であることを確認し、そのプロセスのstdin チャンネル経由で、page を表示するリクエストを送信する。ここで非常に重要なのは、コマンドを行末トークンで終了させ、チャンネルをフラッシュすることである。

void Assistant::showDocumentation(const QString &page)
{
    if (!startAssistant())
        return;

    QByteArray ba("SetSource ");
    ba.append("qthelp://org.qt-project.examples.simpletextviewer/doc/");

    m_process->write(ba + page.toLocal8Bit() + '\n');
}

最後に、アプリケーションがシャットダウンされた場合にQt Assistant が適切に終了するようにします。QProcessのデストラクタはプロセスを終了させますが、これはアプリケーションがユーザー設定を保存するようなことができないことを意味します。これを避けるために、Assistant クラスのデストラクタでQt Assistant を終了するようにします。

Assistant::~Assistant()
{
    if (!m_process.isNull() && m_process->state() == QProcess::Running) {
        QObject::disconnect(m_process.data(), &QProcess::finished, nullptr, nullptr);
        m_process->terminate();
        m_process->waitForFinished(3000);
    }
}

MainWindowクラス

MainWindow Fileメニューでは既存のファイルを開いたり見たりすることができ、HelpメニューではアプリケーションやQtに関する情報を提供したり、Qt Assistant を開いてアプリケーションのドキュメントを表示したりすることができます。

ヘルプ機能にアクセスできるように、MainWindow のコンストラクタでAssistant オブジェクトを初期化します。

MainWindow::MainWindow()
    : textViewer(new TextEdit)
    , assistant(new Assistant)
{
    ...
}

それから、Simple Text Viewerアプリケーションのすべてのアクションを作成します。特に興味深いのは、F1ショートカットやHelp>Help Contentsメニュー項目からアクセスできるassistantAct アクションです。このアクションはMainWindow クラスのshowDocumentation() スロットに接続されています。

void MainWindow::createActions()
{
    assistantAct = new QAction(tr("Help Contents"), this);
    assistantAct->setShortcut(QKeySequence::HelpContents);
    connect(assistantAct, &QAction::triggered, this, &MainWindow::showDocumentation);
    ...
}

showDocumentation() スロットでは、Assistant クラスのshowDocumentation() 関数をドキュメントのホームページのURLで呼び出します。

void MainWindow::showDocumentation()
{
    assistant->showDocumentation("index.html");
}

最後に、アプリケーションを終了する前に、アプリケーションのQt Assistant インスタンスが適切に閉じられるように、保護されたQWidget::closeEvent()イベント・ハンドラを再実装する必要があります。

void MainWindow::closeEvent(QCloseEvent *)
{
    delete assistant;
}

FindFileDialog クラス

Simple Text Viewerアプリケーションは、ワイルドカードマッチングを使用してファイルを検索することができるファイル検索ダイアログを提供します。検索は指定されたディレクトリ内で実行され、ユーザには関連するディレクトリを見つけるために既存のファイルシステムをブラウズするオプションが与えられます。

コンストラクタでは、引数として渡されたAssistantQTextEdit オブジェクトへの参照を保存します。Assistant オブジェクトはFindFileDialoghelp() スロットで使用され、QTextEdit はダイアログのopenFile() スロットで使用され、選択されたファイルを表示します。

FindFileDialog::FindFileDialog(TextEdit *editor, Assistant *assistant)
    : QDialog(editor)
    , currentEditor(editor)
    , currentAssistant(assistant)
{
    ...
}

FindFileDialog クラスで最も重要なメンバは、help() のプライベートスロットです。このスロットはダイアログのヘルプボタンに接続されており、AssistantshowDocumentation() 関数を呼び出すことで、現在のQt Assistant インスタンスをダイアログのドキュメントと共にフォアグラウンドに表示します。

void FindFileDialog::help()
{
    currentAssistant->showDocumentation("filedialog.html");
}

概要

Qt Assistant をアプリケーションのカスタマイズヘルプツールとして動作させるには、Qt 圧縮ヘルプファイルを含むカスタムヘルプコレクションファイルに加え、Qt Assistant を制御するプロセスをアプリケーションに提供する必要があります。

Qt Assistant をカスタムヘルプビューアとして使用するアプリケーションで利用可能なオプションと設定の詳細については、 Qt Assistant カスタマイズを参照してください。

サンプルプロジェクト @ code.qt.io

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.