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)
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())
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)
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
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()
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)
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()
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)
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)
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")
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)
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()
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")
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
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()
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')
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
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())