mirror of
https://gitlab.gnome.org/GNOME/gitg
synced 2024-10-01 05:33:49 +00:00
Factored window stuff in new GitgWindow
GitgWindow now provides most of the control (moved from gitg.c). The main gitg.c now just handles parsing arguments and creating the main window
This commit is contained in:
parent
b52ff4053c
commit
4edfff76a6
|
@ -14,6 +14,7 @@ INCLUDES = \
|
|||
|
||||
gitg_SOURCES = \
|
||||
gitg.c \
|
||||
gitg-window.c \
|
||||
gitg-revision.c \
|
||||
gitg-repository.c \
|
||||
gitg-runner.c \
|
||||
|
|
|
@ -51,6 +51,9 @@ update_markup(GObject *object)
|
|||
static void
|
||||
gitg_revision_view_parser_finished(GtkBuildable *buildable, GtkBuilder *builder)
|
||||
{
|
||||
if (parent_iface.parser_finished)
|
||||
parent_iface.parser_finished(buildable, builder);
|
||||
|
||||
GitgRevisionView *rvv = GITG_REVISION_VIEW(buildable);
|
||||
|
||||
rvv->priv->sha = GTK_LABEL(gtk_builder_get_object(builder, "label_sha"));
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--Generated with glade3 3.4.2 on Thu Jun 26 12:26:40 2008 -->
|
||||
<interface>
|
||||
<object class="GtkWindow" id="window">
|
||||
<object class="GitgWindow" id="window">
|
||||
<property name="title" translatable="yes">GitG</property>
|
||||
<property name="default_width">800</property>
|
||||
<property name="default_height">600</property>
|
||||
|
@ -41,6 +41,48 @@
|
|||
<property name="rules_hint">True</property>
|
||||
<property name="search_column">1</property>
|
||||
<property name="fixed_height_mode">True</property>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="rv_column1">
|
||||
<property name="title" translatable="yes">Subject</property>
|
||||
<property name="fixed-width">400</property>
|
||||
<property name="sizing">GTK_TREE_VIEW_COLUMN_FIXED</property>
|
||||
<property name="resizable">True</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="rv_renderer_subject"/>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="rv_column2">
|
||||
<property name="title" translatable="yes">Author</property>
|
||||
<property name="fixed-width">200</property>
|
||||
<property name="sizing">GTK_TREE_VIEW_COLUMN_FIXED</property>
|
||||
<property name="resizable">True</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="rv_renderer_author"/>
|
||||
<attributes>
|
||||
<attribute name="text">2</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="rv_column3">
|
||||
<property name="title" translatable="yes">Date</property>
|
||||
<property name="fixed-width">200</property>
|
||||
<property name="sizing">GTK_TREE_VIEW_COLUMN_FIXED</property>
|
||||
<property name="resizable">True</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="rv_renderer_date"/>
|
||||
<attributes>
|
||||
<attribute name="text">3</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
|
311
gitg/gitg-window.c
Normal file
311
gitg/gitg-window.c
Normal file
|
@ -0,0 +1,311 @@
|
|||
#include <gdk/gdkkeysyms.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "sexy-icon-entry.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "gitg-utils.h"
|
||||
#include "gitg-window.h"
|
||||
#include "gitg-revision-view.h"
|
||||
|
||||
#define GITG_WINDOW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_WINDOW, GitgWindowPrivate))
|
||||
|
||||
struct _GitgWindowPrivate
|
||||
{
|
||||
GitgRepository *repository;
|
||||
|
||||
// Widget placeholders
|
||||
GtkTreeView *tree_view;
|
||||
GtkStatusbar *statusbar;
|
||||
GitgRevisionView *revision_view;
|
||||
GtkWidget *search_popup;
|
||||
};
|
||||
|
||||
static void gitg_window_buildable_iface_init(GtkBuildableIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED(GitgWindow, gitg_window, GTK_TYPE_WINDOW, 0,
|
||||
G_IMPLEMENT_INTERFACE(GTK_TYPE_BUILDABLE, gitg_window_buildable_iface_init));
|
||||
|
||||
GtkBuildableIface parent_iface = { 0, };
|
||||
|
||||
static void
|
||||
gitg_window_finalize(GObject *object)
|
||||
{
|
||||
GitgWindow *self = GITG_WINDOW(object);
|
||||
|
||||
G_OBJECT_CLASS(gitg_window_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void
|
||||
on_selection_changed(GtkTreeSelection *selection, GitgWindow *window)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
GitgRevision *revision = NULL;
|
||||
|
||||
if (gtk_tree_selection_get_selected(selection, &model, &iter))
|
||||
gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &revision, -1);
|
||||
|
||||
gitg_revision_view_update(window->priv->revision_view, window->priv->repository, revision);
|
||||
}
|
||||
|
||||
static void
|
||||
on_search_icon_pressed(SexyIconEntry *entry, SexyIconEntryPosition icon_pos, int button, GitgWindow *window)
|
||||
{
|
||||
gtk_menu_popup(GTK_MENU(window->priv->search_popup), NULL, NULL, NULL, NULL, button, gtk_get_current_event_time());
|
||||
}
|
||||
|
||||
void
|
||||
search_column_activate(GtkAction *action, gint column, GtkTreeView *tree_view)
|
||||
{
|
||||
if (!gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)))
|
||||
return;
|
||||
|
||||
gtk_tree_view_set_search_column(tree_view, column);
|
||||
}
|
||||
|
||||
void
|
||||
on_subject_activate(GtkAction *action, GitgWindow *window)
|
||||
{
|
||||
search_column_activate(action, 1, window->priv->tree_view);
|
||||
}
|
||||
|
||||
void
|
||||
on_author_activate(GtkAction *action, GitgWindow *window)
|
||||
{
|
||||
search_column_activate(action, 2, window->priv->tree_view);
|
||||
}
|
||||
|
||||
void
|
||||
on_date_activate(GtkAction *action, GitgWindow *window)
|
||||
{
|
||||
search_column_activate(action, 3, window->priv->tree_view);
|
||||
}
|
||||
|
||||
void
|
||||
on_hash_activate(GtkAction *action, GitgWindow *window)
|
||||
{
|
||||
search_column_activate(action, 4, window->priv->tree_view);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
search_hash_equal_func(GtkTreeModel *model, gchar const *key, GtkTreeIter *iter)
|
||||
{
|
||||
GitgRevision *rv;
|
||||
gtk_tree_model_get(model, iter, 0, &rv, -1);
|
||||
|
||||
gchar *sha = gitg_revision_get_sha1(rv);
|
||||
|
||||
gboolean ret = strncmp(sha, key, strlen(key)) != 0;
|
||||
|
||||
g_free(sha);
|
||||
g_object_unref(rv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
search_equal_func(GtkTreeModel *model, gint column, gchar const *key, GtkTreeIter *iter, gpointer userdata)
|
||||
{
|
||||
if (column == 4)
|
||||
return search_hash_equal_func(model, key, iter);
|
||||
|
||||
gchar *cmp;
|
||||
gtk_tree_model_get(model, iter, column, &cmp, -1);
|
||||
|
||||
gchar *s1 = g_utf8_casefold(key, -1);
|
||||
gchar *s2 = g_utf8_casefold(cmp, -1);
|
||||
|
||||
gboolean ret = strstr(s2, s1) == NULL;
|
||||
|
||||
g_free(s1);
|
||||
g_free(s2);
|
||||
|
||||
g_free(cmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
focus_search(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType modifier, gpointer userdata)
|
||||
{
|
||||
gtk_widget_grab_focus(GTK_WIDGET(userdata));
|
||||
}
|
||||
|
||||
static void
|
||||
build_search_entry(GitgWindow *window, GtkBuilder *builder)
|
||||
{
|
||||
GtkWidget *box = GTK_WIDGET(gtk_builder_get_object(builder, "hbox_top"));
|
||||
GtkWidget *entry = sexy_icon_entry_new();
|
||||
|
||||
GtkImage *image = GTK_IMAGE(gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU));
|
||||
sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(entry), SEXY_ICON_ENTRY_PRIMARY, image);
|
||||
|
||||
gtk_tree_view_set_search_entry(window->priv->tree_view, GTK_ENTRY(entry));
|
||||
gtk_widget_show(entry);
|
||||
gtk_box_pack_end(GTK_BOX(box), entry, FALSE, FALSE, 0);
|
||||
|
||||
GtkBuilder *b = gtk_builder_new();
|
||||
gtk_builder_set_translation_domain(b, GETTEXT_PACKAGE);
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gtk_builder_add_from_file(b, GITG_UI_DIR "/gitg-menus.xml", &error))
|
||||
{
|
||||
g_critical("Could not open UI file: %s (%s)", GITG_UI_DIR "/gitg-menus.xml", error->message);
|
||||
g_error_free(error);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
GtkUIManager *manager = GTK_UI_MANAGER(gtk_builder_get_object(b, "uiman"));
|
||||
window->priv->search_popup = GTK_WIDGET(g_object_ref(gtk_ui_manager_get_widget(manager, "/ui/search_popup")));
|
||||
|
||||
gtk_builder_connect_signals(b, window);
|
||||
g_object_unref(b);
|
||||
|
||||
g_signal_connect(entry, "icon-pressed", G_CALLBACK(on_search_icon_pressed), window);
|
||||
gtk_tree_view_set_search_column(window->priv->tree_view, 1);
|
||||
|
||||
gtk_tree_view_set_search_equal_func(window->priv->tree_view, search_equal_func, window, NULL);
|
||||
|
||||
GtkAccelGroup *group = gtk_accel_group_new();
|
||||
|
||||
GClosure *closure = g_cclosure_new(G_CALLBACK(focus_search), entry, NULL);
|
||||
gtk_accel_group_connect(group, GDK_f, GDK_CONTROL_MASK, 0, closure);
|
||||
gtk_window_add_accel_group(GTK_WINDOW(window), group);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_parent_activated(GitgRevisionView *view, gchar *hash, GitgWindow *window)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (!gitg_repository_find_by_hash(window->priv->repository, hash, &iter))
|
||||
return FALSE;
|
||||
|
||||
gtk_tree_selection_select_iter(gtk_tree_view_get_selection(window->priv->tree_view), &iter);
|
||||
GtkTreePath *path;
|
||||
|
||||
path = gtk_tree_model_get_path(GTK_TREE_MODEL(window->priv->repository), &iter);
|
||||
|
||||
gtk_tree_view_scroll_to_cell(window->priv->tree_view, path, NULL, FALSE, 0, 0);
|
||||
gtk_tree_path_free(path);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gitg_window_parser_finished(GtkBuildable *buildable, GtkBuilder *builder)
|
||||
{
|
||||
if (parent_iface.parser_finished)
|
||||
parent_iface.parser_finished(buildable, builder);
|
||||
|
||||
// Store widgets
|
||||
GitgWindow *window = GITG_WINDOW(buildable);
|
||||
window->priv->tree_view = GTK_TREE_VIEW(gtk_builder_get_object(builder, "tree_view_rv"));
|
||||
window->priv->statusbar = GTK_STATUSBAR(gtk_builder_get_object(builder, "statusbar"));
|
||||
window->priv->revision_view = GITG_REVISION_VIEW(gtk_builder_get_object(builder, "revision_view"));
|
||||
|
||||
// Create search entry
|
||||
build_search_entry(window, builder);
|
||||
|
||||
// Connect signals
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(window->priv->tree_view);
|
||||
g_signal_connect(selection, "changed", G_CALLBACK(on_selection_changed), window);
|
||||
g_signal_connect(window->priv->revision_view, "parent-activated", G_CALLBACK(on_parent_activated), window);
|
||||
}
|
||||
|
||||
static void
|
||||
gitg_window_buildable_iface_init(GtkBuildableIface *iface)
|
||||
{
|
||||
parent_iface = *iface;
|
||||
|
||||
iface->parser_finished = gitg_window_parser_finished;
|
||||
}
|
||||
|
||||
static void
|
||||
gitg_window_class_init(GitgWindowClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->finalize = gitg_window_finalize;
|
||||
|
||||
g_type_class_add_private(object_class, sizeof(GitgWindowPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
gitg_window_init(GitgWindow *self)
|
||||
{
|
||||
self->priv = GITG_WINDOW_GET_PRIVATE(self);
|
||||
}
|
||||
|
||||
static void
|
||||
on_begin_loading(GitgRunner *loader, GitgWindow *window)
|
||||
{
|
||||
GdkCursor *cursor = gdk_cursor_new(GDK_WATCH);
|
||||
gdk_window_set_cursor(GTK_WIDGET(window->priv->tree_view)->window, cursor);
|
||||
gdk_cursor_unref(cursor);
|
||||
|
||||
gtk_statusbar_push(window->priv->statusbar, 0, _("Begin loading repository"));
|
||||
}
|
||||
|
||||
static void
|
||||
on_end_loading(GitgRunner *loader, GitgWindow *window)
|
||||
{
|
||||
gchar *msg = g_strdup_printf(_("Loaded %d revisions"), gtk_tree_model_iter_n_children(GTK_TREE_MODEL(window->priv->repository), NULL));
|
||||
|
||||
gtk_statusbar_push(window->priv->statusbar, 0, msg);
|
||||
|
||||
g_free(msg);
|
||||
gdk_window_set_cursor(GTK_WIDGET(window->priv->tree_view)->window, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
on_update(GitgRunner *loader, gchar **revisions, GitgWindow *window)
|
||||
{
|
||||
gchar *msg = g_strdup_printf(_("Loading %d revisions..."), gtk_tree_model_iter_n_children(GTK_TREE_MODEL(window->priv->repository), NULL));
|
||||
|
||||
gtk_statusbar_push(window->priv->statusbar, 0, msg);
|
||||
g_free(msg);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_no_gitdir(GitgWindow *window)
|
||||
{
|
||||
GtkWidget *dlg = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Gitg repository could not be found"));
|
||||
|
||||
gtk_dialog_run(GTK_DIALOG(dlg));
|
||||
gtk_widget_destroy(dlg);
|
||||
}
|
||||
|
||||
void
|
||||
gitg_window_load_repository(GitgWindow *window, gchar const *path)
|
||||
{
|
||||
g_return_if_fail(GITG_IS_WINDOW(window));
|
||||
|
||||
if (window->priv->repository)
|
||||
{
|
||||
gtk_tree_view_set_model(window->priv->tree_view, NULL);
|
||||
g_object_unref(window->priv->repository);
|
||||
}
|
||||
|
||||
window->priv->repository = gitg_repository_new(path);
|
||||
|
||||
if (gitg_repository_get_path(window->priv->repository))
|
||||
{
|
||||
gtk_tree_view_set_model(window->priv->tree_view, GTK_TREE_MODEL(window->priv->repository));
|
||||
GitgRunner *loader = gitg_repository_get_loader(window->priv->repository);
|
||||
|
||||
g_signal_connect(loader, "begin-loading", G_CALLBACK(on_begin_loading), window);
|
||||
g_signal_connect(loader, "end-loading", G_CALLBACK(on_end_loading), window);
|
||||
g_signal_connect(loader, "update", G_CALLBACK(on_update), window);
|
||||
|
||||
g_object_unref(loader);
|
||||
|
||||
gitg_repository_load(window->priv->repository, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle_no_gitdir(window);
|
||||
}
|
||||
}
|
37
gitg/gitg-window.h
Normal file
37
gitg/gitg-window.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef __GITG_WINDOW_H__
|
||||
#define __GITG_WINDOW_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GITG_TYPE_WINDOW (gitg_window_get_type ())
|
||||
#define GITG_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_WINDOW, GitgWindow))
|
||||
#define GITG_WINDOW_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_WINDOW, GitgWindow const))
|
||||
#define GITG_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GITG_TYPE_WINDOW, GitgWindowClass))
|
||||
#define GITG_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_WINDOW))
|
||||
#define GITG_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GITG_TYPE_WINDOW))
|
||||
#define GITG_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GITG_TYPE_WINDOW, GitgWindowClass))
|
||||
|
||||
typedef struct _GitgWindow GitgWindow;
|
||||
typedef struct _GitgWindowClass GitgWindowClass;
|
||||
typedef struct _GitgWindowPrivate GitgWindowPrivate;
|
||||
|
||||
struct _GitgWindow {
|
||||
GtkWindow parent;
|
||||
|
||||
GitgWindowPrivate *priv;
|
||||
};
|
||||
|
||||
struct _GitgWindowClass {
|
||||
GtkWindowClass parent_class;
|
||||
};
|
||||
|
||||
GType gitg_window_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void gitg_window_load_repository(GitgWindow *window, gchar const *path);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GITG_WINDOW_H__ */
|
298
gitg/gitg.c
298
gitg/gitg.c
|
@ -3,13 +3,8 @@
|
|||
#include <glib/gi18n.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <gtksourceview/gtksourceview.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
#include "gitg-repository.h"
|
||||
#include "gitg-revision-view.h"
|
||||
#include "gitg-utils.h"
|
||||
#include "gitg-runner.h"
|
||||
#include "gitg-window.h"
|
||||
#include "sexy-icon-entry.h"
|
||||
#include "config.h"
|
||||
|
||||
|
@ -18,14 +13,6 @@ static GOptionEntry entries[] =
|
|||
{ NULL }
|
||||
};
|
||||
|
||||
static GtkWindow *window;
|
||||
static GtkBuilder *builder;
|
||||
static GtkTreeView *tree_view;
|
||||
static GtkStatusbar *statusbar;
|
||||
static GtkWidget *search_popup;
|
||||
static GitgRepository *repository;
|
||||
static GitgRevisionView *revision_view;
|
||||
|
||||
void
|
||||
parse_options(int *argc, char ***argv)
|
||||
{
|
||||
|
@ -49,222 +36,15 @@ parse_options(int *argc, char ***argv)
|
|||
static gboolean
|
||||
on_window_delete_event(GtkWidget *widget, GdkEvent *event, gpointer userdata)
|
||||
{
|
||||
gtk_tree_view_set_model(tree_view, NULL);
|
||||
|
||||
g_object_unref(builder);
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
static gint
|
||||
string_compare(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
|
||||
{
|
||||
return 0; //gitg_rv_model_compare(store, a, b, GPOINTER_TO_INT(userdata));
|
||||
}
|
||||
|
||||
static void
|
||||
on_selection_changed(GtkTreeSelection *selection, gpointer userdata)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
GitgRevision *revision = NULL;
|
||||
|
||||
if (gtk_tree_selection_get_selected(selection, &model, &iter))
|
||||
gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &revision, -1);
|
||||
|
||||
gitg_revision_view_update(revision_view, repository, revision);
|
||||
}
|
||||
|
||||
static void
|
||||
build_tree_view()
|
||||
{
|
||||
tree_view = GTK_TREE_VIEW(gtk_builder_get_object(builder, "tree_view_rv"));
|
||||
|
||||
gtk_tree_view_set_model(tree_view, GTK_TREE_MODEL(repository));
|
||||
|
||||
gtk_tree_view_insert_column_with_attributes(tree_view,
|
||||
0, _("Subject"), gtk_cell_renderer_text_new(), "text", 1, NULL);
|
||||
|
||||
gtk_tree_view_insert_column_with_attributes(tree_view,
|
||||
1, _("Author"), gtk_cell_renderer_text_new(), "text", 2, NULL);
|
||||
|
||||
gtk_tree_view_insert_column_with_attributes(tree_view,
|
||||
2, _("Date"), gtk_cell_renderer_text_new(), "text", 3, NULL);
|
||||
|
||||
int i;
|
||||
GtkTreeViewColumn *column;
|
||||
|
||||
guint cw[] = {400, 200, 200};
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
column = gtk_tree_view_get_column(tree_view, i);
|
||||
gtk_tree_view_column_set_resizable(column, TRUE);
|
||||
gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
|
||||
gtk_tree_view_column_set_fixed_width(column, cw[i]);
|
||||
|
||||
gtk_tree_view_column_set_sort_column_id(column, i + 1);
|
||||
//gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), i + 1, string_compare, GINT_TO_POINTER(i + 1), NULL);
|
||||
}
|
||||
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
|
||||
|
||||
g_signal_connect(selection, "changed", G_CALLBACK(on_selection_changed), NULL);
|
||||
}
|
||||
|
||||
static GtkImage *
|
||||
search_image()
|
||||
{
|
||||
return GTK_IMAGE(gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU));
|
||||
}
|
||||
|
||||
static void
|
||||
on_search_icon_pressed(SexyIconEntry *entry, SexyIconEntryPosition icon_pos, int button, gpointer userdata)
|
||||
{
|
||||
gtk_menu_popup(GTK_MENU(search_popup), NULL, NULL, NULL, NULL, button, gtk_get_current_event_time());
|
||||
}
|
||||
|
||||
void
|
||||
search_column_activate(GtkAction *action, gint column)
|
||||
{
|
||||
if (!gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)))
|
||||
return;
|
||||
|
||||
gtk_tree_view_set_search_column(tree_view, column);
|
||||
}
|
||||
|
||||
void
|
||||
on_hash_activate(GtkAction *action, gpointer data)
|
||||
{
|
||||
search_column_activate(action, 4);
|
||||
}
|
||||
|
||||
void
|
||||
on_subject_activate(GtkAction *action, gpointer data)
|
||||
{
|
||||
search_column_activate(action, 1);
|
||||
}
|
||||
|
||||
void
|
||||
on_author_activate(GtkAction *action, gpointer data)
|
||||
{
|
||||
search_column_activate(action, 2);
|
||||
}
|
||||
|
||||
void
|
||||
on_date_activate(GtkAction *action, gpointer data)
|
||||
{
|
||||
search_column_activate(action, 3);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
search_hash_equal_func(GtkTreeModel *model, gchar const *key, GtkTreeIter *iter)
|
||||
{
|
||||
GitgRevision *rv;
|
||||
gtk_tree_model_get(model, iter, 0, &rv, -1);
|
||||
|
||||
gchar *sha = gitg_revision_get_sha1(rv);
|
||||
|
||||
gboolean ret = strncmp(sha, key, strlen(key)) != 0;
|
||||
|
||||
g_free(sha);
|
||||
g_object_unref(rv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
search_equal_func(GtkTreeModel *model, gint column, gchar const *key, GtkTreeIter *iter, gpointer userdata)
|
||||
{
|
||||
if (column == 4)
|
||||
return search_hash_equal_func(model, key, iter);
|
||||
|
||||
gchar *cmp;
|
||||
gtk_tree_model_get(model, iter, column, &cmp, -1);
|
||||
|
||||
gchar *s1 = g_utf8_casefold(key, -1);
|
||||
gchar *s2 = g_utf8_casefold(cmp, -1);
|
||||
|
||||
gboolean ret = strstr(s2, s1) == NULL;
|
||||
|
||||
g_free(s1);
|
||||
g_free(s2);
|
||||
|
||||
g_free(cmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
focus_search(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType modifier, gpointer userdata)
|
||||
{
|
||||
gtk_widget_grab_focus(GTK_WIDGET(userdata));
|
||||
}
|
||||
|
||||
static void
|
||||
build_search()
|
||||
{
|
||||
GtkWidget *box = GTK_WIDGET(gtk_builder_get_object(builder, "hbox_top"));
|
||||
GtkWidget *entry = sexy_icon_entry_new();
|
||||
|
||||
GtkImage *image = search_image();
|
||||
sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(entry), SEXY_ICON_ENTRY_PRIMARY, image);
|
||||
|
||||
gtk_tree_view_set_search_entry(tree_view, GTK_ENTRY(entry));
|
||||
gtk_widget_show(entry);
|
||||
gtk_box_pack_end(GTK_BOX(box), entry, FALSE, FALSE, 0);
|
||||
|
||||
GtkBuilder *b = gtk_builder_new();
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gtk_builder_add_from_file(b, GITG_UI_DIR "/gitg-menus.xml", &error))
|
||||
{
|
||||
g_critical("Could not open UI file: %s (%s)", GITG_UI_DIR "/gitg-menus.xml", error->message);
|
||||
g_error_free(error);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
GtkUIManager *manager = GTK_UI_MANAGER(gtk_builder_get_object(b, "uiman"));
|
||||
search_popup = GTK_WIDGET(g_object_ref(gtk_ui_manager_get_widget(manager, "/ui/search_popup")));
|
||||
|
||||
gtk_builder_connect_signals(b, NULL);
|
||||
g_object_unref(b);
|
||||
|
||||
g_signal_connect(entry, "icon-pressed", G_CALLBACK(on_search_icon_pressed), NULL);
|
||||
gtk_tree_view_set_search_column(tree_view, 1);
|
||||
|
||||
gtk_tree_view_set_search_equal_func(tree_view, search_equal_func, entry, NULL);
|
||||
|
||||
GtkAccelGroup *group = gtk_accel_group_new();
|
||||
|
||||
GClosure *closure = g_cclosure_new(G_CALLBACK(focus_search), entry, NULL);
|
||||
gtk_accel_group_connect(group, GDK_f, GDK_CONTROL_MASK, 0, closure);
|
||||
gtk_window_add_accel_group(window, group);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_parent_activated(GitgRevisionView *view, gchar *hash, gpointer userdata)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (!gitg_repository_find_by_hash(repository, hash, &iter))
|
||||
return FALSE;
|
||||
|
||||
gtk_tree_selection_select_iter(gtk_tree_view_get_selection(tree_view), &iter);
|
||||
GtkTreePath *path;
|
||||
|
||||
path = gtk_tree_model_get_path(GTK_TREE_MODEL(repository), &iter);
|
||||
|
||||
gtk_tree_view_scroll_to_cell(tree_view, path, NULL, FALSE, 0, 0);
|
||||
gtk_tree_path_free(path);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
static GitgWindow *
|
||||
build_ui()
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
builder = gtk_builder_new();
|
||||
GtkBuilder *builder = gtk_builder_new();
|
||||
gtk_builder_set_translation_domain(builder, GETTEXT_PACKAGE);
|
||||
|
||||
if (!gtk_builder_add_from_file(builder, GITG_UI_DIR "/gitg-ui.xml", &error))
|
||||
|
@ -274,61 +54,11 @@ build_ui()
|
|||
exit(1);
|
||||
}
|
||||
|
||||
window = GTK_WINDOW(gtk_builder_get_object(builder, "window"));
|
||||
gtk_widget_show_all(GTK_WIDGET(window));
|
||||
|
||||
build_tree_view();
|
||||
build_search();
|
||||
GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
|
||||
gtk_widget_show_all(window);
|
||||
|
||||
g_signal_connect(window, "delete-event", G_CALLBACK(on_window_delete_event), NULL);
|
||||
|
||||
statusbar = GTK_STATUSBAR(gtk_builder_get_object(builder, "statusbar"));
|
||||
revision_view = GITG_REVISION_VIEW(gtk_builder_get_object(builder, "revision_view"));
|
||||
|
||||
g_signal_connect(revision_view, "parent-activated", G_CALLBACK(on_parent_activated), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
on_begin_loading(GitgRunner *loader, gpointer userdata)
|
||||
{
|
||||
GdkCursor *cursor = gdk_cursor_new(GDK_WATCH);
|
||||
gdk_window_set_cursor(GTK_WIDGET(tree_view)->window, cursor);
|
||||
gdk_cursor_unref(cursor);
|
||||
|
||||
gtk_statusbar_push(statusbar, 0, _("Begin loading repository"));
|
||||
}
|
||||
|
||||
static void
|
||||
on_end_loading(GitgRunner *loader, gpointer userdata)
|
||||
{
|
||||
gchar *msg = g_strdup_printf(_("Loaded %d revisions"), gtk_tree_model_iter_n_children(GTK_TREE_MODEL(repository), NULL));
|
||||
|
||||
gtk_statusbar_push(statusbar, 0, msg);
|
||||
|
||||
g_free(msg);
|
||||
gdk_window_set_cursor(GTK_WIDGET(tree_view)->window, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
on_update(GitgRunner *loader, gchar **revisions, gpointer userdata)
|
||||
{
|
||||
gchar *msg = g_strdup_printf(_("Loading %d revisions..."), gtk_tree_model_iter_n_children(GTK_TREE_MODEL(repository), NULL));
|
||||
|
||||
gtk_statusbar_push(statusbar, 0, msg);
|
||||
g_free(msg);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_no_gitdir(gpointer userdata)
|
||||
{
|
||||
if (gitg_repository_get_path(repository))
|
||||
return FALSE;
|
||||
|
||||
GtkWidget *dlg = gtk_message_dialog_new(window, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Gitg repository could not be found"));
|
||||
|
||||
gtk_dialog_run(GTK_DIALOG(dlg));
|
||||
gtk_widget_destroy(dlg);
|
||||
return FALSE;
|
||||
return GITG_WINDOW(window);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -343,23 +73,13 @@ main(int argc, char **argv)
|
|||
|
||||
gtk_init(&argc, &argv);
|
||||
parse_options(&argc, &argv);
|
||||
|
||||
GitgWindow *window = build_ui();
|
||||
|
||||
gchar *gitdir = argc > 1 ? g_strdup(argv[1]) : g_get_current_dir();
|
||||
repository = gitg_repository_new(gitdir);
|
||||
gitg_window_load_repository(window, gitdir);
|
||||
g_free(gitdir);
|
||||
|
||||
build_ui();
|
||||
|
||||
GitgRunner *loader = gitg_repository_get_loader(repository);
|
||||
g_signal_connect(loader, "begin-loading", G_CALLBACK(on_begin_loading), NULL);
|
||||
g_signal_connect(loader, "end-loading", G_CALLBACK(on_end_loading), NULL);
|
||||
g_signal_connect(loader, "update", G_CALLBACK(on_update), NULL);
|
||||
g_object_unref(loader);
|
||||
|
||||
gitg_repository_load(repository, NULL);
|
||||
g_object_unref(repository);
|
||||
|
||||
g_idle_add(handle_no_gitdir, NULL);
|
||||
gtk_main();
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue