Skip to content

Commit 817795e

Browse files
author
lindakladivova
committed
fully working version after refactoring
1 parent 3ec2541 commit 817795e

File tree

19 files changed

+1173
-510
lines changed

19 files changed

+1173
-510
lines changed

gui/icons/grass/jupyter.png

786 Bytes
Loading

gui/icons/grass/jupyter.svg

Lines changed: 85 additions & 0 deletions
Loading
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
"""
2+
@package jupyter_notebook.notebook
3+
4+
@brief Manages the jupyter notebook widget.
5+
6+
Classes:
7+
- page::JupyterAuiNotebook
8+
9+
(C) 2025 by the GRASS Development Team
10+
11+
This program is free software under the GNU General Public License
12+
(>=v2). Read the file COPYING that comes with GRASS for details.
13+
14+
@author Linda Karlovska <linda.karlovska seznam.cz>
15+
"""
16+
17+
import wx
18+
from wx.lib.agw import aui
19+
20+
try:
21+
import wx.html2 as html # wx.html2 is available in wxPython 4.0 and later
22+
except ImportError as e:
23+
raise RuntimeError(_("wx.html2 is required for Jupyter integration.")) from e
24+
25+
from gui_core.wrap import SimpleTabArt
26+
27+
28+
class JupyterAuiNotebook(aui.AuiNotebook):
29+
def __init__(
30+
self,
31+
parent,
32+
agwStyle=aui.AUI_NB_DEFAULT_STYLE
33+
| aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
34+
| aui.AUI_NB_TAB_EXTERNAL_MOVE
35+
| aui.AUI_NB_BOTTOM
36+
| wx.NO_BORDER,
37+
):
38+
"""
39+
Wrapper for the notebook widget that manages notebook pages.
40+
"""
41+
self.parent = parent
42+
self.webview = None
43+
44+
super().__init__(parent=self.parent, id=wx.ID_ANY, agwStyle=agwStyle)
45+
46+
self.SetArtProvider(SimpleTabArt())
47+
48+
self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnPageClose)
49+
50+
def _inject_javascript(self, event):
51+
"""
52+
Inject JavaScript into the Jupyter notebook page to hide UI elements.
53+
54+
Specifically hides:
55+
- The File menu
56+
- The top header bar
57+
58+
This is called once the WebView has fully loaded the Jupyter page.
59+
"""
60+
webview = event.GetEventObject()
61+
js = """
62+
var interval = setInterval(function() {
63+
var fileMenu = document.querySelector('li#file_menu, a#filelink, a[aria-controls="file_menu"]');
64+
if (fileMenu) {
65+
if (fileMenu.tagName === "LI") {
66+
fileMenu.style.display = 'none';
67+
} else if (fileMenu.parentElement && fileMenu.parentElement.tagName === "LI") {
68+
fileMenu.parentElement.style.display = 'none';
69+
}
70+
}
71+
var header = document.getElementById('header-container');
72+
if (header) {
73+
header.style.display = 'none';
74+
}
75+
if (fileMenu && header) {
76+
clearInterval(interval);
77+
}
78+
}, 500);
79+
"""
80+
webview.RunScript(js)
81+
82+
def AddPage(self, url, title):
83+
"""
84+
Add a new aui notebook page with a Jupyter WebView.
85+
:param url: URL of the Jupyter file (str).
86+
:param title: Tab title (str).
87+
"""
88+
browser = html.WebView.New(self)
89+
wx.CallAfter(browser.LoadURL, url)
90+
wx.CallAfter(browser.Bind, html.EVT_WEBVIEW_LOADED, self._inject_javascript)
91+
super().AddPage(browser, title)
92+
93+
def OnPageClose(self, event):
94+
"""Close the aui notebook page with confirmation dialog."""
95+
index = event.GetSelection()
96+
title = self.GetPageText(index)
97+
98+
dlg = wx.MessageDialog(
99+
self,
100+
message=_("Really close page '{}'?").format(title),
101+
caption=_("Close page"),
102+
style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION,
103+
)
104+
105+
if dlg.ShowModal() != wx.ID_YES:
106+
event.Veto()
107+
108+
dlg.Destroy()

0 commit comments

Comments
 (0)