Skip to content
query_view.py 10.1 KiB
Newer Older
Franziska Koehn's avatar
Franziska Koehn committed
import gtk

Franziska Koehn's avatar
Franziska Koehn committed
class QueryView(gtk.VBox):

    @property
    def credentials(self):
        return "%s:%s" % (self.entry_user.get_text(), self.entry_passw.get_text())

    @credentials.setter
    def credentials(self, new_creds):
        user, _, password = new_creds.partition(":")
        self.entry_user.set_text(user)
        self.entry_passw.set_text(password)

    @property
    def host(self):
        return self.entry_host.get_text()

    @host.setter
    def host(self, new_host):
        self.entry_host.set_text(new_host)

    def __send_query(self):
        self.emit("send-query", self.host, self.credentials, self.treeView_search.get_query())

    def __init__(self, *args, **kwargs):
        super(QueryView, self).__init__(*args, **kwargs)

        import gobject
        gobject.signal_new("send-query", QueryView, gobject.SIGNAL_RUN_FIRST,
        gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT))

        # query-tree
        sw_search = gtk.ScrolledWindow()
        sw_search.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        sw_search.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self.pack_start(sw_search, True, True, 0)

        self.treeView_search = TreeViewQuery()
        sw_search.add(self.treeView_search)

        # login fields
        hBox_cedentials = gtk.HBox(False,5)
        self.pack_start(hBox_cedentials, expand=False, fill=False)

        label_user =  gtk.Label()
        label_user.set_text("User:")
        hBox_cedentials.pack_start(label_user, expand=False, fill=False)
        self.entry_user = gtk.Entry()
        hBox_cedentials.pack_start(self.entry_user, expand=True, fill=True)

        label_passw =  gtk.Label()
        label_passw.set_text("Password:")
        hBox_cedentials.pack_start(label_passw, expand=False, fill=False)
        self.entry_passw = gtk.Entry()
        self.entry_passw.set_visibility(False)
        hBox_cedentials.pack_start(self.entry_passw, expand=True, fill=True)

        # host-text-field and send-query-button
        hBox_send = gtk.HBox(False,5)
        self.pack_start(hBox_send, expand=False, fill=False)

        label_host =  gtk.Label()
        label_host.set_text("Host:")
        hBox_send.pack_start(label_host, expand=False, fill=False)

        self.entry_host = gtk.Entry()
        hBox_send.pack_start(self.entry_host, expand=True, fill=True)

        self.button_send = gtk.Button(label="Send Query")
        self.button_send.connect("clicked", lambda *_: self.__send_query())
        hBox_send.pack_end(self.button_send, expand=False, fill=False)


class TreeViewQuery(gtk.TreeView):
Franziska Koehn's avatar
Franziska Koehn committed

    inital_value = "..."
    tooltip = 'Delete by using right click'
    methods = [] #["AND", "OR"]
    types = [] #["TYPE", "TE", "TI"]
    operators = [] #["LIKE", ">", "<", "<=", ">=", "="]

    def __init__(self):
Franziska Koehn's avatar
Franziska Koehn committed
        super(TreeViewQuery, self).__init__()
