# HG changeset patch # User John W. Eaton # Date 1670359527 18000 # Node ID deb553ac2c54f5a874be5fea5c56b2c2f43e7938 # Parent 431f80aba37a0b24e1df43db6c5617270fa67a9a# Parent 29d734430e5f4c327676fe81ecdcea6b8fa527be maint: Merge stable to default. diff -r 29d734430e5f -r deb553ac2c54 .github/workflows/make.yaml --- a/.github/workflows/make.yaml Tue Dec 06 14:53:00 2022 -0500 +++ b/.github/workflows/make.yaml Tue Dec 06 15:45:27 2022 -0500 @@ -85,7 +85,7 @@ key: ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }}:${{ steps.ccache_cache_timestamp.outputs.timestamp }}:${{ github.sha }} restore-keys: | ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }} - ccache:${{ matrix.os }}:${{ matrix.compiler }}:refs/heads/stable + ccache:${{ matrix.os }}:${{ matrix.compiler }}:refs/heads/default - name: configure ccache env: @@ -239,7 +239,7 @@ key: ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }}:${{ steps.ccache_cache_timestamp.outputs.timestamp }}:${{ github.sha }} restore-keys: | ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }} - ccache:${{ matrix.os }}:${{ matrix.compiler }}:refs/heads/stable + ccache:${{ matrix.os }}:${{ matrix.compiler }}:refs/heads/default - name: configure ccache # The cache doesn't seem to compress well on macOS. Is it already compressed? @@ -468,7 +468,7 @@ key: ccache:${{ matrix.os }}:${{ matrix.msystem }}:${{ github.ref }}:${{ steps.ccache_cache_timestamp.outputs.timestamp }}:${{ github.sha }} restore-keys: | ccache:${{ matrix.os }}:${{ matrix.msystem }}:${{ github.ref }} - ccache:${{ matrix.os }}:${{ matrix.msystem }}:refs/heads/stable + ccache:${{ matrix.os }}:${{ matrix.msystem }}:refs/heads/default - name: configure ccache # Limit the maximum size and switch on compression to avoid exceeding the total disk or cache quota. @@ -707,7 +707,7 @@ key: ccache:${{ matrix.os }}:cygwin:${{ github.ref }}:${{ steps.ccache_cache_timestamp.outputs.timestamp }}:${{ github.sha }} restore-keys: | ccache:${{ matrix.os }}:cygwin:${{ github.ref }} - ccache:${{ matrix.os }}:cygwin:refs/heads/stable + ccache:${{ matrix.os }}:cygwin:refs/heads/default - name: configure ccache run: | diff -r 29d734430e5f -r deb553ac2c54 configure.ac --- a/configure.ac Tue Dec 06 14:53:00 2022 -0500 +++ b/configure.ac Tue Dec 06 15:45:27 2022 -0500 @@ -27,7 +27,7 @@ ### Initialize Autoconf AC_PREREQ([2.65]) -AC_INIT([GNU Octave], [8.0.1], [https://octave.org/bugs.html], [octave], +AC_INIT([GNU Octave], [9.0.0], [https://octave.org/bugs.html], [octave], [https://www.gnu.org/software/octave/]) ### Declare version numbers @@ -39,9 +39,9 @@ ## explains how to update these numbers for release and development ## versions. -OCTAVE_MAJOR_VERSION=8 +OCTAVE_MAJOR_VERSION=9 OCTAVE_MINOR_VERSION=0 -OCTAVE_PATCH_VERSION=1 +OCTAVE_PATCH_VERSION=0 dnl PACKAGE_VERSION is set by the AC_INIT VERSION argument. OCTAVE_VERSION="$PACKAGE_VERSION" diff -r 29d734430e5f -r deb553ac2c54 doc/interpreter/contributors.in --- a/doc/interpreter/contributors.in Tue Dec 06 14:53:00 2022 -0500 +++ b/doc/interpreter/contributors.in Tue Dec 06 15:45:27 2022 -0500 @@ -101,6 +101,7 @@ Massimiliano Fasi Stephen Fegan Ramon Garcia Fernandez +Kasper H. Filtenborg Torsten Finke David Finkel Guillaume Flandin diff -r 29d734430e5f -r deb553ac2c54 doc/interpreter/linalg.txi --- a/doc/interpreter/linalg.txi Tue Dec 06 14:53:00 2022 -0500 +++ b/doc/interpreter/linalg.txi Tue Dec 06 15:45:27 2022 -0500 @@ -211,6 +211,8 @@ @DOCSTRING(kron) +@DOCSTRING(tensorprod) + @DOCSTRING(blkmm) @DOCSTRING(sylvester) diff -r 29d734430e5f -r deb553ac2c54 doc/liboctave/range.texi --- a/doc/liboctave/range.texi Tue Dec 06 14:53:00 2022 -0500 +++ b/doc/liboctave/range.texi Tue Dec 06 15:45:27 2022 -0500 @@ -20,35 +20,4 @@ @chapter Ranges @cindex ranges -@deftypefn {} {} Range (void) -@deftypefnx {} {} Range (const Range &@var{r}) -@deftypefnx {} {} Range (double @var{b}, double @var{l}) -@deftypefnx {} {} Range (double @var{b}, double @var{l}, double @var{i}) -@end deftypefn - -@deftypefn {} double base (void) const -@deftypefnx {} double limit (void) const -@deftypefnx {} double inc (void) const -@end deftypefn - -@deftypefn {} void set_base (double @var{b}) -@deftypefnx {} void set_limit (double @var{l}) -@deftypefnx {} void set_inc (double @var{i}) -@end deftypefn - -@deftypefn {} int nelem (void) const -@end deftypefn - -@deftypefn {} double min (void) const -@deftypefnx {} double max (void) const -@end deftypefn - -@deftypefn {} void sort (void) -@end deftypefn - -@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const Range &@var{r}) -@deftypefnx {} {istream&} {operator >>} (istream &@var{is}, Range &@var{r}) -@end deftypefn - -@deftypefn {} void print_range (void) -@end deftypefn +FIXME: The @code{Range} class is obsolete. diff -r 29d734430e5f -r deb553ac2c54 etc/NEWS.8.md diff -r 29d734430e5f -r deb553ac2c54 etc/NEWS.9.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/etc/NEWS.9.md Tue Dec 06 15:45:27 2022 -0500 @@ -0,0 +1,93 @@ +Summary of important user-visible changes for version 9 (yyyy-mm-dd): +--------------------------------------------------------------------- + +### General improvements + +- `oruntests`: The current directory now changes to the directory +containing the files with the tests for the duration of the test. This +aligns the behavior of this function with Octave's test suite. This also +means that the file encoding specified in the `.oct-config` file for the +respective directory is taken into account for the tests. + +### Graphical User Interface + +### Graphics backend + +### Matlab compatibility + +### Alphabetical list of new functions added in Octave 9 + +* `tensorprod` + +### Deprecated functions, properties, and operators + +The following functions and properties have been deprecated in Octave 9 +and will be removed from Octave 11 (or whatever version is the second +major release after 9): + +- Functions + + Function | Replacement + -----------------------|------------------ + +- Properties + + The following property names are discouraged, but there is no fixed + date for their removal. + + Object | Property | Replacement + -----------------|-------------|------------ + +The following features were deprecated in Octave 7 and have been removed +from Octave 9. + +- Functions + + Function | Replacement + ---------------------------|------------------ + disable_diagonal_matrix | optimize_diagonal_matrix + disable_permutation_matrix | optimize_permutation_matrix + disable_range | optimize_range + +- Operators + + Operator | Replacement + ---------|------------ + .+ | + + .+= | += + .- | - + .-= | -= + ** | ^ + **= | ^= + .** | .^ + .**= | .^= + +- Interpreter + + * The use of `'...'` for line continuations *inside* double-quoted + strings has been removed. Use `'\'` for line continuations inside strings + instead. + + * The use of `'\'` as a line continuation *outside* of double-quoted + strings has been removed. Use `'...'` for line continuations instead. + + * Support for trailing whitespace after a `'\'` line continuation has been + removed. Delete unnecessary trailing whitespace. + +- For plot functions, the use of numbers to select line colors in + shorthand formats was an undocumented feature was removed from Octave 9. + +- The environment variable used by `mkoctfile` for linker flags is now + `LDFLAGS` rather than `LFLAGS`. `LFLAGS` was deprecated in Octave 6 + and has been removed. + +### Old release news + +- [Octave 8.x](etc/NEWS.8) +- [Octave 7.x](etc/NEWS.7) +- [Octave 6.x](etc/NEWS.6) +- [Octave 5.x](etc/NEWS.5) +- [Octave 4.x](etc/NEWS.4) +- [Octave 3.x](etc/NEWS.3) +- [Octave 2.x](etc/NEWS.2) +- [Octave 1.x](etc/NEWS.1) diff -r 29d734430e5f -r deb553ac2c54 etc/module.mk --- a/etc/module.mk Tue Dec 06 14:53:00 2022 -0500 +++ b/etc/module.mk Tue Dec 06 15:45:27 2022 -0500 @@ -13,6 +13,7 @@ %reldir%/NEWS.6.md \ %reldir%/NEWS.7.md \ %reldir%/NEWS.8.md \ + %reldir%/NEWS.9.md \ %reldir%/gdbinit %canon_reldir%_EXTRA_DIST += \ diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/BaseControl.cc --- a/libgui/graphics/BaseControl.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/BaseControl.cc Tue Dec 06 15:45:27 2022 -0500 @@ -41,302 +41,301 @@ OCTAVE_BEGIN_NAMESPACE(octave) -static void -updatePalette (const uicontrol::properties& props, QWidget *w) -{ - QPalette p = w->palette (); + static void + updatePalette (const uicontrol::properties& props, QWidget *w) + { + QPalette p = w->palette (); - if (props.style_is ("edit") - || props.style_is ("listbox")) - { - Matrix bg_color = props.get_backgroundcolor_rgb (); - // Matlab compatibility: Default color is ignored, and rendered as - // white ([1.0, 1.0, 1.0]). See bug #58261. - if (bg_color(0) == bg_color(1) && bg_color(0) == bg_color(2) - && (std::abs (bg_color(1) - 0.94) < .005)) - bg_color.fill (1.0); + if (props.style_is ("edit") + || props.style_is ("listbox")) + { + Matrix bg_color = props.get_backgroundcolor_rgb (); + // Matlab compatibility: Default color is ignored, and rendered as + // white ([1.0, 1.0, 1.0]). See bug #58261. + if (bg_color(0) == bg_color(1) && bg_color(0) == bg_color(2) + && (std::abs (bg_color(1) - 0.94) < .005)) + bg_color.fill (1.0); - p.setColor (QPalette::Active, QPalette::Base, - Utils::fromRgb (bg_color)); - p.setColor (QPalette::Inactive, QPalette::Base, - Utils::fromRgb (bg_color)); - p.setColor (QPalette::Active, QPalette::Text, - Utils::fromRgb (props.get_foregroundcolor_rgb ())); - p.setColor (QPalette::Inactive, QPalette::Text, - Utils::fromRgb (props.get_foregroundcolor_rgb ())); - } - else if (props.style_is ("popupmenu")) - { - // popupmenu (QComboBox) is a listbox with a button. - // This requires setting colors for both. - QColor bcol = Utils::fromRgb (props.get_backgroundcolor_rgb ()); - QColor fcol = Utils::fromRgb (props.get_foregroundcolor_rgb ()); - QString qss = QString (":enabled { background: %1 none;\n" - "color: %2; }") - .arg(bcol.name ()).arg (fcol.name ()); - w->setStyleSheet(qss); - return; - } - else if (props.style_is ("radiobutton") - || props.style_is ("checkbox")) - { - p.setColor (QPalette::Active, QPalette::Button, - Utils::fromRgb (props.get_backgroundcolor_rgb ())); - p.setColor (QPalette::Inactive, QPalette::Button, - Utils::fromRgb (props.get_backgroundcolor_rgb ())); - p.setColor (QPalette::Active, QPalette::WindowText, - Utils::fromRgb (props.get_foregroundcolor_rgb ())); - p.setColor (QPalette::Inactive, QPalette::WindowText, - Utils::fromRgb (props.get_foregroundcolor_rgb ())); - } - else if (props.style_is ("pushbutton") - || props.style_is ("togglebutton")) - { - QColor bcol = Utils::fromRgb (props.get_backgroundcolor_rgb ()); - QColor fcol = Utils::fromRgb (props.get_foregroundcolor_rgb ()); - QString qss = QString (":enabled { background: %1 none;\n" - "color: %2; }") - .arg(bcol.name ()).arg (fcol.name ()); - w->setStyleSheet(qss); - return; - } - else - { - p.setColor (QPalette::Active, QPalette::Window, - Utils::fromRgb (props.get_backgroundcolor_rgb ())); - p.setColor (QPalette::Inactive, QPalette::Window, - Utils::fromRgb (props.get_backgroundcolor_rgb ())); - p.setColor (QPalette::Active, QPalette::WindowText, - Utils::fromRgb (props.get_foregroundcolor_rgb ())); - p.setColor (QPalette::Inactive, QPalette::WindowText, - Utils::fromRgb (props.get_foregroundcolor_rgb ())); - } + p.setColor (QPalette::Active, QPalette::Base, + Utils::fromRgb (bg_color)); + p.setColor (QPalette::Inactive, QPalette::Base, + Utils::fromRgb (bg_color)); + p.setColor (QPalette::Active, QPalette::Text, + Utils::fromRgb (props.get_foregroundcolor_rgb ())); + p.setColor (QPalette::Inactive, QPalette::Text, + Utils::fromRgb (props.get_foregroundcolor_rgb ())); + } + else if (props.style_is ("popupmenu")) + { + // popupmenu (QComboBox) is a listbox with a button. + // This requires setting colors for both. + QColor bcol = Utils::fromRgb (props.get_backgroundcolor_rgb ()); + QColor fcol = Utils::fromRgb (props.get_foregroundcolor_rgb ()); + QString qss = QString (":enabled { background: %1 none;\n" + "color: %2; }") + .arg(bcol.name ()).arg (fcol.name ()); + w->setStyleSheet(qss); + return; + } + else if (props.style_is ("radiobutton") + || props.style_is ("checkbox")) + { + p.setColor (QPalette::Active, QPalette::Button, + Utils::fromRgb (props.get_backgroundcolor_rgb ())); + p.setColor (QPalette::Inactive, QPalette::Button, + Utils::fromRgb (props.get_backgroundcolor_rgb ())); + p.setColor (QPalette::Active, QPalette::WindowText, + Utils::fromRgb (props.get_foregroundcolor_rgb ())); + p.setColor (QPalette::Inactive, QPalette::WindowText, + Utils::fromRgb (props.get_foregroundcolor_rgb ())); + } + else if (props.style_is ("pushbutton") + || props.style_is ("togglebutton")) + { + QColor bcol = Utils::fromRgb (props.get_backgroundcolor_rgb ()); + QColor fcol = Utils::fromRgb (props.get_foregroundcolor_rgb ()); + QString qss = QString (":enabled { background: %1 none;\n" + "color: %2; }") + .arg(bcol.name ()).arg (fcol.name ()); + w->setStyleSheet(qss); + return; + } + else + { + p.setColor (QPalette::Active, QPalette::Window, + Utils::fromRgb (props.get_backgroundcolor_rgb ())); + p.setColor (QPalette::Inactive, QPalette::Window, + Utils::fromRgb (props.get_backgroundcolor_rgb ())); + p.setColor (QPalette::Active, QPalette::WindowText, + Utils::fromRgb (props.get_foregroundcolor_rgb ())); + p.setColor (QPalette::Inactive, QPalette::WindowText, + Utils::fromRgb (props.get_foregroundcolor_rgb ())); + } - w->setPalette (p); -} + w->setPalette (p); + } -BaseControl::BaseControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, QWidget *w) - : Object (oct_qobj, interp, go, w), m_normalizedFont (false), - m_keyPressHandlerDefined (false) -{ - qObject ()->setObjectName ("UIControl"); - init (w); -} - -void -BaseControl::init (QWidget *w, bool callBase) -{ - if (callBase) - Object::init (w, callBase); - - uicontrol::properties& up = properties (); + BaseControl::BaseControl (octave::interpreter& interp, + const graphics_object& go, QWidget *w) + : Object (interp, go, w), m_normalizedFont (false), + m_keyPressHandlerDefined (false) + { + qObject ()->setObjectName ("UIControl"); + init (w); + } - Matrix bb = up.get_boundingbox (false); - w->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)), - octave::math::round (bb(2)), octave::math::round (bb(3))); - w->setFont (Utils::computeFont (up, bb(3))); - updatePalette (up, w); - if (up.enable_is ("inactive")) - w->blockSignals (true); - else - w->setEnabled (up.enable_is ("on")); - w->setToolTip (Utils::fromStdString (up.get_tooltipstring ())); - w->setVisible (up.is_visible ()); - m_keyPressHandlerDefined = ! up.get_keypressfcn ().isempty (); + void + BaseControl::init (QWidget *w, bool callBase) + { + if (callBase) + Object::init (w, callBase); - w->installEventFilter (this); + uicontrol::properties& up = properties (); - m_normalizedFont = up.fontunits_is ("normalized"); -} - -BaseControl::~BaseControl (void) -{ } - -void -BaseControl::redraw (void) -{ - update (uicontrol::properties::ID_POSITION); -} - -void -BaseControl::update (int pId) -{ - uicontrol::properties& up = properties (); - QWidget *w = qWidget (); + Matrix bb = up.get_boundingbox (false); + w->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)), + octave::math::round (bb(2)), octave::math::round (bb(3))); + w->setFont (Utils::computeFont (up, bb(3))); + updatePalette (up, w); + if (up.enable_is ("inactive")) + w->blockSignals (true); + else + w->setEnabled (up.enable_is ("on")); + w->setToolTip (Utils::fromStdString (up.get_tooltipstring ())); + w->setVisible (up.is_visible ()); + m_keyPressHandlerDefined = ! up.get_keypressfcn ().isempty (); - switch (pId) - { - case uicontrol::properties::ID_POSITION: - { - Matrix bb = up.get_boundingbox (false); - w->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)), - octave::math::round (bb(2)), octave::math::round (bb(3))); - } - break; + w->installEventFilter (this); + + m_normalizedFont = up.fontunits_is ("normalized"); + } + + BaseControl::~BaseControl (void) + { } - case uicontrol::properties::ID_FONTNAME: - case uicontrol::properties::ID_FONTSIZE: - case uicontrol::properties::ID_FONTWEIGHT: - case uicontrol::properties::ID_FONTANGLE: - w->setFont (Utils::computeFont (up)); - break; + void + BaseControl::redraw (void) + { + update (uicontrol::properties::ID_POSITION); + } - case uicontrol::properties::ID_FONTUNITS: - // FIXME: We shouldn't have to do anything, octave should update - // the "fontsize" property automatically to the new units. - // Hence the actual font used shouldn't change. - m_normalizedFont = up.fontunits_is ("normalized"); - break; - - case uicontrol::properties::ID_BACKGROUNDCOLOR: - case uicontrol::properties::ID_FOREGROUNDCOLOR: - updatePalette (up, w); - break; + void + BaseControl::update (int pId) + { + uicontrol::properties& up = properties (); + QWidget *w = qWidget (); - case uicontrol::properties::ID_ENABLE: - if (up.enable_is ("inactive")) + switch (pId) + { + case uicontrol::properties::ID_POSITION: { - w->blockSignals (true); - w->setEnabled (true); + Matrix bb = up.get_boundingbox (false); + w->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)), + octave::math::round (bb(2)), octave::math::round (bb(3))); } - else - { - w->blockSignals (false); - w->setEnabled (up.enable_is ("on")); - } - break; + break; - case uicontrol::properties::ID_TOOLTIPSTRING: - w->setToolTip (Utils::fromStdString (up.get_tooltipstring ())); - break; - - case base_properties::ID_VISIBLE: - w->setVisible (up.is_visible ()); - break; + case uicontrol::properties::ID_FONTNAME: + case uicontrol::properties::ID_FONTSIZE: + case uicontrol::properties::ID_FONTWEIGHT: + case uicontrol::properties::ID_FONTANGLE: + w->setFont (Utils::computeFont (up)); + break; - case uicontrol::properties::ID_KEYPRESSFCN: - m_keyPressHandlerDefined = ! up.get_keypressfcn ().isempty (); - break; + case uicontrol::properties::ID_FONTUNITS: + // FIXME: We shouldn't have to do anything, octave should update + // the "fontsize" property automatically to the new units. + // Hence the actual font used shouldn't change. + m_normalizedFont = up.fontunits_is ("normalized"); + break; - case uicontrol::properties::ID___FOCUS__: - if (up.is___focus__ ()) - w->setFocus (); - else - w->clearFocus (); - break; + case uicontrol::properties::ID_BACKGROUNDCOLOR: + case uicontrol::properties::ID_FOREGROUNDCOLOR: + updatePalette (up, w); + break; - default: - break; - } -} - -bool -BaseControl::eventFilter (QObject *watched, QEvent *xevent) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - switch (xevent->type ()) - { - case QEvent::Resize: - if (m_normalizedFont) - { - octave::autolock guard (gh_mgr.graphics_lock ()); - - qWidget ()->setFont (Utils::computeFont - (properties ())); - } - break; - - case QEvent::MouseButtonPress: - { - octave::autolock guard (gh_mgr.graphics_lock ()); - - QMouseEvent *m = dynamic_cast (xevent); - graphics_object go = object (); - uicontrol::properties& up = Utils::properties (go); - graphics_object fig = go.get_ancestor ("figure"); - if (fig) + case uicontrol::properties::ID_ENABLE: + if (up.enable_is ("inactive")) + { + w->blockSignals (true); + w->setEnabled (true); + } + else { - emit gh_set_event (fig.get_handle (), "currentobject", - m_handle.value (), false); + w->blockSignals (false); + w->setEnabled (up.enable_is ("on")); + } + break; + + case uicontrol::properties::ID_TOOLTIPSTRING: + w->setToolTip (Utils::fromStdString (up.get_tooltipstring ())); + break; - if (m->button () != Qt::LeftButton || ! up.enable_is ("on")) - { - emit gh_set_event (fig.get_handle (), "selectiontype", - Utils::figureSelectionType (m), false); - emit gh_set_event (fig.get_handle (), "currentpoint", - Utils::figureCurrentPoint (fig, m), - false); - emit gh_callback_event (fig.get_handle (), - "windowbuttondownfcn"); - emit gh_callback_event (m_handle, "buttondownfcn"); + case base_properties::ID_VISIBLE: + w->setVisible (up.is_visible ()); + break; + + case uicontrol::properties::ID_KEYPRESSFCN: + m_keyPressHandlerDefined = ! up.get_keypressfcn ().isempty (); + break; + + case uicontrol::properties::ID___FOCUS__: + if (up.is___focus__ ()) + w->setFocus (); + else + w->clearFocus (); + break; - if (m->button () == Qt::RightButton) - ContextMenu::executeAt (m_interpreter, up, m->globalPos ()); - } - else - { - if (up.style_is ("listbox")) - emit gh_set_event (fig.get_handle (), "selectiontype", - Utils::figureSelectionType (m), - false); - else - emit gh_set_event (fig.get_handle (), "selectiontype", - octave_value ("normal"), false); - } + default: + break; + } + } + + bool + BaseControl::eventFilter (QObject *watched, QEvent *xevent) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + switch (xevent->type ()) + { + case QEvent::Resize: + if (m_normalizedFont) + { + octave::autolock guard (gh_mgr.graphics_lock ()); + + qWidget ()->setFont (Utils::computeFont + (properties ())); } - } - break; + break; - case QEvent::MouseMove: - if (qWidget ()->hasMouseTracking ()) + case QEvent::MouseButtonPress: { octave::autolock guard (gh_mgr.graphics_lock ()); QMouseEvent *m = dynamic_cast (xevent); graphics_object go = object (); + uicontrol::properties& up = Utils::properties (go); graphics_object fig = go.get_ancestor ("figure"); - if (fig) { - emit gh_set_event (fig.get_handle (), "currentpoint", - Utils::figureCurrentPoint (fig, m), false); - emit gh_callback_event (fig.get_handle (), - "windowbuttonmotionfcn"); + emit gh_set_event (fig.get_handle (), "currentobject", + m_handle.value (), false); + + if (m->button () != Qt::LeftButton || ! up.enable_is ("on")) + { + emit gh_set_event (fig.get_handle (), "selectiontype", + Utils::figureSelectionType (m), false); + emit gh_set_event (fig.get_handle (), "currentpoint", + Utils::figureCurrentPoint (fig, m), + false); + emit gh_callback_event (fig.get_handle (), + "windowbuttondownfcn"); + emit gh_callback_event (m_handle, "buttondownfcn"); + + if (m->button () == Qt::RightButton) + ContextMenu::executeAt (m_interpreter, up, m->globalPos ()); + } + else + { + if (up.style_is ("listbox")) + emit gh_set_event (fig.get_handle (), "selectiontype", + Utils::figureSelectionType (m), + false); + else + emit gh_set_event (fig.get_handle (), "selectiontype", + octave_value ("normal"), false); + } } } - break; + break; + + case QEvent::MouseMove: + if (qWidget ()->hasMouseTracking ()) + { + octave::autolock guard (gh_mgr.graphics_lock ()); - case QEvent::KeyPress: - if (m_keyPressHandlerDefined) - { - octave::autolock guard (gh_mgr.graphics_lock ()); + QMouseEvent *m = dynamic_cast (xevent); + graphics_object go = object (); + graphics_object fig = go.get_ancestor ("figure"); - octave_scalar_map keyData = - Utils::makeKeyEventStruct (dynamic_cast (xevent)); - graphics_object fig = object ().get_ancestor ("figure"); + if (fig) + { + emit gh_set_event (fig.get_handle (), "currentpoint", + Utils::figureCurrentPoint (fig, m), false); + emit gh_callback_event (fig.get_handle (), + "windowbuttonmotionfcn"); + } + } + break; - emit gh_set_event (fig.get_handle (), "currentcharacter", - keyData.getfield ("Character"), false); - emit gh_callback_event (m_handle, "keypressfcn", keyData); - } - break; + case QEvent::KeyPress: + if (m_keyPressHandlerDefined) + { + octave::autolock guard (gh_mgr.graphics_lock ()); - case QEvent::FocusIn: - emit gh_set_event (m_handle, "__focus__", "on", false); - break; + octave_scalar_map keyData = + Utils::makeKeyEventStruct (dynamic_cast (xevent)); + graphics_object fig = object ().get_ancestor ("figure"); + + emit gh_set_event (fig.get_handle (), "currentcharacter", + keyData.getfield ("Character"), false); + emit gh_callback_event (m_handle, "keypressfcn", keyData); + } + break; - case QEvent::FocusOut: - emit gh_set_event (m_handle, "__focus__", "off", false); - break; + case QEvent::FocusIn: + emit gh_set_event (m_handle, "__focus__", "on", false); + break; - default: - break; - } + case QEvent::FocusOut: + emit gh_set_event (m_handle, "__focus__", "off", false); + break; - return Object::eventFilter (watched, xevent); -} + default: + break; + } + + return Object::eventFilter (watched, xevent); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/BaseControl.h --- a/libgui/graphics/BaseControl.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/BaseControl.h Tue Dec 06 15:45:27 2022 -0500 @@ -33,29 +33,28 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class BaseControl : public Object -{ -public: - BaseControl (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QWidget *w); - ~BaseControl (void); + class BaseControl : public Object + { + public: + BaseControl (octave::interpreter& interp, + const graphics_object& go, QWidget *w); + ~BaseControl (void); - Container * innerContainer (void) { return nullptr; } + Container * innerContainer (void) { return nullptr; } - bool eventFilter (QObject *watched, QEvent *e); + bool eventFilter (QObject *watched, QEvent *e); -protected: - void init (QWidget *w, bool callBase = false); - void redraw (void); - void update (int pId); + protected: + void init (QWidget *w, bool callBase = false); + void redraw (void); + void update (int pId); -private: - bool m_normalizedFont; - bool m_keyPressHandlerDefined; -}; + private: + bool m_normalizedFont; + bool m_keyPressHandlerDefined; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ButtonControl.cc --- a/libgui/graphics/ButtonControl.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ButtonControl.cc Tue Dec 06 15:45:27 2022 -0500 @@ -39,117 +39,116 @@ OCTAVE_BEGIN_NAMESPACE(octave) -ButtonControl::ButtonControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, - QAbstractButton *btn) -: BaseControl (oct_qobj, interp, go, btn), m_blockCallback (false) -{ - uicontrol::properties& up = properties (); - - QString str = Utils::fromStdString (up.get_string_string ()); - str.replace ("&", "&&"); - btn->setText (str); - if (btn->isCheckable () || up.style_is ("togglebutton")) - { - btn->setCheckable (true); - - Matrix value = up.get_value ().matrix_value (); - - if (value.numel () > 0 && value(0) == up.get_max ()) - btn->setChecked (true); - } + ButtonControl::ButtonControl (octave::interpreter& interp, + const graphics_object& go, + QAbstractButton *btn) + : BaseControl (interp, go, btn), m_blockCallback (false) + { + uicontrol::properties& up = properties (); - connect (btn, &QAbstractButton::clicked, this, &ButtonControl::clicked); - connect (btn, &QAbstractButton::toggled, this, &ButtonControl::toggled); -} - -ButtonControl::~ButtonControl (void) -{ } + QString str = Utils::fromStdString (up.get_string_string ()); + str.replace ("&", "&&"); + btn->setText (str); + if (btn->isCheckable () || up.style_is ("togglebutton")) + { + btn->setCheckable (true); -void -ButtonControl::update (int pId) -{ - uicontrol::properties& up = properties (); - QAbstractButton *btn = qWidget (); + Matrix value = up.get_value ().matrix_value (); - switch (pId) - { - case uicontrol::properties::ID_STRING: - { - QString str = Utils::fromStdString (up.get_string_string ()); - str.replace ("&", "&&"); - btn->setText (str); - break; + if (value.numel () > 0 && value(0) == up.get_max ()) + btn->setChecked (true); } - case uicontrol::properties::ID_VALUE: - m_blockCallback = true; - if (btn->isCheckable ()) - { - Matrix value = up.get_value ().matrix_value (); + connect (btn, &QAbstractButton::clicked, this, &ButtonControl::clicked); + connect (btn, &QAbstractButton::toggled, this, &ButtonControl::toggled); + } - if (value.numel () > 0) - { - double dValue = value(0); + ButtonControl::~ButtonControl (void) + { } + + void + ButtonControl::update (int pId) + { + uicontrol::properties& up = properties (); + QAbstractButton *btn = qWidget (); - if (dValue != 0.0 && dValue != 1.0) - warning ("button value not within valid display range"); - else if (dValue == up.get_min () && btn->isChecked ()) - { - btn->setChecked (false); - if (up.style_is ("radiobutton") || up.style_is ("togglebutton")) - { - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + switch (pId) + { + case uicontrol::properties::ID_STRING: + { + QString str = Utils::fromStdString (up.get_string_string ()); + str.replace ("&", "&&"); + btn->setText (str); + break; + } - Object *parent = Object::parentObject (m_interpreter, gh_mgr.get_object (up.get___myhandle__ ())); - ButtonGroup *btnGroup = dynamic_cast(parent); - if (btnGroup) - btnGroup->selectNothing (); - } - } - else if (dValue == up.get_max () && ! btn->isChecked ()) - btn->setChecked (true); - } - } - m_blockCallback = false; - break; + case uicontrol::properties::ID_VALUE: + m_blockCallback = true; + if (btn->isCheckable ()) + { + Matrix value = up.get_value ().matrix_value (); + + if (value.numel () > 0) + { + double dValue = value(0); + + if (dValue != 0.0 && dValue != 1.0) + warning ("button value not within valid display range"); + else if (dValue == up.get_min () && btn->isChecked ()) + { + btn->setChecked (false); + if (up.style_is ("radiobutton") || up.style_is ("togglebutton")) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - default: - BaseControl::update (pId); - break; - } -} + Object *parent = Object::parentObject (m_interpreter, gh_mgr.get_object (up.get___myhandle__ ())); + ButtonGroup *btnGroup = dynamic_cast(parent); + if (btnGroup) + btnGroup->selectNothing (); + } + } + else if (dValue == up.get_max () && ! btn->isChecked ()) + btn->setChecked (true); + } + } + m_blockCallback = false; + break; -void -ButtonControl::toggled (bool checked) -{ - QAbstractButton *btn = qWidget (); + default: + BaseControl::update (pId); + break; + } + } - if (! m_blockCallback && btn->isCheckable ()) - { - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - octave::autolock guard (gh_mgr.graphics_lock ()); + void + ButtonControl::toggled (bool checked) + { + QAbstractButton *btn = qWidget (); - uicontrol::properties& up = properties (); + if (! m_blockCallback && btn->isCheckable ()) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + octave::autolock guard (gh_mgr.graphics_lock ()); + + uicontrol::properties& up = properties (); + + Matrix oldValue = up.get_value ().matrix_value (); + double newValue = (checked ? up.get_max () : up.get_min ()); - Matrix oldValue = up.get_value ().matrix_value (); - double newValue = (checked ? up.get_max () : up.get_min ()); + if (oldValue.numel () != 1 || (newValue != oldValue(0))) + emit gh_set_event (m_handle, "value", newValue, false); + emit gh_callback_event (m_handle, "callback"); + } + } - if (oldValue.numel () != 1 || (newValue != oldValue(0))) - emit gh_set_event (m_handle, "value", newValue, false); + void + ButtonControl::clicked (void) + { + QAbstractButton *btn = qWidget (); + + if (! btn->isCheckable ()) emit gh_callback_event (m_handle, "callback"); - } -} - -void -ButtonControl::clicked (void) -{ - QAbstractButton *btn = qWidget (); - - if (! btn->isCheckable ()) - emit gh_callback_event (m_handle, "callback"); -} + } OCTAVE_END_NAMESPACE(octave); diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ButtonControl.h --- a/libgui/graphics/ButtonControl.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ButtonControl.h Tue Dec 06 15:45:27 2022 -0500 @@ -32,28 +32,27 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class ButtonControl : public BaseControl -{ - Q_OBJECT + class ButtonControl : public BaseControl + { + Q_OBJECT + + public: + ButtonControl (octave::interpreter& interp, + const graphics_object& go, QAbstractButton *btn); + ~ButtonControl (void); -public: - ButtonControl (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QAbstractButton *btn); - ~ButtonControl (void); - -protected: - void update (int pId); + protected: + void update (int pId); -private slots: - void clicked (void); - void toggled (bool checked); + private slots: + void clicked (void); + void toggled (bool checked); -private: - bool m_blockCallback; -}; + private: + bool m_blockCallback; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ButtonGroup.cc --- a/libgui/graphics/ButtonGroup.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ButtonGroup.cc Tue Dec 06 15:45:27 2022 -0500 @@ -45,7 +45,6 @@ #include "QtHandlesUtils.h" #include "qt-graphics-toolkit.h" -#include "octave-qobject.h" #include "octave-qtutils.h" #include "interpreter.h" @@ -53,479 +52,477 @@ OCTAVE_BEGIN_NAMESPACE(octave) -static int -frameStyleFromProperties (const uibuttongroup::properties& pp) -{ - if (pp.bordertype_is ("none")) - return QFrame::NoFrame; - else if (pp.bordertype_is ("etchedin")) - return (QFrame::Box | QFrame::Sunken); - else if (pp.bordertype_is ("etchedout")) - return (QFrame::Box | QFrame::Raised); - else if (pp.bordertype_is ("beveledin")) - return (QFrame::Panel | QFrame::Sunken); - else if (pp.bordertype_is ("beveledout")) - return (QFrame::Panel | QFrame::Raised); - else - return (QFrame::Panel | QFrame::Plain); -} + static int + frameStyleFromProperties (const uibuttongroup::properties& pp) + { + if (pp.bordertype_is ("none")) + return QFrame::NoFrame; + else if (pp.bordertype_is ("etchedin")) + return (QFrame::Box | QFrame::Sunken); + else if (pp.bordertype_is ("etchedout")) + return (QFrame::Box | QFrame::Raised); + else if (pp.bordertype_is ("beveledin")) + return (QFrame::Panel | QFrame::Sunken); + else if (pp.bordertype_is ("beveledout")) + return (QFrame::Panel | QFrame::Raised); + else + return (QFrame::Panel | QFrame::Plain); + } -static void -setupPalette (const uibuttongroup::properties& pp, QPalette& p) -{ - p.setColor (QPalette::Window, - Utils::fromRgb (pp.get_backgroundcolor_rgb ())); - p.setColor (QPalette::WindowText, - Utils::fromRgb (pp.get_foregroundcolor_rgb ())); - p.setColor (QPalette::Light, - Utils::fromRgb (pp.get_highlightcolor_rgb ())); - p.setColor (QPalette::Dark, - Utils::fromRgb (pp.get_shadowcolor_rgb ())); -} + static void + setupPalette (const uibuttongroup::properties& pp, QPalette& p) + { + p.setColor (QPalette::Window, + Utils::fromRgb (pp.get_backgroundcolor_rgb ())); + p.setColor (QPalette::WindowText, + Utils::fromRgb (pp.get_foregroundcolor_rgb ())); + p.setColor (QPalette::Light, + Utils::fromRgb (pp.get_highlightcolor_rgb ())); + p.setColor (QPalette::Dark, + Utils::fromRgb (pp.get_shadowcolor_rgb ())); + } -static int -borderWidthFromProperties (const uibuttongroup::properties& pp) -{ - int bw = 0; + static int + borderWidthFromProperties (const uibuttongroup::properties& pp) + { + int bw = 0; - if (! pp.bordertype_is ("none")) - { - bw = octave::math::round (pp.get_borderwidth ()); - if (pp.bordertype_is ("etchedin") || pp.bordertype_is ("etchedout")) - bw *= 2; - } + if (! pp.bordertype_is ("none")) + { + bw = octave::math::round (pp.get_borderwidth ()); + if (pp.bordertype_is ("etchedin") || pp.bordertype_is ("etchedout")) + bw *= 2; + } - return bw; -} + return bw; + } -ButtonGroup * -ButtonGroup::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go) -{ - Object *parent = parentObject (interp, go); + ButtonGroup * + ButtonGroup::create (octave::interpreter& interp, const graphics_object& go) + { + Object *parent = parentObject (interp, go); - if (parent) - { - Container *container = parent->innerContainer (); + if (parent) + { + Container *container = parent->innerContainer (); - if (container) - { - QFrame *frame = new QFrame (container); - return new ButtonGroup (oct_qobj, interp, go, - new QButtonGroup (frame), frame); - } - } + if (container) + { + QFrame *frame = new QFrame (container); + return new ButtonGroup (interp, go, + new QButtonGroup (frame), frame); + } + } - return nullptr; -} + return nullptr; + } -ButtonGroup::ButtonGroup (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, - QButtonGroup *buttongroup, QFrame *frame) - : Object (oct_qobj, interp, go, frame), m_hiddenbutton (nullptr), - m_container (nullptr), m_title (nullptr), m_blockUpdates (false) -{ - uibuttongroup::properties& pp = properties (); + ButtonGroup::ButtonGroup (octave::interpreter& interp, + const graphics_object& go, + QButtonGroup *buttongroup, QFrame *frame) + : Object (interp, go, frame), m_hiddenbutton (nullptr), + m_container (nullptr), m_title (nullptr), m_blockUpdates (false) + { + uibuttongroup::properties& pp = properties (); - frame->setObjectName ("UIButtonGroup"); - frame->setAutoFillBackground (true); - Matrix bb = pp.get_boundingbox (false); - frame->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)), - octave::math::round (bb(2)), octave::math::round (bb(3))); - frame->setFrameStyle (frameStyleFromProperties (pp)); - frame->setLineWidth (octave::math::round (pp.get_borderwidth ())); - QPalette pal = frame->palette (); - setupPalette (pp, pal); - frame->setPalette (pal); - m_buttongroup = buttongroup; - m_hiddenbutton = new QRadioButton (frame); - m_hiddenbutton->hide (); - m_buttongroup->addButton (m_hiddenbutton); + frame->setObjectName ("UIButtonGroup"); + frame->setAutoFillBackground (true); + Matrix bb = pp.get_boundingbox (false); + frame->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)), + octave::math::round (bb(2)), octave::math::round (bb(3))); + frame->setFrameStyle (frameStyleFromProperties (pp)); + frame->setLineWidth (octave::math::round (pp.get_borderwidth ())); + QPalette pal = frame->palette (); + setupPalette (pp, pal); + frame->setPalette (pal); + m_buttongroup = buttongroup; + m_hiddenbutton = new QRadioButton (frame); + m_hiddenbutton->hide (); + m_buttongroup->addButton (m_hiddenbutton); + + m_container = new Container (frame, interp); + m_container->canvas (m_handle); + + connect (m_container, SIGNAL (interpeter_event (const fcn_callback&)), + this, SIGNAL (interpeter_event (const fcn_callback&))); + + connect (m_container, SIGNAL (interpeter_event (const meth_callback&)), + this, SIGNAL (interpeter_event (const meth_callback&))); - m_container = new Container (frame, oct_qobj, interp); - m_container->canvas (m_handle); - - connect (m_container, SIGNAL (interpeter_event (const fcn_callback&)), - this, SIGNAL (interpeter_event (const fcn_callback&))); + if (frame->hasMouseTracking ()) + { + for (auto *w : frame->findChildren ()) + w->setMouseTracking (true); + for (auto *w : buttongroup->findChildren ()) + w->setMouseTracking (true); + } - connect (m_container, SIGNAL (interpeter_event (const meth_callback&)), - this, SIGNAL (interpeter_event (const meth_callback&))); + QString title = Utils::fromStdString (pp.get_title ()); + if (! title.isEmpty ()) + { + m_title = new QLabel (title, frame); + m_title->setAutoFillBackground (true); + m_title->setContentsMargins (4, 0, 4, 0); + m_title->setPalette (pal); + m_title->setFont (Utils::computeFont (pp, bb(3))); + } - if (frame->hasMouseTracking ()) - { - for (auto *w : frame->findChildren ()) - w->setMouseTracking (true); - for (auto *w : buttongroup->findChildren ()) - w->setMouseTracking (true); - } + frame->installEventFilter (this); + m_container->installEventFilter (this); - QString title = Utils::fromStdString (pp.get_title ()); - if (! title.isEmpty ()) - { - m_title = new QLabel (title, frame); - m_title->setAutoFillBackground (true); - m_title->setContentsMargins (4, 0, 4, 0); - m_title->setPalette (pal); - m_title->setFont (Utils::computeFont (pp, bb(3))); - } - - frame->installEventFilter (this); - m_container->installEventFilter (this); + if (pp.is_visible ()) + { + QTimer::singleShot (0, frame, &QFrame::show); + // FIXME: What is the intent here? QButtonGroup::show is not a + // member of QButtonGroup. + QTimer::singleShot (0, buttongroup, SLOT (show (void))); + } + else + frame->hide (); - if (pp.is_visible ()) - { - QTimer::singleShot (0, frame, &QFrame::show); - // FIXME: What is the intent here? QButtonGroup::show is not a - // member of QButtonGroup. - QTimer::singleShot (0, buttongroup, SLOT (show (void))); - } - else - frame->hide (); + connect (m_buttongroup, + QOverload::of (&QButtonGroup::buttonClicked), + this, &ButtonGroup::buttonClicked); + } - connect (m_buttongroup, - QOverload::of (&QButtonGroup::buttonClicked), - this, &ButtonGroup::buttonClicked); -} + ButtonGroup::~ButtonGroup (void) + { } + + bool + ButtonGroup::eventFilter (QObject *watched, QEvent *xevent) + { + if (! m_blockUpdates) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); -ButtonGroup::~ButtonGroup (void) -{ } + if (watched == qObject ()) + { + switch (xevent->type ()) + { + case QEvent::Resize: + { + octave::autolock guard (gh_mgr.graphics_lock ()); -bool -ButtonGroup::eventFilter (QObject *watched, QEvent *xevent) -{ - if (! m_blockUpdates) - { - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + graphics_object go = object (); - if (watched == qObject ()) - { - switch (xevent->type ()) - { - case QEvent::Resize: - { - octave::autolock guard (gh_mgr.graphics_lock ()); + if (go.valid_object ()) + { + if (m_title) + { + const uibuttongroup::properties& pp = + Utils::properties (go); - graphics_object go = object (); + if (pp.fontunits_is ("normalized")) + { + QFrame *frame = qWidget (); - if (go.valid_object ()) - { - if (m_title) - { - const uibuttongroup::properties& pp = - Utils::properties (go); + m_title->setFont (Utils::computeFont + (pp, frame->height ())); + m_title->resize (m_title->sizeHint ()); + } + } + updateLayout (); + } + } + break; - if (pp.fontunits_is ("normalized")) - { - QFrame *frame = qWidget (); + case QEvent::MouseButtonPress: + { + QMouseEvent *m = dynamic_cast (xevent); - m_title->setFont (Utils::computeFont - (pp, frame->height ())); - m_title->resize (m_title->sizeHint ()); - } - } - updateLayout (); - } + if (m->button () == Qt::RightButton) + { + octave::autolock guard (gh_mgr.graphics_lock ()); + + ContextMenu::executeAt (m_interpreter, properties (), + m->globalPos ()); + } + } + break; + + default: + break; } - break; - - case QEvent::MouseButtonPress: + } + else if (watched == m_container) + { + switch (xevent->type ()) { - QMouseEvent *m = dynamic_cast (xevent); - - if (m->button () == Qt::RightButton) + case QEvent::Resize: + if (qWidget ()->isVisible ()) { octave::autolock guard (gh_mgr.graphics_lock ()); - ContextMenu::executeAt (m_interpreter, properties (), - m->globalPos ()); + properties ().update_boundingbox (); } + break; + + default: + break; } - break; + } + } + + return false; + } + + void + ButtonGroup::update (int pId) + { + uibuttongroup::properties& pp = properties (); + QFrame *frame = qWidget (); + + m_blockUpdates = true; + + switch (pId) + { + case uibuttongroup::properties::ID_POSITION: + { + Matrix bb = pp.get_boundingbox (false); - default: - break; - } + frame->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)), + octave::math::round (bb(2)), octave::math::round (bb(3))); + updateLayout (); } - else if (watched == m_container) + break; + + case uibuttongroup::properties::ID_BORDERWIDTH: + frame->setLineWidth (octave::math::round (pp.get_borderwidth ())); + updateLayout (); + break; + + case uibuttongroup::properties::ID_BACKGROUNDCOLOR: + case uibuttongroup::properties::ID_FOREGROUNDCOLOR: + case uibuttongroup::properties::ID_HIGHLIGHTCOLOR: + case uibuttongroup::properties::ID_SHADOWCOLOR: + { + QPalette pal = frame->palette (); + + setupPalette (pp, pal); + frame->setPalette (pal); + if (m_title) + m_title->setPalette (pal); + } + break; + + case uibuttongroup::properties::ID_TITLE: { - switch (xevent->type ()) + QString title = Utils::fromStdString (pp.get_title ()); + + if (title.isEmpty ()) + { + if (m_title) + delete m_title; + m_title = nullptr; + } + else { - case QEvent::Resize: - if (qWidget ()->isVisible ()) + if (! m_title) + { + QPalette pal = frame->palette (); + + m_title = new QLabel (title, frame); + m_title->setAutoFillBackground (true); + m_title->setContentsMargins (4, 0, 4, 0); + m_title->setPalette (pal); + m_title->setFont (Utils::computeFont (pp)); + m_title->show (); + } + else { - octave::autolock guard (gh_mgr.graphics_lock ()); + m_title->setText (title); + m_title->resize (m_title->sizeHint ()); + } + } + updateLayout (); + } + break; + + case uibuttongroup::properties::ID_TITLEPOSITION: + updateLayout (); + break; + + case uibuttongroup::properties::ID_BORDERTYPE: + frame->setFrameStyle (frameStyleFromProperties (pp)); + updateLayout (); + break; - properties ().update_boundingbox (); - } - break; + case uibuttongroup::properties::ID_FONTNAME: + case uibuttongroup::properties::ID_FONTSIZE: + case uibuttongroup::properties::ID_FONTWEIGHT: + case uibuttongroup::properties::ID_FONTANGLE: + if (m_title) + { + m_title->setFont (Utils::computeFont (pp)); + m_title->resize (m_title->sizeHint ()); + updateLayout (); + } + break; + + case uibuttongroup::properties::ID_VISIBLE: + frame->setVisible (pp.is_visible ()); + updateLayout (); + break; + + case uibuttongroup::properties::ID_SELECTEDOBJECT: + { + graphics_handle h = pp.get_selectedobject (); - default: - break; + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + octave::autolock guard (gh_mgr.graphics_lock ()); + + graphics_object go = gh_mgr.get_object (h); + + Object *selectedObject = qt_graphics_toolkit::toolkitObject (go); + ToggleButtonControl *toggle = static_cast + (selectedObject); + RadioButtonControl *radio = static_cast(selectedObject); + if (toggle) + { + go.get_properties ().set ("value", 1); + } + else if (radio) + { + go.get_properties ().set ("value", 1); + } + else + { + m_hiddenbutton->setChecked (true); } } - } - - return false; -} - -void -ButtonGroup::update (int pId) -{ - uibuttongroup::properties& pp = properties (); - QFrame *frame = qWidget (); + break; - m_blockUpdates = true; - - switch (pId) - { - case uibuttongroup::properties::ID_POSITION: - { - Matrix bb = pp.get_boundingbox (false); - - frame->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)), - octave::math::round (bb(2)), octave::math::round (bb(3))); - updateLayout (); + default: + break; } - break; + + m_blockUpdates = false; + } - case uibuttongroup::properties::ID_BORDERWIDTH: - frame->setLineWidth (octave::math::round (pp.get_borderwidth ())); - updateLayout (); - break; + void + ButtonGroup::redraw (void) + { + update (uibuttongroup::properties::ID_POSITION); + + // FIXME: is it really necessary to update the opengl canvas here? + Canvas *canvas = m_container->canvas (m_handle); + + if (canvas) + canvas->redraw (); + } - case uibuttongroup::properties::ID_BACKGROUNDCOLOR: - case uibuttongroup::properties::ID_FOREGROUNDCOLOR: - case uibuttongroup::properties::ID_HIGHLIGHTCOLOR: - case uibuttongroup::properties::ID_SHADOWCOLOR: - { - QPalette pal = frame->palette (); + void + ButtonGroup::updateLayout (void) + { + uibuttongroup::properties& pp = properties (); + QFrame *frame = qWidget (); + + Matrix bb = pp.get_boundingbox (true); + int bw = borderWidthFromProperties (pp); - setupPalette (pp, pal); - frame->setPalette (pal); - if (m_title) - m_title->setPalette (pal); - } - break; + frame->setFrameRect (QRect (octave::math::round (bb(0)) - bw, + octave::math::round (bb(1)) - bw, + octave::math::round (bb(2)) + 2*bw, octave::math::round (bb(3)) + 2*bw)); + m_container->setGeometry (octave::math::round (bb(0)), + octave::math::round (bb(1)), + octave::math::round (bb(2)), octave::math::round (bb(3))); - case uibuttongroup::properties::ID_TITLE: - { - QString title = Utils::fromStdString (pp.get_title ()); + if (m_blockUpdates) + pp.update_boundingbox (); - if (title.isEmpty ()) - { - if (m_title) - delete m_title; - m_title = nullptr; - } - else - { - if (! m_title) - { - QPalette pal = frame->palette (); - - m_title = new QLabel (title, frame); - m_title->setAutoFillBackground (true); - m_title->setContentsMargins (4, 0, 4, 0); - m_title->setPalette (pal); - m_title->setFont (Utils::computeFont (pp)); - m_title->show (); - } - else - { - m_title->setText (title); - m_title->resize (m_title->sizeHint ()); - } - } - updateLayout (); - } - break; + if (m_title) + { + QSize sz = m_title->sizeHint (); + int offset = 5; - case uibuttongroup::properties::ID_TITLEPOSITION: - updateLayout (); - break; - - case uibuttongroup::properties::ID_BORDERTYPE: - frame->setFrameStyle (frameStyleFromProperties (pp)); - updateLayout (); - break; + if (pp.titleposition_is ("lefttop")) + m_title->move (bw+offset, 0); + else if (pp.titleposition_is ("righttop")) + m_title->move (frame->width () - bw - offset - sz.width (), 0); + else if (pp.titleposition_is ("leftbottom")) + m_title->move (bw+offset, frame->height () - sz.height ()); + else if (pp.titleposition_is ("rightbottom")) + m_title->move (frame->width () - bw - offset - sz.width (), + frame->height () - sz.height ()); + else if (pp.titleposition_is ("centertop")) + m_title->move (frame->width () / 2 - sz.width () / 2, 0); + else if (pp.titleposition_is ("centerbottom")) + m_title->move (frame->width () / 2 - sz.width () / 2, + frame->height () - sz.height ()); + } + } - case uibuttongroup::properties::ID_FONTNAME: - case uibuttongroup::properties::ID_FONTSIZE: - case uibuttongroup::properties::ID_FONTWEIGHT: - case uibuttongroup::properties::ID_FONTANGLE: - if (m_title) - { - m_title->setFont (Utils::computeFont (pp)); - m_title->resize (m_title->sizeHint ()); - updateLayout (); - } - break; + void + ButtonGroup::selectNothing (void) + { + m_hiddenbutton->setChecked (true); + } - case uibuttongroup::properties::ID_VISIBLE: - frame->setVisible (pp.is_visible ()); - updateLayout (); - break; + void + ButtonGroup::addButton (QAbstractButton *btn) + { + m_buttongroup->addButton (btn); + connect (btn, &QAbstractButton::toggled, this, &ButtonGroup::buttonToggled); + } - case uibuttongroup::properties::ID_SELECTEDOBJECT: + void + ButtonGroup::buttonToggled (bool toggled) + { + Q_UNUSED (toggled); + if (! m_blockUpdates) { - graphics_handle h = pp.get_selectedobject (); - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); octave::autolock guard (gh_mgr.graphics_lock ()); - graphics_object go = gh_mgr.get_object (h); + uibuttongroup::properties& bp = properties (); - Object *selectedObject = qt_graphics_toolkit::toolkitObject (go); - ToggleButtonControl *toggle = static_cast - (selectedObject); - RadioButtonControl *radio = static_cast(selectedObject); - if (toggle) - { - go.get_properties ().set ("value", 1); - } - else if (radio) - { - go.get_properties ().set ("value", 1); - } - else - { - m_hiddenbutton->setChecked (true); - } - } - break; + graphics_handle oldValue = bp.get_selectedobject (); - default: - break; - } - - m_blockUpdates = false; -} + QAbstractButton *checkedBtn = m_buttongroup->checkedButton (); -void -ButtonGroup::redraw (void) -{ - update (uibuttongroup::properties::ID_POSITION); - - // FIXME: is it really necessary to update the opengl canvas here? - Canvas *canvas = m_container->canvas (m_handle); - - if (canvas) - canvas->redraw (); -} - -void -ButtonGroup::updateLayout (void) -{ - uibuttongroup::properties& pp = properties (); - QFrame *frame = qWidget (); + graphics_handle newValue = graphics_handle (); + if (checkedBtn != m_hiddenbutton) + { + Object *checkedObj = Object::fromQObject (checkedBtn); + newValue = checkedObj->properties ().get___myhandle__ (); + } - Matrix bb = pp.get_boundingbox (true); - int bw = borderWidthFromProperties (pp); + if (oldValue != newValue) + emit gh_set_event (m_handle, "selectedobject", + newValue.as_octave_value (), false); + } + } - frame->setFrameRect (QRect (octave::math::round (bb(0)) - bw, - octave::math::round (bb(1)) - bw, - octave::math::round (bb(2)) + 2*bw, octave::math::round (bb(3)) + 2*bw)); - m_container->setGeometry (octave::math::round (bb(0)), - octave::math::round (bb(1)), - octave::math::round (bb(2)), octave::math::round (bb(3))); - - if (m_blockUpdates) - pp.update_boundingbox (); - - if (m_title) - { - QSize sz = m_title->sizeHint (); - int offset = 5; + void + ButtonGroup::buttonClicked (QAbstractButton *btn) + { + Q_UNUSED (btn); - if (pp.titleposition_is ("lefttop")) - m_title->move (bw+offset, 0); - else if (pp.titleposition_is ("righttop")) - m_title->move (frame->width () - bw - offset - sz.width (), 0); - else if (pp.titleposition_is ("leftbottom")) - m_title->move (bw+offset, frame->height () - sz.height ()); - else if (pp.titleposition_is ("rightbottom")) - m_title->move (frame->width () - bw - offset - sz.width (), - frame->height () - sz.height ()); - else if (pp.titleposition_is ("centertop")) - m_title->move (frame->width () / 2 - sz.width () / 2, 0); - else if (pp.titleposition_is ("centerbottom")) - m_title->move (frame->width () / 2 - sz.width () / 2, - frame->height () - sz.height ()); - } -} + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + octave::autolock guard (gh_mgr.graphics_lock ()); + + uibuttongroup::properties& bp = properties (); -void -ButtonGroup::selectNothing (void) -{ - m_hiddenbutton->setChecked (true); -} - -void -ButtonGroup::addButton (QAbstractButton *btn) -{ - m_buttongroup->addButton (btn); - connect (btn, &QAbstractButton::toggled, this, &ButtonGroup::buttonToggled); -} + graphics_handle oldValue = bp.get_selectedobject (); -void -ButtonGroup::buttonToggled (bool toggled) -{ - Q_UNUSED (toggled); - if (! m_blockUpdates) - { - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - octave::autolock guard (gh_mgr.graphics_lock ()); - - uibuttongroup::properties& bp = properties (); - - graphics_handle oldValue = bp.get_selectedobject (); + QAbstractButton *checkedBtn = m_buttongroup->checkedButton (); + Object *checkedObj = Object::fromQObject (checkedBtn); + graphics_handle newValue = checkedObj->properties ().get___myhandle__ (); - QAbstractButton *checkedBtn = m_buttongroup->checkedButton (); - - graphics_handle newValue = graphics_handle (); - if (checkedBtn != m_hiddenbutton) - { - Object *checkedObj = Object::fromQObject (checkedBtn); - newValue = checkedObj->properties ().get___myhandle__ (); - } - - if (oldValue != newValue) - emit gh_set_event (m_handle, "selectedobject", - newValue.as_octave_value (), false); - } -} - -void -ButtonGroup::buttonClicked (QAbstractButton *btn) -{ - Q_UNUSED (btn); - - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - octave::autolock guard (gh_mgr.graphics_lock ()); - - uibuttongroup::properties& bp = properties (); - - graphics_handle oldValue = bp.get_selectedobject (); - - QAbstractButton *checkedBtn = m_buttongroup->checkedButton (); - Object *checkedObj = Object::fromQObject (checkedBtn); - graphics_handle newValue = checkedObj->properties ().get___myhandle__ (); - - if (oldValue != newValue) - { - octave_scalar_map eventData; - eventData.setfield ("OldValue", oldValue.as_octave_value ()); - eventData.setfield ("NewValue", newValue.as_octave_value ()); - eventData.setfield ("Source", bp.get___myhandle__ ().as_octave_value ()); - eventData.setfield ("EventName", "SelectionChanged"); - octave_value selectionChangedEventObject (eventData); - emit gh_callback_event (m_handle, "selectionchangedfcn", - selectionChangedEventObject); - } -} + if (oldValue != newValue) + { + octave_scalar_map eventData; + eventData.setfield ("OldValue", oldValue.as_octave_value ()); + eventData.setfield ("NewValue", newValue.as_octave_value ()); + eventData.setfield ("Source", bp.get___myhandle__ ().as_octave_value ()); + eventData.setfield ("EventName", "SelectionChanged"); + octave_value selectionChangedEventObject (eventData); + emit gh_callback_event (m_handle, "selectionchangedfcn", + selectionChangedEventObject); + } + } OCTAVE_END_NAMESPACE(octave); diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ButtonGroup.h --- a/libgui/graphics/ButtonGroup.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ButtonGroup.h Tue Dec 06 15:45:27 2022 -0500 @@ -36,51 +36,50 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; + + class Container; -class Container; - -class ButtonGroup : public Object -{ - Q_OBJECT + class ButtonGroup : public Object + { + Q_OBJECT -public: - ButtonGroup (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QButtonGroup *buttongroup, - QFrame *frame); - ~ButtonGroup (void); + public: + ButtonGroup (octave::interpreter& interp, + const graphics_object& go, QButtonGroup *buttongroup, + QFrame *frame); + ~ButtonGroup (void); - Container * innerContainer (void) { return m_container; } + Container * innerContainer (void) { return m_container; } - bool eventFilter (QObject *watched, QEvent *event); + bool eventFilter (QObject *watched, QEvent *event); - static ButtonGroup * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + static ButtonGroup * + create (octave::interpreter& interp, + const graphics_object& go); - void addButton (QAbstractButton *btn); + void addButton (QAbstractButton *btn); - void selectNothing (void); + void selectNothing (void); -protected: - void update (int pId); - void redraw (void); + protected: + void update (int pId); + void redraw (void); -private slots: - void buttonToggled (bool toggled); - void buttonClicked (QAbstractButton *btn); + private slots: + void buttonToggled (bool toggled); + void buttonClicked (QAbstractButton *btn); -private: - void updateLayout (void); + private: + void updateLayout (void); -private: - QButtonGroup *m_buttongroup; - QRadioButton *m_hiddenbutton; - Container *m_container; - QLabel *m_title; - bool m_blockUpdates; -}; + private: + QButtonGroup *m_buttongroup; + QRadioButton *m_hiddenbutton; + Container *m_container; + QLabel *m_title; + bool m_blockUpdates; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/Canvas.cc --- a/libgui/graphics/Canvas.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/Canvas.cc Tue Dec 06 15:45:27 2022 -0500 @@ -43,7 +43,7 @@ #include "qt-graphics-toolkit.h" #include "annotation-dialog.h" -#include "octave-qobject.h" +#include "gui-settings.h" #include "qt-interpreter-events.h" #include "builtin-defun-decls.h" @@ -53,905 +53,905 @@ OCTAVE_BEGIN_NAMESPACE(octave) -void -Canvas::redraw (bool sync) -{ - QWidget *w = qWidget (); + void + Canvas::redraw (bool sync) + { + QWidget *w = qWidget (); - if (w) - { - if (sync) - w->repaint (); - else - w->update (); - } -} + if (w) + { + if (sync) + w->repaint (); + else + w->update (); + } + } -void -Canvas::blockRedraw (bool block) -{ - m_redrawBlocked = block; -} + void + Canvas::blockRedraw (bool block) + { + m_redrawBlocked = block; + } -QCursor -Canvas::make_cursor (const QString& name, int hot_x, int hot_y) -{ - octave::resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + QCursor + Canvas::make_cursor (const QString& name, int hot_x, int hot_y) + { + gui_settings settings; - QIcon icon = rmgr.icon (name); + QIcon icon = settings.icon (name); - return QCursor (icon.pixmap (22, 22), hot_x, hot_y); -} + return QCursor (icon.pixmap (22, 22), hot_x, hot_y); + } -void -Canvas::setCursor (MouseMode mode, std::string fallback, - QImage cdata, Matrix hotspot) -{ - QWidget *w = qWidget (); - QCursor cursor = Qt::ArrowCursor; - if (w) - { - switch (mode) - { - case NoMode: + void + Canvas::setCursor (MouseMode mode, std::string fallback, + QImage cdata, Matrix hotspot) + { + QWidget *w = qWidget (); + QCursor cursor = Qt::ArrowCursor; + if (w) + { + switch (mode) { - cursor = Qt::ArrowCursor; + case NoMode: + { + cursor = Qt::ArrowCursor; - if (fallback == "arrow") - cursor = Qt::ArrowCursor; - else if (fallback == "botl") - cursor = make_cursor ("bottom_left_corner", 5, 16); - else if (fallback == "botr") - cursor = make_cursor ("bottom_right_corner", 16, 16); - else if (fallback == "bottom") - cursor = make_cursor ("bottom_side", 11, 16); - else if (fallback == "circle") - cursor = make_cursor ("circle", 10, 10); - else if (fallback == "cross" || fallback == "crosshair") - cursor = make_cursor ("cross", 10, 10); - else if (fallback == "custom") - { - if (hotspot(0) > cdata.width () || hotspot(0) < 1.0 - || hotspot(1) > cdata.height () || hotspot(1) < 1.0) - hotspot = Matrix (1, 2, 1); + if (fallback == "arrow") + cursor = Qt::ArrowCursor; + else if (fallback == "botl") + cursor = make_cursor ("bottom_left_corner", 5, 16); + else if (fallback == "botr") + cursor = make_cursor ("bottom_right_corner", 16, 16); + else if (fallback == "bottom") + cursor = make_cursor ("bottom_side", 11, 16); + else if (fallback == "circle") + cursor = make_cursor ("circle", 10, 10); + else if (fallback == "cross" || fallback == "crosshair") + cursor = make_cursor ("cross", 10, 10); + else if (fallback == "custom") + { + if (hotspot(0) > cdata.width () || hotspot(0) < 1.0 + || hotspot(1) > cdata.height () || hotspot(1) < 1.0) + hotspot = Matrix (1, 2, 1); - cursor = QCursor (QPixmap::fromImage (cdata), - static_cast (hotspot(1) - 1), - static_cast (hotspot(0) - 1)); - } - else if (fallback == "fleur") - cursor = make_cursor ("fleur", 10, 4); - else if (fallback == "hand") - cursor = make_cursor ("hand2", 7, 3); - else if (fallback == "ibeam") - cursor = Qt::IBeamCursor; - else if (fallback == "left") - cursor = make_cursor ("left_side", 4, 10); - else if (fallback == "right") - cursor = make_cursor ("right_side", 17, 10); - else if (fallback == "top") - cursor = make_cursor ("top_side", 11, 4); - else if (fallback == "topl") - cursor = make_cursor ("top_left_corner", 4, 4); - else if (fallback == "topr") - cursor = make_cursor ("top_right_corner", 16, 4); - else if (fallback == "watch") - cursor = Qt::BusyCursor; - } - break; - case SelectMode: - cursor = Qt::ArrowCursor; - break; + cursor = QCursor (QPixmap::fromImage (cdata), + static_cast (hotspot(1) - 1), + static_cast (hotspot(0) - 1)); + } + else if (fallback == "fleur") + cursor = make_cursor ("fleur", 10, 4); + else if (fallback == "hand") + cursor = make_cursor ("hand2", 7, 3); + else if (fallback == "ibeam") + cursor = Qt::IBeamCursor; + else if (fallback == "left") + cursor = make_cursor ("left_side", 4, 10); + else if (fallback == "right") + cursor = make_cursor ("right_side", 17, 10); + else if (fallback == "top") + cursor = make_cursor ("top_side", 11, 4); + else if (fallback == "topl") + cursor = make_cursor ("top_left_corner", 4, 4); + else if (fallback == "topr") + cursor = make_cursor ("top_right_corner", 16, 4); + else if (fallback == "watch") + cursor = Qt::BusyCursor; + } + break; + case SelectMode: + cursor = Qt::ArrowCursor; + break; + + case PanMode: + cursor = make_cursor ("figure-pan"); + break; + + case RotateMode: + cursor = make_cursor ("figure-rotate"); + break; + + case TextMode: + cursor = Qt::IBeamCursor; + break; + + case ZoomInMode: + cursor = make_cursor ("figure-zoom-in", 9, 9); + break; - case PanMode: - cursor = make_cursor ("figure-pan"); - break; + case ZoomOutMode: + cursor = make_cursor ("figure-zoom-out", 9, 9); + break; - case RotateMode: - cursor = make_cursor ("figure-rotate"); - break; + default: + cursor = Qt::ArrowCursor; + break; + } + w->setCursor (cursor); + } + } - case TextMode: - cursor = Qt::IBeamCursor; - break; + /* + Two updateCurrentPoint() routines are required: + 1) Used for QMouseEvents where cursor position data is in callback from Qt. + 2) Used for QKeyEvents where cursor position must be determined. + */ + void + Canvas::updateCurrentPoint (const graphics_object& fig, + const graphics_object& obj, QMouseEvent *event) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - case ZoomInMode: - cursor = make_cursor ("figure-zoom-in", 9, 9); - break; - - case ZoomOutMode: - cursor = make_cursor ("figure-zoom-out", 9, 9); - break; + octave::autolock guard (gh_mgr.graphics_lock ()); - default: - cursor = Qt::ArrowCursor; - break; - } - w->setCursor (cursor); - } -} + emit gh_set_event (fig.get_handle (), "currentpoint", + Utils::figureCurrentPoint (fig, event), false); + + Matrix children = obj.get_properties ().get_children (); + octave_idx_type num_children = children.numel (); + + for (int i = 0; i < num_children; i++) + { + graphics_object childObj (gh_mgr.get_object (children(i))); -/* - Two updateCurrentPoint() routines are required: - 1) Used for QMouseEvents where cursor position data is in callback from Qt. - 2) Used for QKeyEvents where cursor position must be determined. -*/ -void -Canvas::updateCurrentPoint (const graphics_object& fig, - const graphics_object& obj, QMouseEvent *event) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + if (childObj.isa ("axes")) + { + axes::properties& ap = Utils::properties (childObj); + Matrix x_zlim = ap.get_transform_zlim (); + graphics_xform x_form = ap.get_transform (); - octave::autolock guard (gh_mgr.graphics_lock ()); + ColumnVector p1 = x_form.untransform (event->x (), event->y (), + x_zlim(0)); + ColumnVector p2 = x_form.untransform (event->x (), event->y (), + x_zlim(1)); - emit gh_set_event (fig.get_handle (), "currentpoint", - Utils::figureCurrentPoint (fig, event), false); + Matrix cp (2, 3, 0.0); + + cp(0, 0) = p1(0); cp(0, 1) = p1(1); cp(0, 2) = p1(2); + cp(1, 0) = p2(0); cp(1, 1) = p2(1); cp(1, 2) = p2(2); - Matrix children = obj.get_properties ().get_children (); - octave_idx_type num_children = children.numel (); + emit gh_set_event (childObj.get_handle (), "currentpoint", cp, + false); + } + } + } - for (int i = 0; i < num_children; i++) - { - graphics_object childObj (gh_mgr.get_object (children(i))); + void + Canvas::updateCurrentPoint (const graphics_object& fig, + const graphics_object& obj) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - if (childObj.isa ("axes")) - { - axes::properties& ap = Utils::properties (childObj); - Matrix x_zlim = ap.get_transform_zlim (); - graphics_xform x_form = ap.get_transform (); + octave::autolock guard (gh_mgr.graphics_lock ()); + + emit gh_set_event (fig.get_handle (), "currentpoint", + Utils::figureCurrentPoint (fig), false); - ColumnVector p1 = x_form.untransform (event->x (), event->y (), - x_zlim(0)); - ColumnVector p2 = x_form.untransform (event->x (), event->y (), - x_zlim(1)); + Matrix children = obj.get_properties ().get_children (); + octave_idx_type num_children = children.numel (); - Matrix cp (2, 3, 0.0); - - cp(0, 0) = p1(0); cp(0, 1) = p1(1); cp(0, 2) = p1(2); - cp(1, 0) = p2(0); cp(1, 1) = p2(1); cp(1, 2) = p2(2); + for (int i = 0; i < num_children; i++) + { + graphics_object childObj (gh_mgr.get_object (children(i))); - emit gh_set_event (childObj.get_handle (), "currentpoint", cp, - false); - } - } -} + if (childObj.isa ("axes")) + { + // FIXME: QCursor::pos() may give inaccurate results with + // asynchronous window systems like X11 over ssh. + QWidget *w = qWidget (); + QPoint p = w->mapFromGlobal (QCursor::pos ()); + axes::properties& ap = Utils::properties (childObj); + Matrix x_zlim = ap.get_transform_zlim (); + graphics_xform x_form = ap.get_transform (); -void -Canvas::updateCurrentPoint (const graphics_object& fig, - const graphics_object& obj) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + ColumnVector p1 = x_form.untransform (p.x (), p.y (), x_zlim(0)); + ColumnVector p2 = x_form.untransform (p.x (), p.y (), x_zlim(1)); + + Matrix cp (2, 3, 0.0); + + cp(0, 0) = p1(0); cp(0, 1) = p1(1); cp(0, 2) = p1(2); + cp(1, 0) = p2(0); cp(1, 1) = p2(1); cp(1, 2) = p2(2); - octave::autolock guard (gh_mgr.graphics_lock ()); - - emit gh_set_event (fig.get_handle (), "currentpoint", - Utils::figureCurrentPoint (fig), false); + emit gh_set_event (childObj.get_handle (), "currentpoint", cp, + false); + } + } + } - Matrix children = obj.get_properties ().get_children (); - octave_idx_type num_children = children.numel (); + static void + autoscale_axes (gh_manager& gh_mgr, axes::properties& ap) + { + octave::autolock guard (gh_mgr.graphics_lock ()); - for (int i = 0; i < num_children; i++) - { - graphics_object childObj (gh_mgr.get_object (children(i))); + // Reset zoom stack + ap.clear_zoom_stack (false); + + ap.set_xlimmode ("auto"); + ap.set_ylimmode ("auto"); + ap.set_zlimmode ("auto"); + } - if (childObj.isa ("axes")) - { - // FIXME: QCursor::pos() may give inaccurate results with - // asynchronous window systems like X11 over ssh. - QWidget *w = qWidget (); - QPoint p = w->mapFromGlobal (QCursor::pos ()); - axes::properties& ap = Utils::properties (childObj); - Matrix x_zlim = ap.get_transform_zlim (); - graphics_xform x_form = ap.get_transform (); + void + Canvas::canvasPaintEvent (void) + { + if (! m_redrawBlocked) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + octave::autolock guard (gh_mgr.graphics_lock ()); + + draw (m_handle); - ColumnVector p1 = x_form.untransform (p.x (), p.y (), x_zlim(0)); - ColumnVector p2 = x_form.untransform (p.x (), p.y (), x_zlim(1)); - - Matrix cp (2, 3, 0.0); + if ((m_mouseMode == ZoomInMode && m_mouseAxes.ok ()) || m_rectMode) + drawZoomBox (m_mouseAnchor, m_mouseCurrent); + } + } - cp(0, 0) = p1(0); cp(0, 1) = p1(1); cp(0, 2) = p1(2); - cp(1, 0) = p2(0); cp(1, 1) = p2(1); cp(1, 2) = p2(2); + static bool + pan_enabled (const graphics_object figObj) + { + // Getting pan mode property: + octave_value ov_pm + = Utils::properties
(figObj).get___pan_mode__ (); - emit gh_set_event (childObj.get_handle (), "currentpoint", cp, - false); - } - } -} + octave_scalar_map pm = ov_pm.scalar_map_value (); -static void -autoscale_axes (gh_manager& gh_mgr, axes::properties& ap) -{ - octave::autolock guard (gh_mgr.graphics_lock ()); + return pm.contents ("Enable").string_value () == "on"; + } - // Reset zoom stack - ap.clear_zoom_stack (false); + static std::string + pan_mode (const graphics_object figObj) + { + // Getting pan mode property: + octave_value ov_pm + = Utils::properties
(figObj).get___pan_mode__ (); + + octave_scalar_map pm = ov_pm.scalar_map_value (); - ap.set_xlimmode ("auto"); - ap.set_ylimmode ("auto"); - ap.set_zlimmode ("auto"); -} + return pm.contents ("Motion").string_value (); + } -void -Canvas::canvasPaintEvent (void) -{ - if (! m_redrawBlocked) - { - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + static bool + zoom_enabled (const graphics_object figObj) + { + // Getting zoom mode property: + octave_value ov_zm + = Utils::properties
(figObj).get___zoom_mode__ (); - octave::autolock guard (gh_mgr.graphics_lock ()); + octave_scalar_map zm = ov_zm.scalar_map_value (); - draw (m_handle); + return zm.contents ("Enable").string_value () == "on"; + } - if ((m_mouseMode == ZoomInMode && m_mouseAxes.ok ()) || m_rectMode) - drawZoomBox (m_mouseAnchor, m_mouseCurrent); - } -} + static std::string + zoom_mode (const graphics_object figObj) + { + // Getting zoom mode property: + octave_value ov_zm + = Utils::properties
(figObj).get___zoom_mode__ (); -static bool -pan_enabled (const graphics_object figObj) -{ - // Getting pan mode property: - octave_value ov_pm - = Utils::properties
(figObj).get___pan_mode__ (); + octave_scalar_map zm = ov_zm.scalar_map_value (); + + return zm.contents ("Motion").string_value (); + } - octave_scalar_map pm = ov_pm.scalar_map_value (); - - return pm.contents ("Enable").string_value () == "on"; -} + void + Canvas::select_object (graphics_object obj, QMouseEvent *event, + graphics_object& currentObj, graphics_object& axesObj, + bool axes_only, std::vector omit) + { + QList axesList; + Matrix children = obj.get_properties ().get_all_children (); + octave_idx_type num_children = children.numel (); -static std::string -pan_mode (const graphics_object figObj) -{ - // Getting pan mode property: - octave_value ov_pm - = Utils::properties
(figObj).get___pan_mode__ (); + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + for (int i = 0; i < num_children; i++) + { + graphics_object childObj (gh_mgr.get_object (children(i))); - octave_scalar_map pm = ov_pm.scalar_map_value (); - - return pm.contents ("Motion").string_value (); -} - -static bool -zoom_enabled (const graphics_object figObj) -{ - // Getting zoom mode property: - octave_value ov_zm - = Utils::properties
(figObj).get___zoom_mode__ (); + if (childObj.isa ("axes")) + { + auto p = omit.begin (); + bool omitfound = false; + while (p != omit.end () && ! omitfound) + { + omitfound = (childObj.get ("tag").string_value () == *p); + p++; + } + if (! omitfound) + axesList.append (childObj); + } + else if (childObj.isa ("uicontrol") || childObj.isa ("uipanel") + || childObj.isa ("uibuttongroup") || childObj.isa ("uitable")) + { + Matrix bb = childObj.get_properties ().get_boundingbox (false); + QRectF r (bb(0), bb(1), bb(2), bb(3)); - octave_scalar_map zm = ov_zm.scalar_map_value (); - - return zm.contents ("Enable").string_value () == "on"; -} + r.adjust (-5, -5, 5, 5); -static std::string -zoom_mode (const graphics_object figObj) -{ - // Getting zoom mode property: - octave_value ov_zm - = Utils::properties
(figObj).get___zoom_mode__ (); + bool rect_contains_pos = r.contains (event->localPos ()); + if (rect_contains_pos) + { + currentObj = childObj; + break; + } + } + } - octave_scalar_map zm = ov_zm.scalar_map_value (); - - return zm.contents ("Motion").string_value (); -} + if (axes_only) + { + QPoint pt = event->pos (); -void -Canvas::select_object (graphics_object obj, QMouseEvent *event, - graphics_object& currentObj, graphics_object& axesObj, - bool axes_only, std::vector omit) -{ - QList axesList; - Matrix children = obj.get_properties ().get_all_children (); - octave_idx_type num_children = children.numel (); + for (QList::ConstIterator it = axesList.begin (); + it != axesList.end (); ++it) + { + const axes::properties& ap = + dynamic_cast ((*it).get_properties ()); - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - for (int i = 0; i < num_children; i++) - { - graphics_object childObj (gh_mgr.get_object (children(i))); + ColumnVector p0 = ap.pixel2coord (pt.x (), pt.y ()); + Matrix xlim = ap.get_xlim ().matrix_value (); + Matrix ylim = ap.get_ylim ().matrix_value (); - if (childObj.isa ("axes")) - { - auto p = omit.begin (); - bool omitfound = false; - while (p != omit.end () && ! omitfound) - { - omitfound = (childObj.get ("tag").string_value () == *p); - p++; - } - if (! omitfound) - axesList.append (childObj); - } - else if (childObj.isa ("uicontrol") || childObj.isa ("uipanel") - || childObj.isa ("uibuttongroup") || childObj.isa ("uitable")) - { - Matrix bb = childObj.get_properties ().get_boundingbox (false); - QRectF r (bb(0), bb(1), bb(2), bb(3)); + if (xlim(0) < p0(0) && xlim(1) > p0(0) + && ylim(0) < p0(1) && ylim(1) > p0(1)) + { + axesObj = *it; + return; + } + } + } + else if (! currentObj) + { + for (QList::ConstIterator it = axesList.begin (); + it != axesList.end (); ++it) + { + graphics_object go = selectFromAxes (*it, event->pos ()); - r.adjust (-5, -5, 5, 5); + if (go) + { + currentObj = go; + axesObj = *it; + } + // FIXME: is this really necessary? the axes object should + // have been selected through selectFromAxes anyway + else if (it->get_properties ().is_hittest ()) + { + Matrix bb = it->get_properties ().get_boundingbox (true); + QRectF r (bb(0), bb(1), bb(2), bb(3)); - bool rect_contains_pos = r.contains (event->localPos ()); - if (rect_contains_pos) - { - currentObj = childObj; - break; - } - } - } + // Allow a rectangle (e.g., Zoom box) to be slightly outside + // the axes and still select it. + r.adjust (-20, -20, 20, 20); + + bool rect_contains_pos = r.contains (event->localPos ()); + if (rect_contains_pos) + axesObj = *it; + } - if (axes_only) - { - QPoint pt = event->pos (); + if (axesObj && currentObj) + break; + } + } + } - for (QList::ConstIterator it = axesList.begin (); - it != axesList.end (); ++it) - { - const axes::properties& ap = - dynamic_cast ((*it).get_properties ()); + void + Canvas::canvasMouseMoveEvent (QMouseEvent *event) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + octave::autolock guard (gh_mgr.graphics_lock ()); + + graphics_object ax = gh_mgr.get_object (m_mouseAxes); - ColumnVector p0 = ap.pixel2coord (pt.x (), pt.y ()); - Matrix xlim = ap.get_xlim ().matrix_value (); - Matrix ylim = ap.get_ylim ().matrix_value (); + if (m_mouseMode != NoMode && (ax.valid_object () || m_mouseMode == TextMode)) + { + switch (m_mouseMode) + { + case RotateMode: + { + axes::properties& ap = Utils::properties (ax); - if (xlim(0) < p0(0) && xlim(1) > p0(0) - && ylim(0) < p0(1) && ylim(1) > p0(1)) - { - axesObj = *it; - return; + ap.rotate3d (m_mouseCurrent.x (), event->x (), + m_mouseCurrent.y (), event->y ()); + + // Update current mouse position + m_mouseCurrent = event->pos (); + + // Force immediate redraw + redraw (true); } - } - } - else if (! currentObj) - { - for (QList::ConstIterator it = axesList.begin (); - it != axesList.end (); ++it) - { - graphics_object go = selectFromAxes (*it, event->pos ()); + break; + case TextMode: + case ZoomInMode: + case ZoomOutMode: + m_mouseCurrent = event->pos (); + redraw (true); + break; - if (go) + case PanMode: { - currentObj = go; - axesObj = *it; - } - // FIXME: is this really necessary? the axes object should - // have been selected through selectFromAxes anyway - else if (it->get_properties ().is_hittest ()) - { - Matrix bb = it->get_properties ().get_boundingbox (true); - QRectF r (bb(0), bb(1), bb(2), bb(3)); + axes::properties& ap = Utils::properties (ax); + + graphics_object figObj (ax.get_ancestor ("figure")); + + std::string mode = pan_mode (figObj); - // Allow a rectangle (e.g., Zoom box) to be slightly outside - // the axes and still select it. - r.adjust (-20, -20, 20, 20); + ColumnVector p0 = ap.pixel2coord (m_mouseCurrent.x (), + m_mouseCurrent.y ()); + ColumnVector p1 = ap.pixel2coord (event->x (), + event->y ()); - bool rect_contains_pos = r.contains (event->localPos ()); - if (rect_contains_pos) - axesObj = *it; + ap.translate_view (mode, p0(0), p1(0), p0(1), p1(1)); + + // Update current mouse position + m_mouseCurrent = event->pos (); + + // Force immediate redraw + redraw (true); } - if (axesObj && currentObj) + default: break; - } - } -} + } + } + else if (m_mouseMode == NoMode) + { + graphics_object obj = gh_mgr.get_object (m_handle); -void -Canvas::canvasMouseMoveEvent (QMouseEvent *event) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + if (obj.valid_object ()) + { + graphics_object figObj (obj.get_ancestor ("figure")); - octave::autolock guard (gh_mgr.graphics_lock ()); + if (figObj.valid_object () + && ! figObj.get ("windowbuttonmotionfcn").isempty ()) + { + updateCurrentPoint (figObj, obj, event); + emit gh_callback_event (figObj.get_handle (), + "windowbuttonmotionfcn"); + } + } + } - graphics_object ax = gh_mgr.get_object (m_mouseAxes); + // Update mouse coordinates in the figure window status bar + graphics_object obj = gh_mgr.get_object (m_handle); + graphics_object figObj = obj.get_ancestor ("figure"); - if (m_mouseMode != NoMode && (ax.valid_object () || m_mouseMode == TextMode)) - { - switch (m_mouseMode) - { - case RotateMode: + if (figObj.valid_object () && obj.valid_object ()) + { + graphics_object currentObj, axesObj; + std::vector omit = {"legend", "colorbar", "scribeoverlay"}; + select_object (obj, event, currentObj, axesObj, true, omit); + + if (axesObj.valid_object ()) { - axes::properties& ap = Utils::properties (ax); + // FIXME: should we use signal/slot mechanism instead of + // directly calling parent fig methods + Figure *fig = + dynamic_cast
(qt_graphics_toolkit::toolkitObject (figObj)); + axes::properties& ap = Utils::properties (axesObj); - ap.rotate3d (m_mouseCurrent.x (), event->x (), - m_mouseCurrent.y (), event->y ()); - - // Update current mouse position - m_mouseCurrent = event->pos (); + if (fig) + fig->updateStatusBar (ap.pixel2coord (event->x (), event->y ())); + } + } + } - // Force immediate redraw - redraw (true); - } - break; - case TextMode: - case ZoomInMode: - case ZoomOutMode: - m_mouseCurrent = event->pos (); - redraw (true); - break; + void + Canvas::canvasMouseDoubleClickEvent (QMouseEvent *event) + { + // same processing as normal click, but event type is MouseButtonDblClick + canvasMousePressEvent (event); + } + + static double + button_number (QMouseEvent *event) + { + double retval = 0; - case PanMode: - { - axes::properties& ap = Utils::properties (ax); + switch (event->button ()) + { + case Qt::LeftButton: + retval = 1; + break; + + case Qt::MiddleButton: + retval = 2; + break; + + case Qt::RightButton: + retval = 3; + break; - graphics_object figObj (ax.get_ancestor ("figure")); + default: + break; + } + + return retval; + } - std::string mode = pan_mode (figObj); + void + Canvas::canvasMousePressEvent (QMouseEvent *event) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + octave::autolock guard (gh_mgr.graphics_lock ()); - ColumnVector p0 = ap.pixel2coord (m_mouseCurrent.x (), - m_mouseCurrent.y ()); - ColumnVector p1 = ap.pixel2coord (event->x (), - event->y ()); + graphics_object obj = gh_mgr.get_object (m_handle); + + bool isdblclick = (event->type () == QEvent::MouseButtonDblClick); - ap.translate_view (mode, p0(0), p1(0), p0(1), p1(1)); + if (obj.valid_object ()) + { + graphics_object figObj (obj.get_ancestor ("figure")); - // Update current mouse position - m_mouseCurrent = event->pos (); - - // Force immediate redraw - redraw (true); + // Any click in a figure canvas makes it current + if (figObj) + { + graphics_object root = gh_mgr.get_object (0); + Utils::properties (root) + .set_currentfigure (figObj.get_handle ().as_octave_value ()); } - default: - break; - } - } - else if (m_mouseMode == NoMode) - { - graphics_object obj = gh_mgr.get_object (m_handle); - - if (obj.valid_object ()) - { - graphics_object figObj (obj.get_ancestor ("figure")); + graphics_object currentObj, axesObj; - if (figObj.valid_object () - && ! figObj.get ("windowbuttonmotionfcn").isempty ()) - { - updateCurrentPoint (figObj, obj, event); - emit gh_callback_event (figObj.get_handle (), - "windowbuttonmotionfcn"); - } - } - } - - // Update mouse coordinates in the figure window status bar - graphics_object obj = gh_mgr.get_object (m_handle); - graphics_object figObj = obj.get_ancestor ("figure"); + // Retrieve selected object. + select_object (obj, event, currentObj, axesObj); - if (figObj.valid_object () && obj.valid_object ()) - { - graphics_object currentObj, axesObj; - std::vector omit = {"legend", "colorbar", "scribeoverlay"}; - select_object (obj, event, currentObj, axesObj, true, omit); - - if (axesObj.valid_object ()) - { - // FIXME: should we use signal/slot mechanism instead of - // directly calling parent fig methods - Figure *fig = - dynamic_cast
(qt_graphics_toolkit::toolkitObject (figObj)); - axes::properties& ap = Utils::properties (axesObj); - - if (fig) - fig->updateStatusBar (ap.pixel2coord (event->x (), event->y ())); - } - } -} - -void -Canvas::canvasMouseDoubleClickEvent (QMouseEvent *event) -{ - // same processing as normal click, but event type is MouseButtonDblClick - canvasMousePressEvent (event); -} + // currentObj may be invalid if, e.g., all objects under the mouse + // click had "hittest" -> "off" or "pickableparts" -> "none". In that + // case, replace with underlying figObj which always accepts mouse + // clicks. + if (! currentObj.valid_object ()) + currentObj = figObj; + else if (! currentObj.get_properties ().is_hittest ()) + { + // Objects with "hittest"->"off" pass the mouse event to their + // parent and so on. + graphics_object tmpgo; + tmpgo = gh_mgr.get_object (currentObj.get_parent ()); + while (tmpgo && ! tmpgo.get_properties ().is_hittest ()) + tmpgo = gh_mgr.get_object (tmpgo.get_parent ()); -static double -button_number (QMouseEvent *event) -{ - double retval = 0; - - switch (event->button ()) - { - case Qt::LeftButton: - retval = 1; - break; - - case Qt::MiddleButton: - retval = 2; - break; - - case Qt::RightButton: - retval = 3; - break; - - default: - break; - } - - return retval; -} + if (tmpgo && tmpgo.get_handle () != 0.0) + currentObj = tmpgo; + else + currentObj = graphics_object (); + } -void -Canvas::canvasMousePressEvent (QMouseEvent *event) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - octave::autolock guard (gh_mgr.graphics_lock ()); - - graphics_object obj = gh_mgr.get_object (m_handle); - - bool isdblclick = (event->type () == QEvent::MouseButtonDblClick); + // Make selected axes current + bool valid_axes = axesObj.valid_object () + && axesObj.get_properties ().handlevisibility_is ("on") + && axesObj.get_properties ().get_tag () != "legend" + && axesObj.get_properties ().get_tag () != "colorbar"; - if (obj.valid_object ()) - { - graphics_object figObj (obj.get_ancestor ("figure")); + if (valid_axes) + Utils::properties
(figObj) + .set_currentaxes (axesObj.get_handle ().as_octave_value ()); - // Any click in a figure canvas makes it current - if (figObj) - { - graphics_object root = gh_mgr.get_object (0); - Utils::properties (root) - .set_currentfigure (figObj.get_handle ().as_octave_value ()); - } + Figure *fig = dynamic_cast
(qt_graphics_toolkit::toolkitObject (figObj)); - graphics_object currentObj, axesObj; + MouseMode newMouseMode = NoMode; - // Retrieve selected object. - select_object (obj, event, currentObj, axesObj); + if (fig) + newMouseMode = fig->mouseMode (); - // currentObj may be invalid if, e.g., all objects under the mouse - // click had "hittest" -> "off" or "pickableparts" -> "none". In that - // case, replace with underlying figObj which always accepts mouse - // clicks. - if (! currentObj.valid_object ()) - currentObj = figObj; - else if (! currentObj.get_properties ().is_hittest ()) - { - // Objects with "hittest"->"off" pass the mouse event to their - // parent and so on. - graphics_object tmpgo; - tmpgo = gh_mgr.get_object (currentObj.get_parent ()); - while (tmpgo && ! tmpgo.get_properties ().is_hittest ()) - tmpgo = gh_mgr.get_object (tmpgo.get_parent ()); - - if (tmpgo && tmpgo.get_handle () != 0.0) - currentObj = tmpgo; - else - currentObj = graphics_object (); - } - - // Make selected axes current - bool valid_axes = axesObj.valid_object () - && axesObj.get_properties ().handlevisibility_is ("on") - && axesObj.get_properties ().get_tag () != "legend" - && axesObj.get_properties ().get_tag () != "colorbar"; + switch (newMouseMode) + { + case NoMode: + { + // Update the figure "currentobject" + auto& fprop = Utils::properties
(figObj); - if (valid_axes) - Utils::properties
(figObj) - .set_currentaxes (axesObj.get_handle ().as_octave_value ()); - - Figure *fig = dynamic_cast
(qt_graphics_toolkit::toolkitObject (figObj)); - - MouseMode newMouseMode = NoMode; - - if (fig) - newMouseMode = fig->mouseMode (); + if (currentObj + && currentObj.get_properties ().handlevisibility_is ("on")) + fprop.set_currentobject (currentObj.get_handle () + .as_octave_value ()); + else + fprop.set_currentobject (Matrix ()); - switch (newMouseMode) - { - case NoMode: - { - // Update the figure "currentobject" - auto& fprop = Utils::properties
(figObj); + // Update figure "selectiontype" and "currentpoint" + emit gh_set_event (figObj.get_handle (), "selectiontype", + Utils::figureSelectionType (event, isdblclick), + false); - if (currentObj - && currentObj.get_properties ().handlevisibility_is ("on")) - fprop.set_currentobject (currentObj.get_handle () - .as_octave_value ()); - else - fprop.set_currentobject (Matrix ()); - - // Update figure "selectiontype" and "currentpoint" - emit gh_set_event (figObj.get_handle (), "selectiontype", - Utils::figureSelectionType (event, isdblclick), - false); - - updateCurrentPoint (figObj, obj, event); + updateCurrentPoint (figObj, obj, event); - emit gh_callback_event (figObj.get_handle (), - "windowbuttondownfcn", - button_number (event)); - - // Execute the "buttondownfcn" of the selected object. If the - // latter is empty then execute the figure "buttondownfcn" - if (currentObj && ! currentObj.get ("buttondownfcn").isempty ()) - emit gh_callback_event (currentObj.get_handle (), - "buttondownfcn", button_number (event)); - else if (figObj && ! figObj.get ("buttondownfcn").isempty ()) emit gh_callback_event (figObj.get_handle (), - "buttondownfcn", button_number (event)); - - // Show context menu of the selected object - if (currentObj && event->button () == Qt::RightButton) - ContextMenu::executeAt (m_interpreter, - currentObj.get_properties (), - event->globalPos ()); - } - break; + "windowbuttondownfcn", + button_number (event)); - case TextMode: - { - if (event->modifiers () == Qt::NoModifier) - { - switch (event->buttons ()) - { - case Qt::LeftButton: - m_mouseAnchor = m_mouseCurrent = event->pos (); - m_mouseMode = newMouseMode; - m_rectMode = true; - } - } - redraw (false); - } - break; + // Execute the "buttondownfcn" of the selected object. If the + // latter is empty then execute the figure "buttondownfcn" + if (currentObj && ! currentObj.get ("buttondownfcn").isempty ()) + emit gh_callback_event (currentObj.get_handle (), + "buttondownfcn", button_number (event)); + else if (figObj && ! figObj.get ("buttondownfcn").isempty ()) + emit gh_callback_event (figObj.get_handle (), + "buttondownfcn", button_number (event)); - case PanMode: - case RotateMode: - case ZoomInMode: - case ZoomOutMode: - if (valid_axes) - { - bool redraw_figure = true; + // Show context menu of the selected object + if (currentObj && event->button () == Qt::RightButton) + ContextMenu::executeAt (m_interpreter, + currentObj.get_properties (), + event->globalPos ()); + } + break; - if (isdblclick) - { - if (event->button () == Qt::LeftButton) - { - axes::properties& ap = Utils::properties (axesObj); - - autoscale_axes (gh_mgr, ap); - } - else - { - redraw_figure = false; - } - } - else if (event->modifiers () == Qt::NoModifier) + case TextMode: + { + if (event->modifiers () == Qt::NoModifier) { switch (event->buttons ()) { case Qt::LeftButton: m_mouseAnchor = m_mouseCurrent = event->pos (); - m_mouseAxes = axesObj.get_handle (); m_mouseMode = newMouseMode; - m_clickMode = newMouseMode == ZoomInMode; - break; + m_rectMode = true; + } + } + redraw (false); + } + break; - case Qt::RightButton: - if (newMouseMode == ZoomInMode) - { - m_mouseAnchor = m_mouseCurrent = event->pos (); - m_mouseAxes = axesObj.get_handle (); - m_mouseMode = newMouseMode; - m_clickMode = false; - } + case PanMode: + case RotateMode: + case ZoomInMode: + case ZoomOutMode: + if (valid_axes) + { + bool redraw_figure = true; - break; - - case Qt::MiddleButton: + if (isdblclick) + { + if (event->button () == Qt::LeftButton) { - axes::properties& ap = - Utils::properties (axesObj); + axes::properties& ap = Utils::properties (axesObj); autoscale_axes (gh_mgr, ap); } - break; + else + { + redraw_figure = false; + } + } + else if (event->modifiers () == Qt::NoModifier) + { + switch (event->buttons ()) + { + case Qt::LeftButton: + m_mouseAnchor = m_mouseCurrent = event->pos (); + m_mouseAxes = axesObj.get_handle (); + m_mouseMode = newMouseMode; + m_clickMode = newMouseMode == ZoomInMode; + break; - default: - redraw_figure = false; - break; - } - } - else if (event->modifiers () == Qt::ShiftModifier) - { - switch (event->buttons ()) - { - case Qt::LeftButton: - if (newMouseMode == ZoomInMode) - { - m_mouseAnchor = m_mouseCurrent = event->pos (); - m_mouseAxes = axesObj.get_handle (); - m_mouseMode = newMouseMode; - m_clickMode = false; - } - break; + case Qt::RightButton: + if (newMouseMode == ZoomInMode) + { + m_mouseAnchor = m_mouseCurrent = event->pos (); + m_mouseAxes = axesObj.get_handle (); + m_mouseMode = newMouseMode; + m_clickMode = false; + } + + break; - default: - redraw_figure = false; - break; - } - } + case Qt::MiddleButton: + { + axes::properties& ap = + Utils::properties (axesObj); - if (redraw_figure) - redraw (false); - } - break; + autoscale_axes (gh_mgr, ap); + } + break; - default: - break; - } - } - -} - -void -Canvas::canvasMouseReleaseEvent (QMouseEvent *event) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - if ((m_mouseMode == ZoomInMode || m_mouseMode == ZoomOutMode) - && m_mouseAxes.ok ()) - { - octave::autolock guard (gh_mgr.graphics_lock ()); + default: + redraw_figure = false; + break; + } + } + else if (event->modifiers () == Qt::ShiftModifier) + { + switch (event->buttons ()) + { + case Qt::LeftButton: + if (newMouseMode == ZoomInMode) + { + m_mouseAnchor = m_mouseCurrent = event->pos (); + m_mouseAxes = axesObj.get_handle (); + m_mouseMode = newMouseMode; + m_clickMode = false; + } + break; - graphics_object ax = gh_mgr.get_object (m_mouseAxes); + default: + redraw_figure = false; + break; + } + } - if (ax.valid_object ()) - { - axes::properties& ap = Utils::properties (ax); - - graphics_object obj = gh_mgr.get_object (m_handle); + if (redraw_figure) + redraw (false); + } + break; - graphics_object figObj (obj.get_ancestor ("figure")); + default: + break; + } + } - std::string zm = zoom_mode (figObj); + } - if (m_mouseAnchor == event->pos ()) - { - double factor = (m_clickMode ? 2.0 : 0.5); + void + Canvas::canvasMouseReleaseEvent (QMouseEvent *event) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - ColumnVector p1 = ap.pixel2coord (event->x (), event->y ()); + if ((m_mouseMode == ZoomInMode || m_mouseMode == ZoomOutMode) + && m_mouseAxes.ok ()) + { + octave::autolock guard (gh_mgr.graphics_lock ()); + + graphics_object ax = gh_mgr.get_object (m_mouseAxes); - ap.zoom_about_point (zm, p1(0), p1(1), factor); - } - else if (m_mouseMode == ZoomInMode) - { - ColumnVector p0 = ap.pixel2coord (m_mouseAnchor.x (), - m_mouseAnchor.y ()); - ColumnVector p1 = ap.pixel2coord (event->x (), - event->y ()); + if (ax.valid_object ()) + { + axes::properties& ap = Utils::properties (ax); + + graphics_object obj = gh_mgr.get_object (m_handle); + + graphics_object figObj (obj.get_ancestor ("figure")); - Matrix xl (1, 2, 0.0); - Matrix yl (1, 2, 0.0); + std::string zm = zoom_mode (figObj); + + if (m_mouseAnchor == event->pos ()) + { + double factor = (m_clickMode ? 2.0 : 0.5); + + ColumnVector p1 = ap.pixel2coord (event->x (), event->y ()); - xl(0) = std::min (p0(0), p1(0)); - xl(1) = std::max (p0(0), p1(0)); - yl(0) = std::min (p0(1), p1(1)); - yl(1) = std::max (p0(1), p1(1)); - - ap.zoom (zm, xl, yl); - } + ap.zoom_about_point (zm, p1(0), p1(1), factor); + } + else if (m_mouseMode == ZoomInMode) + { + ColumnVector p0 = ap.pixel2coord (m_mouseAnchor.x (), + m_mouseAnchor.y ()); + ColumnVector p1 = ap.pixel2coord (event->x (), + event->y ()); - redraw (false); - } - } - else if (m_mouseMode == NoMode) - { - octave::autolock guard (gh_mgr.graphics_lock ()); + Matrix xl (1, 2, 0.0); + Matrix yl (1, 2, 0.0); - graphics_object obj = gh_mgr.get_object (m_handle); - - if (obj.valid_object ()) - { - graphics_object figObj (obj.get_ancestor ("figure")); + xl(0) = std::min (p0(0), p1(0)); + xl(1) = std::max (p0(0), p1(0)); + yl(0) = std::min (p0(1), p1(1)); + yl(1) = std::max (p0(1), p1(1)); - updateCurrentPoint (figObj, obj, event); - emit gh_callback_event (figObj.get_handle (), "windowbuttonupfcn"); - } - } - else if (m_mouseMode == TextMode) - { - octave::autolock guard (gh_mgr.graphics_lock ()); + ap.zoom (zm, xl, yl); + } - graphics_object figObj - = gh_mgr.get_object (m_handle).get_ancestor ("figure"); + redraw (false); + } + } + else if (m_mouseMode == NoMode) + { + octave::autolock guard (gh_mgr.graphics_lock ()); + + graphics_object obj = gh_mgr.get_object (m_handle); - if (figObj.valid_object ()) - { - QWidget *w = qWidget (); - if (w) - { - Matrix bb = figObj.get ("position").matrix_value (); - bb(0) = m_mouseAnchor.x () / bb(2); - bb(1) = 1.0 - (m_mouseAnchor.y () / bb(3)); - bb(2) = (event->x () - m_mouseAnchor.x ()) / bb(2); - bb(3) = (m_mouseAnchor.y () - event->y ()) / bb(3); + if (obj.valid_object ()) + { + graphics_object figObj (obj.get_ancestor ("figure")); - octave_value_list props = ovl ("textbox", bb); + updateCurrentPoint (figObj, obj, event); + emit gh_callback_event (figObj.get_handle (), "windowbuttonupfcn"); + } + } + else if (m_mouseMode == TextMode) + { + octave::autolock guard (gh_mgr.graphics_lock ()); + + graphics_object figObj + = gh_mgr.get_object (m_handle).get_ancestor ("figure"); - annotation_dialog anno_dlg (m_octave_qobj, w, props); + if (figObj.valid_object ()) + { + QWidget *w = qWidget (); + if (w) + { + Matrix bb = figObj.get ("position").matrix_value (); + bb(0) = m_mouseAnchor.x () / bb(2); + bb(1) = 1.0 - (m_mouseAnchor.y () / bb(3)); + bb(2) = (event->x () - m_mouseAnchor.x ()) / bb(2); + bb(3) = (m_mouseAnchor.y () - event->y ()) / bb(3); - if (anno_dlg.exec () == QDialog::Accepted) - { - props = anno_dlg.get_properties (); - props.prepend (figObj.get_handle ().as_octave_value ()); - - emit interpreter_event - ([=] (octave::interpreter& interp) - { - // INTERPRETER THREAD + octave_value_list props = ovl ("textbox", bb); - interp.feval ("annotation", props); + annotation_dialog anno_dlg (w, props); + + if (anno_dlg.exec () == QDialog::Accepted) + { + props = anno_dlg.get_properties (); + props.prepend (figObj.get_handle ().as_octave_value ()); - redraw (); - }); - } - } - } - } - m_rectMode = false; - m_mouseAxes = graphics_handle (); - m_mouseMode = NoMode; -} + emit interpreter_event + ([=] (octave::interpreter& interp) + { + // INTERPRETER THREAD + + interp.feval ("annotation", props); -void -Canvas::canvasWheelEvent (QWheelEvent *event) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + redraw (); + }); + } + } + } + } + m_rectMode = false; + m_mouseAxes = graphics_handle (); + m_mouseMode = NoMode; + } - octave::autolock guard (gh_mgr.graphics_lock ()); - - graphics_object obj = gh_mgr.get_object (m_handle); + void + Canvas::canvasWheelEvent (QWheelEvent *event) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - if (obj.valid_object ()) - { - std::string mode; + octave::autolock guard (gh_mgr.graphics_lock ()); - graphics_object figObj (obj.get_ancestor ("figure")); + graphics_object obj = gh_mgr.get_object (m_handle); - graphics_object axesObj; + if (obj.valid_object ()) + { + std::string mode; - Matrix children = obj.get_properties ().get_children (); - octave_idx_type num_children = children.numel (); + graphics_object figObj (obj.get_ancestor ("figure")); + + graphics_object axesObj; - for (int i = 0; i < num_children; i++) - { - graphics_object childObj (gh_mgr.get_object (children(i))); + Matrix children = obj.get_properties ().get_children (); + octave_idx_type num_children = children.numel (); - if (childObj.isa ("axes")) - { + for (int i = 0; i < num_children; i++) + { + graphics_object childObj (gh_mgr.get_object (children(i))); + + if (childObj.isa ("axes")) + { #if defined (HAVE_QWHEELEVENT_POSITION) - QPoint pos = event->position().toPoint (); + QPoint pos = event->position().toPoint (); #else - QPoint pos = event->pos (); + QPoint pos = event->pos (); #endif - graphics_object go = selectFromAxes (childObj, pos); + graphics_object go = selectFromAxes (childObj, pos); - if (go) - { - axesObj = childObj; - break; - } - } - } + if (go) + { + axesObj = childObj; + break; + } + } + } - if (axesObj) - { - MouseMode newMouseMode = NoMode; + if (axesObj) + { + MouseMode newMouseMode = NoMode; - Figure *fig = dynamic_cast
(qt_graphics_toolkit::toolkitObject (figObj)); + Figure *fig = dynamic_cast
(qt_graphics_toolkit::toolkitObject (figObj)); - if (fig) - newMouseMode = fig->mouseMode (); + if (fig) + newMouseMode = fig->mouseMode (); - if (axesObj.get_properties ().handlevisibility_is ("on")) - { - Utils::properties
(figObj) + if (axesObj.get_properties ().handlevisibility_is ("on")) + { + Utils::properties
(figObj) .set_currentaxes (axesObj.get_handle ().as_octave_value ()); - if (zoom_enabled (figObj)) - { + if (zoom_enabled (figObj)) + { #if defined (HAVE_QWHEELEVENT_ANGLEDELTA) - if (event->angleDelta().y () > 0) + if (event->angleDelta().y () > 0) #else if (event->delta () > 0) #endif @@ -959,138 +959,138 @@ else newMouseMode = ZoomOutMode; - mode = zoom_mode (figObj); - } - else if (pan_enabled (figObj)) - { - newMouseMode = PanMode; + mode = zoom_mode (figObj); + } + else if (pan_enabled (figObj)) + { + newMouseMode = PanMode; - mode = pan_mode (figObj); - } - } + mode = pan_mode (figObj); + } + } - bool redrawFigure = true; + bool redrawFigure = true; - switch (newMouseMode) - { - case ZoomInMode: - case ZoomOutMode: + switch (newMouseMode) { - axes::properties& ap = Utils::properties (axesObj); - - // Control how fast to zoom when using scroll wheel. - double wheel_zoom_speed = ap.get_mousewheelzoom (); + case ZoomInMode: + case ZoomOutMode: + { + axes::properties& ap = Utils::properties (axesObj); - // Determine if we're zooming in or out. - double factor = (newMouseMode == ZoomInMode - ? 1 / (1.0 - wheel_zoom_speed) - : 1.0 - wheel_zoom_speed); + // Control how fast to zoom when using scroll wheel. + double wheel_zoom_speed = ap.get_mousewheelzoom (); - // FIXME: should we zoom about point for 2D plots? + // Determine if we're zooming in or out. + double factor = (newMouseMode == ZoomInMode + ? 1 / (1.0 - wheel_zoom_speed) + : 1.0 - wheel_zoom_speed); + + // FIXME: should we zoom about point for 2D plots? - ap.zoom (mode, factor); - } - break; + ap.zoom (mode, factor); + } + break; - case PanMode: - { - axes::properties& ap = Utils::properties (axesObj); + case PanMode: + { + axes::properties& ap = Utils::properties (axesObj); #if defined (HAVE_QWHEELEVENT_ANGLEDELTA) - double factor = (event->angleDelta().y () > 0 ? 0.1 : -0.1); + double factor = (event->angleDelta().y () > 0 ? 0.1 : -0.1); #else - double factor = (event->delta () > 0 ? 0.1 : -0.1); + double factor = (event->delta () > 0 ? 0.1 : -0.1); #endif - if (event->modifiers () == Qt::NoModifier - && mode != "horizontal") - ap.pan ("vertical", factor); - else if (event->modifiers () == Qt::ShiftModifier - && mode != "vertical") - ap.pan ("horizontal", factor); - } - break; + if (event->modifiers () == Qt::NoModifier + && mode != "horizontal") + ap.pan ("vertical", factor); + else if (event->modifiers () == Qt::ShiftModifier + && mode != "vertical") + ap.pan ("horizontal", factor); + } + break; - default: - redrawFigure = false; - break; - } + default: + redrawFigure = false; + break; + } - if (redrawFigure) - redraw (false); - } + if (redrawFigure) + redraw (false); + } - if (! figObj.get ("windowscrollwheelfcn").isempty ()) - { - octave_scalar_map eventData = Utils::makeScrollEventStruct (event); - emit gh_callback_event (m_handle, "windowscrollwheelfcn", - eventData); - } - } -} + if (! figObj.get ("windowscrollwheelfcn").isempty ()) + { + octave_scalar_map eventData = Utils::makeScrollEventStruct (event); + emit gh_callback_event (m_handle, "windowscrollwheelfcn", + eventData); + } + } + } -bool -Canvas::canvasKeyPressEvent (QKeyEvent *event) -{ - if (m_eventMask & KeyPress) - { - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + bool + Canvas::canvasKeyPressEvent (QKeyEvent *event) + { + if (m_eventMask & KeyPress) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - octave::autolock guard (gh_mgr.graphics_lock ()); + octave::autolock guard (gh_mgr.graphics_lock ()); - graphics_object obj = gh_mgr.get_object (m_handle); + graphics_object obj = gh_mgr.get_object (m_handle); - if (obj.valid_object ()) - { - graphics_object figObj (obj.get_ancestor ("figure")); + if (obj.valid_object ()) + { + graphics_object figObj (obj.get_ancestor ("figure")); - updateCurrentPoint (figObj, obj); + updateCurrentPoint (figObj, obj); - octave_scalar_map eventData = Utils::makeKeyEventStruct (event); + octave_scalar_map eventData = Utils::makeKeyEventStruct (event); - emit gh_set_event (figObj.get_handle (), "currentcharacter", - eventData.getfield ("Character"), false); - emit gh_callback_event (figObj.get_handle (), "keypressfcn", - eventData); - } + emit gh_set_event (figObj.get_handle (), "currentcharacter", + eventData.getfield ("Character"), false); + emit gh_callback_event (figObj.get_handle (), "keypressfcn", + eventData); + } - return true; - } + return true; + } - return false; -} + return false; + } -bool -Canvas::canvasKeyReleaseEvent (QKeyEvent *event) -{ - if (! event->isAutoRepeat () && (m_eventMask & KeyRelease)) - { - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + bool + Canvas::canvasKeyReleaseEvent (QKeyEvent *event) + { + if (! event->isAutoRepeat () && (m_eventMask & KeyRelease)) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - octave::autolock guard (gh_mgr.graphics_lock ()); + octave::autolock guard (gh_mgr.graphics_lock ()); - graphics_object obj = gh_mgr.get_object (m_handle); + graphics_object obj = gh_mgr.get_object (m_handle); - if (obj.valid_object ()) - { - graphics_object figObj (obj.get_ancestor ("figure")); - emit gh_callback_event (figObj.get_handle (), "keyreleasefcn", - Utils::makeKeyEventStruct (event)); - } + if (obj.valid_object ()) + { + graphics_object figObj (obj.get_ancestor ("figure")); + emit gh_callback_event (figObj.get_handle (), "keyreleasefcn", + Utils::makeKeyEventStruct (event)); + } - return true; - } + return true; + } - return false; -} + return false; + } -Canvas * -Canvas::create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_handle& handle, QWidget *parent, - const std::string& /* name */) -{ - // Only OpenGL - return new GLCanvas (oct_qobj, interp, handle, parent); -} + Canvas * + Canvas::create (octave::interpreter& interp, + const graphics_handle& handle, QWidget *parent, + const std::string& /* name */) + { + // Only OpenGL + return new GLCanvas (interp, handle, parent); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/Canvas.h --- a/libgui/graphics/Canvas.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/Canvas.h Tue Dec 06 15:45:27 2022 -0500 @@ -43,129 +43,125 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class Canvas : public QObject -{ - Q_OBJECT + class Canvas : public QObject + { + Q_OBJECT -public: - enum EventMask + public: + enum EventMask { KeyPress = 0x01, KeyRelease = 0x02 }; -public: - virtual ~Canvas (void) = default; + public: + virtual ~Canvas (void) = default; - void redraw (bool sync = false); - void blockRedraw (bool block = true); + void redraw (bool sync = false); + void blockRedraw (bool block = true); - void print (const QString& file_cmd, const QString& term) - { - do_print (file_cmd, term, m_handle); - } + void print (const QString& file_cmd, const QString& term) + { + do_print (file_cmd, term, m_handle); + } - void addEventMask (int m) { m_eventMask |= m; } - void clearEventMask (int m) { m_eventMask &= (~m); } - void setEventMask (int m) { m_eventMask = m; } + void addEventMask (int m) { m_eventMask |= m; } + void clearEventMask (int m) { m_eventMask &= (~m); } + void setEventMask (int m) { m_eventMask = m; } - void setCursor (MouseMode mode, std::string fallback, - QImage cdata, Matrix hotspot); + void setCursor (MouseMode mode, std::string fallback, + QImage cdata, Matrix hotspot); - virtual QWidget * qWidget (void) = 0; + virtual QWidget * qWidget (void) = 0; - static Canvas * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_handle& handle, QWidget *parent, - const std::string& name); + static Canvas * + create (octave::interpreter& interp, const graphics_handle& handle, + QWidget *parent, const std::string& name); - virtual uint8NDArray getPixels (void) { return do_getPixels (m_handle); }; + virtual uint8NDArray getPixels (void) { return do_getPixels (m_handle); }; -signals: + signals: + + void interpreter_event (const octave::fcn_callback& fcn); + void interpreter_event (const octave::meth_callback& meth); - void interpreter_event (const octave::fcn_callback& fcn); - void interpreter_event (const octave::meth_callback& meth); + void gh_callback_event (const graphics_handle& h, const std::string& name); - void gh_callback_event (const graphics_handle& h, const std::string& name); + void gh_callback_event (const graphics_handle& h, const std::string& name, + const octave_value& data); - void gh_callback_event (const graphics_handle& h, const std::string& name, - const octave_value& data); + void gh_set_event (const graphics_handle& h, const std::string& name, + const octave_value& value); - void gh_set_event (const graphics_handle& h, const std::string& name, - const octave_value& value); - - void gh_set_event (const graphics_handle& h, const std::string& name, - const octave_value& value, bool notify_toolkit); + void gh_set_event (const graphics_handle& h, const std::string& name, + const octave_value& value, bool notify_toolkit); - void gh_set_event (const graphics_handle& h, const std::string& name, - const octave_value& value, bool notify_toolkit, - bool redraw_figure); -protected: - virtual void draw (const graphics_handle& handle) = 0; - virtual void drawZoomBox (const QPoint& p1, const QPoint& p2) = 0; - virtual void resize (int x, int y, int width, int height) = 0; - virtual graphics_object selectFromAxes (const graphics_object& ax, - const QPoint& pt) = 0; - virtual uint8NDArray do_getPixels (const graphics_handle& handle) = 0; - virtual void do_print (const QString& file_cmd, const QString& term, - const graphics_handle& handle) = 0; + void gh_set_event (const graphics_handle& h, const std::string& name, + const octave_value& value, bool notify_toolkit, + bool redraw_figure); + protected: + virtual void draw (const graphics_handle& handle) = 0; + virtual void drawZoomBox (const QPoint& p1, const QPoint& p2) = 0; + virtual void resize (int x, int y, int width, int height) = 0; + virtual graphics_object selectFromAxes (const graphics_object& ax, + const QPoint& pt) = 0; + virtual uint8NDArray do_getPixels (const graphics_handle& handle) = 0; + virtual void do_print (const QString& file_cmd, const QString& term, + const graphics_handle& handle) = 0; -protected: - Canvas (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_handle& handle) - : m_octave_qobj (oct_qobj), - m_interpreter (interp), - m_handle (handle), - m_redrawBlocked (false), - m_mouseMode (NoMode), - m_clickMode (false), - m_eventMask (0), - m_rectMode (false) - { } + protected: + Canvas (octave::interpreter& interp, const graphics_handle& handle) + : m_interpreter (interp), + m_handle (handle), + m_redrawBlocked (false), + m_mouseMode (NoMode), + m_clickMode (false), + m_eventMask (0), + m_rectMode (false) + { } - void canvasToggleAxes (const graphics_handle& handle); - void canvasToggleGrid (const graphics_handle& handle); - void canvasAutoAxes (const graphics_handle& handle); - void canvasPaintEvent (void); - void canvasMouseDoubleClickEvent (QMouseEvent *event); - void canvasMouseMoveEvent (QMouseEvent *event); - void canvasMousePressEvent (QMouseEvent *event); - void canvasMouseReleaseEvent (QMouseEvent *event); - void canvasWheelEvent (QWheelEvent *event); - bool canvasKeyPressEvent (QKeyEvent *event); - bool canvasKeyReleaseEvent (QKeyEvent *event); + void canvasToggleAxes (const graphics_handle& handle); + void canvasToggleGrid (const graphics_handle& handle); + void canvasAutoAxes (const graphics_handle& handle); + void canvasPaintEvent (void); + void canvasMouseDoubleClickEvent (QMouseEvent *event); + void canvasMouseMoveEvent (QMouseEvent *event); + void canvasMousePressEvent (QMouseEvent *event); + void canvasMouseReleaseEvent (QMouseEvent *event); + void canvasWheelEvent (QWheelEvent *event); + bool canvasKeyPressEvent (QKeyEvent *event); + bool canvasKeyReleaseEvent (QKeyEvent *event); - void updateCurrentPoint (const graphics_object& fig, - const graphics_object& obj, QMouseEvent *event); - void updateCurrentPoint (const graphics_object& fig, - const graphics_object& obj); + void updateCurrentPoint (const graphics_object& fig, + const graphics_object& obj, QMouseEvent *event); + void updateCurrentPoint (const graphics_object& fig, + const graphics_object& obj); - void select_object (graphics_object obj, QMouseEvent *event, - graphics_object& currentObj, graphics_object& axesObj, - bool axes_only = false, - std::vector omit = std::vector ()); + void select_object (graphics_object obj, QMouseEvent *event, + graphics_object& currentObj, graphics_object& axesObj, + bool axes_only = false, + std::vector omit = std::vector ()); -protected: - octave::base_qobject& m_octave_qobj; - octave::interpreter& m_interpreter; + protected: -private: + octave::interpreter& m_interpreter; + + private: - QCursor make_cursor (const QString& name, int hot_x = -1, int hot_y = -1); + QCursor make_cursor (const QString& name, int hot_x = -1, int hot_y = -1); - graphics_handle m_handle; - bool m_redrawBlocked; - MouseMode m_mouseMode; - bool m_clickMode; // True: ZoomIn, False: ZoomOut - QPoint m_mouseAnchor; - QPoint m_mouseCurrent; - graphics_handle m_mouseAxes; - int m_eventMask; - bool m_rectMode; -}; + graphics_handle m_handle; + bool m_redrawBlocked; + MouseMode m_mouseMode; + bool m_clickMode; // True: ZoomIn, False: ZoomOut + QPoint m_mouseAnchor; + QPoint m_mouseCurrent; + graphics_handle m_mouseAxes; + int m_eventMask; + bool m_rectMode; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/CheckBoxControl.cc --- a/libgui/graphics/CheckBoxControl.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/CheckBoxControl.cc Tue Dec 06 15:45:27 2022 -0500 @@ -32,66 +32,62 @@ #include "CheckBoxControl.h" #include "Container.h" -#include "octave-qobject.h" - OCTAVE_BEGIN_NAMESPACE(octave) -CheckBoxControl * -CheckBoxControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go) -{ - Object *parent = parentObject (interp, go); + CheckBoxControl * + CheckBoxControl::create (octave::interpreter& interp, + const graphics_object& go) + { + Object *parent = parentObject (interp, go); - if (parent) - { - Container *container = parent->innerContainer (); + if (parent) + { + Container *container = parent->innerContainer (); - if (container) - return new CheckBoxControl (oct_qobj, interp, go, - new QCheckBox (container)); - } + if (container) + return new CheckBoxControl (interp, go, + new QCheckBox (container)); + } - return nullptr; -} + return nullptr; + } -CheckBoxControl::CheckBoxControl (octave::base_qobject& oct_obj, - octave::interpreter& interp, - const graphics_object& go, QCheckBox *box) - : ButtonControl (oct_obj, interp, go, box) -{ - uicontrol::properties& up = properties (); + CheckBoxControl::CheckBoxControl (octave::interpreter& interp, + const graphics_object& go, QCheckBox *box) + : ButtonControl (interp, go, box) + { + uicontrol::properties& up = properties (); - box->setAutoFillBackground (true); - if (up.enable_is ("inactive")) - box->setCheckable (false); -} + box->setAutoFillBackground (true); + if (up.enable_is ("inactive")) + box->setCheckable (false); + } -CheckBoxControl::~CheckBoxControl (void) -{ } + CheckBoxControl::~CheckBoxControl (void) + { } -void -CheckBoxControl::update (int pId) -{ - uicontrol::properties& up = properties (); - QCheckBox *box = qWidget (); + void + CheckBoxControl::update (int pId) + { + uicontrol::properties& up = properties (); + QCheckBox *box = qWidget (); - switch (pId) - { - case uicontrol::properties::ID_ENABLE: + switch (pId) { - if (up.enable_is ("inactive")) - box->setCheckable (false); - else - box->setCheckable (true); + case uicontrol::properties::ID_ENABLE: + { + if (up.enable_is ("inactive")) + box->setCheckable (false); + else + box->setCheckable (true); + ButtonControl::update (pId); + } + break; + + default: ButtonControl::update (pId); + break; } - break; - - default: - ButtonControl::update (pId); - break; - } -} + } OCTAVE_END_NAMESPACE(octave); diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/CheckBoxControl.h --- a/libgui/graphics/CheckBoxControl.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/CheckBoxControl.h Tue Dec 06 15:45:27 2022 -0500 @@ -32,24 +32,22 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class CheckBoxControl : public ButtonControl -{ -public: - CheckBoxControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go, - QCheckBox *box); - ~CheckBoxControl (void); + class CheckBoxControl : public ButtonControl + { + public: + CheckBoxControl (octave::interpreter& interp, const graphics_object& go, + QCheckBox *box); + ~CheckBoxControl (void); - static CheckBoxControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + static CheckBoxControl * + create (octave::interpreter& interp, + const graphics_object& go); -protected: - void update (int pId); -}; + protected: + void update (int pId); + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/Container.cc --- a/libgui/graphics/Container.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/Container.cc Tue Dec 06 15:45:27 2022 -0500 @@ -40,149 +40,147 @@ OCTAVE_BEGIN_NAMESPACE(octave) -Container::Container (QWidget *xparent, octave::base_qobject& oct_qobj, - octave::interpreter& interp) -: ContainerBase (xparent), m_octave_qobj (oct_qobj), - m_interpreter (interp), m_canvas (nullptr) -{ - setFocusPolicy (Qt::ClickFocus); -} + Container::Container (QWidget *xparent, octave::interpreter& interp) + : ContainerBase (xparent), m_interpreter (interp), m_canvas (nullptr) + { + setFocusPolicy (Qt::ClickFocus); + } -Container::~Container (void) -{ } + Container::~Container (void) + { } + + Canvas * + Container::canvas (const graphics_handle& gh, bool xcreate) + { + if (! m_canvas && xcreate) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); -Canvas * -Container::canvas (const graphics_handle& gh, bool xcreate) -{ - if (! m_canvas && xcreate) - { - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + octave::autolock guard (gh_mgr.graphics_lock ()); + + graphics_object go = gh_mgr.get_object (gh); - octave::autolock guard (gh_mgr.graphics_lock ()); + if (go) + { + graphics_object fig = go.get_ancestor ("figure"); - graphics_object go = gh_mgr.get_object (gh); - - if (go) - { - graphics_object fig = go.get_ancestor ("figure"); + m_canvas = Canvas::create (m_interpreter, gh, this, + fig.get ("renderer").string_value ()); - m_canvas = Canvas::create (m_octave_qobj, m_interpreter, gh, this, - fig.get ("renderer").string_value ()); + connect (m_canvas, QOverload::of (&Canvas::interpreter_event), + this, QOverload::of (&Container::interpreter_event)); - connect (m_canvas, QOverload::of (&Canvas::interpreter_event), - this, QOverload::of (&Container::interpreter_event)); + connect (m_canvas, QOverload::of (&Canvas::interpreter_event), + this, QOverload::of (&Container::interpreter_event)); - connect (m_canvas, QOverload::of (&Canvas::interpreter_event), - this, QOverload::of (&Container::interpreter_event)); + connect (m_canvas, + SIGNAL (gh_callback_event (const graphics_handle&, + const std::string&)), + this, + SIGNAL (gh_callback_event (const graphics_handle&, + const std::string&))); - connect (m_canvas, - SIGNAL (gh_callback_event (const graphics_handle&, - const std::string&)), - this, - SIGNAL (gh_callback_event (const graphics_handle&, - const std::string&))); + connect (m_canvas, + SIGNAL (gh_callback_event (const graphics_handle&, + const std::string&, + const octave_value&)), + this, + SIGNAL (gh_callback_event (const graphics_handle&, + const std::string&, + const octave_value&))); - connect (m_canvas, - SIGNAL (gh_callback_event (const graphics_handle&, - const std::string&, - const octave_value&)), - this, - SIGNAL (gh_callback_event (const graphics_handle&, - const std::string&, - const octave_value&))); + connect (m_canvas, + SIGNAL (gh_set_event (const graphics_handle&, + const std::string&, + const octave_value&)), + this, + SIGNAL (gh_set_event (const graphics_handle&, + const std::string&, + const octave_value&))); - connect (m_canvas, - SIGNAL (gh_set_event (const graphics_handle&, - const std::string&, - const octave_value&)), - this, - SIGNAL (gh_set_event (const graphics_handle&, - const std::string&, - const octave_value&))); - - connect (m_canvas, - SIGNAL (gh_set_event (const graphics_handle&, - const std::string&, - const octave_value&, bool)), - this, - SIGNAL (gh_set_event (const graphics_handle&, - const std::string&, - const octave_value&, bool))); + connect (m_canvas, + SIGNAL (gh_set_event (const graphics_handle&, + const std::string&, + const octave_value&, bool)), + this, + SIGNAL (gh_set_event (const graphics_handle&, + const std::string&, + const octave_value&, bool))); - connect (m_canvas, - SIGNAL (gh_set_event (const graphics_handle&, - const std::string&, - const octave_value&, bool, bool)), - this, - SIGNAL (gh_set_event (const graphics_handle&, - const std::string&, - const octave_value&, bool, bool))); + connect (m_canvas, + SIGNAL (gh_set_event (const graphics_handle&, + const std::string&, + const octave_value&, bool, bool)), + this, + SIGNAL (gh_set_event (const graphics_handle&, + const std::string&, + const octave_value&, bool, bool))); - QWidget *canvasWidget = m_canvas->qWidget (); + QWidget *canvasWidget = m_canvas->qWidget (); - canvasWidget->lower (); - canvasWidget->show (); - canvasWidget->setGeometry (0, 0, width (), height ()); - } - } + canvasWidget->lower (); + canvasWidget->show (); + canvasWidget->setGeometry (0, 0, width (), height ()); + } + } - return m_canvas; -} + return m_canvas; + } -void -Container::resizeEvent (QResizeEvent * /* event */) -{ - if (m_canvas) - m_canvas->qWidget ()->setGeometry (0, 0, width (), height ()); + void + Container::resizeEvent (QResizeEvent * /* event */) + { + if (m_canvas) + m_canvas->qWidget ()->setGeometry (0, 0, width (), height ()); - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - octave::autolock guard (gh_mgr.graphics_lock ()); + octave::autolock guard (gh_mgr.graphics_lock ()); - for (auto *qObj : children ()) - { - if (qObj->isWidgetType ()) - { - Object *obj = Object::fromQObject (qObj); + for (auto *qObj : children ()) + { + if (qObj->isWidgetType ()) + { + Object *obj = Object::fromQObject (qObj); - if (obj) - { - graphics_object go = obj->object (); + if (obj) + { + graphics_object go = obj->object (); - if (go.valid_object ()) - { - Matrix bb = go.get_properties ().get_boundingbox (false); + if (go.valid_object ()) + { + Matrix bb = go.get_properties ().get_boundingbox (false); - obj->qWidget ()->setGeometry - (octave::math::round (bb(0)), - octave::math::round (bb(1)), - octave::math::round (bb(2)), - octave::math::round (bb(3))); - } - } - } - } -} + obj->qWidget ()->setGeometry + (octave::math::round (bb(0)), + octave::math::round (bb(1)), + octave::math::round (bb(2)), + octave::math::round (bb(3))); + } + } + } + } + } -void -Container::childEvent (QChildEvent *xevent) -{ - // Enable mouse tracking in child widgets as they are added if the - // container also has mouse tracking enabled. There is no need to - // do this when child objects are removed. + void + Container::childEvent (QChildEvent *xevent) + { + // Enable mouse tracking in child widgets as they are added if the + // container also has mouse tracking enabled. There is no need to + // do this when child objects are removed. - if (xevent->added ()) - { - QObject *obj = xevent->child (); + if (xevent->added ()) + { + QObject *obj = xevent->child (); - if (obj && obj->isWidgetType ()) - { - QWidget *widget = qobject_cast (obj); + if (obj && obj->isWidgetType ()) + { + QWidget *widget = qobject_cast (obj); - if (widget) - widget->setMouseTracking (hasMouseTracking ()); - } - } -} + if (widget) + widget->setMouseTracking (hasMouseTracking ()); + } + } + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/Container.h --- a/libgui/graphics/Container.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/Container.h Tue Dec 06 15:45:27 2022 -0500 @@ -35,55 +35,48 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -} + DECLARE_GENERICEVENTNOTIFY_SENDER(ContainerBase, QWidget); + + class Canvas; -OCTAVE_BEGIN_NAMESPACE(octave) - -DECLARE_GENERICEVENTNOTIFY_SENDER(ContainerBase, QWidget); - -class Canvas; + class Container : public ContainerBase + { + Q_OBJECT -class Container : public ContainerBase -{ - Q_OBJECT + public: + Container (QWidget *parent, octave::interpreter& interp); + ~Container (void); + + Canvas * canvas (const graphics_handle& handle, bool create = true); -public: - Container (QWidget *parent, octave::base_qobject& oct_qobj, - octave::interpreter& interp); - ~Container (void); + signals: - Canvas * canvas (const graphics_handle& handle, bool create = true); + void interpreter_event (const octave::fcn_callback& fcn); + void interpreter_event (const octave::meth_callback& meth); -signals: - - void interpreter_event (const octave::fcn_callback& fcn); - void interpreter_event (const octave::meth_callback& meth); + void gh_callback_event (const graphics_handle& h, const std::string& name); - void gh_callback_event (const graphics_handle& h, const std::string& name); - - void gh_callback_event (const graphics_handle& h, const std::string& name, - const octave_value& data); + void gh_callback_event (const graphics_handle& h, const std::string& name, + const octave_value& data); - void gh_set_event (const graphics_handle& h, const std::string& name, - const octave_value& value); + void gh_set_event (const graphics_handle& h, const std::string& name, + const octave_value& value); - void gh_set_event (const graphics_handle& h, const std::string& name, - const octave_value& value, bool notify_toolkit); + void gh_set_event (const graphics_handle& h, const std::string& name, + const octave_value& value, bool notify_toolkit); - void gh_set_event (const graphics_handle& h, const std::string& name, - const octave_value& value, bool notify_toolkit, - bool redraw_figure); + void gh_set_event (const graphics_handle& h, const std::string& name, + const octave_value& value, bool notify_toolkit, + bool redraw_figure); -protected: - void childEvent (QChildEvent *event); - void resizeEvent (QResizeEvent *event); + protected: + void childEvent (QChildEvent *event); + void resizeEvent (QResizeEvent *event); -private: - octave::base_qobject& m_octave_qobj; - octave::interpreter& m_interpreter; - Canvas *m_canvas; -}; + private: + octave::interpreter& m_interpreter; + Canvas *m_canvas; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ContextMenu.cc --- a/libgui/graphics/ContextMenu.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ContextMenu.cc Tue Dec 06 15:45:27 2022 -0500 @@ -33,118 +33,114 @@ #include "QtHandlesUtils.h" #include "qt-graphics-toolkit.h" -#include "octave-qobject.h" - #include "interpreter.h" OCTAVE_BEGIN_NAMESPACE(octave) -ContextMenu * -ContextMenu::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go) -{ - Object *xparent = parentObject (interp, go); + ContextMenu * + ContextMenu::create (octave::interpreter& interp, const graphics_object& go) + { + Object *xparent = parentObject (interp, go); - if (xparent) - { - QWidget *w = xparent->qWidget (); + if (xparent) + { + QWidget *w = xparent->qWidget (); - return new ContextMenu (oct_qobj, interp, go, new QMenu (w)); - } + return new ContextMenu (interp, go, new QMenu (w)); + } - return nullptr; -} + return nullptr; + } -ContextMenu::ContextMenu (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, QMenu *xmenu) - : Object (oct_qobj, interp, go, xmenu) -{ - xmenu->setAutoFillBackground (true); + ContextMenu::ContextMenu (octave::interpreter& interp, + const graphics_object& go, QMenu *xmenu) + : Object (interp, go, xmenu) + { + xmenu->setAutoFillBackground (true); - connect (xmenu, &QMenu::aboutToShow, this, &ContextMenu::aboutToShow); - connect (xmenu, &QMenu::aboutToHide, this, &ContextMenu::aboutToHide); -} + connect (xmenu, &QMenu::aboutToShow, this, &ContextMenu::aboutToShow); + connect (xmenu, &QMenu::aboutToHide, this, &ContextMenu::aboutToHide); + } -ContextMenu::~ContextMenu (void) -{ } + ContextMenu::~ContextMenu (void) + { } -void -ContextMenu::update (int pId) -{ - uicontextmenu::properties& up = properties (); - QMenu *xmenu = qWidget (); + void + ContextMenu::update (int pId) + { + uicontextmenu::properties& up = properties (); + QMenu *xmenu = qWidget (); - switch (pId) - { - case base_properties::ID_VISIBLE: - if (up.is_visible ()) - { - Matrix pos = up.get_position ().matrix_value (); - QWidget *parentW = xmenu->parentWidget (); - QPoint pt; + switch (pId) + { + case base_properties::ID_VISIBLE: + if (up.is_visible ()) + { + Matrix pos = up.get_position ().matrix_value (); + QWidget *parentW = xmenu->parentWidget (); + QPoint pt; - pt.rx () = octave::math::round (pos(0)); - pt.ry () = parentW->height () - octave::math::round (pos(1)); - pt = parentW->mapToGlobal (pt); + pt.rx () = octave::math::round (pos(0)); + pt.ry () = parentW->height () - octave::math::round (pos(1)); + pt = parentW->mapToGlobal (pt); - xmenu->popup (pt); - } - else - xmenu->hide (); - break; - default: - Object::update (pId); - break; - } -} + xmenu->popup (pt); + } + else + xmenu->hide (); + break; + default: + Object::update (pId); + break; + } + } -void -ContextMenu::aboutToShow (void) -{ - emit gh_callback_event (m_handle, "callback"); - emit gh_set_event (m_handle, "visible", "on", false); -} + void + ContextMenu::aboutToShow (void) + { + emit gh_callback_event (m_handle, "callback"); + emit gh_set_event (m_handle, "visible", "on", false); + } -void -ContextMenu::aboutToHide (void) -{ - emit gh_set_event (m_handle, "visible", "off", false); -} + void + ContextMenu::aboutToHide (void) + { + emit gh_set_event (m_handle, "visible", "off", false); + } -QWidget * -ContextMenu::menu (void) -{ - return qWidget (); -} + QWidget * + ContextMenu::menu (void) + { + return qWidget (); + } -void -ContextMenu::executeAt (octave::interpreter& interp, - const base_properties& props, const QPoint& pt) -{ - graphics_handle h = props.get_uicontextmenu (); + void + ContextMenu::executeAt (octave::interpreter& interp, + const base_properties& props, const QPoint& pt) + { + graphics_handle h = props.get_uicontextmenu (); - if (h.ok ()) - { - gh_manager& gh_mgr = interp.get_gh_manager (); - octave::autolock guard (gh_mgr.graphics_lock ()); + if (h.ok ()) + { + gh_manager& gh_mgr = interp.get_gh_manager (); + octave::autolock guard (gh_mgr.graphics_lock ()); - graphics_object go = gh_mgr.get_object (h); + graphics_object go = gh_mgr.get_object (h); - if (go.valid_object ()) - { - ContextMenu *cMenu = - dynamic_cast (qt_graphics_toolkit::toolkitObject (go)); + if (go.valid_object ()) + { + ContextMenu *cMenu = + dynamic_cast (qt_graphics_toolkit::toolkitObject (go)); - if (cMenu) - { - QMenu *menu = cMenu->qWidget (); + if (cMenu) + { + QMenu *menu = cMenu->qWidget (); - if (menu) - menu->popup (pt); - } - } - } -} + if (menu) + menu->popup (pt); + } + } + } + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ContextMenu.h --- a/libgui/graphics/ContextMenu.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ContextMenu.h Tue Dec 06 15:45:27 2022 -0500 @@ -35,36 +35,35 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; + + class ContextMenu : public Object, public MenuContainer + { + Q_OBJECT -class ContextMenu : public Object, public MenuContainer -{ - Q_OBJECT + public: + ContextMenu (octave::interpreter& interp, + const graphics_object& go, QMenu *menu); + ~ContextMenu (void); -public: - ContextMenu (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QMenu *menu); - ~ContextMenu (void); + static ContextMenu * + create (octave::interpreter& interp, + const graphics_object& go); - static ContextMenu * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + static void executeAt (octave::interpreter& interp, + const base_properties& props, const QPoint& pt); - static void executeAt (octave::interpreter& interp, - const base_properties& props, const QPoint& pt); + Container * innerContainer (void) { return nullptr; } - Container * innerContainer (void) { return nullptr; } + QWidget * menu (void); - QWidget * menu (void); - -protected: - void update (int pId); + protected: + void update (int pId); -private slots: - void aboutToShow (void); - void aboutToHide (void); -}; + private slots: + void aboutToShow (void); + void aboutToHide (void); + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/EditControl.cc --- a/libgui/graphics/EditControl.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/EditControl.cc Tue Dec 06 15:45:27 2022 -0500 @@ -34,280 +34,275 @@ #include "TextEdit.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - OCTAVE_BEGIN_NAMESPACE(octave) -EditControl * -EditControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go) -{ - Object *parent = parentObject (interp, go); + EditControl * + EditControl::create (octave::interpreter& interp, const graphics_object& go) + { + Object *parent = parentObject (interp, go); - if (parent) - { - Container *container = parent->innerContainer (); + if (parent) + { + Container *container = parent->innerContainer (); - if (container) - { - uicontrol::properties& up = Utils::properties (go); + if (container) + { + uicontrol::properties& up = Utils::properties (go); - if ((up.get_max () - up.get_min ()) > 1) - return new EditControl (oct_qobj, interp, go, - new TextEdit (container)); - else - return new EditControl (oct_qobj, interp, go, - new QLineEdit (container)); - } - } + if ((up.get_max () - up.get_min ()) > 1) + return new EditControl (interp, go, + new TextEdit (container)); + else + return new EditControl (interp, go, + new QLineEdit (container)); + } + } - return nullptr; -} + return nullptr; + } -EditControl::EditControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, QLineEdit *edit) - : BaseControl (oct_qobj, interp, go, edit), m_multiLine (false), - m_textChanged (false) -{ - init (edit); -} + EditControl::EditControl (octave::interpreter& interp, + const graphics_object& go, QLineEdit *edit) + : BaseControl (interp, go, edit), m_multiLine (false), + m_textChanged (false) + { + init (edit); + } -void -EditControl::init (QLineEdit *edit, bool callBase) -{ - if (callBase) - BaseControl::init (edit, callBase); + void + EditControl::init (QLineEdit *edit, bool callBase) + { + if (callBase) + BaseControl::init (edit, callBase); - m_multiLine = false; - initCommon (edit); + m_multiLine = false; + initCommon (edit); - uicontrol::properties& up = properties (); + uicontrol::properties& up = properties (); - if (up.enable_is ("inactive")) - edit->setReadOnly (true); - else - edit->setEnabled (up.enable_is ("on")); - edit->setText (Utils::fromStdString (up.get_string_string ())); - edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), - up.get_verticalalignment ())); + if (up.enable_is ("inactive")) + edit->setReadOnly (true); + else + edit->setEnabled (up.enable_is ("on")); + edit->setText (Utils::fromStdString (up.get_string_string ())); + edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), + up.get_verticalalignment ())); - connect (edit, &QLineEdit::textEdited, - this, &EditControl::textChanged); - connect (edit, &QLineEdit::editingFinished, - this, &EditControl::editingFinished); - connect (edit, &QLineEdit::returnPressed, - this, &EditControl::returnPressed); -} + connect (edit, &QLineEdit::textEdited, + this, &EditControl::textChanged); + connect (edit, &QLineEdit::editingFinished, + this, &EditControl::editingFinished); + connect (edit, &QLineEdit::returnPressed, + this, &EditControl::returnPressed); + } -EditControl::EditControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, TextEdit *edit) - : BaseControl (oct_qobj, interp, go, edit), m_multiLine (true), - m_textChanged (false) -{ - init (edit); -} + EditControl::EditControl (octave::interpreter& interp, + const graphics_object& go, TextEdit *edit) + : BaseControl (interp, go, edit), m_multiLine (true), + m_textChanged (false) + { + init (edit); + } -void -EditControl::init (TextEdit *edit, bool callBase) -{ - if (callBase) - BaseControl::init (edit, callBase); + void + EditControl::init (TextEdit *edit, bool callBase) + { + if (callBase) + BaseControl::init (edit, callBase); - m_multiLine = true; - initCommon (edit); + m_multiLine = true; + initCommon (edit); - uicontrol::properties& up = properties (); + uicontrol::properties& up = properties (); - if (up.enable_is ("inactive")) - edit->setReadOnly (true); - else - edit->setEnabled (up.enable_is ("on")); - edit->setAcceptRichText (false); - edit->setPlainText (Utils::fromStringVector - (up.get_string_vector ()).join ("\n")); - edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), - up.get_verticalalignment ())); + if (up.enable_is ("inactive")) + edit->setReadOnly (true); + else + edit->setEnabled (up.enable_is ("on")); + edit->setAcceptRichText (false); + edit->setPlainText (Utils::fromStringVector + (up.get_string_vector ()).join ("\n")); + edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), + up.get_verticalalignment ())); - connect (edit, &TextEdit::textChanged, - this, &EditControl::textChanged); - connect (edit, &TextEdit::editingFinished, - this, &EditControl::editingFinished); - connect (edit, &TextEdit::returnPressed, - this, &EditControl::returnPressed); -} + connect (edit, &TextEdit::textChanged, + this, &EditControl::textChanged); + connect (edit, &TextEdit::editingFinished, + this, &EditControl::editingFinished); + connect (edit, &TextEdit::returnPressed, + this, &EditControl::returnPressed); + } -EditControl::~EditControl (void) -{ } + EditControl::~EditControl (void) + { } -void -EditControl::initCommon (QWidget *) -{ - m_textChanged = false; -} + void + EditControl::initCommon (QWidget *) + { + m_textChanged = false; + } -void -EditControl::update (int pId) -{ - bool handled = false; + void + EditControl::update (int pId) + { + bool handled = false; - if (m_multiLine) - handled = updateMultiLine (pId); - else - handled = updateSingleLine (pId); + if (m_multiLine) + handled = updateMultiLine (pId); + else + handled = updateSingleLine (pId); - if (! handled) - { - switch (pId) - { - default: - BaseControl::update (pId); - break; - } - } -} + if (! handled) + { + switch (pId) + { + default: + BaseControl::update (pId); + break; + } + } + } -bool -EditControl::updateSingleLine (int pId) -{ - uicontrol::properties& up = properties (); - QLineEdit *edit = qWidget (); + bool + EditControl::updateSingleLine (int pId) + { + uicontrol::properties& up = properties (); + QLineEdit *edit = qWidget (); - switch (pId) - { - case uicontrol::properties::ID_STRING: - edit->setText (Utils::fromStdString (up.get_string_string ())); - return true; + switch (pId) + { + case uicontrol::properties::ID_STRING: + edit->setText (Utils::fromStdString (up.get_string_string ())); + return true; - case uicontrol::properties::ID_HORIZONTALALIGNMENT: - case uicontrol::properties::ID_VERTICALALIGNMENT: - edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), - up.get_verticalalignment ())); - return true; + case uicontrol::properties::ID_HORIZONTALALIGNMENT: + case uicontrol::properties::ID_VERTICALALIGNMENT: + edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), + up.get_verticalalignment ())); + return true; - case uicontrol::properties::ID_ENABLE: - if (up.enable_is ("inactive")) - edit->setReadOnly (true); - else - { - edit->setReadOnly (false); - edit->setEnabled (up.enable_is ("on")); - } - return true; + case uicontrol::properties::ID_ENABLE: + if (up.enable_is ("inactive")) + edit->setReadOnly (true); + else + { + edit->setReadOnly (false); + edit->setEnabled (up.enable_is ("on")); + } + return true; - case uicontrol::properties::ID_MIN: - case uicontrol::properties::ID_MAX: - if ((up.get_max () - up.get_min ()) > 1) - { - QWidget *container = edit->parentWidget (); + case uicontrol::properties::ID_MIN: + case uicontrol::properties::ID_MAX: + if ((up.get_max () - up.get_min ()) > 1) + { + QWidget *container = edit->parentWidget (); - delete edit; - init (new TextEdit (container), true); - } - return true; + delete edit; + init (new TextEdit (container), true); + } + return true; - default: - break; - } + default: + break; + } - return false; -} + return false; + } -bool -EditControl::updateMultiLine (int pId) -{ - uicontrol::properties& up = properties (); - TextEdit *edit = qWidget (); + bool + EditControl::updateMultiLine (int pId) + { + uicontrol::properties& up = properties (); + TextEdit *edit = qWidget (); - switch (pId) - { - case uicontrol::properties::ID_STRING: - edit->setPlainText (Utils::fromStringVector - (up.get_string_vector ()).join ("\n")); - return true; + switch (pId) + { + case uicontrol::properties::ID_STRING: + edit->setPlainText (Utils::fromStringVector + (up.get_string_vector ()).join ("\n")); + return true; - case uicontrol::properties::ID_HORIZONTALALIGNMENT: - case uicontrol::properties::ID_VERTICALALIGNMENT: - edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), - up.get_verticalalignment ())); - return true; + case uicontrol::properties::ID_HORIZONTALALIGNMENT: + case uicontrol::properties::ID_VERTICALALIGNMENT: + edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), + up.get_verticalalignment ())); + return true; - case uicontrol::properties::ID_ENABLE: - if (up.enable_is ("inactive")) - edit->setReadOnly (true); - else - { - edit->setReadOnly (false); - edit->setEnabled (up.enable_is ("on")); - } - return true; + case uicontrol::properties::ID_ENABLE: + if (up.enable_is ("inactive")) + edit->setReadOnly (true); + else + { + edit->setReadOnly (false); + edit->setEnabled (up.enable_is ("on")); + } + return true; - case uicontrol::properties::ID_MIN: - case uicontrol::properties::ID_MAX: - if ((up.get_max () - up.get_min ()) <= 1) - { - QWidget *container = edit->parentWidget (); + case uicontrol::properties::ID_MIN: + case uicontrol::properties::ID_MAX: + if ((up.get_max () - up.get_min ()) <= 1) + { + QWidget *container = edit->parentWidget (); - delete edit; - init (new QLineEdit (container), true); - } - return true; + delete edit; + init (new QLineEdit (container), true); + } + return true; - default: - break; - } + default: + break; + } - return false; -} + return false; + } -void -EditControl::textChanged (void) -{ - m_textChanged = true; -} + void + EditControl::textChanged (void) + { + m_textChanged = true; + } -void -EditControl::returnPressed (void) -{ - QString txt = (m_multiLine - ? qWidget ()->toPlainText () - : qWidget ()->text ()); + void + EditControl::returnPressed (void) + { + QString txt = (m_multiLine + ? qWidget ()->toPlainText () + : qWidget ()->text ()); - if (m_textChanged) - { - if (m_multiLine) - emit gh_set_event (m_handle, "string", - Utils::toCellString (txt.split ("\n")), false); - else - emit gh_set_event (m_handle, "string", - Utils::toStdString (txt), false); + if (m_textChanged) + { + if (m_multiLine) + emit gh_set_event (m_handle, "string", + Utils::toCellString (txt.split ("\n")), false); + else + emit gh_set_event (m_handle, "string", + Utils::toStdString (txt), false); - m_textChanged = false; - } + m_textChanged = false; + } - if (txt.length () > 0) - emit gh_callback_event (m_handle, "callback"); -} + if (txt.length () > 0) + emit gh_callback_event (m_handle, "callback"); + } -void -EditControl::editingFinished (void) -{ - if (m_textChanged) - { - QString txt = (m_multiLine - ? qWidget ()->toPlainText () - : qWidget ()->text ()); - if (m_multiLine) - emit gh_set_event (m_handle, "string", - Utils::toCellString (txt.split ("\n")), false); - else - emit gh_set_event (m_handle, "string", Utils::toStdString (txt), - false); - emit gh_callback_event (m_handle, "callback"); + void + EditControl::editingFinished (void) + { + if (m_textChanged) + { + QString txt = (m_multiLine + ? qWidget ()->toPlainText () + : qWidget ()->text ()); + if (m_multiLine) + emit gh_set_event (m_handle, "string", + Utils::toCellString (txt.split ("\n")), false); + else + emit gh_set_event (m_handle, "string", Utils::toStdString (txt), + false); + emit gh_callback_event (m_handle, "callback"); - m_textChanged = false; - } -} + m_textChanged = false; + } + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/EditControl.h --- a/libgui/graphics/EditControl.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/EditControl.h Tue Dec 06 15:45:27 2022 -0500 @@ -33,47 +33,46 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; + + class TextEdit; -class TextEdit; - -class EditControl : public BaseControl -{ - Q_OBJECT + class EditControl : public BaseControl + { + Q_OBJECT -public: - EditControl (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QLineEdit *edit); + public: + EditControl (octave::interpreter& interp, + const graphics_object& go, QLineEdit *edit); - EditControl (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, TextEdit *edit); + EditControl (octave::interpreter& interp, + const graphics_object& go, TextEdit *edit); - ~EditControl (void); + ~EditControl (void); - static EditControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + static EditControl * + create (octave::interpreter& interp, + const graphics_object& go); -protected: - void update (int pId); + protected: + void update (int pId); -private: - void init (QLineEdit *edit, bool callBase = false); - void init (TextEdit *edit, bool callBase = false); - void initCommon (QWidget *widget); - bool updateSingleLine (int pId); - bool updateMultiLine (int pId); + private: + void init (QLineEdit *edit, bool callBase = false); + void init (TextEdit *edit, bool callBase = false); + void initCommon (QWidget *widget); + bool updateSingleLine (int pId); + bool updateMultiLine (int pId); -private slots: - void textChanged (void); - void editingFinished (void); - void returnPressed (void); + private slots: + void textChanged (void); + void editingFinished (void); + void returnPressed (void); -private: - bool m_multiLine; - bool m_textChanged; -}; + private: + bool m_multiLine; + bool m_textChanged; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/Figure.cc --- a/libgui/graphics/Figure.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/Figure.cc Tue Dec 06 15:45:27 2022 -0500 @@ -67,840 +67,840 @@ OCTAVE_BEGIN_NAMESPACE(octave) -DECLARE_GENERICEVENTNOTIFY_SENDER(MenuBar, QMenuBar); + DECLARE_GENERICEVENTNOTIFY_SENDER(MenuBar, QMenuBar); + + static QRect + boundingBoxToRect (const Matrix& bb) + { + QRect r; + + if (bb.numel () == 4) + { + r = QRect (octave::math::round (bb(0)), octave::math::round (bb(1)), + octave::math::round (bb(2)), octave::math::round (bb(3))); + if (! r.isValid ()) + r = QRect (); + } + + return r; + } -static QRect -boundingBoxToRect (const Matrix& bb) -{ - QRect r; + static QImage + pointer_to_qimage (const Matrix& cdata) + { + QImage retval (cdata.rows (), cdata.columns (), QImage::Format_ARGB32); + QColor tmp ("White"); + QColor black ("Black"); + QColor white ("White"); + for (octave_idx_type ii = 0; ii < cdata.rows (); ii++) + for (octave_idx_type jj = 0; jj < cdata.columns (); jj++) + { + if (cdata(ii, jj) == 1.0) + tmp = black; + else if (cdata(ii, jj) == 2.0) + tmp = white; + else + tmp.setAlpha (0); + + retval.setPixel (jj, ii, tmp.rgba ()); + } + + return retval; + } + + Figure * + Figure::create (octave::interpreter& interp, + const graphics_object& go) + { + return new Figure (interp, go, new FigureWindow ()); + } + + Figure::Figure (octave::interpreter& interp, + const graphics_object& go, FigureWindow *win) + : Object (interp, go, win), m_blockUpdates (false), + m_figureToolBar (nullptr), m_menuBar (nullptr), m_innerRect (), + m_outerRect (), m_previousHeight (0), m_resizable (true) + { + m_container = new Container (win, interp); + win->setCentralWidget (m_container); + + connect (m_container, QOverload::of (&Container::interpreter_event), + this, QOverload::of (&Figure::interpreter_event)); + + connect (m_container, QOverload::of (&Container::interpreter_event), + this, QOverload::of (&Figure::interpreter_event)); + + figure::properties& fp = properties
(); - if (bb.numel () == 4) - { - r = QRect (octave::math::round (bb(0)), octave::math::round (bb(1)), - octave::math::round (bb(2)), octave::math::round (bb(3))); - if (! r.isValid ()) - r = QRect (); - } + // Adjust figure position + m_innerRect = boundingBoxToRect (fp.get_boundingbox (true)); + m_outerRect = boundingBoxToRect (fp.get_boundingbox (false)); + + set_geometry (m_innerRect); + + // Menubar + m_menuBar = new MenuBar (win); + win->setMenuBar (m_menuBar); + m_menuBar->addReceiver (this); + m_menuBar->setStyleSheet (m_menuBar->styleSheet () + global_menubar_style); + + // Status bar + m_statusBar = win->statusBar (); + m_statusBar->setVisible (false); + + if (fp.toolbar_is ("figure") + || (fp.toolbar_is ("auto") && fp.menubar_is ("figure"))) + showFigureStatusBar (true); + + // Enable mouse tracking unconditionally + enableMouseTracking (); + + // When this constructor gets called all properties are already + // set, even non default. We force "update" here to get things right. + + // Figure title + update (figure::properties::ID_NUMBERTITLE); + + // Decide what keyboard events we listen to + m_container->canvas (m_handle)->setEventMask (0); + update (figure::properties::ID_KEYPRESSFCN); + update (figure::properties::ID_KEYRELEASEFCN); - return r; -} + // modal style + update (figure::properties::ID_WINDOWSTYLE); + + // Handle resizing constraints + update (figure::properties::ID_RESIZE); + + // Custom pointer data + update (figure::properties::ID_POINTERSHAPECDATA); + + // Visibility + update (figure::properties::ID_VISIBLE); + + connect (this, &Figure::asyncUpdate, this, &Figure::updateContainer); + + // Register for the signal that indicates when a window has moved + // to a different screen + connect (win, &FigureWindow::figureWindowShown, + this, &Figure::figureWindowShown); + + win->addReceiver (this); + m_container->addReceiver (this); + } + + Figure::~Figure (void) + { } + + QString + Figure::fileName (void) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + octave::autolock guard (gh_mgr.graphics_lock ()); + + const figure::properties& fp = properties
(); -static QImage -pointer_to_qimage (const Matrix& cdata) -{ - QImage retval (cdata.rows (), cdata.columns (), QImage::Format_ARGB32); - QColor tmp ("White"); - QColor black ("Black"); - QColor white ("White"); - for (octave_idx_type ii = 0; ii < cdata.rows (); ii++) - for (octave_idx_type jj = 0; jj < cdata.columns (); jj++) + std::string name = fp.get_filename (); + + return QString::fromStdString (name); + } + + void + Figure::setFileName (const QString& name) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + octave::autolock guard (gh_mgr.graphics_lock ()); + + figure::properties& fp = properties
(); + + fp.set_filename (name.toStdString ()); + } + + MouseMode + Figure::mouseMode (void) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + octave::autolock guard (gh_mgr.graphics_lock ()); + + const figure::properties& fp = properties
(); + + std::string mode = fp.get___mouse_mode__ (); + + if (mode == "zoom") + { + octave_scalar_map zm = fp.get___zoom_mode__ ().scalar_map_value (); + + std::string direction = zm.getfield ("Direction").string_value (); + + mode += ' ' + direction; + } + + if (mode == "rotate") + return RotateMode; + else if (mode == "zoom in") + return ZoomInMode; + else if (mode == "zoom out") + return ZoomOutMode; + else if (mode == "pan") + return PanMode; + else if (mode == "text") + return TextMode; + + return NoMode; + } + + void + Figure::set_geometry (QRect r) + { + QMainWindow *win = qWidget (); + + if (! m_resizable) { - if (cdata(ii, jj) == 1.0) - tmp = black; - else if (cdata(ii, jj) == 2.0) - tmp = white; - else - tmp.setAlpha (0); + win->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Preferred); + win->setFixedSize (QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); + } + + // Unlock window if it is maximized or full-screen + int state = win->windowState (); + if (state == Qt::WindowFullScreen || state == Qt::WindowMaximized) + win->setWindowState (Qt::WindowNoState); + + win->setGeometry (r); + + if (! m_resizable) + { + win->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); + win->setFixedSize(win->size ()); + } + } + + Container * + Figure::innerContainer (void) + { + return m_container; + } + + void + Figure::redraw (void) + { + Canvas *canvas = m_container->canvas (m_handle); + + if (canvas) + canvas->redraw (); - retval.setPixel (jj, ii, tmp.rgba ()); + for (auto *qobj : qWidget ()->findChildren ()) + { + if (qobj->objectName () == "UIPanel" + || qobj->objectName () == "UIButtonGroup" + || qobj->objectName () == "UIControl" + || qobj->objectName () == "UITable") + { + Object *obj = Object::fromQObject (qobj); + + if (obj) + obj->slotRedraw (); + } + } + } + + void + Figure::show (void) + { + QWidget *win = qWidget (); + + win->activateWindow (); + win->raise (); + } + + void + Figure::print (const QString& file_cmd, const QString& term) + { + Canvas *canvas = m_container->canvas (m_handle); + + if (canvas) + canvas->print (file_cmd, term); + } + + uint8NDArray + Figure::slotGetPixels (void) + { + uint8NDArray retval; + Canvas *canvas = m_container->canvas (m_handle); + + if (canvas) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + gh_mgr.process_events (); + octave::autolock guard (gh_mgr.graphics_lock ()); + retval = canvas->getPixels (); } - return retval; -} - -Figure * -Figure::create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go) -{ - return new Figure (oct_qobj, interp, go, new FigureWindow ()); -} - -Figure::Figure (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, FigureWindow *win) - : Object (oct_qobj, interp, go, win), m_blockUpdates (false), - m_figureToolBar (nullptr), m_menuBar (nullptr), m_innerRect (), - m_outerRect (), m_previousHeight (0), m_resizable (true) -{ - m_container = new Container (win, oct_qobj, interp); - win->setCentralWidget (m_container); - - connect (m_container, QOverload::of (&Container::interpreter_event), - this, QOverload::of (&Figure::interpreter_event)); + return retval; + } - connect (m_container, QOverload::of (&Container::interpreter_event), - this, QOverload::of (&Figure::interpreter_event)); - - figure::properties& fp = properties
(); - - // Adjust figure position - m_innerRect = boundingBoxToRect (fp.get_boundingbox (true)); - m_outerRect = boundingBoxToRect (fp.get_boundingbox (false)); - - set_geometry (m_innerRect); + void + Figure::beingDeleted (void) + { + Canvas *canvas = m_container->canvas (m_handle.value (), false); - // Menubar - m_menuBar = new MenuBar (win); - win->setMenuBar (m_menuBar); - m_menuBar->addReceiver (this); - m_menuBar->setStyleSheet (m_menuBar->styleSheet () + global_menubar_style); - - // Status bar - m_statusBar = win->statusBar (); - m_statusBar->setVisible (false); - - if (fp.toolbar_is ("figure") - || (fp.toolbar_is ("auto") && fp.menubar_is ("figure"))) - showFigureStatusBar (true); + if (canvas) + canvas->blockRedraw (true); - // Enable mouse tracking unconditionally - enableMouseTracking (); - - // When this constructor gets called all properties are already - // set, even non default. We force "update" here to get things right. - - // Figure title - update (figure::properties::ID_NUMBERTITLE); - - // Decide what keyboard events we listen to - m_container->canvas (m_handle)->setEventMask (0); - update (figure::properties::ID_KEYPRESSFCN); - update (figure::properties::ID_KEYRELEASEFCN); - - // modal style - update (figure::properties::ID_WINDOWSTYLE); - - // Handle resizing constraints - update (figure::properties::ID_RESIZE); - - // Custom pointer data - update (figure::properties::ID_POINTERSHAPECDATA); + m_container->removeReceiver (this); + qWidget ()->removeReceiver (this); + } - // Visibility - update (figure::properties::ID_VISIBLE); - - connect (this, &Figure::asyncUpdate, this, &Figure::updateContainer); - - // Register for the signal that indicates when a window has moved - // to a different screen - connect (win, &FigureWindow::figureWindowShown, - this, &Figure::figureWindowShown); - - win->addReceiver (this); - m_container->addReceiver (this); -} + void + Figure::update (int pId) + { + if (m_blockUpdates) + return; -Figure::~Figure (void) -{ } + figure::properties& fp = properties
(); -QString -Figure::fileName (void) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - octave::autolock guard (gh_mgr.graphics_lock ()); - - const figure::properties& fp = properties
(); - - std::string name = fp.get_filename (); + if (fp.is___printing__ ()) + return; - return QString::fromStdString (name); -} - -void -Figure::setFileName (const QString& name) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - octave::autolock guard (gh_mgr.graphics_lock ()); - - figure::properties& fp = properties
(); - - fp.set_filename (name.toStdString ()); -} - -MouseMode -Figure::mouseMode (void) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - octave::autolock guard (gh_mgr.graphics_lock ()); - - const figure::properties& fp = properties
(); + QMainWindow *win = qWidget (); - std::string mode = fp.get___mouse_mode__ (); - - if (mode == "zoom") - { - octave_scalar_map zm = fp.get___zoom_mode__ ().scalar_map_value (); - - std::string direction = zm.getfield ("Direction").string_value (); - - mode += ' ' + direction; - } + // If the window doesn't exist, there's nothing we can do. + if (! win) + return; - if (mode == "rotate") - return RotateMode; - else if (mode == "zoom in") - return ZoomInMode; - else if (mode == "zoom out") - return ZoomOutMode; - else if (mode == "pan") - return PanMode; - else if (mode == "text") - return TextMode; - - return NoMode; -} + m_blockUpdates = true; -void -Figure::set_geometry (QRect r) -{ - QMainWindow *win = qWidget (); - - if (! m_resizable) - { - win->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Preferred); - win->setFixedSize (QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); - } - - // Unlock window if it is maximized or full-screen - int state = win->windowState (); - if (state == Qt::WindowFullScreen || state == Qt::WindowMaximized) - win->setWindowState (Qt::WindowNoState); - - win->setGeometry (r); - - if (! m_resizable) - { - win->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); - win->setFixedSize(win->size ()); - } -} + switch (pId) + { + case figure::properties::ID_POSITION: + { + m_innerRect = boundingBoxToRect (fp.get_boundingbox (true)); + int toffset = 0; + int boffset = 0; -Container * -Figure::innerContainer (void) -{ - return m_container; -} - -void -Figure::redraw (void) -{ - Canvas *canvas = m_container->canvas (m_handle); + for (auto *tb : win->findChildren ()) + if (! tb->isHidden ()) + toffset += tb->sizeHint ().height (); - if (canvas) - canvas->redraw (); + if (! m_menuBar->isHidden ()) + toffset += m_menuBar->sizeHint ().height (); - for (auto *qobj : qWidget ()->findChildren ()) - { - if (qobj->objectName () == "UIPanel" - || qobj->objectName () == "UIButtonGroup" - || qobj->objectName () == "UIControl" - || qobj->objectName () == "UITable") - { - Object *obj = Object::fromQObject (qobj); + if (! m_statusBar->isHidden ()) + boffset += m_statusBar->sizeHint ().height (); - if (obj) - obj->slotRedraw (); + set_geometry (m_innerRect.adjusted (0, -toffset, 0, boffset)); } - } -} + break; -void -Figure::show (void) -{ - QWidget *win = qWidget (); + case figure::properties::ID_NAME: + case figure::properties::ID_NUMBERTITLE: + win->setWindowTitle (Utils::fromStdString (fp.get_title ())); + break; - win->activateWindow (); - win->raise (); -} + case figure::properties::ID_VISIBLE: + if (fp.is_visible ()) + { + QTimer::singleShot (0, win, &QMainWindow::show); + if (! fp.is___gl_window__ ()) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); -void -Figure::print (const QString& file_cmd, const QString& term) -{ - Canvas *canvas = m_container->canvas (m_handle); - - if (canvas) - canvas->print (file_cmd, term); -} + octave::autolock guard (gh_mgr.graphics_lock ()); + fp.set ("__gl_window__", "on"); + } + } + else + win->hide (); + break; -uint8NDArray -Figure::slotGetPixels (void) -{ - uint8NDArray retval; - Canvas *canvas = m_container->canvas (m_handle); - - if (canvas) - { - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + case figure::properties::ID_RESIZE: + if (fp.is_resize ()) + { + win->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Preferred); + win->setFixedSize (QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); + m_resizable = true; + } + else + { + win->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); + win->setFixedSize(win->size ()); + m_resizable = false; + } + break; - gh_mgr.process_events (); - octave::autolock guard (gh_mgr.graphics_lock ()); - retval = canvas->getPixels (); - } - - return retval; -} - -void -Figure::beingDeleted (void) -{ - Canvas *canvas = m_container->canvas (m_handle.value (), false); - - if (canvas) - canvas->blockRedraw (true); + case figure::properties::ID_MENUBAR: + case figure::properties::ID_TOOLBAR: + if (fp.toolbar_is ("none")) + showFigureStatusBar (false); + else if (fp.toolbar_is ("figure")) + showFigureStatusBar (true); + else // "auto" + showFigureStatusBar (fp.menubar_is ("figure")); + break; - m_container->removeReceiver (this); - qWidget ()->removeReceiver (this); -} - -void -Figure::update (int pId) -{ - if (m_blockUpdates) - return; + case figure::properties::ID_KEYPRESSFCN: + if (fp.get_keypressfcn ().isempty ()) + m_container->canvas (m_handle)->clearEventMask (Canvas::KeyPress); + else + m_container->canvas (m_handle)->addEventMask (Canvas::KeyPress); + // Signal the change to uipanels as well + for (auto *qobj : qWidget ()->findChildren ()) + { + if (qobj->objectName () == "UIPanel") + { + Object *obj = Object::fromQObject (qobj); - figure::properties& fp = properties
(); - - if (fp.is___printing__ ()) - return; - - QMainWindow *win = qWidget (); - - // If the window doesn't exist, there's nothing we can do. - if (! win) - return; - - m_blockUpdates = true; + if (obj) + { + if (fp.get_keypressfcn ().isempty ()) + obj->innerContainer ()->canvas (m_handle)-> + clearEventMask (Canvas::KeyPress); + else + obj->innerContainer ()->canvas (m_handle)-> + addEventMask (Canvas::KeyPress); + } + } + } + break; - switch (pId) - { - case figure::properties::ID_POSITION: - { - m_innerRect = boundingBoxToRect (fp.get_boundingbox (true)); - int toffset = 0; - int boffset = 0; - - for (auto *tb : win->findChildren ()) - if (! tb->isHidden ()) - toffset += tb->sizeHint ().height (); + case figure::properties::ID_KEYRELEASEFCN: + if (fp.get_keyreleasefcn ().isempty ()) + m_container->canvas (m_handle)->clearEventMask (Canvas::KeyRelease); + else + m_container->canvas (m_handle)->addEventMask (Canvas::KeyRelease); + break; + // Signal the change to uipanels as well + for (auto *qobj : qWidget ()->findChildren ()) + { + if (qobj->objectName () == "UIPanel") + { + Object *obj = Object::fromQObject (qobj); - if (! m_menuBar->isHidden ()) - toffset += m_menuBar->sizeHint ().height (); - - if (! m_statusBar->isHidden ()) - boffset += m_statusBar->sizeHint ().height (); + if (obj) + { + if (fp.get_keypressfcn ().isempty ()) + obj->innerContainer ()->canvas (m_handle)-> + clearEventMask (Canvas::KeyRelease); + else + obj->innerContainer ()->canvas (m_handle)-> + addEventMask (Canvas::KeyRelease); + } + } + } + break; - set_geometry (m_innerRect.adjusted (0, -toffset, 0, boffset)); - } - break; + case figure::properties::ID_WINDOWSTYLE: + if (fp.windowstyle_is ("modal")) + { + bool is_visible = win->isVisible (); - case figure::properties::ID_NAME: - case figure::properties::ID_NUMBERTITLE: - win->setWindowTitle (Utils::fromStdString (fp.get_title ())); - break; + // if window is already visible, need to hide and reshow it in order to + // make it use the modal settings + if (is_visible) + win->setVisible (false); - case figure::properties::ID_VISIBLE: - if (fp.is_visible ()) - { - QTimer::singleShot (0, win, &QMainWindow::show); - if (! fp.is___gl_window__ ()) - { - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + win->setWindowModality (Qt::ApplicationModal); + win->setVisible (is_visible); + } + else + win->setWindowModality (Qt::NonModal); + + break; - octave::autolock guard (gh_mgr.graphics_lock ()); - fp.set ("__gl_window__", "on"); - } - } - else - win->hide (); - break; + case figure::properties::ID_POINTERSHAPECDATA: + m_pointer_cdata = + pointer_to_qimage (fp.get_pointershapecdata ().matrix_value ()); + if (fp.get_pointer () != "custom") + break; + OCTAVE_FALLTHROUGH; + + case figure::properties::ID_POINTER: + case figure::properties::ID_POINTERSHAPEHOTSPOT: + case figure::properties::ID___MOUSE_MODE__: + case figure::properties::ID___ZOOM_MODE__: + m_container->canvas (m_handle)->setCursor (mouseMode (), + fp.get_pointer (), + m_pointer_cdata, + fp.get_pointershapehotspot () + .matrix_value()); + break; - case figure::properties::ID_RESIZE: - if (fp.is_resize ()) - { - win->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Preferred); - win->setFixedSize (QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); - m_resizable = true; - } - else - { - win->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); - win->setFixedSize(win->size ()); - m_resizable = false; - } - break; + default: + break; + } + + m_blockUpdates = false; + } - case figure::properties::ID_MENUBAR: - case figure::properties::ID_TOOLBAR: - if (fp.toolbar_is ("none")) - showFigureStatusBar (false); - else if (fp.toolbar_is ("figure")) - showFigureStatusBar (true); - else // "auto" - showFigureStatusBar (fp.menubar_is ("figure")); - break; + void + Figure::showFigureStatusBar (bool visible) + { + if (m_statusBar + && (! m_statusBar->isHidden ()) != visible) + { + int dy = m_statusBar->sizeHint ().height (); + QRect r = qWidget ()->geometry (); + + if (! visible) + r.adjust (0, 0, 0, -dy); + else + r.adjust (0, 0, 0, dy); + + m_blockUpdates = true; + set_geometry (r); + m_statusBar->setVisible (visible); + m_blockUpdates = false; + + updateBoundingBox (false); + } + } - case figure::properties::ID_KEYPRESSFCN: - if (fp.get_keypressfcn ().isempty ()) - m_container->canvas (m_handle)->clearEventMask (Canvas::KeyPress); - else - m_container->canvas (m_handle)->addEventMask (Canvas::KeyPress); - // Signal the change to uipanels as well - for (auto *qobj : qWidget ()->findChildren ()) - { - if (qobj->objectName () == "UIPanel") - { - Object *obj = Object::fromQObject (qobj); + void + Figure::updateFigureHeight (int dh) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + octave::autolock guard (gh_mgr.graphics_lock ()); + graphics_object go = object (); - if (obj) - { - if (fp.get_keypressfcn ().isempty ()) - obj->innerContainer ()->canvas (m_handle)-> - clearEventMask (Canvas::KeyPress); - else - obj->innerContainer ()->canvas (m_handle)-> - addEventMask (Canvas::KeyPress); - } - } - } - break; + if (go.valid_object () && dh != 0) + { + QRect r = qWidget ()->geometry (); + + r.adjust (0, dh, 0, 0); + + m_blockUpdates = true; + set_geometry (r); + m_blockUpdates = false; + + updateBoundingBox (false); + } + } - case figure::properties::ID_KEYRELEASEFCN: - if (fp.get_keyreleasefcn ().isempty ()) - m_container->canvas (m_handle)->clearEventMask (Canvas::KeyRelease); - else - m_container->canvas (m_handle)->addEventMask (Canvas::KeyRelease); - break; - // Signal the change to uipanels as well - for (auto *qobj : qWidget ()->findChildren ()) - { - if (qobj->objectName () == "UIPanel") - { - Object *obj = Object::fromQObject (qobj); + void + Figure::updateStatusBar (ColumnVector pt) + { + if (! m_statusBar->isHidden ()) + m_statusBar->showMessage (QString ("(%1, %2)") + .arg (pt(0), 0, 'g', 5) + .arg (pt(1), 0, 'g', 5)); + } + + void + Figure::do_connections (const QObject *receiver, const QObject * /* emitter */) + { + Object::do_connections (receiver); + Object::do_connections (receiver, m_container->canvas (m_handle)); + } - if (obj) - { - if (fp.get_keypressfcn ().isempty ()) - obj->innerContainer ()->canvas (m_handle)-> - clearEventMask (Canvas::KeyRelease); - else - obj->innerContainer ()->canvas (m_handle)-> - addEventMask (Canvas::KeyRelease); - } - } - } - break; + QWidget * + Figure::menu (void) + { + return qWidget ()->menuBar (); + } - case figure::properties::ID_WINDOWSTYLE: - if (fp.windowstyle_is ("modal")) - { - bool is_visible = win->isVisible (); + void + Figure::updateBoundingBox (bool internal, int flags) + { + QWidget *win = qWidget (); + Matrix bb (1, 4); + std::string prop; - // if window is already visible, need to hide and reshow it in order to - // make it use the modal settings - if (is_visible) - win->setVisible (false); + if (internal) + { + prop = "position"; + QRect r = m_innerRect; + + if (flags & UpdateBoundingBoxPosition) + r.moveTopLeft (win->mapToGlobal (m_container->pos ())); + if (flags & UpdateBoundingBoxSize) + r.setSize (m_container->size ()); - win->setWindowModality (Qt::ApplicationModal); - win->setVisible (is_visible); - } - else - win->setWindowModality (Qt::NonModal); - - break; - - case figure::properties::ID_POINTERSHAPECDATA: - m_pointer_cdata = - pointer_to_qimage (fp.get_pointershapecdata ().matrix_value ()); - if (fp.get_pointer () != "custom") - break; - OCTAVE_FALLTHROUGH; + if (r.isValid () && r != m_innerRect) + { + m_innerRect = r; - case figure::properties::ID_POINTER: - case figure::properties::ID_POINTERSHAPEHOTSPOT: - case figure::properties::ID___MOUSE_MODE__: - case figure::properties::ID___ZOOM_MODE__: - m_container->canvas (m_handle)->setCursor (mouseMode (), - fp.get_pointer (), - m_pointer_cdata, - fp.get_pointershapehotspot () - .matrix_value()); - break; - - default: - break; - } + bb(0) = r.x (); + bb(1) = r.y (); + bb(2) = r.width (); + bb(3) = r.height (); + } + else + return; + } + else + { + prop = "outerposition"; + QRect r = m_outerRect; - m_blockUpdates = false; -} + if (flags & UpdateBoundingBoxPosition) + r.moveTopLeft (win->pos ()); + if (flags & UpdateBoundingBoxSize) + r.setSize (win->frameGeometry ().size ()); -void -Figure::showFigureStatusBar (bool visible) -{ - if (m_statusBar - && (! m_statusBar->isHidden ()) != visible) - { - int dy = m_statusBar->sizeHint ().height (); - QRect r = qWidget ()->geometry (); - - if (! visible) - r.adjust (0, 0, 0, -dy); - else - r.adjust (0, 0, 0, dy); + if (r.isValid () && r != m_outerRect) + { + m_outerRect = r; - m_blockUpdates = true; - set_geometry (r); - m_statusBar->setVisible (visible); - m_blockUpdates = false; - - updateBoundingBox (false); - } -} + bb(0) = r.x (); + bb(1) = r.y (); + bb(2) = r.width (); + bb(3) = r.height (); + } + else + return; + } -void -Figure::updateFigureHeight (int dh) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + figure::properties& fp = properties
(); - octave::autolock guard (gh_mgr.graphics_lock ()); - graphics_object go = object (); - - if (go.valid_object () && dh != 0) - { - QRect r = qWidget ()->geometry (); - - r.adjust (0, dh, 0, 0); + emit gh_set_event (m_handle, prop, fp.bbox2position (bb), false, + prop == "position"); + } - m_blockUpdates = true; - set_geometry (r); - m_blockUpdates = false; - - updateBoundingBox (false); - } -} + bool + Figure::eventNotifyBefore (QObject *obj, QEvent *xevent) + { + if (! m_blockUpdates) + { + // Clicking the toolbar or the menubar makes this figure current + if (xevent->type () == QEvent::MouseButtonPress) + { + figure::properties& fp = properties
(); -void -Figure::updateStatusBar (ColumnVector pt) -{ - if (! m_statusBar->isHidden ()) - m_statusBar->showMessage (QString ("(%1, %2)") - .arg (pt(0), 0, 'g', 5) - .arg (pt(1), 0, 'g', 5)); -} + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + graphics_object root = gh_mgr.get_object (0); -void -Figure::do_connections (const QObject *receiver, const QObject * /* emitter */) -{ - Object::do_connections (receiver); - Object::do_connections (receiver, m_container->canvas (m_handle)); -} + if (fp.get_handlevisibility () == "on") + root.set ("currentfigure", + fp.get___myhandle__ ().as_octave_value ()); + } -QWidget * -Figure::menu (void) -{ - return qWidget ()->menuBar (); -} - -void -Figure::updateBoundingBox (bool internal, int flags) -{ - QWidget *win = qWidget (); - Matrix bb (1, 4); - std::string prop; - - if (internal) - { - prop = "position"; - QRect r = m_innerRect; + if (obj == m_container) + { + // Do nothing... + } + else if (obj == m_menuBar) + { + switch (xevent->type ()) + { + case QEvent::ActionAdded: + case QEvent::ActionChanged: + case QEvent::ActionRemoved: + m_previousHeight = m_menuBar->sizeHint ().height (); - if (flags & UpdateBoundingBoxPosition) - r.moveTopLeft (win->mapToGlobal (m_container->pos ())); - if (flags & UpdateBoundingBoxSize) - r.setSize (m_container->size ()); - - if (r.isValid () && r != m_innerRect) - { - m_innerRect = r; + default: + break; + } + } + else + { + switch (xevent->type ()) + { + case QEvent::Close: + xevent->ignore (); + emit gh_callback_event (m_handle, "closerequestfcn"); + return true; - bb(0) = r.x (); - bb(1) = r.y (); - bb(2) = r.width (); - bb(3) = r.height (); - } - else - return; - } - else - { - prop = "outerposition"; - QRect r = m_outerRect; + default: + break; + } + } + } - if (flags & UpdateBoundingBoxPosition) - r.moveTopLeft (win->pos ()); - if (flags & UpdateBoundingBoxSize) - r.setSize (win->frameGeometry ().size ()); + return false; + } - if (r.isValid () && r != m_outerRect) - { - m_outerRect = r; + void + Figure::eventNotifyAfter (QObject *watched, QEvent *xevent) + { + if (! m_blockUpdates) + { + if (watched == m_container) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - bb(0) = r.x (); - bb(1) = r.y (); - bb(2) = r.width (); - bb(3) = r.height (); - } - else - return; - } - - figure::properties& fp = properties
(); - - emit gh_set_event (m_handle, prop, fp.bbox2position (bb), false, - prop == "position"); -} + switch (xevent->type ()) + { + case QEvent::Resize: + updateBoundingBox (true, UpdateBoundingBoxSize); + break; -bool -Figure::eventNotifyBefore (QObject *obj, QEvent *xevent) -{ - if (! m_blockUpdates) - { - // Clicking the toolbar or the menubar makes this figure current - if (xevent->type () == QEvent::MouseButtonPress) - { - figure::properties& fp = properties
(); - - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - graphics_object root = gh_mgr.get_object (0); + case QEvent::ChildAdded: + if (dynamic_cast (xevent)->child + ()->isWidgetType()) + { + octave::autolock guard (gh_mgr.graphics_lock ()); + update (figure::properties::ID_TOOLBAR); - if (fp.get_handlevisibility () == "on") - root.set ("currentfigure", - fp.get___myhandle__ ().as_octave_value ()); - } + enableMouseTracking (); + } + break; - if (obj == m_container) - { - // Do nothing... - } - else if (obj == m_menuBar) - { - switch (xevent->type ()) - { - case QEvent::ActionAdded: - case QEvent::ActionChanged: - case QEvent::ActionRemoved: - m_previousHeight = m_menuBar->sizeHint ().height (); + case QEvent::ChildRemoved: + if (dynamic_cast (xevent)->child + ()->isWidgetType()) + { + octave::autolock guard (gh_mgr.graphics_lock ()); + update (figure::properties::ID_TOOLBAR); + } + break; - default: - break; - } - } - else - { - switch (xevent->type ()) - { - case QEvent::Close: - xevent->ignore (); - emit gh_callback_event (m_handle, "closerequestfcn"); - return true; - - default: - break; - } - } - } - - return false; -} + default: + break; + } + } + else if (watched == m_menuBar) + { + switch (xevent->type ()) + { + case QEvent::ActionAdded: + case QEvent::ActionChanged: + case QEvent::ActionRemoved: + // The menubar may have been resized if no action is visible + { + QAction *a = dynamic_cast (xevent)->action (); + int currentHeight = m_menuBar->sizeHint ().height (); + if (currentHeight != m_previousHeight + && ! a->isSeparator ()) + updateFigureHeight (m_previousHeight - currentHeight); + } + break; -void -Figure::eventNotifyAfter (QObject *watched, QEvent *xevent) -{ - if (! m_blockUpdates) - { - if (watched == m_container) - { - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + default: + break; + } + } + else + { + switch (xevent->type ()) + { + case QEvent::Move: + updateBoundingBox (false, UpdateBoundingBoxPosition); + updateBoundingBox (true, UpdateBoundingBoxPosition); + break; - switch (xevent->type ()) - { - case QEvent::Resize: - updateBoundingBox (true, UpdateBoundingBoxSize); - break; - - case QEvent::ChildAdded: - if (dynamic_cast (xevent)->child - ()->isWidgetType()) - { - octave::autolock guard (gh_mgr.graphics_lock ()); - update (figure::properties::ID_TOOLBAR); - - enableMouseTracking (); - } - break; + case QEvent::Resize: + updateBoundingBox (false, UpdateBoundingBoxSize); + break; - case QEvent::ChildRemoved: - if (dynamic_cast (xevent)->child - ()->isWidgetType()) - { - octave::autolock guard (gh_mgr.graphics_lock ()); - update (figure::properties::ID_TOOLBAR); - } - break; + default: + break; + } + } + } + } + + void + Figure::addCustomToolBar (QToolBar *bar, bool visible, bool isdefault) + { + QMainWindow *win = qWidget (); + + if (isdefault) + m_figureToolBar = bar; - default: - break; - } - } - else if (watched == m_menuBar) - { - switch (xevent->type ()) - { - case QEvent::ActionAdded: - case QEvent::ActionChanged: - case QEvent::ActionRemoved: - // The menubar may have been resized if no action is visible - { - QAction *a = dynamic_cast (xevent)->action (); - int currentHeight = m_menuBar->sizeHint ().height (); - if (currentHeight != m_previousHeight - && ! a->isSeparator ()) - updateFigureHeight (m_previousHeight - currentHeight); - } - break; + if (! visible) + win->addToolBar (bar); + else + { + QSize sz = bar->sizeHint (); + QRect r = win->geometry (); + + r.adjust (0, -sz.height (), 0, 0); - default: - break; - } - } - else - { - switch (xevent->type ()) - { - case QEvent::Move: - updateBoundingBox (false, UpdateBoundingBoxPosition); - updateBoundingBox (true, UpdateBoundingBoxPosition); - break; + m_blockUpdates = true; + set_geometry (r); + win->addToolBarBreak (); + win->addToolBar (bar); + m_blockUpdates = false; - case QEvent::Resize: - updateBoundingBox (false, UpdateBoundingBoxSize); - break; + updateBoundingBox (false); + } + } - default: - break; - } - } - } -} + void + Figure::showCustomToolBar (QToolBar *bar, bool visible) + { + QMainWindow *win = qWidget (); -void -Figure::addCustomToolBar (QToolBar *bar, bool visible, bool isdefault) -{ - QMainWindow *win = qWidget (); - - if (isdefault) - m_figureToolBar = bar; + if ((! bar->isHidden ()) != visible) + { + QSize sz = bar->sizeHint (); + QRect r = win->geometry (); - if (! visible) - win->addToolBar (bar); - else - { - QSize sz = bar->sizeHint (); - QRect r = win->geometry (); + if (visible) + r.adjust (0, -sz.height (), 0, 0); + else + r.adjust (0, sz.height (), 0, 0); - r.adjust (0, -sz.height (), 0, 0); - - m_blockUpdates = true; - set_geometry (r); - win->addToolBarBreak (); - win->addToolBar (bar); - m_blockUpdates = false; + m_blockUpdates = true; + set_geometry (r); + bar->setVisible (visible); + m_blockUpdates = false; - updateBoundingBox (false); - } -} + updateBoundingBox (false); + } + } -void -Figure::showCustomToolBar (QToolBar *bar, bool visible) -{ - QMainWindow *win = qWidget (); - - if ((! bar->isHidden ()) != visible) - { - QSize sz = bar->sizeHint (); - QRect r = win->geometry (); + void + Figure::updateContainer (void) + { + redraw (); + } - if (visible) - r.adjust (0, -sz.height (), 0, 0); - else - r.adjust (0, sz.height (), 0, 0); + void + Figure::figureWindowShown () + { +#if defined (HAVE_QSCREEN_DEVICEPIXELRATIO) + QWindow *window = qWidget ()->windowHandle (); + QScreen *screen = window->screen (); - m_blockUpdates = true; - set_geometry (r); - bar->setVisible (visible); - m_blockUpdates = false; + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - updateBoundingBox (false); - } -} + octave::autolock guard (gh_mgr.graphics_lock ()); -void -Figure::updateContainer (void) -{ - redraw (); -} - -void -Figure::figureWindowShown () -{ -#if defined (HAVE_QSCREEN_DEVICEPIXELRATIO) - QWindow *window = qWidget ()->windowHandle (); - QScreen *screen = window->screen (); + figure::properties& fp = properties
(); + fp.set___device_pixel_ratio__ (screen->devicePixelRatio ()); - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - octave::autolock guard (gh_mgr.graphics_lock ()); - - figure::properties& fp = properties
(); - fp.set___device_pixel_ratio__ (screen->devicePixelRatio ()); + connect (window, &QWindow::screenChanged, this, &Figure::screenChanged); +#endif + } - connect (window, &QWindow::screenChanged, this, &Figure::screenChanged); -#endif -} - -void -Figure::screenChanged (QScreen *screen) -{ + void + Figure::screenChanged (QScreen *screen) + { #if defined (HAVE_QSCREEN_DEVICEPIXELRATIO) - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - octave::autolock guard (gh_mgr.graphics_lock ()); + octave::autolock guard (gh_mgr.graphics_lock ()); - figure::properties& fp = properties
(); - double old_dpr = fp.get___device_pixel_ratio__ (); - double new_dpr = screen->devicePixelRatio (); - if (old_dpr != new_dpr) - { - fp.set___device_pixel_ratio__ (new_dpr); + figure::properties& fp = properties
(); + double old_dpr = fp.get___device_pixel_ratio__ (); + double new_dpr = screen->devicePixelRatio (); + if (old_dpr != new_dpr) + { + fp.set___device_pixel_ratio__ (new_dpr); - // For some obscure reason, changing the __device_pixel_ratio__ property - // from the GUI thread does not necessarily trigger a redraw. Force it. - redraw (); - } + // For some obscure reason, changing the __device_pixel_ratio__ property + // from the GUI thread does not necessarily trigger a redraw. Force it. + redraw (); + } #else - octave_unused_parameter (screen); + octave_unused_parameter (screen); #endif -} + } -void -Figure::enableMouseTracking (void) -{ - // Enable mouse tracking on every widgets - m_container->setMouseTracking (true); - m_container->canvas (m_handle)->qWidget ()->setMouseTracking (true); - for (auto *w : m_container->findChildren ()) - w->setMouseTracking (true); -} + void + Figure::enableMouseTracking (void) + { + // Enable mouse tracking on every widgets + m_container->setMouseTracking (true); + m_container->canvas (m_handle)->qWidget ()->setMouseTracking (true); + for (auto *w : m_container->findChildren ()) + w->setMouseTracking (true); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/Figure.h --- a/libgui/graphics/Figure.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/Figure.h Tue Dec 06 15:45:27 2022 -0500 @@ -39,10 +39,9 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -enum MouseMode + enum MouseMode { NoMode, RotateMode, @@ -53,94 +52,94 @@ TextMode }; -class Container; -class FigureWindow; -class MenuBar; -class ToolBar; + class Container; + class FigureWindow; + class MenuBar; + class ToolBar; -class Figure : - public Object, - public MenuContainer, - public GenericEventNotifyReceiver -{ - Q_OBJECT + class Figure : + public Object, + public MenuContainer, + public GenericEventNotifyReceiver + { + Q_OBJECT - friend class ToolBar; + friend class ToolBar; -public: - Figure (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, FigureWindow *win); - ~Figure (void); + public: + Figure (octave::interpreter& interp, + const graphics_object& go, FigureWindow *win); + ~Figure (void); - static Figure * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + static Figure * + create (octave::interpreter& interp, + const graphics_object& go); - QString fileName (void); - void setFileName (const QString& name); + QString fileName (void); + void setFileName (const QString& name); - MouseMode mouseMode (void); + MouseMode mouseMode (void); - Container * innerContainer (void); - QWidget * menu (void); - void updateStatusBar (ColumnVector pt); + Container * innerContainer (void); + QWidget * menu (void); + void updateStatusBar (ColumnVector pt); - void do_connections (const QObject *receiver, - const QObject *emitter = nullptr); + void do_connections (const QObject *receiver, + const QObject *emitter = nullptr); - bool eventNotifyBefore (QObject *watched, QEvent *event); - void eventNotifyAfter (QObject *watched, QEvent *event); + bool eventNotifyBefore (QObject *watched, QEvent *event); + void eventNotifyAfter (QObject *watched, QEvent *event); -protected: - enum UpdateBoundingBoxFlag + protected: + enum UpdateBoundingBoxFlag { UpdateBoundingBoxPosition = 0x1, UpdateBoundingBoxSize = 0x2, UpdateBoundingBoxAll = 0x3 }; -protected: - void redraw (void); - void show (void); - void print (const QString& file_cmd, const QString& term); - void update (int pId); - void updateBoundingBox (bool internal = false, int flags = 0); - void beingDeleted (void); + protected: + void redraw (void); + void show (void); + void print (const QString& file_cmd, const QString& term); + void update (int pId); + void updateBoundingBox (bool internal = false, int flags = 0); + void beingDeleted (void); -private: - void showFigureStatusBar (bool visible); - void addCustomToolBar (QToolBar *bar, bool visible, bool isdefault); - void showCustomToolBar (QToolBar *bar, bool visible); - void set_geometry (QRect r); + private: + void showFigureStatusBar (bool visible); + void addCustomToolBar (QToolBar *bar, bool visible, bool isdefault); + void showCustomToolBar (QToolBar *bar, bool visible); + void set_geometry (QRect r); - void enableMouseTracking (void); + void enableMouseTracking (void); -private slots: - void updateFigureHeight (int delta_h); - void updateContainer (void); - void figureWindowShown (); - void screenChanged (QScreen *); + private slots: + void updateFigureHeight (int delta_h); + void updateContainer (void); + void figureWindowShown (); + void screenChanged (QScreen *); -public slots: - uint8NDArray slotGetPixels (void); + public slots: + uint8NDArray slotGetPixels (void); -signals: - void asyncUpdate (void); - void interpreter_event (const octave::fcn_callback& fcn); - void interpreter_event (const octave::meth_callback& meth); + signals: + void asyncUpdate (void); + void interpreter_event (const octave::fcn_callback& fcn); + void interpreter_event (const octave::meth_callback& meth); -private: - Container *m_container; - bool m_blockUpdates; - QToolBar *m_figureToolBar; - MenuBar *m_menuBar; - QStatusBar *m_statusBar; - QRect m_innerRect; - QRect m_outerRect; - QImage m_pointer_cdata; - int m_previousHeight; - bool m_resizable; -}; + private: + Container *m_container; + bool m_blockUpdates; + QToolBar *m_figureToolBar; + MenuBar *m_menuBar; + QStatusBar *m_statusBar; + QRect m_innerRect; + QRect m_outerRect; + QImage m_pointer_cdata; + int m_previousHeight; + bool m_resizable; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/GLCanvas.cc --- a/libgui/graphics/GLCanvas.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/GLCanvas.cc Tue Dec 06 15:45:27 2022 -0500 @@ -45,280 +45,279 @@ QGLFormat (QGL::SampleBuffers | QGL::AlphaChannel \ | QGL::IndirectRendering), # else -# define OCTAVE_QT_OPENGL_WIDGET_FORMAT_ARGS \ +# define OCTAVE_QT_OPENGL_WIDGET_FORMAT_ARGS \ QGLFormat (QGL::SampleBuffers | QGL::AlphaChannel), # endif #endif -GLCanvas::GLCanvas (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_handle& gh, QWidget *xparent) -: OCTAVE_QT_OPENGL_WIDGET (OCTAVE_QT_OPENGL_WIDGET_FORMAT_ARGS xparent), - Canvas (oct_qobj, interp, gh), m_glfcns (), m_renderer (m_glfcns) -{ - setFocusPolicy (Qt::ClickFocus); - setFocus (); -} + GLCanvas::GLCanvas (octave::interpreter& interp, + const graphics_handle& gh, QWidget *xparent) + : OCTAVE_QT_OPENGL_WIDGET (OCTAVE_QT_OPENGL_WIDGET_FORMAT_ARGS xparent), + Canvas (interp, gh), m_glfcns (), m_renderer (m_glfcns) + { + setFocusPolicy (Qt::ClickFocus); + setFocus (); + } -GLCanvas::~GLCanvas (void) -{ } + GLCanvas::~GLCanvas (void) + { } -void -GLCanvas::initializeGL (void) -{ - m_glfcns.init (); -} + void + GLCanvas::initializeGL (void) + { + m_glfcns.init (); + } -void -GLCanvas::draw (const graphics_handle& gh) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + void + GLCanvas::draw (const graphics_handle& gh) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - octave::autolock guard (gh_mgr.graphics_lock ()); + octave::autolock guard (gh_mgr.graphics_lock ()); - graphics_object go = gh_mgr.get_object (gh); + graphics_object go = gh_mgr.get_object (gh); - if (go) - { - graphics_object fig = go.get_ancestor ("figure"); - double dpr = fig.get ("__device_pixel_ratio__").double_value (); - m_renderer.set_viewport (dpr * width (), dpr * height ()); - m_renderer.set_device_pixel_ratio (dpr); - m_renderer.draw (go); - } -} + if (go) + { + graphics_object fig = go.get_ancestor ("figure"); + double dpr = fig.get ("__device_pixel_ratio__").double_value (); + m_renderer.set_viewport (dpr * width (), dpr * height ()); + m_renderer.set_device_pixel_ratio (dpr); + m_renderer.draw (go); + } + } -uint8NDArray -GLCanvas::do_getPixels (const graphics_handle& gh) -{ - uint8NDArray retval; + uint8NDArray + GLCanvas::do_getPixels (const graphics_handle& gh) + { + uint8NDArray retval; - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - graphics_object go = gh_mgr.get_object (gh); + graphics_object go = gh_mgr.get_object (gh); - if (go && go.isa ("figure")) - { - Matrix pos = go.get ("position").matrix_value (); - double dpr = go.get ("__device_pixel_ratio__").double_value (); - pos(2) *= dpr; - pos(3) *= dpr; + if (go && go.isa ("figure")) + { + Matrix pos = go.get ("position").matrix_value (); + double dpr = go.get ("__device_pixel_ratio__").double_value (); + pos(2) *= dpr; + pos(3) *= dpr; - // Make sure we have a valid current context - if (! begin_rendering ()) - return retval; + // Make sure we have a valid current context + if (! begin_rendering ()) + return retval; - // When the figure is not visible or its size is frozen for printing, - // we use a framebuffer object to make sure we are rendering on a - // suitably large frame. - if (go.get ("visible").string_value () == "off" - || go.get ("__printing__").string_value () == "on") - { - OCTAVE_QT_OPENGL_FBO + // When the figure is not visible or its size is frozen for printing, + // we use a framebuffer object to make sure we are rendering on a + // suitably large frame. + if (go.get ("visible").string_value () == "off" + || go.get ("__printing__").string_value () == "on") + { + OCTAVE_QT_OPENGL_FBO fbo (pos(2), pos(3), OCTAVE_QT_OPENGL_FBO::Attachment::Depth); - fbo.bind (); + fbo.bind (); - m_renderer.set_viewport (pos(2), pos(3)); - m_renderer.set_device_pixel_ratio (dpr); - m_renderer.draw (go); - retval = m_renderer.get_pixels (pos(2), pos(3)); + m_renderer.set_viewport (pos(2), pos(3)); + m_renderer.set_device_pixel_ratio (dpr); + m_renderer.draw (go); + retval = m_renderer.get_pixels (pos(2), pos(3)); - fbo.release (); - } - else - { - m_renderer.set_viewport (pos(2), pos(3)); - m_renderer.set_device_pixel_ratio (dpr); - m_renderer.draw (go); - retval = m_renderer.get_pixels (pos(2), pos(3)); - } + fbo.release (); + } + else + { + m_renderer.set_viewport (pos(2), pos(3)); + m_renderer.set_device_pixel_ratio (dpr); + m_renderer.draw (go); + retval = m_renderer.get_pixels (pos(2), pos(3)); + } - end_rendering (); - } - - return retval; -} - -void -GLCanvas::do_print (const QString& file_cmd, const QString& term, - const graphics_handle& handle) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - octave::autolock guard (gh_mgr.graphics_lock ()); + end_rendering (); + } - graphics_object go = gh_mgr.get_object (handle); + return retval; + } - if (go.valid_object ()) - { - graphics_object fig (go.get_ancestor ("figure")); + void + GLCanvas::do_print (const QString& file_cmd, const QString& term, + const graphics_handle& handle) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - // Make sure we have a valid current context - if (! begin_rendering ()) - error ("print: no valid OpenGL offscreen context"); + octave::autolock guard (gh_mgr.graphics_lock ()); - try - { - if (fig.get ("visible").string_value () == "on") - octave::gl2ps_print (m_glfcns, fig, file_cmd.toStdString (), - term.toStdString ()); - else - { - // When the figure is not visible, we use a framebuffer object - // to make sure we are rendering on a suitably large frame. - Matrix pos = fig.get ("position").matrix_value (); - double dpr = fig.get ("__device_pixel_ratio__").double_value (); - pos(2) *= dpr; - pos(3) *= dpr; + graphics_object go = gh_mgr.get_object (handle); + + if (go.valid_object ()) + { + graphics_object fig (go.get_ancestor ("figure")); - OCTAVE_QT_OPENGL_FBO - fbo (pos(2), pos(3), - OCTAVE_QT_OPENGL_FBO::Attachment::Depth); + // Make sure we have a valid current context + if (! begin_rendering ()) + error ("print: no valid OpenGL offscreen context"); - fbo.bind (); - + try + { + if (fig.get ("visible").string_value () == "on") octave::gl2ps_print (m_glfcns, fig, file_cmd.toStdString (), term.toStdString ()); - - fbo.release (); - } - } - catch (octave::execution_exception& ee) - { - emit interpreter_event - ([=] (void) - { - // INTERPRETER THREAD - throw ee; - }); - } - - end_rendering (); - } -} - -graphics_object -GLCanvas::selectFromAxes (const graphics_object& ax, const QPoint& pt) -{ - makeCurrent (); - - if (ax) - { - octave::opengl_selector s (m_glfcns); - - s.set_viewport (width (), height ()); - return s.select (ax, pt.x (), height () - pt.y (), - octave::select_ignore_hittest); - } + else + { + // When the figure is not visible, we use a framebuffer object + // to make sure we are rendering on a suitably large frame. + Matrix pos = fig.get ("position").matrix_value (); + double dpr = fig.get ("__device_pixel_ratio__").double_value (); + pos(2) *= dpr; + pos(3) *= dpr; - return graphics_object (); -} - -void -GLCanvas::drawZoomBox (const QPoint& p1, const QPoint& p2) -{ - Matrix overlaycolor (3, 1); - overlaycolor(0) = 0.45; - overlaycolor(1) = 0.62; - overlaycolor(2) = 0.81; - double overlayalpha = 0.1; - Matrix bordercolor = overlaycolor; - double borderalpha = 0.9; - double borderwidth = 1.5; + OCTAVE_QT_OPENGL_FBO + fbo (pos(2), pos(3), + OCTAVE_QT_OPENGL_FBO::Attachment::Depth); - m_renderer.draw_zoom_box (width (), height (), - p1.x (), p1.y (), p2.x (), p2.y (), - overlaycolor, overlayalpha, - bordercolor, borderalpha, borderwidth); -} + fbo.bind (); -void -GLCanvas::paintGL (void) -{ - canvasPaintEvent (); -} - -void -GLCanvas::mouseDoubleClickEvent (QMouseEvent *xevent) -{ - canvasMouseDoubleClickEvent (xevent); -} + octave::gl2ps_print (m_glfcns, fig, file_cmd.toStdString (), + term.toStdString ()); -void -GLCanvas::mouseMoveEvent (QMouseEvent *xevent) -{ - canvasMouseMoveEvent (xevent); -} - -void -GLCanvas::mousePressEvent (QMouseEvent *xevent) -{ - canvasMousePressEvent (xevent); -} - -void -GLCanvas::mouseReleaseEvent (QMouseEvent *xevent) -{ - canvasMouseReleaseEvent (xevent); -} - -void -GLCanvas::wheelEvent (QWheelEvent *xevent) -{ - canvasWheelEvent (xevent); -} - -void -GLCanvas::keyPressEvent (QKeyEvent *xevent) -{ - if (! canvasKeyPressEvent (xevent)) - OCTAVE_QT_OPENGL_WIDGET::keyPressEvent (xevent); -} + fbo.release (); + } + } + catch (octave::execution_exception& ee) + { + emit interpreter_event + ([=] (void) + { + // INTERPRETER THREAD + throw ee; + }); + } -void -GLCanvas::keyReleaseEvent (QKeyEvent *xevent) -{ - if (! canvasKeyReleaseEvent (xevent)) - OCTAVE_QT_OPENGL_WIDGET::keyReleaseEvent (xevent); -} - -bool -GLCanvas::begin_rendering (void) -{ - bool retval = true; + end_rendering (); + } + } - if (! isValid ()) - { -# if defined (HAVE_QT_OFFSCREEN) - static bool os_ctx_ok = true; - if (os_ctx_ok && ! m_os_context.isValid ()) - { - // Try to initialize offscreen context - m_os_surface.create (); - if (! m_os_context.create ()) - { - os_ctx_ok = false; - return false; - } - } - - retval = m_os_context.makeCurrent (&m_os_surface); -# else - retval = false; -# endif - } - else + graphics_object + GLCanvas::selectFromAxes (const graphics_object& ax, const QPoint& pt) + { makeCurrent (); - return retval; -} + if (ax) + { + octave::opengl_selector s (m_glfcns); + + s.set_viewport (width (), height ()); + return s.select (ax, pt.x (), height () - pt.y (), + octave::select_ignore_hittest); + } + + return graphics_object (); + } + + void + GLCanvas::drawZoomBox (const QPoint& p1, const QPoint& p2) + { + Matrix overlaycolor (3, 1); + overlaycolor(0) = 0.45; + overlaycolor(1) = 0.62; + overlaycolor(2) = 0.81; + double overlayalpha = 0.1; + Matrix bordercolor = overlaycolor; + double borderalpha = 0.9; + double borderwidth = 1.5; + + m_renderer.draw_zoom_box (width (), height (), + p1.x (), p1.y (), p2.x (), p2.y (), + overlaycolor, overlayalpha, + bordercolor, borderalpha, borderwidth); + } + + void + GLCanvas::paintGL (void) + { + canvasPaintEvent (); + } + + void + GLCanvas::mouseDoubleClickEvent (QMouseEvent *xevent) + { + canvasMouseDoubleClickEvent (xevent); + } + + void + GLCanvas::mouseMoveEvent (QMouseEvent *xevent) + { + canvasMouseMoveEvent (xevent); + } + + void + GLCanvas::mousePressEvent (QMouseEvent *xevent) + { + canvasMousePressEvent (xevent); + } -void -GLCanvas::end_rendering (void) -{ - doneCurrent (); -} + void + GLCanvas::mouseReleaseEvent (QMouseEvent *xevent) + { + canvasMouseReleaseEvent (xevent); + } + + void + GLCanvas::wheelEvent (QWheelEvent *xevent) + { + canvasWheelEvent (xevent); + } + + void + GLCanvas::keyPressEvent (QKeyEvent *xevent) + { + if (! canvasKeyPressEvent (xevent)) + OCTAVE_QT_OPENGL_WIDGET::keyPressEvent (xevent); + } + + void + GLCanvas::keyReleaseEvent (QKeyEvent *xevent) + { + if (! canvasKeyReleaseEvent (xevent)) + OCTAVE_QT_OPENGL_WIDGET::keyReleaseEvent (xevent); + } + + bool + GLCanvas::begin_rendering (void) + { + bool retval = true; + + if (! isValid ()) + { +# if defined (HAVE_QT_OFFSCREEN) + static bool os_ctx_ok = true; + if (os_ctx_ok && ! m_os_context.isValid ()) + { + // Try to initialize offscreen context + m_os_surface.create (); + if (! m_os_context.create ()) + { + os_ctx_ok = false; + return false; + } + } + + retval = m_os_context.makeCurrent (&m_os_surface); +# else + retval = false; +# endif + } + else + makeCurrent (); + + return retval; + } + + void + GLCanvas::end_rendering (void) + { + doneCurrent (); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/GLCanvas.h --- a/libgui/graphics/GLCanvas.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/GLCanvas.h Tue Dec 06 15:45:27 2022 -0500 @@ -51,54 +51,49 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -} - -OCTAVE_BEGIN_NAMESPACE(octave) + class GLCanvas : public OCTAVE_QT_OPENGL_WIDGET, public Canvas + { + public: + GLCanvas (octave::interpreter& interp, + const graphics_handle& handle, QWidget *parent); + ~GLCanvas (void); -class GLCanvas : public OCTAVE_QT_OPENGL_WIDGET, public Canvas -{ -public: - GLCanvas (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_handle& handle, QWidget *parent); - ~GLCanvas (void); - - void initializeGL (void); + void initializeGL (void); - void draw (const graphics_handle& handle); - uint8NDArray do_getPixels (const graphics_handle& handle); - void do_print (const QString& file_cmd, const QString& term, - const graphics_handle& handle); - void drawZoomBox (const QPoint& p1, const QPoint& p2); - void resize (int /* x */, int /* y */, - int /* width */, int /* height */) { } - graphics_object selectFromAxes (const graphics_object& ax, - const QPoint& pt); - QWidget * qWidget (void) { return this; } + void draw (const graphics_handle& handle); + uint8NDArray do_getPixels (const graphics_handle& handle); + void do_print (const QString& file_cmd, const QString& term, + const graphics_handle& handle); + void drawZoomBox (const QPoint& p1, const QPoint& p2); + void resize (int /* x */, int /* y */, + int /* width */, int /* height */) { } + graphics_object selectFromAxes (const graphics_object& ax, + const QPoint& pt); + QWidget * qWidget (void) { return this; } -protected: - void paintGL (void); - void mouseDoubleClickEvent (QMouseEvent *event); - void mouseMoveEvent (QMouseEvent *event); - void mousePressEvent (QMouseEvent *event); - void mouseReleaseEvent (QMouseEvent *event); - void wheelEvent (QWheelEvent *event); - void keyPressEvent (QKeyEvent *event); - void keyReleaseEvent (QKeyEvent *event); + protected: + void paintGL (void); + void mouseDoubleClickEvent (QMouseEvent *event); + void mouseMoveEvent (QMouseEvent *event); + void mousePressEvent (QMouseEvent *event); + void mouseReleaseEvent (QMouseEvent *event); + void wheelEvent (QWheelEvent *event); + void keyPressEvent (QKeyEvent *event); + void keyReleaseEvent (QKeyEvent *event); -private: + private: - bool begin_rendering (void); - void end_rendering (void); + bool begin_rendering (void); + void end_rendering (void); - octave::qopengl_functions m_glfcns; - octave::opengl_renderer m_renderer; + octave::qopengl_functions m_glfcns; + octave::opengl_renderer m_renderer; # if defined (HAVE_QT_OFFSCREEN) - QOpenGLContext m_os_context; - QOffscreenSurface m_os_surface; + QOpenGLContext m_os_context; + QOffscreenSurface m_os_surface; # endif -}; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ListBoxControl.cc --- a/libgui/graphics/ListBoxControl.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ListBoxControl.cc Tue Dec 06 15:45:27 2022 -0500 @@ -35,256 +35,252 @@ #include "ListBoxControl.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - OCTAVE_BEGIN_NAMESPACE(octave) -static void -updateSelection (QListWidget *list, const Matrix& value) -{ - octave_idx_type n = value.numel (); - int lc = list->count (); - - list->clearSelection (); - - for (octave_idx_type i = 0; i < n; i++) - { - int idx = octave::math::round (value(i)); + static void + updateSelection (QListWidget *list, const Matrix& value) + { + octave_idx_type n = value.numel (); + int lc = list->count (); - if (1 <= idx && idx <= lc) - { - list->item (idx-1)->setSelected (true); - list->scrollToItem (list->item (idx-1)); - if (i == 0 - && list->selectionMode () == QAbstractItemView::SingleSelection) - break; - } - else - { - // Invalid selection. - list->clearSelection (); - break; - } - } -} + list->clearSelection (); -ListBoxControl * -ListBoxControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go) -{ - Object *parent = parentObject (interp, go); - - if (parent) - { - Container *container = parent->innerContainer (); - - if (container) - return new ListBoxControl (oct_qobj, interp, go, - new QListWidget (container)); - } - - return nullptr; -} - -ListBoxControl::ListBoxControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, QListWidget *list) - : BaseControl (oct_qobj, interp, go, list), m_blockCallback (false), - m_selectionChanged (false) -{ - uicontrol::properties& up = properties (); + for (octave_idx_type i = 0; i < n; i++) + { + int idx = octave::math::round (value(i)); - list->addItems (Utils::fromStringVector (up.get_string_vector ())); - if ((up.get_max () - up.get_min ()) > 1) - list->setSelectionMode (QAbstractItemView::ExtendedSelection); - else - list->setSelectionMode (QAbstractItemView::SingleSelection); - Matrix value = up.get_value ().matrix_value (); - if (value.numel () > 0) - { - octave_idx_type n = value.numel (); - int lc = list->count (); - - for (octave_idx_type i = 0; i < n; i++) - { - int idx = octave::math::round (value(i)); - - if (1 <= idx && idx <= lc) - { - list->item (idx-1)->setSelected (true); - list->scrollToItem (list->item (idx-1)); - if (i == 0 && (list->selectionMode () - == QAbstractItemView::SingleSelection)) - break; - } - } - } - - list->viewport ()->installEventFilter (this); + if (1 <= idx && idx <= lc) + { + list->item (idx-1)->setSelected (true); + list->scrollToItem (list->item (idx-1)); + if (i == 0 + && list->selectionMode () == QAbstractItemView::SingleSelection) + break; + } + else + { + // Invalid selection. + list->clearSelection (); + break; + } + } + } - connect (list, &QListWidget::itemSelectionChanged, - this, &ListBoxControl::itemSelectionChanged); - connect (list, &QListWidget::activated, - this, &ListBoxControl::itemActivated); - connect (list, &QListWidget::itemPressed, - this, &ListBoxControl::itemPressed); -} - -ListBoxControl::~ListBoxControl (void) -{ } - -void -ListBoxControl::update (int pId) -{ - uicontrol::properties& up = properties (); - QListWidget *list = qWidget (); + ListBoxControl * + ListBoxControl::create (octave::interpreter& interp, + const graphics_object& go) + { + Object *parent = parentObject (interp, go); - switch (pId) - { - case uicontrol::properties::ID_STRING: - m_blockCallback = true; - list->clear (); - list->addItems (Utils::fromStringVector (up.get_string_vector ())); - updateSelection (list, up.get_value ().matrix_value ()); - m_blockCallback = false; - break; + if (parent) + { + Container *container = parent->innerContainer (); - case uicontrol::properties::ID_MIN: - case uicontrol::properties::ID_MAX: - if ((up.get_max () - up.get_min ()) > 1) - list->setSelectionMode (QAbstractItemView::ExtendedSelection); - else - list->setSelectionMode (QAbstractItemView::SingleSelection); - break; - - case uicontrol::properties::ID_LISTBOXTOP: - { - int idx = octave::math::fix (up.get_listboxtop ()); - if (idx > 0) - list->scrollToItem (list->item (idx-1), - QAbstractItemView::PositionAtTop); - break; + if (container) + return new ListBoxControl (interp, go, + new QListWidget (container)); } - case uicontrol::properties::ID_VALUE: - m_blockCallback = true; - updateSelection (list, up.get_value ().matrix_value ()); - m_blockCallback = false; - break; + return nullptr; + } - default: - BaseControl::update (pId); - break; - } -} + ListBoxControl::ListBoxControl (octave::interpreter& interp, + const graphics_object& go, QListWidget *list) + : BaseControl (interp, go, list), m_blockCallback (false), + m_selectionChanged (false) + { + uicontrol::properties& up = properties (); -void -ListBoxControl::sendSelectionChange () -{ - if (! m_blockCallback) - { - QListWidget *list = qWidget (); + list->addItems (Utils::fromStringVector (up.get_string_vector ())); + if ((up.get_max () - up.get_min ()) > 1) + list->setSelectionMode (QAbstractItemView::ExtendedSelection); + else + list->setSelectionMode (QAbstractItemView::SingleSelection); + Matrix value = up.get_value ().matrix_value (); + if (value.numel () > 0) + { + octave_idx_type n = value.numel (); + int lc = list->count (); - QModelIndexList l = list->selectionModel ()->selectedIndexes (); - Matrix value (dim_vector (1, l.size ())); - int i = 0; - - for (const auto& idx : l) - value(i++) = idx.row () + 1; + for (octave_idx_type i = 0; i < n; i++) + { + int idx = octave::math::round (value(i)); - emit gh_set_event (m_handle, "value", octave_value (value), false); - emit gh_callback_event (m_handle, "callback"); - } + if (1 <= idx && idx <= lc) + { + list->item (idx-1)->setSelected (true); + list->scrollToItem (list->item (idx-1)); + if (i == 0 && (list->selectionMode () + == QAbstractItemView::SingleSelection)) + break; + } + } + } - m_selectionChanged = false; -} + list->viewport ()->installEventFilter (this); -void -ListBoxControl::itemSelectionChanged (void) -{ - if (! m_blockCallback) - m_selectionChanged = true; -} + connect (list, &QListWidget::itemSelectionChanged, + this, &ListBoxControl::itemSelectionChanged); + connect (list, &QListWidget::activated, + this, &ListBoxControl::itemActivated); + connect (list, &QListWidget::itemPressed, + this, &ListBoxControl::itemPressed); + } + + ListBoxControl::~ListBoxControl (void) + { } + + void + ListBoxControl::update (int pId) + { + uicontrol::properties& up = properties (); + QListWidget *list = qWidget (); -void -ListBoxControl::itemActivated (const QModelIndex&) -{ - m_selectionChanged = true; -} -void -ListBoxControl::itemPressed (QListWidgetItem *) -{ - m_selectionChanged = true; -} + switch (pId) + { + case uicontrol::properties::ID_STRING: + m_blockCallback = true; + list->clear (); + list->addItems (Utils::fromStringVector (up.get_string_vector ())); + updateSelection (list, up.get_value ().matrix_value ()); + m_blockCallback = false; + break; -bool -ListBoxControl::eventFilter (QObject *watched, QEvent *e) -{ - // listbox change - if (watched == m_qobject) - { - switch (e->type ()) + case uicontrol::properties::ID_MIN: + case uicontrol::properties::ID_MAX: + if ((up.get_max () - up.get_min ()) > 1) + list->setSelectionMode (QAbstractItemView::ExtendedSelection); + else + list->setSelectionMode (QAbstractItemView::SingleSelection); + break; + + case uicontrol::properties::ID_LISTBOXTOP: { - case QEvent::KeyRelease: - if (m_selectionChanged) - sendSelectionChange (); - m_selectionChanged = false; - break; - - default: + int idx = octave::math::fix (up.get_listboxtop ()); + if (idx > 0) + list->scrollToItem (list->item (idx-1), + QAbstractItemView::PositionAtTop); break; } - return Object::eventFilter (watched, e); - } - // listbox viewport - else - { - bool override_return = false; - QListWidget *list = qWidget (); + case uicontrol::properties::ID_VALUE: + m_blockCallback = true; + updateSelection (list, up.get_value ().matrix_value ()); + m_blockCallback = false; + break; + + default: + BaseControl::update (pId); + break; + } + } - switch (e->type ()) - { - case QEvent::MouseButtonPress: - { - QMouseEvent *m = dynamic_cast (e); + void + ListBoxControl::sendSelectionChange () + { + if (! m_blockCallback) + { + QListWidget *list = qWidget (); + + QModelIndexList l = list->selectionModel ()->selectedIndexes (); + Matrix value (dim_vector (1, l.size ())); + int i = 0; + + for (const auto& idx : l) + value(i++) = idx.row () + 1; + + emit gh_set_event (m_handle, "value", octave_value (value), false); + emit gh_callback_event (m_handle, "callback"); + } - if (m->button () & Qt::RightButton) - override_return = true; - else - { - if (! list->indexAt (m->pos ()).isValid ()) - override_return = true; - m_selectionChanged = true; - } - break; - } - case QEvent::MouseButtonRelease: + m_selectionChanged = false; + } + + void + ListBoxControl::itemSelectionChanged (void) + { + if (! m_blockCallback) + m_selectionChanged = true; + } + + void + ListBoxControl::itemActivated (const QModelIndex&) + { + m_selectionChanged = true; + } + void + ListBoxControl::itemPressed (QListWidgetItem *) + { + m_selectionChanged = true; + } + + bool + ListBoxControl::eventFilter (QObject *watched, QEvent *e) + { + // listbox change + if (watched == m_qobject) + { + switch (e->type ()) { - QMouseEvent *m = dynamic_cast (e); - - if (m->button () & Qt::RightButton) - override_return = true; - - else if (! list->indexAt (m->pos ()).isValid ()) - { - list->setCurrentRow (list->count () - 1); - override_return = true; - } - + case QEvent::KeyRelease: if (m_selectionChanged) sendSelectionChange (); m_selectionChanged = false; + break; + default: break; } - default: - break; + + return Object::eventFilter (watched, e); + } + // listbox viewport + else + { + bool override_return = false; + QListWidget *list = qWidget (); + + switch (e->type ()) + { + case QEvent::MouseButtonPress: + { + QMouseEvent *m = dynamic_cast (e); - } - return BaseControl::eventFilter (watched, e) || override_return; - } -} + if (m->button () & Qt::RightButton) + override_return = true; + else + { + if (! list->indexAt (m->pos ()).isValid ()) + override_return = true; + m_selectionChanged = true; + } + break; + } + case QEvent::MouseButtonRelease: + { + QMouseEvent *m = dynamic_cast (e); + + if (m->button () & Qt::RightButton) + override_return = true; + + else if (! list->indexAt (m->pos ()).isValid ()) + { + list->setCurrentRow (list->count () - 1); + override_return = true; + } + + if (m_selectionChanged) + sendSelectionChange (); + m_selectionChanged = false; + + break; + } + default: + break; + + } + return BaseControl::eventFilter (watched, e) || override_return; + } + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ListBoxControl.h --- a/libgui/graphics/ListBoxControl.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ListBoxControl.h Tue Dec 06 15:45:27 2022 -0500 @@ -34,37 +34,35 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; + + class ListBoxControl : public BaseControl + { + Q_OBJECT -class ListBoxControl : public BaseControl -{ - Q_OBJECT + public: + ListBoxControl (octave::interpreter& interp, const graphics_object& go, + QListWidget *list); + ~ListBoxControl (void); -public: - ListBoxControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go, - QListWidget *list); - ~ListBoxControl (void); + static ListBoxControl * + create (octave::interpreter& interp, + const graphics_object& go); - static ListBoxControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); - -protected: - void update (int pId); - bool eventFilter (QObject *watched, QEvent *e); - void sendSelectionChange (); + protected: + void update (int pId); + bool eventFilter (QObject *watched, QEvent *e); + void sendSelectionChange (); -private slots: - void itemSelectionChanged (void); - void itemActivated (const QModelIndex&); - void itemPressed (QListWidgetItem *); + private slots: + void itemSelectionChanged (void); + void itemActivated (const QModelIndex&); + void itemPressed (QListWidgetItem *); -private: - bool m_blockCallback; - bool m_selectionChanged; -}; + private: + bool m_blockCallback; + bool m_selectionChanged; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/Menu.cc --- a/libgui/graphics/Menu.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/Menu.cc Tue Dec 06 15:45:27 2022 -0500 @@ -36,209 +36,102 @@ #include "Menu.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - OCTAVE_BEGIN_NAMESPACE(octave) -static QKeySequence -accelSequence (const uimenu::properties& up) -{ - std::string s (up.get_accelerator ()); - - if (! s.empty ()) - { - char c = s[0]; - int keyMod = Qt::CTRL; + static QKeySequence + accelSequence (const uimenu::properties& up) + { + std::string s (up.get_accelerator ()); - if (c >= 'A' && c <= 'Z') - keyMod |= Qt::SHIFT; - if (c >= 'a' && c <= 'z') - c -= ('a' - 'A'); - if (c >= 'A' && c <= 'Z') - return QKeySequence (keyMod | static_cast (c)); - } + if (! s.empty ()) + { + char c = s[0]; + int keyMod = Qt::CTRL; - return QKeySequence (); -} + if (c >= 'A' && c <= 'Z') + keyMod |= Qt::SHIFT; + if (c >= 'a' && c <= 'z') + c -= ('a' - 'A'); + if (c >= 'A' && c <= 'Z') + return QKeySequence (keyMod | static_cast (c)); + } -Menu * -Menu::create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go) -{ - Object *parent_obj = parentObject (interp, go); + return QKeySequence (); + } - if (parent_obj) - { - QObject *qObj = parent_obj->qObject (); + Menu * + Menu::create (octave::interpreter& interp, + const graphics_object& go) + { + Object *parent_obj = parentObject (interp, go); - if (qObj) - return new Menu (oct_qobj, interp, go, new QAction (qObj), - parent_obj); - } - - return nullptr; -} + if (parent_obj) + { + QObject *qObj = parent_obj->qObject (); -Menu::Menu (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QAction *action, Object *xparent) - : Object (oct_qobj, interp, go, action), m_parent (nullptr), - m_separator (nullptr) -{ - uimenu::properties& up = properties (); + if (qObj) + return new Menu (interp, go, new QAction (qObj), + parent_obj); + } - action->setText (Utils::fromStdString (up.get_text ())); + return nullptr; + } - if (up.is_checked ()) - { - action->setCheckable (true); - action->setChecked (up.is_checked ()); - } + Menu::Menu (octave::interpreter& interp, + const graphics_object& go, QAction *action, Object *xparent) + : Object (interp, go, action), m_parent (nullptr), + m_separator (nullptr) + { + uimenu::properties& up = properties (); - action->setEnabled (up.is_enable ()); - action->setShortcut (accelSequence (up)); - action->setVisible (up.is_visible ()); + action->setText (Utils::fromStdString (up.get_text ())); - if (up.is_separator ()) - { - m_separator = new QAction (action); - m_separator->setSeparator (true); - m_separator->setVisible (up.is_visible ()); - } + if (up.is_checked ()) + { + action->setCheckable (true); + action->setChecked (up.is_checked ()); + } - MenuContainer *menuContainer = dynamic_cast (xparent); - - if (menuContainer) - m_parent = menuContainer->menu (); + action->setEnabled (up.is_enable ()); + action->setShortcut (accelSequence (up)); + action->setVisible (up.is_visible ()); - if (m_parent) - { - int pos = static_cast (up.get_position ()); + if (up.is_separator ()) + { + m_separator = new QAction (action); + m_separator->setSeparator (true); + m_separator->setVisible (up.is_visible ()); + } - if (pos <= 0) - { - if (m_separator) - m_parent->insertAction (nullptr, m_separator); - m_parent->insertAction (nullptr, action); + MenuContainer *menuContainer = dynamic_cast (xparent); - int count = 0; + if (menuContainer) + m_parent = menuContainer->menu (); - for (auto *a : m_parent->actions ()) - if (! a->isSeparator ()) - count++; + if (m_parent) + { + int pos = static_cast (up.get_position ()); - up.get_property ("position").set - (octave_value (static_cast (count)), true, false); - } - else - { + if (pos <= 0) + { + if (m_separator) + m_parent->insertAction (nullptr, m_separator); + m_parent->insertAction (nullptr, action); - int count = 0; - QAction *before = nullptr; + int count = 0; - for (auto *a : m_parent->actions ()) - { + for (auto *a : m_parent->actions ()) if (! a->isSeparator ()) - { - count++; - if (pos <= count) - { - before = a; - break; - } - } - } - - if (m_separator) - m_parent->insertAction (before, m_separator); - m_parent->insertAction (before, action); - - if (before) - updateSiblingPositions (); - else - up.get_property ("position").set - (octave_value (static_cast (count+1)), true, false); - } - } - - connect (action, &QAction::triggered, this, &Menu::actionTriggered); -} - -Menu::~Menu (void) -{ } - -void -Menu::update (int pId) -{ - uimenu::properties& up = properties (); - QAction *action = qWidget (); - - switch (pId) - { - case uimenu::properties::ID_TEXT: - action->setText (Utils::fromStdString (up.get_text ())); - break; + count++; - case uimenu::properties::ID_CHECKED: - if (up.is_checked ()) - { - action->setCheckable (true); - action->setChecked (up.is_checked ()); - } - else - { - action->setChecked (false); - action->setCheckable (false); - } - break; - - case uimenu::properties::ID_ENABLE: - action->setEnabled (up.is_enable ()); - break; - - case uimenu::properties::ID_ACCELERATOR: - if (! action->menu ()) - action->setShortcut (accelSequence (up)); - break; + up.get_property ("position").set + (octave_value (static_cast (count)), true, false); + } + else + { - case uimenu::properties::ID_SEPARATOR: - if (up.is_separator ()) - { - if (! m_separator) - { - m_separator = new QAction (action); - m_separator->setSeparator (true); - m_separator->setVisible (up.is_visible ()); - if (m_parent) - m_parent->insertAction (action, m_separator); - } - } - else - { - if (m_separator) - delete m_separator; - m_separator = nullptr; - } - break; - - case uimenu::properties::ID_VISIBLE: - action->setVisible (up.is_visible ()); - if (m_separator) - m_separator->setVisible (up.is_visible ()); - break; - - case uimenu::properties::ID_POSITION: - { - if (m_separator) - m_parent->removeAction (m_separator); - - m_parent->removeAction (action); - - int pos = static_cast (up.get_position ()); - QAction *before = nullptr; - - if (pos > 0) - { int count = 0; + QAction *before = nullptr; for (auto *a : m_parent->actions ()) { @@ -252,88 +145,193 @@ } } } - } - if (m_separator) - m_parent->insertAction (before, m_separator); - - m_parent->insertAction (before, action); + if (m_separator) + m_parent->insertAction (before, m_separator); + m_parent->insertAction (before, action); - updateSiblingPositions (); + if (before) + updateSiblingPositions (); + else + up.get_property ("position").set + (octave_value (static_cast (count+1)), true, false); + } } - break; - default: - Object::update (pId); - break; - } -} + connect (action, &QAction::triggered, this, &Menu::actionTriggered); + } + + Menu::~Menu (void) + { } -QWidget * -Menu::menu (void) -{ - QAction *action = qWidget (); - QMenu *action_menu = action->menu (); + void + Menu::update (int pId) + { + uimenu::properties& up = properties (); + QAction *action = qWidget (); + + switch (pId) + { + case uimenu::properties::ID_TEXT: + action->setText (Utils::fromStdString (up.get_text ())); + break; - if (! action_menu) - { - action_menu = new QMenu (action->parentWidget ()); - action->setMenu (action_menu); - action->setShortcut (QKeySequence ()); - connect (action_menu, &QMenu::aboutToShow, this, &Menu::actionHovered); - } + case uimenu::properties::ID_CHECKED: + if (up.is_checked ()) + { + action->setCheckable (true); + action->setChecked (up.is_checked ()); + } + else + { + action->setChecked (false); + action->setCheckable (false); + } + break; - return action_menu; -} + case uimenu::properties::ID_ENABLE: + action->setEnabled (up.is_enable ()); + break; -void -Menu::actionTriggered (void) -{ - QAction *action = qWidget (); + case uimenu::properties::ID_ACCELERATOR: + if (! action->menu ()) + action->setShortcut (accelSequence (up)); + break; - if (action->isCheckable ()) - action->setChecked (! action->isChecked ()); - emit gh_callback_event (m_handle, "menuselectedfcn"); -} - -void -Menu::actionHovered (void) -{ - emit gh_callback_event (m_handle, "menuselectedfcn"); -} + case uimenu::properties::ID_SEPARATOR: + if (up.is_separator ()) + { + if (! m_separator) + { + m_separator = new QAction (action); + m_separator->setSeparator (true); + m_separator->setVisible (up.is_visible ()); + if (m_parent) + m_parent->insertAction (action, m_separator); + } + } + else + { + if (m_separator) + delete m_separator; + m_separator = nullptr; + } + break; -void -Menu::updateSiblingPositions (void) -{ - if (m_parent) - { - double count = 1.0; + case uimenu::properties::ID_VISIBLE: + action->setVisible (up.is_visible ()); + if (m_separator) + m_separator->setVisible (up.is_visible ()); + break; - for (auto *a : m_parent->actions ()) + case uimenu::properties::ID_POSITION: { - if (! a->isSeparator ()) - { - Object *aObj = Object::fromQObject (a); + if (m_separator) + m_parent->removeAction (m_separator); + + m_parent->removeAction (action); - if (aObj) - { - graphics_object go = aObj->object (); + int pos = static_cast (up.get_position ()); + QAction *before = nullptr; + + if (pos > 0) + { + int count = 0; - // Probably overkill as a uimenu child can only be another - // uimenu object. - if (go.isa ("uimenu")) + for (auto *a : m_parent->actions ()) + { + if (! a->isSeparator ()) { - uimenu::properties& up = Utils::properties (go); - - up.get_property ("position").set - (octave_value (count), true, false); + count++; + if (pos <= count) + { + before = a; + break; + } } } + } - count++; - } + if (m_separator) + m_parent->insertAction (before, m_separator); + + m_parent->insertAction (before, action); + + updateSiblingPositions (); } - } -} + break; + + default: + Object::update (pId); + break; + } + } + + QWidget * + Menu::menu (void) + { + QAction *action = qWidget (); + QMenu *action_menu = action->menu (); + + if (! action_menu) + { + action_menu = new QMenu (action->parentWidget ()); + action->setMenu (action_menu); + action->setShortcut (QKeySequence ()); + connect (action_menu, &QMenu::aboutToShow, this, &Menu::actionHovered); + } + + return action_menu; + } + + void + Menu::actionTriggered (void) + { + QAction *action = qWidget (); + + if (action->isCheckable ()) + action->setChecked (! action->isChecked ()); + emit gh_callback_event (m_handle, "menuselectedfcn"); + } + + void + Menu::actionHovered (void) + { + emit gh_callback_event (m_handle, "menuselectedfcn"); + } + + void + Menu::updateSiblingPositions (void) + { + if (m_parent) + { + double count = 1.0; + + for (auto *a : m_parent->actions ()) + { + if (! a->isSeparator ()) + { + Object *aObj = Object::fromQObject (a); + + if (aObj) + { + graphics_object go = aObj->object (); + + // Probably overkill as a uimenu child can only be another + // uimenu object. + if (go.isa ("uimenu")) + { + uimenu::properties& up = Utils::properties (go); + + up.get_property ("position").set + (octave_value (count), true, false); + } + } + + count++; + } + } + } + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/Menu.h --- a/libgui/graphics/Menu.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/Menu.h Tue Dec 06 15:45:27 2022 -0500 @@ -35,40 +35,39 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class Menu : public Object, public MenuContainer -{ - Q_OBJECT + class Menu : public Object, public MenuContainer + { + Q_OBJECT -public: - Menu (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QAction *action, Object *parent); - ~Menu (void); + public: + Menu (octave::interpreter& interp, + const graphics_object& go, QAction *action, Object *parent); + ~Menu (void); - static Menu * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + static Menu * + create (octave::interpreter& interp, + const graphics_object& go); + + Container * innerContainer (void) { return nullptr; } - Container * innerContainer (void) { return nullptr; } + QWidget * menu (void); - QWidget * menu (void); - -protected: - void update (int pId); + protected: + void update (int pId); -private slots: - void actionTriggered (void); - void actionHovered (void); + private slots: + void actionTriggered (void); + void actionHovered (void); -private: - void updateSiblingPositions (void); + private: + void updateSiblingPositions (void); -private: - QWidget *m_parent; - QAction *m_separator; -}; + private: + QWidget *m_parent; + QAction *m_separator; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/Object.cc --- a/libgui/graphics/Object.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/Object.cc Tue Dec 06 15:45:27 2022 -0500 @@ -32,7 +32,6 @@ #include "Object.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" #include "qt-graphics-toolkit.h" #include "graphics.h" @@ -40,246 +39,246 @@ OCTAVE_BEGIN_NAMESPACE(octave) -Object::Object (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QObject *obj) -: QObject (), m_octave_qobj (oct_qobj), m_interpreter (interp), - m_go (go), m_handle (go.get_handle ()), m_qobject (nullptr) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + Object::Object (octave::interpreter& interp, + const graphics_object& go, QObject *obj) + : QObject (), m_interpreter (interp), m_go (go), + m_handle (go.get_handle ()), m_qobject (nullptr) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - octave::autolock guard (gh_mgr.graphics_lock ()); + octave::autolock guard (gh_mgr.graphics_lock ()); - if (! guard) - qCritical ("octave::Object::Object: " - "creating Object (h=%g) without a valid lock!!!", - m_handle.value ()); + if (! guard) + qCritical ("octave::Object::Object: " + "creating Object (h=%g) without a valid lock!!!", + m_handle.value ()); - init (obj); -} + init (obj); + } -void -Object::init (QObject *obj, bool) -{ - if (m_qobject) - qCritical ("octave::Object::init: " - "resetting QObject while in invalid state"); + void + Object::init (QObject *obj, bool) + { + if (m_qobject) + qCritical ("octave::Object::init: " + "resetting QObject while in invalid state"); - m_qobject = obj; + m_qobject = obj; - if (m_qobject) - { - m_qobject->setProperty ("octave::Object", - QVariant::fromValue (this)); - connect (m_qobject, &QObject::destroyed, - this, &Object::objectDestroyed); - } -} + if (m_qobject) + { + m_qobject->setProperty ("octave::Object", + QVariant::fromValue (this)); + connect (m_qobject, &QObject::destroyed, + this, &Object::objectDestroyed); + } + } -Object::~Object (void) -{ } + Object::~Object (void) + { } -graphics_object -Object::object (void) const -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + graphics_object + Object::object (void) const + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - octave::autolock guard (gh_mgr.graphics_lock (), false); + octave::autolock guard (gh_mgr.graphics_lock (), false); - if (! guard) - qCritical ("octave::Object::object: " - "accessing graphics object (h=%g) without a valid lock!!!", - m_handle.value ()); + if (! guard) + qCritical ("octave::Object::object: " + "accessing graphics object (h=%g) without a valid lock!!!", + m_handle.value ()); - return m_go; -} + return m_go; + } -void -Object::slotUpdate (int pId) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + void + Object::slotUpdate (int pId) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - octave::autolock guard (gh_mgr.graphics_lock ()); + octave::autolock guard (gh_mgr.graphics_lock ()); - switch (pId) - { + switch (pId) + { // Special case for objects being deleted, as it's very likely // that the graphics_object already has been destroyed when this // is executed (because of the async behavior). - case base_properties::ID_BEINGDELETED: - beingDeleted (); - break; + case base_properties::ID_BEINGDELETED: + beingDeleted (); + break; - default: - if (object ().valid_object ()) - update (pId); - break; - } -} + default: + if (object ().valid_object ()) + update (pId); + break; + } + } -void -Object::slotFinalize (void) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + void + Object::slotFinalize (void) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - octave::autolock guard (gh_mgr.graphics_lock ()); + octave::autolock guard (gh_mgr.graphics_lock ()); - finalize (); -} + finalize (); + } -void -Object::slotRedraw (void) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + void + Object::slotRedraw (void) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - octave::autolock guard (gh_mgr.graphics_lock ()); + octave::autolock guard (gh_mgr.graphics_lock ()); - if (object ().valid_object ()) - redraw (); -} + if (object ().valid_object ()) + redraw (); + } -void -Object::slotShow (void) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + void + Object::slotShow (void) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - octave::autolock guard (gh_mgr.graphics_lock ()); + octave::autolock guard (gh_mgr.graphics_lock ()); - if (object ().valid_object ()) - show (); -} + if (object ().valid_object ()) + show (); + } -void -Object::slotPrint (const QString& file_cmd, const QString& term) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + void + Object::slotPrint (const QString& file_cmd, const QString& term) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - octave::autolock guard (gh_mgr.graphics_lock ()); + octave::autolock guard (gh_mgr.graphics_lock ()); - if (object ().valid_object ()) - print (file_cmd, term); -} + if (object ().valid_object ()) + print (file_cmd, term); + } -void -Object::update (int /* pId */) -{ } + void + Object::update (int /* pId */) + { } -void -Object::finalize (void) -{ - if (m_qobject) - { - delete m_qobject; - m_qobject = nullptr; - } - deleteLater (); -} + void + Object::finalize (void) + { + if (m_qobject) + { + delete m_qobject; + m_qobject = nullptr; + } + deleteLater (); + } -void -Object::redraw (void) -{ } + void + Object::redraw (void) + { } + + void + Object::show (void) + { } -void -Object::show (void) -{ } + void + Object::print (const QString& /* file_cmd */, const QString& /* term */) + { } -void -Object::print (const QString& /* file_cmd */, const QString& /* term */) -{ } + void + Object::beingDeleted (void) + { } -void -Object::beingDeleted (void) -{ } - -void Object::objectDestroyed (QObject *obj) -{ - if (obj && obj == m_qobject) - m_qobject = nullptr; -} + void Object::objectDestroyed (QObject *obj) + { + if (obj && obj == m_qobject) + m_qobject = nullptr; + } -Object * -Object::parentObject (octave::interpreter& interp, const graphics_object& go) -{ - gh_manager& gh_mgr = interp.get_gh_manager (); + Object * + Object::parentObject (octave::interpreter& interp, const graphics_object& go) + { + gh_manager& gh_mgr = interp.get_gh_manager (); - octave::autolock guard (gh_mgr.graphics_lock ()); + octave::autolock guard (gh_mgr.graphics_lock ()); - Object *parent = qt_graphics_toolkit::toolkitObject - (gh_mgr.get_object (go.get_parent ())); + Object *parent = qt_graphics_toolkit::toolkitObject + (gh_mgr.get_object (go.get_parent ())); + + return parent; + } - return parent; -} + Object * + Object::fromQObject (QObject *obj) + { + QVariant v = obj->property ("octave::Object"); -Object * -Object::fromQObject (QObject *obj) -{ - QVariant v = obj->property ("octave::Object"); + if (v.isValid ()) + return reinterpret_cast (qvariant_cast (v)); + + return nullptr; + } - if (v.isValid ()) - return reinterpret_cast (qvariant_cast (v)); - - return nullptr; -} + void + Object::do_connections (const QObject *receiver, const QObject *emitter) + { + if (! emitter) + emitter = this; -void -Object::do_connections (const QObject *receiver, const QObject *emitter) -{ - if (! emitter) - emitter = this; + connect (emitter, + SIGNAL (interpreter_event (const octave::fcn_callback&)), + receiver, + SLOT (interpreter_event (const octave::fcn_callback&))); - connect (emitter, - SIGNAL (interpreter_event (const octave::fcn_callback&)), - receiver, - SLOT (interpreter_event (const octave::fcn_callback&))); - - connect (emitter, - SIGNAL (interpreter_event (const octave::meth_callback&)), - receiver, - SLOT (interpreter_event (const octave::meth_callback&))); + connect (emitter, + SIGNAL (interpreter_event (const octave::meth_callback&)), + receiver, + SLOT (interpreter_event (const octave::meth_callback&))); - connect (emitter, - SIGNAL (gh_callback_event (const graphics_handle&, - const std::string&)), - receiver, - SLOT (gh_callback_event (const graphics_handle&, - const std::string&))); + connect (emitter, + SIGNAL (gh_callback_event (const graphics_handle&, + const std::string&)), + receiver, + SLOT (gh_callback_event (const graphics_handle&, + const std::string&))); - connect (emitter, - SIGNAL (gh_callback_event (const graphics_handle&, + connect (emitter, + SIGNAL (gh_callback_event (const graphics_handle&, + const std::string&, + const octave_value&)), + receiver, + SLOT (gh_callback_event (const graphics_handle&, const std::string&, - const octave_value&)), - receiver, - SLOT (gh_callback_event (const graphics_handle&, - const std::string&, - const octave_value&))); + const octave_value&))); - connect (emitter, - SIGNAL (gh_set_event (const graphics_handle&, + connect (emitter, + SIGNAL (gh_set_event (const graphics_handle&, + const std::string&, + const octave_value&)), + receiver, + SLOT (gh_set_event (const graphics_handle&, const std::string&, - const octave_value&)), - receiver, - SLOT (gh_set_event (const graphics_handle&, - const std::string&, - const octave_value&))); + const octave_value&))); - connect (emitter, - SIGNAL (gh_set_event (const graphics_handle&, + connect (emitter, + SIGNAL (gh_set_event (const graphics_handle&, + const std::string&, + const octave_value&, bool)), + receiver, + SLOT (gh_set_event (const graphics_handle&, const std::string&, - const octave_value&, bool)), - receiver, - SLOT (gh_set_event (const graphics_handle&, - const std::string&, - const octave_value&, bool))); + const octave_value&, bool))); - connect (emitter, - SIGNAL (gh_set_event (const graphics_handle&, + connect (emitter, + SIGNAL (gh_set_event (const graphics_handle&, + const std::string&, + const octave_value&, + bool, bool)), + receiver, + SLOT (gh_set_event (const graphics_handle&, const std::string&, const octave_value&, - bool, bool)), - receiver, - SLOT (gh_set_event (const graphics_handle&, - const std::string&, - const octave_value&, - bool, bool))); -} + bool, bool))); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/Object.h --- a/libgui/graphics/Object.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/Object.h Tue Dec 06 15:45:27 2022 -0500 @@ -37,123 +37,121 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; - -class Container; -class ObjectProxy; - -class Object : public QObject -{ - Q_OBJECT + class interpreter; -public: - Object (octave::base_qobject& qobj, octave::interpreter& interp, - const graphics_object& go, QObject *obj = nullptr); - - virtual ~Object (void); + class Container; + class ObjectProxy; - base_properties& properties (void) - { return object ().get_properties (); } - - const base_properties& properties (void) const - { return object ().get_properties (); } - - template - typename T::properties& properties (void) + class Object : public QObject { - return dynamic_cast - (object ().get_properties ()); - } + Q_OBJECT + + public: + Object (octave::interpreter& interp, const graphics_object& go, + QObject *obj = nullptr); + + virtual ~Object (void); - template - const typename T::properties& properties (void) const - { - return dynamic_cast - (object ().get_properties ()); - } + base_properties& properties (void) + { return object ().get_properties (); } + + const base_properties& properties (void) const + { return object ().get_properties (); } - graphics_object object (void) const; - - virtual QObject * qObject (void) { return m_qobject; } + template + typename T::properties& properties (void) + { + return dynamic_cast + (object ().get_properties ()); + } - template - T * qWidget (void) { return qobject_cast(qObject ()); } + template + const typename T::properties& properties (void) const + { + return dynamic_cast + (object ().get_properties ()); + } - virtual Container * innerContainer (void) = 0; + graphics_object object (void) const; - static Object * fromQObject (QObject *obj); + virtual QObject * qObject (void) { return m_qobject; } + + template + T * qWidget (void) { return qobject_cast(qObject ()); } - virtual void do_connections (const QObject *receiver, - const QObject *emitter = nullptr); + virtual Container * innerContainer (void) = 0; -signals: + static Object * fromQObject (QObject *obj); + + virtual void do_connections (const QObject *receiver, + const QObject *emitter = nullptr); - void interpreter_event (const octave::fcn_callback& fcn); - void interpreter_event (const octave::meth_callback& meth); + signals: - void gh_callback_event (const graphics_handle& h, const std::string& name); + void interpreter_event (const octave::fcn_callback& fcn); + void interpreter_event (const octave::meth_callback& meth); + + void gh_callback_event (const graphics_handle& h, const std::string& name); - void gh_callback_event (const graphics_handle& h, const std::string& name, - const octave_value& data); + void gh_callback_event (const graphics_handle& h, const std::string& name, + const octave_value& data); - void gh_set_event (const graphics_handle& h, const std::string& name, - const octave_value& value); + void gh_set_event (const graphics_handle& h, const std::string& name, + const octave_value& value); - void gh_set_event (const graphics_handle& h, const std::string& name, - const octave_value& value, bool notify_toolkit); + void gh_set_event (const graphics_handle& h, const std::string& name, + const octave_value& value, bool notify_toolkit); - void gh_set_event (const graphics_handle& h, const std::string& name, - const octave_value& value, bool notify_toolkit, - bool redraw_figure); + void gh_set_event (const graphics_handle& h, const std::string& name, + const octave_value& value, bool notify_toolkit, + bool redraw_figure); -public slots: - void slotUpdate (int pId); - void slotFinalize (void); - void slotRedraw (void); - void slotShow (void); - void slotPrint (const QString& file_cmd, const QString& term); + public slots: + void slotUpdate (int pId); + void slotFinalize (void); + void slotRedraw (void); + void slotShow (void); + void slotPrint (const QString& file_cmd, const QString& term); - void objectDestroyed (QObject *obj = nullptr); + void objectDestroyed (QObject *obj = nullptr); -protected: - static Object * - parentObject (octave::interpreter& interp, const graphics_object& go); + protected: + static Object * + parentObject (octave::interpreter& interp, const graphics_object& go); - void init (QObject *obj, bool callBase = false); + void init (QObject *obj, bool callBase = false); - virtual void update (int pId); - virtual void finalize (void); - virtual void redraw (void); - virtual void show (void); - virtual void print (const QString& file_cmd, const QString& term); + virtual void update (int pId); + virtual void finalize (void); + virtual void redraw (void); + virtual void show (void); + virtual void print (const QString& file_cmd, const QString& term); - virtual void beingDeleted (void); + virtual void beingDeleted (void); -protected: + protected: - octave::base_qobject& m_octave_qobj; - octave::interpreter& m_interpreter; + octave::interpreter& m_interpreter; - // Store the graphics object directly so that it will exist when - // we need it. Previously, it was possible for the graphics - // toolkit to get a handle to a figure, then have the interpreter - // thread delete the corresponding object before the graphics - // toolkit (GUI) thread had a chance to display it. It should be OK - // to store this object and use it in both threads (graphics_object - // uses a std::shared_ptr) provided that we protect access with - // mutex locks. - graphics_object m_go; + // Store the graphics object directly so that it will exist when + // we need it. Previously, it was possible for the graphics + // toolkit to get a handle to a figure, then have the interpreter + // thread delete the corresponding object before the graphics + // toolkit (GUI) thread had a chance to display it. It should be OK + // to store this object and use it in both threads (graphics_object + // uses a std::shared_ptr) provided that we protect access with + // mutex locks. + graphics_object m_go; - // Handle to the graphics object. This may be redundant now. - // Also, the whole ObjectProxy thing may not need to store a - // pointer now? Maybe we can just have a lookup table from figure - // handle to Object? What does the FLTK toolkit do? Why does - // this seem to be so complicated? - graphics_handle m_handle; + // Handle to the graphics object. This may be redundant now. + // Also, the whole ObjectProxy thing may not need to store a + // pointer now? Maybe we can just have a lookup table from figure + // handle to Object? What does the FLTK toolkit do? Why does + // this seem to be so complicated? + graphics_handle m_handle; - QObject *m_qobject; -}; + QObject *m_qobject; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/Panel.cc --- a/libgui/graphics/Panel.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/Panel.cc Tue Dec 06 15:45:27 2022 -0500 @@ -39,391 +39,389 @@ #include "Panel.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - #include "graphics.h" #include "interpreter.h" OCTAVE_BEGIN_NAMESPACE(octave) -static int -frameStyleFromProperties (const uipanel::properties& pp) -{ - if (pp.bordertype_is ("none")) - return QFrame::NoFrame; - else if (pp.bordertype_is ("etchedin")) - return (QFrame::Box | QFrame::Sunken); - else if (pp.bordertype_is ("etchedout")) - return (QFrame::Box | QFrame::Raised); - else if (pp.bordertype_is ("beveledin")) - return (QFrame::Panel | QFrame::Sunken); - else if (pp.bordertype_is ("beveledout")) - return (QFrame::Panel | QFrame::Raised); - else - return (QFrame::Panel | QFrame::Plain); -} + static int + frameStyleFromProperties (const uipanel::properties& pp) + { + if (pp.bordertype_is ("none")) + return QFrame::NoFrame; + else if (pp.bordertype_is ("etchedin")) + return (QFrame::Box | QFrame::Sunken); + else if (pp.bordertype_is ("etchedout")) + return (QFrame::Box | QFrame::Raised); + else if (pp.bordertype_is ("beveledin")) + return (QFrame::Panel | QFrame::Sunken); + else if (pp.bordertype_is ("beveledout")) + return (QFrame::Panel | QFrame::Raised); + else + return (QFrame::Panel | QFrame::Plain); + } -static void -setupPalette (const uipanel::properties& pp, QPalette& p) -{ - p.setColor (QPalette::Window, - Utils::fromRgb (pp.get_backgroundcolor_rgb ())); - p.setColor (QPalette::WindowText, - Utils::fromRgb (pp.get_foregroundcolor_rgb ())); - p.setColor (QPalette::Light, - Utils::fromRgb (pp.get_highlightcolor_rgb ())); - p.setColor (QPalette::Dark, - Utils::fromRgb (pp.get_shadowcolor_rgb ())); -} + static void + setupPalette (const uipanel::properties& pp, QPalette& p) + { + p.setColor (QPalette::Window, + Utils::fromRgb (pp.get_backgroundcolor_rgb ())); + p.setColor (QPalette::WindowText, + Utils::fromRgb (pp.get_foregroundcolor_rgb ())); + p.setColor (QPalette::Light, + Utils::fromRgb (pp.get_highlightcolor_rgb ())); + p.setColor (QPalette::Dark, + Utils::fromRgb (pp.get_shadowcolor_rgb ())); + } -static int -borderWidthFromProperties (const uipanel::properties& pp) -{ - int bw = 0; + static int + borderWidthFromProperties (const uipanel::properties& pp) + { + int bw = 0; - if (! pp.bordertype_is ("none")) - { - bw = octave::math::round (pp.get_borderwidth ()); - if (pp.bordertype_is ("etchedin") || pp.bordertype_is ("etchedout")) - bw *= 2; - } + if (! pp.bordertype_is ("none")) + { + bw = octave::math::round (pp.get_borderwidth ()); + if (pp.bordertype_is ("etchedin") || pp.bordertype_is ("etchedout")) + bw *= 2; + } + + return bw; + } - return bw; -} + Panel * + Panel::create (octave::interpreter& interp, + const graphics_object& go) + { + Object *parent = parentObject (interp, go); -Panel * -Panel::create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go) -{ - Object *parent = parentObject (interp, go); + if (parent) + { + Container *container = parent->innerContainer (); - if (parent) - { - Container *container = parent->innerContainer (); + if (container) + return new Panel (interp, go, new QFrame (container)); + } + + return nullptr; + } - if (container) - return new Panel (oct_qobj, interp, go, new QFrame (container)); - } - - return nullptr; -} + Panel::Panel (octave::interpreter& interp, + const graphics_object& go, QFrame *frame) + : Object (interp, go, frame), m_container (nullptr), + m_title (nullptr), m_blockUpdates (false), + m_previous_bbox (Matrix (1, 4, 0)) + { + uipanel::properties& pp = properties (); -Panel::Panel (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QFrame *frame) - : Object (oct_qobj, interp, go, frame), m_container (nullptr), - m_title (nullptr), m_blockUpdates (false), - m_previous_bbox (Matrix (1, 4, 0)) -{ - uipanel::properties& pp = properties (); + frame->setObjectName ("UIPanel"); + frame->setAutoFillBackground (true); + Matrix bb = pp.get_boundingbox (false); + frame->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)), + octave::math::round (bb(2)), octave::math::round (bb(3))); + frame->setFrameStyle (frameStyleFromProperties (pp)); + frame->setLineWidth (octave::math::round (pp.get_borderwidth ())); + QPalette pal = frame->palette (); + setupPalette (pp, pal); + frame->setPalette (pal); - frame->setObjectName ("UIPanel"); - frame->setAutoFillBackground (true); - Matrix bb = pp.get_boundingbox (false); - frame->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)), - octave::math::round (bb(2)), octave::math::round (bb(3))); - frame->setFrameStyle (frameStyleFromProperties (pp)); - frame->setLineWidth (octave::math::round (pp.get_borderwidth ())); - QPalette pal = frame->palette (); - setupPalette (pp, pal); - frame->setPalette (pal); + m_container = new Container (frame, interp); + m_container->canvas (m_handle); + + connect (m_container, SIGNAL (interpeter_event (const fcn_callback&)), + this, SIGNAL (interpeter_event (const fcn_callback&))); - m_container = new Container (frame, oct_qobj, interp); - m_container->canvas (m_handle); + connect (m_container, SIGNAL (interpeter_event (const meth_callback&)), + this, SIGNAL (interpeter_event (const meth_callback&))); + + if (frame->hasMouseTracking ()) + { + for (auto *w : frame->findChildren ()) + w->setMouseTracking (true); + } - connect (m_container, SIGNAL (interpeter_event (const fcn_callback&)), - this, SIGNAL (interpeter_event (const fcn_callback&))); - - connect (m_container, SIGNAL (interpeter_event (const meth_callback&)), - this, SIGNAL (interpeter_event (const meth_callback&))); + QString title = Utils::fromStdString (pp.get_title ()); + if (! title.isEmpty ()) + { + m_title = new QLabel (title, frame); + m_title->setAutoFillBackground (true); + m_title->setContentsMargins (4, 0, 4, 0); + m_title->setPalette (pal); + m_title->setFont (Utils::computeFont (pp, bb(3))); + } - if (frame->hasMouseTracking ()) - { - for (auto *w : frame->findChildren ()) - w->setMouseTracking (true); - } + frame->installEventFilter (this); + m_container->installEventFilter (this); + + graphics_object fig (go.get_ancestor ("figure")); + if (! fig.get ("keypressfcn").isempty ()) + m_container->canvas (m_handle)->addEventMask (Canvas::KeyPress); + + if (! fig.get ("keyreleasefcn").isempty ()) + m_container->canvas (m_handle)->addEventMask (Canvas::KeyRelease); - QString title = Utils::fromStdString (pp.get_title ()); - if (! title.isEmpty ()) - { - m_title = new QLabel (title, frame); - m_title->setAutoFillBackground (true); - m_title->setContentsMargins (4, 0, 4, 0); - m_title->setPalette (pal); - m_title->setFont (Utils::computeFont (pp, bb(3))); - } + if (pp.is_visible ()) + QTimer::singleShot (0, frame, &QFrame::show); + else + frame->hide (); + } - frame->installEventFilter (this); - m_container->installEventFilter (this); + Panel::~Panel (void) + { } - graphics_object fig (go.get_ancestor ("figure")); - if (! fig.get ("keypressfcn").isempty ()) - m_container->canvas (m_handle)->addEventMask (Canvas::KeyPress); - - if (! fig.get ("keyreleasefcn").isempty ()) - m_container->canvas (m_handle)->addEventMask (Canvas::KeyRelease); + bool + Panel::eventFilter (QObject *watched, QEvent *xevent) + { + if (! m_blockUpdates) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - if (pp.is_visible ()) - QTimer::singleShot (0, frame, &QFrame::show); - else - frame->hide (); -} + if (watched == qObject ()) + { + switch (xevent->type ()) + { + case QEvent::Resize: + { + octave::autolock guard (gh_mgr.graphics_lock ()); -Panel::~Panel (void) -{ } + graphics_object go = object (); -bool -Panel::eventFilter (QObject *watched, QEvent *xevent) -{ - if (! m_blockUpdates) - { - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + if (go.valid_object ()) + { + if (m_title) + { + const uipanel::properties& pp = + Utils::properties (go); + + if (pp.fontunits_is ("normalized")) + { + QFrame *frame = qWidget (); - if (watched == qObject ()) - { - switch (xevent->type ()) - { - case QEvent::Resize: - { - octave::autolock guard (gh_mgr.graphics_lock ()); + m_title->setFont (Utils::computeFont + (pp, frame->height ())); + m_title->resize (m_title->sizeHint ()); + } + } + updateLayout (); + } + } + break; - graphics_object go = object (); + case QEvent::MouseButtonPress: + { + QMouseEvent *m = dynamic_cast (xevent); - if (go.valid_object ()) - { - if (m_title) - { - const uipanel::properties& pp = - Utils::properties (go); + if (m->button () == Qt::RightButton) + { + octave::autolock guard (gh_mgr.graphics_lock ()); - if (pp.fontunits_is ("normalized")) - { - QFrame *frame = qWidget (); + graphics_object go = object (); - m_title->setFont (Utils::computeFont - (pp, frame->height ())); - m_title->resize (m_title->sizeHint ()); - } - } - updateLayout (); - } + if (go.valid_object ()) + ContextMenu::executeAt (m_interpreter, + go.get_properties (), + m->globalPos ()); + } + } + break; + + default: + break; } - break; - - case QEvent::MouseButtonPress: + } + else if (watched == m_container) + { + switch (xevent->type ()) { - QMouseEvent *m = dynamic_cast (xevent); - - if (m->button () == Qt::RightButton) + case QEvent::Resize: + if (qWidget ()->isVisible ()) { octave::autolock guard (gh_mgr.graphics_lock ()); graphics_object go = object (); if (go.valid_object ()) - ContextMenu::executeAt (m_interpreter, - go.get_properties (), - m->globalPos ()); + go.get_properties ().update_boundingbox (); } + break; + + default: + break; } - break; + } + } + + return false; + } - default: - break; - } - } - else if (watched == m_container) + void + Panel::update (int pId) + { + uipanel::properties& pp = properties (); + QFrame *frame = qWidget (); + + m_blockUpdates = true; + + switch (pId) + { + case uipanel::properties::ID_POSITION: { - switch (xevent->type ()) + Matrix bb = pp.get_boundingbox (false); + if (m_previous_bbox(0) != bb(0) || m_previous_bbox(1) != bb(1) + || m_previous_bbox(2) != bb(2) || m_previous_bbox(3) != bb(3)) { - case QEvent::Resize: - if (qWidget ()->isVisible ()) - { - octave::autolock guard (gh_mgr.graphics_lock ()); + frame->setGeometry (octave::math::round (bb(0)), + octave::math::round (bb(1)), + octave::math::round (bb(2)), + octave::math::round (bb(3))); + updateLayout (); + } + m_previous_bbox = bb; + } + break; - graphics_object go = object (); + case uipanel::properties::ID_BORDERWIDTH: + frame->setLineWidth (octave::math::round (pp.get_borderwidth ())); + updateLayout (); + break; - if (go.valid_object ()) - go.get_properties ().update_boundingbox (); - } - break; + case uipanel::properties::ID_BACKGROUNDCOLOR: + case uipanel::properties::ID_FOREGROUNDCOLOR: + case uipanel::properties::ID_HIGHLIGHTCOLOR: + case uipanel::properties::ID_SHADOWCOLOR: + { + QPalette pal = frame->palette (); - default: - break; - } + setupPalette (pp, pal); + frame->setPalette (pal); + if (m_title) + m_title->setPalette (pal); } - } + break; + + case uipanel::properties::ID_TITLE: + { + QString title = Utils::fromStdString (pp.get_title ()); - return false; -} - -void -Panel::update (int pId) -{ - uipanel::properties& pp = properties (); - QFrame *frame = qWidget (); + if (title.isEmpty ()) + { + if (m_title) + delete m_title; + m_title = nullptr; + } + else + { + if (! m_title) + { + QPalette pal = frame->palette (); - m_blockUpdates = true; + m_title = new QLabel (title, frame); + m_title->setAutoFillBackground (true); + m_title->setContentsMargins (4, 0, 4, 0); + m_title->setPalette (pal); + m_title->setFont (Utils::computeFont (pp)); + m_title->show (); + } + else + { + m_title->setText (title); + m_title->resize (m_title->sizeHint ()); + } + } + updateLayout (); + } + break; - switch (pId) - { - case uipanel::properties::ID_POSITION: - { - Matrix bb = pp.get_boundingbox (false); - if (m_previous_bbox(0) != bb(0) || m_previous_bbox(1) != bb(1) - || m_previous_bbox(2) != bb(2) || m_previous_bbox(3) != bb(3)) + case uipanel::properties::ID_TITLEPOSITION: + updateLayout (); + break; + + case uipanel::properties::ID_BORDERTYPE: + frame->setFrameStyle (frameStyleFromProperties (pp)); + updateLayout (); + break; + + case uipanel::properties::ID_FONTNAME: + case uipanel::properties::ID_FONTSIZE: + case uipanel::properties::ID_FONTWEIGHT: + case uipanel::properties::ID_FONTANGLE: + if (m_title) { - frame->setGeometry (octave::math::round (bb(0)), - octave::math::round (bb(1)), - octave::math::round (bb(2)), - octave::math::round (bb(3))); + m_title->setFont (Utils::computeFont (pp)); + m_title->resize (m_title->sizeHint ()); updateLayout (); } - m_previous_bbox = bb; - } - break; + break; - case uipanel::properties::ID_BORDERWIDTH: - frame->setLineWidth (octave::math::round (pp.get_borderwidth ())); - updateLayout (); - break; + case uipanel::properties::ID_VISIBLE: + frame->setVisible (pp.is_visible ()); + updateLayout (); + break; - case uipanel::properties::ID_BACKGROUNDCOLOR: - case uipanel::properties::ID_FOREGROUNDCOLOR: - case uipanel::properties::ID_HIGHLIGHTCOLOR: - case uipanel::properties::ID_SHADOWCOLOR: - { - QPalette pal = frame->palette (); + default: + break; + } - setupPalette (pp, pal); - frame->setPalette (pal); - if (m_title) - m_title->setPalette (pal); - } - break; - - case uipanel::properties::ID_TITLE: - { - QString title = Utils::fromStdString (pp.get_title ()); + m_blockUpdates = false; + } - if (title.isEmpty ()) - { - if (m_title) - delete m_title; - m_title = nullptr; - } - else - { - if (! m_title) - { - QPalette pal = frame->palette (); + void + Panel::redraw (void) + { + update (uipanel::properties::ID_POSITION); + + Canvas *canvas = m_container->canvas (m_handle); - m_title = new QLabel (title, frame); - m_title->setAutoFillBackground (true); - m_title->setContentsMargins (4, 0, 4, 0); - m_title->setPalette (pal); - m_title->setFont (Utils::computeFont (pp)); - m_title->show (); - } - else - { - m_title->setText (title); - m_title->resize (m_title->sizeHint ()); - } - } - updateLayout (); - } - break; + if (canvas) + canvas->redraw (); + } - case uipanel::properties::ID_TITLEPOSITION: - updateLayout (); - break; + void + Panel::updateLayout (void) + { + uipanel::properties& pp = properties (); + QFrame *frame = qWidget (); - case uipanel::properties::ID_BORDERTYPE: - frame->setFrameStyle (frameStyleFromProperties (pp)); - updateLayout (); - break; + Matrix bb = pp.get_boundingbox (true); + int bw = borderWidthFromProperties (pp); - case uipanel::properties::ID_FONTNAME: - case uipanel::properties::ID_FONTSIZE: - case uipanel::properties::ID_FONTWEIGHT: - case uipanel::properties::ID_FONTANGLE: - if (m_title) - { - m_title->setFont (Utils::computeFont (pp)); - m_title->resize (m_title->sizeHint ()); - updateLayout (); - } - break; - - case uipanel::properties::ID_VISIBLE: - frame->setVisible (pp.is_visible ()); - updateLayout (); - break; + frame->setFrameRect (QRect (octave::math::round (bb(0)) - bw, + octave::math::round (bb(1)) - bw, + octave::math::round (bb(2)) + 2*bw, octave::math::round (bb(3)) + 2*bw)); + m_container->setGeometry (octave::math::round (bb(0)), + octave::math::round (bb(1)), + octave::math::round (bb(2)), octave::math::round (bb(3))); - default: - break; - } - - m_blockUpdates = false; -} - -void -Panel::redraw (void) -{ - update (uipanel::properties::ID_POSITION); + if (m_blockUpdates) + pp.update_boundingbox (); - Canvas *canvas = m_container->canvas (m_handle); - - if (canvas) - canvas->redraw (); -} - -void -Panel::updateLayout (void) -{ - uipanel::properties& pp = properties (); - QFrame *frame = qWidget (); + if (m_title) + { + QSize sz = m_title->sizeHint (); + int offset = 5; - Matrix bb = pp.get_boundingbox (true); - int bw = borderWidthFromProperties (pp); - - frame->setFrameRect (QRect (octave::math::round (bb(0)) - bw, - octave::math::round (bb(1)) - bw, - octave::math::round (bb(2)) + 2*bw, octave::math::round (bb(3)) + 2*bw)); - m_container->setGeometry (octave::math::round (bb(0)), - octave::math::round (bb(1)), - octave::math::round (bb(2)), octave::math::round (bb(3))); - - if (m_blockUpdates) - pp.update_boundingbox (); - - if (m_title) - { - QSize sz = m_title->sizeHint (); - int offset = 5; + if (pp.titleposition_is ("lefttop")) + m_title->move (bw+offset, 0); + else if (pp.titleposition_is ("righttop")) + m_title->move (frame->width () - bw - offset - sz.width (), 0); + else if (pp.titleposition_is ("leftbottom")) + m_title->move (bw+offset, frame->height () - sz.height ()); + else if (pp.titleposition_is ("rightbottom")) + m_title->move (frame->width () - bw - offset - sz.width (), + frame->height () - sz.height ()); + else if (pp.titleposition_is ("centertop")) + m_title->move (frame->width () / 2 - sz.width () / 2, 0); + else if (pp.titleposition_is ("centerbottom")) + m_title->move (frame->width () / 2 - sz.width () / 2, + frame->height () - sz.height ()); + } + } - if (pp.titleposition_is ("lefttop")) - m_title->move (bw+offset, 0); - else if (pp.titleposition_is ("righttop")) - m_title->move (frame->width () - bw - offset - sz.width (), 0); - else if (pp.titleposition_is ("leftbottom")) - m_title->move (bw+offset, frame->height () - sz.height ()); - else if (pp.titleposition_is ("rightbottom")) - m_title->move (frame->width () - bw - offset - sz.width (), - frame->height () - sz.height ()); - else if (pp.titleposition_is ("centertop")) - m_title->move (frame->width () / 2 - sz.width () / 2, 0); - else if (pp.titleposition_is ("centerbottom")) - m_title->move (frame->width () / 2 - sz.width () / 2, - frame->height () - sz.height ()); - } -} - -void -Panel::do_connections (const QObject *receiver, const QObject * /* emitter */) -{ - Object::do_connections (receiver); - Object::do_connections (receiver, m_container->canvas (m_handle)); -} + void + Panel::do_connections (const QObject *receiver, const QObject * /* emitter */) + { + Object::do_connections (receiver); + Object::do_connections (receiver, m_container->canvas (m_handle)); + } OCTAVE_END_NAMESPACE(octave); diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/Panel.h --- a/libgui/graphics/Panel.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/Panel.h Tue Dec 06 15:45:27 2022 -0500 @@ -33,42 +33,41 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class Container; + class Container; -class Panel : public Object -{ -public: - Panel (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QFrame *frame); - ~Panel (void); + class Panel : public Object + { + public: + Panel (octave::interpreter& interp, + const graphics_object& go, QFrame *frame); + ~Panel (void); - Container * innerContainer (void) { return m_container; } + Container * innerContainer (void) { return m_container; } - bool eventFilter (QObject *watched, QEvent *event); + bool eventFilter (QObject *watched, QEvent *event); - static Panel * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + static Panel * + create (octave::interpreter& interp, + const graphics_object& go); - void do_connections (const QObject *receiver, - const QObject *emitter = nullptr); + void do_connections (const QObject *receiver, + const QObject *emitter = nullptr); -protected: - void update (int pId); - void redraw (void); + protected: + void update (int pId); + void redraw (void); -private: - void updateLayout (void); + private: + void updateLayout (void); -private: - Container *m_container; - QLabel *m_title; - bool m_blockUpdates; - Matrix m_previous_bbox; -}; + private: + Container *m_container; + QLabel *m_title; + bool m_blockUpdates; + Matrix m_previous_bbox; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/PopupMenuControl.cc --- a/libgui/graphics/PopupMenuControl.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/PopupMenuControl.cc Tue Dec 06 15:45:27 2022 -0500 @@ -33,121 +33,118 @@ #include "PopupMenuControl.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" #include "octave-qtutils.h" OCTAVE_BEGIN_NAMESPACE(octave) -PopupMenuControl * -PopupMenuControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go) -{ - Object *parent = parentObject (interp, go); + PopupMenuControl * + PopupMenuControl::create (octave::interpreter& interp, + const graphics_object& go) + { + Object *parent = parentObject (interp, go); - if (parent) - { - Container *container = parent->innerContainer (); + if (parent) + { + Container *container = parent->innerContainer (); - if (container) - return new PopupMenuControl (oct_qobj, interp, go, - new QComboBox (container)); - } + if (container) + return new PopupMenuControl (interp, go, + new QComboBox (container)); + } - return nullptr; -} + return nullptr; + } -PopupMenuControl::PopupMenuControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, - QComboBox *box) - : BaseControl (oct_qobj, interp, go, box), m_blockUpdate (false) -{ - uicontrol::properties& up = properties (); + PopupMenuControl::PopupMenuControl (octave::interpreter& interp, + const graphics_object& go, + QComboBox *box) + : BaseControl (interp, go, box), m_blockUpdate (false) + { + uicontrol::properties& up = properties (); - box->addItems (Utils::fromStdString (up.get_string_string ()).split ('|')); + box->addItems (Utils::fromStdString (up.get_string_string ()).split ('|')); + + update (uicontrol::properties::ID_VALUE); - update (uicontrol::properties::ID_VALUE); + connect (box, QOverload::of (&QComboBox::activated), + this, &PopupMenuControl::currentIndexChanged); + } - connect (box, QOverload::of (&QComboBox::activated), - this, &PopupMenuControl::currentIndexChanged); -} - -PopupMenuControl::~PopupMenuControl (void) -{ } + PopupMenuControl::~PopupMenuControl (void) + { } -void PopupMenuControl::update (int pId) -{ - uicontrol::properties& up = properties (); - QComboBox *box = qWidget (); + void PopupMenuControl::update (int pId) + { + uicontrol::properties& up = properties (); + QComboBox *box = qWidget (); - switch (pId) - { - case uicontrol::properties::ID_STRING: - m_blockUpdate = true; + switch (pId) { - int oldCurrent = box->currentIndex (); + case uicontrol::properties::ID_STRING: + m_blockUpdate = true; + { + int oldCurrent = box->currentIndex (); - box->clear (); - box->addItems (Utils::fromStdString - (up.get_string_string ()).split ('|')); - if (box->count () > 0 - && oldCurrent >= 0 - && oldCurrent < box->count ()) - { - box->setCurrentIndex (oldCurrent); - } - else - { - emit gh_set_event (m_handle, "value", - octave_value (box->count () > 0 ? 1.0 : 0.0), - false); - } - } - m_blockUpdate = false; - break; + box->clear (); + box->addItems (Utils::fromStdString + (up.get_string_string ()).split ('|')); + if (box->count () > 0 + && oldCurrent >= 0 + && oldCurrent < box->count ()) + { + box->setCurrentIndex (oldCurrent); + } + else + { + emit gh_set_event (m_handle, "value", + octave_value (box->count () > 0 ? 1.0 : 0.0), + false); + } + } + m_blockUpdate = false; + break; - case uicontrol::properties::ID_VALUE: - m_blockUpdate = true; - { - Matrix value = up.get_value ().matrix_value (); + case uicontrol::properties::ID_VALUE: + m_blockUpdate = true; + { + Matrix value = up.get_value ().matrix_value (); - if (value.numel () > 0) - { - if (value(0) != static_cast (value(0))) - warning ("popupmenu value should be integer"); - else - { - int newIndex = int (value(0)) - 1; + if (value.numel () > 0) + { + if (value(0) != static_cast (value(0))) + warning ("popupmenu value should be integer"); + else + { + int newIndex = int (value(0)) - 1; - if (newIndex >= 0 && newIndex < box->count ()) - { - if (newIndex != box->currentIndex ()) - box->setCurrentIndex (newIndex); - } - else - warning ("popupmenu value not within valid display range"); - } - } + if (newIndex >= 0 && newIndex < box->count ()) + { + if (newIndex != box->currentIndex ()) + box->setCurrentIndex (newIndex); + } + else + warning ("popupmenu value not within valid display range"); + } + } + } + m_blockUpdate = false; + break; + + default: + BaseControl::update (pId); + break; } - m_blockUpdate = false; - break; - - default: - BaseControl::update (pId); - break; - } -} + } -void -PopupMenuControl::currentIndexChanged (int index) -{ - if (! m_blockUpdate) - { - emit gh_set_event (m_handle, "value", octave_value (double (index + 1)), - false); - emit gh_callback_event (m_handle, "callback"); - } -} + void + PopupMenuControl::currentIndexChanged (int index) + { + if (! m_blockUpdate) + { + emit gh_set_event (m_handle, "value", octave_value (double (index + 1)), + false); + emit gh_callback_event (m_handle, "callback"); + } + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/PopupMenuControl.h --- a/libgui/graphics/PopupMenuControl.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/PopupMenuControl.h Tue Dec 06 15:45:27 2022 -0500 @@ -32,32 +32,30 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class PopupMenuControl : public BaseControl -{ - Q_OBJECT + class PopupMenuControl : public BaseControl + { + Q_OBJECT -public: - PopupMenuControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go, - QComboBox *box); - ~PopupMenuControl (void); + public: + PopupMenuControl (octave::interpreter& interp, const graphics_object& go, + QComboBox *box); + ~PopupMenuControl (void); - static PopupMenuControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + static PopupMenuControl * + create (octave::interpreter& interp, + const graphics_object& go); -protected: - void update (int pId); + protected: + void update (int pId); -private slots: - void currentIndexChanged (int index); + private slots: + void currentIndexChanged (int index); -private: - bool m_blockUpdate; -}; + private: + bool m_blockUpdate; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/PushButtonControl.cc --- a/libgui/graphics/PushButtonControl.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/PushButtonControl.cc Tue Dec 06 15:45:27 2022 -0500 @@ -34,71 +34,67 @@ #include "Container.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - OCTAVE_BEGIN_NAMESPACE(octave) -PushButtonControl * -PushButtonControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go) -{ - Object *parent = parentObject (interp, go); + PushButtonControl * + PushButtonControl::create (octave::interpreter& interp, + const graphics_object& go) + { + Object *parent = parentObject (interp, go); - if (parent) - { - Container *container = parent->innerContainer (); + if (parent) + { + Container *container = parent->innerContainer (); - if (container) - return new PushButtonControl (oct_qobj, interp, go, - new QPushButton (container)); - } - - return nullptr; -} + if (container) + return new PushButtonControl (interp, go, + new QPushButton (container)); + } -PushButtonControl::PushButtonControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, - QPushButton *btn) - : ButtonControl (oct_qobj, interp, go, btn) -{ - uicontrol::properties& up = properties (); + return nullptr; + } + + PushButtonControl::PushButtonControl (octave::interpreter& interp, + const graphics_object& go, + QPushButton *btn) + : ButtonControl (interp, go, btn) + { + uicontrol::properties& up = properties (); - btn->setAutoFillBackground (true); - octave_value cdat = up.get_cdata (); - QImage img = Utils::makeImageFromCData (cdat, - cdat.columns (), cdat.rows ()); - btn->setIcon (QIcon (QPixmap::fromImage (img))); - btn->setIconSize (QSize (cdat.columns (), cdat.rows ())); -} + btn->setAutoFillBackground (true); + octave_value cdat = up.get_cdata (); + QImage img = Utils::makeImageFromCData (cdat, + cdat.columns (), cdat.rows ()); + btn->setIcon (QIcon (QPixmap::fromImage (img))); + btn->setIconSize (QSize (cdat.columns (), cdat.rows ())); + } -PushButtonControl::~PushButtonControl (void) -{ } + PushButtonControl::~PushButtonControl (void) + { } -void -PushButtonControl::update (int pId) -{ - uicontrol::properties& up = properties (); - QPushButton *btn = qWidget (); + void + PushButtonControl::update (int pId) + { + uicontrol::properties& up = properties (); + QPushButton *btn = qWidget (); - switch (pId) - { - case uicontrol::properties::ID_CDATA: + switch (pId) { - octave_value cdat = up.get_cdata (); - QImage img = Utils::makeImageFromCData (cdat, - cdat.rows (), - cdat.columns ()); - btn->setIcon (QIcon (QPixmap::fromImage (img))); - btn->setIconSize (QSize (cdat.columns (), cdat.rows ())); + case uicontrol::properties::ID_CDATA: + { + octave_value cdat = up.get_cdata (); + QImage img = Utils::makeImageFromCData (cdat, + cdat.rows (), + cdat.columns ()); + btn->setIcon (QIcon (QPixmap::fromImage (img))); + btn->setIconSize (QSize (cdat.columns (), cdat.rows ())); + } + break; + + default: + ButtonControl::update (pId); + break; } - break; - - default: - ButtonControl::update (pId); - break; - } -} + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/PushButtonControl.h --- a/libgui/graphics/PushButtonControl.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/PushButtonControl.h Tue Dec 06 15:45:27 2022 -0500 @@ -32,24 +32,22 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class PushButtonControl : public ButtonControl -{ -public: - PushButtonControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go, - QPushButton *btn); - ~PushButtonControl (void); + class PushButtonControl : public ButtonControl + { + public: + PushButtonControl (octave::interpreter& interp, const graphics_object& go, + QPushButton *btn); + ~PushButtonControl (void); - static PushButtonControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + static PushButtonControl * + create (octave::interpreter& interp, + const graphics_object& go); -protected: - void update (int pId); -}; + protected: + void update (int pId); + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/PushTool.cc --- a/libgui/graphics/PushTool.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/PushTool.cc Tue Dec 06 15:45:27 2022 -0500 @@ -31,54 +31,50 @@ #include "ToolBarButton.cc" -#include "octave-qobject.h" - OCTAVE_BEGIN_NAMESPACE(octave) -PushTool * -PushTool::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go) -{ - Object *parent = parentObject (interp, go); + PushTool * + PushTool::create (octave::interpreter& interp, const graphics_object& go) + { + Object *parent = parentObject (interp, go); - if (parent) - { - QWidget *parentWidget = parent->qWidget (); + if (parent) + { + QWidget *parentWidget = parent->qWidget (); - if (parentWidget) - return new PushTool (oct_qobj, interp, go, - new QAction (parentWidget)); - } + if (parentWidget) + return new PushTool (interp, go, + new QAction (parentWidget)); + } - return nullptr; -} + return nullptr; + } -PushTool::PushTool (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, QAction *action) - : ToolBarButton (oct_qobj, interp, go, action) -{ - connect (action, &QAction::triggered, this, &PushTool::clicked); -} + PushTool::PushTool (octave::interpreter& interp, + const graphics_object& go, QAction *action) + : ToolBarButton (interp, go, action) + { + connect (action, &QAction::triggered, this, &PushTool::clicked); + } -PushTool::~PushTool (void) -{ } + PushTool::~PushTool (void) + { } -void -PushTool::update (int pId) -{ - switch (pId) - { - default: - ToolBarButton::update (pId); - break; - } -} + void + PushTool::update (int pId) + { + switch (pId) + { + default: + ToolBarButton::update (pId); + break; + } + } -void -PushTool::clicked (void) -{ - emit gh_callback_event (m_handle, "clickedcallback"); -} + void + PushTool::clicked (void) + { + emit gh_callback_event (m_handle, "clickedcallback"); + } OCTAVE_END_NAMESPACE(octave); diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/PushTool.h --- a/libgui/graphics/PushTool.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/PushTool.h Tue Dec 06 15:45:27 2022 -0500 @@ -30,28 +30,27 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class PushTool : public ToolBarButton -{ - Q_OBJECT + class PushTool : public ToolBarButton + { + Q_OBJECT + + public: + PushTool (octave::interpreter& interp, + const graphics_object& go, QAction *action); + ~PushTool (void); -public: - PushTool (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QAction *action); - ~PushTool (void); + static PushTool * + create (octave::interpreter& interp, + const graphics_object& go); - static PushTool * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + protected: + void update (int pId); -protected: - void update (int pId); - -private slots: - void clicked (void); -}; + private slots: + void clicked (void); + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/RadioButtonControl.cc --- a/libgui/graphics/RadioButtonControl.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/RadioButtonControl.cc Tue Dec 06 15:45:27 2022 -0500 @@ -34,73 +34,69 @@ #include "Container.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - OCTAVE_BEGIN_NAMESPACE(octave) -RadioButtonControl * -RadioButtonControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go) -{ - Object *parent = parentObject (interp, go); + RadioButtonControl * + RadioButtonControl::create (octave::interpreter& interp, + const graphics_object& go) + { + Object *parent = parentObject (interp, go); - if (parent) - { - Container *container = parent->innerContainer (); + if (parent) + { + Container *container = parent->innerContainer (); - if (container) - return new RadioButtonControl (oct_qobj, interp, go, - new QRadioButton (container)); - } + if (container) + return new RadioButtonControl (interp, go, + new QRadioButton (container)); + } - return nullptr; -} + return nullptr; + } -RadioButtonControl::RadioButtonControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, - QRadioButton *radio) - : ButtonControl (oct_qobj, interp, go, radio) -{ - Object *parent = parentObject (interp, go); - ButtonGroup *btnGroup = dynamic_cast(parent); - if (btnGroup) - btnGroup->addButton (radio); + RadioButtonControl::RadioButtonControl (octave::interpreter& interp, + const graphics_object& go, + QRadioButton *radio) + : ButtonControl (interp, go, radio) + { + Object *parent = parentObject (interp, go); + ButtonGroup *btnGroup = dynamic_cast(parent); + if (btnGroup) + btnGroup->addButton (radio); - uicontrol::properties& up = properties (); + uicontrol::properties& up = properties (); - radio->setAutoFillBackground (true); - radio->setAutoExclusive (false); - if (up.enable_is ("inactive")) - radio->setCheckable (false); -} + radio->setAutoFillBackground (true); + radio->setAutoExclusive (false); + if (up.enable_is ("inactive")) + radio->setCheckable (false); + } -RadioButtonControl::~RadioButtonControl (void) -{ } + RadioButtonControl::~RadioButtonControl (void) + { } -void -RadioButtonControl::update (int pId) -{ - uicontrol::properties& up = properties (); - QRadioButton *btn = qWidget (); + void + RadioButtonControl::update (int pId) + { + uicontrol::properties& up = properties (); + QRadioButton *btn = qWidget (); - switch (pId) - { - case uicontrol::properties::ID_ENABLE: + switch (pId) { - if (up.enable_is ("inactive")) - btn->setCheckable (false); - else - btn->setCheckable (true); + case uicontrol::properties::ID_ENABLE: + { + if (up.enable_is ("inactive")) + btn->setCheckable (false); + else + btn->setCheckable (true); + ButtonControl::update (pId); + } + break; + + default: ButtonControl::update (pId); + break; } - break; - - default: - ButtonControl::update (pId); - break; - } -} + } OCTAVE_END_NAMESPACE(octave); diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/RadioButtonControl.h --- a/libgui/graphics/RadioButtonControl.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/RadioButtonControl.h Tue Dec 06 15:45:27 2022 -0500 @@ -32,24 +32,21 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class RadioButtonControl : public ButtonControl -{ -public: - RadioButtonControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go, - QRadioButton *box); - ~RadioButtonControl (void); + class RadioButtonControl : public ButtonControl + { + public: + RadioButtonControl (octave::interpreter& interp, const graphics_object& go, + QRadioButton *box); + ~RadioButtonControl (void); - static RadioButtonControl * create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go); + static RadioButtonControl * create (octave::interpreter& interp, + const graphics_object& go); -protected: - void update (int pId); -}; + protected: + void update (int pId); + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/SliderControl.cc --- a/libgui/graphics/SliderControl.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/SliderControl.cc Tue Dec 06 15:45:27 2022 -0500 @@ -33,8 +33,6 @@ #include "SliderControl.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - #include "graphics.h" #include "interpreter.h" @@ -42,132 +40,130 @@ OCTAVE_BEGIN_NAMESPACE(octave) -SliderControl * -SliderControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go) -{ - Object *parent = parentObject (interp, go); + SliderControl * + SliderControl::create (octave::interpreter& interp, + const graphics_object& go) + { + Object *parent = parentObject (interp, go); + + if (parent) + { + Container *container = parent->innerContainer (); - if (parent) - { - Container *container = parent->innerContainer (); + if (container) + return new SliderControl (interp, go, + new QScrollBar (container)); + } + + return nullptr; + } + + SliderControl::SliderControl (octave::interpreter& interp, + const graphics_object& go, + QAbstractSlider *slider) + : BaseControl (interp, go, slider), m_blockUpdates (false) + { + uicontrol::properties& up = properties (); - if (container) - return new SliderControl (oct_qobj, interp, go, - new QScrollBar (container)); - } - - return nullptr; -} + slider->setTracking (false); + Matrix bb = up.get_boundingbox (); + bool vertical_slider = ( bb(2) < bb(3) ); + slider->setOrientation (vertical_slider ? Qt::Vertical : Qt::Horizontal); + if (vertical_slider) + slider->setInvertedAppearance (true); // Matlab compatibility + Matrix steps = up.get_sliderstep ().matrix_value (); + slider->setMinimum (0); + slider->setMaximum (RANGE_INT_MAX); + slider->setSingleStep (octave::math::round (steps(0) * RANGE_INT_MAX)); + slider->setPageStep (octave::math::round (steps(1) * RANGE_INT_MAX)); + Matrix value = up.get_value ().matrix_value (); + if (value.numel () > 0) + { + double dmin = up.get_min (), dmax = up.get_max (); -SliderControl::SliderControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, - QAbstractSlider *slider) - : BaseControl (oct_qobj, interp, go, slider), m_blockUpdates (false) -{ - uicontrol::properties& up = properties (); + slider->setValue (octave::math::round (((value(0) - dmin) / (dmax - dmin)) + * RANGE_INT_MAX)); + } + + connect (slider, &QAbstractSlider::valueChanged, + this, &SliderControl::valueChanged); + } + + SliderControl::~SliderControl (void) + { } + + void + SliderControl::update (int pId) + { + uicontrol::properties& up = properties (); + QScrollBar *slider = qWidget (); - slider->setTracking (false); - Matrix bb = up.get_boundingbox (); - bool vertical_slider = ( bb(2) < bb(3) ); - slider->setOrientation (vertical_slider ? Qt::Vertical : Qt::Horizontal); - if (vertical_slider) - slider->setInvertedAppearance (true); // Matlab compatibility - Matrix steps = up.get_sliderstep ().matrix_value (); - slider->setMinimum (0); - slider->setMaximum (RANGE_INT_MAX); - slider->setSingleStep (octave::math::round (steps(0) * RANGE_INT_MAX)); - slider->setPageStep (octave::math::round (steps(1) * RANGE_INT_MAX)); - Matrix value = up.get_value ().matrix_value (); - if (value.numel () > 0) - { - double dmin = up.get_min (), dmax = up.get_max (); + switch (pId) + { + case uicontrol::properties::ID_SLIDERSTEP: + { + Matrix steps = up.get_sliderstep ().matrix_value (); + + slider->setSingleStep (octave::math::round (steps(0) * RANGE_INT_MAX)); + slider->setPageStep (octave::math::round (steps(1) * RANGE_INT_MAX)); + } + break; - slider->setValue (octave::math::round (((value(0) - dmin) / (dmax - dmin)) - * RANGE_INT_MAX)); - } + case uicontrol::properties::ID_VALUE: + { + Matrix value = up.get_value ().matrix_value (); + double dmax = up.get_max (), dmin = up.get_min (); - connect (slider, &QAbstractSlider::valueChanged, - this, &SliderControl::valueChanged); -} + if (value.numel () > 0) + { + int ival = octave::math::round (((value(0) - dmin) / (dmax - dmin)) + * RANGE_INT_MAX); -SliderControl::~SliderControl (void) -{ } + m_blockUpdates = true; + slider->setValue (ival); + m_blockUpdates = false; + } + } + break; -void -SliderControl::update (int pId) -{ - uicontrol::properties& up = properties (); - QScrollBar *slider = qWidget (); - - switch (pId) - { - case uicontrol::properties::ID_SLIDERSTEP: - { - Matrix steps = up.get_sliderstep ().matrix_value (); - - slider->setSingleStep (octave::math::round (steps(0) * RANGE_INT_MAX)); - slider->setPageStep (octave::math::round (steps(1) * RANGE_INT_MAX)); + default: + BaseControl::update (pId); + break; } - break; + } - case uicontrol::properties::ID_VALUE: + void + SliderControl::valueChanged (int ival) + { + if (! m_blockUpdates) { - Matrix value = up.get_value ().matrix_value (); - double dmax = up.get_max (), dmin = up.get_min (); + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + octave::autolock guard (gh_mgr.graphics_lock ()); + + graphics_object go = object (); - if (value.numel () > 0) + if (go.valid_object ()) { - int ival = octave::math::round (((value(0) - dmin) / (dmax - dmin)) - * RANGE_INT_MAX); + uicontrol::properties& up = Utils::properties (go); + + Matrix value = up.get_value ().matrix_value (); + double dmin = up.get_min (), dmax = up.get_max (); - m_blockUpdates = true; - slider->setValue (ival); - m_blockUpdates = false; + int ival_tmp = (value.numel () > 0 ? + octave::math::round (((value(0) - dmin) / (dmax - dmin)) + * RANGE_INT_MAX) : + 0); + + if (ival != ival_tmp || value.numel () > 0) + { + double dval = dmin + (ival * (dmax - dmin) / RANGE_INT_MAX); + + emit gh_set_event (m_handle, "value", octave_value (dval)); + emit gh_callback_event (m_handle, "callback"); + } } } - break; - - default: - BaseControl::update (pId); - break; - } -} - -void -SliderControl::valueChanged (int ival) -{ - if (! m_blockUpdates) - { - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - octave::autolock guard (gh_mgr.graphics_lock ()); - - graphics_object go = object (); - - if (go.valid_object ()) - { - uicontrol::properties& up = Utils::properties (go); - - Matrix value = up.get_value ().matrix_value (); - double dmin = up.get_min (), dmax = up.get_max (); - - int ival_tmp = (value.numel () > 0 ? - octave::math::round (((value(0) - dmin) / (dmax - dmin)) - * RANGE_INT_MAX) : - 0); - - if (ival != ival_tmp || value.numel () > 0) - { - double dval = dmin + (ival * (dmax - dmin) / RANGE_INT_MAX); - - emit gh_set_event (m_handle, "value", octave_value (dval)); - emit gh_callback_event (m_handle, "callback"); - } - } - } -} + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/SliderControl.h --- a/libgui/graphics/SliderControl.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/SliderControl.h Tue Dec 06 15:45:27 2022 -0500 @@ -32,31 +32,30 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class SliderControl : public BaseControl -{ - Q_OBJECT + class SliderControl : public BaseControl + { + Q_OBJECT -public: - SliderControl (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QAbstractSlider *slider); - ~SliderControl (void); + public: + SliderControl (octave::interpreter& interp, + const graphics_object& go, QAbstractSlider *slider); + ~SliderControl (void); - static SliderControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + static SliderControl * + create (octave::interpreter& interp, + const graphics_object& go); -protected: - void update (int pId); + protected: + void update (int pId); -private slots: - void valueChanged (int ival); + private slots: + void valueChanged (int ival); -private: - bool m_blockUpdates; -}; + private: + bool m_blockUpdates; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/Table.cc --- a/libgui/graphics/Table.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/Table.cc Tue Dec 06 15:45:27 2022 -0500 @@ -48,8 +48,6 @@ #include "Table.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - #include "graphics.h" #include "interpreter.h" #include "oct-map.h" @@ -59,99 +57,99 @@ OCTAVE_BEGIN_NAMESPACE(octave) -static const int AUTO_WIDTH = 75; + static const int AUTO_WIDTH = 75; #define AUTO_HEIGHT (tp.get_fontsize () * 2 - 1) -static QSize realQSizeForTable (QTableWidget *t) -{ - int w = t->verticalHeader ()->width () + 4; - for (int i = 0; i < t->columnCount (); i++) - w += t->columnWidth (i); - int h = t->horizontalHeader ()->height () + 4; - for (int i = 0; i < t->rowCount (); i++) - h += t->rowHeight (i); - return QSize (w, h); -} - -#define FORMATNUMBER(type) \ - static QString formatNumber (type d, \ - char format = 'f', \ - int precision = 4) \ - { \ - type ten = 10; \ - if (format == 'n') \ - { \ - if (d == floor (d)) \ - return QString::number (d, 'g', precision); \ - else if (d <= pow (ten, precision - 1) \ - && d > pow (ten, 1 - precision)) \ - return QString::number (d, 'f', precision); \ - else \ - return QString::number (d, 'e', precision); \ - } \ - else if (format == 'F') \ - { \ - int exponent = floor (log10 (d) / 3) * 3; \ - d *= pow (ten, -exponent); \ - return QString::number (d, 'f', precision) + "e" + \ - (exponent < 0 ? "-" : "+") + \ - QString ("%1").arg (abs (exponent), 3, 10, QChar ('0')); \ - } \ - else if (format == 'E') \ - { \ - int exponent = floor (log10 (d) / 3) * 3; \ - d *= pow (ten, -exponent); \ - return QString::number (d, \ - 'f', \ - precision - floor (log10 (d)) - 1) + \ - "e" + (exponent < 0 ? "-" : "+") + \ - QString ("%1").arg (abs (exponent), 3, 10, QChar ('0')); \ - } \ - else \ - return QString::number (d, format, precision); \ + static QSize realQSizeForTable (QTableWidget *t) + { + int w = t->verticalHeader ()->width () + 4; + for (int i = 0; i < t->columnCount (); i++) + w += t->columnWidth (i); + int h = t->horizontalHeader ()->height () + 4; + for (int i = 0; i < t->rowCount (); i++) + h += t->rowHeight (i); + return QSize (w, h); } -FORMATNUMBER(double) -FORMATNUMBER(float) +#define FORMATNUMBER(type) \ + static QString formatNumber (type d, \ + char format = 'f', \ + int precision = 4) \ + { \ + type ten = 10; \ + if (format == 'n') \ + { \ + if (d == floor (d)) \ + return QString::number (d, 'g', precision); \ + else if (d <= pow (ten, precision - 1) \ + && d > pow (ten, 1 - precision)) \ + return QString::number (d, 'f', precision); \ + else \ + return QString::number (d, 'e', precision); \ + } \ + else if (format == 'F') \ + { \ + int exponent = floor (log10 (d) / 3) * 3; \ + d *= pow (ten, -exponent); \ + return QString::number (d, 'f', precision) + "e" + \ + (exponent < 0 ? "-" : "+") + \ + QString ("%1").arg (abs (exponent), 3, 10, QChar ('0')); \ + } \ + else if (format == 'E') \ + { \ + int exponent = floor (log10 (d) / 3) * 3; \ + d *= pow (ten, -exponent); \ + return QString::number (d, \ + 'f', \ + precision - floor (log10 (d)) - 1) + \ + "e" + (exponent < 0 ? "-" : "+") + \ + QString ("%1").arg (abs (exponent), 3, 10, QChar ('0')); \ + } \ + else \ + return QString::number (d, format, precision); \ + } + + FORMATNUMBER(double) + FORMATNUMBER(float) #undef FORMATNUMBER -static QString formatComplex (Complex c, char format = 'f', int precision = 4) -{ - return formatNumber (c.real (), format, precision) + " + " - + formatNumber (c.imag (), format, precision) + "i"; -} + static QString formatComplex (Complex c, char format = 'f', int precision = 4) + { + return formatNumber (c.real (), format, precision) + " + " + + formatNumber (c.imag (), format, precision) + "i"; + } -#define FORMAT_VALUE_EXCEPT_RAT(f,l) \ - if (format == "numeric" || format == "short") \ - text = formatNumber (value, 'n', f); \ - else if (format == "short f" || format == "shortf") \ - text = formatNumber (value, 'f', f); \ - else if (format == "short e" || format == "shorte") \ - text = formatNumber (value, 'e', f); \ - else if (format == "short eng" || format == "shorteng") \ - text = formatNumber (value, 'F', f); \ - else if (format == "short g" || format == "shortg") \ - text = formatNumber (value, 'g', f + 1); \ - else if (format == "long") \ - text = formatNumber (value, 'n', l); \ - else if (format == "long f" || format == "longf") \ - text = formatNumber (value, 'f', l); \ - else if (format == "long e" || format == "longe") \ - text = formatNumber (value, 'e', l); \ - else if (format == "long eng" || format == "longeng") \ - text = formatNumber (value, 'E', l); \ - else if (format == "long g" || format == "longg") \ - text = formatNumber (value, 'g', l + 1); \ - else if (format == "bank") \ - text = QString::number (value, 'f', 2); \ - else if (format == "+") \ - if (value > 0) \ - text = Utils::fromStdString ("+"); \ - else if (value < 0) \ - text = Utils::fromStdString ("-"); \ - else \ +#define FORMAT_VALUE_EXCEPT_RAT(f,l) \ + if (format == "numeric" || format == "short") \ + text = formatNumber (value, 'n', f); \ + else if (format == "short f" || format == "shortf") \ + text = formatNumber (value, 'f', f); \ + else if (format == "short e" || format == "shorte") \ + text = formatNumber (value, 'e', f); \ + else if (format == "short eng" || format == "shorteng") \ + text = formatNumber (value, 'F', f); \ + else if (format == "short g" || format == "shortg") \ + text = formatNumber (value, 'g', f + 1); \ + else if (format == "long") \ + text = formatNumber (value, 'n', l); \ + else if (format == "long f" || format == "longf") \ + text = formatNumber (value, 'f', l); \ + else if (format == "long e" || format == "longe") \ + text = formatNumber (value, 'e', l); \ + else if (format == "long eng" || format == "longeng") \ + text = formatNumber (value, 'E', l); \ + else if (format == "long g" || format == "longg") \ + text = formatNumber (value, 'g', l + 1); \ + else if (format == "bank") \ + text = QString::number (value, 'f', 2); \ + else if (format == "+") \ + if (value > 0) \ + text = Utils::fromStdString ("+"); \ + else if (value < 0) \ + text = Utils::fromStdString ("-"); \ + else \ text = Utils::fromStdString (""); #define FORMAT_VALUE(f,l) \ @@ -164,220 +162,220 @@ flag = Qt::AlignLeft ; \ } -#define FORMAT_UINT_VALUE() \ - text = QString::number (value); \ - if (format == "char" || format == "popup") \ - flag = Qt::AlignLeft; \ - else if (format == "+") \ - { \ - if (value > 0) \ - text = Utils::fromStdString ("+"); \ - else \ - text = Utils::fromStdString (""); \ +#define FORMAT_UINT_VALUE() \ + text = QString::number (value); \ + if (format == "char" || format == "popup") \ + flag = Qt::AlignLeft; \ + else if (format == "+") \ + { \ + if (value > 0) \ + text = Utils::fromStdString ("+"); \ + else \ + text = Utils::fromStdString (""); \ } -#define FORMAT_INT_VALUE() \ - text = QString::number (value); \ - if (format == "char" || format == "popup") \ - flag = Qt::AlignLeft ; \ - else if (format == "+") \ - { \ - if (value > 0) \ - text = Utils::fromStdString ("+"); \ - else if (value < 0) \ - text = Utils::fromStdString ("-"); \ - else \ - text = Utils::fromStdString (""); \ +#define FORMAT_INT_VALUE() \ + text = QString::number (value); \ + if (format == "char" || format == "popup") \ + flag = Qt::AlignLeft ; \ + else if (format == "+") \ + { \ + if (value > 0) \ + text = Utils::fromStdString ("+"); \ + else if (value < 0) \ + text = Utils::fromStdString ("-"); \ + else \ + text = Utils::fromStdString (""); \ } -static std::pair -qStringValueFor (octave_value val, std::string format = "") -{ - Qt::AlignmentFlag flag = Qt::AlignRight; - QString text; - if (val.isempty ()) - { - text = ""; - flag = Qt::AlignLeft; - } - else if (val.is_string ()) - { - text = octave::Utils::fromStdString (val.string_value ()); - flag = Qt::AlignLeft; - } - else if (val.iscomplex ()) - { - // Matlab has multiple complex types, we only have double. - Complex c = val.complex_value (); - if (format == "short") - text = formatComplex (c, 'f', 4); - else if (format == "short e" || format == "shorte") - text = formatComplex (c, 'e', 4); - else if (format == "short eng" || format == "shorteng") - text = formatComplex (c, 'E', 4); - else if (format == "short g" || format == "shortg") - text = formatComplex (c, 'g', 5); - else if (format == "long") - text = formatComplex (c, 'f', 15); - else if (format == "long e" || format == "longe") - text = formatComplex (c, 'e', 15); - else if (format == "long eng" || format == "longeng") - text = formatComplex (c, 'E', 15); - else if (format == "long g" || format == "longg") - text = formatComplex (c, 'g', 16); - else if (format == "bank") - text = QString::number (c.real (), 'f', 2); - else if (format == "+") - { - if (c.real () > 0) - text = Utils::fromStdString ("+"); - else if (c.real () < 0) - text = Utils::fromStdString ("-"); - else - text = Utils::fromStdString (""); - } - else if (format == "rat") - text = Utils::fromStdString (rational_approx (c.real (), 0)) + " + " - + Utils::fromStdString (rational_approx (c.imag (), 0)) + "i"; - else if (format == "numeric") - text = QString::number (c.real (), 'g', 5) + " + " - + QString::number (c.imag (), 'g', 5) + "i"; - else - { + static std::pair + qStringValueFor (octave_value val, std::string format = "") + { + Qt::AlignmentFlag flag = Qt::AlignRight; + QString text; + if (val.isempty ()) + { + text = ""; + flag = Qt::AlignLeft; + } + else if (val.is_string ()) + { + text = octave::Utils::fromStdString (val.string_value ()); + flag = Qt::AlignLeft; + } + else if (val.iscomplex ()) + { + // Matlab has multiple complex types, we only have double. + Complex c = val.complex_value (); + if (format == "short") + text = formatComplex (c, 'f', 4); + else if (format == "short e" || format == "shorte") + text = formatComplex (c, 'e', 4); + else if (format == "short eng" || format == "shorteng") + text = formatComplex (c, 'E', 4); + else if (format == "short g" || format == "shortg") + text = formatComplex (c, 'g', 5); + else if (format == "long") + text = formatComplex (c, 'f', 15); + else if (format == "long e" || format == "longe") + text = formatComplex (c, 'e', 15); + else if (format == "long eng" || format == "longeng") + text = formatComplex (c, 'E', 15); + else if (format == "long g" || format == "longg") + text = formatComplex (c, 'g', 16); + else if (format == "bank") + text = QString::number (c.real (), 'f', 2); + else if (format == "+") + { + if (c.real () > 0) + text = Utils::fromStdString ("+"); + else if (c.real () < 0) + text = Utils::fromStdString ("-"); + else + text = Utils::fromStdString (""); + } + else if (format == "rat") + text = Utils::fromStdString (rational_approx (c.real (), 0)) + " + " + + Utils::fromStdString (rational_approx (c.imag (), 0)) + "i"; + else if (format == "numeric") text = QString::number (c.real (), 'g', 5) + " + " - + QString::number (c.imag (), 'g', 5) + "i"; - flag = Qt::AlignLeft; - } - } - else if (val.is_double_type () ) - { - double value = val.double_value (); - FORMAT_VALUE(4, 15) - } - else if (val.is_single_type ()) - { - float value = val.float_value (); - FORMAT_VALUE(4, 7) - } - else if (val.is_int8_type ()) - { - short int value = val.short_value (); - FORMAT_INT_VALUE() - } - else if (val.is_uint8_type ()) - { - unsigned short int value = val.ushort_value (); - FORMAT_UINT_VALUE() - } - else if (val.is_int16_type ()) - { - int value = val.int_value (); - FORMAT_INT_VALUE() - } - else if (val.is_uint16_type ()) - { - unsigned int value = val.uint_value (); - FORMAT_UINT_VALUE() - } - else if (val.is_int32_type ()) - { - long int value = val.long_value (); - FORMAT_INT_VALUE() - } - else if (val.is_uint32_type ()) - { - unsigned long int value = val.ulong_value (); - FORMAT_UINT_VALUE() - } - else if (val.is_int64_type ()) - { - int64_t value = val.int64_value (); - FORMAT_INT_VALUE() - } - else if (val.is_uint64_type ()) - { - uint64_t value = val.uint64_value (); - FORMAT_UINT_VALUE() - } - else if (val.islogical ()) - { - bool b = val.bool_value (); - if (format == "char" || format == "popup" || format == "") - { - text = Utils::fromStdString (b ? "true" : "false"); - flag = Qt::AlignLeft; - } - else if (format == "+") - { - text = Utils::fromStdString (b ? "+" : ""); - flag = Qt::AlignLeft; - } - else - text = Utils::fromStdString (b ? "1" : "0"); - } - else - { - std::stringstream warn_string; - warn_string << "Unknown conversion for datatype " << val.class_name () - << " to " << format - << " for value " << val.string_value (true); - warning ("%s", warn_string.str ().c_str ()); + + QString::number (c.imag (), 'g', 5) + "i"; + else + { + text = QString::number (c.real (), 'g', 5) + " + " + + QString::number (c.imag (), 'g', 5) + "i"; + flag = Qt::AlignLeft; + } + } + else if (val.is_double_type () ) + { + double value = val.double_value (); + FORMAT_VALUE(4, 15) + } + else if (val.is_single_type ()) + { + float value = val.float_value (); + FORMAT_VALUE(4, 7) + } + else if (val.is_int8_type ()) + { + short int value = val.short_value (); + FORMAT_INT_VALUE() + } + else if (val.is_uint8_type ()) + { + unsigned short int value = val.ushort_value (); + FORMAT_UINT_VALUE() + } + else if (val.is_int16_type ()) + { + int value = val.int_value (); + FORMAT_INT_VALUE() + } + else if (val.is_uint16_type ()) + { + unsigned int value = val.uint_value (); + FORMAT_UINT_VALUE() + } + else if (val.is_int32_type ()) + { + long int value = val.long_value (); + FORMAT_INT_VALUE() + } + else if (val.is_uint32_type ()) + { + unsigned long int value = val.ulong_value (); + FORMAT_UINT_VALUE() + } + else if (val.is_int64_type ()) + { + int64_t value = val.int64_value (); + FORMAT_INT_VALUE() + } + else if (val.is_uint64_type ()) + { + uint64_t value = val.uint64_value (); + FORMAT_UINT_VALUE() + } + else if (val.islogical ()) + { + bool b = val.bool_value (); + if (format == "char" || format == "popup" || format == "") + { + text = Utils::fromStdString (b ? "true" : "false"); + flag = Qt::AlignLeft; + } + else if (format == "+") + { + text = Utils::fromStdString (b ? "+" : ""); + flag = Qt::AlignLeft; + } + else + text = Utils::fromStdString (b ? "1" : "0"); + } + else + { + std::stringstream warn_string; + warn_string << "Unknown conversion for datatype " << val.class_name () + << " to " << format + << " for value " << val.string_value (true); + warning ("%s", warn_string.str ().c_str ()); - text = Utils::fromStdString (val.string_value (true)); - } + text = Utils::fromStdString (val.string_value (true)); + } - return std::make_pair (flag, text); -} + return std::make_pair (flag, text); + } #undef FORMAT_VALUE #undef FORMAT_VALUE_EXCEPT_RAT #undef FORMAT_UINT_VALUE #undef FORMAT_INT_VALUE -static QTableWidgetItem * itemFor (octave_value val, std::string format = "", - bool enabled = false) -{ - QTableWidgetItem *retval = new QTableWidgetItem (); - std::pair flag_and_text = - qStringValueFor (val, format); - retval->setTextAlignment (flag_and_text.first); - retval->setText (flag_and_text.second); + static QTableWidgetItem * itemFor (octave_value val, std::string format = "", + bool enabled = false) + { + QTableWidgetItem *retval = new QTableWidgetItem (); + std::pair flag_and_text = + qStringValueFor (val, format); + retval->setTextAlignment (flag_and_text.first); + retval->setText (flag_and_text.second); - if (enabled) - retval->setFlags (retval->flags () | Qt::ItemIsEditable); - else - retval->setFlags (retval->flags () & ~Qt::ItemIsEditable); + if (enabled) + retval->setFlags (retval->flags () | Qt::ItemIsEditable); + else + retval->setFlags (retval->flags () & ~Qt::ItemIsEditable); - return retval; -} + return retval; + } -static octave_value -attempt_type_conversion (const octave_value& ov, - const octave_value& old_value) -{ - octave_value retval; + static octave_value + attempt_type_conversion (const octave_value& ov, + const octave_value& old_value) + { + octave_value retval; - // Define a macro to help with the conversion of strings to integers - // FIXME: these will happily integer overflow in the (u)int64 case - // - this probably doesn't matter. -#define SCANF_AND_CONVERT(name,ctype,format) \ - else if (old_value.is_ ## name ## _type ()) \ - { \ - ctype val; \ - int n; \ - const std::string cxx_str = ov.string_value (); \ - const char *c_str = cxx_str.c_str (); \ - int error = sscanf (c_str, format, &val, &n); \ - if (error != 1 || c_str[n]) \ - { \ - val = 0; \ - } \ - retval = octave_value ( octave_ ## name (val)); \ + // Define a macro to help with the conversion of strings to integers + // FIXME: these will happily integer overflow in the (u)int64 case + // - this probably doesn't matter. +#define SCANF_AND_CONVERT(name,ctype,format) \ + else if (old_value.is_ ## name ## _type ()) \ + { \ + ctype val; \ + int n; \ + const std::string cxx_str = ov.string_value (); \ + const char *c_str = cxx_str.c_str (); \ + int error = sscanf (c_str, format, &val, &n); \ + if (error != 1 || c_str[n]) \ + { \ + val = 0; \ + } \ + retval = octave_value ( octave_ ## name (val)); \ } - if (old_value.is_string ()) - retval = ov; - SCANF_AND_CONVERT(int8, int64_t, "%" PRId64 " %n") + if (old_value.is_string ()) + retval = ov; + SCANF_AND_CONVERT(int8, int64_t, "%" PRId64 " %n") SCANF_AND_CONVERT(uint8, uint64_t, "%" PRIu64 " %n") SCANF_AND_CONVERT(int16, int64_t, "%" PRId64 " %n") SCANF_AND_CONVERT(uint16, uint64_t, "%" PRIu64 " %n") @@ -388,747 +386,712 @@ #undef SCANF_AND_CONVERT - else if (old_value.isnumeric () && ! old_value.isinteger ()) - { - // Basically need to do str2double - Complex complex = octave::string::str2double (ov.string_value ()); - if (old_value.is_single_type ()) - retval = octave_value (FloatComplex (complex)); - else - retval = octave_value (complex); - } - else if (old_value.islogical ()) - { - // Right: Matlab basically needs this to be true or false, we should - // accept 1 too. - if (ov.string_value () == "true" || ov.string_value () == "1") - retval = octave_value (true); - else - retval = octave_value (false); - } - else - retval = octave_value (octave::string::str2double (ov.string_value ())); - return retval; -} + else if (old_value.isnumeric () && ! old_value.isinteger ()) + { + // Basically need to do str2double + Complex complex = octave::string::str2double (ov.string_value ()); + if (old_value.is_single_type ()) + retval = octave_value (FloatComplex (complex)); + else + retval = octave_value (complex); + } + else if (old_value.islogical ()) + { + // Right: Matlab basically needs this to be true or false, we should + // accept 1 too. + if (ov.string_value () == "true" || ov.string_value () == "1") + retval = octave_value (true); + else + retval = octave_value (false); + } + else + retval = octave_value (octave::string::str2double (ov.string_value ())); + return retval; + } -QWidget * -Table::checkBoxForLogical (octave_value val, bool enabled = false) -{ - QWidget *retval = new QWidget (m_tableWidget); - QCheckBox *checkBox = new QCheckBox (); - QHBoxLayout *layout = new QHBoxLayout (retval); - layout->addWidget (checkBox); - layout->setAlignment (Qt::AlignCenter); - layout->setContentsMargins (0, 0, 0, 0); - retval->setLayout (layout); + QWidget * + Table::checkBoxForLogical (octave_value val, bool enabled = false) + { + QWidget *retval = new QWidget (m_tableWidget); + QCheckBox *checkBox = new QCheckBox (); + QHBoxLayout *layout = new QHBoxLayout (retval); + layout->addWidget (checkBox); + layout->setAlignment (Qt::AlignCenter); + layout->setContentsMargins (0, 0, 0, 0); + retval->setLayout (layout); - if ((val.islogical () || val.is_bool_scalar ()) && val.bool_value ()) - checkBox->setCheckState (Qt::Checked); - else - checkBox->setCheckState (Qt::Unchecked); + if ((val.islogical () || val.is_bool_scalar ()) && val.bool_value ()) + checkBox->setCheckState (Qt::Checked); + else + checkBox->setCheckState (Qt::Unchecked); - checkBox->setAttribute (Qt::WA_TransparentForMouseEvents, true); - checkBox->setFocusPolicy (Qt::NoFocus); - checkBox->setProperty ("Enabled", QVariant (enabled)); + checkBox->setAttribute (Qt::WA_TransparentForMouseEvents, true); + checkBox->setFocusPolicy (Qt::NoFocus); + checkBox->setProperty ("Enabled", QVariant (enabled)); - return retval; -} + return retval; + } -Table * -Table::create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go) -{ - Object *parent = parentObject (interp, go); + Table * + Table::create (octave::interpreter& interp, + const graphics_object& go) + { + Object *parent = parentObject (interp, go); - if (parent) - { - Container *container = parent->innerContainer (); + if (parent) + { + Container *container = parent->innerContainer (); - if (container) - return new Table (oct_qobj, interp, go, new QTableWidget (container)); - } + if (container) + return new Table (interp, go, new QTableWidget (container)); + } - return 0; -} + return 0; + } -Table::Table (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QTableWidget *tableWidget) - : Object (oct_qobj, interp, go, tableWidget), m_tableWidget (tableWidget), - m_curData (), m_blockUpdates (false) -{ - qObject ()->setObjectName ("UItable"); - uitable::properties& tp = properties (); + Table::Table (octave::interpreter& interp, + const graphics_object& go, QTableWidget *tableWidget) + : Object (interp, go, tableWidget), m_tableWidget (tableWidget), + m_curData (), m_blockUpdates (false) + { + qObject ()->setObjectName ("UItable"); + uitable::properties& tp = properties (); - m_curData = octave_value (tp.get_data ()); - Matrix bb = tp.get_boundingbox (false); - m_tableWidget->setObjectName ("UITable"); - m_tableWidget->setAutoFillBackground (true); - m_tableWidget->setGeometry (octave::math::round (bb(0)), - octave::math::round (bb(1)), - octave::math::round (bb(2)), - octave::math::round (bb(3))); - m_tableWidget->setFont (Utils::computeFont (tp)) ; - m_tableWidget->setSelectionBehavior (QAbstractItemView::SelectItems); - updatePalette (); - m_keyPressHandlerDefined = ! tp.get_keypressfcn ().isempty (); - m_keyReleaseHandlerDefined = ! tp.get_keyreleasefcn ().isempty (); - updateData (); - updateRowname (); - updateColumnname (); - updateColumnwidth (); - updateEnable (); // Also does rearrangeableColumns - m_tableWidget->setToolTip (Utils::fromStdString (tp.get_tooltipstring ())); - m_tableWidget->setVisible (tp.is_visible ()); - updateExtent (); - m_tableWidget->installEventFilter (this); + m_curData = octave_value (tp.get_data ()); + Matrix bb = tp.get_boundingbox (false); + m_tableWidget->setObjectName ("UITable"); + m_tableWidget->setAutoFillBackground (true); + m_tableWidget->setGeometry (octave::math::round (bb(0)), + octave::math::round (bb(1)), + octave::math::round (bb(2)), + octave::math::round (bb(3))); + m_tableWidget->setFont (Utils::computeFont (tp)) ; + m_tableWidget->setSelectionBehavior (QAbstractItemView::SelectItems); + updatePalette (); + m_keyPressHandlerDefined = ! tp.get_keypressfcn ().isempty (); + m_keyReleaseHandlerDefined = ! tp.get_keyreleasefcn ().isempty (); + updateData (); + updateRowname (); + updateColumnname (); + updateColumnwidth (); + updateEnable (); // Also does rearrangeableColumns + m_tableWidget->setToolTip (Utils::fromStdString (tp.get_tooltipstring ())); + m_tableWidget->setVisible (tp.is_visible ()); + updateExtent (); + m_tableWidget->installEventFilter (this); - connect (m_tableWidget, &QTableWidget::itemChanged, - this, &Table::itemChanged); - connect (m_tableWidget, &QTableWidget::cellClicked, - this, &Table::cellClicked); - connect (m_tableWidget, &QTableWidget::itemSelectionChanged, - this, &Table::itemSelectionChanged); -} + connect (m_tableWidget, &QTableWidget::itemChanged, + this, &Table::itemChanged); + connect (m_tableWidget, &QTableWidget::cellClicked, + this, &Table::cellClicked); + connect (m_tableWidget, &QTableWidget::itemSelectionChanged, + this, &Table::itemSelectionChanged); + } -Table::~Table (void) { } + Table::~Table (void) { } -void -Table::itemSelectionChanged () -{ - if (! (properties ().get_cellselectioncallback ().isempty ())) - { - QModelIndexList modelIndexList = - m_tableWidget->selectionModel ()->selectedIndexes (); - int length = modelIndexList.size (); - Matrix indices = Matrix (length, 2); - for (int i = 0; i < length; i++) - { - indices(i, 0) = modelIndexList.value (i).row () + 1; - indices(i, 1) = modelIndexList.value (i).column () + 1; - } - octave_scalar_map eventData; - eventData.setfield ("Indices", indices); - octave_value cellSelectionCallbackEventObject (eventData); - emit gh_callback_event (m_handle, "cellselectioncallback", - cellSelectionCallbackEventObject); - } -} - -void -Table::cellClicked (int row, int col) -{ - QCheckBox *checkBox = nullptr; - QWidget *widget - = qobject_cast (m_tableWidget->cellWidget (row, col)); - if (widget && ! widget->children ().isEmpty ()) - { - QHBoxLayout *layout - = qobject_cast (widget->children ().first ()); + void + Table::itemSelectionChanged () + { + if (! (properties ().get_cellselectioncallback ().isempty ())) + { + QModelIndexList modelIndexList = + m_tableWidget->selectionModel ()->selectedIndexes (); + int length = modelIndexList.size (); + Matrix indices = Matrix (length, 2); + for (int i = 0; i < length; i++) + { + indices(i, 0) = modelIndexList.value (i).row () + 1; + indices(i, 1) = modelIndexList.value (i).column () + 1; + } + octave_scalar_map eventData; + eventData.setfield ("Indices", indices); + octave_value cellSelectionCallbackEventObject (eventData); + emit gh_callback_event (m_handle, "cellselectioncallback", + cellSelectionCallbackEventObject); + } + } - if (layout && layout->count () > 0) - checkBox = qobject_cast (layout->itemAt (0)-> widget ()); - } - - if (checkBox && checkBox->property ("Enabled").toBool ()) - checkBoxClicked (row, col, checkBox); -} + void + Table::cellClicked (int row, int col) + { + QCheckBox *checkBox = nullptr; + QWidget *widget + = qobject_cast (m_tableWidget->cellWidget (row, col)); + if (widget && ! widget->children ().isEmpty ()) + { + QHBoxLayout *layout + = qobject_cast (widget->children ().first ()); -void -Table::sendCellEditCallback (int row, - int col, - octave_value old_value, - octave_value new_value, - octave_value edit_data, - octave_value error) -{ + if (layout && layout->count () > 0) + checkBox = qobject_cast (layout->itemAt (0)-> widget ()); + } - if (!(properties ().get_celleditcallback ().isempty ())) - { - Matrix indices = Matrix (1, 2); - indices(0, 0) = row + 1; - indices(0, 1) = col + 1; + if (checkBox && checkBox->property ("Enabled").toBool ()) + checkBoxClicked (row, col, checkBox); + } - octave_scalar_map eventData; - eventData.setfield ("Indices", indices); - eventData.setfield ("PreviousData", old_value); - eventData.setfield ("NewData", new_value); - eventData.setfield ("EditData", edit_data); - eventData.setfield ("Error", error); + void + Table::sendCellEditCallback (int row, + int col, + octave_value old_value, + octave_value new_value, + octave_value edit_data, + octave_value error) + { - octave_value cellEditCallbackEventObject (eventData); - - emit gh_callback_event (m_handle, "celleditcallback", - cellEditCallbackEventObject); - } - else if (error.string_value ().length () > 0) - warning ("%s", error.string_value ().c_str ()); -} + if (!(properties ().get_celleditcallback ().isempty ())) + { + Matrix indices = Matrix (1, 2); + indices(0, 0) = row + 1; + indices(0, 1) = col + 1; -void -Table::comboBoxCurrentIndexChanged (const QString& value) -{ - if (m_blockUpdates) - return; + octave_scalar_map eventData; + eventData.setfield ("Indices", indices); + eventData.setfield ("PreviousData", old_value); + eventData.setfield ("NewData", new_value); + eventData.setfield ("EditData", edit_data); + eventData.setfield ("Error", error); - m_blockUpdates = true; - - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + octave_value cellEditCallbackEventObject (eventData); - octave::autolock guard (gh_mgr.graphics_lock ()); - - octave_value data = octave_value (m_curData); - bool ok = false; + emit gh_callback_event (m_handle, "celleditcallback", + cellEditCallbackEventObject); + } + else if (error.string_value ().length () > 0) + warning ("%s", error.string_value ().c_str ()); + } - QComboBox *comboBox = qobject_cast (sender ()); - int row = comboBox->property ("row").toInt (); - int col = comboBox->property ("col").toInt (); + void + Table::comboBoxCurrentIndexChanged (const QString& value) + { + if (m_blockUpdates) + return; - octave_value edit_data = octave_value (Utils::toStdString (value)); + m_blockUpdates = true; - if (row < data.rows () && col < data.columns ()) - { - if (data.iscell ()) - { - Cell cell = data.cell_value (); - octave_value old_data = cell(row, col); - if (cell(row, col).is_string ()) - { - cell(row, col) = edit_data; - if (edit_data.string_value () != old_data.string_value ()) - { - m_curData = octave_value (cell); - emit gh_set_event (m_handle, "data", octave_value (cell), - false); - } + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + octave::autolock guard (gh_mgr.graphics_lock ()); + + octave_value data = octave_value (m_curData); + bool ok = false; + + QComboBox *comboBox = qobject_cast (sender ()); + int row = comboBox->property ("row").toInt (); + int col = comboBox->property ("col").toInt (); - octave_value error = octave_value (""); - sendCellEditCallback (row, col, - old_data, - edit_data, - edit_data, - error); - ok = true; - } - else - { - cell(row, col) = attempt_type_conversion (edit_data, old_data); + octave_value edit_data = octave_value (Utils::toStdString (value)); - // Inform the QTableWidget of our change - updateData (row, col, cell(row, col), - columnformat (col), columneditable (col)); - - m_curData = octave_value (cell); - emit gh_set_event (m_handle, "data", octave_value (cell), - false); + if (row < data.rows () && col < data.columns ()) + { + if (data.iscell ()) + { + Cell cell = data.cell_value (); + octave_value old_data = cell(row, col); + if (cell(row, col).is_string ()) + { + cell(row, col) = edit_data; + if (edit_data.string_value () != old_data.string_value ()) + { + m_curData = octave_value (cell); + emit gh_set_event (m_handle, "data", octave_value (cell), + false); + } - octave_value error = octave_value (""); - sendCellEditCallback (row, - col, - old_data, - cell(row, col), - edit_data, - error); - ok = true; - } - } - else - { - octave_value old_data = data.is_matrix_type () - ? data.fast_elem_extract (row + col * data.rows ()) - : octave_value (); - data.fast_elem_insert (row + col * data.rows (), - attempt_type_conversion (edit_data, old_data)); + octave_value error = octave_value (""); + sendCellEditCallback (row, col, + old_data, + edit_data, + edit_data, + error); + ok = true; + } + else + { + cell(row, col) = attempt_type_conversion (edit_data, old_data); - // Inform the QTableWidget of our change - updateData (row, - col, - data.fast_elem_extract (row + col * data.rows ()), - columnformat (col), - columneditable (col)); + // Inform the QTableWidget of our change + updateData (row, col, cell(row, col), + columnformat (col), columneditable (col)); - m_curData = octave_value (data); - emit gh_set_event (m_handle, "data", data, false); + m_curData = octave_value (cell); + emit gh_set_event (m_handle, "data", octave_value (cell), + false); - octave_value error = octave_value (""); - sendCellEditCallback (row, - col, - old_data, - data.fast_elem_extract (row + col * data.rows ()), - edit_data, - error); - ok = true; - } - } - else - { - // Reset the QTableWidgetItem - updateData (row, col, octave_value (""), columnformat (col), - columneditable (col)); + octave_value error = octave_value (""); + sendCellEditCallback (row, + col, + old_data, + cell(row, col), + edit_data, + error); + ok = true; + } + } + else + { + octave_value old_data = data.is_matrix_type () + ? data.fast_elem_extract (row + col * data.rows ()) + : octave_value (); + data.fast_elem_insert (row + col * data.rows (), + attempt_type_conversion (edit_data, old_data)); - octave_value error = - octave_value ("Table data is not editable at this location."); - sendCellEditCallback (row, - col, - octave_value (), - octave_value (), - edit_data, - error); - } + // Inform the QTableWidget of our change + updateData (row, + col, + data.fast_elem_extract (row + col * data.rows ()), + columnformat (col), + columneditable (col)); + + m_curData = octave_value (data); + emit gh_set_event (m_handle, "data", data, false); - if (! ok) - { - comboBox->setCurrentIndex (-1); - comboBox->setEditable (true); - comboBox->setEditText (comboBox->property ("original_value").toString ()); - comboBox->lineEdit ()->setReadOnly (true); - } - m_blockUpdates = false; -} - -void -Table::checkBoxClicked (int row, int col, QCheckBox *checkBox) -{ - if (m_blockUpdates) - return; - m_blockUpdates = true; - - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - octave::autolock guard (gh_mgr.graphics_lock ()); - - bool new_value = ! checkBox->isChecked (); + octave_value error = octave_value (""); + sendCellEditCallback (row, + col, + old_data, + data.fast_elem_extract (row + col * data.rows ()), + edit_data, + error); + ok = true; + } + } + else + { + // Reset the QTableWidgetItem + updateData (row, col, octave_value (""), columnformat (col), + columneditable (col)); - octave_value data = octave_value (m_curData); - if (data.islogical ()) - { - // EASY WE JUST CONVERT - boolMatrix matrix = data.bool_matrix_value (); - if (row < matrix.rows () && col < matrix.columns ()) - { - bool old_value = matrix(row, col); - matrix(row, col) = new_value; - checkBox->setChecked (new_value); - if (new_value != old_value) - { - m_curData = octave_value (matrix); - emit gh_set_event (m_handle, "data", octave_value (matrix), - false); - } + octave_value error = + octave_value ("Table data is not editable at this location."); + sendCellEditCallback (row, + col, + octave_value (), + octave_value (), + edit_data, + error); + } - sendCellEditCallback (row, col, - octave_value (old_value), - octave_value (new_value), - octave_value (new_value), - octave_value ("")); + if (! ok) + { + comboBox->setCurrentIndex (-1); + comboBox->setEditable (true); + comboBox->setEditText (comboBox->property ("original_value").toString ()); + comboBox->lineEdit ()->setReadOnly (true); + } + m_blockUpdates = false; + } + + void + Table::checkBoxClicked (int row, int col, QCheckBox *checkBox) + { + if (m_blockUpdates) + return; + m_blockUpdates = true; - } - else - { - sendCellEditCallback (row, - col, - octave_value (), - octave_value (), - octave_value (new_value), - octave_value ("Table data is not editable at this location.")); - } - } - else if (data.iscell ()) - { - Cell cell = data.cell_value (); - if (row < cell.rows () && col < cell.columns ()) - { - if (cell(row, col).islogical ()) - { - bool old_value = cell(row, col).bool_value (); - cell(row, col) = octave_value (new_value); - checkBox->setChecked (new_value); - if (new_value != old_value) - { - m_curData = octave_value (cell); - emit gh_set_event (m_handle, "data", octave_value (cell), - false); - } + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + octave::autolock guard (gh_mgr.graphics_lock ()); + + bool new_value = ! checkBox->isChecked (); + + octave_value data = octave_value (m_curData); + if (data.islogical ()) + { + // EASY WE JUST CONVERT + boolMatrix matrix = data.bool_matrix_value (); + if (row < matrix.rows () && col < matrix.columns ()) + { + bool old_value = matrix(row, col); + matrix(row, col) = new_value; + checkBox->setChecked (new_value); + if (new_value != old_value) + { + m_curData = octave_value (matrix); + emit gh_set_event (m_handle, "data", octave_value (matrix), + false); + } + + sendCellEditCallback (row, col, + octave_value (old_value), + octave_value (new_value), + octave_value (new_value), + octave_value ("")); - sendCellEditCallback (row, - col, - octave_value (old_value), - octave_value (new_value), - octave_value (new_value), - octave_value ("")); - } - else - { - sendCellEditCallback (row, - col, - cell(row, col), - octave_value (), - octave_value (new_value), - octave_value ("Cannot convert logical edit to other type.")); - } - } - else - { - sendCellEditCallback (row, - col, - cell(row, col), - octave_value (), - octave_value (new_value), - octave_value ("Table data is not editable at this location.")); - } - } - else if (data.is_matrix_type ()) - { - if (row < data.rows () && col < data.columns ()) - { - sendCellEditCallback (row, - col, - data.fast_elem_extract (row + col * data.rows ()), - octave_value (), - octave_value (new_value), - octave_value ("Cannot convert logical edit to other type.")); - } - else - { - sendCellEditCallback (row, - col, - data.fast_elem_extract (row + col * data.rows ()), - octave_value (), - octave_value (new_value), - octave_value ("Table data is not editable at this location.")); - } - } - m_blockUpdates = false; -} + } + else + { + sendCellEditCallback (row, + col, + octave_value (), + octave_value (), + octave_value (new_value), + octave_value ("Table data is not editable at this location.")); + } + } + else if (data.iscell ()) + { + Cell cell = data.cell_value (); + if (row < cell.rows () && col < cell.columns ()) + { + if (cell(row, col).islogical ()) + { + bool old_value = cell(row, col).bool_value (); + cell(row, col) = octave_value (new_value); + checkBox->setChecked (new_value); + if (new_value != old_value) + { + m_curData = octave_value (cell); + emit gh_set_event (m_handle, "data", octave_value (cell), + false); + } -void -Table::itemChanged (QTableWidgetItem *item) -{ - if (m_blockUpdates) - return; - m_blockUpdates = true; - - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - octave::autolock guard (gh_mgr.graphics_lock ()); - - octave_value data = octave_value (m_curData); - - int row = item->row (); - int col = item->column (); - octave_value edit_data = octave_value (Utils::toStdString (item->text ())); - octave_value new_value; - octave_value old_value; - octave_value new_data; + sendCellEditCallback (row, + col, + octave_value (old_value), + octave_value (new_value), + octave_value (new_value), + octave_value ("")); + } + else + { + sendCellEditCallback (row, + col, + cell(row, col), + octave_value (), + octave_value (new_value), + octave_value ("Cannot convert logical edit to other type.")); + } + } + else + { + sendCellEditCallback (row, + col, + cell(row, col), + octave_value (), + octave_value (new_value), + octave_value ("Table data is not editable at this location.")); + } + } + else if (data.is_matrix_type ()) + { + if (row < data.rows () && col < data.columns ()) + { + sendCellEditCallback (row, + col, + data.fast_elem_extract (row + col * data.rows ()), + octave_value (), + octave_value (new_value), + octave_value ("Cannot convert logical edit to other type.")); + } + else + { + sendCellEditCallback (row, + col, + data.fast_elem_extract (row + col * data.rows ()), + octave_value (), + octave_value (new_value), + octave_value ("Table data is not editable at this location.")); + } + } + m_blockUpdates = false; + } - if (row < data.rows () && col < data.columns ()) - { - if (data.iscell ()) - { - old_value = data.cell_value () (row, col); - } - else if (data.is_matrix_type ()) - { - old_value = data.fast_elem_extract (row + col * data.rows ()); - } + void + Table::itemChanged (QTableWidgetItem *item) + { + if (m_blockUpdates) + return; + m_blockUpdates = true; + + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + + octave::autolock guard (gh_mgr.graphics_lock ()); + + octave_value data = octave_value (m_curData); - // Now we need to coerce the new_value in to the type of the old_value - if (old_value.is_string ()) - new_value = edit_data; - else - { - new_value = attempt_type_conversion (edit_data, old_value); - std::pair flag_and_text = - qStringValueFor (new_value, columnformat (col)); - item->setTextAlignment (flag_and_text.first); - item->setText (flag_and_text.second); - } + int row = item->row (); + int col = item->column (); + octave_value edit_data = octave_value (Utils::toStdString (item->text ())); + octave_value new_value; + octave_value old_value; + octave_value new_data; + + if (row < data.rows () && col < data.columns ()) + { + if (data.iscell ()) + { + old_value = data.cell_value () (row, col); + } + else if (data.is_matrix_type ()) + { + old_value = data.fast_elem_extract (row + col * data.rows ()); + } - if (data.iscell ()) - { - Cell cell = data.cell_value (); - cell(row, col) = new_value; - new_data = octave_value (cell); - } - else - { - data.fast_elem_insert (row + col * data.rows (), new_value); - new_data = data; - } - m_curData = octave_value (new_data); - emit gh_set_event (m_handle, "data", new_data, false); + // Now we need to coerce the new_value in to the type of the old_value + if (old_value.is_string ()) + new_value = edit_data; + else + { + new_value = attempt_type_conversion (edit_data, old_value); + std::pair flag_and_text = + qStringValueFor (new_value, columnformat (col)); + item->setTextAlignment (flag_and_text.first); + item->setText (flag_and_text.second); + } + + if (data.iscell ()) + { + Cell cell = data.cell_value (); + cell(row, col) = new_value; + new_data = octave_value (cell); + } + else + { + data.fast_elem_insert (row + col * data.rows (), new_value); + new_data = data; + } + m_curData = octave_value (new_data); + emit gh_set_event (m_handle, "data", new_data, false); - sendCellEditCallback (row, - col, - octave_value (old_value), - octave_value (new_value), - octave_value (new_value), - octave_value ("")); - } - else - { - item->setText (""); + sendCellEditCallback (row, + col, + octave_value (old_value), + octave_value (new_value), + octave_value (new_value), + octave_value ("")); + } + else + { + item->setText (""); - octave_value error = - octave_value ("Table data is not editable at this location."); - sendCellEditCallback (row, - col, - octave_value (), - octave_value (), - edit_data, - error); - } + octave_value error = + octave_value ("Table data is not editable at this location."); + sendCellEditCallback (row, + col, + octave_value (), + octave_value (), + edit_data, + error); + } - m_blockUpdates = false; -} + m_blockUpdates = false; + } -void -Table::redraw (void) -{ - update (uitable::properties::ID_POSITION); -} + void + Table::redraw (void) + { + update (uitable::properties::ID_POSITION); + } -void -Table::update (int pId) -{ - uitable::properties& tp = properties (); + void + Table::update (int pId) + { + uitable::properties& tp = properties (); - switch (pId) - { - case uitable::properties::ID_BACKGROUNDCOLOR: - case uitable::properties::ID_FOREGROUNDCOLOR: - updatePalette (); - break; + switch (pId) + { + case uitable::properties::ID_BACKGROUNDCOLOR: + case uitable::properties::ID_FOREGROUNDCOLOR: + updatePalette (); + break; - case uitable::properties::ID_COLUMNNAME: - updateColumnname (); - updateColumnwidth (); - break; + case uitable::properties::ID_COLUMNNAME: + updateColumnname (); + updateColumnwidth (); + break; - case uitable::properties::ID_COLUMNWIDTH: - updateColumnwidth (); - break; + case uitable::properties::ID_COLUMNWIDTH: + updateColumnwidth (); + break; - case uitable::properties::ID_COLUMNEDITABLE: - case uitable::properties::ID_COLUMNFORMAT: - case uitable::properties::ID_DATA: - m_blockUpdates = true; - m_curData = octave_value (tp.get_data ()); - updateData (); - updateRowname (); - updateColumnname (); - updateColumnwidth (); - updateEnable (); - m_blockUpdates = false; - break; + case uitable::properties::ID_COLUMNEDITABLE: + case uitable::properties::ID_COLUMNFORMAT: + case uitable::properties::ID_DATA: + m_blockUpdates = true; + m_curData = octave_value (tp.get_data ()); + updateData (); + updateRowname (); + updateColumnname (); + updateColumnwidth (); + updateEnable (); + m_blockUpdates = false; + break; + + case uitable::properties::ID_ENABLE: + updateEnable (); + break; - case uitable::properties::ID_ENABLE: - updateEnable (); - break; + case uitable::properties::ID_KEYPRESSFCN: + m_keyPressHandlerDefined = ! tp.get_keypressfcn ().isempty (); + break; - case uitable::properties::ID_KEYPRESSFCN: - m_keyPressHandlerDefined = ! tp.get_keypressfcn ().isempty (); - break; + case uitable::properties::ID_KEYRELEASEFCN: + m_keyReleaseHandlerDefined = ! tp.get_keyreleasefcn ().isempty (); + break; - case uitable::properties::ID_KEYRELEASEFCN: - m_keyReleaseHandlerDefined = ! tp.get_keyreleasefcn ().isempty (); - break; + case uitable::properties::ID_FONTNAME: + case uitable::properties::ID_FONTSIZE: + case uitable::properties::ID_FONTWEIGHT: + case uitable::properties::ID_FONTANGLE: + if (m_tableWidget) + { + m_tableWidget->setFont (Utils::computeFont (tp)); + for (int row = 0; row < m_tableWidget->rowCount (); row++) + { + m_tableWidget->setRowHeight (row, AUTO_HEIGHT); + } + } + break; - case uitable::properties::ID_FONTNAME: - case uitable::properties::ID_FONTSIZE: - case uitable::properties::ID_FONTWEIGHT: - case uitable::properties::ID_FONTANGLE: - if (m_tableWidget) + case uitable::properties::ID_POSITION: { - m_tableWidget->setFont (Utils::computeFont (tp)); - for (int row = 0; row < m_tableWidget->rowCount (); row++) - { - m_tableWidget->setRowHeight (row, AUTO_HEIGHT); - } + Matrix bb = tp.get_boundingbox (false); + m_tableWidget->setGeometry (octave::math::round (bb(0)), + octave::math::round (bb(1)), + octave::math::round (bb(2)), + octave::math::round (bb(3))); + updateExtent (); } - break; + break; - case uitable::properties::ID_POSITION: - { - Matrix bb = tp.get_boundingbox (false); - m_tableWidget->setGeometry (octave::math::round (bb(0)), - octave::math::round (bb(1)), - octave::math::round (bb(2)), - octave::math::round (bb(3))); - updateExtent (); - } - break; + case uitable::properties::ID_REARRANGEABLECOLUMNS: + updateRearrangeableColumns (); + break; - case uitable::properties::ID_REARRANGEABLECOLUMNS: - updateRearrangeableColumns (); - break; + case uitable::properties::ID_ROWNAME: + updateRowname (); + break; - case uitable::properties::ID_ROWNAME: - updateRowname (); - break; + case uitable::properties::ID_ROWSTRIPING: + updatePalette (); + break; - case uitable::properties::ID_ROWSTRIPING: - updatePalette (); - break; + case uitable::properties::ID_TOOLTIPSTRING: + m_tableWidget->setToolTip (Utils::fromStdString (tp.get_tooltipstring ())); + break; - case uitable::properties::ID_TOOLTIPSTRING: - m_tableWidget->setToolTip (Utils::fromStdString (tp.get_tooltipstring ())); - break; + case base_properties::ID_VISIBLE: + m_tableWidget->setVisible (tp.is_visible ()); + break; - case base_properties::ID_VISIBLE: - m_tableWidget->setVisible (tp.is_visible ()); - break; - - default: - break; + default: + break; - } -} + } + } -void -Table::updateColumnname (void) -{ - uitable::properties& tp = properties (); + void + Table::updateColumnname (void) + { + uitable::properties& tp = properties (); - // Reset the Column Count - m_tableWidget->setColumnCount (tp.get_data ().columns ()); + // Reset the Column Count + m_tableWidget->setColumnCount (tp.get_data ().columns ()); - octave_value columnname = tp.get_columnname (); - QStringList l; - bool visible = true; + octave_value columnname = tp.get_columnname (); + QStringList l; + bool visible = true; - if (columnname.is_string () && columnname.string_value (false) == "numbered") - for (int i = 0; i < m_tableWidget->columnCount (); i++) - l << QString::number (i + 1); - else if (columnname.is_string ()) - { - if (m_tableWidget->columnCount () > 0) - l << Utils::fromStdString (columnname.string_value ()); - for (int i = 1; i < m_tableWidget->columnCount (); i++) - l << ""; - } - else if (columnname.isempty ()) - { + if (columnname.is_string () && columnname.string_value (false) == "numbered") for (int i = 0; i < m_tableWidget->columnCount (); i++) - l << ""; + l << QString::number (i + 1); + else if (columnname.is_string ()) + { + if (m_tableWidget->columnCount () > 0) + l << Utils::fromStdString (columnname.string_value ()); + for (int i = 1; i < m_tableWidget->columnCount (); i++) + l << ""; + } + else if (columnname.isempty ()) + { + for (int i = 0; i < m_tableWidget->columnCount (); i++) + l << ""; - visible = false; - } - else if (columnname.iscell ()) - { - octave_idx_type n = columnname.numel (); - Cell cell_value = columnname.cell_value (); - - for (octave_idx_type i = 0; i < n; i++) - { - octave_value v = cell_value (i); - if (v.is_string ()) - l << Utils::fromStdString (v.string_value (true)); - else if (v.is_matrix_type ()) - { - Matrix data = v.matrix_value (); + visible = false; + } + else if (columnname.iscell ()) + { + octave_idx_type n = columnname.numel (); + Cell cell_value = columnname.cell_value (); - /* Now Matlab does something very strange here: - * If data is a row or column matrix, - * then each datapoint is added. - * Otherwise, nothing is set. - */ - if (data.rows () > 1 && data.cols () > 1) - l << ""; - else - for (octave_idx_type j = 0; j < data.numel (); j++) - l << QString::number (data(j)); - } - else if (v.isnumeric ()) - l << QString::number (v.double_value ()); - else - l << QString::number (v.double_value ()); - } - } - else if (columnname.is_matrix_type ()) - { - octave_idx_type n = columnname.numel (); - Matrix matrix_value = columnname.matrix_value (); + for (octave_idx_type i = 0; i < n; i++) + { + octave_value v = cell_value (i); + if (v.is_string ()) + l << Utils::fromStdString (v.string_value (true)); + else if (v.is_matrix_type ()) + { + Matrix data = v.matrix_value (); - for (octave_idx_type i = 0; i < n; i++) - l << QString::number (matrix_value(i)); - } - else - { - for (int i = 0; i < m_tableWidget->columnCount (); i++) - l << ""; - visible = false; - } - - l.replaceInStrings ("|", "\n"); - - // Now add the columns as required - if (m_tableWidget->columnCount () < l.length ()) - { - int oldColumnCount = m_tableWidget->columnCount (); - m_tableWidget->setColumnCount (l.length ()); - for (int col = oldColumnCount; col < l.length (); col++) - { - std::string format = columnformat (col); - bool enabled = columneditable (col); - - for (int row = 0; row < m_tableWidget->rowCount (); row++) - updateData (row, col, octave_value (""), format, enabled); - } - } + /* Now Matlab does something very strange here: + * If data is a row or column matrix, + * then each datapoint is added. + * Otherwise, nothing is set. + */ + if (data.rows () > 1 && data.cols () > 1) + l << ""; + else + for (octave_idx_type j = 0; j < data.numel (); j++) + l << QString::number (data(j)); + } + else if (v.isnumeric ()) + l << QString::number (v.double_value ()); + else + l << QString::number (v.double_value ()); + } + } + else if (columnname.is_matrix_type ()) + { + octave_idx_type n = columnname.numel (); + Matrix matrix_value = columnname.matrix_value (); - m_tableWidget->setHorizontalHeaderLabels (l); - m_tableWidget->horizontalHeader ()->setVisible (visible); -} - -void -Table::updateColumnwidth (void) -{ - uitable::properties& tp = properties (); - - octave_value columnwidth = tp.get_columnwidth (); - if (columnwidth.isempty () - || (columnwidth.is_string () - && columnwidth.string_value (false) == "auto")) - for (int i = 0; i < m_tableWidget->columnCount (); i++) - m_tableWidget->setColumnWidth (i, AUTO_WIDTH); - else if (columnwidth.is_string () - && columnwidth.string_value (false) == "preferred") - for (int i = 0; i < m_tableWidget->columnCount (); i++) + for (octave_idx_type i = 0; i < n; i++) + l << QString::number (matrix_value(i)); + } + else { - int column_size = - (qobject_cast (m_tableWidget))->sizeHintForColumn (i); - int header_size = m_tableWidget->horizontalHeader ()->sectionSizeHint (i); - - if (column_size > header_size) - header_size = column_size; - m_tableWidget->setColumnWidth (i, header_size); + for (int i = 0; i < m_tableWidget->columnCount (); i++) + l << ""; + visible = false; } - else if (columnwidth.iscell ()) - { - Cell cell_value = columnwidth.cell_value (); - int i = 0; - for (; i < m_tableWidget->columnCount () && i < cell_value.numel (); i++) - { - octave_value v = cell_value (i); - if (v.is_string () && v.string_value (false) == "auto") - m_tableWidget->setColumnWidth (i, AUTO_WIDTH); - else if (v.is_string () && v.string_value (false) == "preferred") - { - int column_size = - (qobject_cast (m_tableWidget))->sizeHintForColumn (i); - int header_size = m_tableWidget->horizontalHeader ()->sectionSizeHint (i); + + l.replaceInStrings ("|", "\n"); + + // Now add the columns as required + if (m_tableWidget->columnCount () < l.length ()) + { + int oldColumnCount = m_tableWidget->columnCount (); + m_tableWidget->setColumnCount (l.length ()); + for (int col = oldColumnCount; col < l.length (); col++) + { + std::string format = columnformat (col); + bool enabled = columneditable (col); + + for (int row = 0; row < m_tableWidget->rowCount (); row++) + updateData (row, col, octave_value (""), format, enabled); + } + } - if (column_size > header_size) - header_size = column_size; - m_tableWidget->setColumnWidth (i, header_size); - } - else - { - int w = int (v.double_value ()); - m_tableWidget->setColumnWidth (i, w); - } - } - for (; i < m_tableWidget->columnCount (); i++) + m_tableWidget->setHorizontalHeaderLabels (l); + m_tableWidget->horizontalHeader ()->setVisible (visible); + } + + void + Table::updateColumnwidth (void) + { + uitable::properties& tp = properties (); + + octave_value columnwidth = tp.get_columnwidth (); + if (columnwidth.isempty () + || (columnwidth.is_string () + && columnwidth.string_value (false) == "auto")) + for (int i = 0; i < m_tableWidget->columnCount (); i++) + m_tableWidget->setColumnWidth (i, AUTO_WIDTH); + else if (columnwidth.is_string () + && columnwidth.string_value (false) == "preferred") + for (int i = 0; i < m_tableWidget->columnCount (); i++) { int column_size = (qobject_cast (m_tableWidget))->sizeHintForColumn (i); @@ -1138,594 +1101,629 @@ header_size = column_size; m_tableWidget->setColumnWidth (i, header_size); } - } - else if (columnwidth.is_matrix_type ()) - { - Matrix matrix_value = columnwidth.matrix_value (); - int i = 0; - for (; i < m_tableWidget->columnCount () && i < matrix_value.numel (); i++) - { - octave_value v = matrix_value(i); - int w = int (v.double_value ()); - m_tableWidget->setColumnWidth (i, w); - } - for (; i < m_tableWidget->columnCount (); i++) - m_tableWidget->setColumnWidth (i, AUTO_WIDTH); - } -} + else if (columnwidth.iscell ()) + { + Cell cell_value = columnwidth.cell_value (); + int i = 0; + for (; i < m_tableWidget->columnCount () && i < cell_value.numel (); i++) + { + octave_value v = cell_value (i); + if (v.is_string () && v.string_value (false) == "auto") + m_tableWidget->setColumnWidth (i, AUTO_WIDTH); + else if (v.is_string () && v.string_value (false) == "preferred") + { + int column_size = + (qobject_cast (m_tableWidget))->sizeHintForColumn (i); + int header_size = m_tableWidget->horizontalHeader ()->sectionSizeHint (i); -bool inline -Table::columneditable (int col) -{ - uitable::properties& tp = properties (); - boolNDArray columneditable = tp.get_columneditable ().bool_array_value (); - bool editable = false; + if (column_size > header_size) + header_size = column_size; + m_tableWidget->setColumnWidth (i, header_size); + } + else + { + int w = int (v.double_value ()); + m_tableWidget->setColumnWidth (i, w); + } + } + for (; i < m_tableWidget->columnCount (); i++) + { + int column_size = + (qobject_cast (m_tableWidget))->sizeHintForColumn (i); + int header_size = m_tableWidget->horizontalHeader ()->sectionSizeHint (i); - if (! columneditable.isempty () && col < columneditable.numel ()) - editable = columneditable.xelem (col); - else if (! columneditable.isempty () && columneditable.numel () == 1) - editable = columneditable.xelem (0); + if (column_size > header_size) + header_size = column_size; + m_tableWidget->setColumnWidth (i, header_size); + } + } + else if (columnwidth.is_matrix_type ()) + { + Matrix matrix_value = columnwidth.matrix_value (); + int i = 0; + for (; i < m_tableWidget->columnCount () && i < matrix_value.numel (); i++) + { + octave_value v = matrix_value(i); + int w = int (v.double_value ()); + m_tableWidget->setColumnWidth (i, w); + } + for (; i < m_tableWidget->columnCount (); i++) + m_tableWidget->setColumnWidth (i, AUTO_WIDTH); + } + } - return editable; -} + bool inline + Table::columneditable (int col) + { + uitable::properties& tp = properties (); + boolNDArray columneditable = tp.get_columneditable ().bool_array_value (); + bool editable = false; -std::string inline -Table::columnformat (int col) -{ - uitable::properties& tp = properties (); - std::string format = ""; - octave_value ov_columnformat = tp.get_columnformat (); + if (! columneditable.isempty () && col < columneditable.numel ()) + editable = columneditable.xelem (col); + else if (! columneditable.isempty () && columneditable.numel () == 1) + editable = columneditable.xelem (0); + + return editable; + } - if (ov_columnformat.iscell ()) - { - Cell columnformat = ov_columnformat.cell_value (); - if (! columnformat.isempty () && col < columnformat.numel ()) - { - octave_value format_value = columnformat.xelem (col); + std::string inline + Table::columnformat (int col) + { + uitable::properties& tp = properties (); + std::string format = ""; + octave_value ov_columnformat = tp.get_columnformat (); + + if (ov_columnformat.iscell ()) + { + Cell columnformat = ov_columnformat.cell_value (); + if (! columnformat.isempty () && col < columnformat.numel ()) + { + octave_value format_value = columnformat.xelem (col); - if (! format_value.isempty () && format_value.is_string ()) - format = format_value.string_value (); - else if (! format_value.isempty () && format_value.iscell ()) - format = "popup"; - } - } - else if (ov_columnformat.is_string ()) - { - format = ov_columnformat.string_value (); - } - return format; -} + if (! format_value.isempty () && format_value.is_string ()) + format = format_value.string_value (); + else if (! format_value.isempty () && format_value.iscell ()) + format = "popup"; + } + } + else if (ov_columnformat.is_string ()) + { + format = ov_columnformat.string_value (); + } + return format; + } + + void inline + Table::updateDataColumn (int col) + { + octave_value data = properties ().get_data (); -void inline -Table::updateDataColumn (int col) -{ - octave_value data = properties ().get_data (); + std::string format = columnformat (col); + bool is_editable = columneditable (col); - std::string format = columnformat (col); - bool is_editable = columneditable (col); + for (octave_idx_type row = 0; row < data.rows (); row++) + updateData (row, + col, + data.iscell () + ? data.cell_value () (row, col) + : data.fast_elem_extract (row + col * data.rows ()), + format, + is_editable); + } - for (octave_idx_type row = 0; row < data.rows (); row++) + void inline + Table::updateData (int row, int col) + { + octave_value data = properties ().get_data (); updateData (row, col, data.iscell () ? data.cell_value () (row, col) : data.fast_elem_extract (row + col * data.rows ()), - format, - is_editable); -} + columnformat (col), + columneditable (col)); + } + + void inline + Table::updateData (int row, int col, octave_value value, + std::string format = "", bool enabled = false) + { + if (format == "logical" || (format == "" && value.islogical ())) + { + if (m_tableWidget->item (row, col)) + delete m_tableWidget->item (row, col); + + m_tableWidget->setCellWidget (row, col, checkBoxForLogical (value, enabled)); + m_tableWidget->cellWidget (row, col)->setProperty ("row", QVariant (row)); + m_tableWidget->cellWidget (row, col)->setProperty ("col", QVariant (col)); + } + else if (format == "popup" && enabled) + { + if (m_tableWidget->item (row, col)) + delete m_tableWidget->item (row, col); + + QString string_value = qStringValueFor (value, format).second; + uitable::properties& tp = properties (); + octave_value format_value = tp.get_columnformat ().cell_value ().xelem (col); + + QComboBox *comboBox = new QComboBox (); + comboBox->setProperty ("row", QVariant (row)); + comboBox->setProperty ("col", QVariant (col)); -void inline -Table::updateData (int row, int col) -{ - octave_value data = properties ().get_data (); - updateData (row, - col, - data.iscell () - ? data.cell_value () (row, col) - : data.fast_elem_extract (row + col * data.rows ()), - columnformat (col), - columneditable (col)); -} + int index = -1; + for (int k = 0; k < format_value.numel (); k++) + { + QString popup_item + = Utils::fromStdString (format_value.fast_elem_extract (k).string_value ()); + + comboBox->addItem (popup_item); + + if (popup_item == string_value) + index = k; + } + comboBox->setCurrentIndex (index); -void inline -Table::updateData (int row, int col, octave_value value, - std::string format = "", bool enabled = false) -{ - if (format == "logical" || (format == "" && value.islogical ())) - { - if (m_tableWidget->item (row, col)) - delete m_tableWidget->item (row, col); + if (index < 0) + { + comboBox->setEditable (true); + comboBox->setEditText (string_value); + comboBox->lineEdit ()->setReadOnly (true); + } + + comboBox->setProperty ("original_value", QVariant (string_value)); + + comboBox->installEventFilter (this); + m_tableWidget->setCellWidget (row, col, comboBox); + connect (comboBox, SIGNAL(currentIndexChanged (const QString&)), + this, SLOT(comboBoxCurrentIndexChanged (const QString&))); + } + else + { + if (m_tableWidget->cellWidget (row, col)) + delete m_tableWidget->cellWidget (row, col); + m_tableWidget->setItem (row, col, itemFor (value, format, enabled)); + } + } - m_tableWidget->setCellWidget (row, col, checkBoxForLogical (value, enabled)); - m_tableWidget->cellWidget (row, col)->setProperty ("row", QVariant (row)); - m_tableWidget->cellWidget (row, col)->setProperty ("col", QVariant (col)); - } - else if (format == "popup" && enabled) - { - if (m_tableWidget->item (row, col)) - delete m_tableWidget->item (row, col); + void + Table::updateData () + { + uitable::properties& tp = properties (); + + octave_value data = tp.get_data (); + + if (data.iscell () || data.is_matrix_type ()) + { + m_tableWidget->setRowCount (data.rows ()); + m_tableWidget->setColumnCount (data.columns ()); - QString string_value = qStringValueFor (value, format).second; - uitable::properties& tp = properties (); - octave_value format_value = tp.get_columnformat ().cell_value ().xelem (col); + for (octave_idx_type col = 0; col < data.columns (); col++) + updateDataColumn (col); + } + + for (octave_idx_type row = 0; row < m_tableWidget->rowCount (); row++) + m_tableWidget->setRowHeight (row, AUTO_HEIGHT); + } - QComboBox *comboBox = new QComboBox (); - comboBox->setProperty ("row", QVariant (row)); - comboBox->setProperty ("col", QVariant (col)); + void + Table::updateEnable (void) + { + uitable::properties& tp = properties (); + bool enabled = tp.is_enable (); + m_tableWidget->setEnabled (enabled); + + bool rearrangeableColumns = tp.is_rearrangeablecolumns (); - int index = -1; - for (int k = 0; k < format_value.numel (); k++) - { - QString popup_item - = Utils::fromStdString (format_value.fast_elem_extract (k).string_value ()); + // Set selection mode + m_tableWidget->setSelectionMode (enabled + ? QAbstractItemView::ExtendedSelection + : QAbstractItemView::NoSelection); - comboBox->addItem (popup_item); + // Set rearrangeablecolumns + m_tableWidget->horizontalHeader ()->setSectionsMovable (enabled && rearrangeableColumns); + m_tableWidget->horizontalHeader ()->setDragEnabled (enabled && rearrangeableColumns); + m_tableWidget->horizontalHeader ()->setDragDropMode (QAbstractItemView::InternalMove); + + // Turn off column editable + for (int col = 0; col < m_tableWidget->columnCount (); col++) + { + bool editable = columneditable (col); - if (popup_item == string_value) - index = k; - } - comboBox->setCurrentIndex (index); + for (int row = 0; row < m_tableWidget->rowCount (); row++) + if (QTableWidgetItem *item = m_tableWidget->item (row, col)) + { + Qt::ItemFlags flags = item->flags (); + if (enabled && editable) + item->setFlags (flags | Qt::ItemIsEditable); + else + item->setFlags (flags & ~Qt::ItemIsEditable); + } + else if (QWidget *widget = m_tableWidget->cellWidget (row, col)) + { + QCheckBox *checkBox = nullptr; + if (widget && ! widget->children ().isEmpty ()) + { + QHBoxLayout *layout + = qobject_cast (widget->children ().first ()); - if (index < 0) - { - comboBox->setEditable (true); - comboBox->setEditText (string_value); - comboBox->lineEdit ()->setReadOnly (true); - } - - comboBox->setProperty ("original_value", QVariant (string_value)); + if (layout && layout->count () > 0) + checkBox = qobject_cast (layout->itemAt (0)-> widget ()); + } - comboBox->installEventFilter (this); - m_tableWidget->setCellWidget (row, col, comboBox); - connect (comboBox, SIGNAL(currentIndexChanged (const QString&)), - this, SLOT(comboBoxCurrentIndexChanged (const QString&))); - } - else - { - if (m_tableWidget->cellWidget (row, col)) - delete m_tableWidget->cellWidget (row, col); - m_tableWidget->setItem (row, col, itemFor (value, format, enabled)); - } -} + if (checkBox) + widget->setProperty ("Enabled", QVariant (enabled & editable)); + else + { + widget->setAttribute (Qt::WA_TransparentForMouseEvents, + !(editable & enabled)); + + widget->setFocusPolicy (Qt::NoFocus); + } + } + } + } -void -Table::updateData () -{ - uitable::properties& tp = properties (); - - octave_value data = tp.get_data (); + void + Table::updateExtent (void) + { + QSize s = realQSizeForTable (m_tableWidget); + Matrix extent = Matrix (1, 4); + extent(0, 0) = 0; + extent(0, 1) = 0; + extent(0, 2) = s.width (); + extent(0, 3) = s.height () ; + graphics_object go = object (); + emit gh_set_event (go.get_handle (), "extent", extent, false); + } - if (data.iscell () || data.is_matrix_type ()) - { - m_tableWidget->setRowCount (data.rows ()); - m_tableWidget->setColumnCount (data.columns ()); - - for (octave_idx_type col = 0; col < data.columns (); col++) - updateDataColumn (col); - } + void + Table::updatePalette (void) + { + uitable::properties& tp = properties (); - for (octave_idx_type row = 0; row < m_tableWidget->rowCount (); row++) - m_tableWidget->setRowHeight (row, AUTO_HEIGHT); -} + QPalette p = m_tableWidget->palette (); + p.setColor (QPalette::Text, + Utils::fromRgb (tp.get_foregroundcolor_rgb ())); + p.setColor (QPalette::Base, + Utils::fromRgb (tp.get_backgroundcolor_rgb ())); + p.setColor (QPalette::AlternateBase, + Utils::fromRgb (tp.get_alternatebackgroundcolor_rgb ())); + m_tableWidget->setPalette (p); + m_tableWidget->setAlternatingRowColors (tp.is_rowstriping ()); + // FIXME: Handle multiple alternating background colors + } -void -Table::updateEnable (void) -{ - uitable::properties& tp = properties (); - bool enabled = tp.is_enable (); - m_tableWidget->setEnabled (enabled); + void + Table::updateRowname (void) + { + uitable::properties& tp = properties (); - bool rearrangeableColumns = tp.is_rearrangeablecolumns (); + // Reset the row count + m_tableWidget->setRowCount (tp.get_data ().rows ()); + + octave_value rowname = tp.get_rowname (); + QStringList l; + bool visible = true; - // Set selection mode - m_tableWidget->setSelectionMode (enabled - ? QAbstractItemView::ExtendedSelection - : QAbstractItemView::NoSelection); - - // Set rearrangeablecolumns - m_tableWidget->horizontalHeader ()->setSectionsMovable (enabled && rearrangeableColumns); - m_tableWidget->horizontalHeader ()->setDragEnabled (enabled && rearrangeableColumns); - m_tableWidget->horizontalHeader ()->setDragDropMode (QAbstractItemView::InternalMove); + if (rowname.is_string () && rowname.string_value (false) == "numbered") + for (int i = 0; i < m_tableWidget->rowCount (); i++) + l << QString::number (i + 1); + else if (rowname.is_string ()) + { + if (m_tableWidget->rowCount () > 0) + l << Utils::fromStdString (rowname.string_value ()); + for (int i = 1; i < m_tableWidget->rowCount (); i++) + l << ""; + } + else if (rowname.isempty ()) + { + for (int i = 0; i < m_tableWidget->rowCount (); i++) + l << ""; + visible = false; + } + else if (rowname.iscell ()) + { + octave_idx_type n = rowname.numel (); + Cell cell_value = rowname.cell_value (); - // Turn off column editable - for (int col = 0; col < m_tableWidget->columnCount (); col++) - { - bool editable = columneditable (col); + for (octave_idx_type i = 0; i < n; i++) + { + octave_value v = cell_value (i); + if (v.is_string ()) + l << Utils::fromStdString (v.string_value (true)); + else if (v.is_matrix_type ()) + { + Matrix data = v.matrix_value (); - for (int row = 0; row < m_tableWidget->rowCount (); row++) - if (QTableWidgetItem *item = m_tableWidget->item (row, col)) - { - Qt::ItemFlags flags = item->flags (); - if (enabled && editable) - item->setFlags (flags | Qt::ItemIsEditable); + /* Now Matlab does something very strange here: + * If data is a row or column matrix, + * then each datapoint is added. + * Otherwise, nothing is set. + */ + if (data.rows () > 1 && data.cols () > 1) + l << ""; + else + for (octave_idx_type j = 0; j < data.numel (); j++) + l << QString::number (data(j)); + } + else if (v.isnumeric ()) + l << QString::number (v.double_value (true)); else - item->setFlags (flags & ~Qt::ItemIsEditable); + l << QString::number (v.double_value (true)); } - else if (QWidget *widget = m_tableWidget->cellWidget (row, col)) - { - QCheckBox *checkBox = nullptr; - if (widget && ! widget->children ().isEmpty ()) - { - QHBoxLayout *layout - = qobject_cast (widget->children ().first ()); + } + else if (rowname.is_matrix_type ()) + { + octave_idx_type n = rowname.numel (); + Matrix matrix_value = rowname.matrix_value (); - if (layout && layout->count () > 0) - checkBox = qobject_cast (layout->itemAt (0)-> widget ()); - } + for (octave_idx_type i = 0; i < n; i++) + l << QString::number (matrix_value(i)); + } + else + { + for (int i = 0; i < m_tableWidget->columnCount (); i++) + l << ""; + visible = false; + } - if (checkBox) - widget->setProperty ("Enabled", QVariant (enabled & editable)); - else + // Add dummy rows as required + if (m_tableWidget->rowCount () < l.length ()) + { + int oldRowCount = m_tableWidget->rowCount (); + m_tableWidget->setRowCount (l.length ()); + + for (int col = 0; col < m_tableWidget->columnCount (); col++) + { + std::string format = columnformat (col); + bool enabled = columneditable (col); + + for (int row = oldRowCount; row < l.length (); row++) { - widget->setAttribute (Qt::WA_TransparentForMouseEvents, - !(editable & enabled)); + m_tableWidget->setRowHeight (row, AUTO_HEIGHT); - widget->setFocusPolicy (Qt::NoFocus); + updateData (row, col, octave_value (""), format, enabled); } } - } -} + } -void -Table::updateExtent (void) -{ - QSize s = realQSizeForTable (m_tableWidget); - Matrix extent = Matrix (1, 4); - extent(0, 0) = 0; - extent(0, 1) = 0; - extent(0, 2) = s.width (); - extent(0, 3) = s.height () ; - graphics_object go = object (); - emit gh_set_event (go.get_handle (), "extent", extent, false); -} + m_tableWidget->setVerticalHeaderLabels (l); + m_tableWidget->verticalHeader ()->setVisible (visible); + } -void -Table::updatePalette (void) -{ - uitable::properties& tp = properties (); + void + Table::updateRearrangeableColumns (void) + { + uitable::properties& tp = properties (); - QPalette p = m_tableWidget->palette (); - p.setColor (QPalette::Text, - Utils::fromRgb (tp.get_foregroundcolor_rgb ())); - p.setColor (QPalette::Base, - Utils::fromRgb (tp.get_backgroundcolor_rgb ())); - p.setColor (QPalette::AlternateBase, - Utils::fromRgb (tp.get_alternatebackgroundcolor_rgb ())); - m_tableWidget->setPalette (p); - m_tableWidget->setAlternatingRowColors (tp.is_rowstriping ()); - // FIXME: Handle multiple alternating background colors -} + bool rearrangeableColumns = tp.is_rearrangeablecolumns (); + bool enabled = tp.is_enable (); -void -Table::updateRowname (void) -{ - uitable::properties& tp = properties (); + m_tableWidget->horizontalHeader ()->setSectionsMovable (enabled && rearrangeableColumns); + m_tableWidget->horizontalHeader ()->setDragEnabled (enabled && rearrangeableColumns); + m_tableWidget->horizontalHeader ()->setDragDropMode (QAbstractItemView::InternalMove); + } - // Reset the row count - m_tableWidget->setRowCount (tp.get_data ().rows ()); - - octave_value rowname = tp.get_rowname (); - QStringList l; - bool visible = true; + bool + Table::eventFilter (QObject *watched, QEvent *xevent) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - if (rowname.is_string () && rowname.string_value (false) == "numbered") - for (int i = 0; i < m_tableWidget->rowCount (); i++) - l << QString::number (i + 1); - else if (rowname.is_string ()) - { - if (m_tableWidget->rowCount () > 0) - l << Utils::fromStdString (rowname.string_value ()); - for (int i = 1; i < m_tableWidget->rowCount (); i++) - l << ""; - } - else if (rowname.isempty ()) - { - for (int i = 0; i < m_tableWidget->rowCount (); i++) - l << ""; - visible = false; - } - else if (rowname.iscell ()) - { - octave_idx_type n = rowname.numel (); - Cell cell_value = rowname.cell_value (); + //uitable::properties& tp = properties (); + if (qobject_cast (watched)) + { + switch (xevent->type ()) + { + case QEvent::Resize: + { + octave::autolock guard (gh_mgr.graphics_lock ()); - for (octave_idx_type i = 0; i < n; i++) - { - octave_value v = cell_value (i); - if (v.is_string ()) - l << Utils::fromStdString (v.string_value (true)); - else if (v.is_matrix_type ()) - { - Matrix data = v.matrix_value (); - - /* Now Matlab does something very strange here: - * If data is a row or column matrix, - * then each datapoint is added. - * Otherwise, nothing is set. - */ - if (data.rows () > 1 && data.cols () > 1) - l << ""; - else - for (octave_idx_type j = 0; j < data.numel (); j++) - l << QString::number (data(j)); + graphics_object go = object (); + if (go.valid_object ()) + { + const uitable::properties& tp = + Utils::properties (go); + if (tp.fontunits_is ("normalized")) + m_tableWidget->setFont (Utils::computeFont (tp)); + } } - else if (v.isnumeric ()) - l << QString::number (v.double_value (true)); - else - l << QString::number (v.double_value (true)); - } - } - else if (rowname.is_matrix_type ()) - { - octave_idx_type n = rowname.numel (); - Matrix matrix_value = rowname.matrix_value (); + break; - for (octave_idx_type i = 0; i < n; i++) - l << QString::number (matrix_value(i)); - } - else - { - for (int i = 0; i < m_tableWidget->columnCount (); i++) - l << ""; - visible = false; - } + case QEvent::MouseButtonPress: + { + octave::autolock guard (gh_mgr.graphics_lock ()); - // Add dummy rows as required - if (m_tableWidget->rowCount () < l.length ()) - { - int oldRowCount = m_tableWidget->rowCount (); - m_tableWidget->setRowCount (l.length ()); - - for (int col = 0; col < m_tableWidget->columnCount (); col++) - { - std::string format = columnformat (col); - bool enabled = columneditable (col); + QMouseEvent *m = dynamic_cast (xevent); + graphics_object go = object (); + const uitable::properties& tp = + Utils::properties (go); + graphics_object fig = go.get_ancestor ("figure"); - for (int row = oldRowCount; row < l.length (); row++) - { - m_tableWidget->setRowHeight (row, AUTO_HEIGHT); - - updateData (row, col, octave_value (""), format, enabled); - } - } - } - - m_tableWidget->setVerticalHeaderLabels (l); - m_tableWidget->verticalHeader ()->setVisible (visible); -} + if (m->button () != Qt::LeftButton || ! tp.is_enable ()) + { + emit gh_set_event (fig.get_handle (), "selectiontype", + Utils::figureSelectionType (m), false); + emit gh_set_event (fig.get_handle (), "currentpoint", + Utils::figureCurrentPoint (fig, m), + false); + emit gh_callback_event (fig.get_handle (), + "windowbuttondownfcn"); + emit gh_callback_event (m_handle, "buttondownfcn"); -void -Table::updateRearrangeableColumns (void) -{ - uitable::properties& tp = properties (); - - bool rearrangeableColumns = tp.is_rearrangeablecolumns (); - bool enabled = tp.is_enable (); - - m_tableWidget->horizontalHeader ()->setSectionsMovable (enabled && rearrangeableColumns); - m_tableWidget->horizontalHeader ()->setDragEnabled (enabled && rearrangeableColumns); - m_tableWidget->horizontalHeader ()->setDragDropMode (QAbstractItemView::InternalMove); -} - -bool -Table::eventFilter (QObject *watched, QEvent *xevent) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - - //uitable::properties& tp = properties (); - if (qobject_cast (watched)) - { - switch (xevent->type ()) - { - case QEvent::Resize: - { - octave::autolock guard (gh_mgr.graphics_lock ()); + if (m->button () == Qt::RightButton) + ContextMenu::executeAt (m_interpreter, properties (), + m->globalPos ()); + } + else + { + emit gh_set_event (fig.get_handle (), "selectiontype", + octave_value ("normal"), false); + } + } + break; - graphics_object go = object (); - if (go.valid_object ()) - { - const uitable::properties& tp = - Utils::properties (go); - if (tp.fontunits_is ("normalized")) - m_tableWidget->setFont (Utils::computeFont (tp)); - } - } - break; + case QEvent::KeyPress: + { + QKeyEvent *k = dynamic_cast (xevent); + if (m_keyPressHandlerDefined) + { + octave::autolock guard (gh_mgr.graphics_lock ()); - case QEvent::MouseButtonPress: - { - octave::autolock guard (gh_mgr.graphics_lock ()); + octave_scalar_map keyData = Utils::makeKeyEventStruct (k); + graphics_object fig = object ().get_ancestor ("figure"); - QMouseEvent *m = dynamic_cast (xevent); - graphics_object go = object (); - const uitable::properties& tp = - Utils::properties (go); - graphics_object fig = go.get_ancestor ("figure"); + emit gh_set_event (fig.get_handle (), "currentcharacter", + keyData.getfield ("Character"), false); + emit gh_callback_event (m_handle, "keypressfcn", keyData); + } + int row = m_tableWidget->currentRow (); + int col = m_tableWidget->currentColumn (); + switch (k->key ()) + { + case Qt::Key_Space: + { + QCheckBox *checkBox = nullptr; - if (m->button () != Qt::LeftButton || ! tp.is_enable ()) - { - emit gh_set_event (fig.get_handle (), "selectiontype", - Utils::figureSelectionType (m), false); - emit gh_set_event (fig.get_handle (), "currentpoint", - Utils::figureCurrentPoint (fig, m), - false); - emit gh_callback_event (fig.get_handle (), - "windowbuttondownfcn"); - emit gh_callback_event (m_handle, "buttondownfcn"); + QWidget *widget + = qobject_cast (m_tableWidget->cellWidget (row, col)); - if (m->button () == Qt::RightButton) - ContextMenu::executeAt (m_interpreter, properties (), - m->globalPos ()); - } - else - { - emit gh_set_event (fig.get_handle (), "selectiontype", - octave_value ("normal"), false); - } - } - break; + if (widget && ! widget->children ().isEmpty ()) + { + QHBoxLayout *layout + = qobject_cast (widget->children ().first ()); + + if (layout && layout->count () > 0) + checkBox = qobject_cast (layout->itemAt (0)-> widget ()); + } - case QEvent::KeyPress: - { - QKeyEvent *k = dynamic_cast (xevent); - if (m_keyPressHandlerDefined) - { - octave::autolock guard (gh_mgr.graphics_lock ()); - - octave_scalar_map keyData = Utils::makeKeyEventStruct (k); - graphics_object fig = object ().get_ancestor ("figure"); + if (checkBox && checkBox->property ("Enabled").toBool ()) + checkBoxClicked (row, col, checkBox); - emit gh_set_event (fig.get_handle (), "currentcharacter", - keyData.getfield ("Character"), false); - emit gh_callback_event (m_handle, "keypressfcn", keyData); - } - int row = m_tableWidget->currentRow (); - int col = m_tableWidget->currentColumn (); - switch (k->key ()) - { - case Qt::Key_Space: - { - QCheckBox *checkBox = nullptr; + QComboBox *comboBox + = qobject_cast (m_tableWidget->cellWidget (row, col)); - QWidget *widget - = qobject_cast (m_tableWidget->cellWidget (row, col)); + if (comboBox) + comboBox->showPopup (); + } + break; - if (widget && ! widget->children ().isEmpty ()) - { - QHBoxLayout *layout - = qobject_cast (widget->children ().first ()); - - if (layout && layout->count () > 0) - checkBox = qobject_cast (layout->itemAt (0)-> widget ()); - } - - if (checkBox && checkBox->property ("Enabled").toBool ()) - checkBoxClicked (row, col, checkBox); - - QComboBox *comboBox - = qobject_cast (m_tableWidget->cellWidget (row, col)); - - if (comboBox) - comboBox->showPopup (); - } - break; - - case Qt::Key_Return: - case Qt::Key_Enter: - { - if (k->modifiers () == Qt::NoModifier) - { - if (row + 1 < m_tableWidget->rowCount ()) - m_tableWidget->setCurrentCell (row + 1, col); - else - { - if (col + 1 < m_tableWidget->columnCount ()) - m_tableWidget->setCurrentCell (0, col + 1); - else - m_tableWidget->setCurrentCell (0, 0); - } - } - else if (k->modifiers () == Qt::ShiftModifier) - { - if (row - 1 >= 0) - m_tableWidget->setCurrentCell (row - 1, col); - else - { - if (col - 1 >= 0) - m_tableWidget->setCurrentCell + case Qt::Key_Return: + case Qt::Key_Enter: + { + if (k->modifiers () == Qt::NoModifier) + { + if (row + 1 < m_tableWidget->rowCount ()) + m_tableWidget->setCurrentCell (row + 1, col); + else + { + if (col + 1 < m_tableWidget->columnCount ()) + m_tableWidget->setCurrentCell (0, col + 1); + else + m_tableWidget->setCurrentCell (0, 0); + } + } + else if (k->modifiers () == Qt::ShiftModifier) + { + if (row - 1 >= 0) + m_tableWidget->setCurrentCell (row - 1, col); + else + { + if (col - 1 >= 0) + m_tableWidget->setCurrentCell (m_tableWidget->rowCount () - 1, col - 1); - else - m_tableWidget->setCurrentCell + else + m_tableWidget->setCurrentCell (m_tableWidget->rowCount () - 1, m_tableWidget->columnCount () - 1); + } + } + } + break; + + default: + break; + } + } + break; + + case QEvent::KeyRelease: + { + if (m_keyReleaseHandlerDefined) + { + octave::autolock guard (gh_mgr.graphics_lock ()); + + QKeyEvent *k = dynamic_cast (xevent); + + octave_scalar_map keyData = Utils::makeKeyEventStruct (k); + graphics_object fig = object ().get_ancestor ("figure"); + + emit gh_set_event (fig.get_handle (), "currentcharacter", + keyData.getfield ("Character"), false); + emit gh_callback_event (m_handle, "keyreleasefcn", keyData); + } + } + break; + + default: + break; + } + } + else if (qobject_cast (watched)) + { + switch (xevent->type ()) + { + case QEvent::MouseButtonPress: + { + octave::autolock guard (gh_mgr.graphics_lock ()); + + QMouseEvent *m = dynamic_cast (xevent); + graphics_object go = object (); + const uitable::properties& tp = Utils::properties (go); + graphics_object fig = go.get_ancestor ("figure"); + + if (m->button () != Qt::LeftButton || ! tp.is_enable ()) + { + emit gh_set_event (fig.get_handle (), "selectiontype", + Utils::figureSelectionType (m), false); + emit gh_set_event (fig.get_handle (), "currentpoint", + Utils::figureCurrentPoint (fig, m), + false); + emit gh_callback_event (fig.get_handle (), + "windowbuttondownfcn"); + emit gh_callback_event (m_handle, "buttondownfcn"); + + if (m->button () == Qt::RightButton) + ContextMenu::executeAt (m_interpreter, tp, m->globalPos ()); + } + else + { + emit gh_set_event (fig.get_handle (), "selectiontype", + Utils::figureSelectionType (m), false); + + QComboBox *comboBox_0 = qobject_cast (watched); + for (int row = 0; row < m_tableWidget->rowCount (); row++) + { + for (int col = 0; col < m_tableWidget->columnCount (); col++) + { + QComboBox *comboBox_1 + = qobject_cast (m_tableWidget->cellWidget (row, col)); + + if (comboBox_0 == comboBox_1) + m_tableWidget->setCurrentCell (row, col); } } } - break; - - default: - break; - } - } - break; - - case QEvent::KeyRelease: - { - if (m_keyReleaseHandlerDefined) - { - octave::autolock guard (gh_mgr.graphics_lock ()); - - QKeyEvent *k = dynamic_cast (xevent); - - octave_scalar_map keyData = Utils::makeKeyEventStruct (k); - graphics_object fig = object ().get_ancestor ("figure"); - - emit gh_set_event (fig.get_handle (), "currentcharacter", - keyData.getfield ("Character"), false); - emit gh_callback_event (m_handle, "keyreleasefcn", keyData); - } - } - break; - - default: - break; - } - } - else if (qobject_cast (watched)) - { - switch (xevent->type ()) - { - case QEvent::MouseButtonPress: - { - octave::autolock guard (gh_mgr.graphics_lock ()); + } + break; - QMouseEvent *m = dynamic_cast (xevent); - graphics_object go = object (); - const uitable::properties& tp = Utils::properties (go); - graphics_object fig = go.get_ancestor ("figure"); - - if (m->button () != Qt::LeftButton || ! tp.is_enable ()) - { - emit gh_set_event (fig.get_handle (), "selectiontype", - Utils::figureSelectionType (m), false); - emit gh_set_event (fig.get_handle (), "currentpoint", - Utils::figureCurrentPoint (fig, m), - false); - emit gh_callback_event (fig.get_handle (), - "windowbuttondownfcn"); - emit gh_callback_event (m_handle, "buttondownfcn"); - - if (m->button () == Qt::RightButton) - ContextMenu::executeAt (m_interpreter, tp, m->globalPos ()); - } - else - { - emit gh_set_event (fig.get_handle (), "selectiontype", - Utils::figureSelectionType (m), false); - - QComboBox *comboBox_0 = qobject_cast (watched); - for (int row = 0; row < m_tableWidget->rowCount (); row++) - { - for (int col = 0; col < m_tableWidget->columnCount (); col++) - { - QComboBox *comboBox_1 - = qobject_cast (m_tableWidget->cellWidget (row, col)); - - if (comboBox_0 == comboBox_1) - m_tableWidget->setCurrentCell (row, col); - } - } - } + default: + break; } - break; - - default: - break; - } - } - return false; -} + } + return false; + } #undef AUTO_HEIGHT diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/Table.h --- a/libgui/graphics/Table.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/Table.h Tue Dec 06 15:45:27 2022 -0500 @@ -34,65 +34,64 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; + + class Container; -class Container; - -class Table : public Object -{ - Q_OBJECT + class Table : public Object + { + Q_OBJECT -public: - Table (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QTableWidget *tableWidget); - ~Table (void); + public: + Table (octave::interpreter& interp, + const graphics_object& go, QTableWidget *tableWidget); + ~Table (void); - Container * innerContainer (void) { return m_container; } + Container * innerContainer (void) { return m_container; } - bool eventFilter (QObject *watched, QEvent *event); + bool eventFilter (QObject *watched, QEvent *event); - static Table * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + static Table * + create (octave::interpreter& interp, + const graphics_object& go); -protected: - void update (int pId); - void redraw (void); - void updateColumnname (void); - void updateColumnwidth (void); - void updateData (void); - void updateEnable (void); - void updateExtent (void); - void updatePalette (void); - void updateRearrangeableColumns (void); - void updateRowname (void); + protected: + void update (int pId); + void redraw (void); + void updateColumnname (void); + void updateColumnwidth (void); + void updateData (void); + void updateEnable (void); + void updateExtent (void); + void updatePalette (void); + void updateRearrangeableColumns (void); + void updateRowname (void); -private slots: - void itemChanged (QTableWidgetItem *item); - void comboBoxCurrentIndexChanged (const QString& value); - void cellClicked (int row, int col); - void itemSelectionChanged (void); + private slots: + void itemChanged (QTableWidgetItem *item); + void comboBoxCurrentIndexChanged (const QString& value); + void cellClicked (int row, int col); + void itemSelectionChanged (void); -private: - Container *m_container; - QTableWidget *m_tableWidget; - octave_value m_curData; - bool m_blockUpdates; - bool m_keyPressHandlerDefined; - bool m_keyReleaseHandlerDefined; - QWidget * checkBoxForLogical(octave_value cal, bool enabled); - void updateData (int row, int col, octave_value value, std::string format, - bool enabled); - void updateData (int row, int col); - void updateDataColumn (int col); - std::string columnformat (int column); - bool columneditable (int column); - void sendCellEditCallback (int row, int col, octave_value old_value, - octave_value new_value, octave_value edit_data, octave_value error); - void checkBoxClicked (int row, int col, QCheckBox* checkBox); + private: + Container *m_container; + QTableWidget *m_tableWidget; + octave_value m_curData; + bool m_blockUpdates; + bool m_keyPressHandlerDefined; + bool m_keyReleaseHandlerDefined; + QWidget * checkBoxForLogical(octave_value cal, bool enabled); + void updateData (int row, int col, octave_value value, std::string format, + bool enabled); + void updateData (int row, int col); + void updateDataColumn (int col); + std::string columnformat (int column); + bool columneditable (int column); + void sendCellEditCallback (int row, int col, octave_value old_value, + octave_value new_value, octave_value edit_data, octave_value error); + void checkBoxClicked (int row, int col, QCheckBox* checkBox); -}; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/TextControl.cc --- a/libgui/graphics/TextControl.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/TextControl.cc Tue Dec 06 15:45:27 2022 -0500 @@ -33,67 +33,63 @@ #include "TextControl.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - OCTAVE_BEGIN_NAMESPACE(octave) -TextControl * -TextControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go) -{ - Object *parent = parentObject (interp, go); + TextControl * + TextControl::create (octave::interpreter& interp, const graphics_object& go) + { + Object *parent = parentObject (interp, go); - if (parent) - { - Container *container = parent->innerContainer (); + if (parent) + { + Container *container = parent->innerContainer (); - if (container) - return new TextControl (oct_qobj, interp, go, new QLabel (container)); - } - - return nullptr; -} + if (container) + return new TextControl (interp, go, new QLabel (container)); + } -TextControl::TextControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, QLabel *label) - : BaseControl (oct_qobj, interp, go, label) -{ - uicontrol::properties& up = properties (); + return nullptr; + } + + TextControl::TextControl (octave::interpreter& interp, + const graphics_object& go, QLabel *label) + : BaseControl (interp, go, label) + { + uicontrol::properties& up = properties (); - label->setAutoFillBackground (true); - label->setTextFormat (Qt::PlainText); - label->setWordWrap (false); - label->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), - up.get_verticalalignment ())); - label->setText (Utils::fromStringVector (up.get_string_vector ()).join ("\n")); -} + label->setAutoFillBackground (true); + label->setTextFormat (Qt::PlainText); + label->setWordWrap (false); + label->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), + up.get_verticalalignment ())); + label->setText (Utils::fromStringVector (up.get_string_vector ()).join ("\n")); + } -TextControl::~TextControl (void) -{ } + TextControl::~TextControl (void) + { } -void -TextControl::update (int pId) -{ - uicontrol::properties& up = properties (); - QLabel *label = qWidget (); + void + TextControl::update (int pId) + { + uicontrol::properties& up = properties (); + QLabel *label = qWidget (); - switch (pId) - { - case uicontrol::properties::ID_STRING: - label->setText (Utils::fromStringVector (up.get_string_vector ()).join ("\n")); - break; + switch (pId) + { + case uicontrol::properties::ID_STRING: + label->setText (Utils::fromStringVector (up.get_string_vector ()).join ("\n")); + break; - case uicontrol::properties::ID_HORIZONTALALIGNMENT: - case uicontrol::properties::ID_VERTICALALIGNMENT: - label->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), - up.get_verticalalignment ())); - break; + case uicontrol::properties::ID_HORIZONTALALIGNMENT: + case uicontrol::properties::ID_VERTICALALIGNMENT: + label->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), + up.get_verticalalignment ())); + break; - default: - BaseControl::update (pId); - break; - } -} + default: + BaseControl::update (pId); + break; + } + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/TextControl.h --- a/libgui/graphics/TextControl.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/TextControl.h Tue Dec 06 15:45:27 2022 -0500 @@ -32,23 +32,22 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class TextControl : public BaseControl -{ -public: - TextControl (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QLabel *label); - ~TextControl (void); + class TextControl : public BaseControl + { + public: + TextControl (octave::interpreter& interp, + const graphics_object& go, QLabel *label); + ~TextControl (void); - static TextControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + static TextControl * + create (octave::interpreter& interp, + const graphics_object& go); -protected: - void update (int pId); -}; + protected: + void update (int pId); + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ToggleButtonControl.cc --- a/libgui/graphics/ToggleButtonControl.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ToggleButtonControl.cc Tue Dec 06 15:45:27 2022 -0500 @@ -34,77 +34,73 @@ #include "Container.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - OCTAVE_BEGIN_NAMESPACE(octave) -ToggleButtonControl * -ToggleButtonControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go) -{ - Object *parent = parentObject (interp, go); + ToggleButtonControl * + ToggleButtonControl::create (octave::interpreter& interp, + const graphics_object& go) + { + Object *parent = parentObject (interp, go); - if (parent) - { - Container *container = parent->innerContainer (); + if (parent) + { + Container *container = parent->innerContainer (); - if (container) - return new ToggleButtonControl (oct_qobj, interp, go, - new QPushButton (container)); - } + if (container) + return new ToggleButtonControl (interp, go, + new QPushButton (container)); + } - return nullptr; -} + return nullptr; + } -ToggleButtonControl::ToggleButtonControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, - QPushButton *btn) - : ButtonControl (oct_qobj, interp, go, btn) -{ - Object *parent = parentObject (interp, go); - ButtonGroup *btnGroup = dynamic_cast(parent); - if (btnGroup) - btnGroup->addButton (btn); + ToggleButtonControl::ToggleButtonControl (octave::interpreter& interp, + const graphics_object& go, + QPushButton *btn) + : ButtonControl (interp, go, btn) + { + Object *parent = parentObject (interp, go); + ButtonGroup *btnGroup = dynamic_cast(parent); + if (btnGroup) + btnGroup->addButton (btn); - uicontrol::properties& up = properties (); + uicontrol::properties& up = properties (); - btn->setCheckable (true); - btn->setAutoFillBackground (true); - octave_value cdat = up.get_cdata (); - QImage img = Utils::makeImageFromCData (cdat, - cdat.columns (), cdat.rows ()); - btn->setIcon (QIcon (QPixmap::fromImage (img))); - btn->setIconSize (QSize (cdat.columns (), cdat.rows ())); -} + btn->setCheckable (true); + btn->setAutoFillBackground (true); + octave_value cdat = up.get_cdata (); + QImage img = Utils::makeImageFromCData (cdat, + cdat.columns (), cdat.rows ()); + btn->setIcon (QIcon (QPixmap::fromImage (img))); + btn->setIconSize (QSize (cdat.columns (), cdat.rows ())); + } -ToggleButtonControl::~ToggleButtonControl (void) -{ } + ToggleButtonControl::~ToggleButtonControl (void) + { } -void -ToggleButtonControl::update (int pId) -{ - uicontrol::properties& up = properties (); - QPushButton *btn = qWidget (); + void + ToggleButtonControl::update (int pId) + { + uicontrol::properties& up = properties (); + QPushButton *btn = qWidget (); - switch (pId) - { - case uicontrol::properties::ID_CDATA: + switch (pId) { - octave_value cdat = up.get_cdata (); - QImage img = Utils::makeImageFromCData (cdat, - cdat.rows (), - cdat.columns ()); - btn->setIcon (QIcon (QPixmap::fromImage (img))); - btn->setIconSize (QSize (cdat.columns (), cdat.rows ())); + case uicontrol::properties::ID_CDATA: + { + octave_value cdat = up.get_cdata (); + QImage img = Utils::makeImageFromCData (cdat, + cdat.rows (), + cdat.columns ()); + btn->setIcon (QIcon (QPixmap::fromImage (img))); + btn->setIconSize (QSize (cdat.columns (), cdat.rows ())); + } + break; + + default: + ButtonControl::update (pId); + break; } - break; - - default: - ButtonControl::update (pId); - break; - } -} + } OCTAVE_END_NAMESPACE(octave); diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ToggleButtonControl.h --- a/libgui/graphics/ToggleButtonControl.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ToggleButtonControl.h Tue Dec 06 15:45:27 2022 -0500 @@ -32,24 +32,22 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class ToggleButtonControl : public ButtonControl -{ -public: - ToggleButtonControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, QPushButton *box); - ~ToggleButtonControl (void); + class ToggleButtonControl : public ButtonControl + { + public: + ToggleButtonControl (octave::interpreter& interp, + const graphics_object& go, QPushButton *box); + ~ToggleButtonControl (void); - static ToggleButtonControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + static ToggleButtonControl * + create (octave::interpreter& interp, + const graphics_object& go); -protected: - void update (int pId); -}; + protected: + void update (int pId); + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ToggleTool.cc --- a/libgui/graphics/ToggleTool.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ToggleTool.cc Tue Dec 06 15:45:27 2022 -0500 @@ -31,68 +31,64 @@ #include "ToolBarButton.cc" -#include "octave-qobject.h" - OCTAVE_BEGIN_NAMESPACE(octave) -ToggleTool * -ToggleTool::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go) -{ - Object *parent = parentObject (interp, go); + ToggleTool * + ToggleTool::create (octave::interpreter& interp, const graphics_object& go) + { + Object *parent = parentObject (interp, go); - if (parent) - { - QWidget *parentWidget = parent->qWidget (); + if (parent) + { + QWidget *parentWidget = parent->qWidget (); + + if (parentWidget) + return new ToggleTool (interp, go, + new QAction (parentWidget)); + } - if (parentWidget) - return new ToggleTool (oct_qobj, interp, go, - new QAction (parentWidget)); - } - - return nullptr; -} + return nullptr; + } -ToggleTool::ToggleTool (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, QAction *action) - : ToolBarButton (oct_qobj, interp, go, action) -{ - uitoggletool::properties& tp = properties (); + ToggleTool::ToggleTool (octave::interpreter& interp, + const graphics_object& go, QAction *action) + : ToolBarButton (interp, go, action) + { + uitoggletool::properties& tp = properties (); - action->setCheckable (true); - action->setChecked (tp.is_state ()); + action->setCheckable (true); + action->setChecked (tp.is_state ()); + + connect (action, &QAction::toggled, this, &ToggleTool::triggered); + } - connect (action, &QAction::toggled, this, &ToggleTool::triggered); -} - -ToggleTool::~ToggleTool (void) -{ } + ToggleTool::~ToggleTool (void) + { } -void -ToggleTool::update (int pId) -{ - uitoggletool::properties& tp = properties (); - QAction *action = qWidget (); + void + ToggleTool::update (int pId) + { + uitoggletool::properties& tp = properties (); + QAction *action = qWidget (); - switch (pId) - { - case uitoggletool::properties::ID_STATE: - action->setChecked (tp.is_state ()); - break; + switch (pId) + { + case uitoggletool::properties::ID_STATE: + action->setChecked (tp.is_state ()); + break; - default: - ToolBarButton::update (pId); - break; - } -} + default: + ToolBarButton::update (pId); + break; + } + } -void -ToggleTool::triggered (bool checked) -{ - emit gh_set_event (m_handle, "state", checked, false); - emit gh_callback_event (m_handle, checked ? "oncallback" : "offcallback"); - emit gh_callback_event (m_handle, "clickedcallback"); -} + void + ToggleTool::triggered (bool checked) + { + emit gh_set_event (m_handle, "state", checked, false); + emit gh_callback_event (m_handle, checked ? "oncallback" : "offcallback"); + emit gh_callback_event (m_handle, "clickedcallback"); + } OCTAVE_END_NAMESPACE(octave); diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ToggleTool.h --- a/libgui/graphics/ToggleTool.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ToggleTool.h Tue Dec 06 15:45:27 2022 -0500 @@ -30,29 +30,28 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class ToggleTool : public ToolBarButton -{ - Q_OBJECT + class ToggleTool : public ToolBarButton + { + Q_OBJECT -public: - ToggleTool (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, - QAction *action); - ~ToggleTool (void); + public: + ToggleTool (octave::interpreter& interp, + const graphics_object& go, + QAction *action); + ~ToggleTool (void); - static ToggleTool * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + static ToggleTool * + create (octave::interpreter& interp, + const graphics_object& go); -protected: - void update (int pId); + protected: + void update (int pId); -private slots: - void triggered (bool checked); -}; + private slots: + void triggered (bool checked); + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ToolBar.cc --- a/libgui/graphics/ToolBar.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ToolBar.cc Tue Dec 06 15:45:27 2022 -0500 @@ -42,148 +42,147 @@ #include "QtHandlesUtils.h" #include "gui-preferences-global.h" -#include "octave-qobject.h" OCTAVE_BEGIN_NAMESPACE(octave) -static QIcon makeEmptyIcon (void) -{ - QPixmap pix (16, 16); + static QIcon makeEmptyIcon (void) + { + QPixmap pix (16, 16); - pix.fill (Qt::transparent); + pix.fill (Qt::transparent); - return QIcon (pix); -} + return QIcon (pix); + } -static QAction * -addEmptyAction (QToolBar *bar) -{ - static const QIcon empty_icon = makeEmptyIcon (); + static QAction * + addEmptyAction (QToolBar *bar) + { + static const QIcon empty_icon = makeEmptyIcon (); - QAction *a = bar->addAction (empty_icon, "Empty Toolbar"); + QAction *a = bar->addAction (empty_icon, "Empty Toolbar"); - a->setEnabled (false); - a->setToolTip (""); + a->setEnabled (false); + a->setToolTip (""); - return a; -} + return a; + } -ToolBar * -ToolBar::create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go) -{ - Object *parent = parentObject (interp, go); + ToolBar * + ToolBar::create (octave::interpreter& interp, + const graphics_object& go) + { + Object *parent = parentObject (interp, go); - if (parent) - { - QWidget *parentWidget = parent->qWidget (); + if (parent) + { + QWidget *parentWidget = parent->qWidget (); - if (parentWidget) - return new ToolBar (oct_qobj, interp, go, - new QToolBar (parentWidget)); - } + if (parentWidget) + return new ToolBar (interp, go, + new QToolBar (parentWidget)); + } - return nullptr; -} + return nullptr; + } -ToolBar::ToolBar (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QToolBar *bar) - : Object (oct_qobj, interp, go, bar), m_empty (nullptr), m_figure (nullptr) -{ - uitoolbar::properties& tp = properties (); + ToolBar::ToolBar (octave::interpreter& interp, + const graphics_object& go, QToolBar *bar) + : Object (interp, go, bar), m_empty (nullptr), m_figure (nullptr) + { + uitoolbar::properties& tp = properties (); - bar->setFloatable (false); - bar->setMovable (false); - bar->setVisible (tp.is_visible ()); - bar->setStyleSheet (bar->styleSheet () + global_toolbar_style); + bar->setFloatable (false); + bar->setMovable (false); + bar->setVisible (tp.is_visible ()); + bar->setStyleSheet (bar->styleSheet () + global_toolbar_style); - m_empty = addEmptyAction (bar); + m_empty = addEmptyAction (bar); - m_figure = - dynamic_cast
(Object::fromQObject (bar->parentWidget ())); + m_figure = + dynamic_cast
(Object::fromQObject (bar->parentWidget ())); - if (m_figure) - m_figure->addCustomToolBar (bar, tp.is_visible (), - tp.get_tag () == "__default_toolbar__"); + if (m_figure) + m_figure->addCustomToolBar (bar, tp.is_visible (), + tp.get_tag () == "__default_toolbar__"); - bar->installEventFilter (this); -} + bar->installEventFilter (this); + } -ToolBar::~ToolBar (void) -{ } + ToolBar::~ToolBar (void) + { } -void -ToolBar::update (int pId) -{ - uitoolbar::properties& tp = properties (); - QToolBar *bar = qWidget (); + void + ToolBar::update (int pId) + { + uitoolbar::properties& tp = properties (); + QToolBar *bar = qWidget (); - switch (pId) - { - case base_properties::ID_VISIBLE: - if (m_figure) - m_figure->showCustomToolBar (bar, tp.is_visible ()); - break; + switch (pId) + { + case base_properties::ID_VISIBLE: + if (m_figure) + m_figure->showCustomToolBar (bar, tp.is_visible ()); + break; - default: - Object::update (pId); - break; - } -} + default: + Object::update (pId); + break; + } + } -bool -ToolBar::eventFilter (QObject *watched, QEvent *xevent) -{ - if (watched == qObject ()) - { - switch (xevent->type ()) - { - case QEvent::ActionAdded: - case QEvent::ActionRemoved: + bool + ToolBar::eventFilter (QObject *watched, QEvent *xevent) + { + if (watched == qObject ()) + { + switch (xevent->type ()) { - QActionEvent *ae = dynamic_cast (xevent); - QToolBar *bar = qWidget (); + case QEvent::ActionAdded: + case QEvent::ActionRemoved: + { + QActionEvent *ae = dynamic_cast (xevent); + QToolBar *bar = qWidget (); - if (ae->action () != m_empty) - { - if (xevent->type () == QEvent::ActionAdded) - { - if (bar->actions ().size () == 2) - QTimer::singleShot (0, this, &ToolBar::hideEmpty); - } - else - { - if (bar->actions ().size () == 1) - m_empty->setVisible (true); - } - } + if (ae->action () != m_empty) + { + if (xevent->type () == QEvent::ActionAdded) + { + if (bar->actions ().size () == 2) + QTimer::singleShot (0, this, &ToolBar::hideEmpty); + } + else + { + if (bar->actions ().size () == 1) + m_empty->setVisible (true); + } + } + } + break; + + default: + break; } - break; - - default: - break; - } - } + } - return false; -} + return false; + } -void -ToolBar::hideEmpty (void) -{ - m_empty->setVisible (false); -} + void + ToolBar::hideEmpty (void) + { + m_empty->setVisible (false); + } -void -ToolBar::beingDeleted (void) -{ - if (m_figure) - { - QToolBar *bar = qWidget (); + void + ToolBar::beingDeleted (void) + { + if (m_figure) + { + QToolBar *bar = qWidget (); - if (bar) - m_figure->showCustomToolBar (bar, false); - } -} + if (bar) + m_figure->showCustomToolBar (bar, false); + } + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ToolBar.h --- a/libgui/graphics/ToolBar.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ToolBar.h Tue Dec 06 15:45:27 2022 -0500 @@ -33,39 +33,38 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class Figure; + class Figure; -class ToolBar : public Object -{ - Q_OBJECT + class ToolBar : public Object + { + Q_OBJECT -public: - ToolBar (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QToolBar *bar); - ~ToolBar (void); + public: + ToolBar (octave::interpreter& interp, + const graphics_object& go, QToolBar *bar); + ~ToolBar (void); - static ToolBar * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go); + static ToolBar * + create (octave::interpreter& interp, + const graphics_object& go); - Container * innerContainer (void) { return nullptr; } + Container * innerContainer (void) { return nullptr; } - bool eventFilter (QObject *watched, QEvent *event); + bool eventFilter (QObject *watched, QEvent *event); -protected: - void update (int pId); - void beingDeleted (void); + protected: + void update (int pId); + void beingDeleted (void); -private slots: - void hideEmpty (void); + private slots: + void hideEmpty (void); -private: - QAction *m_empty; - Figure *m_figure; -}; + private: + QAction *m_empty; + Figure *m_figure; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ToolBarButton.cc --- a/libgui/graphics/ToolBarButton.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ToolBarButton.cc Tue Dec 06 15:45:27 2022 -0500 @@ -34,130 +34,128 @@ #include "ToolBarButton.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" #include "gui-preferences-global.h" OCTAVE_BEGIN_NAMESPACE(octave) -template -ToolBarButton::ToolBarButton (octave::base_qobject& oct_qobj, - octave::interpreter& interp, - const graphics_object& go, QAction *action) -: Object (oct_qobj, interp, go, action), m_separator (nullptr) -{ - typename T::properties& tp = properties (); + template + ToolBarButton::ToolBarButton (octave::interpreter& interp, + const graphics_object& go, QAction *action) + : Object (interp, go, action), m_separator (nullptr) + { + typename T::properties& tp = properties (); + + action->setToolTip (Utils::fromStdString (tp.get_tooltipstring ())); + action->setVisible (tp.is_visible ()); - action->setToolTip (Utils::fromStdString (tp.get_tooltipstring ())); - action->setVisible (tp.is_visible ()); + // Get the icon data from cdata or as a named icon + QImage img = Utils::makeImageFromCData (tp.get_cdata (), 24, 24); - // Get the icon data from cdata or as a named icon - QImage img = Utils::makeImageFromCData (tp.get_cdata (), 24, 24); + if (img.width () == 0) + { + QIcon ico; + std::string name = tp.get___named_icon__ (); + if (! name.empty ()) + ico = get_icon (name); - if (img.width () == 0) - { - QIcon ico; - std::string name = tp.get___named_icon__ (); - if (! name.empty ()) - ico = get_icon (name); + action->setIcon (ico); + } + else + action->setIcon (QIcon (QPixmap::fromImage (img))); - action->setIcon (ico); - } - else - action->setIcon (QIcon (QPixmap::fromImage (img))); + if (tp.is_separator ()) + { + m_separator = new QAction (action); + m_separator->setSeparator (true); + m_separator->setVisible (tp.is_visible ()); + } + action->setEnabled (tp.is_enable ()); - if (tp.is_separator ()) - { - m_separator = new QAction (action); - m_separator->setSeparator (true); - m_separator->setVisible (tp.is_visible ()); - } - action->setEnabled (tp.is_enable ()); + QWidget *w = qobject_cast (action->parent ()); - QWidget *w = qobject_cast (action->parent ()); + w->insertAction (w->actions ().back (), action); + if (m_separator) + w->insertAction (action, m_separator); + } + + template + ToolBarButton::~ToolBarButton (void) + { } - w->insertAction (w->actions ().back (), action); - if (m_separator) - w->insertAction (action, m_separator); -} + template + void + ToolBarButton::update (int pId) + { + typename T::properties& tp = properties (); + QAction *action = qWidget (); -template -ToolBarButton::~ToolBarButton (void) -{ } + switch (pId) + { + case base_properties::ID_VISIBLE: + action->setVisible (tp.is_visible ()); + if (m_separator) + m_separator->setVisible (tp.is_visible ()); + break; -template -void -ToolBarButton::update (int pId) -{ - typename T::properties& tp = properties (); - QAction *action = qWidget (); + case T::properties::ID_TOOLTIPSTRING: + action->setToolTip (Utils::fromStdString (tp.get_tooltipstring ())); + break; + + case T::properties::ID_CDATA: + { + // Get the icon data from cdata or as a named icon + QImage img = Utils::makeImageFromCData (tp.get_cdata (), 24, 24); - switch (pId) - { - case base_properties::ID_VISIBLE: - action->setVisible (tp.is_visible ()); - if (m_separator) - m_separator->setVisible (tp.is_visible ()); - break; + if (img.width () == 0) + { + QIcon ico; + std::string name = tp.get___named_icon__ (); + if (! name.empty ()) + ico = get_icon (name); - case T::properties::ID_TOOLTIPSTRING: - action->setToolTip (Utils::fromStdString (tp.get_tooltipstring ())); - break; + action->setIcon (ico); + } + else + action->setIcon (QIcon (QPixmap::fromImage (img))); + } + break; - case T::properties::ID_CDATA: - { - // Get the icon data from cdata or as a named icon - QImage img = Utils::makeImageFromCData (tp.get_cdata (), 24, 24); - - if (img.width () == 0) + case T::properties::ID_SEPARATOR: + if (tp.is_separator ()) { - QIcon ico; - std::string name = tp.get___named_icon__ (); - if (! name.empty ()) - ico = get_icon (name); + if (! m_separator) + { + m_separator = new QAction (action); + m_separator->setSeparator (true); + m_separator->setVisible (tp.is_visible ()); - action->setIcon (ico); + QWidget *w = qobject_cast (action->parent ()); + + w->insertAction (action, m_separator); + } } else - action->setIcon (QIcon (QPixmap::fromImage (img))); - } - break; + { + if (m_separator) + delete m_separator; + m_separator = nullptr; + } + break; - case T::properties::ID_SEPARATOR: - if (tp.is_separator ()) - { - if (! m_separator) - { - m_separator = new QAction (action); - m_separator->setSeparator (true); - m_separator->setVisible (tp.is_visible ()); - - QWidget *w = qobject_cast (action->parent ()); + case T::properties::ID_ENABLE: + action->setEnabled (tp.is_enable ()); + break; - w->insertAction (action, m_separator); - } - } - else - { - if (m_separator) - delete m_separator; - m_separator = nullptr; - } - break; + default: + Object::update (pId); + break; + } + } - case T::properties::ID_ENABLE: - action->setEnabled (tp.is_enable ()); - break; - - default: - Object::update (pId); - break; - } -} - -template -QIcon ToolBarButton::get_icon (const std::string& name) -{ - return QIcon (global_icon_paths.at (ICON_THEME_OCTAVE) + QString::fromStdString (name) + ".png"); -} + template + QIcon ToolBarButton::get_icon (const std::string& name) + { + return QIcon (global_icon_paths.at (ICON_THEME_OCTAVE) + QString::fromStdString (name) + ".png"); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/ToolBarButton.h --- a/libgui/graphics/ToolBarButton.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/ToolBarButton.h Tue Dec 06 15:45:27 2022 -0500 @@ -33,29 +33,28 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class interpreter; + class interpreter; -class Container; + class Container; -template -class ToolBarButton : public Object -{ -public: - ToolBarButton (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_object& go, QAction *action); - ~ToolBarButton (void); + template + class ToolBarButton : public Object + { + public: + ToolBarButton (octave::interpreter& interp, + const graphics_object& go, QAction *action); + ~ToolBarButton (void); - Container * innerContainer (void) { return nullptr; } + Container * innerContainer (void) { return nullptr; } -protected: - void update (int pId); + protected: + void update (int pId); -private: - QAction *m_separator; + private: + QAction *m_separator; - QIcon get_icon (const std::string& name); -}; + QIcon get_icon (const std::string& name); + }; OCTAVE_END_NAMESPACE(octave); diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/annotation-dialog.cc --- a/libgui/graphics/annotation-dialog.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/annotation-dialog.cc Tue Dec 06 15:45:27 2022 -0500 @@ -33,17 +33,14 @@ #include "gui-settings.h" #include "gui-preferences-gp.h" -#include "octave-qobject.h" +#include "gui-settings.h" #include "QtHandlesUtils.h" #include "annotation-dialog.h" #include "ui-annotation-dialog.h" -using namespace octave; - -annotation_dialog::annotation_dialog (octave::base_qobject& oct_qobj, - QWidget *p, const octave_value_list& pr): - QDialog (p), m_octave_qobj (oct_qobj), ui (new Ui::annotation_dialog) +annotation_dialog::annotation_dialog (QWidget *p, const octave_value_list& pr): + QDialog (p), ui (new Ui::annotation_dialog) { props = pr; @@ -55,13 +52,11 @@ { ui->setupUi (this); - octave::resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - - octave::gui_settings *settings = rmgr.get_settings (); + octave::gui_settings settings; // restore last geometry - if (settings && settings->contains (gp_annotation_geometry.key)) - restoreGeometry (settings->value (gp_annotation_geometry).toByteArray ()); + if (settings.contains (gp_annotation_geometry.key)) + restoreGeometry (settings.value (gp_annotation_geometry).toByteArray ()); // connect signals connect (ui->button_box, &QDialogButtonBox::clicked, @@ -101,13 +96,10 @@ QDialogButtonBox::ButtonRole button_role = ui->button_box->buttonRole (button); - octave::resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - - octave::gui_settings *settings = rmgr.get_settings (); + octave::gui_settings settings; // save position - if (settings) - settings->setValue (gp_annotation_geometry.key, saveGeometry ()); + settings.setValue (gp_annotation_geometry.key, saveGeometry ()); if (button_role == QDialogButtonBox::ApplyRole || button_role == QDialogButtonBox::AcceptRole) @@ -164,7 +156,7 @@ ui->cb_font_bold->isChecked () ? "bold" : "normal")); props.append (ovl ("fontangle", ui->cb_font_italic->isChecked () ? "italic" : "normal")); - props.append (ovl ("color", Utils::toRgb (ui->btn_color->palette (). + props.append (ovl ("color", octave::Utils::toRgb (ui->btn_color->palette (). color (QPalette::Button)))); // FIXME: only "none" linestyle is selectable, change the code bellow @@ -249,7 +241,7 @@ { QColor color; if (props(1*i +1).is_matrix_type ()) - color = Utils::fromRgb (props(2*i +1).matrix_value ()); + color = octave::Utils::fromRgb (props(2*i +1).matrix_value ()); else color.setNamedColor (props(2*i +1).string_value ().c_str ()); diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/annotation-dialog.h --- a/libgui/graphics/annotation-dialog.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/annotation-dialog.h Tue Dec 06 15:45:27 2022 -0500 @@ -32,20 +32,16 @@ #include "ovl.h" -OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -OCTAVE_END_NAMESPACE(octave) - -OCTAVE_BEGIN_NAMESPACE(Ui) -class annotation_dialog; -OCTAVE_END_NAMESPACE(Ui) +namespace Ui +{ + class annotation_dialog; +} class annotation_dialog : public QDialog { Q_OBJECT public: - annotation_dialog (octave::base_qobject& oct_qobj, QWidget *parent, - const octave_value_list& pr); + annotation_dialog (QWidget *parent, const octave_value_list& pr); ~annotation_dialog (); octave_value_list get_properties () const; @@ -62,7 +58,6 @@ void get_gui_props (); void set_gui_props (); - octave::base_qobject& m_octave_qobj; Ui::annotation_dialog *ui; octave_value_list props; }; diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/qt-graphics-toolkit.cc --- a/libgui/graphics/qt-graphics-toolkit.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/qt-graphics-toolkit.cc Tue Dec 06 15:45:27 2022 -0500 @@ -57,8 +57,6 @@ #include "ToolBar.h" #include "qt-graphics-toolkit.h" -#include "octave-qobject.h" - #include "event-manager.h" #include "graphics.h" #include "interpreter.h" @@ -75,439 +73,437 @@ OCTAVE_BEGIN_NAMESPACE(octave) -static std::string -toolkitObjectProperty (const graphics_object& go) -{ - if (go.isa ("figure")) - return "__plot_stream__"; - else if (go.isa ("uicontrol") - || go.isa ("uipanel") - || go.isa ("uibuttongroup") - || go.isa ("uimenu") - || go.isa ("uicontextmenu") - || go.isa ("uitable") - || go.isa ("uitoolbar") - || go.isa ("uipushtool") - || go.isa ("uitoggletool")) - return "__object__"; - else - qCritical ("octave::qt_graphics_toolkit: no __object__ property known for object " - "of type %s", go.type ().c_str ()); + static std::string + toolkitObjectProperty (const graphics_object& go) + { + if (go.isa ("figure")) + return "__plot_stream__"; + else if (go.isa ("uicontrol") + || go.isa ("uipanel") + || go.isa ("uibuttongroup") + || go.isa ("uimenu") + || go.isa ("uicontextmenu") + || go.isa ("uitable") + || go.isa ("uitoolbar") + || go.isa ("uipushtool") + || go.isa ("uitoggletool")) + return "__object__"; + else + qCritical ("octave::qt_graphics_toolkit: no __object__ property known for object " + "of type %s", go.type ().c_str ()); - return ""; -} + return ""; + } -qt_graphics_toolkit::qt_graphics_toolkit (octave::interpreter& interp, - octave::base_qobject& oct_qobj) - : QObject (), base_graphics_toolkit ("qt"), m_interpreter (interp), - m_octave_qobj (oct_qobj) -{ - // Implemented with a signal/slot connection in order to properly - // cross from the interpreter thread (where requests to create - // graphics object are initiated) to the GUI application thread - // (where they are actually created and displayed). - // We need to make sure the GUI Object and its proxy are properly - // created before the initialize method returns, so we use a - // BlockingQueuedConnection. After the signal is emitted, the interpreter - // thread is locked until the slot has returned. + qt_graphics_toolkit::qt_graphics_toolkit (octave::interpreter& interp) + : QObject (), base_graphics_toolkit ("qt"), m_interpreter (interp) + { + // Implemented with a signal/slot connection in order to properly + // cross from the interpreter thread (where requests to create + // graphics object are initiated) to the GUI application thread + // (where they are actually created and displayed). + // We need to make sure the GUI Object and its proxy are properly + // created before the initialize method returns, so we use a + // BlockingQueuedConnection. After the signal is emitted, the interpreter + // thread is locked until the slot has returned. - connect (this, &qt_graphics_toolkit::create_object_signal, - this, &qt_graphics_toolkit::create_object, - Qt::BlockingQueuedConnection); -} + connect (this, &qt_graphics_toolkit::create_object_signal, + this, &qt_graphics_toolkit::create_object, + Qt::BlockingQueuedConnection); + } -bool -qt_graphics_toolkit::initialize (const graphics_object& go) -{ - if (go.isa ("figure") - || (go.isa ("uicontrol") && go.get ("style").string_value () != "frame") - || go.isa ("uipanel") - || go.isa ("uibuttongroup") - || go.isa ("uimenu") - || go.isa ("uicontextmenu") - || go.isa ("uitable") - || go.isa ("uitoolbar") - || go.isa ("uipushtool") - || go.isa ("uitoggletool")) - { - // FIXME: We need to unlock the mutex here but we have no way to know - // if it was previously locked by this thread, and thus if we should - // re-lock it. + bool + qt_graphics_toolkit::initialize (const graphics_object& go) + { + if (go.isa ("figure") + || (go.isa ("uicontrol") && go.get ("style").string_value () != "frame") + || go.isa ("uipanel") + || go.isa ("uibuttongroup") + || go.isa ("uimenu") + || go.isa ("uicontextmenu") + || go.isa ("uitable") + || go.isa ("uitoolbar") + || go.isa ("uipushtool") + || go.isa ("uitoggletool")) + { + // FIXME: We need to unlock the mutex here but we have no way to know + // if it was previously locked by this thread, and thus if we should + // re-lock it. - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - gh_mgr.unlock (); + gh_mgr.unlock (); - Logger::debug ("qt_graphics_toolkit::initialize %s from thread %p", - go.type ().c_str (), QThread::currentThreadId ()); + Logger::debug ("qt_graphics_toolkit::initialize %s from thread %p", + go.type ().c_str (), QThread::currentThreadId ()); - ObjectProxy *proxy = new ObjectProxy (); - graphics_object gObj (go); + ObjectProxy *proxy = new ObjectProxy (); + graphics_object gObj (go); - OCTAVE_PTR_TYPE tmp (reinterpret_cast (proxy)); - gObj.get_properties ().set (toolkitObjectProperty (go), tmp); + OCTAVE_PTR_TYPE tmp (reinterpret_cast (proxy)); + gObj.get_properties ().set (toolkitObjectProperty (go), tmp); - emit create_object_signal (go.get_handle ().value ()); + emit create_object_signal (go.get_handle ().value ()); - return true; - } + return true; + } - return false; -} + return false; + } -void -qt_graphics_toolkit::update (const graphics_object& go, int pId) -{ - // Rule out obvious properties we want to ignore. - if (pId == figure::properties::ID___PLOT_STREAM__ - || pId == uicontrol::properties::ID___OBJECT__ - || pId == uipanel::properties::ID___OBJECT__ - || pId == uibuttongroup::properties::ID___OBJECT__ - || pId == uimenu::properties::ID___OBJECT__ - || pId == uicontextmenu::properties::ID___OBJECT__ - || pId == uitable::properties::ID___OBJECT__ - || pId == uitoolbar::properties::ID___OBJECT__ - || pId == uipushtool::properties::ID___OBJECT__ - || pId == uitoggletool::properties::ID___OBJECT__ - || pId == base_properties::ID___MODIFIED__) - return; + void + qt_graphics_toolkit::update (const graphics_object& go, int pId) + { + // Rule out obvious properties we want to ignore. + if (pId == figure::properties::ID___PLOT_STREAM__ + || pId == uicontrol::properties::ID___OBJECT__ + || pId == uipanel::properties::ID___OBJECT__ + || pId == uibuttongroup::properties::ID___OBJECT__ + || pId == uimenu::properties::ID___OBJECT__ + || pId == uicontextmenu::properties::ID___OBJECT__ + || pId == uitable::properties::ID___OBJECT__ + || pId == uitoolbar::properties::ID___OBJECT__ + || pId == uipushtool::properties::ID___OBJECT__ + || pId == uitoggletool::properties::ID___OBJECT__ + || pId == base_properties::ID___MODIFIED__) + return; - Logger::debug ("qt_graphics_toolkit::update %s(%d) from thread %p", - go.type ().c_str (), pId, QThread::currentThreadId ()); + Logger::debug ("qt_graphics_toolkit::update %s(%d) from thread %p", + go.type ().c_str (), pId, QThread::currentThreadId ()); - ObjectProxy *proxy = toolkitObjectProxy (go); + ObjectProxy *proxy = toolkitObjectProxy (go); - if (proxy) - { - if ((go.isa ("uicontrol") - && pId == uicontrol::properties::ID_STYLE) - || (go.isa ("uitable") - && pId == uitable::properties::ID_DATA)) - { - // Special case: we need to recreate the control widget - // associated with the octave graphics_object - // FIXME: For uitable, it would only be necessary to recreate - // the table widget if the type of the displayed values changes - // between Boolean and non-Boolean (bug #63388). + if (proxy) + { + if ((go.isa ("uicontrol") + && pId == uicontrol::properties::ID_STYLE) + || (go.isa ("uitable") + && pId == uitable::properties::ID_DATA)) + { + // Special case: we need to recreate the control widget + // associated with the octave graphics_object + // FIXME: For uitable, it would only be necessary to recreate + // the table widget if the type of the displayed values changes + // between Boolean and non-Boolean (bug #63388). - finalize (go); - initialize (go); - } - else - proxy->update (pId); - } -} + finalize (go); + initialize (go); + } + else + proxy->update (pId); + } + } -void -qt_graphics_toolkit::finalize (const graphics_object& go) -{ - // FIXME: We need to unlock the mutex here but we have no way to know if - // if it was previously locked by this thread, and thus if we should - // re-lock it. + void + qt_graphics_toolkit::finalize (const graphics_object& go) + { + // FIXME: We need to unlock the mutex here but we have no way to know if + // if it was previously locked by this thread, and thus if we should + // re-lock it. - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - gh_mgr.unlock (); + gh_mgr.unlock (); - Logger::debug ("qt_graphics_toolkit::finalize %s from thread %p", - go.type ().c_str (), QThread::currentThreadId ()); + Logger::debug ("qt_graphics_toolkit::finalize %s from thread %p", + go.type ().c_str (), QThread::currentThreadId ()); - ObjectProxy *proxy = toolkitObjectProxy (go); + ObjectProxy *proxy = toolkitObjectProxy (go); - if (proxy) - { - proxy->finalize (); - delete proxy; + if (proxy) + { + proxy->finalize (); + delete proxy; - graphics_object gObj (go); + graphics_object gObj (go); - gObj.get_properties ().set (toolkitObjectProperty (go), Matrix ()); - } -} + gObj.get_properties ().set (toolkitObjectProperty (go), Matrix ()); + } + } -void -qt_graphics_toolkit::redraw_figure (const graphics_object& go) const -{ - if (go.get_properties ().is_visible ()) - { - ObjectProxy *proxy = toolkitObjectProxy (go); + void + qt_graphics_toolkit::redraw_figure (const graphics_object& go) const + { + if (go.get_properties ().is_visible ()) + { + ObjectProxy *proxy = toolkitObjectProxy (go); - if (proxy) - proxy->redraw (); - } -} + if (proxy) + proxy->redraw (); + } + } -void -qt_graphics_toolkit::show_figure (const graphics_object& go) const -{ - if (go.get_properties ().is_visible ()) - { - ObjectProxy *proxy = toolkitObjectProxy (go); + void + qt_graphics_toolkit::show_figure (const graphics_object& go) const + { + if (go.get_properties ().is_visible ()) + { + ObjectProxy *proxy = toolkitObjectProxy (go); - if (proxy) - proxy->show (); - } -} + if (proxy) + proxy->show (); + } + } -void -qt_graphics_toolkit::print_figure (const graphics_object& go, - const std::string& term, - const std::string& file_cmd, - const std::string& /*debug_file*/) const -{ - ObjectProxy *proxy = toolkitObjectProxy (go); + void + qt_graphics_toolkit::print_figure (const graphics_object& go, + const std::string& term, + const std::string& file_cmd, + const std::string& /*debug_file*/) const + { + ObjectProxy *proxy = toolkitObjectProxy (go); - if (proxy) - proxy->print (QString::fromStdString (file_cmd), - QString::fromStdString (term)); -} + if (proxy) + proxy->print (QString::fromStdString (file_cmd), + QString::fromStdString (term)); + } -uint8NDArray -qt_graphics_toolkit::get_pixels (const graphics_object& go) const -{ - uint8NDArray retval; + uint8NDArray + qt_graphics_toolkit::get_pixels (const graphics_object& go) const + { + uint8NDArray retval; - if (go.isa ("figure")) - { - ObjectProxy *proxy = toolkitObjectProxy (go); + if (go.isa ("figure")) + { + ObjectProxy *proxy = toolkitObjectProxy (go); - if (proxy) - retval = proxy->get_pixels (); - } + if (proxy) + retval = proxy->get_pixels (); + } - return retval; -} + return retval; + } -Matrix -qt_graphics_toolkit::get_text_extent (const graphics_object& go) const -{ - Matrix ext (1, 4, 0.0); + Matrix + qt_graphics_toolkit::get_text_extent (const graphics_object& go) const + { + Matrix ext (1, 4, 0.0); - if (go.isa ("uicontrol")) - { - octave_value str = go.get ("string"); - if (! str.isempty ()) - { - const uicontrol::properties& up = - dynamic_cast (go.get_properties ()); - Matrix bb = up.get_boundingbox (false); - QFont font = Utils::computeFont (up, bb(3)); - QFontMetrics fm (font); + if (go.isa ("uicontrol")) + { + octave_value str = go.get ("string"); + if (! str.isempty ()) + { + const uicontrol::properties& up = + dynamic_cast (go.get_properties ()); + Matrix bb = up.get_boundingbox (false); + QFont font = Utils::computeFont (up, bb(3)); + QFontMetrics fm (font); - QString s; - QSize sz; + QString s; + QSize sz; - if (str.is_string ()) - { - s = QString::fromStdString (str.string_value ()); - sz = fm.size (Qt::TextSingleLine, s); - ext(2) = sz.width (); - ext(3) = sz.height (); - } - else if (str.iscellstr ()) - { - string_vector sv = str.string_vector_value (); - double wd = 0.0; - double hg = 0.0; - for (octave_idx_type ii = 0; ii < sv.numel (); ii++) - { - s = QString::fromStdString (sv(ii)); - sz = fm.size (Qt::TextSingleLine, s); - wd = std::max (wd, static_cast (sz.width ())); - hg = std::max (hg, static_cast (sz.height ())); - } + if (str.is_string ()) + { + s = QString::fromStdString (str.string_value ()); + sz = fm.size (Qt::TextSingleLine, s); + ext(2) = sz.width (); + ext(3) = sz.height (); + } + else if (str.iscellstr ()) + { + string_vector sv = str.string_vector_value (); + double wd = 0.0; + double hg = 0.0; + for (octave_idx_type ii = 0; ii < sv.numel (); ii++) + { + s = QString::fromStdString (sv(ii)); + sz = fm.size (Qt::TextSingleLine, s); + wd = std::max (wd, static_cast (sz.width ())); + hg = std::max (hg, static_cast (sz.height ())); + } - ext(2) = wd; - // FIXME: Find a better way to determine the height of e.g. - // listbox uicontrol objects - ext(3) = hg * sv.numel (); - } - } - } + ext(2) = wd; + // FIXME: Find a better way to determine the height of e.g. + // listbox uicontrol objects + ext(3) = hg * sv.numel (); + } + } + } - return ext; -} + return ext; + } -Object * -qt_graphics_toolkit::toolkitObject (const graphics_object& go) -{ - ObjectProxy *proxy = toolkitObjectProxy (go); + Object * + qt_graphics_toolkit::toolkitObject (const graphics_object& go) + { + ObjectProxy *proxy = toolkitObjectProxy (go); - if (proxy) - return proxy->object (); + if (proxy) + return proxy->object (); - return nullptr; -} + return nullptr; + } -ObjectProxy * -qt_graphics_toolkit::toolkitObjectProxy (const graphics_object& go) -{ - if (go) - { - octave_value ov = go.get (toolkitObjectProperty (go)); + ObjectProxy * + qt_graphics_toolkit::toolkitObjectProxy (const graphics_object& go) + { + if (go) + { + octave_value ov = go.get (toolkitObjectProperty (go)); - if (ov.is_defined () && ! ov.isempty ()) - { - OCTAVE_INTPTR_TYPE ptr = ov.OCTAVE_PTR_SCALAR ().value (); + if (ov.is_defined () && ! ov.isempty ()) + { + OCTAVE_INTPTR_TYPE ptr = ov.OCTAVE_PTR_SCALAR ().value (); - return reinterpret_cast (ptr); - } - } + return reinterpret_cast (ptr); + } + } - return nullptr; -} + return nullptr; + } -void -qt_graphics_toolkit::interpreter_event (const octave::fcn_callback& fcn) -{ - octave::event_manager& evmgr = m_interpreter.get_event_manager (); + void + qt_graphics_toolkit::interpreter_event (const octave::fcn_callback& fcn) + { + octave::event_manager& evmgr = m_interpreter.get_event_manager (); - evmgr.post_event (fcn); -} + evmgr.post_event (fcn); + } -void -qt_graphics_toolkit::interpreter_event (const octave::meth_callback& meth) -{ - octave::event_manager& evmgr = m_interpreter.get_event_manager (); + void + qt_graphics_toolkit::interpreter_event (const octave::meth_callback& meth) + { + octave::event_manager& evmgr = m_interpreter.get_event_manager (); - evmgr.post_event (meth); -} + evmgr.post_event (meth); + } -void -qt_graphics_toolkit::create_object (double handle) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + void + qt_graphics_toolkit::create_object (double handle) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - octave::autolock guard (gh_mgr.graphics_lock ()); + octave::autolock guard (gh_mgr.graphics_lock ()); - graphics_object go (gh_mgr.get_object (graphics_handle (handle))); + graphics_object go (gh_mgr.get_object (graphics_handle (handle))); - if (! go.valid_object ()) - { - qWarning ("qt_graphics_toolkit::create_object: invalid object for handle %g", - handle); - return; - } + if (! go.valid_object ()) + { + qWarning ("qt_graphics_toolkit::create_object: invalid object for handle %g", + handle); + return; + } - if (go.get_properties ().is_beingdeleted ()) - { - qWarning ("qt_graphics_toolkit::create_object: object is being deleted"); - return; - } + if (go.get_properties ().is_beingdeleted ()) + { + qWarning ("qt_graphics_toolkit::create_object: object is being deleted"); + return; + } - ObjectProxy *proxy = qt_graphics_toolkit::toolkitObjectProxy (go); + ObjectProxy *proxy = qt_graphics_toolkit::toolkitObjectProxy (go); - if (! proxy) - { - qWarning ("qt_graphics_toolkit::create_object: no proxy for handle %g", - handle); - return; - } + if (! proxy) + { + qWarning ("qt_graphics_toolkit::create_object: no proxy for handle %g", + handle); + return; + } - Logger::debug ("qt_graphics_toolkit::create_object: " - "create %s from thread %p", - go.type ().c_str (), QThread::currentThreadId ()); + Logger::debug ("qt_graphics_toolkit::create_object: " + "create %s from thread %p", + go.type ().c_str (), QThread::currentThreadId ()); - Object *obj = nullptr; + Object *obj = nullptr; - if (go.isa ("figure")) - obj = Figure::create (m_octave_qobj, m_interpreter, go); - else if (go.isa ("uicontrol")) - { - uicontrol::properties& up = - Utils::properties (go); + if (go.isa ("figure")) + obj = Figure::create (m_interpreter, go); + else if (go.isa ("uicontrol")) + { + uicontrol::properties& up = + Utils::properties (go); - if (up.style_is ("pushbutton")) - obj = PushButtonControl::create (m_octave_qobj, m_interpreter, go); - else if (up.style_is ("edit")) - obj = EditControl::create (m_octave_qobj, m_interpreter, go); - else if (up.style_is ("checkbox")) - obj = CheckBoxControl::create (m_octave_qobj, m_interpreter, go); - else if (up.style_is ("radiobutton")) - obj = RadioButtonControl::create (m_octave_qobj, m_interpreter, go); - else if (up.style_is ("togglebutton")) - obj = ToggleButtonControl::create (m_octave_qobj, m_interpreter, go); - else if (up.style_is ("text")) - obj = TextControl::create (m_octave_qobj, m_interpreter, go); - else if (up.style_is ("popupmenu")) - obj = PopupMenuControl::create (m_octave_qobj, m_interpreter, go); - else if (up.style_is ("slider")) - obj = SliderControl::create (m_octave_qobj, m_interpreter, go); - else if (up.style_is ("listbox")) - obj = ListBoxControl::create (m_octave_qobj, m_interpreter, go); - } - else if (go.isa ("uibuttongroup")) - obj = ButtonGroup::create (m_octave_qobj, m_interpreter, go); - else if (go.isa ("uipanel")) - obj = Panel::create (m_octave_qobj, m_interpreter, go); - else if (go.isa ("uimenu")) - obj = Menu::create (m_octave_qobj, m_interpreter, go); - else if (go.isa ("uicontextmenu")) - obj = ContextMenu::create (m_octave_qobj, m_interpreter, go); - else if (go.isa ("uitable")) - obj = Table::create (m_octave_qobj, m_interpreter, go); - else if (go.isa ("uitoolbar")) - obj = ToolBar::create (m_octave_qobj, m_interpreter, go); - else if (go.isa ("uipushtool")) - obj = PushTool::create (m_octave_qobj, m_interpreter, go); - else if (go.isa ("uitoggletool")) - obj = ToggleTool::create (m_octave_qobj, m_interpreter, go); - else - qWarning ("qt_graphics_toolkit::create_object: unsupported type '%s'", - go.type ().c_str ()); + if (up.style_is ("pushbutton")) + obj = PushButtonControl::create (m_interpreter, go); + else if (up.style_is ("edit")) + obj = EditControl::create (m_interpreter, go); + else if (up.style_is ("checkbox")) + obj = CheckBoxControl::create (m_interpreter, go); + else if (up.style_is ("radiobutton")) + obj = RadioButtonControl::create (m_interpreter, go); + else if (up.style_is ("togglebutton")) + obj = ToggleButtonControl::create (m_interpreter, go); + else if (up.style_is ("text")) + obj = TextControl::create (m_interpreter, go); + else if (up.style_is ("popupmenu")) + obj = PopupMenuControl::create (m_interpreter, go); + else if (up.style_is ("slider")) + obj = SliderControl::create (m_interpreter, go); + else if (up.style_is ("listbox")) + obj = ListBoxControl::create (m_interpreter, go); + } + else if (go.isa ("uibuttongroup")) + obj = ButtonGroup::create (m_interpreter, go); + else if (go.isa ("uipanel")) + obj = Panel::create (m_interpreter, go); + else if (go.isa ("uimenu")) + obj = Menu::create (m_interpreter, go); + else if (go.isa ("uicontextmenu")) + obj = ContextMenu::create (m_interpreter, go); + else if (go.isa ("uitable")) + obj = Table::create (m_interpreter, go); + else if (go.isa ("uitoolbar")) + obj = ToolBar::create (m_interpreter, go); + else if (go.isa ("uipushtool")) + obj = PushTool::create (m_interpreter, go); + else if (go.isa ("uitoggletool")) + obj = ToggleTool::create (m_interpreter, go); + else + qWarning ("qt_graphics_toolkit::create_object: unsupported type '%s'", + go.type ().c_str ()); - if (obj) - { - proxy->setObject (obj); - obj->do_connections (this); - } -} + if (obj) + { + proxy->setObject (obj); + obj->do_connections (this); + } + } -void qt_graphics_toolkit::gh_callback_event (const graphics_handle& h, - const std::string& nm) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + void qt_graphics_toolkit::gh_callback_event (const graphics_handle& h, + const std::string& nm) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - gh_mgr.post_callback (h, nm); -} + gh_mgr.post_callback (h, nm); + } -void qt_graphics_toolkit::gh_callback_event (const graphics_handle& h, - const std::string& nm, - const octave_value& data) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + void qt_graphics_toolkit::gh_callback_event (const graphics_handle& h, + const std::string& nm, + const octave_value& data) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - gh_mgr.post_callback (h, nm, data); -} + gh_mgr.post_callback (h, nm, data); + } -void qt_graphics_toolkit::gh_set_event (const graphics_handle& h, - const std::string& nm, - const octave_value& value) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + void qt_graphics_toolkit::gh_set_event (const graphics_handle& h, + const std::string& nm, + const octave_value& value) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - gh_mgr.post_set (h, nm, value); -} + gh_mgr.post_set (h, nm, value); + } -void qt_graphics_toolkit::gh_set_event (const graphics_handle& h, - const std::string& nm, - const octave_value& value, - bool notify_toolkit) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + void qt_graphics_toolkit::gh_set_event (const graphics_handle& h, + const std::string& nm, + const octave_value& value, + bool notify_toolkit) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - gh_mgr.post_set (h, nm, value, notify_toolkit); -} + gh_mgr.post_set (h, nm, value, notify_toolkit); + } -void qt_graphics_toolkit::gh_set_event (const graphics_handle& h, - const std::string& nm, - const octave_value& value, - bool notify_toolkit, - bool redraw_figure) -{ - gh_manager& gh_mgr = m_interpreter.get_gh_manager (); + void qt_graphics_toolkit::gh_set_event (const graphics_handle& h, + const std::string& nm, + const octave_value& value, + bool notify_toolkit, + bool redraw_figure) + { + gh_manager& gh_mgr = m_interpreter.get_gh_manager (); - gh_mgr.post_set (h, nm, value, notify_toolkit, redraw_figure); -} + gh_mgr.post_set (h, nm, value, notify_toolkit, redraw_figure); + } OCTAVE_END_NAMESPACE(octave); diff -r 29d734430e5f -r deb553ac2c54 libgui/graphics/qt-graphics-toolkit.h --- a/libgui/graphics/qt-graphics-toolkit.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/graphics/qt-graphics-toolkit.h Tue Dec 06 15:45:27 2022 -0500 @@ -33,95 +33,91 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class interpreter; -class base_qobject; + class interpreter; -class Object; -class ObjectProxy; + class Object; + class ObjectProxy; -class qt_graphics_toolkit - : public QObject, public octave::base_graphics_toolkit -{ - Q_OBJECT + class qt_graphics_toolkit + : public QObject, public octave::base_graphics_toolkit + { + Q_OBJECT -public: + public: - qt_graphics_toolkit (octave::interpreter& interp, - octave::base_qobject& oct_qobj); + qt_graphics_toolkit (octave::interpreter& interp); - ~qt_graphics_toolkit (void) = default; + ~qt_graphics_toolkit (void) = default; - // The interpreter may call graphics toolkit functions that we - // implement here. The Qt GUI that manages these actions runs in a - // separate thread. So in order to correctly cross from the - // interpreter thread to the GUI thread, these functions should emit - // signals (in the interpreter thread) that are handled by slots - // that will run in the GUI thread. This design is similar to the - // event_manager, interpreter_events, and qt_interpreter_events - // classes work to pass messages from the interpreter to the GUI. - // - // FIXME: currently most of these functions do not emit signals. - // They may work because they use locking and the gh_manager class, - // but it might be better to use Qt signals and slots. In any case, - // we should ensure that they are correctly handling the connection - // between the interpreter and GUI threads. + // The interpreter may call graphics toolkit functions that we + // implement here. The Qt GUI that manages these actions runs in a + // separate thread. So in order to correctly cross from the + // interpreter thread to the GUI thread, these functions should emit + // signals (in the interpreter thread) that are handled by slots + // that will run in the GUI thread. This design is similar to the + // event_manager, interpreter_events, and qt_interpreter_events + // classes work to pass messages from the interpreter to the GUI. + // + // FIXME: currently most of these functions do not emit signals. + // They may work because they use locking and the gh_manager class, + // but it might be better to use Qt signals and slots. In any case, + // we should ensure that they are correctly handling the connection + // between the interpreter and GUI threads. - bool is_valid (void) const { return true; } + bool is_valid (void) const { return true; } - void redraw_figure (const graphics_object& h) const; + void redraw_figure (const graphics_object& h) const; - void show_figure (const graphics_object& h) const; + void show_figure (const graphics_object& h) const; - void update (const graphics_object& obj, int pId); + void update (const graphics_object& obj, int pId); - bool initialize (const graphics_object& obj); + bool initialize (const graphics_object& obj); - void finalize (const graphics_object& obj); + void finalize (const graphics_object& obj); - void print_figure (const graphics_object& go, - const std::string& term, - const std::string& file_cmd, - const std::string& /*debug_file*/) const; + void print_figure (const graphics_object& go, + const std::string& term, + const std::string& file_cmd, + const std::string& /*debug_file*/) const; - uint8NDArray get_pixels (const graphics_object& go) const; + uint8NDArray get_pixels (const graphics_object& go) const; - Matrix get_text_extent (const graphics_object& go) const; - - static Object * toolkitObject (const graphics_object& go); + Matrix get_text_extent (const graphics_object& go) const; - static ObjectProxy * toolkitObjectProxy (const graphics_object& go); + static Object * toolkitObject (const graphics_object& go); -signals: + static ObjectProxy * toolkitObjectProxy (const graphics_object& go); - void create_object_signal (double handle); + signals: -public slots: + void create_object_signal (double handle); - void interpreter_event (const octave::fcn_callback& fcn); - void interpreter_event (const octave::meth_callback& meth); + public slots: - void create_object (double handle); + void interpreter_event (const octave::fcn_callback& fcn); + void interpreter_event (const octave::meth_callback& meth); - void gh_callback_event (const graphics_handle& h, const std::string& name); + void create_object (double handle); - void gh_callback_event (const graphics_handle& h, const std::string& name, - const octave_value& data); + void gh_callback_event (const graphics_handle& h, const std::string& name); - void gh_set_event (const graphics_handle& h, const std::string& name, - const octave_value& value); + void gh_callback_event (const graphics_handle& h, const std::string& name, + const octave_value& data); - void gh_set_event (const graphics_handle& h, const std::string& name, - const octave_value& value, bool notify_toolkit); + void gh_set_event (const graphics_handle& h, const std::string& name, + const octave_value& value); + + void gh_set_event (const graphics_handle& h, const std::string& name, + const octave_value& value, bool notify_toolkit); - void gh_set_event (const graphics_handle& h, const std::string& name, - const octave_value& value, bool notify_toolkit, - bool redraw_figure); -private: + void gh_set_event (const graphics_handle& h, const std::string& name, + const octave_value& value, bool notify_toolkit, + bool redraw_figure); + private: - octave::interpreter& m_interpreter; - - octave::base_qobject& m_octave_qobj; -}; + octave::interpreter& m_interpreter; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/qterminal/libqterminal/QTerminal.cc --- a/libgui/qterminal/libqterminal/QTerminal.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/qterminal/libqterminal/QTerminal.cc Tue Dec 06 15:45:27 2022 -0500 @@ -38,6 +38,7 @@ #include "gui-preferences-global.h" #include "gui-preferences-cs.h" #include "gui-preferences-sc.h" +#include "gui-settings.h" #include "octave-qobject.h" #include "resource-manager.h" @@ -199,32 +200,31 @@ } void -QTerminal::notice_settings (const gui_settings *settings) +QTerminal::notice_settings (void) { - if (! settings) - return; + octave::gui_settings settings; // Set terminal font: QFont term_font = QFont (); term_font.setStyleHint (QFont::TypeWriter); - QString default_font = settings->value (global_mono_font).toString (); + QString default_font = settings.value (global_mono_font).toString (); term_font.setFamily - (settings->value (cs_font.key, default_font).toString ()); + (settings.value (cs_font.key, default_font).toString ()); term_font.setPointSize - (settings->value (cs_font_size).toInt ()); + (settings.value (cs_font_size).toInt ()); setTerminalFont (term_font); QFontMetrics metrics (term_font); setMinimumSize (metrics.maxWidth ()*16, metrics.height ()*3); QString cursor_type - = settings->value (cs_cursor).toString (); + = settings.value (cs_cursor).toString (); bool cursor_blinking; - if (settings->contains (global_cursor_blinking.key)) - cursor_blinking = settings->value (global_cursor_blinking).toBool (); + if (settings.contains (global_cursor_blinking.key)) + cursor_blinking = settings.value (global_cursor_blinking).toBool (); else - cursor_blinking = settings->value (cs_cursor_blinking).toBool (); + cursor_blinking = settings.value (cs_cursor_blinking).toBool (); for (int ct = IBeamCursor; ct <= UnderlineCursor; ct++) { @@ -236,47 +236,47 @@ } bool cursorUseForegroundColor - = settings->value (cs_cursor_use_fgcol).toBool (); + = settings.value (cs_cursor_use_fgcol).toBool (); - int mode = settings->value (cs_color_mode).toInt (); + int mode = settings.value (cs_color_mode).toInt (); - setForegroundColor (settings->color_value (cs_colors[0], mode)); + setForegroundColor (settings.color_value (cs_colors[0], mode)); - setBackgroundColor (settings->color_value (cs_colors[1], mode)); + setBackgroundColor (settings.color_value (cs_colors[1], mode)); - setSelectionColor (settings->color_value (cs_colors[2], mode)); + setSelectionColor (settings.color_value (cs_colors[2], mode)); setCursorColor (cursorUseForegroundColor, - settings->color_value (cs_colors[3], mode)); + settings.color_value (cs_colors[3], mode)); - setScrollBufferSize (settings->value (cs_hist_buffer).toInt ()); + setScrollBufferSize (settings.value (cs_hist_buffer).toInt ()); // If the Copy shortcut is Ctrl+C, then the Copy action also emits // a signal for interrupting the current code executed by the worker. // If the Copy shortcut is not Ctrl+C, an extra interrupt action is // set up for emitting the interrupt signal. - QString sc = settings->sc_value (sc_main_edit_copy); + QString sc = settings.sc_value (sc_main_edit_copy); // Dis- or enable extra interrupt action: We need an extra option when // copy shortcut is not Ctrl-C or when global shortcuts (like copy) are // disabled. bool extra_ir_action = (sc != QKeySequence (Qt::ControlModifier | Qt::Key_C).toString ()) - || settings->value (sc_prevent_rl_conflicts).toBool (); + || settings.value (sc_prevent_rl_conflicts).toBool (); _interrupt_action->setEnabled (extra_ir_action); has_extra_interrupt (extra_ir_action); // check whether shortcut Ctrl-D is in use by the main-window - bool ctrld = settings->value (sc_main_ctrld).toBool (); + bool ctrld = settings.value (sc_main_ctrld).toBool (); _nop_action->setEnabled (! ctrld); } void QTerminal::construct (octave::base_qobject& oct_qobj) { - octave::resource_manager& rmgr = oct_qobj.get_resource_manager (); + octave::gui_settings settings; // context menu setContextMenuPolicy (Qt::CustomContextMenu); @@ -284,11 +284,11 @@ _contextMenu = new QMenu (this); _copy_action - = _contextMenu->addAction (rmgr.icon ("edit-copy"), tr ("Copy"), this, + = _contextMenu->addAction (settings.icon ("edit-copy"), tr ("Copy"), this, SLOT (copyClipboard ())); _paste_action - = _contextMenu->addAction (rmgr.icon ("edit-paste"), tr ("Paste"), this, + = _contextMenu->addAction (settings.icon ("edit-paste"), tr ("Paste"), this, SLOT (pasteClipboard ())); _contextMenu->addSeparator (); diff -r 29d734430e5f -r deb553ac2c54 libgui/qterminal/libqterminal/QTerminal.h --- a/libgui/qterminal/libqterminal/QTerminal.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/qterminal/libqterminal/QTerminal.h Tue Dec 06 15:45:27 2022 -0500 @@ -30,13 +30,6 @@ #include #include -// For now, we need to use the following #include and using statement -// for the signal/slot macros. Could maybe change later when using -// Qt5-style signal/slot connections. -#include "gui-settings.h" - -using octave::gui_settings; - namespace octave { class base_qobject; @@ -126,7 +119,7 @@ virtual void handleCustomContextMenuRequested (const QPoint& at); - void notice_settings (const gui_settings *settings); + void notice_settings (void); virtual void init_terminal_size (void) { } diff -r 29d734430e5f -r deb553ac2c54 libgui/src/command-widget.cc --- a/libgui/src/command-widget.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/command-widget.cc Tue Dec 06 15:45:27 2022 -0500 @@ -44,261 +44,264 @@ #include "event-manager.h" #include "gui-preferences-cs.h" #include "gui-preferences-global.h" +#include "gui-settings.h" #include "gui-utils.h" #include "input.h" #include "interpreter.h" OCTAVE_BEGIN_NAMESPACE(octave) -command_widget::command_widget (base_qobject& oct_qobj, QWidget *p) -: QWidget (p), m_incomplete_parse (false), - m_prompt (QString ()), - m_console (new console (this, oct_qobj)) -{ - QPushButton *pause_button = new QPushButton (tr("Pause"), this); - QPushButton *stop_button = new QPushButton (tr("Stop"), this); - QPushButton *resume_button = new QPushButton (tr("Continue"), this); + command_widget::command_widget (base_qobject& oct_qobj, QWidget *p) + : QWidget (p), m_incomplete_parse (false), + m_prompt (QString ()), + m_console (new console (this, oct_qobj)) + { + QPushButton *pause_button = new QPushButton (tr("Pause"), this); + QPushButton *stop_button = new QPushButton (tr("Stop"), this); + QPushButton *resume_button = new QPushButton (tr("Continue"), this); - QGroupBox *input_group_box = new QGroupBox (); - QHBoxLayout *input_layout = new QHBoxLayout; - input_layout->addWidget (pause_button); - input_layout->addWidget (stop_button); - input_layout->addWidget (resume_button); - input_group_box->setLayout (input_layout); + QGroupBox *input_group_box = new QGroupBox (); + QHBoxLayout *input_layout = new QHBoxLayout; + input_layout->addWidget (pause_button); + input_layout->addWidget (stop_button); + input_layout->addWidget (resume_button); + input_group_box->setLayout (input_layout); - QVBoxLayout *main_layout = new QVBoxLayout (); - main_layout->addWidget (m_console); - main_layout->addWidget (input_group_box); + QVBoxLayout *main_layout = new QVBoxLayout (); + main_layout->addWidget (m_console); + main_layout->addWidget (input_group_box); + + setLayout (main_layout); - setLayout (main_layout); + setFocusProxy (m_console); - setFocusProxy (m_console); + connect (pause_button, &QPushButton::clicked, + this, &command_widget::interpreter_pause); - connect (pause_button, &QPushButton::clicked, - this, &command_widget::interpreter_pause); + connect (resume_button, &QPushButton::clicked, + this, &command_widget::interpreter_resume); - connect (resume_button, &QPushButton::clicked, - this, &command_widget::interpreter_resume); - - connect (stop_button, &QPushButton::clicked, - this, &command_widget::interpreter_stop); + connect (stop_button, &QPushButton::clicked, + this, &command_widget::interpreter_stop); - connect (this, &command_widget::new_command_line_signal, - m_console, &console::new_command_line); + connect (this, &command_widget::new_command_line_signal, + m_console, &console::new_command_line); - insert_interpreter_output ("\n\n Welcome to Octave\n\n"); + insert_interpreter_output ("\n\n Welcome to Octave\n\n"); -} + } -void command_widget::init_command_prompt () -{ - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD + void command_widget::init_command_prompt () + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD - event_manager& evmgr = interp.get_event_manager (); - input_system& input_sys = interp.get_input_system (); - std::string prompt = input_sys.PS1 (); - evmgr.update_prompt (command_editor::decode_prompt_string (prompt)); + event_manager& evmgr = interp.get_event_manager (); + input_system& input_sys = interp.get_input_system (); + std::string prompt = input_sys.PS1 (); + evmgr.update_prompt (command_editor::decode_prompt_string (prompt)); - emit new_command_line_signal (); - }); -} + emit new_command_line_signal (); + }); + } + + void command_widget::update_prompt (const QString& prompt) + { + m_prompt = prompt; + } -void command_widget::update_prompt (const QString& prompt) -{ - m_prompt = prompt; -} + QString command_widget::prompt () + { + return m_prompt; + } -QString command_widget::prompt () -{ - return m_prompt; -} - -void command_widget::insert_interpreter_output (const QString& msg) -{ - m_console->append (msg); -} + void command_widget::insert_interpreter_output (const QString& msg) + { + m_console->append (msg); + } -void command_widget::process_input_line (const QString& input_line) -{ - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD + void command_widget::process_input_line (const QString& input_line) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + interp.parse_and_execute (input_line.toStdString (), + m_incomplete_parse); - interp.parse_and_execute (input_line.toStdString (), - m_incomplete_parse); + event_manager& evmgr = interp.get_event_manager (); + input_system& input_sys = interp.get_input_system (); - event_manager& evmgr = interp.get_event_manager (); - input_system& input_sys = interp.get_input_system (); + std::string prompt + = m_incomplete_parse ? input_sys.PS2 () : input_sys.PS1 (); - std::string prompt - = m_incomplete_parse ? input_sys.PS2 () : input_sys.PS1 (); + evmgr.update_prompt (command_editor::decode_prompt_string (prompt)); + + emit new_command_line_signal (); + }); - evmgr.update_prompt (command_editor::decode_prompt_string (prompt)); + } + + void command_widget::notice_settings (void) + { + gui_settings settings; - emit new_command_line_signal (); - }); - -} + // Set terminal font: + QFont term_font = QFont (); + term_font.setStyleHint (QFont::TypeWriter); + QString default_font = settings.value (global_mono_font).toString (); + term_font.setFamily + (settings.value (cs_font.key, default_font).toString ()); + term_font.setPointSize + (settings.value (cs_font_size).toInt ()); -void command_widget::notice_settings (const gui_settings *settings) -{ - // Set terminal font: - QFont term_font = QFont (); - term_font.setStyleHint (QFont::TypeWriter); - QString default_font = settings->value (global_mono_font).toString (); - term_font.setFamily - (settings->value (cs_font.key, default_font).toString ()); - term_font.setPointSize - (settings->value (cs_font_size).toInt ()); + m_console->setFont (term_font); - m_console->setFont (term_font); + // Colors + int mode = settings.value (cs_color_mode).toInt (); + QColor fgc = settings.color_value (cs_colors[0], mode); + QColor bgc = settings.color_value (cs_colors[1], mode); - // Colors - int mode = settings->value (cs_color_mode).toInt (); - QColor fgc = settings->color_value (cs_colors[0], mode); - QColor bgc = settings->color_value (cs_colors[1], mode); + m_console->setStyleSheet (QString ("color: %1; background-color:%2;") + .arg (fgc.name ()).arg (bgc.name ())); + } - m_console->setStyleSheet (QString ("color: %1; background-color:%2;") - .arg (fgc.name ()).arg (bgc.name ())); -} - -// The console itself using QScintilla. -// This implementation is partly based on the basic concept of -// "qpconsole" as proposed by user "DerManu" in the Qt-forum thread -// https://forum.qt.io/topic/28765/command-terminal-using-qtextedit + // The console itself using QScintilla. + // This implementation is partly based on the basic concept of + // "qpconsole" as proposed by user "DerManu" in the Qt-forum thread + // https://forum.qt.io/topic/28765/command-terminal-using-qtextedit -console::console (command_widget *p, base_qobject&) - : QsciScintilla (p), - m_command_position (-1), - m_cursor_position (0), - m_text_changed (false), - m_command_widget (p), - m_last_key_string (QString ()) -{ - setMargins (0); - setWrapMode (QsciScintilla::WrapWord); + console::console (command_widget *p, base_qobject&) + : QsciScintilla (p), + m_command_position (-1), + m_cursor_position (0), + m_text_changed (false), + m_command_widget (p), + m_last_key_string (QString ()) + { + setMargins (0); + setWrapMode (QsciScintilla::WrapWord); - connect (this, SIGNAL (cursorPositionChanged (int, int)), - this, SLOT (cursor_position_changed (int, int))); + connect (this, SIGNAL (cursorPositionChanged (int, int)), + this, SLOT (cursor_position_changed (int, int))); - connect (this, SIGNAL (textChanged (void)), - this, SLOT (text_changed (void))); + connect (this, SIGNAL (textChanged (void)), + this, SLOT (text_changed (void))); - connect (this, SIGNAL (modificationAttempted (void)), - this, SLOT (move_cursor_to_end (void))); -} + connect (this, SIGNAL (modificationAttempted (void)), + this, SLOT (move_cursor_to_end (void))); + } -// Prepare a new command line with the current prompt -void console::new_command_line (const QString& command) -{ - if (! text (lines () -1).isEmpty ()) - append ("\n"); + // Prepare a new command line with the current prompt + void console::new_command_line (const QString& command) + { + if (! text (lines () -1).isEmpty ()) + append ("\n"); - append_string (m_command_widget->prompt ()); + append_string (m_command_widget->prompt ()); - int line, index; - getCursorPosition (&line,&index); - m_command_position = positionFromLineIndex (line, index); + int line, index; + getCursorPosition (&line,&index); + m_command_position = positionFromLineIndex (line, index); - append_string (command); -} + append_string (command); + } -// Accept the current command line (or block) -void console::accept_command_line () -{ - QString input_line = text (lines () - 1); + // Accept the current command line (or block) + void console::accept_command_line () + { + QString input_line = text (lines () - 1); - if (input_line.startsWith (m_command_widget->prompt ())) - input_line.remove(0, m_command_widget->prompt ().length ()); + if (input_line.startsWith (m_command_widget->prompt ())) + input_line.remove(0, m_command_widget->prompt ().length ()); - input_line = input_line.trimmed (); + input_line = input_line.trimmed (); - append_string ("\n"); + append_string ("\n"); - if (input_line.isEmpty ()) - new_command_line (); - else - m_command_widget->process_input_line (input_line); -} + if (input_line.isEmpty ()) + new_command_line (); + else + m_command_widget->process_input_line (input_line); + } -// Execute a command -void console::execute_command (const QString& command) -{ - if (command.trimmed ().isEmpty ()) - return; + // Execute a command + void console::execute_command (const QString& command) + { + if (command.trimmed ().isEmpty ()) + return; - new_command_line (command); - accept_command_line (); -} + new_command_line (command); + accept_command_line (); + } -// Append a string and update the curdor püosition -void console::append_string (const QString& string) -{ - setReadOnly (false); - append (string); + // Append a string and update the curdor püosition + void console::append_string (const QString& string) + { + setReadOnly (false); + append (string); - int line, index; - lineIndexFromPosition (text ().length (), &line, &index); + int line, index; + lineIndexFromPosition (text ().length (), &line, &index); - setCursorPosition (line, index); -} + setCursorPosition (line, index); + } -// Cursor position changed: Are we in the command line or not? -void console::cursor_position_changed (int line, int col) -{ - m_cursor_position = positionFromLineIndex (line, col); - if (m_cursor_position < m_command_position) - { - // We are in the read only area - if (m_text_changed && (m_cursor_position == m_command_position - 1)) - { - setReadOnly (false); - insert (m_command_widget->prompt ().right (1)); // And here we have tried to remove the prompt by Backspace - setCursorPosition (line+1, col); - } - setReadOnly (true); - } - else - setReadOnly (false); // Writable area + // Cursor position changed: Are we in the command line or not? + void console::cursor_position_changed (int line, int col) + { + m_cursor_position = positionFromLineIndex (line, col); + if (m_cursor_position < m_command_position) + { + // We are in the read only area + if (m_text_changed && (m_cursor_position == m_command_position - 1)) + { + setReadOnly (false); + insert (m_command_widget->prompt ().right (1)); // And here we have tried to remove the prompt by Backspace + setCursorPosition (line+1, col); + } + setReadOnly (true); + } + else + setReadOnly (false); // Writable area - m_text_changed = false; -} + m_text_changed = false; + } -// User attempted to type on read only mode: move cursor at end and allow -// editing -void console::move_cursor_to_end (void) -{ - if ((! m_last_key_string.isEmpty ()) && (m_last_key_string.at (0).isPrint ())) - { - append_string (m_last_key_string); - setReadOnly (true); // Avoid that changing read only text is done afterwards - } -} + // User attempted to type on read only mode: move cursor at end and allow + // editing + void console::move_cursor_to_end (void) + { + if ((! m_last_key_string.isEmpty ()) && (m_last_key_string.at (0).isPrint ())) + { + append_string (m_last_key_string); + setReadOnly (true); // Avoid that changing read only text is done afterwards + } + } -// Text has changed: is cursor still in "writable" area? -// This signal seems to be emitted before cursor position changed. -void console::text_changed (void) -{ - m_text_changed = true; -} + // Text has changed: is cursor still in "writable" area? + // This signal seems to be emitted before cursor position changed. + void console::text_changed (void) + { + m_text_changed = true; + } -// Re-implement key event -void console::keyPressEvent (QKeyEvent *e) -{ - if (e->key () == Qt::Key_Return) - // On "return", accept the current command line - accept_command_line (); - else - { - // Otherwise, store text process the expected event - m_last_key_string = e->text (); - QsciScintilla::keyPressEvent(e); - } -} + // Re-implement key event + void console::keyPressEvent (QKeyEvent *e) + { + if (e->key () == Qt::Key_Return) + // On "return", accept the current command line + accept_command_line (); + else + { + // Otherwise, store text process the expected event + m_last_key_string = e->text (); + QsciScintilla::keyPressEvent(e); + } + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/command-widget.h --- a/libgui/src/command-widget.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/command-widget.h Tue Dec 06 15:45:27 2022 -0500 @@ -30,97 +30,100 @@ #include -#include "octave-qobject.h" -#include "gui-settings.h" +// FIXME: We need the following header for the fcn_callback and +// meth_callback typedefs. Maybe it would be better to declare those in +// a separate file because inclding "event-manager.h" pulls in a lot of +// other unnecessary declarations. +#include "event-manager.h" class QsciScintilla; OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class command_widget; + class base_qobject; + class command_widget; -class console : public QsciScintilla -{ - Q_OBJECT + class console : public QsciScintilla + { + Q_OBJECT -public: + public: - console (command_widget *p, base_qobject& oct_qobj); + console (command_widget *p, base_qobject& oct_qobj); -public slots: + public slots: - void cursor_position_changed (int line, int col); + void cursor_position_changed (int line, int col); - void text_changed (void); + void text_changed (void); - void move_cursor_to_end (void); + void move_cursor_to_end (void); - void new_command_line (const QString& command = QString ()); + void new_command_line (const QString& command = QString ()); - void execute_command (const QString& command); + void execute_command (const QString& command); -protected: + protected: - void keyPressEvent (QKeyEvent *e); + void keyPressEvent (QKeyEvent *e); -private: + private: - void append_string (const QString& string); + void append_string (const QString& string); - void accept_command_line (void); + void accept_command_line (void); - int m_command_position; - int m_cursor_position; - bool m_text_changed; - command_widget *m_command_widget; - QString m_last_key_string; + int m_command_position; + int m_cursor_position; + bool m_text_changed; + command_widget *m_command_widget; + QString m_last_key_string; -}; + }; -class command_widget : public QWidget -{ - Q_OBJECT + class command_widget : public QWidget + { + Q_OBJECT -public: + public: - command_widget (base_qobject& oct_qobj, QWidget *p); + command_widget (base_qobject& oct_qobj, QWidget *p); - console * get_console ( ) { return m_console; }; + console * get_console ( ) { return m_console; }; - void init_command_prompt (); + void init_command_prompt (); - QString prompt (void); + QString prompt (void); -signals: + signals: - void clear_line_edit (void); + void clear_line_edit (void); - void interpreter_pause (void); - void interpreter_resume (void); - void interpreter_stop (void); + void interpreter_pause (void); + void interpreter_resume (void); + void interpreter_stop (void); - void interpreter_event (const fcn_callback& fcn); - void interpreter_event (const meth_callback& meth); + void interpreter_event (const fcn_callback& fcn); + void interpreter_event (const meth_callback& meth); - void new_command_line_signal (const QString& command = QString ()); + void new_command_line_signal (const QString& command = QString ()); -public slots: + public slots: - void process_input_line (const QString& input_line); + void process_input_line (const QString& input_line); - void update_prompt (const QString& prompt); + void update_prompt (const QString& prompt); - void insert_interpreter_output (const QString& msg); + void insert_interpreter_output (const QString& msg); - void notice_settings (const gui_settings *settings); + void notice_settings (void); -private: + private: - bool m_incomplete_parse; - QString m_prompt; - console *m_console; -}; + bool m_incomplete_parse; + QString m_prompt; + console *m_console; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/community-news.cc --- a/libgui/src/community-news.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/community-news.cc Tue Dec 06 15:45:27 2022 -0500 @@ -35,105 +35,99 @@ #include "gui-utils.h" #include "gui-preferences-dw.h" #include "gui-preferences-nr.h" +#include "gui-settings.h" #include "news-reader.h" -#include "octave-qobject.h" OCTAVE_BEGIN_NAMESPACE(octave) -community_news::community_news (base_qobject& oct_qobj, int serial) -: QWidget (nullptr), m_browser (nullptr) -{ - construct (oct_qobj, "https://octave.org", "community-news.html", serial); -} + community_news::community_news (int serial) + : QWidget (nullptr), m_browser (nullptr) + { + construct ("https://octave.org", "community-news.html", serial); + } -community_news::community_news (base_qobject& oct_qobj, QWidget *parent, - const QString& base_url, const QString& page, - int serial) - : QWidget (parent), m_browser (nullptr) -{ - construct (oct_qobj, base_url, page, serial); -} + community_news::community_news (QWidget *parent, const QString& base_url, + const QString& page, int serial) + : QWidget (parent), m_browser (nullptr) + { + construct (base_url, page, serial); + } -void community_news::construct (base_qobject& oct_qobj, - const QString& base_url, const QString& page, - int serial) -{ - m_browser = new QTextBrowser (this); + void community_news::construct (const QString& base_url, const QString& page, + int serial) + { + m_browser = new QTextBrowser (this); - m_browser->setObjectName ("OctaveNews"); - m_browser->setOpenExternalLinks (true); + m_browser->setObjectName ("OctaveNews"); + m_browser->setOpenExternalLinks (true); - QVBoxLayout *vlayout = new QVBoxLayout; + QVBoxLayout *vlayout = new QVBoxLayout; - vlayout->addWidget (m_browser); + vlayout->addWidget (m_browser); - setLayout (vlayout); - setWindowTitle (tr ("Octave Community News")); + setLayout (vlayout); + setWindowTitle (tr ("Octave Community News")); - int win_x, win_y; - get_screen_geometry (win_x, win_y); + int win_x, win_y; + get_screen_geometry (win_x, win_y); - resize (win_x/2, win_y/2); - move ((win_x - width ())/2, (win_y - height ())/2); + resize (win_x/2, win_y/2); + move ((win_x - width ())/2, (win_y - height ())/2); - resource_manager& rmgr = oct_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - QString icon; - QString icon_set = settings->value (dw_icon_set).toString (); - if (icon_set != "NONE") - // No extra icon for Community news, take the one of the release notes - icon = dw_icon_set_names[icon_set] + "ReleaseWidget.png"; - else - icon = dw_icon_set_names[icon_set]; + QString icon; + QString icon_set = settings.value (dw_icon_set).toString (); + if (icon_set != "NONE") + // No extra icon for Community news, take the one of the release notes + icon = dw_icon_set_names[icon_set] + "ReleaseWidget.png"; + else + icon = dw_icon_set_names[icon_set]; - setWindowIcon (QIcon (icon)); - - // FIXME: This is a news reader preference, so shouldn't it be used - // in the news_reader object? + setWindowIcon (QIcon (icon)); - bool connect_to_web - = (settings - ? settings->value (nr_allow_connection).toBool () - : true); + // FIXME: This is a news reader preference, so shouldn't it be used + // in the news_reader object? + + bool connect_to_web = settings.value (nr_allow_connection).toBool (); + + QThread *worker_thread = new QThread; - QThread *worker_thread = new QThread; + news_reader *reader + = new news_reader (base_url, page, serial, connect_to_web); - news_reader *reader = new news_reader (oct_qobj, base_url, page, - serial, connect_to_web); + reader->moveToThread (worker_thread); - reader->moveToThread (worker_thread); + connect (reader, &news_reader::display_news_signal, + this, &community_news::set_news); - connect (reader, &news_reader::display_news_signal, - this, &community_news::set_news); + connect (worker_thread, &QThread::started, + reader, &news_reader::process); - connect (worker_thread, &QThread::started, - reader, &news_reader::process); + connect (reader, &news_reader::finished, worker_thread, &QThread::quit); - connect (reader, &news_reader::finished, worker_thread, &QThread::quit); - - connect (reader, &news_reader::finished, reader, &news_reader::deleteLater); + connect (reader, &news_reader::finished, reader, &news_reader::deleteLater); - connect (worker_thread, &QThread::finished, - worker_thread, &QThread::deleteLater); + connect (worker_thread, &QThread::finished, + worker_thread, &QThread::deleteLater); - worker_thread->start (); -} + worker_thread->start (); + } -void community_news::set_news (const QString& news) -{ - m_browser->setHtml (news); -} + void community_news::set_news (const QString& news) + { + m_browser->setHtml (news); + } -void community_news::display (void) -{ - if (! isVisible ()) - show (); - else if (isMinimized ()) - showNormal (); + void community_news::display (void) + { + if (! isVisible ()) + show (); + else if (isMinimized ()) + showNormal (); - raise (); - activateWindow (); -} + raise (); + activateWindow (); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/community-news.h --- a/libgui/src/community-news.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/community-news.h Tue Dec 06 15:45:27 2022 -0500 @@ -33,36 +33,33 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; + class community_news : public QWidget + { + Q_OBJECT -class community_news : public QWidget -{ - Q_OBJECT + public: -public: - - community_news (base_qobject& oct_qobj, int serial); + community_news (int serial); - community_news (base_qobject& oct_qobj, QWidget *parent = nullptr, - const QString& base_url = "https://octave.org", - const QString& page = "community-news.html", - int serial = -1); + community_news (QWidget *parent = nullptr, + const QString& base_url = "https://octave.org", + const QString& page = "community-news.html", + int serial = -1); - ~community_news (void) = default; - -public slots: + ~community_news (void) = default; - void set_news (const QString& news); + public slots: - void display (void); + void set_news (const QString& news); -private: + void display (void); + + private: - void construct (base_qobject& oct_qobj, const QString& base_url, - const QString& page, int serial); + void construct (const QString& base_url, const QString& page, int serial); - QTextBrowser *m_browser; -}; + QTextBrowser *m_browser; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/dialog.cc --- a/libgui/src/dialog.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/dialog.cc Tue Dec 06 15:45:27 2022 -0500 @@ -42,670 +42,668 @@ #include #include "dialog.h" -#include "octave-qobject.h" #include "gui-preferences-global.h" +#include "gui-settings.h" OCTAVE_BEGIN_NAMESPACE(octave) -QUIWidgetCreator::QUIWidgetCreator (base_qobject& oct_qobj) -: QObject (), m_octave_qobj (oct_qobj), m_dialog_result (-1), - m_dialog_button (), m_string_list (), m_list_index (), m_path_name () -{ - connect (this, &QUIWidgetCreator::create_dialog, - this, &QUIWidgetCreator::handle_create_dialog); + QUIWidgetCreator::QUIWidgetCreator () + : QObject (), m_dialog_result (-1), m_dialog_button (), + m_string_list (), m_list_index (), m_path_name () + { + connect (this, &QUIWidgetCreator::create_dialog, + this, &QUIWidgetCreator::handle_create_dialog); - connect (this, &QUIWidgetCreator::create_listview, - this, &QUIWidgetCreator::handle_create_listview); + connect (this, &QUIWidgetCreator::create_listview, + this, &QUIWidgetCreator::handle_create_listview); - connect (this, &QUIWidgetCreator::create_inputlayout, - this, &QUIWidgetCreator::handle_create_inputlayout); + connect (this, &QUIWidgetCreator::create_inputlayout, + this, &QUIWidgetCreator::handle_create_inputlayout); - connect (this, &QUIWidgetCreator::create_filedialog, - this, &QUIWidgetCreator::handle_create_filedialog); -} + connect (this, &QUIWidgetCreator::create_filedialog, + this, &QUIWidgetCreator::handle_create_filedialog); + } -QString QUIWidgetCreator::rm_amp (const QString& text) -{ - QString text_wo_amp = text; - text_wo_amp.replace (QRegExp ("&(\\w)"), "\\1"); - return text_wo_amp; -} + QString QUIWidgetCreator::rm_amp (const QString& text) + { + QString text_wo_amp = text; + text_wo_amp.replace (QRegExp ("&(\\w)"), "\\1"); + return text_wo_amp; + } -QString QUIWidgetCreator::message_dialog (const QString& message, - const QString& title, - const QString& icon, - const QStringList& buttons, - const QString& defbutton, - const QStringList& role) -{ - QMutexLocker autolock (&m_mutex); + QString QUIWidgetCreator::message_dialog (const QString& message, + const QString& title, + const QString& icon, + const QStringList& buttons, + const QString& defbutton, + const QStringList& role) + { + QMutexLocker autolock (&m_mutex); - // Store button text before a window-manager adds accelerators. + // Store button text before a window-manager adds accelerators. - m_button_list = buttons; + m_button_list = buttons; - // Use the last button in the list as the reject result, i.e., when - // no button is pressed such as in the case of the upper right close - // tab. - if (! buttons.isEmpty ()) - m_dialog_button = buttons.last (); + // Use the last button in the list as the reject result, i.e., when + // no button is pressed such as in the case of the upper right close + // tab. + if (! buttons.isEmpty ()) + m_dialog_button = buttons.last (); - QString xicon = icon; - if (xicon.isEmpty ()) - xicon = "none"; + QString xicon = icon; + if (xicon.isEmpty ()) + xicon = "none"; - emit create_dialog (message, title, xicon, buttons, defbutton, role); + emit create_dialog (message, title, xicon, buttons, defbutton, role); - // Wait while the user is responding to message box. - wait (); + // Wait while the user is responding to message box. + wait (); - // The GUI has sent a signal and the thread has been awakened. - return m_dialog_button; -}; + // The GUI has sent a signal and the thread has been awakened. + return m_dialog_button; + }; -QPair -QUIWidgetCreator::list_dialog (const QStringList& list, const QString& mode, - int wd, int ht, const QList& initial, - const QString& name, - const QStringList& prompt, - const QString& ok_string, - const QString& cancel_string) -{ - if (list.isEmpty ()) - return QPair (); + QPair + QUIWidgetCreator::list_dialog (const QStringList& list, const QString& mode, + int wd, int ht, const QList& initial, + const QString& name, + const QStringList& prompt, + const QString& ok_string, + const QString& cancel_string) + { + if (list.isEmpty ()) + return QPair (); - QMutexLocker autolock (&m_mutex); + QMutexLocker autolock (&m_mutex); - emit create_listview (list, mode, wd, ht, initial, name, - prompt, ok_string, cancel_string); + emit create_listview (list, mode, wd, ht, initial, name, + prompt, ok_string, cancel_string); - // Wait while the user is responding to message box. - wait (); + // Wait while the user is responding to message box. + wait (); - // The GUI has sent a signal and the thread has been awakened. - return QPair (m_list_index, m_dialog_result); -}; + // The GUI has sent a signal and the thread has been awakened. + return QPair (m_list_index, m_dialog_result); + }; -// Create a message dialog with specified string, buttons and -// decorative text. + // Create a message dialog with specified string, buttons and + // decorative text. -QStringList QUIWidgetCreator::input_dialog (const QStringList& prompt, - const QString& title, - const QFloatList& nr, - const QFloatList& nc, - const QStringList& defaults) -{ - if (prompt.isEmpty ()) - return QStringList (); + QStringList QUIWidgetCreator::input_dialog (const QStringList& prompt, + const QString& title, + const QFloatList& nr, + const QFloatList& nc, + const QStringList& defaults) + { + if (prompt.isEmpty ()) + return QStringList (); - QMutexLocker autolock (&m_mutex); + QMutexLocker autolock (&m_mutex); - emit create_inputlayout (prompt, title, nr, nc, defaults); + emit create_inputlayout (prompt, title, nr, nc, defaults); - // Wait while the user is responding to message box. - wait (); + // Wait while the user is responding to message box. + wait (); - // The GUI has sent a signal and the thread has been awakened. - return m_string_list; -}; + // The GUI has sent a signal and the thread has been awakened. + return m_string_list; + }; -QStringList QUIWidgetCreator::file_dialog (const QStringList& filters, - const QString& title, - const QString& filename, - const QString& dirname, - const QString& multimode) -{ - QMutexLocker autolock (&m_mutex); + QStringList QUIWidgetCreator::file_dialog (const QStringList& filters, + const QString& title, + const QString& filename, + const QString& dirname, + const QString& multimode) + { + QMutexLocker autolock (&m_mutex); - emit create_filedialog (filters, title, filename, dirname, multimode); + emit create_filedialog (filters, title, filename, dirname, multimode); - // Wait while the user is responding to dialog. - wait (); + // Wait while the user is responding to dialog. + wait (); - // The GUI has sent a signal and the thread has been awakened. - // Add all the file dialog results to a string list. - QStringList retval; - retval << m_string_list - << m_path_name - << QString::number (m_dialog_result); + // The GUI has sent a signal and the thread has been awakened. + // Add all the file dialog results to a string list. + QStringList retval; + retval << m_string_list + << m_path_name + << QString::number (m_dialog_result); - return retval; -} + return retval; + } -void QUIWidgetCreator::handle_create_dialog (const QString& message, - const QString& title, - const QString& icon, - const QStringList& button, - const QString& defbutton, - const QStringList& role) -{ - MessageDialog *message_dialog - = new MessageDialog (m_octave_qobj, message, title, icon, - button, defbutton, role); + void QUIWidgetCreator::handle_create_dialog (const QString& message, + const QString& title, + const QString& icon, + const QStringList& button, + const QString& defbutton, + const QStringList& role) + { + MessageDialog *message_dialog + = new MessageDialog (message, title, icon, button, defbutton, role); - connect (message_dialog, &MessageDialog::buttonClicked, - this, &QUIWidgetCreator::dialog_button_clicked); + connect (message_dialog, &MessageDialog::buttonClicked, + this, &QUIWidgetCreator::dialog_button_clicked); - message_dialog->setAttribute (Qt::WA_DeleteOnClose); - message_dialog->show (); -} + message_dialog->setAttribute (Qt::WA_DeleteOnClose); + message_dialog->show (); + } -void QUIWidgetCreator::dialog_button_clicked (QAbstractButton *button) -{ - // button is NULL when dialog is closed. - if (button) - { - // Check for a matching button text while ignoring accelerators - // because the window manager may have added one in the passed - // button. + void QUIWidgetCreator::dialog_button_clicked (QAbstractButton *button) + { + // button is NULL when dialog is closed. + if (button) + { + // Check for a matching button text while ignoring accelerators + // because the window manager may have added one in the passed + // button. - QString text_clean = rm_amp (button->text ()); + QString text_clean = rm_amp (button->text ()); - for (int i = 0; i < m_button_list.count (); i++) - { - if (rm_amp (m_button_list.at (i)) == text_clean) - { - // Text w/o extra accelerator. - m_dialog_button = m_button_list.at (i); - break; - } - } - } + for (int i = 0; i < m_button_list.count (); i++) + { + if (rm_amp (m_button_list.at (i)) == text_clean) + { + // Text w/o extra accelerator. + m_dialog_button = m_button_list.at (i); + break; + } + } + } - // The value should always be 1 for the Octave functions. - m_dialog_result = 1; + // The value should always be 1 for the Octave functions. + m_dialog_result = 1; - // Wake up Octave process so that it continues. - wake_all (); -} + // Wake up Octave process so that it continues. + wake_all (); + } -// Create a list dialog with specified list, initially selected, mode, -// view size and decorative text. + // Create a list dialog with specified list, initially selected, mode, + // view size and decorative text. -void QUIWidgetCreator::handle_create_listview (const QStringList& list, - const QString& mode, - int wd, int ht, - const QIntList& initial, - const QString& name, - const QStringList& prompt, - const QString& ok_string, - const QString& cancel_string) -{ - ListDialog *list_dialog - = new ListDialog (m_octave_qobj, list, mode, wd, ht, initial, - name, prompt, ok_string, cancel_string); + void QUIWidgetCreator::handle_create_listview (const QStringList& list, + const QString& mode, + int wd, int ht, + const QIntList& initial, + const QString& name, + const QStringList& prompt, + const QString& ok_string, + const QString& cancel_string) + { + ListDialog *list_dialog + = new ListDialog (list, mode, wd, ht, initial, + name, prompt, ok_string, cancel_string); - connect (list_dialog, &ListDialog::finish_selection, - this, &QUIWidgetCreator::list_select_finished); + connect (list_dialog, &ListDialog::finish_selection, + this, &QUIWidgetCreator::list_select_finished); + + list_dialog->setAttribute (Qt::WA_DeleteOnClose); + list_dialog->show (); + } - list_dialog->setAttribute (Qt::WA_DeleteOnClose); - list_dialog->show (); -} + void QUIWidgetCreator::list_select_finished (const QIntList& selected, + int button_pressed) + { + // Store the value so that builtin functions can retrieve. -void QUIWidgetCreator::list_select_finished (const QIntList& selected, - int button_pressed) -{ - // Store the value so that builtin functions can retrieve. + m_list_index = selected; + m_dialog_result = button_pressed; - m_list_index = selected; - m_dialog_result = button_pressed; + // Wake up Octave process so that it continues. + wake_all (); + } - // Wake up Octave process so that it continues. - wake_all (); -} + // Create an input dialog with specified prompts and defaults, title + // and row/column size specifications. -// Create an input dialog with specified prompts and defaults, title -// and row/column size specifications. + void QUIWidgetCreator::handle_create_inputlayout (const QStringList& prompt, + const QString& title, + const QFloatList& nr, + const QFloatList& nc, + const QStringList& defaults) + { + InputDialog *input_dialog + = new InputDialog (prompt, title, nr, nc, defaults); -void QUIWidgetCreator::handle_create_inputlayout (const QStringList& prompt, - const QString& title, - const QFloatList& nr, - const QFloatList& nc, - const QStringList& defaults) -{ - InputDialog *input_dialog - = new InputDialog (m_octave_qobj, prompt, title, nr, nc, defaults); + connect (input_dialog, &InputDialog::finish_input, + this, &QUIWidgetCreator::input_finished); - connect (input_dialog, &InputDialog::finish_input, - this, &QUIWidgetCreator::input_finished); + input_dialog->setAttribute (Qt::WA_DeleteOnClose); + input_dialog->show (); + } - input_dialog->setAttribute (Qt::WA_DeleteOnClose); - input_dialog->show (); -} + void QUIWidgetCreator::input_finished (const QStringList& input, + int button_pressed) + { + // Store the value so that builtin functions can retrieve. + + m_string_list = input; + m_dialog_result = button_pressed; -void QUIWidgetCreator::input_finished (const QStringList& input, - int button_pressed) -{ - // Store the value so that builtin functions can retrieve. + // Wake up Octave process so that it continues. + wake_all (); + } - m_string_list = input; - m_dialog_result = button_pressed; - - // Wake up Octave process so that it continues. - wake_all (); -} + void QUIWidgetCreator::handle_create_filedialog (const QStringList& filters, + const QString& title, + const QString& filename, + const QString& dirname, + const QString& multimode) + { + FileDialog *file_dialog + = new FileDialog (filters, title, filename, dirname, multimode); -void QUIWidgetCreator::handle_create_filedialog (const QStringList& filters, - const QString& title, - const QString& filename, - const QString& dirname, - const QString& multimode) -{ - FileDialog *file_dialog - = new FileDialog (m_octave_qobj, filters, title, filename, - dirname, multimode); + connect (file_dialog, &FileDialog::finish_input, + this, &QUIWidgetCreator::filedialog_finished); + + file_dialog->setAttribute (Qt::WA_DeleteOnClose); + file_dialog->show (); + } - connect (file_dialog, &FileDialog::finish_input, - this, &QUIWidgetCreator::filedialog_finished); + void QUIWidgetCreator::filedialog_finished (const QStringList& files, + const QString& path, + int filterindex) + { + // Store the value so that builtin functions can retrieve. - file_dialog->setAttribute (Qt::WA_DeleteOnClose); - file_dialog->show (); -} + m_string_list = files; + m_dialog_result = filterindex; + m_path_name = path; -void QUIWidgetCreator::filedialog_finished (const QStringList& files, - const QString& path, - int filterindex) -{ - // Store the value so that builtin functions can retrieve. - - m_string_list = files; - m_dialog_result = filterindex; - m_path_name = path; - - // Wake up Octave process so that it continues. - wake_all (); -} + // Wake up Octave process so that it continues. + wake_all (); + } -MessageDialog::MessageDialog (base_qobject&, const QString& message, - const QString& title, const QString& qsicon, - const QStringList& qsbutton, - const QString& defbutton, - const QStringList& role) - : QMessageBox (QMessageBox::NoIcon, title.isEmpty () ? " " : title, - message) -{ - // Create a NonModal message. - setWindowModality (Qt::NonModal); + MessageDialog::MessageDialog (const QString& message, + const QString& title, const QString& qsicon, + const QStringList& qsbutton, + const QString& defbutton, + const QStringList& role) + : QMessageBox (QMessageBox::NoIcon, title.isEmpty () ? " " : title, + message) + { + // Create a NonModal message. + setWindowModality (Qt::NonModal); - // Interpret the icon string, because enumeration QMessageBox::Icon can't - // easily be made to pass through a signal. + // Interpret the icon string, because enumeration QMessageBox::Icon can't + // easily be made to pass through a signal. + + QMessageBox::Icon eicon = QMessageBox::NoIcon; - QMessageBox::Icon eicon = QMessageBox::NoIcon; + if (qsicon == "error") + eicon = QMessageBox::Critical; + else if (qsicon == "warn") + eicon = QMessageBox::Warning; + else if (qsicon == "help") + eicon = QMessageBox::Information; + else if (qsicon == "quest") + eicon = QMessageBox::Question; - if (qsicon == "error") - eicon = QMessageBox::Critical; - else if (qsicon == "warn") - eicon = QMessageBox::Warning; - else if (qsicon == "help") - eicon = QMessageBox::Information; - else if (qsicon == "quest") - eicon = QMessageBox::Question; + setIcon (eicon); - setIcon (eicon); - - int N = (qsbutton.size () < role.size () ? qsbutton.size () : role.size ()); + int N = (qsbutton.size () < role.size () ? qsbutton.size () : role.size ()); - if (N == 0) - addButton (QMessageBox::Ok); - else - { - for (int i = 0; i < N; i++) - { - // Interpret the button role string, because enumeration - // QMessageBox::ButtonRole can't be made to pass through a - // signal. + if (N == 0) + addButton (QMessageBox::Ok); + else + { + for (int i = 0; i < N; i++) + { + // Interpret the button role string, because enumeration + // QMessageBox::ButtonRole can't be made to pass through a + // signal. - QString srole = role.at (i); - QMessageBox::ButtonRole erole = QMessageBox::InvalidRole; - if (srole == "ResetRole") - erole = QMessageBox::ResetRole; - else if (srole == "YesRole") - erole = QMessageBox::YesRole; - else if (srole == "NoRole") - erole = QMessageBox::NoRole; - else if (srole == "RejectRole") - erole = QMessageBox::RejectRole; - else if (srole == "AcceptRole") - erole = QMessageBox::AcceptRole; + QString srole = role.at (i); + QMessageBox::ButtonRole erole = QMessageBox::InvalidRole; + if (srole == "ResetRole") + erole = QMessageBox::ResetRole; + else if (srole == "YesRole") + erole = QMessageBox::YesRole; + else if (srole == "NoRole") + erole = QMessageBox::NoRole; + else if (srole == "RejectRole") + erole = QMessageBox::RejectRole; + else if (srole == "AcceptRole") + erole = QMessageBox::AcceptRole; - QPushButton *pbutton = addButton (qsbutton.at (i), erole); - if (qsbutton.at (i) == defbutton) - setDefaultButton (pbutton); + QPushButton *pbutton = addButton (qsbutton.at (i), erole); + if (qsbutton.at (i) == defbutton) + setDefaultButton (pbutton); - // Make the last button the button pressed when key activated. - if (i == N-1) - { - // FIXME: Why define and then immediately test value? + // Make the last button the button pressed when key activated. + if (i == N-1) + { + // FIXME: Why define and then immediately test value? #define ACTIVE_ESCAPE 1 #if ACTIVE_ESCAPE - setEscapeButton (pbutton); + setEscapeButton (pbutton); #else - setEscapeButton (0); + setEscapeButton (0); #endif #undef ACTIVE_ESCAPE - } - } - } -} + } + } + } + } -ListDialog::ListDialog (base_qobject&, const QStringList& list, - const QString& mode, int wd, int ht, - const QList& initial, const QString& title, - const QStringList& prompt, - const QString& ok_string, - const QString& cancel_string) - : QDialog (), m_model (new QStringListModel (list, this)) -{ - QListView *view = new QListView; - view->setModel (m_model); + ListDialog::ListDialog (const QStringList& list, + const QString& mode, int wd, int ht, + const QList& initial, const QString& title, + const QStringList& prompt, + const QString& ok_string, + const QString& cancel_string) + : QDialog (), m_model (new QStringListModel (list, this)) + { + QListView *view = new QListView; + view->setModel (m_model); - if (mode == "single") - view->setSelectionMode (QAbstractItemView::SingleSelection); - else if (mode == "multiple") - view->setSelectionMode (QAbstractItemView::ExtendedSelection); - else - view->setSelectionMode (QAbstractItemView::NoSelection); + if (mode == "single") + view->setSelectionMode (QAbstractItemView::SingleSelection); + else if (mode == "multiple") + view->setSelectionMode (QAbstractItemView::ExtendedSelection); + else + view->setSelectionMode (QAbstractItemView::NoSelection); - selector = view->selectionModel (); - int i = 0; - for (auto it = initial.begin (); it != initial.end (); it++) - { - QModelIndex idx = m_model->index (initial.value (i++) - 1, 0, - QModelIndex ()); - selector->select (idx, QItemSelectionModel::Select); - } + selector = view->selectionModel (); + int i = 0; + for (auto it = initial.begin (); it != initial.end (); it++) + { + QModelIndex idx = m_model->index (initial.value (i++) - 1, 0, + QModelIndex ()); + selector->select (idx, QItemSelectionModel::Select); + } - bool fixed_layout = false; - if (wd > 0 && ht > 0) - { - view->setFixedSize (wd, ht); - fixed_layout = true; - } + bool fixed_layout = false; + if (wd > 0 && ht > 0) + { + view->setFixedSize (wd, ht); + fixed_layout = true; + } - view->setEditTriggers (QAbstractItemView::NoEditTriggers); + view->setEditTriggers (QAbstractItemView::NoEditTriggers); - QVBoxLayout *listLayout = new QVBoxLayout; - if (! prompt.isEmpty ()) - { - // For now, assume html-like Rich Text. May be incompatible - // with something down the road, but just testing capability. - QString prompt_string; - for (int j = 0; j < prompt.length (); j++) - { - if (j > 0) - // FIXME: Why define and then immediately test value? + QVBoxLayout *listLayout = new QVBoxLayout; + if (! prompt.isEmpty ()) + { + // For now, assume html-like Rich Text. May be incompatible + // with something down the road, but just testing capability. + QString prompt_string; + for (int j = 0; j < prompt.length (); j++) + { + if (j > 0) + // FIXME: Why define and then immediately test value? #define RICH_TEXT 1 #if RICH_TEXT - prompt_string.append ("
"); + prompt_string.append ("
"); #else - prompt_string.append ("\n"); + prompt_string.append ("\n"); #endif - prompt_string.append (prompt.at (j)); - } - QLabel *plabel = new QLabel (prompt_string); + prompt_string.append (prompt.at (j)); + } + QLabel *plabel = new QLabel (prompt_string); #if RICH_TEXT - plabel->setTextFormat (Qt::RichText); + plabel->setTextFormat (Qt::RichText); #endif #undef RICH_TEXT - listLayout->addWidget (plabel); - } - listLayout->addWidget (view); - QPushButton *select_all = new QPushButton (tr ("Select All")); - select_all->setVisible (mode == "multiple"); - listLayout->addWidget (select_all); + listLayout->addWidget (plabel); + } + listLayout->addWidget (view); + QPushButton *select_all = new QPushButton (tr ("Select All")); + select_all->setVisible (mode == "multiple"); + listLayout->addWidget (select_all); - QPushButton *buttonOk = new QPushButton (ok_string); - QPushButton *buttonCancel = new QPushButton (cancel_string); - QHBoxLayout *buttonsLayout = new QHBoxLayout; - buttonsLayout->addStretch (1); - buttonsLayout->addWidget (buttonOk); - buttonsLayout->addWidget (buttonCancel); - buttonOk->setDefault (true); + QPushButton *buttonOk = new QPushButton (ok_string); + QPushButton *buttonCancel = new QPushButton (cancel_string); + QHBoxLayout *buttonsLayout = new QHBoxLayout; + buttonsLayout->addStretch (1); + buttonsLayout->addWidget (buttonOk); + buttonsLayout->addWidget (buttonCancel); + buttonOk->setDefault (true); - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addLayout (listLayout); - mainLayout->addSpacing (12); - mainLayout->addLayout (buttonsLayout); - setLayout (mainLayout); - if (fixed_layout) - layout ()->setSizeConstraint (QLayout::SetFixedSize); + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addLayout (listLayout); + mainLayout->addSpacing (12); + mainLayout->addLayout (buttonsLayout); + setLayout (mainLayout); + if (fixed_layout) + layout ()->setSizeConstraint (QLayout::SetFixedSize); - // If empty, make blank rather than use default OS behavior. - setWindowTitle (title.isEmpty () ? " " : title); + // If empty, make blank rather than use default OS behavior. + setWindowTitle (title.isEmpty () ? " " : title); - connect (select_all, &QPushButton::clicked, - view, &QListView::selectAll); + connect (select_all, &QPushButton::clicked, + view, &QListView::selectAll); - connect (buttonOk, &QPushButton::clicked, - this, &ListDialog::buttonOk_clicked); + connect (buttonOk, &QPushButton::clicked, + this, &ListDialog::buttonOk_clicked); - connect (buttonCancel, &QPushButton::clicked, - this, &ListDialog::buttonCancel_clicked); + connect (buttonCancel, &QPushButton::clicked, + this, &ListDialog::buttonCancel_clicked); - connect (view, &QListView::doubleClicked, - this, &ListDialog::item_double_clicked); -} + connect (view, &QListView::doubleClicked, + this, &ListDialog::item_double_clicked); + } -void ListDialog::buttonOk_clicked (void) -{ - // Store information about what button was pressed so that builtin - // functions can retrieve. + void ListDialog::buttonOk_clicked (void) + { + // Store information about what button was pressed so that builtin + // functions can retrieve. - QModelIndexList selected_index = selector->selectedIndexes (); - QIntList selected_int; + QModelIndexList selected_index = selector->selectedIndexes (); + QIntList selected_int; - for (int i = 0; i < selected_index.size (); i++) - selected_int << selected_index.at (i).row () + 1; + for (int i = 0; i < selected_index.size (); i++) + selected_int << selected_index.at (i).row () + 1; - emit finish_selection (selected_int, 1); + emit finish_selection (selected_int, 1); - done (QDialog::Accepted); -} + done (QDialog::Accepted); + } -void ListDialog::buttonCancel_clicked (void) -{ - // Store information about what button was pressed so that builtin - // functions can retrieve. + void ListDialog::buttonCancel_clicked (void) + { + // Store information about what button was pressed so that builtin + // functions can retrieve. - QIntList empty; + QIntList empty; - emit finish_selection (empty, 0); + emit finish_selection (empty, 0); - done (QDialog::Rejected); -} + done (QDialog::Rejected); + } -void ListDialog::reject (void) -{ - buttonCancel_clicked (); -} + void ListDialog::reject (void) + { + buttonCancel_clicked (); + } -void ListDialog::item_double_clicked (const QModelIndex&) -{ - buttonOk_clicked (); -} + void ListDialog::item_double_clicked (const QModelIndex&) + { + buttonOk_clicked (); + } -InputDialog::InputDialog (base_qobject&, const QStringList& prompt, - const QString& title, const QFloatList& nr, - const QFloatList& nc, const QStringList& defaults) - : QDialog () -{ + InputDialog::InputDialog (const QStringList& prompt, + const QString& title, const QFloatList& nr, + const QFloatList& nc, const QStringList& defaults) + : QDialog () + { #define LINE_EDIT_FOLLOWS_PROMPT 0 #if LINE_EDIT_FOLLOWS_PROMPT - // Prompt on left followed by input on right. - QGridLayout *promptInputLayout = new QGridLayout; + // Prompt on left followed by input on right. + QGridLayout *promptInputLayout = new QGridLayout; #else - // Prompt aligned above input. - QVBoxLayout *promptInputLayout = new QVBoxLayout; + // Prompt aligned above input. + QVBoxLayout *promptInputLayout = new QVBoxLayout; #endif - int N_gridrows = prompt.size (); - for (int i = 0; i < N_gridrows; i++) - { - QLabel *label = new QLabel (prompt.at (i)); - QLineEdit *line_edit = new QLineEdit (); - if (i < defaults.size ()) - line_edit->setText (defaults.at (i)); - if (i < nr.size () && nr.at (i) > 0) - { - QSize qsize = line_edit->sizeHint (); - int intval = qsize.height () * nr.at (i); - line_edit->setFixedHeight (intval); - if (i < nc.size () && nc.at (i) > 0) - { - intval = qsize.height () * nc.at (i) / 2; - line_edit->setFixedWidth (intval); - } - } - input_line << line_edit; + int N_gridrows = prompt.size (); + for (int i = 0; i < N_gridrows; i++) + { + QLabel *label = new QLabel (prompt.at (i)); + QLineEdit *line_edit = new QLineEdit (); + if (i < defaults.size ()) + line_edit->setText (defaults.at (i)); + if (i < nr.size () && nr.at (i) > 0) + { + QSize qsize = line_edit->sizeHint (); + int intval = qsize.height () * nr.at (i); + line_edit->setFixedHeight (intval); + if (i < nc.size () && nc.at (i) > 0) + { + intval = qsize.height () * nc.at (i) / 2; + line_edit->setFixedWidth (intval); + } + } + input_line << line_edit; #if LINE_EDIT_FOLLOWS_PROMPT - promptInputLayout->addWidget (label, i + 1, 0); - promptInputLayout->addWidget (line_edit, i + 1, 1); + promptInputLayout->addWidget (label, i + 1, 0); + promptInputLayout->addWidget (line_edit, i + 1, 1); #else - promptInputLayout->addWidget (label); - promptInputLayout->addWidget (line_edit); + promptInputLayout->addWidget (label); + promptInputLayout->addWidget (line_edit); #endif - } + } #undef LINE_EDIT_FOLLOWS_PROMPT - QPushButton *buttonOk = new QPushButton ("OK"); - QPushButton *buttonCancel = new QPushButton ("Cancel"); - QHBoxLayout *buttonsLayout = new QHBoxLayout; - buttonsLayout->addStretch (1); - buttonsLayout->addWidget (buttonOk); - buttonsLayout->addWidget (buttonCancel); + QPushButton *buttonOk = new QPushButton ("OK"); + QPushButton *buttonCancel = new QPushButton ("Cancel"); + QHBoxLayout *buttonsLayout = new QHBoxLayout; + buttonsLayout->addStretch (1); + buttonsLayout->addWidget (buttonOk); + buttonsLayout->addWidget (buttonCancel); - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addLayout (promptInputLayout); - mainLayout->addSpacing (12); - mainLayout->addLayout (buttonsLayout); - setLayout (mainLayout); + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addLayout (promptInputLayout); + mainLayout->addSpacing (12); + mainLayout->addLayout (buttonsLayout); + setLayout (mainLayout); - // If empty, make blank rather than use default OS behavior. - setWindowTitle (title.isEmpty () ? " " : title); + // If empty, make blank rather than use default OS behavior. + setWindowTitle (title.isEmpty () ? " " : title); - connect (buttonOk, &QPushButton::clicked, - this, &InputDialog::buttonOk_clicked); + connect (buttonOk, &QPushButton::clicked, + this, &InputDialog::buttonOk_clicked); - connect (buttonCancel, &QPushButton::clicked, - this, &InputDialog::buttonCancel_clicked); -} + connect (buttonCancel, &QPushButton::clicked, + this, &InputDialog::buttonCancel_clicked); + } -void InputDialog::buttonOk_clicked (void) -{ - // Store information about what button was pressed so that builtin - // functions can retrieve. + void InputDialog::buttonOk_clicked (void) + { + // Store information about what button was pressed so that builtin + // functions can retrieve. - QStringList string_result; - for (int i = 0; i < input_line.size (); i++) - string_result << input_line.at (i)->text (); - emit finish_input (string_result, 1); - done (QDialog::Accepted); -} + QStringList string_result; + for (int i = 0; i < input_line.size (); i++) + string_result << input_line.at (i)->text (); + emit finish_input (string_result, 1); + done (QDialog::Accepted); + } -void InputDialog::buttonCancel_clicked (void) -{ - // Store information about what button was pressed so that builtin - // functions can retrieve. + void InputDialog::buttonCancel_clicked (void) + { + // Store information about what button was pressed so that builtin + // functions can retrieve. - QStringList empty; - emit finish_input (empty, 0); - done (QDialog::Rejected); -} + QStringList empty; + emit finish_input (empty, 0); + done (QDialog::Rejected); + } -void InputDialog::reject (void) -{ - buttonCancel_clicked (); -} + void InputDialog::reject (void) + { + buttonCancel_clicked (); + } -FileDialog::FileDialog (base_qobject& oct_qobj, - const QStringList& name_filters, - const QString& title, const QString& filename, - const QString& dirname, const QString& multimode) - : QFileDialog () -{ - // Create a NonModal message. - setWindowModality (Qt::NonModal); + FileDialog::FileDialog (const QStringList& name_filters, + const QString& title, const QString& filename, + const QString& dirname, const QString& multimode) + : QFileDialog () + { + // Create a NonModal message. + setWindowModality (Qt::NonModal); - setWindowTitle (title.isEmpty () ? " " : title); - setDirectory (dirname); + setWindowTitle (title.isEmpty () ? " " : title); + setDirectory (dirname); + + // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - resource_manager& rmgr = oct_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) - setOption(QFileDialog::DontUseNativeDialog); + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) + setOption(QFileDialog::DontUseNativeDialog); - if (multimode == "on") // uigetfile multiselect=on - { - setFileMode (QFileDialog::ExistingFiles); - setAcceptMode (QFileDialog::AcceptOpen); - } - else if (multimode == "create") // uiputfile - { - setFileMode (QFileDialog::AnyFile); - setAcceptMode (QFileDialog::AcceptSave); - setOption (QFileDialog::DontConfirmOverwrite, false); - } - else if (multimode == "dir") // uigetdir - { - setFileMode (QFileDialog::Directory); - setOption (QFileDialog::ShowDirsOnly, true); - setOption (QFileDialog::HideNameFilterDetails, true); - setAcceptMode (QFileDialog::AcceptOpen); - } - else // uigetfile multiselect=off - { - setFileMode (QFileDialog::ExistingFile); - setAcceptMode (QFileDialog::AcceptOpen); - } + if (multimode == "on") // uigetfile multiselect=on + { + setFileMode (QFileDialog::ExistingFiles); + setAcceptMode (QFileDialog::AcceptOpen); + } + else if (multimode == "create") // uiputfile + { + setFileMode (QFileDialog::AnyFile); + setAcceptMode (QFileDialog::AcceptSave); + setOption (QFileDialog::DontConfirmOverwrite, false); + } + else if (multimode == "dir") // uigetdir + { + setFileMode (QFileDialog::Directory); + setOption (QFileDialog::ShowDirsOnly, true); + setOption (QFileDialog::HideNameFilterDetails, true); + setAcceptMode (QFileDialog::AcceptOpen); + } + else // uigetfile multiselect=off + { + setFileMode (QFileDialog::ExistingFile); + setAcceptMode (QFileDialog::AcceptOpen); + } - setNameFilters (name_filters); + setNameFilters (name_filters); - selectFile (filename); + selectFile (filename); - connect (this, &FileDialog::accepted, this, &FileDialog::acceptSelection); + connect (this, &FileDialog::accepted, this, &FileDialog::acceptSelection); - connect (this, &FileDialog::rejected, this, &FileDialog::rejectSelection); -} + connect (this, &FileDialog::rejected, this, &FileDialog::rejectSelection); + } -void FileDialog::rejectSelection (void) -{ - QStringList empty; - emit finish_input (empty, "", 0); -} + void FileDialog::rejectSelection (void) + { + QStringList empty; + emit finish_input (empty, "", 0); + } -void FileDialog::acceptSelection (void) -{ - QStringList string_result; - QString path; - int idx = 1; + void FileDialog::acceptSelection (void) + { + QStringList string_result; + QString path; + int idx = 1; - string_result = selectedFiles (); + string_result = selectedFiles (); - if (testOption (QFileDialog::ShowDirsOnly) && string_result.size () > 0) - path = string_result[0]; - else - path = directory ().absolutePath (); + if (testOption (QFileDialog::ShowDirsOnly) && string_result.size () > 0) + path = string_result[0]; + else + path = directory ().absolutePath (); - // Matlab expects just the filename, whereas the file dialog gave us - // full path names, so fix it. + // Matlab expects just the filename, whereas the file dialog gave us + // full path names, so fix it. - for (int i = 0; i < string_result.size (); i++) - string_result[i] = QFileInfo (string_result[i]).fileName (); + for (int i = 0; i < string_result.size (); i++) + string_result[i] = QFileInfo (string_result[i]).fileName (); - // If not showing only dirs, add end slash for the path component. - if (testOption (QFileDialog::ShowDirsOnly) == false) - path += '/'; + // If not showing only dirs, add end slash for the path component. + if (testOption (QFileDialog::ShowDirsOnly) == false) + path += '/'; - // Convert to native slashes. - path = QDir::toNativeSeparators (path); + // Convert to native slashes. + path = QDir::toNativeSeparators (path); - QStringList name_filters = nameFilters (); - idx = name_filters.indexOf (selectedNameFilter ()) + 1; + QStringList name_filters = nameFilters (); + idx = name_filters.indexOf (selectedNameFilter ()) + 1; - // Send the selected info. - emit finish_input (string_result, path, idx); -} + // Send the selected info. + emit finish_input (string_result, path, idx); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/dialog.h --- a/libgui/src/dialog.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/dialog.h Tue Dec 06 15:45:27 2022 -0500 @@ -44,239 +44,235 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; - -class QUIWidgetCreator : public QObject -{ - Q_OBJECT + class QUIWidgetCreator : public QObject + { + Q_OBJECT -public: + public: - QUIWidgetCreator (base_qobject& oct_qobj); + QUIWidgetCreator (void); - ~QUIWidgetCreator (void) = default; + ~QUIWidgetCreator (void) = default; -public: + public: - QString rm_amp (const QString& text); + QString rm_amp (const QString& text); - QString message_dialog (const QString& message, const QString& title, - const QString& icon, const QStringList& button, - const QString& defbutton, const QStringList& role); + QString message_dialog (const QString& message, const QString& title, + const QString& icon, const QStringList& button, + const QString& defbutton, const QStringList& role); - int get_dialog_result (void) { return m_dialog_result; } + int get_dialog_result (void) { return m_dialog_result; } - QString get_dialog_button (void) { return m_dialog_button; } + QString get_dialog_button (void) { return m_dialog_button; } - QPair list_dialog (const QStringList& list, - const QString& mode, - int wd, int ht, - const QList& initial, - const QString& name, - const QStringList& prompt, - const QString& ok_string, - const QString& cancel_string); + QPair list_dialog (const QStringList& list, + const QString& mode, + int wd, int ht, + const QList& initial, + const QString& name, + const QStringList& prompt, + const QString& ok_string, + const QString& cancel_string); - QIntList get_list_index (void) const { return m_list_index; } + QIntList get_list_index (void) const { return m_list_index; } - QStringList input_dialog (const QStringList& prompt, const QString& title, - const QFloatList& nr, const QFloatList& nc, - const QStringList& defaults); + QStringList input_dialog (const QStringList& prompt, const QString& title, + const QFloatList& nr, const QFloatList& nc, + const QStringList& defaults); - QStringList get_string_list (void) const { return m_string_list; } + QStringList get_string_list (void) const { return m_string_list; } - QStringList file_dialog (const QStringList& filters, const QString& title, - const QString& filename, const QString& dirname, - const QString& multimode); + QStringList file_dialog (const QStringList& filters, const QString& title, + const QString& filename, const QString& dirname, + const QString& multimode); - QString get_dialog_path (void) const { return m_path_name; } + QString get_dialog_path (void) const { return m_path_name; } - void lock (void) { m_mutex.lock (); } - void wait (void) { m_waitcondition.wait (&m_mutex); } - void unlock (void) { m_mutex.unlock (); } - void wake_all (void) { m_waitcondition.wakeAll (); } + void lock (void) { m_mutex.lock (); } + void wait (void) { m_waitcondition.wait (&m_mutex); } + void unlock (void) { m_mutex.unlock (); } + void wake_all (void) { m_waitcondition.wakeAll (); } -signals: + signals: - void create_dialog (const QString&, const QString&, const QString&, - const QStringList&, const QString&, const QStringList&); + void create_dialog (const QString&, const QString&, const QString&, + const QStringList&, const QString&, const QStringList&); - void create_listview (const QStringList&, const QString&, int, int, - const QIntList&, const QString&, const QStringList&, - const QString&, const QString&); + void create_listview (const QStringList&, const QString&, int, int, + const QIntList&, const QString&, const QStringList&, + const QString&, const QString&); - void create_inputlayout (const QStringList&, const QString&, - const QFloatList&, const QFloatList&, - const QStringList&); + void create_inputlayout (const QStringList&, const QString&, + const QFloatList&, const QFloatList&, + const QStringList&); - void create_filedialog (const QStringList& filters, const QString& title, - const QString& filename, const QString& dirname, - const QString& multimode); -public slots: + void create_filedialog (const QStringList& filters, const QString& title, + const QString& filename, const QString& dirname, + const QString& multimode); + public slots: - void handle_create_dialog (const QString& message, const QString& title, - const QString& icon, const QStringList& button, - const QString& defbutton, - const QStringList& role); + void handle_create_dialog (const QString& message, const QString& title, + const QString& icon, const QStringList& button, + const QString& defbutton, + const QStringList& role); - void dialog_button_clicked (QAbstractButton *button); + void dialog_button_clicked (QAbstractButton *button); - void handle_create_listview (const QStringList& list, const QString& mode, - int width, int height, - const QIntList& initial, - const QString& name, - const QStringList& prompt, - const QString& ok_string, - const QString& cancel_string); + void handle_create_listview (const QStringList& list, const QString& mode, + int width, int height, + const QIntList& initial, + const QString& name, + const QStringList& prompt, + const QString& ok_string, + const QString& cancel_string); - void list_select_finished (const QIntList& selected, int button_pressed); + void list_select_finished (const QIntList& selected, int button_pressed); - void handle_create_inputlayout (const QStringList&, const QString&, - const QFloatList&, const QFloatList&, - const QStringList&); + void handle_create_inputlayout (const QStringList&, const QString&, + const QFloatList&, const QFloatList&, + const QStringList&); - void input_finished (const QStringList& input, int button_pressed); + void input_finished (const QStringList& input, int button_pressed); - void handle_create_filedialog (const QStringList& filters, - const QString& title, - const QString& filename, - const QString& dirname, - const QString& multimode); + void handle_create_filedialog (const QStringList& filters, + const QString& title, + const QString& filename, + const QString& dirname, + const QString& multimode); - void filedialog_finished (const QStringList& files, const QString& path, - int filterindex); + void filedialog_finished (const QStringList& files, const QString& path, + int filterindex); -private: + private: - base_qobject& m_octave_qobj; - - int m_dialog_result; - QString m_dialog_button; + int m_dialog_result; + QString m_dialog_button; - // A copy of the dialogs button texts - QStringList m_button_list; + // A copy of the dialogs button texts + QStringList m_button_list; - // The list could conceivably be big. Not sure how things are - // stored internally, so keep off of the stack. - QStringList m_string_list; - QIntList m_list_index; + // The list could conceivably be big. Not sure how things are + // stored internally, so keep off of the stack. + QStringList m_string_list; + QIntList m_list_index; + + QString m_path_name; - QString m_path_name; - - // GUI objects cannot be accessed in the non-GUI thread. However, - // signals can be sent to slots across threads with proper - // synchronization. Hence, the use of QWaitCondition. - QMutex m_mutex; - QWaitCondition m_waitcondition; -}; - -class MessageDialog : public QMessageBox -{ - Q_OBJECT + // GUI objects cannot be accessed in the non-GUI thread. However, + // signals can be sent to slots across threads with proper + // synchronization. Hence, the use of QWaitCondition. + QMutex m_mutex; + QWaitCondition m_waitcondition; + }; -public: - - MessageDialog (base_qobject& oct_qobj, const QString& message, - const QString& title, const QString& icon, - const QStringList& button, const QString& defbutton, - const QStringList& role); - - ~MessageDialog (void) = default; - -private: - - void closeEvent (QCloseEvent *) + class MessageDialog : public QMessageBox { - // Reroute the close tab to a button click so there is only a single - // route to waking the wait condition. - emit buttonClicked (nullptr); - } -}; + Q_OBJECT + + public: + + MessageDialog (const QString& message, + const QString& title, const QString& icon, + const QStringList& button, const QString& defbutton, + const QStringList& role); -class ListDialog : public QDialog -{ - Q_OBJECT + ~MessageDialog (void) = default; + + private: - QItemSelectionModel *selector; - -public: + void closeEvent (QCloseEvent *) + { + // Reroute the close tab to a button click so there is only a single + // route to waking the wait condition. + emit buttonClicked (nullptr); + } + }; - ListDialog (base_qobject& oct_qobj, const QStringList& list, - const QString& mode, int width, int height, - const QList& initial, const QString& name, - const QStringList& prompt, const QString& ok_string, - const QString& cancel_string); + class ListDialog : public QDialog + { + Q_OBJECT - ~ListDialog (void) = default; + QItemSelectionModel *selector; + + public: -signals: + ListDialog (const QStringList& list, + const QString& mode, int width, int height, + const QList& initial, const QString& name, + const QStringList& prompt, const QString& ok_string, + const QString& cancel_string); - void finish_selection (const QIntList&, int); + ~ListDialog (void) = default; -public slots: + signals: + + void finish_selection (const QIntList&, int); - void buttonOk_clicked (void); + public slots: - void buttonCancel_clicked (void); + void buttonOk_clicked (void); + + void buttonCancel_clicked (void); - void reject (void); + void reject (void); - void item_double_clicked (const QModelIndex&); + void item_double_clicked (const QModelIndex&); -private: + private: - QAbstractItemModel *m_model; -}; + QAbstractItemModel *m_model; + }; -class InputDialog : public QDialog -{ - Q_OBJECT + class InputDialog : public QDialog + { + Q_OBJECT - QList input_line; + QList input_line; -public: + public: - InputDialog (base_qobject& oct_qobj, const QStringList& prompt, - const QString& title, const QFloatList& nr, - const QFloatList& nc, const QStringList& defaults); + InputDialog (const QStringList& prompt, + const QString& title, const QFloatList& nr, + const QFloatList& nc, const QStringList& defaults); - ~InputDialog (void) = default; + ~InputDialog (void) = default; -signals: + signals: - void finish_input (const QStringList&, int); + void finish_input (const QStringList&, int); -public slots: + public slots: - void buttonOk_clicked (void); + void buttonOk_clicked (void); - void buttonCancel_clicked (void); + void buttonCancel_clicked (void); - void reject (void); -}; + void reject (void); + }; -class FileDialog : public QFileDialog -{ - Q_OBJECT + class FileDialog : public QFileDialog + { + Q_OBJECT -public: + public: - FileDialog (base_qobject& oct_qobj, const QStringList& filters, - const QString& title, const QString& filename, - const QString& dirname, const QString& multimode); + FileDialog (const QStringList& filters, + const QString& title, const QString& filename, + const QString& dirname, const QString& multimode); - ~FileDialog (void) = default; + ~FileDialog (void) = default; -signals: + signals: - void finish_input (const QStringList&, const QString&, int); + void finish_input (const QStringList&, const QString&, int); -private slots: + private slots: - void acceptSelection (void); + void acceptSelection (void); - void rejectSelection (void); -}; + void rejectSelection (void); + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/documentation-bookmarks.cc --- a/libgui/src/documentation-bookmarks.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/documentation-bookmarks.cc Tue Dec 06 15:45:27 2022 -0500 @@ -28,7 +28,10 @@ #endif #include +#include +#include #include +#include #include #include #include @@ -36,10 +39,10 @@ #include "documentation.h" #include "documentation-bookmarks.h" -#include "gui-settings.h" #include "gui-preferences-global.h" #include "gui-preferences-dc.h" #include "gui-preferences-sc.h" +#include "gui-settings.h" #include "octave-qtutils.h" #include "shortcut-manager.h" @@ -49,497 +52,496 @@ OCTAVE_BEGIN_NAMESPACE(octave) -documentation_bookmarks::documentation_bookmarks ( - documentation *doc, documentation_browser *browser, - base_qobject& oct_qobj, QWidget *p) -: QWidget (p), - m_doc (doc), m_browser (browser), m_octave_qobj (oct_qobj), - m_ctx_menu_item (nullptr) -{ - setObjectName ("documentation_tab_bookmarks"); + documentation_bookmarks::documentation_bookmarks (documentation *doc, + documentation_browser *browser, + QWidget *p) + : QWidget (p), m_doc (doc), m_browser (browser), m_ctx_menu_item (nullptr) + { + setObjectName ("documentation_tab_bookmarks"); + + gui_settings settings; + + // Setup the tree view with the bookmarks + m_tree = new QTreeWidget (p); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + m_tree->setContextMenuPolicy (Qt::CustomContextMenu); + m_tree->setSelectionMode (QAbstractItemView::ExtendedSelection); + m_tree->setSortingEnabled (false); + m_tree->setDragEnabled(true); + m_tree->viewport()->setAcceptDrops(true); + m_tree->setDropIndicatorShown(true); + m_tree->setDragDropMode(QAbstractItemView::InternalMove); + m_tree->setColumnCount (1); + m_tree->setHeaderHidden (true); + m_tree->setEditTriggers (QAbstractItemView::EditKeyPressed + | QAbstractItemView::SelectedClicked); - // Setup the tree view with the bookmarks - m_tree = new QTreeWidget (p); + connect (m_tree, &QTreeWidget::customContextMenuRequested, + this, &documentation_bookmarks::ctx_menu); + connect (m_tree, &QTreeWidget::itemDoubleClicked, + this, &documentation_bookmarks::handle_double_click); - m_tree->setContextMenuPolicy (Qt::CustomContextMenu); - m_tree->setSelectionMode (QAbstractItemView::ExtendedSelection); - m_tree->setSortingEnabled (false); - m_tree->setDragEnabled(true); - m_tree->viewport()->setAcceptDrops(true); - m_tree->setDropIndicatorShown(true); - m_tree->setDragDropMode(QAbstractItemView::InternalMove); - m_tree->setColumnCount (1); - m_tree->setHeaderHidden (true); - m_tree->setEditTriggers (QAbstractItemView::EditKeyPressed - | QAbstractItemView::SelectedClicked); + // Define the icons for the tree view + icon_folder.addPixmap (style ()->standardPixmap(QStyle::SP_DirClosedIcon), + QIcon::Normal, QIcon::Off); + icon_folder.addPixmap (style ()->standardPixmap(QStyle::SP_DirOpenIcon), + QIcon::Normal, QIcon::On); + icon_bookmark.addPixmap (style ()->standardPixmap(QStyle::SP_FileIcon)); + + // Setup and read the bookmarkfile + QFileInfo f (settings.fileName ()); + QString f_path = f.absolutePath (); + f.setFile (QDir (f_path), dc_bookmark_file); + m_xbel_file.setFileName (f.absoluteFilePath ()); - connect (m_tree, &QTreeWidget::customContextMenuRequested, - this, &documentation_bookmarks::ctx_menu); - connect (m_tree, &QTreeWidget::itemDoubleClicked, - this, &documentation_bookmarks::handle_double_click); + if (m_xbel_file.exists ()) + { + QString err = read_bookmarks (); + if ( !err.isEmpty ()) + { + err.append (tr ("\nNo documentation bookmarks loaded!")); + QMessageBox::warning (this, + tr ("Octave: Loading Documentation Bookmarks"), + err); + m_xbel_file.close (); + } + } - // Define the icons for the tree view - icon_folder.addPixmap (style ()->standardPixmap(QStyle::SP_DirClosedIcon), - QIcon::Normal, QIcon::Off); - icon_folder.addPixmap (style ()->standardPixmap(QStyle::SP_DirOpenIcon), - QIcon::Normal, QIcon::On); - icon_bookmark.addPixmap (style ()->standardPixmap(QStyle::SP_FileIcon)); - - // Setup and read the bookmarkfile - QFileInfo f (settings->fileName ()); - QString f_path = f.absolutePath (); - f.setFile (QDir (f_path), dc_bookmark_file); - m_xbel_file.setFileName (f.absoluteFilePath ()); + // Setup the filter widget + m_filter_widget = new QWidget (p); + m_filter = new QComboBox (m_filter_widget); - if (m_xbel_file.exists ()) - { - QString err = read_bookmarks (); - if ( !err.isEmpty ()) - { - err.append (tr ("\nNo documentation bookmarks loaded!")); - QMessageBox::warning (this, - tr ("Octave: Loading Documentation Bookmarks"), - err); - m_xbel_file.close (); - } - } + m_filter->setToolTip (tr ("Enter text to search the bookmarks")); + m_filter->setEditable (true); + m_filter->setInsertPolicy (QComboBox::NoInsert); + m_filter->setMaxCount (10); + m_filter->setMaxVisibleItems (10); + m_filter->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon); + QSizePolicy size_pol (QSizePolicy::Expanding, QSizePolicy::Preferred); + m_filter->setSizePolicy (size_pol); + m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive); + + m_filter->addItems (settings.value (dc_bookmark_filter_mru).toStringList ()); - // Setup the filter widget - m_filter_widget = new QWidget (p); - m_filter = new QComboBox (m_filter_widget); + connect (m_filter, &QComboBox::editTextChanged, + this, &documentation_bookmarks::filter_bookmarks); + connect (m_filter->lineEdit (), &QLineEdit::editingFinished, + this, &documentation_bookmarks::update_filter_history); - m_filter->setToolTip (tr ("Enter text to search the bookmarks")); - m_filter->setEditable (true); - m_filter->setInsertPolicy (QComboBox::NoInsert); - m_filter->setMaxCount (10); - m_filter->setMaxVisibleItems (10); - m_filter->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon); - QSizePolicy size_pol (QSizePolicy::Expanding, QSizePolicy::Preferred); - m_filter->setSizePolicy (size_pol); - m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive); + m_filter_checkbox = new QCheckBox (m_filter_widget); + bool filter_state = settings.value (dc_bookmark_filter_active).toBool (); + m_filter_checkbox->setChecked (filter_state); + filter_activate (filter_state); - m_filter->addItems (settings->value (dc_bookmark_filter_mru).toStringList ()); + connect (m_filter_checkbox, &QCheckBox::toggled, + this, &documentation_bookmarks::filter_activate); - connect (m_filter, &QComboBox::editTextChanged, - this, &documentation_bookmarks::filter_bookmarks); - connect (m_filter->lineEdit (), &QLineEdit::editingFinished, - this, &documentation_bookmarks::update_filter_history); + QLabel *filter_label = new QLabel (tr ("Filter"), m_filter_widget); + QHBoxLayout *h_box_bm = new QHBoxLayout (m_filter_widget); + h_box_bm->addWidget (filter_label); + h_box_bm->addWidget (m_filter_checkbox); + h_box_bm->addWidget (m_filter); + h_box_bm->setMargin (2); + m_filter_widget->setLayout (h_box_bm); - m_filter_checkbox = new QCheckBox (m_filter_widget); - bool filter_state = settings->value (dc_bookmark_filter_active).toBool (); - m_filter_checkbox->setChecked (filter_state); - filter_activate (filter_state); + m_filter_shown = settings.value (dc_bookmark_filter_shown).toBool (); + m_filter_widget->setVisible (m_filter_shown); - connect (m_filter_checkbox, &QCheckBox::toggled, - this, &documentation_bookmarks::filter_activate); + // Resulting Layout of this widget + QVBoxLayout *v_box_bm = new QVBoxLayout (this); + v_box_bm->addWidget (m_filter_widget); + v_box_bm->addWidget (m_tree); + setLayout (v_box_bm); + } - QLabel *filter_label = new QLabel (tr ("Filter"), m_filter_widget); - QHBoxLayout *h_box_bm = new QHBoxLayout (m_filter_widget); - h_box_bm->addWidget (filter_label); - h_box_bm->addWidget (m_filter_checkbox); - h_box_bm->addWidget (m_filter); - h_box_bm->setMargin (2); - m_filter_widget->setLayout (h_box_bm); - - m_filter_shown = settings->value (dc_bookmark_filter_shown).toBool (); - m_filter_widget->setVisible (m_filter_shown); + // Slot for adding the current page as a bookmark + void documentation_bookmarks::add_bookmark (void) + { + QUrl url = m_browser->historyUrl (0); - // Resulting Layout of this widget - QVBoxLayout *v_box_bm = new QVBoxLayout (this); - v_box_bm->addWidget (m_filter_widget); - v_box_bm->addWidget (m_tree); - setLayout (v_box_bm); -} - -// Slot for adding the current page as a bookmark -void documentation_bookmarks::add_bookmark (void) -{ - QUrl url = m_browser->historyUrl (0); + // Check if bookmark already exists and select if yes + QTreeWidgetItemIterator it (m_tree); + while (*it) + { + QUrl url_i = (*it)->data (0, url_role).toUrl (); + if (url == url_i) + { + m_tree->setCurrentItem (*it); + (*it)->setExpanded (true); + return; + } + it++; + } - // Check if bookmark already exists and select if yes - QTreeWidgetItemIterator it (m_tree); - while (*it) - { - QUrl url_i = (*it)->data (0, url_role).toUrl (); - if (url == url_i) - { - m_tree->setCurrentItem (*it); - (*it)->setExpanded (true); - return; - } - it++; - } + // Add the anchor name to the title of the page and add the bookmark + // as top-level-item + QString title = m_doc->title_and_anchor (m_browser->historyTitle (0), url); + add_bookmark (title, url.toString ()); + } - // Add the anchor name to the title of the page and add the bookmark - // as top-level-item - QString title = m_doc->title_and_anchor (m_browser->historyTitle (0), url); - add_bookmark (title, url.toString ()); -} + // Function for actually adding a bookmark to the tree + void documentation_bookmarks::add_bookmark (const QString& title, + const QString& url, + QTreeWidgetItem* item) + { + // Create new bookmark + QTreeWidgetItem *new_item = new QTreeWidgetItem (QStringList (title)); + new_item->setData (0, tag_role, QVariant (bookmark_tag)); + new_item->setData (0, url_role, QVariant (url)); + new_item->setFlags ((new_item->flags () & (~Qt::ItemIsDropEnabled)) + | Qt::ItemIsEditable + | Qt::ItemIsDragEnabled); + new_item->setIcon (0, icon_bookmark); -// Function for actually adding a bookmark to the tree -void documentation_bookmarks::add_bookmark (const QString& title, - const QString& url, - QTreeWidgetItem* item) -{ - // Create new bookmark - QTreeWidgetItem *new_item = new QTreeWidgetItem (QStringList (title)); - new_item->setData (0, tag_role, QVariant (bookmark_tag)); - new_item->setData (0, url_role, QVariant (url)); - new_item->setFlags ((new_item->flags () & (~Qt::ItemIsDropEnabled)) - | Qt::ItemIsEditable - | Qt::ItemIsDragEnabled); - new_item->setIcon (0, icon_bookmark); + // Insert as top level or child item + // TODO: Open dialog allowing to select a target folder if this + // bookmark is added manually and not by reading a bookmark file + if (item) + item->addChild (new_item); + else + m_tree->addTopLevelItem (new_item); + } - // Insert as top level or child item - // TODO: Open dialog allowing to select a target folder if this - // bookmark is added manually and not by reading a bookmark file - if (item) - item->addChild (new_item); - else - m_tree->addTopLevelItem (new_item); -} + // Slot for adding a folder from the context menu + void documentation_bookmarks::add_folder (bool) + { + QTreeWidgetItem *parent_item = nullptr; -// Slot for adding a folder from the context menu -void documentation_bookmarks::add_folder (bool) -{ - QTreeWidgetItem *parent_item = nullptr; + if (m_ctx_menu_item) + { + if (m_ctx_menu_item->data (0, tag_role).toInt () == folder_tag) + parent_item = m_ctx_menu_item; + else + { + QTreeWidgetItem *p = m_ctx_menu_item->parent (); + if (p) + parent_item = p; + } + } - if (m_ctx_menu_item) - { - if (m_ctx_menu_item->data (0, tag_role).toInt () == folder_tag) - parent_item = m_ctx_menu_item; - else - { - QTreeWidgetItem *p = m_ctx_menu_item->parent (); - if (p) - parent_item = p; - } - } + QTreeWidgetItem *new_folder = add_folder (tr ("New Folder"), parent_item); - QTreeWidgetItem *new_folder = add_folder (tr ("New Folder"), parent_item); - - m_tree->setCurrentItem (new_folder); - m_tree->editItem (new_folder); -} + m_tree->setCurrentItem (new_folder); + m_tree->editItem (new_folder); + } -// Function for actually adding a folder to the tree -QTreeWidgetItem* documentation_bookmarks::add_folder (const QString& folder, - QTreeWidgetItem *item, bool expanded) -{ - QTreeWidgetItem *new_folder = new QTreeWidgetItem (QStringList (folder)); - new_folder->setData (0, tag_role, QVariant (folder_tag)); - new_folder->setFlags (new_folder->flags() | Qt::ItemIsEditable - | Qt::ItemIsDragEnabled - | Qt::ItemIsDropEnabled); - new_folder->setChildIndicatorPolicy (QTreeWidgetItem::DontShowIndicatorWhenChildless); - new_folder->setIcon (0, icon_folder); - new_folder->setExpanded (expanded); + // Function for actually adding a folder to the tree + QTreeWidgetItem* documentation_bookmarks::add_folder (const QString& folder, + QTreeWidgetItem *item, bool expanded) + { + QTreeWidgetItem *new_folder = new QTreeWidgetItem (QStringList (folder)); + new_folder->setData (0, tag_role, QVariant (folder_tag)); + new_folder->setFlags (new_folder->flags() | Qt::ItemIsEditable + | Qt::ItemIsDragEnabled + | Qt::ItemIsDropEnabled); + new_folder->setChildIndicatorPolicy (QTreeWidgetItem::DontShowIndicatorWhenChildless); + new_folder->setIcon (0, icon_folder); + new_folder->setExpanded (expanded); - // Insert as top level or child item - if (item) - item->addChild (new_folder); - else - m_tree->addTopLevelItem (new_folder); + // Insert as top level or child item + if (item) + item->addChild (new_folder); + else + m_tree->addTopLevelItem (new_folder); - return new_folder; -} + return new_folder; + } -void documentation_bookmarks::filter_bookmarks (const QString& pattern) -{ - QTreeWidgetItemIterator it (m_tree); + void documentation_bookmarks::filter_bookmarks (const QString& pattern) + { + QTreeWidgetItemIterator it (m_tree); - while (*it) - { - if ((*it)->text (0).contains (pattern, Qt::CaseInsensitive)) - { - (*it)->setHidden (false); - (*it)->setExpanded (true); - QTreeWidgetItem *p = (*it)->parent (); - while (p) - { - p->setHidden (false); - p->setExpanded (true); - p = p->parent (); - } - } - else - (*it)->setHidden (true); + while (*it) + { + if ((*it)->text (0).contains (pattern, Qt::CaseInsensitive)) + { + (*it)->setHidden (false); + (*it)->setExpanded (true); + QTreeWidgetItem *p = (*it)->parent (); + while (p) + { + p->setHidden (false); + p->setExpanded (true); + p = p->parent (); + } + } + else + (*it)->setHidden (true); - it++; - } -} + it++; + } + } -void documentation_bookmarks::filter_activate (bool state) -{ - m_filter->setEnabled (state); + void documentation_bookmarks::filter_activate (bool state) + { + m_filter->setEnabled (state); - QString pattern; - if (state) - pattern = m_filter->currentText (); + QString pattern; + if (state) + pattern = m_filter->currentText (); - filter_bookmarks (pattern); -} + filter_bookmarks (pattern); + } -void documentation_bookmarks::update_filter_history (void) -{ - QString text = m_filter->currentText (); // get current text - int index = m_filter->findText (text); // and its actual index + void documentation_bookmarks::update_filter_history (void) + { + QString text = m_filter->currentText (); // get current text + int index = m_filter->findText (text); // and its actual index - if (index > -1) - m_filter->removeItem (index); // remove if already existing + if (index > -1) + m_filter->removeItem (index); // remove if already existing - m_filter->insertItem (0, text); // (re)insert at beginning - m_filter->setCurrentIndex (0); -} + m_filter->insertItem (0, text); // (re)insert at beginning + m_filter->setCurrentIndex (0); + } -void documentation_bookmarks::handle_double_click (QTreeWidgetItem *item, int) -{ - int tag = item->data (0, tag_role).toInt (); + void documentation_bookmarks::handle_double_click (QTreeWidgetItem *item, int) + { + int tag = item->data (0, tag_role).toInt (); - if (tag == folder_tag) - { - item->setExpanded (! item->isExpanded ()); - return; - } + if (tag == folder_tag) + { + item->setExpanded (! item->isExpanded ()); + return; + } - if (tag == bookmark_tag) - { - QUrl url = item->data (0, url_role).toUrl (); - if (! url.isEmpty ()) - m_browser->setSource (url); - return; - } -} + if (tag == bookmark_tag) + { + QUrl url = item->data (0, url_role).toUrl (); + if (! url.isEmpty ()) + m_browser->setSource (url); + return; + } + } -void documentation_bookmarks::ctx_menu (const QPoint& xpos) -{ - QMenu menu (this); + void documentation_bookmarks::ctx_menu (const QPoint& xpos) + { + QMenu menu (this); - m_ctx_menu_item = m_tree->itemAt (xpos); + m_ctx_menu_item = m_tree->itemAt (xpos); - if (m_ctx_menu_item) - { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + if (m_ctx_menu_item) + { + gui_settings settings; - menu.addAction (tr ("&Open"), this, &documentation_bookmarks::open); - menu.addAction (tr ("&Rename"), this, &documentation_bookmarks::edit); - menu.addAction (rmgr.icon ("window-close"), tr ("Remo&ve"), - this, &documentation_bookmarks::remove); - menu.addSeparator (); - } + menu.addAction (tr ("&Open"), this, &documentation_bookmarks::open); + menu.addAction (tr ("&Rename"), this, &documentation_bookmarks::edit); + menu.addAction (settings.icon ("window-close"), tr ("Remo&ve"), + this, &documentation_bookmarks::remove); + menu.addSeparator (); + } - menu.addAction (tr ("&Add Folder"), this, - QOverload::of (&documentation_bookmarks::add_folder)); + menu.addAction (tr ("&Add Folder"), this, + QOverload::of (&documentation_bookmarks::add_folder)); - menu.addSeparator (); + menu.addSeparator (); - if (m_filter_shown) - menu.addAction (tr ("Hide &Filter"), - this, &documentation_bookmarks::show_filter); - else - menu.addAction (tr ("Show &Filter"), - this, &documentation_bookmarks::show_filter); + if (m_filter_shown) + menu.addAction (tr ("Hide &Filter"), + this, &documentation_bookmarks::show_filter); + else + menu.addAction (tr ("Show &Filter"), + this, &documentation_bookmarks::show_filter); - menu.exec (m_tree->mapToGlobal (xpos)); -} + menu.exec (m_tree->mapToGlobal (xpos)); + } -void documentation_bookmarks::open (bool) -{ - QList items = m_tree->selectedItems (); + void documentation_bookmarks::open (bool) + { + QList items = m_tree->selectedItems (); - if (items.size () > 0) - handle_double_click (items.at (0)); -} + if (items.size () > 0) + handle_double_click (items.at (0)); + } -void documentation_bookmarks::edit (bool) -{ - QList items = m_tree->selectedItems (); + void documentation_bookmarks::edit (bool) + { + QList items = m_tree->selectedItems (); - if (items.size () > 0) - m_tree->editItem (items.at (0)); -} + if (items.size () > 0) + m_tree->editItem (items.at (0)); + } -void documentation_bookmarks::remove (bool) -{ - QList items = m_tree->selectedItems (); + void documentation_bookmarks::remove (bool) + { + QList items = m_tree->selectedItems (); - for (auto it = items.begin () ; it != items.end (); it++) - { - if (*it) - m_tree->takeTopLevelItem ( - m_tree->indexOfTopLevelItem (*it)); - } -} + for (auto it = items.begin () ; it != items.end (); it++) + { + if (*it) + m_tree->takeTopLevelItem ( + m_tree->indexOfTopLevelItem (*it)); + } + } -void documentation_bookmarks::show_filter (bool) -{ - m_filter_shown = ! m_filter_shown; - m_filter_widget->setVisible (m_filter_shown); -} + void documentation_bookmarks::show_filter (bool) + { + m_filter_shown = ! m_filter_shown; + m_filter_widget->setVisible (m_filter_shown); + } -void documentation_bookmarks::save_settings (gui_settings *settings) -{ - // Write the bookmarks to the xbel-file - write_bookmarks (); + void documentation_bookmarks::save_settings (void) + { + // Write the bookmarks to the xbel-file + write_bookmarks (); - // Store settings - settings->setValue (dc_bookmark_filter_active.key, m_filter_checkbox->isChecked ()); - settings->setValue (dc_bookmark_filter_shown.key, m_filter_shown); + // Store settings + gui_settings settings; + + settings.setValue (dc_bookmark_filter_active.key, m_filter_checkbox->isChecked ()); + settings.setValue (dc_bookmark_filter_shown.key, m_filter_shown); - QStringList mru; - for (int i = 0; i < m_filter->count (); i++) - mru.append (m_filter->itemText (i)); - settings->setValue (dc_bookmark_filter_mru.key, mru); + QStringList mru; + for (int i = 0; i < m_filter->count (); i++) + mru.append (m_filter->itemText (i)); + settings.setValue (dc_bookmark_filter_mru.key, mru); - settings->sync (); -} + settings.sync (); + } -void documentation_bookmarks::write_bookmarks (void) -{ - if (! m_xbel_file.open (QFile::WriteOnly | QFile::Text)) - { - QMessageBox::warning (this, tr("Octave: Saving Documentation Bookmarks"), - tr("Unable to write file %1:\n%2.\n\n" - "Documentation bookmarks are not saved!\n") - .arg (m_xbel_file.fileName ()) - .arg (m_xbel_file.errorString())); - return; - } + void documentation_bookmarks::write_bookmarks (void) + { + if (! m_xbel_file.open (QFile::WriteOnly | QFile::Text)) + { + QMessageBox::warning (this, tr("Octave: Saving Documentation Bookmarks"), + tr("Unable to write file %1:\n%2.\n\n" + "Documentation bookmarks are not saved!\n") + .arg (m_xbel_file.fileName ()) + .arg (m_xbel_file.errorString())); + return; + } - QXmlStreamWriter xml_writer (&m_xbel_file); - xml_writer.setAutoFormatting (true); + QXmlStreamWriter xml_writer (&m_xbel_file); + xml_writer.setAutoFormatting (true); - xml_writer.writeStartDocument (); - xml_writer.writeDTD (dc_xbel_doctype); - xml_writer.writeStartElement (dc_xbel_name_format); - xml_writer.writeAttribute (dc_xbel_attr_version, dc_xbel_value_version); + xml_writer.writeStartDocument (); + xml_writer.writeDTD (dc_xbel_doctype); + xml_writer.writeStartElement (dc_xbel_name_format); + xml_writer.writeAttribute (dc_xbel_attr_version, dc_xbel_value_version); - for (int i = 0; i < m_tree->topLevelItemCount(); i++) - write_tree_item (&xml_writer, m_tree->topLevelItem (i)); + for (int i = 0; i < m_tree->topLevelItemCount(); i++) + write_tree_item (&xml_writer, m_tree->topLevelItem (i)); - xml_writer.writeEndDocument(); + xml_writer.writeEndDocument(); - m_xbel_file.flush (); - m_xbel_file.close (); -} + m_xbel_file.flush (); + m_xbel_file.close (); + } -void documentation_bookmarks::write_tree_item (QXmlStreamWriter* xml_writer, - const QTreeWidgetItem *item) -{ - switch (item->data (0, tag_role).toInt ()) - { - case folder_tag: - xml_writer->writeStartElement (dc_xbel_name_folder); - xml_writer->writeAttribute (dc_xbel_attr_folded, - item->isExpanded () ? dc_xbel_value_no : dc_xbel_value_yes); - xml_writer->writeTextElement (dc_xbel_name_title, item->text(0)); - for (int i = 0; i < item->childCount (); i++) - write_tree_item (xml_writer, item->child (i)); - xml_writer->writeEndElement (); - break; + void documentation_bookmarks::write_tree_item (QXmlStreamWriter* xml_writer, + const QTreeWidgetItem *item) + { + switch (item->data (0, tag_role).toInt ()) + { + case folder_tag: + xml_writer->writeStartElement (dc_xbel_name_folder); + xml_writer->writeAttribute (dc_xbel_attr_folded, + item->isExpanded () ? dc_xbel_value_no : dc_xbel_value_yes); + xml_writer->writeTextElement (dc_xbel_name_title, item->text(0)); + for (int i = 0; i < item->childCount (); i++) + write_tree_item (xml_writer, item->child (i)); + xml_writer->writeEndElement (); + break; - case bookmark_tag: - xml_writer->writeStartElement (dc_xbel_name_bookmark); - xml_writer->writeAttribute (dc_xbel_attr_href, item->data (0, url_role).toString ()); - xml_writer->writeTextElement (dc_xbel_name_title, item->text (0)); - xml_writer->writeEndElement (); - break; - } -} + case bookmark_tag: + xml_writer->writeStartElement (dc_xbel_name_bookmark); + xml_writer->writeAttribute (dc_xbel_attr_href, item->data (0, url_role).toString ()); + xml_writer->writeTextElement (dc_xbel_name_title, item->text (0)); + xml_writer->writeEndElement (); + break; + } + } -QString documentation_bookmarks::read_bookmarks (void) -{ - QString error_message; + QString documentation_bookmarks::read_bookmarks (void) + { + QString error_message; - // Check the file - if (! m_xbel_file.open (QFile::ReadOnly | QFile::Text)) - { - error_message = tr ("Unable to read file %1:\n%2.") - .arg (m_xbel_file.fileName ()) - .arg (m_xbel_file.errorString()); - return error_message; - } + // Check the file + if (! m_xbel_file.open (QFile::ReadOnly | QFile::Text)) + { + error_message = tr ("Unable to read file %1:\n%2.") + .arg (m_xbel_file.fileName ()) + .arg (m_xbel_file.errorString()); + return error_message; + } - QXmlStreamReader xml_reader (&m_xbel_file); + QXmlStreamReader xml_reader (&m_xbel_file); - if (! xml_reader.readNextStartElement ()) - { - error_message = tr ("No start element found in %1.\n" - "Invalid bookmark file?") - .arg (m_xbel_file.fileName ()); - return error_message; - } + if (! xml_reader.readNextStartElement ()) + { + error_message = tr ("No start element found in %1.\n" + "Invalid bookmark file?") + .arg (m_xbel_file.fileName ()); + return error_message; + } - if (xml_reader.name() != dc_xbel_name_format - || xml_reader.attributes ().value (dc_xbel_attr_version) != dc_xbel_value_version) - { - error_message = tr ("The file\n" - "%1\n" - "is not a valid XBEL file version 1.0.") - .arg (m_xbel_file.fileName ()); - return error_message; - } + if (xml_reader.name() != dc_xbel_name_format + || xml_reader.attributes ().value (dc_xbel_attr_version) != dc_xbel_value_version) + { + error_message = tr ("The file\n" + "%1\n" + "is not a valid XBEL file version 1.0.") + .arg (m_xbel_file.fileName ()); + return error_message; + } - // Read the elements from the file - while (xml_reader.readNextStartElement ()) - { - if (xml_reader.name () == dc_xbel_name_folder) - read_next_item (&xml_reader, folder_tag); - else if (xml_reader.name () == dc_xbel_name_bookmark) - read_next_item (&xml_reader, bookmark_tag); - else - xml_reader.skipCurrentElement (); - } + // Read the elements from the file + while (xml_reader.readNextStartElement ()) + { + if (xml_reader.name () == dc_xbel_name_folder) + read_next_item (&xml_reader, folder_tag); + else if (xml_reader.name () == dc_xbel_name_bookmark) + read_next_item (&xml_reader, bookmark_tag); + else + xml_reader.skipCurrentElement (); + } - m_xbel_file.close (); + m_xbel_file.close (); - return error_message; -} + return error_message; + } -void documentation_bookmarks::read_next_item (QXmlStreamReader *xml_reader, - item_tag tag, QTreeWidgetItem *item) -{ - QString title (tr ("Unknown title")); - if (tag == folder_tag) - { - // Next item is a folder, which might also have children - bool expanded = (xml_reader->attributes().value (dc_xbel_attr_folded) == dc_xbel_value_no); + void documentation_bookmarks::read_next_item (QXmlStreamReader *xml_reader, + item_tag tag, QTreeWidgetItem *item) + { + QString title (tr ("Unknown title")); + if (tag == folder_tag) + { + // Next item is a folder, which might also have children + bool expanded = (xml_reader->attributes().value (dc_xbel_attr_folded) == dc_xbel_value_no); + + QTreeWidgetItem *new_folder = add_folder (title, item, expanded); - QTreeWidgetItem *new_folder = add_folder (title, item, expanded); - - // Check elements of this folder for title and for recursively - // adding sub-items - while (xml_reader->readNextStartElement ()) - { - if (xml_reader->name () == dc_xbel_name_title) - { + // Check elements of this folder for title and for recursively + // adding sub-items + while (xml_reader->readNextStartElement ()) + { + if (xml_reader->name () == dc_xbel_name_title) + { + title = xml_reader->readElementText(); + new_folder->setText (0, title); + } + else if (xml_reader->name () == dc_xbel_name_folder) + read_next_item (xml_reader, folder_tag, new_folder); + else if (xml_reader->name () == dc_xbel_name_bookmark) + read_next_item (xml_reader, bookmark_tag, new_folder); + else + xml_reader->skipCurrentElement (); + } + } + else if (tag == bookmark_tag) + { + // Next item is a bookmark, without children + QString url = xml_reader->attributes().value (dc_xbel_attr_href).toString (); + while (xml_reader->readNextStartElement ()) + { + if (xml_reader->name() == dc_xbel_name_title) title = xml_reader->readElementText(); - new_folder->setText (0, title); - } - else if (xml_reader->name () == dc_xbel_name_folder) - read_next_item (xml_reader, folder_tag, new_folder); - else if (xml_reader->name () == dc_xbel_name_bookmark) - read_next_item (xml_reader, bookmark_tag, new_folder); - else - xml_reader->skipCurrentElement (); - } - } - else if (tag == bookmark_tag) - { - // Next item is a bookmark, without children - QString url = xml_reader->attributes().value (dc_xbel_attr_href).toString (); - while (xml_reader->readNextStartElement ()) - { - if (xml_reader->name() == dc_xbel_name_title) - title = xml_reader->readElementText(); - else - xml_reader->skipCurrentElement (); - } - add_bookmark (title, url, item); - } -} + else + xml_reader->skipCurrentElement (); + } + add_bookmark (title, url, item); + } + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/documentation-bookmarks.h --- a/libgui/src/documentation-bookmarks.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/documentation-bookmarks.h Tue Dec 06 15:45:27 2022 -0500 @@ -28,96 +28,94 @@ #include #include +#include #include #include #include "documentation.h" -#include "octave-qobject.h" OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class documentation; + class documentation; -class documentation_bookmarks : public QWidget -{ - Q_OBJECT + class documentation_bookmarks : public QWidget + { + Q_OBJECT + + public: -public: + documentation_bookmarks (documentation *doc, + documentation_browser *browser, + QWidget *p = nullptr); - documentation_bookmarks ( - documentation *doc, documentation_browser *browser, - base_qobject& oct_qobj, QWidget *p = nullptr); + ~documentation_bookmarks (void) = default; - ~documentation_bookmarks (void) = default; - -public slots: + public slots: - void add_bookmark (void); - void add_folder (bool); - void save_settings (gui_settings *settings); + void add_bookmark (void); + void add_folder (bool); + void save_settings (void); -private slots: + private slots: - void filter_bookmarks (const QString& pattern); - void filter_activate (bool state); - void update_filter_history (void); - void handle_double_click (QTreeWidgetItem *item, int col = 0); - void ctx_menu (const QPoint& xpos); - void open (bool); - void edit (bool); - void remove (bool); - void show_filter (bool); + void filter_bookmarks (const QString& pattern); + void filter_activate (bool state); + void update_filter_history (void); + void handle_double_click (QTreeWidgetItem *item, int col = 0); + void ctx_menu (const QPoint& xpos); + void open (bool); + void edit (bool); + void remove (bool); + void show_filter (bool); -private: + private: - enum item_role + enum item_role { url_role = Qt::UserRole, tag_role = Qt::UserRole + 1 }; - enum item_tag + enum item_tag { bookmark_tag, folder_tag }; - void add_bookmark (const QString& title, const QString& url, - QTreeWidgetItem *item = nullptr); - QTreeWidgetItem* add_folder (const QString& folder, - QTreeWidgetItem *item = nullptr, - bool expanded = true); + void add_bookmark (const QString& title, const QString& url, + QTreeWidgetItem *item = nullptr); + QTreeWidgetItem* add_folder (const QString& folder, + QTreeWidgetItem *item = nullptr, + bool expanded = true); - /*! - Writing to and reading bookmarks from an xbel-file as - proposed in the qt example - [QXmlStream Bookmarks Example](https://doc.qt.io/qt-5/qtxml-streambookmarks-example.html) - */ - void write_bookmarks (void); - void write_tree_item (QXmlStreamWriter *xml_writer, - const QTreeWidgetItem *item); - QString read_bookmarks (void); - void read_next_item (QXmlStreamReader *xml_writer, item_tag tag, - QTreeWidgetItem *item = nullptr); + /*! + Writing to and reading bookmarks from an xbel-file as + proposed in the qt example + [QXmlStream Bookmarks Example](https://doc.qt.io/qt-5/qtxml-streambookmarks-example.html) + */ + void write_bookmarks (void); + void write_tree_item (QXmlStreamWriter *xml_writer, + const QTreeWidgetItem *item); + QString read_bookmarks (void); + void read_next_item (QXmlStreamReader *xml_writer, item_tag tag, + QTreeWidgetItem *item = nullptr); - documentation *m_doc; - documentation_browser *m_browser; - base_qobject& m_octave_qobj; + documentation *m_doc; + documentation_browser *m_browser; - QComboBox *m_filter; - QTreeWidget *m_tree; + QComboBox *m_filter; + QTreeWidget *m_tree; - QTreeWidgetItem *m_ctx_menu_item; + QTreeWidgetItem *m_ctx_menu_item; - QIcon icon_folder; - QIcon icon_bookmark; + QIcon icon_folder; + QIcon icon_bookmark; - QWidget *m_filter_widget; - QCheckBox *m_filter_checkbox; - bool m_filter_shown; + QWidget *m_filter_widget; + QCheckBox *m_filter_checkbox; + bool m_filter_shown; - QFile m_xbel_file; -}; + QFile m_xbel_file; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/documentation-dock-widget.cc --- a/libgui/src/documentation-dock-widget.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/documentation-dock-widget.cc Tue Dec 06 15:45:27 2022 -0500 @@ -33,65 +33,65 @@ OCTAVE_BEGIN_NAMESPACE(octave) -documentation_dock_widget::documentation_dock_widget (QWidget *p, - base_qobject& oct_qobj) -: octave_dock_widget ("DocumentationDockWidget", p, oct_qobj), - m_docs (new documentation (this, oct_qobj)) -{ - set_title (tr ("Documentation")); - setStatusTip (tr ("See the documentation for help.")); + documentation_dock_widget::documentation_dock_widget (QWidget *p, + base_qobject& oct_qobj) + : octave_dock_widget ("DocumentationDockWidget", p, oct_qobj), + m_docs (new documentation (this, oct_qobj)) + { + set_title (tr ("Documentation")); + setStatusTip (tr ("See the documentation for help.")); - setWidget (m_docs); + setWidget (m_docs); - if (! p) - make_window (); -} + if (! p) + make_window (); + } -void documentation_dock_widget::notice_settings (const gui_settings *settings) -{ - m_docs->notice_settings (settings); -} + void documentation_dock_widget::notice_settings (void) + { + m_docs->notice_settings (); + } -void documentation_dock_widget::save_settings (void) -{ - m_docs->save_settings (); - octave_dock_widget::save_settings (); -} + void documentation_dock_widget::save_settings (void) + { + m_docs->save_settings (); + octave_dock_widget::save_settings (); + } -void documentation_dock_widget::copyClipboard (void) -{ - m_docs->copyClipboard (); -} + void documentation_dock_widget::copyClipboard (void) + { + m_docs->copyClipboard (); + } -void documentation_dock_widget::pasteClipboard (void) -{ - m_docs->pasteClipboard (); -} + void documentation_dock_widget::pasteClipboard (void) + { + m_docs->pasteClipboard (); + } -void documentation_dock_widget::selectAll (void) -{ - m_docs->selectAll (); -} + void documentation_dock_widget::selectAll (void) + { + m_docs->selectAll (); + } -void documentation_dock_widget::showDoc (const QString& name) -{ - // show the doc pane without focus for carrying on typing in the console - if (! isVisible ()) - setVisible (true); + void documentation_dock_widget::showDoc (const QString& name) + { + // show the doc pane without focus for carrying on typing in the console + if (! isVisible ()) + setVisible (true); - raise (); + raise (); - m_docs->load_ref (name); -} + m_docs->load_ref (name); + } -void documentation_dock_widget::registerDoc (const QString& name) -{ - m_docs->registerDoc (name); -} + void documentation_dock_widget::registerDoc (const QString& name) + { + m_docs->registerDoc (name); + } -void documentation_dock_widget::unregisterDoc (const QString& name) -{ - m_docs->unregisterDoc (name); -} + void documentation_dock_widget::unregisterDoc (const QString& name) + { + m_docs->unregisterDoc (name); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/documentation-dock-widget.h --- a/libgui/src/documentation-dock-widget.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/documentation-dock-widget.h Tue Dec 06 15:45:27 2022 -0500 @@ -31,35 +31,35 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; + class base_qobject; -class documentation_dock_widget : public octave_dock_widget -{ - Q_OBJECT + class documentation_dock_widget : public octave_dock_widget + { + Q_OBJECT -public: + public: - documentation_dock_widget (QWidget *parent, base_qobject& oct_qobj); + documentation_dock_widget (QWidget *parent, base_qobject& oct_qobj); - ~documentation_dock_widget (void) = default; + ~documentation_dock_widget (void) = default; -public slots: + public slots: - void notice_settings (const gui_settings *settings); - void save_settings (void); + void notice_settings (void); + void save_settings (void); - void copyClipboard (void); - void pasteClipboard (void); - void selectAll (void); + void copyClipboard (void); + void pasteClipboard (void); + void selectAll (void); - void showDoc (const QString& name); - void registerDoc (const QString& name); - void unregisterDoc (const QString& name); + void showDoc (const QString& name); + void registerDoc (const QString& name); + void unregisterDoc (const QString& name); -private: + private: - documentation *m_docs; -}; + documentation *m_docs; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/documentation.cc --- a/libgui/src/documentation.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/documentation.cc Tue Dec 06 15:45:27 2022 -0500 @@ -56,6 +56,7 @@ #include "gui-preferences-global.h" #include "gui-preferences-dc.h" #include "gui-preferences-sc.h" +#include "gui-settings.h" #include "octave-qobject.h" #include "shortcut-manager.h" @@ -65,1035 +66,1042 @@ OCTAVE_BEGIN_NAMESPACE(octave) -// The documentation splitter, which is the main widget -// of the doc dock widget -documentation::documentation (QWidget *p, base_qobject& oct_qobj) -: QSplitter (Qt::Horizontal, p), - m_octave_qobj (oct_qobj), m_doc_widget (this), - m_tool_bar (new QToolBar (this)), - m_query_string (QString ()), - m_indexed (false), - m_current_ref_name (QString ()), - m_prev_pages_menu (new QMenu (this)), - m_next_pages_menu (new QMenu (this)), - m_prev_pages_count (0), - m_next_pages_count (0), - m_findnext_shortcut (new QShortcut (this)), - m_findprev_shortcut (new QShortcut (this)) -{ - // Get original collection - QString collection = getenv ("OCTAVE_QTHELP_COLLECTION"); - if (collection.isEmpty ()) - collection = QString::fromStdString (config::oct_doc_dir () - + sys::file_ops::dir_sep_str () - + "octave_interpreter.qhc"); + // The documentation splitter, which is the main widget + // of the doc dock widget + documentation::documentation (QWidget *p, base_qobject& oct_qobj) + : QSplitter (Qt::Horizontal, p), + m_octave_qobj (oct_qobj), m_doc_widget (this), + m_tool_bar (new QToolBar (this)), + m_query_string (QString ()), + m_indexed (false), + m_current_ref_name (QString ()), + m_prev_pages_menu (new QMenu (this)), + m_next_pages_menu (new QMenu (this)), + m_prev_pages_count (0), + m_next_pages_count (0), + m_findnext_shortcut (new QShortcut (this)), + m_findprev_shortcut (new QShortcut (this)) + { + // Get original collection + QString collection = getenv ("OCTAVE_QTHELP_COLLECTION"); + if (collection.isEmpty ()) + collection = QString::fromStdString (config::oct_doc_dir () + + sys::file_ops::dir_sep_str () + + "octave_interpreter.qhc"); - // Setup the help engine with the original collection, use a writable copy - // of the original collection and load the help data - m_help_engine = new QHelpEngine (collection, this); + // Setup the help engine with the original collection, use a writable copy + // of the original collection and load the help data + m_help_engine = new QHelpEngine (collection, this); - // Mark help as readonly to avoid error if collection file is stored in a - // readonly location - m_help_engine->setProperty ("_q_readonly", - QVariant::fromValue (true)); + // Mark help as readonly to avoid error if collection file is stored in a + // readonly location + m_help_engine->setProperty ("_q_readonly", + QVariant::fromValue (true)); - QString tmpdir = QString::fromStdString (sys::env::get_temp_directory ()); - m_collection - = QString::fromStdString (sys::tempnam (tmpdir.toStdString (), - "oct-qhelp-")); + QString tmpdir = QString::fromStdString (sys::env::get_temp_directory ()); + m_collection + = QString::fromStdString (sys::tempnam (tmpdir.toStdString (), + "oct-qhelp-")); - if (m_help_engine->copyCollectionFile (m_collection)) - m_help_engine->setCollectionFile (m_collection); - else + if (m_help_engine->copyCollectionFile (m_collection)) + m_help_engine->setCollectionFile (m_collection); + else #ifdef ENABLE_DOCS - // FIXME: Perhaps a better way to do this would be to keep a count - // in the GUI preferences file. After issuing this warning 3 times - // it would be disabled. The count would need to be reset when a new - // version of Octave is installed. - QMessageBox::warning (this, tr ("Octave Documentation"), - tr ("Could not copy help collection to temporary\n" - "file. Search capabilities may be affected.\n" - "%1").arg (m_help_engine->error ())); + // FIXME: Perhaps a better way to do this would be to keep a count + // in the GUI preferences file. After issuing this warning 3 times + // it would be disabled. The count would need to be reset when a new + // version of Octave is installed. + QMessageBox::warning (this, tr ("Octave Documentation"), + tr ("Could not copy help collection to temporary\n" + "file. Search capabilities may be affected.\n" + "%1").arg (m_help_engine->error ())); #endif - connect(m_help_engine->searchEngine (), SIGNAL(indexingFinished ()), - this, SLOT(load_index ())); - connect(m_help_engine, SIGNAL(setupFinished ()), - m_help_engine->searchEngine (), SLOT(reindexDocumentation ())); + connect(m_help_engine->searchEngine (), SIGNAL(indexingFinished ()), + this, SLOT(load_index ())); + connect(m_help_engine, SIGNAL(setupFinished ()), + m_help_engine->searchEngine (), SLOT(reindexDocumentation ())); - if (! m_help_engine->setupData()) - { + if (! m_help_engine->setupData()) + { #ifdef ENABLE_DOCS - QMessageBox::warning (this, tr ("Octave Documentation"), - tr ("Could not setup the data required for the\n" - "documentation viewer. Only help texts in\n" - "the Command Window will be available.")); + QMessageBox::warning (this, tr ("Octave Documentation"), + tr ("Could not setup the data required for the\n" + "documentation viewer. Only help texts in\n" + "the Command Window will be available.")); #endif - disconnect (m_help_engine, 0, 0, 0); + disconnect (m_help_engine, 0, 0, 0); + + delete m_help_engine; + m_help_engine = nullptr; + } - delete m_help_engine; - m_help_engine = nullptr; - } + // The browser + QWidget *browser_find = new QWidget (this); + m_doc_browser = new documentation_browser (m_help_engine, browser_find); + connect (m_doc_browser, &documentation_browser::cursorPositionChanged, + this, &documentation::handle_cursor_position_change); - // The browser - QWidget *browser_find = new QWidget (this); - m_doc_browser = new documentation_browser (m_help_engine, browser_find); - connect (m_doc_browser, &documentation_browser::cursorPositionChanged, - this, &documentation::handle_cursor_position_change); + // Tool bar + construct_tool_bar (); - // Tool bar - construct_tool_bar (); + // Find bar + QWidget *find_footer = new QWidget (browser_find); + QLabel *find_label = new QLabel (tr ("Find:"), find_footer); + m_find_line_edit = new QLineEdit (find_footer); + connect (m_find_line_edit, &QLineEdit::returnPressed, + this, [=] () { find (); }); + connect (m_find_line_edit, &QLineEdit::textEdited, + this, &documentation::find_forward_from_anchor); + QToolButton *forward_button = new QToolButton (find_footer); + forward_button->setText (tr ("Search forward")); + forward_button->setToolTip (tr ("Search forward")); - // Find bar - QWidget *find_footer = new QWidget (browser_find); - QLabel *find_label = new QLabel (tr ("Find:"), find_footer); - m_find_line_edit = new QLineEdit (find_footer); - connect (m_find_line_edit, &QLineEdit::returnPressed, - this, [=] () { find (); }); - connect (m_find_line_edit, &QLineEdit::textEdited, - this, &documentation::find_forward_from_anchor); - QToolButton *forward_button = new QToolButton (find_footer); - forward_button->setText (tr ("Search forward")); - forward_button->setToolTip (tr ("Search forward")); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - forward_button->setIcon (rmgr.icon ("go-down")); - connect (forward_button, &QToolButton::pressed, - this, [=] () { find (); }); - QToolButton *backward_button = new QToolButton (find_footer); - backward_button->setText (tr ("Search backward")); - backward_button->setToolTip (tr ("Search backward")); - backward_button->setIcon (rmgr.icon ("go-up")); - connect (backward_button, &QToolButton::pressed, - this, &documentation::find_backward); - QHBoxLayout *h_box_find_footer = new QHBoxLayout (find_footer); - h_box_find_footer->addWidget (find_label); - h_box_find_footer->addWidget (m_find_line_edit); - h_box_find_footer->addWidget (forward_button); - h_box_find_footer->addWidget (backward_button); - h_box_find_footer->setMargin (2); - find_footer->setLayout (h_box_find_footer); + gui_settings settings; - QVBoxLayout *v_box_browser_find = new QVBoxLayout (browser_find); - v_box_browser_find->addWidget (m_tool_bar); - v_box_browser_find->addWidget (m_doc_browser); - v_box_browser_find->addWidget (find_footer); - browser_find->setLayout (v_box_browser_find); + forward_button->setIcon (settings.icon ("go-down")); + connect (forward_button, &QToolButton::pressed, + this, [=] () { find (); }); + QToolButton *backward_button = new QToolButton (find_footer); + backward_button->setText (tr ("Search backward")); + backward_button->setToolTip (tr ("Search backward")); + backward_button->setIcon (settings.icon ("go-up")); + connect (backward_button, &QToolButton::pressed, + this, &documentation::find_backward); + QHBoxLayout *h_box_find_footer = new QHBoxLayout (find_footer); + h_box_find_footer->addWidget (find_label); + h_box_find_footer->addWidget (m_find_line_edit); + h_box_find_footer->addWidget (forward_button); + h_box_find_footer->addWidget (backward_button); + h_box_find_footer->setMargin (2); + find_footer->setLayout (h_box_find_footer); - notice_settings (rmgr.get_settings ()); + QVBoxLayout *v_box_browser_find = new QVBoxLayout (browser_find); + v_box_browser_find->addWidget (m_tool_bar); + v_box_browser_find->addWidget (m_doc_browser); + v_box_browser_find->addWidget (find_footer); + browser_find->setLayout (v_box_browser_find); + + notice_settings (); - m_findnext_shortcut->setContext (Qt::WidgetWithChildrenShortcut); - connect (m_findnext_shortcut, &QShortcut::activated, - this, [=] () { find (); }); - m_findprev_shortcut->setContext (Qt::WidgetWithChildrenShortcut); - connect (m_findprev_shortcut, &QShortcut::activated, - this, &documentation::find_backward); + m_findnext_shortcut->setContext (Qt::WidgetWithChildrenShortcut); + connect (m_findnext_shortcut, &QShortcut::activated, + this, [=] () { find (); }); + m_findprev_shortcut->setContext (Qt::WidgetWithChildrenShortcut); + connect (m_findprev_shortcut, &QShortcut::activated, + this, &documentation::find_backward); - find_footer->hide (); - m_search_anchor_position = 0; + find_footer->hide (); + m_search_anchor_position = 0; - if (m_help_engine) - { + if (m_help_engine) + { #if defined (HAVE_NEW_QHELPINDEXWIDGET_API) - // Starting in Qt 5.15, help engine uses filters instead of old API - m_help_engine->setUsesFilterEngine (true); + // Starting in Qt 5.15, help engine uses filters instead of old API + m_help_engine->setUsesFilterEngine (true); #endif - // Layout contents, index and search - QTabWidget *navi = new QTabWidget (this); - navi->setTabsClosable (false); - navi->setMovable (true); + // Layout contents, index and search + QTabWidget *navi = new QTabWidget (this); + navi->setTabsClosable (false); + navi->setMovable (true); - // Contents - QHelpContentWidget *content = m_help_engine->contentWidget (); - content->setObjectName ("documentation_tab_contents"); - navi->addTab (content, tr ("Contents")); + // Contents + QHelpContentWidget *content = m_help_engine->contentWidget (); + content->setObjectName ("documentation_tab_contents"); + navi->addTab (content, tr ("Contents")); - connect (m_help_engine->contentWidget (), - &QHelpContentWidget::linkActivated, - m_doc_browser, [=] (const QUrl& url) { - m_doc_browser->handle_index_clicked (url); }); + connect (m_help_engine->contentWidget (), + &QHelpContentWidget::linkActivated, + m_doc_browser, [=] (const QUrl& url) { + m_doc_browser->handle_index_clicked (url); }); - // Index - QHelpIndexWidget *index = m_help_engine->indexWidget (); + // Index + QHelpIndexWidget *index = m_help_engine->indexWidget (); - m_filter = new QComboBox (this); - m_filter->setToolTip (tr ("Enter text to search the indices")); - m_filter->setEditable (true); - m_filter->setInsertPolicy (QComboBox::NoInsert); - m_filter->setMaxCount (10); - m_filter->setMaxVisibleItems (10); - m_filter->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon); - QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred); - m_filter->setSizePolicy (sizePol); - m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive); - QLabel *filter_label = new QLabel (tr ("Search")); + m_filter = new QComboBox (this); + m_filter->setToolTip (tr ("Enter text to search the indices")); + m_filter->setEditable (true); + m_filter->setInsertPolicy (QComboBox::NoInsert); + m_filter->setMaxCount (10); + m_filter->setMaxVisibleItems (10); + m_filter->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon); + QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred); + m_filter->setSizePolicy (sizePol); + m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive); + QLabel *filter_label = new QLabel (tr ("Search")); - QWidget *filter_all = new QWidget (navi); - QHBoxLayout *h_box_index = new QHBoxLayout (filter_all); - h_box_index->addWidget (filter_label); - h_box_index->addWidget (m_filter); - h_box_index->setMargin (2); - filter_all->setLayout (h_box_index); + QWidget *filter_all = new QWidget (navi); + QHBoxLayout *h_box_index = new QHBoxLayout (filter_all); + h_box_index->addWidget (filter_label); + h_box_index->addWidget (m_filter); + h_box_index->setMargin (2); + filter_all->setLayout (h_box_index); - QWidget *index_all = new QWidget (navi); - index_all->setObjectName ("documentation_tab_index"); - QVBoxLayout *v_box_index = new QVBoxLayout (index_all); - v_box_index->addWidget (filter_all); - v_box_index->addWidget (index); - index_all->setLayout (v_box_index); + QWidget *index_all = new QWidget (navi); + index_all->setObjectName ("documentation_tab_index"); + QVBoxLayout *v_box_index = new QVBoxLayout (index_all); + v_box_index->addWidget (filter_all); + v_box_index->addWidget (index); + index_all->setLayout (v_box_index); - navi->addTab (index_all, tr ("Function Index")); + navi->addTab (index_all, tr ("Function Index")); #if defined (HAVE_NEW_QHELPINDEXWIDGET_API) - connect (m_help_engine->indexWidget (), - &QHelpIndexWidget::documentActivated, - this, [=] (const QHelpLink &link) { - m_doc_browser->handle_index_clicked (link.url); }); + connect (m_help_engine->indexWidget (), + &QHelpIndexWidget::documentActivated, + this, [=] (const QHelpLink &link) { + m_doc_browser->handle_index_clicked (link.url); }); #else - connect (m_help_engine->indexWidget (), - &QHelpIndexWidget::linkActivated, - m_doc_browser, &documentation_browser::handle_index_clicked); + connect (m_help_engine->indexWidget (), + &QHelpIndexWidget::linkActivated, + m_doc_browser, &documentation_browser::handle_index_clicked); #endif - connect (m_filter, &QComboBox::editTextChanged, - this, &documentation::filter_update); + connect (m_filter, &QComboBox::editTextChanged, + this, &documentation::filter_update); - connect (m_filter->lineEdit (), &QLineEdit::editingFinished, - this, &documentation::filter_update_history); + connect (m_filter->lineEdit (), &QLineEdit::editingFinished, + this, &documentation::filter_update_history); - // Bookmarks (own class) - m_bookmarks - = new documentation_bookmarks (this, m_doc_browser, m_octave_qobj, navi); - navi->addTab (m_bookmarks, tr ("Bookmarks")); + // Bookmarks (own class) + m_bookmarks = new documentation_bookmarks (this, m_doc_browser, navi); + navi->addTab (m_bookmarks, tr ("Bookmarks")); - connect (m_action_bookmark, &QAction::triggered, - m_bookmarks, [=] () { m_bookmarks->add_bookmark (); }); + connect (m_action_bookmark, &QAction::triggered, + m_bookmarks, [=] () { m_bookmarks->add_bookmark (); }); - // Search - QHelpSearchEngine *search_engine = m_help_engine->searchEngine (); - QHelpSearchQueryWidget *search = search_engine->queryWidget (); - QHelpSearchResultWidget *result = search_engine->resultWidget (); - QWidget *search_all = new QWidget (navi); - QVBoxLayout *v_box_search = new QVBoxLayout (search_all); - v_box_search->addWidget (search); - v_box_search->addWidget (result); - search_all->setLayout (v_box_search); - search_all->setObjectName ("documentation_tab_search"); - navi->addTab (search_all, tr ("Search")); + // Search + QHelpSearchEngine *search_engine = m_help_engine->searchEngine (); + QHelpSearchQueryWidget *search = search_engine->queryWidget (); + QHelpSearchResultWidget *result = search_engine->resultWidget (); + QWidget *search_all = new QWidget (navi); + QVBoxLayout *v_box_search = new QVBoxLayout (search_all); + v_box_search->addWidget (search); + v_box_search->addWidget (result); + search_all->setLayout (v_box_search); + search_all->setObjectName ("documentation_tab_search"); + navi->addTab (search_all, tr ("Search")); - connect (search, &QHelpSearchQueryWidget::search, - this, &documentation::global_search); + connect (search, &QHelpSearchQueryWidget::search, + this, &documentation::global_search); - connect (search_engine, &QHelpSearchEngine::searchingStarted, - this, &documentation::global_search_started); - connect (search_engine, &QHelpSearchEngine::searchingFinished, - this, &documentation::global_search_finished); + connect (search_engine, &QHelpSearchEngine::searchingStarted, + this, &documentation::global_search_started); + connect (search_engine, &QHelpSearchEngine::searchingFinished, + this, &documentation::global_search_finished); - connect (search_engine->resultWidget (), - &QHelpSearchResultWidget::requestShowLink, - this, &documentation::handle_search_result_clicked); + connect (search_engine->resultWidget (), + &QHelpSearchResultWidget::requestShowLink, + this, &documentation::handle_search_result_clicked); - // Fill the splitter - insertWidget (0, navi); - insertWidget (1, browser_find); - setStretchFactor (1, 1); - } -} + // Fill the splitter + insertWidget (0, navi); + insertWidget (1, browser_find); + setStretchFactor (1, 1); + } + } -documentation::~documentation (void) -{ - // Cleanup temporary file and directory - QFile file (m_collection); - if (file.exists ()) - { - QFileInfo finfo (file); - QString bname = finfo.fileName (); - QDir dir = finfo.absoluteDir (); - dir.setFilter (QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden); - QStringList namefilter; - namefilter.append ("*" + bname + "*"); - for (const auto& fi : dir.entryInfoList (namefilter)) - { - std::string file_name = fi.absoluteFilePath ().toStdString (); - sys::recursive_rmdir (file_name); - } + documentation::~documentation (void) + { + // Cleanup temporary file and directory + QFile file (m_collection); + if (file.exists ()) + { + QFileInfo finfo (file); + QString bname = finfo.fileName (); + QDir dir = finfo.absoluteDir (); + dir.setFilter (QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden); + QStringList namefilter; + namefilter.append ("*" + bname + "*"); + for (const auto& fi : dir.entryInfoList (namefilter)) + { + std::string file_name = fi.absoluteFilePath ().toStdString (); + sys::recursive_rmdir (file_name); + } - file.remove(); - } -} + file.remove(); + } + } -QAction * documentation::add_action (const QIcon& icon, const QString& text, - const char *member, QWidget *receiver, - QToolBar *tool_bar) -{ - QAction *a; - QWidget *r = this; - if (receiver != nullptr) - r = receiver; + QAction * documentation::add_action (const QIcon& icon, const QString& text, + const char *member, QWidget *receiver, + QToolBar *tool_bar) + { + QAction *a; + QWidget *r = this; + if (receiver != nullptr) + r = receiver; - a = new QAction (icon, text, this); + a = new QAction (icon, text, this); - if (member) - connect (a, SIGNAL (triggered ()), r, member); + if (member) + connect (a, SIGNAL (triggered ()), r, member); - if (tool_bar) - tool_bar->addAction (a); + if (tool_bar) + tool_bar->addAction (a); - m_doc_widget->addAction (a); // important for shortcut context - a->setShortcutContext (Qt::WidgetWithChildrenShortcut); + m_doc_widget->addAction (a); // important for shortcut context + a->setShortcutContext (Qt::WidgetWithChildrenShortcut); + + return a; + } - return a; -} + void documentation::construct_tool_bar (void) + { + // Home, Previous, Next + gui_settings settings; -void documentation::construct_tool_bar (void) -{ - // Home, Previous, Next - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - m_action_go_home - = add_action (rmgr.icon ("go-home"), tr ("Go home"), SLOT (home (void)), - m_doc_browser, m_tool_bar); + m_action_go_home + = add_action (settings.icon ("go-home"), tr ("Go home"), SLOT (home (void)), + m_doc_browser, m_tool_bar); - m_action_go_prev - = add_action (rmgr.icon ("go-previous"), tr ("Go back"), - SLOT (backward (void)), m_doc_browser, m_tool_bar); - m_action_go_prev->setEnabled (false); + m_action_go_prev + = add_action (settings.icon ("go-previous"), tr ("Go back"), + SLOT (backward (void)), m_doc_browser, m_tool_bar); + m_action_go_prev->setEnabled (false); - // popdown menu with prev pages files - QToolButton *popdown_button_prev_pages = new QToolButton (); - popdown_button_prev_pages->setToolTip (tr ("Previous pages")); - popdown_button_prev_pages->setMenu (m_prev_pages_menu); - popdown_button_prev_pages->setPopupMode (QToolButton::InstantPopup); - popdown_button_prev_pages->setToolButtonStyle (Qt::ToolButtonTextOnly); - popdown_button_prev_pages->setCheckable (false); - popdown_button_prev_pages->setArrowType(Qt::DownArrow); - m_tool_bar->addWidget (popdown_button_prev_pages); + // popdown menu with prev pages files + QToolButton *popdown_button_prev_pages = new QToolButton (); + popdown_button_prev_pages->setToolTip (tr ("Previous pages")); + popdown_button_prev_pages->setMenu (m_prev_pages_menu); + popdown_button_prev_pages->setPopupMode (QToolButton::InstantPopup); + popdown_button_prev_pages->setToolButtonStyle (Qt::ToolButtonTextOnly); + popdown_button_prev_pages->setCheckable (false); + popdown_button_prev_pages->setArrowType(Qt::DownArrow); + m_tool_bar->addWidget (popdown_button_prev_pages); - m_action_go_next - = add_action (rmgr.icon ("go-next"), tr ("Go forward"), - SLOT (forward (void)), m_doc_browser, m_tool_bar); - m_action_go_next->setEnabled (false); + m_action_go_next + = add_action (settings.icon ("go-next"), tr ("Go forward"), + SLOT (forward (void)), m_doc_browser, m_tool_bar); + m_action_go_next->setEnabled (false); - // popdown menu with prev pages files - QToolButton *popdown_button_next_pages = new QToolButton (); - popdown_button_next_pages->setToolTip (tr ("Next pages")); - popdown_button_next_pages->setMenu (m_next_pages_menu); - popdown_button_next_pages->setPopupMode (QToolButton::InstantPopup); - popdown_button_next_pages->setToolButtonStyle (Qt::ToolButtonTextOnly); - popdown_button_next_pages->setArrowType(Qt::DownArrow); - m_tool_bar->addWidget (popdown_button_next_pages); + // popdown menu with prev pages files + QToolButton *popdown_button_next_pages = new QToolButton (); + popdown_button_next_pages->setToolTip (tr ("Next pages")); + popdown_button_next_pages->setMenu (m_next_pages_menu); + popdown_button_next_pages->setPopupMode (QToolButton::InstantPopup); + popdown_button_next_pages->setToolButtonStyle (Qt::ToolButtonTextOnly); + popdown_button_next_pages->setArrowType(Qt::DownArrow); + m_tool_bar->addWidget (popdown_button_next_pages); - connect (m_doc_browser, &documentation_browser::backwardAvailable, - m_action_go_prev, &QAction::setEnabled); - connect (m_doc_browser, &documentation_browser::backwardAvailable, - popdown_button_prev_pages, &QToolButton::setEnabled); - connect (m_doc_browser, &documentation_browser::forwardAvailable, - m_action_go_next, &QAction::setEnabled); - connect (m_doc_browser, &documentation_browser::forwardAvailable, - popdown_button_next_pages, &QToolButton::setEnabled); - connect (m_doc_browser, &documentation_browser::historyChanged, - this, &documentation::update_history_menus); + connect (m_doc_browser, &documentation_browser::backwardAvailable, + m_action_go_prev, &QAction::setEnabled); + connect (m_doc_browser, &documentation_browser::backwardAvailable, + popdown_button_prev_pages, &QToolButton::setEnabled); + connect (m_doc_browser, &documentation_browser::forwardAvailable, + m_action_go_next, &QAction::setEnabled); + connect (m_doc_browser, &documentation_browser::forwardAvailable, + popdown_button_next_pages, &QToolButton::setEnabled); + connect (m_doc_browser, &documentation_browser::historyChanged, + this, &documentation::update_history_menus); - // Init prev/next menus - for (int i = 0; i < max_history_entries; ++i) - { - m_prev_pages_actions[i] = new QAction (this); - m_prev_pages_actions[i]->setVisible (false); - m_next_pages_actions[i] = new QAction (this); - m_next_pages_actions[i]->setVisible (false); - m_prev_pages_menu->addAction (m_prev_pages_actions[i]); - m_next_pages_menu->addAction (m_next_pages_actions[i]); - } + // Init prev/next menus + for (int i = 0; i < max_history_entries; ++i) + { + m_prev_pages_actions[i] = new QAction (this); + m_prev_pages_actions[i]->setVisible (false); + m_next_pages_actions[i] = new QAction (this); + m_next_pages_actions[i]->setVisible (false); + m_prev_pages_menu->addAction (m_prev_pages_actions[i]); + m_next_pages_menu->addAction (m_next_pages_actions[i]); + } - connect (m_prev_pages_menu, &QMenu::triggered, - this, &documentation::open_hist_url); - connect (m_next_pages_menu, &QMenu::triggered, - this, &documentation::open_hist_url); + connect (m_prev_pages_menu, &QMenu::triggered, + this, &documentation::open_hist_url); + connect (m_next_pages_menu, &QMenu::triggered, + this, &documentation::open_hist_url); - // Find - m_tool_bar->addSeparator (); - m_action_find - = add_action (rmgr.icon ("edit-find"), tr ("Find"), - SLOT (activate_find (void)), this, m_tool_bar); + // Find + m_tool_bar->addSeparator (); + m_action_find + = add_action (settings.icon ("edit-find"), tr ("Find"), + SLOT (activate_find (void)), this, m_tool_bar); - // Zoom - m_tool_bar->addSeparator (); - m_action_zoom_in - = add_action (rmgr.icon ("view-zoom-in"), tr ("Zoom in"), - SLOT (zoom_in (void)), m_doc_browser, m_tool_bar); - m_action_zoom_out - = add_action (rmgr.icon ("view-zoom-out"), tr ("Zoom out"), - SLOT (zoom_out (void)), m_doc_browser, m_tool_bar); - m_action_zoom_original - = add_action (rmgr.icon ("view-zoom-original"), tr ("Zoom original"), - SLOT (zoom_original (void)), m_doc_browser, m_tool_bar); + // Zoom + m_tool_bar->addSeparator (); + m_action_zoom_in + = add_action (settings.icon ("view-zoom-in"), tr ("Zoom in"), + SLOT (zoom_in (void)), m_doc_browser, m_tool_bar); + m_action_zoom_out + = add_action (settings.icon ("view-zoom-out"), tr ("Zoom out"), + SLOT (zoom_out (void)), m_doc_browser, m_tool_bar); + m_action_zoom_original + = add_action (settings.icon ("view-zoom-original"), tr ("Zoom original"), + SLOT (zoom_original (void)), m_doc_browser, m_tool_bar); - // Bookmarks (connect slots later) - m_tool_bar->addSeparator (); - m_action_bookmark - = add_action (rmgr.icon ("bookmark-new"), tr ("Bookmark current page"), - nullptr, nullptr, m_tool_bar); -} + // Bookmarks (connect slots later) + m_tool_bar->addSeparator (); + m_action_bookmark + = add_action (settings.icon ("bookmark-new"), + tr ("Bookmark current page"), nullptr, nullptr, m_tool_bar); + } -void documentation::global_search (void) -{ - if (! m_help_engine) - return; + void documentation::global_search (void) + { + if (! m_help_engine) + return; - QString query_string; + QString query_string; #if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT) - QString queries - = m_help_engine->searchEngine ()->queryWidget ()->searchInput (); - query_string = queries; + QString queries + = m_help_engine->searchEngine ()->queryWidget ()->searchInput (); + query_string = queries; #else - // FIXME: drop this part when support for Qt4 is dropped - QList queries - = m_help_engine->searchEngine ()->queryWidget ()->query (); - if (queries.count ()) - query_string = queries.first ().wordList.join (" "); - else - query_string = ""; + // FIXME: drop this part when support for Qt4 is dropped + QList queries + = m_help_engine->searchEngine ()->queryWidget ()->query (); + if (queries.count ()) + query_string = queries.first ().wordList.join (" "); + else + query_string = ""; #endif - if (query_string.isEmpty ()) - return; + if (query_string.isEmpty ()) + return; - // Get quoted search strings first, then take first string as fall back - QRegExp rx ("\"([^\"]*)\""); - if (rx.indexIn (query_string, 0) != -1) - m_internal_search = rx.cap (1); - else + // Get quoted search strings first, then take first string as fall back + QRegExp rx ("\"([^\"]*)\""); + if (rx.indexIn (query_string, 0) != -1) + m_internal_search = rx.cap (1); + else #if defined (HAVE_QT_SPLITBEHAVIOR_ENUM) - m_internal_search = query_string.split (" ", Qt::SkipEmptyParts).first (); + m_internal_search = query_string.split (" ", Qt::SkipEmptyParts).first (); #else - m_internal_search = query_string.split (" ", QString::SkipEmptyParts).first (); + m_internal_search = query_string.split (" ", QString::SkipEmptyParts).first (); #endif - m_help_engine->searchEngine ()->search (queries); -} + m_help_engine->searchEngine ()->search (queries); + } -void documentation::global_search_started (void) -{ - qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); -} + void documentation::global_search_started (void) + { + qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); + } -void documentation::global_search_finished (int) -{ - if (! m_help_engine) - return; + void documentation::global_search_finished (int) + { + if (! m_help_engine) + return; - if (! m_internal_search.isEmpty ()) - { - m_query_string = m_internal_search; + if (! m_internal_search.isEmpty ()) + { + m_query_string = m_internal_search; - QHelpSearchEngine *search_engine = m_help_engine->searchEngine (); - if (search_engine) - { + QHelpSearchEngine *search_engine = m_help_engine->searchEngine (); + if (search_engine) + { #if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT) - QVector res - = search_engine->searchResults (0, search_engine->searchResultCount ()); + QVector res + = search_engine->searchResults (0, search_engine->searchResultCount ()); #else - QList< QPair > res - = search_engine->hits (0, search_engine->hitCount ()); + QList< QPair > res + = search_engine->hits (0, search_engine->hitCount ()); #endif - if (res.count ()) - { - QUrl url; + if (res.count ()) + { + QUrl url; - if (res.count () == 1) + if (res.count () == 1) #if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT) - url = res.front ().url (); + url = res.front ().url (); #else - url = res.front ().first; + url = res.front ().first; #endif - else - { - // Remove the quotes we added - QString search_string = m_internal_search; + else + { + // Remove the quotes we added + QString search_string = m_internal_search; - for (auto r = res.begin (); r != res.end (); r++) - { + for (auto r = res.begin (); r != res.end (); r++) + { #if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT) - QString title = r->title ().toLower (); - QUrl tmpurl = r->url (); + QString title = r->title ().toLower (); + QUrl tmpurl = r->url (); #else - QString title = r->second.toLower (); - QUrl tmpurl = r->first; + QString title = r->second.toLower (); + QUrl tmpurl = r->first; #endif - if (title.contains (search_string.toLower ())) - { - if (title.indexOf (search_string.toLower ()) == 0) - { + if (title.contains (search_string.toLower ())) + { + if (title.indexOf (search_string.toLower ()) == 0) + { + url = tmpurl; + break; + } + else if (url.isEmpty ()) url = tmpurl; - break; - } - else if (url.isEmpty ()) - url = tmpurl; - } - } - } + } + } + } - if (! url.isEmpty ()) - { - connect (this, &documentation::show_single_result, - this, &documentation::handle_search_result_clicked); + if (! url.isEmpty ()) + { + connect (this, &documentation::show_single_result, + this, &documentation::handle_search_result_clicked); - emit show_single_result (url); - } - } - } + emit show_single_result (url); + } + } + } - m_internal_search = QString (); - } + m_internal_search = QString (); + } - qApp->restoreOverrideCursor(); -} + qApp->restoreOverrideCursor(); + } -void documentation::handle_search_result_clicked (const QUrl& url) -{ - // Open url with matching text - m_doc_browser->handle_index_clicked (url); + void documentation::handle_search_result_clicked (const QUrl& url) + { + // Open url with matching text + m_doc_browser->handle_index_clicked (url); - // Select all occurrences of matching text - select_all_occurrences (m_query_string); + // Select all occurrences of matching text + select_all_occurrences (m_query_string); - // Open search widget with matching text as search string - m_find_line_edit->setText (m_query_string); - m_find_line_edit->parentWidget ()->show (); + // Open search widget with matching text as search string + m_find_line_edit->setText (m_query_string); + m_find_line_edit->parentWidget ()->show (); - // If no occurrence can be found go to the top of the page - if (! m_doc_browser->find (m_find_line_edit->text ())) + // If no occurrence can be found go to the top of the page + if (! m_doc_browser->find (m_find_line_edit->text ())) + m_doc_browser->moveCursor (QTextCursor::Start); + else + { + // Go to to first occurrence of search text. Going to the end and then + // search backwards until the last occurrence ensures the search text + // is visible in the first line of the visible part of the text. + m_doc_browser->moveCursor (QTextCursor::End); + while (m_doc_browser->find (m_find_line_edit->text (), + QTextDocument::FindBackward)); + } + } + + void documentation::select_all_occurrences (const QString& text) + { + // Get highlight background and text color + QPalette pal = QApplication::palette (); + QTextCharFormat format; + QColor col = pal.color (QPalette::Highlight); + col.setAlphaF (0.25); + format.setBackground (QBrush (col)); + format.setForeground (QBrush (pal.color (QPalette::Text))); + + // Create list for extra selected items + QList selected; m_doc_browser->moveCursor (QTextCursor::Start); - else - { - // Go to to first occurrence of search text. Going to the end and then - // search backwards until the last occurrence ensures the search text - // is visible in the first line of the visible part of the text. - m_doc_browser->moveCursor (QTextCursor::End); - while (m_doc_browser->find (m_find_line_edit->text (), - QTextDocument::FindBackward)); - } -} - -void documentation::select_all_occurrences (const QString& text) -{ - // Get highlight background and text color - QPalette pal = QApplication::palette (); - QTextCharFormat format; - QColor col = pal.color (QPalette::Highlight); - col.setAlphaF (0.25); - format.setBackground (QBrush (col)); - format.setForeground (QBrush (pal.color (QPalette::Text))); - // Create list for extra selected items - QList selected; - m_doc_browser->moveCursor (QTextCursor::Start); + // Find all occurrences and add them to the selection + while ( m_doc_browser->find (text) ) + { + QTextEdit::ExtraSelection selected_item; + selected_item.cursor = m_doc_browser->textCursor (); + selected_item.format = format; + selected.append (selected_item); + } - // Find all occurrences and add them to the selection - while ( m_doc_browser->find (text) ) - { - QTextEdit::ExtraSelection selected_item; - selected_item.cursor = m_doc_browser->textCursor (); - selected_item.format = format; - selected.append (selected_item); - } + // Apply selection and move back to the beginning + m_doc_browser->setExtraSelections (selected); + m_doc_browser->moveCursor (QTextCursor::Start); + } - // Apply selection and move back to the beginning - m_doc_browser->setExtraSelections (selected); - m_doc_browser->moveCursor (QTextCursor::Start); -} + void documentation::notice_settings (void) + { + gui_settings settings; -void documentation::notice_settings (const gui_settings *settings) -{ - // If m_help_engine is not defined, the objects accessed by this method - // are not valid. Thus, just return in this case. - if (! m_help_engine) - return; + // If m_help_engine is not defined, the objects accessed by this method + // are not valid. Thus, just return in this case. + if (! m_help_engine) + return; - // Icon size in the toolbar. - int size_idx = settings->value (global_icon_size).toInt (); - size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2 + // Icon size in the toolbar. + int size_idx = settings.value (global_icon_size).toInt (); + size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2 + + QStyle *st = style (); + int icon_size = st->pixelMetric (global_icon_sizes[size_idx]); + m_tool_bar->setIconSize (QSize (icon_size, icon_size)); - QStyle *st = style (); - int icon_size = st->pixelMetric (global_icon_sizes[size_idx]); - m_tool_bar->setIconSize (QSize (icon_size, icon_size)); - - // Shortcuts - shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); + // Shortcuts + shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); - scmgr.set_shortcut (m_action_find, sc_edit_edit_find_replace); - scmgr.shortcut (m_findnext_shortcut, sc_edit_edit_find_next); - scmgr.shortcut (m_findprev_shortcut, sc_edit_edit_find_previous); - scmgr.set_shortcut (m_action_zoom_in, sc_edit_view_zoom_in); - scmgr.set_shortcut (m_action_zoom_out, sc_edit_view_zoom_out); - scmgr.set_shortcut (m_action_zoom_original, sc_edit_view_zoom_normal); - scmgr.set_shortcut (m_action_go_home, sc_doc_go_home); - scmgr.set_shortcut (m_action_go_prev, sc_doc_go_back); - scmgr.set_shortcut (m_action_go_next, sc_doc_go_next); - scmgr.set_shortcut (m_action_bookmark, sc_doc_bookmark); + scmgr.set_shortcut (m_action_find, sc_edit_edit_find_replace); + scmgr.shortcut (m_findnext_shortcut, sc_edit_edit_find_next); + scmgr.shortcut (m_findprev_shortcut, sc_edit_edit_find_previous); + scmgr.set_shortcut (m_action_zoom_in, sc_edit_view_zoom_in); + scmgr.set_shortcut (m_action_zoom_out, sc_edit_view_zoom_out); + scmgr.set_shortcut (m_action_zoom_original, sc_edit_view_zoom_normal); + scmgr.set_shortcut (m_action_go_home, sc_doc_go_home); + scmgr.set_shortcut (m_action_go_prev, sc_doc_go_back); + scmgr.set_shortcut (m_action_go_next, sc_doc_go_next); + scmgr.set_shortcut (m_action_bookmark, sc_doc_bookmark); - // Settings for the browser - m_doc_browser->notice_settings (settings); -} + // Settings for the browser + m_doc_browser->notice_settings (); + } -void documentation::save_settings (void) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + void documentation::save_settings (void) + { + gui_settings settings; + + m_doc_browser->save_settings (); + m_bookmarks->save_settings (); + } - m_doc_browser->save_settings (settings); - m_bookmarks->save_settings (settings); -} + void documentation::copyClipboard (void) + { + if (m_doc_browser->hasFocus ()) + { + m_doc_browser->copy(); + } + } -void documentation::copyClipboard (void) -{ - if (m_doc_browser->hasFocus ()) - { - m_doc_browser->copy(); - } -} + void documentation::pasteClipboard (void) { } -void documentation::pasteClipboard (void) { } + void documentation::selectAll (void) { } -void documentation::selectAll (void) { } - -void documentation::load_index (void) -{ - m_indexed = true; + void documentation::load_index (void) + { + m_indexed = true; - // Show index if no other page is required. - if (m_current_ref_name.isEmpty ()) - m_doc_browser->setSource - (QUrl ("qthelp://org.octave.interpreter-1.0/doc/octave.html/index.html")); - else - load_ref (m_current_ref_name); + // Show index if no other page is required. + if (m_current_ref_name.isEmpty ()) + m_doc_browser->setSource + (QUrl ("qthelp://org.octave.interpreter-1.0/doc/octave.html/index.html")); + else + load_ref (m_current_ref_name); - m_help_engine->contentWidget ()->expandToDepth (0); -} + m_help_engine->contentWidget ()->expandToDepth (0); + } -void documentation::load_ref (const QString& ref_name) -{ - if (! m_help_engine || ref_name.isEmpty ()) - return; + void documentation::load_ref (const QString& ref_name) + { + if (! m_help_engine || ref_name.isEmpty ()) + return; - m_current_ref_name = ref_name; + m_current_ref_name = ref_name; - if (! m_indexed) - return; + if (! m_indexed) + return; #if defined (HAVE_QHELPENGINE_DOCUMENTSFORIDENTIFIER) - QList found_links - = m_help_engine->documentsForIdentifier (ref_name); + QList found_links + = m_help_engine->documentsForIdentifier (ref_name); #else - QMap found_links - = m_help_engine->linksForIdentifier (ref_name); + QMap found_links + = m_help_engine->linksForIdentifier (ref_name); #endif - QTabWidget *navi = static_cast (widget (0)); + QTabWidget *navi = static_cast (widget (0)); - if (found_links.count() > 0) - { - // First search in the function index + if (found_links.count() > 0) + { + // First search in the function index #if defined (HAVE_QHELPENGINE_DOCUMENTSFORIDENTIFIER) - QUrl first_url = found_links.constFirst().url; + QUrl first_url = found_links.constFirst().url; #else - QUrl first_url = found_links.constBegin().value (); + QUrl first_url = found_links.constBegin().value (); #endif - m_doc_browser->setSource (first_url); + m_doc_browser->setSource (first_url); - // Switch to function index tab - m_help_engine->indexWidget()->filterIndices (ref_name); - QWidget *index_tab - = navi->findChild ("documentation_tab_index"); - navi->setCurrentWidget (index_tab); - } - else - { - // Use full text search to provide the best match - QHelpSearchEngine *search_engine = m_help_engine->searchEngine (); - QHelpSearchQueryWidget *search_query = search_engine->queryWidget (); + // Switch to function index tab + m_help_engine->indexWidget()->filterIndices (ref_name); + QWidget *index_tab + = navi->findChild ("documentation_tab_index"); + navi->setCurrentWidget (index_tab); + } + else + { + // Use full text search to provide the best match + QHelpSearchEngine *search_engine = m_help_engine->searchEngine (); + QHelpSearchQueryWidget *search_query = search_engine->queryWidget (); #if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT) - QString query = ref_name; - query.prepend ("\"").append ("\""); + QString query = ref_name; + query.prepend ("\"").append ("\""); #else - QList query; - query << QHelpSearchQuery (QHelpSearchQuery::DEFAULT, - QStringList (QString("\"") + ref_name + QString("\""))); + QList query; + query << QHelpSearchQuery (QHelpSearchQuery::DEFAULT, + QStringList (QString("\"") + ref_name + QString("\""))); #endif - m_internal_search = ref_name; - search_engine->search (query); + m_internal_search = ref_name; + search_engine->search (query); - // Switch to search tab + // Switch to search tab #if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT) - search_query->setSearchInput (query); + search_query->setSearchInput (query); #else - search_query->setQuery (query); + search_query->setQuery (query); #endif - QWidget *search_tab - = navi->findChild ("documentation_tab_search"); - navi->setCurrentWidget (search_tab); - } -} + QWidget *search_tab + = navi->findChild ("documentation_tab_search"); + navi->setCurrentWidget (search_tab); + } + } -void documentation::activate_find (void) -{ - if (m_find_line_edit->parentWidget ()->isVisible ()) - { - m_find_line_edit->parentWidget ()->hide (); - m_doc_browser->setFocus (); - } - else - { - m_find_line_edit->parentWidget ()->show (); - m_find_line_edit->selectAll (); - m_find_line_edit->setFocus (); - } -} + void documentation::activate_find (void) + { + if (m_find_line_edit->parentWidget ()->isVisible ()) + { + m_find_line_edit->parentWidget ()->hide (); + m_doc_browser->setFocus (); + } + else + { + m_find_line_edit->parentWidget ()->show (); + m_find_line_edit->selectAll (); + m_find_line_edit->setFocus (); + } + } -void documentation::filter_update (const QString& expression) -{ - if (! m_help_engine) - return; + void documentation::filter_update (const QString& expression) + { + if (! m_help_engine) + return; - QString wildcard; - if (expression.contains (QLatin1Char('*'))) - wildcard = expression; + QString wildcard; + if (expression.contains (QLatin1Char('*'))) + wildcard = expression; - m_help_engine->indexWidget ()->filterIndices(expression, wildcard); -} + m_help_engine->indexWidget ()->filterIndices(expression, wildcard); + } -void documentation::filter_update_history (void) -{ - QString text = m_filter->currentText (); // get current text - int index = m_filter->findText (text); // and its actual index + void documentation::filter_update_history (void) + { + QString text = m_filter->currentText (); // get current text + int index = m_filter->findText (text); // and its actual index - if (index > -1) - m_filter->removeItem (index); // remove if already existing + if (index > -1) + m_filter->removeItem (index); // remove if already existing - m_filter->insertItem (0, text); // (re)insert at beginning - m_filter->setCurrentIndex (0); -} + m_filter->insertItem (0, text); // (re)insert at beginning + m_filter->setCurrentIndex (0); + } -void documentation::find_backward (void) -{ - find (true); -} + void documentation::find_backward (void) + { + find (true); + } -void documentation::find (bool backward) -{ - if (! m_help_engine) - return; + void documentation::find (bool backward) + { + if (! m_help_engine) + return; - QTextDocument::FindFlags find_flags; - if (backward) - find_flags = QTextDocument::FindBackward; + QTextDocument::FindFlags find_flags; + if (backward) + find_flags = QTextDocument::FindBackward; - if (! m_doc_browser->find (m_find_line_edit->text (), find_flags)) - { - // Nothing was found, restart search from the begin or end of text - QTextCursor textcur = m_doc_browser->textCursor (); - if (backward) - textcur.movePosition (QTextCursor::End); - else - textcur.movePosition (QTextCursor::Start); - m_doc_browser->setTextCursor (textcur); - m_doc_browser->find (m_find_line_edit->text (), find_flags); - } + if (! m_doc_browser->find (m_find_line_edit->text (), find_flags)) + { + // Nothing was found, restart search from the begin or end of text + QTextCursor textcur = m_doc_browser->textCursor (); + if (backward) + textcur.movePosition (QTextCursor::End); + else + textcur.movePosition (QTextCursor::Start); + m_doc_browser->setTextCursor (textcur); + m_doc_browser->find (m_find_line_edit->text (), find_flags); + } - record_anchor_position (); -} + record_anchor_position (); + } -void documentation::find_forward_from_anchor (const QString& text) -{ - if (! m_help_engine) - return; + void documentation::find_forward_from_anchor (const QString& text) + { + if (! m_help_engine) + return; - // Search from the current position - QTextCursor textcur = m_doc_browser->textCursor (); - textcur.setPosition (m_search_anchor_position); - m_doc_browser->setTextCursor (textcur); + // Search from the current position + QTextCursor textcur = m_doc_browser->textCursor (); + textcur.setPosition (m_search_anchor_position); + m_doc_browser->setTextCursor (textcur); - if (! m_doc_browser->find (text)) - { - // Nothing was found, restart search from the beginning - textcur.movePosition (QTextCursor::Start); - m_doc_browser->setTextCursor (textcur); - m_doc_browser->find (text); - } -} + if (! m_doc_browser->find (text)) + { + // Nothing was found, restart search from the beginning + textcur.movePosition (QTextCursor::Start); + m_doc_browser->setTextCursor (textcur); + m_doc_browser->find (text); + } + } -void documentation::record_anchor_position (void) -{ - if (! m_help_engine) - return; + void documentation::record_anchor_position (void) + { + if (! m_help_engine) + return; - m_search_anchor_position = m_doc_browser->textCursor ().position (); -} + m_search_anchor_position = m_doc_browser->textCursor ().position (); + } -void documentation::handle_cursor_position_change (void) -{ - if (! m_help_engine) - return; + void documentation::handle_cursor_position_change (void) + { + if (! m_help_engine) + return; - if (m_doc_browser->hasFocus ()) - record_anchor_position (); -} + if (m_doc_browser->hasFocus ()) + record_anchor_position (); + } -void documentation::registerDoc (const QString& qch) -{ - if (m_help_engine) - { - QString ns = m_help_engine->namespaceName (qch); - bool do_setup = true; - if (m_help_engine->registeredDocumentations ().contains (ns)) - { - if (m_help_engine->documentationFileName (ns) == qch) - do_setup = false; - else - { - m_help_engine->unregisterDocumentation (ns); - m_help_engine->registerDocumentation (qch); - } - } - else if (! m_help_engine->registerDocumentation (qch)) - { - QMessageBox::warning (this, tr ("Octave Documentation"), - tr ("Unable to register help file %1."). - arg (qch)); - return; - } + void documentation::registerDoc (const QString& qch) + { + if (m_help_engine) + { + QString ns = m_help_engine->namespaceName (qch); + bool do_setup = true; + if (m_help_engine->registeredDocumentations ().contains (ns)) + { + if (m_help_engine->documentationFileName (ns) == qch) + do_setup = false; + else + { + m_help_engine->unregisterDocumentation (ns); + m_help_engine->registerDocumentation (qch); + } + } + else if (! m_help_engine->registerDocumentation (qch)) + { + QMessageBox::warning (this, tr ("Octave Documentation"), + tr ("Unable to register help file %1."). + arg (qch)); + return; + } - if (do_setup) - m_help_engine->setupData(); - } -} + if (do_setup) + m_help_engine->setupData(); + } + } -void documentation::unregisterDoc (const QString& qch) -{ - if (! m_help_engine) - return; + void documentation::unregisterDoc (const QString& qch) + { + if (! m_help_engine) + return; - QString ns = m_help_engine->namespaceName (qch); - if (m_help_engine - && m_help_engine->registeredDocumentations ().contains (ns) - && m_help_engine->documentationFileName (ns) == qch) - { - m_help_engine->unregisterDocumentation (ns); - m_help_engine->setupData (); - } -} + QString ns = m_help_engine->namespaceName (qch); + if (m_help_engine + && m_help_engine->registeredDocumentations ().contains (ns) + && m_help_engine->documentationFileName (ns) == qch) + { + m_help_engine->unregisterDocumentation (ns); + m_help_engine->setupData (); + } + } -void documentation::update_history_menus (void) -{ - if (m_prev_pages_count != m_doc_browser->backwardHistoryCount ()) - { - update_history (m_doc_browser->backwardHistoryCount (), - m_prev_pages_actions); - m_prev_pages_count = m_doc_browser->backwardHistoryCount (); - } + void documentation::update_history_menus (void) + { + if (m_prev_pages_count != m_doc_browser->backwardHistoryCount ()) + { + update_history (m_doc_browser->backwardHistoryCount (), + m_prev_pages_actions); + m_prev_pages_count = m_doc_browser->backwardHistoryCount (); + } - if (m_next_pages_count != m_doc_browser->forwardHistoryCount ()) - { - update_history (m_doc_browser->forwardHistoryCount (), - m_next_pages_actions); - m_next_pages_count = m_doc_browser->forwardHistoryCount (); - } -} + if (m_next_pages_count != m_doc_browser->forwardHistoryCount ()) + { + update_history (m_doc_browser->forwardHistoryCount (), + m_next_pages_actions); + m_next_pages_count = m_doc_browser->forwardHistoryCount (); + } + } -void documentation::update_history (int new_count, QAction **actions) -{ - // Which menu has to be updated? - int prev_next = -1; - QAction *a = m_action_go_prev; - if (actions == m_next_pages_actions) - { - prev_next = 1; - a = m_action_go_next; - } + void documentation::update_history (int new_count, QAction **actions) + { + // Which menu has to be updated? + int prev_next = -1; + QAction *a = m_action_go_prev; + if (actions == m_next_pages_actions) + { + prev_next = 1; + a = m_action_go_next; + } - // Get maximal count limited by array size - int count = qMin (new_count, int (max_history_entries)); + // Get maximal count limited by array size + int count = qMin (new_count, int (max_history_entries)); - // Fill used menu entries - for (int i = 0; i < count; i++) - { - QString title - = title_and_anchor (m_doc_browser->historyTitle (prev_next*(i+1)), - m_doc_browser->historyUrl (prev_next*(i+1))); + // Fill used menu entries + for (int i = 0; i < count; i++) + { + QString title + = title_and_anchor (m_doc_browser->historyTitle (prev_next*(i+1)), + m_doc_browser->historyUrl (prev_next*(i+1))); - if (i == 0) - a->setText (title); // set tool tip for prev/next buttons + if (i == 0) + a->setText (title); // set tool tip for prev/next buttons - actions[i]->setText (title); - actions[i]->setData (m_doc_browser->historyUrl (prev_next*(i+1))); - actions[i]->setEnabled (true); - actions[i]->setVisible (true); - } + actions[i]->setText (title); + actions[i]->setData (m_doc_browser->historyUrl (prev_next*(i+1))); + actions[i]->setEnabled (true); + actions[i]->setVisible (true); + } - // Hide unused menu entries - for (int j = count; j < max_history_entries; j++) - { - actions[j]->setEnabled (false); - actions[j]->setVisible (false); - } -} + // Hide unused menu entries + for (int j = count; j < max_history_entries; j++) + { + actions[j]->setEnabled (false); + actions[j]->setVisible (false); + } + } -void documentation::open_hist_url (QAction *a) -{ - m_doc_browser->setSource (a->data ().toUrl ()); -} + void documentation::open_hist_url (QAction *a) + { + m_doc_browser->setSource (a->data ().toUrl ()); + } -// Utility functions + // Utility functions -QString documentation::title_and_anchor (const QString& title, const QUrl& url) -{ - QString retval = title; - QString u = url.toString (); + QString documentation::title_and_anchor (const QString& title, const QUrl& url) + { + QString retval = title; + QString u = url.toString (); - retval.remove (QRegExp ("\\s*\\(*GNU Octave \\(version [^\\)]*\\)[: \\)]*")); + retval.remove (QRegExp ("\\s*\\(*GNU Octave \\(version [^\\)]*\\)[: \\)]*")); - // Since the title only contains the section name and not the - // specific anchor, extract the latter from the url and append - // it to the title - if (u.contains ('#')) - { - // Get the anchor from the url - QString anchor = u.split ('#').last (); - // Remove internal string parts - anchor.remove (QRegExp ("^index-")); - anchor.remove (QRegExp ("^SEC_")); - anchor.remove (QRegExp ("^XREF")); - anchor.remove ("Concept-Index_cp_letter-"); - anchor.replace ("-", " "); + // Since the title only contains the section name and not the + // specific anchor, extract the latter from the url and append + // it to the title + if (u.contains ('#')) + { + // Get the anchor from the url + QString anchor = u.split ('#').last (); + // Remove internal string parts + anchor.remove (QRegExp ("^index-")); + anchor.remove (QRegExp ("^SEC_")); + anchor.remove (QRegExp ("^XREF")); + anchor.remove ("Concept-Index_cp_letter-"); + anchor.replace ("-", " "); - // replace encoded special chars by their unencoded versions - QRegExp rx = QRegExp ("_00([0-7][0-9a-f])"); - int pos = 0; - while ((pos = rx.indexIn(anchor, pos)) != -1) - { - anchor.replace ("_00"+rx.cap (1), QChar (rx.cap (1).toInt (nullptr, 16))); - pos += rx.matchedLength(); - } + // replace encoded special chars by their unencoded versions + QRegExp rx = QRegExp ("_00([0-7][0-9a-f])"); + int pos = 0; + while ((pos = rx.indexIn(anchor, pos)) != -1) + { + anchor.replace ("_00"+rx.cap (1), QChar (rx.cap (1).toInt (nullptr, 16))); + pos += rx.matchedLength(); + } - if (retval != anchor) - retval = retval + ": " + anchor; - } + if (retval != anchor) + retval = retval + ": " + anchor; + } + + return retval; + } - return retval; -} - -// -// The documentation browser -// + // + // The documentation browser + // -documentation_browser::documentation_browser (QHelpEngine *he, QWidget *p) - : QTextBrowser (p), m_help_engine (he), m_zoom_level (max_zoom_level+1) -{ - setOpenLinks (false); - connect (this, &documentation_browser::anchorClicked, - this, [=] (const QUrl& url) { handle_index_clicked (url); }); + documentation_browser::documentation_browser (QHelpEngine *he, QWidget *p) + : QTextBrowser (p), m_help_engine (he), m_zoom_level (max_zoom_level+1) + { + setOpenLinks (false); + connect (this, &documentation_browser::anchorClicked, + this, [=] (const QUrl& url) { handle_index_clicked (url); }); + + // Make sure we have access to one of the monospace fonts listed in + // octave.css for rendering formated code blocks + QStringList fonts = {"Fantasque Sans Mono", "FreeMono", "Courier New", + "Cousine", "Courier"}; - // Make sure we have access to one of the monospace fonts listed in - // octave.css for rendering formated code blocks - QStringList fonts = {"Fantasque Sans Mono", "FreeMono", "Courier New", - "Cousine", "Courier"}; - - bool load_default_font = true; + bool load_default_font = true; - for (int i = 0; i < fonts.size (); ++i) - { - QFont font (fonts.at (i)); - if (font.exactMatch ()) - { - load_default_font = false; - break; - } - } + for (int i = 0; i < fonts.size (); ++i) + { + QFont font (fonts.at (i)); + if (font.exactMatch ()) + { + load_default_font = false; + break; + } + } + + if (load_default_font) + { + QString fonts_dir = + QString::fromStdString (sys::env::getenv ("OCTAVE_FONTS_DIR") + + sys::file_ops::dir_sep_str ()); + + QStringList default_fonts = {"FreeMono", "FreeMonoBold", + "FreeMonoBoldOblique", "FreeMonoOblique"}; - if (load_default_font) - { - QString fonts_dir = - QString::fromStdString (sys::env::getenv ("OCTAVE_FONTS_DIR") - + sys::file_ops::dir_sep_str ()); - - QStringList default_fonts = {"FreeMono", "FreeMonoBold", - "FreeMonoBoldOblique", "FreeMonoOblique"}; + for (int i = 0; i < default_fonts.size (); ++i) + { + QString fontpath = + fonts_dir + default_fonts.at(i) + QString (".otf"); + QFontDatabase::addApplicationFont (fontpath); + } + } + } - for (int i = 0; i < default_fonts.size (); ++i) - { - QString fontpath = - fonts_dir + default_fonts.at(i) + QString (".otf"); - QFontDatabase::addApplicationFont (fontpath); - } - } -} + void documentation_browser::handle_index_clicked (const QUrl& url, + const QString&) + { + if (url.scheme () == "qthelp") + setSource (url); + else + QDesktopServices::openUrl (url); + } -void documentation_browser::handle_index_clicked (const QUrl& url, - const QString&) -{ - if (url.scheme () == "qthelp") - setSource (url); - else - QDesktopServices::openUrl (url); -} + void documentation_browser::notice_settings (void) + { + gui_settings settings; -void documentation_browser::notice_settings (const gui_settings *settings) -{ - // Zoom level only at startup, not when other settings have changed - if (m_zoom_level > max_zoom_level) - { - m_zoom_level = settings->value (dc_browser_zoom_level).toInt (); - zoomIn (m_zoom_level); - } -} + // Zoom level only at startup, not when other settings have changed + if (m_zoom_level > max_zoom_level) + { + m_zoom_level = settings.value (dc_browser_zoom_level).toInt (); + zoomIn (m_zoom_level); + } + } -QVariant documentation_browser::loadResource (int type, const QUrl& url) -{ - if (m_help_engine && url.scheme () == "qthelp") - return QVariant (m_help_engine->fileData(url)); - else - return QTextBrowser::loadResource(type, url); -} + QVariant documentation_browser::loadResource (int type, const QUrl& url) + { + if (m_help_engine && url.scheme () == "qthelp") + return QVariant (m_help_engine->fileData(url)); + else + return QTextBrowser::loadResource(type, url); + } -void documentation_browser::save_settings (gui_settings *settings) -{ - settings->setValue (dc_browser_zoom_level.key, m_zoom_level); + void documentation_browser::save_settings (void) + { + gui_settings settings; - settings->sync (); -} + settings.setValue (dc_browser_zoom_level.key, m_zoom_level); + + settings.sync (); + } -void documentation_browser::zoom_in (void) -{ - if (m_zoom_level < max_zoom_level) - { - zoomIn (); - m_zoom_level++; - } -} + void documentation_browser::zoom_in (void) + { + if (m_zoom_level < max_zoom_level) + { + zoomIn (); + m_zoom_level++; + } + } -void documentation_browser::zoom_out (void) -{ - if (m_zoom_level > min_zoom_level) - { - zoomOut (); - m_zoom_level--; - } -} + void documentation_browser::zoom_out (void) + { + if (m_zoom_level > min_zoom_level) + { + zoomOut (); + m_zoom_level--; + } + } -void documentation_browser::zoom_original (void) -{ - zoomIn (- m_zoom_level); - m_zoom_level = 0; -} + void documentation_browser::zoom_original (void) + { + zoomIn (- m_zoom_level); + m_zoom_level = 0; + } -void documentation_browser::wheelEvent (QWheelEvent *we) -{ - if (we->modifiers () == Qt::ControlModifier) - { + void documentation_browser::wheelEvent (QWheelEvent *we) + { + if (we->modifiers () == Qt::ControlModifier) + { #if defined (HAVE_QWHEELEVENT_ANGLEDELTA) - if (we->angleDelta().y () > 0) + if (we->angleDelta().y () > 0) #else if (we->delta() > 0) #endif @@ -1101,10 +1109,10 @@ else zoom_out (); - we->accept (); - } - else - QTextEdit::wheelEvent (we); -} + we->accept (); + } + else + QTextEdit::wheelEvent (we); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/documentation.h --- a/libgui/src/documentation.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/documentation.h Tue Dec 06 15:45:27 2022 -0500 @@ -37,171 +37,169 @@ #include #include -#include "gui-settings.h" - OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class documentation; -class documentation_bookmarks; + class base_qobject; + class documentation; + class documentation_bookmarks; -//! Documentation browser derived from Textbrowser + //! Documentation browser derived from Textbrowser -class documentation_browser : public QTextBrowser -{ - Q_OBJECT + class documentation_browser : public QTextBrowser + { + Q_OBJECT -public: + public: - documentation_browser (QHelpEngine *help_engine, QWidget *parent = nullptr); - ~documentation_browser (void) = default; + documentation_browser (QHelpEngine *help_engine, QWidget *parent = nullptr); + ~documentation_browser (void) = default; - virtual QVariant loadResource (int type, const QUrl& url); + virtual QVariant loadResource (int type, const QUrl& url); -public slots: + public slots: - void handle_index_clicked (const QUrl& url, - const QString& keyword = QString ()); - void notice_settings (const gui_settings *settings); - void save_settings (gui_settings *settings); + void handle_index_clicked (const QUrl& url, + const QString& keyword = QString ()); + void notice_settings (void); + void save_settings (void); - //! Zooming in and out while taking care of the zoom level - //!@{ - void zoom_in (void); - void zoom_out (void); - void zoom_original (void); - //!@} + //! Zooming in and out while taking care of the zoom level + //!@{ + void zoom_in (void); + void zoom_out (void); + void zoom_original (void); + //!@} -protected: + protected: - void wheelEvent (QWheelEvent *we); + void wheelEvent (QWheelEvent *we); -private: + private: - QHelpEngine *m_help_engine; + QHelpEngine *m_help_engine; - //! Store the current zoom level - int m_zoom_level; + //! Store the current zoom level + int m_zoom_level; - //! Minimal and maximal zoom level avoiding calling - //! zoom_in and zoom_out without actually zooming but - //! with changing the stored zoom level - enum + //! Minimal and maximal zoom level avoiding calling + //! zoom_in and zoom_out without actually zooming but + //! with changing the stored zoom level + enum { min_zoom_level = -5, max_zoom_level = 10 }; -}; + }; -//! The documentation main class derived from QSplitter + //! The documentation main class derived from QSplitter -class documentation : public QSplitter -{ - Q_OBJECT + class documentation : public QSplitter + { + Q_OBJECT -public: + public: - documentation (QWidget *parent, base_qobject& oct_qobj); - ~documentation (void); + documentation (QWidget *parent, base_qobject& oct_qobj); + ~documentation (void); - /*! - Generate a string with page name @p title and current anchor - from @p url for using in prev/next or bookmarks menu: + /*! + Generate a string with page name @p title and current anchor + from @p url for using in prev/next or bookmarks menu: - @param title current title of the page as QString - @param url current url as QUrl + @param title current title of the page as QString + @param url current url as QUrl - @return QString "title: anchor" - */ - QString title_and_anchor (const QString& title, const QUrl& url); + @return QString "title: anchor" + */ + QString title_and_anchor (const QString& title, const QUrl& url); -signals: + signals: - void show_single_result (const QUrl&); + void show_single_result (const QUrl&); -public slots: + public slots: - void notice_settings (const gui_settings *settings); - void save_settings (void); + void notice_settings (void); + void save_settings (void); - void copyClipboard (void); - void pasteClipboard (void); - void selectAll (void); + void copyClipboard (void); + void pasteClipboard (void); + void selectAll (void); - void load_index (void); - void load_ref (const QString& name = QString ()); - void registerDoc (const QString& name); - void unregisterDoc (const QString& name); + void load_index (void); + void load_ref (const QString& name = QString ()); + void registerDoc (const QString& name); + void unregisterDoc (const QString& name); -private slots: + private slots: - void activate_find (void); - void global_search (void); - void global_search_started (void); - void global_search_finished (int hits); - void filter_update (const QString& expression); - void filter_update_history (void); - void find (bool backward = false); - void find_backward (void); - void find_forward_from_anchor (const QString& text); - void record_anchor_position (void); - void handle_cursor_position_change (void); - void handle_search_result_clicked (const QUrl& url); + void activate_find (void); + void global_search (void); + void global_search_started (void); + void global_search_finished (int hits); + void filter_update (const QString& expression); + void filter_update_history (void); + void find (bool backward = false); + void find_backward (void); + void find_forward_from_anchor (const QString& text); + void record_anchor_position (void); + void handle_cursor_position_change (void); + void handle_search_result_clicked (const QUrl& url); - void update_history_menus (void); - void open_hist_url (QAction *a); + void update_history_menus (void); + void open_hist_url (QAction *a); -private: + private: - void construct_tool_bar (void); - QAction * add_action (const QIcon& icon, const QString& text, - const char *member, QWidget *receiver = nullptr, - QToolBar *tool_bar = nullptr); - void update_history (int new_count, QAction **actions); + void construct_tool_bar (void); + QAction * add_action (const QIcon& icon, const QString& text, + const char *member, QWidget *receiver = nullptr, + QToolBar *tool_bar = nullptr); + void update_history (int new_count, QAction **actions); - //! Select all occurrences of a string in the doc browser - void select_all_occurrences (const QString& text); + //! Select all occurrences of a string in the doc browser + void select_all_occurrences (const QString& text); - base_qobject& m_octave_qobj; + base_qobject& m_octave_qobj; - QHelpEngine *m_help_engine; - QString m_internal_search; - documentation_browser *m_doc_browser; - documentation_bookmarks *m_bookmarks; - QLineEdit *m_find_line_edit; - int m_search_anchor_position; - QComboBox *m_filter; - QString m_collection; + QHelpEngine *m_help_engine; + QString m_internal_search; + documentation_browser *m_doc_browser; + documentation_bookmarks *m_bookmarks; + QLineEdit *m_find_line_edit; + int m_search_anchor_position; + QComboBox *m_filter; + QString m_collection; - QWidget *m_doc_widget; - QToolBar *m_tool_bar; - QString m_query_string; + QWidget *m_doc_widget; + QToolBar *m_tool_bar; + QString m_query_string; - bool m_indexed; - QString m_current_ref_name; + bool m_indexed; + QString m_current_ref_name; - QAction *m_action_go_home; - QAction *m_action_go_prev; - QAction *m_action_go_next; - QMenu *m_prev_pages_menu; - QMenu *m_next_pages_menu; - int m_prev_pages_count; - int m_next_pages_count; + QAction *m_action_go_home; + QAction *m_action_go_prev; + QAction *m_action_go_next; + QMenu *m_prev_pages_menu; + QMenu *m_next_pages_menu; + int m_prev_pages_count; + int m_next_pages_count; - enum { max_history_entries = 10 }; - QAction *m_prev_pages_actions[max_history_entries]; - QAction *m_next_pages_actions[max_history_entries]; + enum { max_history_entries = 10 }; + QAction *m_prev_pages_actions[max_history_entries]; + QAction *m_next_pages_actions[max_history_entries]; - QAction *m_action_bookmark; + QAction *m_action_bookmark; - QAction *m_action_find; - QShortcut *m_findnext_shortcut; - QShortcut *m_findprev_shortcut; + QAction *m_action_find; + QShortcut *m_findnext_shortcut; + QShortcut *m_findprev_shortcut; - QAction *m_action_zoom_in; - QAction *m_action_zoom_out; - QAction *m_action_zoom_original; -}; + QAction *m_action_zoom_in; + QAction *m_action_zoom_out; + QAction *m_action_zoom_original; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/dw-main-window.cc --- a/libgui/src/dw-main-window.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/dw-main-window.cc Tue Dec 06 15:45:27 2022 -0500 @@ -36,214 +36,215 @@ #include #include "dw-main-window.h" +#include "gui-preferences-sc.h" +#include "gui-settings.h" #include "octave-qobject.h" #include "shortcut-manager.h" -#include "gui-preferences-sc.h" OCTAVE_BEGIN_NAMESPACE(octave) -dw_main_window::dw_main_window (base_qobject& oct_qobj, QWidget *p) -: QMainWindow (p), m_octave_qobj (oct_qobj) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + dw_main_window::dw_main_window (base_qobject& oct_qobj, QWidget *p) + : QMainWindow (p), m_octave_qobj (oct_qobj) + { + gui_settings settings; - // Adding the actions for closing the dock widgets - m_close_action - = add_action (nullptr, rmgr.icon ("window-close", false), - tr ("&Close"), SLOT (request_close ()), this); + // Adding the actions for closing the dock widgets + m_close_action + = add_action (nullptr, settings.icon ("window-close", false), + tr ("&Close"), SLOT (request_close ()), this); - m_close_all_action - = add_action (nullptr, rmgr.icon ("window-close", false), - tr ("Close &All"), SLOT (request_close_all ()), this); + m_close_all_action + = add_action (nullptr, settings.icon ("window-close", false), + tr ("Close &All"), SLOT (request_close_all ()), this); - m_close_others_action - = add_action (nullptr, rmgr.icon ("window-close", false), - tr ("Close &Other"), SLOT (request_close_other ()), this); + m_close_others_action + = add_action (nullptr, settings.icon ("window-close", false), + tr ("Close &Other"), SLOT (request_close_other ()), this); - m_switch_left_action - = add_action (nullptr, QIcon (), tr ("Switch to &Left Widget"), - SLOT (request_switch_left ()), this); + m_switch_left_action + = add_action (nullptr, QIcon (), tr ("Switch to &Left Widget"), + SLOT (request_switch_left ()), this); - m_switch_right_action - = add_action (nullptr, QIcon (), tr ("Switch to &Right Widget"), - SLOT (request_switch_right ()), this); + m_switch_right_action + = add_action (nullptr, QIcon (), tr ("Switch to &Right Widget"), + SLOT (request_switch_right ()), this); - // The list of actions for floating widgets - m_actions_list << m_close_action; - m_actions_list << m_close_others_action; - m_actions_list << m_close_all_action; - m_actions_list << m_switch_left_action; - m_actions_list << m_switch_right_action; + // The list of actions for floating widgets + m_actions_list << m_close_action; + m_actions_list << m_close_others_action; + m_actions_list << m_close_all_action; + m_actions_list << m_switch_left_action; + m_actions_list << m_switch_right_action; - notice_settings (rmgr.get_settings ()); -} + notice_settings (); + } -// Re-implementing the popup menu of the main window -QMenu *dw_main_window::createPopupMenu () -{ - QList new_actions = QList (); - new_actions.append (m_close_action); - new_actions.append (m_close_others_action); - new_actions.append (m_close_all_action); + // Re-implementing the popup menu of the main window + QMenu *dw_main_window::createPopupMenu () + { + QList new_actions = QList (); + new_actions.append (m_close_action); + new_actions.append (m_close_others_action); + new_actions.append (m_close_all_action); - QMenu *menu = QMainWindow::createPopupMenu (); - QList actions = menu->actions(); + QMenu *menu = QMainWindow::createPopupMenu (); + QList actions = menu->actions(); - if (actions.length () > 0) - { - QAction *sep = menu->insertSeparator (actions.at (0)); - menu->insertActions (sep, new_actions); - } - else - menu->addActions (new_actions); + if (actions.length () > 0) + { + QAction *sep = menu->insertSeparator (actions.at (0)); + menu->insertActions (sep, new_actions); + } + else + menu->addActions (new_actions); - return menu; -} + return menu; + } -// Adding an action to the main window -QAction * dw_main_window::add_action (QMenu *menu, const QIcon& icon, - const QString& text, const char *member, - QWidget *receiver) -{ - QAction *a; - QWidget *r = this; + // Adding an action to the main window + QAction * dw_main_window::add_action (QMenu *menu, const QIcon& icon, + const QString& text, const char *member, + QWidget *receiver) + { + QAction *a; + QWidget *r = this; - if (receiver != nullptr) - r = receiver; + if (receiver != nullptr) + r = receiver; - if (menu) - a = menu->addAction (icon, text, r, member); - else - { - a = new QAction (icon, text, this); - a->setEnabled (true); - connect (a, SIGNAL (triggered ()), r, member); - } + if (menu) + a = menu->addAction (icon, text, r, member); + else + { + a = new QAction (icon, text, this); + a->setEnabled (true); + connect (a, SIGNAL (triggered ()), r, member); + } - addAction (a); // important for shortcut context - a->setShortcutContext (Qt::WidgetWithChildrenShortcut); + addAction (a); // important for shortcut context + a->setShortcutContext (Qt::WidgetWithChildrenShortcut); - return a; -} + return a; + } -// Update the settings -void dw_main_window::notice_settings (const gui_settings *) -{ - shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); + // Update the settings + void dw_main_window::notice_settings (void) + { + shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); - scmgr.set_shortcut (m_close_action, sc_edit_file_close); - scmgr.set_shortcut (m_close_all_action, sc_edit_file_close_all); - scmgr.set_shortcut (m_close_others_action, sc_edit_file_close_other); + scmgr.set_shortcut (m_close_action, sc_edit_file_close); + scmgr.set_shortcut (m_close_all_action, sc_edit_file_close_all); + scmgr.set_shortcut (m_close_others_action, sc_edit_file_close_other); - scmgr.set_shortcut (m_switch_left_action, sc_edit_tabs_switch_left_tab); - scmgr.set_shortcut (m_switch_right_action, sc_edit_tabs_switch_right_tab); -} + scmgr.set_shortcut (m_switch_left_action, sc_edit_tabs_switch_left_tab); + scmgr.set_shortcut (m_switch_right_action, sc_edit_tabs_switch_right_tab); + } -// Slots for handling actions + // Slots for handling actions -// Close current widget -void dw_main_window::request_close () -{ - for (int i = 0; i < m_dw_list.length (); i++) - { - if (m_dw_list.at (i)->hasFocus ()) - { - m_dw_list.at (i)->close (); - if (i > 0) - m_dw_list.at (i-1)->setFocus (); - break; - } - } -} + // Close current widget + void dw_main_window::request_close () + { + for (int i = 0; i < m_dw_list.length (); i++) + { + if (m_dw_list.at (i)->hasFocus ()) + { + m_dw_list.at (i)->close (); + if (i > 0) + m_dw_list.at (i-1)->setFocus (); + break; + } + } + } -// Close other widgets -void dw_main_window::request_close_other () -{ - for (int i = m_dw_list.length () - 1; i >= 0; i--) - { - if (! m_dw_list.at (i)->hasFocus ()) - m_dw_list.at (i)->close (); - } -} + // Close other widgets + void dw_main_window::request_close_other () + { + for (int i = m_dw_list.length () - 1; i >= 0; i--) + { + if (! m_dw_list.at (i)->hasFocus ()) + m_dw_list.at (i)->close (); + } + } -// Close all widgets -void dw_main_window::request_close_all () -{ - for (int i = m_dw_list.length () - 1; i >= 0; i--) - m_dw_list.at (i)->close (); -} + // Close all widgets + void dw_main_window::request_close_all () + { + for (int i = m_dw_list.length () - 1; i >= 0; i--) + m_dw_list.at (i)->close (); + } -// Switch to left widget -void dw_main_window::request_switch_left () -{ - request_switch (-1); -} + // Switch to left widget + void dw_main_window::request_switch_left () + { + request_switch (-1); + } -// Switch to right widget -void dw_main_window::request_switch_right () -{ - request_switch (1); -} + // Switch to right widget + void dw_main_window::request_switch_right () + { + request_switch (1); + } -// Switch to left/right widget -void dw_main_window::request_switch (int direction) -{ - int active = -1, next; + // Switch to left/right widget + void dw_main_window::request_switch (int direction) + { + int active = -1, next; - for (int i = m_dw_list.length () - 1; i >= 0; i--) - { - if (m_dw_list.at (i)->hasFocus ()) - { - active = i; - break; - } - } + for (int i = m_dw_list.length () - 1; i >= 0; i--) + { + if (m_dw_list.at (i)->hasFocus ()) + { + active = i; + break; + } + } - if (active == -1) - return; + if (active == -1) + return; - if (direction == -1 && active == 0) - next = m_dw_list.length () - 1; - else if (direction == 1 && active == m_dw_list.length () - 1) - next = 0; - else - next = active + direction; + if (direction == -1 && active == 0) + next = m_dw_list.length () - 1; + else if (direction == 1 && active == m_dw_list.length () - 1) + next = 0; + else + next = active + direction; - m_dw_list.at (next)->raise (); - m_dw_list.at (next)->activateWindow (); - m_dw_list.at (next)->setFocus (); -} + m_dw_list.at (next)->raise (); + m_dw_list.at (next)->activateWindow (); + m_dw_list.at (next)->setFocus (); + } -// Reimplemented Event -bool dw_main_window::event (QEvent *ev) -{ - if (ev->type () == QEvent::ChildAdded - || ev->type () == QEvent::ChildRemoved) - { - // Adding or Removing a child indicates that a dock widget was - // created or removed. - // In all cases, the list of dock widgets has to be updated. - m_dw_list = findChildren(); - } + // Reimplemented Event + bool dw_main_window::event (QEvent *ev) + { + if (ev->type () == QEvent::ChildAdded + || ev->type () == QEvent::ChildRemoved) + { + // Adding or Removing a child indicates that a dock widget was + // created or removed. + // In all cases, the list of dock widgets has to be updated. + m_dw_list = findChildren(); + } - if (ev->type () == QEvent::StyleChange) - { - // This might indicate un- or re-docking a widget: Make sure - // floating widgets get a copy of our actions - for (int i = m_dw_list.length () - 1; i >= 0; i--) - { - // First remove possibly existing actions - for (int j = m_actions_list.length () - 1; j >0; j--) - m_dw_list.at (i)->removeAction (m_actions_list.at (j)); + if (ev->type () == QEvent::StyleChange) + { + // This might indicate un- or re-docking a widget: Make sure + // floating widgets get a copy of our actions + for (int i = m_dw_list.length () - 1; i >= 0; i--) + { + // First remove possibly existing actions + for (int j = m_actions_list.length () - 1; j >0; j--) + m_dw_list.at (i)->removeAction (m_actions_list.at (j)); - // Then add our actions for floating widgets - if (m_dw_list.at (i)->isFloating ()) - m_dw_list.at (i)->addActions (m_actions_list); - } - } + // Then add our actions for floating widgets + if (m_dw_list.at (i)->isFloating ()) + m_dw_list.at (i)->addActions (m_actions_list); + } + } - return QMainWindow::event (ev); -} + return QMainWindow::event (ev); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/dw-main-window.h --- a/libgui/src/dw-main-window.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/dw-main-window.h Tue Dec 06 15:45:27 2022 -0500 @@ -28,67 +28,65 @@ #include -#include "gui-settings.h" - OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; + class base_qobject; -class dw_main_window : public QMainWindow -{ - Q_OBJECT + class dw_main_window : public QMainWindow + { + Q_OBJECT -public: + public: - dw_main_window (base_qobject& oct_qboj, QWidget *parent = nullptr); + dw_main_window (base_qobject& oct_qboj, QWidget *parent = nullptr); - ~dw_main_window (void) = default; + ~dw_main_window (void) = default; - // No copying! + // No copying! - dw_main_window (const dw_main_window&) = delete; + dw_main_window (const dw_main_window&) = delete; - dw_main_window& operator = (const dw_main_window&) = delete; + dw_main_window& operator = (const dw_main_window&) = delete; -public slots: + public slots: - void notice_settings (const gui_settings *); + void notice_settings (void); -protected slots: + protected slots: - virtual QMenu * createPopupMenu (); + virtual QMenu * createPopupMenu (); - virtual bool event (QEvent *ev); + virtual bool event (QEvent *ev); -private slots: + private slots: - void request_close (); - void request_close_all (); - void request_close_other (); + void request_close (); + void request_close_all (); + void request_close_other (); - void request_switch_left (); - void request_switch_right (); + void request_switch_left (); + void request_switch_right (); -private: + private: - void request_switch (int direction); + void request_switch (int direction); - QAction * add_action (QMenu *menu, const QIcon& icon, const QString& text, - const char *member, QWidget *receiver); + QAction * add_action (QMenu *menu, const QIcon& icon, const QString& text, + const char *member, QWidget *receiver); - base_qobject& m_octave_qobj; + base_qobject& m_octave_qobj; - QList m_dw_list; + QList m_dw_list; - QAction *m_close_action; - QAction *m_close_all_action; - QAction *m_close_others_action; + QAction *m_close_action; + QAction *m_close_all_action; + QAction *m_close_others_action; - QAction *m_switch_left_action; - QAction *m_switch_right_action; + QAction *m_switch_left_action; + QAction *m_switch_right_action; - QList m_actions_list; -}; + QList m_actions_list; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/external-editor-interface.cc --- a/libgui/src/external-editor-interface.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/external-editor-interface.cc Tue Dec 06 15:45:27 2022 -0500 @@ -33,99 +33,97 @@ #include "external-editor-interface.h" #include "gui-settings.h" #include "gui-preferences-global.h" -#include "octave-qobject.h" OCTAVE_BEGIN_NAMESPACE(octave) -external_editor_interface::external_editor_interface (QWidget *p, - base_qobject& oct_qobj) -: QWidget (p), m_octave_qobj (oct_qobj) -{ } + external_editor_interface::external_editor_interface (QWidget *p) + : QWidget (p) + { } -// Calling the external editor -bool -external_editor_interface::call_custom_editor (const QString& file, int line) -{ - QString editor = external_editor (); - if (editor.isEmpty ()) - return true; + // Calling the external editor + bool + external_editor_interface::call_custom_editor (const QString& file, int line) + { + QString editor = external_editor (); + if (editor.isEmpty ()) + return true; - if (line < 0) - line = 0; + if (line < 0) + line = 0; - // replace macros - editor.replace ("%f", file); - editor.replace ("%l", QString::number (line)); + // replace macros + editor.replace ("%f", file); + editor.replace ("%l", QString::number (line)); - QStringList arguments = editor.split (QRegExp("\\s+")); - editor = arguments.takeFirst (); + QStringList arguments = editor.split (QRegExp("\\s+")); + editor = arguments.takeFirst (); - // start the process and check for success - bool started_ok = QProcess::startDetached (editor, arguments); + // start the process and check for success + bool started_ok = QProcess::startDetached (editor, arguments); - if (started_ok != true) - { - QMessageBox *msgBox = new QMessageBox (QMessageBox::Critical, - tr ("Octave Editor"), - tr ("Could not start custom file editor\n%1"). - arg (editor), - QMessageBox::Ok); + if (started_ok != true) + { + QMessageBox *msgBox = new QMessageBox (QMessageBox::Critical, + tr ("Octave Editor"), + tr ("Could not start custom file editor\n%1"). + arg (editor), + QMessageBox::Ok); - msgBox->setWindowModality (Qt::NonModal); - msgBox->setAttribute (Qt::WA_DeleteOnClose); - msgBox->show (); - } + msgBox->setWindowModality (Qt::NonModal); + msgBox->setAttribute (Qt::WA_DeleteOnClose); + msgBox->show (); + } - return started_ok; -} + return started_ok; + } -// Slots for the several signals for invoking the editor + // Slots for the several signals for invoking the editor -void external_editor_interface::request_new_file (const QString&) -{ - call_custom_editor (); -} + void external_editor_interface::request_new_file (const QString&) + { + call_custom_editor (); + } -void external_editor_interface::request_open_file (const QString& file_name, - const QString&, int line, - bool, bool, bool, - const QString&) -{ - call_custom_editor (file_name, line); -} + void external_editor_interface::request_open_file (const QString& file_name, + const QString&, int line, + bool, bool, bool, + const QString&) + { + call_custom_editor (file_name, line); + } -void external_editor_interface::handle_edit_file_request (const QString& file) -{ - call_custom_editor (file); -} + void external_editor_interface::handle_edit_file_request (const QString& file) + { + call_custom_editor (file); + } + + // Get and verify the settings of the external editor program + QString external_editor_interface::external_editor (void) + { + gui_settings settings; -// Get and verify the settings of the external editor program -QString external_editor_interface::external_editor (void) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - QString editor = settings->value (global_custom_editor.key, - global_custom_editor.def).toString (); + QString editor = settings.value (global_custom_editor.key, + global_custom_editor.def).toString (); - // check the settings (avoid an empty string) - if (editor.trimmed ().isEmpty ()) - { - QMessageBox *msgBox - = new QMessageBox (QMessageBox::Warning, - tr ("Octave Editor"), - tr ("There is no custom editor configured yet.\n" - "Do you want to open the preferences?"), - QMessageBox::No | QMessageBox::Yes); - msgBox->setDefaultButton (QMessageBox::Yes); - msgBox->setAttribute (Qt::WA_DeleteOnClose); + // check the settings (avoid an empty string) + if (editor.trimmed ().isEmpty ()) + { + QMessageBox *msgBox + = new QMessageBox (QMessageBox::Warning, + tr ("Octave Editor"), + tr ("There is no custom editor configured yet.\n" + "Do you want to open the preferences?"), + QMessageBox::No | QMessageBox::Yes); + msgBox->setDefaultButton (QMessageBox::Yes); + msgBox->setAttribute (Qt::WA_DeleteOnClose); - int button = msgBox->exec (); + int button = msgBox->exec (); - if (button == QMessageBox::Yes) - emit request_settings_dialog ("editor"); - } + if (button == QMessageBox::Yes) + emit request_settings_dialog ("editor"); + } - return editor; -} + return editor; + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/external-editor-interface.h --- a/libgui/src/external-editor-interface.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/external-editor-interface.h Tue Dec 06 15:45:27 2022 -0500 @@ -31,42 +31,38 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; + class external_editor_interface : public QWidget + { + Q_OBJECT -class external_editor_interface : public QWidget -{ - Q_OBJECT + public: -public: + external_editor_interface (QWidget *main_win); - external_editor_interface (QWidget *main_win, base_qobject& oct_qobj); + ~external_editor_interface (void) = default; - ~external_editor_interface (void) = default; + signals: -signals: + void request_settings_dialog (const QString&); - void request_settings_dialog (const QString&); - -public slots: + public slots: - bool call_custom_editor (const QString& file = QString (), int line = -1); + bool call_custom_editor (const QString& file = QString (), int line = -1); - void request_open_file (const QString& fileName, - const QString& encoding = QString (), - int line = -1, bool debug_pointer = false, - bool breakpoint_marker = false, bool insert = true, - const QString& cond = ""); + void request_open_file (const QString& fileName, + const QString& encoding = QString (), + int line = -1, bool debug_pointer = false, + bool breakpoint_marker = false, bool insert = true, + const QString& cond = ""); - void request_new_file (const QString&); + void request_new_file (const QString&); - void handle_edit_file_request (const QString& file); + void handle_edit_file_request (const QString& file); -private: + private: - QString external_editor (void); - - base_qobject& m_octave_qobj; -}; + QString external_editor (void); + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/files-dock-widget.cc --- a/libgui/src/files-dock-widget.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/files-dock-widget.cc Tue Dec 06 15:45:27 2022 -0500 @@ -49,6 +49,7 @@ #include "files-dock-widget.h" #include "gui-preferences-fb.h" #include "gui-preferences-global.h" +#include "gui-settings.h" #include "octave-qobject.h" #include "octave-qtutils.h" #include "qt-interpreter-events.h" @@ -57,1123 +58,1120 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class FileTreeViewer : public QTreeView -{ -public: - - FileTreeViewer (QWidget *p) : QTreeView (p) { } - - ~FileTreeViewer (void) = default; - - void mousePressEvent (QMouseEvent *e) - { - if (e->button () != Qt::RightButton) - QTreeView::mousePressEvent (e); - } -}; - -// to have file renamed in the file tree, it has to be renamed in -// QFileSystemModel::setData. -// For the editor to behave correctly, some signals must be sent before -// and after the rename -class file_system_model : public QFileSystemModel -{ -public: - file_system_model (files_dock_widget *p) : QFileSystemModel (p) {} - - ~file_system_model () = default; - - bool setData (const QModelIndex &idx, const QVariant &value, - int role) override + class FileTreeViewer : public QTreeView { - if (!idx.isValid () || idx.column () != 0 || role != Qt::EditRole - || (flags (idx) & Qt::ItemIsEditable) == 0) - { - return false; - } + public: - QString new_name = value.toString (); - QString old_name = idx.data ().toString (); - if (new_name == old_name) - return true; - if (new_name.isEmpty () - || QDir::toNativeSeparators (new_name).contains (QDir::separator ())) - { - display_rename_failed_message (old_name, new_name); - return false; - } + FileTreeViewer (QWidget *p) : QTreeView (p) { } - auto parent_dir = QDir(filePath (parent (idx))); - - files_dock_widget *fdw = static_cast(parent()); - - fdw->file_remove_signal(parent_dir.filePath(old_name), parent_dir.filePath(new_name)); - - if (!parent_dir.rename (old_name, new_name)) - { - display_rename_failed_message (old_name, new_name); - fdw->file_renamed_signal(false); - return false; - } + ~FileTreeViewer (void) = default; - fdw->file_renamed_signal(true); - - emit fileRenamed(parent_dir.absolutePath(), old_name, new_name); - revert(); - - return true; - } - -private: - void display_rename_failed_message (const QString &old_name, - const QString &new_name) - { - const QString message = + void mousePressEvent (QMouseEvent *e) + { + if (e->button () != Qt::RightButton) + QTreeView::mousePressEvent (e); + } + }; - files_dock_widget::tr ("Could not rename file \"%1\" to \"%2\".") - .arg (old_name) - .arg (new_name); - QMessageBox::information (static_cast (parent ()), - QFileSystemModel::tr ("Invalid filename"), - message, QMessageBox::Ok); - } -}; - -// Delegate to improve ergonomy of file renaming by pre-selecting the text -// before the extension. -class RenameItemDelegate : public QStyledItemDelegate -{ -public: - RenameItemDelegate (QObject *parent = nullptr) - : QStyledItemDelegate{ parent } + // to have file renamed in the file tree, it has to be renamed in + // QFileSystemModel::setData. + // For the editor to behave correctly, some signals must be sent before + // and after the rename + class file_system_model : public QFileSystemModel { - } - - void setEditorData (QWidget *editor, - const QModelIndex &index) const override - { - QLineEdit *line_edit = qobject_cast (editor); - - if (!line_edit) - { - QStyledItemDelegate::setEditorData (editor, index); - return; - } - - QString filename = index.data (Qt::EditRole).toString (); + public: + file_system_model (files_dock_widget *p) : QFileSystemModel (p) {} - int select_len = filename.indexOf (QChar ('.')); - if (select_len == -1) - select_len = filename.size (); - - line_edit->setText (filename); - - // Qt calls QLineEdit::selectAll after this function is called, so to - // actually restrict the selection, we have to post the modification at - // the end of the event loop. - // QTimer allows this easily with 0 as timeout. - QTimer::singleShot (0, [=] () { - line_edit->setSelection (0, select_len); - }); - } -}; + ~file_system_model () = default; -files_dock_widget::files_dock_widget (QWidget *p, base_qobject& oct_qobj) - : octave_dock_widget ("FilesDockWidget", p, oct_qobj) -{ - set_title (tr ("File Browser")); - setToolTip (tr ("Browse your files")); - - m_sig_mapper = nullptr; - - m_columns_shown = QStringList (); - m_columns_shown.append (tr ("File size")); - m_columns_shown.append (tr ("File type")); - m_columns_shown.append (tr ("Date modified")); - m_columns_shown.append (tr ("Show hidden")); - m_columns_shown.append (tr ("Alternating row colors")); - - m_columns_shown_keys = QStringList (); - m_columns_shown_keys.append (fb_show_size.key); - m_columns_shown_keys.append (fb_show_type.key); - m_columns_shown_keys.append (fb_show_date.key); - m_columns_shown_keys.append (fb_show_hidden.key); - m_columns_shown_keys.append (fb_show_altcol.key); - - m_columns_shown_defs = QList (); - m_columns_shown_defs.append (fb_show_size.def); - m_columns_shown_defs.append (fb_show_type.def); - m_columns_shown_defs.append (fb_show_date.def); - m_columns_shown_defs.append (fb_show_hidden.def); - m_columns_shown_defs.append (fb_show_altcol.def); - - QWidget *container = new QWidget (this); + bool setData (const QModelIndex &idx, const QVariant &value, + int role) override + { + if (!idx.isValid () || idx.column () != 0 || role != Qt::EditRole + || (flags (idx) & Qt::ItemIsEditable) == 0) + { + return false; + } - setWidget (container); - - // Create a toolbar - m_navigation_tool_bar = new QToolBar ("", container); - m_navigation_tool_bar->setAllowedAreas (Qt::TopToolBarArea); - m_navigation_tool_bar->setMovable (false); - - m_current_directory = new QComboBox (m_navigation_tool_bar); - m_current_directory->setToolTip (tr ("Enter the path or filename")); - m_current_directory->setEditable (true); - m_current_directory->setMaxCount (MaxMRUDirs); - m_current_directory->setInsertPolicy (QComboBox::NoInsert); - m_current_directory->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon); - QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred); - m_current_directory->setSizePolicy (sizePol); - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - - QAction *directory_up_action - = new QAction (rmgr.icon ("folder-up", false, "go-up"), "", m_navigation_tool_bar); - directory_up_action->setToolTip (tr ("One directory up")); - - m_sync_browser_directory_action - = new QAction (rmgr.icon ("go-first"), tr ("Show Octave directory"), - m_navigation_tool_bar); - m_sync_browser_directory_action->setToolTip (tr ("Go to current Octave directory")); - m_sync_browser_directory_action->setEnabled (false); - - m_sync_octave_directory_action - = new QAction (rmgr.icon ("go-last"), tr ("Set Octave directory"), - m_navigation_tool_bar); - m_sync_octave_directory_action->setToolTip (tr ("Set Octave directory to current browser directory")); - m_sync_octave_directory_action->setEnabled (false); + QString new_name = value.toString (); + QString old_name = idx.data ().toString (); + if (new_name == old_name) + return true; + if (new_name.isEmpty () + || QDir::toNativeSeparators (new_name).contains (QDir::separator ())) + { + display_rename_failed_message (old_name, new_name); + return false; + } - QToolButton *popdown_button = new QToolButton (); - popdown_button->setToolTip (tr ("Actions on current directory")); - QMenu *popdown_menu = new QMenu (); - popdown_menu->addAction (rmgr.icon ("user-home"), - tr ("Show Home Directory"), this, - SLOT (popdownmenu_home (bool))); - popdown_menu->addAction (m_sync_browser_directory_action); - popdown_menu->addAction (m_sync_octave_directory_action); - popdown_button->setMenu (popdown_menu); - popdown_button->setPopupMode (QToolButton::InstantPopup); - popdown_button->setDefaultAction ( - new QAction (rmgr.icon ("folder-settings", false, "applications-system"), - "", m_navigation_tool_bar)); + auto parent_dir = QDir(filePath (parent (idx))); - popdown_menu->addSeparator (); - popdown_menu->addAction (rmgr.icon ("folder"), - tr ("Set Browser Directory..."), - this, &files_dock_widget::popdownmenu_search_dir); - popdown_menu->addSeparator (); - popdown_menu->addAction (rmgr.icon ("edit-find"), - tr ("Find Files..."), - this, &files_dock_widget::popdownmenu_findfiles); - popdown_menu->addSeparator (); - popdown_menu->addAction (rmgr.icon ("document-new"), - tr ("New File..."), - this, &files_dock_widget::popdownmenu_newfile); - popdown_menu->addAction (rmgr.icon ("folder-new"), - tr ("New Directory..."), - this, &files_dock_widget::popdownmenu_newdir); + files_dock_widget *fdw = static_cast(parent()); + + fdw->file_remove_signal(parent_dir.filePath(old_name), parent_dir.filePath(new_name)); - m_navigation_tool_bar->addWidget (m_current_directory); - m_navigation_tool_bar->addAction (directory_up_action); - m_navigation_tool_bar->addWidget (popdown_button); - - connect (directory_up_action, &QAction::triggered, - this, &files_dock_widget::change_directory_up); - connect (m_sync_octave_directory_action, &QAction::triggered, - this, &files_dock_widget::do_sync_octave_directory); - connect (m_sync_browser_directory_action, &QAction::triggered, - this, &files_dock_widget::do_sync_browser_directory); - - gui_settings *settings = rmgr.get_settings (); - // FIXME: what should happen if settings is 0? - - // Create the QFileSystemModel starting in the desired directory - QDir startup_dir; // take current dir + if (!parent_dir.rename (old_name, new_name)) + { + display_rename_failed_message (old_name, new_name); + fdw->file_renamed_signal(false); + return false; + } - if (settings->value (fb_restore_last_dir).toBool ()) - { - // restore last dir from previous session - QStringList last_dirs - = settings->value (fb_mru_list.key).toStringList (); - if (last_dirs.length () > 0) - startup_dir = QDir (last_dirs.at (0)); // last dir in previous session - } - else if (! settings->value (fb_startup_dir).toString ().isEmpty ()) - { - // do not restore but there is a startup dir configured - startup_dir = QDir (settings->value (fb_startup_dir.key).toString ()); - } + fdw->file_renamed_signal(true); - if (! startup_dir.exists ()) - { - // the configured startup dir does not exist, take actual one - startup_dir = QDir (); + emit fileRenamed(parent_dir.absolutePath(), old_name, new_name); + revert(); + + return true; } - m_file_system_model = new file_system_model (this); - m_file_system_model->setResolveSymlinks (false); - m_file_system_model->setFilter ( - QDir::System | QDir::NoDotAndDotDot | QDir::AllEntries); - QModelIndex rootPathIndex - = m_file_system_model->setRootPath (startup_dir.absolutePath ()); - - // Attach the model to the QTreeView and set the root index - m_file_tree_view = new FileTreeViewer (container); - m_file_tree_view->setSelectionMode (QAbstractItemView::ExtendedSelection); - m_file_tree_view->setModel (m_file_system_model); - m_file_tree_view->setRootIndex (rootPathIndex); - m_file_tree_view->setSortingEnabled (true); - m_file_tree_view->setAlternatingRowColors (true); - m_file_tree_view->setAnimated (true); - m_file_tree_view->setToolTip (tr ("Double-click to open file/folder, right click for alternatives")); - - // allow renaming directly in the tree view with - // m_file_tree_view->edit(index) - m_file_system_model->setReadOnly (false); - // delegate to improve rename ergonomy by pre-selecting text up to the - // extension - auto *rename_delegate = new RenameItemDelegate (this); - m_file_tree_view->setItemDelegateForColumn (0, rename_delegate); - // prevent the tree view to override Octave's double-click behavior - m_file_tree_view->setEditTriggers (QAbstractItemView::NoEditTriggers); - // create the rename action (that will be added to context menu) - // and associate to F2 key shortcut - m_rename_action = new QAction (tr ("Rename..."), this); - m_rename_action->setShortcut (Qt::Key_F2); - m_rename_action->setShortcutContext(Qt::WidgetWithChildrenShortcut); - connect (m_rename_action, &QAction::triggered, this, - &files_dock_widget::contextmenu_rename); - addAction(m_rename_action); - - // get sort column and order as well as column state (order and width) - - m_file_tree_view->sortByColumn - (settings->value (fb_sort_column).toInt (), - static_cast (settings->value (fb_sort_order).toUInt ())); - // FIXME: use value instead of static cast after - // dropping support of Qt 5.4 - - if (settings->contains (fb_column_state.key)) - m_file_tree_view->header ()->restoreState - (settings->value (fb_column_state.key).toByteArray ()); - - // Set header properties for sorting - m_file_tree_view->header ()->setSectionsClickable (true); - m_file_tree_view->header ()->setSectionsMovable (true); - m_file_tree_view->header ()->setSortIndicatorShown (true); - - QStringList mru_dirs = - settings->value (fb_mru_list.key).toStringList (); - m_current_directory->addItems (mru_dirs); - - m_current_directory->setEditText - (m_file_system_model->fileInfo (rootPathIndex). absoluteFilePath ()); - - connect (m_file_tree_view, &FileTreeViewer::activated, - this, &files_dock_widget::item_double_clicked); - - // add context menu to tree_view - m_file_tree_view->setContextMenuPolicy (Qt::CustomContextMenu); - connect (m_file_tree_view, &FileTreeViewer::customContextMenuRequested, - this, &files_dock_widget::contextmenu_requested); - - m_file_tree_view->header ()->setContextMenuPolicy (Qt::CustomContextMenu); - connect (m_file_tree_view->header (), - &QHeaderView::customContextMenuRequested, - this, &files_dock_widget::headercontextmenu_requested); - - // Layout the widgets vertically with the toolbar on top - QVBoxLayout *vbox_layout = new QVBoxLayout (); - vbox_layout->setSpacing (0); - vbox_layout->addWidget (m_navigation_tool_bar); - vbox_layout->addWidget (m_file_tree_view); - vbox_layout->setMargin (1); - - container->setLayout (vbox_layout); - - // FIXME: Add right-click contextual menus for copying, pasting, - // deleting files (and others). - - connect (m_current_directory->lineEdit (), &QLineEdit::returnPressed, - this, &files_dock_widget::accept_directory_line_edit); - - // FIXME: We could use - // - // connect (m_current_directory, - // QOverload::of (&QComboBox::activated), - // this, &files_dock_widget::set_current_directory); - // - // but referring to QComboBox::activated will generate deprecated - // function warnings from GCC. We could also use - // - // connect (m_current_directory, &QComboBox::textActivated, - // this, &files_dock_widget::set_current_directory); - // - // but the function textActivated was not introduced until Qt 5.14 - // so we'll need a feature test. - - connect (m_current_directory, SIGNAL (activated (const QString&)), - this, SLOT (set_current_directory (const QString&))); - - QCompleter *completer = new QCompleter (m_file_system_model, this); - m_current_directory->setCompleter (completer); - - setFocusProxy (m_current_directory); - - m_sync_octave_dir = true; // default, overwritten with notice_settings () - m_octave_dir = ""; - - if (! p) - make_window (); -} - -void files_dock_widget::save_settings (void) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (! settings) - return; - - int sort_column = m_file_tree_view->header ()->sortIndicatorSection (); - Qt::SortOrder sort_order = m_file_tree_view->header ()->sortIndicatorOrder (); - settings->setValue (fb_sort_column.key, sort_column); - settings->setValue (fb_sort_order.key, sort_order); - settings->setValue (fb_column_state.key, - m_file_tree_view->header ()->saveState ()); - - QStringList dirs; - for (int i=0; i< m_current_directory->count (); i++) + private: + void display_rename_failed_message (const QString &old_name, + const QString &new_name) { - dirs.append (m_current_directory->itemText (i)); - } - settings->setValue (fb_mru_list.key, dirs); - - settings->sync (); - - octave_dock_widget::save_settings (); - - if (m_sig_mapper) - delete m_sig_mapper; -} + const QString message = -void files_dock_widget::item_double_clicked (const QModelIndex& index) -{ - // Retrieve the file info associated with the model index. - QFileInfo fileInfo = m_file_system_model->fileInfo (index); - set_current_directory (fileInfo.absoluteFilePath ()); -} - -void files_dock_widget::set_current_directory (const QString& dir) -{ - display_directory (dir); -} - -void files_dock_widget::accept_directory_line_edit (void) -{ - display_directory (m_current_directory->currentText ()); -} - -void files_dock_widget::change_directory_up (void) -{ - QDir dir - = QDir (m_file_system_model->filePath (m_file_tree_view->rootIndex ())); - - dir.cdUp (); - display_directory (dir.absolutePath ()); -} - -void files_dock_widget::do_sync_octave_directory (void) -{ - QDir dir - = QDir (m_file_system_model->filePath (m_file_tree_view->rootIndex ())); - - emit displayed_directory_changed (dir.absolutePath ()); -} - -void files_dock_widget::do_sync_browser_directory (void) -{ - display_directory (m_octave_dir, false); // false: no sync of octave dir -} - -void files_dock_widget::update_octave_directory (const QString& dir) -{ - m_octave_dir = dir; - if (m_sync_octave_dir) - display_directory (m_octave_dir, false); // false: no sync of octave dir -} - -void files_dock_widget::display_directory (const QString& dir, - bool set_octave_dir) -{ - QFileInfo fileInfo (dir); - if (fileInfo.exists ()) - { - if (fileInfo.isDir ()) - { - m_file_tree_view->setRootIndex (m_file_system_model-> - index (fileInfo.absoluteFilePath ())); - m_file_system_model->setRootPath (fileInfo.absoluteFilePath ()); - if (m_sync_octave_dir && set_octave_dir) - process_set_current_dir (fileInfo.absoluteFilePath ()); - - // see if it's in the list, and if it is, - // remove it and then put at top of the list - int index - = m_current_directory->findText (fileInfo.absoluteFilePath ()); - if (index != -1) - { - m_current_directory->removeItem (index); - } - m_current_directory->insertItem (0, fileInfo.absoluteFilePath ()); - m_current_directory->setCurrentIndex (0); - } - else - { - QString abs_fname = fileInfo.absoluteFilePath (); + files_dock_widget::tr ("Could not rename file \"%1\" to \"%2\".") + .arg (old_name) + .arg (new_name); + QMessageBox::information (static_cast (parent ()), + QFileSystemModel::tr ("Invalid filename"), + message, QMessageBox::Ok); + } + }; - QString suffix = fileInfo.suffix ().toLower (); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - QString ext = settings->value (fb_txt_file_ext).toString (); -#if defined (HAVE_QT_SPLITBEHAVIOR_ENUM) - QStringList extensions = ext.split (";", Qt::SkipEmptyParts); -#else - QStringList extensions = ext.split (";", QString::SkipEmptyParts); -#endif - if (QFile::exists (abs_fname)) - { - if (extensions.contains (suffix)) - emit open_file (fileInfo.absoluteFilePath ()); - else - emit open_any_signal (abs_fname); - } - } - } -} - -void files_dock_widget::open_item_in_app (const QModelIndex& index) -{ - // Retrieve the file info associated with the model index. - QFileInfo fileInfo = m_file_system_model->fileInfo (index); - - QString file = fileInfo.absoluteFilePath (); - - QDesktopServices::openUrl (QUrl::fromLocalFile (file)); -} - -void files_dock_widget::toggle_header (int col) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - QString key = m_columns_shown_keys.at (col); - bool shown = settings->value (key, false).toBool (); - settings->setValue (key, ! shown); - settings->sync (); - - switch (col) + // Delegate to improve ergonomy of file renaming by pre-selecting the text + // before the extension. + class RenameItemDelegate : public QStyledItemDelegate + { + public: + RenameItemDelegate (QObject *parent = nullptr) + : QStyledItemDelegate{ parent } { - case 0: - case 1: - case 2: - // toggle column visibility - m_file_tree_view->setColumnHidden (col + 1, shown); - break; - case 3: - case 4: - // other actions depending on new settings - notice_settings (settings); - break; - } -} - -void files_dock_widget::headercontextmenu_requested (const QPoint& mpos) -{ - QMenu menu (this); - - if (m_sig_mapper) - delete m_sig_mapper; - m_sig_mapper = new QSignalMapper (this); - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - for (int i = 0; i < m_columns_shown.size (); i++) - { - QAction *action = menu.addAction (m_columns_shown.at (i), - m_sig_mapper, SLOT (map ())); - m_sig_mapper->setMapping (action, i); - action->setCheckable (true); - action->setChecked - (settings->value (m_columns_shown_keys.at (i), - m_columns_shown_defs.at (i)).toBool ()); } - // FIXME: We could use - // - // connect (&m_sig_mapper, QOverload::of (&QSignalMapper::mapped), - // this, &workspace_view::toggle_header); - // - // but referring to QSignalMapper::mapped will generate deprecated - // function warnings from GCC. We could also use - // - // connect (&m_sig_mapper, &QSignalMapper::mappedInt, - // this, &workspace_view::toggle_header); - // - // but the function mappedInt was not introduced until Qt 5.15 so - // we'll need a feature test. - - connect (m_sig_mapper, SIGNAL (mapped (int)), - this, SLOT (toggle_header (int))); - - menu.exec (m_file_tree_view->mapToGlobal (mpos)); -} - -void files_dock_widget::contextmenu_requested (const QPoint& mpos) -{ - - QMenu menu (this); + void setEditorData (QWidget *editor, + const QModelIndex &index) const override + { + QLineEdit *line_edit = qobject_cast (editor); - QModelIndex index = m_file_tree_view->indexAt (mpos); - - if (index.isValid ()) - { - QFileInfo info = m_file_system_model->fileInfo (index); - - QItemSelectionModel *m = m_file_tree_view->selectionModel (); - QModelIndexList sel = m->selectedRows (); - - // check if item at mouse position is seleccted - if (! sel.contains (index)) - { - // is not selected -> clear actual selection and select this item - m->setCurrentIndex (index, - QItemSelectionModel::Clear - | QItemSelectionModel::Select - | QItemSelectionModel::Rows); - } - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - - // construct the context menu depending on item - menu.addAction (rmgr.icon ("document-open"), tr ("Open"), - this, &files_dock_widget::contextmenu_open); - - if (info.isDir ()) + if (!line_edit) { - menu.addAction (tr ("Open in System File Explorer"), - this, &files_dock_widget::contextmenu_open_in_app); - } - - if (info.isFile ()) - menu.addAction (tr ("Open in Text Editor"), - this, &files_dock_widget::contextmenu_open_in_editor); - - menu.addAction (tr ("Copy Selection to Clipboard"), - this, &files_dock_widget::contextmenu_copy_selection); - - if (info.isFile () && info.suffix () == "m") - menu.addAction (rmgr.icon ("media-playback-start"), tr ("Run"), - this, &files_dock_widget::contextmenu_run); - - if (info.isFile ()) - menu.addAction (tr ("Load Data"), - this, &files_dock_widget::contextmenu_load); - - if (info.isDir ()) - { - menu.addSeparator (); - menu.addAction (rmgr.icon ("go-first"), tr ("Set Current Directory"), - this, &files_dock_widget::contextmenu_setcurrentdir); - - QMenu *add_path_menu = menu.addMenu (tr ("Add to Path")); - - add_path_menu->addAction (tr ("Selected Directories"), - this, [=] (bool checked) { contextmenu_add_to_path (checked); }); - add_path_menu->addAction (tr ("Selected Directories and Subdirectories"), - this, &files_dock_widget::contextmenu_add_to_path_subdirs); - - QMenu *rm_path_menu = menu.addMenu (tr ("Remove from Path")); - - rm_path_menu->addAction (tr ("Selected Directories"), - this, &files_dock_widget::contextmenu_rm_from_path); - rm_path_menu->addAction (tr ("Selected Directories and Subdirectories"), - this, &files_dock_widget::contextmenu_rm_from_path_subdirs); - - menu.addSeparator (); - - menu.addAction (rmgr.icon ("edit-find"), tr ("Find Files..."), - this, &files_dock_widget::contextmenu_findfiles); - } - - menu.addSeparator (); - menu.addAction (m_rename_action); - menu.addAction (rmgr.icon ("edit-delete"), tr ("Delete..."), - this, &files_dock_widget::contextmenu_delete); - - if (info.isDir ()) - { - menu.addSeparator (); - menu.addAction (rmgr.icon ("document-new"), tr ("New File..."), - this, &files_dock_widget::contextmenu_newfile); - menu.addAction (rmgr.icon ("folder-new"), tr ("New Directory..."), - this, &files_dock_widget::contextmenu_newdir); + QStyledItemDelegate::setEditorData (editor, index); + return; } - // show the menu - menu.exec (m_file_tree_view->mapToGlobal (mpos)); + QString filename = index.data (Qt::EditRole).toString (); - } -} + int select_len = filename.indexOf (QChar ('.')); + if (select_len == -1) + select_len = filename.size (); + + line_edit->setText (filename); -void files_dock_widget::contextmenu_open (bool) -{ + // Qt calls QLineEdit::selectAll after this function is called, so to + // actually restrict the selection, we have to post the modification at + // the end of the event loop. + // QTimer allows this easily with 0 as timeout. + QTimer::singleShot (0, [=] () { + line_edit->setSelection (0, select_len); + }); + } + }; - QItemSelectionModel *m = m_file_tree_view->selectionModel (); - QModelIndexList rows = m->selectedRows (); + files_dock_widget::files_dock_widget (QWidget *p, base_qobject& oct_qobj) + : octave_dock_widget ("FilesDockWidget", p, oct_qobj) + { + set_title (tr ("File Browser")); + setToolTip (tr ("Browse your files")); + + m_sig_mapper = nullptr; + + m_columns_shown = QStringList (); + m_columns_shown.append (tr ("File size")); + m_columns_shown.append (tr ("File type")); + m_columns_shown.append (tr ("Date modified")); + m_columns_shown.append (tr ("Show hidden")); + m_columns_shown.append (tr ("Alternating row colors")); - for (auto it = rows.begin (); it != rows.end (); it++) - { - QFileInfo file = m_file_system_model->fileInfo (*it); - if (file.exists ()) - display_directory (file.absoluteFilePath ()); - } -} + m_columns_shown_keys = QStringList (); + m_columns_shown_keys.append (fb_show_size.key); + m_columns_shown_keys.append (fb_show_type.key); + m_columns_shown_keys.append (fb_show_date.key); + m_columns_shown_keys.append (fb_show_hidden.key); + m_columns_shown_keys.append (fb_show_altcol.key); + + m_columns_shown_defs = QList (); + m_columns_shown_defs.append (fb_show_size.def); + m_columns_shown_defs.append (fb_show_type.def); + m_columns_shown_defs.append (fb_show_date.def); + m_columns_shown_defs.append (fb_show_hidden.def); + m_columns_shown_defs.append (fb_show_altcol.def); + + QWidget *container = new QWidget (this); + + setWidget (container); -void files_dock_widget::contextmenu_open_in_editor (bool) -{ + // Create a toolbar + m_navigation_tool_bar = new QToolBar ("", container); + m_navigation_tool_bar->setAllowedAreas (Qt::TopToolBarArea); + m_navigation_tool_bar->setMovable (false); - QItemSelectionModel *m = m_file_tree_view->selectionModel (); - QModelIndexList rows = m->selectedRows (); + m_current_directory = new QComboBox (m_navigation_tool_bar); + m_current_directory->setToolTip (tr ("Enter the path or filename")); + m_current_directory->setEditable (true); + m_current_directory->setMaxCount (MaxMRUDirs); + m_current_directory->setInsertPolicy (QComboBox::NoInsert); + m_current_directory->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon); + QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred); + m_current_directory->setSizePolicy (sizePol); + + gui_settings settings; + + QAction *directory_up_action + = new QAction (settings.icon ("folder-up", false, "go-up"), "", + m_navigation_tool_bar); + directory_up_action->setToolTip (tr ("One directory up")); + + m_sync_browser_directory_action + = new QAction (settings.icon ("go-first"), tr ("Show Octave directory"), + m_navigation_tool_bar); + m_sync_browser_directory_action->setToolTip (tr ("Go to current Octave directory")); + m_sync_browser_directory_action->setEnabled (false); - for (auto it = rows.begin (); it != rows.end (); it++) - { - QFileInfo file = m_file_system_model->fileInfo (*it); - if (file.exists ()) - emit open_file (file.absoluteFilePath ()); - } -} + m_sync_octave_directory_action + = new QAction (settings.icon ("go-last"), tr ("Set Octave directory"), + m_navigation_tool_bar); + m_sync_octave_directory_action->setToolTip (tr ("Set Octave directory to current browser directory")); + m_sync_octave_directory_action->setEnabled (false); -void files_dock_widget::contextmenu_open_in_app (bool) -{ - QItemSelectionModel *m = m_file_tree_view->selectionModel (); - QModelIndexList rows = m->selectedRows (); + QToolButton *popdown_button = new QToolButton (); + popdown_button->setToolTip (tr ("Actions on current directory")); + QMenu *popdown_menu = new QMenu (); + popdown_menu->addAction (settings.icon ("user-home"), + tr ("Show Home Directory"), this, + SLOT (popdownmenu_home (bool))); + popdown_menu->addAction (m_sync_browser_directory_action); + popdown_menu->addAction (m_sync_octave_directory_action); + popdown_button->setMenu (popdown_menu); + popdown_button->setPopupMode (QToolButton::InstantPopup); + popdown_button->setDefaultAction ( + new QAction (settings.icon ("folder-settings", false, + "applications-system"), + "", m_navigation_tool_bar)); - for (auto it = rows.begin (); it != rows.end (); it++) - open_item_in_app (*it); -} + popdown_menu->addSeparator (); + popdown_menu->addAction (settings.icon ("folder"), + tr ("Set Browser Directory..."), + this, &files_dock_widget::popdownmenu_search_dir); + popdown_menu->addSeparator (); + popdown_menu->addAction (settings.icon ("edit-find"), + tr ("Find Files..."), + this, &files_dock_widget::popdownmenu_findfiles); + popdown_menu->addSeparator (); + popdown_menu->addAction (settings.icon ("document-new"), + tr ("New File..."), + this, &files_dock_widget::popdownmenu_newfile); + popdown_menu->addAction (settings.icon ("folder-new"), + tr ("New Directory..."), + this, &files_dock_widget::popdownmenu_newdir); + + m_navigation_tool_bar->addWidget (m_current_directory); + m_navigation_tool_bar->addAction (directory_up_action); + m_navigation_tool_bar->addWidget (popdown_button); -void files_dock_widget::contextmenu_copy_selection (bool) -{ - QItemSelectionModel *m = m_file_tree_view->selectionModel (); - QModelIndexList rows = m->selectedRows (); + connect (directory_up_action, &QAction::triggered, + this, &files_dock_widget::change_directory_up); + connect (m_sync_octave_directory_action, &QAction::triggered, + this, &files_dock_widget::do_sync_octave_directory); + connect (m_sync_browser_directory_action, &QAction::triggered, + this, &files_dock_widget::do_sync_browser_directory); - QStringList selection; + // Create the QFileSystemModel starting in the desired directory + QDir startup_dir; // take current dir - for (auto it = rows.begin (); it != rows.end (); it++) - { - QFileInfo info = m_file_system_model->fileInfo (*it); + if (settings.value (fb_restore_last_dir).toBool ()) + { + // restore last dir from previous session + QStringList last_dirs + = settings.value (fb_mru_list.key).toStringList (); + if (last_dirs.length () > 0) + startup_dir = QDir (last_dirs.at (0)); // last dir in previous session + } + else if (! settings.value (fb_startup_dir).toString ().isEmpty ()) + { + // do not restore but there is a startup dir configured + startup_dir = QDir (settings.value (fb_startup_dir.key).toString ()); + } - selection << info.fileName (); - } + if (! startup_dir.exists ()) + { + // the configured startup dir does not exist, take actual one + startup_dir = QDir (); + } - QClipboard *clipboard = QApplication::clipboard (); + m_file_system_model = new file_system_model (this); + m_file_system_model->setResolveSymlinks (false); + m_file_system_model->setFilter ( + QDir::System | QDir::NoDotAndDotDot | QDir::AllEntries); + QModelIndex rootPathIndex + = m_file_system_model->setRootPath (startup_dir.absolutePath ()); - clipboard->setText (selection.join ("\n")); -} + // Attach the model to the QTreeView and set the root index + m_file_tree_view = new FileTreeViewer (container); + m_file_tree_view->setSelectionMode (QAbstractItemView::ExtendedSelection); + m_file_tree_view->setModel (m_file_system_model); + m_file_tree_view->setRootIndex (rootPathIndex); + m_file_tree_view->setSortingEnabled (true); + m_file_tree_view->setAlternatingRowColors (true); + m_file_tree_view->setAnimated (true); + m_file_tree_view->setToolTip (tr ("Double-click to open file/folder, right click for alternatives")); -void files_dock_widget::contextmenu_load (bool) -{ - QItemSelectionModel *m = m_file_tree_view->selectionModel (); - QModelIndexList rows = m->selectedRows (); + // allow renaming directly in the tree view with + // m_file_tree_view->edit(index) + m_file_system_model->setReadOnly (false); + // delegate to improve rename ergonomy by pre-selecting text up to the + // extension + auto *rename_delegate = new RenameItemDelegate (this); + m_file_tree_view->setItemDelegateForColumn (0, rename_delegate); + // prevent the tree view to override Octave's double-click behavior + m_file_tree_view->setEditTriggers (QAbstractItemView::NoEditTriggers); + // create the rename action (that will be added to context menu) + // and associate to F2 key shortcut + m_rename_action = new QAction (tr ("Rename..."), this); + m_rename_action->setShortcut (Qt::Key_F2); + m_rename_action->setShortcutContext(Qt::WidgetWithChildrenShortcut); + connect (m_rename_action, &QAction::triggered, this, + &files_dock_widget::contextmenu_rename); + addAction(m_rename_action); + + // get sort column and order as well as column state (order and width) - if (rows.size () > 0) - { - QModelIndex index = rows[0]; + m_file_tree_view->sortByColumn + (settings.value (fb_sort_column).toInt (), + static_cast (settings.value (fb_sort_order).toUInt ())); + // FIXME: use value instead of static cast after + // dropping support of Qt 5.4 + + if (settings.contains (fb_column_state.key)) + m_file_tree_view->header ()->restoreState + (settings.value (fb_column_state.key).toByteArray ()); - QFileInfo info = m_file_system_model->fileInfo (index); + // Set header properties for sorting + m_file_tree_view->header ()->setSectionsClickable (true); + m_file_tree_view->header ()->setSectionsMovable (true); + m_file_tree_view->header ()->setSortIndicatorShown (true); + + QStringList mru_dirs = + settings.value (fb_mru_list.key).toStringList (); + m_current_directory->addItems (mru_dirs); + + m_current_directory->setEditText + (m_file_system_model->fileInfo (rootPathIndex). absoluteFilePath ()); + + connect (m_file_tree_view, &FileTreeViewer::activated, + this, &files_dock_widget::item_double_clicked); - emit load_file_signal (info.fileName ()); - } -} + // add context menu to tree_view + m_file_tree_view->setContextMenuPolicy (Qt::CustomContextMenu); + connect (m_file_tree_view, &FileTreeViewer::customContextMenuRequested, + this, &files_dock_widget::contextmenu_requested); + + m_file_tree_view->header ()->setContextMenuPolicy (Qt::CustomContextMenu); + connect (m_file_tree_view->header (), + &QHeaderView::customContextMenuRequested, + this, &files_dock_widget::headercontextmenu_requested); -void files_dock_widget::contextmenu_run (bool) -{ - QItemSelectionModel *m = m_file_tree_view->selectionModel (); - QModelIndexList rows = m->selectedRows (); + // Layout the widgets vertically with the toolbar on top + QVBoxLayout *vbox_layout = new QVBoxLayout (); + vbox_layout->setSpacing (0); + vbox_layout->addWidget (m_navigation_tool_bar); + vbox_layout->addWidget (m_file_tree_view); + vbox_layout->setMargin (1); + + container->setLayout (vbox_layout); + + // FIXME: Add right-click contextual menus for copying, pasting, + // deleting files (and others). + + connect (m_current_directory->lineEdit (), &QLineEdit::returnPressed, + this, &files_dock_widget::accept_directory_line_edit); - if (rows.size () > 0) - { - QModelIndex index = rows[0]; + // FIXME: We could use + // + // connect (m_current_directory, + // QOverload::of (&QComboBox::activated), + // this, &files_dock_widget::set_current_directory); + // + // but referring to QComboBox::activated will generate deprecated + // function warnings from GCC. We could also use + // + // connect (m_current_directory, &QComboBox::textActivated, + // this, &files_dock_widget::set_current_directory); + // + // but the function textActivated was not introduced until Qt 5.14 + // so we'll need a feature test. - QFileInfo info = m_file_system_model->fileInfo (index); - emit run_file_signal (info); - } -} + connect (m_current_directory, SIGNAL (activated (const QString&)), + this, SLOT (set_current_directory (const QString&))); + + QCompleter *completer = new QCompleter (m_file_system_model, this); + m_current_directory->setCompleter (completer); + + setFocusProxy (m_current_directory); + + m_sync_octave_dir = true; // default, overwritten with notice_settings () + m_octave_dir = ""; -void files_dock_widget::contextmenu_rename (bool) -{ - QItemSelectionModel *m = m_file_tree_view->selectionModel (); - QModelIndexList rows = m->selectedRows (); - if (rows.size () > 0) - { - QModelIndex index = rows[0]; - m_file_tree_view->edit(index); - } -} + if (! p) + make_window (); + } + + void files_dock_widget::save_settings (void) + { + gui_settings settings; + + int sort_column = m_file_tree_view->header ()->sortIndicatorSection (); + Qt::SortOrder sort_order = m_file_tree_view->header ()->sortIndicatorOrder (); + settings.setValue (fb_sort_column.key, sort_column); + settings.setValue (fb_sort_order.key, sort_order); + settings.setValue (fb_column_state.key, + m_file_tree_view->header ()->saveState ()); + + QStringList dirs; + for (int i=0; i< m_current_directory->count (); i++) + { + dirs.append (m_current_directory->itemText (i)); + } + settings.setValue (fb_mru_list.key, dirs); -void files_dock_widget::contextmenu_delete (bool) -{ - QItemSelectionModel *m = m_file_tree_view->selectionModel (); - QModelIndexList rows = m->selectedRows (); + settings.sync (); + + octave_dock_widget::save_settings (); + + if (m_sig_mapper) + delete m_sig_mapper; + } + + void files_dock_widget::item_double_clicked (const QModelIndex& index) + { + // Retrieve the file info associated with the model index. + QFileInfo fileInfo = m_file_system_model->fileInfo (index); + set_current_directory (fileInfo.absoluteFilePath ()); + } + + void files_dock_widget::set_current_directory (const QString& dir) + { + display_directory (dir); + } + + void files_dock_widget::accept_directory_line_edit (void) + { + display_directory (m_current_directory->currentText ()); + } - int file_cnt = rows.size (); - bool multiple_files = (file_cnt > 1); + void files_dock_widget::change_directory_up (void) + { + QDir dir + = QDir (m_file_system_model->filePath (m_file_tree_view->rootIndex ())); + + dir.cdUp (); + display_directory (dir.absolutePath ()); + } - for (auto it = rows.begin (); it != rows.end (); it++) - { - QModelIndex index = *it; + void files_dock_widget::do_sync_octave_directory (void) + { + QDir dir + = QDir (m_file_system_model->filePath (m_file_tree_view->rootIndex ())); - QFileInfo info = m_file_system_model->fileInfo (index); + emit displayed_directory_changed (dir.absolutePath ()); + } + + void files_dock_widget::do_sync_browser_directory (void) + { + display_directory (m_octave_dir, false); // false: no sync of octave dir + } - QMessageBox::StandardButton dlg_answer; - if (multiple_files) - if (it == rows.begin ()) + void files_dock_widget::update_octave_directory (const QString& dir) + { + m_octave_dir = dir; + if (m_sync_octave_dir) + display_directory (m_octave_dir, false); // false: no sync of octave dir + } + + void files_dock_widget::display_directory (const QString& dir, + bool set_octave_dir) + { + QFileInfo fileInfo (dir); + if (fileInfo.exists ()) + { + if (fileInfo.isDir ()) { - dlg_answer = QMessageBox::question (this, - tr ("Delete file/directory"), - tr ("Are you sure you want to delete all %1 selected files?\n").arg (file_cnt), - QMessageBox::Yes | QMessageBox::No); - if (dlg_answer != QMessageBox::Yes) - return; + m_file_tree_view->setRootIndex (m_file_system_model-> + index (fileInfo.absoluteFilePath ())); + m_file_system_model->setRootPath (fileInfo.absoluteFilePath ()); + if (m_sync_octave_dir && set_octave_dir) + process_set_current_dir (fileInfo.absoluteFilePath ()); + + // see if it's in the list, and if it is, + // remove it and then put at top of the list + int index + = m_current_directory->findText (fileInfo.absoluteFilePath ()); + if (index != -1) + { + m_current_directory->removeItem (index); + } + m_current_directory->insertItem (0, fileInfo.absoluteFilePath ()); + m_current_directory->setCurrentIndex (0); } else - dlg_answer = QMessageBox::Yes; - else - { - dlg_answer = QMessageBox::question (this, - tr ("Delete file/directory"), - tr ("Are you sure you want to delete\n") - + info.filePath (), - QMessageBox::Yes | QMessageBox::No); - } + { + QString abs_fname = fileInfo.absoluteFilePath (); + + QString suffix = fileInfo.suffix ().toLower (); + + gui_settings settings; + + QString ext = settings.value (fb_txt_file_ext).toString (); +#if defined (HAVE_QT_SPLITBEHAVIOR_ENUM) + QStringList extensions = ext.split (";", Qt::SkipEmptyParts); +#else + QStringList extensions = ext.split (";", QString::SkipEmptyParts); +#endif + if (QFile::exists (abs_fname)) + { + if (extensions.contains (suffix)) + emit open_file (fileInfo.absoluteFilePath ()); + else + emit open_any_signal (abs_fname); + } + } + } + } + + void files_dock_widget::open_item_in_app (const QModelIndex& index) + { + // Retrieve the file info associated with the model index. + QFileInfo fileInfo = m_file_system_model->fileInfo (index); + + QString file = fileInfo.absoluteFilePath (); + + QDesktopServices::openUrl (QUrl::fromLocalFile (file)); + } + + void files_dock_widget::toggle_header (int col) + { + gui_settings settings; + + QString key = m_columns_shown_keys.at (col); + bool shown = settings.value (key, false).toBool (); + settings.setValue (key, ! shown); + settings.sync (); + + switch (col) + { + case 0: + case 1: + case 2: + // toggle column visibility + m_file_tree_view->setColumnHidden (col + 1, shown); + break; + case 3: + case 4: + // other actions depending on new settings + notice_settings (); + break; + } + } + + void files_dock_widget::headercontextmenu_requested (const QPoint& mpos) + { + QMenu menu (this); + + if (m_sig_mapper) + delete m_sig_mapper; + m_sig_mapper = new QSignalMapper (this); + + gui_settings settings; + + for (int i = 0; i < m_columns_shown.size (); i++) + { + QAction *action = menu.addAction (m_columns_shown.at (i), + m_sig_mapper, SLOT (map ())); + m_sig_mapper->setMapping (action, i); + action->setCheckable (true); + action->setChecked + (settings.value (m_columns_shown_keys.at (i), + m_columns_shown_defs.at (i)).toBool ()); + } + + // FIXME: We could use + // + // connect (&m_sig_mapper, QOverload::of (&QSignalMapper::mapped), + // this, &workspace_view::toggle_header); + // + // but referring to QSignalMapper::mapped will generate deprecated + // function warnings from GCC. We could also use + // + // connect (&m_sig_mapper, &QSignalMapper::mappedInt, + // this, &workspace_view::toggle_header); + // + // but the function mappedInt was not introduced until Qt 5.15 so + // we'll need a feature test. + + connect (m_sig_mapper, SIGNAL (mapped (int)), + this, SLOT (toggle_header (int))); + + menu.exec (m_file_tree_view->mapToGlobal (mpos)); + } + + void files_dock_widget::contextmenu_requested (const QPoint& mpos) + { + + QMenu menu (this); + + QModelIndex index = m_file_tree_view->indexAt (mpos); + + if (index.isValid ()) + { + QFileInfo info = m_file_system_model->fileInfo (index); + + QItemSelectionModel *m = m_file_tree_view->selectionModel (); + QModelIndexList sel = m->selectedRows (); + + // check if item at mouse position is seleccted + if (! sel.contains (index)) + { + // is not selected -> clear actual selection and select this item + m->setCurrentIndex (index, + QItemSelectionModel::Clear + | QItemSelectionModel::Select + | QItemSelectionModel::Rows); + } + + gui_settings settings; + + // construct the context menu depending on item + menu.addAction (settings.icon ("document-open"), tr ("Open"), + this, &files_dock_widget::contextmenu_open); + + if (info.isDir ()) + { + menu.addAction (tr ("Open in System File Explorer"), + this, &files_dock_widget::contextmenu_open_in_app); + } + + if (info.isFile ()) + menu.addAction (tr ("Open in Text Editor"), + this, &files_dock_widget::contextmenu_open_in_editor); + + menu.addAction (tr ("Copy Selection to Clipboard"), + this, &files_dock_widget::contextmenu_copy_selection); + + if (info.isFile () && info.suffix () == "m") + menu.addAction (settings.icon ("media-playback-start"), tr ("Run"), + this, &files_dock_widget::contextmenu_run); + + if (info.isFile ()) + menu.addAction (tr ("Load Data"), + this, &files_dock_widget::contextmenu_load); + + if (info.isDir ()) + { + menu.addSeparator (); + menu.addAction (settings.icon ("go-first"), tr ("Set Current Directory"), + this, &files_dock_widget::contextmenu_setcurrentdir); + + QMenu *add_path_menu = menu.addMenu (tr ("Add to Path")); - if (dlg_answer == QMessageBox::Yes) - { - if (info.isDir ()) + add_path_menu->addAction (tr ("Selected Directories"), + this, [=] (bool checked) { contextmenu_add_to_path (checked); }); + add_path_menu->addAction (tr ("Selected Directories and Subdirectories"), + this, &files_dock_widget::contextmenu_add_to_path_subdirs); + + QMenu *rm_path_menu = menu.addMenu (tr ("Remove from Path")); + + rm_path_menu->addAction (tr ("Selected Directories"), + this, &files_dock_widget::contextmenu_rm_from_path); + rm_path_menu->addAction (tr ("Selected Directories and Subdirectories"), + this, &files_dock_widget::contextmenu_rm_from_path_subdirs); + + menu.addSeparator (); + + menu.addAction (settings.icon ("edit-find"), tr ("Find Files..."), + this, &files_dock_widget::contextmenu_findfiles); + } + + menu.addSeparator (); + menu.addAction (m_rename_action); + menu.addAction (settings.icon ("edit-delete"), tr ("Delete..."), + this, &files_dock_widget::contextmenu_delete); + + if (info.isDir ()) + { + menu.addSeparator (); + menu.addAction (settings.icon ("document-new"), tr ("New File..."), + this, &files_dock_widget::contextmenu_newfile); + menu.addAction (settings.icon ("folder-new"), tr ("New Directory..."), + this, &files_dock_widget::contextmenu_newdir); + } + + // show the menu + menu.exec (m_file_tree_view->mapToGlobal (mpos)); + + } + } + + void files_dock_widget::contextmenu_open (bool) + { + + QItemSelectionModel *m = m_file_tree_view->selectionModel (); + QModelIndexList rows = m->selectedRows (); + + for (auto it = rows.begin (); it != rows.end (); it++) + { + QFileInfo file = m_file_system_model->fileInfo (*it); + if (file.exists ()) + display_directory (file.absoluteFilePath ()); + } + } + + void files_dock_widget::contextmenu_open_in_editor (bool) + { + + QItemSelectionModel *m = m_file_tree_view->selectionModel (); + QModelIndexList rows = m->selectedRows (); + + for (auto it = rows.begin (); it != rows.end (); it++) + { + QFileInfo file = m_file_system_model->fileInfo (*it); + if (file.exists ()) + emit open_file (file.absoluteFilePath ()); + } + } + + void files_dock_widget::contextmenu_open_in_app (bool) + { + QItemSelectionModel *m = m_file_tree_view->selectionModel (); + QModelIndexList rows = m->selectedRows (); + + for (auto it = rows.begin (); it != rows.end (); it++) + open_item_in_app (*it); + } + + void files_dock_widget::contextmenu_copy_selection (bool) + { + QItemSelectionModel *m = m_file_tree_view->selectionModel (); + QModelIndexList rows = m->selectedRows (); + + QStringList selection; + + for (auto it = rows.begin (); it != rows.end (); it++) + { + QFileInfo info = m_file_system_model->fileInfo (*it); + + selection << info.fileName (); + } + + QClipboard *clipboard = QApplication::clipboard (); + + clipboard->setText (selection.join ("\n")); + } + + void files_dock_widget::contextmenu_load (bool) + { + QItemSelectionModel *m = m_file_tree_view->selectionModel (); + QModelIndexList rows = m->selectedRows (); + + if (rows.size () > 0) + { + QModelIndex index = rows[0]; + + QFileInfo info = m_file_system_model->fileInfo (index); + + emit load_file_signal (info.fileName ()); + } + } + + void files_dock_widget::contextmenu_run (bool) + { + QItemSelectionModel *m = m_file_tree_view->selectionModel (); + QModelIndexList rows = m->selectedRows (); + + if (rows.size () > 0) + { + QModelIndex index = rows[0]; + + QFileInfo info = m_file_system_model->fileInfo (index); + emit run_file_signal (info); + } + } + + void files_dock_widget::contextmenu_rename (bool) + { + QItemSelectionModel *m = m_file_tree_view->selectionModel (); + QModelIndexList rows = m->selectedRows (); + if (rows.size () > 0) + { + QModelIndex index = rows[0]; + m_file_tree_view->edit(index); + } + } + + void files_dock_widget::contextmenu_delete (bool) + { + QItemSelectionModel *m = m_file_tree_view->selectionModel (); + QModelIndexList rows = m->selectedRows (); + + int file_cnt = rows.size (); + bool multiple_files = (file_cnt > 1); + + for (auto it = rows.begin (); it != rows.end (); it++) + { + QModelIndex index = *it; + + QFileInfo info = m_file_system_model->fileInfo (index); + + QMessageBox::StandardButton dlg_answer; + if (multiple_files) + if (it == rows.begin ()) { - // see if directory is empty - QDir path (info.absoluteFilePath ()); - QList fileLst = path.entryInfoList ( - QDir::Hidden | QDir::AllEntries | - QDir::NoDotAndDotDot | QDir::System); - - if (fileLst.count () != 0) - QMessageBox::warning (this, tr ("Delete file/directory"), - tr ("Can not delete a directory that is not empty")); - else - m_file_system_model->rmdir (index); + dlg_answer = QMessageBox::question (this, + tr ("Delete file/directory"), + tr ("Are you sure you want to delete all %1 selected files?\n").arg (file_cnt), + QMessageBox::Yes | QMessageBox::No); + if (dlg_answer != QMessageBox::Yes) + return; } else - { - // Close the file in the editor if open - emit file_remove_signal (info.filePath (), QString ()); - // Remove the file. - bool st = m_file_system_model->remove (index); - if (! st) - { - QMessageBox::warning (this, tr ("Deletion error"), - tr ("Could not delete file \"%1\"."). - arg (info.filePath ())); - // Reload the old file - } - emit file_renamed_signal (st); - } - - m_file_system_model->revert (); + dlg_answer = QMessageBox::Yes; + else + { + dlg_answer = QMessageBox::question (this, + tr ("Delete file/directory"), + tr ("Are you sure you want to delete\n") + + info.filePath (), + QMessageBox::Yes | QMessageBox::No); + } - } - } -} - -// Get the currently selected files/dirs and return their file info -// in a list. -QList files_dock_widget::get_selected_items_info (bool dir) -{ - QItemSelectionModel *m = m_file_tree_view->selectionModel (); - QModelIndexList rows = m->selectedRows (); - - QList infos; - - for (auto it = rows.begin (); it != rows.end (); it++) - { - QModelIndex index = *it; - - QFileInfo info = m_file_system_model->fileInfo (index); + if (dlg_answer == QMessageBox::Yes) + { + if (info.isDir ()) + { + // see if directory is empty + QDir path (info.absoluteFilePath ()); + QList fileLst = path.entryInfoList ( + QDir::Hidden | QDir::AllEntries | + QDir::NoDotAndDotDot | QDir::System); - if (info.exists () && - ((dir & info.isDir ()) || (! dir && info.isFile ()))) - infos.append (info); - } - - return infos; -} + if (fileLst.count () != 0) + QMessageBox::warning (this, tr ("Delete file/directory"), + tr ("Can not delete a directory that is not empty")); + else + m_file_system_model->rmdir (index); + } + else + { + // Close the file in the editor if open + emit file_remove_signal (info.filePath (), QString ()); + // Remove the file. + bool st = m_file_system_model->remove (index); + if (! st) + { + QMessageBox::warning (this, tr ("Deletion error"), + tr ("Could not delete file \"%1\"."). + arg (info.filePath ())); + // Reload the old file + } + emit file_renamed_signal (st); + } -void files_dock_widget::contextmenu_newfile (bool) -{ - QItemSelectionModel *m = m_file_tree_view->selectionModel (); - QModelIndexList rows = m->selectedRows (); + m_file_system_model->revert (); - if (rows.size () > 0) - { - QModelIndex index = rows[0]; + } + } + } - QFileInfo info = m_file_system_model->fileInfo (index); - QString parent_dir = info.filePath (); + // Get the currently selected files/dirs and return their file info + // in a list. + QList files_dock_widget::get_selected_items_info (bool dir) + { + QItemSelectionModel *m = m_file_tree_view->selectionModel (); + QModelIndexList rows = m->selectedRows (); - process_new_file (parent_dir); - } -} + QList infos; + + for (auto it = rows.begin (); it != rows.end (); it++) + { + QModelIndex index = *it; + + QFileInfo info = m_file_system_model->fileInfo (index); -void files_dock_widget::contextmenu_newdir (bool) -{ - QItemSelectionModel *m = m_file_tree_view->selectionModel (); - QModelIndexList rows = m->selectedRows (); + if (info.exists () && + ((dir & info.isDir ()) || (! dir && info.isFile ()))) + infos.append (info); + } + + return infos; + } - if (rows.size () > 0) - { - QModelIndex index = rows[0]; + void files_dock_widget::contextmenu_newfile (bool) + { + QItemSelectionModel *m = m_file_tree_view->selectionModel (); + QModelIndexList rows = m->selectedRows (); - QFileInfo info = m_file_system_model->fileInfo (index); - QString parent_dir = info.filePath (); + if (rows.size () > 0) + { + QModelIndex index = rows[0]; - process_new_dir (parent_dir); - } -} + QFileInfo info = m_file_system_model->fileInfo (index); + QString parent_dir = info.filePath (); -void files_dock_widget::contextmenu_setcurrentdir (bool) -{ - QList infos = get_selected_items_info (true); + process_new_file (parent_dir); + } + } - if (infos.length () > 0 && infos.first ().isDir ()) - process_set_current_dir (infos.first ().absoluteFilePath ()); -} + void files_dock_widget::contextmenu_newdir (bool) + { + QItemSelectionModel *m = m_file_tree_view->selectionModel (); + QModelIndexList rows = m->selectedRows (); -void files_dock_widget::contextmenu_add_to_path (bool, bool rm, bool subdirs) -{ - QList infos = get_selected_items_info (true); + if (rows.size () > 0) + { + QModelIndex index = rows[0]; + + QFileInfo info = m_file_system_model->fileInfo (index); + QString parent_dir = info.filePath (); - QStringList dir_list; + process_new_dir (parent_dir); + } + } - for (int i = 0; i < infos.length (); i++) - dir_list.append (infos.at (i).absoluteFilePath ()); - - if (infos.length () > 0) - emit modify_path_signal (dir_list, rm, subdirs); -} + void files_dock_widget::contextmenu_setcurrentdir (bool) + { + QList infos = get_selected_items_info (true); -void files_dock_widget::contextmenu_add_to_path_subdirs (bool) -{ - contextmenu_add_to_path (true, false, true); -} + if (infos.length () > 0 && infos.first ().isDir ()) + process_set_current_dir (infos.first ().absoluteFilePath ()); + } -void files_dock_widget::contextmenu_rm_from_path (bool) -{ - contextmenu_add_to_path (true, true, false); -} + void files_dock_widget::contextmenu_add_to_path (bool, bool rm, bool subdirs) + { + QList infos = get_selected_items_info (true); + + QStringList dir_list; + + for (int i = 0; i < infos.length (); i++) + dir_list.append (infos.at (i).absoluteFilePath ()); -void files_dock_widget::contextmenu_rm_from_path_subdirs (bool) -{ - contextmenu_add_to_path (true, true, true); -} + if (infos.length () > 0) + emit modify_path_signal (dir_list, rm, subdirs); + } + + void files_dock_widget::contextmenu_add_to_path_subdirs (bool) + { + contextmenu_add_to_path (true, false, true); + } -void files_dock_widget::contextmenu_findfiles (bool) -{ - QItemSelectionModel *m = m_file_tree_view->selectionModel (); - QModelIndexList rows = m->selectedRows (); + void files_dock_widget::contextmenu_rm_from_path (bool) + { + contextmenu_add_to_path (true, true, false); + } - if (rows.size () > 0) - { - QModelIndex index = rows[0]; - - QFileInfo info = m_file_system_model->fileInfo (index); + void files_dock_widget::contextmenu_rm_from_path_subdirs (bool) + { + contextmenu_add_to_path (true, true, true); + } - if (info.isDir ()) - { - process_find_files (info.absoluteFilePath ()); - } - } -} + void files_dock_widget::contextmenu_findfiles (bool) + { + QItemSelectionModel *m = m_file_tree_view->selectionModel (); + QModelIndexList rows = m->selectedRows (); -void files_dock_widget::notice_settings (const gui_settings *settings) -{ - // QSettings pointer is checked before emitting. + if (rows.size () > 0) + { + QModelIndex index = rows[0]; + + QFileInfo info = m_file_system_model->fileInfo (index); - int size_idx = settings->value (global_icon_size).toInt (); - size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2 + if (info.isDir ()) + { + process_find_files (info.absoluteFilePath ()); + } + } + } - QStyle *st = style (); - int icon_size = st->pixelMetric (global_icon_sizes[size_idx]); - m_navigation_tool_bar->setIconSize (QSize (icon_size, icon_size)); + void files_dock_widget::notice_settings (void) + { + gui_settings settings; - // filenames are always shown, other columns can be hidden by settings - for (int i = 0; i < 3; i++) - m_file_tree_view->setColumnHidden (i + 1, - ! settings->value (m_columns_shown_keys.at (i),false).toBool ()); + // QSettings pointer is checked before emitting. - QDir::Filters current_filter = m_file_system_model->filter (); - if (settings->value (m_columns_shown_keys.at (3), false).toBool ()) - m_file_system_model->setFilter (current_filter | QDir::Hidden); - else - m_file_system_model->setFilter (current_filter & (~QDir::Hidden)); + int size_idx = settings.value (global_icon_size).toInt (); + size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2 + + QStyle *st = style (); + int icon_size = st->pixelMetric (global_icon_sizes[size_idx]); + m_navigation_tool_bar->setIconSize (QSize (icon_size, icon_size)); - m_file_tree_view->setAlternatingRowColors - (settings->value (m_columns_shown_keys.at (4),true).toBool ()); - m_file_tree_view->setModel (m_file_system_model); + // filenames are always shown, other columns can be hidden by settings + for (int i = 0; i < 3; i++) + m_file_tree_view->setColumnHidden (i + 1, + ! settings.value (m_columns_shown_keys.at (i),false).toBool ()); - // enable the buttons to sync octave/browser dir - // only if this is not done by default - m_sync_octave_dir - = settings->value (fb_sync_octdir).toBool (); - m_sync_octave_directory_action->setEnabled (! m_sync_octave_dir); - m_sync_browser_directory_action->setEnabled (! m_sync_octave_dir); + QDir::Filters current_filter = m_file_system_model->filter (); + if (settings.value (m_columns_shown_keys.at (3), false).toBool ()) + m_file_system_model->setFilter (current_filter | QDir::Hidden); + else + m_file_system_model->setFilter (current_filter & (~QDir::Hidden)); - // If m_sync_octave_dir is enabled, then we want the file browser to - // update to match the current working directory of the - // interpreter. We don't want to queue any signal to change the - // interpreter's current working directory. In this case, we just - // want the GUI to match the state of the interpreter. + m_file_tree_view->setAlternatingRowColors + (settings.value (m_columns_shown_keys.at (4),true).toBool ()); + m_file_tree_view->setModel (m_file_system_model); - if (m_sync_octave_dir) - do_sync_browser_directory (); -} + // enable the buttons to sync octave/browser dir + // only if this is not done by default + m_sync_octave_dir + = settings.value (fb_sync_octdir).toBool (); + m_sync_octave_directory_action->setEnabled (! m_sync_octave_dir); + m_sync_browser_directory_action->setEnabled (! m_sync_octave_dir); -void files_dock_widget::popdownmenu_home (bool) -{ - QString dir = QString::fromStdString (sys::env::get_home_directory ()); + // If m_sync_octave_dir is enabled, then we want the file browser to + // update to match the current working directory of the + // interpreter. We don't want to queue any signal to change the + // interpreter's current working directory. In this case, we just + // want the GUI to match the state of the interpreter. - if (dir.isEmpty ()) - dir = QDir::homePath (); + if (m_sync_octave_dir) + do_sync_browser_directory (); + } - set_current_directory (dir); -} + void files_dock_widget::popdownmenu_home (bool) + { + QString dir = QString::fromStdString (sys::env::get_home_directory ()); + + if (dir.isEmpty ()) + dir = QDir::homePath (); + + set_current_directory (dir); + } -void files_dock_widget::popdownmenu_search_dir (bool) -{ - // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - int opts = QFileDialog::ShowDirsOnly; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) - opts |= QFileDialog::DontUseNativeDialog; + void files_dock_widget::popdownmenu_search_dir (bool) + { + // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. + int opts = QFileDialog::ShowDirsOnly; - QString dir = QFileDialog::getExistingDirectory (this, - tr ("Set directory of file browser"), - m_file_system_model->rootPath (), - QFileDialog::Option (opts)); - set_current_directory (dir); -} + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) + opts |= QFileDialog::DontUseNativeDialog; -void files_dock_widget::popdownmenu_findfiles (bool) -{ - process_find_files (m_file_system_model->rootPath ()); -} + QString dir = QFileDialog::getExistingDirectory (this, + tr ("Set directory of file browser"), + m_file_system_model->rootPath (), + QFileDialog::Option (opts)); + set_current_directory (dir); + } -void files_dock_widget::popdownmenu_newdir (bool) -{ - process_new_dir (m_file_system_model->rootPath ()); -} + void files_dock_widget::popdownmenu_findfiles (bool) + { + process_find_files (m_file_system_model->rootPath ()); + } -void files_dock_widget::popdownmenu_newfile (bool) -{ - process_new_file (m_file_system_model->rootPath ()); -} + void files_dock_widget::popdownmenu_newdir (bool) + { + process_new_dir (m_file_system_model->rootPath ()); + } -void files_dock_widget::process_new_file (const QString& parent_dir) -{ - bool ok; + void files_dock_widget::popdownmenu_newfile (bool) + { + process_new_file (m_file_system_model->rootPath ()); + } - QString name = QInputDialog::getText (this, tr ("Create File"), - tr ("Create file in\n", "String ends with \\n!") + parent_dir, - QLineEdit::Normal, - tr ("New File.txt"), &ok); - if (ok && name.length () > 0) - { - name = parent_dir + '/' + name; + void files_dock_widget::process_new_file (const QString& parent_dir) + { + bool ok; - QFile file (name); - file.open (QIODevice::WriteOnly); - m_file_system_model->revert (); - } -} + QString name = QInputDialog::getText (this, tr ("Create File"), + tr ("Create file in\n", "String ends with \\n!") + parent_dir, + QLineEdit::Normal, + tr ("New File.txt"), &ok); + if (ok && name.length () > 0) + { + name = parent_dir + '/' + name; -void files_dock_widget::process_new_dir (const QString& parent_dir) -{ - bool ok; + QFile file (name); + file.open (QIODevice::WriteOnly); + m_file_system_model->revert (); + } + } - QString name = QInputDialog::getText (this, tr ("Create Directory"), - tr ("Create folder in\n", "String ends with \\n!") + parent_dir, - QLineEdit::Normal, - tr ("New Directory"), &ok); - if (ok && name.length () > 0) - { - QDir dir (parent_dir); - dir.mkdir (name); - m_file_system_model->revert (); - } -} + void files_dock_widget::process_new_dir (const QString& parent_dir) + { + bool ok; -void files_dock_widget::process_set_current_dir (const QString& dir) -{ - emit displayed_directory_changed (dir); -} + QString name = QInputDialog::getText (this, tr ("Create Directory"), + tr ("Create folder in\n", "String ends with \\n!") + parent_dir, + QLineEdit::Normal, + tr ("New Directory"), &ok); + if (ok && name.length () > 0) + { + QDir dir (parent_dir); + dir.mkdir (name); + m_file_system_model->revert (); + } + } -void files_dock_widget::process_find_files (const QString& dir) -{ - emit find_files_signal (dir); -} + void files_dock_widget::process_set_current_dir (const QString& dir) + { + emit displayed_directory_changed (dir); + } -void files_dock_widget::copyClipboard () -{ - if (m_file_tree_view->hasFocus ()) - contextmenu_copy_selection (true); - if (m_current_directory->hasFocus ()) - { - QClipboard *clipboard = QApplication::clipboard (); + void files_dock_widget::process_find_files (const QString& dir) + { + emit find_files_signal (dir); + } - QLineEdit *edit = m_current_directory->lineEdit (); - if (edit && edit->hasSelectedText ()) - { - clipboard->setText (edit->selectedText ()); - } - } -} + void files_dock_widget::copyClipboard () + { + if (m_file_tree_view->hasFocus ()) + contextmenu_copy_selection (true); + if (m_current_directory->hasFocus ()) + { + QClipboard *clipboard = QApplication::clipboard (); + + QLineEdit *edit = m_current_directory->lineEdit (); + if (edit && edit->hasSelectedText ()) + { + clipboard->setText (edit->selectedText ()); + } + } + } -void files_dock_widget::pasteClipboard () -{ - if (m_current_directory->hasFocus ()) - { - QClipboard *clipboard = QApplication::clipboard (); - QString str = clipboard->text (); - QLineEdit *edit = m_current_directory->lineEdit (); - if (edit && str.length () > 0) - edit->insert (str); - } -} + void files_dock_widget::pasteClipboard () + { + if (m_current_directory->hasFocus ()) + { + QClipboard *clipboard = QApplication::clipboard (); + QString str = clipboard->text (); + QLineEdit *edit = m_current_directory->lineEdit (); + if (edit && str.length () > 0) + edit->insert (str); + } + } -void files_dock_widget::selectAll () -{ - if (m_file_tree_view->hasFocus ()) - m_file_tree_view->selectAll (); - if (m_current_directory->hasFocus ()) - { - QLineEdit *edit = m_current_directory->lineEdit (); - if (edit) - { - edit->selectAll (); - } - } -} + void files_dock_widget::selectAll () + { + if (m_file_tree_view->hasFocus ()) + m_file_tree_view->selectAll (); + if (m_current_directory->hasFocus ()) + { + QLineEdit *edit = m_current_directory->lineEdit (); + if (edit) + { + edit->selectAll (); + } + } + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/files-dock-widget.h --- a/libgui/src/files-dock-widget.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/files-dock-widget.h Tue Dec 06 15:45:27 2022 -0500 @@ -46,194 +46,194 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; + class base_qobject; -//! Dock widget to display files in the current directory. + //! Dock widget to display files in the current directory. -class files_dock_widget : public octave_dock_widget -{ - Q_OBJECT + class files_dock_widget : public octave_dock_widget + { + Q_OBJECT -public: + public: - files_dock_widget (QWidget *parent, base_qobject& oct_qobj); + files_dock_widget (QWidget *parent, base_qobject& oct_qobj); - ~files_dock_widget (void) = default; + ~files_dock_widget (void) = default; -signals: + signals: - //! Emitted, whenever the user requested to open a file. + //! Emitted, whenever the user requested to open a file. - void open_file (const QString& fileName); + void open_file (const QString& fileName); - //! Emitted, whenever the currently displayed directory changed. + //! Emitted, whenever the currently displayed directory changed. - void displayed_directory_changed (const QString& dir); + void displayed_directory_changed (const QString& dir); - //! Emitted, whenever the user requested to load a file in the text editor. + //! Emitted, whenever the user requested to load a file in the text editor. - void load_file_signal (const QString& fileName); + void load_file_signal (const QString& fileName); - //! Emitted, whenever the user requested to open an unknown type file. + //! Emitted, whenever the user requested to open an unknown type file. - void open_any_signal (const QString& fileName); + void open_any_signal (const QString& fileName); - //! Emitted, whenever the user requested to run a file. + //! Emitted, whenever the user requested to run a file. - void run_file_signal (const QFileInfo& info); + void run_file_signal (const QFileInfo& info); - //! Emitted, whenever wants to search for a file . + //! Emitted, whenever wants to search for a file . - void find_files_signal (const QString& startdir); + void find_files_signal (const QString& startdir); - //! Emitted, whenever the user removes or renames a file. + //! Emitted, whenever the user removes or renames a file. - void file_remove_signal (const QString& old_name, const QString& new_name); + void file_remove_signal (const QString& old_name, const QString& new_name); - //! Emitted, when a file or directory is renamed. + //! Emitted, when a file or directory is renamed. - void file_renamed_signal (bool); + void file_renamed_signal (bool); - //! Emitted, when the path has to be modified + //! Emitted, when the path has to be modified - void modify_path_signal (const QStringList& dir_list, bool rm, - bool subdirs); + void modify_path_signal (const QStringList& dir_list, bool rm, + bool subdirs); -public slots: + public slots: - //! Slot for handling a change in directory via double click. + //! Slot for handling a change in directory via double click. - void item_double_clicked (const QModelIndex& index); + void item_double_clicked (const QModelIndex& index); - //! Slot for handling the up-directory button in the toolbar. + //! Slot for handling the up-directory button in the toolbar. - void change_directory_up (void); + void change_directory_up (void); - //! Slot for handling the sync octave directory button in the toolbar. + //! Slot for handling the sync octave directory button in the toolbar. - void do_sync_octave_directory (void); + void do_sync_octave_directory (void); - //! Slot for handling the sync browser directory button in the toolbar. + //! Slot for handling the sync browser directory button in the toolbar. - void do_sync_browser_directory (void); + void do_sync_browser_directory (void); - //! Sets the current directory being displayed. + //! Sets the current directory being displayed. - void set_current_directory (const QString& dir); + void set_current_directory (const QString& dir); - //! Accepts user input a the line edit for the current directory. + //! Accepts user input a the line edit for the current directory. - void accept_directory_line_edit (void); + void accept_directory_line_edit (void); - //! Set the internal variable that holds the actual octave variable. + //! Set the internal variable that holds the actual octave variable. - void update_octave_directory (const QString& dir); + void update_octave_directory (const QString& dir); - //! Tells the widget to react on changed settings. + //! Tells the widget to react on changed settings. - void notice_settings (const gui_settings *settings); + void notice_settings (void); - void save_settings (void); + void save_settings (void); -private slots: + private slots: - void headercontextmenu_requested (const QPoint& pos); - void toggle_header (int col); + void headercontextmenu_requested (const QPoint& pos); + void toggle_header (int col); - //! Context menu wanted. + //! Context menu wanted. - void contextmenu_requested (const QPoint& pos); + void contextmenu_requested (const QPoint& pos); - //! Context menu actions. - //!@{ - void contextmenu_open (bool); - void contextmenu_open_in_editor (bool); - void contextmenu_open_in_app (bool); - void contextmenu_copy_selection (bool); - void contextmenu_run (bool); - void contextmenu_load (bool); - void contextmenu_rename (bool); - void contextmenu_delete (bool); - void contextmenu_newfile (bool); - void contextmenu_newdir (bool); - void contextmenu_setcurrentdir (bool); - void contextmenu_add_to_path (bool, bool rm=false, bool subdirs=false); - void contextmenu_add_to_path_subdirs (bool); - void contextmenu_rm_from_path (bool); - void contextmenu_rm_from_path_subdirs (bool); - void contextmenu_findfiles (bool); - //!@} + //! Context menu actions. + //!@{ + void contextmenu_open (bool); + void contextmenu_open_in_editor (bool); + void contextmenu_open_in_app (bool); + void contextmenu_copy_selection (bool); + void contextmenu_run (bool); + void contextmenu_load (bool); + void contextmenu_rename (bool); + void contextmenu_delete (bool); + void contextmenu_newfile (bool); + void contextmenu_newdir (bool); + void contextmenu_setcurrentdir (bool); + void contextmenu_add_to_path (bool, bool rm=false, bool subdirs=false); + void contextmenu_add_to_path_subdirs (bool); + void contextmenu_rm_from_path (bool); + void contextmenu_rm_from_path_subdirs (bool); + void contextmenu_findfiles (bool); + //!@} - //! Popdown menu options. - //!@{ - void popdownmenu_newfile (bool); - void popdownmenu_newdir (bool); - void popdownmenu_search_dir (bool); - void popdownmenu_findfiles (bool); - void popdownmenu_home (bool); - //!@} + //! Popdown menu options. + //!@{ + void popdownmenu_newfile (bool); + void popdownmenu_newdir (bool); + void popdownmenu_search_dir (bool); + void popdownmenu_findfiles (bool); + void popdownmenu_home (bool); + //!@} - //! Inherited from octave_doc_widget. - //!@{ - void copyClipboard (); - void pasteClipboard (); - void selectAll (); - //!@} + //! Inherited from octave_doc_widget. + //!@{ + void copyClipboard (); + void pasteClipboard (); + void selectAll (); + //!@} -private: + private: - //! Get currently selected QFileInfo object. + //! Get currently selected QFileInfo object. - QList get_selected_items_info (bool); + QList get_selected_items_info (bool); - //! Process new file/directory actions + //! Process new file/directory actions - void process_new_file (const QString& parent_name); - void process_new_dir (const QString& parent_name); + void process_new_file (const QString& parent_name); + void process_new_dir (const QString& parent_name); - //! Process setting current dir or find in files + //! Process setting current dir or find in files - void process_set_current_dir (const QString& parent_name); - void process_find_files (const QString& dir_name); + void process_set_current_dir (const QString& parent_name); + void process_find_files (const QString& dir_name); - //! set a new directory or open a file + //! set a new directory or open a file - void display_directory (const QString& dir, bool set_octave_dir = true); + void display_directory (const QString& dir, bool set_octave_dir = true); - void open_item_in_app (const QModelIndex& index); + void open_item_in_app (const QModelIndex& index); - //! Variables for the actions + //! Variables for the actions - QToolBar *m_navigation_tool_bar; - QAction *m_sync_octave_directory_action; - QAction *m_sync_browser_directory_action; - QAction *m_rename_action; + QToolBar *m_navigation_tool_bar; + QAction *m_sync_octave_directory_action; + QAction *m_sync_browser_directory_action; + QAction *m_rename_action; - //! The file system model. + //! The file system model. - QFileSystemModel *m_file_system_model; + QFileSystemModel *m_file_system_model; - //! The file system view. - //!@{ - QTreeView *m_file_tree_view; - QComboBox *m_current_directory; - //!@} + //! The file system view. + //!@{ + QTreeView *m_file_tree_view; + QComboBox *m_current_directory; + //!@} - //! Flag if syncing with Octave. + //! Flag if syncing with Octave. - bool m_sync_octave_dir; + bool m_sync_octave_dir; - //! The actual Octave directory. + //! The actual Octave directory. - QString m_octave_dir; + QString m_octave_dir; - enum { MaxMRUDirs = 10 }; + enum { MaxMRUDirs = 10 }; - QStringList m_columns_shown; - QStringList m_columns_shown_keys; - QList m_columns_shown_defs; - QSignalMapper *m_sig_mapper; -}; + QStringList m_columns_shown; + QStringList m_columns_shown_keys; + QList m_columns_shown_defs; + QSignalMapper *m_sig_mapper; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/find-files-dialog.cc --- a/libgui/src/find-files-dialog.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/find-files-dialog.cc Tue Dec 06 15:45:27 2022 -0500 @@ -49,367 +49,363 @@ #include "find-files-model.h" #include "gui-preferences-global.h" #include "gui-preferences-ff.h" -#include "octave-qobject.h" +#include "gui-settings.h" OCTAVE_BEGIN_NAMESPACE(octave) -find_files_dialog::find_files_dialog (QWidget *p, base_qobject& oct_qobj) -: QDialog (p), m_octave_qobj (oct_qobj) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + find_files_dialog::find_files_dialog (QWidget *p) + : QDialog (p) + { + gui_settings settings; - setWindowTitle (tr ("Find Files")); - setWindowIcon (rmgr.icon ("edit-find")); + setWindowTitle (tr ("Find Files")); + setWindowIcon (settings.icon ("edit-find")); - m_dir_iterator = nullptr; + m_dir_iterator = nullptr; - m_timer = new QTimer (this); - connect (m_timer, &QTimer::timeout, - this, &find_files_dialog::look_for_files); + m_timer = new QTimer (this); + connect (m_timer, &QTimer::timeout, + this, &find_files_dialog::look_for_files); - gui_settings *settings = rmgr.get_settings (); + QLabel *file_name_label = new QLabel (tr ("Named:")); + m_file_name_edit = new QLineEdit; + m_file_name_edit->setToolTip (tr ("Enter the filename search expression")); - QLabel *file_name_label = new QLabel (tr ("Named:")); - m_file_name_edit = new QLineEdit; - m_file_name_edit->setToolTip (tr ("Enter the filename search expression")); + m_file_name_edit->setText (settings.value (ff_file_name).toString ()); + file_name_label->setBuddy (m_file_name_edit); - m_file_name_edit->setText (settings->value (ff_file_name).toString ()); - file_name_label->setBuddy (m_file_name_edit); + QLabel *start_dir_label = new QLabel (tr ("Start in:")); - QLabel *start_dir_label = new QLabel (tr ("Start in:")); + m_start_dir_edit = new QLineEdit; + m_start_dir_edit->setText (settings.value (ff_start_dir.key, + QDir::currentPath ()).toString ()); + m_start_dir_edit->setToolTip (tr ("Enter the start directory")); + start_dir_label->setBuddy (m_start_dir_edit); - m_start_dir_edit = new QLineEdit; - m_start_dir_edit->setText (settings->value (ff_start_dir.key, - QDir::currentPath ()).toString ()); - m_start_dir_edit->setToolTip (tr ("Enter the start directory")); - start_dir_label->setBuddy (m_start_dir_edit); + m_browse_button = new QPushButton (tr ("Browse...")); + m_browse_button->setToolTip (tr ("Browse for start directory")); + connect (m_browse_button, &QPushButton::clicked, + this, &find_files_dialog::browse_folders); - m_browse_button = new QPushButton (tr ("Browse...")); - m_browse_button->setToolTip (tr ("Browse for start directory")); - connect (m_browse_button, &QPushButton::clicked, - this, &find_files_dialog::browse_folders); + m_recurse_dirs_check = new QCheckBox (tr ("Search subdirectories")); + m_recurse_dirs_check->setChecked (settings.value (ff_recurse_dirs).toBool ()); + m_recurse_dirs_check->setToolTip (tr ("Search recursively through directories for matching files")); - m_recurse_dirs_check = new QCheckBox (tr ("Search subdirectories")); - m_recurse_dirs_check->setChecked (settings->value (ff_recurse_dirs).toBool ()); - m_recurse_dirs_check->setToolTip (tr ("Search recursively through directories for matching files")); + m_include_dirs_check = new QCheckBox (tr ("Include directory names")); + m_include_dirs_check->setChecked (settings.value (ff_include_dirs).toBool ()); + m_include_dirs_check->setToolTip (tr ("Include matching directories in search results")); - m_include_dirs_check = new QCheckBox (tr ("Include directory names")); - m_include_dirs_check->setChecked (settings->value (ff_include_dirs).toBool ()); - m_include_dirs_check->setToolTip (tr ("Include matching directories in search results")); + m_name_case_check = new QCheckBox (tr ("Name case insensitive")); + m_name_case_check->setChecked (settings.value (ff_name_case).toBool ()); + m_name_case_check->setToolTip (tr ("Set matching name is case insensitive")); - m_name_case_check = new QCheckBox (tr ("Name case insensitive")); - m_name_case_check->setChecked (settings->value (ff_name_case).toBool ()); - m_name_case_check->setToolTip (tr ("Set matching name is case insensitive")); + m_contains_text_check = new QCheckBox (tr ("Contains text:")); + m_contains_text_check->setToolTip (tr ("Enter the file content search expression")); + m_contains_text_check->setChecked (settings.value (ff_check_text).toBool ()); - m_contains_text_check = new QCheckBox (tr ("Contains text:")); - m_contains_text_check->setToolTip (tr ("Enter the file content search expression")); - m_contains_text_check->setChecked (settings->value (ff_check_text).toBool ()); + m_contains_text_edit = new QLineEdit (); + m_contains_text_edit->setToolTip (tr ("Text to match")); + m_contains_text_edit->setText (settings.value (ff_contains_text).toString ()); - m_contains_text_edit = new QLineEdit (); - m_contains_text_edit->setToolTip (tr ("Text to match")); - m_contains_text_edit->setText (settings->value (ff_contains_text).toString ()); + m_content_case_check = new QCheckBox (tr ("Text case insensitive")); + m_content_case_check->setChecked (settings.value (ff_content_case).toBool ()); + m_content_case_check->setToolTip (tr ("Set text content is case insensitive")); - m_content_case_check = new QCheckBox (tr ("Text case insensitive")); - m_content_case_check->setChecked (settings->value (ff_content_case).toBool ()); - m_content_case_check->setToolTip (tr ("Set text content is case insensitive")); - - find_files_model *model = new find_files_model (this); + find_files_model *model = new find_files_model (this); - m_file_list = new QTableView; - m_file_list->setWordWrap (false); - m_file_list->setModel (model); - m_file_list->setShowGrid (false); - m_file_list->setSelectionBehavior (QAbstractItemView::SelectRows); - m_file_list->setSelectionMode (QAbstractItemView::SingleSelection); - m_file_list->setAlternatingRowColors (true); - m_file_list->setToolTip (tr ("Search results")); - m_file_list->setSortingEnabled (true); - m_file_list->horizontalHeader ()->restoreState (settings->value (ff_column_state.key).toByteArray ()); - m_file_list->horizontalHeader ()->setSortIndicatorShown (true); - m_file_list->horizontalHeader ()->setSectionsClickable (true); - m_file_list->horizontalHeader ()->setStretchLastSection (true); - m_file_list->sortByColumn (settings->value (ff_sort_files_by_column).toInt (), - static_cast - (settings->value (ff_sort_files_by_order).toUInt ())); - // FIXME: use value instead of static cast after - // dropping support of Qt 5.4 + m_file_list = new QTableView; + m_file_list->setWordWrap (false); + m_file_list->setModel (model); + m_file_list->setShowGrid (false); + m_file_list->setSelectionBehavior (QAbstractItemView::SelectRows); + m_file_list->setSelectionMode (QAbstractItemView::SingleSelection); + m_file_list->setAlternatingRowColors (true); + m_file_list->setToolTip (tr ("Search results")); + m_file_list->setSortingEnabled (true); + m_file_list->horizontalHeader ()->restoreState (settings.value (ff_column_state.key).toByteArray ()); + m_file_list->horizontalHeader ()->setSortIndicatorShown (true); + m_file_list->horizontalHeader ()->setSectionsClickable (true); + m_file_list->horizontalHeader ()->setStretchLastSection (true); + m_file_list->sortByColumn (settings.value (ff_sort_files_by_column).toInt (), + static_cast + (settings.value (ff_sort_files_by_order).toUInt ())); + // FIXME: use value instead of static cast after + // dropping support of Qt 5.4 - connect (m_file_list, &QTableView::doubleClicked, - this, &find_files_dialog::item_double_clicked); + connect (m_file_list, &QTableView::doubleClicked, + this, &find_files_dialog::item_double_clicked); - m_status_bar = new QStatusBar; - m_status_bar->showMessage (tr ("Idle.")); + m_status_bar = new QStatusBar; + m_status_bar->showMessage (tr ("Idle.")); - m_find_button = new QPushButton (tr ("Find")); - m_find_button->setToolTip (tr ("Start search for matching files")); - connect (m_find_button, &QPushButton::clicked, - this, &find_files_dialog::start_find); + m_find_button = new QPushButton (tr ("Find")); + m_find_button->setToolTip (tr ("Start search for matching files")); + connect (m_find_button, &QPushButton::clicked, + this, &find_files_dialog::start_find); - m_stop_button = new QPushButton (tr ("Stop")); - m_stop_button->setToolTip (tr ("Stop searching")); - m_stop_button->setEnabled (false); - connect (m_stop_button, &QPushButton::clicked, - this, &find_files_dialog::stop_find); + m_stop_button = new QPushButton (tr ("Stop")); + m_stop_button->setToolTip (tr ("Stop searching")); + m_stop_button->setEnabled (false); + connect (m_stop_button, &QPushButton::clicked, + this, &find_files_dialog::stop_find); - // layout everything - QDialogButtonBox *button_box = new QDialogButtonBox (Qt::Vertical); - button_box->addButton (m_find_button, QDialogButtonBox::ActionRole); - button_box->addButton (m_stop_button, QDialogButtonBox::ActionRole); + // layout everything + QDialogButtonBox *button_box = new QDialogButtonBox (Qt::Vertical); + button_box->addButton (m_find_button, QDialogButtonBox::ActionRole); + button_box->addButton (m_stop_button, QDialogButtonBox::ActionRole); - // add dialog close button - m_close_button = button_box->addButton (QDialogButtonBox::Close); - connect (button_box, &QDialogButtonBox::rejected, - this, &find_files_dialog::close); + // add dialog close button + m_close_button = button_box->addButton (QDialogButtonBox::Close); + connect (button_box, &QDialogButtonBox::rejected, + this, &find_files_dialog::close); - // name options - QGroupBox *name_group = new QGroupBox (tr ("Filename/location")); - QGridLayout *name_layout = new QGridLayout; - name_group->setLayout (name_layout); + // name options + QGroupBox *name_group = new QGroupBox (tr ("Filename/location")); + QGridLayout *name_layout = new QGridLayout; + name_group->setLayout (name_layout); - name_layout->addWidget (file_name_label, 1, 1, 1, 1); - name_layout->addWidget (m_file_name_edit, 1, 2, 1, -1); + name_layout->addWidget (file_name_label, 1, 1, 1, 1); + name_layout->addWidget (m_file_name_edit, 1, 2, 1, -1); - name_layout->addWidget (start_dir_label, 2, 1); - name_layout->addWidget (m_start_dir_edit, 2, 2, 1, 3); - name_layout->addWidget (m_browse_button, 2, 5); - name_layout->setColumnStretch (2, 1); + name_layout->addWidget (start_dir_label, 2, 1); + name_layout->addWidget (m_start_dir_edit, 2, 2, 1, 3); + name_layout->addWidget (m_browse_button, 2, 5); + name_layout->setColumnStretch (2, 1); - name_layout->addWidget (m_recurse_dirs_check, 3, 1); - name_layout->addWidget (m_include_dirs_check, 3, 2); - name_layout->addWidget (m_name_case_check, 3, 3); + name_layout->addWidget (m_recurse_dirs_check, 3, 1); + name_layout->addWidget (m_include_dirs_check, 3, 2); + name_layout->addWidget (m_name_case_check, 3, 3); - // content options - QGroupBox *content_group = new QGroupBox (tr ("File contents")); - QGridLayout *content_layout = new QGridLayout; - content_group->setLayout (content_layout); - content_layout->addWidget (m_contains_text_check, 4, 1); - content_layout->addWidget (m_contains_text_edit, 4, 2, 1, 3); - content_layout->setColumnStretch (2, 1); - content_layout->addWidget (m_content_case_check, 5, 1); + // content options + QGroupBox *content_group = new QGroupBox (tr ("File contents")); + QGridLayout *content_layout = new QGridLayout; + content_group->setLayout (content_layout); + content_layout->addWidget (m_contains_text_check, 4, 1); + content_layout->addWidget (m_contains_text_edit, 4, 2, 1, 3); + content_layout->setColumnStretch (2, 1); + content_layout->addWidget (m_content_case_check, 5, 1); - QGridLayout *main_layout = new QGridLayout; - main_layout->setSizeConstraint (QLayout::SetFixedSize); - main_layout->addWidget (name_group, 0, 0); - main_layout->addWidget (content_group, 1, 0); - main_layout->addWidget (button_box, 0, 1, 3, 1); - main_layout->addWidget (m_file_list, 2, 0); - main_layout->setRowStretch (2, 1); - main_layout->addWidget (m_status_bar, 3, 0, 1, -1); + QGridLayout *main_layout = new QGridLayout; + main_layout->setSizeConstraint (QLayout::SetFixedSize); + main_layout->addWidget (name_group, 0, 0); + main_layout->addWidget (content_group, 1, 0); + main_layout->addWidget (button_box, 0, 1, 3, 1); + main_layout->addWidget (m_file_list, 2, 0); + main_layout->setRowStretch (2, 1); + main_layout->addWidget (m_status_bar, 3, 0, 1, -1); - setLayout (main_layout); + setLayout (main_layout); - connect (this, &find_files_dialog::finished, - this, &find_files_dialog::handle_done); -} + connect (this, &find_files_dialog::finished, + this, &find_files_dialog::handle_done); + } -find_files_dialog::~find_files_dialog (void) -{ - delete m_dir_iterator; -} + find_files_dialog::~find_files_dialog (void) + { + delete m_dir_iterator; + } -void find_files_dialog::save_settings (void) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (! settings) - return; + void find_files_dialog::save_settings (void) + { + gui_settings settings; - int sort_column = m_file_list->horizontalHeader ()->sortIndicatorSection (); - Qt::SortOrder sort_order - = m_file_list->horizontalHeader ()->sortIndicatorOrder (); - settings->setValue (ff_sort_files_by_column.key, sort_column); - settings->setValue (ff_sort_files_by_order.key, sort_order); - settings->setValue (ff_column_state.key, m_file_list->horizontalHeader ()->saveState ()); + int sort_column = m_file_list->horizontalHeader ()->sortIndicatorSection (); + Qt::SortOrder sort_order + = m_file_list->horizontalHeader ()->sortIndicatorOrder (); + settings.setValue (ff_sort_files_by_column.key, sort_column); + settings.setValue (ff_sort_files_by_order.key, sort_order); + settings.setValue (ff_column_state.key, m_file_list->horizontalHeader ()->saveState ()); + + settings.setValue (ff_file_name.key, m_file_name_edit->text ()); - settings->setValue (ff_file_name.key, m_file_name_edit->text ()); - - settings->setValue (ff_start_dir.key, m_start_dir_edit->text ()); + settings.setValue (ff_start_dir.key, m_start_dir_edit->text ()); - settings->setValue (ff_recurse_dirs.key, m_recurse_dirs_check->text ()); - settings->setValue (ff_include_dirs.key, m_include_dirs_check->text ()); - settings->setValue (ff_name_case.key, m_name_case_check->text ()); + settings.setValue (ff_recurse_dirs.key, m_recurse_dirs_check->text ()); + settings.setValue (ff_include_dirs.key, m_include_dirs_check->text ()); + settings.setValue (ff_name_case.key, m_name_case_check->text ()); + + settings.setValue (ff_contains_text.key, m_contains_text_edit->text ()); + settings.setValue (ff_check_text.key, m_contains_text_check->isChecked ()); + settings.setValue (ff_content_case.key, m_content_case_check->isChecked ()); - settings->setValue (ff_contains_text.key, m_contains_text_edit->text ()); - settings->setValue (ff_check_text.key, m_contains_text_check->isChecked ()); - settings->setValue (ff_content_case.key, m_content_case_check->isChecked ()); - - settings->sync (); -} + settings.sync (); + } -void find_files_dialog::set_search_dir (const QString& dir) -{ - stop_find (); - m_start_dir_edit->setText (dir); -} + void find_files_dialog::set_search_dir (const QString& dir) + { + stop_find (); + m_start_dir_edit->setText (dir); + } -void find_files_dialog::start_find (void) -{ - stop_find (); + void find_files_dialog::start_find (void) + { + stop_find (); + + find_files_model *m = static_cast (m_file_list->model ()); + m->clear (); - find_files_model *m = static_cast (m_file_list->model ()); - m->clear (); + QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags; + if (m_recurse_dirs_check->isChecked ()) + flags |= QDirIterator::Subdirectories; - QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags; - if (m_recurse_dirs_check->isChecked ()) - flags |= QDirIterator::Subdirectories; + QDir::Filters filters = QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files; + if (! m_name_case_check->isChecked ()) + filters |= QDir::CaseSensitive; - QDir::Filters filters = QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files; - if (! m_name_case_check->isChecked ()) - filters |= QDir::CaseSensitive; + QStringList nameFilters; + nameFilters.append (m_file_name_edit->text ()); - QStringList nameFilters; - nameFilters.append (m_file_name_edit->text ()); + if (m_dir_iterator) + delete m_dir_iterator; - if (m_dir_iterator) - delete m_dir_iterator; - - m_dir_iterator = new QDirIterator (m_start_dir_edit->text (), nameFilters, - filters, flags); + m_dir_iterator = new QDirIterator (m_start_dir_edit->text (), nameFilters, + filters, flags); - // enable/disable widgets - m_find_button->setEnabled (false); - m_stop_button->setEnabled (true); - m_close_button->setEnabled (false); - m_browse_button->setEnabled (false); - m_start_dir_edit->setEnabled (false); - m_file_name_edit->setEnabled (false); - m_recurse_dirs_check->setEnabled (false); - m_include_dirs_check->setEnabled (false); - m_name_case_check->setEnabled (false); - m_contains_text_check->setEnabled (false); - m_content_case_check->setEnabled (false); - m_contains_text_edit->setEnabled (false); + // enable/disable widgets + m_find_button->setEnabled (false); + m_stop_button->setEnabled (true); + m_close_button->setEnabled (false); + m_browse_button->setEnabled (false); + m_start_dir_edit->setEnabled (false); + m_file_name_edit->setEnabled (false); + m_recurse_dirs_check->setEnabled (false); + m_include_dirs_check->setEnabled (false); + m_name_case_check->setEnabled (false); + m_contains_text_check->setEnabled (false); + m_content_case_check->setEnabled (false); + m_contains_text_edit->setEnabled (false); - m_status_bar->showMessage (tr ("Searching...")); - m_timer->start (0); -} + m_status_bar->showMessage (tr ("Searching...")); + m_timer->start (0); + } -void find_files_dialog::stop_find (void) -{ - m_timer->stop (); + void find_files_dialog::stop_find (void) + { + m_timer->stop (); - m_find_button->setEnabled (true); - m_stop_button->setEnabled (false); - m_close_button->setEnabled (true); - m_browse_button->setEnabled (true); - m_start_dir_edit->setEnabled (true); - m_file_name_edit->setEnabled (true); - m_recurse_dirs_check->setEnabled (true); - m_include_dirs_check->setEnabled (true); - m_name_case_check->setEnabled (true); - m_contains_text_check->setEnabled (true); - m_content_case_check->setEnabled (true); - m_contains_text_edit->setEnabled (true); + m_find_button->setEnabled (true); + m_stop_button->setEnabled (false); + m_close_button->setEnabled (true); + m_browse_button->setEnabled (true); + m_start_dir_edit->setEnabled (true); + m_file_name_edit->setEnabled (true); + m_recurse_dirs_check->setEnabled (true); + m_include_dirs_check->setEnabled (true); + m_name_case_check->setEnabled (true); + m_contains_text_check->setEnabled (true); + m_content_case_check->setEnabled (true); + m_contains_text_edit->setEnabled (true); + + find_files_model *m = static_cast (m_file_list->model ()); + QString res_str = QString (tr ("%1 match (es)")).arg (m->rowCount ()); - find_files_model *m = static_cast (m_file_list->model ()); - QString res_str = QString (tr ("%1 match (es)")).arg (m->rowCount ()); + m_status_bar->showMessage (res_str); + } - m_status_bar->showMessage (res_str); -} + void find_files_dialog::browse_folders (void) + { + int opts = 0; // No options by default. + + // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. -void find_files_dialog::browse_folders (void) -{ - int opts = 0; // No options by default. - // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) - opts = QFileDialog::DontUseNativeDialog; + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) + opts = QFileDialog::DontUseNativeDialog; + + QString dir = + QFileDialog::getExistingDirectory (this, tr ("Set search directory"), + m_start_dir_edit->text (), + QFileDialog::Option (opts)); - QString dir = - QFileDialog::getExistingDirectory (this, tr ("Set search directory"), - m_start_dir_edit->text (), - QFileDialog::Option (opts)); + if (! dir.isEmpty ()) + m_start_dir_edit->setText (dir); + } - if (! dir.isEmpty ()) - m_start_dir_edit->setText (dir); -} + void find_files_dialog::item_double_clicked (const QModelIndex& idx) + { + find_files_model *m = static_cast (m_file_list->model ()); -void find_files_dialog::item_double_clicked (const QModelIndex& idx) -{ - find_files_model *m = static_cast (m_file_list->model ()); - - QFileInfo info = m->fileInfo (idx); + QFileInfo info = m->fileInfo (idx); - if (idx.column () == 1) - { - // clicked in directory part - emit dir_selected (info.absolutePath ()); - } - else - { - // clicked in filename part - if (info.isDir ()) - emit dir_selected (info.absoluteFilePath ()); - else - emit file_selected (info.absoluteFilePath ()); - } -} + if (idx.column () == 1) + { + // clicked in directory part + emit dir_selected (info.absolutePath ()); + } + else + { + // clicked in filename part + if (info.isDir ()) + emit dir_selected (info.absoluteFilePath ()); + else + emit file_selected (info.absoluteFilePath ()); + } + } -void find_files_dialog::look_for_files (void) -{ - if (m_dir_iterator && m_dir_iterator->hasNext ()) - { - QFileInfo info (m_dir_iterator->next ()); + void find_files_dialog::look_for_files (void) + { + if (m_dir_iterator && m_dir_iterator->hasNext ()) + { + QFileInfo info (m_dir_iterator->next ()); + + find_files_model *m + = static_cast (m_file_list->model ()); - find_files_model *m - = static_cast (m_file_list->model ()); + if (is_match (info)) + m->addFile (info); + } + else + { + stop_find (); + } + } - if (is_match (info)) - m->addFile (info); - } - else - { - stop_find (); - } -} + void find_files_dialog::handle_done (int) + { + // make sure we stopped processing + stop_find (); + } -void find_files_dialog::handle_done (int) -{ - // make sure we stopped processing - stop_find (); -} + bool find_files_dialog::is_match (const QFileInfo& info) + { + bool match = true; + if (info.isDir ()) + { + if (! m_include_dirs_check->isChecked ()) match = false; + if (m_contains_text_check->isChecked ()) match = false; + } + else + { + // a file + if (m_contains_text_check->isChecked ()) + { + match = false; -bool find_files_dialog::is_match (const QFileInfo& info) -{ - bool match = true; - if (info.isDir ()) - { - if (! m_include_dirs_check->isChecked ()) match = false; - if (m_contains_text_check->isChecked ()) match = false; - } - else - { - // a file - if (m_contains_text_check->isChecked ()) - { - match = false; + QFile file (info.absoluteFilePath ()); + if (file.open (QIODevice::ReadOnly)) + { + QTextStream stream (&file); - QFile file (info.absoluteFilePath ()); - if (file.open (QIODevice::ReadOnly)) - { - QTextStream stream (&file); + QString line; + QString match_str = m_contains_text_edit->text (); + + Qt::CaseSensitivity cs = m_content_case_check->isChecked () + ? Qt::CaseInsensitive + : Qt::CaseSensitive; - QString line; - QString match_str = m_contains_text_edit->text (); - - Qt::CaseSensitivity cs = m_content_case_check->isChecked () - ? Qt::CaseInsensitive - : Qt::CaseSensitive; + do + { + line = stream.readLine (); + match = line.contains (match_str, cs); + } + while (! line.isNull () && match == false); + } - do - { - line = stream.readLine (); - match = line.contains (match_str, cs); - } - while (! line.isNull () && match == false); - } + } + } - } - } - - return match; -} + return match; + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/find-files-dialog.h --- a/libgui/src/find-files-dialog.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/find-files-dialog.h Tue Dec 06 15:45:27 2022 -0500 @@ -39,61 +39,57 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; - -class find_files_dialog : public QDialog -{ - Q_OBJECT + class find_files_dialog : public QDialog + { + Q_OBJECT -public: + public: - find_files_dialog (QWidget *parent, base_qobject& oct_qobj); + find_files_dialog (QWidget *parent); - virtual ~find_files_dialog (void); + virtual ~find_files_dialog (void); - void save_settings (void); + void save_settings (void); -signals: + signals: - void file_selected (const QString& fileName); - void dir_selected (const QString& fileName); + void file_selected (const QString& fileName); + void dir_selected (const QString& fileName); -public slots: + public slots: - void set_search_dir (const QString& dir); + void set_search_dir (const QString& dir); -private slots: + private slots: - void start_find (void); - void stop_find (void); - void browse_folders (void); - void look_for_files (void); - void item_double_clicked (const QModelIndex&); - void handle_done (int); + void start_find (void); + void stop_find (void); + void browse_folders (void); + void look_for_files (void); + void item_double_clicked (const QModelIndex&); + void handle_done (int); -private: + private: - bool is_match (const QFileInfo& info); - - base_qobject& m_octave_qobj; + bool is_match (const QFileInfo& info); - QLineEdit *m_start_dir_edit; - QLineEdit *m_file_name_edit; - QPushButton *m_stop_button; - QPushButton *m_find_button; - QPushButton *m_close_button; - QPushButton *m_browse_button; - QTableView *m_file_list; - QTimer *m_timer; - QCheckBox *m_recurse_dirs_check; - QCheckBox *m_include_dirs_check; - QCheckBox *m_name_case_check; - QCheckBox *m_contains_text_check; - QCheckBox *m_content_case_check; - QLineEdit *m_contains_text_edit; - QDirIterator *m_dir_iterator; - QStatusBar *m_status_bar; -}; + QLineEdit *m_start_dir_edit; + QLineEdit *m_file_name_edit; + QPushButton *m_stop_button; + QPushButton *m_find_button; + QPushButton *m_close_button; + QPushButton *m_browse_button; + QTableView *m_file_list; + QTimer *m_timer; + QCheckBox *m_recurse_dirs_check; + QCheckBox *m_include_dirs_check; + QCheckBox *m_name_case_check; + QCheckBox *m_contains_text_check; + QCheckBox *m_content_case_check; + QLineEdit *m_contains_text_edit; + QDirIterator *m_dir_iterator; + QStatusBar *m_status_bar; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/graphics-init.cc --- a/libgui/src/graphics-init.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/graphics-init.cc Tue Dec 06 15:45:27 2022 -0500 @@ -32,7 +32,6 @@ #include #include "graphics-init.h" -#include "octave-qobject.h" #include "qt-graphics-toolkit.h" #include "QtHandlesUtils.h" @@ -42,38 +41,38 @@ OCTAVE_BEGIN_NAMESPACE(octave) -void graphics_init (interpreter& interp, base_qobject& oct_qobj) -{ + void graphics_init (interpreter& interp) + { #if defined (HAVE_QT_GRAPHICS) - gh_manager& gh_mgr = interp.get_gh_manager (); + gh_manager& gh_mgr = interp.get_gh_manager (); - autolock guard (gh_mgr.graphics_lock ()); + autolock guard (gh_mgr.graphics_lock ()); - qRegisterMetaType ("graphics_object"); + qRegisterMetaType ("graphics_object"); - gh_mgr.enable_event_processing (true); + gh_mgr.enable_event_processing (true); - qt_graphics_toolkit *qt_gtk = new qt_graphics_toolkit (interp, oct_qobj); + qt_graphics_toolkit *qt_gtk = new qt_graphics_toolkit (interp); - if (QThread::currentThread () - != QApplication::instance ()->thread ()) - qt_gtk->moveToThread (QApplication::instance ()->thread ()); + if (QThread::currentThread () + != QApplication::instance ()->thread ()) + qt_gtk->moveToThread (QApplication::instance ()->thread ()); - graphics_toolkit tk (qt_gtk); + graphics_toolkit tk (qt_gtk); - gtk_manager& gtk_mgr = interp.get_gtk_manager (); + gtk_manager& gtk_mgr = interp.get_gtk_manager (); - gtk_mgr.register_toolkit ("qt"); + gtk_mgr.register_toolkit ("qt"); - gtk_mgr.load_toolkit (tk); + gtk_mgr.load_toolkit (tk); #else - octave_unused_parameter (interp); - octave_unused_parameter (oct_qobj); + octave_unused_parameter (interp); + octave_unused_parameter (oct_qobj); #endif -} + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/graphics-init.h --- a/libgui/src/graphics-init.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/graphics-init.h Tue Dec 06 15:45:27 2022 -0500 @@ -32,10 +32,9 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class interpreter; -class base_qobject; + class interpreter; -extern void graphics_init (interpreter& interp, base_qobject& oct_qobj); + extern void graphics_init (interpreter& interp); OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/gui-preferences-global.h --- a/libgui/src/gui-preferences-global.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/gui-preferences-global.h Tue Dec 06 15:45:27 2022 -0500 @@ -34,6 +34,9 @@ // Global preferences +const gui_pref +global_skip_welcome_wizard ("global_skip_welcome_wizard", false); + // Get the default monospaced font #if defined (Q_OS_WIN) const QString global_font_family = "Courier"; @@ -118,6 +121,9 @@ }; const gui_pref +global_icon_fallbacks ("icon_fallbacks", QVariant (QStringList ())); + +const gui_pref global_status_bar ("show_status_bar", QVariant (true)); diff -r 29d734430e5f -r deb553ac2c54 libgui/src/gui-preferences.h diff -r 29d734430e5f -r deb553ac2c54 libgui/src/gui-settings.cc --- a/libgui/src/gui-settings.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/gui-settings.cc Tue Dec 06 15:45:27 2022 -0500 @@ -27,85 +27,326 @@ # include "config.h" #endif +#include + #include +#include +#include +#include +#include +#include #include +#include +#include +#include "gui-preferences-cs.h" +#include "gui-preferences-global.h" #include "gui-settings.h" +#include "oct-env.h" + OCTAVE_BEGIN_NAMESPACE(octave) -QColor gui_settings::get_color_value (const QVariant& def, int mode) const -{ - QColor default_color; + QString gui_settings::file_name (void) const + { + return fileName (); + } + + QString gui_settings::directory_name (void) const + { + QFileInfo sfile (fileName ()); + + return sfile.absolutePath (); + } + + QColor gui_settings::get_color_value (const QVariant& def, int mode) const + { + QColor default_color; + + // Determine whether the default value in pref is given as + // QPalette::ColorRole or as QColor + if (def.canConvert (QMetaType::QColor)) + default_color = def.value (); + else + { + // The default colors are given as color roles for + // the application's palette + default_color = QApplication::palette ().color + (static_cast (def.toInt ())); + // FIXME: use value instead of static cast after + // dropping support of Qt 5.4 + } - // Determine whether the default value in pref is given as - // QPalette::ColorRole or as QColor - if (def.canConvert (QMetaType::QColor)) - default_color = def.value (); - else - { - // The default colors are given as color roles for - // the application's palette - default_color = QApplication::palette ().color - (static_cast (def.toInt ())); - // FIXME: use value instead of static cast after - // dropping support of Qt 5.4 - } + if ((mode == 1) && (default_color != settings_color_no_change)) + { + // In second mode, determine the default color from the first mode + qreal h, s, l, a; + default_color.getHslF (&h, &s, &l, &a); + qreal l_new = 1.0-l*0.85; + if (l < 0.3) + l_new = 1.0-l*0.7; // convert darker into lighter colors + default_color.setHslF (h, s, l_new, a); + } + + return default_color; + } + + QColor gui_settings::color_value (const gui_pref& pref, int mode) const + { + QColor default_color = get_color_value (pref.def, mode); + + return value (pref.key + settings_color_modes_ext[mode], + QVariant (default_color)).value (); + } + + void gui_settings::set_color_value (const gui_pref& pref, + const QColor& color, int mode) + { + int m = mode; + if (m > 1) + m = 1; + + setValue (pref.key + settings_color_modes_ext[m], QVariant (color)); + } + + QString gui_settings::sc_value (const sc_pref& pref) const + { + QKeySequence key_seq = sc_def_value (pref); + + // Get the value from the settings where the key sequences are stored + // as strings + return value (sc_group + pref.key, key_seq.toString ()).toString (); + } - if ((mode == 1) && (default_color != settings_color_no_change)) - { - // In second mode, determine the default color from the first mode - qreal h, s, l, a; - default_color.getHslF (&h, &s, &l, &a); - qreal l_new = 1.0-l*0.85; - if (l < 0.3) - l_new = 1.0-l*0.7; // convert darker into lighter colors - default_color.setHslF (h, s, l_new, a); - } + QKeySequence gui_settings::sc_def_value (const sc_pref& pref) const + { + QKeySequence key_seq = QKeySequence (); + + // Check, which of the elements for the default value in the sc_pref + // structure has a valid value and take this as default. If both + // elements are not valid, leave the key sequence empty + if (pref.def) + key_seq = QKeySequence (pref.def); + else if (pref.def_std != QKeySequence::UnknownKey) + key_seq = QKeySequence (pref.def_std); + + return key_seq; + } + + void gui_settings::config_icon_theme (void) + { + int theme_index; + + if (contains (global_icon_theme_index.key)) + theme_index = value (global_icon_theme_index).toInt (); + else + { + // New pref does not exist. Use old if required. Add new and + // remove deprecated key. + + if (value (global_icon_theme).toBool ()) + theme_index = ICON_THEME_SYSTEM; + else + theme_index = ICON_THEME_OCTAVE; + + setValue (global_icon_theme_index.key, theme_index); + remove (global_icon_theme.key); + } + + QIcon::setThemeName (global_all_icon_themes.at (theme_index)); - return default_color; -} + QStringList icon_fallbacks; + + // Set the required fallback search paths. + + switch (theme_index) + { + case ICON_THEME_SYSTEM: + icon_fallbacks << global_icon_paths.at (ICON_THEME_OCTAVE); + icon_fallbacks << global_icon_paths.at (ICON_THEME_TANGO); + break; + case ICON_THEME_TANGO: + icon_fallbacks << global_icon_paths.at (ICON_THEME_OCTAVE); + break; + case ICON_THEME_OCTAVE: + icon_fallbacks << global_icon_paths.at (ICON_THEME_TANGO); + break; + } -QColor gui_settings::color_value (const gui_pref& pref, int mode) const -{ - QColor default_color = get_color_value (pref.def, mode); + icon_fallbacks << global_icon_paths.at (ICON_THEME_CURSORS); + + setValue (global_icon_fallbacks.key, icon_fallbacks); + } + + QIcon gui_settings::icon (const QString& icon_name, bool octave_only, + const QString& icon_alt_name) + { + if (octave_only) + return QIcon (global_icon_paths.at (ICON_THEME_OCTAVE) + icon_name + ".png"); + + if (QIcon::hasThemeIcon (icon_name)) + return QIcon (QIcon::fromTheme (icon_name)); + else if ((! icon_alt_name.isEmpty ()) && QIcon::hasThemeIcon (icon_alt_name)) + return QIcon (QIcon::fromTheme (icon_alt_name)); + + QStringList icon_fallbacks + = value (global_icon_fallbacks.key).toStringList (); - return value (pref.key + settings_color_modes_ext[mode], - QVariant (default_color)).value (); -} + for (int i = 0; i < icon_fallbacks.length (); i++ ) + { + QString icon_file (icon_fallbacks.at (i) + icon_name + ".png"); + if (QFile (icon_file).exists ()) + return QIcon (icon_file); + } + + //QIcon::setThemeName (current_theme); + return QIcon (); + } + + QString gui_settings::get_default_font_family (void) + { + QString default_family; + + // Get all available fixed width fonts via a font combobox + QFontComboBox font_combo_box; + font_combo_box.setFontFilters (QFontComboBox::MonospacedFonts); + QStringList fonts; + + for (int index = 0; index < font_combo_box.count(); index++) + fonts << font_combo_box.itemText(index); + +#if defined (Q_OS_MAC) + // Use hard coded default on macOS, since selection of fixed width + // default font is unreliable (see bug #59128). + // Test for macOS default fixed width font + if (fonts.contains (global_mono_font.def.toString ())) + default_family = global_mono_font.def.toString (); +#endif -void gui_settings::set_color_value (const gui_pref& pref, - const QColor& color, int mode) -{ - int m = mode; - if (m > 1) - m = 1; + // If default font is still empty (on all other platforms or + // if macOS default font is not available): use QFontDatabase + if (default_family.isEmpty ()) + { + // Get the system's default monospaced font + QFont fixed_font = QFontDatabase::systemFont (QFontDatabase::FixedFont); + default_family = fixed_font.defaultFamily (); + + // Since this might be unreliable, test all available fixed width fonts + if (! fonts.contains (default_family)) + { + // Font returned by QFontDatabase is not in fixed fonts list. + // Fallback: take first from this list + default_family = fonts[0]; + } + } + + // Test env variable which has preference + std::string env_default_family = sys::env::getenv ("OCTAVE_DEFAULT_FONT"); + if (! env_default_family.empty ()) + default_family = QString::fromStdString (env_default_family); - setValue (pref.key + settings_color_modes_ext[m], QVariant (color)); -} + return default_family; + } + + QStringList gui_settings::get_default_font (void) + { + QString default_family = get_default_font_family (); + + // determine the fefault font size of the system + // FIXME: QApplication::font () does not return the monospace font, + // but the size should be probably near to the monospace font + QFont font = QApplication::font (); -QString gui_settings::sc_value (const sc_pref& pref) const -{ - QKeySequence key_seq = sc_def_value (pref); + int font_size = font.pointSize (); + if (font_size == -1) + font_size = static_cast (std::floor(font.pointSizeF ())); + + // check for valid font size, otherwise take default 10 + QString default_font_size = "10"; + if (font_size > 0) + default_font_size = QString::number (font_size); + + std::string env_default_font_size + = sys::env::getenv ("OCTAVE_DEFAULT_FONT_SIZE"); - // Get the value from the settings where the key sequences are stored - // as strings - return value (sc_group + pref.key, key_seq.toString ()).toString (); -} + if (! env_default_font_size.empty ()) + default_font_size = QString::fromStdString (env_default_font_size); + + QStringList result; + result << default_family; + result << default_font_size; + return result; + } + + void gui_settings::reload (void) + { + // Declare some empty options, which may be set at first startup for + // writing them into the newly created settings file + QString custom_editor; + QStringList def_font; -QKeySequence gui_settings::sc_def_value (const sc_pref& pref) const -{ - QKeySequence key_seq = QKeySequence (); + // Check whether the settings file does not yet exist + if (! QFile::exists (file_name ())) + { + // Get the default font (for terminal) + def_font = get_default_font (); + + // Get a custom editor defined as env variable + std::string env_default_editor + = sys::env::getenv ("OCTAVE_DEFAULT_EDITOR"); + + if (! env_default_editor.empty ()) + custom_editor = QString::fromStdString (env_default_editor); + } + + check (); + + // Write some settings that were dynamically determined at first startup + + // Custom editor + if (! custom_editor.isEmpty ()) + setValue (global_custom_editor.key, custom_editor); - // Check, which of the elements for the default value in the sc_pref - // structure has a valid value and take this as default. If both - // elements are not valid, leave the key sequence empty - if (pref.def) - key_seq = QKeySequence (pref.def); - else if (pref.def_std != QKeySequence::UnknownKey) - key_seq = QKeySequence (pref.def_std); + // Default monospace font for the terminal + if (def_font.count () > 1) + { + setValue (cs_font.key, def_font[0]); + setValue (cs_font_size.key, def_font[1].toInt ()); + } + + // Write the default monospace font into the settings for later use by + // console and editor as fallbacks of their font preferences. + setValue (global_mono_font.key, get_default_font_family ()); + } + + void gui_settings::check (void) + { + if (status () == QSettings::NoError) + { + // Test usability (force file to be really created) + setValue ("dummy", 0); + sync (); + } - return key_seq; -} + if (! (QFile::exists (file_name ()) + && isWritable () + && status () == QSettings::NoError)) + { + QString msg + = QString (QT_TR_NOOP ("Error %1 creating the settings file\n%2\n" + "Make sure you have read and write permissions to\n%3\n\n" + "Octave GUI must be closed now.")); + + QMessageBox::critical (nullptr, + QString (QT_TR_NOOP ("Octave Critical Error")), + msg.arg (status ()) + .arg (file_name ()) + .arg (directory_name ())); + + exit (1); + } + else + remove ("dummy"); // Remove test entry + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/gui-settings.h --- a/libgui/src/gui-settings.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/gui-settings.h Tue Dec 06 15:45:27 2022 -0500 @@ -26,102 +26,137 @@ #if ! defined (octave_gui_settings_h) #define octave_gui_settings_h 1 -#include "octave-config.h" - +#include +#include #include #include "gui-preferences.h" OCTAVE_BEGIN_NAMESPACE(octave) -class gui_settings : public QSettings -{ - Q_OBJECT + class gui_settings : public QSettings + { + Q_OBJECT + + public: -public: + // Location, name, and format of settings file determined by + // settings in qt_application class construtor. + + gui_settings (QObject *parent = nullptr) + : QSettings (parent) + { } - gui_settings (const QString& file_name, QSettings::Format format, - QObject *parent = nullptr) - : QSettings (file_name, format, parent) - { } + gui_settings (const QString& file_name, QSettings::Format format, + QObject *parent = nullptr) + : QSettings (file_name, format, parent) + { } - gui_settings (QSettings::Format format, QSettings::Scope scope, - const QString& organization, - const QString& application = QString (), - QObject *parent = nullptr) - : QSettings (format, scope, organization, application, parent) - { } + gui_settings (QSettings::Format format, QSettings::Scope scope, + const QString& organization, + const QString& application = QString (), + QObject *parent = nullptr) + : QSettings (format, scope, organization, application, parent) + { } + + // No copying! + + gui_settings (const gui_settings&) = delete; - // No copying! + gui_settings& operator = (const gui_settings&) = delete; - gui_settings (const gui_settings&) = delete; + ~gui_settings (void) = default; + + QString file_name (void) const; - gui_settings& operator = (const gui_settings&) = delete; + QString directory_name (void) const; + + using QSettings::value; - ~gui_settings (void) = default; + QVariant value (const gui_pref& pref) const + { + if (pref.ignore) + return pref.def; // ignore the current pref and always use default - using QSettings::value; + return value (pref.key, pref.def); + } - QVariant value (const gui_pref& pref) const - { - if (pref.ignore) - return pref.def; // ignore the current pref and always use default - - return value (pref.key, pref.def); - } + /*! + Reading a color from the given QVaraitn @p def taking different + color modes into account. The default value for a second color mode + @p mode=1 is deterimined from the standard default value @p mode=0 + by inverting the lightness + \f{eqnarray*}{ + H_1 &=& H_0\\ + S_1 &=& S_0\\ + L_1 &=& 1.0 - 0.85 L_0 L_0 > 0.3 + L_1 &=& 1.0 - 0.70 L_0 L_0 < 0.3 + \f} - /*! - Reading a color from the given QVaraitn @p def taking different - color modes into account. The default value for a second color mode - @p mode=1 is deterimined from the standard default value @p mode=0 - by inverting the lightness - \f{eqnarray*}{ - H_1 &=& H_0\\ - S_1 &=& S_0\\ - L_1 &=& 1.0 - 0.85 L_0 L_0 > 0.3 - L_1 &=& 1.0 - 0.70 L_0 L_0 < 0.3 - \f} + @param def Color default value given by a QVariant of QColor + or QPalette::ColorRole + @param mode Color mode (currently 0 or 1, default is 0) + + @return Color as QColor + */ + QColor get_color_value (const QVariant& def, int mode = 0) const; + + /*! + Reading a color from the gui_settings taking possible color modes + into account. The default value for a second color mode @p mode=1 is + deterimined from the standard default value @p mode=0 by inverting + the lightness (see get_color_value()) - @param def Color default value given by a QVariant of QColor - or QPalette::ColorRole - @param mode Color mode (currently 0 or 1, default is 0) + @param pref gui preference (key string, default value); the default + value can be given by QColor or QPalette::ColorRole + @param mode Color mode (currently 0 or 1, default is 0) + + @return Color as QColor + */ + QColor color_value (const gui_pref& pref, int mode = 0) const; - @return Color as QColor - */ - QColor get_color_value (const QVariant& def, int mode = 0) const; + /*! + Writing a color to the gui_settings taking possible color modes + into account. When @p mode is not zero (standard mode), the + extension related to the mode is appended to the settings key string - /*! - Reading a color from the gui_settings taking possible color modes - into account. The default value for a second color mode @p mode=1 is - deterimined from the standard default value @p mode=0 by inverting - the lightness (see get_color_value()) + @param pref gui preference where the color should be written + @param color QColor to write to the settings + @param mode Color mode (currently 0 or 1, default is 0) - @param pref gui preference (key string, default value); the default - value can be given by QColor or QPalette::ColorRole - @param mode Color mode (currently 0 or 1, default is 0) + */ + void set_color_value (const gui_pref& pref, const QColor& color, + int mode = 0); - @return Color as QColor - */ - QColor color_value (const gui_pref& pref, int mode = 0) const; + QString sc_value (const sc_pref& pref) const; - /*! - Writing a color to the gui_settings taking possible color modes - into account. When @p mode is not zero (standard mode), the - extension related to the mode is appended to the settings key string + QKeySequence sc_def_value (const sc_pref& pref) const; - @param pref gui preference where the color should be written - @param color QColor to write to the settings - @param mode Color mode (currently 0 or 1, default is 0) + // config_icon_theme, icon, get_default_font_family, + // get_default_font, and possibly reload and check could be global + // functions instead of member functions. But at least for the icon + // function, defining it as a member function means that we can + // create a single gui_settings object and access multiple icon + // objects rather than having to create a separate settings object + // each time that an icon is needed. OTOH, creating the base + // QSettings object is supposed to be fast, so that may not matter. + // Hmm. + + void config_icon_theme (void); - */ - void set_color_value (const gui_pref& pref, const QColor& color, - int mode = 0); + QIcon icon (const QString& icon_name, bool octave_only = false, + const QString& icon_alt_name = QString ()); + + QString get_default_font_family (void); + + QStringList get_default_font (void); - QString sc_value (const sc_pref& pref) const; + void reload (void); - QKeySequence sc_def_value (const sc_pref& pref) const; + private: -}; + void check (void); + }; OCTAVE_END_NAMESPACE(octave) @@ -134,3 +169,4 @@ const int settings_reload_default_colors_flag = -1; #endif + diff -r 29d734430e5f -r deb553ac2c54 libgui/src/history-dock-widget.cc --- a/libgui/src/history-dock-widget.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/history-dock-widget.cc Tue Dec 06 15:45:27 2022 -0500 @@ -38,6 +38,7 @@ #include "gui-preferences-cs.h" #include "gui-preferences-global.h" #include "gui-preferences-hw.h" +#include "gui-settings.h" #include "history-dock-widget.h" #include "octave-qobject.h" @@ -47,329 +48,325 @@ OCTAVE_BEGIN_NAMESPACE(octave) -history_dock_widget::history_dock_widget (QWidget *p, base_qobject& oct_qobj) -: octave_dock_widget ("HistoryDockWidget", p, oct_qobj) -{ - setStatusTip (tr ("Browse and search the command history.")); + history_dock_widget::history_dock_widget (QWidget *p, base_qobject& oct_qobj) + : octave_dock_widget ("HistoryDockWidget", p, oct_qobj) + { + setStatusTip (tr ("Browse and search the command history.")); - construct (); + construct (); - if (! p) - make_window (); -} + if (! p) + make_window (); + } -void history_dock_widget::set_history (const QStringList& hist) -{ - m_history_model->setStringList (hist); - m_history_list_view->scrollToBottom (); -} + void history_dock_widget::set_history (const QStringList& hist) + { + m_history_model->setStringList (hist); + m_history_list_view->scrollToBottom (); + } -void history_dock_widget::append_history (const QString& hist_entry) -{ - QStringList lst = m_history_model->stringList (); - lst.append (hist_entry); + void history_dock_widget::append_history (const QString& hist_entry) + { + QStringList lst = m_history_model->stringList (); + lst.append (hist_entry); - QScrollBar *scroll_bar = m_history_list_view->verticalScrollBar (); + QScrollBar *scroll_bar = m_history_list_view->verticalScrollBar (); - bool at_bottom = scroll_bar->maximum () - scroll_bar->value () < 1; + bool at_bottom = scroll_bar->maximum () - scroll_bar->value () < 1; - m_history_model->setStringList (lst); + m_history_model->setStringList (lst); - // Scroll if slider position at bottom. - if (at_bottom) - m_history_list_view->scrollToBottom (); -} + // Scroll if slider position at bottom. + if (at_bottom) + m_history_list_view->scrollToBottom (); + } -void history_dock_widget::clear_history (void) -{ - m_history_model->setStringList (QStringList ()); -} + void history_dock_widget::clear_history (void) + { + m_history_model->setStringList (QStringList ()); + } -void history_dock_widget::save_settings (void) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + void history_dock_widget::save_settings (void) + { + gui_settings settings; - if (! settings) - return; + settings.setValue (hw_filter_active.key, m_filter_checkbox->isChecked ()); + settings.setValue (hw_filter_shown.key, m_filter_shown); - settings->setValue (hw_filter_active.key, m_filter_checkbox->isChecked ()); - settings->setValue (hw_filter_shown.key, m_filter_shown); + QStringList mru; + for (int i = 0; i < m_filter->count (); i++) + mru.append (m_filter->itemText (i)); + settings.setValue (hw_mru_list.key, mru); - QStringList mru; - for (int i = 0; i < m_filter->count (); i++) - mru.append (m_filter->itemText (i)); - settings->setValue (hw_mru_list.key, mru); + settings.sync (); - settings->sync (); - - octave_dock_widget::save_settings (); -} + octave_dock_widget::save_settings (); + } -void history_dock_widget::update_filter_history (void) -{ - QString text = m_filter->currentText (); // get current text - int index = m_filter->findText (text); // and its actual index + void history_dock_widget::update_filter_history (void) + { + QString text = m_filter->currentText (); // get current text + int index = m_filter->findText (text); // and its actual index - if (index > -1) - m_filter->removeItem (index); // remove if already existing + if (index > -1) + m_filter->removeItem (index); // remove if already existing - m_filter->insertItem (0, text); // (re)insert at beginning - m_filter->setCurrentIndex (0); -} + m_filter->insertItem (0, text); // (re)insert at beginning + m_filter->setCurrentIndex (0); + } -void history_dock_widget::set_filter_focus (bool focus) -{ - if (focus) - { - m_filter->setFocus (); - setFocusProxy (m_filter); - } - else - { - m_history_list_view->setFocus (); - setFocusProxy (m_history_list_view); - } -} + void history_dock_widget::set_filter_focus (bool focus) + { + if (focus) + { + m_filter->setFocus (); + setFocusProxy (m_filter); + } + else + { + m_history_list_view->setFocus (); + setFocusProxy (m_history_list_view); + } + } -void history_dock_widget::filter_activate (bool state) -{ - m_filter->setEnabled (state); - m_sort_filter_proxy_model.setDynamicSortFilter (state); + void history_dock_widget::filter_activate (bool state) + { + m_filter->setEnabled (state); + m_sort_filter_proxy_model.setDynamicSortFilter (state); - if (state) - m_sort_filter_proxy_model.setFilterWildcard (m_filter->currentText ()); - else - m_sort_filter_proxy_model.setFilterWildcard (QString ()); + if (state) + m_sort_filter_proxy_model.setFilterWildcard (m_filter->currentText ()); + else + m_sort_filter_proxy_model.setFilterWildcard (QString ()); - set_filter_focus (state); -} + set_filter_focus (state); + } -void history_dock_widget::ctxMenu (const QPoint& xpos) -{ - QMenu menu (this); + void history_dock_widget::ctxMenu (const QPoint& xpos) + { + QMenu menu (this); - QModelIndex index = m_history_list_view->indexAt (xpos); + QModelIndex index = m_history_list_view->indexAt (xpos); - if (index.isValid () && index.column () == 0) - { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + if (index.isValid () && index.column () == 0) + { + gui_settings settings; - menu.addAction (rmgr.icon ("edit-copy"), tr ("Copy"), this, - &history_dock_widget::handle_contextmenu_copy); - menu.addAction (tr ("Evaluate"), this, - &history_dock_widget::handle_contextmenu_evaluate); - menu.addAction (rmgr.icon ("document-new"), tr ("Create script"), this, - &history_dock_widget::handle_contextmenu_create_script); - } - if (m_filter_shown) - menu.addAction (tr ("Hide filter"), this, - &history_dock_widget::handle_contextmenu_filter); - else - menu.addAction (tr ("Show filter"), this, - &history_dock_widget::handle_contextmenu_filter); + menu.addAction (settings.icon ("edit-copy"), tr ("Copy"), this, + &history_dock_widget::handle_contextmenu_copy); + menu.addAction (tr ("Evaluate"), this, + &history_dock_widget::handle_contextmenu_evaluate); + menu.addAction (settings.icon ("document-new"), tr ("Create script"), this, + &history_dock_widget::handle_contextmenu_create_script); + } + if (m_filter_shown) + menu.addAction (tr ("Hide filter"), this, + &history_dock_widget::handle_contextmenu_filter); + else + menu.addAction (tr ("Show filter"), this, + &history_dock_widget::handle_contextmenu_filter); - menu.exec (m_history_list_view->mapToGlobal (xpos)); -} + menu.exec (m_history_list_view->mapToGlobal (xpos)); + } -void history_dock_widget::handle_double_click (QModelIndex modelIndex) -{ - emit command_double_clicked (modelIndex.data ().toString ()); -} + void history_dock_widget::handle_double_click (QModelIndex modelIndex) + { + emit command_double_clicked (modelIndex.data ().toString ()); + } -void history_dock_widget::handle_contextmenu_copy (bool) -{ - QString text; - QItemSelectionModel *selectionModel = m_history_list_view->selectionModel (); - QModelIndexList rows = selectionModel->selectedRows (); - bool prev_valid_row = false; - for (auto it = rows.begin (); it != rows.end (); it++) - { - if ((*it).isValid ()) - { - if (prev_valid_row) - text += '\n'; - text += (*it).data ().toString (); - prev_valid_row = true; - } - } - QApplication::clipboard ()->setText (text); -} + void history_dock_widget::handle_contextmenu_copy (bool) + { + QString text; + QItemSelectionModel *selectionModel = m_history_list_view->selectionModel (); + QModelIndexList rows = selectionModel->selectedRows (); + bool prev_valid_row = false; + for (auto it = rows.begin (); it != rows.end (); it++) + { + if ((*it).isValid ()) + { + if (prev_valid_row) + text += '\n'; + text += (*it).data ().toString (); + prev_valid_row = true; + } + } + QApplication::clipboard ()->setText (text); + } -void history_dock_widget::handle_contextmenu_evaluate (bool) -{ - QItemSelectionModel *selectionModel = m_history_list_view->selectionModel (); - QModelIndexList rows = selectionModel->selectedRows (); - for (auto it = rows.begin () ; it != rows.end (); it++) - { - if ((*it).isValid ()) - emit command_double_clicked ((*it).data ().toString ()); - } -} + void history_dock_widget::handle_contextmenu_evaluate (bool) + { + QItemSelectionModel *selectionModel = m_history_list_view->selectionModel (); + QModelIndexList rows = selectionModel->selectedRows (); + for (auto it = rows.begin () ; it != rows.end (); it++) + { + if ((*it).isValid ()) + emit command_double_clicked ((*it).data ().toString ()); + } + } -void history_dock_widget::handle_contextmenu_create_script (bool) -{ - QString text; - QItemSelectionModel *selectionModel = m_history_list_view->selectionModel (); - QModelIndexList rows = selectionModel->selectedRows (); + void history_dock_widget::handle_contextmenu_create_script (bool) + { + QString text; + QItemSelectionModel *selectionModel = m_history_list_view->selectionModel (); + QModelIndexList rows = selectionModel->selectedRows (); - bool prev_valid_row = false; - for (auto it = rows.begin (); it != rows.end (); it++) - { - if ((*it).isValid ()) - { - if (prev_valid_row) - text += '\n'; - text += (*it).data ().toString (); - prev_valid_row = true; - } - } + bool prev_valid_row = false; + for (auto it = rows.begin (); it != rows.end (); it++) + { + if ((*it).isValid ()) + { + if (prev_valid_row) + text += '\n'; + text += (*it).data ().toString (); + prev_valid_row = true; + } + } - if (text.length () > 0) - emit command_create_script (text); -} + if (text.length () > 0) + emit command_create_script (text); + } -void history_dock_widget::handle_contextmenu_filter (void) -{ - m_filter_shown = ! m_filter_shown; - m_filter_widget->setVisible (m_filter_shown); + void history_dock_widget::handle_contextmenu_filter (void) + { + m_filter_shown = ! m_filter_shown; + m_filter_widget->setVisible (m_filter_shown); - set_filter_focus (m_filter_shown && m_filter_checkbox->isChecked ()) ; -} + set_filter_focus (m_filter_shown && m_filter_checkbox->isChecked ()) ; + } -void history_dock_widget::copyClipboard (void) -{ - if (m_history_list_view->hasFocus ()) - handle_contextmenu_copy (true); - if (m_filter->lineEdit ()->hasFocus () - && m_filter->lineEdit ()->hasSelectedText ()) - { - QClipboard *clipboard = QApplication::clipboard (); - clipboard->setText (m_filter->lineEdit ()->selectedText ()); - } -} + void history_dock_widget::copyClipboard (void) + { + if (m_history_list_view->hasFocus ()) + handle_contextmenu_copy (true); + if (m_filter->lineEdit ()->hasFocus () + && m_filter->lineEdit ()->hasSelectedText ()) + { + QClipboard *clipboard = QApplication::clipboard (); + clipboard->setText (m_filter->lineEdit ()->selectedText ()); + } + } -void history_dock_widget::pasteClipboard (void) -{ - if (m_filter->lineEdit ()->hasFocus ()) - { - QClipboard *clipboard = QApplication::clipboard (); - QString str = clipboard->text (); - if (str.length () > 0) - m_filter->lineEdit ()->insert (str); - } -} + void history_dock_widget::pasteClipboard (void) + { + if (m_filter->lineEdit ()->hasFocus ()) + { + QClipboard *clipboard = QApplication::clipboard (); + QString str = clipboard->text (); + if (str.length () > 0) + m_filter->lineEdit ()->insert (str); + } + } -void history_dock_widget::selectAll (void) -{ - if (m_filter->lineEdit ()->hasFocus ()) - m_filter->lineEdit ()->selectAll (); + void history_dock_widget::selectAll (void) + { + if (m_filter->lineEdit ()->hasFocus ()) + m_filter->lineEdit ()->selectAll (); - if (m_history_list_view->hasFocus ()) - m_history_list_view->selectAll (); -} + if (m_history_list_view->hasFocus ()) + m_history_list_view->selectAll (); + } -void history_dock_widget::handle_visibility (bool visible) -{ - octave_dock_widget::handle_visibility (visible); + void history_dock_widget::handle_visibility (bool visible) + { + octave_dock_widget::handle_visibility (visible); - if (visible) - { - int filter_state = m_filter_checkbox->isChecked (); - filter_activate (filter_state); - } -} + if (visible) + { + int filter_state = m_filter_checkbox->isChecked (); + filter_activate (filter_state); + } + } -void history_dock_widget::construct (void) -{ - m_history_model = new QStringListModel (); - m_sort_filter_proxy_model.setSourceModel (m_history_model); - m_history_list_view = new QListView (this); - m_history_list_view->setModel (&m_sort_filter_proxy_model); - m_history_list_view->setAlternatingRowColors (true); - m_history_list_view->setEditTriggers (QAbstractItemView::NoEditTriggers); - m_history_list_view->setStatusTip - (tr ("Double-click a command to transfer it to the Command Window.")); - m_history_list_view->setSelectionMode (QAbstractItemView::ExtendedSelection); - m_history_list_view->setContextMenuPolicy (Qt::CustomContextMenu); - connect (m_history_list_view, &QListView::customContextMenuRequested, - this, &history_dock_widget::ctxMenu); + void history_dock_widget::construct (void) + { + m_history_model = new QStringListModel (); + m_sort_filter_proxy_model.setSourceModel (m_history_model); + m_history_list_view = new QListView (this); + m_history_list_view->setModel (&m_sort_filter_proxy_model); + m_history_list_view->setAlternatingRowColors (true); + m_history_list_view->setEditTriggers (QAbstractItemView::NoEditTriggers); + m_history_list_view->setStatusTip + (tr ("Double-click a command to transfer it to the Command Window.")); + m_history_list_view->setSelectionMode (QAbstractItemView::ExtendedSelection); + m_history_list_view->setContextMenuPolicy (Qt::CustomContextMenu); + connect (m_history_list_view, &QListView::customContextMenuRequested, + this, &history_dock_widget::ctxMenu); - m_filter = new QComboBox (this); - m_filter->setToolTip (tr ("Enter text to filter the command history")); - m_filter->setEditable (true); - m_filter->setMaxCount (MaxFilterHistory); - m_filter->setInsertPolicy (QComboBox::NoInsert); - m_filter->setSizeAdjustPolicy - (QComboBox::AdjustToMinimumContentsLengthWithIcon); - QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred); - m_filter->setSizePolicy (sizePol); - m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive); + m_filter = new QComboBox (this); + m_filter->setToolTip (tr ("Enter text to filter the command history")); + m_filter->setEditable (true); + m_filter->setMaxCount (MaxFilterHistory); + m_filter->setInsertPolicy (QComboBox::NoInsert); + m_filter->setSizeAdjustPolicy + (QComboBox::AdjustToMinimumContentsLengthWithIcon); + QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred); + m_filter->setSizePolicy (sizePol); + m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive); - QLabel *filter_label = new QLabel (tr ("Filter")); + QLabel *filter_label = new QLabel (tr ("Filter")); - m_filter_checkbox = new QCheckBox (); + m_filter_checkbox = new QCheckBox (); - set_title (tr ("Command History")); - setWidget (new QWidget ()); + set_title (tr ("Command History")); + setWidget (new QWidget ()); - m_filter_widget = new QWidget (this); - QHBoxLayout *filter_layout = new QHBoxLayout (); - filter_layout->addWidget (filter_label); - filter_layout->addWidget (m_filter_checkbox); - filter_layout->addWidget (m_filter); - filter_layout->setMargin(0); - m_filter_widget->setLayout (filter_layout); + m_filter_widget = new QWidget (this); + QHBoxLayout *filter_layout = new QHBoxLayout (); + filter_layout->addWidget (filter_label); + filter_layout->addWidget (m_filter_checkbox); + filter_layout->addWidget (m_filter); + filter_layout->setMargin(0); + m_filter_widget->setLayout (filter_layout); - QVBoxLayout *hist_layout = new QVBoxLayout (); - hist_layout->addWidget (m_filter_widget); - hist_layout->addWidget (m_history_list_view); + QVBoxLayout *hist_layout = new QVBoxLayout (); + hist_layout->addWidget (m_filter_widget); + hist_layout->addWidget (m_history_list_view); - hist_layout->setMargin (2); - hist_layout->setSpacing (0); - widget ()->setLayout (hist_layout); + hist_layout->setMargin (2); + hist_layout->setSpacing (0); + widget ()->setLayout (hist_layout); - // Init state of the filter - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + // Init state of the filter + + gui_settings settings; - m_filter_shown - = settings->value (hw_filter_shown).toBool (); - m_filter_widget->setVisible (m_filter_shown); + m_filter_shown = settings.value (hw_filter_shown).toBool (); + m_filter_widget->setVisible (m_filter_shown); - m_filter->addItems (settings->value (hw_mru_list).toStringList ()); + m_filter->addItems (settings.value (hw_mru_list).toStringList ()); - bool filter_state - = settings->value (hw_filter_active).toBool (); - m_filter_checkbox->setChecked (filter_state); - filter_activate (filter_state); + bool filter_state = settings.value (hw_filter_active).toBool (); + m_filter_checkbox->setChecked (filter_state); + filter_activate (filter_state); - // Connect signals and slots - connect (m_filter, &QComboBox::editTextChanged, - &m_sort_filter_proxy_model, - &QSortFilterProxyModel::setFilterWildcard); - connect (m_filter_checkbox, &QCheckBox::toggled, - this, &history_dock_widget::filter_activate); - connect (m_filter->lineEdit (), &QLineEdit::editingFinished, - this, &history_dock_widget::update_filter_history); + // Connect signals and slots + connect (m_filter, &QComboBox::editTextChanged, + &m_sort_filter_proxy_model, + &QSortFilterProxyModel::setFilterWildcard); + connect (m_filter_checkbox, &QCheckBox::toggled, + this, &history_dock_widget::filter_activate); + connect (m_filter->lineEdit (), &QLineEdit::editingFinished, + this, &history_dock_widget::update_filter_history); - connect (m_history_list_view, &QListView::doubleClicked, - this, &history_dock_widget::handle_double_click); + connect (m_history_list_view, &QListView::doubleClicked, + this, &history_dock_widget::handle_double_click); + + m_history_list_view->setTextElideMode (Qt::ElideRight); + } - m_history_list_view->setTextElideMode (Qt::ElideRight); -} + void history_dock_widget::notice_settings (void) + { + gui_settings settings; -void history_dock_widget::notice_settings (const gui_settings *settings) -{ - QFont font = QFont (); + QFont font = QFont (); - font.setStyleHint (QFont::TypeWriter); - QString default_font = settings->value (global_mono_font).toString (); + font.setStyleHint (QFont::TypeWriter); + QString default_font = settings.value (global_mono_font).toString (); - font.setFamily (settings->value (cs_font.key, default_font).toString ()); - font.setPointSize (settings->value (cs_font_size).toInt ()); + font.setFamily (settings.value (cs_font.key, default_font).toString ()); + font.setPointSize (settings.value (cs_font_size).toInt ()); - m_history_list_view->setFont (font); -} + m_history_list_view->setFont (font); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/history-dock-widget.h --- a/libgui/src/history-dock-widget.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/history-dock-widget.h Tue Dec 06 15:45:27 2022 -0500 @@ -37,75 +37,75 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; + class base_qobject; -class history_dock_widget : public octave_dock_widget -{ - Q_OBJECT + class history_dock_widget : public octave_dock_widget + { + Q_OBJECT -public: + public: - history_dock_widget (QWidget *parent, base_qobject& oct_qobj); + history_dock_widget (QWidget *parent, base_qobject& oct_qobj); - ~history_dock_widget (void) = default; + ~history_dock_widget (void) = default; -signals: + signals: - //! Signal emitted whenever the user double-clicks a command in the - //! history. + //! Signal emitted whenever the user double-clicks a command in the + //! history. - void command_double_clicked (const QString& command); + void command_double_clicked (const QString& command); - //! Signal emitted whenever the user selects commands and chooses - //! "Create script" from the popup menu. + //! Signal emitted whenever the user selects commands and chooses + //! "Create script" from the popup menu. - void command_create_script (const QString& commands); + void command_create_script (const QString& commands); -public slots: + public slots: - void set_history (const QStringList& hist); - void append_history (const QString& hist_entry); - void clear_history (void); - void save_settings (void); - void notice_settings (const gui_settings *); + void set_history (const QStringList& hist); + void append_history (const QString& hist_entry); + void clear_history (void); + void save_settings (void); + void notice_settings (void); -private slots: + private slots: - void update_filter_history (void); - void filter_activate (bool enable); + void update_filter_history (void); + void filter_activate (bool enable); - void ctxMenu (const QPoint& pos); - void handle_double_click (QModelIndex modelIndex); - void handle_contextmenu_copy (bool flag); - void handle_contextmenu_evaluate (bool flag); - void handle_contextmenu_create_script (bool flag); - void handle_contextmenu_filter (void); + void ctxMenu (const QPoint& pos); + void handle_double_click (QModelIndex modelIndex); + void handle_contextmenu_copy (bool flag); + void handle_contextmenu_evaluate (bool flag); + void handle_contextmenu_create_script (bool flag); + void handle_contextmenu_filter (void); - void copyClipboard (void); - void pasteClipboard (void); - void selectAll (void); + void copyClipboard (void); + void pasteClipboard (void); + void selectAll (void); - virtual void handle_visibility (bool visible); + virtual void handle_visibility (bool visible); -private: + private: - void construct (void); - void set_filter_focus (bool focus); + void construct (void); + void set_filter_focus (bool focus); - QListView *m_history_list_view; - QSortFilterProxyModel m_sort_filter_proxy_model; + QListView *m_history_list_view; + QSortFilterProxyModel m_sort_filter_proxy_model; - //! Stores the current history_model. + //! Stores the current history_model. - QStringListModel *m_history_model; + QStringListModel *m_history_model; - QCheckBox *m_filter_checkbox; - QComboBox *m_filter; - QWidget *m_filter_widget; - bool m_filter_shown; + QCheckBox *m_filter_checkbox; + QComboBox *m_filter; + QWidget *m_filter_widget; + bool m_filter_shown; - enum { MaxFilterHistory = 10 }; -}; + enum { MaxFilterHistory = 10 }; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/interpreter-qobject.cc --- a/libgui/src/interpreter-qobject.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/interpreter-qobject.cc Tue Dec 06 15:45:27 2022 -0500 @@ -38,166 +38,166 @@ OCTAVE_BEGIN_NAMESPACE(octave) -interpreter_qobject::interpreter_qobject (base_qobject& oct_qobj) -: QObject (), m_octave_qobj (oct_qobj), m_interpreter (nullptr) -{ } + interpreter_qobject::interpreter_qobject (base_qobject& oct_qobj) + : QObject (), m_octave_qobj (oct_qobj), m_interpreter (nullptr) + { } -void interpreter_qobject::execute (void) -{ - // The Octave application context owns the interpreter. + void interpreter_qobject::execute (void) + { + // The Octave application context owns the interpreter. - qt_application& app_context = m_octave_qobj.app_context (); + qt_application& app_context = m_octave_qobj.app_context (); - interpreter& interp = app_context.create_interpreter (); + interpreter& interp = app_context.create_interpreter (); - event_manager& evmgr = interp.get_event_manager (); + event_manager& evmgr = interp.get_event_manager (); - evmgr.connect_link (m_octave_qobj.get_qt_interpreter_events ()); - evmgr.install_qt_event_handlers (m_octave_qobj.get_qt_interpreter_events ()); - evmgr.enable (); + evmgr.connect_link (m_octave_qobj.get_qt_interpreter_events ()); + evmgr.install_qt_event_handlers (m_octave_qobj.get_qt_interpreter_events ()); + evmgr.enable (); - int exit_status = 0; + int exit_status = 0; - try - { - // Final initialization. + try + { + // Final initialization. - interp.initialize (); + interp.initialize (); - if (app_context.start_gui_p () - && ! m_octave_qobj.experimental_terminal_widget ()) - { - input_system& input_sys = interp.get_input_system (); + if (app_context.start_gui_p () + && ! m_octave_qobj.experimental_terminal_widget ()) + { + input_system& input_sys = interp.get_input_system (); - input_sys.PS1 (">> "); - input_sys.PS2 (""); - } + input_sys.PS1 (">> "); + input_sys.PS2 (""); + } - if (interp.initialized ()) - { - // The interpreter should be completely ready at this point so let - // the GUI know. + if (interp.initialized ()) + { + // The interpreter should be completely ready at this point so let + // the GUI know. - m_interpreter = &interp; + m_interpreter = &interp; - emit ready (); + emit ready (); - graphics_init (interp, m_octave_qobj); + graphics_init (interp); - // Start executing commands in the command window. + // Start executing commands in the command window. - exit_status = interp.execute (); - } - } - catch (const exit_exception& xe) - { - exit_status = xe.exit_status (); - } + exit_status = interp.execute (); + } + } + catch (const exit_exception& xe) + { + exit_status = xe.exit_status (); + } - // FIXME: The following comment doesn't seem to make sense now. + // FIXME: The following comment doesn't seem to make sense now. - // Signal that the interpreter is done executing code in the - // main REPL, from script files, or command line eval arguments. - // By using a signal here, we give the GUI a chance to process - // any pending events, then signal that it is safe to shutdown - // the interpreter. Our notification here allows the GUI to - // insert the request to shutdown the interpreter in the event - // queue after any other pending signals. The application - // context owns the interpreter and will be responsible for - // deleting it later, when the application object destructor is - // executed. + // Signal that the interpreter is done executing code in the + // main REPL, from script files, or command line eval arguments. + // By using a signal here, we give the GUI a chance to process + // any pending events, then signal that it is safe to shutdown + // the interpreter. Our notification here allows the GUI to + // insert the request to shutdown the interpreter in the event + // queue after any other pending signals. The application + // context owns the interpreter and will be responsible for + // deleting it later, when the application object destructor is + // executed. - emit shutdown_finished (exit_status); -} + emit shutdown_finished (exit_status); + } -void interpreter_qobject::interpreter_event (const fcn_callback& fcn) -{ - if (! m_interpreter) - return; + void interpreter_qobject::interpreter_event (const fcn_callback& fcn) + { + if (! m_interpreter) + return; - event_manager& evmgr = m_interpreter->get_event_manager (); + event_manager& evmgr = m_interpreter->get_event_manager (); - evmgr.post_event (fcn); -} + evmgr.post_event (fcn); + } -void interpreter_qobject::interpreter_event (const meth_callback& meth) -{ - if (! m_interpreter) - return; + void interpreter_qobject::interpreter_event (const meth_callback& meth) + { + if (! m_interpreter) + return; - event_manager& evmgr = m_interpreter->get_event_manager (); + event_manager& evmgr = m_interpreter->get_event_manager (); - evmgr.post_event (meth); -} + evmgr.post_event (meth); + } -void interpreter_qobject::interrupt (void) -{ - if (! m_interpreter) - return; + void interpreter_qobject::interrupt (void) + { + if (! m_interpreter) + return; - // The following is a direct function call across threads. - // We need to ensure that it uses thread-safe functions. + // The following is a direct function call across threads. + // We need to ensure that it uses thread-safe functions. - m_interpreter->interrupt (); -} + m_interpreter->interrupt (); + } -void interpreter_qobject::pause (void) -{ - // FIXME: Should we make this action work with the old terminal - // widget? + void interpreter_qobject::pause (void) + { + // FIXME: Should we make this action work with the old terminal + // widget? - if (m_octave_qobj.experimental_terminal_widget ()) - { - if (! m_interpreter) - return; + if (m_octave_qobj.experimental_terminal_widget ()) + { + if (! m_interpreter) + return; - // The following is a direct function call across threads. - // We need to ensure that it uses thread-safe functions. + // The following is a direct function call across threads. + // We need to ensure that it uses thread-safe functions. - m_interpreter->pause (); - } -} + m_interpreter->pause (); + } + } -void interpreter_qobject::stop (void) -{ - // FIXME: Should we make this action work with the old terminal - // widget? + void interpreter_qobject::stop (void) + { + // FIXME: Should we make this action work with the old terminal + // widget? - if (m_octave_qobj.experimental_terminal_widget ()) - { - if (! m_interpreter) - return; + if (m_octave_qobj.experimental_terminal_widget ()) + { + if (! m_interpreter) + return; - // The following is a direct function call across threads. - // We need to ensure that it uses thread-safe functions. + // The following is a direct function call across threads. + // We need to ensure that it uses thread-safe functions. - m_interpreter->stop (); - } -} + m_interpreter->stop (); + } + } -void interpreter_qobject::resume (void) -{ - // FIXME: Should we make this action work with the old terminal - // widget? + void interpreter_qobject::resume (void) + { + // FIXME: Should we make this action work with the old terminal + // widget? - if (m_octave_qobj.experimental_terminal_widget ()) - { - // FIXME: This action should only be available when the - // interpreter is paused. + if (m_octave_qobj.experimental_terminal_widget ()) + { + // FIXME: This action should only be available when the + // interpreter is paused. - interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD + interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD - interp.resume (); - }); - } -} + interp.resume (); + }); + } + } -qt_interpreter_events *interpreter_qobject::qt_link (void) -{ - return m_octave_qobj.qt_link (); -} + qt_interpreter_events *interpreter_qobject::qt_link (void) + { + return m_octave_qobj.qt_link (); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/m-editor/file-editor-interface.h --- a/libgui/src/m-editor/file-editor-interface.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/m-editor/file-editor-interface.h Tue Dec 06 15:45:27 2022 -0500 @@ -30,77 +30,76 @@ #include #include -#include "gui-settings.h" #include "octave-dock-widget.h" OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; + class base_qobject; -class file_editor_interface : public octave_dock_widget -{ - Q_OBJECT + class file_editor_interface : public octave_dock_widget + { + Q_OBJECT -public: + public: - file_editor_interface (QWidget *p, base_qobject& oct_qobj) - : octave_dock_widget ("FileEditor", p, oct_qobj) - { } + file_editor_interface (QWidget *p, base_qobject& oct_qobj) + : octave_dock_widget ("FileEditor", p, oct_qobj) + { } - virtual ~file_editor_interface (void) = default; + virtual ~file_editor_interface (void) = default; - virtual QMenu * get_mru_menu (void) = 0; - virtual QMenu * debug_menu (void) = 0; - virtual QToolBar * toolbar (void) = 0; - virtual QMenuBar * menubar (void) = 0; + virtual QMenu * get_mru_menu (void) = 0; + virtual QMenu * debug_menu (void) = 0; + virtual QToolBar * toolbar (void) = 0; + virtual QMenuBar * menubar (void) = 0; - virtual void insert_global_actions (QList) = 0; - virtual void handle_enter_debug_mode (void) = 0; - virtual void handle_exit_debug_mode (void) = 0; + virtual void insert_global_actions (QList) = 0; + virtual void handle_enter_debug_mode (void) = 0; + virtual void handle_exit_debug_mode (void) = 0; - virtual void - handle_insert_debugger_pointer_request (const QString& file, int line) = 0; + virtual void + handle_insert_debugger_pointer_request (const QString& file, int line) = 0; - virtual void - handle_delete_debugger_pointer_request (const QString& file, int line) = 0; + virtual void + handle_delete_debugger_pointer_request (const QString& file, int line) = 0; - virtual void - handle_update_breakpoint_marker_request (bool insert, const QString& file, - int line, const QString& cond) = 0; + virtual void + handle_update_breakpoint_marker_request (bool insert, const QString& file, + int line, const QString& cond) = 0; - virtual void handle_edit_file_request (const QString& file) = 0; + virtual void handle_edit_file_request (const QString& file) = 0; - virtual bool check_closing (void) = 0; + virtual bool check_closing (void) = 0; - virtual void empty_script (bool, bool) = 0; + virtual void empty_script (bool, bool) = 0; - virtual void restore_session (gui_settings *) = 0; + virtual void restore_session (void) = 0; - virtual void enable_menu_shortcuts (bool enable) = 0; + virtual void enable_menu_shortcuts (bool enable) = 0; -signals: + signals: - void interpreter_event (const fcn_callback& fcn); - void interpreter_event (const meth_callback& meth); + void interpreter_event (const fcn_callback& fcn); + void interpreter_event (const meth_callback& meth); -public slots: + public slots: - virtual void toplevel_change (bool) = 0; + virtual void toplevel_change (bool) = 0; - virtual void handle_file_remove (const QString& o, const QString& n) = 0; + virtual void handle_file_remove (const QString& o, const QString& n) = 0; - virtual void request_new_file (const QString& command = QString ()) = 0; + virtual void request_new_file (const QString& command = QString ()) = 0; - virtual void request_open_file (const QString& openFileName, - const QString& encoding = QString (), - int line = -1, - bool debug_pointer = false, - bool breakpoint_marker = false, - bool insert = true, - const QString& cond = "", - int index = -1, - const QString& bookmarks = QString ()) = 0; -}; + virtual void request_open_file (const QString& openFileName, + const QString& encoding = QString (), + int line = -1, + bool debug_pointer = false, + bool breakpoint_marker = false, + bool insert = true, + const QString& cond = "", + int index = -1, + const QString& bookmarks = QString ()) = 0; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/m-editor/file-editor-tab.cc --- a/libgui/src/m-editor/file-editor-tab.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/m-editor/file-editor-tab.cc Tue Dec 06 15:45:27 2022 -0500 @@ -71,6 +71,7 @@ #include "gui-preferences-cs.h" #include "gui-preferences-ed.h" #include "gui-preferences-global.h" +#include "gui-settings.h" #include "gui-utils.h" #include "marker.h" #include "octave-qobject.h" @@ -97,3202 +98,3199 @@ OCTAVE_BEGIN_NAMESPACE(octave) -//! A file_editor_tab object consists of a text area and three left margins. -//! The first holds breakpoints, bookmarks, and the debug program counter. -//! The second holds line numbers. The third holds "fold" marks, to hide -//! sections of text. - -// Make parent null for the file editor tab so that warning WindowModal -// messages don't affect grandparents. -file_editor_tab::file_editor_tab (base_qobject& oct_qobj, - const QString& directory_arg) -: m_octave_qobj (oct_qobj) -{ - m_lexer_apis = nullptr; - m_is_octave_file = true; - m_lines_changed = false; - m_autoc_active = false; - - m_ced = directory_arg; - - m_file_name = ""; - m_file_system_watcher.setObjectName ("_qt_autotest_force_engine_poller"); - - m_edit_area = new octave_qscintilla (this, m_octave_qobj); - m_line = 0; - m_col = 0; - - m_bp_lines.clear (); // start with empty lists of breakpoints - m_bp_conditions.clear (); - m_bp_restore_count = 0; - - m_breakpoint_info.remove_next = false; - m_breakpoint_info.remove_line = -1; - - // Initialize last modification date to now - m_last_modified = QDateTime::currentDateTimeUtc(); - - connect (m_edit_area, SIGNAL (cursorPositionChanged (int, int)), - this, SLOT (handle_cursor_moved (int,int))); - - connect (m_edit_area, SIGNAL (SCN_CHARADDED (int)), - this, SLOT (handle_char_added (int))); - - connect (m_edit_area, SIGNAL (SCN_DOUBLECLICK (int, int, int)), - this, SLOT (handle_double_click (int, int, int))); - - connect (m_edit_area, SIGNAL (linesChanged ()), - this, SLOT (handle_lines_changed ())); - - connect (m_edit_area, &octave_qscintilla::context_menu_edit_signal, - this, &file_editor_tab::handle_context_menu_edit); - - connect (m_edit_area, &octave_qscintilla::update_rowcol_indicator_signal, - this, &file_editor_tab::update_rowcol_indicator); - - // create statusbar for row/col indicator and eol mode - m_status_bar = new QStatusBar (this); - - // row- and col-indicator - m_row_indicator = new QLabel ("", this); - QFontMetrics fm = m_row_indicator->fontMetrics (); - m_row_indicator->setMinimumSize (4.5*fm.averageCharWidth (), 0); - QLabel *row_label = new QLabel (tr ("line:"), this); - m_col_indicator = new QLabel ("", this); - m_col_indicator->setMinimumSize (4*fm.averageCharWidth (), 0); - QLabel *col_label = new QLabel (tr ("col:"), this); - m_status_bar->addWidget (row_label, 0); - m_status_bar->addWidget (m_row_indicator, 0); - m_status_bar->addWidget (col_label, 0); - m_status_bar->addWidget (m_col_indicator, 0); - - // status bar: encoding - QLabel *enc_label = new QLabel (tr ("encoding:"), this); - m_enc_indicator = new QLabel ("", this); - m_status_bar->addWidget (enc_label, 0); - m_status_bar->addWidget (m_enc_indicator, 0); - m_status_bar->addWidget (new QLabel (" ", this), 0); - - // status bar: eol mode - QLabel *eol_label = new QLabel (tr ("eol:"), this); - m_eol_indicator = new QLabel ("", this); - m_status_bar->addWidget (eol_label, 0); - m_status_bar->addWidget (m_eol_indicator, 0); - m_status_bar->addWidget (new QLabel (" ", this), 0); - - // symbols - m_edit_area->setMarginType (1, QsciScintilla::SymbolMargin); - m_edit_area->setMarginSensitivity (1, true); - m_edit_area->markerDefine (QsciScintilla::RightTriangle, marker::bookmark); - m_edit_area->setMarkerBackgroundColor (QColor (0, 0, 232), marker::bookmark); - m_edit_area->markerDefine (QsciScintilla::Circle, marker::breakpoint); - m_edit_area->setMarkerBackgroundColor (QColor (192, 0, 0), marker::breakpoint); - m_edit_area->markerDefine (QsciScintilla::Circle, marker::cond_break); - m_edit_area->setMarkerBackgroundColor (QColor (255, 127, 0), marker::cond_break); - m_edit_area->markerDefine (QsciScintilla::RightArrow, - marker::debugger_position); - m_edit_area->setMarkerBackgroundColor (QColor (255, 255, 0), - marker::debugger_position); - m_edit_area->markerDefine (QsciScintilla::RightArrow, - marker::unsure_debugger_position); - m_edit_area->setMarkerBackgroundColor (QColor (192, 192, 192), - marker::unsure_debugger_position); - - connect (m_edit_area, SIGNAL (marginClicked (int, int, - Qt::KeyboardModifiers)), - this, SLOT (handle_margin_clicked (int, int, - Qt::KeyboardModifiers))); - - connect (m_edit_area, &octave_qscintilla::context_menu_break_condition_signal, - this, &file_editor_tab::handle_context_menu_break_condition); - - // line numbers - m_edit_area->setMarginsForegroundColor (QColor (96, 96, 96)); - m_edit_area->setMarginsBackgroundColor (QColor (232, 232, 220)); - m_edit_area->setMarginType (2, QsciScintilla::TextMargin); - - // other features - m_edit_area->setBraceMatching (QsciScintilla::StrictBraceMatch); - m_edit_area->setAutoIndent (true); - m_edit_area->setIndentationWidth (2); - m_edit_area->setIndentationsUseTabs (false); - - m_edit_area->setUtf8 (true); - - // auto completion - m_edit_area->SendScintilla (QsciScintillaBase::SCI_AUTOCSETCANCELATSTART, false); - - QVBoxLayout *edit_area_layout = new QVBoxLayout (); - edit_area_layout->addWidget (m_edit_area); - edit_area_layout->addWidget (m_status_bar); - edit_area_layout->setMargin (0); - edit_area_layout->setSpacing (0); - setLayout (edit_area_layout); - - // Any interpreter_event signal from a file_editor_tab_widget is - // handled the same as for the parent main_window object. - - connect (m_edit_area, QOverload::of (&octave_qscintilla::interpreter_event), - this, QOverload::of (&file_editor_tab::interpreter_event)); - - connect (m_edit_area, QOverload::of (&octave_qscintilla::interpreter_event), - this, QOverload::of (&file_editor_tab::interpreter_event)); - - // connect modified signal - connect (m_edit_area, SIGNAL (modificationChanged (bool)), - this, SLOT (update_window_title (bool))); - - connect (m_edit_area, SIGNAL (copyAvailable (bool)), - this, SLOT (handle_copy_available (bool))); - - connect (&m_file_system_watcher, &QFileSystemWatcher::fileChanged, - this, [=] (const QString& path) { file_has_changed (path); }); - - connect (this, &file_editor_tab::maybe_remove_next, - this, &file_editor_tab::handle_remove_next); - - connect (this, &file_editor_tab::dbstop_if, - this, &file_editor_tab::handle_dbstop_if); - - connect (this, &file_editor_tab::request_add_breakpoint, - this, &file_editor_tab::handle_request_add_breakpoint); - - connect (this, &file_editor_tab::api_entries_added, - this, &file_editor_tab::handle_api_entries_added); - - connect (this, &file_editor_tab::confirm_dbquit_and_save_signal, - this, &file_editor_tab::confirm_dbquit_and_save); - - connect (this, &file_editor_tab::do_save_file_signal, - this, &file_editor_tab::do_save_file); - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (settings) - notice_settings (settings, true); - - // encoding, not updated with the settings - m_encoding = settings->value (ed_default_enc.key, "UTF-8").toString (); - m_enc_indicator->setText (m_encoding); - // no changes in encoding yet - m_new_encoding = m_encoding; -} - -file_editor_tab::~file_editor_tab (void) -{ - // Tell all connected markers to self-destruct. - emit remove_all_breakpoints_signal (); - emit remove_all_positions (); - - // Destroy lexer attached to m_edit_area, which is not the parent - // of lexer - QsciLexer *lexer = m_edit_area->lexer (); - if (lexer) - { - delete lexer; - m_edit_area->setLexer (nullptr); - } -} - -void file_editor_tab::set_encoding (const QString& new_encoding) -{ - if (new_encoding.isEmpty ()) - return; - - m_encoding = new_encoding; - m_enc_indicator->setText (m_encoding); - if (! m_edit_area->text ().isEmpty ()) - set_modified (true); -} - -void file_editor_tab::closeEvent (QCloseEvent *e) -{ - int save_dialog = check_file_modified (true); - if ((save_dialog == QMessageBox::Cancel) || - (save_dialog == QMessageBox::Save)) - { - // Ignore close event if file is saved or user cancels - // closing this window. In case of saving, tab is closed after - // successful saving. - e->ignore (); - } - else - { - e->accept (); - emit tab_remove_request (); - } -} - -void file_editor_tab::set_current_directory (const QString& dir) -{ - m_ced = dir; -} - -void file_editor_tab::handle_context_menu_edit (const QString& word_at_cursor) -{ - // Search for a subfunction in actual file (this is done first because - // Octave finds this function before others with the same name in the - // search path. - QRegExp rxfun1 ("^[\t ]*function[^=]+=[\t ]*" - + word_at_cursor + "[\t ]*\\([^\\)]*\\)[\t ]*$"); - QRegExp rxfun2 ("^[\t ]*function[\t ]+" - + word_at_cursor + "[\t ]*\\([^\\)]*\\)[\t ]*$"); - QRegExp rxfun3 ("^[\t ]*function[\t ]+" - + word_at_cursor + "[\t ]*$"); - QRegExp rxfun4 ("^[\t ]*function[^=]+=[\t ]*" - + word_at_cursor + "[\t ]*$"); - - int pos_fct = -1; - QStringList lines = m_edit_area->text ().split ("\n"); - - int line; - for (line = 0; line < lines.count (); line++) - { - if ((pos_fct = rxfun1.indexIn (lines.at (line))) != -1) - break; - if ((pos_fct = rxfun2.indexIn (lines.at (line))) != -1) - break; - if ((pos_fct = rxfun3.indexIn (lines.at (line))) != -1) - break; - if ((pos_fct = rxfun4.indexIn (lines.at (line))) != -1) - break; - } - - if (pos_fct > -1) - { - // reg expr. found: it is an internal function - m_edit_area->setCursorPosition (line, pos_fct); - m_edit_area->SendScintilla (2232, line); // SCI_ENSUREVISIBLE - // SCI_VISIBLEFROMDOCLINE - int vis_line = m_edit_area->SendScintilla (2220, line); - m_edit_area->SendScintilla (2613, vis_line); // SCI_SETFIRSTVISIBLELINE + //! A file_editor_tab object consists of a text area and three left margins. + //! The first holds breakpoints, bookmarks, and the debug program counter. + //! The second holds line numbers. The third holds "fold" marks, to hide + //! sections of text. + + // Make parent null for the file editor tab so that warning WindowModal + // messages don't affect grandparents. + file_editor_tab::file_editor_tab (base_qobject& oct_qobj, + const QString& directory_arg) + : m_octave_qobj (oct_qobj) + { + m_lexer_apis = nullptr; + m_is_octave_file = true; + m_lines_changed = false; + m_autoc_active = false; + + m_ced = directory_arg; + + m_file_name = ""; + m_file_system_watcher.setObjectName ("_qt_autotest_force_engine_poller"); + + m_edit_area = new octave_qscintilla (this, m_octave_qobj); + m_line = 0; + m_col = 0; + + m_bp_lines.clear (); // start with empty lists of breakpoints + m_bp_conditions.clear (); + m_bp_restore_count = 0; + + m_breakpoint_info.remove_next = false; + m_breakpoint_info.remove_line = -1; + + // Initialize last modification date to now + m_last_modified = QDateTime::currentDateTimeUtc(); + + connect (m_edit_area, SIGNAL (cursorPositionChanged (int, int)), + this, SLOT (handle_cursor_moved (int,int))); + + connect (m_edit_area, SIGNAL (SCN_CHARADDED (int)), + this, SLOT (handle_char_added (int))); + + connect (m_edit_area, SIGNAL (SCN_DOUBLECLICK (int, int, int)), + this, SLOT (handle_double_click (int, int, int))); + + connect (m_edit_area, SIGNAL (linesChanged ()), + this, SLOT (handle_lines_changed ())); + + connect (m_edit_area, &octave_qscintilla::context_menu_edit_signal, + this, &file_editor_tab::handle_context_menu_edit); + + connect (m_edit_area, &octave_qscintilla::update_rowcol_indicator_signal, + this, &file_editor_tab::update_rowcol_indicator); + + // create statusbar for row/col indicator and eol mode + m_status_bar = new QStatusBar (this); + + // row- and col-indicator + m_row_indicator = new QLabel ("", this); + QFontMetrics fm = m_row_indicator->fontMetrics (); + m_row_indicator->setMinimumSize (4.5*fm.averageCharWidth (), 0); + QLabel *row_label = new QLabel (tr ("line:"), this); + m_col_indicator = new QLabel ("", this); + m_col_indicator->setMinimumSize (4*fm.averageCharWidth (), 0); + QLabel *col_label = new QLabel (tr ("col:"), this); + m_status_bar->addWidget (row_label, 0); + m_status_bar->addWidget (m_row_indicator, 0); + m_status_bar->addWidget (col_label, 0); + m_status_bar->addWidget (m_col_indicator, 0); + + // status bar: encoding + QLabel *enc_label = new QLabel (tr ("encoding:"), this); + m_enc_indicator = new QLabel ("", this); + m_status_bar->addWidget (enc_label, 0); + m_status_bar->addWidget (m_enc_indicator, 0); + m_status_bar->addWidget (new QLabel (" ", this), 0); + + // status bar: eol mode + QLabel *eol_label = new QLabel (tr ("eol:"), this); + m_eol_indicator = new QLabel ("", this); + m_status_bar->addWidget (eol_label, 0); + m_status_bar->addWidget (m_eol_indicator, 0); + m_status_bar->addWidget (new QLabel (" ", this), 0); + + // symbols + m_edit_area->setMarginType (1, QsciScintilla::SymbolMargin); + m_edit_area->setMarginSensitivity (1, true); + m_edit_area->markerDefine (QsciScintilla::RightTriangle, marker::bookmark); + m_edit_area->setMarkerBackgroundColor (QColor (0, 0, 232), marker::bookmark); + m_edit_area->markerDefine (QsciScintilla::Circle, marker::breakpoint); + m_edit_area->setMarkerBackgroundColor (QColor (192, 0, 0), marker::breakpoint); + m_edit_area->markerDefine (QsciScintilla::Circle, marker::cond_break); + m_edit_area->setMarkerBackgroundColor (QColor (255, 127, 0), marker::cond_break); + m_edit_area->markerDefine (QsciScintilla::RightArrow, + marker::debugger_position); + m_edit_area->setMarkerBackgroundColor (QColor (255, 255, 0), + marker::debugger_position); + m_edit_area->markerDefine (QsciScintilla::RightArrow, + marker::unsure_debugger_position); + m_edit_area->setMarkerBackgroundColor (QColor (192, 192, 192), + marker::unsure_debugger_position); + + connect (m_edit_area, SIGNAL (marginClicked (int, int, + Qt::KeyboardModifiers)), + this, SLOT (handle_margin_clicked (int, int, + Qt::KeyboardModifiers))); + + connect (m_edit_area, &octave_qscintilla::context_menu_break_condition_signal, + this, &file_editor_tab::handle_context_menu_break_condition); + + // line numbers + m_edit_area->setMarginsForegroundColor (QColor (96, 96, 96)); + m_edit_area->setMarginsBackgroundColor (QColor (232, 232, 220)); + m_edit_area->setMarginType (2, QsciScintilla::TextMargin); + + // other features + m_edit_area->setBraceMatching (QsciScintilla::StrictBraceMatch); + m_edit_area->setAutoIndent (true); + m_edit_area->setIndentationWidth (2); + m_edit_area->setIndentationsUseTabs (false); + + m_edit_area->setUtf8 (true); + + // auto completion + m_edit_area->SendScintilla (QsciScintillaBase::SCI_AUTOCSETCANCELATSTART, false); + + QVBoxLayout *edit_area_layout = new QVBoxLayout (); + edit_area_layout->addWidget (m_edit_area); + edit_area_layout->addWidget (m_status_bar); + edit_area_layout->setMargin (0); + edit_area_layout->setSpacing (0); + setLayout (edit_area_layout); + + // Any interpreter_event signal from a file_editor_tab_widget is + // handled the same as for the parent main_window object. + + connect (m_edit_area, QOverload::of (&octave_qscintilla::interpreter_event), + this, QOverload::of (&file_editor_tab::interpreter_event)); + + connect (m_edit_area, QOverload::of (&octave_qscintilla::interpreter_event), + this, QOverload::of (&file_editor_tab::interpreter_event)); + + // connect modified signal + connect (m_edit_area, SIGNAL (modificationChanged (bool)), + this, SLOT (update_window_title (bool))); + + connect (m_edit_area, SIGNAL (copyAvailable (bool)), + this, SLOT (handle_copy_available (bool))); + + connect (&m_file_system_watcher, &QFileSystemWatcher::fileChanged, + this, [=] (const QString& path) { file_has_changed (path); }); + + connect (this, &file_editor_tab::maybe_remove_next, + this, &file_editor_tab::handle_remove_next); + + connect (this, &file_editor_tab::dbstop_if, + this, &file_editor_tab::handle_dbstop_if); + + connect (this, &file_editor_tab::request_add_breakpoint, + this, &file_editor_tab::handle_request_add_breakpoint); + + connect (this, &file_editor_tab::api_entries_added, + this, &file_editor_tab::handle_api_entries_added); + + connect (this, &file_editor_tab::confirm_dbquit_and_save_signal, + this, &file_editor_tab::confirm_dbquit_and_save); + + connect (this, &file_editor_tab::do_save_file_signal, + this, &file_editor_tab::do_save_file); + + notice_settings (true); + + gui_settings settings; + + // encoding, not updated with the settings + m_encoding = settings.value (ed_default_enc.key, "UTF-8").toString (); + m_enc_indicator->setText (m_encoding); + // no changes in encoding yet + m_new_encoding = m_encoding; + } + + file_editor_tab::~file_editor_tab (void) + { + // Tell all connected markers to self-destruct. + emit remove_all_breakpoints_signal (); + emit remove_all_positions (); + + // Destroy lexer attached to m_edit_area, which is not the parent + // of lexer + QsciLexer *lexer = m_edit_area->lexer (); + if (lexer) + { + delete lexer; + m_edit_area->setLexer (nullptr); + } + } + + void file_editor_tab::set_encoding (const QString& new_encoding) + { + if (new_encoding.isEmpty ()) return; - } - - emit edit_mfile_request (word_at_cursor, m_file_name, m_ced, -1); -} - -// If "dbstop if ..." selected from context menu, create a conditional -// breakpoint. The default condition is (a) the existing condition if there -// is already a breakpoint, (b) any selected text, or (c) empty -void file_editor_tab::handle_context_menu_break_condition (int linenr) -{ - // Ensure editor line numbers match Octave core's line numbers. - // Give users the option to save modifications if necessary. - if (! unchanged_or_saved ()) - return; - - QString cond; - - // Search for previous condition. FIXME: is there a more direct way? - if (m_edit_area->markersAtLine (linenr) & (1 << marker::cond_break)) - { - emit report_marker_linenr (m_bp_lines, m_bp_conditions); - for (int i = 0; i < m_bp_lines.length (); i++) - if (m_bp_lines.value (i) == linenr) + + m_encoding = new_encoding; + m_enc_indicator->setText (m_encoding); + if (! m_edit_area->text ().isEmpty ()) + set_modified (true); + } + + void file_editor_tab::closeEvent (QCloseEvent *e) + { + int save_dialog = check_file_modified (true); + if ((save_dialog == QMessageBox::Cancel) || + (save_dialog == QMessageBox::Save)) + { + // Ignore close event if file is saved or user cancels + // closing this window. In case of saving, tab is closed after + // successful saving. + e->ignore (); + } + else + { + e->accept (); + emit tab_remove_request (); + } + } + + void file_editor_tab::set_current_directory (const QString& dir) + { + m_ced = dir; + } + + void file_editor_tab::handle_context_menu_edit (const QString& word_at_cursor) + { + // Search for a subfunction in actual file (this is done first because + // Octave finds this function before others with the same name in the + // search path. + QRegExp rxfun1 ("^[\t ]*function[^=]+=[\t ]*" + + word_at_cursor + "[\t ]*\\([^\\)]*\\)[\t ]*$"); + QRegExp rxfun2 ("^[\t ]*function[\t ]+" + + word_at_cursor + "[\t ]*\\([^\\)]*\\)[\t ]*$"); + QRegExp rxfun3 ("^[\t ]*function[\t ]+" + + word_at_cursor + "[\t ]*$"); + QRegExp rxfun4 ("^[\t ]*function[^=]+=[\t ]*" + + word_at_cursor + "[\t ]*$"); + + int pos_fct = -1; + QStringList lines = m_edit_area->text ().split ("\n"); + + int line; + for (line = 0; line < lines.count (); line++) + { + if ((pos_fct = rxfun1.indexIn (lines.at (line))) != -1) + break; + if ((pos_fct = rxfun2.indexIn (lines.at (line))) != -1) + break; + if ((pos_fct = rxfun3.indexIn (lines.at (line))) != -1) + break; + if ((pos_fct = rxfun4.indexIn (lines.at (line))) != -1) + break; + } + + if (pos_fct > -1) + { + // reg expr. found: it is an internal function + m_edit_area->setCursorPosition (line, pos_fct); + m_edit_area->SendScintilla (2232, line); // SCI_ENSUREVISIBLE + // SCI_VISIBLEFROMDOCLINE + int vis_line = m_edit_area->SendScintilla (2220, line); + m_edit_area->SendScintilla (2613, vis_line); // SCI_SETFIRSTVISIBLELINE + return; + } + + emit edit_mfile_request (word_at_cursor, m_file_name, m_ced, -1); + } + + // If "dbstop if ..." selected from context menu, create a conditional + // breakpoint. The default condition is (a) the existing condition if there + // is already a breakpoint, (b) any selected text, or (c) empty + void file_editor_tab::handle_context_menu_break_condition (int linenr) + { + // Ensure editor line numbers match Octave core's line numbers. + // Give users the option to save modifications if necessary. + if (! unchanged_or_saved ()) + return; + + QString cond; + + // Search for previous condition. FIXME: is there a more direct way? + if (m_edit_area->markersAtLine (linenr) & (1 << marker::cond_break)) + { + emit report_marker_linenr (m_bp_lines, m_bp_conditions); + for (int i = 0; i < m_bp_lines.length (); i++) + if (m_bp_lines.value (i) == linenr) + { + cond = m_bp_conditions.value (i); + break; + } + m_bp_lines.clear (); + m_bp_conditions.clear (); + } + + // If text selected by the mouse, default to that instead + // If both present, use the OR of them, to avoid accidental overwriting + // FIXME: If both are present, show old condition unselected and + // the selection (in edit area) selected (in the dialog). + if (m_edit_area->hasSelectedText ()) + { + if (cond == "") + cond = m_edit_area->selectedText (); + else + cond = '(' + cond + ") || (" + m_edit_area->selectedText () + ')'; + } + + emit dbstop_if ("dbstop if", linenr+1, cond); + } + + // Display dialog in GUI thread to get condition, then emit + // interpreter_event signal to check it in the interpreter thread. + // If the dialog returns a valid condition, then either emit a signal + // to add the breakpoint in the editor tab or a signal to display a + // new dialog. + + void file_editor_tab::handle_dbstop_if (const QString& prompt, int line, + const QString& cond) + { + bool ok; + QString new_cond + = QInputDialog::getText (this, tr ("Breakpoint condition"), + prompt, QLineEdit::Normal, cond, &ok); + + // If cancel, don't change breakpoint condition. + + if (ok && ! new_cond.isEmpty ()) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + error_system& es = interp.get_error_system (); + + unwind_protect frame; + + // Prevent an error in the evaluation here from sending us + // into the debugger. + + es.interpreter_try (frame); + + bool eval_error = false; + std::string msg; + + try + { + tree_evaluator& tw = interp.get_evaluator (); + bp_table& bptab = tw.get_bp_table (); + + bptab.condition_valid (new_cond.toStdString ()); + + // The condition seems OK, so set the conditional + // breakpoint. + + emit request_add_breakpoint (line, new_cond); + } + catch (const execution_exception& ee) + { + interp.recover_from_exception (); + + msg = ee.message (); + eval_error = true; + } + catch (const interrupt_exception&) + { + interp.recover_from_exception (); + + msg = "evaluation interrupted"; + eval_error = true; + } + + if (eval_error) + { + // Try again with a prompt that indicates the last + // attempt was an error. + + QString new_prompt = (tr ("ERROR: ") + + QString::fromStdString (msg) + + "\n\ndbstop if"); + + emit dbstop_if (new_prompt, line, ""); + } + }); + } + } + + void file_editor_tab::set_file_name (const QString& fileName) + { + // update tracked file if we really have a file on disk + QStringList trackedFiles = m_file_system_watcher.files (); + if (! trackedFiles.isEmpty ()) + m_file_system_watcher.removePath (m_file_name); + if (! fileName.isEmpty () && QFile::exists (fileName)) + { + m_file_system_watcher.addPath (fileName); + m_last_modified = QFileInfo (fileName).lastModified ().toUTC (); + } + + // update lexer and file name variable if file name changes + if (m_file_name != fileName) + { + m_file_name = fileName; + update_lexer (); + } + + // set the window title to actual filename (not modified) + update_window_title (m_edit_area->isModified ()); + + // update the file editor with current editing directory + emit editor_state_changed (m_copy_available, m_is_octave_file, + m_edit_area->isModified ()); + + // add the new file to the most-recently-used list + emit mru_add_file (m_file_name, m_encoding); + } + + // valid_file_name (file): checks whether "file" names a file. + // By default, "file" is empty; then m_file_name is checked + bool file_editor_tab::valid_file_name (const QString& file) + { + if (file.isEmpty ()) + { + if (m_file_name.isEmpty ()) + return false; + else + return true; + } + + return true; + } + + void file_editor_tab::enable_file_watcher (bool do_enable) + { + if (do_enable) + m_file_system_watcher.addPath (m_file_name); + else + m_file_system_watcher.removePath (m_file_name); + } + + // We cannot create a breakpoint when the file is modified + // because the line number the editor is providing might + // not match what Octave core is interpreting in the + // file on disk. This function gives the user the option + // to save before creating the breakpoint. + bool file_editor_tab::unchanged_or_saved (void) + { + bool retval = true; + if (m_edit_area->isModified () || ! valid_file_name ()) + { + int ans = QMessageBox::question (nullptr, tr ("Octave Editor"), + tr ("Cannot add breakpoint to modified or unnamed file.\n" + "Save and add breakpoint, or cancel?"), + QMessageBox::Save | QMessageBox::Cancel, QMessageBox::Save); + + if (ans == QMessageBox::Save) + save_file (m_file_name, false); + else + retval = false; + } + + return retval; + } + + // Toggle a breakpoint at the editor_linenr or, if this was called by + // a click with CTRL pressed, toggle a bookmark at that point. + void file_editor_tab::handle_margin_clicked (int margin, int editor_linenr, + Qt::KeyboardModifiers state) + { + if (margin == 1) + { + unsigned int markers_mask = m_edit_area->markersAtLine (editor_linenr); + + if (state & Qt::ControlModifier) { - cond = m_bp_conditions.value (i); - break; + if (markers_mask & (1 << marker::bookmark)) + m_edit_area->markerDelete (editor_linenr, marker::bookmark); + else + m_edit_area->markerAdd (editor_linenr, marker::bookmark); } - m_bp_lines.clear (); - m_bp_conditions.clear (); - } - - // If text selected by the mouse, default to that instead - // If both present, use the OR of them, to avoid accidental overwriting - // FIXME: If both are present, show old condition unselected and - // the selection (in edit area) selected (in the dialog). - if (m_edit_area->hasSelectedText ()) - { - if (cond == "") - cond = m_edit_area->selectedText (); - else - cond = '(' + cond + ") || (" + m_edit_area->selectedText () + ')'; - } - - emit dbstop_if ("dbstop if", linenr+1, cond); -} - -// Display dialog in GUI thread to get condition, then emit -// interpreter_event signal to check it in the interpreter thread. -// If the dialog returns a valid condition, then either emit a signal -// to add the breakpoint in the editor tab or a signal to display a -// new dialog. - -void file_editor_tab::handle_dbstop_if (const QString& prompt, int line, - const QString& cond) -{ - bool ok; - QString new_cond - = QInputDialog::getText (this, tr ("Breakpoint condition"), - prompt, QLineEdit::Normal, cond, &ok); - - // If cancel, don't change breakpoint condition. - - if (ok && ! new_cond.isEmpty ()) - { - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - error_system& es = interp.get_error_system (); - - unwind_protect frame; - - // Prevent an error in the evaluation here from sending us - // into the debugger. - - es.interpreter_try (frame); - - bool eval_error = false; - std::string msg; - - try - { - tree_evaluator& tw = interp.get_evaluator (); - bp_table& bptab = tw.get_bp_table (); - - bptab.condition_valid (new_cond.toStdString ()); - - // The condition seems OK, so set the conditional - // breakpoint. - - emit request_add_breakpoint (line, new_cond); - } - catch (const execution_exception& ee) - { - interp.recover_from_exception (); - - msg = ee.message (); - eval_error = true; - } - catch (const interrupt_exception&) - { - interp.recover_from_exception (); - - msg = "evaluation interrupted"; - eval_error = true; - } - - if (eval_error) - { - // Try again with a prompt that indicates the last - // attempt was an error. - - QString new_prompt = (tr ("ERROR: ") - + QString::fromStdString (msg) - + "\n\ndbstop if"); - - emit dbstop_if (new_prompt, line, ""); - } - }); - } -} - -void file_editor_tab::set_file_name (const QString& fileName) -{ - // update tracked file if we really have a file on disk - QStringList trackedFiles = m_file_system_watcher.files (); - if (! trackedFiles.isEmpty ()) - m_file_system_watcher.removePath (m_file_name); - if (! fileName.isEmpty () && QFile::exists (fileName)) - { - m_file_system_watcher.addPath (fileName); - m_last_modified = QFileInfo (fileName).lastModified ().toUTC (); - } - - // update lexer and file name variable if file name changes - if (m_file_name != fileName) - { - m_file_name = fileName; - update_lexer (); - } - - // set the window title to actual filename (not modified) - update_window_title (m_edit_area->isModified ()); - - // update the file editor with current editing directory - emit editor_state_changed (m_copy_available, m_is_octave_file, - m_edit_area->isModified ()); - - // add the new file to the most-recently-used list - emit mru_add_file (m_file_name, m_encoding); -} - -// valid_file_name (file): checks whether "file" names a file. -// By default, "file" is empty; then m_file_name is checked -bool file_editor_tab::valid_file_name (const QString& file) -{ - if (file.isEmpty ()) - { - if (m_file_name.isEmpty ()) - return false; - else - return true; - } - - return true; -} - -void file_editor_tab::enable_file_watcher (bool do_enable) -{ - if (do_enable) - m_file_system_watcher.addPath (m_file_name); - else - m_file_system_watcher.removePath (m_file_name); -} - -// We cannot create a breakpoint when the file is modified -// because the line number the editor is providing might -// not match what Octave core is interpreting in the -// file on disk. This function gives the user the option -// to save before creating the breakpoint. -bool file_editor_tab::unchanged_or_saved (void) -{ - bool retval = true; - if (m_edit_area->isModified () || ! valid_file_name ()) - { - int ans = QMessageBox::question (nullptr, tr ("Octave Editor"), - tr ("Cannot add breakpoint to modified or unnamed file.\n" - "Save and add breakpoint, or cancel?"), - QMessageBox::Save | QMessageBox::Cancel, QMessageBox::Save); - - if (ans == QMessageBox::Save) - save_file (m_file_name, false); - else - retval = false; - } - - return retval; -} - -// Toggle a breakpoint at the editor_linenr or, if this was called by -// a click with CTRL pressed, toggle a bookmark at that point. -void file_editor_tab::handle_margin_clicked (int margin, int editor_linenr, - Qt::KeyboardModifiers state) -{ - if (margin == 1) - { - unsigned int markers_mask = m_edit_area->markersAtLine (editor_linenr); - - if (state & Qt::ControlModifier) - { - if (markers_mask & (1 << marker::bookmark)) - m_edit_area->markerDelete (editor_linenr, marker::bookmark); - else - m_edit_area->markerAdd (editor_linenr, marker::bookmark); - } - else - { - if (markers_mask & ((1 << marker::breakpoint) - | (1 << marker::cond_break))) - handle_request_remove_breakpoint (editor_linenr + 1); - else - { - if (unchanged_or_saved ()) - handle_request_add_breakpoint (editor_linenr + 1, ""); - } - } - } -} - -void file_editor_tab::update_lexer (void) -{ - // Create a new lexer - QsciLexer *lexer = nullptr; - - m_is_octave_file = false; - - // Find the required lexer from file extensions - if (m_file_name.endsWith (".m") - || m_file_name.endsWith ("octaverc")) - { + else + { + if (markers_mask & ((1 << marker::breakpoint) + | (1 << marker::cond_break))) + handle_request_remove_breakpoint (editor_linenr + 1); + else + { + if (unchanged_or_saved ()) + handle_request_add_breakpoint (editor_linenr + 1, ""); + } + } + } + } + + void file_editor_tab::update_lexer (void) + { + // Create a new lexer + QsciLexer *lexer = nullptr; + + m_is_octave_file = false; + + // Find the required lexer from file extensions + if (m_file_name.endsWith (".m") + || m_file_name.endsWith ("octaverc")) + { #if defined (HAVE_LEXER_OCTAVE) - lexer = new QsciLexerOctave (); + lexer = new QsciLexerOctave (); #elif defined (HAVE_LEXER_MATLAB) - lexer = new QsciLexerMatlab (); + lexer = new QsciLexerMatlab (); #else - lexer = new octave_txt_lexer (); + lexer = new octave_txt_lexer (); #endif - m_is_octave_file = true; - } - - if (! lexer) - { - if (m_file_name.endsWith (".c") - || m_file_name.endsWith (".cc") - || m_file_name.endsWith (".cpp") - || m_file_name.endsWith (".cxx") - || m_file_name.endsWith (".c++") - || m_file_name.endsWith (".h") - || m_file_name.endsWith (".hh") - || m_file_name.endsWith (".hpp") - || m_file_name.endsWith (".h++")) - { - lexer = new QsciLexerCPP (); - } - else if (m_file_name.endsWith (".java")) - { - lexer = new QsciLexerJava (); - } - else if (m_file_name.endsWith (".pl")) - { - lexer = new QsciLexerPerl (); - } - else if (m_file_name.endsWith (".bat")) - { - lexer = new QsciLexerBatch (); - } - else if (m_file_name.endsWith (".diff")) - { - lexer = new QsciLexerDiff (); - } - else if (m_file_name.endsWith (".sh")) - { - lexer = new QsciLexerBash (); - } - else if (! valid_file_name ()) - { - // new, not yet named file: let us assume it is octave + m_is_octave_file = true; + } + + if (! lexer) + { + if (m_file_name.endsWith (".c") + || m_file_name.endsWith (".cc") + || m_file_name.endsWith (".cpp") + || m_file_name.endsWith (".cxx") + || m_file_name.endsWith (".c++") + || m_file_name.endsWith (".h") + || m_file_name.endsWith (".hh") + || m_file_name.endsWith (".hpp") + || m_file_name.endsWith (".h++")) + { + lexer = new QsciLexerCPP (); + } + else if (m_file_name.endsWith (".java")) + { + lexer = new QsciLexerJava (); + } + else if (m_file_name.endsWith (".pl")) + { + lexer = new QsciLexerPerl (); + } + else if (m_file_name.endsWith (".bat")) + { + lexer = new QsciLexerBatch (); + } + else if (m_file_name.endsWith (".diff")) + { + lexer = new QsciLexerDiff (); + } + else if (m_file_name.endsWith (".sh")) + { + lexer = new QsciLexerBash (); + } + else if (! valid_file_name ()) + { + // new, not yet named file: let us assume it is octave #if defined (HAVE_LEXER_OCTAVE) - lexer = new QsciLexerOctave (); - m_is_octave_file = true; + lexer = new QsciLexerOctave (); + m_is_octave_file = true; #elif defined (HAVE_LEXER_MATLAB) - lexer = new QsciLexerMatlab (); - m_is_octave_file = true; + lexer = new QsciLexerMatlab (); + m_is_octave_file = true; #else - lexer = new octave_txt_lexer (); + lexer = new octave_txt_lexer (); #endif - } - else - { - // other or no extension - lexer = new octave_txt_lexer (); - } - } - - // Get any existing lexer - QsciLexer *old_lexer = m_edit_area->lexer (); - - // If new file, no lexer, or lexer has changed, - // delete old one and set the newly created as current lexer - if (! old_lexer || ! valid_file_name () - || QString(old_lexer->lexer ()) != QString(lexer->lexer ())) - { - // Delete and set new lexer - if (old_lexer) - delete old_lexer; - m_edit_area->setLexer (lexer); - - // Build information for auto completion (APIs) - m_lexer_apis = new QsciAPIs (lexer); - - connect (this, &file_editor_tab::request_add_octave_apis, - this, &file_editor_tab::handle_add_octave_apis); - - // Get the settings for this new lexer - update_lexer_settings (); - } - else - { - // Otherwise, delete the newly created lexer and - // use the old, existing one. - delete lexer; - } -} - -// Update settings, which are lexer related and have to be updated -// when -// a) the lexer changes, -// b) the settings have changed, or -// c) a package was loaded/unloaded -void file_editor_tab::update_lexer_settings (bool update_apis_only) -{ - QsciLexer *lexer = m_edit_area->lexer (); - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (m_lexer_apis) - { - m_lexer_apis->cancelPreparation (); // stop preparing if apis exists - - bool update_apis = false; // flag, whether update of apis files - - // Get path to prepared api info (cache). Temporarily set the - // application name to 'octave' instead of 'GNU Octave' name for - // not having blanks in the path. - QString tmp_app_name = QCoreApplication::applicationName (); - QCoreApplication::setApplicationName ("octave"); // Set new name + } + else + { + // other or no extension + lexer = new octave_txt_lexer (); + } + } + + // Get any existing lexer + QsciLexer *old_lexer = m_edit_area->lexer (); + + // If new file, no lexer, or lexer has changed, + // delete old one and set the newly created as current lexer + if (! old_lexer || ! valid_file_name () + || QString(old_lexer->lexer ()) != QString(lexer->lexer ())) + { + // Delete and set new lexer + if (old_lexer) + delete old_lexer; + m_edit_area->setLexer (lexer); + + // Build information for auto completion (APIs) + m_lexer_apis = new QsciAPIs (lexer); + + connect (this, &file_editor_tab::request_add_octave_apis, + this, &file_editor_tab::handle_add_octave_apis); + + // Get the settings for this new lexer + update_lexer_settings (); + } + else + { + // Otherwise, delete the newly created lexer and + // use the old, existing one. + delete lexer; + } + } + + // Update settings, which are lexer related and have to be updated + // when + // a) the lexer changes, + // b) the settings have changed, or + // c) a package was loaded/unloaded + void file_editor_tab::update_lexer_settings (bool update_apis_only) + { + QsciLexer *lexer = m_edit_area->lexer (); + + gui_settings settings; + + if (m_lexer_apis) + { + m_lexer_apis->cancelPreparation (); // stop preparing if apis exists + + bool update_apis = false; // flag, whether update of apis files + + // Get path to prepared api info (cache). Temporarily set the + // application name to 'octave' instead of 'GNU Octave' name for + // not having blanks in the path. + QString tmp_app_name = QCoreApplication::applicationName (); + QCoreApplication::setApplicationName ("octave"); // Set new name #if defined (HAVE_QSTANDARDPATHS) - QString local_data_path - = QStandardPaths::writableLocation (QStandardPaths::CacheLocation); + QString local_data_path + = QStandardPaths::writableLocation (QStandardPaths::CacheLocation); #else - QString local_data_path - = QDesktopServices::storageLocation (QDesktopServices::CacheLocation); + QString local_data_path + = QDesktopServices::storageLocation (QDesktopServices::CacheLocation); #endif - QCoreApplication::setApplicationName ("octave"); // Set temp. name - - m_prep_apis_path - = local_data_path + "/" + QString (OCTAVE_VERSION) + "/qsci/"; - - // get settings which infos are used for octave - bool octave_builtins - = settings->value (ed_code_completion_octave_builtins).toBool (); - bool octave_functions - = settings->value (ed_code_completion_octave_functions).toBool (); - - QCoreApplication::setApplicationName (tmp_app_name); // Restore name - - if (m_is_octave_file) - { - // Keywords and Builtins do not change, this information can be - // stored in prepared form in a file. Information on function are - // changing frequently, then if functions should also be auto- - // completed, the date of any existing file is checked. - - // Keywords are always used - m_prep_apis_file = m_prep_apis_path + lexer->lexer () + "_k"; - - // Builtins are only used if the user settings say so - if (octave_builtins) - m_prep_apis_file += 'b'; - - if (octave_functions) - m_prep_apis_file += 'f'; - - m_prep_apis_file += ".pap"; // final name of apis file - - // check whether the APIs info needs to be prepared and saved - QFileInfo apis_file = QFileInfo (m_prep_apis_file); - - // flag whether apis file needs update - update_apis = ! apis_file.exists (); - - if (octave_functions) - { - // Functions may change frequently. Update the apis data - // if the file is older than a few minutes preventing from - // re-preparing data when the user opens several files. - QDateTime apis_time = apis_file.lastModified (); - if (update_apis_only - || QDateTime::currentDateTime () > apis_time.addSecs (180)) - update_apis = true; - } - - } - else - { - // No octave file, just add extension. - m_prep_apis_file = m_prep_apis_path + lexer->lexer () + ".pap"; - } - - // Make sure the apis file is usable, otherwise the gui might crash, - // e.g., in case of max. number of opened files - QFile f (m_prep_apis_file); - - bool apis_usable = f.open (QIODevice::ReadOnly); - if (! apis_usable) - { - QDir ().mkpath (QFileInfo (f).absolutePath ()); - apis_usable = f.open (QIODevice::WriteOnly); - } - if (apis_usable) - f.close (); - - if (apis_usable - && (update_apis || ! m_lexer_apis->loadPrepared (m_prep_apis_file))) - { - // either we have decided to update the apis file or - // no prepared info was loaded, prepare and save if possible - - // create raw apis info - - m_lexer_apis->clear (); // Clear current contents - - if (m_is_octave_file) - { - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - QStringList api_entries; - - octave_value_list tmp = Fiskeyword (); - const Cell ctmp = tmp(0).cell_value (); - for (octave_idx_type i = 0; i < ctmp.numel (); i++) - { - std::string kw = ctmp(i).string_value (); - api_entries.append (QString::fromStdString (kw)); - } - - if (octave_builtins) - { - symbol_table& symtab = interp.get_symbol_table (); - - string_vector bfl = symtab.built_in_function_names (); - - for (octave_idx_type i = 0; i < bfl.numel (); i++) - api_entries.append (QString::fromStdString (bfl[i])); - } - - if (octave_functions) - { - load_path& lp = interp.get_load_path (); - - string_vector ffl = lp.fcn_names (); - string_vector afl = interp.autoloaded_functions (); - - for (octave_idx_type i = 0; i < ffl.numel (); i++) - api_entries.append (QString::fromStdString (ffl[i])); - - for (octave_idx_type i = 0; i < afl.numel (); i++) - api_entries.append (QString::fromStdString (afl[i])); - } - - emit request_add_octave_apis (api_entries); - }); - } - else - { - for (int i = 1; i <= 3; i++) - { - // Get list, split, and add to API. - - QString keyword = QString (lexer->keywords (i)); - - QStringList keyword_list - = keyword.split (QRegExp (R"(\s+)")); - - for (int j = 0; j < keyword_list.size (); j++) - m_lexer_apis->add (keyword_list.at (j)); - } - - emit api_entries_added (); - } - } - } - - if (update_apis_only) - return; // We are done here - - int mode = settings->value (ed_color_mode).toInt (); - rmgr.read_lexer_settings (lexer, settings, mode); - - m_edit_area->setCaretForegroundColor (lexer->color (0)); - m_edit_area->setIndentationGuidesForegroundColor (lexer->color (0)); - - // set some colors depending on selected background color of the lexer - QColor bg = lexer->paper (0); - QColor fg = lexer->color (0); - - // margin and current line marker colors - QColor bgm, fgm; - - bgm = interpolate_color (bg, fg, 0.5, 0.2); - m_edit_area->setEdgeColor (bgm); - - m_edit_area->setMarkerForegroundColor (lexer->color (0)); - m_edit_area->setMarginsForegroundColor (lexer->color (0)); - - bgm = interpolate_color (bg, fg, 0.5, 0.125); - fgm = interpolate_color (bg, fg, 0.5, 0.25); - m_edit_area->setMarginsBackgroundColor (bgm); - m_edit_area->setFoldMarginColors (bgm, fgm); - - QColor current_line_bg - = settings->color_value (ed_highlight_current_line_color, mode); - if (current_line_bg == settings_color_no_change) - bgm = interpolate_color (bg, fg, 0.5, 0.1); // It is the "auto" color - else - bgm = current_line_bg; // Specific color given - - m_edit_area->setCaretLineBackgroundColor (bgm); - - // color indicator for highlighting all occurrences: - // applications highlight color with more transparency - QColor hg = QApplication::palette ().color (QPalette::Highlight); - m_edit_area->set_selection_marker_color (hg); - - // fix line number width with respect to the font size of the lexer and - // set the line numbers font depending on the lexer's font - if (settings->value (ed_show_line_numbers).toBool ()) - { - // Line numbers width - auto_margin_width (); - - // Line numbers font - QFont line_numbers_font = lexer->defaultFont (); - int font_size = line_numbers_font.pointSize (); - font_size = font_size - + settings->value (ed_line_numbers_size).toInt (); - if (font_size < 4) - font_size = 4; - line_numbers_font.setPointSize (font_size); - - m_edit_area->setMarginsFont (line_numbers_font); - } - else - m_edit_area->setMarginWidth (2, 0); -} - -// function for adding entries to the octave lexer's APIs -void file_editor_tab::handle_add_octave_apis (const QStringList& api_entries) -{ - for (int idx = 0; idx < api_entries.size (); idx++) - m_lexer_apis->add (api_entries.at (idx)); - - emit api_entries_added (); -} - -void file_editor_tab::handle_api_entries_added (void) -{ - // disconnect slot for saving prepared info if already connected - disconnect (m_lexer_apis, &QsciAPIs::apiPreparationFinished, - nullptr, nullptr); - - // check whether path for prepared info exists or can be created - if (QDir ("/").mkpath (m_prep_apis_path)) - { - // path exists, apis info can be saved there - connect (m_lexer_apis, &QsciAPIs::apiPreparationFinished, - this, &file_editor_tab::save_apis_info); - } - - m_lexer_apis->prepare (); // prepare apis info -} - -void file_editor_tab::save_apis_info (void) -{ - m_lexer_apis->savePrepared (m_prep_apis_file); -} - -// slot for fetab_set_focus: sets the focus to the current edit area -void file_editor_tab::set_focus (const QWidget *ID) -{ - if (ID != this) - return; - m_edit_area->setFocus (); - emit edit_area_changed (m_edit_area); // update the edit area in find dlg -} - -void file_editor_tab::context_help (const QWidget *ID, bool doc) -{ - if (ID != this) - return; - - m_edit_area->context_help_doc (doc); -} - -void file_editor_tab::context_edit (const QWidget *ID) -{ - if (ID != this) - return; - - m_edit_area->context_edit (); -} - -void file_editor_tab::save_file (const QWidget *ID) -{ - if (ID != this) - return; - - save_file (m_file_name); -} - -void file_editor_tab::save_file (const QWidget *ID, const QString& fileName, - bool remove_on_success) -{ - if (ID != this) - return; - - save_file (fileName, remove_on_success); -} - -void file_editor_tab::save_file_as (const QWidget *ID) -{ - if (ID != this) - return; - - save_file_as (); -} - -void file_editor_tab::print_file (const QWidget *ID) -{ - if (ID != this) - return; - - QsciPrinter *printer = new QsciPrinter (QPrinter::HighResolution); - - QPrintDialog printDlg (printer, this); - - if (printDlg.exec () == QDialog::Accepted) - printer->printRange (m_edit_area); - - delete printer; -} - -void file_editor_tab::run_file (const QWidget *ID, bool step_into) -{ - if (ID != this) - return; - - if (m_edit_area->isModified () || ! valid_file_name ()) - { - save_file (m_file_name); // save file dialog - - // Running a file is disabled for non-octave files. But when saving - // a new file, an octave file is assumed but might actually saved - // as another file or with an invalid file name. - if (! (m_is_octave_file && valid_file_name ())) + QCoreApplication::setApplicationName ("octave"); // Set temp. name + + m_prep_apis_path + = local_data_path + "/" + QString (OCTAVE_VERSION) + "/qsci/"; + + // get settings which infos are used for octave + bool octave_builtins + = settings.value (ed_code_completion_octave_builtins).toBool (); + bool octave_functions + = settings.value (ed_code_completion_octave_functions).toBool (); + + QCoreApplication::setApplicationName (tmp_app_name); // Restore name + + if (m_is_octave_file) + { + // Keywords and Builtins do not change, this information can be + // stored in prepared form in a file. Information on function are + // changing frequently, then if functions should also be auto- + // completed, the date of any existing file is checked. + + // Keywords are always used + m_prep_apis_file = m_prep_apis_path + lexer->lexer () + "_k"; + + // Builtins are only used if the user settings say so + if (octave_builtins) + m_prep_apis_file += 'b'; + + if (octave_functions) + m_prep_apis_file += 'f'; + + m_prep_apis_file += ".pap"; // final name of apis file + + // check whether the APIs info needs to be prepared and saved + QFileInfo apis_file = QFileInfo (m_prep_apis_file); + + // flag whether apis file needs update + update_apis = ! apis_file.exists (); + + if (octave_functions) + { + // Functions may change frequently. Update the apis data + // if the file is older than a few minutes preventing from + // re-preparing data when the user opens several files. + QDateTime apis_time = apis_file.lastModified (); + if (update_apis_only + || QDateTime::currentDateTime () > apis_time.addSecs (180)) + update_apis = true; + } + + } + else + { + // No octave file, just add extension. + m_prep_apis_file = m_prep_apis_path + lexer->lexer () + ".pap"; + } + + // Make sure the apis file is usable, otherwise the gui might crash, + // e.g., in case of max. number of opened files + QFile f (m_prep_apis_file); + + bool apis_usable = f.open (QIODevice::ReadOnly); + if (! apis_usable) + { + QDir ().mkpath (QFileInfo (f).absolutePath ()); + apis_usable = f.open (QIODevice::WriteOnly); + } + if (apis_usable) + f.close (); + + if (apis_usable + && (update_apis || ! m_lexer_apis->loadPrepared (m_prep_apis_file))) + { + // either we have decided to update the apis file or + // no prepared info was loaded, prepare and save if possible + + // create raw apis info + + m_lexer_apis->clear (); // Clear current contents + + if (m_is_octave_file) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + QStringList api_entries; + + octave_value_list tmp = Fiskeyword (); + const Cell ctmp = tmp(0).cell_value (); + for (octave_idx_type i = 0; i < ctmp.numel (); i++) + { + std::string kw = ctmp(i).string_value (); + api_entries.append (QString::fromStdString (kw)); + } + + if (octave_builtins) + { + symbol_table& symtab = interp.get_symbol_table (); + + string_vector bfl = symtab.built_in_function_names (); + + for (octave_idx_type i = 0; i < bfl.numel (); i++) + api_entries.append (QString::fromStdString (bfl[i])); + } + + if (octave_functions) + { + load_path& lp = interp.get_load_path (); + + string_vector ffl = lp.fcn_names (); + string_vector afl = interp.autoloaded_functions (); + + for (octave_idx_type i = 0; i < ffl.numel (); i++) + api_entries.append (QString::fromStdString (ffl[i])); + + for (octave_idx_type i = 0; i < afl.numel (); i++) + api_entries.append (QString::fromStdString (afl[i])); + } + + emit request_add_octave_apis (api_entries); + }); + } + else + { + for (int i = 1; i <= 3; i++) + { + // Get list, split, and add to API. + + QString keyword = QString (lexer->keywords (i)); + + QStringList keyword_list + = keyword.split (QRegExp (R"(\s+)")); + + for (int j = 0; j < keyword_list.size (); j++) + m_lexer_apis->add (keyword_list.at (j)); + } + + emit api_entries_added (); + } + } + } + + if (update_apis_only) + return; // We are done here + + int mode = settings.value (ed_color_mode).toInt (); + resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + rmgr.read_lexer_settings (lexer, mode); + + m_edit_area->setCaretForegroundColor (lexer->color (0)); + m_edit_area->setIndentationGuidesForegroundColor (lexer->color (0)); + + // set some colors depending on selected background color of the lexer + QColor bg = lexer->paper (0); + QColor fg = lexer->color (0); + + // margin and current line marker colors + QColor bgm, fgm; + + bgm = interpolate_color (bg, fg, 0.5, 0.2); + m_edit_area->setEdgeColor (bgm); + + m_edit_area->setMarkerForegroundColor (lexer->color (0)); + m_edit_area->setMarginsForegroundColor (lexer->color (0)); + + bgm = interpolate_color (bg, fg, 0.5, 0.125); + fgm = interpolate_color (bg, fg, 0.5, 0.25); + m_edit_area->setMarginsBackgroundColor (bgm); + m_edit_area->setFoldMarginColors (bgm, fgm); + + QColor current_line_bg + = settings.color_value (ed_highlight_current_line_color, mode); + if (current_line_bg == settings_color_no_change) + bgm = interpolate_color (bg, fg, 0.5, 0.1); // It is the "auto" color + else + bgm = current_line_bg; // Specific color given + + m_edit_area->setCaretLineBackgroundColor (bgm); + + // color indicator for highlighting all occurrences: + // applications highlight color with more transparency + QColor hg = QApplication::palette ().color (QPalette::Highlight); + m_edit_area->set_selection_marker_color (hg); + + // fix line number width with respect to the font size of the lexer and + // set the line numbers font depending on the lexer's font + if (settings.value (ed_show_line_numbers).toBool ()) + { + // Line numbers width + auto_margin_width (); + + // Line numbers font + QFont line_numbers_font = lexer->defaultFont (); + int font_size = line_numbers_font.pointSize (); + font_size = font_size + + settings.value (ed_line_numbers_size).toInt (); + if (font_size < 4) + font_size = 4; + line_numbers_font.setPointSize (font_size); + + m_edit_area->setMarginsFont (line_numbers_font); + } + else + m_edit_area->setMarginWidth (2, 0); + } + + // function for adding entries to the octave lexer's APIs + void file_editor_tab::handle_add_octave_apis (const QStringList& api_entries) + { + for (int idx = 0; idx < api_entries.size (); idx++) + m_lexer_apis->add (api_entries.at (idx)); + + emit api_entries_added (); + } + + void file_editor_tab::handle_api_entries_added (void) + { + // disconnect slot for saving prepared info if already connected + disconnect (m_lexer_apis, &QsciAPIs::apiPreparationFinished, + nullptr, nullptr); + + // check whether path for prepared info exists or can be created + if (QDir ("/").mkpath (m_prep_apis_path)) + { + // path exists, apis info can be saved there + connect (m_lexer_apis, &QsciAPIs::apiPreparationFinished, + this, &file_editor_tab::save_apis_info); + } + + m_lexer_apis->prepare (); // prepare apis info + } + + void file_editor_tab::save_apis_info (void) + { + m_lexer_apis->savePrepared (m_prep_apis_file); + } + + // slot for fetab_set_focus: sets the focus to the current edit area + void file_editor_tab::set_focus (const QWidget *ID) + { + if (ID != this) + return; + m_edit_area->setFocus (); + emit edit_area_changed (m_edit_area); // update the edit area in find dlg + } + + void file_editor_tab::context_help (const QWidget *ID, bool doc) + { + if (ID != this) + return; + + m_edit_area->context_help_doc (doc); + } + + void file_editor_tab::context_edit (const QWidget *ID) + { + if (ID != this) + return; + + m_edit_area->context_edit (); + } + + void file_editor_tab::save_file (const QWidget *ID) + { + if (ID != this) + return; + + save_file (m_file_name); + } + + void file_editor_tab::save_file (const QWidget *ID, const QString& fileName, + bool remove_on_success) + { + if (ID != this) + return; + + save_file (fileName, remove_on_success); + } + + void file_editor_tab::save_file_as (const QWidget *ID) + { + if (ID != this) + return; + + save_file_as (); + } + + void file_editor_tab::print_file (const QWidget *ID) + { + if (ID != this) + return; + + QsciPrinter *printer = new QsciPrinter (QPrinter::HighResolution); + + QPrintDialog printDlg (printer, this); + + if (printDlg.exec () == QDialog::Accepted) + printer->printRange (m_edit_area); + + delete printer; + } + + void file_editor_tab::run_file (const QWidget *ID, bool step_into) + { + if (ID != this) + return; + + if (m_edit_area->isModified () || ! valid_file_name ()) + { + save_file (m_file_name); // save file dialog + + // Running a file is disabled for non-octave files. But when saving + // a new file, an octave file is assumed but might actually saved + // as another file or with an invalid file name. + if (! (m_is_octave_file && valid_file_name ())) + return; + } + + if (step_into) + { + // Get current first breakpoint and set breakpoint waiting for + // the returned line number. Store whether to remove this breakpoint + // afterwards. + int first_bp_line + = m_edit_area->markerFindNext (0, (1 << marker::breakpoint)) + 1; + + // Set flag for storing the line number of the breakpoint + m_breakpoint_info.remove_next = true; + m_breakpoint_info.do_not_remove_line = first_bp_line; + + // Add breakpoint, storing its line number + handle_request_add_breakpoint (1, QString ()); + } + + QFileInfo info (m_file_name); + emit run_file_signal (info); + } + + void file_editor_tab::context_run (const QWidget *ID) + { + if (ID != this) + return; + + m_edit_area->context_run (); + } + + void file_editor_tab::toggle_bookmark (const QWidget *ID) + { + if (ID != this) + return; + + int line, cur; + m_edit_area->getCursorPosition (&line, &cur); + + if (m_edit_area->markersAtLine (line) & (1 << marker::bookmark)) + m_edit_area->markerDelete (line, marker::bookmark); + else + m_edit_area->markerAdd (line, marker::bookmark); + } + + // Move the text cursor to the closest bookmark + // after the current line. + void file_editor_tab::next_bookmark (const QWidget *ID) + { + if (ID != this) + return; + + int line, cur; + m_edit_area->getCursorPosition (&line, &cur); + + line++; // Find bookmark strictly after the current line. + + int nextline = m_edit_area->markerFindNext (line, (1 << marker::bookmark)); + + // Wrap. + if (nextline == -1) + nextline = m_edit_area->markerFindNext (1, (1 << marker::bookmark)); + + m_edit_area->setCursorPosition (nextline, 0); + } + + // Move the text cursor to the closest bookmark + // before the current line. + void file_editor_tab::previous_bookmark (const QWidget *ID) + { + if (ID != this) + return; + + int line, cur; + m_edit_area->getCursorPosition (&line, &cur); + + line--; // Find bookmark strictly before the current line. + + int prevline = m_edit_area->markerFindPrevious (line, (1 << marker::bookmark)); + + // Wrap. Should use the last line of the file, not 1<<15 + if (prevline == -1) + prevline = m_edit_area->markerFindPrevious (m_edit_area->lines (), + (1 << marker::bookmark)); + + m_edit_area->setCursorPosition (prevline, 0); + } + + QString file_editor_tab::get_all_bookmarks () + { + QString bmlist; + int line = 0; + + while (line > -1) + { + line = m_edit_area->markerFindNext (line, (1 << marker::bookmark)); + if (line > -1) + { + if (! bmlist.isEmpty ()) + bmlist += ","; + bmlist += QString::number (line); + line++; // search from next line, otherwise same line found again + } + } + + return bmlist; + } + + void file_editor_tab::remove_bookmark (const QWidget *ID) + { + if (ID != this) + return; + + m_edit_area->markerDeleteAll (marker::bookmark); + } + + void + file_editor_tab::handle_request_add_breakpoint (int line, + const QString& condition) + { + if (! m_is_octave_file) + return; + + add_breakpoint_event (line, condition); + } + + void file_editor_tab::handle_request_remove_breakpoint (int line) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + tree_evaluator& tw = interp.get_evaluator (); + bp_table& bptab = tw.get_bp_table (); + + bptab.remove_breakpoint_from_file (m_file_name.toStdString (), line); + }); + } + + void file_editor_tab::toggle_breakpoint (const QWidget *ID) + { + if (ID != this) + return; + + int editor_linenr, cur; + m_edit_area->getCursorPosition (&editor_linenr, &cur); + + if (m_edit_area->markersAtLine (editor_linenr) & (1 << marker::breakpoint)) + request_remove_breakpoint_via_editor_linenr (editor_linenr); + else + { + if (unchanged_or_saved ()) + handle_request_add_breakpoint (editor_linenr + 1, ""); + } + } + + // Move the text cursor to the closest breakpoint (conditional or unconditional) + // after the current line. + void file_editor_tab::next_breakpoint (const QWidget *ID) + { + if (ID != this) + return; + + int line, cur; + m_edit_area->getCursorPosition (&line, &cur); + + line++; // Find breakpoint strictly after the current line. + + int nextline = m_edit_area->markerFindNext (line, (1 << marker::breakpoint)); + int nextcond = m_edit_area->markerFindNext (line, (1 << marker::cond_break)); + + // Check if the next conditional breakpoint is before next unconditional one. + if (nextcond != -1 && (nextcond < nextline || nextline == -1)) + nextline = nextcond; + + m_edit_area->setCursorPosition (nextline, 0); + } + + // Move the text cursor to the closest breakpoint (conditional or unconditional) + // before the current line. + void file_editor_tab::previous_breakpoint (const QWidget *ID) + { + if (ID != this) + return; + + int line, cur, prevline, prevcond; + m_edit_area->getCursorPosition (&line, &cur); + + line--; // Find breakpoint strictly before the current line. + + prevline = m_edit_area->markerFindPrevious (line, (1 << marker::breakpoint)); + prevcond = m_edit_area->markerFindPrevious (line, (1 << marker::cond_break)); + + // Check if the prev conditional breakpoint is closer than the unconditional. + if (prevcond != -1 && prevcond > prevline) + prevline = prevcond; + + m_edit_area->setCursorPosition (prevline, 0); + } + + void file_editor_tab::remove_all_breakpoints (const QWidget *ID) + { + if (ID != this) + return; + + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + tree_evaluator& tw = interp.get_evaluator (); + bp_table& bptab = tw.get_bp_table (); + + bptab.remove_all_breakpoints_from_file (m_file_name.toStdString (), + true); + }); + } + + void file_editor_tab::scintilla_command (const QWidget *ID, + unsigned int sci_msg) + { + if (ID != this) + return; + + m_edit_area->SendScintilla (sci_msg); + } + + void file_editor_tab::comment_selected_text (const QWidget *ID, + bool input_str) + { + if (ID != this) + return; + + do_comment_selected_text (true, input_str); + } + + void file_editor_tab::uncomment_selected_text (const QWidget *ID) + { + if (ID != this) + return; + + do_comment_selected_text (false); + } + + void file_editor_tab::indent_selected_text (const QWidget *ID) + { + if (ID != this) + return; + + do_indent_selected_text (true); + } + + void file_editor_tab::unindent_selected_text (const QWidget *ID) + { + if (ID != this) + return; + + do_indent_selected_text (false); + } + + void file_editor_tab::smart_indent_line_or_selected_text (const QWidget *ID) + { + if (ID != this) + return; + + do_smart_indent_line_or_selected_text (); + } + + void file_editor_tab::convert_eol (const QWidget *ID, + QsciScintilla::EolMode eol_mode) + { + if (ID != this) + return; + + m_edit_area->convertEols (eol_mode); + m_edit_area->setEolMode (eol_mode); + update_eol_indicator (); + } + + void file_editor_tab::zoom_in (const QWidget *ID) + { + if (ID != this) + return; + + m_edit_area->zoomIn (1); + auto_margin_width (); + } + + void file_editor_tab::zoom_out (const QWidget *ID) + { + if (ID != this) + return; + + m_edit_area->zoomOut (1); + auto_margin_width (); + } + + void file_editor_tab::zoom_normal (const QWidget *ID) + { + if (ID != this) + return; + + m_edit_area->zoomTo (0); + auto_margin_width (); + } + + void file_editor_tab::add_breakpoint_event (int line, const QString& cond) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + // FIXME: note duplication with the code in + // handle_context_menu_break_condition. + + tree_evaluator& tw = interp.get_evaluator (); + bp_table& bptab = tw.get_bp_table (); + + int lineno = bptab.add_breakpoint_in_file (m_file_name.toStdString (), + line, cond.toStdString ()); + + if (lineno) + emit maybe_remove_next (lineno); + }); + } + + void file_editor_tab::handle_remove_next (int remove_line) + { + // Store some info breakpoint + if (m_breakpoint_info.remove_next) + { + m_breakpoint_info.remove_line = remove_line; + m_breakpoint_info.remove_next = false; + } + } + + void file_editor_tab::goto_line (const QWidget *ID, int line) + { + if (ID != this) + return; + + if (m_bp_restore_count > 0) + { + // This goto-line request is invoked by restoring a breakpoint during + // saving the file, thus, do not go to the related line + m_bp_restore_count--; return; - } - - if (step_into) - { - // Get current first breakpoint and set breakpoint waiting for - // the returned line number. Store whether to remove this breakpoint - // afterwards. - int first_bp_line - = m_edit_area->markerFindNext (0, (1 << marker::breakpoint)) + 1; - - // Set flag for storing the line number of the breakpoint - m_breakpoint_info.remove_next = true; - m_breakpoint_info.do_not_remove_line = first_bp_line; - - // Add breakpoint, storing its line number - handle_request_add_breakpoint (1, QString ()); - } - - QFileInfo info (m_file_name); - emit run_file_signal (info); -} - -void file_editor_tab::context_run (const QWidget *ID) -{ - if (ID != this) - return; - - m_edit_area->context_run (); -} - -void file_editor_tab::toggle_bookmark (const QWidget *ID) -{ - if (ID != this) - return; - - int line, cur; - m_edit_area->getCursorPosition (&line, &cur); - - if (m_edit_area->markersAtLine (line) & (1 << marker::bookmark)) - m_edit_area->markerDelete (line, marker::bookmark); - else - m_edit_area->markerAdd (line, marker::bookmark); -} - -// Move the text cursor to the closest bookmark -// after the current line. -void file_editor_tab::next_bookmark (const QWidget *ID) -{ - if (ID != this) - return; - - int line, cur; - m_edit_area->getCursorPosition (&line, &cur); - - line++; // Find bookmark strictly after the current line. - - int nextline = m_edit_area->markerFindNext (line, (1 << marker::bookmark)); - - // Wrap. - if (nextline == -1) - nextline = m_edit_area->markerFindNext (1, (1 << marker::bookmark)); - - m_edit_area->setCursorPosition (nextline, 0); -} - -// Move the text cursor to the closest bookmark -// before the current line. -void file_editor_tab::previous_bookmark (const QWidget *ID) -{ - if (ID != this) - return; - - int line, cur; - m_edit_area->getCursorPosition (&line, &cur); - - line--; // Find bookmark strictly before the current line. - - int prevline = m_edit_area->markerFindPrevious (line, (1 << marker::bookmark)); - - // Wrap. Should use the last line of the file, not 1<<15 - if (prevline == -1) - prevline = m_edit_area->markerFindPrevious (m_edit_area->lines (), - (1 << marker::bookmark)); - - m_edit_area->setCursorPosition (prevline, 0); -} - -QString file_editor_tab::get_all_bookmarks () -{ - QString bmlist; - int line = 0; - - while (line > -1) - { - line = m_edit_area->markerFindNext (line, (1 << marker::bookmark)); - if (line > -1) - { - if (! bmlist.isEmpty ()) - bmlist += ","; - bmlist += QString::number (line); - line++; // search from next line, otherwise same line found again - } - } - - return bmlist; -} - -void file_editor_tab::remove_bookmark (const QWidget *ID) -{ - if (ID != this) - return; - - m_edit_area->markerDeleteAll (marker::bookmark); -} - -void -file_editor_tab::handle_request_add_breakpoint (int line, - const QString& condition) -{ - if (! m_is_octave_file) - return; - - add_breakpoint_event (line, condition); -} - -void file_editor_tab::handle_request_remove_breakpoint (int line) -{ - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - tree_evaluator& tw = interp.get_evaluator (); - bp_table& bptab = tw.get_bp_table (); - - bptab.remove_breakpoint_from_file (m_file_name.toStdString (), line); - }); -} - -void file_editor_tab::toggle_breakpoint (const QWidget *ID) -{ - if (ID != this) - return; - - int editor_linenr, cur; - m_edit_area->getCursorPosition (&editor_linenr, &cur); - - if (m_edit_area->markersAtLine (editor_linenr) & (1 << marker::breakpoint)) - request_remove_breakpoint_via_editor_linenr (editor_linenr); - else - { - if (unchanged_or_saved ()) - handle_request_add_breakpoint (editor_linenr + 1, ""); - } -} - -// Move the text cursor to the closest breakpoint (conditional or unconditional) -// after the current line. -void file_editor_tab::next_breakpoint (const QWidget *ID) -{ - if (ID != this) - return; - - int line, cur; - m_edit_area->getCursorPosition (&line, &cur); - - line++; // Find breakpoint strictly after the current line. - - int nextline = m_edit_area->markerFindNext (line, (1 << marker::breakpoint)); - int nextcond = m_edit_area->markerFindNext (line, (1 << marker::cond_break)); - - // Check if the next conditional breakpoint is before next unconditional one. - if (nextcond != -1 && (nextcond < nextline || nextline == -1)) - nextline = nextcond; - - m_edit_area->setCursorPosition (nextline, 0); -} - -// Move the text cursor to the closest breakpoint (conditional or unconditional) -// before the current line. -void file_editor_tab::previous_breakpoint (const QWidget *ID) -{ - if (ID != this) - return; - - int line, cur, prevline, prevcond; - m_edit_area->getCursorPosition (&line, &cur); - - line--; // Find breakpoint strictly before the current line. - - prevline = m_edit_area->markerFindPrevious (line, (1 << marker::breakpoint)); - prevcond = m_edit_area->markerFindPrevious (line, (1 << marker::cond_break)); - - // Check if the prev conditional breakpoint is closer than the unconditional. - if (prevcond != -1 && prevcond > prevline) - prevline = prevcond; - - m_edit_area->setCursorPosition (prevline, 0); -} - -void file_editor_tab::remove_all_breakpoints (const QWidget *ID) -{ - if (ID != this) - return; - - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - tree_evaluator& tw = interp.get_evaluator (); - bp_table& bptab = tw.get_bp_table (); - - bptab.remove_all_breakpoints_from_file (m_file_name.toStdString (), - true); - }); -} - -void file_editor_tab::scintilla_command (const QWidget *ID, - unsigned int sci_msg) -{ - if (ID != this) - return; - - m_edit_area->SendScintilla (sci_msg); -} - -void file_editor_tab::comment_selected_text (const QWidget *ID, - bool input_str) -{ - if (ID != this) - return; - - do_comment_selected_text (true, input_str); -} - -void file_editor_tab::uncomment_selected_text (const QWidget *ID) -{ - if (ID != this) - return; - - do_comment_selected_text (false); -} - -void file_editor_tab::indent_selected_text (const QWidget *ID) -{ - if (ID != this) - return; - - do_indent_selected_text (true); -} - -void file_editor_tab::unindent_selected_text (const QWidget *ID) -{ - if (ID != this) - return; - - do_indent_selected_text (false); -} - -void file_editor_tab::smart_indent_line_or_selected_text (const QWidget *ID) -{ - if (ID != this) - return; - - do_smart_indent_line_or_selected_text (); -} - -void file_editor_tab::convert_eol (const QWidget *ID, - QsciScintilla::EolMode eol_mode) -{ - if (ID != this) - return; - - m_edit_area->convertEols (eol_mode); - m_edit_area->setEolMode (eol_mode); - update_eol_indicator (); -} - -void file_editor_tab::zoom_in (const QWidget *ID) -{ - if (ID != this) - return; - - m_edit_area->zoomIn (1); - auto_margin_width (); -} - -void file_editor_tab::zoom_out (const QWidget *ID) -{ - if (ID != this) - return; - - m_edit_area->zoomOut (1); - auto_margin_width (); -} - -void file_editor_tab::zoom_normal (const QWidget *ID) -{ - if (ID != this) - return; - - m_edit_area->zoomTo (0); - auto_margin_width (); -} - -void file_editor_tab::add_breakpoint_event (int line, const QString& cond) -{ - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - // FIXME: note duplication with the code in - // handle_context_menu_break_condition. - - tree_evaluator& tw = interp.get_evaluator (); - bp_table& bptab = tw.get_bp_table (); - - int lineno = bptab.add_breakpoint_in_file (m_file_name.toStdString (), - line, cond.toStdString ()); - - if (lineno) - emit maybe_remove_next (lineno); - }); -} - -void file_editor_tab::handle_remove_next (int remove_line) -{ - // Store some info breakpoint - if (m_breakpoint_info.remove_next) - { - m_breakpoint_info.remove_line = remove_line; - m_breakpoint_info.remove_next = false; - } -} - -void file_editor_tab::goto_line (const QWidget *ID, int line) -{ - if (ID != this) - return; - - if (m_bp_restore_count > 0) - { - // This goto-line request is invoked by restoring a breakpoint during - // saving the file, thus, do not go to the related line - m_bp_restore_count--; + } + + if (line <= 0) // ask for desired line + { + bool ok = false; + int index; + m_edit_area->getCursorPosition (&line, &index); + line = QInputDialog::getInt (m_edit_area, tr ("Goto line"), + tr ("Line number"), line+1, 1, + m_edit_area->lines (), 1, &ok); + if (ok) + m_edit_area->setCursorPosition (line-1, 0); + } + else // go to given line without dialog + m_edit_area->setCursorPosition (line-1, 0); + + center_current_line (false); // only center line if at top or bottom + } + + void file_editor_tab::move_match_brace (const QWidget *ID, bool select) + { + if (ID != this) + return; + + if (select) + m_edit_area->selectToMatchingBrace (); + else + m_edit_area->moveToMatchingBrace (); + } + + void file_editor_tab::show_auto_completion (const QWidget *ID) + { + if (ID != this) return; - } - - if (line <= 0) // ask for desired line - { - bool ok = false; - int index; - m_edit_area->getCursorPosition (&line, &index); - line = QInputDialog::getInt (m_edit_area, tr ("Goto line"), - tr ("Line number"), line+1, 1, - m_edit_area->lines (), 1, &ok); - if (ok) - m_edit_area->setCursorPosition (line-1, 0); - } - else // go to given line without dialog - m_edit_area->setCursorPosition (line-1, 0); - - center_current_line (false); // only center line if at top or bottom -} - -void file_editor_tab::move_match_brace (const QWidget *ID, bool select) -{ - if (ID != this) - return; - - if (select) - m_edit_area->selectToMatchingBrace (); - else - m_edit_area->moveToMatchingBrace (); -} - -void file_editor_tab::show_auto_completion (const QWidget *ID) -{ - if (ID != this) - return; - - m_autoc_active = true; - - QsciScintilla::AutoCompletionSource s = m_edit_area->autoCompletionSource (); - switch (s) - { - case QsciScintilla::AcsAll: - m_edit_area->autoCompleteFromAll (); - break; - - case QsciScintilla::AcsAPIs: - m_edit_area->autoCompleteFromAPIs (); - break; - - case QsciScintilla::AcsDocument: - m_edit_area->autoCompleteFromDocument (); - break; - - case QsciScintilla::AcsNone: - break; - } -} - -void file_editor_tab::do_indent_selected_text (bool indent) -{ - // FIXME: - m_edit_area->beginUndoAction (); - - if (m_edit_area->hasSelectedText ()) - { - int lineFrom, lineTo, colFrom, colTo; - m_edit_area->getSelection (&lineFrom, &colFrom, &lineTo, &colTo); - - if (colTo == 0) // the beginning of last line is not selected - lineTo--; // stop at line above - - for (int i = lineFrom; i <= lineTo; i++) - { - if (indent) - m_edit_area->indent (i); - else - m_edit_area->unindent (i); - } - //set selection on (un)indented section - m_edit_area->setSelection (lineFrom, 0, lineTo, - m_edit_area->text (lineTo).length ()-1); - } - else - { - int cpline, col; - m_edit_area->getCursorPosition (&cpline, &col); - if (indent) - m_edit_area->indent (cpline); - else - m_edit_area->unindent (cpline); - } - - m_edit_area->endUndoAction (); -} - -void file_editor_tab::do_smart_indent_line_or_selected_text (void) -{ - m_edit_area->beginUndoAction (); - - int lineFrom, lineTo; - - if (m_edit_area->hasSelectedText ()) - { - int colFrom, colTo; - m_edit_area->getSelection (&lineFrom, &colFrom, &lineTo, &colTo); - - if (colTo == 0) // the beginning of last line is not selected - lineTo--; // stop at line above - } - else - { - int col; - m_edit_area->getCursorPosition (&lineFrom, &col); - - lineTo = lineFrom; - } - - m_edit_area->smart_indent_line_or_selected_text (lineFrom, lineTo); - - m_edit_area->endUndoAction (); -} - -void file_editor_tab::do_comment_selected_text (bool comment, bool input_str) -{ - QRegExp rxc; - QString ws = "^(?:[ \\t]*)"; - QStringList comment_str = m_edit_area->comment_string (comment); - QString used_comment_str = comment_str.at (0); - - if (comment) - { - if (input_str) - { - bool ok; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - used_comment_str - = QInputDialog::getText (this, tr ("Comment selected text"), - tr ("Comment string to use:\n"), - QLineEdit::Normal, - settings->value (ed_last_comment_str, comment_str.at (0)).toString (), - &ok); - - if ((! ok) || used_comment_str.isEmpty ()) - return; // No input, do nothing - else - settings->setValue (ed_last_comment_str, used_comment_str); // Store last - } - } - else - { - // Uncommenting (several strings possible) - - // Sort strings according their length - QStringList comment_str_sorted (comment_str.at (0)); - bool inserted; - - for (int i = 1; i < comment_str.length (); i++) - { - inserted = false; - for (int j = 0; j < comment_str_sorted.length (); j++) - { - if (comment_str.at (i).length () > comment_str_sorted.at (j).length ()) - { - comment_str_sorted.insert (j, comment_str.at (i)); - inserted = true; - break; - } - } - if (! inserted) - comment_str_sorted << comment_str.at (i); - } - - // Create regular expression - QString regexp; - for (int i = 0; i < comment_str_sorted.length (); i++) - { - if (i > 0) - regexp = regexp + QString ("|"); - regexp = regexp + comment_str_sorted.at (i); - } - rxc = QRegExp (ws + "(" + regexp + ")"); - } - - // Do the commenting/uncommenting - int len = 0, lenc = 0; - m_edit_area->beginUndoAction (); - - if (m_edit_area->hasSelectedText ()) - { - int lineFrom, lineTo, colFrom, colTo; - int change_col_from = 1; - int change_col_to = 1; - bool removed; - - m_edit_area->getSelection (&lineFrom, &colFrom, &lineTo, &colTo); - - if (colTo == 0) // the beginning of last line is not selected - lineTo--; // stop at line above - - for (int i = lineFrom; i <= lineTo; i++) - { - if (comment) - { - m_edit_area->insertAt (used_comment_str, i, 0); - } - else - { - QString line (m_edit_area->text (i)); - if ((removed = line.contains (rxc))) - { - len = rxc.matchedLength (); // complete length - QString matched_text = rxc.capturedTexts ().at (0); - lenc = matched_text.remove (QRegExp (ws)).length (); // only comment string - m_edit_area->setSelection (i, len-lenc, i, len); - m_edit_area->removeSelectedText (); - } - - // handle case, where the selection remains unchanged - if (i == lineFrom && (colFrom < len-lenc || ! removed)) - change_col_from = 0; // do not change start of selection - if (i == lineTo && (colTo < len-lenc || ! removed)) - change_col_to = 0; // do not change end of selection - } - } - - // update the selection area - if (comment) - { - colFrom = colFrom + lenc; // shift start position by comment length - if (colTo > 0) - colTo = colTo + lenc; // shift end position by comment length - else - lineTo++; // colTo == 0 , fully select previous line - } - else - { - if (colTo == 0) - lineTo++; // colTo == 0 , fully select previous line - colFrom = colFrom - change_col_from*lenc; - colTo = colTo - change_col_to*lenc; - } - - // set updated selection area - m_edit_area->setSelection (lineFrom, colFrom, lineTo, colTo); - } - else - { - int cpline, col; - m_edit_area->getCursorPosition (&cpline, &col); - if (comment) - m_edit_area->insertAt (used_comment_str, cpline, 0); - else - { - QString line (m_edit_area->text (cpline)); - if (line.contains (rxc)) - { - len = rxc.matchedLength (); // complete length - QString matched_text = rxc.capturedTexts ().at (0); - lenc = matched_text.remove (QRegExp (ws)).length (); // only comment string - m_edit_area->setSelection (cpline, len-lenc, cpline, len); - m_edit_area->removeSelectedText (); - } - } - } - m_edit_area->endUndoAction (); -} - -void file_editor_tab::update_window_title (bool modified) -{ - QString title (""); - QString tooltip (""); - - if (! valid_file_name ()) - title = tr (""); - else - { - QFileInfo file (m_file_name); - title = file.fileName (); - tooltip = m_file_name; - } - - emit file_name_changed (title, tooltip, modified); -} - -void file_editor_tab::handle_copy_available (bool enableCopy) -{ - m_copy_available = enableCopy; - emit editor_state_changed (m_copy_available, m_is_octave_file, - m_edit_area->isModified ()); -} - -// show_dialog: shows a modal or non modal dialog depending on input arg -void file_editor_tab::show_dialog (QDialog *dlg, bool modal) -{ - dlg->setAttribute (Qt::WA_DeleteOnClose); - if (modal) - dlg->exec (); - else - { - dlg->setWindowModality (Qt::NonModal); - dlg->show (); - } -} - -int file_editor_tab::check_file_modified (bool remove) -{ - int decision = QMessageBox::Yes; - if (m_edit_area->isModified ()) - { - // File is modified but not saved, ask user what to do. The file - // editor tab can't be made parent because it may be deleted depending - // upon the response. Instead, change the m_edit_area to read only. - QMessageBox::StandardButtons buttons = QMessageBox::Save | - QMessageBox::Discard | - QMessageBox::Cancel; - - // For now, just a warning message about closing a tab that has been - // modified seems sufficient. Exit-condition-specific messages could - // be achieved by making 'available_actions' a function input string. - QString available_actions = - tr ("Do you want to cancel closing, save or discard the changes?"); - - QString file; - if (valid_file_name ()) - file = m_file_name; - else - file = tr (""); - - QMessageBox *msgBox - = new QMessageBox (QMessageBox::Warning, tr ("Octave Editor"), - tr ("The file\n\n" - " %1\n\n" - "is about to be closed but has been modified. " - "%2"). - arg (file). arg (available_actions), - buttons, qobject_cast (parent ())); - - msgBox->setDefaultButton (QMessageBox::Save); - m_edit_area->setReadOnly (true); - - decision = msgBox->exec (); // show_dialog (msgBox, true); - - if (decision == QMessageBox::Cancel) - m_edit_area->setReadOnly (false); - else if (decision == QMessageBox::Save) - save_file (m_file_name, remove, false); - else + + m_autoc_active = true; + + QsciScintilla::AutoCompletionSource s = m_edit_area->autoCompletionSource (); + switch (s) + { + case QsciScintilla::AcsAll: + m_edit_area->autoCompleteFromAll (); + break; + + case QsciScintilla::AcsAPIs: + m_edit_area->autoCompleteFromAPIs (); + break; + + case QsciScintilla::AcsDocument: + m_edit_area->autoCompleteFromDocument (); + break; + + case QsciScintilla::AcsNone: + break; + } + } + + void file_editor_tab::do_indent_selected_text (bool indent) + { + // FIXME: + m_edit_area->beginUndoAction (); + + if (m_edit_area->hasSelectedText ()) + { + int lineFrom, lineTo, colFrom, colTo; + m_edit_area->getSelection (&lineFrom, &colFrom, &lineTo, &colTo); + + if (colTo == 0) // the beginning of last line is not selected + lineTo--; // stop at line above + + for (int i = lineFrom; i <= lineTo; i++) + { + if (indent) + m_edit_area->indent (i); + else + m_edit_area->unindent (i); + } + //set selection on (un)indented section + m_edit_area->setSelection (lineFrom, 0, lineTo, + m_edit_area->text (lineTo).length ()-1); + } + else + { + int cpline, col; + m_edit_area->getCursorPosition (&cpline, &col); + if (indent) + m_edit_area->indent (cpline); + else + m_edit_area->unindent (cpline); + } + + m_edit_area->endUndoAction (); + } + + void file_editor_tab::do_smart_indent_line_or_selected_text (void) + { + m_edit_area->beginUndoAction (); + + int lineFrom, lineTo; + + if (m_edit_area->hasSelectedText ()) + { + int colFrom, colTo; + m_edit_area->getSelection (&lineFrom, &colFrom, &lineTo, &colTo); + + if (colTo == 0) // the beginning of last line is not selected + lineTo--; // stop at line above + } + else + { + int col; + m_edit_area->getCursorPosition (&lineFrom, &col); + + lineTo = lineFrom; + } + + m_edit_area->smart_indent_line_or_selected_text (lineFrom, lineTo); + + m_edit_area->endUndoAction (); + } + + void file_editor_tab::do_comment_selected_text (bool comment, bool input_str) + { + QRegExp rxc; + QString ws = "^(?:[ \\t]*)"; + QStringList comment_str = m_edit_area->comment_string (comment); + QString used_comment_str = comment_str.at (0); + + if (comment) + { + if (input_str) + { + bool ok; + gui_settings settings; + + used_comment_str + = QInputDialog::getText (this, tr ("Comment selected text"), + tr ("Comment string to use:\n"), + QLineEdit::Normal, + settings.value (ed_last_comment_str, comment_str.at (0)).toString (), + &ok); + + if ((! ok) || used_comment_str.isEmpty ()) + return; // No input, do nothing + else + settings.setValue (ed_last_comment_str, used_comment_str); // Store last + } + } + else + { + // Uncommenting (several strings possible) + + // Sort strings according their length + QStringList comment_str_sorted (comment_str.at (0)); + bool inserted; + + for (int i = 1; i < comment_str.length (); i++) + { + inserted = false; + for (int j = 0; j < comment_str_sorted.length (); j++) + { + if (comment_str.at (i).length () > comment_str_sorted.at (j).length ()) + { + comment_str_sorted.insert (j, comment_str.at (i)); + inserted = true; + break; + } + } + if (! inserted) + comment_str_sorted << comment_str.at (i); + } + + // Create regular expression + QString regexp; + for (int i = 0; i < comment_str_sorted.length (); i++) + { + if (i > 0) + regexp = regexp + QString ("|"); + regexp = regexp + comment_str_sorted.at (i); + } + rxc = QRegExp (ws + "(" + regexp + ")"); + } + + // Do the commenting/uncommenting + int len = 0, lenc = 0; + m_edit_area->beginUndoAction (); + + if (m_edit_area->hasSelectedText ()) + { + int lineFrom, lineTo, colFrom, colTo; + int change_col_from = 1; + int change_col_to = 1; + bool removed; + + m_edit_area->getSelection (&lineFrom, &colFrom, &lineTo, &colTo); + + if (colTo == 0) // the beginning of last line is not selected + lineTo--; // stop at line above + + for (int i = lineFrom; i <= lineTo; i++) + { + if (comment) + { + m_edit_area->insertAt (used_comment_str, i, 0); + } + else + { + QString line (m_edit_area->text (i)); + if ((removed = line.contains (rxc))) + { + len = rxc.matchedLength (); // complete length + QString matched_text = rxc.capturedTexts ().at (0); + lenc = matched_text.remove (QRegExp (ws)).length (); // only comment string + m_edit_area->setSelection (i, len-lenc, i, len); + m_edit_area->removeSelectedText (); + } + + // handle case, where the selection remains unchanged + if (i == lineFrom && (colFrom < len-lenc || ! removed)) + change_col_from = 0; // do not change start of selection + if (i == lineTo && (colTo < len-lenc || ! removed)) + change_col_to = 0; // do not change end of selection + } + } + + // update the selection area + if (comment) + { + colFrom = colFrom + lenc; // shift start position by comment length + if (colTo > 0) + colTo = colTo + lenc; // shift end position by comment length + else + lineTo++; // colTo == 0 , fully select previous line + } + else + { + if (colTo == 0) + lineTo++; // colTo == 0 , fully select previous line + colFrom = colFrom - change_col_from*lenc; + colTo = colTo - change_col_to*lenc; + } + + // set updated selection area + m_edit_area->setSelection (lineFrom, colFrom, lineTo, colTo); + } + else + { + int cpline, col; + m_edit_area->getCursorPosition (&cpline, &col); + if (comment) + m_edit_area->insertAt (used_comment_str, cpline, 0); + else + { + QString line (m_edit_area->text (cpline)); + if (line.contains (rxc)) + { + len = rxc.matchedLength (); // complete length + QString matched_text = rxc.capturedTexts ().at (0); + lenc = matched_text.remove (QRegExp (ws)).length (); // only comment string + m_edit_area->setSelection (cpline, len-lenc, cpline, len); + m_edit_area->removeSelectedText (); + } + } + } + m_edit_area->endUndoAction (); + } + + void file_editor_tab::update_window_title (bool modified) + { + QString title (""); + QString tooltip (""); + + if (! valid_file_name ()) + title = tr (""); + else + { + QFileInfo file (m_file_name); + title = file.fileName (); + tooltip = m_file_name; + } + + emit file_name_changed (title, tooltip, modified); + } + + void file_editor_tab::handle_copy_available (bool enableCopy) + { + m_copy_available = enableCopy; + emit editor_state_changed (m_copy_available, m_is_octave_file, + m_edit_area->isModified ()); + } + + // show_dialog: shows a modal or non modal dialog depending on input arg + void file_editor_tab::show_dialog (QDialog *dlg, bool modal) + { + dlg->setAttribute (Qt::WA_DeleteOnClose); + if (modal) + dlg->exec (); + else + { + dlg->setWindowModality (Qt::NonModal); + dlg->show (); + } + } + + int file_editor_tab::check_file_modified (bool remove) + { + int decision = QMessageBox::Yes; + if (m_edit_area->isModified ()) + { + // File is modified but not saved, ask user what to do. The file + // editor tab can't be made parent because it may be deleted depending + // upon the response. Instead, change the m_edit_area to read only. + QMessageBox::StandardButtons buttons = QMessageBox::Save | + QMessageBox::Discard | + QMessageBox::Cancel; + + // For now, just a warning message about closing a tab that has been + // modified seems sufficient. Exit-condition-specific messages could + // be achieved by making 'available_actions' a function input string. + QString available_actions = + tr ("Do you want to cancel closing, save or discard the changes?"); + + QString file; + if (valid_file_name ()) + file = m_file_name; + else + file = tr (""); + + QMessageBox *msgBox + = new QMessageBox (QMessageBox::Warning, tr ("Octave Editor"), + tr ("The file\n\n" + " %1\n\n" + "is about to be closed but has been modified. " + "%2"). + arg (file). arg (available_actions), + buttons, qobject_cast (parent ())); + + msgBox->setDefaultButton (QMessageBox::Save); + m_edit_area->setReadOnly (true); + + decision = msgBox->exec (); // show_dialog (msgBox, true); + + if (decision == QMessageBox::Cancel) + m_edit_area->setReadOnly (false); + else if (decision == QMessageBox::Save) + save_file (m_file_name, remove, false); + else + emit tab_ready_to_close (); + } + else + { emit tab_ready_to_close (); - } - else - { - emit tab_ready_to_close (); - } - - return decision; -} - -void file_editor_tab::set_modified (bool modified) -{ - m_edit_area->setModified (modified); -} - -void file_editor_tab::recover_from_exit (void) -{ - // reset the possibly still existing read only state - m_edit_area->setReadOnly (false); - - // if we are in this slot and the list of breakpoints is not empty, - // then this tab was saved during an exit of the applications (not - // restoring the breakpoints and not emptying the list) and the user - // canceled this closing late on. - check_restore_breakpoints (); -} - -void file_editor_tab::check_restore_breakpoints (void) -{ - if (! m_bp_lines.isEmpty ()) - { - // At least one breakpoint is present. - // Get rid of breakpoints at old (now possibly invalid) linenumbers - remove_all_breakpoints (this); - - // and set breakpoints at the new linenumbers - m_bp_restore_count = m_bp_lines.length (); - for (int i = 0; i < m_bp_lines.length (); i++) - handle_request_add_breakpoint (m_bp_lines.value (i) + 1, - m_bp_conditions.value (i)); - - // Keep the list of breakpoints empty, except after explicit requests. - m_bp_lines.clear (); - m_bp_conditions.clear (); - } -} - -QString file_editor_tab::load_file (const QString& fileName) -{ - // get the absolute path - QFileInfo file_info = QFileInfo (fileName); - QString file_to_load; - if (file_info.exists ()) - file_to_load = file_info.canonicalFilePath (); - else - file_to_load = fileName; - QFile file (file_to_load); - if (!file.open(QIODevice::ReadOnly)) - return file.errorString (); - - int col = 0, line = 0; - if (fileName == m_file_name) - { - // We have to reload the current file, thus get current cursor position - line = m_line; - col = m_col; - } - - QApplication::setOverrideCursor (Qt::WaitCursor); - - // read the file binary, decoding later - QByteArray text_data = file.readAll (); - - // remove newline at end of file if we add one again when saving - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (settings->value (ed_force_newline).toBool ()) - { - const QByteArray eol_lf = QByteArray (1, 0x0a); - const QByteArray eol_cr = QByteArray (1, 0x0d); - - if (text_data.endsWith (eol_lf)) - text_data.chop (1); // remove LF - - if (text_data.endsWith (eol_cr)) // remove CR (altogether CRLF, too) - text_data.chop (1); - } - - // decode - QTextCodec::ConverterState st; - QTextCodec *codec = QTextCodec::codecForName (m_encoding.toLatin1 ()); - if (codec == nullptr) - codec = QTextCodec::codecForLocale (); - - const QString text = codec->toUnicode(text_data.constData(), - text_data.size(), &st); - - // Decoding with invalid characters? - if (st.invalidChars > 0) - { - // Set read only - m_edit_area->setReadOnly (true); - - // Message box for user decision - QString msg = tr ("There were problems reading the file\n" - "%1\n" - "with the selected encoding %2.\n\n" - "Modifying and saving the file might " - "cause data loss!") - .arg (file_to_load).arg (m_encoding); - QMessageBox *msg_box = new QMessageBox (); - msg_box->setIcon (QMessageBox::Warning); - msg_box->setText (msg); - msg_box->setWindowTitle (tr ("Octave Editor")); - msg_box->addButton (tr ("&Edit anyway"), QMessageBox::YesRole); - msg_box->addButton (tr ("Chan&ge encoding"), QMessageBox::AcceptRole); - msg_box->addButton (tr ("&Close"), QMessageBox::RejectRole); - - connect (msg_box, &QMessageBox::buttonClicked, - this, &file_editor_tab::handle_decode_warning_answer); - - msg_box->setWindowModality (Qt::WindowModal); - msg_box->setAttribute (Qt::WA_DeleteOnClose); - msg_box->show (); - } - - m_edit_area->setText (text); - m_edit_area->setEolMode (detect_eol_mode ()); - - QApplication::restoreOverrideCursor (); - - m_copy_available = false; // no selection yet available - m_edit_area->setModified (false); // loaded file is not modified yet - set_file_name (file_to_load); - - update_eol_indicator (); - - m_edit_area->setCursorPosition (line, col); - - return QString (); -} - -void file_editor_tab::handle_decode_warning_answer (QAbstractButton *btn) -{ - QString txt = btn->text (); - - if (txt == tr ("&Close")) - { - // Just close the file - close (); + } + + return decision; + } + + void file_editor_tab::set_modified (bool modified) + { + m_edit_area->setModified (modified); + } + + void file_editor_tab::recover_from_exit (void) + { + // reset the possibly still existing read only state + m_edit_area->setReadOnly (false); + + // if we are in this slot and the list of breakpoints is not empty, + // then this tab was saved during an exit of the applications (not + // restoring the breakpoints and not emptying the list) and the user + // canceled this closing late on. + check_restore_breakpoints (); + } + + void file_editor_tab::check_restore_breakpoints (void) + { + if (! m_bp_lines.isEmpty ()) + { + // At least one breakpoint is present. + // Get rid of breakpoints at old (now possibly invalid) linenumbers + remove_all_breakpoints (this); + + // and set breakpoints at the new linenumbers + m_bp_restore_count = m_bp_lines.length (); + for (int i = 0; i < m_bp_lines.length (); i++) + handle_request_add_breakpoint (m_bp_lines.value (i) + 1, + m_bp_conditions.value (i)); + + // Keep the list of breakpoints empty, except after explicit requests. + m_bp_lines.clear (); + m_bp_conditions.clear (); + } + } + + QString file_editor_tab::load_file (const QString& fileName) + { + // get the absolute path + QFileInfo file_info = QFileInfo (fileName); + QString file_to_load; + if (file_info.exists ()) + file_to_load = file_info.canonicalFilePath (); + else + file_to_load = fileName; + QFile file (file_to_load); + if (!file.open(QIODevice::ReadOnly)) + return file.errorString (); + + int col = 0, line = 0; + if (fileName == m_file_name) + { + // We have to reload the current file, thus get current cursor position + line = m_line; + col = m_col; + } + + QApplication::setOverrideCursor (Qt::WaitCursor); + + // read the file binary, decoding later + QByteArray text_data = file.readAll (); + + // remove newline at end of file if we add one again when saving + + gui_settings settings; + + if (settings.value (ed_force_newline).toBool ()) + { + const QByteArray eol_lf = QByteArray (1, 0x0a); + const QByteArray eol_cr = QByteArray (1, 0x0d); + + if (text_data.endsWith (eol_lf)) + text_data.chop (1); // remove LF + + if (text_data.endsWith (eol_cr)) // remove CR (altogether CRLF, too) + text_data.chop (1); + } + + // decode + QTextCodec::ConverterState st; + QTextCodec *codec = QTextCodec::codecForName (m_encoding.toLatin1 ()); + if (codec == nullptr) + codec = QTextCodec::codecForLocale (); + + const QString text = codec->toUnicode(text_data.constData(), + text_data.size(), &st); + + // Decoding with invalid characters? + if (st.invalidChars > 0) + { + // Set read only + m_edit_area->setReadOnly (true); + + // Message box for user decision + QString msg = tr ("There were problems reading the file\n" + "%1\n" + "with the selected encoding %2.\n\n" + "Modifying and saving the file might " + "cause data loss!") + .arg (file_to_load).arg (m_encoding); + QMessageBox *msg_box = new QMessageBox (); + msg_box->setIcon (QMessageBox::Warning); + msg_box->setText (msg); + msg_box->setWindowTitle (tr ("Octave Editor")); + msg_box->addButton (tr ("&Edit anyway"), QMessageBox::YesRole); + msg_box->addButton (tr ("Chan&ge encoding"), QMessageBox::AcceptRole); + msg_box->addButton (tr ("&Close"), QMessageBox::RejectRole); + + connect (msg_box, &QMessageBox::buttonClicked, + this, &file_editor_tab::handle_decode_warning_answer); + + msg_box->setWindowModality (Qt::WindowModal); + msg_box->setAttribute (Qt::WA_DeleteOnClose); + msg_box->show (); + } + + m_edit_area->setText (text); + m_edit_area->setEolMode (detect_eol_mode ()); + + QApplication::restoreOverrideCursor (); + + m_copy_available = false; // no selection yet available + m_edit_area->setModified (false); // loaded file is not modified yet + set_file_name (file_to_load); + + update_eol_indicator (); + + m_edit_area->setCursorPosition (line, col); + + return QString (); + } + + void file_editor_tab::handle_decode_warning_answer (QAbstractButton *btn) + { + QString txt = btn->text (); + + if (txt == tr ("&Close")) + { + // Just close the file + close (); + return; + } + + if (txt == tr ("Chan&ge encoding")) + { + // Dialog for reloading the file with another encoding + QDialog dlg; + dlg.setWindowTitle (tr ("Select new default encoding")); + + QLabel *text + = new QLabel (tr ("Please select a new encoding\n" + "for reloading the current file.\n\n" + "This does not change the default encoding.\n")); + + QComboBox *enc_combo = new QComboBox (); + resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + rmgr.combo_encoding (enc_combo); + m_new_encoding = enc_combo->currentText (); + connect (enc_combo, &QComboBox::currentTextChanged, + this, &file_editor_tab::handle_current_enc_changed); + + QDialogButtonBox *buttons + = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel, + Qt::Horizontal); + connect (buttons, &QDialogButtonBox::accepted, &dlg, &QDialog::accept); + connect (buttons, &QDialogButtonBox::rejected, &dlg, &QDialog::reject); + + QGridLayout *main_layout = new QGridLayout; + main_layout->setSizeConstraint (QLayout::SetFixedSize); + main_layout->addWidget (text, 0, 0); + main_layout->addWidget (enc_combo, 1, 0); + main_layout->addWidget (buttons, 2, 0); + dlg.setLayout (main_layout); + + int answer = dlg.exec (); + + if (answer == QDialog::Accepted) + { + // Reload the file with new encoding but using the same tab + QString reload_file_name = m_file_name; // store file name + m_file_name = ""; // force reuse of this tab when opening a new file + emit request_open_file (reload_file_name, m_new_encoding); + } + } + + // Continue editing, set writable again + m_edit_area->setReadOnly (false); + } + + void file_editor_tab::handle_current_enc_changed (const QString& enc) + { + m_new_encoding = enc; + } + + QsciScintilla::EolMode file_editor_tab::detect_eol_mode (void) + { + QByteArray text = m_edit_area->text ().toLatin1 (); + + QByteArray eol_lf = QByteArray (1, 0x0a); + QByteArray eol_cr = QByteArray (1, 0x0d); + QByteArray eol_crlf = eol_cr; + eol_crlf.append (eol_lf); + + int count_crlf = text.count (eol_crlf); + int count_lf = text.count (eol_lf) - count_crlf; // isolated lf + int count_cr = text.count (eol_cr) - count_crlf; // isolated cr + + gui_settings settings; + + QsciScintilla::EolMode eol_mode + = static_cast (settings.value (ed_default_eol_mode).toInt ()); + + int count_max = 0; + + if (count_crlf > count_max) + { + eol_mode = QsciScintilla::EolWindows; + count_max = count_crlf; + } + if (count_lf > count_max) + { + eol_mode = QsciScintilla::EolUnix; + count_max = count_lf; + } + if (count_cr > count_max) + { + eol_mode = QsciScintilla::EolMac; + } + + return eol_mode; + } + + void file_editor_tab::update_eol_indicator (void) + { + switch (m_edit_area->eolMode ()) + { + case QsciScintilla::EolWindows: + m_eol_indicator->setText ("CRLF"); + break; + case QsciScintilla::EolMac: + m_eol_indicator->setText ("CR"); + break; + case QsciScintilla::EolUnix: + m_eol_indicator->setText ("LF"); + break; + } + } + + void file_editor_tab::update_breakpoints () + { + if (m_file_name.isEmpty ()) return; - } - - if (txt == tr ("Chan&ge encoding")) - { - // Dialog for reloading the file with another encoding - QDialog dlg; - dlg.setWindowTitle (tr ("Select new default encoding")); - - QLabel *text - = new QLabel (tr ("Please select a new encoding\n" - "for reloading the current file.\n\n" - "This does not change the default encoding.\n")); - - QComboBox *enc_combo = new QComboBox (); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - rmgr.combo_encoding (enc_combo); - m_new_encoding = enc_combo->currentText (); - connect (enc_combo, &QComboBox::currentTextChanged, - this, &file_editor_tab::handle_current_enc_changed); - - QDialogButtonBox *buttons - = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel, - Qt::Horizontal); - connect (buttons, &QDialogButtonBox::accepted, &dlg, &QDialog::accept); - connect (buttons, &QDialogButtonBox::rejected, &dlg, &QDialog::reject); - - QGridLayout *main_layout = new QGridLayout; - main_layout->setSizeConstraint (QLayout::SetFixedSize); - main_layout->addWidget (text, 0, 0); - main_layout->addWidget (enc_combo, 1, 0); - main_layout->addWidget (buttons, 2, 0); - dlg.setLayout (main_layout); - - int answer = dlg.exec (); - - if (answer == QDialog::Accepted) - { - // Reload the file with new encoding but using the same tab - QString reload_file_name = m_file_name; // store file name - m_file_name = ""; // force reuse of this tab when opening a new file - emit request_open_file (reload_file_name, m_new_encoding); - } - } - - // Continue editing, set writable again - m_edit_area->setReadOnly (false); -} - -void file_editor_tab::handle_current_enc_changed (const QString& enc) -{ - m_new_encoding = enc; -} - -QsciScintilla::EolMode file_editor_tab::detect_eol_mode (void) -{ - QByteArray text = m_edit_area->text ().toLatin1 (); - - QByteArray eol_lf = QByteArray (1, 0x0a); - QByteArray eol_cr = QByteArray (1, 0x0d); - QByteArray eol_crlf = eol_cr; - eol_crlf.append (eol_lf); - - int count_crlf = text.count (eol_crlf); - int count_lf = text.count (eol_lf) - count_crlf; // isolated lf - int count_cr = text.count (eol_cr) - count_crlf; // isolated cr - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - QsciScintilla::EolMode eol_mode - = static_cast (settings->value (ed_default_eol_mode).toInt ()); - - int count_max = 0; - - if (count_crlf > count_max) - { - eol_mode = QsciScintilla::EolWindows; - count_max = count_crlf; - } - if (count_lf > count_max) - { - eol_mode = QsciScintilla::EolUnix; - count_max = count_lf; - } - if (count_cr > count_max) - { - eol_mode = QsciScintilla::EolMac; - } - - return eol_mode; -} - -void file_editor_tab::update_eol_indicator (void) -{ - switch (m_edit_area->eolMode ()) - { - case QsciScintilla::EolWindows: - m_eol_indicator->setText ("CRLF"); - break; - case QsciScintilla::EolMac: - m_eol_indicator->setText ("CR"); - break; - case QsciScintilla::EolUnix: - m_eol_indicator->setText ("LF"); - break; - } -} - -void file_editor_tab::update_breakpoints () -{ - if (m_file_name.isEmpty ()) - return; - - // Create and queue the command object. - - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - octave_value_list argout = Fdbstatus (interp, ovl (), 1); - - connect (this, &file_editor_tab::update_breakpoints_signal, - this, &file_editor_tab::update_breakpoints_handler, - Qt::QueuedConnection); - - emit update_breakpoints_signal (argout); - }); -} - -void file_editor_tab::update_breakpoints_handler (const octave_value_list& argout) -{ - octave_map dbg = argout(0).map_value (); - octave_idx_type n_dbg = dbg.numel (); - - Cell file = dbg.contents ("file"); - Cell line = dbg.contents ("line"); - Cell cond = dbg.contents ("cond"); - - for (octave_idx_type i = 0; i < n_dbg; i++) - { - if (file (i).string_value () == m_file_name.toStdString ()) - do_breakpoint_marker (true, this, line (i).int_value (), - QString::fromStdString (cond (i).string_value ())); - } -} - -void file_editor_tab::new_file (const QString& commands) -{ - update_window_title (false); // window title (no modification) - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - // set the eol mode from the settings or depending on the OS if the entry is - // missing in the settings - m_edit_area->setEolMode (static_cast (settings->value (ed_default_eol_mode).toInt ())); - - update_eol_indicator (); - - update_lexer (); - - m_edit_area->setText (commands); - m_edit_area->setModified (!commands.isEmpty ()); -} - -void file_editor_tab::confirm_dbquit_and_save (const QString& file_to_save, - const QString& base_name, - bool remove_on_success, - bool restore_breakpoints) -{ - int ans = QMessageBox::question (nullptr, tr ("Debug or Save"), - tr ("This file is currently being executed.\n" - "Quit debugging and save?"), - QMessageBox::Save | QMessageBox::Cancel); - - if (ans == QMessageBox::Save) - { - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - tree_evaluator& tw = interp.get_evaluator (); - - tw.dbquit (true); - - command_editor::interrupt (true); - - std::string std_base_name = base_name.toStdString (); - - symbol_table& symtab = interp.get_symbol_table (); - - symtab.clear_user_function (std_base_name); - - emit do_save_file_signal (file_to_save, remove_on_success, - restore_breakpoints); - }); - } -} - -void file_editor_tab::save_file (const QString& saveFileName, - bool remove_on_success, - bool restore_breakpoints) -{ - // If it is a new file with no name, signal that saveFileAs - // should be performed. - if (! valid_file_name (saveFileName)) - { - save_file_as (remove_on_success); + + // Create and queue the command object. + + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + octave_value_list argout = Fdbstatus (interp, ovl (), 1); + + connect (this, &file_editor_tab::update_breakpoints_signal, + this, &file_editor_tab::update_breakpoints_handler, + Qt::QueuedConnection); + + emit update_breakpoints_signal (argout); + }); + } + + void file_editor_tab::update_breakpoints_handler (const octave_value_list& argout) + { + octave_map dbg = argout(0).map_value (); + octave_idx_type n_dbg = dbg.numel (); + + Cell file = dbg.contents ("file"); + Cell line = dbg.contents ("line"); + Cell cond = dbg.contents ("cond"); + + for (octave_idx_type i = 0; i < n_dbg; i++) + { + if (file (i).string_value () == m_file_name.toStdString ()) + do_breakpoint_marker (true, this, line (i).int_value (), + QString::fromStdString (cond (i).string_value ())); + } + } + + void file_editor_tab::new_file (const QString& commands) + { + update_window_title (false); // window title (no modification) + + gui_settings settings; + + // set the eol mode from the settings or depending on the OS if the entry is + // missing in the settings + m_edit_area->setEolMode (static_cast (settings.value (ed_default_eol_mode).toInt ())); + + update_eol_indicator (); + + update_lexer (); + + m_edit_area->setText (commands); + m_edit_area->setModified (!commands.isEmpty ()); + } + + void file_editor_tab::confirm_dbquit_and_save (const QString& file_to_save, + const QString& base_name, + bool remove_on_success, + bool restore_breakpoints) + { + int ans = QMessageBox::question (nullptr, tr ("Debug or Save"), + tr ("This file is currently being executed.\n" + "Quit debugging and save?"), + QMessageBox::Save | QMessageBox::Cancel); + + if (ans == QMessageBox::Save) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + tree_evaluator& tw = interp.get_evaluator (); + + tw.dbquit (true); + + command_editor::interrupt (true); + + std::string std_base_name = base_name.toStdString (); + + symbol_table& symtab = interp.get_symbol_table (); + + symtab.clear_user_function (std_base_name); + + emit do_save_file_signal (file_to_save, remove_on_success, + restore_breakpoints); + }); + } + } + + void file_editor_tab::save_file (const QString& saveFileName, + bool remove_on_success, + bool restore_breakpoints) + { + // If it is a new file with no name, signal that saveFileAs + // should be performed. + if (! valid_file_name (saveFileName)) + { + save_file_as (remove_on_success); + return; + } + + m_encoding = m_new_encoding; // consider a possible new encoding + + // set the desired codec (if suitable for contents) + QTextCodec *codec = check_valid_codec (); + if (! codec) + return; // No valid codec + + // Get a list of breakpoint line numbers, before exiting debug mode + // and clearing function in interpreter_event action below. + + emit report_marker_linenr (m_bp_lines, m_bp_conditions); + + // get the absolute path (if existing) + QFileInfo file_info = QFileInfo (saveFileName); + QString file_to_save; + if (file_info.exists ()) + { + file_to_save = file_info.canonicalFilePath (); + QString base_name = file_info.baseName (); + + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + // Force reloading of a file after it is saved. + // This is needed to get the right line numbers for + // breakpoints (bug #46632). + + tree_evaluator& tw = interp.get_evaluator (); + + symbol_table& symtab = interp.get_symbol_table (); + + std::string std_base_name = base_name.toStdString (); + + if (tw.in_debug_repl ()) + { + octave_value sym; + try + { + sym = symtab.find_user_function (std_base_name); + } + catch (const execution_exception&) + { + interp.recover_from_exception (); + + // Ignore syntax error. It was in the old file on disk; + // the user may have fixed it already. + } + + // Return early if this file is not loaded in the symbol table + if (! sym.is_defined () || ! sym.is_user_code ()) + { + emit do_save_file_signal (file_to_save, remove_on_success, + restore_breakpoints); + return; + } + + octave_user_code *fcn = sym.user_code_value (); + + std::string full_name = file_to_save.toStdString (); + + if (sys::canonicalize_file_name (full_name) + != sys::canonicalize_file_name (fcn->fcn_file_name ())) + { + emit do_save_file_signal (file_to_save, remove_on_success, + restore_breakpoints); + return; + } + + // If this file is loaded, check that we aren't currently + // running it. + // FIXME: is there a better way to get this info? + + octave_idx_type curr_frame = -1; + + octave_map stk = tw.backtrace (curr_frame, false); + + Cell names = stk.contents ("name"); + + for (octave_idx_type i = names.numel () - 1; i >= 0; i--) + { + if (names(i).string_value () == std_base_name) + { + emit confirm_dbquit_and_save_signal + (file_to_save, base_name, remove_on_success, + restore_breakpoints); + return; + } + } + } + + symtab.clear_user_function (std_base_name); + + emit do_save_file_signal (file_to_save, remove_on_success, + restore_breakpoints); + }); + } + else + emit do_save_file_signal (saveFileName, remove_on_success, + restore_breakpoints); + } + + void file_editor_tab::do_save_file (const QString& file_to_save, + bool remove_on_success, + bool restore_breakpoints) + { + QSaveFile file (file_to_save); + + // stop watching file + QStringList trackedFiles = m_file_system_watcher.files (); + if (trackedFiles.contains (file_to_save)) + m_file_system_watcher.removePath (file_to_save); + + // Remove trailing white spaces if desired + + gui_settings settings; + + if (settings.value (ed_rm_trailing_spaces).toBool ()) + { + // Replace trailing spaces, make sure edit area is writable, + // which is not the case when saving at exit or when closing + // the modified file. + bool ro = m_edit_area->isReadOnly (); + m_edit_area->setReadOnly (false); // allow writing for replace_all + m_edit_area->replace_all ("[ \\t]+$", "", true, false, false); + m_edit_area->setReadOnly (ro); // recover read only state + } + + // open the file for writing (use QIODevice::ReadWrite for avoiding + // truncating the previous file contents) + if (! file.open (QIODevice::WriteOnly)) + { + // Unsuccessful, begin watching file again if it was being + // watched previously. + if (trackedFiles.contains (file_to_save)) + m_file_system_watcher.addPath (file_to_save); + + // Create a NonModal message about error. + QMessageBox *msgBox + = new QMessageBox (QMessageBox::Critical, + tr ("Octave Editor"), + tr ("Could not open file %1 for write:\n%2."). + arg (file_to_save).arg (file.errorString ()), + QMessageBox::Ok, nullptr); + show_dialog (msgBox, false); + + return; + } + + // save the contents into the file + + // write the file + QTextStream out (&file); + + // set the desired codec (if suitable for contents) + QTextCodec *codec = check_valid_codec (); + if (! codec) + return; // No valid codec + + // Save the file + out.setCodec (codec); + + QApplication::setOverrideCursor (Qt::WaitCursor); + + out << m_edit_area->text (); + if (settings.value (ed_force_newline).toBool () + && m_edit_area->text ().length ()) + out << m_edit_area->eol_string (); // Add newline if desired + + out.flush (); + QApplication::restoreOverrideCursor (); + + // Finish writing by committing the changes to disk, + // where nothing is done when an error occurred while writing above + bool writing_ok = file.commit (); + + if (writing_ok) + { + // Writing was successful: file exists now + QFileInfo file_info = QFileInfo (file.fileName ()); + QString full_file_to_save = file_info.canonicalFilePath (); + + // file is save -> not modified, update encoding in statusbar + m_edit_area->setModified (false); + m_enc_indicator->setText (m_encoding); + + // save filename after closing file as set_file_name starts watching again + set_file_name (full_file_to_save); // make absolute + + emit tab_ready_to_close (); + + if (remove_on_success) + { + emit tab_remove_request (); + return; // Don't touch member variables after removal + } + + // Attempt to restore the breakpoints if that is desired. + // This is only allowed if the tab is not closing since changing + // breakpoints would reopen the tab in this case. + if (restore_breakpoints) + check_restore_breakpoints (); + } + else + { + QMessageBox::critical (nullptr, + tr ("Octave Editor"), + tr ("The changes could not be saved to the file\n" + "%1") + .arg (file.fileName ()) + ); + } + } + + void file_editor_tab::save_file_as (bool remove_on_success) + { + // Simply put up the file chooser dialog box with a slot connection + // then return control to the system waiting for a file selection. + + // reset m_new_encoding + m_new_encoding = m_encoding; + + // If the tab is removed in response to a QFileDialog signal, the tab + // can't be a parent. + QFileDialog *fileDialog; + if (remove_on_success) + { + // If tab is closed, "this" cannot be parent in which case modality + // has no effect. Disable editing instead. + m_edit_area->setReadOnly (true); + fileDialog = new QFileDialog (); + } + else + fileDialog = new QFileDialog (this); + + // add the possible filters and the default suffix + QStringList filters; + filters << tr ("Octave Files (*.m)") + << tr ("All Files (*)"); + fileDialog->setNameFilters (filters); + fileDialog->setDefaultSuffix ("m"); + + if (valid_file_name ()) + { + fileDialog->selectFile (m_file_name); + QFileInfo file_info (m_file_name); + if (file_info.suffix () != "m") + { + // it is not an octave file + fileDialog->selectNameFilter (filters.at (1)); // "All Files" + fileDialog->setDefaultSuffix (""); // no default suffix + } + } + else + { + fileDialog->selectFile (""); + fileDialog->setDirectory (m_ced); + + // propose a name corresponding to the function name + // if the new file contains a function + QString fname = get_function_name (); + if (! fname.isEmpty ()) + fileDialog->selectFile (fname + ".m"); + } + + fileDialog->setAcceptMode (QFileDialog::AcceptSave); + fileDialog->setViewMode (QFileDialog::Detail); + fileDialog->setOption (QFileDialog::HideNameFilterDetails, false); + + // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) + { + // Qt file dialogs + fileDialog->setOption(QFileDialog::DontUseNativeDialog); + } + else + { + // Native file dialogs: Test for already existing files is done manually + // since native file dialogs might not consider the automatically + // appended default extension when checking if the file already exists + fileDialog->setOption(QFileDialog::DontConfirmOverwrite); + } + + connect (fileDialog, &QFileDialog::filterSelected, + this, &file_editor_tab::handle_save_as_filter_selected); + + if (remove_on_success) + { + connect (fileDialog, &QFileDialog::fileSelected, + this, &file_editor_tab::handle_save_file_as_answer_close); + + connect (fileDialog, &QFileDialog::rejected, + this, &file_editor_tab::handle_save_file_as_answer_cancel); + } + else + { + connect (fileDialog, &QFileDialog::fileSelected, + this, &file_editor_tab::handle_save_file_as_answer); + } + + show_dialog (fileDialog, ! valid_file_name ()); + } + + void file_editor_tab::handle_save_as_filter_selected (const QString& filter) + { + // On some systems, the filterSelected signal is emitted without user + // action and with an empty filter string when the file dialog is shown. + // Just return in this case and do not remove the current default suffix. + if (filter.isEmpty ()) return; - } - - m_encoding = m_new_encoding; // consider a possible new encoding - - // set the desired codec (if suitable for contents) - QTextCodec *codec = check_valid_codec (); - if (! codec) - return; // No valid codec - - // Get a list of breakpoint line numbers, before exiting debug mode - // and clearing function in interpreter_event action below. - - emit report_marker_linenr (m_bp_lines, m_bp_conditions); - - // get the absolute path (if existing) - QFileInfo file_info = QFileInfo (saveFileName); - QString file_to_save; - if (file_info.exists ()) - { - file_to_save = file_info.canonicalFilePath (); - QString base_name = file_info.baseName (); - - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - // Force reloading of a file after it is saved. - // This is needed to get the right line numbers for - // breakpoints (bug #46632). - - tree_evaluator& tw = interp.get_evaluator (); - - symbol_table& symtab = interp.get_symbol_table (); - - std::string std_base_name = base_name.toStdString (); - - if (tw.in_debug_repl ()) - { - octave_value sym; - try - { - sym = symtab.find_user_function (std_base_name); - } - catch (const execution_exception&) - { - interp.recover_from_exception (); - - // Ignore syntax error. It was in the old file on disk; - // the user may have fixed it already. - } - - // Return early if this file is not loaded in the symbol table - if (! sym.is_defined () || ! sym.is_user_code ()) - { - emit do_save_file_signal (file_to_save, remove_on_success, - restore_breakpoints); - return; - } - - octave_user_code *fcn = sym.user_code_value (); - - std::string full_name = file_to_save.toStdString (); - - if (sys::canonicalize_file_name (full_name) - != sys::canonicalize_file_name (fcn->fcn_file_name ())) - { - emit do_save_file_signal (file_to_save, remove_on_success, - restore_breakpoints); - return; - } - - // If this file is loaded, check that we aren't currently - // running it. - // FIXME: is there a better way to get this info? - - octave_idx_type curr_frame = -1; - - octave_map stk = tw.backtrace (curr_frame, false); - - Cell names = stk.contents ("name"); - - for (octave_idx_type i = names.numel () - 1; i >= 0; i--) - { - if (names(i).string_value () == std_base_name) - { - emit confirm_dbquit_and_save_signal - (file_to_save, base_name, remove_on_success, - restore_breakpoints); - return; - } - } - } - - symtab.clear_user_function (std_base_name); - - emit do_save_file_signal (file_to_save, remove_on_success, - restore_breakpoints); - }); - } - else - emit do_save_file_signal (saveFileName, remove_on_success, - restore_breakpoints); -} - -void file_editor_tab::do_save_file (const QString& file_to_save, - bool remove_on_success, - bool restore_breakpoints) -{ - QSaveFile file (file_to_save); - - // stop watching file - QStringList trackedFiles = m_file_system_watcher.files (); - if (trackedFiles.contains (file_to_save)) - m_file_system_watcher.removePath (file_to_save); - - // Remove trailing white spaces if desired - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (settings->value (ed_rm_trailing_spaces).toBool ()) - { - // Replace trailing spaces, make sure edit area is writable, - // which is not the case when saving at exit or when closing - // the modified file. - bool ro = m_edit_area->isReadOnly (); - m_edit_area->setReadOnly (false); // allow writing for replace_all - m_edit_area->replace_all ("[ \\t]+$", "", true, false, false); - m_edit_area->setReadOnly (ro); // recover read only state - } - - // open the file for writing (use QIODevice::ReadWrite for avoiding - // truncating the previous file contents) - if (! file.open (QIODevice::WriteOnly)) - { - // Unsuccessful, begin watching file again if it was being - // watched previously. - if (trackedFiles.contains (file_to_save)) - m_file_system_watcher.addPath (file_to_save); - - // Create a NonModal message about error. - QMessageBox *msgBox - = new QMessageBox (QMessageBox::Critical, - tr ("Octave Editor"), - tr ("Could not open file %1 for write:\n%2."). - arg (file_to_save).arg (file.errorString ()), - QMessageBox::Ok, nullptr); - show_dialog (msgBox, false); - - return; - } - - // save the contents into the file - - // write the file - QTextStream out (&file); - - // set the desired codec (if suitable for contents) - QTextCodec *codec = check_valid_codec (); - if (! codec) - return; // No valid codec - - // Save the file - out.setCodec (codec); - - QApplication::setOverrideCursor (Qt::WaitCursor); - - out << m_edit_area->text (); - if (settings->value (ed_force_newline).toBool () - && m_edit_area->text ().length ()) - out << m_edit_area->eol_string (); // Add newline if desired - - out.flush (); - QApplication::restoreOverrideCursor (); - - // Finish writing by committing the changes to disk, - // where nothing is done when an error occurred while writing above - bool writing_ok = file.commit (); - - if (writing_ok) - { - // Writing was successful: file exists now - QFileInfo file_info = QFileInfo (file.fileName ()); - QString full_file_to_save = file_info.canonicalFilePath (); - - // file is save -> not modified, update encoding in statusbar - m_edit_area->setModified (false); - m_enc_indicator->setText (m_encoding); - - // save filename after closing file as set_file_name starts watching again - set_file_name (full_file_to_save); // make absolute - - emit tab_ready_to_close (); - - if (remove_on_success) - { - emit tab_remove_request (); - return; // Don't touch member variables after removal - } - - // Attempt to restore the breakpoints if that is desired. - // This is only allowed if the tab is not closing since changing - // breakpoints would reopen the tab in this case. - if (restore_breakpoints) - check_restore_breakpoints (); - } - else - { - QMessageBox::critical (nullptr, - tr ("Octave Editor"), - tr ("The changes could not be saved to the file\n" - "%1") - .arg (file.fileName ()) - ); - } -} - -void file_editor_tab::save_file_as (bool remove_on_success) -{ - // Simply put up the file chooser dialog box with a slot connection - // then return control to the system waiting for a file selection. - - // reset m_new_encoding - m_new_encoding = m_encoding; - - // If the tab is removed in response to a QFileDialog signal, the tab - // can't be a parent. - QFileDialog *fileDialog; - if (remove_on_success) - { - // If tab is closed, "this" cannot be parent in which case modality - // has no effect. Disable editing instead. - m_edit_area->setReadOnly (true); - fileDialog = new QFileDialog (); - } - else - fileDialog = new QFileDialog (this); - - // add the possible filters and the default suffix - QStringList filters; - filters << tr ("Octave Files (*.m)") - << tr ("All Files (*)"); - fileDialog->setNameFilters (filters); - fileDialog->setDefaultSuffix ("m"); - - if (valid_file_name ()) - { - fileDialog->selectFile (m_file_name); - QFileInfo file_info (m_file_name); - if (file_info.suffix () != "m") - { - // it is not an octave file - fileDialog->selectNameFilter (filters.at (1)); // "All Files" - fileDialog->setDefaultSuffix (""); // no default suffix - } - } - else - { - fileDialog->selectFile (""); - fileDialog->setDirectory (m_ced); - - // propose a name corresponding to the function name - // if the new file contains a function - QString fname = get_function_name (); - if (! fname.isEmpty ()) - fileDialog->selectFile (fname + ".m"); - } - - fileDialog->setAcceptMode (QFileDialog::AcceptSave); - fileDialog->setViewMode (QFileDialog::Detail); - fileDialog->setOption (QFileDialog::HideNameFilterDetails, false); - - // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) - { - // Qt file dialogs - fileDialog->setOption(QFileDialog::DontUseNativeDialog); - } - else - { - // Native file dialogs: Test for already existing files is done manually - // since native file dialogs might not consider the automatically - // appended default extension when checking if the file already exists - fileDialog->setOption(QFileDialog::DontConfirmOverwrite); - } - - connect (fileDialog, &QFileDialog::filterSelected, - this, &file_editor_tab::handle_save_as_filter_selected); - - if (remove_on_success) - { - connect (fileDialog, &QFileDialog::fileSelected, - this, &file_editor_tab::handle_save_file_as_answer_close); - - connect (fileDialog, &QFileDialog::rejected, - this, &file_editor_tab::handle_save_file_as_answer_cancel); - } - else - { - connect (fileDialog, &QFileDialog::fileSelected, - this, &file_editor_tab::handle_save_file_as_answer); - } - - show_dialog (fileDialog, ! valid_file_name ()); -} - -void file_editor_tab::handle_save_as_filter_selected (const QString& filter) -{ - // On some systems, the filterSelected signal is emitted without user - // action and with an empty filter string when the file dialog is shown. - // Just return in this case and do not remove the current default suffix. - if (filter.isEmpty ()) - return; - - QFileDialog *file_dialog = qobject_cast (sender ()); - - QRegExp rx ("\\*\\.([^ ^\\)]*)[ \\)]"); // regexp for suffix in filter - int index = rx.indexIn (filter, 0); // get first suffix in filter - - if (index > -1) - file_dialog->setDefaultSuffix (rx.cap (1)); // found a suffix, set default - else - file_dialog->setDefaultSuffix (""); // not found, clear default -} - -bool file_editor_tab::check_valid_identifier (QString file_name) -{ - QFileInfo file = QFileInfo (file_name); - QString base_name = file.baseName (); - - if ((file.suffix () == "m") - && (! valid_identifier (base_name.toStdString ()))) - { - int ans = QMessageBox::question (nullptr, tr ("Octave Editor"), - tr ("\"%1\"\n" - "is not a valid identifier.\n\n" - "If you keep this filename, you will not be able to\n" - "call your script using its name as an Octave command.\n\n" - "Do you want to choose another name?").arg (base_name), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - - if (ans == QMessageBox::Yes) - return true; - } - - return false; -} - -QTextCodec* file_editor_tab::check_valid_codec () -{ - QTextCodec *codec = QTextCodec::codecForName (m_encoding.toLatin1 ()); - - // "SYSTEM" is used as alias for the locale encoding. - if ((! codec) && m_encoding.startsWith("SYSTEM")) - codec = QTextCodec::codecForLocale (); - - if (! codec) - { - QMessageBox::critical (nullptr, - tr ("Octave Editor"), - tr ("The current encoding %1\n" - "can not be applied.\n\n" - "Please select another one!").arg (m_encoding)); - - return nullptr; - } - - QString editor_text = m_edit_area->text (); - bool can_encode = codec->canEncode (editor_text); - - // We cannot rely on QTextCodec::canEncode because it uses the - // ConverterState of convertFromUnicode which isn't updated by some - // implementations. - if (can_encode) - { - QVector u32_str = editor_text.toUcs4 (); - const uint32_t *src = reinterpret_cast - (u32_str.data ()); - - std::size_t length; - const std::string encoding = m_encoding.toStdString (); - char *res_str = - octave_u32_conv_to_encoding_strict (encoding.c_str (), src, - u32_str.size (), &length); - if (! res_str) - { - if (errno == EILSEQ) - can_encode = false; - } - else - ::free (static_cast (res_str)); - } - - if (! can_encode) - { - QMessageBox::StandardButton pressed_button - = QMessageBox::critical (nullptr, + + QFileDialog *file_dialog = qobject_cast (sender ()); + + QRegExp rx ("\\*\\.([^ ^\\)]*)[ \\)]"); // regexp for suffix in filter + int index = rx.indexIn (filter, 0); // get first suffix in filter + + if (index > -1) + file_dialog->setDefaultSuffix (rx.cap (1)); // found a suffix, set default + else + file_dialog->setDefaultSuffix (""); // not found, clear default + } + + bool file_editor_tab::check_valid_identifier (QString file_name) + { + QFileInfo file = QFileInfo (file_name); + QString base_name = file.baseName (); + + if ((file.suffix () == "m") + && (! valid_identifier (base_name.toStdString ()))) + { + int ans = QMessageBox::question (nullptr, tr ("Octave Editor"), + tr ("\"%1\"\n" + "is not a valid identifier.\n\n" + "If you keep this filename, you will not be able to\n" + "call your script using its name as an Octave command.\n\n" + "Do you want to choose another name?").arg (base_name), + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + + if (ans == QMessageBox::Yes) + return true; + } + + return false; + } + + QTextCodec* file_editor_tab::check_valid_codec () + { + QTextCodec *codec = QTextCodec::codecForName (m_encoding.toLatin1 ()); + + // "SYSTEM" is used as alias for the locale encoding. + if ((! codec) && m_encoding.startsWith("SYSTEM")) + codec = QTextCodec::codecForLocale (); + + if (! codec) + { + QMessageBox::critical (nullptr, + tr ("Octave Editor"), + tr ("The current encoding %1\n" + "can not be applied.\n\n" + "Please select another one!").arg (m_encoding)); + + return nullptr; + } + + QString editor_text = m_edit_area->text (); + bool can_encode = codec->canEncode (editor_text); + + // We cannot rely on QTextCodec::canEncode because it uses the + // ConverterState of convertFromUnicode which isn't updated by some + // implementations. + if (can_encode) + { + QVector u32_str = editor_text.toUcs4 (); + const uint32_t *src = reinterpret_cast + (u32_str.data ()); + + std::size_t length; + const std::string encoding = m_encoding.toStdString (); + char *res_str = + octave_u32_conv_to_encoding_strict (encoding.c_str (), src, + u32_str.size (), &length); + if (! res_str) + { + if (errno == EILSEQ) + can_encode = false; + } + else + ::free (static_cast (res_str)); + } + + if (! can_encode) + { + QMessageBox::StandardButton pressed_button + = QMessageBox::critical (nullptr, + tr ("Octave Editor"), + tr ("The current editor contents can not be encoded\n" + "with the selected encoding %1.\n" + "Using it would result in data loss!\n\n" + "Please select another one!").arg (m_encoding), + QMessageBox::Cancel | QMessageBox::Ignore, + QMessageBox::Cancel); + + if (pressed_button == QMessageBox::Ignore) + return codec; + else + return nullptr; + } + + return codec; + } + + void file_editor_tab::handle_save_file_as_answer (const QString& save_file_name) + { + QString saveFileName = save_file_name; + QFileInfo file (saveFileName); + QFileDialog *file_dialog = qobject_cast (sender ()); + + // Test if the file dialog should have added a default file + // suffix, but the selected file still has no suffix (see Qt bug + // https://bugreports.qt.io/browse/QTBUG-59401) + if ((! file_dialog->defaultSuffix ().isEmpty ()) && file.suffix ().isEmpty ()) + { + saveFileName = saveFileName + "." + file_dialog->defaultSuffix (); + } + + file.setFile (saveFileName); + + // If overwrite confirmation was not done by the file dialog (in case + // of native file dialogs, see above), do it here + if (file_dialog->testOption (QFileDialog::DontConfirmOverwrite) && file.exists ()) + { + int ans = QMessageBox::question (file_dialog, + tr ("Octave Editor"), + tr ("%1\n already exists\n" + "Do you want to overwrite it?").arg (saveFileName), + QMessageBox::Yes | QMessageBox::No); + if (ans != QMessageBox::Yes) + { + // Try again, if edit area is read only, remove on success + save_file_as (m_edit_area->isReadOnly ()); + return; + } + } + + if (saveFileName == m_file_name) + { + save_file (saveFileName); + } + else + { + // Have editor check for conflict, do not delete tab after save. + if (check_valid_identifier (saveFileName)) + save_file_as (false); + else + emit editor_check_conflict_save (saveFileName, false); + } + } + + void file_editor_tab::handle_save_file_as_answer_close (const QString& saveFileName) + { + // saveFileName == m_file_name can not happen, because we only can get here + // when we close a tab and m_file_name is not a valid filename yet + + // Have editor check for conflict, delete tab after save. + if (check_valid_identifier (saveFileName)) + save_file_as (true); + else + emit editor_check_conflict_save (saveFileName, true); + } + + void file_editor_tab::handle_save_file_as_answer_cancel (void) + { + // User canceled, allow editing again. + m_edit_area->setReadOnly (false); + } + + void file_editor_tab::file_has_changed (const QString&, bool do_close) + { + bool file_exists = QFile::exists (m_file_name); + + if (file_exists && ! do_close) + { + // Test if file is really modified or if just the timezone has + // changed. In the latter, just return without doing anything. + QDateTime modified = QFileInfo (m_file_name).lastModified ().toUTC (); + + if (modified <= m_last_modified) + return; + + m_last_modified = modified; + } + + // Prevent popping up multiple message boxes when the file has + // been changed multiple times by temporarily removing from the + // file watcher. + QStringList trackedFiles = m_file_system_watcher.files (); + if (! trackedFiles.isEmpty ()) + m_file_system_watcher.removePath (m_file_name); + + if (file_exists && ! do_close) + { + + // The file is modified + if (m_always_reload_changed_files) + load_file (m_file_name); + + else + { + // give editor and this tab the focus, + // possibly making the editor visible if it is hidden + emit set_focus_editor_signal (this); + m_edit_area->setFocus (); + + // Create a WindowModal message that blocks the edit area + // by making m_edit_area parent. + QMessageBox *msgBox + = new QMessageBox (QMessageBox::Warning, tr ("Octave Editor"), - tr ("The current editor contents can not be encoded\n" - "with the selected encoding %1.\n" - "Using it would result in data loss!\n\n" - "Please select another one!").arg (m_encoding), - QMessageBox::Cancel | QMessageBox::Ignore, - QMessageBox::Cancel); - - if (pressed_button == QMessageBox::Ignore) - return codec; - else - return nullptr; - } - - return codec; -} - -void file_editor_tab::handle_save_file_as_answer (const QString& save_file_name) -{ - QString saveFileName = save_file_name; - QFileInfo file (saveFileName); - QFileDialog *file_dialog = qobject_cast (sender ()); - - // Test if the file dialog should have added a default file - // suffix, but the selected file still has no suffix (see Qt bug - // https://bugreports.qt.io/browse/QTBUG-59401) - if ((! file_dialog->defaultSuffix ().isEmpty ()) && file.suffix ().isEmpty ()) - { - saveFileName = saveFileName + "." + file_dialog->defaultSuffix (); - } - - file.setFile (saveFileName); - - // If overwrite confirmation was not done by the file dialog (in case - // of native file dialogs, see above), do it here - if (file_dialog->testOption (QFileDialog::DontConfirmOverwrite) && file.exists ()) - { - int ans = QMessageBox::question (file_dialog, - tr ("Octave Editor"), - tr ("%1\n already exists\n" - "Do you want to overwrite it?").arg (saveFileName), - QMessageBox::Yes | QMessageBox::No); - if (ans != QMessageBox::Yes) - { - // Try again, if edit area is read only, remove on success - save_file_as (m_edit_area->isReadOnly ()); - return; - } - } - - if (saveFileName == m_file_name) - { - save_file (saveFileName); - } - else - { - // Have editor check for conflict, do not delete tab after save. - if (check_valid_identifier (saveFileName)) - save_file_as (false); + tr ("It seems that \'%1\' has been modified by another application. Do you want to reload it?"). + arg (m_file_name), + QMessageBox::Yes | QMessageBox::No, this); + + connect (msgBox, &QMessageBox::finished, + this, &file_editor_tab::handle_file_reload_answer); + + msgBox->setWindowModality (Qt::WindowModal); + msgBox->setAttribute (Qt::WA_DeleteOnClose); + msgBox->show (); + } + } + else + { + // If desired and if file is not modified, + // close the file without any user interaction + if (do_close && ! m_edit_area->isModified ()) + { + handle_file_resave_answer (QMessageBox::Cancel); + return; + } + + // give editor and this tab the focus, + // possibly making the editor visible if it is hidden + emit set_focus_editor_signal (this); + m_edit_area->setFocus (); + + QString modified = ""; + if (m_edit_area->isModified ()) + modified = tr ("\n\nWarning: The contents in the editor is modified!"); + + // Create a WindowModal message. The file editor tab can't be made + // parent because it may be deleted depending upon the response. + // Instead, change the m_edit_area to read only. + QMessageBox *msgBox + = new QMessageBox (QMessageBox::Warning, tr ("Octave Editor"), + tr ("It seems that the file\n" + "%1\n" + "has been deleted or renamed. Do you want to save it now?%2"). + arg (m_file_name).arg (modified), + QMessageBox::Save | QMessageBox::Close, nullptr); + + m_edit_area->setReadOnly (true); + + connect (msgBox, &QMessageBox::finished, + this, &file_editor_tab::handle_file_resave_answer); + + msgBox->setWindowModality (Qt::WindowModal); + msgBox->setAttribute (Qt::WA_DeleteOnClose); + msgBox->show (); + } + } + + void file_editor_tab::notice_settings (bool init) + { + gui_settings settings; + + if (! init) + update_lexer_settings (); + + // code folding + if (settings.value (ed_code_folding).toBool ()) + { + m_edit_area->setMarginType (3, QsciScintilla::SymbolMargin); + m_edit_area->setFolding (QsciScintilla::BoxedTreeFoldStyle, 3); + } + else + { + m_edit_area->setFolding (QsciScintilla::NoFoldStyle, 3); + } + + // status bar + if (settings.value (ed_show_edit_status_bar).toBool ()) + m_status_bar->show (); + else + m_status_bar->hide (); + + //highlight current line color + m_edit_area->setCaretLineVisible + (settings.value (ed_highlight_current_line).toBool ()); + + // auto completion + bool match_keywords = settings.value + (ed_code_completion_keywords).toBool (); + bool match_document = settings.value + (ed_code_completion_document).toBool (); + + QsciScintilla::AutoCompletionSource source = QsciScintilla::AcsNone; + if (match_keywords) + if (match_document) + source = QsciScintilla::AcsAll; else - emit editor_check_conflict_save (saveFileName, false); - } -} - -void file_editor_tab::handle_save_file_as_answer_close (const QString& saveFileName) -{ - // saveFileName == m_file_name can not happen, because we only can get here - // when we close a tab and m_file_name is not a valid filename yet - - // Have editor check for conflict, delete tab after save. - if (check_valid_identifier (saveFileName)) - save_file_as (true); - else - emit editor_check_conflict_save (saveFileName, true); -} - -void file_editor_tab::handle_save_file_as_answer_cancel (void) -{ - // User canceled, allow editing again. - m_edit_area->setReadOnly (false); -} - -void file_editor_tab::file_has_changed (const QString&, bool do_close) -{ - bool file_exists = QFile::exists (m_file_name); - - if (file_exists && ! do_close) - { - // Test if file is really modified or if just the timezone has - // changed. In the latter, just return without doing anything. - QDateTime modified = QFileInfo (m_file_name).lastModified ().toUTC (); - - if (modified <= m_last_modified) - return; - - m_last_modified = modified; - } - - // Prevent popping up multiple message boxes when the file has - // been changed multiple times by temporarily removing from the - // file watcher. - QStringList trackedFiles = m_file_system_watcher.files (); - if (! trackedFiles.isEmpty ()) - m_file_system_watcher.removePath (m_file_name); - - if (file_exists && ! do_close) - { - - // The file is modified - if (m_always_reload_changed_files) - load_file (m_file_name); - - else - { - // give editor and this tab the focus, - // possibly making the editor visible if it is hidden - emit set_focus_editor_signal (this); - m_edit_area->setFocus (); - - // Create a WindowModal message that blocks the edit area - // by making m_edit_area parent. - QMessageBox *msgBox - = new QMessageBox (QMessageBox::Warning, - tr ("Octave Editor"), - tr ("It seems that \'%1\' has been modified by another application. Do you want to reload it?"). - arg (m_file_name), - QMessageBox::Yes | QMessageBox::No, this); - - connect (msgBox, &QMessageBox::finished, - this, &file_editor_tab::handle_file_reload_answer); - - msgBox->setWindowModality (Qt::WindowModal); - msgBox->setAttribute (Qt::WA_DeleteOnClose); - msgBox->show (); - } - } - else - { - // If desired and if file is not modified, - // close the file without any user interaction - if (do_close && ! m_edit_area->isModified ()) - { - handle_file_resave_answer (QMessageBox::Cancel); - return; - } - - // give editor and this tab the focus, - // possibly making the editor visible if it is hidden - emit set_focus_editor_signal (this); - m_edit_area->setFocus (); - - QString modified = ""; - if (m_edit_area->isModified ()) - modified = tr ("\n\nWarning: The contents in the editor is modified!"); - - // Create a WindowModal message. The file editor tab can't be made - // parent because it may be deleted depending upon the response. - // Instead, change the m_edit_area to read only. - QMessageBox *msgBox - = new QMessageBox (QMessageBox::Warning, tr ("Octave Editor"), - tr ("It seems that the file\n" - "%1\n" - "has been deleted or renamed. Do you want to save it now?%2"). - arg (m_file_name).arg (modified), - QMessageBox::Save | QMessageBox::Close, nullptr); - - m_edit_area->setReadOnly (true); - - connect (msgBox, &QMessageBox::finished, - this, &file_editor_tab::handle_file_resave_answer); - - msgBox->setWindowModality (Qt::WindowModal); - msgBox->setAttribute (Qt::WA_DeleteOnClose); - msgBox->show (); - } -} - -void file_editor_tab::notice_settings (const gui_settings *settings, bool init) -{ - if (! settings) - return; - - if (! init) - update_lexer_settings (); - - // code folding - if (settings->value (ed_code_folding).toBool ()) - { - m_edit_area->setMarginType (3, QsciScintilla::SymbolMargin); - m_edit_area->setFolding (QsciScintilla::BoxedTreeFoldStyle, 3); - } - else - { - m_edit_area->setFolding (QsciScintilla::NoFoldStyle, 3); - } - - // status bar - if (settings->value (ed_show_edit_status_bar).toBool ()) - m_status_bar->show (); - else - m_status_bar->hide (); - - //highlight current line color - m_edit_area->setCaretLineVisible - (settings->value (ed_highlight_current_line).toBool ()); - - // auto completion - bool match_keywords = settings->value - (ed_code_completion_keywords).toBool (); - bool match_document = settings->value - (ed_code_completion_document).toBool (); - - QsciScintilla::AutoCompletionSource source = QsciScintilla::AcsNone; - if (match_keywords) - if (match_document) - source = QsciScintilla::AcsAll; + source = QsciScintilla::AcsAPIs; + else if (match_document) + source = QsciScintilla::AcsDocument; + m_edit_area->setAutoCompletionSource (source); + + m_edit_area->setAutoCompletionReplaceWord + (settings.value (ed_code_completion_replace).toBool ()); + m_edit_area->setAutoCompletionCaseSensitivity + (settings.value (ed_code_completion_case).toBool ()); + + if (settings.value (ed_code_completion).toBool ()) + m_edit_area->setAutoCompletionThreshold + (settings.value (ed_code_completion_threshold).toInt ()); else - source = QsciScintilla::AcsAPIs; - else if (match_document) - source = QsciScintilla::AcsDocument; - m_edit_area->setAutoCompletionSource (source); - - m_edit_area->setAutoCompletionReplaceWord - (settings->value (ed_code_completion_replace).toBool ()); - m_edit_area->setAutoCompletionCaseSensitivity - (settings->value (ed_code_completion_case).toBool ()); - - if (settings->value (ed_code_completion).toBool ()) - m_edit_area->setAutoCompletionThreshold - (settings->value (ed_code_completion_threshold).toInt ()); - else - m_edit_area->setAutoCompletionThreshold (-1); - - if (settings->value (ed_show_white_space).toBool ()) - if (settings->value (ed_show_white_space_indent).toBool ()) - m_edit_area->setWhitespaceVisibility (QsciScintilla::WsVisibleAfterIndent); - else - m_edit_area->setWhitespaceVisibility (QsciScintilla::WsVisible); - else - m_edit_area->setWhitespaceVisibility (QsciScintilla::WsInvisible); - - m_edit_area->setEolVisibility (settings->value (ed_show_eol_chars).toBool ()); - - m_save_as_desired_eol = static_cast - (settings->value (ed_default_eol_mode).toInt ()); - - if (settings->value (ed_show_line_numbers).toBool ()) - { - m_edit_area->setMarginLineNumbers (2, true); - auto_margin_width (); - connect (m_edit_area, SIGNAL (linesChanged ()), - this, SLOT (auto_margin_width ())); - } - else - { - m_edit_area->setMarginLineNumbers (2, false); - disconnect (m_edit_area, SIGNAL (linesChanged ()), nullptr, nullptr); - } - - m_smart_indent = settings->value (ed_auto_indent).toBool (); - m_edit_area->setAutoIndent (m_smart_indent); - m_edit_area->setTabIndents - (settings->value (ed_tab_indents_line).toBool ()); - m_edit_area->setBackspaceUnindents - (settings->value (ed_backspace_unindents_line).toBool ()); - m_edit_area->setIndentationGuides - (settings->value (ed_show_indent_guides).toBool ()); - m_edit_area->setIndentationsUseTabs - (settings->value (ed_indent_uses_tabs).toBool ()); - m_edit_area->setIndentationWidth - (settings->value (ed_indent_width).toInt ()); - - m_edit_area->setTabWidth - (settings->value (ed_tab_width).toInt ()); - - m_ind_char_width = 1; - if (m_edit_area->indentationsUseTabs ()) - m_ind_char_width = m_edit_area->tabWidth (); - - m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETHSCROLLBAR, - settings->value (ed_show_hscroll_bar).toBool ()); - m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETSCROLLWIDTH,-1); - m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETSCROLLWIDTHTRACKING,true); - - update_window_title (m_edit_area->isModified ()); - - m_auto_endif = settings->value (ed_auto_endif).toInt (); - - // long line marker - int line_length = settings->value (ed_long_line_column).toInt (); - m_edit_area->setEdgeColumn (line_length); - - if (settings->value (ed_long_line_marker).toBool ()) - { - if (settings->value (ed_long_line_marker_line).toBool ()) - m_edit_area->setEdgeMode (QsciScintilla::EdgeLine); + m_edit_area->setAutoCompletionThreshold (-1); + + if (settings.value (ed_show_white_space).toBool ()) + if (settings.value (ed_show_white_space_indent).toBool ()) + m_edit_area->setWhitespaceVisibility (QsciScintilla::WsVisibleAfterIndent); else - { - if (settings->value (ed_long_line_marker_background) - .toBool ()) - m_edit_area->setEdgeMode (QsciScintilla::EdgeBackground); - else - m_edit_area->setEdgeMode (QsciScintilla::EdgeLine); - } - } - else - m_edit_area->setEdgeMode (QsciScintilla::EdgeNone); - - // line wrapping and breaking - m_edit_area->setWrapVisualFlags (QsciScintilla::WrapFlagByBorder); - m_edit_area->setWrapIndentMode (QsciScintilla::WrapIndentSame); - - if (settings->value (ed_wrap_lines).toBool ()) - m_edit_area->setWrapMode (QsciScintilla::WrapWord); - else - m_edit_area->setWrapMode (QsciScintilla::WrapNone); - - if (settings->value (ed_break_lines).toBool ()) - m_line_break = line_length; - else - m_line_break = 0; - - m_line_break_comments = - settings->value (ed_break_lines_comments).toBool (); - - // highlight all occurrences of a word selected by a double click - m_highlight_all_occurrences = - settings->value (ed_highlight_all_occurrences).toBool (); - - // reload changed files - m_always_reload_changed_files = - settings->value (ed_always_reload_changed_files).toBool (); - - // Set cursor blinking depending on the settings. - // QScintilla ignores the application global settings, so some special - // handling is required - bool cursor_blinking; - - if (settings->contains (global_cursor_blinking.key)) - cursor_blinking = settings->value (global_cursor_blinking).toBool (); - else - cursor_blinking = settings->value (cs_cursor_blinking).toBool (); - - if (cursor_blinking) - m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETCARETPERIOD, 500); - else - m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETCARETPERIOD, 0); - -} - -void file_editor_tab::auto_margin_width (void) -{ - m_edit_area->setMarginWidth (2, "1" + QString::number (m_edit_area->lines ())); -} - -// the following close request was changed from a signal slot into a -// normal function because we need the return value from close whether -// the tab really was closed (for canceling exiting octave). -// When emitting a signal, only the return value from the last slot -// goes back to the sender -bool file_editor_tab::conditional_close (void) -{ - return close (); -} - -void file_editor_tab::change_editor_state (const QWidget *ID) -{ - if (ID != this) - return; - - emit editor_state_changed (m_copy_available, m_is_octave_file, - m_edit_area->isModified ()); -} - -void file_editor_tab::handle_file_reload_answer (int decision) -{ - if (decision == QMessageBox::Yes) - { - // reload: file is readded to the file watcher in set_file_name () - load_file (m_file_name); - } - else - { - // do not reload: readd to the file watcher - m_file_system_watcher.addPath (m_file_name); - } -} - -void file_editor_tab::handle_file_resave_answer (int decision) -{ - // check decision of user in dialog - if (decision == QMessageBox::Save) - { - save_file (m_file_name); // readds file to watcher in set_file_name () - m_edit_area->setReadOnly (false); // delete read only flag - } - else - { - // Definitely close the file. - // Set modified to false to prevent the dialog box when the close event - // is posted. If the user cancels the close in this dialog the tab is - // left open with a non-existing file. - m_edit_area->setModified (false); - close (); - } -} - -void file_editor_tab::insert_debugger_pointer (const QWidget *ID, int line) -{ - if (ID != this || ID == nullptr) - return; - - emit remove_all_positions (); // debugger_position, unsure_debugger_position - - if (line > 0) - { - marker *dp; - - if (m_edit_area->isModified ()) - { - // The best that can be done if the editor contents have been - // modified is to see if there is a match with the original - // line number of any existing breakpoints. We can put a normal - // debugger pointer at that breakpoint position. Otherwise, it - // isn't certain whether the original line number and current line - // number match. - int editor_linenr = -1; - marker *dummy; - emit find_translated_line_number (line, editor_linenr, dummy); - if (editor_linenr != -1) - { - // Match with an existing breakpoint. - dp = new marker (m_edit_area, line, - marker::debugger_position, editor_linenr); - } - else - { - int original_linenr = -1; - editor_linenr = -1; - emit find_linenr_just_before (line, original_linenr, editor_linenr); - if (original_linenr >= 0) - { - // Make a guess by using an offset from the breakpoint. - int linenr_guess = editor_linenr + line - original_linenr; - dp = new marker (m_edit_area, line, - marker::unsure_debugger_position, - linenr_guess); - } - else - { - // Can't make a very good guess, so just use the debugger - // line number. - dp = new marker (m_edit_area, line, - marker::unsure_debugger_position); - } - } - } - else - { - dp = new marker (m_edit_area, line, marker::debugger_position); - - // In case of a not modified file we might have to remove - // a breakpoint here if we have stepped into the file - if (line == m_breakpoint_info.remove_line) - { - m_breakpoint_info.remove_line = -1; - if (line != m_breakpoint_info.do_not_remove_line) - handle_request_remove_breakpoint (line); - } - } - - connect (this, &file_editor_tab::remove_position_via_debugger_linenr, - dp, &marker::handle_remove_via_original_linenr); - - connect (this, &file_editor_tab::remove_all_positions, - dp, &marker::handle_remove); - - center_current_line (false); - } -} - -void file_editor_tab::delete_debugger_pointer (const QWidget *ID, int line) -{ - if (ID != this || ID == nullptr) - return; - - if (line > 0) - emit remove_position_via_debugger_linenr (line); -} - -void file_editor_tab::do_breakpoint_marker (bool insert, - const QWidget *ID, int line, - const QString& cond) -{ - if (ID != this || ID == nullptr) - return; - - if (line > 0) - { - if (insert) - { - int editor_linenr = -1; - marker *bp = nullptr; - - // If comes back indicating a non-zero breakpoint marker, - // reuse it if possible - emit find_translated_line_number (line, editor_linenr, bp); - if (bp != nullptr) - { - if ((cond == "") != (bp->get_cond () == "")) - { - // can only reuse conditional bp as conditional - emit remove_breakpoint_via_debugger_linenr (line); - bp = nullptr; - } - else - bp->set_cond (cond); - } - - if (bp == nullptr) - { - bp = new marker (m_edit_area, line, - cond == "" ? marker::breakpoint - : marker::cond_break, cond); - - connect (this, &file_editor_tab::remove_breakpoint_via_debugger_linenr, - bp, &marker::handle_remove_via_original_linenr); - connect (this, &file_editor_tab::request_remove_breakpoint_via_editor_linenr, - bp, &marker::handle_request_remove_via_editor_linenr); - connect (this, &file_editor_tab::remove_all_breakpoints_signal, - bp, &marker::handle_remove); - connect (this, &file_editor_tab::find_translated_line_number, - bp, &marker::handle_find_translation); - connect (this, &file_editor_tab::find_linenr_just_before, - bp, &marker::handle_find_just_before); - connect (this, &file_editor_tab::report_marker_linenr, - bp, &marker::handle_report_editor_linenr); - connect (bp, &marker::request_remove, - this, &file_editor_tab::handle_request_remove_breakpoint); - } - } - else - emit remove_breakpoint_via_debugger_linenr (line); - } -} - -void file_editor_tab::center_current_line (bool always) -{ - long int visible_lines - = m_edit_area->SendScintilla (QsciScintillaBase::SCI_LINESONSCREEN); - - if (visible_lines > 2) - { - int line, index; - m_edit_area->getCursorPosition (&line, &index); - // compensate for "folding": - // step 1: expand the current line, if it was folded - m_edit_area->SendScintilla (2232, line); // SCI_ENSUREVISIBLE - - // step 2: map file line num to "visible" one // SCI_VISIBLEFROMDOCLINE - int vis_line = m_edit_area->SendScintilla (2220, line); - - int first_line = m_edit_area->firstVisibleLine (); - - if (always || vis_line == first_line - || vis_line > first_line + visible_lines - 2) - { - first_line += (vis_line - first_line - (visible_lines - 1) / 2); - m_edit_area->SendScintilla (2613, first_line); // SCI_SETFIRSTVISIBLELINE - } - } -} - -void file_editor_tab::handle_lines_changed (void) -{ - // the related signal is emitted before cursor-move-signal! - m_lines_changed = true; -} - -void file_editor_tab::handle_cursor_moved (int line, int col) -{ - // Cursor has moved, first check wether an autocompletion list - // is active or if it was closed. Scintilla provides signals for - // completed or cancelled lists, but not for list that where hidden - // due to a new character not matching anymore with the list entries - if (m_edit_area->SendScintilla (QsciScintillaBase::SCI_AUTOCACTIVE)) - m_autoc_active = true; - else if (m_autoc_active) - { - m_autoc_active = false; - emit autoc_closed (); // Tell editor about closed list - } - - // Lines changed? Take care of indentation! - bool do_smart_indent = m_lines_changed && m_is_octave_file - && (line == m_line+1) && (col < m_col) - && (m_smart_indent || m_auto_endif); - m_lines_changed = false; - - // Update line and column indicator in the status bar - int o_line = m_line; - update_rowcol_indicator (line, col); - - // Do smart indent after update of line indicator for having - // consistent indicator data - if (do_smart_indent) - m_edit_area->smart_indent (m_smart_indent, m_auto_endif, - o_line, m_ind_char_width); -} - -void file_editor_tab::update_rowcol_indicator (int line, int col) -{ - m_line = line; - m_col = col; - m_row_indicator->setNum (line+1); - m_col_indicator->setNum (col+1); -} - -// Slot that is entered each time a new character was typed. -// It is used for handling line breaking if this is desired. -// The related signal is emitted after the signal for a moved cursor -// such that m_col and m_line can not be used for current position. -void file_editor_tab::handle_char_added (int) -{ - if (m_line_break) - { - // If line breaking is desired, get the current line and column. - // For taking the tab width into consideration, use own function - int line, col, pos; - m_edit_area->get_current_position (&pos, &line, &col); - - // immediately return if line has not reached the max. line length - if (col <= m_line_break) - return; - - // If line breaking is only desired in comments, - // return if not in a comment - int style_comment = octave_qscintilla::ST_NONE; - if (m_line_break_comments) - { - // line breaking only in comments, check for comment style - style_comment = m_edit_area->is_style_comment (); - if (! style_comment) - return; // no comment, return - } - - // Here we go for breaking the current line by inserting a newline. - // For determining the position of a specific column, we have to get - // the column from the QScintilla function without taking tab lengths - // into account, since the calculation from line/col to position - // ignores this, too. - m_edit_area->getCursorPosition (&line, &col); - int c = 0; - int col_space = col; - int indentation = m_edit_area->indentation (line); - - // Search the first occurrence of space or tab backwards starting from - // the current column (col_space). - while (c != ' ' && c != '\t' && col_space > indentation) - { - pos = m_edit_area->positionFromLineIndex (line, col_space--); - c = m_edit_area->SendScintilla (QsciScintillaBase::SCI_GETCHARAT, pos); - } - - // If a space or tab was found, break at this char, - // otherwise break at cursor position - int col_newline = col - 1; - if (c == ' ' || c == '\t') - col_newline = col_space + 1; - - // Insert a newline char for breaking the line possibly followed - // by a line comment string - QString newline = QString ("\n"); - style_comment = m_edit_area->is_style_comment (); - if (style_comment == octave_qscintilla::ST_LINE_COMMENT) - newline = newline + m_edit_area->comment_string ().at (0); - m_edit_area->insertAt (newline, line, col_newline); - - // Automatically indent the new line to the indentation of previous line - // and set the cursor position to the end of the indentation. - m_edit_area->setIndentation (line + 1, indentation); - m_edit_area->SendScintilla (QsciScintillaBase::SCI_LINEEND); - } -} - -// Slot handling a double click into the text area -void file_editor_tab::handle_double_click (int, int, int modifier) -{ - if (! modifier) - { - // double clicks without modifier - // clear any existing indicators of this type - m_edit_area->clear_selection_markers (); - - if (m_highlight_all_occurrences) - { - // Clear any previous selection. - m_edit_area->set_word_selection (); - - // highlighting of all occurrences of the clicked word is enabled - - // get the resulting cursor position - // (required if click was beyond a line ending) - int line, col; - m_edit_area->getCursorPosition (&line, &col); - - // get the word at the cursor (if any) - QString word = m_edit_area->wordAtLineIndex (line, col); - word = word.trimmed (); - - if (! word.isEmpty ()) - { - // word is not empty, so find all occurrences of the word - - // remember first visible line and x-offset for restoring the view afterwards - int first_line = m_edit_area->firstVisibleLine (); - int x_offset = m_edit_area->SendScintilla (QsciScintillaBase::SCI_GETXOFFSET); - - // search for first occurrence of the detected word - bool find_result_available - = m_edit_area->findFirst (word, - false, // no regexp - true, // case sensitive - true, // whole words only - false, // do not wrap - true, // forward - 0, 0, // from the beginning - false + m_edit_area->setWhitespaceVisibility (QsciScintilla::WsVisible); + else + m_edit_area->setWhitespaceVisibility (QsciScintilla::WsInvisible); + + m_edit_area->setEolVisibility (settings.value (ed_show_eol_chars).toBool ()); + + m_save_as_desired_eol = static_cast + (settings.value (ed_default_eol_mode).toInt ()); + + if (settings.value (ed_show_line_numbers).toBool ()) + { + m_edit_area->setMarginLineNumbers (2, true); + auto_margin_width (); + connect (m_edit_area, SIGNAL (linesChanged ()), + this, SLOT (auto_margin_width ())); + } + else + { + m_edit_area->setMarginLineNumbers (2, false); + disconnect (m_edit_area, SIGNAL (linesChanged ()), nullptr, nullptr); + } + + m_smart_indent = settings.value (ed_auto_indent).toBool (); + m_edit_area->setAutoIndent (m_smart_indent); + m_edit_area->setTabIndents + (settings.value (ed_tab_indents_line).toBool ()); + m_edit_area->setBackspaceUnindents + (settings.value (ed_backspace_unindents_line).toBool ()); + m_edit_area->setIndentationGuides + (settings.value (ed_show_indent_guides).toBool ()); + m_edit_area->setIndentationsUseTabs + (settings.value (ed_indent_uses_tabs).toBool ()); + m_edit_area->setIndentationWidth + (settings.value (ed_indent_width).toInt ()); + + m_edit_area->setTabWidth + (settings.value (ed_tab_width).toInt ()); + + m_ind_char_width = 1; + if (m_edit_area->indentationsUseTabs ()) + m_ind_char_width = m_edit_area->tabWidth (); + + m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETHSCROLLBAR, + settings.value (ed_show_hscroll_bar).toBool ()); + m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETSCROLLWIDTH,-1); + m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETSCROLLWIDTHTRACKING,true); + + update_window_title (m_edit_area->isModified ()); + + m_auto_endif = settings.value (ed_auto_endif).toInt (); + + // long line marker + int line_length = settings.value (ed_long_line_column).toInt (); + m_edit_area->setEdgeColumn (line_length); + + if (settings.value (ed_long_line_marker).toBool ()) + { + if (settings.value (ed_long_line_marker_line).toBool ()) + m_edit_area->setEdgeMode (QsciScintilla::EdgeLine); + else + { + if (settings.value (ed_long_line_marker_background) + .toBool ()) + m_edit_area->setEdgeMode (QsciScintilla::EdgeBackground); + else + m_edit_area->setEdgeMode (QsciScintilla::EdgeLine); + } + } + else + m_edit_area->setEdgeMode (QsciScintilla::EdgeNone); + + // line wrapping and breaking + m_edit_area->setWrapVisualFlags (QsciScintilla::WrapFlagByBorder); + m_edit_area->setWrapIndentMode (QsciScintilla::WrapIndentSame); + + if (settings.value (ed_wrap_lines).toBool ()) + m_edit_area->setWrapMode (QsciScintilla::WrapWord); + else + m_edit_area->setWrapMode (QsciScintilla::WrapNone); + + if (settings.value (ed_break_lines).toBool ()) + m_line_break = line_length; + else + m_line_break = 0; + + m_line_break_comments = + settings.value (ed_break_lines_comments).toBool (); + + // highlight all occurrences of a word selected by a double click + m_highlight_all_occurrences = + settings.value (ed_highlight_all_occurrences).toBool (); + + // reload changed files + m_always_reload_changed_files = + settings.value (ed_always_reload_changed_files).toBool (); + + // Set cursor blinking depending on the settings. + // QScintilla ignores the application global settings, so some special + // handling is required + bool cursor_blinking; + + if (settings.contains (global_cursor_blinking.key)) + cursor_blinking = settings.value (global_cursor_blinking).toBool (); + else + cursor_blinking = settings.value (cs_cursor_blinking).toBool (); + + if (cursor_blinking) + m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETCARETPERIOD, 500); + else + m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETCARETPERIOD, 0); + + } + + void file_editor_tab::auto_margin_width (void) + { + m_edit_area->setMarginWidth (2, "1" + QString::number (m_edit_area->lines ())); + } + + // the following close request was changed from a signal slot into a + // normal function because we need the return value from close whether + // the tab really was closed (for canceling exiting octave). + // When emitting a signal, only the return value from the last slot + // goes back to the sender + bool file_editor_tab::conditional_close (void) + { + return close (); + } + + void file_editor_tab::change_editor_state (const QWidget *ID) + { + if (ID != this) + return; + + emit editor_state_changed (m_copy_available, m_is_octave_file, + m_edit_area->isModified ()); + } + + void file_editor_tab::handle_file_reload_answer (int decision) + { + if (decision == QMessageBox::Yes) + { + // reload: file is readded to the file watcher in set_file_name () + load_file (m_file_name); + } + else + { + // do not reload: readd to the file watcher + m_file_system_watcher.addPath (m_file_name); + } + } + + void file_editor_tab::handle_file_resave_answer (int decision) + { + // check decision of user in dialog + if (decision == QMessageBox::Save) + { + save_file (m_file_name); // readds file to watcher in set_file_name () + m_edit_area->setReadOnly (false); // delete read only flag + } + else + { + // Definitely close the file. + // Set modified to false to prevent the dialog box when the close event + // is posted. If the user cancels the close in this dialog the tab is + // left open with a non-existing file. + m_edit_area->setModified (false); + close (); + } + } + + void file_editor_tab::insert_debugger_pointer (const QWidget *ID, int line) + { + if (ID != this || ID == nullptr) + return; + + emit remove_all_positions (); // debugger_position, unsure_debugger_position + + if (line > 0) + { + marker *dp; + + if (m_edit_area->isModified ()) + { + // The best that can be done if the editor contents have been + // modified is to see if there is a match with the original + // line number of any existing breakpoints. We can put a normal + // debugger pointer at that breakpoint position. Otherwise, it + // isn't certain whether the original line number and current line + // number match. + int editor_linenr = -1; + marker *dummy; + emit find_translated_line_number (line, editor_linenr, dummy); + if (editor_linenr != -1) + { + // Match with an existing breakpoint. + dp = new marker (m_edit_area, line, + marker::debugger_position, editor_linenr); + } + else + { + int original_linenr = -1; + editor_linenr = -1; + emit find_linenr_just_before (line, original_linenr, editor_linenr); + if (original_linenr >= 0) + { + // Make a guess by using an offset from the breakpoint. + int linenr_guess = editor_linenr + line - original_linenr; + dp = new marker (m_edit_area, line, + marker::unsure_debugger_position, + linenr_guess); + } + else + { + // Can't make a very good guess, so just use the debugger + // line number. + dp = new marker (m_edit_area, line, + marker::unsure_debugger_position); + } + } + } + else + { + dp = new marker (m_edit_area, line, marker::debugger_position); + + // In case of a not modified file we might have to remove + // a breakpoint here if we have stepped into the file + if (line == m_breakpoint_info.remove_line) + { + m_breakpoint_info.remove_line = -1; + if (line != m_breakpoint_info.do_not_remove_line) + handle_request_remove_breakpoint (line); + } + } + + connect (this, &file_editor_tab::remove_position_via_debugger_linenr, + dp, &marker::handle_remove_via_original_linenr); + + connect (this, &file_editor_tab::remove_all_positions, + dp, &marker::handle_remove); + + center_current_line (false); + } + } + + void file_editor_tab::delete_debugger_pointer (const QWidget *ID, int line) + { + if (ID != this || ID == nullptr) + return; + + if (line > 0) + emit remove_position_via_debugger_linenr (line); + } + + void file_editor_tab::do_breakpoint_marker (bool insert, + const QWidget *ID, int line, + const QString& cond) + { + if (ID != this || ID == nullptr) + return; + + if (line > 0) + { + if (insert) + { + int editor_linenr = -1; + marker *bp = nullptr; + + // If comes back indicating a non-zero breakpoint marker, + // reuse it if possible + emit find_translated_line_number (line, editor_linenr, bp); + if (bp != nullptr) + { + if ((cond == "") != (bp->get_cond () == "")) + { + // can only reuse conditional bp as conditional + emit remove_breakpoint_via_debugger_linenr (line); + bp = nullptr; + } + else + bp->set_cond (cond); + } + + if (bp == nullptr) + { + bp = new marker (m_edit_area, line, + cond == "" ? marker::breakpoint + : marker::cond_break, cond); + + connect (this, &file_editor_tab::remove_breakpoint_via_debugger_linenr, + bp, &marker::handle_remove_via_original_linenr); + connect (this, &file_editor_tab::request_remove_breakpoint_via_editor_linenr, + bp, &marker::handle_request_remove_via_editor_linenr); + connect (this, &file_editor_tab::remove_all_breakpoints_signal, + bp, &marker::handle_remove); + connect (this, &file_editor_tab::find_translated_line_number, + bp, &marker::handle_find_translation); + connect (this, &file_editor_tab::find_linenr_just_before, + bp, &marker::handle_find_just_before); + connect (this, &file_editor_tab::report_marker_linenr, + bp, &marker::handle_report_editor_linenr); + connect (bp, &marker::request_remove, + this, &file_editor_tab::handle_request_remove_breakpoint); + } + } + else + emit remove_breakpoint_via_debugger_linenr (line); + } + } + + void file_editor_tab::center_current_line (bool always) + { + long int visible_lines + = m_edit_area->SendScintilla (QsciScintillaBase::SCI_LINESONSCREEN); + + if (visible_lines > 2) + { + int line, index; + m_edit_area->getCursorPosition (&line, &index); + // compensate for "folding": + // step 1: expand the current line, if it was folded + m_edit_area->SendScintilla (2232, line); // SCI_ENSUREVISIBLE + + // step 2: map file line num to "visible" one // SCI_VISIBLEFROMDOCLINE + int vis_line = m_edit_area->SendScintilla (2220, line); + + int first_line = m_edit_area->firstVisibleLine (); + + if (always || vis_line == first_line + || vis_line > first_line + visible_lines - 2) + { + first_line += (vis_line - first_line - (visible_lines - 1) / 2); + m_edit_area->SendScintilla (2613, first_line); // SCI_SETFIRSTVISIBLELINE + } + } + } + + void file_editor_tab::handle_lines_changed (void) + { + // the related signal is emitted before cursor-move-signal! + m_lines_changed = true; + } + + void file_editor_tab::handle_cursor_moved (int line, int col) + { + // Cursor has moved, first check wether an autocompletion list + // is active or if it was closed. Scintilla provides signals for + // completed or cancelled lists, but not for list that where hidden + // due to a new character not matching anymore with the list entries + if (m_edit_area->SendScintilla (QsciScintillaBase::SCI_AUTOCACTIVE)) + m_autoc_active = true; + else if (m_autoc_active) + { + m_autoc_active = false; + emit autoc_closed (); // Tell editor about closed list + } + + // Lines changed? Take care of indentation! + bool do_smart_indent = m_lines_changed && m_is_octave_file + && (line == m_line+1) && (col < m_col) + && (m_smart_indent || m_auto_endif); + m_lines_changed = false; + + // Update line and column indicator in the status bar + int o_line = m_line; + update_rowcol_indicator (line, col); + + // Do smart indent after update of line indicator for having + // consistent indicator data + if (do_smart_indent) + m_edit_area->smart_indent (m_smart_indent, m_auto_endif, + o_line, m_ind_char_width); + } + + void file_editor_tab::update_rowcol_indicator (int line, int col) + { + m_line = line; + m_col = col; + m_row_indicator->setNum (line+1); + m_col_indicator->setNum (col+1); + } + + // Slot that is entered each time a new character was typed. + // It is used for handling line breaking if this is desired. + // The related signal is emitted after the signal for a moved cursor + // such that m_col and m_line can not be used for current position. + void file_editor_tab::handle_char_added (int) + { + if (m_line_break) + { + // If line breaking is desired, get the current line and column. + // For taking the tab width into consideration, use own function + int line, col, pos; + m_edit_area->get_current_position (&pos, &line, &col); + + // immediately return if line has not reached the max. line length + if (col <= m_line_break) + return; + + // If line breaking is only desired in comments, + // return if not in a comment + int style_comment = octave_qscintilla::ST_NONE; + if (m_line_break_comments) + { + // line breaking only in comments, check for comment style + style_comment = m_edit_area->is_style_comment (); + if (! style_comment) + return; // no comment, return + } + + // Here we go for breaking the current line by inserting a newline. + // For determining the position of a specific column, we have to get + // the column from the QScintilla function without taking tab lengths + // into account, since the calculation from line/col to position + // ignores this, too. + m_edit_area->getCursorPosition (&line, &col); + int c = 0; + int col_space = col; + int indentation = m_edit_area->indentation (line); + + // Search the first occurrence of space or tab backwards starting from + // the current column (col_space). + while (c != ' ' && c != '\t' && col_space > indentation) + { + pos = m_edit_area->positionFromLineIndex (line, col_space--); + c = m_edit_area->SendScintilla (QsciScintillaBase::SCI_GETCHARAT, pos); + } + + // If a space or tab was found, break at this char, + // otherwise break at cursor position + int col_newline = col - 1; + if (c == ' ' || c == '\t') + col_newline = col_space + 1; + + // Insert a newline char for breaking the line possibly followed + // by a line comment string + QString newline = QString ("\n"); + style_comment = m_edit_area->is_style_comment (); + if (style_comment == octave_qscintilla::ST_LINE_COMMENT) + newline = newline + m_edit_area->comment_string ().at (0); + m_edit_area->insertAt (newline, line, col_newline); + + // Automatically indent the new line to the indentation of previous line + // and set the cursor position to the end of the indentation. + m_edit_area->setIndentation (line + 1, indentation); + m_edit_area->SendScintilla (QsciScintillaBase::SCI_LINEEND); + } + } + + // Slot handling a double click into the text area + void file_editor_tab::handle_double_click (int, int, int modifier) + { + if (! modifier) + { + // double clicks without modifier + // clear any existing indicators of this type + m_edit_area->clear_selection_markers (); + + if (m_highlight_all_occurrences) + { + // Clear any previous selection. + m_edit_area->set_word_selection (); + + // highlighting of all occurrences of the clicked word is enabled + + // get the resulting cursor position + // (required if click was beyond a line ending) + int line, col; + m_edit_area->getCursorPosition (&line, &col); + + // get the word at the cursor (if any) + QString word = m_edit_area->wordAtLineIndex (line, col); + word = word.trimmed (); + + if (! word.isEmpty ()) + { + // word is not empty, so find all occurrences of the word + + // remember first visible line and x-offset for restoring the view afterwards + int first_line = m_edit_area->firstVisibleLine (); + int x_offset = m_edit_area->SendScintilla (QsciScintillaBase::SCI_GETXOFFSET); + + // search for first occurrence of the detected word + bool find_result_available + = m_edit_area->findFirst (word, + false, // no regexp + true, // case sensitive + true, // whole words only + false, // do not wrap + true, // forward + 0, 0, // from the beginning + false #if defined (HAVE_QSCI_VERSION_2_6_0) - , true + , true #endif - ); - - // loop over all occurrences and set the related indicator - int oline, ocol; - int wlen = word.length (); - - while (find_result_available) - { - // get cursor position after having found an occurrence - m_edit_area->getCursorPosition (&oline, &ocol); - // mark the selection - m_edit_area->show_selection_markers (oline, ocol-wlen, oline, ocol); - - // find next occurrence - find_result_available = m_edit_area->findNext (); - } - - // restore the visible area of the file, the cursor position, - // and the selection - m_edit_area->setFirstVisibleLine (first_line); - m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETXOFFSET, x_offset); - m_edit_area->setCursorPosition (line, col); - m_edit_area->setSelection (line, col - wlen, line, col); - m_edit_area->set_word_selection (word); - } - } - } -} - -QString file_editor_tab::get_function_name (void) -{ - QRegExp rxfun1 ("^[\t ]*function[^=]+=([^\\(]+)\\([^\\)]*\\)[\t ]*$"); - QRegExp rxfun2 ("^[\t ]*function[\t ]+([^\\(]+)\\([^\\)]*\\)[\t ]*$"); - QRegExp rxfun3 ("^[\t ]*function[^=]+=[\t ]*([^\\s]+)[\t ]*$"); - QRegExp rxfun4 ("^[\t ]*function[\t ]+([^\\s]+)[\t ]*$"); - QRegExp rxfun5 ("^[\t ]*classdef[\t ]+([^\\s]+)[\t ]*$"); - - QStringList lines = m_edit_area->text ().split ("\n"); - - for (int i = 0; i < lines.count (); i++) - { - if (rxfun1.indexIn (lines.at (i)) != -1) - return rxfun1.cap (1).remove (QRegExp ("[ \t]*")); - else if (rxfun2.indexIn (lines.at (i)) != -1) - return rxfun2.cap (1).remove (QRegExp ("[ \t]*")); - else if (rxfun3.indexIn (lines.at (i)) != -1) - return rxfun3.cap (1).remove (QRegExp ("[ \t]*")); - else if (rxfun4.indexIn (lines.at (i)) != -1) - return rxfun4.cap (1).remove (QRegExp ("[ \t]*")); - else if (rxfun5.indexIn (lines.at (i)) != -1) - return rxfun5.cap (1).remove (QRegExp ("[ \t]*")); - } - - return QString (); -} + ); + + // loop over all occurrences and set the related indicator + int oline, ocol; + int wlen = word.length (); + + while (find_result_available) + { + // get cursor position after having found an occurrence + m_edit_area->getCursorPosition (&oline, &ocol); + // mark the selection + m_edit_area->show_selection_markers (oline, ocol-wlen, oline, ocol); + + // find next occurrence + find_result_available = m_edit_area->findNext (); + } + + // restore the visible area of the file, the cursor position, + // and the selection + m_edit_area->setFirstVisibleLine (first_line); + m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETXOFFSET, x_offset); + m_edit_area->setCursorPosition (line, col); + m_edit_area->setSelection (line, col - wlen, line, col); + m_edit_area->set_word_selection (word); + } + } + } + } + + QString file_editor_tab::get_function_name (void) + { + QRegExp rxfun1 ("^[\t ]*function[^=]+=([^\\(]+)\\([^\\)]*\\)[\t ]*$"); + QRegExp rxfun2 ("^[\t ]*function[\t ]+([^\\(]+)\\([^\\)]*\\)[\t ]*$"); + QRegExp rxfun3 ("^[\t ]*function[^=]+=[\t ]*([^\\s]+)[\t ]*$"); + QRegExp rxfun4 ("^[\t ]*function[\t ]+([^\\s]+)[\t ]*$"); + QRegExp rxfun5 ("^[\t ]*classdef[\t ]+([^\\s]+)[\t ]*$"); + + QStringList lines = m_edit_area->text ().split ("\n"); + + for (int i = 0; i < lines.count (); i++) + { + if (rxfun1.indexIn (lines.at (i)) != -1) + return rxfun1.cap (1).remove (QRegExp ("[ \t]*")); + else if (rxfun2.indexIn (lines.at (i)) != -1) + return rxfun2.cap (1).remove (QRegExp ("[ \t]*")); + else if (rxfun3.indexIn (lines.at (i)) != -1) + return rxfun3.cap (1).remove (QRegExp ("[ \t]*")); + else if (rxfun4.indexIn (lines.at (i)) != -1) + return rxfun4.cap (1).remove (QRegExp ("[ \t]*")); + else if (rxfun5.indexIn (lines.at (i)) != -1) + return rxfun5.cap (1).remove (QRegExp ("[ \t]*")); + } + + return QString (); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/m-editor/file-editor-tab.h --- a/libgui/src/m-editor/file-editor-tab.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/m-editor/file-editor-tab.h Tue Dec 06 15:45:27 2022 -0500 @@ -36,7 +36,6 @@ #include #include -#include "gui-settings.h" #include "marker.h" #include "octave-qscintilla.h" #include "qt-interpreter-events.h" @@ -45,308 +44,308 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class file_editor; + class base_qobject; + class file_editor; -class file_editor_tab : public QWidget -{ - Q_OBJECT + class file_editor_tab : public QWidget + { + Q_OBJECT -public: + public: - file_editor_tab (base_qobject& oct_qobj, const QString& directory = ""); + file_editor_tab (base_qobject& oct_qobj, const QString& directory = ""); - ~file_editor_tab (void); + ~file_editor_tab (void); - octave_qscintilla * qsci_edit_area (void) { return m_edit_area; } + octave_qscintilla * qsci_edit_area (void) { return m_edit_area; } - // Will initiate close if associated with the identifier tag. - bool conditional_close (void); + // Will initiate close if associated with the identifier tag. + bool conditional_close (void); - void update_breakpoints (); - void set_file_name (const QString& fileName); - void enable_file_watcher (bool do_enable); + void update_breakpoints (); + void set_file_name (const QString& fileName); + void enable_file_watcher (bool do_enable); - QString file_name (void) const { return m_file_name; } - QString encoding (void) const { return m_encoding; } + QString file_name (void) const { return m_file_name; } + QString encoding (void) const { return m_encoding; } -signals: + signals: - void tab_ready_to_close (void); - void file_name_changed (const QString& fileName, - const QString& toolTip, - bool modified); - void editor_state_changed (bool copy_available, bool is_octave_file, - bool is_modified); - void set_focus_editor_signal (QWidget *); - void edit_area_changed (octave_qscintilla *edit_area); - void tab_remove_request (void); - void mru_add_file (const QString& file_name, const QString& encoding); - void editor_check_conflict_save (const QString& saveFileName, - bool remove_on_success); - void run_file_signal (const QFileInfo& info); - void request_open_file (const QString&, const QString& = QString ()); - void edit_mfile_request (const QString&, const QString&, - const QString&, int); + void tab_ready_to_close (void); + void file_name_changed (const QString& fileName, + const QString& toolTip, + bool modified); + void editor_state_changed (bool copy_available, bool is_octave_file, + bool is_modified); + void set_focus_editor_signal (QWidget *); + void edit_area_changed (octave_qscintilla *edit_area); + void tab_remove_request (void); + void mru_add_file (const QString& file_name, const QString& encoding); + void editor_check_conflict_save (const QString& saveFileName, + bool remove_on_success); + void run_file_signal (const QFileInfo& info); + void request_open_file (const QString&, const QString& = QString ()); + void edit_mfile_request (const QString&, const QString&, + const QString&, int); - void autoc_closed (void); + void autoc_closed (void); - void update_breakpoints_signal (const octave_value_list& args); + void update_breakpoints_signal (const octave_value_list& args); - void remove_breakpoint_via_debugger_linenr (int debugger_linenr); - void request_remove_breakpoint_via_editor_linenr (int editor_linenr); - void remove_all_breakpoints_signal (void); - void find_translated_line_number (int original_linenr, - int& translated_linenr, marker*&); - void find_linenr_just_before (int linenr, int& original_linenr, - int& editor_linenr); - void report_marker_linenr (QIntList& lines, QStringList& conditions); - void remove_position_via_debugger_linenr (int debugger_linenr); - void remove_all_positions (void); + void remove_breakpoint_via_debugger_linenr (int debugger_linenr); + void request_remove_breakpoint_via_editor_linenr (int editor_linenr); + void remove_all_breakpoints_signal (void); + void find_translated_line_number (int original_linenr, + int& translated_linenr, marker*&); + void find_linenr_just_before (int linenr, int& original_linenr, + int& editor_linenr); + void report_marker_linenr (QIntList& lines, QStringList& conditions); + void remove_position_via_debugger_linenr (int debugger_linenr); + void remove_all_positions (void); - void debug_quit_signal (void); + void debug_quit_signal (void); - void interpreter_event (const fcn_callback& fcn); - void interpreter_event (const meth_callback& meth); + void interpreter_event (const fcn_callback& fcn); + void interpreter_event (const meth_callback& meth); - void maybe_remove_next (int remove_line); + void maybe_remove_next (int remove_line); - void dbstop_if (const QString& prompt, int line, const QString& cond); - void request_add_breakpoint (int line, const QString& cond); - void request_add_octave_apis (const QStringList&); - void api_entries_added (void); + void dbstop_if (const QString& prompt, int line, const QString& cond); + void request_add_breakpoint (int line, const QString& cond); + void request_add_octave_apis (const QStringList&); + void api_entries_added (void); - void do_save_file_signal (const QString& file_to_save, - bool remove_on_success, bool restore_breakpoints); + void do_save_file_signal (const QString& file_to_save, + bool remove_on_success, bool restore_breakpoints); - void confirm_dbquit_and_save_signal (const QString& file_to_save, - const QString& base_name, - bool remove_on_success, - bool restore_breakpoints); + void confirm_dbquit_and_save_signal (const QString& file_to_save, + const QString& base_name, + bool remove_on_success, + bool restore_breakpoints); - // FIXME: The following is similar to "process_octave_code" signal. - // However, currently that signal is connected to something that simply - // focuses a window and does not actually communicate with Octave. - // - // void evaluate_octave_command (const QString& command); + // FIXME: The following is similar to "process_octave_code" signal. + // However, currently that signal is connected to something that simply + // focuses a window and does not actually communicate with Octave. + // + // void evaluate_octave_command (const QString& command); -public slots: + public slots: - void update_window_title (bool modified); - void handle_copy_available (bool enableCopy); - void handle_margin_clicked (int line, int margin, - Qt::KeyboardModifiers state); + void update_window_title (bool modified); + void handle_copy_available (bool enableCopy); + void handle_margin_clicked (int line, int margin, + Qt::KeyboardModifiers state); - // Tells the editor tab to react on changed settings. - void notice_settings (const gui_settings *settings, bool init = false); + // Tells the editor tab to react on changed settings. + void notice_settings (bool init = false); - // Change to a different editor tab by identifier tag. - void change_editor_state (const QWidget *ID); + // Change to a different editor tab by identifier tag. + void change_editor_state (const QWidget *ID); - void set_focus (const QWidget *ID); - void set_current_directory (const QString& dir); - void context_help (const QWidget *ID, bool); - void context_edit (const QWidget *ID); - void save_file (const QWidget *ID); - void save_file (const QWidget *ID, const QString& fileName, - bool remove_on_success); - void save_file_as (const QWidget *ID); - void print_file (const QWidget *ID); - void run_file (const QWidget *ID, bool step_into = false); - void context_run (const QWidget *ID); - void toggle_bookmark (const QWidget *ID); - void next_bookmark (const QWidget *ID); - void previous_bookmark (const QWidget *ID); - void remove_bookmark (const QWidget *ID); + void set_focus (const QWidget *ID); + void set_current_directory (const QString& dir); + void context_help (const QWidget *ID, bool); + void context_edit (const QWidget *ID); + void save_file (const QWidget *ID); + void save_file (const QWidget *ID, const QString& fileName, + bool remove_on_success); + void save_file_as (const QWidget *ID); + void print_file (const QWidget *ID); + void run_file (const QWidget *ID, bool step_into = false); + void context_run (const QWidget *ID); + void toggle_bookmark (const QWidget *ID); + void next_bookmark (const QWidget *ID); + void previous_bookmark (const QWidget *ID); + void remove_bookmark (const QWidget *ID); - void toggle_breakpoint (const QWidget *ID); - void next_breakpoint (const QWidget *ID); - void previous_breakpoint (const QWidget *ID); - void remove_all_breakpoints (const QWidget *ID); + void toggle_breakpoint (const QWidget *ID); + void next_breakpoint (const QWidget *ID); + void previous_breakpoint (const QWidget *ID); + void remove_all_breakpoints (const QWidget *ID); - void scintilla_command (const QWidget *, unsigned int); + void scintilla_command (const QWidget *, unsigned int); - void comment_selected_text (const QWidget *ID, bool input_str); - void uncomment_selected_text (const QWidget *ID); + void comment_selected_text (const QWidget *ID, bool input_str); + void uncomment_selected_text (const QWidget *ID); - void indent_selected_text (const QWidget *ID); - void unindent_selected_text (const QWidget *ID); - void smart_indent_line_or_selected_text (const QWidget *ID); - void convert_eol (const QWidget *ID, QsciScintilla::EolMode); + void indent_selected_text (const QWidget *ID); + void unindent_selected_text (const QWidget *ID); + void smart_indent_line_or_selected_text (const QWidget *ID); + void convert_eol (const QWidget *ID, QsciScintilla::EolMode); - void zoom_in (const QWidget *ID); - void zoom_out (const QWidget *ID); - void zoom_normal (const QWidget *ID); + void zoom_in (const QWidget *ID); + void zoom_out (const QWidget *ID); + void zoom_normal (const QWidget *ID); - void goto_line (const QWidget *ID, int line = -1); - void move_match_brace (const QWidget *ID, bool select); - void show_auto_completion (const QWidget *ID); + void goto_line (const QWidget *ID, int line = -1); + void move_match_brace (const QWidget *ID, bool select); + void show_auto_completion (const QWidget *ID); - void insert_debugger_pointer (const QWidget *ID, int line = -1); - void delete_debugger_pointer (const QWidget *ID, int line = -1); + void insert_debugger_pointer (const QWidget *ID, int line = -1); + void delete_debugger_pointer (const QWidget *ID, int line = -1); - void do_breakpoint_marker (bool insert, const QWidget *ID, int line = -1, - const QString& cond = ""); + void do_breakpoint_marker (bool insert, const QWidget *ID, int line = -1, + const QString& cond = ""); - void recover_from_exit (void); - void set_modified (bool modified = true); + void recover_from_exit (void); + void set_modified (bool modified = true); - void set_encoding (const QString& new_encoding); + void set_encoding (const QString& new_encoding); - QString load_file (const QString& fileName); + QString load_file (const QString& fileName); - void new_file (const QString& commands = QString ()); + void new_file (const QString& commands = QString ()); - void file_has_changed (const QString& path, bool do_close = false); + void file_has_changed (const QString& path, bool do_close = false); - void handle_context_menu_edit (const QString&); - void handle_context_menu_break_condition (int linenr); + void handle_context_menu_edit (const QString&); + void handle_context_menu_break_condition (int linenr); - void handle_request_add_breakpoint (int line, const QString& cond); - void handle_request_remove_breakpoint (int line); + void handle_request_add_breakpoint (int line, const QString& cond); + void handle_request_remove_breakpoint (int line); - void update_breakpoints_handler (const octave_value_list& argout); - void update_rowcol_indicator (int line, int col); - void update_lexer_settings (bool update_apis_only = false); + void update_breakpoints_handler (const octave_value_list& argout); + void update_rowcol_indicator (int line, int col); + void update_lexer_settings (bool update_apis_only = false); -private slots: + private slots: - // When user closes message box for decoding problems - void handle_decode_warning_answer (QAbstractButton *btn); + // When user closes message box for decoding problems + void handle_decode_warning_answer (QAbstractButton *btn); - // When user closes message box for reload question. - void handle_file_reload_answer (int decision); + // When user closes message box for reload question. + void handle_file_reload_answer (int decision); - // When user closes message box for resave question. - void handle_file_resave_answer (int decision); + // When user closes message box for resave question. + void handle_file_resave_answer (int decision); - // When user closes QFileDialog box. - void handle_save_file_as_answer (const QString& fileName); - void handle_save_file_as_answer_close (const QString& fileName); - void handle_save_file_as_answer_cancel (void); - void handle_save_as_filter_selected (const QString& filter); + // When user closes QFileDialog box. + void handle_save_file_as_answer (const QString& fileName); + void handle_save_file_as_answer_close (const QString& fileName); + void handle_save_file_as_answer_cancel (void); + void handle_save_as_filter_selected (const QString& filter); - // When user changes encoding after decoding errors were found - void handle_current_enc_changed (const QString& enc); + // When user changes encoding after decoding errors were found + void handle_current_enc_changed (const QString& enc); - // When apis preparation has finished and is ready to save - void save_apis_info (void); + // When apis preparation has finished and is ready to save + void save_apis_info (void); - // When the numer of lines changes -> adapt width of margin - void auto_margin_width (void); + // When the numer of lines changes -> adapt width of margin + void auto_margin_width (void); - void handle_cursor_moved (int line, int col); - void handle_char_added (int character); - void handle_double_click (int p, int l, int modifier); - void handle_lines_changed (void); + void handle_cursor_moved (int line, int col); + void handle_char_added (int character); + void handle_double_click (int p, int l, int modifier); + void handle_lines_changed (void); - void handle_remove_next (int remove_line); - void handle_dbstop_if (const QString& prompt, int line, - const QString& cond); - void handle_add_octave_apis (const QStringList& api_entries); - void handle_api_entries_added (void); + void handle_remove_next (int remove_line); + void handle_dbstop_if (const QString& prompt, int line, + const QString& cond); + void handle_add_octave_apis (const QStringList& api_entries); + void handle_api_entries_added (void); - void do_save_file (const QString& file_to_save, bool remove_on_success, - bool restore_breakpoints); + void do_save_file (const QString& file_to_save, bool remove_on_success, + bool restore_breakpoints); - void confirm_dbquit_and_save (const QString& file_to_save, - const QString& base_name, - bool remove_on_success, - bool restore_breakpoints); + void confirm_dbquit_and_save (const QString& file_to_save, + const QString& base_name, + bool remove_on_success, + bool restore_breakpoints); -protected: + protected: - void closeEvent (QCloseEvent *event); + void closeEvent (QCloseEvent *event); -private: + private: - base_qobject& m_octave_qobj; + base_qobject& m_octave_qobj; - void add_breakpoint_event (int line, const QString& cond); + void add_breakpoint_event (int line, const QString& cond); - bool valid_file_name (const QString& file = QString ()); - void save_file (const QString& saveFileName, bool remove_on_success = false, - bool restore_breakpoints = true); - void save_file_as (bool remove_on_success = false); - bool check_valid_identifier (QString file_name); - QTextCodec * check_valid_codec (void); + bool valid_file_name (const QString& file = QString ()); + void save_file (const QString& saveFileName, bool remove_on_success = false, + bool restore_breakpoints = true); + void save_file_as (bool remove_on_success = false); + bool check_valid_identifier (QString file_name); + QTextCodec * check_valid_codec (void); - bool unchanged_or_saved (void); + bool unchanged_or_saved (void); - void update_lexer (void); + void update_lexer (void); - void show_dialog (QDialog *dlg, bool modal); + void show_dialog (QDialog *dlg, bool modal); -public: + public: - int check_file_modified (bool remove = false); - QString get_all_bookmarks (void); + int check_file_modified (bool remove = false); + QString get_all_bookmarks (void); -private: - void do_comment_selected_text (bool comment, bool input_str = false); - void do_indent_selected_text (bool indent); - void do_smart_indent_line_or_selected_text (void); + private: + void do_comment_selected_text (bool comment, bool input_str = false); + void do_indent_selected_text (bool indent); + void do_smart_indent_line_or_selected_text (void); - void check_restore_breakpoints (void); - void center_current_line (bool always=true); + void check_restore_breakpoints (void); + void center_current_line (bool always=true); - QString get_function_name (void); + QString get_function_name (void); - QsciScintilla::EolMode detect_eol_mode (void); - void update_eol_indicator (void); + QsciScintilla::EolMode detect_eol_mode (void); + void update_eol_indicator (void); - octave_qscintilla *m_edit_area; + octave_qscintilla *m_edit_area; - QStatusBar *m_status_bar; - QLabel *m_row_indicator; - QLabel *m_col_indicator; - QLabel *m_eol_indicator; - QLabel *m_enc_indicator; + QStatusBar *m_status_bar; + QLabel *m_row_indicator; + QLabel *m_col_indicator; + QLabel *m_eol_indicator; + QLabel *m_enc_indicator; - QsciScintilla::EolMode m_save_as_desired_eol; + QsciScintilla::EolMode m_save_as_desired_eol; - QString m_file_name; - QString m_file_name_short; - QString m_ced; - QString m_encoding; - QString m_new_encoding; - QDateTime m_last_modified; + QString m_file_name; + QString m_file_name_short; + QString m_ced; + QString m_encoding; + QString m_new_encoding; + QDateTime m_last_modified; - bool m_autoc_active; - bool m_copy_available; - bool m_is_octave_file; - bool m_always_reload_changed_files; - bool m_smart_indent; - int m_auto_endif; - int m_ind_char_width; + bool m_autoc_active; + bool m_copy_available; + bool m_is_octave_file; + bool m_always_reload_changed_files; + bool m_smart_indent; + int m_auto_endif; + int m_ind_char_width; - QFileSystemWatcher m_file_system_watcher; + QFileSystemWatcher m_file_system_watcher; - QIntList m_bp_lines; - QStringList m_bp_conditions; + QIntList m_bp_lines; + QStringList m_bp_conditions; - QsciAPIs *m_lexer_apis; - QString m_prep_apis_path; - QString m_prep_apis_file; + QsciAPIs *m_lexer_apis; + QString m_prep_apis_path; + QString m_prep_apis_file; - int m_line_break; - bool m_line_break_comments; - int m_line; - int m_col; - bool m_lines_changed; - bool m_highlight_all_occurrences; - int m_bp_restore_count; + int m_line_break; + bool m_line_break_comments; + int m_line; + int m_col; + bool m_lines_changed; + bool m_highlight_all_occurrences; + int m_bp_restore_count; - struct breakpoint_info - { - bool remove_next; - int remove_line; - int do_not_remove_line; + struct breakpoint_info + { + bool remove_next; + int remove_line; + int do_not_remove_line; + }; + + breakpoint_info m_breakpoint_info; }; - breakpoint_info m_breakpoint_info; -}; - OCTAVE_END_NAMESPACE(octave) #endif diff -r 29d734430e5f -r deb553ac2c54 libgui/src/m-editor/file-editor.cc --- a/libgui/src/m-editor/file-editor.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/m-editor/file-editor.cc Tue Dec 06 15:45:27 2022 -0500 @@ -50,6 +50,7 @@ #include "gui-preferences-ed.h" #include "gui-preferences-sc.h" #include "gui-preferences-global.h" +#include "gui-settings.h" #include "main-window.h" #include "octave-qobject.h" #include "octave-qtutils.h" @@ -65,2806 +66,2807 @@ OCTAVE_BEGIN_NAMESPACE(octave) -// Functions of the the reimplemented tab widget - -file_editor_tab_widget::file_editor_tab_widget (QWidget *p, file_editor *fe) -: QTabWidget (p) -{ - tab_bar *bar = new tab_bar (this); - - connect (bar, &tab_bar::close_current_tab_signal, - fe, &file_editor::request_close_file); - - this->setTabBar (bar); - - setTabsClosable (true); - setUsesScrollButtons (true); - setMovable (true); -} - -tab_bar *file_editor_tab_widget::get_tab_bar (void) const -{ - return qobject_cast (tabBar ()); -} - -std::list -file_editor_tab_widget::tab_list (void) const -{ - std::list retval; - for (int i = 0; i < count (); i++) - retval.push_back (static_cast (widget (i))); - return retval; -} - -// File editor - -file_editor::file_editor (QWidget *p, base_qobject& oct_qobj) - : file_editor_interface (p, oct_qobj) -{ - // Set current editing directory before construction because loaded - // files will change ced accordingly. - m_ced = QDir::currentPath (); - - // Set actions that are later added by the main window to null, - // preventing access to them when they are still undefined. - m_undo_action = nullptr; - m_copy_action = nullptr; - m_paste_action = nullptr; - m_selectall_action = nullptr; - - m_find_dialog = nullptr; - - m_closed = false; - m_no_focus = false; - m_editor_ready = false; - - m_copy_action_enabled = false; - m_undo_action_enabled = false; - m_current_tab_modified = false; - - construct (); - - setVisible (false); - setAcceptDrops (true); - setFocusPolicy (Qt::StrongFocus); -} - -void file_editor::focusInEvent (QFocusEvent *e) -{ - // The focus is transferred to the active tab and its edit - // area in this focus in event handler. This is to avoid - // using focus proxies with conflicts in the proxy change - // presumably introduced by bug - // https://bugreports.qt.io/browse/QTBUG-61092 - reset_focus (); // Make sure editor tab with edit area get focus - - QDockWidget::focusInEvent (e); -} - -// insert global actions, that should also be displayed in the editor window, -// into the editor's menu and/or toolbar -void file_editor::insert_global_actions (QList shared_actions) -{ - // actions/menus that have to be added to the toolbar or the menu - QAction *open_action = shared_actions.at (OPEN_ACTION); - QAction *new_action = shared_actions.at (NEW_SCRIPT_ACTION); - QAction *new_fcn_action = shared_actions.at (NEW_FUNCTION_ACTION); - m_fileMenu->insertAction (m_mru_file_menu->menuAction (), open_action); - m_fileMenu->insertAction (open_action, new_fcn_action); - m_fileMenu->insertAction (new_fcn_action, new_action); - m_tool_bar->insertAction (m_popdown_mru_action, open_action); - m_tool_bar->insertAction (open_action, new_action); - - // actions that are additionally enabled/disabled later by the editor - // undo - m_undo_action = shared_actions.at (UNDO_ACTION); - m_tool_bar->insertAction (m_redo_action, m_undo_action); - m_edit_menu->insertAction (m_redo_action, m_undo_action); - // select all - m_selectall_action = shared_actions.at (SELECTALL_ACTION); - m_edit_menu->insertAction (m_find_action, m_selectall_action); - m_edit_menu->insertSeparator (m_find_action); - // paste - m_paste_action = shared_actions.at (PASTE_ACTION); - m_tool_bar->insertAction (m_find_action, m_paste_action); - m_edit_menu->insertAction (m_selectall_action, m_paste_action); - m_edit_menu->insertSeparator (m_selectall_action); - // copy - m_copy_action = shared_actions.at (COPY_ACTION); - m_tool_bar->insertAction (m_paste_action, m_copy_action); - m_edit_menu->insertAction (m_paste_action, m_copy_action); - // find files - m_find_files_action = shared_actions.at (FIND_FILES_ACTION); - m_edit_menu->insertAction (m_find_action, m_find_files_action); -} - -void file_editor::handle_enter_debug_mode (void) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - QString sc_run = settings->sc_value (sc_edit_run_run_file); - QString sc_cont = settings->sc_value (sc_main_debug_continue); - - if (sc_run == sc_cont) - m_run_action->setShortcut (QKeySequence ()); // prevent ambiguous shortcuts - - m_run_action->setToolTip (tr ("Continue")); // update tool tip - - emit enter_debug_mode_signal (); -} - -void file_editor::handle_exit_debug_mode (void) -{ - shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); - scmgr.set_shortcut (m_run_action, sc_edit_run_run_file); - m_run_action->setToolTip (tr ("Save File and Run")); // update tool tip - - emit exit_debug_mode_signal (); -} - -void file_editor::check_actions (void) -{ - // Do not include shared actions not only related to the editor - bool have_tabs = m_tab_widget->count () > 0; - - m_edit_cmd_menu->setEnabled (have_tabs); - m_edit_fmt_menu->setEnabled (have_tabs); - m_edit_nav_menu->setEnabled (have_tabs); - - m_comment_selection_action->setEnabled (have_tabs); - m_uncomment_selection_action->setEnabled (have_tabs); - m_comment_var_selection_action->setEnabled (have_tabs); - m_indent_selection_action->setEnabled (have_tabs); - m_unindent_selection_action->setEnabled (have_tabs); - m_smart_indent_line_or_selection_action->setEnabled (have_tabs); - - m_context_help_action->setEnabled (have_tabs); - m_context_doc_action->setEnabled (have_tabs); - - m_view_editor_menu->setEnabled (have_tabs); - m_zoom_in_action->setEnabled (have_tabs); - m_zoom_out_action->setEnabled (have_tabs); - m_zoom_normal_action->setEnabled (have_tabs); - - m_find_action->setEnabled (have_tabs); - m_find_next_action->setEnabled (have_tabs); - m_find_previous_action->setEnabled (have_tabs); - m_print_action->setEnabled (have_tabs); - - m_run_action->setEnabled (have_tabs && m_is_octave_file); - - m_toggle_breakpoint_action->setEnabled (have_tabs && m_is_octave_file); - m_next_breakpoint_action->setEnabled (have_tabs && m_is_octave_file); - m_previous_breakpoint_action->setEnabled (have_tabs && m_is_octave_file); - m_remove_all_breakpoints_action->setEnabled (have_tabs && m_is_octave_file); - - m_edit_function_action->setEnabled (have_tabs); - m_save_action->setEnabled (have_tabs && m_current_tab_modified); - m_save_as_action->setEnabled (have_tabs); - m_close_action->setEnabled (have_tabs); - m_close_all_action->setEnabled (have_tabs); - m_close_others_action->setEnabled (have_tabs && m_tab_widget->count () > 1); - m_sort_tabs_action->setEnabled (have_tabs && m_tab_widget->count () > 1); - - emit editor_tabs_changed_signal (have_tabs, m_is_octave_file); -} - -// empty_script determines whether we have to create an empty script -// 1. At startup, when the editor has to be (really) visible -// (Here we can not use the visibility changed signal) -// 2. When the editor becomes visible when octave is running -void file_editor::empty_script (bool startup, bool visible) -{ - - if (startup) - m_editor_ready = true; - else - { - if (! m_editor_ready) - return; // not yet ready but got visibility changed signals - } - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (settings->value (global_use_custom_editor.key, - global_use_custom_editor.def).toBool ()) - return; // do not open an empty script in the external editor - - bool real_visible; - - if (startup) - real_visible = isVisible (); - else - real_visible = visible; - - if (! real_visible || m_tab_widget->count () > 0) - return; - - if (startup && ! isFloating ()) - { - // check if editor is really visible or hidden between tabbed widgets - QWidget *parent = parentWidget (); - - if (parent) - { - QList tab_list = parent->findChildren(); - - bool in_tab = false; - int i = 0; - while ((i < tab_list.count ()) && (! in_tab)) - { - QTabBar *tab = tab_list.at (i); - i++; - - int j = 0; - while ((j < tab->count ()) && (! in_tab)) - { - // check all tabs for the editor - if (tab->tabText (j) == windowTitle ()) - { - // editor is in this tab widget - in_tab = true; - int top = tab->currentIndex (); - if (! (top > -1 && tab->tabText (top) == windowTitle ())) - return; // not current tab -> not visible - } - j++; - } - } - } - } - - request_new_file (""); -} - -void file_editor::restore_session (gui_settings *settings) -{ - //restore previous session - if (! settings->value (ed_restore_session).toBool ()) - return; - - // get the data from the settings file - QStringList sessionFileNames - = settings->value (ed_session_names).toStringList (); - - QStringList session_encodings - = settings->value (ed_session_enc).toStringList (); - - QStringList session_index - = settings->value (ed_session_ind).toStringList (); - - QStringList session_lines - = settings->value (ed_session_lines).toStringList (); - - QStringList session_bookmarks - = settings->value (ed_session_bookmarks).toStringList (); - - // fill a list of the struct and sort it (depending on index) - QList s_data; - - bool do_encoding = (session_encodings.count () == sessionFileNames.count ()); - bool do_index = (session_index.count () == sessionFileNames.count ()); - bool do_lines = (session_lines.count () == sessionFileNames.count ()); - bool do_bookmarks = (session_bookmarks.count () == sessionFileNames.count ()); - - for (int n = 0; n < sessionFileNames.count (); ++n) - { - QFileInfo file = QFileInfo (sessionFileNames.at (n)); - if (! file.exists ()) - continue; - - session_data item = { 0, -1, sessionFileNames.at (n), - QString (), QString (), QString ()}; - if (do_lines) - item.line = session_lines.at (n).toInt (); - if (do_index) - item.index = session_index.at (n).toInt (); - if (do_encoding) - item.encoding = session_encodings.at (n); - if (do_bookmarks) - item.bookmarks = session_bookmarks.at (n); - - s_data << item; - } - - std::sort (s_data.begin (), s_data.end ()); - - // finally open the files with the desired encoding in the desired order - for (int n = 0; n < s_data.count (); ++n) - request_open_file (s_data.at (n).file_name, s_data.at (n).encoding, - s_data.at (n).line, false, false, true, "", -1, - s_data.at (n).bookmarks); -} - -void file_editor::activate (void) -{ - if (m_no_focus) - return; // No focus for the editor if external open/close request - - octave_dock_widget::activate (); - - // set focus to current tab - reset_focus (); -} - -void file_editor::set_focus (QWidget *fet) -{ - setFocus (); - - // set focus to desired tab - if (fet) - m_tab_widget->setCurrentWidget (fet); -} - -// function enabling/disabling the menu accelerators depending on the -// focus of the editor -void file_editor::enable_menu_shortcuts (bool enable) -{ - // Hide or show the find dialog together with the focus of the - // editor widget depending on the overall visibility of the find dialog. - // Do not change internal visibility state. - if (m_find_dialog) - m_find_dialog->set_visible (enable); - - // Take care of the shortcuts - QHash::const_iterator i = m_hash_menu_text.constBegin (); - - while (i != m_hash_menu_text.constEnd ()) - { - i.key ()->setTitle (i.value ().at (! enable)); - ++i; - } - - // when editor loses focus, enable the actions, which are always active - // in the main window due to missing info on selected text and undo actions - if (m_copy_action && m_undo_action) - { - if (enable) - { - m_copy_action->setEnabled (m_copy_action_enabled); - m_undo_action->setEnabled (m_undo_action_enabled); - } - else - { - m_copy_action_enabled = m_copy_action->isEnabled (); - m_undo_action_enabled = m_undo_action->isEnabled (); - m_copy_action->setEnabled (true); - m_undo_action->setEnabled (true); - } - } -} - -// Save open files for restoring in next session -// (even if last session will not be restored next time) -// together with encoding and the tab index -void file_editor::save_session (void) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - QStringList fetFileNames; - QStringList fet_encodings; - QStringList fet_index; - QStringList fet_lines; - QStringList fet_bookmarks; - - std::list editor_tab_lst = m_tab_widget->tab_list (); - - for (auto editor_tab : editor_tab_lst) - { - QString file_name = editor_tab->file_name (); - - // Don't append unnamed files. - - if (! file_name.isEmpty ()) - { - fetFileNames.append (file_name); - fet_encodings.append (editor_tab->encoding ()); - - QString index; - fet_index.append (index.setNum (m_tab_widget->indexOf (editor_tab))); - - int l, c; - editor_tab->qsci_edit_area ()->getCursorPosition (&l, &c); - fet_lines.append (index.setNum (l + 1)); - - fet_bookmarks.append (editor_tab->get_all_bookmarks ()); - } - } - - settings->setValue (ed_session_names.key, fetFileNames); - settings->setValue (ed_session_enc.key, fet_encodings); - settings->setValue (ed_session_ind.key, fet_index); - settings->setValue (ed_session_lines.key, fet_lines); - settings->setValue (ed_session_bookmarks.key, fet_bookmarks); - settings->sync (); -} - -bool file_editor::check_closing (void) -{ - // When the application or the editor is closing and the user wants to - // close all files, in the latter case all editor tabs are checked whether - // they need to be saved. During these checks tabs are not closed since - // the user might cancel closing Octave during one of these saving dialogs. - // Therefore, saving the session for restoring at next start is not done - // before the application is definitely closing. - - // Save the session. Even is closing is cancelled, this would be - // overwritten by the next attempt to close the editor - save_session (); - - std::list fe_tab_lst = m_tab_widget->tab_list (); - m_number_of_tabs = fe_tab_lst.size (); - - for (auto fe_tab : fe_tab_lst) - { - // Wait for all editor tabs to have saved their files if required - - connect (fe_tab, &file_editor_tab::tab_ready_to_close, - this, &file_editor::handle_tab_ready_to_close, - Qt::UniqueConnection); - } - - m_closing_canceled = false; - - for (auto fe_tab : fe_tab_lst) - { - // If there was a cancellation, make the already saved/discarded tabs - // recover from the exit by removing the read-only state and by - // recovering the debugger breakpoints. Finally return false in order - // to cancel closing the application or the editor. - - if (fe_tab->check_file_modified (false) == QMessageBox::Cancel) - { - emit fetab_recover_from_exit (); - - m_closing_canceled = true; - - for (auto fet : fe_tab_lst) - disconnect (fet, &file_editor_tab::tab_ready_to_close, 0, 0); - - return false; - } - } - - return true; -} - -void file_editor::handle_tab_ready_to_close (void) -{ - if (m_closing_canceled) - return; - - // FIXME: Why count down to zero here before doing anything? Why - // not remove and delete each tab that is ready to be closed, one - // per invocation? - - m_number_of_tabs--; - - if (m_number_of_tabs > 0) - return; - - // Here, the application or the editor will be closed -> store the session - - // Take care of the find dialog - if (m_find_dialog) - m_find_dialog->close (); - - // Finally close all the tabs and return indication that we can exit - // the application or close the editor. - // Closing and deleting the tabs makes the editor visible. In case it was - // hidden before, this state has to be restored afterwards. - bool vis = isVisible (); - - std::list editor_tab_lst = m_tab_widget->tab_list (); - for (auto editor_tab : editor_tab_lst) - editor_tab->deleteLater (); - - m_tab_widget->clear (); - - setVisible (vis); -} - -void file_editor::request_new_file (const QString& commands) -{ - // Custom editor? If yes, we can only call the editor without passing - // some initial contents and even without being sure a new file is opened - if (call_custom_editor ()) - return; - - // New file isn't a file_editor_tab function since the file - // editor tab has yet to be created and there is no object to - // pass a signal to. Hence, functionality is here. - - file_editor_tab *fileEditorTab = make_file_editor_tab (m_ced); - add_file_editor_tab (fileEditorTab, ""); // new tab with empty title - fileEditorTab->new_file (commands); // title is updated here - activate (); // focus editor and new tab -} - -void file_editor::request_close_file (bool) -{ - file_editor_tab *editor_tab - = static_cast (m_tab_widget->currentWidget ()); - editor_tab->conditional_close (); -} - -void file_editor::request_close_all_files (bool) -{ - file_editor_tab *editor_tab; - - // loop over all tabs starting from last one otherwise deletion changes index - for (int index = m_tab_widget->count ()-1; index >= 0; index--) - { - editor_tab = static_cast (m_tab_widget->widget (index)); - editor_tab->conditional_close (); - } -} - -void file_editor::request_close_other_files (bool) -{ - file_editor_tab *editor_tab; - QWidget *tabID = m_tab_widget->currentWidget (); - - // loop over all tabs starting from last one otherwise deletion changes index - for (int index = m_tab_widget->count ()-1; index >= 0; index--) - { - if (tabID != m_tab_widget->widget (index)) - { - editor_tab - = static_cast (m_tab_widget->widget (index)); - editor_tab->conditional_close (); - } - } -} - -void file_editor::copy_full_file_path (bool) -{ - file_editor_tab *editor_tab - = static_cast (m_tab_widget->currentWidget ()); - - if (editor_tab) - QGuiApplication::clipboard ()->setText (editor_tab->file_name ()); -} - -// open a file from the mru list -void file_editor::request_mru_open_file (QAction *action) -{ - if (action) - { - request_open_file (action->data ().toStringList ().at (0), - action->data ().toStringList ().at (1)); - } -} - -void file_editor::request_print_file (bool) -{ - emit fetab_print_file (m_tab_widget->currentWidget ()); -} - -void file_editor::request_redo (bool) -{ - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_REDO); -} - -void file_editor::request_cut (bool) -{ - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_CUT); -} - -void file_editor::request_context_help (bool) -{ - emit fetab_context_help (m_tab_widget->currentWidget (), false); -} - -void file_editor::request_context_doc (bool) -{ - emit fetab_context_help (m_tab_widget->currentWidget (), true); -} - -void file_editor::request_context_edit (bool) -{ - emit fetab_context_edit (m_tab_widget->currentWidget ()); -} - -void file_editor::request_save_file (bool) -{ - emit fetab_save_file (m_tab_widget->currentWidget ()); -} - -void file_editor::request_save_file_as (bool) -{ - emit fetab_save_file_as (m_tab_widget->currentWidget ()); -} - -void file_editor::request_run_file (bool) -{ - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - // Act as though this action was entered at the command propmt - // so that the interpreter will check for updated file time - // stamps. - Vlast_prompt_time.stamp (); - - tree_evaluator& tw = interp.get_evaluator (); - - if (tw.in_debug_repl ()) - emit request_dbcont_signal (); - else - emit fetab_run_file (m_tab_widget->currentWidget ()); - }); -} - -void file_editor::request_step_into_file () -{ - emit fetab_run_file (m_tab_widget->currentWidget (), true); -} - -void file_editor::request_context_run (bool) -{ - emit fetab_context_run (m_tab_widget->currentWidget ()); -} - -void file_editor::request_toggle_bookmark (bool) -{ - emit fetab_toggle_bookmark (m_tab_widget->currentWidget ()); -} - -void file_editor::request_next_bookmark (bool) -{ - emit fetab_next_bookmark (m_tab_widget->currentWidget ()); -} - -void file_editor::request_previous_bookmark (bool) -{ - emit fetab_previous_bookmark (m_tab_widget->currentWidget ()); -} - -void file_editor::request_remove_bookmark (bool) -{ - emit fetab_remove_bookmark (m_tab_widget->currentWidget ()); -} - -void file_editor::request_move_match_brace (bool) -{ - emit fetab_move_match_brace (m_tab_widget->currentWidget (), false); -} - -void file_editor::request_sel_match_brace (bool) -{ - emit fetab_move_match_brace (m_tab_widget->currentWidget (), true); -} - -// FIXME: What should this do with conditional breakpoints? -void file_editor::request_toggle_breakpoint (bool) -{ - emit fetab_toggle_breakpoint (m_tab_widget->currentWidget ()); -} - -void file_editor::request_next_breakpoint (bool) -{ - emit fetab_next_breakpoint (m_tab_widget->currentWidget ()); -} - -void file_editor::request_previous_breakpoint (bool) -{ - emit fetab_previous_breakpoint (m_tab_widget->currentWidget ()); -} - -void file_editor::request_remove_breakpoint (bool) -{ - emit fetab_remove_all_breakpoints (m_tab_widget->currentWidget ()); -} - -// slots for Edit->Commands actions -void file_editor::request_delete_start_word (bool) -{ - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_DELWORDLEFT); -} - -void file_editor::request_delete_end_word (bool) -{ - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_DELWORDRIGHT); -} - -void file_editor::request_delete_start_line (bool) -{ - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_DELLINELEFT); -} - -void file_editor::request_delete_end_line (bool) -{ - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_DELLINERIGHT); -} - -void file_editor::request_delete_line (bool) -{ - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_LINEDELETE); -} - -void file_editor::request_copy_line (bool) -{ - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_LINECOPY); -} - -void file_editor::request_cut_line (bool) -{ - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_LINECUT); -} - -void file_editor::request_duplicate_selection (bool) -{ - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_SELECTIONDUPLICATE); -} - -void file_editor::request_transpose_line (bool) -{ - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_LINETRANSPOSE); -} - -void file_editor::request_comment_selected_text (bool) -{ - emit fetab_comment_selected_text (m_tab_widget->currentWidget (), false); -} - -void file_editor::request_uncomment_selected_text (bool) -{ - emit fetab_uncomment_selected_text (m_tab_widget->currentWidget ()); -} - -void file_editor::request_comment_var_selected_text (bool) -{ - emit fetab_comment_selected_text (m_tab_widget->currentWidget (), true); -} - -// slots for Edit->Format actions -void file_editor::request_upper_case (bool) -{ - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_UPPERCASE); -} - -void file_editor::request_lower_case (bool) -{ - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_LOWERCASE); -} - -void file_editor::request_indent_selected_text (bool) -{ - emit fetab_indent_selected_text (m_tab_widget->currentWidget ()); -} - -void file_editor::request_unindent_selected_text (bool) -{ - emit fetab_unindent_selected_text (m_tab_widget->currentWidget ()); -} - -void file_editor::request_smart_indent_line_or_selected_text () -{ - emit fetab_smart_indent_line_or_selected_text (m_tab_widget->currentWidget ()); -} - -void file_editor::request_conv_eol_windows (bool) -{ - emit fetab_convert_eol (m_tab_widget->currentWidget (), - QsciScintilla::EolWindows); -} -void -file_editor::request_conv_eol_unix (bool) -{ - emit fetab_convert_eol (m_tab_widget->currentWidget (), - QsciScintilla::EolUnix); -} - -void file_editor::request_conv_eol_mac (bool) -{ - emit fetab_convert_eol (m_tab_widget->currentWidget (), - QsciScintilla::EolMac); -} - -// Slot for initially creating and showing the find dialog -void file_editor::request_find (bool) -{ - // Create the dialog - find_create (); - - // Since find_create shows the dialog without activating the widget - // (which is reuqired in other cases) do this manually here - m_find_dialog->activateWindow (); - - // Initiate search text from possible selection and save the initial - // data from the dialog on the defined structure - m_find_dialog->init_search_text (); -} - -// This method creates the find dialog. - -void file_editor::find_create () -{ - if (m_find_dialog) - m_find_dialog->close (); - - if (isFloating ()) - m_find_dialog = new find_dialog (m_octave_qobj, this, this); - else - m_find_dialog = new find_dialog (m_octave_qobj, this, parentWidget ()); - - // Add required actions - m_find_dialog->addAction (m_find_next_action); - m_find_dialog->addAction (m_find_previous_action); - - // Update edit area - file_editor_tab *fet - = static_cast (m_tab_widget->currentWidget ()); - m_find_dialog->update_edit_area (fet->qsci_edit_area ()); - - // Icon is the same as the editor - m_find_dialog->setWindowIcon (windowIcon ()); - - // Position: lower right of editor's position - int xp = x () + frameGeometry ().width (); - int yp = y () + frameGeometry ().height (); - - if (! isFloating ()) - { - // Fix position if editor is docked - - QWidget *parent = parentWidget (); - - if (parent) - { - xp = xp + parent->x (); - yp = yp + parent->y (); - } - } - - if (yp < 0) - yp = 0; - - // The size of the find dialog is considered in restore_settings - // since its size might change depending on the options - m_find_dialog->restore_settings (QPoint (xp, yp)); - - // Set visible - m_find_dialog->set_visible (true); -} - -void file_editor::request_find_next (bool) -{ - if (m_find_dialog) - m_find_dialog->find_next (); -} - -void file_editor::request_find_previous (bool) -{ - if (m_find_dialog) - m_find_dialog->find_prev (); -} - -void file_editor::request_goto_line (bool) -{ - emit fetab_goto_line (m_tab_widget->currentWidget ()); -} - -void file_editor::request_completion (bool) -{ - emit fetab_completion (m_tab_widget->currentWidget ()); -} - -void file_editor::handle_file_name_changed (const QString& fname, - const QString& tip, - bool modified) -{ - QObject *fileEditorTab = sender (); - if (fileEditorTab) - { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - - for (int i = 0; i < m_tab_widget->count (); i++) - { - if (m_tab_widget->widget (i) == fileEditorTab) - { - m_tab_widget->setTabText (i, fname); - m_tab_widget->setTabToolTip (i, tip); - - m_save_action->setEnabled (modified); - m_current_tab_modified = modified; - - if (modified) - m_tab_widget->setTabIcon (i, rmgr.icon ("document-save")); - else - m_tab_widget->setTabIcon (i, QIcon ()); - } - } - } -} - -void file_editor::handle_tab_close_request (int index) -{ - file_editor_tab *editor_tab - = static_cast (m_tab_widget->widget (index)); - editor_tab->conditional_close (); -} - -void -file_editor::handle_tab_remove_request (void) -{ - QObject *fileEditorTab = sender (); - if (fileEditorTab) - { - for (int i = 0; i < m_tab_widget->count (); i++) - { - if (m_tab_widget->widget (i) == fileEditorTab) - { - m_tab_widget->removeTab (i); - - // Deleting the sender (even with deleteLater) seems a - // bit strange. Is there a better way? - fileEditorTab->deleteLater (); - break; - } - } - } - check_actions (); - - activate (); // focus stays in editor when tab is closed - -} - -// context menu of edit area -void file_editor::active_tab_changed (int index) -{ - emit fetab_change_request (m_tab_widget->widget (index)); - activate (); -} - -void file_editor::handle_editor_state_changed (bool copy_available, - bool is_octave_file, - bool is_modified) -{ - // In case there is some scenario where traffic could be coming from - // all the file editor tabs, just process info from the current active tab. - if (sender () == m_tab_widget->currentWidget ()) - { - m_save_action->setEnabled (is_modified); - m_current_tab_modified = is_modified; - - if (m_copy_action) - m_copy_action->setEnabled (copy_available); - - m_cut_action->setEnabled (copy_available); - - m_run_selection_action->setEnabled (copy_available); - m_run_action->setEnabled (is_octave_file); - m_is_octave_file = is_octave_file; - - emit editor_tabs_changed_signal (true, m_is_octave_file); - } - - m_copy_action_enabled = m_copy_action->isEnabled (); - m_undo_action_enabled = m_undo_action->isEnabled (); -} - -void file_editor::handle_mru_add_file (const QString& file_name, - const QString& encoding) -{ - int index; - while ((index = m_mru_files.indexOf (file_name)) >= 0) - { - m_mru_files.removeAt (index); - m_mru_files_encodings.removeAt (index); - } - - m_mru_files.prepend (file_name); - m_mru_files_encodings.prepend (encoding); - - mru_menu_update (); -} - -void file_editor::check_conflict_save (const QString& saveFileName, - bool remove_on_success) -{ - // Check whether this file is already open in the editor. - file_editor_tab *tab = find_tab_widget (saveFileName); - - if (tab) - { - // Note: to overwrite the contents of some other file editor tab - // with the same name requires identifying which file editor tab - // that is (not too difficult) then closing that tab. Of course, - // that could trigger another dialog box if the file editor tab - // with the same name has modifications in it. This could become - // somewhat confusing to the user. For now, opt to do nothing. - - // Create a NonModal message about error. - QMessageBox *msgBox - = new QMessageBox (QMessageBox::Critical, tr ("Octave Editor"), - tr ("File not saved! A file with the selected name\n%1\n" - "is already open in the editor"). - arg (saveFileName), - QMessageBox::Ok, nullptr); - - msgBox->setWindowModality (Qt::NonModal); - msgBox->setAttribute (Qt::WA_DeleteOnClose); - msgBox->show (); - + // Functions of the the reimplemented tab widget + + file_editor_tab_widget::file_editor_tab_widget (QWidget *p, file_editor *fe) + : QTabWidget (p) + { + tab_bar *bar = new tab_bar (this); + + connect (bar, &tab_bar::close_current_tab_signal, + fe, &file_editor::request_close_file); + + this->setTabBar (bar); + + setTabsClosable (true); + setUsesScrollButtons (true); + setMovable (true); + } + + tab_bar *file_editor_tab_widget::get_tab_bar (void) const + { + return qobject_cast (tabBar ()); + } + + std::list + file_editor_tab_widget::tab_list (void) const + { + std::list retval; + for (int i = 0; i < count (); i++) + retval.push_back (static_cast (widget (i))); + return retval; + } + + // File editor + + file_editor::file_editor (QWidget *p, base_qobject& oct_qobj) + : file_editor_interface (p, oct_qobj) + { + // Set current editing directory before construction because loaded + // files will change ced accordingly. + m_ced = QDir::currentPath (); + + // Set actions that are later added by the main window to null, + // preventing access to them when they are still undefined. + m_undo_action = nullptr; + m_copy_action = nullptr; + m_paste_action = nullptr; + m_selectall_action = nullptr; + + m_find_dialog = nullptr; + + m_closed = false; + m_no_focus = false; + m_editor_ready = false; + + m_copy_action_enabled = false; + m_undo_action_enabled = false; + m_current_tab_modified = false; + + construct (); + + setVisible (false); + setAcceptDrops (true); + setFocusPolicy (Qt::StrongFocus); + } + + void file_editor::focusInEvent (QFocusEvent *e) + { + // The focus is transferred to the active tab and its edit + // area in this focus in event handler. This is to avoid + // using focus proxies with conflicts in the proxy change + // presumably introduced by bug + // https://bugreports.qt.io/browse/QTBUG-61092 + reset_focus (); // Make sure editor tab with edit area get focus + + QDockWidget::focusInEvent (e); + } + + // insert global actions, that should also be displayed in the editor window, + // into the editor's menu and/or toolbar + void file_editor::insert_global_actions (QList shared_actions) + { + // actions/menus that have to be added to the toolbar or the menu + QAction *open_action = shared_actions.at (OPEN_ACTION); + QAction *new_action = shared_actions.at (NEW_SCRIPT_ACTION); + QAction *new_fcn_action = shared_actions.at (NEW_FUNCTION_ACTION); + m_fileMenu->insertAction (m_mru_file_menu->menuAction (), open_action); + m_fileMenu->insertAction (open_action, new_fcn_action); + m_fileMenu->insertAction (new_fcn_action, new_action); + m_tool_bar->insertAction (m_popdown_mru_action, open_action); + m_tool_bar->insertAction (open_action, new_action); + + // actions that are additionally enabled/disabled later by the editor + // undo + m_undo_action = shared_actions.at (UNDO_ACTION); + m_tool_bar->insertAction (m_redo_action, m_undo_action); + m_edit_menu->insertAction (m_redo_action, m_undo_action); + // select all + m_selectall_action = shared_actions.at (SELECTALL_ACTION); + m_edit_menu->insertAction (m_find_action, m_selectall_action); + m_edit_menu->insertSeparator (m_find_action); + // paste + m_paste_action = shared_actions.at (PASTE_ACTION); + m_tool_bar->insertAction (m_find_action, m_paste_action); + m_edit_menu->insertAction (m_selectall_action, m_paste_action); + m_edit_menu->insertSeparator (m_selectall_action); + // copy + m_copy_action = shared_actions.at (COPY_ACTION); + m_tool_bar->insertAction (m_paste_action, m_copy_action); + m_edit_menu->insertAction (m_paste_action, m_copy_action); + // find files + m_find_files_action = shared_actions.at (FIND_FILES_ACTION); + m_edit_menu->insertAction (m_find_action, m_find_files_action); + } + + void file_editor::handle_enter_debug_mode (void) + { + gui_settings settings; + + QString sc_run = settings.sc_value (sc_edit_run_run_file); + QString sc_cont = settings.sc_value (sc_main_debug_continue); + + if (sc_run == sc_cont) + m_run_action->setShortcut (QKeySequence ()); // prevent ambiguous shortcuts + + m_run_action->setToolTip (tr ("Continue")); // update tool tip + + emit enter_debug_mode_signal (); + } + + void file_editor::handle_exit_debug_mode (void) + { + shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); + scmgr.set_shortcut (m_run_action, sc_edit_run_run_file); + m_run_action->setToolTip (tr ("Save File and Run")); // update tool tip + + emit exit_debug_mode_signal (); + } + + void file_editor::check_actions (void) + { + // Do not include shared actions not only related to the editor + bool have_tabs = m_tab_widget->count () > 0; + + m_edit_cmd_menu->setEnabled (have_tabs); + m_edit_fmt_menu->setEnabled (have_tabs); + m_edit_nav_menu->setEnabled (have_tabs); + + m_comment_selection_action->setEnabled (have_tabs); + m_uncomment_selection_action->setEnabled (have_tabs); + m_comment_var_selection_action->setEnabled (have_tabs); + m_indent_selection_action->setEnabled (have_tabs); + m_unindent_selection_action->setEnabled (have_tabs); + m_smart_indent_line_or_selection_action->setEnabled (have_tabs); + + m_context_help_action->setEnabled (have_tabs); + m_context_doc_action->setEnabled (have_tabs); + + m_view_editor_menu->setEnabled (have_tabs); + m_zoom_in_action->setEnabled (have_tabs); + m_zoom_out_action->setEnabled (have_tabs); + m_zoom_normal_action->setEnabled (have_tabs); + + m_find_action->setEnabled (have_tabs); + m_find_next_action->setEnabled (have_tabs); + m_find_previous_action->setEnabled (have_tabs); + m_print_action->setEnabled (have_tabs); + + m_run_action->setEnabled (have_tabs && m_is_octave_file); + + m_toggle_breakpoint_action->setEnabled (have_tabs && m_is_octave_file); + m_next_breakpoint_action->setEnabled (have_tabs && m_is_octave_file); + m_previous_breakpoint_action->setEnabled (have_tabs && m_is_octave_file); + m_remove_all_breakpoints_action->setEnabled (have_tabs && m_is_octave_file); + + m_edit_function_action->setEnabled (have_tabs); + m_save_action->setEnabled (have_tabs && m_current_tab_modified); + m_save_as_action->setEnabled (have_tabs); + m_close_action->setEnabled (have_tabs); + m_close_all_action->setEnabled (have_tabs); + m_close_others_action->setEnabled (have_tabs && m_tab_widget->count () > 1); + m_sort_tabs_action->setEnabled (have_tabs && m_tab_widget->count () > 1); + + emit editor_tabs_changed_signal (have_tabs, m_is_octave_file); + } + + // empty_script determines whether we have to create an empty script + // 1. At startup, when the editor has to be (really) visible + // (Here we can not use the visibility changed signal) + // 2. When the editor becomes visible when octave is running + void file_editor::empty_script (bool startup, bool visible) + { + + if (startup) + m_editor_ready = true; + else + { + if (! m_editor_ready) + return; // not yet ready but got visibility changed signals + } + + gui_settings settings; + + if (settings.value (global_use_custom_editor.key, + global_use_custom_editor.def).toBool ()) + return; // do not open an empty script in the external editor + + bool real_visible; + + if (startup) + real_visible = isVisible (); + else + real_visible = visible; + + if (! real_visible || m_tab_widget->count () > 0) + return; + + if (startup && ! isFloating ()) + { + // check if editor is really visible or hidden between tabbed widgets + QWidget *parent = parentWidget (); + + if (parent) + { + QList tab_list = parent->findChildren(); + + bool in_tab = false; + int i = 0; + while ((i < tab_list.count ()) && (! in_tab)) + { + QTabBar *tab = tab_list.at (i); + i++; + + int j = 0; + while ((j < tab->count ()) && (! in_tab)) + { + // check all tabs for the editor + if (tab->tabText (j) == windowTitle ()) + { + // editor is in this tab widget + in_tab = true; + int top = tab->currentIndex (); + if (! (top > -1 && tab->tabText (top) == windowTitle ())) + return; // not current tab -> not visible + } + j++; + } + } + } + } + + request_new_file (""); + } + + void file_editor::restore_session (void) + { + gui_settings settings; + + //restore previous session + if (! settings.value (ed_restore_session).toBool ()) + return; + + // get the data from the settings file + QStringList sessionFileNames + = settings.value (ed_session_names).toStringList (); + + QStringList session_encodings + = settings.value (ed_session_enc).toStringList (); + + QStringList session_index + = settings.value (ed_session_ind).toStringList (); + + QStringList session_lines + = settings.value (ed_session_lines).toStringList (); + + QStringList session_bookmarks + = settings.value (ed_session_bookmarks).toStringList (); + + // fill a list of the struct and sort it (depending on index) + QList s_data; + + bool do_encoding = (session_encodings.count () == sessionFileNames.count ()); + bool do_index = (session_index.count () == sessionFileNames.count ()); + bool do_lines = (session_lines.count () == sessionFileNames.count ()); + bool do_bookmarks = (session_bookmarks.count () == sessionFileNames.count ()); + + for (int n = 0; n < sessionFileNames.count (); ++n) + { + QFileInfo file = QFileInfo (sessionFileNames.at (n)); + if (! file.exists ()) + continue; + + session_data item = { 0, -1, sessionFileNames.at (n), + QString (), QString (), QString ()}; + if (do_lines) + item.line = session_lines.at (n).toInt (); + if (do_index) + item.index = session_index.at (n).toInt (); + if (do_encoding) + item.encoding = session_encodings.at (n); + if (do_bookmarks) + item.bookmarks = session_bookmarks.at (n); + + s_data << item; + } + + std::sort (s_data.begin (), s_data.end ()); + + // finally open the files with the desired encoding in the desired order + for (int n = 0; n < s_data.count (); ++n) + request_open_file (s_data.at (n).file_name, s_data.at (n).encoding, + s_data.at (n).line, false, false, true, "", -1, + s_data.at (n).bookmarks); + } + + void file_editor::activate (void) + { + if (m_no_focus) + return; // No focus for the editor if external open/close request + + octave_dock_widget::activate (); + + // set focus to current tab + reset_focus (); + } + + void file_editor::set_focus (QWidget *fet) + { + setFocus (); + + // set focus to desired tab + if (fet) + m_tab_widget->setCurrentWidget (fet); + } + + // function enabling/disabling the menu accelerators depending on the + // focus of the editor + void file_editor::enable_menu_shortcuts (bool enable) + { + // Hide or show the find dialog together with the focus of the + // editor widget depending on the overall visibility of the find dialog. + // Do not change internal visibility state. + if (m_find_dialog) + m_find_dialog->set_visible (enable); + + // Take care of the shortcuts + QHash::const_iterator i = m_hash_menu_text.constBegin (); + + while (i != m_hash_menu_text.constEnd ()) + { + i.key ()->setTitle (i.value ().at (! enable)); + ++i; + } + + // when editor loses focus, enable the actions, which are always active + // in the main window due to missing info on selected text and undo actions + if (m_copy_action && m_undo_action) + { + if (enable) + { + m_copy_action->setEnabled (m_copy_action_enabled); + m_undo_action->setEnabled (m_undo_action_enabled); + } + else + { + m_copy_action_enabled = m_copy_action->isEnabled (); + m_undo_action_enabled = m_undo_action->isEnabled (); + m_copy_action->setEnabled (true); + m_undo_action->setEnabled (true); + } + } + } + + // Save open files for restoring in next session + // (even if last session will not be restored next time) + // together with encoding and the tab index + void file_editor::save_session (void) + { + gui_settings settings; + + QStringList fetFileNames; + QStringList fet_encodings; + QStringList fet_index; + QStringList fet_lines; + QStringList fet_bookmarks; + + std::list editor_tab_lst = m_tab_widget->tab_list (); + + for (auto editor_tab : editor_tab_lst) + { + QString file_name = editor_tab->file_name (); + + // Don't append unnamed files. + + if (! file_name.isEmpty ()) + { + fetFileNames.append (file_name); + fet_encodings.append (editor_tab->encoding ()); + + QString index; + fet_index.append (index.setNum (m_tab_widget->indexOf (editor_tab))); + + int l, c; + editor_tab->qsci_edit_area ()->getCursorPosition (&l, &c); + fet_lines.append (index.setNum (l + 1)); + + fet_bookmarks.append (editor_tab->get_all_bookmarks ()); + } + } + + settings.setValue (ed_session_names.key, fetFileNames); + settings.setValue (ed_session_enc.key, fet_encodings); + settings.setValue (ed_session_ind.key, fet_index); + settings.setValue (ed_session_lines.key, fet_lines); + settings.setValue (ed_session_bookmarks.key, fet_bookmarks); + + settings.sync (); + } + + bool file_editor::check_closing (void) + { + // When the application or the editor is closing and the user wants to + // close all files, in the latter case all editor tabs are checked whether + // they need to be saved. During these checks tabs are not closed since + // the user might cancel closing Octave during one of these saving dialogs. + // Therefore, saving the session for restoring at next start is not done + // before the application is definitely closing. + + // Save the session. Even is closing is cancelled, this would be + // overwritten by the next attempt to close the editor + save_session (); + + std::list fe_tab_lst = m_tab_widget->tab_list (); + m_number_of_tabs = fe_tab_lst.size (); + + for (auto fe_tab : fe_tab_lst) + { + // Wait for all editor tabs to have saved their files if required + + connect (fe_tab, &file_editor_tab::tab_ready_to_close, + this, &file_editor::handle_tab_ready_to_close, + Qt::UniqueConnection); + } + + m_closing_canceled = false; + + for (auto fe_tab : fe_tab_lst) + { + // If there was a cancellation, make the already saved/discarded tabs + // recover from the exit by removing the read-only state and by + // recovering the debugger breakpoints. Finally return false in order + // to cancel closing the application or the editor. + + if (fe_tab->check_file_modified (false) == QMessageBox::Cancel) + { + emit fetab_recover_from_exit (); + + m_closing_canceled = true; + + for (auto fet : fe_tab_lst) + disconnect (fet, &file_editor_tab::tab_ready_to_close, 0, 0); + + return false; + } + } + + return true; + } + + void file_editor::handle_tab_ready_to_close (void) + { + if (m_closing_canceled) + return; + + // FIXME: Why count down to zero here before doing anything? Why + // not remove and delete each tab that is ready to be closed, one + // per invocation? + + m_number_of_tabs--; + + if (m_number_of_tabs > 0) + return; + + // Here, the application or the editor will be closed -> store the session + + // Take care of the find dialog + if (m_find_dialog) + m_find_dialog->close (); + + // Finally close all the tabs and return indication that we can exit + // the application or close the editor. + // Closing and deleting the tabs makes the editor visible. In case it was + // hidden before, this state has to be restored afterwards. + bool vis = isVisible (); + + std::list editor_tab_lst = m_tab_widget->tab_list (); + for (auto editor_tab : editor_tab_lst) + editor_tab->deleteLater (); + + m_tab_widget->clear (); + + setVisible (vis); + } + + void file_editor::request_new_file (const QString& commands) + { + // Custom editor? If yes, we can only call the editor without passing + // some initial contents and even without being sure a new file is opened + if (call_custom_editor ()) return; - } - - QObject *saveFileObject = sender (); - QWidget *saveFileWidget = nullptr; - - for (int i = 0; i < m_tab_widget->count (); i++) - { - if (m_tab_widget->widget (i) == saveFileObject) - { - saveFileWidget = m_tab_widget->widget (i); - break; - } - } - if (! saveFileWidget) - { - // Create a NonModal message about error. - QMessageBox *msgBox - = new QMessageBox (QMessageBox::Critical, tr ("Octave Editor"), - tr ("The associated file editor tab has disappeared."), - QMessageBox::Ok, nullptr); - - msgBox->setWindowModality (Qt::NonModal); - msgBox->setAttribute (Qt::WA_DeleteOnClose); - msgBox->show (); - - return; - } - - // Can save without conflict, have the file editor tab do so. - emit fetab_save_file (saveFileWidget, saveFileName, remove_on_success); -} - -void file_editor::handle_insert_debugger_pointer_request (const QString& file, - int line) -{ - request_open_file (file, QString (), line, true); // default encoding -} - -void file_editor::handle_delete_debugger_pointer_request (const QString& file, - int line) -{ - if (! file.isEmpty ()) - { - // Check whether this file is already open in the editor. - file_editor_tab *tab = find_tab_widget (file); - - if (tab) - { - m_tab_widget->setCurrentWidget (tab); - - if (line > 0) - emit fetab_delete_debugger_pointer (tab, line); - - emit fetab_set_focus (tab); - } - } -} - -void file_editor::handle_update_breakpoint_marker_request (bool insert, - const QString& file, - int line, - const QString& cond) -{ - request_open_file (file, QString (), line, false, true, insert, cond); -} - -void file_editor::handle_edit_file_request (const QString& file) -{ - request_open_file (file); -} - -// Slot used for signals indicating that a file was changed/renamed or -// is going to be deleted/renamed -void file_editor::handle_file_remove (const QString& old_name, - const QString& new_name) -{ - // Clear old list of file data and declare a structure for file data - m_tmp_closed_files.clear (); - removed_file_data f_data; - - // Preprocessing old name(s) - QString old_name_clean = old_name.trimmed (); - int s = old_name_clean.size (); - - if (s > 1 && old_name_clean.at (0) == QChar ('\"') - && old_name_clean.at (s - 1) == QChar ('\"')) - old_name_clean = old_name_clean.mid (1, s - 2); - - QStringList old_names = old_name_clean.split ("\" \""); - - // Check if new name is a file or directory - QFileInfo newf (new_name); - bool new_is_dir = newf.isDir (); - - // Now loop over all old files/dirs (several files by movefile ()) - for (int i = 0; i < old_names.count (); i++) - { - // Check if old name is a file or directory - QFileInfo old (old_names.at (i)); - - if (old.isDir ()) - { - // Call the function which handles directories and return - handle_dir_remove (old_names.at (i), new_name); - } - else - { - // It is a single file. Is it open? - file_editor_tab *editor_tab = find_tab_widget (old_names.at (i)); - - if (editor_tab) - { - - editor_tab->enable_file_watcher (false); - - // For re-enabling tracking if error while removing/renaming - f_data.editor_tab = editor_tab; - // For renaming into new file (if new_file is not empty) - if (new_is_dir) - { - std::string ndir = new_name.toStdString (); - std::string ofile = old.fileName ().toStdString (); - f_data.new_file_name - = QString::fromStdString (sys::env::make_absolute (ofile, ndir)); - } - else - f_data.new_file_name = new_name; - - // Add file data to list - m_tmp_closed_files << f_data; - } - } - } -} - -// Slot for signal indicating that a file was renamed -void file_editor::handle_file_renamed (bool load_new) -{ - m_no_focus = true; // Remember for not focussing editor - - // Loop over all files that have to be handled. Start at the end of the - // list, otherwise the stored indexes are not correct. - for (int i = m_tmp_closed_files.count () - 1; i >= 0; i--) - { - if (load_new) - { - // Close file (remove) or rename into new file (rename) - if (m_tmp_closed_files.at (i).new_file_name.isEmpty ()) - m_tmp_closed_files.at (i).editor_tab->file_has_changed (QString (), true); - else - m_tmp_closed_files.at (i).editor_tab->set_file_name ( - m_tmp_closed_files.at (i).new_file_name); - } - else - { - // Something went wrong while renaming or removing: - // Leave everything as it is but reactivate tracking - m_tmp_closed_files.at (i).editor_tab->enable_file_watcher (true); - } - - } - - m_no_focus = false; // Back to normal focus - - // Clear the list of file data - m_tmp_closed_files.clear (); -} - -void file_editor::notice_settings (const gui_settings *settings) -{ - int size_idx = settings->value (global_icon_size).toInt (); - size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2 - - QStyle *st = style (); - int icon_size = st->pixelMetric (global_icon_sizes[size_idx]); - m_tool_bar->setIconSize (QSize (icon_size, icon_size)); - - // Tab position and rotation - QTabWidget::TabPosition pos - = static_cast (settings->value (ed_tab_position).toInt ()); - bool rotated = settings->value (ed_tabs_rotated).toBool (); - - m_tab_widget->setTabPosition (pos); - - if (rotated) - m_tab_widget->setTabsClosable (false); // No close buttons - // FIXME: close buttons can not be correctly placed in rotated tabs - - // Get the tab bar and set the rotation - int rotation = rotated; - if (pos == QTabWidget::West) - rotation = -rotation; - - tab_bar *bar = m_tab_widget->get_tab_bar (); - bar->set_rotated (rotation); - - // Get suitable height of a tab related to font and icon size - int height = 1.5*QFontMetrics (m_tab_widget->font ()).height (); - int is = 1.5*m_tab_widget->iconSize ().height (); - if (is > height) - height = is; - - // Calculate possibly limited width and set the elide mode - int chars = settings->value (ed_tabs_max_width).toInt (); - int width = 9999; - if (chars > 0) - width = chars * QFontMetrics (m_tab_widget->font ()).averageCharWidth (); - - // Get tab bar size properties for style sheet depending on rotation - QString width_str ("width"); - QString height_str ("height"); - if ((pos == QTabWidget::West) || (pos == QTabWidget::East)) - { - width_str = QString ("height"); - height_str = QString ("width"); - } - - QString style_sheet - = QString ("QTabBar::tab {max-" + height_str + ": %1px;\n" - "max-" + width_str + ": %2px; }") - .arg (height).arg (width); + + // New file isn't a file_editor_tab function since the file + // editor tab has yet to be created and there is no object to + // pass a signal to. Hence, functionality is here. + + file_editor_tab *fileEditorTab = make_file_editor_tab (m_ced); + add_file_editor_tab (fileEditorTab, ""); // new tab with empty title + fileEditorTab->new_file (commands); // title is updated here + activate (); // focus editor and new tab + } + + void file_editor::request_close_file (bool) + { + file_editor_tab *editor_tab + = static_cast (m_tab_widget->currentWidget ()); + editor_tab->conditional_close (); + } + + void file_editor::request_close_all_files (bool) + { + file_editor_tab *editor_tab; + + // loop over all tabs starting from last one otherwise deletion changes index + for (int index = m_tab_widget->count ()-1; index >= 0; index--) + { + editor_tab = static_cast (m_tab_widget->widget (index)); + editor_tab->conditional_close (); + } + } + + void file_editor::request_close_other_files (bool) + { + file_editor_tab *editor_tab; + QWidget *tabID = m_tab_widget->currentWidget (); + + // loop over all tabs starting from last one otherwise deletion changes index + for (int index = m_tab_widget->count ()-1; index >= 0; index--) + { + if (tabID != m_tab_widget->widget (index)) + { + editor_tab + = static_cast (m_tab_widget->widget (index)); + editor_tab->conditional_close (); + } + } + } + + void file_editor::copy_full_file_path (bool) + { + file_editor_tab *editor_tab + = static_cast (m_tab_widget->currentWidget ()); + + if (editor_tab) + QGuiApplication::clipboard ()->setText (editor_tab->file_name ()); + } + + // open a file from the mru list + void file_editor::request_mru_open_file (QAction *action) + { + if (action) + { + request_open_file (action->data ().toStringList ().at (0), + action->data ().toStringList ().at (1)); + } + } + + void file_editor::request_print_file (bool) + { + emit fetab_print_file (m_tab_widget->currentWidget ()); + } + + void file_editor::request_redo (bool) + { + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_REDO); + } + + void file_editor::request_cut (bool) + { + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_CUT); + } + + void file_editor::request_context_help (bool) + { + emit fetab_context_help (m_tab_widget->currentWidget (), false); + } + + void file_editor::request_context_doc (bool) + { + emit fetab_context_help (m_tab_widget->currentWidget (), true); + } + + void file_editor::request_context_edit (bool) + { + emit fetab_context_edit (m_tab_widget->currentWidget ()); + } + + void file_editor::request_save_file (bool) + { + emit fetab_save_file (m_tab_widget->currentWidget ()); + } + + void file_editor::request_save_file_as (bool) + { + emit fetab_save_file_as (m_tab_widget->currentWidget ()); + } + + void file_editor::request_run_file (bool) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + // Act as though this action was entered at the command propmt + // so that the interpreter will check for updated file time + // stamps. + Vlast_prompt_time.stamp (); + + tree_evaluator& tw = interp.get_evaluator (); + + if (tw.in_debug_repl ()) + emit request_dbcont_signal (); + else + emit fetab_run_file (m_tab_widget->currentWidget ()); + }); + } + + void file_editor::request_step_into_file () + { + emit fetab_run_file (m_tab_widget->currentWidget (), true); + } + + void file_editor::request_context_run (bool) + { + emit fetab_context_run (m_tab_widget->currentWidget ()); + } + + void file_editor::request_toggle_bookmark (bool) + { + emit fetab_toggle_bookmark (m_tab_widget->currentWidget ()); + } + + void file_editor::request_next_bookmark (bool) + { + emit fetab_next_bookmark (m_tab_widget->currentWidget ()); + } + + void file_editor::request_previous_bookmark (bool) + { + emit fetab_previous_bookmark (m_tab_widget->currentWidget ()); + } + + void file_editor::request_remove_bookmark (bool) + { + emit fetab_remove_bookmark (m_tab_widget->currentWidget ()); + } + + void file_editor::request_move_match_brace (bool) + { + emit fetab_move_match_brace (m_tab_widget->currentWidget (), false); + } + + void file_editor::request_sel_match_brace (bool) + { + emit fetab_move_match_brace (m_tab_widget->currentWidget (), true); + } + + // FIXME: What should this do with conditional breakpoints? + void file_editor::request_toggle_breakpoint (bool) + { + emit fetab_toggle_breakpoint (m_tab_widget->currentWidget ()); + } + + void file_editor::request_next_breakpoint (bool) + { + emit fetab_next_breakpoint (m_tab_widget->currentWidget ()); + } + + void file_editor::request_previous_breakpoint (bool) + { + emit fetab_previous_breakpoint (m_tab_widget->currentWidget ()); + } + + void file_editor::request_remove_breakpoint (bool) + { + emit fetab_remove_all_breakpoints (m_tab_widget->currentWidget ()); + } + + // slots for Edit->Commands actions + void file_editor::request_delete_start_word (bool) + { + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_DELWORDLEFT); + } + + void file_editor::request_delete_end_word (bool) + { + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_DELWORDRIGHT); + } + + void file_editor::request_delete_start_line (bool) + { + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_DELLINELEFT); + } + + void file_editor::request_delete_end_line (bool) + { + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_DELLINERIGHT); + } + + void file_editor::request_delete_line (bool) + { + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_LINEDELETE); + } + + void file_editor::request_copy_line (bool) + { + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_LINECOPY); + } + + void file_editor::request_cut_line (bool) + { + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_LINECUT); + } + + void file_editor::request_duplicate_selection (bool) + { + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_SELECTIONDUPLICATE); + } + + void file_editor::request_transpose_line (bool) + { + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_LINETRANSPOSE); + } + + void file_editor::request_comment_selected_text (bool) + { + emit fetab_comment_selected_text (m_tab_widget->currentWidget (), false); + } + + void file_editor::request_uncomment_selected_text (bool) + { + emit fetab_uncomment_selected_text (m_tab_widget->currentWidget ()); + } + + void file_editor::request_comment_var_selected_text (bool) + { + emit fetab_comment_selected_text (m_tab_widget->currentWidget (), true); + } + + // slots for Edit->Format actions + void file_editor::request_upper_case (bool) + { + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_UPPERCASE); + } + + void file_editor::request_lower_case (bool) + { + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_LOWERCASE); + } + + void file_editor::request_indent_selected_text (bool) + { + emit fetab_indent_selected_text (m_tab_widget->currentWidget ()); + } + + void file_editor::request_unindent_selected_text (bool) + { + emit fetab_unindent_selected_text (m_tab_widget->currentWidget ()); + } + + void file_editor::request_smart_indent_line_or_selected_text () + { + emit fetab_smart_indent_line_or_selected_text (m_tab_widget->currentWidget ()); + } + + void file_editor::request_conv_eol_windows (bool) + { + emit fetab_convert_eol (m_tab_widget->currentWidget (), + QsciScintilla::EolWindows); + } + void + file_editor::request_conv_eol_unix (bool) + { + emit fetab_convert_eol (m_tab_widget->currentWidget (), + QsciScintilla::EolUnix); + } + + void file_editor::request_conv_eol_mac (bool) + { + emit fetab_convert_eol (m_tab_widget->currentWidget (), + QsciScintilla::EolMac); + } + + // Slot for initially creating and showing the find dialog + void file_editor::request_find (bool) + { + // Create the dialog + find_create (); + + // Since find_create shows the dialog without activating the widget + // (which is reuqired in other cases) do this manually here + m_find_dialog->activateWindow (); + + // Initiate search text from possible selection and save the initial + // data from the dialog on the defined structure + m_find_dialog->init_search_text (); + } + + // This method creates the find dialog. + + void file_editor::find_create () + { + if (m_find_dialog) + m_find_dialog->close (); + + if (isFloating ()) + m_find_dialog = new find_dialog (this, this); + else + m_find_dialog = new find_dialog (this, parentWidget ()); + + // Add required actions + m_find_dialog->addAction (m_find_next_action); + m_find_dialog->addAction (m_find_previous_action); + + // Update edit area + file_editor_tab *fet + = static_cast (m_tab_widget->currentWidget ()); + m_find_dialog->update_edit_area (fet->qsci_edit_area ()); + + // Icon is the same as the editor + m_find_dialog->setWindowIcon (windowIcon ()); + + // Position: lower right of editor's position + int xp = x () + frameGeometry ().width (); + int yp = y () + frameGeometry ().height (); + + if (! isFloating ()) + { + // Fix position if editor is docked + + QWidget *parent = parentWidget (); + + if (parent) + { + xp = xp + parent->x (); + yp = yp + parent->y (); + } + } + + if (yp < 0) + yp = 0; + + // The size of the find dialog is considered in restore_settings + // since its size might change depending on the options + m_find_dialog->restore_settings (QPoint (xp, yp)); + + // Set visible + m_find_dialog->set_visible (true); + } + + void file_editor::request_find_next (bool) + { + if (m_find_dialog) + m_find_dialog->find_next (); + } + + void file_editor::request_find_previous (bool) + { + if (m_find_dialog) + m_find_dialog->find_prev (); + } + + void file_editor::request_goto_line (bool) + { + emit fetab_goto_line (m_tab_widget->currentWidget ()); + } + + void file_editor::request_completion (bool) + { + emit fetab_completion (m_tab_widget->currentWidget ()); + } + + void file_editor::handle_file_name_changed (const QString& fname, + const QString& tip, + bool modified) + { + QObject *fileEditorTab = sender (); + if (fileEditorTab) + { + gui_settings settings; + + for (int i = 0; i < m_tab_widget->count (); i++) + { + if (m_tab_widget->widget (i) == fileEditorTab) + { + m_tab_widget->setTabText (i, fname); + m_tab_widget->setTabToolTip (i, tip); + + m_save_action->setEnabled (modified); + m_current_tab_modified = modified; + + if (modified) + m_tab_widget->setTabIcon (i, settings.icon ("document-save")); + else + m_tab_widget->setTabIcon (i, QIcon ()); + } + } + } + } + + void file_editor::handle_tab_close_request (int index) + { + file_editor_tab *editor_tab + = static_cast (m_tab_widget->widget (index)); + editor_tab->conditional_close (); + } + + void + file_editor::handle_tab_remove_request (void) + { + QObject *fileEditorTab = sender (); + if (fileEditorTab) + { + for (int i = 0; i < m_tab_widget->count (); i++) + { + if (m_tab_widget->widget (i) == fileEditorTab) + { + m_tab_widget->removeTab (i); + + // Deleting the sender (even with deleteLater) seems a + // bit strange. Is there a better way? + fileEditorTab->deleteLater (); + break; + } + } + } + check_actions (); + + activate (); // focus stays in editor when tab is closed + + } + + // context menu of edit area + void file_editor::active_tab_changed (int index) + { + emit fetab_change_request (m_tab_widget->widget (index)); + activate (); + } + + void file_editor::handle_editor_state_changed (bool copy_available, + bool is_octave_file, + bool is_modified) + { + // In case there is some scenario where traffic could be coming from + // all the file editor tabs, just process info from the current active tab. + if (sender () == m_tab_widget->currentWidget ()) + { + m_save_action->setEnabled (is_modified); + m_current_tab_modified = is_modified; + + if (m_copy_action) + m_copy_action->setEnabled (copy_available); + + m_cut_action->setEnabled (copy_available); + + m_run_selection_action->setEnabled (copy_available); + m_run_action->setEnabled (is_octave_file); + m_is_octave_file = is_octave_file; + + emit editor_tabs_changed_signal (true, m_is_octave_file); + } + + m_copy_action_enabled = m_copy_action->isEnabled (); + m_undo_action_enabled = m_undo_action->isEnabled (); + } + + void file_editor::handle_mru_add_file (const QString& file_name, + const QString& encoding) + { + int index; + while ((index = m_mru_files.indexOf (file_name)) >= 0) + { + m_mru_files.removeAt (index); + m_mru_files_encodings.removeAt (index); + } + + m_mru_files.prepend (file_name); + m_mru_files_encodings.prepend (encoding); + + mru_menu_update (); + } + + void file_editor::check_conflict_save (const QString& saveFileName, + bool remove_on_success) + { + // Check whether this file is already open in the editor. + file_editor_tab *tab = find_tab_widget (saveFileName); + + if (tab) + { + // Note: to overwrite the contents of some other file editor tab + // with the same name requires identifying which file editor tab + // that is (not too difficult) then closing that tab. Of course, + // that could trigger another dialog box if the file editor tab + // with the same name has modifications in it. This could become + // somewhat confusing to the user. For now, opt to do nothing. + + // Create a NonModal message about error. + QMessageBox *msgBox + = new QMessageBox (QMessageBox::Critical, tr ("Octave Editor"), + tr ("File not saved! A file with the selected name\n%1\n" + "is already open in the editor"). + arg (saveFileName), + QMessageBox::Ok, nullptr); + + msgBox->setWindowModality (Qt::NonModal); + msgBox->setAttribute (Qt::WA_DeleteOnClose); + msgBox->show (); + + return; + } + + QObject *saveFileObject = sender (); + QWidget *saveFileWidget = nullptr; + + for (int i = 0; i < m_tab_widget->count (); i++) + { + if (m_tab_widget->widget (i) == saveFileObject) + { + saveFileWidget = m_tab_widget->widget (i); + break; + } + } + if (! saveFileWidget) + { + // Create a NonModal message about error. + QMessageBox *msgBox + = new QMessageBox (QMessageBox::Critical, tr ("Octave Editor"), + tr ("The associated file editor tab has disappeared."), + QMessageBox::Ok, nullptr); + + msgBox->setWindowModality (Qt::NonModal); + msgBox->setAttribute (Qt::WA_DeleteOnClose); + msgBox->show (); + + return; + } + + // Can save without conflict, have the file editor tab do so. + emit fetab_save_file (saveFileWidget, saveFileName, remove_on_success); + } + + void file_editor::handle_insert_debugger_pointer_request (const QString& file, + int line) + { + request_open_file (file, QString (), line, true); // default encoding + } + + void file_editor::handle_delete_debugger_pointer_request (const QString& file, + int line) + { + if (! file.isEmpty ()) + { + // Check whether this file is already open in the editor. + file_editor_tab *tab = find_tab_widget (file); + + if (tab) + { + m_tab_widget->setCurrentWidget (tab); + + if (line > 0) + emit fetab_delete_debugger_pointer (tab, line); + + emit fetab_set_focus (tab); + } + } + } + + void file_editor::handle_update_breakpoint_marker_request (bool insert, + const QString& file, + int line, + const QString& cond) + { + request_open_file (file, QString (), line, false, true, insert, cond); + } + + void file_editor::handle_edit_file_request (const QString& file) + { + request_open_file (file); + } + + // Slot used for signals indicating that a file was changed/renamed or + // is going to be deleted/renamed + void file_editor::handle_file_remove (const QString& old_name, + const QString& new_name) + { + // Clear old list of file data and declare a structure for file data + m_tmp_closed_files.clear (); + removed_file_data f_data; + + // Preprocessing old name(s) + QString old_name_clean = old_name.trimmed (); + int s = old_name_clean.size (); + + if (s > 1 && old_name_clean.at (0) == QChar ('\"') + && old_name_clean.at (s - 1) == QChar ('\"')) + old_name_clean = old_name_clean.mid (1, s - 2); + + QStringList old_names = old_name_clean.split ("\" \""); + + // Check if new name is a file or directory + QFileInfo newf (new_name); + bool new_is_dir = newf.isDir (); + + // Now loop over all old files/dirs (several files by movefile ()) + for (int i = 0; i < old_names.count (); i++) + { + // Check if old name is a file or directory + QFileInfo old (old_names.at (i)); + + if (old.isDir ()) + { + // Call the function which handles directories and return + handle_dir_remove (old_names.at (i), new_name); + } + else + { + // It is a single file. Is it open? + file_editor_tab *editor_tab = find_tab_widget (old_names.at (i)); + + if (editor_tab) + { + + editor_tab->enable_file_watcher (false); + + // For re-enabling tracking if error while removing/renaming + f_data.editor_tab = editor_tab; + // For renaming into new file (if new_file is not empty) + if (new_is_dir) + { + std::string ndir = new_name.toStdString (); + std::string ofile = old.fileName ().toStdString (); + f_data.new_file_name + = QString::fromStdString (sys::env::make_absolute (ofile, ndir)); + } + else + f_data.new_file_name = new_name; + + // Add file data to list + m_tmp_closed_files << f_data; + } + } + } + } + + // Slot for signal indicating that a file was renamed + void file_editor::handle_file_renamed (bool load_new) + { + m_no_focus = true; // Remember for not focussing editor + + // Loop over all files that have to be handled. Start at the end of the + // list, otherwise the stored indexes are not correct. + for (int i = m_tmp_closed_files.count () - 1; i >= 0; i--) + { + if (load_new) + { + // Close file (remove) or rename into new file (rename) + if (m_tmp_closed_files.at (i).new_file_name.isEmpty ()) + m_tmp_closed_files.at (i).editor_tab->file_has_changed (QString (), true); + else + m_tmp_closed_files.at (i).editor_tab->set_file_name ( + m_tmp_closed_files.at (i).new_file_name); + } + else + { + // Something went wrong while renaming or removing: + // Leave everything as it is but reactivate tracking + m_tmp_closed_files.at (i).editor_tab->enable_file_watcher (true); + } + + } + + m_no_focus = false; // Back to normal focus + + // Clear the list of file data + m_tmp_closed_files.clear (); + } + + void file_editor::notice_settings (void) + { + gui_settings settings; + + int size_idx = settings.value (global_icon_size).toInt (); + size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2 + + QStyle *st = style (); + int icon_size = st->pixelMetric (global_icon_sizes[size_idx]); + m_tool_bar->setIconSize (QSize (icon_size, icon_size)); + + // Tab position and rotation + QTabWidget::TabPosition pos + = static_cast (settings.value (ed_tab_position).toInt ()); + bool rotated = settings.value (ed_tabs_rotated).toBool (); + + m_tab_widget->setTabPosition (pos); + + if (rotated) + m_tab_widget->setTabsClosable (false); // No close buttons + // FIXME: close buttons can not be correctly placed in rotated tabs + + // Get the tab bar and set the rotation + int rotation = rotated; + if (pos == QTabWidget::West) + rotation = -rotation; + + tab_bar *bar = m_tab_widget->get_tab_bar (); + bar->set_rotated (rotation); + + // Get suitable height of a tab related to font and icon size + int height = 1.5*QFontMetrics (m_tab_widget->font ()).height (); + int is = 1.5*m_tab_widget->iconSize ().height (); + if (is > height) + height = is; + + // Calculate possibly limited width and set the elide mode + int chars = settings.value (ed_tabs_max_width).toInt (); + int width = 9999; + if (chars > 0) + width = chars * QFontMetrics (m_tab_widget->font ()).averageCharWidth (); + + // Get tab bar size properties for style sheet depending on rotation + QString width_str ("width"); + QString height_str ("height"); + if ((pos == QTabWidget::West) || (pos == QTabWidget::East)) + { + width_str = QString ("height"); + height_str = QString ("width"); + } + + QString style_sheet + = QString ("QTabBar::tab {max-" + height_str + ": %1px;\n" + "max-" + width_str + ": %2px; }") + .arg (height).arg (width); #if defined (Q_OS_MAC) - // FIXME: This is a workaround for missing tab close buttons on MacOS - // in several Qt versions (https://bugreports.qt.io/browse/QTBUG-61092) - if (! rotated) - { - QString icon = global_icon_paths.at (ICON_THEME_OCTAVE) + "widget-close.png"; - - QString close_button_css_mac ( - "QTabBar::close-button" - " { image: url(" + icon + ");" - " padding: 4px;" - " subcontrol-position: bottom; }\n" - "QTabBar::close-button:hover" - " { background-color: #cccccc; }"); - - style_sheet = style_sheet + close_button_css_mac; - } + // FIXME: This is a workaround for missing tab close buttons on MacOS + // in several Qt versions (https://bugreports.qt.io/browse/QTBUG-61092) + if (! rotated) + { + QString icon = global_icon_paths.at (ICON_THEME_OCTAVE) + "widget-close.png"; + + QString close_button_css_mac ( + "QTabBar::close-button" + " { image: url(" + icon + ");" + " padding: 4px;" + " subcontrol-position: bottom; }\n" + "QTabBar::close-button:hover" + " { background-color: #cccccc; }"); + + style_sheet = style_sheet + close_button_css_mac; + } #endif - m_tab_widget->setStyleSheet (style_sheet); - - bool show_it; - show_it = settings->value (ed_show_line_numbers).toBool (); - m_show_linenum_action->setChecked (show_it); - show_it = settings->value (ed_show_white_space).toBool (); - m_show_whitespace_action->setChecked (show_it); - show_it = settings->value (ed_show_eol_chars).toBool (); - m_show_eol_action->setChecked (show_it); - show_it = settings->value (ed_show_indent_guides).toBool (); - m_show_indguide_action->setChecked (show_it); - show_it = settings->value (ed_long_line_marker).toBool (); - m_show_longline_action->setChecked (show_it); - - show_it = settings->value (ed_show_toolbar).toBool (); - m_show_toolbar_action->setChecked (show_it); - m_tool_bar->setVisible (show_it); - show_it = settings->value (ed_show_edit_status_bar).toBool (); - m_show_statusbar_action->setChecked (show_it); - show_it = settings->value (ed_show_hscroll_bar).toBool (); - m_show_hscrollbar_action->setChecked (show_it); - - set_shortcuts (); - - // Find dialog with the same icon as the editor - if (m_find_dialog) - m_find_dialog->setWindowIcon (windowIcon ()); - - // Relay signal to file editor tabs. - emit fetab_settings_changed (settings); -} - -void file_editor::set_shortcuts (void) -{ - // Shortcuts also available in the main window, as well as the related - // shortcuts, are defined in main_window and added to the editor - - shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); - - // File menu - scmgr.set_shortcut (m_edit_function_action, sc_edit_file_edit_function); - scmgr.set_shortcut (m_save_action, sc_edit_file_save); - scmgr.set_shortcut (m_save_as_action, sc_edit_file_save_as); - scmgr.set_shortcut (m_close_action, sc_edit_file_close); - scmgr.set_shortcut (m_close_all_action, sc_edit_file_close_all); - scmgr.set_shortcut (m_close_others_action, sc_edit_file_close_other); - scmgr.set_shortcut (m_print_action, sc_edit_file_print); - - // Edit menu - scmgr.set_shortcut (m_redo_action, sc_edit_edit_redo); - scmgr.set_shortcut (m_cut_action, sc_edit_edit_cut); - scmgr.set_shortcut (m_find_action, sc_edit_edit_find_replace); - scmgr.set_shortcut (m_find_next_action, sc_edit_edit_find_next); - scmgr.set_shortcut (m_find_previous_action, sc_edit_edit_find_previous); - - scmgr.set_shortcut (m_delete_start_word_action, sc_edit_edit_delete_start_word); - scmgr.set_shortcut (m_delete_end_word_action, sc_edit_edit_delete_end_word); - scmgr.set_shortcut (m_delete_start_line_action, sc_edit_edit_delete_start_line); - scmgr.set_shortcut (m_delete_end_line_action, sc_edit_edit_delete_end_line); - scmgr.set_shortcut (m_delete_line_action, sc_edit_edit_delete_line); - scmgr.set_shortcut (m_copy_line_action, sc_edit_edit_copy_line); - scmgr.set_shortcut (m_cut_line_action, sc_edit_edit_cut_line); - scmgr.set_shortcut (m_duplicate_selection_action, sc_edit_edit_duplicate_selection); - scmgr.set_shortcut (m_transpose_line_action, sc_edit_edit_transpose_line); - scmgr.set_shortcut (m_comment_selection_action, sc_edit_edit_comment_selection); - scmgr.set_shortcut (m_uncomment_selection_action, sc_edit_edit_uncomment_selection); - scmgr.set_shortcut (m_comment_var_selection_action, sc_edit_edit_comment_var_selection); - - scmgr.set_shortcut (m_upper_case_action, sc_edit_edit_upper_case); - scmgr.set_shortcut (m_lower_case_action, sc_edit_edit_lower_case); - scmgr.set_shortcut (m_indent_selection_action, sc_edit_edit_indent_selection); - scmgr.set_shortcut (m_unindent_selection_action, sc_edit_edit_unindent_selection); - scmgr.set_shortcut (m_smart_indent_line_or_selection_action, sc_edit_edit_smart_indent_line_or_selection); - scmgr.set_shortcut (m_completion_action, sc_edit_edit_completion_list); - scmgr.set_shortcut (m_goto_line_action, sc_edit_edit_goto_line); - scmgr.set_shortcut (m_move_to_matching_brace, sc_edit_edit_move_to_brace); - scmgr.set_shortcut (m_sel_to_matching_brace, sc_edit_edit_select_to_brace); - scmgr.set_shortcut (m_toggle_bookmark_action, sc_edit_edit_toggle_bookmark); - scmgr.set_shortcut (m_next_bookmark_action, sc_edit_edit_next_bookmark); - scmgr.set_shortcut (m_previous_bookmark_action, sc_edit_edit_previous_bookmark); - scmgr.set_shortcut (m_remove_bookmark_action, sc_edit_edit_remove_bookmark); - scmgr.set_shortcut (m_preferences_action, sc_edit_edit_preferences); - scmgr.set_shortcut (m_styles_preferences_action, sc_edit_edit_styles_preferences); - - scmgr.set_shortcut (m_conv_eol_windows_action, sc_edit_edit_conv_eol_winows); - scmgr.set_shortcut (m_conv_eol_unix_action, sc_edit_edit_conv_eol_unix); - scmgr.set_shortcut (m_conv_eol_mac_action, sc_edit_edit_conv_eol_mac); - - // View menu - scmgr.set_shortcut (m_show_linenum_action, sc_edit_view_show_line_numbers); - scmgr.set_shortcut (m_show_whitespace_action, sc_edit_view_show_white_spaces); - scmgr.set_shortcut (m_show_eol_action, sc_edit_view_show_eol_chars); - scmgr.set_shortcut (m_show_indguide_action, sc_edit_view_show_ind_guides); - scmgr.set_shortcut (m_show_longline_action, sc_edit_view_show_long_line); - scmgr.set_shortcut (m_show_toolbar_action, sc_edit_view_show_toolbar); - scmgr.set_shortcut (m_show_statusbar_action, sc_edit_view_show_statusbar); - scmgr.set_shortcut (m_show_hscrollbar_action, sc_edit_view_show_hscrollbar); - scmgr.set_shortcut (m_zoom_in_action, sc_edit_view_zoom_in); - scmgr.set_shortcut (m_zoom_out_action, sc_edit_view_zoom_out); - scmgr.set_shortcut (m_zoom_normal_action, sc_edit_view_zoom_normal); - scmgr.set_shortcut (m_sort_tabs_action, sc_edit_view_sort_tabs); - - // Debug menu - scmgr.set_shortcut (m_toggle_breakpoint_action, sc_edit_debug_toggle_breakpoint); - scmgr.set_shortcut (m_next_breakpoint_action, sc_edit_debug_next_breakpoint); - scmgr.set_shortcut (m_previous_breakpoint_action, sc_edit_debug_previous_breakpoint); - scmgr.set_shortcut (m_remove_all_breakpoints_action, sc_edit_debug_remove_breakpoints); - - // Run menu - scmgr.set_shortcut (m_run_action, sc_edit_run_run_file); - scmgr.set_shortcut (m_run_selection_action, sc_edit_run_run_selection); - - // Help menu - scmgr.set_shortcut (m_context_help_action, sc_edit_help_help_keyword); - scmgr.set_shortcut (m_context_doc_action, sc_edit_help_doc_keyword); - - // Tab navigation without menu entries - scmgr.set_shortcut (m_switch_left_tab_action, sc_edit_tabs_switch_left_tab); - scmgr.set_shortcut (m_switch_right_tab_action, sc_edit_tabs_switch_right_tab); - scmgr.set_shortcut (m_move_tab_left_action, sc_edit_tabs_move_tab_left); - scmgr.set_shortcut (m_move_tab_right_action, sc_edit_tabs_move_tab_right); - -} - -// This slot is a reimplementation of the virtual slot in octave_dock_widget. -// We need this for creating an empty script when the editor has no open -// files and is made visible. -void file_editor::handle_visibility (bool visible) -{ - octave_dock_widget::handle_visibility (visible); - - if (! m_editor_ready) - return; - - if (m_closed && visible) - { - m_closed = false; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - restore_session (settings); - } - - empty_script (false, visible); -} - -// This slot is a reimplementation of the virtual slot in octave_dock_widget. -// We need this for updating the parent of the find dialog -void file_editor::toplevel_change (bool) -{ - if (m_find_dialog) - { - // close current dialog - m_find_dialog->close (); - - // re-create dialog with the new parent (editor or main-win) - find_create (); - m_find_dialog->activateWindow (); - } -} - -void file_editor::update_octave_directory (const QString& dir) -{ - m_ced = dir; - emit fetab_set_directory (m_ced); // for save dialog -} - -void file_editor::copyClipboard (void) -{ - if (editor_tab_has_focus ()) - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_COPY); -} - -void file_editor::pasteClipboard (void) -{ - if (editor_tab_has_focus ()) - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_PASTE); -} - -void file_editor::selectAll (void) -{ - if (editor_tab_has_focus ()) - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_SELECTALL); -} - -void file_editor::do_undo (void) -{ - if (editor_tab_has_focus ()) - emit fetab_scintilla_command (m_tab_widget->currentWidget (), - QsciScintillaBase::SCI_UNDO); -} - -// Open a file, if not already open, and mark the current execution location -// and/or a breakpoint with condition cond. -void file_editor::request_open_file (const QString& openFileName, - const QString& encoding, - int line, bool debug_pointer, - bool breakpoint_marker, bool insert, - const QString& cond, int index, - const QString& bookmarks) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (settings->value (global_use_custom_editor).toBool ()) - { - // Custom editor - if (debug_pointer || breakpoint_marker) - return; // Do not call custom editor during debugging - - if (call_custom_editor (openFileName, line)) - return; // Custom editor called - } - - bool show_dbg_file - = settings->value (ed_show_dbg_file).toBool (); - - if (openFileName.isEmpty ()) - { - // This happens if edit is called without an argument - // Open editor with empty edit area instead (as new file would do) - request_new_file (""); - } - else - { - // Check whether this file is already open in the editor. - file_editor_tab *tab = find_tab_widget (openFileName); - - if (tab) - { - m_tab_widget->setCurrentWidget (tab); - - if (line > 0) - { - if (insert) - emit fetab_goto_line (tab, line); - - if (debug_pointer) - emit fetab_insert_debugger_pointer (tab, line); - - if (breakpoint_marker) - emit fetab_do_breakpoint_marker (insert, tab, line, cond); - } - - if (show_dbg_file && ! ((breakpoint_marker || debug_pointer) - && is_editor_console_tabbed ())) - { - emit fetab_set_focus (tab); - activate (); - } - } - else - { - if (! show_dbg_file && (breakpoint_marker || debug_pointer)) - return; // Do not open a file for showing dbg markers - - if (breakpoint_marker && ! insert) - return; // Never open a file when removing breakpoints - - file_editor_tab *fileEditorTab = nullptr; - // Reuse tab if it hasn't yet been modified. - bool reusing = false; - tab = find_tab_widget (""); - if (tab) - { - fileEditorTab = tab; - if (fileEditorTab->qsci_edit_area ()->isModified ()) + m_tab_widget->setStyleSheet (style_sheet); + + bool show_it; + show_it = settings.value (ed_show_line_numbers).toBool (); + m_show_linenum_action->setChecked (show_it); + show_it = settings.value (ed_show_white_space).toBool (); + m_show_whitespace_action->setChecked (show_it); + show_it = settings.value (ed_show_eol_chars).toBool (); + m_show_eol_action->setChecked (show_it); + show_it = settings.value (ed_show_indent_guides).toBool (); + m_show_indguide_action->setChecked (show_it); + show_it = settings.value (ed_long_line_marker).toBool (); + m_show_longline_action->setChecked (show_it); + + show_it = settings.value (ed_show_toolbar).toBool (); + m_show_toolbar_action->setChecked (show_it); + m_tool_bar->setVisible (show_it); + show_it = settings.value (ed_show_edit_status_bar).toBool (); + m_show_statusbar_action->setChecked (show_it); + show_it = settings.value (ed_show_hscroll_bar).toBool (); + m_show_hscrollbar_action->setChecked (show_it); + + set_shortcuts (); + + // Find dialog with the same icon as the editor + if (m_find_dialog) + m_find_dialog->setWindowIcon (windowIcon ()); + + // Relay signal to file editor tabs. + emit fetab_settings_changed (); + } + + void file_editor::set_shortcuts (void) + { + // Shortcuts also available in the main window, as well as the related + // shortcuts, are defined in main_window and added to the editor + + shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); + + // File menu + scmgr.set_shortcut (m_edit_function_action, sc_edit_file_edit_function); + scmgr.set_shortcut (m_save_action, sc_edit_file_save); + scmgr.set_shortcut (m_save_as_action, sc_edit_file_save_as); + scmgr.set_shortcut (m_close_action, sc_edit_file_close); + scmgr.set_shortcut (m_close_all_action, sc_edit_file_close_all); + scmgr.set_shortcut (m_close_others_action, sc_edit_file_close_other); + scmgr.set_shortcut (m_print_action, sc_edit_file_print); + + // Edit menu + scmgr.set_shortcut (m_redo_action, sc_edit_edit_redo); + scmgr.set_shortcut (m_cut_action, sc_edit_edit_cut); + scmgr.set_shortcut (m_find_action, sc_edit_edit_find_replace); + scmgr.set_shortcut (m_find_next_action, sc_edit_edit_find_next); + scmgr.set_shortcut (m_find_previous_action, sc_edit_edit_find_previous); + + scmgr.set_shortcut (m_delete_start_word_action, sc_edit_edit_delete_start_word); + scmgr.set_shortcut (m_delete_end_word_action, sc_edit_edit_delete_end_word); + scmgr.set_shortcut (m_delete_start_line_action, sc_edit_edit_delete_start_line); + scmgr.set_shortcut (m_delete_end_line_action, sc_edit_edit_delete_end_line); + scmgr.set_shortcut (m_delete_line_action, sc_edit_edit_delete_line); + scmgr.set_shortcut (m_copy_line_action, sc_edit_edit_copy_line); + scmgr.set_shortcut (m_cut_line_action, sc_edit_edit_cut_line); + scmgr.set_shortcut (m_duplicate_selection_action, sc_edit_edit_duplicate_selection); + scmgr.set_shortcut (m_transpose_line_action, sc_edit_edit_transpose_line); + scmgr.set_shortcut (m_comment_selection_action, sc_edit_edit_comment_selection); + scmgr.set_shortcut (m_uncomment_selection_action, sc_edit_edit_uncomment_selection); + scmgr.set_shortcut (m_comment_var_selection_action, sc_edit_edit_comment_var_selection); + + scmgr.set_shortcut (m_upper_case_action, sc_edit_edit_upper_case); + scmgr.set_shortcut (m_lower_case_action, sc_edit_edit_lower_case); + scmgr.set_shortcut (m_indent_selection_action, sc_edit_edit_indent_selection); + scmgr.set_shortcut (m_unindent_selection_action, sc_edit_edit_unindent_selection); + scmgr.set_shortcut (m_smart_indent_line_or_selection_action, sc_edit_edit_smart_indent_line_or_selection); + scmgr.set_shortcut (m_completion_action, sc_edit_edit_completion_list); + scmgr.set_shortcut (m_goto_line_action, sc_edit_edit_goto_line); + scmgr.set_shortcut (m_move_to_matching_brace, sc_edit_edit_move_to_brace); + scmgr.set_shortcut (m_sel_to_matching_brace, sc_edit_edit_select_to_brace); + scmgr.set_shortcut (m_toggle_bookmark_action, sc_edit_edit_toggle_bookmark); + scmgr.set_shortcut (m_next_bookmark_action, sc_edit_edit_next_bookmark); + scmgr.set_shortcut (m_previous_bookmark_action, sc_edit_edit_previous_bookmark); + scmgr.set_shortcut (m_remove_bookmark_action, sc_edit_edit_remove_bookmark); + scmgr.set_shortcut (m_preferences_action, sc_edit_edit_preferences); + scmgr.set_shortcut (m_styles_preferences_action, sc_edit_edit_styles_preferences); + + scmgr.set_shortcut (m_conv_eol_windows_action, sc_edit_edit_conv_eol_winows); + scmgr.set_shortcut (m_conv_eol_unix_action, sc_edit_edit_conv_eol_unix); + scmgr.set_shortcut (m_conv_eol_mac_action, sc_edit_edit_conv_eol_mac); + + // View menu + scmgr.set_shortcut (m_show_linenum_action, sc_edit_view_show_line_numbers); + scmgr.set_shortcut (m_show_whitespace_action, sc_edit_view_show_white_spaces); + scmgr.set_shortcut (m_show_eol_action, sc_edit_view_show_eol_chars); + scmgr.set_shortcut (m_show_indguide_action, sc_edit_view_show_ind_guides); + scmgr.set_shortcut (m_show_longline_action, sc_edit_view_show_long_line); + scmgr.set_shortcut (m_show_toolbar_action, sc_edit_view_show_toolbar); + scmgr.set_shortcut (m_show_statusbar_action, sc_edit_view_show_statusbar); + scmgr.set_shortcut (m_show_hscrollbar_action, sc_edit_view_show_hscrollbar); + scmgr.set_shortcut (m_zoom_in_action, sc_edit_view_zoom_in); + scmgr.set_shortcut (m_zoom_out_action, sc_edit_view_zoom_out); + scmgr.set_shortcut (m_zoom_normal_action, sc_edit_view_zoom_normal); + scmgr.set_shortcut (m_sort_tabs_action, sc_edit_view_sort_tabs); + + // Debug menu + scmgr.set_shortcut (m_toggle_breakpoint_action, sc_edit_debug_toggle_breakpoint); + scmgr.set_shortcut (m_next_breakpoint_action, sc_edit_debug_next_breakpoint); + scmgr.set_shortcut (m_previous_breakpoint_action, sc_edit_debug_previous_breakpoint); + scmgr.set_shortcut (m_remove_all_breakpoints_action, sc_edit_debug_remove_breakpoints); + + // Run menu + scmgr.set_shortcut (m_run_action, sc_edit_run_run_file); + scmgr.set_shortcut (m_run_selection_action, sc_edit_run_run_selection); + + // Help menu + scmgr.set_shortcut (m_context_help_action, sc_edit_help_help_keyword); + scmgr.set_shortcut (m_context_doc_action, sc_edit_help_doc_keyword); + + // Tab navigation without menu entries + scmgr.set_shortcut (m_switch_left_tab_action, sc_edit_tabs_switch_left_tab); + scmgr.set_shortcut (m_switch_right_tab_action, sc_edit_tabs_switch_right_tab); + scmgr.set_shortcut (m_move_tab_left_action, sc_edit_tabs_move_tab_left); + scmgr.set_shortcut (m_move_tab_right_action, sc_edit_tabs_move_tab_right); + + } + + // This slot is a reimplementation of the virtual slot in octave_dock_widget. + // We need this for creating an empty script when the editor has no open + // files and is made visible. + void file_editor::handle_visibility (bool visible) + { + octave_dock_widget::handle_visibility (visible); + + if (! m_editor_ready) + return; + + if (m_closed && visible) + { + m_closed = false; + + restore_session (); + } + + empty_script (false, visible); + } + + // This slot is a reimplementation of the virtual slot in octave_dock_widget. + // We need this for updating the parent of the find dialog + void file_editor::toplevel_change (bool) + { + if (m_find_dialog) + { + // close current dialog + m_find_dialog->close (); + + // re-create dialog with the new parent (editor or main-win) + find_create (); + m_find_dialog->activateWindow (); + } + } + + void file_editor::update_octave_directory (const QString& dir) + { + m_ced = dir; + emit fetab_set_directory (m_ced); // for save dialog + } + + void file_editor::copyClipboard (void) + { + if (editor_tab_has_focus ()) + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_COPY); + } + + void file_editor::pasteClipboard (void) + { + if (editor_tab_has_focus ()) + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_PASTE); + } + + void file_editor::selectAll (void) + { + if (editor_tab_has_focus ()) + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_SELECTALL); + } + + void file_editor::do_undo (void) + { + if (editor_tab_has_focus ()) + emit fetab_scintilla_command (m_tab_widget->currentWidget (), + QsciScintillaBase::SCI_UNDO); + } + + // Open a file, if not already open, and mark the current execution location + // and/or a breakpoint with condition cond. + void file_editor::request_open_file (const QString& openFileName, + const QString& encoding, + int line, bool debug_pointer, + bool breakpoint_marker, bool insert, + const QString& cond, int index, + const QString& bookmarks) + { + gui_settings settings; + + if (settings.value (global_use_custom_editor).toBool ()) + { + // Custom editor + if (debug_pointer || breakpoint_marker) + return; // Do not call custom editor during debugging + + if (call_custom_editor (openFileName, line)) + return; // Custom editor called + } + + bool show_dbg_file = settings.value (ed_show_dbg_file).toBool (); + + if (openFileName.isEmpty ()) + { + // This happens if edit is called without an argument + // Open editor with empty edit area instead (as new file would do) + request_new_file (""); + } + else + { + // Check whether this file is already open in the editor. + file_editor_tab *tab = find_tab_widget (openFileName); + + if (tab) + { + m_tab_widget->setCurrentWidget (tab); + + if (line > 0) + { + if (insert) + emit fetab_goto_line (tab, line); + + if (debug_pointer) + emit fetab_insert_debugger_pointer (tab, line); + + if (breakpoint_marker) + emit fetab_do_breakpoint_marker (insert, tab, line, cond); + } + + if (show_dbg_file && ! ((breakpoint_marker || debug_pointer) + && is_editor_console_tabbed ())) + { + emit fetab_set_focus (tab); + activate (); + } + } + else + { + if (! show_dbg_file && (breakpoint_marker || debug_pointer)) + return; // Do not open a file for showing dbg markers + + if (breakpoint_marker && ! insert) + return; // Never open a file when removing breakpoints + + file_editor_tab *fileEditorTab = nullptr; + // Reuse tab if it hasn't yet been modified. + bool reusing = false; + tab = find_tab_widget (""); + if (tab) + { + fileEditorTab = tab; + if (fileEditorTab->qsci_edit_area ()->isModified ()) + fileEditorTab = nullptr; + else + reusing = true; + } + + // If was absent or modified, create a new tab. + if (! fileEditorTab) + fileEditorTab = make_file_editor_tab (); + + fileEditorTab->set_encoding (encoding); + QString result = fileEditorTab->load_file (openFileName); + if (result == "") + { + // Supply empty title then have the file_editor_tab update + // with full or short name. + if (! reusing) + add_file_editor_tab (fileEditorTab, "", index); + fileEditorTab->update_window_title (false); + // file already loaded, add file to mru list here + QFileInfo file_info = QFileInfo (openFileName); + handle_mru_add_file (file_info.canonicalFilePath (), + encoding); + + if (line > 0) + { + if (insert) + emit fetab_goto_line (fileEditorTab, line); + + if (debug_pointer) + emit fetab_insert_debugger_pointer (fileEditorTab, + line); + if (breakpoint_marker) + emit fetab_do_breakpoint_marker (insert, fileEditorTab, + line, cond); + } + } + else + { + delete fileEditorTab; fileEditorTab = nullptr; - else - reusing = true; - } - - // If was absent or modified, create a new tab. - if (! fileEditorTab) - fileEditorTab = make_file_editor_tab (); - - fileEditorTab->set_encoding (encoding); - QString result = fileEditorTab->load_file (openFileName); - if (result == "") - { - // Supply empty title then have the file_editor_tab update - // with full or short name. - if (! reusing) - add_file_editor_tab (fileEditorTab, "", index); - fileEditorTab->update_window_title (false); - // file already loaded, add file to mru list here - QFileInfo file_info = QFileInfo (openFileName); - handle_mru_add_file (file_info.canonicalFilePath (), - encoding); - - if (line > 0) - { - if (insert) - emit fetab_goto_line (fileEditorTab, line); - - if (debug_pointer) - emit fetab_insert_debugger_pointer (fileEditorTab, - line); - if (breakpoint_marker) - emit fetab_do_breakpoint_marker (insert, fileEditorTab, - line, cond); - } - } - else - { - delete fileEditorTab; - fileEditorTab = nullptr; - - if (QFile::exists (openFileName)) - { - // File not readable: - // create a NonModal message about error. - QMessageBox *msgBox - = new QMessageBox (QMessageBox::Critical, - tr ("Octave Editor"), - tr ("Could not open file\n%1\nfor read: %2."). - arg (openFileName).arg (result), - QMessageBox::Ok, this); - - msgBox->setWindowModality (Qt::NonModal); - msgBox->setAttribute (Qt::WA_DeleteOnClose); - msgBox->show (); - } - else - { - // File does not exist, should it be created? - bool create_file = true; - QMessageBox *msgBox; - - if (! settings->value (ed_create_new_file).toBool ()) - { - msgBox = new QMessageBox (QMessageBox::Question, - tr ("Octave Editor"), - tr ("File\n%1\ndoes not exist. " - "Do you want to create it?").arg (openFileName), - QMessageBox::NoButton, nullptr); - QPushButton *create_button = - msgBox->addButton (tr ("Create"), QMessageBox::YesRole); - msgBox->addButton (tr ("Cancel"), QMessageBox::RejectRole); - msgBox->setDefaultButton (create_button); - msgBox->exec (); - - QAbstractButton *clicked_button = msgBox->clickedButton (); - if (clicked_button != create_button) - create_file = false; - - delete msgBox; - } - - if (create_file) - { - // create the file and call the editor again - QFile file (openFileName); - if (! file.open (QIODevice::WriteOnly)) - { - // error opening the file - msgBox = new QMessageBox (QMessageBox::Critical, - tr ("Octave Editor"), - tr ("Could not open file\n%1\nfor write: %2."). - arg (openFileName).arg (file.errorString ()), - QMessageBox::Ok, this); - - msgBox->setWindowModality (Qt::NonModal); - msgBox->setAttribute (Qt::WA_DeleteOnClose); - msgBox->show (); - } - else - { - file.close (); - request_open_file (openFileName); - } - } - } - } - - if (! bookmarks.isEmpty ()) - { - // Restore bookmarks - for (const auto& bms : bookmarks.split (',')) - { - int bm = bms.toInt (); - if (fileEditorTab) - fileEditorTab->qsci_edit_area ()->markerAdd (bm, marker::bookmark); - } - } - - if (! ((breakpoint_marker || debug_pointer) && is_editor_console_tabbed ())) - { - // update breakpoint pointers, really show editor - // and the current editor tab - if (fileEditorTab) - fileEditorTab->update_breakpoints (); - activate (); - emit file_loaded_signal (); - } - } - } -} - -void file_editor::request_preferences (bool) -{ - emit request_settings_dialog ("editor"); -} - -void file_editor::request_styles_preferences (bool) -{ - emit request_settings_dialog ("editor_styles"); -} - -void file_editor::show_line_numbers (bool) -{ - toggle_preference (ed_show_line_numbers); -} - -void file_editor::show_white_space (bool) -{ - toggle_preference (ed_show_white_space); -} - -void file_editor::show_eol_chars (bool) -{ - toggle_preference (ed_show_eol_chars); -} - -void file_editor::show_indent_guides (bool) -{ - toggle_preference (ed_show_indent_guides); -} - -void file_editor::show_long_line (bool) -{ - toggle_preference (ed_long_line_marker); -} - -void file_editor::show_toolbar (bool) -{ - toggle_preference (ed_show_toolbar); -} - -void file_editor::show_statusbar (bool) -{ - toggle_preference (ed_show_edit_status_bar); -} - -void file_editor::show_hscrollbar (bool) -{ - toggle_preference (ed_show_hscroll_bar); -} - -void file_editor::zoom_in (bool) -{ - emit fetab_zoom_in (m_tab_widget->currentWidget ()); -} - -void file_editor::zoom_out (bool) -{ - emit fetab_zoom_out (m_tab_widget->currentWidget ()); -} - -void file_editor::zoom_normal (bool) -{ - emit fetab_zoom_normal (m_tab_widget->currentWidget ()); -} - -void file_editor::create_context_menu (QMenu *menu) -{ - // remove all standard actions from scintilla - QList all_actions = menu->actions (); - - for (auto *a : all_actions) - menu->removeAction (a); - - // add editor's actions with icons and customized shortcuts - menu->addAction (m_cut_action); - menu->addAction (m_copy_action); - menu->addAction (m_paste_action); - menu->addSeparator (); - menu->addAction (m_selectall_action); - menu->addSeparator (); - menu->addAction (m_find_files_action); - menu->addAction (m_find_action); - menu->addAction (m_find_next_action); - menu->addAction (m_find_previous_action); - menu->addSeparator (); - menu->addMenu (m_edit_cmd_menu); - menu->addMenu (m_edit_fmt_menu); - menu->addMenu (m_edit_nav_menu); - menu->addSeparator (); - menu->addAction (m_run_selection_action); -} - -void file_editor::edit_status_update (bool undo, bool redo) -{ - if (m_undo_action) - m_undo_action->setEnabled (undo); - m_redo_action->setEnabled (redo); -} - -// handler for the close event -void file_editor::closeEvent (QCloseEvent *e) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (settings->value (ed_hiding_closes_files).toBool ()) - { - if (check_closing ()) - { - // All tabs are closed without cancelling, - // store closing state for restoring session when shown again. - // Editor is closing when session data is stored in preferences - m_closed = true; - e->ignore (); - } - else - { - e->ignore (); - return; - } - } - else - e->accept (); - - octave_dock_widget::closeEvent (e); -} - -void file_editor::dragEnterEvent (QDragEnterEvent *e) -{ - if (e->mimeData ()->hasUrls ()) - { - e->acceptProposedAction (); - } -} - -void file_editor::dropEvent (QDropEvent *e) -{ - if (e->mimeData ()->hasUrls ()) - { - for (const auto& url : e->mimeData ()->urls ()) - request_open_file (url.toLocalFile ()); - } -} - -bool file_editor::is_editor_console_tabbed (void) -{ - // FIXME: is there a way to do this job that doesn't require casting - // the parent to a main_window object? - - main_window *w = dynamic_cast (parentWidget ()); - - if (w) - { - QList w_list = w->tabifiedDockWidgets (this); - QDockWidget *console = - static_cast (w->get_dock_widget_list ().at (0)); - - for (int i = 0; i < w_list.count (); i++) - { - if (w_list.at (i) == console) - return true; - } - } - - return false; -} - -void file_editor::construct (void) -{ - QWidget *editor_widget = new QWidget (this); - - // FIXME: what was the intended purpose of this unused variable? - // QStyle *editor_style = QApplication::style (); - - // Menu bar: do not set it native, required in macOS and Ubuntu Unity (Qt5) - // for a visible menu bar in the editor widget. This property is ignored - // on other platforms. - m_menu_bar = new QMenuBar (editor_widget); - m_menu_bar->setNativeMenuBar (false); - - m_tool_bar = new QToolBar (editor_widget); - m_tool_bar->setMovable (true); - - m_tab_widget = new file_editor_tab_widget (editor_widget, this); - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - - // the mru-list and an empty array of actions - gui_settings *settings = rmgr.get_settings (); - m_mru_files = settings->value (ed_mru_file_list).toStringList (); - m_mru_files_encodings = settings->value (ed_mru_file_encodings) - .toStringList (); - - if (m_mru_files_encodings.count () != m_mru_files.count ()) - { - // encodings don't have the same count -> do not use them! - m_mru_files_encodings = QStringList (); - for (int i = 0; i < m_mru_files.count (); i++) - m_mru_files_encodings << QString (); - } - - for (int i = 0; i < MaxMRUFiles; ++i) - { - m_mru_file_actions[i] = new QAction (this); - m_mru_file_actions[i]->setVisible (false); - } - - // menu bar - - // file menu - - m_fileMenu = add_menu (m_menu_bar, tr ("&File")); - - // new and open menus are inserted later by the main window - m_mru_file_menu = new QMenu (tr ("&Recent Editor Files"), m_fileMenu); - for (int i = 0; i < MaxMRUFiles; ++i) - m_mru_file_menu->addAction (m_mru_file_actions[i]); - m_fileMenu->addMenu (m_mru_file_menu); - - m_fileMenu->addSeparator (); - - m_edit_function_action - = add_action (m_fileMenu, - tr ("&Edit Function"), - SLOT (request_context_edit (bool))); - - m_fileMenu->addSeparator (); - - m_save_action - = add_action (m_fileMenu, rmgr.icon ("document-save"), - tr ("&Save File"), SLOT (request_save_file (bool))); - - m_save_as_action - = add_action (m_fileMenu, rmgr.icon ("document-save-as"), - tr ("Save File &As..."), - SLOT (request_save_file_as (bool))); - - m_fileMenu->addSeparator (); - - m_close_action - = add_action (m_fileMenu, rmgr.icon ("window-close", false), - tr ("&Close"), SLOT (request_close_file (bool))); - - m_close_all_action - = add_action (m_fileMenu, rmgr.icon ("window-close", false), - tr ("Close All"), SLOT (request_close_all_files (bool))); - - m_close_others_action - = add_action (m_fileMenu, rmgr.icon ("window-close", false), - tr ("Close Other Files"), - SLOT (request_close_other_files (bool))); - - m_fileMenu->addSeparator (); - - m_print_action - = add_action (m_fileMenu, rmgr.icon ("document-print"), - tr ("Print..."), SLOT (request_print_file (bool))); - - // edit menu (undo, copy, paste and select all later via main window) - - m_edit_menu = add_menu (m_menu_bar, tr ("&Edit")); - - m_redo_action - = add_action (m_edit_menu, rmgr.icon ("edit-redo"), - tr ("&Redo"), SLOT (request_redo (bool))); - m_redo_action->setEnabled (false); - - m_edit_menu->addSeparator (); - - m_cut_action - = add_action (m_edit_menu, rmgr.icon ("edit-cut"), - tr ("Cu&t"), SLOT (request_cut (bool))); - m_cut_action->setEnabled (false); - - m_find_action - = add_action (m_edit_menu, rmgr.icon ("edit-find-replace"), - tr ("&Find and Replace..."), SLOT (request_find (bool))); - - m_find_next_action - = add_action (m_edit_menu, tr ("Find &Next..."), - SLOT (request_find_next (bool))); - - m_find_previous_action - = add_action (m_edit_menu, tr ("Find &Previous..."), - SLOT (request_find_previous (bool))); - - m_edit_menu->addSeparator (); - - m_edit_cmd_menu = m_edit_menu->addMenu (tr ("&Commands")); - - m_delete_line_action - = add_action (m_edit_cmd_menu, tr ("Delete Line"), - SLOT (request_delete_line (bool))); - - m_copy_line_action - = add_action (m_edit_cmd_menu, tr ("Copy Line"), - SLOT (request_copy_line (bool))); - - m_cut_line_action - = add_action (m_edit_cmd_menu, tr ("Cut Line"), - SLOT (request_cut_line (bool))); - - m_edit_cmd_menu->addSeparator (); - - m_delete_start_word_action - = add_action (m_edit_cmd_menu, tr ("Delete to Start of Word"), - SLOT (request_delete_start_word (bool))); - - m_delete_end_word_action - = add_action (m_edit_cmd_menu, tr ("Delete to End of Word"), - SLOT (request_delete_end_word (bool))); - - m_delete_start_line_action - = add_action (m_edit_cmd_menu, tr ("Delete to Start of Line"), - SLOT (request_delete_start_line (bool))); - - m_delete_end_line_action - = add_action (m_edit_cmd_menu, tr ("Delete to End of Line"), - SLOT (request_delete_end_line (bool))); - - m_edit_cmd_menu->addSeparator (); - - m_duplicate_selection_action - = add_action (m_edit_cmd_menu, tr ("Duplicate Selection/Line"), - SLOT (request_duplicate_selection (bool))); - - m_transpose_line_action - = add_action (m_edit_cmd_menu, tr ("Transpose Line"), - SLOT (request_transpose_line (bool))); - - m_edit_cmd_menu->addSeparator (); - - m_completion_action - = add_action (m_edit_cmd_menu, tr ("&Show Completion List"), - SLOT (request_completion (bool))); - - m_edit_fmt_menu = m_edit_menu->addMenu (tr ("&Format")); - - m_upper_case_action - = add_action (m_edit_fmt_menu, tr ("&Uppercase Selection"), - SLOT (request_upper_case (bool))); - - m_lower_case_action - = add_action (m_edit_fmt_menu, tr ("&Lowercase Selection"), - SLOT (request_lower_case (bool))); - - m_edit_fmt_menu->addSeparator (); - - m_comment_selection_action - = add_action (m_edit_fmt_menu, tr ("&Comment"), - SLOT (request_comment_selected_text (bool))); - - m_uncomment_selection_action - = add_action (m_edit_fmt_menu, tr ("&Uncomment"), - SLOT (request_uncomment_selected_text (bool))); - - m_comment_var_selection_action - = add_action (m_edit_fmt_menu, tr ("Comment (Choosing String)"), - SLOT (request_comment_var_selected_text (bool))); - - m_edit_fmt_menu->addSeparator (); - - m_indent_selection_action - = add_action (m_edit_fmt_menu, tr ("&Indent Selection Rigidly"), - SLOT (request_indent_selected_text (bool))); - - m_unindent_selection_action - = add_action (m_edit_fmt_menu, tr ("&Unindent Selection Rigidly"), - SLOT (request_unindent_selected_text (bool))); - - m_smart_indent_line_or_selection_action - = add_action (m_edit_fmt_menu, tr ("Indent Code"), - SLOT (request_smart_indent_line_or_selected_text (void))); - - m_edit_fmt_menu->addSeparator (); - - m_conv_eol_windows_action - = add_action (m_edit_fmt_menu, - tr ("Convert Line Endings to &Windows (CRLF)"), - SLOT (request_conv_eol_windows (bool))); - - m_conv_eol_unix_action - = add_action (m_edit_fmt_menu, tr ("Convert Line Endings to &Unix (LF)"), - SLOT (request_conv_eol_unix (bool))); - - m_conv_eol_mac_action - = add_action (m_edit_fmt_menu, - tr ("Convert Line Endings to Legacy &Mac (CR)"), - SLOT (request_conv_eol_mac (bool))); - - m_edit_nav_menu = m_edit_menu->addMenu (tr ("Navi&gation")); - - m_goto_line_action - = add_action (m_edit_nav_menu, tr ("Go &to Line..."), - SLOT (request_goto_line (bool))); - - m_edit_cmd_menu->addSeparator (); - - m_move_to_matching_brace - = add_action (m_edit_nav_menu, tr ("Move to Matching Brace"), - SLOT (request_move_match_brace (bool))); - - m_sel_to_matching_brace - = add_action (m_edit_nav_menu, tr ("Select to Matching Brace"), - SLOT (request_sel_match_brace (bool))); - - m_edit_nav_menu->addSeparator (); - - m_next_bookmark_action - = add_action (m_edit_nav_menu, tr ("&Next Bookmark"), - SLOT (request_next_bookmark (bool))); - - m_previous_bookmark_action - = add_action (m_edit_nav_menu, tr ("Pre&vious Bookmark"), - SLOT (request_previous_bookmark (bool))); - - m_toggle_bookmark_action - = add_action (m_edit_nav_menu, tr ("Toggle &Bookmark"), - SLOT (request_toggle_bookmark (bool))); - - m_remove_bookmark_action - = add_action (m_edit_nav_menu, tr ("&Remove All Bookmarks"), - SLOT (request_remove_bookmark (bool))); - - m_edit_menu->addSeparator (); - - m_preferences_action - = add_action (m_edit_menu, rmgr.icon ("preferences-system"), - tr ("&Preferences..."), - SLOT (request_preferences (bool))); - - m_styles_preferences_action - = add_action (m_edit_menu, rmgr.icon ("preferences-system"), - tr ("&Styles Preferences..."), - SLOT (request_styles_preferences (bool))); - - // view menu - - QMenu *view_menu = add_menu (m_menu_bar, tr ("&View")); - - m_view_editor_menu = view_menu->addMenu (tr ("&Editor")); - - m_show_linenum_action - = add_action (m_view_editor_menu, tr ("Show &Line Numbers"), - SLOT (show_line_numbers (bool))); - m_show_linenum_action->setCheckable (true); - - m_show_whitespace_action - = add_action (m_view_editor_menu, tr ("Show &Whitespace Characters"), - SLOT (show_white_space (bool))); - m_show_whitespace_action->setCheckable (true); - - m_show_eol_action - = add_action (m_view_editor_menu, tr ("Show Line &Endings"), - SLOT (show_eol_chars (bool))); - m_show_eol_action->setCheckable (true); - - m_show_indguide_action - = add_action (m_view_editor_menu, tr ("Show &Indentation Guides"), - SLOT (show_indent_guides (bool))); - m_show_indguide_action->setCheckable (true); - - m_show_longline_action - = add_action (m_view_editor_menu, tr ("Show Long Line &Marker"), - SLOT (show_long_line (bool))); - m_show_longline_action->setCheckable (true); - - m_view_editor_menu->addSeparator (); - - m_show_toolbar_action - = add_action (m_view_editor_menu, tr ("Show &Toolbar"), - SLOT (show_toolbar (bool))); - m_show_toolbar_action->setCheckable (true); - - m_show_statusbar_action - = add_action (m_view_editor_menu, tr ("Show &Statusbar"), - SLOT (show_statusbar (bool))); - m_show_statusbar_action->setCheckable (true); - - m_show_hscrollbar_action - = add_action (m_view_editor_menu, tr ("Show &Horizontal Scrollbar"), - SLOT (show_hscrollbar (bool))); - m_show_hscrollbar_action->setCheckable (true); - - view_menu->addSeparator (); - - m_zoom_in_action - = add_action (view_menu, rmgr.icon ("view-zoom-in"), tr ("Zoom &In"), - SLOT (zoom_in (bool))); - - m_zoom_out_action - = add_action (view_menu, rmgr.icon ("view-zoom-out"), tr ("Zoom &Out"), - SLOT (zoom_out (bool))); - - m_zoom_normal_action - = add_action (view_menu, rmgr.icon ("view-zoom-original"), tr ("&Normal Size"), - SLOT (zoom_normal (bool))); - - view_menu->addSeparator (); - - m_sort_tabs_action - = add_action (view_menu, tr ("&Sort Tabs Alphabetically"), - SLOT (sort_tabs_alph (void)), - m_tab_widget->get_tab_bar ()); - - m_menu_bar->addMenu (view_menu); - - // debug menu - - m_debug_menu = add_menu (m_menu_bar, tr ("&Debug")); - - m_toggle_breakpoint_action - = add_action (m_debug_menu, rmgr.icon ("bp-toggle"), - tr ("Toggle &Breakpoint"), - SLOT (request_toggle_breakpoint (bool))); - - m_next_breakpoint_action - = add_action (m_debug_menu, rmgr.icon ("bp-next"), - tr ("&Next Breakpoint"), - SLOT (request_next_breakpoint (bool))); - - m_previous_breakpoint_action - = add_action (m_debug_menu, rmgr.icon ("bp-prev"), - tr ("Pre&vious Breakpoint"), - SLOT (request_previous_breakpoint (bool))); - - m_remove_all_breakpoints_action - = add_action (m_debug_menu, rmgr.icon ("bp-rm-all"), - tr ("&Remove All Breakpoints"), - SLOT (request_remove_breakpoint (bool))); - - m_debug_menu->addSeparator (); - - // The other debug actions will be added by the main window. - - // run menu - - QMenu *_run_menu = add_menu (m_menu_bar, tr ("&Run")); - - m_run_action - = add_action (_run_menu, - rmgr.icon ("system-run"), - tr ("Save File and Run / Continue"), - SLOT (request_run_file (bool))); - - m_run_selection_action - = add_action (_run_menu, - tr ("Run &Selection"), - SLOT (request_context_run (bool))); - m_run_selection_action->setEnabled (false); - - // help menu - - QMenu *_help_menu = add_menu (m_menu_bar, tr ("&Help")); - - m_context_help_action - = add_action (_help_menu, - tr ("&Help on Keyword"), - SLOT (request_context_help (bool))); - - m_context_doc_action - = add_action (_help_menu, - tr ("&Documentation on Keyword"), - SLOT (request_context_doc (bool))); - - // tab navigation (no menu, only actions; slots in tab_bar) - - m_switch_left_tab_action - = add_action (nullptr, "", SLOT (switch_left_tab (void)), - m_tab_widget->get_tab_bar ()); - - m_switch_right_tab_action - = add_action (nullptr, "", SLOT (switch_right_tab (void)), - m_tab_widget->get_tab_bar ()); - - m_move_tab_left_action - = add_action (nullptr, "", SLOT (move_tab_left (void)), - m_tab_widget->get_tab_bar ()); - - m_move_tab_right_action - = add_action (nullptr, "", SLOT (move_tab_right (void)), - m_tab_widget->get_tab_bar ()); - - // toolbar - - // popdown menu with mru files - QToolButton *popdown_button = new QToolButton (); - popdown_button->setToolTip (tr ("Recent Files")); - popdown_button->setMenu (m_mru_file_menu); - popdown_button->setPopupMode (QToolButton::InstantPopup); - popdown_button->setArrowType (Qt::DownArrow); - popdown_button->setToolButtonStyle (Qt::ToolButtonTextOnly); - - // new and open actions are inserted later from main window - m_popdown_mru_action = m_tool_bar->addWidget (popdown_button); - m_tool_bar->addAction (m_save_action); - m_tool_bar->addAction (m_save_as_action); - m_tool_bar->addAction (m_print_action); - m_tool_bar->addSeparator (); - // m_undo_action: later via main window - m_tool_bar->addAction (m_redo_action); - m_tool_bar->addSeparator (); - m_tool_bar->addAction (m_cut_action); - // m_copy_action: later via the main window - // m_paste_action: later via the main window - m_tool_bar->addAction (m_find_action); - //m_tool_bar->addAction (m_find_next_action); - //m_tool_bar->addAction (m_find_previous_action); - m_tool_bar->addSeparator (); - m_tool_bar->addAction (m_run_action); - m_tool_bar->addSeparator (); - m_tool_bar->addAction (m_toggle_breakpoint_action); - m_tool_bar->addAction (m_previous_breakpoint_action); - m_tool_bar->addAction (m_next_breakpoint_action); - m_tool_bar->addAction (m_remove_all_breakpoints_action); - - // layout - QVBoxLayout *vbox_layout = new QVBoxLayout (); - vbox_layout->addWidget (m_menu_bar); - vbox_layout->addWidget (m_tool_bar); - vbox_layout->addWidget (m_tab_widget); - vbox_layout->setMargin (0); - vbox_layout->setSpacing (0); - editor_widget->setLayout (vbox_layout); - setWidget (editor_widget); - - // Create the basic context menu of the tab bar with editor actions. - // Actions for selecting an tab are added when the menu is activated. - tab_bar *bar = m_tab_widget->get_tab_bar (); - QMenu *ctx_men = bar->get_context_menu (); - ctx_men->addSeparator (); - ctx_men->addAction (m_close_action); - ctx_men->addAction (m_close_all_action); - ctx_men->addAction (m_close_others_action); - ctx_men->addSeparator (); - ctx_men->addAction (m_sort_tabs_action); - add_action (ctx_men, tr ("Copy Full File &Path"), - SLOT (copy_full_file_path (bool)), this); - - // signals - connect (m_mru_file_menu, &QMenu::triggered, - this, &file_editor::request_mru_open_file); - - mru_menu_update (); - - connect (m_tab_widget, &file_editor_tab_widget::tabCloseRequested, - this, &file_editor::handle_tab_close_request); - - connect (m_tab_widget, &file_editor_tab_widget::currentChanged, - this, &file_editor::active_tab_changed); - - resize (500, 400); - set_title (tr ("Editor")); - - check_actions (); -} - -// Slot when autocompletion list was cancelled -void file_editor::handle_autoc_cancelled (void) -{ - // List was cancelled but somehow still active and blocking the - // edit area from accepting shortcuts. Only after another keypress - // shortcuts and lists are working againnas expected. This is - // probably caused by qt bug https://bugreports.qt.io/browse/QTBUG-83720 - // Hack: Accept the list, which is hidden but still active - // and undo the text insertion, if any - - file_editor_tab *f = reset_focus (); - octave_qscintilla *qsci = f->qsci_edit_area (); - - int line, col; - qsci->getCursorPosition (&line, &col); - int l1 = qsci->lineLength (line); // Current line length - - // Accept autocompletion - qsci->SendScintilla (QsciScintillaBase::SCI_AUTOCCOMPLETE); - - // Was text inserted? If yes, undo - if (qsci->text (line).length () - l1) - qsci->undo (); -} - -file_editor_tab *file_editor::reset_focus (void) -{ - // Reset the focus of the tab and the related edit area - file_editor_tab *f - = static_cast (m_tab_widget->currentWidget ()); - emit fetab_set_focus (f); - return f; -} - -file_editor_tab * -file_editor::make_file_editor_tab (const QString& directory) -{ - file_editor_tab *f = new file_editor_tab (m_octave_qobj, directory); - - // signals from the qscintilla edit area - connect (f->qsci_edit_area (), &octave_qscintilla::status_update, - this, &file_editor::edit_status_update); - - connect (f->qsci_edit_area (), &octave_qscintilla::create_context_menu_signal, - this, &file_editor::create_context_menu); - - connect (f->qsci_edit_area (), - SIGNAL (SCN_AUTOCCOMPLETED (const char *, int, int, int)), - this, SLOT (reset_focus (void))); - - connect (f->qsci_edit_area (), SIGNAL (SCN_AUTOCCANCELLED (void)), - this, SLOT (handle_autoc_cancelled (void))); - - // signals from the qscintilla edit area - connect (this, &file_editor::enter_debug_mode_signal, - f->qsci_edit_area (), &octave_qscintilla::handle_enter_debug_mode); - - connect (this, &file_editor::exit_debug_mode_signal, - f->qsci_edit_area (), &octave_qscintilla::handle_exit_debug_mode); - - // Signals from the file editor_tab - connect (f, &file_editor_tab::autoc_closed, - this, &file_editor::reset_focus); - - connect (f, &file_editor_tab::file_name_changed, - this, &file_editor::handle_file_name_changed); - - connect (f, &file_editor_tab::editor_state_changed, - this, &file_editor::handle_editor_state_changed); - - connect (f, &file_editor_tab::tab_remove_request, - this, &file_editor::handle_tab_remove_request); - - connect (f, &file_editor_tab::editor_check_conflict_save, - this, &file_editor::check_conflict_save); - - connect (f, &file_editor_tab::mru_add_file, - this, &file_editor::handle_mru_add_file); - - connect (f, &file_editor_tab::request_open_file, - this, [=] (const QString& fname, const QString& encoding) { request_open_file (fname, encoding); }); - - connect (f, &file_editor_tab::edit_area_changed, - this, &file_editor::edit_area_changed); - - connect (f, &file_editor_tab::set_focus_editor_signal, - this, &file_editor::set_focus); - - // Signals from the file_editor or main-win non-trivial operations - connect (this, &file_editor::fetab_settings_changed, - f, [=] (const gui_settings *settings) { f->notice_settings (settings); }); - - connect (this, &file_editor::fetab_change_request, - f, &file_editor_tab::change_editor_state); - - connect (this, QOverload::of (&file_editor::fetab_save_file), - f, QOverload::of (&file_editor_tab::save_file)); - - // Signals from the file_editor trivial operations - connect (this, &file_editor::fetab_recover_from_exit, - f, &file_editor_tab::recover_from_exit); - - connect (this, &file_editor::fetab_set_directory, - f, &file_editor_tab::set_current_directory); - - connect (this, &file_editor::fetab_zoom_in, - f, &file_editor_tab::zoom_in); - connect (this, &file_editor::fetab_zoom_out, - f, &file_editor_tab::zoom_out); - connect (this, &file_editor::fetab_zoom_normal, - f, &file_editor_tab::zoom_normal); - - connect (this, &file_editor::fetab_context_help, - f, &file_editor_tab::context_help); - - connect (this, &file_editor::fetab_context_edit, - f, &file_editor_tab::context_edit); - - connect (this, QOverload::of (&file_editor::fetab_save_file), - f, QOverload::of (&file_editor_tab::save_file)); - - connect (this, &file_editor::fetab_save_file_as, - f, QOverload::of (&file_editor_tab::save_file_as)); - - connect (this, &file_editor::fetab_print_file, - f, &file_editor_tab::print_file); - - connect (this, &file_editor::fetab_run_file, - f, &file_editor_tab::run_file); - - connect (this, &file_editor::fetab_context_run, - f, &file_editor_tab::context_run); - - connect (this, &file_editor::fetab_toggle_bookmark, - f, &file_editor_tab::toggle_bookmark); - - connect (this, &file_editor::fetab_next_bookmark, - f, &file_editor_tab::next_bookmark); - - connect (this, &file_editor::fetab_previous_bookmark, - f, &file_editor_tab::previous_bookmark); - - connect (this, &file_editor::fetab_remove_bookmark, - f, &file_editor_tab::remove_bookmark); - - connect (this, &file_editor::fetab_toggle_breakpoint, - f, &file_editor_tab::toggle_breakpoint); - - connect (this, &file_editor::fetab_next_breakpoint, - f, &file_editor_tab::next_breakpoint); - - connect (this, &file_editor::fetab_previous_breakpoint, - f, &file_editor_tab::previous_breakpoint); - - connect (this, &file_editor::fetab_remove_all_breakpoints, - f, &file_editor_tab::remove_all_breakpoints); - - connect (this, &file_editor::fetab_scintilla_command, - f, &file_editor_tab::scintilla_command); - - connect (this, &file_editor::fetab_comment_selected_text, - f, &file_editor_tab::comment_selected_text); - - connect (this, &file_editor::fetab_uncomment_selected_text, - f, &file_editor_tab::uncomment_selected_text); - - connect (this, &file_editor::fetab_indent_selected_text, - f, &file_editor_tab::indent_selected_text); - - connect (this, &file_editor::fetab_unindent_selected_text, - f, &file_editor_tab::unindent_selected_text); - - connect (this, &file_editor::fetab_smart_indent_line_or_selected_text, - f, &file_editor_tab::smart_indent_line_or_selected_text); - - connect (this, &file_editor::fetab_convert_eol, - f, &file_editor_tab::convert_eol); - - connect (this, &file_editor::fetab_goto_line, - f, &file_editor_tab::goto_line); - - connect (this, &file_editor::fetab_move_match_brace, - f, &file_editor_tab::move_match_brace); - - connect (this, &file_editor::fetab_completion, - f, &file_editor_tab::show_auto_completion); - - connect (this, &file_editor::fetab_set_focus, - f, &file_editor_tab::set_focus); - - connect (this, &file_editor::fetab_insert_debugger_pointer, - f, &file_editor_tab::insert_debugger_pointer); - - connect (this, &file_editor::fetab_delete_debugger_pointer, - f, &file_editor_tab::delete_debugger_pointer); - - connect (this, &file_editor::fetab_do_breakpoint_marker, - f, &file_editor_tab::do_breakpoint_marker); - - connect (this, &file_editor::update_gui_lexer_signal, - f, &file_editor_tab::update_lexer_settings); - - // Convert other signals from the edit area and tab to editor signals. - - connect (f->qsci_edit_area (), &octave_qscintilla::execute_command_in_terminal_signal, - this, &file_editor::execute_command_in_terminal_signal); - - connect (f->qsci_edit_area (), &octave_qscintilla::focus_console_after_command_signal, - this, &file_editor::focus_console_after_command_signal); - - connect (f, &file_editor_tab::run_file_signal, - this, &file_editor::run_file_signal); - - connect (f, &file_editor_tab::edit_mfile_request, - this, &file_editor::edit_mfile_request); - - connect (f, &file_editor_tab::debug_quit_signal, - this, &file_editor::debug_quit_signal); - - // Any interpreter_event signal from a file_editor_tab_widget is - // handled the same as for the parent main_window object. - - connect (f, QOverload::of (&file_editor_tab::interpreter_event), - this, QOverload::of (&file_editor::interpreter_event)); - - connect (f, QOverload::of (&file_editor_tab::interpreter_event), - this, QOverload::of (&file_editor::interpreter_event)); - - return f; -} - -void file_editor::add_file_editor_tab (file_editor_tab *f, const QString& fn, - int index) -{ - if (index == -1) - m_tab_widget->addTab (f, fn); - else - m_tab_widget->insertTab (index, f, fn); - - m_tab_widget->setCurrentWidget (f); - - check_actions (); -} - -void file_editor::mru_menu_update (void) -{ - int num_files = qMin (m_mru_files.size (), int (MaxMRUFiles)); - - // configure and show active actions of mru-menu - for (int i = 0; i < num_files; ++i) - { - QString text = QString ("&%1 %2"). - arg ((i+1) % int (MaxMRUFiles)).arg (m_mru_files.at (i)); - m_mru_file_actions[i]->setText (text); - - QStringList action_data; - action_data << m_mru_files.at (i) << m_mru_files_encodings.at (i); - m_mru_file_actions[i]->setData (action_data); - - m_mru_file_actions[i]->setVisible (true); - } - - // hide unused mru-menu entries - for (int j = num_files; j < MaxMRUFiles; ++j) - m_mru_file_actions[j]->setVisible (false); - - // delete entries in string-list beyond MaxMRUFiles - while (m_mru_files.size () > MaxMRUFiles) - { - m_mru_files.removeLast (); - m_mru_files_encodings.removeLast (); - } - - // save actual mru-list in settings - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - settings->setValue (ed_mru_file_list.key, m_mru_files); - settings->setValue (ed_mru_file_encodings.key, m_mru_files_encodings); - settings->sync (); -} - -bool file_editor::call_custom_editor (const QString& file_name, int line) -{ - // Check if the user wants to use a custom file editor. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (settings->value (global_use_custom_editor.key, - global_use_custom_editor.def).toBool ()) - { - // use the external editor interface for handling the call - emit request_open_file_external (file_name, line); - - if (line < 0 && ! file_name.isEmpty ()) - handle_mru_add_file (QFileInfo (file_name).canonicalFilePath (), - QString ()); - + + if (QFile::exists (openFileName)) + { + // File not readable: + // create a NonModal message about error. + QMessageBox *msgBox + = new QMessageBox (QMessageBox::Critical, + tr ("Octave Editor"), + tr ("Could not open file\n%1\nfor read: %2."). + arg (openFileName).arg (result), + QMessageBox::Ok, this); + + msgBox->setWindowModality (Qt::NonModal); + msgBox->setAttribute (Qt::WA_DeleteOnClose); + msgBox->show (); + } + else + { + // File does not exist, should it be created? + bool create_file = true; + QMessageBox *msgBox; + + if (! settings.value (ed_create_new_file).toBool ()) + { + msgBox = new QMessageBox (QMessageBox::Question, + tr ("Octave Editor"), + tr ("File\n%1\ndoes not exist. " + "Do you want to create it?").arg (openFileName), + QMessageBox::NoButton, nullptr); + QPushButton *create_button = + msgBox->addButton (tr ("Create"), QMessageBox::YesRole); + msgBox->addButton (tr ("Cancel"), QMessageBox::RejectRole); + msgBox->setDefaultButton (create_button); + msgBox->exec (); + + QAbstractButton *clicked_button = msgBox->clickedButton (); + if (clicked_button != create_button) + create_file = false; + + delete msgBox; + } + + if (create_file) + { + // create the file and call the editor again + QFile file (openFileName); + if (! file.open (QIODevice::WriteOnly)) + { + // error opening the file + msgBox = new QMessageBox (QMessageBox::Critical, + tr ("Octave Editor"), + tr ("Could not open file\n%1\nfor write: %2."). + arg (openFileName).arg (file.errorString ()), + QMessageBox::Ok, this); + + msgBox->setWindowModality (Qt::NonModal); + msgBox->setAttribute (Qt::WA_DeleteOnClose); + msgBox->show (); + } + else + { + file.close (); + request_open_file (openFileName); + } + } + } + } + + if (! bookmarks.isEmpty ()) + { + // Restore bookmarks + for (const auto& bms : bookmarks.split (',')) + { + int bm = bms.toInt (); + if (fileEditorTab) + fileEditorTab->qsci_edit_area ()->markerAdd (bm, marker::bookmark); + } + } + + if (! ((breakpoint_marker || debug_pointer) && is_editor_console_tabbed ())) + { + // update breakpoint pointers, really show editor + // and the current editor tab + if (fileEditorTab) + fileEditorTab->update_breakpoints (); + activate (); + emit file_loaded_signal (); + } + } + } + } + + void file_editor::request_preferences (bool) + { + emit request_settings_dialog ("editor"); + } + + void file_editor::request_styles_preferences (bool) + { + emit request_settings_dialog ("editor_styles"); + } + + void file_editor::show_line_numbers (bool) + { + toggle_preference (ed_show_line_numbers); + } + + void file_editor::show_white_space (bool) + { + toggle_preference (ed_show_white_space); + } + + void file_editor::show_eol_chars (bool) + { + toggle_preference (ed_show_eol_chars); + } + + void file_editor::show_indent_guides (bool) + { + toggle_preference (ed_show_indent_guides); + } + + void file_editor::show_long_line (bool) + { + toggle_preference (ed_long_line_marker); + } + + void file_editor::show_toolbar (bool) + { + toggle_preference (ed_show_toolbar); + } + + void file_editor::show_statusbar (bool) + { + toggle_preference (ed_show_edit_status_bar); + } + + void file_editor::show_hscrollbar (bool) + { + toggle_preference (ed_show_hscroll_bar); + } + + void file_editor::zoom_in (bool) + { + emit fetab_zoom_in (m_tab_widget->currentWidget ()); + } + + void file_editor::zoom_out (bool) + { + emit fetab_zoom_out (m_tab_widget->currentWidget ()); + } + + void file_editor::zoom_normal (bool) + { + emit fetab_zoom_normal (m_tab_widget->currentWidget ()); + } + + void file_editor::create_context_menu (QMenu *menu) + { + // remove all standard actions from scintilla + QList all_actions = menu->actions (); + + for (auto *a : all_actions) + menu->removeAction (a); + + // add editor's actions with icons and customized shortcuts + menu->addAction (m_cut_action); + menu->addAction (m_copy_action); + menu->addAction (m_paste_action); + menu->addSeparator (); + menu->addAction (m_selectall_action); + menu->addSeparator (); + menu->addAction (m_find_files_action); + menu->addAction (m_find_action); + menu->addAction (m_find_next_action); + menu->addAction (m_find_previous_action); + menu->addSeparator (); + menu->addMenu (m_edit_cmd_menu); + menu->addMenu (m_edit_fmt_menu); + menu->addMenu (m_edit_nav_menu); + menu->addSeparator (); + menu->addAction (m_run_selection_action); + } + + void file_editor::edit_status_update (bool undo, bool redo) + { + if (m_undo_action) + m_undo_action->setEnabled (undo); + m_redo_action->setEnabled (redo); + } + + // handler for the close event + void file_editor::closeEvent (QCloseEvent *e) + { + gui_settings settings; + + if (settings.value (ed_hiding_closes_files).toBool ()) + { + if (check_closing ()) + { + // All tabs are closed without cancelling, + // store closing state for restoring session when shown again. + // Editor is closing when session data is stored in preferences + m_closed = true; + e->ignore (); + } + else + { + e->ignore (); + return; + } + } + else + e->accept (); + + octave_dock_widget::closeEvent (e); + } + + void file_editor::dragEnterEvent (QDragEnterEvent *e) + { + if (e->mimeData ()->hasUrls ()) + { + e->acceptProposedAction (); + } + } + + void file_editor::dropEvent (QDropEvent *e) + { + if (e->mimeData ()->hasUrls ()) + { + for (const auto& url : e->mimeData ()->urls ()) + request_open_file (url.toLocalFile ()); + } + } + + bool file_editor::is_editor_console_tabbed (void) + { + // FIXME: is there a way to do this job that doesn't require casting + // the parent to a main_window object? + + main_window *w = dynamic_cast (parentWidget ()); + + if (w) + { + QList w_list = w->tabifiedDockWidgets (this); + QDockWidget *console = + static_cast (w->get_dock_widget_list ().at (0)); + + for (int i = 0; i < w_list.count (); i++) + { + if (w_list.at (i) == console) + return true; + } + } + + return false; + } + + void file_editor::construct (void) + { + QWidget *editor_widget = new QWidget (this); + + // FIXME: what was the intended purpose of this unused variable? + // QStyle *editor_style = QApplication::style (); + + // Menu bar: do not set it native, required in macOS and Ubuntu Unity (Qt5) + // for a visible menu bar in the editor widget. This property is ignored + // on other platforms. + m_menu_bar = new QMenuBar (editor_widget); + m_menu_bar->setNativeMenuBar (false); + + m_tool_bar = new QToolBar (editor_widget); + m_tool_bar->setMovable (true); + + m_tab_widget = new file_editor_tab_widget (editor_widget, this); + + // the mru-list and an empty array of actions + + gui_settings settings; + + m_mru_files = settings.value (ed_mru_file_list).toStringList (); + m_mru_files_encodings = settings.value (ed_mru_file_encodings) + .toStringList (); + + if (m_mru_files_encodings.count () != m_mru_files.count ()) + { + // encodings don't have the same count -> do not use them! + m_mru_files_encodings = QStringList (); + for (int i = 0; i < m_mru_files.count (); i++) + m_mru_files_encodings << QString (); + } + + for (int i = 0; i < MaxMRUFiles; ++i) + { + m_mru_file_actions[i] = new QAction (this); + m_mru_file_actions[i]->setVisible (false); + } + + // menu bar + + // file menu + + m_fileMenu = add_menu (m_menu_bar, tr ("&File")); + + // new and open menus are inserted later by the main window + m_mru_file_menu = new QMenu (tr ("&Recent Editor Files"), m_fileMenu); + for (int i = 0; i < MaxMRUFiles; ++i) + m_mru_file_menu->addAction (m_mru_file_actions[i]); + m_fileMenu->addMenu (m_mru_file_menu); + + m_fileMenu->addSeparator (); + + m_edit_function_action + = add_action (m_fileMenu, + tr ("&Edit Function"), + SLOT (request_context_edit (bool))); + + m_fileMenu->addSeparator (); + + m_save_action + = add_action (m_fileMenu, settings.icon ("document-save"), + tr ("&Save File"), SLOT (request_save_file (bool))); + + m_save_as_action + = add_action (m_fileMenu, settings.icon ("document-save-as"), + tr ("Save File &As..."), + SLOT (request_save_file_as (bool))); + + m_fileMenu->addSeparator (); + + m_close_action + = add_action (m_fileMenu, settings.icon ("window-close", false), + tr ("&Close"), SLOT (request_close_file (bool))); + + m_close_all_action + = add_action (m_fileMenu, settings.icon ("window-close", false), + tr ("Close All"), SLOT (request_close_all_files (bool))); + + m_close_others_action + = add_action (m_fileMenu, settings.icon ("window-close", false), + tr ("Close Other Files"), + SLOT (request_close_other_files (bool))); + + m_fileMenu->addSeparator (); + + m_print_action + = add_action (m_fileMenu, settings.icon ("document-print"), + tr ("Print..."), SLOT (request_print_file (bool))); + + // edit menu (undo, copy, paste and select all later via main window) + + m_edit_menu = add_menu (m_menu_bar, tr ("&Edit")); + + m_redo_action + = add_action (m_edit_menu, settings.icon ("edit-redo"), + tr ("&Redo"), SLOT (request_redo (bool))); + m_redo_action->setEnabled (false); + + m_edit_menu->addSeparator (); + + m_cut_action + = add_action (m_edit_menu, settings.icon ("edit-cut"), + tr ("Cu&t"), SLOT (request_cut (bool))); + m_cut_action->setEnabled (false); + + m_find_action + = add_action (m_edit_menu, settings.icon ("edit-find-replace"), + tr ("&Find and Replace..."), SLOT (request_find (bool))); + + m_find_next_action + = add_action (m_edit_menu, tr ("Find &Next..."), + SLOT (request_find_next (bool))); + + m_find_previous_action + = add_action (m_edit_menu, tr ("Find &Previous..."), + SLOT (request_find_previous (bool))); + + m_edit_menu->addSeparator (); + + m_edit_cmd_menu = m_edit_menu->addMenu (tr ("&Commands")); + + m_delete_line_action + = add_action (m_edit_cmd_menu, tr ("Delete Line"), + SLOT (request_delete_line (bool))); + + m_copy_line_action + = add_action (m_edit_cmd_menu, tr ("Copy Line"), + SLOT (request_copy_line (bool))); + + m_cut_line_action + = add_action (m_edit_cmd_menu, tr ("Cut Line"), + SLOT (request_cut_line (bool))); + + m_edit_cmd_menu->addSeparator (); + + m_delete_start_word_action + = add_action (m_edit_cmd_menu, tr ("Delete to Start of Word"), + SLOT (request_delete_start_word (bool))); + + m_delete_end_word_action + = add_action (m_edit_cmd_menu, tr ("Delete to End of Word"), + SLOT (request_delete_end_word (bool))); + + m_delete_start_line_action + = add_action (m_edit_cmd_menu, tr ("Delete to Start of Line"), + SLOT (request_delete_start_line (bool))); + + m_delete_end_line_action + = add_action (m_edit_cmd_menu, tr ("Delete to End of Line"), + SLOT (request_delete_end_line (bool))); + + m_edit_cmd_menu->addSeparator (); + + m_duplicate_selection_action + = add_action (m_edit_cmd_menu, tr ("Duplicate Selection/Line"), + SLOT (request_duplicate_selection (bool))); + + m_transpose_line_action + = add_action (m_edit_cmd_menu, tr ("Transpose Line"), + SLOT (request_transpose_line (bool))); + + m_edit_cmd_menu->addSeparator (); + + m_completion_action + = add_action (m_edit_cmd_menu, tr ("&Show Completion List"), + SLOT (request_completion (bool))); + + m_edit_fmt_menu = m_edit_menu->addMenu (tr ("&Format")); + + m_upper_case_action + = add_action (m_edit_fmt_menu, tr ("&Uppercase Selection"), + SLOT (request_upper_case (bool))); + + m_lower_case_action + = add_action (m_edit_fmt_menu, tr ("&Lowercase Selection"), + SLOT (request_lower_case (bool))); + + m_edit_fmt_menu->addSeparator (); + + m_comment_selection_action + = add_action (m_edit_fmt_menu, tr ("&Comment"), + SLOT (request_comment_selected_text (bool))); + + m_uncomment_selection_action + = add_action (m_edit_fmt_menu, tr ("&Uncomment"), + SLOT (request_uncomment_selected_text (bool))); + + m_comment_var_selection_action + = add_action (m_edit_fmt_menu, tr ("Comment (Choosing String)"), + SLOT (request_comment_var_selected_text (bool))); + + m_edit_fmt_menu->addSeparator (); + + m_indent_selection_action + = add_action (m_edit_fmt_menu, tr ("&Indent Selection Rigidly"), + SLOT (request_indent_selected_text (bool))); + + m_unindent_selection_action + = add_action (m_edit_fmt_menu, tr ("&Unindent Selection Rigidly"), + SLOT (request_unindent_selected_text (bool))); + + m_smart_indent_line_or_selection_action + = add_action (m_edit_fmt_menu, tr ("Indent Code"), + SLOT (request_smart_indent_line_or_selected_text (void))); + + m_edit_fmt_menu->addSeparator (); + + m_conv_eol_windows_action + = add_action (m_edit_fmt_menu, + tr ("Convert Line Endings to &Windows (CRLF)"), + SLOT (request_conv_eol_windows (bool))); + + m_conv_eol_unix_action + = add_action (m_edit_fmt_menu, tr ("Convert Line Endings to &Unix (LF)"), + SLOT (request_conv_eol_unix (bool))); + + m_conv_eol_mac_action + = add_action (m_edit_fmt_menu, + tr ("Convert Line Endings to Legacy &Mac (CR)"), + SLOT (request_conv_eol_mac (bool))); + + m_edit_nav_menu = m_edit_menu->addMenu (tr ("Navi&gation")); + + m_goto_line_action + = add_action (m_edit_nav_menu, tr ("Go &to Line..."), + SLOT (request_goto_line (bool))); + + m_edit_cmd_menu->addSeparator (); + + m_move_to_matching_brace + = add_action (m_edit_nav_menu, tr ("Move to Matching Brace"), + SLOT (request_move_match_brace (bool))); + + m_sel_to_matching_brace + = add_action (m_edit_nav_menu, tr ("Select to Matching Brace"), + SLOT (request_sel_match_brace (bool))); + + m_edit_nav_menu->addSeparator (); + + m_next_bookmark_action + = add_action (m_edit_nav_menu, tr ("&Next Bookmark"), + SLOT (request_next_bookmark (bool))); + + m_previous_bookmark_action + = add_action (m_edit_nav_menu, tr ("Pre&vious Bookmark"), + SLOT (request_previous_bookmark (bool))); + + m_toggle_bookmark_action + = add_action (m_edit_nav_menu, tr ("Toggle &Bookmark"), + SLOT (request_toggle_bookmark (bool))); + + m_remove_bookmark_action + = add_action (m_edit_nav_menu, tr ("&Remove All Bookmarks"), + SLOT (request_remove_bookmark (bool))); + + m_edit_menu->addSeparator (); + + m_preferences_action + = add_action (m_edit_menu, settings.icon ("preferences-system"), + tr ("&Preferences..."), + SLOT (request_preferences (bool))); + + m_styles_preferences_action + = add_action (m_edit_menu, settings.icon ("preferences-system"), + tr ("&Styles Preferences..."), + SLOT (request_styles_preferences (bool))); + + // view menu + + QMenu *view_menu = add_menu (m_menu_bar, tr ("&View")); + + m_view_editor_menu = view_menu->addMenu (tr ("&Editor")); + + m_show_linenum_action + = add_action (m_view_editor_menu, tr ("Show &Line Numbers"), + SLOT (show_line_numbers (bool))); + m_show_linenum_action->setCheckable (true); + + m_show_whitespace_action + = add_action (m_view_editor_menu, tr ("Show &Whitespace Characters"), + SLOT (show_white_space (bool))); + m_show_whitespace_action->setCheckable (true); + + m_show_eol_action + = add_action (m_view_editor_menu, tr ("Show Line &Endings"), + SLOT (show_eol_chars (bool))); + m_show_eol_action->setCheckable (true); + + m_show_indguide_action + = add_action (m_view_editor_menu, tr ("Show &Indentation Guides"), + SLOT (show_indent_guides (bool))); + m_show_indguide_action->setCheckable (true); + + m_show_longline_action + = add_action (m_view_editor_menu, tr ("Show Long Line &Marker"), + SLOT (show_long_line (bool))); + m_show_longline_action->setCheckable (true); + + m_view_editor_menu->addSeparator (); + + m_show_toolbar_action + = add_action (m_view_editor_menu, tr ("Show &Toolbar"), + SLOT (show_toolbar (bool))); + m_show_toolbar_action->setCheckable (true); + + m_show_statusbar_action + = add_action (m_view_editor_menu, tr ("Show &Statusbar"), + SLOT (show_statusbar (bool))); + m_show_statusbar_action->setCheckable (true); + + m_show_hscrollbar_action + = add_action (m_view_editor_menu, tr ("Show &Horizontal Scrollbar"), + SLOT (show_hscrollbar (bool))); + m_show_hscrollbar_action->setCheckable (true); + + view_menu->addSeparator (); + + m_zoom_in_action + = add_action (view_menu, settings.icon ("view-zoom-in"), tr ("Zoom &In"), + SLOT (zoom_in (bool))); + + m_zoom_out_action + = add_action (view_menu, settings.icon ("view-zoom-out"), + tr ("Zoom &Out"), SLOT (zoom_out (bool))); + + m_zoom_normal_action + = add_action (view_menu, settings.icon ("view-zoom-original"), + tr ("&Normal Size"), SLOT (zoom_normal (bool))); + + view_menu->addSeparator (); + + m_sort_tabs_action + = add_action (view_menu, tr ("&Sort Tabs Alphabetically"), + SLOT (sort_tabs_alph (void)), + m_tab_widget->get_tab_bar ()); + + m_menu_bar->addMenu (view_menu); + + // debug menu + + m_debug_menu = add_menu (m_menu_bar, tr ("&Debug")); + + m_toggle_breakpoint_action + = add_action (m_debug_menu, settings.icon ("bp-toggle"), + tr ("Toggle &Breakpoint"), + SLOT (request_toggle_breakpoint (bool))); + + m_next_breakpoint_action + = add_action (m_debug_menu, settings.icon ("bp-next"), + tr ("&Next Breakpoint"), + SLOT (request_next_breakpoint (bool))); + + m_previous_breakpoint_action + = add_action (m_debug_menu, settings.icon ("bp-prev"), + tr ("Pre&vious Breakpoint"), + SLOT (request_previous_breakpoint (bool))); + + m_remove_all_breakpoints_action + = add_action (m_debug_menu, settings.icon ("bp-rm-all"), + tr ("&Remove All Breakpoints"), + SLOT (request_remove_breakpoint (bool))); + + m_debug_menu->addSeparator (); + + // The other debug actions will be added by the main window. + + // run menu + + QMenu *_run_menu = add_menu (m_menu_bar, tr ("&Run")); + + m_run_action + = add_action (_run_menu, + settings.icon ("system-run"), + tr ("Save File and Run / Continue"), + SLOT (request_run_file (bool))); + + m_run_selection_action + = add_action (_run_menu, + tr ("Run &Selection"), + SLOT (request_context_run (bool))); + m_run_selection_action->setEnabled (false); + + // help menu + + QMenu *_help_menu = add_menu (m_menu_bar, tr ("&Help")); + + m_context_help_action + = add_action (_help_menu, + tr ("&Help on Keyword"), + SLOT (request_context_help (bool))); + + m_context_doc_action + = add_action (_help_menu, + tr ("&Documentation on Keyword"), + SLOT (request_context_doc (bool))); + + // tab navigation (no menu, only actions; slots in tab_bar) + + m_switch_left_tab_action + = add_action (nullptr, "", SLOT (switch_left_tab (void)), + m_tab_widget->get_tab_bar ()); + + m_switch_right_tab_action + = add_action (nullptr, "", SLOT (switch_right_tab (void)), + m_tab_widget->get_tab_bar ()); + + m_move_tab_left_action + = add_action (nullptr, "", SLOT (move_tab_left (void)), + m_tab_widget->get_tab_bar ()); + + m_move_tab_right_action + = add_action (nullptr, "", SLOT (move_tab_right (void)), + m_tab_widget->get_tab_bar ()); + + // toolbar + + // popdown menu with mru files + QToolButton *popdown_button = new QToolButton (); + popdown_button->setToolTip (tr ("Recent Files")); + popdown_button->setMenu (m_mru_file_menu); + popdown_button->setPopupMode (QToolButton::InstantPopup); + popdown_button->setArrowType (Qt::DownArrow); + popdown_button->setToolButtonStyle (Qt::ToolButtonTextOnly); + + // new and open actions are inserted later from main window + m_popdown_mru_action = m_tool_bar->addWidget (popdown_button); + m_tool_bar->addAction (m_save_action); + m_tool_bar->addAction (m_save_as_action); + m_tool_bar->addAction (m_print_action); + m_tool_bar->addSeparator (); + // m_undo_action: later via main window + m_tool_bar->addAction (m_redo_action); + m_tool_bar->addSeparator (); + m_tool_bar->addAction (m_cut_action); + // m_copy_action: later via the main window + // m_paste_action: later via the main window + m_tool_bar->addAction (m_find_action); + //m_tool_bar->addAction (m_find_next_action); + //m_tool_bar->addAction (m_find_previous_action); + m_tool_bar->addSeparator (); + m_tool_bar->addAction (m_run_action); + m_tool_bar->addSeparator (); + m_tool_bar->addAction (m_toggle_breakpoint_action); + m_tool_bar->addAction (m_previous_breakpoint_action); + m_tool_bar->addAction (m_next_breakpoint_action); + m_tool_bar->addAction (m_remove_all_breakpoints_action); + + // layout + QVBoxLayout *vbox_layout = new QVBoxLayout (); + vbox_layout->addWidget (m_menu_bar); + vbox_layout->addWidget (m_tool_bar); + vbox_layout->addWidget (m_tab_widget); + vbox_layout->setMargin (0); + vbox_layout->setSpacing (0); + editor_widget->setLayout (vbox_layout); + setWidget (editor_widget); + + // Create the basic context menu of the tab bar with editor actions. + // Actions for selecting an tab are added when the menu is activated. + tab_bar *bar = m_tab_widget->get_tab_bar (); + QMenu *ctx_men = bar->get_context_menu (); + ctx_men->addSeparator (); + ctx_men->addAction (m_close_action); + ctx_men->addAction (m_close_all_action); + ctx_men->addAction (m_close_others_action); + ctx_men->addSeparator (); + ctx_men->addAction (m_sort_tabs_action); + add_action (ctx_men, tr ("Copy Full File &Path"), + SLOT (copy_full_file_path (bool)), this); + + // signals + connect (m_mru_file_menu, &QMenu::triggered, + this, &file_editor::request_mru_open_file); + + mru_menu_update (); + + connect (m_tab_widget, &file_editor_tab_widget::tabCloseRequested, + this, &file_editor::handle_tab_close_request); + + connect (m_tab_widget, &file_editor_tab_widget::currentChanged, + this, &file_editor::active_tab_changed); + + resize (500, 400); + set_title (tr ("Editor")); + + check_actions (); + } + + // Slot when autocompletion list was cancelled + void file_editor::handle_autoc_cancelled (void) + { + // List was cancelled but somehow still active and blocking the + // edit area from accepting shortcuts. Only after another keypress + // shortcuts and lists are working againnas expected. This is + // probably caused by qt bug https://bugreports.qt.io/browse/QTBUG-83720 + // Hack: Accept the list, which is hidden but still active + // and undo the text insertion, if any + + file_editor_tab *f = reset_focus (); + octave_qscintilla *qsci = f->qsci_edit_area (); + + int line, col; + qsci->getCursorPosition (&line, &col); + int l1 = qsci->lineLength (line); // Current line length + + // Accept autocompletion + qsci->SendScintilla (QsciScintillaBase::SCI_AUTOCCOMPLETE); + + // Was text inserted? If yes, undo + if (qsci->text (line).length () - l1) + qsci->undo (); + } + + file_editor_tab *file_editor::reset_focus (void) + { + // Reset the focus of the tab and the related edit area + file_editor_tab *f + = static_cast (m_tab_widget->currentWidget ()); + emit fetab_set_focus (f); + return f; + } + + file_editor_tab * + file_editor::make_file_editor_tab (const QString& directory) + { + file_editor_tab *f = new file_editor_tab (m_octave_qobj, directory); + + // signals from the qscintilla edit area + connect (f->qsci_edit_area (), &octave_qscintilla::status_update, + this, &file_editor::edit_status_update); + + connect (f->qsci_edit_area (), &octave_qscintilla::create_context_menu_signal, + this, &file_editor::create_context_menu); + + connect (f->qsci_edit_area (), + SIGNAL (SCN_AUTOCCOMPLETED (const char *, int, int, int)), + this, SLOT (reset_focus (void))); + + connect (f->qsci_edit_area (), SIGNAL (SCN_AUTOCCANCELLED (void)), + this, SLOT (handle_autoc_cancelled (void))); + + // signals from the qscintilla edit area + connect (this, &file_editor::enter_debug_mode_signal, + f->qsci_edit_area (), &octave_qscintilla::handle_enter_debug_mode); + + connect (this, &file_editor::exit_debug_mode_signal, + f->qsci_edit_area (), &octave_qscintilla::handle_exit_debug_mode); + + // Signals from the file editor_tab + connect (f, &file_editor_tab::autoc_closed, + this, &file_editor::reset_focus); + + connect (f, &file_editor_tab::file_name_changed, + this, &file_editor::handle_file_name_changed); + + connect (f, &file_editor_tab::editor_state_changed, + this, &file_editor::handle_editor_state_changed); + + connect (f, &file_editor_tab::tab_remove_request, + this, &file_editor::handle_tab_remove_request); + + connect (f, &file_editor_tab::editor_check_conflict_save, + this, &file_editor::check_conflict_save); + + connect (f, &file_editor_tab::mru_add_file, + this, &file_editor::handle_mru_add_file); + + connect (f, &file_editor_tab::request_open_file, + this, [=] (const QString& fname, const QString& encoding) { request_open_file (fname, encoding); }); + + connect (f, &file_editor_tab::edit_area_changed, + this, &file_editor::edit_area_changed); + + connect (f, &file_editor_tab::set_focus_editor_signal, + this, &file_editor::set_focus); + + // Signals from the file_editor or main-win non-trivial operations + connect (this, &file_editor::fetab_settings_changed, + f, [=] () { f->notice_settings (); }); + + connect (this, &file_editor::fetab_change_request, + f, &file_editor_tab::change_editor_state); + + connect (this, QOverload::of (&file_editor::fetab_save_file), + f, QOverload::of (&file_editor_tab::save_file)); + + // Signals from the file_editor trivial operations + connect (this, &file_editor::fetab_recover_from_exit, + f, &file_editor_tab::recover_from_exit); + + connect (this, &file_editor::fetab_set_directory, + f, &file_editor_tab::set_current_directory); + + connect (this, &file_editor::fetab_zoom_in, + f, &file_editor_tab::zoom_in); + connect (this, &file_editor::fetab_zoom_out, + f, &file_editor_tab::zoom_out); + connect (this, &file_editor::fetab_zoom_normal, + f, &file_editor_tab::zoom_normal); + + connect (this, &file_editor::fetab_context_help, + f, &file_editor_tab::context_help); + + connect (this, &file_editor::fetab_context_edit, + f, &file_editor_tab::context_edit); + + connect (this, QOverload::of (&file_editor::fetab_save_file), + f, QOverload::of (&file_editor_tab::save_file)); + + connect (this, &file_editor::fetab_save_file_as, + f, QOverload::of (&file_editor_tab::save_file_as)); + + connect (this, &file_editor::fetab_print_file, + f, &file_editor_tab::print_file); + + connect (this, &file_editor::fetab_run_file, + f, &file_editor_tab::run_file); + + connect (this, &file_editor::fetab_context_run, + f, &file_editor_tab::context_run); + + connect (this, &file_editor::fetab_toggle_bookmark, + f, &file_editor_tab::toggle_bookmark); + + connect (this, &file_editor::fetab_next_bookmark, + f, &file_editor_tab::next_bookmark); + + connect (this, &file_editor::fetab_previous_bookmark, + f, &file_editor_tab::previous_bookmark); + + connect (this, &file_editor::fetab_remove_bookmark, + f, &file_editor_tab::remove_bookmark); + + connect (this, &file_editor::fetab_toggle_breakpoint, + f, &file_editor_tab::toggle_breakpoint); + + connect (this, &file_editor::fetab_next_breakpoint, + f, &file_editor_tab::next_breakpoint); + + connect (this, &file_editor::fetab_previous_breakpoint, + f, &file_editor_tab::previous_breakpoint); + + connect (this, &file_editor::fetab_remove_all_breakpoints, + f, &file_editor_tab::remove_all_breakpoints); + + connect (this, &file_editor::fetab_scintilla_command, + f, &file_editor_tab::scintilla_command); + + connect (this, &file_editor::fetab_comment_selected_text, + f, &file_editor_tab::comment_selected_text); + + connect (this, &file_editor::fetab_uncomment_selected_text, + f, &file_editor_tab::uncomment_selected_text); + + connect (this, &file_editor::fetab_indent_selected_text, + f, &file_editor_tab::indent_selected_text); + + connect (this, &file_editor::fetab_unindent_selected_text, + f, &file_editor_tab::unindent_selected_text); + + connect (this, &file_editor::fetab_smart_indent_line_or_selected_text, + f, &file_editor_tab::smart_indent_line_or_selected_text); + + connect (this, &file_editor::fetab_convert_eol, + f, &file_editor_tab::convert_eol); + + connect (this, &file_editor::fetab_goto_line, + f, &file_editor_tab::goto_line); + + connect (this, &file_editor::fetab_move_match_brace, + f, &file_editor_tab::move_match_brace); + + connect (this, &file_editor::fetab_completion, + f, &file_editor_tab::show_auto_completion); + + connect (this, &file_editor::fetab_set_focus, + f, &file_editor_tab::set_focus); + + connect (this, &file_editor::fetab_insert_debugger_pointer, + f, &file_editor_tab::insert_debugger_pointer); + + connect (this, &file_editor::fetab_delete_debugger_pointer, + f, &file_editor_tab::delete_debugger_pointer); + + connect (this, &file_editor::fetab_do_breakpoint_marker, + f, &file_editor_tab::do_breakpoint_marker); + + connect (this, &file_editor::update_gui_lexer_signal, + f, &file_editor_tab::update_lexer_settings); + + // Convert other signals from the edit area and tab to editor signals. + + connect (f->qsci_edit_area (), &octave_qscintilla::execute_command_in_terminal_signal, + this, &file_editor::execute_command_in_terminal_signal); + + connect (f->qsci_edit_area (), &octave_qscintilla::focus_console_after_command_signal, + this, &file_editor::focus_console_after_command_signal); + + connect (f, &file_editor_tab::run_file_signal, + this, &file_editor::run_file_signal); + + connect (f, &file_editor_tab::edit_mfile_request, + this, &file_editor::edit_mfile_request); + + connect (f, &file_editor_tab::debug_quit_signal, + this, &file_editor::debug_quit_signal); + + // Any interpreter_event signal from a file_editor_tab_widget is + // handled the same as for the parent main_window object. + + connect (f, QOverload::of (&file_editor_tab::interpreter_event), + this, QOverload::of (&file_editor::interpreter_event)); + + connect (f, QOverload::of (&file_editor_tab::interpreter_event), + this, QOverload::of (&file_editor::interpreter_event)); + + return f; + } + + void file_editor::add_file_editor_tab (file_editor_tab *f, const QString& fn, + int index) + { + if (index == -1) + m_tab_widget->addTab (f, fn); + else + m_tab_widget->insertTab (index, f, fn); + + m_tab_widget->setCurrentWidget (f); + + check_actions (); + } + + void file_editor::mru_menu_update (void) + { + int num_files = qMin (m_mru_files.size (), int (MaxMRUFiles)); + + // configure and show active actions of mru-menu + for (int i = 0; i < num_files; ++i) + { + QString text = QString ("&%1 %2"). + arg ((i+1) % int (MaxMRUFiles)).arg (m_mru_files.at (i)); + m_mru_file_actions[i]->setText (text); + + QStringList action_data; + action_data << m_mru_files.at (i) << m_mru_files_encodings.at (i); + m_mru_file_actions[i]->setData (action_data); + + m_mru_file_actions[i]->setVisible (true); + } + + // hide unused mru-menu entries + for (int j = num_files; j < MaxMRUFiles; ++j) + m_mru_file_actions[j]->setVisible (false); + + // delete entries in string-list beyond MaxMRUFiles + while (m_mru_files.size () > MaxMRUFiles) + { + m_mru_files.removeLast (); + m_mru_files_encodings.removeLast (); + } + + // save actual mru-list in settings + + gui_settings settings; + + settings.setValue (ed_mru_file_list.key, m_mru_files); + settings.setValue (ed_mru_file_encodings.key, m_mru_files_encodings); + + settings.sync (); + } + + bool file_editor::call_custom_editor (const QString& file_name, int line) + { + // Check if the user wants to use a custom file editor. + + gui_settings settings; + + if (settings.value (global_use_custom_editor.key, + global_use_custom_editor.def).toBool ()) + { + // use the external editor interface for handling the call + emit request_open_file_external (file_name, line); + + if (line < 0 && ! file_name.isEmpty ()) + handle_mru_add_file (QFileInfo (file_name).canonicalFilePath (), + QString ()); + + return true; + } + + return false; + } + + void file_editor::toggle_preference (const gui_pref& preference) + { + gui_settings settings; + + bool old = settings.value (preference).toBool (); + settings.setValue (preference.key, ! old); + notice_settings (); + } + + // Function for closing the files in a removed directory + void file_editor::handle_dir_remove (const QString& old_name, + const QString& new_name) + { + QDir old_dir (old_name); + removed_file_data f_data; + + std::list editor_tab_lst = m_tab_widget->tab_list (); + + for (auto editor_tab : editor_tab_lst) + { + QString file_name = editor_tab->file_name (); + + if (file_name.isEmpty ()) + continue; // Nothing to do, no valid file name + + // Get abs. file path and its path relative to the removed directory + QString rel_path_to_file = old_dir.relativeFilePath (file_name); + QString abs_path_to_file = old_dir.absoluteFilePath (file_name); + + // Test whether the file is located within the directory that will + // be removed. For this, two conditions must be met: + // 1. The path of the file rel. to the dir is not equal to the + // its absolute one. + // If both are equal, then there is no relative path and removed + // directory and file are on different drives (e.g. on windows) + // 2. The (real) relative path does not start with "../", i.e., + // the file can be reached from the directory by descending only + if ((rel_path_to_file != abs_path_to_file) + && (rel_path_to_file.left (3) != QString ("../"))) + { + // The currently considered file is included in the + // removed/renamed diectory: remeber it + if (editor_tab) + { + editor_tab->enable_file_watcher (false); + f_data.editor_tab = editor_tab; + + // Add the new file path and the encoding for later reloading + // if new_name is given + if (! new_name.isEmpty ()) + { + QDir new_dir (new_name); + QString append_to_new_dir; + if (new_dir.exists ()) + { + // The new directory already exists (movefile was used). + // This means, we have to add the name (not the path) + // of the old dir and the relative path to the file + // to new dir. + append_to_new_dir + = old_dir.dirName () + "/" + rel_path_to_file; + } + else + append_to_new_dir = rel_path_to_file; + + f_data.new_file_name + = new_dir.absoluteFilePath (append_to_new_dir); + } + else + f_data.new_file_name = ""; // no new name, just removing this file + + // Store data in list for later reloading + m_tmp_closed_files << f_data; + } + } + } + } + + bool file_editor::editor_tab_has_focus (void) + { + QWidget *foc_w = focusWidget (); + if (foc_w && foc_w->inherits ("octave::octave_qscintilla")) return true; - } - - return false; -} - -void file_editor::toggle_preference (const gui_pref& preference) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - bool old = settings->value (preference).toBool (); - settings->setValue (preference.key, ! old); - notice_settings (settings); -} - -// Function for closing the files in a removed directory -void file_editor::handle_dir_remove (const QString& old_name, - const QString& new_name) -{ - QDir old_dir (old_name); - removed_file_data f_data; - - std::list editor_tab_lst = m_tab_widget->tab_list (); - - for (auto editor_tab : editor_tab_lst) - { - QString file_name = editor_tab->file_name (); - - if (file_name.isEmpty ()) - continue; // Nothing to do, no valid file name - - // Get abs. file path and its path relative to the removed directory - QString rel_path_to_file = old_dir.relativeFilePath (file_name); - QString abs_path_to_file = old_dir.absoluteFilePath (file_name); - - // Test whether the file is located within the directory that will - // be removed. For this, two conditions must be met: - // 1. The path of the file rel. to the dir is not equal to the - // its absolute one. - // If both are equal, then there is no relative path and removed - // directory and file are on different drives (e.g. on windows) - // 2. The (real) relative path does not start with "../", i.e., - // the file can be reached from the directory by descending only - if ((rel_path_to_file != abs_path_to_file) - && (rel_path_to_file.left (3) != QString ("../"))) - { - // The currently considered file is included in the - // removed/renamed diectory: remeber it - if (editor_tab) - { - editor_tab->enable_file_watcher (false); - f_data.editor_tab = editor_tab; - - // Add the new file path and the encoding for later reloading - // if new_name is given - if (! new_name.isEmpty ()) - { - QDir new_dir (new_name); - QString append_to_new_dir; - if (new_dir.exists ()) - { - // The new directory already exists (movefile was used). - // This means, we have to add the name (not the path) - // of the old dir and the relative path to the file - // to new dir. - append_to_new_dir - = old_dir.dirName () + "/" + rel_path_to_file; - } - else - append_to_new_dir = rel_path_to_file; - - f_data.new_file_name - = new_dir.absoluteFilePath (append_to_new_dir); - } - else - f_data.new_file_name = ""; // no new name, just removing this file - - // Store data in list for later reloading - m_tmp_closed_files << f_data; - } - } - } -} - -bool file_editor::editor_tab_has_focus (void) -{ - QWidget *foc_w = focusWidget (); - if (foc_w && foc_w->inherits ("octave::octave_qscintilla")) - return true; - return false; -} - -// Check whether this file is already open in the editor. -file_editor_tab *file_editor::find_tab_widget (const QString& file) -{ - std::string std_file = file.toStdString (); - - std::list fe_tab_lst = m_tab_widget->tab_list (); - - for (auto fe_tab : fe_tab_lst) - { - QString tab_file = fe_tab->file_name (); - - // We check file == tab_file because - // - // same_file ("", "") - // - // is false - - if (same_file (std_file, tab_file.toStdString ()) || file == tab_file) - return fe_tab; - } - - return nullptr; -} - -QAction * file_editor::add_action (QMenu *menu, const QString& text, - const char *member, - QWidget *receiver) -{ - return add_action (menu, QIcon (), text, member, receiver); -} - -QAction * file_editor::add_action (QMenu *menu, const QIcon& icon, - const QString& text, const char *member, - QWidget *receiver) -{ - QAction *a; - QWidget *r = this; - - if (receiver != nullptr) - r = receiver; - - if (menu) - a = menu->addAction (icon, text, r, member); - else - { - a = new QAction (this); - connect (a, SIGNAL (triggered ()), r, member); - } - - addAction (a); // important for shortcut context - a->setShortcutContext (Qt::WidgetWithChildrenShortcut); - - return a; -} - -QMenu* file_editor::add_menu (QMenuBar *p, QString name) -{ - QMenu *menu = p->addMenu (name); - - QString base_name = name; // get a copy - // replace intended '&' ("&&") by a temp. string - base_name.replace ("&&", "___octave_amp_replacement___"); - // remove single '&' (shortcut) - base_name.remove ("&"); - // restore intended '&' - base_name.replace ("___octave_amp_replacement___", "&&"); - - // remember names with and without shortcut - m_hash_menu_text[menu] = QStringList () << name << base_name; - - return menu; -} + return false; + } + + // Check whether this file is already open in the editor. + file_editor_tab *file_editor::find_tab_widget (const QString& file) + { + std::string std_file = file.toStdString (); + + std::list fe_tab_lst = m_tab_widget->tab_list (); + + for (auto fe_tab : fe_tab_lst) + { + QString tab_file = fe_tab->file_name (); + + // We check file == tab_file because + // + // same_file ("", "") + // + // is false + + if (same_file (std_file, tab_file.toStdString ()) || file == tab_file) + return fe_tab; + } + + return nullptr; + } + + QAction * file_editor::add_action (QMenu *menu, const QString& text, + const char *member, + QWidget *receiver) + { + return add_action (menu, QIcon (), text, member, receiver); + } + + QAction * file_editor::add_action (QMenu *menu, const QIcon& icon, + const QString& text, const char *member, + QWidget *receiver) + { + QAction *a; + QWidget *r = this; + + if (receiver != nullptr) + r = receiver; + + if (menu) + a = menu->addAction (icon, text, r, member); + else + { + a = new QAction (this); + connect (a, SIGNAL (triggered ()), r, member); + } + + addAction (a); // important for shortcut context + a->setShortcutContext (Qt::WidgetWithChildrenShortcut); + + return a; + } + + QMenu* file_editor::add_menu (QMenuBar *p, QString name) + { + QMenu *menu = p->addMenu (name); + + QString base_name = name; // get a copy + // replace intended '&' ("&&") by a temp. string + base_name.replace ("&&", "___octave_amp_replacement___"); + // remove single '&' (shortcut) + base_name.remove ("&"); + // restore intended '&' + base_name.replace ("___octave_amp_replacement___", "&&"); + + // remember names with and without shortcut + m_hash_menu_text[menu] = QStringList () << name << base_name; + + return menu; + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/m-editor/file-editor.h --- a/libgui/src/m-editor/file-editor.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/m-editor/file-editor.h Tue Dec 06 15:45:27 2022 -0500 @@ -46,71 +46,71 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class file_editor; - -// subclassed QTabWidget for using custom tabbar - -class file_editor_tab_widget : public QTabWidget -{ - Q_OBJECT + class base_qobject; + class file_editor; -public: - - file_editor_tab_widget (QWidget *p, file_editor *fe); + // subclassed QTabWidget for using custom tabbar - ~file_editor_tab_widget (void) = default; - - tab_bar * get_tab_bar (void) const; - - std::list tab_list (void) const; -}; + class file_editor_tab_widget : public QTabWidget + { + Q_OBJECT -// the class for the file editor + public: -class file_editor : public file_editor_interface -{ - Q_OBJECT - -public: + file_editor_tab_widget (QWidget *p, file_editor *fe); - // struct that allows to sort with respect to the tab index - struct session_data - { - int index; - int line; - QString file_name; - QString new_file_name; - QString encoding; - QString bookmarks; + ~file_editor_tab_widget (void) = default; - bool operator < (const session_data& other) const - { - return index < other.index; - } + tab_bar * get_tab_bar (void) const; + + std::list tab_list (void) const; }; - struct removed_file_data + // the class for the file editor + + class file_editor : public file_editor_interface { - file_editor_tab *editor_tab; - QString new_file_name; - }; + Q_OBJECT + + public: - file_editor (QWidget *p, base_qobject& oct_qobj); - - ~file_editor (void) = default; + // struct that allows to sort with respect to the tab index + struct session_data + { + int index; + int line; + QString file_name; + QString new_file_name; + QString encoding; + QString bookmarks; - QMenu * get_mru_menu (void) { return m_mru_file_menu; } + bool operator < (const session_data& other) const + { + return index < other.index; + } + }; - QMenu * debug_menu (void) { return m_debug_menu; } + struct removed_file_data + { + file_editor_tab *editor_tab; + QString new_file_name; + }; - QToolBar * toolbar (void) { return m_tool_bar; } + file_editor (QWidget *p, base_qobject& oct_qobj); - QMenuBar * menubar (void) { return m_menu_bar; } + ~file_editor (void) = default; + + QMenu * get_mru_menu (void) { return m_mru_file_menu; } + + QMenu * debug_menu (void) { return m_debug_menu; } - void insert_global_actions (QList); + QToolBar * toolbar (void) { return m_tool_bar; } + + QMenuBar * menubar (void) { return m_menu_bar; } - enum shared_actions_idx + void insert_global_actions (QList); + + enum shared_actions_idx { NEW_SCRIPT_ACTION = 0, NEW_FUNCTION_ACTION, @@ -122,381 +122,381 @@ SELECTALL_ACTION }; - void check_actions (void); - void empty_script (bool startup, bool visible); - void restore_session (gui_settings *settings); + void check_actions (void); + void empty_script (bool startup, bool visible); + void restore_session (void); -signals: + signals: - void fetab_settings_changed (const gui_settings *settings); - void fetab_change_request (const QWidget *ID); - // Save is a ping-pong type of communication - void fetab_save_file (const QWidget *ID, const QString& fileName, - bool remove_on_success); - // No fetab_open, functionality in editor - // No fetab_new, functionality in editor - void fetab_context_help (const QWidget *ID, bool); - void fetab_context_edit (const QWidget *ID); - void fetab_save_file (const QWidget *ID); - void fetab_save_file_as (const QWidget *ID); - void fetab_print_file (const QWidget *ID); - void fetab_run_file (const QWidget *ID, bool step_into = false); - void fetab_context_run (const QWidget *ID); - void fetab_toggle_bookmark (const QWidget *ID); - void fetab_next_bookmark (const QWidget *ID); - void fetab_previous_bookmark (const QWidget *ID); - void fetab_remove_bookmark (const QWidget *ID); - void fetab_toggle_breakpoint (const QWidget *ID); - void fetab_next_breakpoint (const QWidget *ID); - void fetab_previous_breakpoint (const QWidget *ID); - void fetab_remove_all_breakpoints (const QWidget *ID); - void fetab_comment_selected_text (const QWidget *ID, bool); - void fetab_uncomment_selected_text (const QWidget *ID); - void fetab_indent_selected_text (const QWidget *ID); - void fetab_unindent_selected_text (const QWidget *ID); - void fetab_smart_indent_line_or_selected_text (const QWidget *ID); - void fetab_convert_eol (const QWidget *ID, QsciScintilla::EolMode eol_mode); - void fetab_goto_line (const QWidget *ID, int line = -1); - void fetab_move_match_brace (const QWidget *ID, bool select); - void fetab_completion (const QWidget *); - void fetab_insert_debugger_pointer (const QWidget *ID, int line = -1); - void fetab_delete_debugger_pointer (const QWidget *ID, int line = -1); - void fetab_do_breakpoint_marker (bool insert, const QWidget *ID, - int line = -1, const QString& = ""); - void fetab_set_focus (const QWidget *ID); - void fetab_scintilla_command (const QWidget *ID, unsigned int sci_msg); + void fetab_settings_changed (void); + void fetab_change_request (const QWidget *ID); + // Save is a ping-pong type of communication + void fetab_save_file (const QWidget *ID, const QString& fileName, + bool remove_on_success); + // No fetab_open, functionality in editor + // No fetab_new, functionality in editor + void fetab_context_help (const QWidget *ID, bool); + void fetab_context_edit (const QWidget *ID); + void fetab_save_file (const QWidget *ID); + void fetab_save_file_as (const QWidget *ID); + void fetab_print_file (const QWidget *ID); + void fetab_run_file (const QWidget *ID, bool step_into = false); + void fetab_context_run (const QWidget *ID); + void fetab_toggle_bookmark (const QWidget *ID); + void fetab_next_bookmark (const QWidget *ID); + void fetab_previous_bookmark (const QWidget *ID); + void fetab_remove_bookmark (const QWidget *ID); + void fetab_toggle_breakpoint (const QWidget *ID); + void fetab_next_breakpoint (const QWidget *ID); + void fetab_previous_breakpoint (const QWidget *ID); + void fetab_remove_all_breakpoints (const QWidget *ID); + void fetab_comment_selected_text (const QWidget *ID, bool); + void fetab_uncomment_selected_text (const QWidget *ID); + void fetab_indent_selected_text (const QWidget *ID); + void fetab_unindent_selected_text (const QWidget *ID); + void fetab_smart_indent_line_or_selected_text (const QWidget *ID); + void fetab_convert_eol (const QWidget *ID, QsciScintilla::EolMode eol_mode); + void fetab_goto_line (const QWidget *ID, int line = -1); + void fetab_move_match_brace (const QWidget *ID, bool select); + void fetab_completion (const QWidget *); + void fetab_insert_debugger_pointer (const QWidget *ID, int line = -1); + void fetab_delete_debugger_pointer (const QWidget *ID, int line = -1); + void fetab_do_breakpoint_marker (bool insert, const QWidget *ID, + int line = -1, const QString& = ""); + void fetab_set_focus (const QWidget *ID); + void fetab_scintilla_command (const QWidget *ID, unsigned int sci_msg); - void fetab_zoom_in (const QWidget *ID); - void fetab_zoom_out (const QWidget *ID); - void fetab_zoom_normal (const QWidget *ID); + void fetab_zoom_in (const QWidget *ID); + void fetab_zoom_out (const QWidget *ID); + void fetab_zoom_normal (const QWidget *ID); - void fetab_set_directory (const QString& dir); - void fetab_recover_from_exit (void); + void fetab_set_directory (const QString& dir); + void fetab_recover_from_exit (void); - void edit_area_changed (octave_qscintilla *edit_area); + void edit_area_changed (octave_qscintilla *edit_area); - void request_settings_dialog (const QString&); - void request_open_file_external (const QString& file_name, int line); - void file_loaded_signal (void); + void request_settings_dialog (const QString&); + void request_open_file_external (const QString& file_name, int line); + void file_loaded_signal (void); - void editor_tabs_changed_signal (bool, bool); - void request_dbcont_signal (void); + void editor_tabs_changed_signal (bool, bool); + void request_dbcont_signal (void); - void enter_debug_mode_signal (void); - void exit_debug_mode_signal (void); + void enter_debug_mode_signal (void); + void exit_debug_mode_signal (void); - void update_gui_lexer_signal (bool); - void execute_command_in_terminal_signal (const QString&); - void focus_console_after_command_signal (void); - void run_file_signal (const QFileInfo&); - void edit_mfile_request (const QString&, const QString&, const QString&, int); - void debug_quit_signal (void); + void update_gui_lexer_signal (bool); + void execute_command_in_terminal_signal (const QString&); + void focus_console_after_command_signal (void); + void run_file_signal (const QFileInfo&); + void edit_mfile_request (const QString&, const QString&, const QString&, int); + void debug_quit_signal (void); -public slots: + public slots: - void activate (void); - void set_focus (QWidget *fet); - void enable_menu_shortcuts (bool); - void save_session (void); - bool check_closing (void); - void handle_tab_ready_to_close (void); + void activate (void); + void set_focus (QWidget *fet); + void enable_menu_shortcuts (bool); + void save_session (void); + bool check_closing (void); + void handle_tab_ready_to_close (void); - void handle_enter_debug_mode (void); - void handle_exit_debug_mode (void); + void handle_enter_debug_mode (void); + void handle_exit_debug_mode (void); - void request_new_file (const QString& commands); - void request_close_file (bool); - void request_close_all_files (bool); - void request_close_other_files (bool); - void copy_full_file_path (bool); - void request_mru_open_file (QAction *action); - void request_print_file (bool); + void request_new_file (const QString& commands); + void request_close_file (bool); + void request_close_all_files (bool); + void request_close_other_files (bool); + void copy_full_file_path (bool); + void request_mru_open_file (QAction *action); + void request_print_file (bool); - void request_redo (bool); - void request_cut (bool); - void request_context_help (bool); - void request_context_doc (bool); - void request_context_edit (bool); - void request_save_file (bool); - void request_save_file_as (bool); - void request_run_file (bool); - void request_step_into_file (); - void request_context_run (bool); - void request_toggle_bookmark (bool); - void request_next_bookmark (bool); - void request_previous_bookmark (bool); - void request_remove_bookmark (bool); + void request_redo (bool); + void request_cut (bool); + void request_context_help (bool); + void request_context_doc (bool); + void request_context_edit (bool); + void request_save_file (bool); + void request_save_file_as (bool); + void request_run_file (bool); + void request_step_into_file (); + void request_context_run (bool); + void request_toggle_bookmark (bool); + void request_next_bookmark (bool); + void request_previous_bookmark (bool); + void request_remove_bookmark (bool); - void request_move_match_brace (bool); - void request_sel_match_brace (bool); - void request_toggle_breakpoint (bool); - void request_next_breakpoint (bool); - void request_previous_breakpoint (bool); - void request_remove_breakpoint (bool); + void request_move_match_brace (bool); + void request_sel_match_brace (bool); + void request_toggle_breakpoint (bool); + void request_next_breakpoint (bool); + void request_previous_breakpoint (bool); + void request_remove_breakpoint (bool); - void request_delete_start_word (bool); - void request_delete_end_word (bool); - void request_delete_start_line (bool); - void request_delete_end_line (bool); - void request_delete_line (bool); - void request_copy_line (bool); - void request_cut_line (bool); - void request_duplicate_selection (bool); - void request_transpose_line (bool); + void request_delete_start_word (bool); + void request_delete_end_word (bool); + void request_delete_start_line (bool); + void request_delete_end_line (bool); + void request_delete_line (bool); + void request_copy_line (bool); + void request_cut_line (bool); + void request_duplicate_selection (bool); + void request_transpose_line (bool); - void request_comment_selected_text (bool); - void request_uncomment_selected_text (bool); - void request_comment_var_selected_text (bool); + void request_comment_selected_text (bool); + void request_uncomment_selected_text (bool); + void request_comment_var_selected_text (bool); - void request_upper_case (bool); - void request_lower_case (bool); - void request_indent_selected_text (bool); - void request_unindent_selected_text (bool); - void request_smart_indent_line_or_selected_text (void); - void request_conv_eol_windows (bool); - void request_conv_eol_unix (bool); - void request_conv_eol_mac (bool); + void request_upper_case (bool); + void request_lower_case (bool); + void request_indent_selected_text (bool); + void request_unindent_selected_text (bool); + void request_smart_indent_line_or_selected_text (void); + void request_conv_eol_windows (bool); + void request_conv_eol_unix (bool); + void request_conv_eol_mac (bool); - void request_find (bool); - void request_find_next (bool); - void request_find_previous (bool); + void request_find (bool); + void request_find_next (bool); + void request_find_previous (bool); - void request_goto_line (bool); - void request_completion (bool); + void request_goto_line (bool); + void request_completion (bool); - void handle_file_name_changed (const QString& fileName, - const QString& toolTip, - bool modified); - void handle_tab_close_request (int index); - void handle_tab_remove_request (void); - void active_tab_changed (int index); - void handle_editor_state_changed (bool enableCopy, bool is_octave_file, - bool is_modified); - void handle_mru_add_file (const QString& file_name, const QString& encoding); - void check_conflict_save (const QString& fileName, bool remove_on_success); + void handle_file_name_changed (const QString& fileName, + const QString& toolTip, + bool modified); + void handle_tab_close_request (int index); + void handle_tab_remove_request (void); + void active_tab_changed (int index); + void handle_editor_state_changed (bool enableCopy, bool is_octave_file, + bool is_modified); + void handle_mru_add_file (const QString& file_name, const QString& encoding); + void check_conflict_save (const QString& fileName, bool remove_on_success); - void handle_insert_debugger_pointer_request (const QString& file, int line); - void handle_delete_debugger_pointer_request (const QString& file, int line); - void handle_update_breakpoint_marker_request (bool insert, - const QString& file, int line, - const QString& cond); + void handle_insert_debugger_pointer_request (const QString& file, int line); + void handle_delete_debugger_pointer_request (const QString& file, int line); + void handle_update_breakpoint_marker_request (bool insert, + const QString& file, int line, + const QString& cond); - void handle_edit_file_request (const QString& file); + void handle_edit_file_request (const QString& file); - void handle_file_remove (const QString&, const QString&); - void handle_file_renamed (bool load_new = true); + void handle_file_remove (const QString&, const QString&); + void handle_file_renamed (bool load_new = true); - // Tells the editor to react on changed settings. - void notice_settings (const gui_settings *settings); + // Tells the editor to react on changed settings. + void notice_settings (void); - void set_shortcuts (void); + void set_shortcuts (void); - void handle_visibility (bool visible); + void handle_visibility (bool visible); - void update_octave_directory (const QString& dir); + void update_octave_directory (const QString& dir); - void toplevel_change (bool toplevel); + void toplevel_change (bool toplevel); - void handle_autoc_cancelled (void); + void handle_autoc_cancelled (void); - file_editor_tab * reset_focus (void); + file_editor_tab * reset_focus (void); -protected slots: + protected slots: - void copyClipboard (void); - void pasteClipboard (void); - void selectAll (void); - void do_undo (void); + void copyClipboard (void); + void pasteClipboard (void); + void selectAll (void); + void do_undo (void); -private slots: + private slots: - void request_open_file (const QString& fileName, - const QString& encoding = QString (), - int line = -1, bool debug_pointer = false, - bool breakpoint_marker = false, bool insert = true, - const QString& cond = "", int index = -1, - const QString& bookmarks = QString ()); - void request_preferences (bool); - void request_styles_preferences (bool); + void request_open_file (const QString& fileName, + const QString& encoding = QString (), + int line = -1, bool debug_pointer = false, + bool breakpoint_marker = false, bool insert = true, + const QString& cond = "", int index = -1, + const QString& bookmarks = QString ()); + void request_preferences (bool); + void request_styles_preferences (bool); - void show_line_numbers (bool); - void show_white_space (bool); - void show_eol_chars (bool); - void show_indent_guides (bool); - void show_long_line (bool); - void show_toolbar (bool); - void show_statusbar (bool); - void show_hscrollbar (bool); - void zoom_in (bool); - void zoom_out (bool); - void zoom_normal (bool); + void show_line_numbers (bool); + void show_white_space (bool); + void show_eol_chars (bool); + void show_indent_guides (bool); + void show_long_line (bool); + void show_toolbar (bool); + void show_statusbar (bool); + void show_hscrollbar (bool); + void zoom_in (bool); + void zoom_out (bool); + void zoom_normal (bool); - void create_context_menu (QMenu *); - void edit_status_update (bool, bool); + void create_context_menu (QMenu *); + void edit_status_update (bool, bool); -protected: + protected: - void closeEvent (QCloseEvent *event); - void dragEnterEvent (QDragEnterEvent *event); - void dropEvent (QDropEvent *event); - void focusInEvent (QFocusEvent *e); + void closeEvent (QCloseEvent *event); + void dragEnterEvent (QDragEnterEvent *event); + void dropEvent (QDropEvent *event); + void focusInEvent (QFocusEvent *e); -private: + private: - file_editor_tab * make_file_editor_tab (const QString& directory = ""); + file_editor_tab * make_file_editor_tab (const QString& directory = ""); - bool is_editor_console_tabbed (void); - void construct (void); - void add_file_editor_tab (file_editor_tab *f, const QString& fn, - int index = -1); - void mru_menu_update (void); - bool call_custom_editor (const QString& file_name = QString (), int line = -1); + bool is_editor_console_tabbed (void); + void construct (void); + void add_file_editor_tab (file_editor_tab *f, const QString& fn, + int index = -1); + void mru_menu_update (void); + bool call_custom_editor (const QString& file_name = QString (), int line = -1); - void toggle_preference (const gui_pref& preference); + void toggle_preference (const gui_pref& preference); - void handle_dir_remove (const QString& old_name, const QString& new_name); + void handle_dir_remove (const QString& old_name, const QString& new_name); - bool editor_tab_has_focus (void); + bool editor_tab_has_focus (void); - void find_create (void); + void find_create (void); - file_editor_tab * find_tab_widget (const QString& openFileName); - QAction * add_action (QMenu *menu, const QString& text, - const char *member, QWidget *receiver = nullptr); - QAction * add_action (QMenu *menu, const QIcon& icon, const QString& text, - const char *member, QWidget *receiver = nullptr); + file_editor_tab * find_tab_widget (const QString& openFileName); + QAction * add_action (QMenu *menu, const QString& text, + const char *member, QWidget *receiver = nullptr); + QAction * add_action (QMenu *menu, const QIcon& icon, const QString& text, + const char *member, QWidget *receiver = nullptr); - QMenu * add_menu (QMenuBar *p, QString text); + QMenu * add_menu (QMenuBar *p, QString text); - int m_number_of_tabs; - QHash m_hash_menu_text; + int m_number_of_tabs; + QHash m_hash_menu_text; - QString m_ced; + QString m_ced; - QMenuBar *m_menu_bar; - QToolBar *m_tool_bar; - QMenu *m_debug_menu; + QMenuBar *m_menu_bar; + QToolBar *m_tool_bar; + QMenu *m_debug_menu; - QAction *m_new_action; - QAction *m_new_function_action; - QAction *m_open_action; + QAction *m_new_action; + QAction *m_new_function_action; + QAction *m_open_action; - QAction *m_upper_case_action; - QAction *m_lower_case_action; - QAction *m_comment_selection_action; - QAction *m_comment_var_selection_action; - QAction *m_uncomment_selection_action; - QAction *m_indent_selection_action; - QAction *m_unindent_selection_action; - QAction *m_smart_indent_line_or_selection_action; - QAction *m_conv_eol_windows_action; - QAction *m_conv_eol_unix_action; - QAction *m_conv_eol_mac_action; + QAction *m_upper_case_action; + QAction *m_lower_case_action; + QAction *m_comment_selection_action; + QAction *m_comment_var_selection_action; + QAction *m_uncomment_selection_action; + QAction *m_indent_selection_action; + QAction *m_unindent_selection_action; + QAction *m_smart_indent_line_or_selection_action; + QAction *m_conv_eol_windows_action; + QAction *m_conv_eol_unix_action; + QAction *m_conv_eol_mac_action; - QAction *m_copy_action; - QAction *m_cut_action; - QAction *m_paste_action; - QAction *m_selectall_action; - QAction *m_context_help_action; - QAction *m_context_doc_action; + QAction *m_copy_action; + QAction *m_cut_action; + QAction *m_paste_action; + QAction *m_selectall_action; + QAction *m_context_help_action; + QAction *m_context_doc_action; - QAction *m_show_linenum_action; - QAction *m_show_whitespace_action; - QAction *m_show_eol_action; - QAction *m_show_indguide_action; - QAction *m_show_longline_action; - QAction *m_show_toolbar_action; - QAction *m_show_statusbar_action; - QAction *m_show_hscrollbar_action; - QAction *m_zoom_in_action; - QAction *m_zoom_out_action; - QAction *m_zoom_normal_action; + QAction *m_show_linenum_action; + QAction *m_show_whitespace_action; + QAction *m_show_eol_action; + QAction *m_show_indguide_action; + QAction *m_show_longline_action; + QAction *m_show_toolbar_action; + QAction *m_show_statusbar_action; + QAction *m_show_hscrollbar_action; + QAction *m_zoom_in_action; + QAction *m_zoom_out_action; + QAction *m_zoom_normal_action; - QAction *m_delete_start_word_action; - QAction *m_delete_end_word_action; - QAction *m_delete_start_line_action; - QAction *m_delete_end_line_action; - QAction *m_delete_line_action; - QAction *m_copy_line_action; - QAction *m_cut_line_action; - QAction *m_duplicate_selection_action; - QAction *m_transpose_line_action; + QAction *m_delete_start_word_action; + QAction *m_delete_end_word_action; + QAction *m_delete_start_line_action; + QAction *m_delete_end_line_action; + QAction *m_delete_line_action; + QAction *m_copy_line_action; + QAction *m_cut_line_action; + QAction *m_duplicate_selection_action; + QAction *m_transpose_line_action; - QAction *m_find_action; - QAction *m_find_next_action; - QAction *m_find_previous_action; - QAction *m_find_files_action; - QAction *m_goto_line_action; - QAction *m_completion_action; + QAction *m_find_action; + QAction *m_find_next_action; + QAction *m_find_previous_action; + QAction *m_find_files_action; + QAction *m_goto_line_action; + QAction *m_completion_action; - QAction *m_move_to_matching_brace; - QAction *m_sel_to_matching_brace; - QAction *m_next_bookmark_action; - QAction *m_previous_bookmark_action; - QAction *m_toggle_bookmark_action; - QAction *m_remove_bookmark_action; + QAction *m_move_to_matching_brace; + QAction *m_sel_to_matching_brace; + QAction *m_next_bookmark_action; + QAction *m_previous_bookmark_action; + QAction *m_toggle_bookmark_action; + QAction *m_remove_bookmark_action; - QAction *m_print_action; - QAction *m_run_action; - QAction *m_run_selection_action; + QAction *m_print_action; + QAction *m_run_action; + QAction *m_run_selection_action; - QAction *m_edit_function_action; - QAction *m_popdown_mru_action; - QAction *m_save_action; - QAction *m_save_as_action; - QAction *m_close_action; - QAction *m_close_all_action; - QAction *m_close_others_action; + QAction *m_edit_function_action; + QAction *m_popdown_mru_action; + QAction *m_save_action; + QAction *m_save_as_action; + QAction *m_close_action; + QAction *m_close_all_action; + QAction *m_close_others_action; - QAction *m_redo_action; - QAction *m_undo_action; + QAction *m_redo_action; + QAction *m_undo_action; - QAction *m_preferences_action; - QAction *m_styles_preferences_action; + QAction *m_preferences_action; + QAction *m_styles_preferences_action; - QAction *m_switch_left_tab_action; - QAction *m_switch_right_tab_action; - QAction *m_move_tab_left_action; - QAction *m_move_tab_right_action; - QAction *m_sort_tabs_action; + QAction *m_switch_left_tab_action; + QAction *m_switch_right_tab_action; + QAction *m_move_tab_left_action; + QAction *m_move_tab_right_action; + QAction *m_sort_tabs_action; - QAction *m_toggle_breakpoint_action; - QAction *m_next_breakpoint_action; - QAction *m_previous_breakpoint_action; - QAction *m_remove_all_breakpoints_action; + QAction *m_toggle_breakpoint_action; + QAction *m_next_breakpoint_action; + QAction *m_previous_breakpoint_action; + QAction *m_remove_all_breakpoints_action; - bool m_copy_action_enabled; - bool m_undo_action_enabled; - bool m_is_octave_file; - bool m_current_tab_modified; + bool m_copy_action_enabled; + bool m_undo_action_enabled; + bool m_is_octave_file; + bool m_current_tab_modified; - QMenu *m_edit_menu; - QMenu *m_edit_cmd_menu; - QMenu *m_edit_fmt_menu; - QMenu *m_edit_nav_menu; - QMenu *m_fileMenu; - QMenu *m_view_editor_menu; + QMenu *m_edit_menu; + QMenu *m_edit_cmd_menu; + QMenu *m_edit_fmt_menu; + QMenu *m_edit_nav_menu; + QMenu *m_fileMenu; + QMenu *m_view_editor_menu; - file_editor_tab_widget *m_tab_widget; + file_editor_tab_widget *m_tab_widget; - int m_marker_breakpoint; + int m_marker_breakpoint; - bool m_closing_canceled; - bool m_closed; - bool m_no_focus; - bool m_editor_ready; + bool m_closing_canceled; + bool m_closed; + bool m_no_focus; + bool m_editor_ready; - enum { MaxMRUFiles = 10 }; - QMenu *m_mru_file_menu; - QAction *m_mru_file_actions[MaxMRUFiles]; - QStringList m_mru_files; - QStringList m_mru_files_encodings; + enum { MaxMRUFiles = 10 }; + QMenu *m_mru_file_menu; + QAction *m_mru_file_actions[MaxMRUFiles]; + QStringList m_mru_files; + QStringList m_mru_files_encodings; - QPointer m_find_dialog; + QPointer m_find_dialog; - // List of data on temporarily closed files for later reloading. - QList m_tmp_closed_files; -}; + // List of data on temporarily closed files for later reloading. + QList m_tmp_closed_files; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/m-editor/find-dialog.cc --- a/libgui/src/m-editor/find-dialog.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/m-editor/find-dialog.cc Tue Dec 06 15:45:27 2022 -0500 @@ -84,589 +84,585 @@ #include "gui-preferences-ed.h" #include "gui-utils.h" #include "resource-manager.h" -#include "octave-qobject.h" OCTAVE_BEGIN_NAMESPACE(octave) -find_dialog::find_dialog (base_qobject& oct_qobj, - octave_dock_widget *ed, QWidget *p) -: QDialog (p), m_octave_qobj (oct_qobj), m_editor (ed), - m_in_sel (false), m_sel_beg (-1), m_sel_end (-1) -{ - setWindowTitle (tr ("Editor: Find and Replace")); + find_dialog::find_dialog (octave_dock_widget *ed, QWidget *p) + : QDialog (p), m_editor (ed), m_in_sel (false), + m_sel_beg (-1), m_sel_end (-1) + { + setWindowTitle (tr ("Editor: Find and Replace")); - m_search_label = new QLabel (tr ("Find &what:")); - m_search_line_edit = new QComboBox (this); - m_search_line_edit->setToolTip (tr ("Enter text to search for")); - m_search_line_edit->setEditable (true); - m_search_line_edit->setMaxCount (m_mru_length); - m_search_line_edit->completer ()->setCaseSensitivity (Qt::CaseSensitive); - m_search_label->setBuddy (m_search_line_edit); + m_search_label = new QLabel (tr ("Find &what:")); + m_search_line_edit = new QComboBox (this); + m_search_line_edit->setToolTip (tr ("Enter text to search for")); + m_search_line_edit->setEditable (true); + m_search_line_edit->setMaxCount (m_mru_length); + m_search_line_edit->completer ()->setCaseSensitivity (Qt::CaseSensitive); + m_search_label->setBuddy (m_search_line_edit); - m_replace_label = new QLabel (tr ("Re&place with:")); - m_replace_line_edit = new QComboBox (this); - m_replace_line_edit->setToolTip (tr ("Enter new text replacing search hits")); - m_replace_line_edit->setEditable (true); - m_replace_line_edit->setMaxCount (m_mru_length); - m_replace_line_edit->completer ()->setCaseSensitivity (Qt::CaseSensitive); - m_replace_label->setBuddy (m_replace_line_edit); + m_replace_label = new QLabel (tr ("Re&place with:")); + m_replace_line_edit = new QComboBox (this); + m_replace_line_edit->setToolTip (tr ("Enter new text replacing search hits")); + m_replace_line_edit->setEditable (true); + m_replace_line_edit->setMaxCount (m_mru_length); + m_replace_line_edit->completer ()->setCaseSensitivity (Qt::CaseSensitive); + m_replace_label->setBuddy (m_replace_line_edit); - int width = QFontMetrics (m_search_line_edit->font ()).averageCharWidth(); - m_search_line_edit->setFixedWidth (20*width); - m_replace_line_edit->setFixedWidth (20*width); + int width = QFontMetrics (m_search_line_edit->font ()).averageCharWidth(); + m_search_line_edit->setFixedWidth (20*width); + m_replace_line_edit->setFixedWidth (20*width); - m_case_check_box = new QCheckBox (tr ("Match &case")); - m_from_start_check_box = new QCheckBox (tr ("Search from &start")); - m_wrap_check_box = new QCheckBox (tr ("&Wrap while searching")); - m_wrap_check_box->setChecked (true); - m_find_next_button = new QPushButton (tr ("&Find Next")); - m_find_prev_button = new QPushButton (tr ("Find &Previous")); - m_replace_button = new QPushButton (tr ("&Replace")); - m_replace_all_button = new QPushButton (tr ("Replace &All")); + m_case_check_box = new QCheckBox (tr ("Match &case")); + m_from_start_check_box = new QCheckBox (tr ("Search from &start")); + m_wrap_check_box = new QCheckBox (tr ("&Wrap while searching")); + m_wrap_check_box->setChecked (true); + m_find_next_button = new QPushButton (tr ("&Find Next")); + m_find_prev_button = new QPushButton (tr ("Find &Previous")); + m_replace_button = new QPushButton (tr ("&Replace")); + m_replace_all_button = new QPushButton (tr ("Replace &All")); - m_more_button = new QPushButton (tr ("&More...")); - m_more_button->setCheckable (true); - m_more_button->setAutoDefault (false); + m_more_button = new QPushButton (tr ("&More...")); + m_more_button->setCheckable (true); + m_more_button->setAutoDefault (false); - m_button_box = new QDialogButtonBox (Qt::Vertical); - m_button_box->addButton (m_find_next_button, QDialogButtonBox::ActionRole); - m_button_box->addButton (m_find_prev_button, QDialogButtonBox::ActionRole); - m_button_box->addButton (m_replace_button, QDialogButtonBox::ActionRole); - m_button_box->addButton (m_replace_all_button, QDialogButtonBox::ActionRole); - m_button_box->addButton (m_more_button, QDialogButtonBox::ActionRole); - m_button_box->addButton (QDialogButtonBox::Close); + m_button_box = new QDialogButtonBox (Qt::Vertical); + m_button_box->addButton (m_find_next_button, QDialogButtonBox::ActionRole); + m_button_box->addButton (m_find_prev_button, QDialogButtonBox::ActionRole); + m_button_box->addButton (m_replace_button, QDialogButtonBox::ActionRole); + m_button_box->addButton (m_replace_all_button, QDialogButtonBox::ActionRole); + m_button_box->addButton (m_more_button, QDialogButtonBox::ActionRole); + m_button_box->addButton (QDialogButtonBox::Close); - m_extension = new QWidget (this); - m_whole_words_check_box = new QCheckBox (tr ("&Whole words")); - m_regex_check_box = new QCheckBox (tr ("Regular E&xpressions")); - m_backward_check_box = new QCheckBox (tr ("Search &backward")); - m_search_selection_check_box = new QCheckBox (tr ("Search se&lection")); - m_search_selection_check_box->setCheckable (true); + m_extension = new QWidget (this); + m_whole_words_check_box = new QCheckBox (tr ("&Whole words")); + m_regex_check_box = new QCheckBox (tr ("Regular E&xpressions")); + m_backward_check_box = new QCheckBox (tr ("Search &backward")); + m_search_selection_check_box = new QCheckBox (tr ("Search se&lection")); + m_search_selection_check_box->setCheckable (true); - connect (m_find_next_button, &QPushButton::clicked, - this, &find_dialog::find_next); - connect (m_find_prev_button, &QPushButton::clicked, - this, &find_dialog::find_prev); - connect (m_more_button, &QPushButton::toggled, - m_extension, &QWidget::setVisible); - connect (m_replace_button, &QPushButton::clicked, - this, &find_dialog::replace); - connect (m_replace_all_button, &QPushButton::clicked, - this, &find_dialog::replace_all); - connect (m_backward_check_box, &QCheckBox::stateChanged, - this, &find_dialog::handle_backward_search_changed); - connect (m_button_box, &QDialogButtonBox::rejected, - this, &find_dialog::close); + connect (m_find_next_button, &QPushButton::clicked, + this, &find_dialog::find_next); + connect (m_find_prev_button, &QPushButton::clicked, + this, &find_dialog::find_prev); + connect (m_more_button, &QPushButton::toggled, + m_extension, &QWidget::setVisible); + connect (m_replace_button, &QPushButton::clicked, + this, &find_dialog::replace); + connect (m_replace_all_button, &QPushButton::clicked, + this, &find_dialog::replace_all); + connect (m_backward_check_box, &QCheckBox::stateChanged, + this, &find_dialog::handle_backward_search_changed); + connect (m_button_box, &QDialogButtonBox::rejected, + this, &find_dialog::close); - connect (m_search_selection_check_box, &QCheckBox::stateChanged, - this, &find_dialog::handle_sel_search_changed); + connect (m_search_selection_check_box, &QCheckBox::stateChanged, + this, &find_dialog::handle_sel_search_changed); - QVBoxLayout *extension_layout = new QVBoxLayout (); - extension_layout->setMargin (0); - extension_layout->addWidget (m_whole_words_check_box); - extension_layout->addWidget (m_backward_check_box); - extension_layout->addWidget (m_search_selection_check_box); - m_extension->setLayout (extension_layout); + QVBoxLayout *extension_layout = new QVBoxLayout (); + extension_layout->setMargin (0); + extension_layout->addWidget (m_whole_words_check_box); + extension_layout->addWidget (m_backward_check_box); + extension_layout->addWidget (m_search_selection_check_box); + m_extension->setLayout (extension_layout); - QGridLayout *top_left_layout = new QGridLayout; - top_left_layout->addWidget (m_search_label, 1, 1); - top_left_layout->addWidget (m_search_line_edit, 1, 2); - top_left_layout->addWidget (m_replace_label, 2, 1); - top_left_layout->addWidget (m_replace_line_edit, 2, 2); + QGridLayout *top_left_layout = new QGridLayout; + top_left_layout->addWidget (m_search_label, 1, 1); + top_left_layout->addWidget (m_search_line_edit, 1, 2); + top_left_layout->addWidget (m_replace_label, 2, 1); + top_left_layout->addWidget (m_replace_line_edit, 2, 2); - QVBoxLayout *left_layout = new QVBoxLayout; - left_layout->addLayout (top_left_layout); - left_layout->insertStretch (1, 5); - left_layout->addWidget (m_case_check_box); - left_layout->addWidget (m_from_start_check_box); - left_layout->addWidget (m_wrap_check_box); - left_layout->addWidget (m_regex_check_box); + QVBoxLayout *left_layout = new QVBoxLayout; + left_layout->addLayout (top_left_layout); + left_layout->insertStretch (1, 5); + left_layout->addWidget (m_case_check_box); + left_layout->addWidget (m_from_start_check_box); + left_layout->addWidget (m_wrap_check_box); + left_layout->addWidget (m_regex_check_box); - QGridLayout *main_layout = new QGridLayout; - main_layout->setSizeConstraint (QLayout::SetFixedSize); - main_layout->addLayout (left_layout, 0, 0); - main_layout->addWidget (m_button_box, 0, 1); - main_layout->addWidget (m_extension, 1, 0); - setLayout (main_layout); + QGridLayout *main_layout = new QGridLayout; + main_layout->setSizeConstraint (QLayout::SetFixedSize); + main_layout->addLayout (left_layout, 0, 0); + main_layout->addWidget (m_button_box, 0, 1); + main_layout->addWidget (m_extension, 1, 0); + setLayout (main_layout); - m_extension->hide (); - m_find_next_button->setDefault (true); - m_find_result_available = false; - m_rep_all = 0; - m_rep_active = false; + m_extension->hide (); + m_find_next_button->setDefault (true); + m_find_result_available = false; + m_rep_all = 0; + m_rep_active = false; - // Connect required external signals - connect (ed, SIGNAL (edit_area_changed (octave_qscintilla *)), - this, SLOT (update_edit_area (octave_qscintilla *))); + // Connect required external signals + connect (ed, SIGNAL (edit_area_changed (octave_qscintilla *)), + this, SLOT (update_edit_area (octave_qscintilla *))); - setWindowModality (Qt::NonModal); + setWindowModality (Qt::NonModal); - setAttribute(Qt::WA_ShowWithoutActivating); - setAttribute(Qt::WA_DeleteOnClose); -} + setAttribute(Qt::WA_ShowWithoutActivating); + setAttribute(Qt::WA_DeleteOnClose); + } -// The edit_area has changed: update relevant data of the file dialog -void find_dialog::update_edit_area (octave_qscintilla *edit_area) -{ - m_edit_area = edit_area; - m_search_selection_check_box->setEnabled (edit_area->hasSelectedText ()); + // The edit_area has changed: update relevant data of the file dialog + void find_dialog::update_edit_area (octave_qscintilla *edit_area) + { + m_edit_area = edit_area; + m_search_selection_check_box->setEnabled (edit_area->hasSelectedText ()); - connect (m_edit_area, SIGNAL (copyAvailable (bool)), - this, SLOT (handle_selection_changed (bool)), - Qt::UniqueConnection); -} + connect (m_edit_area, SIGNAL (copyAvailable (bool)), + this, SLOT (handle_selection_changed (bool)), + Qt::UniqueConnection); + } -void find_dialog::save_settings () -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *s = rmgr.get_settings (); + void find_dialog::save_settings () + { + gui_settings settings; - // Save position - QPoint dlg_pos = pos (); + // Save position + QPoint dlg_pos = pos (); #if defined (Q_OS_WIN32) - int y = dlg_pos.y (); + int y = dlg_pos.y (); #else - int y = dlg_pos.y () - geometry ().height () + frameGeometry ().height (); + int y = dlg_pos.y () - geometry ().height () + frameGeometry ().height (); #endif - m_last_position = QPoint (dlg_pos.x (), y); - - s->setValue (ed_fdlg_pos.key, m_last_position); - - // Is current search/replace text in the mru list? - mru_update (m_search_line_edit); - mru_update (m_replace_line_edit); + m_last_position = QPoint (dlg_pos.x (), y); - // Store mru lists - QStringList mru; - for (int i = 0; i < m_search_line_edit->count (); i++) - mru.append (m_search_line_edit->itemText (i)); - s->setValue (ed_fdlg_search.key, mru); - - mru.clear (); - for (int i = 0; i < m_replace_line_edit->count (); i++) - mru.append (m_replace_line_edit->itemText (i)); - s->setValue (ed_fdlg_replace.key, mru); + settings.setValue (ed_fdlg_pos.key, m_last_position); - // Store dialog's options - int opts = 0 - + m_extension->isVisible () * FIND_DLG_MORE - + m_case_check_box->isChecked () * FIND_DLG_CASE - + m_from_start_check_box->isChecked () * FIND_DLG_START - + m_wrap_check_box->isChecked () * FIND_DLG_WRAP - + m_regex_check_box->isChecked () * FIND_DLG_REGX - + m_whole_words_check_box->isChecked () * FIND_DLG_WORDS - + m_backward_check_box->isChecked () * FIND_DLG_BACK - + m_search_selection_check_box->isChecked () * FIND_DLG_SEL; - s->setValue (ed_fdlg_opts.key, opts); - - s->sync (); -} - -void find_dialog::restore_settings (QPoint ed_bottom_right) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *s = rmgr.get_settings (); - - // Get mru lists for search and replace text - QStringList mru = s->value (ed_fdlg_search.key).toStringList (); - while (mru.length () > m_mru_length) - mru.removeLast (); - m_search_line_edit->addItems (mru); + // Is current search/replace text in the mru list? + mru_update (m_search_line_edit); + mru_update (m_replace_line_edit); - mru = s->value (ed_fdlg_replace.key).toStringList (); - while (mru.length () > m_mru_length) - mru.removeLast (); - m_replace_line_edit->addItems (mru); - - // Get the dialog's options - int opts = s->value (ed_fdlg_opts.key, ed_fdlg_opts.def).toInt (); - - m_extension->setVisible (FIND_DLG_MORE & opts); - m_case_check_box->setChecked (FIND_DLG_CASE & opts); - m_from_start_check_box->setChecked (FIND_DLG_START & opts); - m_wrap_check_box->setChecked (FIND_DLG_WRAP & opts); - m_regex_check_box->setChecked (FIND_DLG_REGX & opts); - m_whole_words_check_box->setChecked (FIND_DLG_WORDS & opts); - m_backward_check_box->setChecked (FIND_DLG_BACK & opts); - m_search_selection_check_box->setChecked (FIND_DLG_SEL & opts); - - // Default position: lower right of editor's position - int xp = ed_bottom_right.x () - sizeHint ().width (); - int yp = ed_bottom_right.y () - sizeHint ().height (); - QRect default_geometry (xp, yp, sizeHint ().width (), sizeHint ().height ()); + // Store mru lists + QStringList mru; + for (int i = 0; i < m_search_line_edit->count (); i++) + mru.append (m_search_line_edit->itemText (i)); + settings.setValue (ed_fdlg_search.key, mru); - // Last position from settings - m_last_position = s->value (ed_fdlg_pos.key, QPoint (xp, yp)).toPoint (); - QRect last_geometry (m_last_position, - QSize (sizeHint ().width (), sizeHint ().height ())); - - // Make sure we are on the screen - adjust_to_screen (last_geometry, default_geometry); - m_last_position = last_geometry.topLeft (); - - move (m_last_position); -} - -// set text of "search from start" depending on backward search -void find_dialog::handle_backward_search_changed (int backward) -{ - if (backward) - m_from_start_check_box->setText (tr ("Search from end")); - else - m_from_start_check_box->setText (tr ("Search from start")); -} - -// search text has changed: reset the search -void find_dialog::handle_search_text_changed (void) -{ - // Return if nothing has changed - if (m_search_line_edit->currentText () == m_search_line_edit->itemText (0)) - return; - - if (m_search_selection_check_box->isChecked ()) - m_find_result_available = false; + mru.clear (); + for (int i = 0; i < m_replace_line_edit->count (); i++) + mru.append (m_replace_line_edit->itemText (i)); + settings.setValue (ed_fdlg_replace.key, mru); - mru_update (m_search_line_edit); -} - -// replaced text has changed: reset the search -void find_dialog::handle_replace_text_changed (void) -{ - // Return if nothing has changed - if (m_replace_line_edit->currentText () == m_replace_line_edit->itemText (0)) - return; - - mru_update (m_replace_line_edit); -} - -// Update the mru list -void find_dialog::mru_update (QComboBox *mru) -{ - // Remove possible empty entries from the mru list - int index; - while ((index = mru->findText (QString ())) >= 0) - mru->removeItem (index); - - // Get current text and return if it is empty - QString text = mru->currentText (); - - if (text.isEmpty ()) - return; - - // Remove occurrences of the current text in the mru list - while ((index = mru->findText (text)) >= 0) - mru->removeItem (index); - - // Remove the last entry from the end if the list is full - if (mru->count () == m_mru_length) - mru->removeItem (m_mru_length -1); - - // Insert new item at the beginning and set it as current item - mru->insertItem (0, text); - mru->setCurrentIndex (0); -} - -void find_dialog::handle_sel_search_changed (int selected) -{ - m_from_start_check_box->setEnabled (! selected); - m_find_result_available = false; -} + // Store dialog's options + int opts = 0 + + m_extension->isVisible () * FIND_DLG_MORE + + m_case_check_box->isChecked () * FIND_DLG_CASE + + m_from_start_check_box->isChecked () * FIND_DLG_START + + m_wrap_check_box->isChecked () * FIND_DLG_WRAP + + m_regex_check_box->isChecked () * FIND_DLG_REGX + + m_whole_words_check_box->isChecked () * FIND_DLG_WORDS + + m_backward_check_box->isChecked () * FIND_DLG_BACK + + m_search_selection_check_box->isChecked () * FIND_DLG_SEL; + settings.setValue (ed_fdlg_opts.key, opts); -void find_dialog::handle_selection_changed (bool has_selected) -{ - if (m_rep_active) - return; - - m_search_selection_check_box->setEnabled (has_selected); - m_find_result_available = false; -} - -// initialize search text with selected text if this is in one single line -void find_dialog::init_search_text (void) -{ - if (m_edit_area && m_edit_area->hasSelectedText ()) - { - int lbeg, lend, cbeg, cend; - m_edit_area->getSelection (&lbeg, &cbeg, &lend, &cend); - if (lbeg == lend) - m_search_line_edit->setCurrentText (m_edit_area->selectedText ()); - } - - // set focus to "Find what" and select all text - m_search_line_edit->setFocus (); - m_search_line_edit->lineEdit ()->selectAll (); + settings.sync (); + } - // Default to "find" next time. - // Otherwise, it defaults to the last action, which may be "replace all". - m_find_next_button->setDefault (true); -} - -void find_dialog::find_next (void) -{ - find (! m_backward_check_box->isChecked ()); -} + void find_dialog::restore_settings (QPoint ed_bottom_right) + { + gui_settings settings; -void find_dialog::find_prev (void) -{ - find (m_backward_check_box->isChecked ()); -} - -void find_dialog::find (bool forward) -{ - if (! m_edit_area) - return; - - handle_search_text_changed (); - - // line adn col: -1 means search starts at current position - int line = -1, col = -1; - - bool do_wrap = m_wrap_check_box->isChecked (); - bool do_forward = forward; + // Get mru lists for search and replace text + QStringList mru = settings.value (ed_fdlg_search.key).toStringList (); + while (mru.length () > m_mru_length) + mru.removeLast (); + m_search_line_edit->addItems (mru); - // Initialize the selection begin and end if it is the first search - if (! m_find_result_available) - { - if (m_search_selection_check_box->isChecked () - && m_edit_area->hasSelectedText ()) - { - int l1, c1, l2, c2; - m_edit_area->getSelection (&l1, &c1, &l2, &c2); + mru = settings.value (ed_fdlg_replace.key).toStringList (); + while (mru.length () > m_mru_length) + mru.removeLast (); + m_replace_line_edit->addItems (mru); - // Store the position of the selection - m_sel_beg = m_edit_area->positionFromLineIndex (l1, c1); - m_sel_end = m_edit_area->positionFromLineIndex (l2, c2); - m_in_sel = true; - } - else - m_in_sel = false; - } + // Get the dialog's options + int opts = settings.value (ed_fdlg_opts.key, ed_fdlg_opts.def).toInt (); - // Get the correct line/col for beginning the search - if (m_rep_all) - { - // Replace All - if (m_rep_all == 1) - { - // Start at the beginning of file/sel if it is the first try - if (m_in_sel) - m_edit_area->lineIndexFromPosition (m_sel_beg, &line, &col); - else - { - line = 0; - col = 0; - } - } - do_wrap = false; // Never wrap when replacing all - } - else - { - // Normal search (not replace all): calculate start position of - // search (in file or selection) - if (m_from_start_check_box->isChecked () - || (m_in_sel && (! m_find_result_available))) - { - // From the beginning or the end of file/sel - if (do_forward) - { - // From the beginning - if (m_in_sel) - m_edit_area->lineIndexFromPosition (m_sel_beg, &line, &col); - else - { - line = 0; - col = 0; - } - } - else - { - // From the end - if (m_in_sel) - m_edit_area->lineIndexFromPosition (m_sel_end, &line, &col); - else - { - line = m_edit_area->lines () - 1; - col = m_edit_area->text (line).length () - 1; - if (col == -1) - col = 0; - } - } - } - else if (! do_forward) - { - // Start from where the cursor is. Fix QScintilla's cursor - // positioning - m_edit_area->getCursorPosition (&line, &col); - if (m_find_result_available && m_edit_area->hasSelectedText ()) - { - int currpos = m_edit_area->positionFromLineIndex (line, col); - currpos -= (m_search_line_edit->currentText ().length ()); - if (currpos < 0) - currpos = 0; - m_edit_area->lineIndexFromPosition (currpos, &line, &col); - } - } - } + m_extension->setVisible (FIND_DLG_MORE & opts); + m_case_check_box->setChecked (FIND_DLG_CASE & opts); + m_from_start_check_box->setChecked (FIND_DLG_START & opts); + m_wrap_check_box->setChecked (FIND_DLG_WRAP & opts); + m_regex_check_box->setChecked (FIND_DLG_REGX & opts); + m_whole_words_check_box->setChecked (FIND_DLG_WORDS & opts); + m_backward_check_box->setChecked (FIND_DLG_BACK & opts); + m_search_selection_check_box->setChecked (FIND_DLG_SEL & opts); - // Do the search - m_find_result_available - = m_edit_area->findFirst (m_search_line_edit->currentText (), - m_regex_check_box->isChecked (), - m_case_check_box->isChecked (), - m_whole_words_check_box->isChecked (), - do_wrap, - do_forward, - line, col, - true -#if defined (HAVE_QSCI_VERSION_2_6_0) - , true -#endif - ); + // Default position: lower right of editor's position + int xp = ed_bottom_right.x () - sizeHint ().width (); + int yp = ed_bottom_right.y () - sizeHint ().height (); + QRect default_geometry (xp, yp, sizeHint ().width (), sizeHint ().height ()); - if (m_find_result_available) - { - // Search successful: reset search-from-start box and check for - // the current selection - m_from_start_check_box->setChecked (0); - - if (m_in_sel) - { - m_edit_area->getCursorPosition (&line, &col); - int pos = m_edit_area->positionFromLineIndex (line, col); - - int l1, c1, l2, c2; - m_edit_area->lineIndexFromPosition (m_sel_beg, &l1, &c1); - m_edit_area->lineIndexFromPosition (m_sel_end, &l2, &c2); - m_edit_area->show_selection_markers (l1, c1, l2, c2); - - // Check if new start position is still within the selection - m_find_result_available = pos >= m_sel_beg && pos <= m_sel_end; - } - } + // Last position from settings + m_last_position = settings.value (ed_fdlg_pos.key, QPoint (xp, yp)).toPoint (); + QRect last_geometry (m_last_position, + QSize (sizeHint ().width (), sizeHint ().height ())); - // No more search hits - if (! m_find_result_available) - { - if (m_in_sel) - { - // Restore real selection and remove marker for selection - int l1, c1, l2, c2; - m_edit_area->lineIndexFromPosition (m_sel_beg, &l1, &c1); - m_edit_area->lineIndexFromPosition (m_sel_end, &l2, &c2); - m_edit_area->setSelection (l1, c1, l2, c2); - m_edit_area->clear_selection_markers (); - } + // Make sure we are on the screen + adjust_to_screen (last_geometry, default_geometry); + m_last_position = last_geometry.topLeft (); - // Display message if not replace all - if (! m_rep_all) - no_matches_message (); - } - -} - -void find_dialog::do_replace (void) -{ - if (m_edit_area) - { - m_rep_active = true; // changes in selection not made by the user + move (m_last_position); + } - m_edit_area->replace (m_replace_line_edit->currentText ()); - if (m_in_sel) - { - // Update the length of the selection - m_sel_end = m_sel_end - - m_search_line_edit->currentText ().toUtf8 ().size () - + m_replace_line_edit->currentText ().toUtf8 ().size (); - } - - m_rep_active = false; - } -} - -void find_dialog::replace (void) -{ - if (m_edit_area) - { - handle_replace_text_changed (); - - // Do the replace if we have selected text - if (m_find_result_available && m_edit_area->hasSelectedText ()) - do_replace (); - - find_next (); - } -} + // set text of "search from start" depending on backward search + void find_dialog::handle_backward_search_changed (int backward) + { + if (backward) + m_from_start_check_box->setText (tr ("Search from end")); + else + m_from_start_check_box->setText (tr ("Search from start")); + } -void find_dialog::replace_all (void) -{ - int line, col; - - if (m_edit_area) - { - handle_replace_text_changed (); - - m_edit_area->getCursorPosition (&line, &col); - - m_rep_all = 1; - find_next (); // find first occurrence (forward) + // search text has changed: reset the search + void find_dialog::handle_search_text_changed (void) + { + // Return if nothing has changed + if (m_search_line_edit->currentText () == m_search_line_edit->itemText (0)) + return; - m_edit_area->beginUndoAction (); - while (m_find_result_available) // while search string is found - { - do_replace (); - m_rep_all++; // inc counter - find_next (); // find next - } - m_edit_area->endUndoAction (); - - QMessageBox msg_box (QMessageBox::Information, tr ("Replace Result"), - tr ("%1 items replaced").arg (m_rep_all-1), - QMessageBox::Ok, this); - msg_box.exec (); - - m_rep_all = 0; + if (m_search_selection_check_box->isChecked ()) m_find_result_available = false; - if (! m_search_selection_check_box->isChecked ()) - m_edit_area->setCursorPosition (line, col); - } -} + mru_update (m_search_line_edit); + } + + // replaced text has changed: reset the search + void find_dialog::handle_replace_text_changed (void) + { + // Return if nothing has changed + if (m_replace_line_edit->currentText () == m_replace_line_edit->itemText (0)) + return; + + mru_update (m_replace_line_edit); + } + + // Update the mru list + void find_dialog::mru_update (QComboBox *mru) + { + // Remove possible empty entries from the mru list + int index; + while ((index = mru->findText (QString ())) >= 0) + mru->removeItem (index); + + // Get current text and return if it is empty + QString text = mru->currentText (); + + if (text.isEmpty ()) + return; + + // Remove occurrences of the current text in the mru list + while ((index = mru->findText (text)) >= 0) + mru->removeItem (index); + + // Remove the last entry from the end if the list is full + if (mru->count () == m_mru_length) + mru->removeItem (m_mru_length -1); + + // Insert new item at the beginning and set it as current item + mru->insertItem (0, text); + mru->setCurrentIndex (0); + } + + void find_dialog::handle_sel_search_changed (int selected) + { + m_from_start_check_box->setEnabled (! selected); + m_find_result_available = false; + } + + void find_dialog::handle_selection_changed (bool has_selected) + { + if (m_rep_active) + return; + + m_search_selection_check_box->setEnabled (has_selected); + m_find_result_available = false; + } -void find_dialog::no_matches_message (void) -{ - QMessageBox msg_box (QMessageBox::Information, tr ("Find Result"), - tr ("No more matches found"), QMessageBox::Ok, this); - msg_box.exec (); -} + // initialize search text with selected text if this is in one single line + void find_dialog::init_search_text (void) + { + if (m_edit_area && m_edit_area->hasSelectedText ()) + { + int lbeg, lend, cbeg, cend; + m_edit_area->getSelection (&lbeg, &cbeg, &lend, &cend); + if (lbeg == lend) + m_search_line_edit->setCurrentText (m_edit_area->selectedText ()); + } + + // set focus to "Find what" and select all text + m_search_line_edit->setFocus (); + m_search_line_edit->lineEdit ()->selectAll (); + + // Default to "find" next time. + // Otherwise, it defaults to the last action, which may be "replace all". + m_find_next_button->setDefault (true); + } + + void find_dialog::find_next (void) + { + find (! m_backward_check_box->isChecked ()); + } + + void find_dialog::find_prev (void) + { + find (m_backward_check_box->isChecked ()); + } -void find_dialog::reject () -{ - close (); -} + void find_dialog::find (bool forward) + { + if (! m_edit_area) + return; + + handle_search_text_changed (); + + // line adn col: -1 means search starts at current position + int line = -1, col = -1; + + bool do_wrap = m_wrap_check_box->isChecked (); + bool do_forward = forward; + + // Initialize the selection begin and end if it is the first search + if (! m_find_result_available) + { + if (m_search_selection_check_box->isChecked () + && m_edit_area->hasSelectedText ()) + { + int l1, c1, l2, c2; + m_edit_area->getSelection (&l1, &c1, &l2, &c2); + + // Store the position of the selection + m_sel_beg = m_edit_area->positionFromLineIndex (l1, c1); + m_sel_end = m_edit_area->positionFromLineIndex (l2, c2); + m_in_sel = true; + } + else + m_in_sel = false; + } -void find_dialog::closeEvent (QCloseEvent *e) -{ - save_settings (); - e->accept (); -} + // Get the correct line/col for beginning the search + if (m_rep_all) + { + // Replace All + if (m_rep_all == 1) + { + // Start at the beginning of file/sel if it is the first try + if (m_in_sel) + m_edit_area->lineIndexFromPosition (m_sel_beg, &line, &col); + else + { + line = 0; + col = 0; + } + } + do_wrap = false; // Never wrap when replacing all + } + else + { + // Normal search (not replace all): calculate start position of + // search (in file or selection) + if (m_from_start_check_box->isChecked () + || (m_in_sel && (! m_find_result_available))) + { + // From the beginning or the end of file/sel + if (do_forward) + { + // From the beginning + if (m_in_sel) + m_edit_area->lineIndexFromPosition (m_sel_beg, &line, &col); + else + { + line = 0; + col = 0; + } + } + else + { + // From the end + if (m_in_sel) + m_edit_area->lineIndexFromPosition (m_sel_end, &line, &col); + else + { + line = m_edit_area->lines () - 1; + col = m_edit_area->text (line).length () - 1; + if (col == -1) + col = 0; + } + } + } + else if (! do_forward) + { + // Start from where the cursor is. Fix QScintilla's cursor + // positioning + m_edit_area->getCursorPosition (&line, &col); + if (m_find_result_available && m_edit_area->hasSelectedText ()) + { + int currpos = m_edit_area->positionFromLineIndex (line, col); + currpos -= (m_search_line_edit->currentText ().length ()); + if (currpos < 0) + currpos = 0; + m_edit_area->lineIndexFromPosition (currpos, &line, &col); + } + } + } + + // Do the search + m_find_result_available + = m_edit_area->findFirst (m_search_line_edit->currentText (), + m_regex_check_box->isChecked (), + m_case_check_box->isChecked (), + m_whole_words_check_box->isChecked (), + do_wrap, + do_forward, + line, col, + true +#if defined (HAVE_QSCI_VERSION_2_6_0) + , true +#endif + ); + + if (m_find_result_available) + { + // Search successful: reset search-from-start box and check for + // the current selection + m_from_start_check_box->setChecked (0); + + if (m_in_sel) + { + m_edit_area->getCursorPosition (&line, &col); + int pos = m_edit_area->positionFromLineIndex (line, col); + + int l1, c1, l2, c2; + m_edit_area->lineIndexFromPosition (m_sel_beg, &l1, &c1); + m_edit_area->lineIndexFromPosition (m_sel_end, &l2, &c2); + m_edit_area->show_selection_markers (l1, c1, l2, c2); + + // Check if new start position is still within the selection + m_find_result_available = pos >= m_sel_beg && pos <= m_sel_end; + } + } -// Show and hide with (re-)storing position, otherwise there is always -// a small shift each time the dialog is shown again -void find_dialog::set_visible (bool visible) -{ - if (visible) - { - show (); - move (m_last_position); - } - else - { - m_last_position = pos (); - hide (); - } -} + // No more search hits + if (! m_find_result_available) + { + if (m_in_sel) + { + // Restore real selection and remove marker for selection + int l1, c1, l2, c2; + m_edit_area->lineIndexFromPosition (m_sel_beg, &l1, &c1); + m_edit_area->lineIndexFromPosition (m_sel_end, &l2, &c2); + m_edit_area->setSelection (l1, c1, l2, c2); + m_edit_area->clear_selection_markers (); + } + + // Display message if not replace all + if (! m_rep_all) + no_matches_message (); + } + + } + + void find_dialog::do_replace (void) + { + if (m_edit_area) + { + m_rep_active = true; // changes in selection not made by the user + + m_edit_area->replace (m_replace_line_edit->currentText ()); + if (m_in_sel) + { + // Update the length of the selection + m_sel_end = m_sel_end + - m_search_line_edit->currentText ().toUtf8 ().size () + + m_replace_line_edit->currentText ().toUtf8 ().size (); + } + + m_rep_active = false; + } + } + + void find_dialog::replace (void) + { + if (m_edit_area) + { + handle_replace_text_changed (); + + // Do the replace if we have selected text + if (m_find_result_available && m_edit_area->hasSelectedText ()) + do_replace (); + + find_next (); + } + } + + void find_dialog::replace_all (void) + { + int line, col; + + if (m_edit_area) + { + handle_replace_text_changed (); + + m_edit_area->getCursorPosition (&line, &col); + + m_rep_all = 1; + find_next (); // find first occurrence (forward) + + m_edit_area->beginUndoAction (); + while (m_find_result_available) // while search string is found + { + do_replace (); + m_rep_all++; // inc counter + find_next (); // find next + } + m_edit_area->endUndoAction (); + + QMessageBox msg_box (QMessageBox::Information, tr ("Replace Result"), + tr ("%1 items replaced").arg (m_rep_all-1), + QMessageBox::Ok, this); + msg_box.exec (); + + m_rep_all = 0; + m_find_result_available = false; + + if (! m_search_selection_check_box->isChecked ()) + m_edit_area->setCursorPosition (line, col); + } + } + + void find_dialog::no_matches_message (void) + { + QMessageBox msg_box (QMessageBox::Information, tr ("Find Result"), + tr ("No more matches found"), QMessageBox::Ok, this); + msg_box.exec (); + } + + void find_dialog::reject () + { + close (); + } + + void find_dialog::closeEvent (QCloseEvent *e) + { + save_settings (); + e->accept (); + } + + // Show and hide with (re-)storing position, otherwise there is always + // a small shift each time the dialog is shown again + void find_dialog::set_visible (bool visible) + { + if (visible) + { + show (); + move (m_last_position); + } + else + { + m_last_position = pos (); + hide (); + } + } OCTAVE_END_NAMESPACE(octave) #endif diff -r 29d734430e5f -r deb553ac2c54 libgui/src/m-editor/find-dialog.h --- a/libgui/src/m-editor/find-dialog.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/m-editor/find-dialog.h Tue Dec 06 15:45:27 2022 -0500 @@ -79,102 +79,99 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class file_editor; + class file_editor; -class find_dialog : public QDialog -{ - Q_OBJECT + class find_dialog : public QDialog + { + Q_OBJECT -public: + public: - find_dialog (base_qobject& oct_qobj, octave_dock_widget *ed, QWidget *p); + find_dialog (octave_dock_widget *ed, QWidget *p); - //! Set dialog visible or not and storing the new visibility state - void set_visible (bool visible); - - //! Init the search text with the selected text in the editor tab - void init_search_text (void); + //! Set dialog visible or not and storing the new visibility state + void set_visible (bool visible); - //! Restore position and the search options from the given settings - //! where def_pos is the default position suitable for the current - //! editor position - void restore_settings (QPoint def_pos); + //! Init the search text with the selected text in the editor tab + void init_search_text (void); -public slots: + //! Restore position and the search options from the given settings + //! where def_pos is the default position suitable for the current + //! editor position + void restore_settings (QPoint def_pos); - void find_next (void); - void find_prev (void); + public slots: + + void find_next (void); + void find_prev (void); - //! Slot for updating the edit area when the active tab has changed - void update_edit_area (octave_qscintilla *); + //! Slot for updating the edit area when the active tab has changed + void update_edit_area (octave_qscintilla *); -private slots: - - void handle_sel_search_changed (int); - void handle_selection_changed (bool has_selected); + private slots: - void handle_backward_search_changed (int); + void handle_sel_search_changed (int); + void handle_selection_changed (bool has_selected); - void find (bool forward = true); - void replace (void); - void replace_all (void); + void handle_backward_search_changed (int); -private: + void find (bool forward = true); + void replace (void); + void replace_all (void); - base_qobject& m_octave_qobj; + private: - //! Save position and the search options in the given settings - void save_settings (); + //! Save position and the search options in the given settings + void save_settings (); - //! Reimplemented slot: close instead of hiding - void reject (); + //! Reimplemented slot: close instead of hiding + void reject (); - //! Reimplemented close event - void closeEvent (QCloseEvent *e); + //! Reimplemented close event + void closeEvent (QCloseEvent *e); - //! Update mru lists with new entry - void mru_update (QComboBox *mru); + //! Update mru lists with new entry + void mru_update (QComboBox *mru); - void no_matches_message (void); - void do_replace (void); + void no_matches_message (void); + void do_replace (void); - void handle_search_text_changed (void); - void handle_replace_text_changed (void); + void handle_search_text_changed (void); + void handle_replace_text_changed (void); - octave_dock_widget *m_editor; + octave_dock_widget *m_editor; - QLabel *m_search_label; - QComboBox *m_search_line_edit; - QLabel *m_replace_label; - QComboBox *m_replace_line_edit; - QCheckBox *m_case_check_box; - QCheckBox *m_from_start_check_box; - QCheckBox *m_wrap_check_box; - QCheckBox *m_whole_words_check_box; - QCheckBox *m_regex_check_box; - QCheckBox *m_search_selection_check_box; - QCheckBox *m_backward_check_box; - QDialogButtonBox *m_button_box; - QPushButton *m_find_next_button; - QPushButton *m_find_prev_button; - QPushButton *m_replace_button; - QPushButton *m_replace_all_button; - QPushButton *m_more_button; - QWidget *m_extension; - octave_qscintilla *m_edit_area; - bool m_find_result_available; - int m_rep_all; - bool m_rep_active; + QLabel *m_search_label; + QComboBox *m_search_line_edit; + QLabel *m_replace_label; + QComboBox *m_replace_line_edit; + QCheckBox *m_case_check_box; + QCheckBox *m_from_start_check_box; + QCheckBox *m_wrap_check_box; + QCheckBox *m_whole_words_check_box; + QCheckBox *m_regex_check_box; + QCheckBox *m_search_selection_check_box; + QCheckBox *m_backward_check_box; + QDialogButtonBox *m_button_box; + QPushButton *m_find_next_button; + QPushButton *m_find_prev_button; + QPushButton *m_replace_button; + QPushButton *m_replace_all_button; + QPushButton *m_more_button; + QWidget *m_extension; + octave_qscintilla *m_edit_area; + bool m_find_result_available; + int m_rep_all; + bool m_rep_active; - bool m_in_sel; - int m_sel_beg; - int m_sel_end; + bool m_in_sel; + int m_sel_beg; + int m_sel_end; - QPoint m_last_position; + QPoint m_last_position; - const int m_mru_length = 10; -}; + const int m_mru_length = 10; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/m-editor/octave-qscintilla.cc --- a/libgui/src/m-editor/octave-qscintilla.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/m-editor/octave-qscintilla.cc Tue Dec 06 15:45:27 2022 -0500 @@ -54,6 +54,7 @@ #include "file-editor-tab.h" #include "gui-preferences-ed.h" +#include "gui-settings.h" // FIXME: hardwired marker numbers? #include "marker.h" #include "octave-qobject.h" @@ -73,1294 +74,1297 @@ OCTAVE_BEGIN_NAMESPACE(octave) -static bool -is_end (const QString& candidate, const QString& opening) -{ - bool retval = false; + static bool + is_end (const QString& candidate, const QString& opening) + { + bool retval = false; - if (opening == "do") // The only one that can't be ended by "end" - { - if (candidate == "until") - retval = true; - } - else - { - if (candidate == "end") - retval = true; - else - { - if (opening == "try") - { - if (candidate == "catch" || candidate == "end_try_catch") - retval = true; - } - else if (opening == "unwind_protect") - { - if (candidate == "unwind_protect_cleanup" - || candidate == "end_unwind_protect") - retval = true; - } - else if (candidate == "end" + opening) - retval = true; - else if (opening == "if" && candidate == "else") - retval = true; - } - } + if (opening == "do") // The only one that can't be ended by "end" + { + if (candidate == "until") + retval = true; + } + else + { + if (candidate == "end") + retval = true; + else + { + if (opening == "try") + { + if (candidate == "catch" || candidate == "end_try_catch") + retval = true; + } + else if (opening == "unwind_protect") + { + if (candidate == "unwind_protect_cleanup" + || candidate == "end_unwind_protect") + retval = true; + } + else if (candidate == "end" + opening) + retval = true; + else if (opening == "if" && candidate == "else") + retval = true; + } + } - return retval; -} + return retval; + } -octave_qscintilla::octave_qscintilla (QWidget *p, base_qobject& oct_qobj) - : QsciScintilla (p), m_octave_qobj (oct_qobj), m_debug_mode (false), - m_word_at_cursor (), m_selection (), m_selection_replacement (), - m_selection_line (-1), m_selection_col (-1), m_indicator_id (1) -{ - connect (this, SIGNAL (textChanged (void)), - this, SLOT (text_changed (void))); + octave_qscintilla::octave_qscintilla (QWidget *p, base_qobject& oct_qobj) + : QsciScintilla (p), m_octave_qobj (oct_qobj), m_debug_mode (false), + m_word_at_cursor (), m_selection (), m_selection_replacement (), + m_selection_line (-1), m_selection_col (-1), m_indicator_id (1) + { + connect (this, SIGNAL (textChanged (void)), + this, SLOT (text_changed (void))); - connect (this, SIGNAL (cursorPositionChanged (int, int)), - this, SLOT (cursor_position_changed (int, int))); + connect (this, SIGNAL (cursorPositionChanged (int, int)), + this, SLOT (cursor_position_changed (int, int))); - connect (this, &octave_qscintilla::ctx_menu_run_finished_signal, - this, &octave_qscintilla::ctx_menu_run_finished, - Qt::QueuedConnection); + connect (this, &octave_qscintilla::ctx_menu_run_finished_signal, + this, &octave_qscintilla::ctx_menu_run_finished, + Qt::QueuedConnection); - // clear scintilla edit shortcuts that are handled by the editor - QsciCommandSet *cmd_set = standardCommands (); + // clear scintilla edit shortcuts that are handled by the editor + QsciCommandSet *cmd_set = standardCommands (); - // Disable buffered drawing on all systems - SendScintilla (SCI_SETBUFFEREDDRAW, false); + // Disable buffered drawing on all systems + SendScintilla (SCI_SETBUFFEREDDRAW, false); #if defined (HAVE_QSCI_VERSION_2_6_0) - // find () was added in QScintilla 2.6 - cmd_set->find (QsciCommand::SelectionCopy)->setKey (0); - cmd_set->find (QsciCommand::SelectionCut)->setKey (0); - cmd_set->find (QsciCommand::Paste)->setKey (0); - cmd_set->find (QsciCommand::SelectAll)->setKey (0); - cmd_set->find (QsciCommand::SelectionDuplicate)->setKey (0); - cmd_set->find (QsciCommand::LineTranspose)->setKey (0); - cmd_set->find (QsciCommand::Undo)->setKey (0); - cmd_set->find (QsciCommand::Redo)->setKey (0); - cmd_set->find (QsciCommand::SelectionUpperCase)->setKey (0); - cmd_set->find (QsciCommand::SelectionLowerCase)->setKey (0); - cmd_set->find (QsciCommand::ZoomIn)->setKey (0); - cmd_set->find (QsciCommand::ZoomOut)->setKey (0); - cmd_set->find (QsciCommand::DeleteWordLeft)->setKey (0); - cmd_set->find (QsciCommand::DeleteWordRight)->setKey (0); - cmd_set->find (QsciCommand::DeleteLineLeft)->setKey (0); - cmd_set->find (QsciCommand::DeleteLineRight)->setKey (0); - cmd_set->find (QsciCommand::LineDelete)->setKey (0); - cmd_set->find (QsciCommand::LineCut)->setKey (0); - cmd_set->find (QsciCommand::LineCopy)->setKey (0); + // find () was added in QScintilla 2.6 + cmd_set->find (QsciCommand::SelectionCopy)->setKey (0); + cmd_set->find (QsciCommand::SelectionCut)->setKey (0); + cmd_set->find (QsciCommand::Paste)->setKey (0); + cmd_set->find (QsciCommand::SelectAll)->setKey (0); + cmd_set->find (QsciCommand::SelectionDuplicate)->setKey (0); + cmd_set->find (QsciCommand::LineTranspose)->setKey (0); + cmd_set->find (QsciCommand::Undo)->setKey (0); + cmd_set->find (QsciCommand::Redo)->setKey (0); + cmd_set->find (QsciCommand::SelectionUpperCase)->setKey (0); + cmd_set->find (QsciCommand::SelectionLowerCase)->setKey (0); + cmd_set->find (QsciCommand::ZoomIn)->setKey (0); + cmd_set->find (QsciCommand::ZoomOut)->setKey (0); + cmd_set->find (QsciCommand::DeleteWordLeft)->setKey (0); + cmd_set->find (QsciCommand::DeleteWordRight)->setKey (0); + cmd_set->find (QsciCommand::DeleteLineLeft)->setKey (0); + cmd_set->find (QsciCommand::DeleteLineRight)->setKey (0); + cmd_set->find (QsciCommand::LineDelete)->setKey (0); + cmd_set->find (QsciCommand::LineCut)->setKey (0); + cmd_set->find (QsciCommand::LineCopy)->setKey (0); #else - // find commands via its default key (tricky way without find ()) - QList< QsciCommand * > cmd_list = cmd_set->commands (); - for (int i = 0; i < cmd_list.length (); i++) - { - int cmd_key = cmd_list.at (i)->key (); - switch (cmd_key) - { - case Qt::Key_C | Qt::CTRL : // SelectionCopy - case Qt::Key_X | Qt::CTRL : // SelectionCut - case Qt::Key_V | Qt::CTRL : // Paste - case Qt::Key_A | Qt::CTRL : // SelectAll - case Qt::Key_D | Qt::CTRL : // SelectionDuplicate - case Qt::Key_T | Qt::CTRL : // LineTranspose - case Qt::Key_Z | Qt::CTRL : // Undo - case Qt::Key_Y | Qt::CTRL : // Redo - case Qt::Key_Z | Qt::CTRL | Qt::SHIFT : // Redo - case Qt::Key_U | Qt::CTRL : // SelectionLowerCase - case Qt::Key_U | Qt::CTRL | Qt::SHIFT : // SelectionUpperCase - case Qt::Key_Plus | Qt::CTRL : // ZoomIn - case Qt::Key_Minus | Qt::CTRL : // ZoomOut - case Qt::Key_Backspace | Qt::CTRL | Qt::SHIFT : // DeleteLineLeft - case Qt::Key_Delete | Qt::CTRL | Qt::SHIFT : // DeleteLineRight - case Qt::Key_K | Qt::META : // DeleteLineRight - case Qt::Key_Backspace | Qt::CTRL : // DeleteWordLeft - case Qt::Key_Delete | Qt::CTRL : // DeleteWordRight - case Qt::Key_L | Qt::CTRL | Qt::SHIFT : // LineDelete - case Qt::Key_L | Qt::CTRL : // LineCut - case Qt::Key_T | Qt::CTRL | Qt::SHIFT : // LineCopy - cmd_list.at (i)->setKey (0); - } - } + // find commands via its default key (tricky way without find ()) + QList< QsciCommand * > cmd_list = cmd_set->commands (); + for (int i = 0; i < cmd_list.length (); i++) + { + int cmd_key = cmd_list.at (i)->key (); + switch (cmd_key) + { + case Qt::Key_C | Qt::CTRL : // SelectionCopy + case Qt::Key_X | Qt::CTRL : // SelectionCut + case Qt::Key_V | Qt::CTRL : // Paste + case Qt::Key_A | Qt::CTRL : // SelectAll + case Qt::Key_D | Qt::CTRL : // SelectionDuplicate + case Qt::Key_T | Qt::CTRL : // LineTranspose + case Qt::Key_Z | Qt::CTRL : // Undo + case Qt::Key_Y | Qt::CTRL : // Redo + case Qt::Key_Z | Qt::CTRL | Qt::SHIFT : // Redo + case Qt::Key_U | Qt::CTRL : // SelectionLowerCase + case Qt::Key_U | Qt::CTRL | Qt::SHIFT : // SelectionUpperCase + case Qt::Key_Plus | Qt::CTRL : // ZoomIn + case Qt::Key_Minus | Qt::CTRL : // ZoomOut + case Qt::Key_Backspace | Qt::CTRL | Qt::SHIFT : // DeleteLineLeft + case Qt::Key_Delete | Qt::CTRL | Qt::SHIFT : // DeleteLineRight + case Qt::Key_K | Qt::META : // DeleteLineRight + case Qt::Key_Backspace | Qt::CTRL : // DeleteWordLeft + case Qt::Key_Delete | Qt::CTRL : // DeleteWordRight + case Qt::Key_L | Qt::CTRL | Qt::SHIFT : // LineDelete + case Qt::Key_L | Qt::CTRL : // LineCut + case Qt::Key_T | Qt::CTRL | Qt::SHIFT : // LineCopy + cmd_list.at (i)->setKey (0); + } + } #endif #if defined (Q_OS_MAC) - // Octave interprets Cmd key as Meta whereas Qscintilla interprets it - // as Ctrl. We thus invert Meta/Ctrl in Qscintilla's shortcuts list. - QList< QsciCommand * > cmd_list_mac = cmd_set->commands (); - for (int i = 0; i < cmd_list_mac.length (); i++) - { - // Primary key - int key = cmd_list_mac.at (i)->key (); - - if (static_cast (key | Qt::META) == key - && static_cast (key | Qt::CTRL) != key) - key = (key ^ Qt::META) | Qt::CTRL; - else if (static_cast (key | Qt::CTRL) == key) - key = (key ^ Qt::CTRL) | Qt::META; - - cmd_list_mac.at (i)->setKey (key); - - // Alternate key - key = cmd_list_mac.at (i)->alternateKey (); - - if (static_cast (key | Qt::META) == key - && static_cast (key | Qt::CTRL) != key) - key = (key ^ Qt::META) | Qt::CTRL; - else if (static_cast (key | Qt::CTRL) == key) - key = (key ^ Qt::CTRL) | Qt::META; - - cmd_list_mac.at (i)->setAlternateKey (key); - } -#endif - - // selection markers - - m_indicator_id = indicatorDefine (QsciScintilla::StraightBoxIndicator); - if (m_indicator_id == -1) - m_indicator_id = 1; - - setIndicatorDrawUnder (true, m_indicator_id); - - markerDefine (QsciScintilla::Minus, marker::selection); - - // init state of undo/redo action for this tab - emit status_update (isUndoAvailable (), isRedoAvailable ()); -} - -void octave_qscintilla::setCursorPosition (int line, int col) -{ - QsciScintilla::setCursorPosition (line, col); - emit update_rowcol_indicator_signal (line, col); -} - -void octave_qscintilla::set_selection_marker_color (const QColor& c) -{ - QColor ic = c; - ic.setAlphaF (0.45); - setIndicatorForegroundColor (ic, m_indicator_id); - setIndicatorOutlineColor (ic, m_indicator_id); - - setMarkerForegroundColor (c, marker::selection); - setMarkerBackgroundColor (c, marker::selection); -} - -// context menu requested -void octave_qscintilla::contextMenuEvent (QContextMenuEvent *e) -{ -#if defined (HAVE_QSCI_VERSION_2_6_0) - QPoint global_pos, local_pos; // the menu's position - QMenu *context_menu = createStandardContextMenu (); // standard menu - - bool in_left_margin = false; - - // determine position depending on mouse or keyboard event - if (e->reason () == QContextMenuEvent::Mouse) - { - // context menu by mouse - global_pos = e->globalPos (); // global mouse position - local_pos = e->pos (); // local mouse position - if (e->x () < marginWidth (1) + marginWidth (2)) - in_left_margin = true; - } - else - { - // context menu by keyboard or other: get point of text cursor - get_global_textcursor_pos (&global_pos, &local_pos); - QRect editor_rect = geometry (); // editor rect mapped to global - editor_rect.moveTopLeft - (parentWidget ()->mapToGlobal (editor_rect.topLeft ())); - if (! editor_rect.contains (global_pos)) // is cursor outside editor? - global_pos = editor_rect.topLeft (); // yes, take top left corner - } - -# if defined (HAVE_QSCI_VERSION_2_6_0) - if (! in_left_margin) -# endif - { - // fill context menu with editor's standard actions - emit create_context_menu_signal (context_menu); - - // additional custom entries of the context menu - context_menu->addSeparator (); // separator before custom entries - - // help menu: get the position of the mouse or the text cursor - // (only for octave files) - QString lexer_name = lexer ()->lexer (); - if (lexer_name == "octave" || lexer_name == "matlab") - { - m_word_at_cursor = wordAtPoint (local_pos); - if (! m_word_at_cursor.isEmpty ()) - { - context_menu->addAction (tr ("Help on") + ' ' + m_word_at_cursor, - this, &octave_qscintilla::contextmenu_help); - context_menu->addAction (tr ("Documentation on") - + ' ' + m_word_at_cursor, - this, &octave_qscintilla::contextmenu_doc); - context_menu->addAction (tr ("Edit") + ' ' + m_word_at_cursor, - this, &octave_qscintilla::contextmenu_edit); - } - } - } -# if defined (HAVE_QSCI_VERSION_2_6_0) - else - { - // remove all standard actions from scintilla - QList all_actions = context_menu->actions (); - - for (auto *a : all_actions) - context_menu->removeAction (a); - - QAction *act - = context_menu->addAction (tr ("dbstop if ..."), this, - &octave_qscintilla::contextmenu_break_condition); - act->setData (local_pos); - } -# endif - - // finally show the menu - context_menu->exec (global_pos); - -#else + // Octave interprets Cmd key as Meta whereas Qscintilla interprets it + // as Ctrl. We thus invert Meta/Ctrl in Qscintilla's shortcuts list. + QList< QsciCommand * > cmd_list_mac = cmd_set->commands (); + for (int i = 0; i < cmd_list_mac.length (); i++) + { + // Primary key + int key = cmd_list_mac.at (i)->key (); - octave_unused_parameter (e); - -#endif -} - -// common function with flag for documentation -void octave_qscintilla::contextmenu_help_doc (bool documentation) -{ - if (documentation) - m_octave_qobj.show_documentation_window (m_word_at_cursor); - else - emit execute_command_in_terminal_signal ("help " + m_word_at_cursor); -} - -// call edit the function related to the current word -void octave_qscintilla::context_edit (void) -{ - if (get_actual_word ()) - contextmenu_edit (true); -} - -// call edit the function related to the current word -void octave_qscintilla::context_run (void) -{ - if (hasSelectedText ()) - { - contextmenu_run (true); + if (static_cast (key | Qt::META) == key + && static_cast (key | Qt::CTRL) != key) + key = (key ^ Qt::META) | Qt::CTRL; + else if (static_cast (key | Qt::CTRL) == key) + key = (key ^ Qt::CTRL) | Qt::META; - emit interpreter_event - ([] (interpreter&) - { command_editor::erase_empty_line (false); }); - } -} - -void octave_qscintilla::get_global_textcursor_pos (QPoint *global_pos, - QPoint *local_pos) -{ - long position = SendScintilla (SCI_GETCURRENTPOS); - long point_x = SendScintilla (SCI_POINTXFROMPOSITION, 0, position); - long point_y = SendScintilla (SCI_POINTYFROMPOSITION, 0, position); - *local_pos = QPoint (point_x, point_y); // local cursor position - *global_pos = mapToGlobal (*local_pos); // global position of cursor -} - -// determine the actual word and whether we are in an octave or matlab script -bool octave_qscintilla::get_actual_word (void) -{ - QPoint global_pos, local_pos; - get_global_textcursor_pos (&global_pos, &local_pos); - m_word_at_cursor = wordAtPoint (local_pos); - QString lexer_name = lexer ()->lexer (); - return ((lexer_name == "octave" || lexer_name == "matlab") - && ! m_word_at_cursor.isEmpty ()); -} - -// helper function for clearing all indicators of a specific style -void octave_qscintilla::clear_selection_markers (void) -{ - int end_pos = text ().length (); - int end_line, end_col; - lineIndexFromPosition (end_pos, &end_line, &end_col); - clearIndicatorRange (0, 0, end_line, end_col, m_indicator_id); - - markerDeleteAll (marker::selection); -} + cmd_list_mac.at (i)->setKey (key); -QString octave_qscintilla::eol_string (void) -{ - switch (eolMode ()) - { - case QsciScintilla::EolWindows: - return ("\r\n"); - case QsciScintilla::EolMac: - return ("\r"); - case QsciScintilla::EolUnix: - return ("\n"); - } - - // Last resort, if the above goes wrong (should never happen) - return ("\r\n"); -} - -// Function returning the true cursor position where the tab length -// is taken into account. -void octave_qscintilla::get_current_position (int *pos, int *line, int *col) -{ - *pos = SendScintilla (QsciScintillaBase::SCI_GETCURRENTPOS); - *line = SendScintilla (QsciScintillaBase::SCI_LINEFROMPOSITION, *pos); - *col = SendScintilla (QsciScintillaBase::SCI_GETCOLUMN, *pos); -} - -// Function returning the comment string of the current lexer -QStringList octave_qscintilla::comment_string (bool comment) -{ - int lexer = SendScintilla (SCI_GETLEXER); + // Alternate key + key = cmd_list_mac.at (i)->alternateKey (); - switch (lexer) - { -#if defined (HAVE_LEXER_OCTAVE) || defined (HAVE_LEXER_MATLAB) -#if defined (HAVE_LEXER_OCTAVE) - case SCLEX_OCTAVE: -#else - case SCLEX_MATLAB: -#endif - { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - int comment_string; + if (static_cast (key | Qt::META) == key + && static_cast (key | Qt::CTRL) != key) + key = (key ^ Qt::META) | Qt::CTRL; + else if (static_cast (key | Qt::CTRL) == key) + key = (key ^ Qt::CTRL) | Qt::META; - if (comment) - { - // The commenting string is requested - if (settings->contains (ed_comment_str.key)) - // new version (radio buttons) - comment_string = settings->value (ed_comment_str).toInt (); - else - // old version (combo box) - comment_string = settings->value (ed_comment_str_old.key, - ed_comment_str.def).toInt (); - - return (QStringList (ed_comment_strings.at (comment_string))); - } - else - { - QStringList c_str; - - // The possible uncommenting string(s) are requested - comment_string = settings->value (ed_uncomment_str).toInt (); - - for (int i = 0; i < ed_comment_strings_count; i++) - { - if (1 << i & comment_string) - c_str.append (ed_comment_strings.at (i)); - } - - return c_str; - } - + cmd_list_mac.at (i)->setAlternateKey (key); } #endif - case SCLEX_PERL: - case SCLEX_BASH: - case SCLEX_DIFF: - return QStringList ("#"); + // selection markers + + m_indicator_id = indicatorDefine (QsciScintilla::StraightBoxIndicator); + if (m_indicator_id == -1) + m_indicator_id = 1; + + setIndicatorDrawUnder (true, m_indicator_id); + + markerDefine (QsciScintilla::Minus, marker::selection); + + // init state of undo/redo action for this tab + emit status_update (isUndoAvailable (), isRedoAvailable ()); + } + + void octave_qscintilla::setCursorPosition (int line, int col) + { + QsciScintilla::setCursorPosition (line, col); + emit update_rowcol_indicator_signal (line, col); + } + + void octave_qscintilla::set_selection_marker_color (const QColor& c) + { + QColor ic = c; + ic.setAlphaF (0.45); + setIndicatorForegroundColor (ic, m_indicator_id); + setIndicatorOutlineColor (ic, m_indicator_id); - case SCLEX_CPP: - return QStringList ("//"); + setMarkerForegroundColor (c, marker::selection); + setMarkerBackgroundColor (c, marker::selection); + } + + // context menu requested + void octave_qscintilla::contextMenuEvent (QContextMenuEvent *e) + { +#if defined (HAVE_QSCI_VERSION_2_6_0) + QPoint global_pos, local_pos; // the menu's position + QMenu *context_menu = createStandardContextMenu (); // standard menu + + bool in_left_margin = false; - case SCLEX_BATCH: - return QStringList ("REM "); - } + // determine position depending on mouse or keyboard event + if (e->reason () == QContextMenuEvent::Mouse) + { + // context menu by mouse + global_pos = e->globalPos (); // global mouse position + local_pos = e->pos (); // local mouse position + if (e->x () < marginWidth (1) + marginWidth (2)) + in_left_margin = true; + } + else + { + // context menu by keyboard or other: get point of text cursor + get_global_textcursor_pos (&global_pos, &local_pos); + QRect editor_rect = geometry (); // editor rect mapped to global + editor_rect.moveTopLeft + (parentWidget ()->mapToGlobal (editor_rect.topLeft ())); + if (! editor_rect.contains (global_pos)) // is cursor outside editor? + global_pos = editor_rect.topLeft (); // yes, take top left corner + } - return QStringList ("%"); // should never happen -} +# if defined (HAVE_QSCI_VERSION_2_6_0) + if (! in_left_margin) +# endif + { + // fill context menu with editor's standard actions + emit create_context_menu_signal (context_menu); + + // additional custom entries of the context menu + context_menu->addSeparator (); // separator before custom entries -// provide the style at a specific position -int octave_qscintilla::get_style (int pos) -{ - int position; - if (pos < 0) - // The positition has to be reduced by 2 for getting the real style (?) - position = SendScintilla (QsciScintillaBase::SCI_GETCURRENTPOS) - 2; - else - position = pos; + // help menu: get the position of the mouse or the text cursor + // (only for octave files) + QString lexer_name = lexer ()->lexer (); + if (lexer_name == "octave" || lexer_name == "matlab") + { + m_word_at_cursor = wordAtPoint (local_pos); + if (! m_word_at_cursor.isEmpty ()) + { + context_menu->addAction (tr ("Help on") + ' ' + m_word_at_cursor, + this, &octave_qscintilla::contextmenu_help); + context_menu->addAction (tr ("Documentation on") + + ' ' + m_word_at_cursor, + this, &octave_qscintilla::contextmenu_doc); + context_menu->addAction (tr ("Edit") + ' ' + m_word_at_cursor, + this, &octave_qscintilla::contextmenu_edit); + } + } + } +# if defined (HAVE_QSCI_VERSION_2_6_0) + else + { + // remove all standard actions from scintilla + QList all_actions = context_menu->actions (); + + for (auto *a : all_actions) + context_menu->removeAction (a); + + QAction *act + = context_menu->addAction (tr ("dbstop if ..."), this, + &octave_qscintilla::contextmenu_break_condition); + act->setData (local_pos); + } +# endif + + // finally show the menu + context_menu->exec (global_pos); + +#else + + octave_unused_parameter (e); + +#endif + } + + // common function with flag for documentation + void octave_qscintilla::contextmenu_help_doc (bool documentation) + { + if (documentation) + m_octave_qobj.show_documentation_window (m_word_at_cursor); + else + emit execute_command_in_terminal_signal ("help " + m_word_at_cursor); + } - return SendScintilla (QsciScintillaBase::SCI_GETSTYLEAT, position); -} + // call edit the function related to the current word + void octave_qscintilla::context_edit (void) + { + if (get_actual_word ()) + contextmenu_edit (true); + } + + // call edit the function related to the current word + void octave_qscintilla::context_run (void) + { + if (hasSelectedText ()) + { + contextmenu_run (true); + + emit interpreter_event + ([] (interpreter&) + { command_editor::erase_empty_line (false); }); + } + } -// Is a specific cursor position in a line or block comment? -int octave_qscintilla::is_style_comment (int pos) -{ - int lexer = SendScintilla (QsciScintillaBase::SCI_GETLEXER); - int style = get_style (pos); + void octave_qscintilla::get_global_textcursor_pos (QPoint *global_pos, + QPoint *local_pos) + { + long position = SendScintilla (SCI_GETCURRENTPOS); + long point_x = SendScintilla (SCI_POINTXFROMPOSITION, 0, position); + long point_y = SendScintilla (SCI_POINTYFROMPOSITION, 0, position); + *local_pos = QPoint (point_x, point_y); // local cursor position + *global_pos = mapToGlobal (*local_pos); // global position of cursor + } + + // determine the actual word and whether we are in an octave or matlab script + bool octave_qscintilla::get_actual_word (void) + { + QPoint global_pos, local_pos; + get_global_textcursor_pos (&global_pos, &local_pos); + m_word_at_cursor = wordAtPoint (local_pos); + QString lexer_name = lexer ()->lexer (); + return ((lexer_name == "octave" || lexer_name == "matlab") + && ! m_word_at_cursor.isEmpty ()); + } + + // helper function for clearing all indicators of a specific style + void octave_qscintilla::clear_selection_markers (void) + { + int end_pos = text ().length (); + int end_line, end_col; + lineIndexFromPosition (end_pos, &end_line, &end_col); + clearIndicatorRange (0, 0, end_line, end_col, m_indicator_id); + + markerDeleteAll (marker::selection); + } - switch (lexer) - { - case SCLEX_CPP: - return (ST_LINE_COMMENT * (style == QsciLexerCPP::CommentLine - || style == QsciLexerCPP::CommentLineDoc) - + ST_BLOCK_COMMENT * (style == QsciLexerCPP::Comment - || style == QsciLexerCPP::CommentDoc - || style == QsciLexerCPP::CommentDocKeyword - || style == QsciLexerCPP::CommentDocKeywordError)); + QString octave_qscintilla::eol_string (void) + { + switch (eolMode ()) + { + case QsciScintilla::EolWindows: + return ("\r\n"); + case QsciScintilla::EolMac: + return ("\r"); + case QsciScintilla::EolUnix: + return ("\n"); + } + + // Last resort, if the above goes wrong (should never happen) + return ("\r\n"); + } + + // Function returning the true cursor position where the tab length + // is taken into account. + void octave_qscintilla::get_current_position (int *pos, int *line, int *col) + { + *pos = SendScintilla (QsciScintillaBase::SCI_GETCURRENTPOS); + *line = SendScintilla (QsciScintillaBase::SCI_LINEFROMPOSITION, *pos); + *col = SendScintilla (QsciScintillaBase::SCI_GETCOLUMN, *pos); + } + + // Function returning the comment string of the current lexer + QStringList octave_qscintilla::comment_string (bool comment) + { + int lexer = SendScintilla (SCI_GETLEXER); -#if defined (HAVE_LEXER_MATLAB) - case SCLEX_MATLAB: - return (ST_LINE_COMMENT * (style == QsciLexerMatlab::Comment)); + switch (lexer) + { +#if defined (HAVE_LEXER_OCTAVE) || defined (HAVE_LEXER_MATLAB) +#if defined (HAVE_LEXER_OCTAVE) + case SCLEX_OCTAVE: +#else + case SCLEX_MATLAB: #endif -#if defined (HAVE_LEXER_OCTAVE) - case SCLEX_OCTAVE: - return (ST_LINE_COMMENT * (style == QsciLexerOctave::Comment)); + { + gui_settings settings; + + int comment_string; + + if (comment) + { + // The commenting string is requested + if (settings.contains (ed_comment_str.key)) + // new version (radio buttons) + comment_string = settings.value (ed_comment_str).toInt (); + else + // old version (combo box) + comment_string = settings.value (ed_comment_str_old.key, + ed_comment_str.def).toInt (); + + return (QStringList (ed_comment_strings.at (comment_string))); + } + else + { + QStringList c_str; + + // The possible uncommenting string(s) are requested + comment_string = settings.value (ed_uncomment_str).toInt (); + + for (int i = 0; i < ed_comment_strings_count; i++) + { + if (1 << i & comment_string) + c_str.append (ed_comment_strings.at (i)); + } + + return c_str; + } + + } #endif - case SCLEX_PERL: - return (ST_LINE_COMMENT * (style == QsciLexerPerl::Comment)); - - case SCLEX_BATCH: - return (ST_LINE_COMMENT * (style == QsciLexerBatch::Comment)); - - case SCLEX_DIFF: - return (ST_LINE_COMMENT * (style == QsciLexerDiff::Comment)); - - case SCLEX_BASH: - return (ST_LINE_COMMENT * (style == QsciLexerBash::Comment)); - - } - - return ST_NONE; -} + case SCLEX_PERL: + case SCLEX_BASH: + case SCLEX_DIFF: + return QStringList ("#"); -// Do smart indentation after if, for, ... -void octave_qscintilla::smart_indent (bool do_smart_indent, int do_auto_close, - int line, int ind_char_width) -{ - QString prevline = text (line); + case SCLEX_CPP: + return QStringList ("//"); - QRegExp bkey = QRegExp ("^[\t ]*(if|for|while|switch" - "|do|function|properties|events|classdef" - "|unwind_protect|try" - "|parfor|methods)" - "[\r]?[\n\t #%]"); - // last word except for comments, assuming no ' or " in comment. - // rx_end = QRegExp ("(\\w+)[ \t;\r\n]*([%#][^\"']*)?$"); - - // last word except for comments, - // allowing % and # in single or double quoted strings - // FIXME: This will get confused by transpose. - QRegExp ekey = QRegExp ("(?:(?:['\"][^'\"]*['\"])?[^%#]*)*" - "(\\w+)[ \t;\r\n]*(?:[%#].*)?$"); + case SCLEX_BATCH: + return QStringList ("REM "); + } - int bpos = bkey.indexIn (prevline, 0); - int epos; - - if (bpos > -1) - { - // Found keyword after that indentation should be added - - // Check for existing end statement in the same line - epos = ekey.indexIn (prevline, bpos); - QString first_word = bkey.cap(1); - bool inline_end = (epos > -1) && is_end (ekey.cap(1), first_word); + return QStringList ("%"); // should never happen + } - if (do_smart_indent && ! inline_end) - { - // Do smart indent in the current line (line+1) - indent (line+1); - setCursorPosition (line+1, indentation (line+1) / ind_char_width); - } + // provide the style at a specific position + int octave_qscintilla::get_style (int pos) + { + int position; + if (pos < 0) + // The positition has to be reduced by 2 for getting the real style (?) + position = SendScintilla (QsciScintillaBase::SCI_GETCURRENTPOS) - 2; + else + position = pos; - if (do_auto_close - && ! inline_end - && ! first_word.contains (QRegExp ("(?:case|otherwise|unwind_protect_cleanup)"))) - { - // Do auto close - auto_close (do_auto_close, line, prevline, first_word); - } - - return; - } - - QRegExp mkey = QRegExp ("^[\t ]*(?:else|elseif|catch|unwind_protect_cleanup)" - "[\r]?[\t #%\n]"); - if (prevline.contains (mkey)) - { - int prev_ind = indentation (line-1); - int act_ind = indentation (line); + return SendScintilla (QsciScintillaBase::SCI_GETSTYLEAT, position); + } - if (prev_ind == act_ind) - unindent (line); - else if (prev_ind > act_ind) - { - setIndentation (line+1, prev_ind); - setCursorPosition (line+1, prev_ind); - } - return; - } - - QRegExp case_key = QRegExp ("^[\t ]*(?:case|otherwise)[\r]?[\t #%\n]"); - if (prevline.contains (case_key) && do_smart_indent) - { - QString last_line = text (line-1); - int prev_ind = indentation (line-1); - int act_ind = indentation (line); + // Is a specific cursor position in a line or block comment? + int octave_qscintilla::is_style_comment (int pos) + { + int lexer = SendScintilla (QsciScintillaBase::SCI_GETLEXER); + int style = get_style (pos); - if (last_line.contains (QRegExp ("^[\t ]*switch"))) - { - indent (line+1); - act_ind = indentation (line+1); - } - else - { - if (prev_ind == act_ind) - unindent (line); - else if (prev_ind > act_ind) - act_ind = prev_ind; - } - - setIndentation (line+1, act_ind); - setCursorPosition (line+1, act_ind); - } + switch (lexer) + { + case SCLEX_CPP: + return (ST_LINE_COMMENT * (style == QsciLexerCPP::CommentLine + || style == QsciLexerCPP::CommentLineDoc) + + ST_BLOCK_COMMENT * (style == QsciLexerCPP::Comment + || style == QsciLexerCPP::CommentDoc + || style == QsciLexerCPP::CommentDocKeyword + || style == QsciLexerCPP::CommentDocKeywordError)); - ekey = QRegExp ("^[\t ]*(?:end|endif|endfor|endwhile|until|endfunction" - "|endswitch|end_try_catch|end_unwind_protect)[\r]?[\t #%\n(;]"); - if (prevline.contains (ekey)) - { - if (indentation (line-1) <= indentation (line)) - { - unindent (line+1); - unindent (line); - if (prevline.contains ("endswitch")) - { - // endswitch has to me unndented twice - unindent (line+1); - unindent (line); - } - setCursorPosition (line+1, - indentation (line)); - } - return; - } -} - -// Do smart indentation of current selection or line. -void octave_qscintilla::smart_indent_line_or_selected_text (int lineFrom, - int lineTo) -{ - QRegExp blank_line_regexp = QRegExp ("^[\t ]*$"); +#if defined (HAVE_LEXER_MATLAB) + case SCLEX_MATLAB: + return (ST_LINE_COMMENT * (style == QsciLexerMatlab::Comment)); +#endif +#if defined (HAVE_LEXER_OCTAVE) + case SCLEX_OCTAVE: + return (ST_LINE_COMMENT * (style == QsciLexerOctave::Comment)); +#endif - // end[xxxxx] [# comment] at end of a line - QRegExp end_word_regexp - = QRegExp ("(?:(?:['\"][^'\"]*['\"])?[^%#]*)*" - "(?:end\\w*)[\r\n\t ;]*(?:[%#].*)?$"); + case SCLEX_PERL: + return (ST_LINE_COMMENT * (style == QsciLexerPerl::Comment)); - QRegExp begin_block_regexp - = QRegExp ("^[\t ]*(?:if|elseif|else" - "|for|while|do|parfor" - "|switch|case|otherwise" - "|function" - "|classdef|properties|events|enumeration|methods" - "|unwind_protect|unwind_protect_cleanup|try|catch)" - "[\r\n\t #%]"); + case SCLEX_BATCH: + return (ST_LINE_COMMENT * (style == QsciLexerBatch::Comment)); - QRegExp mid_block_regexp - = QRegExp ("^[\t ]*(?:elseif|else" - "|unwind_protect_cleanup|catch)" - "[\r\n\t #%]"); + case SCLEX_DIFF: + return (ST_LINE_COMMENT * (style == QsciLexerDiff::Comment)); - QRegExp end_block_regexp - = QRegExp ("^[\t ]*(?:end" - "|end(for|function|if|parfor|switch|while" - "|classdef|enumeration|events|methods|properties)" - "|end_(try_catch|unwind_protect)" - "|until)" - "[\r\n\t #%]"); + case SCLEX_BASH: + return (ST_LINE_COMMENT * (style == QsciLexerBash::Comment)); - QRegExp case_block_regexp - = QRegExp ("^[\t ]*(?:case|otherwise)" - "[\r\n\t #%]"); + } - int indent_column = -1; - int indent_increment = indentationWidth (); - bool in_switch = false; - - for (int line = lineFrom-1; line >= 0; line--) - { - QString line_text = text (line); - - if (blank_line_regexp.indexIn (line_text) < 0) - { - // Found first non-blank line above beginning of region or - // current line. Base indentation from this line, increasing - // indentation by indentationWidth if it looks like the - // beginning of a code block. - - indent_column = indentation (line); + return ST_NONE; + } - if (begin_block_regexp.indexIn (line_text) > -1) - { - indent_column += indent_increment; - if (line_text.contains ("switch")) - in_switch = true; - } - - break; - } - } - - if (indent_column < 0) - indent_column = indentation (lineFrom); - - QString prev_line; - for (int line = lineFrom; line <= lineTo; line++) - { - QString line_text = text (line); + // Do smart indentation after if, for, ... + void octave_qscintilla::smart_indent (bool do_smart_indent, int do_auto_close, + int line, int ind_char_width) + { + QString prevline = text (line); - if (end_block_regexp.indexIn (line_text) > -1) - { - indent_column -= indent_increment; - if (line_text.contains ("endswitch")) - { - // need a double de-indent for endswitch - if (in_switch) - indent_column -= indent_increment; - in_switch = false; - } - } - - if (mid_block_regexp.indexIn (line_text) > -1) - indent_column -= indent_increment; - - if (case_block_regexp.indexIn (line_text) > -1) - { - if (case_block_regexp.indexIn (prev_line) < 0 - && !prev_line.contains("switch")) - indent_column -= indent_increment; - in_switch = true; - } - - setIndentation (line, indent_column); + QRegExp bkey = QRegExp ("^[\t ]*(if|for|while|switch" + "|do|function|properties|events|classdef" + "|unwind_protect|try" + "|parfor|methods)" + "[\r]?[\n\t #%]"); + // last word except for comments, assuming no ' or " in comment. + // rx_end = QRegExp ("(\\w+)[ \t;\r\n]*([%#][^\"']*)?$"); - int bpos = begin_block_regexp.indexIn (line_text); - if (bpos > -1) - { - // Check for existing end statement in the same line - int epos = end_word_regexp.indexIn (line_text, bpos); - if (epos == -1) - indent_column += indent_increment; - if (line_text.contains ("switch")) - in_switch = true; - } + // last word except for comments, + // allowing % and # in single or double quoted strings + // FIXME: This will get confused by transpose. + QRegExp ekey = QRegExp ("(?:(?:['\"][^'\"]*['\"])?[^%#]*)*" + "(\\w+)[ \t;\r\n]*(?:[%#].*)?$"); - if (blank_line_regexp.indexIn (line_text) < 0) - prev_line = line_text; - } -} + int bpos = bkey.indexIn (prevline, 0); + int epos; -void octave_qscintilla::set_word_selection (const QString& word) -{ - m_selection = word; - - if (word.isEmpty ()) - { - m_selection_line = -1; - m_selection_col = -1; + if (bpos > -1) + { + // Found keyword after that indentation should be added - m_selection_replacement = ""; - - clear_selection_markers (); - - QToolTip::hideText (); - } - else - { - int pos; - get_current_position (&pos, &m_selection_line, &m_selection_col); - } -} - -void octave_qscintilla::show_selection_markers (int l1, int c1, int l2, int c2) -{ - fillIndicatorRange (l1, c1, l2, c2, m_indicator_id); - - if (l1 == l2) - markerAdd (l1, marker::selection); -} + // Check for existing end statement in the same line + epos = ekey.indexIn (prevline, bpos); + QString first_word = bkey.cap(1); + bool inline_end = (epos > -1) && is_end (ekey.cap(1), first_word); -void octave_qscintilla::contextmenu_help (bool) -{ - contextmenu_help_doc (false); -} - -void octave_qscintilla::contextmenu_doc (bool) -{ - contextmenu_help_doc (true); -} - -void octave_qscintilla::context_help_doc (bool documentation) -{ - if (get_actual_word ()) - contextmenu_help_doc (documentation); -} - -void octave_qscintilla::contextmenu_edit (bool) -{ - emit context_menu_edit_signal (m_word_at_cursor); -} + if (do_smart_indent && ! inline_end) + { + // Do smart indent in the current line (line+1) + indent (line+1); + setCursorPosition (line+1, indentation (line+1) / ind_char_width); + } -void octave_qscintilla::contextmenu_run_temp_error (void) -{ - QMessageBox::critical (this, tr ("Octave Editor"), - tr ("Creating temporary files failed.\n" - "Make sure you have write access to temp. directory\n" - "%1\n\n" - "\"Run Selection\" requires temporary files.").arg (QDir::tempPath ())); -} + if (do_auto_close + && ! inline_end + && ! first_word.contains (QRegExp ("(?:case|otherwise|unwind_protect_cleanup)"))) + { + // Do auto close + auto_close (do_auto_close, line, prevline, first_word); + } -void octave_qscintilla::contextmenu_run (bool) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - - // Take selected code and extend it by commands for echoing each - // evaluated line and for adding the line to the history (use script) - QString code = QString (); - QString hist = QString (); + return; + } - // Split contents into single lines and complete commands - QStringList lines = selectedText ().split (QRegExp ("[\r\n]"), -#if defined (HAVE_QT_SPLITBEHAVIOR_ENUM) - Qt::SkipEmptyParts); -#else - QString::SkipEmptyParts); -#endif -for (int i = 0; i < lines.count (); i++) - { - QString line = lines.at (i); - if (line.trimmed ().isEmpty ()) - continue; - QString line_escaped = line; - line_escaped.replace (QString ("'"), QString ("''")); - QString line_history = line; + QRegExp mkey = QRegExp ("^[\t ]*(?:else|elseif|catch|unwind_protect_cleanup)" + "[\r]?[\t #%\n]"); + if (prevline.contains (mkey)) + { + int prev_ind = indentation (line-1); + int act_ind = indentation (line); - // Prevent output of breakpoint in temp. file for keyboard - QString next_bp_quiet; - QString next_bp_quiet_reset; - if (line.contains ("keyboard")) - { - // Define commands for not showing bp location and for resetting - // this in case "keyboard" was within a comment - next_bp_quiet = "__db_next_breakpoint_quiet__;\n"; - next_bp_quiet_reset = "\n__db_next_breakpoint_quiet__(false);"; + if (prev_ind == act_ind) + unindent (line); + else if (prev_ind > act_ind) + { + setIndentation (line+1, prev_ind); + setCursorPosition (line+1, prev_ind); + } + return; } - // Add codeline - code += next_bp_quiet + line + next_bp_quiet_reset + "\n"; - hist += line_history + "\n"; + QRegExp case_key = QRegExp ("^[\t ]*(?:case|otherwise)[\r]?[\t #%\n]"); + if (prevline.contains (case_key) && do_smart_indent) + { + QString last_line = text (line-1); + int prev_ind = indentation (line-1); + int act_ind = indentation (line); + + if (last_line.contains (QRegExp ("^[\t ]*switch"))) + { + indent (line+1); + act_ind = indentation (line+1); + } + else + { + if (prev_ind == act_ind) + unindent (line); + else if (prev_ind > act_ind) + act_ind = prev_ind; + } + + setIndentation (line+1, act_ind); + setCursorPosition (line+1, act_ind); + } + + ekey = QRegExp ("^[\t ]*(?:end|endif|endfor|endwhile|until|endfunction" + "|endswitch|end_try_catch|end_unwind_protect)[\r]?[\t #%\n(;]"); + if (prevline.contains (ekey)) + { + if (indentation (line-1) <= indentation (line)) + { + unindent (line+1); + unindent (line); + if (prevline.contains ("endswitch")) + { + // endswitch has to me unndented twice + unindent (line+1); + unindent (line); + } + setCursorPosition (line+1, + indentation (line)); + } + return; + } } -octave_stdout << hist.toStdString (); + // Do smart indentation of current selection or line. + void octave_qscintilla::smart_indent_line_or_selected_text (int lineFrom, + int lineTo) + { + QRegExp blank_line_regexp = QRegExp ("^[\t ]*$"); + + // end[xxxxx] [# comment] at end of a line + QRegExp end_word_regexp + = QRegExp ("(?:(?:['\"][^'\"]*['\"])?[^%#]*)*" + "(?:end\\w*)[\r\n\t ;]*(?:[%#].*)?$"); + + QRegExp begin_block_regexp + = QRegExp ("^[\t ]*(?:if|elseif|else" + "|for|while|do|parfor" + "|switch|case|otherwise" + "|function" + "|classdef|properties|events|enumeration|methods" + "|unwind_protect|unwind_protect_cleanup|try|catch)" + "[\r\n\t #%]"); + + QRegExp mid_block_regexp + = QRegExp ("^[\t ]*(?:elseif|else" + "|unwind_protect_cleanup|catch)" + "[\r\n\t #%]"); -// Create tmp file with the code to be executed by the interpreter -QPointer tmp_file -= rmgr.create_tmp_file ("m", code); + QRegExp end_block_regexp + = QRegExp ("^[\t ]*(?:end" + "|end(for|function|if|parfor|switch|while" + "|classdef|enumeration|events|methods|properties)" + "|end_(try_catch|unwind_protect)" + "|until)" + "[\r\n\t #%]"); + + QRegExp case_block_regexp + = QRegExp ("^[\t ]*(?:case|otherwise)" + "[\r\n\t #%]"); + + int indent_column = -1; + int indent_increment = indentationWidth (); + bool in_switch = false; + + for (int line = lineFrom-1; line >= 0; line--) + { + QString line_text = text (line); + + if (blank_line_regexp.indexIn (line_text) < 0) + { + // Found first non-blank line above beginning of region or + // current line. Base indentation from this line, increasing + // indentation by indentationWidth if it looks like the + // beginning of a code block. + + indent_column = indentation (line); -bool tmp = (tmp_file && tmp_file->open ()); -if (! tmp) - { - // tmp files not working: use old way to run selection - contextmenu_run_temp_error (); - return; + if (begin_block_regexp.indexIn (line_text) > -1) + { + indent_column += indent_increment; + if (line_text.contains ("switch")) + in_switch = true; + } + + break; + } + } + + if (indent_column < 0) + indent_column = indentation (lineFrom); + + QString prev_line; + for (int line = lineFrom; line <= lineTo; line++) + { + QString line_text = text (line); + + if (end_block_regexp.indexIn (line_text) > -1) + { + indent_column -= indent_increment; + if (line_text.contains ("endswitch")) + { + // need a double de-indent for endswitch + if (in_switch) + indent_column -= indent_increment; + in_switch = false; + } + } + + if (mid_block_regexp.indexIn (line_text) > -1) + indent_column -= indent_increment; + + if (case_block_regexp.indexIn (line_text) > -1) + { + if (case_block_regexp.indexIn (prev_line) < 0 + && !prev_line.contains("switch")) + indent_column -= indent_increment; + in_switch = true; + } + + setIndentation (line, indent_column); + + int bpos = begin_block_regexp.indexIn (line_text); + if (bpos > -1) + { + // Check for existing end statement in the same line + int epos = end_word_regexp.indexIn (line_text, bpos); + if (epos == -1) + indent_column += indent_increment; + if (line_text.contains ("switch")) + in_switch = true; + } + + if (blank_line_regexp.indexIn (line_text) < 0) + prev_line = line_text; + } } -tmp_file->close (); + void octave_qscintilla::set_word_selection (const QString& word) + { + m_selection = word; -// Create tmp file required for adding command to history -QPointer tmp_hist -= rmgr.create_tmp_file ("", hist); // empty tmp file for history + if (word.isEmpty ()) + { + m_selection_line = -1; + m_selection_col = -1; -tmp = (tmp_hist && tmp_hist->open ()); -if (! tmp) - { - // tmp files not working: use old way to run selection - contextmenu_run_temp_error (); - return; + m_selection_replacement = ""; + + clear_selection_markers (); + + QToolTip::hideText (); + } + else + { + int pos; + get_current_position (&pos, &m_selection_line, &m_selection_col); + } } -tmp_hist->close (); + void octave_qscintilla::show_selection_markers (int l1, int c1, int l2, int c2) + { + fillIndicatorRange (l1, c1, l2, c2, m_indicator_id); -// Add commands to the history -emit interpreter_event -([=] (interpreter& interp) - { - // INTERPRETER THREAD + if (l1 == l2) + markerAdd (l1, marker::selection); + } - std::string opt = "-r"; - std::string path = tmp_hist->fileName ().toStdString (); + void octave_qscintilla::contextmenu_help (bool) + { + contextmenu_help_doc (false); + } - Fhistory (interp, ovl (opt, path)); - }); + void octave_qscintilla::contextmenu_doc (bool) + { + contextmenu_help_doc (true); + } -// Disable opening a file at a breakpoint in case keyboard () is used -gui_settings *settings = rmgr.get_settings (); -bool show_dbg_file = settings->value (ed_show_dbg_file).toBool (); -settings->setValue (ed_show_dbg_file.key, false); + void octave_qscintilla::context_help_doc (bool documentation) + { + if (get_actual_word ()) + contextmenu_help_doc (documentation); + } -// Let the interpreter execute the tmp file -emit interpreter_event -([=] (interpreter& interp) - { - // INTERPRETER THREAD + void octave_qscintilla::contextmenu_edit (bool) + { + emit context_menu_edit_signal (m_word_at_cursor); + } - std::string file = tmp_file->fileName ().toStdString (); - - std::string pending_input = command_editor::get_current_line (); - - int err_line = -1; // For storing the line of a poss. error + void octave_qscintilla::contextmenu_run_temp_error (void) + { + QMessageBox::critical (this, tr ("Octave Editor"), + tr ("Creating temporary files failed.\n" + "Make sure you have write access to temp. directory\n" + "%1\n\n" + "\"Run Selection\" requires temporary files.").arg (QDir::tempPath ())); + } - // Get current state of auto command repeat in debug mode - octave_value_list ovl_dbg = Fisdebugmode (interp); - bool dbg = ovl_dbg(0).bool_value (); - octave_value_list ovl_auto_repeat = ovl (true); - if (dbg) - ovl_auto_repeat = Fauto_repeat_debug_command (interp, ovl (false), 1); - bool auto_repeat = ovl_auto_repeat(0).bool_value (); + void octave_qscintilla::contextmenu_run (bool) + { + resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - try - { - // Do the job - interp.source_file (file); - } - catch (const execution_exception& ee) - { - // Catch errors otherwise the rest of the interpreter - // will not be executed (cleaning up). + // Take selected code and extend it by commands for echoing each + // evaluated line and for adding the line to the history (use script) + QString code = QString (); + QString hist = QString (); - // New error message and error stack - QString new_msg = QString::fromStdString (ee.message ()); - std::list stack = ee.stack_info (); + // Split contents into single lines and complete commands + QStringList lines = selectedText ().split (QRegExp ("[\r\n]"), +#if defined (HAVE_QT_SPLITBEHAVIOR_ENUM) + Qt::SkipEmptyParts); +#else + QString::SkipEmptyParts); +#endif + for (int i = 0; i < lines.count (); i++) + { + QString line = lines.at (i); + if (line.trimmed ().isEmpty ()) + continue; + QString line_escaped = line; + line_escaped.replace (QString ("'"), QString ("''")); + QString line_history = line; - // Remove line and column from first line of error message only - // if it is related to the tmp itself, i.e. only if the - // the error stack size is 0, 1, or, if in debug mode, 2 - size_t max_stack_size = 1; - if (dbg) - max_stack_size = 2; - if (stack.size () <= max_stack_size) - { - QRegExp rx ("source: error sourcing file [^\n]*$"); - if (new_msg.contains (rx)) - { - // Selected code has syntax errors - new_msg.replace (rx, "error sourcing selected code"); - err_line = 0; // Nothing into history? - } - else - { - // Normal error, detect line and remove file - // name from message - QStringList rx_list; - rx_list << "near line (\\d+),[^\n]*\n"; - rx_list << "near line (\\d+),[^\n]*$"; + // Prevent output of breakpoint in temp. file for keyboard + QString next_bp_quiet; + QString next_bp_quiet_reset; + if (line.contains ("keyboard")) + { + // Define commands for not showing bp location and for resetting + // this in case "keyboard" was within a comment + next_bp_quiet = "__db_next_breakpoint_quiet__;\n"; + next_bp_quiet_reset = "\n__db_next_breakpoint_quiet__(false);"; + } + + // Add codeline + code += next_bp_quiet + line + next_bp_quiet_reset + "\n"; + hist += line_history + "\n"; + } + + octave_stdout << hist.toStdString (); - QStringList replace_list; - replace_list << "\n"; - replace_list << ""; + // Create tmp file with the code to be executed by the interpreter + QPointer tmp_file + = rmgr.create_tmp_file ("m", code); + + bool tmp = (tmp_file && tmp_file->open ()); + if (! tmp) + { + // tmp files not working: use old way to run selection + contextmenu_run_temp_error (); + return; + } + + tmp_file->close (); + + // Create tmp file required for adding command to history + QPointer tmp_hist + = rmgr.create_tmp_file ("", hist); // empty tmp file for history - for (int i = 0; i < rx_list.length (); i++) - { - int pos = 0; - rx = QRegExp (rx_list.at (i)); - pos = rx.indexIn (new_msg, pos); - if (pos != -1) - { - err_line = rx.cap (1).toInt (); - new_msg = new_msg.replace (rx, replace_list.at (i)); - } - } - } - } + tmp = (tmp_hist && tmp_hist->open ()); + if (! tmp) + { + // tmp files not working: use old way to run selection + contextmenu_run_temp_error (); + return; + } + + tmp_hist->close (); + + // Add commands to the history + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + std::string opt = "-r"; + std::string path = tmp_hist->fileName ().toStdString (); - // Drop first stack level, which is the temporary function file, - // or, if in debug mode, drop first two stack levels - if (stack.size () > 0) - stack.pop_back (); - if (dbg && (stack.size () > 0)) - stack.pop_back (); + Fhistory (interp, ovl (opt, path)); + }); + + // Disable opening a file at a breakpoint in case keyboard () is used + gui_settings settings; + + bool show_dbg_file = settings.value (ed_show_dbg_file).toBool (); + settings.setValue (ed_show_dbg_file.key, false); - // Clean up before throwing the modified error. - emit ctx_menu_run_finished_signal (show_dbg_file, err_line, - tmp_file, tmp_hist, - dbg, auto_repeat); + // Let the interpreter execute the tmp file + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD - // New exception with updated message and stack - execution_exception nee (ee.err_type (), ee.identifier (), - new_msg.toStdString (), stack); + std::string file = tmp_file->fileName ().toStdString (); - // Throw - throw (nee); - } + std::string pending_input = command_editor::get_current_line (); - // Clean up + int err_line = -1; // For storing the line of a poss. error - emit ctx_menu_run_finished_signal (show_dbg_file, err_line, - tmp_file, tmp_hist, - dbg, auto_repeat); + // Get current state of auto command repeat in debug mode + octave_value_list ovl_dbg = Fisdebugmode (interp); + bool dbg = ovl_dbg(0).bool_value (); + octave_value_list ovl_auto_repeat = ovl (true); + if (dbg) + ovl_auto_repeat = Fauto_repeat_debug_command (interp, ovl (false), 1); + bool auto_repeat = ovl_auto_repeat(0).bool_value (); - command_editor::erase_empty_line (true); - command_editor::replace_line (""); - command_editor::set_initial_input (pending_input); - command_editor::redisplay (); - command_editor::interrupt_event_loop (); - command_editor::accept_line (); - command_editor::erase_empty_line (true); + try + { + // Do the job + interp.source_file (file); + } + catch (const execution_exception& ee) + { + // Catch errors otherwise the rest of the interpreter + // will not be executed (cleaning up). - }); -} - -void octave_qscintilla::ctx_menu_run_finished (bool show_dbg_file, int, - QTemporaryFile* tmp_file, QTemporaryFile* tmp_hist, - bool dbg, bool auto_repeat) -{ - emit focus_console_after_command_signal (); + // New error message and error stack + QString new_msg = QString::fromStdString (ee.message ()); + std::list stack = ee.stack_info (); - // TODO: Use line nr. (int argument) of possible error for removing - // lines from history that were never executed. For this, - // possible lines from commands at a debug prompt must be - // taken into consideration. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - settings->setValue (ed_show_dbg_file.key, show_dbg_file); - rmgr.remove_tmp_file (tmp_file); - rmgr.remove_tmp_file (tmp_hist); + // Remove line and column from first line of error message only + // if it is related to the tmp itself, i.e. only if the + // the error stack size is 0, 1, or, if in debug mode, 2 + size_t max_stack_size = 1; + if (dbg) + max_stack_size = 2; + if (stack.size () <= max_stack_size) + { + QRegExp rx ("source: error sourcing file [^\n]*$"); + if (new_msg.contains (rx)) + { + // Selected code has syntax errors + new_msg.replace (rx, "error sourcing selected code"); + err_line = 0; // Nothing into history? + } + else + { + // Normal error, detect line and remove file + // name from message + QStringList rx_list; + rx_list << "near line (\\d+),[^\n]*\n"; + rx_list << "near line (\\d+),[^\n]*$"; - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - if (dbg) - Fauto_repeat_debug_command (interp, ovl (auto_repeat)); - }); -} - -// wrappers for dbstop related context menu items + QStringList replace_list; + replace_list << "\n"; + replace_list << ""; -// FIXME: Why can't the data be sent as the argument to the function??? -void octave_qscintilla::contextmenu_break_condition (bool) -{ -#if defined (HAVE_QSCI_VERSION_2_6_0) - QAction *action = qobject_cast(sender ()); - QPoint local_pos = action->data ().value (); + for (int i = 0; i < rx_list.length (); i++) + { + int pos = 0; + rx = QRegExp (rx_list.at (i)); + pos = rx.indexIn (new_msg, pos); + if (pos != -1) + { + err_line = rx.cap (1).toInt (); + new_msg = new_msg.replace (rx, replace_list.at (i)); + } + } + } + } - // pick point just right of margins, so lineAt doesn't give -1 - int margins = marginWidth (1) + marginWidth (2) + marginWidth (3); - local_pos = QPoint (margins + 1, local_pos.y ()); - - emit context_menu_break_condition_signal (lineAt (local_pos)); -#endif -} + // Drop first stack level, which is the temporary function file, + // or, if in debug mode, drop first two stack levels + if (stack.size () > 0) + stack.pop_back (); + if (dbg && (stack.size () > 0)) + stack.pop_back (); -void octave_qscintilla::contextmenu_break_once (const QPoint& local_pos) -{ -#if defined (HAVE_QSCI_VERSION_2_6_0) - emit context_menu_break_once (lineAt (local_pos)); -#else - octave_unused_parameter (local_pos); -#endif -} + // Clean up before throwing the modified error. + emit ctx_menu_run_finished_signal (show_dbg_file, err_line, + tmp_file, tmp_hist, + dbg, auto_repeat); + + // New exception with updated message and stack + execution_exception nee (ee.err_type (), ee.identifier (), + new_msg.toStdString (), stack); + + // Throw + throw (nee); + } + + // Clean up -void octave_qscintilla::text_changed (void) -{ - emit status_update (isUndoAvailable (), isRedoAvailable ()); -} + emit ctx_menu_run_finished_signal (show_dbg_file, err_line, + tmp_file, tmp_hist, + dbg, auto_repeat); -void octave_qscintilla::cursor_position_changed (int line, int col) -{ - // Clear the selection if we move away from it. We have to check the - // position, because we allow entering text at the point of the - // selection to trigger a search and replace that does not clear the - // selection until it is complete. + command_editor::erase_empty_line (true); + command_editor::replace_line (""); + command_editor::set_initial_input (pending_input); + command_editor::redisplay (); + command_editor::interrupt_event_loop (); + command_editor::accept_line (); + command_editor::erase_empty_line (true); - if (! m_selection.isEmpty () - && (line != m_selection_line || col != m_selection_col)) - set_word_selection (); -} + }); + } + + void octave_qscintilla::ctx_menu_run_finished (bool show_dbg_file, int, + QTemporaryFile* tmp_file, QTemporaryFile* tmp_hist, + bool dbg, bool auto_repeat) + { + emit focus_console_after_command_signal (); -// when edit area gets focus update information on undo/redo actions -void octave_qscintilla::focusInEvent (QFocusEvent *focusEvent) -{ - emit status_update (isUndoAvailable (), isRedoAvailable ()); - - QsciScintilla::focusInEvent (focusEvent); -} + // TODO: Use line nr. (int argument) of possible error for removing + // lines from history that were never executed. For this, + // possible lines from commands at a debug prompt must be + // taken into consideration. + resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; -void octave_qscintilla::show_replace_action_tooltip (void) -{ - int pos; - get_current_position (&pos, &m_selection_line, &m_selection_col); + settings.setValue (ed_show_dbg_file.key, show_dbg_file); - // Offer to replace other instances. - - QKeySequence keyseq = Qt::SHIFT + Qt::Key_Return; + rmgr.remove_tmp_file (tmp_file); + rmgr.remove_tmp_file (tmp_hist); - QString msg = (tr ("Press '%1' to replace all occurrences of '%2' with '%3'.") - . arg (keyseq.toString ()) - . arg (m_selection) - . arg (m_selection_replacement)); + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + if (dbg) + Fauto_repeat_debug_command (interp, ovl (auto_repeat)); + }); + } - QPoint global_pos; - QPoint local_pos; + // wrappers for dbstop related context menu items - get_global_textcursor_pos (&global_pos, &local_pos); - - QFontMetrics ttfm (QToolTip::font ()); + // FIXME: Why can't the data be sent as the argument to the function??? + void octave_qscintilla::contextmenu_break_condition (bool) + { +#if defined (HAVE_QSCI_VERSION_2_6_0) + QAction *action = qobject_cast(sender ()); + QPoint local_pos = action->data ().value (); - // Try to avoid overlapping with the text completion dialog - // and the text that is currently being edited. + // pick point just right of margins, so lineAt doesn't give -1 + int margins = marginWidth (1) + marginWidth (2) + marginWidth (3); + local_pos = QPoint (margins + 1, local_pos.y ()); - global_pos += QPoint (2*ttfm.maxWidth (), -3*ttfm.height ()); + emit context_menu_break_condition_signal (lineAt (local_pos)); +#endif + } - QToolTip::showText (global_pos, msg); -} + void octave_qscintilla::contextmenu_break_once (const QPoint& local_pos) + { +#if defined (HAVE_QSCI_VERSION_2_6_0) + emit context_menu_break_once (lineAt (local_pos)); +#else + octave_unused_parameter (local_pos); +#endif + } + + void octave_qscintilla::text_changed (void) + { + emit status_update (isUndoAvailable (), isRedoAvailable ()); + } -void octave_qscintilla::replace_all (const QString& o_str, const QString& n_str, - bool re, bool cs, bool wo) -{ - // get the resulting cursor position - int pos, line, col, nline, ncol; - get_current_position (&pos, &line, &col); + void octave_qscintilla::cursor_position_changed (int line, int col) + { + // Clear the selection if we move away from it. We have to check the + // position, because we allow entering text at the point of the + // selection to trigger a search and replace that does not clear the + // selection until it is complete. - // remember first visible line for restoring the view afterwards - int first_line = firstVisibleLine (); + if (! m_selection.isEmpty () + && (line != m_selection_line || col != m_selection_col)) + set_word_selection (); + } + + // when edit area gets focus update information on undo/redo actions + void octave_qscintilla::focusInEvent (QFocusEvent *focusEvent) + { + emit status_update (isUndoAvailable (), isRedoAvailable ()); + + QsciScintilla::focusInEvent (focusEvent); + } - // search for first occurrence of the detected word - bool find_result_available = findFirst (o_str, re, cs, wo, - false, true, 0, 0); - // replace and find more occurrences in a loop - beginUndoAction (); - while (find_result_available) - { - // findNext doesn't work properly if the length of the replacement - // text is different from the original - replace (n_str); - get_current_position (&pos, &nline, &ncol); + void octave_qscintilla::show_replace_action_tooltip (void) + { + int pos; + get_current_position (&pos, &m_selection_line, &m_selection_col); + + // Offer to replace other instances. + + QKeySequence keyseq = Qt::SHIFT + Qt::Key_Return; + + QString msg = (tr ("Press '%1' to replace all occurrences of '%2' with '%3'.") + . arg (keyseq.toString ()) + . arg (m_selection) + . arg (m_selection_replacement)); + + QPoint global_pos; + QPoint local_pos; + + get_global_textcursor_pos (&global_pos, &local_pos); - find_result_available = findFirst (o_str, re, cs, wo, - false, true, nline, ncol); - } - endUndoAction (); + QFontMetrics ttfm (QToolTip::font ()); + + // Try to avoid overlapping with the text completion dialog + // and the text that is currently being edited. - // restore the visible area - setFirstVisibleLine (first_line); + global_pos += QPoint (2*ttfm.maxWidth (), -3*ttfm.height ()); + + QToolTip::showText (global_pos, msg); + } - // fix cursor column if outside of new line length - int eol_len = eol_string ().length (); - if (line == lines () - 1) - eol_len = 0; - const int col_max = text (line).length () - eol_len; - if (col_max < col) - col = col_max; + void octave_qscintilla::replace_all (const QString& o_str, const QString& n_str, + bool re, bool cs, bool wo) + { + // get the resulting cursor position + int pos, line, col, nline, ncol; + get_current_position (&pos, &line, &col); - setCursorPosition (line, col); -} + // remember first visible line for restoring the view afterwards + int first_line = firstVisibleLine (); -bool octave_qscintilla::event (QEvent *e) -{ - if (m_debug_mode && e->type() == QEvent::ToolTip) - { - QHelpEvent *help_e = static_cast(e); - QString variable = wordAtPoint (help_e->pos()); - QStringList symbol_names - = m_octave_qobj.get_workspace_model ()->get_symbol_names (); - int symbol_idx = symbol_names.indexOf (variable); - if (symbol_idx > -1) - { - QStringList symbol_values - = m_octave_qobj.get_workspace_model ()->get_symbol_values (); - QToolTip::showText (help_e->globalPos(), variable - + " = " + symbol_values.at (symbol_idx)); - } - else - { - QToolTip::hideText(); - e->ignore(); - } + // search for first occurrence of the detected word + bool find_result_available = findFirst (o_str, re, cs, wo, + false, true, 0, 0); + // replace and find more occurrences in a loop + beginUndoAction (); + while (find_result_available) + { + // findNext doesn't work properly if the length of the replacement + // text is different from the original + replace (n_str); + get_current_position (&pos, &nline, &ncol); - return true; - } + find_result_available = findFirst (o_str, re, cs, wo, + false, true, nline, ncol); + } + endUndoAction (); - return QsciScintilla::event(e); -} + // restore the visible area + setFirstVisibleLine (first_line); -void octave_qscintilla::keyPressEvent (QKeyEvent *key_event) -{ - if (m_selection.isEmpty ()) - QsciScintilla::keyPressEvent (key_event); - else - { - int key = key_event->key (); - Qt::KeyboardModifiers modifiers = key_event->modifiers (); + // fix cursor column if outside of new line length + int eol_len = eol_string ().length (); + if (line == lines () - 1) + eol_len = 0; + const int col_max = text (line).length () - eol_len; + if (col_max < col) + col = col_max; + + setCursorPosition (line, col); + } - if (key == Qt::Key_Return && modifiers == Qt::ShiftModifier) - { - replace_all (m_selection, m_selection_replacement, - false, true, true); - - // Clear the selection. - set_word_selection (); - } - else - { - // The idea here is to allow backspace to remove the last - // character of the replacement text to allow minimal editing - // and to also end the selection replacement action if text is - // not valid as a word constituent (control characters, - // etc.). Is there a better way than having special cases for - // DEL and ESC here? + bool octave_qscintilla::event (QEvent *e) + { + if (m_debug_mode && e->type() == QEvent::ToolTip) + { + QHelpEvent *help_e = static_cast(e); + QString variable = wordAtPoint (help_e->pos()); + QStringList symbol_names + = m_octave_qobj.get_workspace_model ()->get_symbol_names (); + int symbol_idx = symbol_names.indexOf (variable); + if (symbol_idx > -1) + { + QStringList symbol_values + = m_octave_qobj.get_workspace_model ()->get_symbol_values (); + QToolTip::showText (help_e->globalPos(), variable + + " = " + symbol_values.at (symbol_idx)); + } + else + { + QToolTip::hideText(); + e->ignore(); + } - QString text = key_event->text (); + return true; + } - bool cancel_replacement = false; + return QsciScintilla::event(e); + } - if (key == Qt::Key_Backspace) - { - if (m_selection_replacement.isEmpty ()) - cancel_replacement = true; - else - m_selection_replacement.chop (1); - } - else if (key == Qt::Key_Delete || key == Qt::Key_Escape) - cancel_replacement = true; - else if (! text.isEmpty ()) - m_selection_replacement += text; - else if (modifiers != Qt::ShiftModifier) - cancel_replacement = true; + void octave_qscintilla::keyPressEvent (QKeyEvent *key_event) + { + if (m_selection.isEmpty ()) + QsciScintilla::keyPressEvent (key_event); + else + { + int key = key_event->key (); + Qt::KeyboardModifiers modifiers = key_event->modifiers (); - // Perform default action. + if (key == Qt::Key_Return && modifiers == Qt::ShiftModifier) + { + replace_all (m_selection, m_selection_replacement, + false, true, true); - QsciScintilla::keyPressEvent (key_event); - - if (cancel_replacement) + // Clear the selection. set_word_selection (); + } + else + { + // The idea here is to allow backspace to remove the last + // character of the replacement text to allow minimal editing + // and to also end the selection replacement action if text is + // not valid as a word constituent (control characters, + // etc.). Is there a better way than having special cases for + // DEL and ESC here? - if (! m_selection_replacement.isEmpty ()) - show_replace_action_tooltip (); - } - } -} + QString text = key_event->text (); + + bool cancel_replacement = false; -void octave_qscintilla::auto_close (int auto_endif, int linenr, - const QString& line, QString& first_word) -{ - // Insert an "end" for an "if" etc., if needed. - // (Use of "while" allows "return" to skip the rest. - // It may be clearer to use "if" and "goto", - // but that violates the coding standards.) + if (key == Qt::Key_Backspace) + { + if (m_selection_replacement.isEmpty ()) + cancel_replacement = true; + else + m_selection_replacement.chop (1); + } + else if (key == Qt::Key_Delete || key == Qt::Key_Escape) + cancel_replacement = true; + else if (! text.isEmpty ()) + m_selection_replacement += text; + else if (modifiers != Qt::ShiftModifier) + cancel_replacement = true; - bool autofill_simple_end = (auto_endif == 2); + // Perform default action. - std::size_t start = line.toStdString ().find_first_not_of (" \t"); + QsciScintilla::keyPressEvent (key_event); - // Check if following line has the same or less indentation - // Check if the following line does not start with - // end* (until) (catch) - if (linenr < lines () - 1) - { - int offset = 2; // linenr is the old line, thus, linnr+1 is the - // new one and can not be taken into account - std::size_t next_start; - QString next_line; + if (cancel_replacement) + set_word_selection (); + + if (! m_selection_replacement.isEmpty ()) + show_replace_action_tooltip (); + } + } + } - do // find next non-blank line - { - next_line = text (linenr + offset++); - next_start = next_line.toStdString ().find_first_not_of (" \t\n"); - } - while (linenr + offset < lines () - && next_start == std::string::npos); + void octave_qscintilla::auto_close (int auto_endif, int linenr, + const QString& line, QString& first_word) + { + // Insert an "end" for an "if" etc., if needed. + // (Use of "while" allows "return" to skip the rest. + // It may be clearer to use "if" and "goto", + // but that violates the coding standards.) + + bool autofill_simple_end = (auto_endif == 2); - if (next_start == std::string::npos) - next_start = 0; - if (start == 0 && next_start == 0) - return; // bug #56160, don't add at 0 - if (next_start > start) // more indented => don't add "end" - return; - if (next_start == start) // same => check if already is "end" - { - QRegExp rx_start = QRegExp (R"((\w+))"); - int tmp = rx_start.indexIn (next_line, start); - if (tmp != -1 && is_end (rx_start.cap(1), first_word)) - return; - } - } + std::size_t start = line.toStdString ().find_first_not_of (" \t"); - // If all of the above, insert a new line, with matching indent - // and either 'end' or 'end...', depending on a flag. + // Check if following line has the same or less indentation + // Check if the following line does not start with + // end* (until) (catch) + if (linenr < lines () - 1) + { + int offset = 2; // linenr is the old line, thus, linnr+1 is the + // new one and can not be taken into account + std::size_t next_start; + QString next_line; + + do // find next non-blank line + { + next_line = text (linenr + offset++); + next_start = next_line.toStdString ().find_first_not_of (" \t\n"); + } + while (linenr + offset < lines () + && next_start == std::string::npos); - // If we insert directly after the last line, the "end" is autoindented, - // so add a dummy line. - if (linenr + 2 == lines ()) - insertAt (QString ("\n"), linenr + 2, 0); + if (next_start == std::string::npos) + next_start = 0; + if (start == 0 && next_start == 0) + return; // bug #56160, don't add at 0 + if (next_start > start) // more indented => don't add "end" + return; + if (next_start == start) // same => check if already is "end" + { + QRegExp rx_start = QRegExp (R"((\w+))"); + int tmp = rx_start.indexIn (next_line, start); + if (tmp != -1 && is_end (rx_start.cap(1), first_word)) + return; + } + } - // For try/catch/end, fill "end" first, so "catch" is top of undo stack - if (first_word == "try") - insertAt (QString (start, ' ') - + (autofill_simple_end ? "end\n" : "end_try_catch\n"), - linenr + 2, 0); - else if (first_word == "unwind_protect") - insertAt (QString (start, ' ') - + (autofill_simple_end ? "end\n" : "end_unwind_protect\n"), - linenr + 2, 0); + // If all of the above, insert a new line, with matching indent + // and either 'end' or 'end...', depending on a flag. + + // If we insert directly after the last line, the "end" is autoindented, + // so add a dummy line. + if (linenr + 2 == lines ()) + insertAt (QString ("\n"), linenr + 2, 0); + + // For try/catch/end, fill "end" first, so "catch" is top of undo stack + if (first_word == "try") + insertAt (QString (start, ' ') + + (autofill_simple_end ? "end\n" : "end_try_catch\n"), + linenr + 2, 0); + else if (first_word == "unwind_protect") + insertAt (QString (start, ' ') + + (autofill_simple_end ? "end\n" : "end_unwind_protect\n"), + linenr + 2, 0); - QString next_line; - if (first_word == "do") - next_line = "until\n"; - else if (first_word == "try") - next_line = "catch\n"; - else if (first_word == "unwind_protect") - next_line = "unwind_protect_cleanup\n"; - else if (autofill_simple_end) - next_line = "end\n"; - else - { - if (first_word == "unwind_protect") - first_word = '_' + first_word; - next_line = "end" + first_word + "\n"; - } + QString next_line; + if (first_word == "do") + next_line = "until\n"; + else if (first_word == "try") + next_line = "catch\n"; + else if (first_word == "unwind_protect") + next_line = "unwind_protect_cleanup\n"; + else if (autofill_simple_end) + next_line = "end\n"; + else + { + if (first_word == "unwind_protect") + first_word = '_' + first_word; + next_line = "end" + first_word + "\n"; + } - //insertAt (QString (start, ' ') + next_line, linenr + 2, 0); - insertAt (next_line, linenr + 2, 0); - setIndentation (linenr + 2, indentation (linenr)); -} + //insertAt (QString (start, ' ') + next_line, linenr + 2, 0); + insertAt (next_line, linenr + 2, 0); + setIndentation (linenr + 2, indentation (linenr)); + } -void octave_qscintilla::dragEnterEvent (QDragEnterEvent *e) -{ - // if is not dragging a url, pass to qscintilla to handle, - // otherwise ignore it so that it will be handled by - // the parent - if (!e->mimeData ()->hasUrls ()) - { - QsciScintilla::dragEnterEvent (e); - } - else - { - e->ignore(); - } -} + void octave_qscintilla::dragEnterEvent (QDragEnterEvent *e) + { + // if is not dragging a url, pass to qscintilla to handle, + // otherwise ignore it so that it will be handled by + // the parent + if (!e->mimeData ()->hasUrls ()) + { + QsciScintilla::dragEnterEvent (e); + } + else + { + e->ignore(); + } + } -void octave_qscintilla::handle_enter_debug_mode (void) -{ - m_debug_mode = true; -} + void octave_qscintilla::handle_enter_debug_mode (void) + { + m_debug_mode = true; + } -void octave_qscintilla::handle_exit_debug_mode (void) -{ - m_debug_mode = false; -} + void octave_qscintilla::handle_exit_debug_mode (void) + { + m_debug_mode = false; + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/main-window.cc --- a/libgui/src/main-window.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/main-window.cc Tue Dec 06 15:45:27 2022 -0500 @@ -92,2825 +92,2809 @@ OCTAVE_BEGIN_NAMESPACE(octave) -main_window::main_window (base_qobject& oct_qobj) -: QMainWindow (), m_octave_qobj (oct_qobj), - m_status_bar (nullptr), - m_command_window (nullptr), - m_history_window (nullptr), - m_file_browser_window (nullptr), - m_editor_window (nullptr), - m_workspace_window (nullptr), - m_external_editor (new external_editor_interface (this, m_octave_qobj)), - m_active_editor (m_external_editor), m_settings_dlg (nullptr), - m_find_files_dlg (nullptr), m_set_path_dlg (nullptr), - m_clipboard (QApplication::clipboard ()), - m_prevent_readline_conflicts (true), - m_prevent_readline_conflicts_menu (false), - m_suppress_dbg_location (true), - m_closing (false), m_file_encoding (QString ()) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - - if (rmgr.is_first_run ()) - { - // Before wizard. - m_octave_qobj.config_translators (); - - welcome_wizard welcomeWizard (m_octave_qobj); - - if (welcomeWizard.exec () == QDialog::Rejected) - exit (1); - - // Install settings file. - rmgr.reload_settings (); - } - else - { - // Get settings file. - rmgr.reload_settings (); - - // After settings. - m_octave_qobj.config_translators (); - } - - setObjectName (gui_obj_name_main_window); - - rmgr.config_icon_theme (); - - rmgr.update_network_settings (); - - // We provide specific terminal capabilities, so ensure that - // TERM is always set appropriately. + main_window::main_window (base_qobject& oct_qobj) + : QMainWindow (), m_octave_qobj (oct_qobj), + m_status_bar (nullptr), + m_command_window (nullptr), + m_history_window (nullptr), + m_file_browser_window (nullptr), + m_editor_window (nullptr), + m_workspace_window (nullptr), + m_external_editor (new external_editor_interface (this)), + m_active_editor (m_external_editor), m_settings_dlg (nullptr), + m_find_files_dlg (nullptr), m_set_path_dlg (nullptr), + m_clipboard (QApplication::clipboard ()), + m_prevent_readline_conflicts (true), + m_prevent_readline_conflicts_menu (false), + m_suppress_dbg_location (true), + m_closing (false), m_file_encoding (QString ()) + { + resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + + gui_settings settings; + + if (! settings.value (global_skip_welcome_wizard).toBool ()) + { + // Before wizard. + m_octave_qobj.config_translators (); + + welcome_wizard welcomeWizard; + + if (welcomeWizard.exec () == QDialog::Rejected) + exit (1); + + settings.setValue (global_skip_welcome_wizard.key, QVariant (true)); + + // Install settings file. + settings.reload (); + } + else + { + // Get settings file. + settings.reload (); + + // After settings. + m_octave_qobj.config_translators (); + } + + setObjectName (gui_obj_name_main_window); + + settings.config_icon_theme (); + + rmgr.update_network_settings (); + + // We provide specific terminal capabilities, so ensure that + // TERM is always set appropriately. #if defined (OCTAVE_USE_WINDOWS_API) - sys::env::putenv ("TERM", "cygwin"); + sys::env::putenv ("TERM", "cygwin"); #else - sys::env::putenv ("TERM", "xterm"); + sys::env::putenv ("TERM", "xterm"); #endif - // FIXME: can we do this job when creating the shortcut manager? - // A quick look shows that it may require some coordination with the - // resource manager. Startup is complicated, but maybe we can make - // it simpler? - shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); - scmgr.init_data (); - - construct_central_widget (); - - m_status_bar = new QStatusBar (this); - m_profiler_status_indicator = new led_indicator (); - QLabel *text = new QLabel (tr ("Profiler")); - m_status_bar->addPermanentWidget (text); - m_status_bar->addPermanentWidget (m_profiler_status_indicator); - - adopt_dock_widgets (); + // FIXME: can we do this job when creating the shortcut manager? + // A quick look shows that it may require some coordination with the + // resource manager. Startup is complicated, but maybe we can make + // it simpler? + shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); + scmgr.init_data (); + + construct_central_widget (); + + m_status_bar = new QStatusBar (this); + m_profiler_status_indicator = new led_indicator (); + QLabel *text = new QLabel (tr ("Profiler")); + m_status_bar->addPermanentWidget (text); + m_status_bar->addPermanentWidget (m_profiler_status_indicator); + + adopt_dock_widgets (); #if defined (HAVE_QGUIAPPLICATION_SETDESKTOPFILENAME) - QGuiApplication::setDesktopFileName ("org.octave.Octave.desktop"); + QGuiApplication::setDesktopFileName ("org.octave.Octave.desktop"); #endif - QApplication *qapp = m_octave_qobj.qapplication (); - - m_default_style = qapp->style ()->objectName (); - m_default_palette = qapp->palette (); - - gui_settings *settings = rmgr.get_settings (); - - bool connect_to_web = true; - QDateTime last_checked; - int serial = 0; - m_active_dock = nullptr; - - if (settings) - { - connect_to_web - = settings->value (nr_allow_connection).toBool (); - - last_checked - = settings->value (nr_last_time).toDateTime (); - - serial = settings->value (nr_last_news).toInt (); - m_default_encoding = settings->value (ed_default_enc).toString (); - } - - QDateTime current = QDateTime::currentDateTime (); - QDateTime one_day_ago = current.addDays (-1); - - if (connect_to_web - && (! last_checked.isValid () || one_day_ago > last_checked)) - emit show_community_news_signal (serial); - - construct_octave_qt_link (); - - // We have to set up all our windows, before we finally launch - // octave. - - construct (); - - read_settings (); - - init_terminal_size (); - - emit init_window_menu (); - - focus_command_window (); -} - -main_window::~main_window (void) { } - -void main_window::adopt_dock_widgets (void) -{ - adopt_terminal_widget (); - adopt_documentation_widget (); - adopt_file_browser_widget (); - adopt_history_widget (); - adopt_workspace_widget (); - adopt_editor_widget (); - adopt_variable_editor_widget (); - - m_previous_dock = m_command_window; -} - -void main_window::adopt_terminal_widget (void) -{ - m_command_window = m_octave_qobj.terminal_widget (this); - - make_dock_widget_connections (m_command_window); - - connect (this, &main_window::settings_changed, - m_command_window, &terminal_dock_widget::notice_settings); - - if (! m_octave_qobj.experimental_terminal_widget ()) - { - QTerminal *cmd_widget = m_command_window->get_qterminal (); - - // The following connections were previously made in - // QTerminal::construct, QWinTerminalImpl::QWinTerminalImpl, and - // QUnixTerminalImpl::QUnixTerminalImpl. Similar actions should - // probably be possible for the new command widget. - - connect (cmd_widget, &QTerminal::report_status_message, - this, &main_window::report_status_message); - - connect (cmd_widget, &QTerminal::edit_mfile_request, - this, &main_window::edit_mfile); - - connect (cmd_widget, &QTerminal::execute_command_in_terminal_signal, - this, &main_window::execute_command_in_terminal); - - connect (this, &main_window::init_terminal_size_signal, - cmd_widget, &QTerminal::init_terminal_size); - - connect (this, &main_window::copyClipboard_signal, - cmd_widget, &QTerminal::copyClipboard); - - connect (this, &main_window::pasteClipboard_signal, - cmd_widget, &QTerminal::pasteClipboard); - - connect (this, &main_window::selectAll_signal, - cmd_widget, &QTerminal::selectAll); - - connect (cmd_widget, &QTerminal::request_edit_mfile_signal, - this, &main_window::edit_mfile); - - connect (cmd_widget, &QTerminal::request_open_file_signal, - this, QOverload::of (&main_window::open_file_signal)); - - connect (cmd_widget, &QTerminal::set_screen_size_signal, - this, &main_window::set_screen_size); - - connect (cmd_widget, &QTerminal::clear_command_window_request, - this, &main_window::handle_clear_command_window_request); - } - else - { - connect (this, &main_window::execute_command_signal, - m_command_window, &terminal_dock_widget::execute_command_signal); - } -} - -void main_window::adopt_documentation_widget (void) -{ - m_doc_browser_window = m_octave_qobj.documentation_widget (this); - - make_dock_widget_connections (m_doc_browser_window); -} - -void main_window::adopt_file_browser_widget (void) -{ - m_file_browser_window = m_octave_qobj.file_browser_widget (this); - - make_dock_widget_connections (m_file_browser_window); - - connect (m_file_browser_window, &files_dock_widget::open_file, - this, QOverload::of (&main_window::open_file_signal)); - connect (m_file_browser_window, - &files_dock_widget::displayed_directory_changed, - this, &main_window::set_current_working_directory); - - connect (m_file_browser_window, &files_dock_widget::modify_path_signal, - this, &main_window::modify_path); - - connect (m_file_browser_window, &files_dock_widget::run_file_signal, - this, &main_window::run_file_in_terminal); - - connect (m_file_browser_window, &files_dock_widget::load_file_signal, - this, &main_window::handle_load_workspace_request); - - connect (m_file_browser_window, &files_dock_widget::open_any_signal, - this, &main_window::handle_open_any_request); - - connect (m_file_browser_window, &files_dock_widget::find_files_signal, - this, &main_window::find_files); -} - -void main_window::adopt_history_widget (void) -{ - m_history_window = m_octave_qobj.history_widget (this); - - make_dock_widget_connections (m_history_window); - - connect (m_history_window, &history_dock_widget::command_create_script, - this, &main_window::new_file_signal); - - connect (m_history_window, &history_dock_widget::command_double_clicked, - this, &main_window::execute_command_in_terminal); -} - -void main_window::adopt_workspace_widget (void) -{ - m_workspace_window = m_octave_qobj.workspace_widget (this); - - make_dock_widget_connections (m_workspace_window); - - connect (m_workspace_window, &workspace_view::command_requested, - this, &main_window::execute_command_in_terminal); -} - -void main_window::adopt_editor_widget (void) -{ - interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj (); - - qt_interpreter_events *qt_link = interp_qobj->qt_link (); + QApplication *qapp = m_octave_qobj.qapplication (); + + m_default_style = qapp->style ()->objectName (); + m_default_palette = qapp->palette (); + + bool connect_to_web = true; + QDateTime last_checked; + int serial = 0; + m_active_dock = nullptr; + + connect_to_web = settings.value (nr_allow_connection).toBool (); + last_checked = settings.value (nr_last_time).toDateTime (); + serial = settings.value (nr_last_news).toInt (); + m_default_encoding = settings.value (ed_default_enc).toString (); + + QDateTime current = QDateTime::currentDateTime (); + QDateTime one_day_ago = current.addDays (-1); + + if (connect_to_web + && (! last_checked.isValid () || one_day_ago > last_checked)) + emit show_community_news_signal (serial); + + construct_octave_qt_link (); + + // We have to set up all our windows, before we finally launch + // octave. + + construct (); + + read_settings (); + + init_terminal_size (); + + emit init_window_menu (); + + focus_command_window (); + } + + main_window::~main_window (void) { } + + void main_window::adopt_dock_widgets (void) + { + adopt_terminal_widget (); + adopt_documentation_widget (); + adopt_file_browser_widget (); + adopt_history_widget (); + adopt_workspace_widget (); + adopt_editor_widget (); + adopt_variable_editor_widget (); + + m_previous_dock = m_command_window; + } + + void main_window::adopt_terminal_widget (void) + { + m_command_window = m_octave_qobj.terminal_widget (this); + + make_dock_widget_connections (m_command_window); + + connect (this, &main_window::settings_changed, + m_command_window, &terminal_dock_widget::notice_settings); + + if (! m_octave_qobj.experimental_terminal_widget ()) + { + QTerminal *cmd_widget = m_command_window->get_qterminal (); + + // The following connections were previously made in + // QTerminal::construct, QWinTerminalImpl::QWinTerminalImpl, and + // QUnixTerminalImpl::QUnixTerminalImpl. Similar actions should + // probably be possible for the new command widget. + + connect (cmd_widget, &QTerminal::report_status_message, + this, &main_window::report_status_message); + + connect (cmd_widget, &QTerminal::edit_mfile_request, + this, &main_window::edit_mfile); + + connect (cmd_widget, &QTerminal::execute_command_in_terminal_signal, + this, &main_window::execute_command_in_terminal); + + connect (this, &main_window::init_terminal_size_signal, + cmd_widget, &QTerminal::init_terminal_size); + + connect (this, &main_window::copyClipboard_signal, + cmd_widget, &QTerminal::copyClipboard); + + connect (this, &main_window::pasteClipboard_signal, + cmd_widget, &QTerminal::pasteClipboard); + + connect (this, &main_window::selectAll_signal, + cmd_widget, &QTerminal::selectAll); + + connect (cmd_widget, &QTerminal::request_edit_mfile_signal, + this, &main_window::edit_mfile); + + connect (cmd_widget, &QTerminal::request_open_file_signal, + this, QOverload::of (&main_window::open_file_signal)); + + connect (cmd_widget, &QTerminal::set_screen_size_signal, + this, &main_window::set_screen_size); + + connect (cmd_widget, &QTerminal::clear_command_window_request, + this, &main_window::handle_clear_command_window_request); + } + else + { + connect (this, &main_window::execute_command_signal, + m_command_window, &terminal_dock_widget::execute_command_signal); + } + } + + void main_window::adopt_documentation_widget (void) + { + m_doc_browser_window = m_octave_qobj.documentation_widget (this); + + make_dock_widget_connections (m_doc_browser_window); + } + + void main_window::adopt_file_browser_widget (void) + { + m_file_browser_window = m_octave_qobj.file_browser_widget (this); + + make_dock_widget_connections (m_file_browser_window); + + connect (m_file_browser_window, &files_dock_widget::open_file, + this, QOverload::of (&main_window::open_file_signal)); + connect (m_file_browser_window, + &files_dock_widget::displayed_directory_changed, + this, &main_window::set_current_working_directory); + + connect (m_file_browser_window, &files_dock_widget::modify_path_signal, + this, &main_window::modify_path); + + connect (m_file_browser_window, &files_dock_widget::run_file_signal, + this, &main_window::run_file_in_terminal); + + connect (m_file_browser_window, &files_dock_widget::load_file_signal, + this, &main_window::handle_load_workspace_request); + + connect (m_file_browser_window, &files_dock_widget::open_any_signal, + this, &main_window::handle_open_any_request); + + connect (m_file_browser_window, &files_dock_widget::find_files_signal, + this, &main_window::find_files); + } + + void main_window::adopt_history_widget (void) + { + m_history_window = m_octave_qobj.history_widget (this); + + make_dock_widget_connections (m_history_window); + + connect (m_history_window, &history_dock_widget::command_create_script, + this, &main_window::new_file_signal); + + connect (m_history_window, &history_dock_widget::command_double_clicked, + this, &main_window::execute_command_in_terminal); + } + + void main_window::adopt_workspace_widget (void) + { + m_workspace_window = m_octave_qobj.workspace_widget (this); + + make_dock_widget_connections (m_workspace_window); + + connect (m_workspace_window, &workspace_view::command_requested, + this, &main_window::execute_command_in_terminal); + } + + void main_window::adopt_editor_widget (void) + { + interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj (); + + qt_interpreter_events *qt_link = interp_qobj->qt_link (); #if defined (HAVE_QSCINTILLA) - file_editor *editor = new file_editor (this, m_octave_qobj); - - make_dock_widget_connections (editor); - - // The editor is currently different from other dock widgets. Until - // those differences are resolved, make interpreter_event - // connections here instead of in base_qobject::editor_widget. - m_octave_qobj.connect_interpreter_events (editor); - - connect (editor, &file_editor::request_settings_dialog, - this, QOverload::of (&main_window::process_settings_dialog_request)); - - connect (editor, &file_editor::request_dbcont_signal, - this, &main_window::debug_continue); - - connect (this, &main_window::update_gui_lexer_signal, - editor, &file_editor::update_gui_lexer_signal); - - connect (editor, &file_editor::execute_command_in_terminal_signal, - this, &main_window::execute_command_in_terminal); - - connect (editor, &file_editor::focus_console_after_command_signal, - this, &main_window::focus_console_after_command); - - connect (editor, &file_editor::run_file_signal, - this, &main_window::run_file_in_terminal); - - connect (editor, &file_editor::edit_mfile_request, - this, &main_window::handle_edit_mfile_request); - - connect (editor, &file_editor::debug_quit_signal, - this, &main_window::debug_quit); - - connect (this, &main_window::editor_focus_changed, - editor, &file_editor::enable_menu_shortcuts); - - connect (this, &main_window::step_into_file_signal, - editor, &file_editor::request_step_into_file); - - connect (editor, &file_editor::editor_tabs_changed_signal, - this, &main_window::editor_tabs_changed); - - connect (editor, &file_editor::request_open_file_external, - m_external_editor, &external_editor_interface::call_custom_editor); - - connect (m_external_editor, &external_editor_interface::request_settings_dialog, - this, &main_window::process_settings_dialog_request); - - connect (this, &main_window::insert_debugger_pointer_signal, - editor, &file_editor::handle_insert_debugger_pointer_request); - - connect (this, &main_window::delete_debugger_pointer_signal, - editor, &file_editor::handle_delete_debugger_pointer_request); - - connect (this, &main_window::update_breakpoint_marker_signal, - editor, &file_editor::handle_update_breakpoint_marker_request); - - // Signals for removing/renaming files/dirs in the file browser - connect (m_file_browser_window, &files_dock_widget::file_remove_signal, - editor, &file_editor::handle_file_remove); - - connect (m_file_browser_window, &files_dock_widget::file_renamed_signal, - editor, &file_editor::handle_file_renamed); - - // Signals for removing/renaming files/dirs in the terminal window - connect (qt_link, &qt_interpreter_events::file_renamed_signal, - editor, &file_editor::handle_file_renamed); - - // Signals for entering/exiting debug mode - connect (qt_link, &qt_interpreter_events::enter_debugger_signal, - editor, &file_editor::handle_enter_debug_mode); - - connect (qt_link, &qt_interpreter_events::exit_debugger_signal, - editor, &file_editor::handle_exit_debug_mode); - - connect (qt_link, &qt_interpreter_events::directory_changed_signal, - editor, &file_editor::update_octave_directory); - - m_editor_window = editor; - - m_editor_menubar = m_editor_window->menubar (); - - m_active_editor = m_editor_window; - - m_editor_window->enable_menu_shortcuts (false); + file_editor *editor = new file_editor (this, m_octave_qobj); + + make_dock_widget_connections (editor); + + // The editor is currently different from other dock widgets. Until + // those differences are resolved, make interpreter_event + // connections here instead of in base_qobject::editor_widget. + m_octave_qobj.connect_interpreter_events (editor); + + connect (editor, &file_editor::request_settings_dialog, + this, QOverload::of (&main_window::process_settings_dialog_request)); + + connect (editor, &file_editor::request_dbcont_signal, + this, &main_window::debug_continue); + + connect (this, &main_window::update_gui_lexer_signal, + editor, &file_editor::update_gui_lexer_signal); + + connect (editor, &file_editor::execute_command_in_terminal_signal, + this, &main_window::execute_command_in_terminal); + + connect (editor, &file_editor::focus_console_after_command_signal, + this, &main_window::focus_console_after_command); + + connect (editor, &file_editor::run_file_signal, + this, &main_window::run_file_in_terminal); + + connect (editor, &file_editor::edit_mfile_request, + this, &main_window::handle_edit_mfile_request); + + connect (editor, &file_editor::debug_quit_signal, + this, &main_window::debug_quit); + + connect (this, &main_window::editor_focus_changed, + editor, &file_editor::enable_menu_shortcuts); + + connect (this, &main_window::step_into_file_signal, + editor, &file_editor::request_step_into_file); + + connect (editor, &file_editor::editor_tabs_changed_signal, + this, &main_window::editor_tabs_changed); + + connect (editor, &file_editor::request_open_file_external, + m_external_editor, &external_editor_interface::call_custom_editor); + + connect (m_external_editor, &external_editor_interface::request_settings_dialog, + this, &main_window::process_settings_dialog_request); + + connect (this, &main_window::insert_debugger_pointer_signal, + editor, &file_editor::handle_insert_debugger_pointer_request); + + connect (this, &main_window::delete_debugger_pointer_signal, + editor, &file_editor::handle_delete_debugger_pointer_request); + + connect (this, &main_window::update_breakpoint_marker_signal, + editor, &file_editor::handle_update_breakpoint_marker_request); + + // Signals for removing/renaming files/dirs in the file browser + connect (m_file_browser_window, &files_dock_widget::file_remove_signal, + editor, &file_editor::handle_file_remove); + + connect (m_file_browser_window, &files_dock_widget::file_renamed_signal, + editor, &file_editor::handle_file_renamed); + + // Signals for removing/renaming files/dirs in the terminal window + connect (qt_link, &qt_interpreter_events::file_renamed_signal, + editor, &file_editor::handle_file_renamed); + + // Signals for entering/exiting debug mode + connect (qt_link, &qt_interpreter_events::enter_debugger_signal, + editor, &file_editor::handle_enter_debug_mode); + + connect (qt_link, &qt_interpreter_events::exit_debugger_signal, + editor, &file_editor::handle_exit_debug_mode); + + connect (qt_link, &qt_interpreter_events::directory_changed_signal, + editor, &file_editor::update_octave_directory); + + m_editor_window = editor; + + m_editor_menubar = m_editor_window->menubar (); + + m_active_editor = m_editor_window; + + m_editor_window->enable_menu_shortcuts (false); #else - m_editor_window = nullptr; - - m_editor_menubar = nullptr; - - m_active_editor = m_external_editor; + m_editor_window = nullptr; + + m_editor_menubar = nullptr; + + m_active_editor = m_external_editor; #endif - connect (qt_link, SIGNAL (edit_file_signal (const QString&)), - m_active_editor, SLOT (handle_edit_file_request (const QString&))); -} - -void main_window::adopt_variable_editor_widget (void) -{ - m_variable_editor_window = m_octave_qobj.variable_editor_widget (this); - - make_dock_widget_connections (m_variable_editor_window); -} - -void main_window::make_dock_widget_connections (octave_dock_widget *dw) -{ - connect (this, &main_window::init_window_menu, - dw, &octave_dock_widget::init_window_menu_entry); - - connect (this, &main_window::settings_changed, - dw, &octave_dock_widget::handle_settings); - - connect (this, &main_window::active_dock_changed, - dw, &octave_dock_widget::handle_active_dock_changed); - - // FIXME: shouldn't this action should be associated with closing - // the main window, not with exiting the application? At one time, - // those two actions happened together, but now it is possible to - // close the main window without exiting the application. - connect (qApp, &QApplication::aboutToQuit, - dw, &octave_dock_widget::save_settings); - - // The following is required when the exp. terminal widget is used - // and the main window is closed (no exit via interpreter) - connect (this, &main_window::close_gui_signal, - dw, &octave_dock_widget::save_settings); -} - -bool main_window::command_window_has_focus (void) const -{ - return m_command_window->has_focus (); -} - -void main_window::focus_command_window (void) -{ - m_command_window->activate (); -} - -void main_window::focus_window (const QString& win_name) -{ - if (win_name == "command") + connect (qt_link, SIGNAL (edit_file_signal (const QString&)), + m_active_editor, SLOT (handle_edit_file_request (const QString&))); + } + + void main_window::adopt_variable_editor_widget (void) + { + m_variable_editor_window = m_octave_qobj.variable_editor_widget (this); + + make_dock_widget_connections (m_variable_editor_window); + } + + void main_window::make_dock_widget_connections (octave_dock_widget *dw) + { + connect (this, &main_window::init_window_menu, + dw, &octave_dock_widget::init_window_menu_entry); + + connect (this, &main_window::settings_changed, + dw, &octave_dock_widget::handle_settings); + + connect (this, &main_window::active_dock_changed, + dw, &octave_dock_widget::handle_active_dock_changed); + + // FIXME: shouldn't this action should be associated with closing + // the main window, not with exiting the application? At one time, + // those two actions happened together, but now it is possible to + // close the main window without exiting the application. + connect (qApp, &QApplication::aboutToQuit, + dw, &octave_dock_widget::save_settings); + + // The following is required when the exp. terminal widget is used + // and the main window is closed (no exit via interpreter) + connect (this, &main_window::close_gui_signal, + dw, &octave_dock_widget::save_settings); + } + + bool main_window::command_window_has_focus (void) const + { + return m_command_window->has_focus (); + } + + void main_window::focus_command_window (void) + { m_command_window->activate (); - else if (win_name == "history") - m_history_window->activate (); - else if (win_name == "workspace") - m_workspace_window->activate (); - else if (win_name == "filebrowser") - m_file_browser_window->activate (); -} - -bool main_window::confirm_shutdown (void) -{ - bool closenow = true; - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (settings->value (global_prompt_to_exit.key, - global_prompt_to_exit.def).toBool ()) - { - int ans = QMessageBox::question (this, tr ("Octave"), - tr ("Are you sure you want to exit Octave?"), - (QMessageBox::Ok - | QMessageBox::Cancel), - QMessageBox::Ok); - - if (ans != QMessageBox::Ok) - closenow = false; - } + } + + void main_window::focus_window (const QString& win_name) + { + if (win_name == "command") + m_command_window->activate (); + else if (win_name == "history") + m_history_window->activate (); + else if (win_name == "workspace") + m_workspace_window->activate (); + else if (win_name == "filebrowser") + m_file_browser_window->activate (); + } + + bool main_window::confirm_shutdown (void) + { + bool closenow = true; + + gui_settings settings; + + if (settings.value (global_prompt_to_exit.key, + global_prompt_to_exit.def).toBool ()) + { + int ans = QMessageBox::question (this, tr ("Octave"), + tr ("Are you sure you want to exit Octave?"), + (QMessageBox::Ok + | QMessageBox::Cancel), + QMessageBox::Ok); + + if (ans != QMessageBox::Ok) + closenow = false; + } #if defined (HAVE_QSCINTILLA) - if (closenow) - closenow = m_editor_window->check_closing (); + if (closenow) + closenow = m_editor_window->check_closing (); +#endif + + return closenow; + } + + // catch focus changes and determine the active dock widget + void main_window::focus_changed (QWidget *, QWidget *new_widget) + { + // If there is no new widget or the new widget is a menu bar + // (when pressing ), we can return immediately and reset the + // focus to the previous widget + if (! new_widget + || (new_widget == menuBar ()) + || (new_widget == m_editor_menubar)) + { + if (m_active_dock) + m_active_dock->setFocus (); + + return; + } + + octave_dock_widget *dock = nullptr; + QWidget *w_new = new_widget; // get a copy of new focus widget + QWidget *start = w_new; // Save it as start of our search + int count = 0; // fallback to prevent endless loop + + QList w_list = dock_widget_list (); + + while (w_new && w_new != m_main_tool_bar && count < 100) + { + // Go through all dock widgets and check whether the current widget + // with focus is a child of one of them. + for (auto w : w_list) + { + if (w->isAncestorOf (w_new)) + dock = w; + } + + if (dock) + break; + + // If not yet found (in case w_new is not a child of its dock widget), + // test next widget in the focus chain + w_new = qobject_cast (w_new->previousInFocusChain ()); + + // Measures preventing an endless loop + if (w_new == start) + break; // We have arrived where we began ==> exit loop + count++; // Limited number of trials + } + + // editor and terminal needs extra handling + octave_dock_widget *edit_dock_widget + = static_cast (m_editor_window); + octave_dock_widget *cmd_dock_widget + = static_cast (m_command_window); + + // if new dock has focus, emit signal and store active focus + // except editor changes to a dialog (dock=0) + if ((dock || m_active_dock != edit_dock_widget) && (dock != m_active_dock)) + { + // signal to all dock widgets for updating the style + emit active_dock_changed (m_active_dock, dock); + + if (dock) + { + QList tabbed = tabifiedDockWidgets (dock); + if (tabbed.contains (m_active_dock)) + dock->set_predecessor_widget (m_active_dock); + } + + // Check whether editor loses or gains focus + int editor = 0; + if (edit_dock_widget == dock) + { + emit editor_focus_changed (true); + editor = 1; + } + else if (edit_dock_widget == m_active_dock) + { + emit editor_focus_changed (false); + editor = -1; + } + + // Check whether terminal loses or gains focus + int cmd_involved = 0; + if (cmd_dock_widget == dock) + cmd_involved = 1; + else if (cmd_dock_widget == m_active_dock) + cmd_involved = -1; + + // If we have to take care of Alt+? accelerators of the main + // window, take result of test for terminal widget above + int command = 0; + if (m_prevent_readline_conflicts_menu) + command = cmd_involved; + + // If editor or command gets/looses focus, disable/enable + // main menu accelerators (Alt + ?) + if (editor || command) + { + int sum = editor + command; + if (sum > 0) + disable_menu_shortcuts (true); + else if (sum < 0) + disable_menu_shortcuts (false); + } + + if (m_active_dock) + m_previous_dock = m_active_dock; + m_active_dock = dock; + + // En-/disable global shortcuts (preventing conflicts with + // readline. Do it here because it relies on m_active_dock + if (cmd_involved) + configure_shortcuts (); + } + } + + void main_window::request_reload_settings (void) + { + emit settings_changed (); + } + + void main_window::report_status_message (const QString& statusMessage) + { + m_status_bar->showMessage (statusMessage, 1000); + } + + void main_window::handle_save_workspace_request (void) + { + // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. + int opts = 0; // No options by default. + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) + opts = QFileDialog::DontUseNativeDialog; + + QString file + = QFileDialog::getSaveFileName (this, tr ("Save Workspace As"), ".", + nullptr, nullptr, QFileDialog::Option (opts)); + + if (! file.isEmpty ()) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + Fsave (interp, ovl (file.toStdString ())); + }); + } + } + + void main_window::handle_load_workspace_request (const QString& file_arg) + { + // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. + int opts = 0; // No options by default. + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) + opts = QFileDialog::DontUseNativeDialog; + + QString file = file_arg; + + if (file.isEmpty ()) + file = QFileDialog::getOpenFileName (this, tr ("Load Workspace"), ".", + nullptr, nullptr, QFileDialog::Option (opts)); + + if (! file.isEmpty ()) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + Fload (interp, ovl (file.toStdString ())); + + tree_evaluator& tw = interp.get_evaluator (); + + event_manager& xevmgr = interp.get_event_manager (); + + xevmgr.set_workspace (true, tw.get_symbol_info ()); + }); + } + } + + void main_window::handle_open_any_request (const QString& file_arg) + { + if (! file_arg.isEmpty ()) + { + std::string file = file_arg.toStdString (); + + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + interp.feval ("open", ovl (file)); + + // Update the workspace since open.m may have loaded new + // variables. + tree_evaluator& tw = interp.get_evaluator (); + + event_manager& xevmgr = interp.get_event_manager (); + + xevmgr.set_workspace (true, tw.get_symbol_info ()); + }); + } + } + + void main_window::handle_clear_workspace_request (void) + { + emit interpreter_event + ([] (interpreter& interp) + { + // INTERPRETER THREAD + + Fclear (interp); + }); + } + + void main_window::handle_clear_command_window_request (void) + { + emit interpreter_event + ([] (void) + { + // INTERPRETER THREAD + + command_editor::kill_full_line (); + command_editor::clear_screen (); + }); + } + + void main_window::handle_clear_history_request (void) + { + emit interpreter_event + ([] (interpreter& interp) + { + // INTERPRETER THREAD + + history_system& history_sys = interp.get_history_system (); + + history_sys.do_history (ovl ("-c")); + }); + } + + void main_window::handle_undo_request (void) + { + if (command_window_has_focus ()) + { + emit interpreter_event + ([] (void) + { + // INTERPRETER THREAD + + command_editor::undo (); + command_editor::redisplay (); + }); + } + else + emit undo_signal (); + } + + void main_window::modify_path (const QStringList& dir_list, + bool rm, bool subdirs) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + octave_value_list paths; + + // Loop over all directories in order to get all subdirs + for (octave_idx_type i = 0; i < dir_list.length (); i++) + { + std::string dir = dir_list.at(i).toStdString (); + + if (subdirs) + paths.append (Fgenpath (ovl (dir))); + else + paths.append (dir); + } + + if (rm) + Frmpath (interp, paths); + else + Faddpath (interp, paths); + }); + } + + void main_window::edit_mfile (const QString& name, int line) + { + handle_edit_mfile_request (name, QString (), QString (), line); + } + + void main_window::file_remove_proxy (const QString& o, const QString& n) + { + interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj (); + + qt_interpreter_events *qt_link = interp_qobj->qt_link (); + + // Wait for worker to suspend + qt_link->lock (); + // Close the file if opened +#if defined (HAVE_QSCINTILLA) + m_editor_window->handle_file_remove (o, n); +#else + octave_unused_parameter (o); + octave_unused_parameter (n); #endif - return closenow; -} - -// catch focus changes and determine the active dock widget -void main_window::focus_changed (QWidget *, QWidget *new_widget) -{ - // If there is no new widget or the new widget is a menu bar - // (when pressing ), we can return immediately and reset the - // focus to the previous widget - if (! new_widget - || (new_widget == menuBar ()) - || (new_widget == m_editor_menubar)) - { - if (m_active_dock) - m_active_dock->setFocus (); - - return; - } - - octave_dock_widget *dock = nullptr; - QWidget *w_new = new_widget; // get a copy of new focus widget - QWidget *start = w_new; // Save it as start of our search - int count = 0; // fallback to prevent endless loop - - QList w_list = dock_widget_list (); - - while (w_new && w_new != m_main_tool_bar && count < 100) - { - // Go through all dock widgets and check whether the current widget - // with focus is a child of one of them. - for (auto w : w_list) - { - if (w->isAncestorOf (w_new)) - dock = w; - } - - if (dock) - break; - - // If not yet found (in case w_new is not a child of its dock widget), - // test next widget in the focus chain - w_new = qobject_cast (w_new->previousInFocusChain ()); - - // Measures preventing an endless loop - if (w_new == start) - break; // We have arrived where we began ==> exit loop - count++; // Limited number of trials - } - - // editor and terminal needs extra handling - octave_dock_widget *edit_dock_widget - = static_cast (m_editor_window); - octave_dock_widget *cmd_dock_widget - = static_cast (m_command_window); - - // if new dock has focus, emit signal and store active focus - // except editor changes to a dialog (dock=0) - if ((dock || m_active_dock != edit_dock_widget) && (dock != m_active_dock)) - { - // signal to all dock widgets for updating the style - emit active_dock_changed (m_active_dock, dock); - - if (dock) - { - QList tabbed = tabifiedDockWidgets (dock); - if (tabbed.contains (m_active_dock)) - dock->set_predecessor_widget (m_active_dock); - } - - // Check whether editor loses or gains focus - int editor = 0; - if (edit_dock_widget == dock) - { - emit editor_focus_changed (true); - editor = 1; - } - else if (edit_dock_widget == m_active_dock) - { - emit editor_focus_changed (false); - editor = -1; - } - - // Check whether terminal loses or gains focus - int cmd_involved = 0; - if (cmd_dock_widget == dock) - cmd_involved = 1; - else if (cmd_dock_widget == m_active_dock) - cmd_involved = -1; - - // If we have to take care of Alt+? accelerators of the main - // window, take result of test for terminal widget above - int command = 0; - if (m_prevent_readline_conflicts_menu) - command = cmd_involved; - - // If editor or command gets/looses focus, disable/enable - // main menu accelerators (Alt + ?) - if (editor || command) - { - int sum = editor + command; - if (sum > 0) - disable_menu_shortcuts (true); - else if (sum < 0) - disable_menu_shortcuts (false); - } - - if (m_active_dock) - m_previous_dock = m_active_dock; - m_active_dock = dock; - - // En-/disable global shortcuts (preventing conflicts with - // readline. Do it here because it relies on m_active_dock - if (cmd_involved) - configure_shortcuts (); - } -} - -void main_window::request_reload_settings (void) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (settings) - emit settings_changed (settings); -} - -void main_window::report_status_message (const QString& statusMessage) -{ - m_status_bar->showMessage (statusMessage, 1000); -} - -void main_window::handle_save_workspace_request (void) -{ - // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - int opts = 0; // No options by default. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) - opts = QFileDialog::DontUseNativeDialog; - - QString file - = QFileDialog::getSaveFileName (this, tr ("Save Workspace As"), ".", - nullptr, nullptr, QFileDialog::Option (opts)); - - if (! file.isEmpty ()) - { - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - Fsave (interp, ovl (file.toStdString ())); - }); - } -} - -void main_window::handle_load_workspace_request (const QString& file_arg) -{ - // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - int opts = 0; // No options by default. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) - opts = QFileDialog::DontUseNativeDialog; - - QString file = file_arg; - - if (file.isEmpty ()) - file = QFileDialog::getOpenFileName (this, tr ("Load Workspace"), ".", - nullptr, nullptr, QFileDialog::Option (opts)); - - if (! file.isEmpty ()) - { - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - Fload (interp, ovl (file.toStdString ())); - - tree_evaluator& tw = interp.get_evaluator (); - - event_manager& xevmgr = interp.get_event_manager (); - - xevmgr.set_workspace (true, tw.get_symbol_info ()); - }); - } -} - -void main_window::handle_open_any_request (const QString& file_arg) -{ - if (! file_arg.isEmpty ()) - { - std::string file = file_arg.toStdString (); - - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - interp.feval ("open", ovl (file)); - - // Update the workspace since open.m may have loaded new - // variables. - tree_evaluator& tw = interp.get_evaluator (); - - event_manager& xevmgr = interp.get_event_manager (); - - xevmgr.set_workspace (true, tw.get_symbol_info ()); - }); - } -} - -void main_window::handle_clear_workspace_request (void) -{ - emit interpreter_event - ([] (interpreter& interp) - { - // INTERPRETER THREAD - - Fclear (interp); - }); -} - -void main_window::handle_clear_command_window_request (void) -{ - emit interpreter_event - ([] (void) - { - // INTERPRETER THREAD - - command_editor::kill_full_line (); - command_editor::clear_screen (); - }); -} - -void main_window::handle_clear_history_request (void) -{ - emit interpreter_event - ([] (interpreter& interp) - { - // INTERPRETER THREAD - - history_system& history_sys = interp.get_history_system (); - - history_sys.do_history (ovl ("-c")); - }); -} - -void main_window::handle_undo_request (void) -{ - if (command_window_has_focus ()) - { - emit interpreter_event - ([] (void) - { - // INTERPRETER THREAD - - command_editor::undo (); - command_editor::redisplay (); - }); - } - else - emit undo_signal (); -} - -void main_window::modify_path (const QStringList& dir_list, - bool rm, bool subdirs) -{ - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - octave_value_list paths; - - // Loop over all directories in order to get all subdirs - for (octave_idx_type i = 0; i < dir_list.length (); i++) - { - std::string dir = dir_list.at(i).toStdString (); - - if (subdirs) - paths.append (Fgenpath (ovl (dir))); - else - paths.append (dir); - } - - if (rm) - Frmpath (interp, paths); - else - Faddpath (interp, paths); - }); -} - -void main_window::edit_mfile (const QString& name, int line) -{ - handle_edit_mfile_request (name, QString (), QString (), line); -} - -void main_window::file_remove_proxy (const QString& o, const QString& n) -{ - interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj (); - - qt_interpreter_events *qt_link = interp_qobj->qt_link (); - - // Wait for worker to suspend - qt_link->lock (); - // Close the file if opened + // We are done: Unlock and wake the worker thread + qt_link->unlock (); + qt_link->wake_all (); + } + + void main_window::open_online_documentation_page (void) + { + QDesktopServices::openUrl + (QUrl ("https://octave.org/doc/interpreter/index.html")); + } + + void main_window::open_bug_tracker_page (void) + { + QDesktopServices::openUrl (QUrl ("https://octave.org/bugs.html")); + } + + void main_window::open_octave_packages_page (void) + { + QDesktopServices::openUrl (QUrl ("https://packages.octave.org/index.html")); + } + + void main_window::open_contribute_page (void) + { + QDesktopServices::openUrl (QUrl ("https://octave.org/contribute.html")); + } + + void main_window::open_donate_page (void) + { + QDesktopServices::openUrl (QUrl ("https://octave.org/donate.html")); + } + + void main_window::process_settings_dialog_request (const QString& desired_tab) + { + if (m_settings_dlg) // m_settings_dlg is a guarded pointer! + { + // here the dialog is still open and called once again + if (! desired_tab.isEmpty ()) + m_settings_dlg->show_tab (desired_tab); + return; + } + + m_settings_dlg = new settings_dialog (this, m_octave_qobj, desired_tab); + + connect (m_settings_dlg, &settings_dialog::apply_new_settings, + this, &main_window::request_reload_settings); + + m_settings_dlg->setModal (false); + m_settings_dlg->setAttribute (Qt::WA_DeleteOnClose); + m_settings_dlg->show (); + } + + void main_window::show_about_octave (void) + { + std::string message + = octave_name_version_copyright_copying_warranty_and_bugs (true); + + QMessageBox::about (this, tr ("About Octave"), + QString::fromStdString (message)); + } + + void main_window::notice_settings (bool update_by_worker) + { + gui_settings settings; + + // Get desired style from preferences or take the default one if + // the desired one is not found + QString preferred_style = settings.value (global_style).toString (); + + if (preferred_style == global_style.def.toString ()) + preferred_style = m_default_style; + + QApplication* qapp = m_octave_qobj.qapplication(); + + if (preferred_style == global_extra_styles.at (EXTRA_STYLE_FUSION_DARK)) + { + QStyle *new_style = QStyleFactory::create (QStringLiteral("Fusion")); + if (new_style) + qapp->setStyle (new_style); + qapp->setPalette (getFusionDarkPalette()); + qapp->setStyleSheet ("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }"); + } + else + { + QStyle *new_style = QStyleFactory::create (preferred_style); + if (new_style) + { + qapp->setPalette (m_default_palette); + qapp->setStyle (new_style); + } + } + + // the widget's icons (when floating) + QString icon_set = settings.value (dw_icon_set).toString (); + + QString icon; + for (auto *widget : dock_widget_list ()) + { + QString name = widget->objectName (); + if (! name.isEmpty ()) + { + // if child has a name + icon = dw_icon_set_names[icon_set]; + if (icon_set != "NONE") + icon += name + ".png"; // add widget name and ext. + widget->setWindowIcon (QIcon (icon)); + } + } + + int size_idx = settings.value (global_icon_size).toInt (); + size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2 + + QStyle *st = style (); + int icon_size = st->pixelMetric (global_icon_sizes[size_idx]); + m_main_tool_bar->setIconSize (QSize (icon_size, icon_size)); + + if (settings.value (global_status_bar).toBool ()) + m_status_bar->show (); + else + m_status_bar->hide (); + + m_prevent_readline_conflicts + = settings.value (sc_prevent_rl_conflicts).toBool (); + + m_prevent_readline_conflicts_menu + = settings.value (sc_prevent_rl_conflicts_menu).toBool (); + + m_suppress_dbg_location + = ! settings.value (cs_dbg_location).toBool (); + + resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + rmgr.update_network_settings (); + + emit active_dock_changed (nullptr, m_active_dock); // update dock widget styles + + configure_shortcuts (); + + bool do_disable_main_menu_shortcuts + = (m_active_dock == m_editor_window) + || (m_prevent_readline_conflicts_menu + && (m_active_dock == m_command_window)); + + disable_menu_shortcuts (do_disable_main_menu_shortcuts); + + // Check whether some octave internal preferences have to be updated + QString new_default_encoding + = settings.value (ed_default_enc).toString (); + // Do not update internal pref only if a) this update was not initiated + // by the worker and b) the pref has really changes + if (! update_by_worker && (new_default_encoding != m_default_encoding)) + update_default_encoding (new_default_encoding); + + // Set cursor blinking depending on the settings + // Cursor blinking: consider old terminal related setting if not yet set + // TODO: This pref. can be deprecated / removed if Qt adds support for + // getting the cursor blink preferences from all OS environments + bool cursor_blinking; + + if (settings.contains (global_cursor_blinking.key)) + cursor_blinking = settings.value (global_cursor_blinking).toBool (); + else + cursor_blinking = settings.value (cs_cursor_blinking).toBool (); + + if (cursor_blinking) + QApplication::setCursorFlashTime (1000); // 1000 ms flash time + else + QApplication::setCursorFlashTime (0); // no flashing + + } + + QPalette main_window::getFusionDarkPalette() + { + QPalette darkPalette; + darkPalette.setColor(QPalette::Window, QColor(53, 53, 53)); + darkPalette.setColor(QPalette::WindowText, Qt::white); + darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(127, 127, 127)); + darkPalette.setColor(QPalette::Base, QColor(42, 42, 42)); + darkPalette.setColor(QPalette::AlternateBase, QColor(66, 66, 66)); + darkPalette.setColor(QPalette::ToolTipBase, Qt::white); + darkPalette.setColor(QPalette::ToolTipText, Qt::white); + darkPalette.setColor(QPalette::Text, Qt::white); + darkPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127)); + darkPalette.setColor(QPalette::Dark, QColor(35, 35, 35)); + darkPalette.setColor(QPalette::Shadow, QColor(20, 20, 20)); + darkPalette.setColor(QPalette::Button, QColor(53, 53, 53)); + darkPalette.setColor(QPalette::ButtonText, Qt::white); + darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127)); + darkPalette.setColor(QPalette::BrightText, Qt::red); + darkPalette.setColor(QPalette::Link, QColor(42, 130, 218)); + darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218)); + darkPalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(80, 80, 80)); + darkPalette.setColor(QPalette::HighlightedText, Qt::white); + darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(127, 127, 127)); + + return darkPalette; + } + + void main_window::prepare_to_exit (void) + { + // Find files dialog is constructed dynamically, not at time of main_window + // construction. Connecting it to qApp aboutToQuit signal would have + // caused it to run after gui_settings is deleted. + if (m_find_files_dlg) + m_find_files_dlg->save_settings (); + + if (m_set_path_dlg) + m_set_path_dlg->save_settings (); + + write_settings (); + + // No more active dock, otherwise, focus_changed would try to set + // the focus to a dock widget that might not exist anymore + m_active_dock = nullptr; + } + + void main_window::go_to_previous_widget (void) + { + m_previous_dock->activate (); + } + + void main_window::update_octave_directory (const QString& dir) + { + // Remove existing entry, if any, then add new directory at top and + // mark it as the current directory. Finally, update the file list + // widget. + + int index = m_current_directory_combo_box->findText (dir); + + if (index >= 0) + m_current_directory_combo_box->removeItem (index); + + m_current_directory_combo_box->insertItem (0, dir); + m_current_directory_combo_box->setCurrentIndex (0); + } + + void main_window::browse_for_directory (void) + { + // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. + int opts = QFileDialog::ShowDirsOnly; + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) + opts = QFileDialog::DontUseNativeDialog; + + QString dir + = QFileDialog::getExistingDirectory (this, tr ("Browse directories"), nullptr, + QFileDialog::Option (opts)); + + set_current_working_directory (dir); + + // FIXME: on Windows systems, the command window freezes after the + // previous actions. Forcing the focus appears to unstick it. + + focus_command_window (); + } + + void main_window::set_current_working_directory (const QString& dir) + { + // Change to dir if it is an existing directory. + + QString xdir = (dir.isEmpty () ? "." : dir); + + QFileInfo fileInfo (xdir); + + if (fileInfo.exists () && fileInfo.isDir ()) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + interp.chdir (xdir.toStdString ()); + }); + } + } + + void main_window::change_directory_up (void) + { + set_current_working_directory (".."); + } + + // Slot that is called if return is pressed in the line edit of the + // combobox to change to a new directory or a directory that is already + // in the drop down list. + + void main_window::accept_directory_line_edit (void) + { + // Get new directory name, and change to it if it is new. Otherwise, + // the combo box will trigger the "activated" signal to change to the + // directory. + + QString dir = m_current_directory_combo_box->currentText (); + + int index = m_current_directory_combo_box->findText (dir); + + if (index < 0) + set_current_working_directory (dir); + } + + void main_window::execute_command_in_terminal (const QString& command) + { + if (m_octave_qobj.experimental_terminal_widget ()) + { + emit execute_command_signal (command); + } + else + { + emit interpreter_event + ([=] (void) + { + // INTERPRETER THREAD + + std::string pending_input = command_editor::get_current_line (); + + command_editor::set_initial_input (pending_input); + command_editor::replace_line (command.toStdString ()); + command_editor::redisplay (); + command_editor::interrupt_event_loop (); + command_editor::accept_line (); + }); + } + + focus_console_after_command (); + } + + void main_window::run_file_in_terminal (const QFileInfo& info) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + QString function_name = info.fileName (); + function_name.chop (info.suffix ().length () + 1); + std::string file_path = info.absoluteFilePath ().toStdString (); + + std::string pending_input = command_editor::get_current_line (); + + if (valid_identifier (function_name.toStdString ())) + { + // Valid identifier: call as function with possibility to + // debug. + + load_path& lp = interp.get_load_path (); + + std::string path = info.absolutePath ().toStdString (); + + if (lp.contains_file_in_dir (file_path, path)) + command_editor::replace_line (function_name.toStdString ()); + } + else + { + // No valid identifier: use equivalent of Fsource (), no + // debug possible. + + interp.source_file (file_path); + + command_editor::replace_line (""); + } + + command_editor::set_initial_input (pending_input); + command_editor::redisplay (); + command_editor::interrupt_event_loop (); + command_editor::accept_line (); + }); + + focus_console_after_command (); + } + + void main_window::handle_new_figure_request (void) + { + emit interpreter_event + ([] (interpreter& interp) + { + // INTERPRETER THREAD + + Fbuiltin (interp, ovl ("figure")); + Fdrawnow (interp); + }); + } + + void main_window::handle_enter_debugger (void) + { + setWindowTitle ("Octave (Debugging)"); + + m_debug_continue->setEnabled (true); + m_debug_step_into->setEnabled (true); + m_debug_step_over->setEnabled (true); + m_debug_step_out->setEnabled (true); + m_debug_quit->setEnabled (true); + } + + void main_window::handle_exit_debugger (void) + { + setWindowTitle ("Octave"); + + m_debug_continue->setEnabled (false); + m_debug_step_into->setEnabled (false); + m_debug_step_over->setEnabled (m_editor_has_tabs && m_editor_is_octave_file); + m_debug_step_out->setEnabled (false); + m_debug_quit->setEnabled (false); + } + + void main_window::debug_continue (void) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location)); + Fdbcont (interp); + + command_editor::interrupt (true); + }); + } + + void main_window::debug_step_into (void) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location)); + Fdbstep (interp, ovl ("in")); + + command_editor::interrupt (true); + }); + } + + void main_window::debug_step_over (void) + { + if (m_debug_quit->isEnabled ()) + { + // We are in debug mode, just call dbstep. + + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + F__db_next_breakpoint_quiet__ (interp, + ovl (m_suppress_dbg_location)); + Fdbstep (interp); + + command_editor::interrupt (true); + }); + } + else + { + // Not in debug mode: "step into" the current editor file + emit step_into_file_signal (); + } + } + + void main_window::debug_step_out (void) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location)); + Fdbstep (interp, ovl ("out")); + + command_editor::interrupt (true); + }); + } + + void main_window::debug_quit (void) + { + emit interpreter_event + ([] (interpreter& interp) + { + // INTERPRETER THREAD + + Fdbquit (interp); + + command_editor::interrupt (true); + }); + } + + // + // Functions related to file editing + // + // These are moved from editor to here for also using them when octave + // is built without qscintilla + // + void main_window::request_open_file (void) + { + // Open file isn't a file_editor_tab or editor function since the file + // might be opened in an external editor. Hence, functionality is here. + + gui_settings settings; + + bool is_internal = m_editor_window + && ! settings.value (global_use_custom_editor.key, + global_use_custom_editor.def).toBool (); + + // Create a NonModal message. + QWidget *p = this; + if (is_internal) + p = m_editor_window; + QFileDialog *fileDialog = new QFileDialog (p); + fileDialog->setNameFilter (tr ("Octave Files (*.m);;All Files (*)")); + + fileDialog->setAcceptMode (QFileDialog::AcceptOpen); + fileDialog->setViewMode (QFileDialog::Detail); + fileDialog->setFileMode (QFileDialog::ExistingFiles); + fileDialog->setDirectory (m_current_directory_combo_box->itemText (0)); + + // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. + if (! settings.value (global_use_native_dialogs).toBool ()) + fileDialog->setOption(QFileDialog::DontUseNativeDialog); + + connect (fileDialog, &QFileDialog::filesSelected, + this, &main_window::request_open_files); + + fileDialog->setWindowModality (Qt::NonModal); + fileDialog->setAttribute (Qt::WA_DeleteOnClose); + fileDialog->show (); + } + + // Create a new script + void main_window::request_new_script (const QString& commands) + { + emit new_file_signal (commands); + } + + // Create a new function and open it + void main_window::request_new_function (bool) + { + bool ok; + // Get the name of the new function: Parent of the input dialog is the + // editor window or the main window. The latter is chosen, if a custom + // editor is used or qscintilla is not available + QWidget *p = m_editor_window; + + gui_settings settings; + + if (! p || settings.value (global_use_custom_editor.key, + global_use_custom_editor.def).toBool ()) + p = this; + QString new_name = QInputDialog::getText (p, tr ("New Function"), + tr ("New function name:\n"), QLineEdit::Normal, "", &ok); + + if (ok && new_name.length () > 0) + { + // append suffix if it does not already exist + if (new_name.rightRef (2) != ".m") + new_name.append (".m"); + // check whether new files are created without prompt + if (! settings.value (ed_create_new_file).toBool ()) + { + // no, so enable this settings and wait for end of new file loading + settings.setValue (ed_create_new_file.key, true); + connect (m_editor_window, SIGNAL (file_loaded_signal (void)), + this, SLOT (restore_create_file_setting (void))); + } + // start the edit command + execute_command_in_terminal ("edit " + new_name); + } + } + + void main_window::handle_edit_mfile_request (const QString& fname, + const QString& ffile, + const QString& curr_dir, + int line) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + // Split possible subfunctions + QStringList fcn_list = fname.split ('>'); + QString fcn_name = fcn_list.at (0) + ".m"; + + // FIXME: could use symbol_exist directly, but we may also want + // to fix that to be a member function in the interpreter + // class? + + // Is it a regular function within the search path? (Call Fexist) + octave_value_list fct = Fexist (interp, ovl (fname.toStdString ()),0); + int type = fct (0).int_value (); + + QString message = QString (); + QString filename = QString (); + + switch (type) + { + case 3: + case 5: + case 103: + message = tr ("%1 is a built-in, compiled or inline\n" + "function and can not be edited."); + break; + + case 2: + // FIXME: could use a load_path function directly. + octave_value_list file_path + = Ffile_in_loadpath (interp, ovl (fcn_name.toStdString ()), 0); + if (file_path.length () > 0) + filename = QString::fromStdString (file_path (0).string_value ()); + break; + } + + if (filename.isEmpty () && message.isEmpty ()) + { + // No error so far, but function still not known + // -> try directory of edited file + // get directory + QDir dir; + if (ffile.isEmpty ()) + { + if (curr_dir.isEmpty ()) + dir = QDir (m_current_directory_combo_box->itemText (0)); + else + dir = QDir (curr_dir); + } + else + dir = QDir (QFileInfo (ffile).canonicalPath ()); + + QFileInfo file = QFileInfo (dir, fcn_name); + if (file.exists ()) + filename = file.canonicalFilePath (); // local file exists + else + { + // local file does not exist -> try private directory + file = QFileInfo (ffile); + file = QFileInfo (QDir (file.canonicalPath () + "/private"), + fcn_name); + if (file.exists ()) + filename = file.canonicalFilePath (); // private function exists + else + message = tr ("Can not find function %1"); // no file found + + } + } + + if (! message.isEmpty ()) + { + emit warning_function_not_found_signal (message.arg (fname)); + return; + } + + if (! filename.endsWith (".m")) + filename.append (".m"); + + // default encoding + emit open_file_signal (filename, QString (), line); + }); + } + + void main_window::warning_function_not_found (const QString& message) + { + QMessageBox *msgBox = new QMessageBox (QMessageBox::Critical, + tr ("Octave Editor"), + message, QMessageBox::Ok, this); + msgBox->setWindowModality (Qt::NonModal); + msgBox->setAttribute (Qt::WA_DeleteOnClose); + msgBox->show (); + } + + void main_window::handle_insert_debugger_pointer_request (const QString& file, + int line) + { + bool cmd_focus = command_window_has_focus (); + + emit insert_debugger_pointer_signal (file, line); + + if (cmd_focus) + focus_command_window (); + } + + void main_window::handle_delete_debugger_pointer_request (const QString& file, + int line) + { + bool cmd_focus = command_window_has_focus (); + + emit delete_debugger_pointer_signal (file, line); + + if (cmd_focus) + focus_command_window (); + } + + void main_window::handle_update_breakpoint_marker_request (bool insert, + const QString& file, + int line, + const QString& cond) + { + bool cmd_focus = command_window_has_focus (); + + emit update_breakpoint_marker_signal (insert, file, line, cond); + + if (cmd_focus) + focus_command_window (); + } + + void main_window::read_settings (void) + { + gui_settings settings; + + set_window_layout (); + + // restore the list of the last directories + QStringList curr_dirs = settings.value (mw_dir_list).toStringList (); + for (int i=0; i < curr_dirs.size (); i++) + { + m_current_directory_combo_box->addItem (curr_dirs.at (i)); + } + + emit settings_changed (); + } + + void main_window::init_terminal_size (void) + { + emit init_terminal_size_signal (); + } + + void main_window::set_window_layout (void) + { + gui_settings settings; + + // For resetting from some inconsistent state, first reset layout + // without saving or showing it + do_reset_windows (true, false); + + // Restore main window state and geometry from settings file or, in case + // of an error (no pref values yet), from the default layout. + if (! restoreGeometry (settings.value (mw_geometry).toByteArray ())) + { + do_reset_windows (true); + return; + } + + if (isMaximized()) + { + // If the window state is restored to maximized layout, the + // horizontal layout is not preserved. This cann be avoided by + // setting the geometry to the max. available geometry. However, on + // X11, the available geometry (excluding task bar etc.) is equal to + // the total geometry leading to a full screen mode without window + // decorations. This in turn can be avoided by explicitly adding + // a title bar in the window flags. + + // Get available geometry for current screen and set this + // window's geometry to it. + QScreen *s = windowHandle ()->screen (); + QRect av_geom = s->availableGeometry (); + setGeometry (av_geom); // Set (correct) available geometry + + // Force full title bar + setWindowFlags(Qt::WindowTitleHint + | Qt::WindowMinMaxButtonsHint + | Qt::WindowSystemMenuHint + | Qt::WindowCloseButtonHint); + } + + if (! restoreState (settings.value (mw_state).toByteArray ())) + { + do_reset_windows (true); + return; + } + + // Restore the geometry of all dock-widgets + + for (auto *widget : dock_widget_list ()) + { + // Leave any widgets that existed before main_window was created + // as they were. + + if (widget->adopted ()) + continue; + + QString name = widget->objectName (); + + if (! name.isEmpty ()) + { + bool floating = false; + bool visible = true; + + floating = settings.value + (dw_is_floating.key.arg (name), dw_is_floating.def).toBool (); + visible = settings.value + (dw_is_visible.key.arg (name), dw_is_visible.def).toBool (); + + // If floating, make window from widget. + if (floating) + { + widget->make_window (); + + if (visible) + { + if (settings.value (dw_is_minimized.key.arg (name), + dw_is_minimized.def).toBool ()) + widget->showMinimized (); + else + widget->setVisible (true); + } + else + widget->setVisible (false); + } + else // not floating + { + if (! widget->parent ()) // should not be floating but is + widget->make_widget (false); // no docking, just reparent + + widget->make_widget (); + widget->setVisible (visible); // not floating -> show + } + } + } + + show (); + } + + void main_window::write_settings (void) + { + gui_settings settings; + + settings.setValue (mw_geometry.key, saveGeometry ()); + settings.setValue (mw_state.key, saveState ()); + // write the list of recently used directories + QStringList curr_dirs; + for (int i=0; icount (); i++) + { + curr_dirs.append (m_current_directory_combo_box->itemText (i)); + } + settings.setValue (mw_dir_list.key, curr_dirs); + settings.sync (); + } + + void main_window::copyClipboard (void) + { + if (m_current_directory_combo_box->hasFocus ()) + { + QLineEdit *edit = m_current_directory_combo_box->lineEdit (); + if (edit && edit->hasSelectedText ()) + { + QClipboard *clipboard = QApplication::clipboard (); + clipboard->setText (edit->selectedText ()); + } + } + else + emit copyClipboard_signal (); + } + + void main_window::pasteClipboard (void) + { + if (m_current_directory_combo_box->hasFocus ()) + { + QLineEdit *edit = m_current_directory_combo_box->lineEdit (); + QClipboard *clipboard = QApplication::clipboard (); + QString str = clipboard->text (); + if (edit && str.length () > 0) + { + edit->insert (str); + } + } + else + emit pasteClipboard_signal (); + } + + void main_window::selectAll (void) + { + if (m_current_directory_combo_box->hasFocus ()) + { + QLineEdit *edit = m_current_directory_combo_box->lineEdit (); + if (edit) + { + edit->selectAll (); + } + } + else + emit selectAll_signal (); + } + + void main_window::handle_gui_status_update (const QString& feature, + const QString& status) + { + // Put actions that are required for updating a gui features here + + // Profiler on/off + if (! feature.compare ("profiler")) + { + if (! status.compare ("on", Qt::CaseInsensitive)) + handle_profiler_status_update (true); + else if (! status.compare ("off", Qt::CaseInsensitive)) + handle_profiler_status_update (false); + } + } + + void main_window::handle_octave_ready (void) + { + // actions after the startup files are executed + + gui_settings settings; + + QDir startup_dir = QDir (); // current octave dir after startup + + if (settings.value (global_restore_ov_dir).toBool ()) + { + // restore last dir from previous session + QStringList curr_dirs + = settings.value (mw_dir_list).toStringList (); + if (curr_dirs.length () > 0) + startup_dir = QDir (curr_dirs.at (0)); // last dir prev. session + } + else if (! settings.value (global_ov_startup_dir).toString ().isEmpty ()) + { + // do not restore but there is a startup dir configured + startup_dir + = QDir (settings.value (global_ov_startup_dir).toString ()); + } + + update_default_encoding (settings.value (ed_default_enc).toString ()); + + if (! startup_dir.exists ()) + { + // the configured startup dir does not exist, take actual one + startup_dir = QDir (); + } + + set_current_working_directory (startup_dir.absolutePath ()); + + if (m_editor_window) + { #if defined (HAVE_QSCINTILLA) - m_editor_window->handle_file_remove (o, n); -#else - octave_unused_parameter (o); - octave_unused_parameter (n); + // Octave ready, determine whether to create an empty script. + // This can not be done when the editor is created because all functions + // must be known for the lexer's auto completion information + m_editor_window->empty_script (true, false); + m_editor_window->restore_session (); #endif - - // We are done: Unlock and wake the worker thread - qt_link->unlock (); - qt_link->wake_all (); -} - -void main_window::open_online_documentation_page (void) -{ - QDesktopServices::openUrl - (QUrl ("https://octave.org/doc/interpreter/index.html")); -} - -void main_window::open_bug_tracker_page (void) -{ - QDesktopServices::openUrl (QUrl ("https://octave.org/bugs.html")); -} - -void main_window::open_octave_packages_page (void) -{ - QDesktopServices::openUrl (QUrl ("https://packages.octave.org/index.html")); -} - -void main_window::open_contribute_page (void) -{ - QDesktopServices::openUrl (QUrl ("https://octave.org/contribute.html")); -} - -void main_window::open_donate_page (void) -{ - QDesktopServices::openUrl (QUrl ("https://octave.org/donate.html")); -} - -void main_window::process_settings_dialog_request (const QString& desired_tab) -{ - if (m_settings_dlg) // m_settings_dlg is a guarded pointer! - { - // here the dialog is still open and called once again - if (! desired_tab.isEmpty ()) - m_settings_dlg->show_tab (desired_tab); + } + + if (m_octave_qobj.experimental_terminal_widget ()) + { + // Set initial prompt. + + emit interpreter_event + ([] (interpreter& interp) + { + // INTERPRETER_THREAD + + event_manager& evmgr = interp.get_event_manager (); + input_system& input_sys = interp.get_input_system (); + + input_sys.PS1 (">> "); + std::string prompt = input_sys.PS1 (); + + evmgr.update_prompt (command_editor::decode_prompt_string (prompt)); + }); + } + + m_command_window->init_command_prompt (); + focus_command_window (); // make sure that the command window has focus + } + + void main_window::handle_set_path_dialog_request (void) + { + if (m_set_path_dlg) // m_set_path_dlg is a guarded pointer! return; - } - - m_settings_dlg = new settings_dialog (this, m_octave_qobj, desired_tab); - - connect (m_settings_dlg, &settings_dialog::apply_new_settings, - this, &main_window::request_reload_settings); - - m_settings_dlg->setModal (false); - m_settings_dlg->setAttribute (Qt::WA_DeleteOnClose); - m_settings_dlg->show (); -} - -void main_window::show_about_octave (void) -{ - std::string message - = octave_name_version_copyright_copying_warranty_and_bugs (true); - - QMessageBox::about (this, tr ("About Octave"), - QString::fromStdString (message)); -} - -void main_window::notice_settings (const gui_settings *settings, - bool update_by_worker) -{ - if (! settings) - return; - - // Get desired style from preferences or take the default one if - // the desired one is not found - QString preferred_style = settings->value (global_style).toString (); - - if (preferred_style == global_style.def.toString ()) - preferred_style = m_default_style; - - QApplication* qapp = m_octave_qobj.qapplication(); - - if (preferred_style == global_extra_styles.at (EXTRA_STYLE_FUSION_DARK)) - { - QStyle *new_style = QStyleFactory::create (QStringLiteral("Fusion")); - if (new_style) - qapp->setStyle (new_style); - qapp->setPalette (getFusionDarkPalette()); - qapp->setStyleSheet ("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }"); - } - else - { - QStyle *new_style = QStyleFactory::create (preferred_style); - if (new_style) - { - qapp->setPalette (m_default_palette); - qapp->setStyle (new_style); - } - } - - // the widget's icons (when floating) - QString icon_set = settings->value (dw_icon_set).toString (); - - QString icon; - for (auto *widget : dock_widget_list ()) - { - QString name = widget->objectName (); - if (! name.isEmpty ()) - { - // if child has a name - icon = dw_icon_set_names[icon_set]; - if (icon_set != "NONE") - icon += name + ".png"; // add widget name and ext. - widget->setWindowIcon (QIcon (icon)); - } - } - - int size_idx = settings->value (global_icon_size).toInt (); - size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2 - - QStyle *st = style (); - int icon_size = st->pixelMetric (global_icon_sizes[size_idx]); - m_main_tool_bar->setIconSize (QSize (icon_size, icon_size)); - - if (settings->value (global_status_bar).toBool ()) - m_status_bar->show (); - else - m_status_bar->hide (); - - m_prevent_readline_conflicts - = settings->value (sc_prevent_rl_conflicts).toBool (); - - m_prevent_readline_conflicts_menu - = settings->value (sc_prevent_rl_conflicts_menu).toBool (); - - m_suppress_dbg_location - = ! settings->value (cs_dbg_location).toBool (); - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - rmgr.update_network_settings (); - - emit active_dock_changed (nullptr, m_active_dock); // update dock widget styles - - configure_shortcuts (); - - bool do_disable_main_menu_shortcuts - = (m_active_dock == m_editor_window) - || (m_prevent_readline_conflicts_menu - && (m_active_dock == m_command_window)); - - disable_menu_shortcuts (do_disable_main_menu_shortcuts); - - // Check whether some octave internal preferences have to be updated - QString new_default_encoding - = settings->value (ed_default_enc).toString (); - // Do not update internal pref only if a) this update was not initiated - // by the worker and b) the pref has really changes - if (! update_by_worker && (new_default_encoding != m_default_encoding)) - update_default_encoding (new_default_encoding); - - // Set cursor blinking depending on the settings - // Cursor blinking: consider old terminal related setting if not yet set - // TODO: This pref. can be deprecated / removed if Qt adds support for - // getting the cursor blink preferences from all OS environments - bool cursor_blinking; - - if (settings->contains (global_cursor_blinking.key)) - cursor_blinking = settings->value (global_cursor_blinking).toBool (); - else - cursor_blinking = settings->value (cs_cursor_blinking).toBool (); - - if (cursor_blinking) - QApplication::setCursorFlashTime (1000); // 1000 ms flash time - else - QApplication::setCursorFlashTime (0); // no flashing - -} - -QPalette main_window::getFusionDarkPalette() -{ - QPalette darkPalette; - darkPalette.setColor(QPalette::Window, QColor(53, 53, 53)); - darkPalette.setColor(QPalette::WindowText, Qt::white); - darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(127, 127, 127)); - darkPalette.setColor(QPalette::Base, QColor(42, 42, 42)); - darkPalette.setColor(QPalette::AlternateBase, QColor(66, 66, 66)); - darkPalette.setColor(QPalette::ToolTipBase, Qt::white); - darkPalette.setColor(QPalette::ToolTipText, Qt::white); - darkPalette.setColor(QPalette::Text, Qt::white); - darkPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127)); - darkPalette.setColor(QPalette::Dark, QColor(35, 35, 35)); - darkPalette.setColor(QPalette::Shadow, QColor(20, 20, 20)); - darkPalette.setColor(QPalette::Button, QColor(53, 53, 53)); - darkPalette.setColor(QPalette::ButtonText, Qt::white); - darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127)); - darkPalette.setColor(QPalette::BrightText, Qt::red); - darkPalette.setColor(QPalette::Link, QColor(42, 130, 218)); - darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218)); - darkPalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(80, 80, 80)); - darkPalette.setColor(QPalette::HighlightedText, Qt::white); - darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(127, 127, 127)); - - return darkPalette; -} - -void main_window::prepare_to_exit (void) -{ - // Find files dialog is constructed dynamically, not at time of main_window - // construction. Connecting it to qApp aboutToQuit signal would have - // caused it to run after gui_settings is deleted. - if (m_find_files_dlg) - m_find_files_dlg->save_settings (); - - if (m_set_path_dlg) - m_set_path_dlg->save_settings (); - - write_settings (); - - // No more active dock, otherwise, focus_changed would try to set - // the focus to a dock widget that might not exist anymore - m_active_dock = nullptr; -} - -void main_window::go_to_previous_widget (void) -{ - m_previous_dock->activate (); -} - -void main_window::update_octave_directory (const QString& dir) -{ - // Remove existing entry, if any, then add new directory at top and - // mark it as the current directory. Finally, update the file list - // widget. - - int index = m_current_directory_combo_box->findText (dir); - - if (index >= 0) - m_current_directory_combo_box->removeItem (index); - - m_current_directory_combo_box->insertItem (0, dir); - m_current_directory_combo_box->setCurrentIndex (0); -} - -void main_window::browse_for_directory (void) -{ - // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - int opts = QFileDialog::ShowDirsOnly; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) - opts = QFileDialog::DontUseNativeDialog; - - QString dir - = QFileDialog::getExistingDirectory (this, tr ("Browse directories"), nullptr, - QFileDialog::Option (opts)); - - set_current_working_directory (dir); - - // FIXME: on Windows systems, the command window freezes after the - // previous actions. Forcing the focus appears to unstick it. - - focus_command_window (); -} - -void main_window::set_current_working_directory (const QString& dir) -{ - // Change to dir if it is an existing directory. - - QString xdir = (dir.isEmpty () ? "." : dir); - - QFileInfo fileInfo (xdir); - - if (fileInfo.exists () && fileInfo.isDir ()) - { - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - interp.chdir (xdir.toStdString ()); - }); - } -} - -void main_window::change_directory_up (void) -{ - set_current_working_directory (".."); -} - -// Slot that is called if return is pressed in the line edit of the -// combobox to change to a new directory or a directory that is already -// in the drop down list. - -void main_window::accept_directory_line_edit (void) -{ - // Get new directory name, and change to it if it is new. Otherwise, - // the combo box will trigger the "activated" signal to change to the - // directory. - - QString dir = m_current_directory_combo_box->currentText (); - - int index = m_current_directory_combo_box->findText (dir); - - if (index < 0) - set_current_working_directory (dir); -} - -void main_window::execute_command_in_terminal (const QString& command) -{ - if (m_octave_qobj.experimental_terminal_widget ()) - { - emit execute_command_signal (command); - } - else - { - emit interpreter_event - ([=] (void) - { - // INTERPRETER THREAD - - std::string pending_input = command_editor::get_current_line (); - - command_editor::set_initial_input (pending_input); - command_editor::replace_line (command.toStdString ()); - command_editor::redisplay (); - command_editor::interrupt_event_loop (); - command_editor::accept_line (); - }); - } - - focus_console_after_command (); -} - -void main_window::run_file_in_terminal (const QFileInfo& info) -{ - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - QString function_name = info.fileName (); - function_name.chop (info.suffix ().length () + 1); - std::string file_path = info.absoluteFilePath ().toStdString (); - - std::string pending_input = command_editor::get_current_line (); - - if (valid_identifier (function_name.toStdString ())) - { - // Valid identifier: call as function with possibility to - // debug. - - load_path& lp = interp.get_load_path (); - - std::string path = info.absolutePath ().toStdString (); - - if (lp.contains_file_in_dir (file_path, path)) - command_editor::replace_line (function_name.toStdString ()); - } - else - { - // No valid identifier: use equivalent of Fsource (), no - // debug possible. - - interp.source_file (file_path); - - command_editor::replace_line (""); - } - - command_editor::set_initial_input (pending_input); - command_editor::redisplay (); - command_editor::interrupt_event_loop (); - command_editor::accept_line (); - }); - - focus_console_after_command (); -} - -void main_window::handle_new_figure_request (void) -{ - emit interpreter_event - ([] (interpreter& interp) - { - // INTERPRETER THREAD - - Fbuiltin (interp, ovl ("figure")); - Fdrawnow (interp); - }); -} - -void main_window::handle_enter_debugger (void) -{ - setWindowTitle ("Octave (Debugging)"); - - m_debug_continue->setEnabled (true); - m_debug_step_into->setEnabled (true); - m_debug_step_over->setEnabled (true); - m_debug_step_out->setEnabled (true); - m_debug_quit->setEnabled (true); -} - -void main_window::handle_exit_debugger (void) -{ - setWindowTitle ("Octave"); - - m_debug_continue->setEnabled (false); - m_debug_step_into->setEnabled (false); - m_debug_step_over->setEnabled (m_editor_has_tabs && m_editor_is_octave_file); - m_debug_step_out->setEnabled (false); - m_debug_quit->setEnabled (false); -} - -void main_window::debug_continue (void) -{ - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location)); - Fdbcont (interp); - - command_editor::interrupt (true); - }); -} - -void main_window::debug_step_into (void) -{ - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location)); - Fdbstep (interp, ovl ("in")); - - command_editor::interrupt (true); - }); -} - -void main_window::debug_step_over (void) -{ - if (m_debug_quit->isEnabled ()) - { - // We are in debug mode, just call dbstep. - - emit interpreter_event - ([=] (interpreter& interp) + + m_set_path_dlg = new set_path_dialog (this); + + m_set_path_dlg->setModal (false); + m_set_path_dlg->setAttribute (Qt::WA_DeleteOnClose); + m_set_path_dlg->show (); + + // Any interpreter_event signal from a set_path_dialog object is + // handled the same as for the main_window object. + + connect (m_set_path_dlg, QOverload::of (&set_path_dialog::interpreter_event), + this, QOverload::of (&main_window::interpreter_event)); + + connect (m_set_path_dlg, QOverload::of (&set_path_dialog::interpreter_event), + this, QOverload::of (&main_window::interpreter_event)); + + connect (m_set_path_dlg, &set_path_dialog::modify_path_signal, + this, &main_window::modify_path); + + interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj (); + + qt_interpreter_events *qt_link = interp_qobj->qt_link (); + + connect (qt_link, &qt_interpreter_events::update_path_dialog_signal, + m_set_path_dlg, &set_path_dialog::update_model); + + // Now that all the signal connections are in place for the dialog + // we can set the initial value of the path in the model. + + m_set_path_dlg->update_model (); + } + + void main_window::find_files (const QString& start_dir) + { + + if (! m_find_files_dlg) + { + m_find_files_dlg = new find_files_dialog (this); + + connect (m_find_files_dlg, &find_files_dialog::finished, + this, &main_window::find_files_finished); + + connect (m_find_files_dlg, &find_files_dialog::dir_selected, + m_file_browser_window, &files_dock_widget::set_current_directory); + + connect (m_find_files_dlg, &find_files_dialog::file_selected, + this, QOverload::of (&main_window::open_file_signal)); + + m_find_files_dlg->setWindowModality (Qt::NonModal); + } + + if (! m_find_files_dlg->isVisible ()) + { + m_find_files_dlg->show (); + } + + m_find_files_dlg->set_search_dir (start_dir); + + m_find_files_dlg->activateWindow (); + + } + + void main_window::set_screen_size (int ht, int wd) + { + emit interpreter_event + ([=] (void) + { + // INTERPRETER THREAD + + command_editor::set_screen_size (ht, wd); + }); + } + + void main_window::clipboard_has_changed (void) + { + if (m_clipboard->text ().isEmpty ()) + { + m_paste_action->setEnabled (false); + m_clear_clipboard_action->setEnabled (false); + } + else + { + m_paste_action->setEnabled (true); + m_clear_clipboard_action->setEnabled (true); + } + } + + void main_window::clear_clipboard (void) + { + m_clipboard->clear (QClipboard::Clipboard); + } + + void main_window::disable_menu_shortcuts (bool disable) + { + QHash::const_iterator i = m_hash_menu_text.constBegin (); + + while (i != m_hash_menu_text.constEnd ()) + { + i.key ()->setTitle (i.value ().at (disable)); + ++i; + } + } + + void main_window::restore_create_file_setting (void) + { + // restore the new files creation setting + + gui_settings settings; + + settings.setValue (ed_create_new_file.key, false); + disconnect (m_editor_window, SIGNAL (file_loaded_signal (void)), + this, SLOT (restore_create_file_setting (void))); + } + + void main_window::set_file_encoding (const QString& new_encoding) + { + m_file_encoding = new_encoding; + } + + // The following slot is called after files have been selected in the + // open file dialog, possibly with a new selected encoding stored in + // m_file_encoding + void main_window::request_open_files (const QStringList& open_file_names) + { + for (int i = 0; i < open_file_names.count (); i++) + emit open_file_signal (open_file_names.at (i), m_file_encoding, -1); + } + + void main_window::profiler_session (void) + { + emit interpreter_event + ([=] (interpreter& interp) { // INTERPRETER THREAD - F__db_next_breakpoint_quiet__ (interp, - ovl (m_suppress_dbg_location)); - Fdbstep (interp); - - command_editor::interrupt (true); + Ffeval (interp, ovl ("profile","on")); }); - } - else - { - // Not in debug mode: "step into" the current editor file - emit step_into_file_signal (); - } -} - -void main_window::debug_step_out (void) -{ - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location)); - Fdbstep (interp, ovl ("out")); - - command_editor::interrupt (true); - }); -} - -void main_window::debug_quit (void) -{ - emit interpreter_event - ([] (interpreter& interp) - { - // INTERPRETER THREAD - - Fdbquit (interp); - - command_editor::interrupt (true); - }); -} - -// -// Functions related to file editing -// -// These are moved from editor to here for also using them when octave -// is built without qscintilla -// -void main_window::request_open_file (void) -{ - // Open file isn't a file_editor_tab or editor function since the file - // might be opened in an external editor. Hence, functionality is here. - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - bool is_internal = m_editor_window - && ! settings->value (global_use_custom_editor.key, - global_use_custom_editor.def).toBool (); - - // Create a NonModal message. - QWidget *p = this; - if (is_internal) - p = m_editor_window; - QFileDialog *fileDialog = new QFileDialog (p); - fileDialog->setNameFilter (tr ("Octave Files (*.m);;All Files (*)")); - - fileDialog->setAcceptMode (QFileDialog::AcceptOpen); - fileDialog->setViewMode (QFileDialog::Detail); - fileDialog->setFileMode (QFileDialog::ExistingFiles); - fileDialog->setDirectory (m_current_directory_combo_box->itemText (0)); - - // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - if (! settings->value (global_use_native_dialogs).toBool ()) - fileDialog->setOption(QFileDialog::DontUseNativeDialog); - - connect (fileDialog, &QFileDialog::filesSelected, - this, &main_window::request_open_files); - - fileDialog->setWindowModality (Qt::NonModal); - fileDialog->setAttribute (Qt::WA_DeleteOnClose); - fileDialog->show (); -} - -// Create a new script -void main_window::request_new_script (const QString& commands) -{ - emit new_file_signal (commands); -} - -// Create a new function and open it -void main_window::request_new_function (bool) -{ - bool ok; - // Get the name of the new function: Parent of the input dialog is the - // editor window or the main window. The latter is chosen, if a custom - // editor is used or qscintilla is not available - QWidget *p = m_editor_window; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! p || settings->value (global_use_custom_editor.key, - global_use_custom_editor.def).toBool ()) - p = this; - QString new_name = QInputDialog::getText (p, tr ("New Function"), - tr ("New function name:\n"), QLineEdit::Normal, "", &ok); - - if (ok && new_name.length () > 0) - { - // append suffix if it does not already exist - if (new_name.rightRef (2) != ".m") - new_name.append (".m"); - // check whether new files are created without prompt - if (! settings->value (ed_create_new_file).toBool ()) - { - // no, so enable this settings and wait for end of new file loading - settings->setValue (ed_create_new_file.key, true); - connect (m_editor_window, SIGNAL (file_loaded_signal (void)), - this, SLOT (restore_create_file_setting (void))); - } - // start the edit command - execute_command_in_terminal ("edit " + new_name); - } -} - -void main_window::handle_edit_mfile_request (const QString& fname, - const QString& ffile, - const QString& curr_dir, - int line) -{ - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - // Split possible subfunctions - QStringList fcn_list = fname.split ('>'); - QString fcn_name = fcn_list.at (0) + ".m"; - - // FIXME: could use symbol_exist directly, but we may also want - // to fix that to be a member function in the interpreter - // class? - - // Is it a regular function within the search path? (Call Fexist) - octave_value_list fct = Fexist (interp, ovl (fname.toStdString ()),0); - int type = fct (0).int_value (); - - QString message = QString (); - QString filename = QString (); - - switch (type) - { - case 3: - case 5: - case 103: - message = tr ("%1 is a built-in, compiled or inline\n" - "function and can not be edited."); - break; - - case 2: - // FIXME: could use a load_path function directly. - octave_value_list file_path - = Ffile_in_loadpath (interp, ovl (fcn_name.toStdString ()), 0); - if (file_path.length () > 0) - filename = QString::fromStdString (file_path (0).string_value ()); - break; - } - - if (filename.isEmpty () && message.isEmpty ()) + } + + void main_window::profiler_session_resume (void) + { + emit interpreter_event + ([=] (interpreter& interp) { - // No error so far, but function still not known - // -> try directory of edited file - // get directory - QDir dir; - if (ffile.isEmpty ()) - { - if (curr_dir.isEmpty ()) - dir = QDir (m_current_directory_combo_box->itemText (0)); - else - dir = QDir (curr_dir); - } - else - dir = QDir (QFileInfo (ffile).canonicalPath ()); - - QFileInfo file = QFileInfo (dir, fcn_name); - if (file.exists ()) - filename = file.canonicalFilePath (); // local file exists - else - { - // local file does not exist -> try private directory - file = QFileInfo (ffile); - file = QFileInfo (QDir (file.canonicalPath () + "/private"), - fcn_name); - if (file.exists ()) - filename = file.canonicalFilePath (); // private function exists - else - message = tr ("Can not find function %1"); // no file found - - } - } - - if (! message.isEmpty ()) - { - emit warning_function_not_found_signal (message.arg (fname)); - return; - } - - if (! filename.endsWith (".m")) - filename.append (".m"); - - // default encoding - emit open_file_signal (filename, QString (), line); - }); -} - -void main_window::warning_function_not_found (const QString& message) -{ - QMessageBox *msgBox = new QMessageBox (QMessageBox::Critical, - tr ("Octave Editor"), - message, QMessageBox::Ok, this); - msgBox->setWindowModality (Qt::NonModal); - msgBox->setAttribute (Qt::WA_DeleteOnClose); - msgBox->show (); -} - -void main_window::handle_insert_debugger_pointer_request (const QString& file, - int line) -{ - bool cmd_focus = command_window_has_focus (); - - emit insert_debugger_pointer_signal (file, line); - - if (cmd_focus) - focus_command_window (); -} - -void main_window::handle_delete_debugger_pointer_request (const QString& file, - int line) -{ - bool cmd_focus = command_window_has_focus (); - - emit delete_debugger_pointer_signal (file, line); - - if (cmd_focus) - focus_command_window (); -} - -void main_window::handle_update_breakpoint_marker_request (bool insert, - const QString& file, - int line, - const QString& cond) -{ - bool cmd_focus = command_window_has_focus (); - - emit update_breakpoint_marker_signal (insert, file, line, cond); - - if (cmd_focus) - focus_command_window (); -} - -void main_window::read_settings (void) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (! settings) - { - qDebug ("Error: gui_settings pointer from resource manager is NULL."); - return; - } - - set_window_layout (settings); - - // restore the list of the last directories - QStringList curr_dirs = settings->value (mw_dir_list).toStringList (); - for (int i=0; i < curr_dirs.size (); i++) - { - m_current_directory_combo_box->addItem (curr_dirs.at (i)); - } - emit settings_changed (settings); -} - -void main_window::init_terminal_size (void) -{ - emit init_terminal_size_signal (); -} - -void main_window::set_window_layout (gui_settings *settings) -{ - // For resetting from some inconsistent state, first reset layout - // without saving or showing it - do_reset_windows (true, false); - - // Restore main window state and geometry from settings file or, in case - // of an error (no pref values yet), from the default layout. - if (! restoreGeometry (settings->value (mw_geometry).toByteArray ())) - { - do_reset_windows (true); - return; - } - - if (isMaximized()) - { - // If the window state is restored to maximized layout, the - // horizontal layout is not preserved. This cann be avoided by - // setting the geometry to the max. available geometry. However, on - // X11, the available geometry (excluding task bar etc.) is equal to - // the total geometry leading to a full screen mode without window - // decorations. This in turn can be avoided by explicitly adding - // a title bar in the window flags. - - // Get available geometry for current screen and set this - // window's geometry to it. - QScreen *s = windowHandle ()->screen (); - QRect av_geom = s->availableGeometry (); - setGeometry (av_geom); // Set (correct) available geometry - - // Force full title bar - setWindowFlags(Qt::WindowTitleHint - | Qt::WindowMinMaxButtonsHint - | Qt::WindowSystemMenuHint - | Qt::WindowCloseButtonHint); - } - - if (! restoreState (settings->value (mw_state).toByteArray ())) - { - do_reset_windows (true); - return; - } - - // Restore the geometry of all dock-widgets - - for (auto *widget : dock_widget_list ()) - { - // Leave any widgets that existed before main_window was created - // as they were. - - if (widget->adopted ()) - continue; - - QString name = widget->objectName (); - - if (! name.isEmpty ()) + // INTERPRETER THREAD + + Ffeval (interp, ovl ("profile","resume")); + }); + } + + void main_window::profiler_stop (void) + { + emit interpreter_event + ([=] (interpreter& interp) { - bool floating = false; - bool visible = true; - - floating = settings->value - (dw_is_floating.key.arg (name), dw_is_floating.def).toBool (); - visible = settings->value - (dw_is_visible.key.arg (name), dw_is_visible.def).toBool (); - - // If floating, make window from widget. - if (floating) - { - widget->make_window (); - - if (visible) - { - if (settings->value (dw_is_minimized.key.arg (name), - dw_is_minimized.def).toBool ()) - widget->showMinimized (); - else - widget->setVisible (true); - } - else - widget->setVisible (false); - } - else // not floating - { - if (! widget->parent ()) // should not be floating but is - widget->make_widget (false); // no docking, just reparent - - widget->make_widget (); - widget->setVisible (visible); // not floating -> show - } - } - } - - show (); -} - -void main_window::write_settings (void) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings) - { - qDebug ("Error: gui_settings pointer from resource manager is NULL."); - return; - } - - settings->setValue (mw_geometry.key, saveGeometry ()); - settings->setValue (mw_state.key, saveState ()); - // write the list of recently used directories - QStringList curr_dirs; - for (int i=0; icount (); i++) - { - curr_dirs.append (m_current_directory_combo_box->itemText (i)); - } - settings->setValue (mw_dir_list.key, curr_dirs); - settings->sync (); -} - -void main_window::copyClipboard (void) -{ - if (m_current_directory_combo_box->hasFocus ()) - { - QLineEdit *edit = m_current_directory_combo_box->lineEdit (); - if (edit && edit->hasSelectedText ()) - { - QClipboard *clipboard = QApplication::clipboard (); - clipboard->setText (edit->selectedText ()); - } - } - else - emit copyClipboard_signal (); -} - -void main_window::pasteClipboard (void) -{ - if (m_current_directory_combo_box->hasFocus ()) - { - QLineEdit *edit = m_current_directory_combo_box->lineEdit (); - QClipboard *clipboard = QApplication::clipboard (); - QString str = clipboard->text (); - if (edit && str.length () > 0) - { - edit->insert (str); - } - } - else - emit pasteClipboard_signal (); -} - -void main_window::selectAll (void) -{ - if (m_current_directory_combo_box->hasFocus ()) - { - QLineEdit *edit = m_current_directory_combo_box->lineEdit (); - if (edit) - { - edit->selectAll (); - } - } - else - emit selectAll_signal (); -} - -void main_window::handle_gui_status_update (const QString& feature, - const QString& status) -{ - // Put actions that are required for updating a gui features here - - // Profiler on/off - if (! feature.compare ("profiler")) - { - if (! status.compare ("on", Qt::CaseInsensitive)) - handle_profiler_status_update (true); - else if (! status.compare ("off", Qt::CaseInsensitive)) - handle_profiler_status_update (false); - } -} - -void main_window::handle_octave_ready (void) -{ - // actions after the startup files are executed - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - QDir startup_dir = QDir (); // current octave dir after startup - - if (settings) - { - if (settings->value (global_restore_ov_dir).toBool ()) - { - // restore last dir from previous session - QStringList curr_dirs - = settings->value (mw_dir_list).toStringList (); - if (curr_dirs.length () > 0) - startup_dir = QDir (curr_dirs.at (0)); // last dir prev. session - } - else if (! settings->value (global_ov_startup_dir).toString ().isEmpty ()) - { - // do not restore but there is a startup dir configured - startup_dir - = QDir (settings->value (global_ov_startup_dir).toString ()); - } - - update_default_encoding (settings->value (ed_default_enc).toString ()); - } - - if (! startup_dir.exists ()) - { - // the configured startup dir does not exist, take actual one - startup_dir = QDir (); - } - - set_current_working_directory (startup_dir.absolutePath ()); - - if (m_editor_window) - { -#if defined (HAVE_QSCINTILLA) - // Octave ready, determine whether to create an empty script. - // This can not be done when the editor is created because all functions - // must be known for the lexer's auto completion information - m_editor_window->empty_script (true, false); - m_editor_window->restore_session (settings); -#endif - } - - if (m_octave_qobj.experimental_terminal_widget ()) - { - // Set initial prompt. - - emit interpreter_event - ([] (interpreter& interp) - { - // INTERPRETER_THREAD - - event_manager& evmgr = interp.get_event_manager (); - input_system& input_sys = interp.get_input_system (); - - input_sys.PS1 (">> "); - std::string prompt = input_sys.PS1 (); - - evmgr.update_prompt (command_editor::decode_prompt_string (prompt)); + // INTERPRETER THREAD + + Ffeval (interp, ovl ("profile","off")); }); - } - - m_command_window->init_command_prompt (); - focus_command_window (); // make sure that the command window has focus -} - -void main_window::handle_set_path_dialog_request (void) -{ - if (m_set_path_dlg) // m_set_path_dlg is a guarded pointer! - return; - - m_set_path_dlg = new set_path_dialog (this, m_octave_qobj); - - m_set_path_dlg->setModal (false); - m_set_path_dlg->setAttribute (Qt::WA_DeleteOnClose); - m_set_path_dlg->show (); - - // Any interpreter_event signal from a set_path_dialog object is - // handled the same as for the main_window object. - - connect (m_set_path_dlg, QOverload::of (&set_path_dialog::interpreter_event), - this, QOverload::of (&main_window::interpreter_event)); - - connect (m_set_path_dlg, QOverload::of (&set_path_dialog::interpreter_event), - this, QOverload::of (&main_window::interpreter_event)); - - connect (m_set_path_dlg, &set_path_dialog::modify_path_signal, - this, &main_window::modify_path); - - interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj (); - - qt_interpreter_events *qt_link = interp_qobj->qt_link (); - - connect (qt_link, &qt_interpreter_events::update_path_dialog_signal, - m_set_path_dlg, &set_path_dialog::update_model); - - // Now that all the signal connections are in place for the dialog - // we can set the initial value of the path in the model. - - m_set_path_dlg->update_model (); -} - -void main_window::find_files (const QString& start_dir) -{ - - if (! m_find_files_dlg) - { - m_find_files_dlg = new find_files_dialog (this, m_octave_qobj); - - connect (m_find_files_dlg, &find_files_dialog::finished, - this, &main_window::find_files_finished); - - connect (m_find_files_dlg, &find_files_dialog::dir_selected, - m_file_browser_window, &files_dock_widget::set_current_directory); - - connect (m_find_files_dlg, &find_files_dialog::file_selected, - this, QOverload::of (&main_window::open_file_signal)); - - m_find_files_dlg->setWindowModality (Qt::NonModal); - } - - if (! m_find_files_dlg->isVisible ()) - { - m_find_files_dlg->show (); - } - - m_find_files_dlg->set_search_dir (start_dir); - - m_find_files_dlg->activateWindow (); - -} - -void main_window::set_screen_size (int ht, int wd) -{ - emit interpreter_event - ([=] (void) - { - // INTERPRETER THREAD - - command_editor::set_screen_size (ht, wd); - }); -} - -void main_window::clipboard_has_changed (void) -{ - if (m_clipboard->text ().isEmpty ()) - { - m_paste_action->setEnabled (false); - m_clear_clipboard_action->setEnabled (false); - } - else - { - m_paste_action->setEnabled (true); - m_clear_clipboard_action->setEnabled (true); - } -} - -void main_window::clear_clipboard (void) -{ - m_clipboard->clear (QClipboard::Clipboard); -} - -void main_window::disable_menu_shortcuts (bool disable) -{ - QHash::const_iterator i = m_hash_menu_text.constBegin (); - - while (i != m_hash_menu_text.constEnd ()) - { - i.key ()->setTitle (i.value ().at (disable)); - ++i; - } -} - -void main_window::restore_create_file_setting (void) -{ - // restore the new files creation setting - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - settings->setValue (ed_create_new_file.key, false); - disconnect (m_editor_window, SIGNAL (file_loaded_signal (void)), - this, SLOT (restore_create_file_setting (void))); -} - -void main_window::set_file_encoding (const QString& new_encoding) -{ - m_file_encoding = new_encoding; -} - -// The following slot is called after files have been selected in the -// open file dialog, possibly with a new selected encoding stored in -// m_file_encoding -void main_window::request_open_files (const QStringList& open_file_names) -{ - for (int i = 0; i < open_file_names.count (); i++) - emit open_file_signal (open_file_names.at (i), m_file_encoding, -1); -} - -void main_window::profiler_session (void) -{ - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - Ffeval (interp, ovl ("profile","on")); - }); -} - -void main_window::profiler_session_resume (void) -{ - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - Ffeval (interp, ovl ("profile","resume")); - }); -} - -void main_window::profiler_stop (void) -{ - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - Ffeval (interp, ovl ("profile","off")); - }); -} - -void main_window::handle_profiler_status_update (bool active) -{ - m_profiler_start->setEnabled (! active); - m_profiler_resume->setEnabled (! active); - m_profiler_stop->setEnabled (active); - - led_indicator::led_state state = led_indicator::LED_STATE_INACTIVE; - if (active) - state = led_indicator::LED_STATE_ACTIVE; - m_profiler_status_indicator->set_state (state); -} - -void main_window::profiler_show (void) -{ - // Do not use a separate interpreter event as in the other - // profiler slots since the output of the command "profshow" - // would obscure the prompt and we do not need to emimt a signal - // for action that is required in the gui after rhe command - execute_command_in_terminal ("profshow"); -} - -void main_window::closeEvent (QCloseEvent *e) -{ - write_settings (); - - if (confirm_shutdown ()) - { - // FIXME: Instead of ignoring the event and posting an - // interpreter event, should we just accept the event and - // shutdown and clean up the interpreter as part of closing the - // GUI? Going that route might make it easier to close the GUI - // without having to stop the interpreter, for example, if the - // GUI is started from the interpreter command line. - + } + + void main_window::handle_profiler_status_update (bool active) + { + m_profiler_start->setEnabled (! active); + m_profiler_resume->setEnabled (! active); + m_profiler_stop->setEnabled (active); + + led_indicator::led_state state = led_indicator::LED_STATE_INACTIVE; + if (active) + state = led_indicator::LED_STATE_ACTIVE; + m_profiler_status_indicator->set_state (state); + } + + void main_window::profiler_show (void) + { + // Do not use a separate interpreter event as in the other + // profiler slots since the output of the command "profshow" + // would obscure the prompt and we do not need to emimt a signal + // for action that is required in the gui after rhe command + execute_command_in_terminal ("profshow"); + } + + void main_window::closeEvent (QCloseEvent *e) + { + write_settings (); + + if (confirm_shutdown ()) + { + // FIXME: Instead of ignoring the event and posting an + // interpreter event, should we just accept the event and + // shutdown and clean up the interpreter as part of closing the + // GUI? Going that route might make it easier to close the GUI + // without having to stop the interpreter, for example, if the + // GUI is started from the interpreter command line. + + e->ignore (); + + if (m_octave_qobj.experimental_terminal_widget () + && ! m_octave_qobj.is_gui_app ()) + emit close_gui_signal (); + else + { + emit interpreter_event + ([] (interpreter& interp) + { + // INTERPRETER THREAD + + interp.quit (0, false, false); + }); + } + } + else e->ignore (); - - if (m_octave_qobj.experimental_terminal_widget () - && ! m_octave_qobj.is_gui_app ()) - emit close_gui_signal (); - else - { - emit interpreter_event - ([] (interpreter& interp) - { - // INTERPRETER THREAD - - interp.quit (0, false, false); - }); - } - } - else - e->ignore (); -} - -void main_window::construct_central_widget (void) -{ - // Create and set the central widget. QMainWindow takes ownership of - // the widget (pointer) so there is no need to delete the object upon - // destroying this main_window. - - QWidget *dummyWidget = new QWidget (); - dummyWidget->setObjectName ("CentralDummyWidget"); - dummyWidget->resize (10, 10); - dummyWidget->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); - dummyWidget->hide (); - setCentralWidget (dummyWidget); -} + } + + void main_window::construct_central_widget (void) + { + // Create and set the central widget. QMainWindow takes ownership of + // the widget (pointer) so there is no need to delete the object upon + // destroying this main_window. + + QWidget *dummyWidget = new QWidget (); + dummyWidget->setObjectName ("CentralDummyWidget"); + dummyWidget->resize (10, 10); + dummyWidget->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); + dummyWidget->hide (); + setCentralWidget (dummyWidget); + } // Main subroutine of the constructor -void main_window::construct (void) -{ - setWindowIcon (QIcon (dw_icon_set_names["NONE"])); - - interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj (); - - qt_interpreter_events *qt_link = interp_qobj->qt_link (); - - construct_menu_bar (); - - construct_tool_bar (); - - // FIXME: Is this action intended to be about quitting application - // or closing the main window? - connect (qApp, &QApplication::aboutToQuit, - this, &main_window::prepare_to_exit); - - connect (qApp, &QApplication::focusChanged, - this, &main_window::focus_changed); - - connect (this, &main_window::settings_changed, - this, [=] (const gui_settings *settings) { notice_settings (settings); }); - - // Connections for signals from the interpreter thread where the slot - // should be executed by the gui thread - - connect (this, &main_window::warning_function_not_found_signal, - this, &main_window::warning_function_not_found); - - setWindowTitle ("Octave"); - - setStatusBar (m_status_bar); - - // Signals for removing/renaming files/dirs in the temrinal window - connect (qt_link, &qt_interpreter_events::file_remove_signal, - this, &main_window::file_remove_proxy); - - connect (this, QOverload::of (&main_window::interpreter_event), - &m_octave_qobj, QOverload::of (&base_qobject::interpreter_event)); - - connect (this, QOverload::of (&main_window::interpreter_event), - &m_octave_qobj, QOverload::of (&base_qobject::interpreter_event)); - - configure_shortcuts (); -} - -void main_window::construct_octave_qt_link (void) -{ - interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj (); - - qt_interpreter_events *qt_link = interp_qobj->qt_link (); - - connect (qt_link, &qt_interpreter_events::settings_changed, - this, &main_window::notice_settings); - - connect (qt_link, &qt_interpreter_events::apply_new_settings, - this, &main_window::request_reload_settings); - - connect (qt_link, &qt_interpreter_events::directory_changed_signal, - this, &main_window::update_octave_directory); - - connect (qt_link, &qt_interpreter_events::execute_command_in_terminal_signal, - this, &main_window::execute_command_in_terminal); - - connect (qt_link, &qt_interpreter_events::enter_debugger_signal, - this, &main_window::handle_enter_debugger); - - connect (qt_link, &qt_interpreter_events::exit_debugger_signal, - this, &main_window::handle_exit_debugger); - - connect (qt_link, &qt_interpreter_events::show_preferences_signal, - this, [=] () { process_settings_dialog_request (); }); - - connect (qt_link, &qt_interpreter_events::insert_debugger_pointer_signal, - this, &main_window::handle_insert_debugger_pointer_request); - - connect (qt_link, &qt_interpreter_events::delete_debugger_pointer_signal, - this, &main_window::handle_delete_debugger_pointer_request); - - connect (qt_link, &qt_interpreter_events::update_breakpoint_marker_signal, - this, &main_window::handle_update_breakpoint_marker_request); - - connect (qt_link, &qt_interpreter_events::gui_status_update_signal, - this, &main_window::handle_gui_status_update); - - connect (qt_link, &qt_interpreter_events::update_gui_lexer_signal, - this, &main_window::update_gui_lexer_signal); -} - -QAction* main_window::add_action (QMenu *menu, const QIcon& icon, - const QString& text, const char *member, - const QWidget *receiver) -{ - QAction *a; - - if (receiver) - a = menu->addAction (icon, text, receiver, member); - else - a = menu->addAction (icon, text, this, member); - - addAction (a); // important for shortcut context - a->setShortcutContext (Qt::ApplicationShortcut); - return a; -} - -QMenu* main_window::m_add_menu (QMenuBar *p, QString name) -{ - QMenu *menu = p->addMenu (name); - - QString base_name = name; // get a copy - // replace intended '&' ("&&") by a temp. string - base_name.replace ("&&", "___octave_amp_replacement___"); - // remove single '&' (shortcut) - base_name.remove ("&"); - // restore intended '&' - base_name.replace ("___octave_amp_replacement___", "&&"); - - // remember names with and without shortcut - m_hash_menu_text[menu] = QStringList ({ name, base_name }); - - return menu; -} - -void main_window::construct_menu_bar (void) -{ - QMenuBar *menu_bar = menuBar (); - - construct_file_menu (menu_bar); - - construct_edit_menu (menu_bar); - - construct_debug_menu (menu_bar); - - construct_tools_menu (menu_bar); - - construct_window_menu (menu_bar); - - construct_help_menu (menu_bar); - - construct_news_menu (menu_bar); + void main_window::construct (void) + { + setWindowIcon (QIcon (dw_icon_set_names["NONE"])); + + interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj (); + + qt_interpreter_events *qt_link = interp_qobj->qt_link (); + + construct_menu_bar (); + + construct_tool_bar (); + + // FIXME: Is this action intended to be about quitting application + // or closing the main window? + connect (qApp, &QApplication::aboutToQuit, + this, &main_window::prepare_to_exit); + + connect (qApp, &QApplication::focusChanged, + this, &main_window::focus_changed); + + // Default argument requires wrapper. + connect (this, &main_window::settings_changed, + this, [=] () { notice_settings (); }); + + // Connections for signals from the interpreter thread where the slot + // should be executed by the gui thread + + connect (this, &main_window::warning_function_not_found_signal, + this, &main_window::warning_function_not_found); + + setWindowTitle ("Octave"); + + setStatusBar (m_status_bar); + + // Signals for removing/renaming files/dirs in the temrinal window + connect (qt_link, &qt_interpreter_events::file_remove_signal, + this, &main_window::file_remove_proxy); + + connect (this, QOverload::of (&main_window::interpreter_event), + &m_octave_qobj, QOverload::of (&base_qobject::interpreter_event)); + + connect (this, QOverload::of (&main_window::interpreter_event), + &m_octave_qobj, QOverload::of (&base_qobject::interpreter_event)); + + configure_shortcuts (); + } + + void main_window::construct_octave_qt_link (void) + { + interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj (); + + qt_interpreter_events *qt_link = interp_qobj->qt_link (); + + connect (qt_link, &qt_interpreter_events::settings_changed, + this, &main_window::notice_settings); + + connect (qt_link, &qt_interpreter_events::apply_new_settings, + this, &main_window::request_reload_settings); + + connect (qt_link, &qt_interpreter_events::directory_changed_signal, + this, &main_window::update_octave_directory); + + connect (qt_link, &qt_interpreter_events::execute_command_in_terminal_signal, + this, &main_window::execute_command_in_terminal); + + connect (qt_link, &qt_interpreter_events::enter_debugger_signal, + this, &main_window::handle_enter_debugger); + + connect (qt_link, &qt_interpreter_events::exit_debugger_signal, + this, &main_window::handle_exit_debugger); + + connect (qt_link, &qt_interpreter_events::show_preferences_signal, + this, [=] () { process_settings_dialog_request (); }); + + connect (qt_link, &qt_interpreter_events::insert_debugger_pointer_signal, + this, &main_window::handle_insert_debugger_pointer_request); + + connect (qt_link, &qt_interpreter_events::delete_debugger_pointer_signal, + this, &main_window::handle_delete_debugger_pointer_request); + + connect (qt_link, &qt_interpreter_events::update_breakpoint_marker_signal, + this, &main_window::handle_update_breakpoint_marker_request); + + connect (qt_link, &qt_interpreter_events::gui_status_update_signal, + this, &main_window::handle_gui_status_update); + + connect (qt_link, &qt_interpreter_events::update_gui_lexer_signal, + this, &main_window::update_gui_lexer_signal); + } + + QAction* main_window::add_action (QMenu *menu, const QIcon& icon, + const QString& text, const char *member, + const QWidget *receiver) + { + QAction *a; + + if (receiver) + a = menu->addAction (icon, text, receiver, member); + else + a = menu->addAction (icon, text, this, member); + + addAction (a); // important for shortcut context + a->setShortcutContext (Qt::ApplicationShortcut); + return a; + } + + QMenu* main_window::m_add_menu (QMenuBar *p, QString name) + { + QMenu *menu = p->addMenu (name); + + QString base_name = name; // get a copy + // replace intended '&' ("&&") by a temp. string + base_name.replace ("&&", "___octave_amp_replacement___"); + // remove single '&' (shortcut) + base_name.remove ("&"); + // restore intended '&' + base_name.replace ("___octave_amp_replacement___", "&&"); + + // remember names with and without shortcut + m_hash_menu_text[menu] = QStringList ({ name, base_name }); + + return menu; + } + + void main_window::construct_menu_bar (void) + { + QMenuBar *menu_bar = menuBar (); + + construct_file_menu (menu_bar); + + construct_edit_menu (menu_bar); + + construct_debug_menu (menu_bar); + + construct_tools_menu (menu_bar); + + construct_window_menu (menu_bar); + + construct_help_menu (menu_bar); + + construct_news_menu (menu_bar); #if defined (HAVE_QSCINTILLA) - // call the editor to add actions which should also be available in the - // editor's menu and tool bar - QList shared_actions = { - m_new_script_action, - m_new_function_action, - m_open_action, - m_find_files_action, - m_undo_action, - m_copy_action, - m_paste_action, - m_select_all_action - }; - m_editor_window->insert_global_actions (shared_actions); + // call the editor to add actions which should also be available in the + // editor's menu and tool bar + QList shared_actions = { + m_new_script_action, + m_new_function_action, + m_open_action, + m_find_files_action, + m_undo_action, + m_copy_action, + m_paste_action, + m_select_all_action + }; + m_editor_window->insert_global_actions (shared_actions); #endif -} - -void main_window::construct_file_menu (QMenuBar *p) -{ - QMenu *file_menu = m_add_menu (p, tr ("&File")); - - construct_new_menu (file_menu); - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - - m_open_action = add_action ( - file_menu, rmgr.icon ("document-open"), tr ("Open..."), - SLOT (request_open_file (void)), this); - m_open_action->setToolTip (tr ("Open an existing file in editor")); + } + + void main_window::construct_file_menu (QMenuBar *p) + { + QMenu *file_menu = m_add_menu (p, tr ("&File")); + + construct_new_menu (file_menu); + + gui_settings settings; + + m_open_action = add_action ( + file_menu, settings.icon ("document-open"), tr ("Open..."), + SLOT (request_open_file (void)), this); + m_open_action->setToolTip (tr ("Open an existing file in editor")); #if defined (HAVE_QSCINTILLA) - file_menu->addMenu (m_editor_window->get_mru_menu ()); + file_menu->addMenu (m_editor_window->get_mru_menu ()); #endif - file_menu->addSeparator (); - - m_load_workspace_action = add_action ( - file_menu, QIcon (), tr ("Load Workspace..."), - SLOT (handle_load_workspace_request (void)), this); - - m_save_workspace_action = add_action ( - file_menu, QIcon (), tr ("Save Workspace As..."), - SLOT (handle_save_workspace_request (void)), this); - - file_menu->addSeparator (); - - m_exit_action = add_action ( - file_menu, QIcon (), tr ("Exit"), - SLOT (close (void)), this); - m_exit_action->setMenuRole (QAction::QuitRole); - - // Connect signal related to opening or creating editor files - connect (this, SIGNAL (new_file_signal (const QString&)), - m_active_editor, SLOT (request_new_file (const QString&))); - - connect (this, SIGNAL (open_file_signal (const QString&)), - m_active_editor, SLOT (request_open_file (const QString&))); - - connect (this, - SIGNAL (open_file_signal (const QString&, const QString&, int)), - m_active_editor, - SLOT (request_open_file (const QString&, const QString&, int))); -} - -void main_window::construct_new_menu (QMenu *p) -{ - QMenu *new_menu = p->addMenu (tr ("New")); - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - - m_new_script_action = add_action ( - new_menu, rmgr.icon ("document-new"), tr ("New Script"), - SLOT (request_new_script (void)), this); - - m_new_function_action = add_action ( - new_menu, QIcon (), tr ("New Function..."), - SLOT (request_new_function (void)), this); - - m_new_figure_action = add_action ( - new_menu, QIcon (), tr ("New Figure"), - SLOT (handle_new_figure_request (void)), this); -} - -void main_window::construct_edit_menu (QMenuBar *p) -{ - QMenu *edit_menu = m_add_menu (p, tr ("&Edit")); - - QKeySequence ctrl_shift = Qt::ControlModifier + Qt::ShiftModifier; - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - m_undo_action - = edit_menu->addAction (rmgr.icon ("edit-undo"), tr ("Undo")); - m_undo_action->setShortcutContext (Qt::ApplicationShortcut); - - edit_menu->addSeparator (); - - m_copy_action - = edit_menu->addAction (rmgr.icon ("edit-copy"), tr ("Copy"), this, - &main_window::copyClipboard); - m_copy_action->setShortcutContext (Qt::ApplicationShortcut); - - m_paste_action - = edit_menu->addAction (rmgr.icon ("edit-paste"), tr ("Paste"), this, - &main_window::pasteClipboard); - m_paste_action->setShortcutContext (Qt::ApplicationShortcut); - - m_select_all_action - = edit_menu->addAction (tr ("Select All"), this, - &main_window::selectAll); - m_select_all_action->setShortcutContext (Qt::ApplicationShortcut); - - m_clear_clipboard_action - = edit_menu->addAction (tr ("Clear Clipboard"), this, - &main_window::clear_clipboard); - - edit_menu->addSeparator (); - - m_find_files_action - = edit_menu->addAction (rmgr.icon ("edit-find"), tr ("Find Files...")); - - edit_menu->addSeparator (); - - m_clear_command_window_action - = edit_menu->addAction (tr ("Clear Command Window")); - - m_clear_command_history_action - = edit_menu->addAction (tr ("Clear Command History")); - - m_clear_workspace_action - = edit_menu->addAction (tr ("Clear Workspace")); - - edit_menu->addSeparator (); - - m_set_path_action - = edit_menu->addAction (tr ("Set Path")); - - m_preferences_action - = edit_menu->addAction (rmgr.icon ("preferences-system"), - tr ("Preferences...")); - - connect (m_find_files_action, &QAction::triggered, - this, [=] () { find_files (); }); - - connect (m_clear_command_window_action, &QAction::triggered, - this, &main_window::handle_clear_command_window_request); - - connect (m_clear_command_history_action, &QAction::triggered, - this, &main_window::handle_clear_history_request); - - connect (m_clear_workspace_action, &QAction::triggered, - this, &main_window::handle_clear_workspace_request); - - connect (m_clipboard, &QClipboard::dataChanged, - this, &main_window::clipboard_has_changed); - clipboard_has_changed (); + file_menu->addSeparator (); + + m_load_workspace_action = add_action ( + file_menu, QIcon (), tr ("Load Workspace..."), + SLOT (handle_load_workspace_request (void)), this); + + m_save_workspace_action = add_action ( + file_menu, QIcon (), tr ("Save Workspace As..."), + SLOT (handle_save_workspace_request (void)), this); + + file_menu->addSeparator (); + + m_exit_action = add_action ( + file_menu, QIcon (), tr ("Exit"), + SLOT (close (void)), this); + m_exit_action->setMenuRole (QAction::QuitRole); + + // Connect signal related to opening or creating editor files + connect (this, SIGNAL (new_file_signal (const QString&)), + m_active_editor, SLOT (request_new_file (const QString&))); + + connect (this, SIGNAL (open_file_signal (const QString&)), + m_active_editor, SLOT (request_open_file (const QString&))); + + connect (this, + SIGNAL (open_file_signal (const QString&, const QString&, int)), + m_active_editor, + SLOT (request_open_file (const QString&, const QString&, int))); + } + + void main_window::construct_new_menu (QMenu *p) + { + QMenu *new_menu = p->addMenu (tr ("New")); + + gui_settings settings; + + m_new_script_action = add_action ( + new_menu, settings.icon ("document-new"), tr ("New Script"), + SLOT (request_new_script (void)), this); + + m_new_function_action = add_action ( + new_menu, QIcon (), tr ("New Function..."), + SLOT (request_new_function (void)), this); + + m_new_figure_action = add_action ( + new_menu, QIcon (), tr ("New Figure"), + SLOT (handle_new_figure_request (void)), this); + } + + void main_window::construct_edit_menu (QMenuBar *p) + { + QMenu *edit_menu = m_add_menu (p, tr ("&Edit")); + + QKeySequence ctrl_shift = Qt::ControlModifier + Qt::ShiftModifier; + + gui_settings settings; + + m_undo_action + = edit_menu->addAction (settings.icon ("edit-undo"), tr ("Undo")); + m_undo_action->setShortcutContext (Qt::ApplicationShortcut); + + edit_menu->addSeparator (); + + m_copy_action + = edit_menu->addAction (settings.icon ("edit-copy"), tr ("Copy"), this, + &main_window::copyClipboard); + m_copy_action->setShortcutContext (Qt::ApplicationShortcut); + + m_paste_action + = edit_menu->addAction (settings.icon ("edit-paste"), tr ("Paste"), this, + &main_window::pasteClipboard); + m_paste_action->setShortcutContext (Qt::ApplicationShortcut); + + m_select_all_action + = edit_menu->addAction (tr ("Select All"), this, + &main_window::selectAll); + m_select_all_action->setShortcutContext (Qt::ApplicationShortcut); + + m_clear_clipboard_action + = edit_menu->addAction (tr ("Clear Clipboard"), this, + &main_window::clear_clipboard); + + edit_menu->addSeparator (); + + m_find_files_action + = edit_menu->addAction (settings.icon ("edit-find"), tr ("Find Files...")); + + edit_menu->addSeparator (); + + m_clear_command_window_action + = edit_menu->addAction (tr ("Clear Command Window")); + + m_clear_command_history_action + = edit_menu->addAction (tr ("Clear Command History")); + + m_clear_workspace_action + = edit_menu->addAction (tr ("Clear Workspace")); + + edit_menu->addSeparator (); + + m_set_path_action + = edit_menu->addAction (tr ("Set Path")); + + m_preferences_action + = edit_menu->addAction (settings.icon ("preferences-system"), + tr ("Preferences...")); + + connect (m_find_files_action, &QAction::triggered, + this, [=] () { find_files (); }); + + connect (m_clear_command_window_action, &QAction::triggered, + this, &main_window::handle_clear_command_window_request); + + connect (m_clear_command_history_action, &QAction::triggered, + this, &main_window::handle_clear_history_request); + + connect (m_clear_workspace_action, &QAction::triggered, + this, &main_window::handle_clear_workspace_request); + + connect (m_clipboard, &QClipboard::dataChanged, + this, &main_window::clipboard_has_changed); + clipboard_has_changed (); #if defined (Q_OS_WIN32) - // Always enable paste action (unreliable clipboard signals in windows) - // FIXME: This has to be removed, when the clipboard signals in windows - // are working again - m_paste_action->setEnabled (true); - m_clear_clipboard_action->setEnabled (true); + // Always enable paste action (unreliable clipboard signals in windows) + // FIXME: This has to be removed, when the clipboard signals in windows + // are working again + m_paste_action->setEnabled (true); + m_clear_clipboard_action->setEnabled (true); #endif - connect (m_preferences_action, &QAction::triggered, - this, [=] () { process_settings_dialog_request (); }); - - connect (m_set_path_action, &QAction::triggered, - this, &main_window::handle_set_path_dialog_request); - -} - -QAction * main_window::construct_debug_menu_item (const char *icon, - const QString& item, - const char *member) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - QAction *action = add_action (m_debug_menu, rmgr.icon (QString (icon)), - item, member); - - action->setEnabled (false); + connect (m_preferences_action, &QAction::triggered, + this, [=] () { process_settings_dialog_request (); }); + + connect (m_set_path_action, &QAction::triggered, + this, &main_window::handle_set_path_dialog_request); + + } + + QAction * main_window::construct_debug_menu_item (const char *icon, + const QString& item, + const char *member) + { + gui_settings settings; + + QAction *action = add_action (m_debug_menu, settings.icon (QString (icon)), + item, member); + + action->setEnabled (false); #if defined (HAVE_QSCINTILLA) - m_editor_window->debug_menu ()->addAction (action); - m_editor_window->toolbar ()->addAction (action); + m_editor_window->debug_menu ()->addAction (action); + m_editor_window->toolbar ()->addAction (action); #endif - return action; -} - -void main_window::construct_debug_menu (QMenuBar *p) -{ - m_debug_menu = m_add_menu (p, tr ("De&bug")); - - m_debug_step_over - = construct_debug_menu_item ("db-step", tr ("Step"), - SLOT (debug_step_over (void))); - - m_debug_step_into - = construct_debug_menu_item ("db-step-in", tr ("Step In"), - SLOT (debug_step_into (void))); - - m_debug_step_out - = construct_debug_menu_item ("db-step-out", tr ("Step Out"), - SLOT (debug_step_out (void))); - - m_debug_continue - = construct_debug_menu_item ("db-cont", tr ("Continue"), - SLOT (debug_continue (void))); - - m_debug_menu->addSeparator (); + return action; + } + + void main_window::construct_debug_menu (QMenuBar *p) + { + m_debug_menu = m_add_menu (p, tr ("De&bug")); + + m_debug_step_over + = construct_debug_menu_item ("db-step", tr ("Step"), + SLOT (debug_step_over (void))); + + m_debug_step_into + = construct_debug_menu_item ("db-step-in", tr ("Step In"), + SLOT (debug_step_into (void))); + + m_debug_step_out + = construct_debug_menu_item ("db-step-out", tr ("Step Out"), + SLOT (debug_step_out (void))); + + m_debug_continue + = construct_debug_menu_item ("db-cont", tr ("Continue"), + SLOT (debug_continue (void))); + + m_debug_menu->addSeparator (); #if defined (HAVE_QSCINTILLA) - m_editor_window->debug_menu ()->addSeparator (); + m_editor_window->debug_menu ()->addSeparator (); #endif - m_debug_quit - = construct_debug_menu_item ("db-stop", tr ("Quit Debug Mode"), - SLOT (debug_quit (void))); -} - -void main_window::construct_tools_menu (QMenuBar *p) -{ - QMenu *tools_menu = m_add_menu (p, tr ("&Tools")); - - m_profiler_start = add_action (tools_menu, QIcon (), - tr ("Start &Profiler Session"), SLOT (profiler_session ())); - - m_profiler_resume = add_action (tools_menu, QIcon (), - tr ("&Resume Profiler Session"), SLOT (profiler_session_resume ())); - - m_profiler_stop = add_action (tools_menu, QIcon (), - tr ("&Stop Profiler"), SLOT (profiler_stop ())); - m_profiler_stop->setEnabled (false); - - m_profiler_show = add_action (tools_menu, QIcon (), - tr ("&Show Profile Data"), SLOT (profiler_show ())); -} - -void main_window::editor_tabs_changed (bool have_tabs, bool is_octave) -{ - // Set state of actions which depend on the existence of editor tabs - m_editor_has_tabs = have_tabs; - m_editor_is_octave_file = is_octave; - m_debug_step_over->setEnabled (have_tabs && is_octave); -} - -QAction * main_window::construct_window_menu_item (QMenu *p, - const QString& item, - bool checkable, - QWidget *widget) -{ - QAction *action = p->addAction (QIcon (), item); - - addAction (action); // important for shortcut context - action->setCheckable (checkable); - action->setShortcutContext (Qt::ApplicationShortcut); - - if (widget) // might be zero for m_editor_window - { - if (checkable) - { - // action for visibility of dock widget - connect (action, SIGNAL (toggled (bool)), - widget, SLOT (setVisible (bool))); - - connect (widget, SIGNAL (active_changed (bool)), - action, SLOT (setChecked (bool))); - } - else - { - // action for focus of dock widget - connect (action, SIGNAL (triggered (void)), - widget, SLOT (activate (void))); - } - } - else - { - action->setEnabled (false); - } - - return action; -} - -void main_window::construct_window_menu (QMenuBar *p) -{ - QMenu *window_menu = m_add_menu (p, tr ("&Window")); - - m_show_command_window_action = construct_window_menu_item - (window_menu, tr ("Show Command Window"), true, m_command_window); - - m_show_history_action = construct_window_menu_item - (window_menu, tr ("Show Command History"), true, m_history_window); - - m_show_file_browser_action = construct_window_menu_item - (window_menu, tr ("Show File Browser"), true, m_file_browser_window); - - m_show_workspace_action = construct_window_menu_item - (window_menu, tr ("Show Workspace"), true, m_workspace_window); - - m_show_editor_action = construct_window_menu_item - (window_menu, tr ("Show Editor"), true, m_editor_window); - - m_show_documentation_action = construct_window_menu_item - (window_menu, tr ("Show Documentation"), true, m_doc_browser_window); - - m_show_variable_editor_action = construct_window_menu_item - (window_menu, tr ("Show Variable Editor"), true, m_variable_editor_window); - - window_menu->addSeparator (); - - m_command_window_action = construct_window_menu_item - (window_menu, tr ("Command Window"), false, m_command_window); - - m_history_action = construct_window_menu_item - (window_menu, tr ("Command History"), false, m_history_window); - - m_file_browser_action = construct_window_menu_item - (window_menu, tr ("File Browser"), false, m_file_browser_window); - - m_workspace_action = construct_window_menu_item - (window_menu, tr ("Workspace"), false, m_workspace_window); - - m_editor_action = construct_window_menu_item - (window_menu, tr ("Editor"), false, m_editor_window); - - m_documentation_action = construct_window_menu_item - (window_menu, tr ("Documentation"), false, m_doc_browser_window); - - m_variable_editor_action = construct_window_menu_item - (window_menu, tr ("Variable Editor"), false, m_variable_editor_window); - - window_menu->addSeparator (); - - m_previous_dock_action = add_action (window_menu, QIcon (), - tr ("Previous Widget"), SLOT (go_to_previous_widget (void))); - - window_menu->addSeparator (); - - m_reset_windows_action = add_action (window_menu, QIcon (), - tr ("Reset Default Window Layout"), SLOT (reset_windows (void))); -} - -void main_window::construct_help_menu (QMenuBar *p) -{ - QMenu *help_menu = m_add_menu (p, tr ("&Help")); - - construct_documentation_menu (help_menu); - - help_menu->addSeparator (); - - m_report_bug_action = add_action (help_menu, QIcon (), - tr ("Report Bug"), SLOT (open_bug_tracker_page ())); - - m_octave_packages_action = add_action (help_menu, QIcon (), - tr ("Octave Packages"), SLOT (open_octave_packages_page ())); - - m_contribute_action = add_action (help_menu, QIcon (), - tr ("Contribute"), SLOT (open_contribute_page ())); - - m_developer_action = add_action (help_menu, QIcon (), - tr ("Donate to Octave"), SLOT (open_donate_page ())); - - help_menu->addSeparator (); - - m_about_octave_action = add_action (help_menu, QIcon (), - tr ("About Octave"), SLOT (show_about_octave ())); -} - -void main_window::construct_documentation_menu (QMenu *p) -{ - QMenu *doc_menu = p->addMenu (tr ("Documentation")); - - m_ondisk_doc_action = add_action (doc_menu, QIcon (), - tr ("On Disk"), SLOT (activate ()), m_doc_browser_window); - - m_online_doc_action = add_action (doc_menu, QIcon (), - tr ("Online"), SLOT (open_online_documentation_page ())); -} - -void main_window::construct_news_menu (QMenuBar *p) -{ - QMenu *news_menu = m_add_menu (p, tr ("&News")); - - m_release_notes_action - = news_menu->addAction (QIcon (), tr ("Release Notes"), - [=] () { - emit show_release_notes_signal (); - }); - addAction (m_release_notes_action); - m_release_notes_action->setShortcutContext (Qt::ApplicationShortcut); - - m_current_news_action - = news_menu->addAction (QIcon (), tr ("Community News"), - [=] () { - emit show_community_news_signal (-1); - }); - addAction (m_current_news_action); - m_current_news_action->setShortcutContext (Qt::ApplicationShortcut); -} - -void main_window::construct_tool_bar (void) -{ - m_main_tool_bar = addToolBar (tr ("Toolbar")); - m_main_tool_bar->setStyleSheet (m_main_tool_bar->styleSheet () - + global_toolbar_style); - - m_main_tool_bar->setObjectName ("MainToolBar"); - m_main_tool_bar->addAction (m_new_script_action); - m_main_tool_bar->addAction (m_open_action); - - m_main_tool_bar->addSeparator (); - - m_main_tool_bar->addAction (m_copy_action); - m_main_tool_bar->addAction (m_paste_action); - m_main_tool_bar->addAction (m_undo_action); - - m_main_tool_bar->addSeparator (); - - m_current_directory_combo_box = new QComboBox (this); - QFontMetrics fm = m_current_directory_combo_box->fontMetrics (); - m_current_directory_combo_box->setFixedWidth (48*fm.averageCharWidth ()); - m_current_directory_combo_box->setEditable (true); - m_current_directory_combo_box->setInsertPolicy (QComboBox::NoInsert); - m_current_directory_combo_box->setToolTip (tr ("Enter directory name")); - m_current_directory_combo_box->setMaxVisibleItems (current_directory_max_visible); - m_current_directory_combo_box->setMaxCount (current_directory_max_count); - QSizePolicy sizePol (QSizePolicy::Preferred, QSizePolicy::Preferred); - m_current_directory_combo_box->setSizePolicy (sizePol); - - // addWidget takes ownership of the objects so there is no - // need to delete these upon destroying this main_window. - m_main_tool_bar->addWidget (new QLabel (tr ("Current Directory: "))); - m_main_tool_bar->addWidget (m_current_directory_combo_box); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - QAction *current_dir_up - = m_main_tool_bar->addAction (rmgr.icon ("folder-up", false, "go-up"), - tr ("One directory up")); - QAction *current_dir_search - = m_main_tool_bar->addAction (rmgr.icon ("folder"), - tr ("Browse directories")); - - connect (m_current_directory_combo_box, SIGNAL (activated (const QString&)), - this, SLOT (set_current_working_directory (const QString&))); - - connect (m_current_directory_combo_box->lineEdit (), - &QLineEdit::returnPressed, - this, &main_window::accept_directory_line_edit); - - connect (current_dir_search, &QAction::triggered, - this, &main_window::browse_for_directory); - - connect (current_dir_up, &QAction::triggered, - this, &main_window::change_directory_up); - - connect (m_undo_action, &QAction::triggered, - this, &main_window::handle_undo_request); -} - -void main_window::focus_console_after_command (void) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (settings->value (cs_focus_cmd).toBool ()) - focus_command_window (); -} - -void main_window::configure_shortcuts (void) -{ - bool enable - = ! ((m_active_dock == m_command_window) && m_prevent_readline_conflicts); - - shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); - - // file menu - scmgr.set_shortcut (m_open_action, sc_main_file_open_file, enable); - scmgr.set_shortcut (m_new_script_action, sc_main_file_new_file, enable); - scmgr.set_shortcut (m_new_function_action, sc_main_file_new_function, enable); - scmgr.set_shortcut (m_new_figure_action, sc_main_file_new_figure, enable); - scmgr.set_shortcut (m_load_workspace_action, sc_main_file_load_workspace, enable); - scmgr.set_shortcut (m_save_workspace_action, sc_main_file_save_workspace, enable); - scmgr.set_shortcut (m_exit_action, sc_main_file_exit, enable); - - // edit menu - scmgr.set_shortcut (m_copy_action, sc_main_edit_copy, enable); - scmgr.set_shortcut (m_paste_action, sc_main_edit_paste, enable); - scmgr.set_shortcut (m_undo_action, sc_main_edit_undo, enable); - scmgr.set_shortcut (m_select_all_action, sc_main_edit_select_all, enable); - scmgr.set_shortcut (m_clear_clipboard_action, sc_main_edit_clear_clipboard, enable); - scmgr.set_shortcut (m_find_files_action, sc_main_edit_find_in_files, enable); - scmgr.set_shortcut (m_clear_command_history_action, sc_main_edit_clear_history, enable); - scmgr.set_shortcut (m_clear_command_window_action, sc_main_edit_clear_command_window, enable); - scmgr.set_shortcut (m_clear_workspace_action, sc_main_edit_clear_workspace, enable); - scmgr.set_shortcut (m_set_path_action, sc_main_edit_set_path, enable); - scmgr.set_shortcut (m_preferences_action, sc_main_edit_preferences, enable); - - // debug menu - scmgr.set_shortcut (m_debug_step_over, sc_main_debug_step_over, enable); - scmgr.set_shortcut (m_debug_step_into, sc_main_debug_step_into, enable); - scmgr.set_shortcut (m_debug_step_out, sc_main_debug_step_out, enable); - scmgr.set_shortcut (m_debug_continue, sc_main_debug_continue, enable); - scmgr.set_shortcut (m_debug_quit, sc_main_debug_quit, enable); - - // tools menu - scmgr.set_shortcut (m_profiler_start, sc_main_tools_start_profiler, enable); - scmgr.set_shortcut (m_profiler_resume, sc_main_tools_resume_profiler, enable); - scmgr.set_shortcut (m_profiler_stop, sc_main_tools_start_profiler, enable); // same, toggling - scmgr.set_shortcut (m_profiler_show, sc_main_tools_show_profiler, enable); - - // window menu - scmgr.set_shortcut (m_show_command_window_action, sc_main_window_show_command, enable); - scmgr.set_shortcut (m_show_history_action, sc_main_window_show_history, enable); - scmgr.set_shortcut (m_show_workspace_action, sc_main_window_show_workspace, enable); - scmgr.set_shortcut (m_show_file_browser_action, sc_main_window_show_file_browser, enable); - scmgr.set_shortcut (m_show_editor_action, sc_main_window_show_editor, enable); - scmgr.set_shortcut (m_show_documentation_action, sc_main_window_show_doc, enable); - scmgr.set_shortcut (m_show_variable_editor_action, sc_main_window_show_variable_editor, enable); - scmgr.set_shortcut (m_reset_windows_action, sc_main_window_reset, enable); - scmgr.set_shortcut (m_command_window_action, sc_main_window_command, enable); - // Switching to the other widgets (including the previous one) is always enabled - scmgr.set_shortcut (m_history_action, sc_main_window_history, true); - scmgr.set_shortcut (m_workspace_action, sc_main_window_workspace, true); - scmgr.set_shortcut (m_file_browser_action, sc_main_window_file_browser, true); - scmgr.set_shortcut (m_editor_action, sc_main_window_editor, true); - scmgr.set_shortcut (m_documentation_action, sc_main_window_doc, true); - scmgr.set_shortcut (m_variable_editor_action, sc_main_window_variable_editor, true); - scmgr.set_shortcut (m_previous_dock_action, sc_main_window_previous_dock, true); - - // help menu - scmgr.set_shortcut (m_ondisk_doc_action, sc_main_help_ondisk_doc, enable); - scmgr.set_shortcut (m_online_doc_action, sc_main_help_online_doc, enable); - scmgr.set_shortcut (m_report_bug_action, sc_main_help_report_bug, enable); - scmgr.set_shortcut (m_octave_packages_action, sc_main_help_packages, enable); - scmgr.set_shortcut (m_contribute_action, sc_main_help_contribute, enable); - scmgr.set_shortcut (m_developer_action, sc_main_help_developer, enable); - scmgr.set_shortcut (m_about_octave_action, sc_main_help_about, enable); - - // news menu - scmgr.set_shortcut (m_release_notes_action, sc_main_news_release_notes, enable); - scmgr.set_shortcut (m_current_news_action, sc_main_news_community_news, enable); -} - -QList main_window::dock_widget_list (void) -{ - QList list = QList (); - list.append (static_cast (m_command_window)); - list.append (static_cast (m_history_window)); - list.append (static_cast (m_file_browser_window)); - list.append (static_cast (m_doc_browser_window)); + m_debug_quit + = construct_debug_menu_item ("db-stop", tr ("Quit Debug Mode"), + SLOT (debug_quit (void))); + } + + void main_window::construct_tools_menu (QMenuBar *p) + { + QMenu *tools_menu = m_add_menu (p, tr ("&Tools")); + + m_profiler_start = add_action (tools_menu, QIcon (), + tr ("Start &Profiler Session"), SLOT (profiler_session ())); + + m_profiler_resume = add_action (tools_menu, QIcon (), + tr ("&Resume Profiler Session"), SLOT (profiler_session_resume ())); + + m_profiler_stop = add_action (tools_menu, QIcon (), + tr ("&Stop Profiler"), SLOT (profiler_stop ())); + m_profiler_stop->setEnabled (false); + + m_profiler_show = add_action (tools_menu, QIcon (), + tr ("&Show Profile Data"), SLOT (profiler_show ())); + } + + void main_window::editor_tabs_changed (bool have_tabs, bool is_octave) + { + // Set state of actions which depend on the existence of editor tabs + m_editor_has_tabs = have_tabs; + m_editor_is_octave_file = is_octave; + m_debug_step_over->setEnabled (have_tabs && is_octave); + } + + QAction * main_window::construct_window_menu_item (QMenu *p, + const QString& item, + bool checkable, + QWidget *widget) + { + QAction *action = p->addAction (QIcon (), item); + + addAction (action); // important for shortcut context + action->setCheckable (checkable); + action->setShortcutContext (Qt::ApplicationShortcut); + + if (widget) // might be zero for m_editor_window + { + if (checkable) + { + // action for visibility of dock widget + connect (action, SIGNAL (toggled (bool)), + widget, SLOT (setVisible (bool))); + + connect (widget, SIGNAL (active_changed (bool)), + action, SLOT (setChecked (bool))); + } + else + { + // action for focus of dock widget + connect (action, SIGNAL (triggered (void)), + widget, SLOT (activate (void))); + } + } + else + { + action->setEnabled (false); + } + + return action; + } + + void main_window::construct_window_menu (QMenuBar *p) + { + QMenu *window_menu = m_add_menu (p, tr ("&Window")); + + m_show_command_window_action = construct_window_menu_item + (window_menu, tr ("Show Command Window"), true, m_command_window); + + m_show_history_action = construct_window_menu_item + (window_menu, tr ("Show Command History"), true, m_history_window); + + m_show_file_browser_action = construct_window_menu_item + (window_menu, tr ("Show File Browser"), true, m_file_browser_window); + + m_show_workspace_action = construct_window_menu_item + (window_menu, tr ("Show Workspace"), true, m_workspace_window); + + m_show_editor_action = construct_window_menu_item + (window_menu, tr ("Show Editor"), true, m_editor_window); + + m_show_documentation_action = construct_window_menu_item + (window_menu, tr ("Show Documentation"), true, m_doc_browser_window); + + m_show_variable_editor_action = construct_window_menu_item + (window_menu, tr ("Show Variable Editor"), true, m_variable_editor_window); + + window_menu->addSeparator (); + + m_command_window_action = construct_window_menu_item + (window_menu, tr ("Command Window"), false, m_command_window); + + m_history_action = construct_window_menu_item + (window_menu, tr ("Command History"), false, m_history_window); + + m_file_browser_action = construct_window_menu_item + (window_menu, tr ("File Browser"), false, m_file_browser_window); + + m_workspace_action = construct_window_menu_item + (window_menu, tr ("Workspace"), false, m_workspace_window); + + m_editor_action = construct_window_menu_item + (window_menu, tr ("Editor"), false, m_editor_window); + + m_documentation_action = construct_window_menu_item + (window_menu, tr ("Documentation"), false, m_doc_browser_window); + + m_variable_editor_action = construct_window_menu_item + (window_menu, tr ("Variable Editor"), false, m_variable_editor_window); + + window_menu->addSeparator (); + + m_previous_dock_action = add_action (window_menu, QIcon (), + tr ("Previous Widget"), SLOT (go_to_previous_widget (void))); + + window_menu->addSeparator (); + + m_reset_windows_action = add_action (window_menu, QIcon (), + tr ("Reset Default Window Layout"), SLOT (reset_windows (void))); + } + + void main_window::construct_help_menu (QMenuBar *p) + { + QMenu *help_menu = m_add_menu (p, tr ("&Help")); + + construct_documentation_menu (help_menu); + + help_menu->addSeparator (); + + m_report_bug_action = add_action (help_menu, QIcon (), + tr ("Report Bug"), SLOT (open_bug_tracker_page ())); + + m_octave_packages_action = add_action (help_menu, QIcon (), + tr ("Octave Packages"), SLOT (open_octave_packages_page ())); + + m_contribute_action = add_action (help_menu, QIcon (), + tr ("Contribute"), SLOT (open_contribute_page ())); + + m_developer_action = add_action (help_menu, QIcon (), + tr ("Donate to Octave"), SLOT (open_donate_page ())); + + help_menu->addSeparator (); + + m_about_octave_action = add_action (help_menu, QIcon (), + tr ("About Octave"), SLOT (show_about_octave ())); + } + + void main_window::construct_documentation_menu (QMenu *p) + { + QMenu *doc_menu = p->addMenu (tr ("Documentation")); + + m_ondisk_doc_action = add_action (doc_menu, QIcon (), + tr ("On Disk"), SLOT (activate ()), m_doc_browser_window); + + m_online_doc_action = add_action (doc_menu, QIcon (), + tr ("Online"), SLOT (open_online_documentation_page ())); + } + + void main_window::construct_news_menu (QMenuBar *p) + { + QMenu *news_menu = m_add_menu (p, tr ("&News")); + + m_release_notes_action + = news_menu->addAction (QIcon (), tr ("Release Notes"), + [=] () { + emit show_release_notes_signal (); + }); + addAction (m_release_notes_action); + m_release_notes_action->setShortcutContext (Qt::ApplicationShortcut); + + m_current_news_action + = news_menu->addAction (QIcon (), tr ("Community News"), + [=] () { + emit show_community_news_signal (-1); + }); + addAction (m_current_news_action); + m_current_news_action->setShortcutContext (Qt::ApplicationShortcut); + } + + void main_window::construct_tool_bar (void) + { + m_main_tool_bar = addToolBar (tr ("Toolbar")); + m_main_tool_bar->setStyleSheet (m_main_tool_bar->styleSheet () + + global_toolbar_style); + + m_main_tool_bar->setObjectName ("MainToolBar"); + m_main_tool_bar->addAction (m_new_script_action); + m_main_tool_bar->addAction (m_open_action); + + m_main_tool_bar->addSeparator (); + + m_main_tool_bar->addAction (m_copy_action); + m_main_tool_bar->addAction (m_paste_action); + m_main_tool_bar->addAction (m_undo_action); + + m_main_tool_bar->addSeparator (); + + m_current_directory_combo_box = new QComboBox (this); + QFontMetrics fm = m_current_directory_combo_box->fontMetrics (); + m_current_directory_combo_box->setFixedWidth (48*fm.averageCharWidth ()); + m_current_directory_combo_box->setEditable (true); + m_current_directory_combo_box->setInsertPolicy (QComboBox::NoInsert); + m_current_directory_combo_box->setToolTip (tr ("Enter directory name")); + m_current_directory_combo_box->setMaxVisibleItems (current_directory_max_visible); + m_current_directory_combo_box->setMaxCount (current_directory_max_count); + QSizePolicy sizePol (QSizePolicy::Preferred, QSizePolicy::Preferred); + m_current_directory_combo_box->setSizePolicy (sizePol); + + // addWidget takes ownership of the objects so there is no + // need to delete these upon destroying this main_window. + m_main_tool_bar->addWidget (new QLabel (tr ("Current Directory: "))); + m_main_tool_bar->addWidget (m_current_directory_combo_box); + + gui_settings settings; + + QAction *current_dir_up + = m_main_tool_bar->addAction (settings.icon ("folder-up", false, "go-up"), + tr ("One directory up")); + QAction *current_dir_search + = m_main_tool_bar->addAction (settings.icon ("folder"), + tr ("Browse directories")); + + connect (m_current_directory_combo_box, SIGNAL (activated (const QString&)), + this, SLOT (set_current_working_directory (const QString&))); + + connect (m_current_directory_combo_box->lineEdit (), + &QLineEdit::returnPressed, + this, &main_window::accept_directory_line_edit); + + connect (current_dir_search, &QAction::triggered, + this, &main_window::browse_for_directory); + + connect (current_dir_up, &QAction::triggered, + this, &main_window::change_directory_up); + + connect (m_undo_action, &QAction::triggered, + this, &main_window::handle_undo_request); + } + + void main_window::focus_console_after_command (void) + { + gui_settings settings; + + if (settings.value (cs_focus_cmd).toBool ()) + focus_command_window (); + } + + void main_window::configure_shortcuts (void) + { + bool enable + = ! ((m_active_dock == m_command_window) && m_prevent_readline_conflicts); + + shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); + + // file menu + scmgr.set_shortcut (m_open_action, sc_main_file_open_file, enable); + scmgr.set_shortcut (m_new_script_action, sc_main_file_new_file, enable); + scmgr.set_shortcut (m_new_function_action, sc_main_file_new_function, enable); + scmgr.set_shortcut (m_new_figure_action, sc_main_file_new_figure, enable); + scmgr.set_shortcut (m_load_workspace_action, sc_main_file_load_workspace, enable); + scmgr.set_shortcut (m_save_workspace_action, sc_main_file_save_workspace, enable); + scmgr.set_shortcut (m_exit_action, sc_main_file_exit, enable); + + // edit menu + scmgr.set_shortcut (m_copy_action, sc_main_edit_copy, enable); + scmgr.set_shortcut (m_paste_action, sc_main_edit_paste, enable); + scmgr.set_shortcut (m_undo_action, sc_main_edit_undo, enable); + scmgr.set_shortcut (m_select_all_action, sc_main_edit_select_all, enable); + scmgr.set_shortcut (m_clear_clipboard_action, sc_main_edit_clear_clipboard, enable); + scmgr.set_shortcut (m_find_files_action, sc_main_edit_find_in_files, enable); + scmgr.set_shortcut (m_clear_command_history_action, sc_main_edit_clear_history, enable); + scmgr.set_shortcut (m_clear_command_window_action, sc_main_edit_clear_command_window, enable); + scmgr.set_shortcut (m_clear_workspace_action, sc_main_edit_clear_workspace, enable); + scmgr.set_shortcut (m_set_path_action, sc_main_edit_set_path, enable); + scmgr.set_shortcut (m_preferences_action, sc_main_edit_preferences, enable); + + // debug menu + scmgr.set_shortcut (m_debug_step_over, sc_main_debug_step_over, enable); + scmgr.set_shortcut (m_debug_step_into, sc_main_debug_step_into, enable); + scmgr.set_shortcut (m_debug_step_out, sc_main_debug_step_out, enable); + scmgr.set_shortcut (m_debug_continue, sc_main_debug_continue, enable); + scmgr.set_shortcut (m_debug_quit, sc_main_debug_quit, enable); + + // tools menu + scmgr.set_shortcut (m_profiler_start, sc_main_tools_start_profiler, enable); + scmgr.set_shortcut (m_profiler_resume, sc_main_tools_resume_profiler, enable); + scmgr.set_shortcut (m_profiler_stop, sc_main_tools_start_profiler, enable); // same, toggling + scmgr.set_shortcut (m_profiler_show, sc_main_tools_show_profiler, enable); + + // window menu + scmgr.set_shortcut (m_show_command_window_action, sc_main_window_show_command, enable); + scmgr.set_shortcut (m_show_history_action, sc_main_window_show_history, enable); + scmgr.set_shortcut (m_show_workspace_action, sc_main_window_show_workspace, enable); + scmgr.set_shortcut (m_show_file_browser_action, sc_main_window_show_file_browser, enable); + scmgr.set_shortcut (m_show_editor_action, sc_main_window_show_editor, enable); + scmgr.set_shortcut (m_show_documentation_action, sc_main_window_show_doc, enable); + scmgr.set_shortcut (m_show_variable_editor_action, sc_main_window_show_variable_editor, enable); + scmgr.set_shortcut (m_reset_windows_action, sc_main_window_reset, enable); + scmgr.set_shortcut (m_command_window_action, sc_main_window_command, enable); + // Switching to the other widgets (including the previous one) is always enabled + scmgr.set_shortcut (m_history_action, sc_main_window_history, true); + scmgr.set_shortcut (m_workspace_action, sc_main_window_workspace, true); + scmgr.set_shortcut (m_file_browser_action, sc_main_window_file_browser, true); + scmgr.set_shortcut (m_editor_action, sc_main_window_editor, true); + scmgr.set_shortcut (m_documentation_action, sc_main_window_doc, true); + scmgr.set_shortcut (m_variable_editor_action, sc_main_window_variable_editor, true); + scmgr.set_shortcut (m_previous_dock_action, sc_main_window_previous_dock, true); + + // help menu + scmgr.set_shortcut (m_ondisk_doc_action, sc_main_help_ondisk_doc, enable); + scmgr.set_shortcut (m_online_doc_action, sc_main_help_online_doc, enable); + scmgr.set_shortcut (m_report_bug_action, sc_main_help_report_bug, enable); + scmgr.set_shortcut (m_octave_packages_action, sc_main_help_packages, enable); + scmgr.set_shortcut (m_contribute_action, sc_main_help_contribute, enable); + scmgr.set_shortcut (m_developer_action, sc_main_help_developer, enable); + scmgr.set_shortcut (m_about_octave_action, sc_main_help_about, enable); + + // news menu + scmgr.set_shortcut (m_release_notes_action, sc_main_news_release_notes, enable); + scmgr.set_shortcut (m_current_news_action, sc_main_news_community_news, enable); + } + + QList main_window::dock_widget_list (void) + { + QList list = QList (); + list.append (static_cast (m_command_window)); + list.append (static_cast (m_history_window)); + list.append (static_cast (m_file_browser_window)); + list.append (static_cast (m_doc_browser_window)); #if defined (HAVE_QSCINTILLA) - list.append (static_cast (m_editor_window)); + list.append (static_cast (m_editor_window)); #endif - list.append (static_cast (m_workspace_window)); - list.append (static_cast (m_variable_editor_window)); - return list; -} - -void main_window::update_default_encoding (const QString& default_encoding) -{ - m_default_encoding = default_encoding; - std::string mfile_encoding = m_default_encoding.toStdString (); - if (m_default_encoding.startsWith ("SYSTEM", Qt::CaseInsensitive)) - mfile_encoding = "SYSTEM"; - - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD - - F__mfile_encoding__ (interp, ovl (mfile_encoding)); - }); -} - -void main_window::resize_dock (QDockWidget *dw, int width, int height) -{ + list.append (static_cast (m_workspace_window)); + list.append (static_cast (m_variable_editor_window)); + return list; + } + + void main_window::update_default_encoding (const QString& default_encoding) + { + m_default_encoding = default_encoding; + std::string mfile_encoding = m_default_encoding.toStdString (); + if (m_default_encoding.startsWith ("SYSTEM", Qt::CaseInsensitive)) + mfile_encoding = "SYSTEM"; + + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + F__mfile_encoding__ (interp, ovl (mfile_encoding)); + }); + } + + void main_window::resize_dock (QDockWidget *dw, int width, int height) + { #if defined (HAVE_QMAINWINDOW_RESIZEDOCKS) - // resizeDockWidget was added to Qt in Qt 5.6 - if (width >= 0) - resizeDocks ({dw}, {width}, Qt::Horizontal); - if (height >= 0) - resizeDocks ({dw}, {height}, Qt::Vertical); + // resizeDockWidget was added to Qt in Qt 5.6 + if (width >= 0) + resizeDocks ({dw}, {width}, Qt::Horizontal); + if (height >= 0) + resizeDocks ({dw}, {height}, Qt::Vertical); #else - // This replacement of resizeDockWidget is not very reliable. - // But even if Qt4 is not yet - QSize s = dw->widget ()->size (); - if (width >= 0) - s.setWidth (width); - if (height >= 0) - s.setHeight (height); - dw->widget ()->resize (s); - dw->adjustSize (); + // This replacement of resizeDockWidget is not very reliable. + // But even if Qt4 is not yet + QSize s = dw->widget ()->size (); + if (width >= 0) + s.setWidth (width); + if (height >= 0) + s.setHeight (height); + dw->widget ()->resize (s); + dw->adjustSize (); #endif -} - -// The default main window size relative to the desktop size -void main_window::set_default_geometry () -{ - int win_x, win_y; - get_screen_geometry (win_x, win_y); - - move (0, 0); - resize (2*win_x/3, 7*win_y/8); -} - -void main_window::reset_windows (void) -{ - // Slot for resetting the window layout to the default one - hide (); - showNormal (); // Unmaximize - do_reset_windows (true, true, true); // Add all widgets - - // Re-add after giving time: This seems to be a reliable way to - // reset the main window's layout - - // JWE says: The following also works for me with 0 delay, so I - // think the problem might just be that the event loop needs to run - // somewhere in the sequence of resizing and adding widgets. Maybe - // some actions in do_reset_windows should be using signal/slot - // connections so that the event loop can do what it needs to do. - // But I haven't been able to find the magic sequence. - - QTimer::singleShot (250, this, [=] () { do_reset_windows (true, true, true); }); -} - -// Create the default layout of the main window. Do not use -// restoreState () and restoreGeometry () with default values since -// this might lead to problems when the Qt version changes -void main_window::do_reset_windows (bool show, bool save, bool force_all) -{ - // Set main window default geometry and store its width for - // later resizing the command window - set_default_geometry (); - int win_x = geometry ().width (); - - // Resize command window (if docked), - //the important one in the default layout - if (dockWidgetArea (m_command_window) != Qt::NoDockWidgetArea) - resize_dock (m_command_window, 7*win_x/8, -1); - - // See Octave bug #53409 and https://bugreports.qt.io/browse/QTBUG-55357 + } + + // The default main window size relative to the desktop size + void main_window::set_default_geometry () + { + int win_x, win_y; + get_screen_geometry (win_x, win_y); + + move (0, 0); + resize (2*win_x/3, 7*win_y/8); + } + + void main_window::reset_windows (void) + { + // Slot for resetting the window layout to the default one + hide (); + showNormal (); // Unmaximize + do_reset_windows (true, true, true); // Add all widgets + + // Re-add after giving time: This seems to be a reliable way to + // reset the main window's layout + + // JWE says: The following also works for me with 0 delay, so I + // think the problem might just be that the event loop needs to run + // somewhere in the sequence of resizing and adding widgets. Maybe + // some actions in do_reset_windows should be using signal/slot + // connections so that the event loop can do what it needs to do. + // But I haven't been able to find the magic sequence. + + QTimer::singleShot (250, this, [=] () { do_reset_windows (true, true, true); }); + } + + // Create the default layout of the main window. Do not use + // restoreState () and restoreGeometry () with default values since + // this might lead to problems when the Qt version changes + void main_window::do_reset_windows (bool show, bool save, bool force_all) + { + // Set main window default geometry and store its width for + // later resizing the command window + set_default_geometry (); + int win_x = geometry ().width (); + + // Resize command window (if docked), + //the important one in the default layout + if (dockWidgetArea (m_command_window) != Qt::NoDockWidgetArea) + resize_dock (m_command_window, 7*win_x/8, -1); + + // See Octave bug #53409 and https://bugreports.qt.io/browse/QTBUG-55357 #if (QT_VERSION < 0x050601) || (QT_VERSION >= 0x050701) - setDockOptions (QMainWindow::AnimatedDocks - | QMainWindow::AllowNestedDocks - | QMainWindow::AllowTabbedDocks); + setDockOptions (QMainWindow::AnimatedDocks + | QMainWindow::AllowNestedDocks + | QMainWindow::AllowTabbedDocks); #else - setDockNestingEnabled (true); + setDockNestingEnabled (true); #endif - // Add the dock widgets and show them - if (! m_file_browser_window->adopted () || force_all) - { - // FIXME: Maybe there should be a main_window::add_dock_widget - // function that combines both of these actions? - - addDockWidget (Qt::LeftDockWidgetArea, m_file_browser_window); - m_file_browser_window->set_adopted (false); - } - - if (! m_workspace_window->adopted () || force_all) - { - addDockWidget (Qt::LeftDockWidgetArea, m_workspace_window); - m_workspace_window->set_adopted (false); - } - - if (! m_history_window->adopted () || force_all) - { - addDockWidget (Qt::LeftDockWidgetArea, m_history_window); - m_history_window->set_adopted (false); - } - - if (! m_command_window->adopted () || force_all) - { - addDockWidget (Qt::RightDockWidgetArea, m_command_window); - m_command_window->set_adopted (false); - } - - if (! m_doc_browser_window->adopted () || force_all) - { - addDockWidget (Qt::RightDockWidgetArea, m_doc_browser_window); - tabifyDockWidget (m_command_window, m_doc_browser_window); - m_doc_browser_window->set_adopted (false); - } - - if (! m_variable_editor_window->adopted () || force_all) - { - addDockWidget (Qt::RightDockWidgetArea, m_variable_editor_window); - tabifyDockWidget (m_command_window, m_variable_editor_window); - m_variable_editor_window->set_adopted (false); - } + // Add the dock widgets and show them + if (! m_file_browser_window->adopted () || force_all) + { + // FIXME: Maybe there should be a main_window::add_dock_widget + // function that combines both of these actions? + + addDockWidget (Qt::LeftDockWidgetArea, m_file_browser_window); + m_file_browser_window->set_adopted (false); + } + + if (! m_workspace_window->adopted () || force_all) + { + addDockWidget (Qt::LeftDockWidgetArea, m_workspace_window); + m_workspace_window->set_adopted (false); + } + + if (! m_history_window->adopted () || force_all) + { + addDockWidget (Qt::LeftDockWidgetArea, m_history_window); + m_history_window->set_adopted (false); + } + + if (! m_command_window->adopted () || force_all) + { + addDockWidget (Qt::RightDockWidgetArea, m_command_window); + m_command_window->set_adopted (false); + } + + if (! m_doc_browser_window->adopted () || force_all) + { + addDockWidget (Qt::RightDockWidgetArea, m_doc_browser_window); + tabifyDockWidget (m_command_window, m_doc_browser_window); + m_doc_browser_window->set_adopted (false); + } + + if (! m_variable_editor_window->adopted () || force_all) + { + addDockWidget (Qt::RightDockWidgetArea, m_variable_editor_window); + tabifyDockWidget (m_command_window, m_variable_editor_window); + m_variable_editor_window->set_adopted (false); + } #if defined (HAVE_QSCINTILLA) - addDockWidget (Qt::RightDockWidgetArea, m_editor_window); - tabifyDockWidget (m_command_window, m_editor_window); + addDockWidget (Qt::RightDockWidgetArea, m_editor_window); + tabifyDockWidget (m_command_window, m_editor_window); #endif - // Resize command window, the important one in the default layout - resize_dock (m_command_window, 2*win_x/3, -1); - - // Show main wibdow, save state and geometry of main window and - // all dock widgets - if (show) - { - // Show all dock widgets - for (auto *widget : dock_widget_list ()) - widget->show (); - - // Show main window and store size and state - showNormal (); - - if (save) - { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - settings->setValue (mw_geometry.key, saveGeometry ()); - settings->setValue (mw_state.key, saveState ()); - } - - focus_command_window (); - } -} + // Resize command window, the important one in the default layout + resize_dock (m_command_window, 2*win_x/3, -1); + + // Show main wibdow, save state and geometry of main window and + // all dock widgets + if (show) + { + // Show all dock widgets + for (auto *widget : dock_widget_list ()) + widget->show (); + + // Show main window and store size and state + showNormal (); + + if (save) + { + gui_settings settings; + + settings.setValue (mw_geometry.key, saveGeometry ()); + settings.setValue (mw_state.key, saveState ()); + } + + focus_command_window (); + } + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/main-window.h --- a/libgui/src/main-window.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/main-window.h Tue Dec 06 15:45:27 2022 -0500 @@ -52,7 +52,6 @@ #include "interpreter-qobject.h" #include "led-indicator.h" #include "octave-dock-widget.h" -#include "octave-qobject.h" #include "qt-interpreter-events.h" #include "set-path-dialog.h" #include "terminal-dock-widget.h" @@ -63,383 +62,383 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class interpreter; + class interpreter; -class settings_dialog; + class base_qobject; + class settings_dialog; -//! Represents the main window. + //! Represents the main window. -class main_window : public QMainWindow -{ - Q_OBJECT + class main_window : public QMainWindow + { + Q_OBJECT -public: + public: - typedef std::pair name_pair; - typedef std::pair int_pair; + typedef std::pair name_pair; + typedef std::pair int_pair; - main_window (base_qobject& oct_qobj); + main_window (base_qobject& oct_qobj); - ~main_window (void); + ~main_window (void); - void make_dock_widget_connections (octave_dock_widget *dw); + void make_dock_widget_connections (octave_dock_widget *dw); - bool command_window_has_focus (void) const; + bool command_window_has_focus (void) const; - void focus_command_window (void); + void focus_command_window (void); - bool confirm_shutdown (void); + bool confirm_shutdown (void); -signals: + signals: - // Note: CLOSE_GUI_SIGNAL is currently only used by the new - // experimental terminal widget. - void close_gui_signal (void); + // Note: CLOSE_GUI_SIGNAL is currently only used by the new + // experimental terminal widget. + void close_gui_signal (void); - void active_dock_changed (octave_dock_widget *, octave_dock_widget *); - void editor_focus_changed (bool); + void active_dock_changed (octave_dock_widget *, octave_dock_widget *); + void editor_focus_changed (bool); - void settings_changed (const gui_settings *); - void init_terminal_size_signal (void); - void init_window_menu (void); - void new_file_signal (const QString&); - void open_file_signal (const QString&); - void open_file_signal (const QString& file, const QString& enc, int line); - void step_into_file_signal (void); + void settings_changed (void); + void init_terminal_size_signal (void); + void init_window_menu (void); + void new_file_signal (const QString&); + void open_file_signal (const QString&); + void open_file_signal (const QString& file, const QString& enc, int line); + void step_into_file_signal (void); - void show_community_news_signal (int serial); - void show_release_notes_signal (void); + void show_community_news_signal (int serial); + void show_release_notes_signal (void); - void update_gui_lexer_signal (bool); + void update_gui_lexer_signal (bool); - void insert_debugger_pointer_signal (const QString& file, int line); - void delete_debugger_pointer_signal (const QString& file, int line); - void update_breakpoint_marker_signal (bool insert, const QString& file, - int line, const QString& cond); + void insert_debugger_pointer_signal (const QString& file, int line); + void delete_debugger_pointer_signal (const QString& file, int line); + void update_breakpoint_marker_signal (bool insert, const QString& file, + int line, const QString& cond); - void copyClipboard_signal (void); - void pasteClipboard_signal (void); - void selectAll_signal (void); - void undo_signal (void); + void copyClipboard_signal (void); + void pasteClipboard_signal (void); + void selectAll_signal (void); + void undo_signal (void); - void add_actions_signal (QList action_list); + void add_actions_signal (QList action_list); - void warning_function_not_found_signal (const QString& message); + void warning_function_not_found_signal (const QString& message); - void interpreter_event (const fcn_callback& fcn); - void interpreter_event (const meth_callback& meth); + void interpreter_event (const fcn_callback& fcn); + void interpreter_event (const meth_callback& meth); - void execute_command_signal (const QString& command); + void execute_command_signal (const QString& command); -public slots: + public slots: - void focus_changed (QWidget *w_old, QWidget *w_new); - void focus_window (const QString& win_name); - void request_reload_settings (void); + void focus_changed (QWidget *w_old, QWidget *w_new); + void focus_window (const QString& win_name); + void request_reload_settings (void); - void report_status_message (const QString& statusMessage); - void handle_save_workspace_request (void); - void handle_load_workspace_request (const QString& file = QString ()); - void handle_open_any_request (const QString& file = QString ()); - void handle_clear_workspace_request (void); - void handle_clear_command_window_request (void); - void handle_clear_history_request (void); - void handle_undo_request (void); - void modify_path (const QStringList& dir_list, bool rm, bool subdirs); - void edit_mfile (const QString&, int); - void file_remove_proxy (const QString& o, const QString& n); - void open_online_documentation_page (void); - void open_bug_tracker_page (void); - void open_octave_packages_page (void); - void open_contribute_page (void); - void open_donate_page (void); - void process_settings_dialog_request (const QString& desired_tab - = QString ()); - void show_about_octave (void); - void notice_settings (const gui_settings *settings, - bool update_by_worker = false); - QPalette getFusionDarkPalette(); - void prepare_to_exit (void); - void go_to_previous_widget (void); - void reset_windows (void); - void do_reset_windows (bool show = true, bool save = true, - bool force_all = false); + void report_status_message (const QString& statusMessage); + void handle_save_workspace_request (void); + void handle_load_workspace_request (const QString& file = QString ()); + void handle_open_any_request (const QString& file = QString ()); + void handle_clear_workspace_request (void); + void handle_clear_command_window_request (void); + void handle_clear_history_request (void); + void handle_undo_request (void); + void modify_path (const QStringList& dir_list, bool rm, bool subdirs); + void edit_mfile (const QString&, int); + void file_remove_proxy (const QString& o, const QString& n); + void open_online_documentation_page (void); + void open_bug_tracker_page (void); + void open_octave_packages_page (void); + void open_contribute_page (void); + void open_donate_page (void); + void process_settings_dialog_request (const QString& desired_tab + = QString ()); + void show_about_octave (void); + void notice_settings (bool update_by_worker = false); + QPalette getFusionDarkPalette(); + void prepare_to_exit (void); + void go_to_previous_widget (void); + void reset_windows (void); + void do_reset_windows (bool show = true, bool save = true, + bool force_all = false); - void update_octave_directory (const QString& dir); - void browse_for_directory (void); - void set_current_working_directory (const QString& dir); - void change_directory_up (void); - void accept_directory_line_edit (void); + void update_octave_directory (const QString& dir); + void browse_for_directory (void); + void set_current_working_directory (const QString& dir); + void change_directory_up (void); + void accept_directory_line_edit (void); - void execute_command_in_terminal (const QString& dir); - void run_file_in_terminal (const QFileInfo& info); + void execute_command_in_terminal (const QString& dir); + void run_file_in_terminal (const QFileInfo& info); - void handle_new_figure_request (void); + void handle_new_figure_request (void); - void handle_enter_debugger (void); - void handle_exit_debugger (void); - void debug_continue (void); - void debug_step_into (void); - void debug_step_over (void); - void debug_step_out (void); - void debug_quit (void); - void editor_tabs_changed (bool, bool); + void handle_enter_debugger (void); + void handle_exit_debugger (void); + void debug_continue (void); + void debug_step_into (void); + void debug_step_over (void); + void debug_step_out (void); + void debug_quit (void); + void editor_tabs_changed (bool, bool); - void request_open_file (void); - void request_new_script (const QString& commands = QString ()); - void request_new_function (bool triggered = true); - void handle_edit_mfile_request (const QString& name, const QString& file, - const QString& curr_dir, int line); + void request_open_file (void); + void request_new_script (const QString& commands = QString ()); + void request_new_function (bool triggered = true); + void handle_edit_mfile_request (const QString& name, const QString& file, + const QString& curr_dir, int line); - void handle_insert_debugger_pointer_request (const QString& file, int line); - void handle_delete_debugger_pointer_request (const QString& file, int line); - void handle_update_breakpoint_marker_request (bool insert, - const QString& file, int line, - const QString& cond); + void handle_insert_debugger_pointer_request (const QString& file, int line); + void handle_delete_debugger_pointer_request (const QString& file, int line); + void handle_update_breakpoint_marker_request (bool insert, + const QString& file, int line, + const QString& cond); - void read_settings (void); - void init_terminal_size (void); - void set_window_layout (gui_settings *settings); - void write_settings (void); + void read_settings (void); + void init_terminal_size (void); + void set_window_layout (void); + void write_settings (void); - void copyClipboard (void); - void pasteClipboard (void); - void selectAll (void); + void copyClipboard (void); + void pasteClipboard (void); + void selectAll (void); - void handle_gui_status_update (const QString& feature, const QString& status); + void handle_gui_status_update (const QString& feature, const QString& status); - void focus_console_after_command (void); + void focus_console_after_command (void); - void profiler_session (void); - void profiler_session_resume (void); - void profiler_stop (void); - void handle_profiler_status_update (bool); - void profiler_show (void); + void profiler_session (void); + void profiler_session_resume (void); + void profiler_stop (void); + void handle_profiler_status_update (bool); + void profiler_show (void); - void handle_octave_ready (); + void handle_octave_ready (); - void handle_set_path_dialog_request (void); + void handle_set_path_dialog_request (void); - //! Find files dialog. - //!@{ - void find_files (const QString& startdir = QDir::currentPath ()); - void find_files_finished (int) { } - //!@} + //! Find files dialog. + //!@{ + void find_files (const QString& startdir = QDir::currentPath ()); + void find_files_finished (int) { } + //!@} - void set_screen_size (int ht, int wd); + void set_screen_size (int ht, int wd); - //! Handling the clipboard. - //!@{ - void clipboard_has_changed (void); - void clear_clipboard (); - //!@} + //! Handling the clipboard. + //!@{ + void clipboard_has_changed (void); + void clear_clipboard (); + //!@} - //! Returns a list of dock widgets. + //! Returns a list of dock widgets. - QList get_dock_widget_list (void) - { - return dock_widget_list (); - } + QList get_dock_widget_list (void) + { + return dock_widget_list (); + } -private slots: + private slots: - void disable_menu_shortcuts (bool disable); - void restore_create_file_setting (void); - void set_file_encoding (const QString& new_encoding); - void request_open_files (const QStringList& open_file_names); + void disable_menu_shortcuts (bool disable); + void restore_create_file_setting (void); + void set_file_encoding (const QString& new_encoding); + void request_open_files (const QStringList& open_file_names); - void warning_function_not_found (const QString& message); + void warning_function_not_found (const QString& message); -protected: + protected: - void closeEvent (QCloseEvent *closeEvent); + void closeEvent (QCloseEvent *closeEvent); -private: + private: - void adopt_dock_widgets (void); + void adopt_dock_widgets (void); - void adopt_terminal_widget (void); - void adopt_documentation_widget (void); - void adopt_file_browser_widget (void); - void adopt_history_widget (void); - void adopt_workspace_widget (void); - void adopt_editor_widget (void); - void adopt_variable_editor_widget (void); + void adopt_terminal_widget (void); + void adopt_documentation_widget (void); + void adopt_file_browser_widget (void); + void adopt_history_widget (void); + void adopt_workspace_widget (void); + void adopt_editor_widget (void); + void adopt_variable_editor_widget (void); - void construct_central_widget (void); + void construct_central_widget (void); - void construct (void); + void construct (void); - void construct_octave_qt_link (void); + void construct_octave_qt_link (void); - QAction * add_action (QMenu *menu, const QIcon& icon, - const QString& text, const char *member, - const QWidget *receiver = nullptr); + QAction * add_action (QMenu *menu, const QIcon& icon, + const QString& text, const char *member, + const QWidget *receiver = nullptr); - QMenu * m_add_menu (QMenuBar *p, QString text); - void construct_menu_bar (void); - void construct_file_menu (QMenuBar *p); - void construct_new_menu (QMenu *p); - void construct_edit_menu (QMenuBar *p); - QAction * construct_debug_menu_item (const char *icon, const QString& item, - const char *member); - void construct_debug_menu (QMenuBar *p); - QAction * construct_window_menu_item (QMenu *p, const QString& item, - bool checkable, QWidget *); - void construct_tools_menu (QMenuBar *p); - void construct_window_menu (QMenuBar *p); - void construct_help_menu (QMenuBar *p); - void construct_documentation_menu (QMenu *p); + QMenu * m_add_menu (QMenuBar *p, QString text); + void construct_menu_bar (void); + void construct_file_menu (QMenuBar *p); + void construct_new_menu (QMenu *p); + void construct_edit_menu (QMenuBar *p); + QAction * construct_debug_menu_item (const char *icon, const QString& item, + const char *member); + void construct_debug_menu (QMenuBar *p); + QAction * construct_window_menu_item (QMenu *p, const QString& item, + bool checkable, QWidget *); + void construct_tools_menu (QMenuBar *p); + void construct_window_menu (QMenuBar *p); + void construct_help_menu (QMenuBar *p); + void construct_documentation_menu (QMenu *p); - void construct_news_menu (QMenuBar *p); + void construct_news_menu (QMenuBar *p); - void construct_tool_bar (void); + void construct_tool_bar (void); - void configure_shortcuts (void); + void configure_shortcuts (void); - QList dock_widget_list (void); + QList dock_widget_list (void); - void update_default_encoding (const QString& default_encoding); + void update_default_encoding (const QString& default_encoding); - void set_default_geometry (void); - void resize_dock (QDockWidget *dw, int width, int height); + void set_default_geometry (void); + void resize_dock (QDockWidget *dw, int width, int height); - base_qobject& m_octave_qobj; + base_qobject& m_octave_qobj; - QHash m_hash_menu_text; + QHash m_hash_menu_text; - QString m_default_encoding; + QString m_default_encoding; - QString m_default_style; - QPalette m_default_palette; + QString m_default_style; + QPalette m_default_palette; - //! Toolbar. + //! Toolbar. - QStatusBar *m_status_bar; - led_indicator *m_profiler_status_indicator; + QStatusBar *m_status_bar; + led_indicator *m_profiler_status_indicator; - //! Dock widgets. - //!@{ - QPointer m_command_window; - QPointer m_history_window; - QPointer m_file_browser_window; - QPointer m_doc_browser_window; - QPointer m_editor_window; - QPointer m_workspace_window; - QPointer m_variable_editor_window; - //!@} + //! Dock widgets. + //!@{ + QPointer m_command_window; + QPointer m_history_window; + QPointer m_file_browser_window; + QPointer m_doc_browser_window; + QPointer m_editor_window; + QPointer m_workspace_window; + QPointer m_variable_editor_window; + //!@} - external_editor_interface *m_external_editor; - QWidget *m_active_editor; + external_editor_interface *m_external_editor; + QWidget *m_active_editor; - octave_dock_widget *m_previous_dock; - octave_dock_widget *m_active_dock; + octave_dock_widget *m_previous_dock; + octave_dock_widget *m_active_dock; - QToolBar *m_main_tool_bar; + QToolBar *m_main_tool_bar; - QMenu *m_debug_menu; + QMenu *m_debug_menu; - QMenuBar *m_editor_menubar; + QMenuBar *m_editor_menubar; - QAction *m_debug_continue; - QAction *m_debug_step_into; - QAction *m_debug_step_over; - QAction *m_debug_step_out; - QAction *m_debug_quit; + QAction *m_debug_continue; + QAction *m_debug_step_into; + QAction *m_debug_step_over; + QAction *m_debug_step_out; + QAction *m_debug_quit; - QAction *m_new_script_action; - QAction *m_new_function_action; - QAction *m_open_action; - QAction *m_new_figure_action; - QAction *m_load_workspace_action; - QAction *m_save_workspace_action; - QAction *m_set_path_action; - QAction *m_preferences_action; - QAction *m_exit_action; + QAction *m_new_script_action; + QAction *m_new_function_action; + QAction *m_open_action; + QAction *m_new_figure_action; + QAction *m_load_workspace_action; + QAction *m_save_workspace_action; + QAction *m_set_path_action; + QAction *m_preferences_action; + QAction *m_exit_action; - QAction *m_copy_action; - QAction *m_paste_action; - QAction *m_clear_clipboard_action; - QAction *m_undo_action; - QAction *m_clear_command_window_action; - QAction *m_clear_command_history_action; - QAction *m_clear_workspace_action; - QAction *m_find_files_action; - QAction *m_select_all_action; + QAction *m_copy_action; + QAction *m_paste_action; + QAction *m_clear_clipboard_action; + QAction *m_undo_action; + QAction *m_clear_command_window_action; + QAction *m_clear_command_history_action; + QAction *m_clear_workspace_action; + QAction *m_find_files_action; + QAction *m_select_all_action; - QAction *m_profiler_start; - QAction *m_profiler_resume; - QAction *m_profiler_stop; - QAction *m_profiler_show; + QAction *m_profiler_start; + QAction *m_profiler_resume; + QAction *m_profiler_stop; + QAction *m_profiler_show; - QAction *m_show_command_window_action; - QAction *m_show_history_action; - QAction *m_show_workspace_action; - QAction *m_show_file_browser_action; - QAction *m_show_editor_action; - QAction *m_show_documentation_action; - QAction *m_show_variable_editor_action; - QAction *m_command_window_action; - QAction *m_history_action; - QAction *m_workspace_action; - QAction *m_file_browser_action; - QAction *m_editor_action; - QAction *m_documentation_action; - QAction *m_variable_editor_action; - QAction *m_previous_dock_action; - QAction *m_reset_windows_action; + QAction *m_show_command_window_action; + QAction *m_show_history_action; + QAction *m_show_workspace_action; + QAction *m_show_file_browser_action; + QAction *m_show_editor_action; + QAction *m_show_documentation_action; + QAction *m_show_variable_editor_action; + QAction *m_command_window_action; + QAction *m_history_action; + QAction *m_workspace_action; + QAction *m_file_browser_action; + QAction *m_editor_action; + QAction *m_documentation_action; + QAction *m_variable_editor_action; + QAction *m_previous_dock_action; + QAction *m_reset_windows_action; - QAction *m_ondisk_doc_action; - QAction *m_online_doc_action; - QAction *m_report_bug_action; - QAction *m_octave_packages_action; - QAction *m_contribute_action; - QAction *m_developer_action; - QAction *m_about_octave_action; + QAction *m_ondisk_doc_action; + QAction *m_online_doc_action; + QAction *m_report_bug_action; + QAction *m_octave_packages_action; + QAction *m_contribute_action; + QAction *m_developer_action; + QAction *m_about_octave_action; - QAction *m_release_notes_action; - QAction *m_current_news_action; + QAction *m_release_notes_action; + QAction *m_current_news_action; - //! For Toolbars. - //!@{ - QComboBox *m_current_directory_combo_box; - static const int current_directory_max_visible = 16; - static const int current_directory_max_count = 16; - QLineEdit *m_current_directory_line_edit; - //!@} + //! For Toolbars. + //!@{ + QComboBox *m_current_directory_combo_box; + static const int current_directory_max_visible = 16; + static const int current_directory_max_count = 16; + QLineEdit *m_current_directory_line_edit; + //!@} - //! Settings dialog as guarded pointer (set to 0 when deleted). + //! Settings dialog as guarded pointer (set to 0 when deleted). - QPointer m_settings_dlg; + QPointer m_settings_dlg; - //! Find files dialog. + //! Find files dialog. - find_files_dialog *m_find_files_dlg; + find_files_dialog *m_find_files_dlg; - //! Set path dialog - QPointer m_set_path_dlg; + //! Set path dialog + QPointer m_set_path_dlg; - //! Release notes window. + //! Release notes window. - QWidget *m_release_notes_window; + QWidget *m_release_notes_window; - QClipboard *m_clipboard; + QClipboard *m_clipboard; - //! Some class global flags. - //!@{ - bool m_prevent_readline_conflicts; - bool m_prevent_readline_conflicts_menu; - bool m_suppress_dbg_location; - bool m_editor_has_tabs; - bool m_editor_is_octave_file; + //! Some class global flags. + //!@{ + bool m_prevent_readline_conflicts; + bool m_prevent_readline_conflicts_menu; + bool m_suppress_dbg_location; + bool m_editor_has_tabs; + bool m_editor_is_octave_file; - //! Flag for closing the whole application. + //! Flag for closing the whole application. - bool m_closing; - //!@} + bool m_closing; + //!@} - QString m_file_encoding; -}; + QString m_file_encoding; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/news-reader.cc --- a/libgui/src/news-reader.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/news-reader.cc Tue Dec 06 15:45:27 2022 -0500 @@ -33,123 +33,114 @@ #include #include "news-reader.h" -#include "octave-qobject.h" #include "gui-preferences-nr.h" +#include "gui-settings.h" #include "url-transfer.h" #include "version.h" OCTAVE_BEGIN_NAMESPACE(octave) -void news_reader::process (void) -{ - QString html_text; + void news_reader::process (void) + { + QString html_text; - if (m_connect_to_web) - { - // Run this part in a separate thread so Octave can continue to - // run while we wait for the page to load. Then emit the signal - // to display it when we have the page contents. + if (m_connect_to_web) + { + // Run this part in a separate thread so Octave can continue to + // run while we wait for the page to load. Then emit the signal + // to display it when we have the page contents. - QString url = m_base_url + '/' + m_page; - std::ostringstream buf; - url_transfer octave_dot_org (url.toStdString (), buf); + QString url = m_base_url + '/' + m_page; + std::ostringstream buf; + url_transfer octave_dot_org (url.toStdString (), buf); - if (octave_dot_org.is_valid ()) - { - Array param; - octave_dot_org.http_get (param); + if (octave_dot_org.is_valid ()) + { + Array param; + octave_dot_org.http_get (param); - if (octave_dot_org.good ()) - html_text = QString::fromStdString (buf.str ()); - } + if (octave_dot_org.good ()) + html_text = QString::fromStdString (buf.str ()); + } - if (html_text.contains ("this-is-the-gnu-octave-community-news-page")) - { - if (m_serial >= 0) - { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + if (html_text.contains ("this-is-the-gnu-octave-community-news-page")) + { + if (m_serial >= 0) + { + gui_settings settings; - if (settings) - { - settings->setValue (nr_last_time.key, - QDateTime::currentDateTime ()); + settings.setValue (nr_last_time.key, + QDateTime::currentDateTime ()); + + settings.sync (); - settings->sync (); - } + QString tag ("community-news-page-serial="); - QString tag ("community-news-page-serial="); - - int b = html_text.indexOf (tag); + int b = html_text.indexOf (tag); - if (b) - { - b += tag.length (); + if (b) + { + b += tag.length (); - int e = html_text.indexOf ("\n", b); + int e = html_text.indexOf ("\n", b); - QString tmp = html_text.mid (b, e-b); + QString tmp = html_text.mid (b, e-b); - int curr_page_serial = tmp.toInt (); + int curr_page_serial = tmp.toInt (); - if (curr_page_serial > m_serial) - { - if (settings) - { - settings->setValue (nr_last_news.key, - curr_page_serial); + if (curr_page_serial > m_serial) + { + settings.setValue (nr_last_news.key, curr_page_serial); + settings.sync (); + } + else + return; + } + else + return; + } + } + else + html_text = QString + (tr ("\n" + "\n" + "

\n" + "Octave's community news source seems to be unavailable.\n" + "

\n" + "

\n" + "For the latest news, please check\n" + "https://octave.org/community-news.html\n" + "when you have a connection to the web (link opens in an external browser).\n" + "

\n" + "

\n" + "— The Octave Developers, ") + OCTAVE_RELEASE_DATE + "\n" + "

\n" + "\n" + "\n"); + } + else + html_text = QString + (tr ("\n" + "\n" + "

\n" + "Connecting to the web to display the latest Octave Community news has been disabled.\n" + "

\n" + "

\n" + "For the latest news, please check\n" + "https://octave.org/community-news.html\n" + "when you have a connection to the web (link opens in an external browser)\n" + "or enable web connections for news in Octave's network settings dialog.\n" + "

\n" + "

\n" + "— The Octave Developers, ") + OCTAVE_RELEASE_DATE + "\n" + "

\n" + "\n" + "\n"); - settings->sync (); - } - } - else - return; - } - else - return; - } - } - else - html_text = QString - (tr ("\n" - "\n" - "

\n" - "Octave's community news source seems to be unavailable.\n" - "

\n" - "

\n" - "For the latest news, please check\n" - "https://octave.org/community-news.html\n" - "when you have a connection to the web (link opens in an external browser).\n" - "

\n" - "

\n" - "— The Octave Developers, ") + OCTAVE_RELEASE_DATE + "\n" - "

\n" - "\n" - "\n"); - } - else - html_text = QString - (tr ("\n" - "\n" - "

\n" - "Connecting to the web to display the latest Octave Community news has been disabled.\n" - "

\n" - "

\n" - "For the latest news, please check\n" - "https://octave.org/community-news.html\n" - "when you have a connection to the web (link opens in an external browser)\n" - "or enable web connections for news in Octave's network settings dialog.\n" - "

\n" - "

\n" - "— The Octave Developers, ") + OCTAVE_RELEASE_DATE + "\n" - "

\n" - "\n" - "\n"); + emit display_news_signal (html_text); - emit display_news_signal (html_text); - - emit finished (); -} + emit finished (); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/news-reader.h --- a/libgui/src/news-reader.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/news-reader.h Tue Dec 06 15:45:27 2022 -0500 @@ -31,40 +31,35 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; + class news_reader : public QObject + { + Q_OBJECT -class news_reader : public QObject -{ - Q_OBJECT - -public: + public: - news_reader (base_qobject& oct_qobj, const QString& base_url, - const QString& page, int serial = -1, - bool connect_to_web = false) - : QObject (), m_octave_qobj (oct_qobj), m_base_url (base_url), - m_page (page), m_serial (serial), m_connect_to_web (connect_to_web) - { } + news_reader (const QString& base_url, const QString& page, + int serial = -1, bool connect_to_web = false) + : QObject (), m_base_url (base_url), + m_page (page), m_serial (serial), m_connect_to_web (connect_to_web) + { } -signals: + signals: - void display_news_signal (const QString& news); + void display_news_signal (const QString& news); - void finished (void); + void finished (void); -public slots: + public slots: - void process (void); + void process (void); -private: - - base_qobject& m_octave_qobj; + private: - QString m_base_url; - QString m_page; - int m_serial; - bool m_connect_to_web; -}; + QString m_base_url; + QString m_page; + int m_serial; + bool m_connect_to_web; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/octave-dock-widget.cc --- a/libgui/src/octave-dock-widget.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/octave-dock-widget.cc Tue Dec 06 15:45:27 2022 -0500 @@ -49,810 +49,786 @@ OCTAVE_BEGIN_NAMESPACE(octave) -label_dock_widget::label_dock_widget (QWidget *p, base_qobject& oct_qobj) -: QDockWidget (p), m_octave_qobj (oct_qobj), - m_default_float_button (nullptr), m_default_close_button (nullptr) -{ - QStyle *st = style (); - m_icon_size = 0.75*st->pixelMetric (QStyle::PM_SmallIconSize); + label_dock_widget::label_dock_widget (QWidget *p, base_qobject& oct_qobj) + : QDockWidget (p), m_octave_qobj (oct_qobj), + m_default_float_button (nullptr), m_default_close_button (nullptr) + { + QStyle *st = style (); + m_icon_size = 0.75*st->pixelMetric (QStyle::PM_SmallIconSize); - // keep track of the original buttons on the default title bar, - // the button further left is considered "float" - QList buttonlist = findChildren (); - if (buttonlist.size () == 2) - { - if (buttonlist.at (0)->x () < buttonlist.at (1)->x ()) - { - m_default_float_button = buttonlist.at (0); - m_default_close_button = buttonlist.at (1); - } - else - { - m_default_float_button = buttonlist.at (1); - m_default_close_button = buttonlist.at (0); - } - } + // keep track of the original buttons on the default title bar, + // the button further left is considered "float" + QList buttonlist = findChildren (); + if (buttonlist.size () == 2) + { + if (buttonlist.at (0)->x () < buttonlist.at (1)->x ()) + { + m_default_float_button = buttonlist.at (0); + m_default_close_button = buttonlist.at (1); + } + else + { + m_default_float_button = buttonlist.at (1); + m_default_close_button = buttonlist.at (0); + } + } - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; - // the custom (extra) title bar of the widget - m_title_widget = new QWidget (); + // the custom (extra) title bar of the widget + m_title_widget = new QWidget (); - m_dock_action = new QAction - (rmgr.icon ("widget-undock", true), "", this); - m_dock_action->setToolTip (tr ("Undock widget")); - m_dock_button = new QToolButton (m_title_widget); - m_dock_button->setDefaultAction (m_dock_action); - m_dock_button->setFocusPolicy (Qt::NoFocus); - m_dock_button->setIconSize (QSize (m_icon_size, m_icon_size)); + m_dock_action = new QAction + (settings.icon ("widget-undock", true), "", this); + m_dock_action->setToolTip (tr ("Undock widget")); + m_dock_button = new QToolButton (m_title_widget); + m_dock_button->setDefaultAction (m_dock_action); + m_dock_button->setFocusPolicy (Qt::NoFocus); + m_dock_button->setIconSize (QSize (m_icon_size, m_icon_size)); - m_close_action = new QAction - (rmgr.icon ("widget-close", true), "", this); - m_close_action->setToolTip (tr ("Close widget")); - m_close_button = new QToolButton (m_title_widget); - m_close_button->setDefaultAction (m_close_action); - m_close_button->setFocusPolicy (Qt::NoFocus); - m_close_button->setIconSize (QSize (m_icon_size, m_icon_size)); + m_close_action = new QAction + (settings.icon ("widget-close", true), "", this); + m_close_action->setToolTip (tr ("Close widget")); + m_close_button = new QToolButton (m_title_widget); + m_close_button->setDefaultAction (m_close_action); + m_close_button->setFocusPolicy (Qt::NoFocus); + m_close_button->setIconSize (QSize (m_icon_size, m_icon_size)); - QString css_button = QString ("QToolButton {background: transparent; border: 0px;}"); - m_dock_button->setStyleSheet (css_button); - m_close_button->setStyleSheet (css_button); + QString css_button = QString ("QToolButton {background: transparent; border: 0px;}"); + m_dock_button->setStyleSheet (css_button); + m_close_button->setStyleSheet (css_button); - QHBoxLayout *h_layout = new QHBoxLayout (); - h_layout->addStretch (100); - h_layout->addWidget (m_dock_button); - h_layout->addWidget (m_close_button); - h_layout->setSpacing (10); - h_layout->setContentsMargins (5, 2, 2, 2); + QHBoxLayout *h_layout = new QHBoxLayout (); + h_layout->addStretch (100); + h_layout->addWidget (m_dock_button); + h_layout->addWidget (m_close_button); + h_layout->setSpacing (10); + h_layout->setContentsMargins (5, 2, 2, 2); - m_title_widget->setLayout (h_layout); + m_title_widget->setLayout (h_layout); - if (p && (p->objectName () == gui_obj_name_main_window)) - { - // Only connect the when a parent (main window) is given - // copy & paste handling - connect (p, SIGNAL (copyClipboard_signal ()), - this, SLOT (copyClipboard ())); - connect (p, SIGNAL (pasteClipboard_signal ()), - this, SLOT (pasteClipboard ())); - connect (p, SIGNAL (selectAll_signal ()), - this, SLOT (selectAll ())); + if (p && (p->objectName () == gui_obj_name_main_window)) + { + // Only connect the when a parent (main window) is given + // copy & paste handling + connect (p, SIGNAL (copyClipboard_signal ()), + this, SLOT (copyClipboard ())); + connect (p, SIGNAL (pasteClipboard_signal ()), + this, SLOT (pasteClipboard ())); + connect (p, SIGNAL (selectAll_signal ()), + this, SLOT (selectAll ())); - // undo handling - connect (p, SIGNAL (undo_signal ()), this, SLOT (do_undo ())); - } -} + // undo handling + connect (p, SIGNAL (undo_signal ()), this, SLOT (do_undo ())); + } + } -// set the title in the dockwidgets title bar -void -label_dock_widget::set_title (const QString& title) -{ - QHBoxLayout *h_layout - = static_cast (m_title_widget->layout ()); - QLabel *label = new QLabel (title, m_title_widget); - label->setStyleSheet ("background-color: transparent;"); - h_layout->insertWidget (0, label); - setTitleBarWidget (m_title_widget); - setWindowTitle (title); -} + // set the title in the dockwidgets title bar + void + label_dock_widget::set_title (const QString& title) + { + QHBoxLayout *h_layout + = static_cast (m_title_widget->layout ()); + QLabel *label = new QLabel (title, m_title_widget); + label->setStyleSheet ("background-color: transparent;"); + h_layout->insertWidget (0, label); + setTitleBarWidget (m_title_widget); + setWindowTitle (title); + } -static QString -qdockwidget_css (const QString& close_icon, const QString& close_tooltip, - const QString& float_icon, const QString& float_tooltip, - int icon_size, const QString& titlebar_foreground, - const QString& titlebar_background) -{ - return QString ("QDockWidget\n" - "{\n" - "%6" - " border: none;\n" - " titlebar-close-icon: url(%1);\n" - " titlebar-normal-icon: url(%2);\n" - "}\n" - "\n" - "QDockWidget::close-button, QDockWidget::float-button\n" - "{\n" - " border: none;\n" - " icon-size: %3px;\n" - "}\n" - "\n" - "QAbstractButton#qt_dockwidget_closebutton\n" - "{\n" - " qproperty-toolTip: \"%4\";\n" - "}\n" - "\n" - "QAbstractButton#qt_dockwidget_floatbutton\n" - "{\n" - " qproperty-toolTip: \"%5\";\n" - "}\n" - "\n" - "QDockWidget::title {\n" - " text-align: left;\n" - "%7" - " padding-left: 1px;\n" - "}\n" - "\n" - "QDockWidget::close-button\n" - "{\n" - " right: %8px;\n" - " top: 3px;\n" - "}\n" - "\n" - "QDockWidget::float-button\n" - "{\n" - " right: %9px;\n" - " top: 3px;\n" - "}\n" - ).arg (close_icon).arg (float_icon).arg (icon_size) - .arg (close_tooltip).arg (float_tooltip) - .arg (titlebar_foreground).arg (titlebar_background) - .arg ((icon_size*2)/3).arg((icon_size*7)/3); -} + static QString + qdockwidget_css (const QString& close_icon, const QString& close_tooltip, + const QString& float_icon, const QString& float_tooltip, + int icon_size, const QString& titlebar_foreground, + const QString& titlebar_background) + { + return QString ("QDockWidget\n" + "{\n" + "%6" + " border: none;\n" + " titlebar-close-icon: url(%1);\n" + " titlebar-normal-icon: url(%2);\n" + "}\n" + "\n" + "QDockWidget::close-button, QDockWidget::float-button\n" + "{\n" + " border: none;\n" + " icon-size: %3px;\n" + "}\n" + "\n" + "QAbstractButton#qt_dockwidget_closebutton\n" + "{\n" + " qproperty-toolTip: \"%4\";\n" + "}\n" + "\n" + "QAbstractButton#qt_dockwidget_floatbutton\n" + "{\n" + " qproperty-toolTip: \"%5\";\n" + "}\n" + "\n" + "QDockWidget::title {\n" + " text-align: left;\n" + "%7" + " padding-left: 1px;\n" + "}\n" + "\n" + "QDockWidget::close-button\n" + "{\n" + " right: %8px;\n" + " top: 3px;\n" + "}\n" + "\n" + "QDockWidget::float-button\n" + "{\n" + " right: %9px;\n" + " top: 3px;\n" + "}\n" + ).arg (close_icon).arg (float_icon).arg (icon_size) + .arg (close_tooltip).arg (float_tooltip) + .arg (titlebar_foreground).arg (titlebar_background) + .arg ((icon_size*2)/3).arg((icon_size*7)/3); + } -octave_dock_widget::octave_dock_widget (const QString& obj_name, QWidget *p, - base_qobject& oct_qobj) - : label_dock_widget (p, oct_qobj), m_adopted (false), - m_custom_style (false), m_focus_follows_mouse (false), - m_recent_float_geom (), m_recent_dock_geom (), - m_waiting_for_mouse_button_release (false) -{ - setObjectName (obj_name); + octave_dock_widget::octave_dock_widget (const QString& obj_name, QWidget *p, + base_qobject& oct_qobj) + : label_dock_widget (p, oct_qobj), m_adopted (false), + m_custom_style (false), m_focus_follows_mouse (false), + m_recent_float_geom (), m_recent_dock_geom (), + m_waiting_for_mouse_button_release (false) + { + setObjectName (obj_name); - // FIXME: Can we avoid the cast here? - m_main_window = dynamic_cast (p); + // FIXME: Can we avoid the cast here? + m_main_window = dynamic_cast (p); - m_predecessor_widget = nullptr; + m_predecessor_widget = nullptr; - connect (this, &octave_dock_widget::topLevelChanged, - this, &octave_dock_widget::toplevel_change); - connect (this, &octave_dock_widget::visibilityChanged, - this, &octave_dock_widget::handle_visibility); + connect (this, &octave_dock_widget::topLevelChanged, + this, &octave_dock_widget::toplevel_change); + connect (this, &octave_dock_widget::visibilityChanged, + this, &octave_dock_widget::handle_visibility); - if (m_default_float_button != nullptr) - { - disconnect (m_default_float_button, 0, 0, 0); - connect (m_default_float_button, &QAbstractButton::clicked, - this, &octave_dock_widget::make_window); - } - connect (this, &octave_dock_widget::queue_make_window, - this, &octave_dock_widget::make_window, Qt::QueuedConnection); - connect (this, &octave_dock_widget::queue_make_widget, - this, [=] () { make_widget (); }, Qt::QueuedConnection); + if (m_default_float_button != nullptr) + { + disconnect (m_default_float_button, 0, 0, 0); + connect (m_default_float_button, &QAbstractButton::clicked, + this, &octave_dock_widget::make_window); + } + connect (this, &octave_dock_widget::queue_make_window, + this, &octave_dock_widget::make_window, Qt::QueuedConnection); + connect (this, &octave_dock_widget::queue_make_widget, + this, [=] () { make_widget (); }, Qt::QueuedConnection); - shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); - scmgr.set_shortcut (m_dock_action, sc_dock_widget_dock); - m_dock_action->setShortcutContext (Qt::WidgetWithChildrenShortcut); - addAction (m_dock_action); - connect (m_dock_action, &QAction::triggered, - this, &octave_dock_widget::make_window); + shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); + scmgr.set_shortcut (m_dock_action, sc_dock_widget_dock); + m_dock_action->setShortcutContext (Qt::WidgetWithChildrenShortcut); + addAction (m_dock_action); + connect (m_dock_action, &QAction::triggered, + this, &octave_dock_widget::make_window); - scmgr.set_shortcut (m_close_action, sc_dock_widget_close); - m_close_action->setShortcutContext (Qt::WidgetWithChildrenShortcut); - addAction (m_close_action); - connect (m_close_action, &QAction::triggered, - this, &octave_dock_widget::change_visibility); + scmgr.set_shortcut (m_close_action, sc_dock_widget_close); + m_close_action->setShortcutContext (Qt::WidgetWithChildrenShortcut); + addAction (m_close_action); + connect (m_close_action, &QAction::triggered, + this, &octave_dock_widget::change_visibility); - m_close_action->setToolTip (tr ("Hide widget")); + m_close_action->setToolTip (tr ("Hide widget")); - setStyleSheet (qdockwidget_css ( - global_icon_paths.at (ICON_THEME_OCTAVE) + "widget-close.png", - QString ("Close widget"), - global_icon_paths.at (ICON_THEME_OCTAVE) + "widget-undock.png", - QString ("Undock widget"), - m_icon_size, - QString (""), - QString (""))); + setStyleSheet (qdockwidget_css ( + global_icon_paths.at (ICON_THEME_OCTAVE) + "widget-close.png", + QString ("Close widget"), + global_icon_paths.at (ICON_THEME_OCTAVE) + "widget-undock.png", + QString ("Undock widget"), + m_icon_size, + QString (""), + QString (""))); - if (widget ()) - widget ()->setToolTip (QString ("")); + if (widget ()) + widget ()->setToolTip (QString ("")); - m_icon_color = ""; - m_title_3d = 50; + m_icon_color = ""; + m_title_3d = 50; - installEventFilter (this); + installEventFilter (this); - setFocusPolicy (Qt::StrongFocus); + setFocusPolicy (Qt::StrongFocus); - setFeatures (QDockWidget::DockWidgetClosable - | QDockWidget::DockWidgetMovable - | QDockWidget::DockWidgetFloatable); + setFeatures (QDockWidget::DockWidgetClosable + | QDockWidget::DockWidgetMovable + | QDockWidget::DockWidgetFloatable); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - handle_settings (rmgr.get_settings ()); -} + handle_settings (); + } -void -octave_dock_widget::init_window_menu_entry (void) -{ - emit active_changed (isVisible ()); // emit once for init of window menu -} + void + octave_dock_widget::init_window_menu_entry (void) + { + emit active_changed (isVisible ()); // emit once for init of window menu + } -// make the widget floating -void -octave_dock_widget::make_window (bool widget_was_dragged) -{ - bool vis = isVisible (); + // make the widget floating + void + octave_dock_widget::make_window (bool widget_was_dragged) + { + bool vis = isVisible (); - // prevent follow-up calls by clearing state variable - m_waiting_for_mouse_button_release = false; + // prevent follow-up calls by clearing state variable + m_waiting_for_mouse_button_release = false; - set_focus_predecessor (); // set focus previously active widget if tabbed + set_focus_predecessor (); // set focus previously active widget if tabbed - // Before unparenting, get current geometry for restoring if dragged - QRect geom = geometry (); + // Before unparenting, get current geometry for restoring if dragged + QRect geom = geometry (); - // the widget has to be reparented (parent = 0), preferably - // from a non-toplevel widget otherwise may not have full - // decorations, e.g., no taskbar icon and always in front - if (isFloating ()) - setFloating (false); + // the widget has to be reparented (parent = 0), preferably + // from a non-toplevel widget otherwise may not have full + // decorations, e.g., no taskbar icon and always in front + if (isFloating ()) + setFloating (false); - if (m_main_window) - { - // Before making it a separate (no more parent) floating widget, - // remove the dock widget from the main window. This ensures - // that tabbed widgets keep their focus when it is re-docked - // later - m_main_window->removeDockWidget (this); - } + if (m_main_window) + { + // Before making it a separate (no more parent) floating widget, + // remove the dock widget from the main window. This ensures + // that tabbed widgets keep their focus when it is re-docked + // later + m_main_window->removeDockWidget (this); + } - setParent (0, Qt::CustomizeWindowHint | Qt::WindowTitleHint | - Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::Window); + setParent (0, Qt::CustomizeWindowHint | Qt::WindowTitleHint | + Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::Window); - // restore the last geometry when floating only if we have not dragged - // the window outside the main window - if (! widget_was_dragged) - geom = m_recent_float_geom.isNull () ? QRect (50,100,480,480) - : m_recent_float_geom; - setGeometry (geom); + // restore the last geometry when floating only if we have not dragged + // the window outside the main window + if (! widget_was_dragged) + geom = m_recent_float_geom.isNull () ? QRect (50,100,480,480) + : m_recent_float_geom; + setGeometry (geom); - // adjust the (un)dock action - disconnect (m_dock_action, 0, this, 0); - connect (m_dock_action, &QAction::triggered, - this, &octave_dock_widget::make_widget); + // adjust the (un)dock action + disconnect (m_dock_action, 0, this, 0); + connect (m_dock_action, &QAction::triggered, + this, &octave_dock_widget::make_widget); + + // adjust the (un)dock icon + if (titleBarWidget ()) + { + gui_settings settings; - // adjust the (un)dock icon - if (titleBarWidget ()) - { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - m_dock_action->setIcon (rmgr.icon ("widget-dock" + m_icon_color, true)); - m_dock_action->setToolTip (tr ("Dock widget")); - } - else - { - disconnect (m_default_float_button, 0, this, 0); - connect (m_default_float_button, &QAbstractButton::clicked, - this, &octave_dock_widget::make_widget); - } + m_dock_action->setIcon (settings.icon ("widget-dock" + m_icon_color, true)); + m_dock_action->setToolTip (tr ("Dock widget")); + } + else + { + disconnect (m_default_float_button, 0, this, 0); + connect (m_default_float_button, &QAbstractButton::clicked, + this, &octave_dock_widget::make_widget); + } - raise (); - activateWindow (); + raise (); + activateWindow (); - if (vis) - { - show (); - setFocus (); - set_style (true); - } + if (vis) + { + show (); + setFocus (); + set_style (true); + } - emit topLevelChanged (true); // Be sure signal is emitted -} + emit topLevelChanged (true); // Be sure signal is emitted + } -// dock the widget -void -octave_dock_widget::make_widget (bool) -{ - bool vis = isVisible (); + // dock the widget + void + octave_dock_widget::make_widget (bool) + { + gui_settings settings; - // Since floating widget has no parent, we have to read it - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + bool vis = isVisible (); + + // Since floating widget has no parent, we have to read it - if (m_main_window) - { - settings->setValue (mw_state.key, m_main_window->saveState ()); + if (m_main_window) + { + settings.setValue (mw_state.key, m_main_window->saveState ()); - // Stay window, otherwise will bounce back to window by default - // because there is no layout information for this widget in the - // saved settings. - setParent (m_main_window, Qt::Window); - m_main_window->addDockWidget (Qt::BottomDockWidgetArea, this); - m_adopted = false; - // recover old window states, hide and re-show new added widget - m_main_window->restoreState (settings->value (mw_state.key).toByteArray ()); - setFloating (false); - // restore size using setGeometry instead of restoreGeometry - // following this post: - // https://forum.qt.io/topic/79326/qdockwidget-restoregeometry-not-working-correctly-when-qmainwindow-is-maximized/5 - setGeometry (m_recent_dock_geom); - } + // Stay window, otherwise will bounce back to window by default + // because there is no layout information for this widget in the + // saved settings. + setParent (m_main_window, Qt::Window); + m_main_window->addDockWidget (Qt::BottomDockWidgetArea, this); + m_adopted = false; + // recover old window states, hide and re-show new added widget + m_main_window->restoreState (settings.value (mw_state.key).toByteArray ()); + setFloating (false); + // restore size using setGeometry instead of restoreGeometry + // following this post: + // https://forum.qt.io/topic/79326/qdockwidget-restoregeometry-not-working-correctly-when-qmainwindow-is-maximized/5 + setGeometry (m_recent_dock_geom); + } - // adjust the (un)dock icon - disconnect (m_dock_action, 0, this, 0); - connect (m_dock_action, &QAction::triggered, - this, &octave_dock_widget::make_window); - if (titleBarWidget ()) - { - m_dock_action->setIcon (rmgr.icon ("widget-undock" + m_icon_color, true)); - m_dock_action->setToolTip (tr ("Undock widget")); - } - else - { - disconnect (m_default_float_button, 0, this, 0); - connect (m_default_float_button, &QAbstractButton::clicked, - this, &octave_dock_widget::make_window); - } + // adjust the (un)dock icon + disconnect (m_dock_action, 0, this, 0); + connect (m_dock_action, &QAction::triggered, + this, &octave_dock_widget::make_window); + if (titleBarWidget ()) + { + m_dock_action->setIcon (settings.icon ("widget-undock" + m_icon_color, true)); + m_dock_action->setToolTip (tr ("Undock widget")); + } + else + { + disconnect (m_default_float_button, 0, this, 0); + connect (m_default_float_button, &QAbstractButton::clicked, + this, &octave_dock_widget::make_window); + } - raise (); - QApplication::setActiveWindow (this); + raise (); + QApplication::setActiveWindow (this); - if (vis) - { - show (); - setFocus (); - set_style (true); - } -} + if (vis) + { + show (); + setFocus (); + set_style (true); + } + } -// dock the widget -void -octave_dock_widget::default_dock (bool) -{ - setFloating (false); -} + // dock the widget + void + octave_dock_widget::default_dock (bool) + { + setFloating (false); + } -// set the widget which previously had focus when tabified -void -octave_dock_widget::set_predecessor_widget (octave_dock_widget *prev_widget) -{ - m_predecessor_widget = prev_widget; -} + // set the widget which previously had focus when tabified + void + octave_dock_widget::set_predecessor_widget (octave_dock_widget *prev_widget) + { + m_predecessor_widget = prev_widget; + } -void -octave_dock_widget::set_main_window (main_window *mw) -{ - m_main_window = mw; + void + octave_dock_widget::set_main_window (main_window *mw) + { + m_main_window = mw; - if (m_main_window) - { - connect (m_main_window, &main_window::copyClipboard_signal, - this, &octave_dock_widget::copyClipboard); + if (m_main_window) + { + connect (m_main_window, &main_window::copyClipboard_signal, + this, &octave_dock_widget::copyClipboard); - connect (m_main_window, &main_window::pasteClipboard_signal, - this, &octave_dock_widget::pasteClipboard); + connect (m_main_window, &main_window::pasteClipboard_signal, + this, &octave_dock_widget::pasteClipboard); - connect (m_main_window, &main_window::selectAll_signal, - this, &octave_dock_widget::selectAll); + connect (m_main_window, &main_window::selectAll_signal, + this, &octave_dock_widget::selectAll); - connect (m_main_window, &main_window::undo_signal, - this, &octave_dock_widget::do_undo); - } -} + connect (m_main_window, &main_window::undo_signal, + this, &octave_dock_widget::do_undo); + } + } -// close event -void -octave_dock_widget::closeEvent (QCloseEvent *e) -{ - emit active_changed (false); - set_focus_predecessor (); - save_settings (); + // close event + void + octave_dock_widget::closeEvent (QCloseEvent *e) + { + emit active_changed (false); + set_focus_predecessor (); + save_settings (); - QDockWidget::closeEvent (e); -} + QDockWidget::closeEvent (e); + } -// get focus widget -QWidget * -octave_dock_widget::focusWidget (void) -{ - QWidget *w = QApplication::focusWidget (); - if (w && w->focusProxy ()) w = w->focusProxy (); - return w; -} + // get focus widget + QWidget * + octave_dock_widget::focusWidget (void) + { + QWidget *w = QApplication::focusWidget (); + if (w && w->focusProxy ()) w = w->focusProxy (); + return w; + } -bool -octave_dock_widget::event (QEvent *event) -{ - // low-level check of whether docked-widget became a window via - // double-click or via drag-and-drop - if ( (event->type () == QEvent::MouseButtonDblClick && ! isFloating ()) - || (event->type () == QEvent::ActivationChange - && m_waiting_for_mouse_button_release)) - { - bool retval = QDockWidget::event (event); - if (isFloating () && parent () != 0) - { - m_waiting_for_mouse_button_release = false; - emit queue_make_window (event->type () != QEvent::MouseButtonDblClick); - } - return retval; - } + bool + octave_dock_widget::event (QEvent *event) + { + // low-level check of whether docked-widget became a window via + // double-click or via drag-and-drop + if ( (event->type () == QEvent::MouseButtonDblClick && ! isFloating ()) + || (event->type () == QEvent::ActivationChange + && m_waiting_for_mouse_button_release)) + { + bool retval = QDockWidget::event (event); + if (isFloating () && parent () != 0) + { + m_waiting_for_mouse_button_release = false; + emit queue_make_window (event->type () != QEvent::MouseButtonDblClick); + } + return retval; + } - return QDockWidget::event (event); -} + return QDockWidget::event (event); + } -void -octave_dock_widget::handle_settings (const gui_settings *settings) -{ - if (! settings) - return; + void + octave_dock_widget::handle_settings (void) + { + gui_settings settings; - m_focus_follows_mouse = settings->value (dw_focus_follows_mouse).toBool (); + m_focus_follows_mouse = settings.value (dw_focus_follows_mouse).toBool (); - m_custom_style - = settings->value (dw_title_custom_style).toBool (); + m_custom_style + = settings.value (dw_title_custom_style).toBool (); - m_title_3d = settings->value (dw_title_3d.key, dw_title_3d.def).toInt (); + m_title_3d = settings.value (dw_title_3d.key, dw_title_3d.def).toInt (); - m_fg_color - = settings->value (dw_title_fg_color).value (); + m_fg_color + = settings.value (dw_title_fg_color).value (); - m_fg_color_active - = settings->value (dw_title_fg_color_active).value (); + m_fg_color_active + = settings.value (dw_title_fg_color_active).value (); - m_bg_color = settings->value (dw_title_bg_color).value (); + m_bg_color = settings.value (dw_title_bg_color).value (); - m_bg_color_active - = settings->value (dw_title_bg_color_active).value (); + m_bg_color_active + = settings.value (dw_title_bg_color_active).value (); - QColor bcol (m_bg_color); - QColor bcola (m_bg_color_active); + QColor bcol (m_bg_color); + QColor bcola (m_bg_color_active); - if (! m_custom_style) - { - bcol = QWidget::palette ().color (m_title_widget->backgroundRole ()); - bcola = bcol; - } + if (! m_custom_style) + { + bcol = QWidget::palette ().color (m_title_widget->backgroundRole ()); + bcola = bcol; + } - int r, g, b; - bcol.getRgb (&r, &g, &b); - if (r+g+b < 400) - m_icon_color = "-light"; - else - m_icon_color = ""; + int r, g, b; + bcol.getRgb (&r, &g, &b); + if (r+g+b < 400) + m_icon_color = "-light"; + else + m_icon_color = ""; - bcola.getRgb (&r, &g, &b); - if (r+g+b < 400) - m_icon_color_active = "-light"; - else - m_icon_color_active = ""; + bcola.getRgb (&r, &g, &b); + if (r+g+b < 400) + m_icon_color_active = "-light"; + else + m_icon_color_active = ""; - int x, y, w, h; - QGuiApplication::primaryScreen ()->availableGeometry ().getRect (&x, &y, &w, &h); - QRect default_floating_size = QRect (x+16, y+32, w/3, h/2); + int x, y, w, h; + QGuiApplication::primaryScreen ()->availableGeometry ().getRect (&x, &y, &w, &h); + QRect default_floating_size = QRect (x+16, y+32, w/3, h/2); - QRect default_dock_size; - if (m_main_window) - { - // We have a main window, dock size depends on size of main window - m_main_window->geometry ().getRect (&x, &y, &w, &h); - default_dock_size = QRect (x+16, y+32, w/3, h/3); - } - else - { - // No main window, default dock size should never be used - default_dock_size = QRect (0, 0, w/10, h/10); - } + QRect default_dock_size; + if (m_main_window) + { + // We have a main window, dock size depends on size of main window + m_main_window->geometry ().getRect (&x, &y, &w, &h); + default_dock_size = QRect (x+16, y+32, w/3, h/3); + } + else + { + // No main window, default dock size should never be used + default_dock_size = QRect (0, 0, w/10, h/10); + } - m_recent_float_geom - = settings->value (dw_float_geometry.key.arg (objectName ()), - default_floating_size).toRect (); + m_recent_float_geom + = settings.value (dw_float_geometry.key.arg (objectName ()), + default_floating_size).toRect (); - adjust_to_screen (m_recent_float_geom, default_floating_size); + adjust_to_screen (m_recent_float_geom, default_floating_size); - // The following is required for ensure smooth transition from old - // saveGeomety to new QRect setting (see comment for restoring size - // of docked widgets) - QVariant dock_geom - = settings->value (dw_dock_geometry.key.arg (objectName ()), - default_dock_size); - if (dock_geom.canConvert (QMetaType::QRect)) - m_recent_dock_geom = dock_geom.toRect (); - else - m_recent_dock_geom = dw_dock_geometry.def.toRect (); + // The following is required for ensure smooth transition from old + // saveGeomety to new QRect setting (see comment for restoring size + // of docked widgets) + QVariant dock_geom + = settings.value (dw_dock_geometry.key.arg (objectName ()), + default_dock_size); + if (dock_geom.canConvert (QMetaType::QRect)) + m_recent_dock_geom = dock_geom.toRect (); + else + m_recent_dock_geom = dw_dock_geometry.def.toRect (); - notice_settings (settings); // call individual handler + notice_settings (); // call individual handler - set_style (false); + set_style (false); - // Compacter design - QToolBar *toolbar = findChild (); - if (toolbar) - toolbar->setStyleSheet (toolbar->styleSheet () + global_toolbar_style); + // Compacter design + QToolBar *toolbar = findChild (); + if (toolbar) + toolbar->setStyleSheet (toolbar->styleSheet () + global_toolbar_style); - QMenuBar *menubar = findChild (); - if (menubar) - menubar->setStyleSheet (menubar->styleSheet () + global_menubar_style); + QMenuBar *menubar = findChild (); + if (menubar) + menubar->setStyleSheet (menubar->styleSheet () + global_menubar_style); -} + } -void -octave_dock_widget::handle_active_dock_changed (octave_dock_widget *w_old, - octave_dock_widget *w_new) -{ - if (m_custom_style && this == w_old) - { - set_style (false); - update (); - } + void + octave_dock_widget::handle_active_dock_changed (octave_dock_widget *w_old, + octave_dock_widget *w_new) + { + if (m_custom_style && this == w_old) + { + set_style (false); + update (); + } - if (m_custom_style && this == w_new) - { - set_style (true); - update (); - } -} + if (m_custom_style && this == w_new) + { + set_style (true); + update (); + } + } -void -octave_dock_widget::save_settings (void) -{ - // save state of this dock-widget - QString name = objectName (); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + void + octave_dock_widget::save_settings (void) + { + gui_settings settings; - if (! settings) - return; + // save state of this dock-widget + QString name = objectName (); - store_geometry (); + store_geometry (); - // conditional needed? - if (! m_recent_float_geom.isNull ()) - settings->setValue (dw_float_geometry.key.arg (name), m_recent_float_geom); + // conditional needed? + if (! m_recent_float_geom.isNull ()) + settings.setValue (dw_float_geometry.key.arg (name), m_recent_float_geom); - if (! m_recent_dock_geom.isEmpty ()) - settings->setValue (dw_dock_geometry.key.arg (name), m_recent_dock_geom); - settings->setValue (dw_is_visible.key.arg (name), isVisible ()); // store visibility - settings->setValue (dw_is_floating.key.arg (name), isFloating ()); // store floating - settings->setValue (dw_is_minimized.key.arg (name), isMinimized ()); // store minimized + if (! m_recent_dock_geom.isEmpty ()) + settings.setValue (dw_dock_geometry.key.arg (name), m_recent_dock_geom); + settings.setValue (dw_is_visible.key.arg (name), isVisible ()); // store visibility + settings.setValue (dw_is_floating.key.arg (name), isFloating ()); // store floating + settings.setValue (dw_is_minimized.key.arg (name), isMinimized ()); // store minimized - settings->sync (); -} + settings.sync (); + } -bool octave_dock_widget::eventFilter (QObject *obj, QEvent *e) -{ - // Ignore double clicks into window decoration elements - if (e->type () == QEvent::NonClientAreaMouseButtonDblClick) - { - e->ignore (); - return true; - } + bool octave_dock_widget::eventFilter (QObject *obj, QEvent *e) + { + // Ignore double clicks into window decoration elements + if (e->type () == QEvent::NonClientAreaMouseButtonDblClick) + { + e->ignore (); + return true; + } - // Detect mouse enter events if "focus follows mouse" is desired - // for widgets docked to the main window (non floating) and activate - // the widget currently under the mouse - if (m_focus_follows_mouse && ! isFloating () && (e->type () == QEvent::Enter)) - setFocus (); + // Detect mouse enter events if "focus follows mouse" is desired + // for widgets docked to the main window (non floating) and activate + // the widget currently under the mouse + if (m_focus_follows_mouse && ! isFloating () && (e->type () == QEvent::Enter)) + setFocus (); - return QDockWidget::eventFilter (obj, e); -} + return QDockWidget::eventFilter (obj, e); + } -void -octave_dock_widget::store_geometry (void) -{ - if (isFloating ()) - { - if (! parent ()) - m_recent_float_geom = geometry (); - } - else - { - m_recent_dock_geom = geometry (); - } -} + void + octave_dock_widget::store_geometry (void) + { + if (isFloating ()) + { + if (! parent ()) + m_recent_float_geom = geometry (); + } + else + { + m_recent_dock_geom = geometry (); + } + } -void -octave_dock_widget::moveEvent (QMoveEvent *event) -{ - store_geometry (); + void + octave_dock_widget::moveEvent (QMoveEvent *event) + { + store_geometry (); - QDockWidget::moveEvent (event); -} + QDockWidget::moveEvent (event); + } -void -octave_dock_widget::resizeEvent (QResizeEvent *event) -{ - store_geometry (); + void + octave_dock_widget::resizeEvent (QResizeEvent *event) + { + store_geometry (); - QDockWidget::resizeEvent (event); -} + QDockWidget::resizeEvent (event); + } -// slot for hiding the widget -void -octave_dock_widget::change_visibility (bool) -{ - setVisible (false); - emit active_changed (false); -} + // slot for hiding the widget + void + octave_dock_widget::change_visibility (bool) + { + setVisible (false); + emit active_changed (false); + } -void octave_dock_widget::activate (void) -{ - if (! isVisible ()) - setVisible (true); + void octave_dock_widget::activate (void) + { + if (! isVisible ()) + setVisible (true); - setFocus (); - activateWindow (); - raise (); -} + setFocus (); + activateWindow (); + raise (); + } -void octave_dock_widget::handle_visibility (bool visible) -{ - if (visible) - { - emit active_changed (true); - if (! isFloating ()) - setFocus (); - } -} + void octave_dock_widget::handle_visibility (bool visible) + { + if (visible) + { + emit active_changed (true); + if (! isFloating ()) + setFocus (); + } + } -void -octave_dock_widget::toplevel_change (bool toplevel) -{ - QObject *dockobj; - const char *docksig; + void + octave_dock_widget::toplevel_change (bool toplevel) + { + QObject *dockobj; + const char *docksig; - if (titleBarWidget ()) - { - dockobj = m_dock_action; - docksig = SIGNAL (triggered (bool)); - } - else - { - dockobj = m_default_float_button; - docksig = SIGNAL (clicked (bool)); - } + if (titleBarWidget ()) + { + dockobj = m_dock_action; + docksig = SIGNAL (triggered (bool)); + } + else + { + dockobj = m_default_float_button; + docksig = SIGNAL (clicked (bool)); + } - if (toplevel) - { - // This is a fallback in case the attempt to create a floated - // top-level window fails and the QDockWidget remains a child - // of the QMainWindow. - connect (dockobj, docksig, this, SLOT (default_dock (bool))); + if (toplevel) + { + // This is a fallback in case the attempt to create a floated + // top-level window fails and the QDockWidget remains a child + // of the QMainWindow. + connect (dockobj, docksig, this, SLOT (default_dock (bool))); - // Could be dragging window, so must wait until there is a - // change in focus. - if (parent () != 0) - m_waiting_for_mouse_button_release = true; - } - else - { - // If a drag-and-drop within the QMainWindow occurred, want to remain a widget. - m_waiting_for_mouse_button_release = false; + // Could be dragging window, so must wait until there is a + // change in focus. + if (parent () != 0) + m_waiting_for_mouse_button_release = true; + } + else + { + // If a drag-and-drop within the QMainWindow occurred, want to remain a widget. + m_waiting_for_mouse_button_release = false; - // Making into a widget immediately will mangle the double-click - // status and cause problems on followup button clicks. - if (parent () == 0) - emit queue_make_widget (); - } -} + // Making into a widget immediately will mangle the double-click + // status and cause problems on followup button clicks. + if (parent () == 0) + emit queue_make_widget (); + } + } -void -octave_dock_widget::set_style (bool active) -{ - QString css_foreground; - QString css_background; - QString css_button; - QString dock_icon; + void + octave_dock_widget::set_style (bool active) + { + QString css_foreground; + QString css_background; + QString css_button; + QString dock_icon; - QString icon_col = m_icon_color; + QString icon_col = m_icon_color; - QString close_tooltip = "Close widget"; - QString dock_tooltip; + QString close_tooltip = "Close widget"; + QString dock_tooltip; - if (isFloating ()) - { - dock_icon = "widget-dock"; - dock_tooltip = "Dock widget"; - } - else - { - dock_icon = "widget-undock"; - dock_tooltip = "Undock widget"; - } + if (isFloating ()) + { + dock_icon = "widget-dock"; + dock_tooltip = "Dock widget"; + } + else + { + dock_icon = "widget-undock"; + dock_tooltip = "Undock widget"; + } #if defined (Q_OS_MAC) - QString alignment = "center"; + QString alignment = "center"; #else - QString alignment = "center left"; + QString alignment = "center left"; #endif - if (m_custom_style) - { - - QColor bg_col, fg_col; + if (m_custom_style) + { - if (active) - { - bg_col = m_bg_color_active; - fg_col = m_fg_color_active; - icon_col = m_icon_color_active; - } - else - { - bg_col = m_bg_color; - fg_col = m_fg_color; - icon_col = m_icon_color; - } + QColor bg_col, fg_col; - QColor bg_col_top, bg_col_bottom; - if (m_title_3d > 0) - { - bg_col_top = bg_col.lighter (100 + m_title_3d); - bg_col_bottom = bg_col.darker (100 + m_title_3d); - } - else - { - bg_col_top = bg_col.darker (100 - m_title_3d); - bg_col_bottom = bg_col.lighter (100 - m_title_3d); - } + if (active) + { + bg_col = m_bg_color_active; + fg_col = m_fg_color_active; + icon_col = m_icon_color_active; + } + else + { + bg_col = m_bg_color; + fg_col = m_fg_color; + icon_col = m_icon_color; + } - css_foreground = QString (" color: %1;\n").arg (fg_col.name ()); + QColor bg_col_top, bg_col_bottom; + if (m_title_3d > 0) + { + bg_col_top = bg_col.lighter (100 + m_title_3d); + bg_col_bottom = bg_col.darker (100 + m_title_3d); + } + else + { + bg_col_top = bg_col.darker (100 - m_title_3d); + bg_col_bottom = bg_col.lighter (100 - m_title_3d); + } - css_background = - QString (" background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," - " stop: 0 %1, stop: 0.60 %2, stop: 0.95 %2 stop: 1.0 %3);\n"). - arg (bg_col_top.name ()). - arg (bg_col.name ()). - arg (bg_col_bottom.name ()); - } - else - { - css_foreground = QString (""); - css_background = QString (""); - } + css_foreground = QString (" color: %1;\n").arg (fg_col.name ()); - QString full_dock_icon = dock_icon + icon_col; - QString full_close_icon = "widget-close" + icon_col; - if (titleBarWidget ()) - { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - titleBarWidget ()->setStyleSheet (css_foreground + css_background); - css_button = QString ("QToolButton {background: transparent; border: 0px;}"); - m_dock_button->setStyleSheet (css_button); - m_close_button->setStyleSheet (css_button); - m_dock_action->setIcon (rmgr.icon (full_dock_icon, true)); - m_close_action->setIcon (rmgr.icon (full_close_icon, true)); - } - else - { - setStyleSheet (qdockwidget_css (global_icon_paths.at (ICON_THEME_OCTAVE) + full_close_icon + ".png", - close_tooltip, - global_icon_paths.at (ICON_THEME_OCTAVE) + full_dock_icon + ".png", - dock_tooltip, - m_icon_size, - css_foreground, - css_background)); - } -} + css_background = + QString (" background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," + " stop: 0 %1, stop: 0.60 %2, stop: 0.95 %2 stop: 1.0 %3);\n"). + arg (bg_col_top.name ()). + arg (bg_col.name ()). + arg (bg_col_bottom.name ()); + } + else + { + css_foreground = QString (""); + css_background = QString (""); + } + + QString full_dock_icon = dock_icon + icon_col; + QString full_close_icon = "widget-close" + icon_col; + if (titleBarWidget ()) + { + gui_settings settings; -// set focus to previously active widget in tabbed widget stack -void -octave_dock_widget::set_focus_predecessor (void) -{ - // only != 0 if widget was tabbed - if (m_predecessor_widget && m_predecessor_widget->isVisible ()) - m_predecessor_widget->setFocus (); - - m_predecessor_widget = nullptr; + titleBarWidget ()->setStyleSheet (css_foreground + css_background); + css_button = QString ("QToolButton {background: transparent; border: 0px;}"); + m_dock_button->setStyleSheet (css_button); + m_close_button->setStyleSheet (css_button); + m_dock_action->setIcon (settings.icon (full_dock_icon, true)); + m_close_action->setIcon (settings.icon (full_close_icon, true)); + } + else + { + setStyleSheet (qdockwidget_css (global_icon_paths.at (ICON_THEME_OCTAVE) + full_close_icon + ".png", + close_tooltip, + global_icon_paths.at (ICON_THEME_OCTAVE) + full_dock_icon + ".png", + dock_tooltip, + m_icon_size, + css_foreground, + css_background)); + } + } - // FIXME: Until cset bda0c5b38bda, the wrong keys "Dockwidget/..." were used - // here. This had no effect in Qt4, but does in Qt5. In the following, the - // four incorrect keys are updated if still present in the settings files. - // The keys are also used in the settings dialog, but - // octave_dock_widget::handle_settings is already called at program start. - // These tests can be removed in a future version of Octave (version 6). - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + // set focus to previously active widget in tabbed widget stack + void + octave_dock_widget::set_focus_predecessor (void) + { + // only != 0 if widget was tabbed + if (m_predecessor_widget && m_predecessor_widget->isVisible ()) + m_predecessor_widget->setFocus (); - rmgr.update_settings_key ("Dockwidgets/title_bg_color", - dw_title_bg_color.key); - - rmgr.update_settings_key ("Dockwidgets/title_bg_color_active", - dw_title_bg_color_active.key); - - rmgr.update_settings_key ("Dockwidgets/title_fg_color", - dw_title_fg_color.key); - - rmgr.update_settings_key ("Dockwidgets/title_fg_color_active", - dw_title_fg_color_active.key); -} + m_predecessor_widget = nullptr; + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/octave-dock-widget.h --- a/libgui/src/octave-dock-widget.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/octave-dock-widget.h Tue Dec 06 15:45:27 2022 -0500 @@ -31,158 +31,157 @@ #include #include -#include "gui-settings.h" #include "qt-interpreter-events.h" OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; -class main_window; + class base_qobject; + class main_window; -// The few decoration items common to both main window and variable editor. + // The few decoration items common to both main window and variable editor. -class label_dock_widget : public QDockWidget -{ - Q_OBJECT + class label_dock_widget : public QDockWidget + { + Q_OBJECT -public: + public: - label_dock_widget (QWidget *p, base_qobject& oct_qobj); + label_dock_widget (QWidget *p, base_qobject& oct_qobj); - ~label_dock_widget (void) = default; + ~label_dock_widget (void) = default; - // set_title() uses the custom title bar while setWindowTitle() uses - // the default title bar (with style sheets) - void set_title (const QString&); + // set_title() uses the custom title bar while setWindowTitle() uses + // the default title bar (with style sheets) + void set_title (const QString&); -protected slots: + protected slots: - //! Slots to handle copy & paste. - //!@{ - virtual void copyClipboard (void) { } - virtual void pasteClipboard (void) { } - virtual void selectAll (void) { } - //!@} + //! Slots to handle copy & paste. + //!@{ + virtual void copyClipboard (void) { } + virtual void pasteClipboard (void) { } + virtual void selectAll (void) { } + //!@} - //! Slot to handle undo. + //! Slot to handle undo. - virtual void do_undo (void) { } + virtual void do_undo (void) { } -protected: + protected: - base_qobject& m_octave_qobj; + base_qobject& m_octave_qobj; - int m_icon_size; - QWidget *m_title_widget; - QToolButton *m_dock_button; - QToolButton *m_close_button; - QAction *m_dock_action; - QAction *m_close_action; + int m_icon_size; + QWidget *m_title_widget; + QToolButton *m_dock_button; + QToolButton *m_close_button; + QAction *m_dock_action; + QAction *m_close_action; - QAbstractButton *m_default_float_button; - QAbstractButton *m_default_close_button; -}; + QAbstractButton *m_default_float_button; + QAbstractButton *m_default_close_button; + }; -class octave_dock_widget : public label_dock_widget -{ - Q_OBJECT + class octave_dock_widget : public label_dock_widget + { + Q_OBJECT -public: + public: - octave_dock_widget (const QString& obj_name, QWidget *p, - base_qobject& oct_qobj); + octave_dock_widget (const QString& obj_name, QWidget *p, + base_qobject& oct_qobj); - ~octave_dock_widget (void) = default; + ~octave_dock_widget (void) = default; - void set_predecessor_widget (octave_dock_widget *prev_widget); + void set_predecessor_widget (octave_dock_widget *prev_widget); - void set_main_window (main_window *mw); + void set_main_window (main_window *mw); - void set_adopted (bool adopted = true) { m_adopted = adopted; } - bool adopted (void) const { return m_adopted; } + void set_adopted (bool adopted = true) { m_adopted = adopted; } + bool adopted (void) const { return m_adopted; } -signals: + signals: - //! Custom signal that tells whether a user has clicked away that dock - //! widget, i.e. the active dock widget has changed. + //! Custom signal that tells whether a user has clicked away that dock + //! widget, i.e. the active dock widget has changed. - void active_changed (bool active); + void active_changed (bool active); - void queue_make_window (bool widget_was_dragged); + void queue_make_window (bool widget_was_dragged); - void queue_make_widget (void); + void queue_make_widget (void); -protected: + protected: - virtual void closeEvent (QCloseEvent *e); + virtual void closeEvent (QCloseEvent *e); - QWidget * focusWidget (void); + QWidget * focusWidget (void); - bool event (QEvent *event); + bool event (QEvent *event); -public slots: + public slots: - virtual void activate (void); + virtual void activate (void); - virtual void handle_visibility (bool visible); + virtual void handle_visibility (bool visible); - virtual void notice_settings (const gui_settings *) { } + virtual void notice_settings (void) { } - virtual void save_settings (void); + virtual void save_settings (void); - void init_window_menu_entry (void); + void init_window_menu_entry (void); - void handle_settings (const gui_settings *); + void handle_settings (void); - void handle_active_dock_changed (octave_dock_widget *, octave_dock_widget *); + void handle_active_dock_changed (octave_dock_widget *, octave_dock_widget *); - void moveEvent (QMoveEvent *event); + void moveEvent (QMoveEvent *event); - void resizeEvent (QResizeEvent *event); + void resizeEvent (QResizeEvent *event); - void make_window (bool widget_was_dragged = false); + void make_window (bool widget_was_dragged = false); - void make_widget (bool not_used = false); + void make_widget (bool not_used = false); - void default_dock (bool not_used = false); + void default_dock (bool not_used = false); -protected slots: + protected slots: - virtual void toplevel_change (bool); + virtual void toplevel_change (bool); - //! Event filter for double clicks into the window decoration elements. + //! Event filter for double clicks into the window decoration elements. - bool eventFilter (QObject *obj, QEvent *e); + bool eventFilter (QObject *obj, QEvent *e); -private slots: + private slots: - void change_visibility (bool); + void change_visibility (bool); -private: + private: - void set_style (bool active); - void set_focus_predecessor (void); - void store_geometry (void); + void set_style (bool active); + void set_focus_predecessor (void); + void store_geometry (void); - //! Stores the parent, since we are reparenting to 0. + //! Stores the parent, since we are reparenting to 0. - main_window *m_main_window; + main_window *m_main_window; - bool m_adopted; - bool m_custom_style; - bool m_focus_follows_mouse; - int m_title_3d; - QColor m_bg_color; - QColor m_bg_color_active; - QColor m_fg_color; - QColor m_fg_color_active; - QString m_icon_color; - QString m_icon_color_active; - octave_dock_widget *m_predecessor_widget; - QRect m_recent_float_geom; - QRect m_recent_dock_geom; - bool m_waiting_for_mouse_button_release; -}; + bool m_adopted; + bool m_custom_style; + bool m_focus_follows_mouse; + int m_title_3d; + QColor m_bg_color; + QColor m_bg_color_active; + QColor m_fg_color; + QColor m_fg_color_active; + QString m_icon_color; + QString m_icon_color_active; + octave_dock_widget *m_predecessor_widget; + QRect m_recent_float_geom; + QRect m_recent_dock_geom; + bool m_waiting_for_mouse_button_release; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/octave-qobject.cc --- a/libgui/src/octave-qobject.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/octave-qobject.cc Tue Dec 06 15:45:27 2022 -0500 @@ -46,6 +46,7 @@ #include "community-news.h" #include "documentation-dock-widget.h" #include "files-dock-widget.h" +#include "gui-settings.h" #include "history-dock-widget.h" #include "interpreter-qobject.h" #include "main-window.h" @@ -131,911 +132,909 @@ OCTAVE_BEGIN_NAMESPACE(octave) -// Disable all Qt messages by default. + // Disable all Qt messages by default. -static void -message_handler (QtMsgType, const QMessageLogContext&, const QString&) -{ } + static void + message_handler (QtMsgType, const QMessageLogContext&, const QString&) + { } -//! Reimplement QApplication::notify. Octave's own exceptions are -//! caught and rethrown in the interpreter thread. + //! Reimplement QApplication::notify. Octave's own exceptions are + //! caught and rethrown in the interpreter thread. -bool octave_qapplication::notify (QObject *receiver, QEvent *ev) -{ - try - { - return QApplication::notify (receiver, ev); - } - catch (execution_exception& ee) - { - emit interpreter_event - ([=] (void) - { - // INTERPRETER THREAD - throw ee; - }); - } + bool octave_qapplication::notify (QObject *receiver, QEvent *ev) + { + try + { + return QApplication::notify (receiver, ev); + } + catch (execution_exception& ee) + { + emit interpreter_event + ([=] (void) + { + // INTERPRETER THREAD + throw ee; + }); + } - return false; -} + return false; + } -// We will create a QApplication object, even if START_GUI is false, -// so that we can use Qt widgets for plot windows when running in -// command-line mode. Note that we are creating an -// octave_qapplication object but handling it as a QApplication object -// because the octave_qapplication should behave identically to a -// QApplication object except that it overrides the notify method so -// we can handle forward Octave interpreter exceptions from the GUI -// thread to the interpreter thread. + // We will create a QApplication object, even if START_GUI is false, + // so that we can use Qt widgets for plot windows when running in + // command-line mode. Note that we are creating an + // octave_qapplication object but handling it as a QApplication object + // because the octave_qapplication should behave identically to a + // QApplication object except that it overrides the notify method so + // we can handle forward Octave interpreter exceptions from the GUI + // thread to the interpreter thread. -base_qobject::base_qobject (qt_application& app_context, bool gui_app) - : QObject (), - m_app_context (app_context), - m_argc (m_app_context.sys_argc ()), - m_argv (m_app_context.sys_argv ()), - m_qapplication (new octave_qapplication (m_argc, m_argv)), - m_resource_manager (), - m_shortcut_manager (*this), - m_qt_tr (new QTranslator ()), - m_gui_tr (new QTranslator ()), - m_qsci_tr (new QTranslator ()), - m_translators_installed (false), - m_qt_interpreter_events (new qt_interpreter_events (*this)), - m_interpreter_qobj (new interpreter_qobject (*this)), - m_main_thread (new QThread ()), - m_gui_app (gui_app), - m_interpreter_ready (false), - m_workspace_model (new workspace_model ()), - m_documentation_widget (), - m_file_browser_widget (), - m_history_widget (), - m_workspace_widget (), - m_editor_widget (), - m_variable_editor_widget (), - m_main_window (nullptr) -{ - std::string show_gui_msgs = - sys::env::getenv ("OCTAVE_SHOW_GUI_MESSAGES"); + base_qobject::base_qobject (qt_application& app_context, bool gui_app) + : QObject (), + m_app_context (app_context), + m_argc (m_app_context.sys_argc ()), + m_argv (m_app_context.sys_argv ()), + m_qapplication (new octave_qapplication (m_argc, m_argv)), + m_resource_manager (), + m_shortcut_manager (), + m_qt_tr (new QTranslator ()), + m_gui_tr (new QTranslator ()), + m_qsci_tr (new QTranslator ()), + m_translators_installed (false), + m_qt_interpreter_events (new qt_interpreter_events (*this)), + m_interpreter_qobj (new interpreter_qobject (*this)), + m_main_thread (new QThread ()), + m_gui_app (gui_app), + m_interpreter_ready (false), + m_workspace_model (new workspace_model ()), + m_documentation_widget (), + m_file_browser_widget (), + m_history_widget (), + m_workspace_widget (), + m_editor_widget (), + m_variable_editor_widget (), + m_main_window (nullptr) + { + std::string show_gui_msgs = + sys::env::getenv ("OCTAVE_SHOW_GUI_MESSAGES"); - // Installing our handler suppresses the messages. + // Installing our handler suppresses the messages. - if (show_gui_msgs.empty ()) - qInstallMessageHandler (message_handler); + if (show_gui_msgs.empty ()) + qInstallMessageHandler (message_handler); - // Set the codec for all strings (before wizard or any GUI object) + // Set the codec for all strings (before wizard or any GUI object) #if ! defined (Q_OS_WIN32) - QTextCodec::setCodecForLocale (QTextCodec::codecForName ("UTF-8")); + QTextCodec::setCodecForLocale (QTextCodec::codecForName ("UTF-8")); #endif - // Initialize global Qt application metadata. + // Register octave_value_list for connecting thread crossing signals. - QCoreApplication::setApplicationName ("GNU Octave"); - QCoreApplication::setApplicationVersion (OCTAVE_VERSION); - - // Register octave_value_list for connecting thread crossing signals. + qRegisterMetaType ("octave_value_list"); - qRegisterMetaType ("octave_value_list"); - - // Bug #55940 (Disable App Nap on Mac) +// Bug #55940 (Disable App Nap on Mac) #if defined (Q_OS_MAC) - // Mac App Nap feature causes pause() and sleep() to misbehave. - // Disable it for the entire program run. - disable_app_nap (); + // Mac App Nap feature causes pause() and sleep() to misbehave. + // Disable it for the entire program run. + disable_app_nap (); #endif - // Force left-to-right alignment (see bug #46204) - m_qapplication->setLayoutDirection (Qt::LeftToRight); + // Force left-to-right alignment (see bug #46204) + m_qapplication->setLayoutDirection (Qt::LeftToRight); - // Qt docs recommend using Qt::QueuedConnection when connecting to - // the QCoreApplication::exit slot. - connect (m_interpreter_qobj, &interpreter_qobject::shutdown_finished, - m_qapplication, &octave_qapplication::exit, - Qt::QueuedConnection); + // Qt docs recommend using Qt::QueuedConnection when connecting to + // the QCoreApplication::exit slot. + connect (m_interpreter_qobj, &interpreter_qobject::shutdown_finished, + m_qapplication, &octave_qapplication::exit, + Qt::QueuedConnection); - connect (m_interpreter_qobj, &interpreter_qobject::ready, - this, &base_qobject::interpreter_ready); + connect (m_interpreter_qobj, &interpreter_qobject::ready, + this, &base_qobject::interpreter_ready); - connect (m_main_thread, &QThread::finished, - m_main_thread, &QThread::deleteLater); + connect (m_main_thread, &QThread::finished, + m_main_thread, &QThread::deleteLater); - // Handle any interpreter_event signal from the octave_qapplication - // object here. + // Handle any interpreter_event signal from the octave_qapplication + // object here. - connect (m_qapplication, QOverload::of (&octave_qapplication::interpreter_event), - this, QOverload::of (&base_qobject::interpreter_event)); + connect (m_qapplication, QOverload::of (&octave_qapplication::interpreter_event), + this, QOverload::of (&base_qobject::interpreter_event)); - connect (m_qapplication, QOverload::of (&octave_qapplication::interpreter_event), - this, QOverload::of (&base_qobject::interpreter_event)); + connect (m_qapplication, QOverload::of (&octave_qapplication::interpreter_event), + this, QOverload::of (&base_qobject::interpreter_event)); - if (m_app_context.experimental_terminal_widget ()) - { - connect (qt_link (), &qt_interpreter_events::start_gui_signal, - this, &base_qobject::start_gui); + if (m_app_context.experimental_terminal_widget ()) + { + connect (qt_link (), &qt_interpreter_events::start_gui_signal, + this, &base_qobject::start_gui); - connect (qt_link (), &qt_interpreter_events::show_terminal_window_signal, - this, &base_qobject::show_terminal_window); - } + connect (qt_link (), &qt_interpreter_events::show_terminal_window_signal, + this, &base_qobject::show_terminal_window); + } - connect (qt_link (), &qt_interpreter_events::copy_image_to_clipboard_signal, - this, &base_qobject::copy_image_to_clipboard); + connect (qt_link (), &qt_interpreter_events::copy_image_to_clipboard_signal, + this, &base_qobject::copy_image_to_clipboard); - connect (qt_link (), &qt_interpreter_events::show_documentation_signal, - this, &base_qobject::show_documentation_window); + connect (qt_link (), &qt_interpreter_events::show_documentation_signal, + this, &base_qobject::show_documentation_window); - connect (qt_link (), &qt_interpreter_events::show_file_browser_signal, - this, &base_qobject::show_file_browser_window); + connect (qt_link (), &qt_interpreter_events::show_file_browser_signal, + this, &base_qobject::show_file_browser_window); - connect (qt_link (), &qt_interpreter_events::show_command_history_signal, - this, &base_qobject::show_command_history_window); + connect (qt_link (), &qt_interpreter_events::show_command_history_signal, + this, &base_qobject::show_command_history_window); - connect (qt_link (), &qt_interpreter_events::show_workspace_signal, - this, &base_qobject::show_workspace_window); + connect (qt_link (), &qt_interpreter_events::show_workspace_signal, + this, &base_qobject::show_workspace_window); - connect (qt_link (), &qt_interpreter_events::edit_variable_signal, - this, &base_qobject::show_variable_editor_window); + connect (qt_link (), &qt_interpreter_events::edit_variable_signal, + this, &base_qobject::show_variable_editor_window); - connect (qt_link (), &qt_interpreter_events::show_community_news_signal, - this, &base_qobject::show_community_news); + connect (qt_link (), &qt_interpreter_events::show_community_news_signal, + this, &base_qobject::show_community_news); - connect (qt_link (), &qt_interpreter_events::show_release_notes_signal, - this, &base_qobject::show_release_notes); + connect (qt_link (), &qt_interpreter_events::show_release_notes_signal, + this, &base_qobject::show_release_notes); - if (m_app_context.experimental_terminal_widget ()) - { - m_qapplication->setQuitOnLastWindowClosed (false); - } - else - { - if (gui_app) - { - m_main_window = new main_window (*this); + if (m_app_context.experimental_terminal_widget ()) + { + m_qapplication->setQuitOnLastWindowClosed (false); + } + else + { + if (gui_app) + { + m_main_window = new main_window (*this); - connect (m_main_window, &main_window::show_community_news_signal, - this, &base_qobject::show_community_news); + connect (m_main_window, &main_window::show_community_news_signal, + this, &base_qobject::show_community_news); - connect (m_main_window, &main_window::show_release_notes_signal, - this, &base_qobject::show_release_notes); + connect (m_main_window, &main_window::show_release_notes_signal, + this, &base_qobject::show_release_notes); - if (m_interpreter_ready) - m_main_window->handle_octave_ready (); - else - connect (m_interpreter_qobj, &interpreter_qobject::ready, - m_main_window, &main_window::handle_octave_ready); + if (m_interpreter_ready) + m_main_window->handle_octave_ready (); + else + connect (m_interpreter_qobj, &interpreter_qobject::ready, + m_main_window, &main_window::handle_octave_ready); - connect (qt_link (), &qt_interpreter_events::focus_window_signal, - m_main_window, &main_window::focus_window); + connect (qt_link (), &qt_interpreter_events::focus_window_signal, + m_main_window, &main_window::focus_window); - m_app_context.gui_running (true); - } - else - { - // Get settings file. - m_resource_manager.reload_settings (); + m_app_context.gui_running (true); + } + else + { + // Get settings file. + gui_settings settings; - // After settings. - config_translators (); - m_resource_manager.config_icon_theme (); + settings.reload (); + + // After settings. + config_translators (); - // Initilize the shortcut-manager - m_shortcut_manager.init_data (); + settings.config_icon_theme (); - m_qapplication->setQuitOnLastWindowClosed (false); - } - } + // Initilize the shortcut-manager + m_shortcut_manager.init_data (); - start_main_thread (); -} + m_qapplication->setQuitOnLastWindowClosed (false); + } + } -base_qobject::~base_qobject (void) -{ - // Note that we don't delete m_main_thread here. That is handled by - // deleteLater slot that is called when the m_main_thread issues a - // finished signal. + start_main_thread (); + } - // FIXME: Why are dock widget settings and/or the main window - // configuration not saved correctly if the main window is deleted - // after the dock widgets? + base_qobject::~base_qobject (void) + { + // Note that we don't delete m_main_thread here. That is handled by + // deleteLater slot that is called when the m_main_thread issues a + // finished signal. - // Calling close will cause settings to be saved. - // If m_main_window exists, the widgets are closed by the main window + // FIXME: Why are dock widget settings and/or the main window + // configuration not saved correctly if the main window is deleted + // after the dock widgets? - if (! m_main_window) - { - if (m_terminal_widget) - m_terminal_widget->close (); + // Calling close will cause settings to be saved. + // If m_main_window exists, the widgets are closed by the main window + + if (! m_main_window) + { + if (m_terminal_widget) + m_terminal_widget->close (); - if (m_documentation_widget) - m_documentation_widget->close (); + if (m_documentation_widget) + m_documentation_widget->close (); - if (m_file_browser_widget) - m_file_browser_widget->close (); + if (m_file_browser_widget) + m_file_browser_widget->close (); - if (m_history_widget) - m_history_widget->close (); + if (m_history_widget) + m_history_widget->close (); - if (m_workspace_widget) - m_workspace_widget->close (); + if (m_workspace_widget) + m_workspace_widget->close (); - if (m_editor_widget) - m_editor_widget->close (); + if (m_editor_widget) + m_editor_widget->close (); - if (m_variable_editor_widget) - m_variable_editor_widget->close (); + if (m_variable_editor_widget) + m_variable_editor_widget->close (); - if (m_community_news) - m_community_news->close (); - } - else - { - delete m_main_window; - } + if (m_community_news) + m_community_news->close (); + } + else + { + delete m_main_window; + } - delete m_terminal_widget; - delete m_documentation_widget; - delete m_file_browser_widget; - delete m_history_widget; - delete m_workspace_widget; - delete m_editor_widget; - delete m_variable_editor_widget; - delete m_community_news; + delete m_terminal_widget; + delete m_documentation_widget; + delete m_file_browser_widget; + delete m_history_widget; + delete m_workspace_widget; + delete m_editor_widget; + delete m_variable_editor_widget; + delete m_community_news; - delete m_interpreter_qobj; - delete m_qsci_tr; - delete m_gui_tr; - delete m_qt_tr; - delete m_qapplication; - delete m_workspace_model; + delete m_interpreter_qobj; + delete m_qsci_tr; + delete m_gui_tr; + delete m_qt_tr; + delete m_qapplication; + delete m_workspace_model; - string_vector::delete_c_str_vec (m_argv); -} + string_vector::delete_c_str_vec (m_argv); + } -void base_qobject::config_translators (void) -{ - if (m_translators_installed) - return; + void base_qobject::config_translators (void) + { + if (m_translators_installed) + return; - m_resource_manager.config_translators (m_qt_tr, m_qsci_tr, m_gui_tr); + m_resource_manager.config_translators (m_qt_tr, m_qsci_tr, m_gui_tr); - m_qapplication->installTranslator (m_qt_tr); - m_qapplication->installTranslator (m_gui_tr); - m_qapplication->installTranslator (m_qsci_tr); + m_qapplication->installTranslator (m_qt_tr); + m_qapplication->installTranslator (m_gui_tr); + m_qapplication->installTranslator (m_qsci_tr); - m_translators_installed = true; -} + m_translators_installed = true; + } -void base_qobject::start_main_thread (void) -{ - // Note: if using the new experimental terminal widget, we defer - // initializing and executing the interpreter until the main event - // loop begins executing. + void base_qobject::start_main_thread (void) + { + // Note: if using the new experimental terminal widget, we defer + // initializing and executing the interpreter until the main event + // loop begins executing. - // With the old terminal widget, we defer initializing and executing - // the interpreter until after the main window and QApplication are - // running to prevent race conditions. + // With the old terminal widget, we defer initializing and executing + // the interpreter until after the main window and QApplication are + // running to prevent race conditions. - QTimer::singleShot (0, m_interpreter_qobj, SLOT (execute (void))); + QTimer::singleShot (0, m_interpreter_qobj, SLOT (execute (void))); - m_interpreter_qobj->moveToThread (m_main_thread); + m_interpreter_qobj->moveToThread (m_main_thread); - m_main_thread->start (); -} + m_main_thread->start (); + } -int base_qobject::exec (void) -{ - int status = m_qapplication->exec (); + int base_qobject::exec (void) + { + int status = m_qapplication->exec (); #if defined (Q_OS_MAC) - // fprintf to stderr is needed by macOS, for poorly-understood reasons. - fprintf (stderr, "\n"); + // fprintf to stderr is needed by macOS, for poorly-understood reasons. + fprintf (stderr, "\n"); #endif - m_main_thread->quit (); - m_main_thread->wait (); + m_main_thread->quit (); + m_main_thread->wait (); - return status; -} + return status; + } -// Provided for convenience. Will be removed once we eliminate the -// old terminal widget. -bool base_qobject::experimental_terminal_widget (void) const -{ - return m_app_context.experimental_terminal_widget (); -} + // Provided for convenience. Will be removed once we eliminate the + // old terminal widget. + bool base_qobject::experimental_terminal_widget (void) const + { + return m_app_context.experimental_terminal_widget (); + } -bool base_qobject::gui_running (void) const -{ - return m_app_context.gui_running (); -} + bool base_qobject::gui_running (void) const + { + return m_app_context.gui_running (); + } -QPointer -base_qobject::terminal_widget (main_window *mw) -{ - if (m_terminal_widget && mw) - { - m_terminal_widget->set_main_window (mw); - m_terminal_widget->set_adopted (true); - } - else if (! m_terminal_widget) - { - m_terminal_widget - = QPointer (new terminal_dock_widget (mw, *this)); - if (experimental_terminal_widget ()) - { + QPointer + base_qobject::terminal_widget (main_window *mw) + { + if (m_terminal_widget && mw) + { + m_terminal_widget->set_main_window (mw); + m_terminal_widget->set_adopted (true); + } + else if (! m_terminal_widget) + { + m_terminal_widget + = QPointer (new terminal_dock_widget (mw, *this)); + if (experimental_terminal_widget ()) + { #if defined (HAVE_QSCINTILLA) - command_widget *cmd_widget - = m_terminal_widget->get_command_widget (); + command_widget *cmd_widget + = m_terminal_widget->get_command_widget (); - connect (cmd_widget, &command_widget::interpreter_pause, - this, &base_qobject::interpreter_pause); + connect (cmd_widget, &command_widget::interpreter_pause, + this, &base_qobject::interpreter_pause); - connect (cmd_widget, &command_widget::interpreter_resume, - this, &base_qobject::interpreter_resume); + connect (cmd_widget, &command_widget::interpreter_resume, + this, &base_qobject::interpreter_resume); - connect (cmd_widget, &command_widget::interpreter_stop, - this, &base_qobject::interpreter_stop); + connect (cmd_widget, &command_widget::interpreter_stop, + this, &base_qobject::interpreter_stop); - connect (qt_link (), &qt_interpreter_events::interpreter_output_signal, - m_terminal_widget, &terminal_dock_widget::interpreter_output_signal); + connect (qt_link (), &qt_interpreter_events::interpreter_output_signal, + m_terminal_widget, &terminal_dock_widget::interpreter_output_signal); - connect (qt_link (), &qt_interpreter_events::update_prompt_signal, - m_terminal_widget, &terminal_dock_widget::update_prompt_signal); + connect (qt_link (), &qt_interpreter_events::update_prompt_signal, + m_terminal_widget, &terminal_dock_widget::update_prompt_signal); - connect (qt_link (), &qt_interpreter_events::new_command_line_signal, - m_terminal_widget, &terminal_dock_widget::new_command_line_signal); + connect (qt_link (), &qt_interpreter_events::new_command_line_signal, + m_terminal_widget, &terminal_dock_widget::new_command_line_signal); - connect_interpreter_events (cmd_widget); + connect_interpreter_events (cmd_widget); #endif - } - else - { - QTerminal *cmd_widget = m_terminal_widget->get_qterminal (); + } + else + { + QTerminal *cmd_widget = m_terminal_widget->get_qterminal (); - // Connect the interrupt signal (emitted by Ctrl-C) - connect (cmd_widget, &QTerminal::interrupt_signal, - this, &base_qobject::interpreter_interrupt); - } - } + // Connect the interrupt signal (emitted by Ctrl-C) + connect (cmd_widget, &QTerminal::interrupt_signal, + this, &base_qobject::interpreter_interrupt); + } + } - return m_terminal_widget; -} + return m_terminal_widget; + } -QPointer -base_qobject::documentation_widget (main_window *mw) -{ - if (m_documentation_widget && mw) - { - m_documentation_widget->set_main_window (mw); - m_documentation_widget->set_adopted (true); - } - else if (! m_documentation_widget) - { - m_documentation_widget - = QPointer (new documentation_dock_widget (mw, *this)); + QPointer + base_qobject::documentation_widget (main_window *mw) + { + if (m_documentation_widget && mw) + { + m_documentation_widget->set_main_window (mw); + m_documentation_widget->set_adopted (true); + } + else if (! m_documentation_widget) + { + m_documentation_widget + = QPointer (new documentation_dock_widget (mw, *this)); - connect (qt_link (), - &qt_interpreter_events::register_documentation_signal, - m_documentation_widget, - &documentation_dock_widget::registerDoc); + connect (qt_link (), + &qt_interpreter_events::register_documentation_signal, + m_documentation_widget, + &documentation_dock_widget::registerDoc); - connect (qt_link (), - &qt_interpreter_events::unregister_documentation_signal, - m_documentation_widget, - &documentation_dock_widget::unregisterDoc); - } + connect (qt_link (), + &qt_interpreter_events::unregister_documentation_signal, + m_documentation_widget, + &documentation_dock_widget::unregisterDoc); + } - return m_documentation_widget; -} + return m_documentation_widget; + } -QPointer -base_qobject::file_browser_widget (main_window *mw) -{ - if (m_file_browser_widget) - { - m_file_browser_widget->set_main_window (mw); - m_file_browser_widget->set_adopted (true); - } - else if (! m_file_browser_widget) - m_file_browser_widget - = QPointer (new files_dock_widget (mw, *this)); + QPointer + base_qobject::file_browser_widget (main_window *mw) + { + if (m_file_browser_widget) + { + m_file_browser_widget->set_main_window (mw); + m_file_browser_widget->set_adopted (true); + } + else if (! m_file_browser_widget) + m_file_browser_widget + = QPointer (new files_dock_widget (mw, *this)); - connect (qt_link (), &qt_interpreter_events::directory_changed_signal, - m_file_browser_widget, &files_dock_widget::update_octave_directory); + connect (qt_link (), &qt_interpreter_events::directory_changed_signal, + m_file_browser_widget, &files_dock_widget::update_octave_directory); - return m_file_browser_widget; -} + return m_file_browser_widget; + } -QPointer -base_qobject::history_widget (main_window *mw) -{ - if (m_history_widget) - { - m_history_widget->set_main_window (mw); - m_history_widget->set_adopted (true); - } - else if (! m_history_widget) - { - m_history_widget - = QPointer (new history_dock_widget (mw, *this)); + QPointer + base_qobject::history_widget (main_window *mw) + { + if (m_history_widget) + { + m_history_widget->set_main_window (mw); + m_history_widget->set_adopted (true); + } + else if (! m_history_widget) + { + m_history_widget + = QPointer (new history_dock_widget (mw, *this)); - connect (qt_link (), &qt_interpreter_events::set_history_signal, - m_history_widget, &history_dock_widget::set_history); + connect (qt_link (), &qt_interpreter_events::set_history_signal, + m_history_widget, &history_dock_widget::set_history); - connect (qt_link (), &qt_interpreter_events::append_history_signal, - m_history_widget, &history_dock_widget::append_history); + connect (qt_link (), &qt_interpreter_events::append_history_signal, + m_history_widget, &history_dock_widget::append_history); - connect (qt_link (), &qt_interpreter_events::clear_history_signal, - m_history_widget, &history_dock_widget::clear_history); + connect (qt_link (), &qt_interpreter_events::clear_history_signal, + m_history_widget, &history_dock_widget::clear_history); - emit interpreter_event - ([=] (interpreter& interp) { - // INTERPRETER THREAD + emit interpreter_event + ([=] (interpreter& interp) { + // INTERPRETER THREAD - event_manager& xevmgr = interp.get_event_manager (); + event_manager& xevmgr = interp.get_event_manager (); - xevmgr.set_history (); - }); - } + xevmgr.set_history (); + }); + } - return m_history_widget; -} + return m_history_widget; + } -QPointer -base_qobject::workspace_widget (main_window *mw) -{ - if (m_workspace_widget) - { - m_workspace_widget->set_main_window (mw); - m_workspace_widget->set_adopted (true); - } - else if (! m_workspace_widget) - { - m_workspace_widget - = QPointer (new workspace_view (mw, *this)); + QPointer + base_qobject::workspace_widget (main_window *mw) + { + if (m_workspace_widget) + { + m_workspace_widget->set_main_window (mw); + m_workspace_widget->set_adopted (true); + } + else if (! m_workspace_widget) + { + m_workspace_widget + = QPointer (new workspace_view (mw, *this)); - m_workspace_widget->setModel (m_workspace_model); + m_workspace_widget->setModel (m_workspace_model); - connect (m_workspace_model, &workspace_model::model_changed, - m_workspace_widget, &workspace_view::handle_model_changed); + connect (m_workspace_model, &workspace_model::model_changed, + m_workspace_widget, &workspace_view::handle_model_changed); - connect (qt_link (), &qt_interpreter_events::set_workspace_signal, - m_workspace_model, &workspace_model::set_workspace); + connect (qt_link (), &qt_interpreter_events::set_workspace_signal, + m_workspace_model, &workspace_model::set_workspace); - connect (qt_link (), &qt_interpreter_events::clear_workspace_signal, - m_workspace_model, &workspace_model::clear_workspace); + connect (qt_link (), &qt_interpreter_events::clear_workspace_signal, + m_workspace_model, &workspace_model::clear_workspace); - connect (m_workspace_widget, - &workspace_view::copy_variable_value_to_clipboard, - [=] (const QString& var_name) { - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD + connect (m_workspace_widget, + &workspace_view::copy_variable_value_to_clipboard, + [=] (const QString& var_name) { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD - octave_value val = interp.varval (var_name.toStdString ()); + octave_value val = interp.varval (var_name.toStdString ()); - if (val.is_undefined ()) - val = 0; + if (val.is_undefined ()) + val = 0; - std::ostringstream buf; - val.print_raw (buf, true); + std::ostringstream buf; + val.print_raw (buf, true); - // FIXME: is the following operation thread safe or should - // it be done with a signal/slot connection? + // FIXME: is the following operation thread safe or should + // it be done with a signal/slot connection? - QClipboard *clipboard = QApplication::clipboard (); - clipboard->setText (QString::fromStdString (buf.str ())); - }); - }); + QClipboard *clipboard = QApplication::clipboard (); + clipboard->setText (QString::fromStdString (buf.str ())); + }); + }); - connect (m_workspace_widget, &workspace_view::rename_variable_signal, - [=] (const QString& old_name, const QString& new_name) { - emit interpreter_event - ([=] (interpreter& interp) { - // INTERPRETER THREAD + connect (m_workspace_widget, &workspace_view::rename_variable_signal, + [=] (const QString& old_name, const QString& new_name) { + emit interpreter_event + ([=] (interpreter& interp) { + // INTERPRETER THREAD - symbol_scope scope = interp.get_current_scope (); + symbol_scope scope = interp.get_current_scope (); - if (scope) - { - scope.rename (old_name.toStdString (), - new_name.toStdString ()); + if (scope) + { + scope.rename (old_name.toStdString (), + new_name.toStdString ()); - tree_evaluator& tw = interp.get_evaluator (); + tree_evaluator& tw = interp.get_evaluator (); - event_manager& xevmgr = interp.get_event_manager (); + event_manager& xevmgr = interp.get_event_manager (); - xevmgr.set_workspace (true, tw.get_symbol_info ()); - } + xevmgr.set_workspace (true, tw.get_symbol_info ()); + } - // FIXME: if this action fails, do we need a way to - // display that info in the GUI? - }); - }); + // FIXME: if this action fails, do we need a way to + // display that info in the GUI? + }); + }); - connect (m_workspace_widget, &workspace_view::edit_variable_signal, - [=] (const QString& var_name) { - emit interpreter_event - ([=] (interpreter& interp) { - // INTERPRETER THREAD + connect (m_workspace_widget, &workspace_view::edit_variable_signal, + [=] (const QString& var_name) { + emit interpreter_event + ([=] (interpreter& interp) { + // INTERPRETER THREAD - std::string name = var_name.toStdString (); - octave_value val = interp.varval (name); + std::string name = var_name.toStdString (); + octave_value val = interp.varval (name); - event_manager& xevmgr = interp.get_event_manager (); + event_manager& xevmgr = interp.get_event_manager (); - xevmgr.edit_variable (name, val); - }); - }); + xevmgr.edit_variable (name, val); + }); + }); - emit interpreter_event - ([=] (interpreter& interp) { - // INTERPRETER THREAD + emit interpreter_event + ([=] (interpreter& interp) { + // INTERPRETER THREAD - event_manager& xevmgr = interp.get_event_manager (); + event_manager& xevmgr = interp.get_event_manager (); - xevmgr.set_workspace (); - }); - } + xevmgr.set_workspace (); + }); + } - return m_workspace_widget; -} + return m_workspace_widget; + } -QPointer -base_qobject::editor_widget (main_window */*mw*/) -{ + QPointer + base_qobject::editor_widget (main_window */*mw*/) + { #if 0 - if (m_editor_widget && mw) - { - m_editor_widget->set_main_window (mw); - m_editor_widget->set_adopted (true); - } - else if (! m_editor_widget) - m_editor_widget = new file_editor (mw, *this); + if (m_editor_widget && mw) + { + m_editor_widget->set_main_window (mw); + m_editor_widget->set_adopted (true); + } + else if (! m_editor_widget) + m_editor_widget = new file_editor (mw, *this); #endif - return m_editor_widget; -} + return m_editor_widget; + } -QPointer -base_qobject::variable_editor_widget (main_window *mw) -{ - if (m_variable_editor_widget && mw) - { - m_variable_editor_widget->set_main_window (mw); - m_variable_editor_widget->set_adopted (true); - } - else if (! m_variable_editor_widget) - { - m_variable_editor_widget - = QPointer (new variable_editor (mw, *this)); + QPointer + base_qobject::variable_editor_widget (main_window *mw) + { + if (m_variable_editor_widget && mw) + { + m_variable_editor_widget->set_main_window (mw); + m_variable_editor_widget->set_adopted (true); + } + else if (! m_variable_editor_widget) + { + m_variable_editor_widget + = QPointer (new variable_editor (mw, *this)); - connect (m_variable_editor_widget, &variable_editor::updated, - this, &base_qobject::handle_variable_editor_update); + connect (m_variable_editor_widget, &variable_editor::updated, + this, &base_qobject::handle_variable_editor_update); - connect (m_variable_editor_widget, &variable_editor::command_signal, - this, &base_qobject::execute_command); + connect (m_variable_editor_widget, &variable_editor::command_signal, + this, &base_qobject::execute_command); - connect (qt_link (), - &qt_interpreter_events::refresh_variable_editor_signal, - m_variable_editor_widget, &variable_editor::refresh); + connect (qt_link (), + &qt_interpreter_events::refresh_variable_editor_signal, + m_variable_editor_widget, &variable_editor::refresh); - connect_interpreter_events (m_variable_editor_widget); - } + connect_interpreter_events (m_variable_editor_widget); + } - return m_variable_editor_widget; -} + return m_variable_editor_widget; + } -QPointer base_qobject::community_news_widget (int serial) -{ - if (! m_community_news) - m_community_news - = QPointer (new community_news (*this, serial)); + QPointer base_qobject::community_news_widget (int serial) + { + if (! m_community_news) + m_community_news + = QPointer (new community_news (serial)); - return m_community_news; -} + return m_community_news; + } -QPointer base_qobject::release_notes_widget (void) -{ - if (! m_release_notes) - m_release_notes = QPointer (new release_notes (*this)); + QPointer base_qobject::release_notes_widget (void) + { + if (! m_release_notes) + m_release_notes = QPointer (new release_notes ()); - return m_release_notes; -} + return m_release_notes; + } -bool base_qobject::confirm_shutdown (void) -{ - // Currently, we forward to main_window::confirm_shutdown instead of - // just displaying a dialog box here because the main_window also - // knows about and is responsible for notifying the editor. + bool base_qobject::confirm_shutdown (void) + { + // Currently, we forward to main_window::confirm_shutdown instead of + // just displaying a dialog box here because the main_window also + // knows about and is responsible for notifying the editor. - return m_main_window ? m_main_window->confirm_shutdown () : true; -} + return m_main_window ? m_main_window->confirm_shutdown () : true; + } -void base_qobject::start_gui (bool gui_app) -{ - if (m_app_context.experimental_terminal_widget ()) - { - if (m_main_window) - return; + void base_qobject::start_gui (bool gui_app) + { + if (m_app_context.experimental_terminal_widget ()) + { + if (m_main_window) + return; - m_gui_app = gui_app; + m_gui_app = gui_app; - m_main_window = new main_window (*this); + m_main_window = new main_window (*this); - connect (qt_link (), &qt_interpreter_events::focus_window_signal, - m_main_window, &main_window::focus_window); + connect (qt_link (), &qt_interpreter_events::focus_window_signal, + m_main_window, &main_window::focus_window); - connect (qt_link (), &qt_interpreter_events::close_gui_signal, - this, &base_qobject::close_gui); + connect (qt_link (), &qt_interpreter_events::close_gui_signal, + this, &base_qobject::close_gui); - connect (m_main_window, &main_window::close_gui_signal, - this, &base_qobject::close_gui); + connect (m_main_window, &main_window::close_gui_signal, + this, &base_qobject::close_gui); - connect (m_main_window, &main_window::show_community_news_signal, - this, &base_qobject::show_community_news); + connect (m_main_window, &main_window::show_community_news_signal, + this, &base_qobject::show_community_news); - connect (m_main_window, &main_window::show_release_notes_signal, - this, &base_qobject::show_release_notes); + connect (m_main_window, &main_window::show_release_notes_signal, + this, &base_qobject::show_release_notes); - if (m_interpreter_ready) - m_main_window->handle_octave_ready (); - else - connect (m_interpreter_qobj, &interpreter_qobject::ready, - m_main_window, &main_window::handle_octave_ready); + if (m_interpreter_ready) + m_main_window->handle_octave_ready (); + else + connect (m_interpreter_qobj, &interpreter_qobject::ready, + m_main_window, &main_window::handle_octave_ready); - if (m_gui_app) - m_qapplication->setQuitOnLastWindowClosed (true); - else - { - // FIXME: Save current values of PS1 and PS2 so they can be - // restored when we return to the command line? - } + if (m_gui_app) + m_qapplication->setQuitOnLastWindowClosed (true); + else + { + // FIXME: Save current values of PS1 and PS2 so they can be + // restored when we return to the command line? + } - m_app_context.gui_running (true); - } -} + m_app_context.gui_running (true); + } + } -void base_qobject::show_terminal_window (void) -{ - terminal_dock_widget *widget - = (m_terminal_widget - ? m_terminal_widget : terminal_widget ()); + void base_qobject::show_terminal_window (void) + { + terminal_dock_widget *widget + = (m_terminal_widget + ? m_terminal_widget : terminal_widget ()); - if (! widget->isVisible ()) - { - widget->show (); - widget->raise (); - } -} + if (! widget->isVisible ()) + { + widget->show (); + widget->raise (); + } + } -void base_qobject::show_documentation_window (const QString& file) -{ - documentation_dock_widget *widget - = (m_documentation_widget - ? m_documentation_widget : documentation_widget ()); + void base_qobject::show_documentation_window (const QString& file) + { + documentation_dock_widget *widget + = (m_documentation_widget + ? m_documentation_widget : documentation_widget ()); - widget->showDoc (file); + widget->showDoc (file); - if (! widget->isVisible ()) - { - widget->show (); - widget->raise (); - } -} + if (! widget->isVisible ()) + { + widget->show (); + widget->raise (); + } + } -void base_qobject::show_file_browser_window (void) -{ - files_dock_widget *widget - = m_file_browser_widget ? m_file_browser_widget : file_browser_widget (); + void base_qobject::show_file_browser_window (void) + { + files_dock_widget *widget + = m_file_browser_widget ? m_file_browser_widget : file_browser_widget (); - if (! widget->isVisible ()) - { - widget->show (); - widget->raise (); - } -} + if (! widget->isVisible ()) + { + widget->show (); + widget->raise (); + } + } -void base_qobject::show_command_history_window (void) -{ - history_dock_widget *widget - = m_history_widget ? m_history_widget : history_widget (); + void base_qobject::show_command_history_window (void) + { + history_dock_widget *widget + = m_history_widget ? m_history_widget : history_widget (); - if (! widget->isVisible ()) - { - widget->show (); - widget->raise (); - } -} + if (! widget->isVisible ()) + { + widget->show (); + widget->raise (); + } + } -void base_qobject::show_workspace_window (void) -{ - workspace_view *widget - = m_workspace_widget ? m_workspace_widget : workspace_widget (); + void base_qobject::show_workspace_window (void) + { + workspace_view *widget + = m_workspace_widget ? m_workspace_widget : workspace_widget (); - if (! widget->isVisible ()) - { - widget->show (); - widget->raise (); - } -} + if (! widget->isVisible ()) + { + widget->show (); + widget->raise (); + } + } -void base_qobject::show_variable_editor_window (const QString& name, - const octave_value& value) -{ - variable_editor *widget - = (m_variable_editor_widget - ? m_variable_editor_widget : variable_editor_widget ()); + void base_qobject::show_variable_editor_window (const QString& name, + const octave_value& value) + { + variable_editor *widget + = (m_variable_editor_widget + ? m_variable_editor_widget : variable_editor_widget ()); - if (! widget->isVisible ()) - { - widget->show (); - widget->raise (); - } + if (! widget->isVisible ()) + { + widget->show (); + widget->raise (); + } - // FIXME: Should this be done with a signal/slot connection? - widget->edit_variable (name, value); -} + // FIXME: Should this be done with a signal/slot connection? + widget->edit_variable (name, value); + } -void base_qobject::handle_variable_editor_update (void) -{ - // Called when the variable editor emits the updated signal. The size - // of a variable may have changed, so we refresh the workspace in the - // interpreter. That will eventually cause the workspace view in the - // GUI to be updated. + void base_qobject::handle_variable_editor_update (void) + { + // Called when the variable editor emits the updated signal. The size + // of a variable may have changed, so we refresh the workspace in the + // interpreter. That will eventually cause the workspace view in the + // GUI to be updated. - interpreter_event - ([] (interpreter& interp) - { - // INTERPRETER THREAD + interpreter_event + ([] (interpreter& interp) + { + // INTERPRETER THREAD - tree_evaluator& tw = interp.get_evaluator (); + tree_evaluator& tw = interp.get_evaluator (); - event_manager& xevmgr = interp.get_event_manager (); + event_manager& xevmgr = interp.get_event_manager (); - xevmgr.set_workspace (true, tw.get_symbol_info (), false); - }); -} + xevmgr.set_workspace (true, tw.get_symbol_info (), false); + }); + } -void base_qobject::show_community_news (int serial) -{ - // Ensure widget exists. - community_news_widget (serial); + void base_qobject::show_community_news (int serial) + { + // Ensure widget exists. + community_news_widget (serial); - m_community_news->display (); -} + m_community_news->display (); + } -void base_qobject::show_release_notes (void) -{ - // Ensure widget exists. - release_notes_widget (); + void base_qobject::show_release_notes (void) + { + // Ensure widget exists. + release_notes_widget (); - m_release_notes->display (); -} + m_release_notes->display (); + } -void base_qobject::execute_command (const QString& command) -{ - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD + void base_qobject::execute_command (const QString& command) + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD - // FIXME: Do we need to do anything special about errors here? - // Currently the eval function will just call error() in the - // interpreter event loop and throw an execution error. It will - // be caught, so shouldn't crash the interpreter, but the - // message may not go anywhere useful depending on how the GUI - // is being used or if Octave running server mode. + // FIXME: Do we need to do anything special about errors here? + // Currently the eval function will just call error() in the + // interpreter event loop and throw an execution error. It will + // be caught, so shouldn't crash the interpreter, but the + // message may not go anywhere useful depending on how the GUI + // is being used or if Octave running server mode. - interp.eval (command.toStdString (), 0); - }); -} + interp.eval (command.toStdString (), 0); + }); + } -void base_qobject::close_gui (void) -{ - if (m_app_context.experimental_terminal_widget ()) - { - if (! m_main_window) - return; + void base_qobject::close_gui (void) + { + if (m_app_context.experimental_terminal_widget ()) + { + if (! m_main_window) + return; - // FIXME: Restore previous values of PS1 and PS2 if we are - // returning to the command line? + // FIXME: Restore previous values of PS1 and PS2 if we are + // returning to the command line? - interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD + interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD - application *app = interp.get_app_context (); + application *app = interp.get_app_context (); - cmdline_options opts = app->options (); + cmdline_options opts = app->options (); - if (opts.gui ()) - interp.quit (0, false, false); - }); + if (opts.gui ()) + interp.quit (0, false, false); + }); - m_app_context.gui_running (false); + m_app_context.gui_running (false); - if (m_main_window) - { - m_main_window->deleteLater (); + if (m_main_window) + { + m_main_window->deleteLater (); - m_main_window = nullptr; - } - } -} + m_main_window = nullptr; + } + } + } -void base_qobject::interpreter_ready (void) -{ - m_interpreter_ready = true; -} + void base_qobject::interpreter_ready (void) + { + m_interpreter_ready = true; + } -void base_qobject::interpreter_event (const fcn_callback& fcn) -{ - // The following is a direct function call across threads. It works - // because it is accessing a thread-safe queue of events that - // are later executed by the Octave interpreter in the other thread. + void base_qobject::interpreter_event (const fcn_callback& fcn) + { + // The following is a direct function call across threads. It works + // because it is accessing a thread-safe queue of events that + // are later executed by the Octave interpreter in the other thread. - // See also the comments in interpreter-qobject.h about - // interpreter_qobject slots. + // See also the comments in interpreter-qobject.h about + // interpreter_qobject slots. - m_interpreter_qobj->interpreter_event (fcn); -} + m_interpreter_qobj->interpreter_event (fcn); + } -void base_qobject::interpreter_event (const meth_callback& meth) -{ - // The following is a direct function call across threads. It works - // because it is accessing a thread-safe queue of events that - // are later executed by the Octave interpreter in the other thread. + void base_qobject::interpreter_event (const meth_callback& meth) + { + // The following is a direct function call across threads. It works + // because it is accessing a thread-safe queue of events that + // are later executed by the Octave interpreter in the other thread. - // See also the comments in interpreter-qobject.h about - // interpreter_qobject slots. + // See also the comments in interpreter-qobject.h about + // interpreter_qobject slots. - m_interpreter_qobj->interpreter_event (meth); -} + m_interpreter_qobj->interpreter_event (meth); + } -void base_qobject::interpreter_interrupt (void) -{ - m_interpreter_qobj->interrupt (); -} + void base_qobject::interpreter_interrupt (void) + { + m_interpreter_qobj->interrupt (); + } -// FIXME: Should we try to make the pause, stop, and resume actions -// work for both the old and new terminal widget? + // FIXME: Should we try to make the pause, stop, and resume actions + // work for both the old and new terminal widget? -void base_qobject::interpreter_pause (void) -{ - if (m_app_context.experimental_terminal_widget ()) - m_interpreter_qobj->pause (); -} + void base_qobject::interpreter_pause (void) + { + if (m_app_context.experimental_terminal_widget ()) + m_interpreter_qobj->pause (); + } -void base_qobject::interpreter_stop (void) -{ - if (m_app_context.experimental_terminal_widget ()) - m_interpreter_qobj->stop (); -} + void base_qobject::interpreter_stop (void) + { + if (m_app_context.experimental_terminal_widget ()) + m_interpreter_qobj->stop (); + } -void base_qobject::interpreter_resume (void) -{ - if (m_app_context.experimental_terminal_widget ()) - m_interpreter_qobj->resume (); -} + void base_qobject::interpreter_resume (void) + { + if (m_app_context.experimental_terminal_widget ()) + m_interpreter_qobj->resume (); + } -void base_qobject::copy_image_to_clipboard (const QString& file, - bool remove_file) -{ - QClipboard *clipboard = QApplication::clipboard (); + void base_qobject::copy_image_to_clipboard (const QString& file, + bool remove_file) + { + QClipboard *clipboard = QApplication::clipboard (); - QImage img (file); + QImage img (file); - if (img.isNull ()) - { - // Report error? - return; - } + if (img.isNull ()) + { + // Report error? + return; + } - clipboard->setImage (img); + clipboard->setImage (img); - if (remove_file) - QFile::remove (file); -} + if (remove_file) + QFile::remove (file); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/qt-application.cc --- a/libgui/src/qt-application.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/qt-application.cc Tue Dec 06 15:45:27 2022 -0500 @@ -27,6 +27,10 @@ # include "config.h" #endif +#include +#include +#include + #include "main-window.h" #include "octave-qobject.h" #include "qt-application.h" @@ -42,35 +46,60 @@ OCTAVE_BEGIN_NAMESPACE(octave) -qt_application::qt_application (int argc, char **argv) -: application (argc, argv) -{ - // This should probably happen early. - sysdep_init (); -} + qt_application::qt_application (const std::string& organization_name, + const std::string& application_name, + const std::string& application_version, + int argc, char **argv) + : application (argc, argv) + { + if (! organization_name.empty ()) + QCoreApplication::setOrganizationName + (QString::fromStdString (organization_name)); -bool qt_application::start_gui_p (void) const -{ - // Note: this function is not needed if using the experimental - // terminal widget, so return a dummy value of false in that case. + if (! application_name.empty ()) + QCoreApplication::setApplicationName + (QString::fromStdString (application_name)); - return experimental_terminal_widget () ? false : m_options.gui (); -} + if (! application_version.empty ()) + QCoreApplication::setApplicationVersion + (QString::fromStdString (application_version)); + + // FIXME: Is there a better place for this? + QSettings::setDefaultFormat (QSettings::IniFormat); + + // This should probably happen early. + sysdep_init (); + } -int qt_application::execute (void) -{ - octave_block_interrupt_signal (); + qt_application::qt_application (int argc, char **argv) + : application (argc, argv) + { + // This should probably happen early. + sysdep_init (); + } - set_application_id (); + bool qt_application::start_gui_p (void) const + { + // Note: this function is not needed if using the experimental + // terminal widget, so return a dummy value of false in that case. - // Create and show main window. + return experimental_terminal_widget () ? false : m_options.gui (); + } - // Note: the second argument is ignored if using the new terminal - // widget. + int qt_application::execute (void) + { + octave_block_interrupt_signal (); + + set_application_id (); + + // Create and show main window. - base_qobject qt_interface (*this, start_gui_p ()); + // Note: the second argument is ignored if using the new terminal + // widget. - return qt_interface.exec (); -} + base_qobject qt_interface (*this, start_gui_p ()); + + return qt_interface.exec (); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/qt-application.h --- a/libgui/src/qt-application.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/qt-application.h Tue Dec 06 15:45:27 2022 -0500 @@ -26,48 +26,55 @@ #if ! defined (octave_qt_application_h) #define octave_qt_application_h 1 +#include + #include "octave.h" OCTAVE_BEGIN_NAMESPACE(octave) -// Programming Note: This file must not include any Qt headers. Any -// Qt header files required by the qt_application::execute function -// must be included only in the corresponding .cc file. + // Programming Note: This file must not include any Qt headers. Any + // Qt header files required by the qt_application::execute function + // must be included only in the corresponding .cc file. -//! This class inherits from the pure-virtual base class -//! application and provides an implementation of the -//! application::execute method that starts an interface to Octave -//! that is based on Qt. It may start a command-line interface that -//! allows Qt graphics to be used or it may start an interface that -//! provides the full GUI experience. + //! This class inherits from the pure-virtual base class + //! application and provides an implementation of the + //! application::execute method that starts an interface to Octave + //! that is based on Qt. It may start a command-line interface that + //! allows Qt graphics to be used or it may start an interface that + //! provides the full GUI experience. class OCTGUI_API qt_application : public application -{ - public: + { + public: - qt_application (int argc, char **argv); + qt_application (const std::string& organization_name, + const std::string& application_name, + const std::string& application_version, + int argc, char **argv); - // No copying, at least not yet. + qt_application (int argc, char **argv); - qt_application (const qt_application&) = delete; + // No copying, at least not yet. - qt_application& operator = (const qt_application&) = delete; + qt_application (const qt_application&) = delete; - ~qt_application (void) = default; + qt_application& operator = (const qt_application&) = delete; - // Should we start the GUI or fall back to the CLI? - bool start_gui_p (void) const; + ~qt_application (void) = default; - int execute (void); + // Should we start the GUI or fall back to the CLI? + bool start_gui_p (void) const; + + int execute (void); - bool gui_running (void) const { return m_gui_running; } - void gui_running (bool arg) { m_gui_running = arg; } + bool gui_running (void) const { return m_gui_running; } + void gui_running (bool arg) { m_gui_running = arg; } - private: + private: - // If TRUE, the GUI should be started. - bool m_gui_running = false; -}; + // If TRUE, the GUI should be started. + bool m_gui_running = false; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/qt-interpreter-events.cc --- a/libgui/src/qt-interpreter-events.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/qt-interpreter-events.cc Tue Dec 06 15:45:27 2022 -0500 @@ -39,6 +39,7 @@ #include "dialog.h" #include "gui-preferences-ed.h" +#include "gui-settings.h" #include "octave-qobject.h" #include "qt-interpreter-events.h" #include "qt-utils.h" @@ -64,690 +65,689 @@ OCTAVE_BEGIN_NAMESPACE(octave) -static QStringList -make_qstring_list (const std::list& lst) -{ - QStringList retval; + static QStringList + make_qstring_list (const std::list& lst) + { + QStringList retval; - for (const auto& s : lst) - retval.append (QString::fromStdString (s)); + for (const auto& s : lst) + retval.append (QString::fromStdString (s)); - return retval; -} + return retval; + } -static QStringList -make_filter_list (const event_manager::filter_list& lst) -{ - QStringList retval; + static QStringList + make_filter_list (const event_manager::filter_list& lst) + { + QStringList retval; - // We have pairs of data, first being the list of extensions - // exta;exb;extc etc second the name to use as filter name - // (optional). Qt wants a list of filters in the format of - // 'FilterName (space separated exts)'. + // We have pairs of data, first being the list of extensions + // exta;exb;extc etc second the name to use as filter name + // (optional). Qt wants a list of filters in the format of + // 'FilterName (space separated exts)'. - for (const auto& ext_name : lst) - { - QString ext = QString::fromStdString (ext_name.first); - QString name = QString::fromStdString (ext_name.second); + for (const auto& ext_name : lst) + { + QString ext = QString::fromStdString (ext_name.first); + QString name = QString::fromStdString (ext_name.second); - // Strip out extensions from name and replace ';' with spaces in list. + // Strip out extensions from name and replace ';' with spaces in list. - name.replace (QRegExp (R"(\(.*\))"), ""); - ext.replace (";", " "); + name.replace (QRegExp (R"(\(.*\))"), ""); + ext.replace (";", " "); - if (name.isEmpty ()) - { - // No name field. Build one from the extensions. - name = ext.toUpper () + " Files"; - } + if (name.isEmpty ()) + { + // No name field. Build one from the extensions. + name = ext.toUpper () + " Files"; + } - retval.append (name + " (" + ext + ')'); - } + retval.append (name + " (" + ext + ')'); + } - return retval; -} + return retval; + } -qt_interpreter_events::qt_interpreter_events (base_qobject& oct_qobj) - : interpreter_events (), m_octave_qobj (oct_qobj), - m_uiwidget_creator (oct_qobj), m_result (), m_mutex (), - m_waitcondition () -{ - qRegisterMetaType ("QIntList"); - qRegisterMetaType ("QFloatList"); + qt_interpreter_events::qt_interpreter_events (base_qobject& oct_qobj) + : interpreter_events (), m_octave_qobj (oct_qobj), + m_uiwidget_creator (), m_result (), m_mutex (), + m_waitcondition () + { + qRegisterMetaType ("QIntList"); + qRegisterMetaType ("QFloatList"); - qRegisterMetaType ("octave_value"); - qRegisterMetaType ("symbol_info_list"); + qRegisterMetaType ("octave_value"); + qRegisterMetaType ("symbol_info_list"); - qRegisterMetaType ("fcn_callback"); - qRegisterMetaType ("meth_callback"); + qRegisterMetaType ("fcn_callback"); + qRegisterMetaType ("meth_callback"); - connect (this, &qt_interpreter_events::confirm_shutdown_signal, - this, &qt_interpreter_events::confirm_shutdown_octave); + connect (this, &qt_interpreter_events::confirm_shutdown_signal, + this, &qt_interpreter_events::confirm_shutdown_octave); - connect (this, &qt_interpreter_events::get_named_icon_signal, - this, &qt_interpreter_events::get_named_icon_slot); + connect (this, &qt_interpreter_events::get_named_icon_signal, + this, &qt_interpreter_events::get_named_icon_slot); - connect (this, &qt_interpreter_events::gui_preference_signal, - this, &qt_interpreter_events::gui_preference_slot); -} + connect (this, &qt_interpreter_events::gui_preference_signal, + this, &qt_interpreter_events::gui_preference_slot); + } -void qt_interpreter_events::start_gui (bool gui_app) -{ - if (m_octave_qobj.experimental_terminal_widget ()) - emit start_gui_signal (gui_app); -} + void qt_interpreter_events::start_gui (bool gui_app) + { + if (m_octave_qobj.experimental_terminal_widget ()) + emit start_gui_signal (gui_app); + } -void qt_interpreter_events::close_gui (void) -{ - if (m_octave_qobj.experimental_terminal_widget ()) - emit close_gui_signal (); -} + void qt_interpreter_events::close_gui (void) + { + if (m_octave_qobj.experimental_terminal_widget ()) + emit close_gui_signal (); + } -std::list -qt_interpreter_events::file_dialog (const filter_list& filter, - const std::string& title, - const std::string& filename, - const std::string& dirname, - const std::string& multimode) -{ - QStringList lst - = m_uiwidget_creator.file_dialog (make_filter_list (filter), - QString::fromStdString (title), - QString::fromStdString (filename), - QString::fromStdString (dirname), - QString::fromStdString (multimode)); + std::list + qt_interpreter_events::file_dialog (const filter_list& filter, + const std::string& title, + const std::string& filename, + const std::string& dirname, + const std::string& multimode) + { + QStringList lst + = m_uiwidget_creator.file_dialog (make_filter_list (filter), + QString::fromStdString (title), + QString::fromStdString (filename), + QString::fromStdString (dirname), + QString::fromStdString (multimode)); - std::list retval; + std::list retval; - for (const auto& s : lst) - retval.push_back (s.toStdString ()); + for (const auto& s : lst) + retval.push_back (s.toStdString ()); - return retval; -} + return retval; + } -std::list -qt_interpreter_events::input_dialog (const std::list& prompt, - const std::string& title, - const std::list& nr, - const std::list& nc, - const std::list& defaults) -{ - QStringList lst - = m_uiwidget_creator.input_dialog (make_qstring_list (prompt), - QString::fromStdString (title), - std_list_to_qt_list (nr), - std_list_to_qt_list (nc), - make_qstring_list (defaults)); - std::list retval; + std::list + qt_interpreter_events::input_dialog (const std::list& prompt, + const std::string& title, + const std::list& nr, + const std::list& nc, + const std::list& defaults) + { + QStringList lst + = m_uiwidget_creator.input_dialog (make_qstring_list (prompt), + QString::fromStdString (title), + std_list_to_qt_list (nr), + std_list_to_qt_list (nc), + make_qstring_list (defaults)); + std::list retval; - for (const auto& s : lst) - retval.push_back (s.toStdString ()); + for (const auto& s : lst) + retval.push_back (s.toStdString ()); - return retval; -} + return retval; + } -std::pair, int> -qt_interpreter_events::list_dialog (const std::list& list, - const std::string& mode, - int width, int height, - const std::list& initial, - const std::string& name, - const std::list& prompt, - const std::string& ok_string, - const std::string& cancel_string) -{ - QPair result - = m_uiwidget_creator.list_dialog (make_qstring_list (list), - QString::fromStdString (mode), - width, height, - std_list_to_qt_list (initial), - QString::fromStdString (name), - make_qstring_list (prompt), - QString::fromStdString (ok_string), - QString::fromStdString (cancel_string)); + std::pair, int> + qt_interpreter_events::list_dialog (const std::list& list, + const std::string& mode, + int width, int height, + const std::list& initial, + const std::string& name, + const std::list& prompt, + const std::string& ok_string, + const std::string& cancel_string) + { + QPair result + = m_uiwidget_creator.list_dialog (make_qstring_list (list), + QString::fromStdString (mode), + width, height, + std_list_to_qt_list (initial), + QString::fromStdString (name), + make_qstring_list (prompt), + QString::fromStdString (ok_string), + QString::fromStdString (cancel_string)); - QIntList& lst = result.first; - return std::pair, int> (std::list (lst.begin (), - lst.end ()), - result.second); -} + QIntList& lst = result.first; + return std::pair, int> (std::list (lst.begin (), + lst.end ()), + result.second); + } -std::string -qt_interpreter_events::question_dialog (const std::string& msg, - const std::string& title, - const std::string& btn1, - const std::string& btn2, - const std::string& btn3, - const std::string& btndef) -{ - QString icon = "quest"; - QStringList buttons; - QStringList role; + std::string + qt_interpreter_events::question_dialog (const std::string& msg, + const std::string& title, + const std::string& btn1, + const std::string& btn2, + const std::string& btn3, + const std::string& btndef) + { + QString icon = "quest"; + QStringList buttons; + QStringList role; - // Must use ResetRole which is left-aligned for all OS and WM. - role << "ResetRole" << "ResetRole" << "ResetRole"; + // Must use ResetRole which is left-aligned for all OS and WM. + role << "ResetRole" << "ResetRole" << "ResetRole"; - buttons << QString::fromStdString (btn1); - if (btn2 == "") - role.removeAt (0); - else - buttons << QString::fromStdString (btn2); - buttons << QString::fromStdString (btn3); + buttons << QString::fromStdString (btn1); + if (btn2 == "") + role.removeAt (0); + else + buttons << QString::fromStdString (btn2); + buttons << QString::fromStdString (btn3); - QString answer - = m_uiwidget_creator.message_dialog (QString::fromStdString (msg), - QString::fromStdString (title), - icon, buttons, - QString::fromStdString (btndef), - role); + QString answer + = m_uiwidget_creator.message_dialog (QString::fromStdString (msg), + QString::fromStdString (title), + icon, buttons, + QString::fromStdString (btndef), + role); - return answer.toStdString (); -} + return answer.toStdString (); + } -void qt_interpreter_events::update_path_dialog (void) -{ - emit update_path_dialog_signal (); -} + void qt_interpreter_events::update_path_dialog (void) + { + emit update_path_dialog_signal (); + } -void qt_interpreter_events::show_preferences (void) -{ - emit show_preferences_signal (); -} + void qt_interpreter_events::show_preferences (void) + { + emit show_preferences_signal (); + } -void qt_interpreter_events::apply_preferences (void) -{ - emit apply_new_settings (); -} + void qt_interpreter_events::apply_preferences (void) + { + emit apply_new_settings (); + } -void qt_interpreter_events::show_terminal_window (void) -{ - emit show_terminal_window_signal (); -} + void qt_interpreter_events::show_terminal_window (void) + { + emit show_terminal_window_signal (); + } -bool qt_interpreter_events::show_documentation (const std::string& file) -{ - emit show_documentation_signal (QString::fromStdString (file)); + bool qt_interpreter_events::show_documentation (const std::string& file) + { + emit show_documentation_signal (QString::fromStdString (file)); - return true; -} + return true; + } -void qt_interpreter_events::show_file_browser (void) -{ - emit show_file_browser_signal (); -} + void qt_interpreter_events::show_file_browser (void) + { + emit show_file_browser_signal (); + } -void qt_interpreter_events::show_command_history (void) -{ - emit show_command_history_signal (); -} + void qt_interpreter_events::show_command_history (void) + { + emit show_command_history_signal (); + } -void qt_interpreter_events::show_workspace (void) -{ - emit show_workspace_signal (); -} + void qt_interpreter_events::show_workspace (void) + { + emit show_workspace_signal (); + } -void qt_interpreter_events::show_community_news (int serial) -{ - emit show_community_news_signal (serial); -} + void qt_interpreter_events::show_community_news (int serial) + { + emit show_community_news_signal (serial); + } -void qt_interpreter_events::show_release_notes (void) -{ - emit show_release_notes_signal (); -} + void qt_interpreter_events::show_release_notes (void) + { + emit show_release_notes_signal (); + } -bool qt_interpreter_events::edit_file (const std::string& file) -{ - emit edit_file_signal (QString::fromStdString (file)); + bool qt_interpreter_events::edit_file (const std::string& file) + { + emit edit_file_signal (QString::fromStdString (file)); - return true; -} + return true; + } -void qt_interpreter_events::edit_variable (const std::string& expr, - const octave_value& val) -{ - emit edit_variable_signal (QString::fromStdString (expr), val); -} + void qt_interpreter_events::edit_variable (const std::string& expr, + const octave_value& val) + { + emit edit_variable_signal (QString::fromStdString (expr), val); + } -bool qt_interpreter_events::confirm_shutdown (void) -{ - QMutexLocker autolock (&m_mutex); + bool qt_interpreter_events::confirm_shutdown (void) + { + QMutexLocker autolock (&m_mutex); - emit confirm_shutdown_signal (); + emit confirm_shutdown_signal (); - // Wait for result. - wait (); + // Wait for result. + wait (); - return m_result.toBool (); -} + return m_result.toBool (); + } -bool qt_interpreter_events::prompt_new_edit_file (const std::string& file) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + bool qt_interpreter_events::prompt_new_edit_file (const std::string& file) + { + gui_settings settings; + + if (settings.value (ed_create_new_file).toBool ()) + return true; - if (! settings || settings->value (ed_create_new_file).toBool ()) - return true; - - std::string abs_fname = sys::env::make_absolute (file); + std::string abs_fname = sys::env::make_absolute (file); - QStringList btn; - QStringList role; - role << "YesRole" << "RejectRole"; - btn << tr ("Create") << tr ("Cancel"); + QStringList btn; + QStringList role; + role << "YesRole" << "RejectRole"; + btn << tr ("Create") << tr ("Cancel"); + + QString answer = m_uiwidget_creator.message_dialog + (tr ("File\n%1\ndoes not exist. Do you want to create it?"). + arg (QString::fromStdString (abs_fname)), + tr ("Octave Editor"), "quest", btn, tr ("Create"), role); - QString answer = m_uiwidget_creator.message_dialog - (tr ("File\n%1\ndoes not exist. Do you want to create it?"). - arg (QString::fromStdString (abs_fname)), - tr ("Octave Editor"), "quest", btn, tr ("Create"), role); + return (answer == tr ("Create")); + } - return (answer == tr ("Create")); -} - -// Prompt to allow file to be run by setting cwd (or if -// addpath_option==true, alternatively setting the path). + // Prompt to allow file to be run by setting cwd (or if + // addpath_option==true, alternatively setting the path). -int -qt_interpreter_events::debug_cd_or_addpath_error (const std::string& file, - const std::string& dir, - bool addpath_option) -{ - int retval = -1; + int + qt_interpreter_events::debug_cd_or_addpath_error (const std::string& file, + const std::string& dir, + bool addpath_option) + { + int retval = -1; - QString qdir = QString::fromStdString (dir); - QString qfile = QString::fromStdString (file); - QString msg - = (addpath_option - ? tr ("The file %1 does not exist in the load path. To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.").arg (qfile).arg (qdir) - : tr ("The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.").arg (qfile).arg (qdir)); + QString qdir = QString::fromStdString (dir); + QString qfile = QString::fromStdString (file); + QString msg + = (addpath_option + ? tr ("The file %1 does not exist in the load path. To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.").arg (qfile).arg (qdir) + : tr ("The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.").arg (qfile).arg (qdir)); + + QString title = tr ("Change Directory or Add Directory to Load Path"); - QString title = tr ("Change Directory or Add Directory to Load Path"); - - QString cd_txt = tr ("&Change Directory"); - QString addpath_txt = tr ("&Add Directory to Load Path"); - QString cancel_txt = tr ("Cancel"); + QString cd_txt = tr ("&Change Directory"); + QString addpath_txt = tr ("&Add Directory to Load Path"); + QString cancel_txt = tr ("Cancel"); - QStringList btn; - QStringList role; - btn << cd_txt; - role << "YesRole"; - if (addpath_option) - { - btn << addpath_txt; - role << "AcceptRole"; - } - btn << cancel_txt; - role << "RejectRole"; + QStringList btn; + QStringList role; + btn << cd_txt; + role << "YesRole"; + if (addpath_option) + { + btn << addpath_txt; + role << "AcceptRole"; + } + btn << cancel_txt; + role << "RejectRole"; - QString result - = m_uiwidget_creator.message_dialog (msg, title, "quest", btn, - cancel_txt, role); + QString result + = m_uiwidget_creator.message_dialog (msg, title, "quest", btn, + cancel_txt, role); - if (result == cd_txt) - retval = 1; - else if (result == addpath_txt) - retval = 2; + if (result == cd_txt) + retval = 1; + else if (result == addpath_txt) + retval = 2; - return retval; -} + return retval; + } -uint8NDArray qt_interpreter_events::get_named_icon (const std::string& name) -{ - QMutexLocker autolock (&m_mutex); + uint8NDArray qt_interpreter_events::get_named_icon (const std::string& name) + { + QMutexLocker autolock (&m_mutex); - emit get_named_icon_signal (QString::fromStdString (name)); + emit get_named_icon_signal (QString::fromStdString (name)); - // Wait for result. - wait (); + // Wait for result. + wait (); - uint8NDArray empty_img; + uint8NDArray empty_img; - QIcon icon = m_result.value (); + QIcon icon = m_result.value (); - if (icon.isNull ()) - return empty_img; + if (icon.isNull ()) + return empty_img; - QImage img = icon.pixmap (QSize (32, 32)).toImage (); + QImage img = icon.pixmap (QSize (32, 32)).toImage (); - if (img.format () != QImage::Format_ARGB32_Premultiplied) - return empty_img; + if (img.format () != QImage::Format_ARGB32_Premultiplied) + return empty_img; - dim_vector dims (img.height (), img.width (), 4); + dim_vector dims (img.height (), img.width (), 4); - uint8NDArray retval (dims, 0); + uint8NDArray retval (dims, 0); - uint8_t *bits = img.bits (); + uint8_t *bits = img.bits (); - for (int i = 0; i < img.height (); i++) - { - for (int j = 0; j < img.width (); j++) - { - retval(i, j, 2) = bits[0]; - retval(i, j, 1) = bits[1]; - retval(i, j, 0) = bits[2]; - retval(i, j, 3) = bits[3]; + for (int i = 0; i < img.height (); i++) + { + for (int j = 0; j < img.width (); j++) + { + retval(i, j, 2) = bits[0]; + retval(i, j, 1) = bits[1]; + retval(i, j, 0) = bits[2]; + retval(i, j, 3) = bits[3]; - bits += 4; - } - } + bits += 4; + } + } - return retval; -} + return retval; + } + + void qt_interpreter_events::get_named_icon_slot (const QString& name) + { + QMutexLocker autolock (&m_mutex); -void qt_interpreter_events::get_named_icon_slot (const QString& name) -{ - QMutexLocker autolock (&m_mutex); + gui_settings settings; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - m_result = QVariant::fromValue (rmgr.icon (name)); + m_result = QVariant::fromValue (settings.icon (name)); - wake_all (); -} + wake_all (); + } -std::string -qt_interpreter_events::gui_preference (const std::string& key, - const std::string& value) -{ - QString pref_value; + std::string + qt_interpreter_events::gui_preference (const std::string& key, + const std::string& value) + { + QString pref_value; - QMutexLocker autolock (&m_mutex); + QMutexLocker autolock (&m_mutex); - // Emit the signal for changing or getting a preference - emit gui_preference_signal (QString::fromStdString (key), - QString::fromStdString (value)); + // Emit the signal for changing or getting a preference + emit gui_preference_signal (QString::fromStdString (key), + QString::fromStdString (value)); - // Wait for response (pref_value). - wait (); + // Wait for response (pref_value). + wait (); - QString pref = m_result.toString (); + QString pref = m_result.toString (); - return pref.toStdString (); -} + return pref.toStdString (); + } -bool qt_interpreter_events::copy_image_to_clipboard (const std::string& file) -{ - emit copy_image_to_clipboard_signal (QString::fromStdString (file), true); + bool qt_interpreter_events::copy_image_to_clipboard (const std::string& file) + { + emit copy_image_to_clipboard_signal (QString::fromStdString (file), true); - return true; -} + return true; + } -void qt_interpreter_events::focus_window (const std::string win_name) -{ - emit focus_window_signal (QString::fromStdString (win_name)); -} + void qt_interpreter_events::focus_window (const std::string win_name) + { + emit focus_window_signal (QString::fromStdString (win_name)); + } -void qt_interpreter_events::execute_command_in_terminal -(const std::string& command) -{ - emit execute_command_in_terminal_signal (QString::fromStdString (command)); -} + void qt_interpreter_events::execute_command_in_terminal + (const std::string& command) + { + emit execute_command_in_terminal_signal (QString::fromStdString (command)); + } -void qt_interpreter_events::register_documentation (const std::string& file) -{ - emit register_documentation_signal (QString::fromStdString (file)); -} + void qt_interpreter_events::register_documentation (const std::string& file) + { + emit register_documentation_signal (QString::fromStdString (file)); + } -void qt_interpreter_events::unregister_documentation (const std::string& file) -{ - emit unregister_documentation_signal (QString::fromStdString (file)); -} + void qt_interpreter_events::unregister_documentation (const std::string& file) + { + emit unregister_documentation_signal (QString::fromStdString (file)); + } -void qt_interpreter_events::interpreter_output (const std::string& msg) -{ - if (m_octave_qobj.experimental_terminal_widget () - && m_octave_qobj.have_terminal_window ()) - emit interpreter_output_signal (QString::fromStdString (msg)); - else - { - // FIXME: is this the correct thing to do? - std::cout << msg; - } -} + void qt_interpreter_events::interpreter_output (const std::string& msg) + { + if (m_octave_qobj.experimental_terminal_widget () + && m_octave_qobj.have_terminal_window ()) + emit interpreter_output_signal (QString::fromStdString (msg)); + else + { + // FIXME: is this the correct thing to do? + std::cout << msg; + } + } -void qt_interpreter_events::display_exception (const execution_exception& ee, - bool beep) -{ - if (m_octave_qobj.experimental_terminal_widget () - && m_octave_qobj.have_terminal_window ()) - { - // Output the exception message - std::ostringstream buf; - ee.display (buf); - emit interpreter_output_signal (QString::fromStdString (buf.str ())); - // Create w new command line - emit new_command_line_signal (); - } - else - { - if (beep) - std::cerr << "\a"; + void qt_interpreter_events::display_exception (const execution_exception& ee, + bool beep) + { + if (m_octave_qobj.experimental_terminal_widget () + && m_octave_qobj.have_terminal_window ()) + { + // Output the exception message + std::ostringstream buf; + ee.display (buf); + emit interpreter_output_signal (QString::fromStdString (buf.str ())); + // Create w new command line + emit new_command_line_signal (); + } + else + { + if (beep) + std::cerr << "\a"; - ee.display (std::cerr); - } -} + ee.display (std::cerr); + } + } -void qt_interpreter_events::gui_status_update (const std::string& feature, - const std::string& status) -{ - emit gui_status_update_signal (QString::fromStdString (feature), - QString::fromStdString (status)); -} + void qt_interpreter_events::gui_status_update (const std::string& feature, + const std::string& status) + { + emit gui_status_update_signal (QString::fromStdString (feature), + QString::fromStdString (status)); + } -void qt_interpreter_events::update_gui_lexer (void) -{ - emit update_gui_lexer_signal (true); -} + void qt_interpreter_events::update_gui_lexer (void) + { + emit update_gui_lexer_signal (true); + } -void qt_interpreter_events::directory_changed (const std::string& dir) -{ - emit directory_changed_signal (QString::fromStdString (dir)); -} + void qt_interpreter_events::directory_changed (const std::string& dir) + { + emit directory_changed_signal (QString::fromStdString (dir)); + } -void qt_interpreter_events::file_remove (const std::string& old_name, - const std::string& new_name) -{ - QMutexLocker autolock (&m_mutex); + void qt_interpreter_events::file_remove (const std::string& old_name, + const std::string& new_name) + { + QMutexLocker autolock (&m_mutex); - // Emit the signal for the editor for closing the file if it is open - emit file_remove_signal (QString::fromStdString (old_name), - QString::fromStdString (new_name)); + // Emit the signal for the editor for closing the file if it is open + emit file_remove_signal (QString::fromStdString (old_name), + QString::fromStdString (new_name)); - // Wait for file removal to complete before continuing. - wait (); -} + // Wait for file removal to complete before continuing. + wait (); + } -void qt_interpreter_events::file_renamed (bool load_new) -{ - emit file_renamed_signal (load_new); -} + void qt_interpreter_events::file_renamed (bool load_new) + { + emit file_renamed_signal (load_new); + } -void qt_interpreter_events::set_workspace (bool top_level, bool debug, - const symbol_info_list& syminfo, - bool update_variable_editor) -{ - if (! top_level && ! debug) - return; + void qt_interpreter_events::set_workspace (bool top_level, bool debug, + const symbol_info_list& syminfo, + bool update_variable_editor) + { + if (! top_level && ! debug) + return; - emit set_workspace_signal (top_level, debug, syminfo); + emit set_workspace_signal (top_level, debug, syminfo); - if (update_variable_editor) - emit refresh_variable_editor_signal (); -} + if (update_variable_editor) + emit refresh_variable_editor_signal (); + } -void qt_interpreter_events::clear_workspace (void) -{ - emit clear_workspace_signal (); -} + void qt_interpreter_events::clear_workspace (void) + { + emit clear_workspace_signal (); + } + + void qt_interpreter_events::update_prompt (const std::string& prompt) + { + emit update_prompt_signal (QString::fromStdString (prompt)); + } + + void qt_interpreter_events::set_history (const string_vector& hist) + { + QStringList qt_hist; + + for (octave_idx_type i = 0; i < hist.numel (); i++) + qt_hist.append (QString::fromStdString (hist[i])); -void qt_interpreter_events::update_prompt (const std::string& prompt) -{ - emit update_prompt_signal (QString::fromStdString (prompt)); -} + emit set_history_signal (qt_hist); + } + + void qt_interpreter_events::append_history (const std::string& hist_entry) + { + emit append_history_signal (QString::fromStdString (hist_entry)); + } -void qt_interpreter_events::set_history (const string_vector& hist) -{ - QStringList qt_hist; + void qt_interpreter_events::clear_history (void) + { + emit clear_history_signal (); + } - for (octave_idx_type i = 0; i < hist.numel (); i++) - qt_hist.append (QString::fromStdString (hist[i])); + void qt_interpreter_events::pre_input_event (void) + { } + + void qt_interpreter_events::post_input_event (void) + { } - emit set_history_signal (qt_hist); -} + void qt_interpreter_events::enter_debugger_event (const std::string& /*fcn_name*/, + const std::string& fcn_file_name, + int line) + { + if (fcn_file_name.empty ()) + return; + + insert_debugger_pointer (fcn_file_name, line); -void qt_interpreter_events::append_history (const std::string& hist_entry) -{ - emit append_history_signal (QString::fromStdString (hist_entry)); -} + emit enter_debugger_signal (); + } + + void + qt_interpreter_events::execute_in_debugger_event (const std::string& file, + int line) + { + delete_debugger_pointer (file, line); + } -void qt_interpreter_events::clear_history (void) -{ - emit clear_history_signal (); -} + void qt_interpreter_events::exit_debugger_event (void) + { + emit exit_debugger_signal (); + } -void qt_interpreter_events::pre_input_event (void) -{ } + // Display (if @insert true) or remove the appropriate symbol for a breakpoint + // in @file at @line with condition @cond. + void qt_interpreter_events::update_breakpoint (bool insert, + const std::string& file, + int line, + const std::string& cond) + { + emit update_breakpoint_marker_signal (insert, QString::fromStdString (file), + line, QString::fromStdString (cond)); + } -void qt_interpreter_events::post_input_event (void) -{ } - -void qt_interpreter_events::enter_debugger_event (const std::string& /*fcn_name*/, - const std::string& fcn_file_name, + void + qt_interpreter_events::insert_debugger_pointer (const std::string& file, int line) -{ - if (fcn_file_name.empty ()) - return; - - insert_debugger_pointer (fcn_file_name, line); - - emit enter_debugger_signal (); -} - -void -qt_interpreter_events::execute_in_debugger_event (const std::string& file, - int line) -{ - delete_debugger_pointer (file, line); -} - -void qt_interpreter_events::exit_debugger_event (void) -{ - emit exit_debugger_signal (); -} + { + emit insert_debugger_pointer_signal (QString::fromStdString (file), line); + } -// Display (if @insert true) or remove the appropriate symbol for a breakpoint -// in @file at @line with condition @cond. -void qt_interpreter_events::update_breakpoint (bool insert, - const std::string& file, - int line, - const std::string& cond) -{ - emit update_breakpoint_marker_signal (insert, QString::fromStdString (file), - line, QString::fromStdString (cond)); -} - -void -qt_interpreter_events::insert_debugger_pointer (const std::string& file, - int line) -{ - emit insert_debugger_pointer_signal (QString::fromStdString (file), line); -} - -void -qt_interpreter_events::delete_debugger_pointer (const std::string& file, - int line) -{ - emit delete_debugger_pointer_signal (QString::fromStdString (file), line); -} + void + qt_interpreter_events::delete_debugger_pointer (const std::string& file, + int line) + { + emit delete_debugger_pointer_signal (QString::fromStdString (file), line); + } -void -qt_interpreter_events::confirm_shutdown_octave (void) -{ - QMutexLocker autolock (&m_mutex); + void + qt_interpreter_events::confirm_shutdown_octave (void) + { + QMutexLocker autolock (&m_mutex); - m_result = m_octave_qobj.confirm_shutdown (); + m_result = m_octave_qobj.confirm_shutdown (); - wake_all (); -} + wake_all (); + } -// If VALUE is empty, return current value of preference named by KEY. -// -// If VALUE is not empty, set preference named by KEY to VALUE return -// previous value. -// -// FIXME: should we have separate get and set functions? With only -// one, we don't allow a preference value to be set to the empty -// string. + // If VALUE is empty, return current value of preference named by KEY. + // + // If VALUE is not empty, set preference named by KEY to VALUE return + // previous value. + // + // FIXME: should we have separate get and set functions? With only + // one, we don't allow a preference value to be set to the empty + // string. -void -qt_interpreter_events::gui_preference_slot (const QString& key, - const QString& value) -{ - QMutexLocker autolock (&m_mutex); + void + qt_interpreter_events::gui_preference_slot (const QString& key, + const QString& value) + { + QMutexLocker autolock (&m_mutex); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - QString read_value = settings->value (key).toString (); + QString read_value = settings.value (key).toString (); + + // Some preferences need extra handling + QString adjusted_value = gui_preference_adjust (key, value); - // Some preferences need extra handling - QString adjusted_value = gui_preference_adjust (key, value); + if (! adjusted_value.isEmpty () && (read_value != adjusted_value)) + { + // Change settings only for new, non-empty values + settings.setValue (key, QVariant (adjusted_value)); - if (! adjusted_value.isEmpty () && (read_value != adjusted_value)) - { - // Change settings only for new, non-empty values - settings->setValue (key, QVariant (adjusted_value)); + emit settings_changed (true); // true: changed by worker + } - emit settings_changed (settings, true); // true: changed by worker - } + m_result = read_value; - m_result = read_value; + wake_all (); + } - wake_all (); -} + QString + qt_interpreter_events::gui_preference_adjust (const QString& key, + const QString& value) + { + // Immediately return if no new value is given. -QString -qt_interpreter_events::gui_preference_adjust (const QString& key, - const QString& value) -{ - // Immediately return if no new value is given. + if (value.isEmpty ()) + return value; + + QString adjusted_value = value; - if (value.isEmpty ()) - return value; - - QString adjusted_value = value; + // Not all encodings are available. Encodings are uppercase and do + // not use CPxxx but IBMxxx or WINDOWS-xxx. - // Not all encodings are available. Encodings are uppercase and do - // not use CPxxx but IBMxxx or WINDOWS-xxx. + if (key == ed_default_enc.key) + { + adjusted_value = adjusted_value.toUpper (); - if (key == ed_default_enc.key) - { - adjusted_value = adjusted_value.toUpper (); + QStringList codecs; + resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + rmgr.get_codecs (&codecs); - QStringList codecs; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - rmgr.get_codecs (&codecs); - - QRegExp re ("^CP(\\d+)$"); + QRegExp re ("^CP(\\d+)$"); - if (adjusted_value == "SYSTEM") - adjusted_value = - QString ("SYSTEM (") + - QString (octave_locale_charset_wrapper ()).toUpper () + - QString (")"); - else if (re.indexIn (adjusted_value) > -1) - { - if (codecs.contains ("IBM" + re.cap (1))) - adjusted_value = "IBM" + re.cap (1); - else if (codecs.contains ("WINDOWS-" + re.cap (1))) - adjusted_value = "WINDOWS-" + re.cap (1); - else - adjusted_value.clear (); - } - else if (! codecs.contains (adjusted_value)) - adjusted_value.clear (); - } + if (adjusted_value == "SYSTEM") + adjusted_value = + QString ("SYSTEM (") + + QString (octave_locale_charset_wrapper ()).toUpper () + + QString (")"); + else if (re.indexIn (adjusted_value) > -1) + { + if (codecs.contains ("IBM" + re.cap (1))) + adjusted_value = "IBM" + re.cap (1); + else if (codecs.contains ("WINDOWS-" + re.cap (1))) + adjusted_value = "WINDOWS-" + re.cap (1); + else + adjusted_value.clear (); + } + else if (! codecs.contains (adjusted_value)) + adjusted_value.clear (); + } - return adjusted_value; -} + return adjusted_value; + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/qt-interpreter-events.h --- a/libgui/src/qt-interpreter-events.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/qt-interpreter-events.h Tue Dec 06 15:45:27 2022 -0500 @@ -36,7 +36,6 @@ #include #include "dialog.h" -#include "gui-settings.h" #include "event-manager.h" @@ -47,284 +46,284 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; + class base_qobject; -// The functions in this class are not normally called directly, but -// are invoked from the Octave interpreter thead by methods in the -// event_manager class. In most cases, they should only translate -// data from the types typically used in the interpreter to whatever -// is required by the GUI (for example, std::string to QString) and -// emit a Qt signal. -// -// The use of Qt signals provides a thread-safe way for the Octave -// interpreter to notify the GUI of events (directory or workspace has -// changed, for example) or to request that the GUI perform actions -// (display a dialog, for example). -// -// By using this class as a wrapper around the Qt signals, we maintain -// a separation between the Octave interpreter and any specific GUI -// toolkit (no Qt headers are used in the Octave interpreter sources). + // The functions in this class are not normally called directly, but + // are invoked from the Octave interpreter thead by methods in the + // event_manager class. In most cases, they should only translate + // data from the types typically used in the interpreter to whatever + // is required by the GUI (for example, std::string to QString) and + // emit a Qt signal. + // + // The use of Qt signals provides a thread-safe way for the Octave + // interpreter to notify the GUI of events (directory or workspace has + // changed, for example) or to request that the GUI perform actions + // (display a dialog, for example). + // + // By using this class as a wrapper around the Qt signals, we maintain + // a separation between the Octave interpreter and any specific GUI + // toolkit (no Qt headers are used in the Octave interpreter sources). -class qt_interpreter_events : public QObject, public interpreter_events -{ - Q_OBJECT + class qt_interpreter_events : public QObject, public interpreter_events + { + Q_OBJECT -public: + public: - qt_interpreter_events (base_qobject& oct_qobj); + qt_interpreter_events (base_qobject& oct_qobj); - // No copying! + // No copying! - qt_interpreter_events (const qt_interpreter_events&) = delete; + qt_interpreter_events (const qt_interpreter_events&) = delete; - qt_interpreter_events& operator = (const qt_interpreter_events&) = delete; + qt_interpreter_events& operator = (const qt_interpreter_events&) = delete; - ~qt_interpreter_events (void) = default; + ~qt_interpreter_events (void) = default; - // Note: these functions currently do nothing with the old terminal - // widget. - void start_gui (bool gui_app = false); - void close_gui (void); + // Note: these functions currently do nothing with the old terminal + // widget. + void start_gui (bool gui_app = false); + void close_gui (void); - bool have_dialogs (void) const { return true; } + bool have_dialogs (void) const { return true; } - std::list - file_dialog (const filter_list& filter, const std::string& title, - const std::string& filename, const std::string& pathname, - const std::string& multimode); + std::list + file_dialog (const filter_list& filter, const std::string& title, + const std::string& filename, const std::string& pathname, + const std::string& multimode); - std::list - input_dialog (const std::list& prompt, - const std::string& title, const std::list& nr, - const std::list& nc, - const std::list& defaults); + std::list + input_dialog (const std::list& prompt, + const std::string& title, const std::list& nr, + const std::list& nc, + const std::list& defaults); - std::pair, int> - list_dialog (const std::list& list, - const std::string& mode, int width, int height, - const std::list& initial_value, - const std::string& name, - const std::list& prompt, - const std::string& ok_string, - const std::string& cancel_string); + std::pair, int> + list_dialog (const std::list& list, + const std::string& mode, int width, int height, + const std::list& initial_value, + const std::string& name, + const std::list& prompt, + const std::string& ok_string, + const std::string& cancel_string); - std::string - question_dialog (const std::string& msg, const std::string& title, - const std::string& btn1, const std::string& btn2, - const std::string& btn3, const std::string& btndef); + std::string + question_dialog (const std::string& msg, const std::string& title, + const std::string& btn1, const std::string& btn2, + const std::string& btn3, const std::string& btndef); - void update_path_dialog (void); + void update_path_dialog (void); - void show_preferences (void); + void show_preferences (void); - void apply_preferences (void); + void apply_preferences (void); - void show_terminal_window (void); + void show_terminal_window (void); - bool show_documentation (const std::string& file); + bool show_documentation (const std::string& file); - void show_file_browser (void); + void show_file_browser (void); - void show_command_history (void); + void show_command_history (void); - void show_workspace (void); + void show_workspace (void); - void show_community_news (int serial); - void show_release_notes (void); + void show_community_news (int serial); + void show_release_notes (void); - bool edit_file (const std::string& file); + bool edit_file (const std::string& file); - void edit_variable (const std::string& name, const octave_value& val); + void edit_variable (const std::string& name, const octave_value& val); - bool confirm_shutdown (void); + bool confirm_shutdown (void); - bool prompt_new_edit_file (const std::string& file); + bool prompt_new_edit_file (const std::string& file); - int debug_cd_or_addpath_error (const std::string& file, - const std::string& dir, - bool addpath_option); + int debug_cd_or_addpath_error (const std::string& file, + const std::string& dir, + bool addpath_option); - uint8NDArray get_named_icon (const std::string& icon_name); + uint8NDArray get_named_icon (const std::string& icon_name); - std::string gui_preference (const std::string& key, - const std::string& value); + std::string gui_preference (const std::string& key, + const std::string& value); - bool copy_image_to_clipboard (const std::string& file); + bool copy_image_to_clipboard (const std::string& file); - void focus_window (const std::string win_name); + void focus_window (const std::string win_name); - void execute_command_in_terminal (const std::string& command); + void execute_command_in_terminal (const std::string& command); - void register_documentation (const std::string& file); + void register_documentation (const std::string& file); - void unregister_documentation (const std::string& file); + void unregister_documentation (const std::string& file); - // Note: this function currently does nothing with the old terminal - // widget. - void interpreter_output (const std::string& msg); + // Note: this function currently does nothing with the old terminal + // widget. + void interpreter_output (const std::string& msg); - void display_exception (const execution_exception& ee, bool beep); + void display_exception (const execution_exception& ee, bool beep); - void gui_status_update (const std::string& feature, const std::string& status); + void gui_status_update (const std::string& feature, const std::string& status); - void update_gui_lexer (void); + void update_gui_lexer (void); - void directory_changed (const std::string& dir); + void directory_changed (const std::string& dir); - void file_remove (const std::string& old_name, - const std::string& new_name); + void file_remove (const std::string& old_name, + const std::string& new_name); - void file_renamed (bool load_new = true); + void file_renamed (bool load_new = true); - void set_workspace (bool top_level, bool debug, - const symbol_info_list& syminfo, - bool update_variable_editor); + void set_workspace (bool top_level, bool debug, + const symbol_info_list& syminfo, + bool update_variable_editor); - void clear_workspace (void); + void clear_workspace (void); - void update_prompt (const std::string& prompt); + void update_prompt (const std::string& prompt); - void set_history (const string_vector& hist); + void set_history (const string_vector& hist); - void append_history (const std::string& hist_entry); + void append_history (const std::string& hist_entry); - void clear_history (void); + void clear_history (void); - void pre_input_event (void); + void pre_input_event (void); - void post_input_event (void); + void post_input_event (void); - void enter_debugger_event (const std::string& fcn_name, - const std::string& fcn_file_name, int line); + void enter_debugger_event (const std::string& fcn_name, + const std::string& fcn_file_name, int line); - void execute_in_debugger_event (const std::string& file, int line); + void execute_in_debugger_event (const std::string& file, int line); - void exit_debugger_event (void); + void exit_debugger_event (void); - void update_breakpoint (bool insert, const std::string& file, int line, - const std::string& cond); + void update_breakpoint (bool insert, const std::string& file, int line, + const std::string& cond); - void lock (void) { m_mutex.lock (); } + void lock (void) { m_mutex.lock (); } - void wait (void) { m_waitcondition.wait (&m_mutex); } + void wait (void) { m_waitcondition.wait (&m_mutex); } - void unlock (void) { m_mutex.unlock (); } + void unlock (void) { m_mutex.unlock (); } - void wake_all (void) { m_waitcondition.wakeAll (); } + void wake_all (void) { m_waitcondition.wakeAll (); } -public slots: + public slots: - void confirm_shutdown_octave (void); + void confirm_shutdown_octave (void); - void get_named_icon_slot (const QString& name); + void get_named_icon_slot (const QString& name); - void gui_preference_slot (const QString& key, const QString& value); + void gui_preference_slot (const QString& key, const QString& value); -signals: + signals: - // Note: these signals are not currently used by the old terminal widget. - void start_gui_signal (bool gui_app); - void close_gui_signal (void); + // Note: these signals are not currently used by the old terminal widget. + void start_gui_signal (bool gui_app); + void close_gui_signal (void); - void copy_image_to_clipboard_signal (const QString& file, bool remove_file); + void copy_image_to_clipboard_signal (const QString& file, bool remove_file); - void focus_window_signal (const QString& win_name); + void focus_window_signal (const QString& win_name); - void edit_file_signal (const QString& file); + void edit_file_signal (const QString& file); - void directory_changed_signal (const QString& dir); + void directory_changed_signal (const QString& dir); - void update_path_dialog_signal (void); + void update_path_dialog_signal (void); - void file_remove_signal (const QString& old_name, const QString& new_name); + void file_remove_signal (const QString& old_name, const QString& new_name); - void file_renamed_signal (bool load_new); + void file_renamed_signal (bool load_new); - void execute_command_in_terminal_signal (const QString& command); + void execute_command_in_terminal_signal (const QString& command); - void set_workspace_signal (bool top_level, bool debug, - const symbol_info_list& syminfo); + void set_workspace_signal (bool top_level, bool debug, + const symbol_info_list& syminfo); - void clear_workspace_signal (void); + void clear_workspace_signal (void); - void update_prompt_signal (const QString& prompt); + void update_prompt_signal (const QString& prompt); - void set_history_signal (const QStringList& hist); + void set_history_signal (const QStringList& hist); - void append_history_signal (const QString& hist_entry); + void append_history_signal (const QString& hist_entry); - void clear_history_signal (void); + void clear_history_signal (void); - void enter_debugger_signal (void); + void enter_debugger_signal (void); - void exit_debugger_signal (void); + void exit_debugger_signal (void); - void update_breakpoint_marker_signal (bool insert, const QString& file, - int line, const QString& cond); + void update_breakpoint_marker_signal (bool insert, const QString& file, + int line, const QString& cond); - void insert_debugger_pointer_signal (const QString&, int); + void insert_debugger_pointer_signal (const QString&, int); - void delete_debugger_pointer_signal (const QString&, int); + void delete_debugger_pointer_signal (const QString&, int); - void show_preferences_signal (void); + void show_preferences_signal (void); - void gui_preference_signal (const QString& key, const QString& value); + void gui_preference_signal (const QString& key, const QString& value); - void show_terminal_window_signal (void); + void show_terminal_window_signal (void); - void show_documentation_signal (const QString& file); + void show_documentation_signal (const QString& file); - void register_documentation_signal (const QString& file); + void register_documentation_signal (const QString& file); - void unregister_documentation_signal (const QString& file); + void unregister_documentation_signal (const QString& file); - void show_file_browser_signal (void); + void show_file_browser_signal (void); - void show_command_history_signal (void); + void show_command_history_signal (void); - void show_workspace_signal (void); + void show_workspace_signal (void); - void show_community_news_signal (int serial); - void show_release_notes_signal (void); + void show_community_news_signal (int serial); + void show_release_notes_signal (void); - // Note: the next two signals are currently not used by the old terminal widget. - void interpreter_output_signal (const QString& msg); - void new_command_line_signal (const QString& msg = QString ()); + // Note: the next two signals are currently not used by the old terminal widget. + void interpreter_output_signal (const QString& msg); + void new_command_line_signal (const QString& msg = QString ()); - void gui_status_update_signal (const QString& feature, const QString& status); + void gui_status_update_signal (const QString& feature, const QString& status); - void update_gui_lexer_signal (bool update_apis_only); + void update_gui_lexer_signal (bool update_apis_only); - void edit_variable_signal (const QString& name, const octave_value& val); + void edit_variable_signal (const QString& name, const octave_value& val); - void refresh_variable_editor_signal (void); + void refresh_variable_editor_signal (void); - void confirm_shutdown_signal (void); + void confirm_shutdown_signal (void); - void get_named_icon_signal (const QString& name); + void get_named_icon_signal (const QString& name); - void settings_changed (const gui_settings *, bool); + void settings_changed (bool); - void apply_new_settings (void); + void apply_new_settings (void); -private: + private: - QString gui_preference_adjust (const QString& key, const QString& value); + QString gui_preference_adjust (const QString& key, const QString& value); - void insert_debugger_pointer (const std::string& file, int line); + void insert_debugger_pointer (const std::string& file, int line); - void delete_debugger_pointer (const std::string& file, int line); + void delete_debugger_pointer (const std::string& file, int line); - base_qobject& m_octave_qobj; + base_qobject& m_octave_qobj; - QUIWidgetCreator m_uiwidget_creator; + QUIWidgetCreator m_uiwidget_creator; - QVariant m_result; + QVariant m_result; - QMutex m_mutex; + QMutex m_mutex; - QWaitCondition m_waitcondition; -}; + QWaitCondition m_waitcondition; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/release-notes.cc --- a/libgui/src/release-notes.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/release-notes.cc Tue Dec 06 15:45:27 2022 -0500 @@ -40,83 +40,83 @@ #include "gui-utils.h" #include "gui-preferences-dw.h" #include "gui-preferences-nr.h" +#include "gui-settings.h" #include "news-reader.h" -#include "octave-qobject.h" #include "defaults.h" OCTAVE_BEGIN_NAMESPACE(octave) -release_notes::release_notes (base_qobject& oct_qobj) -: QWidget (nullptr), m_browser (nullptr) -{ + release_notes::release_notes (void) + : QWidget (nullptr), m_browser (nullptr) + { - resource_manager& rmgr = oct_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; + + // The icon + QString icon_set = settings.value (dw_icon_set).toString (); - // The icon - QString icon_set = settings->value (dw_icon_set).toString (); - if (icon_set != "NONE") - m_release_notes_icon = dw_icon_set_names[icon_set] - + "ReleaseWidget.png"; - else - m_release_notes_icon = dw_icon_set_names[icon_set]; + if (icon_set != "NONE") + m_release_notes_icon = dw_icon_set_names[icon_set] + + "ReleaseWidget.png"; + else + m_release_notes_icon = dw_icon_set_names[icon_set]; - std::string news_file = config::oct_etc_dir () + "/NEWS"; + std::string news_file = config::oct_etc_dir () + "/NEWS"; - QString news; + QString news; - QFile *file = new QFile (QString::fromStdString (news_file)); - if (file->open (QFile::ReadOnly)) - { - QTextStream *stream = new QTextStream (file); - news = stream->readAll (); - if (! news.isEmpty ()) - { - // Convert '<', '>' which would be interpreted as HTML - news.replace ("<", "<"); - news.replace (">", ">"); - // Add HTML tags for pre-formatted text - news.prepend ("
");
-          news.append ("
"); - } - else - news = (tr ("The release notes file '%1' is empty.") - . arg (QString::fromStdString (news_file))); - } - else - news = (tr ("The release notes file '%1' cannot be read.") - . arg (QString::fromStdString (news_file))); + QFile *file = new QFile (QString::fromStdString (news_file)); + if (file->open (QFile::ReadOnly)) + { + QTextStream *stream = new QTextStream (file); + news = stream->readAll (); + if (! news.isEmpty ()) + { + // Convert '<', '>' which would be interpreted as HTML + news.replace ("<", "<"); + news.replace (">", ">"); + // Add HTML tags for pre-formatted text + news.prepend ("
");
+            news.append ("
"); + } + else + news = (tr ("The release notes file '%1' is empty.") + . arg (QString::fromStdString (news_file))); + } + else + news = (tr ("The release notes file '%1' cannot be read.") + . arg (QString::fromStdString (news_file))); - m_browser = new QTextBrowser (this); - m_browser->setText (news); + m_browser = new QTextBrowser (this); + m_browser->setText (news); - QVBoxLayout *vlayout = new QVBoxLayout; - vlayout->addWidget (m_browser); + QVBoxLayout *vlayout = new QVBoxLayout; + vlayout->addWidget (m_browser); - setLayout (vlayout); - setWindowTitle (tr ("Octave Release Notes")); + setLayout (vlayout); + setWindowTitle (tr ("Octave Release Notes")); - m_browser->document ()->adjustSize (); + m_browser->document ()->adjustSize (); - int win_x, win_y; - get_screen_geometry (win_x, win_y); + int win_x, win_y; + get_screen_geometry (win_x, win_y); - resize (win_x*2/5, win_y*2/3); - move (20, 20); // move to the top left corner -} + resize (win_x*2/5, win_y*2/3); + move (20, 20); // move to the top left corner + } -void release_notes::display (void) -{ - if (! isVisible ()) - show (); - else if (isMinimized ()) - showNormal (); + void release_notes::display (void) + { + if (! isVisible ()) + show (); + else if (isMinimized ()) + showNormal (); - setWindowIcon (QIcon (m_release_notes_icon)); + setWindowIcon (QIcon (m_release_notes_icon)); - raise (); - activateWindow (); -} + raise (); + activateWindow (); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/release-notes.h --- a/libgui/src/release-notes.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/release-notes.h Tue Dec 06 15:45:27 2022 -0500 @@ -33,27 +33,25 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; + class release_notes : public QWidget + { + Q_OBJECT -class release_notes : public QWidget -{ - Q_OBJECT + public: -public: + release_notes (void); - release_notes (base_qobject& qct_qobj); + ~release_notes (void) = default; - ~release_notes (void) = default; + public slots: -public slots: - - void display (void); + void display (void); -private: + private: - QTextBrowser *m_browser; - QString m_release_notes_icon; -}; + QTextBrowser *m_browser; + QString m_release_notes_icon; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/resource-manager.cc --- a/libgui/src/resource-manager.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/resource-manager.cc Tue Dec 06 15:45:27 2022 -0500 @@ -33,12 +33,10 @@ #include #include +#include #include #include -#include -#include #include -#include #include #include @@ -48,7 +46,7 @@ #include "gui-preferences-cs.h" #include "gui-preferences-ed.h" #include "gui-preferences-global.h" -#include "octave-qobject.h" +#include "gui-settings.h" #include "resource-manager.h" #include "variable-editor.h" #include "workspace-model.h" @@ -58,737 +56,416 @@ #include "oct-env.h" #include "defaults.h" -#include "error.h" -#include "help.h" OCTAVE_BEGIN_NAMESPACE(octave) -resource_manager::resource_manager (void) -: m_settings_directory (), m_settings_file (), m_settings (nullptr), - m_default_settings (nullptr), m_temporary_files (), m_icon_fallbacks () -{ - // Let gui_settings decide where to put the ini file with gui preferences - m_default_settings - = new gui_settings (QSettings::IniFormat, QSettings::UserScope, - "octave", "octave-gui"); - - m_settings_file = m_default_settings->fileName (); - - QFileInfo sfile (m_settings_file); - m_settings_directory = sfile.absolutePath (); - - QString xdg_config_home - = QString::fromLocal8Bit (qgetenv ("XDG_CONFIG_HOME")); + resource_manager::resource_manager (void) + : m_temporary_files () + { } - if ((! sfile.exists ()) && xdg_config_home.isEmpty ()) - { - // File does not exist yet: Look for a settings file at the old - // location ($HOME/.config/octave/qt-settings) for impoting all - // available keys into the new settings file. - // Do not look for an old settings file if XDG_CONFIG_HOME is set, - // since then a nonexistent new settings file does not necessarily - // indicate a first run of octave with new config file locations. -#if defined (HAVE_QSTANDARDPATHS) - QString home_path - = QStandardPaths::writableLocation (QStandardPaths::HomeLocation); -#else - QString home_path - = QDesktopServices::storageLocation (QDesktopServices::HomeLocation); -#endif + resource_manager::~resource_manager (void) + { + for (int i = m_temporary_files.count () - 1; i >=0; i--) + remove_tmp_file (m_temporary_files.at (i)); + } - QString old_settings_directory = home_path + "/.config/octave"; - QString old_settings_file = old_settings_directory + "/qt-settings"; - - QFile ofile (old_settings_file); - - if (ofile.exists ()) - { - // Old settings file exists; create a gui_settings object related - // to it and copy all available keys to the new settings - gui_settings old_settings (old_settings_file, QSettings::IniFormat); - - QStringList keys = old_settings.allKeys (); - for (int i = 0; i < keys.count(); i++) - m_default_settings->setValue (keys.at(i), - old_settings.value(keys.at(i))); - - m_default_settings->sync (); // Done, make sure keys are written - } - } -} + QString resource_manager::get_gui_translation_dir (void) + { + // get environment variable for the locale dir (e.g. from run-octave) + std::string dldir = sys::env::getenv ("OCTAVE_LOCALE_DIR"); + if (dldir.empty ()) + dldir = config::oct_locale_dir (); // env-var empty, load the default location + return QString::fromStdString (dldir); + } -resource_manager::~resource_manager (void) -{ - delete m_settings; - delete m_default_settings; - - for (int i = m_temporary_files.count () - 1; i >=0; i--) - remove_tmp_file (m_temporary_files.at (i)); -} + void resource_manager::config_translators (QTranslator *qt_tr, + QTranslator *qsci_tr, + QTranslator *gui_tr) + { + bool loaded; -QString resource_manager::get_gui_translation_dir (void) -{ - // get environment variable for the locale dir (e.g. from run-octave) - std::string dldir = sys::env::getenv ("OCTAVE_LOCALE_DIR"); - if (dldir.empty ()) - dldir = config::oct_locale_dir (); // env-var empty, load the default location - return QString::fromStdString (dldir); -} - -void resource_manager::config_translators (QTranslator *qt_tr, - QTranslator *qsci_tr, - QTranslator *gui_tr) -{ - bool loaded; - - QString qt_trans_dir - = QLibraryInfo::location (QLibraryInfo::TranslationsPath); - - QString language = "SYSTEM"; // take system language per default + QString qt_trans_dir + = QLibraryInfo::location (QLibraryInfo::TranslationsPath); - // FIXME: can we somehow ensure that the settings object will always - // be initialize and valid? + QString language = "SYSTEM"; // take system language per default - if (m_settings) - { - // get the locale from the settings if already available - language = m_settings->value (global_language.key, - global_language.def).toString (); - } + // FIXME: can we somehow ensure that the settings object will always + // be initialize and valid? - // load the translations depending on the settings - if (language == "SYSTEM") - { - // get the system locale and pass it to the translators for loading - // the suitable translation files - QLocale sys_locale = QLocale::system (); + gui_settings settings; - qt_tr->load (sys_locale, "qt", "_", qt_trans_dir); - qsci_tr->load (sys_locale, "qscintilla", "_", qt_trans_dir); - gui_tr->load (sys_locale, "", "", get_gui_translation_dir ()); - } - else - { - // load the translation files depending on the given locale name - loaded = qt_tr->load ("qt_" + language, qt_trans_dir); - if (! loaded) // try lower case - qt_tr->load ("qt_" + language.toLower (), qt_trans_dir); - - loaded = qsci_tr->load ("qscintilla_" + language, qt_trans_dir); - if (! loaded) // try lower case - qsci_tr->load ("qscintilla_" + language.toLower (), qt_trans_dir); + // get the locale from the settings if already available + language = settings.value (global_language.key, + global_language.def).toString (); - gui_tr->load (language, get_gui_translation_dir ()); - } - -} - -void resource_manager::config_icon_theme (void) -{ - m_icon_fallbacks.clear (); - - int theme = global_icon_theme_index.def.toInt (); + // load the translations depending on the settings + if (language == "SYSTEM") + { + // get the system locale and pass it to the translators for loading + // the suitable translation files + QLocale sys_locale = QLocale::system (); - if (m_settings) - { - // check for new and old setting and use old if required - if (! m_settings->contains (global_icon_theme_index.key)) - { - // new pref does not exist - if (m_settings->value (global_icon_theme).toBool ()) - theme = ICON_THEME_SYSTEM; - else - theme = ICON_THEME_OCTAVE; - m_settings->setValue (global_icon_theme_index.key, theme); // add new - m_settings->remove (global_icon_theme.key); // remove deprecated key - } - else - { - // get new settings - theme = m_settings->value (global_icon_theme_index).toInt (); - } - } - - QIcon::setThemeName (global_all_icon_themes.at (theme)); - - // set the required fallback search paths - switch (theme) - { - case ICON_THEME_SYSTEM: - m_icon_fallbacks << global_icon_paths.at (ICON_THEME_OCTAVE); - m_icon_fallbacks << global_icon_paths.at (ICON_THEME_TANGO); - break; - case ICON_THEME_TANGO: - m_icon_fallbacks << global_icon_paths.at (ICON_THEME_OCTAVE); - break; - case ICON_THEME_OCTAVE: - m_icon_fallbacks << global_icon_paths.at (ICON_THEME_TANGO); - break; - } - - m_icon_fallbacks << global_icon_paths.at (ICON_THEME_CURSORS); -} + qt_tr->load (sys_locale, "qt", "_", qt_trans_dir); + qsci_tr->load (sys_locale, "qscintilla", "_", qt_trans_dir); + gui_tr->load (sys_locale, "", "", get_gui_translation_dir ()); + } + else + { + // load the translation files depending on the given locale name + loaded = qt_tr->load ("qt_" + language, qt_trans_dir); + if (! loaded) // try lower case + qt_tr->load ("qt_" + language.toLower (), qt_trans_dir); -gui_settings * resource_manager::get_settings (void) const -{ - if (! m_settings) - { - QString msg (QT_TR_NOOP ("Octave has lost its settings.\n" - "This should not happen.\n\n" - "Please report this bug.\n\n" - "Octave GUI must be closed now.")); + loaded = qsci_tr->load ("qscintilla_" + language, qt_trans_dir); + if (! loaded) // try lower case + qsci_tr->load ("qscintilla_" + language.toLower (), qt_trans_dir); - QMessageBox::critical (nullptr, - QString (QT_TR_NOOP ("Octave Critical Error")), - msg); - exit (1); - } - - return m_settings; -} + gui_tr->load (language, get_gui_translation_dir ()); + } -gui_settings * resource_manager::get_default_settings (void) const -{ - if (! m_default_settings) - { - QString msg (QT_TR_NOOP ("Octave has lost its default settings.\n" - "This should not happen.\n" - "Please report this bug.\n\n" - "Octave GUI must be closed now.")); + } - QMessageBox::critical (nullptr, - QString (QT_TR_NOOP ("Octave Critical Error")), - msg); - exit (1); - } - - return m_default_settings; -} - -QString resource_manager::get_settings_directory (void) -{ - return m_settings_directory; -} - -QString resource_manager::get_settings_file (void) -{ - return m_settings_file; -} - -QString resource_manager::get_default_font_family (void) -{ - QString default_family; - - // Get all available fixed width fonts via a font combobox - QFontComboBox font_combo_box; - font_combo_box.setFontFilters (QFontComboBox::MonospacedFonts); - QStringList fonts; - - for (int index = 0; index < font_combo_box.count(); index++) - fonts << font_combo_box.itemText(index); - -#if defined (Q_OS_MAC) - // Use hard coded default on macOS, since selection of fixed width - // default font is unreliable (see bug #59128). - // Test for macOS default fixed width font - if (fonts.contains (global_mono_font.def.toString ())) - default_family = global_mono_font.def.toString (); +#if defined (HAVE_QSCINTILLA) + int resource_manager::get_valid_lexer_styles (QsciLexer *lexer, int *styles) + { + int max_style = 0; + int actual_style = 0; + while (actual_style < ed_max_style_number && max_style < ed_max_lexer_styles) + { + if ((lexer->description (actual_style)) != "") // valid style + styles[max_style++] = actual_style; + actual_style++; + } + return max_style; + } #endif - // If default font is still empty (on all other platforms or - // if macOS default font is not available): use QFontDatabase - if (default_family.isEmpty ()) - { - // Get the system's default monospaced font - QFont fixed_font = QFontDatabase::systemFont (QFontDatabase::FixedFont); - default_family = fixed_font.defaultFamily (); - - // Since this might be unreliable, test all available fixed width fonts - if (! fonts.contains (default_family)) - { - // Font returned by QFontDatabase is not in fixed fonts list. - // Fallback: take first from this list - default_family = fonts[0]; - } - } - - // Test env variable which has preference - std::string env_default_family = sys::env::getenv ("OCTAVE_DEFAULT_FONT"); - if (! env_default_family.empty ()) - default_family = QString::fromStdString (env_default_family); - - return default_family; -} - -QStringList resource_manager::get_default_font (void) -{ - QString default_family = get_default_font_family (); - - // determine the fefault font size of the system - // FIXME: QApplication::font () does not return the monospace font, - // but the size should be probably near to the monospace font - QFont font = QApplication::font (); - - int font_size = font.pointSize (); - if (font_size == -1) - font_size = static_cast (std::floor(font.pointSizeF ())); - - // check for valid font size, otherwise take default 10 - QString default_font_size = "10"; - if (font_size > 0) - default_font_size = QString::number (font_size); - - std::string env_default_font_size - = sys::env::getenv ("OCTAVE_DEFAULT_FONT_SIZE"); - - if (! env_default_font_size.empty ()) - default_font_size = QString::fromStdString (env_default_font_size); - - QStringList result; - result << default_family; - result << default_font_size; - return result; -} - -void resource_manager::reload_settings (void) -{ - // Declare some empty options, which may be set at first startup for - // writing them into the newly created settings file - QString custom_editor; - QStringList def_font; + QFont resource_manager::copy_font_attributes (const QFont& attr, + const QFont& base) const + { + QFont dest (base); - // Check whether the settings file does not yet exist - if (! QFile::exists (m_settings_file)) - { - // Get the default font (for terminal) - def_font = get_default_font (); - - // Get a custom editor defined as env variable - std::string env_default_editor - = sys::env::getenv ("OCTAVE_DEFAULT_EDITOR"); - - if (! env_default_editor.empty ()) - custom_editor = QString::fromStdString (env_default_editor); - } - - set_settings (m_settings_file); - - // Write some settings that were dynamically determined at first startup - if (m_settings) - { - // Custom editor - if (! custom_editor.isEmpty ()) - m_settings->setValue (global_custom_editor.key, custom_editor); - - // Default monospace font for the terminal - if (def_font.count () > 1) - { - m_settings->setValue (cs_font.key, def_font[0]); - m_settings->setValue (cs_font_size.key, def_font[1].toInt ()); - } + dest.setBold (attr.bold ()); + dest.setItalic (attr.italic ()); + dest.setUnderline (attr.underline ()); - // Write the default monospace font into the settings for later use by - // console and editor as fallbacks of their font preferences. - m_settings->setValue (global_mono_font.key, get_default_font_family ()); - } -} - -#if defined (HAVE_QSCINTILLA) -int resource_manager::get_valid_lexer_styles (QsciLexer *lexer, int *styles) -{ - int max_style = 0; - int actual_style = 0; - while (actual_style < ed_max_style_number && max_style < ed_max_lexer_styles) - { - if ((lexer->description (actual_style)) != "") // valid style - styles[max_style++] = actual_style; - actual_style++; - } - return max_style; -} -#endif - -QFont resource_manager::copy_font_attributes (const QFont& attr, - const QFont& base) const -{ - QFont dest (base); - - dest.setBold (attr.bold ()); - dest.setItalic (attr.italic ()); - dest.setUnderline (attr.underline ()); - - return dest; -} + return dest; + } #if defined (HAVE_QSCINTILLA) -void resource_manager::read_lexer_settings (QsciLexer *lexer, - gui_settings *settings, - int mode, int def) -{ - // Test whether the settings for lexer is already contained in the - // given gui settings file. If yes, load them, if not copy them from the - // default settings file. - // This is useful when a new language support is implemented and the - // existing settings file is used (which is of course the common case). - int m = mode; - if (m > 1) - m = 1; + void resource_manager::read_lexer_settings (QsciLexer *lexer, + int mode, int def) + { + gui_settings settings; - QString group ("Scintilla" + settings_color_modes_ext[m]); + // Test whether the settings for lexer is already contained in the + // given gui settings file. If yes, load them, if not copy them from the + // default settings file. + // This is useful when a new language support is implemented and the + // existing settings file is used (which is of course the common case). + int m = mode; + if (m > 1) + m = 1; - settings->beginGroup (group); - settings->beginGroup (lexer->language ()); + QString group ("Scintilla" + settings_color_modes_ext[m]); - QStringList lexer_keys = settings->allKeys (); + settings.beginGroup (group); + settings.beginGroup (lexer->language ()); + + QStringList lexer_keys = settings.allKeys (); - settings->endGroup (); - settings->endGroup (); + settings.endGroup (); + settings.endGroup (); - if (def == settings_reload_default_colors_flag || lexer_keys.count () == 0) - { - // We have to reload the default values or no Lexer keys found: - // If mode == 0, take all settings except font from default lexer - // If Mode == 1, take all settings except font from default lexer - // and convert the color by inverting the lightness + if (def == settings_reload_default_colors_flag || lexer_keys.count () == 0) + { + // We have to reload the default values or no Lexer keys found: + // If mode == 0, take all settings except font from default lexer + // If Mode == 1, take all settings except font from default lexer + // and convert the color by inverting the lightness - // Get the default font - QStringList def_font = get_default_font (); - QFont df (def_font[0], def_font[1].toInt ()); - QFont dfa = copy_font_attributes (lexer->defaultFont (), df); - lexer->setDefaultFont (dfa); + // Get the default font + QStringList def_font = settings.get_default_font (); + QFont df (def_font[0], def_font[1].toInt ()); + QFont dfa = copy_font_attributes (lexer->defaultFont (), df); + lexer->setDefaultFont (dfa); - QColor c, p; + QColor c, p; - int styles[ed_max_lexer_styles]; // array for saving valid styles - int max_style = get_valid_lexer_styles (lexer, styles); + int styles[ed_max_lexer_styles]; // array for saving valid styles + int max_style = get_valid_lexer_styles (lexer, styles); - for (int i = 0; i < max_style; i++) - { - c = settings->get_color_value (QVariant (lexer->color (styles[i])), m); - lexer->setColor (c, styles[i]); - p = settings->get_color_value (QVariant (lexer->paper (styles[i])), m); - lexer->setPaper (p, styles[i]); - dfa = copy_font_attributes (lexer->font (styles[i]), df); - lexer->setFont (dfa, styles[i]); - } - // Set defaults last for not changing the defaults of the styles - lexer->setDefaultColor (lexer->color (styles[0])); - lexer->setDefaultPaper (lexer->paper (styles[0])); + for (int i = 0; i < max_style; i++) + { + c = settings.get_color_value (QVariant (lexer->color (styles[i])), m); + lexer->setColor (c, styles[i]); + p = settings.get_color_value (QVariant (lexer->paper (styles[i])), m); + lexer->setPaper (p, styles[i]); + dfa = copy_font_attributes (lexer->font (styles[i]), df); + lexer->setFont (dfa, styles[i]); + } + // Set defaults last for not changing the defaults of the styles + lexer->setDefaultColor (lexer->color (styles[0])); + lexer->setDefaultPaper (lexer->paper (styles[0])); - // Write settings if not just reload the default values - if (def != settings_reload_default_colors_flag) - { - const std::string group_str = group.toStdString (); - lexer->writeSettings (*settings, group_str.c_str ()); - settings->sync (); - } - } - else - { - // Found lexer keys, read the settings - const std::string group_str = group.toStdString (); - lexer->readSettings (*settings, group_str.c_str ()); - } -} + // Write settings if not just reload the default values + if (def != settings_reload_default_colors_flag) + { + const std::string group_str = group.toStdString (); + lexer->writeSettings (settings, group_str.c_str ()); + settings.sync (); + } + } + else + { + // Found lexer keys, read the settings + const std::string group_str = group.toStdString (); + lexer->readSettings (settings, group_str.c_str ()); + } + } #endif -void resource_manager::set_settings (const QString& file) -{ - delete m_settings; - m_settings = new gui_settings (file, QSettings::IniFormat); + bool resource_manager::update_settings_key (const QString& old_key, + const QString& new_key) + { + gui_settings settings; - if (m_settings->status () == QSettings::NoError) - { - // Test usability (force file to be really created) - m_settings->setValue ("dummy", 0); - m_settings->sync (); - } + if (settings.contains (old_key)) + { + QVariant preference = settings.value (old_key); + settings.setValue (new_key, preference); + settings.remove (old_key); + return true; + } - if (! (QFile::exists (m_settings->fileName ()) - && m_settings->isWritable () - && m_settings->status () == QSettings::NoError)) - { - QString msg - = QString (QT_TR_NOOP ("The settings file\n%1\n" - "does not exist and can not be created.\n" - "Make sure you have read and write permissions to\n%2\n\n" - "Octave GUI must be closed now.")); + return false; + } - QMessageBox::critical (nullptr, - QString (QT_TR_NOOP ("Octave Critical Error")), - msg.arg (get_settings_file ()).arg (get_settings_directory ())); - - exit (1); - } - else - m_settings->remove ("dummy"); // Remove test entry -} + void resource_manager::update_network_settings (void) + { + QNetworkProxy proxy; -bool resource_manager::update_settings_key (const QString& old_key, - const QString& new_key) -{ - if (m_settings->contains (old_key)) - { - QVariant preference = m_settings->value (old_key); - m_settings->setValue (new_key, preference); - m_settings->remove (old_key); - return true; - } + // Assume no proxy and empty proxy data + QNetworkProxy::ProxyType proxy_type = QNetworkProxy::NoProxy; + QString scheme; + QString host; + int port = 0; + QString user; + QString pass; + QUrl proxy_url = QUrl (); - return false; -} + gui_settings settings; -bool resource_manager::is_first_run (void) const -{ - return ! QFile::exists (m_settings_file); -} + if (settings.value (global_use_proxy.key, global_use_proxy.def).toBool ()) + { + // Use a proxy, collect all required information + QString proxy_type_string + = settings.value (global_proxy_type.key, global_proxy_type.def).toString (); -void resource_manager::update_network_settings (void) -{ - if (! m_settings) - return; - - QNetworkProxy proxy; - - // Assume no proxy and empty proxy data - QNetworkProxy::ProxyType proxy_type = QNetworkProxy::NoProxy; - QString scheme; - QString host; - int port = 0; - QString user; - QString pass; - QUrl proxy_url = QUrl (); - - if (m_settings->value (global_use_proxy.key, global_use_proxy.def).toBool ()) - { - // Use a proxy, collect all required information - QString proxy_type_string - = m_settings->value (global_proxy_type.key, global_proxy_type.def).toString (); - - // The proxy type for the Qt proxy settings - if (proxy_type_string == "Socks5Proxy") - proxy_type = QNetworkProxy::Socks5Proxy; - else if (proxy_type_string == "HttpProxy") - proxy_type = QNetworkProxy::HttpProxy; + // The proxy type for the Qt proxy settings + if (proxy_type_string == "Socks5Proxy") + proxy_type = QNetworkProxy::Socks5Proxy; + else if (proxy_type_string == "HttpProxy") + proxy_type = QNetworkProxy::HttpProxy; - // The proxy data from the settings - if (proxy_type_string == "HttpProxy" - || proxy_type_string == "Socks5Proxy") - { - host = m_settings->value (global_proxy_host.key, - global_proxy_host.def).toString (); - port = m_settings->value (global_proxy_port.key, - global_proxy_port.def).toInt (); - user = m_settings->value (global_proxy_user.key, - global_proxy_user.def).toString (); - pass = m_settings->value (global_proxy_pass.key, - global_proxy_pass.def).toString (); - if (proxy_type_string == "HttpProxy") - scheme = "http"; - else if (proxy_type_string == "Socks5Proxy") - scheme = "socks5"; + // The proxy data from the settings + if (proxy_type_string == "HttpProxy" + || proxy_type_string == "Socks5Proxy") + { + host = settings.value (global_proxy_host.key, + global_proxy_host.def).toString (); + port = settings.value (global_proxy_port.key, + global_proxy_port.def).toInt (); + user = settings.value (global_proxy_user.key, + global_proxy_user.def).toString (); + pass = settings.value (global_proxy_pass.key, + global_proxy_pass.def).toString (); + if (proxy_type_string == "HttpProxy") + scheme = "http"; + else if (proxy_type_string == "Socks5Proxy") + scheme = "socks5"; - QUrl env_var_url = QUrl (); - proxy_url.setScheme (scheme); - proxy_url.setHost (host); - proxy_url.setPort (port); - if (! user.isEmpty ()) - proxy_url.setUserName (user); - if (! pass.isEmpty ()) - proxy_url.setPassword (pass); - } + QUrl env_var_url = QUrl (); + proxy_url.setScheme (scheme); + proxy_url.setHost (host); + proxy_url.setPort (port); + if (! user.isEmpty ()) + proxy_url.setUserName (user); + if (! pass.isEmpty ()) + proxy_url.setPassword (pass); + } - // The proxy data from environment variables - if (proxy_type_string == global_proxy_all_types.at (2)) - { - const std::array env_vars = + // The proxy data from environment variables + if (proxy_type_string == global_proxy_all_types.at (2)) + { + const std::array env_vars = { "ALL_PROXY", "all_proxy", "HTTP_PROXY", "http_proxy", "HTTPS_PROXY", "https_proxy" }; - unsigned int count = 0; - while (! proxy_url.isValid () && count < env_vars.size ()) - { - proxy_url = QUrl (QString::fromStdString - (sys::env::getenv (env_vars[count]))); - count++; - } + unsigned int count = 0; + while (! proxy_url.isValid () && count < env_vars.size ()) + { + proxy_url = QUrl (QString::fromStdString + (sys::env::getenv (env_vars[count]))); + count++; + } - if (proxy_url.isValid ()) - { - // Found an entry, get the data from the string - scheme = proxy_url.scheme (); - - if (scheme.contains ("socks", Qt::CaseInsensitive)) - proxy_type = QNetworkProxy::Socks5Proxy; - else - proxy_type = QNetworkProxy::HttpProxy; + if (proxy_url.isValid ()) + { + // Found an entry, get the data from the string + scheme = proxy_url.scheme (); - host = proxy_url.host (); - port = proxy_url.port (); - user = proxy_url.userName (); - pass = proxy_url.password (); - } - } - } + if (scheme.contains ("socks", Qt::CaseInsensitive)) + proxy_type = QNetworkProxy::Socks5Proxy; + else + proxy_type = QNetworkProxy::HttpProxy; - // Set proxy for Qt framework - proxy.setType (proxy_type); - proxy.setHostName (host); - proxy.setPort (port); - proxy.setUser (user); - proxy.setPassword (pass); + host = proxy_url.host (); + port = proxy_url.port (); + user = proxy_url.userName (); + pass = proxy_url.password (); + } + } + } - QNetworkProxy::setApplicationProxy (proxy); + // Set proxy for Qt framework + proxy.setType (proxy_type); + proxy.setHostName (host); + proxy.setPort (port); + proxy.setUser (user); + proxy.setPassword (pass); - // Set proxy for curl library if not based on environment variables - std::string proxy_url_str = proxy_url.toString().toStdString (); - sys::env::putenv ("http_proxy", proxy_url_str); - sys::env::putenv ("HTTP_PROXY", proxy_url_str); - sys::env::putenv ("https_proxy", proxy_url_str); - sys::env::putenv ("HTTPS_PROXY", proxy_url_str); -} + QNetworkProxy::setApplicationProxy (proxy); -QIcon resource_manager::icon (const QString& icon_name, bool octave_only, - const QString& icon_alt_name) -{ - if (octave_only) - return QIcon (global_icon_paths.at (ICON_THEME_OCTAVE) + icon_name + ".png"); + // Set proxy for curl library if not based on environment variables + std::string proxy_url_str = proxy_url.toString().toStdString (); + sys::env::putenv ("http_proxy", proxy_url_str); + sys::env::putenv ("HTTP_PROXY", proxy_url_str); + sys::env::putenv ("https_proxy", proxy_url_str); + sys::env::putenv ("HTTPS_PROXY", proxy_url_str); + } - if (QIcon::hasThemeIcon (icon_name)) - return QIcon (QIcon::fromTheme (icon_name)); - else if ((! icon_alt_name.isEmpty ()) && QIcon::hasThemeIcon (icon_alt_name)) - return QIcon (QIcon::fromTheme (icon_alt_name)); - - for (int i = 0; i < m_icon_fallbacks.length (); i++ ) - { - QString icon_file (m_icon_fallbacks.at (i) + icon_name + ".png"); - if (QFile (icon_file).exists ()) - return QIcon (icon_file); - } + // get a list of all available encodings + void resource_manager::get_codecs (QStringList *codecs) + { + // get the codec name for each mib + QList all_mibs = QTextCodec::availableMibs (); + for (auto mib : all_mibs) + { + QTextCodec *c = QTextCodec::codecForMib (mib); + codecs->append (c->name ().toUpper ()); + } - //QIcon::setThemeName (current_theme); - return QIcon (); -} + // Append SYSTEM + codecs->append (QString ("SYSTEM (") + + QString (octave_locale_charset_wrapper ()).toUpper () + + QString (")")); + + // Clean up and sort list of codecs + codecs->removeDuplicates (); + std::sort (codecs->begin (), codecs->end ()); + } -// get a list of all available encodings -void resource_manager::get_codecs (QStringList *codecs) -{ - // get the codec name for each mib - QList all_mibs = QTextCodec::availableMibs (); - for (auto mib : all_mibs) - { - QTextCodec *c = QTextCodec::codecForMib (mib); - codecs->append (c->name ().toUpper ()); - } + // initialize a given combo box with available text encodings + void resource_manager::combo_encoding (QComboBox *combo, + const QString& current) + { + QStringList all_codecs; + get_codecs (&all_codecs); - // Append SYSTEM - codecs->append (QString ("SYSTEM (") + - QString (octave_locale_charset_wrapper ()).toUpper () + - QString (")")); - - // Clean up and sort list of codecs - codecs->removeDuplicates (); - std::sort (codecs->begin (), codecs->end ()); -} + // get the value from the settings file if no current encoding is given + QString enc = current; -// initialize a given combo box with available text encodings -void resource_manager::combo_encoding (QComboBox *combo, - const QString& current) -{ - QStringList all_codecs; - get_codecs (&all_codecs); - - // get the value from the settings file if no current encoding is given - QString enc = current; + // Check for valid codec for the default. If this fails, "SYSTEM" (i.e. + // locale_charset) will be chosen. + // FIXME: The default is "SYSTEM" on all platforms. So can this fallback + // logic be removed completely? + bool default_exists = false; + bool show_system = false; + if (ed_default_enc.def.toString ().startsWith ("SYSTEM")) + show_system = true; + else if (QTextCodec::codecForName (ed_default_enc.def.toString ().toLatin1 ())) + default_exists = true; - // Check for valid codec for the default. If this fails, "SYSTEM" (i.e. - // locale_charset) will be chosen. - // FIXME: The default is "SYSTEM" on all platforms. So can this fallback - // logic be removed completely? - bool default_exists = false; - bool show_system = false; - if (ed_default_enc.def.toString ().startsWith ("SYSTEM")) - show_system = true; - else if (QTextCodec::codecForName (ed_default_enc.def.toString ().toLatin1 ())) - default_exists = true; + QString default_enc = + QString ("SYSTEM (") + + QString (octave_locale_charset_wrapper ()).toUpper () + QString (")"); + + if (enc.isEmpty ()) + { + gui_settings settings; - QString default_enc = - QString ("SYSTEM (") + - QString (octave_locale_charset_wrapper ()).toUpper () + QString (")"); + enc = settings.value (ed_default_enc).toString (); - if (enc.isEmpty ()) - { - enc = m_settings->value (ed_default_enc).toString (); + if (enc.isEmpty ()) // still empty? + { + if (default_exists) + enc = ed_default_enc.def.toString (); + else + enc = default_enc; + } + } - if (enc.isEmpty ()) // still empty? - { - if (default_exists) - enc = ed_default_enc.def.toString (); - else - enc = default_enc; - } - } + // fill the combo box + for (const auto& c : all_codecs) + combo->addItem (c); - // fill the combo box - for (const auto& c : all_codecs) - combo->addItem (c); + // prepend the default item + combo->insertSeparator (0); + if (show_system || ! default_exists) + combo->insertItem (0, default_enc); + else + combo->insertItem (0, ed_default_enc.def.toString ()); - // prepend the default item - combo->insertSeparator (0); - if (show_system || ! default_exists) - combo->insertItem (0, default_enc); - else - combo->insertItem (0, ed_default_enc.def.toString ()); + // select the default or the current one + int idx = combo->findText (enc, Qt::MatchExactly); + if (idx >= 0) + combo->setCurrentIndex (idx); + else + combo->setCurrentIndex (0); + + combo->setMaxVisibleItems (12); + } - // select the default or the current one - int idx = combo->findText (enc, Qt::MatchExactly); - if (idx >= 0) - combo->setCurrentIndex (idx); - else - combo->setCurrentIndex (0); + QPointer + resource_manager::create_tmp_file (const QString& extension, + const QString& contents) + { + QString ext = extension; + if ((! ext.isEmpty ()) && (! ext.startsWith ('.'))) + ext = QString (".") + ext; - combo->setMaxVisibleItems (12); -} - -QPointer -resource_manager::create_tmp_file (const QString& extension, - const QString& contents) -{ - QString ext = extension; - if ((! ext.isEmpty ()) && (! ext.startsWith ('.'))) - ext = QString (".") + ext; + // Create octave dir within temp. dir + QString tmp_dir = QString::fromStdString (sys::env::get_temp_directory ()); - // Create octave dir within temp. dir - QString tmp_dir = QString::fromStdString (sys::env::get_temp_directory ()); + // Create temp. file + QPointer tmp_file + = new QTemporaryFile (tmp_dir + QDir::separator() + + "octave_XXXXXX" + ext, this); - // Create temp. file - QPointer tmp_file - = new QTemporaryFile (tmp_dir + QDir::separator() + - "octave_XXXXXX" + ext, this); + if (tmp_file->open ()) + { + tmp_file->write (contents.toUtf8 ()); + tmp_file->close (); - if (tmp_file->open ()) - { - tmp_file->write (contents.toUtf8 ()); - tmp_file->close (); + m_temporary_files << tmp_file; + } - m_temporary_files << tmp_file; - } - - return tmp_file; -} + return tmp_file; + } -void resource_manager::remove_tmp_file (QPointer tmp_file) -{ - if (tmp_file) - { - if (tmp_file->exists ()) - tmp_file->remove (); + void resource_manager::remove_tmp_file (QPointer tmp_file) + { + if (tmp_file) + { + if (tmp_file->exists ()) + tmp_file->remove (); - m_temporary_files.removeAll (tmp_file); - } -} + m_temporary_files.removeAll (tmp_file); + } + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/resource-manager.h --- a/libgui/src/resource-manager.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/resource-manager.h Tue Dec 06 15:45:27 2022 -0500 @@ -27,7 +27,6 @@ #define octave_resource_manager_h 1 #include -#include #include #if defined (HAVE_QSCINTILLA) # include @@ -35,98 +34,63 @@ #include #include -#include "gui-settings.h" - OCTAVE_BEGIN_NAMESPACE(octave) -class resource_manager : public QObject -{ - Q_OBJECT + class resource_manager : public QObject + { + Q_OBJECT -protected: + protected: public: - resource_manager (void); - - // No copying! + resource_manager (void); - resource_manager (const resource_manager&) = delete; - - resource_manager& operator = (const resource_manager&) = delete; + // No copying! - ~resource_manager (); - - QString get_gui_translation_dir (void); + resource_manager (const resource_manager&) = delete; - void config_translators (QTranslator *qt_tr, QTranslator *qsci_tr, - QTranslator *gui_tr); - void config_icon_theme (void); + resource_manager& operator = (const resource_manager&) = delete; - gui_settings * get_settings (void) const; + ~resource_manager (); - gui_settings * get_default_settings (void) const; - - QString get_settings_directory (void); + QString get_gui_translation_dir (void); - QString get_settings_file (void); - - QString get_default_font_family (void); + void config_translators (QTranslator *qt_tr, QTranslator *qsci_tr, + QTranslator *gui_tr); - QStringList get_default_font (void); + QPointer + create_tmp_file (const QString& extension = QString (), + const QString& contents = QString ()); - QPointer - create_tmp_file (const QString& extension = QString (), - const QString& contents = QString ()); - - void remove_tmp_file (QPointer tmp_file); - - void reload_settings (void); + void remove_tmp_file (QPointer tmp_file); #if defined (HAVE_QSCINTILLA) - int get_valid_lexer_styles (QsciLexer *lexer, int *styles); - void read_lexer_settings (QsciLexer *lexer, gui_settings *settings, - int mode = 0, int def = 0); + int get_valid_lexer_styles (QsciLexer *lexer, int *styles); + void read_lexer_settings (QsciLexer *lexer, int mode = 0, int def = 0); #endif - void set_settings (const QString& file); - - bool update_settings_key (const QString& new_key, const QString& old_key); + bool update_settings_key (const QString& new_key, const QString& old_key); - bool is_first_run (void) const; - - void update_network_settings (void); + void update_network_settings (void); - QIcon icon (const QString& icon_name, bool octave_only = false, - const QString& icon_alt_name = QString ()); + void get_codecs (QStringList *codecs); - void get_codecs (QStringList *codecs); + void combo_encoding (QComboBox *combo, const QString& current = QString ()); - void combo_encoding (QComboBox *combo, const QString& current = QString ()); - -private: + private: - /*! - * Copys the attributes bold, italic and underline from QFont - * @p attr to the font @p base and returns the result without - * changing @p base, - * @param attr QFont with the desired attributes - * @param base QFont with desired family and size - */ - QFont copy_font_attributes (const QFont& attr, const QFont& base) const; - - QString m_settings_directory; + /*! + * Copys the attributes bold, italic and underline from QFont + * @p attr to the font @p base and returns the result without + * changing @p base, + * @param attr QFont with the desired attributes + * @param base QFont with desired family and size + */ + QFont copy_font_attributes (const QFont& attr, const QFont& base) const; - QString m_settings_file; - - gui_settings *m_settings; - - gui_settings *m_default_settings; - - QList m_temporary_files; - - QStringList m_icon_fallbacks; -}; + QList m_temporary_files; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/set-path-dialog.cc --- a/libgui/src/set-path-dialog.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/set-path-dialog.cc Tue Dec 06 15:45:27 2022 -0500 @@ -50,7 +50,7 @@ #include #include "gui-preferences-pd.h" -#include "octave-qobject.h" +#include "gui-settings.h" #include "octave-qtutils.h" #include "set-path-dialog.h" #include "set-path-model.h" @@ -59,256 +59,255 @@ OCTAVE_BEGIN_NAMESPACE(octave) -set_path_dialog::set_path_dialog (QWidget *parent, base_qobject& oct_qobj) -: QDialog (parent), m_octave_qobj (oct_qobj) -{ - setWindowTitle (tr ("Set Path")); + set_path_dialog::set_path_dialog (QWidget *parent) + : QDialog (parent) + { + setWindowTitle (tr ("Set Path")); - set_path_model *model = new set_path_model (this); + set_path_model *model = new set_path_model (this); - m_info_label = new QLabel (tr ("All changes take effect immediately.")); + m_info_label = new QLabel (tr ("All changes take effect immediately.")); - m_add_folder_button = new QPushButton (tr ("Add Folder...")); + m_add_folder_button = new QPushButton (tr ("Add Folder...")); - QMenu *add_dir_menu = new QMenu (); - m_add_folder_button->setMenu (add_dir_menu); - add_dir_menu->addAction (tr ("Single Folder"), - this, &set_path_dialog::add_dir); - add_dir_menu->addAction (tr ("Folder With Subfolders"), - this, &set_path_dialog::add_dir_subdirs); + QMenu *add_dir_menu = new QMenu (); + m_add_folder_button->setMenu (add_dir_menu); + add_dir_menu->addAction (tr ("Single Folder"), + this, &set_path_dialog::add_dir); + add_dir_menu->addAction (tr ("Folder With Subfolders"), + this, &set_path_dialog::add_dir_subdirs); - m_move_to_top_button = new QPushButton (tr ("Move to Top")); - m_move_to_bottom_button = new QPushButton (tr ("Move to Bottom")); - m_move_up_button = new QPushButton (tr ("Move Up")); - m_move_down_button = new QPushButton (tr ("Move Down")); - m_remove_button = new QPushButton (tr ("Remove")); + m_move_to_top_button = new QPushButton (tr ("Move to Top")); + m_move_to_bottom_button = new QPushButton (tr ("Move to Bottom")); + m_move_up_button = new QPushButton (tr ("Move Up")); + m_move_down_button = new QPushButton (tr ("Move Down")); + m_remove_button = new QPushButton (tr ("Remove")); - m_reload_button = new QPushButton (tr ("Reload")); - m_save_button = new QPushButton (tr ("Save")); + m_reload_button = new QPushButton (tr ("Reload")); + m_save_button = new QPushButton (tr ("Save")); - m_revert_button = new QPushButton (tr ("Revert")); + m_revert_button = new QPushButton (tr ("Revert")); - QMenu *revert_menu = new QMenu (); - m_revert_button->setMenu (revert_menu); - revert_menu->addAction (tr ("Revert Last Change"), - model, &set_path_model::revert_last); - revert_menu->addAction (tr ("Revert All Changes"), - model, &set_path_model::revert); + QMenu *revert_menu = new QMenu (); + m_revert_button->setMenu (revert_menu); + revert_menu->addAction (tr ("Revert Last Change"), + model, &set_path_model::revert_last); + revert_menu->addAction (tr ("Revert All Changes"), + model, &set_path_model::revert); - m_save_button->setFocus (); + m_save_button->setFocus (); - connect (m_remove_button, &QPushButton::clicked, - this, &set_path_dialog::rm_dir); + connect (m_remove_button, &QPushButton::clicked, + this, &set_path_dialog::rm_dir); - connect (m_move_to_top_button, &QPushButton::clicked, - this, &set_path_dialog::move_dir_top); + connect (m_move_to_top_button, &QPushButton::clicked, + this, &set_path_dialog::move_dir_top); - connect (m_move_to_bottom_button, &QPushButton::clicked, - this, &set_path_dialog::move_dir_bottom); + connect (m_move_to_bottom_button, &QPushButton::clicked, + this, &set_path_dialog::move_dir_bottom); - connect (m_move_up_button, &QPushButton::clicked, - this, &set_path_dialog::move_dir_up); + connect (m_move_up_button, &QPushButton::clicked, + this, &set_path_dialog::move_dir_up); - connect (m_move_down_button, &QPushButton::clicked, - this, &set_path_dialog::move_dir_down); + connect (m_move_down_button, &QPushButton::clicked, + this, &set_path_dialog::move_dir_down); - connect (m_reload_button, &QPushButton::clicked, - model, &set_path_model::path_to_model); + connect (m_reload_button, &QPushButton::clicked, + model, &set_path_model::path_to_model); - connect (m_save_button, &QPushButton::clicked, - model, &set_path_model::save); + connect (m_save_button, &QPushButton::clicked, + model, &set_path_model::save); - // Any interpreter_event signal from a set_path_model object is - // handled the same as for the parent set_path_dialog object. + // Any interpreter_event signal from a set_path_model object is + // handled the same as for the parent set_path_dialog object. - connect (model, QOverload::of (&set_path_model::interpreter_event), - this, QOverload::of (&set_path_dialog::interpreter_event)); + connect (model, QOverload::of (&set_path_model::interpreter_event), + this, QOverload::of (&set_path_dialog::interpreter_event)); - connect (model, QOverload::of (&set_path_model::interpreter_event), - this, QOverload::of (&set_path_dialog::interpreter_event)); + connect (model, QOverload::of (&set_path_model::interpreter_event), + this, QOverload::of (&set_path_dialog::interpreter_event)); - m_path_list = new QListView (this); - m_path_list->setWordWrap (false); - m_path_list->setModel (model); - m_path_list->setSelectionBehavior (QAbstractItemView::SelectRows); - m_path_list->setSelectionMode (QAbstractItemView::ExtendedSelection); - m_path_list->setAlternatingRowColors (true); - m_path_list->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_path_list = new QListView (this); + m_path_list->setWordWrap (false); + m_path_list->setModel (model); + m_path_list->setSelectionBehavior (QAbstractItemView::SelectRows); + m_path_list->setSelectionMode (QAbstractItemView::ExtendedSelection); + m_path_list->setAlternatingRowColors (true); + m_path_list->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - // layout everything - QDialogButtonBox *button_box = new QDialogButtonBox (Qt::Horizontal); - button_box->addButton (m_save_button, QDialogButtonBox::ActionRole); - button_box->addButton (m_reload_button, QDialogButtonBox::ActionRole); + // layout everything + QDialogButtonBox *button_box = new QDialogButtonBox (Qt::Horizontal); + button_box->addButton (m_save_button, QDialogButtonBox::ActionRole); + button_box->addButton (m_reload_button, QDialogButtonBox::ActionRole); - // add dialog close button - m_close_button = button_box->addButton (QDialogButtonBox::Close); - connect (button_box, &QDialogButtonBox::rejected, - this, &set_path_dialog::close); + // add dialog close button + m_close_button = button_box->addButton (QDialogButtonBox::Close); + connect (button_box, &QDialogButtonBox::rejected, + this, &set_path_dialog::close); - button_box->addButton (m_revert_button, QDialogButtonBox::ActionRole); + button_box->addButton (m_revert_button, QDialogButtonBox::ActionRole); - // path edit options - QDialogButtonBox *path_edit_layout = new QDialogButtonBox (Qt::Vertical); - path_edit_layout->addButton (m_add_folder_button, QDialogButtonBox::ActionRole); - path_edit_layout->addButton (m_move_to_top_button, QDialogButtonBox::ActionRole); - path_edit_layout->addButton (m_move_up_button, QDialogButtonBox::ActionRole); - path_edit_layout->addButton (m_move_down_button, QDialogButtonBox::ActionRole); - path_edit_layout->addButton (m_move_to_bottom_button, QDialogButtonBox::ActionRole); - path_edit_layout->addButton (m_remove_button, QDialogButtonBox::ActionRole); + // path edit options + QDialogButtonBox *path_edit_layout = new QDialogButtonBox (Qt::Vertical); + path_edit_layout->addButton (m_add_folder_button, QDialogButtonBox::ActionRole); + path_edit_layout->addButton (m_move_to_top_button, QDialogButtonBox::ActionRole); + path_edit_layout->addButton (m_move_up_button, QDialogButtonBox::ActionRole); + path_edit_layout->addButton (m_move_down_button, QDialogButtonBox::ActionRole); + path_edit_layout->addButton (m_move_to_bottom_button, QDialogButtonBox::ActionRole); + path_edit_layout->addButton (m_remove_button, QDialogButtonBox::ActionRole); - // main layout - QHBoxLayout *main_hboxlayout = new QHBoxLayout; - main_hboxlayout->addWidget(path_edit_layout); - main_hboxlayout->addWidget(m_path_list); + // main layout + QHBoxLayout *main_hboxlayout = new QHBoxLayout; + main_hboxlayout->addWidget(path_edit_layout); + main_hboxlayout->addWidget(m_path_list); - QGridLayout *main_layout = new QGridLayout; - main_layout->addWidget (m_info_label, 0, 0); - main_layout->addLayout (main_hboxlayout, 1, 0); - main_layout->addWidget (button_box, 2, 0); + QGridLayout *main_layout = new QGridLayout; + main_layout->addWidget (m_info_label, 0, 0); + main_layout->addLayout (main_hboxlayout, 1, 0); + main_layout->addWidget (button_box, 2, 0); - setLayout (main_layout); + setLayout (main_layout); + + gui_settings settings; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - restoreGeometry ( - settings->value(pd_geometry.key).toByteArray()); -} + restoreGeometry (settings.value(pd_geometry.key).toByteArray()); + } -void set_path_dialog::update_model (void) -{ - set_path_model *m = static_cast (m_path_list->model ()); - m->path_to_model (); -} + void set_path_dialog::update_model (void) + { + set_path_model *m = static_cast (m_path_list->model ()); + m->path_to_model (); + } -void set_path_dialog::add_dir_common (bool subdirs) -{ - QString dir - = QFileDialog::getExistingDirectory (this, tr ("Open Directory"), - "", - (QFileDialog::ShowDirsOnly - | QFileDialog::DontResolveSymlinks)); + void set_path_dialog::add_dir_common (bool subdirs) + { + QString dir + = QFileDialog::getExistingDirectory (this, tr ("Open Directory"), + "", + (QFileDialog::ShowDirsOnly + | QFileDialog::DontResolveSymlinks)); - if (! dir.isEmpty ()) - { - if (subdirs) - { - // Use existing method mofifying load path and updating dialog - // instead of adding string and updating load path - emit modify_path_signal (QStringList (dir), false, true); - } - else - { - set_path_model *m - = static_cast (m_path_list->model ()); - m->add_dir (dir); - } - } -} + if (! dir.isEmpty ()) + { + if (subdirs) + { + // Use existing method mofifying load path and updating dialog + // instead of adding string and updating load path + emit modify_path_signal (QStringList (dir), false, true); + } + else + { + set_path_model *m + = static_cast (m_path_list->model ()); + m->add_dir (dir); + } + } + } -void set_path_dialog::add_dir(void) -{ - add_dir_common (false); -} + void set_path_dialog::add_dir(void) + { + add_dir_common (false); + } -void set_path_dialog::add_dir_subdirs (void) -{ - add_dir_common (true); -} + void set_path_dialog::add_dir_subdirs (void) + { + add_dir_common (true); + } -void set_path_dialog::rm_dir (void) -{ - set_path_model *m = static_cast (m_path_list->model ()); - QItemSelectionModel *selmodel = m_path_list->selectionModel (); - QModelIndexList indexlist = selmodel->selectedIndexes(); - m->rm_dir (indexlist); + void set_path_dialog::rm_dir (void) + { + set_path_model *m = static_cast (m_path_list->model ()); + QItemSelectionModel *selmodel = m_path_list->selectionModel (); + QModelIndexList indexlist = selmodel->selectedIndexes(); + m->rm_dir (indexlist); - selmodel->clearSelection (); -} + selmodel->clearSelection (); + } -void set_path_dialog::move_dir_up (void) -{ - set_path_model *m = static_cast (m_path_list->model ()); - QItemSelectionModel *selmodel = m_path_list->selectionModel (); - QModelIndexList indexlist = selmodel->selectedIndexes(); - m->move_dir_up (indexlist); + void set_path_dialog::move_dir_up (void) + { + set_path_model *m = static_cast (m_path_list->model ()); + QItemSelectionModel *selmodel = m_path_list->selectionModel (); + QModelIndexList indexlist = selmodel->selectedIndexes(); + m->move_dir_up (indexlist); - // Update selection and view - selmodel->clearSelection (); - int min_row = m->rowCount () - 1; - for (int i = 0; i < indexlist.length (); i++) - { - int new_row = std::max (indexlist.at (i).row () - 1, 0); - min_row = std::min (min_row, new_row); - selmodel->select (m->index (new_row), QItemSelectionModel::Select); - } + // Update selection and view + selmodel->clearSelection (); + int min_row = m->rowCount () - 1; + for (int i = 0; i < indexlist.length (); i++) + { + int new_row = std::max (indexlist.at (i).row () - 1, 0); + min_row = std::min (min_row, new_row); + selmodel->select (m->index (new_row), QItemSelectionModel::Select); + } - m_path_list->scrollTo (m->index (min_row)); -} + m_path_list->scrollTo (m->index (min_row)); + } -void set_path_dialog::move_dir_down (void) -{ - set_path_model *m = static_cast (m_path_list->model ()); - QItemSelectionModel *selmodel = m_path_list->selectionModel (); - QModelIndexList indexlist = selmodel->selectedIndexes(); - m->move_dir_down (indexlist); + void set_path_dialog::move_dir_down (void) + { + set_path_model *m = static_cast (m_path_list->model ()); + QItemSelectionModel *selmodel = m_path_list->selectionModel (); + QModelIndexList indexlist = selmodel->selectedIndexes(); + m->move_dir_down (indexlist); - // Update selection and view - selmodel->clearSelection (); - int max_row = 0; - for (int i = 0; i < indexlist.length (); i++) - { - int new_row = std::min (indexlist.at (i).row () + 1, m->rowCount () - 1); - max_row = std::max (max_row, new_row); - selmodel->select (m->index (new_row), QItemSelectionModel::Select); - } + // Update selection and view + selmodel->clearSelection (); + int max_row = 0; + for (int i = 0; i < indexlist.length (); i++) + { + int new_row = std::min (indexlist.at (i).row () + 1, m->rowCount () - 1); + max_row = std::max (max_row, new_row); + selmodel->select (m->index (new_row), QItemSelectionModel::Select); + } - m_path_list->scrollTo (m->index (max_row)); -} + m_path_list->scrollTo (m->index (max_row)); + } -void set_path_dialog::move_dir_top (void) -{ - set_path_model *m = static_cast (m_path_list->model ()); - QItemSelectionModel *selmodel = m_path_list->selectionModel (); - QModelIndexList indexlist = selmodel->selectedIndexes(); - m->move_dir_top (indexlist); + void set_path_dialog::move_dir_top (void) + { + set_path_model *m = static_cast (m_path_list->model ()); + QItemSelectionModel *selmodel = m_path_list->selectionModel (); + QModelIndexList indexlist = selmodel->selectedIndexes(); + m->move_dir_top (indexlist); - // Update selection and view - selmodel->clearSelection (); - for (int i = 0; i < indexlist.length (); i++) - selmodel->select (m->index (i), QItemSelectionModel::Select); + // Update selection and view + selmodel->clearSelection (); + for (int i = 0; i < indexlist.length (); i++) + selmodel->select (m->index (i), QItemSelectionModel::Select); - m_path_list->scrollTo (m->index (0)); -} + m_path_list->scrollTo (m->index (0)); + } -void set_path_dialog::move_dir_bottom (void) -{ - set_path_model *m = static_cast (m_path_list->model ()); - QItemSelectionModel *selmodel = m_path_list->selectionModel (); - QModelIndexList indexlist = selmodel->selectedIndexes(); - m->move_dir_bottom (indexlist); + void set_path_dialog::move_dir_bottom (void) + { + set_path_model *m = static_cast (m_path_list->model ()); + QItemSelectionModel *selmodel = m_path_list->selectionModel (); + QModelIndexList indexlist = selmodel->selectedIndexes(); + m->move_dir_bottom (indexlist); - // Update selection and view - selmodel->clearSelection (); - int row_count = m->rowCount (); - for (int i = 0; i < indexlist.length (); i++) - selmodel->select (m->index (row_count - 1 - i), - QItemSelectionModel::Select); + // Update selection and view + selmodel->clearSelection (); + int row_count = m->rowCount (); + for (int i = 0; i < indexlist.length (); i++) + selmodel->select (m->index (row_count - 1 - i), + QItemSelectionModel::Select); - m_path_list->scrollTo (m->index (row_count - 1)); -} + m_path_list->scrollTo (m->index (row_count - 1)); + } + + void set_path_dialog::save_settings (void) + { + gui_settings settings; -void set_path_dialog::save_settings () -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - settings->setValue (pd_geometry.key, saveGeometry ()); -} + settings.setValue (pd_geometry.key, saveGeometry ()); + } -void set_path_dialog::closeEvent (QCloseEvent *e) -{ - save_settings (); + void set_path_dialog::closeEvent (QCloseEvent *e) + { + save_settings (); - QWidget::closeEvent (e); -} + QWidget::closeEvent (e); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/set-path-dialog.h --- a/libgui/src/set-path-dialog.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/set-path-dialog.h Tue Dec 06 15:45:27 2022 -0500 @@ -41,79 +41,75 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; + class set_path_dialog : public QDialog + { + Q_OBJECT -class set_path_dialog : public QDialog -{ - Q_OBJECT - -public: + public: - // You must call update_model to fully initialize the path displayed - // in the dialog. That may only be done after the intepreter_event - // signal connections are made to the Octave interpreter. + // You must call update_model to fully initialize the path displayed + // in the dialog. That may only be done after the intepreter_event + // signal connections are made to the Octave interpreter. - set_path_dialog (QWidget *parent, base_qobject& oct_qobj); + set_path_dialog (QWidget *parent); - virtual ~set_path_dialog (void) = default; + virtual ~set_path_dialog (void) = default; - void save_settings (void); + void save_settings (void); -signals: + signals: - //! Emitted, when the path has to be modified + //! Emitted, when the path has to be modified - void modify_path_signal (const QStringList& dir_list, bool rm, - bool subdirs); + void modify_path_signal (const QStringList& dir_list, bool rm, + bool subdirs); - void interpreter_event (const fcn_callback& fcn); - void interpreter_event (const meth_callback& meth); + void interpreter_event (const fcn_callback& fcn); + void interpreter_event (const meth_callback& meth); -public slots: + public slots: - void update_model (void); + void update_model (void); -protected: + protected: - void closeEvent (QCloseEvent *e); + void closeEvent (QCloseEvent *e); -private slots: + private slots: - void add_dir (void); - void add_dir_subdirs (void); + void add_dir (void); + void add_dir_subdirs (void); - void rm_dir (void); - - void move_dir_up (void); + void rm_dir (void); - void move_dir_down (void); + void move_dir_up (void); - void move_dir_top (void); + void move_dir_down (void); - void move_dir_bottom (void); + void move_dir_top (void); -private: + void move_dir_bottom (void); - void add_dir_common (bool subdirs); + private: - base_qobject& m_octave_qobj; + void add_dir_common (bool subdirs); - QLabel *m_info_label; - QPushButton *m_reload_button; - QPushButton *m_save_button; - QPushButton *m_close_button; - QPushButton *m_revert_button; - QPushButton *m_revert_last_button; + QLabel *m_info_label; + QPushButton *m_reload_button; + QPushButton *m_save_button; + QPushButton *m_close_button; + QPushButton *m_revert_button; + QPushButton *m_revert_last_button; - QListView *m_path_list; + QListView *m_path_list; - QPushButton *m_add_folder_button; - QPushButton *m_move_to_top_button; - QPushButton *m_move_to_bottom_button; - QPushButton *m_move_up_button; - QPushButton *m_move_down_button; - QPushButton *m_remove_button; -}; + QPushButton *m_add_folder_button; + QPushButton *m_move_to_top_button; + QPushButton *m_move_to_bottom_button; + QPushButton *m_move_up_button; + QPushButton *m_move_down_button; + QPushButton *m_remove_button; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/settings-dialog.cc --- a/libgui/src/settings-dialog.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/settings-dialog.cc Tue Dec 06 15:45:27 2022 -0500 @@ -72,1547 +72,1547 @@ OCTAVE_BEGIN_NAMESPACE(octave) -settings_dialog::settings_dialog (QWidget *p, base_qobject& oct_qobj, - const QString& desired_tab) -: QDialog (p), Ui::settings_dialog (), m_octave_qobj (oct_qobj) -{ - setupUi (this); + settings_dialog::settings_dialog (QWidget *p, base_qobject& oct_qobj, + const QString& desired_tab) + : QDialog (p), Ui::settings_dialog (), m_octave_qobj (oct_qobj) + { + setupUi (this); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; + + // look for available language files and the actual settings + resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + QString qm_dir_name = rmgr.get_gui_translation_dir (); - if (! settings) - { - QMessageBox msgBox - (QMessageBox::Warning, tr ("Octave Preferences"), - tr ("Unable to save preferences. Missing preferences file or unknown directory.")); - - msgBox.exec (); + QDir qm_dir (qm_dir_name); + QFileInfoList qm_files = qm_dir.entryInfoList (QStringList ("*.qm"), + QDir::Files | QDir::Readable, QDir::Name); - return; - } - - // look for available language files and the actual settings - QString qm_dir_name = rmgr.get_gui_translation_dir (); - QDir qm_dir (qm_dir_name); - QFileInfoList qm_files = qm_dir.entryInfoList (QStringList ("*.qm"), - QDir::Files | QDir::Readable, QDir::Name); + for (int i = 0; i < qm_files.length (); i++) // insert available languages + comboBox_language->addItem (qm_files.at (i).baseName ()); + // System at beginning + comboBox_language->insertItem (0, tr ("System setting")); + comboBox_language->insertSeparator (1); // separator after System + QString language = settings.value (global_language.key, + global_language.def).toString (); + if (language == global_language.def.toString ()) + language = tr ("System setting"); + int selected = comboBox_language->findText (language); + if (selected >= 0) + comboBox_language->setCurrentIndex (selected); + else + comboBox_language->setCurrentIndex (0); // System is default - for (int i = 0; i < qm_files.length (); i++) // insert available languages - comboBox_language->addItem (qm_files.at (i).baseName ()); - // System at beginning - comboBox_language->insertItem (0, tr ("System setting")); - comboBox_language->insertSeparator (1); // separator after System - QString language = settings->value (global_language.key, - global_language.def).toString (); - if (language == global_language.def.toString ()) - language = tr ("System setting"); - int selected = comboBox_language->findText (language); - if (selected >= 0) - comboBox_language->setCurrentIndex (selected); - else - comboBox_language->setCurrentIndex (0); // System is default + // Global style + QStringList styles = QStyleFactory::keys(); + styles.append (global_extra_styles); + combo_styles->addItems (styles); + combo_styles->insertItem (0, global_style.def.toString ()); + combo_styles->insertSeparator (1); + QString current_style = settings.value (global_style).toString (); + if (current_style == global_style.def.toString ()) + current_style = global_style.def.toString (); + selected = combo_styles->findText (current_style); + if (selected >= 0) + combo_styles->setCurrentIndex (selected); + else + combo_styles->setCurrentIndex (0); + + // icon size and theme + QButtonGroup *icon_size_group = new QButtonGroup (this); + icon_size_group->addButton (icon_size_small); + icon_size_group->addButton (icon_size_normal); + icon_size_group->addButton (icon_size_large); + int icon_size = settings.value (global_icon_size).toInt (); + icon_size_normal->setChecked (true); // the default + icon_size_small->setChecked (icon_size < 0); + icon_size_large->setChecked (icon_size > 0); + combo_box_icon_theme->addItems (global_all_icon_theme_names); + int theme = settings.value (global_icon_theme_index.key).toInt (); + combo_box_icon_theme->setCurrentIndex (theme); - // Global style - QStringList styles = QStyleFactory::keys(); - styles.append (global_extra_styles); - combo_styles->addItems (styles); - combo_styles->insertItem (0, global_style.def.toString ()); - combo_styles->insertSeparator (1); - QString current_style = settings->value (global_style).toString (); - if (current_style == global_style.def.toString ()) - current_style = global_style.def.toString (); - selected = combo_styles->findText (current_style); - if (selected >= 0) - combo_styles->setCurrentIndex (selected); - else - combo_styles->setCurrentIndex (0); + // which icon has to be selected + QButtonGroup *icon_group = new QButtonGroup (this); + icon_group->addButton (general_icon_octave); + icon_group->addButton (general_icon_graphic); + icon_group->addButton (general_icon_letter); + QString widget_icon_set = + settings.value (dw_icon_set).toString (); + general_icon_octave->setChecked (true); // the default (if invalid set) + general_icon_octave->setChecked (widget_icon_set == "NONE"); + general_icon_graphic->setChecked (widget_icon_set == "GRAPHIC"); + general_icon_letter->setChecked (widget_icon_set == "LETTER"); - // icon size and theme - QButtonGroup *icon_size_group = new QButtonGroup (this); - icon_size_group->addButton (icon_size_small); - icon_size_group->addButton (icon_size_normal); - icon_size_group->addButton (icon_size_large); - int icon_size = settings->value (global_icon_size).toInt (); - icon_size_normal->setChecked (true); // the default - icon_size_small->setChecked (icon_size < 0); - icon_size_large->setChecked (icon_size > 0); - combo_box_icon_theme->addItems (global_all_icon_theme_names); - int theme = settings->value (global_icon_theme_index.key).toInt (); - combo_box_icon_theme->setCurrentIndex (theme); + // custom title bar of dock widget + QColor bg_color = settings.value (dw_title_bg_color).value (); + m_widget_title_bg_color = new color_picker (bg_color); + m_widget_title_bg_color->setEnabled (false); + layout_widget_bgtitle->addWidget (m_widget_title_bg_color, 0); - // which icon has to be selected - QButtonGroup *icon_group = new QButtonGroup (this); - icon_group->addButton (general_icon_octave); - icon_group->addButton (general_icon_graphic); - icon_group->addButton (general_icon_letter); - QString widget_icon_set = - settings->value (dw_icon_set).toString (); - general_icon_octave->setChecked (true); // the default (if invalid set) - general_icon_octave->setChecked (widget_icon_set == "NONE"); - general_icon_graphic->setChecked (widget_icon_set == "GRAPHIC"); - general_icon_letter->setChecked (widget_icon_set == "LETTER"); + connect (cb_widget_custom_style, &QCheckBox::toggled, + m_widget_title_bg_color, &color_picker::setEnabled); + + QColor bg_color_active = settings.value (dw_title_bg_color_active).value (); + m_widget_title_bg_color_active = new color_picker (bg_color_active); + m_widget_title_bg_color_active->setEnabled (false); + layout_widget_bgtitle_active->addWidget (m_widget_title_bg_color_active, 0); + + connect (cb_widget_custom_style, &QCheckBox::toggled, + m_widget_title_bg_color_active, &color_picker::setEnabled); - // custom title bar of dock widget - QColor bg_color = settings->value (dw_title_bg_color).value (); - m_widget_title_bg_color = new color_picker (bg_color); - m_widget_title_bg_color->setEnabled (false); - layout_widget_bgtitle->addWidget (m_widget_title_bg_color, 0); + QColor fg_color = settings.value (dw_title_fg_color).value (); + m_widget_title_fg_color = new color_picker (fg_color); + m_widget_title_fg_color->setEnabled (false); + layout_widget_fgtitle->addWidget (m_widget_title_fg_color, 0); + + connect (cb_widget_custom_style, &QCheckBox::toggled, + m_widget_title_fg_color, &color_picker::setEnabled); - connect (cb_widget_custom_style, &QCheckBox::toggled, - m_widget_title_bg_color, &color_picker::setEnabled); + QColor fg_color_active = settings.value (dw_title_fg_color_active).value (); + m_widget_title_fg_color_active = new color_picker (fg_color_active); + m_widget_title_fg_color_active->setEnabled (false); + layout_widget_fgtitle_active->addWidget (m_widget_title_fg_color_active, 0); - QColor bg_color_active = settings->value (dw_title_bg_color_active).value (); - m_widget_title_bg_color_active = new color_picker (bg_color_active); - m_widget_title_bg_color_active->setEnabled (false); - layout_widget_bgtitle_active->addWidget (m_widget_title_bg_color_active, 0); + connect (cb_widget_custom_style, &QCheckBox::toggled, + m_widget_title_fg_color_active, &color_picker::setEnabled); - connect (cb_widget_custom_style, &QCheckBox::toggled, - m_widget_title_bg_color_active, &color_picker::setEnabled); + sb_3d_title->setValue (settings.value (dw_title_3d.key, + dw_title_3d.def).toInt ()); + cb_widget_custom_style->setChecked (settings.value (dw_title_custom_style).toBool ()); - QColor fg_color = settings->value (dw_title_fg_color).value (); - m_widget_title_fg_color = new color_picker (fg_color); - m_widget_title_fg_color->setEnabled (false); - layout_widget_fgtitle->addWidget (m_widget_title_fg_color, 0); - - connect (cb_widget_custom_style, &QCheckBox::toggled, - m_widget_title_fg_color, &color_picker::setEnabled); - - QColor fg_color_active = settings->value (dw_title_fg_color_active).value (); - m_widget_title_fg_color_active = new color_picker (fg_color_active); - m_widget_title_fg_color_active->setEnabled (false); - layout_widget_fgtitle_active->addWidget (m_widget_title_fg_color_active, 0); + // Native file dialogs. + // FIXME: This preference can be deprecated / removed if all display + // managers, especially KDE, run those dialogs without hangs or + // delays from the start (bug #54607). + cb_use_native_file_dialogs->setChecked (settings.value (global_use_native_dialogs).toBool ()); - connect (cb_widget_custom_style, &QCheckBox::toggled, - m_widget_title_fg_color_active, &color_picker::setEnabled); + // Cursor blinking: consider old terminal related setting if not yet set + // FIXME: This pref. can be deprecated / removed if Qt adds support for + // getting the cursor blink preferences from all OS environments + if (settings.contains (global_cursor_blinking.key)) + { + // Preference exists, read its value + cb_cursor_blinking->setChecked (settings.value + (global_cursor_blinking.key, global_cursor_blinking.def).toBool ()); + } + else + { + // Pref. does not exist, so take old terminal related pref. + cb_cursor_blinking->setChecked (settings.value + (cs_cursor_blinking.key, cs_cursor_blinking.def).toBool ()); + } - sb_3d_title->setValue (settings->value (dw_title_3d.key, - dw_title_3d.def).toInt ()); - cb_widget_custom_style->setChecked (settings->value (dw_title_custom_style).toBool ()); - - // Native file dialogs. - // FIXME: This preference can be deprecated / removed if all display - // managers, especially KDE, run those dialogs without hangs or - // delays from the start (bug #54607). - cb_use_native_file_dialogs->setChecked (settings->value (global_use_native_dialogs).toBool ()); + // focus follows mouse + cb_focus_follows_mouse->setChecked ( + settings.value (dw_focus_follows_mouse).toBool ()); - // Cursor blinking: consider old terminal related setting if not yet set - // FIXME: This pref. can be deprecated / removed if Qt adds support for - // getting the cursor blink preferences from all OS environments - if (settings->contains (global_cursor_blinking.key)) - { - // Preference exists, read its value - cb_cursor_blinking->setChecked (settings->value - (global_cursor_blinking.key, global_cursor_blinking.def).toBool ()); - } - else - { - // Pref. does not exist, so take old terminal related pref. - cb_cursor_blinking->setChecked (settings->value - (cs_cursor_blinking.key, cs_cursor_blinking.def).toBool ()); - } + // prompt on exit + cb_prompt_to_exit->setChecked ( + settings.value (global_prompt_to_exit.key, global_prompt_to_exit.def).toBool ()); + + // Main status bar + cb_status_bar->setChecked ( + settings.value (global_status_bar.key, global_status_bar.def).toBool ()); - // focus follows mouse - cb_focus_follows_mouse->setChecked ( - settings->value (dw_focus_follows_mouse).toBool ()); + // Octave startup + cb_restore_octave_dir->setChecked ( + settings.value (global_restore_ov_dir.key, global_restore_ov_dir.def).toBool ()); + le_octave_dir->setText (settings.value (global_ov_startup_dir.key, + global_ov_startup_dir.def).toString ()); - // prompt on exit - cb_prompt_to_exit->setChecked ( - settings->value (global_prompt_to_exit.key, global_prompt_to_exit.def).toBool ()); + connect (pb_octave_dir, &QPushButton::pressed, + this, &settings_dialog::get_octave_dir); - // Main status bar - cb_status_bar->setChecked ( - settings->value (global_status_bar.key, global_status_bar.def).toBool ()); + // + // editor + // + useCustomFileEditor->setChecked ( + settings.value (global_use_custom_editor.key, global_use_custom_editor.def).toBool ()); + customFileEditor->setText ( + settings.value (global_custom_editor.key, global_custom_editor.def).toString ()); + editor_showLineNumbers->setChecked (settings.value (ed_show_line_numbers).toBool ()); + editor_linenr_size->setValue (settings.value (ed_line_numbers_size).toInt ()); - // Octave startup - cb_restore_octave_dir->setChecked ( - settings->value (global_restore_ov_dir.key, global_restore_ov_dir.def).toBool ()); - le_octave_dir->setText (settings->value (global_ov_startup_dir.key, - global_ov_startup_dir.def).toString ()); + rmgr.combo_encoding (editor_combo_encoding); - connect (pb_octave_dir, &QPushButton::pressed, - this, &settings_dialog::get_octave_dir); - - // - // editor - // - useCustomFileEditor->setChecked ( - settings->value (global_use_custom_editor.key, global_use_custom_editor.def).toBool ()); - customFileEditor->setText ( - settings->value (global_custom_editor.key, global_custom_editor.def).toString ()); - editor_showLineNumbers->setChecked (settings->value (ed_show_line_numbers).toBool ()); - editor_linenr_size->setValue (settings->value (ed_line_numbers_size).toInt ()); - - rmgr.combo_encoding (editor_combo_encoding); + editor_highlightCurrentLine->setChecked (settings.value (ed_highlight_current_line).toBool ()); + editor_long_line_marker->setChecked (settings.value (ed_long_line_marker).toBool ()); + bool long_line = + settings.value (ed_long_line_marker_line).toBool (); + editor_long_line_marker_line->setChecked (long_line); + bool long_back = + settings.value (ed_long_line_marker_background).toBool (); + editor_long_line_marker_background->setChecked (long_back); + if (! (long_line || long_back)) + editor_long_line_marker_line->setChecked (true); + editor_long_line_column->setValue (settings.value (ed_long_line_column).toInt ()); + editor_break_checkbox->setChecked (settings.value (ed_break_lines).toBool ()); + editor_break_comments_checkbox->setChecked (settings.value (ed_break_lines_comments).toBool ()); + editor_wrap_checkbox->setChecked (settings.value (ed_wrap_lines).toBool ()); + cb_edit_status_bar->setChecked (settings.value (ed_show_edit_status_bar).toBool ()); + cb_edit_tool_bar->setChecked (settings.value (ed_show_toolbar).toBool ()); + cb_code_folding->setChecked (settings.value (ed_code_folding).toBool ()); + editor_highlight_all_occurrences->setChecked (settings.value (ed_highlight_all_occurrences).toBool ()); - editor_highlightCurrentLine->setChecked (settings->value (ed_highlight_current_line).toBool ()); - editor_long_line_marker->setChecked (settings->value (ed_long_line_marker).toBool ()); - bool long_line = - settings->value (ed_long_line_marker_line).toBool (); - editor_long_line_marker_line->setChecked (long_line); - bool long_back = - settings->value (ed_long_line_marker_background).toBool (); - editor_long_line_marker_background->setChecked (long_back); - if (! (long_line || long_back)) - editor_long_line_marker_line->setChecked (true); - editor_long_line_column->setValue (settings->value (ed_long_line_column).toInt ()); - editor_break_checkbox->setChecked (settings->value (ed_break_lines).toBool ()); - editor_break_comments_checkbox->setChecked (settings->value (ed_break_lines_comments).toBool ()); - editor_wrap_checkbox->setChecked (settings->value (ed_wrap_lines).toBool ()); - cb_edit_status_bar->setChecked (settings->value (ed_show_edit_status_bar).toBool ()); - cb_edit_tool_bar->setChecked (settings->value (ed_show_toolbar).toBool ()); - cb_code_folding->setChecked (settings->value (ed_code_folding).toBool ()); - editor_highlight_all_occurrences->setChecked (settings->value (ed_highlight_all_occurrences).toBool ()); + editor_auto_endif->setCurrentIndex (settings.value (ed_auto_endif).toInt () ); + editor_codeCompletion->setChecked (settings.value (ed_code_completion).toBool ()); + editor_spinbox_ac_threshold->setValue (settings.value (ed_code_completion_threshold).toInt ()); + editor_checkbox_ac_keywords->setChecked (settings.value (ed_code_completion_keywords).toBool ()); + editor_checkbox_ac_builtins->setEnabled (editor_checkbox_ac_keywords->isChecked ()); + editor_checkbox_ac_functions->setEnabled (editor_checkbox_ac_keywords->isChecked ()); + editor_checkbox_ac_builtins->setChecked (settings.value (ed_code_completion_octave_builtins).toBool ()); + editor_checkbox_ac_functions->setChecked (settings.value (ed_code_completion_octave_functions).toBool ()); + editor_checkbox_ac_document->setChecked (settings.value (ed_code_completion_document).toBool ()); + editor_checkbox_ac_case->setChecked (settings.value (ed_code_completion_case).toBool ()); + editor_checkbox_ac_replace->setChecked (settings.value (ed_code_completion_replace).toBool ()); + editor_ws_checkbox->setChecked (settings.value (ed_show_white_space).toBool ()); + editor_ws_indent_checkbox->setChecked (settings.value (ed_show_white_space_indent).toBool ()); + cb_show_eol->setChecked (settings.value (ed_show_eol_chars).toBool ()); + cb_show_hscrollbar->setChecked (settings.value (ed_show_hscroll_bar).toBool ()); + + for (int i = 0; i < ed_tab_position_names.length (); i++) + editor_combox_tab_pos->insertItem (i, + tr (ed_tab_position_names.at (i).toStdString ().data ())); + editor_combox_tab_pos->setCurrentIndex + (settings.value (ed_tab_position).toInt ()); - editor_auto_endif->setCurrentIndex (settings->value (ed_auto_endif).toInt () ); - editor_codeCompletion->setChecked (settings->value (ed_code_completion).toBool ()); - editor_spinbox_ac_threshold->setValue (settings->value (ed_code_completion_threshold).toInt ()); - editor_checkbox_ac_keywords->setChecked (settings->value (ed_code_completion_keywords).toBool ()); - editor_checkbox_ac_builtins->setEnabled (editor_checkbox_ac_keywords->isChecked ()); - editor_checkbox_ac_functions->setEnabled (editor_checkbox_ac_keywords->isChecked ()); - editor_checkbox_ac_builtins->setChecked (settings->value (ed_code_completion_octave_builtins).toBool ()); - editor_checkbox_ac_functions->setChecked (settings->value (ed_code_completion_octave_functions).toBool ()); - editor_checkbox_ac_document->setChecked (settings->value (ed_code_completion_document).toBool ()); - editor_checkbox_ac_case->setChecked (settings->value (ed_code_completion_case).toBool ()); - editor_checkbox_ac_replace->setChecked (settings->value (ed_code_completion_replace).toBool ()); - editor_ws_checkbox->setChecked (settings->value (ed_show_white_space).toBool ()); - editor_ws_indent_checkbox->setChecked (settings->value (ed_show_white_space_indent).toBool ()); - cb_show_eol->setChecked (settings->value (ed_show_eol_chars).toBool ()); - cb_show_hscrollbar->setChecked (settings->value (ed_show_hscroll_bar).toBool ()); + editor_cb_tabs_rotated->setChecked (settings.value (ed_tabs_rotated).toBool ()); + editor_sb_tabs_max_width->setValue (settings.value (ed_tabs_max_width).toInt ()); + + int selected_comment_string, selected_uncomment_string; + + if (settings.contains (ed_comment_str.key)) // new version (radio buttons) + selected_comment_string = settings.value (ed_comment_str).toInt (); + else // old version (combo box) + selected_comment_string = settings.value (ed_comment_str_old.key, ed_comment_str.def).toInt (); - for (int i = 0; i < ed_tab_position_names.length (); i++) - editor_combox_tab_pos->insertItem (i, - tr (ed_tab_position_names.at (i).toStdString ().data ())); - editor_combox_tab_pos->setCurrentIndex - (settings->value (ed_tab_position).toInt ()); + selected_uncomment_string = settings.value (ed_uncomment_str).toInt (); - editor_cb_tabs_rotated->setChecked (settings->value (ed_tabs_rotated).toBool ()); - editor_sb_tabs_max_width->setValue (settings->value (ed_tabs_max_width).toInt ()); + for (int i = 0; i < ed_comment_strings_count; i++) + { + m_rb_comment_strings[i] = new QRadioButton (); + m_rb_uncomment_strings[i] = new QCheckBox (); - int selected_comment_string, selected_uncomment_string; + connect (m_rb_comment_strings[i], &QRadioButton::clicked, + m_rb_uncomment_strings[i], &QCheckBox::setChecked); + connect (m_rb_comment_strings[i], &QRadioButton::toggled, + m_rb_uncomment_strings[i], &QCheckBox::setDisabled); - if (settings->contains (ed_comment_str.key)) // new version (radio buttons) - selected_comment_string = settings->value (ed_comment_str).toInt (); - else // old version (combo box) - selected_comment_string = settings->value (ed_comment_str_old.key, ed_comment_str.def).toInt (); - - selected_uncomment_string = settings->value (ed_uncomment_str).toInt (); - - for (int i = 0; i < ed_comment_strings_count; i++) - { - m_rb_comment_strings[i] = new QRadioButton (); - m_rb_uncomment_strings[i] = new QCheckBox (); + m_rb_comment_strings[i]->setText (ed_comment_strings.at(i)); + m_rb_comment_strings[i]->setChecked (i == selected_comment_string); + layout_comment_strings->addWidget (m_rb_comment_strings[i]); - connect (m_rb_comment_strings[i], &QRadioButton::clicked, - m_rb_uncomment_strings[i], &QCheckBox::setChecked); - connect (m_rb_comment_strings[i], &QRadioButton::toggled, - m_rb_uncomment_strings[i], &QCheckBox::setDisabled); - - m_rb_comment_strings[i]->setText (ed_comment_strings.at(i)); - m_rb_comment_strings[i]->setChecked (i == selected_comment_string); - layout_comment_strings->addWidget (m_rb_comment_strings[i]); - - m_rb_uncomment_strings[i]->setText (ed_comment_strings.at(i)); - m_rb_uncomment_strings[i]->setAutoExclusive (false); - m_rb_uncomment_strings[i]->setChecked ( 1 << i & selected_uncomment_string); - layout_uncomment_strings->addWidget (m_rb_uncomment_strings[i]); - } + m_rb_uncomment_strings[i]->setText (ed_comment_strings.at(i)); + m_rb_uncomment_strings[i]->setAutoExclusive (false); + m_rb_uncomment_strings[i]->setChecked ( 1 << i & selected_uncomment_string); + layout_uncomment_strings->addWidget (m_rb_uncomment_strings[i]); + } - combo_eol_mode->setCurrentIndex (settings->value (ed_default_eol_mode).toInt ()); - editor_auto_ind_checkbox->setChecked (settings->value (ed_auto_indent).toBool ()); - editor_tab_ind_checkbox->setChecked (settings->value (ed_tab_indents_line).toBool ()); - editor_bs_unind_checkbox->setChecked (settings->value (ed_backspace_unindents_line).toBool ()); - editor_ind_guides_checkbox->setChecked (settings->value (ed_show_indent_guides).toBool ()); - editor_ind_width_spinbox->setValue (settings->value (ed_indent_width).toInt ()); - editor_ind_uses_tabs_checkbox->setChecked (settings->value (ed_indent_uses_tabs).toBool ()); - editor_tab_width_spinbox->setValue (settings->value (ed_tab_width).toInt ()); - editor_restoreSession->setChecked (settings->value (ed_restore_session).toBool ()); - editor_create_new_file->setChecked (settings->value (ed_create_new_file).toBool ()); - editor_reload_changed_files->setChecked (settings->value (ed_always_reload_changed_files).toBool ()); - editor_force_newline->setChecked (settings->value (ed_force_newline).toBool ()); - editor_remove_trailing_spaces->setChecked (settings->value (ed_rm_trailing_spaces).toBool ()); - editor_hiding_closes_files->setChecked (settings->value (ed_hiding_closes_files).toBool ()); - editor_show_dbg_file->setChecked (settings->value (ed_show_dbg_file).toBool ()); + combo_eol_mode->setCurrentIndex (settings.value (ed_default_eol_mode).toInt ()); + editor_auto_ind_checkbox->setChecked (settings.value (ed_auto_indent).toBool ()); + editor_tab_ind_checkbox->setChecked (settings.value (ed_tab_indents_line).toBool ()); + editor_bs_unind_checkbox->setChecked (settings.value (ed_backspace_unindents_line).toBool ()); + editor_ind_guides_checkbox->setChecked (settings.value (ed_show_indent_guides).toBool ()); + editor_ind_width_spinbox->setValue (settings.value (ed_indent_width).toInt ()); + editor_ind_uses_tabs_checkbox->setChecked (settings.value (ed_indent_uses_tabs).toBool ()); + editor_tab_width_spinbox->setValue (settings.value (ed_tab_width).toInt ()); + editor_restoreSession->setChecked (settings.value (ed_restore_session).toBool ()); + editor_create_new_file->setChecked (settings.value (ed_create_new_file).toBool ()); + editor_reload_changed_files->setChecked (settings.value (ed_always_reload_changed_files).toBool ()); + editor_force_newline->setChecked (settings.value (ed_force_newline).toBool ()); + editor_remove_trailing_spaces->setChecked (settings.value (ed_rm_trailing_spaces).toBool ()); + editor_hiding_closes_files->setChecked (settings.value (ed_hiding_closes_files).toBool ()); + editor_show_dbg_file->setChecked (settings.value (ed_show_dbg_file).toBool ()); - // terminal - QString default_font = settings->value (global_mono_font).toString (); - terminal_fontName->setCurrentFont (QFont (settings->value (cs_font.key, default_font).toString ())); - terminal_fontSize->setValue (settings->value (cs_font_size).toInt ()); - terminal_history_buffer->setValue (settings->value (cs_hist_buffer).toInt ()); - terminal_cursorUseForegroundColor->setChecked (settings->value (cs_cursor_use_fgcol).toBool ()); - terminal_focus_command->setChecked (settings->value (cs_focus_cmd).toBool ()); - terminal_print_dbg_location->setChecked (settings->value (cs_dbg_location).toBool ()); + // terminal + QString default_font = settings.value (global_mono_font).toString (); + terminal_fontName->setCurrentFont (QFont (settings.value (cs_font.key, default_font).toString ())); + terminal_fontSize->setValue (settings.value (cs_font_size).toInt ()); + terminal_history_buffer->setValue (settings.value (cs_hist_buffer).toInt ()); + terminal_cursorUseForegroundColor->setChecked (settings.value (cs_cursor_use_fgcol).toBool ()); + terminal_focus_command->setChecked (settings.value (cs_focus_cmd).toBool ()); + terminal_print_dbg_location->setChecked (settings.value (cs_dbg_location).toBool ()); - QString cursor_type - = settings->value (cs_cursor).toString (); + QString cursor_type + = settings.value (cs_cursor).toString (); + + QStringList items; + items << QString ("0") << QString ("1") << QString ("2"); + terminal_cursorType->addItems (items); + terminal_cursorType->setItemText (0, tr ("IBeam Cursor")); + terminal_cursorType->setItemText (1, tr ("Block Cursor")); + terminal_cursorType->setItemText (2, tr ("Underline Cursor")); - QStringList items; - items << QString ("0") << QString ("1") << QString ("2"); - terminal_cursorType->addItems (items); - terminal_cursorType->setItemText (0, tr ("IBeam Cursor")); - terminal_cursorType->setItemText (1, tr ("Block Cursor")); - terminal_cursorType->setItemText (2, tr ("Underline Cursor")); + for (unsigned int i = 0; i < cs_cursor_types.size (); i++) + { + if (cursor_type.toStdString () == cs_cursor_types[i]) + { + terminal_cursorType->setCurrentIndex (i); + break; + } + } - for (unsigned int i = 0; i < cs_cursor_types.size (); i++) - { - if (cursor_type.toStdString () == cs_cursor_types[i]) - { - terminal_cursorType->setCurrentIndex (i); - break; - } - } + read_terminal_colors (); - read_terminal_colors (settings); - - // file browser - connect (sync_octave_directory, &QCheckBox::toggled, - this, &settings_dialog::set_disabled_pref_file_browser_dir); + // file browser + connect (sync_octave_directory, &QCheckBox::toggled, + this, &settings_dialog::set_disabled_pref_file_browser_dir); - sync_octave_directory->setChecked (settings->value (fb_sync_octdir).toBool ()); - cb_restore_file_browser_dir->setChecked (settings->value (fb_restore_last_dir).toBool ()); - le_file_browser_dir->setText (settings->value (fb_startup_dir.key).toString ()); + sync_octave_directory->setChecked (settings.value (fb_sync_octdir).toBool ()); + cb_restore_file_browser_dir->setChecked (settings.value (fb_restore_last_dir).toBool ()); + le_file_browser_dir->setText (settings.value (fb_startup_dir.key).toString ()); - connect (pb_file_browser_dir, &QPushButton::pressed, - this, &settings_dialog::get_file_browser_dir); + connect (pb_file_browser_dir, &QPushButton::pressed, + this, &settings_dialog::get_file_browser_dir); - le_file_browser_extensions->setText (settings->value (fb_txt_file_ext).toString ()); + le_file_browser_extensions->setText (settings.value (fb_txt_file_ext).toString ()); - checkbox_allow_web_connect->setChecked (settings->value (nr_allow_connection).toBool ()); + checkbox_allow_web_connect->setChecked (settings.value (nr_allow_connection).toBool ()); - // Proxy - bool use_proxy = settings->value (global_use_proxy.key, global_use_proxy.def).toBool (); - use_proxy_server->setChecked (use_proxy); - // Fill combo box and activate current one - QString proxy_type_string = settings->value (global_proxy_type.key, global_proxy_type.def).toString (); - proxy_type->addItems (global_proxy_all_types); - for (int i = 0; i < global_proxy_all_types.length (); i++) - { - if (proxy_type->itemText (i) == proxy_type_string) - { - proxy_type->setCurrentIndex (i); - break; - } - } - // Fill all line edits - proxy_host_name->setText (settings->value (global_proxy_host.key, global_proxy_host.def).toString ()); - proxy_port->setText (settings->value (global_proxy_port.key, global_proxy_port.def).toString ()); - proxy_username->setText (settings->value (global_proxy_user.key, global_proxy_user.def).toString ()); - proxy_password->setText (settings->value (global_proxy_pass.key, global_proxy_pass.def).toString ()); - // Connect relevant signals for dis-/enabling some elements - connect (proxy_type, QOverload::of (&QComboBox::currentIndexChanged), - this, &settings_dialog::proxy_items_update); - connect (use_proxy_server, &QCheckBox::toggled, - this, &settings_dialog::proxy_items_update); - // Check whehter line edits have to be enabled - proxy_items_update (); + // Proxy + bool use_proxy = settings.value (global_use_proxy.key, global_use_proxy.def).toBool (); + use_proxy_server->setChecked (use_proxy); + // Fill combo box and activate current one + QString proxy_type_string = settings.value (global_proxy_type.key, global_proxy_type.def).toString (); + proxy_type->addItems (global_proxy_all_types); + for (int i = 0; i < global_proxy_all_types.length (); i++) + { + if (proxy_type->itemText (i) == proxy_type_string) + { + proxy_type->setCurrentIndex (i); + break; + } + } + // Fill all line edits + proxy_host_name->setText (settings.value (global_proxy_host.key, global_proxy_host.def).toString ()); + proxy_port->setText (settings.value (global_proxy_port.key, global_proxy_port.def).toString ()); + proxy_username->setText (settings.value (global_proxy_user.key, global_proxy_user.def).toString ()); + proxy_password->setText (settings.value (global_proxy_pass.key, global_proxy_pass.def).toString ()); + // Connect relevant signals for dis-/enabling some elements + connect (proxy_type, QOverload::of (&QComboBox::currentIndexChanged), + this, &settings_dialog::proxy_items_update); + connect (use_proxy_server, &QCheckBox::toggled, + this, &settings_dialog::proxy_items_update); + // Check whehter line edits have to be enabled + proxy_items_update (); - // Workspace - read_workspace_colors (settings); + // Workspace + read_workspace_colors (); - // variable editor - varedit_columnWidth->setValue (settings->value (ve_column_width).toInt ()); - varedit_rowHeight->setValue (settings->value (ve_row_height).toInt ()); + // variable editor + varedit_columnWidth->setValue (settings.value (ve_column_width).toInt ()); + varedit_rowHeight->setValue (settings.value (ve_row_height).toInt ()); - varedit_font->setCurrentFont (QFont (settings->value (ve_font_name.key, - settings->value (cs_font.key, default_font)).toString ())); - varedit_fontSize->setValue (settings->value (ve_font_size).toInt ()); - connect (varedit_useTerminalFont, &QCheckBox::toggled, - varedit_font, &QFontComboBox::setDisabled); - connect (varedit_useTerminalFont, &QCheckBox::toggled, - varedit_fontSize, &QSpinBox::setDisabled); - varedit_useTerminalFont->setChecked (settings->value (ve_use_terminal_font).toBool ()); - varedit_font->setDisabled (varedit_useTerminalFont->isChecked ()); - varedit_fontSize->setDisabled (varedit_useTerminalFont->isChecked ()); + varedit_font->setCurrentFont (QFont (settings.value (ve_font_name.key, + settings.value (cs_font.key, default_font)).toString ())); + varedit_fontSize->setValue (settings.value (ve_font_size).toInt ()); + connect (varedit_useTerminalFont, &QCheckBox::toggled, + varedit_font, &QFontComboBox::setDisabled); + connect (varedit_useTerminalFont, &QCheckBox::toggled, + varedit_fontSize, &QSpinBox::setDisabled); + varedit_useTerminalFont->setChecked (settings.value (ve_use_terminal_font).toBool ()); + varedit_font->setDisabled (varedit_useTerminalFont->isChecked ()); + varedit_fontSize->setDisabled (varedit_useTerminalFont->isChecked ()); - varedit_alternate->setChecked (settings->value (ve_alternate_rows).toBool ()); + varedit_alternate->setChecked (settings.value (ve_alternate_rows).toBool ()); - // variable editor colors - read_varedit_colors (settings); + // variable editor colors + read_varedit_colors (); - // shortcuts + // shortcuts - shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); + shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); - cb_prevent_readline_conflicts->setChecked ( - settings->value (sc_prevent_rl_conflicts.key, - sc_prevent_rl_conflicts.def).toBool ()); - cb_prevent_readline_conflicts_menu->setChecked ( - settings->value (sc_prevent_rl_conflicts_menu.key, - sc_prevent_rl_conflicts_menu.def).toBool ()); + cb_prevent_readline_conflicts->setChecked ( + settings.value (sc_prevent_rl_conflicts.key, + sc_prevent_rl_conflicts.def).toBool ()); + cb_prevent_readline_conflicts_menu->setChecked ( + settings.value (sc_prevent_rl_conflicts_menu.key, + sc_prevent_rl_conflicts_menu.def).toBool ()); - // initialize the tree view with all shortcut data - scmgr.fill_treewidget (shortcuts_treewidget); + // initialize the tree view with all shortcut data + scmgr.fill_treewidget (shortcuts_treewidget); - // connect the buttons for import/export of the shortcut sets - connect (btn_import_shortcut_set, &QPushButton::clicked, - this, &settings_dialog::import_shortcut_set); + // connect the buttons for import/export of the shortcut sets + connect (btn_import_shortcut_set, &QPushButton::clicked, + this, &settings_dialog::import_shortcut_set); - connect (btn_export_shortcut_set, &QPushButton::clicked, - this, &settings_dialog::export_shortcut_set); + connect (btn_export_shortcut_set, &QPushButton::clicked, + this, &settings_dialog::export_shortcut_set); - connect (btn_default_shortcut_set, &QPushButton::clicked, - this, &settings_dialog::default_shortcut_set); + connect (btn_default_shortcut_set, &QPushButton::clicked, + this, &settings_dialog::default_shortcut_set); #if defined (HAVE_QSCINTILLA) - int mode = settings->value (ed_color_mode).toInt (); + int mode = settings.value (ed_color_mode).toInt (); - QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ()), - group_box_editor_styles); - cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ())); - cb_color_mode->setChecked (mode > 0); - cb_color_mode->setObjectName (ed_color_mode.key); + QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ()), + group_box_editor_styles); + cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ())); + cb_color_mode->setChecked (mode > 0); + cb_color_mode->setObjectName (ed_color_mode.key); - QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_styles.toStdString ().data ())); - pb_reload_default_colors->setToolTip (tr (settings_reload_styles_tooltip.toStdString ().data ())); + QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_styles.toStdString ().data ())); + pb_reload_default_colors->setToolTip (tr (settings_reload_styles_tooltip.toStdString ().data ())); - color_picker *current_line_color = new color_picker ( - settings->value (ed_highlight_current_line_color.key + - settings_color_modes_ext[mode], - ed_highlight_current_line_color.def).value (), this); - current_line_color->setObjectName (ed_highlight_current_line_color.key); - QLabel *current_line_color_label = new QLabel( - tr ("Color of highlighted current line (magenta (255,0,255) for automatic color)") - ); + color_picker *current_line_color = new color_picker ( + settings.value (ed_highlight_current_line_color.key + + settings_color_modes_ext[mode], + ed_highlight_current_line_color.def).value (), this); + current_line_color->setObjectName (ed_highlight_current_line_color.key); + QLabel *current_line_color_label = new QLabel( + tr ("Color of highlighted current line (magenta (255,0,255) for automatic color)") + ); - QHBoxLayout *color_mode = new QHBoxLayout (); - color_mode->addWidget (cb_color_mode); - color_mode->addItem (new QSpacerItem (5, 5, QSizePolicy::Expanding)); - color_mode->addWidget (pb_reload_default_colors); + QHBoxLayout *color_mode = new QHBoxLayout (); + color_mode->addWidget (cb_color_mode); + color_mode->addItem (new QSpacerItem (5, 5, QSizePolicy::Expanding)); + color_mode->addWidget (pb_reload_default_colors); - QHBoxLayout *current_line = new QHBoxLayout (); - current_line->addWidget (current_line_color_label); - current_line->addWidget (current_line_color); - current_line->addItem (new QSpacerItem (5, 5, QSizePolicy::Expanding)); + QHBoxLayout *current_line = new QHBoxLayout (); + current_line->addWidget (current_line_color_label); + current_line->addWidget (current_line_color); + current_line->addItem (new QSpacerItem (5, 5, QSizePolicy::Expanding)); - editor_styles_layout->addLayout (color_mode); - editor_styles_layout->addLayout (current_line); + editor_styles_layout->addLayout (color_mode); + editor_styles_layout->addLayout (current_line); - // update colors depending on second theme selection - connect (cb_color_mode, &QCheckBox::stateChanged, - this, &settings_dialog::update_editor_lexers); - connect (pb_reload_default_colors, &QPushButton::clicked, - [=] () { update_editor_lexers (settings_reload_default_colors_flag); }); + // update colors depending on second theme selection + connect (cb_color_mode, &QCheckBox::stateChanged, + this, &settings_dialog::update_editor_lexers); + connect (pb_reload_default_colors, &QPushButton::clicked, + [=] () { update_editor_lexers (settings_reload_default_colors_flag); }); - // finally read the lexer colors using the update slot - update_editor_lexers (); + // finally read the lexer colors using the update slot + update_editor_lexers (); #endif - // which tab is the desired one? - show_tab (desired_tab); + // which tab is the desired one? + show_tab (desired_tab); - // connect button box signal - connect (button_box, &QDialogButtonBox::clicked, - this, &settings_dialog::button_clicked); + // connect button box signal + connect (button_box, &QDialogButtonBox::clicked, + this, &settings_dialog::button_clicked); - // restore last geometry - if (settings->contains (sd_geometry.key)) - restoreGeometry (settings->value (sd_geometry).toByteArray ()); - else - setGeometry (QRect (10, 50, 1000, 600)); -} + // restore last geometry + if (settings.contains (sd_geometry.key)) + restoreGeometry (settings.value (sd_geometry).toByteArray ()); + else + setGeometry (QRect (10, 50, 1000, 600)); + } -void settings_dialog::show_tab (const QString& tab) -{ - if (tab.isEmpty ()) - { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (settings) - tabWidget->setCurrentIndex (settings->value (sd_last_tab).toInt ()); - } - else - { - QHash tab_hash; - tab_hash["editor"] = tab_editor; - tab_hash["editor_styles"] = tab_editor; - tabWidget->setCurrentIndex (tabWidget->indexOf (tab_hash.value (tab))); - if (tab == "editor_styles") - tab_editor_scroll_area->ensureWidgetVisible (group_box_editor_styles); - } -} + void settings_dialog::show_tab (const QString& tab) + { + if (tab.isEmpty ()) + { + gui_settings settings; + + tabWidget->setCurrentIndex (settings.value (sd_last_tab).toInt ()); + } + else + { + QHash tab_hash; + tab_hash["editor"] = tab_editor; + tab_hash["editor_styles"] = tab_editor; + tabWidget->setCurrentIndex (tabWidget->indexOf (tab_hash.value (tab))); + if (tab == "editor_styles") + tab_editor_scroll_area->ensureWidgetVisible (group_box_editor_styles); + } + } -void settings_dialog::get_octave_dir (void) -{ - get_dir (le_octave_dir, tr ("Set Octave Startup Directory")); -} + void settings_dialog::get_octave_dir (void) + { + get_dir (le_octave_dir, tr ("Set Octave Startup Directory")); + } + + void settings_dialog::get_file_browser_dir (void) + { + get_dir (le_file_browser_dir, tr ("Set File Browser Startup Directory")); + } -void settings_dialog::get_file_browser_dir (void) -{ - get_dir (le_file_browser_dir, tr ("Set File Browser Startup Directory")); -} + void settings_dialog::get_dir (QLineEdit *line_edit, const QString& title) + { + // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. + int opts = QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks; + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) + opts |= QFileDialog::DontUseNativeDialog; -void settings_dialog::get_dir (QLineEdit *line_edit, const QString& title) -{ - // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - int opts = QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) - opts |= QFileDialog::DontUseNativeDialog; + QString dir = QFileDialog::getExistingDirectory + (this, title, line_edit->text (), QFileDialog::Option (opts)); - QString dir = QFileDialog::getExistingDirectory - (this, title, line_edit->text (), QFileDialog::Option (opts)); + line_edit->setText (dir); + } + + void settings_dialog::button_clicked (QAbstractButton *button) + { + QDialogButtonBox::ButtonRole button_role = button_box->buttonRole (button); - line_edit->setText (dir); -} - -void settings_dialog::button_clicked (QAbstractButton *button) -{ - QDialogButtonBox::ButtonRole button_role = button_box->buttonRole (button); + if (button_role == QDialogButtonBox::ApplyRole + || button_role == QDialogButtonBox::AcceptRole) + { + write_changed_settings (button_role == QDialogButtonBox::AcceptRole); + emit apply_new_settings (); + } - if (button_role == QDialogButtonBox::ApplyRole - || button_role == QDialogButtonBox::AcceptRole) - { - write_changed_settings (button_role == QDialogButtonBox::AcceptRole); - emit apply_new_settings (); - } + if (button_role == QDialogButtonBox::RejectRole + || button_role == QDialogButtonBox::AcceptRole) + { + // save last settings dialog's geometry and close - if (button_role == QDialogButtonBox::RejectRole - || button_role == QDialogButtonBox::AcceptRole) - { - // save last settings dialog's geometry and close - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; + + settings.setValue (sd_last_tab.key, tabWidget->currentIndex ()); + settings.setValue (sd_geometry.key, saveGeometry ()); + settings.sync (); - settings->setValue (sd_last_tab.key, tabWidget->currentIndex ()); - settings->setValue (sd_geometry.key, saveGeometry ()); - settings->sync (); + close (); + } + } - close (); - } -} + void settings_dialog::set_disabled_pref_file_browser_dir (bool disable) + { + cb_restore_file_browser_dir->setDisabled (disable); -void settings_dialog::set_disabled_pref_file_browser_dir (bool disable) -{ - cb_restore_file_browser_dir->setDisabled (disable); + if (! disable) + { + le_file_browser_dir->setDisabled (cb_restore_file_browser_dir->isChecked ()); + pb_file_browser_dir->setDisabled (cb_restore_file_browser_dir->isChecked ()); + } + else + { + le_file_browser_dir->setDisabled (disable); + pb_file_browser_dir->setDisabled (disable); + } + } - if (! disable) - { - le_file_browser_dir->setDisabled (cb_restore_file_browser_dir->isChecked ()); - pb_file_browser_dir->setDisabled (cb_restore_file_browser_dir->isChecked ()); - } - else - { - le_file_browser_dir->setDisabled (disable); - pb_file_browser_dir->setDisabled (disable); - } -} - -// slot for updating enabled state of proxy settings -void settings_dialog::proxy_items_update (void) -{ - bool use_proxy = use_proxy_server->isChecked (); + // slot for updating enabled state of proxy settings + void settings_dialog::proxy_items_update (void) + { + bool use_proxy = use_proxy_server->isChecked (); - bool manual = false; - for (int i = 0; i < global_proxy_manual_types.length (); i++) - { - if (proxy_type->currentIndex () == global_proxy_manual_types.at (i)) - { - manual = true; - break; - } - } + bool manual = false; + for (int i = 0; i < global_proxy_manual_types.length (); i++) + { + if (proxy_type->currentIndex () == global_proxy_manual_types.at (i)) + { + manual = true; + break; + } + } - proxy_type->setEnabled (use_proxy); - proxy_host_name_label->setEnabled (use_proxy && manual); - proxy_host_name->setEnabled (use_proxy && manual); - proxy_port_label->setEnabled (use_proxy && manual); - proxy_port->setEnabled (use_proxy && manual); - proxy_username_label->setEnabled (use_proxy && manual); - proxy_username->setEnabled (use_proxy && manual); - proxy_password_label->setEnabled (use_proxy && manual); - proxy_password->setEnabled (use_proxy && manual); -} + proxy_type->setEnabled (use_proxy); + proxy_host_name_label->setEnabled (use_proxy && manual); + proxy_host_name->setEnabled (use_proxy && manual); + proxy_port_label->setEnabled (use_proxy && manual); + proxy_port->setEnabled (use_proxy && manual); + proxy_username_label->setEnabled (use_proxy && manual); + proxy_username->setEnabled (use_proxy && manual); + proxy_password_label->setEnabled (use_proxy && manual); + proxy_password->setEnabled (use_proxy && manual); + } -// slots for import/export of shortcut sets + // slots for import/export of shortcut sets -void settings_dialog::import_shortcut_set (void) -{ - shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); + void settings_dialog::import_shortcut_set (void) + { + shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); - scmgr.import_export (shortcut_manager::OSC_IMPORT); -} + scmgr.import_export (shortcut_manager::OSC_IMPORT); + } -void settings_dialog::export_shortcut_set (void) -{ - shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); + void settings_dialog::export_shortcut_set (void) + { + shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); - scmgr.import_export (shortcut_manager::OSC_EXPORT); -} + scmgr.import_export (shortcut_manager::OSC_EXPORT); + } -void settings_dialog::default_shortcut_set (void) -{ - shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); + void settings_dialog::default_shortcut_set (void) + { + shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); - scmgr.import_export (shortcut_manager::OSC_DEFAULT); -} + scmgr.import_export (shortcut_manager::OSC_DEFAULT); + } -void settings_dialog::update_editor_lexers (int def) -{ + void settings_dialog::update_editor_lexers (int def) + { #if defined (HAVE_QSCINTILLA) - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - QCheckBox *cb_color_mode - = group_box_editor_styles->findChild (ed_color_mode.key); + QCheckBox *cb_color_mode + = group_box_editor_styles->findChild (ed_color_mode.key); - int m = 0; - if (cb_color_mode && cb_color_mode->isChecked ()) - m = 1; + int m = 0; + if (cb_color_mode && cb_color_mode->isChecked ()) + m = 1; - color_picker *c_picker = findChild (ed_highlight_current_line_color.key); - if (c_picker) - { - if (def != settings_reload_default_colors_flag) - { - // Get current value from settings or the default - c_picker->set_color (settings->color_value (ed_highlight_current_line_color, m)); - } - else - { - // Get the default value - c_picker->set_color (settings->get_color_value (ed_highlight_current_line_color.def, m)); - } - } + color_picker *c_picker = findChild (ed_highlight_current_line_color.key); + if (c_picker) + { + if (def != settings_reload_default_colors_flag) + { + // Get current value from settings or the default + c_picker->set_color (settings.color_value (ed_highlight_current_line_color, m)); + } + else + { + // Get the default value + c_picker->set_color (settings.get_color_value (ed_highlight_current_line_color.def, m)); + } + } - // editor styles: create lexer, read settings, and - // create or update dialog elements - QsciLexer *lexer; + // editor styles: create lexer, read settings, and + // create or update dialog elements + QsciLexer *lexer; # if defined (HAVE_LEXER_OCTAVE) - lexer = new QsciLexerOctave (); - update_lexer (lexer, settings, m, def); - delete lexer; + lexer = new QsciLexerOctave (); + update_lexer (lexer, m, def); + delete lexer; # elif defined (HAVE_LEXER_MATLAB) - lexer = new QsciLexerMatlab (); - update_lexer (lexer, settings, m, def); - delete lexer; + lexer = new QsciLexerMatlab (); + update_lexer (lexer, m, def); + delete lexer; # endif - lexer = new QsciLexerCPP (); - update_lexer (lexer, settings, m, def); - delete lexer; + lexer = new QsciLexerCPP (); + update_lexer (lexer, m, def); + delete lexer; - lexer = new QsciLexerJava (); - update_lexer (lexer, settings, m, def); - delete lexer; + lexer = new QsciLexerJava (); + update_lexer (lexer, m, def); + delete lexer; - lexer = new QsciLexerPerl (); - update_lexer (lexer, settings, m, def); - delete lexer; + lexer = new QsciLexerPerl (); + update_lexer (lexer, m, def); + delete lexer; - lexer = new QsciLexerBatch (); - update_lexer (lexer, settings, m, def); - delete lexer; + lexer = new QsciLexerBatch (); + update_lexer (lexer, m, def); + delete lexer; - lexer = new QsciLexerDiff (); - update_lexer (lexer, settings, m, def); - delete lexer; + lexer = new QsciLexerDiff (); + update_lexer (lexer, m, def); + delete lexer; - lexer = new QsciLexerBash (); - update_lexer (lexer, settings, m, def); - delete lexer; + lexer = new QsciLexerBash (); + update_lexer (lexer, m, def); + delete lexer; - lexer = new octave_txt_lexer (); - update_lexer (lexer, settings, m, def); - delete lexer; + lexer = new octave_txt_lexer (); + update_lexer (lexer, m, def); + delete lexer; #else - octave_unused_parameter (def); + octave_unused_parameter (def); #endif -} + } #if defined (HAVE_QSCINTILLA) -void settings_dialog::update_lexer (QsciLexer *lexer, gui_settings *settings, - int mode, int def) -{ - // Get lexer settings and copy from default settings if not yet - // available in normal settings file - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - rmgr.read_lexer_settings (lexer, settings, mode, def); + void settings_dialog::update_lexer (QsciLexer *lexer, int mode, int def) + { + // Get lexer settings and copy from default settings if not yet + // available in normal settings file + resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + rmgr.read_lexer_settings (lexer, mode, def); - // When reloading default styles, the style tabs do already exists. - // Otherwise, check if they exist or not. - QString lexer_name = lexer->language (); + // When reloading default styles, the style tabs do already exists. + // Otherwise, check if they exist or not. + QString lexer_name = lexer->language (); - int index = -1; - for (int i = 0; i < tabs_editor_lexers->count (); i++) - { - if (tabs_editor_lexers->tabText (i) == lexer_name) - { - index = i; - break; - } - } + int index = -1; + for (int i = 0; i < tabs_editor_lexers->count (); i++) + { + if (tabs_editor_lexers->tabText (i) == lexer_name) + { + index = i; + break; + } + } - if (index == -1) - { - // This is not an update, call get_lexer_settings for building - // the settings tab - get_lexer_settings (lexer, settings); - return; - } + if (index == -1) + { + // This is not an update, call get_lexer_settings for building + // the settings tab + get_lexer_settings (lexer); + return; + } - // Update the styles elements in all styles - int styles[ed_max_lexer_styles]; // array for saving valid styles - int max_style = rmgr.get_valid_lexer_styles (lexer, styles); - QWidget *tab = tabs_editor_lexers->widget (index); - int default_size = 0; - QString default_family; + // Update the styles elements in all styles + int styles[ed_max_lexer_styles]; // array for saving valid styles + int max_style = rmgr.get_valid_lexer_styles (lexer, styles); + QWidget *tab = tabs_editor_lexers->widget (index); + int default_size = 0; + QString default_family; - for (int i = 0; i < max_style; i++) // create dialog elements for all styles - { - QString actual_name = lexer->description (styles[i]); - color_picker *bg_color - = tab->findChild (actual_name + "_bg_color"); - if (bg_color) - { - // Update - if (styles[i] == 0) - bg_color->set_color (lexer->defaultPaper ()); - else - { - if (lexer->paper (styles[i]) == lexer->defaultPaper ()) - bg_color->set_color (settings_color_no_change); - else - bg_color->set_color (lexer->paper (styles[i])); - } - } + for (int i = 0; i < max_style; i++) // create dialog elements for all styles + { + QString actual_name = lexer->description (styles[i]); + color_picker *bg_color + = tab->findChild (actual_name + "_bg_color"); + if (bg_color) + { + // Update + if (styles[i] == 0) + bg_color->set_color (lexer->defaultPaper ()); + else + { + if (lexer->paper (styles[i]) == lexer->defaultPaper ()) + bg_color->set_color (settings_color_no_change); + else + bg_color->set_color (lexer->paper (styles[i])); + } + } - color_picker *color = tab->findChild (actual_name + "_color"); - if (color) - color->set_color (lexer->color (styles[i])); + color_picker *color = tab->findChild (actual_name + "_color"); + if (color) + color->set_color (lexer->color (styles[i])); - QFont font = lexer->font (styles[i]); + QFont font = lexer->font (styles[i]); - QCheckBox *cb = tab->findChild (actual_name + "_bold"); - if (cb) - cb->setChecked (font.bold ()); - cb = tab->findChild (actual_name + "_italic"); - if (cb) - cb->setChecked (font.italic ()); - cb = tab->findChild (actual_name + "_underline"); - if (cb) - cb->setChecked (font.underline ()); + QCheckBox *cb = tab->findChild (actual_name + "_bold"); + if (cb) + cb->setChecked (font.bold ()); + cb = tab->findChild (actual_name + "_italic"); + if (cb) + cb->setChecked (font.italic ()); + cb = tab->findChild (actual_name + "_underline"); + if (cb) + cb->setChecked (font.underline ()); - QFontComboBox *fcb = tab->findChild (actual_name + "_font"); - if (fcb) - { - if (styles[i] == 0) - { - default_family = font.family (); - fcb->setEditText (default_family); - } - else - { - if (font.family () == default_family) - fcb->setEditText (lexer->description (0)); - else - fcb->setEditText (font.family ()); - } - } - QSpinBox *fs = tab->findChild (actual_name + "_size"); - if (fs) - { - if (styles[i] == 0) - { - default_size = font.pointSize (); - fs->setValue (default_size); - } - else - fs->setValue (font.pointSize () - default_size); - } - } + QFontComboBox *fcb = tab->findChild (actual_name + "_font"); + if (fcb) + { + if (styles[i] == 0) + { + default_family = font.family (); + fcb->setEditText (default_family); + } + else + { + if (font.family () == default_family) + fcb->setEditText (lexer->description (0)); + else + fcb->setEditText (font.family ()); + } + } + QSpinBox *fs = tab->findChild (actual_name + "_size"); + if (fs) + { + if (styles[i] == 0) + { + default_size = font.pointSize (); + fs->setValue (default_size); + } + else + fs->setValue (font.pointSize () - default_size); + } + } -} + } -void settings_dialog::get_lexer_settings (QsciLexer *lexer, - gui_settings *settings) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + void settings_dialog::get_lexer_settings (QsciLexer *lexer) + { + resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - int styles[ed_max_lexer_styles]; // array for saving valid styles - // (enum is not continuous) - int max_style = rmgr.get_valid_lexer_styles (lexer, styles); - QGridLayout *style_grid = new QGridLayout (); - QVector description (max_style); - QVector select_font (max_style); - QVector font_size (max_style); - QVector attrib_font (3 * max_style); - QVector color (max_style); - QVector bg_color (max_style); - int default_size = 10; - QFont default_font = QFont (); - int label_width; - QColor default_color = QColor (); + int styles[ed_max_lexer_styles]; // array for saving valid styles + // (enum is not continuous) + int max_style = rmgr.get_valid_lexer_styles (lexer, styles); + QGridLayout *style_grid = new QGridLayout (); + QVector description (max_style); + QVector select_font (max_style); + QVector font_size (max_style); + QVector attrib_font (3 * max_style); + QVector color (max_style); + QVector bg_color (max_style); + int default_size = 10; + QFont default_font = QFont (); + int label_width; + QColor default_color = QColor (); - for (int i = 0; i < max_style; i++) // create dialog elements for all styles - { - QString actual_name = lexer->description (styles[i]); - QFont actual_font = lexer->font (styles[i]); - description[i] = new QLabel (actual_name); - description[i]->setWordWrap (true); - label_width = 24*description[i]->fontMetrics ().averageCharWidth (); - description[i]->setMaximumSize (label_width, QWIDGETSIZE_MAX); - description[i]->setMinimumSize (label_width, 1); - select_font[i] = new QFontComboBox (); - select_font[i]->setObjectName (actual_name + "_font"); - select_font[i]->setMaximumSize (label_width, QWIDGETSIZE_MAX); - select_font[i]->setMinimumSize (label_width, 1); - font_size[i] = new QSpinBox (); - font_size[i]->setObjectName (actual_name + "_size"); - if (styles[i] == 0) // the default - { - select_font[i]->setCurrentFont (actual_font); - default_font = actual_font; - font_size[i]->setRange (6, 24); - default_size = actual_font.pointSize (); - font_size[i]->setValue (default_size); - default_color = lexer->defaultPaper (); - bg_color[i] = new color_picker (default_color); - } - else // other styles - { - select_font[i]->setCurrentFont (actual_font); - if (actual_font.family () == default_font.family ()) - select_font[i]->setEditText (lexer->description (0)); - font_size[i]->setRange (-4, 4); - font_size[i]->setValue (actual_font.pointSize ()-default_size); - font_size[i]->setToolTip (QObject::tr ("Difference to the default size")); - if (lexer->paper (styles[i]) == default_color) - bg_color[i] = new color_picker (settings_color_no_change); - else - bg_color[i] = new color_picker (lexer->paper (styles[i])); - bg_color[i]->setToolTip - (QObject::tr ("Background color, magenta (255, 0, 255) means default")); - } - attrib_font[0+3*i] = new QCheckBox (QObject::tr ("b", "short form for bold")); - attrib_font[1+3*i] = new QCheckBox (QObject::tr ("i", "short form for italic")); - attrib_font[2+3*i] = new QCheckBox (QObject::tr ("u", "short form for underlined")); - attrib_font[0+3*i]->setChecked (actual_font.bold ()); - attrib_font[0+3*i]->setObjectName (actual_name + "_bold"); - attrib_font[1+3*i]->setChecked (actual_font.italic ()); - attrib_font[1+3*i]->setObjectName (actual_name + "_italic"); - attrib_font[2+3*i]->setChecked (actual_font.underline ()); - attrib_font[2+3*i]->setObjectName (actual_name + "_underline"); - color[i] = new color_picker (lexer->color (styles[i])); - color[i]->setObjectName (actual_name + "_color"); - bg_color[i]->setObjectName (actual_name + "_bg_color"); - int column = 1; - style_grid->addWidget (description[i], i, column++); - style_grid->addWidget (select_font[i], i, column++); - style_grid->addWidget (font_size[i], i, column++); - style_grid->addWidget (attrib_font[0+3*i], i, column++); - style_grid->addWidget (attrib_font[1+3*i], i, column++); - style_grid->addWidget (attrib_font[2+3*i], i, column++); - style_grid->addWidget (color[i], i, column++); - style_grid->addWidget (bg_color[i], i, column++); - } + for (int i = 0; i < max_style; i++) // create dialog elements for all styles + { + QString actual_name = lexer->description (styles[i]); + QFont actual_font = lexer->font (styles[i]); + description[i] = new QLabel (actual_name); + description[i]->setWordWrap (true); + label_width = 24*description[i]->fontMetrics ().averageCharWidth (); + description[i]->setMaximumSize (label_width, QWIDGETSIZE_MAX); + description[i]->setMinimumSize (label_width, 1); + select_font[i] = new QFontComboBox (); + select_font[i]->setObjectName (actual_name + "_font"); + select_font[i]->setMaximumSize (label_width, QWIDGETSIZE_MAX); + select_font[i]->setMinimumSize (label_width, 1); + font_size[i] = new QSpinBox (); + font_size[i]->setObjectName (actual_name + "_size"); + if (styles[i] == 0) // the default + { + select_font[i]->setCurrentFont (actual_font); + default_font = actual_font; + font_size[i]->setRange (6, 24); + default_size = actual_font.pointSize (); + font_size[i]->setValue (default_size); + default_color = lexer->defaultPaper (); + bg_color[i] = new color_picker (default_color); + } + else // other styles + { + select_font[i]->setCurrentFont (actual_font); + if (actual_font.family () == default_font.family ()) + select_font[i]->setEditText (lexer->description (0)); + font_size[i]->setRange (-4, 4); + font_size[i]->setValue (actual_font.pointSize ()-default_size); + font_size[i]->setToolTip (QObject::tr ("Difference to the default size")); + if (lexer->paper (styles[i]) == default_color) + bg_color[i] = new color_picker (settings_color_no_change); + else + bg_color[i] = new color_picker (lexer->paper (styles[i])); + bg_color[i]->setToolTip + (QObject::tr ("Background color, magenta (255, 0, 255) means default")); + } + attrib_font[0+3*i] = new QCheckBox (QObject::tr ("b", "short form for bold")); + attrib_font[1+3*i] = new QCheckBox (QObject::tr ("i", "short form for italic")); + attrib_font[2+3*i] = new QCheckBox (QObject::tr ("u", "short form for underlined")); + attrib_font[0+3*i]->setChecked (actual_font.bold ()); + attrib_font[0+3*i]->setObjectName (actual_name + "_bold"); + attrib_font[1+3*i]->setChecked (actual_font.italic ()); + attrib_font[1+3*i]->setObjectName (actual_name + "_italic"); + attrib_font[2+3*i]->setChecked (actual_font.underline ()); + attrib_font[2+3*i]->setObjectName (actual_name + "_underline"); + color[i] = new color_picker (lexer->color (styles[i])); + color[i]->setObjectName (actual_name + "_color"); + bg_color[i]->setObjectName (actual_name + "_bg_color"); + int column = 1; + style_grid->addWidget (description[i], i, column++); + style_grid->addWidget (select_font[i], i, column++); + style_grid->addWidget (font_size[i], i, column++); + style_grid->addWidget (attrib_font[0+3*i], i, column++); + style_grid->addWidget (attrib_font[1+3*i], i, column++); + style_grid->addWidget (attrib_font[2+3*i], i, column++); + style_grid->addWidget (color[i], i, column++); + style_grid->addWidget (bg_color[i], i, column++); + } - // place grid with elements into the tab - QScrollArea *scroll_area = new QScrollArea (); - QWidget *scroll_area_contents = new QWidget (); - scroll_area_contents->setObjectName (QString (lexer->language ()) + "_styles"); - scroll_area_contents->setLayout (style_grid); - scroll_area->setWidget (scroll_area_contents); - tabs_editor_lexers->addTab (scroll_area, lexer->language ()); + // place grid with elements into the tab + QScrollArea *scroll_area = new QScrollArea (); + QWidget *scroll_area_contents = new QWidget (); + scroll_area_contents->setObjectName (QString (lexer->language ()) + "_styles"); + scroll_area_contents->setLayout (style_grid); + scroll_area->setWidget (scroll_area_contents); + tabs_editor_lexers->addTab (scroll_area, lexer->language ()); - tabs_editor_lexers->setCurrentIndex (settings->value (sd_last_editor_styles_tab).toInt ()); -} + gui_settings settings; -void settings_dialog::write_lexer_settings (QsciLexer *lexer, - gui_settings *settings) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + tabs_editor_lexers->setCurrentIndex (settings.value (sd_last_editor_styles_tab).toInt ()); + } + + void settings_dialog::write_lexer_settings (QsciLexer *lexer) + { + gui_settings settings; - QCheckBox *cb_color_mode - = group_box_editor_styles->findChild (ed_color_mode.key); - int mode = 0; - if (cb_color_mode && cb_color_mode->isChecked ()) - mode = 1; + QCheckBox *cb_color_mode + = group_box_editor_styles->findChild (ed_color_mode.key); + int mode = 0; + if (cb_color_mode && cb_color_mode->isChecked ()) + mode = 1; - settings->setValue (ed_color_mode.key, mode); + settings.setValue (ed_color_mode.key, mode); - QWidget *tab = tabs_editor_lexers-> - findChild (QString (lexer->language ()) + "_styles"); - int styles[ed_max_lexer_styles]; // array for saving valid styles - // (enum is not continuous) - int max_style = rmgr.get_valid_lexer_styles (lexer, styles); - QFontComboBox *select_font; - QSpinBox *font_size; - QCheckBox *attrib_font[3]; - color_picker *color; - color_picker *bg_color; - int default_size = 10; + QWidget *tab = tabs_editor_lexers-> + findChild (QString (lexer->language ()) + "_styles"); + int styles[ed_max_lexer_styles]; // array for saving valid styles + // (enum is not continuous) + + resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + int max_style = rmgr.get_valid_lexer_styles (lexer, styles); - color = findChild (ed_highlight_current_line_color.key); - if (color) - settings->setValue (ed_highlight_current_line_color.key - + settings_color_modes_ext[mode], color->color ()); + QFontComboBox *select_font; + QSpinBox *font_size; + QCheckBox *attrib_font[3]; + color_picker *color; + color_picker *bg_color; + int default_size = 10; - QString default_font_name - = settings->value (global_mono_font).toString (); - QFont default_font = QFont (default_font_name, 10, -1, 0); - QColor default_color = QColor (); + color = findChild (ed_highlight_current_line_color.key); + if (color) + settings.setValue (ed_highlight_current_line_color.key + + settings_color_modes_ext[mode], color->color ()); + + QString default_font_name + = settings.value (global_mono_font).toString (); + QFont default_font = QFont (default_font_name, 10, -1, 0); + QColor default_color = QColor (); - for (int i = 0; i < max_style; i++) // get dialog elements and their contents - { - QString actual_name = lexer->description (styles[i]); - select_font = tab->findChild (actual_name + "_font"); - font_size = tab->findChild (actual_name + "_size"); - attrib_font[0] = tab->findChild (actual_name + "_bold"); - attrib_font[1] = tab->findChild (actual_name + "_italic"); - attrib_font[2] = tab->findChild (actual_name + "_underline"); - color = tab->findChild (actual_name + "_color"); - bg_color = tab->findChild (actual_name + "_bg_color"); - QFont new_font = default_font; - if (select_font) - { - new_font = select_font->currentFont (); - if (styles[i] == 0) - default_font = new_font; - else if (select_font->currentText () == lexer->description (0)) - new_font = default_font; - } - if (font_size) - { - if (styles[i] == 0) - { - default_size = font_size->value (); - new_font.setPointSize (font_size->value ()); - } - else - new_font.setPointSize (font_size->value ()+default_size); - } - if (attrib_font[0]) - new_font.setBold (attrib_font[0]->isChecked ()); - if (attrib_font[1]) - new_font.setItalic (attrib_font[1]->isChecked ()); - if (attrib_font[2]) - new_font.setUnderline (attrib_font[2]->isChecked ()); - lexer->setFont (new_font, styles[i]); - if (styles[i] == 0) - lexer->setDefaultFont (new_font); - if (color) - lexer->setColor (color->color (), styles[i]); - if (bg_color) - { - if (styles[i] == 0) - { - default_color = bg_color->color (); - lexer->setPaper (default_color, styles[i]); - lexer->setDefaultPaper (default_color); - } - else - { - if (bg_color->color () == settings_color_no_change) + for (int i = 0; i < max_style; i++) // get dialog elements and their contents + { + QString actual_name = lexer->description (styles[i]); + select_font = tab->findChild (actual_name + "_font"); + font_size = tab->findChild (actual_name + "_size"); + attrib_font[0] = tab->findChild (actual_name + "_bold"); + attrib_font[1] = tab->findChild (actual_name + "_italic"); + attrib_font[2] = tab->findChild (actual_name + "_underline"); + color = tab->findChild (actual_name + "_color"); + bg_color = tab->findChild (actual_name + "_bg_color"); + QFont new_font = default_font; + if (select_font) + { + new_font = select_font->currentFont (); + if (styles[i] == 0) + default_font = new_font; + else if (select_font->currentText () == lexer->description (0)) + new_font = default_font; + } + if (font_size) + { + if (styles[i] == 0) + { + default_size = font_size->value (); + new_font.setPointSize (font_size->value ()); + } + else + new_font.setPointSize (font_size->value ()+default_size); + } + if (attrib_font[0]) + new_font.setBold (attrib_font[0]->isChecked ()); + if (attrib_font[1]) + new_font.setItalic (attrib_font[1]->isChecked ()); + if (attrib_font[2]) + new_font.setUnderline (attrib_font[2]->isChecked ()); + lexer->setFont (new_font, styles[i]); + if (styles[i] == 0) + lexer->setDefaultFont (new_font); + if (color) + lexer->setColor (color->color (), styles[i]); + if (bg_color) + { + if (styles[i] == 0) + { + default_color = bg_color->color (); lexer->setPaper (default_color, styles[i]); - else - lexer->setPaper (bg_color->color (), styles[i]); - } - } - } + lexer->setDefaultPaper (default_color); + } + else + { + if (bg_color->color () == settings_color_no_change) + lexer->setPaper (default_color, styles[i]); + else + lexer->setPaper (bg_color->color (), styles[i]); + } + } + } - const std::string group = - QString ("Scintilla" + settings_color_modes_ext[mode]).toStdString (); + const std::string group = + QString ("Scintilla" + settings_color_modes_ext[mode]).toStdString (); - lexer->writeSettings (*settings, group.c_str ()); + lexer->writeSettings (settings, group.c_str ()); - settings->setValue (sd_last_editor_styles_tab.key, - tabs_editor_lexers->currentIndex ()); - settings->sync (); -} + settings.setValue (sd_last_editor_styles_tab.key, + tabs_editor_lexers->currentIndex ()); + settings.sync (); + } #endif -void settings_dialog::write_changed_settings (bool closing) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + void settings_dialog::write_changed_settings (bool closing) + { + gui_settings settings; + + // the icon set + QString widget_icon_set = "NONE"; + if (general_icon_letter->isChecked ()) + widget_icon_set = "LETTER"; + else if (general_icon_graphic->isChecked ()) + widget_icon_set = "GRAPHIC"; + settings.setValue (dw_icon_set.key, widget_icon_set); - // the icon set - QString widget_icon_set = "NONE"; - if (general_icon_letter->isChecked ()) - widget_icon_set = "LETTER"; - else if (general_icon_graphic->isChecked ()) - widget_icon_set = "GRAPHIC"; - settings->setValue (dw_icon_set.key, widget_icon_set); + // language + QString language = comboBox_language->currentText (); + if (language == tr ("System setting")) + language = global_language.def.toString (); + settings.setValue (global_language.key, language); - // language - QString language = comboBox_language->currentText (); - if (language == tr ("System setting")) - language = global_language.def.toString (); - settings->setValue (global_language.key, language); - - // style - QString selected_style = combo_styles->currentText (); - if (selected_style == global_style.def.toString ()) - selected_style = global_style.def.toString (); - settings->setValue (global_style.key, selected_style); + // style + QString selected_style = combo_styles->currentText (); + if (selected_style == global_style.def.toString ()) + selected_style = global_style.def.toString (); + settings.setValue (global_style.key, selected_style); - // dock widget title bar - settings->setValue (dw_title_custom_style.key, cb_widget_custom_style->isChecked ()); - settings->setValue (dw_title_3d.key, sb_3d_title->value ()); - settings->setValue (dw_title_bg_color.key, m_widget_title_bg_color->color ()); - settings->setValue (dw_title_bg_color_active.key, m_widget_title_bg_color_active->color ()); - settings->setValue (dw_title_fg_color.key, m_widget_title_fg_color->color ()); - settings->setValue (dw_title_fg_color_active.key, m_widget_title_fg_color_active->color ()); + // dock widget title bar + settings.setValue (dw_title_custom_style.key, cb_widget_custom_style->isChecked ()); + settings.setValue (dw_title_3d.key, sb_3d_title->value ()); + settings.setValue (dw_title_bg_color.key, m_widget_title_bg_color->color ()); + settings.setValue (dw_title_bg_color_active.key, m_widget_title_bg_color_active->color ()); + settings.setValue (dw_title_fg_color.key, m_widget_title_fg_color->color ()); + settings.setValue (dw_title_fg_color_active.key, m_widget_title_fg_color_active->color ()); - // icon size and theme - int icon_size = icon_size_large->isChecked () - icon_size_small->isChecked (); - settings->setValue (global_icon_size.key, icon_size); - settings->setValue (global_icon_theme_index.key, combo_box_icon_theme->currentIndex ()); + // icon size and theme + int icon_size = icon_size_large->isChecked () - icon_size_small->isChecked (); + settings.setValue (global_icon_size.key, icon_size); + settings.setValue (global_icon_theme_index.key, combo_box_icon_theme->currentIndex ()); - // native file dialogs - settings->setValue (global_use_native_dialogs.key, cb_use_native_file_dialogs->isChecked ()); + // native file dialogs + settings.setValue (global_use_native_dialogs.key, cb_use_native_file_dialogs->isChecked ()); - // cursor blinking - settings->setValue (global_cursor_blinking.key, cb_cursor_blinking->isChecked ()); + // cursor blinking + settings.setValue (global_cursor_blinking.key, cb_cursor_blinking->isChecked ()); - // focus follows mouse - settings->setValue (dw_focus_follows_mouse.key, cb_focus_follows_mouse->isChecked ()); + // focus follows mouse + settings.setValue (dw_focus_follows_mouse.key, cb_focus_follows_mouse->isChecked ()); - // promp to exit - settings->setValue (global_prompt_to_exit.key, cb_prompt_to_exit->isChecked ()); + // promp to exit + settings.setValue (global_prompt_to_exit.key, cb_prompt_to_exit->isChecked ()); - // status bar - settings->setValue (global_status_bar.key, cb_status_bar->isChecked ()); + // status bar + settings.setValue (global_status_bar.key, cb_status_bar->isChecked ()); - // Octave startup - settings->setValue (global_restore_ov_dir.key, cb_restore_octave_dir->isChecked ()); - settings->setValue (global_ov_startup_dir.key, le_octave_dir->text ()); + // Octave startup + settings.setValue (global_restore_ov_dir.key, cb_restore_octave_dir->isChecked ()); + settings.setValue (global_ov_startup_dir.key, le_octave_dir->text ()); - //editor - settings->setValue (global_use_custom_editor.key, useCustomFileEditor->isChecked ()); - settings->setValue (global_custom_editor.key, customFileEditor->text ()); - settings->setValue (ed_show_line_numbers.key, editor_showLineNumbers->isChecked ()); - settings->setValue (ed_line_numbers_size.key, editor_linenr_size->value ()); - settings->setValue (ed_highlight_current_line.key, editor_highlightCurrentLine->isChecked ()); - settings->setValue (ed_long_line_marker.key, editor_long_line_marker->isChecked ()); - settings->setValue (ed_long_line_marker_line.key, editor_long_line_marker_line->isChecked ()); - settings->setValue (ed_long_line_marker_background.key, editor_long_line_marker_background->isChecked ()); - settings->setValue (ed_long_line_column.key, editor_long_line_column->value ()); - settings->setValue (ed_break_lines.key, editor_break_checkbox->isChecked ()); - settings->setValue (ed_break_lines_comments.key, editor_break_comments_checkbox->isChecked ()); - settings->setValue (ed_wrap_lines.key, editor_wrap_checkbox->isChecked ()); - settings->setValue (ed_code_folding.key, cb_code_folding->isChecked ()); - settings->setValue (ed_show_edit_status_bar.key, cb_edit_status_bar->isChecked ()); - settings->setValue (ed_show_toolbar.key, cb_edit_tool_bar->isChecked ()); - settings->setValue (ed_highlight_all_occurrences.key, editor_highlight_all_occurrences->isChecked ()); - settings->setValue (ed_code_completion.key, editor_codeCompletion->isChecked ()); - settings->setValue (ed_code_completion_threshold.key, editor_spinbox_ac_threshold->value ()); - settings->setValue (ed_code_completion_keywords.key, editor_checkbox_ac_keywords->isChecked ()); - settings->setValue (ed_code_completion_octave_builtins.key, editor_checkbox_ac_builtins->isChecked ()); - settings->setValue (ed_code_completion_octave_functions.key, editor_checkbox_ac_functions->isChecked ()); - settings->setValue (ed_code_completion_document.key, editor_checkbox_ac_document->isChecked ()); - settings->setValue (ed_code_completion_case.key, editor_checkbox_ac_case->isChecked ()); - settings->setValue (ed_code_completion_replace.key, editor_checkbox_ac_replace->isChecked ()); - settings->setValue (ed_auto_endif.key, editor_auto_endif->currentIndex ()); - settings->setValue (ed_show_white_space.key, editor_ws_checkbox->isChecked ()); - settings->setValue (ed_show_white_space_indent.key, editor_ws_indent_checkbox->isChecked ()); - settings->setValue (ed_show_eol_chars.key, cb_show_eol->isChecked ()); - settings->setValue (ed_show_hscroll_bar.key, cb_show_hscrollbar->isChecked ()); - settings->setValue (ed_default_eol_mode.key, combo_eol_mode->currentIndex ()); + //editor + settings.setValue (global_use_custom_editor.key, useCustomFileEditor->isChecked ()); + settings.setValue (global_custom_editor.key, customFileEditor->text ()); + settings.setValue (ed_show_line_numbers.key, editor_showLineNumbers->isChecked ()); + settings.setValue (ed_line_numbers_size.key, editor_linenr_size->value ()); + settings.setValue (ed_highlight_current_line.key, editor_highlightCurrentLine->isChecked ()); + settings.setValue (ed_long_line_marker.key, editor_long_line_marker->isChecked ()); + settings.setValue (ed_long_line_marker_line.key, editor_long_line_marker_line->isChecked ()); + settings.setValue (ed_long_line_marker_background.key, editor_long_line_marker_background->isChecked ()); + settings.setValue (ed_long_line_column.key, editor_long_line_column->value ()); + settings.setValue (ed_break_lines.key, editor_break_checkbox->isChecked ()); + settings.setValue (ed_break_lines_comments.key, editor_break_comments_checkbox->isChecked ()); + settings.setValue (ed_wrap_lines.key, editor_wrap_checkbox->isChecked ()); + settings.setValue (ed_code_folding.key, cb_code_folding->isChecked ()); + settings.setValue (ed_show_edit_status_bar.key, cb_edit_status_bar->isChecked ()); + settings.setValue (ed_show_toolbar.key, cb_edit_tool_bar->isChecked ()); + settings.setValue (ed_highlight_all_occurrences.key, editor_highlight_all_occurrences->isChecked ()); + settings.setValue (ed_code_completion.key, editor_codeCompletion->isChecked ()); + settings.setValue (ed_code_completion_threshold.key, editor_spinbox_ac_threshold->value ()); + settings.setValue (ed_code_completion_keywords.key, editor_checkbox_ac_keywords->isChecked ()); + settings.setValue (ed_code_completion_octave_builtins.key, editor_checkbox_ac_builtins->isChecked ()); + settings.setValue (ed_code_completion_octave_functions.key, editor_checkbox_ac_functions->isChecked ()); + settings.setValue (ed_code_completion_document.key, editor_checkbox_ac_document->isChecked ()); + settings.setValue (ed_code_completion_case.key, editor_checkbox_ac_case->isChecked ()); + settings.setValue (ed_code_completion_replace.key, editor_checkbox_ac_replace->isChecked ()); + settings.setValue (ed_auto_endif.key, editor_auto_endif->currentIndex ()); + settings.setValue (ed_show_white_space.key, editor_ws_checkbox->isChecked ()); + settings.setValue (ed_show_white_space_indent.key, editor_ws_indent_checkbox->isChecked ()); + settings.setValue (ed_show_eol_chars.key, cb_show_eol->isChecked ()); + settings.setValue (ed_show_hscroll_bar.key, cb_show_hscrollbar->isChecked ()); + settings.setValue (ed_default_eol_mode.key, combo_eol_mode->currentIndex ()); - settings->setValue (ed_tab_position.key, editor_combox_tab_pos->currentIndex ()); - settings->setValue (ed_tabs_rotated.key, editor_cb_tabs_rotated->isChecked ()); - settings->setValue (ed_tabs_max_width.key, editor_sb_tabs_max_width->value ()); + settings.setValue (ed_tab_position.key, editor_combox_tab_pos->currentIndex ()); + settings.setValue (ed_tabs_rotated.key, editor_cb_tabs_rotated->isChecked ()); + settings.setValue (ed_tabs_max_width.key, editor_sb_tabs_max_width->value ()); - // Comment strings - int rb_uncomment = 0; - for (int i = 0; i < ed_comment_strings_count; i++) - { - if (m_rb_comment_strings[i]->isChecked ()) - { - settings->setValue (ed_comment_str.key, i); - if (i < 3) - settings->setValue (ed_comment_str_old.key, i); - else - settings->setValue (ed_comment_str_old.key, ed_comment_str.def); - } - if (m_rb_uncomment_strings[i]->isChecked ()) - rb_uncomment = rb_uncomment + (1 << i); - } - settings->setValue (ed_uncomment_str.key, rb_uncomment); + // Comment strings + int rb_uncomment = 0; + for (int i = 0; i < ed_comment_strings_count; i++) + { + if (m_rb_comment_strings[i]->isChecked ()) + { + settings.setValue (ed_comment_str.key, i); + if (i < 3) + settings.setValue (ed_comment_str_old.key, i); + else + settings.setValue (ed_comment_str_old.key, ed_comment_str.def); + } + if (m_rb_uncomment_strings[i]->isChecked ()) + rb_uncomment = rb_uncomment + (1 << i); + } + settings.setValue (ed_uncomment_str.key, rb_uncomment); - settings->setValue (ed_default_enc.key, editor_combo_encoding->currentText ()); - settings->setValue (ed_auto_indent.key, editor_auto_ind_checkbox->isChecked ()); - settings->setValue (ed_tab_indents_line.key, editor_tab_ind_checkbox->isChecked ()); - settings->setValue (ed_backspace_unindents_line.key, editor_bs_unind_checkbox->isChecked ()); - settings->setValue (ed_show_indent_guides.key, editor_ind_guides_checkbox->isChecked ()); - settings->setValue (ed_indent_width.key, editor_ind_width_spinbox->value ()); - settings->setValue (ed_indent_uses_tabs.key, editor_ind_uses_tabs_checkbox->isChecked ()); - settings->setValue (ed_tab_width.key, editor_tab_width_spinbox->value ()); - settings->setValue (ed_restore_session.key, editor_restoreSession->isChecked ()); - settings->setValue (ed_create_new_file.key, editor_create_new_file->isChecked ()); - settings->setValue (ed_hiding_closes_files.key, editor_hiding_closes_files->isChecked ()); - settings->setValue (ed_always_reload_changed_files.key, editor_reload_changed_files->isChecked ()); - settings->setValue (ed_force_newline.key, editor_force_newline->isChecked ()); - settings->setValue (ed_rm_trailing_spaces.key, editor_remove_trailing_spaces->isChecked ()); - settings->setValue (ed_show_dbg_file.key, editor_show_dbg_file->isChecked ()); + settings.setValue (ed_default_enc.key, editor_combo_encoding->currentText ()); + settings.setValue (ed_auto_indent.key, editor_auto_ind_checkbox->isChecked ()); + settings.setValue (ed_tab_indents_line.key, editor_tab_ind_checkbox->isChecked ()); + settings.setValue (ed_backspace_unindents_line.key, editor_bs_unind_checkbox->isChecked ()); + settings.setValue (ed_show_indent_guides.key, editor_ind_guides_checkbox->isChecked ()); + settings.setValue (ed_indent_width.key, editor_ind_width_spinbox->value ()); + settings.setValue (ed_indent_uses_tabs.key, editor_ind_uses_tabs_checkbox->isChecked ()); + settings.setValue (ed_tab_width.key, editor_tab_width_spinbox->value ()); + settings.setValue (ed_restore_session.key, editor_restoreSession->isChecked ()); + settings.setValue (ed_create_new_file.key, editor_create_new_file->isChecked ()); + settings.setValue (ed_hiding_closes_files.key, editor_hiding_closes_files->isChecked ()); + settings.setValue (ed_always_reload_changed_files.key, editor_reload_changed_files->isChecked ()); + settings.setValue (ed_force_newline.key, editor_force_newline->isChecked ()); + settings.setValue (ed_rm_trailing_spaces.key, editor_remove_trailing_spaces->isChecked ()); + settings.setValue (ed_show_dbg_file.key, editor_show_dbg_file->isChecked ()); - // file browser - settings->setValue (fb_sync_octdir.key, sync_octave_directory->isChecked ()); - settings->setValue (fb_restore_last_dir.key, cb_restore_file_browser_dir->isChecked ()); - settings->setValue (fb_startup_dir.key, le_file_browser_dir->text ()); - settings->setValue (fb_txt_file_ext.key, le_file_browser_extensions->text ()); + // file browser + settings.setValue (fb_sync_octdir.key, sync_octave_directory->isChecked ()); + settings.setValue (fb_restore_last_dir.key, cb_restore_file_browser_dir->isChecked ()); + settings.setValue (fb_startup_dir.key, le_file_browser_dir->text ()); + settings.setValue (fb_txt_file_ext.key, le_file_browser_extensions->text ()); - // network - settings->setValue (nr_allow_connection.key, checkbox_allow_web_connect->isChecked ()); - settings->setValue (global_use_proxy.key, use_proxy_server->isChecked ()); - settings->setValue (global_proxy_type.key, proxy_type->currentText ()); - settings->setValue (global_proxy_host.key, proxy_host_name->text ()); - settings->setValue (global_proxy_port.key, proxy_port->text ()); - settings->setValue (global_proxy_user.key, proxy_username->text ()); - settings->setValue (global_proxy_pass.key, proxy_password->text ()); + // network + settings.setValue (nr_allow_connection.key, checkbox_allow_web_connect->isChecked ()); + settings.setValue (global_use_proxy.key, use_proxy_server->isChecked ()); + settings.setValue (global_proxy_type.key, proxy_type->currentText ()); + settings.setValue (global_proxy_host.key, proxy_host_name->text ()); + settings.setValue (global_proxy_port.key, proxy_port->text ()); + settings.setValue (global_proxy_user.key, proxy_username->text ()); + settings.setValue (global_proxy_pass.key, proxy_password->text ()); - // command window - settings->setValue (cs_font_size.key, terminal_fontSize->value ()); - settings->setValue (cs_font.key, terminal_fontName->currentFont ().family ()); - settings->setValue (cs_cursor_use_fgcol.key, terminal_cursorUseForegroundColor->isChecked ()); - settings->setValue (cs_focus_cmd.key, terminal_focus_command->isChecked ()); - settings->setValue (cs_dbg_location.key, terminal_print_dbg_location->isChecked ()); - settings->setValue (cs_hist_buffer.key, terminal_history_buffer->value ()); - write_terminal_colors (settings); + // command window + settings.setValue (cs_font_size.key, terminal_fontSize->value ()); + settings.setValue (cs_font.key, terminal_fontName->currentFont ().family ()); + settings.setValue (cs_cursor_use_fgcol.key, terminal_cursorUseForegroundColor->isChecked ()); + settings.setValue (cs_focus_cmd.key, terminal_focus_command->isChecked ()); + settings.setValue (cs_dbg_location.key, terminal_print_dbg_location->isChecked ()); + settings.setValue (cs_hist_buffer.key, terminal_history_buffer->value ()); + write_terminal_colors (); - // the cursor - QString cursor_type; - unsigned int cursor_int = terminal_cursorType->currentIndex (); - if ((cursor_int > 0) && (cursor_int < cs_cursor_types.size ())) - cursor_type = QString (cs_cursor_types[cursor_int].data ()); - else - cursor_type = cs_cursor.def.toString (); + // the cursor + QString cursor_type; + unsigned int cursor_int = terminal_cursorType->currentIndex (); + if ((cursor_int > 0) && (cursor_int < cs_cursor_types.size ())) + cursor_type = QString (cs_cursor_types[cursor_int].data ()); + else + cursor_type = cs_cursor.def.toString (); - settings->setValue (cs_cursor.key, cursor_type); + settings.setValue (cs_cursor.key, cursor_type); #if defined (HAVE_QSCINTILLA) - // editor styles: create lexer, get dialog contents, and write settings - QsciLexer *lexer; + // editor styles: create lexer, get dialog contents, and write settings + QsciLexer *lexer; #if defined (HAVE_LEXER_OCTAVE) - lexer = new QsciLexerOctave (); - write_lexer_settings (lexer, settings); - delete lexer; + lexer = new QsciLexerOctave (); + write_lexer_settings (lexer); + delete lexer; #elif defined (HAVE_LEXER_MATLAB) - lexer = new QsciLexerMatlab (); - write_lexer_settings (lexer, settings); - delete lexer; + lexer = new QsciLexerMatlab (); + write_lexer_settings (lexer); + delete lexer; #endif - lexer = new QsciLexerCPP (); - write_lexer_settings (lexer, settings); - delete lexer; + lexer = new QsciLexerCPP (); + write_lexer_settings (lexer); + delete lexer; - lexer = new QsciLexerJava (); - write_lexer_settings (lexer, settings); - delete lexer; + lexer = new QsciLexerJava (); + write_lexer_settings (lexer); + delete lexer; - lexer = new QsciLexerPerl (); - write_lexer_settings (lexer, settings); - delete lexer; + lexer = new QsciLexerPerl (); + write_lexer_settings (lexer); + delete lexer; - lexer = new QsciLexerBatch (); - write_lexer_settings (lexer, settings); - delete lexer; + lexer = new QsciLexerBatch (); + write_lexer_settings (lexer); + delete lexer; - lexer = new QsciLexerDiff (); - write_lexer_settings (lexer, settings); - delete lexer; + lexer = new QsciLexerDiff (); + write_lexer_settings (lexer); + delete lexer; - lexer = new QsciLexerBash (); - write_lexer_settings (lexer, settings); - delete lexer; + lexer = new QsciLexerBash (); + write_lexer_settings (lexer); + delete lexer; - lexer = new octave_txt_lexer (); - write_lexer_settings (lexer, settings); - delete lexer; + lexer = new octave_txt_lexer (); + write_lexer_settings (lexer); + delete lexer; #endif - // Workspace - write_workspace_colors (settings); + // Workspace + write_workspace_colors (); - // Variable editor - settings->setValue (ve_column_width.key, varedit_columnWidth->value ()); - settings->setValue (ve_row_height.key, varedit_rowHeight->value ()); - settings->setValue (ve_use_terminal_font.key, varedit_useTerminalFont->isChecked ()); - settings->setValue (ve_alternate_rows.key, varedit_alternate->isChecked ()); - settings->setValue (ve_font_name.key, varedit_font->currentFont ().family ()); - settings->setValue (ve_font_size.key, varedit_fontSize->value ()); - write_varedit_colors (settings); + // Variable editor + settings.setValue (ve_column_width.key, varedit_columnWidth->value ()); + settings.setValue (ve_row_height.key, varedit_rowHeight->value ()); + settings.setValue (ve_use_terminal_font.key, varedit_useTerminalFont->isChecked ()); + settings.setValue (ve_alternate_rows.key, varedit_alternate->isChecked ()); + settings.setValue (ve_font_name.key, varedit_font->currentFont ().family ()); + settings.setValue (ve_font_size.key, varedit_fontSize->value ()); + write_varedit_colors (); - // shortcuts + // shortcuts + + settings.setValue (sc_prevent_rl_conflicts.key, cb_prevent_readline_conflicts->isChecked ()); + settings.setValue (sc_prevent_rl_conflicts_menu.key, cb_prevent_readline_conflicts_menu->isChecked ()); + + shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); + scmgr.write_shortcuts (settings, closing); - settings->setValue (sc_prevent_rl_conflicts.key, cb_prevent_readline_conflicts->isChecked ()); - settings->setValue (sc_prevent_rl_conflicts_menu.key, cb_prevent_readline_conflicts_menu->isChecked ()); - shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); - scmgr.write_shortcuts (settings, closing); + settings.sync (); + } - settings->sync (); -} + void settings_dialog::read_workspace_colors (void) + { + gui_settings settings; -void settings_dialog::read_workspace_colors (gui_settings *settings) -{ - // Construct the grid with all color related settings - QGridLayout *style_grid = new QGridLayout (); - QVector description (ws_colors_count); - QVector color (ws_colors_count); + // Construct the grid with all color related settings + QGridLayout *style_grid = new QGridLayout (); + QVector description (ws_colors_count); + QVector color (ws_colors_count); - int column = 0; - const int color_columns = 3; // place colors in so many columns - int row = 0; - int mode = settings->value (ws_color_mode).toInt (); + int column = 0; + const int color_columns = 3; // place colors in so many columns + int row = 0; + int mode = settings.value (ws_color_mode).toInt (); - m_ws_enable_colors = new QCheckBox (tr ("Enable attribute colors")); - style_grid->addWidget (m_ws_enable_colors, row++, column, 1, 4); + m_ws_enable_colors = new QCheckBox (tr ("Enable attribute colors")); + style_grid->addWidget (m_ws_enable_colors, row++, column, 1, 4); - m_ws_hide_tool_tips = new QCheckBox (tr ("Hide tools tips")); - style_grid->addWidget (m_ws_hide_tool_tips, row++, column, 1, 4); - connect (m_ws_enable_colors, &QCheckBox::toggled, - m_ws_hide_tool_tips, &QCheckBox::setEnabled); - m_ws_hide_tool_tips->setChecked - (settings->value (ws_hide_tool_tips).toBool ()); + m_ws_hide_tool_tips = new QCheckBox (tr ("Hide tools tips")); + style_grid->addWidget (m_ws_hide_tool_tips, row++, column, 1, 4); + connect (m_ws_enable_colors, &QCheckBox::toggled, + m_ws_hide_tool_tips, &QCheckBox::setEnabled); + m_ws_hide_tool_tips->setChecked + (settings.value (ws_hide_tool_tips).toBool ()); - QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ())); - cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ())); - cb_color_mode->setChecked (mode == 1); - cb_color_mode->setObjectName (ws_color_mode.key); - connect (m_ws_enable_colors, &QCheckBox::toggled, - cb_color_mode, &QCheckBox::setEnabled); - style_grid->addWidget (cb_color_mode, row, column); + QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ())); + cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ())); + cb_color_mode->setChecked (mode == 1); + cb_color_mode->setObjectName (ws_color_mode.key); + connect (m_ws_enable_colors, &QCheckBox::toggled, + cb_color_mode, &QCheckBox::setEnabled); + style_grid->addWidget (cb_color_mode, row, column); - QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_colors.toStdString ().data ())); - pb_reload_default_colors->setToolTip (tr (settings_reload_colors_tooltip.toStdString ().data ())); - connect (m_ws_enable_colors, &QCheckBox::toggled, - pb_reload_default_colors, &QPushButton::setEnabled); - style_grid->addWidget (pb_reload_default_colors, row+1, column++); + QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_colors.toStdString ().data ())); + pb_reload_default_colors->setToolTip (tr (settings_reload_colors_tooltip.toStdString ().data ())); + connect (m_ws_enable_colors, &QCheckBox::toggled, + pb_reload_default_colors, &QPushButton::setEnabled); + style_grid->addWidget (pb_reload_default_colors, row+1, column++); - bool colors_enabled = settings->value (ws_enable_colors).toBool (); + bool colors_enabled = settings.value (ws_enable_colors).toBool (); - for (int i = 0; i < ws_colors_count; i++) - { - description[i] = new QLabel (" " - + tr (ws_color_names.at (i).toStdString ().data ())); - description[i]->setAlignment (Qt::AlignRight); - description[i]->setEnabled (colors_enabled); - connect (m_ws_enable_colors, &QCheckBox::toggled, - description[i], &QLabel::setEnabled); + for (int i = 0; i < ws_colors_count; i++) + { + description[i] = new QLabel (" " + + tr (ws_color_names.at (i).toStdString ().data ())); + description[i]->setAlignment (Qt::AlignRight); + description[i]->setEnabled (colors_enabled); + connect (m_ws_enable_colors, &QCheckBox::toggled, + description[i], &QLabel::setEnabled); - QColor setting_color = settings->color_value (ws_colors[i], mode); - color[i] = new color_picker (setting_color); - color[i]->setObjectName (ws_colors[i].key); - color[i]->setMinimumSize (30, 10); - color[i]->setEnabled (colors_enabled); - connect (m_ws_enable_colors, &QCheckBox::toggled, - color[i], &color_picker::setEnabled); + QColor setting_color = settings.color_value (ws_colors[i], mode); + color[i] = new color_picker (setting_color); + color[i]->setObjectName (ws_colors[i].key); + color[i]->setMinimumSize (30, 10); + color[i]->setEnabled (colors_enabled); + connect (m_ws_enable_colors, &QCheckBox::toggled, + color[i], &color_picker::setEnabled); - style_grid->addWidget (description[i], row, 3*column); - style_grid->addWidget (color[i], row, 3*column+1); - if (++column > color_columns) - { - style_grid->setColumnStretch (4*column, 10); - row++; - column = 1; - } - } + style_grid->addWidget (description[i], row, 3*column); + style_grid->addWidget (color[i], row, 3*column+1); + if (++column > color_columns) + { + style_grid->setColumnStretch (4*column, 10); + row++; + column = 1; + } + } - // Load enable settings at the end for having signals already connected - m_ws_enable_colors->setChecked (colors_enabled); - m_ws_hide_tool_tips->setEnabled (colors_enabled); - cb_color_mode->setEnabled (colors_enabled); - pb_reload_default_colors->setEnabled (colors_enabled); + // Load enable settings at the end for having signals already connected + m_ws_enable_colors->setChecked (colors_enabled); + m_ws_hide_tool_tips->setEnabled (colors_enabled); + cb_color_mode->setEnabled (colors_enabled); + pb_reload_default_colors->setEnabled (colors_enabled); - // place grid with elements into the tab - workspace_colors_box->setLayout (style_grid); + // place grid with elements into the tab + workspace_colors_box->setLayout (style_grid); - // update colors depending on second theme selection or reloading - // the dfault values - connect (cb_color_mode, &QCheckBox::stateChanged, - this, &settings_dialog::update_workspace_colors); - connect (pb_reload_default_colors, &QPushButton::clicked, - [=] () { update_workspace_colors (settings_reload_default_colors_flag); }); -} + // update colors depending on second theme selection or reloading + // the dfault values + connect (cb_color_mode, &QCheckBox::stateChanged, + this, &settings_dialog::update_workspace_colors); + connect (pb_reload_default_colors, &QPushButton::clicked, + [=] () { update_workspace_colors (settings_reload_default_colors_flag); }); + } -void settings_dialog::update_workspace_colors (int def) -{ - QCheckBox *cb_color_mode - = workspace_colors_box->findChild (ws_color_mode.key); + void settings_dialog::update_workspace_colors (int def) + { + QCheckBox *cb_color_mode + = workspace_colors_box->findChild (ws_color_mode.key); - int m = 0; - if (cb_color_mode && cb_color_mode->isChecked ()) - m = 1; + int m = 0; + if (cb_color_mode && cb_color_mode->isChecked ()) + m = 1; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - color_picker *c_picker; + color_picker *c_picker; - for (unsigned int i = 0; i < ws_colors_count; i++) - { - c_picker = workspace_colors_box->findChild (ws_colors[i].key); - if (c_picker) - { - if (def != settings_reload_default_colors_flag) - { - // Get current value from settings or the default - c_picker->set_color (settings->color_value (ws_colors[i], m)); - } - else - { - // Get the default value - c_picker->set_color (settings->get_color_value (ws_colors[i].def, m)); - } - } - } -} + for (unsigned int i = 0; i < ws_colors_count; i++) + { + c_picker = workspace_colors_box->findChild (ws_colors[i].key); + if (c_picker) + { + if (def != settings_reload_default_colors_flag) + { + // Get current value from settings or the default + c_picker->set_color (settings.color_value (ws_colors[i], m)); + } + else + { + // Get the default value + c_picker->set_color (settings.get_color_value (ws_colors[i].def, m)); + } + } + } + } -void settings_dialog::write_workspace_colors (gui_settings *settings) -{ - settings->setValue (ws_enable_colors.key, m_ws_enable_colors->isChecked ()); - settings->setValue (ws_hide_tool_tips.key, m_ws_hide_tool_tips->isChecked ()); + void settings_dialog::write_workspace_colors (void) + { + gui_settings settings; + + settings.setValue (ws_enable_colors.key, m_ws_enable_colors->isChecked ()); + settings.setValue (ws_hide_tool_tips.key, m_ws_hide_tool_tips->isChecked ()); - QCheckBox *cb_color_mode - = workspace_colors_box->findChild (ws_color_mode.key); + QCheckBox *cb_color_mode + = workspace_colors_box->findChild (ws_color_mode.key); - int mode = 0; - if (cb_color_mode && cb_color_mode->isChecked ()) - mode = 1; + int mode = 0; + if (cb_color_mode && cb_color_mode->isChecked ()) + mode = 1; - color_picker *color; + color_picker *color; - for (int i = 0; i < ws_colors_count; i++) - { - color = workspace_colors_box->findChild (ws_colors[i].key); - if (color) - settings->set_color_value (ws_colors[i], color->color (), mode); - } + for (int i = 0; i < ws_colors_count; i++) + { + color = workspace_colors_box->findChild (ws_colors[i].key); + if (color) + settings.set_color_value (ws_colors[i], color->color (), mode); + } - settings->setValue (ws_color_mode.key, mode); + settings.setValue (ws_color_mode.key, mode); - settings->sync (); -} + settings.sync (); + } -void settings_dialog::read_terminal_colors (gui_settings *settings) -{ - QGridLayout *style_grid = new QGridLayout (); - QVector description (cs_colors_count); - QVector color (cs_colors_count); + void settings_dialog::read_terminal_colors (void) + { + gui_settings settings; - int mode = settings->value (cs_color_mode).toInt (); + QGridLayout *style_grid = new QGridLayout (); + QVector description (cs_colors_count); + QVector color (cs_colors_count); + + int mode = settings.value (cs_color_mode).toInt (); - QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ())); - cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ())); - cb_color_mode->setChecked (mode == 1); - cb_color_mode->setObjectName (cs_color_mode.key); - style_grid->addWidget (cb_color_mode, 0, 0); + QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ())); + cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ())); + cb_color_mode->setChecked (mode == 1); + cb_color_mode->setObjectName (cs_color_mode.key); + style_grid->addWidget (cb_color_mode, 0, 0); - QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_colors.toStdString ().data ())); - pb_reload_default_colors->setToolTip (tr (settings_reload_colors_tooltip.toStdString ().data ())); - style_grid->addWidget (pb_reload_default_colors, 1, 0); + QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_colors.toStdString ().data ())); + pb_reload_default_colors->setToolTip (tr (settings_reload_colors_tooltip.toStdString ().data ())); + style_grid->addWidget (pb_reload_default_colors, 1, 0); - int column = 1; // column 0 is for the color mode checkbox - const int color_columns = 2; // place colors in so many columns - int row = 0; - for (unsigned int i = 0; i < cs_colors_count; i++) - { - description[i] = new QLabel (" " - + tr (cs_color_names.at (i).toStdString ().data ())); - description[i]->setAlignment (Qt::AlignRight); - QColor setting_color = settings->color_value (cs_colors[i], mode); - color[i] = new color_picker (setting_color); - color[i]->setObjectName (cs_colors[i].key); - color[i]->setMinimumSize (30, 10); - style_grid->addWidget (description[i], row, 2*column); - style_grid->addWidget (color[i], row, 2*column+1); - if (++column > color_columns) - { - style_grid->setColumnStretch (3*column, 10); - row++; - column = 1; - } - } + int column = 1; // column 0 is for the color mode checkbox + const int color_columns = 2; // place colors in so many columns + int row = 0; + for (unsigned int i = 0; i < cs_colors_count; i++) + { + description[i] = new QLabel (" " + + tr (cs_color_names.at (i).toStdString ().data ())); + description[i]->setAlignment (Qt::AlignRight); + QColor setting_color = settings.color_value (cs_colors[i], mode); + color[i] = new color_picker (setting_color); + color[i]->setObjectName (cs_colors[i].key); + color[i]->setMinimumSize (30, 10); + style_grid->addWidget (description[i], row, 2*column); + style_grid->addWidget (color[i], row, 2*column+1); + if (++column > color_columns) + { + style_grid->setColumnStretch (3*column, 10); + row++; + column = 1; + } + } - // place grid with elements into the tab - terminal_colors_box->setLayout (style_grid); + // place grid with elements into the tab + terminal_colors_box->setLayout (style_grid); - // update colors depending on second theme selection - connect (cb_color_mode, &QCheckBox::stateChanged, - this, &settings_dialog::update_terminal_colors); - connect (pb_reload_default_colors, &QPushButton::clicked, - [=] () { update_terminal_colors (settings_reload_default_colors_flag); }); -} + // update colors depending on second theme selection + connect (cb_color_mode, &QCheckBox::stateChanged, + this, &settings_dialog::update_terminal_colors); + connect (pb_reload_default_colors, &QPushButton::clicked, + [=] () { update_terminal_colors (settings_reload_default_colors_flag); }); + } -void settings_dialog::update_terminal_colors (int def) -{ - QCheckBox *cb_color_mode - = terminal_colors_box->findChild (cs_color_mode.key); + void settings_dialog::update_terminal_colors (int def) + { + QCheckBox *cb_color_mode + = terminal_colors_box->findChild (cs_color_mode.key); - int m = 0; - if (cb_color_mode && cb_color_mode->isChecked ()) - m = 1; + int m = 0; + if (cb_color_mode && cb_color_mode->isChecked ()) + m = 1; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - color_picker *c_picker; + color_picker *c_picker; - for (unsigned int i = 0; i < cs_colors_count; i++) - { - c_picker = terminal_colors_box->findChild (cs_colors[i].key); - if (c_picker) - { - if (def != settings_reload_default_colors_flag) - { - // Get current value from settings or the default - c_picker->set_color (settings->color_value (cs_colors[i], m)); - } - else - { - // Get the default value - c_picker->set_color (settings->get_color_value (cs_colors[i].def, m)); - } - } - } -} + for (unsigned int i = 0; i < cs_colors_count; i++) + { + c_picker = terminal_colors_box->findChild (cs_colors[i].key); + if (c_picker) + { + if (def != settings_reload_default_colors_flag) + { + // Get current value from settings or the default + c_picker->set_color (settings.color_value (cs_colors[i], m)); + } + else + { + // Get the default value + c_picker->set_color (settings.get_color_value (cs_colors[i].def, m)); + } + } + } + } -void settings_dialog::write_terminal_colors (gui_settings *settings) -{ - QCheckBox *cb_color_mode - = terminal_colors_box->findChild (cs_color_mode.key); + void settings_dialog::write_terminal_colors (void) + { + QCheckBox *cb_color_mode + = terminal_colors_box->findChild (cs_color_mode.key); - int mode = 0; - if (cb_color_mode && cb_color_mode->isChecked ()) - mode = 1; + int mode = 0; + if (cb_color_mode && cb_color_mode->isChecked ()) + mode = 1; - color_picker *color; + gui_settings settings; - for (int i = 0; i < cs_color_names.size (); i++) - { - color = terminal_colors_box->findChild (cs_colors[i].key); - if (color) - settings->set_color_value (cs_colors[i], color->color (), mode); - } + color_picker *color; + + for (int i = 0; i < cs_color_names.size (); i++) + { + color = terminal_colors_box->findChild (cs_colors[i].key); + if (color) + settings.set_color_value (cs_colors[i], color->color (), mode); + } - settings->setValue (cs_color_mode.key, mode); + settings.setValue (cs_color_mode.key, mode); - settings->sync (); -} + settings.sync (); + } -void settings_dialog::read_varedit_colors (gui_settings *settings) -{ - QGridLayout *style_grid = new QGridLayout (); - QVector description (ve_colors_count); - QVector color (ve_colors_count); + void settings_dialog::read_varedit_colors (void) + { + gui_settings settings; - int mode = settings->value (ve_color_mode).toInt (); + QGridLayout *style_grid = new QGridLayout (); + QVector description (ve_colors_count); + QVector color (ve_colors_count); + + int mode = settings.value (ve_color_mode).toInt (); - QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ())); - cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ())); - cb_color_mode->setChecked (mode == 1); - cb_color_mode->setObjectName (ve_color_mode.key); - style_grid->addWidget (cb_color_mode, 0, 0); + QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ())); + cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ())); + cb_color_mode->setChecked (mode == 1); + cb_color_mode->setObjectName (ve_color_mode.key); + style_grid->addWidget (cb_color_mode, 0, 0); - QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_colors.toStdString ().data ())); - pb_reload_default_colors->setToolTip (tr (settings_reload_colors_tooltip.toStdString ().data ())); - style_grid->addWidget (pb_reload_default_colors, 1, 0); + QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_colors.toStdString ().data ())); + pb_reload_default_colors->setToolTip (tr (settings_reload_colors_tooltip.toStdString ().data ())); + style_grid->addWidget (pb_reload_default_colors, 1, 0); - int column = 1; - int color_columns = 2; - int row = 0; - for (int i = 0; i < ve_colors_count; i++) - { - description[i] = new QLabel (" " - + tr (ve_color_names.at (i).toStdString ().data ())); - description[i]->setAlignment (Qt::AlignRight); + int column = 1; + int color_columns = 2; + int row = 0; + for (int i = 0; i < ve_colors_count; i++) + { + description[i] = new QLabel (" " + + tr (ve_color_names.at (i).toStdString ().data ())); + description[i]->setAlignment (Qt::AlignRight); - QColor setting_color = settings->color_value (ve_colors[i], mode); - color[i] = new color_picker (setting_color); - color[i]->setObjectName (ve_colors[i].key); - color[i]->setMinimumSize (30, 10); - style_grid->addWidget (description[i], row, 2*column); - style_grid->addWidget (color[i], row, 2*column+1); - if (++column > color_columns) - { - style_grid->setColumnStretch (3*column, 10); - row++; - column = 1; - } - } + QColor setting_color = settings.color_value (ve_colors[i], mode); + color[i] = new color_picker (setting_color); + color[i]->setObjectName (ve_colors[i].key); + color[i]->setMinimumSize (30, 10); + style_grid->addWidget (description[i], row, 2*column); + style_grid->addWidget (color[i], row, 2*column+1); + if (++column > color_columns) + { + style_grid->setColumnStretch (3*column, 10); + row++; + column = 1; + } + } - // place grid with elements into the tab - varedit_colors_box->setLayout (style_grid); + // place grid with elements into the tab + varedit_colors_box->setLayout (style_grid); - // update colors depending on second theme selection - connect (cb_color_mode, &QCheckBox::stateChanged, - this, &settings_dialog::update_varedit_colors); - connect (pb_reload_default_colors, &QPushButton::clicked, - [=] () { update_varedit_colors (settings_reload_default_colors_flag); }); -} + // update colors depending on second theme selection + connect (cb_color_mode, &QCheckBox::stateChanged, + this, &settings_dialog::update_varedit_colors); + connect (pb_reload_default_colors, &QPushButton::clicked, + [=] () { update_varedit_colors (settings_reload_default_colors_flag); }); + } -void settings_dialog::update_varedit_colors (int def) -{ - QCheckBox *cb_color_mode - = varedit_colors_box->findChild (ve_color_mode.key); + void settings_dialog::update_varedit_colors (int def) + { + QCheckBox *cb_color_mode + = varedit_colors_box->findChild (ve_color_mode.key); - int m = 0; - if (cb_color_mode && cb_color_mode->isChecked ()) - m = 1; + int m = 0; + if (cb_color_mode && cb_color_mode->isChecked ()) + m = 1; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - color_picker *c_picker; + color_picker *c_picker; - for (unsigned int i = 0; i < ve_colors_count; i++) - { - c_picker = varedit_colors_box->findChild (ve_colors[i].key); - if (c_picker) - { - if (def != settings_reload_default_colors_flag) - { - // Get current value from settings or the default - c_picker->set_color (settings->color_value (ve_colors[i], m)); - } - else - { - // Get the default value - c_picker->set_color (settings->get_color_value (ve_colors[i].def, m)); - } - } - } -} + for (unsigned int i = 0; i < ve_colors_count; i++) + { + c_picker = varedit_colors_box->findChild (ve_colors[i].key); + if (c_picker) + { + if (def != settings_reload_default_colors_flag) + { + // Get current value from settings or the default + c_picker->set_color (settings.color_value (ve_colors[i], m)); + } + else + { + // Get the default value + c_picker->set_color (settings.get_color_value (ve_colors[i].def, m)); + } + } + } + } -void settings_dialog::write_varedit_colors (gui_settings *settings) -{ - QCheckBox *cb_color_mode - = varedit_colors_box->findChild (ve_color_mode.key); + void settings_dialog::write_varedit_colors (void) + { + QCheckBox *cb_color_mode + = varedit_colors_box->findChild (ve_color_mode.key); - int mode = 0; - if (cb_color_mode && cb_color_mode->isChecked ()) - mode = 1; + int mode = 0; + if (cb_color_mode && cb_color_mode->isChecked ()) + mode = 1; - color_picker *color; + gui_settings settings; - for (int i = 0; i < ve_colors_count; i++) - { - color = varedit_colors_box->findChild (ve_colors[i].key); - if (color) - settings->set_color_value (ve_colors[i], color->color (), mode); - } + color_picker *color; - settings->setValue (ve_color_mode.key, mode); + for (int i = 0; i < ve_colors_count; i++) + { + color = varedit_colors_box->findChild (ve_colors[i].key); + if (color) + settings.set_color_value (ve_colors[i], color->color (), mode); + } - settings->sync (); -} + settings.setValue (ve_color_mode.key, mode); + + settings.sync (); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/settings-dialog.h --- a/libgui/src/settings-dialog.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/settings-dialog.h Tue Dec 06 15:45:27 2022 -0500 @@ -33,86 +33,85 @@ #include "color-picker.h" #include "gui-preferences-ed.h" -#include "gui-settings.h" #include "ui-settings-dialog.h" class QsciLexer; OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; + class base_qobject; -// Ui::settings_dialog is a generated class. + // Ui::settings_dialog is a generated class. -class settings_dialog : public QDialog, private Ui::settings_dialog -{ + class settings_dialog : public QDialog, private Ui::settings_dialog + { Q_OBJECT public: - explicit settings_dialog (QWidget *parent, base_qobject& octave_qobj, - const QString& desired_tab = QString ()); + explicit settings_dialog (QWidget *parent, base_qobject& octave_qobj, + const QString& desired_tab = QString ()); - ~settings_dialog (void) = default; + ~settings_dialog (void) = default; - void show_tab (const QString&); + void show_tab (const QString&); -signals: + signals: - void apply_new_settings (void); + void apply_new_settings (void); -private slots: + private slots: - void get_octave_dir (void); - void get_file_browser_dir (void); - void get_dir (QLineEdit *, const QString&); - void set_disabled_pref_file_browser_dir (bool disable); - void proxy_items_update (void); + void get_octave_dir (void); + void get_file_browser_dir (void); + void get_dir (QLineEdit *, const QString&); + void set_disabled_pref_file_browser_dir (bool disable); + void proxy_items_update (void); - // slots updating colors depending on theme - void update_terminal_colors (int def = 0); - void update_workspace_colors (int def = 0); - void update_varedit_colors (int def = 0); - void update_editor_lexers (int def = 0); + // slots updating colors depending on theme + void update_terminal_colors (int def = 0); + void update_workspace_colors (int def = 0); + void update_varedit_colors (int def = 0); + void update_editor_lexers (int def = 0); - // slots for dialog's buttons - void button_clicked (QAbstractButton *button); + // slots for dialog's buttons + void button_clicked (QAbstractButton *button); - // slots for import/export-buttons of shortcut sets - void import_shortcut_set (void); - void export_shortcut_set (void); - void default_shortcut_set (void); + // slots for import/export-buttons of shortcut sets + void import_shortcut_set (void); + void export_shortcut_set (void); + void default_shortcut_set (void); -private: + private: #if defined (HAVE_QSCINTILLA) - void update_lexer (QsciLexer *lexer, gui_settings *settings, int mode, int def = 0); - void get_lexer_settings (QsciLexer *lexer, gui_settings *settings); - void write_lexer_settings (QsciLexer *lexer, gui_settings *settings); + void update_lexer (QsciLexer *lexer, int mode, int def = 0); + void get_lexer_settings (QsciLexer *lexer); + void write_lexer_settings (QsciLexer *lexer); #endif - void write_changed_settings (bool closing); + void write_changed_settings (bool closing); - void read_workspace_colors (gui_settings *settings); - void write_workspace_colors (gui_settings *settings); + void read_workspace_colors (void); + void write_workspace_colors (void); - void read_terminal_colors (gui_settings *settings); - void write_terminal_colors (gui_settings *settings); + void read_terminal_colors (void); + void write_terminal_colors (void); - void read_varedit_colors (gui_settings *settings); - void write_varedit_colors (gui_settings *settings); + void read_varedit_colors (void); + void write_varedit_colors (void); - base_qobject& m_octave_qobj; + base_qobject& m_octave_qobj; - color_picker *m_widget_title_bg_color; - color_picker *m_widget_title_bg_color_active; - color_picker *m_widget_title_fg_color; - color_picker *m_widget_title_fg_color_active; + color_picker *m_widget_title_bg_color; + color_picker *m_widget_title_bg_color_active; + color_picker *m_widget_title_fg_color; + color_picker *m_widget_title_fg_color_active; - QRadioButton *m_rb_comment_strings[ed_comment_strings_count]; - QCheckBox *m_rb_uncomment_strings[ed_comment_strings_count]; + QRadioButton *m_rb_comment_strings[ed_comment_strings_count]; + QCheckBox *m_rb_uncomment_strings[ed_comment_strings_count]; - QCheckBox *m_ws_enable_colors; - QCheckBox *m_ws_hide_tool_tips; -}; + QCheckBox *m_ws_enable_colors; + QCheckBox *m_ws_hide_tool_tips; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/shortcut-manager.cc --- a/libgui/src/shortcut-manager.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/shortcut-manager.cc Tue Dec 06 15:45:27 2022 -0500 @@ -42,757 +42,780 @@ #include #include -#include "octave-qobject.h" #include "shortcut-manager.h" #include "gui-preferences-global.h" #include "gui-preferences-sc.h" +#include "gui-settings.h" #include "error.h" OCTAVE_BEGIN_NAMESPACE(octave) -// enter_shortcut: -// class derived from QLineEdit for directly entering key sequences which + // enter_shortcut: + // class derived from QLineEdit for directly entering key sequences which -enter_shortcut::enter_shortcut (QWidget *p) : QLineEdit (p) -{ - m_direct_shortcut = true; // the shortcut is directly entered - m_shift_modifier = false; // the shift modifier is not added -} + enter_shortcut::enter_shortcut (QWidget *p) : QLineEdit (p) + { + m_direct_shortcut = true; // the shortcut is directly entered + m_shift_modifier = false; // the shift modifier is not added + } -// new keyPressEvent -void enter_shortcut::keyPressEvent (QKeyEvent *e) -{ - if (! m_direct_shortcut) - { - QLineEdit::keyPressEvent (e); - return; - } + // new keyPressEvent + void enter_shortcut::keyPressEvent (QKeyEvent *e) + { + if (! m_direct_shortcut) + { + QLineEdit::keyPressEvent (e); + return; + } - if (e->type () == QEvent::KeyPress) - { - int key = e->key (); + if (e->type () == QEvent::KeyPress) + { + int key = e->key (); - if (key == Qt::Key_unknown || key == 0) - return; + if (key == Qt::Key_unknown || key == 0) + return; - Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers (); //e->modifiers (); + Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers (); //e->modifiers (); - if (m_shift_modifier || (modifiers & Qt::ShiftModifier)) - key += Qt::SHIFT; - if (modifiers & Qt::ControlModifier) - key += Qt::CTRL; - if (modifiers & Qt::AltModifier) - key += Qt::ALT; - if (modifiers & Qt::MetaModifier) - key += Qt::META; + if (m_shift_modifier || (modifiers & Qt::ShiftModifier)) + key += Qt::SHIFT; + if (modifiers & Qt::ControlModifier) + key += Qt::CTRL; + if (modifiers & Qt::AltModifier) + key += Qt::ALT; + if (modifiers & Qt::MetaModifier) + key += Qt::META; - setText (QKeySequence (key).toString ()); - } -} + setText (QKeySequence (key).toString ()); + } + } -// slot for checkbox whether the shortcut is directly entered or not -void enter_shortcut::handle_direct_shortcut (int state) -{ - if (state) - m_direct_shortcut = true; // the shortcut is directly entered - else - m_direct_shortcut = false; // the shortcut has to be written as text -} + // slot for checkbox whether the shortcut is directly entered or not + void enter_shortcut::handle_direct_shortcut (int state) + { + if (state) + m_direct_shortcut = true; // the shortcut is directly entered + else + m_direct_shortcut = false; // the shortcut has to be written as text + } -// slot for checkbox whether the shift modifier should be added -void enter_shortcut::handle_shift_modifier (int state) -{ - if (state) - m_shift_modifier = true; // the shortcut is directly entered - else - m_shift_modifier = false; // the shortcut has to be written as text -} + // slot for checkbox whether the shift modifier should be added + void enter_shortcut::handle_shift_modifier (int state) + { + if (state) + m_shift_modifier = true; // the shortcut is directly entered + else + m_shift_modifier = false; // the shortcut has to be written as text + } -shortcut_manager::shortcut_manager (base_qobject& oct_qobj) - : m_octave_qobj (oct_qobj) -{ - setObjectName ("Shortcut_Manager"); + shortcut_manager::shortcut_manager (void) + { + setObjectName ("Shortcut_Manager"); - // Mac: don't let Qt interpret CMD key ("Meta" in Qt terminology) as Ctrl + // Mac: don't let Qt interpret CMD key ("Meta" in Qt terminology) as Ctrl #if defined (Q_OS_MAC) - QCoreApplication::setAttribute (Qt::AA_MacDontSwapCtrlAndMeta, true); + QCoreApplication::setAttribute (Qt::AA_MacDontSwapCtrlAndMeta, true); #endif -} + } -void shortcut_manager::init_data (void) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + void shortcut_manager::init_data (void) + { + gui_settings settings; - settings->setValue (sc_main_ctrld.key, false); // reset use fo ctrl-d + settings.setValue (sc_main_ctrld.key, false); // reset use fo ctrl-d - // actions not related to specific menus or widgets + // actions not related to specific menus or widgets - // dock widgets - init (tr ("Undock/Dock Widget"), sc_dock_widget_dock); - init (tr ("Close Widget"), sc_dock_widget_close); + // dock widgets + init (tr ("Undock/Dock Widget"), sc_dock_widget_dock); + init (tr ("Close Widget"), sc_dock_widget_close); - // actions of the main window + // actions of the main window - // file - init (tr ("New File"), sc_main_file_new_file); - init (tr ("New Function"), sc_main_file_new_function); - init (tr ("New Figure"), sc_main_file_new_figure); - init (tr ("Open File"), sc_main_file_open_file); - init (tr ("Load Workspace"), sc_main_file_load_workspace); - init (tr ("Save Workspace As"), sc_main_file_save_workspace); - init (tr ("Exit Octave"), sc_main_file_exit); + // file + init (tr ("New File"), sc_main_file_new_file); + init (tr ("New Function"), sc_main_file_new_function); + init (tr ("New Figure"), sc_main_file_new_figure); + init (tr ("Open File"), sc_main_file_open_file); + init (tr ("Load Workspace"), sc_main_file_load_workspace); + init (tr ("Save Workspace As"), sc_main_file_save_workspace); + init (tr ("Exit Octave"), sc_main_file_exit); - // edit - init (tr ("Copy"), sc_main_edit_copy); - init (tr ("Paste"), sc_main_edit_paste); - init (tr ("Undo"), sc_main_edit_undo); - init (tr ("Select All"), sc_main_edit_select_all); - init (tr ("Clear Clipboard"), sc_main_edit_clear_clipboard); - init (tr ("Find in Files"), sc_main_edit_find_in_files); - init (tr ("Clear Command Window"), sc_main_edit_clear_command_window); - init (tr ("Clear Command History"), sc_main_edit_clear_history); - init (tr ("Clear Workspace"), sc_main_edit_clear_workspace); - init (tr ("Set Path"), sc_main_edit_set_path); - init (tr ("Preferences"), sc_main_edit_preferences); + // edit + init (tr ("Copy"), sc_main_edit_copy); + init (tr ("Paste"), sc_main_edit_paste); + init (tr ("Undo"), sc_main_edit_undo); + init (tr ("Select All"), sc_main_edit_select_all); + init (tr ("Clear Clipboard"), sc_main_edit_clear_clipboard); + init (tr ("Find in Files"), sc_main_edit_find_in_files); + init (tr ("Clear Command Window"), sc_main_edit_clear_command_window); + init (tr ("Clear Command History"), sc_main_edit_clear_history); + init (tr ("Clear Workspace"), sc_main_edit_clear_workspace); + init (tr ("Set Path"), sc_main_edit_set_path); + init (tr ("Preferences"), sc_main_edit_preferences); - // debug - init (tr ("Step"), sc_main_debug_step_over); - init (tr ("Step Into"), sc_main_debug_step_into); - init (tr ("Step Out"), sc_main_debug_step_out); - init (tr ("Continue"), sc_main_debug_continue); - init (tr ("Quit Debug Mode"), sc_main_debug_quit); + // debug + init (tr ("Step"), sc_main_debug_step_over); + init (tr ("Step Into"), sc_main_debug_step_into); + init (tr ("Step Out"), sc_main_debug_step_out); + init (tr ("Continue"), sc_main_debug_continue); + init (tr ("Quit Debug Mode"), sc_main_debug_quit); - // tools - init (tr ("Start/Stop Profiler Session"), sc_main_tools_start_profiler); - init (tr ("Resume Profiler Session"), sc_main_tools_resume_profiler); - init (tr ("Show Profile Data"), sc_main_tools_show_profiler); + // tools + init (tr ("Start/Stop Profiler Session"), sc_main_tools_start_profiler); + init (tr ("Resume Profiler Session"), sc_main_tools_resume_profiler); + init (tr ("Show Profile Data"), sc_main_tools_show_profiler); - // window - init (tr ("Show Command Window"), sc_main_window_show_command); - init (tr ("Show Command History"), sc_main_window_show_history); - init (tr ("Show File Browser"), sc_main_window_show_file_browser); - init (tr ("Show Workspace"), sc_main_window_show_workspace); - init (tr ("Show Editor"), sc_main_window_show_editor); - init (tr ("Show Documentation"), sc_main_window_show_doc); - init (tr ("Show Variable Editor"), sc_main_window_show_variable_editor); - init (tr ("Command Window"), sc_main_window_command); - init (tr ("Command History"), sc_main_window_history); - init (tr ("File Browser"), sc_main_window_file_browser); - init (tr ("Workspace"), sc_main_window_workspace); - init (tr ("Editor"), sc_main_window_editor); - init (tr ("Documentation"), sc_main_window_doc); - init (tr ("Variable Editor"), sc_main_window_variable_editor); - init (tr ("Previous Widget"), sc_main_window_previous_dock); - init (tr ("Reset Default Window Layout"), sc_main_window_reset); + // window + init (tr ("Show Command Window"), sc_main_window_show_command); + init (tr ("Show Command History"), sc_main_window_show_history); + init (tr ("Show File Browser"), sc_main_window_show_file_browser); + init (tr ("Show Workspace"), sc_main_window_show_workspace); + init (tr ("Show Editor"), sc_main_window_show_editor); + init (tr ("Show Documentation"), sc_main_window_show_doc); + init (tr ("Show Variable Editor"), sc_main_window_show_variable_editor); + init (tr ("Command Window"), sc_main_window_command); + init (tr ("Command History"), sc_main_window_history); + init (tr ("File Browser"), sc_main_window_file_browser); + init (tr ("Workspace"), sc_main_window_workspace); + init (tr ("Editor"), sc_main_window_editor); + init (tr ("Documentation"), sc_main_window_doc); + init (tr ("Variable Editor"), sc_main_window_variable_editor); + init (tr ("Previous Widget"), sc_main_window_previous_dock); + init (tr ("Reset Default Window Layout"), sc_main_window_reset); - // help - init (tr ("Show On-disk Documentation"), sc_main_help_ondisk_doc); - init (tr ("Show Online Documentation"), sc_main_help_online_doc); - init (tr ("Report Bug"), sc_main_help_report_bug); - init (tr ("Octave Packages"), sc_main_help_packages); - init (tr ("Contribute to Octave"), sc_main_help_contribute); - init (tr ("Octave Developer Resources"), sc_main_help_developer); - init (tr ("About Octave"), sc_main_help_about); + // help + init (tr ("Show On-disk Documentation"), sc_main_help_ondisk_doc); + init (tr ("Show Online Documentation"), sc_main_help_online_doc); + init (tr ("Report Bug"), sc_main_help_report_bug); + init (tr ("Octave Packages"), sc_main_help_packages); + init (tr ("Contribute to Octave"), sc_main_help_contribute); + init (tr ("Octave Developer Resources"), sc_main_help_developer); + init (tr ("About Octave"), sc_main_help_about); - // news - init (tr ("Release Notes"), sc_main_news_release_notes); - init (tr ("Community News"), sc_main_news_community_news); + // news + init (tr ("Release Notes"), sc_main_news_release_notes); + init (tr ("Community News"), sc_main_news_community_news); - // Tab handling - // The following shortcuts are moved into a separate tab. The key names - // are not changed, to preserve compatibility with older versions. - init (tr ("Close Tab"), sc_edit_file_close); - init (tr ("Close All Tabs"), sc_edit_file_close_all); - init (tr ("Close Other Tabs"), sc_edit_file_close_other); - init (tr ("Switch to Left Tab"), sc_edit_tabs_switch_left_tab); - init (tr ("Switch to Right Tab"), sc_edit_tabs_switch_right_tab); - init (tr ("Move Tab Left"), sc_edit_tabs_move_tab_left); - init (tr ("Move Tab Right"), sc_edit_tabs_move_tab_right); + // Tab handling + // The following shortcuts are moved into a separate tab. The key names + // are not changed, to preserve compatibility with older versions. + init (tr ("Close Tab"), sc_edit_file_close); + init (tr ("Close All Tabs"), sc_edit_file_close_all); + init (tr ("Close Other Tabs"), sc_edit_file_close_other); + init (tr ("Switch to Left Tab"), sc_edit_tabs_switch_left_tab); + init (tr ("Switch to Right Tab"), sc_edit_tabs_switch_right_tab); + init (tr ("Move Tab Left"), sc_edit_tabs_move_tab_left); + init (tr ("Move Tab Right"), sc_edit_tabs_move_tab_right); - // Zooming - init (tr ("Zoom In"), sc_edit_view_zoom_in); - init (tr ("Zoom Out"), sc_edit_view_zoom_out); + // Zooming + init (tr ("Zoom In"), sc_edit_view_zoom_in); + init (tr ("Zoom Out"), sc_edit_view_zoom_out); #if defined (Q_OS_MAC) - init (tr ("Zoom Normal"), sc_edit_view_zoom_normal); + init (tr ("Zoom Normal"), sc_edit_view_zoom_normal); #else - init (tr ("Zoom Normal"), sc_edit_view_zoom_normal); + init (tr ("Zoom Normal"), sc_edit_view_zoom_normal); #endif - // actions of the editor + // actions of the editor - // file - init (tr ("Edit Function"), sc_edit_file_edit_function); - init (tr ("Save File"), sc_edit_file_save); - init (tr ("Save File As"), sc_edit_file_save_as); - init (tr ("Print"), sc_edit_file_print); + // file + init (tr ("Edit Function"), sc_edit_file_edit_function); + init (tr ("Save File"), sc_edit_file_save); + init (tr ("Save File As"), sc_edit_file_save_as); + init (tr ("Print"), sc_edit_file_print); - // edit - init (tr ("Redo"), sc_edit_edit_redo); - init (tr ("Cut"), sc_edit_edit_cut); - init (tr ("Find and Replace"), sc_edit_edit_find_replace); - init (tr ("Find Next"), sc_edit_edit_find_next); - init (tr ("Find Previous"), sc_edit_edit_find_previous); - init (tr ("Delete to Start of Word"), sc_edit_edit_delete_start_word); - init (tr ("Delete to End of Word"), sc_edit_edit_delete_end_word); - init (tr ("Delete to Start of Line"), sc_edit_edit_delete_start_line); - init (tr ("Delete to End of Line"), sc_edit_edit_delete_end_line); - init (tr ("Delete Line"), sc_edit_edit_delete_line); - init (tr ("Copy Line"), sc_edit_edit_copy_line); - init (tr ("Cut Line"), sc_edit_edit_cut_line); - init (tr ("Duplicate Selection/Line"), sc_edit_edit_duplicate_selection); - init (tr ("Transpose Line"), sc_edit_edit_transpose_line); - init (tr ("Show Completion List"), sc_edit_edit_completion_list); + // edit + init (tr ("Redo"), sc_edit_edit_redo); + init (tr ("Cut"), sc_edit_edit_cut); + init (tr ("Find and Replace"), sc_edit_edit_find_replace); + init (tr ("Find Next"), sc_edit_edit_find_next); + init (tr ("Find Previous"), sc_edit_edit_find_previous); + init (tr ("Delete to Start of Word"), sc_edit_edit_delete_start_word); + init (tr ("Delete to End of Word"), sc_edit_edit_delete_end_word); + init (tr ("Delete to Start of Line"), sc_edit_edit_delete_start_line); + init (tr ("Delete to End of Line"), sc_edit_edit_delete_end_line); + init (tr ("Delete Line"), sc_edit_edit_delete_line); + init (tr ("Copy Line"), sc_edit_edit_copy_line); + init (tr ("Cut Line"), sc_edit_edit_cut_line); + init (tr ("Duplicate Selection/Line"), sc_edit_edit_duplicate_selection); + init (tr ("Transpose Line"), sc_edit_edit_transpose_line); + init (tr ("Show Completion List"), sc_edit_edit_completion_list); - init (tr ("Comment Selection"), sc_edit_edit_comment_selection); - init (tr ("Uncomment Selection"), sc_edit_edit_uncomment_selection); - init (tr ("Comment Selection (Choosing String)"), sc_edit_edit_comment_var_selection); - init (tr ("Uppercase Selection"), sc_edit_edit_upper_case); - init (tr ("Lowercase Selection"), sc_edit_edit_lower_case); + init (tr ("Comment Selection"), sc_edit_edit_comment_selection); + init (tr ("Uncomment Selection"), sc_edit_edit_uncomment_selection); + init (tr ("Comment Selection (Choosing String)"), sc_edit_edit_comment_var_selection); + init (tr ("Uppercase Selection"), sc_edit_edit_upper_case); + init (tr ("Lowercase Selection"), sc_edit_edit_lower_case); #if defined (Q_OS_MAC) - init (tr ("Indent Selection Rigidly"), sc_edit_edit_indent_selection); - init (tr ("Unindent Selection Rigidly"), sc_edit_edit_unindent_selection); + init (tr ("Indent Selection Rigidly"), sc_edit_edit_indent_selection); + init (tr ("Unindent Selection Rigidly"), sc_edit_edit_unindent_selection); #else - init (tr ("Indent Selection Rigidly"), sc_edit_edit_indent_selection); - init (tr ("Unindent Selection Rigidly"), sc_edit_edit_unindent_selection); + init (tr ("Indent Selection Rigidly"), sc_edit_edit_indent_selection); + init (tr ("Unindent Selection Rigidly"), sc_edit_edit_unindent_selection); #endif - init (tr ("Indent Code"), sc_edit_edit_smart_indent_line_or_selection); + init (tr ("Indent Code"), sc_edit_edit_smart_indent_line_or_selection); - init (tr ("Convert Line Endings to Windows"), sc_edit_edit_conv_eol_winows); - init (tr ("Convert Line Endings to Unix"), sc_edit_edit_conv_eol_unix); - init (tr ("Convert Line Endings to Mac"), sc_edit_edit_conv_eol_mac); + init (tr ("Convert Line Endings to Windows"), sc_edit_edit_conv_eol_winows); + init (tr ("Convert Line Endings to Unix"), sc_edit_edit_conv_eol_unix); + init (tr ("Convert Line Endings to Mac"), sc_edit_edit_conv_eol_mac); - init (tr ("Goto Line"), sc_edit_edit_goto_line); - init (tr ("Move to Matching Brace"), sc_edit_edit_move_to_brace); - init (tr ("Select to Matching Brace"), sc_edit_edit_select_to_brace); - init (tr ("Toggle Bookmark"), sc_edit_edit_toggle_bookmark); - init (tr ("Next Bookmark"), sc_edit_edit_next_bookmark); - init (tr ("Previous Bookmark"), sc_edit_edit_previous_bookmark); - init (tr ("Remove All Bookmark"), sc_edit_edit_remove_bookmark); + init (tr ("Goto Line"), sc_edit_edit_goto_line); + init (tr ("Move to Matching Brace"), sc_edit_edit_move_to_brace); + init (tr ("Select to Matching Brace"), sc_edit_edit_select_to_brace); + init (tr ("Toggle Bookmark"), sc_edit_edit_toggle_bookmark); + init (tr ("Next Bookmark"), sc_edit_edit_next_bookmark); + init (tr ("Previous Bookmark"), sc_edit_edit_previous_bookmark); + init (tr ("Remove All Bookmark"), sc_edit_edit_remove_bookmark); - init (tr ("Preferences"), sc_edit_edit_preferences); - init (tr ("Styles Preferences"), sc_edit_edit_styles_preferences); + init (tr ("Preferences"), sc_edit_edit_preferences); + init (tr ("Styles Preferences"), sc_edit_edit_styles_preferences); - // view - init (tr ("Show Line Numbers"), sc_edit_view_show_line_numbers); - init (tr ("Show Whitespace Characters"), sc_edit_view_show_white_spaces); - init (tr ("Show Line Endings"), sc_edit_view_show_eol_chars); - init (tr ("Show Indentation Guides"), sc_edit_view_show_ind_guides); - init (tr ("Show Long Line Marker"), sc_edit_view_show_long_line); - init (tr ("Show Toolbar"), sc_edit_view_show_toolbar); - init (tr ("Show Statusbar"), sc_edit_view_show_statusbar); - init (tr ("Show Horizontal Scrollbar"), sc_edit_view_show_hscrollbar); - init (tr ("Sort Tabs Alphabetically"), sc_edit_view_sort_tabs); + // view + init (tr ("Show Line Numbers"), sc_edit_view_show_line_numbers); + init (tr ("Show Whitespace Characters"), sc_edit_view_show_white_spaces); + init (tr ("Show Line Endings"), sc_edit_view_show_eol_chars); + init (tr ("Show Indentation Guides"), sc_edit_view_show_ind_guides); + init (tr ("Show Long Line Marker"), sc_edit_view_show_long_line); + init (tr ("Show Toolbar"), sc_edit_view_show_toolbar); + init (tr ("Show Statusbar"), sc_edit_view_show_statusbar); + init (tr ("Show Horizontal Scrollbar"), sc_edit_view_show_hscrollbar); + init (tr ("Sort Tabs Alphabetically"), sc_edit_view_sort_tabs); - // debug - init (tr ("Toggle Breakpoint"), sc_edit_debug_toggle_breakpoint); - init (tr ("Next Breakpoint"), sc_edit_debug_next_breakpoint); - init (tr ("Previous Breakpoint"), sc_edit_debug_previous_breakpoint); - init (tr ("Remove All Breakpoints"), sc_edit_debug_remove_breakpoints); + // debug + init (tr ("Toggle Breakpoint"), sc_edit_debug_toggle_breakpoint); + init (tr ("Next Breakpoint"), sc_edit_debug_next_breakpoint); + init (tr ("Previous Breakpoint"), sc_edit_debug_previous_breakpoint); + init (tr ("Remove All Breakpoints"), sc_edit_debug_remove_breakpoints); - // run - init (tr ("Run File"), sc_edit_run_run_file); - init (tr ("Run Selection"), sc_edit_run_run_selection); + // run + init (tr ("Run File"), sc_edit_run_run_file); + init (tr ("Run Selection"), sc_edit_run_run_selection); - // help - init (tr ("Help on Keyword"), sc_edit_help_help_keyword); - init (tr ("Document on Keyword"), sc_edit_help_doc_keyword); + // help + init (tr ("Help on Keyword"), sc_edit_help_help_keyword); + init (tr ("Document on Keyword"), sc_edit_help_doc_keyword); - // Documentation browser - init (tr ("Go to Homepage"), sc_doc_go_home); - init (tr ("Go Back one Page"), sc_doc_go_back); - init (tr ("Go Forward one Page"), sc_doc_go_next); - init (tr ("Bookmark this Page"), sc_doc_bookmark); -} + // Documentation browser + init (tr ("Go to Homepage"), sc_doc_go_home); + init (tr ("Go Back one Page"), sc_doc_go_back); + init (tr ("Go Forward one Page"), sc_doc_go_next); + init (tr ("Bookmark this Page"), sc_doc_bookmark); + } -// write one or all actual shortcut set(s) into a settings file -void shortcut_manager::write_shortcuts (gui_settings *settings, - bool closing) -{ - bool sc_ctrld = false; + // write one or all actual shortcut set(s) into a settings file + void shortcut_manager::write_shortcuts (gui_settings& settings, + bool closing) + { + bool sc_ctrld = false; - QString sc_main = sc_main_file.mid (0, sc_main_file.indexOf ('_') + 1); + QString sc_main = sc_main_file.mid (0, sc_main_file.indexOf ('_') + 1); - for (int i = 0; i < m_sc.count (); i++) // loop over all shortcuts - { - settings->setValue (sc_group + "/" + m_sc.at (i).m_settings_key, - m_sc.at (i).m_actual_sc.toString ()); - // special: check main-window for Ctrl-D (Terminal) - if (m_sc.at (i).m_settings_key.startsWith (sc_main) - && m_sc.at (i).m_actual_sc == QKeySequence (Qt::ControlModifier+Qt::Key_D)) - sc_ctrld = true; - } + for (int i = 0; i < m_sc.count (); i++) // loop over all shortcuts + { + settings.setValue (sc_group + "/" + m_sc.at (i).m_settings_key, + m_sc.at (i).m_actual_sc.toString ()); + // special: check main-window for Ctrl-D (Terminal) + if (m_sc.at (i).m_settings_key.startsWith (sc_main) + && m_sc.at (i).m_actual_sc == QKeySequence (Qt::ControlModifier+Qt::Key_D)) + sc_ctrld = true; + } - settings->setValue (sc_main_ctrld.key, sc_ctrld); + settings.setValue (sc_main_ctrld.key, sc_ctrld); - if (closing) - { - delete m_dialog; // the dialog for key sequences can be removed now - m_dialog = nullptr; // make sure it is zero again - } + if (closing) + { + delete m_dialog; // the dialog for key sequences can be removed now + m_dialog = nullptr; // make sure it is zero again + } - settings->sync (); // sync the settings file -} + settings.sync (); // sync the settings file + } -void shortcut_manager::set_shortcut (QAction *action, const sc_pref& scpref, - bool enable) -{ - if (! enable) - { - // Disable => remove existing shortcut from the action - action->setShortcut (QKeySequence ()); - return; - } + void shortcut_manager::set_shortcut (QAction *action, const sc_pref& scpref, + bool enable) + { + if (! enable) + { + // Disable => remove existing shortcut from the action + action->setShortcut (QKeySequence ()); + return; + } - // Enable: Is the given key known? If yes, get the value from the - // settings file and set it to the action - int index; + // Enable: Is the given key known? If yes, get the value from the + // settings file and set it to the action + int index; - index = m_action_hash[scpref.key] - 1; + index = m_action_hash[scpref.key] - 1; + + if (index > -1 && index < m_sc.count ()) + { + gui_settings settings; - if (index > -1 && index < m_sc.count ()) - { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - action->setShortcut (QKeySequence (settings->sc_value (scpref))); - } - else - qDebug () << "Key: " << scpref.key << " not found in m_action_hash"; -} + action->setShortcut (QKeySequence (settings.sc_value (scpref))); + } + else + qDebug () << "Key: " << scpref.key << " not found in m_action_hash"; + } -void shortcut_manager::shortcut (QShortcut *sc, const sc_pref& scpref) -{ - int index; + void shortcut_manager::shortcut (QShortcut *sc, const sc_pref& scpref) + { + int index; - index = m_action_hash[scpref.key] - 1; + index = m_action_hash[scpref.key] - 1; + + if (index > -1 && index < m_sc.count ()) + { + gui_settings settings; - if (index > -1 && index < m_sc.count ()) - { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - sc->setKey (QKeySequence (settings->sc_value (scpref))); - } - else - qDebug () << "Key: " << scpref.key << " not found in m_action_hash"; -} + sc->setKey (QKeySequence (settings.sc_value (scpref))); + } + else + qDebug () << "Key: " << scpref.key << " not found in m_action_hash"; + } -void shortcut_manager::fill_treewidget (QTreeWidget *tree_view) -{ - m_dialog = nullptr; - m_level_hash.clear (); + void shortcut_manager::fill_treewidget (QTreeWidget *tree_view) + { + m_dialog = nullptr; + m_level_hash.clear (); - tree_view->header ()->setSectionResizeMode (QHeaderView::ResizeToContents); + tree_view->header ()->setSectionResizeMode (QHeaderView::ResizeToContents); - QTreeWidgetItem *main = new QTreeWidgetItem (tree_view); - main->setText (0, tr ("Global")); - main->setExpanded (true); - QTreeWidgetItem *main_file = new QTreeWidgetItem (main); - main_file->setText (0, tr ("File Menu")); - QTreeWidgetItem *main_edit = new QTreeWidgetItem (main); - main_edit->setText (0, tr ("Edit Menu")); - QTreeWidgetItem *main_debug = new QTreeWidgetItem (main); - main_debug->setText (0, tr ("Debug Menu")); - QTreeWidgetItem *main_tools = new QTreeWidgetItem (main); - main_tools->setText (0, tr ("Tools Menu")); - QTreeWidgetItem *main_window = new QTreeWidgetItem (main); - main_window->setText (0, tr ("Window Menu")); - QTreeWidgetItem *main_help = new QTreeWidgetItem (main); - main_help->setText (0, tr ("Help Menu")); - QTreeWidgetItem *main_news = new QTreeWidgetItem (main); - main_news->setText (0, tr ("News Menu")); - QTreeWidgetItem *main_dock_widgets = new QTreeWidgetItem (main); - main_dock_widgets->setText (0, tr ("Handling of Dock Widgets")); - QTreeWidgetItem *main_tabs = new QTreeWidgetItem (main); - main_tabs->setText (0, tr ("Tab Handling in Dock Widgets")); - QTreeWidgetItem *main_find = new QTreeWidgetItem (main); - main_find->setText (0, tr ("Find & Replace in Dock Widgets")); - QTreeWidgetItem *main_zoom = new QTreeWidgetItem (main); - main_zoom->setText (0, tr ("Zooming in Editor and Documentation")); + QTreeWidgetItem *main = new QTreeWidgetItem (tree_view); + main->setText (0, tr ("Global")); + main->setExpanded (true); + QTreeWidgetItem *main_file = new QTreeWidgetItem (main); + main_file->setText (0, tr ("File Menu")); + QTreeWidgetItem *main_edit = new QTreeWidgetItem (main); + main_edit->setText (0, tr ("Edit Menu")); + QTreeWidgetItem *main_debug = new QTreeWidgetItem (main); + main_debug->setText (0, tr ("Debug Menu")); + QTreeWidgetItem *main_tools = new QTreeWidgetItem (main); + main_tools->setText (0, tr ("Tools Menu")); + QTreeWidgetItem *main_window = new QTreeWidgetItem (main); + main_window->setText (0, tr ("Window Menu")); + QTreeWidgetItem *main_help = new QTreeWidgetItem (main); + main_help->setText (0, tr ("Help Menu")); + QTreeWidgetItem *main_news = new QTreeWidgetItem (main); + main_news->setText (0, tr ("News Menu")); + QTreeWidgetItem *main_dock_widgets = new QTreeWidgetItem (main); + main_dock_widgets->setText (0, tr ("Handling of Dock Widgets")); + QTreeWidgetItem *main_tabs = new QTreeWidgetItem (main); + main_tabs->setText (0, tr ("Tab Handling in Dock Widgets")); + QTreeWidgetItem *main_find = new QTreeWidgetItem (main); + main_find->setText (0, tr ("Find & Replace in Dock Widgets")); + QTreeWidgetItem *main_zoom = new QTreeWidgetItem (main); + main_zoom->setText (0, tr ("Zooming in Editor and Documentation")); - m_level_hash[sc_main_file] = main_file; - m_level_hash[sc_main_edit] = main_edit; - m_level_hash[sc_main_debug] = main_debug; - m_level_hash[sc_main_tools] = main_tools; - m_level_hash[sc_main_window] = main_window; - m_level_hash[sc_main_help] = main_help; - m_level_hash[sc_main_news] = main_news; - m_level_hash[sc_dock_widget] = main_dock_widgets; - m_level_hash[sc_edit_tabs] = main_tabs; - m_level_hash[sc_edit_find] = main_find; - m_level_hash[sc_edit_zoom] = main_zoom; + m_level_hash[sc_main_file] = main_file; + m_level_hash[sc_main_edit] = main_edit; + m_level_hash[sc_main_debug] = main_debug; + m_level_hash[sc_main_tools] = main_tools; + m_level_hash[sc_main_window] = main_window; + m_level_hash[sc_main_help] = main_help; + m_level_hash[sc_main_news] = main_news; + m_level_hash[sc_dock_widget] = main_dock_widgets; + m_level_hash[sc_edit_tabs] = main_tabs; + m_level_hash[sc_edit_find] = main_find; + m_level_hash[sc_edit_zoom] = main_zoom; - QTreeWidgetItem *editor = new QTreeWidgetItem (tree_view); - editor->setText (0, tr ("Editor")); - editor->setExpanded (true); - QTreeWidgetItem *editor_file = new QTreeWidgetItem (editor); - editor_file->setText (0, tr ("File Menu")); - QTreeWidgetItem *editor_edit = new QTreeWidgetItem (editor); - editor_edit->setText (0, tr ("Edit Menu")); - QTreeWidgetItem *editor_view = new QTreeWidgetItem (editor); - editor_view->setText (0, tr ("View Menu")); - QTreeWidgetItem *editor_debug = new QTreeWidgetItem (editor); - editor_debug->setText (0, tr ("Debug Menu")); - QTreeWidgetItem *editor_run = new QTreeWidgetItem (editor); - editor_run->setText (0, tr ("Run Menu")); - QTreeWidgetItem *editor_help = new QTreeWidgetItem (editor); - editor_help->setText (0, tr ("Help Menu")); + QTreeWidgetItem *editor = new QTreeWidgetItem (tree_view); + editor->setText (0, tr ("Editor")); + editor->setExpanded (true); + QTreeWidgetItem *editor_file = new QTreeWidgetItem (editor); + editor_file->setText (0, tr ("File Menu")); + QTreeWidgetItem *editor_edit = new QTreeWidgetItem (editor); + editor_edit->setText (0, tr ("Edit Menu")); + QTreeWidgetItem *editor_view = new QTreeWidgetItem (editor); + editor_view->setText (0, tr ("View Menu")); + QTreeWidgetItem *editor_debug = new QTreeWidgetItem (editor); + editor_debug->setText (0, tr ("Debug Menu")); + QTreeWidgetItem *editor_run = new QTreeWidgetItem (editor); + editor_run->setText (0, tr ("Run Menu")); + QTreeWidgetItem *editor_help = new QTreeWidgetItem (editor); + editor_help->setText (0, tr ("Help Menu")); - m_level_hash[sc_edit_file] = editor_file; - m_level_hash[sc_edit_edit] = editor_edit; - m_level_hash[sc_edit_view] = editor_view; - m_level_hash[sc_edit_debug] = editor_debug; - m_level_hash[sc_edit_run] = editor_run; - m_level_hash[sc_edit_help] = editor_help; + m_level_hash[sc_edit_file] = editor_file; + m_level_hash[sc_edit_edit] = editor_edit; + m_level_hash[sc_edit_view] = editor_view; + m_level_hash[sc_edit_debug] = editor_debug; + m_level_hash[sc_edit_run] = editor_run; + m_level_hash[sc_edit_help] = editor_help; - QTreeWidgetItem *doc = new QTreeWidgetItem (tree_view); - doc->setText (0, tr ("Documentation Viewer")); - doc->setExpanded (true); + QTreeWidgetItem *doc = new QTreeWidgetItem (tree_view); + doc->setText (0, tr ("Documentation Viewer")); + doc->setExpanded (true); - QTreeWidgetItem *doc_browser = new QTreeWidgetItem (doc); - doc_browser->setText (0, tr ("Browser")); + QTreeWidgetItem *doc_browser = new QTreeWidgetItem (doc); + doc_browser->setText (0, tr ("Browser")); + + m_level_hash[sc_doc] = doc_browser; - m_level_hash[sc_doc] = doc_browser; - - connect (tree_view, &QTreeWidget::itemDoubleClicked, - this, &shortcut_manager::handle_double_clicked); + connect (tree_view, &QTreeWidget::itemDoubleClicked, + this, &shortcut_manager::handle_double_clicked); - for (int i = 0; i < m_sc.count (); i++) - { - shortcut_t sc = m_sc.at (i); + for (int i = 0; i < m_sc.count (); i++) + { + shortcut_t sc = m_sc.at (i); - QTreeWidgetItem *section = m_level_hash[sc.m_settings_key.section (':', 0, 0)]; + QTreeWidgetItem *section = m_level_hash[sc.m_settings_key.section (':', 0, 0)]; - // handle sections which have changed and do not correspond to the - // previously defined keyname - if (section == editor_file) - { - // Closing tabs now in global tab handling section - if (sc.m_settings_key.contains (sc_edit_file_cl)) - section = main_tabs; - } - if (section == editor_edit) - { - // Find & replace now in global file & replace handling section - if (sc.m_settings_key.contains (sc_edit_edit_find)) - section = main_find; - } - if (section == editor_view) - { - // Zooming now in global zoom handling section - if (sc.m_settings_key.contains (sc_edit_view_zoom)) - section = main_zoom; - } + // handle sections which have changed and do not correspond to the + // previously defined keyname + if (section == editor_file) + { + // Closing tabs now in global tab handling section + if (sc.m_settings_key.contains (sc_edit_file_cl)) + section = main_tabs; + } + if (section == editor_edit) + { + // Find & replace now in global file & replace handling section + if (sc.m_settings_key.contains (sc_edit_edit_find)) + section = main_find; + } + if (section == editor_view) + { + // Zooming now in global zoom handling section + if (sc.m_settings_key.contains (sc_edit_view_zoom)) + section = main_zoom; + } - QTreeWidgetItem *tree_item = new QTreeWidgetItem (section); + QTreeWidgetItem *tree_item = new QTreeWidgetItem (section); + + // set a slightly transparent foreground for default columns + QColor fg = QColor (tree_item->foreground (1).color ()); + fg.setAlpha (128); + tree_item->setForeground (1, QBrush (fg)); - // set a slightly transparent foreground for default columns - QColor fg = QColor (tree_item->foreground (1).color ()); - fg.setAlpha (128); - tree_item->setForeground (1, QBrush (fg)); + // write the shortcuts + tree_item->setText (0, sc.m_description); + tree_item->setText (1, sc.m_default_sc.toString ()); + tree_item->setText (2, sc.m_actual_sc.toString ()); - // write the shortcuts - tree_item->setText (0, sc.m_description); - tree_item->setText (1, sc.m_default_sc.toString ()); - tree_item->setText (2, sc.m_actual_sc.toString ()); - - m_item_index_hash[tree_item] = i + 1; // index+1 to avoid 0 - m_index_item_hash[i] = tree_item; - } -} + m_item_index_hash[tree_item] = i + 1; // index+1 to avoid 0 + m_index_item_hash[i] = tree_item; + } + } -// import or export of shortcut sets, -// called from settings dialog when related buttons are clicked; -// returns true on success, false otherwise -bool -shortcut_manager::import_export (int action) -{ - // ask to save the current shortcuts, maybe abort import - if (action == OSC_DEFAULT || action == OSC_IMPORT) - { - if (! overwrite_all_shortcuts ()) - return false; - } + // import or export of shortcut sets, + // called from settings dialog when related buttons are clicked; + // returns true on success, false otherwise + bool + shortcut_manager::import_export (int action) + { + // ask to save the current shortcuts, maybe abort import + if (action == OSC_DEFAULT || action == OSC_IMPORT) + { + if (! overwrite_all_shortcuts ()) + return false; + } - // get the filename to read or write the shortcuts, - // the default extension is .osc (octave shortcuts) - if (action != OSC_DEFAULT) - { - QString file; + // get the filename to read or write the shortcuts, + // the default extension is .osc (octave shortcuts) + if (action != OSC_DEFAULT) + { + QString file; + + // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. + int opts = 0; // No options by default. + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) + opts = QFileDialog::DontUseNativeDialog; - // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - int opts = 0; // No options by default. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) - opts = QFileDialog::DontUseNativeDialog; + if (action == OSC_IMPORT) + file = QFileDialog::getOpenFileName (this, + tr ("Import shortcuts from file..."), QString (), + tr ("Octave Shortcut Files (*.osc);;All Files (*)"), + nullptr, QFileDialog::Option (opts)); + else if (action == OSC_EXPORT) + file = QFileDialog::getSaveFileName (this, + tr ("Export shortcuts to file..."), QString (), + tr ("Octave Shortcut Files (*.osc);;All Files (*)"), + nullptr, QFileDialog::Option (opts)); - if (action == OSC_IMPORT) - file = QFileDialog::getOpenFileName (this, - tr ("Import shortcuts from file..."), QString (), - tr ("Octave Shortcut Files (*.osc);;All Files (*)"), - nullptr, QFileDialog::Option (opts)); - else if (action == OSC_EXPORT) - file = QFileDialog::getSaveFileName (this, - tr ("Export shortcuts to file..."), QString (), - tr ("Octave Shortcut Files (*.osc);;All Files (*)"), - nullptr, QFileDialog::Option (opts)); - - if (file.isEmpty ()) - return false; - - gui_settings osc_settings (file, QSettings::IniFormat); - - if (osc_settings.status () != QSettings::NoError) - { - qWarning () << tr ("Failed to open %1 as Octave shortcut file") - .arg (file); + if (file.isEmpty ()) return false; - } - else - { - if (action == OSC_IMPORT) - import_shortcuts (&osc_settings); // import (special action) - else if (action == OSC_EXPORT) - write_shortcuts (&osc_settings, false); // export, (save settings) - } - } - else - { - import_shortcuts (nullptr); - } + + gui_settings osc_settings (file, QSettings::IniFormat); - return true; -} + if (osc_settings.status () != QSettings::NoError) + { + qWarning () << tr ("Failed to open %1 as Octave shortcut file") + .arg (file); + return false; + } + else + { + if (action == OSC_IMPORT) + import_shortcuts (osc_settings); // import (special action) + else if (action == OSC_EXPORT) + write_shortcuts (osc_settings, false); // export, (save settings) + } + } + else + reset_default_shortcuts (); + + return true; + } -void shortcut_manager::handle_double_clicked (QTreeWidgetItem *item, int col) -{ - if (col != 2) - return; + void shortcut_manager::handle_double_clicked (QTreeWidgetItem *item, int col) + { + if (col != 2) + return; - int i = m_item_index_hash[item]; - if (i == 0) - return; // top-level-item clicked + int i = m_item_index_hash[item]; + if (i == 0) + return; // top-level-item clicked + + shortcut_dialog (i-1); // correct to index starting at 0 + } - shortcut_dialog (i-1); // correct to index starting at 0 -} + void shortcut_manager::shortcut_dialog_finished (int result) + { + if (result == QDialog::Rejected) + return; + + // check for duplicate + int double_index = m_shortcut_hash[m_edit_actual->text ()] - 1; -void shortcut_manager::shortcut_dialog_finished (int result) -{ - if (result == QDialog::Rejected) - return; - - // check for duplicate - int double_index = m_shortcut_hash[m_edit_actual->text ()] - 1; + if (double_index >= 0 && double_index != m_handled_index) + { + int ret = QMessageBox::warning (this, tr ("Double Shortcut"), + tr ("The chosen shortcut\n \"%1\"\n" + "is already used for the action\n \"%2\".\n" + "Do you want to use the shortcut anyhow removing it " + "from the previous action?") + .arg (m_edit_actual->text ()) + .arg (m_sc.at (double_index).m_description), + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - if (double_index >= 0 && double_index != m_handled_index) - { - int ret = QMessageBox::warning (this, tr ("Double Shortcut"), - tr ("The chosen shortcut\n \"%1\"\n" - "is already used for the action\n \"%2\".\n" - "Do you want to use the shortcut anyhow removing it " - "from the previous action?") - .arg (m_edit_actual->text ()) - .arg (m_sc.at (double_index).m_description), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + if (ret == QMessageBox::Yes) + { + shortcut_t double_shortcut = m_sc.at (double_index); + double_shortcut.m_actual_sc = QKeySequence (); + m_sc.replace (double_index, double_shortcut); + m_index_item_hash[double_index]->setText (2, QString ()); + } + else + return; + } + + shortcut_t shortcut = m_sc.at (m_handled_index); + if (! shortcut.m_actual_sc.isEmpty ()) + m_shortcut_hash.remove (shortcut.m_actual_sc.toString ()); + shortcut.m_actual_sc = m_edit_actual->text (); + m_sc.replace (m_handled_index, shortcut); - if (ret == QMessageBox::Yes) - { - shortcut_t double_shortcut = m_sc.at (double_index); - double_shortcut.m_actual_sc = QKeySequence (); - m_sc.replace (double_index, double_shortcut); - m_index_item_hash[double_index]->setText (2, QString ()); - } - else - return; - } + m_index_item_hash[m_handled_index]->setText (2, shortcut.m_actual_sc.toString ()); + + if (! shortcut.m_actual_sc.isEmpty ()) + m_shortcut_hash[shortcut.m_actual_sc.toString ()] = m_handled_index + 1; + } - shortcut_t shortcut = m_sc.at (m_handled_index); - if (! shortcut.m_actual_sc.isEmpty ()) - m_shortcut_hash.remove (shortcut.m_actual_sc.toString ()); - shortcut.m_actual_sc = m_edit_actual->text (); - m_sc.replace (m_handled_index, shortcut); + void shortcut_manager::shortcut_dialog_set_default (void) + { + m_edit_actual->setText (m_label_default->text ()); + } - m_index_item_hash[m_handled_index]->setText (2, shortcut.m_actual_sc.toString ()); + void shortcut_manager::init (const QString& description, const sc_pref& sc) + { + gui_settings settings; + + QKeySequence actual = QKeySequence (settings.sc_value (sc)); - if (! shortcut.m_actual_sc.isEmpty ()) - m_shortcut_hash[shortcut.m_actual_sc.toString ()] = m_handled_index + 1; -} + // append the new shortcut to the list + shortcut_t shortcut_info; + shortcut_info.m_description = description; + shortcut_info.m_settings_key = sc.key; + shortcut_info.m_actual_sc = actual; + shortcut_info.m_default_sc = settings.sc_def_value (sc); + m_sc << shortcut_info; -void shortcut_manager::shortcut_dialog_set_default (void) -{ - m_edit_actual->setText (m_label_default->text ()); -} + // insert shortcut in order to check for duplicates later + if (! actual.isEmpty ()) + m_shortcut_hash[actual.toString ()] = m_sc.count (); + m_action_hash[sc.key] = m_sc.count (); -void shortcut_manager::init (const QString& description, const sc_pref& sc) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - QKeySequence actual = QKeySequence (settings->sc_value (sc)); + // check whether ctrl+d is used from main window, i.e. is a global shortcut + QString main_group_prefix + = sc_main_file.mid (0, sc_main_file.indexOf ('_') + 1); + if (sc.key.startsWith (main_group_prefix) + && actual == QKeySequence (Qt::ControlModifier+Qt::Key_D)) + settings.setValue (sc_main_ctrld.key, true); + } - // append the new shortcut to the list - shortcut_t shortcut_info; - shortcut_info.m_description = description; - shortcut_info.m_settings_key = sc.key; - shortcut_info.m_actual_sc = actual; - shortcut_info.m_default_sc = settings->sc_def_value (sc); - m_sc << shortcut_info; + void shortcut_manager::shortcut_dialog (int index) + { + if (! m_dialog) + { + m_dialog = new QDialog (this); + + m_dialog->setWindowTitle (tr ("Enter new Shortcut")); - // insert shortcut in order to check for duplicates later - if (! actual.isEmpty ()) - m_shortcut_hash[actual.toString ()] = m_sc.count (); - m_action_hash[sc.key] = m_sc.count (); + QVBoxLayout *box = new QVBoxLayout (m_dialog); + box->setSpacing (2); + box->setContentsMargins (12, 12, 12, 12); - // check whether ctrl+d is used from main window, i.e. is a global shortcut - QString main_group_prefix - = sc_main_file.mid (0, sc_main_file.indexOf ('_') + 1); - if (sc.key.startsWith (main_group_prefix) - && actual == QKeySequence (Qt::ControlModifier+Qt::Key_D)) - settings->setValue (sc_main_ctrld.key, true); -} + QLabel *help = new QLabel (tr ("Apply the desired shortcut or click " + "on the right button to reset the " + "shortcut to its default.")); + help->setWordWrap (true); + box->addWidget (help); + + QCheckBox *direct + = new QCheckBox (tr ("Enter shortcut directly by performing it")); -void shortcut_manager::shortcut_dialog (int index) -{ - if (! m_dialog) - { - m_dialog = new QDialog (this); + QCheckBox *shift + = new QCheckBox (tr ("Add Shift modifier\n" + "(allows one to enter number keys)")); + + shift->setStyleSheet + ("QCheckBox::indicator { subcontrol-position: left top; }"); - m_dialog->setWindowTitle (tr ("Enter new Shortcut")); + connect (direct, &QCheckBox::clicked, shift, &QCheckBox::setEnabled); + + direct->setCheckState (Qt::Checked); - QVBoxLayout *box = new QVBoxLayout (m_dialog); - box->setSpacing (2); - box->setContentsMargins (12, 12, 12, 12); + box->addWidget (direct); + box->addWidget (shift); + + box->addSpacing (15); - QLabel *help = new QLabel (tr ("Apply the desired shortcut or click " - "on the right button to reset the " - "shortcut to its default.")); - help->setWordWrap (true); - box->addWidget (help); + QGridLayout *grid = new QGridLayout (); - QCheckBox *direct - = new QCheckBox (tr ("Enter shortcut directly by performing it")); + QLabel *actual = new QLabel (tr ("Actual shortcut")); + m_edit_actual = new enter_shortcut (m_dialog); + m_edit_actual->setAlignment (Qt::AlignHCenter); + grid->addWidget (actual, 0, 0); + grid->addWidget (m_edit_actual, 0, 1); - QCheckBox *shift - = new QCheckBox (tr ("Add Shift modifier\n" - "(allows one to enter number keys)")); - - shift->setStyleSheet - ("QCheckBox::indicator { subcontrol-position: left top; }"); + QLabel *def = new QLabel (tr ("Default shortcut")); + m_label_default = new QLabel (m_dialog); + m_label_default->setAlignment (Qt::AlignHCenter); + grid->addWidget (def, 1, 0); + grid->addWidget (m_label_default, 1, 1); - connect (direct, &QCheckBox::clicked, shift, &QCheckBox::setEnabled); - - direct->setCheckState (Qt::Checked); - - box->addWidget (direct); - box->addWidget (shift); + QPushButton *set_default = new QPushButton (tr ("Set to default")); + grid->addWidget (set_default, 0, 2); + connect (set_default, &QPushButton::clicked, + this, &shortcut_manager::shortcut_dialog_set_default); - box->addSpacing (15); + box->addLayout (grid); - QGridLayout *grid = new QGridLayout (); + box->addSpacing (18); - QLabel *actual = new QLabel (tr ("Actual shortcut")); - m_edit_actual = new enter_shortcut (m_dialog); - m_edit_actual->setAlignment (Qt::AlignHCenter); - grid->addWidget (actual, 0, 0); - grid->addWidget (m_edit_actual, 0, 1); + QDialogButtonBox *button_box = new QDialogButtonBox (QDialogButtonBox::Ok + | QDialogButtonBox::Cancel); + QList buttons = button_box->buttons (); + for (int i = 0; i < buttons.count (); i++) + buttons.at (i)->setShortcut (QKeySequence ()); + connect (button_box, &QDialogButtonBox::accepted, + m_dialog, &QDialog::accept); + connect (button_box, &QDialogButtonBox::rejected, + m_dialog, &QDialog::reject); + box->addWidget (button_box); - QLabel *def = new QLabel (tr ("Default shortcut")); - m_label_default = new QLabel (m_dialog); - m_label_default->setAlignment (Qt::AlignHCenter); - grid->addWidget (def, 1, 0); - grid->addWidget (m_label_default, 1, 1); + m_dialog->setLayout (box); - QPushButton *set_default = new QPushButton (tr ("Set to default")); - grid->addWidget (set_default, 0, 2); - connect (set_default, &QPushButton::clicked, - this, &shortcut_manager::shortcut_dialog_set_default); + connect (direct, &QCheckBox::stateChanged, + m_edit_actual, &enter_shortcut::handle_direct_shortcut); + connect (shift, &QCheckBox::stateChanged, + m_edit_actual, &enter_shortcut::handle_shift_modifier); + connect (m_dialog, &QDialog::finished, + this, &shortcut_manager::shortcut_dialog_finished); - box->addLayout (grid); - - box->addSpacing (18); + } - QDialogButtonBox *button_box = new QDialogButtonBox (QDialogButtonBox::Ok - | QDialogButtonBox::Cancel); - QList buttons = button_box->buttons (); - for (int i = 0; i < buttons.count (); i++) - buttons.at (i)->setShortcut (QKeySequence ()); - connect (button_box, &QDialogButtonBox::accepted, - m_dialog, &QDialog::accept); - connect (button_box, &QDialogButtonBox::rejected, - m_dialog, &QDialog::reject); - box->addWidget (button_box); + m_edit_actual->setText (m_sc.at (index).m_actual_sc.toString ()); + m_label_default->setText (m_sc.at (index).m_default_sc.toString ()); + m_handled_index = index; + + m_edit_actual->setFocus (); + m_dialog->setFocusProxy (m_edit_actual); + m_dialog->exec (); + } - m_dialog->setLayout (box); + // import a shortcut set from a given settings file and refresh the + // tree view + void shortcut_manager::import_shortcuts (gui_settings& settings) + { + for (int i = 0; i < m_sc.count (); i++) + { + // update the list of all shortcuts - connect (direct, &QCheckBox::stateChanged, - m_edit_actual, &enter_shortcut::handle_direct_shortcut); - connect (shift, &QCheckBox::stateChanged, - m_edit_actual, &enter_shortcut::handle_shift_modifier); - connect (m_dialog, &QDialog::finished, - this, &shortcut_manager::shortcut_dialog_finished); + // make a copy + shortcut_t sc = m_sc.at (i); - } + // get new shortcut from settings and use the old one as default + sc.m_actual_sc = QKeySequence (settings.value (sc_group + sc.m_settings_key, sc.m_actual_sc).toString ()); - m_edit_actual->setText (m_sc.at (index).m_actual_sc.toString ()); - m_label_default->setText (m_sc.at (index).m_default_sc.toString ()); - m_handled_index = index; + // replace the old with the new one + m_sc.replace (i, sc); - m_edit_actual->setFocus (); - m_dialog->setFocusProxy (m_edit_actual); - m_dialog->exec (); -} + // update the tree view + // get related tree item + QTreeWidgetItem *tree_item = m_index_item_hash[i]; + + // display new shortcut + tree_item->setText (2, sc.m_actual_sc.toString ()); + } + } -// import a shortcut set from a given settings file or reset to -// the defaults (settings = 0) and refresh the tree view -void shortcut_manager::import_shortcuts (gui_settings *settings) -{ - for (int i = 0; i < m_sc.count (); i++) - { - // update the list of all shortcuts - shortcut_t sc = m_sc.at (i); // make a copy + // reset to the defaults and refresh the tree view + void shortcut_manager::reset_default_shortcuts (void) + { + for (int i = 0; i < m_sc.count (); i++) + { + // update the list of all shortcuts - if (settings) - sc.m_actual_sc = QKeySequence ( // get new shortcut from settings - settings->value (sc_group + sc.m_settings_key,sc.m_actual_sc). - toString ()); // and use the old one as default - else - sc.m_actual_sc = QKeySequence (sc.m_default_sc); // get default shortcut + // make a copy + shortcut_t sc = m_sc.at (i); + + // get default shortcut + sc.m_actual_sc = QKeySequence (sc.m_default_sc); - m_sc.replace (i, sc); // replace the old with the new one + // replace the old with the new one + m_sc.replace (i, sc); - // update the tree view - QTreeWidgetItem *tree_item = m_index_item_hash[i]; // get related tree item - tree_item->setText (2, sc.m_actual_sc.toString ()); // display new shortcut - } -} + // update the tree view + // get related tree item + QTreeWidgetItem *tree_item = m_index_item_hash[i]; + + // display new shortcut + tree_item->setText (2, sc.m_actual_sc.toString ()); + } + } -// ask the user whether to save the current shortcut set; -// returns true to proceed with import action, false to abort it -bool shortcut_manager::overwrite_all_shortcuts (void) -{ - QMessageBox msg_box; - msg_box.setWindowTitle (tr ("Overwriting Shortcuts")); - msg_box.setIcon (QMessageBox::Warning); - msg_box.setText (tr ("You are about to overwrite all shortcuts.\n" - "Would you like to save the current shortcut set or cancel the action?")); - msg_box.setStandardButtons (QMessageBox::Save | QMessageBox::Cancel); - QPushButton *discard = msg_box.addButton (tr ("Don't save"), - QMessageBox::DestructiveRole); - msg_box.setDefaultButton (QMessageBox::Save); + // ask the user whether to save the current shortcut set; + // returns true to proceed with import action, false to abort it + bool shortcut_manager::overwrite_all_shortcuts (void) + { + QMessageBox msg_box; + msg_box.setWindowTitle (tr ("Overwriting Shortcuts")); + msg_box.setIcon (QMessageBox::Warning); + msg_box.setText (tr ("You are about to overwrite all shortcuts.\n" + "Would you like to save the current shortcut set or cancel the action?")); + msg_box.setStandardButtons (QMessageBox::Save | QMessageBox::Cancel); + QPushButton *discard = msg_box.addButton (tr ("Don't save"), + QMessageBox::DestructiveRole); + msg_box.setDefaultButton (QMessageBox::Save); - int ret = msg_box.exec (); + int ret = msg_box.exec (); - if (msg_box.clickedButton () == discard) - return true; // do not save and go ahead + if (msg_box.clickedButton () == discard) + return true; // do not save and go ahead - if (ret == QMessageBox::Save) - { - if (import_export (OSC_EXPORT)) - return true; // go ahead - } + if (ret == QMessageBox::Save) + { + if (import_export (OSC_EXPORT)) + return true; // go ahead + } - return false; // abort the import -} + return false; // abort the import + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/shortcut-manager.h --- a/libgui/src/shortcut-manager.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/shortcut-manager.h Tue Dec 06 15:45:27 2022 -0500 @@ -33,142 +33,141 @@ #include #include -#include "gui-settings.h" +#include "gui-preferences.h" OCTAVE_BEGIN_NAMESPACE(octave) -class enter_shortcut : public QLineEdit -{ - Q_OBJECT + class enter_shortcut : public QLineEdit + { + Q_OBJECT -public: + public: - enter_shortcut (QWidget *p = nullptr); + enter_shortcut (QWidget *p = nullptr); - ~enter_shortcut (void) = default; + ~enter_shortcut (void) = default; - virtual void keyPressEvent (QKeyEvent *e); + virtual void keyPressEvent (QKeyEvent *e); -public slots: + public slots: - void handle_direct_shortcut (int); - void handle_shift_modifier (int); + void handle_direct_shortcut (int); + void handle_shift_modifier (int); -private: + private: - bool m_direct_shortcut; - bool m_shift_modifier; + bool m_direct_shortcut; + bool m_shift_modifier; -}; + }; -class base_qobject; + class gui_settings; -class shortcut_manager : public QWidget -{ - Q_OBJECT + class shortcut_manager : public QWidget + { + Q_OBJECT -public: + public: - enum + enum { OSC_IMPORT = 0, OSC_EXPORT = 1, OSC_DEFAULT = 2 }; - shortcut_manager (base_qobject& oct_qobj); + shortcut_manager (void); - // No copying! + // No copying! - shortcut_manager (const shortcut_manager&) = delete; + shortcut_manager (const shortcut_manager&) = delete; - shortcut_manager& operator = (const shortcut_manager&) = delete; + shortcut_manager& operator = (const shortcut_manager&) = delete; - ~shortcut_manager (void) = default; + ~shortcut_manager (void) = default; - void init_data (void); + void init_data (void); - void write_shortcuts (gui_settings *settings, bool closing); + void write_shortcuts (gui_settings& settings, bool closing); - void set_shortcut (QAction *action, const sc_pref& scpref, bool enable = true); + void set_shortcut (QAction *action, const sc_pref& scpref, bool enable = true); - void shortcut (QShortcut *sc, const sc_pref& scpref); + void shortcut (QShortcut *sc, const sc_pref& scpref); - void fill_treewidget (QTreeWidget *tree_view); + void fill_treewidget (QTreeWidget *tree_view); - bool import_export (int action); + bool import_export (int action); -protected slots: + protected slots: - void handle_double_clicked (QTreeWidgetItem *, int); - void shortcut_dialog_finished (int); - void shortcut_dialog_set_default (); + void handle_double_clicked (QTreeWidgetItem *, int); + void shortcut_dialog_finished (int); + void shortcut_dialog_set_default (); -private: + private: - void init (const QString&, const sc_pref& scpref); - void shortcut_dialog (int); - void import_shortcuts (gui_settings *settings); - bool overwrite_all_shortcuts (void); + void init (const QString&, const sc_pref& scpref); + void shortcut_dialog (int); + void import_shortcuts (gui_settings& settings); + void reset_default_shortcuts (void); + bool overwrite_all_shortcuts (void); - class shortcut_t - { - public: + class shortcut_t + { + public: - shortcut_t (void) - : m_tree_item (nullptr), m_description (), m_settings_key (), - m_actual_sc (QKeySequence ()), m_default_sc (QKeySequence ()) - { } + shortcut_t (void) + : m_tree_item (nullptr), m_description (), m_settings_key (), + m_actual_sc (QKeySequence ()), m_default_sc (QKeySequence ()) + { } - shortcut_t (const shortcut_t& x) - : m_tree_item (x.m_tree_item), m_description (x.m_description), - m_settings_key (x.m_settings_key) - { - m_actual_sc = x.m_actual_sc; - m_default_sc = x.m_default_sc; - } + shortcut_t (const shortcut_t& x) + : m_tree_item (x.m_tree_item), m_description (x.m_description), + m_settings_key (x.m_settings_key) + { + m_actual_sc = x.m_actual_sc; + m_default_sc = x.m_default_sc; + } - shortcut_t& operator = (const shortcut_t& x) - { - if (&x != this) - { - m_tree_item = x.m_tree_item; - m_description = x.m_description; - m_settings_key = x.m_settings_key; + shortcut_t& operator = (const shortcut_t& x) + { + if (&x != this) + { + m_tree_item = x.m_tree_item; + m_description = x.m_description; + m_settings_key = x.m_settings_key; - m_actual_sc = QKeySequence (); - m_default_sc = QKeySequence (); + m_actual_sc = QKeySequence (); + m_default_sc = QKeySequence (); - m_actual_sc = x.m_actual_sc; - m_default_sc = x.m_default_sc; - } + m_actual_sc = x.m_actual_sc; + m_default_sc = x.m_default_sc; + } - return *this; - } + return *this; + } - ~shortcut_t (void) = default; + ~shortcut_t (void) = default; - QTreeWidgetItem *m_tree_item; - QString m_description; - QString m_settings_key; - QKeySequence m_actual_sc; - QKeySequence m_default_sc; - }; + QTreeWidgetItem *m_tree_item; + QString m_description; + QString m_settings_key; + QKeySequence m_actual_sc; + QKeySequence m_default_sc; + }; - base_qobject& m_octave_qobj; + QList m_sc; + QHash m_shortcut_hash; + QHash m_action_hash; + QHash m_level_hash; + QHash m_index_item_hash; + QHash m_item_index_hash; - QList m_sc; - QHash m_shortcut_hash; - QHash m_action_hash; - QHash m_level_hash; - QHash m_index_item_hash; - QHash m_item_index_hash; - - QDialog *m_dialog; - enter_shortcut *m_edit_actual; - QLabel *m_label_default; - int m_handled_index; -}; + QDialog *m_dialog; + enter_shortcut *m_edit_actual; + QLabel *m_label_default; + int m_handled_index; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/terminal-dock-widget.cc --- a/libgui/src/terminal-dock-widget.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/terminal-dock-widget.cc Tue Dec 06 15:45:27 2022 -0500 @@ -45,127 +45,127 @@ OCTAVE_BEGIN_NAMESPACE(octave) -terminal_dock_widget::terminal_dock_widget (QWidget *p, - base_qobject& oct_qobj) -: octave_dock_widget ("TerminalDockWidget", p, oct_qobj), - m_experimental_terminal_widget (oct_qobj.experimental_terminal_widget ()) -{ - // FIXME: we could do this in a better way, but improving it doesn't - // matter much if we will eventually be removing the old terminal. - if (m_experimental_terminal_widget) - { + terminal_dock_widget::terminal_dock_widget (QWidget *p, + base_qobject& oct_qobj) + : octave_dock_widget ("TerminalDockWidget", p, oct_qobj), + m_experimental_terminal_widget (oct_qobj.experimental_terminal_widget ()) + { + // FIXME: we could do this in a better way, but improving it doesn't + // matter much if we will eventually be removing the old terminal. + if (m_experimental_terminal_widget) + { #if defined (HAVE_QSCINTILLA) - command_widget *widget = new command_widget (oct_qobj, this); - console *con = widget->get_console (); + command_widget *widget = new command_widget (oct_qobj, this); + console *con = widget->get_console (); - connect (this, &terminal_dock_widget::settings_changed, - widget, &command_widget::notice_settings); + connect (this, &terminal_dock_widget::settings_changed, + widget, &command_widget::notice_settings); - connect (this, &terminal_dock_widget::update_prompt_signal, - widget, &command_widget::update_prompt); + connect (this, &terminal_dock_widget::update_prompt_signal, + widget, &command_widget::update_prompt); - connect (this, &terminal_dock_widget::interpreter_output_signal, - widget, &command_widget::insert_interpreter_output); + connect (this, &terminal_dock_widget::interpreter_output_signal, + widget, &command_widget::insert_interpreter_output); - connect (this, &terminal_dock_widget::execute_command_signal, - con, &console::execute_command); + connect (this, &terminal_dock_widget::execute_command_signal, + con, &console::execute_command); - connect (this, &terminal_dock_widget::new_command_line_signal, - con, &console::new_command_line); + connect (this, &terminal_dock_widget::new_command_line_signal, + con, &console::new_command_line); - m_terminal = widget; + m_terminal = widget; #endif - } - else - { - QTerminal *widget = QTerminal::create (oct_qobj, this); + } + else + { + QTerminal *widget = QTerminal::create (oct_qobj, this); - connect (this, &terminal_dock_widget::settings_changed, - widget, &QTerminal::notice_settings); + connect (this, &terminal_dock_widget::settings_changed, + widget, &QTerminal::notice_settings); - // Connect the visibility signal to the terminal for - // dis-/enabling timers. - connect (this, &terminal_dock_widget::visibilityChanged, - widget, &QTerminal::handle_visibility_changed); + // Connect the visibility signal to the terminal for + // dis-/enabling timers. + connect (this, &terminal_dock_widget::visibilityChanged, + widget, &QTerminal::handle_visibility_changed); - m_terminal = widget; - } + m_terminal = widget; + } - m_terminal->setObjectName ("OctaveTerminal"); - m_terminal->setFocusPolicy (Qt::StrongFocus); + m_terminal->setObjectName ("OctaveTerminal"); + m_terminal->setFocusPolicy (Qt::StrongFocus); - set_title (tr ("Command Window")); + set_title (tr ("Command Window")); - setWidget (m_terminal); - setFocusProxy (m_terminal); + setWidget (m_terminal); + setFocusProxy (m_terminal); - // Chose a reasonable size at startup in order to avoid truncated - // startup messages - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + // Chose a reasonable size at startup in order to avoid truncated + // startup messages + + gui_settings settings; - QFont font = QFont (); - font.setStyleHint (QFont::TypeWriter); - QString default_font = settings->value (global_mono_font).toString (); - font.setFamily - (settings->value (cs_font.key, default_font).toString ()); - font.setPointSize - (settings->value (cs_font_size).toInt ()); + QFont font = QFont (); + font.setStyleHint (QFont::TypeWriter); + QString default_font = settings.value (global_mono_font).toString (); + font.setFamily + (settings.value (cs_font.key, default_font).toString ()); + font.setPointSize + (settings.value (cs_font_size).toInt ()); - QFontMetrics metrics(font); + QFontMetrics metrics(font); - int win_x = metrics.maxWidth()*80; - int win_y = metrics.height()*25; + int win_x = metrics.maxWidth()*80; + int win_y = metrics.height()*25; - int max_x = QGuiApplication::primaryScreen ()->availableGeometry ().width (); - int max_y = QGuiApplication::primaryScreen ()->availableGeometry ().height (); + int max_x = QGuiApplication::primaryScreen ()->availableGeometry ().width (); + int max_y = QGuiApplication::primaryScreen ()->availableGeometry ().height (); - if (win_x > max_x) - win_x = max_x; - if (win_y > max_y) - win_y = max_y; + if (win_x > max_x) + win_x = max_x; + if (win_y > max_y) + win_y = max_y; - setGeometry (0, 0, win_x, win_y); + setGeometry (0, 0, win_x, win_y); - if (! p) - make_window (); -} + if (! p) + make_window (); + } -bool terminal_dock_widget::has_focus (void) const -{ - QWidget *w = widget (); - return w->hasFocus (); -} + bool terminal_dock_widget::has_focus (void) const + { + QWidget *w = widget (); + return w->hasFocus (); + } -QTerminal * terminal_dock_widget::get_qterminal (void) -{ - return (m_experimental_terminal_widget - ? nullptr : dynamic_cast (m_terminal)); -} + QTerminal * terminal_dock_widget::get_qterminal (void) + { + return (m_experimental_terminal_widget + ? nullptr : dynamic_cast (m_terminal)); + } #if defined (HAVE_QSCINTILLA) -command_widget * terminal_dock_widget::get_command_widget (void) -{ - return (m_experimental_terminal_widget - ? dynamic_cast (m_terminal) : nullptr); -} + command_widget * terminal_dock_widget::get_command_widget (void) + { + return (m_experimental_terminal_widget + ? dynamic_cast (m_terminal) : nullptr); + } #endif -void terminal_dock_widget::notice_settings (const gui_settings *settings) -{ - emit settings_changed (settings); -} + void terminal_dock_widget::notice_settings (void) + { + emit settings_changed (); + } -void terminal_dock_widget::init_command_prompt () -{ - if (m_experimental_terminal_widget) - { + void terminal_dock_widget::init_command_prompt () + { + if (m_experimental_terminal_widget) + { #if defined (HAVE_QSCINTILLA) - command_widget *cmd = get_command_widget (); - if (cmd) - cmd->init_command_prompt (); + command_widget *cmd = get_command_widget (); + if (cmd) + cmd->init_command_prompt (); #endif - } -} + } + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/terminal-dock-widget.h --- a/libgui/src/terminal-dock-widget.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/terminal-dock-widget.h Tue Dec 06 15:45:27 2022 -0500 @@ -34,61 +34,61 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class command_widget; -class base_qobject; + class command_widget; + class base_qobject; -class terminal_dock_widget : public octave_dock_widget -{ - Q_OBJECT + class terminal_dock_widget : public octave_dock_widget + { + Q_OBJECT -public: + public: - terminal_dock_widget (QWidget *parent, base_qobject& oct_qobj); + terminal_dock_widget (QWidget *parent, base_qobject& oct_qobj); - ~terminal_dock_widget (void) = default; + ~terminal_dock_widget (void) = default; - bool has_focus (void) const; + bool has_focus (void) const; - void init_command_prompt (); + void init_command_prompt (); - // FIXME: The next two functions could be eliminated (or combined) - // if we had a common interface for the old and new terminal - // widgets. + // FIXME: The next two functions could be eliminated (or combined) + // if we had a common interface for the old and new terminal + // widgets. - // Only valid if using the old terminal widget. - QTerminal * get_qterminal (void); + // Only valid if using the old terminal widget. + QTerminal * get_qterminal (void); #if defined (HAVE_QSCINTILLA) - // Only valid if using the new terminal widget. - command_widget * get_command_widget (void); + // Only valid if using the new terminal widget. + command_widget * get_command_widget (void); #endif -signals: + signals: - void settings_changed (const gui_settings *settings); + void settings_changed (void); - // Note: the following four signals are - // currently only used by the new experimental terminal widget. + // Note: the following four signals are + // currently only used by the new experimental terminal widget. - void update_prompt_signal (const QString&); + void update_prompt_signal (const QString&); - void interpreter_output_signal (const QString&); + void interpreter_output_signal (const QString&); - void new_command_line_signal (const QString& = QString ()); + void new_command_line_signal (const QString& = QString ()); - void execute_command_signal (const QString&); + void execute_command_signal (const QString&); -public slots: + public slots: - void notice_settings (const gui_settings *settings); + void notice_settings (void); -private: + private: - bool m_experimental_terminal_widget; + bool m_experimental_terminal_widget; - // FIXME!!! Maybe my_term should just be derived from QTerminal? - QWidget *m_terminal; -}; + // FIXME!!! Maybe my_term should just be derived from QTerminal? + QWidget *m_terminal; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/variable-editor.cc --- a/libgui/src/variable-editor.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/variable-editor.cc Tue Dec 06 15:45:27 2022 -0500 @@ -55,6 +55,7 @@ #include "gui-preferences-global.h" #include "gui-preferences-sc.h" #include "gui-preferences-ve.h" +#include "gui-settings.h" #include "octave-qobject.h" #include "octave-qtutils.h" #include "ovl.h" @@ -65,1721 +66,1722 @@ OCTAVE_BEGIN_NAMESPACE(octave) -// Code reuse functions + // Code reuse functions -static QSignalMapper * -make_plot_mapper (QMenu *menu) -{ - QList list; - list << "plot" << "bar" << "stem" << "stairs" << "area" << "pie" << "hist"; + static QSignalMapper * + make_plot_mapper (QMenu *menu) + { + QList list; + list << "plot" << "bar" << "stem" << "stairs" << "area" << "pie" << "hist"; - QSignalMapper *plot_mapper = new QSignalMapper (menu); + QSignalMapper *plot_mapper = new QSignalMapper (menu); - for (int i = 0; i < list.size(); ++i) - plot_mapper->setMapping - (menu->addAction (list.at (i), plot_mapper, SLOT (map ())), list.at (i)); + for (int i = 0; i < list.size(); ++i) + plot_mapper->setMapping + (menu->addAction (list.at (i), plot_mapper, SLOT (map ())), list.at (i)); - return plot_mapper; -} + return plot_mapper; + } -// Variable dock widget + // Variable dock widget -variable_dock_widget::variable_dock_widget (QWidget *p, - base_qobject& oct_qobj) - : label_dock_widget (p, oct_qobj) - // See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813 + variable_dock_widget::variable_dock_widget (QWidget *p, + base_qobject& oct_qobj) + : label_dock_widget (p, oct_qobj) +// See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813 #if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION) - , m_waiting_for_mouse_move (false) - , m_waiting_for_mouse_button_release (false) + , m_waiting_for_mouse_move (false) + , m_waiting_for_mouse_button_release (false) #endif -{ - setFocusPolicy (Qt::StrongFocus); - setAttribute (Qt::WA_DeleteOnClose); + { + setFocusPolicy (Qt::StrongFocus); + setAttribute (Qt::WA_DeleteOnClose); - connect (m_dock_action, &QAction::triggered, - this, &variable_dock_widget::change_floating); - connect (m_close_action, &QAction::triggered, - this, &variable_dock_widget::change_existence); - connect (this, &variable_dock_widget::topLevelChanged, - this, &variable_dock_widget::toplevel_change); + connect (m_dock_action, &QAction::triggered, + this, &variable_dock_widget::change_floating); + connect (m_close_action, &QAction::triggered, + this, &variable_dock_widget::change_existence); + connect (this, &variable_dock_widget::topLevelChanged, + this, &variable_dock_widget::toplevel_change); #define DOCKED_FULLSCREEN_BUTTON_TOOLTIP "Fullscreen undock" #define UNDOCKED_FULLSCREEN_BUTTON_TOOLTIP "Fullscreen" - // Add a fullscreen button + // Add a fullscreen button - m_fullscreen_action = nullptr; - m_full_screen = false; - m_prev_floating = false; - m_prev_geom = QRect (0, 0, 0, 0); + m_fullscreen_action = nullptr; + m_full_screen = false; + m_prev_floating = false; + m_prev_geom = QRect (0, 0, 0, 0); + + QHBoxLayout *h_layout = m_title_widget->findChild (); - QHBoxLayout *h_layout = m_title_widget->findChild (); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - m_fullscreen_action - = new QAction (rmgr.icon ("view-fullscreen", false), "", this); - m_fullscreen_action->setToolTip (tr (DOCKED_FULLSCREEN_BUTTON_TOOLTIP)); - QToolButton *fullscreen_button = new QToolButton (m_title_widget); - fullscreen_button->setDefaultAction (m_fullscreen_action); - fullscreen_button->setFocusPolicy (Qt::NoFocus); - fullscreen_button->setIconSize (QSize (m_icon_size, m_icon_size)); - QString css_button = QString ("QToolButton {background: transparent; border: 0px;}"); - fullscreen_button->setStyleSheet (css_button); + gui_settings settings; + m_fullscreen_action + = new QAction (settings.icon ("view-fullscreen", false), "", this); + m_fullscreen_action->setToolTip (tr (DOCKED_FULLSCREEN_BUTTON_TOOLTIP)); + QToolButton *fullscreen_button = new QToolButton (m_title_widget); + fullscreen_button->setDefaultAction (m_fullscreen_action); + fullscreen_button->setFocusPolicy (Qt::NoFocus); + fullscreen_button->setIconSize (QSize (m_icon_size, m_icon_size)); + QString css_button = QString ("QToolButton {background: transparent; border: 0px;}"); + fullscreen_button->setStyleSheet (css_button); - connect (m_fullscreen_action, &QAction::triggered, - this, &variable_dock_widget::change_fullscreen); + connect (m_fullscreen_action, &QAction::triggered, + this, &variable_dock_widget::change_fullscreen); - int index = -1; - QToolButton *first = m_title_widget->findChild (); - if (first != nullptr) - index = h_layout->indexOf (first); - h_layout->insertWidget (index, fullscreen_button); + int index = -1; + QToolButton *first = m_title_widget->findChild (); + if (first != nullptr) + index = h_layout->indexOf (first); + h_layout->insertWidget (index, fullscreen_button); - // Custom title bars cause loss of decorations, add a frame - m_frame = new QFrame (this); - m_frame->setFrameStyle (QFrame::Box | QFrame::Sunken); - m_frame->setAttribute (Qt::WA_TransparentForMouseEvents); -} + // Custom title bars cause loss of decorations, add a frame + m_frame = new QFrame (this); + m_frame->setFrameStyle (QFrame::Box | QFrame::Sunken); + m_frame->setAttribute (Qt::WA_TransparentForMouseEvents); + } -// slot for (un)dock action -void -variable_dock_widget::change_floating (bool) -{ - if (isFloating ()) - { - if (m_full_screen) - { - setGeometry (m_prev_geom); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - m_fullscreen_action->setIcon (rmgr.icon ("view-fullscreen", false)); - m_full_screen = false; - } - m_fullscreen_action->setToolTip (tr (DOCKED_FULLSCREEN_BUTTON_TOOLTIP)); - } - else - m_fullscreen_action->setToolTip (tr (UNDOCKED_FULLSCREEN_BUTTON_TOOLTIP)); + // slot for (un)dock action + void + variable_dock_widget::change_floating (bool) + { + if (isFloating ()) + { + if (m_full_screen) + { + setGeometry (m_prev_geom); + gui_settings settings; + m_fullscreen_action->setIcon (settings.icon ("view-fullscreen", false)); + m_full_screen = false; + } + m_fullscreen_action->setToolTip (tr (DOCKED_FULLSCREEN_BUTTON_TOOLTIP)); + } + else + m_fullscreen_action->setToolTip (tr (UNDOCKED_FULLSCREEN_BUTTON_TOOLTIP)); - setFloating (! isFloating ()); -} + setFloating (! isFloating ()); + } -// slot for hiding the widget -void -variable_dock_widget::change_existence (bool) -{ - close (); -} + // slot for hiding the widget + void + variable_dock_widget::change_existence (bool) + { + close (); + } -void -variable_dock_widget::toplevel_change (bool toplevel) -{ - if (toplevel) - { - m_dock_action->setIcon (QIcon (global_icon_paths.at (ICON_THEME_OCTAVE) - + "widget-dock.png")); - m_dock_action->setToolTip (tr ("Dock widget")); + void + variable_dock_widget::toplevel_change (bool toplevel) + { + if (toplevel) + { + m_dock_action->setIcon (QIcon (global_icon_paths.at (ICON_THEME_OCTAVE) + + "widget-dock.png")); + m_dock_action->setToolTip (tr ("Dock widget")); - setWindowFlags (Qt::Window); - setWindowTitle (tr ("Variable Editor: ") + objectName ()); + setWindowFlags (Qt::Window); + setWindowTitle (tr ("Variable Editor: ") + objectName ()); - show (); - activateWindow (); - setFocus (); + show (); + activateWindow (); + setFocus (); - // See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813 +// See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813 #if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION) - m_waiting_for_mouse_move = true; + m_waiting_for_mouse_move = true; #endif - } - else - { - m_dock_action->setIcon (QIcon (global_icon_paths.at (ICON_THEME_OCTAVE) - + "widget-undock.png")); - m_dock_action->setToolTip (tr ("Undock widget")); + } + else + { + m_dock_action->setIcon (QIcon (global_icon_paths.at (ICON_THEME_OCTAVE) + + "widget-undock.png")); + m_dock_action->setToolTip (tr ("Undock widget")); - setFocus (); + setFocus (); - // See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813 +// See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813 #if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION) - m_waiting_for_mouse_move = false; - m_waiting_for_mouse_button_release = false; + m_waiting_for_mouse_move = false; + m_waiting_for_mouse_button_release = false; #endif - } -} + } + } -void -variable_dock_widget::change_fullscreen (void) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + void + variable_dock_widget::change_fullscreen (void) + { + gui_settings settings; - if (! m_full_screen) - { - m_prev_floating = isFloating (); - m_fullscreen_action->setIcon (rmgr.icon ("view-restore", false)); - if (m_prev_floating) - m_fullscreen_action->setToolTip (tr ("Restore geometry")); - else - { - m_fullscreen_action->setToolTip (tr ("Redock")); - setFloating (true); - } - m_prev_geom = geometry (); + if (! m_full_screen) + { + m_prev_floating = isFloating (); + m_fullscreen_action->setIcon (settings.icon ("view-restore", false)); + if (m_prev_floating) + m_fullscreen_action->setToolTip (tr ("Restore geometry")); + else + { + m_fullscreen_action->setToolTip (tr ("Redock")); + setFloating (true); + } + m_prev_geom = geometry (); - // showFullscreen() and setWindowState() only work for QWindow objects. - QScreen *pscreen = QGuiApplication::primaryScreen (); - QRect rect (0, 0, 0, 0); - rect = pscreen->availableGeometry (); - setGeometry (rect); + // showFullscreen() and setWindowState() only work for QWindow objects. + QScreen *pscreen = QGuiApplication::primaryScreen (); + QRect rect (0, 0, 0, 0); + rect = pscreen->availableGeometry (); + setGeometry (rect); - m_full_screen = true; - } - else - { - m_fullscreen_action->setIcon (rmgr.icon ("view-fullscreen", false)); - setGeometry (m_prev_geom); - if (m_prev_floating) - m_fullscreen_action->setToolTip (tr (UNDOCKED_FULLSCREEN_BUTTON_TOOLTIP)); - else - { - setFloating (false); - m_fullscreen_action->setToolTip (tr (DOCKED_FULLSCREEN_BUTTON_TOOLTIP)); - } + m_full_screen = true; + } + else + { + m_fullscreen_action->setIcon (settings.icon ("view-fullscreen", false)); + setGeometry (m_prev_geom); + if (m_prev_floating) + m_fullscreen_action->setToolTip (tr (UNDOCKED_FULLSCREEN_BUTTON_TOOLTIP)); + else + { + setFloating (false); + m_fullscreen_action->setToolTip (tr (DOCKED_FULLSCREEN_BUTTON_TOOLTIP)); + } - m_full_screen = false; - } + m_full_screen = false; + } #undef DOCKED_FULLSCREEN_BUTTON_TOOLTIP #undef UNDOCKED_FULLSCREEN_BUTTON_TOOLTIP -} + } -void -variable_dock_widget::closeEvent (QCloseEvent *e) -{ - QDockWidget::closeEvent (e); -} + void + variable_dock_widget::closeEvent (QCloseEvent *e) + { + QDockWidget::closeEvent (e); + } -void -variable_dock_widget::handle_focus_change (QWidget *old, QWidget *now) -{ - octave_unused_parameter (now); + void + variable_dock_widget::handle_focus_change (QWidget *old, QWidget *now) + { + octave_unused_parameter (now); - // This is a proxied test - if (hasFocus ()) - { - if (old == this) - return; + // This is a proxied test + if (hasFocus ()) + { + if (old == this) + return; - if (titleBarWidget () != nullptr) - { - QLabel *label = titleBarWidget ()->findChild (); - if (label != nullptr) - { - label->setBackgroundRole (QPalette::Highlight); - label->setStyleSheet ("background-color: palette(highlight); color: palette(highlightedText);"); - } - } + if (titleBarWidget () != nullptr) + { + QLabel *label = titleBarWidget ()->findChild (); + if (label != nullptr) + { + label->setBackgroundRole (QPalette::Highlight); + label->setStyleSheet ("background-color: palette(highlight); color: palette(highlightedText);"); + } + } - emit variable_focused_signal (objectName ()); - } - else if (old == focusWidget()) - { - if (titleBarWidget () != nullptr) - { - QLabel *label = titleBarWidget ()->findChild (); - if (label != nullptr) - { - label->setBackgroundRole (QPalette::NoRole); - label->setStyleSheet (";"); - } - } - } -} + emit variable_focused_signal (objectName ()); + } + else if (old == focusWidget()) + { + if (titleBarWidget () != nullptr) + { + QLabel *label = titleBarWidget ()->findChild (); + if (label != nullptr) + { + label->setBackgroundRole (QPalette::NoRole); + label->setStyleSheet (";"); + } + } + } + } -void variable_dock_widget::resizeEvent (QResizeEvent *) -{ - if (m_frame) - m_frame->resize (size ()); -} + void variable_dock_widget::resizeEvent (QResizeEvent *) + { + if (m_frame) + m_frame->resize (size ()); + } // See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813 #if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION) -bool -variable_dock_widget::event (QEvent *event) -{ - // low-level check of whether docked-widget became a window via - // via drag-and-drop - if (event->type () == QEvent::MouseButtonPress) - { - m_waiting_for_mouse_move = false; - m_waiting_for_mouse_button_release = false; - } - if (event->type () == QEvent::MouseMove && m_waiting_for_mouse_move) - { - m_waiting_for_mouse_move = false; - m_waiting_for_mouse_button_release = true; - } - if (event->type () == QEvent::MouseButtonRelease - && m_waiting_for_mouse_button_release) - { - m_waiting_for_mouse_button_release = false; - bool retval = QDockWidget::event (event); - if (isFloating ()) - emit queue_unfloat_float (); - return retval; - } + bool + variable_dock_widget::event (QEvent *event) + { + // low-level check of whether docked-widget became a window via + // via drag-and-drop + if (event->type () == QEvent::MouseButtonPress) + { + m_waiting_for_mouse_move = false; + m_waiting_for_mouse_button_release = false; + } + if (event->type () == QEvent::MouseMove && m_waiting_for_mouse_move) + { + m_waiting_for_mouse_move = false; + m_waiting_for_mouse_button_release = true; + } + if (event->type () == QEvent::MouseButtonRelease + && m_waiting_for_mouse_button_release) + { + m_waiting_for_mouse_button_release = false; + bool retval = QDockWidget::event (event); + if (isFloating ()) + emit queue_unfloat_float (); + return retval; + } - return QDockWidget::event (event); -} + return QDockWidget::event (event); + } -void -variable_dock_widget::unfloat_float (void) -{ - hide (); - setFloating (false); - // Avoid a Ubunty Unity issue by queuing this rather than direct. - emit queue_float (); - m_waiting_for_mouse_move = false; - m_waiting_for_mouse_button_release = false; -} + void + variable_dock_widget::unfloat_float (void) + { + hide (); + setFloating (false); + // Avoid a Ubunty Unity issue by queuing this rather than direct. + emit queue_float (); + m_waiting_for_mouse_move = false; + m_waiting_for_mouse_button_release = false; + } -void -variable_dock_widget::refloat (void) -{ - setFloating (true); - m_waiting_for_mouse_move = false; - m_waiting_for_mouse_button_release = false; - show (); - activateWindow (); - setFocus (); -} + void + variable_dock_widget::refloat (void) + { + setFloating (true); + m_waiting_for_mouse_move = false; + m_waiting_for_mouse_button_release = false; + show (); + activateWindow (); + setFocus (); + } #else -void -variable_dock_widget::unfloat_float (void) -{ } + void + variable_dock_widget::unfloat_float (void) + { } -void -variable_dock_widget::refloat (void) -{ } + void + variable_dock_widget::refloat (void) + { } #endif -// Variable editor stack + // Variable editor stack -variable_editor_stack::variable_editor_stack (QWidget *p, - base_qobject& oct_qobj) - : QStackedWidget (p), m_octave_qobj (oct_qobj), - m_edit_view (new variable_editor_view (this, m_octave_qobj)) -{ - setFocusPolicy (Qt::StrongFocus); + variable_editor_stack::variable_editor_stack (QWidget *p, + base_qobject& oct_qobj) + : QStackedWidget (p), m_octave_qobj (oct_qobj), + m_edit_view (new variable_editor_view (this, m_octave_qobj)) + { + setFocusPolicy (Qt::StrongFocus); - m_disp_view = make_disp_view (this); + m_disp_view = make_disp_view (this); - addWidget (m_edit_view); - addWidget (m_disp_view); -} + addWidget (m_edit_view); + addWidget (m_disp_view); + } -QTextEdit * -variable_editor_stack::make_disp_view (QWidget *parent) -{ - QTextEdit *viewer = new QTextEdit (parent); + QTextEdit * + variable_editor_stack::make_disp_view (QWidget *parent) + { + QTextEdit *viewer = new QTextEdit (parent); - viewer->setLineWrapMode (QTextEdit::NoWrap); - viewer->setReadOnly (true); + viewer->setLineWrapMode (QTextEdit::NoWrap); + viewer->setReadOnly (true); - return viewer; -} + return viewer; + } -void -variable_editor_stack::set_editable (bool editable) -{ - // The QTableView is for editable data models - // and the QTextEdit is for non-editable models. + void + variable_editor_stack::set_editable (bool editable) + { + // The QTableView is for editable data models + // and the QTextEdit is for non-editable models. - if (editable) - { - if (m_edit_view != nullptr) - { - setCurrentWidget (m_edit_view); - setFocusProxy (m_edit_view); - m_edit_view->setFocusPolicy (Qt::StrongFocus); - } + if (editable) + { + if (m_edit_view != nullptr) + { + setCurrentWidget (m_edit_view); + setFocusProxy (m_edit_view); + m_edit_view->setFocusPolicy (Qt::StrongFocus); + } - if (m_disp_view != nullptr) - m_disp_view->setFocusPolicy (Qt::NoFocus); - } - else - { - if (m_disp_view != nullptr) - { - setCurrentWidget (m_disp_view); - setFocusProxy (m_disp_view); + if (m_disp_view != nullptr) + m_disp_view->setFocusPolicy (Qt::NoFocus); + } + else + { + if (m_disp_view != nullptr) + { + setCurrentWidget (m_disp_view); + setFocusProxy (m_disp_view); - QAbstractTableModel *model = findChild (); - if (model != nullptr) - m_disp_view->setPlainText (model->data (QModelIndex ()).toString ()); - else - m_disp_view->setPlainText (""); - } + QAbstractTableModel *model = findChild (); + if (model != nullptr) + m_disp_view->setPlainText (model->data (QModelIndex ()).toString ()); + else + m_disp_view->setPlainText (""); + } - if (m_edit_view != nullptr) - m_edit_view->setFocusPolicy (Qt::NoFocus); - } -} + if (m_edit_view != nullptr) + m_edit_view->setFocusPolicy (Qt::NoFocus); + } + } -void -variable_editor_stack::levelUp (void) -{ - if (! hasFocus ()) - return; + void + variable_editor_stack::levelUp (void) + { + if (! hasFocus ()) + return; - QString name = objectName (); + QString name = objectName (); - // FIXME: Is there a better way? + // FIXME: Is there a better way? - if (name.endsWith (')') || name.endsWith ('}')) - { - name.remove ( QRegExp ("[({][^({]*[)}]$)") ); - emit edit_variable_signal (name, octave_value ()); - } -} + if (name.endsWith (')') || name.endsWith ('}')) + { + name.remove ( QRegExp ("[({][^({]*[)}]$)") ); + emit edit_variable_signal (name, octave_value ()); + } + } -// Slot for saving a variable into a file -void -variable_editor_stack::save (const QString& format) -{ - if (! hasFocus ()) - return; - - // Check whether a format for saving the variable is given - QString format_string; - if (! format.isEmpty ()) - { - format_string = "-" + format; - do_save (format_string, format_string); + // Slot for saving a variable into a file + void + variable_editor_stack::save (const QString& format) + { + if (! hasFocus ()) return; - } - // No format given, test save default options - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD + // Check whether a format for saving the variable is given + QString format_string; + if (! format.isEmpty ()) + { + format_string = "-" + format; + do_save (format_string, format_string); + return; + } - octave_value_list argout - = Fsave_default_options (interp, octave_value_list (), 1); - QString save_opts = QString::fromStdString (argout(0).string_value ()); + // No format given, test save default options + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD - connect (this, &variable_editor_stack::do_save_signal, - this, &variable_editor_stack::do_save); + octave_value_list argout + = Fsave_default_options (interp, octave_value_list (), 1); + QString save_opts = QString::fromStdString (argout(0).string_value ()); - emit (do_save_signal (format_string, save_opts)); + connect (this, &variable_editor_stack::do_save_signal, + this, &variable_editor_stack::do_save); - }); -} + emit (do_save_signal (format_string, save_opts)); -// Perform saving the variable after desired format is determined -void -variable_editor_stack::do_save (const QString& format, const QString& save_opts) -{ - QString file_ext = "txt"; - for (int i = 0; i < ve_save_formats_ext.length ()/2; i++) - { - if (save_opts.contains (ve_save_formats_ext.at (2*i), Qt::CaseInsensitive)) - { - file_ext = ve_save_formats_ext.at (2*i + 1); - break; - } - } + }); + } - // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - int opts = 0; // No options by default. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) - opts = QFileDialog::DontUseNativeDialog; + // Perform saving the variable after desired format is determined + void + variable_editor_stack::do_save (const QString& format, const QString& save_opts) + { + QString file_ext = "txt"; + for (int i = 0; i < ve_save_formats_ext.length ()/2; i++) + { + if (save_opts.contains (ve_save_formats_ext.at (2*i), Qt::CaseInsensitive)) + { + file_ext = ve_save_formats_ext.at (2*i + 1); + break; + } + } - QString name = objectName (); - QString file - = QFileDialog::getSaveFileName (this, - tr ("Save Variable %1 As").arg (name), - QString ("./%1.%2").arg (name).arg (file_ext), - 0, 0, QFileDialog::Option (opts)); + // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. + int opts = 0; // No options by default. + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) + opts = QFileDialog::DontUseNativeDialog; - if (file.isEmpty ()) - return; // No file selected: Just return + QString name = objectName (); + QString file + = QFileDialog::getSaveFileName (this, + tr ("Save Variable %1 As").arg (name), + QString ("./%1.%2").arg (name).arg (file_ext), + 0, 0, QFileDialog::Option (opts)); - // Let the interpreter thread do the saving - emit interpreter_event - ([=] (interpreter& interp) - { - // INTERPRETER THREAD + if (file.isEmpty ()) + return; // No file selected: Just return - octave_value_list ovl; - std::list str_list - = {octave_value (file.toStdString ()), - octave_value (name.toStdString ())}; - if (! format.isEmpty ()) - str_list.push_front (octave_value (format.toStdString ())); + // Let the interpreter thread do the saving + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD - Fsave (interp, octave_value_list (str_list)); - }); -} - -// Custom editable variable table view + octave_value_list ovl; + std::list str_list + = {octave_value (file.toStdString ()), + octave_value (name.toStdString ())}; + if (! format.isEmpty ()) + str_list.push_front (octave_value (format.toStdString ())); -variable_editor_view::variable_editor_view (QWidget *p, - base_qobject& oct_qobj) - : QTableView (p), m_octave_qobj (oct_qobj), m_var_model (nullptr) -{ - setWordWrap (false); - setContextMenuPolicy (Qt::CustomContextMenu); - setSelectionMode (QAbstractItemView::ContiguousSelection); + Fsave (interp, octave_value_list (str_list)); + }); + } + + // Custom editable variable table view - horizontalHeader ()->setContextMenuPolicy (Qt::CustomContextMenu); - verticalHeader ()->setContextMenuPolicy (Qt::CustomContextMenu); + variable_editor_view::variable_editor_view (QWidget *p, + base_qobject& oct_qobj) + : QTableView (p), m_octave_qobj (oct_qobj), m_var_model (nullptr) + { + setWordWrap (false); + setContextMenuPolicy (Qt::CustomContextMenu); + setSelectionMode (QAbstractItemView::ContiguousSelection); - setHorizontalScrollMode (QAbstractItemView::ScrollPerPixel); - setVerticalScrollMode (QAbstractItemView::ScrollPerPixel); + horizontalHeader ()->setContextMenuPolicy (Qt::CustomContextMenu); + verticalHeader ()->setContextMenuPolicy (Qt::CustomContextMenu); - verticalHeader ()->setSectionResizeMode (QHeaderView::Interactive); -} + setHorizontalScrollMode (QAbstractItemView::ScrollPerPixel); + setVerticalScrollMode (QAbstractItemView::ScrollPerPixel); -void -variable_editor_view::setModel (QAbstractItemModel *model) -{ - QTableView::setModel (model); + verticalHeader ()->setSectionResizeMode (QHeaderView::Interactive); + } - horizontalHeader ()->setSectionResizeMode (QHeaderView::Interactive); + void + variable_editor_view::setModel (QAbstractItemModel *model) + { + QTableView::setModel (model); - m_var_model = parent ()->findChild (); + horizontalHeader ()->setSectionResizeMode (QHeaderView::Interactive); - if (m_var_model != nullptr && m_var_model->column_width () > 0) - { - // col_width is in characters. The font should be a fixed-width - // font, so any character will do. If not, you lose! + m_var_model = parent ()->findChild (); + + if (m_var_model != nullptr && m_var_model->column_width () > 0) + { + // col_width is in characters. The font should be a fixed-width + // font, so any character will do. If not, you lose! - QFontMetrics fm (font ()); - int w = (m_var_model->column_width () - * qt_fontmetrics_horizontal_advance (fm, '0')); - horizontalHeader ()->setDefaultSectionSize (w); - } -} + QFontMetrics fm (font ()); + int w = (m_var_model->column_width () + * qt_fontmetrics_horizontal_advance (fm, '0')); + horizontalHeader ()->setDefaultSectionSize (w); + } + } -QList -variable_editor_view::range_selected (void) -{ - QItemSelectionModel *sel = selectionModel (); + QList + variable_editor_view::range_selected (void) + { + QItemSelectionModel *sel = selectionModel (); - // Return early if nothing selected. - if (! sel->hasSelection ()) - return QList (); + // Return early if nothing selected. + if (! sel->hasSelection ()) + return QList (); - QList indices = sel->selectedIndexes (); + QList indices = sel->selectedIndexes (); - // FIXME: Shouldn't this be keyed to octave_idx_type? + // FIXME: Shouldn't this be keyed to octave_idx_type? - int32_t from_row = std::numeric_limits::max (); - int32_t to_row = 0; - int32_t from_col = std::numeric_limits::max (); - int32_t to_col = 0; + int32_t from_row = std::numeric_limits::max (); + int32_t to_row = 0; + int32_t from_col = std::numeric_limits::max (); + int32_t to_col = 0; - for (const auto& idx : indices) - { - from_row = std::min (from_row, idx.row ()); - to_row = std::max (to_row, idx.row ()); - from_col = std::min (from_col, idx.column ()); - to_col = std::max (to_col, idx.column ()); - } + for (const auto& idx : indices) + { + from_row = std::min (from_row, idx.row ()); + to_row = std::max (to_row, idx.row ()); + from_col = std::min (from_col, idx.column ()); + to_col = std::max (to_col, idx.column ()); + } - QVector vect; - vect << from_row + 1 << to_row + 1 << from_col + 1 << to_col + 1; - QList range = QList::fromVector(vect); + QVector vect; + vect << from_row + 1 << to_row + 1 << from_col + 1 << to_col + 1; + QList range = QList::fromVector(vect); - return range; -} + return range; + } -void -variable_editor_view::selected_command_requested (const QString& cmd) -{ - if (! hasFocus ()) - return; + void + variable_editor_view::selected_command_requested (const QString& cmd) + { + if (! hasFocus ()) + return; - QList range = range_selected (); - if (range.isEmpty ()) - { - // Nothing selected, apply print command to all data - range << 1 << m_var_model->data_rows () - << 1 << m_var_model->data_columns (); - } + QList range = range_selected (); + if (range.isEmpty ()) + { + // Nothing selected, apply print command to all data + range << 1 << m_var_model->data_rows () + << 1 << m_var_model->data_columns (); + } - int s1 = m_var_model->data_rows (); - int s2 = m_var_model->data_columns (); - if (s1 < range.at (0) || s2 < range.at (2)) - return; // Selected range does not contain data + int s1 = m_var_model->data_rows (); + int s2 = m_var_model->data_columns (); + if (s1 < range.at (0) || s2 < range.at (2)) + return; // Selected range does not contain data - s1 = std::min (s1, range.at (1)); - s2 = std::min (s2, range.at (3)); + s1 = std::min (s1, range.at (1)); + s2 = std::min (s2, range.at (3)); - // Variable with desired range as string - QString variable = QString ("%1(%2:%3,%4:%5)") - .arg (objectName ()) - .arg (range.at (0)).arg (s1) - .arg (range.at (2)).arg (s2); + // Variable with desired range as string + QString variable = QString ("%1(%2:%3,%4:%5)") + .arg (objectName ()) + .arg (range.at (0)).arg (s1) + .arg (range.at (2)).arg (s2); - // Desired command as string - QString command; - if (cmd == "create") - command = QString ("unnamed = %1;").arg (variable); - else - command = QString ("figure (); %1 (%2); title ('%2');") - .arg (cmd).arg (variable); + // Desired command as string + QString command; + if (cmd == "create") + command = QString ("unnamed = %1;").arg (variable); + else + command = QString ("figure (); %1 (%2); title ('%2');") + .arg (cmd).arg (variable); - emit command_signal (command); -} + emit command_signal (command); + } -void -variable_editor_view::add_edit_actions (QMenu *menu, - const QString& qualifier_string) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + void + variable_editor_view::add_edit_actions (QMenu *menu, + const QString& qualifier_string) + { + gui_settings settings; - menu->addAction (rmgr.icon ("edit-cut"), - tr ("Cut") + qualifier_string, - this, &variable_editor_view::cutClipboard); + menu->addAction (settings.icon ("edit-cut"), + tr ("Cut") + qualifier_string, + this, &variable_editor_view::cutClipboard); - menu->addAction (rmgr.icon ("edit-copy"), - tr ("Copy") + qualifier_string, - this, &variable_editor_view::copyClipboard); + menu->addAction (settings.icon ("edit-copy"), + tr ("Copy") + qualifier_string, + this, &variable_editor_view::copyClipboard); - menu->addAction (rmgr.icon ("edit-paste"), - tr ("Paste"), - this, &variable_editor_view::pasteClipboard); + menu->addAction (settings.icon ("edit-paste"), + tr ("Paste"), + this, &variable_editor_view::pasteClipboard); - menu->addSeparator (); + menu->addSeparator (); - menu->addAction (rmgr.icon ("edit-delete"), - tr ("Clear") + qualifier_string, - this, &variable_editor_view::clearContent); + menu->addAction (settings.icon ("edit-delete"), + tr ("Clear") + qualifier_string, + this, &variable_editor_view::clearContent); - menu->addAction (rmgr.icon ("edit-delete"), - tr ("Delete") + qualifier_string, - this, &variable_editor_view::delete_selected); + menu->addAction (settings.icon ("edit-delete"), + tr ("Delete") + qualifier_string, + this, &variable_editor_view::delete_selected); - menu->addAction (rmgr.icon ("document-new"), - tr ("Variable from Selection"), - this, &variable_editor_view::createVariable); -} + menu->addAction (settings.icon ("document-new"), + tr ("Variable from Selection"), + this, &variable_editor_view::createVariable); + } -void -variable_editor_view::createContextMenu (const QPoint& qpos) -{ - QModelIndex index = indexAt (qpos); + void + variable_editor_view::createContextMenu (const QPoint& qpos) + { + QModelIndex index = indexAt (qpos); - if (index.isValid ()) - { - QMenu *menu = new QMenu (this); + if (index.isValid ()) + { + QMenu *menu = new QMenu (this); - add_edit_actions (menu, tr ("")); + add_edit_actions (menu, tr ("")); - // FIXME: addAction for sort? - // FIXME: Add icon for transpose. + // FIXME: addAction for sort? + // FIXME: Add icon for transpose. - menu->addAction (tr ("Transpose"), - this, &variable_editor_view::transposeContent); + menu->addAction (tr ("Transpose"), + this, &variable_editor_view::transposeContent); - QItemSelectionModel *sel = selectionModel (); + QItemSelectionModel *sel = selectionModel (); - QList indices = sel->selectedIndexes (); + QList indices = sel->selectedIndexes (); - if (! indices.isEmpty ()) - { - menu->addSeparator (); + if (! indices.isEmpty ()) + { + menu->addSeparator (); - QSignalMapper *plot_mapper = make_plot_mapper (menu); + QSignalMapper *plot_mapper = make_plot_mapper (menu); - connect (plot_mapper, SIGNAL (mapped (const QString&)), - this, SLOT (selected_command_requested (const QString&))); - } + connect (plot_mapper, SIGNAL (mapped (const QString&)), + this, SLOT (selected_command_requested (const QString&))); + } - menu->exec (mapToGlobal (qpos)); - } -} + menu->exec (mapToGlobal (qpos)); + } + } -void -variable_editor_view::createColumnMenu (const QPoint& pt) -{ - int index = horizontalHeader ()->logicalIndexAt (pt); + void + variable_editor_view::createColumnMenu (const QPoint& pt) + { + int index = horizontalHeader ()->logicalIndexAt (pt); - if (index < 0 || index > model ()->columnCount ()) - return; + if (index < 0 || index > model ()->columnCount ()) + return; - QList coords = range_selected (); + QList coords = range_selected (); - bool nothingSelected = coords.isEmpty (); + bool nothingSelected = coords.isEmpty (); - bool whole_columns_selected - = (nothingSelected - ? false - : (coords[0] == 1 && coords[1] == model ()->rowCount ())); + bool whole_columns_selected + = (nothingSelected + ? false + : (coords[0] == 1 && coords[1] == model ()->rowCount ())); - bool current_column_selected - = nothingSelected ? false : (coords[2] <= index+1 && coords[3] > index); + bool current_column_selected + = nothingSelected ? false : (coords[2] <= index+1 && coords[3] > index); - int column_selection_count - = nothingSelected ? 0 : (coords[3] - coords[2] + 1); + int column_selection_count + = nothingSelected ? 0 : (coords[3] - coords[2] + 1); - if (! whole_columns_selected || ! current_column_selected) - { - selectColumn (index); - column_selection_count = 1; - } + if (! whole_columns_selected || ! current_column_selected) + { + selectColumn (index); + column_selection_count = 1; + } - QString column_string - = column_selection_count > 1 ? tr (" columns") : tr (" column"); + QString column_string + = column_selection_count > 1 ? tr (" columns") : tr (" column"); - QMenu *menu = new QMenu (this); + QMenu *menu = new QMenu (this); - add_edit_actions (menu, column_string); + add_edit_actions (menu, column_string); - menu->addSeparator (); + menu->addSeparator (); - QSignalMapper *plot_mapper = make_plot_mapper (menu); + QSignalMapper *plot_mapper = make_plot_mapper (menu); - connect (plot_mapper, SIGNAL (mapped (const QString&)), - this, SLOT (selected_command_requested (const QString&))); + connect (plot_mapper, SIGNAL (mapped (const QString&)), + this, SLOT (selected_command_requested (const QString&))); - QPoint menupos = pt; - menupos.setY (horizontalHeader ()->height ()); + QPoint menupos = pt; + menupos.setY (horizontalHeader ()->height ()); - menu->exec (mapToGlobal (menupos)); -} + menu->exec (mapToGlobal (menupos)); + } -void -variable_editor_view::createRowMenu (const QPoint& pt) -{ - int index = verticalHeader ()->logicalIndexAt (pt); + void + variable_editor_view::createRowMenu (const QPoint& pt) + { + int index = verticalHeader ()->logicalIndexAt (pt); - if (index < 0 || index > model ()->columnCount ()) - return; + if (index < 0 || index > model ()->columnCount ()) + return; - QList coords = range_selected (); + QList coords = range_selected (); - bool nothingSelected = coords.isEmpty (); + bool nothingSelected = coords.isEmpty (); - bool whole_rows_selected - = (nothingSelected - ? false - : (coords[2] == 1 && coords[3] == model ()->columnCount ())); + bool whole_rows_selected + = (nothingSelected + ? false + : (coords[2] == 1 && coords[3] == model ()->columnCount ())); - bool current_row_selected - = (nothingSelected ? false : (coords[0] <= index+1 && coords[1] > index)); + bool current_row_selected + = (nothingSelected ? false : (coords[0] <= index+1 && coords[1] > index)); - int rowselection_count = nothingSelected ? 0 : (coords[3] - coords[2] + 1); + int rowselection_count = nothingSelected ? 0 : (coords[3] - coords[2] + 1); - if (! whole_rows_selected || ! current_row_selected) - { - selectRow (index); - rowselection_count = 1; - } + if (! whole_rows_selected || ! current_row_selected) + { + selectRow (index); + rowselection_count = 1; + } - QString row_string = rowselection_count > 1 ? tr (" rows") : tr (" row"); + QString row_string = rowselection_count > 1 ? tr (" rows") : tr (" row"); - QMenu *menu = new QMenu (this); + QMenu *menu = new QMenu (this); - add_edit_actions (menu, row_string); + add_edit_actions (menu, row_string); - menu->addSeparator (); + menu->addSeparator (); - QSignalMapper *plot_mapper = make_plot_mapper (menu); + QSignalMapper *plot_mapper = make_plot_mapper (menu); - connect (plot_mapper, SIGNAL (mapped (const QString&)), - this, SLOT (selected_command_requested (const QString&))); + connect (plot_mapper, SIGNAL (mapped (const QString&)), + this, SLOT (selected_command_requested (const QString&))); - QPoint menupos = pt; - menupos.setX (verticalHeader ()->width ()); + QPoint menupos = pt; + menupos.setX (verticalHeader ()->width ()); - // FIXME: What was the intent here? - // setY (verticalHeader ()->sectionPosition (index+1) + - // verticalHeader ()->sectionSize (index)); + // FIXME: What was the intent here? + // setY (verticalHeader ()->sectionPosition (index+1) + + // verticalHeader ()->sectionSize (index)); - menu->exec (mapToGlobal (menupos)); -} + menu->exec (mapToGlobal (menupos)); + } -void -variable_editor_view::createVariable (void) -{ - // FIXME: Create unnamed1..n if exist ('unnamed', 'var') is true. + void + variable_editor_view::createVariable (void) + { + // FIXME: Create unnamed1..n if exist ('unnamed', 'var') is true. - selected_command_requested ("create"); -} + selected_command_requested ("create"); + } -void -variable_editor_view::transposeContent (void) -{ - if (! hasFocus ()) - return; + void + variable_editor_view::transposeContent (void) + { + if (! hasFocus ()) + return; - emit command_signal (QString ("%1 = %1';").arg (objectName ())); -} + emit command_signal (QString ("%1 = %1';").arg (objectName ())); + } -void -variable_editor_view::delete_selected (void) -{ - if (! hasFocus ()) - return; + void + variable_editor_view::delete_selected (void) + { + if (! hasFocus ()) + return; - QAbstractItemModel *mod = model (); - QList coords = range_selected (); + QAbstractItemModel *mod = model (); + QList coords = range_selected (); - if (coords.isEmpty ()) - return; + if (coords.isEmpty ()) + return; - bool whole_columns_selected - = coords[0] == 1 && coords[1] == mod->rowCount (); + bool whole_columns_selected + = coords[0] == 1 && coords[1] == mod->rowCount (); - bool whole_rows_selected - = coords[2] == 1 && coords[3] == mod->columnCount (); + bool whole_rows_selected + = coords[2] == 1 && coords[3] == mod->columnCount (); - // Must be deleting whole columns or whole rows, and not the whole thing. + // Must be deleting whole columns or whole rows, and not the whole thing. - if (whole_columns_selected == whole_rows_selected) - return; + if (whole_columns_selected == whole_rows_selected) + return; - if (whole_rows_selected) - mod->removeRows (coords[0], coords[1] - coords[0]); + if (whole_rows_selected) + mod->removeRows (coords[0], coords[1] - coords[0]); - if (whole_columns_selected) - mod->removeColumns (coords[2], coords[3] - coords[2]); -} + if (whole_columns_selected) + mod->removeColumns (coords[2], coords[3] - coords[2]); + } -void -variable_editor_view::clearContent (void) -{ - if (! hasFocus ()) - return; + void + variable_editor_view::clearContent (void) + { + if (! hasFocus ()) + return; - if (m_var_model == nullptr) - return; + if (m_var_model == nullptr) + return; - QItemSelectionModel *sel = selectionModel (); - QList indices = sel->selectedIndexes (); + QItemSelectionModel *sel = selectionModel (); + QList indices = sel->selectedIndexes (); - // FIXME: Use [] for empty cells? + // FIXME: Use [] for empty cells? - for (const auto& idx : indices) - m_var_model->clear_content (idx); -} + for (const auto& idx : indices) + m_var_model->clear_content (idx); + } -void -variable_editor_view::cutClipboard (void) -{ - copyClipboard (); + void + variable_editor_view::cutClipboard (void) + { + copyClipboard (); - clearContent (); -} + clearContent (); + } -void -variable_editor_view::copyClipboard (void) -{ - if (! hasFocus ()) - return; + void + variable_editor_view::copyClipboard (void) + { + if (! hasFocus ()) + return; - QItemSelectionModel *sel = selectionModel (); - QList indices = sel->selectedIndexes (); - std::sort (indices.begin (), indices.end ()); + QItemSelectionModel *sel = selectionModel (); + QList indices = sel->selectedIndexes (); + std::sort (indices.begin (), indices.end ()); - if (indices.isEmpty ()) - return; + if (indices.isEmpty ()) + return; - // Convert selected items into TSV format and copy that. - // Spreadsheet tools should understand that. + // Convert selected items into TSV format and copy that. + // Spreadsheet tools should understand that. - QAbstractItemModel *mod = model (); - QModelIndex previous = indices.first (); - QString copy = mod->data (previous).toString (); - indices.removeFirst (); - for (auto idx : indices) - { - copy.push_back (previous.row () != idx.row () ? '\n' : '\t'); - copy.append (mod->data (idx).toString ()); - previous = idx; - } + QAbstractItemModel *mod = model (); + QModelIndex previous = indices.first (); + QString copy = mod->data (previous).toString (); + indices.removeFirst (); + for (auto idx : indices) + { + copy.push_back (previous.row () != idx.row () ? '\n' : '\t'); + copy.append (mod->data (idx).toString ()); + previous = idx; + } - QClipboard *clipboard = QApplication::clipboard (); - clipboard->setText (copy); -} + QClipboard *clipboard = QApplication::clipboard (); + clipboard->setText (copy); + } -void -variable_editor_view::pasteClipboard (void) -{ - if (! hasFocus ()) - return; + void + variable_editor_view::pasteClipboard (void) + { + if (! hasFocus ()) + return; - QAbstractItemModel *mod = model (); - QItemSelectionModel *sel = selectionModel (); - QList indices = sel->selectedIndexes (); + QAbstractItemModel *mod = model (); + QItemSelectionModel *sel = selectionModel (); + QList indices = sel->selectedIndexes (); - QClipboard *clipboard = QApplication::clipboard (); - QString text = clipboard->text (); + QClipboard *clipboard = QApplication::clipboard (); + QString text = clipboard->text (); - QPoint start, end; + QPoint start, end; - QPoint tabsize = QPoint (mod->rowCount (), mod->columnCount ()); + QPoint tabsize = QPoint (mod->rowCount (), mod->columnCount ()); - if (indices.isEmpty ()) - { - start = QPoint (0, 0); - end = tabsize; - } - else if (indices.size () == 1) - { - start = QPoint (indices[0].row (), indices[0].column ()); - end = tabsize; - } - else - { - end = QPoint (0, 0); - start = tabsize; + if (indices.isEmpty ()) + { + start = QPoint (0, 0); + end = tabsize; + } + else if (indices.size () == 1) + { + start = QPoint (indices[0].row (), indices[0].column ()); + end = tabsize; + } + else + { + end = QPoint (0, 0); + start = tabsize; - for (int i = 0; i < indices.size (); i++) - { - if (indices[i].column () < start.y ()) - start.setY (indices[i].column ()); + for (int i = 0; i < indices.size (); i++) + { + if (indices[i].column () < start.y ()) + start.setY (indices[i].column ()); - if (indices[i].column () > end.y ()) - end.setY (indices[i].column ()); + if (indices[i].column () > end.y ()) + end.setY (indices[i].column ()); - if (indices[i].row () < start.x ()) - start.setX (indices[i].column ()); + if (indices[i].row () < start.x ()) + start.setX (indices[i].column ()); - if (indices[i].row () > end.x ()) - end.setX (indices[i].column ()); - } - } + if (indices[i].row () > end.x ()) + end.setX (indices[i].column ()); + } + } - int rownum = 0; - int colnum = 0; + int rownum = 0; + int colnum = 0; - QStringList rows = text.split ('\n'); - for (const auto& row : rows) - { - if (rownum > end.x () - start.x ()) - continue; + QStringList rows = text.split ('\n'); + for (const auto& row : rows) + { + if (rownum > end.x () - start.x ()) + continue; - QStringList cols = row.split ('\t'); - if (cols.isEmpty ()) - continue; + QStringList cols = row.split ('\t'); + if (cols.isEmpty ()) + continue; - for (const auto& col : cols) - { - if (col.isEmpty ()) - continue; - if (colnum > end.y () - start.y () ) - continue; + for (const auto& col : cols) + { + if (col.isEmpty ()) + continue; + if (colnum > end.y () - start.y () ) + continue; - mod->setData (mod->index (rownum + start.x (), - colnum + start.y ()), - QVariant (col)); + mod->setData (mod->index (rownum + start.x (), + colnum + start.y ()), + QVariant (col)); - colnum++; - } + colnum++; + } - colnum = 0; - rownum++; - } -} + colnum = 0; + rownum++; + } + } -void -variable_editor_view::handle_horizontal_scroll_action (int action) -{ - if (action == QAbstractSlider::SliderSingleStepAdd - || action == QAbstractSlider::SliderPageStepAdd - || action == QAbstractSlider::SliderToMaximum - || action == QAbstractSlider::SliderMove) - { - if (m_var_model != nullptr) - { - QScrollBar *sb = horizontalScrollBar (); + void + variable_editor_view::handle_horizontal_scroll_action (int action) + { + if (action == QAbstractSlider::SliderSingleStepAdd + || action == QAbstractSlider::SliderPageStepAdd + || action == QAbstractSlider::SliderToMaximum + || action == QAbstractSlider::SliderMove) + { + if (m_var_model != nullptr) + { + QScrollBar *sb = horizontalScrollBar (); - if (sb && sb->value () == sb->maximum ()) - { - int new_cols = m_var_model->display_columns () + 16; + if (sb && sb->value () == sb->maximum ()) + { + int new_cols = m_var_model->display_columns () + 16; - m_var_model->maybe_resize_columns (new_cols); - } - } - } -} + m_var_model->maybe_resize_columns (new_cols); + } + } + } + } -void -variable_editor_view::handle_vertical_scroll_action (int action) -{ - if (action == QAbstractSlider::SliderSingleStepAdd - || action == QAbstractSlider::SliderPageStepAdd - || action == QAbstractSlider::SliderToMaximum - || action == QAbstractSlider::SliderMove) - { - if (m_var_model != nullptr) - { - QScrollBar *sb = verticalScrollBar (); + void + variable_editor_view::handle_vertical_scroll_action (int action) + { + if (action == QAbstractSlider::SliderSingleStepAdd + || action == QAbstractSlider::SliderPageStepAdd + || action == QAbstractSlider::SliderToMaximum + || action == QAbstractSlider::SliderMove) + { + if (m_var_model != nullptr) + { + QScrollBar *sb = verticalScrollBar (); - if (sb && sb->value () == sb->maximum ()) - { - int new_rows = m_var_model->display_rows () + 16; + if (sb && sb->value () == sb->maximum ()) + { + int new_rows = m_var_model->display_rows () + 16; - m_var_model->maybe_resize_rows (new_rows); - } - } - } -} + m_var_model->maybe_resize_rows (new_rows); + } + } + } + } -// Gadgets for focus restoration + // Gadgets for focus restoration -HoverToolButton::HoverToolButton (QWidget *parent) - : QToolButton (parent) -{ - installEventFilter (this); -} + HoverToolButton::HoverToolButton (QWidget *parent) + : QToolButton (parent) + { + installEventFilter (this); + } -bool HoverToolButton::eventFilter (QObject *obj, QEvent *ev) -{ - if (ev->type () == QEvent::HoverEnter) - emit hovered_signal (); - else if (ev->type () == QEvent::MouseButtonPress) - emit popup_shown_signal (); + bool HoverToolButton::eventFilter (QObject *obj, QEvent *ev) + { + if (ev->type () == QEvent::HoverEnter) + emit hovered_signal (); + else if (ev->type () == QEvent::MouseButtonPress) + emit popup_shown_signal (); - return QToolButton::eventFilter (obj, ev); -} + return QToolButton::eventFilter (obj, ev); + } -ReturnFocusToolButton::ReturnFocusToolButton (QWidget *parent) - : HoverToolButton (parent) -{ - installEventFilter (this); -} + ReturnFocusToolButton::ReturnFocusToolButton (QWidget *parent) + : HoverToolButton (parent) + { + installEventFilter (this); + } -bool ReturnFocusToolButton::eventFilter (QObject *obj, QEvent *ev) -{ + bool ReturnFocusToolButton::eventFilter (QObject *obj, QEvent *ev) + { - if (ev->type () == QEvent::MouseButtonRelease && isDown ()) - { - emit about_to_activate (); + if (ev->type () == QEvent::MouseButtonRelease && isDown ()) + { + emit about_to_activate (); - setDown (false); - QAction *action = defaultAction (); - if (action != nullptr) - action->activate (QAction::Trigger); + setDown (false); + QAction *action = defaultAction (); + if (action != nullptr) + action->activate (QAction::Trigger); - return true; - } + return true; + } - return HoverToolButton::eventFilter (obj, ev); -} + return HoverToolButton::eventFilter (obj, ev); + } -ReturnFocusMenu::ReturnFocusMenu (QWidget *parent) - : QMenu (parent) -{ - installEventFilter (this); -} + ReturnFocusMenu::ReturnFocusMenu (QWidget *parent) + : QMenu (parent) + { + installEventFilter (this); + } -bool ReturnFocusMenu::eventFilter (QObject *obj, QEvent *ev) -{ - if (ev->type () == QEvent::MouseButtonRelease && underMouse ()) - { - emit about_to_activate (); - } + bool ReturnFocusMenu::eventFilter (QObject *obj, QEvent *ev) + { + if (ev->type () == QEvent::MouseButtonRelease && underMouse ()) + { + emit about_to_activate (); + } - return QMenu::eventFilter (obj, ev); -} + return QMenu::eventFilter (obj, ev); + } -// Variable editor. + // Variable editor. -variable_editor::variable_editor (QWidget *p, base_qobject& oct_qobj) - : octave_dock_widget ("VariableEditor", p, oct_qobj), - m_main (new dw_main_window (oct_qobj)), - m_tool_bar (new QToolBar (m_main)), - m_default_width (30), - m_default_height (100), - m_add_font_height (0), - m_use_terminal_font (true), - m_alternate_rows (true), - m_stylesheet (""), - m_font (), - m_sel_font (), - m_table_colors (), - m_current_focus_vname (""), - m_hovered_focus_vname (""), - m_plot_mapper (nullptr), - m_focus_widget (nullptr), - m_focus_widget_vdw (nullptr) -{ - set_title (tr ("Variable Editor")); - setStatusTip (tr ("Edit variables.")); - setAttribute (Qt::WA_AlwaysShowToolTips); + variable_editor::variable_editor (QWidget *p, base_qobject& oct_qobj) + : octave_dock_widget ("VariableEditor", p, oct_qobj), + m_main (new dw_main_window (oct_qobj)), + m_tool_bar (new QToolBar (m_main)), + m_default_width (30), + m_default_height (100), + m_add_font_height (0), + m_use_terminal_font (true), + m_alternate_rows (true), + m_stylesheet (""), + m_font (), + m_sel_font (), + m_table_colors (), + m_current_focus_vname (""), + m_hovered_focus_vname (""), + m_plot_mapper (nullptr), + m_focus_widget (nullptr), + m_focus_widget_vdw (nullptr) + { + set_title (tr ("Variable Editor")); + setStatusTip (tr ("Edit variables.")); + setAttribute (Qt::WA_AlwaysShowToolTips); - m_main->setParent (this); - // See Octave bug #53409 and https://bugreports.qt.io/browse/QTBUG-55357 + m_main->setParent (this); +// See Octave bug #53409 and https://bugreports.qt.io/browse/QTBUG-55357 #if (QT_VERSION < 0x050601) || (QT_VERSION >= 0x050701) - m_main->setDockOptions (QMainWindow::AnimatedDocks | - QMainWindow::AllowNestedDocks | - QMainWindow::VerticalTabs); + m_main->setDockOptions (QMainWindow::AnimatedDocks | + QMainWindow::AllowNestedDocks | + QMainWindow::VerticalTabs); #else - m_main->setDockNestingEnabled (true); + m_main->setDockNestingEnabled (true); #endif - // Tool Bar. + // Tool Bar. - construct_tool_bar (); - m_main->addToolBar (m_tool_bar); + construct_tool_bar (); + m_main->addToolBar (m_tool_bar); - // Colors. + // Colors. - for (int i = 0; i < ve_colors_count; i++) - m_table_colors.append (QColor (Qt::white)); + for (int i = 0; i < ve_colors_count; i++) + m_table_colors.append (QColor (Qt::white)); - // Use an MDI area that is shrunk to nothing as the central widget. - // Future feature might be to switch to MDI mode in which the dock - // area is shrunk to nothing and the widgets live in the MDI window. + // Use an MDI area that is shrunk to nothing as the central widget. + // Future feature might be to switch to MDI mode in which the dock + // area is shrunk to nothing and the widgets live in the MDI window. - QMdiArea *central_mdiarea = new QMdiArea (m_main); - central_mdiarea->setMinimumSize (QSize (0, 0)); - central_mdiarea->setMaximumSize (QSize (0, 0)); - central_mdiarea->resize (QSize (0, 0)); - m_main->setCentralWidget (central_mdiarea); + QMdiArea *central_mdiarea = new QMdiArea (m_main); + central_mdiarea->setMinimumSize (QSize (0, 0)); + central_mdiarea->setMaximumSize (QSize (0, 0)); + central_mdiarea->resize (QSize (0, 0)); + m_main->setCentralWidget (central_mdiarea); - setWidget (m_main); + setWidget (m_main); - if (! p) - make_window (); -} + if (! p) + make_window (); + } -void variable_editor::focusInEvent (QFocusEvent *ev) -{ - octave_dock_widget::focusInEvent (ev); + void variable_editor::focusInEvent (QFocusEvent *ev) + { + octave_dock_widget::focusInEvent (ev); - // set focus to the current variable or most recent if still valid - if (m_focus_widget != nullptr) - { - // Activating a floating window causes problems. - if (! m_focus_widget_vdw->isFloating ()) - activateWindow (); - m_focus_widget->setFocus (); - } - else - { - QWidget *fw = m_main->focusWidget (); - if (fw != nullptr) - { + // set focus to the current variable or most recent if still valid + if (m_focus_widget != nullptr) + { + // Activating a floating window causes problems. + if (! m_focus_widget_vdw->isFloating ()) activateWindow (); - fw->setFocus (); - } - else - { - QDockWidget *any_qdw = m_main->findChild (); - if (any_qdw != nullptr) - { - activateWindow (); - any_qdw->setFocus (); - } - else - setFocus(); - } - } -} + m_focus_widget->setFocus (); + } + else + { + QWidget *fw = m_main->focusWidget (); + if (fw != nullptr) + { + activateWindow (); + fw->setFocus (); + } + else + { + QDockWidget *any_qdw = m_main->findChild (); + if (any_qdw != nullptr) + { + activateWindow (); + any_qdw->setFocus (); + } + else + setFocus(); + } + } + } -variable_editor::~variable_editor (void) -{ - // FIXME: Maybe toolbar actions could be handled with signals and - // slots so that deleting the toolbar here would disconnect all - // toolbar actions and any other slots that might try to access the - // toolbar would work properly (I'm looking at you, - // handle_focus_change). + variable_editor::~variable_editor (void) + { + // FIXME: Maybe toolbar actions could be handled with signals and + // slots so that deleting the toolbar here would disconnect all + // toolbar actions and any other slots that might try to access the + // toolbar would work properly (I'm looking at you, + // handle_focus_change). - delete m_tool_bar; - m_tool_bar = nullptr; -} - -void -variable_editor::edit_variable (const QString& name, const octave_value& val) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + delete m_tool_bar; + m_tool_bar = nullptr; + } - if (m_stylesheet.isEmpty ()) - { - gui_settings *settings = rmgr.get_settings (); - notice_settings (settings); - } + void + variable_editor::edit_variable (const QString& name, const octave_value& val) + { + if (m_stylesheet.isEmpty ()) + notice_settings (); - QDockWidget *existing_qdw = m_main->findChild (name); - if (existing_qdw) - { - // Already open. + QDockWidget *existing_qdw = m_main->findChild (name); + if (existing_qdw) + { + // Already open. - // Put current focused variable out of focus - if (m_main->focusWidget () != nullptr) - { - QFocusEvent event (QEvent::FocusOut, Qt::OtherFocusReason); - QApplication::sendEvent (m_main->focusWidget (), &event); - } + // Put current focused variable out of focus + if (m_main->focusWidget () != nullptr) + { + QFocusEvent event (QEvent::FocusOut, Qt::OtherFocusReason); + QApplication::sendEvent (m_main->focusWidget (), &event); + } - // Put existing variable in focus and raise - m_main->parentWidget ()->show (); - existing_qdw->show (); - existing_qdw->raise (); - existing_qdw->activateWindow (); - tab_to_front (); - existing_qdw->setFocus (); + // Put existing variable in focus and raise + m_main->parentWidget ()->show (); + existing_qdw->show (); + existing_qdw->raise (); + existing_qdw->activateWindow (); + tab_to_front (); + existing_qdw->setFocus (); - return; - } + return; + } - variable_dock_widget *page - = new variable_dock_widget (this, m_octave_qobj); + variable_dock_widget *page + = new variable_dock_widget (this, m_octave_qobj); - page->setObjectName (name); - m_main->addDockWidget (Qt::LeftDockWidgetArea, page); + page->setObjectName (name); + m_main->addDockWidget (Qt::LeftDockWidgetArea, page); - // The old-style signal/slot connection appears to be needed here to - // prevent a crash when closing a variable_dock_widget object. - connect (qApp, SIGNAL (focusChanged (QWidget *, QWidget *)), - page, SLOT (handle_focus_change (QWidget *, QWidget *))); + // The old-style signal/slot connection appears to be needed here to + // prevent a crash when closing a variable_dock_widget object. + connect (qApp, SIGNAL (focusChanged (QWidget *, QWidget *)), + page, SLOT (handle_focus_change (QWidget *, QWidget *))); - connect (this, &variable_editor::visibilityChanged, - page, &variable_dock_widget::setVisible); + connect (this, &variable_editor::visibilityChanged, + page, &variable_dock_widget::setVisible); - // Notify the variable editor for page actions. - connect (page, &variable_dock_widget::destroyed, - this, &variable_editor::variable_destroyed); - connect (page, &variable_dock_widget::variable_focused_signal, - this, &variable_editor::variable_focused); + // Notify the variable editor for page actions. + connect (page, &variable_dock_widget::destroyed, + this, &variable_editor::variable_destroyed); + connect (page, &variable_dock_widget::variable_focused_signal, + this, &variable_editor::variable_focused); - // See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813 + // See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813 #if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION) - connect (page, SIGNAL (queue_unfloat_float ()), - page, SLOT (unfloat_float ()), Qt::QueuedConnection); - connect (page, SIGNAL (queue_float ()), - page, SLOT (refloat ()), Qt::QueuedConnection); + connect (page, SIGNAL (queue_unfloat_float ()), + page, SLOT (unfloat_float ()), Qt::QueuedConnection); + connect (page, SIGNAL (queue_float ()), + page, SLOT (refloat ()), Qt::QueuedConnection); #endif - variable_editor_stack *stack - = new variable_editor_stack (page, m_octave_qobj); + variable_editor_stack *stack + = new variable_editor_stack (page, m_octave_qobj); - stack->setObjectName (name); - page->setWidget (stack); - page->setFocusProxy (stack); + stack->setObjectName (name); + page->setWidget (stack); + page->setFocusProxy (stack); - // Any interpreter_event signal from a variable_editor_stack object is - // handled the same as for the parent variable_editor object. - connect (stack, QOverload::of (&variable_editor_stack::interpreter_event), - this, QOverload::of (&variable_editor::interpreter_event)); + // Any interpreter_event signal from a variable_editor_stack object is + // handled the same as for the parent variable_editor object. + connect (stack, QOverload::of (&variable_editor_stack::interpreter_event), + this, QOverload::of (&variable_editor::interpreter_event)); - connect (stack, QOverload::of (&variable_editor_stack::interpreter_event), - this, QOverload::of (&variable_editor::interpreter_event)); + connect (stack, QOverload::of (&variable_editor_stack::interpreter_event), + this, QOverload::of (&variable_editor::interpreter_event)); - connect (stack, &variable_editor_stack::edit_variable_signal, - this, &variable_editor::edit_variable); - connect (this, &variable_editor::level_up_signal, - stack, &variable_editor_stack::levelUp); - connect (this, &variable_editor::save_signal, - stack, [=] () { stack->save (); }); + connect (stack, &variable_editor_stack::edit_variable_signal, + this, &variable_editor::edit_variable); + connect (this, &variable_editor::level_up_signal, + stack, &variable_editor_stack::levelUp); + connect (this, &variable_editor::save_signal, + stack, [=] () { stack->save (); }); - variable_editor_view *edit_view = stack->edit_view (); + variable_editor_view *edit_view = stack->edit_view (); - edit_view->setObjectName (name); - edit_view->setFont (m_font); - edit_view->setStyleSheet (m_stylesheet); - edit_view->setAlternatingRowColors (m_alternate_rows); - edit_view->verticalHeader ()->setDefaultSectionSize (m_default_height - + m_add_font_height); + edit_view->setObjectName (name); + edit_view->setFont (m_font); + edit_view->setStyleSheet (m_stylesheet); + edit_view->setAlternatingRowColors (m_alternate_rows); + edit_view->verticalHeader ()->setDefaultSectionSize (m_default_height + + m_add_font_height); - connect (m_plot_mapper, SIGNAL (mapped (const QString&)), - edit_view, SLOT (selected_command_requested (const QString&))); - connect (m_save_mapper, SIGNAL (mapped (const QString&)), - stack, SLOT (save (const QString&))); + connect (m_plot_mapper, SIGNAL (mapped (const QString&)), + edit_view, SLOT (selected_command_requested (const QString&))); + connect (m_save_mapper, SIGNAL (mapped (const QString&)), + stack, SLOT (save (const QString&))); - connect (edit_view, &variable_editor_view::command_signal, - this, &variable_editor::command_signal); - connect (this, &variable_editor::delete_selected_signal, - edit_view, &variable_editor_view::delete_selected); - connect (this, &variable_editor::clear_content_signal, - edit_view, &variable_editor_view::clearContent); - connect (this, &variable_editor::copy_clipboard_signal, - edit_view, &variable_editor_view::copyClipboard); - connect (this, &variable_editor::paste_clipboard_signal, - edit_view, &variable_editor_view::pasteClipboard); - connect (edit_view->horizontalHeader (), - &QHeaderView::customContextMenuRequested, - edit_view, &variable_editor_view::createColumnMenu); - connect (edit_view->verticalHeader (), - &QHeaderView::customContextMenuRequested, - edit_view, &variable_editor_view::createRowMenu); - connect (edit_view, &variable_editor_view::customContextMenuRequested, - edit_view, &variable_editor_view::createContextMenu); - connect (edit_view->horizontalScrollBar (), &QScrollBar::actionTriggered, - edit_view, &variable_editor_view::handle_horizontal_scroll_action); - connect (edit_view->verticalScrollBar (), &QScrollBar::actionTriggered, - edit_view, &variable_editor_view::handle_vertical_scroll_action); + connect (edit_view, &variable_editor_view::command_signal, + this, &variable_editor::command_signal); + connect (this, &variable_editor::delete_selected_signal, + edit_view, &variable_editor_view::delete_selected); + connect (this, &variable_editor::clear_content_signal, + edit_view, &variable_editor_view::clearContent); + connect (this, &variable_editor::copy_clipboard_signal, + edit_view, &variable_editor_view::copyClipboard); + connect (this, &variable_editor::paste_clipboard_signal, + edit_view, &variable_editor_view::pasteClipboard); + connect (edit_view->horizontalHeader (), + &QHeaderView::customContextMenuRequested, + edit_view, &variable_editor_view::createColumnMenu); + connect (edit_view->verticalHeader (), + &QHeaderView::customContextMenuRequested, + edit_view, &variable_editor_view::createRowMenu); + connect (edit_view, &variable_editor_view::customContextMenuRequested, + edit_view, &variable_editor_view::createContextMenu); + connect (edit_view->horizontalScrollBar (), &QScrollBar::actionTriggered, + edit_view, &variable_editor_view::handle_horizontal_scroll_action); + connect (edit_view->verticalScrollBar (), &QScrollBar::actionTriggered, + edit_view, &variable_editor_view::handle_vertical_scroll_action); - variable_editor_model *model = - new variable_editor_model (name, val, stack); + variable_editor_model *model = + new variable_editor_model (name, val, stack); - connect (model, &variable_editor_model::edit_variable_signal, - this, &variable_editor::edit_variable); - connect (model, &variable_editor_model::dataChanged, - this, &variable_editor::callUpdate); - connect (this, &variable_editor::refresh_signal, - model, &variable_editor_model::update_data_cache); - connect (model, &variable_editor_model::set_editable_signal, - stack, &variable_editor_stack::set_editable); + connect (model, &variable_editor_model::edit_variable_signal, + this, &variable_editor::edit_variable); + connect (model, &variable_editor_model::dataChanged, + this, &variable_editor::callUpdate); + connect (this, &variable_editor::refresh_signal, + model, &variable_editor_model::update_data_cache); + connect (model, &variable_editor_model::set_editable_signal, + stack, &variable_editor_stack::set_editable); - edit_view->setModel (model); - connect (edit_view, &variable_editor_view::doubleClicked, - model, &variable_editor_model::double_click); + edit_view->setModel (model); + connect (edit_view, &variable_editor_view::doubleClicked, + model, &variable_editor_model::double_click); - // Any interpreter_event signal from a variable_editor_model object is - // handled the same as for the parent variable_editor object. + // Any interpreter_event signal from a variable_editor_model object is + // handled the same as for the parent variable_editor object. - connect (model, QOverload::of (&variable_editor_model::interpreter_event), - this, QOverload::of (&variable_editor::interpreter_event)); + connect (model, QOverload::of (&variable_editor_model::interpreter_event), + this, QOverload::of (&variable_editor::interpreter_event)); - connect (model, QOverload::of (&variable_editor_model::interpreter_event), - this, QOverload::of (&variable_editor::interpreter_event)); + connect (model, QOverload::of (&variable_editor_model::interpreter_event), + this, QOverload::of (&variable_editor::interpreter_event)); - // Must supply a title for a QLabel to be created. Calling set_title() - // more than once will add more QLabels. Could change octave_dock_widget - // to always supply a QLabel (initially empty) and then simply update its - // contents. - page->set_title (name); - if (page->titleBarWidget () != nullptr) - { - QLabel *existing_ql = page->titleBarWidget ()->findChild (); + // Must supply a title for a QLabel to be created. Calling set_title() + // more than once will add more QLabels. Could change octave_dock_widget + // to always supply a QLabel (initially empty) and then simply update its + // contents. + page->set_title (name); + if (page->titleBarWidget () != nullptr) + { + QLabel *existing_ql = page->titleBarWidget ()->findChild (); - // FIXME: What was the intent here? update_label_signal does - // not seem to exist now. - connect (model, SIGNAL (description_changed (const QString&)), - existing_ql, SLOT (setText (const QString&))); - existing_ql->setMargin (2); - } + // FIXME: What was the intent here? update_label_signal does + // not seem to exist now. + connect (model, SIGNAL (description_changed (const QString&)), + existing_ql, SLOT (setText (const QString&))); + existing_ql->setMargin (2); + } - model->update_data (val); + model->update_data (val); - if (m_tool_bar) - { - QList viewlist = findChildren (); - if (viewlist.size () == 1 && m_tool_bar) - m_tool_bar->setEnabled (true); - } + if (m_tool_bar) + { + QList viewlist = findChildren (); + if (viewlist.size () == 1 && m_tool_bar) + m_tool_bar->setEnabled (true); + } - show (); - page->show (); - page->raise (); - page->activateWindow (); - tab_to_front (); - page->setFocus (); -} + show (); + page->show (); + page->raise (); + page->activateWindow (); + tab_to_front (); + page->setFocus (); + } -void -variable_editor::tab_to_front (void) -{ - QWidget *parent = parentWidget (); + void + variable_editor::tab_to_front (void) + { + QWidget *parent = parentWidget (); - if (parent) - { - QList barlist = parent->findChildren (); + if (parent) + { + QList barlist = parent->findChildren (); - QVariant this_value (reinterpret_cast (this)); + QVariant this_value (reinterpret_cast (this)); - for (auto *tbar : barlist) - { - for (int i = 0; i < tbar->count (); i++) - { - if (tbar->tabData (i) == this_value) - { - tbar->setCurrentIndex (i); - return; - } - } - } - } -} + for (auto *tbar : barlist) + { + for (int i = 0; i < tbar->count (); i++) + { + if (tbar->tabData (i) == this_value) + { + tbar->setCurrentIndex (i); + return; + } + } + } + } + } -void -variable_editor::refresh (void) -{ - emit refresh_signal (); -} + void + variable_editor::refresh (void) + { + emit refresh_signal (); + } -void -variable_editor::callUpdate (const QModelIndex&, const QModelIndex&) -{ - emit updated (); -} + void + variable_editor::callUpdate (const QModelIndex&, const QModelIndex&) + { + emit updated (); + } -void -variable_editor::notice_settings (const gui_settings *settings) -{ - m_main->notice_settings (settings); // update settings in parent main win + void + variable_editor::notice_settings (void) + { + gui_settings settings; - m_default_width = settings->value (ve_column_width).toInt (); + m_main->notice_settings (); // update settings in parent main win - m_default_height = settings->value (ve_row_height).toInt (); + m_default_width = settings.value (ve_column_width).toInt (); - m_alternate_rows = settings->value (ve_alternate_rows).toBool (); + m_default_height = settings.value (ve_row_height).toInt (); - m_use_terminal_font = settings->value (ve_use_terminal_font).toBool (); + m_alternate_rows = settings.value (ve_alternate_rows).toBool (); - QString font_name; - int font_size; - QString default_font = settings->value (global_mono_font).toString (); + m_use_terminal_font = settings.value (ve_use_terminal_font).toBool (); - if (m_use_terminal_font) - { - font_name = settings->value (cs_font.key, default_font).toString (); - font_size = settings->value (cs_font_size).toInt (); - } - else - { - font_name = settings->value (ve_font_name.key, default_font).toString (); - font_size = settings->value (ve_font_size).toInt (); - } + QString font_name; + int font_size; + QString default_font = settings.value (global_mono_font).toString (); - m_font = QFont (font_name, font_size); + if (m_use_terminal_font) + { + font_name = settings.value (cs_font.key, default_font).toString (); + font_size = settings.value (cs_font_size).toInt (); + } + else + { + font_name = settings.value (ve_font_name.key, default_font).toString (); + font_size = settings.value (ve_font_size).toInt (); + } - QFontMetrics fm (m_font); + m_font = QFont (font_name, font_size); - m_add_font_height = fm.height (); + QFontMetrics fm (m_font); + + m_add_font_height = fm.height (); - int mode = settings->value (ve_color_mode).toInt (); + int mode = settings.value (ve_color_mode).toInt (); - for (int i = 0; i < ve_colors_count; i++) - { - QColor setting_color = settings->color_value (ve_colors[i], mode); - m_table_colors.replace (i, setting_color); - } + for (int i = 0; i < ve_colors_count; i++) + { + QColor setting_color = settings.color_value (ve_colors[i], mode); + m_table_colors.replace (i, setting_color); + } - update_colors (); + update_colors (); - // Icon size in the toolbar. + // Icon size in the toolbar. - if (m_tool_bar) - { - int size_idx = settings->value (global_icon_size).toInt (); - size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2 + if (m_tool_bar) + { + int size_idx = settings.value (global_icon_size).toInt (); + size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2 - QStyle *st = style (); - int icon_size = st->pixelMetric (global_icon_sizes[size_idx]); - m_tool_bar->setIconSize (QSize (icon_size, icon_size)); - } + QStyle *st = style (); + int icon_size = st->pixelMetric (global_icon_sizes[size_idx]); + m_tool_bar->setIconSize (QSize (icon_size, icon_size)); + } - // Shortcuts (same as file editor) - shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); - scmgr.set_shortcut (m_save_action, sc_edit_file_save); -} + // Shortcuts (same as file editor) + shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); + scmgr.set_shortcut (m_save_action, sc_edit_file_save); + } -void -variable_editor::closeEvent (QCloseEvent *e) -{ - emit finished (); + void + variable_editor::closeEvent (QCloseEvent *e) + { + emit finished (); - octave_dock_widget::closeEvent (e); -} + octave_dock_widget::closeEvent (e); + } -void -variable_editor::variable_destroyed (QObject *obj) -{ - // Invalidate the focus-restoring widget pointer if currently active. - if (m_focus_widget_vdw == obj) - { - m_focus_widget = nullptr; - m_focus_widget_vdw = nullptr; - } + void + variable_editor::variable_destroyed (QObject *obj) + { + // Invalidate the focus-restoring widget pointer if currently active. + if (m_focus_widget_vdw == obj) + { + m_focus_widget = nullptr; + m_focus_widget_vdw = nullptr; + } - if (m_tool_bar) - { - // If no variable pages remain, deactivate the tool bar. - QList vdwlist = findChildren (); - if (vdwlist.isEmpty ()) - m_tool_bar->setEnabled (false); - } + if (m_tool_bar) + { + // If no variable pages remain, deactivate the tool bar. + QList vdwlist = findChildren (); + if (vdwlist.isEmpty ()) + m_tool_bar->setEnabled (false); + } - QFocusEvent ev (QEvent::FocusIn); - focusInEvent (&ev); -} + QFocusEvent ev (QEvent::FocusIn); + focusInEvent (&ev); + } -void -variable_editor::variable_focused (const QString& name) -{ - m_current_focus_vname = name; + void + variable_editor::variable_focused (const QString& name) + { + m_current_focus_vname = name; - // focusWidget() appears lost in transition to/from main window - // so keep a record of the widget. + // focusWidget() appears lost in transition to/from main window + // so keep a record of the widget. - QWidget *current = QApplication::focusWidget (); - m_focus_widget = nullptr; - m_focus_widget_vdw = nullptr; - if (current != nullptr) - { - QList vdwlist = findChildren (); - for (int i = 0; i < vdwlist.size (); i++) - { - variable_dock_widget *vdw = vdwlist.at (i); - if (vdw->isAncestorOf (current)) - { - m_focus_widget = current; - m_focus_widget_vdw = vdw; - break; - } - } - } -} + QWidget *current = QApplication::focusWidget (); + m_focus_widget = nullptr; + m_focus_widget_vdw = nullptr; + if (current != nullptr) + { + QList vdwlist = findChildren (); + for (int i = 0; i < vdwlist.size (); i++) + { + variable_dock_widget *vdw = vdwlist.at (i); + if (vdw->isAncestorOf (current)) + { + m_focus_widget = current; + m_focus_widget_vdw = vdw; + break; + } + } + } + } -void -variable_editor::record_hovered_focus_variable (void) -{ - m_hovered_focus_vname = m_current_focus_vname; -} + void + variable_editor::record_hovered_focus_variable (void) + { + m_hovered_focus_vname = m_current_focus_vname; + } -void -variable_editor::restore_hovered_focus_variable (void) -{ - variable_dock_widget *tofocus = findChild (m_hovered_focus_vname); - if (tofocus != nullptr) - { - // Note that this may be platform and window system dependent. - // On a particular Linux system, activateWindow() alone didn't - // immediately set the active window and there was a race - // between the window focus and action signal. Setting the - // active window via the QApplication route did work. - QApplication::setActiveWindow(tofocus->window()); - tofocus->activateWindow (); - tofocus->setFocus (Qt::OtherFocusReason); - } -} + void + variable_editor::restore_hovered_focus_variable (void) + { + variable_dock_widget *tofocus = findChild (m_hovered_focus_vname); + if (tofocus != nullptr) + { + // Note that this may be platform and window system dependent. + // On a particular Linux system, activateWindow() alone didn't + // immediately set the active window and there was a race + // between the window focus and action signal. Setting the + // active window via the QApplication route did work. + QApplication::setActiveWindow(tofocus->window()); + tofocus->activateWindow (); + tofocus->setFocus (Qt::OtherFocusReason); + } + } -void -variable_editor::save (void) -{ - emit save_signal (); -} + void + variable_editor::save (void) + { + emit save_signal (); + } -void -variable_editor::cutClipboard (void) -{ - copyClipboard (); + void + variable_editor::cutClipboard (void) + { + copyClipboard (); - emit clear_content_signal (); -} + emit clear_content_signal (); + } -void -variable_editor::copyClipboard (void) -{ - emit copy_clipboard_signal (); -} + void + variable_editor::copyClipboard (void) + { + emit copy_clipboard_signal (); + } -void -variable_editor::pasteClipboard (void) -{ - emit paste_clipboard_signal (); + void + variable_editor::pasteClipboard (void) + { + emit paste_clipboard_signal (); - emit updated (); -} + emit updated (); + } -void -variable_editor::levelUp (void) -{ - emit level_up_signal (); -} + void + variable_editor::levelUp (void) + { + emit level_up_signal (); + } -// Also updates the font. + // Also updates the font. -void variable_editor::update_colors (void) -{ - m_stylesheet = ""; + void variable_editor::update_colors (void) + { + m_stylesheet = ""; - if (m_table_colors.length () > 0) - m_stylesheet += "QTableView::item{ color: " - + m_table_colors[0].name () +" }"; + if (m_table_colors.length () > 0) + m_stylesheet += "QTableView::item{ color: " + + m_table_colors[0].name () +" }"; - if (m_table_colors.length () > 1) - m_stylesheet += "QTableView::item{ background-color: " - + m_table_colors[1].name () +" }"; + if (m_table_colors.length () > 1) + m_stylesheet += "QTableView::item{ background-color: " + + m_table_colors[1].name () +" }"; - if (m_table_colors.length () > 2) - m_stylesheet += "QTableView::item{ selection-color: " - + m_table_colors[2].name () +" }"; + if (m_table_colors.length () > 2) + m_stylesheet += "QTableView::item{ selection-color: " + + m_table_colors[2].name () +" }"; - if (m_table_colors.length () > 3) - m_stylesheet += "QTableView::item:selected{ background-color: " - + m_table_colors[3].name () +" }"; + if (m_table_colors.length () > 3) + m_stylesheet += "QTableView::item:selected{ background-color: " + + m_table_colors[3].name () +" }"; - if (m_table_colors.length () > 4 && m_alternate_rows) - { - m_stylesheet += "QTableView::item:alternate{ background-color: " - + m_table_colors[4].name () +" }"; + if (m_table_colors.length () > 4 && m_alternate_rows) + { + m_stylesheet += "QTableView::item:alternate{ background-color: " + + m_table_colors[4].name () +" }"; - m_stylesheet += "QTableView::item:alternate:selected{ background-color: " - + m_table_colors[3].name () +" }"; - } + m_stylesheet += "QTableView::item:alternate:selected{ background-color: " + + m_table_colors[3].name () +" }"; + } - QList viewlist = findChildren (); - for (int i = 0; i < viewlist.size (); i++) - { - QTableView *view = viewlist.at (i); + QList viewlist = findChildren (); + for (int i = 0; i < viewlist.size (); i++) + { + QTableView *view = viewlist.at (i); - if (! view) - continue; + if (! view) + continue; - view->setAlternatingRowColors (m_alternate_rows); - view->setStyleSheet (m_stylesheet); - view->setFont (m_font); - } + view->setAlternatingRowColors (m_alternate_rows); + view->setStyleSheet (m_stylesheet); + view->setFont (m_font); + } -} + } -QAction * -variable_editor::add_tool_bar_button (const QIcon& icon, - const QString& text, - const QObject *receiver, - const char *member) -{ - QAction *action = new QAction (icon, text, this); - connect(action, SIGNAL (triggered ()), receiver, member); - QToolButton *button = new ReturnFocusToolButton (m_tool_bar); - button->setDefaultAction (action); - button->setText (text); - button->setToolTip (text); - button->setIcon (icon); - m_tool_bar->addWidget (button); + QAction * + variable_editor::add_tool_bar_button (const QIcon& icon, + const QString& text, + const QObject *receiver, + const char *member) + { + QAction *action = new QAction (icon, text, this); + connect(action, SIGNAL (triggered ()), receiver, member); + QToolButton *button = new ReturnFocusToolButton (m_tool_bar); + button->setDefaultAction (action); + button->setText (text); + button->setToolTip (text); + button->setIcon (icon); + m_tool_bar->addWidget (button); - return action; -} + return action; + } -void -variable_editor::construct_tool_bar (void) -{ - m_tool_bar->setAllowedAreas (Qt::TopToolBarArea); + void + variable_editor::construct_tool_bar (void) + { + m_tool_bar->setAllowedAreas (Qt::TopToolBarArea); - m_tool_bar->setObjectName ("VariableEditorToolBar"); + m_tool_bar->setObjectName ("VariableEditorToolBar"); - m_tool_bar->setWindowTitle (tr ("Variable Editor Toolbar")); + m_tool_bar->setWindowTitle (tr ("Variable Editor Toolbar")); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; - m_save_action = add_tool_bar_button (rmgr.icon ("document-save"), tr ("Save"), - this, SLOT (save ())); - addAction (m_save_action); - m_save_action->setShortcutContext (Qt::WidgetWithChildrenShortcut); - m_save_action->setStatusTip(tr("Save variable to a file")); + m_save_action = add_tool_bar_button (settings.icon ("document-save"), + tr ("Save"), this, SLOT (save ())); + addAction (m_save_action); + m_save_action->setShortcutContext (Qt::WidgetWithChildrenShortcut); + m_save_action->setStatusTip(tr("Save variable to a file")); - QAction *action = new QAction (rmgr.icon ("document-save-as"), tr ("Save in format ..."), m_tool_bar); + QAction *action = new QAction (settings.icon ("document-save-as"), + tr ("Save in format ..."), m_tool_bar); - QToolButton *save_tool_button = new HoverToolButton (m_tool_bar); - save_tool_button->setDefaultAction (action); + QToolButton *save_tool_button = new HoverToolButton (m_tool_bar); + save_tool_button->setDefaultAction (action); - save_tool_button->setText (tr ("Save in format ...")); - save_tool_button->setToolTip (tr("Save variable to a file in different format")); - save_tool_button->setIcon (rmgr.icon ("document-save-as")); - save_tool_button->setPopupMode (QToolButton::InstantPopup); + save_tool_button->setText (tr ("Save in format ...")); + save_tool_button->setToolTip (tr("Save variable to a file in different format")); + save_tool_button->setIcon (settings.icon ("document-save-as")); + save_tool_button->setPopupMode (QToolButton::InstantPopup); - QMenu *save_menu = new ReturnFocusMenu (save_tool_button); - save_menu->setTitle (tr ("Save in format ...")); - save_menu->setSeparatorsCollapsible (false); + QMenu *save_menu = new ReturnFocusMenu (save_tool_button); + save_menu->setTitle (tr ("Save in format ...")); + save_menu->setSeparatorsCollapsible (false); - m_save_mapper = new QSignalMapper (save_menu); - for (int i = 0; i < ve_save_formats.length (); i++) - m_save_mapper->setMapping - (save_menu->addAction (ve_save_formats.at (i), - m_save_mapper, SLOT (map ())), - ve_save_formats.at (i)); + m_save_mapper = new QSignalMapper (save_menu); + for (int i = 0; i < ve_save_formats.length (); i++) + m_save_mapper->setMapping + (save_menu->addAction (ve_save_formats.at (i), + m_save_mapper, SLOT (map ())), + ve_save_formats.at (i)); - save_tool_button->setMenu (save_menu); - m_tool_bar->addWidget (save_tool_button); + save_tool_button->setMenu (save_menu); + m_tool_bar->addWidget (save_tool_button); - m_tool_bar->addSeparator (); + m_tool_bar->addSeparator (); - action = add_tool_bar_button (rmgr.icon ("edit-cut"), tr ("Cut"), - this, SLOT (cutClipboard ())); - action->setStatusTip(tr("Cut data to clipboard")); + action = add_tool_bar_button (settings.icon ("edit-cut"), tr ("Cut"), + this, SLOT (cutClipboard ())); + action->setStatusTip(tr("Cut data to clipboard")); - action = add_tool_bar_button (rmgr.icon ("edit-copy"), tr ("Copy"), - this, SLOT (copyClipboard ())); - action->setStatusTip(tr("Copy data to clipboard")); + action = add_tool_bar_button (settings.icon ("edit-copy"), tr ("Copy"), + this, SLOT (copyClipboard ())); + action->setStatusTip(tr("Copy data to clipboard")); - action = add_tool_bar_button (rmgr.icon ("edit-paste"), tr ("Paste"), - this, SLOT (pasteClipboard ())); - action->setStatusTip(tr("Paste clipboard into variable data")); + action = add_tool_bar_button (settings.icon ("edit-paste"), tr ("Paste"), + this, SLOT (pasteClipboard ())); + action->setStatusTip(tr("Paste clipboard into variable data")); - m_tool_bar->addSeparator (); + m_tool_bar->addSeparator (); - // FIXME: Add a print item? - // QAction *print_action; /icons/fileprint.png - // m_tool_bar->addSeparator (); + // FIXME: Add a print item? + // QAction *print_action; /icons/fileprint.png + // m_tool_bar->addSeparator (); - action = new QAction (rmgr.icon ("plot-xy-curve"), tr ("Plot"), m_tool_bar); - action->setToolTip (tr ("Plot Selected Data")); - QToolButton *plot_tool_button = new HoverToolButton (m_tool_bar); - plot_tool_button->setDefaultAction (action); + action = new QAction (settings.icon ("plot-xy-curve"), tr ("Plot"), + m_tool_bar); + action->setToolTip (tr ("Plot Selected Data")); + QToolButton *plot_tool_button = new HoverToolButton (m_tool_bar); + plot_tool_button->setDefaultAction (action); - plot_tool_button->setText (tr ("Plot")); - plot_tool_button->setToolTip (tr ("Plot selected data")); - plot_tool_button->setIcon (rmgr.icon ("plot-xy-curve")); + plot_tool_button->setText (tr ("Plot")); + plot_tool_button->setToolTip (tr ("Plot selected data")); + plot_tool_button->setIcon (settings.icon ("plot-xy-curve")); - plot_tool_button->setPopupMode (QToolButton::InstantPopup); + plot_tool_button->setPopupMode (QToolButton::InstantPopup); - QMenu *plot_menu = new ReturnFocusMenu (plot_tool_button); - plot_menu->setTitle (tr ("Plot")); - plot_menu->setSeparatorsCollapsible (false); + QMenu *plot_menu = new ReturnFocusMenu (plot_tool_button); + plot_menu->setTitle (tr ("Plot")); + plot_menu->setSeparatorsCollapsible (false); - m_plot_mapper = make_plot_mapper (plot_menu); + m_plot_mapper = make_plot_mapper (plot_menu); - plot_tool_button->setMenu (plot_menu); + plot_tool_button->setMenu (plot_menu); - m_tool_bar->addWidget (plot_tool_button); + m_tool_bar->addWidget (plot_tool_button); - m_tool_bar->addSeparator (); + m_tool_bar->addSeparator (); - action = add_tool_bar_button (rmgr.icon ("go-up"), tr ("Up"), this, - SLOT (levelUp ())); - action->setStatusTip(tr("Go one level up in variable hierarchy")); + action = add_tool_bar_button (settings.icon ("go-up"), tr ("Up"), this, + SLOT (levelUp ())); + action->setStatusTip(tr("Go one level up in variable hierarchy")); - // The QToolButton mouse-clicks change active window, so connect all - // HoverToolButton and ReturnFocusToolButton objects to the mechanism - // that restores active window and focus before acting. - QList hbuttonlist - = m_tool_bar->findChildren ("" - , Qt::FindDirectChildrenOnly - ); - for (int i = 0; i < hbuttonlist.size (); i++) - { - connect (hbuttonlist.at (i), &HoverToolButton::hovered_signal, - this, &variable_editor::record_hovered_focus_variable); - connect (hbuttonlist.at (i), &HoverToolButton::popup_shown_signal, - this, &variable_editor::restore_hovered_focus_variable); - } + // The QToolButton mouse-clicks change active window, so connect all + // HoverToolButton and ReturnFocusToolButton objects to the mechanism + // that restores active window and focus before acting. + QList hbuttonlist + = m_tool_bar->findChildren ("" + , Qt::FindDirectChildrenOnly + ); + for (int i = 0; i < hbuttonlist.size (); i++) + { + connect (hbuttonlist.at (i), &HoverToolButton::hovered_signal, + this, &variable_editor::record_hovered_focus_variable); + connect (hbuttonlist.at (i), &HoverToolButton::popup_shown_signal, + this, &variable_editor::restore_hovered_focus_variable); + } - QList rfbuttonlist - = m_tool_bar->findChildren ("" - , Qt::FindDirectChildrenOnly - ); - for (int i = 0; i < rfbuttonlist.size (); i++) - { - connect (rfbuttonlist.at (i), &ReturnFocusToolButton::about_to_activate, - this, &variable_editor::restore_hovered_focus_variable); - } + QList rfbuttonlist + = m_tool_bar->findChildren ("" + , Qt::FindDirectChildrenOnly + ); + for (int i = 0; i < rfbuttonlist.size (); i++) + { + connect (rfbuttonlist.at (i), &ReturnFocusToolButton::about_to_activate, + this, &variable_editor::restore_hovered_focus_variable); + } - // Same for QMenu - QList menulist - = m_tool_bar->findChildren (); - for (int i = 0; i < menulist.size (); i++) - { - connect (menulist.at (i), &ReturnFocusMenu::about_to_activate, - this, &variable_editor::restore_hovered_focus_variable); - } + // Same for QMenu + QList menulist + = m_tool_bar->findChildren (); + for (int i = 0; i < menulist.size (); i++) + { + connect (menulist.at (i), &ReturnFocusMenu::about_to_activate, + this, &variable_editor::restore_hovered_focus_variable); + } - m_tool_bar->setAttribute(Qt::WA_ShowWithoutActivating); - m_tool_bar->setFocusPolicy (Qt::NoFocus); + m_tool_bar->setAttribute(Qt::WA_ShowWithoutActivating); + m_tool_bar->setFocusPolicy (Qt::NoFocus); - // Disabled when no tab is present. + // Disabled when no tab is present. - m_tool_bar->setEnabled (false); -} + m_tool_bar->setEnabled (false); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/variable-editor.h --- a/libgui/src/variable-editor.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/variable-editor.h Tue Dec 06 15:45:27 2022 -0500 @@ -32,7 +32,6 @@ #include #include "dw-main-window.h" -#include "gui-settings.h" #include "octave-dock-widget.h" #include "qt-interpreter-events.h" #include "tab-bar.h" @@ -45,375 +44,375 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; + class base_qobject; -class variable_editor_model; -class variable_editor_view; + class variable_editor_model; + class variable_editor_view; -// The individual variable subwindow class + // The individual variable subwindow class -class variable_dock_widget : public label_dock_widget -{ - Q_OBJECT + class variable_dock_widget : public label_dock_widget + { + Q_OBJECT -public: + public: - variable_dock_widget (QWidget *p, base_qobject& oct_qobj); + variable_dock_widget (QWidget *p, base_qobject& oct_qobj); - ~variable_dock_widget (void) = default; + ~variable_dock_widget (void) = default; -signals: + signals: - void variable_focused_signal (const QString& name); + void variable_focused_signal (const QString& name); -protected: + protected: - virtual void closeEvent (QCloseEvent *e); + virtual void closeEvent (QCloseEvent *e); - void resizeEvent (QResizeEvent *event); + void resizeEvent (QResizeEvent *event); -public slots: + public slots: - void handle_focus_change (QWidget *old, QWidget *now); + void handle_focus_change (QWidget *old, QWidget *now); -private slots: + private slots: - void change_floating (bool); + void change_floating (bool); - void change_existence (bool); + void change_existence (bool); - void toplevel_change (bool); + void toplevel_change (bool); - void change_fullscreen (void); + void change_fullscreen (void); -protected: + protected: - QFrame *m_frame; + QFrame *m_frame; - QAction *m_fullscreen_action; + QAction *m_fullscreen_action; - bool m_full_screen; + bool m_full_screen; - bool m_prev_floating; + bool m_prev_floating; - QRect m_prev_geom; + QRect m_prev_geom; - // See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813 +// See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813 #define QTBUG_44813_FIX_VERSION 0x999999 -signals: + signals: - void queue_unfloat_float (void); + void queue_unfloat_float (void); - void queue_float (void); + void queue_float (void); -protected slots: + protected slots: - void unfloat_float (void); + void unfloat_float (void); - void refloat (void); + void refloat (void); #if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION) -protected: + protected: - bool event (QEvent *event); + bool event (QEvent *event); -private: + private: - bool m_waiting_for_mouse_move; + bool m_waiting_for_mouse_move; - bool m_waiting_for_mouse_button_release; + bool m_waiting_for_mouse_button_release; #endif -}; + }; -class variable_editor_stack : public QStackedWidget -{ - Q_OBJECT + class variable_editor_stack : public QStackedWidget + { + Q_OBJECT -public: + public: - variable_editor_stack (QWidget *p, base_qobject& oct_qobj); + variable_editor_stack (QWidget *p, base_qobject& oct_qobj); - ~variable_editor_stack (void) = default; + ~variable_editor_stack (void) = default; - variable_editor_view * edit_view (void) {return m_edit_view;}; + variable_editor_view * edit_view (void) {return m_edit_view;}; - QTextEdit * disp_view (void) {return m_disp_view;}; + QTextEdit * disp_view (void) {return m_disp_view;}; -signals: + signals: - void edit_variable_signal (const QString& name, const octave_value& val); + void edit_variable_signal (const QString& name, const octave_value& val); - void do_save_signal (const QString& format, const QString& save_opts); + void do_save_signal (const QString& format, const QString& save_opts); - void interpreter_event (const fcn_callback& fcn); - void interpreter_event (const meth_callback& meth); + void interpreter_event (const fcn_callback& fcn); + void interpreter_event (const meth_callback& meth); -public slots: + public slots: - void set_editable (bool editable); + void set_editable (bool editable); - void levelUp (void); + void levelUp (void); - void save (const QString& format = QString ()); + void save (const QString& format = QString ()); - void do_save (const QString& format, const QString& save_opts); + void do_save (const QString& format, const QString& save_opts); -private: + private: - QTextEdit * make_disp_view (QWidget *parent); + QTextEdit * make_disp_view (QWidget *parent); - base_qobject& m_octave_qobj; + base_qobject& m_octave_qobj; - variable_editor_view *m_edit_view; + variable_editor_view *m_edit_view; - QTextEdit *m_disp_view; -}; + QTextEdit *m_disp_view; + }; -class variable_editor_view : public QTableView -{ - Q_OBJECT + class variable_editor_view : public QTableView + { + Q_OBJECT -public: + public: - variable_editor_view (QWidget *p, base_qobject& oct_qobj); + variable_editor_view (QWidget *p, base_qobject& oct_qobj); - ~variable_editor_view (void) = default; + ~variable_editor_view (void) = default; - void setModel (QAbstractItemModel *model); + void setModel (QAbstractItemModel *model); -signals: + signals: - void command_signal (const QString& cmd); + void command_signal (const QString& cmd); - void add_edit_actions_signal (QMenu *menu, const QString& qualifier_string); + void add_edit_actions_signal (QMenu *menu, const QString& qualifier_string); -public slots: + public slots: - void createVariable (void); + void createVariable (void); - void transposeContent (void); + void transposeContent (void); - QList range_selected (void); + QList range_selected (void); - void delete_selected (void); + void delete_selected (void); - void clearContent (void); + void clearContent (void); - void cutClipboard (void); + void cutClipboard (void); - void copyClipboard (void); + void copyClipboard (void); - void pasteClipboard (void); + void pasteClipboard (void); - void handle_horizontal_scroll_action (int action); + void handle_horizontal_scroll_action (int action); - void handle_vertical_scroll_action (int action); + void handle_vertical_scroll_action (int action); - void createContextMenu (const QPoint& pt); + void createContextMenu (const QPoint& pt); - void createColumnMenu (const QPoint& pt); + void createColumnMenu (const QPoint& pt); - void createRowMenu (const QPoint& pt); + void createRowMenu (const QPoint& pt); - void selected_command_requested (const QString& cmd); + void selected_command_requested (const QString& cmd); -private: + private: - void add_edit_actions (QMenu *menu, const QString& qualifier_string); + void add_edit_actions (QMenu *menu, const QString& qualifier_string); - base_qobject& m_octave_qobj; + base_qobject& m_octave_qobj; - variable_editor_model *m_var_model; -}; + variable_editor_model *m_var_model; + }; -// Gadgets to keep track of and restore what variable window was in focus -// just prior to selecting something on the menu bar. + // Gadgets to keep track of and restore what variable window was in focus + // just prior to selecting something on the menu bar. -class HoverToolButton : public QToolButton -{ - Q_OBJECT + class HoverToolButton : public QToolButton + { + Q_OBJECT -public: + public: - HoverToolButton (QWidget *parent = nullptr); + HoverToolButton (QWidget *parent = nullptr); - ~HoverToolButton (void) = default; + ~HoverToolButton (void) = default; -signals: + signals: - void hovered_signal (void); + void hovered_signal (void); - void popup_shown_signal (void); + void popup_shown_signal (void); -protected: + protected: - bool eventFilter (QObject *obj, QEvent *ev); -}; + bool eventFilter (QObject *obj, QEvent *ev); + }; -class ReturnFocusToolButton : public HoverToolButton -{ - Q_OBJECT + class ReturnFocusToolButton : public HoverToolButton + { + Q_OBJECT -public: + public: - ReturnFocusToolButton (QWidget *parent = nullptr); + ReturnFocusToolButton (QWidget *parent = nullptr); - ~ReturnFocusToolButton (void) = default; + ~ReturnFocusToolButton (void) = default; -signals: + signals: - void about_to_activate (void); + void about_to_activate (void); -protected: + protected: - bool eventFilter (QObject *obj, QEvent *ev); -}; + bool eventFilter (QObject *obj, QEvent *ev); + }; -class ReturnFocusMenu : public QMenu -{ - Q_OBJECT + class ReturnFocusMenu : public QMenu + { + Q_OBJECT -public: + public: - ReturnFocusMenu (QWidget *parent = nullptr); + ReturnFocusMenu (QWidget *parent = nullptr); - ~ReturnFocusMenu (void) = default; + ~ReturnFocusMenu (void) = default; -signals: + signals: - void about_to_activate (void); + void about_to_activate (void); -protected: + protected: - bool eventFilter (QObject *obj, QEvent *ev); -}; + bool eventFilter (QObject *obj, QEvent *ev); + }; -// The variable editor class + // The variable editor class -class variable_editor : public octave_dock_widget -{ - Q_OBJECT + class variable_editor : public octave_dock_widget + { + Q_OBJECT -public: + public: - variable_editor (QWidget *parent, base_qobject& oct_qobj); + variable_editor (QWidget *parent, base_qobject& oct_qobj); - ~variable_editor (void); + ~variable_editor (void); - // No copying! + // No copying! - variable_editor (const variable_editor&) = delete; + variable_editor (const variable_editor&) = delete; - variable_editor& operator = (const variable_editor&) = delete; + variable_editor& operator = (const variable_editor&) = delete; - void refresh (void); + void refresh (void); - void tab_to_front (void); + void tab_to_front (void); -signals: + signals: - void updated (void); + void updated (void); - void finished (void); + void finished (void); - void command_signal (const QString& cmd); + void command_signal (const QString& cmd); - void refresh_signal (void); + void refresh_signal (void); - void clear_content_signal (void); + void clear_content_signal (void); - void copy_clipboard_signal (void); + void copy_clipboard_signal (void); - void paste_clipboard_signal (void); + void paste_clipboard_signal (void); - void level_up_signal (void); + void level_up_signal (void); - void save_signal (void); + void save_signal (void); - void delete_selected_signal (void); + void delete_selected_signal (void); - void interpreter_event (const fcn_callback& fcn); - void interpreter_event (const meth_callback& meth); + void interpreter_event (const fcn_callback& fcn); + void interpreter_event (const meth_callback& meth); -public slots: + public slots: - void callUpdate (const QModelIndex&, const QModelIndex&); + void callUpdate (const QModelIndex&, const QModelIndex&); - void notice_settings (const gui_settings *); + void notice_settings (void); - void edit_variable (const QString& name, const octave_value& val); + void edit_variable (const QString& name, const octave_value& val); - void variable_destroyed (QObject *obj); + void variable_destroyed (QObject *obj); - void variable_focused (const QString& name); + void variable_focused (const QString& name); - void record_hovered_focus_variable (void); + void record_hovered_focus_variable (void); - void restore_hovered_focus_variable (void); + void restore_hovered_focus_variable (void); -protected slots: + protected slots: - void closeEvent (QCloseEvent *); + void closeEvent (QCloseEvent *); - void save (void); + void save (void); - void cutClipboard (void); + void cutClipboard (void); - void copyClipboard (void); + void copyClipboard (void); - void pasteClipboard (void); + void pasteClipboard (void); - void levelUp (void); + void levelUp (void); -protected: + protected: - void focusInEvent (QFocusEvent *ev); + void focusInEvent (QFocusEvent *ev); -private: + private: - dw_main_window *m_main; + dw_main_window *m_main; - QToolBar *m_tool_bar; - QAction *m_save_action; + QToolBar *m_tool_bar; + QAction *m_save_action; - int m_default_width; + int m_default_width; - int m_default_height; + int m_default_height; - int m_add_font_height; + int m_add_font_height; - bool m_use_terminal_font; + bool m_use_terminal_font; - bool m_alternate_rows; + bool m_alternate_rows; - QString m_stylesheet; + QString m_stylesheet; - QFont m_font; + QFont m_font; - // If use_terminal_font is true then this will be different since - // "font" will contain the terminal font. - QFont m_sel_font; + // If use_terminal_font is true then this will be different since + // "font" will contain the terminal font. + QFont m_sel_font; - QList m_table_colors; + QList m_table_colors; - void update_colors (void); + void update_colors (void); - QAction * add_tool_bar_button (const QIcon& icon, const QString& text, - const QObject *receiver, const char *member); + QAction * add_tool_bar_button (const QIcon& icon, const QString& text, + const QObject *receiver, const char *member); - void construct_tool_bar (void); + void construct_tool_bar (void); - QString m_current_focus_vname; + QString m_current_focus_vname; - QString m_hovered_focus_vname; + QString m_hovered_focus_vname; - QSignalMapper *m_plot_mapper; - QSignalMapper *m_save_mapper; + QSignalMapper *m_plot_mapper; + QSignalMapper *m_save_mapper; - QWidget *m_focus_widget; + QWidget *m_focus_widget; - variable_dock_widget *m_focus_widget_vdw; -}; + variable_dock_widget *m_focus_widget_vdw; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/welcome-wizard.cc --- a/libgui/src/welcome-wizard.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/welcome-wizard.cc Tue Dec 06 15:45:27 2022 -0500 @@ -39,352 +39,343 @@ #include "gui-preferences-dw.h" #include "gui-preferences-nr.h" -#include "octave-qobject.h" +#include "gui-settings.h" #include "welcome-wizard.h" OCTAVE_BEGIN_NAMESPACE(octave) -static QLabel * -make_octave_logo (QWidget *p = nullptr, int height = 100) -{ - QLabel *logo = new QLabel (p); - QPixmap logo_pixmap (dw_icon_set_names["NONE"]); - logo->setPixmap (logo_pixmap.scaledToHeight (height)); - return logo; -}; + static QLabel * + make_octave_logo (QWidget *p = nullptr, int height = 100) + { + QLabel *logo = new QLabel (p); + QPixmap logo_pixmap (dw_icon_set_names["NONE"]); + logo->setPixmap (logo_pixmap.scaledToHeight (height)); + return logo; + }; -welcome_wizard::welcome_wizard (base_qobject& oct_qobj, QWidget *p) - : QDialog (p), m_octave_qobj (oct_qobj), m_page_ctor_list (), - m_page_list_iterator (), - m_current_page (initial_page::create (oct_qobj, this)), - m_allow_web_connect_state (false), - m_max_height (0), m_max_width (0) -{ - m_page_ctor_list.push_back (initial_page::create); - m_page_ctor_list.push_back (setup_community_news::create); - m_page_ctor_list.push_back (final_page::create); + welcome_wizard::welcome_wizard (QWidget *p) + : QDialog (p), m_page_ctor_list (), m_page_list_iterator (), + m_current_page (initial_page::create (this)), + m_allow_web_connect_state (false), + m_max_height (0), m_max_width (0) + { + m_page_ctor_list.push_back (initial_page::create); + m_page_ctor_list.push_back (setup_community_news::create); + m_page_ctor_list.push_back (final_page::create); - m_page_list_iterator = m_page_ctor_list.begin (); + m_page_list_iterator = m_page_ctor_list.begin (); - setWindowTitle (tr ("Welcome to GNU Octave")); + setWindowTitle (tr ("Welcome to GNU Octave")); - setEnabled (true); + setEnabled (true); - setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - // Create all pages for pre-setting the minimal required size for all pages - show_page (); - adjust_size (); - next_page (); - adjust_size (); - next_page (); - adjust_size (); - // now go back to the first page - previous_page (); - previous_page (); + // Create all pages for pre-setting the minimal required size for all pages + show_page (); + adjust_size (); + next_page (); + adjust_size (); + next_page (); + adjust_size (); + // now go back to the first page + previous_page (); + previous_page (); - // Set the size determined above - resize (m_max_width, m_max_height); + // Set the size determined above + resize (m_max_width, m_max_height); #if defined (OCTAVE_USE_WINDOWS_API) - // HACK to forceshow of dialog if started minimized - ShowWindow (reinterpret_cast (winId ()), SW_SHOWNORMAL); + // HACK to forceshow of dialog if started minimized + ShowWindow (reinterpret_cast (winId ()), SW_SHOWNORMAL); #endif -} + } -void welcome_wizard::adjust_size (void) -{ - // Get adjusted size for the current page - adjustSize (); - QSize sz = size (); + void welcome_wizard::adjust_size (void) + { + // Get adjusted size for the current page + adjustSize (); + QSize sz = size (); - // Update the max. size of the three pages if required + // Update the max. size of the three pages if required - if (sz.height () > m_max_height) - m_max_height = sz.height (); + if (sz.height () > m_max_height) + m_max_height = sz.height (); - if (sz.width () > m_max_width) - m_max_width = sz.width (); -} - -void welcome_wizard::handle_web_connect_option (int state) -{ - m_allow_web_connect_state = state == Qt::Checked; -} + if (sz.width () > m_max_width) + m_max_width = sz.width (); + } -void welcome_wizard::show_page (void) -{ - delete m_current_page; - delete layout (); + void welcome_wizard::handle_web_connect_option (int state) + { + m_allow_web_connect_state = state == Qt::Checked; + } - m_current_page = (*m_page_list_iterator) (m_octave_qobj, this); + void welcome_wizard::show_page (void) + { + delete m_current_page; + delete layout (); - QVBoxLayout *new_layout = new QVBoxLayout (); - setLayout (new_layout); + m_current_page = (*m_page_list_iterator) (this); - new_layout->addWidget (m_current_page); -} + QVBoxLayout *new_layout = new QVBoxLayout (); + setLayout (new_layout); -void welcome_wizard::previous_page (void) -{ - --m_page_list_iterator; + new_layout->addWidget (m_current_page); + } - show_page (); -} + void welcome_wizard::previous_page (void) + { + --m_page_list_iterator; -void welcome_wizard::next_page (void) -{ - ++m_page_list_iterator; - - show_page (); -} + show_page (); + } -void welcome_wizard::accept (void) -{ - // Create default settings file. + void welcome_wizard::next_page (void) + { + ++m_page_list_iterator; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - rmgr.reload_settings (); - - gui_settings *settings = rmgr.get_settings (); + show_page (); + } - if (settings) - { - settings->setValue (nr_allow_connection.key, - m_allow_web_connect_state); + void welcome_wizard::accept (void) + { + // Create default settings file. + + gui_settings settings; - settings->sync (); - } + settings.setValue (nr_allow_connection.key, m_allow_web_connect_state); - QDialog::accept (); -} + settings.sync (); + + QDialog::accept (); + } -initial_page::initial_page (base_qobject& oct_qobj, welcome_wizard *wizard) - : QWidget (wizard), - m_title (new QLabel (tr ("Welcome to Octave!"), this)), - m_message (new QLabel (this)), - m_logo (make_octave_logo (this)), - m_next (new QPushButton (tr ("Next"), this)), - m_cancel (new QPushButton (tr ("Cancel"), this)) -{ - QFont ft; - ft.setPointSize (20); - m_title->setFont (ft); + initial_page::initial_page (welcome_wizard *wizard) + : QWidget (wizard), + m_title (new QLabel (tr ("Welcome to Octave!"), this)), + m_message (new QLabel (this)), + m_logo (make_octave_logo (this)), + m_next (new QPushButton (tr ("Next"), this)), + m_cancel (new QPushButton (tr ("Cancel"), this)) + { + QFont ft; + ft.setPointSize (20); + m_title->setFont (ft); - resource_manager& rmgr = oct_qobj.get_resource_manager (); + gui_settings settings; - m_message->setText - (tr ("\n" - "

You seem to be using the Octave graphical interface for the first time on this computer.\n" - "Click 'Next' to create a configuration file and launch Octave.

\n" - "

The configuration file is stored in
%1.

\n" - ""). - arg (rmgr.get_settings_file ())); - m_message->setWordWrap (true); - m_message->setMinimumWidth (400); + m_message->setText + (tr ("\n" + "

You seem to be using the Octave graphical interface for the first time on this computer.\n" + "Click 'Next' to create a configuration file and launch Octave.

\n" + "

The configuration file is stored in
%1.

\n" + ""). + arg (settings.file_name ())); + m_message->setWordWrap (true); + m_message->setMinimumWidth (400); - QVBoxLayout *message_layout = new QVBoxLayout; + QVBoxLayout *message_layout = new QVBoxLayout; - message_layout->addWidget (m_title); - message_layout->addWidget (m_message); + message_layout->addWidget (m_title); + message_layout->addWidget (m_message); - QHBoxLayout *message_and_logo = new QHBoxLayout; + QHBoxLayout *message_and_logo = new QHBoxLayout; - message_and_logo->addLayout (message_layout); - message_and_logo->addStretch (10); - message_and_logo->addWidget (m_logo, 0, Qt::AlignTop); - - QHBoxLayout *button_bar = new QHBoxLayout; + message_and_logo->addLayout (message_layout); + message_and_logo->addStretch (10); + message_and_logo->addWidget (m_logo, 0, Qt::AlignTop); - button_bar->addStretch (10); - button_bar->addWidget (m_next); - button_bar->addWidget (m_cancel); + QHBoxLayout *button_bar = new QHBoxLayout; - QVBoxLayout *page_layout = new QVBoxLayout (this); - setLayout (page_layout); + button_bar->addStretch (10); + button_bar->addWidget (m_next); + button_bar->addWidget (m_cancel); + + QVBoxLayout *page_layout = new QVBoxLayout (this); + setLayout (page_layout); - page_layout->addLayout (message_and_logo); - page_layout->addStretch (10); - page_layout->addSpacing (20); - page_layout->addLayout (button_bar); + page_layout->addLayout (message_and_logo); + page_layout->addStretch (10); + page_layout->addSpacing (20); + page_layout->addLayout (button_bar); - setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - m_next->setDefault (true); - m_next->setFocus (); + m_next->setDefault (true); + m_next->setFocus (); - connect (m_next, &QPushButton::clicked, wizard, &welcome_wizard::next_page); - connect (m_cancel, &QPushButton::clicked, wizard, &welcome_wizard::reject); -} + connect (m_next, &QPushButton::clicked, wizard, &welcome_wizard::next_page); + connect (m_cancel, &QPushButton::clicked, wizard, &welcome_wizard::reject); + } -setup_community_news::setup_community_news (base_qobject&, - welcome_wizard *wizard) - : QWidget (wizard), - m_title (new QLabel (tr ("Community News"), this)), - m_message (new QLabel (this)), - m_checkbox (new QCheckBox (this)), - m_checkbox_message (new QLabel (this)), - m_logo (make_octave_logo (this)), - m_previous (new QPushButton (tr ("Previous"), this)), - m_next (new QPushButton (tr ("Next"), this)), - m_cancel (new QPushButton (tr ("Cancel"), this)) -{ - QFont ft; - ft.setPointSize (20); - m_title->setFont (ft); + setup_community_news::setup_community_news (welcome_wizard *wizard) + : QWidget (wizard), + m_title (new QLabel (tr ("Community News"), this)), + m_message (new QLabel (this)), + m_checkbox (new QCheckBox (this)), + m_checkbox_message (new QLabel (this)), + m_logo (make_octave_logo (this)), + m_previous (new QPushButton (tr ("Previous"), this)), + m_next (new QPushButton (tr ("Next"), this)), + m_cancel (new QPushButton (tr ("Cancel"), this)) + { + QFont ft; + ft.setPointSize (20); + m_title->setFont (ft); - m_message->setText - (tr ("\n" - "

When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\n" - "The check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.

\n" - "

You may also view the news by selecting the \"Community News\" item in the \"Help\" menu, or by visiting\n" - "https://octave.org/community-news.html.

\n" - "")); - m_message->setWordWrap (true); - m_message->setMinimumWidth (400); - m_message->setOpenExternalLinks (true); + m_message->setText + (tr ("\n" + "

When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\n" + "The check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.

\n" + "

You may also view the news by selecting the \"Community News\" item in the \"Help\" menu, or by visiting\n" + "https://octave.org/community-news.html.

\n" + "")); + m_message->setWordWrap (true); + m_message->setMinimumWidth (400); + m_message->setOpenExternalLinks (true); - QVBoxLayout *message_layout = new QVBoxLayout; + QVBoxLayout *message_layout = new QVBoxLayout; - message_layout->addWidget (m_title); - message_layout->addWidget (m_message); + message_layout->addWidget (m_title); + message_layout->addWidget (m_message); - QHBoxLayout *message_and_logo = new QHBoxLayout; + QHBoxLayout *message_and_logo = new QHBoxLayout; - message_and_logo->addLayout (message_layout); - message_and_logo->addStretch (10); - message_and_logo->addWidget (m_logo, 0, Qt::AlignTop); + message_and_logo->addLayout (message_layout); + message_and_logo->addStretch (10); + message_and_logo->addWidget (m_logo, 0, Qt::AlignTop); - QHBoxLayout *checkbox_layout = new QHBoxLayout; + QHBoxLayout *checkbox_layout = new QHBoxLayout; - bool allow_connection = nr_allow_connection.def.toBool (); - if (allow_connection) - m_checkbox->setCheckState (Qt::Checked); - else - m_checkbox->setCheckState (Qt::Unchecked); + bool allow_connection = nr_allow_connection.def.toBool (); + if (allow_connection) + m_checkbox->setCheckState (Qt::Checked); + else + m_checkbox->setCheckState (Qt::Unchecked); - m_checkbox_message->setText - (tr ("\n" - "\n" - "

Allow Octave to connect to the Octave web site when it starts to display current news and information about the Octave community.

\n" - "")); - m_checkbox_message->setWordWrap (true); - m_checkbox_message->setOpenExternalLinks (true); - m_checkbox_message->setMinimumWidth (500); + m_checkbox_message->setText + (tr ("\n" + "\n" + "

Allow Octave to connect to the Octave web site when it starts to display current news and information about the Octave community.

\n" + "")); + m_checkbox_message->setWordWrap (true); + m_checkbox_message->setOpenExternalLinks (true); + m_checkbox_message->setMinimumWidth (500); - checkbox_layout->addWidget (m_checkbox, 0, Qt::AlignTop); - checkbox_layout->addSpacing (20); - checkbox_layout->addWidget (m_checkbox_message, 0, Qt::AlignTop); - checkbox_layout->addStretch (10); + checkbox_layout->addWidget (m_checkbox, 0, Qt::AlignTop); + checkbox_layout->addSpacing (20); + checkbox_layout->addWidget (m_checkbox_message, 0, Qt::AlignTop); + checkbox_layout->addStretch (10); - QVBoxLayout *message_logo_and_checkbox = new QVBoxLayout; + QVBoxLayout *message_logo_and_checkbox = new QVBoxLayout; - message_logo_and_checkbox->addLayout (message_and_logo); - message_logo_and_checkbox->addSpacing (20); - message_logo_and_checkbox->addLayout (checkbox_layout); + message_logo_and_checkbox->addLayout (message_and_logo); + message_logo_and_checkbox->addSpacing (20); + message_logo_and_checkbox->addLayout (checkbox_layout); - QHBoxLayout *button_bar = new QHBoxLayout; + QHBoxLayout *button_bar = new QHBoxLayout; - button_bar->addStretch (10); - button_bar->addWidget (m_previous); - button_bar->addWidget (m_next); - button_bar->addWidget (m_cancel); + button_bar->addStretch (10); + button_bar->addWidget (m_previous); + button_bar->addWidget (m_next); + button_bar->addWidget (m_cancel); - QVBoxLayout *page_layout = new QVBoxLayout (this); - setLayout (page_layout); + QVBoxLayout *page_layout = new QVBoxLayout (this); + setLayout (page_layout); - page_layout->addLayout (message_logo_and_checkbox); - page_layout->addStretch (10); - page_layout->addSpacing (20); - page_layout->addLayout (button_bar); + page_layout->addLayout (message_logo_and_checkbox); + page_layout->addStretch (10); + page_layout->addSpacing (20); + page_layout->addLayout (button_bar); - setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - m_next->setDefault (true); - m_next->setFocus (); + m_next->setDefault (true); + m_next->setFocus (); - connect (m_checkbox, &QCheckBox::stateChanged, - wizard, &welcome_wizard::handle_web_connect_option); + connect (m_checkbox, &QCheckBox::stateChanged, + wizard, &welcome_wizard::handle_web_connect_option); - connect (m_previous, &QPushButton::clicked, wizard, &welcome_wizard::previous_page); - connect (m_next, &QPushButton::clicked, wizard, &welcome_wizard::next_page); - connect (m_cancel, &QPushButton::clicked, wizard, &welcome_wizard::reject); -} + connect (m_previous, &QPushButton::clicked, wizard, &welcome_wizard::previous_page); + connect (m_next, &QPushButton::clicked, wizard, &welcome_wizard::next_page); + connect (m_cancel, &QPushButton::clicked, wizard, &welcome_wizard::reject); + } -final_page::final_page (base_qobject&, welcome_wizard *wizard) - : QWidget (wizard), - m_title (new QLabel (tr ("Enjoy!"), this)), - m_message (new QLabel (this)), - m_logo (make_octave_logo (this)), - m_links (new QLabel (this)), - m_previous (new QPushButton (tr ("Previous"), this)), - m_finish (new QPushButton (tr ("Finish"), this)), - m_cancel (new QPushButton (tr ("Cancel"), this)) -{ - QFont ft; - ft.setPointSize (20); - m_title->setFont (ft); + final_page::final_page (welcome_wizard *wizard) + : QWidget (wizard), + m_title (new QLabel (tr ("Enjoy!"), this)), + m_message (new QLabel (this)), + m_logo (make_octave_logo (this)), + m_links (new QLabel (this)), + m_previous (new QPushButton (tr ("Previous"), this)), + m_finish (new QPushButton (tr ("Finish"), this)), + m_cancel (new QPushButton (tr ("Cancel"), this)) + { + QFont ft; + ft.setPointSize (20); + m_title->setFont (ft); - m_message->setText - (tr ("\n" - "

We hope you find Octave to be a useful tool.

\n" - "

If you encounter problems, there are a number of ways to get help, including commercial support options, a mailing list, a wiki, and other community-based support channels.\n" - "You can find more information about each of these by visiting https://octave.org/support.html (opens in external browser).

\n" - "")); - m_message->setWordWrap (true); - m_message->setMinimumWidth (400); - m_message->setOpenExternalLinks (true); + m_message->setText + (tr ("\n" + "

We hope you find Octave to be a useful tool.

\n" + "

If you encounter problems, there are a number of ways to get help, including commercial support options, a mailing list, a wiki, and other community-based support channels.\n" + "You can find more information about each of these by visiting https://octave.org/support.html (opens in external browser).

\n" + "")); + m_message->setWordWrap (true); + m_message->setMinimumWidth (400); + m_message->setOpenExternalLinks (true); - QVBoxLayout *message_layout = new QVBoxLayout; + QVBoxLayout *message_layout = new QVBoxLayout; - message_layout->addWidget (m_title); - message_layout->addWidget (m_message); + message_layout->addWidget (m_title); + message_layout->addWidget (m_message); - QHBoxLayout *message_and_logo = new QHBoxLayout; + QHBoxLayout *message_and_logo = new QHBoxLayout; - message_and_logo->addLayout (message_layout); - message_and_logo->addStretch (10); - message_and_logo->addWidget (m_logo, 0, Qt::AlignTop); + message_and_logo->addLayout (message_layout); + message_and_logo->addStretch (10); + message_and_logo->addWidget (m_logo, 0, Qt::AlignTop); - m_links->setText - (tr ("\n" - "\n" - "

For more information about Octave:

\n" - "
    \n" - "
  • Visit https://octave.org (opens in external browser)
  • \n" - "
  • Get the documentation online as html- or pdf-document (opens in external browser)
  • \n" - "
  • Open the documentation browser of the Octave GUI with the help menu
  • \n" - "
\n" - "")); - m_links->setWordWrap (true); - m_links->setOpenExternalLinks (true); + m_links->setText + (tr ("\n" + "\n" + "

For more information about Octave:

\n" + "
    \n" + "
  • Visit https://octave.org (opens in external browser)
  • \n" + "
  • Get the documentation online as html- or pdf-document (opens in external browser)
  • \n" + "
  • Open the documentation browser of the Octave GUI with the help menu
  • \n" + "
\n" + "")); + m_links->setWordWrap (true); + m_links->setOpenExternalLinks (true); - QHBoxLayout *button_bar = new QHBoxLayout; + QHBoxLayout *button_bar = new QHBoxLayout; - button_bar->addStretch (10); - button_bar->addWidget (m_previous); - button_bar->addWidget (m_finish); - button_bar->addWidget (m_cancel); + button_bar->addStretch (10); + button_bar->addWidget (m_previous); + button_bar->addWidget (m_finish); + button_bar->addWidget (m_cancel); - QVBoxLayout *page_layout = new QVBoxLayout (this); - setLayout (page_layout); + QVBoxLayout *page_layout = new QVBoxLayout (this); + setLayout (page_layout); - page_layout->addLayout (message_and_logo); - page_layout->addSpacing (20); - page_layout->addWidget (m_links); - page_layout->addStretch (10); - page_layout->addSpacing (20); - page_layout->addLayout (button_bar); + page_layout->addLayout (message_and_logo); + page_layout->addSpacing (20); + page_layout->addWidget (m_links); + page_layout->addStretch (10); + page_layout->addSpacing (20); + page_layout->addLayout (button_bar); - setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - m_finish->setDefault (true); - m_finish->setFocus (); + m_finish->setDefault (true); + m_finish->setFocus (); - connect (m_previous, &QPushButton::clicked, - wizard, &welcome_wizard::previous_page); - connect (m_finish, &QPushButton::clicked, wizard, &welcome_wizard::accept); - connect (m_cancel, &QPushButton::clicked, wizard, &welcome_wizard::reject); -} + connect (m_previous, &QPushButton::clicked, + wizard, &welcome_wizard::previous_page); + connect (m_finish, &QPushButton::clicked, wizard, &welcome_wizard::accept); + connect (m_cancel, &QPushButton::clicked, wizard, &welcome_wizard::reject); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/welcome-wizard.h --- a/libgui/src/welcome-wizard.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/welcome-wizard.h Tue Dec 06 15:45:27 2022 -0500 @@ -32,123 +32,119 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; + class welcome_wizard : public QDialog + { + Q_OBJECT -class welcome_wizard : public QDialog -{ - Q_OBJECT + public: -public: + typedef QWidget *(*page_creator_fptr) (welcome_wizard *); - typedef QWidget *(*page_creator_fptr) (base_qobject&, welcome_wizard *); + welcome_wizard (QWidget *parent = nullptr); - welcome_wizard (base_qobject& oct_qobj, QWidget *parent = nullptr); + ~welcome_wizard (void) = default; - ~welcome_wizard (void) = default; + void adjust_size (void); - void adjust_size (void); - -private: + private: - base_qobject& m_octave_qobj; + QList m_page_ctor_list; + QList::iterator m_page_list_iterator; + QWidget *m_current_page; + bool m_allow_web_connect_state; + int m_max_height; + int m_max_width; - QList m_page_ctor_list; - QList::iterator m_page_list_iterator; - QWidget *m_current_page; - bool m_allow_web_connect_state; - int m_max_height; - int m_max_width; + public slots: -public slots: + void handle_web_connect_option (int state); - void handle_web_connect_option (int state); + void show_page (void); + void previous_page (void); + void next_page (void); - void show_page (void); - void previous_page (void); - void next_page (void); + void accept (void); + }; - void accept (void); -}; + class initial_page : public QWidget + { + Q_OBJECT -class initial_page : public QWidget -{ - Q_OBJECT + public: -public: + initial_page (welcome_wizard *wizard); - initial_page (base_qobject& oct_qobj, welcome_wizard *wizard); + ~initial_page (void) = default; - ~initial_page (void) = default; + static QWidget * + create (welcome_wizard *wizard) + { + return new initial_page (wizard); + } - static QWidget * - create (base_qobject& oct_qobj, welcome_wizard *wizard) - { - return new initial_page (oct_qobj, wizard); - } - -private: + private: - QLabel *m_title; - QLabel *m_message; - QLabel *m_logo; - QPushButton *m_next; - QPushButton *m_cancel; -}; + QLabel *m_title; + QLabel *m_message; + QLabel *m_logo; + QPushButton *m_next; + QPushButton *m_cancel; + }; -class setup_community_news : public QWidget -{ - Q_OBJECT + class setup_community_news : public QWidget + { + Q_OBJECT -public: + public: - setup_community_news (base_qobject& oct_qobj, welcome_wizard *wizard); + setup_community_news (welcome_wizard *wizard); - ~setup_community_news (void) = default; + ~setup_community_news (void) = default; - static QWidget * - create (base_qobject& oct_qobj, welcome_wizard *wizard) - { - return new setup_community_news (oct_qobj, wizard); - } + static QWidget * + create (welcome_wizard *wizard) + { + return new setup_community_news (wizard); + } -private: + private: - QLabel *m_title; - QLabel *m_message; - QCheckBox *m_checkbox; - QLabel *m_checkbox_message; - QLabel *m_logo; - QPushButton *m_previous; - QPushButton *m_next; - QPushButton *m_cancel; -}; + QLabel *m_title; + QLabel *m_message; + QCheckBox *m_checkbox; + QLabel *m_checkbox_message; + QLabel *m_logo; + QPushButton *m_previous; + QPushButton *m_next; + QPushButton *m_cancel; + }; -class final_page : public QWidget -{ - Q_OBJECT + class final_page : public QWidget + { + Q_OBJECT -public: + public: - final_page (base_qobject& oct_qobj, welcome_wizard *wizard); + final_page (welcome_wizard *wizard); - ~final_page (void) = default; + ~final_page (void) = default; - static QWidget * - create (base_qobject& oct_qobj, welcome_wizard *wizard) - { - return new final_page (oct_qobj, wizard); - } + static QWidget * + create (welcome_wizard *wizard) + { + return new final_page (wizard); + } -private: + private: - QLabel *m_title; - QLabel *m_message; - QLabel *m_logo; - QLabel *m_links; - QPushButton *m_previous; - QPushButton *m_finish; - QPushButton *m_cancel; -}; + QLabel *m_title; + QLabel *m_message; + QLabel *m_logo; + QLabel *m_links; + QPushButton *m_previous; + QPushButton *m_finish; + QPushButton *m_cancel; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/workspace-model.cc --- a/libgui/src/workspace-model.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/workspace-model.cc Tue Dec 06 15:45:27 2022 -0500 @@ -33,7 +33,6 @@ #include "gui-preferences-ws.h" #include "gui-settings.h" -#include "octave-qobject.h" #include "workspace-model.h" #include "syminfo.h" @@ -41,235 +40,237 @@ OCTAVE_BEGIN_NAMESPACE(octave) -workspace_model::workspace_model (QObject *p) -: QAbstractTableModel (p) -{ - // The header names. Use tr () again when accessing them since - // the translator si not yet initialized when this ctor is called - m_columnNames.append (tr ("Name")); - m_columnNames.append (tr ("Class")); - m_columnNames.append (tr ("Dimension")); - m_columnNames.append (tr ("Value")); - m_columnNames.append (tr ("Attribute")); + workspace_model::workspace_model (QObject *p) + : QAbstractTableModel (p) + { + // The header names. Use tr () again when accessing them since + // the translator si not yet initialized when this ctor is called + m_columnNames.append (tr ("Name")); + m_columnNames.append (tr ("Class")); + m_columnNames.append (tr ("Dimension")); + m_columnNames.append (tr ("Value")); + m_columnNames.append (tr ("Attribute")); - // Initialize the background and foreground colors of special - // classes in the workspace view. The structure is - // m_storage_class_colors(1,2,...,colors): background colors - // m_storage_class_colors(colors+1,...,2*colors): foreground colors - for (unsigned int i = 0; i < 2*ws_colors_count; i++) - m_storage_class_colors.append (QColor (Qt::white)); + // Initialize the background and foreground colors of special + // classes in the workspace view. The structure is + // m_storage_class_colors(1,2,...,colors): background colors + // m_storage_class_colors(colors+1,...,2*colors): foreground colors + for (unsigned int i = 0; i < 2*ws_colors_count; i++) + m_storage_class_colors.append (QColor (Qt::white)); -} + } + + int + workspace_model::rowCount (const QModelIndex&) const + { + return m_symbols.size (); + } -int -workspace_model::rowCount (const QModelIndex&) const -{ - return m_symbols.size (); -} + int + workspace_model::columnCount (const QModelIndex&) const + { + return m_columnNames.size (); + } -int -workspace_model::columnCount (const QModelIndex&) const -{ - return m_columnNames.size (); -} + Qt::ItemFlags + workspace_model::flags (const QModelIndex& idx) const + { + Qt::ItemFlags retval = Qt::NoItemFlags; + + if (idx.isValid ()) + { + retval |= Qt::ItemIsEnabled; -Qt::ItemFlags -workspace_model::flags (const QModelIndex& idx) const -{ - Qt::ItemFlags retval = Qt::NoItemFlags; + if (m_top_level && idx.column () == 0) + retval |= Qt::ItemIsSelectable; + } + + return retval; + } - if (idx.isValid ()) - { - retval |= Qt::ItemIsEnabled; - - if (m_top_level && idx.column () == 0) - retval |= Qt::ItemIsSelectable; - } - - return retval; -} + QVariant + workspace_model::headerData (int section, Qt::Orientation orientation, + int role) const + { + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + return tr (m_columnNames[section].toStdString ().data ()); + else + return QVariant (); + } -QVariant -workspace_model::headerData (int section, Qt::Orientation orientation, - int role) const -{ - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) - return tr (m_columnNames[section].toStdString ().data ()); - else - return QVariant (); -} + QVariant + workspace_model::data (const QModelIndex& idx, int role) const + { + QVariant retval; -QVariant -workspace_model::data (const QModelIndex& idx, int role) const -{ - QVariant retval; + if (idx.isValid ()) + { + if ((role == Qt::BackgroundRole || role == Qt::ForegroundRole) + && m_enable_colors) + { + int actual_class + = ws_class_chars.indexOf (m_scopes[idx.row ()].toLatin1 ()); + if (actual_class >= 0) + { + // Valid class: Get background (normal indexes) or foreground + // color (indexes with offset) + if (role == Qt::ForegroundRole) + actual_class += ws_colors_count; - if (idx.isValid ()) - { - if ((role == Qt::BackgroundRole || role == Qt::ForegroundRole) - && m_enable_colors) - { - int actual_class - = ws_class_chars.indexOf (m_scopes[idx.row ()].toLatin1 ()); - if (actual_class >= 0) - { - // Valid class: Get background (normal indexes) or foreground - // color (indexes with offset) - if (role == Qt::ForegroundRole) - actual_class += ws_colors_count; + return QVariant (m_storage_class_colors.at (actual_class)); + } + else + return retval; + } - return QVariant (m_storage_class_colors.at (actual_class)); - } - else - return retval; - } + if (role == Qt::DisplayRole + || (idx.column () == 0 && role == Qt::EditRole) + || (idx.column () == 0 && role == Qt::ToolTipRole)) + { + switch (idx.column ()) + { + case 0: + if (role == Qt::ToolTipRole) + retval + = QVariant (tr ("Right click to copy, rename, or display")); + else + retval = QVariant (m_symbols[idx.row ()]); + break; - if (role == Qt::DisplayRole - || (idx.column () == 0 && role == Qt::EditRole) - || (idx.column () == 0 && role == Qt::ToolTipRole)) - { - switch (idx.column ()) - { - case 0: - if (role == Qt::ToolTipRole) - retval - = QVariant (tr ("Right click to copy, rename, or display")); - else - retval = QVariant (m_symbols[idx.row ()]); - break; + case 1: + retval = QVariant (m_class_names[idx.row ()]); + break; + + case 2: + retval = QVariant (m_dimensions[idx.row ()]); + break; - case 1: - retval = QVariant (m_class_names[idx.row ()]); - break; - - case 2: - retval = QVariant (m_dimensions[idx.row ()]); - break; + case 3: + retval = QVariant (m_values[idx.row ()]); + break; - case 3: - retval = QVariant (m_values[idx.row ()]); - break; + case 4: + { + QString sclass; - case 4: - { - QString sclass; + int actual_class + = ws_class_chars.indexOf (m_scopes[idx.row ()].toLatin1 ()); - int actual_class - = ws_class_chars.indexOf (m_scopes[idx.row ()].toLatin1 ()); + if (actual_class >= 0) + sclass = ws_color_names.at (actual_class); - if (actual_class >= 0) - sclass = ws_color_names.at (actual_class); + if (m_complex_flags[idx.row ()]) + { + if (sclass.isEmpty ()) + sclass = tr ("complex"); + else + sclass += ", " + tr ("complex"); + } - if (m_complex_flags[idx.row ()]) - { - if (sclass.isEmpty ()) - sclass = tr ("complex"); - else - sclass += ", " + tr ("complex"); - } + retval = QVariant (sclass); + } + break; + } + } + } - retval = QVariant (sclass); - } - break; - } - } - } + return retval; + } - return retval; -} + void + workspace_model::set_workspace (bool top_level, bool /* debug */, + const symbol_info_list& syminfo) + { + clear_data (); -void -workspace_model::set_workspace (bool top_level, bool /* debug */, - const symbol_info_list& syminfo) -{ - clear_data (); + m_top_level = top_level; + m_syminfo_list = syminfo; + + update_table (); + } - m_top_level = top_level; - m_syminfo_list = syminfo; - - update_table (); -} + void + workspace_model::clear_workspace (void) + { + clear_data (); + update_table (); + } -void -workspace_model::clear_workspace (void) -{ - clear_data (); - update_table (); -} + void + workspace_model::notice_settings (void) + { + gui_settings settings; + + m_enable_colors = settings.value (ws_enable_colors).toBool (); -void -workspace_model::notice_settings (const gui_settings *settings) -{ - m_enable_colors = settings->value (ws_enable_colors).toBool (); - - int mode = settings->value (ws_color_mode).toInt (); + int mode = settings.value (ws_color_mode).toInt (); - for (int i = 0; i < ws_colors_count; i++) - { - QColor setting_color = settings->color_value (ws_colors[i], mode); + for (int i = 0; i < ws_colors_count; i++) + { + QColor setting_color = settings.color_value (ws_colors[i], mode); - QPalette p (setting_color); - m_storage_class_colors.replace (i, setting_color); + QPalette p (setting_color); + m_storage_class_colors.replace (i, setting_color); - QColor fg_color = p.color (QPalette::WindowText); - m_storage_class_colors.replace (i + ws_colors_count, fg_color); + QColor fg_color = p.color (QPalette::WindowText); + m_storage_class_colors.replace (i + ws_colors_count, fg_color); - } -} + } + } -void -workspace_model::clear_data (void) -{ - m_top_level = false; - m_syminfo_list = symbol_info_list (); - m_scopes = QString (); - m_symbols = QStringList (); - m_class_names = QStringList (); - m_dimensions = QStringList (); - m_values = QStringList (); - m_complex_flags = QIntList (); -} + void + workspace_model::clear_data (void) + { + m_top_level = false; + m_syminfo_list = symbol_info_list (); + m_scopes = QString (); + m_symbols = QStringList (); + m_class_names = QStringList (); + m_dimensions = QStringList (); + m_values = QStringList (); + m_complex_flags = QIntList (); + } -void -workspace_model::update_table (void) -{ - beginResetModel (); + void + workspace_model::update_table (void) + { + beginResetModel (); - for (const auto& syminfo : m_syminfo_list) - { - std::string nm = syminfo.name (); + for (const auto& syminfo : m_syminfo_list) + { + std::string nm = syminfo.name (); - octave_value val = syminfo.value (); + octave_value val = syminfo.value (); - // FIXME: fix size for objects, see kluge in ov.cc - Matrix sz = val.size (); - dim_vector dv = dim_vector::alloc (sz.numel ()); - for (octave_idx_type i = 0; i < dv.ndims (); i++) - dv(i) = sz(i); + // FIXME: fix size for objects, see kluge in ov.cc + Matrix sz = val.size (); + dim_vector dv = dim_vector::alloc (sz.numel ()); + for (octave_idx_type i = 0; i < dv.ndims (); i++) + dv(i) = sz(i); - char storage = ' '; - if (syminfo.is_formal ()) - storage = 'a'; - else if (syminfo.is_global ()) - storage = 'g'; - else if (syminfo.is_persistent ()) - storage = 'p'; + char storage = ' '; + if (syminfo.is_formal ()) + storage = 'a'; + else if (syminfo.is_global ()) + storage = 'g'; + else if (syminfo.is_persistent ()) + storage = 'p'; - std::ostringstream buf; - val.short_disp (buf); - std::string short_disp_str = buf.str (); + std::ostringstream buf; + val.short_disp (buf); + std::string short_disp_str = buf.str (); - m_scopes.append (storage); - m_symbols.append (QString::fromStdString (nm)); - m_class_names.append (QString::fromStdString (val.class_name ())); - m_dimensions.append (QString::fromStdString (dv.str ())); - m_values.append (QString::fromStdString (short_disp_str)); - m_complex_flags.append (val.iscomplex ()); - } + m_scopes.append (storage); + m_symbols.append (QString::fromStdString (nm)); + m_class_names.append (QString::fromStdString (val.class_name ())); + m_dimensions.append (QString::fromStdString (dv.str ())); + m_values.append (QString::fromStdString (short_disp_str)); + m_complex_flags.append (val.iscomplex ()); + } - endResetModel (); + endResetModel (); - emit model_changed (); -} + emit model_changed (); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/workspace-model.h --- a/libgui/src/workspace-model.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/workspace-model.h Tue Dec 06 15:45:27 2022 -0500 @@ -34,8 +34,6 @@ #include #include -#include "gui-settings.h" - #include "syminfo.h" // Defined for purposes of sending QList as part of signal. @@ -43,73 +41,73 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class workspace_model : public QAbstractTableModel -{ - Q_OBJECT + class workspace_model : public QAbstractTableModel + { + Q_OBJECT -public: + public: - workspace_model (QObject *parent = nullptr); + workspace_model (QObject *parent = nullptr); - ~workspace_model (void) = default; + ~workspace_model (void) = default; - int rowCount (const QModelIndex& parent = QModelIndex ()) const; + int rowCount (const QModelIndex& parent = QModelIndex ()) const; - int columnCount (const QModelIndex& parent = QModelIndex ()) const; + int columnCount (const QModelIndex& parent = QModelIndex ()) const; - Qt::ItemFlags flags (const QModelIndex& index) const; + Qt::ItemFlags flags (const QModelIndex& index) const; - QVariant headerData (int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const; + QVariant headerData (int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; - QVariant data (const QModelIndex& index, int role) const; + QVariant data (const QModelIndex& index, int role) const; - bool is_top_level (void) const { return m_top_level; } + bool is_top_level (void) const { return m_top_level; } - QColor storage_class_color (int s_class) - { - return m_storage_class_colors.at (s_class); - } + QColor storage_class_color (int s_class) + { + return m_storage_class_colors.at (s_class); + } - symbol_info_list get_symbol_info (void) const { return m_syminfo_list; } + symbol_info_list get_symbol_info (void) const { return m_syminfo_list; } - QStringList get_symbol_names (void) const { return m_symbols; } - QStringList get_symbol_values (void) const { return m_values; } + QStringList get_symbol_names (void) const { return m_symbols; } + QStringList get_symbol_values (void) const { return m_values; } -signals: + signals: - void model_changed (void); - void prompt_variable_editor(void); + void model_changed (void); + void prompt_variable_editor(void); -public slots: + public slots: - void set_workspace (bool top_level, bool debug, - const symbol_info_list& syminfo); + void set_workspace (bool top_level, bool debug, + const symbol_info_list& syminfo); - void clear_workspace (void); + void clear_workspace (void); - void notice_settings (const gui_settings *); + void notice_settings (void); -private: + private: - void clear_data (void); - void update_table (void); + void clear_data (void); + void update_table (void); - bool m_top_level; - symbol_info_list m_syminfo_list; - QString m_scopes; - QStringList m_symbols; - QStringList m_class_names; - QStringList m_dimensions; - QStringList m_values; - QIntList m_complex_flags; + bool m_top_level; + symbol_info_list m_syminfo_list; + QString m_scopes; + QStringList m_symbols; + QStringList m_class_names; + QStringList m_dimensions; + QStringList m_values; + QIntList m_complex_flags; - QStringList m_columnNames; + QStringList m_columnNames; - QList m_storage_class_colors; - bool m_enable_colors; + QList m_storage_class_colors; + bool m_enable_colors; -}; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/workspace-view.cc --- a/libgui/src/workspace-view.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/workspace-view.cc Tue Dec 06 15:45:27 2022 -0500 @@ -42,515 +42,508 @@ #include #include "gui-preferences-ws.h" +#include "gui-settings.h" #include "octave-qobject.h" #include "octave-qtutils.h" #include "workspace-view.h" OCTAVE_BEGIN_NAMESPACE(octave) -workspace_view::workspace_view (QWidget *p, base_qobject& oct_qobj) -: octave_dock_widget ("WorkspaceView", p, oct_qobj), - m_view (new QTableView (this)), - m_filter_checkbox (new QCheckBox ()), - m_filter (new QComboBox (this)), - m_filter_widget (new QWidget (this)) -{ - set_title (tr ("Workspace")); - setStatusTip (tr ("View the variables in the active workspace.")); + workspace_view::workspace_view (QWidget *p, base_qobject& oct_qobj) + : octave_dock_widget ("WorkspaceView", p, oct_qobj), + m_view (new QTableView (this)), + m_filter_checkbox (new QCheckBox ()), + m_filter (new QComboBox (this)), + m_filter_widget (new QWidget (this)) + { + set_title (tr ("Workspace")); + setStatusTip (tr ("View the variables in the active workspace.")); + + m_filter->setToolTip (tr ("Enter text to filter the workspace")); + m_filter->setEditable (true); + m_filter->setMaxCount (ws_max_filter_history.def.toInt ()); + m_filter->setInsertPolicy (QComboBox::NoInsert); + m_filter->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon); + QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred); + m_filter->setSizePolicy (sizePol); + m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive); + + QLabel *filter_label = new QLabel (tr ("Filter")); + + m_view->setWordWrap (false); + m_view->setContextMenuPolicy (Qt::CustomContextMenu); + m_view->setShowGrid (false); + (m_view->verticalHeader) ()->hide (); + m_view->setAlternatingRowColors (true); + m_view_previous_row_count = 0; - m_filter->setToolTip (tr ("Enter text to filter the workspace")); - m_filter->setEditable (true); - m_filter->setMaxCount (ws_max_filter_history.def.toInt ()); - m_filter->setInsertPolicy (QComboBox::NoInsert); - m_filter->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon); - QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred); - m_filter->setSizePolicy (sizePol); - m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive); + // Set an empty widget, so we can assign a layout to it. + setWidget (new QWidget (this)); + + // Create the layouts + QHBoxLayout *filter_layout = new QHBoxLayout (); - QLabel *filter_label = new QLabel (tr ("Filter")); + filter_layout->addWidget (filter_label); + filter_layout->addWidget (m_filter_checkbox); + filter_layout->addWidget (m_filter); + filter_layout->setMargin (0); + + m_filter_widget->setLayout (filter_layout); - m_view->setWordWrap (false); - m_view->setContextMenuPolicy (Qt::CustomContextMenu); - m_view->setShowGrid (false); - (m_view->verticalHeader) ()->hide (); - m_view->setAlternatingRowColors (true); - m_view_previous_row_count = 0; + QVBoxLayout *ws_layout = new QVBoxLayout (); + ws_layout->addWidget (m_filter_widget); + ws_layout->addWidget (m_view); + ws_layout->setSpacing (0); + + gui_settings settings; - // Set an empty widget, so we can assign a layout to it. - setWidget (new QWidget (this)); + m_filter_shown = settings.value (ws_filter_shown).toBool (); + m_filter_widget->setVisible (m_filter_shown); + + ws_layout->setMargin (2); - // Create the layouts - QHBoxLayout *filter_layout = new QHBoxLayout (); + // Set the empty widget to have our layout. + widget ()->setLayout (ws_layout); + + // Initialize collapse/expand state of the workspace subcategories. - filter_layout->addWidget (filter_label); - filter_layout->addWidget (m_filter_checkbox); - filter_layout->addWidget (m_filter); - filter_layout->setMargin (0); + //enable sorting (setting column and order after model was set) + m_view->setSortingEnabled (true); + // Initialize column order and width of the workspace + m_view->horizontalHeader ()->restoreState + (settings.value (ws_column_state.key).toByteArray ()); - m_filter_widget->setLayout (filter_layout); + // Set header properties for sorting + m_view->horizontalHeader ()->setSectionsClickable (true); + m_view->horizontalHeader ()->setSectionsMovable (true); + m_view->horizontalHeader ()->setSortIndicator ( + settings.value (ws_sort_column).toInt (), + static_cast (settings.value (ws_sort_order).toUInt ())); + // FIXME: use value instead of static cast after + // dropping support of Qt 5.4 - QVBoxLayout *ws_layout = new QVBoxLayout (); - ws_layout->addWidget (m_filter_widget); - ws_layout->addWidget (m_view); - ws_layout->setSpacing (0); + m_view->horizontalHeader ()->setSortIndicatorShown (true); + + m_view->horizontalHeader ()->setContextMenuPolicy (Qt::CustomContextMenu); + connect (m_view->horizontalHeader (), + &QTableView::customContextMenuRequested, + this, &workspace_view::header_contextmenu_requested); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + // Init state of the filter + m_filter->addItems (settings.value (ws_mru_list.key).toStringList ()); - if (settings) - { - m_filter_shown = settings->value (ws_filter_shown).toBool (); - m_filter_widget->setVisible (m_filter_shown); + bool filter_state = settings.value (ws_filter_active).toBool (); + m_filter_checkbox->setChecked (filter_state); + filter_activate (filter_state); + + // Connect signals and slots. - ws_layout->setMargin (2); + connect (m_filter, &QComboBox::editTextChanged, + this, &workspace_view::filter_update); + connect (m_filter_checkbox, &QCheckBox::toggled, + this, &workspace_view::filter_activate); + connect (m_filter->lineEdit (), &QLineEdit::editingFinished, + this, &workspace_view::update_filter_history); - // Set the empty widget to have our layout. - widget ()->setLayout (ws_layout); + connect (m_view, &QTableView::customContextMenuRequested, + this, &workspace_view::contextmenu_requested); - // Initialize collapse/expand state of the workspace subcategories. + connect (m_view, &QTableView::activated, + this, &workspace_view::handle_contextmenu_edit); - //enable sorting (setting column and order after model was set) - m_view->setSortingEnabled (true); - // Initialize column order and width of the workspace - m_view->horizontalHeader ()->restoreState - (settings->value (ws_column_state.key).toByteArray ()); + if (! p) + make_window (); + } + + void workspace_view::setModel (workspace_model *model) + { + m_filter_model.setSourceModel (model); + m_filter_model.setFilterKeyColumn(0); - // Set header properties for sorting - m_view->horizontalHeader ()->setSectionsClickable (true); - m_view->horizontalHeader ()->setSectionsMovable (true); - m_view->horizontalHeader ()->setSortIndicator ( - settings->value (ws_sort_column).toInt (), - static_cast (settings->value (ws_sort_order).toUInt ())); + m_view->setModel (&m_filter_model); + + // set the sorting after the model is set, it would be ignored otherwise + + gui_settings settings; + + m_view->sortByColumn ( + settings.value (ws_sort_column).toInt (), + static_cast (settings.value (ws_sort_order).toUInt ())); // FIXME: use value instead of static cast after // dropping support of Qt 5.4 - m_view->horizontalHeader ()->setSortIndicatorShown (true); + m_model = model; + } - m_view->horizontalHeader ()->setContextMenuPolicy (Qt::CustomContextMenu); - connect (m_view->horizontalHeader (), - &QTableView::customContextMenuRequested, - this, &workspace_view::header_contextmenu_requested); + void + workspace_view::notice_settings (void) + { + gui_settings settings; - // Init state of the filter - m_filter->addItems (settings->value (ws_mru_list.key).toStringList ()); + m_model->notice_settings (); // update colors of model first - bool filter_state = - settings->value (ws_filter_active).toBool (); - m_filter_checkbox->setChecked (filter_state); - filter_activate (filter_state); - } + for (int i = 0; i < ws_columns_shown.length (); i++) + m_view->setColumnHidden (i + 1, ! settings.value (ws_columns_shown_keys.at (i), true).toBool ()); + + QString tool_tip; - // Connect signals and slots. - - connect (m_filter, &QComboBox::editTextChanged, - this, &workspace_view::filter_update); - connect (m_filter_checkbox, &QCheckBox::toggled, - this, &workspace_view::filter_activate); - connect (m_filter->lineEdit (), &QLineEdit::editingFinished, - this, &workspace_view::update_filter_history); + if (settings.value (ws_enable_colors).toBool () + && ! settings.value (ws_hide_tool_tips).toBool ()) + { + tool_tip = QString (tr ("View the variables in the active workspace.
")); + tool_tip += QString (tr ("Colors for variable attributes:")); - connect (m_view, &QTableView::customContextMenuRequested, - this, &workspace_view::contextmenu_requested); - - connect (m_view, &QTableView::activated, - this, &workspace_view::handle_contextmenu_edit); - - if (! p) - make_window (); -} + for (int i = 0; i < ws_colors_count; i++) + { + tool_tip += + QString (R"(
%3
)") + .arg (m_model->storage_class_color (i).name ()) + .arg (m_model->storage_class_color (i + ws_colors_count).name ()) + .arg (QCoreApplication::translate ("octave::settings_dialog", + ws_color_names.at (i).toStdString ().data ())); + } + } -void workspace_view::setModel (workspace_model *model) -{ - m_filter_model.setSourceModel (model); - m_filter_model.setFilterKeyColumn(0); - - m_view->setModel (&m_filter_model); + setToolTip (tool_tip); + } - // set the sorting after the model is set, it would be ignored otherwise - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - m_view->sortByColumn ( - settings->value (ws_sort_column).toInt (), - static_cast (settings->value (ws_sort_order).toUInt ())); - // FIXME: use value instead of static cast after - // dropping support of Qt 5.4 + void + workspace_view::save_settings (void) + { + gui_settings settings; + + settings.setValue (ws_column_state.key, + m_view->horizontalHeader ()->saveState ()); - m_model = model; -} + int sort_column = m_view->horizontalHeader ()->sortIndicatorSection (); + Qt::SortOrder sort_order = m_view->horizontalHeader ()->sortIndicatorOrder (); + settings.setValue (ws_sort_column.key, sort_column); + settings.setValue (ws_sort_order.key, sort_order); -void -workspace_view::notice_settings (const gui_settings *settings) -{ - m_model->notice_settings (settings); // update colors of model first + settings.setValue (ws_filter_active.key, m_filter_checkbox->isChecked ()); + settings.setValue (ws_filter_shown.key, m_filter_shown); - for (int i = 0; i < ws_columns_shown.length (); i++) - m_view->setColumnHidden (i + 1, ! settings->value (ws_columns_shown_keys.at (i), true).toBool ()); - - QString tool_tip; + QStringList mru; + for (int i = 0; i < m_filter->count (); i++) + mru.append (m_filter->itemText (i)); + settings.setValue (ws_mru_list.key, mru); - if (settings->value (ws_enable_colors).toBool () - && ! settings->value (ws_hide_tool_tips).toBool ()) - { - tool_tip = QString (tr ("View the variables in the active workspace.
")); - tool_tip += QString (tr ("Colors for variable attributes:")); + settings.sync (); + + octave_dock_widget::save_settings (); + } - for (int i = 0; i < ws_colors_count; i++) - { - tool_tip += - QString (R"(
%3
)") - .arg (m_model->storage_class_color (i).name ()) - .arg (m_model->storage_class_color (i + ws_colors_count).name ()) - .arg (QCoreApplication::translate ("octave::settings_dialog", - ws_color_names.at (i).toStdString ().data ())); - } - } - - setToolTip (tool_tip); -} + void workspace_view::set_filter_focus (bool focus) + { + if (focus) + { + m_filter->setFocus (); + setFocusProxy (m_filter); + } + else + { + m_view->setFocus (); + setFocusProxy (m_view); + } + } -void -workspace_view::save_settings (void) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (! settings) - return; + void + workspace_view::filter_update (const QString& expression) + { + m_filter_model.setFilterWildcard (expression); + handle_model_changed (); + } - settings->setValue (ws_column_state.key, - m_view->horizontalHeader ()->saveState ()); - - int sort_column = m_view->horizontalHeader ()->sortIndicatorSection (); - Qt::SortOrder sort_order = m_view->horizontalHeader ()->sortIndicatorOrder (); - settings->setValue (ws_sort_column.key, sort_column); - settings->setValue (ws_sort_order.key, sort_order); - - settings->setValue (ws_filter_active.key, m_filter_checkbox->isChecked ()); - settings->setValue (ws_filter_shown.key, m_filter_shown); + void + workspace_view::filter_activate (bool state) + { + m_filter->setEnabled (state); + m_filter_model.setDynamicSortFilter (state); - QStringList mru; - for (int i = 0; i < m_filter->count (); i++) - mru.append (m_filter->itemText (i)); - settings->setValue (ws_mru_list.key, mru); + if (state) + filter_update (m_filter->currentText ()); + else + filter_update (QString ()); - settings->sync (); - - octave_dock_widget::save_settings (); -} + set_filter_focus (state); + } -void workspace_view::set_filter_focus (bool focus) -{ - if (focus) - { - m_filter->setFocus (); - setFocusProxy (m_filter); - } - else - { - m_view->setFocus (); - setFocusProxy (m_view); - } -} + void + workspace_view::update_filter_history (void) + { + QString text = m_filter->currentText (); // get current text + int index = m_filter->findText (text); // and its actual index + + if (index > -1) + m_filter->removeItem (index); // remove if already existing -void -workspace_view::filter_update (const QString& expression) -{ - m_filter_model.setFilterWildcard (expression); - handle_model_changed (); -} + m_filter->insertItem (0, text); // (re)insert at beginning + m_filter->setCurrentIndex (0); + } -void -workspace_view::filter_activate (bool state) -{ - m_filter->setEnabled (state); - m_filter_model.setDynamicSortFilter (state); + void + workspace_view::header_contextmenu_requested (const QPoint& mpos) + { + QMenu menu (this); + QSignalMapper sig_mapper (this); - if (state) - filter_update (m_filter->currentText ()); - else - filter_update (QString ()); - - set_filter_focus (state); -} + gui_settings settings; -void -workspace_view::update_filter_history (void) -{ - QString text = m_filter->currentText (); // get current text - int index = m_filter->findText (text); // and its actual index - - if (index > -1) - m_filter->removeItem (index); // remove if already existing + for (int i = 0; i < ws_columns_shown.length (); i++) + { + QAction *action + = menu.addAction (tr (ws_columns_shown.at (i).toStdString ().data ()), + &sig_mapper, SLOT (map ())); + sig_mapper.setMapping (action, i); + action->setCheckable (true); + action->setChecked (settings.value (ws_columns_shown_keys.at (i), true).toBool ()); + } - m_filter->insertItem (0, text); // (re)insert at beginning - m_filter->setCurrentIndex (0); -} - -void -workspace_view::header_contextmenu_requested (const QPoint& mpos) -{ - QMenu menu (this); - QSignalMapper sig_mapper (this); + // FIXME: We could use + // + // connect (&m_sig_mapper, QOverload::of (&QSignalMapper::mapped), + // this, &workspace_view::toggle_header); + // + // but referring to QSignalMapper::mapped will generate deprecated + // function warnings from GCC. We could also use + // + // connect (&m_sig_mapper, &QSignalMapper::mappedInt, + // this, &workspace_view::toggle_header); + // + // but the function mappedInt was not introduced until Qt 5.15 so + // we'll need a feature test. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + connect (&sig_mapper, SIGNAL (mapped (int)), + this, SLOT (toggle_header (int))); + + menu.exec (m_view->mapToGlobal (mpos)); + } - for (int i = 0; i < ws_columns_shown.length (); i++) - { - QAction *action - = menu.addAction (tr (ws_columns_shown.at (i).toStdString ().data ()), - &sig_mapper, SLOT (map ())); - sig_mapper.setMapping (action, i); - action->setCheckable (true); - action->setChecked (settings->value (ws_columns_shown_keys.at (i), true).toBool ()); - } + void + workspace_view::toggle_header (int col) + { + gui_settings settings; + + QString key = ws_columns_shown_keys.at (col); + bool shown = settings.value (key, true).toBool (); - // FIXME: We could use - // - // connect (&m_sig_mapper, QOverload::of (&QSignalMapper::mapped), - // this, &workspace_view::toggle_header); - // - // but referring to QSignalMapper::mapped will generate deprecated - // function warnings from GCC. We could also use - // - // connect (&m_sig_mapper, &QSignalMapper::mappedInt, - // this, &workspace_view::toggle_header); - // - // but the function mappedInt was not introduced until Qt 5.15 so - // we'll need a feature test. + m_view->setColumnHidden (col + 1, shown); + + settings.setValue (key, ! shown); + settings.sync (); + + octave_dock_widget::save_settings (); + } + + void + workspace_view::contextmenu_requested (const QPoint& qpos) + { + QMenu menu (this); - connect (&sig_mapper, SIGNAL (mapped (int)), - this, SLOT (toggle_header (int))); + QModelIndex index = m_view->indexAt (qpos); - menu.exec (m_view->mapToGlobal (mpos)); -} + // if it isn't Local, Global etc, allow the ctx menu + if (index.isValid () && index.column () == 0) + { + QString var_name = get_var_name (index); -void -workspace_view::toggle_header (int col) -{ - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + menu.addAction (tr ("Open in Variable Editor"), this, + &workspace_view::handle_contextmenu_edit); - QString key = ws_columns_shown_keys.at (col); - bool shown = settings->value (key, true).toBool (); + menu.addAction (tr ("Copy name"), this, + &workspace_view::handle_contextmenu_copy); - m_view->setColumnHidden (col + 1, shown); + menu.addAction (tr ("Copy value"), this, + &workspace_view::handle_contextmenu_copy_value); - settings->setValue (key, ! shown); - settings->sync (); - - octave_dock_widget::save_settings (); -} - -void -workspace_view::contextmenu_requested (const QPoint& qpos) -{ - QMenu menu (this); + QAction *rename + = menu.addAction (tr ("Rename"), this, + &workspace_view::handle_contextmenu_rename); - QModelIndex index = m_view->indexAt (qpos); + // Use m_model here instead of using "m_view->model ()" because + // that points to the proxy model. + if (! m_model->is_top_level ()) + { + rename->setDisabled (true); + rename->setToolTip (tr ("Only top-level symbols may be renamed")); + } - // if it isn't Local, Global etc, allow the ctx menu - if (index.isValid () && index.column () == 0) - { - QString var_name = get_var_name (index); + menu.addAction ("Clear " + var_name, this, + &workspace_view::handle_contextmenu_clear); - menu.addAction (tr ("Open in Variable Editor"), this, - &workspace_view::handle_contextmenu_edit); + menu.addSeparator (); - menu.addAction (tr ("Copy name"), this, - &workspace_view::handle_contextmenu_copy); + menu.addAction ("disp (" + var_name + ')', this, + &workspace_view::handle_contextmenu_disp); - menu.addAction (tr ("Copy value"), this, - &workspace_view::handle_contextmenu_copy_value); + menu.addAction ("plot (" + var_name + ')', this, + &workspace_view::handle_contextmenu_plot); - QAction *rename - = menu.addAction (tr ("Rename"), this, - &workspace_view::handle_contextmenu_rename); + menu.addAction ("stem (" + var_name + ')', this, + &workspace_view::handle_contextmenu_stem); + + menu.addSeparator (); + + } - // Use m_model here instead of using "m_view->model ()" because - // that points to the proxy model. - if (! m_model->is_top_level ()) - { - rename->setDisabled (true); - rename->setToolTip (tr ("Only top-level symbols may be renamed")); - } - - menu.addAction ("Clear " + var_name, this, - &workspace_view::handle_contextmenu_clear); + if (m_filter_shown) + menu.addAction (tr ("Hide filter"), this, + &workspace_view::handle_contextmenu_filter); + else + menu.addAction (tr ("Show filter"), this, + &workspace_view::handle_contextmenu_filter); - menu.addSeparator (); - - menu.addAction ("disp (" + var_name + ')', this, - &workspace_view::handle_contextmenu_disp); + menu.exec (m_view->mapToGlobal (qpos)); + } - menu.addAction ("plot (" + var_name + ')', this, - &workspace_view::handle_contextmenu_plot); - - menu.addAction ("stem (" + var_name + ')', this, - &workspace_view::handle_contextmenu_stem); + void + workspace_view::handle_contextmenu_copy (void) + { + QModelIndex index = m_view->currentIndex (); - menu.addSeparator (); - - } + if (index.isValid ()) + { + QString var_name = get_var_name (index); - if (m_filter_shown) - menu.addAction (tr ("Hide filter"), this, - &workspace_view::handle_contextmenu_filter); - else - menu.addAction (tr ("Show filter"), this, - &workspace_view::handle_contextmenu_filter); + QClipboard *clipboard = QApplication::clipboard (); + + clipboard->setText (var_name); + } + } - menu.exec (m_view->mapToGlobal (qpos)); -} + void + workspace_view::handle_contextmenu_copy_value (void) + { + QModelIndex index = m_view->currentIndex (); -void -workspace_view::handle_contextmenu_copy (void) -{ - QModelIndex index = m_view->currentIndex (); + if (index.isValid ()) + emit copy_variable_value_to_clipboard (get_var_name (index)); + } - if (index.isValid ()) - { - QString var_name = get_var_name (index); - - QClipboard *clipboard = QApplication::clipboard (); + void + workspace_view::handle_contextmenu_rename (void) + { + QModelIndex index = m_view->currentIndex (); - clipboard->setText (var_name); - } -} + if (index.isValid ()) + { + QString var_name = get_var_name (index); -void -workspace_view::handle_contextmenu_copy_value (void) -{ - QModelIndex index = m_view->currentIndex (); + QInputDialog *inputDialog = new QInputDialog (); - if (index.isValid ()) - emit copy_variable_value_to_clipboard (get_var_name (index)); -} + inputDialog->setOptions (QInputDialog::NoButtons); + + bool ok = false; -void -workspace_view::handle_contextmenu_rename (void) -{ - QModelIndex index = m_view->currentIndex (); + QString new_name + = inputDialog->getText (nullptr, "Rename Variable", "New name:", + QLineEdit::Normal, var_name, &ok); - if (index.isValid ()) - { - QString var_name = get_var_name (index); + if (ok && ! new_name.isEmpty ()) + emit rename_variable_signal (var_name, new_name); + } + } - QInputDialog *inputDialog = new QInputDialog (); - - inputDialog->setOptions (QInputDialog::NoButtons); - - bool ok = false; + void + workspace_view::handle_contextmenu_edit (void) + { + QModelIndex index = m_view->currentIndex (); - QString new_name - = inputDialog->getText (nullptr, "Rename Variable", "New name:", - QLineEdit::Normal, var_name, &ok); - - if (ok && ! new_name.isEmpty ()) - emit rename_variable_signal (var_name, new_name); - } -} + if (index.isValid ()) + emit edit_variable_signal (get_var_name (index)); + } -void -workspace_view::handle_contextmenu_edit (void) -{ - QModelIndex index = m_view->currentIndex (); + void + workspace_view::handle_contextmenu_clear (void) + { + relay_contextmenu_command ("clear", true); + } - if (index.isValid ()) - emit edit_variable_signal (get_var_name (index)); -} - -void -workspace_view::handle_contextmenu_clear (void) -{ - relay_contextmenu_command ("clear", true); -} + void + workspace_view::handle_contextmenu_disp (void) + { + relay_contextmenu_command ("disp"); + } -void -workspace_view::handle_contextmenu_disp (void) -{ - relay_contextmenu_command ("disp"); -} - -void -workspace_view::handle_contextmenu_plot (void) -{ - relay_contextmenu_command ("figure (); plot"); -} + void + workspace_view::handle_contextmenu_plot (void) + { + relay_contextmenu_command ("figure (); plot"); + } -void -workspace_view::handle_contextmenu_stem (void) -{ - relay_contextmenu_command ("figure (); stem"); -} + void + workspace_view::handle_contextmenu_stem (void) + { + relay_contextmenu_command ("figure (); stem"); + } -void -workspace_view::handle_contextmenu_filter (void) -{ - m_filter_shown = ! m_filter_shown; - m_filter_widget->setVisible (m_filter_shown); + void + workspace_view::handle_contextmenu_filter (void) + { + m_filter_shown = ! m_filter_shown; + m_filter_widget->setVisible (m_filter_shown); - set_filter_focus (m_filter_shown && m_filter_checkbox->isChecked ()); -} + set_filter_focus (m_filter_shown && m_filter_checkbox->isChecked ()); + } -void -workspace_view::handle_model_changed (void) -{ - // m_view->resizeRowsToContents (); - // Just modify those rows that have been added rather than go through - // the whole list. For-loop test will handle when number of rows reduced. - QFontMetrics fm = m_view->fontMetrics (); - int row_height = fm.height (); - int new_row_count = m_filter_model.rowCount (); - for (int i = m_view_previous_row_count; i < new_row_count; i++) - m_view->setRowHeight (i, row_height); - m_view_previous_row_count = new_row_count; -} + void + workspace_view::handle_model_changed (void) + { + // m_view->resizeRowsToContents (); + // Just modify those rows that have been added rather than go through + // the whole list. For-loop test will handle when number of rows reduced. + QFontMetrics fm = m_view->fontMetrics (); + int row_height = fm.height (); + int new_row_count = m_filter_model.rowCount (); + for (int i = m_view_previous_row_count; i < new_row_count; i++) + m_view->setRowHeight (i, row_height); + m_view_previous_row_count = new_row_count; + } -void -workspace_view::copyClipboard () -{ - if (m_view->hasFocus ()) - handle_contextmenu_copy (); -} + void + workspace_view::copyClipboard () + { + if (m_view->hasFocus ()) + handle_contextmenu_copy (); + } -void -workspace_view::selectAll () -{ - if (m_view->hasFocus ()) - m_view->selectAll (); -} + void + workspace_view::selectAll () + { + if (m_view->hasFocus ()) + m_view->selectAll (); + } -void -workspace_view::relay_contextmenu_command (const QString& cmdname, bool str) -{ - QModelIndex index = m_view->currentIndex (); + void + workspace_view::relay_contextmenu_command (const QString& cmdname, bool str) + { + QModelIndex index = m_view->currentIndex (); - if (index.isValid ()) - { - QString var_name; + if (index.isValid ()) + { + QString var_name; - if (str) - var_name = "\'" + get_var_name (index) + "\'"; - else - var_name = get_var_name (index); + if (str) + var_name = "\'" + get_var_name (index) + "\'"; + else + var_name = get_var_name (index); - emit command_requested (cmdname + " (" + var_name + ");"); - } -} + emit command_requested (cmdname + " (" + var_name + ");"); + } + } -QString -workspace_view::get_var_name (const QModelIndex& index) -{ - // We are using a sort model proxy so m_model won't provide the - // correct ordering. + QString + workspace_view::get_var_name (const QModelIndex& index) + { + // We are using a sort model proxy so m_model won't provide the + // correct ordering. - QAbstractItemModel *m = m_view->model (); + QAbstractItemModel *m = m_view->model (); - QMap item_data - = m->itemData (index.sibling (index.row (), 0)); + QMap item_data + = m->itemData (index.sibling (index.row (), 0)); - return item_data[0].toString (); -} + return item_data[0].toString (); + } OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libgui/src/workspace-view.h --- a/libgui/src/workspace-view.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libgui/src/workspace-view.h Tue Dec 06 15:45:27 2022 -0500 @@ -39,95 +39,95 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class base_qobject; + class base_qobject; -class workspace_view : public octave_dock_widget -{ - Q_OBJECT + class workspace_view : public octave_dock_widget + { + Q_OBJECT -public: + public: - workspace_view (QWidget *parent, base_qobject& oct_qobj); + workspace_view (QWidget *parent, base_qobject& oct_qobj); - ~workspace_view (void) = default; + ~workspace_view (void) = default; -signals: + signals: - //! Signal that user had requested a command on a variable. + //! Signal that user had requested a command on a variable. - void command_requested (const QString& cmd); + void command_requested (const QString& cmd); - //! Signal that user wnats to copy a variable value to the - //! clipboard. + //! Signal that user wnats to copy a variable value to the + //! clipboard. - void copy_variable_value_to_clipboard (const QString&); + void copy_variable_value_to_clipboard (const QString&); - //! Signal that user wants to rename a variable. + //! Signal that user wants to rename a variable. - void rename_variable_signal (const QString&, const QString&); + void rename_variable_signal (const QString&, const QString&); - //! Signal that user wants to edit a variable. + //! Signal that user wants to edit a variable. - void edit_variable_signal (const QString&); + void edit_variable_signal (const QString&); -public slots: + public slots: - void setModel (workspace_model *model); + void setModel (workspace_model *model); - void notice_settings (const gui_settings *); + void notice_settings (void); - void save_settings (void); + void save_settings (void); -protected slots: + protected slots: - void filter_update (const QString& expression); - void filter_activate (bool enable); - void update_filter_history (void); + void filter_update (const QString& expression); + void filter_activate (bool enable); + void update_filter_history (void); - void header_contextmenu_requested (const QPoint& mpos); + void header_contextmenu_requested (const QPoint& mpos); - void toggle_header (int column); + void toggle_header (int column); - void contextmenu_requested (const QPoint& pos); + void contextmenu_requested (const QPoint& pos); - void handle_contextmenu_copy (void); - void handle_contextmenu_copy_value (void); - void handle_contextmenu_rename (void); - void handle_contextmenu_edit (void); - void handle_contextmenu_clear (void); - void handle_contextmenu_disp (void); - void handle_contextmenu_plot (void); - void handle_contextmenu_stem (void); - void handle_contextmenu_filter (void); + void handle_contextmenu_copy (void); + void handle_contextmenu_copy_value (void); + void handle_contextmenu_rename (void); + void handle_contextmenu_edit (void); + void handle_contextmenu_clear (void); + void handle_contextmenu_disp (void); + void handle_contextmenu_plot (void); + void handle_contextmenu_stem (void); + void handle_contextmenu_filter (void); -public slots: + public slots: - void handle_model_changed (void); + void handle_model_changed (void); - void copyClipboard (void); - void selectAll (void); + void copyClipboard (void); + void selectAll (void); -private: + private: - void relay_contextmenu_command (const QString& cmdname, bool str = false); - void set_filter_focus (bool focus); + void relay_contextmenu_command (const QString& cmdname, bool str = false); + void set_filter_focus (bool focus); - QString get_var_name (const QModelIndex& index); + QString get_var_name (const QModelIndex& index); - QTableView *m_view; - int m_view_previous_row_count; + QTableView *m_view; + int m_view_previous_row_count; - // We are using a sort model proxy so m_model won't provide the - // correct ordering. It is still OK to use this pointer to access - // other info attached to the model, for example the scope or colors. - workspace_model *m_model; + // We are using a sort model proxy so m_model won't provide the + // correct ordering. It is still OK to use this pointer to access + // other info attached to the model, for example the scope or colors. + workspace_model *m_model; - QSortFilterProxyModel m_filter_model; - QCheckBox *m_filter_checkbox; - QComboBox *m_filter; - QWidget *m_filter_widget; - bool m_filter_shown; -}; + QSortFilterProxyModel m_filter_model; + QCheckBox *m_filter_checkbox; + QComboBox *m_filter; + QWidget *m_filter_widget; + bool m_filter_shown; + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/c-file-ptr-stream.h --- a/libinterp/corefcn/c-file-ptr-stream.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/c-file-ptr-stream.h Tue Dec 06 15:45:27 2022 -0500 @@ -232,39 +232,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::i_c_file_ptr_stream' instead") -typedef octave::i_c_file_ptr_stream i_c_file_ptr_stream; - -OCTAVE_DEPRECATED (7, "use 'octave::o_c_file_ptr_stream' instead") -typedef octave::o_c_file_ptr_stream o_c_file_ptr_stream; - -OCTAVE_DEPRECATED (7, "use 'octave::io_c_file_ptr_stream' instead") -typedef octave::io_c_file_ptr_stream io_c_file_ptr_stream; - -// FIXME: HAVE_ZLIB is not defined here because we do not (and should -// not) include config.h in this header file. We need to find a way to -// define this interface without exposing gzFile. Should this be a -// private header that can only be used if included after config.h in an -// Octave source file and not inside another header file? - -# if defined (HAVE_ZLIB) - -OCTAVE_DEPRECATED (7, "use 'octave::i_c_zfile_ptr_stream' instead") -typedef octave::c_file_ptr_stream - i_c_zfile_ptr_stream; - -OCTAVE_DEPRECATED (7, "use 'octave::o_c_zfile_ptr_stream' instead") -typedef octave::c_file_ptr_stream - o_c_zfile_ptr_stream; - -OCTAVE_DEPRECATED (7, "use 'octave::io_c_zfile_ptr_stream' instead") -typedef octave::c_file_ptr_stream - io_c_zfile_ptr_stream; - -# endif - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/data.cc --- a/libinterp/corefcn/data.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/data.cc Tue Dec 06 15:45:27 2022 -0500 @@ -6523,7 +6523,7 @@ (@dots{}((@var{A1} * @var{A2}) * @var{A3}) * @dots{}) @end example -@seealso{times, plus, minus, rdivide, mrdivide, mldivide, mpower} +@seealso{times, plus, minus, rdivide, mrdivide, mldivide, mpower, tensorprod} @end deftypefn */) { return binary_assoc_op_defun_body (octave_value::op_mul, diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/data.h --- a/libinterp/corefcn/data.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/data.h Tue Dec 06 15:45:27 2022 -0500 @@ -41,14 +41,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::do_class_concat' instead") -inline OCTINTERP_API octave_value -do_class_concat (const octave_value_list& ovl, const std::string& cattype, - int dim) -{ - return octave::do_class_concat (ovl, cattype, dim); -} #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/dot.cc --- a/libinterp/corefcn/dot.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/dot.cc Tue Dec 06 15:45:27 2022 -0500 @@ -91,7 +91,7 @@ the result is equivalent to @code{@var{X}' * @var{Y}}. Although, @code{dot} is defined for integer arrays, the output may differ from the expected result due to the limited range of integer objects. -@seealso{cross, divergence} +@seealso{cross, divergence, tensorprod} @end deftypefn */) { int nargin = args.length (); diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/error.cc --- a/libinterp/corefcn/error.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/error.cc Tue Dec 06 15:45:27 2022 -0500 @@ -901,17 +901,6 @@ last_error_stack (make_stack_map (ee.stack_info ())); } -// DEPRECATED in Octave 7. -void error_system::display_exception (const execution_exception& ee, - std::ostream& os) const -{ - if (m_beep_on_error) - os << "\a"; - - ee.display (octave_diary); - ee.display (os); -} - void error_system::display_exception (const execution_exception& ee) const { // FIXME: How should we handle beep_on_error? diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/error.h --- a/libinterp/corefcn/error.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/error.h Tue Dec 06 15:45:27 2022 -0500 @@ -334,13 +334,6 @@ OCTINTERP_API void save_exception (const execution_exception& ee); - // FIXME - //#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "second argument is no longer accepted") - OCTINTERP_API void display_exception (const execution_exception& ee, - std::ostream& os) const; - //#endif - OCTINTERP_API void display_exception (const execution_exception& ee) const; private: @@ -573,44 +566,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::defun_usage_message' instead") -inline void defun_usage_message (const std::string& msg) -{ - octave::defun_usage_message (msg); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_warning_state' instead") -inline octave_value_list -set_warning_state (const std::string& id, const std::string& state) -{ - return octave::set_warning_state (id, state); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_warning_state' instead") -inline octave_value_list set_warning_state (const octave_value_list& args) -{ - return octave::set_warning_state (args); -} - -OCTAVE_DEPRECATED (7, "use 'octave::warning_enabled' instead") -inline int warning_enabled (const std::string& id) -{ - return octave::warning_enabled (id); -} - -OCTAVE_DEPRECATED (7, "use 'octave::disable_warning' instead") -inline void disable_warning (const std::string& id) -{ - octave::disable_warning (id); -} - -OCTAVE_DEPRECATED (7, "use 'octave::interpreter_try' instead") -inline void interpreter_try (octave::unwind_protect& uwp) -{ - octave::interpreter_try (uwp); -} - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/graphics.in.h --- a/libinterp/corefcn/graphics.in.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/graphics.in.h Tue Dec 06 15:45:27 2022 -0500 @@ -6958,164 +6958,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::base_scaler' instead") -typedef octave::base_scaler base_scaler; - -OCTAVE_DEPRECATED (7, "use 'octave::lin_scaler' instead") -typedef octave::lin_scaler lin_scaler; - -OCTAVE_DEPRECATED (7, "use 'octave::log_scaler' instead") -typedef octave::log_scaler log_scaler; - -OCTAVE_DEPRECATED (7, "use 'octave::neg_log_scaler' instead") -typedef octave::neg_log_scaler neg_log_scaler; - -OCTAVE_DEPRECATED (7, "use 'octave::scaler' instead") -typedef octave::scaler scaler; - -OCTAVE_DEPRECATED (7, "use 'octave::base_property' instead") -typedef octave::base_property base_property; - -OCTAVE_DEPRECATED (7, "use 'octave::string_property' instead") -typedef octave::string_property string_property; - -OCTAVE_DEPRECATED (7, "use 'octave::string_array_property' instead") -typedef octave::string_array_property string_array_property; - -OCTAVE_DEPRECATED (7, "use 'octave::text_label_property' instead") -typedef octave::text_label_property text_label_property; - -OCTAVE_DEPRECATED (7, "use 'octave::radio_values' instead") -typedef octave::radio_values radio_values; - -OCTAVE_DEPRECATED (7, "use 'octave::radio_property' instead") -typedef octave::radio_property radio_property; - -OCTAVE_DEPRECATED (7, "use 'octave::color_values' instead") -typedef octave::color_values color_values; - -OCTAVE_DEPRECATED (7, "use 'octave::color_property' instead") -typedef octave::color_property color_property; - -OCTAVE_DEPRECATED (7, "use 'octave::double_property' instead") -typedef octave::double_property double_property; - -OCTAVE_DEPRECATED (7, "use 'octave::double_radio_property' instead") -typedef octave::double_radio_property double_radio_property; - -OCTAVE_DEPRECATED (7, "use 'octave::array_property' instead") -typedef octave::array_property array_property; - -OCTAVE_DEPRECATED (7, "use 'octave::row_vector_property' instead") -typedef octave::row_vector_property row_vector_property; - -OCTAVE_DEPRECATED (7, "use 'octave::bool_property' instead") -typedef octave::bool_property bool_property; - -OCTAVE_DEPRECATED (7, "use 'octave::handle_property' instead") -typedef octave::handle_property handle_property; - -OCTAVE_DEPRECATED (7, "use 'octave::any_property' instead") -typedef octave::any_property any_property; - -OCTAVE_DEPRECATED (7, "use 'octave::children_property' instead") -typedef octave::children_property children_property; - -OCTAVE_DEPRECATED (7, "use 'octave::callback_property' instead") -typedef octave::callback_property callback_property; - -OCTAVE_DEPRECATED (7, "use 'octave::property' instead") -typedef octave::property property; - -OCTAVE_DEPRECATED (7, "use 'octave::pval_vector' instead") -typedef octave::pval_vector pval_vector; - -OCTAVE_DEPRECATED (7, "use 'octave::property_list' instead") -typedef octave::property_list property_list; - -OCTAVE_DEPRECATED (7, "use 'octave::base_properties' instead") -typedef octave::base_properties base_properties; - -OCTAVE_DEPRECATED (7, "use 'octave::base_graphics_object' instead") -typedef octave::base_graphics_object base_graphics_object; - -OCTAVE_DEPRECATED (7, "use 'octave::graphics_object' instead") -typedef octave::graphics_object graphics_object; - -OCTAVE_DEPRECATED (7, "use 'octave::root_figure' instead") -typedef octave::root_figure root_figure; - -OCTAVE_DEPRECATED (7, "use 'octave::figure' instead") -typedef octave::figure figure; - -OCTAVE_DEPRECATED (7, "use 'octave::graphics_xform' instead") -typedef octave::graphics_xform graphics_xform; - -OCTAVE_DEPRECATED (7, "use 'octave::axes' instead") -typedef octave::axes axes; - -OCTAVE_DEPRECATED (7, "use 'octave::line' instead") -typedef octave::line line; - -OCTAVE_DEPRECATED (7, "use 'octave::text' instead") -typedef octave::text text; - -OCTAVE_DEPRECATED (7, "use 'octave::image' instead") -typedef octave::image image; - -OCTAVE_DEPRECATED (7, "use 'octave::light' instead") -typedef octave::light light; - -OCTAVE_DEPRECATED (7, "use 'octave::patch' instead") -typedef octave::patch patch; - -OCTAVE_DEPRECATED (7, "use 'octave::scatter' instead") -typedef octave::scatter scatter; - -OCTAVE_DEPRECATED (7, "use 'octave::surface' instead") -typedef octave::surface surface; - -OCTAVE_DEPRECATED (7, "use 'octave::hggroup' instead") -typedef octave::hggroup hggroup; - -OCTAVE_DEPRECATED (7, "use 'octave::uimenu' instead") -typedef octave::uimenu uimenu; - -OCTAVE_DEPRECATED (7, "use 'octave::uicontextmenu' instead") -typedef octave::uicontextmenu uicontextmenu; - -OCTAVE_DEPRECATED (7, "use 'octave::uicontrol' instead") -typedef octave::uicontrol uicontrol; - -OCTAVE_DEPRECATED (7, "use 'octave::uibuttongroup' instead") -typedef octave::uibuttongroup uibuttongroup; - -OCTAVE_DEPRECATED (7, "use 'octave::uipanel' instead") -typedef octave::uipanel uipanel; - -OCTAVE_DEPRECATED (7, "use 'octave::uitable' instead") -typedef octave::uitable uitable; - -OCTAVE_DEPRECATED (7, "use 'octave::uitoolbar' instead") -typedef octave::uitoolbar uitoolbar; - -OCTAVE_DEPRECATED (7, "use 'octave::uipushtool' instead") -typedef octave::uipushtool uipushtool; - -OCTAVE_DEPRECATED (7, "use 'octave::uitoggletool' instead") -typedef octave::uitoggletool uitoggletool; - -OCTAVE_DEPRECATED (7, "use 'octave::base_graphics_event' instead") -typedef octave::base_graphics_event base_graphics_event; - -OCTAVE_DEPRECATED (7, "use 'octave::graphics_event' instead") -typedef octave::graphics_event graphics_event; - -OCTAVE_DEPRECATED (7, "use 'octave::gh_manager' instead") -typedef octave::gh_manager gh_manager; - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/hook-fcn.h --- a/libinterp/corefcn/hook-fcn.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/hook-fcn.h Tue Dec 06 15:45:27 2022 -0500 @@ -214,21 +214,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::base_hook_function' instead") -typedef octave::base_hook_function base_hook_function; - -OCTAVE_DEPRECATED (7, "use 'octave::hook_function' instead") -typedef octave::hook_function hook_function; - -OCTAVE_DEPRECATED (7, "use 'octave::named_hook_function' instead") -typedef octave::named_hook_function named_hook_function; - -OCTAVE_DEPRECATED (7, "use 'octave::fcn_handle_hook_function' instead") -typedef octave::fcn_handle_hook_function fcn_handle_hook_function; - -OCTAVE_DEPRECATED (7, "use 'octave::hook_function_list' instead") -typedef octave::hook_function_list hook_function_list; #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/kron.cc --- a/libinterp/corefcn/kron.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/kron.cc Tue Dec 06 15:45:27 2022 -0500 @@ -275,6 +275,7 @@ @noindent Since the Kronecker product is associative, this is well-defined. +@seealso{tensorprod} @end deftypefn */) { int nargin = args.length (); diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/load-save.cc --- a/libinterp/corefcn/load-save.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/load-save.cc Tue Dec 06 15:45:27 2022 -0500 @@ -2060,13 +2060,3 @@ } OCTAVE_END_NAMESPACE(octave) - -// DEPRECATED in Octave 7 - -void -dump_octave_core (void) -{ - octave::load_save_system& load_save_sys = octave::__get_load_save_system__ (); - - load_save_sys.dump_octave_core (); -} diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/load-save.h --- a/libinterp/corefcn/load-save.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/load-save.h Tue Dec 06 15:45:27 2022 -0500 @@ -294,7 +294,4 @@ OCTAVE_END_NAMESPACE(octave) -OCTAVE_DEPRECATED (7, "use 'load_save_system::dump_octave_core' instead") -extern OCTINTERP_API void dump_octave_core (void); - #endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/ls-ascii-helper.h --- a/libinterp/corefcn/ls-ascii-helper.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/ls-ascii-helper.h Tue Dec 06 15:45:27 2022 -0500 @@ -44,29 +44,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::skip_until_newline' instead") -inline void -skip_until_newline (std::istream& is, bool keep_newline = false) -{ - return octave::skip_until_newline (is, keep_newline); -} - -OCTAVE_DEPRECATED (7, "use 'octave::skip_preceding_newline' instead") -inline void -skip_preceeding_newline (std::istream& is) -{ - return octave::skip_preceeding_newline (is); -} - -OCTAVE_DEPRECATED (7, "use 'octave::read_until_newline' instead") -inline std::string -read_until_newline (std::istream& is, bool keep_newline = false) -{ - return octave::read_until_newline (is, keep_newline); -} - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/ls-utils.h --- a/libinterp/corefcn/ls-utils.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/ls-utils.h Tue Dec 06 15:45:27 2022 -0500 @@ -40,22 +40,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::get_save_type' instead") -inline save_type -get_save_type (double max_val, double min_val) -{ - return octave::get_save_type (max_val, min_val); -} - -OCTAVE_DEPRECATED (7, "use 'octave::get_save_type' instead") -inline save_type -get_save_type (float max_val, float min_val) -{ - return octave::get_save_type (max_val, min_val); -} - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/oct-fstrm.h --- a/libinterp/corefcn/oct-fstrm.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/oct-fstrm.h Tue Dec 06 15:45:27 2022 -0500 @@ -90,11 +90,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::fstream' instead") -typedef octave::fstream octave_fstream; - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/oct-hdf5-types.h --- a/libinterp/corefcn/oct-hdf5-types.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/oct-hdf5-types.h Tue Dec 06 15:45:27 2022 -0500 @@ -38,16 +38,6 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::check_hdf5_types' instead") -inline bool check_hdf5_types (bool warn = true) -{ - return octave::check_hdf5_types (warn); -} - -#endif - #endif // Available for C and C++. diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/oct-iostrm.h --- a/libinterp/corefcn/oct-iostrm.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/oct-iostrm.h Tue Dec 06 15:45:27 2022 -0500 @@ -161,17 +161,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::base_iostream' instead") -typedef octave::base_iostream octave_base_iostream; - -OCTAVE_DEPRECATED (7, "use 'octave::istream' instead") -typedef octave::istream octave_istream; - -OCTAVE_DEPRECATED (7, "use 'octave::ostream' instead") -typedef octave::ostream octave_ostream; - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/oct-prcstrm.h --- a/libinterp/corefcn/oct-prcstrm.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/oct-prcstrm.h Tue Dec 06 15:45:27 2022 -0500 @@ -98,14 +98,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::octave_iprocstream' instead") -typedef octave::octave_iprocstream octave_iprocstream; - -OCTAVE_DEPRECATED (7, "use 'octave::octave_oprocstream' instead") -typedef octave::octave_oprocstream octave_oprocstream; - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/oct-procbuf.h --- a/libinterp/corefcn/oct-procbuf.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/oct-procbuf.h Tue Dec 06 15:45:27 2022 -0500 @@ -83,11 +83,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use octave::procbuf' instead") -typedef octave::procbuf procbuf; - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/oct-stdstrm.h --- a/libinterp/corefcn/oct-stdstrm.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/oct-stdstrm.h Tue Dec 06 15:45:27 2022 -0500 @@ -199,14 +199,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::stdiostream' instead") -typedef octave::stdiostream octave_stdiostream; - -OCTAVE_DEPRECATED (7, "use 'octave::zstdiostream' instead") -typedef octave::zstdiostream octave_zstdiostream; - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/oct-stream.cc --- a/libinterp/corefcn/oct-stream.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/oct-stream.cc Tue Dec 06 15:45:27 2022 -0500 @@ -4288,6 +4288,9 @@ { T value = T (); + is >> std::ws; // skip through whitespace and advance stream pointer + std::streampos pos = is.tellg (); + switch (fmt.type) { case 'o': @@ -4301,11 +4304,7 @@ case 'i': { - int c1 = std::istream::traits_type::eof (); - - while (is && (c1 = is.get ()) != std::istream::traits_type::eof () - && isspace (c1)) - ; // skip whitespace + int c1 = is.get (); if (c1 != std::istream::traits_type::eof ()) { @@ -4354,18 +4353,33 @@ break; } - // If conversion produces an integer that overflows, failbit is set but - // value is non-zero. We want to treat this case as success, so clear - // failbit from the stream state to keep going. - // FIXME: Maybe set error state on octave stream as above? Matlab does - // *not* indicate an error message on overflow. - if ((is.rdstate () & std::ios::failbit) && value != T ()) - is.clear (is.rdstate () & ~std::ios::failbit); - - // Only copy the converted value if the stream is in a state where we - // want to continue reading. - if (! (is.rdstate () & std::ios::failbit)) - *valptr = value; + std::ios::iostate status = is.rdstate (); + if (! (status & std::ios::failbit)) + { + // Copy the converted value if the stream is in a good state + *valptr = value; + } + else + { + if (value != T ()) + { + // If conversion produces an integer that overflows, failbit is set + // but value is non-zero. We want to treat this case as success, + // so clear failbit from the stream state to keep going. + // FIXME: Maybe set error state on octave stream? Matlab does + // *not* indicate an error message on overflow. + is.clear (status & ~std::ios::failbit); + *valptr = value; + } + else + { + // True error. + // Reset stream to original position, clear eof bit, pass status on. + is.clear (); + is.seekg (pos); + is.setstate (status & ~std::ios_base::eofbit); + } + } return is; } @@ -4433,17 +4447,20 @@ case 'E': case 'G': { - int c1 = std::istream::traits_type::eof (); - - while (is && (c1 = is.get ()) != std::istream::traits_type::eof () - && isspace (c1)) - ; // skip whitespace - - if (c1 != std::istream::traits_type::eof ()) + is >> std::ws; // skip through whitespace and advance stream pointer + if (is.good ()) { - is.putback (c1); + std::streampos pos = is.tellg (); ref = read_value (is); + + std::ios::iostate status = is.rdstate (); + if (status & std::ios::failbit) + { + is.clear (); + is.seekg (pos); + is.setstate (status & ~std::ios_base::eofbit); + } } } break; @@ -4497,11 +4514,16 @@ { \ int c = std::istream::traits_type::eof (); \ \ + /* get all whitespace characters */ \ while (is && (c = is.get ()) != std::istream::traits_type::eof () \ && isspace (c)) \ { /* skip whitespace */ } \ \ - if (c != std::istream::traits_type::eof ()) \ + if (c == std::istream::traits_type::eof ()) \ + /* reset failbit at eof */ \ + is.clear (is.rdstate () & (~std::ios::failbit)); \ + else \ + /* put back non-whitespace character */ \ is.putback (c); \ } \ while (0) @@ -4566,8 +4588,8 @@ && (c = is.get ()) != std::istream::traits_type::eof ()) \ tmp[n++] = static_cast (c); \ \ - if (n > 0 && c == std::istream::traits_type::eof ()) \ - is.clear (); \ + if (c == std::istream::traits_type::eof ()) \ + is.clear (is.rdstate () & (~std::ios::failbit)); \ \ tmp.resize (n) @@ -4609,8 +4631,8 @@ tmp[n++] = static_cast (c); \ } \ \ - if (n > 0 && c == std::istream::traits_type::eof ()) \ - is.clear (); \ + if (c == std::istream::traits_type::eof ()) \ + is.clear (is.rdstate () & (~std::ios::failbit)); \ \ tmp.resize (n); \ } \ @@ -4623,15 +4645,13 @@ // This format must match a nonempty sequence of characters. #define BEGIN_CHAR_CLASS_CONVERSION() \ - int width = elt->width; \ + int width = (elt->width ? elt->width \ + : std::numeric_limits::max ()); \ \ std::string tmp; \ \ do \ { \ - if (! width) \ - width = std::numeric_limits::max (); \ - \ std::ostringstream buf; \ \ std::string char_class = elt->char_class; \ @@ -4642,29 +4662,39 @@ { \ int chars_read = 0; \ while (is && chars_read++ < width \ - && (c = is.get ()) != std::istream::traits_type::eof () \ - && char_class.find (c) != std::string::npos) \ - buf << static_cast (c); \ + && (c = is.get ()) != std::istream::traits_type::eof ()) \ + { \ + if (char_class.find (c) != std::string::npos) \ + buf << static_cast (c); \ + else \ + { \ + is.putback (c); \ + break; \ + } \ + } \ } \ else \ { \ int chars_read = 0; \ while (is && chars_read++ < width \ - && (c = is.get ()) != std::istream::traits_type::eof () \ - && char_class.find (c) == std::string::npos) \ - buf << static_cast (c); \ + && (c = is.get ()) != std::istream::traits_type::eof ()) \ + { \ + if (char_class.find (c) == std::string::npos) \ + buf << static_cast (c); \ + else \ + { \ + is.putback (c); \ + break; \ + } \ + } \ } \ \ - if (width == std::numeric_limits::max () \ - && c != std::istream::traits_type::eof ()) \ - is.putback (c); \ - \ tmp = buf.str (); \ \ if (tmp.empty ()) \ is.setstate (std::ios::failbit); \ else if (c == std::istream::traits_type::eof ()) \ - is.clear (); \ + is.clear (is.rdstate () & (~std::ios::failbit)); \ \ } \ while (0) @@ -4676,7 +4706,7 @@ tmp = string::u8_from_encoding (who, tmp, encoding ()); \ width = tmp.length (); \ \ - if (is) \ + if (is && width > 0) \ { \ int i = 0; \ \ @@ -5048,10 +5078,10 @@ // If it looks like we have a matching failure, then // reset the failbit in the stream state. - if (! is.eof () && is.rdstate () & std::ios::failbit) + if (is.rdstate () & std::ios::failbit) { - error (who, "format failed to match"); is.clear (is.rdstate () & (~std::ios::failbit)); + error (who, "format failed to match"); } // FIXME: is this the right thing to do? diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/oct-strstrm.h --- a/libinterp/corefcn/oct-strstrm.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/oct-strstrm.h Tue Dec 06 15:45:27 2022 -0500 @@ -194,17 +194,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::base_strstream' instead") -typedef octave::base_strstream octave_base_strstream; - -OCTAVE_DEPRECATED (7, "use 'octave::istrstream' instead") -typedef octave::istrstream octave_istrstream; - -OCTAVE_DEPRECATED (7, "use 'octave::ostrstream' instead") -typedef octave::ostrstream octave_ostrstream; - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/procstream.h --- a/libinterp/corefcn/procstream.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/procstream.h Tue Dec 06 15:45:27 2022 -0500 @@ -187,20 +187,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::procstreambase' instead") -typedef octave::procstreambase procstreambase; - -OCTAVE_DEPRECATED (7, "use 'octave::iprocstream' instead") -typedef octave::iprocstream iprocstream; - -OCTAVE_DEPRECATED (7, "use 'octave::oprocstream' instead") -typedef octave::oprocstream oprocstream; - -OCTAVE_DEPRECATED (7, "use 'octave::procstream' instead") -typedef octave::procstream procstream; - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/sparse-xdiv.h --- a/libinterp/corefcn/sparse-xdiv.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/sparse-xdiv.h Tue Dec 06 15:45:27 2022 -0500 @@ -104,207 +104,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline Matrix -xdiv (const Matrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const Matrix& a, const SparseComplexMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const ComplexMatrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const ComplexMatrix& a, const SparseComplexMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseMatrix -xdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseComplexMatrix -xdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseComplexMatrix -xdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseComplexMatrix -xdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b, - MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseMatrix -xdiv (const SparseMatrix& a, const DiagMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseComplexMatrix -xdiv (const SparseMatrix& a, const ComplexDiagMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseComplexMatrix -xdiv (const SparseComplexMatrix& a, const DiagMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseComplexMatrix -xdiv (const SparseComplexMatrix& a, const ComplexDiagMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline Matrix -x_el_div (double a, const SparseMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexMatrix -x_el_div (double a, const SparseComplexMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexMatrix -x_el_div (const Complex& a, const SparseMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexMatrix -x_el_div (const Complex& a, const SparseComplexMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline Matrix -xleftdiv (const SparseMatrix& a, const Matrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const SparseMatrix& a, const ComplexMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const SparseComplexMatrix& a, const Matrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const SparseComplexMatrix& a, const ComplexMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseMatrix -xleftdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseComplexMatrix -xleftdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseComplexMatrix -xleftdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseComplexMatrix -xleftdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b, - MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseMatrix -xleftdiv (const DiagMatrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseComplexMatrix -xleftdiv (const ComplexDiagMatrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseComplexMatrix -xleftdiv (const DiagMatrix& a, const SparseComplexMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseComplexMatrix -xleftdiv (const ComplexDiagMatrix& a, const SparseComplexMatrix& b, - MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/sparse-xpow.h --- a/libinterp/corefcn/sparse-xpow.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/sparse-xpow.h Tue Dec 06 15:45:27 2022 -0500 @@ -62,106 +62,4 @@ OCTAVE_END_NAMESPACE(octave) -#if (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const SparseMatrix& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const SparseComplexMatrix& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (double a, const SparseMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (double a, const SparseComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseMatrix& a, double b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseMatrix& a, const SparseMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseMatrix& a, const Complex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseMatrix& a, const SparseComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Complex& a, const SparseMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Complex& a, const SparseComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseComplexMatrix& a, double b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseComplexMatrix& a, const SparseMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseComplexMatrix& a, const Complex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseComplexMatrix& a, const SparseComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/variables.h --- a/libinterp/corefcn/variables.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/variables.h Tue Dec 06 15:45:27 2022 -0500 @@ -107,91 +107,6 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::symbol_exist' instead") -inline int -symbol_exist (const std::string& name, const std::string& type = "any") -{ - return octave::symbol_exist (name, type); -} - -OCTAVE_DEPRECATED (7, "use 'octave::unique_symbol_name' instead") -inline std::string -unique_symbol_name (const std::string& basename) -{ - return octave::unique_symbol_name (basename); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead") -inline octave_value -set_internal_variable (bool& var, const octave_value_list& args, int nargout, - const char *nm) -{ - return octave::set_internal_variable (var, args, nargout, nm); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead") -inline octave_value -set_internal_variable (char& var, const octave_value_list& args, int nargout, - const char *nm) -{ - return octave::set_internal_variable (var, args, nargout, nm); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead") -inline octave_value -set_internal_variable (int& var, const octave_value_list& args, int nargout, - const char *nm, - int minval = std::numeric_limits::min (), - int maxval = std::numeric_limits::max ()) -{ - return octave::set_internal_variable (var, args, nargout, nm, minval, maxval); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead") -inline octave_value -set_internal_variable (double& var, const octave_value_list& args, int nargout, - const char *nm, - double minval = -octave::numeric_limits::Inf (), - double maxval = octave::numeric_limits::Inf ()) -{ - return octave::set_internal_variable (var, args, nargout, nm, minval, maxval); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead") -inline octave_value -set_internal_variable (std::string& var, const octave_value_list& args, - int nargout, const char *nm, bool empty_ok = true) -{ - return octave::set_internal_variable (var, args, nargout, nm, empty_ok); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead") -inline octave_value -set_internal_variable (std::string& var, const octave_value_list& args, - int nargout, const char *nm, const char **choices) -{ - return octave::set_internal_variable (var, args, nargout, nm, choices); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead") -inline octave_value -set_internal_variable (int& var, const octave_value_list& args, int nargout, - const char *nm, const char **choices) -{ - return octave::set_internal_variable (var, args, nargout, nm, choices); -} - -OCTAVE_DEPRECATED (7, "use 'octave::maybe_missing_function_hook' instead") -inline std::string -maybe_missing_function_hook (const std::string& name) -{ - return octave::maybe_missing_function_hook (name); -} - -#endif - // The following macros should also be considered obsolete. #define SET_INTERNAL_VARIABLE(NM) \ diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/xdiv.h --- a/libinterp/corefcn/xdiv.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/xdiv.h Tue Dec 06 15:45:27 2022 -0500 @@ -156,415 +156,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline Matrix -xdiv (const Matrix& a, const Matrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const Matrix& a, const ComplexMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const ComplexMatrix& a, const Matrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const ComplexMatrix& a, const ComplexMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline Matrix -x_el_div (double a, const Matrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexMatrix -x_el_div (double a, const ComplexMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexMatrix -x_el_div (const Complex a, const Matrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexMatrix -x_el_div (const Complex a, const ComplexMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline NDArray -x_el_div (double a, const NDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexNDArray -x_el_div (double a, const ComplexNDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexNDArray -x_el_div (const Complex a, const NDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexNDArray -x_el_div (const Complex a, const ComplexNDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline Matrix -xleftdiv (const Matrix& a, const Matrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const Matrix& a, const ComplexMatrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const ComplexMatrix& a, const Matrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const ComplexMatrix& a, const ComplexMatrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatMatrix -xdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexMatrix -xdiv (const FloatMatrix& a, const FloatComplexMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexMatrix -xdiv (const FloatComplexMatrix& a, const FloatMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexMatrix -xdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatMatrix -x_el_div (float a, const FloatMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatComplexMatrix -x_el_div (float a, const FloatComplexMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatComplexMatrix -x_el_div (const FloatComplex a, const FloatMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatComplexMatrix -x_el_div (const FloatComplex a, const FloatComplexMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatNDArray -x_el_div (float a, const FloatNDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatComplexNDArray -x_el_div (float a, const FloatComplexNDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatComplexNDArray -x_el_div (const FloatComplex a, const FloatNDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatComplexNDArray -x_el_div (const FloatComplex a, const FloatComplexNDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatMatrix -xleftdiv (const FloatMatrix& a, const FloatMatrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatComplexMatrix -xleftdiv (const FloatMatrix& a, const FloatComplexMatrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatComplexMatrix -xleftdiv (const FloatComplexMatrix& a, const FloatMatrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatComplexMatrix -xleftdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline Matrix -xdiv (const Matrix& a, const DiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const ComplexMatrix& a, const DiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const ComplexMatrix& a, const ComplexDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline DiagMatrix -xdiv (const DiagMatrix& a, const DiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexDiagMatrix -xdiv (const ComplexDiagMatrix& a, const DiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexDiagMatrix -xdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatMatrix -xdiv (const FloatMatrix& a, const FloatDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexMatrix -xdiv (const FloatComplexMatrix& a, const FloatDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexMatrix -xdiv (const FloatMatrix& a, const FloatComplexDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexMatrix -xdiv (const FloatComplexMatrix& a, const FloatComplexDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatDiagMatrix -xdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexDiagMatrix -xdiv (const FloatComplexDiagMatrix& a, const FloatDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexDiagMatrix -xdiv (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline Matrix -xleftdiv (const DiagMatrix& a, const Matrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const DiagMatrix& a, const ComplexMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const ComplexDiagMatrix& a, const ComplexMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline DiagMatrix -xleftdiv (const DiagMatrix& a, const DiagMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexDiagMatrix -xleftdiv (const DiagMatrix& a, const ComplexDiagMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexDiagMatrix -xleftdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatMatrix -xleftdiv (const FloatDiagMatrix& a, const FloatMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatComplexMatrix -xleftdiv (const FloatDiagMatrix& a, const FloatComplexMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatComplexMatrix -xleftdiv (const FloatComplexDiagMatrix& a, const FloatComplexMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatDiagMatrix -xleftdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatComplexDiagMatrix -xleftdiv (const FloatDiagMatrix& a, const FloatComplexDiagMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatComplexDiagMatrix -xleftdiv (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b) -{ - return octave::xleftdiv (a, b); -} - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/xnorm.h --- a/libinterp/corefcn/xnorm.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/xnorm.h Tue Dec 06 15:45:27 2022 -0500 @@ -48,36 +48,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline octave_value -xnorm (const octave_value& x, const octave_value& p) -{ - return octave::xnorm (x, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead") -inline octave_value -xcolnorms (const octave_value& x, const octave_value& p) -{ - return octave::xcolnorms (x, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead") -inline octave_value -xrownorms (const octave_value& x, const octave_value& p) -{ - return octave::xrownorms (x, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead") -inline octave_value -xfrobnorm (const octave_value& x) -{ - return octave::xfrobnorm (x); -} - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/corefcn/xpow.h --- a/libinterp/corefcn/xpow.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/corefcn/xpow.h Tue Dec 06 15:45:27 2022 -0500 @@ -44,7 +44,6 @@ class ComplexNDArray; class FloatComplexNDArray; class octave_value; -class Range; OCTAVE_BEGIN_NAMESPACE(octave) @@ -209,589 +208,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (double a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (double a, const Matrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (double a, const Complex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (double a, const ComplexMatrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const Matrix& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const Matrix& a, const Complex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const DiagMatrix& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const DiagMatrix& a, const Complex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const PermMatrix& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const Complex& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const Complex& a, const Matrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const Complex& a, const Complex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const Complex& a, const ComplexMatrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const ComplexMatrix& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const ComplexMatrix& a, const Complex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const ComplexDiagMatrix& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const ComplexDiagMatrix& a, const Complex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (double a, const Matrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (double a, const ComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (double a, const octave::range& r) -{ - return octave::elem_xpow (a, r); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Matrix& a, double b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Matrix& a, const Matrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Matrix& a, const Complex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Matrix& a, const ComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Complex& a, const Matrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Complex& a, const ComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Complex& a, const octave::range& r) -{ - return octave::elem_xpow (a, r); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexMatrix& a, double b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexMatrix& a, const Matrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexMatrix& a, const Complex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexMatrix& a, const ComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (double a, const NDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (double a, const ComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const NDArray& a, double b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const NDArray& a, const NDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const NDArray& a, const Complex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const NDArray& a, const ComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Complex& a, const NDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Complex& a, const ComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexNDArray& a, double b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexNDArray& a, const NDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexNDArray& a, const Complex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexNDArray& a, const ComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (float a, float b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (float a, const FloatMatrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (float a, const FloatComplex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (float a, const FloatComplexMatrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatMatrix& a, float b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatMatrix& a, const FloatComplex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatDiagMatrix& a, float b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatDiagMatrix& a, const FloatComplex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplex& a, float b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplex& a, const FloatMatrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplex& a, const FloatComplex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplex& a, const FloatComplexMatrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplexMatrix& a, float b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplexMatrix& a, const FloatComplex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplexDiagMatrix& a, float b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplexDiagMatrix& a, const FloatComplex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (float a, const FloatMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (float a, const FloatComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatMatrix& a, float b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatMatrix& a, const FloatMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatMatrix& a, const FloatComplex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatMatrix& a, const FloatComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplex& a, const FloatMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplex& a, const FloatComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexMatrix& a, float b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexMatrix& a, const FloatMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexMatrix& a, const FloatComplex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexMatrix& a, const FloatComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (float a, const FloatNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (float a, const FloatComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatNDArray& a, float b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatNDArray& a, const FloatNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatNDArray& a, const FloatComplex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatNDArray& a, const FloatComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplex& a, const FloatNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplex& a, const FloatComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexNDArray& a, float b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexNDArray& a, const FloatNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexNDArray& a, const FloatComplex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexNDArray& a, const FloatComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/mk-builtins.pl --- a/libinterp/mk-builtins.pl Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/mk-builtins.pl Tue Dec 06 15:45:27 2022 -0500 @@ -150,23 +150,6 @@ print "\nOCTAVE_END_NAMESPACE(octave)\n"; - print "\n#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)\n\n"; - - foreach $name (sort (@fcn_names)) - { - print "OCTAVE_DEPRECATED (7, \"use 'octave::$name' instead\") -inline octave_value_list -$name (const octave_value_list& args = octave_value_list (), int nargout = 0) -{ - return octave::$name (args, nargout); -} - -"; - } - - ## end OCTAVE_PROVIDE_DEPRECATED_SYMBOLS block - print "\n\n#endif\n"; - print "\n#endif\n"; } elsif ($make_source) diff -r 29d734430e5f -r deb553ac2c54 libinterp/module.mk --- a/libinterp/module.mk Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/module.mk Tue Dec 06 15:45:27 2022 -0500 @@ -176,11 +176,6 @@ LIBINTERP_DEFUN_FILES += \ $(BUILT_IN_DEFUN_FILES) -## FIXME: The following two variables are deprecated and should be removed -## in Octave version 3.12. -DLL_CDEFS = @OCTINTERP_DLL_DEFS@ -DLL_CXXDEFS = @OCTINTERP_DLL_DEFS@ - ## Rules to build test files LIBINTERP_TST_FILES_SRC := $(shell $(SHELL) $(srcdir)/build-aux/find-files-with-tests.sh "$(srcdir)" $(ULT_DIST_SRC) $(DLDFCN_SRC)) diff -r 29d734430e5f -r deb553ac2c54 libinterp/octave-value/ov-legacy-range.cc --- a/libinterp/octave-value/ov-legacy-range.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/octave-value/ov-legacy-range.cc Tue Dec 06 15:45:27 2022 -0500 @@ -31,6 +31,7 @@ #include #include +#include "Range.h" #include "lo-ieee.h" #include "lo-utils.h" @@ -49,23 +50,326 @@ #include "ls-hdf5.h" #include "ls-utils.h" -#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +class +Range +{ +public: + + Range (void) + : m_base (0), m_limit (0), m_inc (0), m_numel (0) + { } + + // Assume range is already properly constructed, so just copy internal + // values. However, we set LIMIT to the computed final value because + // that mimics the behavior of the other Range class constructors that + // reset limit to the computed final value. + + Range (const octave::range& r) + : m_base (r.base ()), m_limit (r.final_value ()), m_inc (r.increment ()), + m_numel (r.numel ()) + { } + + Range (const Range& r) = default; + + Range& operator = (const Range& r) = default; + + ~Range (void) = default; + + Range (double b, double l) + : m_base (b), m_limit (l), m_inc (1), m_numel (numel_internal ()) + { + if (! octave::math::isinf (m_limit)) + m_limit = limit_internal (); + } + + Range (double b, double l, double i) + : m_base (b), m_limit (l), m_inc (i), m_numel (numel_internal ()) + { + if (! octave::math::isinf (m_limit)) + m_limit = limit_internal (); + } + + // The range has a finite number of elements. + bool ok (void) const + { + return (octave::math::isfinite (m_limit) + && (m_numel >= 0 || m_numel == -2)); + } + + double base (void) const { return m_base; } + double limit (void) const { return m_limit; } + double increment (void) const { return m_inc; } + + octave_idx_type numel (void) const { return m_numel; } + + bool all_elements_are_ints (void) const; + + Matrix matrix_value (void) const; + + double min (void) const; + double max (void) const; + +private: + + double m_base; + double m_limit; + double m_inc; + + octave_idx_type m_numel; + + octave_idx_type numel_internal (void) const; + + double limit_internal (void) const; + + void init (void); +}; + +bool +Range::all_elements_are_ints (void) const +{ + // If the base and increment are ints, the final value in the range will also + // be an integer, even if the limit is not. If there is one or fewer + // elements only the base needs to be an integer. + + return (! (octave::math::isnan (m_base) || octave::math::isnan (m_inc)) + && (octave::math::nint_big (m_base) == m_base || m_numel < 1) + && (octave::math::nint_big (m_inc) == m_inc || m_numel <= 1)); +} + +Matrix +Range::matrix_value (void) const +{ + Matrix retval (1, m_numel); + + if (m_numel > 0) + { + // The first element must always be *exactly* the base. + // E.g, -0 would otherwise become +0 in the loop (-0 + 0*increment). + retval(0) = m_base; + + double b = m_base; + double increment = m_inc; + for (octave_idx_type i = 1; i < m_numel - 1; i++) + retval.xelem (i) = b + i * increment; + + retval.xelem (m_numel - 1) = m_limit; + } + + return retval; +} + +// NOTE: max and min only return useful values if numel > 0. +// do_minmax_body() in max.cc avoids calling Range::min/max if numel == 0. + +double +Range::min (void) const +{ + double retval = 0.0; + if (m_numel > 0) + { + if (m_inc > 0) + retval = m_base; + else + { + retval = m_base + (m_numel - 1) * m_inc; + + // Require '<=' test. See note in max (). + if (retval <= m_limit) + retval = m_limit; + } + + } + return retval; +} + +double +Range::max (void) const +{ + double retval = 0.0; + if (m_numel > 0) + { + if (m_inc > 0) + { + retval = m_base + (m_numel - 1) * m_inc; + + // On some machines (x86 with extended precision floating point + // arithmetic, for example) it is possible that we can overshoot the + // limit by approximately the machine precision even though we were + // very careful in our calculation of the number of elements. + // Therefore, we clip the result to the limit if it overshoots. + // The test also includes equality (>= m_limit) to have expressions + // such as -5:1:-0 result in a -0 endpoint. + if (retval >= m_limit) + retval = m_limit; + } + else + retval = m_base; + } + return retval; +} + +// C See Knuth, Art Of Computer Programming, Vol. 1, Problem 1.2.4-5. +// C +// C===Tolerant FLOOR function. +// C +// C X - is given as a Double Precision argument to be operated on. +// C It is assumed that X is represented with M mantissa bits. +// C CT - is given as a Comparison Tolerance such that +// C 0.LT.CT.LE.3-SQRT(5)/2. If the relative difference between +// C X and A whole number is less than CT, then TFLOOR is +// C returned as this whole number. By treating the +// C floating-point numbers as a finite ordered set note that +// C the heuristic EPS=2.**(-(M-1)) and CT=3*EPS causes +// C arguments of TFLOOR/TCEIL to be treated as whole numbers +// C if they are exactly whole numbers or are immediately +// C adjacent to whole number representations. Since EPS, the +// C "distance" between floating-point numbers on the unit +// C interval, and M, the number of bits in X'S mantissa, exist +// C on every floating-point computer, TFLOOR/TCEIL are +// C consistently definable on every floating-point computer. +// C +// C For more information see the following references: +// C (1) P. E. Hagerty, "More On Fuzzy Floor And Ceiling," APL QUOTE +// C QUAD 8(4):20-24, June 1978. Note that TFLOOR=FL5. +// C (2) L. M. Breed, "Definitions For Fuzzy Floor And Ceiling", APL +// C QUOTE QUAD 8(3):16-23, March 1978. This paper cites FL1 through +// C FL5, the history of five years of evolutionary development of +// C FL5 - the seven lines of code below - by open collaboration +// C and corroboration of the mathematical-computing community. +// C +// C Penn State University Center for Academic Computing +// C H. D. Knoble - August, 1978. + +static inline double +tfloor (double x, double ct) +{ +// C---------FLOOR(X) is the largest integer algebraically less than +// C or equal to X; that is, the unfuzzy FLOOR function. + +// DINT (X) = X - DMOD (X, 1.0); +// FLOOR (X) = DINT (X) - DMOD (2.0 + DSIGN (1.0, X), 3.0); + +// C---------Hagerty's FL5 function follows... + + double q = 1.0; + + if (x < 0.0) + q = 1.0 - ct; + + double rmax = q / (2.0 - ct); + + double t1 = 1.0 + std::floor (x); + t1 = (ct / q) * (t1 < 0.0 ? -t1 : t1); + t1 = (rmax < t1 ? rmax : t1); + t1 = (ct > t1 ? ct : t1); + t1 = std::floor (x + t1); + + if (x <= 0.0 || (t1 - x) < rmax) + return t1; + else + return t1 - 1.0; +} + +static inline bool +teq (double u, double v, + double ct = 3.0 * std::numeric_limits::epsilon ()) +{ + double tu = std::abs (u); + double tv = std::abs (v); + + return std::abs (u - v) < ((tu > tv ? tu : tv) * ct); +} + +octave_idx_type +Range::numel_internal (void) const +{ + octave_idx_type retval = -1; + + if (! octave::math::isfinite (m_base) || ! octave::math::isfinite (m_inc) + || octave::math::isnan (m_limit)) + retval = -2; + else if (octave::math::isinf (m_limit) + && ((m_inc > 0 && m_limit > 0) + || (m_inc < 0 && m_limit < 0))) + retval = std::numeric_limits::max () - 1; + else if (m_inc == 0 + || (m_limit > m_base && m_inc < 0) + || (m_limit < m_base && m_inc > 0)) + { + retval = 0; + } + else + { + double ct = 3.0 * std::numeric_limits::epsilon (); + + double tmp = tfloor ((m_limit - m_base + m_inc) / m_inc, ct); + + octave_idx_type n_elt = (tmp > 0.0 + ? static_cast (tmp) : 0); + + // If the final element that we would compute for the range is equal to + // the limit of the range, or is an adjacent floating point number, + // accept it. Otherwise, try a range with one fewer element. If that + // fails, try again with one more element. + // + // I'm not sure this is very good, but it seems to work better than just + // using tfloor as above. For example, without it, the expression + // 1.8:0.05:1.9 fails to produce the expected result of [1.8, 1.85, 1.9]. + + if (! teq (m_base + (n_elt - 1) * m_inc, m_limit)) + { + if (teq (m_base + (n_elt - 2) * m_inc, m_limit)) + n_elt--; + else if (teq (m_base + n_elt * m_inc, m_limit)) + n_elt++; + } + + retval = ((n_elt < std::numeric_limits::max ()) + ? n_elt : -1); + } + + return retval; +} + +double +Range::limit_internal (void) const +{ + double new_limit = m_inc > 0 ? max () : min (); + + // If result must be an integer then force the new_limit to be one. + if (all_elements_are_ints ()) + new_limit = std::round (new_limit); + + return new_limit; +} + +void +Range::init (void) +{ + m_numel = numel_internal (); + + if (! octave::math::isinf (m_limit)) + m_limit = limit_internal (); +} DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_legacy_range, "range", "double"); octave_legacy_range::octave_legacy_range (void) - : octave_base_value (), range () { } + : octave_base_value (), m_range (new Range ()) { } octave_legacy_range::octave_legacy_range (const Range& r) - : octave_base_value (), range (r) + : octave_base_value (), m_range (new Range (r)) { - if (range.numel () < 0 && range.numel () != -2) + if (m_range->numel () < 0 && m_range->numel () != -2) error ("invalid range"); } +octave_legacy_range::octave_legacy_range (const octave_legacy_range& r) + : octave_base_value (r), m_range () +{ + m_range.reset (new Range (*(r.m_range))); +} + static octave_base_value * default_numeric_conversion_function (const octave_base_value& a) { @@ -78,7 +382,7 @@ octave_legacy_range::numeric_conversion_function (void) const { return octave_base_value::type_conv_info (default_numeric_conversion_function, - octave_matrix::static_type_id ()); + octave_matrix::static_type_id ()); } octave_base_value * @@ -86,10 +390,10 @@ { octave_base_value *retval = nullptr; - switch (range.numel ()) + switch (m_range->numel ()) { case 1: - retval = new octave_scalar (range.base ()); + retval = new octave_scalar (m_range->base ()); break; case 0: @@ -97,17 +401,17 @@ break; case -2: - retval = new octave_matrix (range.matrix_value ()); + retval = new octave_matrix (m_range->matrix_value ()); break; default: { - if (range.increment () == 0) - retval = new octave_matrix (range.matrix_value ()); + if (m_range->increment () == 0) + retval = new octave_matrix (m_range->matrix_value ()); else retval = new octave_range - (octave::range (range.base (), range.increment (), - range.limit (), range.numel ())); + (octave::range (m_range->base (), m_range->increment (), + m_range->limit (), m_range->numel ())); } break; } @@ -145,9 +449,9 @@ error ("load: failed to load range constant"); if (inc != 0) - range = Range (base, limit, inc); + m_range.reset (new Range (base, limit, inc)); else - range = Range (base, inc, static_cast (limit)); + m_range.reset (new Range (base, inc, static_cast (limit))); return true; } @@ -173,9 +477,9 @@ if (swap) swap_bytes<8> (&inc); if (inc != 0) - range = Range (bas, lim, inc); + m_range.reset (new Range (bas, lim, inc)); else - range = Range (bas, inc, static_cast (lim)); + m_range.reset (new Range (bas, inc, static_cast (lim))); return true; } @@ -245,14 +549,14 @@ octave_idx_type nel; if (hdf5_get_scalar_attr (data_hid, H5T_NATIVE_IDX, "OCTAVE_RANGE_NELEM", &nel)) - range = Range (rangevals[0], rangevals[2], nel); + m_range.reset (new Range (rangevals[0], rangevals[2], nel)); else { if (rangevals[2] != 0) - range = Range (rangevals[0], rangevals[1], rangevals[2]); + m_range.reset (new Range (rangevals[0], rangevals[1], rangevals[2])); else - range = Range (rangevals[0], rangevals[2], - static_cast (rangevals[1])); + m_range.reset (new Range (rangevals[0], rangevals[2], + static_cast (rangevals[1]))); } } @@ -269,7 +573,3 @@ return retval; } - -#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC) -# pragma GCC diagnostic pop -#endif diff -r 29d734430e5f -r deb553ac2c54 libinterp/octave-value/ov-legacy-range.h --- a/libinterp/octave-value/ov-legacy-range.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/octave-value/ov-legacy-range.h Tue Dec 06 15:45:27 2022 -0500 @@ -31,10 +31,9 @@ #include #include +#include #include -#include "Range.h" - #include "lo-mappers.h" #include "lo-utils.h" #include "mx-base.h" @@ -45,6 +44,8 @@ #include "ov-re-mat.h" #include "ov-typeinfo.h" +class Range; + class octave_value_list; // Legacy Range values. @@ -65,13 +66,13 @@ octave_legacy_range (const Range& r); - octave_legacy_range (const octave_legacy_range& r) = default; + octave_legacy_range (const octave_legacy_range& r); // No assignment. octave_legacy_range& operator = (const octave_legacy_range&) = delete; - ~octave_legacy_range (void) { } + ~octave_legacy_range (void) = default; octave_base_value * clone (void) const { @@ -102,7 +103,7 @@ private: - Range range; + std::unique_ptr m_range; DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA }; diff -r 29d734430e5f -r deb553ac2c54 libinterp/octave-value/ov.cc --- a/libinterp/octave-value/ov.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/octave-value/ov.cc Tue Dec 06 15:45:27 2022 -0500 @@ -1073,36 +1073,6 @@ maybe_mutate (); } -// Remove when public constructor that uses this function is removed. -octave_base_value * -octave_value::make_range_rep_deprecated (double base, double inc, double limit) -{ -#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - - return dynamic_cast - (new octave_legacy_range (Range (base, inc, limit))); - -#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC) -# pragma GCC diagnostic pop -#endif -} - -// Remove when public constructor that uses this function is removed. -octave_base_value * -octave_value::make_range_rep_deprecated (const Range& r, bool force_range) -{ - if (! force_range && ! r.ok ()) - error ("invalid range"); - - if ((force_range || Voptimize_range)) - return dynamic_cast (new octave_legacy_range (r)); - else - return dynamic_cast (new octave_matrix (r.matrix_value ())); -} - octave_value::octave_value (const octave::range& r, bool force_range) : m_rep (force_range || Voptimize_range ? dynamic_cast (new ov_range (r)) @@ -1201,8 +1171,8 @@ : m_rep (force_range || optimize_range ? dynamic_cast (new octave_char_range (r, type)) : dynamic_cast (type == '"' - ? new octave_char_matrix_dq_str (r.array_value ()) - : new octave_char_matrix_sq_str (r.array_value ()))) + ? new octave_char_matrix_dq_str (r.array_value ()) + : new octave_char_matrix_sq_str (r.array_value ()))) #else : m_rep (type == '"' ? new octave_char_matrix_dq_str (r.array_value ()) @@ -1891,10 +1861,10 @@ ComplexColumnVector octave_value::complex_column_vector_value (bool force_string_conv, - bool frc_vec_conv) const + bool frc_vec_conv) const { return ComplexColumnVector (complex_vector_value (force_string_conv, - frc_vec_conv)); + frc_vec_conv)); } RowVector @@ -1910,7 +1880,7 @@ bool frc_vec_conv) const { return ComplexRowVector (complex_vector_value (force_string_conv, - frc_vec_conv)); + frc_vec_conv)); } Array @@ -1920,8 +1890,8 @@ Array retval = array_value (force_string_conv); return retval.reshape (make_vector_dims (retval.dims (), - force_vector_conversion, - type_name (), "real vector")); + force_vector_conversion, + type_name (), "real vector")); } template @@ -1989,8 +1959,8 @@ } return retval.reshape (make_vector_dims (retval.dims (), - force_vector_conversion, - type_name (), "integer vector")); + force_vector_conversion, + type_name (), "integer vector")); } template @@ -2008,8 +1978,8 @@ Array octave_value::octave_idx_type_vector_value (bool require_int, - bool force_string_conv, - bool force_vector_conversion) const + bool force_string_conv, + bool force_vector_conversion) const { Array retval; @@ -2059,8 +2029,8 @@ } return retval.reshape (make_vector_dims (retval.dims (), - force_vector_conversion, - type_name (), "integer vector")); + force_vector_conversion, + type_name (), "integer vector")); } Array @@ -2070,25 +2040,25 @@ Array retval = complex_array_value (force_string_conv); return retval.reshape (make_vector_dims (retval.dims (), - force_vector_conversion, - type_name (), "complex vector")); + force_vector_conversion, + type_name (), "complex vector")); } FloatColumnVector octave_value::float_column_vector_value (bool force_string_conv, - bool frc_vec_conv) const + bool frc_vec_conv) const { return FloatColumnVector (float_vector_value (force_string_conv, - frc_vec_conv)); + frc_vec_conv)); } FloatComplexColumnVector octave_value::float_complex_column_vector_value (bool force_string_conv, - bool frc_vec_conv) const + bool frc_vec_conv) const { return FloatComplexColumnVector (float_complex_vector_value (force_string_conv, - frc_vec_conv)); + frc_vec_conv)); } FloatRowVector @@ -2096,15 +2066,15 @@ bool frc_vec_conv) const { return FloatRowVector (float_vector_value (force_string_conv, - frc_vec_conv)); + frc_vec_conv)); } FloatComplexRowVector octave_value::float_complex_row_vector_value (bool force_string_conv, - bool frc_vec_conv) const + bool frc_vec_conv) const { return FloatComplexRowVector (float_complex_vector_value (force_string_conv, - frc_vec_conv)); + frc_vec_conv)); } Array @@ -2114,19 +2084,19 @@ Array retval = float_array_value (force_string_conv); return retval.reshape (make_vector_dims (retval.dims (), - force_vector_conversion, - type_name (), "real vector")); + force_vector_conversion, + type_name (), "real vector")); } Array octave_value::float_complex_vector_value (bool force_string_conv, - bool force_vector_conversion) const + bool force_vector_conversion) const { Array retval = float_complex_array_value (force_string_conv); return retval.reshape (make_vector_dims (retval.dims (), - force_vector_conversion, - type_name (), "complex vector")); + force_vector_conversion, + type_name (), "complex vector")); } // NAME can't always be "x ## FCN" because some of the original @@ -2214,8 +2184,7 @@ XVALUE_EXTRACTOR (DiagMatrix, xdiag_matrix_value, diag_matrix_value) XVALUE_EXTRACTOR (FloatDiagMatrix, xfloat_diag_matrix_value, float_diag_matrix_value) XVALUE_EXTRACTOR (ComplexDiagMatrix, xcomplex_diag_matrix_value, complex_diag_matrix_value) -XVALUE_EXTRACTOR (FloatComplexDiagMatrix, xfloat_complex_diag_matrix_value, - float_complex_diag_matrix_value) +XVALUE_EXTRACTOR (FloatComplexDiagMatrix, xfloat_complex_diag_matrix_value, float_complex_diag_matrix_value) XVALUE_EXTRACTOR (PermMatrix, xperm_matrix_value, perm_matrix_value) @@ -2273,16 +2242,13 @@ XVALUE_EXTRACTOR (ComplexRowVector, xcomplex_row_vector_value, complex_row_vector_value) XVALUE_EXTRACTOR (FloatColumnVector, xfloat_column_vector_value, float_column_vector_value) -XVALUE_EXTRACTOR (FloatComplexColumnVector, xfloat_complex_column_vector_value, - float_complex_column_vector_value) +XVALUE_EXTRACTOR (FloatComplexColumnVector, xfloat_complex_column_vector_value, float_complex_column_vector_value) XVALUE_EXTRACTOR (FloatRowVector, xfloat_row_vector_value, float_row_vector_value) -XVALUE_EXTRACTOR (FloatComplexRowVector, xfloat_complex_row_vector_value, - float_complex_row_vector_value) +XVALUE_EXTRACTOR (FloatComplexRowVector, xfloat_complex_row_vector_value, float_complex_row_vector_value) XVALUE_EXTRACTOR (Array, xint_vector_value, int_vector_value) -XVALUE_EXTRACTOR (Array, xoctave_idx_type_vector_value, - octave_idx_type_vector_value) +XVALUE_EXTRACTOR (Array, xoctave_idx_type_vector_value, octave_idx_type_vector_value) XVALUE_EXTRACTOR (Array, xvector_value, vector_value) XVALUE_EXTRACTOR (Array, xcomplex_vector_value, complex_vector_value) @@ -2520,7 +2486,7 @@ if (! tmp) err_unary_op_conversion_failed - (octave_value::unary_op_as_string (op), type_name ()); + (octave_value::unary_op_as_string (op), type_name ()); octave_base_value *old_rep = m_rep; m_rep = tmp; @@ -2692,950 +2658,950 @@ OCTAVE_BEGIN_NAMESPACE(octave) -OCTAVE_NORETURN static void -err_binary_op (const std::string& on, const std::string& tn1, - const std::string& tn2) -{ - error ("binary operator '%s' not implemented for '%s' by '%s' operations", - on.c_str (), tn1.c_str (), tn2.c_str ()); -} - -OCTAVE_NORETURN static void -err_binary_op_conv (const std::string& on) -{ - error ("type conversion failed for binary operator '%s'", on.c_str ()); -} - -octave_value -binary_op (type_info& ti, octave_value::binary_op op, - const octave_value& v1, const octave_value& v2) -{ - octave_value retval; - - int t1 = v1.type_id (); - int t2 = v2.type_id (); - - if (t1 == octave_class::static_type_id () - || t2 == octave_class::static_type_id () - || t1 == octave_classdef::static_type_id () - || t2 == octave_classdef::static_type_id ()) - { - type_info::binary_class_op_fcn f = ti.lookup_binary_class_op (op); - - if (! f) - err_binary_op (octave_value::binary_op_as_string (op), - v1.class_name (), v2.class_name ()); - - retval = f (v1, v2); - } - else - { - // FIXME: we need to handle overloading operators for built-in - // classes (double, char, int8, etc.) - - type_info::binary_op_fcn f - = ti.lookup_binary_op (op, t1, t2); - - if (f) - retval = f (v1.get_rep (), v2.get_rep ()); - else - { - octave_value tv1; - octave_base_value::type_conv_info cf1 - = v1.numeric_conversion_function (); - - octave_value tv2; - octave_base_value::type_conv_info cf2 - = v2.numeric_conversion_function (); - - // Try biased (one-sided) conversions first. - if (cf2.type_id () >= 0 - && ti.lookup_binary_op (op, t1, cf2.type_id ())) - cf1 = nullptr; - else if (cf1.type_id () >= 0 - && ti.lookup_binary_op (op, cf1.type_id (), t2)) - cf2 = nullptr; - - if (cf1) - { - octave_base_value *tmp = cf1 (v1.get_rep ()); - - if (! tmp) - err_binary_op_conv (octave_value::binary_op_as_string (op)); - - tv1 = octave_value (tmp); - t1 = tv1.type_id (); - } - else - tv1 = v1; - - if (cf2) - { - octave_base_value *tmp = cf2 (v2.get_rep ()); - - if (! tmp) - err_binary_op_conv (octave_value::binary_op_as_string (op)); - - tv2 = octave_value (tmp); - t2 = tv2.type_id (); - } - else - tv2 = v2; - - if (cf1 || cf2) - { - retval = binary_op (op, tv1, tv2); - } - else - { - //demote double -> single and try again - cf1 = tv1.numeric_demotion_function (); - - cf2 = tv2.numeric_demotion_function (); - - // Try biased (one-sided) conversions first. - if (cf2.type_id () >= 0 - && ti.lookup_binary_op (op, t1, cf2.type_id ())) - cf1 = nullptr; - else if (cf1.type_id () >= 0 - && ti.lookup_binary_op (op, cf1.type_id (), t2)) - cf2 = nullptr; - - if (cf1) - { - octave_base_value *tmp = cf1 (tv1.get_rep ()); - - if (! tmp) - err_binary_op_conv (octave_value::binary_op_as_string (op)); - - tv1 = octave_value (tmp); - t1 = tv1.type_id (); - } - - if (cf2) - { - octave_base_value *tmp = cf2 (tv2.get_rep ()); - - if (! tmp) - err_binary_op_conv (octave_value::binary_op_as_string (op)); - - tv2 = octave_value (tmp); - t2 = tv2.type_id (); - } - - if (! cf1 && ! cf2) - err_binary_op (octave_value::binary_op_as_string (op), - v1.type_name (), v2.type_name ()); - - f = ti.lookup_binary_op (op, t1, t2); - - if (! f) - err_binary_op (octave_value::binary_op_as_string (op), - v1.type_name (), v2.type_name ()); - - retval = f (tv1.get_rep (), tv2.get_rep ()); - } - } - } - - return retval; -} - -octave_value -binary_op (octave_value::binary_op op, const octave_value& v1, - const octave_value& v2) -{ - type_info& ti = __get_type_info__ (); - - return binary_op (ti, op, v1, v2); -} - -static octave_value -decompose_binary_op (type_info& ti, octave_value::compound_binary_op op, - const octave_value& v1, const octave_value& v2) -{ - switch (op) - { - case octave_value::op_trans_mul: - return binary_op (octave_value::op_mul, - unary_op (octave_value::op_transpose, v1), v2); - - case octave_value::op_mul_trans: - return binary_op (ti, octave_value::op_mul, - v1, unary_op (octave_value::op_transpose, v2)); - - case octave_value::op_herm_mul: - return binary_op (ti, octave_value::op_mul, - unary_op (octave_value::op_hermitian, v1), v2); - - case octave_value::op_mul_herm: - return binary_op (ti, octave_value::op_mul, - v1, unary_op (octave_value::op_hermitian, v2)); - - case octave_value::op_trans_ldiv: - return binary_op (ti, octave_value::op_ldiv, - unary_op (octave_value::op_transpose, v1), v2); - - case octave_value::op_herm_ldiv: - return binary_op (ti, octave_value::op_ldiv, - unary_op (octave_value::op_hermitian, v1), v2); - - case octave_value::op_el_not_and: - return binary_op (ti, octave_value::op_el_and, - unary_op (octave_value::op_not, v1), v2); - - case octave_value::op_el_not_or: - return binary_op (ti, octave_value::op_el_or, - unary_op (octave_value::op_not, v1), v2); - - case octave_value::op_el_and_not: - return binary_op (ti, octave_value::op_el_and, - v1, unary_op (octave_value::op_not, v2)); - - case octave_value::op_el_or_not: - return binary_op (ti, octave_value::op_el_or, - v1, unary_op (octave_value::op_not, v2)); - - default: - error ("invalid compound operator"); - } -} - -octave_value -binary_op (type_info& ti, octave_value::compound_binary_op op, - const octave_value& v1, const octave_value& v2) -{ - octave_value retval; - - int t1 = v1.type_id (); - int t2 = v2.type_id (); - - if (t1 == octave_class::static_type_id () - || t2 == octave_class::static_type_id () - || t1 == octave_classdef::static_type_id () - || t2 == octave_classdef::static_type_id ()) - { - type_info::binary_class_op_fcn f = ti.lookup_binary_class_op (op); - - if (f) + OCTAVE_NORETURN static void + err_binary_op (const std::string& on, const std::string& tn1, + const std::string& tn2) + { + error ("binary operator '%s' not implemented for '%s' by '%s' operations", + on.c_str (), tn1.c_str (), tn2.c_str ()); + } + + OCTAVE_NORETURN static void + err_binary_op_conv (const std::string& on) + { + error ("type conversion failed for binary operator '%s'", on.c_str ()); + } + + octave_value + binary_op (type_info& ti, octave_value::binary_op op, + const octave_value& v1, const octave_value& v2) + { + octave_value retval; + + int t1 = v1.type_id (); + int t2 = v2.type_id (); + + if (t1 == octave_class::static_type_id () + || t2 == octave_class::static_type_id () + || t1 == octave_classdef::static_type_id () + || t2 == octave_classdef::static_type_id ()) + { + type_info::binary_class_op_fcn f = ti.lookup_binary_class_op (op); + + if (! f) + err_binary_op (octave_value::binary_op_as_string (op), + v1.class_name (), v2.class_name ()); + retval = f (v1, v2); - else - retval = decompose_binary_op (ti, op, v1, v2); - } - else - { - type_info::binary_op_fcn f = ti.lookup_binary_op (op, t1, t2); - - if (f) - retval = f (v1.get_rep (), v2.get_rep ()); - else - retval = decompose_binary_op (ti, op, v1, v2); - } - - return retval; -} - -octave_value -binary_op (octave_value::compound_binary_op op, - const octave_value& v1, const octave_value& v2) -{ - type_info& ti = __get_type_info__ (); - - return binary_op (ti, op, v1, v2); -} - -OCTAVE_NORETURN static void -err_cat_op (const std::string& tn1, const std::string& tn2) -{ - error ("concatenation operator not implemented for '%s' by '%s' operations", - tn1.c_str (), tn2.c_str ()); -} - -OCTAVE_NORETURN static void -err_cat_op_conv (void) -{ - error ("type conversion failed for concatenation operator"); -} - -octave_value -cat_op (type_info& ti, const octave_value& v1, - const octave_value& v2, const Array& ra_idx) -{ - octave_value retval; - - // Can't rapid return for concatenation with an empty object here as - // something like cat(1,[],single([]) must return the correct type. - - int t1 = v1.type_id (); - int t2 = v2.type_id (); - - type_info::cat_op_fcn f = ti.lookup_cat_op (t1, t2); - - if (f) - retval = f (v1.get_rep (), v2.get_rep (), ra_idx); - else - { - octave_value tv1; - octave_base_value::type_conv_info cf1 = v1.numeric_conversion_function (); - - octave_value tv2; - octave_base_value::type_conv_info cf2 = v2.numeric_conversion_function (); - - // Try biased (one-sided) conversions first. - if (cf2.type_id () >= 0 && ti.lookup_cat_op (t1, cf2.type_id ())) - cf1 = nullptr; - else if (cf1.type_id () >= 0 && ti.lookup_cat_op (cf1.type_id (), t2)) - cf2 = nullptr; - - if (cf1) - { - octave_base_value *tmp = cf1 (v1.get_rep ()); - - if (! tmp) - err_cat_op_conv (); - - tv1 = octave_value (tmp); - t1 = tv1.type_id (); - } - else - tv1 = v1; - - if (cf2) - { - octave_base_value *tmp = cf2 (v2.get_rep ()); - - if (! tmp) - err_cat_op_conv (); - - tv2 = octave_value (tmp); - t2 = tv2.type_id (); - } - else - tv2 = v2; - - if (! cf1 && ! cf2) - err_cat_op (v1.type_name (), v2.type_name ()); - - retval = cat_op (ti, tv1, tv2, ra_idx); - } - - return retval; -} - -octave_value -cat_op (const octave_value& v1, const octave_value& v2, - const Array& ra_idx) -{ - type_info& ti = __get_type_info__ (); - - return cat_op (ti, v1, v2, ra_idx); -} - -// Unless the colon operator is used with a class or classdef object, -// then all arguments must be the same type or mixed with double -// values. - -static builtin_type_t -get_colon_op_type (builtin_type_t op1_type, builtin_type_t op2_type) -{ - if (op1_type == op2_type) - return op1_type; - - if (op1_type == btyp_double) - return op2_type; - - if (op2_type == btyp_double) - return op1_type; - - return btyp_unknown; -} - -static builtin_type_t -get_colon_op_type (const octave_value& base, const octave_value& increment, + } + else + { + // FIXME: we need to handle overloading operators for built-in + // classes (double, char, int8, etc.) + + type_info::binary_op_fcn f + = ti.lookup_binary_op (op, t1, t2); + + if (f) + retval = f (v1.get_rep (), v2.get_rep ()); + else + { + octave_value tv1; + octave_base_value::type_conv_info cf1 + = v1.numeric_conversion_function (); + + octave_value tv2; + octave_base_value::type_conv_info cf2 + = v2.numeric_conversion_function (); + + // Try biased (one-sided) conversions first. + if (cf2.type_id () >= 0 + && ti.lookup_binary_op (op, t1, cf2.type_id ())) + cf1 = nullptr; + else if (cf1.type_id () >= 0 + && ti.lookup_binary_op (op, cf1.type_id (), t2)) + cf2 = nullptr; + + if (cf1) + { + octave_base_value *tmp = cf1 (v1.get_rep ()); + + if (! tmp) + err_binary_op_conv (octave_value::binary_op_as_string (op)); + + tv1 = octave_value (tmp); + t1 = tv1.type_id (); + } + else + tv1 = v1; + + if (cf2) + { + octave_base_value *tmp = cf2 (v2.get_rep ()); + + if (! tmp) + err_binary_op_conv (octave_value::binary_op_as_string (op)); + + tv2 = octave_value (tmp); + t2 = tv2.type_id (); + } + else + tv2 = v2; + + if (cf1 || cf2) + { + retval = binary_op (op, tv1, tv2); + } + else + { + //demote double -> single and try again + cf1 = tv1.numeric_demotion_function (); + + cf2 = tv2.numeric_demotion_function (); + + // Try biased (one-sided) conversions first. + if (cf2.type_id () >= 0 + && ti.lookup_binary_op (op, t1, cf2.type_id ())) + cf1 = nullptr; + else if (cf1.type_id () >= 0 + && ti.lookup_binary_op (op, cf1.type_id (), t2)) + cf2 = nullptr; + + if (cf1) + { + octave_base_value *tmp = cf1 (tv1.get_rep ()); + + if (! tmp) + err_binary_op_conv (octave_value::binary_op_as_string (op)); + + tv1 = octave_value (tmp); + t1 = tv1.type_id (); + } + + if (cf2) + { + octave_base_value *tmp = cf2 (tv2.get_rep ()); + + if (! tmp) + err_binary_op_conv (octave_value::binary_op_as_string (op)); + + tv2 = octave_value (tmp); + t2 = tv2.type_id (); + } + + if (! cf1 && ! cf2) + err_binary_op (octave_value::binary_op_as_string (op), + v1.type_name (), v2.type_name ()); + + f = ti.lookup_binary_op (op, t1, t2); + + if (! f) + err_binary_op (octave_value::binary_op_as_string (op), + v1.type_name (), v2.type_name ()); + + retval = f (tv1.get_rep (), tv2.get_rep ()); + } + } + } + + return retval; + } + + octave_value + binary_op (octave_value::binary_op op, const octave_value& v1, + const octave_value& v2) + { + type_info& ti = __get_type_info__ (); + + return binary_op (ti, op, v1, v2); + } + + static octave_value + decompose_binary_op (type_info& ti, octave_value::compound_binary_op op, + const octave_value& v1, const octave_value& v2) + { + switch (op) + { + case octave_value::op_trans_mul: + return binary_op (octave_value::op_mul, + unary_op (octave_value::op_transpose, v1), v2); + + case octave_value::op_mul_trans: + return binary_op (ti, octave_value::op_mul, + v1, unary_op (octave_value::op_transpose, v2)); + + case octave_value::op_herm_mul: + return binary_op (ti, octave_value::op_mul, + unary_op (octave_value::op_hermitian, v1), v2); + + case octave_value::op_mul_herm: + return binary_op (ti, octave_value::op_mul, + v1, unary_op (octave_value::op_hermitian, v2)); + + case octave_value::op_trans_ldiv: + return binary_op (ti, octave_value::op_ldiv, + unary_op (octave_value::op_transpose, v1), v2); + + case octave_value::op_herm_ldiv: + return binary_op (ti, octave_value::op_ldiv, + unary_op (octave_value::op_hermitian, v1), v2); + + case octave_value::op_el_not_and: + return binary_op (ti, octave_value::op_el_and, + unary_op (octave_value::op_not, v1), v2); + + case octave_value::op_el_not_or: + return binary_op (ti, octave_value::op_el_or, + unary_op (octave_value::op_not, v1), v2); + + case octave_value::op_el_and_not: + return binary_op (ti, octave_value::op_el_and, + v1, unary_op (octave_value::op_not, v2)); + + case octave_value::op_el_or_not: + return binary_op (ti, octave_value::op_el_or, + v1, unary_op (octave_value::op_not, v2)); + + default: + error ("invalid compound operator"); + } + } + + octave_value + binary_op (type_info& ti, octave_value::compound_binary_op op, + const octave_value& v1, const octave_value& v2) + { + octave_value retval; + + int t1 = v1.type_id (); + int t2 = v2.type_id (); + + if (t1 == octave_class::static_type_id () + || t2 == octave_class::static_type_id () + || t1 == octave_classdef::static_type_id () + || t2 == octave_classdef::static_type_id ()) + { + type_info::binary_class_op_fcn f = ti.lookup_binary_class_op (op); + + if (f) + retval = f (v1, v2); + else + retval = decompose_binary_op (ti, op, v1, v2); + } + else + { + type_info::binary_op_fcn f = ti.lookup_binary_op (op, t1, t2); + + if (f) + retval = f (v1.get_rep (), v2.get_rep ()); + else + retval = decompose_binary_op (ti, op, v1, v2); + } + + return retval; + } + + octave_value + binary_op (octave_value::compound_binary_op op, + const octave_value& v1, const octave_value& v2) + { + type_info& ti = __get_type_info__ (); + + return binary_op (ti, op, v1, v2); + } + + OCTAVE_NORETURN static void + err_cat_op (const std::string& tn1, const std::string& tn2) + { + error ("concatenation operator not implemented for '%s' by '%s' operations", + tn1.c_str (), tn2.c_str ()); + } + + OCTAVE_NORETURN static void + err_cat_op_conv (void) + { + error ("type conversion failed for concatenation operator"); + } + + octave_value + cat_op (type_info& ti, const octave_value& v1, + const octave_value& v2, const Array& ra_idx) + { + octave_value retval; + + // Can't rapid return for concatenation with an empty object here as + // something like cat(1,[],single([]) must return the correct type. + + int t1 = v1.type_id (); + int t2 = v2.type_id (); + + type_info::cat_op_fcn f = ti.lookup_cat_op (t1, t2); + + if (f) + retval = f (v1.get_rep (), v2.get_rep (), ra_idx); + else + { + octave_value tv1; + octave_base_value::type_conv_info cf1 = v1.numeric_conversion_function (); + + octave_value tv2; + octave_base_value::type_conv_info cf2 = v2.numeric_conversion_function (); + + // Try biased (one-sided) conversions first. + if (cf2.type_id () >= 0 && ti.lookup_cat_op (t1, cf2.type_id ())) + cf1 = nullptr; + else if (cf1.type_id () >= 0 && ti.lookup_cat_op (cf1.type_id (), t2)) + cf2 = nullptr; + + if (cf1) + { + octave_base_value *tmp = cf1 (v1.get_rep ()); + + if (! tmp) + err_cat_op_conv (); + + tv1 = octave_value (tmp); + t1 = tv1.type_id (); + } + else + tv1 = v1; + + if (cf2) + { + octave_base_value *tmp = cf2 (v2.get_rep ()); + + if (! tmp) + err_cat_op_conv (); + + tv2 = octave_value (tmp); + t2 = tv2.type_id (); + } + else + tv2 = v2; + + if (! cf1 && ! cf2) + err_cat_op (v1.type_name (), v2.type_name ()); + + retval = cat_op (ti, tv1, tv2, ra_idx); + } + + return retval; + } + + octave_value + cat_op (const octave_value& v1, const octave_value& v2, + const Array& ra_idx) + { + type_info& ti = __get_type_info__ (); + + return cat_op (ti, v1, v2, ra_idx); + } + + // Unless the colon operator is used with a class or classdef object, + // then all arguments must be the same type or mixed with double + // values. + + static builtin_type_t + get_colon_op_type (builtin_type_t op1_type, builtin_type_t op2_type) + { + if (op1_type == op2_type) + return op1_type; + + if (op1_type == btyp_double) + return op2_type; + + if (op2_type == btyp_double) + return op1_type; + + return btyp_unknown; + } + + static builtin_type_t + get_colon_op_type (const octave_value& base, const octave_value& increment, + const octave_value& limit) + { + builtin_type_t typ + = get_colon_op_type (base.builtin_type (), increment.builtin_type ()); + + if (typ == btyp_unknown) + return typ; + + return get_colon_op_type (typ, limit.builtin_type ()); + } + + // This check depends on the type of VAL either being the expected + // integer type or a double value. + + template + static void + check_colon_operand (const octave_value& val, const char *op_str) + { + if (! val.is_double_type ()) + return; + + double dval = val.double_value (); + double intpart; + static const double out_of_range_top + = static_cast (std::numeric_limits::max ()) + + 1.; + + if (dval >= out_of_range_top + || dval < std::numeric_limits::min () + || std::modf (dval, &intpart) != 0.0) + error ("colon operator %s invalid (not an integer or out of range for given integer type)", op_str); + } + + // Return the difference between two unsigned integers as an unsigned + // integer of the same type. + + template ::value + && std::is_unsigned::value), + bool>::type = true> + UT + integer_difference (UT a, UT b) + { + return a > b ? a - b : b - a; + } + + // Return the difference between two signed integers as an unsigned + // integer corresponding to the signed type. + + template ::type, + typename std::enable_if<(std::is_integral::value + && std::is_signed::value), + bool>::type = true> + UT + integer_difference (ST a, ST b) + { + // Map to unsigned. + // Idea from https://stackoverflow.com/questions/10589559 + + static const UT offset + = UT (0) - static_cast (std::numeric_limits::min ()); + + UT au = static_cast (a) + offset; + UT bu = static_cast (b) + offset; + + return integer_difference (au, bu); + } + + // Number of elements in an integer range taking care to avoid + // overflow. Base and limit are of the same type. If they are + // unsigned, then increment is also of the same type. If they are + // signed, then the type of increment is the unsigned type + // corresponding to T. Assumes that the base and limit values are + // consistent with the sign of the original increment (not an empty + // range) so we can calculate numel with the absolute value of the + // increment and the absolute difference between the base and limit + // values. + + template ::type, + typename std::enable_if::value, + bool>::type = true> + octave_idx_type + range_numel_aux (T base, UT unsigned_increment, T limit) + { + // Adding one to DIFF/INCREMENT may overflow, so check whether it is + // out of range before adding. + + UT nel_m1 = integer_difference (limit, base) / unsigned_increment; + + // FIXME: fix error message. + if (nel_m1 > std::numeric_limits::max () - 1) + error ("too many elements for range!"); + + return static_cast (nel_m1) + 1; + } + + // Convert signed range increment to unsigned. + + template ::type, + typename std::enable_if<(std::is_integral::value + && std::is_signed::value), + bool>::type = true> + UT + range_increment (ST increment) + { + return (increment < 0 + ? UT (0) - static_cast (increment) + : static_cast (increment)); + } + + // "Convert" unsigned range increment to unsigned. A no-op, but + // needed to provide a consistent interface for other template + // functions. + + template ::type, + typename std::enable_if<(std::is_integral::value + && std::is_unsigned::value), + bool>::type = true> + UT + range_increment (UT increment) + { + return increment; + } + + // Convert double range increment to unsigned. Enable by return type. + + template ::type> + typename std::enable_if<(std::is_integral::value + && std::is_unsigned::value), UT>::type + range_increment (double increment) + { + double abs_increment = std::abs (increment); + + return static_cast (abs_increment); + } + + // Number of elements in an integer range base:increment:limit. Base, + // increment, and limit are of the same signed type. + + template ::value + && std::is_signed::value), + bool>::type = true> + octave_idx_type + range_numel (ST base, ST increment, ST limit) + { + typedef typename std::make_unsigned::type UT; + + if (increment == 0 + || (increment > 0 && base > limit) + || (increment < 0 && base < limit)) + return 0; + + UT unsigned_increment = range_increment (increment); + + return range_numel_aux (base, unsigned_increment, limit); + } + + // Number of elements in an integer range base:increment:limit. Base, + // increment, and limit are unsigned and of the same type. + + template ::value + && std::is_unsigned::value), + bool>::type = true> + octave_idx_type + range_numel (UT base, UT increment, UT limit) + { + // Unsigned, INCREMENT is always >= 0. + if (increment == 0 || base > limit) + return 0; + + return range_numel_aux (base, increment, limit); + } + + // Number of elements in an integer range base:increment:limit. Base + // and limit are of the same type and increment is a double value. + + template ::type, + typename std::enable_if::value, + bool>::type = true> + octave_idx_type + range_numel (T base, double increment, T limit) + { + double intpart; + if (math::isnan (increment) || std::modf (increment, &intpart) != 0.0) + error ("colon operator increment invalid (not an integer)"); + + if (increment == 0 + || (increment > 0 && base > limit) + || (increment < 0 && base < limit)) + return 0; + + static const double out_of_range_top + = static_cast (std::numeric_limits::max ()) + 1.; + + double abs_increment = std::abs (increment); + + // Technically, this condition should be + // `abs_increment > std::numeric_limits::max ()`. + // But intmax('uint64') is not representable exactly as floating point + // number. Instead, it "rounds" up by 1 to 2^64. To account for + // this, use the following expression which works for all unsigned + // integer types. + if (abs_increment >= out_of_range_top) + return 1; + + UT unsigned_increment = range_increment (increment); + + return range_numel_aux (base, unsigned_increment, limit); + } + + // Make a range from integer values. Increment may be integer or double. + + template ::value + && std::is_arithmetic::value), + bool>::type = true> + octave_value + make_int_range (T base, IT increment, T limit) + { + octave_idx_type nel = range_numel (base, increment, limit); + + // For now, we create arrays instead of range for all types + // except double. + + Array> result (dim_vector (1, nel)); + + if (nel > 0) + { + typedef typename std::make_unsigned::type UT; + + UT unsigned_increment = range_increment (increment); + + T val = base; + result.xelem (0) = val; + + if (limit > base) + { + for (octave_idx_type i = 1; i < nel; i++) + { + val += unsigned_increment; + result.xelem (i) = val; + } + } + else + { + for (octave_idx_type i = 1; i < nel; i++) + { + val -= unsigned_increment; + result.xelem (i) = val; + } + } + } + + return octave_value (result); + } + + // Make a range from floating point values. + + // FIXME: Try again to define memory efficient range classes for + // integer and floating point values? Maybe with the templates + // defined in this file we could do that in a reasonable way? + // Regardless of that, it might be good to provide special treatment + // of colon expressions in FOR loops so that we can eliminate the + // "is_for_cmd_expr / force_range" flag from the parser and the + // octave_value constructors for range objects. + + // NOTE: We define this function separately for float and double so + // that we can avoid having to instantiate ov_range. We DO + // instantiate range but only so we can take advantage of the + // range class to generate the corresponding array of float values + // and not have to duplicate that code here. + + template ::value, + bool>::type = true> + octave_value + make_float_range (T base, T increment, T limit, bool is_for_cmd_expr) + { + if (math::isnan (base) + || math::isnan (increment) + || math::isnan (limit)) + return octave_value (numeric_limits::NaN ()); + + if (increment == 0 + || (increment > 0 && base > limit) + || (increment < 0 && base < limit)) + return octave_value (Array (dim_vector (1, 0))); + + // At this point, we know that the base and limit values are + // consistent with the sign of the increment (not an empty range). + + range r (base, increment, limit); + + if (! is_for_cmd_expr && ! r.is_storable ()) + error ("range with infinite number of elements cannot be stored"); + + return octave_value (r, is_for_cmd_expr); + } + + template ::value, + bool>::type = true> + octave_value + make_float_range (T base, T increment, T limit, bool is_for_cmd_expr) + { + if (math::isnan (base) + || math::isnan (increment) + || math::isnan (limit)) + return octave_value (numeric_limits::NaN ()); + + if (increment == 0 + || (increment > 0 && base > limit) + || (increment < 0 && base < limit)) + return octave_value (Array (dim_vector (1, 0))); + + // At this point, we know that the base and limit values are + // consistent with the sign of the increment (not an empty range). + + range r (base, increment, limit); + + if (! is_for_cmd_expr && ! r.is_storable ()) + error ("range with infinite number of elements cannot be stored"); + + return octave_value (r.array_value ()); + } + + template ::value + || std::is_same::value + || std::is_same::value + || std::is_same::value + || std::is_same::value + || std::is_same::value + || std::is_same::value + || std::is_same::value), + bool>::type = true> + octave_value + make_int_range (const octave_value& base, const octave_value& increment, + const octave_value& limit) + { + if (base.isempty () || increment.isempty () || limit.isempty ()) + return octave_value (Array (dim_vector (1, 0))); + + check_colon_operand (base, "lower bound"); + check_colon_operand (limit, "upper bound"); + + typename T::val_type base_val = octave_value_extract (base).value (); + typename T::val_type limit_val = octave_value_extract (limit).value (); + + if (increment.is_double_type ()) + { + double increment_val = increment.double_value (); + + return make_int_range (base_val, increment_val, limit_val); + } + + check_colon_operand (increment, "increment"); + + typename T::val_type increment_val + = octave_value_extract (increment).value (); + + return make_int_range (base_val, increment_val, limit_val); + } + + template ::value, + bool>::type = true> + octave_value + make_float_range (const octave_value& base, const octave_value& increment, + const octave_value& limit, bool is_for_cmd_expr) + { + if (base.isempty () || increment.isempty () || limit.isempty ()) + return octave_value (Array (dim_vector (1, 0))); + + T base_val = octave_value_extract (base); + T increment_val = octave_value_extract (increment); + T limit_val = octave_value_extract (limit); + + return make_float_range (base_val, increment_val, limit_val, + is_for_cmd_expr); + } + + + octave_value + make_char_range (const octave_value& base, const octave_value& increment, const octave_value& limit) -{ - builtin_type_t typ - = get_colon_op_type (base.builtin_type (), increment.builtin_type ()); - - if (typ == btyp_unknown) - return typ; - - return get_colon_op_type (typ, limit.builtin_type ()); -} - -// This check depends on the type of VAL either being the expected -// integer type or a double value. - -template -static void -check_colon_operand (const octave_value& val, const char *op_str) -{ - if (! val.is_double_type ()) - return; - - double dval = val.double_value (); - double intpart; - static const double out_of_range_top - = static_cast (std::numeric_limits::max ()) - + 1.; - - if (dval >= out_of_range_top - || dval < std::numeric_limits::min () - || std::modf (dval, &intpart) != 0.0) - error ("colon operator %s invalid (not an integer or out of range for given integer type)", op_str); -} - -// Return the difference between two unsigned integers as an unsigned -// integer of the same type. - -template ::value - && std::is_unsigned::value), - bool>::type = true> -UT -integer_difference (UT a, UT b) -{ - return a > b ? a - b : b - a; -} - -// Return the difference between two signed integers as an unsigned -// integer corresponding to the signed type. - -template ::type, - typename std::enable_if<(std::is_integral::value - && std::is_signed::value), - bool>::type = true> -UT -integer_difference (ST a, ST b) -{ - // Map to unsigned. - // Idea from https://stackoverflow.com/questions/10589559 - - static const UT offset - = UT (0) - static_cast (std::numeric_limits::min ()); - - UT au = static_cast (a) + offset; - UT bu = static_cast (b) + offset; - - return integer_difference (au, bu); -} - -// Number of elements in an integer range taking care to avoid -// overflow. Base and limit are of the same type. If they are -// unsigned, then increment is also of the same type. If they are -// signed, then the type of increment is the unsigned type -// corresponding to T. Assumes that the base and limit values are -// consistent with the sign of the original increment (not an empty -// range) so we can calculate numel with the absolute value of the -// increment and the absolute difference between the base and limit -// values. - -template ::type, - typename std::enable_if::value, - bool>::type = true> -octave_idx_type -range_numel_aux (T base, UT unsigned_increment, T limit) -{ - // Adding one to DIFF/INCREMENT may overflow, so check whether it is - // out of range before adding. - - UT nel_m1 = integer_difference (limit, base) / unsigned_increment; - - // FIXME: fix error message. - if (nel_m1 > std::numeric_limits::max () - 1) - error ("too many elements for range!"); - - return static_cast (nel_m1) + 1; -} - -// Convert signed range increment to unsigned. - -template ::type, - typename std::enable_if<(std::is_integral::value - && std::is_signed::value), - bool>::type = true> -UT -range_increment (ST increment) -{ - return (increment < 0 - ? UT (0) - static_cast (increment) - : static_cast (increment)); -} - -// "Convert" unsigned range increment to unsigned. A no-op, but -// needed to provide a consistent interface for other template -// functions. - -template ::type, - typename std::enable_if<(std::is_integral::value - && std::is_unsigned::value), - bool>::type = true> -UT -range_increment (UT increment) -{ - return increment; -} - -// Convert double range increment to unsigned. Enable by return type. - -template ::type> -typename std::enable_if<(std::is_integral::value - && std::is_unsigned::value), UT>::type -range_increment (double increment) -{ - double abs_increment = std::abs (increment); - - return static_cast (abs_increment); -} - -// Number of elements in an integer range base:increment:limit. Base, -// increment, and limit are of the same signed type. - -template ::value - && std::is_signed::value), - bool>::type = true> -octave_idx_type -range_numel (ST base, ST increment, ST limit) -{ - typedef typename std::make_unsigned::type UT; - - if (increment == 0 - || (increment > 0 && base > limit) - || (increment < 0 && base < limit)) - return 0; - - UT unsigned_increment = range_increment (increment); - - return range_numel_aux (base, unsigned_increment, limit); -} - -// Number of elements in an integer range base:increment:limit. Base, -// increment, and limit are unsigned and of the same type. - -template ::value - && std::is_unsigned::value), - bool>::type = true> -octave_idx_type -range_numel (UT base, UT increment, UT limit) -{ - // Unsigned, INCREMENT is always >= 0. - if (increment == 0 || base > limit) - return 0; - - return range_numel_aux (base, increment, limit); -} - -// Number of elements in an integer range base:increment:limit. Base -// and limit are of the same type and increment is a double value. - -template ::type, - typename std::enable_if::value, - bool>::type = true> -octave_idx_type -range_numel (T base, double increment, T limit) -{ - double intpart; - if (math::isnan (increment) || std::modf (increment, &intpart) != 0.0) - error ("colon operator increment invalid (not an integer)"); - - if (increment == 0 - || (increment > 0 && base > limit) - || (increment < 0 && base < limit)) - return 0; - - static const double out_of_range_top - = static_cast (std::numeric_limits::max ()) + 1.; - - double abs_increment = std::abs (increment); - - // Technically, this condition should be - // `abs_increment > std::numeric_limits::max ()`. - // But intmax('uint64') is not representable exactly as floating point - // number. Instead, it "rounds" up by 1 to 2^64. To account for - // this, use the following expression which works for all unsigned - // integer types. - if (abs_increment >= out_of_range_top) - return 1; - - UT unsigned_increment = range_increment (increment); - - return range_numel_aux (base, unsigned_increment, limit); -} - -// Make a range from integer values. Increment may be integer or double. - -template ::value - && std::is_arithmetic::value), - bool>::type = true> -octave_value -make_int_range (T base, IT increment, T limit) -{ - octave_idx_type nel = range_numel (base, increment, limit); - - // For now, we create arrays instead of range for all types - // except double. - - Array> result (dim_vector (1, nel)); - - if (nel > 0) - { - typedef typename std::make_unsigned::type UT; - - UT unsigned_increment = range_increment (increment); - - T val = base; - result.xelem (0) = val; - - if (limit > base) - { - for (octave_idx_type i = 1; i < nel; i++) - { - val += unsigned_increment; - result.xelem (i) = val; - } - } - else - { - for (octave_idx_type i = 1; i < nel; i++) - { - val -= unsigned_increment; - result.xelem (i) = val; - } - } - } - - return octave_value (result); -} - -// Make a range from floating point values. - -// FIXME: Try again to define memory efficient range classes for -// integer and floating point values? Maybe with the templates -// defined in this file we could do that in a reasonable way? -// Regardless of that, it might be good to provide special treatment -// of colon expressions in FOR loops so that we can eliminate the -// "is_for_cmd_expr / force_range" flag from the parser and the -// octave_value constructors for range objects. - -// NOTE: We define this function separately for float and double so -// that we can avoid having to instantiate ov_range. We DO -// instantiate range but only so we can take advantage of the -// range class to generate the corresponding array of float values -// and not have to duplicate that code here. - -template ::value, - bool>::type = true> -octave_value -make_float_range (T base, T increment, T limit, bool is_for_cmd_expr) -{ - if (math::isnan (base) - || math::isnan (increment) - || math::isnan (limit)) - return octave_value (numeric_limits::NaN ()); - - if (increment == 0 - || (increment > 0 && base > limit) - || (increment < 0 && base < limit)) - return octave_value (Array (dim_vector (1, 0))); - - // At this point, we know that the base and limit values are - // consistent with the sign of the increment (not an empty range). - - range r (base, increment, limit); - - if (! is_for_cmd_expr && ! r.is_storable ()) - error ("range with infinite number of elements cannot be stored"); - - return octave_value (r, is_for_cmd_expr); -} - -template ::value, - bool>::type = true> -octave_value -make_float_range (T base, T increment, T limit, bool is_for_cmd_expr) -{ - if (math::isnan (base) - || math::isnan (increment) - || math::isnan (limit)) - return octave_value (numeric_limits::NaN ()); - - if (increment == 0 - || (increment > 0 && base > limit) - || (increment < 0 && base < limit)) - return octave_value (Array (dim_vector (1, 0))); - - // At this point, we know that the base and limit values are - // consistent with the sign of the increment (not an empty range). - - range r (base, increment, limit); - - if (! is_for_cmd_expr && ! r.is_storable ()) - error ("range with infinite number of elements cannot be stored"); - - return octave_value (r.array_value ()); -} - -template ::value - || std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value), - bool>::type = true> -octave_value -make_int_range (const octave_value& base, const octave_value& increment, - const octave_value& limit) -{ - if (base.isempty () || increment.isempty () || limit.isempty ()) - return octave_value (Array (dim_vector (1, 0))); - - check_colon_operand (base, "lower bound"); - check_colon_operand (limit, "upper bound"); - - typename T::val_type base_val = octave_value_extract (base).value (); - typename T::val_type limit_val = octave_value_extract (limit).value (); - - if (increment.is_double_type ()) - { - double increment_val = increment.double_value (); - - return make_int_range (base_val, increment_val, limit_val); - } - - check_colon_operand (increment, "increment"); - - typename T::val_type increment_val - = octave_value_extract (increment).value (); - - return make_int_range (base_val, increment_val, limit_val); -} - -template ::value, - bool>::type = true> -octave_value -make_float_range (const octave_value& base, const octave_value& increment, - const octave_value& limit, bool is_for_cmd_expr) -{ - if (base.isempty () || increment.isempty () || limit.isempty ()) - return octave_value (Array (dim_vector (1, 0))); - - T base_val = octave_value_extract (base); - T increment_val = octave_value_extract (increment); - T limit_val = octave_value_extract (limit); - - return make_float_range (base_val, increment_val, limit_val, - is_for_cmd_expr); -} - - -octave_value -make_char_range (const octave_value& base, const octave_value& increment, - const octave_value& limit) -{ - octave_value retval; - - bool dq_str = (base.is_dq_string () || increment.is_dq_string () - || limit.is_dq_string ()); - - char type = dq_str ? '"' : '\''; - - if (base.isempty () || increment.isempty () || limit.isempty ()) - retval = octave_value ("", type); - else - { - Matrix mtx_base = base.matrix_value (true); - Matrix mtx_increment = increment.matrix_value (true); - Matrix mtx_limit = limit.matrix_value (true); - - range tmp (mtx_base(0), mtx_increment(0), mtx_limit(0)); - - retval = octave_value (tmp); - } - - return retval.convert_to_str (false, true, type); -} - -octave_value -colon_op (const octave_value& base, const octave_value& increment_arg, - const octave_value& limit, bool is_for_cmd_expr) -{ - if (base.isobject () || increment_arg.isobject () || limit.isobject ()) - { - octave_value_list tmp1; - - if (increment_arg.is_defined ()) - { - tmp1(2) = limit; - tmp1(1) = increment_arg; - tmp1(0) = base; - } - else - { - tmp1(1) = limit; - tmp1(0) = base; - } - - interpreter& interp = __get_interpreter__ (); - - symbol_table& symtab = interp.get_symbol_table (); - - octave_value fcn = symtab.find_function ("colon", tmp1); - - if (fcn.is_defined ()) - { - octave_value_list tmp2 = interp.feval (fcn, tmp1, 1); - - return tmp2(0); - } - } - - octave_value increment - = increment_arg.is_defined () ? increment_arg : octave_value (1.0); - - if (base.numel () > 1 || limit.numel () > 1 || increment.numel () > 1) - warning_with_id ("Octave:colon-nonscalar-argument", - "colon arguments should be scalars"); - - if (base.iscomplex () || limit.iscomplex () || increment.iscomplex ()) - warning_with_id ("Octave:colon-complex-argument", - "imaginary part of complex colon arguments is ignored"); - - // FIXME: is there a better way to do this job, maybe using type traits? - - builtin_type_t type_id = get_colon_op_type (base, increment, limit); - - // For compatibility with Matlab, don't allow the range used in - // a FOR loop expression to be converted to a Matrix. - - // For now, these functions create arrays instead of range for - // all types except double. - - switch (type_id) - { - case btyp_double: - case btyp_complex: - return make_float_range (base, increment, limit, is_for_cmd_expr); - - case btyp_float: - case btyp_float_complex: - return make_float_range (base, increment, limit, is_for_cmd_expr); - - case btyp_int8: - return make_int_range (base, increment, limit); - - case btyp_int16: - return make_int_range (base, increment, limit); - - case btyp_int32: - return make_int_range (base, increment, limit); - - case btyp_int64: - return make_int_range (base, increment, limit); - - case btyp_uint8: - return make_int_range (base, increment, limit); - - case btyp_uint16: - return make_int_range (base, increment, limit); - - case btyp_uint32: - return make_int_range (base, increment, limit); - - case btyp_uint64: - return make_int_range (base, increment, limit); - - case btyp_char: - return make_char_range (base, increment, limit); - - case btyp_unknown: - error ("incompatible types found in range expression"); - - default: - error ("invalid types found in range expression"); - } - - return octave_value (); -} - -OCTAVE_NORETURN static void -err_unary_op_conv (const std::string& on) -{ - error ("type conversion failed for unary operator '%s'", on.c_str ()); -} - -octave_value -unary_op (type_info& ti, octave_value::unary_op op, - const octave_value& v) -{ - octave_value retval; - - int t = v.type_id (); - - if (t == octave_class::static_type_id () - || t == octave_classdef::static_type_id ()) - { - type_info::unary_class_op_fcn f = ti.lookup_unary_class_op (op); - - if (! f) - err_unary_op (octave_value::unary_op_as_string (op), v.class_name ()); - - retval = f (v); - } - else - { - // FIXME: we need to handle overloading operators for built-in - // classes (double, char, int8, etc.) - - type_info::unary_op_fcn f = ti.lookup_unary_op (op, t); - - if (f) - retval = f (v.get_rep ()); - else - { - octave_value tv; - octave_base_value::type_conv_fcn cf - = v.numeric_conversion_function (); - - if (! cf) - err_unary_op (octave_value::unary_op_as_string (op), - v.type_name ()); - - octave_base_value *tmp = cf (v.get_rep ()); - - if (! tmp) - err_unary_op_conv (octave_value::unary_op_as_string (op)); - - tv = octave_value (tmp); - retval = unary_op (op, tv); - } - } - - return retval; -} - -octave_value -unary_op (octave_value::unary_op op, const octave_value& v) -{ - type_info& ti = __get_type_info__ (); - - return unary_op (ti, op, v); -} + { + octave_value retval; + + bool dq_str = (base.is_dq_string () || increment.is_dq_string () + || limit.is_dq_string ()); + + char type = dq_str ? '"' : '\''; + + if (base.isempty () || increment.isempty () || limit.isempty ()) + retval = octave_value ("", type); + else + { + Matrix mtx_base = base.matrix_value (true); + Matrix mtx_increment = increment.matrix_value (true); + Matrix mtx_limit = limit.matrix_value (true); + + range tmp (mtx_base(0), mtx_increment(0), mtx_limit(0)); + + retval = octave_value (tmp); + } + + return retval.convert_to_str (false, true, type); + } + + octave_value + colon_op (const octave_value& base, const octave_value& increment_arg, + const octave_value& limit, bool is_for_cmd_expr) + { + if (base.isobject () || increment_arg.isobject () || limit.isobject ()) + { + octave_value_list tmp1; + + if (increment_arg.is_defined ()) + { + tmp1(2) = limit; + tmp1(1) = increment_arg; + tmp1(0) = base; + } + else + { + tmp1(1) = limit; + tmp1(0) = base; + } + + interpreter& interp = __get_interpreter__ (); + + symbol_table& symtab = interp.get_symbol_table (); + + octave_value fcn = symtab.find_function ("colon", tmp1); + + if (fcn.is_defined ()) + { + octave_value_list tmp2 = interp.feval (fcn, tmp1, 1); + + return tmp2(0); + } + } + + octave_value increment + = increment_arg.is_defined () ? increment_arg : octave_value (1.0); + + if (base.numel () > 1 || limit.numel () > 1 || increment.numel () > 1) + warning_with_id ("Octave:colon-nonscalar-argument", + "colon arguments should be scalars"); + + if (base.iscomplex () || limit.iscomplex () || increment.iscomplex ()) + warning_with_id ("Octave:colon-complex-argument", + "imaginary part of complex colon arguments is ignored"); + + // FIXME: is there a better way to do this job, maybe using type traits? + + builtin_type_t type_id = get_colon_op_type (base, increment, limit); + + // For compatibility with Matlab, don't allow the range used in + // a FOR loop expression to be converted to a Matrix. + + // For now, these functions create arrays instead of range for + // all types except double. + + switch (type_id) + { + case btyp_double: + case btyp_complex: + return make_float_range (base, increment, limit, is_for_cmd_expr); + + case btyp_float: + case btyp_float_complex: + return make_float_range (base, increment, limit, is_for_cmd_expr); + + case btyp_int8: + return make_int_range (base, increment, limit); + + case btyp_int16: + return make_int_range (base, increment, limit); + + case btyp_int32: + return make_int_range (base, increment, limit); + + case btyp_int64: + return make_int_range (base, increment, limit); + + case btyp_uint8: + return make_int_range (base, increment, limit); + + case btyp_uint16: + return make_int_range (base, increment, limit); + + case btyp_uint32: + return make_int_range (base, increment, limit); + + case btyp_uint64: + return make_int_range (base, increment, limit); + + case btyp_char: + return make_char_range (base, increment, limit); + + case btyp_unknown: + error ("incompatible types found in range expression"); + + default: + error ("invalid types found in range expression"); + } + + return octave_value (); + } + + OCTAVE_NORETURN static void + err_unary_op_conv (const std::string& on) + { + error ("type conversion failed for unary operator '%s'", on.c_str ()); + } + + octave_value + unary_op (type_info& ti, octave_value::unary_op op, + const octave_value& v) + { + octave_value retval; + + int t = v.type_id (); + + if (t == octave_class::static_type_id () + || t == octave_classdef::static_type_id ()) + { + type_info::unary_class_op_fcn f = ti.lookup_unary_class_op (op); + + if (! f) + err_unary_op (octave_value::unary_op_as_string (op), v.class_name ()); + + retval = f (v); + } + else + { + // FIXME: we need to handle overloading operators for built-in + // classes (double, char, int8, etc.) + + type_info::unary_op_fcn f = ti.lookup_unary_op (op, t); + + if (f) + retval = f (v.get_rep ()); + else + { + octave_value tv; + octave_base_value::type_conv_fcn cf + = v.numeric_conversion_function (); + + if (! cf) + err_unary_op (octave_value::unary_op_as_string (op), + v.type_name ()); + + octave_base_value *tmp = cf (v.get_rep ()); + + if (! tmp) + err_unary_op_conv (octave_value::unary_op_as_string (op)); + + tv = octave_value (tmp); + retval = unary_op (op, tv); + } + } + + return retval; + } + + octave_value + unary_op (octave_value::unary_op op, const octave_value& v) + { + type_info& ti = __get_type_info__ (); + + return unary_op (ti, op, v); + } OCTAVE_END_NAMESPACE(octave) @@ -3748,8 +3714,7 @@ std::string& type_string, std::list& idx) { - const octave_map m = - arg.xmap_value ("%s: second argument must be a structure with fields 'type' and 'subs'", name); + const octave_map m = arg.xmap_value ("%s: second argument must be a structure with fields 'type' and 'subs'", name); if (m.nfields () != 2 || ! m.contains ("type") || ! m.contains ("subs")) error ("%s: second argument must be a structure with fields 'type' and 'subs'", diff -r 29d734430e5f -r deb553ac2c54 libinterp/octave-value/ov.h --- a/libinterp/octave-value/ov.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/octave-value/ov.h Tue Dec 06 15:45:27 2022 -0500 @@ -36,7 +36,6 @@ #include #include -#include "Range.h" #include "data-conv.h" #include "idx-vector.h" #include "mach-info.h" @@ -288,34 +287,6 @@ OCTINTERP_API octave_value (const Array& cellstr); OCTINTERP_API octave_value (const octave::idx_vector& idx, bool lazy = true); -private: - - // Remove when public constructors that use this function are removed. - static OCTINTERP_API octave_base_value * - make_range_rep_deprecated (double base, double inc, double limit); - - // Remove when public constructors that use this function are removed. - static OCTINTERP_API octave_base_value * - make_range_rep_deprecated (const Range& r, bool force_range); - -public: - -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'octave_value (range&)' instead") - octave_value (double base, double limit, double inc) - : m_rep (make_range_rep_deprecated (base, inc, limit)) - { - maybe_mutate (); - } - - OCTAVE_DEPRECATED (7, "use 'octave_value (range&)' instead") - octave_value (const Range& r, bool force_range = false) - : m_rep (make_range_rep_deprecated (r, force_range)) - { - maybe_mutate (); - } -#endif - OCTINTERP_API octave_value (const octave::range& r, bool force_range = false); @@ -552,15 +523,6 @@ return m_rep->do_index_op (idx, resize_ok); } -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'octave_value::index_op' instead") - octave_value do_index_op (const octave_value_list& idx, - bool resize_ok = false) - { - return index_op (idx, resize_ok); - } -#endif - OCTINTERP_API octave_value subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs); @@ -1459,27 +1421,10 @@ OCTINTERP_API octave_value& non_const_unary_op (unary_op op); -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'octave_value::non_const_unary_op' instead") - octave_value& do_non_const_unary_op (unary_op op) - { - return non_const_unary_op (op); - } -#endif - OCTINTERP_API octave_value& non_const_unary_op (unary_op op, const std::string& type, const std::list& idx); -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'octave_value::non_const_unary_op' instead") - octave_value& do_non_const_unary_op (unary_op op, const std::string& type, - const std::list& idx) - { - return non_const_unary_op (op, type, idx); - } -#endif - const octave_base_value& get_rep (void) const { return *m_rep; } bool is_copy_of (const octave_value& val) const { return m_rep == val.m_rep; } @@ -1736,87 +1681,6 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::unary_op' instead") -inline octave_value -do_unary_op (octave::type_info& ti, octave_value::unary_op op, - const octave_value& a) -{ - return octave::unary_op (ti, op, a); -} - -OCTAVE_DEPRECATED (7, "use 'octave::unary_op' instead") -inline octave_value -do_unary_op (octave_value::unary_op op, const octave_value& a) -{ - return octave::unary_op (op, a); -} - -OCTAVE_DEPRECATED (7, "use 'octave::binary_op' instead") -inline octave_value -do_binary_op (octave::type_info& ti, octave_value::binary_op op, - const octave_value& a, const octave_value& b) -{ - return octave::binary_op (ti, op, a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::binary_op' instead") -inline octave_value -do_binary_op (octave::type_info& ti, octave_value::compound_binary_op op, - const octave_value& a, const octave_value& b) -{ - return octave::binary_op (ti, op, a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::binary_op' instead") -inline octave_value -do_binary_op (octave_value::binary_op op, const octave_value& a, - const octave_value& b) -{ - return octave::binary_op (op, a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::binary_op' instead") -inline octave_value -do_binary_op (octave_value::compound_binary_op op, const octave_value& a, - const octave_value& b) -{ - return octave::binary_op (op, a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::cat_op' instead") -inline octave_value -do_cat_op (octave::type_info& ti, const octave_value& a, - const octave_value& b, const Array& ra_idx) -{ - return octave::cat_op (ti, a, b, ra_idx); -} - -OCTAVE_DEPRECATED (7, "use 'octave::cat_op' instead") -inline octave_value -do_cat_op (const octave_value& a, const octave_value& b, - const Array& ra_idx) -{ - return octave::cat_op (a, b, ra_idx); -} - -OCTAVE_DEPRECATED (7, "use 'octave::colon_op' instead") -inline octave_value -do_colon_op (const octave_value& base, const octave_value& increment, - const octave_value& limit, bool is_for_cmd_expr = false) -{ - return octave::colon_op (base, increment, limit, is_for_cmd_expr); -} - -OCTAVE_DEPRECATED (7, "use 'octave::colon_op' instead") -inline octave_value -do_colon_op (const octave_value& base, const octave_value& limit, - bool is_for_cmd_expr = false) -{ - return octave::colon_op (base, limit, is_for_cmd_expr); -} -#endif - #define OV_UNOP_FN(name) \ inline octave_value \ name (const octave_value& a) \ diff -r 29d734430e5f -r deb553ac2c54 libinterp/parse-tree/bp-table.h --- a/libinterp/parse-tree/bp-table.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/parse-tree/bp-table.h Tue Dec 06 15:45:27 2022 -0500 @@ -39,217 +39,172 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class tree_evaluator; - -struct bp_type -{ -public: - bp_type (int l, const std::string& c) : line (l), cond (c) { } - - //-------- + class tree_evaluator; - int line; - std::string cond; -}; + struct bp_type + { + public: + bp_type (int l, const std::string& c) : line (l), cond (c) { } -// Interface to breakpoints. -class OCTINTERP_API bp_table -{ -public: + //-------- - bp_table (tree_evaluator& tw) - : m_evaluator (tw), m_bp_set (), m_errors_that_stop (), - m_caught_that_stop (), m_warnings_that_stop () - { } - - ~bp_table (void) = default; - - // Set of breakpoint lines. - typedef std::set bp_lines; + int line; + std::string cond; + }; - typedef bp_lines::const_iterator const_bp_lines_iterator; - typedef bp_lines::iterator bp_lines_iterator; - - typedef std::map fname_line_map; - - typedef fname_line_map::const_iterator const_fname_line_map_iterator; - typedef fname_line_map::iterator fname_line_map_iterator; - - typedef std::map > fname_bp_map; - typedef fname_bp_map::const_iterator const_fname_bp_map_iterator; - typedef fname_bp_map::iterator fname_bp_map_iterator; + // Interface to breakpoints. + class OCTINTERP_API bp_table + { + public: -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'bp_table::add_breakpoints_in_function' instead") - int add_breakpoint (const std::string& fname = "", - const std::string& class_name = "", - int line = 1, - const std::string& condition = "") - { - return add_breakpoint_in_function (fname, class_name, line, condition); - } + bp_table (tree_evaluator& tw) + : m_evaluator (tw), m_bp_set (), m_errors_that_stop (), + m_caught_that_stop (), m_warnings_that_stop () + { } - OCTAVE_DEPRECATED (7, "use 'bp_table::add_breakpoints_in_function' instead") - bp_lines add_breakpoint (const std::string& fname = "", - const std::string& class_name = "", - const bp_lines& lines = bp_lines (), - const std::string& condition = "") - { - return add_breakpoints_in_function (fname, class_name, lines, condition); - } -#endif + ~bp_table (void) = default; + + // Set of breakpoint lines. + typedef std::set bp_lines; + + typedef bp_lines::const_iterator const_bp_lines_iterator; + typedef bp_lines::iterator bp_lines_iterator; - // Add a breakpoint at the nearest executable line in a function. - int add_breakpoint_in_function (const std::string& fname = "", - const std::string& class_name = "", - int line = 1, - const std::string& condition = ""); + typedef std::map fname_line_map; + + typedef fname_line_map::const_iterator const_fname_line_map_iterator; + typedef fname_line_map::iterator fname_line_map_iterator; - // Add a set of breakpoints at the nearest executable lines in a - // function. - bp_lines add_breakpoints_in_function (const std::string& fname = "", - const std::string& class_name = "", - const bp_lines& lines = bp_lines (), - const std::string& condition = ""); + typedef std::map > fname_bp_map; + typedef fname_bp_map::const_iterator const_fname_bp_map_iterator; + typedef fname_bp_map::iterator fname_bp_map_iterator; - // Add a breakpoint at the nearest executable line in a file. - int add_breakpoint_in_file (const std::string& file = "", - int line = 1, - const std::string& condition = ""); - - // Add a set of breakpoints at the nearest executable lines in a - // file. - bp_lines add_breakpoints_in_file (const std::string& file = "", - const bp_lines& lines = bp_lines (), + // Add a breakpoint at the nearest executable line in a function. + int add_breakpoint_in_function (const std::string& fname = "", + const std::string& class_name = "", + int line = 1, const std::string& condition = ""); -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'bp_table::remove_breakpoint_from_function' instead") - int remove_breakpoint (const std::string& fname = "", - int line = 1) - { - return remove_breakpoint_from_function (fname, line); - } + // Add a set of breakpoints at the nearest executable lines in a + // function. + bp_lines add_breakpoints_in_function (const std::string& fname = "", + const std::string& class_name = "", + const bp_lines& lines = bp_lines (), + const std::string& condition = ""); - OCTAVE_DEPRECATED (7, "use 'bp_table::remove_breakpoints_from_function' instead") - int remove_breakpoint (const std::string& fname = "", - const bp_lines& lines = bp_lines ()) - { - return remove_breakpoints_from_function (fname, lines); - } -#endif + // Add a breakpoint at the nearest executable line in a file. + int add_breakpoint_in_file (const std::string& file = "", + int line = 1, + const std::string& condition = ""); + + // Add a set of breakpoints at the nearest executable lines in a + // file. + bp_lines add_breakpoints_in_file (const std::string& file = "", + const bp_lines& lines = bp_lines (), + const std::string& condition = ""); - // Remove a breakpoint from the given line in file. - int remove_breakpoint_from_function (const std::string& fname = "", - int line = 1); + // Remove a breakpoint from the given line in file. + int remove_breakpoint_from_function (const std::string& fname = "", + int line = 1); - // Remove a set of breakpoints from the given lines in file. - int remove_breakpoints_from_function (const std::string& fname = "", - const bp_lines& lines = bp_lines ()); + // Remove a set of breakpoints from the given lines in file. + int remove_breakpoints_from_function (const std::string& fname = "", + const bp_lines& lines = bp_lines ()); - // Remove all the breakpoints in a specified function. - bp_lines remove_all_breakpoints_from_function (const std::string& fname, - bool silent = false); + // Remove all the breakpoints in a specified function. + bp_lines remove_all_breakpoints_from_function (const std::string& fname, + bool silent = false); - // Remove a breakpoint from the given line in file. - int remove_breakpoint_from_file (const std::string& file = "", - int line = 1); + // Remove a breakpoint from the given line in file. + int remove_breakpoint_from_file (const std::string& file = "", + int line = 1); - // Remove a set of breakpoints from the given lines in file. - int remove_breakpoints_from_file (const std::string& file = "", - const bp_lines& lines = bp_lines ()); + // Remove a set of breakpoints from the given lines in file. + int remove_breakpoints_from_file (const std::string& file = "", + const bp_lines& lines = bp_lines ()); -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'bp_table::remove_all_breakpoints_from_function' instead") - bp_lines remove_all_breakpoints_in_file (const std::string& fname, - bool silent = false) - { - return remove_all_breakpoints_from_function (fname, silent); - } -#endif + // Remove all the breakpoints from a file. + bp_lines remove_all_breakpoints_from_file (const std::string& file, + bool silent = false); + + // Remove all the breakpoints registered with octave. + void remove_all_breakpoints (void); - // Remove all the breakpoints from a file. - bp_lines remove_all_breakpoints_from_file (const std::string& file, - bool silent = false); + // Return all breakpoints. Each element of the map is a vector + // containing the breakpoints corresponding to a given function name. + fname_bp_map get_breakpoint_list (const octave_value_list& fname_list); + + bool have_breakpoints (void) { return (! m_bp_set.empty ()); } - // Remove all the breakpoints registered with octave. - void remove_all_breakpoints (void); - - // Return all breakpoints. Each element of the map is a vector - // containing the breakpoints corresponding to a given function name. - fname_bp_map get_breakpoint_list (const octave_value_list& fname_list); - - bool have_breakpoints (void) { return (! m_bp_set.empty ()); } + // Should we enter debugging for this particular error identifier? + bool debug_on_err (const std::string& id) + { + return (m_errors_that_stop.empty () || m_errors_that_stop.count (id)); + } - // Should we enter debugging for this particular error identifier? - bool debug_on_err (const std::string& id) - { - return (m_errors_that_stop.empty () || m_errors_that_stop.count (id)); - } + // Should we enter debugging for this particular identifier in a try/catch? + bool debug_on_caught (const std::string& id) + { + return (m_caught_that_stop.empty () || m_caught_that_stop.count (id)); + } - // Should we enter debugging for this particular identifier in a try/catch? - bool debug_on_caught (const std::string& id) - { - return (m_caught_that_stop.empty () || m_caught_that_stop.count (id)); - } + // Should we enter debugging for this particular warning identifier? + bool debug_on_warn (const std::string& id) + { + return (m_warnings_that_stop.empty () || m_warnings_that_stop.count (id)); + } - // Should we enter debugging for this particular warning identifier? - bool debug_on_warn (const std::string& id) - { - return (m_warnings_that_stop.empty () || m_warnings_that_stop.count (id)); - } + octave_map stop_on_err_warn_status (bool to_screen); + + void dbstop_process_map_args (const octave_map& mv); - octave_map stop_on_err_warn_status (bool to_screen); + void dbclear_all_signals (void); - void dbstop_process_map_args (const octave_map& mv); + bool condition_valid (const std::string& cond); - void dbclear_all_signals (void); - - bool condition_valid (const std::string& cond); + void parse_dbfunction_params (const char *who, + const octave_value_list& args, + std::string& fcn_name, + std::string& class_name, + bp_table::bp_lines& lines, + std::string& cond); - void parse_dbfunction_params (const char *who, - const octave_value_list& args, - std::string& fcn_name, - std::string& class_name, - bp_table::bp_lines& lines, - std::string& cond); + private: + + typedef std::set::const_iterator const_bp_set_iterator; + typedef std::set::iterator bp_set_iterator; -private: - - typedef std::set::const_iterator const_bp_set_iterator; - typedef std::set::iterator bp_set_iterator; + tree_evaluator& m_evaluator; - tree_evaluator& m_evaluator; - - // Set of function (.m file) names containing at least one breakpoint. - std::set m_bp_set; + // Set of function (.m file) names containing at least one breakpoint. + std::set m_bp_set; - // Set of error and warning message IDs that cause us to stop - // *if* Vdebug_on_error / Vdebug_on_caught / Vdebug_on_warning is set. - // Empty means stop on any error / caught error / warning. - std::set m_errors_that_stop; - std::set m_caught_that_stop; - std::set m_warnings_that_stop; + // Set of error and warning message IDs that cause us to stop + // *if* Vdebug_on_error / Vdebug_on_caught / Vdebug_on_warning is set. + // Empty means stop on any error / caught error / warning. + std::set m_errors_that_stop; + std::set m_caught_that_stop; + std::set m_warnings_that_stop; - void set_stop_flag (const char *who, const std::string& condition, - bool on_off); + void set_stop_flag (const char *who, const std::string& condition, + bool on_off); - void process_id_list (const char *who, const std::string& condition, - const octave_value_list& args, - int nargin, int& pos, bool on_off, - std::set& id_list); + void process_id_list (const char *who, const std::string& condition, + const octave_value_list& args, + int nargin, int& pos, bool on_off, + std::set& id_list); - bool add_breakpoint_1 (octave_user_code *fcn, const std::string& fname, - const bp_lines& line, const std::string& condition, - bp_lines& retval); + bool add_breakpoint_1 (octave_user_code *fcn, const std::string& fname, + const bp_lines& line, const std::string& condition, + bp_lines& retval); - int remove_breakpoint_1 (octave_user_code *fcn, const std::string&, - const bp_lines& lines); + int remove_breakpoint_1 (octave_user_code *fcn, const std::string&, + const bp_lines& lines); - bp_lines remove_all_breakpoints_in_file_1 (octave_user_code *fcn, - const std::string& fname); -}; + bp_lines remove_all_breakpoints_in_file_1 (octave_user_code *fcn, + const std::string& fname); + }; OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 libinterp/parse-tree/lex.h --- a/libinterp/parse-tree/lex.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/parse-tree/lex.h Tue Dec 06 15:45:27 2022 -0500 @@ -691,10 +691,6 @@ void warn_deprecated_syntax (const std::string& msg); - void warn_deprecated_operator (const std::string& deprecated_op, - const std::string& recommended_op, - const std::string& version); - void push_token (token *); token * current_token (void); diff -r 29d734430e5f -r deb553ac2c54 libinterp/parse-tree/lex.ll --- a/libinterp/parse-tree/lex.ll Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/parse-tree/lex.ll Tue Dec 06 15:45:27 2022 -0500 @@ -183,28 +183,6 @@ } \ while (0) -#define CMD_OR_DEPRECATED_OP(PATTERN, REPLACEMENT, VERSION, TOK) \ - do \ - { \ - curr_lexer->lexer_debug (PATTERN); \ - \ - if (curr_lexer->looks_like_command_arg ()) \ - { \ - yyless (0); \ - curr_lexer->push_start_state (COMMAND_START); \ - } \ - else \ - { \ - curr_lexer->warn_deprecated_operator (PATTERN, REPLACEMENT, \ - #VERSION); \ - /* set COMPAT to true here to avoid warning about \ - compatibility since we've already warned about the \ - operator being deprecated. */ \ - return curr_lexer->handle_op (TOK, false, true); \ - } \ - } \ - while (0) - #define CMD_OR_UNARY_OP(PATTERN, TOK, COMPAT) \ do \ { \ @@ -1088,28 +1066,6 @@ curr_lexer->m_string_text += '\v'; } -(\.\.\.){S}*{NL} { - curr_lexer->lexer_debug ("(\\.\\.\\.){S}*{NL}"); - - /* FIXME: Remove support for '...' continuation in Octave 9 */ - static const char *msg = "'...' continuations in double-quoted character strings were deprecated in version 7 and will not be allowed in a future version of Octave; please use '\\' instead"; - - curr_lexer->warn_deprecated_syntax (msg); - - HANDLE_STRING_CONTINUATION; - } - -\\{S}+{NL} { - curr_lexer->lexer_debug ("\\\\{S}+{NL}"); - - /* FIXME: Remove support for WS after line continuation in Octave 9 */ - static const char *msg = "whitespace after continuation markers in double-quoted character strings were deprecated in version 7 and will not be allowed in a future version of Octave"; - - curr_lexer->warn_deprecated_syntax (msg); - - HANDLE_STRING_CONTINUATION; - } - \\{NL} { curr_lexer->lexer_debug ("\\\\{NL}"); @@ -1302,17 +1258,6 @@ // Deprecated C preprocessor style continuation markers. %} -\\{S}*{NL} | -\\{S}*{CCHAR}{ANY_EXCEPT_NL}*{NL} { - curr_lexer->lexer_debug ("\\\\{S}*{NL}|\\\\{S}*{CCHAR}{ANY_EXCEPT_NL}*{NL}"); - - /* FIXME: Remove support for '\\' line continuation in Octave 9 */ - static const char *msg = "using continuation marker \\ outside of double quoted strings was deprecated in version 7 and will be removed from a future version of Octave, use ... instead"; - - curr_lexer->warn_deprecated_syntax (msg); - - curr_lexer->handle_continuation (); - } %{ // End of file. @@ -1644,13 +1589,10 @@ %} ":" { CMD_OR_OP (":", ':', true); } -".+" { CMD_OR_DEPRECATED_OP (".+", "+", 7, '+'); } -".-" { CMD_OR_DEPRECATED_OP (".-", "-", 7, '-'); } ".*" { CMD_OR_OP (".*", EMUL, true); } "./" { CMD_OR_OP ("./", EDIV, true); } ".\\" { CMD_OR_OP (".\\", ELEFTDIV, true); } ".^" { CMD_OR_OP (".^", EPOW, true); } -".**" { CMD_OR_DEPRECATED_OP (".**", ".^", 7, EPOW); } "<=" { CMD_OR_OP ("<=", EXPR_LE, true); } "==" { CMD_OR_OP ("==", EXPR_EQ, true); } "!=" { CMD_OR_OP ("!=", EXPR_NE, false); } @@ -1680,7 +1622,6 @@ } "^" { CMD_OR_OP ("^", POW, true); } -"**" { CMD_OR_DEPRECATED_OP ("**", "^", 7, POW); } "&&" { CMD_OR_OP ("&&", EXPR_AND_AND, true); } "||" { CMD_OR_OP ("||", EXPR_OR_OR, true); } @@ -1817,15 +1758,11 @@ "*=" { CMD_OR_OP ("*=", MUL_EQ, false); } "/=" { CMD_OR_OP ("/=", DIV_EQ, false); } "\\=" { CMD_OR_OP ("\\=", LEFTDIV_EQ, false); } -".+=" { CMD_OR_DEPRECATED_OP (".+=", "+=", 7, ADD_EQ); } -".-=" { CMD_OR_DEPRECATED_OP (".-=", "-=", 7, SUB_EQ); } ".*=" { CMD_OR_OP (".*=", EMUL_EQ, false); } "./=" { CMD_OR_OP ("./=", EDIV_EQ, false); } ".\\=" { CMD_OR_OP (".\\=", ELEFTDIV_EQ, false); } "^=" { CMD_OR_OP ("^=", POW_EQ, false); } -"**=" { CMD_OR_DEPRECATED_OP ("**=", "^=", 7, POW_EQ); } ".^=" { CMD_OR_OP (".^=", EPOW_EQ, false); } -".**=" { CMD_OR_DEPRECATED_OP (".**=", ".^=", 7, EPOW_EQ); } "&=" { CMD_OR_OP ("&=", AND_EQ, false); } "|=" { CMD_OR_OP ("|=", OR_EQ, false); } @@ -3667,16 +3604,6 @@ } void - base_lexer::warn_deprecated_operator (const std::string& deprecated_op, - const std::string& recommended_op, - const std::string& version) - { - std::string msg = "the '" + deprecated_op + "' operator was deprecated in version " + version + " and will not be allowed in a future version of Octave; please use '" + recommended_op + "' instead"; - - warn_deprecated_syntax (msg); - } - - void base_lexer::push_token (token *tok) { YYSTYPE *lval = yyget_lval (m_scanner); diff -r 29d734430e5f -r deb553ac2c54 libinterp/parse-tree/oct-lvalue.h --- a/libinterp/parse-tree/oct-lvalue.h Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/parse-tree/oct-lvalue.h Tue Dec 06 15:45:27 2022 -0500 @@ -81,14 +81,6 @@ void unary_op (octave_value::unary_op op); -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'octave_lvalue::unary_op' instead") - void do_unary_op (octave_value::unary_op op) - { - return unary_op (op); - } -#endif - octave_value value (void) const; private: diff -r 29d734430e5f -r deb553ac2c54 libinterp/parse-tree/pt-eval.cc --- a/libinterp/parse-tree/pt-eval.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/libinterp/parse-tree/pt-eval.cc Tue Dec 06 15:45:27 2022 -0500 @@ -75,616 +75,855 @@ OCTAVE_BEGIN_NAMESPACE(octave) -// Normal evaluator. - -class quit_debug_exception -{ -public: - - quit_debug_exception (bool all = false) : m_all (all) { } - - quit_debug_exception (const quit_debug_exception&) = default; - - quit_debug_exception& operator = (const quit_debug_exception&) = default; - - ~quit_debug_exception (void) = default; - - bool all (void) const { return m_all; } - -private: - - bool m_all; -}; - -class debugger -{ -public: - - enum execution_mode - { - EX_NORMAL = 0, - EX_CONTINUE = 1, - EX_QUIT = 2, - EX_QUIT_ALL = 3 + // Normal evaluator. + + class quit_debug_exception + { + public: + + quit_debug_exception (bool all = false) : m_all (all) { } + + quit_debug_exception (const quit_debug_exception&) = default; + + quit_debug_exception& operator = (const quit_debug_exception&) = default; + + ~quit_debug_exception (void) = default; + + bool all (void) const { return m_all; } + + private: + + bool m_all; }; - debugger (interpreter& interp, std::size_t level) - : m_interpreter (interp), m_level (level), - m_execution_mode (EX_NORMAL), m_in_debug_repl (false) - { } - - int server_loop (void); - - void repl (const std::string& prompt = "debug> "); - - bool in_debug_repl (void) const { return m_in_debug_repl; } - - void dbcont (void) { m_execution_mode = EX_CONTINUE; } - - void dbquit (bool all = false) - { - if (all) - m_execution_mode = EX_QUIT_ALL; - else - m_execution_mode = EX_QUIT; - } - - bool quitting_debugger (void) const; - -private: - - interpreter& m_interpreter; - - std::size_t m_level; - execution_mode m_execution_mode; - bool m_in_debug_repl; -}; - -// FIXME: Could the debugger server_loop and repl functions be merged -// with the corresponding tree_evaluator functions or do they need to -// remain separate? They perform nearly the same functions. - -int debugger::server_loop (void) -{ - // Process events from the event queue. - - tree_evaluator& tw = m_interpreter.get_evaluator (); - - void (tree_evaluator::*server_mode_fptr) (bool) - = &tree_evaluator::server_mode; - unwind_action act (server_mode_fptr, &tw, true); - - int exit_status = 0; - - do - { - if (m_execution_mode == EX_CONTINUE || tw.dbstep_flag ()) - break; - - if (quitting_debugger ()) - break; - - try - { - // FIXME: Should we call octave_quit in the octave::sleep - // and/or command_editor::run_event_hooks functions? - - octave_quit (); - - // FIXME: Running the event queue should be decoupled from - // the command_editor. - - // FIXME: Is it OK to use command_editor::run_event_hooks - // here? It may run more than one queued function per call, - // and it seems that the checks at the top of the loop - // probably need to be done after each individual event - // function is executed. For now, maybe the simplest thing - // would be to pass a predicate function (lambda expression) - // to the command_editor::run_event_hooks and have it check - // that and break out of the eval loop(s) if the condition - // is met? - - // FIXME: We should also use a condition variable to manage - // the execution of entries in the queue and eliminate the - // need for the busy-wait loop. - - command_editor::run_event_hooks (); - - release_unreferenced_dynamic_libraries (); - - sleep (0.1); - } - catch (const interrupt_exception&) - { - octave_interrupt_state = 1; - m_interpreter.recover_from_exception (); - - // Required newline when the user does Ctrl+C at the prompt. - if (m_interpreter.interactive ()) - octave_stdout << "\n"; - } - catch (const index_exception& e) - { - m_interpreter.recover_from_exception (); - - std::cerr << "error: unhandled index exception: " - << e.message () << " -- trying to return to prompt" - << std::endl; - } - catch (const execution_exception& ee) - { - error_system& es = m_interpreter.get_error_system (); - - es.save_exception (ee); - es.display_exception (ee); - - if (m_interpreter.interactive ()) - { - m_interpreter.recover_from_exception (); - } - else - { - // We should exit with a nonzero status. - exit_status = 1; - break; - } - } - catch (const quit_debug_exception& qde) - { - if (qde.all ()) - throw; - - // Continue in this debug level. - } - catch (const std::bad_alloc&) - { - m_interpreter.recover_from_exception (); - - std::cerr << "error: out of memory -- trying to return to prompt" - << std::endl; - } - } - while (exit_status == 0); - - if (exit_status == EOF) - { - if (m_interpreter.interactive ()) - octave_stdout << "\n"; - - exit_status = 0; - } - - return exit_status; -} - -void debugger::repl (const std::string& prompt_arg) -{ - unwind_protect frame; - - frame.protect_var (m_in_debug_repl); - frame.protect_var (m_execution_mode); - - m_in_debug_repl = true; - - tree_evaluator& tw = m_interpreter.get_evaluator (); - - bool silent = tw.quiet_breakpoint_flag (false); - - frame.add (&tree_evaluator::restore_frame, &tw, - tw.current_call_stack_frame_number ()); - - tw.goto_frame (tw.debug_frame ()); - - octave_user_code *caller = tw.current_user_code (); - std::string fcn_file_nm, fcn_nm; - - if (caller) - { - fcn_file_nm = caller->fcn_file_name (); - fcn_nm = fcn_file_nm.empty () ? caller->name () : fcn_file_nm; - } - - int curr_debug_line = tw.current_line (); - - std::ostringstream buf; - - input_system& input_sys = m_interpreter.get_input_system (); - - event_manager& evmgr = m_interpreter.get_event_manager (); - - if (! fcn_nm.empty ()) - { - if (input_sys.gud_mode ()) - { - static char ctrl_z = 'Z' & 0x1f; - - buf << ctrl_z << ctrl_z << fcn_nm << ':' << curr_debug_line; - } - else - { - // FIXME: we should come up with a clean way to detect - // that we are stopped on the no-op command that marks the - // end of a function or script. - - if (! silent) - { - std::shared_ptr frm = tw.current_user_frame (); - - frm->display_stopped_in_message (buf); - } - - evmgr.enter_debugger_event (fcn_nm, fcn_file_nm, curr_debug_line); - - evmgr.set_workspace (); - - frame.add (&event_manager::execute_in_debugger_event, &evmgr, - fcn_nm, curr_debug_line); - - if (! silent) - { - std::string line_buf; - - if (caller) - line_buf = caller->get_code_line (curr_debug_line); - - if (! line_buf.empty ()) - buf << curr_debug_line << ": " << line_buf; - } - } - } - - if (silent) - command_editor::erase_empty_line (true); - - std::string stopped_in_msg = buf.str (); - - if (m_interpreter.server_mode ()) - { - if (! stopped_in_msg.empty ()) - octave_stdout << stopped_in_msg << std::endl; - - evmgr.push_event_queue (); - - frame.add (&event_manager::pop_event_queue, &evmgr); - - frame.add (&tree_evaluator::set_parser, &tw, tw.get_parser ()); - - std::shared_ptr - debug_parser (new push_parser (m_interpreter)); - - tw.set_parser (debug_parser); - - server_loop (); - } - else + class debugger + { + public: + + enum execution_mode + { + EX_NORMAL = 0, + EX_CONTINUE = 1, + EX_QUIT = 2, + EX_QUIT_ALL = 3 + }; + + debugger (interpreter& interp, std::size_t level) + : m_interpreter (interp), m_level (level), + m_execution_mode (EX_NORMAL), m_in_debug_repl (false) + { } + + int server_loop (void); + + void repl (const std::string& prompt = "debug> "); + + bool in_debug_repl (void) const { return m_in_debug_repl; } + + void dbcont (void) { m_execution_mode = EX_CONTINUE; } + + void dbquit (bool all = false) { - if (! stopped_in_msg.empty ()) - std::cerr << stopped_in_msg << std::endl; - - std::string tmp_prompt = prompt_arg; - if (m_level > 0) - tmp_prompt = "[" + std::to_string (m_level) + "]" + prompt_arg; - - frame.add (&input_system::set_PS1, &input_sys, input_sys.PS1 ()); - input_sys.PS1 (tmp_prompt); - - if (! m_interpreter.interactive ()) - { - void (interpreter::*interactive_fptr) (bool) - = &interpreter::interactive; - frame.add (interactive_fptr, &m_interpreter, - m_interpreter.interactive ()); - - m_interpreter.interactive (true); - - // FIXME: should debugging be possible in an embedded - // interpreter? - - application *app = application::app (); - - if (app) - { - void (application::*forced_interactive_fptr) (bool) - = &application::forced_interactive; - frame.add (forced_interactive_fptr, app, - app->forced_interactive ()); - - app->forced_interactive (true); - } - } - -#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER) - - input_reader reader (m_interpreter); - - push_parser debug_parser (m_interpreter); - -#else - - parser debug_parser (m_interpreter); - -#endif - - error_system& es = m_interpreter.get_error_system (); - - while (m_in_debug_repl) - { - if (m_execution_mode == EX_CONTINUE || tw.dbstep_flag ()) - break; - - if (quitting_debugger ()) - break; - - try - { - debug_parser.reset (); - -#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER) - - int retval = 0; - - std::string prompt - = command_editor::decode_prompt_string (tmp_prompt); - - do - { - bool eof = false; - std::string input_line = reader.get_input (prompt, eof); - - if (eof) - { - retval = EOF; - break; - } - - retval = debug_parser.run (input_line, false); - - prompt = command_editor::decode_prompt_string (input_sys.PS2 ()); - } - while (retval < 0); - -#else - - int retval = debug_parser.run (); - -#endif - if (command_editor::interrupt (false)) - { - // Break regardless of m_execution_mode value. - - quitting_debugger (); - - break; - } - else - { - if (retval == 0) - { - std::shared_ptr stmt_list - = debug_parser.statement_list (); - - if (stmt_list) - stmt_list->accept (tw); - - if (octave_completion_matches_called) - octave_completion_matches_called = false; - - // FIXME: the following statement is here because - // the last command may have been a dbup, dbdown, or - // dbstep command that changed the current debug - // frame. If so, we need to reset the current frame - // for the call stack. But is this right way to do - // this job? What if the statement list was - // something like "dbup; dbstack"? Will the call to - // dbstack use the right frame? If not, how can we - // fix this problem? - tw.goto_frame (tw.debug_frame ()); - } - - octave_quit (); - } - } - catch (const execution_exception& ee) - { - es.save_exception (ee); - es.display_exception (ee); - - // Ignore errors when in debugging mode; - m_interpreter.recover_from_exception (); - } - catch (const quit_debug_exception& qde) - { - if (qde.all ()) - throw; - - // Continue in this debug level. - } - } - } -} - -bool debugger::quitting_debugger (void) const -{ - if (m_execution_mode == EX_QUIT) - { - // If there is no enclosing debug level or the top-level - // repl is not active, handle dbquit the same as dbcont. - - if (m_level > 0 || m_interpreter.server_mode () - || m_interpreter.in_top_level_repl ()) - throw quit_debug_exception (); + if (all) + m_execution_mode = EX_QUIT_ALL; else - return true; + m_execution_mode = EX_QUIT; } - if (m_execution_mode == EX_QUIT_ALL) - { - // If the top-level repl is not active, handle "dbquit all" - // the same as dbcont. - - if (m_interpreter.server_mode () || m_interpreter.in_top_level_repl ()) - throw quit_debug_exception (true); - else - return true; - } - - return false; -} - -bool tree_evaluator::at_top_level (void) const -{ - return m_call_stack.at_top_level (); -} - -std::string -tree_evaluator::mfilename (const std::string& opt) const -{ - std::string fname; - - octave_user_code *fcn = m_call_stack.current_user_code (); - - if (fcn) - { - fname = fcn->fcn_file_name (); - - if (fname.empty ()) - fname = fcn->name (); - } - - if (opt == "fullpathext") - return fname; - - std::size_t dpos = fname.rfind (sys::file_ops::dir_sep_char ()); - std::size_t epos = fname.rfind ('.'); - - if (epos <= dpos+1) - epos = std::string::npos; - - if (epos != std::string::npos) - fname = fname.substr (0, epos); - - if (opt == "fullpath") - return fname; - - if (dpos != std::string::npos) - fname = fname.substr (dpos+1); - - return fname; -} - -void tree_evaluator::parse_and_execute (const std::string& input, - bool& incomplete_parse) -{ - incomplete_parse = false; - - unwind_protect_var upv (m_in_top_level_repl, true); - - if (at_top_level ()) - { - dbstep_flag (0); - reset_debug_state (); - } - - // FIXME: OK to do this job here, or should it be in the functions - // that do the actual prompting? - - // Update the time stamp for the "prompt" so that automatically - // finding modified files based on file modification times will - // work. In the future, we may do something completely different to - // check for changes to files but for now, we rely on the prompt - // time stamp to limit the checks for file modification times. - - Vlast_prompt_time.stamp (); - - bool eof = false; - - event_manager& evmgr = m_interpreter.get_event_manager (); - - if (command_history::add (input)) - evmgr.append_history (input); - - m_exit_status = m_parser->run (input, eof); - - if (m_exit_status == 0) - { - std::shared_ptr - stmt_list = m_parser->statement_list (); - - if (stmt_list) - { - command_editor::increment_current_command_number (); - - eval (stmt_list, m_interpreter.interactive ()); - - evmgr.set_workspace (); - } - else if (m_parser->at_end_of_input ()) - m_exit_status = EOF; - } - else - incomplete_parse = true; - - // FIXME: Should we be checking m_exit_status or incomplete_parse or - // both here? Could EOF have a value other than -1, and is there - // possible confusion between that state and the parser returning -1? - - if (m_exit_status == -1) - m_exit_status = 0; - else - m_parser->reset (); - - evmgr.pre_input_event (); -} - -void tree_evaluator::get_line_and_eval (void) -{ - std::mutex mtx; - std::unique_lock lock (mtx); - std::condition_variable cv; - bool incomplete_parse = false; - bool evaluation_pending = false; - bool exiting = false; - - input_system& input_sys = m_interpreter.get_input_system (); - event_manager& evmgr = m_interpreter.get_event_manager (); - - while (true) - { - // FIXME: Detect EOF? Use readline? If - // so, then we need to disable idle event loop hook function - // execution. - - std::string ps = incomplete_parse ? input_sys.PS2 () : input_sys.PS1 (); - - std::cout << command_editor::decode_prompt_string (ps); - - std::string input; - std::getline (std::cin, input); - - if (input.empty ()) - continue; - - incomplete_parse = false; - evaluation_pending = true; - exiting = false; - - evmgr.post_event - ([&] (interpreter& interp) + bool quitting_debugger (void) const; + + private: + + interpreter& m_interpreter; + + std::size_t m_level; + execution_mode m_execution_mode; + bool m_in_debug_repl; + }; + + // FIXME: Could the debugger server_loop and repl functions be merged + // with the corresponding tree_evaluator functions or do they need to + // remain separate? They perform nearly the same functions. + + int debugger::server_loop (void) + { + // Process events from the event queue. + + tree_evaluator& tw = m_interpreter.get_evaluator (); + + void (tree_evaluator::*server_mode_fptr) (bool) + = &tree_evaluator::server_mode; + unwind_action act (server_mode_fptr, &tw, true); + + int exit_status = 0; + + do { - // INTERPRETER THREAD - - std::lock_guard local_lock (mtx); + if (m_execution_mode == EX_CONTINUE || tw.dbstep_flag ()) + break; + + if (quitting_debugger ()) + break; try { - interp.parse_and_execute (input, incomplete_parse); + // FIXME: Should we call octave_quit in the octave::sleep + // and/or command_editor::run_event_hooks functions? + + octave_quit (); + + // FIXME: Running the event queue should be decoupled from + // the command_editor. + + // FIXME: Is it OK to use command_editor::run_event_hooks + // here? It may run more than one queued function per call, + // and it seems that the checks at the top of the loop + // probably need to be done after each individual event + // function is executed. For now, maybe the simplest thing + // would be to pass a predicate function (lambda expression) + // to the command_editor::run_event_hooks and have it check + // that and break out of the eval loop(s) if the condition + // is met? + + // FIXME: We should also use a condition variable to manage + // the execution of entries in the queue and eliminate the + // need for the busy-wait loop. + + command_editor::run_event_hooks (); + + release_unreferenced_dynamic_libraries (); + + sleep (0.1); + } + catch (const interrupt_exception&) + { + octave_interrupt_state = 1; + m_interpreter.recover_from_exception (); + + // Required newline when the user does Ctrl+C at the prompt. + if (m_interpreter.interactive ()) + octave_stdout << "\n"; + } + catch (const index_exception& e) + { + m_interpreter.recover_from_exception (); + + std::cerr << "error: unhandled index exception: " + << e.message () << " -- trying to return to prompt" + << std::endl; + } + catch (const execution_exception& ee) + { + error_system& es = m_interpreter.get_error_system (); + + es.save_exception (ee); + es.display_exception (ee); + + if (m_interpreter.interactive ()) + { + m_interpreter.recover_from_exception (); + } + else + { + // We should exit with a nonzero status. + exit_status = 1; + break; + } + } + catch (const quit_debug_exception& qde) + { + if (qde.all ()) + throw; + + // Continue in this debug level. + } + catch (const std::bad_alloc&) + { + m_interpreter.recover_from_exception (); + + std::cerr << "error: out of memory -- trying to return to prompt" + << std::endl; } - catch (const exit_exception&) + } + while (exit_status == 0); + + if (exit_status == EOF) + { + if (m_interpreter.interactive ()) + octave_stdout << "\n"; + + exit_status = 0; + } + + return exit_status; + } + + void debugger::repl (const std::string& prompt_arg) + { + unwind_protect frame; + + frame.protect_var (m_in_debug_repl); + frame.protect_var (m_execution_mode); + + m_in_debug_repl = true; + + tree_evaluator& tw = m_interpreter.get_evaluator (); + + bool silent = tw.quiet_breakpoint_flag (false); + + frame.add (&tree_evaluator::restore_frame, &tw, + tw.current_call_stack_frame_number ()); + + tw.goto_frame (tw.debug_frame ()); + + octave_user_code *caller = tw.current_user_code (); + std::string fcn_file_nm, fcn_nm; + + if (caller) + { + fcn_file_nm = caller->fcn_file_name (); + fcn_nm = fcn_file_nm.empty () ? caller->name () : fcn_file_nm; + } + + int curr_debug_line = tw.current_line (); + + std::ostringstream buf; + + input_system& input_sys = m_interpreter.get_input_system (); + + event_manager& evmgr = m_interpreter.get_event_manager (); + + if (! fcn_nm.empty ()) + { + if (input_sys.gud_mode ()) + { + static char ctrl_z = 'Z' & 0x1f; + + buf << ctrl_z << ctrl_z << fcn_nm << ':' << curr_debug_line; + } + else + { + // FIXME: we should come up with a clean way to detect + // that we are stopped on the no-op command that marks the + // end of a function or script. + + if (! silent) + { + std::shared_ptr frm = tw.current_user_frame (); + + frm->display_stopped_in_message (buf); + } + + evmgr.enter_debugger_event (fcn_nm, fcn_file_nm, curr_debug_line); + + evmgr.set_workspace (); + + frame.add (&event_manager::execute_in_debugger_event, &evmgr, + fcn_nm, curr_debug_line); + + if (! silent) + { + std::string line_buf; + + if (caller) + line_buf = caller->get_code_line (curr_debug_line); + + if (! line_buf.empty ()) + buf << curr_debug_line << ": " << line_buf; + } + } + } + + if (silent) + command_editor::erase_empty_line (true); + + std::string stopped_in_msg = buf.str (); + + if (m_interpreter.server_mode ()) + { + if (! stopped_in_msg.empty ()) + octave_stdout << stopped_in_msg << std::endl; + + evmgr.push_event_queue (); + + frame.add (&event_manager::pop_event_queue, &evmgr); + + frame.add (&tree_evaluator::set_parser, &tw, tw.get_parser ()); + + std::shared_ptr + debug_parser (new push_parser (m_interpreter)); + + tw.set_parser (debug_parser); + + server_loop (); + } + else + { + if (! stopped_in_msg.empty ()) + std::cerr << stopped_in_msg << std::endl; + + std::string tmp_prompt = prompt_arg; + if (m_level > 0) + tmp_prompt = "[" + std::to_string (m_level) + "]" + prompt_arg; + + frame.add (&input_system::set_PS1, &input_sys, input_sys.PS1 ()); + input_sys.PS1 (tmp_prompt); + + if (! m_interpreter.interactive ()) + { + void (interpreter::*interactive_fptr) (bool) + = &interpreter::interactive; + frame.add (interactive_fptr, &m_interpreter, + m_interpreter.interactive ()); + + m_interpreter.interactive (true); + + // FIXME: should debugging be possible in an embedded + // interpreter? + + application *app = application::app (); + + if (app) + { + void (application::*forced_interactive_fptr) (bool) + = &application::forced_interactive; + frame.add (forced_interactive_fptr, app, + app->forced_interactive ()); + + app->forced_interactive (true); + } + } + +#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER) + + input_reader reader (m_interpreter); + + push_parser debug_parser (m_interpreter); + +#else + + parser debug_parser (m_interpreter); + +#endif + + error_system& es = m_interpreter.get_error_system (); + + while (m_in_debug_repl) { - evaluation_pending = false; - exiting = true; - cv.notify_all (); - throw; + if (m_execution_mode == EX_CONTINUE || tw.dbstep_flag ()) + break; + + if (quitting_debugger ()) + break; + + try + { + debug_parser.reset (); + +#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER) + + int retval = 0; + + std::string prompt + = command_editor::decode_prompt_string (tmp_prompt); + + do + { + bool eof = false; + std::string input_line = reader.get_input (prompt, eof); + + if (eof) + { + retval = EOF; + break; + } + + retval = debug_parser.run (input_line, false); + + prompt = command_editor::decode_prompt_string (input_sys.PS2 ()); + } + while (retval < 0); + +#else + + int retval = debug_parser.run (); + +#endif + if (command_editor::interrupt (false)) + { + // Break regardless of m_execution_mode value. + + quitting_debugger (); + + break; + } + else + { + if (retval == 0) + { + std::shared_ptr stmt_list + = debug_parser.statement_list (); + + if (stmt_list) + stmt_list->accept (tw); + + if (octave_completion_matches_called) + octave_completion_matches_called = false; + + // FIXME: the following statement is here because + // the last command may have been a dbup, dbdown, or + // dbstep command that changed the current debug + // frame. If so, we need to reset the current frame + // for the call stack. But is this right way to do + // this job? What if the statement list was + // something like "dbup; dbstack"? Will the call to + // dbstack use the right frame? If not, how can we + // fix this problem? + tw.goto_frame (tw.debug_frame ()); + } + + octave_quit (); + } + } + catch (const execution_exception& ee) + { + es.save_exception (ee); + es.display_exception (ee); + + // Ignore errors when in debugging mode; + m_interpreter.recover_from_exception (); + } + catch (const quit_debug_exception& qde) + { + if (qde.all ()) + throw; + + // Continue in this debug level. + } + } + } + } + + bool debugger::quitting_debugger (void) const + { + if (m_execution_mode == EX_QUIT) + { + // If there is no enclosing debug level or the top-level + // repl is not active, handle dbquit the same as dbcont. + + if (m_level > 0 || m_interpreter.server_mode () + || m_interpreter.in_top_level_repl ()) + throw quit_debug_exception (); + else + return true; + } + + if (m_execution_mode == EX_QUIT_ALL) + { + // If the top-level repl is not active, handle "dbquit all" + // the same as dbcont. + + if (m_interpreter.server_mode () || m_interpreter.in_top_level_repl ()) + throw quit_debug_exception (true); + else + return true; + } + + return false; + } + + bool tree_evaluator::at_top_level (void) const + { + return m_call_stack.at_top_level (); + } + + std::string + tree_evaluator::mfilename (const std::string& opt) const + { + std::string fname; + + octave_user_code *fcn = m_call_stack.current_user_code (); + + if (fcn) + { + fname = fcn->fcn_file_name (); + + if (fname.empty ()) + fname = fcn->name (); + } + + if (opt == "fullpathext") + return fname; + + std::size_t dpos = fname.rfind (sys::file_ops::dir_sep_char ()); + std::size_t epos = fname.rfind ('.'); + + if (epos <= dpos+1) + epos = std::string::npos; + + if (epos != std::string::npos) + fname = fname.substr (0, epos); + + if (opt == "fullpath") + return fname; + + if (dpos != std::string::npos) + fname = fname.substr (dpos+1); + + return fname; + } + + void tree_evaluator::parse_and_execute (const std::string& input, + bool& incomplete_parse) + { + incomplete_parse = false; + + unwind_protect_var upv (m_in_top_level_repl, true); + + if (at_top_level ()) + { + dbstep_flag (0); + reset_debug_state (); + } + + // FIXME: OK to do this job here, or should it be in the functions + // that do the actual prompting? + + // Update the time stamp for the "prompt" so that automatically + // finding modified files based on file modification times will + // work. In the future, we may do something completely different to + // check for changes to files but for now, we rely on the prompt + // time stamp to limit the checks for file modification times. + + Vlast_prompt_time.stamp (); + + bool eof = false; + + event_manager& evmgr = m_interpreter.get_event_manager (); + + if (command_history::add (input)) + evmgr.append_history (input); + + m_exit_status = m_parser->run (input, eof); + + if (m_exit_status == 0) + { + std::shared_ptr + stmt_list = m_parser->statement_list (); + + if (stmt_list) + { + command_editor::increment_current_command_number (); + + eval (stmt_list, m_interpreter.interactive ()); + + evmgr.set_workspace (); + } + else if (m_parser->at_end_of_input ()) + m_exit_status = EOF; + } + else + incomplete_parse = true; + + // FIXME: Should we be checking m_exit_status or incomplete_parse or + // both here? Could EOF have a value other than -1, and is there + // possible confusion between that state and the parser returning -1? + + if (m_exit_status == -1) + m_exit_status = 0; + else + m_parser->reset (); + + evmgr.pre_input_event (); + } + + void tree_evaluator::get_line_and_eval (void) + { + std::mutex mtx; + std::unique_lock lock (mtx); + std::condition_variable cv; + bool incomplete_parse = false; + bool evaluation_pending = false; + bool exiting = false; + + input_system& input_sys = m_interpreter.get_input_system (); + event_manager& evmgr = m_interpreter.get_event_manager (); + + while (true) + { + // FIXME: Detect EOF? Use readline? If + // so, then we need to disable idle event loop hook function + // execution. + + std::string ps = incomplete_parse ? input_sys.PS2 () : input_sys.PS1 (); + + std::cout << command_editor::decode_prompt_string (ps); + + std::string input; + std::getline (std::cin, input); + + if (input.empty ()) + continue; + + incomplete_parse = false; + evaluation_pending = true; + exiting = false; + + evmgr.post_event + ([&] (interpreter& interp) + { + // INTERPRETER THREAD + + std::lock_guard local_lock (mtx); + + try + { + interp.parse_and_execute (input, incomplete_parse); + } + catch (const exit_exception&) + { + evaluation_pending = false; + exiting = true; + cv.notify_all (); + throw; + } + catch (const execution_exception& ee) + { + error_system& es = m_interpreter.get_error_system (); + + es.save_exception (ee); + es.display_exception (ee); + + if (m_interpreter.interactive ()) + { + m_interpreter.recover_from_exception (); + m_parser->reset (); + evaluation_pending = false; + cv.notify_all (); + } + else + { + evaluation_pending = false; + cv.notify_all (); + throw exit_exception (1); + } + } + catch (...) + { + evaluation_pending = false; + cv.notify_all (); + throw; + } + + evaluation_pending = false; + cv.notify_all (); + }); + + // Wait until evaluation is finished before prompting for input + // again. + + cv.wait (lock, [&] { return ! evaluation_pending; }); + + if (exiting) + break; + } + } + + int tree_evaluator::repl (void) + { + // The big loop. Read, Eval, Print, Loop. Normally user + // interaction at the command line in a terminal session, but we may + // also end up here when reading from a pipe or when stdin is + // connected to a file by the magic of input redirection. + + int exit_status = 0; + + // FIXME: should this choice be a command-line option? Note that we + // intend that the push parser interface only be used for + // interactive sessions. + +#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER) + static bool use_command_line_push_parser = true; +#else + static bool use_command_line_push_parser = false; +#endif + + // The following logic is written as it is to allow easy transition + // to setting USE_COMMAND_LINE_PUSH_PARSER at run time and to + // simplify the logic of the main loop below by using the same + // base_parser::run interface for both push and pull parsers. + + std::shared_ptr repl_parser; + + if (m_interpreter.interactive ()) + { + if (use_command_line_push_parser) + { + push_parser *pp + = new push_parser (m_interpreter, + new input_reader (m_interpreter)); + + repl_parser = std::shared_ptr (pp); + } + else + { + parser *pp = new parser (new lexer (m_interpreter)); + repl_parser = std::shared_ptr (pp); + } + } + else + { + parser *pp = new parser (new lexer (stdin, m_interpreter)); + repl_parser = std::shared_ptr (pp); + } + + do + { + try + { + unwind_protect_var upv (m_in_top_level_repl, true); + + repl_parser->reset (); + + if (at_top_level ()) + { + dbstep_flag (0); + reset_debug_state (); + } + + exit_status = repl_parser->run (); + + if (exit_status == 0) + { + std::shared_ptr + stmt_list = repl_parser->statement_list (); + + if (stmt_list) + { + command_editor::increment_current_command_number (); + + eval (stmt_list, m_interpreter.interactive ()); + } + else if (repl_parser->at_end_of_input ()) + { + exit_status = EOF; + break; + } + } + } + catch (const interrupt_exception&) + { + m_interpreter.recover_from_exception (); + + // Required newline when the user does Ctrl+C at the prompt. + if (m_interpreter.interactive ()) + octave_stdout << "\n"; + } + catch (const index_exception& ie) + { + m_interpreter.recover_from_exception (); + + std::cerr << "error: unhandled index exception: " + << ie.message () << " -- trying to return to prompt" + << std::endl; + } + catch (const execution_exception& ee) + { + error_system& es = m_interpreter.get_error_system (); + + es.save_exception (ee); + es.display_exception (ee); + + if (m_interpreter.interactive ()) + m_interpreter.recover_from_exception (); + else + { + // We should exit with a nonzero status. + exit_status = 1; + break; + } + } + catch (const quit_debug_exception&) + { + m_interpreter.recover_from_exception (); + + // FIXME: Does anything else need to happen here? + } + catch (const std::bad_alloc&) + { + m_interpreter.recover_from_exception (); + + std::cerr << "error: out of memory -- trying to return to prompt" + << std::endl; + } + } + while (exit_status == 0); + + if (exit_status == EOF) + { + if (m_interpreter.interactive ()) + octave_stdout << "\n"; + + exit_status = 0; + } + + return exit_status; + } + + int tree_evaluator::server_loop (void) + { + // Process events from the event queue. + + unwind_protect_var upv1 (m_server_mode, true); + + m_exit_status = 0; + + std::shared_ptr parser (new push_parser (m_interpreter)); + unwind_protect_var> upv2 (m_parser, parser); + + // FIXME: We are currently resetting the parser after every call to + // recover_from_exception. This action should probably be handled + // in a more consistent way, but resetting the parser in every call + // to interpreter::recover_from_exception appears to cause + // segfaults in the test suite. + + do + { + try + { + // FIXME: Should we call octave_quit in the octave::sleep + // and/or command_editor::run_event_hooks functions? + + octave_quit (); + + // FIXME: Running the event queue should be decoupled from + // the command_editor. We should also use a condition + // variable to manage the execution of entries in the queue + // and eliminate the need for the busy-wait loop. + + command_editor::run_event_hooks (); + + release_unreferenced_dynamic_libraries (); + + sleep (0.1); + } + catch (const interrupt_exception&) + { + octave_interrupt_state = 1; + m_interpreter.recover_from_exception (); + m_parser->reset (); + + // Required newline when the user does Ctrl+C at the prompt. + if (m_interpreter.interactive ()) + octave_stdout << "\n"; + } + catch (const index_exception& e) + { + m_interpreter.recover_from_exception (); + m_parser->reset (); + + std::cerr << "error: unhandled index exception: " + << e.message () << " -- trying to return to prompt" + << std::endl; } catch (const execution_exception& ee) { @@ -697,1133 +936,874 @@ { m_interpreter.recover_from_exception (); m_parser->reset (); - evaluation_pending = false; - cv.notify_all (); } else { - evaluation_pending = false; - cv.notify_all (); - throw exit_exception (1); + // We should exit with a nonzero status. + m_exit_status = 1; + break; } } - catch (...) + catch (const quit_debug_exception&) { - evaluation_pending = false; - cv.notify_all (); - throw; - } - - evaluation_pending = false; - cv.notify_all (); - }); - - // Wait until evaluation is finished before prompting for input - // again. - - cv.wait (lock, [&] { return ! evaluation_pending; }); - - if (exiting) - break; - } -} - -int tree_evaluator::repl (void) -{ - // The big loop. Read, Eval, Print, Loop. Normally user - // interaction at the command line in a terminal session, but we may - // also end up here when reading from a pipe or when stdin is - // connected to a file by the magic of input redirection. - - int exit_status = 0; - - // FIXME: should this choice be a command-line option? Note that we - // intend that the push parser interface only be used for - // interactive sessions. - -#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER) - static bool use_command_line_push_parser = true; -#else - static bool use_command_line_push_parser = false; -#endif - - // The following logic is written as it is to allow easy transition - // to setting USE_COMMAND_LINE_PUSH_PARSER at run time and to - // simplify the logic of the main loop below by using the same - // base_parser::run interface for both push and pull parsers. - - std::shared_ptr repl_parser; - - if (m_interpreter.interactive ()) - { - if (use_command_line_push_parser) - { - push_parser *pp - = new push_parser (m_interpreter, - new input_reader (m_interpreter)); - - repl_parser = std::shared_ptr (pp); - } - else - { - parser *pp = new parser (new lexer (m_interpreter)); - repl_parser = std::shared_ptr (pp); - } - } - else - { - parser *pp = new parser (new lexer (stdin, m_interpreter)); - repl_parser = std::shared_ptr (pp); - } - - do - { - try - { - unwind_protect_var upv (m_in_top_level_repl, true); - - repl_parser->reset (); - - if (at_top_level ()) - { - dbstep_flag (0); - reset_debug_state (); - } - - exit_status = repl_parser->run (); - - if (exit_status == 0) - { - std::shared_ptr - stmt_list = repl_parser->statement_list (); - - if (stmt_list) - { - command_editor::increment_current_command_number (); - - eval (stmt_list, m_interpreter.interactive ()); - } - else if (repl_parser->at_end_of_input ()) - { - exit_status = EOF; - break; - } - } - } - catch (const interrupt_exception&) - { - m_interpreter.recover_from_exception (); - - // Required newline when the user does Ctrl+C at the prompt. - if (m_interpreter.interactive ()) - octave_stdout << "\n"; - } - catch (const index_exception& ie) - { - m_interpreter.recover_from_exception (); - - std::cerr << "error: unhandled index exception: " - << ie.message () << " -- trying to return to prompt" - << std::endl; - } - catch (const execution_exception& ee) - { - error_system& es = m_interpreter.get_error_system (); - - es.save_exception (ee); - es.display_exception (ee); - - if (m_interpreter.interactive ()) + octave_interrupt_state = 1; m_interpreter.recover_from_exception (); - else - { - // We should exit with a nonzero status. - exit_status = 1; - break; - } - } - catch (const quit_debug_exception&) - { - m_interpreter.recover_from_exception (); - - // FIXME: Does anything else need to happen here? - } - catch (const std::bad_alloc&) - { - m_interpreter.recover_from_exception (); - - std::cerr << "error: out of memory -- trying to return to prompt" - << std::endl; - } - } - while (exit_status == 0); - - if (exit_status == EOF) - { - if (m_interpreter.interactive ()) - octave_stdout << "\n"; - - exit_status = 0; - } - - return exit_status; -} - -int tree_evaluator::server_loop (void) -{ - // Process events from the event queue. - - unwind_protect_var upv1 (m_server_mode, true); - - m_exit_status = 0; - - std::shared_ptr parser (new push_parser (m_interpreter)); - unwind_protect_var> upv2 (m_parser, parser); - - // FIXME: We are currently resetting the parser after every call to - // recover_from_exception. This action should probably be handled - // in a more consistent way, but resetting the parser in every call - // to interpreter::recover_from_exception appears to cause - // segfaults in the test suite. - - do - { - try - { - // FIXME: Should we call octave_quit in the octave::sleep - // and/or command_editor::run_event_hooks functions? - - octave_quit (); - - // FIXME: Running the event queue should be decoupled from - // the command_editor. We should also use a condition - // variable to manage the execution of entries in the queue - // and eliminate the need for the busy-wait loop. - - command_editor::run_event_hooks (); - - release_unreferenced_dynamic_libraries (); - - sleep (0.1); - } - catch (const interrupt_exception&) - { - octave_interrupt_state = 1; - m_interpreter.recover_from_exception (); - m_parser->reset (); - - // Required newline when the user does Ctrl+C at the prompt. - if (m_interpreter.interactive ()) - octave_stdout << "\n"; - } - catch (const index_exception& e) - { - m_interpreter.recover_from_exception (); - m_parser->reset (); - - std::cerr << "error: unhandled index exception: " - << e.message () << " -- trying to return to prompt" - << std::endl; - } - catch (const execution_exception& ee) - { - error_system& es = m_interpreter.get_error_system (); - - es.save_exception (ee); - es.display_exception (ee); - - if (m_interpreter.interactive ()) - { - m_interpreter.recover_from_exception (); - m_parser->reset (); - } - else - { - // We should exit with a nonzero status. - m_exit_status = 1; - break; - } - } - catch (const quit_debug_exception&) - { - octave_interrupt_state = 1; - m_interpreter.recover_from_exception (); - m_parser->reset (); - } - catch (const exit_exception& xe) - { - m_exit_status = xe.exit_status (); - break; - } - catch (const std::bad_alloc&) - { - m_interpreter.recover_from_exception (); - m_parser->reset (); - - std::cerr << "error: out of memory -- trying to return to prompt" - << std::endl; - } - } - while (m_exit_status == 0); - - if (m_exit_status == EOF) - { - if (m_interpreter.interactive ()) - octave_stdout << "\n"; - - m_exit_status = 0; - } - - return m_exit_status; -} - -void tree_evaluator::eval (std::shared_ptr& stmt_list, - bool interactive) -{ - try - { - stmt_list->accept (*this); - - octave_quit (); - - if (! interactive) - { - bool quit = (m_returning || m_breaking); - - if (m_returning) - m_returning = 0; - - if (m_breaking) - m_breaking--; - - if (quit) - return; - } - - if (octave_completion_matches_called) - octave_completion_matches_called = false; - } - catch (const quit_debug_exception&) - { - m_interpreter.recover_from_exception (); - } -} - -octave_value_list -tree_evaluator::eval_string (const std::string& eval_str, bool silent, - int& parse_status, int nargout) -{ - octave_value_list retval; - - parser eval_parser (eval_str, m_interpreter); - - do - { - eval_parser.reset (); - - // If we are looking at - // - // val = eval ("code"); - // - // then don't allow code to be parsed as a command. - - if (nargout > 0) - eval_parser.disallow_command_syntax (); - - parse_status = eval_parser.run (); - - if (parse_status == 0) - { - std::shared_ptr stmt_list - = eval_parser.statement_list (); - - if (stmt_list) - { - tree_statement *stmt = nullptr; - - if (stmt_list->length () == 1 - && (stmt = stmt_list->front ()) - && stmt->is_expression ()) - { - tree_expression *expr = stmt->expression (); - - if (silent) - expr->set_print_flag (false); - - retval = expr->evaluate_n (*this, nargout); - - bool do_bind_ans = false; - - if (expr->is_identifier ()) - do_bind_ans = ! is_variable (expr); - else - do_bind_ans = ! expr->is_assignment_expression (); - - if (do_bind_ans && ! retval.empty ()) - bind_ans (retval(0), expr->print_result ()); - - if (nargout == 0) - retval = octave_value_list (); - } - else if (nargout == 0) - stmt_list->accept (*this); - else - error ("eval: invalid use of statement list"); - - if (returning () || breaking () || continuing ()) - break; - } - else if (eval_parser.at_end_of_input ()) + m_parser->reset (); + } + catch (const exit_exception& xe) + { + m_exit_status = xe.exit_status (); break; - } - } - while (parse_status == 0); - - return retval; -} - -octave_value tree_evaluator::eval_string (const std::string& eval_str, - bool silent, int& parse_status) -{ - octave_value retval; - - octave_value_list tmp = eval_string (eval_str, silent, parse_status, 1); - - if (! tmp.empty ()) - retval = tmp(0); - - return retval; -} - -octave_value_list tree_evaluator::eval_string (const octave_value& arg, - bool silent, int& parse_status, - int nargout) -{ - std::string s = arg.xstring_value ("eval: expecting string argument"); - - return eval_string (s, silent, parse_status, nargout); -} - -octave_value_list tree_evaluator::eval (const std::string& try_code, - int nargout) -{ - int parse_status = 0; - - return eval_string (try_code, nargout > 0, parse_status, nargout); -} - -octave_value_list tree_evaluator::eval (const std::string& try_code, - const std::string& catch_code, - int nargout) -{ - octave_value_list retval; - - error_system& es = m_interpreter.get_error_system (); - - int parse_status = 0; - - bool execution_error = false; - - octave_value_list tmp; - - try - { - tmp = eval_string (try_code, nargout > 0, parse_status, nargout); - } - catch (const execution_exception& ee) - { - es.save_exception (ee); - m_interpreter.recover_from_exception (); - - execution_error = true; - } - - if (parse_status != 0 || execution_error) - { - tmp = eval_string (catch_code, nargout > 0, parse_status, nargout); - - retval = (nargout > 0) ? tmp : octave_value_list (); - } - else - { - if (nargout > 0) - retval = tmp; - - // FIXME: we should really be rethrowing whatever - // exception occurred, not just throwing an - // execution exception. - if (execution_error) - throw execution_exception (); - } - - return retval; -} - -octave_value_list tree_evaluator::evalin (const std::string& context, - const std::string& try_code, - int nargout) -{ - unwind_action act ([=] (std::size_t frm) - { - m_call_stack.restore_frame (frm); - }, m_call_stack.current_frame ()); - - if (context == "caller") - m_call_stack.goto_caller_frame (); - else if (context == "base") - m_call_stack.goto_base_frame (); - else - error (R"(evalin: CONTEXT must be "caller" or "base")"); - - int parse_status = 0; - - return eval_string (try_code, nargout > 0, parse_status, nargout); -} - -octave_value_list tree_evaluator::evalin (const std::string& context, - const std::string& try_code, - const std::string& catch_code, - int nargout) -{ - octave_value_list retval; - - unwind_action act1 ([=] (std::size_t frm) - { - m_call_stack.restore_frame (frm); - }, m_call_stack.current_frame ()); - - if (context == "caller") - m_call_stack.goto_caller_frame (); - else if (context == "base") - m_call_stack.goto_base_frame (); - else - error (R"(evalin: CONTEXT must be "caller" or "base")"); - - error_system& es = m_interpreter.get_error_system (); - - int parse_status = 0; - - bool execution_error = false; - - octave_value_list tmp; - - try - { - tmp = eval_string (try_code, nargout > 0, parse_status, nargout); - } - catch (const execution_exception& ee) - { - es.save_exception (ee); - m_interpreter.recover_from_exception (); - - execution_error = true; - } - - if (parse_status != 0 || execution_error) - { - tmp = eval_string (catch_code, nargout > 0, parse_status, nargout); - - retval = (nargout > 0) ? tmp : octave_value_list (); - } - else - { - if (nargout > 0) - retval = tmp; - - // FIXME: we should really be rethrowing whatever - // exception occurred, not just throwing an - // execution exception. - if (execution_error) - throw execution_exception (); - } - - return retval; -} - -void -tree_evaluator::visit_anon_fcn_handle (tree_anon_fcn_handle&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_argument_list (tree_argument_list&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_arguments_block (tree_arguments_block&) -{ - warning ("function arguments validation blocks are not supported; INCORRECT RESULTS ARE POSSIBLE"); -} - -void -tree_evaluator::visit_args_block_attribute_list (tree_args_block_attribute_list&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_args_block_validation_list (tree_args_block_validation_list&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_arg_validation (tree_arg_validation&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_arg_size_spec (tree_arg_size_spec&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_arg_validation_fcns (tree_arg_validation_fcns&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_binary_expression (tree_binary_expression&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_boolean_expression (tree_boolean_expression&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_compound_binary_expression (tree_compound_binary_expression&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_break_command (tree_break_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - if (m_in_loop_command) - m_breaking = 1; - else - error ("break must appear in a loop in the same file as loop command"); -} - -void -tree_evaluator::visit_colon_expression (tree_colon_expression&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_continue_command (tree_continue_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - if (m_in_loop_command) - m_continuing = 1; -} - -bool -tree_evaluator::statement_printing_enabled (void) -{ - return ! (m_silent_functions && (m_statement_context == SC_FUNCTION - || m_statement_context == SC_SCRIPT)); -} - -void -tree_evaluator::reset_debug_state (void) -{ - m_debug_mode = (m_bp_table.have_breakpoints () - || m_dbstep_flag != 0 - || m_break_on_next_stmt - || in_debug_repl ()); -} - -void -tree_evaluator::reset_debug_state (bool mode) -{ - m_debug_mode = mode; -} - -void -tree_evaluator::enter_debugger (const std::string& prompt) -{ - unwind_protect frame; - - frame.add (command_history::ignore_entries, - command_history::ignoring_entries ()); - - command_history::ignore_entries (false); - - frame.add (&call_stack::restore_frame, &m_call_stack, - m_call_stack.current_frame ()); - - // Don't allow errors or warnings at the debug prompt to push us - // into deeper levels of debugging. - - error_system& es = m_interpreter.get_error_system (); - - frame.add (&error_system::set_debug_on_error, &es, es.debug_on_error ()); - - frame.add (&error_system::set_debug_on_warning, &es, - es.debug_on_warning ()); - - es.debug_on_error (false); - es.debug_on_warning (false); - - // Go up to the nearest user code frame. - - m_debug_frame = m_call_stack.dbupdown (0); - - // FIXME: probably we just want to print one line, not the - // entire statement, which might span many lines... - // - // tree_print_code tpc (octave_stdout); - // stmt.accept (tpc); - - debugger *dbgr = new debugger (m_interpreter, m_debugger_stack.size ()); - - m_debugger_stack.push (dbgr); - - frame.add ([=] (void) - { - delete m_debugger_stack.top (); - m_debugger_stack.pop (); - reset_debug_state (); - }); - - dbgr->repl (prompt); -} - -void -tree_evaluator::keyboard (const std::string& prompt) -{ - enter_debugger (prompt); -} - -void -tree_evaluator::dbupdown (int n, bool verbose) -{ - m_debug_frame = m_call_stack.dbupdown (n, verbose); -} - -Matrix -tree_evaluator::ignored_fcn_outputs (void) const -{ - Matrix retval; - - const std::list *lvalues = m_lvalue_list; - - if (! lvalues) + } + catch (const std::bad_alloc&) + { + m_interpreter.recover_from_exception (); + m_parser->reset (); + + std::cerr << "error: out of memory -- trying to return to prompt" + << std::endl; + } + } + while (m_exit_status == 0); + + if (m_exit_status == EOF) + { + if (m_interpreter.interactive ()) + octave_stdout << "\n"; + + m_exit_status = 0; + } + + return m_exit_status; + } + + void tree_evaluator::eval (std::shared_ptr& stmt_list, + bool interactive) + { + try + { + stmt_list->accept (*this); + + octave_quit (); + + if (! interactive) + { + bool quit = (m_returning || m_breaking); + + if (m_returning) + m_returning = 0; + + if (m_breaking) + m_breaking--; + + if (quit) + return; + } + + if (octave_completion_matches_called) + octave_completion_matches_called = false; + } + catch (const quit_debug_exception&) + { + m_interpreter.recover_from_exception (); + } + } + + octave_value_list + tree_evaluator::eval_string (const std::string& eval_str, bool silent, + int& parse_status, int nargout) + { + octave_value_list retval; + + parser eval_parser (eval_str, m_interpreter); + + do + { + eval_parser.reset (); + + // If we are looking at + // + // val = eval ("code"); + // + // then don't allow code to be parsed as a command. + + if (nargout > 0) + eval_parser.disallow_command_syntax (); + + parse_status = eval_parser.run (); + + if (parse_status == 0) + { + std::shared_ptr stmt_list + = eval_parser.statement_list (); + + if (stmt_list) + { + tree_statement *stmt = nullptr; + + if (stmt_list->length () == 1 + && (stmt = stmt_list->front ()) + && stmt->is_expression ()) + { + tree_expression *expr = stmt->expression (); + + if (silent) + expr->set_print_flag (false); + + retval = expr->evaluate_n (*this, nargout); + + bool do_bind_ans = false; + + if (expr->is_identifier ()) + do_bind_ans = ! is_variable (expr); + else + do_bind_ans = ! expr->is_assignment_expression (); + + if (do_bind_ans && ! retval.empty ()) + bind_ans (retval(0), expr->print_result ()); + + if (nargout == 0) + retval = octave_value_list (); + } + else if (nargout == 0) + stmt_list->accept (*this); + else + error ("eval: invalid use of statement list"); + + if (returning () || breaking () || continuing ()) + break; + } + else if (eval_parser.at_end_of_input ()) + break; + } + } + while (parse_status == 0); + + return retval; + } + + octave_value tree_evaluator::eval_string (const std::string& eval_str, + bool silent, int& parse_status) + { + octave_value retval; + + octave_value_list tmp = eval_string (eval_str, silent, parse_status, 1); + + if (! tmp.empty ()) + retval = tmp(0); + + return retval; + } + + octave_value_list tree_evaluator::eval_string (const octave_value& arg, + bool silent, int& parse_status, + int nargout) + { + std::string s = arg.xstring_value ("eval: expecting string argument"); + + return eval_string (s, silent, parse_status, nargout); + } + + octave_value_list tree_evaluator::eval (const std::string& try_code, + int nargout) + { + int parse_status = 0; + + return eval_string (try_code, nargout > 0, parse_status, nargout); + } + + octave_value_list tree_evaluator::eval (const std::string& try_code, + const std::string& catch_code, + int nargout) + { + octave_value_list retval; + + error_system& es = m_interpreter.get_error_system (); + + int parse_status = 0; + + bool execution_error = false; + + octave_value_list tmp; + + try + { + tmp = eval_string (try_code, nargout > 0, parse_status, nargout); + } + catch (const execution_exception& ee) + { + es.save_exception (ee); + m_interpreter.recover_from_exception (); + + execution_error = true; + } + + if (parse_status != 0 || execution_error) + { + tmp = eval_string (catch_code, nargout > 0, parse_status, nargout); + + retval = (nargout > 0) ? tmp : octave_value_list (); + } + else + { + if (nargout > 0) + retval = tmp; + + // FIXME: we should really be rethrowing whatever + // exception occurred, not just throwing an + // execution exception. + if (execution_error) + throw execution_exception (); + } + + return retval; + } + + octave_value_list tree_evaluator::evalin (const std::string& context, + const std::string& try_code, + int nargout) + { + unwind_action act ([=] (std::size_t frm) + { + m_call_stack.restore_frame (frm); + }, m_call_stack.current_frame ()); + + if (context == "caller") + m_call_stack.goto_caller_frame (); + else if (context == "base") + m_call_stack.goto_base_frame (); + else + error (R"(evalin: CONTEXT must be "caller" or "base")"); + + int parse_status = 0; + + return eval_string (try_code, nargout > 0, parse_status, nargout); + } + + octave_value_list tree_evaluator::evalin (const std::string& context, + const std::string& try_code, + const std::string& catch_code, + int nargout) + { + octave_value_list retval; + + unwind_action act1 ([=] (std::size_t frm) + { + m_call_stack.restore_frame (frm); + }, m_call_stack.current_frame ()); + + if (context == "caller") + m_call_stack.goto_caller_frame (); + else if (context == "base") + m_call_stack.goto_base_frame (); + else + error (R"(evalin: CONTEXT must be "caller" or "base")"); + + error_system& es = m_interpreter.get_error_system (); + + int parse_status = 0; + + bool execution_error = false; + + octave_value_list tmp; + + try + { + tmp = eval_string (try_code, nargout > 0, parse_status, nargout); + } + catch (const execution_exception& ee) + { + es.save_exception (ee); + m_interpreter.recover_from_exception (); + + execution_error = true; + } + + if (parse_status != 0 || execution_error) + { + tmp = eval_string (catch_code, nargout > 0, parse_status, nargout); + + retval = (nargout > 0) ? tmp : octave_value_list (); + } + else + { + if (nargout > 0) + retval = tmp; + + // FIXME: we should really be rethrowing whatever + // exception occurred, not just throwing an + // execution exception. + if (execution_error) + throw execution_exception (); + } + return retval; - - octave_idx_type nbh = 0; - - for (const auto& lval : *lvalues) - nbh += lval.is_black_hole (); - - if (nbh > 0) - { - retval.resize (1, nbh); - - octave_idx_type k = 0; - octave_idx_type l = 0; - - for (const auto& lval : *lvalues) - { - if (lval.is_black_hole ()) - retval(l++) = k+1; - - k += lval.numel (); - } - } - - return retval; -} - -// If NAME is an operator (like "+", "-", ...), convert it to the -// corresponding function name ("plus", "minus", ...). - -static std::string -get_operator_function_name (const std::string& name) -{ - // Bow to the god of compatibility. - - // FIXME: it seems ugly to put this here, but there is no single - // function in the parser that converts from the operator name to - // the corresponding function name. At least try to do it without N - // string compares. - - // FIXME: .+, .-, **, and .** are deprecated but still need to be - // handled here until they are removed. - - std::size_t len = name.length (); - - if (len == 3 && name == ".**") - // deprecated - return "power"; - else if (len == 2) - { - if (name[0] == '.') - { - switch (name[1]) - { - case '\'': - return "transpose"; - - case '+': - // deprecated - return "plus"; - - case '-': - // deprecated - return "minus"; - - case '*': - return "times"; - - case '/': - return "rdivide"; - - case '^': - return "power"; - - case '\\': - return "ldivide"; - - default: - break; - } - } - else if (name[1] == '=') - { - switch (name[0]) - { - case '<': - return "le"; - - case '=': - return "eq"; - - case '>': - return "ge"; - - case '~': - case '!': - return "ne"; - - default: - break; - } - } - else if (name == "**") - // deprecated - return "mpower"; - } - else if (len == 1) - { - switch (name[0]) - { - case '~': - case '!': - return "not"; - - case '\'': - return "ctranspose"; - - case '+': - return "plus"; - - case '-': - return "minus"; - - case '*': - return "mtimes"; - - case '/': - return "mrdivide"; - - case '^': - return "mpower"; - - case '\\': - return "mldivide"; - - case '<': - return "lt"; - - case '>': - return "gt"; - - case '&': - return "and"; - - case '|': - return "or"; - - default: - break; - } - } - - return name; -} - -// Creates a function handle that takes into account the context, -// finding local, nested, private, or sub functions. - -octave_value -tree_evaluator::make_fcn_handle (const std::string& name) -{ - octave_value retval; - - // The str2func function can create a function handle with the name - // of an operator (for example, "+"). If so, it is converted to the - // name of the corresponding function ("+" -> "plus") and we create - // a simple function handle using that name. - - std::string fcn_name = get_operator_function_name (name); - - // If FCN_NAME is different from NAME, then NAME is an operator. As - // of version 2020a, Matlab apparently uses the function name - // corresponding to the operator to search for private and local - // functions in the current scope but not(!) nested functions. - - bool name_is_operator = fcn_name != name; - - std::size_t pos = fcn_name.find ('.'); - - if (pos != std::string::npos) - { - // Recognize (some of? which ones?) the following cases - // and create something other than a simple function handle? - // Should we just be checking for the last two when the first - // element of the dot-separated list is an object? If so, then - // should this syntax be limited to a dot-separated list with - // exactly two elements? - // - // object . method - // object . static-method - // - // Code to do that duplicates some of simple_fcn_handle::call. - - // Only accept expressions that contain one '.' separator. - - // FIXME: The logic here is a bit complicated. Is there a good - // way to simplify it? - - std::string meth_nm = fcn_name.substr (pos+1); - - if (meth_nm.find ('.') == std::string::npos) - { - std::string obj_nm = fcn_name.substr (0, pos); - - // If obj_nm is an object in the current scope with a - // method named meth_nm, create a classsimple handle. - - octave_value object = varval (obj_nm); - - if (object.is_defined () && object.is_classdef_object ()) - { - octave_classdef *cdef = object.classdef_object_value (); - - if (cdef) - { - std::string class_nm = cdef->class_name (); - - cdef_object cdef_obj = cdef->get_object (); - - cdef_class cls = cdef_obj.get_class (); - - cdef_method meth = cls.find_method (meth_nm); - - if (meth.ok ()) - { - // If the method we found is static, create a - // new function name from the class name and - // method name and create a simple function - // handle below. Otherwise, create a class - // simple function handle. - - if (meth.is_static ()) - fcn_name = class_nm + '.' + meth_nm; - else - { - octave_value meth_fcn = meth.get_function (); - - octave_fcn_handle *fh - = new octave_fcn_handle (object, meth_fcn, - class_nm, meth_nm); - - return octave_value (fh); - } - } - } - } - } - - // We didn't match anything above, so create handle to SIMPLE - // package function or static class method. Function resolution - // is performed when the handle is used. - - return octave_value (new octave_fcn_handle (fcn_name)); - } - - // If the function name refers to a sub/local/private function or a - // class method/constructor, create scoped function handle that is - // bound to that function. Use the same precedence list as - // fcn_info::find but limit search to the following types of - // functions: - // - // nested functions (and subfunctions) - // local functions in the current file - // private function - // class method - // - // For anything else we create a simple function handle that will be - // resolved dynamically in the scope where it is evaluated. - - symbol_scope curr_scope = get_current_scope (); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - if (curr_scope) - { - octave_value ov_fcn - = symtab.find_scoped_function (fcn_name, curr_scope); - - // If name is operator, we are in Fstr2func, so skip the stack - // frame for that function. - - bool skip_first = name_is_operator; - octave_function *curr_fcn = current_function (skip_first); - - if (ov_fcn.is_defined ()) - { - octave_function *fcn = ov_fcn.function_value (); - - if (fcn->is_nested_function ()) - { - if (! name_is_operator) - { - // Get current stack frame and return handle to nested - // function. - - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - // If we are creating a handle to the current - // function or a handle to a sibling function (i.e., - // not a child of the current function), then use - // the calling stack frame as the context instead of - // the current stack frame. - - // FIXME: Do we need both checks here or is it - // sufficient to check that the parent of curr_fcn - // is the same as the parent of fcn? Is there any - // case where curr_fcn could be nullptr, or does - // that indicate an internal error of some kind? - - if (curr_fcn - && (fcn_name == curr_fcn->name () - || fcn->parent_fcn_name () == curr_fcn->parent_fcn_name ())) - frame = frame->access_link (); - - octave_fcn_handle *fh - = new octave_fcn_handle (ov_fcn, fcn_name, frame); - - return octave_value (fh); - } - } - else if (fcn->is_subfunction () - /* || fcn->is_localfunction () */ - || fcn->is_private_function ()) - { - // Create handle to SCOPED function (sub/local function - // or private function). - - std::list parentage = fcn->parent_fcn_names (); - - octave_fcn_handle *fh - = new octave_fcn_handle (ov_fcn, fcn_name, parentage); - - return octave_value (fh); - } - } - - if (curr_fcn && (curr_fcn->is_class_method () - || curr_fcn->is_class_constructor ())) - { - std::string dispatch_class = curr_fcn->dispatch_class (); - - octave_value ov_meth - = symtab.find_method (fcn_name, dispatch_class); - - if (ov_meth.is_defined ()) - { - octave_function *fcn = ov_meth.function_value (); - - // FIXME: do we need to check that it is a method of - // dispatch_class, or is it sufficient to just check - // that it is a method? - - if (fcn->is_class_method ()) - { - // Create CLASSSIMPLE handle to method but don't - // bind to the method. Lookup will be done later. - - octave_fcn_handle *fh - = new octave_fcn_handle (dispatch_class, fcn_name); - - return octave_value (fh); - } - } - } - } - - octave_value ov_fcn = symtab.find_user_function (fcn_name); - - // Create handle to SIMPLE function. If the function is not found - // now, then we will look for it again when the handle is used. - - return octave_value (new octave_fcn_handle (ov_fcn, fcn_name)); -} + } + + void + tree_evaluator::visit_anon_fcn_handle (tree_anon_fcn_handle&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_argument_list (tree_argument_list&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_arguments_block (tree_arguments_block&) + { + warning ("function arguments validation blocks are not supported; INCORRECT RESULTS ARE POSSIBLE"); + } + + void + tree_evaluator::visit_args_block_attribute_list (tree_args_block_attribute_list&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_args_block_validation_list (tree_args_block_validation_list&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_arg_validation (tree_arg_validation&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_arg_size_spec (tree_arg_size_spec&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_arg_validation_fcns (tree_arg_validation_fcns&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_binary_expression (tree_binary_expression&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_boolean_expression (tree_boolean_expression&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_compound_binary_expression (tree_compound_binary_expression&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_break_command (tree_break_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + if (m_in_loop_command) + m_breaking = 1; + else + error ("break must appear in a loop in the same file as loop command"); + } + + void + tree_evaluator::visit_colon_expression (tree_colon_expression&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_continue_command (tree_continue_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + if (m_in_loop_command) + m_continuing = 1; + } + + bool + tree_evaluator::statement_printing_enabled (void) + { + return ! (m_silent_functions && (m_statement_context == SC_FUNCTION + || m_statement_context == SC_SCRIPT)); + } + + void + tree_evaluator::reset_debug_state (void) + { + m_debug_mode = (m_bp_table.have_breakpoints () + || m_dbstep_flag != 0 + || m_break_on_next_stmt + || in_debug_repl ()); + } + + void + tree_evaluator::reset_debug_state (bool mode) + { + m_debug_mode = mode; + } + + void + tree_evaluator::enter_debugger (const std::string& prompt) + { + unwind_protect frame; + + frame.add (command_history::ignore_entries, + command_history::ignoring_entries ()); + + command_history::ignore_entries (false); + + frame.add (&call_stack::restore_frame, &m_call_stack, + m_call_stack.current_frame ()); + + // Don't allow errors or warnings at the debug prompt to push us + // into deeper levels of debugging. + + error_system& es = m_interpreter.get_error_system (); + + frame.add (&error_system::set_debug_on_error, &es, es.debug_on_error ()); + + frame.add (&error_system::set_debug_on_warning, &es, + es.debug_on_warning ()); + + es.debug_on_error (false); + es.debug_on_warning (false); + + // Go up to the nearest user code frame. + + m_debug_frame = m_call_stack.dbupdown (0); + + // FIXME: probably we just want to print one line, not the + // entire statement, which might span many lines... + // + // tree_print_code tpc (octave_stdout); + // stmt.accept (tpc); + + debugger *dbgr = new debugger (m_interpreter, m_debugger_stack.size ()); + + m_debugger_stack.push (dbgr); + + frame.add ([=] (void) + { + delete m_debugger_stack.top (); + m_debugger_stack.pop (); + reset_debug_state (); + }); + + dbgr->repl (prompt); + } + + void + tree_evaluator::keyboard (const std::string& prompt) + { + enter_debugger (prompt); + } + + void + tree_evaluator::dbupdown (int n, bool verbose) + { + m_debug_frame = m_call_stack.dbupdown (n, verbose); + } + + Matrix + tree_evaluator::ignored_fcn_outputs (void) const + { + Matrix retval; + + const std::list *lvalues = m_lvalue_list; + + if (! lvalues) + return retval; + + octave_idx_type nbh = 0; + + for (const auto& lval : *lvalues) + nbh += lval.is_black_hole (); + + if (nbh > 0) + { + retval.resize (1, nbh); + + octave_idx_type k = 0; + octave_idx_type l = 0; + + for (const auto& lval : *lvalues) + { + if (lval.is_black_hole ()) + retval(l++) = k+1; + + k += lval.numel (); + } + } + + return retval; + } + + // If NAME is an operator (like "+", "-", ...), convert it to the + // corresponding function name ("plus", "minus", ...). + + static std::string + get_operator_function_name (const std::string& name) + { + // Bow to the god of compatibility. + + // FIXME: it seems ugly to put this here, but there is no single + // function in the parser that converts from the operator name to + // the corresponding function name. At least try to do it without N + // string compares. + + std::size_t len = name.length (); + + if (len == 2) + { + if (name[0] == '.') + { + switch (name[1]) + { + case '\'': + return "transpose"; + + case '*': + return "times"; + + case '/': + return "rdivide"; + + case '^': + return "power"; + + case '\\': + return "ldivide"; + + default: + break; + } + } + else if (name[1] == '=') + { + switch (name[0]) + { + case '<': + return "le"; + + case '=': + return "eq"; + + case '>': + return "ge"; + + case '~': + case '!': + return "ne"; + + default: + break; + } + } + } + else if (len == 1) + { + switch (name[0]) + { + case '~': + case '!': + return "not"; + + case '\'': + return "ctranspose"; + + case '+': + return "plus"; + + case '-': + return "minus"; + + case '*': + return "mtimes"; + + case '/': + return "mrdivide"; + + case '^': + return "mpower"; + + case '\\': + return "mldivide"; + + case '<': + return "lt"; + + case '>': + return "gt"; + + case '&': + return "and"; + + case '|': + return "or"; + + default: + break; + } + } + + return name; + } + + // Creates a function handle that takes into account the context, + // finding local, nested, private, or sub functions. + + octave_value + tree_evaluator::make_fcn_handle (const std::string& name) + { + octave_value retval; + + // The str2func function can create a function handle with the name + // of an operator (for example, "+"). If so, it is converted to the + // name of the corresponding function ("+" -> "plus") and we create + // a simple function handle using that name. + + std::string fcn_name = get_operator_function_name (name); + + // If FCN_NAME is different from NAME, then NAME is an operator. As + // of version 2020a, Matlab apparently uses the function name + // corresponding to the operator to search for private and local + // functions in the current scope but not(!) nested functions. + + bool name_is_operator = fcn_name != name; + + std::size_t pos = fcn_name.find ('.'); + + if (pos != std::string::npos) + { + // Recognize (some of? which ones?) the following cases + // and create something other than a simple function handle? + // Should we just be checking for the last two when the first + // element of the dot-separated list is an object? If so, then + // should this syntax be limited to a dot-separated list with + // exactly two elements? + // + // object . method + // object . static-method + // + // Code to do that duplicates some of simple_fcn_handle::call. + + // Only accept expressions that contain one '.' separator. + + // FIXME: The logic here is a bit complicated. Is there a good + // way to simplify it? + + std::string meth_nm = fcn_name.substr (pos+1); + + if (meth_nm.find ('.') == std::string::npos) + { + std::string obj_nm = fcn_name.substr (0, pos); + + // If obj_nm is an object in the current scope with a + // method named meth_nm, create a classsimple handle. + + octave_value object = varval (obj_nm); + + if (object.is_defined () && object.is_classdef_object ()) + { + octave_classdef *cdef = object.classdef_object_value (); + + if (cdef) + { + std::string class_nm = cdef->class_name (); + + cdef_object cdef_obj = cdef->get_object (); + + cdef_class cls = cdef_obj.get_class (); + + cdef_method meth = cls.find_method (meth_nm); + + if (meth.ok ()) + { + // If the method we found is static, create a + // new function name from the class name and + // method name and create a simple function + // handle below. Otherwise, create a class + // simple function handle. + + if (meth.is_static ()) + fcn_name = class_nm + '.' + meth_nm; + else + { + octave_value meth_fcn = meth.get_function (); + + octave_fcn_handle *fh + = new octave_fcn_handle (object, meth_fcn, + class_nm, meth_nm); + + return octave_value (fh); + } + } + } + } + } + + // We didn't match anything above, so create handle to SIMPLE + // package function or static class method. Function resolution + // is performed when the handle is used. + + return octave_value (new octave_fcn_handle (fcn_name)); + } + + // If the function name refers to a sub/local/private function or a + // class method/constructor, create scoped function handle that is + // bound to that function. Use the same precedence list as + // fcn_info::find but limit search to the following types of + // functions: + // + // nested functions (and subfunctions) + // local functions in the current file + // private function + // class method + // + // For anything else we create a simple function handle that will be + // resolved dynamically in the scope where it is evaluated. + + symbol_scope curr_scope = get_current_scope (); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + if (curr_scope) + { + octave_value ov_fcn + = symtab.find_scoped_function (fcn_name, curr_scope); + + // If name is operator, we are in Fstr2func, so skip the stack + // frame for that function. + + bool skip_first = name_is_operator; + octave_function *curr_fcn = current_function (skip_first); + + if (ov_fcn.is_defined ()) + { + octave_function *fcn = ov_fcn.function_value (); + + if (fcn->is_nested_function ()) + { + if (! name_is_operator) + { + // Get current stack frame and return handle to nested + // function. + + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + // If we are creating a handle to the current + // function or a handle to a sibling function (i.e., + // not a child of the current function), then use + // the calling stack frame as the context instead of + // the current stack frame. + + // FIXME: Do we need both checks here or is it + // sufficient to check that the parent of curr_fcn + // is the same as the parent of fcn? Is there any + // case where curr_fcn could be nullptr, or does + // that indicate an internal error of some kind? + + if (curr_fcn + && (fcn_name == curr_fcn->name () + || fcn->parent_fcn_name () == curr_fcn->parent_fcn_name ())) + frame = frame->access_link (); + + octave_fcn_handle *fh + = new octave_fcn_handle (ov_fcn, fcn_name, frame); + + return octave_value (fh); + } + } + else if (fcn->is_subfunction () + /* || fcn->is_localfunction () */ + || fcn->is_private_function ()) + { + // Create handle to SCOPED function (sub/local function + // or private function). + + std::list parentage = fcn->parent_fcn_names (); + + octave_fcn_handle *fh + = new octave_fcn_handle (ov_fcn, fcn_name, parentage); + + return octave_value (fh); + } + } + + if (curr_fcn && (curr_fcn->is_class_method () + || curr_fcn->is_class_constructor ())) + { + std::string dispatch_class = curr_fcn->dispatch_class (); + + octave_value ov_meth + = symtab.find_method (fcn_name, dispatch_class); + + if (ov_meth.is_defined ()) + { + octave_function *fcn = ov_meth.function_value (); + + // FIXME: do we need to check that it is a method of + // dispatch_class, or is it sufficient to just check + // that it is a method? + + if (fcn->is_class_method ()) + { + // Create CLASSSIMPLE handle to method but don't + // bind to the method. Lookup will be done later. + + octave_fcn_handle *fh + = new octave_fcn_handle (dispatch_class, fcn_name); + + return octave_value (fh); + } + } + } + } + + octave_value ov_fcn = symtab.find_user_function (fcn_name); + + // Create handle to SIMPLE function. If the function is not found + // now, then we will look for it again when the handle is used. + + return octave_value (new octave_fcn_handle (ov_fcn, fcn_name)); + } /* %!test -%! x = {".**", "power"; -%! ".'", "transpose"; -%! ".+", "plus"; -%! ".-", "minus"; +%! x = {".'", "transpose"; %! ".*", "times"; %! "./", "rdivide"; %! ".^", "power"; @@ -1833,7 +1813,6 @@ %! ">=", "ge"; %! "!=", "ne"; %! "~=", "ne"; -%! "**", "mpower"; %! "~", "not"; %! "!", "not"; %! "\'", "ctranspose"; @@ -1852,401 +1831,401 @@ %! endfor */ -octave_value -tree_evaluator::evaluate (tree_decl_elt *elt) -{ - // Do not allow functions to return null values. - - tree_identifier *id = elt->ident (); - - return id ? id->evaluate (*this).storable_value () : octave_value (); -} - -bool -tree_evaluator::is_variable (const std::string& name) const -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->is_variable (name); -} - -bool -tree_evaluator::is_local_variable (const std::string& name) const -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->is_local_variable (name); -} - -bool -tree_evaluator::is_variable (const tree_expression *expr) const -{ - if (expr->is_identifier ()) - { - const tree_identifier *id - = dynamic_cast (expr); - - if (id->is_black_hole ()) - return false; - - return is_variable (id->symbol ()); - } - - return false; -} - -bool -tree_evaluator::is_defined (const tree_expression *expr) const -{ - if (expr->is_identifier ()) - { - const tree_identifier *id - = dynamic_cast (expr); - - return is_defined (id->symbol ()); - } - - return false; -} - -bool -tree_evaluator::is_variable (const symbol_record& sym) const -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->is_variable (sym); -} - -bool -tree_evaluator::is_defined (const symbol_record& sym) const -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->is_defined (sym); -} - -bool tree_evaluator::is_global (const std::string& name) const -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->is_global (name); -} - -octave_value -tree_evaluator::varval (const symbol_record& sym) const -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->varval (sym); -} - -octave_value -tree_evaluator::varval (const std::string& name) const -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->varval (name); -} - -void tree_evaluator::install_variable (const std::string& name, - const octave_value& value, - bool global) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->install_variable (name, value, global); -} - -octave_value -tree_evaluator::global_varval (const std::string& name) const -{ - return m_call_stack.global_varval (name); -} - -octave_value& -tree_evaluator::global_varref (const std::string& name) -{ - return m_call_stack.global_varref (name); -} - -void -tree_evaluator::global_assign (const std::string& name, - const octave_value& val) -{ - m_call_stack.global_varref (name) = val; -} - -octave_value -tree_evaluator::top_level_varval (const std::string& name) const -{ - return m_call_stack.get_top_level_value (name); -} - -void -tree_evaluator::top_level_assign (const std::string& name, - const octave_value& val) -{ - m_call_stack.set_top_level_value (name, val); -} - -void -tree_evaluator::assign (const std::string& name, const octave_value& val) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - frame->assign (name, val); -} - -void -tree_evaluator::assignin (const std::string& context, - const std::string& name, const octave_value& val) -{ - // FIXME: Can this be done without an unwind-protect frame, simply - // by getting a reference to the caller or base stack frame and - // calling assign on that? - - unwind_action act ([=] (std::size_t frm) - { - m_call_stack.restore_frame (frm); - }, m_call_stack.current_frame ()); - - if (context == "caller") - m_call_stack.goto_caller_frame (); - else if (context == "base") - m_call_stack.goto_base_frame (); - else - error (R"(assignin: CONTEXT must be "caller" or "base")"); - - if (valid_identifier (name)) - { - // Put the check here so that we don't slow down assignments - // generally. Any that go through Octave's parser should have - // already been checked. - - if (iskeyword (name)) - error ("assignin: invalid assignment to keyword '%s'", - name.c_str ()); - - assign (name, val); - } - else - error ("assignin: invalid variable name '%s'", name.c_str ()); -} - -void -tree_evaluator::source_file (const std::string& file_name, - const std::string& context, - bool verbose, bool require_file) -{ - // Map from absolute name of script file to recursion level. We - // use a map instead of simply placing a limit on recursion in the - // source_file function so that two mutually recursive scripts - // written as - // - // foo1.m: - // ------ - // foo2 - // - // foo2.m: - // ------ - // foo1 - // - // and called with - // - // foo1 - // - // (for example) will behave the same if they are written as - // - // foo1.m: - // ------ - // source ("foo2.m") - // - // foo2.m: - // ------ - // source ("foo1.m") - // - // and called with - // - // source ("foo1.m") - // - // (for example). - - static std::map source_call_depth; - - std::string file_full_name - = sys::file_ops::tilde_expand (file_name); - - std::size_t pos - = file_full_name.find_last_of (sys::file_ops::dir_sep_str ()); - - std::string dir_name = file_full_name.substr (0, pos); - - file_full_name = sys::env::make_absolute (file_full_name); - - unwind_protect frame; - - if (source_call_depth.find (file_full_name) == source_call_depth.end ()) - source_call_depth[file_full_name] = -1; - - frame.protect_var (source_call_depth[file_full_name]); - - source_call_depth[file_full_name]++; - - if (source_call_depth[file_full_name] >= max_recursion_depth ()) - error ("max_recursion_depth exceeded"); - - if (! context.empty ()) - { - frame.add (&call_stack::restore_frame, &m_call_stack, - m_call_stack.current_frame ()); - - if (context == "caller") - m_call_stack.goto_caller_frame (); - else if (context == "base") - m_call_stack.goto_base_frame (); - else - error (R"(source: CONTEXT must be "caller" or "base")"); - } - - // Find symbol name that would be in symbol_table, if it were loaded. - std::size_t dir_end - = file_name.find_last_of (sys::file_ops::dir_sep_chars ()); - dir_end = (dir_end == std::string::npos) ? 0 : dir_end + 1; - - std::size_t extension = file_name.find_last_of ('.'); - if (extension == std::string::npos) - extension = file_name.length (); - - std::string symbol = file_name.substr (dir_end, extension - dir_end); - std::string full_name = sys::canonicalize_file_name (file_name); - - // Check if this file is already loaded (or in the path) - symbol_table& symtab = m_interpreter.get_symbol_table (); - octave_value ov_code = symtab.fcn_table_find (symbol); - - // For compatibility with Matlab, accept both scripts and - // functions. - - if (ov_code.is_user_code ()) - { - octave_user_code *code = ov_code.user_code_value (); - - if (! code - || (sys::canonicalize_file_name (code->fcn_file_name ()) - != full_name)) - { - // Wrong file, so load it below. - ov_code = octave_value (); - } - } - else - { - // Not a script, so load it below. - ov_code = octave_value (); - } - - // If no symbol of this name, or the symbol is for a different - // file, load. - - if (ov_code.is_undefined ()) - { - try - { - ov_code = parse_fcn_file (m_interpreter, file_full_name, - file_name, dir_name, "", "", - require_file, true, false, false); - } - catch (execution_exception& ee) - { - error (ee, "source: error sourcing file '%s'", - file_full_name.c_str ()); - } - } - - // Return or error if we don't have a valid script or function. - - if (ov_code.is_undefined ()) - return; - - if (! ov_code.is_user_code ()) - error ("source: %s is not a script", full_name.c_str ()); - - if (verbose) - { - octave_stdout << "executing commands from " << full_name << " ... "; - octave_stdout.flush (); - } - - octave_user_code *code = ov_code.user_code_value (); - - code->call (*this, 0, octave_value_list ()); - - if (verbose) - octave_stdout << "done." << std::endl; -} - -void -tree_evaluator::set_auto_fcn_var (stack_frame::auto_var_type avt, - const octave_value& val) -{ - m_call_stack.set_auto_fcn_var (avt, val); -} - -octave_value -tree_evaluator::get_auto_fcn_var (stack_frame::auto_var_type avt) const -{ - return m_call_stack.get_auto_fcn_var (avt); -} - -void -tree_evaluator::define_parameter_list_from_arg_vector -(tree_parameter_list *param_list, const octave_value_list& args) -{ - if (! param_list || param_list->varargs_only ()) - return; - - int i = -1; - - for (tree_decl_elt *elt : *param_list) - { - i++; - - octave_lvalue ref = elt->lvalue (*this); - - if (i < args.length ()) - { - if (args(i).is_defined () && args(i).is_magic_colon ()) - { - if (! eval_decl_elt (elt)) - error ("no default value for argument %d", i+1); - } - else - ref.define (args(i)); - } - else - eval_decl_elt (elt); - } -} - -void -tree_evaluator::undefine_parameter_list (tree_parameter_list *param_list) -{ - for (tree_decl_elt *elt : *param_list) - { - octave_lvalue ref = elt->lvalue (*this); - - ref.assign (octave_value::op_asn_eq, octave_value ()); - } -} + octave_value + tree_evaluator::evaluate (tree_decl_elt *elt) + { + // Do not allow functions to return null values. + + tree_identifier *id = elt->ident (); + + return id ? id->evaluate (*this).storable_value () : octave_value (); + } + + bool + tree_evaluator::is_variable (const std::string& name) const + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->is_variable (name); + } + + bool + tree_evaluator::is_local_variable (const std::string& name) const + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->is_local_variable (name); + } + + bool + tree_evaluator::is_variable (const tree_expression *expr) const + { + if (expr->is_identifier ()) + { + const tree_identifier *id + = dynamic_cast (expr); + + if (id->is_black_hole ()) + return false; + + return is_variable (id->symbol ()); + } + + return false; + } + + bool + tree_evaluator::is_defined (const tree_expression *expr) const + { + if (expr->is_identifier ()) + { + const tree_identifier *id + = dynamic_cast (expr); + + return is_defined (id->symbol ()); + } + + return false; + } + + bool + tree_evaluator::is_variable (const symbol_record& sym) const + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->is_variable (sym); + } + + bool + tree_evaluator::is_defined (const symbol_record& sym) const + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->is_defined (sym); + } + + bool tree_evaluator::is_global (const std::string& name) const + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->is_global (name); + } + + octave_value + tree_evaluator::varval (const symbol_record& sym) const + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->varval (sym); + } + + octave_value + tree_evaluator::varval (const std::string& name) const + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->varval (name); + } + + void tree_evaluator::install_variable (const std::string& name, + const octave_value& value, + bool global) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->install_variable (name, value, global); + } + + octave_value + tree_evaluator::global_varval (const std::string& name) const + { + return m_call_stack.global_varval (name); + } + + octave_value& + tree_evaluator::global_varref (const std::string& name) + { + return m_call_stack.global_varref (name); + } + + void + tree_evaluator::global_assign (const std::string& name, + const octave_value& val) + { + m_call_stack.global_varref (name) = val; + } + + octave_value + tree_evaluator::top_level_varval (const std::string& name) const + { + return m_call_stack.get_top_level_value (name); + } + + void + tree_evaluator::top_level_assign (const std::string& name, + const octave_value& val) + { + m_call_stack.set_top_level_value (name, val); + } + + void + tree_evaluator::assign (const std::string& name, const octave_value& val) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + frame->assign (name, val); + } + + void + tree_evaluator::assignin (const std::string& context, + const std::string& name, const octave_value& val) + { + // FIXME: Can this be done without an unwind-protect frame, simply + // by getting a reference to the caller or base stack frame and + // calling assign on that? + + unwind_action act ([=] (std::size_t frm) + { + m_call_stack.restore_frame (frm); + }, m_call_stack.current_frame ()); + + if (context == "caller") + m_call_stack.goto_caller_frame (); + else if (context == "base") + m_call_stack.goto_base_frame (); + else + error (R"(assignin: CONTEXT must be "caller" or "base")"); + + if (valid_identifier (name)) + { + // Put the check here so that we don't slow down assignments + // generally. Any that go through Octave's parser should have + // already been checked. + + if (iskeyword (name)) + error ("assignin: invalid assignment to keyword '%s'", + name.c_str ()); + + assign (name, val); + } + else + error ("assignin: invalid variable name '%s'", name.c_str ()); + } + + void + tree_evaluator::source_file (const std::string& file_name, + const std::string& context, + bool verbose, bool require_file) + { + // Map from absolute name of script file to recursion level. We + // use a map instead of simply placing a limit on recursion in the + // source_file function so that two mutually recursive scripts + // written as + // + // foo1.m: + // ------ + // foo2 + // + // foo2.m: + // ------ + // foo1 + // + // and called with + // + // foo1 + // + // (for example) will behave the same if they are written as + // + // foo1.m: + // ------ + // source ("foo2.m") + // + // foo2.m: + // ------ + // source ("foo1.m") + // + // and called with + // + // source ("foo1.m") + // + // (for example). + + static std::map source_call_depth; + + std::string file_full_name + = sys::file_ops::tilde_expand (file_name); + + std::size_t pos + = file_full_name.find_last_of (sys::file_ops::dir_sep_str ()); + + std::string dir_name = file_full_name.substr (0, pos); + + file_full_name = sys::env::make_absolute (file_full_name); + + unwind_protect frame; + + if (source_call_depth.find (file_full_name) == source_call_depth.end ()) + source_call_depth[file_full_name] = -1; + + frame.protect_var (source_call_depth[file_full_name]); + + source_call_depth[file_full_name]++; + + if (source_call_depth[file_full_name] >= max_recursion_depth ()) + error ("max_recursion_depth exceeded"); + + if (! context.empty ()) + { + frame.add (&call_stack::restore_frame, &m_call_stack, + m_call_stack.current_frame ()); + + if (context == "caller") + m_call_stack.goto_caller_frame (); + else if (context == "base") + m_call_stack.goto_base_frame (); + else + error (R"(source: CONTEXT must be "caller" or "base")"); + } + + // Find symbol name that would be in symbol_table, if it were loaded. + std::size_t dir_end + = file_name.find_last_of (sys::file_ops::dir_sep_chars ()); + dir_end = (dir_end == std::string::npos) ? 0 : dir_end + 1; + + std::size_t extension = file_name.find_last_of ('.'); + if (extension == std::string::npos) + extension = file_name.length (); + + std::string symbol = file_name.substr (dir_end, extension - dir_end); + std::string full_name = sys::canonicalize_file_name (file_name); + + // Check if this file is already loaded (or in the path) + symbol_table& symtab = m_interpreter.get_symbol_table (); + octave_value ov_code = symtab.fcn_table_find (symbol); + + // For compatibility with Matlab, accept both scripts and + // functions. + + if (ov_code.is_user_code ()) + { + octave_user_code *code = ov_code.user_code_value (); + + if (! code + || (sys::canonicalize_file_name (code->fcn_file_name ()) + != full_name)) + { + // Wrong file, so load it below. + ov_code = octave_value (); + } + } + else + { + // Not a script, so load it below. + ov_code = octave_value (); + } + + // If no symbol of this name, or the symbol is for a different + // file, load. + + if (ov_code.is_undefined ()) + { + try + { + ov_code = parse_fcn_file (m_interpreter, file_full_name, + file_name, dir_name, "", "", + require_file, true, false, false); + } + catch (execution_exception& ee) + { + error (ee, "source: error sourcing file '%s'", + file_full_name.c_str ()); + } + } + + // Return or error if we don't have a valid script or function. + + if (ov_code.is_undefined ()) + return; + + if (! ov_code.is_user_code ()) + error ("source: %s is not a script", full_name.c_str ()); + + if (verbose) + { + octave_stdout << "executing commands from " << full_name << " ... "; + octave_stdout.flush (); + } + + octave_user_code *code = ov_code.user_code_value (); + + code->call (*this, 0, octave_value_list ()); + + if (verbose) + octave_stdout << "done." << std::endl; + } + + void + tree_evaluator::set_auto_fcn_var (stack_frame::auto_var_type avt, + const octave_value& val) + { + m_call_stack.set_auto_fcn_var (avt, val); + } + + octave_value + tree_evaluator::get_auto_fcn_var (stack_frame::auto_var_type avt) const + { + return m_call_stack.get_auto_fcn_var (avt); + } + + void + tree_evaluator::define_parameter_list_from_arg_vector + (tree_parameter_list *param_list, const octave_value_list& args) + { + if (! param_list || param_list->varargs_only ()) + return; + + int i = -1; + + for (tree_decl_elt *elt : *param_list) + { + i++; + + octave_lvalue ref = elt->lvalue (*this); + + if (i < args.length ()) + { + if (args(i).is_defined () && args(i).is_magic_colon ()) + { + if (! eval_decl_elt (elt)) + error ("no default value for argument %d", i+1); + } + else + ref.define (args(i)); + } + else + eval_decl_elt (elt); + } + } + + void + tree_evaluator::undefine_parameter_list (tree_parameter_list *param_list) + { + for (tree_decl_elt *elt : *param_list) + { + octave_lvalue ref = elt->lvalue (*this); + + ref.assign (octave_value::op_asn_eq, octave_value ()); + } + } // END is documented in op-kw-docs. DEFMETHOD (end, interp, args, , @@ -2292,2989 +2271,2988 @@ %! assert (x(minus (minus (end, 1), 1)), 8); */ -octave_value_list -tree_evaluator::convert_to_const_vector (tree_argument_list *args) -{ - std::list arg_vals; - - for (auto elt : *args) - { - // FIXME: is it possible for elt to be invalid? - - if (! elt) + octave_value_list + tree_evaluator::convert_to_const_vector (tree_argument_list *args) + { + std::list arg_vals; + + for (auto elt : *args) + { + // FIXME: is it possible for elt to be invalid? + + if (! elt) + break; + + octave_value tmp = elt->evaluate (*this); + + if (tmp.is_cs_list ()) + { + octave_value_list tmp_ovl = tmp.list_value (); + + for (octave_idx_type i = 0; i < tmp_ovl.length (); i++) + arg_vals.push_back (tmp_ovl(i)); + } + else if (tmp.is_defined ()) + arg_vals.push_back (tmp); + } + + return octave_value_list (arg_vals); + } + + octave_value_list + tree_evaluator::convert_return_list_to_const_vector + (tree_parameter_list *ret_list, int nargout, const Matrix& ignored_outputs, + const Cell& varargout) + { + octave_idx_type vlen = varargout.numel (); + int len = ret_list->length (); + + // Special case. Will do a shallow copy. + if (len == 0) + return varargout; + else + { + int i = 0; + int k = 0; + int num_ignored = ignored_outputs.numel (); + int ignored = num_ignored > 0 ? ignored_outputs(k) - 1 : -1; + + if (nargout <= len) + { + int nout = nargout > 0 ? nargout : 1; + octave_value_list retval (nout); + + for (tree_decl_elt *elt : *ret_list) + { + if (nargout == 0 && ! is_defined (elt->ident ())) + break; + + if (ignored >= 0 && i == ignored) + { + i++; + k++; + ignored = k < num_ignored ? ignored_outputs(k) - 1 : -1; + } + else + retval(i++) = evaluate (elt); + + if (i == nout) + break; + } + + return retval; + } + else + { + octave_value_list retval (len + vlen); + + for (tree_decl_elt *elt : *ret_list) + { + if (ignored >= 0 && i == ignored) + { + i++; + k++; + ignored = k < num_ignored ? ignored_outputs(k) - 1 : -1; + } + else + retval(i++) = evaluate (elt); + } + + for (octave_idx_type j = 0; j < vlen; j++) + retval(i++) = varargout(j); + + return retval; + } + } + } + + bool + tree_evaluator::eval_decl_elt (tree_decl_elt *elt) + { + bool retval = false; + + tree_identifier *id = elt->ident (); + tree_expression *expr = elt->expression (); + + if (id && expr) + { + octave_lvalue ult = id->lvalue (*this); + + octave_value init_val = expr->evaluate (*this); + + ult.assign (octave_value::op_asn_eq, init_val); + + retval = true; + } + + return retval; + } + + bool + tree_evaluator::switch_case_label_matches (tree_switch_case *expr, + const octave_value& val) + { + tree_expression *label = expr->case_label (); + + octave_value label_value = label->evaluate (*this); + + if (label_value.is_defined ()) + { + if (label_value.iscell ()) + { + Cell cell (label_value.cell_value ()); + + for (octave_idx_type i = 0; i < cell.rows (); i++) + { + for (octave_idx_type j = 0; j < cell.columns (); j++) + { + bool match = val.is_equal (cell(i,j)); + + if (match) + return true; + } + } + } + else + return val.is_equal (label_value); + } + + return false; + } + + void tree_evaluator::push_stack_frame (const symbol_scope& scope) + { + m_call_stack.push (scope); + } + + void tree_evaluator::push_stack_frame (octave_user_function *fcn, + const std::shared_ptr& closure_frames) + { + m_call_stack.push (fcn, closure_frames); + } + + void tree_evaluator::push_stack_frame (octave_user_function *fcn, + const stack_frame::local_vars_map& local_vars, + const std::shared_ptr& closure_frames) + { + m_call_stack.push (fcn, local_vars, closure_frames); + } + + void tree_evaluator::push_stack_frame (octave_user_script *script) + { + m_call_stack.push (script); + } + + void tree_evaluator::push_stack_frame (octave_function *fcn) + { + m_call_stack.push (fcn); + } + + void tree_evaluator::pop_stack_frame (void) + { + m_call_stack.pop (); + } + + int tree_evaluator::current_line (void) const + { + return m_call_stack.current_line (); + } + + int tree_evaluator::current_column (void) const + { + return m_call_stack.current_column (); + } + + int tree_evaluator::debug_user_code_line (void) const + { + return m_call_stack.debug_user_code_line (); + } + + int tree_evaluator::debug_user_code_column (void) const + { + return m_call_stack.debug_user_code_column (); + } + + void tree_evaluator::debug_where (std::ostream& os) const + { + std::shared_ptr frm = m_call_stack.current_user_frame (); + + frm->display_stopped_in_message (os); + } + + octave_user_code * tree_evaluator::current_user_code (void) const + { + return m_call_stack.current_user_code (); + } + + unwind_protect * tree_evaluator::curr_fcn_unwind_protect_frame (void) + { + return m_call_stack.curr_fcn_unwind_protect_frame (); + } + + octave_user_code * tree_evaluator::debug_user_code (void) const + { + return m_call_stack.debug_user_code (); + } + + octave_function * tree_evaluator::current_function (bool skip_first) const + { + return m_call_stack.current_function (skip_first); + } + + octave_function * tree_evaluator::caller_function (void) const + { + return m_call_stack.current_function (true); + } + + bool tree_evaluator::goto_frame (std::size_t n, bool verbose) + { + return m_call_stack.goto_frame (n, verbose); + } + + void tree_evaluator::goto_caller_frame (void) + { + m_call_stack.goto_caller_frame (); + } + + void tree_evaluator::goto_base_frame (void) + { + m_call_stack.goto_base_frame (); + } + + void tree_evaluator::restore_frame (std::size_t n) + { + return m_call_stack.restore_frame (n); + } + + std::string tree_evaluator::get_dispatch_class (void) const + { + return m_call_stack.get_dispatch_class (); + } + + void tree_evaluator::set_dispatch_class (const std::string& class_name) + { + m_call_stack.set_dispatch_class (class_name); + } + + bool + tree_evaluator::is_class_method_executing (std::string& dclass) const + { + return m_call_stack.is_class_method_executing (dclass); + } + + bool + tree_evaluator::is_class_constructor_executing (std::string& dclass) const + { + return m_call_stack.is_class_constructor_executing (dclass); + } + + std::list> + tree_evaluator::backtrace_frames (octave_idx_type& curr_user_frame) const + { + return m_call_stack.backtrace_frames (curr_user_frame); + } + + std::list> + tree_evaluator::backtrace_frames (void) const + { + return m_call_stack.backtrace_frames (); + } + + std::list + tree_evaluator::backtrace_info (octave_idx_type& curr_user_frame, + bool print_subfn) const + { + return m_call_stack.backtrace_info (curr_user_frame, print_subfn); + } + + std::list tree_evaluator::backtrace_info (void) const + { + return m_call_stack.backtrace_info (); + } + + octave_map + tree_evaluator::backtrace (octave_idx_type& curr_user_frame, + bool print_subfn) const + { + return m_call_stack.backtrace (curr_user_frame, print_subfn); + } + + octave_map tree_evaluator::backtrace (void) const + { + return m_call_stack.backtrace (); + } + + octave_map tree_evaluator::empty_backtrace (void) const + { + return m_call_stack.empty_backtrace (); + } + + std::string tree_evaluator::backtrace_message (void) const + { + std::list frames = backtrace_info (); + + std::ostringstream buf; + + for (const auto& frm : frames) + { + buf << " " << frm.fcn_name (); + + int line = frm.line (); + + if (line > 0) + { + buf << " at line " << line; + + int column = frm.column (); + + if (column > 0) + buf << " column " << column; + + buf << "\n"; + } + } + + return buf.str (); + } + + void tree_evaluator::push_dummy_scope (const std::string& name) + { + symbol_scope dummy_scope (name + "$dummy"); + + m_call_stack.push (dummy_scope); + } + + void tree_evaluator::pop_scope (void) + { + m_call_stack.pop (); + } + + symbol_scope tree_evaluator::get_top_scope (void) const + { + return m_call_stack.top_scope (); + } + + symbol_scope tree_evaluator::get_current_scope (void) const + { + return m_call_stack.current_scope (); + } + + void tree_evaluator::mlock (bool skip_first) const + { + octave_function *fcn = m_call_stack.current_function (skip_first); + + if (! fcn) + error ("mlock: invalid use outside a function"); + + if (fcn->is_builtin_function ()) + { + warning ("mlock: locking built-in function has no effect"); + return; + } + + fcn->lock (); + } + + void tree_evaluator::munlock (bool skip_first) const + { + octave_function *fcn = m_call_stack.current_function (skip_first); + + if (! fcn) + error ("munlock: invalid use outside a function"); + + if (fcn->is_builtin_function ()) + { + warning ("munlock: unlocking built-in function has no effect"); + return; + } + + fcn->unlock (); + } + + bool tree_evaluator::mislocked (bool skip_first) const + { + octave_function *fcn = m_call_stack.current_function (skip_first); + + if (! fcn) + error ("mislocked: invalid use outside a function"); + + return fcn->islocked (); + } + + octave_value + tree_evaluator::max_stack_depth (const octave_value_list& args, int nargout) + { + return m_call_stack.max_stack_depth (args, nargout); + } + + void tree_evaluator::display_call_stack (void) const + { + m_call_stack.display (); + } + + octave_value tree_evaluator::find (const std::string& name) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + octave_value val = frame->varval (name); + + if (val.is_defined ()) + return val; + + // Subfunction. I think it only makes sense to check for + // subfunctions if we are currently executing a function defined + // from a .m file. + + octave_value fcn = frame->find_subfunction (name); + + if (fcn.is_defined ()) + return fcn; + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + return symtab.fcn_table_find (name, ovl ()); + } + + void tree_evaluator::clear_objects (void) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + frame->clear_objects (); + } + + void tree_evaluator::clear_variable (const std::string& name) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + frame->clear_variable (name); + } + + void tree_evaluator::clear_variable_pattern (const std::string& pattern) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + frame->clear_variable_pattern (pattern); + } + + void tree_evaluator::clear_variable_regexp (const std::string& pattern) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + frame->clear_variable_regexp (pattern); + } + + void tree_evaluator::clear_variables (void) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + frame->clear_variables (); + } + + void tree_evaluator::clear_global_variable (const std::string& name) + { + m_call_stack.clear_global_variable (name); + } + + void + tree_evaluator::clear_global_variable_pattern (const std::string& pattern) + { + m_call_stack.clear_global_variable_pattern (pattern); + } + + void tree_evaluator::clear_global_variable_regexp(const std::string& pattern) + { + m_call_stack.clear_global_variable_regexp (pattern); + } + + void tree_evaluator::clear_global_variables (void) + { + m_call_stack.clear_global_variables (); + } + + void tree_evaluator::clear_all (bool force) + { + // FIXME: should this also clear objects? + + clear_variables (); + clear_global_variables (); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + symtab.clear_functions (force); + } + + void tree_evaluator::clear_symbol (const std::string& name) + { + // FIXME: are we supposed to do both here? + + clear_variable (name); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + symtab.clear_function (name); + } + + void tree_evaluator::clear_symbol_pattern (const std::string& pattern) + { + // FIXME: are we supposed to do both here? + + clear_variable_pattern (pattern); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + symtab.clear_function_pattern (pattern); + } + + void tree_evaluator::clear_symbol_regexp (const std::string& pattern) + { + // FIXME: are we supposed to do both here? + + clear_variable_regexp (pattern); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + symtab.clear_function_regexp (pattern); + } + + std::list tree_evaluator::global_variable_names (void) const + { + return m_call_stack.global_variable_names (); + } + + std::list tree_evaluator::top_level_variable_names (void) const + { + return m_call_stack.top_level_variable_names (); + } + + std::list tree_evaluator::variable_names (void) const + { + return m_call_stack.variable_names (); + } + + // Return a pointer to the user-defined function FNAME. If FNAME is empty, + // search backward for the first user-defined function in the + // current call stack. + + octave_user_code * + tree_evaluator::get_user_code (const std::string& fname, + const std::string& class_name) + { + octave_user_code *user_code = nullptr; + + if (fname.empty ()) + user_code = m_call_stack.debug_user_code (); + else + { + std::string name = fname; + + if (sys::file_ops::dir_sep_char () != '/' && name[0] == '@') + { + auto beg = name.begin () + 2; // never have @/method + auto end = name.end () - 1; // never have trailing '/' + std::replace (beg, end, '/', sys::file_ops::dir_sep_char ()); + } + + std::size_t name_len = name.length (); + + if (name_len > 2 && name.substr (name_len-2) == ".m") + name = name.substr (0, name_len-2); + + if (name.empty ()) + return nullptr; + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + octave_value fcn; + std::size_t p2 = std::string::npos; + + if (name[0] == '@') + { + std::size_t p1 = name.find (sys::file_ops::dir_sep_char (), 1); + + if (p1 == std::string::npos) + return nullptr; + + std::string dispatch_type = name.substr (1, p1-1); + + p2 = name.find ('>', p1); + + std::string method = name.substr (p1+1, p2-1); + + fcn = symtab.find_method (method, dispatch_type); + } + else if (! class_name.empty ()) + { + cdef_manager& cdm = m_interpreter.get_cdef_manager (); + + fcn = cdm.find_method (class_name, name); + + // If there is no classdef method, then try legacy classes. + if (fcn.is_undefined ()) + fcn = symtab.find_method (name, class_name); + } + else + { + p2 = name.find ('>'); + + std::string main_fcn = name.substr (0, p2); + + fcn = symtab.find_function (main_fcn); + } + + // List of function names sub1>sub2>... + std::string subfuns; + + if (p2 != std::string::npos) + subfuns = name.substr (p2+1); + + if (fcn.is_defined () && fcn.is_user_code ()) + user_code = fcn.user_code_value (); + + if (! user_code || subfuns.empty ()) + return user_code; + + fcn = user_code->find_subfunction (subfuns); + + if (fcn.is_undefined ()) + return nullptr; + + user_code = fcn.user_code_value (); + } + + return user_code; + } + + std::string + tree_evaluator::current_function_name (bool skip_first) const + { + octave_function *curfcn = m_call_stack.current_function (skip_first); + + if (curfcn) + return curfcn->name (); + + return ""; + } + + bool + tree_evaluator::in_user_code (void) const + { + return m_call_stack.current_user_code () != nullptr; + } + + void + tree_evaluator::visit_decl_command (tree_decl_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + // FIXME: tree_decl_init_list is not derived from tree, so should it + // really have an accept method? + + tree_decl_init_list *init_list = cmd.initializer_list (); + + if (init_list) + init_list->accept (*this); + } + + void + tree_evaluator::visit_decl_elt (tree_decl_elt& elt) + { + tree_identifier *id = elt.ident (); + + if (id) + { + if (elt.is_global ()) + m_call_stack.make_global (id->symbol ()); + else if (elt.is_persistent ()) + m_call_stack.make_persistent (id->symbol ()); + else + error ("declaration list element not global or persistent"); + + octave_lvalue ult = id->lvalue (*this); + + if (ult.is_undefined ()) + { + tree_expression *expr = elt.expression (); + + octave_value init_val; + + if (expr) + init_val = expr->evaluate (*this); + else + init_val = Matrix (); + + ult.assign (octave_value::op_asn_eq, init_val); + } + } + } + + template + void + tree_evaluator::execute_range_loop (const range& rng, int line, + octave_lvalue& ult, + tree_statement_list *loop_body) + { + octave_idx_type steps = rng.numel (); + + if (math::isinf (rng.limit ())) + warning_with_id ("Octave:infinite-loop", + "FOR loop limit is infinite, will stop after %" + OCTAVE_IDX_TYPE_FORMAT " steps", steps); + + for (octave_idx_type i = 0; i < steps; i++) + { + if (m_echo_state) + m_echo_file_pos = line; + + octave_value val (rng.elem (i)); + + ult.assign (octave_value::op_asn_eq, val); + + if (loop_body) + loop_body->accept (*this); + + if (quit_loop_now ()) + break; + } + } + + void + tree_evaluator::visit_simple_for_command (tree_simple_for_command& cmd) + { + int line = cmd.line (); + if (line < 0) + line = 1; + + if (m_echo_state) + { + echo_code (line); + line++; + } + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + // FIXME: need to handle PARFOR loops here using cmd.in_parallel () + // and cmd.maxproc_expr (); + + unwind_protect_var upv (m_in_loop_command, true); + + tree_expression *expr = cmd.control_expr (); + + octave_value rhs = expr->evaluate (*this); + + if (rhs.is_undefined ()) + return; + + tree_expression *lhs = cmd.left_hand_side (); + + octave_lvalue ult = lhs->lvalue (*this); + + tree_statement_list *loop_body = cmd.body (); + + if (rhs.is_range ()) + { + // FIXME: is there a better way to dispatch here? + + if (rhs.is_double_type ()) + { + execute_range_loop (rhs.range_value (), line, ult, loop_body); + return; + } + + // For now, disable all but range. + +#if 0 + if (rhs.is_int64_type ()) + { + execute_range_loop (rhs.int64_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_uint64_type ()) + { + execute_range_loop (rhs.uint64_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_int32_type ()) + { + execute_range_loop (rhs.int32_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_uint32_type ()) + { + execute_range_loop (rhs.uint32_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_int16_type ()) + { + execute_range_loop (rhs.int16_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_uint16_type ()) + { + execute_range_loop (rhs.uint16_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_int8_type ()) + { + execute_range_loop (rhs.int8_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_uint8_type ()) + { + execute_range_loop (rhs.uint8_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_single_type ()) + { + execute_range_loop (rhs.float_range_value (), line, ult, loop_body); + return; + } +#endif + } + + if (rhs.is_scalar_type ()) + { + if (m_echo_state) + m_echo_file_pos = line; + + ult.assign (octave_value::op_asn_eq, rhs); + + if (loop_body) + loop_body->accept (*this); + + // Maybe decrement break and continue states. + quit_loop_now (); + + return; + } + + // Also handle any range types not explicitly handled above, though + // not as efficiently as the specialized code above. + + if (rhs.is_range () || rhs.is_matrix_type () || rhs.iscell () + || rhs.is_string () || rhs.isstruct ()) + { + // A matrix or cell is reshaped to 2 dimensions and iterated by + // columns. + + dim_vector dv = rhs.dims ().redim (2); + + octave_idx_type nrows = dv(0); + octave_idx_type steps = dv(1); + + octave_value arg = rhs; + if (rhs.ndims () > 2) + arg = arg.reshape (dv); + + if (nrows > 0 && steps > 0) + { + octave_value_list idx; + octave_idx_type iidx; + + // for row vectors, use single index to speed things up. + if (nrows == 1) + { + idx.resize (1); + iidx = 0; + } + else + { + idx.resize (2); + idx(0) = octave_value::magic_colon_t; + iidx = 1; + } + + for (octave_idx_type i = 1; i <= steps; i++) + { + if (m_echo_state) + m_echo_file_pos = line; + + // index_op expects one-based indices. + idx(iidx) = i; + octave_value val = arg.index_op (idx); + + ult.assign (octave_value::op_asn_eq, val); + + if (loop_body) + loop_body->accept (*this); + + if (quit_loop_now ()) + break; + } + } + else + { + // Handle empty cases, while still assigning to loop var. + ult.assign (octave_value::op_asn_eq, arg); + } + + return; + } + + error ("invalid type in for loop expression near line %d, column %d", + cmd.line (), cmd.column ()); + } + + void + tree_evaluator::visit_complex_for_command (tree_complex_for_command& cmd) + { + int line = cmd.line (); + if (line < 0) + line = 1; + + if (m_echo_state) + { + echo_code (line); + line++; + } + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + unwind_protect_var upv (m_in_loop_command, true); + + tree_expression *expr = cmd.control_expr (); + + octave_value rhs = expr->evaluate (*this); + + if (rhs.is_undefined ()) + return; + + if (! rhs.isstruct ()) + error ("in statement 'for [X, Y] = VAL', VAL must be a structure"); + + // Cycle through structure elements. First element of id_list + // is set to value and the second is set to the name of the + // structure element. + + tree_argument_list *lhs = cmd.left_hand_side (); + + auto p = lhs->begin (); + + tree_expression *elt = *p++; + + octave_lvalue val_ref = elt->lvalue (*this); + + elt = *p; + + octave_lvalue key_ref = elt->lvalue (*this); + + const octave_map tmp_val = rhs.map_value (); + + tree_statement_list *loop_body = cmd.body (); + + string_vector keys = tmp_val.keys (); + + octave_idx_type nel = keys.numel (); + + for (octave_idx_type i = 0; i < nel; i++) + { + if (m_echo_state) + m_echo_file_pos = line; + + std::string key = keys[i]; + + const Cell val_lst = tmp_val.contents (key); + + octave_idx_type n = val_lst.numel (); + + octave_value val = (n == 1) ? val_lst(0) : octave_value (val_lst); + + val_ref.assign (octave_value::op_asn_eq, val); + key_ref.assign (octave_value::op_asn_eq, key); + + if (loop_body) + loop_body->accept (*this); + + if (quit_loop_now ()) + break; + } + } + + void tree_evaluator::visit_spmd_command (tree_spmd_command& cmd) + { + // For now, we just execute the commands serially. + + tree_statement_list *body = cmd.body (); + + if (body) + body->accept (*this); + } + + octave_value + tree_evaluator::evaluate_anon_fcn_handle (tree_anon_fcn_handle& afh) + { + // FIXME: should CMD_LIST be limited to a single expression? + // I think that is what Matlab does. + + symbol_scope new_scope; + symbol_scope scope = afh.scope (); + if (scope) + new_scope = scope.dup (); + + tree_parameter_list *param_list = afh.parameter_list (); + tree_parameter_list *param_list_dup + = param_list ? param_list->dup (new_scope) : nullptr; + + tree_parameter_list *ret_list = nullptr; + + tree_statement_list *stmt_list = nullptr; + + symbol_scope parent_scope = get_current_scope (); + + new_scope.set_parent (parent_scope); + new_scope.set_primary_parent (parent_scope); + + tree_expression *expr = afh.expression (); + if (expr) + { + tree_expression *expr_dup = expr->dup (new_scope); + tree_statement *stmt = new tree_statement (expr_dup, nullptr); + stmt_list = new tree_statement_list (stmt); + } + + tree_anon_scopes anon_fcn_ctx (afh); + + std::set free_vars = anon_fcn_ctx.free_variables (); + + stack_frame::local_vars_map local_vars; + + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + for (auto& name : free_vars) + { + octave_value val = frame->varval (name); + + if (val.is_defined ()) + local_vars[name] = val; + } + + octave_user_function *af + = new octave_user_function (new_scope, param_list_dup, ret_list, + stmt_list); + + octave_function *curr_fcn = m_call_stack.current_function (); + + bool is_nested = false; + + if (curr_fcn) + { + // FIXME: maybe it would be better to just stash curr_fcn + // instead of individual bits of info about it? + + // An anonymous function defined inside another nested function + // or parent of a nested function also behaves like a nested + // function. + + if (curr_fcn->is_parent_function () || curr_fcn->is_nested_function ()) + { + is_nested = true; + af->mark_as_nested_function (); + new_scope.set_nesting_depth (parent_scope.nesting_depth () + 1); + } + + af->stash_dir_name (curr_fcn->dir_name ()); + + new_scope.cache_fcn_file_name (curr_fcn->fcn_file_name ()); + new_scope.cache_dir_name (curr_fcn->dir_name ()); + + // The following is needed so that class method dispatch works + // properly for anonymous functions that wrap class methods. + + if (curr_fcn->is_class_method () || curr_fcn->is_class_constructor ()) + af->stash_dispatch_class (curr_fcn->dispatch_class ()); + + af->stash_fcn_file_name (curr_fcn->fcn_file_name ()); + } + + af->mark_as_anonymous_function (); + + octave_value ov_fcn (af); + + return (is_nested + ? octave_value (new octave_fcn_handle (ov_fcn, local_vars, frame)) + : octave_value (new octave_fcn_handle (ov_fcn, local_vars))); + } + + octave_value_list + tree_evaluator::execute_builtin_function (octave_builtin& builtin_function, + int nargout, + const octave_value_list& args) + { + octave_value_list retval; + + if (args.has_magic_colon ()) + error ("invalid use of colon in function argument list"); + + profiler::enter block (m_profiler, builtin_function); + + octave_builtin::fcn fcn = builtin_function.function (); + + if (fcn) + retval = (*fcn) (args, nargout); + else + { + octave_builtin::meth meth = builtin_function.method (); + + retval = (*meth) (m_interpreter, args, nargout); + } + + // Do not allow null values to be returned from functions. + // FIXME: perhaps true builtins should be allowed? + + retval.make_storable_values (); + + // Fix the case of a single undefined value. + // This happens when a compiled function uses + // + // octave_value retval; + // + // instead of + // + // octave_value_list retval; + // + // the idiom is very common, so we solve that here. + + if (retval.length () == 1 && retval.xelem (0).is_undefined ()) + retval.clear (); + + return retval; + } + + octave_value_list + tree_evaluator::execute_mex_function (octave_mex_function& mex_function, + int nargout, + const octave_value_list& args) + { + octave_value_list retval; + + if (args.has_magic_colon ()) + error ("invalid use of colon in function argument list"); + + profiler::enter block (m_profiler, mex_function); + + retval = call_mex (mex_function, args, nargout); + + return retval; + } + + octave_value_list + tree_evaluator::execute_user_script (octave_user_script& user_script, + int nargout, + const octave_value_list& args) + { + octave_value_list retval; + + std::string file_name = user_script.fcn_file_name (); + + if (args.length () != 0 || nargout != 0) + error ("invalid call to script %s", file_name.c_str ()); + + tree_statement_list *cmd_list = user_script.body (); + + if (! cmd_list) + return retval; + + // FIXME: Maybe this check belongs in the places where we push a new + // stack frame? Or in the call_stack push method itself? + + if (m_call_stack.size () >= static_cast (m_max_recursion_depth)) + error ("max_recursion_depth exceeded"); + + unwind_protect_var upv (m_statement_context, SC_SCRIPT); + + profiler::enter block (m_profiler, user_script); + + if (echo ()) + push_echo_state (tree_evaluator::ECHO_SCRIPTS, file_name); + + // FIXME: Should we be using tree_evaluator::eval here? + + cmd_list->accept (*this); + + if (m_returning) + m_returning = 0; + + if (m_breaking) + m_breaking--; + + return retval; + } + + void + tree_evaluator::visit_octave_user_script (octave_user_script&) + { + // ?? + panic_impossible (); + } + + octave_value_list + tree_evaluator::execute_user_function (octave_user_function& user_function, + int nargout, + const octave_value_list& xargs) + { + octave_value_list retval; + + // If this function is a classdef constructor, extract the first input + // argument, which must be the partially constructed object instance. + + octave_value_list args (xargs); + octave_value_list ret_args; + + int nargin = args.length (); + + if (user_function.is_classdef_constructor ()) + { + if (nargin > 0) + { + ret_args = args.slice (0, 1, true); + --nargin; + args = args.slice (1, nargin, true); + } + else + panic_impossible (); + } + + // FIXME: this probably shouldn't be a double-precision matrix. + Matrix ignored_outputs = ignored_fcn_outputs (); + + tree_parameter_list *param_list = user_function.parameter_list (); + + bool takes_varargs = false; + int max_inputs = 0; + + if (param_list) + { + takes_varargs = param_list->takes_varargs (); + max_inputs = param_list->length (); + } + + if (! takes_varargs && nargin > max_inputs) + { + std::string name = user_function.name (); + + if (name.empty ()) + name = "@"; + + error_with_id ("Octave:invalid-fun-call", + "%s: function called with too many inputs", + name.c_str ()); + } + + define_parameter_list_from_arg_vector (param_list, args); + + tree_parameter_list *ret_list = user_function.return_list (); + + if (ret_list && ! ret_list->takes_varargs ()) + { + int max_outputs = ret_list->length (); + + if (nargout > max_outputs) + { + std::string name = user_function.name (); + + error_with_id ("Octave:invalid-fun-call", + "%s: function called with too many outputs", + name.c_str ()); + } + } + + bind_auto_fcn_vars (xargs.name_tags (), ignored_outputs, nargin, + nargout, user_function.takes_varargs (), + user_function.all_va_args (args)); + + // For classdef constructor, pre-populate the output arguments + // with the pre-initialized object instance, extracted above. + + if (user_function.is_classdef_constructor ()) + { + if (! ret_list) + error ("%s: invalid classdef constructor, no output argument defined", + user_function.dispatch_class ().c_str ()); + + define_parameter_list_from_arg_vector (ret_list, ret_args); + } + + // FIXME: Maybe this check belongs in the places where we push a + // new stack frame? Or in the call_stack push method itself? + + if (m_call_stack.size () >= static_cast (m_max_recursion_depth)) + error ("max_recursion_depth exceeded"); + + unwind_action act2 ([&user_function] () { + user_function.restore_warning_states (); + }); + + // Evaluate the commands that make up the function. + + unwind_protect_var upv (m_statement_context, SC_FUNCTION); + + tree_statement_list *cmd_list = user_function.body (); + + if (cmd_list) + { + profiler::enter + block (m_profiler, user_function); + + if (echo ()) + push_echo_state (tree_evaluator::ECHO_FUNCTIONS, + user_function.fcn_file_name ()); + + if (user_function.is_special_expr ()) + { + panic_if (cmd_list->length () != 1); + + tree_statement *stmt = cmd_list->front (); + + tree_expression *expr = stmt->expression (); + + if (expr) + { + m_call_stack.set_location (stmt->line (), stmt->column ()); + + retval = expr->evaluate_n (*this, nargout); + } + } + else + cmd_list->accept (*this); + + if (m_returning) + m_returning = 0; + + if (m_breaking) + m_breaking--; + } + + // Copy return values out. + + if (ret_list && ! user_function.is_special_expr ()) + { + Cell varargout; + + if (ret_list->takes_varargs ()) + { + octave_value varargout_varval = varval ("varargout"); + + if (varargout_varval.is_defined ()) + varargout = varargout_varval.xcell_value ("varargout must be a cell array object"); + } + + retval = convert_return_list_to_const_vector (ret_list, nargout, + ignored_outputs, + varargout); + } + + return retval; + } + + void + tree_evaluator::visit_octave_user_function (octave_user_function&) + { + // ?? + panic_impossible (); + } + + void + tree_evaluator::visit_octave_user_function_header (octave_user_function&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_octave_user_function_trailer (octave_user_function&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_function_def (tree_function_def& cmd) + { + octave_value fcn = cmd.function (); + + octave_function *f = fcn.function_value (); + + if (f) + { + std::string nm = f->name (); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + symtab.install_cmdline_function (nm, fcn); + + // Make sure that any variable with the same name as the new + // function is cleared. + + assign (nm); + } + } + + void + tree_evaluator::visit_identifier (tree_identifier&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_if_clause (tree_if_clause&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_if_command (tree_if_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + // FIXME: tree_if_command_list is not derived from tree, so should it + // really have an accept method? + + tree_if_command_list *lst = cmd.cmd_list (); + + if (lst) + lst->accept (*this); + } + + void + tree_evaluator::visit_if_command_list (tree_if_command_list& lst) + { + for (tree_if_clause *tic : lst) + { + tree_expression *expr = tic->condition (); + + if (! (in_debug_repl () + && m_call_stack.current_frame () == m_debug_frame)) + m_call_stack.set_location (tic->line (), tic->column ()); + + if (m_debug_mode && ! tic->is_else_clause ()) + do_breakpoint (tic->is_active_breakpoint (*this)); + + if (tic->is_else_clause () || is_logically_true (expr, "if")) + { + tree_statement_list *stmt_lst = tic->commands (); + + if (stmt_lst) + stmt_lst->accept (*this); + + break; + } + } + } + + void + tree_evaluator::visit_index_expression (tree_index_expression&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_matrix (tree_matrix&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_cell (tree_cell&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_multi_assignment (tree_multi_assignment&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_no_op_command (tree_no_op_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + if (m_debug_mode && cmd.is_end_of_fcn_or_script ()) + do_breakpoint (cmd.is_active_breakpoint (*this), true); + } + + void + tree_evaluator::visit_constant (tree_constant&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_fcn_handle (tree_fcn_handle&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_parameter_list (tree_parameter_list&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_postfix_expression (tree_postfix_expression&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_prefix_expression (tree_prefix_expression&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_return_command (tree_return_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + // Act like dbcont. + + if (in_debug_repl () && m_call_stack.current_frame () == m_debug_frame) + dbcont (); + else if (m_statement_context == SC_FUNCTION + || m_statement_context == SC_SCRIPT + || m_in_loop_command) + m_returning = 1; + } + + void + tree_evaluator::visit_simple_assignment (tree_simple_assignment&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_statement (tree_statement& stmt) + { + tree_command *cmd = stmt.command (); + tree_expression *expr = stmt.expression (); + + if (cmd || expr) + { + if (! (in_debug_repl () + && m_call_stack.current_frame () == m_debug_frame)) + m_call_stack.set_location (stmt.line (), stmt.column ()); + + try + { + if (cmd) + { + unwind_protect_var *> + upv (m_lvalue_list, nullptr); + + cmd->accept (*this); + } + else + { + if (m_echo_state) + { + int line = stmt.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + if (m_debug_mode) + do_breakpoint (expr->is_active_breakpoint (*this)); + + // FIXME: maybe all of this should be packaged in + // one virtual function that returns a flag saying whether + // or not the expression will take care of binding ans and + // printing the result. + + // FIXME: it seems that we should just have to + // evaluate the expression and that should take care of + // everything, binding ans as necessary? + + octave_value tmp_result = expr->evaluate (*this, 0); + + if (tmp_result.is_defined ()) + { + bool do_bind_ans = false; + + if (expr->is_identifier ()) + do_bind_ans = ! is_variable (expr); + else + do_bind_ans = ! expr->is_assignment_expression (); + + if (do_bind_ans) + bind_ans (tmp_result, expr->print_result () + && statement_printing_enabled ()); + } + } + } + catch (const std::bad_alloc&) + { + // FIXME: We want to use error_with_id here so that give users + // control over this error message but error_with_id will + // require some memory allocations. Is there anything we can + // do to make those more likely to succeed? + + error_with_id ("Octave:bad-alloc", + "out of memory or dimension too large for Octave's index type"); + } + catch (const interrupt_exception&) + { + // If we are debugging, then continue with next statement. + // Otherwise, jump out of here. + + if (m_debug_mode) + m_interpreter.recover_from_exception (); + else + throw; + } + catch (const execution_exception& ee) + { + error_system& es = m_interpreter.get_error_system (); + + if ((m_interpreter.interactive () + || application::forced_interactive ()) + && ((es.debug_on_error () + && m_bp_table.debug_on_err (es.last_error_id ())) + || (es.debug_on_caught () + && m_bp_table.debug_on_caught (es.last_error_id ()))) + && in_user_code ()) + { + es.save_exception (ee); + es.display_exception (ee); + + enter_debugger (); + + // It doesn't make sense to continue execution after an + // error occurs so force the debugger to quit all debug + // levels and return the the top prompt. + + throw quit_debug_exception (true); + } + else + throw; + } + } + } + + void + tree_evaluator::visit_statement_list (tree_statement_list& lst) + { + // FIXME: commented out along with else clause below. + // static octave_value_list empty_list; + + auto p = lst.begin (); + + if (p != lst.end ()) + { + while (true) + { + tree_statement *elt = *p++; + + if (! elt) + error ("invalid statement found in statement list!"); + + octave_quit (); + + elt->accept (*this); + + if (m_breaking || m_continuing) + break; + + if (m_returning) + break; + + if (p == lst.end ()) + break; + else + { + // Clear previous values before next statement is + // evaluated so that we aren't holding an extra + // reference to a value that may be used next. For + // example, in code like this: + // + // X = rand (N); # refcount for X should be 1 + // # after this statement + // + // X(idx) = val; # no extra copy of X should be + // # needed, but we will be faked + // # out if retval is not cleared + // # between statements here + + // result_values = empty_list; + } + } + } + } + + void + tree_evaluator::visit_switch_case (tree_switch_case&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_switch_case_list (tree_switch_case_list&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_switch_command (tree_switch_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + tree_expression *expr = cmd.switch_value (); + + if (! expr) + error ("missing value in switch command near line %d, column %d", + cmd.line (), cmd.column ()); + + octave_value val = expr->evaluate (*this); + + tree_switch_case_list *lst = cmd.case_list (); + + if (lst) + { + for (tree_switch_case *t : *lst) + { + if (t->is_default_case () || switch_case_label_matches (t, val)) + { + tree_statement_list *stmt_lst = t->commands (); + + if (stmt_lst) + stmt_lst->accept (*this); + + break; + } + } + } + } + + void + tree_evaluator::visit_try_catch_command (tree_try_catch_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + bool execution_error = false; + octave_scalar_map err_map; + + tree_statement_list *try_code = cmd.body (); + + if (try_code) + { + // unwind frame before catch block + + unwind_protect frame; + + interpreter_try (frame); + + // The catch code is *not* added to unwind_protect stack; it + // doesn't need to be run on interrupts. + + try + { + try_code->accept (*this); + } + catch (const execution_exception& ee) + { + execution_error = true; + + error_system& es = m_interpreter.get_error_system (); + + es.save_exception (ee); + + err_map.assign ("message", es.last_error_message ()); + err_map.assign ("identifier", es.last_error_id ()); + err_map.assign ("stack", es.last_error_stack ()); + + m_interpreter.recover_from_exception (); + } + + // Actions attached to unwind_protect frame will run here, prior + // to executing the catch block. + } + + if (execution_error) + { + tree_statement_list *catch_code = cmd.cleanup (); + + if (catch_code) + { + tree_identifier *expr_id = cmd.identifier (); + + if (expr_id) + { + octave_lvalue ult = expr_id->lvalue (*this); + + ult.assign (octave_value::op_asn_eq, err_map); + } + + // perform actual "catch" block + catch_code->accept (*this); + } + } + } + + void + tree_evaluator::do_unwind_protect_cleanup_code (tree_statement_list *list) + { + unwind_protect frame; + + frame.protect_var (octave_interrupt_state); + octave_interrupt_state = 0; + + // We want to preserve the last location info for possible + // backtracking. + + frame.add (&call_stack::set_line, &m_call_stack, + m_call_stack.current_line ()); + + frame.add (&call_stack::set_column, &m_call_stack, + m_call_stack.current_column ()); + + // Similarly, if we have seen a return or break statement, allow all + // the cleanup code to run before returning or handling the break. + // We don't have to worry about continue statements because they can + // only occur in loops. + + frame.protect_var (m_returning); + m_returning = 0; + + frame.protect_var (m_breaking); + m_breaking = 0; + + try + { + if (list) + list->accept (*this); + } + catch (const execution_exception& ee) + { + error_system& es = m_interpreter.get_error_system (); + + es.save_exception (ee); + m_interpreter.recover_from_exception (); + + if (m_breaking || m_returning) + frame.discard (2); + else + frame.run (2); + + frame.discard (2); + + throw; + } + + // The unwind_protects are popped off the stack in the reverse of + // the order they are pushed on. + + // FIXME: these statements say that if we see a break or + // return statement in the cleanup block, that we want to use the + // new value of the breaking or returning flag instead of restoring + // the previous value. Is that the right thing to do? I think so. + // Consider the case of + // + // function foo () + // unwind_protect + // fprintf (stderr, "1: this should always be executed\n"); + // break; + // fprintf (stderr, "1: this should never be executed\n"); + // unwind_protect_cleanup + // fprintf (stderr, "2: this should always be executed\n"); + // return; + // fprintf (stderr, "2: this should never be executed\n"); + // end_unwind_protect + // endfunction + // + // If we reset the value of the breaking flag, both the returning + // flag and the breaking flag will be set, and we shouldn't have + // both. So, use the most recent one. If there is no return or + // break in the cleanup block, the values should be reset to + // whatever they were when the cleanup block was entered. + + if (m_breaking || m_returning) + frame.discard (2); + else + frame.run (2); + } + + void + tree_evaluator::visit_unwind_protect_command (tree_unwind_protect_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + tree_statement_list *cleanup_code = cmd.cleanup (); + + tree_statement_list *unwind_protect_code = cmd.body (); + + if (unwind_protect_code) + { + try + { + unwind_protect_code->accept (*this); + } + catch (const execution_exception& ee) + { + error_system& es = m_interpreter.get_error_system (); + + // FIXME: Maybe we should be able to temporarily set the + // interpreter's exception handling state to something "safe" + // while the cleanup block runs instead of just resetting it + // here? + es.save_exception (ee); + m_interpreter.recover_from_exception (); + + // Run the cleanup code on exceptions, so that it is run even + // in case of interrupt or out-of-memory. + do_unwind_protect_cleanup_code (cleanup_code); + + // If an error occurs inside the cleanup code, a new + // exception will be thrown instead of the original. + throw; + } + catch (const interrupt_exception&) + { + // The comments above apply here as well. + m_interpreter.recover_from_exception (); + do_unwind_protect_cleanup_code (cleanup_code); + throw; + } + + // Also execute the unwind_protect_cleanump code if the + // unwind_protect block runs without error. + do_unwind_protect_cleanup_code (cleanup_code); + } + } + + void + tree_evaluator::visit_while_command (tree_while_command& cmd) + { + int line = cmd.line (); + if (line < 0) + line = 1; + + if (m_echo_state) + { + echo_code (line); + line++; + } + + unwind_protect_var upv (m_in_loop_command, true); + + tree_expression *expr = cmd.condition (); + + if (! expr) + panic_impossible (); + + for (;;) + { + if (m_echo_state) + m_echo_file_pos = line; + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + if (is_logically_true (expr, "while")) + { + tree_statement_list *loop_body = cmd.body (); + + if (loop_body) + loop_body->accept (*this); + + if (quit_loop_now ()) + break; + } + else + break; + } + } + + void + tree_evaluator::visit_do_until_command (tree_do_until_command& cmd) + { + int line = cmd.line (); + if (line < 0) + line = 1; + + if (m_echo_state) + { + echo_code (line); + line++; + } + + unwind_protect_var upv (m_in_loop_command, true); + + tree_expression *expr = cmd.condition (); + + if (! expr) + panic_impossible (); + + for (;;) + { + if (m_echo_state) + m_echo_file_pos = line; + + tree_statement_list *loop_body = cmd.body (); + + if (loop_body) + loop_body->accept (*this); + + if (quit_loop_now ()) + break; + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + if (is_logically_true (expr, "do-until")) + break; + } + } + + void + tree_evaluator::visit_superclass_ref (tree_superclass_ref&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_metaclass_query (tree_metaclass_query&) + { + panic_impossible (); + } + + void tree_evaluator::bind_ans (const octave_value& val, bool print) + { + static std::string ans = "ans"; + + if (val.is_defined ()) + { + if (val.is_cs_list ()) + { + octave_value_list lst = val.list_value (); + + for (octave_idx_type i = 0; i < lst.length (); i++) + bind_ans (lst(i), print); + } + else + { + // FIXME: Maybe assign could also return the assigned value, + // just for convenience? + + assign (ans, val); + + if (print) + { + // Use varval instead of displaying VAL directly so that + // we get the right type and value for things like + // magic_int values that may mutate when stored. + + octave_value_list args = ovl (varval (ans)); + args.stash_name_tags (string_vector (ans)); + feval ("display", args); + } + } + } + } + + void + tree_evaluator::do_breakpoint (tree_statement& stmt) + { + do_breakpoint (stmt.is_active_breakpoint (*this), + stmt.is_end_of_fcn_or_script ()); + } + + void + tree_evaluator::do_breakpoint (bool is_breakpoint, + bool is_end_of_fcn_or_script) + { + bool break_on_this_statement = false; + + if (is_breakpoint) + break_on_this_statement = true; + else if (m_dbstep_flag > 0) + { + if (m_call_stack.current_frame () == m_debug_frame) + { + if (m_dbstep_flag == 1 || is_end_of_fcn_or_script) + { + // We get here if we are doing a "dbstep" or a "dbstep N" and + // the count has reached 1 so that we must stop and return to + // debug prompt. Alternatively, "dbstep N" has been used but + // the end of the frame has been reached so we stop at the last + // line and return to prompt. + + break_on_this_statement = true; + } + else + { + // Executing "dbstep N". Decrease N by one and continue. + + m_dbstep_flag--; + } + + } + else if (m_dbstep_flag == 1 + && m_call_stack.current_frame () < m_debug_frame) + { + // We stepped out from the end of a function. + + m_debug_frame = m_call_stack.current_frame (); + + break_on_this_statement = true; + } + } + else if (m_dbstep_flag == -1) + { + // We get here if we are doing a "dbstep in". + + break_on_this_statement = true; + + m_debug_frame = m_call_stack.current_frame (); + } + else if (m_dbstep_flag == -2) + { + // We get here if we are doing a "dbstep out". Check for end of + // function and whether the current frame is the same as the + // cached value because we want to step out from the frame where + // "dbstep out" was evaluated, not from any functions called from + // that frame. + + if (is_end_of_fcn_or_script + && m_call_stack.current_frame () == m_debug_frame) + m_dbstep_flag = -1; + } + + if (! break_on_this_statement) + break_on_this_statement = m_break_on_next_stmt; + + m_break_on_next_stmt = false; + + if (break_on_this_statement) + { + m_dbstep_flag = 0; + + enter_debugger (); + } + } + + bool + tree_evaluator::is_logically_true (tree_expression *expr, + const char *warn_for) + { + bool expr_value = false; + + m_call_stack.set_location (expr->line (), expr->column ()); + + octave_value t1 = expr->evaluate (*this); + + if (t1.is_defined ()) + return t1.is_true (); + else + error ("%s: undefined value used in conditional expression", warn_for); + + return expr_value; + } + + octave_value + tree_evaluator::max_recursion_depth (const octave_value_list& args, + int nargout) + { + return set_internal_variable (m_max_recursion_depth, args, nargout, + "max_recursion_depth", 0); + } + + symbol_info_list + tree_evaluator::glob_symbol_info (const std::string& pattern) const + { + return m_call_stack.glob_symbol_info (pattern); + } + + symbol_info_list + tree_evaluator::regexp_symbol_info (const std::string& pattern) const + { + return m_call_stack.regexp_symbol_info (pattern); + } + + symbol_info_list + tree_evaluator::get_symbol_info (void) + { + return m_call_stack.get_symbol_info (); + } + + symbol_info_list + tree_evaluator::top_scope_symbol_info (void) const + { + return m_call_stack.top_scope_symbol_info (); + } + + octave_map tree_evaluator::get_autoload_map (void) const + { + Cell fcn_names (dim_vector (m_autoload_map.size (), 1)); + Cell file_names (dim_vector (m_autoload_map.size (), 1)); + + octave_idx_type i = 0; + for (const auto& fcn_fname : m_autoload_map) + { + fcn_names(i) = fcn_fname.first; + file_names(i) = fcn_fname.second; + + i++; + } + + octave_map m; + + m.assign ("function", fcn_names); + m.assign ("file", file_names); + + return m; + } + + std::string tree_evaluator::lookup_autoload (const std::string& nm) const + { + std::string retval; + + auto p = m_autoload_map.find (nm); + + if (p != m_autoload_map.end ()) + { + load_path& lp = m_interpreter.get_load_path (); + + retval = lp.find_file (p->second); + } + + return retval; + } + + std::list tree_evaluator::autoloaded_functions (void) const + { + std::list names; + + for (const auto& fcn_fname : m_autoload_map) + names.push_back (fcn_fname.first); + + return names; + } + + std::list + tree_evaluator::reverse_lookup_autoload (const std::string& nm) const + { + std::list names; + + for (const auto& fcn_fname : m_autoload_map) + if (nm == fcn_fname.second) + names.push_back (fcn_fname.first); + + return names; + } + + void tree_evaluator::add_autoload (const std::string& fcn, + const std::string& nm) + { + std::string file_name = check_autoload_file (nm); + + m_autoload_map[fcn] = file_name; + } + + void tree_evaluator::remove_autoload (const std::string& fcn, + const std::string& nm) + { + check_autoload_file (nm); + + // Remove function from symbol table and autoload map. + symbol_table& symtab = m_interpreter.get_symbol_table (); + + symtab.clear_dld_function (fcn); + + m_autoload_map.erase (fcn); + } + + octave_value + tree_evaluator::whos_line_format (const octave_value_list& args, int nargout) + { + return set_internal_variable (m_whos_line_format, args, nargout, + "whos_line_format"); + } + + octave_value + tree_evaluator::silent_functions (const octave_value_list& args, int nargout) + { + return set_internal_variable (m_silent_functions, args, nargout, + "silent_functions"); + } + + octave_value + tree_evaluator::string_fill_char (const octave_value_list& args, int nargout) + { + return set_internal_variable (m_string_fill_char, args, nargout, + "string_fill_char"); + } + + // Final step of processing an indexing error. Add the name of the + // variable being indexed, if any, then issue an error. (Will this also + // be needed by pt-lvalue, which calls subsref?) + + void tree_evaluator::final_index_error (index_exception& ie, + const tree_expression *expr) + { + std::string extra_message; + + if (is_variable (expr)) + { + std::string var = expr->name (); + + ie.set_var (var); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + octave_value fcn = symtab.find_function (var); + + if (fcn.is_function ()) + { + octave_function *fp = fcn.function_value (); + + if (fp && fp->name () == var) + extra_message + = " (note: variable '" + var + "' shadows function)"; + } + } + + std::string msg = ie.message () + extra_message; + + error_with_id (ie.err_id (), "%s", msg.c_str ()); + } + + octave_value + tree_evaluator::do_who (int argc, const string_vector& argv, + bool return_list, bool verbose) + { + return m_call_stack.do_who (argc, argv, return_list, verbose); + } + + octave_value_list + tree_evaluator::make_value_list (tree_argument_list *args, + const string_vector& arg_nm) + { + octave_value_list retval; + + if (args) + { + unwind_protect_var *> + upv (m_lvalue_list, nullptr); + + int len = args->length (); + + unwind_protect_var upv2 (m_index_position); + unwind_protect_var upv3 (m_num_indices); + + m_num_indices = len; + + std::list arg_vals; + + int k = 0; + + for (auto elt : *args) + { + // FIXME: is it possible for elt to be invalid? + + if (! elt) + break; + + m_index_position = k++; + + octave_value tmp = elt->evaluate (*this); + + if (tmp.is_cs_list ()) + { + octave_value_list tmp_ovl = tmp.list_value (); + + for (octave_idx_type i = 0; i < tmp_ovl.length (); i++) + arg_vals.push_back (tmp_ovl(i)); + } + else if (tmp.is_defined ()) + arg_vals.push_back (tmp); + } + + retval = octave_value_list (arg_vals); + } + + octave_idx_type n = retval.length (); + + if (n > 0) + retval.stash_name_tags (arg_nm); + + return retval; + } + + std::list + tree_evaluator::make_lvalue_list (tree_argument_list *lhs) + { + std::list retval; + + for (tree_expression *elt : *lhs) + retval.push_back (elt->lvalue (*this)); + + return retval; + } + + void + tree_evaluator::push_echo_state (int type, const std::string& file_name, + int pos) + { + unwind_protect *frame = m_call_stack.curr_fcn_unwind_protect_frame (); + + if (frame) + { + push_echo_state_cleanup (*frame); + + set_echo_state (type, file_name, pos); + } + } + + void + tree_evaluator::set_echo_state (int type, const std::string& file_name, + int pos) + { + m_echo_state = echo_this_file (file_name, type); + m_echo_file_name = file_name; + m_echo_file_pos = pos; + } + + void + tree_evaluator::uwp_set_echo_state (bool state, const std::string& file_name, + int pos) + { + m_echo_state = state; + m_echo_file_name = file_name; + m_echo_file_pos = pos; + } + + void + tree_evaluator::maybe_set_echo_state (void) + { + octave_function *caller = caller_function (); + + if (caller && caller->is_user_code ()) + { + octave_user_code *fcn = dynamic_cast (caller); + + int type = fcn->is_user_function () ? ECHO_FUNCTIONS : ECHO_SCRIPTS; + + std::string file_name = fcn->fcn_file_name (); + + // We want the line where "echo" was called, not the line number + // stored in the stack frame that was created for the echo + // function (that will always be -1). + + int pos = m_call_stack.current_user_code_line (); + + if (pos < 0) + pos = 1; + + set_echo_state (type, file_name, pos); + } + } + + void + tree_evaluator::push_echo_state_cleanup (unwind_protect& frame) + { + frame.add (&tree_evaluator::uwp_set_echo_state, this, + m_echo_state, m_echo_file_name, m_echo_file_pos); + } + + bool tree_evaluator::maybe_push_echo_state_cleanup (void) + { + // This function is expected to be called from ECHO, which would be + // the top of the call stack. If the caller of ECHO is a + // user-defined function or script, then set up unwind-protect + // elements to restore echo state. + + unwind_protect *frame = m_call_stack.curr_fcn_unwind_protect_frame (); + + if (frame) + { + push_echo_state_cleanup (*frame); + return true; + } + + return false; + } + + + octave_value + tree_evaluator::echo (const octave_value_list& args, int) + { + bool cleanup_pushed = maybe_push_echo_state_cleanup (); + + string_vector argv = args.make_argv (); + + switch (args.length ()) + { + case 0: + if ((m_echo & ECHO_SCRIPTS) || (m_echo & ECHO_FUNCTIONS)) + { + m_echo = ECHO_OFF; + m_echo_files.clear (); + } + else + m_echo = ECHO_SCRIPTS; break; - octave_value tmp = elt->evaluate (*this); - - if (tmp.is_cs_list ()) + case 1: { - octave_value_list tmp_ovl = tmp.list_value (); - - for (octave_idx_type i = 0; i < tmp_ovl.length (); i++) - arg_vals.push_back (tmp_ovl(i)); - } - else if (tmp.is_defined ()) - arg_vals.push_back (tmp); - } - - return octave_value_list (arg_vals); -} - -octave_value_list -tree_evaluator::convert_return_list_to_const_vector -(tree_parameter_list *ret_list, int nargout, const Matrix& ignored_outputs, - const Cell& varargout) -{ - octave_idx_type vlen = varargout.numel (); - int len = ret_list->length (); - - // Special case. Will do a shallow copy. - if (len == 0) - return varargout; - else - { - int i = 0; - int k = 0; - int num_ignored = ignored_outputs.numel (); - int ignored = num_ignored > 0 ? ignored_outputs(k) - 1 : -1; - - if (nargout <= len) - { - int nout = nargout > 0 ? nargout : 1; - octave_value_list retval (nout); - - for (tree_decl_elt *elt : *ret_list) + std::string arg0 = argv[0]; + + if (arg0 == "on") + m_echo = ECHO_SCRIPTS; + else if (arg0 == "off") + m_echo = ECHO_OFF; + else { - if (nargout == 0 && ! is_defined (elt->ident ())) - break; - - if (ignored >= 0 && i == ignored) + std::string file = fcn_file_in_path (arg0); + file = sys::env::make_absolute (file); + + if (file.empty ()) + error ("echo: no such file %s", arg0.c_str ()); + + if (m_echo & ECHO_ALL) { - i++; - k++; - ignored = k < num_ignored ? ignored_outputs(k) - 1 : -1; + // Echo is enabled for all functions, so turn it off + // for this one. + + m_echo_files[file] = false; } else - retval(i++) = evaluate (elt); - - if (i == nout) - break; - } - - return retval; - } - else - { - octave_value_list retval (len + vlen); - - for (tree_decl_elt *elt : *ret_list) - { - if (ignored >= 0 && i == ignored) { - i++; - k++; - ignored = k < num_ignored ? ignored_outputs(k) - 1 : -1; - } - else - retval(i++) = evaluate (elt); - } - - for (octave_idx_type j = 0; j < vlen; j++) - retval(i++) = varargout(j); - - return retval; - } - } -} - -bool -tree_evaluator::eval_decl_elt (tree_decl_elt *elt) -{ - bool retval = false; - - tree_identifier *id = elt->ident (); - tree_expression *expr = elt->expression (); - - if (id && expr) - { - octave_lvalue ult = id->lvalue (*this); - - octave_value init_val = expr->evaluate (*this); - - ult.assign (octave_value::op_asn_eq, init_val); - - retval = true; - } - - return retval; -} - -bool -tree_evaluator::switch_case_label_matches (tree_switch_case *expr, - const octave_value& val) -{ - tree_expression *label = expr->case_label (); - - octave_value label_value = label->evaluate (*this); - - if (label_value.is_defined ()) - { - if (label_value.iscell ()) - { - Cell cell (label_value.cell_value ()); - - for (octave_idx_type i = 0; i < cell.rows (); i++) - { - for (octave_idx_type j = 0; j < cell.columns (); j++) - { - bool match = val.is_equal (cell(i, j)); - - if (match) - return true; + // Echo may be enabled for specific functions. + + auto p = m_echo_files.find (file); + + if (p == m_echo_files.end ()) + { + // Not this one, so enable it. + + m_echo |= ECHO_FUNCTIONS; + m_echo_files[file] = true; + } + else + { + // This one is already in the list. Flip the + // status for it. + + p->second = ! p->second; + } } } } - else - return val.is_equal (label_value); - } - - return false; -} - -void tree_evaluator::push_stack_frame (const symbol_scope& scope) -{ - m_call_stack.push (scope); -} - -void tree_evaluator::push_stack_frame (octave_user_function *fcn, - const std::shared_ptr& closure_frames) -{ - m_call_stack.push (fcn, closure_frames); -} - -void tree_evaluator::push_stack_frame (octave_user_function *fcn, - const stack_frame::local_vars_map& local_vars, - const std::shared_ptr& closure_frames) -{ - m_call_stack.push (fcn, local_vars, closure_frames); -} - -void tree_evaluator::push_stack_frame (octave_user_script *script) -{ - m_call_stack.push (script); -} - -void tree_evaluator::push_stack_frame (octave_function *fcn) -{ - m_call_stack.push (fcn); -} - -void tree_evaluator::pop_stack_frame (void) -{ - m_call_stack.pop (); -} - -int tree_evaluator::current_line (void) const -{ - return m_call_stack.current_line (); -} - -int tree_evaluator::current_column (void) const -{ - return m_call_stack.current_column (); -} - -int tree_evaluator::debug_user_code_line (void) const -{ - return m_call_stack.debug_user_code_line (); -} - -int tree_evaluator::debug_user_code_column (void) const -{ - return m_call_stack.debug_user_code_column (); -} - -void tree_evaluator::debug_where (std::ostream& os) const -{ - std::shared_ptr frm = m_call_stack.current_user_frame (); - - frm->display_stopped_in_message (os); -} - -octave_user_code *tree_evaluator::current_user_code (void) const -{ - return m_call_stack.current_user_code (); -} - -unwind_protect *tree_evaluator::curr_fcn_unwind_protect_frame (void) -{ - return m_call_stack.curr_fcn_unwind_protect_frame (); -} - -octave_user_code *tree_evaluator::debug_user_code (void) const -{ - return m_call_stack.debug_user_code (); -} - -octave_function *tree_evaluator::current_function (bool skip_first) const -{ - return m_call_stack.current_function (skip_first); -} - -octave_function *tree_evaluator::caller_function (void) const -{ - return m_call_stack.current_function (true); -} - -bool tree_evaluator::goto_frame (std::size_t n, bool verbose) -{ - return m_call_stack.goto_frame (n, verbose); -} - -void tree_evaluator::goto_caller_frame (void) -{ - m_call_stack.goto_caller_frame (); -} - -void tree_evaluator::goto_base_frame (void) -{ - m_call_stack.goto_base_frame (); -} - -void tree_evaluator::restore_frame (std::size_t n) -{ - return m_call_stack.restore_frame (n); -} - -std::string tree_evaluator::get_dispatch_class (void) const -{ - return m_call_stack.get_dispatch_class (); -} - -void tree_evaluator::set_dispatch_class (const std::string& class_name) -{ - m_call_stack.set_dispatch_class (class_name); -} - -bool -tree_evaluator::is_class_method_executing (std::string& dclass) const -{ - return m_call_stack.is_class_method_executing (dclass); -} - -bool -tree_evaluator::is_class_constructor_executing (std::string& dclass) const -{ - return m_call_stack.is_class_constructor_executing (dclass); -} - -std::list> - tree_evaluator::backtrace_frames (octave_idx_type& curr_user_frame) const -{ - return m_call_stack.backtrace_frames (curr_user_frame); -} - -std::list> - tree_evaluator::backtrace_frames (void) const -{ - return m_call_stack.backtrace_frames (); -} - -std::list -tree_evaluator::backtrace_info (octave_idx_type& curr_user_frame, - bool print_subfn) const -{ - return m_call_stack.backtrace_info (curr_user_frame, print_subfn); -} - -std::list tree_evaluator::backtrace_info (void) const -{ - return m_call_stack.backtrace_info (); -} - -octave_map -tree_evaluator::backtrace (octave_idx_type& curr_user_frame, - bool print_subfn) const -{ - return m_call_stack.backtrace (curr_user_frame, print_subfn); -} - -octave_map tree_evaluator::backtrace (void) const -{ - return m_call_stack.backtrace (); -} - -octave_map tree_evaluator::empty_backtrace (void) const -{ - return m_call_stack.empty_backtrace (); -} - -std::string tree_evaluator::backtrace_message (void) const -{ - std::list frames = backtrace_info (); - - std::ostringstream buf; - - for (const auto& frm : frames) - { - buf << " " << frm.fcn_name (); - - int line = frm.line (); - - if (line > 0) + break; + + case 2: { - buf << " at line " << line; - - int column = frm.column (); - - if (column > 0) - buf << " column " << column; - - buf << "\n"; - } - } - - return buf.str (); -} - -void tree_evaluator::push_dummy_scope (const std::string& name) -{ - symbol_scope dummy_scope (name + "$dummy"); - - m_call_stack.push (dummy_scope); -} - -void tree_evaluator::pop_scope (void) -{ - m_call_stack.pop (); -} - -symbol_scope tree_evaluator::get_top_scope (void) const -{ - return m_call_stack.top_scope (); -} - -symbol_scope tree_evaluator::get_current_scope (void) const -{ - return m_call_stack.current_scope (); -} - -void tree_evaluator::mlock (bool skip_first) const -{ - octave_function *fcn = m_call_stack.current_function (skip_first); - - if (! fcn) - error ("mlock: invalid use outside a function"); - - if (fcn->is_builtin_function ()) - { - warning ("mlock: locking built-in function has no effect"); - return; - } - - fcn->lock (); -} - -void tree_evaluator::munlock (bool skip_first) const -{ - octave_function *fcn = m_call_stack.current_function (skip_first); - - if (! fcn) - error ("munlock: invalid use outside a function"); - - if (fcn->is_builtin_function ()) - { - warning ("munlock: unlocking built-in function has no effect"); - return; - } - - fcn->unlock (); -} - -bool tree_evaluator::mislocked (bool skip_first) const -{ - octave_function *fcn = m_call_stack.current_function (skip_first); - - if (! fcn) - error ("mislocked: invalid use outside a function"); - - return fcn->islocked (); -} - -octave_value -tree_evaluator::max_stack_depth (const octave_value_list& args, int nargout) -{ - return m_call_stack.max_stack_depth (args, nargout); -} - -void tree_evaluator::display_call_stack (void) const -{ - m_call_stack.display (); -} - -octave_value tree_evaluator::find (const std::string& name) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - octave_value val = frame->varval (name); - - if (val.is_defined ()) - return val; - - // Subfunction. I think it only makes sense to check for - // subfunctions if we are currently executing a function defined - // from a .m file. - - octave_value fcn = frame->find_subfunction (name); - - if (fcn.is_defined ()) - return fcn; - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - return symtab.fcn_table_find (name, ovl ()); -} - -void tree_evaluator::clear_objects (void) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - frame->clear_objects (); -} - -void tree_evaluator::clear_variable (const std::string& name) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - frame->clear_variable (name); -} - -void tree_evaluator::clear_variable_pattern (const std::string& pattern) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - frame->clear_variable_pattern (pattern); -} - -void tree_evaluator::clear_variable_regexp (const std::string& pattern) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - frame->clear_variable_regexp (pattern); -} - -void tree_evaluator::clear_variables (void) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - frame->clear_variables (); -} - -void tree_evaluator::clear_global_variable (const std::string& name) -{ - m_call_stack.clear_global_variable (name); -} - -void -tree_evaluator::clear_global_variable_pattern (const std::string& pattern) -{ - m_call_stack.clear_global_variable_pattern (pattern); -} - -void tree_evaluator::clear_global_variable_regexp(const std::string& pattern) -{ - m_call_stack.clear_global_variable_regexp (pattern); -} - -void tree_evaluator::clear_global_variables (void) -{ - m_call_stack.clear_global_variables (); -} - -void tree_evaluator::clear_all (bool force) -{ - // FIXME: should this also clear objects? - - clear_variables (); - clear_global_variables (); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - symtab.clear_functions (force); -} - -void tree_evaluator::clear_symbol (const std::string& name) -{ - // FIXME: are we supposed to do both here? - - clear_variable (name); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - symtab.clear_function (name); -} - -void tree_evaluator::clear_symbol_pattern (const std::string& pattern) -{ - // FIXME: are we supposed to do both here? - - clear_variable_pattern (pattern); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - symtab.clear_function_pattern (pattern); -} - -void tree_evaluator::clear_symbol_regexp (const std::string& pattern) -{ - // FIXME: are we supposed to do both here? - - clear_variable_regexp (pattern); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - symtab.clear_function_regexp (pattern); -} - -std::list tree_evaluator::global_variable_names (void) const -{ - return m_call_stack.global_variable_names (); -} - -std::list tree_evaluator::top_level_variable_names (void) const -{ - return m_call_stack.top_level_variable_names (); -} - -std::list tree_evaluator::variable_names (void) const -{ - return m_call_stack.variable_names (); -} - -// Return a pointer to the user-defined function FNAME. If FNAME is empty, -// search backward for the first user-defined function in the -// current call stack. - -octave_user_code * -tree_evaluator::get_user_code (const std::string& fname, - const std::string& class_name) -{ - octave_user_code *user_code = nullptr; - - if (fname.empty ()) - user_code = m_call_stack.debug_user_code (); - else - { - std::string name = fname; - - if (sys::file_ops::dir_sep_char () != '/' && name[0] == '@') - { - auto beg = name.begin () + 2; // never have @/method - auto end = name.end () - 1; // never have trailing '/' - std::replace (beg, end, '/', sys::file_ops::dir_sep_char ()); - } - - std::size_t name_len = name.length (); - - if (name_len > 2 && name.substr (name_len-2) == ".m") - name = name.substr (0, name_len-2); - - if (name.empty ()) - return nullptr; - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - octave_value fcn; - std::size_t p2 = std::string::npos; - - if (name[0] == '@') - { - std::size_t p1 = name.find (sys::file_ops::dir_sep_char (), 1); - - if (p1 == std::string::npos) - return nullptr; - - std::string dispatch_type = name.substr (1, p1-1); - - p2 = name.find ('>', p1); - - std::string method = name.substr (p1+1, p2-1); - - fcn = symtab.find_method (method, dispatch_type); - } - else if (! class_name.empty ()) - { - cdef_manager& cdm = m_interpreter.get_cdef_manager (); - - fcn = cdm.find_method (class_name, name); - - // If there is no classdef method, then try legacy classes. - if (fcn.is_undefined ()) - fcn = symtab.find_method (name, class_name); - } - else - { - p2 = name.find ('>'); - - std::string main_fcn = name.substr (0, p2); - - fcn = symtab.find_function (main_fcn); - } - - // List of function names sub1>sub2>... - std::string subfuns; - - if (p2 != std::string::npos) - subfuns = name.substr (p2+1); - - if (fcn.is_defined () && fcn.is_user_code ()) - user_code = fcn.user_code_value (); - - if (! user_code || subfuns.empty ()) - return user_code; - - fcn = user_code->find_subfunction (subfuns); - - if (fcn.is_undefined ()) - return nullptr; - - user_code = fcn.user_code_value (); - } - - return user_code; -} - -std::string -tree_evaluator::current_function_name (bool skip_first) const -{ - octave_function *curfcn = m_call_stack.current_function (skip_first); - - if (curfcn) - return curfcn->name (); - - return ""; -} - -bool -tree_evaluator::in_user_code (void) const -{ - return m_call_stack.current_user_code () != nullptr; -} - -void -tree_evaluator::visit_decl_command (tree_decl_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - // FIXME: tree_decl_init_list is not derived from tree, so should it - // really have an accept method? - - tree_decl_init_list *init_list = cmd.initializer_list (); - - if (init_list) - init_list->accept (*this); -} - -void -tree_evaluator::visit_decl_elt (tree_decl_elt& elt) -{ - tree_identifier *id = elt.ident (); - - if (id) - { - if (elt.is_global ()) - m_call_stack.make_global (id->symbol ()); - else if (elt.is_persistent ()) - m_call_stack.make_persistent (id->symbol ()); - else - error ("declaration list element not global or persistent"); - - octave_lvalue ult = id->lvalue (*this); - - if (ult.is_undefined ()) - { - tree_expression *expr = elt.expression (); - - octave_value init_val; - - if (expr) - init_val = expr->evaluate (*this); - else - init_val = Matrix (); - - ult.assign (octave_value::op_asn_eq, init_val); - } - } -} - -template -void -tree_evaluator::execute_range_loop (const range& rng, int line, - octave_lvalue& ult, - tree_statement_list *loop_body) -{ - octave_idx_type steps = rng.numel (); - - if (math::isinf (rng.limit ())) - warning_with_id ("Octave:infinite-loop", - "FOR loop limit is infinite, will stop after %" - OCTAVE_IDX_TYPE_FORMAT " steps", steps); - - for (octave_idx_type i = 0; i < steps; i++) - { - if (m_echo_state) - m_echo_file_pos = line; - - octave_value val (rng.elem (i)); - - ult.assign (octave_value::op_asn_eq, val); - - if (loop_body) - loop_body->accept (*this); - - if (quit_loop_now ()) - break; - } -} - -void -tree_evaluator::visit_simple_for_command (tree_simple_for_command& cmd) -{ - int line = cmd.line (); - if (line < 0) - line = 1; - - if (m_echo_state) - { - echo_code (line); - line++; - } - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - // FIXME: need to handle PARFOR loops here using cmd.in_parallel () - // and cmd.maxproc_expr (); - - unwind_protect_var upv (m_in_loop_command, true); - - tree_expression *expr = cmd.control_expr (); - - octave_value rhs = expr->evaluate (*this); - - if (rhs.is_undefined ()) - return; - - tree_expression *lhs = cmd.left_hand_side (); - - octave_lvalue ult = lhs->lvalue (*this); - - tree_statement_list *loop_body = cmd.body (); - - if (rhs.is_range ()) - { - // FIXME: is there a better way to dispatch here? - - if (rhs.is_double_type ()) - { - execute_range_loop (rhs.range_value (), line, ult, loop_body); - return; - } - - // For now, disable all but range. - -#if 0 - if (rhs.is_int64_type ()) - { - execute_range_loop (rhs.int64_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_uint64_type ()) - { - execute_range_loop (rhs.uint64_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_int32_type ()) - { - execute_range_loop (rhs.int32_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_uint32_type ()) - { - execute_range_loop (rhs.uint32_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_int16_type ()) - { - execute_range_loop (rhs.int16_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_uint16_type ()) - { - execute_range_loop (rhs.uint16_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_int8_type ()) - { - execute_range_loop (rhs.int8_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_uint8_type ()) - { - execute_range_loop (rhs.uint8_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_single_type ()) - { - execute_range_loop (rhs.float_range_value (), line, ult, loop_body); - return; - } -#endif - } - - if (rhs.is_scalar_type ()) - { - if (m_echo_state) - m_echo_file_pos = line; - - ult.assign (octave_value::op_asn_eq, rhs); - - if (loop_body) - loop_body->accept (*this); - - // Maybe decrement break and continue states. - quit_loop_now (); - - return; - } - - // Also handle any range types not explicitly handled above, though - // not as efficiently as the specialized code above. - - if (rhs.is_range () || rhs.is_matrix_type () || rhs.iscell () - || rhs.is_string () || rhs.isstruct ()) - { - // A matrix or cell is reshaped to 2 dimensions and iterated by - // columns. - - dim_vector dv = rhs.dims ().redim (2); - - octave_idx_type nrows = dv(0); - octave_idx_type steps = dv(1); - - octave_value arg = rhs; - if (rhs.ndims () > 2) - arg = arg.reshape (dv); - - if (nrows > 0 && steps > 0) - { - octave_value_list idx; - octave_idx_type iidx; - - // for row vectors, use single index to speed things up. - if (nrows == 1) + std::string arg0 = argv[0]; + std::string arg1 = argv[1]; + + if (arg1 == "on" || arg1 == "off") + std::swap (arg0, arg1); + + if (arg0 == "on") { - idx.resize (1); - iidx = 0; + if (arg1 == "all") + { + m_echo = (ECHO_SCRIPTS | ECHO_FUNCTIONS | ECHO_ALL); + m_echo_files.clear (); + } + else + { + std::string file = fcn_file_in_path (arg1); + file = sys::env::make_absolute (file); + + if (file.empty ()) + error ("echo: no such file %s", arg1.c_str ()); + + m_echo |= ECHO_FUNCTIONS; + m_echo_files[file] = true; + } + } + else if (arg0 == "off") + { + if (arg1 == "all") + { + m_echo = ECHO_OFF; + m_echo_files.clear (); + } + else + { + std::string file = fcn_file_in_path (arg1); + file = sys::env::make_absolute (file); + + if (file.empty ()) + error ("echo: no such file %s", arg1.c_str ()); + + m_echo_files[file] = false; + } } else - { - idx.resize (2); - idx(0) = octave_value::magic_colon_t; - iidx = 1; - } - - for (octave_idx_type i = 1; i <= steps; i++) - { - if (m_echo_state) - m_echo_file_pos = line; - - // index_op expects one-based indices. - idx(iidx) = i; - octave_value val = arg.index_op (idx); - - ult.assign (octave_value::op_asn_eq, val); - - if (loop_body) - loop_body->accept (*this); - - if (quit_loop_now ()) - break; - } - } - else - { - // Handle empty cases, while still assigning to loop var. - ult.assign (octave_value::op_asn_eq, arg); - } - - return; - } - - error ("invalid type in for loop expression near line %d, column %d", - cmd.line (), cmd.column ()); -} - -void -tree_evaluator::visit_complex_for_command (tree_complex_for_command& cmd) -{ - int line = cmd.line (); - if (line < 0) - line = 1; - - if (m_echo_state) - { - echo_code (line); - line++; - } - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - unwind_protect_var upv (m_in_loop_command, true); - - tree_expression *expr = cmd.control_expr (); - - octave_value rhs = expr->evaluate (*this); - - if (rhs.is_undefined ()) - return; - - if (! rhs.isstruct ()) - error ("in statement 'for [X, Y] = VAL', VAL must be a structure"); - - // Cycle through structure elements. First element of id_list - // is set to value and the second is set to the name of the - // structure element. - - tree_argument_list *lhs = cmd.left_hand_side (); - - auto p = lhs->begin (); - - tree_expression *elt = *p++; - - octave_lvalue val_ref = elt->lvalue (*this); - - elt = *p; - - octave_lvalue key_ref = elt->lvalue (*this); - - const octave_map tmp_val = rhs.map_value (); - - tree_statement_list *loop_body = cmd.body (); - - string_vector keys = tmp_val.keys (); - - octave_idx_type nel = keys.numel (); - - for (octave_idx_type i = 0; i < nel; i++) - { - if (m_echo_state) - m_echo_file_pos = line; - - std::string key = keys[i]; - - const Cell val_lst = tmp_val.contents (key); - - octave_idx_type n = val_lst.numel (); - - octave_value val = (n == 1) ? val_lst(0) : octave_value (val_lst); - - val_ref.assign (octave_value::op_asn_eq, val); - key_ref.assign (octave_value::op_asn_eq, key); - - if (loop_body) - loop_body->accept (*this); - - if (quit_loop_now ()) - break; - } -} - -void tree_evaluator::visit_spmd_command (tree_spmd_command& cmd) -{ - // For now, we just execute the commands serially. - - tree_statement_list *body = cmd.body (); - - if (body) - body->accept (*this); -} - -octave_value -tree_evaluator::evaluate_anon_fcn_handle (tree_anon_fcn_handle& afh) -{ - // FIXME: should CMD_LIST be limited to a single expression? - // I think that is what Matlab does. - - symbol_scope new_scope; - symbol_scope scope = afh.scope (); - if (scope) - new_scope = scope.dup (); - - tree_parameter_list *param_list = afh.parameter_list (); - tree_parameter_list *param_list_dup - = param_list ? param_list->dup (new_scope) : nullptr; - - tree_parameter_list *ret_list = nullptr; - - tree_statement_list *stmt_list = nullptr; - - symbol_scope parent_scope = get_current_scope (); - - new_scope.set_parent (parent_scope); - new_scope.set_primary_parent (parent_scope); - - tree_expression *expr = afh.expression (); - if (expr) - { - tree_expression *expr_dup = expr->dup (new_scope); - tree_statement *stmt = new tree_statement (expr_dup, nullptr); - stmt_list = new tree_statement_list (stmt); - } - - tree_anon_scopes anon_fcn_ctx (afh); - - std::set free_vars = anon_fcn_ctx.free_variables (); - - stack_frame::local_vars_map local_vars; - - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - for (auto& name : free_vars) - { - octave_value val = frame->varval (name); - - if (val.is_defined ()) - local_vars[name] = val; - } - - octave_user_function *af - = new octave_user_function (new_scope, param_list_dup, ret_list, - stmt_list); - - octave_function *curr_fcn = m_call_stack.current_function (); - - bool is_nested = false; - - if (curr_fcn) - { - // FIXME: maybe it would be better to just stash curr_fcn - // instead of individual bits of info about it? - - // An anonymous function defined inside another nested function - // or parent of a nested function also behaves like a nested - // function. - - if (curr_fcn->is_parent_function () || curr_fcn->is_nested_function ()) - { - is_nested = true; - af->mark_as_nested_function (); - new_scope.set_nesting_depth (parent_scope.nesting_depth () + 1); - } - - af->stash_dir_name (curr_fcn->dir_name ()); - - new_scope.cache_fcn_file_name (curr_fcn->fcn_file_name ()); - new_scope.cache_dir_name (curr_fcn->dir_name ()); - - // The following is needed so that class method dispatch works - // properly for anonymous functions that wrap class methods. - - if (curr_fcn->is_class_method () || curr_fcn->is_class_constructor ()) - af->stash_dispatch_class (curr_fcn->dispatch_class ()); - - af->stash_fcn_file_name (curr_fcn->fcn_file_name ()); - } - - af->mark_as_anonymous_function (); - - octave_value ov_fcn (af); - - return (is_nested - ? octave_value (new octave_fcn_handle (ov_fcn, local_vars, frame)) - : octave_value (new octave_fcn_handle (ov_fcn, local_vars))); -} - -octave_value_list -tree_evaluator::execute_builtin_function (octave_builtin& builtin_function, - int nargout, - const octave_value_list& args) -{ - octave_value_list retval; - - if (args.has_magic_colon ()) - error ("invalid use of colon in function argument list"); - - profiler::enter block (m_profiler, builtin_function); - - octave_builtin::fcn fcn = builtin_function.function (); - - if (fcn) - retval = (*fcn) (args, nargout); - else - { - octave_builtin::meth meth = builtin_function.method (); - - retval = (*meth) (m_interpreter, args, nargout); - } - - // Do not allow null values to be returned from functions. - // FIXME: perhaps true builtins should be allowed? - - retval.make_storable_values (); - - // Fix the case of a single undefined value. - // This happens when a compiled function uses - // - // octave_value retval; - // - // instead of - // - // octave_value_list retval; - // - // the idiom is very common, so we solve that here. - - if (retval.length () == 1 && retval.xelem (0).is_undefined ()) - retval.clear (); - - return retval; -} - -octave_value_list -tree_evaluator::execute_mex_function (octave_mex_function& mex_function, - int nargout, - const octave_value_list& args) -{ - octave_value_list retval; - - if (args.has_magic_colon ()) - error ("invalid use of colon in function argument list"); - - profiler::enter block (m_profiler, mex_function); - - retval = call_mex (mex_function, args, nargout); - - return retval; -} - -octave_value_list -tree_evaluator::execute_user_script (octave_user_script& user_script, - int nargout, - const octave_value_list& args) -{ - octave_value_list retval; - - std::string file_name = user_script.fcn_file_name (); - - if (args.length () != 0 || nargout != 0) - error ("invalid call to script %s", file_name.c_str ()); - - tree_statement_list *cmd_list = user_script.body (); - - if (! cmd_list) - return retval; - - // FIXME: Maybe this check belongs in the places where we push a new - // stack frame? Or in the call_stack push method itself? - - if (m_call_stack.size () >= static_cast (m_max_recursion_depth)) - error ("max_recursion_depth exceeded"); - - unwind_protect_var upv (m_statement_context, SC_SCRIPT); - - profiler::enter block (m_profiler, user_script); - - if (echo ()) - push_echo_state (tree_evaluator::ECHO_SCRIPTS, file_name); - - // FIXME: Should we be using tree_evaluator::eval here? - - cmd_list->accept (*this); - - if (m_returning) - m_returning = 0; - - if (m_breaking) - m_breaking--; - - return retval; -} - -void -tree_evaluator::visit_octave_user_script (octave_user_script&) -{ - // ?? - panic_impossible (); -} - -octave_value_list -tree_evaluator::execute_user_function (octave_user_function& user_function, - int nargout, - const octave_value_list& xargs) -{ - octave_value_list retval; - - // If this function is a classdef constructor, extract the first input - // argument, which must be the partially constructed object instance. - - octave_value_list args (xargs); - octave_value_list ret_args; - - int nargin = args.length (); - - if (user_function.is_classdef_constructor ()) - { - if (nargin > 0) - { - ret_args = args.slice (0, 1, true); - --nargin; - args = args.slice (1, nargin, true); - } - else - panic_impossible (); - } - - // FIXME: this probably shouldn't be a double-precision matrix. - Matrix ignored_outputs = ignored_fcn_outputs (); - - tree_parameter_list *param_list = user_function.parameter_list (); - - bool takes_varargs = false; - int max_inputs = 0; - - if (param_list) - { - takes_varargs = param_list->takes_varargs (); - max_inputs = param_list->length (); - } - - if (! takes_varargs && nargin > max_inputs) - { - std::string name = user_function.name (); - - if (name.empty ()) - name = "@"; - - error_with_id ("Octave:invalid-fun-call", - "%s: function called with too many inputs", - name.c_str ()); - } - - define_parameter_list_from_arg_vector (param_list, args); - - tree_parameter_list *ret_list = user_function.return_list (); - - if (ret_list && ! ret_list->takes_varargs ()) - { - int max_outputs = ret_list->length (); - - if (nargout > max_outputs) - { - std::string name = user_function.name (); - - error_with_id ("Octave:invalid-fun-call", - "%s: function called with too many outputs", - name.c_str ()); - } - } - - bind_auto_fcn_vars (xargs.name_tags (), ignored_outputs, nargin, - nargout, user_function.takes_varargs (), - user_function.all_va_args (args)); - - // For classdef constructor, pre-populate the output arguments - // with the pre-initialized object instance, extracted above. - - if (user_function.is_classdef_constructor ()) - { - if (! ret_list) - error ("%s: invalid classdef constructor, no output argument defined", - user_function.dispatch_class ().c_str ()); - - define_parameter_list_from_arg_vector (ret_list, ret_args); - } - - // FIXME: Maybe this check belongs in the places where we push a - // new stack frame? Or in the call_stack push method itself? - - if (m_call_stack.size () >= static_cast (m_max_recursion_depth)) - error ("max_recursion_depth exceeded"); - - unwind_action act2 ([&user_function] () - { - user_function.restore_warning_states (); - }); - - // Evaluate the commands that make up the function. - - unwind_protect_var upv (m_statement_context, SC_FUNCTION); - - tree_statement_list *cmd_list = user_function.body (); - - if (cmd_list) - { - profiler::enter - block (m_profiler, user_function); - - if (echo ()) - push_echo_state (tree_evaluator::ECHO_FUNCTIONS, - user_function.fcn_file_name ()); - - if (user_function.is_special_expr ()) - { - panic_if (cmd_list->length () != 1); - - tree_statement *stmt = cmd_list->front (); - - tree_expression *expr = stmt->expression (); - - if (expr) - { - m_call_stack.set_location (stmt->line (), stmt->column ()); - - retval = expr->evaluate_n (*this, nargout); - } - } - else - cmd_list->accept (*this); - - if (m_returning) - m_returning = 0; - - if (m_breaking) - m_breaking--; - } - - // Copy return values out. - - if (ret_list && ! user_function.is_special_expr ()) - { - Cell varargout; - - if (ret_list->takes_varargs ()) - { - octave_value varargout_varval = varval ("varargout"); - - if (varargout_varval.is_defined ()) - varargout = varargout_varval.xcell_value ("varargout must be a cell array object"); - } - - retval = convert_return_list_to_const_vector (ret_list, nargout, - ignored_outputs, - varargout); - } - - return retval; -} - -void -tree_evaluator::visit_octave_user_function (octave_user_function&) -{ - // ?? - panic_impossible (); -} - -void -tree_evaluator::visit_octave_user_function_header (octave_user_function&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_octave_user_function_trailer (octave_user_function&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_function_def (tree_function_def& cmd) -{ - octave_value fcn = cmd.function (); - - octave_function *f = fcn.function_value (); - - if (f) - { - std::string nm = f->name (); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - symtab.install_cmdline_function (nm, fcn); - - // Make sure that any variable with the same name as the new - // function is cleared. - - assign (nm); - } -} - -void -tree_evaluator::visit_identifier (tree_identifier&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_if_clause (tree_if_clause&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_if_command (tree_if_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - // FIXME: tree_if_command_list is not derived from tree, so should it - // really have an accept method? - - tree_if_command_list *lst = cmd.cmd_list (); - - if (lst) - lst->accept (*this); -} - -void -tree_evaluator::visit_if_command_list (tree_if_command_list& lst) -{ - for (tree_if_clause *tic : lst) - { - tree_expression *expr = tic->condition (); - - if (! (in_debug_repl () - && m_call_stack.current_frame () == m_debug_frame)) - m_call_stack.set_location (tic->line (), tic->column ()); - - if (m_debug_mode && ! tic->is_else_clause ()) - do_breakpoint (tic->is_active_breakpoint (*this)); - - if (tic->is_else_clause () || is_logically_true (expr, "if")) - { - tree_statement_list *stmt_lst = tic->commands (); - - if (stmt_lst) - stmt_lst->accept (*this); - - break; - } - } -} - -void -tree_evaluator::visit_index_expression (tree_index_expression&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_matrix (tree_matrix&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_cell (tree_cell&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_multi_assignment (tree_multi_assignment&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_no_op_command (tree_no_op_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - if (m_debug_mode && cmd.is_end_of_fcn_or_script ()) - do_breakpoint (cmd.is_active_breakpoint (*this), true); -} - -void -tree_evaluator::visit_constant (tree_constant&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_fcn_handle (tree_fcn_handle&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_parameter_list (tree_parameter_list&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_postfix_expression (tree_postfix_expression&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_prefix_expression (tree_prefix_expression&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_return_command (tree_return_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - // Act like dbcont. - - if (in_debug_repl () && m_call_stack.current_frame () == m_debug_frame) - dbcont (); - else if (m_statement_context == SC_FUNCTION - || m_statement_context == SC_SCRIPT - || m_in_loop_command) - m_returning = 1; -} - -void -tree_evaluator::visit_simple_assignment (tree_simple_assignment&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_statement (tree_statement& stmt) -{ - tree_command *cmd = stmt.command (); - tree_expression *expr = stmt.expression (); - - if (cmd || expr) - { - if (! (in_debug_repl () - && m_call_stack.current_frame () == m_debug_frame)) - m_call_stack.set_location (stmt.line (), stmt.column ()); - - try - { - if (cmd) - { - unwind_protect_var *> - upv (m_lvalue_list, nullptr); - - cmd->accept (*this); - } - else - { - if (m_echo_state) - { - int line = stmt.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - if (m_debug_mode) - do_breakpoint (expr->is_active_breakpoint (*this)); - - // FIXME: maybe all of this should be packaged in - // one virtual function that returns a flag saying whether - // or not the expression will take care of binding ans and - // printing the result. - - // FIXME: it seems that we should just have to - // evaluate the expression and that should take care of - // everything, binding ans as necessary? - - octave_value tmp_result = expr->evaluate (*this, 0); - - if (tmp_result.is_defined ()) - { - bool do_bind_ans = false; - - if (expr->is_identifier ()) - do_bind_ans = ! is_variable (expr); - else - do_bind_ans = ! expr->is_assignment_expression (); - - if (do_bind_ans) - bind_ans (tmp_result, expr->print_result () - && statement_printing_enabled ()); - } - } - } - catch (const std::bad_alloc&) - { - // FIXME: We want to use error_with_id here so that give users - // control over this error message but error_with_id will - // require some memory allocations. Is there anything we can - // do to make those more likely to succeed? - - error_with_id ("Octave:bad-alloc", - "out of memory or dimension too large for Octave's index type"); - } - catch (const interrupt_exception&) - { - // If we are debugging, then continue with next statement. - // Otherwise, jump out of here. - - if (m_debug_mode) - m_interpreter.recover_from_exception (); - else - throw; - } - catch (const execution_exception& ee) - { - error_system& es = m_interpreter.get_error_system (); - - if ((m_interpreter.interactive () - || application::forced_interactive ()) - && ((es.debug_on_error () - && m_bp_table.debug_on_err (es.last_error_id ())) - || (es.debug_on_caught () - && m_bp_table.debug_on_caught (es.last_error_id ()))) - && in_user_code ()) - { - es.save_exception (ee); - es.display_exception (ee); - - enter_debugger (); - - // It doesn't make sense to continue execution after an - // error occurs so force the debugger to quit all debug - // levels and return the the top prompt. - - throw quit_debug_exception (true); - } - else - throw; - } - } -} - -void -tree_evaluator::visit_statement_list (tree_statement_list& lst) -{ - // FIXME: commented out along with else clause below. - // static octave_value_list empty_list; - - auto p = lst.begin (); - - if (p != lst.end ()) - { - while (true) - { - tree_statement *elt = *p++; - - if (! elt) - error ("invalid statement found in statement list!"); - - octave_quit (); - - elt->accept (*this); - - if (m_breaking || m_continuing) - break; - - if (m_returning) - break; - - if (p == lst.end ()) - break; - else - { - // Clear previous values before next statement is - // evaluated so that we aren't holding an extra - // reference to a value that may be used next. For - // example, in code like this: - // - // X = rand (N); # refcount for X should be 1 - // # after this statement - // - // X(idx) = val; # no extra copy of X should be - // # needed, but we will be faked - // # out if retval is not cleared - // # between statements here - - // result_values = empty_list; - } + print_usage (); } - } -} - -void -tree_evaluator::visit_switch_case (tree_switch_case&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_switch_case_list (tree_switch_case_list&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_switch_command (tree_switch_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - tree_expression *expr = cmd.switch_value (); - - if (! expr) - error ("missing value in switch command near line %d, column %d", - cmd.line (), cmd.column ()); - - octave_value val = expr->evaluate (*this); - - tree_switch_case_list *lst = cmd.case_list (); - - if (lst) - { - for (tree_switch_case *t : *lst) - { - if (t->is_default_case () || switch_case_label_matches (t, val)) - { - tree_statement_list *stmt_lst = t->commands (); - - if (stmt_lst) - stmt_lst->accept (*this); - - break; - } - } - } -} - -void -tree_evaluator::visit_try_catch_command (tree_try_catch_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - bool execution_error = false; - octave_scalar_map err_map; - - tree_statement_list *try_code = cmd.body (); - - if (try_code) - { - // unwind frame before catch block - - unwind_protect frame; - - interpreter_try (frame); - - // The catch code is *not* added to unwind_protect stack; it - // doesn't need to be run on interrupts. - - try - { - try_code->accept (*this); - } - catch (const execution_exception& ee) - { - execution_error = true; - - error_system& es = m_interpreter.get_error_system (); - - es.save_exception (ee); - - err_map.assign ("message", es.last_error_message ()); - err_map.assign ("identifier", es.last_error_id ()); - err_map.assign ("stack", es.last_error_stack ()); - - m_interpreter.recover_from_exception (); - } - - // Actions attached to unwind_protect frame will run here, prior - // to executing the catch block. - } - - if (execution_error) - { - tree_statement_list *catch_code = cmd.cleanup (); - - if (catch_code) - { - tree_identifier *expr_id = cmd.identifier (); - - if (expr_id) - { - octave_lvalue ult = expr_id->lvalue (*this); - - ult.assign (octave_value::op_asn_eq, err_map); - } - - // perform actual "catch" block - catch_code->accept (*this); - } - } -} - -void -tree_evaluator::do_unwind_protect_cleanup_code (tree_statement_list *list) -{ - unwind_protect frame; - - frame.protect_var (octave_interrupt_state); - octave_interrupt_state = 0; - - // We want to preserve the last location info for possible - // backtracking. - - frame.add (&call_stack::set_line, &m_call_stack, - m_call_stack.current_line ()); - - frame.add (&call_stack::set_column, &m_call_stack, - m_call_stack.current_column ()); - - // Similarly, if we have seen a return or break statement, allow all - // the cleanup code to run before returning or handling the break. - // We don't have to worry about continue statements because they can - // only occur in loops. - - frame.protect_var (m_returning); - m_returning = 0; - - frame.protect_var (m_breaking); - m_breaking = 0; - - try - { - if (list) - list->accept (*this); - } - catch (const execution_exception& ee) - { - error_system& es = m_interpreter.get_error_system (); - - es.save_exception (ee); - m_interpreter.recover_from_exception (); - - if (m_breaking || m_returning) - frame.discard (2); - else - frame.run (2); - - frame.discard (2); - - throw; - } - - // The unwind_protects are popped off the stack in the reverse of - // the order they are pushed on. - - // FIXME: these statements say that if we see a break or - // return statement in the cleanup block, that we want to use the - // new value of the breaking or returning flag instead of restoring - // the previous value. Is that the right thing to do? I think so. - // Consider the case of - // - // function foo () - // unwind_protect - // fprintf (stderr, "1: this should always be executed\n"); - // break; - // fprintf (stderr, "1: this should never be executed\n"); - // unwind_protect_cleanup - // fprintf (stderr, "2: this should always be executed\n"); - // return; - // fprintf (stderr, "2: this should never be executed\n"); - // end_unwind_protect - // endfunction - // - // If we reset the value of the breaking flag, both the returning - // flag and the breaking flag will be set, and we shouldn't have - // both. So, use the most recent one. If there is no return or - // break in the cleanup block, the values should be reset to - // whatever they were when the cleanup block was entered. - - if (m_breaking || m_returning) - frame.discard (2); - else - frame.run (2); -} - -void -tree_evaluator::visit_unwind_protect_command (tree_unwind_protect_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - tree_statement_list *cleanup_code = cmd.cleanup (); - - tree_statement_list *unwind_protect_code = cmd.body (); - - if (unwind_protect_code) - { - try - { - unwind_protect_code->accept (*this); - } - catch (const execution_exception& ee) - { - error_system& es = m_interpreter.get_error_system (); - - // FIXME: Maybe we should be able to temporarily set the - // interpreter's exception handling state to something "safe" - // while the cleanup block runs instead of just resetting it - // here? - es.save_exception (ee); - m_interpreter.recover_from_exception (); - - // Run the cleanup code on exceptions, so that it is run even - // in case of interrupt or out-of-memory. - do_unwind_protect_cleanup_code (cleanup_code); - - // If an error occurs inside the cleanup code, a new - // exception will be thrown instead of the original. - throw; - } - catch (const interrupt_exception&) - { - // The comments above apply here as well. - m_interpreter.recover_from_exception (); - do_unwind_protect_cleanup_code (cleanup_code); - throw; - } - - // Also execute the unwind_protect_cleanump code if the - // unwind_protect block runs without error. - do_unwind_protect_cleanup_code (cleanup_code); - } -} - -void -tree_evaluator::visit_while_command (tree_while_command& cmd) -{ - int line = cmd.line (); - if (line < 0) - line = 1; - - if (m_echo_state) - { - echo_code (line); - line++; - } - - unwind_protect_var upv (m_in_loop_command, true); - - tree_expression *expr = cmd.condition (); - - if (! expr) - panic_impossible (); - - for (;;) - { - if (m_echo_state) - m_echo_file_pos = line; - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - if (is_logically_true (expr, "while")) - { - tree_statement_list *loop_body = cmd.body (); - - if (loop_body) - loop_body->accept (*this); - - if (quit_loop_now ()) - break; - } - else break; - } -} - -void -tree_evaluator::visit_do_until_command (tree_do_until_command& cmd) -{ - int line = cmd.line (); - if (line < 0) - line = 1; - - if (m_echo_state) - { - echo_code (line); - line++; - } - - unwind_protect_var upv (m_in_loop_command, true); - - tree_expression *expr = cmd.condition (); - - if (! expr) - panic_impossible (); - - for (;;) - { - if (m_echo_state) - m_echo_file_pos = line; - - tree_statement_list *loop_body = cmd.body (); - - if (loop_body) - loop_body->accept (*this); - - if (quit_loop_now ()) - break; - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - if (is_logically_true (expr, "do-until")) + + default: + print_usage (); break; - } -} - -void -tree_evaluator::visit_superclass_ref (tree_superclass_ref&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_metaclass_query (tree_metaclass_query&) -{ - panic_impossible (); -} - -void tree_evaluator::bind_ans (const octave_value& val, bool print) -{ - static std::string ans = "ans"; - - if (val.is_defined ()) - { - if (val.is_cs_list ()) - { - octave_value_list lst = val.list_value (); - - for (octave_idx_type i = 0; i < lst.length (); i++) - bind_ans (lst(i), print); - } - else - { - // FIXME: Maybe assign could also return the assigned value, - // just for convenience? - - assign (ans, val); - - if (print) - { - // Use varval instead of displaying VAL directly so that - // we get the right type and value for things like - // magic_int values that may mutate when stored. - - octave_value_list args = ovl (varval (ans)); - args.stash_name_tags (string_vector (ans)); - feval ("display", args); - } - } - } -} - -void -tree_evaluator::do_breakpoint (tree_statement& stmt) -{ - do_breakpoint (stmt.is_active_breakpoint (*this), - stmt.is_end_of_fcn_or_script ()); -} - -void -tree_evaluator::do_breakpoint (bool is_breakpoint, - bool is_end_of_fcn_or_script) -{ - bool break_on_this_statement = false; - - if (is_breakpoint) - break_on_this_statement = true; - else if (m_dbstep_flag > 0) - { - if (m_call_stack.current_frame () == m_debug_frame) - { - if (m_dbstep_flag == 1 || is_end_of_fcn_or_script) - { - // We get here if we are doing a "dbstep" or a "dbstep N" and - // the count has reached 1 so that we must stop and return to - // debug prompt. Alternatively, "dbstep N" has been used but - // the end of the frame has been reached so we stop at the last - // line and return to prompt. - - break_on_this_statement = true; - } - else - { - // Executing "dbstep N". Decrease N by one and continue. - - m_dbstep_flag--; - } - - } - else if (m_dbstep_flag == 1 - && m_call_stack.current_frame () < m_debug_frame) - { - // We stepped out from the end of a function. - - m_debug_frame = m_call_stack.current_frame (); - - break_on_this_statement = true; - } - } - else if (m_dbstep_flag == -1) - { - // We get here if we are doing a "dbstep in". - - break_on_this_statement = true; - - m_debug_frame = m_call_stack.current_frame (); - } - else if (m_dbstep_flag == -2) - { - // We get here if we are doing a "dbstep out". Check for end of - // function and whether the current frame is the same as the - // cached value because we want to step out from the frame where - // "dbstep out" was evaluated, not from any functions called from - // that frame. - - if (is_end_of_fcn_or_script - && m_call_stack.current_frame () == m_debug_frame) - m_dbstep_flag = -1; - } - - if (! break_on_this_statement) - break_on_this_statement = m_break_on_next_stmt; - - m_break_on_next_stmt = false; - - if (break_on_this_statement) - { - m_dbstep_flag = 0; - - enter_debugger (); - } -} - -bool -tree_evaluator::is_logically_true (tree_expression *expr, - const char *warn_for) -{ - bool expr_value = false; - - m_call_stack.set_location (expr->line (), expr->column ()); - - octave_value t1 = expr->evaluate (*this); - - if (t1.is_defined ()) - return t1.is_true (); - else - error ("%s: undefined value used in conditional expression", warn_for); - - return expr_value; -} - -octave_value -tree_evaluator::max_recursion_depth (const octave_value_list& args, - int nargout) -{ - return set_internal_variable (m_max_recursion_depth, args, nargout, - "max_recursion_depth", 0); -} - -symbol_info_list -tree_evaluator::glob_symbol_info (const std::string& pattern) const -{ - return m_call_stack.glob_symbol_info (pattern); -} - -symbol_info_list -tree_evaluator::regexp_symbol_info (const std::string& pattern) const -{ - return m_call_stack.regexp_symbol_info (pattern); -} - -symbol_info_list -tree_evaluator::get_symbol_info (void) -{ - return m_call_stack.get_symbol_info (); -} - -symbol_info_list -tree_evaluator::top_scope_symbol_info (void) const -{ - return m_call_stack.top_scope_symbol_info (); -} - -octave_map tree_evaluator::get_autoload_map (void) const -{ - Cell fcn_names (dim_vector (m_autoload_map.size (), 1)); - Cell file_names (dim_vector (m_autoload_map.size (), 1)); - - octave_idx_type i = 0; - for (const auto& fcn_fname : m_autoload_map) - { - fcn_names(i) = fcn_fname.first; - file_names(i) = fcn_fname.second; - - i++; - } - - octave_map m; - - m.assign ("function", fcn_names); - m.assign ("file", file_names); - - return m; -} - -std::string tree_evaluator::lookup_autoload (const std::string& nm) const -{ - std::string retval; - - auto p = m_autoload_map.find (nm); - - if (p != m_autoload_map.end ()) - { - load_path& lp = m_interpreter.get_load_path (); - - retval = lp.find_file (p->second); - } - - return retval; -} - -std::list tree_evaluator::autoloaded_functions (void) const -{ - std::list names; - - for (const auto& fcn_fname : m_autoload_map) - names.push_back (fcn_fname.first); - - return names; -} - -std::list -tree_evaluator::reverse_lookup_autoload (const std::string& nm) const -{ - std::list names; - - for (const auto& fcn_fname : m_autoload_map) - if (nm == fcn_fname.second) - names.push_back (fcn_fname.first); - - return names; -} - -void tree_evaluator::add_autoload (const std::string& fcn, - const std::string& nm) -{ - std::string file_name = check_autoload_file (nm); - - m_autoload_map[fcn] = file_name; -} - -void tree_evaluator::remove_autoload (const std::string& fcn, - const std::string& nm) -{ - check_autoload_file (nm); - - // Remove function from symbol table and autoload map. - symbol_table& symtab = m_interpreter.get_symbol_table (); - - symtab.clear_dld_function (fcn); - - m_autoload_map.erase (fcn); -} - -octave_value -tree_evaluator::whos_line_format (const octave_value_list& args, int nargout) -{ - return set_internal_variable (m_whos_line_format, args, nargout, - "whos_line_format"); -} - -octave_value -tree_evaluator::silent_functions (const octave_value_list& args, int nargout) -{ - return set_internal_variable (m_silent_functions, args, nargout, - "silent_functions"); -} - -octave_value -tree_evaluator::string_fill_char (const octave_value_list& args, int nargout) -{ - return set_internal_variable (m_string_fill_char, args, nargout, - "string_fill_char"); -} - -// Final step of processing an indexing error. Add the name of the -// variable being indexed, if any, then issue an error. (Will this also -// be needed by pt-lvalue, which calls subsref?) - -void tree_evaluator::final_index_error (index_exception& ie, - const tree_expression *expr) -{ - std::string extra_message; - - if (is_variable (expr)) - { - std::string var = expr->name (); - - ie.set_var (var); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - octave_value fcn = symtab.find_function (var); - - if (fcn.is_function ()) - { - octave_function *fp = fcn.function_value (); - - if (fp && fp->name () == var) - extra_message - = " (note: variable '" + var + "' shadows function)"; - } - } - - std::string msg = ie.message () + extra_message; - - error_with_id (ie.err_id (), "%s", msg.c_str ()); -} - -octave_value -tree_evaluator::do_who (int argc, const string_vector& argv, - bool return_list, bool verbose) -{ - return m_call_stack.do_who (argc, argv, return_list, verbose); -} - -octave_value_list -tree_evaluator::make_value_list (tree_argument_list *args, - const string_vector& arg_nm) -{ - octave_value_list retval; - - if (args) - { - unwind_protect_var *> - upv (m_lvalue_list, nullptr); - - int len = args->length (); - - unwind_protect_var upv2 (m_index_position); - unwind_protect_var upv3 (m_num_indices); - - m_num_indices = len; - - std::list arg_vals; - - int k = 0; - - for (auto elt : *args) - { - // FIXME: is it possible for elt to be invalid? - - if (! elt) - break; - - m_index_position = k++; - - octave_value tmp = elt->evaluate (*this); - - if (tmp.is_cs_list ()) - { - octave_value_list tmp_ovl = tmp.list_value (); - - for (octave_idx_type i = 0; i < tmp_ovl.length (); i++) - arg_vals.push_back (tmp_ovl(i)); - } - else if (tmp.is_defined ()) - arg_vals.push_back (tmp); - } - - retval = octave_value_list (arg_vals); - } - - octave_idx_type n = retval.length (); - - if (n > 0) - retval.stash_name_tags (arg_nm); - - return retval; -} - -std::list -tree_evaluator::make_lvalue_list (tree_argument_list *lhs) -{ - std::list retval; - - for (tree_expression *elt : *lhs) - retval.push_back (elt->lvalue (*this)); - - return retval; -} - -void -tree_evaluator::push_echo_state (int type, const std::string& file_name, - int pos) -{ - unwind_protect *frame = m_call_stack.curr_fcn_unwind_protect_frame (); - - if (frame) - { - push_echo_state_cleanup (*frame); - - set_echo_state (type, file_name, pos); - } -} - -void -tree_evaluator::set_echo_state (int type, const std::string& file_name, - int pos) -{ - m_echo_state = echo_this_file (file_name, type); - m_echo_file_name = file_name; - m_echo_file_pos = pos; -} - -void -tree_evaluator::uwp_set_echo_state (bool state, const std::string& file_name, - int pos) -{ - m_echo_state = state; - m_echo_file_name = file_name; - m_echo_file_pos = pos; -} - -void -tree_evaluator::maybe_set_echo_state (void) -{ - octave_function *caller = caller_function (); - - if (caller && caller->is_user_code ()) - { - octave_user_code *fcn = dynamic_cast (caller); - - int type = fcn->is_user_function () ? ECHO_FUNCTIONS : ECHO_SCRIPTS; - - std::string file_name = fcn->fcn_file_name (); - - // We want the line where "echo" was called, not the line number - // stored in the stack frame that was created for the echo - // function (that will always be -1). - - int pos = m_call_stack.current_user_code_line (); - - if (pos < 0) - pos = 1; - - set_echo_state (type, file_name, pos); - } -} - -void -tree_evaluator::push_echo_state_cleanup (unwind_protect& frame) -{ - frame.add (&tree_evaluator::uwp_set_echo_state, this, - m_echo_state, m_echo_file_name, m_echo_file_pos); -} - -bool tree_evaluator::maybe_push_echo_state_cleanup (void) -{ - // This function is expected to be called from ECHO, which would be - // the top of the call stack. If the caller of ECHO is a - // user-defined function or script, then set up unwind-protect - // elements to restore echo state. - - unwind_protect *frame = m_call_stack.curr_fcn_unwind_protect_frame (); - - if (frame) - { - push_echo_state_cleanup (*frame); - return true; - } - - return false; -} - - -octave_value -tree_evaluator::echo (const octave_value_list& args, int) -{ - bool cleanup_pushed = maybe_push_echo_state_cleanup (); - - string_vector argv = args.make_argv (); - - switch (args.length ()) - { - case 0: - if ((m_echo & ECHO_SCRIPTS) || (m_echo & ECHO_FUNCTIONS)) - { - m_echo = ECHO_OFF; - m_echo_files.clear (); - } - else - m_echo = ECHO_SCRIPTS; - break; - - case 1: + } + + if (cleanup_pushed) + maybe_set_echo_state (); + + return octave_value (); + } + + bool tree_evaluator::in_debug_repl (void) const + { + return (m_debugger_stack.empty () + ? false : m_debugger_stack.top()->in_debug_repl ()); + } + + void tree_evaluator::dbcont (void) + { + if (! m_debugger_stack.empty ()) + m_debugger_stack.top()->dbcont (); + } + + void tree_evaluator::dbquit (bool all) + { + if (! m_debugger_stack.empty ()) + m_debugger_stack.top()->dbquit (all); + } + + static octave_value end_value (const octave_value& value, + octave_idx_type index_position, + octave_idx_type num_indices) + { + dim_vector dv = value.dims (); + int ndims = dv.ndims (); + + if (num_indices < ndims) { - std::string arg0 = argv[0]; - - if (arg0 == "on") - m_echo = ECHO_SCRIPTS; - else if (arg0 == "off") - m_echo = ECHO_OFF; + for (int i = num_indices; i < ndims; i++) + dv(num_indices-1) *= dv(i); + + if (num_indices == 1) + { + ndims = 2; + dv.resize (ndims); + dv(1) = 1; + } else { - std::string file = fcn_file_in_path (arg0); - file = sys::env::make_absolute (file); - - if (file.empty ()) - error ("echo: no such file %s", arg0.c_str ()); - - if (m_echo & ECHO_ALL) - { - // Echo is enabled for all functions, so turn it off - // for this one. - - m_echo_files[file] = false; - } - else + ndims = num_indices; + dv.resize (ndims); + } + } + + return (index_position < ndims + ? octave_value (dv(index_position)) : octave_value (1.0)); + } + + octave_value_list + tree_evaluator::evaluate_end_expression (const octave_value_list& args) + { + int nargin = args.length (); + + if (nargin != 0 && nargin != 3) + print_usage (); + + if (nargin == 3) + { + octave_idx_type index_position + = args(1).xidx_type_value ("end: K must be integer value"); + + if (index_position < 1) + error ("end: K must be greater than zero"); + + octave_idx_type num_indices + = args(2).xidx_type_value ("end: N must be integer value"); + + if (num_indices < 1) + error ("end: N must be greater than zero"); + + return end_value (args(0), index_position-1, num_indices); + } + + // If m_indexed_object is undefined, then this use of 'end' is + // either appearing in a function call argument list or in an + // attempt to index an undefined symbol. There seems to be no + // reasonable way to provide a better error message. So just fail + // with an invalid use message. See bug #58830. + + if (m_indexed_object.is_undefined ()) + error ("invalid use of 'end': may only be used to index existing value"); + + octave_value expr_result; + + if (m_index_list.empty ()) + expr_result = m_indexed_object; + else + { + try + { + // When evaluating "end" with no arguments, we should have + // been called from the built-in Fend function that appears + // in the context of an argument list. Fend will be + // evaluated in its own stack frame. But we need to + // evaluate the partial expression that the special "end" + // token applies to in the calling stack frame. + + unwind_action act ([=] (std::size_t frm) + { + m_call_stack.restore_frame (frm); + }, m_call_stack.current_frame ()); + + std::size_t n = m_call_stack.find_current_user_frame (); + m_call_stack.goto_frame (n); + + // End is only valid inside argument lists used for + // indexing. The dispatch class is set by the function that + // evaluates the argument list. + + // Silently ignore extra output values. + + octave_value_list tmp + = m_indexed_object.subsref (m_index_type, m_index_list, 1); + + expr_result = tmp.length () ? tmp(0) : octave_value (); + + if (expr_result.is_cs_list ()) + err_indexed_cs_list (); + } + catch (const index_exception&) + { + error ("error evaluating partial expression for END"); + } + } + + if (expr_result.isobject ()) + { + // FIXME: is there a better way to lookup and execute a method + // that handles all the details like setting the dispatch class + // appropriately? + + std::string dispatch_class = expr_result.class_name (); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + octave_value meth = symtab.find_method ("end", dispatch_class); + + if (meth.is_defined ()) + return m_interpreter.feval + (meth, ovl (expr_result, m_index_position+1, m_num_indices), 1); + } + + return end_value (expr_result, m_index_position, m_num_indices); + } + + octave_value + tree_evaluator::PS4 (const octave_value_list& args, int nargout) + { + return set_internal_variable (m_PS4, args, nargout, "PS4"); + } + + bool tree_evaluator::echo_this_file (const std::string& file, int type) const + { + if ((type & m_echo) == ECHO_SCRIPTS) + { + // Asking about scripts and echo is enabled for them. + return true; + } + + if ((type & m_echo) == ECHO_FUNCTIONS) + { + // Asking about functions and echo is enabled for functions. + // Now, which ones? + + auto p = m_echo_files.find (file); + + if (m_echo & ECHO_ALL) + { + // Return true ulness echo was turned off for a specific + // file. + + return (p == m_echo_files.end () || p->second); + } + else + { + // Return true if echo is specifically enabled for this file. + + return p != m_echo_files.end () && p->second; + } + } + + return false; + } + + void tree_evaluator::echo_code (int line) + { + std::string prefix = command_editor::decode_prompt_string (m_PS4); + + octave_function *curr_fcn = m_call_stack.current_function (); + + if (curr_fcn && curr_fcn->is_user_code ()) + { + octave_user_code *code = dynamic_cast (curr_fcn); + + int num_lines = line - m_echo_file_pos + 1; + + std::deque lines + = code->get_code_lines (m_echo_file_pos, num_lines); + + for (auto& elt : lines) + octave_stdout << prefix << elt << std::endl; + } + } + + // Decide if it's time to quit a for or while loop. + bool tree_evaluator::quit_loop_now (void) + { + octave_quit (); + + // Maybe handle 'continue N' someday... + + if (m_continuing) + m_continuing--; + + bool quit = (m_returning || m_breaking || m_continuing); + + if (m_breaking) + m_breaking--; + + return quit; + } + + void tree_evaluator::bind_auto_fcn_vars (const string_vector& arg_names, + const Matrix& ignored_outputs, + int nargin, int nargout, + bool takes_varargs, + const octave_value_list& va_args) + { + set_auto_fcn_var (stack_frame::ARG_NAMES, Cell (arg_names)); + set_auto_fcn_var (stack_frame::IGNORED, ignored_outputs); + set_auto_fcn_var (stack_frame::NARGIN, nargin); + set_auto_fcn_var (stack_frame::NARGOUT, nargout); + set_auto_fcn_var (stack_frame::SAVED_WARNING_STATES, octave_value ()); + + if (takes_varargs) + assign ("varargin", va_args.cell_value ()); + } + + std::string + tree_evaluator::check_autoload_file (const std::string& nm) const + { + if (sys::env::absolute_pathname (nm)) + return nm; + + std::string full_name = nm; + + octave_user_code *fcn = m_call_stack.current_user_code (); + + bool found = false; + + if (fcn) + { + std::string fname = fcn->fcn_file_name (); + + if (! fname.empty ()) + { + fname = sys::env::make_absolute (fname); + fname = fname.substr (0, fname.find_last_of (sys::file_ops::dir_sep_str ()) + 1); + + sys::file_stat fs (fname + nm); + + if (fs.exists ()) { - // Echo may be enabled for specific functions. - - auto p = m_echo_files.find (file); - - if (p == m_echo_files.end ()) - { - // Not this one, so enable it. - - m_echo |= ECHO_FUNCTIONS; - m_echo_files[file] = true; - } - else - { - // This one is already in the list. Flip the - // status for it. - - p->second = ! p->second; - } + full_name = fname + nm; + found = true; } } } - break; - - case 2: - { - std::string arg0 = argv[0]; - std::string arg1 = argv[1]; - - if (arg1 == "on" || arg1 == "off") - std::swap (arg0, arg1); - - if (arg0 == "on") - { - if (arg1 == "all") - { - m_echo = (ECHO_SCRIPTS | ECHO_FUNCTIONS | ECHO_ALL); - m_echo_files.clear (); - } - else - { - std::string file = fcn_file_in_path (arg1); - file = sys::env::make_absolute (file); - - if (file.empty ()) - error ("echo: no such file %s", arg1.c_str ()); - - m_echo |= ECHO_FUNCTIONS; - m_echo_files[file] = true; - } - } - else if (arg0 == "off") - { - if (arg1 == "all") - { - m_echo = ECHO_OFF; - m_echo_files.clear (); - } - else - { - std::string file = fcn_file_in_path (arg1); - file = sys::env::make_absolute (file); - - if (file.empty ()) - error ("echo: no such file %s", arg1.c_str ()); - - m_echo_files[file] = false; - } - } - else - print_usage (); - } - break; - - default: - print_usage (); - break; - } - - if (cleanup_pushed) - maybe_set_echo_state (); - - return octave_value (); -} - -bool tree_evaluator::in_debug_repl (void) const -{ - return (m_debugger_stack.empty () - ? false : m_debugger_stack.top()->in_debug_repl ()); -} - -void tree_evaluator::dbcont (void) -{ - if (! m_debugger_stack.empty ()) - m_debugger_stack.top()->dbcont (); -} - -void tree_evaluator::dbquit (bool all) -{ - if (! m_debugger_stack.empty ()) - m_debugger_stack.top()->dbquit (all); -} - -static octave_value end_value (const octave_value& value, - octave_idx_type index_position, - octave_idx_type num_indices) -{ - dim_vector dv = value.dims (); - int ndims = dv.ndims (); - - if (num_indices < ndims) - { - for (int i = num_indices; i < ndims; i++) - dv(num_indices-1) *= dv(i); - - if (num_indices == 1) - { - ndims = 2; - dv.resize (ndims); - dv(1) = 1; - } - else - { - ndims = num_indices; - dv.resize (ndims); - } - } - - return (index_position < ndims - ? octave_value (dv(index_position)) : octave_value (1.0)); -} - -octave_value_list -tree_evaluator::evaluate_end_expression (const octave_value_list& args) -{ - int nargin = args.length (); - - if (nargin != 0 && nargin != 3) - print_usage (); - - if (nargin == 3) - { - octave_idx_type index_position - = args(1).xidx_type_value ("end: K must be integer value"); - - if (index_position < 1) - error ("end: K must be greater than zero"); - - octave_idx_type num_indices - = args(2).xidx_type_value ("end: N must be integer value"); - - if (num_indices < 1) - error ("end: N must be greater than zero"); - - return end_value (args(0), index_position-1, num_indices); - } - - // If m_indexed_object is undefined, then this use of 'end' is - // either appearing in a function call argument list or in an - // attempt to index an undefined symbol. There seems to be no - // reasonable way to provide a better error message. So just fail - // with an invalid use message. See bug #58830. - - if (m_indexed_object.is_undefined ()) - error ("invalid use of 'end': may only be used to index existing value"); - - octave_value expr_result; - - if (m_index_list.empty ()) - expr_result = m_indexed_object; - else - { - try - { - // When evaluating "end" with no arguments, we should have - // been called from the built-in Fend function that appears - // in the context of an argument list. Fend will be - // evaluated in its own stack frame. But we need to - // evaluate the partial expression that the special "end" - // token applies to in the calling stack frame. - - unwind_action act ([=] (std::size_t frm) - { - m_call_stack.restore_frame (frm); - }, m_call_stack.current_frame ()); - - std::size_t n = m_call_stack.find_current_user_frame (); - m_call_stack.goto_frame (n); - - // End is only valid inside argument lists used for - // indexing. The dispatch class is set by the function that - // evaluates the argument list. - - // Silently ignore extra output values. - - octave_value_list tmp - = m_indexed_object.subsref (m_index_type, m_index_list, 1); - - expr_result = tmp.length () ? tmp(0) : octave_value (); - - if (expr_result.is_cs_list ()) - err_indexed_cs_list (); - } - catch (const index_exception&) - { - error ("error evaluating partial expression for END"); - } - } - - if (expr_result.isobject ()) - { - // FIXME: is there a better way to lookup and execute a method - // that handles all the details like setting the dispatch class - // appropriately? - - std::string dispatch_class = expr_result.class_name (); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - octave_value meth = symtab.find_method ("end", dispatch_class); - - if (meth.is_defined ()) - return m_interpreter.feval - (meth, ovl (expr_result, m_index_position+1, m_num_indices), 1); - } - - return end_value (expr_result, m_index_position, m_num_indices); -} - -octave_value -tree_evaluator::PS4 (const octave_value_list& args, int nargout) -{ - return set_internal_variable (m_PS4, args, nargout, "PS4"); -} - -bool tree_evaluator::echo_this_file (const std::string& file, int type) const -{ - if ((type & m_echo) == ECHO_SCRIPTS) - { - // Asking about scripts and echo is enabled for them. - return true; - } - - if ((type & m_echo) == ECHO_FUNCTIONS) - { - // Asking about functions and echo is enabled for functions. - // Now, which ones? - - auto p = m_echo_files.find (file); - - if (m_echo & ECHO_ALL) - { - // Return true ulness echo was turned off for a specific - // file. - - return (p == m_echo_files.end () || p->second); - } - else - { - // Return true if echo is specifically enabled for this file. - - return p != m_echo_files.end () && p->second; - } - } - - return false; -} - -void tree_evaluator::echo_code (int line) -{ - std::string prefix = command_editor::decode_prompt_string (m_PS4); - - octave_function *curr_fcn = m_call_stack.current_function (); - - if (curr_fcn && curr_fcn->is_user_code ()) - { - octave_user_code *code = dynamic_cast (curr_fcn); - - int num_lines = line - m_echo_file_pos + 1; - - std::deque lines - = code->get_code_lines (m_echo_file_pos, num_lines); - - for (auto& elt : lines) - octave_stdout << prefix << elt << std::endl; - } -} - -// Decide if it's time to quit a for or while loop. -bool tree_evaluator::quit_loop_now (void) -{ - octave_quit (); - - // Maybe handle 'continue N' someday... - - if (m_continuing) - m_continuing--; - - bool quit = (m_returning || m_breaking || m_continuing); - - if (m_breaking) - m_breaking--; - - return quit; -} - -void tree_evaluator::bind_auto_fcn_vars (const string_vector& arg_names, - const Matrix& ignored_outputs, - int nargin, int nargout, - bool takes_varargs, - const octave_value_list& va_args) -{ - set_auto_fcn_var (stack_frame::ARG_NAMES, Cell (arg_names)); - set_auto_fcn_var (stack_frame::IGNORED, ignored_outputs); - set_auto_fcn_var (stack_frame::NARGIN, nargin); - set_auto_fcn_var (stack_frame::NARGOUT, nargout); - set_auto_fcn_var (stack_frame::SAVED_WARNING_STATES, octave_value ()); - - if (takes_varargs) - assign ("varargin", va_args.cell_value ()); -} - -std::string -tree_evaluator::check_autoload_file (const std::string& nm) const -{ - if (sys::env::absolute_pathname (nm)) - return nm; - - std::string full_name = nm; - - octave_user_code *fcn = m_call_stack.current_user_code (); - - bool found = false; - - if (fcn) - { - std::string fname = fcn->fcn_file_name (); - - if (! fname.empty ()) - { - fname = sys::env::make_absolute (fname); - fname = fname.substr (0, fname.find_last_of (sys::file_ops::dir_sep_str ()) + 1); - - sys::file_stat fs (fname + nm); - - if (fs.exists ()) - { - full_name = fname + nm; - found = true; - } - } - } - - if (! found) - warning_with_id ("Octave:autoload-relative-file-name", - "autoload: '%s' is not an absolute filename", - nm.c_str ()); - - return full_name; -} + + if (! found) + warning_with_id ("Octave:autoload-relative-file-name", + "autoload: '%s' is not an absolute filename", + nm.c_str ()); + + return full_name; + } DEFMETHOD (max_recursion_depth, interp, args, nargout, doc: /* -*- texinfo -*- diff -r 29d734430e5f -r deb553ac2c54 liboctave/array/Array.h --- a/liboctave/array/Array.h Tue Dec 06 14:53:00 2022 -0500 +++ b/liboctave/array/Array.h Tue Dec 06 15:45:27 2022 -0500 @@ -663,12 +663,6 @@ OCTARRAY_OVERRIDABLE_FUNC_API const T * data (void) const { return m_slice_data; } -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "for read-only access, use 'data' method instead") - OCTARRAY_OVERRIDABLE_FUNC_API const T * fortran_vec (void) const - { return data (); } -#endif - OCTARRAY_API T * fortran_vec (void); OCTARRAY_OVERRIDABLE_FUNC_API bool is_shared (void) diff -r 29d734430e5f -r deb553ac2c54 liboctave/array/DiagArray2.h --- a/liboctave/array/DiagArray2.h Tue Dec 06 14:53:00 2022 -0500 +++ b/liboctave/array/DiagArray2.h Tue Dec 06 15:45:27 2022 -0500 @@ -168,11 +168,6 @@ const T * data (void) const { return Array::data (); } -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "for read-only access, use 'data' method instead") - const T * fortran_vec (void) const { return Array::data (); } -#endif - T * fortran_vec (void) { return Array::fortran_vec (); } void print_info (std::ostream& os, const std::string& prefix) const diff -r 29d734430e5f -r deb553ac2c54 liboctave/array/Range.cc --- a/liboctave/array/Range.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/liboctave/array/Range.cc Tue Dec 06 15:45:27 2022 -0500 @@ -453,553 +453,3 @@ } OCTAVE_END_NAMESPACE(octave) - -bool -Range::all_elements_are_ints (void) const -{ - // If the base and increment are ints, the final value in the range will also - // be an integer, even if the limit is not. If there is one or fewer - // elements only the base needs to be an integer. - - return (! (octave::math::isnan (m_base) || octave::math::isnan (m_inc)) - && (octave::math::nint_big (m_base) == m_base || m_numel < 1) - && (octave::math::nint_big (m_inc) == m_inc || m_numel <= 1)); -} - -octave_idx_type -Range::nnz (void) const -{ - octave_idx_type retval = 0; - - if (! isempty ()) - { - if ((m_base > 0.0 && m_limit > 0.0) || (m_base < 0.0 && m_limit < 0.0)) - { - // All elements have the same sign, hence there are no zeros. - retval = m_numel; - } - else if (m_inc != 0.0) - { - if (m_base == 0.0 || m_limit == 0.0) - // Exactly one zero at beginning or end of range. - retval = m_numel - 1; - else if ((m_base / m_inc) != std::floor (m_base / m_inc)) - // Range crosses negative/positive without hitting zero. - retval = m_numel; - else - // Range crosses negative/positive and hits zero. - retval = m_numel - 1; - } - else - { - // All elements are equal (m_inc = 0) but not positive or negative, - // therefore all elements are zero. - retval = 0; - } - } - - return retval; -} - -Matrix -Range::matrix_value (void) const -{ - Matrix retval (1, m_numel); - - if (m_numel > 0) - { - // The first element must always be *exactly* the base. - // E.g, -0 would otherwise become +0 in the loop (-0 + 0*increment). - retval(0) = m_base; - - double b = m_base; - double increment = m_inc; - for (octave_idx_type i = 1; i < m_numel - 1; i++) - retval.xelem (i) = b + i * increment; - - retval.xelem (m_numel - 1) = m_limit; - } - - return retval; -} - -double -Range::checkelem (octave_idx_type i) const -{ - if (i < 0 || i >= m_numel) - octave::err_index_out_of_range (2, 2, i+1, m_numel, dims ()); - - if (i == 0) - return m_base; - else if (i < m_numel - 1) - return m_base + i * m_inc; - else - return m_limit; -} - -double -Range::checkelem (octave_idx_type i, octave_idx_type j) const -{ - // Ranges are *always* row vectors. - if (i != 0) - octave::err_index_out_of_range (1, 1, i+1, m_numel, dims ()); - - return checkelem (j); -} - -double -Range::elem (octave_idx_type i) const -{ - if (i == 0) - return m_base; - else if (i < m_numel - 1) - return m_base + i * m_inc; - else - return m_limit; -} - -Array -Range::index (const octave::idx_vector& idx) const -{ - Array retval; - - octave_idx_type n = m_numel; - - if (idx.is_colon ()) - { - retval = matrix_value ().reshape (dim_vector (m_numel, 1)); - } - else - { - if (idx.extent (n) != n) - octave::err_index_out_of_range (1, 1, idx.extent (n), n, dims ()); // throws - - dim_vector idx_dims = idx.orig_dimensions (); - octave_idx_type idx_len = idx.length (n); - - // taken from Array.cc. - if (n != 1 && idx_dims.isvector ()) - idx_dims = dim_vector (1, idx_len); - - retval.clear (idx_dims); - - // Loop over all values in IDX, executing the lambda expression - // for each index value. - - double *array = retval.fortran_vec (); - - idx.loop (n, [=, &array] (idx_vector i) - { - if (i == 0) - *array++ = m_base; - else if (i < m_numel - 1) - *array++ = m_base + i * m_inc; - else - *array++ = m_limit; - }); - } - - return retval; -} - -// NOTE: max and min only return useful values if numel > 0. -// do_minmax_body() in max.cc avoids calling Range::min/max if numel == 0. - -double -Range::min (void) const -{ - double retval = 0.0; - if (m_numel > 0) - { - if (m_inc > 0) - retval = m_base; - else - { - retval = m_base + (m_numel - 1) * m_inc; - - // Require '<=' test. See note in max (). - if (retval <= m_limit) - retval = m_limit; - } - - } - return retval; -} - -double -Range::max (void) const -{ - double retval = 0.0; - if (m_numel > 0) - { - if (m_inc > 0) - { - retval = m_base + (m_numel - 1) * m_inc; - - // On some machines (x86 with extended precision floating point - // arithmetic, for example) it is possible that we can overshoot the - // limit by approximately the machine precision even though we were - // very careful in our calculation of the number of elements. - // Therefore, we clip the result to the limit if it overshoots. - // The test also includes equality (>= m_limit) to have expressions - // such as -5:1:-0 result in a -0 endpoint. - if (retval >= m_limit) - retval = m_limit; - } - else - retval = m_base; - } - return retval; -} - -void -Range::sort_internal (bool ascending) -{ - if ((ascending && m_base > m_limit && m_inc < 0.0) - || (! ascending && m_base < m_limit && m_inc > 0.0)) - { - std::swap (m_base, m_limit); - m_inc = -m_inc; - } -} - -void -Range::sort_internal (Array& sidx, bool ascending) -{ - octave_idx_type nel = numel (); - - sidx.resize (dim_vector (1, nel)); - - octave_idx_type *psidx = sidx.fortran_vec (); - - bool reverse = false; - - if ((ascending && m_base > m_limit && m_inc < 0.0) - || (! ascending && m_base < m_limit && m_inc > 0.0)) - { - std::swap (m_base, m_limit); - m_inc = -m_inc; - reverse = true; - } - - octave_idx_type tmp = (reverse ? nel - 1 : 0); - octave_idx_type stp = (reverse ? -1 : 1); - - for (octave_idx_type i = 0; i < nel; i++, tmp += stp) - psidx[i] = tmp; -} - -Matrix -Range::diag (octave_idx_type k) const -{ - return matrix_value ().diag (k); -} - -Range -Range::sort (octave_idx_type dim, sortmode mode) const -{ - Range retval = *this; - - if (dim == 1) - { - if (mode == ASCENDING) - retval.sort_internal (true); - else if (mode == DESCENDING) - retval.sort_internal (false); - } - else if (dim != 0) - (*current_liboctave_error_handler) ("Range::sort: invalid dimension"); - - return retval; -} - -Range -Range::sort (Array& sidx, octave_idx_type dim, - sortmode mode) const -{ - Range retval = *this; - - if (dim == 1) - { - if (mode == ASCENDING) - retval.sort_internal (sidx, true); - else if (mode == DESCENDING) - retval.sort_internal (sidx, false); - } - else if (dim != 0) - (*current_liboctave_error_handler) ("Range::sort: invalid dimension"); - - return retval; -} - -sortmode -Range::issorted (sortmode mode) const -{ - if (m_numel > 1 && m_inc > 0) - mode = (mode == DESCENDING) ? UNSORTED : ASCENDING; - else if (m_numel > 1 && m_inc < 0) - mode = (mode == ASCENDING) ? UNSORTED : DESCENDING; - else - mode = (mode == UNSORTED) ? ASCENDING : mode; - - return mode; -} - -void -Range::set_base (double b) -{ - if (m_base != b) - { - m_base = b; - - init (); - } -} - -void -Range::set_limit (double l) -{ - if (m_limit != l) - { - m_limit = l; - - init (); - } -} - -void -Range::set_inc (double i) -{ - if (m_inc != i) - { - m_inc = i; - - init (); - } -} - -std::ostream& -operator << (std::ostream& os, const Range& a) -{ - double b = a.base (); - double increment = a.increment (); - octave_idx_type nel = a.numel (); - - if (nel > 1) - { - // First element must be the base *exactly* (e.g., -0). - os << b << ' '; - for (octave_idx_type i = 1; i < nel-1; i++) - os << b + i * increment << ' '; - } - - // Print out the last element exactly, rather than a calculated last element. - os << a.m_limit << "\n"; - - return os; -} - -std::istream& -operator >> (std::istream& is, Range& a) -{ - is >> a.m_base; - if (is) - { - double tmp_limit; - is >> tmp_limit; - - if (is) - is >> a.m_inc; - - // Clip the m_limit to the true limit, rebuild numel, clear cache - a.set_limit (tmp_limit); - } - - return is; -} - -// DEPRECATED in Octave 7. -Range operator - (const Range& r) -{ - return Range (-r.base (), -r.limit (), -r.increment (), r.numel ()); -} - -// DEPRECATED in Octave 7. -Range operator + (double x, const Range& r) -{ - return Range (x + r.base (), x + r.limit (), r.increment (), r.numel ()); -} - -// DEPRECATED in Octave 7. -Range operator + (const Range& r, double x) -{ - return Range (r.base () + x, r.limit () + x, r.increment (), r.numel ()); -} - -// DEPRECATED in Octave 7. -Range operator - (double x, const Range& r) -{ - return Range (x - r.base (), x - r.limit (), -r.increment (), r.numel ()); -} - -// DEPRECATED in Octave 7. -Range operator - (const Range& r, double x) -{ - return Range (r.base () - x, r.limit () - x, r.increment (), r.numel ()); -} - -// DEPRECATED in Octave 7. -Range operator * (double x, const Range& r) -{ - return Range (x * r.base (), x * r.limit (), x * r.increment (), r.numel ()); -} - -// DEPRECATED in Octave 7. -Range operator * (const Range& r, double x) -{ - return Range (r.base () * x, r.limit () * x, r.increment () * x, r.numel ()); -} - -// C See Knuth, Art Of Computer Programming, Vol. 1, Problem 1.2.4-5. -// C -// C===Tolerant FLOOR function. -// C -// C X - is given as a Double Precision argument to be operated on. -// C It is assumed that X is represented with M mantissa bits. -// C CT - is given as a Comparison Tolerance such that -// C 0.LT.CT.LE.3-SQRT(5)/2. If the relative difference between -// C X and A whole number is less than CT, then TFLOOR is -// C returned as this whole number. By treating the -// C floating-point numbers as a finite ordered set note that -// C the heuristic EPS=2.**(-(M-1)) and CT=3*EPS causes -// C arguments of TFLOOR/TCEIL to be treated as whole numbers -// C if they are exactly whole numbers or are immediately -// C adjacent to whole number representations. Since EPS, the -// C "distance" between floating-point numbers on the unit -// C interval, and M, the number of bits in X'S mantissa, exist -// C on every floating-point computer, TFLOOR/TCEIL are -// C consistently definable on every floating-point computer. -// C -// C For more information see the following references: -// C (1) P. E. Hagerty, "More On Fuzzy Floor And Ceiling," APL QUOTE -// C QUAD 8(4):20-24, June 1978. Note that TFLOOR=FL5. -// C (2) L. M. Breed, "Definitions For Fuzzy Floor And Ceiling", APL -// C QUOTE QUAD 8(3):16-23, March 1978. This paper cites FL1 through -// C FL5, the history of five years of evolutionary development of -// C FL5 - the seven lines of code below - by open collaboration -// C and corroboration of the mathematical-computing community. -// C -// C Penn State University Center for Academic Computing -// C H. D. Knoble - August, 1978. - -static inline double -tfloor (double x, double ct) -{ -// C---------FLOOR(X) is the largest integer algebraically less than -// C or equal to X; that is, the unfuzzy FLOOR function. - -// DINT (X) = X - DMOD (X, 1.0); -// FLOOR (X) = DINT (X) - DMOD (2.0 + DSIGN (1.0, X), 3.0); - -// C---------Hagerty's FL5 function follows... - - double q = 1.0; - - if (x < 0.0) - q = 1.0 - ct; - - double rmax = q / (2.0 - ct); - - double t1 = 1.0 + std::floor (x); - t1 = (ct / q) * (t1 < 0.0 ? -t1 : t1); - t1 = (rmax < t1 ? rmax : t1); - t1 = (ct > t1 ? ct : t1); - t1 = std::floor (x + t1); - - if (x <= 0.0 || (t1 - x) < rmax) - return t1; - else - return t1 - 1.0; -} - -static inline bool -teq (double u, double v, - double ct = 3.0 * std::numeric_limits::epsilon ()) -{ - double tu = std::abs (u); - double tv = std::abs (v); - - return std::abs (u - v) < ((tu > tv ? tu : tv) * ct); -} - -octave_idx_type -Range::numel_internal (void) const -{ - octave_idx_type retval = -1; - - if (! octave::math::isfinite (m_base) || ! octave::math::isfinite (m_inc) - || octave::math::isnan (m_limit)) - retval = -2; - else if (octave::math::isinf (m_limit) - && ((m_inc > 0 && m_limit > 0) - || (m_inc < 0 && m_limit < 0))) - retval = std::numeric_limits::max () - 1; - else if (m_inc == 0 - || (m_limit > m_base && m_inc < 0) - || (m_limit < m_base && m_inc > 0)) - { - retval = 0; - } - else - { - double ct = 3.0 * std::numeric_limits::epsilon (); - - double tmp = tfloor ((m_limit - m_base + m_inc) / m_inc, ct); - - octave_idx_type n_elt = (tmp > 0.0 - ? static_cast (tmp) : 0); - - // If the final element that we would compute for the range is equal to - // the limit of the range, or is an adjacent floating point number, - // accept it. Otherwise, try a range with one fewer element. If that - // fails, try again with one more element. - // - // I'm not sure this is very good, but it seems to work better than just - // using tfloor as above. For example, without it, the expression - // 1.8:0.05:1.9 fails to produce the expected result of [1.8, 1.85, 1.9]. - - if (! teq (m_base + (n_elt - 1) * m_inc, m_limit)) - { - if (teq (m_base + (n_elt - 2) * m_inc, m_limit)) - n_elt--; - else if (teq (m_base + n_elt * m_inc, m_limit)) - n_elt++; - } - - retval = ((n_elt < std::numeric_limits::max ()) - ? n_elt : -1); - } - - return retval; -} - -double -Range::limit_internal (void) const -{ - double new_limit = m_inc > 0 ? max () : min (); - - // If result must be an integer then force the new_limit to be one. - if (all_elements_are_ints ()) - new_limit = std::round (new_limit); - - return new_limit; -} - -void -Range::init (void) -{ - m_numel = numel_internal (); - - if (! octave::math::isinf (m_limit)) - m_limit = limit_internal (); -} diff -r 29d734430e5f -r deb553ac2c54 liboctave/array/Range.h --- a/liboctave/array/Range.h Tue Dec 06 14:53:00 2022 -0500 +++ b/liboctave/array/Range.h Tue Dec 06 15:45:27 2022 -0500 @@ -40,550 +40,360 @@ OCTAVE_BEGIN_NAMESPACE(octave) -// For now, only define for floating point types. However, we only -// need range as a temporary local variable in make_float_range -// in ov.cc. - -template -class -range::value>::type> -{ -public: - - range (void) - : m_base (0), m_increment (0), m_limit (0), m_final (0), m_numel (0), - m_reverse (false) - { } - - // LIMIT is an upper limit and may be outside the range of actual - // values. For floating point ranges, we perform a tolerant check - // to attempt to capture limit in the set of values if it is "close" - // to the value of base + a multiple of the increment. - - range (const T& base, const T& increment, const T& limit, - bool reverse = false) - : m_base (base), m_increment (increment), m_limit (limit), - m_final (), m_numel (), m_reverse (reverse) - { - init (); - } - - range (const T& base, const T& limit) - : m_base (base), m_increment (1), m_limit (limit), m_final (), m_numel (), - m_reverse (false) - { - init (); - } + // For now, only define for floating point types. However, we only + // need range as a temporary local variable in make_float_range + // in ov.cc. - // Allow conversion from (presumably) properly constructed Range - // objects. The values of base, limit, increment, and numel must be - // consistent. - - // FIXME: Actually check that base, limit, increment, and numel are - // consistent? - - range (const T& base, const T& increment, const T& limit, - octave_idx_type numel, bool reverse = false) - : m_base (base), m_increment (increment), m_limit (limit), - m_final (limit), m_numel (numel), m_reverse (reverse) - { } - - // We don't use a constructor for this because it will conflict with - // range (base, limit, increment) when T is octave_idx_type. - - static range make_n_element_range (const T& base, const T& increment, - octave_idx_type numel, - bool reverse = false) - { - // We could just make this constructor public, but it allows - // inconsistent ranges to be constructed. And it is probably much - // clearer to see "make_n_element_range" instead of puzzling over the - // purpose of this strange constructor form. - - T final_val = (reverse ? base - (numel - 1) * increment - : base + (numel - 1) * increment); - - return range (base, increment, final_val, numel, reverse); - } - - range (const range& r) - : m_base (r.m_base), m_increment (r.m_increment), - m_limit (r.m_limit), m_final (r.m_final), - m_numel (r.m_numel), m_reverse (r.m_reverse) - { } - - range& operator = (const range& r) + template + class + range::value>::type> { - if (this != &r) - { - m_base = r.m_base; - m_increment = r.m_increment; - m_limit = r.m_limit; - m_final = r.m_final; - m_numel = r.m_numel; - m_reverse = r.m_reverse; - } + public: + + range (void) + : m_base (0), m_increment (0), m_limit (0), m_final (0), m_numel (0), + m_reverse (false) + { } + + // LIMIT is an upper limit and may be outside the range of actual + // values. For floating point ranges, we perform a tolerant check + // to attempt to capture limit in the set of values if it is "close" + // to the value of base + a multiple of the increment. - return *this; - } - - ~range (void) = default; + range (const T& base, const T& increment, const T& limit, + bool reverse = false) + : m_base (base), m_increment (increment), m_limit (limit), + m_final (), m_numel (), m_reverse (reverse) + { + init (); + } - T base (void) const { return m_base; } - T increment (void) const { return m_increment; } - T limit (void) const { return m_limit; } - bool reverse (void) const { return m_reverse; } + range (const T& base, const T& limit) + : m_base (base), m_increment (1), m_limit (limit), m_final (), m_numel (), + m_reverse (false) + { + init (); + } + + // Allow conversion from (presumably) properly constructed Range + // objects. The values of base, limit, increment, and numel must be + // consistent. - T final_value (void) const { return m_final; } + // FIXME: Actually check that base, limit, increment, and numel are + // consistent? - T min (void) const - { - return (m_numel > 0 - ? ((m_reverse ? m_increment > T (0) - : m_increment > T (0)) ? base () : final_value ()) - : T (0)); - } + range (const T& base, const T& increment, const T& limit, + octave_idx_type numel, bool reverse = false) + : m_base (base), m_increment (increment), m_limit (limit), + m_final (limit), m_numel (numel), m_reverse (reverse) + { } + + // We don't use a constructor for this because it will conflict with + // range (base, limit, increment) when T is octave_idx_type. - T max (void) const - { - return (m_numel > 0 - ? ((m_reverse ? m_increment < T (0) - : m_increment > T (0)) ? final_value () : base ()) - : T (0)); - } + static range make_n_element_range (const T& base, const T& increment, + octave_idx_type numel, + bool reverse = false) + { + // We could just make this constructor public, but it allows + // inconsistent ranges to be constructed. And it is probably much + // clearer to see "make_n_element_range" instead of puzzling over the + // purpose of this strange constructor form. - octave_idx_type numel (void) const { return m_numel; } + T final_val = (reverse ? base - (numel - 1) * increment + : base + (numel - 1) * increment); + + return range (base, increment, final_val, numel, reverse); + } + + range (const range& r) + : m_base (r.m_base), m_increment (r.m_increment), + m_limit (r.m_limit), m_final (r.m_final), + m_numel (r.m_numel), m_reverse (r.m_reverse) + { } - // To support things like "for i = 1:Inf; ...; end" that are - // required for Matlab compatibility, creation of a range object - // like 1:Inf is allowed with m_numel set to - // numeric_limits::max(). However, it is not - // possible to store these ranges. The following function allows - // us to easily distinguish ranges with an infinite number of - // elements. There are specializations for double and float. + range& operator = (const range& r) + { + if (this != &r) + { + m_base = r.m_base; + m_increment = r.m_increment; + m_limit = r.m_limit; + m_final = r.m_final; + m_numel = r.m_numel; + m_reverse = r.m_reverse; + } - bool is_storable (void) const { return true; } + return *this; + } + + ~range (void) = default; - dim_vector dims (void) const { return dim_vector (1, m_numel); } + T base (void) const { return m_base; } + T increment (void) const { return m_increment; } + T limit (void) const { return m_limit; } + bool reverse (void) const { return m_reverse; } - octave_idx_type rows (void) const { return 1; } + T final_value (void) const { return m_final; } - octave_idx_type cols (void) const { return numel (); } - octave_idx_type columns (void) const { return numel (); } + T min (void) const + { + return (m_numel > 0 + ? ((m_reverse ? m_increment > T (0) + : m_increment > T (0)) ? base () : final_value ()) + : T (0)); + } - bool isempty (void) const { return numel () == 0; } + T max (void) const + { + return (m_numel > 0 + ? ((m_reverse ? m_increment < T (0) + : m_increment > T (0)) ? final_value () : base ()) + : T (0)); + } - bool all_elements_are_ints (void) const { return true; } + octave_idx_type numel (void) const { return m_numel; } - sortmode issorted (sortmode mode = ASCENDING) const - { - if (m_numel > 1 && (m_reverse ? m_increment < T (0) - : m_increment > T (0))) - mode = ((mode == DESCENDING) ? UNSORTED : ASCENDING); - else if (m_numel > 1 && (m_reverse ? m_increment > T (0) - : m_increment < T (0))) - mode = ((mode == ASCENDING) ? UNSORTED : DESCENDING); - else - mode = ((mode == UNSORTED) ? ASCENDING : mode); + // To support things like "for i = 1:Inf; ...; end" that are + // required for Matlab compatibility, creation of a range object + // like 1:Inf is allowed with m_numel set to + // numeric_limits::max(). However, it is not + // possible to store these ranges. The following function allows + // us to easily distinguish ranges with an infinite number of + // elements. There are specializations for double and float. + + bool is_storable (void) const { return true; } + + dim_vector dims (void) const { return dim_vector (1, m_numel); } + + octave_idx_type rows (void) const { return 1; } + + octave_idx_type cols (void) const { return numel (); } + octave_idx_type columns (void) const { return numel (); } + + bool isempty (void) const { return numel () == 0; } + + bool all_elements_are_ints (void) const { return true; } - return mode; - } - - OCTAVE_API octave_idx_type nnz (void) const; + sortmode issorted (sortmode mode = ASCENDING) const + { + if (m_numel > 1 && (m_reverse ? m_increment < T (0) + : m_increment > T (0))) + mode = ((mode == DESCENDING) ? UNSORTED : ASCENDING); + else if (m_numel > 1 && (m_reverse ? m_increment > T (0) + : m_increment < T (0))) + mode = ((mode == ASCENDING) ? UNSORTED : DESCENDING); + else + mode = ((mode == UNSORTED) ? ASCENDING : mode); - // Support for single-index subscripting, without generating matrix cache. + return mode; + } + + OCTAVE_API octave_idx_type nnz (void) const; - T checkelem (octave_idx_type i) const - { - if (i < 0 || i >= m_numel) - err_index_out_of_range (2, 2, i+1, m_numel, dims ()); + // Support for single-index subscripting, without generating matrix cache. + + T checkelem (octave_idx_type i) const + { + if (i < 0 || i >= m_numel) + err_index_out_of_range (2, 2, i+1, m_numel, dims ()); - if (i == 0) - // Required for proper NaN handling. - return (m_numel == 1 ? final_value () : m_base); - else if (i < m_numel - 1) - return (m_reverse ? m_base + T (i) * m_increment - : m_base + T (i) * m_increment); - else - return final_value (); - } + if (i == 0) + // Required for proper NaN handling. + return (m_numel == 1 ? final_value () : m_base); + else if (i < m_numel - 1) + return (m_reverse ? m_base + T (i) * m_increment + : m_base + T (i) * m_increment); + else + return final_value (); + } - T checkelem (octave_idx_type i, octave_idx_type j) const - { - // Ranges are *always* row vectors. - if (i != 0) - err_index_out_of_range (1, 1, i+1, m_numel, dims ()); + T checkelem (octave_idx_type i, octave_idx_type j) const + { + // Ranges are *always* row vectors. + if (i != 0) + err_index_out_of_range (1, 1, i+1, m_numel, dims ()); - return checkelem (j); - } + return checkelem (j); + } - T elem (octave_idx_type i) const - { - if (i == 0) - // Required for proper NaN handling. - return (m_numel == 1 ? final_value () : m_base); - else if (i < m_numel - 1) - return (m_reverse ? m_base - T (i) * m_increment - : m_base + T (i) * m_increment); - else - return final_value (); - } + T elem (octave_idx_type i) const + { + if (i == 0) + // Required for proper NaN handling. + return (m_numel == 1 ? final_value () : m_base); + else if (i < m_numel - 1) + return (m_reverse ? m_base - T (i) * m_increment + : m_base + T (i) * m_increment); + else + return final_value (); + } - T elem (octave_idx_type /* i */, octave_idx_type j) const - { - return elem (j); - } + T elem (octave_idx_type /* i */, octave_idx_type j) const + { + return elem (j); + } - T operator () (octave_idx_type i) const - { - return elem (i); - } + T operator () (octave_idx_type i) const + { + return elem (i); + } - T operator () (octave_idx_type i, octave_idx_type j) const - { - return elem (i, j); - } + T operator () (octave_idx_type i, octave_idx_type j) const + { + return elem (i, j); + } - Array index (const idx_vector& idx) const - { - Array retval; + Array index (const idx_vector& idx) const + { + Array retval; - octave_idx_type n = m_numel; + octave_idx_type n = m_numel; - if (idx.is_colon ()) - { - retval = array_value ().reshape (dim_vector (m_numel, 1)); - } - else - { - if (idx.extent (n) != n) - err_index_out_of_range (1, 1, idx.extent (n), n, dims ()); + if (idx.is_colon ()) + { + retval = array_value ().reshape (dim_vector (m_numel, 1)); + } + else + { + if (idx.extent (n) != n) + err_index_out_of_range (1, 1, idx.extent (n), n, dims ()); - dim_vector idx_dims = idx.orig_dimensions (); - octave_idx_type idx_len = idx.length (n); + dim_vector idx_dims = idx.orig_dimensions (); + octave_idx_type idx_len = idx.length (n); - // taken from Array.cc. - if (n != 1 && idx_dims.isvector ()) - idx_dims = dim_vector (1, idx_len); + // taken from Array.cc. + if (n != 1 && idx_dims.isvector ()) + idx_dims = dim_vector (1, idx_len); - retval.clear (idx_dims); + retval.clear (idx_dims); - // Loop over all values in IDX, executing the lambda - // expression for each index value. + // Loop over all values in IDX, executing the lambda + // expression for each index value. - T *array = retval.fortran_vec (); + T *array = retval.fortran_vec (); - idx.loop (n, [=, &array] (octave_idx_type i) - { - if (i == 0) - // Required for proper NaN handling. - *array++ = (m_numel == 0 ? m_final : m_base); - else if (i < m_numel - 1) - *array++ = (m_reverse ? m_base - T (i) * m_increment - : m_base + T (i) * m_increment); - else - *array++ = m_final; - }); - } + idx.loop (n, [=, &array] (octave_idx_type i) + { + if (i == 0) + // Required for proper NaN handling. + *array++ = (m_numel == 0 ? m_final : m_base); + else if (i < m_numel - 1) + *array++ = (m_reverse ? m_base - T (i) * m_increment + : m_base + T (i) * m_increment); + else + *array++ = m_final; + }); + } - return retval; - } + return retval; + } - Array diag (octave_idx_type k) const - { - return array_value ().diag (k); - } + Array diag (octave_idx_type k) const + { + return array_value ().diag (k); + } - Array array_value (void) const - { - octave_idx_type nel = numel (); + Array array_value (void) const + { + octave_idx_type nel = numel (); - Array retval (dim_vector (1, nel)); + Array retval (dim_vector (1, nel)); - if (nel == 1) - // Required for proper NaN handling. - retval(0) = final_value (); - else if (nel > 1) - { - // The first element must always be *exactly* the base. - // E.g, -0 would otherwise become +0 in the loop (-0 + 0*increment). - retval(0) = m_base; + if (nel == 1) + // Required for proper NaN handling. + retval(0) = final_value (); + else if (nel > 1) + { + // The first element must always be *exactly* the base. + // E.g, -0 would otherwise become +0 in the loop (-0 + 0*increment). + retval(0) = m_base; - if (m_reverse) - for (octave_idx_type i = 1; i < nel - 1; i++) - retval.xelem (i) = m_base - i * m_increment; - else - for (octave_idx_type i = 1; i < nel - 1; i++) - retval.xelem (i) = m_base + i * m_increment; + if (m_reverse) + for (octave_idx_type i = 1; i < nel - 1; i++) + retval.xelem (i) = m_base - i * m_increment; + else + for (octave_idx_type i = 1; i < nel - 1; i++) + retval.xelem (i) = m_base + i * m_increment; - retval.xelem (nel - 1) = final_value (); - } + retval.xelem (nel - 1) = final_value (); + } - return retval; - } + return retval; + } -private: + private: - T m_base; - T m_increment; - T m_limit; - T m_final; - octave_idx_type m_numel; - bool m_reverse; + T m_base; + T m_increment; + T m_limit; + T m_final; + octave_idx_type m_numel; + bool m_reverse; - // Setting the number of elements to zero when the increment is zero - // is intentional and matches the behavior of Matlab's colon - // operator. + // Setting the number of elements to zero when the increment is zero + // is intentional and matches the behavior of Matlab's colon + // operator. - // These calculations are appropriate for integer ranges. There are - // specializations for double and float. + // These calculations are appropriate for integer ranges. There are + // specializations for double and float. - void init (void) - { - if (m_reverse) - { - m_numel = ((m_increment == T (0) - || (m_limit > m_base && m_increment > T (0)) - || (m_limit < m_base && m_increment < T (0))) - ? T (0) - : (m_base - m_limit - m_increment) / m_increment); + void init (void) + { + if (m_reverse) + { + m_numel = ((m_increment == T (0) + || (m_limit > m_base && m_increment > T (0)) + || (m_limit < m_base && m_increment < T (0))) + ? T (0) + : (m_base - m_limit - m_increment) / m_increment); - m_final = m_base - (m_numel - 1) * m_increment; - } - else - { - m_numel = ((m_increment == T (0) - || (m_limit > m_base && m_increment < T (0)) - || (m_limit < m_base && m_increment > T (0))) - ? T (0) - : (m_limit - m_base + m_increment) / m_increment); + m_final = m_base - (m_numel - 1) * m_increment; + } + else + { + m_numel = ((m_increment == T (0) + || (m_limit > m_base && m_increment < T (0)) + || (m_limit < m_base && m_increment > T (0))) + ? T (0) + : (m_limit - m_base + m_increment) / m_increment); - m_final = m_base + (m_numel - 1) * m_increment; - } - } -}; + m_final = m_base + (m_numel - 1) * m_increment; + } + } + }; -// Specializations defined externally. + // Specializations defined externally. -template <> OCTAVE_API bool range::all_elements_are_ints (void) const; -template <> OCTAVE_API bool range::all_elements_are_ints (void) const; + template <> OCTAVE_API bool range::all_elements_are_ints (void) const; + template <> OCTAVE_API bool range::all_elements_are_ints (void) const; -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); -// For now, only define for floating point types. However, we only -// need range as a temporary local variable in make_float_range -// in ov.cc. + // For now, only define for floating point types. However, we only + // need range as a temporary local variable in make_float_range + // in ov.cc. #if 0 -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); #endif -template <> OCTAVE_API bool range::is_storable (void) const; -template <> OCTAVE_API bool range::is_storable (void) const; + template <> OCTAVE_API bool range::is_storable (void) const; + template <> OCTAVE_API bool range::is_storable (void) const; -template <> OCTAVE_API octave_idx_type range::nnz (void) const; -template <> OCTAVE_API octave_idx_type range::nnz (void) const; + template <> OCTAVE_API octave_idx_type range::nnz (void) const; + template <> OCTAVE_API octave_idx_type range::nnz (void) const; OCTAVE_END_NAMESPACE(octave) -class -Range -{ -public: - - OCTAVE_DEPRECATED (7, "use the 'octave::range' class instead") - Range (void) - : m_base (0), m_limit (0), m_inc (0), m_numel (0) - { } - - // Assume range is already properly constructed, so just copy internal - // values. However, we set LIMIT to the computed final value because - // that mimics the behavior of the other Range class constructors that - // reset limit to the computed final value. - - OCTAVE_DEPRECATED (7, "use the 'octave::range' class instead") - Range (const octave::range& r) - : m_base (r.base ()), m_limit (r.final_value ()), m_inc (r.increment ()), - m_numel (r.numel ()) - { } - - Range (const Range& r) = default; - - Range& operator = (const Range& r) = default; - - ~Range (void) = default; - - OCTAVE_DEPRECATED (7, "use the 'octave::range' class instead") - Range (double b, double l) - : m_base (b), m_limit (l), m_inc (1), m_numel (numel_internal ()) - { - if (! octave::math::isinf (m_limit)) - m_limit = limit_internal (); - } - - OCTAVE_DEPRECATED (7, "use the 'octave::range' class instead") - Range (double b, double l, double i) - : m_base (b), m_limit (l), m_inc (i), m_numel (numel_internal ()) - { - if (! octave::math::isinf (m_limit)) - m_limit = limit_internal (); - } - - // NOTE: The following constructor may be deprecated and removed after - // the arithmetic operators are removed. - - // For operators' usage (to preserve element count) and to create - // constant row vectors (obsolete usage). - - OCTAVE_DEPRECATED (7, "use the 'octave::range' class instead") - Range (double b, double i, octave_idx_type n) - : m_base (b), m_limit (b + (n-1) * i), m_inc (i), m_numel (n) - { - if (! octave::math::isinf (m_limit)) - m_limit = limit_internal (); - } - - // The range has a finite number of elements. - bool ok (void) const - { - return (octave::math::isfinite (m_limit) - && (m_numel >= 0 || m_numel == -2)); - } - - double base (void) const { return m_base; } - double limit (void) const { return m_limit; } - double inc (void) const { return m_inc; } - double increment (void) const { return m_inc; } - - // We adjust the limit to be the final value, so return that. We - // could introduce a new variable to store the final value separately, - // but it seems like that would just add confusion. If we changed - // the meaning of the limit function, we would change the behavior of - // programs that expect limit to be the final value instead of the - // value of the limit when the range was created. This problem will - // be fixed with the new template range class. - double final_value (void) const { return m_limit; } - - octave_idx_type numel (void) const { return m_numel; } - - dim_vector dims (void) const { return dim_vector (1, m_numel); } - - octave_idx_type rows (void) const { return 1; } - - octave_idx_type cols (void) const { return numel (); } - octave_idx_type columns (void) const { return numel (); } - - bool isempty (void) const { return numel () == 0; } - - OCTAVE_API bool all_elements_are_ints (void) const; - - OCTAVE_API Matrix matrix_value (void) const; - - OCTAVE_API double min (void) const; - OCTAVE_API double max (void) const; - - OCTAVE_API void sort_internal (bool ascending = true); - OCTAVE_API void sort_internal (Array& sidx, bool ascending = true); - - OCTAVE_API Matrix diag (octave_idx_type k = 0) const; - - OCTAVE_API Range sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const; - OCTAVE_API Range sort (Array& sidx, octave_idx_type dim = 0, - sortmode mode = ASCENDING) const; - - OCTAVE_API sortmode issorted (sortmode mode = ASCENDING) const; - - OCTAVE_API octave_idx_type nnz (void) const; - - // Support for single-index subscripting, without generating matrix cache. - - OCTAVE_API double checkelem (octave_idx_type i) const; - OCTAVE_API double checkelem (octave_idx_type i, octave_idx_type j) const; - - OCTAVE_API double elem (octave_idx_type i) const; - double elem (octave_idx_type /* i */, octave_idx_type j) const - { return elem (j); } - - double operator () (octave_idx_type i) const { return elem (i); } - double operator () (octave_idx_type i, octave_idx_type j) const - { return elem (i, j); } - - OCTAVE_API Array index (const octave::idx_vector& i) const; - - OCTAVE_API void set_base (double b); - - OCTAVE_API void set_limit (double l); - - OCTAVE_API void set_inc (double i); - - friend OCTAVE_API std::ostream& operator << (std::ostream& os, - const Range& r); - friend OCTAVE_API std::istream& operator >> (std::istream& is, Range& r); - - friend OCTAVE_API Range operator - (const Range& r); - friend OCTAVE_API Range operator + (double x, const Range& r); - friend OCTAVE_API Range operator + (const Range& r, double x); - friend OCTAVE_API Range operator - (double x, const Range& r); - friend OCTAVE_API Range operator - (const Range& r, double x); - friend OCTAVE_API Range operator * (double x, const Range& r); - friend OCTAVE_API Range operator * (const Range& r, double x); - -private: - - double m_base; - double m_limit; - double m_inc; - - octave_idx_type m_numel; - - OCTAVE_API octave_idx_type numel_internal (void) const; - - OCTAVE_API double limit_internal (void) const; - - OCTAVE_API void init (void); - -protected: - - // NOTE: The following constructor may be removed when the arithmetic - // operators are removed. - - // For operators' usage (to allow all values to be set directly). - Range (double b, double l, double i, octave_idx_type n) - : m_base (b), m_limit (l), m_inc (i), m_numel (n) - { } -}; - -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable") -extern OCTAVE_API Range operator - (const Range& r); - -OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable") -extern OCTAVE_API Range operator + (double x, const Range& r); - -OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable") -extern OCTAVE_API Range operator + (const Range& r, double x); - -OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable") -extern OCTAVE_API Range operator - (double x, const Range& r); - -OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable") -extern OCTAVE_API Range operator - (const Range& r, double x); - -OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable") -extern OCTAVE_API Range operator * (double x, const Range& r); - -OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable") -extern OCTAVE_API Range operator * (const Range& r, double x); #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 liboctave/numeric/CollocWt.h --- a/liboctave/numeric/CollocWt.h Tue Dec 06 14:53:00 2022 -0500 +++ b/liboctave/numeric/CollocWt.h Tue Dec 06 15:45:27 2022 -0500 @@ -209,9 +209,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::CollocWt' instead") -typedef octave::CollocWt CollocWt; #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 liboctave/numeric/oct-convn.h --- a/liboctave/numeric/oct-convn.h Tue Dec 06 14:53:00 2022 -0500 +++ b/liboctave/numeric/oct-convn.h Tue Dec 06 15:45:27 2022 -0500 @@ -158,152 +158,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline NDArray -convn (const NDArray& a, const NDArray& b, convn_type ct) -{ - return octave::convn (a, b, static_cast (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline Matrix -convn (const Matrix& a, const Matrix& b, convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline Matrix -convn (const Matrix& a, const ColumnVector& c, const RowVector& r, - convn_type ct) -{ - return octave::convn (a, c, r, octave::convert_enum (ct)); -} - -// double complex X double real - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline ComplexNDArray -convn (const ComplexNDArray& a, const NDArray& b, convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline ComplexMatrix -convn (const ComplexMatrix& a, const Matrix& b, convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline ComplexMatrix -convn (const ComplexMatrix& a, const ColumnVector& c, const RowVector& r, - convn_type ct) -{ - return octave::convn (a, c, r, octave::convert_enum (ct)); -} - -// double complex X double complex - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline ComplexNDArray -convn (const ComplexNDArray& a, const ComplexNDArray& b, convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline ComplexMatrix -convn (const ComplexMatrix& a, const ComplexMatrix& b, convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline ComplexMatrix -convn (const ComplexMatrix& a, const ComplexColumnVector& c, - const ComplexRowVector& r, convn_type ct) -{ - return octave::convn (a, c, r, octave::convert_enum (ct)); -} - -// float real X float real - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatNDArray -convn (const FloatNDArray& a, const FloatNDArray& b, convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatMatrix -convn (const FloatMatrix& a, const FloatMatrix& b, convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatMatrix -convn (const FloatMatrix& a, const FloatColumnVector& c, - const FloatRowVector& r, convn_type ct) -{ - return octave::convn (a, c, r, octave::convert_enum (ct)); -} - -// float complex X float real - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatComplexNDArray -convn (const FloatComplexNDArray& a, const FloatNDArray& b, - convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatComplexMatrix -convn (const FloatComplexMatrix& a, const FloatMatrix& b, - convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatComplexMatrix -convn (const FloatComplexMatrix& a, const FloatColumnVector& c, - const FloatRowVector& r, convn_type ct) -{ - return octave::convn (a, c, r, octave::convert_enum (ct)); -} - -// float complex X float complex - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatComplexNDArray -convn (const FloatComplexNDArray& a, const FloatComplexNDArray& b, - convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatComplexMatrix -convn (const FloatComplexMatrix& a, const FloatComplexMatrix& b, - convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatComplexMatrix -convn (const FloatComplexMatrix& a, const FloatComplexColumnVector& c, - const FloatComplexRowVector& r, convn_type ct) -{ - return octave::convn (a, c, r, octave::convert_enum (ct)); -} #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 liboctave/numeric/oct-norm.cc --- a/liboctave/numeric/oct-norm.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/liboctave/numeric/oct-norm.cc Tue Dec 06 15:45:27 2022 -0500 @@ -65,261 +65,261 @@ OCTAVE_BEGIN_NAMESPACE(octave) -// Theory: norm accumulator is an object that has an accum method able -// to handle both real and complex element, and a cast operator -// returning the intermediate norm. Reference: Higham, N. "Estimating -// the Matrix p-Norm." Numer. Math. 62, 539-555, 1992. + // Theory: norm accumulator is an object that has an accum method able + // to handle both real and complex element, and a cast operator + // returning the intermediate norm. Reference: Higham, N. "Estimating + // the Matrix p-Norm." Numer. Math. 62, 539-555, 1992. -// norm accumulator for the p-norm -template -class norm_accumulator_p -{ -public: - norm_accumulator_p () { } // we need this one for Array - norm_accumulator_p (R pp) : m_p(pp), m_scl(0), m_sum(1) { } + // norm accumulator for the p-norm + template + class norm_accumulator_p + { + public: + norm_accumulator_p () { } // we need this one for Array + norm_accumulator_p (R pp) : m_p(pp), m_scl(0), m_sum(1) { } - template - void accum (U val) - { - octave_quit (); - R t = std::abs (val); - if (m_scl == t) // we need this to handle Infs properly - m_sum += 1; - else if (m_scl < t) - { - m_sum *= std::pow (m_scl/t, m_p); + template + void accum (U val) + { + octave_quit (); + R t = std::abs (val); + if (m_scl == t) // we need this to handle Infs properly m_sum += 1; - m_scl = t; - } - else if (t != 0) - m_sum += std::pow (t/m_scl, m_p); - } + else if (m_scl < t) + { + m_sum *= std::pow (m_scl/t, m_p); + m_sum += 1; + m_scl = t; + } + else if (t != 0) + m_sum += std::pow (t/m_scl, m_p); + } + + operator R () { return m_scl * std::pow (m_sum, 1/m_p); } - operator R () { return m_scl * std::pow (m_sum, 1/m_p); } + private: + R m_p, m_scl, m_sum; + }; -private: - R m_p, m_scl, m_sum; -}; + // norm accumulator for the minus p-pseudonorm + template + class norm_accumulator_mp + { + public: + norm_accumulator_mp () { } // we need this one for Array + norm_accumulator_mp (R pp) : m_p(pp), m_scl(0), m_sum(1) { } -// norm accumulator for the minus p-pseudonorm -template -class norm_accumulator_mp -{ -public: - norm_accumulator_mp () { } // we need this one for Array - norm_accumulator_mp (R pp) : m_p(pp), m_scl(0), m_sum(1) { } + template + void accum (U val) + { + octave_quit (); + R t = 1 / std::abs (val); + if (m_scl == t) + m_sum += 1; + else if (m_scl < t) + { + m_sum *= std::pow (m_scl/t, m_p); + m_sum += 1; + m_scl = t; + } + else if (t != 0) + m_sum += std::pow (t/m_scl, m_p); + } - template - void accum (U val) + operator R () { return m_scl * std::pow (m_sum, -1/m_p); } + + private: + R m_p, m_scl, m_sum; + }; + + // norm accumulator for the 2-norm (euclidean) + template + class norm_accumulator_2 { - octave_quit (); - R t = 1 / std::abs (val); - if (m_scl == t) - m_sum += 1; - else if (m_scl < t) - { - m_sum *= std::pow (m_scl/t, m_p); + public: + norm_accumulator_2 () : m_scl(0), m_sum(1) { } + + void accum (R val) + { + R t = std::abs (val); + if (m_scl == t) m_sum += 1; - m_scl = t; - } - else if (t != 0) - m_sum += std::pow (t/m_scl, m_p); - } + else if (m_scl < t) + { + m_sum *= pow2 (m_scl/t); + m_sum += 1; + m_scl = t; + } + else if (t != 0) + m_sum += pow2 (t/m_scl); + } - operator R () { return m_scl * std::pow (m_sum, -1/m_p); } + void accum (std::complex val) + { + accum (val.real ()); + accum (val.imag ()); + } + + operator R () { return m_scl * std::sqrt (m_sum); } + + private: + static inline R pow2 (R x) { return x*x; } + + //-------- -private: - R m_p, m_scl, m_sum; -}; + R m_scl, m_sum; + }; -// norm accumulator for the 2-norm (euclidean) -template -class norm_accumulator_2 -{ -public: - norm_accumulator_2 () : m_scl(0), m_sum(1) { } + // norm accumulator for the 1-norm (city metric) + template + class norm_accumulator_1 + { + public: + norm_accumulator_1 () : m_sum (0) { } + template + void accum (U val) + { + m_sum += std::abs (val); + } - void accum (R val) + operator R () { return m_sum; } + + private: + R m_sum; + }; + + // norm accumulator for the inf-norm (max metric) + template + class norm_accumulator_inf { - R t = std::abs (val); - if (m_scl == t) - m_sum += 1; - else if (m_scl < t) - { - m_sum *= pow2 (m_scl/t); - m_sum += 1; - m_scl = t; - } - else if (t != 0) - m_sum += pow2 (t/m_scl); - } + public: + norm_accumulator_inf () : m_max (0) { } + template + void accum (U val) + { + if (math::isnan (val)) + m_max = numeric_limits::NaN (); + else + m_max = std::max (m_max, std::abs (val)); + } + + operator R () { return m_max; } - void accum (std::complex val) + private: + R m_max; + }; + + // norm accumulator for the -inf pseudonorm (min abs value) + template + class norm_accumulator_minf { - accum (val.real ()); - accum (val.imag ()); - } + public: + norm_accumulator_minf () : m_min (numeric_limits::Inf ()) { } + template + void accum (U val) + { + if (math::isnan (val)) + m_min = numeric_limits::NaN (); + else + m_min = std::min (m_min, std::abs (val)); + } - operator R () { return m_scl * std::sqrt (m_sum); } - -private: - static inline R pow2 (R x) { return x*x; } + operator R () { return m_min; } - //-------- - - R m_scl, m_sum; -}; + private: + R m_min; + }; -// norm accumulator for the 1-norm (city metric) -template -class norm_accumulator_1 -{ -public: - norm_accumulator_1 () : m_sum (0) { } - template - void accum (U val) + // norm accumulator for the 0-pseudonorm (hamming distance) + template + class norm_accumulator_0 { - m_sum += std::abs (val); + public: + norm_accumulator_0 () : m_num (0) { } + template + void accum (U val) + { + if (val != static_cast (0)) ++m_num; + } + + operator R () { return m_num; } + + private: + unsigned int m_num; + }; + + // OK, we're armed :) Now let's go for the fun + + template + inline void vector_norm (const Array& v, R& res, ACC acc) + { + for (octave_idx_type i = 0; i < v.numel (); i++) + acc.accum (v(i)); + + res = acc; } - operator R () { return m_sum; } - -private: - R m_sum; -}; + // dense versions + template + void column_norms (const MArray& m, MArray& res, ACC acc) + { + res = MArray (dim_vector (1, m.columns ())); + for (octave_idx_type j = 0; j < m.columns (); j++) + { + ACC accj = acc; + for (octave_idx_type i = 0; i < m.rows (); i++) + accj.accum (m(i, j)); -// norm accumulator for the inf-norm (max metric) -template -class norm_accumulator_inf -{ -public: - norm_accumulator_inf () : m_max (0) { } - template - void accum (U val) - { - if (math::isnan (val)) - m_max = numeric_limits::NaN (); - else - m_max = std::max (m_max, std::abs (val)); + res.xelem (j) = accj; + } } - operator R () { return m_max; } - -private: - R m_max; -}; - -// norm accumulator for the -inf pseudonorm (min abs value) -template -class norm_accumulator_minf -{ -public: - norm_accumulator_minf () : m_min (numeric_limits::Inf ()) { } - template - void accum (U val) + template + void row_norms (const MArray& m, MArray& res, ACC acc) { - if (math::isnan (val)) - m_min = numeric_limits::NaN (); - else - m_min = std::min (m_min, std::abs (val)); - } - - operator R () { return m_min; } + res = MArray (dim_vector (m.rows (), 1)); + std::vector acci (m.rows (), acc); + for (octave_idx_type j = 0; j < m.columns (); j++) + { + for (octave_idx_type i = 0; i < m.rows (); i++) + acci[i].accum (m(i, j)); + } -private: - R m_min; -}; - -// norm accumulator for the 0-pseudonorm (hamming distance) -template -class norm_accumulator_0 -{ -public: - norm_accumulator_0 () : m_num (0) { } - template - void accum (U val) - { - if (val != static_cast (0)) ++m_num; + for (octave_idx_type i = 0; i < m.rows (); i++) + res.xelem (i) = acci[i]; } - operator R () { return m_num; } - -private: - unsigned int m_num; -}; - -// OK, we're armed :) Now let's go for the fun - -template -inline void vector_norm (const Array& v, R& res, ACC acc) -{ - for (octave_idx_type i = 0; i < v.numel (); i++) - acc.accum (v(i)); + // sparse versions + template + void column_norms (const MSparse& m, MArray& res, ACC acc) + { + res = MArray (dim_vector (1, m.columns ())); + for (octave_idx_type j = 0; j < m.columns (); j++) + { + ACC accj = acc; + for (octave_idx_type k = m.cidx (j); k < m.cidx (j+1); k++) + accj.accum (m.data (k)); - res = acc; -} - -// dense versions -template -void column_norms (const MArray& m, MArray& res, ACC acc) -{ - res = MArray (dim_vector (1, m.columns ())); - for (octave_idx_type j = 0; j < m.columns (); j++) - { - ACC accj = acc; - for (octave_idx_type i = 0; i < m.rows (); i++) - accj.accum (m(i, j)); - - res.xelem (j) = accj; - } -} + res.xelem (j) = accj; + } + } -template -void row_norms (const MArray& m, MArray& res, ACC acc) -{ - res = MArray (dim_vector (m.rows (), 1)); - std::vector acci (m.rows (), acc); - for (octave_idx_type j = 0; j < m.columns (); j++) - { - for (octave_idx_type i = 0; i < m.rows (); i++) - acci[i].accum (m(i, j)); - } - - for (octave_idx_type i = 0; i < m.rows (); i++) - res.xelem (i) = acci[i]; -} + template + void row_norms (const MSparse& m, MArray& res, ACC acc) + { + res = MArray (dim_vector (m.rows (), 1)); + std::vector acci (m.rows (), acc); + for (octave_idx_type j = 0; j < m.columns (); j++) + { + for (octave_idx_type k = m.cidx (j); k < m.cidx (j+1); k++) + acci[m.ridx (k)].accum (m.data (k)); + } -// sparse versions -template -void column_norms (const MSparse& m, MArray& res, ACC acc) -{ - res = MArray (dim_vector (1, m.columns ())); - for (octave_idx_type j = 0; j < m.columns (); j++) - { - ACC accj = acc; - for (octave_idx_type k = m.cidx (j); k < m.cidx (j+1); k++) - accj.accum (m.data (k)); - - res.xelem (j) = accj; - } -} + for (octave_idx_type i = 0; i < m.rows (); i++) + res.xelem (i) = acci[i]; + } -template -void row_norms (const MSparse& m, MArray& res, ACC acc) -{ - res = MArray (dim_vector (m.rows (), 1)); - std::vector acci (m.rows (), acc); - for (octave_idx_type j = 0; j < m.columns (); j++) - { - for (octave_idx_type k = m.cidx (j); k < m.cidx (j+1); k++) - acci[m.ridx (k)].accum (m.data (k)); - } - - for (octave_idx_type i = 0; i < m.rows (); i++) - res.xelem (i) = acci[i]; -} - -// now the dispatchers + // now the dispatchers #define DEFINE_DISPATCHER(FCN_NAME, ARG_TYPE, RES_TYPE) \ template \ RES_TYPE FCN_NAME (const ARG_TYPE& v, R p) \ @@ -345,224 +345,216 @@ return res; \ } -DEFINE_DISPATCHER (vector_norm, MArray, R) -DEFINE_DISPATCHER (column_norms, MArray, MArray) -DEFINE_DISPATCHER (row_norms, MArray, MArray) -DEFINE_DISPATCHER (column_norms, MSparse, MArray) -DEFINE_DISPATCHER (row_norms, MSparse, MArray) + DEFINE_DISPATCHER (vector_norm, MArray, R) + DEFINE_DISPATCHER (column_norms, MArray, MArray) + DEFINE_DISPATCHER (row_norms, MArray, MArray) + DEFINE_DISPATCHER (column_norms, MSparse, MArray) + DEFINE_DISPATCHER (row_norms, MSparse, MArray) -// The approximate subproblem in Higham's method. Find lambda and mu such -// that norm ([lambda, mu], p) == 1 and norm (y*lambda + col*mu, p) is -// maximized. -// Real version. As in Higham's paper. -template -static void -higham_subp (const ColVectorT& y, const ColVectorT& col, - octave_idx_type nsamp, R p, R& lambda, R& mu) -{ - R nrm = 0; - for (octave_idx_type i = 0; i < nsamp; i++) - { - octave_quit (); - R fi = i * static_cast (M_PI) / nsamp; - R lambda1 = cos (fi); - R mu1 = sin (fi); - R lmnr = std::pow (std::pow (std::abs (lambda1), p) + - std::pow (std::abs (mu1), p), 1/p); - lambda1 /= lmnr; mu1 /= lmnr; - R nrm1 = vector_norm (lambda1 * y + mu1 * col, p); - if (nrm1 > nrm) - { - lambda = lambda1; - mu = mu1; - nrm = nrm1; - } - } -} + // The approximate subproblem in Higham's method. Find lambda and mu such + // that norm ([lambda, mu], p) == 1 and norm (y*lambda + col*mu, p) is + // maximized. + // Real version. As in Higham's paper. + template + static void + higham_subp (const ColVectorT& y, const ColVectorT& col, + octave_idx_type nsamp, R p, R& lambda, R& mu) + { + R nrm = 0; + for (octave_idx_type i = 0; i < nsamp; i++) + { + octave_quit (); + R fi = i * static_cast (M_PI) / nsamp; + R lambda1 = cos (fi); + R mu1 = sin (fi); + R lmnr = std::pow (std::pow (std::abs (lambda1), p) + + std::pow (std::abs (mu1), p), 1/p); + lambda1 /= lmnr; mu1 /= lmnr; + R nrm1 = vector_norm (lambda1 * y + mu1 * col, p); + if (nrm1 > nrm) + { + lambda = lambda1; + mu = mu1; + nrm = nrm1; + } + } + } -// Complex version. Higham's paper does not deal with complex case, so we -// use a simple extension. First, guess the magnitudes as in real version, -// then try to rotate lambda to improve further. -template -static void -higham_subp (const ColVectorT& y, const ColVectorT& col, - octave_idx_type nsamp, R p, - std::complex& lambda, std::complex& mu) -{ - typedef std::complex CR; - R nrm = 0; - lambda = 1.0; - CR lamcu = lambda / std::abs (lambda); - // Probe magnitudes - for (octave_idx_type i = 0; i < nsamp; i++) - { - octave_quit (); - R fi = i * static_cast (M_PI) / nsamp; - R lambda1 = cos (fi); - R mu1 = sin (fi); - R lmnr = std::pow (std::pow (std::abs (lambda1), p) + - std::pow (std::abs (mu1), p), 1/p); - lambda1 /= lmnr; mu1 /= lmnr; - R nrm1 = vector_norm (lambda1 * lamcu * y + mu1 * col, p); - if (nrm1 > nrm) - { - lambda = lambda1 * lamcu; - mu = mu1; - nrm = nrm1; - } - } - R lama = std::abs (lambda); - // Probe orientation - for (octave_idx_type i = 0; i < nsamp; i++) - { - octave_quit (); - R fi = i * static_cast (M_PI) / nsamp; - lamcu = CR (cos (fi), sin (fi)); - R nrm1 = vector_norm (lama * lamcu * y + mu * col, p); - if (nrm1 > nrm) - { - lambda = lama * lamcu; - nrm = nrm1; - } - } -} + // Complex version. Higham's paper does not deal with complex case, so we + // use a simple extension. First, guess the magnitudes as in real version, + // then try to rotate lambda to improve further. + template + static void + higham_subp (const ColVectorT& y, const ColVectorT& col, + octave_idx_type nsamp, R p, + std::complex& lambda, std::complex& mu) + { + typedef std::complex CR; + R nrm = 0; + lambda = 1.0; + CR lamcu = lambda / std::abs (lambda); + // Probe magnitudes + for (octave_idx_type i = 0; i < nsamp; i++) + { + octave_quit (); + R fi = i * static_cast (M_PI) / nsamp; + R lambda1 = cos (fi); + R mu1 = sin (fi); + R lmnr = std::pow (std::pow (std::abs (lambda1), p) + + std::pow (std::abs (mu1), p), 1/p); + lambda1 /= lmnr; mu1 /= lmnr; + R nrm1 = vector_norm (lambda1 * lamcu * y + mu1 * col, p); + if (nrm1 > nrm) + { + lambda = lambda1 * lamcu; + mu = mu1; + nrm = nrm1; + } + } + R lama = std::abs (lambda); + // Probe orientation + for (octave_idx_type i = 0; i < nsamp; i++) + { + octave_quit (); + R fi = i * static_cast (M_PI) / nsamp; + lamcu = CR (cos (fi), sin (fi)); + R nrm1 = vector_norm (lama * lamcu * y + mu * col, p); + if (nrm1 > nrm) + { + lambda = lama * lamcu; + nrm = nrm1; + } + } + } -// the p-dual element (should work for both real and complex) -template -inline T elem_dual_p (T x, R p) -{ - return math::signum (x) * std::pow (std::abs (x), p-1); -} + // the p-dual element (should work for both real and complex) + template + inline T elem_dual_p (T x, R p) + { + return math::signum (x) * std::pow (std::abs (x), p-1); + } -// the VectorT is used for vectors, but actually it has to be -// a Matrix type to allow all the operations. For instance SparseMatrix -// does not support multiplication with column/row vectors. -// the dual vector -template -VectorT dual_p (const VectorT& x, R p, R q) -{ - VectorT res (x.dims ()); - for (octave_idx_type i = 0; i < x.numel (); i++) - res.xelem (i) = elem_dual_p (x(i), p); - return res / vector_norm (res, q); -} + // the VectorT is used for vectors, but actually it has to be + // a Matrix type to allow all the operations. For instance SparseMatrix + // does not support multiplication with column/row vectors. + // the dual vector + template + VectorT dual_p (const VectorT& x, R p, R q) + { + VectorT res (x.dims ()); + for (octave_idx_type i = 0; i < x.numel (); i++) + res.xelem (i) = elem_dual_p (x(i), p); + return res / vector_norm (res, q); + } -// Higham's hybrid method -template -R higham (const MatrixT& m, R p, R tol, int maxiter, - VectorT& x) -{ - x.resize (m.columns (), 1); - // the OSE part - VectorT y(m.rows (), 1, 0), z(m.rows (), 1); - typedef typename VectorT::element_type RR; - RR lambda = 0; - RR mu = 1; - for (octave_idx_type k = 0; k < m.columns (); k++) - { - octave_quit (); - VectorT col (m.column (k)); - if (k > 0) - higham_subp (y, col, 4*k, p, lambda, mu); - for (octave_idx_type i = 0; i < k; i++) - x(i) *= lambda; - x(k) = mu; - y = lambda * y + mu * col; - } - - // the PM part - x = x / vector_norm (x, p); - R q = p/(p-1); + // Higham's hybrid method + template + R higham (const MatrixT& m, R p, R tol, int maxiter, + VectorT& x) + { + x.resize (m.columns (), 1); + // the OSE part + VectorT y(m.rows (), 1, 0), z(m.rows (), 1); + typedef typename VectorT::element_type RR; + RR lambda = 0; + RR mu = 1; + for (octave_idx_type k = 0; k < m.columns (); k++) + { + octave_quit (); + VectorT col (m.column (k)); + if (k > 0) + higham_subp (y, col, 4*k, p, lambda, mu); + for (octave_idx_type i = 0; i < k; i++) + x(i) *= lambda; + x(k) = mu; + y = lambda * y + mu * col; + } - R gamma = 0, gamma1; - int iter = 0; - while (iter < maxiter) - { - octave_quit (); - y = m*x; - gamma1 = gamma; - gamma = vector_norm (y, p); - z = dual_p (y, p, q); - z = z.hermitian (); - z = z * m; + // the PM part + x = x / vector_norm (x, p); + R q = p/(p-1); - if (iter > 0 && (vector_norm (z, q) <= gamma - || (gamma - gamma1) <= tol*gamma)) - break; + R gamma = 0, gamma1; + int iter = 0; + while (iter < maxiter) + { + octave_quit (); + y = m*x; + gamma1 = gamma; + gamma = vector_norm (y, p); + z = dual_p (y, p, q); + z = z.hermitian (); + z = z * m; - z = z.hermitian (); - x = dual_p (z, q, p); - iter++; - } + if (iter > 0 && (vector_norm (z, q) <= gamma + || (gamma - gamma1) <= tol*gamma)) + break; - return gamma; -} + z = z.hermitian (); + x = dual_p (z, q, p); + iter++; + } -// derive column vector and SVD types + return gamma; + } -static const char *p_less1_gripe = "xnorm: p must be >= 1"; + // derive column vector and SVD types -// Static constant to control the maximum number of iterations. 100 seems to -// be a good value. Eventually, we can provide a means to change this -// constant from Octave. -static int max_norm_iter = 100; + static const char *p_less1_gripe = "xnorm: p must be >= 1"; -// version with SVD for dense matrices -template -R svd_matrix_norm (const MatrixT& m, R p, VectorT) -{ - // NOTE: The octave:: namespace tags are needed for the following - // function calls until the deprecated inline functions are removed - // from oct-norm.h. + // Static constant to control the maximum number of iterations. 100 seems to + // be a good value. Eventually, we can provide a means to change this + // constant from Octave. + static int max_norm_iter = 100; - R res = 0; - if (p == 2) - { - math::svd fact (m, math::svd::Type::sigma_only); - res = fact.singular_values () (0, 0); - } - else if (p == 1) - res = octave::xcolnorms (m, static_cast (1)).max (); - else if (lo_ieee_isinf (p) && p > 1) - res = octave::xrownorms (m, static_cast (1)).max (); - else if (p > 1) - { - VectorT x; - const R sqrteps = std::sqrt (std::numeric_limits::epsilon ()); - res = higham (m, p, sqrteps, max_norm_iter, x); - } - else - (*current_liboctave_error_handler) ("%s", p_less1_gripe); - - return res; -} + // version with SVD for dense matrices + template + R svd_matrix_norm (const MatrixT& m, R p, VectorT) + { + R res = 0; + if (p == 2) + { + math::svd fact (m, math::svd::Type::sigma_only); + res = fact.singular_values () (0, 0); + } + else if (p == 1) + res = xcolnorms (m, static_cast (1)).max (); + else if (lo_ieee_isinf (p) && p > 1) + res = xrownorms (m, static_cast (1)).max (); + else if (p > 1) + { + VectorT x; + const R sqrteps = std::sqrt (std::numeric_limits::epsilon ()); + res = higham (m, p, sqrteps, max_norm_iter, x); + } + else + (*current_liboctave_error_handler) ("%s", p_less1_gripe); -// SVD-free version for sparse matrices -template -R matrix_norm (const MatrixT& m, R p, VectorT) -{ - // NOTE: The octave:: namespace tags are needed for the following - // function calls until the deprecated inline functions are removed - // from oct-norm.h. + return res; + } - R res = 0; - if (p == 1) - res = octave::xcolnorms (m, static_cast (1)).max (); - else if (lo_ieee_isinf (p) && p > 1) - res = octave::xrownorms (m, static_cast (1)).max (); - else if (p > 1) - { - VectorT x; - const R sqrteps = std::sqrt (std::numeric_limits::epsilon ()); - res = higham (m, p, sqrteps, max_norm_iter, x); - } - else - (*current_liboctave_error_handler) ("%s", p_less1_gripe); + // SVD-free version for sparse matrices + template + R matrix_norm (const MatrixT& m, R p, VectorT) + { + R res = 0; + if (p == 1) + res = xcolnorms (m, static_cast (1)).max (); + else if (lo_ieee_isinf (p) && p > 1) + res = xrownorms (m, static_cast (1)).max (); + else if (p > 1) + { + VectorT x; + const R sqrteps = std::sqrt (std::numeric_limits::epsilon ()); + res = higham (m, p, sqrteps, max_norm_iter, x); + } + else + (*current_liboctave_error_handler) ("%s", p_less1_gripe); - return res; -} + return res; + } -// and finally, here's what we've promised in the header file + // and finally, here's what we've promised in the header file #define DEFINE_XNORM_FCNS(PREFIX, RTYPE) \ RTYPE xnorm (const PREFIX##ColumnVector& x, RTYPE p) \ @@ -582,21 +574,21 @@ return vector_norm (x, static_cast (2)); \ } -DEFINE_XNORM_FCNS(, double) -DEFINE_XNORM_FCNS(Complex, double) -DEFINE_XNORM_FCNS(Float, float) -DEFINE_XNORM_FCNS(FloatComplex, float) + DEFINE_XNORM_FCNS(, double) + DEFINE_XNORM_FCNS(Complex, double) + DEFINE_XNORM_FCNS(Float, float) + DEFINE_XNORM_FCNS(FloatComplex, float) -// this is needed to avoid copying the sparse matrix for xfrobnorm -template -inline void array_norm_2 (const T *v, octave_idx_type n, R& res) -{ - norm_accumulator_2 acc; - for (octave_idx_type i = 0; i < n; i++) - acc.accum (v[i]); + // this is needed to avoid copying the sparse matrix for xfrobnorm + template + inline void array_norm_2 (const T *v, octave_idx_type n, R& res) + { + norm_accumulator_2 acc; + for (octave_idx_type i = 0; i < n; i++) + acc.accum (v[i]); - res = acc; -} + res = acc; + } #define DEFINE_XNORM_SPARSE_FCNS(PREFIX, RTYPE) \ RTYPE xnorm (const Sparse##PREFIX##Matrix& x, RTYPE p) \ @@ -610,8 +602,8 @@ return res; \ } -DEFINE_XNORM_SPARSE_FCNS(, double) -DEFINE_XNORM_SPARSE_FCNS(Complex, double) + DEFINE_XNORM_SPARSE_FCNS(, double) + DEFINE_XNORM_SPARSE_FCNS(Complex, double) #define DEFINE_COLROW_NORM_FCNS(PREFIX, RPREFIX, RTYPE) \ RPREFIX##RowVector \ @@ -625,12 +617,12 @@ return row_norms (m, p); \ } \ -DEFINE_COLROW_NORM_FCNS(,, double) -DEFINE_COLROW_NORM_FCNS(Complex,, double) -DEFINE_COLROW_NORM_FCNS(Float, Float, float) -DEFINE_COLROW_NORM_FCNS(FloatComplex, Float, float) + DEFINE_COLROW_NORM_FCNS(, , double) + DEFINE_COLROW_NORM_FCNS(Complex, , double) + DEFINE_COLROW_NORM_FCNS(Float, Float, float) + DEFINE_COLROW_NORM_FCNS(FloatComplex, Float, float) -DEFINE_COLROW_NORM_FCNS(Sparse,, double) -DEFINE_COLROW_NORM_FCNS(SparseComplex,, double) + DEFINE_COLROW_NORM_FCNS(Sparse, , double) + DEFINE_COLROW_NORM_FCNS(SparseComplex, , double) OCTAVE_END_NAMESPACE(octave) diff -r 29d734430e5f -r deb553ac2c54 liboctave/numeric/oct-norm.h --- a/liboctave/numeric/oct-norm.h Tue Dec 06 14:53:00 2022 -0500 +++ b/liboctave/numeric/oct-norm.h Tue Dec 06 15:45:27 2022 -0500 @@ -32,14 +32,6 @@ #include "oct-cmplx.h" -// The remaining includes can be removed when the deprecated functions -// at the end of this file are removed. - -#include "dColVector.h" -#include "dRowVector.h" -#include "fColVector.h" -#include "fRowVector.h" - OCTAVE_BEGIN_NAMESPACE(octave) extern OCTAVE_API double xnorm (const ColumnVector&, double p = 2); @@ -88,198 +80,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const ColumnVector& v, double p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const RowVector& v, double p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const Matrix& m, double p = 2) -{ - return octave::xnorm (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead") -inline double xfrobnorm (const Matrix& m) -{ - return octave::xfrobnorm (m); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const ComplexColumnVector& v, double p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const ComplexRowVector& v, double p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const ComplexMatrix& m, double p = 2) -{ - return octave::xnorm (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead") -inline double xfrobnorm (const ComplexMatrix& m) -{ - return octave::xfrobnorm (m); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline float xnorm (const FloatColumnVector& v, float p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline float xnorm (const FloatRowVector& v, float p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline float xnorm (const FloatMatrix& m, float p = 2) -{ - return octave::xnorm (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead") -inline float xfrobnorm (const FloatMatrix& m) -{ - return octave::xfrobnorm (m); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline float xnorm (const FloatComplexColumnVector& v, float p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline float xnorm (const FloatComplexRowVector& v, float p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline float xnorm (const FloatComplexMatrix& m, float p = 2) -{ - return octave::xnorm (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead") -inline float xfrobnorm (const FloatComplexMatrix& m) -{ - return octave::xfrobnorm (m); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const SparseMatrix& m, double p = 2) -{ - return octave::xnorm (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead") -inline double xfrobnorm (const SparseMatrix& m) -{ - return octave::xfrobnorm (m); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const SparseComplexMatrix& m, double p = 2) -{ - return octave::xnorm (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead") -inline double xfrobnorm (const SparseComplexMatrix& m) -{ - return octave::xfrobnorm (m); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead") -inline RowVector xcolnorms (const Matrix& m, double p = 2) -{ - return octave::xcolnorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead") -inline ColumnVector xrownorms (const Matrix& m, double p = 2) -{ - return octave::xrownorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead") -inline RowVector xcolnorms (const ComplexMatrix& m, double p = 2) -{ - return octave::xcolnorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead") -inline ColumnVector xrownorms (const ComplexMatrix& m, double p = 2) -{ - return octave::xrownorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead") -inline FloatRowVector xcolnorms (const FloatMatrix& m, float p = 2) -{ - return octave::xcolnorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead") -inline FloatColumnVector xrownorms (const FloatMatrix& m, float p = 2) -{ - return octave::xrownorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead") -inline FloatRowVector xcolnorms (const FloatComplexMatrix& m, float p = 2) -{ - return octave::xcolnorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead") -inline FloatColumnVector xrownorms (const FloatComplexMatrix& m, float p = 2) -{ - return octave::xrownorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead") -inline RowVector xcolnorms (const SparseMatrix& m, double p = 2) -{ - return octave::xcolnorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead") -inline ColumnVector xrownorms (const SparseMatrix& m, double p = 2) -{ - return octave::xrownorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead") -inline RowVector xcolnorms (const SparseComplexMatrix& m, double p = 2) -{ - return octave::xcolnorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead") -inline ColumnVector xrownorms (const SparseComplexMatrix& m, double p = 2) -{ - return octave::xrownorms (m, p); -} #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 liboctave/numeric/oct-spparms.h --- a/liboctave/numeric/oct-spparms.h Tue Dec 06 14:53:00 2022 -0500 +++ b/liboctave/numeric/oct-spparms.h Tue Dec 06 15:45:27 2022 -0500 @@ -116,9 +116,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::sparse_params' instead") -typedef octave::sparse_params octave_sparse_params; #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 liboctave/util/lo-ieee.h --- a/liboctave/util/lo-ieee.h Tue Dec 06 14:53:00 2022 -0500 +++ b/liboctave/util/lo-ieee.h Tue Dec 06 15:45:27 2022 -0500 @@ -156,17 +156,4 @@ #endif -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use '__lo_ieee_isfinite' instead") -inline int __lo_ieee_finite (double x) { return __lo_ieee_isfinite (x); } - -OCTAVE_DEPRECATED (7, "use '__lo_ieee_float_isfinite' instead") -inline int __lo_ieee_float_finite (float x) -{ return __lo_ieee_float_isfinite (x); } - -#define lo_ieee_finite(x) lo_ieee_isfinite(x) - #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 liboctave/util/lo-utils.cc --- a/liboctave/util/lo-utils.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/liboctave/util/lo-utils.cc Tue Dec 06 15:45:27 2022 -0500 @@ -47,473 +47,479 @@ OCTAVE_BEGIN_NAMESPACE(octave) -bool is_int_or_inf_or_nan (double x) -{ - return math::isnan (x) || math::x_nint (x) == x; -} + bool is_int_or_inf_or_nan (double x) + { + return math::isnan (x) || math::x_nint (x) == x; + } + + bool too_large_for_float (double x) + { + return (math::isfinite (x) + && fabs (x) > std::numeric_limits::max ()); + } + + bool too_large_for_float (const Complex& x) + { + return (too_large_for_float (x.real ()) + || too_large_for_float (x.imag ())); + } + + bool is_int_or_inf_or_nan (float x) + { + return math::isnan (x) || math::x_nint (x) == x; + } -bool too_large_for_float (double x) -{ - return (math::isfinite (x) - && fabs (x) > std::numeric_limits::max ()); -} + // Save a string. + + char * strsave (const char *s) + { + if (! s) + return nullptr; -bool too_large_for_float (const Complex& x) -{ - return (too_large_for_float (x.real ()) - || too_large_for_float (x.imag ())); -} + int len = strlen (s); + char *tmp = new char [len+1]; + tmp = strcpy (tmp, s); + return tmp; + } + + std::string fgets (FILE *f) + { + bool eof; + return fgets (f, eof); + } + + std::string fgets (FILE *f, bool& eof) + { + eof = false; + + std::string retval; -bool is_int_or_inf_or_nan (float x) -{ - return math::isnan (x) || math::x_nint (x) == x; -} + int grow_size = 1024; + int max_size = grow_size; + + char *buf = static_cast (std::malloc (max_size)); + if (! buf) + (*current_liboctave_error_handler) ("octave_fgets: unable to malloc %d bytes", max_size); -// Save a string. + char *bufptr = buf; + int len = 0; -char * strsave (const char *s) -{ - if (! s) - return nullptr; + do + { + if (std::fgets (bufptr, grow_size, f)) + { + len = strlen (bufptr); - int len = strlen (s); - char *tmp = new char [len+1]; - tmp = strcpy (tmp, s); - return tmp; -} + if (len == grow_size - 1) + { + int tmp = bufptr - buf + grow_size - 1; + grow_size *= 2; + max_size += grow_size; + auto tmpbuf = static_cast (std::realloc (buf, max_size)); + if (! tmpbuf) + { + free (buf); + (*current_liboctave_error_handler) ("octave_fgets: unable to realloc %d bytes", max_size); + } + buf = tmpbuf; + bufptr = buf + tmp; -std::string fgets (FILE *f) -{ - bool eof; - return fgets (f, eof); -} + if (*(bufptr-1) == '\n') + { + *bufptr = '\0'; + retval = buf; + } + } + else if (bufptr[len-1] != '\n') + { + bufptr[len++] = '\n'; + bufptr[len] = '\0'; + retval = buf; + } + else + retval = buf; + } + else + { + if (len == 0) + { + eof = true; -std::string fgets (FILE *f, bool& eof) -{ - eof = false; + free (buf); + + buf = nullptr; + } + + break; + } + } + while (retval.empty ()); + + free (buf); + + octave_quit (); - std::string retval; + return retval; + } - int grow_size = 1024; - int max_size = grow_size; + std::string fgetl (FILE *f) + { + bool eof; + return fgetl (f, eof); + } + + std::string fgetl (FILE *f, bool& eof) + { + std::string retval = fgets (f, eof); + + if (! retval.empty () && retval.back () == '\n') + retval.pop_back (); - char *buf = static_cast (std::malloc (max_size)); - if (! buf) - (*current_liboctave_error_handler) ("octave_fgets: unable to malloc %d bytes", max_size); + return retval; + } + + template + T + read_value (std::istream& is) + { + T retval; + is >> retval; + return retval; + } - char *bufptr = buf; - int len = 0; + template OCTAVE_API bool read_value (std::istream& is); + template OCTAVE_API octave_int8 read_value (std::istream& is); + template OCTAVE_API octave_int16 read_value (std::istream& is); + template OCTAVE_API octave_int32 read_value (std::istream& is); + template OCTAVE_API octave_int64 read_value (std::istream& is); + template OCTAVE_API octave_uint8 read_value (std::istream& is); + template OCTAVE_API octave_uint16 read_value (std::istream& is); + template OCTAVE_API octave_uint32 read_value (std::istream& is); + template OCTAVE_API octave_uint64 read_value (std::istream& is); - do - { - if (std::fgets (bufptr, grow_size, f)) + // Note that the caller is responsible for repositioning the stream on + // failure. + + template + T + read_inf_nan_na (std::istream& is, char c0) + { + T val = 0.0; + + switch (c0) + { + case 'i': case 'I': { - len = strlen (bufptr); - - if (len == grow_size - 1) + char c1 = is.get (); + if (c1 == 'n' || c1 == 'N') { - int tmp = bufptr - buf + grow_size - 1; - grow_size *= 2; - max_size += grow_size; - auto tmpbuf = static_cast (std::realloc (buf, max_size)); - if (! tmpbuf) + char c2 = is.get (); + if (c2 == 'f' || c2 == 'F') { - free (buf); - (*current_liboctave_error_handler) ("octave_fgets: unable to realloc %d bytes", max_size); + val = std::numeric_limits::infinity (); + is.peek (); // Potentially set EOF bit } - buf = tmpbuf; - bufptr = buf + tmp; + else + is.setstate (std::ios::failbit); + } + else + is.setstate (std::ios::failbit); + } + break; - if (*(bufptr-1) == '\n') + case 'n': case 'N': + { + char c1 = is.get (); + if (c1 == 'a' || c1 == 'A') + { + char c2 = is.get (); + if (c2 == 'n' || c2 == 'N') { - *bufptr = '\0'; - retval = buf; + val = std::numeric_limits::quiet_NaN (); + is.peek (); // Potentially set EOF bit + } + else + { + val = numeric_limits::NA (); + if (c2 != std::istream::traits_type::eof ()) + is.putback (c2); + else + is.clear (is.rdstate () & ~std::ios::failbit); } } - else if (bufptr[len-1] != '\n') - { - bufptr[len++] = '\n'; - bufptr[len] = '\0'; - retval = buf; - } else - retval = buf; + is.setstate (std::ios::failbit); } - else + break; + + default: + (*current_liboctave_error_handler) + ("read_inf_nan_na: invalid character '%c'", c0); + } + + return val; + } + + // Read a double value. Discard any sign on NaN and NA. + + template + double + read_fp_value (std::istream& is) + { + T val = 0.0; + + // FIXME: resetting stream position is likely to fail unless we are + // reading from a file. + std::streampos pos = is.tellg (); + + is >> std::ws; // skip through whitespace and advance stream pointer + + bool neg = false; + char c1 = is.get (); + switch (c1) + { + case '-': + neg = true; + OCTAVE_FALLTHROUGH; + + case '+': { - if (len == 0) + char c2 = 0; + c2 = is.get (); + if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N') + val = read_inf_nan_na (is, c2); + else if (isspace (c2)) + is.setstate (std::ios::failbit); + else { - eof = true; - - free (buf); - - buf = nullptr; + is.putback (c2); + is >> val; } - break; + if (neg && ! math::isnan (val) && ! is.fail ()) + val = -val; } - } - while (retval.empty ()); - - free (buf); - - octave_quit (); - - return retval; -} + break; -std::string fgetl (FILE *f) -{ - bool eof; - return fgetl (f, eof); -} + case 'i': case 'I': + case 'n': case 'N': + val = read_inf_nan_na (is, c1); + break; -std::string fgetl (FILE *f, bool& eof) -{ - std::string retval = fgets (f, eof); - - if (! retval.empty () && retval.back () == '\n') - retval.pop_back (); - - return retval; -} + default: + is.putback (c1); + is >> val; + break; + } -template -T -read_value (std::istream& is) -{ - T retval; - is >> retval; - return retval; -} + std::ios::iostate status = is.rdstate (); + if (status & std::ios::failbit) + { + // Convert MAX_VAL returned by C++ streams for very large numbers to Inf + if (val == std::numeric_limits::max ()) + { + if (neg) + val = -std::numeric_limits::infinity (); + else + val = std::numeric_limits::infinity (); + is.clear (status & ~std::ios::failbit); + } + else + { + // True error. + // Reset stream to original position, clear eof bit, pass status on. + is.clear (); + is.seekg (pos); + is.setstate (status & ~std::ios_base::eofbit); + } + } -template OCTAVE_API bool read_value (std::istream& is); -template OCTAVE_API octave_int8 read_value (std::istream& is); -template OCTAVE_API octave_int16 read_value (std::istream& is); -template OCTAVE_API octave_int32 read_value (std::istream& is); -template OCTAVE_API octave_int64 read_value (std::istream& is); -template OCTAVE_API octave_uint8 read_value (std::istream& is); -template OCTAVE_API octave_uint16 read_value (std::istream& is); -template OCTAVE_API octave_uint32 read_value (std::istream& is); -template OCTAVE_API octave_uint64 read_value (std::istream& is); + return val; + } -// Note that the caller is responsible for repositioning the stream on -// failure. + template + std::complex + read_cx_fp_value (std::istream& is) + { + T re = 0.0; + T im = 0.0; -template -T -read_inf_nan_na (std::istream& is, char c0) -{ - T val = 0.0; + std::complex cx = 0.0; + + char ch = ' '; - switch (c0) - { - case 'i': case 'I': + while (isspace (ch)) + ch = is.get (); + + if (ch == '(') { - char c1 = is.get (); - if (c1 == 'n' || c1 == 'N') + re = read_value (is); + ch = is.get (); + + if (ch == ',') { - char c2 = is.get (); - if (c2 == 'f' || c2 == 'F') - val = std::numeric_limits::infinity (); + im = read_value (is); + ch = is.get (); + + if (ch == ')') + cx = std::complex (re, im); else is.setstate (std::ios::failbit); } - else - is.setstate (std::ios::failbit); - } - break; - - case 'n': case 'N': - { - char c1 = is.get (); - if (c1 == 'a' || c1 == 'A') - { - char c2 = is.get (); - if (c2 == 'n' || c2 == 'N') - val = std::numeric_limits::quiet_NaN (); - else - { - val = numeric_limits::NA (); - if (c2 != std::istream::traits_type::eof ()) - is.putback (c2); - else - is.clear (is.rdstate () & ~std::ios::failbit); - } - } + else if (ch == ')') + cx = re; else is.setstate (std::ios::failbit); } - break; - - default: - (*current_liboctave_error_handler) - ("read_inf_nan_na: invalid character '%c'", c0); - } - - return val; -} - -// Read a double value. Discard any sign on NaN and NA. - -template -double -read_fp_value (std::istream& is) -{ - T val = 0.0; - - // FIXME: resetting stream position is likely to fail unless we are - // reading from a file. - std::streampos pos = is.tellg (); - - char c1 = ' '; + else + { + is.putback (ch); + cx = read_value (is); + } - while (isspace (c1)) - c1 = is.get (); - - bool neg = false; - - switch (c1) - { - case '-': - neg = true; - OCTAVE_FALLTHROUGH; + return cx; + } - case '+': - { - char c2 = 0; - c2 = is.get (); - if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N') - val = read_inf_nan_na (is, c2); - else - { - is.putback (c2); - is >> val; - } + // FIXME: Could we use traits and enable_if to avoid duplication in the + // following specializations? - if (neg && ! is.fail ()) - val = -val; - } - break; + template <> OCTAVE_API double read_value (std::istream& is) + { + return read_fp_value (is); + } - case 'i': case 'I': - case 'n': case 'N': - val = read_inf_nan_na (is, c1); - break; + template <> OCTAVE_API Complex read_value (std::istream& is) + { + return read_cx_fp_value (is); + } - default: - is.putback (c1); - is >> val; - break; - } + template <> OCTAVE_API float read_value (std::istream& is) + { + return read_fp_value (is); + } - std::ios::iostate status = is.rdstate (); - if (status & std::ios::failbit) - { - // Convert MAX_VAL returned by C++ streams for very large numbers to Inf - if (val == std::numeric_limits::max ()) - { - if (neg) - val = -std::numeric_limits::infinity (); - else - val = std::numeric_limits::infinity (); - is.clear (status & ~std::ios::failbit); - } - else - { - // True error. Reset stream to original position and pass status on. - is.clear (); - is.seekg (pos); - is.setstate (status); - } - } - - return val; -} + template <> OCTAVE_API FloatComplex read_value (std::istream& is) + { + return read_cx_fp_value (is); + } -template -std::complex -read_cx_fp_value (std::istream& is) -{ - T re = 0.0; - T im = 0.0; - - std::complex cx = 0.0; - - char ch = ' '; - - while (isspace (ch)) - ch = is.get (); - - if (ch == '(') - { - re = read_value (is); - ch = is.get (); - - if (ch == ',') - { - im = read_value (is); - ch = is.get (); + template + void + write_value (std::ostream& os, const T& value) + { + os << value; + } - if (ch == ')') - cx = std::complex (re, im); - else - is.setstate (std::ios::failbit); - } - else if (ch == ')') - cx = re; - else - is.setstate (std::ios::failbit); - } - else - { - is.putback (ch); - cx = read_value (is); - } - - return cx; -} - -// FIXME: Could we use traits and enable_if to avoid duplication in the -// following specializations? + template OCTAVE_API void + write_value (std::ostream& os, const bool& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_int8& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_int16& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_int32& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_int64& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_uint8& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_uint16& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_uint32& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_uint64& value); -template <> OCTAVE_API double read_value (std::istream& is) -{ - return read_fp_value (is); -} - -template <> OCTAVE_API Complex read_value (std::istream& is) -{ - return read_cx_fp_value (is); -} + // Note: precision is supposed to be managed outside of this function by + // setting stream parameters. -template <> OCTAVE_API float read_value (std::istream& is) -{ - return read_fp_value (is); -} - -template <> OCTAVE_API FloatComplex read_value (std::istream& is) -{ - return read_cx_fp_value (is); -} - -template -void -write_value (std::ostream& os, const T& value) -{ - os << value; -} + template <> OCTAVE_API void + write_value (std::ostream& os, const double& value) + { + if (lo_ieee_is_NA (value)) + os << "NA"; + else if (lo_ieee_isnan (value)) + os << "NaN"; + else if (lo_ieee_isinf (value)) + os << (value < 0 ? "-Inf" : "Inf"); + else + os << value; + } -template OCTAVE_API void -write_value (std::ostream& os, const bool& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_int8& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_int16& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_int32& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_int64& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_uint8& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_uint16& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_uint32& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_uint64& value); + template <> OCTAVE_API void + write_value (std::ostream& os, const Complex& value) + { + os << '('; + write_value (os, real (value)); + os << ','; + write_value (os, imag (value)); + os << ')'; + } -// Note: precision is supposed to be managed outside of this function by -// setting stream parameters. - -template <> OCTAVE_API void -write_value (std::ostream& os, const double& value) -{ - if (lo_ieee_is_NA (value)) - os << "NA"; - else if (lo_ieee_isnan (value)) - os << "NaN"; - else if (lo_ieee_isinf (value)) - os << (value < 0 ? "-Inf" : "Inf"); - else - os << value; -} + // Note: precision is supposed to be managed outside of this function by + // setting stream parameters. -template <> OCTAVE_API void -write_value (std::ostream& os, const Complex& value) -{ - os << '('; - write_value (os, real (value)); - os << ','; - write_value (os, imag (value)); - os << ')'; -} - -// Note: precision is supposed to be managed outside of this function by -// setting stream parameters. + template <> OCTAVE_API void + write_value (std::ostream& os, const float& value) + { + if (lo_ieee_is_NA (value)) + os << "NA"; + else if (lo_ieee_isnan (value)) + os << "NaN"; + else if (lo_ieee_isinf (value)) + os << (value < 0 ? "-Inf" : "Inf"); + else + os << value; + } -template <> OCTAVE_API void -write_value (std::ostream& os, const float& value) -{ - if (lo_ieee_is_NA (value)) - os << "NA"; - else if (lo_ieee_isnan (value)) - os << "NaN"; - else if (lo_ieee_isinf (value)) - os << (value < 0 ? "-Inf" : "Inf"); - else - os << value; -} - -template <> OCTAVE_API void -write_value (std::ostream& os, const FloatComplex& value) -{ - os << '('; - write_value (os, real (value)); - os << ','; - write_value (os, imag (value)); - os << ')'; -} + template <> OCTAVE_API void + write_value (std::ostream& os, const FloatComplex& value) + { + os << '('; + write_value (os, real (value)); + os << ','; + write_value (os, imag (value)); + os << ')'; + } OCTAVE_BEGIN_NAMESPACE(math) -bool int_multiply_overflow (int a, int b, int *r) -{ - return octave_i_multiply_overflow_wrapper (a, b, r); -} + bool int_multiply_overflow (int a, int b, int *r) + { + return octave_i_multiply_overflow_wrapper (a, b, r); + } -bool int_multiply_overflow (long int a, long int b, long int *r) -{ - return octave_li_multiply_overflow_wrapper (a, b, r); -} + bool int_multiply_overflow (long int a, long int b, long int *r) + { + return octave_li_multiply_overflow_wrapper (a, b, r); + } #if defined (OCTAVE_HAVE_LONG_LONG_INT) -bool int_multiply_overflow (long long int a, long long int b, - long long int *r) -{ - return octave_lli_multiply_overflow_wrapper (a, b, r); -} + bool int_multiply_overflow (long long int a, long long int b, + long long int *r) + { + return octave_lli_multiply_overflow_wrapper (a, b, r); + } #endif -bool int_multiply_overflow (unsigned int a, unsigned int b, - unsigned int *r) -{ - return octave_ui_multiply_overflow_wrapper (a, b, r); -} + bool int_multiply_overflow (unsigned int a, unsigned int b, + unsigned int *r) + { + return octave_ui_multiply_overflow_wrapper (a, b, r); + } -bool int_multiply_overflow (unsigned long int a, unsigned long int b, - unsigned long int *r) -{ - return octave_uli_multiply_overflow_wrapper (a, b, r); -} + bool int_multiply_overflow (unsigned long int a, unsigned long int b, + unsigned long int *r) + { + return octave_uli_multiply_overflow_wrapper (a, b, r); + } #if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT) -bool int_multiply_overflow (unsigned long long int a, - unsigned long long int b, - unsigned long long int *r) -{ - return octave_ulli_multiply_overflow_wrapper (a, b, r); -} + bool int_multiply_overflow (unsigned long long int a, + unsigned long long int b, + unsigned long long int *r) + { + return octave_ulli_multiply_overflow_wrapper (a, b, r); + } #endif OCTAVE_END_NAMESPACE(math) diff -r 29d734430e5f -r deb553ac2c54 liboctave/util/lo-utils.h --- a/liboctave/util/lo-utils.h Tue Dec 06 14:53:00 2022 -0500 +++ b/liboctave/util/lo-utils.h Tue Dec 06 15:45:27 2022 -0500 @@ -137,146 +137,4 @@ OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -template -OCTAVE_DEPRECATED (7, "use 'octave::any_all_test' instead") -bool -any_all_test (F fcn, const T *m, octave_idx_type len) -{ - return octave::any_all_test (fcn, m, len); -} - -OCTAVE_DEPRECATED (7, "use 'octave::is_int_or_inf_or_nan' instead") -inline bool xis_int_or_inf_or_nan (double x) -{ - return octave::is_int_or_inf_or_nan (x); -} - -template -OCTAVE_DEPRECATED (7, "use 'octave::is_one_or_zero' instead") -bool -xis_one_or_zero (const T& x) -{ - return octave::is_one_or_zero (x); -} - -template -OCTAVE_DEPRECATED (7, "use 'octave::is_zero' instead") -bool -xis_zero (const T& x) -{ - return octave::is_zero (x); -} - -OCTAVE_DEPRECATED (7, "use 'octave::' instead") -inline bool xtoo_large_for_float (double x) -{ - return octave::too_large_for_float (x); -} - -OCTAVE_DEPRECATED (7, "use 'octave::' instead") -inline bool xtoo_large_for_float (const Complex& x) -{ - return octave::too_large_for_float (x); -} - -OCTAVE_DEPRECATED (7, "use 'octave::' instead") -inline bool xis_int_or_inf_or_nan (float x) -{ - return octave::is_int_or_inf_or_nan (x); -} - -OCTAVE_DEPRECATED (7, "use 'octave::' instead") -inline bool xtoo_large_for_float (float x) -{ - return octave::too_large_for_float (x); -} - -OCTAVE_DEPRECATED (7, "use 'octave::strsave' instead") -inline char * strsave (const char *s) -{ - return octave::strsave (s); -} - -OCTAVE_DEPRECATED (7, "use 'octave::fgets' instead") -inline std::string octave_fgets (std::FILE *f) -{ - return octave::fgets (f); -} - -OCTAVE_DEPRECATED (7, "use 'octave::fgetl' instead") -inline std::string octave_fgetl (std::FILE *f) -{ - return octave::fgetl (f); -} - -OCTAVE_DEPRECATED (7, "use 'octave::fgets' instead") -inline std::string octave_fgets (std::FILE *f, bool& eof) -{ - return octave::fgets (f, eof); -} - -OCTAVE_DEPRECATED (7, "use 'octave::fgetl' instead") -inline std::string octave_fgetl (std::FILE *f, bool& eof) -{ - return octave::fgetl (f, eof); -} - -OCTAVE_DEPRECATED (7, "use 'octave::read_value' instead") -inline double -octave_read_double (std::istream& is) -{ - return octave::read_value (is); -} - -OCTAVE_DEPRECATED (7, "use 'octave::read_value' instead") -inline Complex -octave_read_complex (std::istream& is) -{ - return octave::read_value (is); -} - -OCTAVE_DEPRECATED (7, "use 'octave::read_value' instead") -inline float -octave_read_float (std::istream& is) -{ - return octave::read_value (is); -} - -OCTAVE_DEPRECATED (7, "use 'octave::read_value' instead") -inline FloatComplex -octave_read_float_complex (std::istream& is) -{ - return octave::read_value (is); -} - -OCTAVE_DEPRECATED (7, "use 'octave::write_value' instead") -inline void -octave_write_double (std::ostream& os, double value) -{ - octave::write_value (os, value); -} - -OCTAVE_DEPRECATED (7, "use 'octave::write_value' instead") -inline void -octave_write_complex (std::ostream& os, const Complex& value) -{ - octave::write_value (os, value); -} - -OCTAVE_DEPRECATED (7, "use 'octave::write_value' instead") -inline void -octave_write_float (std::ostream& os, float value) -{ - octave::write_value (os, value); -} - -OCTAVE_DEPRECATED (7, "use 'octave::write_value' instead") -inline void -octave_write_float_complex (std::ostream& os, const FloatComplex& value) -{ - octave::write_value (os, value); -} #endif - -#endif diff -r 29d734430e5f -r deb553ac2c54 oct-conf-post-public.in.h --- a/oct-conf-post-public.in.h Tue Dec 06 14:53:00 2022 -0500 +++ b/oct-conf-post-public.in.h Tue Dec 06 15:45:27 2022 -0500 @@ -39,7 +39,7 @@ OCTAVE_ATTRIBUTE_NAME in place of vendor specific attribute mechanisms. As compilers evolve, the underlying implementation can be changed with the macro definitions below. FIXME: Update macros - to use C++ standard attribute syntax when Octave moves to C++ 2011 + to use C++ standard attribute syntax when Octave moves to C++ 2014 standard. */ #if defined (__GNUC__) diff -r 29d734430e5f -r deb553ac2c54 scripts/deprecated/disable_diagonal_matrix.m --- a/scripts/deprecated/disable_diagonal_matrix.m Tue Dec 06 14:53:00 2022 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -######################################################################## -## -## Copyright (C) 2021-2022 The Octave Project Developers -## -## See the file COPYRIGHT.md in the top-level directory of this -## distribution or . -## -## This file is part of Octave. -## -## Octave 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. -## -## Octave 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 Octave; see the file COPYING. If not, see -## . -## -######################################################################## - -## -*- texinfo -*- -## @deftypefn {} {@var{val} =} disable_diagonal_matrix () -## @deftypefnx {} {@var{old_val} =} disable_diagonal_matrix (@var{new_val}) -## @deftypefnx {} {@var{old_val} =} disable_diagonal_matrix (@var{new_val}, "local") -## -## @code{disable_diagonal_matrix} is deprecated and will be removed in Octave -## version 9. Use @code{optimize_diagonal_matrix} instead. -## -## Query or set whether storing diagonal matrices in a special space-efficient -## format is disabled. -## -## The default value is false. If this option is set to true, Octave will -## store ranges as full matrices. -## -## When called from inside a function with the @qcode{"local"} option, the -## setting is changed locally for the function and any subroutines it calls. -## The original setting is restored when exiting the function. -## @seealso{disable_diagonal_matrix, disable_permutation_matrix} -## @end deftypefn - -## FIXME: DEPRECATED: Remove in version 9. - -function retval = disable_diagonal_matrix (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "disable_diagonal_matrix is obsolete and will be removed from a future version of Octave, please use optimize_diagonal_matrix instead\n"); - endif - - if (nargin == 0) - retval = ! optimize_diagonal_matrix (); - elseif (nargout == 0) - optimize_diagonal_matrix (! varargin{1}, varargin{2:end}); - else - retval = ! optimize_diagonal_matrix (! varargin{1}, varargin{2:end}); - endif - -endfunction diff -r 29d734430e5f -r deb553ac2c54 scripts/deprecated/disable_permutation_matrix.m --- a/scripts/deprecated/disable_permutation_matrix.m Tue Dec 06 14:53:00 2022 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -######################################################################## -## -## Copyright (C) 2021-2022 The Octave Project Developers -## -## See the file COPYRIGHT.md in the top-level directory of this -## distribution or . -## -## This file is part of Octave. -## -## Octave 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. -## -## Octave 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 Octave; see the file COPYING. If not, see -## . -## -######################################################################## - -## -*- texinfo -*- -## @deftypefn {} {@var{val} =} disable_permutation_matrix () -## @deftypefnx {} {@var{old_val} =} disable_permutation_matrix (@var{new_val}) -## @deftypefnx {} {@var{old_val} =} disable_permutation_matrix (@var{new_val}, "local") -## -## @code{disable_permutation_matrix} is deprecated and will be removed in -## Octave version 9. Use @code{optimize_permutation_matrix} instead. -## -## Query or set whether storing permutation matrices in a special -## space-efficient format is disabled. -## -## The default value is false. If this option is set to true, Octave will -## store ranges as full matrices. -## -## When called from inside a function with the @qcode{"local"} option, the -## setting is changed locally for the function and any subroutines it calls. -## The original setting is restored when exiting the function. -## @seealso{disable_diagonal_matrix, disable_permutation_matrix} -## @end deftypefn - -## FIXME: DEPRECATED: Remove in version 9. - -function retval = disable_permutation_matrix (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "disable_permutation_matrix is obsolete and will be removed from a future version of Octave, please use optimize_permutation_matrix instead\n"); - endif - - if (nargin == 0) - retval = ! optimize_permutation_matrix (); - elseif (nargout == 0) - optimize_permutation_matrix (! varargin{1}, varargin{2:end}); - else - retval = ! optimize_permutation_matrix (! varargin{1}, varargin{2:end}); - endif - -endfunction diff -r 29d734430e5f -r deb553ac2c54 scripts/deprecated/disable_range.m --- a/scripts/deprecated/disable_range.m Tue Dec 06 14:53:00 2022 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -######################################################################## -## -## Copyright (C) 2021-2022 The Octave Project Developers -## -## See the file COPYRIGHT.md in the top-level directory of this -## distribution or . -## -## This file is part of Octave. -## -## Octave 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. -## -## Octave 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 Octave; see the file COPYING. If not, see -## . -## -######################################################################## - -## -*- texinfo -*- -## @deftypefn {} {@var{val} =} disable_range () -## @deftypefnx {} {@var{old_val} =} disable_range (@var{new_val}) -## @deftypefnx {} {@var{old_val} =} disable_range (@var{new_val}, "local") -## -## @code{disable_range} is deprecated and will be removed in Octave version 9. -## Use @code{optimize_range} instead. -## -## Query or set whether storing ranges in a special space-efficient format is -## disabled. -## -## The default value is false. If this option is set to true, Octave will -## store ranges as full matrices. -## -## When called from inside a function with the @qcode{"local"} option, the -## setting is changed locally for the function and any subroutines it calls. -## The original setting is restored when exiting the function. -## @seealso{disable_diagonal_matrix, disable_permutation_matrix} -## @end deftypefn - -## FIXME: DEPRECATED: Remove in version 9. - -function retval = disable_range (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "disable_range is obsolete and will be removed from a future version of Octave, please use optimize_range instead\n"); - endif - - if (nargin == 0) - retval = ! optimize_range (); - elseif (nargout == 0) - optimize_range (! varargin{1}, varargin{2:end}); - else - retval = ! optimize_range (! varargin{1}, varargin{2:end}); - endif - -endfunction diff -r 29d734430e5f -r deb553ac2c54 scripts/deprecated/module.mk --- a/scripts/deprecated/module.mk Tue Dec 06 14:53:00 2022 -0500 +++ b/scripts/deprecated/module.mk Tue Dec 06 15:45:27 2022 -0500 @@ -2,9 +2,6 @@ %canon_reldir%_FCN_FILES = \ %reldir%/.oct-config \ - %reldir%/disable_diagonal_matrix.m \ - %reldir%/disable_permutation_matrix.m \ - %reldir%/disable_range.m \ %reldir%/shift.m \ %reldir%/sparse_auto_mutate.m diff -r 29d734430e5f -r deb553ac2c54 scripts/geometry/tsearchn.m --- a/scripts/geometry/tsearchn.m Tue Dec 06 14:53:00 2022 -0500 +++ b/scripts/geometry/tsearchn.m Tue Dec 06 15:45:27 2022 -0500 @@ -26,15 +26,17 @@ ## -*- texinfo -*- ## @deftypefn {} {@var{idx} =} tsearchn (@var{x}, @var{t}, @var{xi}) ## @deftypefnx {} {[@var{idx}, @var{p}] =} tsearchn (@var{x}, @var{t}, @var{xi}) -## Search for the enclosing Delaunay convex hull. +## Find the simplexes enclosing the given points. ## -## For @code{@var{t} = delaunayn (@var{x})}, finds the index in @var{t} -## containing the points @var{xi}. For points outside the convex hull, -## @var{idx} is NaN. +## @code{tsearchn} is typically used with @code{delaunayn}: +## @code{@var{t} = delaunayn (@var{x})} returns a set of simplexes @code{t}, +## then @code{tsearchn} returns the row index of @var{t} containing each point +## of @var{xi}. For points outside the convex hull, @var{idx} is NaN. ## -## If requested @code{tsearchn} also returns the Barycentric coordinates -## @var{p} of the enclosing triangles. -## @seealso{delaunay, delaunayn} +## If requested, @code{tsearchn} also returns the barycentric coordinates +## @var{p} of the enclosing simplexes. +## +## @seealso{delaunay, delaunayn, tsearch} ## @end deftypefn function [idx, p] = tsearchn (x, t, xi) @@ -43,57 +45,53 @@ print_usage (); endif + if (columns (x) != columns (xi)) + error ("tsearchn: number of columns of X and XI must match"); + endif + + if (max (t(:)) > rows (x)) + error ("tsearchn: triangulation T must not access points outside X"); + endif + + if (nargout <= 1 && columns (x) == 2) # pass to the faster tsearch.cc + idx = tsearch (x(:,1), x(:,2), t, xi(:,1), xi(:,2)); + return; + endif + nt = rows (t); [m, n] = size (x); mi = rows (xi); idx = NaN (mi, 1); p = NaN (mi, n + 1); - ni = [1:mi].'; - for i = 1 : nt - ## Only calculate the Barycentric coordinates for points that have not - ## already been found in a triangle. - b = cart2bary (x (t (i, :), :), xi(ni,:)); - ## Our points xi are in the current triangle if - ## (all (b >= 0) && all (b <= 1)). However as we impose that - ## sum (b,2) == 1 we only need to test all(b>=0). Note need to add - ## a small margin for rounding errors - intri = all (b >= -1e-12, 2); - idx(ni(intri)) = i; - p(ni(intri),:) = b(intri, :); - ni(intri) = []; - endfor + for i = 1 : nt # each simplex in turn -endfunction - -function Beta = cart2bary (T, P) + T = x(t(i, :), :); # T is the current simplex + P = xi(ni, :); # P is the set of points left to calculate - ## Conversion of Cartesian to Barycentric coordinates. - ## Given a reference simplex in N dimensions represented by an - ## N+1-by-N matrix, an arbitrary point P in Cartesian coordinates, - ## represented by an N-by-1 column vector can be written as - ## - ## P = Beta * T - ## - ## Where Beta is an N+1 vector of the barycentric coordinates. A criteria - ## on Beta is that - ## - ## sum (Beta) == 1 - ## - ## and therefore we can write the above as - ## - ## P - T(end, :) = Beta(1:end-1) * (T(1:end-1,:) - ones (N,1) * T(end,:)) - ## - ## and then we can solve for Beta as - ## - ## Beta(1:end-1) = (P - T(end,:)) / (T(1:end-1,:) - ones (N,1) * T(end,:)) - ## Beta(end) = sum (Beta) - ## - ## Note code below is generalized for multiple values of P, one per row. - [M, N] = size (P); - Beta = (P - ones (M,1) * T(end,:)) / (T(1:end-1,:) - ones (N,1) * T(end,:)); - Beta (:,end+1) = 1 - sum (Beta, 2); + ## Convert to barycentric coords: these are used to express a point P + ## as P = Beta * T + ## where T is a simplex. + ## + ## If 0 <= Beta <= 1, then the linear combination is also convex, + ## and the point P is inside the simplex T, otherwise it is outside. + ## Since the equation system is underdetermined, we apply the constraint + ## sum (Beta) == 1 to make it unique up to scaling. + ## + ## Note that the code below is vectorized over P, one point per row. + + b = (P - T(end,:)) / (T(1:end-1,:) - T(end,:)); + b(:, end+1) = 1 - sum (b, 2); + + ## The points xi are inside the current simplex if + ## (all (b >= 0) && all (b <= 1)). As sum (b,2) == 1, we only need to + ## test all(b>=0). + inside = all (b >= -1e-12, 2); # -1e-12 instead of 0 for rounding errors + idx(ni(inside)) = i; + p(ni(inside), :) = b(inside, :); + ni = ni(! inside); + endfor endfunction @@ -121,3 +119,10 @@ %! [idx, p] = tsearchn (x,tri,[1,1]); %! assert (idx, NaN); %! assert (p, [NaN, NaN, NaN]); + +## Test input validation +%!error tsearchn () +%!error tsearchn (1) +%!error tsearchn (1, 2) +%!error tsearchn ([1,2], 3, 4) +%!error tsearchn (1, 2, 3) diff -r 29d734430e5f -r deb553ac2c54 scripts/linear-algebra/module.mk --- a/scripts/linear-algebra/module.mk Tue Dec 06 14:53:00 2022 -0500 +++ b/scripts/linear-algebra/module.mk Tue Dec 06 15:45:27 2022 -0500 @@ -35,6 +35,7 @@ %reldir%/rref.m \ %reldir%/subspace.m \ %reldir%/trace.m \ + %reldir%/tensorprod.m \ %reldir%/vech.m \ %reldir%/vecnorm.m diff -r 29d734430e5f -r deb553ac2c54 scripts/linear-algebra/tensorprod.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/linear-algebra/tensorprod.m Tue Dec 06 15:45:27 2022 -0500 @@ -0,0 +1,437 @@ +######################################################################## +## +## Copyright (C) 2022 The Octave Project Developers +## +## See the file COPYRIGHT.md in the top-level directory of this +## distribution or . +## +## This file is part of Octave. +## +## Octave 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. +## +## Octave 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 Octave; see the file COPYING. If not, see +## . +## +######################################################################## + +## -*- texinfo -*- +## @deftypefn {} {@var{C} =} tensorprod (@var{A}, @var{B}, @var{dimA}, @var{dimB}) +## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B}, @var{dim}) +## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B}) +## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B}, "all") +## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B}, @dots{}, "NumDimensionsA", @var{value}) +## Compute the tensor product between numeric tensors @var{A} and @var{B}. +## +## The dimensions of @var{A} and @var{B} that are contracted are defined by +## @var{dimA} and @var{dimB}, respectively. @var{dimA} and @var{dimB} are +## scalars or equal length vectors that define the dimensions to match up. +## The matched dimensions of @var{A} and @var{B} must have equal lengths. +## +## When @var{dim} is used, it is equivalent to @var{dimA} = @var{dimB} = +## @var{dim}. +## +## When no dimensions are specified, @var{dimA} = @var{dimB} = []. This +## computes the outer product between @var{A} and @var{B}. +## +## Using the "all" option results in the inner product between @var{A} and +## @var{B}. This requires size(@var{A}) == size(@var{B}). +## +## Use the property-value pair with the property name "NumDimensionsA" when +## @var{A} has trailing singleton dimensions that should be transfered to +## @var{C}. The specified @var{value} should be the total number of +## dimensions of @var{A}. +## +## Matlab Compatibility: Octave does not currently support the "name=value" +## syntax for the "NumDimensionsA" parameter. +## +## @seealso{kron, dot, mtimes} +## @end deftypefn + +function C = tensorprod (A, B, varargin) + + ## FIXME: shortcut code paths could be added for trivial cases, such as if + ## either A or B are a scalars, null, identity tensors, etc. + + if (nargin < 2 || nargin > 6) + print_usage (); + endif + + ## Check that A and B are single or double + if (! isfloat (A)) + error ("tensorprod: A must be a single or double precision array"); + endif + + if (! isfloat (B)) + error ("tensorprod: B must be a single or double precision array"); + endif + + ## Check for misplaced NumDimensionsA property + if (nargin > 2) + if (strcmpi (varargin{end}, "NumDimensionsA")) + error (["tensorprod: a value for the NumDimensionsA property must ", ... + "be provided"]); + elseif (strcmpi ( strtok (inputname (nargin, false)), "NumDimensionsA")) + ## FIXME: Add support for keyword=value syntax + error (["tensorprod: NumDimensionsA=ndimsA syntax is not yet ", ... + "supported in Octave - provide the value as a ", ... + "property-value pair"]); + endif + endif + + ## Check for NumDimensionsA property + if (nargin > 3) + if (strcmpi (varargin{end - 1}, "NumDimensionsA")) + if (! (isnumeric (varargin{end}) && isscalar (varargin{end}))) + error (["tensorprod: value for NumDimensionsA must be a ", ... + "numeric scalar"]); + elseif (varargin{end} < 1 || rem (varargin{end}, 1) != 0) + error (["tensorprod: value for NumDimensionsA must be a ", ... + "positive integer"]); + endif + NumDimensionsA = varargin{end}; + endif + endif + + existNumDimensionsA = exist ("NumDimensionsA"); + ndimargs = nargin - 2 - 2 * existNumDimensionsA; + + ## Set dimA and dimB + if (ndimargs == 0) + ## Calling without dimension arguments + dimA = []; + dimB = []; + elseif (ndimargs == 1) + ## Calling with dim or "all" option + if (isnumeric (varargin{1})) + if (! (isvector (varargin{1}) || isnull (varargin{1}))) + error ("tensorprod: dim must be a numeric vector of integers or []"); + endif + ## Calling with dim + dimA = transpose ([varargin{1}(:)]); + elseif (ischar (varargin{1})) + if (strcmpi (varargin{1}, "all")) + if (! size_equal (A, B)) + error (["tensorprod: size of A and B must be identical when ", ... + "using the 'all' option"]); + endif + else + error ("tensorprod: unknown option '%s'", varargin{1}); + endif + ## Calling with "all" option + dimA = 1:ndims(A); + else + error (["tensorprod: third argument must be a numeric vector of ", ... + "integers, [], or 'all'"]); + endif + dimB = dimA; + elseif (ndimargs == 2) + ## Calling with dimA and dimB + if (! (isnumeric (varargin{1}) && (isvector (varargin{1}) || ... + isnull (varargin{1})))) + error("tensorprod: dimA must be a numeric vector of integers or []"); + endif + + if (! (isnumeric (varargin{2}) && (isvector (varargin{2}) || ... + isnull (varargin{2})))) + error ("tensorprod: dimB must be a numeric vector of integers or []"); + endif + + if (length (varargin{1}) != length (varargin{2})) + error (["tensorprod: an equal number of dimensions must be ", ... + "matched for A and B"]); + endif + dimA = transpose ([varargin{1}(:)]); + dimB = transpose ([varargin{2}(:)]); + else + ## Something is wrong - try to find the error + for i = 1:ndimargs + if (ischar (varargin{i})) + if (strcmpi (varargin{i}, "NumDimensionsA")) + error ("tensorprod: misplaced 'NumDimensionsA' option"); + elseif (strcmpi (varargin{i}, "all")) + error ("tensorprod: misplaced 'all' option"); + else + error ("tensorprod: unknown option '%s'", varargin{i}); + endif + elseif (! isnumeric (varargin{i})) + error (["tensorprod: optional arguments must be numeric vectors ", ... + "of integers, [], 'all', or 'NumDimensionsA'"]); + endif + endfor + error ("tensorprod: too many dimension inputs given"); + endif + + ## Check that dimensions are positive integers ([] will also pass) + if (any ([dimA < 1, dimB < 1, (rem (dimA, 1) != 0), (rem (dimB, 1) != 0)])) + error ("tensorprod: dimension(s) must be positive integer(s)"); + endif + + ## Check that the length of matched dimensions are equal + if (any (size (A, dimA) != size (B, dimB))) + error (["tensorprod: matched dimension(s) of A and B must have the ", ... + "same length(s)"]); + endif + + ## Find size and ndims of A and B + ndimsA = max ([ndims(A), max(dimA)]); + sizeA = size (A, 1:ndimsA); + ndimsB = max ([ndims(B), max(dimB)]); + sizeB = size (B, 1:ndimsB); + + ## Take NumDimensionsA property into account + if (existNumDimensionsA) + if (NumDimensionsA < ndimsA) + if (ndimargs == 1) + error (["tensorprod: highest dimension of dim must be less than ", ... + "or equal to NumDimensionsA"]); + elseif (ndimargs == 2) + error (["tensorprod: highest dimension of dimA must be less ", ... + "than or equal to NumDimensionsA"]); + else + error (["tensorprod: NumDimensionsA cannot be smaller than the ", ... + "number of dimensions of A"]); + endif + elseif (NumDimensionsA > ndimsA) + sizeA = [sizeA, ones(1, NumDimensionsA - ndimsA)]; + ndimsA = NumDimensionsA; + endif + endif + + ## Interchange the dimension to sum over the end of A and the front of B + ## Prepare for A + remainDimA = setdiff (1:ndimsA, dimA); # Dimensions of A to keep + newDimOrderA = [remainDimA, dimA]; # New dim order [to_keep, to_contract] + newSizeA = [prod(sizeA(remainDimA)), prod(sizeA(dimA))]; # Temp. 2D size for A + remainSizeA = sizeA(remainDimA); # Contrib. to size of C from remaining A dims + + ## Prepare for B (See comments for A. Note that in principle, + ## prod (sizeB (dimB)) should always be equal to prod (sizeA (dimA)). May + ## be able to optimize further here. + remainDimB = setdiff (1:ndimsB, dimB); + newDimOrderB = [remainDimB, dimB]; + newSizeB = [prod(sizeB(remainDimB)), prod(sizeB(dimB))]; + remainSizeB = sizeB(remainDimB); + + ## Do reshaping into 2D array + newA = reshape (permute (A, newDimOrderA), newSizeA); + newB = reshape (permute (B, newDimOrderB), newSizeB); + + ## Compute + C = newA * transpose (newB); + + ## If not an inner product, reshape back to tensor + if (! isscalar (C)) + C = reshape (C, [remainSizeA, remainSizeB]); + endif + +endfunction + + +%!assert (tensorprod (2, 3), 6) +%!assert (tensorprod (2, 3, 1), 6) +%!assert (tensorprod (2, 3, 2), 6) +%!assert (tensorprod (2, 3, 10), 6) +%!assert (tensorprod (2, 3, [1 2]), 6) +%!assert (tensorprod (2, 3, [1 10]), 6) +%!assert (tensorprod (2, 3, []), 6) +%!assert (tensorprod (2, 3, 2, 1), 6) +%!assert (tensorprod (2, 3, [], []), 6) + +%!shared v1, v2, M1, M2, T +%! v1 = [1, 2]; +%! M1 = [1, 2; 3, 4]; +%! M2 = [1, 2; 3, 4; 5, 6]; +%! T = cat (3, M2, M2); + +%!assert (tensorprod (3, v1), reshape ([3, 6], [1, 1, 1, 2])); +%!assert (tensorprod (v1, 3), [3, 6]); +%!assert (tensorprod (v1, v1, "all"), 5); +%!assert (tensorprod (v1, v1), reshape ([1, 2, 2, 4], [1, 2, 1, 2])); +%!assert (tensorprod (v1, v1, 1), [1, 2; 2, 4]); +%!assert (tensorprod (v1, v1, 2), 5); +%!assert (tensorprod (v1, v1, 3), reshape ([1, 2, 2, 4], [1, 2, 1, 2])); +%!assert (tensorprod (v1, v1, 5), reshape ([1, 2, 2, 4], [1, 2, 1, 1, 1, 2])); + +%!assert (tensorprod (M1, v1), cat (4, [1,2;3,4], [2,4;6,8])) +%!assert (tensorprod (M1, v1'), cat (3, [1,2;3,4], [2,4;6,8])) +%!assert (tensorprod (v1, M1), reshape ([1 2 3 6 2 4 4 8], [1,2,2,2])) +%!assert (tensorprod (v1', M1), reshape ([1 2 3 6 2 4 4 8], [2,1,2,2])) +%!assert (tensorprod (M1, v1', 2, 1), [5; 11]) +%!assert (tensorprod (M1, v1', 4, 4), cat(4, M1, 2*M1)) +%!assert (tensorprod (M1, v1', [1, 3]), [7; 10]) +%!assert (tensorprod (M1, v1', [1, 3], [1, 3]), [7; 10]) +%!assert (tensorprod (M1, v1', [2, 3], [1, 3]), [5; 11]) +%!assert (tensorprod (M1, v1', [2; 3], [1; 3]), [5; 11]) +%!assert (tensorprod (M1, v1', [2; 3], [1, 3]), [5; 11]) +%!assert (tensorprod (M1, v1', [2, 3], [1; 3]), [5; 11]) +%!assert (tensorprod (M1, v1', [], []), cat (3, M1, 2*M1)) +%!assert (tensorprod (M1, M1, "all"), 30) +%!assert (tensorprod (M1, M1, 1), [10, 14; 14, 20]) +%!assert (tensorprod (M1, M1, 2), [5, 11; 11, 25]) +%!assert (tensorprod (M1, M2, 2), [5, 11, 17; 11, 25, 39]) +%!assert (tensorprod (M1, M2, 1, 2), [7, 15, 23; 10, 22, 34]) +%!assert (tensorprod (M1, M2), reshape ([1,3,2,4,3,9,6,12,5,15,10,20,2,6,4, ... +%! 8,4,12,8,16,6,18,12,24], [2,2,3,2])) + +%!assert (tensorprod (T, M1), +%! reshape([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18,2, ... +%! 6,10,4,8,12,2,6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24], +%! [3,2,2,2,2])) +%!assert (tensorprod (T, M1, 2), +%! cat (3, [5, 5; 11 11; 17, 17], [11, 11; 25, 25; 39, 39])) +%!assert (tensorprod (T, M2, 1), cat (3, [35, 35; 44, 44], [44, 44; 56, 56])) +%!assert (tensorprod (T, M2, 2), cat (3, [5, 5; 11, 11; 17, 17], +%! [11,11;25,25;39,39], [17, 17; 39, 39; 61, 61])) +%!assert (tensorprod (T, T, "all"), 182) +%!assert (tensorprod (T, T, 1), +%! reshape ([35,44,35,44,44,56,44,56,35,44,35,44,44,56,44,56], +%! [2,2,2,2])) +%!assert (tensorprod (T, T, 2), +%! reshape ([5,11,17,5,11,17,11,25,39,11,25,39,17,39,61,17,39,61,5, ... +%! 11,17,5,11,17,11,25,39,11,25,39,17,39,61,17,39,61], +%! [3,2,3,2])) +%!assert (tensorprod (T, T, 3), +%! reshape ([2,6,10,4,8,12,6,18,30,12,24,36,10,30,50,20,40,60,4,12, ... +%! 20,8,16,24,8,24,40,16,32,48,12,36,60,24,48,72], [3,2,3,2])); +%!assert (tensorprod (T, T, 10), +%! reshape ([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18, ... +%! 5,15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2,6,10, ... +%! 4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24,36, ... +%! 6,18,30,12,24,36,1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18, ... +%! 3,9,15,6,12,18,5,15,25,10,20,30,5,15,25,10,20,30,2,6,10, ... +%! 4,8,12,2,6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6, ... +%! 18,30,12,24,36,6,18,30,12,24,36], +%! [3,2,2,1,1,1,1,1,1,3,2,2])) +%!assert (tensorprod (T, T, []), +%! reshape ([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18, ... +%! 5,15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2,6,10, ... +%! 4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24,36, ... +%! 6,18,30,12,24,36,1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18, ... +%! 3,9,15,6,12,18,5,15,25,10,20,30,5,15,25,10,20,30,2,6,10, ... +%! 4,8,12,2,6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6, ... +%! 18,30,12,24,36,6,18,30,12,24,36], +%! [3,2,2,3,2,2])) +%!assert (tensorprod (T, T, 2, 3), +%! reshape ([3,7,11,3,7,11,9,21,33,9,21,33,15,35,55,15,35,55,6,14, ... +%! 22,6,14,22,12,28,44,12,28,44,18,42,66,18,42,66], +%! [3,2,3,2])) +%!assert (tensorprod (T, T(1:2, 1:2, :), [2, 3],[1, 3]), +%! [14, 20; 30, 44; 46, 68]) +%!assert (tensorprod (T, T(1:2, 1:2, :), [3, 2],[1, 3]), +%! [12, 18; 28, 42; 44, 66]) +%!assert (tensorprod (T, reshape (T, [2, 2, 3]), 2, 1), +%! reshape ([7,15,23,7,15,23,9,23,37,9,23,37,16,36,56,16,36,56,7,15, ... +%! 23,7,15,23,9,23,37,9,23,37,16,36,56,16,36,56], +%! [3,2,2,3])) +%!assert (tensorprod (T, T, [1, 3]), [70, 88; 88, 112]) +%!assert (tensorprod (T, T, [1, 3]), tensorprod (T, T, [3, 1])) +%!assert (tensorprod (T, reshape (T, [2, 2, 3]), [2, 3], [1, 2]), +%! [16, 23, 25; 38, 51, 59; 60, 79, 93]) + +## NumDimensionsA tests +%!assert (tensorprod (v1, v1, "NumDimensionsA", 2), +%! reshape ([1, 2, 2, 4], [1, 2, 1, 2])); +%!assert (tensorprod (v1, v1, "numdimensionsa", 2), +%! tensorprod (v1, v1, "NumDimensionsA", 2)); +%!assert (tensorprod (v1, v1, "NumDimensionsA", 3), +%! reshape ([1, 2, 2, 4], [1, 2, 1, 1, 2])); +%!assert (tensorprod (v1, v1, [], "NumDimensionsA", 3), +%! reshape ([1, 2, 2, 4], [1, 2, 1, 1, 2])); +%!assert (tensorprod (v1, v1, [], [], "NumDimensionsA", 3), +%! reshape ([1, 2, 2, 4], [1, 2, 1, 1, 2])); +%!assert (tensorprod (v1, v1, "all", "NumDimensionsA", 3), 5); +%!assert (tensorprod (M1, v1, 2, "NumDimensionsA", 2), [5; 11]); +%!assert (tensorprod (M1, v1, 2, "NumDimensionsA", 5), [5; 11]); +%!assert (tensorprod (M1, v1, [2, 3], "NumDimensionsA", 5), [5; 11]); +%!assert (tensorprod (M1, M2, "NumDimensionsA", 2), reshape ([1,3,2,4,3,9,6, ... +%! 12,5,15,10,20,2,6,4,8,4,12,8,16,6,18,12,24], [2,2,3,2])) +%!assert (tensorprod (M1, M2, "NumDimensionsA", 3), reshape ([1,3,2,4,3,9,6, ... +%! 12,5,15,10,20,2,6,4,8,4,12,8,16,6,18,12,24], [2,2,1,3,2])) +%!assert (tensorprod (T, T, 1, "NumDimensionsA", 3), +%! reshape ([35,44,35,44,44,56,44,56,35,44,35,44,44,56,44,56], +%! [2,2,2,2])) +%!assert (tensorprod (T, T, 3, "NumDimensionsA", 3), +%! reshape ([2,6,10,4,8,12,6,18,30,12,24,36,10,30,50,20,40,60,4,12, ... +%! 20,8,16,24, 8,24,40,16,32,48,12,36,60,24,48,72], +%! [3,2,3,2])) +%!assert (tensorprod (T, T, 1, "NumDimensionsA", 4), +%! reshape ([35,44,35,44,44,56,44,56,35,44,35,44,44,56,44,56], +%! [2,2,1,2,2])) +%!assert (tensorprod (T, T, 4, "NumDimensionsA", 4), +%! reshape ([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18,5, ... +%! 15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2,6,10,4,8, ... +%! 12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24,36,6,18, ... +%! 30,12,24,36,1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15, ... +%! 6,12,18,5,15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2, ... +%! 6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24, ... +%! 36,6,18,30,12,24,36], +%! [3,2,2,3,2,2])) + +## Test empty inputs +%!assert (tensorprod ([], []), zeros (0, 0, 0, 0)) +%!assert (tensorprod ([], 1), []) +%!assert (tensorprod (1, []), zeros (1, 1, 0, 0)) +%!assert (tensorprod (zeros (0, 0, 0), zeros (0, 0, 0)), zeros (0, 0, 0, 0, 0, 0)) +%!assert (tensorprod ([], [], []), zeros (0, 0, 0, 0)) +%!assert (tensorprod ([], [], 1), []) +%!assert (tensorprod ([], [], 2), []) +%!assert (tensorprod ([], [], 3), zeros (0, 0, 0, 0)) +%!assert (tensorprod ([], [], 4), zeros (0, 0, 1, 0, 0)) +%!assert (tensorprod ([], [], 5), zeros (0, 0, 1, 1, 0, 0)) +%!assert (tensorprod ([], [], 3, "NumDimensionsA", 4), zeros (0, 0, 1, 0, 0)) +%!assert (tensorprod ([], [], 3, 4, "NumDimensionsA", 5), zeros (0, 0, 1, 1, 0, 0)) + +## Test input validation +%!error tensorprod () +%!error tensorprod (1) +%!error tensorprod (1,2,3,4,5,6,7) +%!error tensorprod ("foo", 1) +%!error tensorprod (1, "bar") +%!error tensorprod (int32(1), 1) +%!error tensorprod (1, int32(1)) +%!error tensorprod (1, 1, "foo") +%!error tensorprod (1, 1, 1, "foo", 1) +%!error tensorprod (1, 1, "foo", 1) +%!error tensorprod (1, 1, 1, "bar") +%!error tensorprod (1, 1, zeros(0,0,0), []) +%!error tensorprod (1, 1, [], zeros(0,0,0)) +%!error tensorprod (1, 1, zeros(0,0,0)) +%!error tensorprod (1, 1, 1, "all", 1) +%!error tensorprod (1, 1, "NumDimensionsA", 1, 1) +%!error tensorprod (1, 1, 1, {}, 1) +%!error tensorprod (ones (3, 4), ones (4, 3), 1) +%!error tensorprod (ones (3, 4), ones (4, 3), 1, 1) +%!error tensorprod (1, 1, 0) +%!error tensorprod (1, 1, -1) +%!error tensorprod (1, 1, 1.5) +%!error tensorprod (1, 1, NaN) +%!error tensorprod (1, 1, Inf) +%!error tensorprod (1, 1, {}) +%!error tensorprod (ones (3, 4), ones (4, 3), 1, [1, 2]) +%!error tensorprod (ones (3, 4), ones (4, 3), 1, []) +%!error tensorprod (ones (3, 4), ones (4, 3), [], [1, 2]) +%!error tensorprod (ones (3, 4), ones (4, 3), "all") +%!error tensorprod (1, 1, "NumDimensionsA") +%!error tensorprod (ones (2, 2, 2), 1, "NumDimensionsA", 2) +%!error tensorprod (1, 1, 5, "NumDimensionsA", 4) +%!error tensorprod (1, 1, 5, 5, "NumDimensionsA", 4) +%!error tensorprod (1, 1, NumDimensionsA=4) +%!error tensorprod (1, 1, numdimensionsa=4) +%!error tensorprod (1, 1, 2, 1, 1) +%!error tensorprod (1, 1, 2, 1, 1, 1) +%!error tensorprod (1, 1, 2, 1, "NumDimensionsA", "foo") +%!error tensorprod (1, 1, 2, 1, "NumDimensionsA", {}) +%!error tensorprod (1, 1, 2, 1, "NumDimensionsA", -1) +%!error tensorprod (1, 1, 2, 1, "NumDimensionsA", 0) +%!error tensorprod (1, 1, 2, 1, "NumDimensionsA", 1.5) +%!error tensorprod (1, 1, 2, 1, "NumDimensionsA", NaN) +%!error tensorprod (1, 1, 2, 1, "NumDimensionsA", Inf) diff -r 29d734430e5f -r deb553ac2c54 scripts/plot/util/__pltopt__.m --- a/scripts/plot/util/__pltopt__.m Tue Dec 06 14:53:00 2022 -0500 +++ b/scripts/plot/util/__pltopt__.m Tue Dec 06 15:45:27 2022 -0500 @@ -158,12 +158,6 @@ topt = opt(1); n = 1; - if (any (topt == "0":"6")) - warning ("Octave:deprecated-option", ... - ["%s: using numbers to select line colors is deprecated. ", ... - "Use the corresponding color identifier instead."], caller); - endif - ## LineStyles if (strncmp (opt, "--", 2) || strncmp (opt, "-.", 2)) options.linestyle = opt(1:2); @@ -195,20 +189,19 @@ topt = "+"; endif options.marker = topt; - ## Numeric color specs are for backward compatibility. Don't document. - elseif (topt == "k" || topt == "0") + elseif (topt == "k") options.color = [0, 0, 0]; - elseif (topt == "r" || topt == "1") + elseif (topt == "r") if (strncmp (opt, "red", 3)) n = 3; endif options.color = [1, 0, 0]; - elseif (topt == "g" || topt == "2") + elseif (topt == "g") if (strncmp (opt, "green", 5)) n = 5; endif options.color = [0, 1, 0]; - elseif (topt == "b" || topt == "3") + elseif (topt == "b") if (strncmp (opt, "black", 5)) options.color = [0, 0, 0]; n = 5; @@ -223,17 +216,17 @@ n = 6; endif options.color = [1, 1, 0]; - elseif (topt == "m" || topt == "4") + elseif (topt == "m") if (strncmp (opt, "magenta", 7)) n = 7; endif options.color = [1, 0, 1]; - elseif (topt == "c" || topt == "5") + elseif (topt == "c") if (strncmp (opt, "cyan", 4)) n = 4; endif options.color = [0, 1, 1]; - elseif (topt == "w" || topt == "6") + elseif (topt == "w") if (strncmp (opt, "white", 5)) n = 5; endif diff -r 29d734430e5f -r deb553ac2c54 scripts/plot/util/private/__print_parse_opts__.m --- a/scripts/plot/util/private/__print_parse_opts__.m Tue Dec 06 14:53:00 2022 -0500 +++ b/scripts/plot/util/private/__print_parse_opts__.m Tue Dec 06 15:45:27 2022 -0500 @@ -234,7 +234,7 @@ if (any (strcmp (unsupported, arg_st.devopt))) warning ('Octave:print:deprecated-format', - 'print: "%s" format is no more officially supported', ... + 'print: "%s" format is no longer officially supported', arg_st.devopt); endif diff -r 29d734430e5f -r deb553ac2c54 scripts/strings/isstring.m --- a/scripts/strings/isstring.m Tue Dec 06 14:53:00 2022 -0500 +++ b/scripts/strings/isstring.m Tue Dec 06 15:45:27 2022 -0500 @@ -46,7 +46,7 @@ print_usage (); endif - tf = false; + tf = isa (s, 'string'); endfunction @@ -60,4 +60,3 @@ %!assert (isstring ({"b"}), false) %!error isstring () -%!error isstring ("a", "b") diff -r 29d734430e5f -r deb553ac2c54 scripts/testfun/oruntests.m --- a/scripts/testfun/oruntests.m Tue Dec 06 14:53:00 2022 -0500 +++ b/scripts/testfun/oruntests.m Tue Dec 06 15:45:27 2022 -0500 @@ -71,29 +71,34 @@ no_tests = {}; printf ("Processing files in %s:\n\n", directory); fflush (stdout); - for i = 1:numel (flist) - f = flist{i}; - if ((length (f) > 2 && strcmpi (f((end-1):end), ".m")) - || (length (f) > 3 && strcmpi (f((end-2):end), ".cc"))) - ff = fullfile (directory, f); - if (! isfile (ff)) - continue; + unwind_protect + old_dir = cd (directory); + for i = 1:numel (flist) + f = flist{i}; + if ((length (f) > 2 && strcmpi (f((end-1):end), ".m")) + || (length (f) > 3 && strcmpi (f((end-2):end), ".cc"))) + ff = fullfile (directory, f); + if (! isfile (ff)) + continue; + endif + if (has_tests (ff)) + print_test_file_name (f); + [p, n, xf, xb, sk, rtsk, rgrs] = test (ff, "quiet"); + print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs); + fflush (stdout); + elseif (has_functions (ff)) + no_tests(end+1) = f; + endif + elseif (f(1) == "@") + f = fullfile (directory, f); + if (isfolder (f)) + dirs(end+1) = f; + endif endif - if (has_tests (ff)) - print_test_file_name (f); - [p, n, xf, xb, sk, rtsk, rgrs] = test (ff, "quiet"); - print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs); - fflush (stdout); - elseif (has_functions (ff)) - no_tests(end+1) = f; - endif - elseif (f(1) == "@") - f = fullfile (directory, f); - if (isfolder (f)) - dirs(end+1) = f; - endif - endif - endfor + endfor + unwind_protect_cleanup + cd (old_dir); + end_unwind_protect if (! isempty (no_tests)) printf ("\nThe following files in %s have no tests:\n\n", directory); printf ("%s", list_in_columns (no_tests)); diff -r 29d734430e5f -r deb553ac2c54 src/main-gui.cc --- a/src/main-gui.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/src/main-gui.cc Tue Dec 06 15:45:27 2022 -0500 @@ -52,6 +52,7 @@ #include "octave-build-info.h" #include "qt-application.h" #include "sysdep.h" +#include "version.h" static void check_hg_versions (void) @@ -143,7 +144,8 @@ octave::sys::env::set_program_name (argv[0]); - octave::qt_application app (argc, argv); + octave::qt_application app ("octave", "octave-gui", OCTAVE_VERSION, + argc, argv); int ret = app.execute (); diff -r 29d734430e5f -r deb553ac2c54 src/mkoctfile.in.cc --- a/src/mkoctfile.in.cc Tue Dec 06 14:53:00 2022 -0500 +++ b/src/mkoctfile.in.cc Tue Dec 06 15:45:27 2022 -0500 @@ -356,11 +356,6 @@ vars["LD_STATIC_FLAG"] = get_variable ("LD_STATIC_FLAG", %OCTAVE_CONF_LD_STATIC_FLAG%); - // FIXME: Remove LFLAGS in Octave 9 - vars["LFLAGS"] = get_variable ("LFLAGS", DEFAULT_LDFLAGS); - if (vars["LFLAGS"] != DEFAULT_LDFLAGS) - std::cerr << "mkoctfile: warning: LFLAGS is deprecated and will be removed in a future version of Octave, use LDFLAGS instead" << std::endl; - vars["F77_INTEGER8_FLAG"] = get_variable ("F77_INTEGER8_FLAG", %OCTAVE_CONF_F77_INTEGER_8_FLAG%); vars["ALL_FFLAGS"] = vars["FFLAGS"] + ' ' + vars["F77_INTEGER8_FLAG"]; @@ -888,10 +883,6 @@ { ++i; - // FIXME: Remove LFLAGS checking in Octave 9 - if (argv[i] == "LFLAGS") - std::cerr << "mkoctfile: warning: LFLAGS is deprecated and will be removed in a future version of Octave, use LDFLAGS instead" << std::endl; - if (! var_to_print.empty ()) std::cerr << "mkoctfile: warning: only one '" << arg << "' option will be processed" << std::endl; @@ -1317,13 +1308,12 @@ octave_libs = "-L" + quote_path (vars["OCTLIBDIR"]) + ' ' + vars["OCTAVE_LIBS"]; - // FIXME: Remove LFLAGS in Octave 9 std::string cmd = (vars["CXXLD"] + ' ' + vars["CPPFLAGS"] + ' ' + vars["ALL_CXXFLAGS"] + ' ' + vars["RDYNAMIC_FLAG"] + ' ' + pass_on_options + ' ' + output_option + ' ' + objfiles + ' ' + libfiles + ' ' + ldflags + ' ' + vars["ALL_LDFLAGS"] + ' ' - + vars["LFLAGS"] + ' ' + octave_libs + ' ' + + octave_libs + ' ' + vars["OCTAVE_LINK_OPTS"] + ' ' + vars["OCTAVE_LINK_DEPS"]); int status = run_command (cmd, verbose, printonly); @@ -1348,12 +1338,11 @@ + ' ' + vars["OCTAVE_LIBS"]; #endif - // FIXME: Remove LFLAGS in Octave 9 std::string cmd = (vars["CXXLD"] + ' ' + vars["ALL_CXXFLAGS"] + ' ' + pass_on_options + " -o " + octfile + ' ' + objfiles + ' ' + libfiles + ' ' + ldflags + ' ' + vars["DL_LDFLAGS"] + ' ' - + vars["LDFLAGS"] + ' ' + vars["LFLAGS"] + ' ' + octave_libs + ' ' + + vars["LDFLAGS"] + ' ' + octave_libs + ' ' + vars["OCT_LINK_OPTS"] + ' ' + vars["OCT_LINK_DEPS"]); #if defined (OCTAVE_USE_WINDOWS_API) || defined(CROSS) diff -r 29d734430e5f -r deb553ac2c54 test/io.tst --- a/test/io.tst Tue Dec 06 14:53:00 2022 -0500 +++ b/test/io.tst Tue Dec 06 15:45:27 2022 -0500 @@ -297,6 +297,118 @@ %!assert (sscanf ('0177 08', '%i'), [127; 0; 8]) %!assert (sscanf ('0177 08', '%d'), [177; 8]) +## Extensive testing of '%c' +%!test +%! [val, cnt, msg, pos] = sscanf ('abcde', '%c'); +%! assert (val, 'abcde'); +%! assert (cnt, 5); +%! assert (msg, ''); +%! assert (pos, 6); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%10c'); +%! assert (val, 'abcde'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 6); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%3c'); +%! assert (val, 'abcde'); +%! assert (cnt, 2); +%! assert (msg, ''); +%! assert (pos, 6); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%3c', 1); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%c', 5); +%! assert (val, 'abcde'); +%! assert (cnt, 5); +%! assert (msg, ''); +%! assert (pos, 6); + +## Extensive testing of '%s' +%!test +%! [val, cnt, msg, pos] = sscanf ('abcde', '%s'); +%! assert (val, 'abcde'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 6); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%10s'); +%! assert (val, 'abcde'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 6); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%3s'); +%! assert (val, 'abcde'); +%! assert (cnt, 2); +%! assert (msg, ''); +%! assert (pos, 6); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%3s', 1); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%1s', 5); +%! assert (val, 'abcde'); +%! assert (cnt, 5); +%! assert (msg, ''); +%! assert (pos, 6); + +## Extensive testing of '%[]' +%!test +%! [val, cnt, msg, pos] = sscanf ('abcde', '%[a-c]'); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%10[a-c]'); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[a-c]'); +%! assert (val, 'abc'); +%! assert (cnt, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[a-c]', 1); +%! assert (val, 'ab'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 3); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%[a-c]', 1); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 4); + +## Extensive testing of '%[^]' +%!test +%! [val, cnt, msg, pos] = sscanf ('abcde', '%[^de]'); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%10[^de]'); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[^de]'); +%! assert (val, 'abc'); +%! assert (cnt, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[^de]', 1); +%! assert (val, 'ab'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 3); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%[^de]', 1); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 4); + ## bug #47741 %!assert (sscanf ('2147483647', '%d'), 2147483647) %!assert (sscanf ('2147483647', '%i'), 2147483647) @@ -389,10 +501,169 @@ %!test <*62723> %! [val, count, msg, pos] = sscanf ("p", "%c"); -%! assert (val, "p"); +%! assert (val, 'p'); +%! assert (count, 1); +%! assert (msg, ''); +%! assert (pos, 2); + +%!test <*62723> +%! [val, count, msg, pos] = sscanf (' ,1 ', ' %s ', 1); +%! assert (val, ',1'); %! assert (count, 1); -%! assert (msg, ""); -%! assert (pos, 2); +%! assert (msg, ''); +%! assert (pos, 5); + +## Test NaN at EOF +%!test <*63383> +%! [val, count, msg, pos] = sscanf ('2 3 n', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 na', '%f'); +%! assert (val, [2; 3; NA]); +%! assert (count, 3); +%! assert (msg, ''); +%! assert (pos, 7); +%! [val, count, msg, pos] = sscanf ('2 3 nan', '%f'); +%! assert (val, [2; 3; NaN]); +%! assert (count, 3); +%! assert (msg, ''); +%! assert (pos, 8); + +## Test NaN within string +%!test <*63383> +%! [val, count, msg, pos] = sscanf ('2 3 n 4', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 na 4', '%f'); +%! assert (val, [2; 3; NA; 4]); +%! assert (count, 4); +%! assert (msg, ''); +%! assert (pos, 9); +%! [val, count, msg, pos] = sscanf ('2 3 nan 4', '%f'); +%! assert (val, [2; 3; NaN; 4]); +%! assert (count, 4); +%! assert (msg, ''); +%! assert (pos, 10); + +## Test Inf at EOF +%!test <*63383> +%! [val, count, msg, pos] = sscanf ('2 3 i', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 in', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 inf', '%f'); +%! assert (val, [2; 3; Inf]); +%! assert (count, 3); +%! assert (msg, ''); +%! assert (pos, 8); + +## Test Inf within string +%!test <*63383> +%! [val, count, msg, pos] = sscanf ('2 3 i 4', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 in 4', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 inf 4', '%f'); +%! assert (val, [2; 3; Inf; 4]); +%! assert (count, 4); +%! assert (msg, ''); +%! assert (pos, 10); + +## Test '-' at EOF +%!test <*63383> +%! [val, count, msg, pos] = sscanf ('2 3 -', '%d'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 -', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); + +## Test '-' within string +%!test <63383> +%! [val, count, msg, pos] = sscanf ('1 2 - 3', '%d'); +%! assert (val, [1; 2]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('1 2 - 3', '%f'); +%! assert (val, [1; 2]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); + +## Test '+' at EOF +%!test <*63383> +%! [val, count, msg, pos] = sscanf ('2 3 +', '%d'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 +', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); + +## Test '+' within string +%!test <63383> +%! [val, count, msg, pos] = sscanf ('1 2 + 3', '%d'); +%! assert (val, [1; 2]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('1 2 + 3', '%f'); +%! assert (val, [1; 2]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); + +%## Test +NA, -NA, +NAN, -NAN +%!test <*63383> +%! [val, count, msg, pos] = sscanf ('+NA -NA 1 +NAN -NAN', '%f'); +%! assert (val, [NA; NA; 1; NaN; NaN]); +%! assert (count, 5); +%! assert (msg, ''); +%! assert (pos, 20); +%! [val, count, msg, pos] = sscanf ('-NA', '%f'); +%! assert (val, NA); +%! assert (count, 1); +%! assert (msg, ''); +%! assert (pos, 4); +%! [val, count, msg, pos] = sscanf ('+NA', '%f'); +%! assert (val, NA); +%! assert (count, 1); +%! assert (msg, ''); +%! assert (pos, 4); +%! [val, count, msg, pos] = sscanf ('-NaN', '%f'); +%! assert (val, NaN); +%! assert (count, 1); +%! assert (msg, ''); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('+NaN', '%f'); +%! assert (val, NaN); +%! assert (count, 1); +%! assert (msg, ''); +%! assert (pos, 5); %!test %! [a, b, c] = sscanf ("1.2 3 foo", "%f%d%s", "C"); @@ -403,14 +674,16 @@ %! && v1 == [1; 2; 3; 4; 5; 6] && c1 == 6 && ischar (m1) %! && v2 == [1; 2] && c2 == 2 && ischar (m2))); -%!error sscanf () -%!error sscanf (1, 2) -%!error sscanf ("foo", "bar", "C", 1) - %!test %! [x, n] = sscanf (" 0.024000 0.200 0.200 2.000 1987 5 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 4 5 1 2 2 5 5 8 2 8 12 6 15 18 28 26 47 88 118 162 192 130 88 56 27 23 14 9 6 3 4 1 0 2 3 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0.026000 0.250 0.250 2.100 3115 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 1 0 1 1 1 0 1 0 1 3 2 0 5 15 25 44 66 145 179 193 172 104 57 17 11 12 2 1 0 1 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.028000 0.300 0.300 2.200 4929 3 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 2 2 3 2 3 14 21 49 80 148 184 218 159 124 63 37 13 12 3 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.030000 0.350 0.350 2.300 7051 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 2 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 2 0 0 0 1 5 6 14 28 51 88 154 177 208 169 124 65 39 15 5 3 3 2 1 0 1 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.032000 0.400 0.400 2.400 9113 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 2 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 2 0 1 0 0 1 1 0 2 3 5 3 17 30 60 117 156 189 209 129 102 64 56 16 11 4 2 2 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0.034000 0.450 0.450 2.500 11811 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 2 1 0 0 1 0 5 5 15 21 57 99 149 190 195 159 130 69 41 16 10 2 5 3 0 1 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.036000 0.500 0.500 2.600 14985 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 2 2 6 10 34 60 95 126 177 194 155 99 71 44 17 6 7 2 0 0 0 3 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.038000 0.550 0.550 2.700 18391 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 2 0 0 1 1 0 1 2 1 0 0 0 1 0 1 3 6 19 27 52 95 161 154 169 134 94 64 37 19 9 6 0 2 1 0 0 0 0 1 2 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 2 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.040000 0.600 0.600 2.800 22933 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 2 0 3 4 7 18 27 47 82 134 163 133 138 101 58 34 26 10 5 2 1 2 1 1 0 2 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0.042000 0.650 0.650 2.900 27719 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 2 8 16 37 51 87 128 153 146 123 105 62 35 24 8 3 5 0 1 2 1 0 0 0 1 1 1 0 0 0 1 0 1 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.044000 0.700 0.700 3.000 32922 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 2 1 0 0 0 0 1 1 1 1 0 0 1 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 1 0 1 1 1 1 0 0 0 1 4 3 5 5 15 35 54 88 132 168 149 105 92 62 30 16 17 4 5 1 0 0 1 0 1 1 0 1 1 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.046000 0.750 0.750 3.100 38973 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 4 3 5 20 37 56 94 110 135 149 124 84 58 36 17 14 7 1 0 2 0 1 0 0 1 1 0 0 0 0 0 1 1 0 0 0 1 0 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 0 0 0 1 0 0 0 1 1 0 1 0 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.048000 0.800 0.800 3.200 45376 5 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 1 1 0 0 2 1 1 2 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 3 18 34 55 82 104 135 116 99 79 60 51 29 10 4 3 1 1 1 0 0 1 0 0 0 1 0 0 3 1 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.050000 0.850 0.850 3.300 52060 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 1 0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 2 2 1 3 12 24 40 39 107 121 127 138 100 86 68 44 23 15 7 3 1 1 0 1 1 0 0 2 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.052000 0.900 0.900 3.400 59454 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 1 0 0 2 0 2 1 0 0 0 1 0 0 1 0 0 0 0 0 3 3 6 21 32 68 90 132 111 122 107 73 57 47 24 11 7 4 2 2 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 2 0 1 1 0 0 1 0 0 0 0 0 3 0 1 0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0.054000 0.950 0.950 3.500 67013 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 1 0 0 0 0 1 0 0 1 1 0 0 0 1 0 1 0 1 2 4 3 7 9 28 31 71 94 115 96 108 78 82 60 38 17 12 11 4 3 1 1 0 2 1 0 0 0 2 1 3 0 0 0 0 3 0 0 1 0 0 0 0 0 0 0 2 0 0 0 1 0 2 0 1 0 2 0 1 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0.056000 1.000 1.000 3.600 75475 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 3 0 0 1 1 2 0 1 4 0 1 8 6 7 17 41 56 71 109 113 84 103 72 54 35 22 6 9 1 7 5 4 0 0 1 0 0 0 0 0 0 1 0 0 2 1 0 0 0 0 2 0 0 1 0 0 1 0 0 0 0 0 0 1 0 2 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 3 0 0 0 1 0 0 0 0 0 0 1 1 0 0 2 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0.058000 1.050 1.050 3.700 83558 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 2 0 0 2 0 0 1 0 3 2 3 6 15 27 41 77 73 94 94 92 76 61 56 42 23 13 11 6 2 1 2 0 1 2 0 0 1 0 1 0 0 1 0 0 1 1 1 0 0 0 1 0 0 0 1 0 0 0 0 1 1 0 0 0 0 2 0 0 0 0 0 1 2 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0.060000 1.100 1.100 3.800 93087 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 2 2 0 0 0 1 0 1 1 0 0 0 1 1 0 4 0 0 1 2 0 3 1 3 5 13 33 31 65 75 77 96 97 80 59 45 36 32 18 2 5 0 1 0 0 1 0 0 3 0 0 0 0 1 0 0 0 0 0 1 0 0 1 2 0 0 0 0 1 0 0 0 0 1 0 1 1 1 0 0 2 0 0 2 0 1 0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.062000 1.150 1.150 3.900 102829 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 1 0 0 0 0 0 1 1 1 0 1 0 1 1 0 1 1 0 2 0 2 1 2 0 0 2 4 3 5 11 9 23 43 53 68 65 87 83 77 59 49 34 18 15 9 4 2 3 2 0 0 0 4 0 1 1 0 0 2 0 0 1 0 0 0 0 1 1 1 0 1 0 0 0 0 2 0 0 0 0 1 0 0 1 1 1 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0.064000 1.200 1.200 4.000 113442 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 1 1 1 0 1 1 1 1 1 0 0 0 1 2 0 0 0 2 0 4 5 11 13 29 39 61 68 61 75 76 74 73 44 37 29 19 6 3 3 2 0 1 2 1 0 0 0 0 1 1 1 0 1 1 0 0 0 1 0 1 1 0 1 2 0 2 1 1 1 0 0 0 0 1 0 0 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0.066000 1.250 1.250 4.100 126668 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 1 0 0 0 1 1 2 3 0 2 1 2 0 1 0 3 0 0 0 1 0 1 1 3 0 0 1 3 0 2 4 3 12 12 30 48 56 66 77 78 71 82 52 31 32 19 20 16 8 2 1 3 0 0 2 1 0 1 0 1 0 0 0 1 3 1 0 1 0 1 1 1 0 0 0 0 0 2 0 2 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 2 0 3 1 0 0 1 0 0 0 0 0 0 1 0 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.068000 1.300 1.300 4.200 138042 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 2 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 3 0 0 1 0 0 1 2 0 0 0 3 0 1 0 0 3 0 1 0 1 1 3 1 4 7 11 14 27 36 44 68 72 70 71 45 44 46 29 13 16 11 5 2 0 3 0 0 0 0 1 1 2 0 0 1 1 2 1 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 2 0 0 1 1 0 1 1 1 0 0 1 0 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.070000 1.350 1.350 4.300 152335 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 2 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 2 0 0 0 0 1 1 1 0 1 1 0 1 1 1 1 0 2 0 0 0 0 0 2 0 1 7 14 19 34 35 54 72 68 72 68 58 48 36 37 27 25 17 1 4 1 0 0 0 1 2 2 0 0 1 1 1 2 1 0 3 1 0 1 0 2 1 0 0 0 1 1 1 2 0 0 0 0 1 1 0 1 1 0 2 1 1 1 1 0 0 0 1 1 0 0 2 0 0 1 0 0 0 1 1 0 2 1 1 0 0 0 0 2 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0.072000 1.400 1.400 4.400 166280 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 1 0 1 0 1 1 1 0 0 1 0 1 0 0 3 4 2 2 0 0 0 0 0 1 1 3 1 0 3 2 2 1 2 2 0 2 2 1 8 14 26 24 29 47 47 68 65 63 55 42 41 26 29 17 8 4 4 1 0 1 2 0 0 0 1 1 2 0 1 2 1 0 0 1 1 1 0 0 1 0 0 0 1 0 0 1 2 1 2 1 0 0 0 0 0 1 1 2 0 2 2 0 0 0 0 1 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0.074000 1.450 1.450 4.500 179484 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 1 0 1 0 0 1 0 1 2 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 2 0 0 1 1 2 1 0 1 1 2 2 0 1 5 6 10 20 43 50 57 62 53 62 66 45 42 33 27 26 23 14 3 0 2 0 1 0 0 1 1 0 0 2 1 1 0 0 3 0 1 1 1 0 1 1 0 1 0 1 2 1 0 0 1 2 0 2 0 0 0 0 1 1 3 1 0 0 2 1 1 1 0 0 0 0 0 0 1 2 0 1 0 0 0 0 0 1 1 0 2 0 0 0 0 0 1 0 2 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0.076000 1.500 1.500 4.600 197657 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 2 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 2 0 0 0 2 1 1 0 1 1 0 1 1 3 2 1 1 2 1 0 1 0 0 0 0 0 1 1 1 0 5 3 7 12 24 38 32 41 48 54 66 71 49 46 31 38 25 15 8 6 6 5 0 1 3 0 1 1 1 1 1 0 1 2 0 1 0 0 0 1 0 2 1 2 0 0 0 0 1 3 1 0 0 0 0 1 1 0 1 0 1 1 1 1 1 0 4 1 1 1 0 3 0 0 0 2 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0.078000 1.550 1.550 4.700 212054 3 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 1 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 2 0 0 0 1 0 0 1 0 1 1 0 1 3 1 0 0 1 2 0 0 0 1 0 0 0 0 0 2 1 2 1 1 1 0 0 1 5 1 1 2 3 5 7 9 11 22 31 37 48 50 52 54 57 37 38 38 33 24 11 19 11 3 1 2 0 3 3 2 1 0 1 3 0 1 1 1 1 1 2 0 0 0 1 1 2 0 1 1 3 0 1 1 0 0 1 0 2 0 1 0 0 1 3 0 2 0 1 0 1 2 0 1 1 1 1 1 0 3 0 1 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 0 0.080000 1.600 1.600 4.800 231971 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 1 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 2 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 2 1 0 1 1 1 0 1 0 0 1 0 1 3 0 0 0 1 0 0 0 1 1 1 0 0 4 1 1 0 2 0 1 1 1 2 0 0 0 1 0 1 2 1 2 3 2 0 1 0 4 3 1 1 1 1 3 1 0 0 0 2 1 0 2 7 17 13 29 47 58 59 52 38 51 51 38 34 35 21 14 13 4 1 0 1 1 1 0 2 2 4 1 0 1 1 4 0 0 0 2 0 2 2 2 0 0 1 3 2 1 1 2 2 2 2 1 0 3 0 2 1 2 1 2 2 0 0 1 1 0 2 0 2 2 0 1 0 2 2 3 1 2 3 1 1 0 1 0 2 0 1 2 1 2 0 2 1 0 0 3 0 0 1 1 1 1 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0.082000 1.650 1.650 4.900 252503 3 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 2 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 2 0 0 1 0 1 2 2 2 1 0 2 0 1 0 1 1 2 2 0 3 0 0 4 1 0 0 3 0 0 1 2 0 1 1 1 3 0 1 0 2 9 11 25 27 34 53 41 49 43 47 36 31 38 22 30 22 18 9 5 9 2 2 1 2 2 3 1 4 1 1 0 0 1 2 0 2 1 0 0 1 3 2 2 1 0 0 0 1 2 1 0 0 0 2 1 1 0 2 0 0 1 0 0 2 1 3 1 1 1 0 2 1 1 0 2 1 0 1 3 0 0 0 0 2 0 0 1 0 0 0 0 0 1 2 1 1 1 0 2 1 0 0 0 2 0 1 0 0 0 0 1 0 0 0 0 1 0 0 2 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0.084000 1.700 1.700 5.000 267889 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 3 0 1 1 1 0 1 2 1 0 2 0 2 4 0 1 0 0 0 1 1 0 1 3 2 0 2 0 4 0 0 2 0 1 4 2 4 3 3 6 10 14 28 37 54 36 40 52 40 50 46 40 32 26 29 12 18 5 2 0 2 4 1 2 1 0 2 1 2 2 1 0 1 0 2 1 2 4 1 1 5 1 0 2 0 1 2 3 2 2 1 2 1 0 2 1 2 1 1 4 1 2 1 4 0 2 2 0 0 3 1 0 2 0 0 1 1 1 0 0 2 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0.086000 1.750 1.750 5.100 290294 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 1 3 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 0 2 1 0 1 0 1 0 0 2 2 0 1 2 2 0 2 0 2 0 1 0 0 1 1 1 3 1 1 1 1 3 4 1 1 2 2 2 1 0 3 0 0 0 2 4 5 6 16 18 20 31 40 54 55 46 41 52 35 27 21 28 27 20 15 8 6 7 1 0 0 3 0 0 2 2 0 3 1 3 1 1 2 0 0 1 2 1 3 2 0 1 2 1 3 1 1 1 1 1 2 0 2 1 0 1 1 1 3 1 1 2 0 1 0 1 0 2 1 1 0 0 1 2 0 3 1 1 0 0 0 1 3 1 1 1 0 0 1 2 1 0 0 1 1 1 0 0 1 0 0 0 0 0 0 2 0 1 0 0 0 2 1 0 2 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0.088000 1.800 1.800 5.200 312476 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 1 0 1 0 1 1 0 0 0 0 0 0 2 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 2 0 0 0 1 0 1 0 0 0 0 0 0 2 1 0 0 1 0 0 1 1 1 1 4 2 0 1 0 0 3 0 0 0 0 0 1 1 4 0 0 0 0 1 1 2 1 0 3 0 0 2 2 4 0 3 1 6 9 10 13 21 24 32 43 33 41 43 49 50 32 26 31 27 12 16 17 3 3 3 5 0 3 0 2 1 3 3 2 1 2 3 1 2 1 1 1 2 0 1 1 0 2 0 3 0 0 2 0 0 0 0 1 0 1 1 3 3 0 1 1 1 1 1 1 2 2 2 0 3 1 0 2 2 2 0 0 0 0 3 1 2 5 1 1 2 0 0 3 3 0 2 2 0 0 0 0 1 2 0 0 1 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0.090000 1.850 1.850 5.300 337348 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 2 0 1 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 2 0 1 1 0 0 0 1 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 2 0 0 0 1 3 2 0 0 2 2 3 3 2 2 2 0 0 1 1 3 1 3 0 0 0 0 0 0 1 2 1 2 1 2 2 2 0 1 1 0 4 2 2 7 6 15 22 21 39 37 50 31 51 30 33 34 34 26 21 14 13 10 9 4 3 3 4 2 2 0 1 2 3 3 0 1 3 2 5 3 2 2 4 0 2 3 0 4 2 1 2 2 2 4 2 1 3 1 3 2 1 3 1 2 4 1 1 1 1 2 4 1 3 3 3 1 0 4 1 0 1 1 1 1 2 3 0 3 0 0 4 1 1 1 0 2 2 2 1 2 2 0 1 1 0 0 0 2 0 1 0 1 0 0 1 0 0 0 1 3 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 0 0 0.092000 1.900 1.900 5.400 357303 3 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 1 1 0 1 0 0 1 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 1 3 1 0 1 0 0 0 0 1 0 0 1 0 0 1 1 2 2 0 0 2 2 1 1 1 1 1 1 0 1 0 0 1 1 1 3 1 1 1 1 1 0 1 4 0 1 1 1 3 0 1 1 2 2 2 0 2 3 2 2 2 2 1 2 1 3 8 22 14 32 36 46 39 42 39 29 36 38 26 24 26 18 16 19 10 9 3 6 5 0 3 2 1 1 1 2 0 2 1 1 0 1 1 3 1 0 2 4 2 2 1 4 1 2 2 1 1 0 1 2 0 2 2 2 4 2 1 1 0 2 1 3 1 2 3 4 2 3 2 3 0 1 2 1 0 0 0 4 1 1 1 2 1 3 1 0 5 1 0 0 0 0 0 0 1 0 2 0 1 2 1 0 1 0 0 0 0 0 1 1 0 1 0 1 4 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0.094000 1.950 1.950 5.500 383138 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 1 1 1 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 2 1 0 1 1 1 0 0 0 0 0 0 1 1 0 1 0 0 1 1 0 1 0 0 0 0 0 0 0 2 1 1 1 1 2 1 0 2 0 1 0 3 2 1 3 0 1 3 1 1 0 5 0 1 0 1 2 0 0 1 1 2 0 0 6 1 0 3 2 2 3 4 5 0 4 2 1 5 4 11 15 22 27 28 57 38 38 40 38 39 38 27 26 30 18 14 10 10 4 4 4 3 3 2 2 2 2 1 1 1 1 2 2 3 4 1 2 3 1 2 1 2 2 2 1 3 2 1 5 0 1 1 1 3 2 2 2 1 3 1 1 0 3 2 2 0 0 2 2 2 0 0 0 2 0 1 3 1 2 3 2 1 1 0 1 1 1 0 3 2 2 1 0 0 1 3 1 1 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 3 1 0 0 0 0 1 0 1 1 0 0 0 1 0 0 0 0 0 0.096000 2.000 2.000 5.600 409868 3 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 2 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 2 0 1 0 0 2 0 2 0 0 0 0 1 0 0 2 1 2 2 2 1 2 1 1 1 1 1 2 0 0 1 1 0 1 0 2 1 2 0 2 0 3 1 2 1 3 1 5 0 2 2 1 2 4 1 2 0 3 1 4 7 5 9 13 22 19 31 27 28 41 34 39 37 22 23 21 22 17 23 15 8 9 3 8 0 3 1 2 2 2 3 1 0 4 2 4 2 2 2 2 4 2 1 1 0 2 0 3 0 3 2 2 1 2 2 1 4 1 2 2 1 1 5 2 1 2 1 2 2 1 0 2 4 3 2 1 2 2 3 2 3 1 2 1 1 1 1 2 1 1 2 2 1 2 3 2 1 1 0 2 2 4 0 1 1 1 1 1 0 0 1 1 3 0 0 0 0 0 1 0 0 2 0 1 2 0 1 1 1 0 1 0 1 0 0 0.098000 2.050 2.050 5.700 439102 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1 1 0 0 1 0 1 0 1 0 0 0 0 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1 0 0 0 0 0 0 0 1 2 0 0 1 1 1 1 2 0 1 1 0 0 0 0 1 1 1 0 4 0 0 0 2 1 1 0 3 4 0 1 2 2 1 0 3 0 3 2 0 0 2 0 1 0 0 1 0 1 3 1 3 5 0 2 2 3 5 2 2 2 0 3 2 3 6 5 16 21 19 23 28 29 35 42 42 44 39 33 23 30 18 25 24 15 13 5 4 2 2 0 3 3 0 0 1 3 0 1 1 3 2 4 3 4 2 1 1 1 3 1 0 0 2 2 4 2 2 1 4 2 4 2 2 2 1 2 2 1 2 0 4 2 2 3 1 2 1 1 2 2 1 2 4 2 1 4 1 2 2 2 2 0 2 0 3 0 1 0 2 1 0 4 2 1 3 2 1 0 2 1 1 1 1 0 1 1 2 1 1 1 2 0 1 0 2 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0.100000 2.100 2.100 5.800 467340 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 1 0 0 1 2 0 0 0 0 0 1 0 2 0 0 2 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 0 1 1 0 0 1 0 0 1 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 1 2 0 2 2 4 1 0 1 1 2 3 4 1 4 1 5 1 2 1 0 2 2 2 1 5 4 1 5 4 0 1 2 4 2 2 0 2 1 2 5 4 1 1 1 2 5 7 9 16 23 31 15 22 36 36 44 42 29 31 28 28 18 35 12 10 13 8 4 3 2 2 5 1 2 3 3 1 3 3 5 2 0 3 4 1 2 2 3 0 0 5 2 3 6 2 1 2 5 3 4 3 1 1 1 1 2 2 4 0 2 3 1 2 1 2 4 5 4 3 5 2 1 2 0 5 0 2 2 4 1 0 4 1 0 2 1 2 0 0 1 3 2 4 3 0 2 3 3 3 4 2 2 0 0 0 0 1 1 0 3 2 0 1 2 0 4 2 1 1 1 2 0 0 0 0 0 0 0 0 0 0 0.102000 2.150 2.150 5.900 497495 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1 0 2 1 0 0 0 0 1 0 1 0 0 0 0 1 2 0 0 0 0 0 2 0 0 1 0 1 0 0 0 0 1 1 0 0 0 1 1 1 1 2 0 0 1 0 0 0 1 0 2 2 1 0 0 0 2 0 2 1 1 1 6 3 2 0 3 2 2 2 1 1 3 4 1 0 1 2 4 2 3 3 1 1 1 1 3 3 1 4 1 3 4 3 2 3 1 2 2 5 11 11 14 26 27 28 28 28 36 39 42 29 33 24 20 29 18 13 17 13 6 10 4 3 3 6 1 0 1 0 2 1 3 2 3 1 2 3 1 2 1 2 0 2 2 3 1 3 1 1 2 4 4 1 4 3 2 2 3 5 5 3 0 2 5 3 5 1 4 1 1 3 4 2 2 2 2 1 3 0 1 1 2 2 4 2 1 3 2 0 1 2 1 0 2 3 1 2 0 0 0 2 0 0 1 3 0 0 1 2 0 3 1 0 3 1 2 2 1 1 2 0 0 0 0 2 0 0 1 0 0 0 0 0 0.104000 2.200 2.200 6.000 529288 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 1 3 0 2 0 2 0 0 3 2 2 0 4 0 3 2 2 1 3 1 7 3 1 1 0 4 3 2 1 0 0 3 2 3 5 2 1 4 1 5 1 0 3 2 3 0 1 2 4 7 3 7 8 12 15 20 24 34 39 34 35 27 36 34 23 22 26 15 24 12 12 14 5 3 0 7 1 1 3 5 1 2 2 2 4 3 1 2 5 2 2 3 1 1 4 2 1 3 0 4 5 4 6 4 5 3 3 3 3 1 1 5 0 6 1 2 4 2 3 2 1 3 2 0 0 0 1 3 3 0 1 4 0 3 2 3 0 3 3 0 2 3 4 3 1 1 1 2 5 3 1 2 1 1 2 4 1 0 2 4 1 3 0 0 3 0 1 3 0 1 0 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0.106000 2.250 2.250 6.100 560628 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 2 0 1 0 1 0 1 0 1 0 0 1 0 0 0 0 0 0 1 1 0 1 1 0 0 1 1 1 0 1 1 0 0 0 1 1 1 1 0 0 1 1 2 0 0 0 0 2 0 3 1 1 0 0 2 2 2 0 5 2 1 1 1 1 3 1 2 3 0 1 0 0 0 0 1 0 2 2 1 2 1 0 4 3 2 1 2 1 0 4 2 2 0 2 1 1 2 3 1 2 1 2 4 4 11 12 17 19 19 29 30 24 30 35 51 32 36 34 31 19 22 17 11 19 11 7 6 6 3 4 0 3 3 2 0 2 2 2 3 1 5 3 2 3 5 1 0 2 2 5 4 2 3 2 0 1 6 1 2 2 2 2 1 1 2 2 1 4 3 2 2 1 2 5 2 0 2 0 2 5 4 5 2 1 3 6 1 3 4 4 0 0 6 0 2 6 1 2 2 2 0 1 3 1 3 4 2 1 4 2 1 2 3 3 0 3 1 0 2 0 2 1 0 2 1 2 0 0 1 1 0 2 0 0 0 0 0 0 0 0.108000 2.300 2.300 6.200 593293 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 2 0 2 2 1 0 0 2 0 1 0 1 0 0 1 2 2 1 0 0 1 0 2 0 0 0 0 0 1 1 1 1 1 0 0 1 1 0 0 1 1 1 2 2 1 0 1 1 0 1 5 0 2 4 1 0 1 4 2 1 3 2 2 3 2 3 2 0 0 3 4 3 1 3 2 2 0 3 0 2 4 0 3 2 5 1 2 1 4 6 1 2 4 0 3 6 1 7 6 4 5 4 10 16 24 22 20 40 37 44 34 29 21 28 36 36 27 23 24 14 10 4 5 2 5 3 6 2 3 3 1 4 2 1 5 1 3 5 3 2 1 2 2 6 2 3 1 1 0 5 3 3 3 4 5 2 2 3 3 5 5 1 6 2 3 2 6 0 5 2 4 3 5 1 2 2 5 1 2 3 1 2 2 2 4 2 5 5 2 2 2 5 0 1 2 5 2 3 2 3 1 1 2 4 0 2 1 4 2 1 1 1 0 1 2 0 0 1 3 1 0 2 1 1 3 3 2 0 0 0 1 2 0 0 0 0 0.110000 2.350 2.350 6.300 636559 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 1 0 0 0 1 1 2 0 0 1 0 0 0 0 0 0 0 1 2 0 0 1 1 1 0 0 0 0 1 0 1 1 0 0 1 0 0 2 0 1 0 1 0 1 0 0 1 1 3 0 1 2 2 0 2 1 1 1 1 0 1 0 1 3 0 3 2 3 4 3 3 4 3 3 2 6 3 1 1 1 2 4 2 3 1 5 1 3 1 4 5 3 3 2 1 3 7 4 3 10 19 17 19 23 27 28 33 39 36 23 23 32 32 16 19 35 23 12 11 12 8 4 5 7 1 2 2 1 2 3 5 4 2 3 2 6 4 4 2 4 1 2 2 1 2 3 0 4 2 1 2 6 2 2 1 3 3 1 6 4 8 5 2 3 5 2 3 0 3 2 3 1 2 2 3 4 3 8 6 2 1 4 6 3 1 2 0 2 0 2 5 0 3 3 3 3 1 3 3 2 5 4 2 1 4 2 2 4 4 1 3 2 5 2 3 1 2 0 4 0 1 0 6 3 1 2 0 2 0 1 0 0 0 0 0.112000 2.400 2.400 6.400 670484 3 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 1 1 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 2 0 1 1 1 3 0 0 0 2 1 3 0 1 1 1 0 1 1 1 0 0 1 2 0 1 3 1 5 2 3 0 4 0 2 0 0 1 2 1 0 1 0 0 1 0 2 2 3 2 3 2 2 2 3 4 4 2 3 5 3 3 2 3 3 4 2 4 0 3 2 4 4 1 3 1 3 4 2 2 5 2 8 6 12 17 14 22 27 26 29 39 30 24 36 22 22 20 9 19 15 5 12 16 4 7 5 7 5 5 1 4 5 5 4 4 1 4 4 3 3 3 4 2 2 4 2 4 4 4 4 0 2 3 2 1 4 3 6 1 3 3 3 4 5 4 2 2 2 5 3 0 2 5 4 2 5 3 5 1 1 3 1 1 3 6 6 2 3 2 0 3 2 4 3 4 1 2 2 6 2 0 3 2 2 5 3 3 5 2 1 0 3 1 1 2 2 0 1 1 3 2 3 2 1 1 1 1 3 2 1 0 0 0 0 0 0 0 0.114000 2.450 2.450 6.500 711783 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 1 0 2 1 2 0 1 0 0 1 0 0 1 1 1 1 0 0 0 1 1 2 0 1 1 0 0 0 2 1 1 1 1 1 2 1 2 3 3 1 1 1 2 3 1 3 2 2 1 0 1 1 4 4 4 1 0 4 0 0 1 1 2 1 3 2 0 3 4 1 1 1 1 3 2 0 1 3 2 1 2 1 0 3 3 2 5 4 2 5 3 4 2 2 5 3 3 3 3 5 5 8 7 14 12 28 22 24 23 36 33 26 32 27 26 18 30 24 15 13 19 15 17 6 5 7 5 4 3 5 3 1 4 4 9 5 3 1 4 0 0 6 2 5 3 3 3 1 2 3 2 4 1 5 5 3 8 2 1 1 4 1 7 5 6 6 4 4 3 2 6 3 3 3 3 1 3 4 5 4 3 4 3 1 2 3 1 2 1 2 2 6 5 2 2 2 4 2 2 0 2 3 3 2 7 4 4 1 4 2 0 3 1 1 2 1 2 3 1 3 2 2 4 3 1 4 0 0 4 2 2 2 1 0 0 0 0 0.116000 2.500 2.500 6.600 745364 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 2 1 1 2 1 1 1 0 1 0 2 0 1 1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 1 2 3 0 1 4 4 0 4 0 1 0 1 3 3 0 2 1 2 3 2 1 1 1 2 0 4 0 0 4 5 2 5 4 1 3 5 5 4 0 4 4 2 3 2 3 5 2 2 4 2 3 4 2 3 3 3 3 3 2 4 12 10 13 14 19 22 23 24 36 19 32 25 25 36 24 18 20 21 14 18 13 8 6 9 2 9 5 2 5 3 4 4 3 3 0 4 3 2 5 3 4 2 2 6 3 4 0 2 4 1 3 4 7 4 5 3 2 4 5 5 3 4 4 4 2 3 2 4 4 2 1 5 7 1 5 2 4 1 5 5 3 4 4 3 2 4 2 4 0 6 2 3 4 1 2 2 2 4 1 4 2 2 2 5 6 5 1 4 4 2 3 3 3 1 4 3 4 2 6 2 5 3 2 2 1 3 2 2 5 1 1 0 0 1 0 0 0 0.118000 2.550 2.550 6.700 791846 4 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 2 1 1 0 0 0 0 0 1 0 0 0 1 1 0 1 0 1 0 1 1 0 1 0 1 4 1 2 3 0 3 1 0 1 1 1 0 3 1 2 1 1 1 0 0 1 1 1 3 1 3 2 3 1 2 2 1 3 2 4 1 4 0 2 4 1 4 3 2 1 1 2 1 3 2 3 3 2 1 1 5 3 3 3 3 2 3 4 3 5 3 1 1 2 2 3 5 1 2 1 1 4 4 6 9 6 6 13 17 21 20 24 22 25 20 29 23 28 30 26 27 18 20 17 16 17 12 10 8 5 6 6 6 4 3 1 2 4 6 9 2 2 3 5 7 6 2 3 8 5 4 5 6 4 6 5 3 5 3 2 5 3 2 8 3 5 4 5 3 5 4 3 4 8 4 3 8 3 3 3 1 1 2 2 5 4 7 3 2 3 3 2 2 3 6 3 2 2 1 1 5 2 5 6 3 5 3 4 1 3 1 2 1 0 4 1 4 2 2 2 3 1 1 1 1 3 2 0 1 6 1 1 0 2 1 0 1 0 0 0 0 0.120000 2.600 2.600 6.800 833394 3 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 2 1 1 1 2 1 0 0 0 1 0 1 0 0 0 1 0 0 1 1 2 1 0 0 0 0 0 2 2 0 3 1 0 0 2 1 1 1 1 0 1 2 1 5 0 1 0 2 2 1 2 0 4 2 1 4 3 4 2 2 1 2 1 5 2 3 1 3 0 2 2 2 2 3 4 0 4 2 3 3 4 5 2 2 6 3 4 5 5 5 3 4 6 5 1 3 0 5 4 5 1 3 2 2 6 18 13 17 27 27 21 28 28 24 26 27 29 23 21 16 17 19 22 14 11 9 5 14 7 7 6 4 4 12 3 6 4 5 4 6 4 2 0 1 8 1 6 8 5 2 3 4 5 6 4 2 5 8 3 1 1 6 3 7 8 4 1 6 5 2 8 11 5 6 5 6 2 4 5 1 2 7 2 2 5 5 6 3 3 2 3 8 5 1 9 3 3 2 3 6 3 5 3 2 4 6 3 1 3 5 4 4 4 6 3 3 5 0 2 2 5 1 3 2 2 1 4 2 0 2 2 2 2 4 1 2 1 2 1 1 0 0.122000 2.650 2.650 6.900 876007 3 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 1 1 1 1 2 2 1 0 0 1 0 0 0 1 1 0 0 0 2 0 0 4 1 0 2 1 2 0 1 2 0 1 3 2 1 0 1 1 0 1 2 1 0 2 3 3 5 3 3 3 0 1 4 0 1 5 3 4 3 1 2 2 2 4 1 3 3 3 2 3 2 3 2 1 4 4 2 2 5 5 3 4 1 2 1 2 4 2 4 7 2 4 4 2 7 3 5 7 5 3 6 8 10 10 18 21 22 24 14 25 27 29 31 22 25 24 21 27 20 19 22 19 14 13 14 10 5 7 3 4 5 5 3 1 4 3 8 4 5 4 0 3 4 3 4 1 7 6 1 1 3 4 4 3 4 3 6 4 3 4 2 4 4 3 5 6 5 1 1 6 2 6 6 3 5 5 3 2 6 5 4 3 4 6 4 3 5 5 6 5 6 2 4 2 1 2 2 4 2 7 6 2 1 3 1 5 2 1 2 4 3 3 3 2 5 2 4 1 4 3 2 2 5 5 1 1 3 3 2 2 2 2 1 0 0 0 0 0 0.124000 2.700 2.700 7.000 925764 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 2 1 3 0 1 1 0 0 0 0 0 1 1 1 1 0 0 0 1 1 0 1 2 0 0 3 2 0 1 2 1 1 2 0 2 1 2 2 0 0 2 3 2 3 2 2 3 2 2 4 0 2 0 5 1 3 2 3 1 2 3 2 0 6 4 3 6 2 5 0 5 2 1 4 4 5 7 4 2 3 5 2 0 2 5 2 4 7 4 4 4 8 5 3 1 7 2 2 1 5 5 5 14 19 16 22 18 30 29 25 36 23 23 22 25 25 27 26 23 14 20 16 16 10 6 6 6 4 2 6 6 6 6 6 4 6 1 0 3 4 4 5 2 4 3 2 4 4 5 5 5 6 10 6 3 6 8 5 5 8 7 4 6 4 3 4 8 5 5 7 4 6 3 5 8 4 3 4 4 3 4 3 1 3 3 7 2 4 8 3 6 4 3 3 2 5 4 4 3 7 4 5 4 4 3 4 7 2 3 3 4 3 0 2 2 4 3 4 2 4 2 2 6 4 4 6 6 1 5 1 1 2 1 0 0 0 0 0 0.126000 2.750 2.750 7.100 969560 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 1 1 0 1 2 0 2 0 2 2 0 1 1 1 0 0 1 0 1 1 1 1 2 0 1 2 2 1 2 0 0 1 0 1 0 2 1 0 1 0 1 1 2 0 3 0 3 4 3 1 3 2 0 4 0 1 2 0 3 1 1 2 3 2 2 2 5 1 7 1 5 1 5 4 2 0 0 1 2 1 3 2 3 3 5 4 10 10 2 5 11 4 1 2 1 7 3 5 4 4 1 5 10 8 7 9 9 20 20 21 33 21 28 20 27 32 21 29 22 20 24 15 13 27 14 13 15 10 9 3 11 6 7 5 3 6 8 5 4 4 1 3 3 5 2 7 3 6 6 1 6 4 6 5 3 4 2 4 3 3 9 4 5 4 4 5 2 3 10 4 3 2 6 10 6 3 6 5 5 5 4 8 8 5 4 3 6 4 4 2 4 4 4 5 7 4 4 4 4 5 2 2 3 4 5 2 1 3 2 6 2 7 7 1 6 4 4 6 5 5 4 0 2 2 3 2 7 5 0 4 1 1 4 6 1 0 3 2 0 0 1 0.128000 2.800 2.800 7.200 1022713 5 0 0 0 0 0 0 0 0 0 0 0 0 1 0 2 0 0 0 1 0 1 1 0 0 1 1 1 0 0 0 2 1 0 0 4 0 0 1 2 3 1 1 0 1 0 1 0 3 1 1 1 2 2 1 1 1 3 1 0 2 4 2 1 2 1 2 0 3 1 3 2 1 5 2 1 3 1 2 1 5 3 2 1 2 5 3 8 2 3 2 5 5 4 3 6 4 4 4 3 2 3 8 4 3 4 5 4 5 4 7 6 5 3 3 3 5 2 9 10 7 9 12 11 13 17 15 22 19 33 24 28 30 26 21 24 22 27 20 26 16 10 10 9 20 10 7 4 5 7 7 2 7 5 3 5 1 6 1 5 7 5 6 3 1 5 1 1 3 4 8 6 3 9 5 5 3 6 7 4 6 7 6 4 2 4 6 2 3 6 5 6 7 6 4 4 9 6 8 6 9 7 1 2 6 2 7 5 4 4 4 4 5 5 4 4 3 6 3 5 3 6 4 3 6 6 2 5 2 8 4 5 3 6 5 4 5 8 4 3 5 6 5 5 2 8 1 2 2 5 4 1 3 0 0 0 0 0 0.130000 2.850 2.850 7.300 1081669 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 5 0 0 2 2 0 0 1 0 0 0 1 1 0 2 0 2 2 2 1 0 1 0 2 2 3 1 1 0 2 0 1 0 2 1 1 2 2 0 1 4 3 0 2 1 1 0 2 5 2 1 0 1 3 2 5 2 1 2 5 2 3 4 3 6 6 6 4 6 6 3 1 3 2 3 4 7 5 2 9 7 4 1 4 4 3 2 2 2 7 4 8 4 7 4 6 8 5 1 8 6 10 18 21 18 15 21 24 21 26 22 30 28 27 23 22 21 17 25 20 17 13 17 9 12 7 8 5 4 4 5 5 2 4 1 1 2 5 7 6 4 9 7 7 5 5 5 5 5 2 4 5 3 6 8 2 4 9 4 10 5 1 4 5 5 5 10 3 2 8 6 5 7 3 13 3 3 6 5 1 4 5 9 5 2 7 4 5 6 3 5 6 5 4 5 9 6 4 3 4 4 4 5 8 5 5 0 3 6 3 4 3 7 5 6 4 3 3 6 8 4 1 3 1 2 7 3 4 6 6 1 3 4 1 0 1 0 0 0.132000 2.900 2.900 7.400 1131887 3 0 0 0 0 0 0 0 0 0 1 0 0 1 2 1 1 0 0 0 1 2 2 1 1 0 2 1 1 0 1 1 1 0 2 2 3 1 0 1 0 1 0 2 0 2 0 1 4 0 1 2 2 0 0 0 2 3 0 1 2 3 0 1 2 3 5 6 2 2 3 1 4 4 8 4 3 3 3 7 2 2 5 7 4 1 2 4 8 1 5 2 7 3 4 2 9 6 5 5 6 2 2 3 6 2 5 6 7 7 2 8 3 3 3 3 6 6 5 3 10 15 15 17 19 13 29 20 23 22 34 28 28 33 20 20 22 17 22 18 15 19 14 11 9 13 6 6 13 4 2 9 8 8 7 6 5 6 4 4 9 6 2 8 9 7 2 6 3 7 3 6 3 7 4 4 5 4 5 6 4 7 5 4 10 2 6 6 8 3 6 6 9 5 8 8 7 6 4 8 5 7 5 5 7 3 5 5 5 10 7 3 8 7 5 7 2 4 4 6 4 10 7 6 4 4 4 4 3 2 4 2 6 5 9 7 3 2 6 2 5 1 5 6 2 2 1 9 2 5 2 5 1 0 0 0 1 1 0.134000 2.950 2.950 7.500 1185706 3 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 3 2 1 0 1 1 0 0 0 0 0 1 0 1 1 2 0 1 0 1 2 0 0 0 1 1 0 1 1 1 0 2 2 0 1 3 3 2 3 0 0 2 2 3 2 1 1 3 0 0 1 1 3 4 3 1 1 9 1 4 0 1 3 4 1 3 2 6 4 7 7 3 2 8 5 2 5 2 4 6 7 3 7 7 8 4 7 2 4 7 7 9 9 2 5 5 8 3 5 7 3 6 10 6 10 15 10 13 14 29 21 23 37 26 20 28 20 16 24 25 16 19 21 20 20 17 11 10 12 8 7 7 5 5 5 4 5 6 7 3 6 5 7 5 11 9 6 8 11 6 4 6 8 8 7 7 7 4 5 4 8 5 4 3 4 8 10 7 9 4 7 6 8 9 7 3 5 7 7 6 2 6 4 7 3 9 8 12 7 6 6 6 4 5 7 2 4 7 3 2 4 4 7 1 4 5 0 4 6 3 10 8 5 4 3 4 5 7 5 7 5 7 3 5 2 5 6 4 5 2 4 1 6 6 2 4 2 0 0 1 0 0.136000 3.000 3.000 7.600 1238426 3 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 2 4 0 2 0 2 2 0 1 1 1 0 2 1 1 2 1 0 1 1 0 3 1 0 0 1 0 1 0 0 2 1 1 0 4 0 2 6 3 3 4 0 3 1 2 4 0 4 4 0 1 5 2 2 5 1 3 4 3 3 5 2 4 4 6 2 5 3 4 5 4 5 6 7 5 6 2 8 3 4 7 2 4 4 3 7 6 5 1 4 8 3 7 10 3 3 6 1 5 3 8 11 5 7 15 11 15 17 21 23 21 24 28 16 21 29 15 22 27 28 20 13 19 13 7 15 10 11 9 6 8 8 4 7 5 4 6 5 10 6 7 8 9 3 5 5 9 5 9 4 4 4 3 5 7 4 10 6 8 4 9 8 4 6 7 9 11 6 8 3 5 8 12 3 6 9 7 11 9 6 7 4 7 7 7 2 5 4 5 0 2 9 5 5 5 10 7 5 6 3 9 4 4 13 2 7 5 7 4 7 2 0 4 5 4 4 6 8 1 2 5 6 4 7 3 11 4 3 3 5 5 4 4 3 1 4 2 2 1 1 0 0.138000 3.050 3.050 7.700 1299809 6 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 1 2 1 1 0 0 1 0 0 2 0 1 2 0 0 3 0 0 1 3 1 2 0 2 0 1 1 2 1 2 3 2 1 2 5 2 2 2 4 3 2 5 3 0 3 2 4 5 4 3 0 5 4 1 4 3 8 6 4 4 7 4 5 4 3 6 5 6 10 3 6 6 2 6 3 4 4 3 6 7 6 8 3 4 7 5 4 9 2 4 8 5 9 8 3 7 5 7 7 13 7 11 15 17 16 18 18 18 20 17 26 25 19 20 26 31 22 18 20 18 14 11 16 4 7 11 10 8 9 9 6 3 8 8 7 5 6 10 3 5 6 6 3 12 7 8 8 2 10 4 13 9 9 12 4 5 9 7 9 5 7 4 8 9 6 7 8 10 8 7 5 7 11 6 4 4 4 6 4 9 4 5 9 10 7 4 12 7 4 9 5 10 10 6 8 4 7 2 4 7 2 6 8 4 11 3 3 9 7 6 7 3 8 7 4 8 5 3 7 4 5 5 7 4 6 7 5 5 3 5 2 5 4 1 2 0 0 1 0.140000 3.100 3.100 7.800 1361810 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 3 2 1 0 0 0 1 1 1 2 0 0 0 0 1 0 2 2 2 1 0 0 3 3 0 2 0 6 2 3 1 0 3 3 1 2 2 5 3 5 3 3 2 2 7 3 2 2 3 4 2 3 4 4 1 3 7 4 5 4 2 3 5 4 2 1 3 6 3 4 3 8 7 6 5 3 5 11 5 5 3 3 7 3 6 4 4 2 4 4 4 1 5 5 9 6 6 9 3 10 8 6 8 3 10 8 16 16 13 18 23 29 25 19 19 20 27 19 22 27 24 21 15 18 11 20 21 17 12 5 18 6 12 7 9 11 7 12 11 4 8 8 4 8 7 7 2 6 4 4 9 6 9 3 4 7 7 7 4 10 4 11 5 8 8 8 5 4 4 8 6 4 9 8 12 12 8 5 8 3 10 8 7 5 3 5 6 8 5 6 10 7 2 11 2 5 5 6 8 10 2 7 5 5 14 2 7 3 9 3 5 2 8 2 3 4 4 7 9 5 4 7 6 7 5 6 3 5 4 7 6 7 7 9 3 0 2 1 1 1 0 0 0.142000 3.150 3.150 7.900 1429499 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 1 2 1 1 0 0 0 3 0 2 2 1 0 3 0 2 1 3 0 0 1 1 3 1 2 4 1 5 3 5 1 0 7 1 3 2 3 2 2 2 3 0 0 1 3 6 3 2 2 4 4 4 6 4 3 6 4 10 3 7 2 5 4 7 4 5 8 4 7 4 1 7 11 5 2 10 2 11 3 7 8 10 9 6 3 5 3 6 3 10 11 5 5 9 7 10 8 9 5 15 11 9 18 18 15 24 17 23 17 19 25 17 24 18 37 16 17 21 17 14 20 17 15 15 9 4 11 7 3 8 10 8 8 6 8 3 4 5 8 4 6 3 9 9 6 2 10 4 4 3 8 4 9 1 7 5 9 7 10 9 10 4 6 5 8 6 6 10 10 6 5 7 6 6 10 5 7 8 8 8 7 7 11 12 8 3 10 6 9 13 11 4 6 7 6 3 10 5 8 4 7 7 7 5 8 4 9 5 5 7 6 6 7 11 11 7 8 5 3 5 7 7 10 3 3 6 5 7 9 2 3 7 1 0 0 0 0 1 0.144000 3.200 3.200 8.000 1493946 3 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 2 3 0 0 1 2 1 1 1 4 1 0 1 0 1 2 1 3 1 1 1 1 2 1 1 3 2 6 0 4 0 1 4 2 4 5 2 1 3 0 2 2 4 2 3 2 4 3 5 4 4 4 1 5 1 3 4 5 6 4 7 2 8 8 8 5 3 6 0 7 3 2 2 5 7 5 7 5 8 9 6 4 3 6 8 6 10 2 5 6 3 3 6 6 6 6 17 5 10 6 6 11 11 13 12 21 26 18 24 21 24 23 30 18 22 20 24 19 13 17 25 22 17 15 8 13 7 10 8 9 6 7 9 8 7 8 9 7 7 6 12 5 9 9 12 9 12 6 9 7 10 7 7 4 9 7 4 2 7 4 5 8 8 9 7 6 7 5 9 4 8 13 6 5 4 7 9 6 7 7 9 4 4 5 8 10 9 10 6 6 7 9 12 11 8 8 9 11 5 8 7 5 5 8 5 9 10 5 5 11 11 6 8 8 4 8 5 5 5 4 7 4 5 6 5 6 6 7 7 4 2 6 3 2 1 0 0 0 0 0 0.146000 3.250 3.250 8.100 1562352 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 2 0 1 2 1 1 0 0 1 0 1 2 0 0 0 3 1 2 0 4 4 2 0 0 2 3 2 0 1 3 3 4 0 1 4 3 3 4 5 5 4 2 1 4 2 5 3 2 7 6 3 5 6 5 5 5 1 5 2 7 4 8 7 4 6 5 7 5 3 5 8 1 6 4 6 8 7 6 7 6 3 4 6 3 5 8 4 10 3 3 11 6 5 3 9 6 4 3 17 9 11 11 24 13 15 14 25 26 26 21 17 32 32 22 18 25 29 29 27 24 21 12 23 14 12 11 9 17 7 9 11 3 7 6 5 5 12 3 6 8 7 4 7 11 10 8 9 5 8 2 10 9 8 10 10 7 7 4 7 5 7 7 9 10 8 7 7 16 6 8 10 5 6 6 12 12 7 11 11 8 9 7 8 12 10 7 8 7 11 8 9 7 7 4 9 4 7 14 9 8 8 13 9 8 7 13 5 9 5 7 4 9 5 7 8 7 8 7 3 10 9 3 4 4 4 5 2 6 6 3 5 10 4 4 2 3 0 1 0 0 0.148000 3.300 3.300 8.200 1630559 3 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 4 2 1 1 1 2 1 2 0 2 1 5 0 1 1 4 0 2 1 4 5 3 0 1 1 1 2 1 3 3 3 1 1 1 1 1 3 4 6 6 8 8 4 3 2 7 2 2 1 7 4 4 5 1 10 6 4 4 4 3 3 3 6 11 6 4 5 4 8 5 5 9 4 5 5 7 6 4 13 12 3 6 7 5 2 7 9 7 8 8 4 7 6 4 10 6 8 9 9 9 13 15 17 23 25 13 16 24 22 26 21 27 24 24 21 21 21 15 17 22 25 21 22 17 14 11 8 12 5 9 7 8 5 11 10 6 6 5 9 13 10 9 8 8 8 6 4 9 10 9 9 7 8 7 5 7 8 14 13 5 14 5 12 11 8 9 6 5 4 9 13 7 10 13 11 11 8 5 9 10 8 7 6 7 13 3 13 8 7 13 17 5 8 5 10 7 12 7 6 6 9 7 8 8 11 8 11 9 11 11 8 5 6 10 4 9 3 10 8 7 10 8 7 8 10 10 7 4 11 5 7 8 2 4 3 0 0 1 0 1 0.150000 3.350 3.350 8.300 1707576 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 1 2 1 0 2 0 2 3 1 3 2 2 2 2 0 2 1 4 3 2 2 3 1 2 1 0 2 2 4 2 5 3 3 5 2 8 4 5 4 2 3 6 7 6 1 0 7 4 7 7 6 5 4 3 4 6 6 7 6 2 7 4 4 2 5 5 6 9 3 3 3 6 6 5 3 5 7 8 8 6 8 8 6 8 3 9 6 6 8 8 6 4 8 6 6 10 4 11 6 11 15 23 16 8 17 20 21 19 24 15 14 19 21 30 25 21 15 19 16 18 21 21 15 14 12 16 8 10 12 7 10 9 8 10 10 7 9 8 10 12 6 6 9 11 6 5 9 12 6 7 12 7 5 6 8 5 9 4 11 9 8 8 10 7 6 10 7 11 13 7 4 13 11 8 11 9 16 6 12 11 10 10 19 2 9 11 8 7 8 8 6 13 6 10 12 12 9 12 9 9 8 7 7 9 6 12 8 4 9 9 8 5 7 8 9 5 12 5 7 5 9 10 9 10 3 6 6 8 7 11 3 5 5 4 2 0 0 0 0 0.152000 3.400 3.400 8.400 1777231 3 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 1 1 3 1 0 3 4 2 3 3 3 3 3 2 1 1 1 1 3 3 0 1 8 0 0 5 3 7 4 4 4 4 4 3 5 2 2 5 3 6 1 7 6 1 2 2 5 2 1 6 6 8 7 7 5 10 4 1 6 9 3 4 5 3 5 8 4 9 8 11 8 3 2 7 7 9 10 9 10 8 6 8 6 8 7 10 8 7 3 8 4 10 7 6 8 9 6 5 16 9 19 24 23 17 23 24 22 30 21 15 23 27 20 20 20 18 20 23 18 17 15 19 17 18 13 9 4 4 7 12 7 10 4 8 6 10 5 6 13 2 3 8 7 8 7 3 11 8 7 9 7 19 7 8 9 6 14 8 8 11 10 11 13 14 10 16 8 9 13 8 9 9 12 7 12 11 6 9 15 5 9 9 9 11 11 13 6 10 6 4 12 9 9 12 11 8 6 9 16 10 10 10 8 10 10 6 7 4 1 15 6 8 4 9 13 11 8 10 11 9 8 3 3 6 6 7 9 4 6 8 7 4 2 1 2 2 1 0 0.154000 3.450 3.450 8.500 1849489 6 0 0 0 0 0 0 0 0 0 0 0 1 1 3 0 1 2 2 0 1 4 1 1 0 1 0 2 1 0 0 1 1 1 1 6 3 6 1 3 1 3 3 0 6 0 4 2 7 4 6 4 4 3 7 4 5 7 5 5 2 3 9 9 2 5 5 3 9 4 2 7 6 2 8 2 5 7 12 6 5 4 5 10 4 12 10 6 4 14 7 9 10 11 7 7 7 7 3 9 7 4 3 8 7 5 7 9 6 8 9 6 8 8 12 6 5 11 12 13 11 13 21 26 19 23 25 18 23 22 23 23 18 27 20 15 20 25 24 19 18 12 14 13 15 8 15 10 11 7 9 13 11 12 13 11 11 7 11 13 6 5 10 6 6 10 8 14 5 14 11 8 5 9 7 10 10 8 7 15 13 3 13 12 18 15 7 10 9 10 8 15 9 6 8 9 10 10 9 5 7 7 5 10 11 13 12 12 12 10 6 17 10 11 9 4 8 7 6 6 9 12 8 16 18 7 5 10 8 12 10 15 6 13 11 6 10 16 10 11 16 8 9 5 11 10 14 11 5 2 5 7 3 1 1 0 1 0 0.156000 3.500 3.500 8.600 1920727 4 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 2 1 2 0 3 0 1 1 0 1 0 3 0 4 4 1 3 1 2 3 3 4 3 1 2 3 9 5 2 3 7 3 3 6 5 2 6 1 4 3 2 3 6 5 1 8 3 8 5 3 7 6 13 11 9 5 8 7 7 5 8 7 4 8 6 4 10 4 6 5 6 9 9 12 6 7 10 9 9 8 8 3 8 9 8 8 2 12 11 13 8 13 7 8 6 6 9 6 8 16 13 14 16 16 22 20 21 21 17 20 18 19 22 20 11 20 22 21 14 19 15 23 17 15 12 14 19 16 10 11 14 11 9 11 9 12 8 16 14 9 6 18 10 11 7 10 11 17 10 13 8 10 12 9 12 7 7 10 10 11 11 9 8 8 14 10 10 9 14 9 14 13 9 19 16 17 4 11 8 12 11 10 21 6 10 8 9 12 9 7 7 12 7 16 14 10 13 6 13 8 9 10 6 10 8 7 10 4 6 11 19 12 6 7 5 8 11 10 12 13 9 6 10 5 11 11 4 14 10 7 2 6 5 1 2 5 1 1 0 0 0.158000 3.550 3.550 8.700 1999833 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 2 3 2 2 2 1 2 3 0 1 0 1 3 2 0 0 3 2 3 2 5 7 0 3 4 1 10 7 7 4 5 2 3 4 3 8 3 6 4 4 4 8 2 3 4 5 5 7 1 6 7 8 1 6 8 1 4 4 11 9 4 7 11 9 10 5 6 8 4 3 9 7 9 11 5 5 8 8 4 8 7 8 11 9 12 6 4 13 4 12 10 6 9 11 10 11 10 11 11 11 14 15 14 23 18 17 29 16 26 23 15 19 14 18 19 22 31 13 21 20 12 16 15 14 18 17 15 8 12 14 13 10 10 10 10 10 13 11 6 8 11 8 14 8 10 11 11 8 10 13 5 14 7 12 9 10 10 12 15 18 8 6 9 9 12 8 9 20 14 16 10 11 14 5 5 13 6 11 9 11 15 6 9 13 11 7 8 7 10 8 16 12 11 8 10 14 11 17 11 8 16 13 9 10 5 10 17 13 14 16 8 10 9 11 5 10 9 10 12 8 11 12 11 8 6 7 12 15 13 12 7 13 5 0 3 2 0 0 0 0 0.160000 3.600 3.600 8.800 2073149 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 2 1 2 1 2 2 1 0 2 2 1 0 3 6 4 5 5 2 2 2 5 5 3 6 4 6 4 5 2 4 4 3 2 4 6 3 3 6 5 7 4 5 7 5 3 5 6 13 5 3 10 5 9 7 4 5 6 5 10 6 5 5 6 6 4 14 7 6 11 6 9 10 9 8 5 3 8 10 10 6 6 8 9 5 6 14 7 11 10 9 9 11 13 8 4 5 10 12 6 16 8 8 7 19 20 23 10 16 27 25 23 19 26 21 16 20 21 24 18 25 8 11 13 16 18 13 22 18 9 16 4 16 10 12 13 9 7 9 8 17 11 10 13 10 14 4 9 12 16 8 9 16 17 13 11 14 8 8 13 9 11 15 10 11 14 8 6 4 9 11 18 9 9 8 9 15 11 11 11 9 6 13 13 10 7 8 10 15 14 9 7 4 10 12 17 10 14 13 10 10 12 20 9 7 6 11 15 11 10 8 9 6 10 13 17 6 8 9 6 13 13 16 10 15 5 11 14 11 12 6 5 12 9 4 9 2 4 1 1 0 0 0 0.162000 3.650 3.650 8.900 2156456 5 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 2 0 1 1 3 2 3 4 3 3 2 1 3 6 5 2 3 4 4 3 6 2 3 4 4 5 5 3 4 1 4 5 9 3 3 4 3 3 8 5 6 12 2 10 3 4 6 8 9 8 8 2 2 7 5 8 2 8 9 7 2 6 8 6 5 8 2 7 5 6 13 5 6 8 11 6 10 5 6 3 8 10 11 10 10 14 10 11 8 11 8 12 6 12 5 15 12 13 10 13 13 18 23 12 21 18 21 23 20 30 20 23 26 24 24 21 21 29 19 21 16 23 20 13 19 13 16 11 15 13 13 11 8 11 14 14 13 4 16 15 18 13 9 19 8 11 6 9 14 8 13 12 13 10 13 10 14 11 13 11 8 10 13 11 11 14 11 8 14 11 10 9 14 12 14 18 8 12 7 13 12 10 14 14 8 12 17 11 13 9 12 12 15 7 9 13 17 11 11 11 12 17 12 11 16 15 8 9 12 7 13 15 11 16 7 10 7 14 5 18 10 10 8 8 6 6 13 14 6 9 11 9 9 3 5 1 1 3 0 0 0.164000 3.700 3.700 9.000 2234753 3 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 4 1 4 2 1 3 1 1 3 2 3 3 1 3 6 2 4 4 3 3 3 6 5 2 6 4 1 3 3 7 1 4 4 6 12 4 5 2 6 4 9 3 1 8 11 5 2 7 6 3 8 4 7 3 8 3 9 6 7 8 9 2 7 6 9 6 15 6 9 5 9 4 9 17 15 10 2 10 6 8 12 12 11 12 10 9 7 11 8 7 5 11 10 14 16 7 7 7 13 15 10 16 17 21 19 14 18 24 19 27 27 24 20 22 24 21 20 14 24 17 17 18 32 15 12 13 15 12 8 14 11 11 19 11 14 15 18 10 5 12 11 11 9 15 9 7 9 16 12 9 12 10 15 9 18 7 11 12 14 7 20 8 10 13 14 11 6 6 9 11 8 10 16 8 17 13 17 9 16 11 10 9 13 20 17 14 12 10 13 11 9 9 17 20 10 16 8 14 13 14 18 15 15 8 10 12 11 22 12 13 9 12 9 11 14 19 12 12 8 8 12 11 19 11 11 12 15 11 15 13 9 9 10 9 4 9 4 2 1 0 0 0.166000 3.750 3.750 9.100 2327990 3 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 2 0 1 2 2 1 1 0 0 3 1 4 2 6 4 2 4 3 2 5 5 2 3 1 3 1 2 10 2 7 4 3 4 3 3 4 3 10 6 9 6 3 8 5 5 3 4 4 6 8 4 4 7 5 5 11 14 5 3 6 8 8 7 10 11 7 17 7 11 10 8 7 8 12 13 11 12 6 13 9 7 7 6 5 8 13 10 10 14 11 11 8 12 15 14 9 13 10 9 18 13 18 12 23 14 17 24 15 23 25 31 19 17 29 19 19 19 26 25 19 17 22 19 19 19 11 11 12 22 21 8 10 18 10 14 19 17 13 14 10 6 9 10 15 11 5 13 13 11 11 17 16 9 7 14 7 19 6 10 13 7 12 18 14 7 12 15 13 13 9 13 13 13 12 12 14 12 19 10 16 18 18 12 8 10 10 9 7 14 9 11 13 12 8 15 12 11 10 12 11 17 15 19 14 14 12 7 7 12 11 15 16 12 11 12 10 19 19 12 14 12 15 11 20 13 7 18 9 15 19 16 11 5 9 8 6 2 4 0 2 0 1 0.168000 3.800 3.800 9.200 2406866 3 0 0 0 0 0 0 0 0 0 0 1 0 2 0 1 0 2 3 2 3 1 2 1 2 2 5 2 1 2 3 2 2 2 5 3 5 3 3 1 3 6 8 6 1 3 9 6 3 6 10 5 5 7 4 5 7 12 9 5 7 5 6 6 8 3 5 4 7 8 5 6 5 8 13 4 10 2 10 9 7 7 16 9 10 9 13 8 12 9 13 15 9 15 9 10 11 6 6 6 7 7 6 8 15 9 8 9 6 12 12 11 14 12 11 13 8 17 18 18 11 14 19 14 25 21 15 10 15 19 27 23 22 24 17 19 18 12 16 22 21 25 9 25 15 19 15 21 15 8 11 13 12 10 12 7 13 11 17 11 13 10 16 19 14 23 11 8 12 13 10 9 17 4 14 10 7 10 17 14 11 11 20 18 13 8 12 6 8 13 12 23 15 14 15 16 9 14 9 13 14 17 11 17 11 10 15 17 11 6 12 12 14 15 17 12 16 16 8 17 15 15 10 15 11 10 15 12 13 9 12 9 12 15 12 6 18 7 15 14 12 21 18 11 10 18 11 19 11 7 11 3 2 5 4 0 1 1 0.170000 3.850 3.850 9.300 2508471 7 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 1 2 1 4 3 3 1 2 7 0 3 2 2 2 2 5 2 3 2 3 3 4 3 7 3 5 3 4 4 6 2 3 10 4 11 3 13 7 7 5 6 3 8 10 6 6 4 10 11 4 12 7 8 9 7 7 8 4 6 7 9 9 5 9 11 5 14 9 10 7 9 8 8 5 6 11 13 14 10 10 10 10 8 9 9 9 9 14 14 13 11 8 18 9 10 9 16 12 13 15 13 10 17 16 20 14 22 20 26 29 29 27 24 20 37 21 24 13 18 13 28 24 22 25 21 13 14 15 9 11 18 8 16 17 16 13 12 16 11 11 17 15 11 15 10 11 12 13 12 12 20 15 14 15 16 12 17 15 15 12 10 14 14 17 15 19 15 13 13 11 12 16 14 17 16 8 16 12 8 14 13 13 10 10 9 12 11 19 20 13 11 4 15 11 14 11 20 18 18 13 20 12 20 21 15 15 12 13 18 18 11 16 9 14 9 18 11 10 11 20 11 13 17 13 13 12 14 16 10 12 12 23 12 11 12 8 8 1 0 1 2 0 0.172000 3.900 3.900 9.400 2591210 3 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 4 4 3 2 1 3 3 2 3 0 3 6 1 3 1 5 5 4 3 9 9 0 4 7 5 3 5 5 8 7 3 3 5 5 8 5 11 10 8 10 3 6 6 6 7 7 8 8 12 9 6 10 8 7 10 8 8 10 4 6 12 20 4 6 11 7 9 10 7 5 10 6 12 11 7 13 13 16 12 6 8 14 13 9 7 5 14 17 17 10 12 11 6 13 11 17 3 23 13 21 12 21 28 11 23 30 28 23 24 26 26 17 21 15 27 23 33 16 22 25 11 20 22 23 21 20 7 21 13 16 12 16 16 13 18 18 9 13 16 15 9 20 13 19 15 8 9 11 14 13 10 9 10 16 15 14 17 15 19 16 12 14 12 14 14 16 19 19 4 24 8 12 15 16 11 15 14 20 14 13 13 14 16 19 14 13 19 14 18 23 15 15 4 14 17 14 8 10 15 20 11 15 19 12 9 13 12 11 16 12 16 13 14 16 13 16 16 19 19 12 11 10 19 15 15 14 12 5 11 18 17 10 13 12 9 6 2 0 0 1 0 0.174000 3.950 3.950 9.500 2675515 3 0 0 0 0 0 0 0 0 0 0 0 2 0 1 1 0 2 1 2 3 3 1 3 1 3 7 5 3 6 4 3 9 4 5 2 5 3 3 3 6 9 5 5 2 6 8 5 8 4 8 5 6 5 6 4 6 3 7 11 6 9 9 3 6 6 7 6 8 7 9 12 18 6 9 8 11 11 8 14 15 15 11 15 13 9 19 10 15 14 9 4 18 5 8 10 8 10 13 9 12 11 8 8 12 6 15 8 9 9 18 7 17 21 9 13 18 14 21 24 18 22 17 26 15 21 23 25 19 26 23 20 27 17 27 20 26 15 22 15 19 15 16 24 12 15 24 13 13 17 11 7 10 21 15 15 16 13 20 22 12 16 12 16 15 14 18 11 12 14 14 24 10 13 16 19 8 11 18 19 15 15 23 16 16 11 12 18 11 13 14 16 10 14 13 18 12 15 15 14 8 11 17 12 22 13 12 14 15 10 11 15 19 15 12 17 8 21 23 13 19 11 8 12 15 11 14 15 19 15 10 17 9 16 14 18 14 16 14 14 23 14 14 13 16 12 14 15 14 9 14 7 5 2 3 1 1 1 0.176000 4.000 4.000 9.600 2779386 5 0 0 0 0 0 0 0 0 0 0 0 0 2 2 3 0 1 3 0 6 2 6 3 1 5 0 4 1 6 5 1 6 3 6 5 6 2 5 4 5 3 9 8 5 7 5 8 4 12 8 12 6 8 5 7 5 7 10 5 5 6 7 9 7 10 7 10 10 8 12 10 6 13 10 11 12 11 10 10 16 9 6 12 9 11 17 10 11 10 14 11 16 7 11 13 12 10 17 14 11 13 12 10 13 16 16 17 17 15 14 11 8 15 13 27 22 14 19 17 22 22 27 18 28 19 27 32 24 33 21 17 23 12 27 25 20 20 17 22 14 15 22 21 14 9 16 12 19 16 17 16 16 20 14 18 15 14 18 10 12 9 16 12 12 10 13 19 12 12 15 14 15 22 12 11 15 18 19 18 10 6 11 14 10 23 17 14 16 19 10 10 16 19 17 23 16 18 19 18 16 12 14 14 14 13 11 10 24 21 22 26 18 18 18 14 17 5 13 17 11 13 16 14 18 16 9 15 15 18 16 14 21 13 22 17 9 8 16 17 16 16 19 7 20 19 18 16 10 6 10 6 3 5 1 0 0 2 0.178000 4.050 4.050 9.700 2869617 3 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 1 4 1 3 2 2 1 2 3 2 2 4 4 7 5 6 5 3 6 6 5 7 8 1 5 2 3 5 5 8 10 7 6 10 9 6 8 9 7 8 10 15 4 10 5 8 8 6 11 8 8 11 7 5 8 14 5 11 7 13 10 9 7 8 9 14 12 10 9 11 6 14 15 14 13 11 9 18 18 10 14 14 10 12 16 12 9 8 14 15 6 11 11 12 10 14 12 11 18 13 13 27 16 23 23 20 21 32 20 18 25 22 24 32 25 34 19 23 21 25 22 25 19 23 19 21 16 19 16 18 9 18 6 13 12 13 18 12 8 19 14 14 11 16 13 15 14 21 11 14 14 13 11 20 14 14 26 10 22 16 18 15 20 24 18 19 19 16 14 14 14 21 13 19 18 20 13 17 11 17 14 22 17 15 15 20 8 21 15 16 16 23 17 13 19 21 20 12 15 18 15 19 15 18 17 20 15 13 14 24 18 15 15 14 18 20 19 17 19 20 21 21 15 19 19 17 11 16 16 11 23 10 20 13 10 5 10 2 3 1 1 0 0.180000 4.100 4.100 9.800 2975040 3 0 0 0 0 0 0 0 0 0 1 0 0 1 2 2 4 4 2 4 4 1 2 5 0 3 3 5 2 5 5 4 9 2 7 8 4 8 3 11 6 10 4 7 8 6 6 5 8 8 7 11 4 4 11 12 7 11 7 10 11 7 11 11 10 9 7 13 12 18 8 14 12 14 12 8 8 16 10 10 14 16 10 6 8 15 15 15 22 13 19 18 12 6 11 10 7 12 12 24 15 17 9 17 21 10 17 18 14 14 14 9 22 11 23 17 15 23 32 20 11 12 20 15 23 30 20 25 19 26 29 19 27 23 15 19 11 30 16 21 24 18 18 14 8 6 25 13 21 13 13 19 13 21 25 23 18 14 14 13 20 12 14 8 10 25 14 15 20 15 10 15 16 21 8 15 20 21 20 13 16 15 20 11 18 17 17 9 12 24 19 13 18 17 20 14 15 20 10 23 19 25 8 7 13 14 11 15 18 13 10 12 10 17 11 24 16 17 11 12 13 16 20 14 26 12 17 13 14 16 16 6 20 16 23 22 11 17 16 14 25 19 17 21 22 19 13 19 16 18 10 11 7 4 6 0 0 2 0.182000 4.150 4.150 9.900 3083416 6 0 0 0 0 0 0 0 0 0 0 0 2 1 1 4 1 3 4 3 5 6 2 1 4 2 3 5 6 6 7 2 4 1 11 7 5 2 6 6 8 9 8 12 7 11 9 6 12 7 8 9 6 6 8 11 6 6 8 11 8 11 12 11 13 9 10 7 9 6 11 9 13 12 12 8 14 15 8 9 8 8 11 22 16 6 11 16 15 9 13 12 12 13 11 15 9 9 16 14 14 12 21 12 12 12 16 19 10 15 18 8 16 14 16 16 21 30 22 9 25 19 19 26 23 33 25 22 21 19 21 20 20 21 20 26 20 29 27 25 25 21 20 25 21 21 18 14 19 15 6 20 18 16 20 16 13 13 15 15 15 15 22 16 15 15 11 21 19 11 19 13 14 15 17 21 12 18 12 22 18 21 18 13 23 15 18 9 21 11 14 23 18 21 25 18 22 15 21 23 15 15 16 19 21 18 19 21 17 13 24 23 22 19 14 20 22 15 14 14 20 20 23 13 18 15 18 20 20 24 9 12 17 21 21 12 16 17 16 16 21 26 19 15 21 22 24 15 11 13 13 6 8 1 4 0 1 0 0.184000 4.200 4.200 10.00 3174897 3 0 0 0 0 0 0 0 0 0 0 0 1 1 2 3 0 5 4 3 3 0 7 3 2 4 2 8 6 4 5 9 3 8 6 4 2 7 6 8 7 9 3 5 8 5 9 7 7 6 11 14 7 12 9 9 5 15 12 14 15 12 9 11 5 8 13 11 12 10 9 17 12 11 8 17 11 19 11 15 9 11 7 15 14 16 16 16 7 12 10 14 13 13 16 16 11 15 13 14 12 16 11 12 13 17 10 13 19 11 17 11 13 14 13 10 19 19 23 24 22 24 24 31 19 23 22 28 21 25 29 17 23 17 21 30 22 19 25 27 27 22 23 23 17 25 17 20 17 12 23 21 9 17 20 16 19 16 17 20 9 16 11 22 16 15 12 15 17 23 24 16 16 18 26 11 16 20 18 10 14 17 26 19 17 15 17 19 12 21 20 24 17 27 13 16 18 19 23 14 19 14 10 11 18 19 6 15 21 23 25 17 17 18 21 27 20 17 18 20 25 22 20 18 22 18 17 15 24 16 15 22 18 22 14 20 20 22 18 22 25 19 26 12 19 19 13 12 16 19 14 9 7 5 4 2 0 2 0.186000 4.250 4.250 10.10 3283256 3 0 0 0 0 0 0 0 0 1 0 0 1 1 4 1 5 2 5 5 3 4 6 3 2 4 7 8 2 6 6 4 10 7 8 7 5 4 4 9 8 18 10 7 6 6 13 12 10 13 10 7 15 4 7 10 13 12 8 8 13 5 14 6 9 14 9 10 16 12 13 11 8 12 11 10 13 9 11 15 17 23 18 13 10 12 11 12 14 14 14 10 12 12 16 13 15 13 13 14 18 10 13 17 14 14 14 12 12 8 18 14 23 20 16 19 16 16 16 27 18 21 19 20 19 37 22 21 22 28 24 26 18 21 28 21 22 21 21 22 16 15 13 22 22 27 22 11 13 20 10 17 16 19 20 30 18 25 8 7 22 18 17 14 23 16 17 11 16 24 19 18 22 15 15 23 16 13 15 22 14 8 12 18 13 15 22 17 15 15 17 27 21 19 21 24 17 10 12 14 19 17 22 18 19 17 28 19 15 14 16 28 17 20 15 11 22 18 19 16 21 17 24 19 22 22 20 10 20 18 18 18 21 18 23 18 32 26 21 21 22 20 22 16 17 20 22 21 17 13 13 11 9 5 0 1 1 1 0.188000 4.300 4.300 10.20 3396610 5 0 0 0 0 0 0 0 0 0 0 0 1 2 3 0 2 5 5 4 3 3 5 1 2 3 6 9 3 3 3 8 7 2 9 5 7 5 11 8 9 7 6 9 6 4 5 8 6 10 9 14 10 15 6 7 13 15 10 13 7 15 10 10 11 14 14 6 7 17 13 19 3 13 9 6 13 13 14 10 11 12 16 17 13 10 15 15 19 19 11 11 15 11 13 9 13 20 8 18 14 18 23 23 23 15 19 20 14 11 7 18 16 15 22 28 20 24 22 25 17 20 39 24 26 25 25 33 25 25 25 33 15 29 18 29 18 12 18 23 17 24 28 22 16 20 33 23 18 23 26 23 15 24 16 16 16 16 17 15 15 16 14 11 9 23 17 13 13 18 12 19 20 30 20 20 15 21 19 16 18 20 23 19 15 10 11 15 19 13 22 22 18 19 16 19 23 16 10 25 23 20 21 20 31 19 19 18 15 22 18 14 13 21 18 19 22 19 16 17 21 14 20 26 18 26 22 19 26 19 20 22 15 13 24 23 15 21 21 21 27 18 22 19 24 17 22 16 18 23 10 12 3 5 3 3 0 0 0.190000 4.350 4.350 10.30 3502025 3 0 0 0 0 0 0 0 0 0 0 0 0 3 0 3 2 3 4 4 3 4 5 10 7 6 6 4 5 12 10 6 6 13 10 6 7 14 9 6 13 10 12 16 3 9 9 7 5 6 13 11 10 8 11 19 12 14 13 16 13 14 9 12 14 13 14 16 10 14 7 16 18 16 9 15 11 20 15 10 14 14 11 14 17 10 6 16 10 15 12 17 17 20 15 7 12 23 15 8 13 12 8 16 15 20 16 16 20 14 11 20 24 23 20 16 18 27 25 31 27 27 25 21 31 27 20 23 24 32 17 21 34 27 17 19 19 25 30 27 21 24 28 30 19 26 21 14 16 21 23 27 8 17 21 17 11 23 15 22 15 18 10 17 20 23 18 18 17 19 22 15 22 21 19 23 18 18 26 17 18 26 18 24 15 22 23 23 19 23 25 23 24 26 10 21 16 32 23 18 19 24 21 28 26 22 19 19 14 30 21 24 23 22 21 13 27 20 27 24 15 20 22 22 13 25 14 19 32 21 18 18 23 22 22 14 18 20 24 14 19 20 18 17 24 29 27 20 12 18 17 11 9 2 3 2 1 0 0.192000 4.400 4.400 10.40 3593938 3 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 2 3 4 7 8 1 5 6 8 3 7 5 4 9 8 8 7 7 9 7 9 9 15 5 7 8 15 14 9 9 13 8 8 15 10 7 10 9 10 14 7 8 18 16 17 11 14 15 13 8 15 8 15 18 16 16 22 12 8 16 13 10 13 13 10 21 11 10 16 16 13 13 17 16 20 23 13 22 16 14 15 22 19 22 15 22 24 16 16 16 19 12 15 16 17 20 18 19 26 17 23 18 32 20 28 36 22 25 30 29 31 36 24 24 21 29 24 32 29 30 23 34 19 33 34 25 20 31 27 24 16 14 21 20 13 24 17 28 13 24 16 26 15 26 21 11 15 20 13 20 18 25 23 18 24 26 22 16 22 14 13 16 20 24 25 19 29 20 15 20 16 25 26 21 22 17 24 22 21 17 23 23 15 19 30 23 17 21 19 18 21 26 14 29 24 20 33 19 15 20 23 28 19 23 25 15 19 17 31 23 18 29 26 25 14 24 25 18 19 19 24 35 31 23 23 14 15 19 11 20 19 24 17 16 9 10 12 3 2 2 0 1 0.194000 4.450 4.450 10.50 3712573 7 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 5 3 5 4 3 11 3 10 4 6 7 8 5 5 5 8 9 12 7 7 11 8 6 7 9 10 13 10 6 13 9 9 9 11 14 14 12 13 10 6 13 13 15 12 13 19 8 14 13 16 11 13 14 15 9 15 16 13 16 17 17 17 23 18 16 19 10 13 18 16 10 9 21 11 22 14 20 14 18 13 15 12 13 14 16 14 15 20 29 17 14 18 8 15 21 15 19 15 22 20 17 15 23 26 16 26 24 23 23 23 23 30 24 29 28 26 35 33 31 22 23 22 20 37 22 27 33 26 27 26 17 16 18 27 22 21 24 18 18 18 17 15 18 14 19 24 22 15 20 21 15 19 25 15 16 26 19 22 29 20 16 13 15 16 32 24 23 13 33 17 22 18 18 23 24 22 21 20 26 21 16 22 18 18 16 15 26 26 17 22 21 13 25 24 13 23 18 18 25 32 20 24 21 17 19 24 24 23 33 19 19 21 32 18 22 23 19 23 32 18 31 22 25 23 23 31 29 21 16 20 20 15 22 14 12 5 10 9 2 1 0 1 0.196000 4.500 4.500 10.60 3829518 3 0 0 0 0 0 0 0 0 0 0 1 2 2 1 6 2 6 5 9 3 5 6 8 6 3 8 10 7 11 9 4 8 9 5 11 10 13 9 16 13 10 9 5 12 9 15 10 13 9 12 18 14 19 9 13 14 12 13 21 17 17 18 16 13 12 16 14 18 10 15 15 16 11 15 22 17 19 17 11 12 26 12 17 19 18 21 20 27 17 18 19 21 14 19 16 12 16 21 20 18 8 17 17 13 13 18 15 19 15 19 20 28 21 29 27 27 34 24 26 31 25 24 16 17 23 23 30 28 18 28 32 28 37 18 26 18 16 33 21 31 21 20 22 19 20 25 18 18 20 11 17 20 22 23 14 14 17 18 20 25 20 19 20 22 19 16 33 25 21 21 24 18 16 22 29 22 16 27 26 28 21 20 22 17 25 23 20 23 18 16 19 26 22 21 22 23 15 20 19 17 23 19 20 15 22 18 22 26 23 23 31 17 29 18 13 15 19 18 24 22 28 22 17 23 24 26 21 23 25 24 29 26 18 41 24 29 22 27 23 28 16 30 24 18 23 19 17 18 21 17 14 8 2 5 2 0 0 0.198000 4.550 4.550 10.70 3950740 3 0 0 0 0 0 0 0 0 0 1 1 1 2 1 3 7 5 6 7 7 7 4 5 6 4 1 8 9 10 9 8 10 8 12 6 10 8 10 8 11 9 10 15 7 11 8 13 11 13 15 15 17 12 10 8 17 12 9 14 12 14 11 14 21 14 15 20 18 16 8 15 22 24 14 10 18 14 15 16 12 10 16 21 16 25 17 20 17 17 20 15 24 15 17 22 25 17 13 22 18 20 19 11 21 22 21 16 21 24 16 22 17 21 17 24 22 24 35 27 24 28 24 32 37 34 25 24 29 37 37 25 28 21 23 24 22 21 20 25 22 32 19 21 22 24 20 21 20 22 18 27 17 14 20 22 22 22 14 19 20 20 21 23 22 14 20 21 23 20 18 23 20 25 31 24 18 22 14 23 22 21 23 27 27 20 21 18 22 23 24 23 21 18 22 17 22 21 35 15 24 24 12 27 30 27 28 22 31 24 24 19 27 24 28 23 25 26 35 27 22 29 21 24 18 19 26 33 29 31 23 25 19 24 26 21 10 23 24 26 28 20 27 26 17 29 22 18 14 22 8 10 11 4 4 1 2 0 0.200000 4.600 4.600 10.80 4068161 5 0 0 0 0 0 0 0 0 0 0 1 1 0 1 5 5 2 9 3 11 6 9 8 7 7 8 3 3 13 10 8 7 5 8 13 8 7 14 12 10 7 15 13 13 11 12 12 14 12 13 12 10 15 11 14 7 16 15 8 15 13 15 13 18 13 17 21 15 12 13 13 17 18 18 18 16 19 20 17 14 17 24 13 12 18 19 19 13 21 18 26 21 23 16 14 18 19 13 33 13 19 20 14 20 23 14 26 19 22 21 21 16 27 30 25 28 22 32 21 30 27 31 21 30 22 27 27 31 27 21 17 38 41 17 21 20 19 30 24 27 20 20 21 30 20 19 19 31 25 24 13 21 23 19 24 33 24 17 20 17 12 25 23 18 24 11 24 25 22 33 20 11 22 31 21 20 26 27 21 26 24 14 23 23 20 20 26 28 10 20 27 24 22 17 27 28 20 23 23 33 20 24 26 32 33 29 21 25 24 17 18 19 27 26 20 24 26 24 24 26 21 19 24 21 36 32 18 33 33 20 23 25 33 19 27 25 27 24 27 21 21 23 28 18 27 25 19 24 15 17 12 15 7 2 1 0 0 ", "%f ", Inf); %! assert (rows (x) == n); +## Test input validation +%!error sscanf () +%!error sscanf (1, "2") +%!error