mwxlib 1.6.8__py3-none-any.whl → 1.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mwxlib might be problematic. Click here for more details.
- mwx/bookshelf.py +26 -22
- mwx/controls.py +142 -143
- mwx/framework.py +109 -114
- mwx/graphman.py +90 -89
- mwx/matplot2.py +82 -81
- mwx/matplot2g.py +165 -165
- mwx/matplot2lg.py +57 -57
- mwx/mgplt.py +12 -12
- mwx/nutshell.py +306 -288
- mwx/plugins/ffmpeg_view.py +15 -15
- mwx/plugins/fft_view.py +4 -4
- mwx/plugins/frame_listview.py +26 -26
- mwx/plugins/line_profile.py +1 -1
- mwx/utilus.py +40 -40
- mwx/wxmon.py +20 -20
- mwx/wxpdb.py +46 -46
- mwx/wxwil.py +11 -11
- mwx/wxwit.py +15 -15
- {mwxlib-1.6.8.dist-info → mwxlib-1.7.0.dist-info}/METADATA +1 -1
- mwxlib-1.7.0.dist-info/RECORD +28 -0
- mwxlib-1.6.8.dist-info/RECORD +0 -28
- {mwxlib-1.6.8.dist-info → mwxlib-1.7.0.dist-info}/WHEEL +0 -0
- {mwxlib-1.6.8.dist-info → mwxlib-1.7.0.dist-info}/top_level.txt +0 -0
mwx/graphman.py
CHANGED
|
@@ -72,7 +72,7 @@ class Thread:
|
|
|
72
72
|
if self.worker:
|
|
73
73
|
return self.worker.is_alive()
|
|
74
74
|
return False
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
def __init__(self, owner=None):
|
|
77
77
|
self.owner = owner
|
|
78
78
|
self.worker = None
|
|
@@ -90,11 +90,11 @@ class Thread:
|
|
|
90
90
|
'thread_end' : [ None ],
|
|
91
91
|
},
|
|
92
92
|
})
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
def __del__(self):
|
|
95
95
|
if self.active:
|
|
96
96
|
self.Stop()
|
|
97
|
-
|
|
97
|
+
|
|
98
98
|
@contextmanager
|
|
99
99
|
def entry(self):
|
|
100
100
|
"""Exclusive reentrant lock manager.
|
|
@@ -110,26 +110,26 @@ class Thread:
|
|
|
110
110
|
## The thread must be activated to enter.
|
|
111
111
|
## assert self.active, f"{self!r} must be activated to enter {name!r}."
|
|
112
112
|
yield self
|
|
113
|
-
|
|
113
|
+
|
|
114
114
|
def enters(self, f):
|
|
115
115
|
"""Decorator to add a one-time handler for the enter event.
|
|
116
116
|
The specified function will be called from the main thread.
|
|
117
117
|
"""
|
|
118
118
|
return self.handler.binds('thread_begin', _F(f))
|
|
119
|
-
|
|
119
|
+
|
|
120
120
|
def exits(self, f):
|
|
121
121
|
"""Decorator to add a one-time handler for the exit event.
|
|
122
122
|
The specified function will be called from the main thread.
|
|
123
123
|
"""
|
|
124
124
|
return self.handler.binds('thread_end', _F(f))
|
|
125
|
-
|
|
125
|
+
|
|
126
126
|
def wraps(self, f, *args, **kwargs):
|
|
127
127
|
"""Decorator for a function that starts a new thread."""
|
|
128
128
|
@wraps(f)
|
|
129
129
|
def _f(*v, **kw):
|
|
130
130
|
return self.Start(f, *v, *args, **kw, **kwargs)
|
|
131
131
|
return _f
|
|
132
|
-
|
|
132
|
+
|
|
133
133
|
def check(self, timeout=None):
|
|
134
134
|
"""Check the thread event flags."""
|
|
135
135
|
if not self.running:
|
|
@@ -139,7 +139,7 @@ class Thread:
|
|
|
139
139
|
if not self.active:
|
|
140
140
|
raise KeyboardInterrupt("terminated by user")
|
|
141
141
|
return True
|
|
142
|
-
|
|
142
|
+
|
|
143
143
|
def pause(self, msg=None, caption=wx.MessageBoxCaptionStr):
|
|
144
144
|
"""Pause the thread.
|
|
145
145
|
Confirm whether to terminate the thread.
|
|
@@ -168,7 +168,7 @@ class Thread:
|
|
|
168
168
|
return False
|
|
169
169
|
finally:
|
|
170
170
|
self.event.set() # resume
|
|
171
|
-
|
|
171
|
+
|
|
172
172
|
def Start(self, f, *args, **kwargs):
|
|
173
173
|
"""Start the thread to run the specified function.
|
|
174
174
|
"""
|
|
@@ -205,7 +205,7 @@ class Thread:
|
|
|
205
205
|
args=args, kwargs=kwargs, daemon=True)
|
|
206
206
|
self.worker.start()
|
|
207
207
|
self.event.set()
|
|
208
|
-
|
|
208
|
+
|
|
209
209
|
def Stop(self):
|
|
210
210
|
"""Stop the thread.
|
|
211
211
|
|
|
@@ -248,31 +248,31 @@ class LayerInterface(CtrlInterface):
|
|
|
248
248
|
dockable = True
|
|
249
249
|
reloadable = True
|
|
250
250
|
unloadable = True
|
|
251
|
-
|
|
251
|
+
|
|
252
252
|
graph = property(lambda self: self.parent.graph)
|
|
253
253
|
output = property(lambda self: self.parent.output)
|
|
254
254
|
histogram = property(lambda self: self.parent.histogram)
|
|
255
255
|
selected_view = property(lambda self: self.parent.selected_view)
|
|
256
|
-
|
|
256
|
+
|
|
257
257
|
message = property(lambda self: self.parent.message)
|
|
258
|
-
|
|
258
|
+
|
|
259
259
|
## thread_type = Thread
|
|
260
260
|
thread = None
|
|
261
|
-
|
|
261
|
+
|
|
262
262
|
## layout helper function (internal use only)
|
|
263
263
|
pack = mwx.pack
|
|
264
|
-
|
|
264
|
+
|
|
265
265
|
## funcall = interactive_call (internal use only)
|
|
266
266
|
funcall = staticmethod(_F)
|
|
267
|
-
|
|
267
|
+
|
|
268
268
|
## for debug (internal use only)
|
|
269
269
|
pane = property(lambda self: self.parent.get_pane(self))
|
|
270
|
-
|
|
270
|
+
|
|
271
271
|
@property
|
|
272
272
|
def Arts(self):
|
|
273
273
|
"""List of arts <matplotlib.artist.Artist>."""
|
|
274
274
|
return self.__artists
|
|
275
|
-
|
|
275
|
+
|
|
276
276
|
@Arts.setter
|
|
277
277
|
def Arts(self, arts):
|
|
278
278
|
for art in self.__artists[:]:
|
|
@@ -280,13 +280,13 @@ class LayerInterface(CtrlInterface):
|
|
|
280
280
|
art.remove()
|
|
281
281
|
self.__artists.remove(art)
|
|
282
282
|
self.__artists = arts
|
|
283
|
-
|
|
283
|
+
|
|
284
284
|
@Arts.deleter
|
|
285
285
|
def Arts(self):
|
|
286
286
|
for art in self.__artists:
|
|
287
287
|
art.remove()
|
|
288
288
|
self.__artists = []
|
|
289
|
-
|
|
289
|
+
|
|
290
290
|
def attach_artists(self, axes, *artists):
|
|
291
291
|
"""Attach artists (e.g., patches) to the given axes."""
|
|
292
292
|
for art in artists:
|
|
@@ -296,7 +296,7 @@ class LayerInterface(CtrlInterface):
|
|
|
296
296
|
axes.add_artist(art)
|
|
297
297
|
if art not in self.__artists:
|
|
298
298
|
self.__artists.append(art)
|
|
299
|
-
|
|
299
|
+
|
|
300
300
|
def detach_artists(self, *artists):
|
|
301
301
|
"""Detach artists (e.g., patches) from their axes."""
|
|
302
302
|
for art in artists:
|
|
@@ -304,7 +304,7 @@ class LayerInterface(CtrlInterface):
|
|
|
304
304
|
art.remove()
|
|
305
305
|
art._transformSet = False
|
|
306
306
|
self.__artists.remove(art)
|
|
307
|
-
|
|
307
|
+
|
|
308
308
|
def __init__(self, parent, session=None):
|
|
309
309
|
if hasattr(self, 'handler'):
|
|
310
310
|
warn(f"Duplicate iniheritance of CtrlInterface by {self}.")
|
|
@@ -398,21 +398,21 @@ class LayerInterface(CtrlInterface):
|
|
|
398
398
|
self.load_session(session)
|
|
399
399
|
except Exception:
|
|
400
400
|
traceback.print_exc() # Failed to load the plug session.
|
|
401
|
-
|
|
401
|
+
|
|
402
402
|
def Init(self):
|
|
403
403
|
"""Initialize layout before load_session (to be overridden)."""
|
|
404
404
|
pass
|
|
405
|
-
|
|
405
|
+
|
|
406
406
|
def load_session(self, session):
|
|
407
407
|
"""Restore settings from a session file (to be overridden)."""
|
|
408
408
|
if 'params' in session:
|
|
409
409
|
self.parameters = session['params']
|
|
410
|
-
|
|
410
|
+
|
|
411
411
|
def save_session(self, session):
|
|
412
412
|
"""Save settings in a session file (to be overridden)."""
|
|
413
413
|
if self.parameters:
|
|
414
414
|
session['params'] = self.parameters
|
|
415
|
-
|
|
415
|
+
|
|
416
416
|
def OnDestroy(self, evt):
|
|
417
417
|
if evt.EventObject is self:
|
|
418
418
|
if self.thread and self.thread.active:
|
|
@@ -420,7 +420,7 @@ class LayerInterface(CtrlInterface):
|
|
|
420
420
|
self.thread.Stop()
|
|
421
421
|
del self.Arts
|
|
422
422
|
evt.Skip()
|
|
423
|
-
|
|
423
|
+
|
|
424
424
|
def OnShow(self, evt):
|
|
425
425
|
if not self:
|
|
426
426
|
return
|
|
@@ -430,11 +430,11 @@ class LayerInterface(CtrlInterface):
|
|
|
430
430
|
else:
|
|
431
431
|
self.handler('page_hidden', self)
|
|
432
432
|
evt.Skip()
|
|
433
|
-
|
|
433
|
+
|
|
434
434
|
Shown = property(
|
|
435
435
|
lambda self: self.IsShown(),
|
|
436
436
|
lambda self, v: self.Show(v))
|
|
437
|
-
|
|
437
|
+
|
|
438
438
|
def IsShown(self):
|
|
439
439
|
"""Return True if the window is physically visible on the screen.
|
|
440
440
|
|
|
@@ -443,7 +443,7 @@ class LayerInterface(CtrlInterface):
|
|
|
443
443
|
"""
|
|
444
444
|
## return self.pane.IsShown()
|
|
445
445
|
return self.IsShownOnScreen()
|
|
446
|
-
|
|
446
|
+
|
|
447
447
|
def Show(self, show=True, interactive=False):
|
|
448
448
|
"""Shows or hides the window.
|
|
449
449
|
|
|
@@ -451,14 +451,14 @@ class LayerInterface(CtrlInterface):
|
|
|
451
451
|
Note: This might be called from a thread.
|
|
452
452
|
"""
|
|
453
453
|
wx.CallAfter(self.parent.show_pane, self, show, interactive) # Use main thread.
|
|
454
|
-
|
|
454
|
+
|
|
455
455
|
Drawn = property(
|
|
456
456
|
lambda self: self.IsDrawn(),
|
|
457
457
|
lambda self, v: self.Draw(v))
|
|
458
|
-
|
|
458
|
+
|
|
459
459
|
def IsDrawn(self):
|
|
460
460
|
return any(art.get_visible() for art in self.Arts)
|
|
461
|
-
|
|
461
|
+
|
|
462
462
|
def Draw(self, show=None):
|
|
463
463
|
"""Draw artists.
|
|
464
464
|
If show is None:default, draw only when the pane is visible.
|
|
@@ -493,14 +493,14 @@ def _register__dummy_plug__(cls, module):
|
|
|
493
493
|
## warn(f"Duplicate iniheritance of LayerInterface by {cls}.")
|
|
494
494
|
module.Plugin = cls
|
|
495
495
|
return cls
|
|
496
|
-
|
|
496
|
+
|
|
497
497
|
class _Plugin(cls, LayerInterface):
|
|
498
498
|
def __init__(self, parent, session=None, **kwargs):
|
|
499
499
|
cls.__init__(self, parent, **kwargs)
|
|
500
500
|
LayerInterface.__init__(self, parent, session)
|
|
501
501
|
Show = LayerInterface.Show
|
|
502
502
|
IsShown = LayerInterface.IsShown
|
|
503
|
-
|
|
503
|
+
|
|
504
504
|
_Plugin.__module__ = module.__name__
|
|
505
505
|
_Plugin.__qualname__ = cls.__qualname__ + "~"
|
|
506
506
|
_Plugin.__name__ = cls.__name__ + "~"
|
|
@@ -534,24 +534,24 @@ class Graph(GraphPlot):
|
|
|
534
534
|
})
|
|
535
535
|
## ドロップターゲットを許可する
|
|
536
536
|
self.SetDropTarget(MyFileDropLoader(self, self.loader))
|
|
537
|
-
|
|
537
|
+
|
|
538
538
|
def refresh(self):
|
|
539
539
|
if self.frame:
|
|
540
540
|
self.frame.update_buffer()
|
|
541
541
|
self.draw()
|
|
542
|
-
|
|
542
|
+
|
|
543
543
|
def toggle_infobar(self):
|
|
544
544
|
"""Toggle infobar (frame.annotation)."""
|
|
545
545
|
if self.infobar.IsShown():
|
|
546
546
|
self.infobar.Dismiss()
|
|
547
547
|
elif self.frame:
|
|
548
548
|
self.infobar.ShowMessage(self.frame.annotation)
|
|
549
|
-
|
|
549
|
+
|
|
550
550
|
def update_infobar(self, frame):
|
|
551
551
|
"""Show infobar (frame.annotation)."""
|
|
552
552
|
if self.infobar.IsShown():
|
|
553
553
|
self.infobar.ShowMessage(frame.annotation)
|
|
554
|
-
|
|
554
|
+
|
|
555
555
|
def hide_layers(self):
|
|
556
556
|
for plug in self.parent.get_all_plugs():
|
|
557
557
|
for art in plug.Arts:
|
|
@@ -574,7 +574,7 @@ class MyFileDropLoader(wx.FileDropTarget):
|
|
|
574
574
|
|
|
575
575
|
self.view = target
|
|
576
576
|
self.loader = loader
|
|
577
|
-
|
|
577
|
+
|
|
578
578
|
def OnDropFiles(self, x, y, filenames):
|
|
579
579
|
pos = self.view.ScreenPosition + (x, y)
|
|
580
580
|
paths = []
|
|
@@ -607,24 +607,24 @@ class Frame(mwx.Frame):
|
|
|
607
607
|
graph = property(lambda self: self.__graph)
|
|
608
608
|
output = property(lambda self: self.__output)
|
|
609
609
|
histogram = property(lambda self: self.__histgrm)
|
|
610
|
-
|
|
610
|
+
|
|
611
611
|
selected_view = property(lambda self: self.__view)
|
|
612
|
-
|
|
612
|
+
|
|
613
613
|
def select_view(self, view):
|
|
614
614
|
self.__view = view
|
|
615
615
|
self.set_title(view.frame)
|
|
616
|
-
|
|
616
|
+
|
|
617
617
|
@property
|
|
618
618
|
def graphic_windows(self):
|
|
619
619
|
"""Graphic windows list.
|
|
620
620
|
[0] graph [1] output [2:] others(user-defined)
|
|
621
621
|
"""
|
|
622
622
|
return self.__graphic_windows
|
|
623
|
-
|
|
623
|
+
|
|
624
624
|
@property
|
|
625
625
|
def graphic_windows_on_screen(self):
|
|
626
626
|
return [w for w in self.__graphic_windows if w.IsShownOnScreen()]
|
|
627
|
-
|
|
627
|
+
|
|
628
628
|
def __init__(self, *args, **kwargs):
|
|
629
629
|
mwx.Frame.__init__(self, *args, **kwargs)
|
|
630
630
|
|
|
@@ -823,9 +823,9 @@ class Frame(mwx.Frame):
|
|
|
823
823
|
|
|
824
824
|
## Accepts DnD
|
|
825
825
|
self.SetDropTarget(MyFileDropLoader(self.graph, self))
|
|
826
|
-
|
|
826
|
+
|
|
827
827
|
SYNC_SWITCH = True
|
|
828
|
-
|
|
828
|
+
|
|
829
829
|
def sync(self, a, b):
|
|
830
830
|
"""Synchronize b to a."""
|
|
831
831
|
if (self.SYNC_SWITCH
|
|
@@ -836,17 +836,17 @@ class Frame(mwx.Frame):
|
|
|
836
836
|
b.ylim = a.ylim
|
|
837
837
|
b.OnDraw(None)
|
|
838
838
|
b.canvas.draw_idle()
|
|
839
|
-
|
|
839
|
+
|
|
840
840
|
def set_title(self, frame):
|
|
841
841
|
ssn = os.path.basename(self.session_file or '--')
|
|
842
842
|
ssn, _ = os.path.splitext(ssn)
|
|
843
843
|
name = (frame.pathname or frame.name) if frame else ''
|
|
844
844
|
self.SetTitle("{}@{} - [{}] {}".format(self.Name, platform.node(), ssn, name))
|
|
845
|
-
|
|
845
|
+
|
|
846
846
|
def OnActivate(self, evt): #<wx._core.ActivateEvent>
|
|
847
847
|
if self and evt.Active:
|
|
848
848
|
self.set_title(self.selected_view.frame)
|
|
849
|
-
|
|
849
|
+
|
|
850
850
|
def OnClose(self, evt): #<wx._core.CloseEvent>
|
|
851
851
|
ssn = os.path.basename(self.session_file or '--')
|
|
852
852
|
with wx.MessageDialog(None,
|
|
@@ -881,15 +881,15 @@ class Frame(mwx.Frame):
|
|
|
881
881
|
evt.Veto()
|
|
882
882
|
return
|
|
883
883
|
evt.Skip()
|
|
884
|
-
|
|
884
|
+
|
|
885
885
|
def Destroy(self):
|
|
886
886
|
self._mgr.UnInit()
|
|
887
887
|
return mwx.Frame.Destroy(self)
|
|
888
|
-
|
|
888
|
+
|
|
889
889
|
## --------------------------------
|
|
890
890
|
## pane window interface
|
|
891
891
|
## --------------------------------
|
|
892
|
-
|
|
892
|
+
|
|
893
893
|
def get_pane(self, name):
|
|
894
894
|
"""Get named pane or notebook pane.
|
|
895
895
|
|
|
@@ -901,7 +901,7 @@ class Frame(mwx.Frame):
|
|
|
901
901
|
name = plug.category or plug
|
|
902
902
|
if name:
|
|
903
903
|
return self._mgr.GetPane(name)
|
|
904
|
-
|
|
904
|
+
|
|
905
905
|
def show_pane(self, name, show=True, interactive=False):
|
|
906
906
|
"""Show named pane or notebook pane.
|
|
907
907
|
|
|
@@ -969,7 +969,7 @@ class Frame(mwx.Frame):
|
|
|
969
969
|
pane.Show(show)
|
|
970
970
|
self._mgr.Update()
|
|
971
971
|
return (show != shown)
|
|
972
|
-
|
|
972
|
+
|
|
973
973
|
def update_pane(self, name, **props):
|
|
974
974
|
"""Update the layout of the pane (internal use only).
|
|
975
975
|
|
|
@@ -996,7 +996,7 @@ class Frame(mwx.Frame):
|
|
|
996
996
|
pane.Dock()
|
|
997
997
|
else:
|
|
998
998
|
pane.Float()
|
|
999
|
-
|
|
999
|
+
|
|
1000
1000
|
def OnPaneClose(self, evt): #<wx.aui.AuiManagerEvent>
|
|
1001
1001
|
pane = evt.GetPane()
|
|
1002
1002
|
win = pane.window
|
|
@@ -1006,19 +1006,19 @@ class Frame(mwx.Frame):
|
|
|
1006
1006
|
else:
|
|
1007
1007
|
win.handler('page_closed', win)
|
|
1008
1008
|
evt.Skip(False) # Don't skip to avoid being called twice.
|
|
1009
|
-
|
|
1009
|
+
|
|
1010
1010
|
## --------------------------------
|
|
1011
1011
|
## Plugin <Layer> interface
|
|
1012
1012
|
## --------------------------------
|
|
1013
1013
|
plugins = property(lambda self: self.__plugins)
|
|
1014
|
-
|
|
1014
|
+
|
|
1015
1015
|
def register(self, cls=None, **kwargs):
|
|
1016
1016
|
"""Decorator of plugin class register."""
|
|
1017
1017
|
if cls is None:
|
|
1018
1018
|
return lambda f: self.register(f, **kwargs)
|
|
1019
1019
|
self.load_plug(cls, force=1, show=1, **kwargs)
|
|
1020
1020
|
return cls
|
|
1021
|
-
|
|
1021
|
+
|
|
1022
1022
|
def require(self, name):
|
|
1023
1023
|
"""Get named plug window.
|
|
1024
1024
|
If not found, try to load it once.
|
|
@@ -1032,7 +1032,7 @@ class Frame(mwx.Frame):
|
|
|
1032
1032
|
if self.load_plug(name) is not False:
|
|
1033
1033
|
return self.get_plug(name)
|
|
1034
1034
|
return plug
|
|
1035
|
-
|
|
1035
|
+
|
|
1036
1036
|
def get_plug(self, name):
|
|
1037
1037
|
"""Get named plug window."""
|
|
1038
1038
|
if isinstance(name, str):
|
|
@@ -1043,11 +1043,11 @@ class Frame(mwx.Frame):
|
|
|
1043
1043
|
elif isinstance(name, LayerInterface):
|
|
1044
1044
|
## return name
|
|
1045
1045
|
return next((x for x in self.get_all_plugs() if x is name), None)
|
|
1046
|
-
|
|
1046
|
+
|
|
1047
1047
|
def get_all_plugs(self):
|
|
1048
1048
|
for name, module in self.plugins.items():
|
|
1049
1049
|
yield module.__plug__
|
|
1050
|
-
|
|
1050
|
+
|
|
1051
1051
|
def load_plug(self, root, session=None, force=False, show=False,
|
|
1052
1052
|
dock=0, floating_pos=None, floating_size=None,
|
|
1053
1053
|
**kwargs):
|
|
@@ -1081,8 +1081,6 @@ class Frame(mwx.Frame):
|
|
|
1081
1081
|
name = root.__module__
|
|
1082
1082
|
else:
|
|
1083
1083
|
name = root
|
|
1084
|
-
if name == "__main__":
|
|
1085
|
-
name = inspect.getfile(__import__("__main__"))
|
|
1086
1084
|
|
|
1087
1085
|
dirname_, name = os.path.split(name) # if the name is full-path:str
|
|
1088
1086
|
if name.endswith(".py"):
|
|
@@ -1117,11 +1115,11 @@ class Frame(mwx.Frame):
|
|
|
1117
1115
|
|
|
1118
1116
|
## Load or reload the module, and check whether it contains a class named `Plugin`.
|
|
1119
1117
|
try:
|
|
1120
|
-
|
|
1118
|
+
## Check if the module is reloadable.
|
|
1119
|
+
loadable = not name.startswith(("__main__", "builtins")) # no __file__
|
|
1121
1120
|
if not loadable:
|
|
1122
1121
|
module = types.ModuleType(name) # dummy module (cannot reload)
|
|
1123
1122
|
module.__file__ = "<scratch>"
|
|
1124
|
-
## sys.modules[name] = module
|
|
1125
1123
|
elif name in sys.modules:
|
|
1126
1124
|
module = reload(sys.modules[name])
|
|
1127
1125
|
else:
|
|
@@ -1252,8 +1250,10 @@ class Frame(mwx.Frame):
|
|
|
1252
1250
|
self.menubar[menu] = []
|
|
1253
1251
|
self.menubar[menu] += [plug.__Menu_item]
|
|
1254
1252
|
self.menubar.update(menu)
|
|
1253
|
+
|
|
1254
|
+
self.handler('plug_loaded', plug)
|
|
1255
1255
|
return None
|
|
1256
|
-
|
|
1256
|
+
|
|
1257
1257
|
def unload_plug(self, name):
|
|
1258
1258
|
"""Unload plugin and detach the pane from UI manager."""
|
|
1259
1259
|
plug = self.get_plug(name)
|
|
@@ -1279,6 +1279,7 @@ class Frame(mwx.Frame):
|
|
|
1279
1279
|
self._mgr.DetachPane(plug)
|
|
1280
1280
|
self._mgr.Update()
|
|
1281
1281
|
|
|
1282
|
+
self.handler('plug_unloaded', plug)
|
|
1282
1283
|
plug.handler('page_closed', plug) # (even if not shown)
|
|
1283
1284
|
plug.Destroy()
|
|
1284
1285
|
|
|
@@ -1286,7 +1287,7 @@ class Frame(mwx.Frame):
|
|
|
1286
1287
|
self._mgr.DetachPane(nb) # detach notebook pane
|
|
1287
1288
|
self._mgr.Update()
|
|
1288
1289
|
nb.Destroy()
|
|
1289
|
-
|
|
1290
|
+
|
|
1290
1291
|
def reload_plug(self, name):
|
|
1291
1292
|
"""Reload plugin."""
|
|
1292
1293
|
plug = self.get_plug(name)
|
|
@@ -1307,7 +1308,7 @@ class Frame(mwx.Frame):
|
|
|
1307
1308
|
for shell in self.shellframe.get_all_shells():
|
|
1308
1309
|
if shell.target is plug:
|
|
1309
1310
|
shell.handler('shell_activated', shell)
|
|
1310
|
-
|
|
1311
|
+
|
|
1311
1312
|
def inspect_plug(self, name):
|
|
1312
1313
|
"""Dive into the process to inspect plugs in the shell."""
|
|
1313
1314
|
plug = self.get_plug(name)
|
|
@@ -1330,7 +1331,7 @@ class Frame(mwx.Frame):
|
|
|
1330
1331
|
self.shellframe.Show()
|
|
1331
1332
|
if wx.GetKeyState(wx.WXK_SHIFT): # open the source code.
|
|
1332
1333
|
self.shellframe.load(plug)
|
|
1333
|
-
|
|
1334
|
+
|
|
1334
1335
|
def OnLoadPlugins(self, evt):
|
|
1335
1336
|
with wx.FileDialog(self, "Load a plugin file",
|
|
1336
1337
|
wildcard="Python file (*.py)|*.py",
|
|
@@ -1339,7 +1340,7 @@ class Frame(mwx.Frame):
|
|
|
1339
1340
|
if dlg.ShowModal() == wx.ID_OK:
|
|
1340
1341
|
for path in dlg.Paths:
|
|
1341
1342
|
self.load_plug(path)
|
|
1342
|
-
|
|
1343
|
+
|
|
1343
1344
|
def Quit(self, evt=None):
|
|
1344
1345
|
"""Stop all Layer threads."""
|
|
1345
1346
|
for plug in self.get_all_plugs():
|
|
@@ -1347,12 +1348,12 @@ class Frame(mwx.Frame):
|
|
|
1347
1348
|
if thread and thread.active:
|
|
1348
1349
|
## thread.active = 0
|
|
1349
1350
|
thread.Stop()
|
|
1350
|
-
|
|
1351
|
+
|
|
1351
1352
|
## --------------------------------
|
|
1352
1353
|
## load/save index file
|
|
1353
1354
|
## --------------------------------
|
|
1354
1355
|
ATTRIBUTESFILE = "results.index"
|
|
1355
|
-
|
|
1356
|
+
|
|
1356
1357
|
def load_index(self, filename=None, view=None):
|
|
1357
1358
|
"""Load frames :ref to the Index file.
|
|
1358
1359
|
|
|
@@ -1388,7 +1389,7 @@ class Frame(mwx.Frame):
|
|
|
1388
1389
|
"{} files are missing.".format(n, len(res)-n, len(mis)))
|
|
1389
1390
|
print(self.message.read())
|
|
1390
1391
|
return frames
|
|
1391
|
-
|
|
1392
|
+
|
|
1392
1393
|
def save_index(self, filename=None, frames=None):
|
|
1393
1394
|
"""Save frames :ref to the Index file.
|
|
1394
1395
|
"""
|
|
@@ -1438,11 +1439,11 @@ class Frame(mwx.Frame):
|
|
|
1438
1439
|
"{} files are missing.".format(n, len(res)-n, len(mis)))
|
|
1439
1440
|
print(self.message.read())
|
|
1440
1441
|
return frames
|
|
1441
|
-
|
|
1442
|
+
|
|
1442
1443
|
## --------------------------------
|
|
1443
1444
|
## load/save frames and attributes
|
|
1444
1445
|
## --------------------------------
|
|
1445
|
-
|
|
1446
|
+
|
|
1446
1447
|
@classmethod
|
|
1447
1448
|
def read_attributes(self, filename):
|
|
1448
1449
|
"""Read attributes file."""
|
|
@@ -1472,7 +1473,7 @@ class Frame(mwx.Frame):
|
|
|
1472
1473
|
print("- Failed to read attributes.", e)
|
|
1473
1474
|
wx.MessageBox(str(e), style=wx.ICON_ERROR)
|
|
1474
1475
|
return res, mis
|
|
1475
|
-
|
|
1476
|
+
|
|
1476
1477
|
@classmethod
|
|
1477
1478
|
def write_attributes(self, filename, frames):
|
|
1478
1479
|
"""Write attributes file."""
|
|
@@ -1492,7 +1493,7 @@ class Frame(mwx.Frame):
|
|
|
1492
1493
|
print("- Failed to write attributes.", e)
|
|
1493
1494
|
wx.MessageBox(str(e), style=wx.ICON_ERROR)
|
|
1494
1495
|
return new, mis
|
|
1495
|
-
|
|
1496
|
+
|
|
1496
1497
|
def load_frame(self, paths=None, view=None):
|
|
1497
1498
|
"""Load frames from files to the view window.
|
|
1498
1499
|
|
|
@@ -1511,7 +1512,7 @@ class Frame(mwx.Frame):
|
|
|
1511
1512
|
results = savedirs[savedir]
|
|
1512
1513
|
frame.update_attr(results.get(frame.name))
|
|
1513
1514
|
return frames
|
|
1514
|
-
|
|
1515
|
+
|
|
1515
1516
|
def save_frame(self, path=None, frame=None):
|
|
1516
1517
|
"""Save frame to a file.
|
|
1517
1518
|
|
|
@@ -1523,7 +1524,7 @@ class Frame(mwx.Frame):
|
|
|
1523
1524
|
fn = os.path.join(savedir, self.ATTRIBUTESFILE)
|
|
1524
1525
|
res, mis = self.write_attributes(fn, [frame])
|
|
1525
1526
|
return frame
|
|
1526
|
-
|
|
1527
|
+
|
|
1527
1528
|
## --------------------------------
|
|
1528
1529
|
## load/save images
|
|
1529
1530
|
## --------------------------------
|
|
@@ -1531,7 +1532,7 @@ class Frame(mwx.Frame):
|
|
|
1531
1532
|
"TIF file (*.tif)|*.tif",
|
|
1532
1533
|
"ALL files (*.*)|*.*",
|
|
1533
1534
|
]
|
|
1534
|
-
|
|
1535
|
+
|
|
1535
1536
|
@staticmethod
|
|
1536
1537
|
def read_buffer(path):
|
|
1537
1538
|
"""Read buffer from a file (to be overridden)."""
|
|
@@ -1542,7 +1543,7 @@ class Frame(mwx.Frame):
|
|
|
1542
1543
|
## return np.asarray(buf), info # ref
|
|
1543
1544
|
## return np.array(buf), info # copy
|
|
1544
1545
|
return buf, info
|
|
1545
|
-
|
|
1546
|
+
|
|
1546
1547
|
@staticmethod
|
|
1547
1548
|
def write_buffer(path, buf):
|
|
1548
1549
|
"""Write buffer to a file (to be overridden)."""
|
|
@@ -1555,7 +1556,7 @@ class Frame(mwx.Frame):
|
|
|
1555
1556
|
if os.path.exists(path):
|
|
1556
1557
|
os.remove(path)
|
|
1557
1558
|
raise
|
|
1558
|
-
|
|
1559
|
+
|
|
1559
1560
|
@ignore(ResourceWarning)
|
|
1560
1561
|
def load_buffer(self, paths=None, view=None):
|
|
1561
1562
|
"""Load buffers from paths to the view window.
|
|
@@ -1615,7 +1616,7 @@ class Frame(mwx.Frame):
|
|
|
1615
1616
|
if frame:
|
|
1616
1617
|
view.select(frame)
|
|
1617
1618
|
return frames
|
|
1618
|
-
|
|
1619
|
+
|
|
1619
1620
|
def save_buffer(self, path=None, frame=None):
|
|
1620
1621
|
"""Save buffer of the frame to a file.
|
|
1621
1622
|
"""
|
|
@@ -1654,7 +1655,7 @@ class Frame(mwx.Frame):
|
|
|
1654
1655
|
self.message("\b failed.")
|
|
1655
1656
|
wx.MessageBox(str(e), style=wx.ICON_ERROR)
|
|
1656
1657
|
return None
|
|
1657
|
-
|
|
1658
|
+
|
|
1658
1659
|
def save_buffers_as_tiffs(self, path=None, frames=None):
|
|
1659
1660
|
"""Save buffers to a file as a multi-page tiff."""
|
|
1660
1661
|
if not frames:
|
|
@@ -1687,12 +1688,12 @@ class Frame(mwx.Frame):
|
|
|
1687
1688
|
self.message("\b failed.")
|
|
1688
1689
|
wx.MessageBox(str(e), style=wx.ICON_ERROR)
|
|
1689
1690
|
return False
|
|
1690
|
-
|
|
1691
|
+
|
|
1691
1692
|
## --------------------------------
|
|
1692
1693
|
## load/save session
|
|
1693
1694
|
## --------------------------------
|
|
1694
1695
|
session_file = None
|
|
1695
|
-
|
|
1696
|
+
|
|
1696
1697
|
def load_session(self, filename=None, flush=True):
|
|
1697
1698
|
"""Load session from file."""
|
|
1698
1699
|
if not filename:
|
|
@@ -1738,7 +1739,7 @@ class Frame(mwx.Frame):
|
|
|
1738
1739
|
win.handler('page_shown', win)
|
|
1739
1740
|
|
|
1740
1741
|
self.message("\b done.")
|
|
1741
|
-
|
|
1742
|
+
|
|
1742
1743
|
def save_session_as(self):
|
|
1743
1744
|
"""Save session as a new file."""
|
|
1744
1745
|
with wx.FileDialog(self, "Save session as",
|
|
@@ -1750,7 +1751,7 @@ class Frame(mwx.Frame):
|
|
|
1750
1751
|
if dlg.ShowModal() == wx.ID_OK:
|
|
1751
1752
|
self.session_file = dlg.Path
|
|
1752
1753
|
self.save_session()
|
|
1753
|
-
|
|
1754
|
+
|
|
1754
1755
|
def save_session(self):
|
|
1755
1756
|
"""Save session to file."""
|
|
1756
1757
|
if not self.session_file:
|