Prechádzať zdrojové kódy

Added Mask generic activity (unfinished)

Billy Barrow 7 rokov pred
rodič
commit
869408d1c7

+ 4 - 0
.vscode/settings.json

@@ -0,0 +1,4 @@
+{
+    "python.pythonPath": "/usr/bin/python3",
+    "python.linting.pylintEnabled": false
+}

+ 30 - 0
Activity/Mask/Mask.py

@@ -0,0 +1,30 @@
+import PF2.VectorMask
+
+import cv2
+
+import numpy
+
+
+class Mask:
+    def __init__(self, image, width, height):
+        self.image = image
+        self.mask = PF2.VectorMask.VectorMask()
+        self.mask.set_dimentions(width, height)
+
+    def get_mask_preview(self, image):
+        mask =  self.mask.get_mask_map()
+
+        if(type(mask) == numpy.ndarray):
+            w, h = image.shape[:2]
+            print(w, h)
+
+            # Bits per pixel
+            bpp = float(str(image.dtype).replace("uint", "").replace("float", ""))
+            # Pixel value range
+            np = float(2 ** bpp - 1)
+
+            mask = cv2.resize(mask, (h, w), interpolation=cv2.INTER_AREA)
+            inverted_map = (mask * -1) + 1
+            image[0:, 0:, 2] = (np * mask) + (image[0:, 0:, 2] * inverted_map)
+
+        return image

+ 247 - 0
Activity/Mask/__init__.py

