Commit 47f71165 authored by Franziska Koehn's avatar Franziska Koehn
Browse files

simple workflow for ext-cSubAssessment-Data implemented

parent 6add98ef
......@@ -165,7 +165,7 @@ def disconnect_xnat_server():
except:
return
def query_for_additional_data(rest, result, host, user, passw):
def query_for_additional_data(rest, result, host, creds):
import re
def subfunc(f):
......@@ -173,6 +173,7 @@ def query_for_additional_data(rest, result, host, user, passw):
return result[key]
ret = re.sub('\{\w+\}', subfunc, rest)
user, passw = creds
central = get_xnat_server_connection(host=host, user=user, passw=passw)
exp = central.select(ret)
......
"""
:Author: Franziska Koehn
:Created: 2015/01/26
This module houses classes relating to the GUI-representation of the additional data (like fields of questionnaires)
"""
import gtk
class AdddataView(gtk.VBox):
"""Container with all widgets for working with some additional data."""
def __init__(self):
"""Creates area."""
super(AdddataView, self).__init__()
hbox_formula = gtk.HBox()
self.pack_start(hbox_formula, False, True, 0)
label_user = gtk.Label()
label_user.set_text("Filter: ")
hbox_formula.pack_start(label_user, False, True, 0)
entry_formula = gtk.Entry()
entry_formula.set_text("field0 == \"test\" or field1 < 2")
hbox_formula.pack_start(entry_formula, True, True, 0)
sw_results = gtk.ScrolledWindow()
sw_results.set_shadow_type(gtk.SHADOW_ETCHED_IN)
sw_results.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.pack_start(sw_results, True, True, 0)
self.treeview_results = TreeViewResults()
sw_results.add(self.treeview_results)
def show_comparison(self, root_type, table):
self.treeview_results.show_data(root_type, table)
class TreeViewResults(gtk.TreeView):
def __init__(self):
super(TreeViewResults, self).__init__()
def show_data(self, root_type, table):
if table == []:
return
self.create_columns(root_type, table.headers())
self.create_model(table)
def create_columns(self, root_type, column_names):
import xsa.datatypereader
for c in self.get_columns():
self.remove_column(c)
for i,key in enumerate(column_names, start=1):
cname = xsa.datatypereader.get_field_label_by_key(root_type, key)
column = gtk.TreeViewColumn(cname, gtk.CellRendererText(), text=i)
column.set_sort_column_id(i)
column.set_resizable(True)
self.append_column(column)
def create_model(self, table):
import gobject
model_columns = []
model_columns.append(gobject.TYPE_PYOBJECT) # 0 data-set
for column in table.headers():
model_columns.append(str) # 1..* values for chosen columns
store = gtk.ListStore(*model_columns)
for row in table:
row_data=[]
row_data.append(row)
for h in table.headers():
row_data.append(row[h])
store.append(row_data)
self.set_model(store)
import gtk
import xsa.datatypereader
class ComparisonDialogView(gtk.HBox):
def __init__(self, root_type, results, host, (user, passw), *args, **kwargs):
super(ComparisonDialogView, self).__init__(*args, **kwargs)
hpaned_root = gtk.HPaned()
hpaned_root.set_position(700)
self.pack_start(hpaned_root, True, True, 0)
hpaned = gtk.HPaned()
hpaned.set_position(200)
hpaned_root.add1(hpaned)
# Table for getting additional data
vbox_ident = gtk.VBox()
hpaned.add1(vbox_ident)
sw_ident = gtk.ScrolledWindow()
sw_ident.set_shadow_type(gtk.SHADOW_ETCHED_IN)
sw_ident.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
vbox_ident.pack_start(sw_ident, True, True, 0)
self.treev_identifier = TreeViewIdentifier(root_type, results)
sw_ident.add(self.treev_identifier)
def callback_get_add_data(*_):
print "Downloading data..."
self.treev_identifier.get_additional_data(host, user, passw)
data = self.treev_identifier.data
print "Importing data..."
self.treev_fields.add_new_fields(data)
print "finished."
button_get_indent = gtk.Button()
button_get_indent.set_label("Get additional Data")
button_get_indent.connect("pressed", callback_get_add_data)
vbox_ident.pack_start(button_get_indent,False,False,0)
try:
xsa.datatypereader.get_comparison_extra_source(root_type)
except Exception as e:
print e
button_get_indent.set_sensitive(False)
# Table that includes all fields
vbox_fields = gtk.VBox()
hpaned.add2(vbox_fields)
hbox_filter_fields = gtk.HBox()
vbox_fields.pack_start(hbox_filter_fields, False, False, 0)
label_filter_fields = gtk.Label("Filter: ")
def callback_activate_entry(entry, *_):
self.treev_fields.filter_store(entry.get_text())
hbox_filter_fields.pack_start(label_filter_fields, False, True, 0)
entry_filter_fields = gtk.Entry()
entry_filter_fields.connect("activate", callback_activate_entry)
hbox_filter_fields.pack_start(entry_filter_fields,True,True,0)
sw_fields = gtk.ScrolledWindow()
sw_fields.set_shadow_type(gtk.SHADOW_ETCHED_IN)
sw_fields.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
vbox_fields.pack_start(sw_fields, True, True, 0)
self.treev_fields = TreeViewFields(root_type, results)
sw_fields.add(self.treev_fields)
hbox_buttons_add = gtk.HBox()
vbox_fields.pack_start(hbox_buttons_add,False,False,0)
def callback_add_partic(*_):
selected = self.treev_fields.get_selected()
self.treev_columns.add_particular(selected)
self.treev_fields.mark_selected_as_added_and_deselect()
button_add_partic = gtk.Button()
button_add_partic.set_label("Add particular")
button_add_partic.connect("pressed", callback_add_partic)
hbox_buttons_add.add(button_add_partic)
def callback_add_combin(*_):
dialog = gtk.MessageDialog(
None,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
gtk.MESSAGE_QUESTION,
gtk.BUTTONS_OK_CANCEL,
None)
dialog.set_markup('Please enter a <b>name</b> for your <i>Combined Column</i>:')
entry = gtk.Entry()
hbox = gtk.HBox()
hbox.pack_start(gtk.Label("Column-Name:"), False, 5, 5)
hbox.pack_end(entry)
dialog.vbox.pack_end(hbox, True, True, 0)
dialog.show_all()
response = dialog.run()
text = entry.get_text()
dialog.destroy()
if response == gtk.RESPONSE_OK:
selected = self.treev_fields.get_selected()
self.treev_columns.add_combined(selected, text)
self.treev_fields.mark_selected_as_added_and_deselect()
button_add_combin = gtk.Button()
button_add_combin.set_label("Add combined")
button_add_combin.connect("pressed", callback_add_combin)
hbox_buttons_add.add(button_add_combin)
# Table that includes all selected/combined fields
sw_columns = gtk.ScrolledWindow()
sw_columns.set_shadow_type(gtk.SHADOW_ETCHED_IN)
sw_columns.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
hpaned_root.add2(sw_columns)
self.treev_columns = TreeViewColumns()
sw_columns.add(self.treev_columns)
def create_comparison_table(self):
column_store = self.treev_columns.store
data = self.treev_identifier.data
print data
result=[]
for d in data:
dic = {}
for row in column_store:
field = row[1]
values = []
try:
values.append(d[field])
except:
pass
for child in row.iterchildren():
try:
values.append(d[child[1]])
except:
pass
if values == []:
dic[field] = "N/A"
else:
dic[field] = values
result.append(dic)
from pyxnat.core.jsonutil import JsonTable
return JsonTable(result)
class TreeViewIdentifier(gtk.TreeView):
source = None
root_type = None
data = []
def __init__(self, root_type, results, *args, **kwargs):
super(TreeViewIdentifier, self).__init__(*args, **kwargs)
keys = xsa.datatypereader.get_comparison_identifier(root_type)
labels = []
for k in keys:
labels.append(xsa.datatypereader.get_field_label_by_key(root_type, k))
try:
self.source = xsa.datatypereader.get_comparison_extra_source(root_type)
except:
self.source = None
self.root_type = root_type
self.data = results
self.create_columns(labels)
self.create_model(keys, (self.source is not None))
def get_additional_data(self, host, user, passw):
import xsa.queries
rest = xsa.datatypereader.get_comparison_extra_source(self.root_type)
result = []
for row in self.store:
result.append(xsa.queries.query_for_additional_data(rest, row[1], host, user, passw))
row[0] = False
if result is not []:
self.data = result
def create_columns(self, labels):
def cell_data_func(tree_column, cell, model, tree_iter):
if model.get_value(tree_iter, 0):
stock_id = gtk.STOCK_SAVE
else:
stock_id = gtk.STOCK_APPLY
cell.set_property('stock-id', stock_id)
self.insert_column_with_data_func(0, '', gtk.CellRendererPixbuf(), cell_data_func)
for i,label in enumerate(labels, start=2):
column = gtk.TreeViewColumn(label, gtk.CellRendererText(), text=i)
column.set_sort_column_id(i)
column.set_resizable(True)
self.append_column(column)
def create_model(self, keys, has_source):
import gobject
model_columns = []
model_columns.append(bool) # 0 has additional data
model_columns.append(gobject.TYPE_PYOBJECT) # 1 result
for k in keys:
model_columns.append(str) # 2..* identifiers
self.store = gtk.ListStore(*model_columns)
for result in self.data:
new_set = []
new_set.append(has_source)
new_set.append(result)
for k in keys:
new_set.append(result[k])
self.store.append(new_set)
self.set_model(self.store)
class TreeViewFields(gtk.TreeView):
root_type = None
filter_string = ""
def __init__(self, root_type, results, *args, **kwargs):
super(TreeViewFields, self).__init__(*args, **kwargs)
self.root_type = root_type
self.create_columns()
self.create_model(results)
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()
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)
def cell_data_func(tree_column, cell, model, tree_iter):
if model.get_value(tree_iter, 3):
stock_id = gtk.STOCK_APPLY
else:
stock_id = gtk.STOCK_CLOSE
cell.set_property('stock-id', stock_id)
self.insert_column_with_data_func(1, 'added', gtk.CellRendererPixbuf(), cell_data_func)
column = gtk.TreeViewColumn("Field", gtk.CellRendererText(), text=1)
column.set_sort_column_id(2)
column.set_resizable(True)
self.append_column(column)
column = gtk.TreeViewColumn("Identifier", gtk.CellRendererText(), text=2)
column.set_sort_column_id(3)
column.set_resizable(True)
self.append_column(column)
def prepare_additional_data(self, data):
from collections import defaultdict
identifiers = xsa.datatypereader.get_comparison_identifier(self.root_type)
type_fieldkeys = xsa.datatypereader.get_keys(self.root_type)
result = defaultdict(list)
for d in data:
for field_key in d.keys():
if field_key not in type_fieldkeys:
values = []
values.append(self.concatenate_identifier_string(d))
result[field_key].extend(values)
return result
def add_new_fields(self, data):
prepared_data = self.prepare_additional_data(data)
for d in prepared_data.iterkeys():
self.store.append([False, d, prepared_data[d], False,d])
def create_model(self, results):
labels = {}
for field_key in results.headers():
field = xsa.datatypereader.get_field_label_by_key(self.root_type, field_key)
values = []
for r in results:
values.append(self.concatenate_identifier_string(r))
labels[field] = (values, field_key)
self.store = gtk.ListStore(bool, str, str, bool, str) #0 is_selected, 1 field, 2 identifiers, 3 is_added, 4 field-key
for l in labels.iterkeys():
self.store.append([False, l, labels[l][0], False, labels[l][1]])
self.store_filter = self.store.filter_new()
#TODO something is buggy about this:
def filter_func(model, iter, *_):
value_field, value_indent = model.get(iter, 1, 2)
if (value_field is not None) and (self.filter_string.lower() in value_field.lower() or self.filter_string.lower() in value_indent.lower()):
return True
else:
return False
self.store_filter.set_visible_func(filter_func)
self.set_model(self.store_filter)
def concatenate_identifier_string(self, result):
identifiers = xsa.datatypereader.get_comparison_identifier(self.root_type)
indents = ""
for i in identifiers:
indents = indents +"-"+ result[i]
return indents
def get_selected(self):
results = []
for row in self.store:
if row[0]:
results.append((row[1], row[4]))
return results
def mark_selected_as_added_and_deselect(self):
for row in self.store:
if row[0]:
row[0] = False
row[3] = True
def filter_store(self, text):
self.filter_string = text
self.store_filter.refilter()
class TreeViewColumns(gtk.TreeView):
def __init__(self):
super(TreeViewColumns, self).__init__()
self.create_columns()
self.store = gtk.TreeStore(str,str)
self.set_model(self.store)
def create_columns(self):
column = gtk.TreeViewColumn("Column", gtk.CellRendererText(), text=0)
column.set_sort_column_id(0)
column.set_resizable(True)
self.append_column(column)
def add_particular(self, columns):
for c,k in columns:
self.store.append(None, [c,k])
def add_combined(self, columns, name):
it = self.store.append(None, [name, name])
for c,k in columns:
self.store.append(it, [c,k])
......@@ -10,6 +10,8 @@ This module contains the controller that provides the communication between view
import gtk
import gobject
import xsa.datatypereader
class QueryController(gobject.GObject):
"""Provides communication between different views."""
......@@ -86,7 +88,6 @@ class QueryController(gobject.GObject):
def on_search_query(host, credentials, root_type, query, fields):
user, passw = credentials
import xsa.queries as queries
import xsa.errors
if passw =='' or user=='' or host=='':
......@@ -107,7 +108,7 @@ class QueryController(gobject.GObject):
return
try:
query_results = queries.search_for( host,
query_results = xsa.queries.search_for( host,
root_type,
query,
fields,
......@@ -140,31 +141,29 @@ class QueryController(gobject.GObject):
if self.results == []:
self.menuview.disable_download_button(False, "No Results for downloading")
self.menuview.disable_adddata_button(False, "No Results for comparison")
self.menuview.disable_export_button(False, "No Results for exporting")
self.menuview.disable_adddata_button(False, "No Results for getting additional data")
return
else:
try:
type_reader.get_rest(root_type)
xsa.datatypereader.get_rest(root_type)
self.menuview.disable_download_button(True, "Download selected items from result-table")
except xsa.errors.NoRestApiError as e:
self.menuview.disable_download_button(False, str(e))
self.menuview.disable_adddata_button(True, "Define the Comparison-Table")
self.menuview.disable_adddata_button(True, "Get additional data")
self.menuview.disable_export_button(True, "Export Result-Table as csv-file")
self.root=self.queryview.get_root_type()
self.query=self.queryview.get_query()
self.labels=self.queryview.get_fields()
import xsa.datatypereader as type_reader
fields = type_reader.get_fields_from_labels(self.labels,self.root)
on_search_query(self.host, self.credentials_tuple,
self.root,
self.query,
fields)
fields = xsa.datatypereader.get_fields_from_labels(self.labels,self.root)
on_search_query(self.host, self.credentials_tuple, self.root, self.query, fields)
def __init__(self, main, queryview, menuview, chartview, resultsview, comparison_view, statusbar):
def __init__(self, main, queryview, menuview, chartview, resultsview, statusbar):
"""
Connects signals to views. Contains definitions for callbacks of toolbar-buttons.
......@@ -183,26 +182,51 @@ class QueryController(gobject.GObject):
self.menuview = menuview
self.chartview = chartview
self.resultsview = resultsview
self.comparison_view = comparison_view
self.statusbar = statusbar
def callback_define_comparison(*_):
dialog = gtk.Dialog("Define Comparison", None, 0,
(gtk.STOCK_OK, gtk.RESPONSE_OK, "Cancel", gtk.RESPONSE_CANCEL))
dialog.set_resizable(True)
dialog.set_size_request(900, 500)
def callback_get_additional_data(*_):
from xsagtk.comparison_dialog_view import ComparisonDialogView
compdialog = ComparisonDialogView(self.root, self.results, self.host, self.credentials_tuple)
dialog.vbox.pack_start(compdialog, True, True, 0)
rest = xsa.datatypereader.get_comparison_extra_source(self.root)
new_data_sets = []
for r in self.results:
new_data_sets.append(xsa.queries.query_for_additional_data(rest, r, self.host, self.credentials_tuple))
keys = []
for data_set in new_data_sets:
for key in data_set.keys():
keys.append(key)
new_result = []
for data_set in new_data_sets:
dic = {}
for key in keys:
try:
dic[key] = data_set[key]
except:
dic[key] = "N/A"
new_result.append(dic)
from pyxnat.core.jsonutil import JsonTable
self.results = JsonTable(new_result)
self.resultsview.show_data(self.results, self.root)
self.chartview.update_chart_view(self.results, self.root)
def callback_export_csv(*_):
dialog = gtk.FileChooserDialog( "Save as...",
None,
gtk.FILE_CHOOSER_ACTION_SAVE,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN, gtk.RESPONSE_OK))
dialog.set_default_response(gtk.RESPONSE_CANCEL)
dialog.show_all()
response = dialog.run()
if response == gtk.RESPONSE_OK:
table = compdialog.create_comparison_table()
self.comparison_view.show_comparison(self.root, table)
self.results.dump_csv(dialog.get_filename())
dialog.destroy()
def callback_edit_Server_Settings(*_):
dialog = gtk.Dialog( "Server Settings",
None, 0,
......@@ -277,9 +301,6 @@ class QueryController(gobject.GObject):
if self.resultsview.get_selected_items() == []:
return