# HG changeset patch # User Jacob Dawid # Date 1343669234 -7200 # Node ID 48ae6a7c69c12ee316fb2fe69f8e702fa1a27c0b # Parent 6889217b9d786c5347ad55e9a76bbb6b629fd950 Integrated texinfo browser from QtOctave. * documentation-dockwidget.cc: Added new dock widget for the documentation. * documentation-dockwidget.h: Added new dock widget for the documentation. * bookmark.png: New icon file. * question.png: New icon file. * star.png: New icon file. * stop.png: New icon file. * zoom-in.png: New icon file. * zoom-out.png: New icon file. * parser.cc: Added file from QtOctave, refactored code. * parser.h: Added file from QtOctave, refactored code. * webinfo.cc: Added file from QtOctave, refactored code. * webinfo.h: Added file from QtOctave, refactored code. * main-window.cc: Added menu entries to handle documentation and integrated new documentation dock widget. * main-window.h: Including header for documentation dock widget and added member variable. * resource.qrc: Added icon entries for new icon files. * src.pro: Added file entries for new file added to the project. diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/documentation-dockwidget.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/src/documentation-dockwidget.cc Mon Jul 30 19:27:14 2012 +0200 @@ -0,0 +1,45 @@ +/* OctaveGUI - A graphical user interface for Octave + * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "documentation-dockwidget.h" + +documentation_dock_widget::documentation_dock_widget (QWidget *parent) + : QDockWidget (parent) +{ + setObjectName ("DocumentationDockWidget"); + setWindowTitle (tr ("Documentation")); + + connect (this, SIGNAL (visibilityChanged (bool)), + this, SLOT (handle_visibility_changed (bool))); + + _webinfo = new webinfo (this); + setWidget (_webinfo); +} + +void +documentation_dock_widget::handle_visibility_changed (bool visible) +{ + if (visible) + emit active_changed (true); +} + +void +documentation_dock_widget::closeEvent (QCloseEvent *event) +{ + emit active_changed (false); + QDockWidget::closeEvent (event); +} diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/documentation-dockwidget.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/src/documentation-dockwidget.h Mon Jul 30 19:27:14 2012 +0200 @@ -0,0 +1,45 @@ +/* OctaveGUI - A graphical user interface for Octave + * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef DOCUMENTATIONDOCKWIDGET_H +#define DOCUMENTATIONDOCKWIDGET_H + +#include +#include "webinfo.h" + +class documentation_dock_widget : public QDockWidget +{ + Q_OBJECT +public: + documentation_dock_widget (QWidget *parent = 0); + +public slots: + /** Slot to steer changing visibility from outside. */ + void handle_visibility_changed (bool visible); + +signals: + /** Custom signal that tells if a user has clicked away that dock widget. */ + void active_changed (bool active); + +protected: + void closeEvent (QCloseEvent *event); + +private: + webinfo *_webinfo; +}; + +#endif // DOCUMENTATIONDOCKWIDGET_H diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/icons/bookmark.png Binary file gui/src/icons/bookmark.png has changed diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/icons/question.png Binary file gui/src/icons/question.png has changed diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/icons/star.png Binary file gui/src/icons/star.png has changed diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/icons/stop.png Binary file gui/src/icons/stop.png has changed diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/icons/zoom-in.png Binary file gui/src/icons/zoom-in.png has changed diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/icons/zoom-out.png Binary file gui/src/icons/zoom-out.png has changed diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/main-window.cc --- a/gui/src/main-window.cc Mon Jul 30 09:55:57 2012 +0200 +++ b/gui/src/main-window.cc Mon Jul 30 19:27:14 2012 +0200 @@ -310,6 +310,19 @@ } void +main_window::focus_documentation () +{ + if (!_documentation_dock_widget->isVisible ()) + { + _documentation_dock_widget->setVisible (true); + } + + _documentation_dock_widget->setFocus (); + _documentation_dock_widget->activateWindow (); + _documentation_dock_widget->raise (); +} + +void main_window::handle_entered_debug_mode () { setWindowTitle ("Octave (Debugging)"); @@ -429,6 +442,8 @@ _history_dock_widget->setStatusTip (tr ("Browse and search the command history.")); _files_dock_widget = new files_dock_widget (this); _files_dock_widget->setStatusTip (tr ("Browse your files.")); + _documentation_dock_widget= new documentation_dock_widget (this); + _documentation_dock_widget->setStatusTip (tr ("See the documentation for help.")); _status_bar = new QStatusBar (this); _current_directory_combo_box = new QComboBox (this); @@ -639,6 +654,11 @@ show_editor_action->setCheckable (true); show_editor_action->setShortcut (Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_4); + + QAction * show_documentation_action = window_menu->addAction (tr ("Show Documentation")); + show_documentation_action->setCheckable (true); + show_documentation_action->setShortcut (Qt::ControlModifier + Qt::ShiftModifier + + Qt::Key_5); window_menu->addSeparator (); QAction * command_window_action @@ -661,6 +681,10 @@ = window_menu->addAction (tr ("Editor")); editor_action->setShortcut (Qt::ControlModifier + Qt::Key_4); + QAction * documentation_action + = window_menu->addAction (tr ("Documentation")); + documentation_action->setShortcut (Qt::ControlModifier + Qt::Key_5); + window_menu->addSeparator (); QAction * reset_windows_action = window_menu->addAction (tr ("Reset Windows")); @@ -733,6 +757,10 @@ _file_editor, SLOT (setVisible (bool))); connect (_file_editor, SIGNAL (active_changed (bool)), show_editor_action, SLOT (setChecked (bool))); + connect (show_documentation_action, SIGNAL (toggled (bool)), + _documentation_dock_widget, SLOT (setVisible (bool))); + connect (_documentation_dock_widget, SIGNAL (active_changed (bool)), + show_documentation_action, SLOT (setChecked (bool))); connect (command_window_action, SIGNAL (triggered ()), this, SLOT (focus_command_window ())); @@ -744,6 +772,8 @@ this, SLOT (focus_current_directory ())); connect (editor_action, SIGNAL (triggered ()), this, SLOT (focus_editor ())); + connect (documentation_action, SIGNAL (triggered ()), + this, SLOT (focus_documentation ())); connect (reset_windows_action, SIGNAL (triggered ()), this, SLOT (reset_windows ())); @@ -796,6 +826,7 @@ addDockWidget (Qt::RightDockWidgetArea, _files_dock_widget); addDockWidget (Qt::RightDockWidgetArea, _file_editor); addDockWidget (Qt::BottomDockWidgetArea, _terminal_dock_widget); + addDockWidget (Qt::RightDockWidgetArea, _documentation_dock_widget); setStatusBar (_status_bar); read_settings (); diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/main-window.h --- a/gui/src/main-window.h Mon Jul 30 09:55:57 2012 +0200 +++ b/gui/src/main-window.h Mon Jul 30 19:27:14 2012 +0200 @@ -44,6 +44,7 @@ #include "history-dockwidget.h" #include "files-dockwidget.h" #include "terminal-dockwidget.h" +#include "documentation-dockwidget.h" #include "octave-qt-event-listener.h" #include "octave-event-observer.h" @@ -104,6 +105,7 @@ void focus_current_directory (); void focus_workspace (); void focus_editor (); + void focus_documentation (); void handle_entered_debug_mode (); void handle_quit_debug_mode (); @@ -137,6 +139,7 @@ history_dock_widget * _history_dock_widget; files_dock_widget * _files_dock_widget; terminal_dock_widget * _terminal_dock_widget; + documentation_dock_widget*_documentation_dock_widget; // Toolbars. QStatusBar * _status_bar; diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/qtinfo/parser.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/src/qtinfo/parser.cc Mon Jul 30 19:27:14 2012 +0200 @@ -0,0 +1,578 @@ +/* Copyright (C) 2009 P.L. Lucas + * Copyright (C) 2012 Jacob Dawid + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "parser.h" +#include +#include +#include +#include +#include +#include +#include + +parser::parser(QObject *parent) + : QObject(parent) +{ + _compressors_map.insert ("bz2", "bzip2 -dc \"%1\""); + _compressors_map.insert ("gz", "gzip -dc \"%1\""); + _compressors_map.insert ("lzma", "lzma -dc \"%1\""); + _compressors_map.insert ("xz", "xz -dc \"%1\""); + _compressors_map.insert ("Z", "gunzip -c \"%1\""); +} + +void +parser::set_info_path (QString infoPath) +{ + this->_info_path = infoPath; + + _info_files.clear (); + + QFileInfo info (infoPath); + + QString path = info.absolutePath (); + QString fileName = info.fileName (); + + QDir infoDir (path); + QStringList filter; + filter.append (fileName + "*"); + + _info_files = infoDir.entryInfoList (filter, QDir::Files); + parse_info_map (); +} + +QString +parser::get_info_path () +{ + return _info_path; +} + +QIODevice * +parser::open_file (QFileInfo & file_info) +{ + QIODevice *iodevice=NULL; + if ( _compressors_map.contains(file_info.suffix ())) + { + QProcess gzip; + gzip.start (_compressors_map.value (file_info.suffix ()).arg (file_info.absoluteFilePath ())); + + if (!gzip.waitForFinished ()) + return NULL; + + QByteArray result = gzip.readAll (); + + QBuffer *io = new QBuffer (this); + io->setData (result); + + if (!io->open (QIODevice::ReadOnly | QIODevice::Text)) + return NULL; + + iodevice = io; + } + else + { + QFile *io = new QFile (file_info.absoluteFilePath ()); + if (!io->open (QIODevice::ReadOnly | QIODevice::Text)) + return NULL; + iodevice = io; + } + + return iodevice; +} + +int +parser::is_ref (QString node) +{ + if (_ref_map.contains (node)) + { + node_position ref = _ref_map [node]; + + return ref.pos-_node_map [ref._node_name].pos; + } + return -1; +} + +QString +parser::search_node (QString node) +{ + QFileInfo file_info; + QString ref; + + if (_ref_map.contains (node)) + { + ref = node; + node = _ref_map [ref]._node_name; + } + + if (_node_map.contains (node)) + { + int pos = _node_map [node].pos; + int realPos; + + real_position (pos, file_info, realPos); + + QIODevice *io = open_file (file_info); + if (io == NULL) + { + return QString (); + } + + seek (io, realPos); + + QString text = get_next_node (io); + if (!text.isEmpty()) + { + return text; + } + + io->close (); + delete io; + } + + return QString (); +} + +QString +parser::search_node (QString node, QIODevice *io) +{ + while (!io->atEnd ()) + { + QString text = get_next_node (io); + if(node == get_node_name (text)) + { + return text; + } + } + + return QString (); +} + +QString +parser::get_next_node (QIODevice *io) +{ + QString text; + while (!io->atEnd ()) + { + QByteArray line = io->readLine (); + if (line.at(0) == 31) + { + break; + } + else + { + text.append (line); + } + } + return text; +} + +static QString +get_first_line (QString text) +{ + int n = text.indexOf ("\n"); + + if (n < 0) + { + return QString (); + } + + QString first_line = text.left (n); + return first_line; +} + +static QString +parser_node (QString text, QString node_name) +{ + QString firstLine = get_first_line (text); + QStringList nodes = firstLine.split (","); + for (int i = 0;i < nodes.size (); i++) + { + QString node = nodes.at (i).trimmed (); + + if (node.startsWith (node_name)) + { + return node.remove (0, node_name.size ()).trimmed (); + } + } + return QString (); +} + +QString +parser::get_node_name (QString text) +{ + return parser_node (text, "Node:"); +} + +QString +parser::get_node_up (QString text) +{ + return parser_node (text, "Up:"); +} + +QString +parser::get_node_next (QString text) +{ + return parser_node (text, "Next:"); +} + +QString +parser::get_node_prev (QString text) +{ + return parser_node (text, "Prev:"); +} + +static void +replace_links (QString &text) +{ + QRegExp re ("(\\*[N|n]ote|\n\\*)([ |\n]+)([^:]+):([^:\\.,]*)([:,\\.])"); + int i = 0, f; + + while ( (i = re.indexIn (text,i)) != -1) + { + QString type = re.cap (1); + QString note = re.cap (3); + QString url_link = re.cap (4); + QString link = re.cap (4); + + if (url_link.isEmpty ()) + { + url_link = note; + } + + url_link = url_link.trimmed (); + url_link.replace ("\n"," "); + url_link.replace (QRegExp (" +")," "); + url_link.replace ("",""); + url_link.replace ("",""); + url_link = QUrl::toPercentEncoding (url_link, "", "'"); + + QString href; + if (type=="\n*") + { + href="\n"; + } + else + { + href=""; + } + href += re.cap (2) + "" + note + ":" + link + re.cap (5) + ""; + f = re.matchedLength (); + text.replace (i,f,href); + i += href.size (); + } +} + +static void +replace_colons (QString &text) +{ + QRegExp re ("`([^']+)'"); + int i = 0, f; + while ( (i = re.indexIn (text, i)) != -1) + { + QString t = re.cap (1); + QString bold = "`" + t + "'"; + + f = re.matchedLength (); + text.replace (i,f,bold); + i += bold.size (); + } +} + +static void +info_to_html (QString &text) +{ + text.replace ("&", "&"); + text.replace ("<", "<"); + text.replace (">", ">"); + + text.replace ("\n* Menu:", "\nMenu:"); + text.replace ("*See also:*", "See also:"); + replace_colons (text); + replace_links (text); +} + +QString +parser::node_text_to_html (QString text, int anchorPos, QString anchor) +{ + QString nodeName = get_node_name (text); + QString nodeUp = get_node_up (text); + QString nodeNext = get_node_next (text); + QString nodePrev = get_node_prev (text); + + if (anchorPos > -1) + { + QString text1 = text.left (anchorPos); + QString text2 = text.mid (anchorPos); + + int n = text1.indexOf ("\n"); + text1.remove (0, n); + + info_to_html (text1); + info_to_html (text2); + + text = text1 + "" + text2; + } + else + { + int n = text.indexOf ("\n"); + text.remove (0, n); + info_to_html (text); + } + + QString navigationLinks = QString ( + " Section: %1
" + "Previous Section:
%3
" + "Next Section: %5
" + "Up: %7
\n" + ) + .arg (nodeName) + .arg (QString (QUrl::toPercentEncoding (nodePrev, "", "'"))) + .arg (nodePrev) + .arg (QString (QUrl::toPercentEncoding (nodeNext, "", "'"))) + .arg (nodeNext) + .arg (QString (QUrl::toPercentEncoding (nodeUp, "", "'"))) + .arg (nodeUp); + + + text.prepend ("
\n
");
+  text.append ("
\n

\n"); + text.prepend (navigationLinks); + text.append (navigationLinks); + text.prepend ("\n"); + text.append ("\n"); + return text; +} + +void +parser::parse_info_map () +{ + QRegExp re ("(Node|Ref): ([^\\0177]+)\\0177(\\d+)\n"); + QRegExp re_files ("([^:]+): (\\d+)\n"); + int foundCount = 0; + + for(int i = 0; i < _info_files.size (); i++) + { + QFileInfo fileInfo = _info_files.at (i); + + QIODevice *io = open_file (fileInfo); + if (io == NULL) + { + continue; + } + + QString nodeText; + while (! (nodeText=get_next_node (io)).isEmpty () && foundCount < 2) + { + QString first_line = get_first_line (nodeText); + if (first_line.startsWith ("Tag") ) + { + foundCount++; + int pos = 0; + QString last_node; + + while ((pos = re.indexIn (nodeText, pos)) != -1) { + QString type = re.cap (1); + QString node = re.cap (2); + int index = re.cap (3).toInt (); + + if (type == "Node") + { + node_map_item item; + item.pos = index; + _node_map [node] = item; + last_node = node; + } + else if (type == "Ref") + { + node_position item; + item._node_name = last_node; + item.pos = index; + _ref_map [node] = item; + } + pos += re.matchedLength (); + } + break; + } + else if (first_line.startsWith ("Indirect:")) + { + foundCount++; + int pos = 0; + + while ( (pos = re_files.indexIn (nodeText, pos)) != -1) { + QString fileCap = re_files.cap (1).trimmed (); + int index = re_files.cap (2).toInt (); + + info_file_item item; + for (int j = 0;j < _info_files.size (); j++) + { + QFileInfo info = _info_files.at (j); + if (info.fileName ().startsWith (fileCap)) + { + item.file_info = info; + break; + } + } + item.real_size = index; + _info_file_real_size_list.append (item); + pos += re_files.matchedLength (); + } + + } + } + io->close (); + delete io; + } +} + +void +parser::real_position (int pos, QFileInfo & file_info, int & real_pos) +{ + int header = -1, sum = 0; + for (int i = 0; i < _info_file_real_size_list.size (); i++) + { + info_file_item item = _info_file_real_size_list.at (i); + if (header == -1) + { + file_info = item.file_info; + header = item.real_size; + } + + if (pos < item.real_size) + { + break; + } + + file_info = item.file_info; + sum = item.real_size; + } + real_pos = pos - sum + header + 2; +} + +void +parser::seek (QIODevice *io, int pos) +{ + char ch; + while (!io->atEnd () && pos > 0) + { + io->getChar (&ch); + pos--; + } +} + +static void +replace (QString &text, QRegExp re, QString after) +{ + int pos = 0; + + while ( (pos = re.indexIn (text, pos)) != -1) + { + QString cap = text.mid (pos,re.matchedLength ()); + QString a (after); + a = a.arg (cap); + text.remove (pos, re.matchedLength ()); + text.insert (pos, a); + pos += a.size (); + } +} + +QString +parser::global_search (QString text, int max_founds) +{ + QString results; + QStringList words = text.split (" ",QString::SkipEmptyParts); + + QString re_program ("(" + words.at (0)); + for (int i = 1; i < words.size (); i++) + { + re_program += "|" + words.at (i); + } + re_program += ")"; + + QRegExp re (re_program, Qt::CaseInsensitive); + + results.append ("\n

Search results

\nResults for: "); + results.append (text); + results.append ("
\n"); + + for (int i = 0; i < _info_files.size (); i++) + { + QFileInfo file_info = _info_files.at (i); + QIODevice *io = open_file (file_info); + if (io == NULL) + { + continue; + } + + QString node_text; + while ( !(node_text = get_next_node (io)).isEmpty ()) + { + QString firstLine = get_first_line (node_text); + QString node = get_node_name (node_text); + if (node.isEmpty ()) + { + continue; + } + + int n = node_text.indexOf ("\n"); + node_text.remove (0, n); + + int pos = 0; + int founds = 0; + + for (; founds < words.size () && node_text.indexOf (words.at (founds)) >= 0; founds++) + { } + + if (founds\n "); + results.append (node); + results.append ("
\n"); + } + + replace (line, re, "%1"); + results.append (line); + results.append ("
\n"); + + founds++; + + pos += re.matchedLength (); + } + } + io->close (); + delete io; + } + + results.append (""); + return results; +} diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/qtinfo/parser.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/src/qtinfo/parser.h Mon Jul 30 19:27:14 2012 +0200 @@ -0,0 +1,111 @@ +/* Copyright (C) 2009 P.L. Lucas + * Copyright (C) 2012 Jacob Dawid + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +/** + * \class parser + * This class gets nodes and searchs inside of `info files'. + *

Each info file has nodes. Every node has the documentation. + * Info files contains a map with position of each node.

+ *

What is position? + * There is a simple answer: + * If you make a queue with info files, position will be the number of bytes + * from begining to node position.

+ *

+ * But is not so easy. There is headers, and qtinfo must not take these headers into account. + *

+ *

+ * This class also translates info files to html. + *

+ */ +class parser + : public QObject +{ + Q_OBJECT + +public: + parser (QObject *parent = 0); + void set_info_path (QString _info_path); + QString get_info_path (); + QString search_node (QString node); + QString global_search (QString text, int maxFounds); + + /** Checks if this node is reference. If node is reference, it will be returned its position + * in text, else it will be returned -1. + */ + int is_ref (QString node); + + /**Translates text of node to Html. If anchorPos is not -1, then anchor is inserted in that + * position. + */ + QString node_text_to_html (QString text, int anchorPos=-1, QString anchor=QString()); + +private: + struct node_position + { + QString _node_name; + int pos; + }; + + struct node_map_item + { + int pos; + }; + + struct info_file_item + { + QFileInfo file_info; + int real_size; + }; + + QString search_node (QString node, QIODevice * io); + QString get_next_node (QIODevice * io); + QString get_node_name (QString text); + QString get_node_up (QString text); + QString get_node_next (QString text); + QString get_node_prev (QString text); + + /** Parses info files and gets map of node positions.*/ + void parse_info_map(); + + /** Open info files and uncompress them. */ + QIODevice *open_file(QFileInfo & fileInfo); + + /** Calculates real position of nodes. + * \param pos position from info file. + * \param fileInfo returns file what contains that position. + * \param realPos returns real position inside of fileInfo. + */ + void real_position (int pos, QFileInfo & file_info, int & real_pos); + + /** Seeks to position pos. */ + void seek (QIODevice *io, int pos); + + + QString _info_path; + QFileInfoList _info_files; + QHash _node_map; + QHash _ref_map; + QList _info_file_real_size_list; + QHash _compressors_map; +}; diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/qtinfo/webinfo.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/src/qtinfo/webinfo.cc Mon Jul 30 19:27:14 2012 +0200 @@ -0,0 +1,209 @@ +/* Copyright (C) 2009 P.L. Lucas + * Copyright (C) 2012 Jacob Dawid + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "webinfo.h" +#include +#include + + +webinfo::webinfo (QWidget *parent) + :QWidget (parent) +{ + _font_web = font (); + + QVBoxLayout *layout = new QVBoxLayout (); + setLayout (layout); + + QHBoxLayout *hboxLayout = new QHBoxLayout (); + layout->addLayout (hboxLayout); + + _close_tab_button = new QPushButton (this); + _close_tab_button->setSizePolicy (QSizePolicy::Fixed,QSizePolicy::Preferred); + _close_tab_button->setIcon (QIcon (":/actions/icons/stop.png")); + hboxLayout->addWidget (_close_tab_button); + + _tab_bar = new QTabBar (this); + _tab_bar->setSizePolicy (QSizePolicy::Preferred,QSizePolicy::Preferred); + _tab_bar->setExpanding (false); + hboxLayout->addWidget (_tab_bar); + + _zoom_in_button = new QToolButton (this); + _zoom_in_button->setSizePolicy (QSizePolicy::Fixed,QSizePolicy::Preferred); + _zoom_in_button->setIcon (QIcon (":/actions/icons/zoom-in.png")); + hboxLayout->addWidget (_zoom_in_button); + + _zoom_out_button = new QToolButton (this); + _zoom_out_button->setSizePolicy (QSizePolicy::Fixed,QSizePolicy::Preferred); + _zoom_out_button->setIcon (QIcon (":/actions/icons/zoom-out.png")); + hboxLayout->addWidget (_zoom_out_button); + + _stacked_widget = new QStackedWidget (this); + layout->addWidget (_stacked_widget); + + hboxLayout = new QHBoxLayout (); + layout->addLayout (hboxLayout); + + _search_line_edit = new QLineEdit(this); + _search_line_edit->setPlaceholderText (tr ("Type here and press \'Return\' to search")); + hboxLayout->addWidget (_search_line_edit); + + _search_check_box = new QCheckBox (tr ("Global search")); + hboxLayout->addWidget (_search_check_box); + + connect (_close_tab_button, SIGNAL (clicked ()), this, SLOT (close_tab ())); + connect (_tab_bar, SIGNAL (currentChanged (int)), this, SLOT (current_tab_changed (int))); + connect (_zoom_in_button, SIGNAL (clicked ()), this, SLOT (zoom_in ())); + connect (_zoom_out_button, SIGNAL (clicked ()), this, SLOT (zoom_out ())); + connect (_search_line_edit, SIGNAL (returnPressed ()), this, SLOT (search ())); + + resize (500, 300); + + set_info_path ("../../doc/interpreter/octave.info"); +} + +void +webinfo::set_info_path (QString info_path) +{ + _parser.set_info_path (info_path); + load_node ("Top"); +} + +void +webinfo::load_node (QString node_name) +{ + //Check if node has been already opened. + for (int i = 0;i < _tab_bar->count (); i++) + { + if (node_name == _tab_bar->tabText (i)) + { + _tab_bar->setCurrentIndex (i); + return; + } + } + + QString text = _parser.search_node (node_name); + int i = _parser.is_ref (node_name); + _text_browser = addNewTab (node_name); + _text_browser->setHtml (_parser.node_text_to_html (text, i - 1, "anchor")); + + if (i != -1) + { + _text_browser->scrollToAnchor ("anchor"); + } +} + +void +webinfo::link_clicked (const QUrl & link) +{ + QString node = link.toString (); + load_node (node); +} + +void +webinfo::current_tab_changed (int index) +{ + QVariant data = _tab_bar->tabData (index); + _text_browser = (QTextBrowser*) (data.value ()); + + _stacked_widget->setCurrentIndex (_stacked_widget->indexOf (_text_browser)); + + if (_text_browser->font () != _font_web) + { + _text_browser->setFont (_font_web); + } +} + +QTextBrowser * +webinfo::addNewTab(QString name) +{ + _text_browser = new QTextBrowser (this); + _text_browser->setOpenLinks (false); + _text_browser->show (); + + connect (_text_browser, SIGNAL (anchorClicked (const QUrl &)), this, SLOT (link_clicked (const QUrl &)) ); + disconnect(_tab_bar, SIGNAL (currentChanged(int)), this, SLOT (current_tab_changed (int))); + + int ns = _stacked_widget->addWidget (_text_browser); + _stacked_widget->setCurrentIndex (ns); + + int nt = _tab_bar->addTab (name); + _tab_bar->setCurrentIndex (nt); + QVariant data; + data.setValue ( (void*)_text_browser); + _tab_bar->setTabData (nt, data); + + connect (_tab_bar, SIGNAL (currentChanged (int)), this, SLOT (current_tab_changed (int))); + + if (_text_browser->font () != _font_web) + { + _text_browser->setFont (_font_web); + } + return _text_browser; +} + +void +webinfo::close_tab () +{ + int index = _tab_bar->currentIndex (); + if (_tab_bar->tabText (index) != "Top") + closeTab (index); +} + +void +webinfo::closeTab (int index) +{ + QVariant data = _tab_bar->tabData (index); + QWidget *w = (QWidget*) (data.value ()); + _stacked_widget->removeWidget (w); + delete w; + + _tab_bar->removeTab (index); +} + +void +webinfo::search () +{ + if (_search_check_box->isChecked ()) + { + // Global search + QString results = _parser.global_search (_search_line_edit->text (), 5); + _text_browser=addNewTab ("Results for: " + _search_line_edit->text ()); + _text_browser->setHtml (results); + } + else + { + // Local search + _text_browser->find (_search_line_edit->text ()); + } +} + +void +webinfo::zoom_in () +{ + _font_web.setPointSize (_font_web.pointSize() + 1); + _text_browser->setFont (_font_web); +} + +void +webinfo::zoom_out () +{ + _font_web.setPointSize (_font_web.pointSize() - 1); + _text_browser->setFont (_font_web); +} + diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/qtinfo/webinfo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/src/qtinfo/webinfo.h Mon Jul 30 19:27:14 2012 +0200 @@ -0,0 +1,60 @@ +/* Copyright (C) 2009 P.L. Lucas + * Copyright (C) 2012 Jacob Dawid + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include "parser.h" +#include +#include +#include +#include +#include +#include + +class webinfo : public QWidget +{ + Q_OBJECT +public: + webinfo (QWidget *parent = 0); + void set_info_path (QString info_path); + void load_node (QString node_name); + +public slots: + void link_clicked (const QUrl &link); + void current_tab_changed (int index); + void close_tab (); + void search (); + void zoom_in (); + void zoom_out (); + +private: + QTextBrowser *_text_browser; + QTabBar *_tab_bar; + QStackedWidget *_stacked_widget; + QPushButton *_close_tab_button; + QLineEdit *_search_line_edit; + QCheckBox *_search_check_box; + QToolButton *_zoom_in_button; + QToolButton *_zoom_out_button; + + parser _parser; + QFont _font_web; + + QTextBrowser *addNewTab (QString name); + void closeTab(int index); +}; diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/resource.qrc --- a/gui/src/resource.qrc Mon Jul 30 09:55:57 2012 +0200 +++ b/gui/src/resource.qrc Mon Jul 30 19:27:14 2012 +0200 @@ -15,5 +15,11 @@ icons/filesaveas.png icons/redled.png icons/arrow_right.png + icons/bookmark.png + icons/question.png + icons/star.png + icons/stop.png + icons/zoom-in.png + icons/zoom-out.png diff -r 6889217b9d78 -r 48ae6a7c69c1 gui/src/src.pro --- a/gui/src/src.pro Mon Jul 30 09:55:57 2012 +0200 +++ b/gui/src/src.pro Mon Jul 30 19:27:14 2012 +0200 @@ -44,6 +44,7 @@ INCLUDEPATH += . \ octave-adapter \ m-editor \ + qtinfo \ ../qterminal/libqterminal \ /usr/include/qt4 \ ../.. \ @@ -83,6 +84,8 @@ m-editor/lexer-octave-gui.cc \ m-editor/file-editor.cc \ m-editor/file-editor-tab.cc \ + qtinfo/parser.cc \ + qtinfo/webinfo.cc \ main-window.cc \ workspace-view.cc \ history-dockwidget.cc \ @@ -93,7 +96,8 @@ welcome-wizard.cc \ workspace-model.cc \ terminal-dockwidget.cc \ - octave-qt-event-listener.cc + octave-qt-event-listener.cc \ + documentation-dockwidget.cc HEADERS += \ octave-adapter/octave-link.h \ @@ -105,6 +109,8 @@ m-editor/file-editor.h \ m-editor/file-editor-interface.h \ m-editor/file-editor-tab.h \ + qtinfo/parser.h \ + qtinfo/webinfo.h \ symbol-information.h \ main-window.h \ workspace-view.h \ @@ -115,7 +121,8 @@ welcome-wizard.h \ workspace-model.h \ terminal-dockwidget.h \ - octave-qt-event-listener.h + octave-qt-event-listener.h \ + documentation-dockwidget.h FORMS += \ settings-dialog.ui \