Трентон Шульц |
Qt предлагает много способов обеспечения оперативной помощи, которые включают в себя советы, сообщения типа "Что это?" и доступ к программе-помощнику Qt Assistant. Иногда мы хотим обеспечить больше помощи для определенного виджета, чем может предложить сообщение "Что это?", и нам хочется предоставить пользователю помощь, не вынуждая его искать или пролистывать страницу для этого. Решение проблемы - обеспечить контекстно-зависимую помощь для текущего виджета.
В этой статье мы представляем класс HelpClient. Этот класс обеспечивает механизм для соотношения виджетов с файлами помощи. Класс также имеет фильтр события, который он использует, чтобы обнаружить, когда пользователь просит помощи (например, нажатием F1) и обратиться к Qt Assistant с соответствующим файлом помощи. Давайте начнем с определения HelpClient:
typedef QMap<QWidget *, QString> HelpMap; class HelpClient : public QObject { Q_OBJECT public: HelpClient(QObject *parent, const char *name = 0); void installHelpFiles(HelpMap helpMap); protected: bool eventFilter(QObject *obj, QEvent *event); private slots: void handleError(const QString &msg); private: QAssistantClient *mClient; HelpMap mHelpMap; };
Код включает оператор typedef для предоставления нам отображения QWidget * -> QString. Класс HelpClient использует класс QAssistantClient, который обеспечивает интерфейс Qt Assistant. QAssistantClient реализован в отдельной библиотекей, так что вы должны добавить следующую строку к вашему .pro файлу таким образом, чтобы ваша система могла найти его:
LIBS += -lqassistantclient
Теперь мы готовы посмотреть на выполнение HelpClient
const QString AssistantPath = "/usr/X11R6/bin";
Чтобы запустить Qt Assistant, мы должны знать, где он находится. Здесь мы указываем путь, но его можно легко найти в QSettings и установить при первой инсталляции приложения.
HelpClient::HelpClient(QObject *parent, const char *name) : QObject(parent, name) { parent->installEventFilter(this); mClient = new QAssistantClient(AssistantPath, this); connect(mClient, SIGNAL(error(const QString&)), this, SLOT(handleError(const QString &))); }
В конструкторе HelpClient устанавливает себя как фильтр события на его родителе. Это означает, что каждое событие, которое отослано родителю, должно сразу пройти через нашу функцию HelpClient::eventfilter(), на которую мы обратим внимаение позже. Остальная часть конструктора имеет дело с инициализацией QAssistantClient. QAssistantClient берет путь к Qt Assistant как его первый аргумент и родитель QObject как его второй аргумент. Как всегда в Qt, QAssistantClient будет удален, когда его родитель удален. Мы также делаем связь между сигналом QAssistantClient's error () и нашим собственным handleError() слотом.
void HelpClient::handleError(const QString &msg) { QMessageBox::information(0, tr("Error"), msg); }
Эта функция более полезна для отладки.
void HelpClient::installHelpFiles(HelpMap helpMap) { mHelpMap = helpMap; }
Функция installHelpFiles() простая. Теперь давайте посмотрим на фильтр события, который обеспечивает основу функциональности.
bool HelpClient::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::KeyPress) { QKeyEvent *ke = static_cast<QKeyEvent *>(event); if (ke->key() == Key_F1 || ke->key() == Key_Help) { QWidget *widget = 0; QString page = "index.html"; if (obj->isWidgetType()) widget = static_cast<QWidget *>(obj)-> focusWidget(); HelpMap::const_iterator it = mHelpMap.find(widget); if (it != mHelpMap.constEnd()) page = *it; mClient->showPage(qApp->applicationDirPath() + "/help/" + page); return true; } } return false; }
Функция eventFilter() принимает значение QEvent, и QObject, которому назначено событие. Она возвращает булевское значение, что должно быть сделано с событием по окончании функции.
Начнем с проверки типа события. Если это нажатие клавиши (KeyPress), мы относим его к KeyEvent. Затем мы должны удостовериться, что это клавиша F1 (стандартная клавиша помощи) или Help (специальная клавиша для Mac и Sparc). Если нажата клавиша помощи, мы проверяем, является ли объект, который получит событие, виджетом, и если это так, мы вызываем focuswidget(). Focuswidget() используется как клавиша для вызова нужной страницы из HelpMap. Если подходящего виджета нет, возвращаемся на страницу index.html. В случае, если есть страница для отображения, обращаемся к HelpClient::showPage(),который запускает Qt Assistant с подходящей страницы. Предполагается, что help-файлы приложения находятся в подкаталоге help каталога, где находятся данные приложения.
Обычно мы вызываем accept() или ignore() по событию QKeyEvent, чтобы определить, должно ли распространяться событие, но в фильтре события возвращаем значение true или false, чтобы указать Qt необходимое действие. В случае нажатия клавиши помощи мы возвращаем значение true, чтобы указать Qt, что мы обработали это событие, так что оно не должно передаваться дальше; в противном случае возвращаем значение false, которое заставляет Qt продолжать поиск событий.
Использование HelpClient |
Как использовать HelpClient. Мы просто создаем объект HelpClient в каждом виджете, где мы хотим обеспечить помощь, и передаем в HelpMap, которая связывает производные виджеты с help-файлами. Предположим, например, что мы хотим обеспечить помощь для конфигурационного диалога, такого, как приведенный ниже.
Чтобы использовать HelpClient, мы просто включаем helpclient.h и создаем HelpMap в конструкторе виджета или функции init().
#include "helpclient.h" void ConfigureForm::init() { HelpClient *helpClient = new HelpClient(this); HelpMap hMap; hMap.insert(helpButton, "config.html"); hMap.insert(okButton, "config.html"); hMap.insert(cancelButton, "config.html"); hMap.insert(saveCheckBox, "config.html#save"); hMap.insert(restoreCheckBox, "config.html#restore"); hMap.insert(clipboardCheckBox, "config.html#clipboard"); hMap.insert(webButton, "browser.html"); hMap.insert(emailButton, "email.html"); helpClient->installHelpFiles(hMap); }
В случае с флагами (checkbox) мы должны внести информацию-помощь в тот же самый файл и использовать стандартный HTML # синтаксис, (например, ) в help-файле.
Заметьте, что для того, чтобы это хорошо работало, все виджеты должны иметь StrongFocus или WheelFocus. Это гарантирует, что табуляция или щелчок мышью на виджете и нажатие F1 обеспечит контекстно-зависимую помощь.
Предлагаемые улучшения |
HelpClient полезен и в том виде, в котором он есть, но есть некоторые возможности, на которые вы могли бы обратить внимание:
Copyright © 2003 Trolltech | Trademarks |