Beispiel für einen einfachen Text-Viewer

Verwendung von Qt Assistant als angepasster Hilfe-Viewer für Ihre Anwendung.

Dieses Beispiel zeigt, wie man Qt Assistant als benutzerdefinierten Hilfe-Viewer in einer benutzerdefinierten Anwendung verwenden kann. Dies geschieht in zwei Schritten. Erstens wird die Dokumentation erstellt und Qt Assistant angepasst; zweitens wird der Anwendung die Funktionalität zum Starten und Steuern von Qt Assistant hinzugefügt.

Mit der Anwendung Simple Text Viewer kann der Benutzer vorhandene Dateien auswählen und anzeigen. Die Anwendung stellt eine eigene Dokumentation zur Verfügung, die über das Menü " Hilfe" in der Menüleiste des Hauptfensters oder durch Anklicken der Schaltfläche " Hilfe" im Dateisuchdialog der Anwendung aufgerufen werden kann.

Das Beispiel besteht aus vier Klassen:

  • Assistant bietet die Funktionalität zum Starten von Qt Assistant.
  • MainWindow ist das Hauptfenster der Anwendung.
  • FindFileDialog ermöglicht es dem Benutzer, mit Hilfe von Platzhaltern nach Dateien zu suchen.
  • TextEdit bietet einen Rich-Text-Browser, der sicherstellt, dass Bilder, auf die in HTML-Dokumenten verwiesen wird, korrekt angezeigt werden.

Hinweis: Wir werden nur die Teile der Implementierung kommentieren, die für das Hauptproblem relevant sind, d.h. Qt Assistant als angepassten Hilfe-Viewer für unsere Simple Text Viewer Anwendung zu verwenden.

Dokumentation erstellen und anpassen Qt Assistant

Wie man die eigentliche Dokumentation in Form von HTML-Seiten erstellt, ist nicht Gegenstand dieses Beispiels. Im Allgemeinen können HTML-Seiten entweder von Hand geschrieben oder mit Hilfe von Dokumentationswerkzeugen wie qdoc oder Doxygen erstellt werden. Für die Zwecke dieses Beispiels gehen wir davon aus, dass die HTML-Dateien bereits erstellt worden sind. Das Einzige, was noch getan werden muss, ist Qt Assistant mitzuteilen, wie die Hilfeinformationen strukturiert und angezeigt werden sollen.

Organisieren der Dokumentation für Qt Assistant

Einfache HTML-Dateien enthalten nur Text oder Dokumentation zu bestimmten Themen, aber in der Regel keine Informationen darüber, wie sich mehrere HTML-Dokumente zueinander verhalten oder in welcher Reihenfolge sie gelesen werden sollen. Was fehlt, ist ein Inhaltsverzeichnis und ein Index, um schnell auf bestimmte Hilfeinhalte zugreifen zu können, ohne viele Dokumente durchforsten zu müssen, um eine bestimmte Information zu finden.

Um die Dokumentation zu organisieren und für Qt Assistant verfügbar zu machen, müssen wir eine Qt-Hilfe-Projektdatei (.qhp) erstellen. Der erste und wichtigste Teil der Projektdatei ist die Definition des Namespace. Der Namespace muss eindeutig sein und wird der erste Teil der Seiten-URL in Qt Assistant sein. Zusätzlich müssen wir einen virtuellen Ordner festlegen, der als gemeinsamer Ordner für Dokumentations-Sets dient. Das bedeutet, dass zwei Dokumentationsgruppen, die durch zwei verschiedene Namensräume identifiziert werden, auf HTML-Dateien verweisen können, da sich diese Dateien in einem großen virtuellen Ordner befinden. In diesem Beispiel wird jedoch nur eine Dokumentationsgruppe zur Verfügung stehen, so dass der Name des virtuellen Ordners und seine Funktionalität nicht wichtig sind.

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

