view libgui/src/variable-editor.h @ 25354:05a690606fd5

Use default title bar to preserve GUI float decorations (bug #53276) * QUnixTerminalImpl.cpp (QUnixTerminalImpl::setBackgroundColor): Use cascading style sheets to set the background color of the TerminalView. * documentation-dock-widget.cc (constructor): Use setWindowTitle() for default title bar instead of set_title(). * files-dock-widget.cc (constructor): Ditto. * history-dock-widget.cc (history_dock_widget::construct): Ditto. * file-editor.cc (file_editor::construct): Ditto. * terminal-dock-widget.cc (constructor): Ditto. * workspace-view.cc (constructor): Ditto. * octave-dock-widget.cc (label_dock_widget::label_dock_widget): Initialize m_default_float_button and m_default_close_button to nullptr then check for the existence of these buttons in the default title bar. Change spacing between title bar icons from 0 to 10. Do not call setTitleBarWidget(). (label_dock_widget::set_title): Use m_title_widget for pointer instead of titleBarWidget(). Call setTitleBarWidget(m_title_widget) to activate use of custom title bar. (qdockwidget_css): Added. New local routine that constructs the cascading style sheet for the QDockWidget used in several places. (octave_dock_widget::octave_dock_widget): Initialize m_recent_float_geom, m_recent_dock_area, m_recent_dock_geom, m_waiting_for_mouse_button_release. Remove m_floating. Connect the topLevelChanged() signal to the toplevel_change() slot. Do not restrict features floatable and closeable. If the m_default_float_button was found, disconnect its default slots and connect it instead to slot make_window(). Enable queuing of make_window() via the queue_make_window() signal. Enable queuing of make_widget() via the queue_make_widget() signal. Connect the m_dock_action triggered() signal to make_window() slot rather than change_floating(). Set the style sheet (icons and tooltips) for the dockable widget and disable the main widget's tooltip. Set all dock widget features. (octave_dock_widget::make_window): Change the input to be bool (unused) so that the function can be used as a slot. Prevent follow-up calls by setting m_waiting_for_mouse_button_release to 'false'. Set focus to the predecessor in tab list. Set floating off prior to making it a toplevel window. Do not perform a second reparent with a custom title bar. Get geometry from m_recent_float_geom rather than settings. Drop use of m_floating. Make the (un)dock icon adjustment more elaborate by using style sheets via the set_style() function. Disconnect the existing behavior and connect the "make widget" behavior into the appropriate button/action. Call raise(), show(), activateWindow() and setFocus() to bring the new window to the front of the GUI desktop. (octave_dock_widget::make_widget): Drop the dock/not-dock logic. When adding widget back to parent window set the area to m_recent_dock_area. Make the (un)dock icon adjustment more elaborate by using style sheets via set_style() function. Disconnect the existing behavior and connect the "make window" behavior into the appropriate button/action. (octave_dock_widget::default_dock): Added. Simply call base setFloating() with argument "false". (octave_dock_widget::event): Reimplement the virtual low-level function to check if a conversion from widget to window took place as a result of a double-click or if a button release took place after a window drag, and if so set m_waiting_for_mouse_button_release to 'false' and emit a queued make_window(). (octave_dock_widget::handle_settings): Get the geometry and docked layout information, stored in m_recent_float_geom, m_recent_dock_area and m_recent_dock_geom. (octave_dock_widget::save_settings): Get saved geometry info from m_recent_float_geom, m_recent_dock_area and m_recent_dock_geom. Use isFloating() rather than m_floating for "Floating" state. (octave_dock_widget::change_floating): Removed. (octave_dock_widget::store_geometry): Added. Reuasable routine to save geometry and dock info in the appropriate variables based on isFloating() state. (octave_dock_widget::moveEvent): Added. Reimplemented virtual routine to store the geometry whenever the widget is moved. (octave_dock_widget::resizeEvent): Added. Reimplemented virtual routine to store the geometry whenever the widget is resized. (octave_dock_widget::toplevel_change): Added. Puts a fallback behavior in place in case the transition to a toplevel window fails on some OS. Also, handles drag-to-float by setting m_waiting_for_mouse_button_release to 'true' if toplevel input is true. If toplevel input is false, set m_waiting_for_mouse_button_release to 'false'. If need to reparent, emit queue_make_widget() to avoid button-click/double-click corruption. (octave_dock_widget::set_style): Use isFloating() instead of m_floating. Condition the style changes to custom title bar widgets on titleBarWidget() and use CSS style sheets to match the default title bar color scheme to that of the custom title bar. Break the css into string variables css_foreground and css_background providing better control in the qdockwidget_css() routine. * octave-dock-widget.h (label_dock_widget:QDockWidget): Add pointers m_default_float_button and m_default_close_button. (label_dock_widget::set_title): Add note about selecting use of default or custom title bar via this routine. (octave_dock_widget:label_dock_widget): Add variables m_recent_float_geom, m_recent_dock_area, m_recent_dock_geom for avoiding using the file settings as an intermediate storage space. Add boolean variable m_waiting_for_mouse_button_release for implementing a single delayed make_window() if needed. (octave_dock_widget::make_window): Change to a public slot with an unused bool input variable. (octave_dock_widget::make_widget): Change to a public slot. (octave_dock_widget::queue_make_window): Added. New signal to queue make_window() and avoid crash when calling make_widget() directly. (octave_dock_widget::queue_make_widget): Added. New signal to queue make_widget() and avoid mouse click corruption when calling make_widget() directly. (octave_dock_widget::event): Added. Reimplement low-level event() routine, check for double-click float and for drag-and-drop float. (octave_dock_widget::moveEvent): Added. Declartion of reimplemented virtual routine. (octave_dock_widget::resizeEvent): Ditto. (octave_dock_widget::default_dock): Added. A simple routine that calls the default setFloating(false). (octave_dock_widget::change_floating): Removed. (octave_dock_widget::toplevel_change): Added. React to topLevelChanged() signal and install the default button action in case toplevel transition fails. Check if (re)parent action needed. (octave_dock_widget::store_geometry): Added. An in-memory copy of the geometry. * variable-editor.cc (variable_dock_widget::variable_dock_widget): Initialize two new state variables m_waiting_for_mouse_move and m_waiting_for_mouse_button_release intending to identify exactly when a float-by-mouse-drag occurs in order to circumvent Qt bug QTBUG-44813. Use pointer m_title_widget instead of titleBarWidget() and construct the layout unconditionally. (variable_dock_widget::toplevel_change): Remove the default input from setFocus(). If toplevel is true, set m_waiting_for_mouse_move in case a mouse-drag occurs. If toplevel is not true, clear the state variables m_waiting_for_mouse_move and m_waiting_for_mouse_button_release. (variable_dock_widget::change_fullscreen): Fix a bug in which geometry was not properly restored during the fullscreen-to-dock transition by moving the copy m_prev_geom after the variable_dock_widget is floated rather than before. (variable_dock_widget::handle_focus_change): Condition the label adjustment on the presence of custom titleBarWidget(). (variable_dock_widget::event): Added. The state-machine logic for detecting a drag-and-drop floating change. When that happens queue a redock-undock. (variable_editor::variable_editor): Use setWindowTitle() for default title bar instead of set_title(). Added to address QTBUG-44813 by using a very simple state machine to identify float-by-mouse-drag from mouse move and button press events. Then emit queue_unfloat_float() to redock and undock the QDockWidget directly which doesn't have the bug. (variable_dock_widget::unfloat_float): Short slot that does setFloating(true) followed by setFloating(false). This code is conditioned on the yet-to-be- fully determined Qt bug range, and need a NULL-function slot routine. (variable_editor::variable_editor): Initialize new variables m_focus_widget and m_focus_widget_vdw to nullptr. Use setWindowTitle() rather than set_title(). (variable_editor::focusInEvent): Make the focusing rules more complex and use the variables m_focus_widget and m_focus_widget_vdw for logic. (variable_editor::focusOutEvent): Removed. (variable_editor::edit_variable): Make the connection between signal queue_unfloat_float() and slot unfloat_float() pre-processor conditioned on the range for Qt bug QTBUG-44813. Condition the connection between the model's update_lable_signal() and label's setText() slot on the presence of custom titleBarWidget(). (variable_editor::variable_destroyed): If the variable_dock_widget that is destroyed matches m_focus_widget_vdw then clear both that variable and m_focus_widget. Make use of the focusInEvent() routine to set the focus to the next logical variable_dock_widget. (variable_editor::variable_focused): Make the association between the currently-focused object and the variable_dock_widget on which it resides. * variable-editor.h (variable_dock_widget:label_dock_widget): Define QTBUG_44813_FIX_VERSION as an indefinite version in the future when Qt developers fix QTBUG-44813. (variable_dock_widget::queue_unfloat_float): Added. New signal. (variable_dock_widget::unfloat_float): Added. New protected slot. (variable_dock_widget::event): Added. Conditioned on QTBUG-44813 range, the overrided virtual function that will identify float-by-mouse-drag scenario. Requires new private Boolean variables m_waiting_for_mouse_move, m_waiting_for_mouse_button_release and m_waiting_for_activation_change. (variable_editor:octave_dock_widget): Change m_variable_focus_widget to m_focus_widget and add variable_dock_widget pointer m_focus_widget_vdw. (variable_editor::focusOutEvent): Removed.
author Daniel J Sebald <daniel.sebald@ieee.org>
date Sun, 06 May 2018 00:19:03 -0500
parents 07bddddc5856
children a78e5b8d5ee7
line wrap: on
line source

/*

Copyright (C) 2013-2018 John W. Eaton
Copyright (C) 2015 Michael Barnes
Copyright (C) 2013 RĂ¼diger Sonderfeld

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
<https://www.gnu.org/licenses/>.

*/

#if ! defined (variable_editor_h)
#define variable_editor_h 1

#include <QHeaderView>
#include <QSettings>
#include <QStackedWidget>
#include <QTableView>

#include "octave-dock-widget.h"
#include "tab-bar.h"

class octave_value;

class QModelIndex;
class QTextEdit;
class QToolBar;

namespace octave
{
  class variable_editor_model;
  class variable_editor_view;

  // The individual variable subwindow class

  class variable_dock_widget : public label_dock_widget
  {
    Q_OBJECT

  public:

    variable_dock_widget (QWidget *p = nullptr);

  signals:

    void variable_focused_signal (const QString& name);

  protected:

    virtual void closeEvent (QCloseEvent *e);

    void resizeEvent (QResizeEvent *event);

  public slots:

    void handle_focus_change (QWidget *old, QWidget *now);

  private slots:

    void change_floating (bool);

    void change_existence (bool);

    void toplevel_change (bool);

    void change_fullscreen (void);

  protected:

    QFrame *m_frame;

#if defined (HAVE_QGUIAPPLICATION)

    QAction *m_fullscreen_action;

    bool m_full_screen;

    bool m_prev_floating;

    QRect m_prev_geom;

#endif

// See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
#define QTBUG_44813_FIX_VERSION 0x999999
  signals:

    void queue_unfloat_float (void);

  protected slots:

    void unfloat_float (void);

#if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION)
  protected:

    bool event (QEvent *event);

  private:

    bool m_waiting_for_mouse_move;

    bool m_waiting_for_mouse_button_release;
#endif
  };

  class variable_editor_stack : public QStackedWidget
  {
    Q_OBJECT

  public:

    variable_editor_stack (QWidget *p = nullptr);

    variable_editor_view *edit_view (void) {return m_edit_view;};

    QTextEdit *disp_view (void) {return m_disp_view;};

  signals:

    void command_signal (const QString& cmd);

    void edit_variable_signal (const QString& name, const octave_value& val);

  public slots:

    void set_editable (bool editable);

    void levelUp (void);

    void save (void);

  private:

    QTextEdit *make_disp_view (QWidget *parent);

    variable_editor_view *m_edit_view;

    QTextEdit *m_disp_view;
  };


  class variable_editor_view : public QTableView
  {
    Q_OBJECT

  public:

    variable_editor_view (QWidget *p = nullptr);

    void setModel (QAbstractItemModel *model);

  signals:

    void command_signal (const QString& cmd);

    void add_edit_actions_signal (QMenu *menu, const QString& qualifier_string);

  public slots:

    void createVariable (void);

    void transposeContent (void);

    QList<int> range_selected (void);

    void delete_selected (void);

    void clearContent (void);

    void cutClipboard (void);

    void copyClipboard (void);

    void pasteClipboard (void);

    void pasteTableClipboard (void);

    void handle_horizontal_scroll_action (int action);

    void handle_vertical_scroll_action (int action);

    void createContextMenu (const QPoint& pt);

    void createColumnMenu (const QPoint& pt);

    void createRowMenu (const QPoint& pt);

    // Convert selection to an Octave expression.
    QString selected_to_octave (void);

    void selected_command_requested (const QString& cmd);

  private:

    void add_edit_actions (QMenu *menu, const QString& qualifier_string);

    variable_editor_model *m_var_model;
  };

  // Gadgets to keep track and restore what variable window
  // was in focus just prior to selecting something on the
  // menu bar

  class HoverToolButton : public QToolButton
  {
    Q_OBJECT

  public:

    HoverToolButton (QWidget *parent = nullptr);

  signals:

    void hovered_signal (void);

    void popup_shown_signal (void);

  protected:

    bool eventFilter (QObject *obj, QEvent *ev);
  };

  class ReturnFocusToolButton : public HoverToolButton
  {
    Q_OBJECT

  public:

    ReturnFocusToolButton (QWidget *parent = nullptr);

  signals:

    void about_to_activate (void);

  protected:

    bool eventFilter (QObject *obj, QEvent *ev);
  };

  class ReturnFocusMenu : public QMenu
  {
    Q_OBJECT

  public:

    ReturnFocusMenu (QWidget *parent = nullptr);

  signals:

    void about_to_activate (void);

  protected:

    bool eventFilter (QObject *obj, QEvent *ev);
  };

  // The variable editor class

  class variable_editor : public octave_dock_widget
  {
    Q_OBJECT

  public:

    variable_editor (QWidget *parent = nullptr);

    ~variable_editor (void) = default;

    // No copying!

    variable_editor (const variable_editor&) = delete;

    variable_editor& operator = (const variable_editor&) = delete;

    void refresh (void);

    static QList<QColor> default_colors (void);

    static QStringList color_names (void);

    void tab_to_front (void);

  public slots:

    void callUpdate (const QModelIndex&, const QModelIndex&);

    void notice_settings (const QSettings *);

    void edit_variable (const QString& name, const octave_value& val);

    void variable_destroyed (QObject *obj);

    void variable_focused (const QString& name);

    void record_hovered_focus_variable (void);

    void restore_hovered_focus_variable (void);

  protected slots:

    void closeEvent (QCloseEvent *);

    void save (void);

    void cutClipboard (void);

    void copyClipboard (void);

    void pasteClipboard (void);

    void pasteTableClipboard (void);

    void levelUp (void);

    // Send command to Octave interpreter.
    // %1 in CMD is replaced with the value of selected_to_octave.
    void relay_selected_command (const QString& cmd);

  signals:

    void updated (void);

    void finished (void);

    void command_signal (const QString& cmd);

    void refresh_signal (void);

    void clear_content_signal (void);

    void copy_clipboard_signal (void);

    void paste_clipboard_signal (void);

    void paste_table_clipboard_signal (void);

    void level_up_signal (void);

    void save_signal (void);

    void delete_selected_signal (void);

    void selected_command_signal (const QString& cmd);

  protected:

    void focusInEvent (QFocusEvent *ev);

  private:

    QAction * add_action (QMenu *menu, const QIcon& icon, const QString& text,
                          const char *member);

    QMainWindow *m_main;

    QToolBar *m_tool_bar;

    int m_default_width;

    int m_default_height;

    int m_add_font_height;

    bool m_use_terminal_font;

    bool m_alternate_rows;

    QString m_stylesheet;

    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;

    QList<QColor> m_table_colors;

    void update_colors (void);

    QAction *add_tool_bar_button (const QIcon &icon, const QString &text,
                                  const QObject *receiver, const char *member);

    void construct_tool_bar (void);

    QString m_current_focus_vname;

    QString m_hovered_focus_vname;

    QWidget *m_focus_widget;

    variable_dock_widget *m_focus_widget_vdw;
  };
}

#endif