예제 #1
0
class Reference(Box):
    __gtype_name__ = "Reference"

    actions = Template.Child("actions")
    grid = Template.Child("grid")

    #new_ref = Template.Child("new_ref")
    #values = Template.Child("values")

    def __init__(self, *args, new=False, **kwargs):
        Box.__init__(self, *args, **kwargs)

        if new:
            #self.new_ref.set_visible(True)
            self.grid.set_visible(False)
            self.props.margin_top = 0
            self.props.margin_bottom = 0

        # Styling
        #context = self.get_style_context()
        #provider = CssProvider()
        #provider.load_from_resource('/ml/prevete/Daty/gtk/reference.css')
        #context.add_provider(provider, STYLE_PROVIDER_PRIORITY_APPLICATION)

    @Template.Callback()
    def button_press_event_cb(self, widget, event):
        visible = self.actions.get_visible()
        self.actions.set_visible(not visible)
예제 #2
0
class LanguageAdd(Window):
    __gtype_name__ = "LanguageAdd"

    cancel = Template.Child("cancel")
    select = Template.Child("select")
    languages = Template.Child("languages")
    search_entry = Template.Child("search_entry")

    def __init__(self, languages, *args, **kwargs):
        Window.__init__(self, *args, **kwargs)

        icon = lambda x: IconTheme.get_default().load_icon((name), x, 0)
        icons = [icon(size) for size in [32, 48, 64, 96]]
        self.set_icon_list(icons)

        self.languages.set_header_func(self.update_header)
        for language in languages:
            row = ListBoxRow()
            label = Label()
            label.set_text(language['itemLabel']['value'])
            label.code = language['c']['value']
            row.child = label
            row.add(label)
            self.languages.add(row)
        self.languages.show_all()

    @Template.Callback()
    def cancel_clicked_cb(self, widget):
        self.hide()
        self.destroy()

    @Template.Callback()
    def select_clicked_cb(self, widget):
        pass

    @Template.Callback()
    def search_entry_search_changed_cb(self, entry):
        for row in self.languages.get_children():
            if entry.get_text().lower() in row.child.get_text().lower():
                row.set_visible(True)
                row.set_no_show_all(False)
            else:
                row.set_visible(False)
                row.set_no_show_all(True)
        self.languages.show_all()

    def update_header(self, row, before, *args):
        """See GTK+ Documentation"""
        if before:
            row.set_header(Separator())
예제 #3
0
class RoundedButton(Button):
    __gtype_name__ = "RoundedButton"

    image = Template.Child("image")

    def __init__(self,
                 *args,
                 image=None,
                 tooltip=None,
                 callback=None,
                 cb_args={},
                 **kwargs):
        Button.__init__(self, *args, **kwargs)

        # Styling
        context = self.get_style_context()
        provider = CssProvider()
        provider.load_from_resource('/ml/prevete/Daty/gtk/roundedbutton.css')
        context.add_provider(provider, STYLE_PROVIDER_PRIORITY_APPLICATION)

        if callback:
            self.connect("clicked", callback, *cb_args)

        if image:
            self.image.set_from_icon_name(image, IconSize.BUTTON)

        if tooltip:
            self.set_tooltip_text(tooltip)
예제 #4
0
class LabeledComponent(Box):
    __gtype_name__='LabeledComponent'
    Label = Template.Child()
    Header = Template.Child(internal=True)
    Main  = Template.Child(internal=True)
    Footer = Template.Child(internal=True)
    def __new__(cls,*args,**kwargs):
        print ("NEW")
        result = Box.__new__(cls,*args,**kwargs)
        return result
    def addHeader(self,comp):
        self.Header.add(comp)
        pass
    def set_label(self,text):
        self.Label.set_label(text)
        pass
    pass
예제 #5
0
class Property(Button):
    __gtype_name__ = "Property"

    __gsignals__ = {'value-new':(sf.RUN_LAST,
                                 TYPE_NONE,
                                 (TYPE_PYOBJECT,))}

    property_label = Template.Child("property_label")
    popover = Template.Child("popover")
    description = Template.Child("description")
    #values = Template.Child("values")

    def __init__(self, prop, *args, **kwargs):
        Button.__init__(self, *args, **kwargs)

        # Styling
        context = self.get_style_context()      
        provider = CssProvider()
        resource = 'ml/prevete/Daty/gtk/property.css'
        provider.load_from_resource(resource)
        context.add_provider(provider, STYLE_PROVIDER_PRIORITY_APPLICATION) 

        context = self.description.get_style_context()
        set_style(context, resource, 'popover_description', True)

        self.set_label(prop["Label"], prop["Description"])
        self.description.set_text(prop['Description'])
        self.description.set_line_wrap(True)


    def set_label(self, label, tooltip):
        self.property_label.set_text(label)
        self.property_label.set_tooltip_text(tooltip)

    @Template.Callback()
    def value_new_clicked_cb(self, widget):
        print("value-new emitted")
        self.emit('value-new', self.position)
        self.popover.popdown()

    @Template.Callback()
    def clicked_cb(self, widget):
        print("hi")
        self.popover.popup()
예제 #6
0
class QualifierProperty(EventBox):
    __gtype_name__ = "QualifierProperty"

    label = Template.Child("label")
    wikidata = Wikidata()

    def __init__(self, prop, *args, **kwargs):
        EventBox.__init__(self, *args, **kwargs)
        self.URI = prop['URI']
        set_text(self.label, prop["Label"], prop["Description"])

    def set_label(self, label, tooltip):
        self.label.set_text(label)
        self.label.set_tooltip_text(tooltip)
예제 #7
0
class Statements(TreeView):
    __gtype_name__ = "Statements"

    list_store = Template.Child("list_store")
    wikidata = Wikidata()

    def __init__(self, *args, **kwargs):
        TreeView.__init__(self, *args, **kwargs)

    def add(self, cell_list):
        self.list_store.append(cell_list)
        self.set_model(self.list_store)
        model = self.get_model()
        print(model)
        print(self.list_store)
        self.show_all()
예제 #8
0
class Editor(ApplicationWindow):

    __gtype_name__ = "Editor"

    __gsignals__ = {'entity-close':(sf.RUN_LAST,
                                    TYPE_NONE,
                                    (TYPE_PYOBJECT,))}

    # Title bar
    titlebar = Template.Child("titlebar")
    header_box = Template.Child("header_box")

    # Header bar
    header_bar = Template.Child("header_bar")
    entity_close = Template.Child("entity_close")
    entity_discussion_open_external = Template.Child("entity_discussion_open_external")
    entity_history_open_external = Template.Child("entity_history_open_external")
    entity_open = Template.Child("entity_open")
    entity_menu_popover = Template.Child("entity_menu_popover")
    entities_search = Template.Child("entities_search")
    entities_select = Template.Child("entities_select")
    entity_open_external = Template.Child("entity_open_external")
    cancel_entities_selection = Template.Child("cancel_entities_selection")
    app_menu = Template.Child("app_menu")
    app_menu_popover = Template.Child("app_menu_popover")
    help = Template.Child("help")

    # Sub header bar
    sub_header_bar = Template.Child("sub_header_bar")
    entity_back = Template.Child("entity_back")
    entity_stack = Template.Child("entity_stack")
    entity_button = Template.Child("entity_button")
    entity = Template.Child("entity")
    description = Template.Child("description")
    entity_search = Template.Child("entity_search")

    # Sidebar
    sidebar = Template.Child("sidebar")
    sidebar_search_bar = Template.Child("sidebar_search_bar")
    sidebar_search_entry = Template.Child("sidebar_search_entry")
    sidebar_viewport = Template.Child("sidebar_viewport")

    # Content
    content_box = Template.Child("content_box")
    content_stack = Template.Child("content_stack")
    single_column = Template.Child("single_column")

    # Specific
    entity_search_bar = Template.Child("entity_search_bar")
    entity_search_entry = Template.Child("entity_search_entry")
    pages = Template.Child("pages")

    start_pane_size_group = Template.Child("start_pane_size_group")

    # Separator
