示例#1
0
文件: TabBlobView.py 项目: Zaffy/emma
    def on_blob_save_clicked(self, button):
        d = self.emma.assign_once(
            "save dialog",
            gtk.FileChooserDialog,
            "save blob contents",
            self.emma.mainwindow,
            gtk.FILE_CHOOSER_ACTION_SAVE,
            (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))

        d.set_default_response(gtk.RESPONSE_ACCEPT)
        answer = d.run()
        d.hide()
        if not answer == gtk.RESPONSE_ACCEPT:
            return
        filename = d.get_filename()
        if os.path.exists(filename):
            if not os.path.isfile(filename):
                show_message("save blob contents", "%s already exists and is not a file!" % filename)
                return
            if not confirm(
                    "overwrite file?", "%s already exists! do you want to overwrite it?" % filename,
                    self.emma.mainwindow):
                return
        b = self.tv.get_buffer()
        new_value = b.get_text(b.get_start_iter(), b.get_end_iter()).encode(self.emma.current_query.encoding, "ignore")
        try:
            fp = file(filename, "wb")
            fp.write(new_value)
            fp.close()
        except:
            show_message("save blob contents", "error writing query to file %s: %s" % (filename, sys.exc_value))
示例#2
0
文件: TabBlobView.py 项目: Zaffy/emma
    def on_blob_save_clicked(self, button):
        d = self.emma.assign_once("save dialog", gtk.FileChooserDialog,
                                  "save blob contents", self.emma.mainwindow,
                                  gtk.FILE_CHOOSER_ACTION_SAVE,
                                  (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
                                   gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))

        d.set_default_response(gtk.RESPONSE_ACCEPT)
        answer = d.run()
        d.hide()
        if not answer == gtk.RESPONSE_ACCEPT:
            return
        filename = d.get_filename()
        if os.path.exists(filename):
            if not os.path.isfile(filename):
                show_message("save blob contents",
                             "%s already exists and is not a file!" % filename)
                return
            if not confirm(
                    "overwrite file?",
                    "%s already exists! do you want to overwrite it?" %
                    filename, self.emma.mainwindow):
                return
        b = self.tv.get_buffer()
        new_value = b.get_text(b.get_start_iter(), b.get_end_iter()).encode(
            self.emma.current_query.encoding, "ignore")
        try:
            fp = file(filename, "wb")
            fp.write(new_value)
            fp.close()
        except:
            show_message(
                "save blob contents", "error writing query to file %s: %s" %
                (filename, sys.exc_value))
示例#3
0
文件: MySqlTable.py 项目: Zaffy/emma
 def on_toolbar_truncate_table(self, *args):
     if not confirm(
             "Truncate table",
             "Do You really want to TRUNCATE the <b>%s</b> table in database "
             "<b>%s</b> on <b>%s</b>?" % (self.name, self.db.name, self.db.host.name),
             None):
         return
     if self.db.query("truncate table `%s`" % self.name):
         if emma_instance:
             emma_instance.events.on_table_modified(self)
示例#4
0
文件: MySqlTable.py 项目: Zaffy/emma
 def on_toolbar_drop_table(self, *args):
     if not confirm(
             "Drop table",
             "do you really want to DROP the <b>%s</b> table in database "
             "<b>%s</b> on <b>%s</b>?" % (self.name, self.db.name, self.db.host.name),
             None):
         return
     if self.db.query("drop table `%s`" % self.name):
         if emma_instance:
             emma_instance.events.on_table_dropped(self)