Der nächste Schritt besteht darin, den Filterabschnitt zu definieren. Ein Filterabschnitt enthält das Inhaltsverzeichnis, Indizes und eine vollständige Liste aller Dokumentationsdateien und kann mit einer beliebigen Anzahl von Filterattributen versehen werden. Ein Filterattribut ist eine gewöhnliche Zeichenkette, die frei gewählt werden kann. Später in Qt Assistant können Benutzer dann einen benutzerdefinierten Filter definieren, der sich auf diese Attribute bezieht. Wenn die Attribute eines Filterabschnitts mit den Attributen des benutzerdefinierten Filters übereinstimmen, wird die Dokumentation angezeigt, andernfalls blendet Qt Assistant die Dokumentation aus.

Da wir auch hier nur eine Dokumentation haben werden, benötigen wir die Filterfunktion von Qt Assistant nicht und können daher die Filterattribute weglassen.

Nun bauen wir das Inhaltsverzeichnis auf. Ein Element in der Tabelle wird durch den Tag section definiert, der die Attribute für den Titel des Elements sowie den Link zur eigentlichen Seite enthält. Abschnitts-Tags können unbegrenzt verschachtelt werden, aber aus praktischen Gründen ist es nicht empfehlenswert, sie tiefer als drei oder vier Ebenen zu verschachteln. Für unser Beispiel wollen wir die folgende Gliederung für das Inhaltsverzeichnis verwenden:

  • Einfacher Textbetrachter
    • Datei suchen
      • Datei-Dialog
      • Wildcard-Übereinstimmung
      • Durchsuchen
    • Datei öffnen

In der Hilfeprojektdatei wird die Gliederung durch dargestellt:

<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>

Nachdem das Inhaltsverzeichnis definiert ist, werden wir alle Index-Schlüsselwörter auflisten:

<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>

Als letzten Schritt müssen wir alle Dateien auflisten, aus denen die Dokumentation besteht. Ein wichtiger Punkt ist, dass alle Dateien aufgelistet werden müssen, einschließlich der Bilddateien und sogar der Stylesheets, wenn sie verwendet werden.

    <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>

Die Hilfe-Projektdatei ist nun fertig. Wenn Sie die resultierende Dokumentation in Qt Assistant sehen wollen, müssen Sie daraus eine komprimierte Qt-Hilfedatei erzeugen und diese in der Standard-Hilfe-Sammlung von Qt Assistant registrieren.

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

Wenn Sie nun Qt Assistant starten, sehen Sie die Simple Text Viewer Dokumentation neben der Qt Dokumentation. Dies ist für Testzwecke in Ordnung, aber für die endgültige Version wollen wir nur die Simple Text Viewer Dokumentation in Qt Assistant haben.

Anpassen von Qt Assistant

Der einfachste Weg, Qt Assistant dazu zu bringen, nur die Dokumentation des Simple Text Viewers anzuzeigen, ist, eine eigene Hilfesammlungsdatei zu erstellen. Eine Sammeldatei wird in einem Binärformat gespeichert, ähnlich wie die komprimierte Hilfedatei, und aus einer Hilfesammlungsprojektdatei (*.qhcp) erzeugt. Mit Hilfe einer Sammlungsdatei können wir das Aussehen und sogar einige der von Qt Assistant angebotenen Funktionen anpassen.

Als erstes ändern wir den Fenstertitel und das Symbol. Anstelle von "Qt Assistant" wird "Simple Text Viewer" angezeigt, so dass es für den Benutzer viel klarer ist, dass der Hilfebetrachter tatsächlich zu unserer Anwendung gehört.

<?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>

Das Tag cacheDirectory gibt ein Unterverzeichnis des Datenverzeichnisses des Benutzers an (siehe Qt Help Sammeldateien), in dem die Cachedatei für die Volltextsuche oder die Einstellungsdatei gespeichert werden soll.

Danach legen wir die Seite fest, die von Qt Assistant beim ersten Start in der neuen Konfiguration angezeigt wird. Die URL besteht aus dem Namespace und dem virtuellen Ordner, die in der Qt Help-Projektdatei definiert sind, gefolgt von dem eigentlichen Dateinamen der Seite.

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

Als nächstes ändern wir den Namen des Menüpunkts "Über" in "Über den Simple Text Viewer". Der Inhalt des About-Dialogs wird ebenfalls geändert, indem eine Datei angegeben wird, aus der der About-Text oder das Icon entnommen wird.

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