#    edit_column_separator = Template.Child("edit_column_separator")

    # Common
    #common = Template.Child("common-viewport")
    #common_page = Template.Child("common_page")

    wikidata = Wikidata()

    def __init__(self, *args, entities=[], quit_cb=None, max_pages=10, **kwargs):
        """Editor class

            Args:
                entities (list): of dict having keys"Label", "URI", "Description";
                max_pages (int): maximum number of pages kept in RAM
        """
        ApplicationWindow.__init__(self, *args, **kwargs)

        self.quit_cb = quit_cb
        self.open_dialogs = []

        # Set window icon
        icon = lambda x: IconTheme.get_default().load_icon((name), x, 0)
        icons = [icon(size) for size in [32, 48, 64, 96]];
        self.set_icon_list(icons);

        # Set shortcuts
        accelerators = AccelGroup()
        self.add_accel_group(accelerators)
        add_accelerator(accelerators, self.entity_open, "<Control>o", signal="clicked")
        add_accelerator(accelerators, self.entity_search, "<Control>f", signal="clicked")
        add_accelerator(accelerators, self.entity_discussion_open_external, "<Control>d", signal="clicked")
        add_accelerator(accelerators, self.entity_history_open_external, "<Control>h", signal="clicked")
        add_accelerator(accelerators, self.entities_select, "<Control>s", signal="clicked")
        add_accelerator(accelerators, self.cancel_entities_selection, "<Control><Shift>s", signal="clicked")
        add_accelerator(accelerators, self.entities_search, "<Control><Shift>f", signal="activate")


        # Init sidebar
        self.sidebar_list = SidebarList()
        self.sidebar_list.connect("entity-selected", self.sidebar_row_selected_cb)
        self.sidebar_viewport.add(self.sidebar_list)

        # Init pages
        loading = LoadingPage()
        self.pages.add_titled(loading, "loading", "Loading")

        # Parse args
        self.max_pages = max_pages
        if entities:
            self.load(entities)
        else:
            entities_open_dialog = Open(quit_cb=self.quit_cb,
                                        new_session=True)
            entities_open_dialog.connect("new-window-clicked", self.new_window_clicked_cb)
            entities_open_dialog.connect("window-new", self.open_window_new_clicked_cb)
            self.open_dialogs.append(entities_open_dialog)
            entities_open_dialog.get_focus()

    def filter(self, query, text):
        return query.lower() in text.lower()

    def sidebar_search_entry_search_changed_cb(self, entry):
        text = entry.get_text()
        for row in self.sidebar_list.get_children():
            if row.get_children():
                child = row.child
                entity = child.entity
                if text.lower() in entity["Label"].lower() or text.lower() in entity["Description"].lower():
                    row.set_visible(True)
                    label_color(child.label, text)
                    label_color(child.description, text)
                else:
                    row.set_visible(False)

    def sidebar_row_selected_cb(self, sidebar_list, entity):
        print("Editor: sidebar row selected")
        self.single_column.set_visible_child_name("content_stack")
        self.header_box.set_visible_child_name("sub_header_bar")

        # Set titlebar
        def set_text(widget, label):
            widget.set_text(label)
            widget.set_tooltip_text(label)

        set_text(self.entity, entity["Label"])
        set_text(self.description, entity["Description"])

        if hasattr(self, 'entity_open_external_connection'):
            self.entity_open_external.disconnect(self.entity_open_external_connection)
        self.entity_open_external_connection = self.entity_open_external.connect("clicked",
                                                                                 self.entity_open_external_clicked_cb,
                                                                                 entity['URI'])
        if hasattr(self, 'entity_history_open_external_connection'):
            self.entity_history_open_external.disconnect(self.entity_history_open_external_connection)
        self.entity_history_open_external_connection = self.entity_history_open_external.connect("clicked",
                                                                                                 self.entity_history_open_external_clicked_cb,
                                                                                                 entity['URI'])
        if hasattr(self, 'entity_discussion_open_external_connection'):
            self.entity_discussion_open_external.disconnect(self.entity_discussion_open_external_connection)
        self.entity_discussion_open_external_connection = self.entity_discussion_open_external.connect("clicked",
                                                                                                       self.entity_discussion_open_external_clicked_cb,
                                                                                                       entity['URI'])
        # Get selected sidebar entity for popover close button
        current_row = self.sidebar_list.get_selected_row()
        sidebar_entity = current_row.child

        if not self.pages.get_child_by_name(entity['URI']):
            self.pages.set_visible_child_name("loading")
            children = self.pages.get_children()

            if len(children) >= 10:
                oldest = children[1]
                children.remove(oldest)
                oldest.destroy()
                del oldest

            # TODO: Implement a short timeout to make sure you explicitly wanted to load the row

            self.load_page_async(entity)
        else:
            self.pages.set_visible_child_name(entity['URI'])
            self.entity_search_entry.connect('search-changed',
                                             self.entity_search_entry_search_changed_cb)
            self.sidebar_search_entry.connect('search-changed',
                                             self.sidebar_search_entry_search_changed_cb)

    def load_page_async(self, entity):
        def do_call():
            idle_add(lambda: self.on_page_complete(entity))
        thread = MyThread(target = do_call)
        thread.start()

    def on_page_complete(self, entity):
        page = Page(entity['Data'])
        page.connect("claim-changed", self.claim_changed_cb)
        page.connect("entity-editing", self.entity_editing_cb)
        self.entity_leaving_connection = page.connect("entity-leaving", self.entity_leaving_cb)
        #self.connect("claim-changed-done", page.claim_changed_done_cb)
        page.connect("new-window-clicked", self.new_window_clicked_cb)
        page.connect("reference-new-clicked", self.reference_new_clicked_cb)
        self.pages.add_titled(page, entity['URI'], entity['Label'])
        self.pages.set_visible_child_name(entity['URI'])
        self.entity_search_entry.connect("search-changed",
                                         self.entity_search_entry_search_changed_cb)
        self.sidebar_search_entry.connect("search-changed",
                                          self.sidebar_search_entry_search_changed_cb)
        return None

    def value_disable_signals(self, page, value, entity):
        print("Editor: disabling all Value signals")

        try:
            if hasattr(value, 'button_press_connection'):
                value.disconnect(value.button_press_connection)

            if hasattr(self, 'reference_new_connection'):
                page_connection = self.reference_new_connection
                page_enter = self.from_value_qualifier_new_enter_connection
                page_leave = self.from_value_qualifier_new_leave_connection
                reference_enter = self.from_value_reference_new_enter_connection
                reference_leave = self.from_value_reference_new_leave_connection
                del self.reference_new_connection
            elif hasattr(self, 'entity_popover_connection'):
                page_connection = self.entity_popover_connection
                page_enter = self.qualifier_new_enter_connection
                page_leave = self.qualifier_new_leave_connection
                reference_enter = self.reference_new_enter_connection
                reference_leave = self.reference_new_leave_connection
                del self.entity_popover_connection
            else:
                print("no signals to be disconnected")
                raise Exception

            page.disconnect(page_connection)
            self.current_value.qualifier_new.disconnect(page_enter)
            self.current_value.qualifier_new.disconnect(page_leave)
            self.current_value.reference_new.disconnect(reference_enter)
            self.current_value.reference_new.disconnect(reference_leave)
            self.current_value.button_press_connection = self.current_value.connect("button-press-event",
                                                                                        self.current_value.clicked_cb)

            self.current_value.actions.set_visible(False)
            self.current_value.button.set_visible(True)

        except Exception as e:
            print(e)
            pass

    def reference_new_clicked_cb(self, page, value, entity):
        self.value_disable_signals(page, value, entity)
        if not hasattr(self, 'reference_new_connection'):
            self.current_value = value
            self.reference_new_connection = page.connect("button-press-event",
                                                         self.reference_new_button_press_event_elsewhere,
                                                         value,
                                                         entity)
            print("Editor: Page 'button-press-event' connected to 'elsewhere' cb with value", self.reference_new_connection)

            self.from_value_qualifier_new_enter_connection = value.qualifier_new.connect("enter-notify-event",
                                                                                         self.from_value_object_new_enter_notify_event_cb,
                                                                                         page,
                                                                                         value,
                                                                                         entity)
            self.from_value_qualifier_new_leave_connection = value.qualifier_new.connect("leave-notify-event",
                                                                                         self.from_value_object_new_leave_notify_event_cb,
                                                                                         page,
                                                                                         value,
                                                                                         entity)

            self.from_value_reference_new_enter_connection = value.reference_new.connect("enter-notify-event",
                                                                                         self.from_value_object_new_enter_notify_event_cb,
                                                                                         page,
                                                                                         value,
                                                                                         entity)
            self.from_value_reference_new_leave_connection = value.reference_new.connect("leave-notify-event",
                                                                                         self.from_value_object_new_leave_notify_event_cb,
                                                                                         page,
                                                                                         value,
                                                                                         entity)


    def from_value_object_new_enter_notify_event_cb(self, qualifier_new, event, page, value, entity):
        print("Editor: entering new disposable entry")
        print("disconnect elsewhere signal", self.reference_new_connection)
        page.disconnect(self.reference_new_connection)

    def from_value_object_new_leave_notify_event_cb(self, actions, event, page, value, entity):
        print("Editor: leaving new disposable entry")
        self.reference_new_connection = page.connect("button-press-event",
                                                     self.reference_new_button_press_event_elsewhere,
                                                     value,
                                                     entity)
        print("reconnecting page to 'reference new button press elsewhere'", self.reference_new_connection)


    def reference_new_button_press_event_elsewhere(self, page, event, value, entity):
        visible = value.actions.get_visible()
        if not visible:
            print("Elsewhere cb: show actions")
            value.actions.set_visible(True)
            if not hasattr(value, 'references'):
                value.button.set_visible(False)
        else:
            self.value_disable_signals(page, value, entity)
            value.actions.set_visible(False)
            value.button.set_visible(True)

    def entity_leaving_cb(self, page, value, entity):
        print("Editor: entity leaving")
        value.actions.set_visible(False)
        if not hasattr(value, 'references'):
            value.button.set_visible(True)
        return True


    def entity_editing_cb(self, page, value, entity, popover):
        print("Editor: entity editing")
        self.value_disable_signals(page, value, entity)
        self.current_value = value
        value.actions.set_visible(True)
        if not hasattr(value, 'references'):
            value.button.set_visible(False)

        self.entity_popover_connection = page.connect("button-press-event",
                                                      self.button_press_event_cb,
                                                      value,
                                                      entity)
        print("Editor: Page 'button-press-event' connected to 'elsewhere' cb with value", self.entity_popover_connection)
        self.qualifier_new_enter_connection = value.qualifier_new.connect("enter-notify-event",
                                                                          self.object_new_enter_notify_event_cb,
                                                                          page,
                                                                          value)
        self.qualifier_new_leave_connection = value.qualifier_new.connect("leave-notify-event",
                                                                          self.object_new_leave_notify_event_cb,
                                                                          page,
                                                                          value,
                                                                          entity)
        self.reference_new_enter_connection = value.reference_new.connect("enter-notify-event",
                                                                          self.object_new_enter_notify_event_cb,
                                                                          page,
                                                                          value)
        self.reference_new_leave_connection = value.reference_new.connect("leave-notify-event",
                                                                          self.object_new_leave_notify_event_cb,
                                                                          page,
                                                                          value,
                                                                          entity)

    def object_new_enter_notify_event_cb(self, object_new, event, page, value):
        print("Editor: entering new object entry")
        page.disconnect(self.entity_popover_connection)
        page.disconnect(self.entity_leaving_connection)

    def object_new_leave_notify_event_cb(self, actions, event, page, value, entity):
        print("Editor: leaving new object entry")
        self.entity_popover_connection = page.connect("button-press-event",
                                                      self.button_press_event_cb,
                                                      value,
                                                      entity)
        self.entity_leaving_connection = page.connect("entity-leaving",
                                                      self.entity_leaving_cb)

    def button_press_event_cb(self, page, event, value, entity):
        print("Disconnecting all signals")
        self.value_disable_signals(page, value, entity)

        print("Editor: Entity entry emitting 'focus-out-event'")
        event = Event(EventType(12))
        event.window = page.get_window()  # the gtk.gdk.Window of the widget
        event.send_event = True  # this means you sent the event explicitly
        event.in_ = False
        entity.entry.emit("focus-out-event", event)

    def claim_changed_cb(self, page, claim, target, value):
        print("Editor: claim changed")
        URI = self.pages.get_visible_child_name()
        edit(URI, claim, target, self.on_claim_changed, value)

    def on_claim_changed(self, target, error, value):
        if not error:
            set_style(value.context, '/ml/prevete/Daty/gtk/value.css',
                                     'loading', False)
            print("Modifica effettuata correttamente")
        else:
            print("Error", error)


    def entity_search_entry_search_changed_cb(self, entry):
        text = entry.get_text()
        page = self.pages.get_visible_child()
        statements = page.statements
        i = 0
        row = lambda i,j: statements.get_child_at(j,i)
        while row(i,0):
            p_label = row(i,0).property_label.get_text()
            p_desc = row(i,0).property_label.get_tooltip_text()
            p_found = self.filter(text, p_label) or self.filter(text, p_desc)
            if p_found:
                label_color(row(i,0).property_label, text)
                row(i,0).set_visible(True)
                row(i,1).set_visible(True)
            else:
                label_color(row(i,0).property_label, color='')
                row(i,0).set_visible(False)
                row(i,1).set_visible(False)
            i = i + 1

    def load(self, entities):
        """Open entities

            Args:
                entities (list): of dict having "URI", "Label", "Description" keys;
        """
        for entity in entities[:-1]:
            download(entity, self.load_row_async, use_cache=False)
        download(entities[-1], self.load_row_async, select=True)
        self.show()
        self.present()

    def load_row_async(self, entity, **kwargs):
        """It creates sidebar passing downloaded data to its rows.

            Gets executed when download method has finished its task

            Args:
                entity (dict): have keys "URI", "Label", "Description", "Data"
        """
        f = lambda : entity
        def do_call():
            entity = f()
            idle_add(lambda: self.on_row_complete(entity, **kwargs))
        thread = MyThread(target = do_call)
        thread.start()

    def on_row_complete(self, entity, **kwargs):

        # Build entity
        if not entity['Label']:
            entity['Label'] = self.wikidata.get_label(entity['Data'], language='en')
        if not entity['Description']:
            entity['Description'] = self.wikidata.get_description(entity['Data'])

        sidebar_entity = SidebarEntity(entity, description=True, URI=True)
        sidebar_entity.button.connect("clicked", self.entity_close_clicked_cb,
                                      sidebar_entity)

        row = ListBoxRow()
        row.child = sidebar_entity

        row.add(sidebar_entity)

        current_row = self.sidebar_list.get_selected_row()
        rows = self.sidebar_list.get_children()
        i = 0
        for i, r in enumerate(rows):
            if r == current_row:
                break
        if (i < len(rows) - 2):
            self.sidebar_list.insert(row, i+1)
        else:
            self.sidebar_list.add(row)
        self.sidebar_list.show_all()
        if 'select' in kwargs and kwargs['select']:
            self.sidebar_list.select_row(row)

    @Template.Callback()
    def entity_open_clicked_cb(self, widget):
        """New entity button clicked callback

            If clicked, it opens the 'open new entities' window.

            Args:
                widget (Gtk.Widget): the clicked widget.
        """
        open_dialog = Open(quit_cb=self.quit_cb, new_session=False)
        open_dialog.connect("entity-new", self.entity_new_clicked_cb)
        open_dialog.connect("new-window-clicked", self.new_window_clicked_cb)
        open_dialog.connect("window-new", self.open_window_new_clicked_cb)
        self.open_dialogs.append(open_dialog)

    def new_window_clicked_cb(self, dialog, entities):
        self.load(entities)
        #print("Editor: new window clicked")
        #open_dialog = Open(quit_cb=self.quit_cb, new_session=False)
        #open_dialog.connect("entity-new", self.entity_new_clicked_cb)
        #open_dialog.connect("new-window-clicked", self.new_window_clicked_cb)
        #open_dialog.connect("window-new", self.open_window_new_clicked_cb)
        #self.open_dialogs.append(open_dialog)

    def open_window_new_clicked_cb(self, dialog, good):
        print(good)
        print("Editor: new open dialog")

        open_dialog = Open(quit_cb=self.quit_cb, new_session=False)
        open_dialog.connect("entity-new", self.entity_new_clicked_cb)
        open_dialog.connect("new-window-clicked", self.new_window_clicked_cb)
        open_dialog.connect("window-new", self.open_window_new_clicked_cb)
        self.open_dialogs.append(open_dialog)

    def entity_new_clicked_cb(self, open, query):
        print("New entity", query)


    def entity_history_open_external_clicked_cb(self, widget, URI):
        browser_open(''.join(['https://wikidata.org/w/index.php?action=history&title=', URI]))

    def entity_discussion_open_external_clicked_cb(self, widget, URI):
        browser_open(''.join(['https://www.wikidata.org/wiki/Talk:', URI]))

    def entity_open_external_clicked_cb(self, widget, URI):
        browser_open('/'.join(['https://wikidata.org/wiki', URI]))

    @Template.Callback()
    def entities_search_toggled_cb(self, widget):
        if widget.get_active():
            self.sidebar_search_bar.set_search_mode(True)
        else:
            self.sidebar_search_bar.set_search_mode(False)

    @Template.Callback()
    def entities_select_clicked_cb(self, widget):
        """Select sidebar entities button clicked callback

            If clicked, activates header bar selection mode.

            Args:
                widget (Gtk.Widget): the clicked widget.
        """
        self.set_selection_mode(True)

    @Template.Callback()
    def cancel_entities_selection_clicked_cb(self, widget):
        """Cancel sidebar entities selection button clicked callback

            If clicked, disables header bar selection mode.

            Args:
                widget (Gtk.Widget): the clicked widget.
        """
        self.set_selection_mode(False)

    def set_selection_mode(self, value):
        """Toggle selection mode

            Args:
                value (bool): if True, activates selection mode.
        """
        # Titlebar
        self.titlebar.set_selection_mode(value)
        # New entity button
        self.entity_open.set_visible(not value)
        # Entities search button
        self.entities_search.set_visible(value)
        # App menu
        self.app_menu.set_visible(not value)
        # Select button
        self.entities_select.set_visible(not value)
        # Cancel selection button
        self.cancel_entities_selection.set_visible(value)
        # Sidebar
        self.sidebar_list.set_selection_mode(value)
        if value:
            self.column_separator = Separator()
            self.common = Label(label="common")
            self.content_box.add(self.column_separator)
            self.content_box.add(self.common)
            self.content_box.show_all()
        else:
            self.content_box.remove(self.column_separator)
            self.content_box.remove(self.common)

    @Template.Callback()
    def app_menu_clicked_cb(self, widget):
        """Primary menu button clicked callback

            If clicked, open primary menu (app menu).

            Args:
                widget (Gtk.Widget): the clicked widget.
        """
        if self.app_menu_popover.get_visible():
            self.app_menu_popover.hide()
        else:
            self.app_menu_popover.set_visible(True)

    @Template.Callback()
    def entity_menu_clicked_cb(self, widget):
        """Primary menu button clicked callback

            If clicked, open primary menu (app menu).

            Args:
                widget (Gtk.Widget): the clicked widget.
        """
        if self.entity_menu_popover.get_visible():
            self.entity_menu_popover.hide()
        else:
            self.entity_menu_popover.set_visible(True)

    @Template.Callback()
    def on_content_box_folded_changed(self, leaflet, folded):
        """Third column folding signal

            If in selection/multi-editing mode, set stack switcher
            depending on window size

            Args:
                leaflet (Handy.Leaflet): the leaflet emitting the signal;
                folded (GParamBoolean): whether it is folded or not.
        """
        # If we are in selection mode
        if self.titlebar.get_selection_mode():
            # If the title is displayed
            if self.content_box.props.folded:
                # Set switcher in the titlebar
                self.entity_stack.set_visible_child_name("column_switcher")

                # Move common page from third column to content_stack
                self.content_box.remove(self.column_separator)
                self.content_box.remove(self.common)
                self.content_stack.add_titled(self.common, "common", "Common")

            else:
                # Set the switcher to something else
                self.entity_stack.set_visible_child_name("entity_button")

                # Move common page from content stack to third column
                self.content_stack.remove(self.common)
                self.content_box.add(self.column_separator)
                self.content_box.add(self.common)

    @Template.Callback()
    def on_single_column_folded_changed(self, leaflet, folded):
        if self.single_column.props.folded:
            self.entity_back.set_visible(True)
        else:
            self.entity_back.set_visible(False)

    @Template.Callback()
    def entity_back_clicked_cb(self, widget):
        self.header_box.set_visible_child(self.header_bar)
        self.single_column.set_visible_child(self.sidebar)

    @Template.Callback()
    def entity_search_toggled_cb(self, widget):
        if widget.get_active():
            self.entity_search_bar.set_search_mode(True)
        else:
            self.entity_search_bar.set_search_mode(False)

    #@Template.Callback()
    def key_press_event_cb(self, window, event):
        """Manages editor's key press events

        Args:
            window (Gtk.Window): it is self;
            event (Gdk.Event): the key press event.
        """
        if event.keyval in modifiers:
            return None
        focused = window.get_focus()

        # Sidebar
        sidebar_leaflet_focused = self.single_column.get_visible_child_name() == 'sidebar'
        if hasattr(focused, 'child'):
            if type(focused.child) == SidebarEntity:
                sidebar_entity_focused = True
        else:
            sidebar_entity_focused = False
        sidebar_focused = sidebar_leaflet_focused or sidebar_entity_focused

        # Search Entries
        search_entry_focused = type(focused) == SearchEntry
        sidebar_search_entry_focused = focused == self.sidebar_search_entry
        entity_search_entry_focused = type(focused) == self.entity_search_entry

        if sidebar_focused:
            if not self.sidebar_search_bar.get_search_mode():
                self.entities_search.set_active(True)
                self.sidebar_search_bar.set_search_mode(True)
            else:
                self.sidebar_search_entry.grab_focus()
        elif search_entry_focused:
            if entity_search_entry_focused:
                if not self.entity_search_bar.get_search_mode():
                    self.entity_search.set_active(True)
                    self.entity_search_bar.set_search_mode(True)
        else:
            if event.keyval == KEY_Escape:
                 if self.titlebar.get_selection_mode():
                     self.set_selection_mode(False)
            else:
                if not self.entity_search_bar.get_search_mode():
                    self.entity_search.set_active(True)
                    self.entity_search_bar.set_search_mode(True)
                    #self.entity_search_entry.set_text(event.string)

    @Template.Callback()
    def entity_search_entry_stop_search_cb(self, widget):
        if self.entity_search.get_active():
            self.entity_search.set_active(False)
            self.entity_search_bar.set_search_mode(False)

    def entity_close_clicked_cb(self, widget, sidebar_entity):
        row = sidebar_entity.get_parent()
        print(row)
        URI = sidebar_entity.entity["URI"]
        self.sidebar_list.last = list(filter(lambda x: x != row,
                                             self.sidebar_list.last))
        row.destroy()
        try:
            page = self.pages.get_child_by_name(URI)
            page.destroy()
        except Exception as e:
            print ("page not loaded")

    def get_neighbor(self, i, next=True):
        f = lambda x: x + 1 if next else x - 1
        while True:
            try:
                print(self.sidebar_list.get_children())
                self.sidebar_list.get_row_at_index(i)
                return True
            except AttributeError as e:
                i = f(i)