示例#5
0
    def on_clicked(self, _):
        """

        @param _:
        @return:
        """
        d = self.emma.assign_once("load dialog", gtk.FileChooserDialog,
                                  "Load query", self.emma.mainwindow,
                                  gtk.FILE_CHOOSER_ACTION_OPEN,
                                  (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
                                   gtk.STOCK_OPEN, gtk.RESPONSE_ACCEPT))

        d.set_default_response(gtk.RESPONSE_ACCEPT)
        answer = d.run()
        d.hide()
        if not answer == gtk.RESPONSE_ACCEPT:
            return

        filename = d.get_filename()
        try:
            sbuf = os.stat(filename)
        except:
            dialogs.show_message("Load query",
                                 "%s does not exists!" % filename)
            return
        if not S_ISREG(sbuf.st_mode):
            dialogs.show_message("Load query",
                                 "%s exists, but is not a file!" % filename)
            return

        size = sbuf.st_size
        _max = int(
            self.emma.config.get("ask_execute_query_from_disk_min_size"))
        if size > _max:
            if dialogs.confirm(
                    "load query", """
<b>%s</b> is very big (<b>%.2fMB</b>)!
opening it in the normal query-view may need a very long time!
if you just want to execute this skript file without editing and
syntax-highlighting, i can open this file using the <b>execute file from disk</b> function.
<b>shall i do this?</b>""" % (filename, size / 1024.0 / 1000.0),
                    self.emma.mainwindow):
                self.emma.on_execute_query_from_disk_activate(None, filename)
                return
        try:
            fp = file(filename, "rb")
            query_text = fp.read()
            fp.close()
        except:
            dialogs.show_message(
                "Load Query", "Error reading query from file %s: %s" %
                (filename, sys.exc_value))
            return
        self.query.textview.get_buffer().set_text(query_text)
示例#6
0
    def on_save_result_clicked(self, _):
        d = self.emma.assign_once(
            "save results dialog",
            gtk.FileChooserDialog,
            "save results",
            self.emma.mainwindow, gtk.FILE_CHOOSER_ACTION_SAVE,
            (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))

        d.set_default_response(gtk.RESPONSE_ACCEPT)
        answer = d.run()
        d.hide()
        if not answer == gtk.RESPONSE_ACCEPT:
            return
        filename = d.get_filename()
        if os.path.exists(filename):
            if not os.path.isfile(filename):
                dialogs.show_message(
                    "save results",
                    "%s already exists and is not a file!" % filename
                )
                return
            if not dialogs.confirm(
                    "overwrite file?",
                    "%s already exists! do you want to overwrite it?" % filename,
                    self.emma.mainwindow):
                return
        q = self.query
        _iter = q.model.get_iter_first()
        indices = range(q.model.get_n_columns())
        field_delim = self.emma.config.get("save_result_as_csv_delim")
        line_delim = self.emma.config.get("save_result_as_csv_line_delim")
        try:
            fp = file(filename, "wb")
            for search, replace in {"\\n": "\n", "\\r": "\r", "\\t": "\t", "\\0": "\0"}.iteritems():
                field_delim = field_delim.replace(search, replace)
                line_delim = line_delim.replace(search, replace)
            while _iter:
                row = q.model.get(_iter, *indices)
                for field in row:
                    value = field
                    if value is None:
                        value = ""
                    fp.write(value.replace(field_delim, "\\" + field_delim))
                    fp.write(field_delim)
                fp.write(line_delim)
                _iter = q.model.iter_next(_iter)
            fp.close()
        except:
            dialogs.show_message(
                "save results",
                "error writing query to file %s: %s" % (filename, sys.exc_value)
            )
示例#7
0
文件: TableFields.py 项目: Zaffy/emma
 def on_drop_activate(self, *args):
     path, column = self.tv_fields.get_cursor()
     _iter = self.tv_fields_model.get_iter(path)
     _field_name = self.tv_fields_model.get_value(_iter, 2)
     if not confirm(
             "Drop field",
             "Do you really want to DROP field <b>%s</b> from table <b>%s</b>"
             " in database <b>%s</b> on <b>%s</b>?" %
         (_field_name, self.table.name, self.table.db.name,
          self.table.db.host.name), None):
         return
     self.table.drop_field(_field_name)
     self.refresh()
示例#8
0
 def on_drop_activate(self, *args):
     path, column = self.tv_fields.get_cursor()
     _iter = self.tv_fields_model.get_iter(path)
     _field_name = self.tv_fields_model.get_value(_iter, 2)
     if not confirm(
         "Drop field",
         "Do you really want to DROP field <b>%s</b> from table <b>%s</b>"
         " in database <b>%s</b> on <b>%s</b>?"
         % (_field_name, self.table.name, self.table.db.name, self.table.db.host.name),
         None,
     ):
         return
     self.table.drop_field(_field_name)
     self.refresh()
