changeset 15055:48ae6a7c69c1 gui

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.
author Jacob Dawid <jacob.dawid@gmail.com>
date Mon, 30 Jul 2012 19:27:14 +0200
parents 6889217b9d78
children 4c4f2fb07a50
files gui/src/documentation-dockwidget.cc gui/src/documentation-dockwidget.h gui/src/icons/bookmark.png gui/src/icons/question.png gui/src/icons/star.png gui/src/icons/stop.png gui/src/icons/zoom-in.png gui/src/icons/zoom-out.png gui/src/main-window.cc gui/src/main-window.h gui/src/qtinfo/parser.cc gui/src/qtinfo/parser.h gui/src/qtinfo/webinfo.cc gui/src/qtinfo/webinfo.h gui/src/resource.qrc gui/src/src.pro
diffstat 16 files changed, 1097 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/gui/src/documentation-dockwidget.cc
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#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);
+}
new file mode 100644
--- /dev/null
+++ b/gui/src/documentation-dockwidget.h
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DOCUMENTATIONDOCKWIDGET_H
+#define DOCUMENTATIONDOCKWIDGET_H
+
+#include <QDockWidget>
+#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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5e761587198608815a4625f26923e4c2c59d5ed1
GIT binary patch
literal 690
zc$@*U0!{siP)<h;3K|Lk000e1NJLTq000mG000jN1^@s6?Q>5r00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!L`g(JRCwBA
zV88=DRWZzeU(PTepBjJwV#Fo!p^`y>iJ$%c@81jzzux>*l$^-$0h>C20Aj*r!2kaY
z1+2RA0&IF(0)PK76yQ<^5I{H$U|?g4XLHbF;Br!C_{Yi=k4qUq0AV%YZ5cxXv#PWL
zBj;lVM()Q99O?=RPntv<{{7o6fUXuGfEfREG0gw_k3r!t(64_v*&P0H^D}_h+!2-x
z%pxzrivGNmV|YH}0K?zE3=H32d}Lr?=lJmP{-+B-uRQ<=AjZF)4D<h~swXfzSpX&8
zLCt-N!@(jz%+B!l=^uuBvraO+Jojz^KmdVb;d=u^!9PCcevS}*21e#@xZ~^(BTzE~
z!<A{b7(T!JTWGhNVFEw^!K3kg1w#UZ0LOf8D?SDm5e`hvKbaW5-U8aZ`5D8f*Z&f2
zcQPyh2?GQWN;-HyS+d~wo0t6}?!s6NxW4EO!-wa81Fd&3Y=8*^1P}{Kh)Sypuzr2T
z!0_=WMBpD%JOKlcos*H_-#^p@1rR_e2K;*Z$exoGlnj3XF(bpTkN<(u@t=WB80b(S
z;${a1!yg6*po#-9JpciOV!+=|Ume&v|1<o({hQ(WlYb0v-~PYw2N<OSLW~9qI!p`#
zyg)U780?Yt00a;`A%POfucvPrKHUDtaQnvJ4<FwDPc&T1U}(CD!SL0K|B0t|{r&Lt
z_Fs^X43G@~2q1VM-cDpt0Q&DfFcCEZ=?OY3Q2n~kfdQN+fL^EvCOk!-Qw$G4;s5~#
Y0GrXxbc~n>*8l(j07*qoM6N<$f~cq`1poj5
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9cc2a8b0892852068bd18c7660c0e254d261ba4f
GIT binary patch
literal 1903
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..058efcf4ba174495d8d89d1916c3ccebf393a2af
GIT binary patch
literal 1468
zc$@*e1w;CYP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004XF*Lt007q5
z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU%PDw;TRCwCN
zmwRkeWfZ{AcYE9J(Z{y#5w?Ue!AaNzvxPtviOz^b6N8xjXJS&Oe@tNdhd~+tOycW5
zOiYXmOVDUyP?Ud$gc!0YasB~eTPL)GiS4$Iy<cr_+uM6T&vzePU)ws++2r(l+}rQ`
z&iT%F&R0Syh5z%zv#-w1&WBp$_3bB$v3cYx&!+>}N+@!!zvcc7D~w{e$0UcZJIgN|
z!l7e5>pnEVk(##CP;cHzYm8u_GjHNlElS>o0JsX<8b~EMMJo(ItBt^mu^OD-f@0Ya
z0AiQV(K>TtoNo=<uqoOQ546Brr-{@2c=DXxJjIkV2=jjm;DTcfq>(>G9fs5+Wse&z
zFjua5faH7(Rf}3(F~~PXz%qIsI<DeWR6A0cuCIhMa$}~Ksg;9D@NOQ0y@fbrbn%=3
zj=<3-4x}#A9tlij0p1852f7GLqG0q$ll-3&7<@4(xQVY$+u?pIappapHGLsKDflZ9
zK#zl9P5@o-`85|D_i_%yV_+sgIc0OKJV$o(oV=UNi%=Mk0GWsbEj0qQ8`M-oQXNe<
z@wi~5fQ5q=2f<upK<a~ot#W@{fH1DiBt(IPWJSQtDb~?i69Vv%ct=2qpf6%5ajI-s
zwRLc-4JIpb&4OIwfUsJirDAIXbT>C{{ke-)8C5hzNM@g;&!hGF7{NGC420Q2w>-u5
zgu&i(5l&peCqlNEN(NxdmOKw%wr|-s_zo@RvMc8@m8XnJQlF_C6M;-gAkLU>gcmKB
zgW$M&3EKX^ClOXNk^%HBsW`-ca<;5`^hGG(QmmzGDPOJ6*1;_!(-P3@v0wnUw<E~6
z>3M*K*3`xLd&d_2j+?N=_L?U4oM4|Qt=?DT1VU=ez-oQA213vZ9ymK#;$VImb?xA@
z#05LMW50{dt<Q{q{X<@Hs7g7}ibXWZI-0PMWO<hG7FnJrOA>_rg^|I91Kxgkp`QgR
zzd~?EN1%RSDO&P<{`}(Gi7j9tJob(0uFeEYff6VP6NM4?V$)DR9ANq69tyiV4DqX+
z5TVF8S;ev&3nn6=yID|0Wi_~nnnfrBVq(%1k|Yoj70+8E?r@6YTPR-UWt4>#0Wdp0
z%N5DZkk0_nr4mtEz?MkrnP+3d@_;0((WAhqP(sueamSupQL&z;R|Ft=v;)fdgwo_T
z6Gk874@GpHV2xaW_Fn|BxpAfs#gnc$qZp-G-$bg&K3c#OkgO1?Fq${wY8wvO!h&qO
zi=!SC=7G7D3R6}9Vu22J!(j{4BxNZuaeW>VbBTAO82T}o#wR{jz*w1BvmB>bzl%rf
zxeSY$0y2r4jmZSc@knHOM`;&`ew?M%lxO!q1=k^OHfk=_77Swlo(TTHj(}gR_uq#7
zw_jTL?5Rz4!?ij@vUf_k5q2{+X?Ft18NdZcU**cUeR4igOUH-^i=LvOcg{I{2b|t8
z*hVzB`nuz7-@S6{;}0CW?(bm`DO;tgwP+Bz1IWN{;|B$hXSt{^uruI+C+}j;X2HZ1
z|Aq25%7h+NKZ)<V4i9{Ewxn^=2^KC97ql1&mL9+Z=itm2Pr&85zQ95KUgy)!@F=Sh
zz?M}GT4G;^e~g`MIeY^loKq?U^Mo<?`(=7D67XWujV+V&D3?%rS;|D2L5ZaWRaA$V
z?JettC{+U!Q*|l$iZl<9^#CyI#!*-T8Pt+TXpR4R%Mibn_L6G?kYN#uVVwP6%!f7n
zku49%>-lq;0uepgvVZcMcMTxc-GRMsSgsoD0(j7m0`V)n_93>9YFjn7*46wU0R{lz
WQ-?g>7HstZ0000<MNUMnLSTZnY^yy0
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f6357ee4d9aab6ab05fa4ba7fa8715595482567e
GIT binary patch
literal 358
zc%17D@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b
z3=G_YAk0{w5<d|r$X?><>&kwejh{zL(}4fnL!i)SPZ!4!i_=FZ8|Jkb2)ND<Ji?lB
zLar&vzoAFuC(oS&&mWqUe9>@R_JCuzo*19QV-xSBJ#LFSrszjX)&H)qwn_ex&+&k{
zV$PlaqRQ(VtS#?3f4nWmbNIj}oi(qy9A+)sEwNzLD(M2oceC|wHf_tD7_?~0A&J8#
zz7oj+UW!YXysw_MjB!V+`A(*F>$0CKn_Z8xUi(!~_M^!Uozs&l=Sd#__;g~|B8AhN
zWUrUX9(a0O;e0W}nynVk>rSh%+>YYNew!_tWU;EN_?+s#<cgx6@0N-!9*gdN75S}Z
z_;DS7AB*Di?(*6KwuKeD586(9?3nfFeEnnd;+=DZ@}dicfZk{DboFyt=akR{0ELZ_
A761SM
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..63b3bd031ed91915dd2ddf38e4bd5ac5d812c890
GIT binary patch
literal 1871
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
JPDHLkV1mfBh8O?<
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b56a0bb79fc0403afca890a53945c9feba7a2092
GIT binary patch
literal 1866
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
Eg7rj$G5`Po
--- a/gui/src/main-window.cc
+++ b/gui/src/main-window.cc
@@ -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 ();
 
--- a/gui/src/main-window.h
+++ b/gui/src/main-window.h
@@ -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;
new file mode 100644
--- /dev/null
+++ b/gui/src/qtinfo/parser.cc
@@ -0,0 +1,578 @@
+/* Copyright (C) 2009 P.L. Lucas
+ * Copyright (C) 2012 Jacob Dawid <jacob.dawid@gmail.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 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 <QFileInfo>
+#include <QDir>
+#include <QFile>
+#include <QUrl>
+#include <QRegExp>
+#include <QProcess>
+#include <QBuffer>
+
+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 ("<b>","");
+      url_link.replace ("</b>","");
+      url_link = QUrl::toPercentEncoding (url_link, "", "'");
+
+      QString href;
+      if (type=="\n*")
+        {
+          href="\n<img src=':/actions/icons/bookmark.png'/>";
+        }
+      else
+        {
+          href="<img src=':/actions/icons/bookmark.png'/>";
+        }
+      href += re.cap (2) + "<a href='" + url_link + "'>" + note + ":" + link + re.cap (5) + "</a>";
+      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 = "<b>`" + t + "</b>'";
+
+      f = re.matchedLength ();
+      text.replace (i,f,bold);
+      i += bold.size ();
+    }
+}
+
+static void
+info_to_html (QString &text)
+{
+  text.replace ("&", "&amp;");
+  text.replace ("<", "&lt;");
+  text.replace (">", "&gt;");
+
+  text.replace ("\n* Menu:", "\n<b>Menu:</b>");
+  text.replace ("*See also:*", "<b>See also:</b>");
+  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 + "<a name='" + anchor + "' /><img src=':/actions/icons/stop.png'>" + text2;
+    }
+  else
+    {
+      int n = text.indexOf ("\n");
+      text.remove (0, n);
+      info_to_html (text);
+    }
+
+  QString navigationLinks = QString (
+        "<img src=':/actions/icons/arrow_right.png'/> <b>Section:</b> %1<br>"
+        "<b>Previous Section:</b> <a href='%2'>%3</a><br>"
+        "<b>Next Section:</b> <a href='%4'>%5</a><br>"
+        "<b>Up:</b> <a href='%6'>%7</a><br>\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 ("<hr>\n<pre>");
+  text.append ("</pre>\n<hr><hr>\n");
+  text.prepend (navigationLinks);
+  text.append (navigationLinks);
+  text.prepend ("<html><body>\n");
+  text.append ("</body></html>\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 ("<html><body>\n<h1>Search results</h1>\n<b>Results for:</b> ");
+  results.append (text);
+  results.append ("<br>\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<words.size ())
+            {
+              continue;
+            }
+          founds = 0;
+
+          while ( (pos = re.indexIn (node_text, pos)) != -1 && founds < max_founds)
+            {
+              int line_start, line_end;
+              line_start = node_text.lastIndexOf ("\n", pos);
+              line_end = node_text.indexOf ("\n", pos);
+              QString line = node_text.mid (line_start, line_end - line_start).trimmed ();
+
+              if (founds == 0)
+                {
+                  results.append(
+                        "<br>\n<img src=':/actions/icons/bookmark.png'> <a href='"
+                        + QString(QUrl::toPercentEncoding(node,"","'")) +
+                        "'>");
+                  results.append (node);
+                  results.append ("</a><br>\n");
+                }
+
+              replace (line, re, "<i>%1</i>");
+              results.append (line);
+              results.append ("<br>\n");
+
+              founds++;
+
+              pos += re.matchedLength ();
+            }
+        }
+      io->close ();
+      delete io;
+    }
+
+  results.append ("</body></html>");
+  return results;
+}
new file mode 100644
--- /dev/null
+++ b/gui/src/qtinfo/parser.h
@@ -0,0 +1,111 @@
+/* Copyright (C) 2009 P.L. Lucas
+ * Copyright (C) 2012 Jacob Dawid <jacob.dawid@gmail.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 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 <QStringList>
+#include <QIODevice>
+#include <QFileInfoList>
+#include <QHash>
+
+/**
+ * \class parser
+ * This class gets nodes and searchs inside of `info files'.
+ * <p>Each info file has nodes. Every node has the documentation.
+ * Info files contains a map with position of each node.</p>
+ * <p>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.</p>
+ * <p>
+ * But is not so easy. There is headers, and qtinfo must not take these headers into account.
+ * </p>
+ * <p>
+ * This class also translates info files to html.
+ * </p>
+ */
+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<QString, node_map_item> _node_map;
+  QHash<QString, node_position> _ref_map;
+  QList<info_file_item>         _info_file_real_size_list;
+  QHash<QString, QString>       _compressors_map;
+};
new file mode 100644
--- /dev/null
+++ b/gui/src/qtinfo/webinfo.cc
@@ -0,0 +1,209 @@
+/* Copyright (C) 2009 P.L. Lucas
+ * Copyright (C) 2012 Jacob Dawid <jacob.dawid@gmail.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 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 <QVBoxLayout>
+#include <QHBoxLayout>
+
+
+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<void*> ());
+
+  _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<void*> ());
+  _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);
+}
+
new file mode 100644
--- /dev/null
+++ b/gui/src/qtinfo/webinfo.h
@@ -0,0 +1,60 @@
+/* Copyright (C) 2009 P.L. Lucas
+ * Copyright (C) 2012 Jacob Dawid <jacob.dawid@gmail.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 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 <QTextBrowser>
+#include "parser.h"
+#include <QStackedWidget>
+#include <QTabBar>
+#include <QPushButton>
+#include <QLineEdit>
+#include <QCheckBox>
+#include <QToolButton>
+
+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);
+};
--- a/gui/src/resource.qrc
+++ b/gui/src/resource.qrc
@@ -15,5 +15,11 @@
         <file>icons/filesaveas.png</file>
         <file>icons/redled.png</file>
         <file>icons/arrow_right.png</file>
+        <file>icons/bookmark.png</file>
+        <file>icons/question.png</file>
+        <file>icons/star.png</file>
+        <file>icons/stop.png</file>
+        <file>icons/zoom-in.png</file>
+        <file>icons/zoom-out.png</file>
     </qresource>
 </RCC>
--- a/gui/src/src.pro
+++ b/gui/src/src.pro
@@ -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 \