예제 #9
0
class Page(ScrolledWindow):

    __gtype_name__ = "Page"

    __gsignals__ = {
        'claim-changed': (sf.RUN_LAST, TYPE_NONE,
                          (TYPE_PYOBJECT, TYPE_PYOBJECT, TYPE_PYOBJECT)),
        'entity-editing': (sf.RUN_LAST, TYPE_NONE,
                           (TYPE_PYOBJECT, TYPE_PYOBJECT, TYPE_PYOBJECT)),
        'entity-leaving':
        (sf.RUN_LAST, TYPE_NONE, (TYPE_PYOBJECT, TYPE_PYOBJECT)),
        'new-window-clicked': (sf.RUN_LAST, TYPE_NONE, (TYPE_PYOBJECT, )),
        'reference-new-clicked': (sf.RUN_LAST, TYPE_NONE, (
            TYPE_PYOBJECT,
            TYPE_PYOBJECT,
        )),
    }

    image = Template.Child("image")
    statements = Template.Child("statements")

    references_toggled = 1

    def __init__(self, entity, *args, new=False, **kwargs):
        ScrolledWindow.__init__(self, *args, **kwargs)

        claims = entity['claims']

        if not 'P18' in claims:
            self.image.set_visible(False)

        for i, P in enumerate(claims):
            download_light(P, self.load_property, i)
            N = len(claims[P])
            if N > 5:
                frame = ScrolledWindow()
                frame.height = 36 * 6
                frame.set_min_content_height(frame.height)
            else:
                frame = Frame()
            frame.set_shadow_type(2)
            frame.set_visible(True)
            values = Values()
            values.connect("reference-toggled", self.reference_toggled_cb,
                           frame)

            frame.add(values)
            self.statements.attach(frame, 1, i, 3, 1)
            for claim in claims[P]:
                claim = claim.toJSON()
                self.load_value_async(claim, values)

    def reference_toggled_cb(self, values, state, frame):
        if type(frame) == ScrolledWindow:
            if state:
                self.references_toggled += 1
            else:
                self.references_toggled -= 1
            frame.set_min_content_height(frame.height *
                                         min(self.references_toggled, 3))

    @Template.Callback()
    def statement_add_clicked_cb(self, widget):
        print("deve comparire una barra di ricerca")

    def load_property(self, URI, prop, error, i):
        try:
            if error:
                print(error)
            prop = Property(prop)
            prop.connect('value-new', self.property_value_new_clicked_cb)
            prop.position, prop.size = (0, i), (1, 1)
            self.statements.attach(prop, *prop.position, *prop.size)
            return None
        except Exception as e:
            print(URI)
            raise e

    def property_value_new_clicked_cb(self, property, original_position):
        get_top = lambda x: self.statements.child_get_property(x, 'top-attach')
        property_top_value = get_top(property)
        for x in self.statements.get_children():
            if get_top(x) == property_top_value:
                while type(x) in (Frame, ScrolledWindow, Viewport):
                    x = x.get_children()[0]
                    values = x
        while not type(x) == Value:
            x = x.get_children()[0]
            value = x
        print(value.entity)
        print(values.get_children()[0].get_children())
        claim = {
            'mainsnak': {
                'snaktype': 'value',
                'datavalue': {
                    'type': 'wikibase-entityid',
                    'value': {
                        'entity-type': 'item',
                        'numeric-id': 1
                    }
                },
                'datatype': 'wikibase-item'
            }
        }
        #value = Value(claim=claim, new=True)
        #values.insert(value,0)
        value = Value(claim={}, new=True)
        values.add(value)
        values.show_all()
        #event = EventButton()
        #value.entity.value_eventbox.do_button_press_event(self, event)
        #value.entity.set_visible_child_name('entry')
        #value.entity.entry.grab_focus()
        #values.show_all()

    def load_value_async(self, claim, values):
        def do_call():
            error = None
            try:
                pass
            except Exception as err:
                error = err
            idle_add(lambda: self.on_value_complete(claim, values, error))  #,
            #priority=PRIORITY_LOW)

        thread = MyThread(target=do_call)
        thread.start()

    def on_value_complete(self, claim, values, error):
        if error:
            print(error)
        value = Value(claim=claim)
        value.connect("entity-editing", self.entity_editing_cb)
        value.connect("entity-leaving", self.entity_leaving_cb)
        value.connect("claim-changed", self.claim_changed_cb)
        value.connect("new-window-clicked", self.new_window_clicked_cb)
        value.connect("reference-new-clicked", self.reference_new_clicked_cb)
        value.connect('references-toggled', values.references_toggled_cb)
        values.add(value)
        values.show_all()
        return None

    def reference_new_clicked_cb(self, value, entity):
        self.emit("reference-new-clicked", value, entity)
        return True

    def entity_leaving_cb(self, value, entity):
        print("Page: entity leaving")
        self.emit("entity-leaving", value, entity)
        return True

    def entity_editing_cb(self, value, entity, popover):
        self.emit("entity-editing", value, entity, popover)
        #self.entity_popover_connection = self.connect("button-press-event",
        #                                              self.button_press_event_cb,
        #                                              entity,
        #                                              popover)

    def button_press_event_cb(self, widget, event, entity, popover):
        print(event)
        popover.set_visible(False)
        entity.set_visible_child_name("view")
        try:
            self.disconnect(self.entity_popover_connection)
        except Exception as e:
            print(e)

    def claim_changed_cb(self, value, claim, target):
        self.emit("claim-changed", claim, target, value)

    def new_window_clicked_cb(self, value, entity):
        self.emit("new-window-clicked", entity)