示例#9
0
文件: LoadQuery.py 项目: fastflo/emma
    def on_clicked(self, _):
        """

        @param _:
        @return:
        """
        d = self.emma.assign_once(
            "load dialog",
            gtk.FileChooserDialog, "Load query", self.emma.mainwindow, gtk.FILE_CHOOSER_ACTION_OPEN,
            (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OPEN, gtk.RESPONSE_ACCEPT))

        d.set_default_response(gtk.RESPONSE_ACCEPT)
        answer = d.run()
        d.hide()
        if not answer == gtk.RESPONSE_ACCEPT:
            return

        filename = d.get_filename()
        try:
            sbuf = os.stat(filename)
        except:
            dialogs.show_message("Load query", "%s does not exists!" % filename)
            return
        if not S_ISREG(sbuf.st_mode):
            dialogs.show_message("Load query", "%s exists, but is not a file!" % filename)
            return

        size = sbuf.st_size
        _max = int(self.emma.config.get("ask_execute_query_from_disk_min_size"))
        if size > _max:
            if dialogs.confirm("load query", """
<b>%s</b> is very big (<b>%.2fMB</b>)!
opening it in the normal query-view may need a very long time!
if you just want to execute this skript file without editing and
syntax-highlighting, i can open this file using the <b>execute file from disk</b> function.
<b>shall i do this?</b>""" % (filename, size / 1024.0 / 1000.0), self.emma.mainwindow):
                self.emma.on_execute_query_from_disk_activate(None, filename)
                return
        try:
            fp = file(filename, "rb")
            query_text = fp.read()
            fp.close()
        except:
            dialogs.show_message(
                "Load Query", "Error reading query from file %s: %s" % (filename, sys.exc_value))
            return
        self.query.textview.get_buffer().set_text(query_text)
示例#10
0
文件: SaveQuery.py 项目: fastflo/emma
    def on_clicked(self, _):
        """

        @param _:
        @return:
        """
        d = self.emma.assign_once(
            "save dialog",
            gtk.FileChooserDialog, "Save query", self.emma.mainwindow, gtk.FILE_CHOOSER_ACTION_SAVE,
            (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))

        d.set_default_response(gtk.RESPONSE_ACCEPT)
        answer = d.run()
        d.hide()
        if not answer == gtk.RESPONSE_ACCEPT:
            return
        filename = d.get_filename()
        if os.path.exists(filename):
            if not os.path.isfile(filename):
                dialogs.show_message(
                    "save query",
                    "%s already exists and is not a file!" % filename
                )
                return
            if not dialogs.confirm(
                    "Overwrite file?",
                    "%s already exists! Do you want to overwrite it?" % filename,
                    self.emma.mainwindow
            ):
                return
        b = self.query.textview.get_buffer()
        query_text = b.get_text(b.get_start_iter(), b.get_end_iter())
        try:
            fp = file(filename, "wb")
            fp.write(query_text)
            fp.close()
        except:
            dialogs.show_message(
                "Save Query",
                "Error writing query to file %s: %s" % (filename, sys.exc_value)
            )
示例#11
0
    def on_clicked(self, _):
        """

        @param _:
        @return:
        """
        d = self.emma.assign_once("save dialog", gtk.FileChooserDialog,
                                  "Save query", self.emma.mainwindow,
                                  gtk.FILE_CHOOSER_ACTION_SAVE,
                                  (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
                                   gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))

        d.set_default_response(gtk.RESPONSE_ACCEPT)
        answer = d.run()
        d.hide()
        if not answer == gtk.RESPONSE_ACCEPT:
            return
        filename = d.get_filename()
        if os.path.exists(filename):
            if not os.path.isfile(filename):
                dialogs.show_message(
                    "save query",
                    "%s already exists and is not a file!" % filename)
                return
            if not dialogs.confirm(
                    "Overwrite file?",
                    "%s already exists! Do you want to overwrite it?" %
                    filename, self.emma.mainwindow):
                return
        b = self.query.textview.get_buffer()
        query_text = b.get_text(b.get_start_iter(), b.get_end_iter())
        try:
            fp = file(filename, "wb")
            fp.write(query_text)
            fp.close()
        except:
            dialogs.show_message(
                "Save Query", "Error writing query to file %s: %s" %
                (filename, sys.exc_value))
