]> git.neil.brown.name Git - edlib.git/commitdiff
doc-to-text: don't wait for conversion to complete.
authorNeilBrown <neil@brown.name>
Fri, 26 May 2023 05:36:55 +0000 (15:36 +1000)
committerNeilBrown <neil@brown.name>
Fri, 26 May 2023 22:18:43 +0000 (08:18 +1000)
If permitted by called, don't start the conversion to text until a
notification arrives.

This requires getting multipart to forward doc:replaced notifications.

Signed-off-by: NeilBrown <neil@brown.name>
doc-multipart.c
python/lib-doc-to-text.py

index b801a0b40e670326a2ac344cd75a4e894447e014..50ce4a17d46f00fb5553eb290ee845aa15ba975d 100644 (file)
@@ -662,6 +662,15 @@ DEF_CMD(mp_notify_viewers)
        return 1;
 }
 
+DEF_CMD(mp_doc_replaced)
+{
+       /* Something changed in a component, report that the
+        * whole doc changed - simplest for now.
+        */
+       pane_notify("doc:replaced", ci->home);
+       return 1;
+}
+
 static void mp_resize(struct mp_info *mpi safe, int size)
 {
        if (mpi->parts_size >= size)
@@ -695,6 +704,7 @@ DEF_CMD(mp_add)
 
        pane_add_notify(ci->home, ci->focus, "Notify:Close");
        home_call(ci->focus, "doc:request:doc:notify-viewers", ci->home);
+       home_call(ci->focus, "doc:request:doc:replaced", ci->home);
 
        return 1;
 }
@@ -827,6 +837,7 @@ static void mp_init_map(void)
        key_add(mp_map, "Free", &mp_free);
        key_add(mp_map, "Notify:Close", &mp_notify_close);
        key_add(mp_map, "doc:notify-viewers", &mp_notify_viewers);
+       key_add(mp_map, "doc:replaced", &mp_doc_replaced);
        key_add(mp_map, "multipart-add", &mp_add);
        key_add(mp_map, "debug:validate-marks", &mp_val_marks);
        key_add(mp_map, "doc:multipart:get-part", &mp_get_part);
index 0746175fd351408e650fda66edca0459ec30061c..ef93cc1a4989d2a57abb123d23612189efd18166 100644 (file)
@@ -10,7 +10,84 @@ import subprocess
 import tempfile
 import os
 
-def doc_to_text(key, home, focus, str1, comm2, **a):
+class doc_pane(edlib.Pane):
+    def __init__(self, focus, path, newpath, delayed):
+        edlib.Pane.__init__(self, focus)
+        self.doc = focus
+        self.path = path
+        self.add_notify(focus, "Close")
+        self.newpath = newpath
+        focus.call("doc:replace", 1, "(Converting content to text...)\n")
+        if delayed:
+            self.call("doc:request:convert-now")
+        else:
+            self.handle_visible("key", focus)
+
+    def handle_visible(self, key, focus, **a):
+        "handle:convert-now"
+        pipe = subprocess.Popen(["/usr/bin/lowriter", "--convert-to", "txt:Text",
+                                 self.path], close_fds=True,
+                         cwd = os.path.dirname(self.path),
+                         stdout=subprocess.PIPE, stderr = subprocess.PIPE,
+                         stdin =subprocess.DEVNULL)
+        fd = pipe.stdout.fileno()
+        self.pipe = pipe
+        fcntl.fcntl(fd, fcntl.F_SETFL,
+                    fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK)
+        self.call("event:read", pipe.stdout.fileno(), self.read)
+
+    def handle_close(self, key, **a):
+        "handle:Close"
+        try:
+            os.unlink(self.path)
+        except FileNotFoundError:
+            pass
+        try:
+            os.unlink(self.newpath)
+        except FileNotFoundError:
+            pass
+        return 1
+
+    def handle_doc_close(self, key, focus, **a):
+        "handle:Notify:Close"
+        if focus == self.doc:
+            self.doc = None
+            if self.pipe:
+                self.pipe.kill()
+        return 1
+
+    def read(self, key, **a):
+        if not self.pipe:
+            return edlib.Efalse
+        try:
+            r = os.read(self.pipe.stdout.fileno(), 65536)
+        except IOError:
+            return 1
+        if r:
+            # Not interesting in any output, just in EOF
+            return 1
+
+        out, err = self.pipe.communicate()
+        self.pipe = None
+        if err:
+            edlib.LOG("doc-to-text:", err.decode("utf-8","ignore"))
+        try:
+            with open(self.newpath, 'rb') as fp:
+                out = fp.read()
+        except:
+            out = (b"DOC coversions failed:\n" + err)
+
+        if self.doc:
+            m = edlib.Mark(self.doc)
+            m2 = m.dup()
+            m.step(1)
+            self.doc.call("doc:set-ref", m2)
+            self.doc.call("doc:replace", 1, out.decode("utf-8", 'ignore'),
+                          m, m2)
+        self.close()
+        return edlib.Efalse
+
+def doc_to_text(key, home, focus, num, str1, comm2, **a):
 
     if not str1 or '.' not in str1:
         # we need a file name to get an extension
@@ -24,26 +101,10 @@ def doc_to_text(key, home, focus, str1, comm2, **a):
     os.close(fd)
     newpath = path[:path.rindex('.')] + ".txt"
 
-    p = subprocess.Popen(["/usr/bin/lowriter", "--convert-to", "txt:Text",
-                          path], close_fds=True,
-                         cwd = os.path.dirname(path),
-                         stdout=subprocess.PIPE, stderr = subprocess.PIPE,
-                         stdin =subprocess.DEVNULL)
-    out,err = p.communicate()
-    if err:
-        edlib.LOG("doctotext:", err.decode("utf-8", 'ignore'))
-
-    try:
-        with open(newpath, 'rb') as fp:
-            out = fp.read()
-            os.unlink(newpath)
-    except:
-        out = (b"DOC conversion failed:\n" + err)
-    os.unlink(path)
-
-    doc = focus.call("doc:from-text", "office-document",
-                         out.decode("utf-8", 'ignore'),
-                         ret='pane')
+    doc = focus.call("doc:from-text", "office-document", "", ret='pane')
+
+    doc_pane(doc, path, newpath, num)
+
     comm2("cb", doc)
     return 1