예제 #10
0
class Open(Window):
    __gtype_name__ = "Open"

    __gsignals__ = {'entity-new':(sf.RUN_LAST,
                                  TYPE_NONE,
                                  (TYPE_PYOBJECT,)),
                    'new-window-clicked':(sf.RUN_LAST,
                                          TYPE_NONE,
                                          (TYPE_PYOBJECT,)),
                    'window-new':(sf.RUN_LAST,
                                  TYPE_NONE,
                                  (TYPE_PYOBJECT,))}

    wikidata = Wikidata()

    app_menu = Template.Child("app_menu")
    back = Template.Child("back")
    bottom_bar = Template.Child("bottom_bar")
    header_bar = Template.Child("header_bar")
    cancel = Template.Child("cancel")
    filters_box = Template.Child("filters_box")
    filters_viewport = Template.Child("filters_viewport")
    filter_new_box = Template.Child("filter_new_box")
    filters_subtitle = Template.Child("filters_subtitle")
    help = Template.Child("help")
    help_menu = Template.Child("help_menu")
    open_session = Template.Child("open_session")
    page = Template.Child("page")
    open_button = Template.Child("open_button")
    results = Template.Child("results")
    results_listbox = Template.Child("results_listbox")
    results_nope_query = Template.Child("results_nope_query")
    results_number_box = Template.Child("results_number_box")
    results_number = Template.Child("results_number")
    select = Template.Child("select")
    select_entities = Template.Child("select_entities")
    select_menu = Template.Child("select_menu")
    search_box = Template.Child("search_box")
    search_entry = Template.Child("search_entry")
    subtitle = Template.Child("subtitle")
    title = Template.Child("title")
    titlebar = Template.Child("titlebar")

    def __init__(self, *args, new_session=True, quit_cb=None, verbose=False):
        Window.__init__(self, *args)

        # Set window icon
        icon = lambda x: IconTheme.get_default().load_icon((name), x, 0)
        icons = [icon(size) for size in [32, 48, 64, 96]];
        self.set_icon_list(icons);

        self.verbose = verbose
        self.new_session = new_session
        self.results_listbox.selected = EntitySet()
        self.filtered_results = EntitySet()
        self.entities = self.results_listbox.selected
        self.variables = EntitySet(triplet=False)
        self.hb_title = self.header_bar.get_title()
        self.hb_subtitle = self.header_bar.get_subtitle()

        self.search_entry_connection = self.search_entry.connect("search-changed",
                                                                 self.search_entry_search_changed_cb)

        self.filters_listbox = FiltersList()
        self.filters_viewport.add(self.filters_listbox)

        if quit_cb:
            self.quit_cb = quit_cb
            self.connect("delete-event", self.on_quit)
        self.show()

        if new_session:
            self.header_bar.set_show_close_button(True)
        else:
            self.header_bar.set_show_close_button(False)
            self.back.set_visible(True)

        self.open_button.connect('clicked', self.open_button_clicked_cb)
        text = """<b>Search for an <a href="url">entity</a> in the database</b>"""
        if system() == 'Linux':
            url = "help:daty/daty-entities"
        if system() == 'Windows':
            url = "http://daty.prevete.ml/daty-entities.html"
        text = sub('url', url, text)
        set_text(self.subtitle, text, url, markup=True)

    def on_quit(self, widget, event):
        self.quit_cb()


    def set_search_placeholder(self, value):
        self.title.set_visible(value)
        self.subtitle.set_visible(value)
        self.filters_subtitle.set_visible(value)
        self.help.set_visible(value)
        self.help_menu.set_visible(not value)
        self.select.set_visible(not value)
        #self.open_button.set_visible(not value)
        self.results.set_visible(not value)
        child = self.page.get_child_at(0,0)
        child.set_property("vexpand", value)
        if value:
            self.page.child_set_property(child, "width", 2)
            if not self.filters_box.get_visible():
                self.filter_new_box.props.valign = 1
        else:
            self.page.child_set_property(child, "width", 1)
            if not self.filters_box.get_visible():
                self.filter_new_box.props.valign = 0

    def open_button_clicked_cb(self, widget):
        if self.entities != []:
            self.emit("new-window-clicked", self.entities)
        self.destroy()

    @Template.Callback()
    def back_clicked_cb(self, widget):
        self.destroy()

    @Template.Callback()
    def app_menu_clicked_cb(self, widget):
        if self.app_menu.get_visible():
            self.app_menu.hide()
        else:
            self.app_menu.set_visible(True)

    @Template.Callback()
    def filters_help_clicked_cb(self, widget):
        if system() == 'Linux':
            show_uri (None, "help:daty/daty-filters-overview", CURRENT_TIME)
        if system() == 'Windows':
            from webbrowser import open
            open('http://daty.prevete.ml/daty-filters-overview.html')

    @Template.Callback()
    def help_clicked_cb(self, widget):
        if system() == 'Linux':
            show_uri (None, "help:daty", CURRENT_TIME)
        if system() == 'Windows':
            from webbrowser import open
            open('http://daty.prevete.ml')

    @Template.Callback()
    def on_about(self, widget):
        from .aboutdaty import AboutDaty
        about_dialog = AboutDaty(transient_for=self, modal=True)
        about_dialog.present()

    @Template.Callback()
    def filter_new_clicked_cb(self, widget):
        self.filters_box.set_visible(True)
        self.filters_subtitle.set_visible(False)
        triplet = Triplet(variables=self.variables)
        triplet.connect("default-variable-selected", self.triplets_default_variable_selected_cb)
        triplet.connect("entity-new", self.entity_new_clicked_cb)
        triplet.connect("new-window-clicked", self.new_window_clicked_cb)
        triplet.connect("object-selected", self.triplets_check_cb)
        triplet.connect("variable-deleted", self.triplet_variable_deleted_cb)
        row = OverlayedListBoxRow(triplet)
        row.context = row.get_style_context()
        provider = CssProvider()
        provider.load_from_resource('/ml/prevete/Daty/gtk/value.css')
        row.context.add_provider(provider, STYLE_PROVIDER_PRIORITY_APPLICATION)
        row.context.add_class('unreferenced')

        close_button = RoundedButton(callback=self.triplet_delete,
                                     cb_args=[row])
        close_button.set_visible(True)
        row.revealer.add(close_button)
        self.filters_listbox.add(row)
        self.filters_listbox.show_all()

    def entity_new_clicked_cb(self, popover, query):
        self.emit("entity-new", query)

    def new_window_clicked_cb(self, triplet, entities):
        self.emit("new-window-clicked", entities)

    def triplet_variable_deleted_cb(self, triplet, entity):
        output = self.objects_foreach(self.object_delete, entity)
        for object in (o for o in output if o):
            object.entity["Label"] = "deleted variable"
            object.entity["Description"] = "deleted variable"
            object.entity["URI"] = ""
            del object.entity["Variable"]
            triplet.set_widget(object, object.entity)
        self.triplets_check_cb(triplet, entity)


    def object_delete(self, triplet, object, entity):
        if object.entity == entity:
            return object

    def objects_foreach(self, function, *args):
        output = []
        for row in (r for r in self.filters_listbox if hasattr(r, 'child')):
            triplet = row.child
            for object in triplet.members:
                output.append(function(triplet, object, *args))
        return output

    def triplet_delete(self, widget, row):
        row.destroy()
        if not [r for r in self.filters_listbox if hasattr(r, 'child')]:
            self.filters_box.set_visible(False)
            self.filters_subtitle.set_visible(True)
            self.search_entry.disconnect(self.search_entry_connection)
            self.search_entry_connection = self.search_entry.connect("search-changed",
                                                                     self.search_entry_search_changed_cb)
            self.results_number_box.set_visible(False)


    def triplets_check_cb(self, triplet, entity):
        print("Open: checking triplet")
        triplets = []
        statements = []
        for row in (r for r in self.filters_listbox if hasattr(r, 'child')):
            triplet = row.child
            entities = [o.entity for o in triplet.members]
            ready = all('Variable' in e or e['URI'] for e in entities)
            #triplets.append(ready)
            if ready:
                statements.append({'s':entities[0],
                                   'p':entities[1],
                                   'o':entities[2]})
                try:
                    row.context.remove_class('unreferenced')
                except:
                    pass
            else:
                row.context.add_class("unreferenced")
        var = [s[r] for s in statements for r in s if "Variable" in s[r] and s[r]["Variable"]]
        if var: var = var[-1]
        if statements and var:
            self.results.set_visible_child_name("results_searching")
            select(var, statements, self.on_select_done)
            self.set_search_placeholder(False)
        else:
            self.search_entry.disconnect(self.search_entry_connection)
            self.search_entry_connection = self.search_entry.connect("search-changed",
                                                                     self.search_entry_search_changed_cb)
            if not self.search_entry.get_text():
                self.set_search_placeholder(True)

    def on_download_done(self, URI, entity, error):
        if not entity:
            print("problematic URI", URI)
        else:
            entity = SidebarEntity(entity, button=False)
            row = ListBoxRow()
            row.child = entity
            row.add(entity)
            self.results_listbox.add(row)
            self.results_listbox.show_all()

    def on_select_done(self, results):
        if not results:
            self.results.set_visible_child_name("results_filters_nope")
            self.search_entry.disconnect(self.search_entry_connection)
            self.search_entry_connection = self.search_entry.connect("search-changed",
                                                                     self.search_entry_search_changed_cb)
            self.results_number_box.set_visible(False)
        if results:
            n = len(results)
            self.search_entry.disconnect(self.search_entry_connection)
            self.search_entry_connection = self.search_entry.connect("search-changed",
                                                                     self.search_entry_filters_search_changed_cb)
            self.results.set_visible_child_name("results_scrolled_window")
            self.results_number_box.set_visible(True)
            set_text(self.results_number, str(n), str(n))
            if self.filtered_results != results:
                self.filtered_results = results
                self.results_listbox.foreach(self.results_listbox.remove)
                if len(results) > 100:
                    partial_results = results[:100]
                    #rest_of_esults = results[100:]
                    #for r in self.filtered_results[:20]:


                #else:
                partial_results = results
                for URI in partial_results:
                    if re_search("^[QP]([0-9]|[A-Z]|-)+([0-9]|[A-Z])$", URI):
                        download_light(URI, self.on_download_done)
                    else:
                        entity = {"Label":URI,
                                  "Description":"String",
                                  "URI":""}
                        self.on_download_done(URI, entity, "")

    def object_is_empty(self, triplet, object):
        is_var = 'Variable' in object.entity
        has_uri = 'URI' in object.entity and object.entity['URI']
        return any([is_var, has_uri])

    def is_default_variable_set(self, triplet, object):
        if 'Variable' in object.entity and object.entity["Variable"]:
            return object.entity

    def object_is_default_variable(self, triplet, object, entity):
        if 'Variable' in object.entity:
            if object.entity["Label"] == entity["Label"]:
                object.entity["Variable"] = True
                object.entity["Description"] = "selected query variable"
                triplet.set_widget(object, object.entity)
                triplet.set_selected(object, True)
            else:
                object.entity["Variable"] = False
                object.entity["Description"] = "query variable"
                triplet.set_widget(object, object.entity)
                triplet.set_selected(object, False)
        object.popover.search_entry.set_text("")

    def triplets_default_variable_selected_cb(self, triplet, entity):
        print("Open: triplets default variable selected callback")
        self.objects_foreach(self.object_is_default_variable, entity)
        triplet.emit("object-selected", entity)

    @Template.Callback()
    def key_press_event_cb(self, widget, event):
        # if Esc, set placeholder ot [Right Alt, Tab, Esc, Maiusc, Control, Bloc Maiusc, Left Alt]
        if event.keyval == 65307:
            if not self.search_entry.get_text() and not self.new_session:
                self.destroy()
                return None
            self.search_entry.set_text("")

    def on_search_done(self, results, error, query):
        if error:
            self.set_search_placeholder(False)
            self.results.set_visible_child_name("results_no_internet")
            print("connection error")
        else:
            if query == self.search_entry.get_text():
                self.results_listbox.foreach(self.results_listbox.remove)

                if results == []:
                    self.results.set_visible_child_name("results_nope")
                    set_text(self.results_nope_query, query, query)
                else:
                    self.results.set_visible_child_name("results_scrolled_window")
                for r in results:
                    if self.titlebar.get_selection_mode():
                        entity = EntitySelectable(r,
                                              selected=self.entities,
                                              open_button=self.open_button,
                                              select_entities=self.select_entities)
                    else:
                        entity = SidebarEntity(r, button=False)
                    row = ListBoxRow()
                    row.child = entity
                    row.add(entity)
                    self.results_listbox.add(row)
                #row.child()
                self.results_listbox.show_all()
                self.set_search_placeholder(False)


