Skip to content
query_view.py 14.2 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.combobox.get_selected_item(), self.treeView_search.get_query(self.combobox.get_selected_item()), self.treeView_fields.get_selected_fields())
Franziska Koehn's avatar
Franziska Koehn committed

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

        import xsalogic.datatypereader as type_reader
Franziska Koehn's avatar
Franziska Koehn committed
        import gobject
Franziska Koehn's avatar
Franziska Koehn committed
        gobject.signal_new("send-query", QueryView, gobject.SIGNAL_RUN_FIRST,
Franziska Koehn's avatar
Franziska Koehn committed
        gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT))
Franziska Koehn's avatar
Franziska Koehn committed

        # root-type

        hBox_root_type = gtk.HBox()
        self.pack_start(hBox_root_type, False, True, 0)

        label_root_type = gtk.Label()
        label_root_type.set_text("Root-Type: ")
        hBox_root_type.pack_start(label_root_type, False, True, 0)

        def changed_cb(combobox):
            selected =  combobox.get_selected_item()
            fields = type_reader.get_field_labels_required_of_type(selected)
            self.treeView_search.set_root_type(selected)
            self.treeView_fields.show_fields(fields)

Franziska Koehn's avatar
Franziska Koehn committed
        self.combobox = ComboBoxRootType(gtk.ListStore(str))
        self.combobox.connect('changed', changed_cb)
        cell = gtk.CellRendererText()
Franziska Koehn's avatar
Franziska Koehn committed
        self.combobox.pack_start(cell)
        self.combobox.add_attribute(cell, 'text', 0)
        for t in type_reader.get_data_types():
Franziska Koehn's avatar
Franziska Koehn committed
            self.combobox.append_text(t)
        hBox_root_type.pack_start(self.combobox, True, True,0)

        # Sash

        vpaned_chart = gtk.VPaned()
        vpaned_chart.set_position(250)
        self.pack_start(vpaned_chart, True, True, 0)

Franziska Koehn's avatar
Franziska Koehn committed
        # 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)
Franziska Koehn's avatar
Franziska Koehn committed

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

        #result fields
        sw_fields = gtk.ScrolledWindow()
        sw_fields.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        sw_fields.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        vpaned_chart.add2(sw_fields)

        self.treeView_fields = TreeViewResultFields()
        sw_fields.add(self.treeView_fields)

Franziska Koehn's avatar
Franziska Koehn committed
        # 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)

        # setting start state
Franziska Koehn's avatar
Franziska Koehn committed
        self.combobox.set_active(0)
        self.treeView_search.set_root_type(self.combobox.get_selected_item())

class ComboBoxRootType(gtk.ComboBox):

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

    def get_selected_item(self):
        model = self.get_model()
        index = self.get_active()
        if index > -1:
            return  model[index][0]
        else:
            return None


class TreeViewResultFields(gtk.TreeView):

    def __init__(self):
        super(TreeViewResultFields, self).__init__()
        self.create_columns()
        self.store = gtk.ListStore(bool, str, bool) # is_selected, label, is_required
        self.set_model(self.store)

    def create_columns(self):

        def callback_toggled(cellrenderertoggle, path_string, col, *_):
            it = self.store.get_iter_from_string(path_string)
            is_active = cellrenderertoggle.get_active()
            if not self.store.get_value(it, 2):
                self.store.set(it, col, not is_active)

        renderer = gtk.CellRendererToggle()
        renderer.set_property('activatable', True)
        renderer.connect("toggled", callback_toggled, 0)
        column = gtk.TreeViewColumn("", renderer)
        column.add_attribute(renderer, "active", 0)
        column.set_sort_column_id(0)
        column.set_resizable(False)
        self.append_column(column)

        column = gtk.TreeViewColumn("Requested Result-Fields", gtk.CellRendererText(), text=1)
        column.set_sort_column_id(1)
        column.set_resizable(True)
        self.append_column(column)

    def show_fields(self, fields):
            self.store.append( [ f[1],  # is_selected
                                f[0],   # label
                                f[1]    # is_required
Franziska Koehn's avatar
Franziska Koehn committed
    def get_selected_fields(self):
        results = []
        for r in self.store:
            if r[0]: # if selected
                results.append(r[1])
        return results
Franziska Koehn's avatar
Franziska Koehn committed

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

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

Franziska Koehn's avatar
Franziska Koehn committed
    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("Query", rendererCombo, text=0)
Franziska Koehn's avatar
Franziska Koehn committed
        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())
Franziska Koehn's avatar
Franziska Koehn committed
        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 set_root_type(self, root_type):
        self.root_type = root_type
        self.reset_model()
        self.create_type_list()
        self.get_column(0).get_cell_renderers()[0].set_property ("model", self.create_combo_list_type()); #TODO column number???

Franziska Koehn's avatar
Franziska Koehn committed
    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 reset_model(self):
        self.store.clear()
        self.store.append(None, (self.inital_value, '', '', False, self.tooltip))

Franziska Koehn's avatar
Franziska Koehn committed
    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 xsalogic.datatypereader as type_reader
        self.types = type_reader.get_field_labels_of_type(self.root_type)
Franziska Koehn's avatar
Franziska Koehn committed

    def create_method_list(self):
        import xsalogic.queries as queries
        self.methods = queries.get_query_methods()
Franziska Koehn's avatar
Franziska Koehn committed

    def create_operator_list(self):
        import xsalogic.queries as queries
        self.operators = queries.get_operators()
    def get_query(self, type):
        import xsalogic.datatypereader as type_reader
        search_fields = type_reader.get_fields_of_type(type)
Franziska Koehn's avatar
Franziska Koehn committed
        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