示例#12
0
    def on_save_result_sql_clicked(self, _):
        title = "save results as sql insert script"
        d = self.emma.assign_once(
            "save results dialog",
            gtk.FileChooserDialog, title, self.emma.mainwindow, gtk.FILE_CHOOSER_ACTION_SAVE,
            (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))

        d.set_default_response(gtk.RESPONSE_ACCEPT)
        answer = d.run()
        d.hide()
        if not answer == gtk.RESPONSE_ACCEPT:
            return
        filename = d.get_filename()
        if os.path.exists(filename):
            if not os.path.isfile(filename):
                dialogs.show_message(title, "%s already exists and is not a file!" % filename)
                return
            if not dialogs.confirm(
                    "overwrite file?",
                    "%s already exists! "
                    "do you want to overwrite it?" % filename, self.emma.mainwindow):
                return
        q = self.query
        _iter = q.model.get_iter_first()
        indices = range(q.model.get_n_columns())

        # try to guess target table name from query
        table_name = ""
        query = self.query.last_source
        result = is_query_appendable(query)
        if result:
            table_list = result.group(7)
            table_list = table_list.replace(" join ", ",")
            table_list = re.sub(
                "(?i)(?:order[ \t\r\n]by.*|limit.*|group[ \r\n\t]by.*|order[ \r\n\t]by.*|where.*)",
                "",
                table_list)
            table_list = table_list.replace("`", "")
            tables = map(lambda s: s.strip(), table_list.split(","))
            table_name = "_".join(tables)
        table_name = dialogs.input_dialog(
            title,
            "Please enter the name of the target table:", table_name,
            self.emma.mainwindow
        )
        if table_name is None:
            return
        table_name = self.emma.current_host.escape_table(table_name)

        output_row = None
        try:
            fp = file(filename, "wb")
            fp.write("insert into %s values" % table_name)
            row_delim = "\n\t"
            while _iter:
                row = q.model.get(_iter, *indices)
                if not output_row:
                    output_row = range(len(row))
                for i, field in enumerate(row):
                    if field is None:
                        field = "NULL"
                    elif not field.isdigit():
                        field = "'%s'" % q.current_host.escape(field.encode(q.encoding))
                    output_row[i] = field
                fp.write("%s(%s)" % (row_delim, ",".join(output_row)))
                row_delim = ",\n\t"
                _iter = q.model.iter_next(_iter)
            fp.write("\n;\n")
            fp.close()
        except:
            dialogs.show_message(title, "error writing to file %s: %s" % (filename, sys.exc_value))