#    @Template.Callback()
    def search_entry_search_changed_cb(self, entry):
        query = entry.get_text()
        print("Label search:", query)
        if query:
            search(entry.get_text(), self.on_search_done, query)
        else:
            self.set_search_placeholder(True)

    def search_entry_filters_search_changed_cb(self, entry):
        query = entry.get_text().lower()
        print("Search entry filter:", query)
        n = 0
        for row in self.results_listbox:
            entity = row.child.entity
            if query in entity['Label'].lower() or query in entity['Description'].lower():
                row.set_visible(True)
                n += 1
            else:
                row.set_visible(False)
        self.results_number_box.set_visible(True)
        set_text(self.results_number, str(n), str(n))

    @Template.Callback()
    def results_listbox_row_activated_cb(self, widget, row):
        if self.titlebar.get_selection_mode():
            toggle = row.child
            toggle.set_active(False) if toggle.get_active() else toggle.set_active(True)
        else:
            self.entities.add(row.child.entity)
            self.emit("new-window-clicked", self.entities)
            self.destroy()

    def set_selection_mode(self, value):
        self.titlebar.set_selection_mode(value)
        self.select.set_visible(not value)
        self.cancel.set_visible(value)
        self.bottom_bar.set_visible(value)
        if value:
            self.header_bar.set_custom_title(self.select_entities)
        else:
            self.header_bar.set_custom_title(None)
        self.results_listbox.foreach(self.set_row_selection, value)

    def set_row_selection(self, row, value):
        entity = row.child.entity
        if value:
            entity = EntitySelectable(entity,
                                      selected=self.entities,
                                      open_button=self.open_button,
                                      select_entities=self.select_entities)
        else:
            entity = SidebarEntity(entity, description=True, button=False)
        row.child.destroy()
        row.add(entity)
        row.child = entity

    @Template.Callback()
    def select_clicked_cb(self, widget):
        if not self.titlebar.get_selection_mode():
            self.set_selection_mode(True)
        else:
            self.set_selection_mode(False)

    @Template.Callback()
    def select_entities_clicked_cb(self, widget):
        self.select_menu.set_visible(True)

    @Template.Callback()
    def select_all_clicked_cb(self, widget):
        self.results_listbox.foreach(self.select_row, True)

    def select_row(self, row, value):
        row.child.set_active(value)

    @Template.Callback()
    def deselect_all_clicked_cb(self, widget):
        self.results_listbox.foreach(self.select_row, False)

    @Template.Callback()
    def window_new_clicked_cb(self, widget):
        self.emit("window-new", "ciao")
        print("open dialog: window new clicked")
예제 #11
0
class SidebarEntity(EventBox):
    __gtype_name__ = "SidebarEntity"

    box = Template.Child("box")
    button = Template.Child("button")
    button1 = Template.Child("button1")
    image_button = Template.Child("image_button")
    image_button1 = Template.Child("image_button1")
    label = Template.Child("label")
    description = Template.Child("description")
    URI = Template.Child("URI")

    def __init__(self,
                 entity,
                 *args,
                 description=True,
                 URI=True,
                 button=True,
                 button1=False):
        """Widget representing an entity in the sidebar

            Args:
                entity (dict): keys are at least "Label", "Description" and "URI";
                description (bool): whether to show description
                URI (bool): whether to show entity URI
        """
        EventBox.__init__(self, *args)

        if button:
            self.button.set_tooltip_text("Close entity")
            context = self.button.get_style_context()
            provider = CssProvider()
            provider.load_from_resource(
                '/ml/prevete/Daty/gtk/sidebarentity.css')
            context.add_provider(provider, STYLE_PROVIDER_PRIORITY_APPLICATION)
            self.enter_connection = self.connect("enter-notify-event",
                                                 self.enter_notify_event_cb)
            self.leave_connection = self.connect("leave-notify-event",
                                                 self.leave_notify_event_cb)
            self.button.connect("leave-notify-event",
                                self.button_leave_notify_event_cb)
        if button1:
            context = self.button1.get_style_context()
            context.add_provider(provider, STYLE_PROVIDER_PRIORITY_APPLICATION)
            self.button1.connect("leave-notify-event",
                                 self.button_leave_notify_event_cb)

        self.entity = entity
        self.enable_button1 = button1

        set_text(self.label, entity["Label"], entity["Label"])

        if description:
            set_text(self.description, entity['Description'],
                     entity['Description'])
        else:
            self.description.destroy()

        if URI:
            set_text(self.URI, entity['URI'], entity['URI'])
        else:
            self.URI.destroy()

    def enter_notify_event_cb(self, widget, event):
        self.button.set_visible(True)
        if self.enable_button1:
            self.button1.set_visible(True)
        self.URI.set_visible(False)

    def leave_notify_event_cb(self, widget, event):
        if event.detail == NotifyType(2):
            self.disconnect(self.enter_connection)
            self.disconnect(self.leave_connection)
        else:
            self.button.set_visible(False)
            if self.enable_button1:
                self.button1.set_visible(False)
            self.URI.set_visible(True)

    def button_leave_notify_event_cb(self, widget, event):
        self.enter_connection = self.connect("enter-notify-event",
                                             self.enter_notify_event_cb)
        self.leave_connection = self.connect("leave-notify-event",
                                             self.leave_notify_event_cb)
예제 #12
0
class EntityPopover(PopoverMenu):

    __gtype_name__ = "EntityPopover"

    __gsignals__ = {'default-variable-selected':(sf.RUN_LAST,
                                                 TYPE_NONE,
                                                 (TYPE_PYOBJECT,)),
                    'entity-new':(sf.RUN_LAST,
                                       TYPE_NONE,
                                       (TYPE_PYOBJECT,)),
                    'new-window-clicked':(sf.RUN_LAST,
                                          TYPE_NONE,
                                          (TYPE_PYOBJECT,)),
                    'object-selected':(sf.RUN_LAST,
                                       TYPE_NONE,
                                       (TYPE_PYOBJECT,)),
                    'variable-deleted':(sf.RUN_LAST,
                                       TYPE_NONE,
                                       (TYPE_PYOBJECT,))}

    label = Template.Child("label")
    description = Template.Child("description")
    entity_grid = Template.Child("entity_grid")
    entity_new = Template.Child("entity_new")
    new_window = Template.Child("new_window")
    results = Template.Child("results")
    results_frame = Template.Child("results_frame")
    results_listbox = Template.Child("results_listbox")
    results_nope_query = Template.Child("results_nope_query")
    results_stack = Template.Child("results_stack")
    search_entry = Template.Child("search_entry")
    search_subtitle = Template.Child("search_subtitle")
    variable_grid = Template.Child("variable_grid")
    variable_record = Template.Child("variable_record")
    variable_title = Template.Child("variable_title")
    variable_subtitle = Template.Child("variable_subtitle")

    def __init__(self, entity=None, variables=None, filters=[], **kwargs):
        PopoverMenu.__init__(self, **kwargs)

        self.filters = filters
        self.variables = variables
        if not entity:
            entity = {"Label":"", "Description":"", "URI":""}
            self.entity_grid.set_visible(False)
        self.entity = entity
        if self.variables != None:
            self.set_modal(True)
            self.search_entry.set_visible(True)
            self.variable_grid.set_visible(True)
            self.entity_grid.set_visible(False)
            subtitle = "Search for entities or\n<i>define new variables</i>"
            set_text(self.search_subtitle, subtitle, subtitle, markup=True)
            self.search_entry.connect("search-changed",
                                      self.search_entry_search_changed_cb)
            self.search_entry.grab_focus()

        if 'url' in entity:
            self.results_frame.set_visible(False)
            self.new_window.set_visible(False)
            self.set_size_request(300,-1)
            self.description.set_line_wrap_mode(WrapMode(2))
            entity['Label'] = "Loading title"
            entity['Description'] = "".join(["<a href='", entity['url'], "'>",
                                             entity['url'], "</a>"])
            get_title(entity['url'], self.on_title_got)

        set_text(self.label, entity["Label"], entity["Label"])
        set_text(self.description, entity["Description"], entity["Description"], markup=True)

    def on_title_got(self, url, title):
        set_text(self.label, title, title)
        self.set_size_request(300,-1)

    def search_entry_search_changed_cb(self, entry):
        query = entry.get_text()
        if query:
            self.results_stack.set_visible_child_name("results_searching")
            search(query, self.on_search_done, query, entry, filters=self.filters)
        else:
            self.variable_grid.set_visible(False)
            if self.variables:
                self.variables_set_results(self.results_listbox)
                self.results_stack.set_visible_child_name("results")
            else:
                self.results_stack.set_visible_child_name("results_placeholder")
                print(self.results_stack.get_visible_child_name())

    def on_search_done(self, results, error, query, entry, *args, **kwargs):
        if query == entry.get_text():
            print("EntityPopover: search", query, 'complete')
            try:
                listbox = self.results_listbox
                listbox.foreach(listbox.remove)
                set_text(self.variable_title, query, query)
                pango_label(self.variable_title, 'bold')
                if self.variables != None:
                    self.variables_set_results(listbox, query=query)
                if self.variables or results:
                    self.results_stack.set_visible_child_name("results")
                else:
                    set_text(self.results_nope_query, query, query)
                    self.entity_new.connect("clicked", self.entity_new_clicked_cb, query)
                    self.results_stack.set_visible_child_name("results_nope")
                for r in results:
                    if r['URI'] != self.entity['URI']:
                        entity = SidebarEntity(r, URI=False, button=True)
                        entity.image_button.set_from_icon_name('focus-windows-symbolic', IconSize.BUTTON)
                        entity.button.connect("clicked", self.new_window_clicked_cb, r)

                        row = ListBoxRow()
                        row.child = entity
                        row.add(entity)
                        listbox.add(row)
                listbox.show_all()
                self.set_search_placeholder(False)
            except Exception as e:
                raise e

    def entity_new_clicked_cb(self, widget, query):
        self.emit("entity-new", query)

    def variables_set_results(self, listbox, query=""):
        listbox.foreach(listbox.remove)
        if hasattr(self.variable_record, 'connection'):
            self.variable_record.disconnect(self.variable_record.connection)
        exact_match = [v for v in self.variables if v["Label"] == query]
        if exact_match:
            label = "Select variable"
            self.variable_record.connection = self.variable_record.connect("clicked",
                                                                           self.object_selected_cb,
                                                                           exact_match[-1])
            selected = any(v["Variable"] for v in exact_match)
            if selected:
                pango_label(self.variable_title, 'ultrabold')
        else:
            label = "Record new variable"
            self.variable_record.connection = self.variable_record.connect("clicked",
                                                                           self.variable_record_clicked_cb)
        set_text(self.variable_subtitle, label, label)

        for v in [v for v in self.variables if v["Label"] and "Variable" in v]:
            if query in v["Label"] and not query == v["Label"]:
                row = ListBoxRow()
                if query:
                    entity = SidebarEntity(v, URI=False)
                else:
                    entity = SidebarEntity(v, URI=False, button1=True)
                    entity.button1.connect("clicked", self.variable_row_set_default_clicked_cb,
                                           v)
                    entity.image_button1.set_from_icon_name('edit-select-symbolic',
                                                            IconSize.BUTTON)
                    entity.button1.set_tooltip_text("Select variable for the query")
                entity.button.connect("clicked", self.delete_variable_clicked_cb,
                                      row, v)
                entity.button.set_tooltip_text("Delete variable")
                row.child = entity
                if v["Variable"]:
                    pango_label(entity.label, 'ultrabold')
                    entity.label.props.attributes = None
                row.add(entity)
                listbox.add(row)
                listbox.show_all()

    def delete_variable_clicked_cb(self, widget, row, entity):
        print("Delete variable callback", entity)
        row.destroy()
        self.variables.remove(entity)
        self.emit("variable-deleted", entity)
        if not self.variables:
            self.hide()

    def set_search_placeholder(self, value):
        try:
            if self.variables != None:
                self.variable_grid.set_visible(not value)
            self.results.set_visible(not value)
        except AttributeError as e:
            raise e

    @Template.Callback()
    def new_window_clicked_cb(self, widget, *cb_args):
        if cb_args:
            payload = list(cb_args)
        else:
            payload = [self.entity]
        self.emit("new-window-clicked", payload)

    def is_variable(self, entity):
        if 'Variable' in entity: return True

    def is_default_variable(self, entity):
        if self.is_variable(entity) and entity["Variable"]:
            return True

    @Template.Callback()
    def variable_set_default_clicked_cb(self, widget):
        if not self.is_default_variable(self.entity):
            self.entity["Variable"] = True
            label = self.search_entry.get_text()
            self.entity["Label"] = label
            self.entity["URI"] = ""
            self.variables.add(self.entity)
            self.entity["Description"] = "selected query variable"
            pango_label(self.variable_title, weight='ultrabold')
            set_text(self.variable_subtitle,
                     self.entity["Description"],
                     self.entity["Description"])
            print("EntityPopover: variable_set_default_clicked_cb")
            self.emit("default-variable-selected", self.entity)
        self.hide()

    def variable_row_set_default_clicked_cb(self, widget, entity):
        entity["Variable"] = True
        self.object_selected_cb(widget, entity)
        self.hide()

    def variable_record_clicked_cb(self, widget):
        print("Variable record button: clicked")
        print("Variable record callback: I am setting the popover entity to the query",
        self.search_entry.get_text())
        self.entity["Variable"] = False
        self.entity["URI"] = ""
        self.entity["Label"] = self.search_entry.get_text()
        pango_label(self.variable_title, weight='bold')
        self.variables.add(self.entity)
        self.entity["Description"] = "query variable"
        self.emit("object-selected", self.entity)
        self.hide()

    def object_selected_cb(self, widget, entity):
        print("Object selected callback with argument", entity)
        for field in entity:
            self.entity[field] = entity[field]
        if entity["URI"] and self.is_variable(self.entity):
            del self.entity["Variable"]
        if self.is_default_variable(self.entity):
            print("The entity is default, emitting default variable selected signal")
            self.emit("default-variable-selected", self.entity)
        else:
            self.emit("object-selected", self.entity)
        self.hide()

    @Template.Callback()
    def results_listbox_row_activated_cb(self, listbox, row):
        sidebar_entity = row.child
        entity = sidebar_entity.entity
        self.object_selected_cb(sidebar_entity, entity)
        self.hide()
