Advanced notification - Basic search function

Added following functionality:
  * Notification via vanishing pop-ups, different
    notification levels and changeable text2
  * Basic search function
  * Check file existence
  * Scroll to begin or bottom of a page

Fixes and other changes:
  * Fixed unnecessary high processor load
  * Fixed update status
  * Added variable for number of pages
This commit is contained in:
Moritz Lipp 2009-08-13 22:55:36 +02:00
parent 2754798c73
commit 1789541e78
2 changed files with 215 additions and 88 deletions

View File

@ -1,20 +1,29 @@
static const float ZOOM_STEP = 0.1;
static const float SCROLL_STEP = 40;
/* settings */
static const int SHOW_NOTIFICATION = 5;
static const float ZOOM_STEP = 0.1;
static const float SCROLL_STEP = 40;
/* look */
static const char font[] = "monospace normal 9";
static const char default_bgcolor[] = "#141414";
static const char default_fgcolor[] = "#CCCCCC";
static const char notification_fgcolor[] = "#0F0F0F";
static const char notification_bgcolor[] = "#F9F9F9";
static const char notification_warning_fgcolor[] = "2222222";
static const char notification_warning_bgcolor[] = "#E8E62E";
static const char notification_error_fgcolor[] = "#CCCCCC";
static const char notification_error_bgcolor[] = "#B82121";
static const char inputbar_bgcolor[] = "#141414";
static const char inputbar_fgcolor[] = "#9FBC00";
static const char inputbar_wn_fgcolor[] = "#CCCCCC";
static const char inputbar_wn_bgcolor[] = "#B82121";
static const char completion_fgcolor[] = "#CCCCCC";
static const char completion_bgcolor[] = "#232323";
static const char completion_hl_fgcolor[] = "#232323";
static const char completion_hl_bgcolor[] = "#9FBC00";
/* shortcuts */
Shortcut shortcuts[] = {
// mask, key, function, argument
{GDK_CONTROL_MASK, GDK_f, sc_navigate, { NEXT } },
@ -24,11 +33,16 @@ Shortcut shortcuts[] = {
{GDK_CONTROL_MASK, GDK_0, sc_zoom, { ZOOM_ORIGINAL } },
{GDK_CONTROL_MASK, GDK_r, sc_rotate, { RIGHT } },
{GDK_CONTROL_MASK, GDK_e, sc_rotate, { LEFT } },
{GDK_CONTROL_MASK, GDK_q, sc_quit, {0} },
{GDK_CONTROL_MASK, GDK_p, sc_print, {0} },
{GDK_CONTROL_MASK, GDK_q, sc_quit, {0} },
{0, GDK_n, sc_search, { FORWARD } },
{0, GDK_N, sc_search, { BACKWARD } },
{0, GDK_h, sc_scroll, { LEFT } },
{0, GDK_j, sc_scroll, { DOWN } },
{0, GDK_k, sc_scroll, { UP } },
{0, GDK_l, sc_scroll, { RIGHT } },
{0, GDK_Page_Up, sc_scroll, { TOP } },
{0, GDK_Page_Down, sc_scroll, { BOTTOM } },
{0, GDK_i, sc_adjust_window, { ADJUST_BESTFIT } },
{0, GDK_u, sc_adjust_window, { ADJUST_WIDTH } },
{0, GDK_colon, sc_focus_inputbar, { .data = ":" } },
@ -39,6 +53,7 @@ Shortcut shortcuts[] = {
{0, GDK_slash, sc_focus_inputbar, { .data = "/" } },
};
/* commands */
Command commands[] = {
// command, function
{"g", cmd_goto},

278
zathura.c
View File

@ -1,5 +1,6 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <poppler/glib/poppler.h>
#include <cairo.h>
@ -12,8 +13,8 @@
/* enums */
enum { UP, DOWN, LEFT, RIGHT, ZOOM_IN, ZOOM_OUT, ZOOM_ORIGINAL,
NEXT, PREVIOUS, HIDE, ERROR, WARNING, DEFAULT,
ADJUST_BESTFIT, ADJUST_WIDTH };
NEXT, PREVIOUS, HIDE, ERROR, WARNING, DEFAULT, TOP, BOTTOM,
ADJUST_BESTFIT, ADJUST_WIDTH, FORWARD, BACKWARD };
struct
{
@ -21,6 +22,7 @@ struct
GtkBox *box;
GtkScrolledWindow *view;
GtkWidget *drawing_area;
GtkBox *notification;
GtkEntry *inputbar;
struct
@ -29,8 +31,12 @@ struct
GdkColor default_bg;
GdkColor inputbar_fg;
GdkColor inputbar_bg;
GdkColor inputbar_wn_fg;
GdkColor inputbar_wn_bg;
GdkColor notification_fg;
GdkColor notification_bg;
GdkColor notification_wn_fg;
GdkColor notification_wn_bg;
GdkColor notification_er_fg;
GdkColor notification_er_bg;
GdkColor completion_fg;
GdkColor completion_bg;
GdkColor completion_hl_fg;
@ -42,11 +48,12 @@ struct
{
PopplerDocument *document;
PopplerPage *page;
char *file;
cairo_surface_t *surface;
int page_number;
int number_of_pages;
double scale;
int rotate;
cairo_surface_t *surface;
char *file;
} PDF;
} Zathura;
@ -74,11 +81,14 @@ typedef struct
/* function declarations */
void init();
void update_title();
void update_status(int, char*);
void update_status();
void set_page(int);
void draw();
void hilight_result(PopplerRectangle*);
gboolean complete(Argument*);
gboolean delete_widget(gpointer);
GtkLabel* notify(int, char*);
/* shortcut declarations */
void sc_focus_inputbar(Argument*);
@ -87,13 +97,14 @@ void sc_navigate(Argument*);
void sc_zoom(Argument*);
void sc_adjust_window(Argument*);
void sc_rotate(Argument*);
void sc_search(Argument*);
void sc_print(Argument*);
void sc_quit(Argument*);
/* command declarations */
void cmd_goto(int, char**);
void cmd_open(int, char**);
void cmd_rotate(int, char**);
void cmd_search(int, char**);
void cmd_quit(int, char**);
void cmd_zoom(int, char**);
@ -115,16 +126,20 @@ void
init()
{
/* settings */
gdk_color_parse(default_fgcolor, &(Zathura.Settings.default_fg));
gdk_color_parse(default_bgcolor, &(Zathura.Settings.default_bg));
gdk_color_parse(inputbar_fgcolor, &(Zathura.Settings.inputbar_fg));
gdk_color_parse(inputbar_bgcolor, &(Zathura.Settings.inputbar_bg));
gdk_color_parse(inputbar_wn_fgcolor, &(Zathura.Settings.inputbar_wn_fg));
gdk_color_parse(inputbar_wn_bgcolor, &(Zathura.Settings.inputbar_wn_bg));
gdk_color_parse(completion_fgcolor, &(Zathura.Settings.completion_fg));
gdk_color_parse(completion_bgcolor, &(Zathura.Settings.completion_bg));
gdk_color_parse(completion_hl_fgcolor, &(Zathura.Settings.completion_hl_fg));
gdk_color_parse(completion_hl_bgcolor, &(Zathura.Settings.completion_hl_bg));
gdk_color_parse(default_fgcolor, &(Zathura.Settings.default_fg));
gdk_color_parse(default_bgcolor, &(Zathura.Settings.default_bg));
gdk_color_parse(inputbar_fgcolor, &(Zathura.Settings.inputbar_fg));
gdk_color_parse(inputbar_bgcolor, &(Zathura.Settings.inputbar_bg));
gdk_color_parse(notification_fgcolor, &(Zathura.Settings.notification_fg));
gdk_color_parse(notification_bgcolor, &(Zathura.Settings.notification_bg));
gdk_color_parse(notification_warning_fgcolor, &(Zathura.Settings.notification_wn_fg));
gdk_color_parse(notification_warning_bgcolor, &(Zathura.Settings.notification_wn_bg));
gdk_color_parse(notification_error_fgcolor, &(Zathura.Settings.notification_er_fg));
gdk_color_parse(notification_error_bgcolor, &(Zathura.Settings.notification_er_bg));
gdk_color_parse(completion_fgcolor, &(Zathura.Settings.completion_fg));
gdk_color_parse(completion_bgcolor, &(Zathura.Settings.completion_bg));
gdk_color_parse(completion_hl_fgcolor, &(Zathura.Settings.completion_hl_fg));
gdk_color_parse(completion_hl_bgcolor, &(Zathura.Settings.completion_hl_bg));
Zathura.Settings.font = pango_font_description_from_string(font);
/* variables */
@ -132,6 +147,7 @@ init()
Zathura.box = GTK_BOX(gtk_vbox_new(FALSE, 0));
Zathura.view = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL));
Zathura.drawing_area = gtk_drawing_area_new();
Zathura.notification = GTK_BOX(gtk_vbox_new(FALSE, 0));
Zathura.inputbar = GTK_ENTRY(gtk_entry_new());
Zathura.PDF.scale = 1.0;
Zathura.PDF.rotate = 0;
@ -148,16 +164,16 @@ init()
/* view */
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(Zathura.view), Zathura.drawing_area);
g_signal_connect(G_OBJECT(Zathura.view), "key-press-event", G_CALLBACK(cb_view_key_pressed), NULL);
/* drawing area */
g_signal_connect(G_OBJECT(Zathura.drawing_area), "expose-event", G_CALLBACK(cb_draw), NULL);
#ifdef SHOW_SCROLLBARS
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(Zathura.view), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
#else
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(Zathura.view), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
#endif
/* drawing area */
g_signal_connect(G_OBJECT(Zathura.drawing_area), "expose-event", G_CALLBACK(cb_draw), NULL);
/* inputbar */
gtk_entry_set_inner_border(Zathura.inputbar, NULL);
gtk_entry_set_has_frame(Zathura.inputbar, FALSE);
@ -168,8 +184,9 @@ init()
g_signal_connect(G_OBJECT(Zathura.inputbar), "key-release-event", G_CALLBACK(cb_inputbar_key_released), NULL);
/* packing */
gtk_box_pack_start(Zathura.box, GTK_WIDGET(Zathura.view), TRUE, TRUE, 0);
gtk_box_pack_end(Zathura.box, GTK_WIDGET(Zathura.inputbar), FALSE, FALSE, 0);
gtk_box_pack_start(Zathura.box, GTK_WIDGET(Zathura.view), TRUE, TRUE, 0);
gtk_box_pack_start(Zathura.box, GTK_WIDGET(Zathura.notification), FALSE, FALSE, 0);
gtk_box_pack_end(Zathura.box, GTK_WIDGET(Zathura.inputbar), FALSE, FALSE, 0);
/* visuals */
gtk_widget_modify_base(GTK_WIDGET(Zathura.inputbar), GTK_STATE_NORMAL, &(Zathura.Settings.inputbar_bg));
@ -181,34 +198,56 @@ void
update_title()
{
if(Zathura.PDF.file != NULL)
gtk_window_set_title(GTK_WINDOW(Zathura.window), Zathura.PDF.file + strlen("file://"));
gtk_window_set_title(GTK_WINDOW(Zathura.window), Zathura.PDF.file);
else
gtk_window_set_title(GTK_WINDOW(Zathura.window), "zathura");
}
void
update_status(int level, char* text)
GtkLabel*
notify(int level, char* text)
{
GtkLabel *message = GTK_LABEL(gtk_label_new(text));
GtkEventBox *view = GTK_EVENT_BOX(gtk_event_box_new());
gtk_misc_set_alignment(GTK_MISC(message), 0, 0);
gtk_widget_modify_font(GTK_WIDGET(message), Zathura.Settings.font);
if(level == WARNING)
{
gtk_widget_modify_text(GTK_WIDGET(Zathura.inputbar), GTK_STATE_NORMAL, &(Zathura.Settings.inputbar_wn_fg));
gtk_widget_modify_base(GTK_WIDGET(Zathura.inputbar), GTK_STATE_NORMAL, &(Zathura.Settings.inputbar_wn_bg));
gtk_widget_modify_fg(GTK_WIDGET(message), GTK_STATE_NORMAL, &(Zathura.Settings.notification_wn_fg));
gtk_widget_modify_bg(GTK_WIDGET(view), GTK_STATE_NORMAL, &(Zathura.Settings.notification_wn_bg));
}
else if(level == DEFAULT)
else if(level == ERROR)
{
gtk_widget_modify_text(GTK_WIDGET(Zathura.inputbar), GTK_STATE_NORMAL, &(Zathura.Settings.inputbar_fg));
gtk_widget_modify_base(GTK_WIDGET(Zathura.inputbar), GTK_STATE_NORMAL, &(Zathura.Settings.inputbar_bg));
gtk_widget_modify_fg(GTK_WIDGET(message), GTK_STATE_NORMAL, &(Zathura.Settings.notification_er_fg));
gtk_widget_modify_bg(GTK_WIDGET(view), GTK_STATE_NORMAL, &(Zathura.Settings.notification_er_bg));
}
else
{
gtk_widget_modify_fg(GTK_WIDGET(message), GTK_STATE_NORMAL, &(Zathura.Settings.notification_fg));
gtk_widget_modify_bg(GTK_WIDGET(view), GTK_STATE_NORMAL, &(Zathura.Settings.notification_bg));
}
if(text == (char*) "")
gtk_container_add(GTK_CONTAINER(view), GTK_WIDGET(message));
gtk_container_add(GTK_CONTAINER(Zathura.notification), GTK_WIDGET(view));
gtk_widget_show_all(GTK_WIDGET(Zathura.window));
g_timeout_add_seconds(SHOW_NOTIFICATION, delete_widget, GTK_WIDGET(GTK_WIDGET(view)));
return message;
}
void
update_status()
{
char* text = "";
if(Zathura.PDF.document && Zathura.PDF.page)
{
if(Zathura.PDF.document && Zathura.PDF.page)
{
char* show_page = g_strdup_printf("[%i/%i]", Zathura.PDF.page_number + 1,
poppler_document_get_n_pages(Zathura.PDF.document));
char* filename = Zathura.PDF.file + strlen("file://");
text = g_strdup_printf("%s %s", show_page, filename);
}
char* show_page = g_strdup_printf("[%i/%i]", Zathura.PDF.page_number + 1,
Zathura.PDF.number_of_pages);
text = g_strdup_printf("%s %s", show_page, Zathura.PDF.file);
}
gtk_entry_set_text(Zathura.inputbar, text);
@ -216,9 +255,9 @@ update_status(int level, char* text)
void set_page(int page_number)
{
if(page_number > poppler_document_get_n_pages(Zathura.PDF.document))
if(page_number > Zathura.PDF.number_of_pages)
{
update_status(WARNING, "Error: Could not open page");
notify(WARNING, "Could not open page");
return;
}
@ -292,10 +331,23 @@ draw()
gtk_widget_queue_draw(Zathura.drawing_area);
}
void
hilight_result(PopplerRectangle* rectangle)
{
}
gboolean
delete_widget(gpointer data)
{
gtk_widget_destroy(GTK_WIDGET(data));
return FALSE;
}
gboolean
complete(Argument* argument)
{
static GtkBox *results;
static GtkWidget **result_rows;
static char **command_names;
@ -432,8 +484,12 @@ sc_scroll(Argument *argument)
gdouble value = gtk_adjustment_get_value(adjustment);
gdouble max = gtk_adjustment_get_upper(adjustment) - view_size;
if((argument->n == LEFT) || (argument->n == DOWN))
if( (argument->n == LEFT) || (argument->n == DOWN))
gtk_adjustment_set_value(adjustment, (value - SCROLL_STEP) < 0 ? 0 : (value - SCROLL_STEP));
else if (argument->n == TOP)
gtk_adjustment_set_value(adjustment, 0);
else if(argument->n == BOTTOM)
gtk_adjustment_set_value(adjustment, max);
else
gtk_adjustment_set_value(adjustment, (value + SCROLL_STEP) > max ? max : (value + SCROLL_STEP));
}
@ -449,11 +505,15 @@ sc_navigate(Argument *argument)
else if(argument->n == PREVIOUS)
new_page = abs( (new_page + number_of_pages - 1) % number_of_pages);
Zathura.PDF.page = poppler_document_get_page(Zathura.PDF.document, new_page);
Zathura.PDF.page_number = new_page;
update_status(DEFAULT, "");
set_page(new_page);
Argument reset;
reset.n = TOP;
sc_scroll(&reset);
draw();
update_status();
}
void
@ -504,6 +564,60 @@ sc_rotate(Argument *argument)
draw();
}
void
sc_search(Argument *argument)
{
static char* search_item;
static int direction;
int page_counter;
GList* results;
GList* list;
if(argument->data)
search_item = (char*) argument->data;
if(!Zathura.PDF.document || !Zathura.PDF.page || !search_item)
return;
/* search document */
GtkLabel* search_status = notify(DEFAULT, "Searching...");
if(argument->n)
direction = (argument->n == BACKWARD) ? -1 : 1;
for(page_counter = 0; page_counter < Zathura.PDF.number_of_pages; page_counter++)
{
int next_page = (Zathura.PDF.page_number + page_counter * direction) % Zathura.PDF.number_of_pages;
set_page(next_page);
results = poppler_page_find_text(Zathura.PDF.page, search_item);
if(results)
break;
}
/* draw results */
if(results)
{
draw();
gtk_label_set_text(search_status, g_strdup_printf("%s found on page %i for %i time(s)",
search_item, Zathura.PDF.page_number, g_list_length(results)));
for(list = results; list && list->data; list = g_list_next(list))
{
hilight_result((PopplerRectangle*) list->data);
}
}
else
gtk_label_set_text(search_status, g_strdup_printf("No match for %s", search_item));
}
void
sc_print(Argument *argument)
{
}
void
sc_quit(Argument *argument)
{
@ -519,24 +633,31 @@ cmd_open(int argc, char** argv)
gchar* file;
if(!g_file_test(argv[0], G_FILE_TEST_EXISTS))
{
notify(ERROR, "File does not exist");
return;
}
if(g_ascii_strncasecmp(argv[0], "file://", strlen("file://")) == 0)
file = g_strdup(argv[0]);
else
file = g_filename_to_uri(argv[0], NULL, NULL);
Zathura.PDF.document = poppler_document_new_from_file(file, (argc == 2) ? argv[1] : NULL, NULL);
if(!Zathura.PDF.document)
{
printf("Error: Could not open file %s\n", file);
notify(WARNING, "Can not open file");
return;
}
Zathura.PDF.file = file;
Zathura.PDF.number_of_pages = poppler_document_get_n_pages(Zathura.PDF.document);
Zathura.PDF.file = file + strlen("file://");
set_page(0);
draw();
update_status(DEFAULT, "");
update_status();
update_title();
}
@ -547,7 +668,15 @@ cmd_goto(int argc, char** argv)
return;
int page = atoi(argv[0]);;
set_page(page);
set_page(page - 1);
Argument argument;
argument.n = TOP;
sc_scroll(&argument);
draw();
update_status();
}
void
@ -568,24 +697,6 @@ cmd_rotate(int argc, char** argv)
sc_rotate(&argument);
}
void
cmd_search(int argc, char** argv)
{
if(!Zathura.PDF.document || !Zathura.PDF.page || !argv[0])
return;
GList* results = poppler_page_find_text(Zathura.PDF.page, argv[0]);
GList* list;
if(results)
{
for(list = results; list && list->data; list = g_list_next(list))
{
//PopplerRectangle *rectangle = (PopplerRectangle*) list->data;
}
}
}
void
cmd_zoom(int argc, char** argv)
{
@ -612,8 +723,6 @@ cb_draw(GtkWidget *widget, gpointer data)
{
gdk_window_clear(widget->window);
draw();
cairo_t *cairo = gdk_cairo_create(widget->window);
cairo_set_source_surface(cairo, Zathura.PDF.surface, 0, 0);
cairo_paint(cairo);
@ -661,11 +770,13 @@ cb_inputbar_activate(GtkEntry* entry, gpointer data)
// special command
if(*tokens[0] == '/')
{
char *term = (char*) gtk_entry_get_text(entry) + 1;
cmd_search(1, &term);
Argument argument;
argument.data = (char*) gtk_entry_get_text(entry) + 1;
argument.n = -1;
sc_search(&argument);
g_strfreev(tokens);
update_status();
gtk_widget_grab_focus(GTK_WIDGET(Zathura.view));
update_status(DEFAULT, "");
return;
}
@ -681,10 +792,9 @@ cb_inputbar_activate(GtkEntry* entry, gpointer data)
}
if(!success)
update_status(WARNING, "Not a valid command");
else
update_status(DEFAULT, "");
notify(ERROR, g_strdup_printf("\"%s\" is not a valid command", command));
update_status();
g_strfreev(tokens);
gtk_widget_grab_focus(GTK_WIDGET(Zathura.view));
}
@ -696,8 +806,9 @@ cb_inputbar_button_pressed(GtkWidget* widget, GdkEventButton* event, gpointer da
{
gtk_widget_modify_text(GTK_WIDGET(Zathura.inputbar), GTK_STATE_NORMAL, &(Zathura.Settings.inputbar_fg));
gtk_widget_modify_base(GTK_WIDGET(Zathura.inputbar), GTK_STATE_NORMAL, &(Zathura.Settings.inputbar_bg));
gtk_editable_set_position(GTK_EDITABLE(Zathura.inputbar), -1);
gtk_widget_grab_focus(GTK_WIDGET(Zathura.inputbar));
gtk_entry_set_text(Zathura.inputbar, "");
gtk_editable_set_position(GTK_EDITABLE(Zathura.inputbar), -1);
}
}
@ -710,7 +821,6 @@ cb_inputbar_key_pressed(GtkEntry* entry, GdkEventKey *event, gpointer data)
{
case GDK_Escape:
gtk_widget_grab_focus(GTK_WIDGET(Zathura.view));
update_status(DEFAULT, "");
argument.n = HIDE;
return complete(&argument);
case GDK_Tab:
@ -738,8 +848,10 @@ cb_inputbar_key_released(GtkEntry *entry, GdkEventKey *event, gpointer data)
}
else if(length > 1 && text[0] == '/')
{
char *term = text + 1;
cmd_search(1, &term);
Argument argument;
argument.data = (char*) text + 1;
argument.n = -1;
sc_search(&argument);
gtk_widget_grab_focus(GTK_WIDGET(Zathura.inputbar));
gtk_editable_set_position(GTK_EDITABLE(Zathura.inputbar), -1);
}