changeset 25878:bb4af245dff7

Use uimenu objects for default menus in Qt toolkit * Menu.cc (Menu::Menu): use QAction name to tag wether a menu is a builtin or a custom menu based on the uimenu "tag" property. * Figure.cc (hasUiMenuChildren): Remove (Figure::editCopy,Figure::fileCloseFigure,Figure::fileSaveFigureAs, Figure::copy_figure_callback, Figure::save_figure_callback): Remove (Figure::createFigureToolBarAndMenuBar): Don't create menus not backed by uimenu objects (Figure::showMenuBar): Make use of the QAction name for menu triage. Use the difference between previous and current menubar height to adjust the figure position. * __add_default_menu__.m: Create default menus for Qt aswell. Change actions in the "Edit" menu to "Tools" menu. Add a few actions in "Edit" menu. Rename uimenu handles to hui as is conventional in Octave code. * clf.m: With "reset" option, don't unnecessarily delete/recreate default menus.
author Pantxo Diribarne <pantxo.diribarne@gmail.com>
date Wed, 12 Sep 2018 23:19:40 +0200
parents eba6d823cf62
children c25ee75beea1
files libgui/graphics/Figure.cc libgui/graphics/Figure.h libgui/graphics/Menu.cc scripts/plot/util/clf.m scripts/plot/util/private/__add_default_menu__.m
diffstat 5 files changed, 98 insertions(+), 231 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/graphics/Figure.cc	Tue Sep 11 22:18:28 2018 +0200
+++ b/libgui/graphics/Figure.cc	Wed Sep 12 23:19:40 2018 +0200
@@ -82,25 +82,6 @@
     return false;
   }
 
-  static bool
-  hasUiMenuChildren (const figure::properties& fp)
-  {
-    gh_manager::auto_lock lock;
-
-    Matrix kids = fp.get_all_children ();
-
-    for (int i = 0; i < kids.numel (); i++)
-      {
-        graphics_object go (gh_manager::get_object (kids(i)));
-
-        if (go && go.isa ("uimenu") &&
-            go.get ("visible").string_value () == "on")
-          return true;
-      }
-
-    return false;
-  }
-
   static QRect
   boundingBoxToRect (const Matrix& bb)
   {
@@ -154,9 +135,7 @@
         m_statusBar->hide ();
       }
 
-    if (fp.menubar_is ("figure") || hasUiMenuChildren (fp))
-      toffset += m_menuBar->sizeHint ().height ();
-    else
+    if (! fp.menubar_is ("figure"))
       m_menuBar->hide ();
 
     m_innerRect = boundingBoxToRect (fp.get_boundingbox (true));
@@ -319,27 +298,6 @@
 
     m_menuBar = new MenuBar (win);
     win->setMenuBar (m_menuBar);
-
-    QMenu *fileMenu = m_menuBar->addMenu (tr ("&File"));
-    fileMenu->menuAction ()->setObjectName ("builtinMenu");
-    fileMenu->addAction (tr ("&Save"), this, SLOT (fileSaveFigure (bool)));
-    fileMenu->addAction (tr ("Save &As"), this, SLOT (fileSaveFigureAs (void)));
-    fileMenu->addSeparator ();
-    fileMenu->addAction (tr ("&Close Figure"), this,
-                         SLOT (fileCloseFigure (void)), Qt::CTRL | Qt::Key_W);
-
-    QMenu *editMenu = m_menuBar->addMenu (tr ("&Edit"));
-    editMenu->menuAction ()->setObjectName ("builtinMenu");
-    editMenu->addAction (tr ("Cop&y"), this, SLOT (editCopy (bool)),
-                         Qt::CTRL | Qt::Key_C);
-    editMenu->addSeparator ();
-    editMenu->addActions (m_mouseModeGroup->actions ());
-
-    QMenu *helpMenu = m_menuBar->addMenu (tr ("&Help"));
-    helpMenu->menuAction ()->setObjectName ("builtinMenu");
-    helpMenu->addAction (tr ("About Octave"), this,
-                         SLOT (helpAboutOctave (void)));
-
     m_menuBar->addReceiver (this);
   }
 
