GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
octave-dock-widget.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2012-2017 Richard Crozier
4 Copyright (C) 2013-2016 Torsten <ttl@justmail.de>
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if defined (HAVE_CONFIG_H)
25 # include "config.h"
26 #endif
27 
28 #include <QApplication>
29 #include <QToolBar>
30 #include <QAction>
31 #include <QHBoxLayout>
32 #include <QLabel>
33 #include <QSettings>
34 #include <QStyle>
35 
36 #include "resource-manager.h"
37 #include "octave-dock-widget.h"
38 
39 
41  : QDockWidget (p)
42 {
43  _parent = static_cast<QMainWindow *> (p); // store main window
44  _floating = false;
46 
47  connect (this, SIGNAL (visibilityChanged (bool)),
48  this, SLOT (handle_visibility_changed (bool)));
49 
50  connect (p, SIGNAL (settings_changed (const QSettings*)),
51  this, SLOT (handle_settings (const QSettings*)));
52 
53  connect (p, SIGNAL (active_dock_changed (octave_dock_widget*,
57 
58  QStyle *st = style ();
59  _icon_size = 0.75*st->pixelMetric (QStyle::PM_SmallIconSize);
60 
61 #if defined (Q_OS_WIN32)
62  // windows: add an extra title bar that persists when floating
63 
64  setFeatures (QDockWidget::DockWidgetMovable); // not floatable or closeable
65 
66  // the custom (extra) title bar of the widget
67  _dock_action = new QAction
68  (QIcon (":/actions/icons/widget-undock.png"), "", this);
69  _dock_action-> setToolTip (tr ("Undock widget"));
70  connect (_dock_action, SIGNAL (triggered (bool)),
71  this, SLOT (change_floating (bool)));
72  _dock_button = new QToolButton (this);
73  _dock_button->setDefaultAction (_dock_action);
74  _dock_button->setFocusPolicy (Qt::NoFocus);
75  _dock_button->setIconSize (QSize (_icon_size,_icon_size));
76 
77  _close_action = new QAction
78  (QIcon (":/actions/icons/widget-close.png"), "", this);
79  _close_action-> setToolTip (tr ("Hide widget"));
80  connect (_close_action, SIGNAL (triggered (bool)),
81  this, SLOT (change_visibility (bool)));
82  _close_button = new QToolButton (this);
83  _close_button->setDefaultAction (_close_action);
84  _close_button->setFocusPolicy (Qt::NoFocus);
85  _close_button->setIconSize (QSize (_icon_size,_icon_size));
86 
87  _icon_color = "";
88  _title_3d = 50;
89 
90  QHBoxLayout *h_layout = new QHBoxLayout ();
91  h_layout->addStretch (100);
92  h_layout->addWidget (_dock_button);
93  h_layout->addWidget (_close_button);
94  h_layout->setSpacing (0);
95  h_layout->setContentsMargins (5,2,2,2);
96 
97  _title_widget = new QWidget ();
98  _title_widget->setLayout (h_layout);
99  setTitleBarWidget (_title_widget);
100 
101 #else
102 
103  // non windows: qt takes control of floating widgets
104  setFeatures (QDockWidget::DockWidgetMovable |
105  QDockWidget::DockWidgetClosable |
106  QDockWidget::DockWidgetFloatable); // floatable and closeable
107 
108  connect (this, SIGNAL (topLevelChanged (bool)),
109  this, SLOT (change_floating (bool)));
110 
111 #endif
112 
113  // copy & paste handling
114  connect (p, SIGNAL (copyClipboard_signal ()),
115  this, SLOT (copyClipboard ()));
116  connect (p, SIGNAL (pasteClipboard_signal ()),
117  this, SLOT (pasteClipboard ()));
118  connect (p, SIGNAL (selectAll_signal ()),
119  this, SLOT (selectAll ()));
120  // undo handling
121  connect (p, SIGNAL (undo_signal ()), this, SLOT (do_undo ()));
122 
123  installEventFilter (this);
124 
125  setFocusPolicy (Qt::StrongFocus);
126 }
127 
128 void
130 {
131  // save state of this dock-widget
132  QString name = objectName ();
133  QSettings *settings = resource_manager::get_settings ();
134 
135  if (! settings)
136  return;
137 
138  settings->beginGroup ("DockWidgets");
139 
140 #if defined (Q_OS_WIN32)
141  if (_floating) // widget is floating (windows), save actual floating geometry
142  settings->setValue (name+"_floating_geometry", geometry ());
143  else // not floating save docked (normal) geometry
144 #endif
145  settings->setValue (name, saveGeometry ());
146 
147  settings->setValue (name+"Visible", isVisible ()); // store visibility
148  settings->setValue (name+"Floating", _floating); // store visibility
149  settings->setValue (name+"_minimized", isMinimized ()); // store minimized
150 
151  settings->endGroup ();
152  settings->sync ();
153 }
154 
155 // connect signal visibility changed to related slot (called from main-window)
156 void
158 {
159  connect (this, SIGNAL (visibilityChanged (bool)),
160  this, SLOT (handle_visibility (bool)));
161  emit active_changed (isVisible ()); // emit once for init of window menu
162 }
163 
164 // set the widget which previously had focus when tabified
165 void
167 {
168  _predecessor_widget = prev_widget;
169 }
170 
171 // set the title in the dockwidgets title bar
172 void
173 octave_dock_widget::set_title (const QString& title)
174 {
175 #if defined (Q_OS_WIN32)
176  QHBoxLayout* h_layout
177  = static_cast<QHBoxLayout *> (titleBarWidget ()->layout ());
178  QLabel *label = new QLabel (title);
179  label->setStyleSheet ("background: transparent;");
180  h_layout->insertWidget (0,label);
181 #endif
182  setWindowTitle (title);
183 }
184 
185 // set focus to previously active widget in tabbed widget stack
186 void
188 {
189  if (_predecessor_widget) // only != 0 if widget was tabbed
191 
193 }
194 
195 // make the widget floating
196 void
198 {
199 #if defined (Q_OS_WIN32)
200 
201  // windows: the widget has to be reparented (parent = 0)
202 
203  QSettings *settings = resource_manager::get_settings ();
204 
205  // save the docking area and geometry for later redocking
206  // FIXME: dockWidgetArea always returns 2
207  settings->setValue ("DockWidgets/" + objectName () + "_dock_area",
208  _parent->dockWidgetArea (this));
209  settings->setValue ("DockWidgets/" + objectName (), saveGeometry ());
210  settings->sync ();
211 
212  // remove parent and adjust the (un)dock icon
213  setParent (0, Qt::Window);
214  _dock_action->setIcon (QIcon (":/actions/icons/widget-dock"
215  + _icon_color + ".png"));
216  _dock_action->setToolTip (tr ("Dock widget"));
217 
218  // restore the last geometry when floating
219  setGeometry (settings->value ("DockWidgets/" + objectName ()
220  + "_floating_geometry",
221  QRect (50,100,480,480)).toRect ());
222 
223 #else
224 
225  // non windows: Just set the appripriate window flag
226  setWindowFlags (Qt::Window);
227 
228  QString css = styleSheet ();
229  css.replace ("widget-undock","widget-dock");
230  setStyleSheet (css);
231 
232 #endif
233 
234  _floating = true;
235 
236  set_focus_predecessor (); // set focus previously active widget if tabbed
237 }
238 
239 // dock the widget
240 void
242 {
243 #if defined (Q_OS_WIN32)
244 
245  // windows: Since floating widget has no parent, we have to read it
246 
247  QSettings *settings = resource_manager::get_settings ();
248 
249  // save last floating geometry if widget really was floating
250  if (_floating)
251  settings->setValue ("DockWidgets/" + objectName () + "_floating_geometry",
252  geometry ());
253  settings->sync ();
254 
255  if (dock)
256  {
257  // add widget to last saved docking area (dock=true is default)
258  int area
259  = settings->value ("DockWidgets/" + objectName () + "_dock_area",
260  Qt::TopDockWidgetArea).toInt ();
261  _parent->addDockWidget (static_cast<Qt::DockWidgetArea> (area), this);
262 
263  // FIXME: restoreGeometry is ignored for docked widgets
264  // and its child widget
265  restoreGeometry (settings->value
266  ("DockWidgets/" + objectName ()).toByteArray ());
267  }
268  else // only reparent, no docking
269  setParent (_parent);
270 
271  // adjust the (un)dock icon
272  _dock_action->setIcon (QIcon (":/actions/icons/widget-undock"
273  + _icon_color + ".png"));
274  _dock_action->setToolTip (tr ("Undock widget"));
275 
276 #else
277 
278  // non windows: just say we are a docked widget again
279 
280  Q_UNUSED (dock);
281 
282  setWindowFlags (Qt::Widget);
283 
284  QString css = styleSheet ();
285  css.replace ("widget-dock","widget-undock");
286  setStyleSheet (css);
287 
288 #endif
289 
290  _floating = false;
291 }
292 
293 // slot for (un)dock action
294 void
296 {
297  if (_floating)
298  make_widget ();
299  else
300  {
301  make_window ();
302  focus ();
303  }
304 }
305 
306 // slot for hiding the widget
307 void
309 {
310  setVisible (false);
311  emit active_changed (false);
312 }
313 
314 // get focus widget
315 QWidget *
317 {
318  QWidget * w = QApplication::focusWidget ();
319  if (w && w->focusProxy ()) w = w->focusProxy ();
320  return w;
321 }
322 
323 void
325 {
326  QString css;
327  QString css_button;
328  QString dock_icon;
329 
330  QString icon_col = _icon_color;
331 
332  if (_floating)
333  dock_icon = "widget-dock";
334  else
335  dock_icon = "widget-undock";
336 
337 #if defined (Q_OS_MAC)
338  QString alignment = "center";
339 #else
340  QString alignment = "center left";
341 #endif
342  if (_custom_style)
343  {
344 
345  QColor bg_col, fg_col;
346 
347  if (active)
348  {
349  bg_col = _bg_color_active;
350  fg_col = _fg_color_active;
351  icon_col = _icon_color_active;
352  }
353  else
354  {
355  bg_col = _bg_color;
356  fg_col = _fg_color;
357  icon_col = _icon_color;
358  }
359 
360  QColor bg_col_top, bg_col_bottom;
361  if (_title_3d > 0)
362  {
363  bg_col_top = bg_col.lighter (100 + _title_3d);
364  bg_col_bottom = bg_col.darker (100 + _title_3d);
365  }
366  else
367  {
368  bg_col_top = bg_col.darker (100 - _title_3d);
369  bg_col_bottom = bg_col.lighter (100 - _title_3d);
370  }
371 
372  QString background =
373  QString ("background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
374  " stop: 0 %1, stop: 0.60 %2, stop: 0.95 %2 stop: 1.0 %3);").
375  arg (bg_col_top.name ()).
376  arg (bg_col.name ()).
377  arg (bg_col_bottom.name ());
378 
379 #if defined (Q_OS_WIN32)
380  css = background + QString (" color: %1 ;").arg (fg_col.name ());
381 #else
382  css = QString ("QDockWidget::title { " + background +
383  " text-align: " + alignment + ";"
384  " padding: 0px 0px 0px 4px;}\n"
385  "QDockWidget { color: %1 ; "
386  " titlebar-close-icon: url(:/actions/icons/widget-close%2.png);"
387  " titlebar-normal-icon: url(:/actions/icons/"+dock_icon+"%2); }"
388  "QDockWidget::close-button,"
389  "QDockWidget::float-button { border: 0px; icon-size: %3px; width: %3px}"
390  ).
391  arg (fg_col.name ()).arg (icon_col).arg (_icon_size);
392 #endif
393  }
394  else
395  {
396 #if defined (Q_OS_WIN32)
397  css = QString ("");
398 #else
399  css = QString ("QDockWidget::title { text-align: " + alignment + ";"
400  " padding: 0px 0px 0px 4px;}"
401  "QDockWidget {"
402  " titlebar-close-icon: url(:/actions/icons/widget-close.png);"
403  " titlebar-normal-icon: url(:/actions/icons/"+dock_icon+"); }"
404  "QDockWidget::close-button,"
405  "QDockWidget::float-button { border: 0px; icon-size: %1px; width: %1px}"
406  ).arg (_icon_size);
407 #endif
408  }
409 
410 #if defined (Q_OS_WIN32)
411  _title_widget->setStyleSheet (css);
412  css_button = QString ("background: transparent; border: 0px;");
413  _dock_button->setStyleSheet (css_button);
414  _close_button->setStyleSheet (css_button);
415  _dock_action->setIcon (QIcon (":/actions/icons/" + dock_icon + icon_col +
416  ".png"));
417  _close_action->setIcon (QIcon (":/actions/icons/widget-close" + icon_col +
418  ".png"));
419 #else
420  setStyleSheet (css);
421 #endif
422 }
423 
424 void
425 octave_dock_widget::handle_settings (const QSettings *settings)
426 {
428  = settings->value ("DockWidgets/widget_title_custom_style",false).toBool ();
429 
430  _title_3d
431  = settings->value ("DockWidgets/widget_title_3d",50).toInt ();
432 
433  QColor default_var = QColor (0,0,0);
434  _fg_color = settings->value ("Dockwidgets/title_fg_color",
435  default_var).value<QColor> ();
436  default_var = QColor (0,0,0);
437  _fg_color_active = settings->value ("Dockwidgets/title_fg_color_active",
438  default_var).value<QColor> ();
439 
440  default_var = QColor (255,255,255);
441  _bg_color = settings->value ("Dockwidgets/title_bg_color",
442  default_var).value<QColor> ();
443  default_var = QColor (192,192,192);
444  _bg_color_active = settings->value ("Dockwidgets/title_bg_color_active",
445  default_var).value<QColor> ();
446 
447  int r, g, b;
448  _bg_color.getRgb (&r, &g, &b);
449  if (r+g+b < 400)
450  _icon_color = "-light";
451  else
452  _icon_color = "";
453 
454  _bg_color_active.getRgb (&r, &g, &b);
455  if (r+g+b < 400)
456  _icon_color_active = "-light";
457  else
458  _icon_color_active = "";
459 
460  notice_settings (settings); // call individual handler
461 
462  set_style (false);
463 }
464 
466 {
467  if (e->type () == QEvent::NonClientAreaMouseButtonDblClick)
468  {
469  e->ignore (); // ignore double clicks into window decoration elements
470  return true;
471  }
472 
473  return QDockWidget::eventFilter (obj,e);
474 }
475 
476 void
478  octave_dock_widget *w_new)
479 {
480  if (_custom_style && this == w_old)
481  {
482  set_style (false);
483  update ();
484  }
485 
486  if (_custom_style && this == w_new)
487  {
488  set_style (true);
489  update ();
490  }
491 }
492 
493 // close event
494 void
496 {
497  emit active_changed (false);
499  QDockWidget::closeEvent (e);
500 }
virtual void handle_visibility_changed(bool visible)
Slot to steer changing visibility from outside.
octave_dock_widget * _predecessor_widget
void handle_settings(const QSettings *)
octave_value arg(void) const
Definition: ov.h:1350
bool eventFilter(QObject *obj, QEvent *e)
void set_title(const QString &)
void make_widget(bool dock=true)
i e
Definition: data.cc:2724
octave_value arg
Definition: pr-output.cc:3440
OCTAVE_EXPORT octave_value_list any number nd example oindent prints the prompt xample Pick a any number!nd example oindent and waits for the user to enter a value The string entered by the user is evaluated as an so it may be a literal a variable name
Definition: input.cc:871
octave_dock_widget(QWidget *p=0)
virtual void pasteClipboard()
std::complex< double > w(std::complex< double > z, double relerr=0)
void handle_active_dock_changed(octave_dock_widget *, octave_dock_widget *)
void set_predecessor_widget(octave_dock_widget *prev_widget)
void active_changed(bool active)
Custom signal that tells whether a user has clicked away that dock widget, i.e the active dock widget...
virtual void selectAll()
static QSettings * get_settings(void)
virtual void notice_settings(const QSettings *)
p
Definition: lu.cc:138
virtual void copyClipboard()
slots to handle copy & paste
b
Definition: cellfun.cc:398
virtual void closeEvent(QCloseEvent *e)
void set_style(bool active)
virtual void handle_visibility(bool visible)
virtual void do_undo()
slots to handle undo
virtual void focus(void)
virtual void connect_visibility_changed(void)