Franziska Koehn's avatar
Franziska Koehn committed

        self.create_type_list()
        self.create_method_list()
        self.create_operator_list()

        self.set_rules_hint(True)
        self.create_columns()
        self.set_headers_visible(True)
        self.create_model()
        self.set_model(self.store)

        def on_treeview_button_press_event(treeview, event):
            if event.button == 3:
                x = int(event.x)
                y = int(event.y)
                path_info = treeview.get_path_at_pos(x, y)
                if path_info is not None:
                    path, col, cellx, celly = path_info
                    iter = self.store.get_iter(path)
                    if not path == (0,):
                        md = gtk.MessageDialog(type=gtk.MESSAGE_WARNING,
                                               buttons=gtk.BUTTONS_YES_NO,
                                               message_format="Remove the element and its children?"
                                               )
                        response = md.run()
                        md.destroy()
                        if response == gtk.RESPONSE_YES:
                            self.store.remove(iter)

        self.connect('button_press_event', on_treeview_button_press_event)

        self.set_tooltip_column(4)

    def create_columns(self):

        def root_changed_callback(combo, path_string, new_iter, col, del_col, *_):

            it = self.store.get_iter_from_string(path_string)
            new_value = combo.get_property("model")[new_iter][0]
            old_value = self.store.get_value(it, col)

            def append_inital_child(parent):
                last_child = self.store.iter_n_children(parent) -1
                child = self.store.iter_nth_child(parent, last_child)
                if not child is None:
                    child_value = self.store.get_value(child, 0)
                    if not child_value == self.inital_value:
                        self.store.append(parent,  (self.inital_value, '', '', False, self.tooltip))
                else:
                    self.store.append(parent,  (self.inital_value, '', '', False, self.tooltip))

            def set_new_value_and_append_child(has_operator_and_value):
                self.store.set(it, col, str(new_value))
                self.store.set(it, 3, has_operator_and_value)
                if has_operator_and_value:
                    parent = self.store.iter_parent(it)
                    if not parent is None:
                        append_inital_child(parent)
                else:
                    append_inital_child(it)

            if new_value in self.types:
                if (not old_value == self.inital_value) and (not old_value in self.types):
                    md = gtk.MessageDialog(type=gtk.MESSAGE_WARNING,
                                           buttons=gtk.BUTTONS_YES_NO,
                                           message_format="The children will be destroyed!Continue?"
                                           )
                    response = md.run()
                    md.destroy()
                    if response == gtk.RESPONSE_YES:
                        set_new_value_and_append_child(True)
                        while not self.store.iter_children(it) is None:
                            child = self.store.iter_children(it)
                            self.store.remove(child)
                else:
                    set_new_value_and_append_child(True)
            else:
                set_new_value_and_append_child(False)
                for c in del_col:
                    self.store.set(it, c, '')

        def cell_changed_callback(combo, path_string, new_iter, col, *_):
            it = self.store.get_iter_from_string(path_string)
            text = combo.get_property("model")[new_iter][0]
            self.store.set(it, col, str(text))

        def cell_edited_callback(cellrenderertext, path_string, new_text, col, *_):
            it = self.store.get_iter_from_string(path_string)
            self.store.set(it, col, new_text)

        rendererCombo = gtk.CellRendererCombo()
        rendererCombo.set_property('editable', True)
        rendererCombo.set_property ("model", self.create_combo_list_type());
        rendererCombo.set_property ("text-column", 0);
        rendererCombo.connect('changed', root_changed_callback, 0, [1,2])

        column = gtk.TreeViewColumn("", rendererCombo, text=0)
        column.set_sort_column_id(0)
        column.set_min_width(100)
        column.set_resizable(True)
        self.append_column(column)

        rendererCombo = gtk.CellRendererCombo()
        rendererCombo.set_property('editable', True)
        rendererCombo.set_property ("model", self.create_combo_list_operator());
        rendererCombo.set_property ("text-column", 0);
        rendererCombo.connect('changed', cell_changed_callback, 1)

        column = gtk.TreeViewColumn("Operator", rendererCombo, text=1, editable=3)
        column.set_sort_column_id(1)
        column.set_min_width(70)
        self.append_column(column)

        rendererText = gtk.CellRendererText()
        rendererText.set_property('editable', True)
        rendererText.connect('edited', cell_edited_callback, 2)

        column = gtk.TreeViewColumn("Value", rendererText, text=2, editable=3)
        column.set_sort_column_id(2)
        column.set_min_width(100)
        column.set_resizable(True)

        self.append_column(column)

    @staticmethod
    def create_combo_list(labels):
        combo_model = gtk.ListStore(str)
        for l in labels:
            combo_model.append((str(l),))
        return combo_model

    def create_combo_list_type(self):
        return self.create_combo_list(self.methods+self.types)

    def create_combo_list_operator(self):
        return self.create_combo_list(self.operators)

    def create_model(self):
        self.store = gtk.TreeStore(str, str, str, bool, str)
        self.store.append(None, (self.inital_value, '', '', False, self.tooltip))

    def create_type_list(self):
        import xnat_search
        for type in xnat_search.get_search_fields():
            self.types.append(type['label'])

    def create_method_list(self):
        import xnat_search
        self.methods = xnat_search.get_query_methods()

    def create_operator_list(self):
        import xnat_search
        self.operators = xnat_search.get_operators()

    def get_query(self):
        import xnat_search

        search_fields = xnat_search.get_search_fields()
        query = []

        def add_next_to_querry(iter):
            value = self.store.get_value(iter, 0)
            if value in self.methods:
                query.append(value)
            elif value in self.types:
                for field in search_fields:
                    if field['label'] == value:
                        value = field['field']
                operator = self.store.get_value(iter, 1)
                field_value = self.store.get_value(iter, 2)
                query.append( (value, operator, field_value) )
            child = self.store.iter_children(iter)
            if not child is None:
                add_next_to_querry(child)
            next_ = self.store.iter_next(iter)
            if not next_ is None:
                add_next_to_querry(next_)

        it = self.store.get_iter_first()
        add_next_to_querry(it)
        return query