Skip to content
chart_view.py 7.76 KiB
Newer Older
Franziska Koehn's avatar
Franziska Koehn committed
"""
Franziska Koehn's avatar
Franziska Koehn committed

Franziska Koehn's avatar
Franziska Koehn committed
:Author: Franziska Koehn
Franziska Koehn's avatar
Franziska Koehn committed
:Created: 2015/01/13

Franziska Koehn's avatar
Franziska Koehn committed
This module houses classes relating to the GUI-representation of the chart.

Franziska Koehn's avatar
Franziska Koehn committed
"""
Franziska Koehn's avatar
Franziska Koehn committed

import gtk

class ChartView(gtk.HPaned):
Franziska Koehn's avatar
Franziska Koehn committed
    """
    contains all widgets for working with the chart.
Franziska Koehn's avatar
Franziska Koehn committed

Franziska Koehn's avatar
Franziska Koehn committed
    """
    def create_new_chart(self, field, allocation):
        """
        Reads values from TreeViewChartValues and calls the function for creating the chart.
Franziska Koehn's avatar
Franziska Koehn committed

Franziska Koehn's avatar
Franziska Koehn committed
        **Parameters**

            :field: the field, for which the chart will be drawn
            :allocation: the size of the chart
Franziska Koehn's avatar
Franziska Koehn committed
        """
        import xsa.chart as chart
        import tempfile
        substrings = []
        strings = []
        if field is not None:
            for r in self.results:
                strings.append(r[field])
        for sub in self.TreeViewChartValues.store:
            if not sub[0] == self.TreeViewChartValues.inital_value:
        data = chart.count_substrings(substrings, strings)
Franziska Koehn's avatar
Franziska Koehn committed
        #save chart as tmp-file without a name
        with tempfile.NamedTemporaryFile(delete=True) as file:
            chart.create(file,data,(allocation.width,allocation.height),len(self.results), len(self.TreeViewChartValues.store)-1)
            file.flush()
            self.image.set_from_file(file.name)

    def update_chart_view(self, data, root_type):
        """
        updates chart and combobox for a new search.

        **Parameters**

            :data: results of search
            :root_type: root_type of search, for showing the fields of this type in the combobox
        self.combobox.show_data(root_type, data)
        self.combobox.set_active(0)
        type_ = self.combobox.get_selected_item()
        self.create_new_chart(type_,self.image.get_allocation())
Franziska Koehn's avatar
Franziska Koehn committed
        self.set_position(220)

        v_box = gtk.VBox()
        self.add1(v_box)
Franziska Koehn's avatar
Franziska Koehn committed
        hBox_type = gtk.HBox()
        v_box.pack_start(hBox_type, False, True, 0)

        label_type = gtk.Label()
        label_type.set_text("Type: ")
        hBox_type.pack_start(label_type, False, True, 0)

        def changed_cb(combobox):
            selected_type =  combobox.get_selected_item()
            self.create_new_chart(selected_type, self.image.get_allocation())

        self.combobox = ComboBoxRootType()
        self.combobox.connect('changed', changed_cb)
        cell = gtk.CellRendererText()
        self.combobox.pack_start(cell)
        self.combobox.add_attribute(cell, 'text', 0)
        hBox_type.pack_start(self.combobox, True, True,0)
Franziska Koehn's avatar
Franziska Koehn committed
        sw_hist_values = gtk.ScrolledWindow()
        sw_hist_values.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        sw_hist_values.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        v_box.pack_start(sw_hist_values, True, True, 0)


        def callback_columns_changed(*_):
            selected_type = self.combobox.get_selected_item()
            self.create_new_chart(selected_type, self.image.get_allocation())

        self.TreeViewChartValues = TreeViewChartValues()
        self.TreeViewChartValues.connect("values-changed", callback_columns_changed)
        sw_hist_values.add(self.TreeViewChartValues)
Franziska Koehn's avatar
Franziska Koehn committed
        # chart

        frame_image = gtk.Frame()
        self.add2(frame_image)
        frame_image.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        self.image = gtk.Image()
        frame_image.add(self.image)

        from pydash import throttle # for creating less images to increase the performance

        def callback_char_size_allocate(widget, allocation, *_):
            if callback_char_size_allocate.old_allocation.width != allocation.width or callback_char_size_allocate.old_allocation.height != allocation.height:
                selected_type =  self.combobox.get_selected_item()
                self.create_new_chart(selected_type, allocation)
                callback_char_size_allocate.old_allocation = allocation

        callback_char_size_allocate = throttle(callback_char_size_allocate, 50)
        callback_char_size_allocate.old_allocation = gtk.gdk.Rectangle()

        self.image.connect("size-allocate",callback_char_size_allocate)

class ComboBoxRootType(gtk.ComboBox):
    """
    ComboBox for choosing Type.
    """
    store = []

    def __init__(self, *args, **kwargs):
        """
        Calls parent-constructor. Creates store and set it as model.
        """
        super(ComboBoxRootType, self).__init__(*args, **kwargs)
        self.store = gtk.ListStore(str, str)
        self.set_model(self.store)

    def get_selected_item(self):
        """
        returns string of selected item.
        """
        model = self.get_model()
        index = self.get_active()
        if index > -1:
            return  model[index][1] # return key
        else:
            return None

    def show_data(self, root_type, data):
        """
        clears store, tests for emtpy data (= no results of search) and, if data is not empty, sets list of fields of given root-type in combobox-store.

        **Parameters**

            :root_type: root_type of search
            :data: results of search, if empty the store will just cleared
        import xsa.datatypereader as type_reader
        self.store.clear()
        if data == []:
            return
        for key in data.headers():
Franziska Koehn's avatar
Franziska Koehn committed
            label = type_reader.get_field_label_by_key(root_type, key)
            self.store.append([label, key])
class TreeViewChartValues(gtk.TreeView):
    """
    For creating the strings, shown in the chart (by the user).
    """

    inital_value = "..."
    tooltip = 'Delete by using right click'

    def __init__(self):
        """
        calls parent-constructor, calls funktions for creating the model and creating the column.

        """

        super(TreeViewChartValues, self).__init__()
        self.create_model()
        self.create_column()

        gobject.signal_new("values-changed", TreeViewChartValues, gobject.SIGNAL_RUN_FIRST,
        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 self.store.get_value(iter,0) != self.inital_value:
                        self.store.remove(iter)

        self.connect('button_press_event', on_treeview_button_press_event)
        self.set_tooltip_column(1)


    def create_column(self):
        """
        Creates column and its edited-callback.

        """

        def cell_edited_callback(cellrenderertext, path_string, new_text, *_):
            it = self.store.get_iter_from_string(path_string)
            it_last = self.store.get_iter(len(self.store)-1)
            self.store.set(it, 0, new_text)
            if not (it_last is None) and (self.store.get_value(it_last, 0) != self.inital_value):
                self.store.append([self.inital_value, self.tooltip])


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

Franziska Koehn's avatar
Franziska Koehn committed
        column = gtk.TreeViewColumn("Chart Values (Type Substrings)", rendererText, text=0)
        column.set_sort_column_id(0)
        self.append_column(column)

    def create_model(self):
        creates store and set it as the model.
        self.store = gtk.ListStore(str, str)
        self.store.append([self.inital_value, self.tooltip])
        self.set_model(self.store)