Qt Assistant bietet die Möglichkeit, Dokumentation über den Einstellungsdialog hinzuzufügen oder zu entfernen. Diese Funktion ist hilfreich, wenn Qt Assistant als zentraler Hilfebetrachter für mehrere Anwendungen verwendet wird, aber in unserem Fall wollen wir den Benutzer daran hindern, die Dokumentation zu entfernen. Daher blenden wir die Registerkarte "Dokumentation" im Dialogfeld " Voreinstellungen " aus.

Da die Adressleiste bei einer so kleinen Dokumentation nicht wirklich relevant ist, schalten wir sie ebenfalls aus. Da wir nur einen Filterabschnitt ohne Filterattribute haben, können wir auch die Filterfunktionalität von Qt Assistant deaktivieren, was bedeutet, dass die Filterseite und die Filtersymbolleiste nicht verfügbar sind.

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

Zu Testzwecken haben wir bereits die komprimierte Hilfedatei erzeugt und sie in der Standard-Hilfesammlung von Qt Assistant registriert. Mit den folgenden Zeilen erreichen wir das gleiche Ergebnis. Der einzige und wichtige Unterschied ist, dass wir die komprimierte Hilfedatei nicht in der Standardsammlung, sondern in unserer eigenen Sammlungsdatei registrieren.

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

Als letzten Schritt müssen wir die binäre Sammlungsdatei aus der Projektdatei der Hilfesammlung erzeugen. Dazu führen wir das Tool qhelpgenerator aus.

qhelpgenerator simpletextviewer.qhcp -o simpletextviewer.qhc

Um alle Anpassungen, die wir an Qt Assistant vorgenommen haben, zu testen, fügen wir den Namen der Sammlungsdatei in die Befehlszeile ein:

assistant -collectionFile simpletextviewer.qhc

Steuerung von Qt Assistant über die Assistenten-Klasse

Zunächst sehen wir uns an, wie man Qt Assistant von einer entfernten Anwendung aus starten und bedienen kann. Zu diesem Zweck erstellen wir eine Klasse namens Assistant.

Diese Klasse bietet eine öffentliche Funktion, die zum Anzeigen von Seiten der Dokumentation verwendet wird, und eine private Hilfsfunktion, die sicherstellt, dass Qt Assistant gestartet ist und läuft.

Der Start von Qt Assistant erfolgt in der Funktion startAssistant() durch einfaches Erstellen und Starten eines QProcess. Wenn der Prozess bereits läuft, kehrt die Funktion sofort zurück. Andernfalls muss der Prozess eingerichtet und gestartet werden.

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;
}

Zum Starten des Prozesses benötigen wir den Namen der ausführbaren Datei Qt Assistant sowie die Kommandozeilenargumente für die Ausführung von Qt Assistant in einem angepassten Modus. Der Name der ausführbaren Datei ist ein wenig knifflig, da er von der Plattform abhängt, aber glücklicherweise ist er nur unter macOS anders.

Die angezeigte Dokumentation kann mit dem Befehlszeilenargument -collectionFile beim Starten von Qt Assistant geändert werden. Wenn das Programm ohne Optionen gestartet wird, zeigt Qt Assistant einen Standardsatz an Dokumentation an. Wenn Qt installiert ist, enthält die Standarddokumentation in Qt Assistant die Qt-Referenzdokumentation sowie die Werkzeuge, die mit Qt geliefert werden, wie Qt Designer und qmake.

In unserem Beispiel ersetzen wir die Standarddokumentation durch unsere eigene Dokumentation, indem wir unsere anwendungsspezifische Sammeldatei an die Kommandozeilenoptionen des Prozesses übergeben.

Als letztes Argument fügen wir -enableRemoteControl hinzu, was Qt Assistant veranlasst, seinen Kanal stdin auf Befehle abzuhören, z. B. um eine bestimmte Seite in der Dokumentation anzuzeigen. Dann starten wir den Prozess und warten, bis er tatsächlich ausgeführt wird. Wenn Qt Assistant aus irgendeinem Grund nicht gestartet werden kann, gibt startAssistant() false zurück.