예제 #13
0
class Entity(Stack):

    __gtype_name__ = "Entity"

    __gsignals__ = {
        'entity-editing': (sf.RUN_LAST, TYPE_NONE, (TYPE_PYOBJECT, )),
        'entity-leaving': (sf.RUN_LAST, TYPE_NONE, (TYPE_PYOBJECT, )),
        'new-window-clicked': (sf.RUN_LAST, TYPE_NONE, (TYPE_PYOBJECT, )),
        'object-selected': (sf.RUN_LAST, TYPE_NONE, (TYPE_PYOBJECT, ))
    }

    entry = Template.Child("entry")
    label = Template.Child("label")
    value_eventbox = Template.Child("value_eventbox")
    unit = Template.Child("unit")

    #TODO:implement editing

    def __init__(self,
                 snak=None,
                 new=False,
                 qualifier=False,
                 css=None,
                 **kwargs):
        Stack.__init__(self, **kwargs)

        context = self.entry.get_style_context()
        provider = CssProvider()
        provider.load_from_resource('/ml/prevete/Daty/gtk/entity.css')
        context.add_provider(provider, STYLE_PROVIDER_PRIORITY_APPLICATION)

        if qualifier:
            self.label.props.valign = 1
            self.unit.props.valign = 1

        self.new = new
        if self.new:
            print("new entity")
            item_new = lambda Q: {
                'snaktype': 'value',
                'datavalue': {
                    'type': 'wikibase-entityid',
                    'value': {
                        'entity-type': 'item',
                        'numeric-id': Q
                    }
                },
                'datatype': 'wikibase-item'
            }
            snak = item_new(352346)

        try:
            self.read(snak)
        except Exception as err:
            raise err

        self.entry_focus_out_connection = self.entry.connect(
            "focus-out-event", self.entry_focus_out_event_cb)
        self.entry_focus_in_connection = self.entry.connect(
            "focus-in-event", self.entry_focus_in_event_cb)

        #self.entry.connect("search-changed", self.entry_search_changed_cb)

    def read(self, snak):
        if snak['snaktype'] == 'novalue':
            self.label.set_text("No value")
        if snak['snaktype'] == 'value':
            dv = snak['datavalue']
            dt = snak['datatype']
            if dt == 'wikibase-item' or dt == 'wikibase-property':
                if dv['type'] == 'wikibase-entityid':
                    entity_type = dv['value']['entity-type']
                    numeric_id = dv['value']['numeric-id']
                    if entity_type == 'item':
                        URI = 'Q' + str(numeric_id)
                    if entity_type == 'property':
                        URI = 'P' + str(numeric_id)
                    print("Entity: light downloading", URI)
                    download_light(URI, self.load_entity)
            if dt == 'url':
                url = dv['value']
                #label = "".join(["<a href='", url, "'>", url.split('/')[2], '</a>'])
                label = url.split('/')[2]
                self.data = {"url": url}
                self.set_text(label, url)
                context = self.label.get_style_context()
                set_style(context, '/ml/prevete/Daty/gtk/entity.css', 'url',
                          True)
            #self.label.props.use_markup = True
            if dt == 'quantity':
                unit = dv['value']['unit']
                if unit.startswith('http'):
                    unit = dv['value']['unit'].split('/')[-1]
                    download_light(unit, self.on_download_unit)

                amount = dv['value']['amount']
                ub = dv['value']['upperBound']
                lb = dv['value']['lowerBound']
                if float(amount) > 0:
                    amount = str(round(float(amount)))
                if ub and lb:
                    amount = amount + " ± " + str(
                        round(float(ub) - float(amount)))
                if ub and not lb:
                    amount = amount + " + " + str(
                        round(float(ub) - float(amount)))
                if not ub and lb:
                    amount = amount + " - " + str(
                        round(float(amount) - float(lb)))
                self.label.set_text(amount)
            if dt == 'string':
                self.set_text(dv['value'], "Text")
            if dt == 'monolingualtext':
                #TODO: better implement monolingual text
                self.set_text(dv['value']['text'], dv['value']['language'])
            if dt == 'commonsMedia':
                self.set_text(dv['value'], "Picture")
            if dt == 'external-id':
                self.set_text(dv['value'], "External ID")
            if dt == 'geo-shape':
                #TODO: implement geo-shape
                #print('geo-shape')
                pass
            if dt == 'globe-coordinate':
                #TODO: implement globe-coordinate
                #print('globe-coordinate')
                pass
            if dt == 'tabular-data':
                #TODO: implement tabular-data
                #print('tabular-data')
                pass
            if dt == 'time':
                #TODO: implement time point
                #print('time')
                pass
        del snak

    def set_text(self, label, description):
        set_text(self.label, label, description)
        set_text(self.entry, label, description)

    def on_download_unit(self, URI, unit, error):
        if error:
            print(error)
            print(type(error))
        if unit:
            self.unit.set_text(unit["Label"])
            self.unit.set_visible(True)
            del unit
            return None

    def load_entity(self, URI, entity, error):
        if error:
            print(type(error))
            print(error)
        self.data = entity
        self.URI = URI
        self.set_text(entity["Label"], entity["Description"])
        self.show_all()

        if self.new:
            self.set_visible_child_name('entry')
            self.entry.grab_focus()

        return None

    @Template.Callback()
    def button_press_event_cb(self, widget, event):
        if event.type == EventType._2BUTTON_PRESS:
            print("double click")
        elif event.type == EventType.BUTTON_PRESS:
            self.entry.set_visible(True)
            self.set_visible_child_name("entry")
            self.entry.grab_focus()

    @Template.Callback()
    def entry_changed_cb(self, entry):
        if not self.entry.props.secondary_icon_name == "user-trash-symbolic":
            self.entry.props.secondary_icon_tooltip_text = ""

    @Template.Callback()
    def entry_icon_press_cb(self, entry, icon_pos, event):
        if entry.props.secondary_icon_name == "user-trash-symbolic":
            print("this statement will be destroyed")

#    @Template.Callback()

    def entry_focus_in_event_cb(self, entry, event):
        self.entry.props.secondary_icon_name = "user-trash-symbolic"
        entry.props.margin_top = 3
        entry.props.margin_bottom = 3
        label = self.label.get_label()
        description = self.label.get_tooltip_text()
        if not hasattr(self, 'popover'):
            try:
                from .entitypopover import EntityPopover
                self.popover = EntityPopover(self.data)
                self.popover.set_relative_to(self)
                self.popover.set_position(PositionType(3))
                self.entry.connect("search-changed",
                                   self.popover.search_entry_search_changed_cb)
                self.popover.connect("new-window-clicked",
                                     self.new_window_clicked_cb)
                self.popover.connect("object-selected",
                                     self.object_selected_cb)
                self.entry.emit("search-changed")
                self.popover.set_visible(True)
                self.emit("entity-editing", self.popover)
            except AttributeError as e:
                raise e
                print("Exception", e)
                print("no popover available for this type of value")
        else:
            self.entry.emit("search-changed")
            self.popover.popup()
            self.emit("entity-editing", self.popover)

    def object_selected_cb(self, popover, entity):
        print("Editor: object selected:", entity['URI'])
        self.load_entity(entity['URI'], entity, None)
        self.emit("object-selected", entity)

    def new_window_clicked_cb(self, popover, entities):
        print("Entity: new window clicked")
        self.emit("new-window-clicked", entities)

#    @Template.Callback()

    def entry_focus_out_event_cb(self, widget, event):
        self.set_visible_child_name("view")
        self.entry.set_text(self.label.get_text())
        self.entry.set_visible(False)
        self.entry.props.margin_top = 0
        self.entry.props.margin_bottom = 0
        try:
            self.popover.popdown()
        except AttributeError as e:
            print(self.label.get_text())
            print(e)
            print("this entity has no popover")
        self.emit("entity-leaving", self)
        return True

    @Template.Callback()
    def entry_key_release_event_cb(self, widget, event):
        #pass
        try:
            if event.keyval == KEY_Escape:
                self.entry_focus_out_event_cb(widget, event)
        except AttributeError as e:
            print("no entity popover for this value")