@@ -0,0 +1,247 @@
+import getpass
+import glob
+import os
+
+import subprocess
+
+import shutil
+import threading
+
+import cv2
+
+import Activity
+from gi.repository import GLib, Gtk, GdkPixbuf, Pango
+
+import Export
+
+import Activity.Mask.Mask as Mask
+
+import numpy
+
+import Activity.Mask.Inpaint as Inpaint
+
+
+class Inpainter(Activity.Activity):
+
+    def on_init(self):
+
+        UI_FILE = "ui/Mask_Activity.glade"
+        self.builder.add_from_file(UI_FILE)
+        print(UI_FILE)
+
+        self.widget = self.builder.get_object("Mask_main")
+        self.stack.add_titled(self.widget, self.id, self.name)
+
+        self.header_widget = self.builder.get_object("Mask_header")
+        self.header_stack.add_titled(self.header_widget, self.id, self.name)
+
+        # Get all UI Components
+        self.ui = {}
+        components = [
+            "open_window",
+            "open_chooser",
+            "preview_button",
+            "open_header",
+            "open_open_button",
+            "open_cancel_button",
+            "open",
+            "popovermenu",
+            "toolbar",
+            "scroll_window",
+            "preview",
+            "mask_draw_toggle",
+            "mask_erase_toggle",
+            "preview_eventbox",
+            "scroll_window",
+            "mask_brush_size",
+            "preview_button"
+        ]
+
+        self.paths = []
+        self.exporting = False
+
+        for component in components:
+            self.ui[component] = self.builder.get_object("Mask_%s" % component))
+
+        self.menu_popover = self.ui["popovermenu"]
+
+        self.image_readonly = None
+        self.image = None
+        self.image_pb = None
+        self.mousedown = False
+
+        self.mask = None
+        self.current_path = None
+        self.actual_width = 0
+
+        self.ui["open_window"].set_transient_for(self.root)
+        self.ui["open_window"].set_titlebar(self.ui["open_header"])
+        self.ui["open_open_button"].connect("clicked", self.on_file_opened)
+        self.ui["open_cancel_button"].connect("clicked", self.on_file_canceled)
+        self.ui["preview_eventbox"].connect('motion-notify-event', self.preview_dragged)
+        self.ui["preview_eventbox"].connect('button-press-event', self.new_path)
+        self.ui["scroll_window"].connect_after("draw", self.draw_ui_brush_circle)
+        self.ui["scroll_window"].connect_after('motion-notify-event', self.mouse_coords_changed)
+        self.ui["preview_button"].connect("clicked", self.create_preview)
+
+        self.ui["open"].connect("clicked", self.on_open_clicked)
+
+        self.update_enabled()
+
+
+    def update_enabled(self):
+        self.ui["toolbar"].set_sensitive(type(self.image) == numpy.ndarray)
+        self.ui["preview_button"].set_sensitive(type(self.image) == numpy.ndarray)
+
+    def on_open_clicked(self, sender):
+        self.ui["open_window"].show_all()
+
+    def on_file_canceled(self, sender):
+        self.ui["open_window"].hide()
+
+    def on_file_opened(self, sender):
+        self.ui["open_window"].hide()
+        path = self.ui["open_chooser"].get_filename()
+        threading.Thread(target=self.load_image, args=(path,)).start()
+
+
+    def load_image(self, path):
+        self.get_sized_image(path)
+        self.root.get_titlebar().set_subtitle("%s" % path)
+
+
+    def get_sized_image(self, path):
+        self.start_work()
+        w = self.ui["scroll_window"].get_allocated_width() - 12
+        h = self.ui["scroll_window"].get_allocated_height() - 12
+        threading.Thread(target=self.get_preview_image, args=(path, w, h)).start()
+
+
+    def get_preview_image(self, path, w, h):
+        if (not os.path.exists("/tmp/inpainter-%s" % getpass.getuser())):
+            os.mkdir("/tmp/inpainter-%s" % getpass.getuser())
+
+        im = cv2.imread(path, 2 | 1)
+        height, width = im.shape[:2]
+
+        self.actual_width = width
+
+        # Get fitting size
+        ratio = float(w) / width
+        if (height * ratio > h):
+            ratio = float(h) / height
+
+        nw = width * ratio
+        nh = height * ratio
+
+        im = cv2.resize(im, (int(nw), int(nh)), interpolation=cv2.INTER_AREA)
+
+        
+        self.image = im
+        self.image_readonly = im.copy()
+        self.mask = Mask.Mask(im, width, height)
+        self.update_preview(im)
+
+    def update_preview(self, image):
+        cv2.imwrite("/tmp/inpainter-%s/pre-preview.tiff" % getpass.getuser(), image)
+        pb = GdkPixbuf.Pixbuf.new_from_file("/tmp/inpainter-%s/pre-preview.tiff" % getpass.getuser())
+        shutil.rmtree("/tmp/inpainter-%s" % getpass.getuser())
+        self.image_pb = pb
+        GLib.idle_add(self.set_pixbuf)
+
+    def set_pixbuf(self):
+        self.ui["preview"].set_from_pixbuf(self.image_pb)
+        self.stop_work()
+        self.update_enabled()
+
+    
+    def preview_dragged(self, widget, event):
+
+        x, y = widget.translate_coordinates(self.ui["preview"], event.x, event.y)
+
+        draw = self.ui["mask_draw_toggle"].get_active()
+        erase = self.ui["mask_erase_toggle"].get_active()
+        if((draw or erase) and self.current_path):
+
+            if (x < 0.0):
+                x = 0
+            if (y < 0.0):
+                y = 0
+
+            pwidth = self.image_pb.get_width()
+            pheight = self.image_pb.get_height()
+
+            if (x > pwidth):
+                x = pwidth
+            if (y > pheight):
+                y = pheight
+
+            print(x, y)
+
+            fill = (0, 0, 255)
+            if(erase):
+                fill = (255, 0, 0)
+
+            self.draw_path(x, y, pheight, pwidth, fill)
+
+            self.on_mask_change()
+
+            self.mouse_down_coords_changed(widget, event)
+            return True
+
+
+    def draw_path(self, x, y, pheight, pwidth, fill):
+        preview = self.current_path.add_point(int(x), int(y), (pheight, pwidth, 3), fill)
+
+        # Bits per pixel
+        bpp = float(str(self.image.dtype).replace("uint", "").replace("float", ""))
+        # Pixel value range
+        np = float(2 ** bpp - 1)
+
+        self.image[preview == 255] = np
+        cv2.imwrite("/dev/shm/inpaint-preview-%s-drag.png" % getpass.getuser(), self.image)
+        temppbuf = GdkPixbuf.Pixbuf.new_from_file("/dev/shm/inpaint-preview-%s-drag.png" % getpass.getuser())
+        self.ui["preview"].set_from_pixbuf(temppbuf)
+
+
+    def new_path(self, widget, event):
+        draw = self.ui["mask_draw_toggle"].get_active()
+        erase = self.ui["mask_erase_toggle"].get_active()
+        if(draw or erase):
+            print(self.image_pb.get_width(), self.image_pb.get_height())
+            width = self.image_pb.get_width()
+            size = self.ui["mask_brush_size"].get_value()
+            feather = 0
+            self.current_path = self.mask.mask.get_new_path(size, feather, float(self.actual_width)/float(width), draw)
+
+    
+    def mouse_coords_changed(self, widget, event):
+        self.mousedown = False
+        self.mousex, self.mousey = event.x, event.y
+        widget.queue_draw()
+
+    def mouse_down_coords_changed(self, widget, event):
+        self.mousedown = True
+        self.mousex, self.mousey = widget.translate_coordinates(self.ui["scroll_window"], event.x, event.y)
+        widget.queue_draw()
+
+
+    def draw_ui_brush_circle(self, widget, context):
+        if(type(self.image) == numpy.ndarray):
+            size = self.ui["mask_brush_size"].get_value()
+            if(self.mousedown):
+                context.set_source_rgb(255, 0, 0)
+            else:
+                context.set_source_rgb(255, 255, 255)
+            context.arc(self.mousex, self.mousey, size/2.0, 0.0, 2 * numpy.pi)
+            context.stroke()
+
+
+    def on_mask_change(self):
+        threading.Thread(target=self.__on_mask_change).start()
+
+    def __on_mask_change(self):
+        image = self.image_readonly.copy()
+        image = self.mask.get_mask_preview(image)
+        self.image = image
+        self.update_preview(image)

