-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathbackend.py
More file actions
163 lines (131 loc) · 5.61 KB
/
backend.py
File metadata and controls
163 lines (131 loc) · 5.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
"""Matplotlib backend to include matplotlib figures as dockwidgets in the
psyplot gui
This backend is based upon matplotlibs qt4agg and qt5agg backends."""
# Disclaimer
# ----------
#
# Copyright (C) 2021 Helmholtz-Zentrum Hereon
# Copyright (C) 2020-2021 Helmholtz-Zentrum Geesthacht
# Copyright (C) 2016-2021 University of Lausanne
#
# This file is part of psyplot-gui and is released under the GNU LGPL-3.O license.
# See COPYING and COPYING.LESSER in the root of the repository for full
# licensing details.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3.0 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LGPL-3.0 license for more details.
#
# You should have received a copy of the GNU LGPL-3.0 license
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from psyplot_gui.compat.qtcompat import (
QDockWidget, Qt, QWidget, QVBoxLayout, with_qt5)
from psyplot_gui.common import DockMixin
from matplotlib.backend_bases import FigureManagerBase
from matplotlib.figure import Figure
if with_qt5:
from matplotlib.backends.backend_qt5agg import (
show, FigureManagerQT, FigureCanvasQTAgg)
else:
from matplotlib.backends.backend_qt4agg import (
show, FigureManagerQT, FigureCanvasQTAgg)
class FiguresDock(QDockWidget):
"""Reimplemented QDockWidget to remove the dock widget when closed
"""
def close(self, *args, **kwargs):
"""
Reimplemented to remove the dock widget from the mainwindow when closed
"""
from psyplot_gui.main import mainwindow
try:
mainwindow.figures.remove(self)
except Exception:
pass
try:
mainwindow.removeDockWidget(self)
except Exception:
pass
return super(FiguresDock, self).close(*args, **kwargs)
class FigureWidget(DockMixin, QWidget):
"""A simple container for figures in the psyplot backend"""
dock_cls = FiguresDock
def new_figure_manager(num, *args, **kwargs):
"""
Create a new figure manager instance
"""
FigureClass = kwargs.pop('FigureClass', Figure)
thisFig = FigureClass(*args, **kwargs)
return new_figure_manager_given_figure(num, thisFig)
def new_figure_manager_given_figure(num, figure):
"""
Create a new figure manager instance for the given figure.
"""
canvas = PsyplotCanvas(figure)
return PsyplotCanvasManager(canvas, num)
class PsyplotCanvasManager(FigureManagerQT):
"""The canvas manager for the psyplot backend interacting with the
mainwindow of the psyplot gui"""
toolbar = None
def __init__(self, canvas, num):
from psyplot_gui.main import mainwindow
self.main = mainwindow
if mainwindow is None:
return super(PsyplotCanvasManager, self).__init__(canvas, num)
parent_widget = FigureWidget()
parent_widget.vbox = vbox = QVBoxLayout()
self.window = dock = parent_widget.to_dock(
mainwindow, title="Figure %d" % num, position=Qt.TopDockWidgetArea,
docktype=None)
if mainwindow.figures:
mainwindow.tabifyDockWidget(mainwindow.figures[-1], dock)
mainwindow.figures.append(dock)
FigureManagerBase.__init__(self, canvas, num)
self.canvas = canvas
self.window.setWindowTitle("Figure %d" % num)
if hasattr(self, "_get_toolbar"):
# legacy solution for matplotlib < 3.6
self.toolbar = self._get_toolbar(canvas, parent_widget)
# add text label to status bar
self.statusbar_label = mainwindow.figures_label
if self.toolbar is not None:
vbox.addWidget(self.toolbar)
self.toolbar.message.connect(self.statusbar_label.setText)
vbox.addWidget(canvas)
parent_widget.setLayout(vbox)
self.parent_widget = parent_widget
# Give the keyboard focus to the figure instead of the
# manager; StrongFocus accepts both tab and click to focus and
# will enable the canvas to process event w/o clicking.
# ClickFocus only takes the focus is the window has been
# clicked
# on. http://qt-project.org/doc/qt-4.8/qt.html#FocusPolicy-enum or
# http://doc.qt.digia.com/qt/qt.html#FocusPolicy-enum
self.canvas.setFocusPolicy(Qt.StrongFocus)
self.canvas.setFocus()
self.window._destroying = False
self.main.show()
def notify_axes_change(fig):
# This will be called whenever the current axes is changed
if self.toolbar is not None:
self.toolbar.update()
self.canvas.figure.add_axobserver(notify_axes_change)
def statusBar(self, *args, **kwargs):
if self.main is None:
return super(PsyplotCanvasManager, self).statusBar(*args, **kwargs)
return self.main.statusBar(*args, **kwargs)
def resize(self, width, height):
self.window.resize(width, height + self.toolbar.sizeHint().height())
class PsyplotCanvas(FigureCanvasQTAgg):
"""The canvas class with reimplemented resizing"""
def resizeEvent(self, event):
"""Reimplemented to make sure that the figure is only resized for
events with height and width greater 0"""
if event.size().width() > 0 and event.size().height() > 0:
super(PsyplotCanvas, self).resizeEvent(event)
FigureManager = PsyplotCanvasManager
FigureCanvas = PsyplotCanvas