Die Implementierung für showDocumentation() ist nun einfach. Zunächst stellen wir sicher, dass Qt Assistant läuft, dann senden wir die Anfrage zur Anzeige von page über den Kanal stdin des Prozesses. Dabei ist es sehr wichtig, dass der Befehl durch ein Zeilenende-Token abgeschlossen wird, um den Kanal zu leeren.

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');
}

Schließlich stellen wir sicher, dass Qt Assistant ordnungsgemäß beendet wird, falls die Anwendung heruntergefahren wird. Der Destruktor von QProcess beendet den Prozess, was bedeutet, dass die Anwendung keine Möglichkeit hat, Dinge wie das Speichern von Benutzereinstellungen zu tun, was zu beschädigten Einstellungsdateien führen würde. Um dies zu vermeiden, bitten wir Qt Assistant, sich im Destruktor der Klasse Assistant zu beenden.

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-Klasse

Die Klasse MainWindow stellt das Hauptanwendungsfenster mit zwei Menüs zur Verfügung: Mit dem Menü File kann der Benutzer eine vorhandene Datei öffnen und ansehen, während das Menü Help Informationen über die Anwendung und über Qt liefert und den Benutzer Qt Assistant öffnen lässt, um die Dokumentation der Anwendung anzuzeigen.

Um auf die Hilfefunktionalität zugreifen zu können, initialisieren wir das Objekt Assistant im Konstruktor von MainWindow.

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

Dann erstellen wir alle Aktionen für die Anwendung Simple Text Viewer. Von besonderem Interesse ist die Aktion assistantAct, die über die Tastenkombination F1 oder den Menüpunkt Hilfe > Hilfeinhalt zugänglich ist. Diese Aktion ist mit dem Slot showDocumentation() der Klasse MainWindow verbunden.

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

Im Slot showDocumentation() rufen wir die Funktion showDocumentation() der Klasse Assistant mit der URL der Homepage der Dokumentation auf.

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

Schließlich müssen wir den geschützten QWidget::closeEvent()-Ereignishandler reimplementieren, um sicherzustellen, dass die Instanz Qt Assistant der Anwendung ordnungsgemäß geschlossen wird, bevor wir die Anwendung beenden.

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

FindFileDialog Klasse

Die Anwendung Simple Text Viewer bietet einen Dateisuchdialog, der es dem Benutzer ermöglicht, mit Hilfe von Platzhaltern nach Dateien zu suchen. Die Suche wird innerhalb des angegebenen Verzeichnisses durchgeführt, und der Benutzer hat die Möglichkeit, das vorhandene Dateisystem zu durchsuchen, um das entsprechende Verzeichnis zu finden.

Im Konstruktor speichern wir die Verweise auf die als Argumente übergebenen Objekte Assistant und QTextEdit. Das Objekt Assistant wird im Slot help() von FindFileDialog verwendet, wie wir gleich sehen werden, während QTextEdit im Slot openFile() des Dialogs verwendet wird, um die ausgewählte Datei anzuzeigen.

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

Das wichtigste Mitglied der Klasse FindFileDialog ist der private Slot help(). Der Slot ist mit der Hilfe-Schaltfläche des Dialogs verbunden und bringt die aktuelle Instanz Qt Assistant mit der Dokumentation für den Dialog in den Vordergrund, indem er die Funktion showDocumentation() von Assistant aufruft.

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

Zusammenfassung

Damit Qt Assistant als benutzerdefiniertes Hilfewerkzeug für Ihre Anwendung fungieren kann, müssen Sie Ihrer Anwendung einen Prozess zur Verfügung stellen, der Qt Assistant zusätzlich zu einer benutzerdefinierten Hilfesammlungsdatei mit komprimierten Qt-Hilfedateien steuert.

Weitere Informationen zu den Optionen und Einstellungen, die Anwendungen zur Verfügung stehen, die Qt Assistant als benutzerdefinierten Hilfe-Viewer verwenden, finden Sie unter Anpassen Qt Assistant.

Beispielprojekt @ 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.