26 #if defined (HAVE_CONFIG_H)
31 #include <QApplication>
33 #include <QDesktopServices>
37 #include <QFontDatabase>
38 #include <QHelpContentWidget>
39 #include <QHelpIndexWidget>
40 #if defined (HAVE_NEW_QHELPINDEXWIDGET_API) \
41 || defined (HAVE_QHELPENGINE_DOCUMENTSFORIDENTIFIER)
44 #include <QHelpSearchEngine>
45 #include <QHelpSearchQueryWidget>
46 #include <QHelpSearchResultWidget>
49 #include <QMessageBox>
52 #include <QVBoxLayout>
72 m_octave_qobj (oct_qobj), m_doc_widget (this),
73 m_tool_bar (new QToolBar (this)),
74 m_query_string (QString ()),
76 m_current_ref_name (QString ()),
77 m_prev_pages_menu (new
QMenu (this)),
78 m_next_pages_menu (new
QMenu (this)),
79 m_prev_pages_count (0),
80 m_next_pages_count (0),
81 m_findnext_shortcut (new QShortcut (this)),
82 m_findprev_shortcut (new QShortcut (this))
85 QString collection = getenv (
"OCTAVE_QTHELP_COLLECTION");
86 if (collection.isEmpty ())
89 +
"octave_interpreter.qhc");
93 m_help_engine =
new QHelpEngine (collection,
this);
97 m_help_engine->setProperty (
"_q_readonly",
98 QVariant::fromValue<bool> (
true));
105 if (m_help_engine->copyCollectionFile (m_collection))
106 m_help_engine->setCollectionFile (m_collection);
114 tr (
"Could not copy help collection to temporary\n"
115 "file. Search capabilities may be affected.\n"
116 "%1").arg (m_help_engine->error ()));
119 connect(m_help_engine->searchEngine (), SIGNAL(indexingFinished ()),
120 this, SLOT(load_index ()));
121 connect(m_help_engine, SIGNAL(setupFinished ()),
122 m_help_engine->searchEngine (), SLOT(reindexDocumentation ()));
124 if (! m_help_engine->setupData())
128 tr (
"Could not setup the data required for the\n"
129 "documentation viewer. Only help texts in\n"
130 "the Command Window will be available."));
133 disconnect (m_help_engine, 0, 0, 0);
135 delete m_help_engine;
136 m_help_engine =
nullptr;
142 connect (m_doc_browser, &documentation_browser::cursorPositionChanged,
146 construct_tool_bar ();
150 QLabel *find_label =
new QLabel (tr (
"Find:"), find_footer);
151 m_find_line_edit =
new QLineEdit (find_footer);
152 connect (m_find_line_edit, &QLineEdit::returnPressed,
153 this, [=] () {
find (); });
154 connect (m_find_line_edit, &QLineEdit::textEdited,
157 forward_button->setText (tr (
"Search forward"));
158 forward_button->setToolTip (tr (
"Search forward"));
160 forward_button->setIcon (rmgr.
icon (
"go-down"));
161 connect (forward_button, &QToolButton::pressed,
162 this, [=] () {
find (); });
164 backward_button->setText (tr (
"Search backward"));
165 backward_button->setToolTip (tr (
"Search backward"));
166 backward_button->setIcon (rmgr.
icon (
"go-up"));
167 connect (backward_button, &QToolButton::pressed,
169 QHBoxLayout *h_box_find_footer =
new QHBoxLayout (find_footer);
170 h_box_find_footer->addWidget (find_label);
171 h_box_find_footer->addWidget (m_find_line_edit);
172 h_box_find_footer->addWidget (forward_button);
173 h_box_find_footer->addWidget (backward_button);
174 h_box_find_footer->setMargin (2);
175 find_footer->setLayout (h_box_find_footer);
177 QVBoxLayout *v_box_browser_find =
new QVBoxLayout (browser_find);
178 v_box_browser_find->addWidget (m_tool_bar);
179 v_box_browser_find->addWidget (m_doc_browser);
180 v_box_browser_find->addWidget (find_footer);
181 browser_find->setLayout (v_box_browser_find);
185 m_findnext_shortcut->setContext (Qt::WidgetWithChildrenShortcut);
186 connect (m_findnext_shortcut, &QShortcut::activated,
187 this, [=] () {
find (); });
188 m_findprev_shortcut->setContext (Qt::WidgetWithChildrenShortcut);
189 connect (m_findprev_shortcut, &QShortcut::activated,
192 find_footer->hide ();
193 m_search_anchor_position = 0;
197 #if defined (HAVE_NEW_QHELPINDEXWIDGET_API)
199 m_help_engine->setUsesFilterEngine (
true);
203 navi->setTabsClosable (
false);
204 navi->setMovable (
true);
207 QHelpContentWidget *content = m_help_engine->contentWidget ();
208 content->setObjectName (
"documentation_tab_contents");
209 navi->addTab (content, tr (
"Contents"));
211 connect (m_help_engine->contentWidget (),
212 &QHelpContentWidget::linkActivated,
213 m_doc_browser, [=] (
const QUrl& url) {
214 m_doc_browser->handle_index_clicked (url); });
217 QHelpIndexWidget *index = m_help_engine->indexWidget ();
219 m_filter =
new QComboBox (
this);
220 m_filter->setToolTip (tr (
"Enter text to search the indices"));
221 m_filter->setEditable (
true);
222 m_filter->setInsertPolicy (QComboBox::NoInsert);
223 m_filter->setMaxCount (10);
224 m_filter->setMaxVisibleItems (10);
225 m_filter->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon);
226 QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred);
227 m_filter->setSizePolicy (sizePol);
228 m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive);
232 QHBoxLayout *h_box_index =
new QHBoxLayout (filter_all);
233 h_box_index->addWidget (filter_label);
234 h_box_index->addWidget (m_filter);
235 h_box_index->setMargin (2);
236 filter_all->setLayout (h_box_index);
239 index_all->setObjectName (
"documentation_tab_index");
240 QVBoxLayout *v_box_index =
new QVBoxLayout (index_all);
241 v_box_index->addWidget (filter_all);
242 v_box_index->addWidget (index);
243 index_all->setLayout (v_box_index);
245 navi->addTab (index_all, tr (
"Function Index"));
247 #if defined (HAVE_NEW_QHELPINDEXWIDGET_API)
248 connect (m_help_engine->indexWidget (),
249 &QHelpIndexWidget::documentActivated,
250 this, [=] (
const QHelpLink &
link) {
251 m_doc_browser->handle_index_clicked (link.url); });
253 connect (m_help_engine->indexWidget (),
254 &QHelpIndexWidget::linkActivated,
258 connect (m_filter, &QComboBox::editTextChanged,
261 connect (m_filter->lineEdit (), &QLineEdit::editingFinished,
267 navi->addTab (m_bookmarks, tr (
"Bookmarks"));
269 connect (m_action_bookmark, &QAction::triggered,
270 m_bookmarks, [=] () { m_bookmarks->add_bookmark (); });
273 QHelpSearchEngine *search_engine = m_help_engine->searchEngine ();
274 QHelpSearchQueryWidget *
search = search_engine->queryWidget ();
275 QHelpSearchResultWidget *result = search_engine->resultWidget ();
277 QVBoxLayout *v_box_search =
new QVBoxLayout (search_all);
278 v_box_search->addWidget (
search);
279 v_box_search->addWidget (result);
280 search_all->setLayout (v_box_search);
281 search_all->setObjectName (
"documentation_tab_search");
282 navi->addTab (search_all, tr (
"Search"));
287 connect (search_engine, &QHelpSearchEngine::searchingStarted,
289 connect (search_engine, &QHelpSearchEngine::searchingFinished,
292 connect (search_engine->resultWidget (),
293 &QHelpSearchResultWidget::requestShowLink,
297 insertWidget (0, navi);
298 insertWidget (1, browser_find);
299 setStretchFactor (1, 1);
309 QFileInfo finfo (file);
310 QString bname = finfo.fileName ();
311 QDir dir = finfo.absoluteDir ();
312 dir.setFilter (QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden);
313 QStringList namefilter;
314 namefilter.append (
"*" + bname +
"*");
315 for (
const auto&
fi : dir.entryInfoList (namefilter))
317 std::string file_name =
fi.absoluteFilePath ().toStdString ();
326 const char *member,
QWidget *receiver,
331 if (receiver !=
nullptr)
334 a =
new QAction (icon, text,
this);
337 connect (a, SIGNAL (triggered ()),
r, member);
340 tool_bar->addAction (a);
343 a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
353 =
add_action (rmgr.
icon (
"go-home"), tr (
"Go home"), SLOT (home (
void)),
363 popdown_button_prev_pages->setToolTip (tr (
"Previous pages"));
365 popdown_button_prev_pages->setPopupMode (QToolButton::InstantPopup);
366 popdown_button_prev_pages->setToolButtonStyle (Qt::ToolButtonTextOnly);
367 popdown_button_prev_pages->setCheckable (
false);
368 popdown_button_prev_pages->setArrowType(Qt::DownArrow);
369 m_tool_bar->addWidget (popdown_button_prev_pages);
378 popdown_button_next_pages->setToolTip (tr (
"Next pages"));
380 popdown_button_next_pages->setPopupMode (QToolButton::InstantPopup);
381 popdown_button_next_pages->setToolButtonStyle (Qt::ToolButtonTextOnly);
382 popdown_button_next_pages->setArrowType(Qt::DownArrow);
383 m_tool_bar->addWidget (popdown_button_next_pages);
385 connect (
m_doc_browser, &documentation_browser::backwardAvailable,
387 connect (
m_doc_browser, &documentation_browser::backwardAvailable,
388 popdown_button_prev_pages, &QToolButton::setEnabled);
389 connect (
m_doc_browser, &documentation_browser::forwardAvailable,
391 connect (
m_doc_browser, &documentation_browser::forwardAvailable,
392 popdown_button_next_pages, &QToolButton::setEnabled);
393 connect (
m_doc_browser, &documentation_browser::historyChanged,
427 =
add_action (rmgr.
icon (
"view-zoom-original"), tr (
"Zoom original"),
433 =
add_action (rmgr.
icon (
"bookmark-new"), tr (
"Bookmark current page"),
442 QString query_string;
443 #if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
445 =
m_help_engine->searchEngine ()->queryWidget ()->searchInput ();
446 query_string = queries;
451 if (queries.count ())
452 query_string = queries.first ().wordList.join (
" ");
457 if (query_string.isEmpty ())
461 QRegExp rx (
"\"([^\"]*)\"");
462 if (rx.indexIn (query_string, 0) != -1)
465 #if defined (HAVE_QT_SPLITBEHAVIOR_ENUM)
476 qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
488 QHelpSearchEngine *search_engine =
m_help_engine->searchEngine ();
491 #if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
492 QVector<QHelpSearchResult> res
493 = search_engine->searchResults (0, search_engine->searchResultCount ());
496 = search_engine->hits (0, search_engine->hitCount ());
503 if (res.count () == 1)
504 #if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
505 url = res.front ().url ();
507 url = res.front ().first;
514 for (
auto r = res.begin ();
r != res.end ();
r++)
516 #if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
517 QString title =
r->title ().toLower ();
518 QUrl tmpurl =
r->url ();
520 QString title =
r->second.toLower ();
521 QUrl tmpurl =
r->first;
523 if (title.contains (search_string.toLower ()))
525 if (title.indexOf (search_string.toLower ()) == 0)
530 else if (url.isEmpty ())
536 if (! url.isEmpty ())
549 qApp->restoreOverrideCursor();
574 QTextDocument::FindBackward));
581 QPalette pal = QApplication::palette ();
583 QColor col = pal.color (QPalette::Highlight);
584 col.setAlphaF (0.25);
585 format.setBackground (QBrush (col));
586 format.setForeground (QBrush (pal.color (QPalette::Text)));
595 QTextEdit::ExtraSelection selected_item;
597 selected_item.format =
format;
598 selected.append (selected_item);
615 size_idx = (size_idx > 0) - (size_idx < 0) + 1;
617 QStyle *st = style ();
619 m_tool_bar->setIconSize (QSize (icon_size, icon_size));
667 (QUrl (
"qthelp://org.octave.interpreter-1.0/doc/octave.html/index.html"));
684 #if defined (HAVE_QHELPENGINE_DOCUMENTSFORIDENTIFIER)
694 if (found_links.count() > 0)
697 #if defined (HAVE_QHELPENGINE_DOCUMENTSFORIDENTIFIER)
698 QUrl first_url = found_links.constFirst().url;
700 QUrl first_url = found_links.constBegin().value ();
708 = navi->findChild<
QWidget *> (
"documentation_tab_index");
709 navi->setCurrentWidget (index_tab);
714 QHelpSearchEngine *search_engine =
m_help_engine->searchEngine ();
715 QHelpSearchQueryWidget *search_query = search_engine->queryWidget ();
717 #if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
718 QString query = ref_name;
719 query.prepend (
"\"").append (
"\"");
722 query << QHelpSearchQuery (QHelpSearchQuery::DEFAULT,
723 QStringList (QString(
"\"") + ref_name + QString(
"\"")));
726 search_engine->search (query);
729 #if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
730 search_query->setSearchInput (query);
732 search_query->setQuery (query);
735 = navi->findChild<
QWidget *> (
"documentation_tab_search");
736 navi->setCurrentWidget (search_tab);
761 if (expression.contains (QLatin1Char(
'*')))
762 wildcard = expression;
764 m_help_engine->indexWidget ()->filterIndices(expression, wildcard);
769 QString text =
m_filter->currentText ();
770 int index =
m_filter->findText (text);
789 QTextDocument::FindFlags find_flags;
791 find_flags = QTextDocument::FindBackward;
798 textcur.movePosition (QTextCursor::End);
800 textcur.movePosition (QTextCursor::Start);
821 textcur.movePosition (QTextCursor::Start);
849 bool do_setup =
true;
850 if (
m_help_engine->registeredDocumentations ().contains (ns))
863 tr (
"Unable to register help file %1.").
920 for (
int i = 0; i < count; i++)
929 actions[i]->setText (title);
930 actions[i]->setData (
m_doc_browser->historyUrl (prev_next*(i+1)));
931 actions[i]->setEnabled (
true);
932 actions[i]->setVisible (
true);
938 actions[j]->setEnabled (
false);
939 actions[j]->setVisible (
false);
952 QString retval = title;
953 QString u = url.toString ();
955 retval.remove (QRegExp (
"\\s*\\(*GNU Octave \\(version [^\\)]*\\)[: \\)]*"));
960 if (u.contains (
'#'))
963 QString anchor = u.split (
'#').last ();
965 anchor.remove (QRegExp (
"^index-"));
966 anchor.remove (QRegExp (
"^SEC_"));
967 anchor.remove (QRegExp (
"^XREF"));
968 anchor.remove (
"Concept-Index_cp_letter-");
969 anchor.replace (
"-",
" ");
972 QRegExp rx = QRegExp (
"_00([0-7][0-9a-f])");
974 while ((pos = rx.indexIn(anchor, pos)) != -1)
976 anchor.replace (
"_00"+rx.cap (1), QChar (rx.cap (1).toInt (
nullptr, 16)));
977 pos += rx.matchedLength();
980 if (retval != anchor)
981 retval = retval +
": " + anchor;
992 :
QTextBrowser (p), m_help_engine (he), m_zoom_level (max_zoom_level+1)
994 setOpenLinks (
false);
995 connect (
this, &documentation_browser::anchorClicked,
1000 QStringList fonts = {
"Fantasque Sans Mono",
"FreeMono",
"Courier New",
1001 "Cousine",
"Courier"};
1003 bool load_default_font =
true;
1005 for (
int i = 0; i < fonts.size (); ++i)
1007 QFont font (fonts.at (i));
1008 if (font.exactMatch ())
1010 load_default_font =
false;
1015 if (load_default_font)
1021 QStringList default_fonts = {
"FreeMono",
"FreeMonoBold",
1022 "FreeMonoBoldOblique",
"FreeMonoOblique"};
1024 for (
int i = 0; i < default_fonts.size (); ++i)
1027 fonts_dir + default_fonts.at(i) + QString (
".otf");
1028 QFontDatabase::addApplicationFont (fontpath);
1036 if (url.scheme () ==
"qthelp")
1039 QDesktopServices::openUrl (url);
1057 return QTextBrowser::loadResource(type, url);
1093 if (
we->modifiers () == Qt::ControlModifier)
1095 #if defined (HAVE_QWHEELEVENT_ANGLEDELTA)
1096 if (
we->angleDelta().y () > 0)
1098 if (
we->delta() > 0)
1107 QTextEdit::wheelEvent (
we);
Base class for Octave interfaces that use Qt.
resource_manager & get_resource_manager(void)
shortcut_manager & get_shortcut_manager(void)
void save_settings(gui_settings *settings)
Documentation browser derived from Textbrowser.
documentation_browser(QHelpEngine *help_engine, QWidget *parent=nullptr)
void zoom_out(void)
Zooming in and out while taking care of the zoom level.
void save_settings(gui_settings *settings)
void wheelEvent(QWheelEvent *we)
void zoom_in(void)
Zooming in and out while taking care of the zoom level.
int m_zoom_level
Store the current zoom level.
virtual QVariant loadResource(int type, const QUrl &url)
QHelpEngine * m_help_engine
void notice_settings(const gui_settings *settings)
void zoom_original(void)
Zooming in and out while taking care of the zoom level.
void handle_index_clicked(const QUrl &url, const QString &keyword=QString())
The documentation main class derived from QSplitter.
QAction * m_action_zoom_out
void pasteClipboard(void)
void find_forward_from_anchor(const QString &text)
QAction * m_action_go_next
void select_all_occurrences(const QString &text)
Select all occurrences of a string in the doc browser.
void show_single_result(const QUrl &)
QShortcut * m_findprev_shortcut
QAction * m_action_go_prev
void find(bool backward=false)
QString m_current_ref_name
QAction * m_action_zoom_original
documentation_bookmarks * m_bookmarks
void global_search_finished(int hits)
QLineEdit * m_find_line_edit
QMenu * m_prev_pages_menu
QAction * m_action_bookmark
void notice_settings(const gui_settings *settings)
QString title_and_anchor(const QString &title, const QUrl &url)
int m_search_anchor_position
void record_anchor_position(void)
QString m_internal_search
base_qobject & m_octave_qobj
void handle_search_result_clicked(const QUrl &url)
QAction * add_action(const QIcon &icon, const QString &text, const char *member, QWidget *receiver=nullptr, QToolBar *tool_bar=nullptr)
void update_history_menus(void)
void open_hist_url(QAction *a)
void load_ref(const QString &name=QString())
QHelpEngine * m_help_engine
void filter_update(const QString &expression)
QShortcut * m_findnext_shortcut
void handle_cursor_position_change(void)
QAction * m_action_zoom_in
documentation_browser * m_doc_browser
QAction * m_action_go_home
void unregisterDoc(const QString &name)
void filter_update_history(void)
void global_search_started(void)
void registerDoc(const QString &name)
QAction * m_next_pages_actions[max_history_entries]
QMenu * m_next_pages_menu
void update_history(int new_count, QAction **actions)
void construct_tool_bar(void)
QAction * m_prev_pages_actions[max_history_entries]
gui_settings * get_settings(void) const
QIcon icon(const QString &icon_name, bool octave_only=false, const QString &icon_alt_name=QString())
void set_shortcut(QAction *action, const sc_pref &scpref, bool enable=true)
void shortcut(QShortcut *sc, const sc_pref &scpref)
static octave_idx_type find(octave_idx_type i, octave_idx_type *pp)
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
std::string oct_doc_dir(void)
void warning(const char *fmt,...)
std::string tempnam(const std::string &dir, const std::string &pfx)
int link(const std::string &old_name, const std::string &new_name)
std::string dir_sep_str(void)
int recursive_rmdir(const std::string &name)
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)
static std::string get_temp_directory(void)
QString fromStdString(const std::string &s)
std::size_t format(std::ostream &os, const char *fmt,...)