2010-01-23 4 views
2

Я делаю тривиальный текстовый редактор (как упражнение) в GTK с использованием Glade, GtkBuilder и C. У меня есть меню редактирования с Cut, Copy и Paste, а также GtkTextView для текст. GtkTextView автоматически связывает последовательности вырезания/копирования/вставки для себя (и даже предоставляет пункты меню, если вы щелкните правой кнопкой мыши). Я хочу подключить пункты меню «Вырезать», «Копировать» и «Вставить» в свою панель меню в текстовое представление, чтобы они действовали так, как ожидалось.Как подключить GtkTextView к GtkMenuItem

Обратите внимание, что это двухстороннее соединение. (1) Когда один из элементов Cut, Copy или Paste GtkMenuItem активирован, он сообщает GtkTextView что-то сделать. (2) Когда выбор сделан или очищен в GtkTextView, Cut и Copy включены или отключены соответственно (см. Gedit в качестве примера). Кроме того, (3), включена ли вставка, зависит от состояния буфера обмена.

Как подключить пункты меню «Вырезать», «Копировать» и «Вставить» в текстовое представление? Есть ли способ сделать это в Glade, или моя программа на C нуждается в дополнительном коде для этого? Есть ли оптимизированный способ сделать это, или мне нужно реализовать все три поведения, указанные в приведенном выше параграфе вручную?

ответ

2

Вам понадобится дополнительный код C, но не много. В этом примере я предполагаю, что вы используете GtkAction s для своих пунктов меню, но если вы не решение, оно должно быть аналогичным.

Сначала сделайте обратные вызовы для вырезания, копирования и вставки действий в Glade. Когда вы подключаете сигналы, передайте некоторую структуру данных, содержащую по крайней мере указатели на действия вырезания, копирования и вставки, а также текстовое представление в качестве пользовательских данных.

void 
on_cut(GtkAction *action, SomeStruct *data) 
{ 
    g_signal_emit_by_name(data->view, "cut-clipboard", NULL); 
    gtk_action_set_sensitive(data->paste_action, TRUE); 
} 

void 
on_copy(GtkAction *action, SomeStruct *data) 
{ 
    g_signal_emit_by_name(data->view, "copy-clipboard", NULL); 
    gtk_action_set_sensitive(data->paste_action, TRUE); 
} 

void 
on_paste(GtkAction *action, SomeStruct *data) 
{ 
    g_signal_emit_by_name(data->view, "paste-clipboard", NULL); 
} 

Затем подключите к notify::has-selection сигнала вашего GtkTextBuffer:

void 
on_has_selection_notify(GtkTextBuffer *buffer, GParamSpec *pspec, SomeStruct *data) 
{ 
    gboolean has_selection = gtk_text_buffer_get_has_selection(buffer); 
    gtk_action_set_sensitive(data->cut_action, has_selection); 
    gtk_action_set_sensitive(data->copy_action, has_selection); 
} 

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

gtk_action_set_sensitive(data->paste_action, 
    gtk_clipboard_wait_is_text_available(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD))); 

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

Caveat lector: введенный здесь код не проверен.

+0

Спасибо, это сработало (сначала я не знал, что вы можете подключиться к свойству через «notify :: property-name»). Однако, я думаю, я нашел лучший способ обработки буфера обмена: подключиться к сигналу «изменение владельца» в буфере обмена. Этот сигнал, кажется, испускается каждый раз, когда буфер обмена обновляется. В моей системе это работало во всех крайних случаях, о которых я мог думать. –

Смежные вопросы