26#if defined (HAVE_CONFIG_H)
31#include <QApplication>
33#include <QDesktopServices>
37#include <QHelpContentWidget>
38#include <QHelpIndexWidget>
39#if defined (HAVE_NEW_QHELPINDEXWIDGET_API) \
40 || defined (HAVE_QHELPENGINE_DOCUMENTSFORIDENTIFIER)
43#include <QHelpSearchEngine>
44#include <QHelpSearchQueryWidget>
45#include <QHelpSearchResultWidget>
71 m_octave_qobj (oct_qobj), m_doc_widget (this),
72 m_tool_bar (new QToolBar (this)),
73 m_query_string (QString ()),
75 m_current_ref_name (QString ()),
76 m_prev_pages_menu (new
QMenu (this)),
77 m_next_pages_menu (new
QMenu (this)),
78 m_prev_pages_count (0),
79 m_next_pages_count (0),
80 m_findnext_shortcut (new QShortcut (this)),
81 m_findprev_shortcut (new QShortcut (this))
84 QString collection = getenv (
"OCTAVE_QTHELP_COLLECTION");
85 if (collection.isEmpty ())
88 +
"octave_interpreter.qhc");
97 QVariant::fromValue<bool> (
true));
99 QString tmpdir = QDir::tempPath();
113 tr (
"Could not copy help collection to temporary\n"
114 "file. Search capabilities may be affected.\n"
118 connect(
m_help_engine->searchEngine (), SIGNAL(indexingFinished ()),
121 m_help_engine->searchEngine (), SLOT(reindexDocumentation ()));
127 tr (
"Could not setup the data required for the\n"
128 "documentation viewer. Only help texts in\n"
129 "the Command Window will be available."));
141 connect (
m_doc_browser, &documentation_browser::cursorPositionChanged,
149 QLabel *find_label =
new QLabel (tr (
"Find:"), find_footer);
152 this, [=] () {
find (); });
156 forward_button->setText (tr (
"Search forward"));
157 forward_button->setToolTip (tr (
"Search forward"));
159 forward_button->setIcon (rmgr.
icon (
"go-down"));
160 connect (forward_button, &QToolButton::pressed,
161 this, [=] () {
find (); });
163 backward_button->setText (tr (
"Search backward"));
164 backward_button->setToolTip (tr (
"Search backward"));
165 backward_button->setIcon (rmgr.
icon (
"go-up"));
166 connect (backward_button, &QToolButton::pressed,
168 QHBoxLayout *h_box_find_footer =
new QHBoxLayout (find_footer);
169 h_box_find_footer->addWidget (find_label);
171 h_box_find_footer->addWidget (forward_button);
172 h_box_find_footer->addWidget (backward_button);
173 h_box_find_footer->setMargin (2);
174 find_footer->setLayout (h_box_find_footer);
176 QVBoxLayout *v_box_browser_find =
new QVBoxLayout (browser_find);
179 v_box_browser_find->addWidget (find_footer);
180 browser_find->setLayout (v_box_browser_find);
186 this, [=] () {
find (); });
191 find_footer->hide ();
196#if defined (HAVE_NEW_QHELPINDEXWIDGET_API)
202 navi->setTabsClosable (
false);
203 navi->setMovable (
true);
206 QHelpContentWidget *content =
m_help_engine->contentWidget ();
207 content->setObjectName (
"documentation_tab_contents");
208 navi->addTab (content, tr (
"Contents"));
211 &QHelpContentWidget::linkActivated,
213 m_doc_browser->handle_index_clicked (url); });
219 m_filter->setToolTip (tr (
"Enter text to search the indices"));
221 m_filter->setInsertPolicy (QComboBox::NoInsert);
224 m_filter->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon);
225 QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred);
227 m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive);
231 QHBoxLayout *h_box_index =
new QHBoxLayout (filter_all);
232 h_box_index->addWidget (filter_label);
234 h_box_index->setMargin (2);
235 filter_all->setLayout (h_box_index);
238 index_all->setObjectName (
"documentation_tab_index");
239 QVBoxLayout *v_box_index =
new QVBoxLayout (index_all);
240 v_box_index->addWidget (filter_all);
241 v_box_index->addWidget (index);
242 index_all->setLayout (v_box_index);
244 navi->addTab (index_all, tr (
"Function Index"));
246#if defined (HAVE_NEW_QHELPINDEXWIDGET_API)
248 &QHelpIndexWidget::documentActivated,
249 this, [=] (
const QHelpLink &
link) {
250 m_doc_browser->handle_index_clicked (link.url); });
253 &QHelpIndexWidget::linkActivated,
257 connect (
m_filter, &QComboBox::editTextChanged,
260 connect (
m_filter->lineEdit (), &QLineEdit::editingFinished,
272 QHelpSearchEngine *search_engine =
m_help_engine->searchEngine ();
273 QHelpSearchQueryWidget *
search = search_engine->queryWidget ();
274 QHelpSearchResultWidget *result = search_engine->resultWidget ();
276 QVBoxLayout *v_box_search =
new QVBoxLayout (search_all);
277 v_box_search->addWidget (
search);
278 v_box_search->addWidget (result);
279 search_all->setLayout (v_box_search);
280 search_all->setObjectName (
"documentation_tab_search");
281 navi->addTab (search_all, tr (
"Search"));
286 connect (search_engine, &QHelpSearchEngine::searchingStarted,
288 connect (search_engine, &QHelpSearchEngine::searchingFinished,
291 connect (search_engine->resultWidget (),
292 &QHelpSearchResultWidget::requestShowLink,
296 insertWidget (0, navi);
297 insertWidget (1, browser_find);
298 setStretchFactor (1, 1);
308 QFileInfo finfo (file);
309 QString bname = finfo.fileName ();
310 QDir dir = finfo.absoluteDir ();
311 dir.setFilter (QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden);
312 QStringList namefilter;
313 namefilter.append (
"*" + bname +
"*");
314 for (
const auto&
fi : dir.entryInfoList (namefilter))
316 std::string file_name =
fi.absoluteFilePath ().toStdString ();
325 const char *member,
QWidget *receiver,
330 if (receiver !=
nullptr)
333 a =
new QAction (icon, text,
this);
336 connect (a, SIGNAL (triggered ()), r, member);
339 tool_bar->addAction (a);
342 a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
352 =
add_action (rmgr.
icon (
"go-home"), tr (
"Go home"), SLOT (home (
void)),
362 popdown_button_prev_pages->setToolTip (tr (
"Previous pages"));
364 popdown_button_prev_pages->setPopupMode (QToolButton::InstantPopup);
365 popdown_button_prev_pages->setToolButtonStyle (Qt::ToolButtonTextOnly);
366 popdown_button_prev_pages->setCheckable (
false);
367 popdown_button_prev_pages->setArrowType(Qt::DownArrow);
368 m_tool_bar->addWidget (popdown_button_prev_pages);
377 popdown_button_next_pages->setToolTip (tr (
"Next pages"));
379 popdown_button_next_pages->setPopupMode (QToolButton::InstantPopup);
380 popdown_button_next_pages->setToolButtonStyle (Qt::ToolButtonTextOnly);
381 popdown_button_next_pages->setArrowType(Qt::DownArrow);
382 m_tool_bar->addWidget (popdown_button_next_pages);
384 connect (
m_doc_browser, &documentation_browser::backwardAvailable,
386 connect (
m_doc_browser, &documentation_browser::backwardAvailable,
387 popdown_button_prev_pages, &QToolButton::setEnabled);
388 connect (
m_doc_browser, &documentation_browser::forwardAvailable,
390 connect (
m_doc_browser, &documentation_browser::forwardAvailable,
391 popdown_button_next_pages, &QToolButton::setEnabled);
392 connect (
m_doc_browser, &documentation_browser::historyChanged,
432 =
add_action (rmgr.
icon (
"bookmark-new"), tr (
"Bookmark current page"),
441 QString query_string;
442#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
444 =
m_help_engine->searchEngine ()->queryWidget ()->searchInput ();
445 query_string = queries;
450 if (queries.count ())
451 query_string = queries.first ().wordList.join (
" ");
456 if (query_string.isEmpty ())
460 QRegExp rx (
"\"([^\"]*)\"");
461 if (rx.indexIn (query_string, 0) != -1)
464#if defined (HAVE_QT_SPLITBEHAVIOR_ENUM)
475 qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
487 QHelpSearchEngine *search_engine =
m_help_engine->searchEngine ();
490#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
491 QVector<QHelpSearchResult> res
492 = search_engine->searchResults (0, search_engine->searchResultCount ());
495 = search_engine->hits (0, search_engine->hitCount ());
502 if (res.count () == 1)
503#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
504 url = res.front ().url ();
506 url = res.front ().first;
513 for (
auto r = res.begin (); r != res.end (); r++)
515#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
516 QString title = r->title ().toLower ();
517 QUrl tmpurl = r->url ();
519 QString title = r->second.toLower ();
520 QUrl tmpurl = r->first;
522 if (title.contains (search_string.toLower ()))
524 if (title.indexOf (search_string.toLower ()) == 0)
529 else if (url.isEmpty ())
535 if (! url.isEmpty ())
548 qApp->restoreOverrideCursor();
573 QTextDocument::FindBackward));
580 QPalette pal = QApplication::palette ();
582 QColor col = pal.color (QPalette::Highlight);
583 col.setAlphaF (0.25);
584 format.setBackground (QBrush (col));
585 format.setForeground (QBrush (pal.color (QPalette::Text)));
594 QTextEdit::ExtraSelection selected_item;
596 selected_item.format =
format;
597 selected.append (selected_item);
614 size_idx = (size_idx > 0) - (size_idx < 0) + 1;
616 QStyle *st = style ();
618 m_tool_bar->setIconSize (QSize (icon_size, icon_size));
666 (QUrl (
"qthelp://org.octave.interpreter-1.0/doc/octave.html/index.html"));
683#if defined (HAVE_QHELPENGINE_DOCUMENTSFORIDENTIFIER)
693 if (found_links.count() > 0)
696#if defined (HAVE_QHELPENGINE_DOCUMENTSFORIDENTIFIER)
697 QUrl first_url = found_links.constFirst().url;
699 QUrl first_url = found_links.constBegin().value ();
707 = navi->findChild<
QWidget *> (
"documentation_tab_index");
708 navi->setCurrentWidget (index_tab);
713 QHelpSearchEngine *search_engine =
m_help_engine->searchEngine ();
714 QHelpSearchQueryWidget *search_query = search_engine->queryWidget ();
716#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
717 QString query = ref_name;
718 query.prepend (
"\"").append (
"\"");
721 query << QHelpSearchQuery (QHelpSearchQuery::DEFAULT,
722 QStringList (QString(
"\"") + ref_name + QString(
"\"")));
725 search_engine->search (query);
728#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
729 search_query->setSearchInput (query);
731 search_query->setQuery (query);
734 = navi->findChild<
QWidget *> (
"documentation_tab_search");
735 navi->setCurrentWidget (search_tab);
760 if (expression.contains (QLatin1Char(
'*')))
761 wildcard = expression;
763 m_help_engine->indexWidget ()->filterIndices(expression, wildcard);
768 QString text =
m_filter->currentText ();
769 int index =
m_filter->findText (text);
788 QTextDocument::FindFlags find_flags;
790 find_flags = QTextDocument::FindBackward;
797 textcur.movePosition (QTextCursor::End);
799 textcur.movePosition (QTextCursor::Start);
820 textcur.movePosition (QTextCursor::Start);
848 bool do_setup =
true;
849 if (
m_help_engine->registeredDocumentations ().contains (ns))
862 tr (
"Unable to register help file %1.").
919 for (
int i = 0; i < count; i++)
928 actions[i]->setText (title);
929 actions[i]->setData (
m_doc_browser->historyUrl (prev_next*(i+1)));
930 actions[i]->setEnabled (
true);
931 actions[i]->setVisible (
true);
937 actions[j]->setEnabled (
false);
938 actions[j]->setVisible (
false);
951 QString retval = title;
952 QString u = url.toString ();
954 retval.remove (QRegExp (
"\\s*\\(*GNU Octave \\(version [^\\)]*\\)[: \\)]*"));
959 if (u.contains (
'#'))
962 QString anchor = u.split (
'#').last ();
964 anchor.remove (QRegExp (
"^index-"));
965 anchor.remove (QRegExp (
"^SEC_"));
966 anchor.remove (QRegExp (
"^XREF"));
967 anchor.remove (
"Concept-Index_cp_letter-");
968 anchor.replace (
"-",
" ");
971 QRegExp rx = QRegExp (
"_00([0-7][0-9a-f])");
973 while ((pos = rx.indexIn(anchor, pos)) != -1)
975 anchor.replace (
"_00"+rx.cap (1), QChar (rx.cap (1).toInt (
nullptr, 16)));
976 pos += rx.matchedLength();
979 if (retval != anchor)
980 retval = retval +
": " + anchor;
993 :
QTextBrowser (p), m_help_engine (he), m_zoom_level (max_zoom_level+1)
995 setOpenLinks (
false);
996 connect (
this, &documentation_browser::anchorClicked,
1003 if (url.scheme () ==
"qthelp")
1006 QDesktopServices::openUrl (url);
1024 return QTextBrowser::loadResource(type, url);
1060 if (
we->modifiers () == Qt::ControlModifier)
1062#if defined (HAVE_QWHEELEVENT_ANGLEDELTA)
1063 if (
we->angleDelta().y () > 0)
1065 if (
we->delta() > 0)
1074 QTextEdit::wheelEvent (
we);
Base class for Octave interfaces that use Qt.
shortcut_manager & get_shortcut_manager(void)
resource_manager & get_resource_manager(void)
void save_settings(gui_settings *settings)
Documentation browser derived from Textbrowser.
void zoom_original(void)
Zooming in and out while taking care of the zoom level.
void zoom_out(void)
Zooming in and out while taking care of the zoom level.
QHelpEngine * m_help_engine
int m_zoom_level
Store the current zoom level.
void handle_index_clicked(const QUrl &url, const QString &keyword=QString())
void zoom_in(void)
Zooming in and out while taking care of the zoom level.
void save_settings(gui_settings *settings)
void notice_settings(const gui_settings *settings)
documentation_browser(QHelpEngine *help_engine, QWidget *parent=nullptr)
virtual QVariant loadResource(int type, const QUrl &url)
void wheelEvent(QWheelEvent *we)
QAction * m_action_go_next
QString title_and_anchor(const QString &title, const QUrl &url)
void filter_update_history(void)
documentation(QWidget *parent, base_qobject &oct_qobj)
void filter_update(const QString &expression)
void load_ref(const QString &name=QString())
QShortcut * m_findprev_shortcut
QMenu * m_prev_pages_menu
void find_forward_from_anchor(const QString &text)
void global_search_started(void)
int m_search_anchor_position
QHelpEngine * m_help_engine
QAction * m_action_zoom_out
QAction * m_prev_pages_actions[max_history_entries]
QAction * m_next_pages_actions[max_history_entries]
documentation_browser * m_doc_browser
void construct_tool_bar(void)
base_qobject & m_octave_qobj
void handle_search_result_clicked(const QUrl &url)
QShortcut * m_findnext_shortcut
void pasteClipboard(void)
QString m_current_ref_name
void update_history_menus(void)
void handle_cursor_position_change(void)
void record_anchor_position(void)
QAction * m_action_zoom_original
QAction * m_action_go_prev
QAction * m_action_go_home
documentation_bookmarks * m_bookmarks
QMenu * m_next_pages_menu
QAction * m_action_bookmark
QAction * add_action(const QIcon &icon, const QString &text, const char *member, QWidget *receiver=nullptr, QToolBar *tool_bar=nullptr)
void open_hist_url(QAction *a)
QAction * m_action_zoom_in
QString m_internal_search
void update_history(int new_count, QAction **actions)
void global_search_finished(int hits)
void select_all_occurrences(const QString &text)
Select all occurrences of a string in the doc browser.
void find(bool backward=false)
void show_single_result(const QUrl &)
void notice_settings(const gui_settings *settings)
QLineEdit * m_find_line_edit
void registerDoc(const QString &name)
void unregisterDoc(const QString &name)
gui_settings * get_settings(void) const
QIcon icon(const QString &icon_name, bool fallback=true)
void set_shortcut(QAction *action, const sc_pref &scpref, bool enable=true)
void shortcut(QShortcut *sc, const sc_pref &scpref)
static octave_idx_type link(octave_idx_type s, octave_idx_type t, octave_idx_type *pp)
void warning(const char *fmt,...)
const gui_pref dc_browser_zoom_level("documentation_widget/browser_zoom_level", QVariant(0))
const QStyle::PixelMetric global_icon_sizes[3]
const gui_pref global_icon_size("toolbar_icon_size", QVariant(0))
const sc_pref sc_doc_go_home(sc_doc+":go_home", Qt::AltModifier+Qt::Key_Home)
const sc_pref sc_doc_go_back(sc_doc+":go_back", QKeySequence::Back)
const sc_pref sc_edit_view_zoom_normal(sc_edit_view_zoom+"_normal", CTRL+Qt::Key_Period)
const sc_pref sc_edit_edit_find_replace(sc_edit_edit_find+"_replace", QKeySequence::Find)
const sc_pref sc_doc_bookmark(sc_doc+":bookmark", CTRL+Qt::Key_D)
const sc_pref sc_edit_edit_find_next(sc_edit_edit_find+"_next", QKeySequence::FindNext)
const sc_pref sc_edit_edit_find_previous(sc_edit_edit_find+"_previous", QKeySequence::FindPrevious)
const sc_pref sc_edit_view_zoom_in(sc_edit_view_zoom+"_in", QKeySequence::ZoomIn)
const sc_pref sc_doc_go_next(sc_doc+":go_next", QKeySequence::Forward)
const sc_pref sc_edit_view_zoom_out(sc_edit_view_zoom+"_out", QKeySequence::ZoomOut)
static std::list< std::string > search(const std::string &path, const std::string &original_name, bool all)
std::string oct_doc_dir(void)
QString fromStdString(const std::string &s)
std::string dir_sep_str(void)
std::string tempnam(const std::string &dir, const std::string &pfx)
int recursive_rmdir(const std::string &name)
std::size_t format(std::ostream &os, const char *fmt,...)