+ 488 - 0
ui/Mask_Activity.glade

@@ -0,0 +1,488 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.4 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkFileFilter" id="Mask_filefilter">
+    <mime-types>
+      <mime-type>image/jpeg</mime-type>
+      <mime-type>image/bmp</mime-type>
+      <mime-type>image/png</mime-type>
+      <mime-type>image/tiff</mime-type>
+      <mime-type>image/x-tiff</mime-type>
+    </mime-types>
+  </object>
+  <object class="GtkWindow" id="Mask_open_window">
+    <property name="can_focus">False</property>
+    <property name="modal">True</property>
+    <property name="type_hint">dialog</property>
+    <property name="deletable">False</property>
+    <child>
+      <object class="GtkFileChooserWidget" id="Mask_open_chooser">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="create_folders">False</property>
+        <property name="filter">Mask_filefilter</property>
+      </object>
+    </child>
+    <child type="titlebar">
+      <placeholder/>
+    </child>
+  </object>
+  <object class="GtkBox" id="Mask_header">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="spacing">6</property>
+    <child>
+      <object class="GtkButton" id="Mask_open">
+        <property name="label">gtk-open</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">True</property>
+        <property name="use_stock">True</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkToggleButton" id="Mask_preview_button">
+        <property name="label" translatable="yes">Show Preview</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">True</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
+  <object class="GtkAdjustment" id="Mask_mask_brush_size">
+    <property name="lower">1</property>
+    <property name="upper">200</property>
+    <property name="value">20</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkHeaderBar" id="Mask_open_header">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="title">Open Photo</property>
+    <child>
+      <object class="GtkButton" id="Mask_open_cancel_button">
+        <property name="label">gtk-cancel</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">True</property>
+        <property name="use_stock">True</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkButton" id="Mask_open_open_button">
+        <property name="label">gtk-open</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">True</property>
+        <property name="use_stock">True</property>
+        <style>
+          <class name="suggested-action"/>
+        </style>
+      </object>
+      <packing>
+        <property name="pack_type">end</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
+  <object class="GtkAdjustment" id="Mask_patch_size">
+    <property name="upper">20</property>
+    <property name="value">9</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkBox" id="Mask_main">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="margin_top">1</property>
+    <child>
+      <object class="GtkScrolledWindow" id="Mask_scroll_window">
+        <property name="width_request">600</property>
+        <property name="height_request">500</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="margin_left">18</property>
+        <property name="margin_right">18</property>
+        <property name="margin_top">18</property>
+        <property name="margin_bottom">18</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="shadow_type">in</property>
+        <child>
+          <object class="GtkViewport">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkEventBox" id="Mask_preview_eventbox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="above_child">True</property>
+                <child>
+                  <object class="GtkImage" id="Mask_preview">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">center</property>
+                    <property name="valign">center</property>
+                    <property name="pixbuf">logo.png</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkRevealer">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="halign">end</property>
+        <property name="hexpand">False</property>
+        <property name="transition_type">slide-left</property>
+        <property name="reveal_child">True</property>
+        <child>
+          <object class="GtkBox" id="Mask_toolbar">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <object class="GtkSeparator">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_left">6</property>
+                <property name="orientation">vertical</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkBox">
+                    <property name="width_request">338</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="margin_left">18</property>
+                    <property name="margin_right">18</property>
+                    <property name="margin_top">18</property>
+                    <property name="margin_bottom">18</property>
+                    <property name="orientation">vertical</property>
+                    <property name="spacing">6</property>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="orientation">vertical</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="halign">start</property>
+                            <property name="label" translatable="yes">&lt;b&gt;Inpaint Mask&lt;/b&gt;</property>
+                            <property name="use_markup">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkButtonBox">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="margin_top">8</property>
+                                <property name="margin_bottom">8</property>
+                                <property name="homogeneous">True</property>
+                                <property name="layout_style">expand</property>
+                                <child>
+                                  <object class="GtkToggleButton" id="Mask_mask_draw_toggle">
+                                    <property name="label" translatable="yes">Draw</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">True</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkToggleButton" id="Mask_mask_erase_toggle">
+                                    <property name="label" translatable="yes">Erase</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">True</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkGrid">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="margin_bottom">8</property>
+                                <property name="column_spacing">8</property>
+                                <child>
+                                  <object class="GtkScale">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="hexpand">True</property>
+                                    <property name="adjustment">Mask_mask_brush_size</property>
+                                    <property name="round_digits">1</property>
+                                    <property name="value_pos">right</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">1</property>
+                                    <property name="top_attach">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="halign">end</property>
+                                    <property name="label" translatable="yes">Brush Size</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">0</property>
+                                    <property name="top_attach">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkSeparator">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="orientation">vertical</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="halign">start</property>
+                            <property name="label" translatable="yes">&lt;b&gt;Inpaint Settings&lt;/b&gt;</property>
+                            <property name="use_markup">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkGrid">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="margin_bottom">8</property>
+                                <property name="column_spacing">8</property>
+                                <child>
+                                  <object class="GtkScale">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="hexpand">True</property>
+                                    <property name="adjustment">Mask_patch_size</property>
+                                    <property name="round_digits">1</property>
+                                    <property name="digits">0</property>
+                                    <property name="value_pos">right</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">1</property>
+                                    <property name="top_attach">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="halign">end</property>
+                                    <property name="label" translatable="yes">Patch Size</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">0</property>
+                                    <property name="top_attach">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkSeparator">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">2</property>
+      </packing>
+    </child>
+  </object>
+  <object class="GtkPopoverMenu" id="Mask_popovermenu">
+    <property name="can_focus">False</property>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="margin_left">6</property>
+        <property name="margin_right">6</property>
+        <property name="margin_top">6</property>
+        <property name="margin_bottom">6</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkModelButton" id="Mask_export_image">
+            <property name="visible">True</property>
+            <property name="sensitive">False</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="text" translatable="yes">Export Image</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkModelButton" id="Mask_open_pf2">
+            <property name="visible">True</property>
+            <property name="sensitive">False</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="text" translatable="yes">Send to PhotoFiddle Editor</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+      <packing>
+        <property name="submenu">main</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
+</interface>