How to save edited webview result?

179 Views Asked by At

Situation description: Python 3.7, GTK 3.0, PyGObjects 3.34.0 Webkit2 4.0

I have a dialog window, with GtkNotebook containing 2 tabs. 1. tab contains editable Webkit webview, the 2. tab contains textview. One of the arguments provided in class consrtructor is valid HTML snippet as string variable

What I would like to get as a result, is that any changes made in any window, are automatically reflected in other.

Current problem: Using solution provided here, any previous changes that were made in webview are discarded upon switching the notepad tabs. Debugging shows that html obtained with aforementioned call, does not contain changes.

Any ideas what might be missing in the logic or handling itself?

For reference, the code for the dialog is as follows:

# -*- coding: utf-8 -*-
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('WebKit2', '4.0')
from gi.repository import Gtk, WebKit2



class DescriptionDialog:
    def __init__(self, *args):
# GTK Builder
        self._builder = args[0]
        self._builder.add_from_file("UI/GUI/description.glade")
        self.dialog = self._builder.get_object("descriptionDialog")
        self._textView = self._builder.get_object("textview1")
        self.webViewContainer = self._builder.get_object("WebViewContainer")
        self.browserHolder = WebKit2.WebView()
        self.browserHolder.set_editable(True)
        self.webViewContainer.add(self.browserHolder)
        self.browserHolder.show()
# valid html snippet, held as string
        self.__buffer_orig__ = args[2]
        self.buffer = args[2]
        self.browserHolder.load_html(self.buffer)
        self._builder.connect_signals(
            {
                "onDialogClose": self.onDialogClose,
                "pageChangeNotebook": self.onPageChange
            })
        self.dialog.set_transient_for(self._builder.get_object("MainWindow"))
        self.textBuffer = self._builder.get_object("textbuffer1")
        self.textBuffer.set_text(self.buffer)
        self.dialog.show()

    def onDialogClose(self, handler):
        self.dialog.hide()

    def onPageChange(self, notebook=None, scrolledWindow=None, pageNumber=0):
        if pageNumber == 0:
            self.buffer = self.textBuffer.get_text(self.textBuffer.get_start_iter(), self.textBuffer.get_end_iter(), True)
            self.browserHolder.load_html(self.buffer)
        if pageNumber == 1:
            self.browserHolder.get_main_resource().get_data(None, self.getDataFromResource, None)

    def getDataFromResource(self, resource, result, userData=None):
# Changed html is not returned here
        self.buffer = str(resource.get_data_finish(result).decode("utf-8"))
        self.textBuffer.set_text(self.buffer)
1

There are 1 best solutions below

0
On

For other internet users finding this thread. Currently, at the given versions, this is the working result that I have come up with. Main idea with this implementation is following - use the WebView enabled Javascript engine to obtain the contents of a <body> tag. Then, parse the Javascript result to use this value later on.

def onPageChange(self, notebook=None, scrolledWindow=None, pageNumber=0):
    if pageNumber == 0:
        self.buffer = self.textBuffer.get_text(self.textBuffer.get_start_iter(), self.textBuffer.get_end_iter(), True)
        self.browserHolder.load_html(self.buffer)
    if pageNumber == 1:
        # use JavaScript to get the html contained in rendered body tag
        script = "document.body.innerHTML;"
        # Execute JavasScript via WebKit2.WebView bindings.
        # Result can be obtained asynchronously, via callback method
        self.browserHolder.run_javascript(script, None, self.getJSStatus, None)

def getJSStatus(self, resource, result, userData=None):
    # Sample adapted and simplified from here:
    # https://lazka.github.io/pgi-docs/#WebKit2-4.0/classes/WebView.html#WebKit2.WebView.run_javascript_finish
    # Get the JavaScript result
    data = self.browserHolder.run_javascript_finish(result)
    # Get value from result, and convert it to string
    self.buffer = data.get_js_value().to_string()
    self.textBuffer.set_text(self.buffer)