@@ -581,35 +539,36 @@
   Figure::showMenuBar (bool visible, int h1)
   {
     // Get the height before and after toggling the visibility of builtin menus
-    if (h1 <= 0)
+    if (h1 < 0)
       h1 = m_menuBar->sizeHint ().height ();
 
+    // Keep the menubar visible if it contains custom menus
+    bool keep_visible = visible;
     foreach (QAction *a, m_menuBar->actions ())
       if (a->objectName () == "builtinMenu")
         a->setVisible (visible);
+      else if ((a->objectName () == "customMenu") && a->isVisible ())
+        keep_visible = true;
+    
+    visible = keep_visible;
 
     int h2 = m_menuBar->sizeHint ().height ();
-
-    // Keep the menubar visible if it contains custom menus
-    if (! visible)
-      visible = hasUiMenuChildren (properties<figure> ());
-
-    if ((m_menuBar->isVisible () && ! visible)
+    
+    if (h1 != h2 || (m_menuBar->isVisible () && ! visible)
         || (! m_menuBar->isVisible () && visible))
       {
-        int dy = qMax (h1, h2);
+        int dy = h2 - h1;
+
         QRect r = qWidget<QWidget> ()->geometry ();
 
-        if (! visible)
-          r.adjust (0, dy, 0, 0);
-        else
-          r.adjust (0, -dy, 0, 0);
+        r.adjust (0, -dy, 0, 0);
 
         m_blockUpdates = true;
         qWidget<QWidget> ()->setGeometry (r);
         m_menuBar->setVisible (visible);
         m_blockUpdates = false;
       }
+
     updateBoundingBox (false);
   }
 
@@ -756,18 +715,10 @@
           {
             switch (xevent->type ())
               {
+              case QEvent::ActionAdded:
               case QEvent::ActionChanged:
-                m_previousHeight = m_menuBar->sizeHint ().height ();
-                break;
               case QEvent::ActionRemoved:
-                {
-                  QAction *a = dynamic_cast<QActionEvent *> (xevent)->action ();
-
-                  if (! a->isSeparator ()
-                      && a->objectName () != "builtinMenu")
-                    updateMenuBar ();
-                }
-                break;
+                m_previousHeight = m_menuBar->sizeHint ().height ();
 
               default:
                 break;
@@ -832,26 +783,17 @@
           {
             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<QActionEvent *> (xevent)->action ();
                   if (m_menuBar->sizeHint ().height () != m_previousHeight
-                      && a->objectName () != "builtinMenu"
                       && ! a->isSeparator ())
                     updateMenuBar (m_previousHeight);
                 }
                 break;
-              case QEvent::ActionAdded:
-                {
-                  QAction *a = dynamic_cast<QActionEvent *> (xevent)->action ();
-
-                  if (! a->isSeparator ()
-                      && a->objectName () != "builtinMenu"
-                      && a->isVisible ())
-                    updateMenuBar ();
-                }
-                break;
 
               default:
                 break;
@@ -878,16 +820,6 @@
   }
 
   void
-  Figure::helpAboutOctave (void)
-  {
-    std::string message
-      = octave_name_version_copyright_copying_warranty_and_bugs (true);
-
-    QMessageBox::about (qWidget<QMainWindow> (), tr ("About Octave"),
-                        QString::fromStdString (message));
-  }
-
-  void
   Figure::setMouseMode (MouseMode mode)
   {
     if (m_blockUpdates)
@@ -906,109 +838,6 @@
   }
 
   void
-  Figure::fileSaveFigure (bool prompt)
-  {
-    QString file = fileName ();
-
-    if (file.isEmpty ())
-      {
-        prompt = true;
-
-        file = "untitled.ofig";
-      }
-
-    if (prompt || file.isEmpty ())
-      {
-        QFileInfo finfo (file);
-
-        file = QFileDialog::getSaveFileName (qWidget<FigureWindow> (),
-                                             tr ("Save Figure As"),
-                                             finfo.absoluteFilePath (),
-                                             tr ("Octave Figure File (*.ofig);;Vector Image Formats (*.eps *.epsc *.pdf *.svg *.ps *.tikz);;Bitmap Image Formats (*.gif *.jpg *.png *.tiff)"),
-                                             nullptr,
-                                             QFileDialog::DontUseNativeDialog);
-      }
-
-    if (! file.isEmpty ())
-      {
-        QFileInfo finfo (file);
-
-        setFileName (finfo.absoluteFilePath ());
-
-        octave_link::post_event (this, &Figure::save_figure_callback,
-                                 file.toStdString ());
-      }
-  }
-
-  void
-  Figure::save_figure_callback (const std::string& file)
-  {
-    figure::properties& fp = properties<figure> ();
-    octave_value fnum = fp.get___myhandle__ ().as_octave_value ();
-
-    size_t flen = file.length ();
-
-    if (flen > 5 && file.substr (flen-5) == ".ofig")
-      Ffeval (ovl ("hgsave", fnum, file));
-    else
-      Ffeval (ovl ("print", fnum, file));
-  }
-
-  void
-  Figure::copy_figure_callback (const std::string& format)
-  {
-    std::string msg;
-
-    std::string file = octave::sys::tempnam ("", "oct-", msg) + '.' + format;
-
-    if (file.empty ())
-      {
-        // Report error?
-        return;
-      }
-
-    save_figure_callback (file);
-
-    octave_link::copy_image_to_clipboard (file);
-  }
-
-  void
-  Figure::fileSaveFigureAs (void)
-  {
-    fileSaveFigure (true);
-  }
-
-  void
-  Figure::fileCloseFigure (void)
-  {
-    qWidget<QMainWindow> ()->close ();
-  }
-
-  void
-  Figure::editCopy (bool /* choose_format */)
-  {
-    QString format = "png";
-
-#if 0
-
-    // FIXME: allow choice of image formats.
-
-    if (choose_format)
-      {
-        QFileInfo finfo (file);
-
-        format = QFileDialog::getSaveFileName (qWidget<FigureWindow> (),
-                                               tr ("Save Figure As"),
-                                               finfo.absoluteFilePath (), 0, 0,
-                                               QFileDialog::DontUseNativeDialog);
-      }
-#endif
-
-    octave_link::post_event (this, &Figure::copy_figure_callback,
-                             format.toStdString ());
-  }
-
-  void
   Figure::addCustomToolBar (QToolBar *bar, bool visible)
   {
     QMainWindow *win = qWidget<QMainWindow> ();
--- a/libgui/graphics/Figure.h	Tue Sep 11 22:18:28 2018 +0200
+++ b/libgui/graphics/Figure.h	Wed Sep 12 23:19:40 2018 +0200
@@ -112,18 +112,11 @@
     static void updateBoundingBoxHelper (void*);
 
     void close_figure_callback (void);
-    void copy_figure_callback (const std::string& format);
-    void save_figure_callback (const std::string& file);
 
     void enableMouseTracking (void);
 
   private slots:
     void setMouseMode (MouseMode mode);
-    void fileSaveFigure (bool prompt = false);
-    void fileSaveFigureAs (void);
-    void fileCloseFigure (void);
-    void editCopy (bool choose_format = false);
-    void helpAboutOctave (void);
     void updateMenuBar (int height = -1);
     void updateContainer (void);
     void toggleAxes (void);
--- a/libgui/graphics/Menu.cc	Tue Sep 11 22:18:28 2018 +0200
+++ b/libgui/graphics/Menu.cc	Wed Sep 12 23:19:40 2018 +0200
@@ -80,6 +80,12 @@
 
     action->setText (Utils::fromStdString (up.get_label ()));
 
+    // Tag menus for further triage in Figure.cc
+    if (up.get_tag ().substr (0, 15) == "__default_menu_")
+      action->setObjectName ("builtinMenu");
+    else
+      action->setObjectName ("customMenu");
+
     if (up.is_checked ())
       {
         action->setCheckable (true);
--- a/scripts/plot/util/clf.m	Tue Sep 11 22:18:28 2018 +0200
+++ b/scripts/plot/util/clf.m	Wed Sep 12 23:19:40 2018 +0200
@@ -70,10 +70,13 @@
   endif
 
   if (do_reset)
-    ## Select all the children, including the one with hidden handles.
-    delete (allchild (hfig));
+    ## Delete all the children, including the ones with hidden handles,
+    ## except default menus.
+    kids = allchild (hfig);
+    ismenu = cellfun (@(s) strncmp (s, "__default_menu_", 15), ...
+                      get (kids, "tag")); 
+    delete (kids(! ismenu));
     reset (hfig);
-    __add_default_menu__ (hfig);
     __set_default_mouse_modes__ (hfig);
   else
     ## Select only the chilren with visible handles.
--- a/scripts/plot/util/private/__add_default_menu__.m	Tue Sep 11 22:18:28 2018 +0200
+++ b/scripts/plot/util/private/__add_default_menu__.m	Wed Sep 12 23:19:40 2018 +0200
@@ -26,41 +26,77 @@
 
 ## Author: Kai Habel
 
-function __add_default_menu__ (fig)
-
-  ## Only FLTK toolkit currently provides menubar
-  if (! strcmp (get (fig, "__graphics_toolkit__"), "fltk"))
-    return;
-  endif
-
-  obj = findall (fig, "-depth", 1, "tag", "__default_menu__", "label", "&File");
-  if (isempty (obj))
-    __f = uimenu (fig, "label", "&File", "handlevisibility", "off",
-                       "tag", "__default_menu__");
-      uimenu (__f, "label", "&Save", "callback", @save_cb);
-      uimenu (__f, "label", "Save &As", "callback", @save_cb);
-      uimenu (__f, "label", "&Close", "callback", @close_cb);
+function __add_default_menu__ (hf)
 
-    __e = uimenu (fig, "label", "&Edit", "handlevisibility", "off",
-                       "tag", "__default_menu__");
-      uimenu (__e, "label", "Toggle &grid on all axes", "tag", "toggle", "callback", @grid_cb);
-      uimenu (__e, "label", "Show grid on all axes", "tag", "on", "callback", @grid_cb);
-      uimenu (__e, "label", "Hide grid on all axes", "tag", "off", "callback", @grid_cb);
-      uimenu (__e, "label", "Auto&scale all axes", "callback", @autoscale_cb);
-      gm = uimenu (__e, "label", "GUI &Mode (on all axes)");
-        uimenu (gm, "label", "Pan x and y", "tag", "pan_on", "callback", @guimode_cb);
-        uimenu (gm, "label", "Pan x only", "tag", "pan_xon", "callback", @guimode_cb);
-        uimenu (gm, "label", "Pan y only", "tag", "pan_yon", "callback", @guimode_cb);
-        uimenu (gm, "label", "Disable pan and rotate", "tag", "no_pan_rotate", "callback", @guimode_cb);
-        uimenu (gm, "label", "Rotate on", "tag", "rotate3d", "callback", @guimode_cb);
-        uimenu (gm, "label", "Enable mousezoom", "tag", "zoom_on", "callback", @guimode_cb);
-        uimenu (gm, "label", "Disable mousezoom", "tag", "zoom_off", "callback", @guimode_cb);
-
+  obj = findall (hf, "-depth", 1, "tag", "__default_menu__File", ...
+                 "label", "&File");
+  if (isempty (obj))
+    ## File menu
+    hui = uimenu (hf, "label", "&File", "handlevisibility", "off", ...
+                  "tag", "__default_menu__File");
+    uimenu (hui, "label", "&Open", "callback", @open_cb, ...
+            "accelerator", "o");
+    uimenu (hui, "label", "&Save", "callback", @save_cb, ...
+            "accelerator", "s");
+    uimenu (hui, "label", "Save &As", "callback", @save_cb, ...
+            "accelerator", "S");
+    uimenu (hui, "label", "&Close", "callback", @close_cb, ...
+           "accelerator", "w", "separator", "on");
+    
+    ## Edit menu
+    hui = uimenu (hf, "label", "&Edit", "handlevisibility", "off", ...
+                  "tag", "__default_menu__Edit");
+    uimenu (hui, "label", "&New Figure", "callback", "figure ();", ...
+            "accelerator", "n");
+    uimenu (hui, "label", "&Duplicate Figure",
+            "callback", "copyobj (gcbf (), groot ());", ...
+            "accelerator", "d");
+    uimenu (hui, "label", "Clea&r Figure",
+            "callback", "clf (gcbf ());");
+    uimenu (hui, "label", "Reset Figure",
+            "callback", "reset (gcbf ());");
+    
+    ## Tools menu
+    hui = uimenu (hf, "label", "&Tools", "handlevisibility", "off", ...
+                  "tag", "__default_menu__Tools");
+    uimenu (hui, "label", "Toggle &grid on all axes", "tag", "toggle", ...
+            "callback", @grid_cb);
+    uimenu (hui, "label", "Show grid on all axes", "tag", "on", ...
+            "callback", @grid_cb);
+    uimenu (hui, "label", "Hide grid on all axes", "tag", "off", ...
+            "callback", @grid_cb);
+    uimenu (hui, "label", "Auto&scale all axes", "callback", @autoscale_cb);
+    
+    hui2 = uimenu (hui, "label", "GUI &Mode (on all axes)");
+    uimenu (hui2, "label", "Pan x and y", "tag", "pan_on", ...
+            "callback", @guimode_cb);
+    uimenu (hui2, "label", "Pan x only", "tag", "pan_xon", ...
+            "callback", @guimode_cb);
+    uimenu (hui2, "label", "Pan y only", "tag", "pan_yon", ...
+            "callback", @guimode_cb);
+    uimenu (hui2, "label", "Disable pan and rotate", "tag", ...
+            "no_pan_rotate", "callback", @guimode_cb);
+    uimenu (hui2, "label", "Rotate on", "tag", "rotate3d", ...
+            "callback", @guimode_cb);
+    uimenu (hui2, "label", "Enable mousezoom", "tag", "zoom_on", ...
+            "callback", @guimode_cb);
+    uimenu (hui2, "label", "Disable mousezoom", "tag", "zoom_off", ...
+            "callback", @guimode_cb);
   endif
 
 endfunction
 
 
+function open_cb (h, e)
+  [filename, filedir] = uigetfile ({"*.ofig", "Octave Figure File"}, ...
+                                   "Open Figure");
+  if (filename != 0)
+    fname = fullfile (filedir, filename);
+    tmphf = hgload (fname);
+    set (tmphf, "filename", fname);
+  endif
+endfunction
+
 function save_cb (h, e)
   [hcbo, hfig] = gcbo ();
   lbl = get (hcbo, "label");
@@ -77,7 +113,7 @@
 endfunction
 
 
-function __save_as__ (caller)
+function __save_as__ (hf)
   [filename, filedir] = uiputfile ...
     ({"*.ofig", "Octave Figure File";
       "*.eps;*.epsc;*.pdf;*.svg;*.ps;*.tikz", "Vector Image Formats";
@@ -89,9 +125,9 @@
     set (gcbf, "filename", fname);
     flen = numel (fname);
     if (flen > 5 && strcmp (fname(flen-4:end), ".ofig"))
-      hgsave (caller, fname);
+      hgsave (hf, fname);
     else
-      saveas (caller, fname);
+      saveas (hf, fname);
     endif
   endif
 endfunction