GhostLLM: Add text rewrite functionality to GtkTextView
Table of contents
Hello,
This is final part of the GhostLLM project. The goal was to introduce “Rewrite Text” functionality to GTK3 TextView using Ollama.
If you haven’t been following this project, you can find the links below:
Part 1
Part 2
Part 3
In this part, I have updated GtkTextView
widget with relevant GhostLLM code for the text rewrite functionality.
Theory
We need to adapt the GhostLLM related code from gtkentry.c
to gtktextview.c
and test the features. This code has proven to be working with GtkEntry in the last part so I am not expecting any issues now.
Implementation
You will find latest changes on Github repo here.
Here’s the relevant code:
gtktextview.c (GhostLLM callback code):
static void
ghostllm_rewrite_text_cb (GtkWidget *widget)
{
GtkTextView *text_view = GTK_TEXT_VIEW (widget);
GtkTextBuffer *buffer;
GtkTextIter start_iter, end_iter;
buffer = text_view->priv->buffer;
// Get selection bounds for string
gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter);
// Get selected text from selection bounds
char *input_str = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE);
// Rewrite the input string
char* response = ghostllm_rewrite_text(input_str);
if (response == NULL) {
g_printerr("Unable to generate GhostLLM response.");
return;
}
// HACK: Delete user selected text using "Cut" operation
gtk_text_view_cut_clipboard(text_view);
// Insert rewritten text
gtk_text_view_insert_at_cursor(text_view, response);
g_free (response);
}
gtktextview.c (Context menu code)
// This code goes after line number 9586
// GhostLLM stuff
// The root GtkMenuItem that shows "GhostLLM" option on the context menu
GtkWidget *ghostllm_root_menuitem = gtk_menu_item_new_with_mnemonic (_("GhostLLM"));
gtk_widget_set_sensitive(ghostllm_root_menuitem, gtk_text_buffer_get_char_count (priv->buffer) > 0);
// The GtkMenu widget which holds the LLM menu options.
GtkWidget *ghostllm_submenu = gtk_menu_new ();
menuitem = gtk_menu_item_new_with_mnemonic (_("_Rewrite Text"));
g_signal_connect_swapped (menuitem, "activate", G_CALLBACK (ghostllm_rewrite_text_cb), text_view);
gtk_widget_show (menuitem);
// Append "Rewrite Text" option into LLM submenu
gtk_menu_shell_append (GTK_MENU_SHELL (ghostllm_submenu), menuitem);
// Set submenu options for GhostLLM root menu item
gtk_menu_item_set_submenu ( GTK_MENU_ITEM (ghostllm_root_menuitem), ghostllm_submenu);
gtk_widget_show(menuitem);
gtk_widget_show(ghostllm_root_menuitem);
// Append the GhostLLM root GtkMenuItem into GtkEntry's context menu
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), ghostllm_root_menuitem);
I have tested my changes using the “sunny” example provided on the GTK repo. I had to make the following change in meson.build
at the project root and compiled the whole thing.
diff --git a/meson.build b/meson.build
index 67b24e5e7d..9df8fae828 100644
--- a/meson.build
+++ b/meson.build
@@ -857,6 +857,7 @@ subdir('gdk')
subdir('gtk')
subdir('modules')
subdir('libgail-util')
+subdir('examples')
if get_option('demos')
subdir('demos')
endif
@@ -864,9 +865,8 @@ if get_option('tests')
subdir('tests')
subdir('testsuite')
endif
-if get_option('examples')
- subdir('examples')
-endif
+#if get_option('examples')
+#endif
# config.h
configure_file(
Screenshots
User input screen
Output screen
My Opinion on LLMs
I personally feel the current LLM “AI” stuff is just hype around a new technology and just like “dot com bubble” as well as the crypto crap a few years back, this too shall wither away in the future.
I do see the potential with this technology as a completely offline auto complete or auto suggestions like functionality based on this however that would involve using much smaller LLM models. In this example, I am using qwen2.5:3b which did the job but it’s 1.9GB in size and it took a few seconds for my GTX 1050 Ti to process the request. This would only increase with the input tokens.
Conclusion
This marks the end of the fun (and silly) GhostLLM project. I learned a lot working on this and has proven yet again why I prefer GTK+ on my projects.
Thanks for following along on this project. Please leave a Like on the post to show your appreciation.
Bye for now :-)