Обработка данных электронных таблиц через буфер обмена в GTK - PullRequest
3 голосов
/ 07 января 2010

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

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

Source становится Destination

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

Я нахожусь на Ubuntu 9.10, Python 2.6.

1 Ответ

7 голосов
/ 13 января 2010

Чтобы перехватить событие вставки, необходимо сначала создать собственный класс записи (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)
...