示例#13
0
    def on_clicked(self, _, query=None):
        """

        @param _:
        @param query:
        @return:
        """
        field_count = 0
        if not query:
            b = self.query.textview.get_buffer()
            text = b.get_text(b.get_start_iter(), b.get_end_iter())
        else:
            text = query

        self.query.current_host = host = self.query.current_host
        if not host:
            show_message(
                "error executing this query!",
                "could not execute query, because there is no selected host!"
            )
            return

        self.query.current_db = self.query.current_db
        if self.query.current_db:
            host.select_database(self.query.current_db)
        elif host.current_db:
            if not confirm(
                    "query without selected db",
                    """warning: this query tab has no database selected
                    but the host-connection already has the database '%s' selected.
                    the author knows no way to deselect this database.
                    do you want to continue?""" % host.current_db.name, self.emma.mainwindow):
                return

        update = False
        select = False
        self.query.editable = False

        # single popup
        self.query.toolbar.add_record.set_sensitive(False)
        self.query.toolbar.delete_record.set_sensitive(False)
        # per query buttons
        self.query.toolbar.add_record.set_sensitive(False)
        self.query.toolbar.delete_record.set_sensitive(False)
        self.query.toolbar.apply_record.set_sensitive(False)
        self.query.toolbar.local_search.set_sensitive(False)
        self.query.toolbar.remove_order.set_sensitive(False)
        self.query.toolbar.save_result_csv.set_sensitive(False)
        self.query.toolbar.save_result_sql.set_sensitive(False)

        affected_rows = 0
        last_insert_id = 0
        num_rows = 0

        query_time = 0
        download_time = 0
        display_time = 0
        query_count = 0
        total_start = time.time()

        # cleanup last query model and treeview
        for col in self.query.treeview.get_columns():
            self.query.treeview.remove_column(col)
        if self.query.model:
            self.query.model.clear()

        _start = 0
        while _start < len(text):
            # search query end
            query_start, end = read_query(text, _start)
            if query_start is None:
                break
            thisquery = text[query_start:end]
            # print "about to execute query %r" % thisquery
            _start = end + 1

            thisquery.strip(" \r\n\t;")
            if not thisquery:
                continue  # empty query
            query_count += 1
            query_hint = re.sub("[\n\r\t ]+", " ", thisquery[:40])
            self.query.label.set_text("executing query %d %s..." % (query_count, query_hint))
            self.query.label.window.process_updates(False)

            appendable = False
            appendable_result = is_query_appendable(thisquery)
            if appendable_result:
                appendable = True
                self.query.editable = self.query.is_query_editable(thisquery, appendable_result)
            # print "appendable: %s, editable: %s" % (appendable, self.query.editable)

            ret = host.query(thisquery, encoding=self.query.encoding)
            query_time += host.query_time

            if not ret:
                message = host.last_error
                self.emma.events.trigger('execute_query_error')
                # print "mysql error: %r" % (message, )
                error(message)
                # message = "error at: %s" % host.last_error.replace(
                #     "You have an error in your SQL syntax.  "
                #     "Check the manual that corresponds to your "
                #     "MySQL server version for the right syntax to use near ",
                #     "")
                # message = "error at: %s" % message.replace(
                #     "You have an error in your SQL syntax; "
                #     "check the manual that corresponds to your MySQL server "
                #     "version for the right syntax to use near ", "")
                #
                # line_pos = 0
                # pos = message.find("at line ")
                # if pos != -1:
                #     line_no = int(message[pos + 8:])
                #     while 1:
                #         line_no -= 1
                #         if line_no < 1:
                #             break
                #         p = thisquery.find("\n", line_pos)
                #         if p == -1:
                #             break
                #         line_pos = p + 1
                #
                # i = self.query.textview.get_buffer().get_iter_at_offset(query_start + line_pos)
                #
                # match = re.search("error at: '(.*)'", message, re.DOTALL)
                # if match and match.group(1):
                #     # set focus and cursor!
                #     # print "search for ->%s<-" % match.group(1)
                #     pos = text.find(
                #         match.group(1),
                #         query_start + line_pos,
                #         query_start + len(thisquery)
                #     )
                #     if not pos == -1:
                #         i.set_offset(pos)
                # else:
                #     match = re.match("Unknown column '(.*?')", message)
                #     if match:
                #         # set focus and cursor!
                #         pos = thisquery.find(match.group(1))
                #         if not pos == 1:
                #             i.set_offset(query_start + pos)
                #
                # self.query.textview.get_buffer().place_cursor(i)
                # self.query.textview.scroll_to_iter(i, 0.0)
                # self.query.textview.grab_focus()
                self.query.label.set_text(re.sub("[\r\n\t ]+", " ", message))
                return

            self.emma.events.trigger('execute_query_success')
            field_count = host.handle.field_count()
            if field_count == 0:
                # query without result
                update = True
                affected_rows += host.handle.affected_rows()
                last_insert_id = host.handle.insert_id()
                self.emma.events.trigger('execute_query_no_result')
                continue

            # query with result
            self.query.append_iter = None
            self.query.toolbar.local_search.set_sensitive(True)
            self.query.toolbar.add_record.set_sensitive(appendable)
            self.query.toolbar.delete_record.set_sensitive(self.query.editable)
            select = True
            self.query.last_source = thisquery
            # get sort order!
            sortable = True  # todo
            current_order = get_order_from_query(thisquery)
            sens = False
            if len(current_order) > 0:
                sens = True
            self.query.toolbar.remove_order.set_sensitive(sens and sortable)

            sort_fields = dict()
            for c, o in current_order:
                sort_fields[c.lower()] = o
            self.query.label.set_text("downloading resultset...")
            self.query.label.window.process_updates(False)

            start_download = time.time()
            result = host.handle.store_result()
            download_time = time.time() - start_download
            if download_time < 0:
                download_time = 0

            self.query.label.set_text("displaying resultset...")
            self.query.label.window.process_updates(False)

            # store field info
            self.query.result_info = result.describe()
            num_rows = result.num_rows()

            if num_rows == 0:
                self.emma.events.trigger('execute_query_empty')
            else:
                self.emma.events.trigger('execute_query_not_empty')

            for col in self.query.treeview.get_columns():
                self.query.treeview.remove_column(col)

            columns = [gobject.TYPE_STRING] * field_count
            self.query.model = gtk.ListStore(*columns)
            self.query.treeview.set_model(self.query.model)
            self.query.treeview.set_rules_hint(True)
            self.query.treeview.set_headers_clickable(True)
            for i in range(field_count):
                title = self.query.result_info[i][0].replace("_", "__").replace("[\r\n\t ]+", " ")
                text_renderer = gtk.CellRendererText()
                if self.query.editable:
                    text_renderer.set_property("editable", True)
                    text_renderer.connect("edited", self.query.on_query_change_data, i)
                l = self.query.treeview.insert_column_with_data_func(
                    -1, title, text_renderer, ResultCellRenders.render_mysql_string, i)

                col = self.query.treeview.get_column(l - 1)

                if self.emma.config.get_bool("result_view_column_resizable"):
                    col.set_resizable(True)
                else:
                    col.set_resizable(False)
                    col.set_min_width(int(self.emma.config.get("result_view_column_width_min")))
                    col.set_max_width(int(self.emma.config.get("result_view_column_width_max")))

                if sortable:
                    col.set_clickable(True)
                    col.connect("clicked", self.query.on_query_column_sort, i)
                    # set sort indicator
                    field_name = self.query.result_info[i][0].lower()
                    try:
                        sort_col = sort_fields[field_name]
                        col.set_sort_indicator(True)
                        if sort_col:
                            col.set_sort_order(gtk.SORT_ASCENDING)
                        else:
                            col.set_sort_order(gtk.SORT_DESCENDING)
                    except:
                        col.set_sort_indicator(False)
                else:
                    col.set_clickable(False)
                    col.set_sort_indicator(False)

            cnt = 0
            start_display = time.time()
            last_display = start_display
            for row in result.fetch_row(0):
                def to_string(f):
                    """
                    To string Value of field
                    @param f:
                    @return:
                    """
                    if isinstance(f, str):
                        f = f.decode(self.query.encoding, "replace")
                    elif f is None:
                        pass
                    else:
                        f = str(f)
                    return f
                self.query.model.append(map(to_string, row))
                cnt += 1
                if (cnt % 100) != 0:
                    continue

                now = time.time()
                if (now - last_display) < 0.2:
                    continue

                self.query.label.set_text("displayed %d rows..." % cnt)
                self.query.label.window.process_updates(False)
                last_display = now

            display_time = time.time() - start_display
            if display_time < 0:
                display_time = 0

        result = []
        if select:
            # there was a query with a result
            result.append("rows: %d" % num_rows)
            result.append("fields: %d" % field_count)
            self.query.toolbar.save_result_csv.set_sensitive(True)
            self.query.toolbar.save_result_sql.set_sensitive(True)
        if update:
            # there was a query without a result
            result.append("affected rows: %d" % affected_rows)
            result.append("insert_id: %d" % last_insert_id)
        total_time = time.time() - total_start
        result.append("| total time: %.2fs (query: %.2fs" % (total_time, query_time))
        if select:
            result.append("download: %.2fs display: %.2fs" % (download_time, display_time))
        result.append(")")

        self.query.label.set_text(' '.join(result))
        self.emma.blob_view.tv.set_editable(self.query.editable)
        self.emma.blob_view.blob_update.set_sensitive(self.query.editable)
        self.emma.blob_view.blob_load.set_sensitive(self.query.editable)
        # todo update_buttons()
        gc.collect()
        return True