ClipIt-v1.3.0-14112010001
+ Added: Added "Edit" and "Remove" buttons to the "Manage History" dialog. + Fixed: Major speed improvements for big history entries while: searching through the history; populating the "Manage History" dialog; generating the popup menus; All of these should now be more than 99% faster, at the expense of an (at most) 1MB overhead. I think it's worth it, though. + Fixed: Fixed a drawing issue with the small history menu when activated by clicking on the systray icon.
This commit is contained in:
parent
49b85b9c5e
commit
d1fe47618e
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
|||||||
|
ClipIt-v1.3.0-14112010001 - 14 Nov. 2010
|
||||||
|
+ Added: Added "Edit" and "Remove" buttons to the "Manage History" dialog.
|
||||||
|
+ Fixed: Major speed improvements for big history entries while:
|
||||||
|
searching through the history;
|
||||||
|
populating the "Manage History" dialog;
|
||||||
|
generating the popup menus;
|
||||||
|
All of these should now be more than 99% faster, at the expense
|
||||||
|
of an (at most) 1MB overhead. I think it's worth it, though.
|
||||||
|
+ Fixed: Fixed a drawing issue with the small history menu when activated
|
||||||
|
by clicking on the systray icon.
|
||||||
|
|
||||||
ClipIt-v1.2.6-12112010003 - 12 Nov. 2010
|
ClipIt-v1.2.6-12112010003 - 12 Nov. 2010
|
||||||
+ Fixed: Removed reference to pthread.h from configure.in.
|
+ Fixed: Removed reference to pthread.h from configure.in.
|
||||||
+ Fixed: Set AM_MAINTAINER_MODE to disabled by default.
|
+ Fixed: Set AM_MAINTAINER_MODE to disabled by default.
|
||||||
|
3
TODO
3
TODO
@ -1,10 +1,7 @@
|
|||||||
+ Add primary support for CLI.
|
+ Add primary support for CLI.
|
||||||
+ Dialog with listed history contents for searching and removing.
|
|
||||||
+ Static entries.
|
+ Static entries.
|
||||||
+ Added variable to hold return values of fread and system, we should
|
+ Added variable to hold return values of fread and system, we should
|
||||||
actually use that return value to display an error if there was one.
|
actually use that return value to display an error if there was one.
|
||||||
+ Redo Preferences dialog.
|
+ Redo Preferences dialog.
|
||||||
+ Clean up the code and indent it properly.
|
+ Clean up the code and indent it properly.
|
||||||
+ Add "Edit" and "Remove" buttons to the search window and rename
|
|
||||||
it to "Manage Clipboard".
|
|
||||||
+ Move all pop-up and menu functions from main.c to menus.c.
|
+ Move all pop-up and menu functions from main.c to menus.c.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# Autoconf/automake.
|
# Autoconf/automake.
|
||||||
# -------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------
|
||||||
AC_PREREQ([2.5])
|
AC_PREREQ([2.5])
|
||||||
AC_INIT([clipit], [1.2.6], [oss@web-tm.com])
|
AC_INIT([clipit], [1.3.0], [oss@web-tm.com])
|
||||||
AM_INIT_AUTOMAKE([AC_PACKAGE_TARNAME()], [AC_PACKAGE_VERSION()])
|
AM_INIT_AUTOMAKE([AC_PACKAGE_TARNAME()], [AC_PACKAGE_VERSION()])
|
||||||
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
@ -25,9 +25,11 @@
|
|||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define HISTORY_FILE ".local/share/clipit/history"
|
#define HISTORY_FILE ".local/share/clipit/history"
|
||||||
/* Set maximum size of one clipboard entry to 512KB
|
/* Set maximum size of one clipboard entry to 1024KB (1MB)
|
||||||
* 250 pages × 2000 characters per page - should be more than enough */
|
* 1024 pages × 2000 characters per page - should be more than enough.
|
||||||
#define ENTRY_MAX_SIZE 524288
|
* WARNING: if you use all 1000 history items, clipit could use up to
|
||||||
|
* 1 GB of RAM. If you don't want that, set this lower. */
|
||||||
|
#define ENTRY_MAX_SIZE 1048576
|
||||||
|
|
||||||
extern GSList* history;
|
extern GSList* history;
|
||||||
|
|
||||||
|
118
src/main.c
118
src/main.c
@ -264,60 +264,6 @@ edit_actions_selected(GtkButton *button, gpointer user_data)
|
|||||||
show_preferences(ACTIONS_TAB);
|
show_preferences(ACTIONS_TAB);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called when Edit is selected from history menu */
|
|
||||||
static void
|
|
||||||
edit_selected(GtkMenuItem *menu_item, gpointer user_data)
|
|
||||||
{
|
|
||||||
/* This helps prevent multiple instances */
|
|
||||||
if (!gtk_grab_get_current())
|
|
||||||
{
|
|
||||||
/* Create clipboard buffer and set its text */
|
|
||||||
GtkTextBuffer* clipboard_buffer = gtk_text_buffer_new(NULL);
|
|
||||||
gchar* current_clipboard_text = gtk_clipboard_wait_for_text(clipboard);
|
|
||||||
if (current_clipboard_text != NULL)
|
|
||||||
{
|
|
||||||
gtk_text_buffer_set_text(clipboard_buffer, current_clipboard_text, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the dialog */
|
|
||||||
GtkWidget* dialog = gtk_dialog_new_with_buttons(_("Editing Clipboard"), NULL,
|
|
||||||
(GTK_DIALOG_MODAL + GTK_DIALOG_NO_SEPARATOR),
|
|
||||||
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
|
|
||||||
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
|
|
||||||
|
|
||||||
gtk_window_set_default_size((GtkWindow*)dialog, 450, 300);
|
|
||||||
gtk_window_set_icon((GtkWindow*)dialog, gtk_widget_render_icon(dialog, GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU, NULL));
|
|
||||||
|
|
||||||
/* Build the scrolled window with the text view */
|
|
||||||
GtkWidget* scrolled_window = gtk_scrolled_window_new((GtkAdjustment*) gtk_adjustment_new(0, 0, 0, 0, 0, 0),
|
|
||||||
(GtkAdjustment*) gtk_adjustment_new(0, 0, 0, 0, 0, 0));
|
|
||||||
|
|
||||||
gtk_scrolled_window_set_policy((GtkScrolledWindow*)scrolled_window,
|
|
||||||
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
|
||||||
|
|
||||||
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrolled_window, TRUE, TRUE, 2);
|
|
||||||
GtkWidget* text_view = gtk_text_view_new_with_buffer(clipboard_buffer);
|
|
||||||
gtk_text_view_set_left_margin((GtkTextView*)text_view, 2);
|
|
||||||
gtk_text_view_set_right_margin((GtkTextView*)text_view, 2);
|
|
||||||
gtk_container_add((GtkContainer*)scrolled_window, text_view);
|
|
||||||
|
|
||||||
/* Run the dialog */
|
|
||||||
gtk_widget_show_all(dialog);
|
|
||||||
if (gtk_dialog_run((GtkDialog*)dialog) == GTK_RESPONSE_ACCEPT)
|
|
||||||
{
|
|
||||||
/* Save changes done to the clipboard */
|
|
||||||
GtkTextIter start, end;
|
|
||||||
gtk_text_buffer_get_start_iter(clipboard_buffer, &start);
|
|
||||||
gtk_text_buffer_get_end_iter(clipboard_buffer, &end);
|
|
||||||
gchar* new_clipboard_text = gtk_text_buffer_get_text(clipboard_buffer, &start, &end, TRUE);
|
|
||||||
gtk_clipboard_set_text(clipboard, new_clipboard_text, -1);
|
|
||||||
g_free(new_clipboard_text);
|
|
||||||
}
|
|
||||||
gtk_widget_destroy(dialog);
|
|
||||||
g_free(current_clipboard_text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Called when an item is selected from history menu */
|
/* Called when an item is selected from history menu */
|
||||||
static void
|
static void
|
||||||
item_selected(GtkMenuItem *menu_item, gpointer user_data)
|
item_selected(GtkMenuItem *menu_item, gpointer user_data)
|
||||||
@ -584,14 +530,6 @@ show_history_menu_full(gpointer data)
|
|||||||
/* Create the menu */
|
/* Create the menu */
|
||||||
menu = gtk_menu_new();
|
menu = gtk_menu_new();
|
||||||
g_signal_connect((GObject*)menu, "selection-done", (GCallback)gtk_widget_destroy, NULL);
|
g_signal_connect((GObject*)menu, "selection-done", (GCallback)gtk_widget_destroy, NULL);
|
||||||
/* Edit clipboard */
|
|
||||||
menu_item = gtk_image_menu_item_new_with_mnemonic(_("_Edit Clipboard"));
|
|
||||||
menu_image = gtk_image_new_from_stock(GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU);
|
|
||||||
gtk_image_menu_item_set_image((GtkImageMenuItem*)menu_item, menu_image);
|
|
||||||
g_signal_connect((GObject*)menu_item, "activate", (GCallback)edit_selected, NULL);
|
|
||||||
gtk_menu_shell_append((GtkMenuShell*)menu, menu_item);
|
|
||||||
/* -------------------- */
|
|
||||||
gtk_menu_shell_append((GtkMenuShell*)menu, gtk_separator_menu_item_new());
|
|
||||||
/* Items */
|
/* Items */
|
||||||
if ((history != NULL) && (history->data != NULL))
|
if ((history != NULL) && (history->data != NULL))
|
||||||
{
|
{
|
||||||
@ -610,15 +548,6 @@ show_history_menu_full(gpointer data)
|
|||||||
for (element = history; element != NULL; element = element->next)
|
for (element = history; element != NULL; element = element->next)
|
||||||
{
|
{
|
||||||
GString* string = g_string_new((gchar*)element->data);
|
GString* string = g_string_new((gchar*)element->data);
|
||||||
/* Remove control characters */
|
|
||||||
int i = 0;
|
|
||||||
while (i < string->len)
|
|
||||||
{
|
|
||||||
if (string->str[i] == '\n')
|
|
||||||
g_string_erase(string, i, 1);
|
|
||||||
else
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
/* Ellipsize text */
|
/* Ellipsize text */
|
||||||
if (string->len > prefs.item_length)
|
if (string->len > prefs.item_length)
|
||||||
{
|
{
|
||||||
@ -638,6 +567,14 @@ show_history_menu_full(gpointer data)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Remove control characters */
|
||||||
|
int i = 0;
|
||||||
|
while (i < string->len)
|
||||||
|
{
|
||||||
|
if (string->str[i] == '\n')
|
||||||
|
g_string_overwrite(string, i, " ");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
/* Make new item with ellipsized text */
|
/* Make new item with ellipsized text */
|
||||||
gchar* list_item;
|
gchar* list_item;
|
||||||
if (prefs.show_indexes)
|
if (prefs.show_indexes)
|
||||||
@ -733,15 +670,6 @@ show_history_menu_small(gpointer data)
|
|||||||
for (element = history; (element != NULL) && (element_number_small < prefs.history_small); element = element->next)
|
for (element = history; (element != NULL) && (element_number_small < prefs.history_small); element = element->next)
|
||||||
{
|
{
|
||||||
GString* string = g_string_new((gchar*)element->data);
|
GString* string = g_string_new((gchar*)element->data);
|
||||||
/* Remove control characters */
|
|
||||||
int i = 0;
|
|
||||||
while (i < string->len)
|
|
||||||
{
|
|
||||||
if (string->str[i] == '\n')
|
|
||||||
g_string_erase(string, i, 1);
|
|
||||||
else
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
/* Ellipsize text */
|
/* Ellipsize text */
|
||||||
if (string->len > prefs.item_length)
|
if (string->len > prefs.item_length)
|
||||||
{
|
{
|
||||||
@ -761,6 +689,14 @@ show_history_menu_small(gpointer data)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Remove control characters */
|
||||||
|
int i = 0;
|
||||||
|
while (i < string->len)
|
||||||
|
{
|
||||||
|
if (string->str[i] == '\n')
|
||||||
|
g_string_overwrite(string, i, " ");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
/* Make new item with ellipsized text */
|
/* Make new item with ellipsized text */
|
||||||
gchar* list_item;
|
gchar* list_item;
|
||||||
if (prefs.show_indexes)
|
if (prefs.show_indexes)
|
||||||
@ -835,7 +771,7 @@ show_history_menu_small(gpointer data)
|
|||||||
|
|
||||||
/* Called when status icon is left-clicked */
|
/* Called when status icon is left-clicked */
|
||||||
static gboolean
|
static gboolean
|
||||||
show_history_menu(gpointer data)
|
show_history_menu()
|
||||||
{
|
{
|
||||||
if (prefs.small_history)
|
if (prefs.small_history)
|
||||||
g_timeout_add(POPUP_DELAY, show_history_menu_small, NULL);
|
g_timeout_add(POPUP_DELAY, show_history_menu_small, NULL);
|
||||||
@ -847,8 +783,7 @@ show_history_menu(gpointer data)
|
|||||||
|
|
||||||
/* Called when status icon is right-clicked */
|
/* Called when status icon is right-clicked */
|
||||||
static void
|
static void
|
||||||
show_clipit_menu(GtkStatusIcon *status_icon, guint button,
|
show_clipit_menu(GtkStatusIcon *status_icon, guint button, guint activate_time)
|
||||||
guint activate_time, gpointer user_data)
|
|
||||||
{
|
{
|
||||||
/* Declare some variables */
|
/* Declare some variables */
|
||||||
GtkWidget *menu, *menu_item,
|
GtkWidget *menu, *menu_item,
|
||||||
@ -886,13 +821,13 @@ show_clipit_menu(GtkStatusIcon *status_icon, guint button,
|
|||||||
gtk_menu_shell_append((GtkMenuShell*)menu, menu_item);
|
gtk_menu_shell_append((GtkMenuShell*)menu, menu_item);
|
||||||
/* Popup the menu... */
|
/* Popup the menu... */
|
||||||
gtk_widget_show_all(menu);
|
gtk_widget_show_all(menu);
|
||||||
gtk_menu_popup((GtkMenu*)menu, NULL, NULL, NULL, user_data, button, activate_time);
|
gtk_menu_popup((GtkMenu*)menu, NULL, NULL, NULL, NULL, button, activate_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called when status icon is clicked */
|
/* Called when status icon is clicked */
|
||||||
/* (checks type of click and calls correct function */
|
/* (checks type of click and calls correct function */
|
||||||
static void
|
static void
|
||||||
status_icon_clicked(GtkStatusIcon *status_icon, gpointer user_data)
|
status_icon_clicked(GtkStatusIcon *status_icon, GdkEventButton *event )
|
||||||
{
|
{
|
||||||
/* Check what type of click was recieved */
|
/* Check what type of click was recieved */
|
||||||
GdkModifierType state;
|
GdkModifierType state;
|
||||||
@ -906,9 +841,13 @@ status_icon_clicked(GtkStatusIcon *status_icon, gpointer user_data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Normal click */
|
/* Normal click */
|
||||||
|
else if (event->button == 1)
|
||||||
|
{
|
||||||
|
show_history_menu();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_timeout_add(POPUP_DELAY, show_history_menu, NULL);
|
show_clipit_menu(status_icon, event->button, gtk_get_current_event_time());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -930,15 +869,13 @@ actions_hotkey(char *keystring, gpointer user_data)
|
|||||||
void
|
void
|
||||||
menu_hotkey(char *keystring, gpointer user_data)
|
menu_hotkey(char *keystring, gpointer user_data)
|
||||||
{
|
{
|
||||||
show_clipit_menu(status_icon, 0, 0, NULL);
|
show_clipit_menu(status_icon, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called when search global hotkey is pressed */
|
/* Called when search global hotkey is pressed */
|
||||||
void
|
void
|
||||||
search_hotkey(char *keystring, gpointer user_data)
|
search_hotkey(char *keystring, gpointer user_data)
|
||||||
{
|
{
|
||||||
if (!gtk_grab_get_current())
|
|
||||||
/* Show the search dialog */
|
|
||||||
g_timeout_add(POPUP_DELAY, show_search, NULL);
|
g_timeout_add(POPUP_DELAY, show_search, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -970,8 +907,7 @@ clipit_init()
|
|||||||
{
|
{
|
||||||
status_icon = gtk_status_icon_new_from_stock(GTK_STOCK_PASTE);
|
status_icon = gtk_status_icon_new_from_stock(GTK_STOCK_PASTE);
|
||||||
gtk_status_icon_set_tooltip((GtkStatusIcon*)status_icon, _("Clipboard Manager"));
|
gtk_status_icon_set_tooltip((GtkStatusIcon*)status_icon, _("Clipboard Manager"));
|
||||||
g_signal_connect((GObject*)status_icon, "activate", (GCallback)status_icon_clicked, NULL);
|
g_signal_connect((GObject*)status_icon, "button_release_event", (GCallback)status_icon_clicked, NULL);
|
||||||
g_signal_connect((GObject*)status_icon, "popup-menu", (GCallback)show_clipit_menu, NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
316
src/manage.c
316
src/manage.c
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
#include <string.h>
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "history.h"
|
#include "history.h"
|
||||||
@ -30,22 +31,233 @@
|
|||||||
|
|
||||||
GtkListStore* search_list;
|
GtkListStore* search_list;
|
||||||
GtkWidget *search_entry;
|
GtkWidget *search_entry;
|
||||||
GtkTreeSelection* search_selection;
|
GtkWidget* treeview_search;
|
||||||
|
|
||||||
|
/* Search through the history */
|
||||||
|
static void
|
||||||
|
search_history()
|
||||||
|
{
|
||||||
|
guint16 search_len = gtk_entry_get_text_length((GtkEntry*)search_entry);
|
||||||
|
/* Test if there is text in the search box */
|
||||||
|
if(search_len > 0)
|
||||||
|
{
|
||||||
|
if ((history != NULL) && (history->data != NULL))
|
||||||
|
{
|
||||||
|
char* search_input = (char *)g_strdup(gtk_entry_get_text((GtkEntry*)search_entry));
|
||||||
|
GtkTreeIter search_iter;
|
||||||
|
while(gtk_tree_model_get_iter_first((GtkTreeModel*)search_list, &search_iter))
|
||||||
|
gtk_list_store_remove(search_list, &search_iter);
|
||||||
|
|
||||||
|
/* Declare some variables */
|
||||||
|
GSList* element;
|
||||||
|
gint element_number = 0;
|
||||||
|
/* Go through each element and adding each */
|
||||||
|
for (element = history; element != NULL; element = element->next)
|
||||||
|
{
|
||||||
|
GString* string = g_string_new((gchar*)element->data);
|
||||||
|
gchar* strn_cmp_to = g_utf8_strdown(string->str, string->len);
|
||||||
|
gchar* strn_find = g_utf8_strdown(search_input, search_len);
|
||||||
|
char* result = strstr(strn_cmp_to, strn_find);
|
||||||
|
if(result)
|
||||||
|
{
|
||||||
|
GtkTreeIter row_iter;
|
||||||
|
gtk_list_store_append(search_list, &row_iter);
|
||||||
|
if (string->len > prefs.item_length)
|
||||||
|
{
|
||||||
|
switch (prefs.ellipsize)
|
||||||
|
{
|
||||||
|
case PANGO_ELLIPSIZE_START:
|
||||||
|
string = g_string_erase(string, 0, string->len-(prefs.item_length));
|
||||||
|
string = g_string_prepend(string, "...");
|
||||||
|
break;
|
||||||
|
case PANGO_ELLIPSIZE_MIDDLE:
|
||||||
|
string = g_string_erase(string, (prefs.item_length/2), string->len-(prefs.item_length));
|
||||||
|
string = g_string_insert(string, (string->len/2), "...");
|
||||||
|
break;
|
||||||
|
case PANGO_ELLIPSIZE_END:
|
||||||
|
string = g_string_truncate(string, prefs.item_length);
|
||||||
|
string = g_string_append(string, "...");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int i = 0;
|
||||||
|
while (i < string->len)
|
||||||
|
{
|
||||||
|
if (string->str[i] == '\n')
|
||||||
|
g_string_overwrite(string, i, " ");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
int row_num = g_slist_position(history, element);
|
||||||
|
gtk_list_store_set(search_list, &row_iter, 0, row_num, 1, string->str, -1);
|
||||||
|
}
|
||||||
|
/* Prepare for next item */
|
||||||
|
g_string_free(string, TRUE);
|
||||||
|
element_number++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If nothing is searched for, we show all items */
|
||||||
|
if ((history != NULL) && (history->data != NULL))
|
||||||
|
{
|
||||||
|
GtkTreeIter search_iter;
|
||||||
|
/* First, we remove all items */
|
||||||
|
while(gtk_tree_model_get_iter_first((GtkTreeModel*)search_list, &search_iter))
|
||||||
|
gtk_list_store_remove(search_list, &search_iter);
|
||||||
|
|
||||||
|
/* Declare some variables */
|
||||||
|
GSList* element;
|
||||||
|
/* Go through each element and adding each */
|
||||||
|
for (element = history; element != NULL; element = element->next)
|
||||||
|
{
|
||||||
|
GString* string = g_string_new((gchar*)element->data);
|
||||||
|
GtkTreeIter row_iter;
|
||||||
|
gtk_list_store_append(search_list, &row_iter);
|
||||||
|
if (string->len > prefs.item_length)
|
||||||
|
{
|
||||||
|
switch (prefs.ellipsize)
|
||||||
|
{
|
||||||
|
case PANGO_ELLIPSIZE_START:
|
||||||
|
string = g_string_erase(string, 0, string->len-(prefs.item_length));
|
||||||
|
string = g_string_prepend(string, "...");
|
||||||
|
break;
|
||||||
|
case PANGO_ELLIPSIZE_MIDDLE:
|
||||||
|
string = g_string_erase(string, (prefs.item_length/2), string->len-(prefs.item_length));
|
||||||
|
string = g_string_insert(string, (string->len/2), "...");
|
||||||
|
break;
|
||||||
|
case PANGO_ELLIPSIZE_END:
|
||||||
|
string = g_string_truncate(string, prefs.item_length);
|
||||||
|
string = g_string_append(string, "...");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int i = 0;
|
||||||
|
while (i < string->len)
|
||||||
|
{
|
||||||
|
if (string->str[i] == '\n')
|
||||||
|
g_string_overwrite(string, i, " ");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
int row_num = g_slist_position(history, element);
|
||||||
|
gtk_list_store_set(search_list, &row_iter, 0, row_num, 1, string->str, -1);
|
||||||
|
|
||||||
|
/* Prepare for next item */
|
||||||
|
g_string_free(string, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called when Edit is selected from Manage dialog */
|
||||||
|
static void
|
||||||
|
edit_selected()
|
||||||
|
{
|
||||||
|
GtkTreeIter sel_iter;
|
||||||
|
GtkTreeSelection* search_selection = gtk_tree_view_get_selection((GtkTreeView*)treeview_search);
|
||||||
|
/* This helps prevent multiple instances and checks if there's anything selected */
|
||||||
|
if (!gtk_grab_get_current() &&
|
||||||
|
gtk_tree_selection_get_selected(search_selection, NULL, &sel_iter))
|
||||||
|
{
|
||||||
|
/* Create clipboard buffer and set its text */
|
||||||
|
gint selected_item_nr;
|
||||||
|
gtk_tree_model_get((GtkTreeModel*)search_list, &sel_iter, 0, &selected_item_nr, -1);
|
||||||
|
GSList* element = g_slist_nth(history, selected_item_nr);
|
||||||
|
GString* s_selected_item = g_string_new((gchar*)element->data);
|
||||||
|
GtkTextBuffer* clipboard_buffer = gtk_text_buffer_new(NULL);
|
||||||
|
gtk_text_buffer_set_text(clipboard_buffer, s_selected_item->str, -1);
|
||||||
|
/* Create the dialog */
|
||||||
|
GtkWidget* dialog = gtk_dialog_new_with_buttons(_("Editing Clipboard"), NULL,
|
||||||
|
(GTK_DIALOG_MODAL + GTK_DIALOG_NO_SEPARATOR),
|
||||||
|
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
|
||||||
|
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
|
||||||
|
|
||||||
|
gtk_window_set_default_size((GtkWindow*)dialog, 450, 300);
|
||||||
|
gtk_window_set_icon((GtkWindow*)dialog, gtk_widget_render_icon(dialog, GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU, NULL));
|
||||||
|
|
||||||
|
/* Build the scrolled window with the text view */
|
||||||
|
GtkWidget* scrolled_window = gtk_scrolled_window_new((GtkAdjustment*) gtk_adjustment_new(0, 0, 0, 0, 0, 0),
|
||||||
|
(GtkAdjustment*) gtk_adjustment_new(0, 0, 0, 0, 0, 0));
|
||||||
|
|
||||||
|
gtk_scrolled_window_set_policy((GtkScrolledWindow*)scrolled_window,
|
||||||
|
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||||
|
|
||||||
|
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrolled_window, TRUE, TRUE, 2);
|
||||||
|
GtkWidget* text_view = gtk_text_view_new_with_buffer(clipboard_buffer);
|
||||||
|
gtk_text_view_set_left_margin((GtkTextView*)text_view, 2);
|
||||||
|
gtk_text_view_set_right_margin((GtkTextView*)text_view, 2);
|
||||||
|
gtk_container_add((GtkContainer*)scrolled_window, text_view);
|
||||||
|
|
||||||
|
/* Run the dialog */
|
||||||
|
gtk_widget_show_all(dialog);
|
||||||
|
if (gtk_dialog_run((GtkDialog*)dialog) == GTK_RESPONSE_ACCEPT)
|
||||||
|
{
|
||||||
|
/* Save changes done to the clipboard */
|
||||||
|
GtkTextIter start, end;
|
||||||
|
gtk_text_buffer_get_start_iter(clipboard_buffer, &start);
|
||||||
|
gtk_text_buffer_get_end_iter(clipboard_buffer, &end);
|
||||||
|
|
||||||
|
/* Delete any duplicate */
|
||||||
|
delete_duplicate(gtk_text_buffer_get_text(clipboard_buffer, &start, &end, TRUE));
|
||||||
|
|
||||||
|
/* Insert new element before the old one */
|
||||||
|
history = g_slist_insert_before(history, element->next,
|
||||||
|
g_strdup(gtk_text_buffer_get_text(clipboard_buffer, &start, &end, TRUE))
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Remove old entry */
|
||||||
|
history = g_slist_remove(history, element->data);
|
||||||
|
|
||||||
|
if(selected_item_nr == 0)
|
||||||
|
{
|
||||||
|
GtkClipboard* clipboard;
|
||||||
|
clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
|
||||||
|
gtk_clipboard_set_text(clipboard,
|
||||||
|
gtk_text_buffer_get_text(clipboard_buffer, &start, &end, TRUE),
|
||||||
|
-1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gtk_widget_destroy(dialog);
|
||||||
|
g_string_free(s_selected_item, TRUE);
|
||||||
|
search_history();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called when Remove is selected from Manage dialog */
|
||||||
|
static void
|
||||||
|
remove_selected()
|
||||||
|
{
|
||||||
|
GtkTreeIter sel_iter;
|
||||||
|
GtkTreeSelection* search_selection = gtk_tree_view_get_selection((GtkTreeView*)treeview_search);
|
||||||
|
/* This checks if there's anything selected */
|
||||||
|
if (gtk_tree_selection_get_selected(search_selection, NULL, &sel_iter))
|
||||||
|
{
|
||||||
|
/* Get item to delete */
|
||||||
|
gint selected_item_nr;
|
||||||
|
gtk_tree_model_get((GtkTreeModel*)search_list, &sel_iter, 0, &selected_item_nr, -1);
|
||||||
|
GSList* element = g_slist_nth(history, selected_item_nr);
|
||||||
|
/* Remove entry */
|
||||||
|
history = g_slist_remove(history, element->data);
|
||||||
|
search_history();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
search_doubleclick()
|
search_doubleclick()
|
||||||
{
|
{
|
||||||
GtkTreeIter sel_iter;
|
GtkTreeIter sel_iter;
|
||||||
|
GtkTreeSelection* search_selection = gtk_tree_view_get_selection((GtkTreeView*)treeview_search);
|
||||||
/* Check if selected */
|
/* Check if selected */
|
||||||
if (gtk_tree_selection_get_selected(search_selection, NULL, &sel_iter))
|
if (gtk_tree_selection_get_selected(search_selection, NULL, &sel_iter))
|
||||||
{
|
{
|
||||||
gchar *selected_item;
|
gchar *selected_item;
|
||||||
gtk_tree_model_get((GtkTreeModel*)search_list, &sel_iter, 0, &selected_item, -1);
|
gtk_tree_model_get((GtkTreeModel*)search_list, &sel_iter, 1, &selected_item, -1);
|
||||||
GString* s_selected_item = g_string_new(selected_item);
|
GtkClipboard* prim = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
|
||||||
GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
|
GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
|
||||||
|
gtk_clipboard_set_text(prim, (gchar*)selected_item, -1);
|
||||||
gtk_clipboard_set_text(clip, (gchar*)selected_item, -1);
|
gtk_clipboard_set_text(clip, (gchar*)selected_item, -1);
|
||||||
g_free(selected_item);
|
g_free(selected_item);
|
||||||
g_string_free(s_selected_item, TRUE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,48 +272,6 @@ search_click(GtkWidget *widget, GdkEventButton *event, GtkWidget *search_window)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search through the history */
|
|
||||||
static void
|
|
||||||
search_history()
|
|
||||||
{
|
|
||||||
guint16 search_len = gtk_entry_get_text_length((GtkEntry*)search_entry);
|
|
||||||
gchar* search_input = g_strdup(gtk_entry_get_text((GtkEntry*)search_entry));
|
|
||||||
gchar* search_reg = g_regex_escape_string(search_input, search_len);
|
|
||||||
gchar* search_regex = g_strconcat (".*", search_reg, ".*", NULL);
|
|
||||||
GRegex* regex = g_regex_new(search_regex, G_REGEX_CASELESS, 0, NULL);
|
|
||||||
GtkTreeIter search_iter;
|
|
||||||
while(gtk_tree_model_get_iter_first((GtkTreeModel*)search_list, &search_iter))
|
|
||||||
gtk_list_store_remove(search_list, &search_iter);
|
|
||||||
/* Test if there is text in the search box */
|
|
||||||
if(search_len > 0)
|
|
||||||
{
|
|
||||||
if ((history != NULL) && (history->data != NULL))
|
|
||||||
{
|
|
||||||
/* Declare some variables */
|
|
||||||
GSList* element;
|
|
||||||
gint element_number = 0;
|
|
||||||
/* Go through each element and adding each */
|
|
||||||
for (element = history; element != NULL; element = element->next)
|
|
||||||
{
|
|
||||||
GString* string = g_string_new((gchar*)element->data);
|
|
||||||
gchar* compare = string->str;
|
|
||||||
gboolean result = g_regex_match(regex, compare, 0, NULL);
|
|
||||||
if(result)
|
|
||||||
{
|
|
||||||
GtkTreeIter row_iter;
|
|
||||||
gtk_list_store_append(search_list, &row_iter);
|
|
||||||
gtk_list_store_set(search_list, &row_iter, 0, string->str, -1);
|
|
||||||
}
|
|
||||||
/* Prepare for next item */
|
|
||||||
g_string_free(string, TRUE);
|
|
||||||
element_number++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_regex_unref(regex);
|
|
||||||
}
|
|
||||||
g_free(search_regex);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
search_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
|
search_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
|
||||||
{
|
{
|
||||||
@ -111,10 +281,23 @@ search_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
search_window_response(GtkDialog *dialog, gint response_id, gpointer user_data)
|
||||||
|
{
|
||||||
|
if(response_id < 0)
|
||||||
|
{
|
||||||
|
save_history();
|
||||||
|
gtk_widget_destroy((GtkWidget*)dialog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Shows the search dialog */
|
/* Shows the search dialog */
|
||||||
gboolean
|
gboolean
|
||||||
show_search()
|
show_search()
|
||||||
{
|
{
|
||||||
|
/* Prevent multiple instances */
|
||||||
|
if(gtk_grab_get_current())
|
||||||
|
return FALSE;
|
||||||
/* Declare some variables */
|
/* Declare some variables */
|
||||||
GtkWidget *frame, *label,
|
GtkWidget *frame, *label,
|
||||||
*alignment, *hbox,
|
*alignment, *hbox,
|
||||||
@ -123,15 +306,14 @@ show_search()
|
|||||||
GtkTreeViewColumn *tree_column;
|
GtkTreeViewColumn *tree_column;
|
||||||
|
|
||||||
/* Create the dialog */
|
/* Create the dialog */
|
||||||
GtkWidget* search_dialog = gtk_dialog_new_with_buttons(_("Search"), NULL,
|
GtkWidget* search_dialog = gtk_dialog_new();
|
||||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
||||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
|
|
||||||
|
|
||||||
gtk_window_set_icon((GtkWindow*)search_dialog, gtk_widget_render_icon(search_dialog, GTK_STOCK_FIND, GTK_ICON_SIZE_MENU, NULL));
|
gtk_window_set_icon((GtkWindow*)search_dialog, gtk_widget_render_icon(search_dialog, GTK_STOCK_FIND, GTK_ICON_SIZE_MENU, NULL));
|
||||||
|
gtk_window_set_title((GtkWindow*)search_dialog, "Manage History");
|
||||||
gtk_window_set_resizable((GtkWindow*)search_dialog, TRUE);
|
gtk_window_set_resizable((GtkWindow*)search_dialog, TRUE);
|
||||||
gtk_window_set_position((GtkWindow*)search_dialog, GTK_WIN_POS_CENTER);
|
gtk_window_set_position((GtkWindow*)search_dialog, GTK_WIN_POS_CENTER);
|
||||||
|
|
||||||
GtkWidget* vbox_search = gtk_vbox_new(FALSE, 12);
|
GtkWidget* vbox_search = gtk_vbox_new(FALSE, 10);
|
||||||
gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area (GTK_DIALOG(search_dialog))), vbox_search, TRUE, TRUE, 2);
|
gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area (GTK_DIALOG(search_dialog))), vbox_search, TRUE, TRUE, 2);
|
||||||
gtk_widget_set_size_request((GtkWidget*)vbox_search, 400, 600);
|
gtk_widget_set_size_request((GtkWidget*)vbox_search, 400, 600);
|
||||||
|
|
||||||
@ -148,29 +330,43 @@ show_search()
|
|||||||
|
|
||||||
gtk_scrolled_window_set_policy((GtkScrolledWindow*)scrolled_window_search, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
gtk_scrolled_window_set_policy((GtkScrolledWindow*)scrolled_window_search, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||||
gtk_scrolled_window_set_shadow_type((GtkScrolledWindow*)scrolled_window_search, GTK_SHADOW_ETCHED_OUT);
|
gtk_scrolled_window_set_shadow_type((GtkScrolledWindow*)scrolled_window_search, GTK_SHADOW_ETCHED_OUT);
|
||||||
GtkWidget* treeview_search = gtk_tree_view_new();
|
treeview_search = gtk_tree_view_new();
|
||||||
gtk_tree_view_set_reorderable((GtkTreeView*)treeview_search, TRUE);
|
|
||||||
gtk_tree_view_set_rules_hint((GtkTreeView*)treeview_search, TRUE);
|
gtk_tree_view_set_rules_hint((GtkTreeView*)treeview_search, TRUE);
|
||||||
search_list = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
|
search_list = gtk_list_store_new(2, G_TYPE_UINT, G_TYPE_STRING);
|
||||||
gtk_tree_view_set_model((GtkTreeView*)treeview_search, (GtkTreeModel*)search_list);
|
gtk_tree_view_set_model((GtkTreeView*)treeview_search, (GtkTreeModel*)search_list);
|
||||||
GtkCellRenderer* name_renderer_exclude = gtk_cell_renderer_text_new();
|
GtkCellRenderer* cell_renderer = gtk_cell_renderer_text_new();
|
||||||
g_object_set(name_renderer_exclude, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
tree_column = gtk_tree_view_column_new_with_attributes("ID", cell_renderer, NULL);
|
||||||
g_object_set(name_renderer_exclude, "single-paragraph-mode", TRUE, NULL);
|
gtk_tree_view_column_set_visible(tree_column, FALSE);
|
||||||
tree_column = gtk_tree_view_column_new_with_attributes(_("Results"), name_renderer_exclude, "text", 0, NULL);
|
gtk_tree_view_append_column((GtkTreeView*)treeview_search, tree_column);
|
||||||
gtk_tree_view_column_set_resizable(tree_column, TRUE);
|
cell_renderer = gtk_cell_renderer_text_new();
|
||||||
|
g_object_set(cell_renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||||
|
g_object_set(cell_renderer, "single-paragraph-mode", TRUE, NULL);
|
||||||
|
tree_column = gtk_tree_view_column_new_with_attributes("Results", cell_renderer, "text", 1, NULL);
|
||||||
gtk_tree_view_append_column((GtkTreeView*)treeview_search, tree_column);
|
gtk_tree_view_append_column((GtkTreeView*)treeview_search, tree_column);
|
||||||
gtk_container_add((GtkContainer*)scrolled_window_search, treeview_search);
|
gtk_container_add((GtkContainer*)scrolled_window_search, treeview_search);
|
||||||
gtk_box_pack_start((GtkBox*)vbox_search, scrolled_window_search, TRUE, TRUE, 0);
|
gtk_box_pack_start((GtkBox*)vbox_search, scrolled_window_search, TRUE, TRUE, 0);
|
||||||
|
|
||||||
search_selection = gtk_tree_view_get_selection((GtkTreeView*)treeview_search);
|
GtkWidget* edit_button = gtk_dialog_add_button((GtkDialog*)search_dialog, "Edit", 1);
|
||||||
|
g_signal_connect((GObject*)edit_button, "clicked", (GCallback)edit_selected, NULL);
|
||||||
|
GtkWidget* remove_button = gtk_dialog_add_button((GtkDialog*)search_dialog, "Remove", 1);
|
||||||
|
g_signal_connect((GObject*)remove_button, "clicked", (GCallback)remove_selected, NULL);
|
||||||
|
GtkWidget* close_button = gtk_dialog_add_button((GtkDialog*)search_dialog, "Close", GTK_RESPONSE_OK);
|
||||||
|
g_signal_connect((GObject*)close_button, "clicked", (GCallback)search_history, NULL);
|
||||||
|
|
||||||
|
GtkTreeSelection* search_selection = gtk_tree_view_get_selection((GtkTreeView*)treeview_search);
|
||||||
gtk_tree_selection_set_mode(search_selection, GTK_SELECTION_BROWSE);
|
gtk_tree_selection_set_mode(search_selection, GTK_SELECTION_BROWSE);
|
||||||
g_signal_connect((GObject*)treeview_search, "button_press_event", (GCallback)search_click, search_dialog);
|
g_signal_connect((GObject*)treeview_search, "button_press_event", (GCallback)search_click, search_dialog);
|
||||||
|
|
||||||
g_signal_connect((GtkDialog*)search_dialog, "response", (GCallback)gtk_widget_destroy, search_dialog);
|
g_signal_connect((GtkDialog*)search_dialog, "response", (GCallback)search_window_response, search_dialog);
|
||||||
gtk_widget_show_all(vbox_search);
|
gtk_widget_show_all(vbox_search);
|
||||||
|
|
||||||
/* show the dialog */
|
/* show the dialog */
|
||||||
gtk_widget_show_all((GtkWidget*)search_dialog);
|
gtk_widget_show_all((GtkWidget*)search_dialog);
|
||||||
|
gtk_widget_set_sensitive((GtkWidget*)search_dialog, TRUE);
|
||||||
|
gtk_grab_add((GtkWidget*)search_dialog);
|
||||||
|
|
||||||
|
/* Populate the list */
|
||||||
|
search_history();
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user