Обработка данных электронных таблиц через буфер обмена в GTK

Я использую GtkSheet виджет в PyGTK для работы с электронной таблицей моего приложения, и он дает мне API для извлечения и извлечения данных из ячеек. (Я смотрел на использование GtkTreeView, но это было слишком много работы)

Что я не понимаю, так это как перехватывать запросы на вставку (например, с помощью CTRL+V), чтобы я мог обрабатывать их, а не передавать их в виджет. В настоящее время при вставке из таблицы данные отображаются следующим образом:

http://img503.imageshack.us/img503/8265/sourcespread.png становится http://img80.imageshack.us/img80/7563/destspread.png

Есть ли сигнал, который я должен перехватить?

Я на Ubuntu 9.10, Python 2.6.

1 ответ

Решение

Чтобы поймать событие вставки, вам нужно сначала создать собственный класс записи (PastableEntry в этом примере), который наследует от gtksheet.ItemEntry, Во время его инициализации мы подключаемся к paste-clipboard сигнал для перехвата вставки событий:

class PastableEntry(gtksheet.ItemEntry):
    def __init__(self):
        gtksheet.ItemEntry.__init__(self)
        self.connect('paste-clipboard', self.__on_paste)

Тяжелая работа в обработчике событий. Сначала нам нужно получить содержимое буфера обмена. В Unix источники буфера обмена могут рекламировать несколько форматов данных. Исходя из вашего скриншота, я предполагаю, что вы пытаетесь скопировать данные из Gnumeric. Gnumeric поддерживает application/x-gnumeric, text/html, UTF8_STRING, COMPOUND_TEXT, а также STRING, Для этого примера мы будем использовать формат UTF8_STRING, который выглядит следующим образом:

1,1 <tab> 1,2 <tab> 1,3 <newline>
2,1 <tab> 2,2 <tab> 2,3 <newline>
3,1 <tab> 3,2 <tab> 3,3

Очевидно, что это ужасно не получается, если какая-либо из ячеек содержит символ табуляции или символ новой строки, но мы будем использовать это для простоты. В реальном приложении вы можете проанализировать application/x-gnumeric или же text/html отформатированные данные.

Возвращаясь к нашему классу PastableEntry, теперь мы определяем обработчик события вставки:

    def __on_paste(self, entry):
        clip = gtk.Clipboard()
        data = clip.wait_for_contents('UTF8_STRING')
        text = data.get_text()
        sheet = self.parent
        o_row, o_col = sheet.get_active_cell()
        for i_row, row in enumerate(text.split('\n')):
            for i_col, cell in enumerate(row.split('\t')):
                sheet.set_cell_text(o_row + i_row, o_col + i_col, cell)
        self.stop_emission('paste-clipboard')

Это должно быть совершенно очевидно. Мы разбиваем данные буфера обмена на строки (по символам новой строки), а затем на ячейки (по символам табуляции) и соответствующим образом устанавливаем значения ячеек листа.

stop_emission есть ли возможность остановить GTK+ от запуска обработчика по умолчанию для операций вставки. Без этой строки выбранная ячейка будет перезаписана необработанными данными.

Затем мы регистрируем класс в GObject:

gobject.type_register(PastableEntry)

Наконец, чтобы фактически использовать наш собственный класс записи, передайте его конструктору gtksheet.Sheet:

s = gtksheet.Sheet(20, 20, "Sheet 1", entry_type=PastableEntry)
Другие вопросы по тегам