예제 #14
0
class Triplet(Grid):
    __gtype_name__ = "Triplet"
    __gsignals__ = {'triplet-ready':(sf.RUN_LAST,
                                     TYPE_NONE,
                                     (TYPE_BOOLEAN,)),
                    'default-variable-selected':(sf.RUN_LAST,
                                                 TYPE_NONE,
                                                 (TYPE_PYOBJECT,)),
                    'entity-new':(sf.RUN_LAST,
                                  TYPE_NONE,
                                  (TYPE_PYOBJECT,)),
                    'new-window-clicked':(sf.RUN_LAST,
                                          TYPE_NONE,
                                          (TYPE_PYOBJECT,)),
                    'object-selected':(sf.RUN_LAST,
                                       TYPE_NONE,
                                       (TYPE_PYOBJECT,)),
                    'variable-deleted':(sf.RUN_LAST,
                                       TYPE_NONE,
                                       (TYPE_PYOBJECT,))}

    subject = Template.Child("subject")
    subject_title = Template.Child("subject_title")
    subject_description = Template.Child("subject_description")
    property = Template.Child("property")
    property_title = Template.Child("property_title")
    property_description = Template.Child("property_description")
    object = Template.Child("object")
    object_title = Template.Child("object_title")
    object_description = Template.Child("object_description")

    def __init__(self, variables=None, *args, **kwargs):
        Grid.__init__(self, *args, **kwargs)

        self.variables = variables
        self.subject.title = self.subject_title
        self.subject.description = self.subject_description
        self.property.title = self.property_title
        self.property.description = self.property_description
        self.object.title = self.object_title
        self.object.description = self.object_description

        self.members = (self.subject, self.property, self.object)

        for widget in self.members:
            widget.entity = {"Label":"", "Description":"", "URI":""}
            widget.popover = EntityPopover(widget.entity,
                                                  variables=self.variables)
            widget.popover.set_relative_to(widget)
            widget.popover.connect("default-variable-selected",
                                          self.default_variable_selected_cb)
            widget.popover.connect("entity-new",
                                          self.entity_new_clicked_cb)
            widget.popover.connect("new-window-clicked",
                                          self.new_window_clicked_cb)
            widget.popover.connect("object-selected",
                                          self.object_selected_cb)
            widget.popover.connect("variable-deleted",
                                          self.variable_deleted_cb)

        self.property.popover.search_entry.set_text("property:")

        self.show_all()

    def entity_new_clicked_cb(self, popover, query):
        #print(query)
        self.emit("entity-new", query)

    def new_window_clicked_cb(self, popover, entities):
        self.emit("new-window-clicked", entities)

    def variable_deleted_cb(self, popover, entity):
        self.emit("variable-deleted", entity)

    def set_widget(self, widget, entity):
        set_text(widget.title, entity["Label"], entity["Label"])
        pango_label(widget.title, 'bold')
        set_text(widget.description, entity["Description"], entity["Description"])
        self.show_all()

    def set_selected(self, widget, value):
        if value:
            pango_label(widget.title, 'ultrabold')
        else:
            pango_label(widget.title, 'bold')

    @Template.Callback()
    def widget_clicked_cb(self, widget):
        widget.popover.set_visible(True)

    def popover_closed_cb(self, popover):
        self.emit('triplet-ready', True)

    def default_variable_selected_cb(self, popover, entity):
        widget = self.object_selected_cb(popover, entity, emit=False)
        pango_label(widget.title, 'ultrabold')
        self.emit('default-variable-selected', widget.entity)

    def object_selected_cb(self, popover, entity, emit=True):
        widget = popover.get_relative_to()
        self.set_widget(widget, entity)
        if emit:
            self.emit("object-selected", entity)
        return widget
예제 #15
0
class UserSetup(Assistant):
    __gtype_name__ = "UserSetup"

    credentials = Template.Child("credentials")
    username = Template.Child("username")
    username_label = Template.Child("username_label")
    bot_username = Template.Child("bot_username")
    bot_username_label = Template.Child("bot_username_label")
    bot_password = Template.Child("bot_password")
    bot_password_label = Template.Child("bot_password_label")
    username_label2 = Template.Child("username_label2")
    bot_username_label2 = Template.Child("bot_username_label2")

    def __init__(self, config, *args, **kwargs):
        Assistant.__init__(self)

        icon = lambda x: IconTheme.get_default().load_icon((name), x, 0)
        icons = [icon(size) for size in [32, 48, 64, 96]];
        self.set_icon_list(icons);

        self.config = config
        self.credentials.set_header_func(self.update_header)

        elements = [("user", self.username_label, self.username),
                    ("bot_user", self.bot_username_label, self.bot_username),
                    ("bot_password", self.bot_password_label, self.bot_password)]

        for key, label, entry in elements:
            row = ListBoxRow()
            grid = Grid()
            grid.props.column_homogeneous = True
            label.props.halign = Align(1)
            grid.attach(label, 0, 0, 1, 1)
            grid.attach(entry, 1, 0, 2, 1)
            row.add(grid)
            self.credentials.add(row)
        self.credentials.show_all()

        lc, encoding = getdefaultlocale()
        if (lc):
            language = lc.split("_")[0]
        else:
            language = environ.get("LANGUAGE", None)
            if language:
                language = language.split(":")[0]
        self.config.data['languages'] = [language]

        self.connect('destroy', main_quit)
        self.show_all()

    def update_header(self, row, before, *args):
        """See GTK+ Documentation"""
        if before:
            row.set_header(Separator())

    def do_cancel(self):
        self.destroy()

    def do_apply(self):
        self.config.create_pywikibot_config(self.username.props.text,
                                       self.bot_username.props.text,
                                       self.bot_password.props.text)

    def do_close(self):
        self.destroy()

    @Template.Callback()
    def credentials_help_clicked_cb(self, widget):
        if system() == 'Linux':
            show_uri (None, "help:daty/daty-credentials", CURRENT_TIME)
        if system() == 'Windows':
            from webbrowser import open
            open('http://daty.prevete.ml/daty-credentials.html')

    @Template.Callback()
    def on_field_changed(self, widget):
        if (  self.username.props.text and
              self.bot_username.props.text and
              self.bot_password.props.text ):

            self.username_label2.props.label = self.username.props.text
            self.bot_username_label2.props.label = self.bot_username.props.text
            page = self.get_nth_page(self.get_current_page())
            self.set_page_complete(page, True)

    @Template.Callback()
    def on_field_activate(self, widget):
        page = self.get_nth_page(self.get_current_page())
        if self.get_page_complete(page):
            self.do_apply()
            self.next_page()
예제 #16
0
class Value(Grid):

    __gtype_name__ = "Value"

    __gsignals__ = {
        'entity-editing':
        (sf.RUN_LAST, TYPE_NONE, (TYPE_PYOBJECT, TYPE_PYOBJECT)),
        'entity-leaving': (sf.RUN_LAST, TYPE_NONE, (TYPE_PYOBJECT, )),
        'edit_new': (sf.RUN_LAST, TYPE_NONE, (TYPE_PYOBJECT, )),
        'claim-changed':
        (sf.RUN_LAST, TYPE_NONE, (TYPE_PYOBJECT, TYPE_PYOBJECT)),
        'new-window-clicked': (sf.RUN_LAST, TYPE_NONE, (TYPE_PYOBJECT, )),
        'reference-new-clicked': (sf.RUN_LAST, TYPE_NONE, (TYPE_PYOBJECT, )),
        'references-toggled': (sf.RUN_LAST, TYPE_NONE, (TYPE_PYOBJECT, ))
    }

    button = Template.Child("button")
    actions = Template.Child("actions")
    icon = Template.Child("icon")
    #qualifier_new = Template.Child("qualifier_new")
    qualifiers = Template.Child("qualifiers")
    mainsnak = Template.Child("mainsnak")
    qualifier_new = Template.Child("qualifier_new")
    reference_new = Template.Child("reference_new")

    def __init__(self, claim, *args, new=False, **kwargs):
        Grid.__init__(self, *args, **kwargs)

        self.qualifier_new.modify_font(FontDescription('Cantarell 8'))
        self.reference_new.modify_font(FontDescription('Cantarell 8'))
        self.qualifier_pos = {}

        self.qualifier_row = 0
        self.reference_row = 0
        self.references_expanded = False

        if new:
            snak = None
        else:
            snak = claim['mainsnak']

        self.entity = Entity(snak=snak, new=new)
        self.entity.connect("entity-editing", self.entity_editing_cb)
        self.entity.connect("entity-leaving", self.entity_leaving_cb)
        self.entity.connect("object-selected", self.object_selected_cb, claim)
        self.entity.connect('new-window-clicked', self.new_window_clicked_cb)
        self.mainsnak.add(self.entity)

        self.hide_actions = True

        if 'qualifiers' in claim:
            self.props.row_spacing = 3
            self.qualifiers.set_visible(True)
            claims = claim['qualifiers']

            for i, P in enumerate(claims):
                download_light(P, self.load_qualifier, i, claims[P])

        self.actions_hide = False

        if 'references' in claim:
            self.references = claim['references']
            self.button_connection = self.button.connect(
                "button-press-event", self.references_expand_clicked_cb)
        else:
            self.icon.set_from_icon_name('list-add-symbolic', IconSize.BUTTON)
            #self.button_connection = self.button.connect("button-press-event", self.reference_new_clicked_cb)

        self.button_press_connection = self.connect("button-press-event",
                                                    self.clicked_cb)

        del claim

    @Template.Callback()
    def object_new_focus_in_event_cb(self, object, event):
        if not object.get_name() == 'qualifier_new':
            object.props.secondary_icon_name = "user-trash-symbolic"
            object.props.secondary_icon_activatable = True
            N = self.get_grid_rows(self.qualifiers)
            #object.connect("icon-press", self.object_new_icon_press_cb, position)
        context = object.get_style_context()
        resource = '/ml/prevete/Daty/gtk/entity.css'
        set_style(context, resource, 'search_entry', True)
        object.popover = EntityPopover(filters=['property'])
        object.popover.set_relative_to(object)
        object.popover.set_position(PositionType(3))
        object.connect("search-changed",
                       object.popover.search_entry_search_changed_cb)
        object.popover.connect("new-window-clicked",
                               self.new_window_clicked_cb)
        object.popover.connect("object-selected", self.object_new_selected_cb)
        object.popover.popup()
        #self.emit("entity-editing", self.entity, object.popover)

    def get_grid_rows(self, grid):
        rows = 0
        for child in grid.get_children():
            y = grid.child_get_property(child, 'top-attach')
            height = grid.child_get_property(child, 'height')
            rows = max(rows, y + height)
        return rows

    def object_new_icon_press_cb(self, entry, icon_pos, event, position):
        if entry.props.secondary_icon_name == "user-trash-symbolic":
            if position == PositionType(1):
                prop = self.qualifiers.get_child_at(0, row)
                prop.destroy()
            entry.destroy()
            get

    def qualifier_new_check(self, property):
        for child in self.qualifiers.get_children():
            if type(child) == QualifierProperty:
                if child.URI == property['URI']:
                    N = self.qualifiers.child_get_property(child, 'height')
                    child = self.qualifiers.get_child_at(1, N)
                    prop = self.qualifiers.get_child_at(0, N)
                    self.qualifiers.insert_next_to(child, PositionType(2))
                    self.qualifiers.remove(prop)
                    self.qualifiers.attach(prop, 0, N, 1, 1)
                    return N, child, PositionType(2)
        return None, None, None

    def object_new_selected_cb(self, popover, property):
        parent = popover.get_relative_to()
        parent.set_text("")
        self.actions.set_visible(False)
        self.button.set_visible(True)
        if parent.get_name() == "qualifier_new":
            if property['URI'] in self.qualifier_pos:
                pos = self.qualifier_pos[property['URI']]
                N = pos['start'] + pos['end']
                child = self.qualifiers.get_child_at(1, N)
                position = PositionType(3)
                self.qualifiers.insert_next_to(child, PositionType(3))
                pos['end'] += 1
                for uri in self.qualifier_pos:
                    q_pos = self.qualifier_pos[uri]
                    if q_pos['start'] > pos['start']:
                        q_pos['start'] += 1
            else:
                qualifier = QualifierProperty(property)
                N = self.get_grid_rows(self.qualifiers)
                self.qualifiers.attach(qualifier, 0, N, 1, 1)
                child = qualifier
                position = PositionType(1)

            qualifier_value = SearchEntry()
            context = qualifier_value.get_style_context()
            resource = '/ml/prevete/Daty/gtk/entity.css'
            set_style(context, resource, 'flat', True)
            qualifier_value.props.secondary_icon_activatable = True
            qualifier_value.set_visible(True)
            qualifier_value.set_name("qualifier_new_value")
            qualifier_value.set_placeholder_text("Search to add the value")
            qualifier_value.connect("icon-press",
                                    self.object_new_icon_press_cb, position)
            qualifier_value.connect("focus-in-event",
                                    self.object_new_focus_in_event_cb)
            qualifier_value.connect("focus-out-event",
                                    self.object_new_focus_out_event_cb)
            self.qualifiers.attach_next_to(qualifier_value, child, position, 2,
                                           1)

            qualifier_value.grab_focus()
        if parent.get_name() == "qualifier_new_value":
            print("hi, I am a new qualifier value")

    @Template.Callback()
    def object_new_focus_out_event_cb(self, object, event):
        context = object.get_style_context()
        resource = '/ml/prevete/Daty/gtk/entity.css'
        set_style(context, resource, 'search_entry', False)
        #object.set_text("")
        if not object.get_name() == 'qualifier_new':
            object.props.secondary_icon_name = "user-trash-symbolic"
            object.props.secondary_icon_activatable = True
            N = self.get_grid_rows(self.qualifiers)
            #object.connect("icon-press", self.object_new_icon_press_cb)
        object.popover.popdown()

    def entity_leaving_cb(self, entity, popover):
        print("Value: entity leaving")
        self.emit("entity-leaving", entity)
        return True

    def new_window_clicked_cb(self, entity, payload):
        print("Value: new window clicked")
        self.emit("new-window-clicked", payload)

    def clicked_cb(self, widget, event):
        print(event.button)
        if hasattr(self, 'references'):
            if event.button == 1:  #EventType(4) single click
                self.references_expand_clicked_cb(widget, event)
            if event.button == 3:
                self.reference_new_clicked_cb(widget, event)
        else:
            self.reference_new_clicked_cb(widget, event)

    def reference_new_clicked_cb(self, widget, event):
        if not self.actions_hide:
            self.emit("reference-new-clicked", self.entity)
            print("Value: 'reference-new' emitted")
            if self.icon.get_icon_name()[0] == "list-add-symbolic":
                self.button.set_visible(False)
        else:
            print("Value: hiding actions")
            self.actions.set_visible(False)
            if self.icon.get_icon_name()[0] == "list-add-symbolic":
                self.button.set_visible(True)

    def references_expand_clicked_cb(self, widget, event):
        self.references_expanded = not self.references_expanded
        state = self.references_expanded
        if state:
            icon_name = 'pan-down-symbolic'
        else:
            icon_name = 'pan-end-symbolic'
        self.icon.set_from_icon_name(icon_name, IconSize.BUTTON)
        self.emit('references-toggled', self)

    def init_references(self):
        self.references_widgets = []
        for j, ref in enumerate(self.references):
            widget = Reference()
            self.references_widgets.append(widget)
            for i, P in enumerate(ref['snaks-order']):
                download_light(P, self.load_reference, i, widget,
                               ref['snaks'][P])
        #self.references_widgets.append(Reference(new=True))

    def load_reference(self, URI, property, error, i, widget, refs):
        try:
            print(property["Label"], i)
            property = QualifierProperty(property)
            widget.grid.attach(property, 0, i + self.reference_row, 1, 1)
            for j, ref in enumerate(refs):
                self.load_async(self.on_value_complete, URI, ref, widget.grid,
                                i + self.reference_row + j)
            self.reference_row += len(refs) - 1
        except Exception as e:
            print(URI)
            raise e

    def load_qualifier(self, URI, qualifier, error, i, claims):
        try:
            qualifier = QualifierProperty(qualifier)
            self.qualifier_pos[URI] = {"start": i + self.qualifier_row}
            self.qualifiers.attach(qualifier, 0,
                                   self.qualifier_pos[URI]['start'], 1, 1)

            for j, claim in enumerate(claims):
                self.load_async(self.on_value_complete, URI, claim,
                                self.qualifiers,
                                self.qualifier_pos[URI]['start'] + j)
            self.qualifier_pos[URI]['end'] = len(claims) - 1
            self.qualifier_row += self.qualifier_pos[URI]['end']
            return None
        except Exception as e:
            print(URI)
            raise e

    def on_value_complete(self, URI, snak, grid, row):
        value = Entity(snak, qualifier=True)
        value.connect("entity-editing", self.entity_editing_cb)
        value.entry.connect("focus-out-event", self.entity_leaving_cb)
        value.connect("object-selected", self.object_selected_cb, snak)
        value.connect('new-window-clicked', self.new_window_clicked_cb)
        self.set_font_deprecated(value)
        grid.attach(value, 1, row, 2, 1)
        grid.set_size_request(-1, 100)
        grid.set_size_request(-1, -1)
        return None

    def entity_editing_cb(self, entity, popover):
        print("Value: entity editing")
        #self.actions_hide = False
        #self.reference_new_clicked_cb(entity, popover)
        self.emit("entity-editing", entity, popover)

    def load_async(self, callback, *cb_args):  #URI, claim, j):
        def do_call():
            error = None
            try:
                pass
            except Exception as err:
                print(URI)
                raise err
            idle_add(lambda: callback(*cb_args))  #claim, j))

        thread = MyThread(target=do_call)
        thread.start()

    def object_selected_cb(self, entity, target, claim):
        print("Value: object selected")
        print("Value: entity", entity.data['Label'])
        provider = CssProvider()
        provider.load_from_resource('/ml/prevete/Daty/gtk/value.css')
        self.context.add_provider(provider,
                                  STYLE_PROVIDER_PRIORITY_APPLICATION)
        self.context.add_class('loading')
        self.emit("claim-changed", claim, target)

    def set_font_deprecated(self, editor_widget):
        pango_context = editor_widget.create_pango_context()
        font_description = pango_context.get_font_description()
        increase = 8  #pt 14
        font_size = 1024 * increase
        font_description.set_size(font_size)
        editor_widget.override_font(font_description)

    def set_references(self):
        if not hasattr(self, 'references'):
            provider = CssProvider()
            provider.load_from_resource('/ml/prevete/Daty/gtk/value.css')
            self.context.add_provider(provider,
                                      STYLE_PROVIDER_PRIORITY_APPLICATION)
            self.context.add_class('unreferenced')
        else:
            self.context.remove_class('unreferenced')

    def set_expanded(self):
        if self.references_expanded:
            provider = CssProvider()
            provider.load_from_resource('/ml/prevete/Daty/gtk/value.css')
            self.context.add_provider(provider,
                                      STYLE_PROVIDER_PRIORITY_APPLICATION)
            self.context.add_class('expanded')
        else:
            self.context.remove_class('expanded')
예제 #17
0
class EntitySelectable(CheckButton):
    __gtype_name__ = "EntitySelectable"

    widget = Template.Child("widget")
    label = Template.Child("label")
    description = Template.Child("description")
    URI = Template.Child("URI")

    def __init__(self,
                 entity,
                 *args,
                 widget=True,
                 selected=None,
                 open_button=None,
                 select_entities=None):
        """Search result widget in 'open new entity' dialog

            Args:
                entity (dict): havig keys "URI, "Label", "Description" and "Data".
                selected (list): keep track of entity's selected status
        """
        CheckButton.__init__(self, *args)

        self.entity = entity

        if widget:
            self.label.set_text(entity['Label'])
            self.description.set_text(entity['Description'])
            self.URI.set_text(entity['URI'])
        else:
            self.label.destroy()
            self.description.destroy()
            self.URI.destroy()

        #TODO: implement selected as signal in cointaining listbox
        if selected != None:
            if entity["URI"] in (v["URI"] for v in selected):
                self.set_active(True)
            args = [self.toggled_cb, selected]
            if open_button: args = args + [open_button]
            if select_entities: args = args + [select_entities]
            self.connect("toggled", *args)
        self.show_all()

    def toggled_cb(self, widget, selected, *args):
        """Toggled callback

            Args:
                widget (Gtk.Widget): toggled widget (so self);
                selected (list): add self's entity attribute to it to 
                keep track of parent listbox selected toggles.
        """
        if widget.get_active():
            selected.add(self.entity)
            try:
                args[0].set_sensitive(True)
                args[1].set_label(" ".join(
                    ["Selected", str(len(selected)), "entities"]))
            except Exception as e:
                raise e
                #pass
        else:
            selected.remove(self.entity)
            try:
                if not selected:
                    args[0].set_sensitive(False)
                    args[1].set_label("Click on entities to select them")
                else:
                    args[1].set_label(" ".join(
                        ["Selected",
                         str(len(selected)), "entities"]))
            except:
                pass
예제 #18
0
class Preferences(Window):
    __gtype_name__ = "Preferences"

    config = Config()
    credentials = Template.Child("credentials")
    languages = Template.Child("languages")

    #values = Template.Child("values")

    def __init__(self, *args, **kwargs):
        Window.__init__(self, *args, **kwargs)

        icon = lambda x: IconTheme.get_default().load_icon((name), x, 0)
        icons = [icon(size) for size in [32, 48, 64, 96]]
        self.set_icon_list(icons)

        self.credentials.set_header_func(self.update_header)
        self.languages.set_header_func(self.update_header)

        for key in self.config.data['credentials']:
            row = ListBoxRow()
            grid = Grid()
            grid.props.column_homogeneous = True
            label = Label()
            label.set_text(key)
            label.props.halign = Align(1)
            context = label.get_style_context()
            resource = "/ml/prevete/Daty/gtk/value.css"
            set_style(context, resource, "dim-label", True)
            entry = Entry()
            entry.set_text(self.config.data['credentials'][key])
            context = entry.get_style_context()
            set_style(context, resource, "flat", True)
            grid.attach(label, 0, 0, 1, 1)
            grid.attach(entry, 1, 0, 2, 1)
            row.add(grid)
            self.credentials.add(row)
        self.credentials.show_all()

        query = """SELECT ?item ?itemLabel ?c
{
  ?item wdt:P424 ?c .
  MINUS{?item wdt:P31/wdt:P279* wd:Q14827288} #exclude Wikimedia projects
  MINUS{?item wdt:P31/wdt:P279* wd:Q17442446} #exclude Wikimedia internal stuff
  SERVICE wikibase:label { bd:serviceParam wikibase:language "your_first_language". }
}
        """

        query = sub("your_first_language", self.config.data['languages'][0],
                    query)
        self.retrieve(query, self.languages_callback)

    @Template.Callback()
    def language_new_clicked_cb(self, widget):
        language_add = LanguageAdd(self.language_results)
        print(language_add)
        language_add.show_all()

    def languages_callback(self, results):
        languages = self.config.data['languages']
        self.language_results = results['results']['bindings']
        for lang in languages:
            for r in self.language_results:
                if r['c']['value'] == lang:
                    row = ListBoxRow()
                    label = Label()
                    label.set_text(r['itemLabel']['value'])
                    label.props.halign = Align(1)
                    row.add(label)
                    self.languages.add(row)
        self.languages.show_all()

    def retrieve(self, query, callback, *cb_args, **kwargs):
        """Asynchronously download entity from wikidata
             Args:
                entity (dict): have keys "URI", "Label", "Description"
        """
        def do_call():
            from pywikibot.data.sparql import SparqlQuery
            sparql = SparqlQuery()
            results = sparql.query(query)
            idle_add(lambda: callback(results, *cb_args, **kwargs))
            return None

        thread = Thread(target=do_call)
        thread.start()

    def update_header(self, row, before, *args):
        """See GTK+ Documentation"""
        if before:
            row.set_header(Separator())