Merge commit 'upstream/0.1.8'
This commit is contained in:
commit
ace30a9234
81 changed files with 21257 additions and 8570 deletions
5
AUTHORS
5
AUTHORS
|
@ -48,6 +48,7 @@ Translations:
|
|||
hu: SZERVÁC Attila <sas@321.hu>
|
||||
id: Andhika Padmawan <andhika.padmawan@gmail.com>
|
||||
it: Sergio Durzu <sergio.durzu@ildeposito.org>
|
||||
it: Luca Perri <kurama_luka@yahoo.it>
|
||||
ja: Masato Hashimoto <cabezon.hashimoto@gmail.com>
|
||||
nl: Vincent Tunru <projects@vinnl.nl>
|
||||
pl: Przemysław Sitek <el.pescado@gazeta.pl>
|
||||
|
@ -58,8 +59,10 @@ Translations:
|
|||
ru: Troitskiy Nikita <niktr@mail.ru>
|
||||
ru: Anton Shestakov <engored@ya.ru>
|
||||
sk: Robert Hartl <hartl.robert@gmail.com>
|
||||
sr: Miloš Popović <gpopac@gmail.com>
|
||||
sv: Mikael Magnusson <mikachu@comhem.se>
|
||||
tr: Mirat Can Bayrak <MiratCanBayrak@gmail.com>
|
||||
tr: Gökmen Görgen <gkmngrgn@gmail.com>
|
||||
uk: Dmitry Nikitin <luckas_fb@mail.ru>
|
||||
zh_CN: Stanley Zhang <yatzhang@gmail.com>
|
||||
zh_TW: Wei-Lun Chao <william.chao@ossii.com.tw>
|
||||
|
@ -67,5 +70,7 @@ Translations:
|
|||
Code from other projects:
|
||||
GTK+/ GdkPixbuf, Matthias Clasen <mclasen@redhat.com>
|
||||
GTK+/ GtkEntry, Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
GTK+/ GtkToolbar, Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
Modified by the GTK+ Team and others 1997-2000
|
||||
libSoup/ CookieJarText, Copyright (C) 2008 Xan Lopez <xan@gnome.org>, Dan Winship <danw@gnome.org>
|
||||
libSylph, Copyright 1999-2008 Hiroyuki Yamamoto, Copyright 2006-2009 Enrico Tröger <enrico.troeger@uvena.de>
|
||||
|
|
28
ChangeLog
28
ChangeLog
|
@ -1,5 +1,33 @@
|
|||
This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||
|
||||
v0.1.8:
|
||||
+ Initial support for extension unit tests
|
||||
+ Set a "browser" role on browser windows
|
||||
+ Support typing search tokens to open websites
|
||||
+ Fix focus loss when switching search engines
|
||||
+ Rewrite Netscape Plugins panel backed by javascript
|
||||
+ Implement a compact menu if menubar is hidden
|
||||
+ Provide a context menu for tab labels
|
||||
+ Implement Tab Panel as a tabbar replacement
|
||||
+ Remember the last active tab
|
||||
+ Read and write XBEL metadata internally
|
||||
+ Implement -e, --execute to perform commands
|
||||
+ Support socket based single instance
|
||||
+ Move Go button inside the location entry
|
||||
+ Fix the ident string after Midori updates
|
||||
+ Bind Alt + n to switching to the n-th tab
|
||||
+ Revisit conflicting mnemonics
|
||||
+ Add a Toolbar Editor extension
|
||||
+ Add a Shortcut Editor extension
|
||||
+ Implement context menu in the Transfers panel
|
||||
+ Simplified Extensions and Addons panels with tick marks
|
||||
+ Fix Mouse Gestures often ignoreing gestures
|
||||
+ Use one cookie manager model in all windows
|
||||
+ Support building Midori for Win32
|
||||
+ Add an entry to specify Fixed-Width font size
|
||||
+ Implement Save As in the download dialog
|
||||
+ Use one history model in all windows
|
||||
|
||||
v0.1.7:
|
||||
+ Save the activation status of extensions
|
||||
+ Catch and ignore mouse buttons meant for horizontal scrolling
|
||||
|
|
4
TODO
4
TODO
|
@ -18,17 +18,13 @@ TODO:
|
|||
. Have an internal uri scheme, eg. 'res:', to reference eg. themed icons
|
||||
. 'about:' uris: about, blank, cache, config, plugins
|
||||
. Panel of open tabs (with tree-structure), optional thumbnail-view
|
||||
. Spell check support
|
||||
. Check specific bookmarks for updates automatically (extension)
|
||||
. Mark "new" as well as "actually modified" tabs specially (even over sessions)
|
||||
. SearchEngine: "Show in context menu"
|
||||
. Use libnotify for events, e.g. download finished
|
||||
. Save screenshot of a document?
|
||||
. Right-click a textbox in a search form and choose 'add to websearch'
|
||||
. Honor design principle "no warnings but undo of backups"?
|
||||
. Support widgets 1.0 spec in tool windows and standalone?
|
||||
. Blank page: several custom links, displayed as thumbnails, like Opera?
|
||||
. Handle downloads, optionally in a downloadbar
|
||||
. Protected tabs prompt when attempting to close them
|
||||
. Provide a 'sleep mode' after a crash where open documents are loaded manually
|
||||
. Option to run plugins or scripts only on demand, like NoScript, per-site
|
||||
|
|
2
data/midori.rc
Normal file
2
data/midori.rc
Normal file
|
@ -0,0 +1,2 @@
|
|||
|
||||
IDR_MAINFRAME ICON DISCARDABLE "../_build_/default/data/midori.ico"
|
|
@ -235,10 +235,6 @@
|
|||
var a = cross.getNext ();
|
||||
var p = a.getNext ();
|
||||
|
||||
cross.dispose ();
|
||||
div.removeClass ('activated');
|
||||
a.empty ();
|
||||
|
||||
cross.dispose ();
|
||||
div.removeClass ('activated');
|
||||
a.empty ().set ('html', '<h1>' + num + '</h1><h4><span/></h4>');
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
# This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||
|
||||
import pproc as subprocess
|
||||
import os
|
||||
|
||||
for module in ('midori', 'katze'):
|
||||
try:
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
static void
|
||||
adblock_app_add_browser_cb (MidoriApp* app,
|
||||
|
@ -36,17 +39,64 @@ adblock_deactivate_cb (MidoriExtension* extension,
|
|||
}
|
||||
|
||||
static void
|
||||
adblock_preferences_render_text (GtkTreeViewColumn* column,
|
||||
GtkCellRenderer* renderer,
|
||||
GtkTreeModel* model,
|
||||
adblock_preferences_renderer_text_edited_cb (GtkCellRenderer* renderer,
|
||||
const gchar* tree_path,
|
||||
const gchar* new_text,
|
||||
GtkTreeModel* model)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (gtk_tree_model_get_iter_from_string (model, &iter, tree_path))
|
||||
gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, new_text, -1);
|
||||
}
|
||||
|
||||
static void
|
||||
adblock_preferences_model_row_changed_cb (GtkTreeModel* model,
|
||||
GtkTreePath* path,
|
||||
GtkTreeIter* iter,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
gchar* uri;
|
||||
gsize length = gtk_tree_model_iter_n_children (model, NULL);
|
||||
gchar** filters = g_new (gchar*, length + 1);
|
||||
guint i = 0;
|
||||
|
||||
gtk_tree_model_get (model, iter, 0, &uri, -1);
|
||||
g_object_set (renderer, "text", uri, NULL);
|
||||
g_free (uri);
|
||||
if (gtk_tree_model_iter_children (model, iter, NULL))
|
||||
do
|
||||
{
|
||||
gchar* filter;
|
||||
gtk_tree_model_get (model, iter, 0, &filter, -1);
|
||||
filters[i++] = filter;
|
||||
}
|
||||
while (gtk_tree_model_iter_next (model, iter));
|
||||
filters[length] = NULL;
|
||||
midori_extension_set_string_list (extension, "filters", filters, length);
|
||||
}
|
||||
|
||||
static void
|
||||
adblock_preferences_model_row_deleted_cb (GtkTreeModel* model,
|
||||
GtkTreePath* path,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
adblock_preferences_model_row_changed_cb (model, path, &iter, extension);
|
||||
}
|
||||
|
||||
static void
|
||||
adblock_preferences_add_clicked_cb (GtkWidget* button,
|
||||
GtkTreeModel* model)
|
||||
{
|
||||
gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
|
||||
NULL, 0, 0, "", -1);
|
||||
}
|
||||
|
||||
static void
|
||||
adblock_preferences_remove_clicked_cb (GtkWidget* button,
|
||||
GtkTreeView* treeview)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
if (katze_tree_view_get_selected_iter (treeview, &model, &iter))
|
||||
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
|
@ -102,19 +152,26 @@ adblock_get_preferences_dialog (MidoriExtension* extension)
|
|||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
|
||||
TRUE, TRUE, 12);
|
||||
liststore = gtk_list_store_new (1, G_TYPE_STRING);
|
||||
g_object_connect (liststore,
|
||||
"signal::row-inserted",
|
||||
adblock_preferences_model_row_changed_cb, extension,
|
||||
"signal::row-changed",
|
||||
adblock_preferences_model_row_changed_cb, extension,
|
||||
"signal::row-deleted",
|
||||
adblock_preferences_model_row_deleted_cb, extension,
|
||||
NULL);
|
||||
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (liststore));
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
|
||||
column = gtk_tree_view_column_new ();
|
||||
renderer_pixbuf = gtk_cell_renderer_pixbuf_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE);
|
||||
/* gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf,
|
||||
(GtkTreeCellDataFunc)adblock_preferences_render_icon_cb,
|
||||
treeview, NULL); */
|
||||
renderer_text = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer_text, TRUE);
|
||||
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
|
||||
(GtkTreeCellDataFunc)adblock_preferences_render_text,
|
||||
extension, NULL);
|
||||
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (column), renderer_text,
|
||||
"text", 0, NULL);
|
||||
g_object_set (renderer_text, "editable", TRUE, NULL);
|
||||
g_signal_connect (renderer_text, "edited",
|
||||
G_CALLBACK (adblock_preferences_renderer_text_edited_cb), liststore);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
scrolled = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
|
||||
|
@ -138,18 +195,16 @@ adblock_get_preferences_dialog (MidoriExtension* extension)
|
|||
vbox = gtk_vbox_new (FALSE, 4);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 4);
|
||||
button = gtk_button_new_from_stock (GTK_STOCK_ADD);
|
||||
/* g_signal_connect (button, "clicked",
|
||||
G_CALLBACK (adblock_preferences_add_cb), extension); */
|
||||
g_signal_connect (button, "clicked",
|
||||
G_CALLBACK (adblock_preferences_add_clicked_cb), liststore);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
gtk_widget_set_sensitive (button, FALSE);
|
||||
button = gtk_button_new_from_stock (GTK_STOCK_EDIT);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
gtk_widget_set_sensitive (button, FALSE);
|
||||
button = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
|
||||
/* g_signal_connect (button, "clicked",
|
||||
G_CALLBACK (adblock_preferences_remove_cb), extension); */
|
||||
g_signal_connect (button, "clicked",
|
||||
G_CALLBACK (adblock_preferences_remove_clicked_cb), treeview);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
gtk_widget_set_sensitive (button, FALSE);
|
||||
button = gtk_label_new (""); /* This is an invisible separator */
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 8);
|
||||
gtk_widget_set_sensitive (button, FALSE);
|
||||
|
@ -223,14 +278,22 @@ adblock_app_add_browser_cb (MidoriApp* app,
|
|||
G_CALLBACK (adblock_deactivate_cb), menuitem);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
adblock_is_matched (const gchar* pattern,
|
||||
const GRegex* regex,
|
||||
const gchar* uri)
|
||||
{
|
||||
return g_regex_match_full (regex, uri, -1, 0, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
adblock_session_request_queued_cb (SoupSession* session,
|
||||
SoupMessage* msg,
|
||||
GRegex* regex)
|
||||
GHashTable* pattern)
|
||||
{
|
||||
SoupURI* soup_uri = soup_message_get_uri (msg);
|
||||
gchar* uri = soup_uri ? soup_uri_to_string (soup_uri, FALSE) : g_strdup ("");
|
||||
if (g_regex_match_full (regex, uri, -1, 0, 0, NULL, NULL))
|
||||
if (g_hash_table_find (pattern, (GHRFunc) adblock_is_matched, uri))
|
||||
{
|
||||
/* g_debug ("match! '%s'", uri); */
|
||||
/* FIXME: This leads to funny error pages if frames are blocked */
|
||||
|
@ -239,60 +302,77 @@ adblock_session_request_queued_cb (SoupSession* session,
|
|||
g_free (uri);
|
||||
}
|
||||
|
||||
static void
|
||||
adblock_session_add_filter (SoupSession* session,
|
||||
gchar* path)
|
||||
static gchar*
|
||||
adblock_parse_line (gchar* line)
|
||||
{
|
||||
if (!line)
|
||||
return NULL;
|
||||
|
||||
/* Ignore comments and new lines */
|
||||
if (line[0] == '!')
|
||||
return NULL;
|
||||
/* FIXME: No support for whitelisting */
|
||||
if (line[0] == '@' && line[1] == '@')
|
||||
return NULL;
|
||||
/* FIXME: Differentiate # comments from element hiding */
|
||||
/* FIXME: No support for element hiding */
|
||||
if (line[0] == '#' && line[1] == '#')
|
||||
return NULL;
|
||||
/* FIXME: No support for [include] and [exclude] tags */
|
||||
if (line[0] == '[')
|
||||
return NULL;
|
||||
g_strchomp (line);
|
||||
/* TODO: Replace trailing '*' with '.*' */
|
||||
if (line[0] == '*')
|
||||
return g_strconcat (".", line, NULL);
|
||||
else if (line[0] == '?')
|
||||
return g_strconcat ("\\", line, NULL);
|
||||
return g_strdup (line);
|
||||
}
|
||||
|
||||
static GHashTable*
|
||||
adblock_parse_file (gchar* path)
|
||||
{
|
||||
FILE* file;
|
||||
|
||||
if ((file = g_fopen (path, "r")))
|
||||
{
|
||||
/* We assume filter lists found on the web are commonly very long */
|
||||
GString* pattern = g_string_sized_new (1000 * 200);
|
||||
GHashTable* pattern = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(GDestroyNotify)g_free,
|
||||
(GDestroyNotify)g_regex_unref);
|
||||
|
||||
gboolean have_pattern = FALSE;
|
||||
gchar line[255];
|
||||
GRegex* regex;
|
||||
GError* error;
|
||||
|
||||
while (fgets (line, 255, file))
|
||||
{
|
||||
/* Ignore comments and new lines */
|
||||
if (line[0] == '!')
|
||||
continue;
|
||||
/* FIXME: No support for whitelisting */
|
||||
if (line[0] == '@' && line[1] == '@')
|
||||
continue;
|
||||
/* FIXME: Differentiate # comments from element hiding */
|
||||
/* FIXME: No support for element hiding */
|
||||
if (line[0] == '#' && line[1] == '#')
|
||||
continue;
|
||||
/* FIXME: No support for [include] and [exclude] tags */
|
||||
if (line[0] == '[')
|
||||
continue;
|
||||
g_strchomp (line);
|
||||
g_string_append (pattern, line);
|
||||
g_string_append_c (pattern, '|');
|
||||
}
|
||||
GError* error = NULL;
|
||||
gchar* parsed;
|
||||
|
||||
error = NULL;
|
||||
if (pattern->len > 2 &&
|
||||
(regex = g_regex_new (pattern->str, G_REGEX_OPTIMIZE,
|
||||
G_REGEX_MATCH_NOTEMPTY, &error)))
|
||||
parsed = adblock_parse_line (line);
|
||||
regex = g_regex_new (parsed, G_REGEX_OPTIMIZE,
|
||||
G_REGEX_MATCH_NOTEMPTY, &error);
|
||||
if (error)
|
||||
{
|
||||
/* g_debug ("%s: '%s'", G_STRFUNC, pattern->str); */
|
||||
g_signal_connect_data (session, "request-queued",
|
||||
G_CALLBACK (adblock_session_request_queued_cb),
|
||||
regex, (GClosureNotify)g_regex_unref, 0);
|
||||
}
|
||||
else if (error)
|
||||
{
|
||||
/* g_warning ("%s: %s", G_STRFUNC, error->message); */
|
||||
g_warning ("%s: %s", G_STRFUNC, error->message);
|
||||
g_error_free (error);
|
||||
g_free (parsed);
|
||||
}
|
||||
else
|
||||
{
|
||||
have_pattern = TRUE;
|
||||
g_hash_table_insert (pattern, parsed, regex);
|
||||
}
|
||||
}
|
||||
g_string_free (pattern, TRUE);
|
||||
fclose (file);
|
||||
|
||||
if (have_pattern)
|
||||
return pattern;
|
||||
}
|
||||
/* FIXME: This should presumably be freed, but there's a possible crash
|
||||
g_free (path); */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||||
|
@ -302,7 +382,11 @@ adblock_download_notify_status_cb (WebKitDownload* download,
|
|||
gchar* path)
|
||||
{
|
||||
SoupSession* session = webkit_get_default_session ();
|
||||
adblock_session_add_filter (session, path);
|
||||
GHashTable* pattern = adblock_parse_file (path);
|
||||
if (pattern)
|
||||
g_signal_connect_data (session, "request-queued",
|
||||
G_CALLBACK (adblock_session_request_queued_cb),
|
||||
pattern, (GClosureNotify)g_hash_table_destroy, 0);
|
||||
/* g_object_unref (download); */
|
||||
}
|
||||
#endif
|
||||
|
@ -359,7 +443,13 @@ adblock_activate_cb (MidoriExtension* extension,
|
|||
#endif
|
||||
}
|
||||
else
|
||||
adblock_session_add_filter (session, path);
|
||||
{
|
||||
GHashTable* pattern = adblock_parse_file (path);
|
||||
if (pattern)
|
||||
g_signal_connect_data (session, "request-queued",
|
||||
G_CALLBACK (adblock_session_request_queued_cb),
|
||||
pattern, (GClosureNotify)g_hash_table_destroy, 0);
|
||||
}
|
||||
g_free (filename);
|
||||
}
|
||||
}
|
||||
|
@ -367,6 +457,68 @@ adblock_activate_cb (MidoriExtension* extension,
|
|||
g_free (folder);
|
||||
}
|
||||
|
||||
#if G_ENABLE_DEBUG
|
||||
static void
|
||||
test_adblock_parse (void)
|
||||
{
|
||||
g_assert (!adblock_parse_line (NULL));
|
||||
g_assert (!adblock_parse_line ("!"));
|
||||
g_assert (!adblock_parse_line ("@@"));
|
||||
g_assert (!adblock_parse_line ("##"));
|
||||
g_assert (!adblock_parse_line ("["));
|
||||
|
||||
g_assert_cmpstr (adblock_parse_line ("*foo"), ==, ".*foo");
|
||||
g_assert_cmpstr (adblock_parse_line ("?foo"), ==, "\\?foo");
|
||||
/* g_assert_cmpstr (adblock_parse_line ("foo*"), ==, "foo.*");
|
||||
g_assert_cmpstr (adblock_parse_line ("foo?"), ==, "foo\\?"); */
|
||||
|
||||
g_assert_cmpstr (adblock_parse_line (".*foo/bar"), ==, ".*foo/bar");
|
||||
g_assert_cmpstr (adblock_parse_line ("http://bla.blub/.*"), ==, "http://bla.blub/.*");
|
||||
}
|
||||
|
||||
static void
|
||||
test_adblock_pattern (void)
|
||||
{
|
||||
gint temp;
|
||||
gchar* filename;
|
||||
GHashTable* pattern;
|
||||
|
||||
temp = g_file_open_tmp ("midori_adblock_match_test_XXXXXX", &filename, NULL);
|
||||
|
||||
g_file_set_contents (filename,
|
||||
"*ads.foo.bar.*\n"
|
||||
".*ads.bogus.name.*\n"
|
||||
"http://ads.bla.blub/.*\n"
|
||||
"http://ads.blub.boing/*.",
|
||||
-1, NULL);
|
||||
pattern = adblock_parse_file (filename);
|
||||
|
||||
g_assert (g_hash_table_find (pattern, (GHRFunc) adblock_is_matched,
|
||||
"http://ads.foo.bar/teddy"));
|
||||
g_assert (!g_hash_table_find (pattern, (GHRFunc) adblock_is_matched,
|
||||
"http://ads.fuu.bar/teddy"));
|
||||
g_assert (g_hash_table_find (pattern, (GHRFunc) adblock_is_matched,
|
||||
"https://ads.bogus.name/blub"));
|
||||
g_assert (g_hash_table_find (pattern, (GHRFunc) adblock_is_matched,
|
||||
"http://ads.bla.blub/kitty"));
|
||||
g_assert (g_hash_table_find (pattern, (GHRFunc) adblock_is_matched,
|
||||
"http://ads.blub.boing/soda"));
|
||||
g_assert (!g_hash_table_find (pattern, (GHRFunc) adblock_is_matched,
|
||||
"http://ads.foo.boing/beer"));
|
||||
|
||||
g_hash_table_destroy (pattern);
|
||||
close (temp);
|
||||
g_unlink (filename);
|
||||
}
|
||||
|
||||
void
|
||||
extension_test (void)
|
||||
{
|
||||
g_test_add_func ("/extensions/adblock/parse", test_adblock_parse);
|
||||
g_test_add_func ("/extensions/adblock/pattern", test_adblock_pattern);
|
||||
}
|
||||
#endif
|
||||
|
||||
MidoriExtension*
|
||||
extension_init (void)
|
||||
{
|
||||
|
|
|
@ -72,7 +72,7 @@ static void
|
|||
colorful_tabs_button_toggled_cb (GtkWidget* button,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
MidoriBrowser* browser = MIDORI_BROWSER (gtk_widget_get_toplevel (button));
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (button);
|
||||
|
||||
midori_extension_set_boolean (extension, "tint",
|
||||
!midori_extension_get_boolean (extension, "tint"));
|
||||
|
@ -96,7 +96,7 @@ colorful_tabs_deactivate_cb (MidoriExtension* extension,
|
|||
g_signal_handlers_disconnect_by_func (
|
||||
extension, colorful_tabs_deactivate_cb, bbox);
|
||||
/* FIXME: Disconnect signals */
|
||||
midori_browser_foreach (MIDORI_BROWSER (gtk_widget_get_toplevel (bbox)),
|
||||
midori_browser_foreach (midori_browser_get_for_widget (bbox),
|
||||
(GtkCallback)colorful_tabs_browser_foreach_cb, extension);
|
||||
gtk_widget_destroy (bbox);
|
||||
}
|
||||
|
|
|
@ -28,22 +28,17 @@ typedef struct _CookieManagerPagePrivate CookieManagerPagePrivate;
|
|||
|
||||
#define CM_EMPTY_LABEL_TEXT "\n\n\n\n\n\n"
|
||||
|
||||
enum
|
||||
{
|
||||
COOKIE_MANAGER_COL_NAME,
|
||||
COOKIE_MANAGER_COL_COOKIE,
|
||||
COOKIE_MANAGER_COL_VISIBLE,
|
||||
COOKIE_MANAGER_N_COLUMNS
|
||||
};
|
||||
|
||||
|
||||
struct _CookieManagerPagePrivate
|
||||
{
|
||||
CookieManager *parent;
|
||||
|
||||
GtkWidget *treeview;
|
||||
GtkTreeStore *store;
|
||||
GtkTreeModel *filter;
|
||||
|
||||
GtkWidget *filter_entry;
|
||||
gboolean ignore_changed_filter;
|
||||
|
||||
GtkWidget *desc_label;
|
||||
GtkWidget *delete_button;
|
||||
|
@ -53,11 +48,13 @@ struct _CookieManagerPagePrivate
|
|||
|
||||
GtkWidget *toolbar;
|
||||
GtkWidget *popup_menu;
|
||||
};
|
||||
|
||||
GSList *cookies;
|
||||
SoupCookieJar *jar;
|
||||
guint timer_id;
|
||||
gint ignore_changed_count;
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_STORE,
|
||||
PROP_PARENT
|
||||
};
|
||||
|
||||
|
||||
|
@ -69,7 +66,6 @@ static void cm_button_delete_all_clicked_cb(GtkToolButton *button, CookieManager
|
|||
static void cm_tree_popup_collapse_activate_cb(GtkMenuItem *item, CookieManagerPage *cmp);
|
||||
static void cm_tree_popup_expand_activate_cb(GtkMenuItem *item, CookieManagerPage *cmp);
|
||||
static void cm_filter_tree(CookieManagerPage *cmp, const gchar *filter_text);
|
||||
static void cm_jar_changed_cb(SoupCookieJar *jar, SoupCookie *old, SoupCookie *new, CookieManagerPage *cmp);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE(CookieManagerPage, cookie_manager_page, GTK_TYPE_VBOX,
|
||||
|
@ -90,22 +86,6 @@ static const gchar *cookie_manager_page_get_stock_id(MidoriViewable *viewable)
|
|||
}
|
||||
|
||||
|
||||
static void cm_free_cookie_list(CookieManagerPage *cmp)
|
||||
{
|
||||
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp);
|
||||
|
||||
if (priv->cookies != NULL)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = priv->cookies; l != NULL; l = g_slist_next(l))
|
||||
soup_cookie_free(l->data);
|
||||
g_slist_free(priv->cookies);
|
||||
priv->cookies = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void cm_create_toolbar(CookieManagerPage *cmp)
|
||||
{
|
||||
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp);
|
||||
|
@ -174,73 +154,19 @@ static void cookie_manager_page_viewable_iface_init(MidoriViewableIface* iface)
|
|||
}
|
||||
|
||||
|
||||
static void cookie_manager_page_finalize(GObject *object)
|
||||
static void cookie_manager_page_pre_cookies_change_cb(CookieManager *cm, CookieManagerPage *cmp)
|
||||
{
|
||||
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(object);
|
||||
|
||||
g_signal_handlers_disconnect_by_func(priv->jar, cm_jar_changed_cb, object);
|
||||
|
||||
if (priv->timer_id > 0)
|
||||
g_source_remove(priv->timer_id);
|
||||
|
||||
cm_free_cookie_list(COOKIE_MANAGER_PAGE(object));
|
||||
|
||||
gtk_widget_destroy(priv->popup_menu);
|
||||
|
||||
G_OBJECT_CLASS(cookie_manager_page_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
|
||||
static void cm_refresh_store(CookieManagerPage *cmp)
|
||||
{
|
||||
GSList *l;
|
||||
GHashTable *parents;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeIter *parent_iter;
|
||||
SoupCookie *cookie;
|
||||
const gchar *filter_text;
|
||||
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp);
|
||||
|
||||
g_object_ref(priv->filter);
|
||||
gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview), NULL);
|
||||
}
|
||||
|
||||
gtk_tree_store_clear(priv->store);
|
||||
|
||||
/* free the old list */
|
||||
cm_free_cookie_list(cmp);
|
||||
|
||||
priv->cookies = soup_cookie_jar_all_cookies(priv->jar);
|
||||
|
||||
/* Hashtable holds domain names as keys, the corresponding tree iters as values */
|
||||
parents = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
|
||||
|
||||
for (l = priv->cookies; l != NULL; l = g_slist_next(l))
|
||||
{
|
||||
cookie = l->data;
|
||||
|
||||
/* look for the parent item for the current domain name and create it if it doesn't exist */
|
||||
if ((parent_iter = (GtkTreeIter*) g_hash_table_lookup(parents, cookie->domain)) == NULL)
|
||||
{
|
||||
parent_iter = g_new0(GtkTreeIter, 1);
|
||||
|
||||
gtk_tree_store_append(priv->store, parent_iter, NULL);
|
||||
gtk_tree_store_set(priv->store, parent_iter,
|
||||
COOKIE_MANAGER_COL_NAME, cookie->domain,
|
||||
COOKIE_MANAGER_COL_COOKIE, NULL,
|
||||
COOKIE_MANAGER_COL_VISIBLE, TRUE,
|
||||
-1);
|
||||
|
||||
g_hash_table_insert(parents, g_strdup(cookie->domain), parent_iter);
|
||||
}
|
||||
|
||||
gtk_tree_store_append(priv->store, &iter, parent_iter);
|
||||
gtk_tree_store_set(priv->store, &iter,
|
||||
COOKIE_MANAGER_COL_NAME, cookie->name,
|
||||
COOKIE_MANAGER_COL_COOKIE, cookie,
|
||||
COOKIE_MANAGER_COL_VISIBLE, TRUE,
|
||||
-1);
|
||||
}
|
||||
g_hash_table_destroy(parents);
|
||||
static void cookie_manager_page_cookies_changed_cb(CookieManager *cm, CookieManagerPage *cmp)
|
||||
{
|
||||
const gchar *filter_text;
|
||||
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp);
|
||||
|
||||
gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview), GTK_TREE_MODEL(priv->filter));
|
||||
g_object_unref(priv->filter);
|
||||
|
@ -255,32 +181,78 @@ static void cm_refresh_store(CookieManagerPage *cmp)
|
|||
}
|
||||
|
||||
|
||||
static gboolean cm_delayed_refresh(CookieManagerPage *cmp)
|
||||
{
|
||||
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp);
|
||||
|
||||
cm_refresh_store(cmp);
|
||||
priv->timer_id = 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void cm_jar_changed_cb(SoupCookieJar *jar, SoupCookie *old, SoupCookie *new,
|
||||
static void cookie_manager_page_filter_changed_cb(CookieManager *cm, const gchar *text,
|
||||
CookieManagerPage *cmp)
|
||||
{
|
||||
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp);
|
||||
|
||||
if (priv->ignore_changed_count > 0)
|
||||
{
|
||||
priv->ignore_changed_count--;
|
||||
return;
|
||||
}
|
||||
priv->ignore_changed_filter = TRUE;
|
||||
gtk_entry_set_text(GTK_ENTRY(priv->filter_entry), text);
|
||||
priv->ignore_changed_filter = FALSE;
|
||||
}
|
||||
|
||||
/* We delay these events a little bit to avoid too many rebuilds of the tree.
|
||||
* Some websites (like Flyspray bugtrackers sent a whole bunch of cookies at once. */
|
||||
if (priv->timer_id == 0)
|
||||
priv->timer_id = g_timeout_add_seconds(1, (GSourceFunc) cm_delayed_refresh, cmp);
|
||||
|
||||
static void cookie_manager_page_finalize(GObject *object)
|
||||
{
|
||||
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(object);
|
||||
|
||||
gtk_widget_destroy(priv->popup_menu);
|
||||
|
||||
g_signal_handlers_disconnect_by_func(priv->parent,
|
||||
cookie_manager_page_pre_cookies_change_cb, object);
|
||||
g_signal_handlers_disconnect_by_func(priv->parent,
|
||||
cookie_manager_page_cookies_changed_cb, object);
|
||||
g_signal_handlers_disconnect_by_func(priv->parent,
|
||||
cookie_manager_page_filter_changed_cb, object);
|
||||
|
||||
G_OBJECT_CLASS(cookie_manager_page_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
|
||||
static void cookie_manager_page_set_property(GObject *object, guint prop_id, const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(object);
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_STORE:
|
||||
{
|
||||
priv->store = g_value_get_object(value);
|
||||
|
||||
/* setting filter and model */
|
||||
priv->filter = gtk_tree_model_filter_new(GTK_TREE_MODEL(priv->store), NULL);
|
||||
gtk_tree_model_filter_set_visible_column(GTK_TREE_MODEL_FILTER(priv->filter),
|
||||
COOKIE_MANAGER_COL_VISIBLE);
|
||||
gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview), GTK_TREE_MODEL(priv->filter));
|
||||
g_object_unref(priv->filter);
|
||||
|
||||
break;
|
||||
}
|
||||
case PROP_PARENT:
|
||||
{
|
||||
if (priv->parent != NULL)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func(priv->parent,
|
||||
cookie_manager_page_pre_cookies_change_cb, object);
|
||||
g_signal_handlers_disconnect_by_func(priv->parent,
|
||||
cookie_manager_page_cookies_changed_cb, object);
|
||||
g_signal_handlers_disconnect_by_func(priv->parent,
|
||||
cookie_manager_page_filter_changed_cb, object);
|
||||
}
|
||||
priv->parent = g_value_get_object(value);
|
||||
|
||||
g_signal_connect(priv->parent, "pre-cookies-change",
|
||||
G_CALLBACK(cookie_manager_page_pre_cookies_change_cb), object);
|
||||
g_signal_connect(priv->parent, "cookies-changed",
|
||||
G_CALLBACK(cookie_manager_page_cookies_changed_cb), object);
|
||||
g_signal_connect(priv->parent, "filter-changed",
|
||||
G_CALLBACK(cookie_manager_page_filter_changed_cb), object);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -288,7 +260,27 @@ static void cookie_manager_page_class_init(CookieManagerPageClass *klass)
|
|||
{
|
||||
GObjectClass *g_object_class;
|
||||
g_object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
g_object_class->finalize = cookie_manager_page_finalize;
|
||||
g_object_class->set_property = cookie_manager_page_set_property;
|
||||
|
||||
g_object_class_install_property(g_object_class,
|
||||
PROP_STORE,
|
||||
g_param_spec_object(
|
||||
"store",
|
||||
"Treestore",
|
||||
"The tree store",
|
||||
GTK_TYPE_TREE_STORE,
|
||||
G_PARAM_WRITABLE));
|
||||
|
||||
g_object_class_install_property(g_object_class,
|
||||
PROP_PARENT,
|
||||
g_param_spec_object(
|
||||
"parent",
|
||||
"Parent",
|
||||
"The CookieManager parent instance",
|
||||
COOKIE_MANAGER_TYPE,
|
||||
G_PARAM_WRITABLE));
|
||||
|
||||
g_type_class_add_private(klass, sizeof(CookieManagerPagePrivate));
|
||||
}
|
||||
|
@ -346,13 +338,7 @@ static void cm_delete_cookie(CookieManagerPage *cmp, GtkTreeModel *model, GtkTre
|
|||
|
||||
gtk_tree_model_get(model, child, COOKIE_MANAGER_COL_COOKIE, &cookie, -1);
|
||||
|
||||
if (cookie != NULL)
|
||||
{
|
||||
priv->ignore_changed_count++;
|
||||
|
||||
soup_cookie_jar_delete_cookie(priv->jar, cookie);
|
||||
/* the SoupCookie object is freed when the whole list gets updated */
|
||||
}
|
||||
cookie_manager_delete_cookie(priv->parent, cookie);
|
||||
}
|
||||
|
||||
|
||||
|
@ -670,11 +656,17 @@ static void cm_filter_tree(CookieManagerPage *cmp, const gchar *filter_text)
|
|||
|
||||
static void cm_filter_entry_changed_cb(GtkEditable *editable, CookieManagerPage *cmp)
|
||||
{
|
||||
const gchar *text = gtk_entry_get_text(GTK_ENTRY(editable));
|
||||
const gchar *text;
|
||||
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp);
|
||||
|
||||
if (priv->ignore_changed_filter)
|
||||
return;
|
||||
|
||||
text = gtk_entry_get_text(GTK_ENTRY(editable));
|
||||
cm_filter_tree(cmp, text);
|
||||
|
||||
cookie_manager_update_filter(priv->parent, text);
|
||||
|
||||
if (*text != '\0')
|
||||
gtk_tree_view_expand_all(GTK_TREE_VIEW(priv->treeview));
|
||||
else
|
||||
|
@ -830,20 +822,6 @@ static GtkWidget *cm_tree_prepare(CookieManagerPage *cmp)
|
|||
sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
|
||||
gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
|
||||
|
||||
/* create the main store */
|
||||
priv->store = gtk_tree_store_new(COOKIE_MANAGER_N_COLUMNS,
|
||||
G_TYPE_STRING, SOUP_TYPE_COOKIE, G_TYPE_BOOLEAN);
|
||||
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(priv->store),
|
||||
COOKIE_MANAGER_COL_NAME, GTK_SORT_ASCENDING);
|
||||
|
||||
/* setting filter and model */
|
||||
priv->filter = gtk_tree_model_filter_new(GTK_TREE_MODEL(priv->store), NULL);
|
||||
gtk_tree_model_filter_set_visible_column(GTK_TREE_MODEL_FILTER(priv->filter),
|
||||
COOKIE_MANAGER_COL_VISIBLE);
|
||||
gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview), GTK_TREE_MODEL(priv->filter));
|
||||
g_object_unref(priv->store);
|
||||
g_object_unref(priv->filter);
|
||||
|
||||
/* signals */
|
||||
g_signal_connect(sel, "changed", G_CALLBACK(cm_tree_selection_changed_cb), cmp);
|
||||
g_signal_connect(treeview, "button-press-event", G_CALLBACK(cm_tree_button_press_event_cb), cmp);
|
||||
|
@ -909,9 +887,12 @@ static void cookie_manager_page_init(CookieManagerPage *self)
|
|||
GtkWidget *filter_hbox;
|
||||
GtkWidget *filter_label;
|
||||
GtkWidget *treeview;
|
||||
SoupSession *session;
|
||||
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(self);
|
||||
|
||||
priv->parent = NULL;
|
||||
priv->store = NULL;
|
||||
priv->ignore_changed_filter = FALSE;
|
||||
|
||||
cm_create_toolbar(self);
|
||||
|
||||
priv->desc_label = gtk_label_new(CM_EMPTY_LABEL_TEXT);
|
||||
|
@ -968,18 +949,19 @@ static void cookie_manager_page_init(CookieManagerPage *self)
|
|||
|
||||
gtk_box_pack_start(GTK_BOX(self), filter_hbox, FALSE, FALSE, 5);
|
||||
gtk_box_pack_start(GTK_BOX(self), paned, TRUE, TRUE, 0);
|
||||
|
||||
/* setup soup */
|
||||
session = webkit_get_default_session();
|
||||
priv->jar = SOUP_COOKIE_JAR(soup_session_get_feature(session, soup_cookie_jar_get_type()));
|
||||
g_signal_connect(priv->jar, "changed", G_CALLBACK(cm_jar_changed_cb), self);
|
||||
|
||||
cm_refresh_store(self);
|
||||
}
|
||||
|
||||
|
||||
GtkWidget *cookie_manager_page_new(void)
|
||||
GtkWidget *cookie_manager_page_new(CookieManager *parent, GtkTreeStore *store,
|
||||
const gchar *filter_text)
|
||||
{
|
||||
return g_object_new(COOKIE_MANAGER_PAGE_TYPE, NULL);
|
||||
GtkWidget *cmp;
|
||||
|
||||
cmp = g_object_new(COOKIE_MANAGER_PAGE_TYPE, "parent", parent, "store", store, NULL);
|
||||
|
||||
if (filter_text != NULL)
|
||||
cookie_manager_page_filter_changed_cb(parent, filter_text, COOKIE_MANAGER_PAGE(cmp));
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,9 @@ struct _CookieManagerPageClass
|
|||
};
|
||||
|
||||
GType cookie_manager_page_get_type (void);
|
||||
GtkWidget* cookie_manager_page_new (void);
|
||||
GtkWidget* cookie_manager_page_new (CookieManager *parent,
|
||||
GtkTreeStore *store,
|
||||
const gchar *filter_text);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
@ -16,115 +16,324 @@
|
|||
#include "cookie-manager.h"
|
||||
#include "cookie-manager-page.h"
|
||||
|
||||
typedef struct _CookieManagerPrivate CookieManagerPrivate;
|
||||
|
||||
#define COOKIE_MANAGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj),\
|
||||
COOKIE_MANAGER_TYPE, CookieManagerPrivate))
|
||||
|
||||
typedef struct
|
||||
struct _CookieManager
|
||||
{
|
||||
GObject parent;
|
||||
};
|
||||
|
||||
struct _CookieManagerClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
struct _CookieManagerPrivate
|
||||
{
|
||||
MidoriApp *app;
|
||||
MidoriBrowser *browser;
|
||||
MidoriExtension *extension;
|
||||
GtkWidget *panel_page;
|
||||
} CMData;
|
||||
|
||||
static void cm_app_add_browser_cb(MidoriApp *app, MidoriBrowser *browser, MidoriExtension *ext);
|
||||
static void cm_deactivate_cb(MidoriExtension *extension, CMData *cmdata);
|
||||
GSList *panel_pages;
|
||||
|
||||
GtkTreeStore *store;
|
||||
GSList *cookies;
|
||||
SoupCookieJar *jar;
|
||||
guint timer_id;
|
||||
gint ignore_changed_count;
|
||||
|
||||
gchar *filter_text;
|
||||
};
|
||||
|
||||
static void cm_browser_close_cb(GtkObject *browser, CMData *cmdata)
|
||||
static void cookie_manager_finalize(GObject *object);
|
||||
static void cookie_manager_app_add_browser_cb(MidoriApp *app, MidoriBrowser *browser,
|
||||
CookieManager *cm);
|
||||
|
||||
enum
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func(cmdata->extension, cm_deactivate_cb, cmdata);
|
||||
g_signal_handlers_disconnect_by_func(cmdata->browser, cm_browser_close_cb, cmdata);
|
||||
COOKIES_CHANGED,
|
||||
PRE_COOKIES_CHANGE,
|
||||
FILTER_CHANGED,
|
||||
|
||||
/* the panel_page widget gets destroyed automatically when a browser is closed but not
|
||||
* when the extension is deactivated */
|
||||
if (cmdata->panel_page != NULL && IS_COOKIE_MANAGER_PAGE(cmdata->panel_page))
|
||||
gtk_widget_destroy(cmdata->panel_page);
|
||||
LAST_SIGNAL
|
||||
};
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
g_free(cmdata);
|
||||
|
||||
G_DEFINE_TYPE(CookieManager, cookie_manager, G_TYPE_OBJECT);
|
||||
|
||||
|
||||
static void cookie_manager_class_init(CookieManagerClass *klass)
|
||||
{
|
||||
GObjectClass *g_object_class;
|
||||
|
||||
g_object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
g_object_class->finalize = cookie_manager_finalize;
|
||||
|
||||
signals[COOKIES_CHANGED] = g_signal_new(
|
||||
"cookies-changed",
|
||||
G_TYPE_FROM_CLASS(klass),
|
||||
(GSignalFlags) 0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
signals[PRE_COOKIES_CHANGE] = g_signal_new(
|
||||
"pre-cookies-change",
|
||||
G_TYPE_FROM_CLASS(klass),
|
||||
(GSignalFlags) 0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
signals[FILTER_CHANGED] = g_signal_new(
|
||||
"filter-changed",
|
||||
G_TYPE_FROM_CLASS(klass),
|
||||
(GSignalFlags) 0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__STRING,
|
||||
G_TYPE_NONE, 1, G_TYPE_STRING);
|
||||
|
||||
g_type_class_add_private(klass, sizeof(CookieManagerPrivate));
|
||||
}
|
||||
|
||||
|
||||
static void cm_deactivate_cb(MidoriExtension *extension, CMData *cmdata)
|
||||
static void cookie_manager_panel_pages_foreach(gpointer ptr, gpointer data)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func(cmdata->app, cm_app_add_browser_cb, extension);
|
||||
cm_browser_close_cb(NULL, cmdata);
|
||||
if (ptr != NULL && GTK_IS_WIDGET(ptr))
|
||||
gtk_widget_destroy(GTK_WIDGET(ptr));
|
||||
}
|
||||
|
||||
|
||||
static void cm_app_add_browser_cb(MidoriApp *app, MidoriBrowser *browser, MidoriExtension *ext)
|
||||
static void cookie_manager_page_destroy_cb(GtkObject *page, CookieManager *cm)
|
||||
{
|
||||
GtkWidget *panel;
|
||||
CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm);
|
||||
|
||||
priv->panel_pages = g_slist_remove(priv->panel_pages, page);
|
||||
}
|
||||
|
||||
|
||||
static void cookie_manager_app_add_browser_cb(MidoriApp *app, MidoriBrowser *browser,
|
||||
CookieManager *cm)
|
||||
{
|
||||
MidoriPanel *panel;
|
||||
GtkWidget *page;
|
||||
CMData *cmdata;
|
||||
CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm);
|
||||
|
||||
panel = katze_object_get_object(browser, "panel");
|
||||
|
||||
page = cookie_manager_page_new();
|
||||
page = cookie_manager_page_new(cm, priv->store, priv->filter_text);
|
||||
gtk_widget_show(page);
|
||||
midori_panel_append_page(MIDORI_PANEL(panel), MIDORI_VIEWABLE(page));
|
||||
midori_panel_append_page(panel, MIDORI_VIEWABLE(page));
|
||||
g_signal_connect(page, "destroy", G_CALLBACK(cookie_manager_page_destroy_cb), cm);
|
||||
|
||||
cmdata = g_new0(CMData, 1);
|
||||
cmdata->app = app;
|
||||
cmdata->browser = browser;
|
||||
cmdata->extension = ext;
|
||||
cmdata->panel_page = page;
|
||||
|
||||
g_signal_connect(browser, "destroy", G_CALLBACK(cm_browser_close_cb), cmdata);
|
||||
g_signal_connect(ext, "deactivate", G_CALLBACK(cm_deactivate_cb), cmdata);
|
||||
priv->panel_pages = g_slist_append(priv->panel_pages, page);
|
||||
|
||||
g_object_unref(panel);
|
||||
}
|
||||
|
||||
|
||||
static void cm_activate_cb(MidoriExtension *extension, MidoriApp *app, gpointer data)
|
||||
static void cookie_manager_free_cookie_list(CookieManager *cm)
|
||||
{
|
||||
CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm);
|
||||
|
||||
if (priv->cookies != NULL)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = priv->cookies; l != NULL; l = g_slist_next(l))
|
||||
soup_cookie_free(l->data);
|
||||
g_slist_free(priv->cookies);
|
||||
priv->cookies = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void cookie_manager_refresh_store(CookieManager *cm)
|
||||
{
|
||||
GSList *l;
|
||||
GHashTable *parents;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeIter *parent_iter;
|
||||
SoupCookie *cookie;
|
||||
CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm);
|
||||
|
||||
g_signal_emit(cm, signals[PRE_COOKIES_CHANGE], 0);
|
||||
|
||||
gtk_tree_store_clear(priv->store);
|
||||
|
||||
/* free the old list */
|
||||
cookie_manager_free_cookie_list(cm);
|
||||
|
||||
priv->cookies = soup_cookie_jar_all_cookies(priv->jar);
|
||||
|
||||
/* Hashtable holds domain names as keys, the corresponding tree iters as values */
|
||||
parents = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
|
||||
|
||||
for (l = priv->cookies; l != NULL; l = g_slist_next(l))
|
||||
{
|
||||
cookie = l->data;
|
||||
|
||||
/* look for the parent item for the current domain name and create it if it doesn't exist */
|
||||
if ((parent_iter = (GtkTreeIter*) g_hash_table_lookup(parents, cookie->domain)) == NULL)
|
||||
{
|
||||
parent_iter = g_new0(GtkTreeIter, 1);
|
||||
|
||||
gtk_tree_store_append(priv->store, parent_iter, NULL);
|
||||
gtk_tree_store_set(priv->store, parent_iter,
|
||||
COOKIE_MANAGER_COL_NAME, cookie->domain,
|
||||
COOKIE_MANAGER_COL_COOKIE, NULL,
|
||||
COOKIE_MANAGER_COL_VISIBLE, TRUE,
|
||||
-1);
|
||||
|
||||
g_hash_table_insert(parents, g_strdup(cookie->domain), parent_iter);
|
||||
}
|
||||
|
||||
gtk_tree_store_append(priv->store, &iter, parent_iter);
|
||||
gtk_tree_store_set(priv->store, &iter,
|
||||
COOKIE_MANAGER_COL_NAME, cookie->name,
|
||||
COOKIE_MANAGER_COL_COOKIE, cookie,
|
||||
COOKIE_MANAGER_COL_VISIBLE, TRUE,
|
||||
-1);
|
||||
}
|
||||
g_hash_table_destroy(parents);
|
||||
|
||||
g_signal_emit(cm, signals[COOKIES_CHANGED], 0);
|
||||
}
|
||||
|
||||
|
||||
static gboolean cookie_manager_delayed_refresh(CookieManager *cm)
|
||||
{
|
||||
CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm);
|
||||
|
||||
cookie_manager_refresh_store(cm);
|
||||
priv->timer_id = 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void cookie_manager_jar_changed_cb(SoupCookieJar *jar, SoupCookie *old, SoupCookie *new,
|
||||
CookieManager *cm)
|
||||
{
|
||||
CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm);
|
||||
|
||||
if (priv->ignore_changed_count > 0)
|
||||
{
|
||||
priv->ignore_changed_count--;
|
||||
return;
|
||||
}
|
||||
|
||||
/* We delay these events a little bit to avoid too many rebuilds of the tree.
|
||||
* Some websites (like Flyspray bugtrackers sent a whole bunch of cookies at once. */
|
||||
if (priv->timer_id == 0)
|
||||
priv->timer_id = g_timeout_add_seconds(1, (GSourceFunc) cookie_manager_delayed_refresh, cm);
|
||||
}
|
||||
|
||||
|
||||
static void cookie_manager_finalize(GObject *object)
|
||||
{
|
||||
CookieManager *cm = COOKIE_MANAGER(object);
|
||||
CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm);
|
||||
|
||||
g_signal_handlers_disconnect_by_func(priv->app, cookie_manager_app_add_browser_cb, cm);
|
||||
g_signal_handlers_disconnect_by_func(priv->jar, cookie_manager_jar_changed_cb, cm);
|
||||
|
||||
/* remove all panel pages from open windows */
|
||||
g_slist_foreach(priv->panel_pages, cookie_manager_panel_pages_foreach, NULL);
|
||||
g_slist_free(priv->panel_pages);
|
||||
|
||||
/* clean cookies */
|
||||
if (priv->timer_id > 0)
|
||||
g_source_remove(priv->timer_id);
|
||||
|
||||
cookie_manager_free_cookie_list(cm);
|
||||
|
||||
g_object_unref(priv->store);
|
||||
g_free(priv->filter_text);
|
||||
|
||||
G_OBJECT_CLASS(cookie_manager_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
|
||||
static void cookie_manager_init(CookieManager *self)
|
||||
{
|
||||
CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(self);
|
||||
SoupSession *session;
|
||||
|
||||
priv->filter_text = NULL;
|
||||
priv->panel_pages = NULL;
|
||||
/* create the main store */
|
||||
priv->store = gtk_tree_store_new(COOKIE_MANAGER_N_COLUMNS,
|
||||
G_TYPE_STRING, SOUP_TYPE_COOKIE, G_TYPE_BOOLEAN);
|
||||
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(priv->store),
|
||||
COOKIE_MANAGER_COL_NAME, GTK_SORT_ASCENDING);
|
||||
|
||||
/* setup soup */
|
||||
session = webkit_get_default_session();
|
||||
priv->jar = SOUP_COOKIE_JAR(soup_session_get_feature(session, soup_cookie_jar_get_type()));
|
||||
g_signal_connect(priv->jar, "changed", G_CALLBACK(cookie_manager_jar_changed_cb), self);
|
||||
|
||||
cookie_manager_refresh_store(self);
|
||||
}
|
||||
|
||||
|
||||
void cookie_manager_update_filter(CookieManager *cm, const gchar *text)
|
||||
{
|
||||
CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm);
|
||||
|
||||
katze_assign(priv->filter_text, g_strdup(text));
|
||||
|
||||
g_signal_emit(cm, signals[FILTER_CHANGED], 0, text);
|
||||
}
|
||||
|
||||
|
||||
void cookie_manager_delete_cookie(CookieManager *cm, SoupCookie *cookie)
|
||||
{
|
||||
CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm);
|
||||
|
||||
if (cookie != NULL)
|
||||
{
|
||||
priv->ignore_changed_count++;
|
||||
|
||||
soup_cookie_jar_delete_cookie(priv->jar, cookie);
|
||||
/* the SoupCookie object is freed when the whole list gets updated */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CookieManager *cookie_manager_new(MidoriExtension *extension, MidoriApp *app)
|
||||
{
|
||||
CookieManager *cm;
|
||||
CookieManagerPrivate *priv;
|
||||
guint i;
|
||||
KatzeArray *browsers;
|
||||
MidoriBrowser *browser;
|
||||
|
||||
cm = g_object_new(COOKIE_MANAGER_TYPE, NULL);
|
||||
|
||||
priv = COOKIE_MANAGER_GET_PRIVATE(cm);
|
||||
priv->app = app;
|
||||
priv->extension = extension;
|
||||
|
||||
/* add the cookie manager panel page to existing browsers */
|
||||
browsers = katze_object_get_object(app, "browsers");
|
||||
i = 0;
|
||||
while ((browser = katze_array_get_nth_item(browsers, i++)))
|
||||
cm_app_add_browser_cb(app, browser, extension);
|
||||
cookie_manager_app_add_browser_cb(app, browser, cm);
|
||||
g_object_unref(browsers);
|
||||
|
||||
g_signal_connect(app, "add-browser", G_CALLBACK(cm_app_add_browser_cb), extension);
|
||||
g_signal_connect(app, "add-browser", G_CALLBACK(cookie_manager_app_add_browser_cb), cm);
|
||||
|
||||
return cm;
|
||||
}
|
||||
|
||||
|
||||
MidoriExtension *extension_init(void)
|
||||
{
|
||||
MidoriExtension *extension;
|
||||
GtkIconFactory *factory;
|
||||
GtkIconSource *icon_source;
|
||||
GtkIconSet *icon_set;
|
||||
static GtkStockItem items[] =
|
||||
{
|
||||
{ STOCK_COOKIE_MANAGER, N_("_Cookie Manager"), 0, 0, NULL }
|
||||
};
|
||||
|
||||
factory = gtk_icon_factory_new();
|
||||
gtk_stock_add(items, G_N_ELEMENTS(items));
|
||||
icon_set = gtk_icon_set_new();
|
||||
icon_source = gtk_icon_source_new();
|
||||
gtk_icon_source_set_icon_name(icon_source, GTK_STOCK_DIALOG_AUTHENTICATION);
|
||||
gtk_icon_set_add_source(icon_set, icon_source);
|
||||
gtk_icon_source_free(icon_source);
|
||||
gtk_icon_factory_add(factory, STOCK_COOKIE_MANAGER, icon_set);
|
||||
gtk_icon_set_unref(icon_set);
|
||||
gtk_icon_factory_add_default(factory);
|
||||
g_object_unref(factory);
|
||||
|
||||
extension = g_object_new(MIDORI_TYPE_EXTENSION,
|
||||
"name", _("Cookie Manager"),
|
||||
"description", _("List, view and delete cookies"),
|
||||
"version", "0.2",
|
||||
"authors", "Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>",
|
||||
NULL);
|
||||
|
||||
g_signal_connect(extension, "activate", G_CALLBACK(cm_activate_cb), NULL);
|
||||
|
||||
return extension;
|
||||
}
|
||||
|
|
|
@ -13,8 +13,38 @@
|
|||
#ifndef __COOKIE_MANAGER_H__
|
||||
#define __COOKIE_MANAGER_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define STOCK_COOKIE_MANAGER "cookie-manager"
|
||||
|
||||
enum
|
||||
{
|
||||
COOKIE_MANAGER_COL_NAME,
|
||||
COOKIE_MANAGER_COL_COOKIE,
|
||||
COOKIE_MANAGER_COL_VISIBLE,
|
||||
COOKIE_MANAGER_N_COLUMNS
|
||||
};
|
||||
|
||||
#endif /* __COOKIE_MANAGER_H__ */
|
||||
|
||||
#define COOKIE_MANAGER_TYPE (cookie_manager_get_type())
|
||||
#define COOKIE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
|
||||
COOKIE_MANAGER_TYPE, CookieManager))
|
||||
#define COOKIE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\
|
||||
COOKIE_MANAGER_TYPE, CookieManagerClass))
|
||||
#define IS_COOKIE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\
|
||||
COOKIE_MANAGER_TYPE))
|
||||
#define IS_COOKIE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\
|
||||
COOKIE_MANAGER_TYPE))
|
||||
|
||||
typedef struct _CookieManager CookieManager;
|
||||
typedef struct _CookieManagerClass CookieManagerClass;
|
||||
|
||||
GType cookie_manager_get_type (void);
|
||||
CookieManager* cookie_manager_new (MidoriExtension *extension, MidoriApp *app);
|
||||
|
||||
void cookie_manager_delete_cookie(CookieManager *cm, SoupCookie *cookie);
|
||||
void cookie_manager_update_filter(CookieManager *cm, const gchar *text);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __COOKIE-MANAGER_H__ */
|
||||
|
|
66
extensions/cookie-manager/main.c
Normal file
66
extensions/cookie-manager/main.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
Copyright (C) 2009 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <midori/midori.h>
|
||||
|
||||
#include "cookie-manager.h"
|
||||
|
||||
CookieManager *cm = NULL;
|
||||
|
||||
|
||||
static void cm_deactivate_cb(MidoriExtension *extension, gpointer data)
|
||||
{
|
||||
g_object_unref(cm);
|
||||
}
|
||||
|
||||
|
||||
static void cm_activate_cb(MidoriExtension *extension, MidoriApp *app, gpointer data)
|
||||
{
|
||||
cm = cookie_manager_new(extension, app);
|
||||
}
|
||||
|
||||
|
||||
MidoriExtension *extension_init(void)
|
||||
{
|
||||
MidoriExtension *extension;
|
||||
GtkIconFactory *factory;
|
||||
GtkIconSource *icon_source;
|
||||
GtkIconSet *icon_set;
|
||||
static GtkStockItem items[] =
|
||||
{
|
||||
{ STOCK_COOKIE_MANAGER, N_("_Cookie Manager"), 0, 0, NULL }
|
||||
};
|
||||
|
||||
factory = gtk_icon_factory_new();
|
||||
gtk_stock_add(items, G_N_ELEMENTS(items));
|
||||
icon_set = gtk_icon_set_new();
|
||||
icon_source = gtk_icon_source_new();
|
||||
gtk_icon_source_set_icon_name(icon_source, GTK_STOCK_DIALOG_AUTHENTICATION);
|
||||
gtk_icon_set_add_source(icon_set, icon_source);
|
||||
gtk_icon_source_free(icon_source);
|
||||
gtk_icon_factory_add(factory, STOCK_COOKIE_MANAGER, icon_set);
|
||||
gtk_icon_set_unref(icon_set);
|
||||
gtk_icon_factory_add_default(factory);
|
||||
g_object_unref(factory);
|
||||
|
||||
extension = g_object_new(MIDORI_TYPE_EXTENSION,
|
||||
"name", _("Cookie Manager"),
|
||||
"description", _("List, view and delete cookies"),
|
||||
"version", "0.2",
|
||||
"authors", "Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>",
|
||||
NULL);
|
||||
|
||||
g_signal_connect(extension, "activate", G_CALLBACK(cm_activate_cb), NULL);
|
||||
g_signal_connect(extension, "deactivate", G_CALLBACK(cm_deactivate_cb), NULL);
|
||||
|
||||
return extension;
|
||||
}
|
|
@ -44,7 +44,7 @@ static gboolean mouse_gestures_handle_events (GtkWidget *widget,
|
|||
MidoriBrowser *browser)
|
||||
{
|
||||
/* A button was pressed */
|
||||
if (event->type == GDK_BUTTON_PRESS)
|
||||
if (event->type == GDK_BUTTON_PRESS && event->button.button == 2)
|
||||
{
|
||||
/* If the gesture was previously cleaned, start a new gesture and coordinates */
|
||||
if (gesture->last == MOUSE_BUTTON_UNSET)
|
||||
|
@ -177,32 +177,25 @@ static void mouse_gestures_browser_cb (MidoriApp *app, MidoriBrowser *browser)
|
|||
static void mouse_gestures_deactivate (MidoriExtension *extension, MidoriApp *app)
|
||||
{
|
||||
gulong signal_id;
|
||||
KatzeArray *browsers;
|
||||
KatzeArray* browsers;
|
||||
MidoriBrowser* browser;
|
||||
guint i;
|
||||
gint j;
|
||||
GtkWidget *notebook;
|
||||
|
||||
signal_id =
|
||||
g_signal_handler_find (app, G_SIGNAL_MATCH_FUNC,
|
||||
0, 0, NULL,
|
||||
signal_id = g_signal_handler_find (app, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
|
||||
mouse_gestures_browser_cb, NULL);
|
||||
|
||||
if(signal_id != 0)
|
||||
if (signal_id != 0)
|
||||
g_signal_handler_disconnect (app, signal_id);
|
||||
|
||||
browsers = katze_object_get_object (app, "browsers");
|
||||
|
||||
for (i = 0; i < katze_array_get_length (browsers); i++)
|
||||
i = 0;
|
||||
while ((browser = katze_array_get_nth_item (browsers, i++)))
|
||||
{
|
||||
MidoriBrowser *browser;
|
||||
|
||||
browser = katze_array_get_nth_item (browsers, i);
|
||||
|
||||
signal_id =
|
||||
g_signal_handler_find (browser, G_SIGNAL_MATCH_FUNC,
|
||||
0, 0, NULL,
|
||||
mouse_gestures_tab_cb, NULL);
|
||||
gint j;
|
||||
GtkWidget* notebook;
|
||||
|
||||
signal_id = g_signal_handler_find (browser, G_SIGNAL_MATCH_FUNC,
|
||||
0, 0, NULL, mouse_gestures_tab_cb, NULL);
|
||||
if (signal_id != 0)
|
||||
g_signal_handler_disconnect (browser, signal_id);
|
||||
|
||||
|
@ -212,15 +205,14 @@ static void mouse_gestures_deactivate (MidoriExtension *extension, MidoriApp *ap
|
|||
{
|
||||
GtkWidget *page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), j);
|
||||
|
||||
signal_id =
|
||||
g_signal_handler_find (page, G_SIGNAL_MATCH_FUNC,
|
||||
0, 0, NULL,
|
||||
mouse_gestures_handle_events, NULL);
|
||||
signal_id = g_signal_handler_find (page, G_SIGNAL_MATCH_FUNC,
|
||||
0, 0, NULL, mouse_gestures_handle_events, NULL);
|
||||
|
||||
if (signal_id != 0)
|
||||
g_signal_handler_disconnect (page, signal_id);
|
||||
}
|
||||
}
|
||||
g_object_unref (browsers);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (extension, mouse_gestures_deactivate, app);
|
||||
g_free (gesture);
|
||||
|
|
305
extensions/shortcuts.c
Normal file
305
extensions/shortcuts.c
Normal file
|
@ -0,0 +1,305 @@
|
|||
/*
|
||||
Copyright (C) 2009 Christian Dywan <christian@twotoasts.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#include <midori/midori.h>
|
||||
|
||||
#include <midori/sokoke.h>
|
||||
#include "config.h"
|
||||
|
||||
static void
|
||||
shortcuts_app_add_browser_cb (MidoriApp* app,
|
||||
MidoriBrowser* browser,
|
||||
MidoriExtension* extension);
|
||||
|
||||
static void
|
||||
shortcuts_deactivate_cb (MidoriExtension* extension,
|
||||
GtkWidget* menuitem)
|
||||
{
|
||||
MidoriApp* app = midori_extension_get_app (extension);
|
||||
|
||||
gtk_widget_destroy (menuitem);
|
||||
g_signal_handlers_disconnect_by_func (
|
||||
extension, shortcuts_deactivate_cb, menuitem);
|
||||
g_signal_handlers_disconnect_by_func (
|
||||
app, shortcuts_app_add_browser_cb, extension);
|
||||
}
|
||||
|
||||
static void
|
||||
shortcuts_preferences_render_text (GtkTreeViewColumn* column,
|
||||
GtkCellRenderer* renderer,
|
||||
GtkTreeModel* model,
|
||||
GtkTreeIter* iter,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
GtkAction* action;
|
||||
gchar* label;
|
||||
gchar* stripped;
|
||||
|
||||
gtk_tree_model_get (model, iter, 0, &action, -1);
|
||||
if ((label = katze_object_get_string (action, "label")))
|
||||
stripped = katze_strip_mnemonics (label);
|
||||
else
|
||||
{
|
||||
GtkStockItem item;
|
||||
g_object_get (action, "stock-id", &label, NULL);
|
||||
if (gtk_stock_lookup (label, &item))
|
||||
stripped = katze_strip_mnemonics (item.label);
|
||||
else
|
||||
stripped = g_strdup ("");
|
||||
}
|
||||
g_free (label);
|
||||
g_object_set (renderer, "text", stripped, NULL);
|
||||
g_free (stripped);
|
||||
g_object_unref (action);
|
||||
}
|
||||
|
||||
static void
|
||||
shortcuts_preferences_render_accel (GtkTreeViewColumn* column,
|
||||
GtkCellRenderer* renderer,
|
||||
GtkTreeModel* model,
|
||||
GtkTreeIter* iter,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
GtkAction* action;
|
||||
const gchar* accel_path;
|
||||
GtkAccelKey key;
|
||||
|
||||
gtk_tree_model_get (model, iter, 0, &action, -1);
|
||||
accel_path = gtk_action_get_accel_path (action);
|
||||
if (accel_path)
|
||||
{
|
||||
if (gtk_accel_map_lookup_entry (accel_path, &key))
|
||||
{
|
||||
if (key.accel_key)
|
||||
g_object_set (renderer,
|
||||
"accel-key", key.accel_key,
|
||||
"accel-mods", key.accel_mods,
|
||||
NULL);
|
||||
else
|
||||
g_object_set (renderer, "text", _("None"), NULL);
|
||||
}
|
||||
g_object_set (renderer, "sensitive", TRUE, "editable", TRUE, NULL);
|
||||
}
|
||||
else
|
||||
g_object_set (renderer, "text", "", "sensitive", FALSE, NULL);
|
||||
g_object_unref (action);
|
||||
}
|
||||
|
||||
static void
|
||||
shortcuts_accel_edited_cb (GtkCellRenderer* renderer,
|
||||
const gchar* tree_path,
|
||||
guint accel_key,
|
||||
GdkModifierType accel_mods,
|
||||
guint keycode,
|
||||
GtkTreeModel* model)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (gtk_tree_model_get_iter_from_string (model, &iter, tree_path))
|
||||
{
|
||||
GtkAction* action;
|
||||
const gchar* accel_path;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &action, -1);
|
||||
accel_path = gtk_action_get_accel_path (action);
|
||||
gtk_accel_map_change_entry (accel_path, accel_key, accel_mods, TRUE);
|
||||
|
||||
g_object_unref (action);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
shortcuts_accel_cleared_cb (GtkCellRenderer* renderer,
|
||||
const gchar* tree_path,
|
||||
GtkTreeModel* model)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (gtk_tree_model_get_iter_from_string (model, &iter, tree_path))
|
||||
{
|
||||
GtkAction* action;
|
||||
const gchar* accel_path;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &action, -1);
|
||||
accel_path = gtk_action_get_accel_path (action);
|
||||
gtk_accel_map_change_entry (accel_path, 0, 0, FALSE);
|
||||
|
||||
g_object_unref (action);
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
shortcuts_get_preferences_dialog (MidoriExtension* extension)
|
||||
{
|
||||
MidoriApp* app;
|
||||
GtkWidget* browser;
|
||||
const gchar* dialog_title;
|
||||
GtkWidget* dialog;
|
||||
gint width, height;
|
||||
GtkWidget* xfce_heading;
|
||||
GtkWidget* hbox;
|
||||
GtkListStore* liststore;
|
||||
GtkWidget* treeview;
|
||||
GtkTreeViewColumn* column;
|
||||
GtkCellRenderer* renderer_text;
|
||||
GtkCellRenderer* renderer_accel;
|
||||
GtkWidget* scrolled;
|
||||
GtkActionGroup* action_group;
|
||||
GList* actions;
|
||||
guint i;
|
||||
GtkAction* action;
|
||||
#if HAVE_OSX
|
||||
GtkWidget* icon;
|
||||
#endif
|
||||
|
||||
app = midori_extension_get_app (extension);
|
||||
browser = katze_object_get_object (app, "browser");
|
||||
|
||||
dialog_title = _("Configure Keyboard shortcuts");
|
||||
dialog = gtk_dialog_new_with_buttons (dialog_title, GTK_WINDOW (browser),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
|
||||
#if !HAVE_OSX
|
||||
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
|
||||
#endif
|
||||
NULL);
|
||||
g_signal_connect (dialog, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &dialog);
|
||||
gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_PROPERTIES);
|
||||
sokoke_widget_get_text_size (dialog, "M", &width, &height);
|
||||
gtk_window_set_default_size (GTK_WINDOW (dialog), width * 52, height * 24);
|
||||
g_signal_connect (dialog, "response",
|
||||
G_CALLBACK (gtk_widget_destroy), dialog);
|
||||
if ((xfce_heading = sokoke_xfce_header_new (
|
||||
gtk_window_get_icon_name (GTK_WINDOW (dialog)), dialog_title)))
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
|
||||
xfce_heading, FALSE, FALSE, 0);
|
||||
hbox = gtk_hbox_new (FALSE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
|
||||
TRUE, TRUE, 12);
|
||||
liststore = gtk_list_store_new (1, GTK_TYPE_ACTION);
|
||||
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (liststore));
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
|
||||
column = gtk_tree_view_column_new ();
|
||||
renderer_text = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
|
||||
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
|
||||
(GtkTreeCellDataFunc)shortcuts_preferences_render_text,
|
||||
extension, NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
column = gtk_tree_view_column_new ();
|
||||
renderer_accel = gtk_cell_renderer_accel_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer_accel, TRUE);
|
||||
gtk_tree_view_column_set_cell_data_func (column, renderer_accel,
|
||||
(GtkTreeCellDataFunc)shortcuts_preferences_render_accel,
|
||||
extension, NULL);
|
||||
g_signal_connect (renderer_accel, "accel-edited",
|
||||
G_CALLBACK (shortcuts_accel_edited_cb), liststore);
|
||||
g_signal_connect (renderer_accel, "accel-cleared",
|
||||
G_CALLBACK (shortcuts_accel_cleared_cb), liststore);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
scrolled = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
|
||||
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||
gtk_container_add (GTK_CONTAINER (scrolled), treeview);
|
||||
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled),
|
||||
GTK_SHADOW_IN);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), scrolled, TRUE, TRUE, 5);
|
||||
|
||||
action_group = midori_browser_get_action_group (MIDORI_BROWSER (browser));
|
||||
actions = gtk_action_group_list_actions (action_group);
|
||||
i = 0;
|
||||
/* FIXME: Catch added and removed actions */
|
||||
while ((action = g_list_nth_data (actions, i++)))
|
||||
gtk_list_store_insert_with_values (GTK_LIST_STORE (liststore),
|
||||
NULL, G_MAXINT, 0, action, -1);
|
||||
g_list_free (actions);
|
||||
|
||||
g_object_unref (liststore);
|
||||
|
||||
gtk_widget_show_all (GTK_DIALOG (dialog)->vbox);
|
||||
|
||||
g_object_unref (browser);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
static void
|
||||
shortcuts_menu_configure_shortcuts_activate_cb (GtkWidget* menuitem,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
static GtkWidget* dialog = NULL;
|
||||
|
||||
if (!dialog)
|
||||
{
|
||||
dialog = shortcuts_get_preferences_dialog (extension);
|
||||
g_signal_connect (dialog, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &dialog);
|
||||
gtk_widget_show (dialog);
|
||||
}
|
||||
else
|
||||
gtk_window_present (GTK_WINDOW (dialog));
|
||||
}
|
||||
|
||||
static void
|
||||
shortcuts_app_add_browser_cb (MidoriApp* app,
|
||||
MidoriBrowser* browser,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
GtkWidget* panel;
|
||||
GtkWidget* menu;
|
||||
GtkWidget* menuitem;
|
||||
|
||||
panel = katze_object_get_object (browser, "panel");
|
||||
menu = katze_object_get_object (panel, "menu");
|
||||
g_object_unref (panel);
|
||||
menuitem = gtk_menu_item_new_with_mnemonic (_("Configure Sh_ortcuts..."));
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (shortcuts_menu_configure_shortcuts_activate_cb), extension);
|
||||
gtk_widget_show (menuitem);
|
||||
gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 3);
|
||||
g_object_unref (menu);
|
||||
|
||||
g_signal_connect (extension, "deactivate",
|
||||
G_CALLBACK (shortcuts_deactivate_cb), menuitem);
|
||||
}
|
||||
|
||||
static void
|
||||
shortcuts_activate_cb (MidoriExtension* extension,
|
||||
MidoriApp* app)
|
||||
{
|
||||
KatzeArray* browsers;
|
||||
MidoriBrowser* browser;
|
||||
guint i;
|
||||
|
||||
browsers = katze_object_get_object (app, "browsers");
|
||||
i = 0;
|
||||
while ((browser = katze_array_get_nth_item (browsers, i++)))
|
||||
shortcuts_app_add_browser_cb (app, browser, extension);
|
||||
g_signal_connect (app, "add-browser",
|
||||
G_CALLBACK (shortcuts_app_add_browser_cb), extension);
|
||||
g_object_unref (browsers);
|
||||
}
|
||||
|
||||
MidoriExtension*
|
||||
extension_init (void)
|
||||
{
|
||||
MidoriExtension* extension = g_object_new (MIDORI_TYPE_EXTENSION,
|
||||
"name", _("Shortcuts"),
|
||||
"description", _("View and edit keyboard shortcuts"),
|
||||
"version", "0.1",
|
||||
"authors", "Christian Dywan <christian@twotoasts.de>",
|
||||
NULL);
|
||||
|
||||
g_signal_connect (extension, "activate",
|
||||
G_CALLBACK (shortcuts_activate_cb), NULL);
|
||||
|
||||
return extension;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -16,13 +16,45 @@ statusbar_features_app_add_browser_cb (MidoriApp* app,
|
|||
MidoriBrowser* browser,
|
||||
MidoriExtension* extension);
|
||||
|
||||
static void
|
||||
statusbar_features_toolbar_notify_toolbar_style_cb (GtkWidget* toolbar,
|
||||
GParamSpec* pspec,
|
||||
GtkWidget* button)
|
||||
{
|
||||
GtkToolbarStyle style = katze_object_get_enum (toolbar, "toolbar-style");
|
||||
const gchar* text = g_object_get_data (G_OBJECT (button), "feature-label");
|
||||
switch (style)
|
||||
{
|
||||
case GTK_TOOLBAR_BOTH:
|
||||
case GTK_TOOLBAR_BOTH_HORIZ:
|
||||
gtk_button_set_label (GTK_BUTTON (button), text);
|
||||
gtk_widget_show (gtk_button_get_image (GTK_BUTTON (button)));
|
||||
break;
|
||||
case GTK_TOOLBAR_TEXT:
|
||||
gtk_button_set_label (GTK_BUTTON (button), text);
|
||||
gtk_widget_hide (gtk_button_get_image (GTK_BUTTON (button)));
|
||||
break;
|
||||
case GTK_TOOLBAR_ICONS:
|
||||
gtk_button_set_label (GTK_BUTTON (button), "");
|
||||
gtk_widget_show (gtk_button_get_image (GTK_BUTTON (button)));
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
statusbar_features_deactivate_cb (MidoriExtension* extension,
|
||||
GtkWidget* bbox)
|
||||
{
|
||||
MidoriApp* app = midori_extension_get_app (extension);
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (bbox);
|
||||
GtkWidget* toolbar = katze_object_get_object (browser, "navigationbar");
|
||||
|
||||
gtk_widget_destroy (bbox);
|
||||
g_signal_handlers_disconnect_matched (toolbar, G_SIGNAL_MATCH_FUNC,
|
||||
0, -1, NULL, statusbar_features_toolbar_notify_toolbar_style_cb, NULL);
|
||||
g_object_unref (toolbar);
|
||||
g_signal_handlers_disconnect_by_func (
|
||||
extension, statusbar_features_deactivate_cb, bbox);
|
||||
g_signal_handlers_disconnect_by_func (
|
||||
|
@ -37,6 +69,7 @@ statusbar_features_app_add_browser_cb (MidoriApp* app,
|
|||
GtkWidget* statusbar;
|
||||
GtkWidget* bbox;
|
||||
MidoriWebSettings* settings;
|
||||
GtkWidget* toolbar;
|
||||
GtkWidget* button;
|
||||
GtkWidget* image;
|
||||
|
||||
|
@ -46,36 +79,47 @@ statusbar_features_app_add_browser_cb (MidoriApp* app,
|
|||
statusbar = katze_object_get_object (browser, "statusbar");
|
||||
bbox = gtk_hbox_new (FALSE, 0);
|
||||
settings = katze_object_get_object (browser, "settings");
|
||||
toolbar = katze_object_get_object (browser, "navigationbar");
|
||||
button = katze_property_proxy (settings, "auto-load-images", "toggle");
|
||||
g_object_set_data (G_OBJECT (button), "feature-label", _("Images"));
|
||||
image = gtk_image_new_from_stock (STOCK_IMAGE, GTK_ICON_SIZE_MENU);
|
||||
gtk_widget_show (image);
|
||||
gtk_container_add (GTK_CONTAINER (button), image);
|
||||
gtk_button_set_image (GTK_BUTTON (button), image);
|
||||
#if GTK_CHECK_VERSION(2, 12, 0)
|
||||
gtk_widget_set_tooltip_text (button, _("Load images automatically"));
|
||||
#endif
|
||||
statusbar_features_toolbar_notify_toolbar_style_cb (toolbar, NULL, button);
|
||||
g_signal_connect (toolbar, "notify::toolbar-style",
|
||||
G_CALLBACK (statusbar_features_toolbar_notify_toolbar_style_cb), button);
|
||||
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
|
||||
gtk_widget_show (button);
|
||||
button = katze_property_proxy (settings, "enable-scripts", "toggle");
|
||||
g_object_set_data (G_OBJECT (button), "feature-label", _("Scripts"));
|
||||
image = gtk_image_new_from_stock (STOCK_SCRIPTS, GTK_ICON_SIZE_MENU);
|
||||
gtk_widget_show (image);
|
||||
gtk_container_add (GTK_CONTAINER (button), image);
|
||||
gtk_button_set_image (GTK_BUTTON (button), image);
|
||||
#if GTK_CHECK_VERSION(2, 12, 0)
|
||||
gtk_widget_set_tooltip_text (button, _("Enable scripts"));
|
||||
#endif
|
||||
statusbar_features_toolbar_notify_toolbar_style_cb (toolbar, NULL, button);
|
||||
g_signal_connect (toolbar, "notify::toolbar-style",
|
||||
G_CALLBACK (statusbar_features_toolbar_notify_toolbar_style_cb), button);
|
||||
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
|
||||
gtk_widget_show (button);
|
||||
button = katze_property_proxy (settings, "enable-plugins", "toggle");
|
||||
g_object_set_data (G_OBJECT (button), "feature-label", _("Netscape plugins"));
|
||||
image = gtk_image_new_from_stock (STOCK_PLUGINS, GTK_ICON_SIZE_MENU);
|
||||
gtk_widget_show (image);
|
||||
gtk_container_add (GTK_CONTAINER (button), image);
|
||||
gtk_button_set_image (GTK_BUTTON (button), image);
|
||||
#if GTK_CHECK_VERSION(2, 12, 0)
|
||||
gtk_widget_set_tooltip_text (button, _("Enable Netscape plugins"));
|
||||
#endif
|
||||
statusbar_features_toolbar_notify_toolbar_style_cb (toolbar, NULL, button);
|
||||
g_signal_connect (toolbar, "notify::toolbar-style",
|
||||
G_CALLBACK (statusbar_features_toolbar_notify_toolbar_style_cb), button);
|
||||
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
|
||||
gtk_widget_show (button);
|
||||
gtk_widget_show (bbox);
|
||||
gtk_box_pack_start (GTK_BOX (statusbar), bbox, FALSE, FALSE, 3);
|
||||
g_object_unref (settings);
|
||||
g_object_unref (statusbar);
|
||||
|
||||
g_signal_connect (extension, "deactivate",
|
||||
G_CALLBACK (statusbar_features_deactivate_cb), bbox);
|
||||
|
@ -95,6 +139,7 @@ statusbar_features_activate_cb (MidoriExtension* extension,
|
|||
statusbar_features_app_add_browser_cb (app, browser, extension);
|
||||
g_signal_connect (app, "add-browser",
|
||||
G_CALLBACK (statusbar_features_app_add_browser_cb), extension);
|
||||
g_object_unref (browsers);
|
||||
}
|
||||
|
||||
MidoriExtension*
|
||||
|
|
362
extensions/tab-panel.c
Normal file
362
extensions/tab-panel.c
Normal file
|
@ -0,0 +1,362 @@
|
|||
/*
|
||||
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#include <midori/midori.h>
|
||||
#include <midori/sokoke.h>
|
||||
|
||||
#define STOCK_TAB_PANEL "tab-panel"
|
||||
|
||||
static void
|
||||
tab_panel_app_add_browser_cb (MidoriApp* app,
|
||||
MidoriBrowser* browser,
|
||||
MidoriExtension* extension);
|
||||
|
||||
static void
|
||||
tab_panel_deactivate_cb (MidoriExtension* extension,
|
||||
GtkWidget* panel)
|
||||
{
|
||||
MidoriApp* app = midori_extension_get_app (extension);
|
||||
GtkTreeModel* model;
|
||||
MidoriBrowser* browser;
|
||||
|
||||
model = g_object_get_data (G_OBJECT (extension), "treemodel");
|
||||
g_object_unref (model);
|
||||
browser = midori_browser_get_for_widget (panel);
|
||||
g_object_set (browser, "show-tabs", TRUE, NULL);
|
||||
|
||||
gtk_widget_destroy (panel);
|
||||
g_signal_handlers_disconnect_by_func (
|
||||
extension, tab_panel_deactivate_cb, panel);
|
||||
g_signal_handlers_disconnect_by_func (
|
||||
app, tab_panel_app_add_browser_cb, extension);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extension_cursor_or_row_changed_cb (GtkTreeView* treeview,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extension_treeview_render_icon_cb (GtkTreeViewColumn* column,
|
||||
GtkCellRenderer* renderer,
|
||||
GtkTreeModel* model,
|
||||
GtkTreeIter* iter,
|
||||
GtkWidget* treeview)
|
||||
{
|
||||
MidoriView* view;
|
||||
GdkPixbuf* pixbuf;
|
||||
|
||||
gtk_tree_model_get (model, iter, 0, &view, -1);
|
||||
|
||||
if ((pixbuf = midori_view_get_icon (view)))
|
||||
g_object_set (renderer, "pixbuf", pixbuf, NULL);
|
||||
|
||||
g_object_unref (view);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extension_treeview_render_text_cb (GtkTreeViewColumn* column,
|
||||
GtkCellRenderer* renderer,
|
||||
GtkTreeModel* model,
|
||||
GtkTreeIter* iter,
|
||||
GtkWidget* treeview)
|
||||
{
|
||||
MidoriView* view;
|
||||
|
||||
gtk_tree_model_get (model, iter, 0, &view, -1);
|
||||
|
||||
g_object_set (renderer, "text", midori_view_get_display_title (view), NULL);
|
||||
|
||||
g_object_unref (view);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extension_row_activated_cb (GtkTreeView* treeview,
|
||||
GtkTreePath* path,
|
||||
GtkTreeViewColumn* column,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
model = gtk_tree_view_get_model (treeview);
|
||||
|
||||
if (gtk_tree_model_get_iter (model, &iter, path))
|
||||
{
|
||||
GtkWidget* view;
|
||||
MidoriBrowser* browser;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &view, -1);
|
||||
browser = midori_browser_get_for_widget (GTK_WIDGET (treeview));
|
||||
midori_browser_set_current_tab (browser, view);
|
||||
|
||||
g_object_unref (view);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extension_popup (GtkWidget* widget,
|
||||
GdkEventButton* event,
|
||||
GtkWidget* view,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
GtkWidget* menu = midori_view_get_tab_menu (MIDORI_VIEW (view));
|
||||
|
||||
sokoke_widget_popup (widget, GTK_MENU (menu),
|
||||
event, SOKOKE_MENU_POSITION_CURSOR);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
midori_extension_button_release_event_cb (GtkWidget* widget,
|
||||
GdkEventButton* event,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (event->button < 1 || event->button > 3)
|
||||
return FALSE;
|
||||
|
||||
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter))
|
||||
{
|
||||
GtkWidget* view;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &view, -1);
|
||||
|
||||
if (event->button == 1)
|
||||
{
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (widget);
|
||||
midori_browser_set_current_tab (browser, view);
|
||||
}
|
||||
else if (event->button == 2)
|
||||
gtk_widget_destroy (view);
|
||||
else
|
||||
midori_extension_popup (widget, event, view, extension);
|
||||
|
||||
g_object_unref (view);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
midori_extension_key_release_event_cb (GtkWidget* widget,
|
||||
GdkEventKey* event,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
/* Nothing to do */
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extension_popup_menu_cb (GtkWidget* widget,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter))
|
||||
{
|
||||
GtkWidget* view;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &view, -1);
|
||||
midori_extension_popup (widget, NULL, view, extension);
|
||||
g_object_unref (view);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tab_panel_browser_add_tab_cb (MidoriBrowser* browser,
|
||||
GtkWidget* view,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
GtkTreeModel* model = g_object_get_data (G_OBJECT (extension), "treemodel");
|
||||
GtkTreeIter iter;
|
||||
GtkWidget* notebook = katze_object_get_object (browser, "notebook");
|
||||
gint page = gtk_notebook_page_num (GTK_NOTEBOOK (notebook), view);
|
||||
g_object_unref (notebook);
|
||||
gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
|
||||
&iter, NULL, page, 0, view, -1);
|
||||
}
|
||||
|
||||
static void
|
||||
tab_panel_browser_foreach_cb (GtkWidget* view,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
tab_panel_browser_add_tab_cb (midori_browser_get_for_widget (view),
|
||||
view, extension);
|
||||
}
|
||||
|
||||
static void
|
||||
tab_panel_browser_remove_tab_cb (MidoriBrowser* browser,
|
||||
MidoriView* view,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
GtkTreeModel* model = g_object_get_data (G_OBJECT (extension), "treemodel");
|
||||
guint i;
|
||||
GtkTreeIter iter;
|
||||
|
||||
i = 0;
|
||||
while (gtk_tree_model_iter_nth_child (model, &iter, NULL, i))
|
||||
{
|
||||
MidoriView* view_;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &view_, -1);
|
||||
|
||||
if (view == view_)
|
||||
{
|
||||
gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
|
||||
g_object_unref (view_);
|
||||
break;
|
||||
}
|
||||
|
||||
g_object_unref (view_);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tab_panel_app_add_browser_cb (MidoriApp* app,
|
||||
MidoriBrowser* browser,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
GtkTreeStore* model;
|
||||
GtkWidget* treeview;
|
||||
GtkTreeViewColumn* column;
|
||||
GtkCellRenderer* renderer_pixbuf;
|
||||
GtkCellRenderer* renderer_text;
|
||||
GtkWidget* panel;
|
||||
GtkWidget* toolbar;
|
||||
/* GtkToolItem* toolitem; */
|
||||
|
||||
g_object_set (browser, "show-tabs", FALSE, NULL);
|
||||
|
||||
panel = katze_object_get_object (browser, "panel");
|
||||
|
||||
model = g_object_get_data (G_OBJECT (extension), "treemodel");
|
||||
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
|
||||
column = gtk_tree_view_column_new ();
|
||||
renderer_pixbuf = gtk_cell_renderer_pixbuf_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE);
|
||||
gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf,
|
||||
(GtkTreeCellDataFunc)midori_extension_treeview_render_icon_cb,
|
||||
treeview, NULL);
|
||||
renderer_text = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
|
||||
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
|
||||
(GtkTreeCellDataFunc)midori_extension_treeview_render_text_cb,
|
||||
treeview, NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
g_object_connect (treeview,
|
||||
"signal::row-activated",
|
||||
midori_extension_row_activated_cb, extension,
|
||||
"signal::cursor-changed",
|
||||
midori_extension_cursor_or_row_changed_cb, extension,
|
||||
"signal::columns-changed",
|
||||
midori_extension_cursor_or_row_changed_cb, extension,
|
||||
"signal::button-release-event",
|
||||
midori_extension_button_release_event_cb, extension,
|
||||
"signal::key-release-event",
|
||||
midori_extension_key_release_event_cb, extension,
|
||||
"signal::popup-menu",
|
||||
midori_extension_popup_menu_cb, extension,
|
||||
NULL);
|
||||
gtk_widget_show (treeview);
|
||||
|
||||
toolbar = gtk_toolbar_new ();
|
||||
gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ);
|
||||
gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON);
|
||||
gtk_widget_show (toolbar);
|
||||
|
||||
/*
|
||||
TODO: Implement optional thumbnail images
|
||||
toolitem = gtk_toggle_tool_button_new_from_stock (STOCK_IMAGE);
|
||||
gtk_tool_item_set_is_important (toolitem, TRUE);
|
||||
g_signal_connect (toolitem, "toggled",
|
||||
G_CALLBACK (tab_panel_button_thumbnail_toggled_cb), notebook);
|
||||
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); */
|
||||
|
||||
midori_panel_append_widget (MIDORI_PANEL (panel), treeview,
|
||||
STOCK_TAB_PANEL, _("Tab Panel"), toolbar);
|
||||
g_object_unref (panel);
|
||||
|
||||
midori_browser_foreach (browser,
|
||||
(GtkCallback)tab_panel_browser_foreach_cb, treeview);
|
||||
|
||||
g_signal_connect_after (browser, "add-tab",
|
||||
G_CALLBACK (tab_panel_browser_add_tab_cb), extension);
|
||||
g_signal_connect (browser, "remove-tab",
|
||||
G_CALLBACK (tab_panel_browser_remove_tab_cb), extension);
|
||||
g_signal_connect (extension, "deactivate",
|
||||
G_CALLBACK (tab_panel_deactivate_cb), treeview);
|
||||
}
|
||||
|
||||
static void
|
||||
tab_panel_activate_cb (MidoriExtension* extension,
|
||||
MidoriApp* app)
|
||||
{
|
||||
GtkTreeStore* model;
|
||||
KatzeArray* browsers;
|
||||
MidoriBrowser* browser;
|
||||
guint i;
|
||||
|
||||
model = gtk_tree_store_new (1, MIDORI_TYPE_VIEW);
|
||||
g_object_set_data (G_OBJECT (extension), "treemodel", model);
|
||||
|
||||
browsers = katze_object_get_object (app, "browsers");
|
||||
i = 0;
|
||||
while ((browser = katze_array_get_nth_item (browsers, i++)))
|
||||
tab_panel_app_add_browser_cb (app, browser, extension);
|
||||
g_object_unref (browsers);
|
||||
g_signal_connect (app, "add-browser",
|
||||
G_CALLBACK (tab_panel_app_add_browser_cb), extension);
|
||||
}
|
||||
|
||||
MidoriExtension*
|
||||
extension_init (void)
|
||||
{
|
||||
GtkIconFactory* factory;
|
||||
GtkIconSource* icon_source;
|
||||
GtkIconSet* icon_set;
|
||||
static GtkStockItem items[] =
|
||||
{
|
||||
{ STOCK_TAB_PANEL, N_("T_ab Panel"), 0, 0, NULL },
|
||||
};
|
||||
|
||||
factory = gtk_icon_factory_new ();
|
||||
gtk_stock_add (items, G_N_ELEMENTS (items));
|
||||
icon_set = gtk_icon_set_new ();
|
||||
icon_source = gtk_icon_source_new ();
|
||||
gtk_icon_source_set_icon_name (icon_source, GTK_STOCK_INDEX);
|
||||
gtk_icon_set_add_source (icon_set, icon_source);
|
||||
gtk_icon_source_free (icon_source);
|
||||
gtk_icon_factory_add (factory, STOCK_TAB_PANEL, icon_set);
|
||||
gtk_icon_set_unref (icon_set);
|
||||
gtk_icon_factory_add_default (factory);
|
||||
g_object_unref (factory);
|
||||
|
||||
MidoriExtension* extension = g_object_new (MIDORI_TYPE_EXTENSION,
|
||||
"name", _("Tab Panel"),
|
||||
"description", _("Show tabs in a vertical panel"),
|
||||
"version", "0.1",
|
||||
"authors", "Christian Dywan <christian@twotoasts.de>",
|
||||
NULL);
|
||||
|
||||
g_signal_connect (extension, "activate",
|
||||
G_CALLBACK (tab_panel_activate_cb), NULL);
|
||||
|
||||
return extension;
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#include "tab-panel-extension.h"
|
||||
|
||||
#include <midori/midori.h>
|
||||
|
||||
#define STOCK_TAB_PANEL "tab-panel"
|
||||
|
||||
static void
|
||||
tab_panel_app_add_browser_cb (MidoriApp* app,
|
||||
MidoriBrowser* browser)
|
||||
{
|
||||
GtkWidget* panel;
|
||||
GtkWidget* child;
|
||||
|
||||
/* FIXME: Actually provide a tree view listing all views. */
|
||||
|
||||
panel = katze_object_get_object (browser, "panel");
|
||||
child = midori_view_new (NULL);
|
||||
gtk_widget_show (child);
|
||||
midori_panel_append_widget (MIDORI_PANEL (panel), child,
|
||||
STOCK_TAB_PANEL, _("Tab Panel"), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
tab_panel_activate_cb (MidoriExtension* extension,
|
||||
MidoriApp* app)
|
||||
{
|
||||
g_signal_connect (app, "add-browser",
|
||||
G_CALLBACK (tab_panel_app_add_browser_cb), NULL);
|
||||
}
|
||||
|
||||
MidoriExtension*
|
||||
extension_init (void)
|
||||
{
|
||||
MidoriExtension* extension;
|
||||
GtkIconFactory* factory;
|
||||
GtkIconSource* icon_source;
|
||||
GtkIconSet* icon_set;
|
||||
static GtkStockItem items[] =
|
||||
{
|
||||
{ STOCK_TAB_PANEL, N_("T_ab Panel"), 0, 0, NULL },
|
||||
};
|
||||
|
||||
factory = gtk_icon_factory_new ();
|
||||
gtk_stock_add (items, G_N_ELEMENTS (items));
|
||||
icon_set = gtk_icon_set_new ();
|
||||
icon_source = gtk_icon_source_new ();
|
||||
gtk_icon_source_set_icon_name (icon_source, GTK_STOCK_INDEX);
|
||||
gtk_icon_set_add_source (icon_set, icon_source);
|
||||
gtk_icon_source_free (icon_source);
|
||||
gtk_icon_factory_add (factory, STOCK_TAB_PANEL, icon_set);
|
||||
gtk_icon_set_unref (icon_set);
|
||||
gtk_icon_factory_add_default (factory);
|
||||
g_object_unref (factory);
|
||||
|
||||
extension = g_object_new (TAB_PANEL_TYPE_EXTENSION,
|
||||
"name", _("Tab Panel"),
|
||||
"description", "",
|
||||
"version", "0.1",
|
||||
"authors", "Christian Dywan <christian@twotoasts.de>",
|
||||
NULL);
|
||||
|
||||
g_signal_connect (extension, "activate",
|
||||
G_CALLBACK (tab_panel_activate_cb), NULL);
|
||||
|
||||
return extension;
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#include "tab-panel-extension.h"
|
||||
|
||||
#include <midori/midori.h>
|
||||
|
||||
struct _TabPanelExtension
|
||||
{
|
||||
MidoriExtension parent_instance;
|
||||
};
|
||||
|
||||
struct _TabPanelExtensionClass
|
||||
{
|
||||
MidoriExtensionClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (TabPanelExtension, tab_panel_extension, MIDORI_TYPE_EXTENSION);
|
||||
|
||||
static void
|
||||
tab_panel_extension_class_init (TabPanelExtensionClass* class)
|
||||
{
|
||||
/* Nothing to do. */
|
||||
}
|
||||
|
||||
static void
|
||||
tab_panel_extension_init (TabPanelExtension* extension)
|
||||
{
|
||||
/* Nothing to do. */
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#ifndef __TAB_PANEL_EXTENSION_H__
|
||||
#define __TAB_PANEL_EXTENSION_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define TAB_PANEL_TYPE_EXTENSION \
|
||||
(midori_extension_get_type ())
|
||||
#define TAB_PANEL_EXTENSION(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), TAB_PANEL_TYPE_EXTENSION, TabPanelExtension))
|
||||
#define TAB_PANEL_EXTENSION_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), TAB_PANEL_TYPE_EXTENSION, TabPanelExtensionClass))
|
||||
#define TAB_PANEL_IS_EXTENSION(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), TAB_PANEL_TYPE_EXTENSION))
|
||||
#define TAB_PANEL_IS_EXTENSION_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), TAB_PANEL_TYPE_EXTENSION))
|
||||
#define TAB_PANEL_EXTENSION_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), TAB_PANEL_TYPE_EXTENSION, TabPanelExtensionClass))
|
||||
|
||||
typedef struct _TabPanelExtension TabPanelExtension;
|
||||
typedef struct _TabPanelExtensionClass TabPanelExtensionClass;
|
||||
|
||||
GType
|
||||
tab_panel_extension_get_type (void);
|
||||
|
||||
/* There is no API for TabPanelExtension. Please use the
|
||||
available properties and signals. */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __TAB_PANEL_EXTENSION_H__ */
|
625
extensions/toolbar-editor.c
Normal file
625
extensions/toolbar-editor.c
Normal file
|
@ -0,0 +1,625 @@
|
|||
/*
|
||||
Copyright (C) 2009 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#include <midori/midori.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if !HAVE_HILDON
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
|
||||
GtkTreeView *tree_available;
|
||||
GtkTreeView *tree_used;
|
||||
|
||||
GtkListStore *store_available;
|
||||
GtkListStore *store_used;
|
||||
|
||||
GtkTreePath *last_drag_path;
|
||||
GtkTreeViewDropPosition last_drag_pos;
|
||||
|
||||
GtkWidget *drag_source;
|
||||
|
||||
GtkActionGroup *action_group;
|
||||
MidoriBrowser *browser;
|
||||
} TBEditorWidget;
|
||||
|
||||
enum
|
||||
{
|
||||
TB_EDITOR_COL_ACTION,
|
||||
TB_EDITOR_COL_LABEL,
|
||||
TB_EDITOR_COL_ICON,
|
||||
TB_EDITOR_COLS_MAX
|
||||
};
|
||||
|
||||
static const GtkTargetEntry tb_editor_dnd_targets[] =
|
||||
{
|
||||
{ "MIDORI_TB_EDITOR_ROW", 0, 0 }
|
||||
};
|
||||
static const gint tb_editor_dnd_targets_len = G_N_ELEMENTS(tb_editor_dnd_targets);
|
||||
|
||||
|
||||
static void tb_editor_app_add_browser_cb(MidoriApp *app, MidoriBrowser *browser, MidoriExtension *ext);
|
||||
|
||||
|
||||
static void tb_editor_deactivate_cb(MidoriExtension *extension, GtkWidget *menuitem)
|
||||
{
|
||||
MidoriApp *app = midori_extension_get_app(extension);
|
||||
|
||||
gtk_widget_destroy(menuitem);
|
||||
g_signal_handlers_disconnect_by_func(extension, tb_editor_deactivate_cb, menuitem);
|
||||
g_signal_handlers_disconnect_by_func(app, tb_editor_app_add_browser_cb, extension);
|
||||
}
|
||||
|
||||
|
||||
static void tb_editor_set_item_values(TBEditorWidget *tbw, const gchar *action_name,
|
||||
GtkListStore *store, GtkTreeIter *iter)
|
||||
{
|
||||
gchar *icon = NULL;
|
||||
gchar *label = NULL;
|
||||
gchar *label_clean = NULL;
|
||||
GtkAction *action;
|
||||
|
||||
action = gtk_action_group_get_action(tbw->action_group, action_name);
|
||||
if (action != NULL)
|
||||
{
|
||||
icon = katze_object_get_string(action, "icon-name");
|
||||
if (icon == NULL)
|
||||
{
|
||||
icon = katze_object_get_string(action, "stock-id");
|
||||
}
|
||||
|
||||
label = katze_object_get_string(action, "label");
|
||||
if (label != NULL)
|
||||
label_clean = katze_strip_mnemonics(label);
|
||||
}
|
||||
|
||||
gtk_list_store_set(store, iter,
|
||||
TB_EDITOR_COL_ACTION, action_name,
|
||||
TB_EDITOR_COL_LABEL, label_clean,
|
||||
TB_EDITOR_COL_ICON, icon,
|
||||
-1);
|
||||
|
||||
g_free(icon);
|
||||
g_free(label);
|
||||
g_free(label_clean);
|
||||
}
|
||||
|
||||
|
||||
static GSList *tb_editor_array_to_list(const gchar **items)
|
||||
{
|
||||
const gchar **name;
|
||||
GSList *list = NULL;
|
||||
|
||||
name = items;
|
||||
while (*name != NULL)
|
||||
{
|
||||
if (*name[0] != '\0')
|
||||
list = g_slist_append(list, g_strdup(*name));
|
||||
name++;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
static GSList *tb_editor_parse_active_items(MidoriBrowser *browser)
|
||||
{
|
||||
gchar *items;
|
||||
gchar **names;
|
||||
GSList *list = NULL;
|
||||
MidoriWebSettings *settings;
|
||||
|
||||
settings = katze_object_get_object(browser, "settings");
|
||||
g_object_get(settings, "toolbar-items", &items, NULL);
|
||||
g_object_unref(settings);
|
||||
|
||||
names = g_strsplit(items ? items : "", ",", 0);
|
||||
list = tb_editor_array_to_list((const gchar **) names);
|
||||
|
||||
g_strfreev(names);
|
||||
g_free(items);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
static GSList *tb_editor_get_available_actions(MidoriBrowser *browser)
|
||||
{
|
||||
GSList *list = NULL;
|
||||
|
||||
list = tb_editor_array_to_list(midori_browser_get_toolbar_actions(browser));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
static void tb_editor_scroll_to_iter(GtkTreeView *treeview, GtkTreeIter *iter)
|
||||
{
|
||||
GtkTreePath *path = gtk_tree_model_get_path(gtk_tree_view_get_model(treeview), iter);
|
||||
gtk_tree_view_scroll_to_cell(treeview, path, NULL, TRUE, 0.5, 0.0);
|
||||
gtk_tree_path_free(path);
|
||||
}
|
||||
|
||||
|
||||
static void tb_editor_free_path(TBEditorWidget *tbw)
|
||||
{
|
||||
if (tbw->last_drag_path != NULL)
|
||||
{
|
||||
gtk_tree_path_free(tbw->last_drag_path);
|
||||
tbw->last_drag_path = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void tb_editor_btn_remove_clicked_cb(GtkWidget *button, TBEditorWidget *tbw)
|
||||
{
|
||||
GtkTreeModel *model_used;
|
||||
GtkTreeSelection *selection_used;
|
||||
GtkTreeIter iter_used, iter_new;
|
||||
gchar *action_name;
|
||||
|
||||
selection_used = gtk_tree_view_get_selection(tbw->tree_used);
|
||||
if (gtk_tree_selection_get_selected(selection_used, &model_used, &iter_used))
|
||||
{
|
||||
gtk_tree_model_get(model_used, &iter_used, TB_EDITOR_COL_ACTION, &action_name, -1);
|
||||
if (g_strcmp0(action_name, "Location") != 0)
|
||||
{
|
||||
if (gtk_list_store_remove(tbw->store_used, &iter_used))
|
||||
gtk_tree_selection_select_iter(selection_used, &iter_used);
|
||||
|
||||
if (g_strcmp0(action_name, "Separator") != 0)
|
||||
{
|
||||
gtk_list_store_append(tbw->store_available, &iter_new);
|
||||
tb_editor_set_item_values(tbw, action_name, tbw->store_available, &iter_new);
|
||||
tb_editor_scroll_to_iter(tbw->tree_available, &iter_new);
|
||||
}
|
||||
}
|
||||
g_free(action_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void tb_editor_btn_add_clicked_cb(GtkWidget *button, TBEditorWidget *tbw)
|
||||
{
|
||||
GtkTreeModel *model_available;
|
||||
GtkTreeSelection *selection_available, *selection_used;
|
||||
GtkTreeIter iter_available, iter_new, iter_selected;
|
||||
gchar *action_name;
|
||||
|
||||
selection_available = gtk_tree_view_get_selection(tbw->tree_available);
|
||||
if (gtk_tree_selection_get_selected(selection_available, &model_available, &iter_available))
|
||||
{
|
||||
gtk_tree_model_get(model_available, &iter_available, TB_EDITOR_COL_ACTION, &action_name, -1);
|
||||
if (g_strcmp0(action_name, "Separator") != 0)
|
||||
{
|
||||
if (gtk_list_store_remove(tbw->store_available, &iter_available))
|
||||
gtk_tree_selection_select_iter(selection_available, &iter_available);
|
||||
}
|
||||
|
||||
selection_used = gtk_tree_view_get_selection(tbw->tree_used);
|
||||
if (gtk_tree_selection_get_selected(selection_used, NULL, &iter_selected))
|
||||
{
|
||||
gtk_list_store_insert_before(tbw->store_used, &iter_new, &iter_selected);
|
||||
tb_editor_set_item_values(tbw, action_name, tbw->store_used, &iter_new);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_list_store_append(tbw->store_used, &iter_new);
|
||||
tb_editor_set_item_values(tbw, action_name, tbw->store_used, &iter_new);
|
||||
}
|
||||
|
||||
tb_editor_scroll_to_iter(tbw->tree_used, &iter_new);
|
||||
|
||||
g_free(action_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static gboolean tb_editor_drag_motion_cb(GtkWidget *widget, GdkDragContext *drag_context,
|
||||
gint x, gint y, guint ltime, TBEditorWidget *tbw)
|
||||
{
|
||||
if (tbw->last_drag_path != NULL)
|
||||
gtk_tree_path_free(tbw->last_drag_path);
|
||||
gtk_tree_view_get_drag_dest_row(GTK_TREE_VIEW(widget),
|
||||
&(tbw->last_drag_path), &(tbw->last_drag_pos));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void tb_editor_drag_data_get_cb(GtkWidget *widget, GdkDragContext *context,
|
||||
GtkSelectionData *data, guint info, guint ltime,
|
||||
TBEditorWidget *tbw)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreeModel *model;
|
||||
GdkAtom atom;
|
||||
gchar *name;
|
||||
|
||||
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
|
||||
if (! gtk_tree_selection_get_selected(selection, &model, &iter))
|
||||
return;
|
||||
|
||||
gtk_tree_model_get(model, &iter, TB_EDITOR_COL_ACTION, &name, -1);
|
||||
if (name == NULL || *name == '\0')
|
||||
{
|
||||
g_free(name);
|
||||
return;
|
||||
}
|
||||
|
||||
atom = gdk_atom_intern(tb_editor_dnd_targets[0].target, FALSE);
|
||||
gtk_selection_data_set(data, atom, 8, (guchar*) name, strlen(name));
|
||||
|
||||
g_free(name);
|
||||
|
||||
tbw->drag_source = widget;
|
||||
}
|
||||
|
||||
|
||||
static void tb_editor_drag_data_rcvd_cb(GtkWidget *widget, GdkDragContext *context,
|
||||
gint x, gint y, GtkSelectionData *data, guint info,
|
||||
guint ltime, TBEditorWidget *tbw)
|
||||
{
|
||||
GtkTreeView *tree = GTK_TREE_VIEW(widget);
|
||||
gboolean del = FALSE;
|
||||
|
||||
if (data->length >= 0 && data->format == 8)
|
||||
{
|
||||
gboolean is_sep;
|
||||
gchar *text = NULL;
|
||||
|
||||
text = (gchar*) data->data;
|
||||
|
||||
/* We allow re-ordering the Location item but not removing it from the list. */
|
||||
if (g_strcmp0(text, "Location") == 0 && widget != tbw->drag_source)
|
||||
return;
|
||||
|
||||
is_sep = (g_strcmp0(text, "Separator") == 0);
|
||||
/* If the source of the action is equal to the target, we do just re-order and so need
|
||||
* to delete the separator to get it moved, not just copied. */
|
||||
if (is_sep && widget == tbw->drag_source)
|
||||
is_sep = FALSE;
|
||||
|
||||
if (tree != tbw->tree_available || ! is_sep)
|
||||
{
|
||||
GtkTreeIter iter, iter_before, *iter_before_ptr;
|
||||
GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model(tree));
|
||||
|
||||
if (tbw->last_drag_path != NULL)
|
||||
{
|
||||
gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter_before, tbw->last_drag_path);
|
||||
|
||||
if (gtk_list_store_iter_is_valid(store, &iter_before))
|
||||
iter_before_ptr = &iter_before;
|
||||
else
|
||||
iter_before_ptr = NULL;
|
||||
|
||||
if (tbw->last_drag_pos == GTK_TREE_VIEW_DROP_BEFORE ||
|
||||
tbw->last_drag_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
|
||||
gtk_list_store_insert_before(store, &iter, iter_before_ptr);
|
||||
else
|
||||
gtk_list_store_insert_after(store, &iter, iter_before_ptr);
|
||||
|
||||
tb_editor_set_item_values(tbw, text, store, &iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_list_store_append(store, &iter);
|
||||
tb_editor_set_item_values(tbw, text, store, &iter);
|
||||
}
|
||||
|
||||
tb_editor_scroll_to_iter(tree, &iter);
|
||||
}
|
||||
if (tree != tbw->tree_used || ! is_sep)
|
||||
del = TRUE;
|
||||
}
|
||||
|
||||
tbw->drag_source = NULL; /* reset the value just to be sure */
|
||||
tb_editor_free_path(tbw);
|
||||
gtk_drag_finish(context, TRUE, del, ltime);
|
||||
}
|
||||
|
||||
|
||||
static gboolean tb_editor_foreach_used(GtkTreeModel *model, GtkTreePath *path,
|
||||
GtkTreeIter *iter, gpointer data)
|
||||
{
|
||||
gchar *action_name;
|
||||
|
||||
gtk_tree_model_get(model, iter, TB_EDITOR_COL_ACTION, &action_name, -1);
|
||||
|
||||
if (action_name != NULL && *action_name != '\0')
|
||||
{
|
||||
g_string_append(data, action_name);
|
||||
g_string_append_c(data, ',');
|
||||
}
|
||||
|
||||
g_free(action_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void tb_editor_update_toolbar(TBEditorWidget *tbw)
|
||||
{
|
||||
MidoriWebSettings *settings;
|
||||
GString *str = g_string_new(NULL);
|
||||
|
||||
gtk_tree_model_foreach(GTK_TREE_MODEL(tbw->store_used), tb_editor_foreach_used, str);
|
||||
|
||||
settings = katze_object_get_object(tbw->browser, "settings");
|
||||
g_object_set(settings, "toolbar-items", str->str, NULL);
|
||||
g_object_unref(settings);
|
||||
|
||||
g_string_free(str, TRUE);
|
||||
}
|
||||
|
||||
|
||||
static void tb_editor_available_items_changed_cb(GtkTreeModel *model, GtkTreePath *arg1,
|
||||
GtkTreeIter *arg2, TBEditorWidget *tbw)
|
||||
{
|
||||
tb_editor_update_toolbar(tbw);
|
||||
}
|
||||
|
||||
|
||||
static void tb_editor_available_items_deleted_cb(GtkTreeModel *model, GtkTreePath *arg1,
|
||||
TBEditorWidget *tbw)
|
||||
{
|
||||
tb_editor_update_toolbar(tbw);
|
||||
}
|
||||
|
||||
|
||||
static TBEditorWidget *tb_editor_create_dialog(MidoriBrowser *parent)
|
||||
{
|
||||
GtkWidget *dialog, *vbox, *hbox, *vbox_buttons, *button_add, *button_remove;
|
||||
GtkWidget *swin_available, *swin_used, *tree_available, *tree_used, *label;
|
||||
GtkCellRenderer *text_renderer, *icon_renderer;
|
||||
GtkTreeViewColumn *column;
|
||||
TBEditorWidget *tbw = g_new(TBEditorWidget, 1);
|
||||
|
||||
dialog = gtk_dialog_new_with_buttons(_("Customize Toolbar"),
|
||||
GTK_WINDOW(parent),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
|
||||
vbox = (GTK_DIALOG(dialog))->vbox;
|
||||
gtk_box_set_spacing(GTK_BOX(vbox), 6);
|
||||
gtk_widget_set_name(dialog, "GeanyDialog");
|
||||
gtk_window_set_default_size(GTK_WINDOW(dialog), -1, 400);
|
||||
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE);
|
||||
|
||||
tbw->store_available = gtk_list_store_new(TB_EDITOR_COLS_MAX,
|
||||
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
|
||||
tbw->store_used = gtk_list_store_new(TB_EDITOR_COLS_MAX,
|
||||
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
|
||||
|
||||
label = gtk_label_new(
|
||||
_("Select items to be displayed on the toolbar. Items can be reodered by drag and drop."));
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
|
||||
|
||||
tree_available = gtk_tree_view_new();
|
||||
gtk_tree_view_set_model(GTK_TREE_VIEW(tree_available), GTK_TREE_MODEL(tbw->store_available));
|
||||
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree_available), TRUE);
|
||||
gtk_tree_sortable_set_sort_column_id(
|
||||
GTK_TREE_SORTABLE(tbw->store_available), TB_EDITOR_COL_LABEL, GTK_SORT_ASCENDING);
|
||||
|
||||
icon_renderer = gtk_cell_renderer_pixbuf_new();
|
||||
column = gtk_tree_view_column_new_with_attributes(
|
||||
NULL, icon_renderer, "stock-id", TB_EDITOR_COL_ICON, NULL);
|
||||
gtk_tree_view_append_column(GTK_TREE_VIEW(tree_available), column);
|
||||
|
||||
text_renderer = gtk_cell_renderer_text_new();
|
||||
column = gtk_tree_view_column_new_with_attributes(
|
||||
_("Available Items"), text_renderer, "text", TB_EDITOR_COL_LABEL, NULL);
|
||||
gtk_tree_view_append_column(GTK_TREE_VIEW(tree_available), column);
|
||||
|
||||
swin_available = gtk_scrolled_window_new(NULL, NULL);
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin_available),
|
||||
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
||||
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(swin_available), GTK_SHADOW_ETCHED_IN);
|
||||
gtk_container_add(GTK_CONTAINER(swin_available), tree_available);
|
||||
|
||||
tree_used = gtk_tree_view_new();
|
||||
gtk_tree_view_set_model(GTK_TREE_VIEW(tree_used), GTK_TREE_MODEL(tbw->store_used));
|
||||
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree_used), TRUE);
|
||||
gtk_tree_view_set_reorderable(GTK_TREE_VIEW(tree_used), TRUE);
|
||||
|
||||
icon_renderer = gtk_cell_renderer_pixbuf_new();
|
||||
column = gtk_tree_view_column_new_with_attributes(
|
||||
NULL, icon_renderer, "stock-id", TB_EDITOR_COL_ICON, NULL);
|
||||
gtk_tree_view_append_column(GTK_TREE_VIEW(tree_used), column);
|
||||
|
||||
text_renderer = gtk_cell_renderer_text_new();
|
||||
column = gtk_tree_view_column_new_with_attributes(
|
||||
_("Displayed Items"), text_renderer, "text", TB_EDITOR_COL_LABEL, NULL);
|
||||
gtk_tree_view_append_column(GTK_TREE_VIEW(tree_used), column);
|
||||
|
||||
swin_used = gtk_scrolled_window_new(NULL, NULL);
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin_used),
|
||||
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
||||
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(swin_used), GTK_SHADOW_ETCHED_IN);
|
||||
gtk_container_add(GTK_CONTAINER(swin_used), tree_used);
|
||||
|
||||
/* drag'n'drop */
|
||||
gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(tree_available), GDK_BUTTON1_MASK,
|
||||
tb_editor_dnd_targets, tb_editor_dnd_targets_len, GDK_ACTION_MOVE);
|
||||
gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(tree_available),
|
||||
tb_editor_dnd_targets, tb_editor_dnd_targets_len, GDK_ACTION_MOVE);
|
||||
g_signal_connect(tree_available, "drag-data-get",
|
||||
G_CALLBACK(tb_editor_drag_data_get_cb), tbw);
|
||||
g_signal_connect(tree_available, "drag-data-received",
|
||||
G_CALLBACK(tb_editor_drag_data_rcvd_cb), tbw);
|
||||
g_signal_connect(tree_available, "drag-motion",
|
||||
G_CALLBACK(tb_editor_drag_motion_cb), tbw);
|
||||
|
||||
gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(tree_used), GDK_BUTTON1_MASK,
|
||||
tb_editor_dnd_targets, tb_editor_dnd_targets_len, GDK_ACTION_MOVE);
|
||||
gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(tree_used),
|
||||
tb_editor_dnd_targets, tb_editor_dnd_targets_len, GDK_ACTION_MOVE);
|
||||
g_signal_connect(tree_used, "drag-data-get",
|
||||
G_CALLBACK(tb_editor_drag_data_get_cb), tbw);
|
||||
g_signal_connect(tree_used, "drag-data-received",
|
||||
G_CALLBACK(tb_editor_drag_data_rcvd_cb), tbw);
|
||||
g_signal_connect(tree_used, "drag-motion",
|
||||
G_CALLBACK(tb_editor_drag_motion_cb), tbw);
|
||||
|
||||
|
||||
button_add = gtk_button_new();
|
||||
gtk_button_set_image(GTK_BUTTON(button_add),
|
||||
gtk_image_new_from_stock(GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_BUTTON));
|
||||
button_remove = gtk_button_new();
|
||||
g_signal_connect(button_add, "clicked", G_CALLBACK(tb_editor_btn_add_clicked_cb), tbw);
|
||||
gtk_button_set_image(GTK_BUTTON(button_remove),
|
||||
gtk_image_new_from_stock(GTK_STOCK_GO_BACK, GTK_ICON_SIZE_BUTTON));
|
||||
g_signal_connect(button_remove, "clicked", G_CALLBACK(tb_editor_btn_remove_clicked_cb), tbw);
|
||||
|
||||
vbox_buttons = gtk_vbox_new(FALSE, 6);
|
||||
/* FIXME this is a little hack'ish, any better ideas? */
|
||||
gtk_box_pack_start(GTK_BOX(vbox_buttons), gtk_label_new(""), TRUE, TRUE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(vbox_buttons), button_add, FALSE, FALSE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(vbox_buttons), button_remove, FALSE, FALSE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(vbox_buttons), gtk_label_new(""), TRUE, TRUE, 0);
|
||||
|
||||
hbox = gtk_hbox_new(FALSE, 6);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), swin_available, TRUE, TRUE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), vbox_buttons, FALSE, FALSE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), swin_used, TRUE, TRUE, 0);
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 6);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
|
||||
|
||||
gtk_widget_show_all(vbox);
|
||||
|
||||
g_object_unref(tbw->store_available);
|
||||
g_object_unref(tbw->store_used);
|
||||
|
||||
tbw->dialog = dialog;
|
||||
tbw->tree_available = GTK_TREE_VIEW(tree_available);
|
||||
tbw->tree_used = GTK_TREE_VIEW(tree_used);
|
||||
|
||||
tbw->last_drag_path = NULL;
|
||||
|
||||
return tbw;
|
||||
}
|
||||
|
||||
|
||||
static void tb_editor_menu_configure_toolbar_activate_cb(GtkWidget *menuitem, MidoriBrowser *browser)
|
||||
{
|
||||
GSList *node, *used_items, *all_items;
|
||||
GtkTreeIter iter;
|
||||
GtkTreePath *path;
|
||||
TBEditorWidget *tbw;
|
||||
|
||||
/* read the current active toolbar items */
|
||||
used_items = tb_editor_parse_active_items(browser);
|
||||
|
||||
/* get all available actions */
|
||||
all_items = tb_editor_get_available_actions(browser);
|
||||
|
||||
/* create the GUI */
|
||||
tbw = tb_editor_create_dialog(browser);
|
||||
|
||||
/* cache some pointers, this is safe enough since the dialog is run modally */
|
||||
tbw->action_group = midori_browser_get_action_group(browser);
|
||||
tbw->browser = browser;
|
||||
|
||||
/* fill the stores */
|
||||
for (node = all_items; node != NULL; node = node->next)
|
||||
{
|
||||
if (strcmp(node->data, "Separator") == 0 ||
|
||||
g_slist_find_custom(used_items, node->data, (GCompareFunc) strcmp) == NULL)
|
||||
{
|
||||
gtk_list_store_append(tbw->store_available, &iter);
|
||||
tb_editor_set_item_values(tbw, node->data, tbw->store_available, &iter);
|
||||
}
|
||||
}
|
||||
for (node = used_items; node != NULL; node = node->next)
|
||||
{
|
||||
gtk_list_store_append(tbw->store_used, &iter);
|
||||
tb_editor_set_item_values(tbw, node->data, tbw->store_used, &iter);
|
||||
}
|
||||
/* select first item */
|
||||
path = gtk_tree_path_new_from_string("0");
|
||||
gtk_tree_selection_select_path(gtk_tree_view_get_selection(tbw->tree_used), path);
|
||||
gtk_tree_path_free(path);
|
||||
|
||||
/* connect the changed signals after populating the store */
|
||||
g_signal_connect(tbw->store_used, "row-changed",
|
||||
G_CALLBACK(tb_editor_available_items_changed_cb), tbw);
|
||||
g_signal_connect(tbw->store_used, "row-deleted",
|
||||
G_CALLBACK(tb_editor_available_items_deleted_cb), tbw);
|
||||
|
||||
/* run it */
|
||||
gtk_dialog_run(GTK_DIALOG(tbw->dialog));
|
||||
|
||||
gtk_widget_destroy(tbw->dialog);
|
||||
|
||||
g_slist_foreach(used_items, (GFunc) g_free, NULL);
|
||||
g_slist_foreach(all_items, (GFunc) g_free, NULL);
|
||||
g_slist_free(used_items);
|
||||
g_slist_free(all_items);
|
||||
tb_editor_free_path(tbw);
|
||||
g_free(tbw);
|
||||
}
|
||||
|
||||
|
||||
static void tb_editor_app_add_browser_cb(MidoriApp *app, MidoriBrowser *browser, MidoriExtension *ext)
|
||||
{
|
||||
GtkWidget *panel;
|
||||
GtkWidget *menu;
|
||||
GtkWidget *menuitem;
|
||||
|
||||
panel = katze_object_get_object(browser, "panel");
|
||||
menu = katze_object_get_object(panel, "menu");
|
||||
g_object_unref(panel);
|
||||
menuitem = gtk_menu_item_new_with_mnemonic(_("Configure _Toolbar..."));
|
||||
g_signal_connect(menuitem, "activate",
|
||||
G_CALLBACK(tb_editor_menu_configure_toolbar_activate_cb), browser);
|
||||
gtk_widget_show(menuitem);
|
||||
gtk_menu_shell_insert(GTK_MENU_SHELL (menu), menuitem, 3);
|
||||
g_object_unref(menu);
|
||||
|
||||
g_signal_connect(ext, "deactivate", G_CALLBACK(tb_editor_deactivate_cb), menuitem);
|
||||
}
|
||||
|
||||
|
||||
static void tb_editor_activate_cb(MidoriExtension *extension, MidoriApp *app)
|
||||
{
|
||||
KatzeArray *browsers;
|
||||
MidoriBrowser *browser;
|
||||
guint i;
|
||||
|
||||
browsers = katze_object_get_object(app, "browsers");
|
||||
i = 0;
|
||||
while ((browser = katze_array_get_nth_item(browsers, i++)))
|
||||
tb_editor_app_add_browser_cb(app, browser, extension);
|
||||
g_signal_connect(app, "add-browser", G_CALLBACK(tb_editor_app_add_browser_cb), extension);
|
||||
g_object_unref(browsers);
|
||||
}
|
||||
|
||||
|
||||
MidoriExtension *extension_init(void)
|
||||
{
|
||||
MidoriExtension* extension = g_object_new(MIDORI_TYPE_EXTENSION,
|
||||
"name", _("Toolbar Editor"),
|
||||
"description", _("Easily edit the toolbar layout"),
|
||||
"version", "0.1",
|
||||
"authors", "Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>",
|
||||
NULL);
|
||||
|
||||
g_signal_connect(extension, "activate", G_CALLBACK(tb_editor_activate_cb), NULL);
|
||||
|
||||
return extension;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -2,11 +2,10 @@
|
|||
# WAF build script for midori
|
||||
# This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||
|
||||
import os
|
||||
|
||||
extensions = os.listdir ('extensions')
|
||||
for extension in extensions:
|
||||
# Tab Panel isn't useful at this point
|
||||
if extension == 'tab-panel':
|
||||
continue
|
||||
# Adblock is incomplete and not ready for release
|
||||
if extension == 'adblock.c':
|
||||
continue
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
# This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||
|
||||
import Utils
|
||||
import os
|
||||
|
||||
def add_image (bld, category, name):
|
||||
|
||||
|
@ -14,10 +15,10 @@ def add_image (bld, category, name):
|
|||
if rsvg_convert:
|
||||
Utils.check_dir (blddir + '/icons')
|
||||
|
||||
for size in [16, 22, 32, 48]:
|
||||
for size in [16, 22, 24, 32, 48]:
|
||||
format = str (size) + 'x' + str (size)
|
||||
if os.access (srcdir + '/icons/' + format + '/' + name + '.png', os.F_OK):
|
||||
bld.install_files ('${DATADIR}/icons/hicolor/' + format + '/' + category,
|
||||
bld.install_files ('${MDATADIR}/icons/hicolor/' + format + '/' + category,
|
||||
srcdir + '/icons/' + format + '/' + name + '.png')
|
||||
elif not rsvg_convert:
|
||||
pass
|
||||
|
@ -28,7 +29,7 @@ def add_image (bld, category, name):
|
|||
' -o ' + blddir + '/icons/' + format + '/' + name + '.png' + \
|
||||
' ' + srcdir + '/icons/scalable/' + name + '.svg'
|
||||
if not Utils.exec_command (command):
|
||||
bld.install_files ('${DATADIR}/icons/hicolor/' + format + '/' + category,
|
||||
bld.install_files ('${MDATADIR}/icons/hicolor/' + format + '/' + category,
|
||||
blddir + '/icons/' + format + '/' + name + '.png')
|
||||
else:
|
||||
Utils.pprint ('BLUE', "Optimized icons could not be created.")
|
||||
|
|
|
@ -559,7 +559,7 @@ katze_array_action_create_tool_item_for (KatzeArrayAction* array_action,
|
|||
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image);
|
||||
label = gtk_label_new (NULL);
|
||||
/* FIXME: Should text direction be respected here? */
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
|
||||
gtk_label_set_max_width_chars (GTK_LABEL (label), 25);
|
||||
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE);
|
||||
gtk_widget_show (label);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -147,7 +147,8 @@ katze_item_class_init (KatzeItemClass* class)
|
|||
static void
|
||||
katze_item_init (KatzeItem* item)
|
||||
{
|
||||
/* Nothing to do here */
|
||||
item->metadata = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_free);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -161,6 +162,8 @@ katze_item_finalize (GObject* object)
|
|||
g_free (item->icon);
|
||||
g_free (item->token);
|
||||
|
||||
g_hash_table_unref (item->metadata);
|
||||
|
||||
G_OBJECT_CLASS (katze_item_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
@ -451,6 +454,151 @@ katze_item_set_added (KatzeItem* item,
|
|||
g_object_notify (G_OBJECT (item), "added");
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_item_get_meta_keys:
|
||||
* @item: a #KatzeItem
|
||||
*
|
||||
* Retrieves a list of all meta keys.
|
||||
*
|
||||
* Return value: a newly allocated #GList of constant strings
|
||||
*
|
||||
* Since: 0.1.8
|
||||
**/
|
||||
GList*
|
||||
katze_item_get_meta_keys (KatzeItem* item)
|
||||
{
|
||||
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
|
||||
|
||||
return g_hash_table_get_keys (item->metadata);
|
||||
}
|
||||
|
||||
static void
|
||||
katze_item_set_meta_data_value (KatzeItem* item,
|
||||
const gchar* key,
|
||||
gchar* value)
|
||||
{
|
||||
/* FIXME: Make the default namespace configurable */
|
||||
if (g_str_has_prefix (key, "midori:"))
|
||||
g_hash_table_insert (item->metadata, g_strdup (&key[7]), value);
|
||||
else
|
||||
g_hash_table_insert (item->metadata, g_strdup (key), value);
|
||||
/* TODO: Emit meta-key-changed */
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_item_get_meta_string:
|
||||
* @item: a #KatzeItem
|
||||
* @key: the name of an integer value
|
||||
*
|
||||
* Retrieves a string value by the specified key from the
|
||||
* meta data of the item.
|
||||
*
|
||||
* Specify "namespace:key" or "key" to use the default namespace.
|
||||
*
|
||||
* Return value: a string, or %NULL
|
||||
*
|
||||
* Since: 0.1.8
|
||||
**/
|
||||
const gchar*
|
||||
katze_item_get_meta_string (KatzeItem* item,
|
||||
const gchar* key)
|
||||
{
|
||||
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
|
||||
g_return_val_if_fail (key != NULL, NULL);
|
||||
|
||||
if (g_str_has_prefix (key, "midori:"))
|
||||
key = &key[7];
|
||||
return g_hash_table_lookup (item->metadata, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_item_set_meta_string:
|
||||
* @item: a #KatzeItem
|
||||
* @key: the name of a string value
|
||||
* @value: the value as a string
|
||||
*
|
||||
* Saves the specified string value in the meta data of
|
||||
* the item under the specified key.
|
||||
*
|
||||
* Specify "namespace:key" or "key" to use the default namespace.
|
||||
*
|
||||
* Since: 0.1.8
|
||||
**/
|
||||
void
|
||||
katze_item_set_meta_string (KatzeItem* item,
|
||||
const gchar* key,
|
||||
const gchar* value)
|
||||
{
|
||||
g_return_if_fail (KATZE_IS_ITEM (item));
|
||||
g_return_if_fail (key != NULL);
|
||||
|
||||
katze_item_set_meta_data_value (item, key, g_strdup (value));
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_item_get_meta_integer:
|
||||
* @item: a #KatzeItem
|
||||
* @key: the name of an integer value
|
||||
*
|
||||
* Retrieves an integer value by the specified key from the
|
||||
* meta data of the item.
|
||||
*
|
||||
* If the key is present but not representable as an
|
||||
* integer, -1 is returned.
|
||||
*
|
||||
* Return value: an integer value, or -1
|
||||
*
|
||||
* Since: 0.1.8
|
||||
**/
|
||||
gint64
|
||||
katze_item_get_meta_integer (KatzeItem* item,
|
||||
const gchar* key)
|
||||
{
|
||||
gpointer value;
|
||||
|
||||
g_return_val_if_fail (KATZE_IS_ITEM (item), -1);
|
||||
g_return_val_if_fail (key != NULL, -1);
|
||||
|
||||
if (g_str_has_prefix (key, "midori:"))
|
||||
key = &key[7];
|
||||
if (g_hash_table_lookup_extended (item->metadata, key, NULL, &value))
|
||||
return g_ascii_strtoll (value, NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_item_set_meta_integer:
|
||||
* @item: a #KatzeItem
|
||||
* @key: the name of an integer value
|
||||
*
|
||||
* Saves the specified integer value in the meta data of
|
||||
* the item under the specified key.
|
||||
*
|
||||
* A value of -1 is intepreted as unset.
|
||||
*
|
||||
* Since: 0.1.8
|
||||
**/
|
||||
void
|
||||
katze_item_set_meta_integer (KatzeItem* item,
|
||||
const gchar* key,
|
||||
gint64 value)
|
||||
{
|
||||
g_return_if_fail (KATZE_IS_ITEM (item));
|
||||
g_return_if_fail (key != NULL);
|
||||
|
||||
if (value == -1)
|
||||
katze_item_set_meta_data_value (item, key, NULL);
|
||||
else
|
||||
{
|
||||
katze_item_set_meta_data_value (item, key,
|
||||
#ifdef G_GINT64_FORMAT
|
||||
g_strdup_printf ("%" G_GINT64_FORMAT, value));
|
||||
#else
|
||||
g_strdup_printf ("%li", value));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_item_get_parent:
|
||||
* @item: a #KatzeItem
|
||||
|
|
|
@ -42,6 +42,7 @@ struct _KatzeItem
|
|||
gchar* icon;
|
||||
gchar* token;
|
||||
gint64 added;
|
||||
GHashTable* metadata;
|
||||
|
||||
KatzeItem* parent;
|
||||
};
|
||||
|
@ -102,6 +103,27 @@ void
|
|||
katze_item_set_added (KatzeItem* item,
|
||||
gint64 added);
|
||||
|
||||
GList*
|
||||
katze_item_get_meta_keys (KatzeItem* item);
|
||||
|
||||
const gchar*
|
||||
katze_item_get_meta_string (KatzeItem* item,
|
||||
const gchar* key);
|
||||
|
||||
void
|
||||
katze_item_set_meta_string (KatzeItem* item,
|
||||
const gchar* key,
|
||||
const gchar* value);
|
||||
|
||||
gint64
|
||||
katze_item_get_meta_integer (KatzeItem* item,
|
||||
const gchar* key);
|
||||
|
||||
void
|
||||
katze_item_set_meta_integer (KatzeItem* item,
|
||||
const gchar* key,
|
||||
gint64 value);
|
||||
|
||||
gpointer
|
||||
katze_item_get_parent (KatzeItem* item);
|
||||
|
||||
|
|
|
@ -129,6 +129,22 @@ proxy_object_notify_string_cb (GObject* object,
|
|||
g_free (value);
|
||||
}
|
||||
|
||||
static void
|
||||
proxy_widget_boolean_destroy_cb (GtkWidget* proxy,
|
||||
GObject* object)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (object,
|
||||
proxy_object_notify_boolean_cb, proxy);
|
||||
}
|
||||
|
||||
static void
|
||||
proxy_widget_string_destroy_cb (GtkWidget* proxy,
|
||||
GObject* object)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (object,
|
||||
proxy_object_notify_string_cb, proxy);
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_property_proxy:
|
||||
* @object: a #GObject
|
||||
|
@ -153,6 +169,7 @@ proxy_object_notify_string_cb (GObject* object,
|
|||
* Since 0.1.6 the following hints are also supported:
|
||||
* "toggle": the widget created will be an empty toggle button. This
|
||||
* is only supported with boolean properties.
|
||||
* Since 0.1.8 "toggle" creates GtkCheckButton widgets without checkmarks.
|
||||
*
|
||||
* Any other values for @hint are silently ignored.
|
||||
*
|
||||
|
@ -196,16 +213,19 @@ katze_property_proxy (gpointer object,
|
|||
gchar* notify_property;
|
||||
gboolean toggled = katze_object_get_boolean (object, property);
|
||||
|
||||
widget = gtk_check_button_new ();
|
||||
if (_hint == g_intern_string ("toggle"))
|
||||
widget = gtk_toggle_button_new ();
|
||||
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (widget), FALSE);
|
||||
else
|
||||
widget = gtk_check_button_new_with_label (gettext (nick));
|
||||
gtk_button_set_label (GTK_BUTTON (widget), gettext (nick));
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), toggled);
|
||||
g_signal_connect (widget, "toggled",
|
||||
G_CALLBACK (proxy_toggle_button_toggled_cb), object);
|
||||
notify_property = g_strdup_printf ("notify::%s", property);
|
||||
g_signal_connect (object, notify_property,
|
||||
G_CALLBACK (proxy_object_notify_boolean_cb), widget);
|
||||
g_signal_connect (widget, "destroy",
|
||||
G_CALLBACK (proxy_widget_boolean_destroy_cb), object);
|
||||
g_free (notify_property);
|
||||
}
|
||||
else if (type == G_TYPE_PARAM_STRING && _hint == g_intern_string ("file"))
|
||||
|
@ -298,6 +318,8 @@ katze_property_proxy (gpointer object,
|
|||
notify_property = g_strdup_printf ("notify::%s", property);
|
||||
g_signal_connect (object, notify_property,
|
||||
G_CALLBACK (proxy_object_notify_string_cb), widget);
|
||||
g_signal_connect (widget, "destroy",
|
||||
G_CALLBACK (proxy_widget_string_destroy_cb), object);
|
||||
g_free (notify_property);
|
||||
}
|
||||
else if (type == G_TYPE_PARAM_FLOAT)
|
||||
|
@ -602,6 +624,64 @@ katze_tree_view_get_selected_iter (GtkTreeView* treeview,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_strip_mnemonics:
|
||||
* @original: a string with mnemonics
|
||||
*
|
||||
* Parses the given string for mnemonics in the form
|
||||
* "B_utton" or "Button (_U)" and returns a string
|
||||
* without any mnemonics.
|
||||
*
|
||||
* Return value: a newly allocated string without mnemonics
|
||||
*
|
||||
* Since: 0.1.8
|
||||
**/
|
||||
gchar*
|
||||
katze_strip_mnemonics (const gchar* original)
|
||||
{
|
||||
/* A copy of _gtk_toolbar_elide_underscores
|
||||
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
Copied from GTK+ 2.17.1 */
|
||||
gchar *q, *result;
|
||||
const gchar *p, *end;
|
||||
gsize len;
|
||||
gboolean last_underscore;
|
||||
|
||||
if (!original)
|
||||
return NULL;
|
||||
|
||||
len = strlen (original);
|
||||
q = result = g_malloc (len + 1);
|
||||
last_underscore = FALSE;
|
||||
|
||||
end = original + len;
|
||||
for (p = original; p < end; p++)
|
||||
{
|
||||
if (!last_underscore && *p == '_')
|
||||
last_underscore = TRUE;
|
||||
else
|
||||
{
|
||||
last_underscore = FALSE;
|
||||
if (original + 2 <= p && p + 1 <= end &&
|
||||
p[-2] == '(' && p[-1] == '_' && p[0] != '_' && p[1] == ')')
|
||||
{
|
||||
q--;
|
||||
*q = '\0';
|
||||
p++;
|
||||
}
|
||||
else
|
||||
*q++ = *p;
|
||||
}
|
||||
}
|
||||
|
||||
if (last_underscore)
|
||||
*q++ = '_';
|
||||
|
||||
*q = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_object_has_property:
|
||||
* @object: a #GObject
|
||||
|
|
|
@ -106,6 +106,9 @@ katze_tree_view_get_selected_iter (GtkTreeView* treeview,
|
|||
GtkTreeModel** model,
|
||||
GtkTreeIter* iter);
|
||||
|
||||
gchar*
|
||||
katze_strip_mnemonics (const gchar* original);
|
||||
|
||||
gboolean
|
||||
katze_object_has_property (gpointer object,
|
||||
const gchar* property);
|
||||
|
|
|
@ -27,10 +27,13 @@ gtk_icon_entry_set_icon_from_pixbuf (GtkEntry* entry,
|
|||
GtkEntryIconPosition position,
|
||||
GdkPixbuf* pixbuf)
|
||||
{
|
||||
gboolean activatable;
|
||||
|
||||
/* Without this ugly hack pixbuf icons don't work */
|
||||
gtk_widget_hide (GTK_WIDGET (entry));
|
||||
activatable = gtk_entry_get_icon_activatable (entry, position);
|
||||
gtk_entry_set_icon_from_pixbuf (entry, position, pixbuf);
|
||||
gtk_widget_show (GTK_WIDGET (entry));
|
||||
gtk_entry_set_icon_activatable (entry, position, !activatable);
|
||||
gtk_entry_set_icon_activatable (entry, position, activatable);
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
|
@ -220,9 +220,9 @@ settings_save_to_file (MidoriWebSettings* settings,
|
|||
}
|
||||
else if (type == G_TYPE_PARAM_BOOLEAN)
|
||||
{
|
||||
gboolean boolean;
|
||||
g_object_get (settings, property, &boolean, NULL);
|
||||
g_key_file_set_boolean (key_file, "settings", property, boolean);
|
||||
gboolean truth;
|
||||
g_object_get (settings, property, &truth, NULL);
|
||||
g_key_file_set_boolean (key_file, "settings", property, truth);
|
||||
}
|
||||
else if (type == G_TYPE_PARAM_ENUM)
|
||||
{
|
||||
|
@ -744,6 +744,15 @@ settings_notify_cb (MidoriWebSettings* settings,
|
|||
g_free (config_file);
|
||||
}
|
||||
|
||||
static void
|
||||
extension_activate_cb (MidoriExtension* extension,
|
||||
MidoriApp* app)
|
||||
{
|
||||
MidoriWebSettings* settings = katze_object_get_object (app, "settings");
|
||||
settings_notify_cb (settings, NULL, app);
|
||||
g_object_unref (settings);
|
||||
}
|
||||
|
||||
static void
|
||||
accel_map_changed_cb (GtkAccelMap* accel_map,
|
||||
gchar* accel_path,
|
||||
|
@ -1185,6 +1194,8 @@ midori_load_extensions (gpointer data)
|
|||
if (extension_dir != NULL)
|
||||
{
|
||||
const gchar* filename;
|
||||
gchar* config_file = build_config_filename ("config");
|
||||
gboolean is_writable = is_writable (config_file);
|
||||
|
||||
while ((filename = g_dir_read_name (extension_dir)))
|
||||
{
|
||||
|
@ -1228,9 +1239,17 @@ midori_load_extensions (gpointer data)
|
|||
if (!g_strcmp0 (filename, name))
|
||||
g_signal_emit_by_name (extension, "activate", app);
|
||||
}
|
||||
if (is_writable)
|
||||
{
|
||||
g_signal_connect_after (extension, "activate",
|
||||
G_CALLBACK (extension_activate_cb), app);
|
||||
g_signal_connect_after (extension, "deactivate",
|
||||
G_CALLBACK (extension_activate_cb), app);
|
||||
}
|
||||
g_object_unref (extension);
|
||||
}
|
||||
g_dir_close (extension_dir);
|
||||
g_free (config_file);
|
||||
}
|
||||
g_free (extension_path);
|
||||
}
|
||||
|
@ -1250,6 +1269,8 @@ midori_load_session (gpointer data)
|
|||
KatzeArray* session;
|
||||
KatzeItem* item;
|
||||
guint i;
|
||||
gint64 current;
|
||||
gchar** command = g_object_get_data (G_OBJECT (app), "execute-command");
|
||||
|
||||
browser = midori_app_create_browser (app);
|
||||
midori_app_add_browser (app, browser);
|
||||
|
@ -1285,7 +1306,11 @@ midori_load_session (gpointer data)
|
|||
i = 0;
|
||||
while ((item = katze_array_get_nth_item (_session, i++)))
|
||||
midori_browser_add_item (browser, item);
|
||||
/* FIXME: Switch to the last active page */
|
||||
current = katze_item_get_meta_integer (KATZE_ITEM (_session), "current");
|
||||
if (current < 0)
|
||||
current = 0;
|
||||
midori_browser_set_current_page (browser, current);
|
||||
if (!(item = katze_array_get_nth_item (_session, current)))
|
||||
item = katze_array_get_nth_item (_session, 0);
|
||||
if (!strcmp (katze_item_get_uri (item), ""))
|
||||
midori_browser_activate_action (browser, "Location");
|
||||
|
@ -1304,9 +1329,13 @@ midori_load_session (gpointer data)
|
|||
(GWeakNotify)(midori_browser_weak_notify_cb), browser);
|
||||
}
|
||||
|
||||
if (command)
|
||||
midori_app_send_command (app, command);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_JSCORE
|
||||
static gint
|
||||
midori_run_script (const gchar* filename)
|
||||
{
|
||||
|
@ -1344,6 +1373,7 @@ midori_run_script (const gchar* filename)
|
|||
g_print ("%s - Exception: %s\n", filename, exception);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 6)
|
||||
static void
|
||||
|
@ -1372,6 +1402,19 @@ snapshot_load_finished_cb (GtkWidget* web_view,
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
midori_web_app_browser_notify_load_status_cb (MidoriBrowser* browser,
|
||||
GParamSpec* pspec,
|
||||
gpointer data)
|
||||
{
|
||||
if (katze_object_get_enum (browser, "load-status") != MIDORI_LOAD_PROVISIONAL)
|
||||
{
|
||||
GtkWidget* view = midori_browser_get_current_tab (browser);
|
||||
GdkPixbuf* icon = midori_view_get_icon (MIDORI_VIEW (view));
|
||||
gtk_window_set_icon (GTK_WINDOW (browser), icon);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char** argv)
|
||||
|
@ -1380,6 +1423,7 @@ main (int argc,
|
|||
gchar* config;
|
||||
gboolean run;
|
||||
gchar* snapshot;
|
||||
gboolean execute;
|
||||
gboolean version;
|
||||
gchar** uris;
|
||||
MidoriApp* app;
|
||||
|
@ -1391,12 +1435,16 @@ main (int argc,
|
|||
N_("Run ADDRESS as a web application"), N_("ADDRESS") },
|
||||
{ "config", 'c', 0, G_OPTION_ARG_FILENAME, &config,
|
||||
N_("Use FOLDER as configuration folder"), N_("FOLDER") },
|
||||
#ifdef HAVE_JSCORE
|
||||
{ "run", 'r', 0, G_OPTION_ARG_NONE, &run,
|
||||
N_("Run the specified filename as javascript"), NULL },
|
||||
#endif
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 6)
|
||||
{ "snapshot", 's', 0, G_OPTION_ARG_STRING, &snapshot,
|
||||
N_("Take a snapshot of the specified URI"), NULL },
|
||||
#endif
|
||||
{ "execute", 'e', 0, G_OPTION_ARG_NONE, &execute,
|
||||
N_("Execute the specified command"), NULL },
|
||||
{ "version", 'V', 0, G_OPTION_ARG_NONE, &version,
|
||||
N_("Display program version"), NULL },
|
||||
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &uris,
|
||||
|
@ -1430,7 +1478,15 @@ main (int argc,
|
|||
if (g_getenv ("NLSPATH"))
|
||||
bindtextdomain (GETTEXT_PACKAGE, g_getenv ("NLSPATH"));
|
||||
else
|
||||
#ifdef G_OS_WIN32
|
||||
{
|
||||
gchar* path = sokoke_find_data_filename ("locale");
|
||||
bindtextdomain (GETTEXT_PACKAGE, path);
|
||||
g_free (path);
|
||||
}
|
||||
#else
|
||||
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
|
||||
#endif
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
#endif
|
||||
|
@ -1440,6 +1496,7 @@ main (int argc,
|
|||
config = NULL;
|
||||
run = FALSE;
|
||||
snapshot = NULL;
|
||||
execute = FALSE;
|
||||
version = FALSE;
|
||||
uris = NULL;
|
||||
error = NULL;
|
||||
|
@ -1515,10 +1572,13 @@ main (int argc,
|
|||
"show-menubar", FALSE,
|
||||
"show-navigationbar", TRUE,
|
||||
"toolbar-items", "Back,Forward,ReloadStop,Location",
|
||||
"homepage", NULL,
|
||||
"show-statusbar", TRUE,
|
||||
NULL);
|
||||
g_object_unref (settings);
|
||||
g_object_set (browser, "settings", settings, NULL);
|
||||
g_signal_connect (browser, "notify::load-status",
|
||||
G_CALLBACK (midori_web_app_browser_notify_load_status_cb), NULL);
|
||||
midori_browser_add_uri (browser, webapp);
|
||||
g_object_set_data (G_OBJECT (browser), "locked", (void*)1);
|
||||
g_signal_connect (browser, "destroy",
|
||||
|
@ -1529,9 +1589,11 @@ main (int argc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_JSCORE
|
||||
/* Standalone javascript support */
|
||||
if (run)
|
||||
return midori_run_script (uris ? *uris : NULL);
|
||||
#endif
|
||||
|
||||
#if HAVE_HILDON
|
||||
osso_context = osso_initialize (PACKAGE_NAME, PACKAGE_VERSION, FALSE, NULL);
|
||||
|
@ -1569,8 +1631,9 @@ main (int argc,
|
|||
{
|
||||
GtkWidget* dialog;
|
||||
|
||||
/* TODO: Open as many tabs as we have uris, seperated by pipes */
|
||||
if (uris)
|
||||
if (execute)
|
||||
result = midori_app_send_command (app, uris);
|
||||
else if (uris) /* TODO: Open a tab per URI, seperated by pipes */
|
||||
result = midori_app_instance_send_uris (app, uris);
|
||||
else
|
||||
result = midori_app_instance_send_new_browser (app);
|
||||
|
@ -1606,6 +1669,15 @@ main (int argc,
|
|||
}
|
||||
if (!error && katze_array_is_empty (search_engines))
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
gchar* dir;
|
||||
|
||||
dir = g_win32_get_package_installation_directory_of_module (NULL);
|
||||
katze_assign (config_file,
|
||||
g_build_filename (dir, "etc", "xdg", PACKAGE_NAME, "search", NULL));
|
||||
g_free (dir);
|
||||
search_engines = search_engines_new_from_file (config_file, NULL);
|
||||
#else
|
||||
const gchar* const * config_dirs = g_get_system_config_dirs ();
|
||||
i = 0;
|
||||
while (config_dirs[i])
|
||||
|
@ -1625,6 +1697,7 @@ main (int argc,
|
|||
g_build_filename (SYSCONFDIR, "xdg", PACKAGE_NAME, "search", NULL));
|
||||
search_engines = search_engines_new_from_file (config_file, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (error)
|
||||
{
|
||||
|
@ -1730,6 +1803,9 @@ main (int argc,
|
|||
}
|
||||
g_string_free (error_messages, TRUE);
|
||||
|
||||
/* If -e or --execute was specified, "uris" refers to the command. */
|
||||
if (!execute)
|
||||
{
|
||||
/* Open as many tabs as we have uris, seperated by pipes */
|
||||
i = 0;
|
||||
while (uris && uris[i])
|
||||
|
@ -1747,6 +1823,7 @@ main (int argc,
|
|||
g_free (uri);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
katze_assign (config_file, build_config_filename ("config"));
|
||||
if (is_writable (config_file))
|
||||
|
@ -1845,6 +1922,9 @@ main (int argc,
|
|||
katze_item_set_parent (KATZE_ITEM (_session), app);
|
||||
g_idle_add (midori_load_session, _session);
|
||||
|
||||
if (execute)
|
||||
g_object_set_data (G_OBJECT (app), "execute-command", uris);
|
||||
|
||||
gtk_main ();
|
||||
|
||||
#if HAVE_HILDON
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -21,7 +21,14 @@
|
|||
#include <glib/gi18n.h>
|
||||
|
||||
#if HAVE_UNIQUE
|
||||
typedef gpointer MidoriAppInstance;
|
||||
#define MidoriAppInstanceNull NULL
|
||||
#include <unique/unique.h>
|
||||
#define MIDORI_UNIQUE_COMMAND 1
|
||||
#else
|
||||
typedef gint MidoriAppInstance;
|
||||
#define MidoriAppInstanceNull -1
|
||||
#include "socket.h"
|
||||
#endif
|
||||
|
||||
typedef struct _NotifyNotification NotifyNotification;
|
||||
|
@ -54,7 +61,7 @@ struct _MidoriApp
|
|||
KatzeArray* extensions;
|
||||
KatzeArray* browsers;
|
||||
|
||||
gpointer instance;
|
||||
MidoriAppInstance instance;
|
||||
|
||||
/* libnotify handling */
|
||||
gchar* program_notify_send;
|
||||
|
@ -197,6 +204,7 @@ _midori_app_add_browser (MidoriApp* app,
|
|||
|
||||
katze_array_add_item (app->browsers, browser);
|
||||
|
||||
app->browser = browser;
|
||||
#if HAVE_UNIQUE
|
||||
if (app->instance)
|
||||
unique_app_watch_window (app->instance, GTK_WINDOW (browser));
|
||||
|
@ -383,56 +391,56 @@ midori_app_class_init (MidoriAppClass* class)
|
|||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
#if HAVE_UNIQUE
|
||||
static UniqueResponse
|
||||
midori_browser_message_received_cb (UniqueApp* instance,
|
||||
UniqueCommand command,
|
||||
UniqueMessageData* message,
|
||||
guint timestamp,
|
||||
MidoriApp* app)
|
||||
static gboolean
|
||||
midori_app_command_received (MidoriApp* app,
|
||||
const gchar* command,
|
||||
gchar** uris,
|
||||
GdkScreen* screen)
|
||||
{
|
||||
UniqueResponse response;
|
||||
MidoriBrowser* browser;
|
||||
gchar** uris;
|
||||
MidoriNewPage open_external_pages_in;
|
||||
gboolean first;
|
||||
|
||||
switch (command)
|
||||
if (!screen)
|
||||
{
|
||||
case UNIQUE_ACTIVATE:
|
||||
gtk_window_set_screen (GTK_WINDOW (app->browser),
|
||||
unique_message_data_get_screen (message));
|
||||
if (app->browser && gtk_widget_has_screen (GTK_WIDGET (app->browser)))
|
||||
screen = gtk_widget_get_screen (GTK_WIDGET (app->browser));
|
||||
else
|
||||
screen = gdk_screen_get_default ();
|
||||
}
|
||||
|
||||
if (g_str_equal (command, "activate"))
|
||||
{
|
||||
gtk_window_set_screen (GTK_WINDOW (app->browser), screen);
|
||||
gtk_window_present (GTK_WINDOW (app->browser));
|
||||
response = UNIQUE_RESPONSE_OK;
|
||||
break;
|
||||
case UNIQUE_NEW:
|
||||
browser = midori_app_create_browser (app);
|
||||
return TRUE;
|
||||
}
|
||||
else if (g_str_equal (command, "new"))
|
||||
{
|
||||
MidoriBrowser* browser = midori_app_create_browser (app);
|
||||
midori_app_add_browser (app, browser);
|
||||
/* FIXME: Should open the homepage according to settings */
|
||||
midori_browser_add_uri (browser, "");
|
||||
midori_browser_activate_action (browser, "Location");
|
||||
gtk_window_set_screen (GTK_WINDOW (app->browser),
|
||||
unique_message_data_get_screen (message));
|
||||
gtk_window_set_screen (GTK_WINDOW (app->browser), screen);
|
||||
gtk_widget_show (GTK_WIDGET (browser));
|
||||
response = UNIQUE_RESPONSE_OK;
|
||||
break;
|
||||
case UNIQUE_OPEN:
|
||||
gtk_window_set_screen (GTK_WINDOW (app->browser),
|
||||
unique_message_data_get_screen (message));
|
||||
return TRUE;
|
||||
}
|
||||
else if (g_str_equal (command, "open"))
|
||||
{
|
||||
gtk_window_set_screen (GTK_WINDOW (app->browser), screen);
|
||||
gtk_window_present (GTK_WINDOW (app->browser));
|
||||
uris = unique_message_data_get_uris (message);
|
||||
if (!uris)
|
||||
response = UNIQUE_RESPONSE_FAIL;
|
||||
return FALSE;
|
||||
else
|
||||
{
|
||||
MidoriBrowser* browser;
|
||||
MidoriNewPage open_external_pages_in;
|
||||
gboolean first;
|
||||
|
||||
g_object_get (app->settings, "open-external-pages-in",
|
||||
&open_external_pages_in, NULL);
|
||||
if (open_external_pages_in == MIDORI_NEW_PAGE_WINDOW)
|
||||
{
|
||||
browser = midori_app_create_browser (app);
|
||||
midori_app_add_browser (app, browser);
|
||||
gtk_window_set_screen (GTK_WINDOW (app->browser),
|
||||
unique_message_data_get_screen (message));
|
||||
gtk_window_set_screen (GTK_WINDOW (app->browser), screen);
|
||||
gtk_widget_show (GTK_WIDGET (browser));
|
||||
}
|
||||
else
|
||||
|
@ -452,37 +460,137 @@ midori_browser_message_received_cb (UniqueApp* instance,
|
|||
g_free (fixed_uri);
|
||||
uris++;
|
||||
}
|
||||
/* g_strfreev (uris); */
|
||||
response = UNIQUE_RESPONSE_OK;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if (g_str_equal (command, "command"))
|
||||
{
|
||||
if (!uris || !app->browser)
|
||||
return FALSE;
|
||||
midori_browser_activate_action (app->browser, *uris);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if HAVE_UNIQUE
|
||||
static UniqueResponse
|
||||
midori_browser_message_received_cb (UniqueApp* instance,
|
||||
UniqueCommand command,
|
||||
UniqueMessageData* message,
|
||||
guint timestamp,
|
||||
MidoriApp* app)
|
||||
{
|
||||
gboolean success;
|
||||
GdkScreen* screen = unique_message_data_get_screen (message);
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case UNIQUE_ACTIVATE:
|
||||
success = midori_app_command_received (app, "activate", NULL, screen);
|
||||
break;
|
||||
case UNIQUE_NEW:
|
||||
success = midori_app_command_received (app, "new", NULL, screen);
|
||||
break;
|
||||
case UNIQUE_OPEN:
|
||||
{
|
||||
gchar** uris = unique_message_data_get_uris (message);
|
||||
success = midori_app_command_received (app, "open", uris, screen);
|
||||
/* g_strfreev (uris); */
|
||||
break;
|
||||
}
|
||||
case MIDORI_UNIQUE_COMMAND:
|
||||
{
|
||||
gchar** uris = unique_message_data_get_uris (message);
|
||||
success = midori_app_command_received (app, "command", uris, screen);
|
||||
/* g_strfreev (uris); */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
response = UNIQUE_RESPONSE_FAIL;
|
||||
success = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return response;
|
||||
return success ? UNIQUE_RESPONSE_OK : UNIQUE_RESPONSE_FAIL;
|
||||
}
|
||||
#else
|
||||
static gboolean
|
||||
midori_app_io_channel_watch_cb (GIOChannel* channel,
|
||||
GIOCondition condition,
|
||||
MidoriApp* app)
|
||||
{
|
||||
GdkScreen* screen = gtk_widget_get_screen (GTK_WIDGET (app->browser));
|
||||
gint fd, sock;
|
||||
gchar buf[4096];
|
||||
struct sockaddr_in caddr;
|
||||
guint caddr_len = sizeof(caddr);
|
||||
|
||||
fd = app->instance;
|
||||
sock = accept (fd, (struct sockaddr *)&caddr, &caddr_len);
|
||||
|
||||
while (fd_gets (sock, buf, sizeof (buf)) != -1)
|
||||
{
|
||||
if (strncmp (buf, "activate", 8) == 0)
|
||||
{
|
||||
midori_app_command_received (app, "open", NULL, screen);
|
||||
}
|
||||
else if (strncmp (buf, "new", 3) == 0)
|
||||
{
|
||||
midori_app_command_received (app, "new", NULL, screen);
|
||||
}
|
||||
else if (strncmp (buf, "open", 4) == 0)
|
||||
{
|
||||
while (fd_gets (sock, buf, sizeof (buf)) != -1 && *buf != '.')
|
||||
{
|
||||
gchar** uris = g_strsplit (g_strstrip (buf), "\n", 2);
|
||||
midori_app_command_received (app, "open", uris, screen);
|
||||
g_strfreev (uris);
|
||||
}
|
||||
}
|
||||
else if (strncmp (buf, "command", 7) == 0)
|
||||
{
|
||||
guint i = 0;
|
||||
gchar** uris = g_new (gchar*, 100);
|
||||
while (fd_gets (sock, buf, sizeof (buf)) != -1 && *buf != '.')
|
||||
{
|
||||
uris[i++] = g_strdup (g_strstrip (buf));
|
||||
if (i == 99)
|
||||
break;
|
||||
}
|
||||
uris[i] = NULL;
|
||||
midori_app_command_received (app, "command", uris, screen);
|
||||
g_strfreev (uris);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_window_present (GTK_WINDOW (app->browser));
|
||||
|
||||
fd_close (sock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static gpointer
|
||||
static MidoriAppInstance
|
||||
midori_app_create_instance (MidoriApp* app,
|
||||
const gchar* name)
|
||||
{
|
||||
#if HAVE_UNIQUE
|
||||
gpointer instance;
|
||||
MidoriAppInstance instance;
|
||||
GdkDisplay* display;
|
||||
gchar* display_name;
|
||||
gchar* instance_name;
|
||||
guint i, n;
|
||||
#if !HAVE_UNIQUE
|
||||
gboolean exists;
|
||||
GIOChannel* channel;
|
||||
#endif
|
||||
|
||||
if (!name)
|
||||
name = "midori";
|
||||
|
||||
#if HAVE_UNIQUE
|
||||
if (!(display = gdk_display_get_default ()))
|
||||
return NULL;
|
||||
return MidoriAppInstanceNull;
|
||||
|
||||
display_name = g_strdup (gdk_display_get_name (display));
|
||||
n = strlen (display_name);
|
||||
|
@ -490,15 +598,25 @@ midori_app_create_instance (MidoriApp* app,
|
|||
if (display_name[i] == ':' || display_name[i] == '.')
|
||||
display_name[i] = '_';
|
||||
instance_name = g_strdup_printf ("de.twotoasts.%s_%s", name, display_name);
|
||||
|
||||
#if HAVE_UNIQUE
|
||||
instance = unique_app_new (instance_name, NULL);
|
||||
g_free (instance_name);
|
||||
g_free (display_name);
|
||||
unique_app_add_command (instance, "midori-command", MIDORI_UNIQUE_COMMAND);
|
||||
g_signal_connect (instance, "message-received",
|
||||
G_CALLBACK (midori_browser_message_received_cb), app);
|
||||
return instance;
|
||||
#else
|
||||
return NULL;
|
||||
instance = socket_init (instance_name, sokoke_set_config_dir (NULL), &exists);
|
||||
g_object_set_data (G_OBJECT (app), "sock-exists",
|
||||
exists ? (gpointer)0xdeadbeef : NULL);
|
||||
channel = g_io_channel_unix_new (instance);
|
||||
g_io_add_watch (channel, G_IO_IN | G_IO_PRI | G_IO_ERR,
|
||||
(GIOFunc)midori_app_io_channel_watch_cb, app);
|
||||
#endif
|
||||
|
||||
g_free (instance_name);
|
||||
g_free (display_name);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -514,7 +632,7 @@ midori_app_init (MidoriApp* app)
|
|||
app->extensions = NULL;
|
||||
app->browsers = katze_array_new (MIDORI_TYPE_BROWSER);
|
||||
|
||||
app->instance = NULL;
|
||||
app->instance = MidoriAppInstanceNull;
|
||||
|
||||
midori_app_init_libnotify (app);
|
||||
}
|
||||
|
@ -535,7 +653,11 @@ midori_app_finalize (GObject* object)
|
|||
katze_object_assign (app->extensions, NULL);
|
||||
katze_object_assign (app->browsers, NULL);
|
||||
|
||||
#if HAVE_UNIQUE
|
||||
katze_object_assign (app->instance, NULL);
|
||||
#else
|
||||
sock_cleanup ();
|
||||
#endif
|
||||
|
||||
if (app->libnotify_module)
|
||||
{
|
||||
|
@ -663,9 +785,6 @@ midori_app_new (void)
|
|||
* Use the "name" property if you want to run more
|
||||
* than one instance.
|
||||
*
|
||||
* If Midori was built without single instance support
|
||||
* this function will always return %FALSE.
|
||||
*
|
||||
* Return value: %TRUE if an instance is already running
|
||||
**/
|
||||
gboolean
|
||||
|
@ -673,11 +792,13 @@ midori_app_instance_is_running (MidoriApp* app)
|
|||
{
|
||||
g_return_val_if_fail (MIDORI_IS_APP (app), FALSE);
|
||||
|
||||
#if HAVE_UNIQUE
|
||||
if (!app->instance)
|
||||
if (app->instance == MidoriAppInstanceNull)
|
||||
app->instance = midori_app_create_instance (app, app->name);
|
||||
#if HAVE_UNIQUE
|
||||
if (app->instance)
|
||||
return unique_app_is_running (app->instance);
|
||||
#else
|
||||
return g_object_get_data (G_OBJECT (app), "sock-exists") != NULL;
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -710,6 +831,12 @@ midori_app_instance_send_activate (MidoriApp* app)
|
|||
if (response == UNIQUE_RESPONSE_OK)
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
if (app->instance > -1)
|
||||
{
|
||||
send_open_command (app->instance, "activate", NULL);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -740,6 +867,12 @@ midori_app_instance_send_new_browser (MidoriApp* app)
|
|||
if (response == UNIQUE_RESPONSE_OK)
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
if (app->instance > -1)
|
||||
{
|
||||
send_open_command (app->instance, "new", NULL);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -779,6 +912,63 @@ midori_app_instance_send_uris (MidoriApp* app,
|
|||
if (response == UNIQUE_RESPONSE_OK)
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
if (app->instance > -1)
|
||||
{
|
||||
send_open_command (app->instance, "open", uris);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* midori_app_send_command:
|
||||
* @app: a #MidoriApp
|
||||
* @command: a string vector of a command to execute
|
||||
*
|
||||
* Sends a command to an instance of Midori, which
|
||||
* is either the current process or an already running
|
||||
* instance with the same name on the default display.
|
||||
*
|
||||
* Names of GtkAction objects of MidoriBrowser are recognized as commands.
|
||||
*
|
||||
* Return value: %TRUE if the message was sent successfully
|
||||
*
|
||||
* Since: 0.1.8
|
||||
**/
|
||||
gboolean
|
||||
midori_app_send_command (MidoriApp* app,
|
||||
gchar** command)
|
||||
{
|
||||
#if HAVE_UNIQUE
|
||||
UniqueMessageData* message;
|
||||
UniqueResponse response;
|
||||
#endif
|
||||
|
||||
/* g_return_val_if_fail (MIDORI_IS_APP (app), FALSE); */
|
||||
g_return_val_if_fail (command != NULL, FALSE);
|
||||
|
||||
if (!midori_app_instance_is_running (app))
|
||||
return midori_app_command_received (app, "command", command, NULL);
|
||||
|
||||
#if HAVE_UNIQUE
|
||||
if (app->instance)
|
||||
{
|
||||
message = unique_message_data_new ();
|
||||
unique_message_data_set_uris (message, command);
|
||||
response = unique_app_send_message (app->instance,
|
||||
MIDORI_UNIQUE_COMMAND, message);
|
||||
unique_message_data_free (message);
|
||||
if (response == UNIQUE_RESPONSE_OK)
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
if (app->instance > -1)
|
||||
{
|
||||
send_open_command (app->instance, "command", command);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,10 @@ gboolean
|
|||
midori_app_instance_send_uris (MidoriApp* app,
|
||||
gchar** uris);
|
||||
|
||||
gboolean
|
||||
midori_app_send_command (MidoriApp* app,
|
||||
gchar** command);
|
||||
|
||||
void
|
||||
midori_app_add_browser (MidoriApp* app,
|
||||
MidoriBrowser* browser);
|
||||
|
|
|
@ -22,6 +22,13 @@
|
|||
#include <libxml/tree.h>
|
||||
#endif
|
||||
|
||||
static void
|
||||
katze_xbel_parse_info (KatzeItem* item,
|
||||
xmlNodePtr cur);
|
||||
|
||||
static gchar*
|
||||
katze_item_metadata_to_xbel (KatzeItem* item);
|
||||
|
||||
#if HAVE_LIBXML
|
||||
static KatzeItem*
|
||||
katze_item_from_xmlNodePtr (xmlNodePtr cur)
|
||||
|
@ -49,6 +56,8 @@ katze_item_from_xmlNodePtr (xmlNodePtr cur)
|
|||
katze_item_set_text (item, g_strstrip ((gchar*)key));
|
||||
g_free (key);
|
||||
}
|
||||
else if (!xmlStrcmp (cur->name, (const xmlChar*)"info"))
|
||||
katze_xbel_parse_info (item, cur);
|
||||
cur = cur->next;
|
||||
}
|
||||
return item;
|
||||
|
@ -109,6 +118,52 @@ katze_array_from_xmlNodePtr (xmlNodePtr cur)
|
|||
return array;
|
||||
}
|
||||
|
||||
static void
|
||||
katze_xbel_parse_info (KatzeItem* item,
|
||||
xmlNodePtr cur)
|
||||
{
|
||||
cur = cur->xmlChildrenNode;
|
||||
while (cur)
|
||||
{
|
||||
if (!xmlStrcmp (cur->name, (const xmlChar*)"metadata"))
|
||||
{
|
||||
xmlChar* owner = xmlGetProp (cur, (xmlChar*)"owner");
|
||||
g_strstrip ((gchar*)owner);
|
||||
/* FIXME: Save metadata from unknown owners */
|
||||
if (!g_strcmp0 ((gchar*)owner, "http://www.twotoasts.de"))
|
||||
{
|
||||
xmlAttrPtr properties = cur->properties;
|
||||
while (properties)
|
||||
{
|
||||
if (!xmlStrcmp (properties->name, (xmlChar*)"owner"))
|
||||
{
|
||||
properties = properties->next;
|
||||
continue;
|
||||
}
|
||||
xmlChar* value = xmlGetProp (cur, properties->name);
|
||||
if (properties->ns && properties->ns->prefix)
|
||||
{
|
||||
gchar* ns_value = g_strdup_printf ("%s:%s",
|
||||
properties->ns->prefix, properties->name);
|
||||
katze_item_set_meta_string (item,
|
||||
(gchar*)ns_value, (gchar*)value);
|
||||
g_free (ns_value);
|
||||
}
|
||||
else
|
||||
katze_item_set_meta_string (item,
|
||||
(gchar*)properties->name, (gchar*)value);
|
||||
xmlFree (value);
|
||||
properties = properties->next;
|
||||
}
|
||||
}
|
||||
xmlFree (owner);
|
||||
}
|
||||
else if (g_strcmp0 ((gchar*)cur->name, "text"))
|
||||
g_critical ("Unexpected element <%s> in <metadata>.", cur->name);
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Loads the contents from an xmlNodePtr into an array. */
|
||||
static gboolean
|
||||
katze_array_from_xmlDocPtr (KatzeArray* array,
|
||||
|
@ -153,8 +208,8 @@ katze_array_from_xmlDocPtr (KatzeArray* array,
|
|||
item = katze_item_from_xmlNodePtr (cur);
|
||||
else if (!xmlStrcmp (cur->name, (const xmlChar*)"separator"))
|
||||
item = katze_item_new ();
|
||||
/*else if (!xmlStrcmp (cur->name, (const xmlChar*)"info"))
|
||||
item = katze_xbel_parse_info (xbel, cur);*/
|
||||
else if (!xmlStrcmp (cur->name, (const xmlChar*)"info"))
|
||||
katze_xbel_parse_info (KATZE_ITEM (array), cur);
|
||||
if (item)
|
||||
katze_array_add_item (array, item);
|
||||
cur = cur->next;
|
||||
|
@ -236,10 +291,12 @@ static gchar*
|
|||
katze_item_to_data (KatzeItem* item)
|
||||
{
|
||||
gchar* markup;
|
||||
gchar* metadata;
|
||||
|
||||
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
|
||||
|
||||
markup = NULL;
|
||||
metadata = katze_item_metadata_to_xbel (item);
|
||||
if (KATZE_IS_ARRAY (item))
|
||||
{
|
||||
GString* _markup = g_string_new (NULL);
|
||||
|
@ -254,10 +311,11 @@ katze_item_to_data (KatzeItem* item)
|
|||
/* gchar* folded = item->folded ? NULL : g_strdup_printf (" folded=\"no\""); */
|
||||
gchar* title = _simple_xml_element ("title", katze_item_get_name (item));
|
||||
gchar* desc = _simple_xml_element ("desc", katze_item_get_text (item));
|
||||
markup = g_strdup_printf ("<folder%s>\n%s%s%s</folder>\n",
|
||||
markup = g_strdup_printf ("<folder%s>\n%s%s%s%s</folder>\n",
|
||||
"" /* folded ? folded : "" */,
|
||||
title, desc,
|
||||
_markup->str);
|
||||
_markup->str,
|
||||
metadata);
|
||||
g_string_free (_markup, TRUE);
|
||||
/* g_free (folded); */
|
||||
g_free (title);
|
||||
|
@ -273,16 +331,42 @@ katze_item_to_data (KatzeItem* item)
|
|||
markup = g_strdup_printf ("<bookmark%s>\n%s%s%s</bookmark>\n",
|
||||
href,
|
||||
title, desc,
|
||||
"");
|
||||
metadata);
|
||||
g_free (href);
|
||||
g_free (title);
|
||||
g_free (desc);
|
||||
}
|
||||
else
|
||||
markup = g_strdup ("<separator/>\n");
|
||||
g_free (metadata);
|
||||
return markup;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
katze_item_metadata_to_xbel (KatzeItem* item)
|
||||
{
|
||||
GList* keys = katze_item_get_meta_keys (item);
|
||||
GString* markup;
|
||||
/* FIXME: Allow specifying an alternative namespace/ URI */
|
||||
const gchar* namespace_uri = "http://www.twotoasts.de";
|
||||
const gchar* namespace = "midori";
|
||||
gsize i;
|
||||
const gchar* key;
|
||||
|
||||
if (!keys)
|
||||
return g_strdup ("");
|
||||
|
||||
markup = g_string_new ("<info>\n<metadata owner=\"");
|
||||
g_string_append_printf (markup, "%s\"", namespace_uri);
|
||||
i = 0;
|
||||
while ((key = g_list_nth_data (keys, i++)))
|
||||
if (katze_item_get_meta_string (item, key))
|
||||
g_string_append_printf (markup, " %s:%s=\"%s\"", namespace, key,
|
||||
katze_item_get_meta_string (item, key));
|
||||
g_string_append_printf (markup, "/>\n</info>\n");
|
||||
return g_string_free (markup, FALSE);
|
||||
}
|
||||
|
||||
static gchar*
|
||||
katze_array_to_xbel (KatzeArray* array,
|
||||
GError** error)
|
||||
|
@ -291,8 +375,10 @@ katze_array_to_xbel (KatzeArray* array,
|
|||
guint i;
|
||||
KatzeItem* item;
|
||||
gchar* item_xml;
|
||||
const gchar* namespacing;
|
||||
gchar* title;
|
||||
gchar* desc;
|
||||
gchar* metadata;
|
||||
gchar* outer_markup;
|
||||
|
||||
inner_markup = g_string_new (NULL);
|
||||
|
@ -304,20 +390,25 @@ katze_array_to_xbel (KatzeArray* array,
|
|||
g_free (item_xml);
|
||||
}
|
||||
|
||||
namespacing = " xmlns:midori=\"http://www.twotoasts.de\"";
|
||||
title = _simple_xml_element ("title", katze_item_get_name (KATZE_ITEM (array)));
|
||||
desc = _simple_xml_element ("desc", katze_item_get_text (KATZE_ITEM (array)));
|
||||
metadata = katze_item_metadata_to_xbel (KATZE_ITEM (array));
|
||||
outer_markup = g_strdup_printf (
|
||||
"%s%s<xbel version=\"1.0\">\n%s%s%s</xbel>\n",
|
||||
"%s%s<xbel version=\"1.0\"%s>\n%s%s%s%s</xbel>\n",
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
|
||||
"<!DOCTYPE xbel PUBLIC \"+//IDN python.org//DTD "
|
||||
"XML Bookmark Exchange Language 1.0//EN//XML\" "
|
||||
"\"http://www.python.org/topics/xml/dtds/xbel-1.0.dtd\">\n",
|
||||
namespacing,
|
||||
title,
|
||||
desc,
|
||||
metadata,
|
||||
inner_markup->str);
|
||||
g_string_free (inner_markup, TRUE);
|
||||
g_free (title);
|
||||
g_free (desc);
|
||||
g_free (metadata);
|
||||
|
||||
return outer_markup;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -138,6 +138,9 @@ midori_browser_get_for_widget (GtkWidget* widget);
|
|||
void
|
||||
midori_browser_quit (MidoriBrowser* browser);
|
||||
|
||||
const gchar**
|
||||
midori_browser_get_toolbar_actions (MidoriBrowser* browser);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __MIDORI_BROWSER_H__ */
|
||||
|
|
|
@ -28,6 +28,7 @@ struct _MidoriExtensionPrivate
|
|||
gchar* description;
|
||||
gchar* version;
|
||||
gchar* authors;
|
||||
gchar* website;
|
||||
|
||||
MidoriApp* app;
|
||||
gint active;
|
||||
|
@ -129,7 +130,8 @@ enum
|
|||
PROP_NAME,
|
||||
PROP_DESCRIPTION,
|
||||
PROP_VERSION,
|
||||
PROP_AUTHORS
|
||||
PROP_AUTHORS,
|
||||
PROP_WEBSITE
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -227,6 +229,22 @@ midori_extension_class_init (MidoriExtensionClass* class)
|
|||
NULL,
|
||||
flags));
|
||||
|
||||
/**
|
||||
* MidoriExtension:website:
|
||||
*
|
||||
* The website of the extension.
|
||||
*
|
||||
* Since: 0.1.8
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_WEBSITE,
|
||||
g_param_spec_string (
|
||||
"website",
|
||||
"Website",
|
||||
"The website of the extension",
|
||||
NULL,
|
||||
flags));
|
||||
|
||||
g_type_class_add_private (class, sizeof (MidoriExtensionPrivate));
|
||||
}
|
||||
|
||||
|
@ -346,6 +364,7 @@ midori_extension_finalize (GObject* object)
|
|||
katze_assign (extension->priv->description, NULL);
|
||||
katze_assign (extension->priv->version, NULL);
|
||||
katze_assign (extension->priv->authors, NULL);
|
||||
katze_assign (extension->priv->website, NULL);
|
||||
|
||||
katze_assign (extension->priv->config_dir, NULL);
|
||||
g_list_free (extension->priv->lsettings);
|
||||
|
@ -376,6 +395,9 @@ midori_extension_set_property (GObject* object,
|
|||
case PROP_AUTHORS:
|
||||
katze_assign (extension->priv->authors, g_value_dup_string (value));
|
||||
break;
|
||||
case PROP_WEBSITE:
|
||||
katze_assign (extension->priv->website, g_value_dup_string (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -404,6 +426,9 @@ midori_extension_get_property (GObject* object,
|
|||
case PROP_AUTHORS:
|
||||
g_value_set_string (value, extension->priv->authors);
|
||||
break;
|
||||
case PROP_WEBSITE:
|
||||
g_value_set_string (value, extension->priv->website);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
|
@ -36,6 +36,8 @@ struct _MidoriLocationAction
|
|||
GtkTreeModel* sort_model;
|
||||
GdkPixbuf* default_icon;
|
||||
GHashTable* items;
|
||||
KatzeNet* net;
|
||||
KatzeArray* history;
|
||||
};
|
||||
|
||||
struct _MidoriLocationActionClass
|
||||
|
@ -50,12 +52,14 @@ enum
|
|||
PROP_0,
|
||||
|
||||
PROP_PROGRESS,
|
||||
PROP_SECONDARY_ICON
|
||||
PROP_SECONDARY_ICON,
|
||||
PROP_HISTORY
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ACTIVE_CHANGED,
|
||||
FOCUS_IN,
|
||||
FOCUS_OUT,
|
||||
SECONDARY_ICON_RELEASED,
|
||||
RESET_URI,
|
||||
|
@ -72,6 +76,7 @@ enum
|
|||
TITLE_COL,
|
||||
VISITS_COL,
|
||||
VISIBLE_COL,
|
||||
YALIGN_COL,
|
||||
N_COLS
|
||||
};
|
||||
|
||||
|
@ -104,6 +109,10 @@ static void
|
|||
midori_location_action_disconnect_proxy (GtkAction* action,
|
||||
GtkWidget* proxy);
|
||||
|
||||
static void
|
||||
midori_location_action_completion_init (MidoriLocationAction* location_action,
|
||||
GtkEntry* entry);
|
||||
|
||||
static void
|
||||
midori_location_action_class_init (MidoriLocationActionClass* class)
|
||||
{
|
||||
|
@ -120,6 +129,22 @@ midori_location_action_class_init (MidoriLocationActionClass* class)
|
|||
G_TYPE_NONE, 1,
|
||||
G_TYPE_INT);
|
||||
|
||||
/**
|
||||
* MidoriLocationAction:focus-in:
|
||||
*
|
||||
* The focus-in signal is emitted when the entry obtains the focus.
|
||||
*
|
||||
* Since 0.1.8
|
||||
*/
|
||||
signals[FOCUS_IN] = g_signal_new ("focus-in",
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
(GSignalFlags) (G_SIGNAL_RUN_LAST),
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
signals[FOCUS_OUT] = g_signal_new ("focus-out",
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
(GSignalFlags) (G_SIGNAL_RUN_LAST),
|
||||
|
@ -187,6 +212,24 @@ midori_location_action_class_init (MidoriLocationActionClass* class)
|
|||
"The stock ID of the secondary icon",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* MidoriLocationAction:history:
|
||||
*
|
||||
* The list of history items.
|
||||
*
|
||||
* This is actually a reference to a history instance.
|
||||
*
|
||||
* Since 0.1.8
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_HISTORY,
|
||||
g_param_spec_object (
|
||||
"history",
|
||||
"History",
|
||||
"The list of history items",
|
||||
KATZE_TYPE_ARRAY,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
/* Allow this to be used in tests, it's otherwise private */
|
||||
|
@ -194,10 +237,7 @@ midori_location_action_class_init (MidoriLocationActionClass* class)
|
|||
midori_location_action_entry_for_proxy (GtkWidget* proxy)
|
||||
{
|
||||
GtkWidget* alignment = gtk_bin_get_child (GTK_BIN (proxy));
|
||||
GtkWidget* hbox = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
GList* children = gtk_container_get_children (GTK_CONTAINER (hbox));
|
||||
GtkWidget* entry = g_list_nth_data (children, 0);
|
||||
g_list_free (children);
|
||||
GtkWidget* entry = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
@ -218,9 +258,7 @@ midori_location_action_set_model (MidoriLocationAction* location_action,
|
|||
entry = gtk_bin_get_child (GTK_BIN (location_entry));
|
||||
|
||||
g_object_set (location_entry, "model", model, NULL);
|
||||
gtk_entry_completion_set_model (
|
||||
gtk_entry_get_completion (GTK_ENTRY (entry)),
|
||||
model ? location_action->filter_model : NULL);
|
||||
midori_location_action_completion_init (location_action, GTK_ENTRY (entry));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -285,10 +323,10 @@ midori_location_action_thaw (MidoriLocationAction* location_action)
|
|||
filter_model = gtk_tree_model_filter_new (sort_model, NULL);
|
||||
gtk_tree_model_filter_set_visible_column (
|
||||
GTK_TREE_MODEL_FILTER (filter_model), VISIBLE_COL);
|
||||
midori_location_action_set_model (location_action, location_action->model);
|
||||
|
||||
location_action->filter_model = filter_model;
|
||||
location_action->sort_model = sort_model;
|
||||
midori_location_action_set_model (location_action, location_action->model);
|
||||
|
||||
i = MAX_ITEMS;
|
||||
while (gtk_tree_model_iter_nth_child (sort_model, &iter, NULL, i++))
|
||||
|
@ -300,6 +338,15 @@ midori_location_action_thaw (MidoriLocationAction* location_action)
|
|||
}
|
||||
}
|
||||
|
||||
static GtkTreeModel*
|
||||
midori_location_action_create_model (void)
|
||||
{
|
||||
GtkTreeModel* model = (GtkTreeModel*)gtk_list_store_new (N_COLS,
|
||||
GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING,
|
||||
G_TYPE_INT, G_TYPE_BOOLEAN, G_TYPE_FLOAT);
|
||||
return model;
|
||||
}
|
||||
|
||||
static void
|
||||
midori_location_action_init (MidoriLocationAction* location_action)
|
||||
{
|
||||
|
@ -309,9 +356,7 @@ midori_location_action_init (MidoriLocationAction* location_action)
|
|||
location_action->secondary_icon = NULL;
|
||||
location_action->default_icon = NULL;
|
||||
|
||||
location_action->model = (GtkTreeModel*)gtk_list_store_new (N_COLS,
|
||||
GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING,
|
||||
G_TYPE_INT, G_TYPE_BOOLEAN);
|
||||
location_action->model = midori_location_action_create_model ();
|
||||
|
||||
location_action->filter_model = NULL;
|
||||
location_action->sort_model = NULL;
|
||||
|
@ -319,6 +364,8 @@ midori_location_action_init (MidoriLocationAction* location_action)
|
|||
|
||||
location_action->items = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_free);
|
||||
location_action->net = katze_net_new ();
|
||||
location_action->history = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -335,10 +382,55 @@ midori_location_action_finalize (GObject* object)
|
|||
katze_object_assign (location_action->default_icon, NULL);
|
||||
|
||||
g_hash_table_destroy (location_action->items);
|
||||
katze_object_assign (location_action->net, NULL);
|
||||
katze_object_assign (location_action->history, NULL);
|
||||
|
||||
G_OBJECT_CLASS (midori_location_action_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_location_action_history_remove_item_cb (KatzeArray* folder,
|
||||
KatzeItem* item,
|
||||
MidoriLocationAction* action)
|
||||
{
|
||||
midori_location_action_delete_item_from_uri (action, katze_item_get_uri (item));
|
||||
if (KATZE_IS_ARRAY (item))
|
||||
g_signal_handlers_disconnect_by_func (item,
|
||||
midori_location_action_history_remove_item_cb, action);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_location_action_insert_history_item (MidoriLocationAction* action,
|
||||
KatzeItem* item)
|
||||
{
|
||||
KatzeItem* child;
|
||||
guint i;
|
||||
const gchar* uri;
|
||||
GdkPixbuf* pixbuf = NULL;
|
||||
|
||||
if (KATZE_IS_ARRAY (item))
|
||||
{
|
||||
for (i = katze_array_get_length (KATZE_ARRAY (item)); i > 0; i--)
|
||||
{
|
||||
child = katze_array_get_nth_item (KATZE_ARRAY (item), i - 1);
|
||||
midori_location_action_insert_history_item (action, child);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uri = katze_item_get_uri (item);
|
||||
pixbuf = katze_net_load_icon (action->net, katze_item_get_uri (item),
|
||||
NULL, NULL, NULL);
|
||||
if (!pixbuf)
|
||||
pixbuf = action->default_icon;
|
||||
midori_location_action_add_item (action, uri,
|
||||
pixbuf, katze_item_get_name (item));
|
||||
g_object_unref (pixbuf);
|
||||
g_signal_connect (katze_item_get_parent (item), "remove-item",
|
||||
G_CALLBACK (midori_location_action_history_remove_item_cb), action);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
midori_location_action_set_property (GObject* object,
|
||||
guint prop_id,
|
||||
|
@ -357,6 +449,35 @@ midori_location_action_set_property (GObject* object,
|
|||
midori_location_action_set_secondary_icon (location_action,
|
||||
g_value_get_string (value));
|
||||
break;
|
||||
case PROP_HISTORY:
|
||||
{
|
||||
KatzeArray* history;
|
||||
GtkTreeModel* model;
|
||||
|
||||
history = g_value_dup_object (value);
|
||||
katze_assign (location_action->history, g_object_ref (history));
|
||||
model = g_object_get_data (G_OBJECT (history), "midori-location-model");
|
||||
if (model != NULL)
|
||||
{
|
||||
katze_object_assign (location_action->model, g_object_ref (model));
|
||||
location_action->filter_model = NULL;
|
||||
midori_location_action_thaw (location_action);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_unref (location_action->model);
|
||||
location_action->model = midori_location_action_create_model ();
|
||||
midori_location_action_freeze (location_action);
|
||||
/* FIXME: MidoriBrowser is essentially making up for the lack
|
||||
of synchronicity of newly added items. */
|
||||
midori_location_action_insert_history_item (location_action,
|
||||
KATZE_ITEM (g_value_get_object (value)));
|
||||
midori_location_action_thaw (location_action);
|
||||
g_object_set_data (G_OBJECT (history),
|
||||
"midori-location-model", location_action->model);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -379,6 +500,9 @@ midori_location_action_get_property (GObject* object,
|
|||
case PROP_SECONDARY_ICON:
|
||||
g_value_set_string (value, location_action->secondary_icon);
|
||||
break;
|
||||
case PROP_HISTORY:
|
||||
g_value_set_object (value, location_action->history);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -407,29 +531,12 @@ midori_location_action_activate (GtkAction* action)
|
|||
GTK_ACTION_CLASS (midori_location_action_parent_class)->activate (action);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_location_action_go_clicked_cb (GtkWidget* button,
|
||||
GtkAction* action)
|
||||
{
|
||||
GtkWidget* hbox = gtk_widget_get_parent (button);
|
||||
GList* children = gtk_container_get_children (GTK_CONTAINER (hbox));
|
||||
GtkWidget* location_entry = g_list_nth_data (children, 0);
|
||||
g_list_free (children);
|
||||
GtkWidget* entry = gtk_bin_get_child (GTK_BIN (location_entry));
|
||||
const gchar* uri = gtk_entry_get_text (GTK_ENTRY (entry));
|
||||
if (uri && *uri)
|
||||
g_signal_emit (action, signals[SUBMIT_URI], 0, uri, FALSE);
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
midori_location_action_create_tool_item (GtkAction* action)
|
||||
{
|
||||
GtkWidget* toolitem;
|
||||
GtkWidget* alignment;
|
||||
GtkWidget* hbox;
|
||||
GtkWidget* location_entry;
|
||||
GtkWidget* go_button;
|
||||
GtkWidget* go_icon;
|
||||
|
||||
toolitem = GTK_WIDGET (gtk_tool_item_new ());
|
||||
gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE);
|
||||
|
@ -437,21 +544,9 @@ midori_location_action_create_tool_item (GtkAction* action)
|
|||
alignment = gtk_alignment_new (0.0f, 0.5f, 1.0f, 0.1f);
|
||||
gtk_widget_show (alignment);
|
||||
gtk_container_add (GTK_CONTAINER (toolitem), alignment);
|
||||
hbox = gtk_hbox_new (FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
gtk_container_add (GTK_CONTAINER (alignment), hbox);
|
||||
location_entry = midori_location_entry_new ();
|
||||
gtk_widget_show (location_entry);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), location_entry, TRUE, TRUE, 0);
|
||||
go_button = gtk_button_new ();
|
||||
gtk_button_set_focus_on_click (GTK_BUTTON (go_button), FALSE);
|
||||
gtk_button_set_relief (GTK_BUTTON (go_button), GTK_RELIEF_NONE);
|
||||
go_icon = gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU);
|
||||
gtk_button_set_image (GTK_BUTTON (go_button), go_icon);
|
||||
gtk_widget_show (go_button);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), go_button, FALSE, FALSE, 0);
|
||||
g_signal_connect (go_button, "clicked",
|
||||
G_CALLBACK (midori_location_action_go_clicked_cb), action);
|
||||
gtk_container_add (GTK_CONTAINER (alignment), location_entry);
|
||||
|
||||
return toolitem;
|
||||
}
|
||||
|
@ -485,6 +580,15 @@ midori_location_action_key_press_event_cb (GtkWidget* widget,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
midori_location_action_focus_in_event_cb (GtkWidget* widget,
|
||||
GdkEventKey* event,
|
||||
GtkAction* action)
|
||||
{
|
||||
g_signal_emit (action, signals[FOCUS_IN], 0);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
midori_location_action_focus_out_event_cb (GtkWidget* widget,
|
||||
GdkEventKey* event,
|
||||
|
@ -504,23 +608,6 @@ midori_location_action_icon_released_cb (GtkWidget* widget,
|
|||
g_signal_emit (action, signals[SECONDARY_ICON_RELEASED], 0, widget);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_location_entry_render_pixbuf_cb (GtkCellLayout* layout,
|
||||
GtkCellRenderer* renderer,
|
||||
GtkTreeModel* model,
|
||||
GtkTreeIter* iter,
|
||||
gpointer data)
|
||||
{
|
||||
GdkPixbuf* pixbuf;
|
||||
|
||||
gtk_tree_model_get (model, iter, FAVICON_COL, &pixbuf, -1);
|
||||
if (pixbuf)
|
||||
{
|
||||
g_object_set (renderer, "pixbuf", pixbuf, "yalign", 0.25, NULL);
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
midori_location_entry_render_text_cb (GtkCellLayout* layout,
|
||||
GtkCellRenderer* renderer,
|
||||
|
@ -662,7 +749,7 @@ midori_location_action_set_item (MidoriLocationAction* location_action,
|
|||
gtk_tree_model_get (location_action->model, iter, TITLE_COL, &item->title, -1);
|
||||
|
||||
gtk_list_store_set (GTK_LIST_STORE (location_action->model), iter,
|
||||
URI_COL, item->uri, TITLE_COL, item->title, -1);
|
||||
URI_COL, item->uri, TITLE_COL, item->title, YALIGN_COL, 0.25, -1);
|
||||
|
||||
gtk_tree_model_get (location_action->model, iter, FAVICON_COL, &icon, -1);
|
||||
if (item->favicon)
|
||||
|
@ -820,16 +907,26 @@ midori_location_action_add_actions (GtkEntryCompletion* completion,
|
|||
|
||||
static void
|
||||
midori_location_action_completion_init (MidoriLocationAction* location_action,
|
||||
GtkWidget* location_entry)
|
||||
GtkEntry* entry)
|
||||
{
|
||||
GtkWidget* entry;
|
||||
GtkEntryCompletion* completion;
|
||||
GtkCellRenderer* renderer;
|
||||
|
||||
entry = gtk_bin_get_child (GTK_BIN (location_entry));
|
||||
completion = gtk_entry_completion_new ();
|
||||
if ((completion = gtk_entry_get_completion (entry)))
|
||||
{
|
||||
gtk_entry_completion_set_model (completion,
|
||||
midori_location_action_is_frozen (location_action)
|
||||
? NULL : location_action->filter_model);
|
||||
return;
|
||||
}
|
||||
|
||||
completion = gtk_entry_completion_new ();
|
||||
gtk_entry_set_completion (entry, completion);
|
||||
g_object_unref (completion);
|
||||
gtk_entry_completion_set_model (completion,
|
||||
midori_location_action_is_frozen (location_action)
|
||||
? NULL : location_action->filter_model);
|
||||
|
||||
gtk_entry_completion_set_model (completion, location_action->sort_model);
|
||||
gtk_entry_completion_set_text_column (completion, URI_COL);
|
||||
#if GTK_CHECK_VERSION (2, 12, 0)
|
||||
gtk_entry_completion_set_inline_selection (completion, TRUE);
|
||||
|
@ -838,10 +935,12 @@ midori_location_action_completion_init (MidoriLocationAction* location_action,
|
|||
|
||||
renderer = gtk_cell_renderer_pixbuf_new ();
|
||||
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), renderer, FALSE);
|
||||
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (completion), renderer,
|
||||
midori_location_entry_render_pixbuf_cb,
|
||||
NULL, NULL);
|
||||
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (completion), renderer,
|
||||
"pixbuf", FAVICON_COL, "yalign", YALIGN_COL, NULL);
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
gtk_cell_renderer_set_fixed_size (renderer, 1, -1);
|
||||
gtk_cell_renderer_text_set_fixed_height_from_font (
|
||||
GTK_CELL_RENDERER_TEXT (renderer), 2);
|
||||
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), renderer, TRUE);
|
||||
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (completion), renderer,
|
||||
midori_location_entry_render_text_cb,
|
||||
|
@ -849,7 +948,7 @@ midori_location_action_completion_init (MidoriLocationAction* location_action,
|
|||
gtk_entry_completion_set_match_func (completion,
|
||||
midori_location_entry_completion_match_cb, NULL, NULL);
|
||||
|
||||
gtk_entry_set_completion (GTK_ENTRY (entry), completion);
|
||||
|
||||
g_signal_connect (completion, "match-selected",
|
||||
G_CALLBACK (midori_location_entry_match_selected_cb), location_action);
|
||||
|
||||
|
@ -857,8 +956,6 @@ midori_location_action_completion_init (MidoriLocationAction* location_action,
|
|||
location_action->search_engines);
|
||||
g_signal_connect (completion, "action-activated",
|
||||
G_CALLBACK (midori_location_entry_action_activated_cb), location_action);
|
||||
|
||||
g_object_unref (completion);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -923,21 +1020,24 @@ midori_location_action_connect_proxy (GtkAction* action,
|
|||
/* Setup the renderer for the favicon */
|
||||
renderer = gtk_cell_renderer_pixbuf_new ();
|
||||
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (entry), renderer, FALSE);
|
||||
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (entry),
|
||||
renderer, midori_location_entry_render_pixbuf_cb, NULL, NULL);
|
||||
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (entry), renderer,
|
||||
"pixbuf", FAVICON_COL, "yalign", YALIGN_COL, NULL);
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (entry), renderer, TRUE);
|
||||
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (entry),
|
||||
renderer, midori_location_entry_render_text_cb, NULL, NULL);
|
||||
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (entry), -1);
|
||||
midori_location_action_completion_init (location_action, entry);
|
||||
midori_location_action_completion_init (location_action,
|
||||
GTK_ENTRY (gtk_bin_get_child (GTK_BIN (entry))));
|
||||
g_signal_connect (entry, "changed",
|
||||
G_CALLBACK (midori_location_action_entry_changed_cb), action);
|
||||
|
||||
g_object_connect (gtk_bin_get_child (GTK_BIN (entry)),
|
||||
"signal::key-press-event",
|
||||
midori_location_action_key_press_event_cb, action,
|
||||
"signal::focus-in-event",
|
||||
midori_location_action_focus_in_event_cb, action,
|
||||
"signal::focus-out-event",
|
||||
midori_location_action_focus_out_event_cb, action,
|
||||
"signal::icon-release",
|
||||
|
@ -1271,6 +1371,7 @@ midori_location_action_set_search_engines (MidoriLocationAction* location_action
|
|||
entry = midori_location_action_entry_for_proxy (proxies->data);
|
||||
child = gtk_bin_get_child (GTK_BIN (entry));
|
||||
|
||||
midori_location_action_completion_init (location_action, GTK_ENTRY (child));
|
||||
completion = gtk_entry_get_completion (GTK_ENTRY (child));
|
||||
i = 0;
|
||||
if (location_action->search_engines)
|
||||
|
@ -1342,7 +1443,7 @@ midori_location_action_set_secondary_icon (MidoriLocationAction* location_action
|
|||
}
|
||||
|
||||
/**
|
||||
* midori_location_action_set_item_from_uri:
|
||||
* midori_location_action_delete_item_from_uri:
|
||||
* @location_action: a #MidoriLocationAction
|
||||
* @uri: a string
|
||||
*
|
||||
|
|
|
@ -231,7 +231,6 @@ static void
|
|||
midori_panel_button_detach_clicked_cb (GtkWidget* toolbutton,
|
||||
MidoriPanel* panel)
|
||||
{
|
||||
/* FIXME: Use stock icon for window */
|
||||
/* FIXME: What happens when the browser is destroyed? */
|
||||
/* FIXME: What about multiple browsers? */
|
||||
/* FIXME: Should we remember if the child was detached? */
|
||||
|
@ -248,6 +247,7 @@ midori_panel_button_detach_clicked_cb (GtkWidget* toolbutton,
|
|||
GtkWidget* vbox = gtk_vbox_new (FALSE, 0);
|
||||
g_object_set_data (G_OBJECT (window), "scrolled", scrolled);
|
||||
gtk_window_set_title (GTK_WINDOW (window), title);
|
||||
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), TRUE);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 250, 400);
|
||||
gtk_window_set_transient_for (GTK_WINDOW (window),
|
||||
GTK_WINDOW (gtk_widget_get_toplevel (panel->notebook)));
|
||||
|
@ -329,10 +329,8 @@ midori_panel_init (MidoriPanel* panel)
|
|||
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_FULLSCREEN);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (toolitem), FALSE);
|
||||
panel->button_detach = toolitem;
|
||||
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem),
|
||||
_("Detach chosen panel from the window"));
|
||||
gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (toolitem),
|
||||
_("Whether to detach the chosen panel from the window"));
|
||||
_("Detach chosen panel from the window"));
|
||||
g_signal_connect (toolitem, "clicked",
|
||||
G_CALLBACK (midori_panel_button_detach_clicked_cb), panel);
|
||||
#if HAVE_OSX
|
||||
|
@ -341,10 +339,8 @@ midori_panel_init (MidoriPanel* panel)
|
|||
gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, -1);
|
||||
#endif
|
||||
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_GO_FORWARD);
|
||||
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem),
|
||||
_("Align sidepanel on the right"));
|
||||
gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (toolitem),
|
||||
_("Whether to align the sidepanel on the right"));
|
||||
_("Align sidepanel to the right"));
|
||||
g_signal_connect (toolitem, "clicked",
|
||||
G_CALLBACK (midori_panel_button_align_clicked_cb), panel);
|
||||
#if HAVE_OSX
|
||||
|
@ -488,7 +484,7 @@ midori_panel_set_compact (MidoriPanel* panel,
|
|||
|
||||
/**
|
||||
* midori_panel_set_right_aligned:
|
||||
* @compact: %TRUE if the panel should be aligned to the right
|
||||
* @right_aligned: %TRUE if the panel should be aligned to the right
|
||||
*
|
||||
* Determines if the panel should be right aligned.
|
||||
*
|
||||
|
@ -508,6 +504,9 @@ midori_panel_set_right_aligned (MidoriPanel* panel,
|
|||
gtk_tool_button_set_stock_id (GTK_TOOL_BUTTON (panel->button_align),
|
||||
right_aligned ? GTK_STOCK_GO_BACK : GTK_STOCK_GO_FORWARD);
|
||||
panel->right_aligned = right_aligned;
|
||||
gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (panel->button_align),
|
||||
!panel->right_aligned ? _("Align sidepanel to the right")
|
||||
: _("Align sidepanel to the left"));
|
||||
g_object_notify (G_OBJECT (panel), "right-aligned");
|
||||
}
|
||||
|
||||
|
@ -662,7 +661,7 @@ midori_panel_append_page (MidoriPanel* panel,
|
|||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (midori_panel_menu_item_activate_cb),
|
||||
panel);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (panel->menu), menuitem);
|
||||
gtk_menu_shell_insert (GTK_MENU_SHELL (panel->menu), menuitem, 4);
|
||||
g_object_set_data (G_OBJECT (scrolled), "panel-menuitem", menuitem);
|
||||
g_signal_connect (viewable, "destroy",
|
||||
G_CALLBACK (midori_panel_widget_destroy_cb), menuitem);
|
||||
|
@ -798,6 +797,8 @@ midori_panel_page_num (MidoriPanel* panel,
|
|||
*
|
||||
* The child must be visible, otherwise the underlying GtkNotebook will
|
||||
* silently ignore the attempt to switch the page.
|
||||
*
|
||||
* Since 0.1.8 the "page" property is notifying changes.
|
||||
**/
|
||||
void
|
||||
midori_panel_set_current_page (MidoriPanel* panel,
|
||||
|
@ -807,15 +808,15 @@ midori_panel_set_current_page (MidoriPanel* panel,
|
|||
|
||||
g_return_if_fail (MIDORI_IS_PANEL (panel));
|
||||
|
||||
gtk_notebook_set_current_page (GTK_NOTEBOOK (panel->toolbook), n);
|
||||
gtk_notebook_set_current_page (GTK_NOTEBOOK (panel->notebook), n);
|
||||
|
||||
if ((viewable = midori_panel_get_nth_page (panel, n)))
|
||||
{
|
||||
const gchar* label;
|
||||
|
||||
gtk_notebook_set_current_page (GTK_NOTEBOOK (panel->toolbook), n);
|
||||
gtk_notebook_set_current_page (GTK_NOTEBOOK (panel->notebook), n);
|
||||
label = midori_viewable_get_label (MIDORI_VIEWABLE (viewable));
|
||||
g_object_set (panel->toolbar_label, "label", label, NULL);
|
||||
g_object_notify (G_OBJECT (panel), "page");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -452,9 +452,14 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
|
|||
FILLED_ADD (hbox, 1, 2, 0, 1);
|
||||
label = gtk_label_new (_("Fixed-width Font Family"));
|
||||
INDENTED_ADD (label, 0, 1, 1, 2);
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
button = katze_property_proxy (settings, "monospace-font-family", "font");
|
||||
gtk_widget_set_tooltip_text (button, _("The font family used to display fixed-width text"));
|
||||
INDENTED_ADD (button, 1, 2, 1, 2);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
|
||||
entry = katze_property_proxy (settings, "default-monospace-font-size", NULL);
|
||||
gtk_widget_set_tooltip_text (entry, _("The font size used to display fixed-width text"));
|
||||
gtk_box_pack_end (GTK_BOX (hbox), entry, FALSE, FALSE, 4);
|
||||
INDENTED_ADD (hbox, 1, 2, 1, 2);
|
||||
label = gtk_label_new (_("Minimum Font Size"));
|
||||
INDENTED_ADD (label, 0, 1, 2, 3);
|
||||
entry = katze_property_proxy (settings, "minimum-font-size", NULL);
|
||||
|
@ -546,12 +551,10 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
|
|||
INDENTED_ADD (label, 0, 1, 0, 1);
|
||||
button = katze_property_proxy (settings, "open-new-pages-in", NULL);
|
||||
FILLED_ADD (button, 1, 2, 0, 1);
|
||||
#if HAVE_UNIQUE
|
||||
label = katze_property_label (settings, "open-external-pages-in");
|
||||
INDENTED_ADD (label, 0, 1, 1, 2);
|
||||
button = katze_property_proxy (settings, "open-external-pages-in", NULL);
|
||||
FILLED_ADD (button, 1, 2, 1, 2);
|
||||
#endif
|
||||
button = katze_property_proxy (settings, "always-show-tabbar", NULL);
|
||||
INDENTED_ADD (button, 0, 1, 2, 3);
|
||||
button = katze_property_proxy (settings, "open-tabs-in-the-background", NULL);
|
||||
|
|
|
@ -1016,6 +1016,20 @@ midori_search_action_get_editor (MidoriSearchAction* search_action,
|
|||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_search_action_activate_edit_cb (GtkTreeView *treeview,
|
||||
GtkTreePath *path,
|
||||
GtkTreeViewColumn *column,
|
||||
MidoriSearchAction* search_action)
|
||||
{
|
||||
GtkTreeSelection* selection;
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
|
||||
if (gtk_tree_selection_get_selected (selection, NULL, NULL))
|
||||
midori_search_action_get_editor (search_action, FALSE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
midori_search_action_dialog_add_cb (GtkWidget* widget,
|
||||
MidoriSearchAction* search_action)
|
||||
|
@ -1228,6 +1242,8 @@ midori_search_action_get_dialog (MidoriSearchAction* search_action)
|
|||
g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
|
||||
"changed", G_CALLBACK (midori_search_action_treeview_selection_cb),
|
||||
search_action);
|
||||
g_signal_connect (treeview, "row-activated",
|
||||
G_CALLBACK (midori_search_action_activate_edit_cb), search_action);
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
|
||||
g_object_set_data (G_OBJECT (treeview), "search-action", search_action);
|
||||
column = gtk_tree_view_column_new ();
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#define STOCK_EXTENSION "extension"
|
||||
#define STOCK_EXTENSIONS "extension"
|
||||
#define STOCK_HISTORY "document-open-recent"
|
||||
#define STOCK_WEB_BROWSER "web-browser"
|
||||
#define STOCK_NEWS_FEED "news-feed"
|
||||
#define STOCK_STYLE "gnome-settings-theme"
|
||||
#define STOCK_STYLES "gnome-settings-theme"
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "midori-view.h"
|
||||
#include "midori-stock.h"
|
||||
#include "midori-browser.h"
|
||||
|
||||
#include "compat.h"
|
||||
#include "marshal.h"
|
||||
|
@ -26,6 +27,7 @@
|
|||
#include <glib/gi18n.h>
|
||||
#include <glib/gprintf.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <webkit/webkit.h>
|
||||
|
||||
/* This is unstable API, so we need to declare it */
|
||||
|
@ -45,6 +47,11 @@ midori_search_action_get_icon (KatzeNet* net,
|
|||
static void
|
||||
midori_view_construct_web_view (MidoriView* view);
|
||||
|
||||
GdkPixbuf*
|
||||
midori_view_get_snapshot (MidoriView* view,
|
||||
gint width,
|
||||
gint height);
|
||||
|
||||
struct _MidoriView
|
||||
{
|
||||
GtkScrolledWindow parent_instance;
|
||||
|
@ -74,6 +81,7 @@ struct _MidoriView
|
|||
|
||||
GtkWidget* menu_item;
|
||||
GtkWidget* tab_label;
|
||||
/* GtkWidget* tooltip_image; */
|
||||
GtkWidget* tab_icon;
|
||||
GtkWidget* tab_title;
|
||||
GtkWidget* tab_close;
|
||||
|
@ -514,6 +522,7 @@ midori_view_class_init (MidoriViewClass* class)
|
|||
static void
|
||||
midori_view_update_title (MidoriView* view)
|
||||
{
|
||||
#ifndef G_OS_WIN32
|
||||
/* If left-to-right text is combined with right-to-left text the default
|
||||
behaviour of Pango can result in awkwardly aligned text. For example
|
||||
"بستيان نوصر (hadess) | An era comes to an end - Midori" becomes
|
||||
|
@ -525,6 +534,7 @@ midori_view_update_title (MidoriView* view)
|
|||
gchar* new_title = g_strconcat ("", view->title, NULL);
|
||||
katze_assign (view->title, new_title);
|
||||
}
|
||||
#endif
|
||||
#define title midori_view_get_display_title (view)
|
||||
if (view->tab_label)
|
||||
{
|
||||
|
@ -547,7 +557,9 @@ midori_view_update_title (MidoriView* view)
|
|||
soup_uri_free (uri);
|
||||
}
|
||||
gtk_label_set_text (GTK_LABEL (view->tab_title), title);
|
||||
#if 1
|
||||
gtk_widget_set_tooltip_text (view->tab_title, title);
|
||||
#endif
|
||||
}
|
||||
if (view->menu_item)
|
||||
gtk_label_set_text (GTK_LABEL (gtk_bin_get_child (GTK_BIN (
|
||||
|
@ -720,10 +732,12 @@ webkit_web_view_load_error_cb (WebKitWebView* web_view,
|
|||
GError* error,
|
||||
MidoriView* view)
|
||||
{
|
||||
const gchar* template_file = DATADIR "/midori/res/error.html";
|
||||
gchar* template_file = g_build_filename ("midori", "res", "error.html", NULL);
|
||||
gchar* path = sokoke_find_data_filename (template_file);
|
||||
gchar* template;
|
||||
|
||||
if (g_file_get_contents (template_file, &template, NULL, NULL))
|
||||
g_free (template_file);
|
||||
if (g_file_get_contents (path, &template, NULL, NULL))
|
||||
{
|
||||
SoupServer* res_server;
|
||||
guint port;
|
||||
|
@ -754,9 +768,11 @@ webkit_web_view_load_error_cb (WebKitWebView* web_view,
|
|||
g_free (res_root);
|
||||
g_free (stock_root);
|
||||
g_free (result);
|
||||
g_free (path);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
g_free (path);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -777,7 +793,7 @@ webkit_web_frame_load_done_cb (WebKitWebFrame* web_frame,
|
|||
data = g_strdup_printf (
|
||||
"<html><head><title>%s</title></head>"
|
||||
"<body><h1>%s</h1>"
|
||||
"<img src=\"file://" DATADIR "/midori/logo-shade.png\" "
|
||||
"<img src=\"file://" MDATADIR "/midori/logo-shade.png\" "
|
||||
"style=\"position: absolute; right: 15px; bottom: 15px;\">"
|
||||
"<p />The page you were opening doesn't exist."
|
||||
"<p />Try to <a href=\"%s\">load the page again</a>, "
|
||||
|
@ -817,12 +833,13 @@ webkit_web_view_load_finished_cb (WebKitWebView* web_view,
|
|||
"f.push (l[i].href + '|' + l[i].title); } return f; }"
|
||||
"feeds (document.getElementsByTagName ('link'))", NULL);
|
||||
gchar** items = g_strsplit (value, ",", 0);
|
||||
gchar** iter;
|
||||
guint i = 0;
|
||||
|
||||
katze_array_clear (view->news_feeds);
|
||||
for (iter = items; iter && *iter; iter++)
|
||||
if (items != NULL)
|
||||
while (items[i] != NULL)
|
||||
{
|
||||
gchar** parts = g_strsplit (*iter, "|", 2);
|
||||
gchar** parts = g_strsplit (items[i], "|", 2);
|
||||
KatzeItem* item = g_object_new (KATZE_TYPE_ITEM,
|
||||
"uri", parts ? *parts : "",
|
||||
"name", parts && *parts ? parts[1] : NULL,
|
||||
|
@ -830,6 +847,7 @@ webkit_web_view_load_finished_cb (WebKitWebView* web_view,
|
|||
katze_array_add_item (view->news_feeds, item);
|
||||
g_object_unref (item);
|
||||
g_strfreev (parts);
|
||||
i++;
|
||||
}
|
||||
g_strfreev (items);
|
||||
g_object_set_data (G_OBJECT (view), "news-feeds",
|
||||
|
@ -1007,6 +1025,9 @@ gtk_widget_button_press_event_cb (WebKitWebView* web_view,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* We propagate the event, since it may otherwise be stuck in WebKit */
|
||||
g_signal_emit_by_name (view, "event", event, &background);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -1016,15 +1037,16 @@ gtk_widget_key_press_event_cb (WebKitWebView* web_view,
|
|||
MidoriView* view)
|
||||
{
|
||||
guint character = gdk_unicode_to_keyval (event->keyval);
|
||||
/* Skip control characters */
|
||||
if (character == (event->keyval | 0x01000000))
|
||||
return FALSE;
|
||||
|
||||
if (character == '.' || character == '/')
|
||||
if (event->keyval == '.' || event->keyval == '/' || event->keyval == GDK_KP_Divide)
|
||||
character = '\0';
|
||||
else if (!view->find_while_typing)
|
||||
return FALSE;
|
||||
|
||||
/* Skip control characters */
|
||||
if (character == (event->keyval | 0x01000000))
|
||||
return FALSE;
|
||||
|
||||
if (!webkit_web_view_can_cut_clipboard (web_view)
|
||||
&& !webkit_web_view_can_paste_clipboard (web_view))
|
||||
{
|
||||
|
@ -1070,13 +1092,6 @@ midori_web_view_menu_new_tab_activate_cb (GtkWidget* widget,
|
|||
view->open_tabs_in_the_background);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_web_view_menu_action_add_speed_dial_cb (GtkWidget* widget,
|
||||
MidoriView* view)
|
||||
{
|
||||
g_signal_emit (view, signals[ADD_SPEED_DIAL], 0, view->link_uri);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_web_view_menu_search_web_activate_cb (GtkWidget* widget,
|
||||
MidoriView* view)
|
||||
|
@ -1121,19 +1136,13 @@ midori_web_view_menu_add_bookmark_activate_cb (GtkWidget* widget,
|
|||
g_signal_emit (view, signals[ADD_BOOKMARK], 0, view->link_uri);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_web_view_menu_action_activate_cb (GtkWidget* widget,
|
||||
MidoriView* view)
|
||||
{
|
||||
const gchar* action = g_object_get_data (G_OBJECT (widget), "action");
|
||||
g_signal_emit (view, signals[ACTIVATE_ACTION], 0, action);
|
||||
}
|
||||
|
||||
static void
|
||||
webkit_web_view_populate_popup_cb (WebKitWebView* web_view,
|
||||
GtkWidget* menu,
|
||||
MidoriView* view)
|
||||
{
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (view));
|
||||
GtkActionGroup* actions = midori_browser_get_action_group (browser);
|
||||
GtkWidget* menuitem;
|
||||
GtkWidget* icon;
|
||||
gchar* stock_id;
|
||||
|
@ -1301,63 +1310,74 @@ webkit_web_view_populate_popup_cb (WebKitWebView* web_view,
|
|||
}
|
||||
}
|
||||
g_list_free (items);
|
||||
menuitem = gtk_image_menu_item_new_with_mnemonic (_("Undo Close Tab"));
|
||||
icon = gtk_image_new_from_stock (GTK_STOCK_UNDELETE, GTK_ICON_SIZE_MENU);
|
||||
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon);
|
||||
menuitem = sokoke_action_create_popup_menu_item (
|
||||
gtk_action_group_get_action (actions, "UndoTabClose"));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
g_object_set_data (G_OBJECT (menuitem), "action", "UndoTabClose");
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (midori_web_view_menu_action_activate_cb), view);
|
||||
/* FIXME: Make this sensitive only when there is a tab to undo */
|
||||
gtk_widget_show (menuitem);
|
||||
|
||||
menuitem = gtk_separator_menu_item_new ();
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
gtk_widget_show (menuitem);
|
||||
|
||||
menuitem = gtk_image_menu_item_new_from_stock (STOCK_BOOKMARK_ADD, NULL);
|
||||
menuitem = sokoke_action_create_popup_menu_item (
|
||||
gtk_action_group_get_action (actions, "ZoomIn"));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
menuitem = sokoke_action_create_popup_menu_item (
|
||||
gtk_action_group_get_action (actions, "ZoomOut"));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
|
||||
menuitem = sokoke_action_create_popup_menu_item (
|
||||
gtk_action_group_get_action (actions, "Encoding"));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
if (GTK_WIDGET_IS_SENSITIVE (menuitem))
|
||||
{
|
||||
GtkWidget* sub_menu;
|
||||
static const GtkActionEntry encodings[] = {
|
||||
{ "EncodingAutomatic" },
|
||||
{ "EncodingChinese" },
|
||||
{ "EncodingJapanese" },
|
||||
{ "EncodingRussian" },
|
||||
{ "EncodingUnicode" },
|
||||
{ "EncodingWestern" },
|
||||
{ "EncodingCustom" },
|
||||
};
|
||||
guint i;
|
||||
|
||||
sub_menu = gtk_menu_new ();
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), sub_menu);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (encodings); i++)
|
||||
{
|
||||
menuitem = sokoke_action_create_popup_menu_item (
|
||||
gtk_action_group_get_action (actions, encodings[i].name));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (sub_menu), menuitem);
|
||||
}
|
||||
}
|
||||
|
||||
menuitem = gtk_separator_menu_item_new ();
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
g_object_set_data (G_OBJECT (menuitem), "action", "BookmarkAdd");
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (midori_web_view_menu_action_activate_cb), view);
|
||||
gtk_widget_show (menuitem);
|
||||
|
||||
menuitem = sokoke_action_create_popup_menu_item (
|
||||
gtk_action_group_get_action (actions, "BookmarkAdd"));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
|
||||
if (view->speed_dial_in_new_tabs && !midori_view_is_blank (view))
|
||||
{
|
||||
menuitem = gtk_image_menu_item_new_with_mnemonic (_("Add to Speed _dial"));
|
||||
menuitem = sokoke_action_create_popup_menu_item (
|
||||
gtk_action_group_get_action (actions, "AddSpeedDial"));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
g_object_set_data (G_OBJECT (menuitem), "action", "AddSpeedDial");
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (midori_web_view_menu_action_add_speed_dial_cb), view);
|
||||
gtk_widget_show (menuitem);
|
||||
}
|
||||
|
||||
menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_SAVE_AS, NULL);
|
||||
menuitem = sokoke_action_create_popup_menu_item (
|
||||
gtk_action_group_get_action (actions, "SaveAs"));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
g_object_set_data (G_OBJECT (menuitem), "action", "SaveAs");
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (midori_web_view_menu_action_activate_cb), view);
|
||||
gtk_widget_show (menuitem);
|
||||
/* Currently views that don't support source, don't support
|
||||
saving either. If that changes, we need to think of something. */
|
||||
if (!midori_view_can_view_source (view))
|
||||
gtk_widget_set_sensitive (menuitem, FALSE);
|
||||
|
||||
menuitem = gtk_image_menu_item_new_with_mnemonic (_("View _Source"));
|
||||
menuitem = sokoke_action_create_popup_menu_item (
|
||||
gtk_action_group_get_action (actions, "SourceView"));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
g_object_set_data (G_OBJECT (menuitem), "action", "SourceView");
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (midori_web_view_menu_action_activate_cb), view);
|
||||
gtk_widget_show (menuitem);
|
||||
if (!midori_view_can_view_source (view))
|
||||
gtk_widget_set_sensitive (menuitem, FALSE);
|
||||
|
||||
menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_PRINT, NULL);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
g_object_set_data (G_OBJECT (menuitem), "action", "Print");
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (midori_web_view_menu_action_activate_cb), view);
|
||||
gtk_widget_show (menuitem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1479,6 +1499,7 @@ webkit_web_view_mime_type_decision_cb (GtkWidget* web_view,
|
|||
}
|
||||
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
|
||||
GTK_STOCK_SAVE, 1,
|
||||
GTK_STOCK_SAVE_AS, 4,
|
||||
GTK_STOCK_CANCEL, 2,
|
||||
GTK_STOCK_OPEN, 3,
|
||||
NULL);
|
||||
|
@ -1487,6 +1508,11 @@ webkit_web_view_mime_type_decision_cb (GtkWidget* web_view,
|
|||
g_object_set_data (G_OBJECT (view), "open-download", (gpointer)0);
|
||||
switch (response)
|
||||
{
|
||||
case 4:
|
||||
g_object_set_data (G_OBJECT (view), "save-as-download", (gpointer)1);
|
||||
webkit_web_policy_decision_download (decision);
|
||||
webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (view->web_view));
|
||||
return TRUE;
|
||||
case 3:
|
||||
g_object_set_data (G_OBJECT (view), "open-download", (gpointer)1);
|
||||
case 1:
|
||||
|
@ -1525,7 +1551,10 @@ webkit_web_view_download_requested_cb (GtkWidget* web_view,
|
|||
gboolean handled;
|
||||
g_object_set_data (G_OBJECT (download), "open-download",
|
||||
g_object_get_data (G_OBJECT (view), "open-download"));
|
||||
g_object_set_data (G_OBJECT (download), "save-as-download",
|
||||
g_object_get_data (G_OBJECT (view), "save-as-download"));
|
||||
g_object_set_data (G_OBJECT (view), "open-download", (gpointer)0);
|
||||
g_object_set_data (G_OBJECT (view), "save-as-download", (gpointer)0);
|
||||
g_signal_emit (view, signals[DOWNLOAD_REQUESTED], 0, download, &handled);
|
||||
return handled;
|
||||
}
|
||||
|
@ -2038,7 +2067,7 @@ midori_view_set_uri (MidoriView* view,
|
|||
|
||||
katze_assign (view->uri, g_strdup (""));
|
||||
|
||||
g_file_get_contents (DATADIR "/midori/res/speeddial-head.html",
|
||||
g_file_get_contents (MDATADIR "/midori/res/speeddial-head.html",
|
||||
&speed_dial_head, NULL, NULL);
|
||||
|
||||
res_server = sokoke_get_res_server ();
|
||||
|
@ -2050,7 +2079,7 @@ midori_view_set_uri (MidoriView* view,
|
|||
|
||||
if (!g_file_test (body_fname, G_FILE_TEST_EXISTS))
|
||||
{
|
||||
if (g_file_get_contents (DATADIR "/midori/res/speeddial.json",
|
||||
if (g_file_get_contents (MDATADIR "/midori/res/speeddial.json",
|
||||
&speed_dial_body, NULL, NULL))
|
||||
g_file_set_contents (body_fname, speed_dial_body, -1, NULL);
|
||||
else
|
||||
|
@ -2101,7 +2130,7 @@ midori_view_set_uri (MidoriView* view,
|
|||
data = g_strdup_printf (
|
||||
"<html><head><title>%s</title></head>"
|
||||
"<body><h1>%s</h1>"
|
||||
"<img src=\"file://" DATADIR "/midori/logo-shade.png\" "
|
||||
"<img src=\"file://" MDATADIR "/midori/logo-shade.png\" "
|
||||
"style=\"position: absolute; right: 15px; bottom: 15px;\">"
|
||||
"<p />The document %s of type '%s' cannot be displayed."
|
||||
"</body></html>",
|
||||
|
@ -2118,7 +2147,7 @@ midori_view_set_uri (MidoriView* view,
|
|||
data = g_strdup_printf (
|
||||
"<html><head><title>%s</title></head>"
|
||||
"<body><h1>%s</h1>"
|
||||
"<img src=\"file://" DATADIR "/midori/logo-shade.png\" "
|
||||
"<img src=\"file://" MDATADIR "/midori/logo-shade.png\" "
|
||||
"style=\"position: absolute; right: 15px; bottom: 15px;\">"
|
||||
"<p />There is no documentation installed at %s."
|
||||
"You may want to ask your distribution or "
|
||||
|
@ -2178,6 +2207,8 @@ midori_view_is_blank (MidoriView* view)
|
|||
*
|
||||
* Retrieves the icon of the view.
|
||||
*
|
||||
* The returned icon is owned by the @view and must not be modified.
|
||||
*
|
||||
* Return value: a #GdkPixbuf
|
||||
**/
|
||||
GdkPixbuf*
|
||||
|
@ -2396,6 +2427,84 @@ midori_view_get_proxy_menu_item (MidoriView* view)
|
|||
return view->menu_item;
|
||||
}
|
||||
|
||||
static void
|
||||
midori_view_tab_label_menu_open_cb (GtkWidget* menuitem,
|
||||
GtkWidget* view)
|
||||
{
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (view);
|
||||
midori_browser_set_current_tab (browser, view);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_view_tab_label_menu_window_new_cb (GtkWidget* menuitem,
|
||||
GtkWidget* view)
|
||||
{
|
||||
g_signal_emit (view, signals[NEW_WINDOW], 0,
|
||||
midori_view_get_display_uri (MIDORI_VIEW (view)));
|
||||
}
|
||||
|
||||
static void
|
||||
midori_view_tab_label_menu_duplicate_tab_cb (GtkWidget* menuitem,
|
||||
MidoriView* view)
|
||||
{
|
||||
MidoriNewView where = MIDORI_NEW_VIEW_TAB;
|
||||
GtkWidget* new_view = g_object_new (MIDORI_TYPE_VIEW,
|
||||
"net", view->net, "settings", view->settings, NULL);
|
||||
midori_view_set_uri (MIDORI_VIEW (new_view),
|
||||
midori_view_get_display_uri (view));
|
||||
g_signal_emit (view, signals[NEW_VIEW], 0, new_view, where);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_view_tab_label_menu_close_cb (GtkWidget* menuitem,
|
||||
GtkWidget* view)
|
||||
{
|
||||
gtk_widget_destroy (view);
|
||||
}
|
||||
|
||||
/**
|
||||
* midori_view_get_tab_menu:
|
||||
* @view: a #MidoriView
|
||||
*
|
||||
* Retrieves a menu that is typically shown when right-clicking
|
||||
* a tab label or equivalent representation.
|
||||
*
|
||||
* Return value: a #GtkMenu
|
||||
*
|
||||
* Since: 0.1.8
|
||||
**/
|
||||
GtkWidget*
|
||||
midori_view_get_tab_menu (MidoriView* view)
|
||||
{
|
||||
GtkWidget* menu;
|
||||
GtkWidget* menuitem;
|
||||
|
||||
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
||||
|
||||
menu = gtk_menu_new ();
|
||||
menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_OPEN, NULL);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (midori_view_tab_label_menu_open_cb), view);
|
||||
menuitem = gtk_image_menu_item_new_from_stock (STOCK_WINDOW_NEW, NULL);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (midori_view_tab_label_menu_window_new_cb), view);
|
||||
menuitem = gtk_menu_item_new_with_mnemonic (_("_Duplicate Tab"));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (midori_view_tab_label_menu_duplicate_tab_cb), view);
|
||||
menuitem = gtk_separator_menu_item_new ();
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLOSE, NULL);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (midori_view_tab_label_menu_close_cb), view);
|
||||
gtk_widget_show_all (menu);
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
midori_view_tab_label_button_release_event (GtkWidget* tab_label,
|
||||
GdkEventButton* event,
|
||||
|
@ -2407,6 +2516,15 @@ midori_view_tab_label_button_release_event (GtkWidget* tab_label,
|
|||
gtk_widget_destroy (widget);
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->button == 3)
|
||||
{
|
||||
/* Show a context menu on right click */
|
||||
GtkWidget* menu = midori_view_get_tab_menu (MIDORI_VIEW (widget));
|
||||
|
||||
katze_widget_popup (widget, GTK_MENU (menu),
|
||||
event, SOKOKE_MENU_POSITION_CURSOR);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -2533,6 +2651,23 @@ midori_view_tab_label_parent_set (GtkWidget* tab_label,
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static gboolean
|
||||
midori_view_tab_label_query_tooltip_cb (GtkWidget* tab_label,
|
||||
gint x,
|
||||
gint y,
|
||||
gboolean keyboard,
|
||||
GtkTooltip* tooltip,
|
||||
MidoriView* view)
|
||||
{
|
||||
if (view->speed_dial_in_new_tabs)
|
||||
gtk_tooltip_set_icon (tooltip, midori_view_get_snapshot (view, -160, -107));
|
||||
else
|
||||
gtk_tooltip_set_text (tooltip, midori_view_get_display_title (view));
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* midori_view_get_proxy_tab_label:
|
||||
* @view: a #MidoriView
|
||||
|
@ -2609,6 +2744,11 @@ midori_view_get_proxy_tab_label (MidoriView* view)
|
|||
G_CALLBACK (midori_view_tab_close_clicked), view);
|
||||
|
||||
view->tab_label = event_box;
|
||||
#if 0
|
||||
gtk_widget_set_has_tooltip (view->tab_label, TRUE);
|
||||
g_signal_connect (view->tab_label, "query-tooltip",
|
||||
G_CALLBACK (midori_view_tab_label_query_tooltip_cb), view);
|
||||
#endif
|
||||
g_signal_connect (view->tab_icon, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed),
|
||||
&view->tab_icon);
|
||||
|
@ -2768,6 +2908,8 @@ midori_view_reload (MidoriView* view,
|
|||
#endif
|
||||
if (view->title && strstr (title, view->title))
|
||||
webkit_web_view_open (WEBKIT_WEB_VIEW (view->web_view), view->uri);
|
||||
else if (midori_view_is_blank (view))
|
||||
midori_view_set_uri (view, view->uri);
|
||||
else if (from_cache)
|
||||
webkit_web_view_reload (WEBKIT_WEB_VIEW (view->web_view));
|
||||
else
|
||||
|
@ -2978,10 +3120,12 @@ midori_view_execute_script (MidoriView* view,
|
|||
/* For now this is private API */
|
||||
GdkPixbuf*
|
||||
midori_view_get_snapshot (MidoriView* view,
|
||||
guint width,
|
||||
guint height)
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
GtkWidget* web_view;
|
||||
gboolean fast;
|
||||
gint x, y, w, h;
|
||||
GdkRectangle rect;
|
||||
GdkPixmap* pixmap;
|
||||
GdkEvent event;
|
||||
|
@ -2993,13 +3137,30 @@ midori_view_get_snapshot (MidoriView* view,
|
|||
web_view = gtk_bin_get_child (GTK_BIN (view));
|
||||
g_return_val_if_fail (web_view->window, NULL);
|
||||
|
||||
rect.x = web_view->allocation.x;
|
||||
rect.y = web_view->allocation.y;
|
||||
rect.width = web_view->allocation.width;
|
||||
rect.height = web_view->allocation.height;
|
||||
x = web_view->allocation.x;
|
||||
y = web_view->allocation.y;
|
||||
w = web_view->allocation.width;
|
||||
h = web_view->allocation.height;
|
||||
|
||||
pixmap = gdk_pixmap_new (web_view->window,
|
||||
web_view->allocation.width, web_view->allocation.height,
|
||||
/* If width and height are both negative, we try to render faster at
|
||||
the cost of correctness or beauty. Only a part of the page is
|
||||
rendered which makes it a lot faster and scaling isn't as nice. */
|
||||
fast = FALSE;
|
||||
if (width < 0 && height < 0)
|
||||
{
|
||||
width *= -1;
|
||||
height *= -1;
|
||||
w = w > 320 ? 320 : w;
|
||||
h = h > 240 ? 240 : h;
|
||||
fast = TRUE;
|
||||
}
|
||||
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
rect.width = w;
|
||||
rect.height = h;
|
||||
|
||||
pixmap = gdk_pixmap_new (web_view->window, w, h,
|
||||
gdk_drawable_get_depth (web_view->window));
|
||||
event.expose.type = GDK_EXPOSE;
|
||||
event.expose.window = pixmap;
|
||||
|
@ -3025,8 +3186,9 @@ midori_view_get_snapshot (MidoriView* view,
|
|||
width = rect.width;
|
||||
if (!height)
|
||||
height = rect.height;
|
||||
|
||||
scaled = gdk_pixbuf_scale_simple (pixbuf, width, height,
|
||||
GDK_INTERP_TILES);
|
||||
fast ? GDK_INTERP_NEAREST : GDK_INTERP_TILES);
|
||||
g_object_unref (pixbuf);
|
||||
return scaled;
|
||||
}
|
||||
|
|
|
@ -113,6 +113,9 @@ midori_view_can_paste_clipboard (MidoriView* view);
|
|||
GtkWidget*
|
||||
midori_view_get_proxy_menu_item (MidoriView* view);
|
||||
|
||||
GtkWidget*
|
||||
midori_view_get_tab_menu (MidoriView* view);
|
||||
|
||||
GtkWidget*
|
||||
midori_view_get_proxy_tab_label (MidoriView* view);
|
||||
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined (G_OS_UNIX)
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
struct _MidoriWebSettings
|
||||
{
|
||||
WebKitWebSettings parent_instance;
|
||||
|
@ -513,7 +517,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
|
|||
"toolbar-items",
|
||||
_("Toolbar Items"),
|
||||
_("The items to show on the toolbar"),
|
||||
"Back,Forward,ReloadStop,Location,Panel,Trash,Search",
|
||||
"Back,Forward,ReloadStop,Location,Panel,Search,Trash",
|
||||
flags));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
|
@ -592,11 +596,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
|
|||
_("Show speed dial in new tabs"),
|
||||
_("Show speed dial in newly opened tabs"),
|
||||
TRUE,
|
||||
#if GTK_CHECK_VERSION (2, 14, 0)
|
||||
flags));
|
||||
#else
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
#endif
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DOWNLOAD_FOLDER,
|
||||
|
@ -741,11 +741,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
|
|||
_("Where to open externally opened pages"),
|
||||
MIDORI_TYPE_NEW_PAGE,
|
||||
MIDORI_NEW_PAGE_TAB,
|
||||
#if HAVE_UNIQUE
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
#else
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
#endif
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_MIDDLE_CLICK_OPENS_SELECTION,
|
||||
|
@ -1033,6 +1029,24 @@ midori_web_settings_finalize (GObject* object)
|
|||
G_OBJECT_CLASS (midori_web_settings_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
#if defined (G_OS_UNIX)
|
||||
static gchar*
|
||||
get_sys_name (void)
|
||||
{
|
||||
static gchar* sys_name = NULL;
|
||||
|
||||
if (!sys_name)
|
||||
{
|
||||
struct utsname name;
|
||||
if (uname (&name) != -1)
|
||||
sys_name = g_strdup_printf ("%s %s", name.sysname, name.machine);
|
||||
else
|
||||
sys_name = "Unix";
|
||||
}
|
||||
return sys_name;
|
||||
}
|
||||
#endif
|
||||
|
||||
static gchar*
|
||||
generate_ident_string (MidoriIdentity identify_as)
|
||||
{
|
||||
|
@ -1057,12 +1071,7 @@ generate_ident_string (MidoriIdentity identify_as)
|
|||
"PPC Mac OS X";
|
||||
#endif */
|
||||
#elif defined (G_OS_UNIX)
|
||||
/* struct utsname name;
|
||||
if (uname (&name) != -1)
|
||||
String::format ("%s %s", name.sysname, name.machine);
|
||||
else
|
||||
"Unknown";*/
|
||||
"Linux";
|
||||
get_sys_name ();
|
||||
#elif defined (G_OS_WIN32)
|
||||
// FIXME: Windows NT version
|
||||
"Windows";
|
||||
|
@ -1296,6 +1305,7 @@ midori_web_settings_set_property (GObject* object,
|
|||
}
|
||||
break;
|
||||
case PROP_IDENT_STRING:
|
||||
if (web_settings->identify_as == MIDORI_IDENT_CUSTOM)
|
||||
katze_assign (web_settings->ident_string, g_value_dup_string (value));
|
||||
break;
|
||||
case PROP_CACHE_SIZE:
|
||||
|
|
1766
midori/socket.c
Normal file
1766
midori/socket.c
Normal file
File diff suppressed because it is too large
Load diff
128
midori/socket.h
Normal file
128
midori/socket.h
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
Copyright 1999-2008 Hiroyuki Yamamoto
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#ifndef __SYLPH_SOCKET_H__
|
||||
#define __SYLPH_SOCKET_H__
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#if HAVE_NETDB_H
|
||||
# include <netdb.h>
|
||||
#endif
|
||||
|
||||
typedef struct _SockInfo SockInfo;
|
||||
|
||||
#if USE_SSL
|
||||
# include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CONN_READY,
|
||||
CONN_LOOKUPSUCCESS,
|
||||
CONN_ESTABLISHED,
|
||||
CONN_LOOKUPFAILED,
|
||||
CONN_FAILED
|
||||
} ConnectionState;
|
||||
|
||||
typedef gint (*SockConnectFunc) (SockInfo *sock,
|
||||
gpointer data);
|
||||
typedef gboolean (*SockFunc) (SockInfo *sock,
|
||||
GIOCondition condition,
|
||||
gpointer data);
|
||||
|
||||
struct _SockInfo
|
||||
{
|
||||
gint sock;
|
||||
#if USE_SSL
|
||||
SSL *ssl;
|
||||
#else
|
||||
gpointer ssl;
|
||||
#endif
|
||||
GIOChannel *sock_ch;
|
||||
|
||||
gchar *hostname;
|
||||
gushort port;
|
||||
ConnectionState state;
|
||||
gboolean nonblock;
|
||||
gpointer data;
|
||||
|
||||
SockFunc callback;
|
||||
GIOCondition condition;
|
||||
};
|
||||
|
||||
void send_open_command (gint sock, const gchar *command,
|
||||
gchar **args);
|
||||
gint socket_init (const gchar *instance_name,
|
||||
const gchar *config_dir, gboolean *exists);
|
||||
|
||||
gint sock_cleanup (void);
|
||||
|
||||
gint sock_set_io_timeout (guint sec);
|
||||
|
||||
gint sock_set_nonblocking_mode (SockInfo *sock, gboolean nonblock);
|
||||
gboolean sock_is_nonblocking_mode (SockInfo *sock);
|
||||
|
||||
gboolean sock_has_read_data (SockInfo *sock);
|
||||
|
||||
guint sock_add_watch (SockInfo *sock, GIOCondition condition,
|
||||
SockFunc func, gpointer data);
|
||||
|
||||
struct hostent *my_gethostbyname (const gchar *hostname);
|
||||
|
||||
SockInfo *sock_connect (const gchar *hostname, gushort port);
|
||||
#ifdef G_OS_UNIX
|
||||
gint sock_connect_async (const gchar *hostname, gushort port,
|
||||
SockConnectFunc func, gpointer data);
|
||||
gint sock_connect_async_cancel (gint id);
|
||||
#endif
|
||||
|
||||
/* Basic I/O functions */
|
||||
gint sock_printf (SockInfo *sock, const gchar *format, ...)
|
||||
G_GNUC_PRINTF(2, 3);
|
||||
gint sock_read (SockInfo *sock, gchar *buf, gint len);
|
||||
gint sock_write (SockInfo *sock, const gchar *buf, gint len);
|
||||
gint sock_write_all (SockInfo *sock, const gchar *buf, gint len);
|
||||
gint sock_gets (SockInfo *sock, gchar *buf, gint len);
|
||||
gint sock_getline (SockInfo *sock, gchar **line);
|
||||
gint sock_puts (SockInfo *sock, const gchar *buf);
|
||||
gint sock_peek (SockInfo *sock, gchar *buf, gint len);
|
||||
gint sock_close (SockInfo *sock);
|
||||
|
||||
/* Functions to directly work on FD. They are needed for pipes */
|
||||
gint fd_connect_inet (gushort port);
|
||||
gint fd_open_inet (gushort port);
|
||||
gint fd_connect_unix (const gchar *path);
|
||||
gint fd_open_unix (const gchar *path);
|
||||
gint fd_accept (gint sock);
|
||||
|
||||
gint fd_read (gint sock, gchar *buf, gint len);
|
||||
gint fd_write (gint sock, const gchar *buf, gint len);
|
||||
gint fd_write_all (gint sock, const gchar *buf, gint len);
|
||||
gint fd_gets (gint sock, gchar *buf, gint len);
|
||||
gint fd_getline (gint sock, gchar **line);
|
||||
gint fd_close (gint sock);
|
||||
|
||||
/* Functions for SSL */
|
||||
#if USE_SSL
|
||||
gint ssl_read (SSL *ssl, gchar *buf, gint len);
|
||||
gint ssl_write (SSL *ssl, const gchar *buf, gint len);
|
||||
gint ssl_write_all (SSL *ssl, const gchar *buf, gint len);
|
||||
gint ssl_gets (SSL *ssl, gchar *buf, gint len);
|
||||
gint ssl_getline (SSL *ssl, gchar **line);
|
||||
gint ssl_peek (SSL *ssl, gchar *buf, gint len);
|
||||
void ssl_done_socket (SockInfo *sockinfo);
|
||||
#endif
|
||||
|
||||
#endif /* __SYLPH_SOCKET_H__ */
|
|
@ -36,6 +36,7 @@
|
|||
#include <idna.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_JSCORE
|
||||
static gchar*
|
||||
sokoke_js_string_utf8 (JSStringRef js_string)
|
||||
{
|
||||
|
@ -49,18 +50,22 @@ sokoke_js_string_utf8 (JSStringRef js_string)
|
|||
JSStringGetUTF8CString (js_string, string_utf8, size_utf8);
|
||||
return string_utf8;
|
||||
}
|
||||
#endif
|
||||
|
||||
gchar*
|
||||
sokoke_js_script_eval (JSContextRef js_context,
|
||||
const gchar* script,
|
||||
gchar** exception)
|
||||
{
|
||||
#ifdef HAVE_JSCORE
|
||||
gchar* value;
|
||||
JSStringRef js_value_string;
|
||||
#endif
|
||||
|
||||
g_return_val_if_fail (js_context, FALSE);
|
||||
g_return_val_if_fail (script, FALSE);
|
||||
|
||||
#ifdef HAVE_JSCORE
|
||||
JSStringRef js_script = JSStringCreateWithUTF8CString (script);
|
||||
JSValueRef js_exception = NULL;
|
||||
JSValueRef js_value = JSEvaluateScript (js_context, js_script,
|
||||
|
@ -79,6 +84,9 @@ sokoke_js_script_eval (JSContextRef js_context,
|
|||
value = sokoke_js_string_utf8 (js_value_string);
|
||||
JSStringRelease (js_value_string);
|
||||
return value;
|
||||
#else
|
||||
return g_strdup ("");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -92,8 +100,6 @@ error_dialog (const gchar* short_message,
|
|||
gtk_widget_show (dialog);
|
||||
g_signal_connect_swapped (dialog, "response",
|
||||
G_CALLBACK (gtk_widget_destroy), dialog);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -355,11 +361,11 @@ sokoke_magic_uri (const gchar* uri,
|
|||
search_uri = NULL;
|
||||
/* Do we have a keyword and a string? */
|
||||
parts = g_strsplit (uri, " ", 2);
|
||||
if (parts[0] && parts[1])
|
||||
if (parts[0])
|
||||
if ((item = katze_array_find_token (search_engines, parts[0])))
|
||||
{
|
||||
search_uri = katze_item_get_uri (item);
|
||||
search = sokoke_search_uri (search_uri, parts[1]);
|
||||
search = sokoke_search_uri (search_uri, parts[1] ? parts[1] : "");
|
||||
}
|
||||
g_strfreev (parts);
|
||||
return search;
|
||||
|
@ -511,12 +517,16 @@ sokoke_hig_frame_new (const gchar* title)
|
|||
{
|
||||
/* Create a frame with no actual frame but a bold label and indentation */
|
||||
GtkWidget* frame = gtk_frame_new (NULL);
|
||||
#ifdef G_OS_WIN32
|
||||
gtk_frame_set_label (GTK_FRAME (frame), title);
|
||||
#else
|
||||
gchar* title_bold = g_strdup_printf ("<b>%s</b>", title);
|
||||
GtkWidget* label = gtk_label_new (NULL);
|
||||
gtk_label_set_markup (GTK_LABEL (label), title_bold);
|
||||
g_free (title_bold);
|
||||
gtk_frame_set_label_widget (GTK_FRAME (frame), label);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
|
||||
#endif
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
@ -735,6 +745,9 @@ sokoke_action_create_popup_menu_item (GtkAction* action)
|
|||
|
||||
g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
|
||||
|
||||
if (KATZE_IS_ARRAY_ACTION (action))
|
||||
return gtk_action_create_menu_item (action);
|
||||
|
||||
g_object_get (action,
|
||||
"label", &label,
|
||||
"stock-id", &stock_id,
|
||||
|
@ -747,6 +760,9 @@ sokoke_action_create_popup_menu_item (GtkAction* action)
|
|||
menuitem = gtk_check_menu_item_new_with_mnemonic (label);
|
||||
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
|
||||
gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
|
||||
if (GTK_IS_RADIO_ACTION (action))
|
||||
gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (menuitem),
|
||||
TRUE);
|
||||
}
|
||||
else if (stock_id)
|
||||
{
|
||||
|
@ -839,6 +855,7 @@ sokoke_register_stock_items (void)
|
|||
{
|
||||
{ STOCK_EXTENSION, NULL, 0, 0, GTK_STOCK_CONVERT },
|
||||
{ STOCK_IMAGE, NULL, 0, 0, GTK_STOCK_ORIENTATION_PORTRAIT },
|
||||
{ STOCK_WEB_BROWSER, NULL, 0, 0, "gnome-web-browser" },
|
||||
{ STOCK_NEWS_FEED, NULL, 0, 0, GTK_STOCK_INDEX },
|
||||
{ STOCK_SCRIPT, NULL, 0, 0, GTK_STOCK_EXECUTE },
|
||||
{ STOCK_STYLE, NULL, 0, 0, GTK_STOCK_SELECT_COLOR },
|
||||
|
@ -846,7 +863,7 @@ sokoke_register_stock_items (void)
|
|||
|
||||
{ STOCK_BOOKMARK, N_("_Bookmark"), 0, 0, GTK_STOCK_FILE },
|
||||
{ STOCK_BOOKMARKS, N_("_Bookmarks"), 0, 0, GTK_STOCK_DIRECTORY },
|
||||
{ STOCK_BOOKMARK_ADD, N_("_Add Bookmark"), 0, 0, GTK_STOCK_ADD },
|
||||
{ STOCK_BOOKMARK_ADD, N_("Add Boo_kmark"), 0, 0, GTK_STOCK_ADD },
|
||||
{ STOCK_CONSOLE, N_("_Console"), 0, 0, GTK_STOCK_DIALOG_WARNING },
|
||||
{ STOCK_EXTENSIONS, N_("_Extensions"), 0, 0, GTK_STOCK_CONVERT },
|
||||
{ STOCK_HISTORY, N_("_History"), 0, 0, GTK_STOCK_SORT_ASCENDING },
|
||||
|
@ -948,6 +965,32 @@ sokoke_remove_path (const gchar* path,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* sokoke_find_data_filename:
|
||||
* @filename: a filename or relative path
|
||||
*
|
||||
* Looks for the specified filename in the system data
|
||||
* directories, depending on the platform.
|
||||
*
|
||||
* Return value: a full path
|
||||
**/
|
||||
gchar*
|
||||
sokoke_find_data_filename (const gchar* filename)
|
||||
{
|
||||
const gchar* const* data_dirs = g_get_system_data_dirs ();
|
||||
guint i = 0;
|
||||
const gchar* data_dir;
|
||||
|
||||
while ((data_dir = data_dirs[i++]))
|
||||
{
|
||||
gchar* path = g_build_filename (data_dir, filename, NULL);
|
||||
if (g_file_test (path, G_FILE_TEST_EXISTS))
|
||||
return path;
|
||||
g_free (path);
|
||||
}
|
||||
return g_build_filename (MDATADIR, filename, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
res_server_handler_cb (SoupServer* res_server,
|
||||
SoupMessage* msg,
|
||||
|
@ -958,13 +1001,15 @@ res_server_handler_cb (SoupServer* res_server,
|
|||
{
|
||||
if (g_str_has_prefix (path, "/res"))
|
||||
{
|
||||
gchar* filename = g_strconcat (DATADIR "/midori", path, NULL);
|
||||
gchar* filename = g_build_filename ("midori", path, NULL);
|
||||
gchar* filepath = sokoke_find_data_filename (filename);
|
||||
gchar* contents;
|
||||
gsize length;
|
||||
|
||||
if (g_file_get_contents (filename, &contents, &length, NULL))
|
||||
g_free (filename);
|
||||
if (g_file_get_contents (filepath, &contents, &length, NULL))
|
||||
{
|
||||
gchar* content_type = g_content_type_guess (filename, (guchar*)contents,
|
||||
gchar* content_type = g_content_type_guess (filepath, (guchar*)contents,
|
||||
length, NULL);
|
||||
gchar* mime_type = g_content_type_get_mime_type (content_type);
|
||||
g_free (content_type);
|
||||
|
@ -975,7 +1020,7 @@ res_server_handler_cb (SoupServer* res_server,
|
|||
}
|
||||
else
|
||||
soup_message_set_status (msg, 404);
|
||||
g_free (filename);
|
||||
g_free (filepath);
|
||||
}
|
||||
else if (g_str_has_prefix (path, "/stock/"))
|
||||
{
|
||||
|
|
|
@ -151,6 +151,9 @@ gboolean
|
|||
sokoke_remove_path (const gchar* path,
|
||||
gboolean ignore_errors);
|
||||
|
||||
gchar*
|
||||
sokoke_find_data_filename (const gchar* filename);
|
||||
|
||||
SoupServer*
|
||||
sokoke_get_res_server (void);
|
||||
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
import platform
|
||||
|
||||
obj = bld.new_task_gen ('cc', 'staticlib')
|
||||
obj.name = 'midori'
|
||||
obj.name = 'midori-core'
|
||||
obj.target = 'midori'
|
||||
obj.includes = '. ..'
|
||||
obj.find_sources_in_dirs ('.', excludes=['main.c'])
|
||||
obj.add_marshal_file ('marshal.list', 'midori_cclosure_marshal')
|
||||
obj.uselib = 'UNIQUE LIBSOUP LIBIDN GIO GTK SQLITE WEBKIT LIBXML HILDON'
|
||||
obj.uselib = 'UNIQUE LIBSOUP LIBIDN GIO GTK SQLITE WEBKIT LIBXML WS2_32 OPENSSL HILDON'
|
||||
obj.uselib_local = 'katze'
|
||||
obj.install_path = None
|
||||
|
||||
|
@ -20,12 +20,14 @@ obj.target = 'panels'
|
|||
obj.includes = '. ..'
|
||||
obj.find_sources_in_dirs ('../panels')
|
||||
obj.uselib = 'UNIQUE LIBSOUP GMODULE GTHREAD GIO GTK SQLITE WEBKIT LIBXML'
|
||||
obj.uselib_local = 'midori'
|
||||
obj.uselib_local = 'midori-core'
|
||||
obj.install_path = None
|
||||
|
||||
obj = bld.new_task_gen ('cc', 'program')
|
||||
obj.target = 'midori'
|
||||
obj.includes = '. .. ../panels'
|
||||
obj.source = 'main.c'
|
||||
if bld.env['WINRC']:
|
||||
obj.source += ' ../data/midori.rc'
|
||||
obj.uselib = 'UNIQUE LIBSOUP GMODULE GTHREAD GIO GTK SQLITE WEBKIT LIBXML'
|
||||
obj.uselib_local = 'panels'
|
||||
|
|
|
@ -306,49 +306,6 @@ _addons_get_files (MidoriAddons* addons)
|
|||
return files;
|
||||
}
|
||||
|
||||
static GtkTreePath*
|
||||
_treeview_first_selected_path (GtkTreeView *treeview)
|
||||
{
|
||||
GtkTreeSelection* selection;
|
||||
GList* tree_paths;
|
||||
|
||||
selection = gtk_tree_view_get_selection (treeview);
|
||||
if (!selection)
|
||||
return NULL;
|
||||
|
||||
if (gtk_tree_selection_get_selected (selection, NULL, NULL))
|
||||
{
|
||||
GtkTreePath* result;
|
||||
tree_paths = gtk_tree_selection_get_selected_rows (selection, NULL);
|
||||
result = gtk_tree_path_copy (g_list_nth_data (tree_paths, 0));
|
||||
g_list_foreach (tree_paths, (GFunc)gtk_tree_path_free, NULL);
|
||||
g_list_free (tree_paths);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_addons_toggle_enable_button (MidoriAddons* addons,
|
||||
gboolean sensitive)
|
||||
{
|
||||
GtkToolItem* button;
|
||||
|
||||
button = gtk_toolbar_get_nth_item (GTK_TOOLBAR (addons->toolbar), 1);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (button), sensitive);
|
||||
}
|
||||
|
||||
static void
|
||||
_addons_toggle_disable_button (MidoriAddons* addons,
|
||||
gboolean sensitive)
|
||||
{
|
||||
GtkToolItem* button;
|
||||
|
||||
button = gtk_toolbar_get_nth_item (GTK_TOOLBAR (addons->toolbar), 2);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (button), sensitive);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_addons_directory_monitor_changed (GFileMonitor* monitor,
|
||||
GFile* child,
|
||||
|
@ -359,67 +316,6 @@ midori_addons_directory_monitor_changed (GFileMonitor* monitor,
|
|||
midori_addons_update_elements (addons);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_addons_treeview_cursor_changed (GtkTreeView* treeview,
|
||||
MidoriAddons* addons)
|
||||
{
|
||||
struct AddonElement* element;
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
GtkTreePath *path;
|
||||
|
||||
path = _treeview_first_selected_path (treeview);
|
||||
|
||||
model = gtk_tree_view_get_model (treeview);
|
||||
if (path && gtk_tree_model_get_iter (model, &iter, path))
|
||||
{
|
||||
gtk_tree_model_get (model, &iter, 0, &element, -1);
|
||||
if (element->broken)
|
||||
{
|
||||
_addons_toggle_enable_button (addons, FALSE);
|
||||
_addons_toggle_disable_button (addons, FALSE);
|
||||
} else
|
||||
{
|
||||
_addons_toggle_enable_button (addons, !element->enabled);
|
||||
_addons_toggle_disable_button (addons, element->enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
midori_addons_button_status_clicked_cb (GtkToolItem* toolitem,
|
||||
MidoriAddons* addons)
|
||||
{
|
||||
GtkTreeView* treeview;
|
||||
struct AddonElement* element;
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
GtkTreePath* path;
|
||||
|
||||
treeview = GTK_TREE_VIEW (addons->treeview);
|
||||
|
||||
path = _treeview_first_selected_path (treeview);
|
||||
model = gtk_tree_view_get_model (treeview);
|
||||
if (gtk_tree_model_get_iter (model, &iter, path))
|
||||
{
|
||||
gtk_tree_model_get (model, &iter, 0, &element, -1);
|
||||
if (toolitem == gtk_toolbar_get_nth_item (
|
||||
GTK_TOOLBAR (addons->toolbar), 2)) /* disable button */
|
||||
element->enabled = FALSE;
|
||||
else if (toolitem == gtk_toolbar_get_nth_item (
|
||||
GTK_TOOLBAR (addons->toolbar), 1)) /* enable button */
|
||||
element->enabled = TRUE;
|
||||
|
||||
_addons_toggle_enable_button (addons, !element->enabled);
|
||||
_addons_toggle_disable_button (addons, element->enabled);
|
||||
|
||||
/* After enabling or disabling an element, the tree view
|
||||
is not updated automatically; we need to notify tree model
|
||||
in order to take the modification into account */
|
||||
gtk_tree_model_row_changed (model, path, &iter);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
midori_addons_button_add_clicked_cb (GtkToolItem* toolitem,
|
||||
MidoriAddons* addons)
|
||||
|
@ -435,7 +331,7 @@ midori_addons_button_add_clicked_cb (GtkToolItem* toolitem,
|
|||
}
|
||||
|
||||
static void
|
||||
midori_addons_treeview_render_icon_cb (GtkTreeViewColumn* column,
|
||||
midori_addons_treeview_render_tick_cb (GtkTreeViewColumn* column,
|
||||
GtkCellRenderer* renderer,
|
||||
GtkTreeModel* model,
|
||||
GtkTreeIter* iter,
|
||||
|
@ -445,10 +341,10 @@ midori_addons_treeview_render_icon_cb (GtkTreeViewColumn* column,
|
|||
|
||||
gtk_tree_model_get (model, iter, 0, &element, -1);
|
||||
|
||||
if (element->broken)
|
||||
g_object_set (renderer, "stock-id", GTK_STOCK_STOP, NULL);
|
||||
else
|
||||
g_object_set (renderer, "stock-id", GTK_STOCK_FILE, NULL);
|
||||
g_object_set (renderer,
|
||||
"active", element->enabled,
|
||||
"sensitive", !element->broken,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -475,14 +371,48 @@ midori_addons_treeview_row_activated_cb (GtkTreeView* treeview,
|
|||
GtkTreeViewColumn* column,
|
||||
MidoriAddons* addons)
|
||||
{
|
||||
/*GtkTreeModel* model = gtk_tree_view_get_model (treeview);
|
||||
GtkTreeModel* model = gtk_tree_view_get_model (treeview);
|
||||
GtkTreeIter iter;
|
||||
if (gtk_tree_model_get_iter (model, &iter, path))
|
||||
{
|
||||
gchar* b;
|
||||
gtk_tree_model_get (model, &iter, 2, &b, -1);
|
||||
g_free (b);
|
||||
}*/
|
||||
struct AddonElement *element;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &element, -1);
|
||||
|
||||
element->enabled = !element->enabled;
|
||||
|
||||
/* After enabling or disabling an element, the tree view
|
||||
is not updated automatically; we need to notify tree model
|
||||
in order to take the modification into account */
|
||||
gtk_tree_model_row_changed (model, path, &iter);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
midori_addons_cell_renderer_toggled_cb (GtkCellRendererToggle* renderer,
|
||||
const gchar* path,
|
||||
MidoriAddons* addons)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (addons->treeview));
|
||||
if (gtk_tree_model_get_iter_from_string (model, &iter, path))
|
||||
{
|
||||
struct AddonElement *element;
|
||||
GtkTreePath* tree_path;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &element, -1);
|
||||
|
||||
element->enabled = !element->enabled;
|
||||
|
||||
/* After enabling or disabling an element, the tree view
|
||||
is not updated automatically; we need to notify tree model
|
||||
in order to take the modification into account */
|
||||
tree_path = gtk_tree_path_new_from_string (path);
|
||||
gtk_tree_model_row_changed (model, tree_path, &iter);
|
||||
gtk_tree_path_free (tree_path);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -490,7 +420,7 @@ midori_addons_init (MidoriAddons* addons)
|
|||
{
|
||||
GtkTreeViewColumn* column;
|
||||
GtkCellRenderer* renderer_text;
|
||||
GtkCellRenderer* renderer_pixbuf;
|
||||
GtkCellRenderer* renderer_toggle;
|
||||
|
||||
addons->web_widget = NULL;
|
||||
addons->elements = NULL;
|
||||
|
@ -498,11 +428,15 @@ midori_addons_init (MidoriAddons* addons)
|
|||
addons->treeview = gtk_tree_view_new ();
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (addons->treeview), FALSE);
|
||||
column = gtk_tree_view_column_new ();
|
||||
renderer_pixbuf = gtk_cell_renderer_pixbuf_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE);
|
||||
gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf,
|
||||
(GtkTreeCellDataFunc)midori_addons_treeview_render_icon_cb,
|
||||
renderer_toggle = gtk_cell_renderer_toggle_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer_toggle, FALSE);
|
||||
gtk_tree_view_column_set_cell_data_func (column, renderer_toggle,
|
||||
(GtkTreeCellDataFunc)midori_addons_treeview_render_tick_cb,
|
||||
addons->treeview, NULL);
|
||||
g_signal_connect (renderer_toggle, "toggled",
|
||||
G_CALLBACK (midori_addons_cell_renderer_toggled_cb), addons);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (addons->treeview), column);
|
||||
column = gtk_tree_view_column_new ();
|
||||
renderer_text = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
|
||||
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
|
||||
|
@ -1026,26 +960,6 @@ midori_addons_get_toolbar (MidoriViewable* addons)
|
|||
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||
|
||||
/* enable button */
|
||||
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_YES);
|
||||
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), _("_Enable"));
|
||||
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), _("Enable"));
|
||||
g_signal_connect (toolitem, "clicked",
|
||||
G_CALLBACK (midori_addons_button_status_clicked_cb), addons);
|
||||
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (toolitem), FALSE);
|
||||
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||
|
||||
/* disable button */
|
||||
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_NO);
|
||||
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), _("_Disable"));
|
||||
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), _("Disable"));
|
||||
g_signal_connect (toolitem, "clicked",
|
||||
G_CALLBACK (midori_addons_button_status_clicked_cb), addons);
|
||||
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (toolitem), FALSE);
|
||||
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||
|
||||
/* separator */
|
||||
toolitem = gtk_separator_tool_item_new ();
|
||||
gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (toolitem),
|
||||
|
@ -1063,10 +977,6 @@ midori_addons_get_toolbar (MidoriViewable* addons)
|
|||
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||
MIDORI_ADDONS (addons)->toolbar = toolbar;
|
||||
|
||||
g_signal_connect (MIDORI_ADDONS (addons)->treeview, "cursor-changed",
|
||||
G_CALLBACK (midori_addons_treeview_cursor_changed),
|
||||
addons);
|
||||
|
||||
g_signal_connect (toolbar, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed),
|
||||
&MIDORI_ADDONS (addons)->toolbar);
|
||||
|
@ -1179,12 +1089,5 @@ midori_addons_update_elements (MidoriAddons* addons)
|
|||
gtk_tree_view_set_model (GTK_TREE_VIEW (addons->treeview),
|
||||
GTK_TREE_MODEL (liststore));
|
||||
|
||||
/* In case a row was selected, that selection will be cancelled
|
||||
when calling gtk_tree_view_set_model. So, we need to make sure
|
||||
that the buttons are insensitive. */
|
||||
if (addons->toolbar)
|
||||
{
|
||||
_addons_toggle_enable_button (addons, FALSE);
|
||||
_addons_toggle_disable_button (addons, FALSE);
|
||||
}
|
||||
gtk_widget_queue_draw (GTK_WIDGET (addons->treeview));
|
||||
}
|
||||
|
|
110
panels/midori-bookmark-store.c
Normal file
110
panels/midori-bookmark-store.c
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
Copyright (C) 2009 Christian Dywan <christian@twotoasts.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#include "midori-bookmark-store.h"
|
||||
|
||||
struct _MidoriBookmarkStore
|
||||
{
|
||||
GtkTreeStore parent_instance;
|
||||
};
|
||||
|
||||
struct _MidoriBookmarkStoreClass
|
||||
{
|
||||
GtkTreeStoreClass parent_class;
|
||||
};
|
||||
|
||||
static void
|
||||
midori_bookmark_store_drag_source_iface_init (GtkTreeDragSourceIface* iface);
|
||||
|
||||
static void
|
||||
midori_bookmark_store_drag_dest_iface_init (GtkTreeDragDestIface* iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (MidoriBookmarkStore, midori_bookmark_store, GTK_TYPE_TREE_STORE,
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
|
||||
midori_bookmark_store_drag_source_iface_init)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
|
||||
midori_bookmark_store_drag_dest_iface_init));
|
||||
|
||||
static void
|
||||
midori_bookmark_store_finalize (GObject* object);
|
||||
|
||||
static void
|
||||
midori_bookmark_store_class_init (MidoriBookmarkStoreClass* class)
|
||||
{
|
||||
GObjectClass* gobject_class;
|
||||
|
||||
gobject_class = G_OBJECT_CLASS (class);
|
||||
gobject_class->finalize = midori_bookmark_store_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
midori_bookmark_store_init (MidoriBookmarkStore* bookmark_store)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
static void
|
||||
midori_bookmark_store_finalize (GObject* object)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
static void
|
||||
midori_bookmark_store_drag_source_iface_init (GtkTreeDragSourceIface* iface)
|
||||
{
|
||||
/*iface->row_draggable = real_gtk_tree_store_row_draggable;
|
||||
iface->drag_data_delete = gtk_tree_store_drag_data_delete;
|
||||
iface->drag_data_get = gtk_tree_store_drag_data_get;*/
|
||||
}
|
||||
|
||||
static void
|
||||
midori_bookmark_store_drag_dest_iface_init (GtkTreeDragDestIface* iface)
|
||||
{
|
||||
/*iface->drag_data_received = gtk_tree_store_drag_data_received;
|
||||
iface->row_drop_possible = gtk_tree_store_row_drop_possible;*/
|
||||
}
|
||||
|
||||
/**
|
||||
* midori_bookmark_store_new:
|
||||
*
|
||||
* Creates a new empty bookmark_store.
|
||||
*
|
||||
* Return value: a new #MidoriBookmarkStore
|
||||
*
|
||||
* Since: 0.1.8
|
||||
**/
|
||||
GtkTreeStore*
|
||||
midori_bookmark_store_new (gint n_columns,
|
||||
...)
|
||||
{
|
||||
GtkTreeStore* treestore;
|
||||
va_list args;
|
||||
gint i;
|
||||
GType* types;
|
||||
|
||||
g_return_val_if_fail (n_columns > 0, NULL);
|
||||
|
||||
treestore = g_object_new (MIDORI_TYPE_BOOKMARK_STORE, NULL);
|
||||
|
||||
va_start (args, n_columns);
|
||||
|
||||
types = g_new (GType, n_columns);
|
||||
for (i = 0; i < n_columns; i++)
|
||||
{
|
||||
GType type = va_arg (args, GType);
|
||||
types[i] = type;
|
||||
}
|
||||
va_end (args);
|
||||
|
||||
gtk_tree_store_set_column_types (treestore, i, types);
|
||||
|
||||
return treestore;
|
||||
}
|
44
panels/midori-bookmark-store.h
Normal file
44
panels/midori-bookmark-store.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
Copyright (C) 2009 Christian Dywan <christian@twotoasts.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#ifndef __MIDORI_BOOKMARK_STORE_H__
|
||||
#define __MIDORI_BOOKMARK_STORE_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define MIDORI_TYPE_BOOKMARK_STORE \
|
||||
(midori_bookmark_store_get_type ())
|
||||
#define MIDORI_BOOKMARK_STORE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_BOOKMARK_STORE, MidoriBookmarkStore))
|
||||
#define MIDORI_BOOKMARK_STORE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_BOOKMARK_STORE, MidoriBookmarkStoreClass))
|
||||
#define MIDORI_IS_BOOKMARK_STORE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_BOOKMARK_STORE))
|
||||
#define MIDORI_IS_BOOKMARK_STORE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_BOOKMARK_STORE))
|
||||
#define MIDORI_BOOKMARK_STORE_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_BOOKMARK_STORE, MidoriBookmarkStoreClass))
|
||||
|
||||
typedef struct _MidoriBookmarkStore MidoriBookmarkStore;
|
||||
typedef struct _MidoriBookmarkStoreClass MidoriBookmarkStoreClass;
|
||||
|
||||
GType
|
||||
midori_bookmark_store_get_type (void);
|
||||
|
||||
GtkTreeStore*
|
||||
midori_bookmark_store_new (gint n_columns,
|
||||
...);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __MIDORI_BOOKMARK_STORE_H__ */
|
|
@ -16,6 +16,7 @@
|
|||
#include "midori-stock.h"
|
||||
#include "midori-view.h"
|
||||
#include "midori-viewable.h"
|
||||
#include "midori-bookmark-store.h"
|
||||
|
||||
#include "sokoke.h"
|
||||
|
||||
|
@ -725,8 +726,10 @@ midori_bookmarks_open_in_window_activate_cb (GtkWidget* menuitem,
|
|||
|
||||
if (uri && *uri)
|
||||
{
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks));
|
||||
g_signal_emit_by_name (browser, "new-window", uri);
|
||||
MidoriBrowser* new_browser = midori_app_create_browser (bookmarks->app);
|
||||
midori_app_add_browser (bookmarks->app, new_browser);
|
||||
gtk_widget_show (GTK_WIDGET (new_browser));
|
||||
midori_browser_add_uri (new_browser, uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -892,7 +895,7 @@ midori_bookmarks_init (MidoriBookmarks* bookmarks)
|
|||
bookmarks->net = katze_net_new ();
|
||||
|
||||
/* Create the treeview */
|
||||
model = gtk_tree_store_new (1, KATZE_TYPE_ITEM);
|
||||
model = midori_bookmark_store_new (1, KATZE_TYPE_ITEM);
|
||||
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
|
||||
column = gtk_tree_view_column_new ();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -59,6 +59,9 @@ midori_extensions_get_property (GObject* object,
|
|||
GValue* value,
|
||||
GParamSpec* pspec);
|
||||
|
||||
static void
|
||||
midori_extensions_finalize (GObject* object);
|
||||
|
||||
static void
|
||||
midori_extensions_class_init (MidoriExtensionsClass* class)
|
||||
{
|
||||
|
@ -68,6 +71,7 @@ midori_extensions_class_init (MidoriExtensionsClass* class)
|
|||
gobject_class = G_OBJECT_CLASS (class);
|
||||
gobject_class->set_property = midori_extensions_set_property;
|
||||
gobject_class->get_property = midori_extensions_get_property;
|
||||
gobject_class->finalize = midori_extensions_finalize;
|
||||
|
||||
flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
|
||||
|
||||
|
@ -93,37 +97,6 @@ midori_extensions_get_stock_id (MidoriViewable* viewable)
|
|||
return STOCK_EXTENSIONS;
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extensions_button_status_clicked_cb (GtkToolItem* toolitem,
|
||||
MidoriExtensions* extensions)
|
||||
{
|
||||
GtkTreeView* treeview;
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
MidoriExtension* extension;
|
||||
|
||||
treeview = GTK_TREE_VIEW (extensions->treeview);
|
||||
|
||||
if (katze_tree_view_get_selected_iter (treeview, &model, &iter))
|
||||
{
|
||||
GtkToolItem* button_enable = gtk_toolbar_get_nth_item (
|
||||
GTK_TOOLBAR (extensions->toolbar), 1);
|
||||
GtkToolItem* button_disable = gtk_toolbar_get_nth_item (
|
||||
GTK_TOOLBAR (extensions->toolbar), 2);
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &extension, -1);
|
||||
if (toolitem == button_enable)
|
||||
g_signal_emit_by_name (extension, "activate", extensions->app);
|
||||
else if (toolitem == button_disable)
|
||||
midori_extension_deactivate (extension);
|
||||
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (button_enable),
|
||||
!midori_extension_is_active (extension));
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (button_disable),
|
||||
midori_extension_is_active (extension));
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
midori_extensions_get_toolbar (MidoriViewable* extensions)
|
||||
{
|
||||
|
@ -139,26 +112,6 @@ midori_extensions_get_toolbar (MidoriViewable* extensions)
|
|||
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||
|
||||
/* enable button */
|
||||
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_YES);
|
||||
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), _("_Enable"));
|
||||
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), _("Enable"));
|
||||
g_signal_connect (toolitem, "clicked",
|
||||
G_CALLBACK (midori_extensions_button_status_clicked_cb), extensions);
|
||||
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (toolitem), FALSE);
|
||||
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||
|
||||
/* disable button */
|
||||
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_NO);
|
||||
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), _("_Disable"));
|
||||
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), _("Disable"));
|
||||
g_signal_connect (toolitem, "clicked",
|
||||
G_CALLBACK (midori_extensions_button_status_clicked_cb), extensions);
|
||||
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (toolitem), FALSE);
|
||||
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||
|
||||
MIDORI_EXTENSIONS (extensions)->toolbar = toolbar;
|
||||
}
|
||||
|
||||
|
@ -173,6 +126,21 @@ midori_extensions_viewable_iface_init (MidoriViewableIface* iface)
|
|||
iface->get_toolbar = midori_extensions_get_toolbar;
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extensions_extension_activate_cb (MidoriExtension* extension,
|
||||
MidoriApp* app,
|
||||
MidoriExtensions* extensions)
|
||||
{
|
||||
gtk_widget_queue_draw (GTK_WIDGET (extensions->treeview));
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extensions_extension_deactivate_cb (MidoriExtension* extension,
|
||||
MidoriExtensions* extensions)
|
||||
{
|
||||
gtk_widget_queue_draw (GTK_WIDGET (extensions->treeview));
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extensions_add_item_cb (KatzeArray* array,
|
||||
MidoriExtension* extension,
|
||||
|
@ -184,6 +152,10 @@ midori_extensions_add_item_cb (KatzeArray* array,
|
|||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (extensions->treeview));
|
||||
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
|
||||
gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, extension, -1);
|
||||
g_signal_connect (extension, "activate",
|
||||
G_CALLBACK (midori_extensions_extension_activate_cb), extensions);
|
||||
g_signal_connect (extension, "deactivate",
|
||||
G_CALLBACK (midori_extensions_extension_deactivate_cb), extensions);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -239,13 +211,19 @@ midori_extensions_get_property (GObject* object,
|
|||
}
|
||||
|
||||
static void
|
||||
midori_extensions_treeview_render_icon_cb (GtkTreeViewColumn* column,
|
||||
midori_extensions_treeview_render_tick_cb (GtkTreeViewColumn* column,
|
||||
GtkCellRenderer* renderer,
|
||||
GtkTreeModel* model,
|
||||
GtkTreeIter* iter,
|
||||
GtkWidget* treeview)
|
||||
{
|
||||
g_object_set (renderer, "stock-id", GTK_STOCK_EXECUTE, NULL);
|
||||
MidoriExtension* extension;
|
||||
|
||||
gtk_tree_model_get (model, iter, 0, &extension, -1);
|
||||
|
||||
g_object_set (renderer, "active", midori_extension_is_active (extension), NULL);
|
||||
|
||||
g_object_unref (extension);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -266,13 +244,13 @@ midori_extensions_treeview_render_text_cb (GtkTreeViewColumn* column,
|
|||
name = katze_object_get_string (extension, "name");
|
||||
version = katze_object_get_string (extension, "version");
|
||||
desc = katze_object_get_string (extension, "description");
|
||||
text = g_strdup_printf ("%s %s\n%s", name, version, desc);
|
||||
text = g_markup_printf_escaped ("<b>%s</b> %s\n%s", name, version, desc);
|
||||
g_free (name);
|
||||
g_free (version);
|
||||
g_free (desc);
|
||||
g_object_set (renderer, "text", text,
|
||||
"sensitive", midori_extension_is_active (extension),
|
||||
NULL);
|
||||
|
||||
g_object_set (renderer, "markup", text, NULL);
|
||||
|
||||
g_free (text);
|
||||
g_object_unref (extension);
|
||||
}
|
||||
|
@ -283,16 +261,10 @@ midori_extensions_treeview_row_activated_cb (GtkTreeView* treeview,
|
|||
GtkTreeViewColumn* column,
|
||||
MidoriExtensions* extensions)
|
||||
{
|
||||
GtkToolItem* button_enable;
|
||||
GtkToolItem* button_disable;
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
model = gtk_tree_view_get_model (treeview);
|
||||
button_enable = gtk_toolbar_get_nth_item (
|
||||
GTK_TOOLBAR (extensions->toolbar), 1);
|
||||
button_disable = gtk_toolbar_get_nth_item (
|
||||
GTK_TOOLBAR (extensions->toolbar), 2);
|
||||
if (gtk_tree_model_get_iter (model, &iter, path))
|
||||
{
|
||||
MidoriExtension* extension;
|
||||
|
@ -302,45 +274,198 @@ midori_extensions_treeview_row_activated_cb (GtkTreeView* treeview,
|
|||
midori_extension_deactivate (extension);
|
||||
else
|
||||
g_signal_emit_by_name (extension, "activate", extensions->app);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (button_enable),
|
||||
!midori_extension_is_active (extension));
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (button_disable),
|
||||
midori_extension_is_active (extension));
|
||||
/* FIXME: Update only the appropriate row */
|
||||
gtk_widget_queue_draw (GTK_WIDGET (treeview));
|
||||
|
||||
g_object_unref (extension);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extensions_treeview_cursor_changed_cb (GtkTreeView* treeview,
|
||||
midori_extensions_preferences_activate_cb (GtkWidget* menuitem,
|
||||
MidoriExtensions* extensions)
|
||||
{
|
||||
MidoriExtension* extension;
|
||||
|
||||
extension = g_object_get_data (G_OBJECT (menuitem), "MidoriExtension");
|
||||
g_return_if_fail (extension != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extensions_website_activate_cb (GtkWidget* menuitem,
|
||||
MidoriExtensions* extensions)
|
||||
{
|
||||
gchar* uri;
|
||||
gint n;
|
||||
MidoriBrowser* browser;
|
||||
|
||||
MidoriExtension* extension;
|
||||
|
||||
extension = g_object_get_data (G_OBJECT (menuitem), "MidoriExtension");
|
||||
g_return_if_fail (extension != NULL);
|
||||
uri = katze_object_get_string (extension, "website");
|
||||
|
||||
browser = midori_browser_get_for_widget (GTK_WIDGET (extensions));
|
||||
n = midori_browser_add_uri (browser, uri);
|
||||
midori_browser_set_current_page (browser, n);
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extensions_about_activate_cb (GtkWidget* menuitem,
|
||||
MidoriExtensions* extensions)
|
||||
{
|
||||
MidoriExtension* extension;
|
||||
|
||||
extension = g_object_get_data (G_OBJECT (menuitem), "MidoriExtension");
|
||||
g_return_if_fail (extension != NULL);
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
midori_extensions_popup_menu_item (GtkMenu* menu,
|
||||
const gchar* stock_id,
|
||||
const gchar* label,
|
||||
MidoriExtension* extension,
|
||||
gpointer callback,
|
||||
gboolean enabled,
|
||||
MidoriExtensions* extensions)
|
||||
{
|
||||
GtkWidget* menuitem;
|
||||
|
||||
menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL);
|
||||
if (label)
|
||||
gtk_label_set_text_with_mnemonic (GTK_LABEL (gtk_bin_get_child (
|
||||
GTK_BIN (menuitem))), label);
|
||||
|
||||
if (!enabled)
|
||||
gtk_widget_set_sensitive (menuitem, FALSE);
|
||||
|
||||
g_object_set_data (G_OBJECT (menuitem), "MidoriExtension", extension);
|
||||
|
||||
if (callback)
|
||||
g_signal_connect (menuitem, "activate", G_CALLBACK (callback), extensions);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
gtk_widget_show (menuitem);
|
||||
|
||||
return menuitem;
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extensions_popup (GtkWidget* widget,
|
||||
GdkEventButton* event,
|
||||
MidoriExtension* extension,
|
||||
MidoriExtensions* extensions)
|
||||
{
|
||||
GtkWidget* menu;
|
||||
gchar* website;
|
||||
|
||||
website = katze_object_get_string (extension, "website");
|
||||
|
||||
menu = gtk_menu_new ();
|
||||
midori_extensions_popup_menu_item (GTK_MENU (menu), GTK_STOCK_PREFERENCES, NULL, extension,
|
||||
midori_extensions_preferences_activate_cb, FALSE,
|
||||
extensions);
|
||||
midori_extensions_popup_menu_item (GTK_MENU (menu), GTK_STOCK_HOME, NULL, extension,
|
||||
midori_extensions_website_activate_cb, website != NULL,
|
||||
extensions);
|
||||
midori_extensions_popup_menu_item (GTK_MENU (menu), GTK_STOCK_ABOUT, NULL, extension,
|
||||
midori_extensions_about_activate_cb, FALSE,
|
||||
extensions);
|
||||
|
||||
sokoke_widget_popup (widget, GTK_MENU (menu),
|
||||
event, SOKOKE_MENU_POSITION_CURSOR);
|
||||
|
||||
g_free (website);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
midori_extensions_popup_menu_cb (GtkWidget* widget,
|
||||
MidoriExtensions* extensions)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreePath* path;
|
||||
GtkTreeIter iter;
|
||||
GtkToolItem* button_enable;
|
||||
GtkToolItem* button_disable;
|
||||
|
||||
gtk_tree_view_get_cursor (treeview, &path, NULL);
|
||||
model = gtk_tree_view_get_model (treeview);
|
||||
button_enable = gtk_toolbar_get_nth_item (
|
||||
GTK_TOOLBAR (extensions->toolbar), 1);
|
||||
button_disable = gtk_toolbar_get_nth_item (
|
||||
GTK_TOOLBAR (extensions->toolbar), 2);
|
||||
if (gtk_tree_model_get_iter (model, &iter, path))
|
||||
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter))
|
||||
{
|
||||
MidoriExtension* extension;
|
||||
MidoriExtension *extension;
|
||||
|
||||
if (katze_tree_view_get_selected_iter (treeview, &model, &iter))
|
||||
{
|
||||
gtk_tree_model_get (model, &iter, 0, &extension, -1);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (button_enable),
|
||||
!midori_extension_is_active (extension));
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (button_disable),
|
||||
midori_extension_is_active (extension));
|
||||
|
||||
midori_extensions_popup (widget, NULL, extension, extensions);
|
||||
g_object_unref (extension);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
midori_extensions_button_release_event_cb (GtkWidget* widget,
|
||||
GdkEventButton* event,
|
||||
MidoriExtensions* extensions)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (event->button != 3)
|
||||
return FALSE;
|
||||
|
||||
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter))
|
||||
{
|
||||
MidoriExtension *extension;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &extension, -1);
|
||||
|
||||
midori_extensions_popup (widget, event, extension, extensions);
|
||||
g_object_unref (extension);
|
||||
return TRUE;
|
||||
}
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extensions_cell_renderer_toggled_cb (GtkCellRendererToggle* renderer,
|
||||
const gchar* path,
|
||||
MidoriExtensions* extensions)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (extensions->treeview));
|
||||
if (gtk_tree_model_get_iter_from_string (model, &iter, path))
|
||||
{
|
||||
MidoriExtension *extension;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &extension, -1);
|
||||
if (midori_extension_is_active (extension))
|
||||
midori_extension_deactivate (extension);
|
||||
else
|
||||
g_signal_emit_by_name (extension, "activate", extensions->app);
|
||||
|
||||
g_object_unref (extension);
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
midori_extensions_tree_sort_func (GtkTreeModel* model,
|
||||
GtkTreeIter* a,
|
||||
GtkTreeIter* b,
|
||||
gpointer data)
|
||||
{
|
||||
MidoriExtension* e1, *e2;
|
||||
gchar* name1, *name2;
|
||||
gint result = 0;
|
||||
|
||||
gtk_tree_model_get (model, a, 0, &e1, -1);
|
||||
gtk_tree_model_get (model, b, 0, &e2, -1);
|
||||
|
||||
name1 = katze_object_get_string (e1, "name");
|
||||
name2 = katze_object_get_string (e2, "name");
|
||||
|
||||
result = g_strcmp0 (name1, name2);
|
||||
|
||||
g_free (name1);
|
||||
g_free (name2);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -349,16 +474,24 @@ midori_extensions_init (MidoriExtensions* extensions)
|
|||
/* Create the treeview */
|
||||
GtkTreeViewColumn* column;
|
||||
GtkCellRenderer* renderer_text;
|
||||
GtkCellRenderer* renderer_pixbuf;
|
||||
GtkCellRenderer* renderer_toggle;
|
||||
GtkListStore* liststore = gtk_list_store_new (1, G_TYPE_OBJECT);
|
||||
extensions->treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (liststore));
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (liststore),
|
||||
0, GTK_SORT_ASCENDING);
|
||||
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (liststore),
|
||||
0, midori_extensions_tree_sort_func, NULL, NULL);
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (extensions->treeview), FALSE);
|
||||
column = gtk_tree_view_column_new ();
|
||||
renderer_pixbuf = gtk_cell_renderer_pixbuf_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE);
|
||||
gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf,
|
||||
(GtkTreeCellDataFunc)midori_extensions_treeview_render_icon_cb,
|
||||
renderer_toggle = gtk_cell_renderer_toggle_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer_toggle, FALSE);
|
||||
gtk_tree_view_column_set_cell_data_func (column, renderer_toggle,
|
||||
(GtkTreeCellDataFunc)midori_extensions_treeview_render_tick_cb,
|
||||
extensions->treeview, NULL);
|
||||
g_signal_connect (renderer_toggle, "toggled",
|
||||
G_CALLBACK (midori_extensions_cell_renderer_toggled_cb), extensions);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (extensions->treeview), column);
|
||||
column = gtk_tree_view_column_new ();
|
||||
renderer_text = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
|
||||
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
|
||||
|
@ -366,16 +499,39 @@ midori_extensions_init (MidoriExtensions* extensions)
|
|||
extensions->treeview, NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (extensions->treeview), column);
|
||||
g_object_unref (liststore);
|
||||
g_signal_connect (extensions->treeview, "row-activated",
|
||||
G_CALLBACK (midori_extensions_treeview_row_activated_cb),
|
||||
extensions);
|
||||
g_signal_connect (extensions->treeview, "cursor-changed",
|
||||
G_CALLBACK (midori_extensions_treeview_cursor_changed_cb),
|
||||
extensions);
|
||||
g_object_connect (extensions->treeview,
|
||||
"signal::row-activated",
|
||||
midori_extensions_treeview_row_activated_cb, extensions,
|
||||
"signal::button-release-event",
|
||||
midori_extensions_button_release_event_cb, extensions,
|
||||
"signal::popup-menu",
|
||||
midori_extensions_popup_menu_cb, extensions,
|
||||
NULL);
|
||||
gtk_widget_show (extensions->treeview);
|
||||
gtk_box_pack_start (GTK_BOX (extensions), extensions->treeview, TRUE, TRUE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_extensions_finalize (GObject* object)
|
||||
{
|
||||
MidoriExtensions* extensions = MIDORI_EXTENSIONS (object);
|
||||
KatzeArray* array = katze_object_get_object (extensions->app, "extensions");
|
||||
guint i = 0;
|
||||
MidoriExtension* extension;
|
||||
|
||||
while ((extension = katze_array_get_nth_item (array, i++)))
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (extension,
|
||||
midori_extensions_extension_activate_cb, extensions);
|
||||
g_signal_handlers_disconnect_by_func (extension,
|
||||
midori_extensions_extension_deactivate_cb, extensions);
|
||||
}
|
||||
g_signal_handlers_disconnect_by_func (array,
|
||||
midori_extensions_add_item_cb, extensions);
|
||||
|
||||
g_object_unref (array);
|
||||
}
|
||||
|
||||
/**
|
||||
* midori_extensions_new:
|
||||
*
|
||||
|
|
|
@ -757,8 +757,10 @@ midori_history_open_in_window_activate_cb (GtkWidget* menuitem,
|
|||
|
||||
if (uri && *uri)
|
||||
{
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (history));
|
||||
g_signal_emit_by_name (browser, "new-window", uri);
|
||||
MidoriBrowser* new_browser = midori_app_create_browser (history->app);
|
||||
midori_app_add_browser (history->app, new_browser);
|
||||
gtk_widget_show (GTK_WIDGET (new_browser));
|
||||
midori_browser_add_uri (new_browser, uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -224,6 +224,7 @@ midori_plugins_init (MidoriPlugins* plugins)
|
|||
GtkCellRenderer* renderer_text;
|
||||
GtkCellRenderer* renderer_pixbuf;
|
||||
GtkListStore* liststore = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
|
||||
|
||||
plugins->treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (liststore));
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (plugins->treeview), FALSE);
|
||||
column = gtk_tree_view_column_new ();
|
||||
|
@ -242,76 +243,34 @@ midori_plugins_init (MidoriPlugins* plugins)
|
|||
gtk_widget_show (plugins->treeview);
|
||||
gtk_box_pack_start (GTK_BOX (plugins), plugins->treeview, TRUE, TRUE, 0);
|
||||
|
||||
if (1)
|
||||
{
|
||||
/* FIXME: WebKit should have API to obtain the list of plugins. */
|
||||
/* FIXME: Monitor folders for newly added and removes files */
|
||||
if (g_module_supported ())
|
||||
GtkWidget* web_view = webkit_web_view_new ();
|
||||
WebKitWebFrame* web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view));
|
||||
JSContextRef js_context = webkit_web_frame_get_global_context (web_frame);
|
||||
/* This snippet joins the available plugins into a string like this:
|
||||
URI1|title1,URI2|title2
|
||||
FIXME: Ensure separators contained in the string can't break it */
|
||||
gchar* value = sokoke_js_script_eval (js_context,
|
||||
"function plugins (l) { var f = new Array (); for (i in l) "
|
||||
"{ var t = l[i].name; "
|
||||
"f.push (l[i].name + '|' + l[i].filename); } return f; }"
|
||||
"plugins (navigator.plugins)", NULL);
|
||||
gchar** items = g_strsplit (value, ",", 0);
|
||||
guint i = 0;
|
||||
|
||||
if (items != NULL)
|
||||
while (items[i] != NULL)
|
||||
{
|
||||
/* FIXME: WebKit is also looking in legacy folders,
|
||||
we should have API to obtain that same list. */
|
||||
gchar** plugin_dirs;
|
||||
gsize i = 0;
|
||||
|
||||
if (g_getenv ("MOZ_PLUGIN_PATH"))
|
||||
plugin_dirs = g_strsplit (g_getenv ("MOZ_PLUGIN_PATH"), ":", 0);
|
||||
else
|
||||
plugin_dirs = g_strsplit ("/usr/lib/mozilla/plugins", ":", 0);
|
||||
|
||||
while (plugin_dirs[i])
|
||||
{
|
||||
gchar* plugin_path;
|
||||
GDir* plugin_dir;
|
||||
|
||||
plugin_path = g_build_filename (plugin_dirs[i], NULL);
|
||||
plugin_dir = g_dir_open (plugin_path, 0, NULL);
|
||||
if (plugin_dir != 0)
|
||||
{
|
||||
const gchar* filename;
|
||||
|
||||
while ((filename = g_dir_read_name (plugin_dir)))
|
||||
{
|
||||
gchar* fullname;
|
||||
GModule* module;
|
||||
typedef int (*NP_GetValue_func)(void* instance,
|
||||
int variable,
|
||||
void* value);
|
||||
NP_GetValue_func NP_GetValue;
|
||||
const gchar* plugin_name;
|
||||
const gchar* plugin_description;
|
||||
|
||||
/* Ignore files which don't have the correct suffix */
|
||||
if (!g_str_has_suffix (filename, G_MODULE_SUFFIX))
|
||||
continue;
|
||||
|
||||
fullname = g_build_filename (plugin_path, filename, NULL);
|
||||
module = g_module_open (fullname, G_MODULE_BIND_LOCAL);
|
||||
g_free (fullname);
|
||||
|
||||
if (module && g_module_symbol (module, "NP_GetValue",
|
||||
(gpointer) &NP_GetValue))
|
||||
{
|
||||
typedef const gchar* (*NP_GetMIMEDescription_func)(void);
|
||||
NP_GetMIMEDescription_func NP_GetMIMEDescription;
|
||||
|
||||
NP_GetValue (NULL, 2, &plugin_name);
|
||||
if (g_module_symbol (module, "NP_GetMIMEDescription",
|
||||
(gpointer) &NP_GetMIMEDescription))
|
||||
plugin_description = NP_GetMIMEDescription ();
|
||||
else
|
||||
plugin_description = g_module_error ();
|
||||
}
|
||||
else
|
||||
{
|
||||
plugin_name = filename;
|
||||
plugin_description = g_module_error ();
|
||||
}
|
||||
|
||||
midori_plugins_add_item (plugins, plugin_name, plugin_description);
|
||||
}
|
||||
g_dir_close (plugin_dir);
|
||||
}
|
||||
g_free (plugin_path);
|
||||
gchar** parts = g_strsplit (items[i], "|", 2);
|
||||
if (parts && *parts && !g_str_equal (parts[1], "undefined"))
|
||||
midori_plugins_add_item (plugins, *parts, parts[1]);
|
||||
g_strfreev (parts);
|
||||
i++;
|
||||
}
|
||||
g_strfreev (plugin_dirs);
|
||||
g_strfreev (items);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -372,6 +372,169 @@ midori_transfers_hierarchy_changed_cb (MidoriTransfers* transfers,
|
|||
#endif
|
||||
}
|
||||
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||||
static GtkWidget*
|
||||
midori_transfers_popup_menu_item (GtkMenu* menu,
|
||||
const gchar* stock_id,
|
||||
const gchar* label,
|
||||
WebKitDownload* download,
|
||||
gpointer callback,
|
||||
gboolean enabled,
|
||||
MidoriTransfers* transfers)
|
||||
{
|
||||
GtkWidget* menuitem;
|
||||
|
||||
menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL);
|
||||
if (label)
|
||||
gtk_label_set_text_with_mnemonic (GTK_LABEL (gtk_bin_get_child (
|
||||
GTK_BIN (menuitem))), label);
|
||||
|
||||
if (!enabled)
|
||||
gtk_widget_set_sensitive (menuitem, FALSE);
|
||||
|
||||
g_object_set_data (G_OBJECT (menuitem), "WebKitDownload", download);
|
||||
|
||||
if (callback)
|
||||
g_signal_connect (menuitem, "activate", G_CALLBACK (callback), transfers);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
gtk_widget_show (menuitem);
|
||||
|
||||
return menuitem;
|
||||
}
|
||||
|
||||
static void
|
||||
midori_transfers_open_activate_cb (GtkWidget* menuitem,
|
||||
MidoriTransfers* transfers)
|
||||
{
|
||||
WebKitDownload* download;
|
||||
const gchar* uri;
|
||||
|
||||
download = g_object_get_data (G_OBJECT (menuitem), "WebKitDownload");
|
||||
g_return_if_fail (download != NULL);
|
||||
|
||||
uri = webkit_download_get_destination_uri (download);
|
||||
sokoke_show_uri (gtk_widget_get_screen (GTK_WIDGET (transfers->treeview)),
|
||||
uri, gtk_get_current_event_time (), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_transfers_open_folder_activate_cb (GtkWidget* menuitem,
|
||||
MidoriTransfers* transfers)
|
||||
{
|
||||
WebKitDownload* download;
|
||||
const gchar* uri;
|
||||
GFile* file;
|
||||
GFile* folder;
|
||||
|
||||
download = g_object_get_data (G_OBJECT (menuitem), "WebKitDownload");
|
||||
g_return_if_fail (download != NULL);
|
||||
|
||||
uri = webkit_download_get_destination_uri (download);
|
||||
file = g_file_new_for_uri (uri);
|
||||
if ((folder = g_file_get_parent (file)))
|
||||
{
|
||||
gchar* folder_uri = g_file_get_uri (folder);
|
||||
sokoke_show_uri (gtk_widget_get_screen (GTK_WIDGET (transfers->treeview)),
|
||||
folder_uri, gtk_get_current_event_time (), NULL);
|
||||
g_free (folder_uri);
|
||||
g_object_unref (folder);
|
||||
}
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_transfers_copy_address_activate_cb (GtkWidget* menuitem,
|
||||
MidoriTransfers* transfers)
|
||||
{
|
||||
WebKitDownload* download;
|
||||
const gchar* uri;
|
||||
GtkClipboard* clipboard;
|
||||
|
||||
download = g_object_get_data (G_OBJECT (menuitem), "WebKitDownload");
|
||||
g_return_if_fail (download != NULL);
|
||||
|
||||
uri = webkit_download_get_destination_uri (download);
|
||||
clipboard = gtk_clipboard_get_for_display (
|
||||
gtk_widget_get_display (GTK_WIDGET (menuitem)),
|
||||
GDK_SELECTION_CLIPBOARD);
|
||||
gtk_clipboard_set_text (clipboard, uri, -1);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_transfers_popup (GtkWidget* widget,
|
||||
GdkEventButton* event,
|
||||
WebKitDownload* download,
|
||||
MidoriTransfers* transfers)
|
||||
{
|
||||
GtkWidget* menu;
|
||||
gboolean finished = FALSE;
|
||||
|
||||
if (webkit_download_get_status (download) == WEBKIT_DOWNLOAD_STATUS_FINISHED)
|
||||
finished = TRUE;
|
||||
|
||||
menu = gtk_menu_new ();
|
||||
midori_transfers_popup_menu_item (GTK_MENU (menu), GTK_STOCK_OPEN, NULL, download,
|
||||
midori_transfers_open_activate_cb, finished, transfers);
|
||||
midori_transfers_popup_menu_item (GTK_MENU (menu), GTK_STOCK_DIRECTORY,
|
||||
_("Open Destination _Folder"), download,
|
||||
midori_transfers_open_folder_activate_cb, TRUE, transfers);
|
||||
midori_transfers_popup_menu_item (GTK_MENU (menu), GTK_STOCK_COPY,
|
||||
_("Copy Link Loc_ation"), download,
|
||||
midori_transfers_copy_address_activate_cb, FALSE, transfers);
|
||||
|
||||
sokoke_widget_popup (widget, GTK_MENU (menu),
|
||||
event, SOKOKE_MENU_POSITION_CURSOR);
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
midori_transfers_popup_menu_cb (GtkWidget* widget,
|
||||
MidoriTransfers* transfers)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter))
|
||||
{
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||||
WebKitDownload* download;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 1, &download, -1);
|
||||
|
||||
midori_transfers_popup (widget, NULL, download, transfers);
|
||||
g_object_unref (download);
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
midori_transfers_button_release_event_cb (GtkWidget* widget,
|
||||
GdkEventButton* event,
|
||||
MidoriTransfers* transfers)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (event->button != 3)
|
||||
return FALSE;
|
||||
|
||||
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter))
|
||||
{
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||||
WebKitDownload* download;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 1, &download, -1);
|
||||
|
||||
midori_transfers_popup (widget, NULL, download, transfers);
|
||||
g_object_unref (download);
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
midori_transfers_init (MidoriTransfers* transfers)
|
||||
{
|
||||
|
@ -400,9 +563,14 @@ midori_transfers_init (MidoriTransfers* transfers)
|
|||
transfers->treeview, NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (transfers->treeview), column);
|
||||
g_object_unref (treestore);
|
||||
g_signal_connect (transfers->treeview, "row-activated",
|
||||
G_CALLBACK (midori_transfers_treeview_row_activated_cb),
|
||||
transfers);
|
||||
g_object_connect (transfers->treeview,
|
||||
"signal::row-activated",
|
||||
midori_transfers_treeview_row_activated_cb, transfers,
|
||||
"signal::button-release-event",
|
||||
midori_transfers_button_release_event_cb, transfers,
|
||||
"signal::popup-menu",
|
||||
midori_transfers_popup_menu_cb, transfers,
|
||||
NULL);
|
||||
gtk_widget_show (transfers->treeview);
|
||||
gtk_box_pack_start (GTK_BOX (transfers), transfers->treeview, TRUE, TRUE, 0);
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
# set of available languages (in alphabetic order)
|
||||
cs da de el en_GB es et fi fr gl he hu id it ja nl pl pt ro ru sk sv tr uk zh_CN zh_TW
|
||||
cs da de el en_GB es et fi fr gl he hu id it ja nl pl pt ro ru sk sr sr@latin sv tr uk zh_CN zh_TW
|
||||
|
|
|
@ -5,6 +5,8 @@ midori/main.c
|
|||
midori/midori-app.c
|
||||
midori/midori-array.c
|
||||
midori/midori-browser.c
|
||||
midori/midori-locationaction.c
|
||||
midori/midori-locationentry.c
|
||||
midori/midori-panel.c
|
||||
midori/midori-websettings.c
|
||||
midori/midori-view.c
|
||||
|
@ -28,6 +30,7 @@ extensions/adblock.c
|
|||
extensions/colorful-tabs.c
|
||||
extensions/cookie-manager/cookie-manager.c
|
||||
extensions/cookie-manager/cookie-manager-page.c
|
||||
extensions/cookie-manager/main.c
|
||||
extensions/feed-panel/feed-atom.c
|
||||
extensions/feed-panel/feed-panel.c
|
||||
extensions/feed-panel/feed-parse.c
|
||||
|
@ -35,4 +38,7 @@ extensions/feed-panel/feed-rss.c
|
|||
extensions/feed-panel/main.c
|
||||
extensions/mouse-gestures/main.c
|
||||
extensions/page-holder.c
|
||||
extensions/shortcuts.c
|
||||
extensions/statusbar-features.c
|
||||
extensions/tab-panel.c
|
||||
extensions/toolbar-editor.c
|
||||
|
|
1706
po/en_GB.po
1706
po/en_GB.po
File diff suppressed because it is too large
Load diff
1140
po/midori.pot
1140
po/midori.pot
File diff suppressed because it is too large
Load diff
2063
po/sr@latin.po
Normal file
2063
po/sr@latin.po
Normal file
File diff suppressed because it is too large
Load diff
1140
po/zh_CN.po
1140
po/zh_CN.po
File diff suppressed because it is too large
Load diff
|
@ -282,6 +282,8 @@ int
|
|||
main (int argc,
|
||||
char** argv)
|
||||
{
|
||||
/* libSoup uses threads, so we need to initialize threads. */
|
||||
if (!g_thread_supported ()) g_thread_init (NULL);
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
gtk_init_check (&argc, &argv);
|
||||
|
||||
|
|
|
@ -167,15 +167,81 @@ extension_settings (void)
|
|||
midori_extension_deactivate (extension);
|
||||
}
|
||||
|
||||
static void
|
||||
extension_activate (gconstpointer data)
|
||||
{
|
||||
MidoriApp* app = midori_app_new ();
|
||||
MidoriExtension* extension = MIDORI_EXTENSION (data);
|
||||
/* g_signal_emit_by_name (extension, "activate", app);
|
||||
midori_extension_deactivate (extension); */
|
||||
g_object_unref (app);
|
||||
}
|
||||
|
||||
static void
|
||||
load_extensions (void)
|
||||
{
|
||||
if (g_module_supported ())
|
||||
{
|
||||
GDir* extension_dir = g_dir_open (EXTENSION_PATH, 0, NULL);
|
||||
if (extension_dir != NULL)
|
||||
{
|
||||
const gchar* filename;
|
||||
|
||||
while ((filename = g_dir_read_name (extension_dir)))
|
||||
{
|
||||
gchar* fullname;
|
||||
GModule* module;
|
||||
typedef MidoriExtension* (*extension_init_func)(void);
|
||||
extension_init_func extension_init;
|
||||
|
||||
/* Ignore files which don't have the correct suffix */
|
||||
if (!g_str_has_suffix (filename, G_MODULE_SUFFIX))
|
||||
continue;
|
||||
|
||||
fullname = g_build_filename (EXTENSION_PATH, filename, NULL);
|
||||
module = g_module_open (fullname, G_MODULE_BIND_LOCAL);
|
||||
g_free (fullname);
|
||||
|
||||
if (module && g_module_symbol (module, "extension_init",
|
||||
(gpointer) &extension_init))
|
||||
{
|
||||
guint length;
|
||||
gchar* name;
|
||||
gchar* path;
|
||||
typedef MidoriExtension* (*extension_test_func)(const gchar* path);
|
||||
extension_test_func extension_test;
|
||||
|
||||
if (g_str_has_prefix (filename, "lib"))
|
||||
filename = &filename[3];
|
||||
length = strlen (filename);
|
||||
name = g_strdup (filename);
|
||||
name[length - strlen (G_MODULE_SUFFIX) - 1] = '\0';
|
||||
path = g_strconcat ("/extensions/", name, "/activate", NULL);
|
||||
g_free (name);
|
||||
g_test_add_data_func (path, extension_init (), extension_activate);
|
||||
g_free (path);
|
||||
if (g_module_symbol (module, "extension_test",
|
||||
(gpointer) &extension_test))
|
||||
extension_test (path);
|
||||
}
|
||||
}
|
||||
g_dir_close (extension_dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char** argv)
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
gtk_init_check (&argc, &argv);
|
||||
if (!g_thread_supported ()) g_thread_init (NULL);
|
||||
|
||||
g_test_add_func ("/extensions/create", extension_create);
|
||||
g_test_add_func ("/extensions/settings", extension_settings);
|
||||
|
||||
load_extensions ();
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
@ -141,6 +141,7 @@ magic_uri_search (void)
|
|||
test_input ("max@mustermann.de", NULL);
|
||||
test_input ("g max@mustermann.de", NULL);
|
||||
test_input ("g inurl:http://twotoasts.de bug", NULL);
|
||||
test_input ("sm", SM);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -17,6 +17,29 @@
|
|||
#include "midori-bookmarks.h"
|
||||
#include "sokoke.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const gchar* type;
|
||||
const gchar* property;
|
||||
} ObjectProperty;
|
||||
|
||||
static ObjectProperty properties_object_skip[] =
|
||||
{
|
||||
{ "MidoriWebSettings", "ident-string" },
|
||||
};
|
||||
|
||||
static gboolean
|
||||
properties_should_skip (const gchar* type,
|
||||
const gchar* property)
|
||||
{
|
||||
guint i;
|
||||
for (i = 0; i < G_N_ELEMENTS (properties_object_skip); i++)
|
||||
if (g_str_equal (properties_object_skip[i].type, type))
|
||||
if (g_str_equal (properties_object_skip[i].property, property))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#define pspec_is_writable(pspec) (pspec->flags & G_PARAM_WRITABLE \
|
||||
&& !(pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)))
|
||||
|
||||
|
@ -35,11 +58,26 @@ properties_object_get_set (GObject* object)
|
|||
GType type = G_PARAM_SPEC_TYPE (pspec);
|
||||
const gchar* property = g_param_spec_get_name (pspec);
|
||||
void* value = NULL;
|
||||
guint j;
|
||||
|
||||
/* Skip properties of parent classes */
|
||||
if (pspec->owner_type != G_OBJECT_TYPE (object))
|
||||
continue;
|
||||
|
||||
/* Skip properties that cannot be tested generically */
|
||||
if (properties_should_skip (G_OBJECT_TYPE_NAME (object), property))
|
||||
continue;
|
||||
|
||||
/* Verify that the ID is unique */
|
||||
if (pspecs[i]->owner_type == G_OBJECT_TYPE (object))
|
||||
for (j = 0; j < n_properties; j++)
|
||||
if (i != j && pspecs[j]->owner_type == G_OBJECT_TYPE (object))
|
||||
if (pspec->param_id == pspecs[j]->param_id)
|
||||
g_error ("Duplicate ID %d of %s and %s",
|
||||
pspec->param_id,
|
||||
g_param_spec_get_name (pspec),
|
||||
g_param_spec_get_name (pspecs[j]));
|
||||
|
||||
g_object_get (object, property, &value, NULL);
|
||||
if (type == G_TYPE_PARAM_BOOLEAN)
|
||||
{
|
||||
|
@ -84,25 +122,25 @@ properties_object_get_set (GObject* object)
|
|||
{
|
||||
GEnumClass* enum_class = G_ENUM_CLASS (
|
||||
g_type_class_ref (pspec->value_type));
|
||||
gint j;
|
||||
|
||||
if (pspec_is_writable (pspec))
|
||||
{
|
||||
gint k;
|
||||
g_object_set (object, property,
|
||||
G_PARAM_SPEC_ENUM (pspec)->default_value, NULL);
|
||||
for (j = enum_class->minimum; j < enum_class->maximum; j++)
|
||||
for (k = enum_class->minimum; k < enum_class->maximum; k++)
|
||||
{
|
||||
GEnumValue* enum_value = g_enum_get_value (enum_class, j);
|
||||
GEnumValue* enum_value = g_enum_get_value (enum_class, k);
|
||||
if (!enum_value)
|
||||
g_error ("%s.%s has no value %d",
|
||||
G_OBJECT_TYPE_NAME (object), property, j);
|
||||
G_OBJECT_TYPE_NAME (object), property, k);
|
||||
GEnumValue* enum_value_ = g_enum_get_value_by_name (enum_class,
|
||||
enum_value->value_name);
|
||||
if (!enum_value)
|
||||
g_error ("%s.%s has no value '%s'",
|
||||
G_OBJECT_TYPE_NAME (object), property, enum_value->value_name);
|
||||
g_assert_cmpint (enum_value->value, ==, enum_value_->value);
|
||||
g_object_set (object, property, j, NULL);
|
||||
g_object_set (object, property, k, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
# WAF build script for midori
|
||||
# This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||
|
||||
import os
|
||||
|
||||
tests = os.listdir ('tests')
|
||||
for test in tests:
|
||||
folder = 'tests' + os.sep + test
|
||||
|
@ -24,6 +26,7 @@ for test in tests:
|
|||
obj = bld.new_task_gen ('cc', 'program')
|
||||
obj.target = 'test-' + target
|
||||
obj.includes = '.. ../midori ../panels'
|
||||
obj.cflags = ['-DEXTENSION_PATH="' + os.path.abspath ('_build_/default/extensions') + '"']
|
||||
obj.source = source
|
||||
obj.uselib = 'UNIQUE LIBSOUP GIO GTK SQLITE WEBKIT LIBXML'
|
||||
obj.uselib_local = 'panels'
|
||||
|
|
231
wscript
231
wscript
|
@ -19,10 +19,13 @@ import Utils
|
|||
import pproc as subprocess
|
||||
import os
|
||||
import UnitTest
|
||||
import Task
|
||||
from TaskGen import extension
|
||||
import misc
|
||||
|
||||
major = 0
|
||||
minor = 1
|
||||
micro = 7
|
||||
micro = 8
|
||||
|
||||
APPNAME = 'midori'
|
||||
VERSION = str (major) + '.' + str (minor) + '.' + str (micro)
|
||||
|
@ -38,24 +41,45 @@ srcdir = '.'
|
|||
blddir = '_build_'
|
||||
|
||||
def option_enabled (option):
|
||||
if eval ('Options.options.enable_' + option):
|
||||
if getattr (Options.options, 'enable_' + option):
|
||||
return True
|
||||
if eval ('Options.options.disable_' + option):
|
||||
if getattr (Options.options, 'disable_' + option):
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_mingw (env):
|
||||
if 'CC' in env:
|
||||
cc = env['CC']
|
||||
if not isinstance (cc, str):
|
||||
cc = ''.join (cc)
|
||||
return cc.find ('mingw') != -1# or cc.find ('wine') != -1
|
||||
return False
|
||||
|
||||
# Compile Win32 res files to (resource) object files
|
||||
@extension ('.rc')
|
||||
def rc_file(self, node):
|
||||
rctask = self.create_task ('winrc')
|
||||
rctask.set_inputs (node)
|
||||
rctask.set_outputs (node.change_ext ('.rc.o'))
|
||||
self.compiled_tasks.append (rctask)
|
||||
Task.simple_task_type ('winrc', '${WINRC} -o${TGT} ${SRC}', color='BLUE',
|
||||
before='cc cxx', shell=False)
|
||||
|
||||
def configure (conf):
|
||||
def option_checkfatal (option, desc):
|
||||
if eval ('Options.options.enable_' + option):
|
||||
if hasattr (Options.options, 'enable_' + option):
|
||||
if getattr (Options.options, 'enable_' + option):
|
||||
Utils.pprint ('RED', desc + ' N/A')
|
||||
sys.exit (1)
|
||||
|
||||
def dirname_default (dirname, default):
|
||||
if eval ('Options.options.' + dirname) == '':
|
||||
def dirname_default (dirname, default, defname=None):
|
||||
if getattr (Options.options, dirname) == '':
|
||||
dirvalue = default
|
||||
else:
|
||||
dirvalue = eval ('Options.options.' + dirname)
|
||||
conf.define (dirname, dirvalue)
|
||||
dirvalue = getattr (Options.options, dirname)
|
||||
if not defname:
|
||||
defname = dirname
|
||||
conf.define (defname, dirvalue)
|
||||
return dirvalue
|
||||
|
||||
conf.check_tool ('compiler_cc')
|
||||
|
@ -85,13 +109,47 @@ def configure (conf):
|
|||
nls = 'no '
|
||||
conf.define ('ENABLE_NLS', [0,1][nls == 'yes'])
|
||||
|
||||
dirname_default ('DATADIR', os.path.join (conf.env['PREFIX'], 'share'))
|
||||
dirname_default ('DOCDIR', os.path.join (conf.env['DATADIR'], 'doc'))
|
||||
if conf.find_program ('rsvg-convert', var='RSVG_CONVERT'):
|
||||
icons = 'yes'
|
||||
else:
|
||||
icons = 'no '
|
||||
|
||||
if is_mingw (conf.env) or Options.platform == 'win32':
|
||||
if not conf.find_program ('convert', var='CONVERT'):
|
||||
Utils.pprint ('YELLOW', 'midori.ico won\'t be created')
|
||||
conf.find_program ('windres', var='WINRC')
|
||||
|
||||
# This is specific to cross compiling with mingw
|
||||
if is_mingw (conf.env) and Options.platform != 'win32':
|
||||
if not 'AR' in os.environ and not 'RANLIB' in os.environ:
|
||||
conf.env['AR'] = os.environ['CC'][:-3] + 'ar'
|
||||
if conf.find_program (os.environ['CC'][:-3] + 'windres', var='WINRC'):
|
||||
os.environ['WINRC'] = os.environ['CC'][:-3] + 'windres'
|
||||
Options.platform = 'win32'
|
||||
# Make sure we don't have -fPIC in the CCFLAGS
|
||||
conf.env["shlib_CCFLAGS"] = []
|
||||
# Adjust file naming
|
||||
conf.env["shlib_PATTERN"] = 'lib%s.dll'
|
||||
conf.env['program_PATTERN'] = '%s.exe'
|
||||
# Use Visual C++ compatible alignment
|
||||
conf.env.append_value ('CCFLAGS', '-mms-bitfields')
|
||||
conf.env['staticlib_LINKFLAGS'] = []
|
||||
|
||||
Utils.pprint ('BLUE', 'Mingw recognized, assuming cross compile.')
|
||||
|
||||
if conf.env['CONVERT'] and not conf.env['WINRC']:
|
||||
Utils.pprint ('YELLOW', 'midori.ico won\'t be created')
|
||||
|
||||
dirname_default ('LIBDIR', os.path.join (conf.env['PREFIX'], 'lib'))
|
||||
if conf.env['PREFIX'] == '/usr':
|
||||
dirname_default ('SYSCONFDIR', '/etc')
|
||||
else:
|
||||
dirname_default ('SYSCONFDIR', os.path.join (conf.env['PREFIX'], 'etc'))
|
||||
dirname_default ('DATADIR', os.path.join (conf.env['PREFIX'], 'share'),
|
||||
# Use MDATADIR because DATADIR is a constant in objidl.h on Windows
|
||||
'MDATADIR')
|
||||
conf.undefine ('DATADIR')
|
||||
dirname_default ('DOCDIR', os.path.join (conf.env['MDATADIR'], 'doc'))
|
||||
|
||||
if option_enabled ('apidocs'):
|
||||
conf.find_program ('gtkdoc-scan', var='GTKDOC_SCAN')
|
||||
|
@ -107,33 +165,37 @@ def configure (conf):
|
|||
else:
|
||||
api_docs = 'no '
|
||||
|
||||
def check_pkg (name, version='', mandatory=True, var=None):
|
||||
def check_pkg (name, version='', mandatory=True, var=None, args=''):
|
||||
if not var:
|
||||
var = name.split ('-')[0].upper ()
|
||||
conf.check_cfg (package=name, uselib_store=var, args='--cflags --libs',
|
||||
conf.check_cfg (package=name, uselib_store=var, args='--cflags --libs ' + args,
|
||||
atleast_version=version, mandatory=mandatory)
|
||||
return conf.env['HAVE_' + var]
|
||||
|
||||
if option_enabled ('unique'):
|
||||
check_pkg ('unique-1.0', '0.9', False)
|
||||
unique = ['N/A', 'yes'][conf.env['HAVE_UNIQUE'] == 1]
|
||||
else:
|
||||
if unique != 'yes':
|
||||
option_checkfatal ('unique', 'single instance')
|
||||
else:
|
||||
unique = 'no '
|
||||
conf.define ('HAVE_UNIQUE', [0,1][unique == 'yes'])
|
||||
|
||||
if option_enabled ('libidn'):
|
||||
check_pkg ('libidn', '1.0', False)
|
||||
libidn = ['N/A','yes'][conf.env['HAVE_LIBIDN'] == 1]
|
||||
else:
|
||||
if libidn != 'yes':
|
||||
option_checkfatal ('libidn', 'international domain names')
|
||||
else:
|
||||
libidn = 'no '
|
||||
conf.define ('HAVE_LIBIDN', [0,1][libidn == 'yes'])
|
||||
|
||||
if option_enabled ('sqlite'):
|
||||
check_pkg ('sqlite3', '3.0', False, var='SQLITE')
|
||||
sqlite = ['N/A','yes'][conf.env['HAVE_SQLITE'] == 1]
|
||||
else:
|
||||
if sqlite != 'yes':
|
||||
option_checkfatal ('sqlite', 'history database')
|
||||
else:
|
||||
sqlite = 'no '
|
||||
conf.define ('HAVE_SQLITE', [0,1][sqlite == 'yes'])
|
||||
|
||||
|
@ -141,29 +203,44 @@ def configure (conf):
|
|||
check_pkg ('gmodule-2.0', '2.8.0', False)
|
||||
check_pkg ('gthread-2.0', '2.8.0', False)
|
||||
check_pkg ('gio-2.0', '2.16.0')
|
||||
check_pkg ('gtk+-2.0', '2.10.0', var='GTK')
|
||||
check_pkg ('webkit-1.0', '1.1.1')
|
||||
args = ''
|
||||
if Options.platform == 'win32':
|
||||
args = '--define-variable=target=win32'
|
||||
check_pkg ('gtk+-2.0', '2.10.0', var='GTK', args=args)
|
||||
check_pkg ('webkit-1.0', '1.1.1', args=args)
|
||||
check_pkg ('libsoup-2.4', '2.25.2')
|
||||
conf.define ('HAVE_LIBSOUP_2_25_2', 1)
|
||||
check_pkg ('libxml-2.0', '2.6')
|
||||
|
||||
if option_enabled ('hildon'):
|
||||
check_pkg ('hildon-1', mandatory=False, var='HILDON')
|
||||
if conf.env['HAVE_HILDON'] == 1:
|
||||
check_pkg ('libosso', mandatory=False, var='HILDON')
|
||||
if check_pkg ('hildon-1', mandatory=False, var='HILDON'):
|
||||
check_pkg ('libosso', var='HILDON')
|
||||
hildon = ['N/A','yes'][conf.env['HAVE_HILDON'] == 1]
|
||||
else:
|
||||
if hildon != 'yes':
|
||||
option_checkfatal ('hildon', 'Maemo integration')
|
||||
else:
|
||||
hildon = 'no '
|
||||
conf.define ('HAVE_HILDON', [0,1][hildon == 'yes'])
|
||||
|
||||
conf.check (header_name='unistd.h')
|
||||
conf.define ('HAVE_OSX', int(sys.platform == 'darwin'))
|
||||
# Store options in env, since 'Options' is not persistent
|
||||
if 'CC' in os.environ: conf.env['CC'] = os.environ['CC'].split()
|
||||
conf.env['addons'] = option_enabled ('addons')
|
||||
conf.env['docs'] = option_enabled ('docs')
|
||||
|
||||
if conf.find_program ('rsvg-convert', var='RSVG_CONVERT'):
|
||||
icons = 'yes'
|
||||
else:
|
||||
icons = 'no '
|
||||
conf.check (header_name='unistd.h')
|
||||
if not conf.env['HAVE_UNIQUE']:
|
||||
if Options.platform == 'win32':
|
||||
conf.check (lib='ws2_32')
|
||||
check_pkg ('openssl', mandatory=False)
|
||||
conf.define ('USE_SSL', [0,1][conf.env['HAVE_OPENSSL'] == 1])
|
||||
conf.define ('HAVE_NETDB_H', [0,1][conf.check (header_name='netdb.h')])
|
||||
conf.check (header_name='sys/wait.h')
|
||||
conf.check (header_name='sys/select.h')
|
||||
conf.check (function_name='inet_aton')
|
||||
conf.check (function_name='inet_addr')
|
||||
conf.define ('HAVE_OSX', int(sys.platform == 'darwin'))
|
||||
if Options.platform == 'win32':
|
||||
conf.env.append_value ('LINKFLAGS', '-mwindows')
|
||||
|
||||
conf.define ('PACKAGE_VERSION', VERSION)
|
||||
conf.define ('PACKAGE_NAME', APPNAME)
|
||||
|
@ -205,22 +282,22 @@ def configure (conf):
|
|||
Utils.pprint ('RED', 'No debugging level support for ' + compiler)
|
||||
sys.exit (1)
|
||||
|
||||
print
|
||||
print "Optional build time dependencies:"
|
||||
print "Localization: " + nls + " (intltool)"
|
||||
print "Icon optimizations: " + icons + " (rsvg-convert)"
|
||||
print "User documentation: " + user_docs + " (docutils)"
|
||||
print "API documentation: " + api_docs + " (gtk-doc)"
|
||||
print
|
||||
print "Single instance: " + unique + " (unique)"
|
||||
print '''
|
||||
Localization: %(nls)s (intltool)
|
||||
Icon optimizations: %(icons)s (rsvg-convert)
|
||||
Persistent history: %(sqlite)s (sqlite3)
|
||||
|
||||
IDN support: %(libidn)s (libidn)
|
||||
User documentation: %(user_docs)s (docutils)
|
||||
API documentation: %(api_docs)s (gtk-doc)
|
||||
''' % locals ()
|
||||
if unique == 'yes' and conf.check_cfg (modversion='unique-1.0') == '1.0.4':
|
||||
Utils.pprint ('RED', 'unique 1.0.4 found, this version is erroneous.')
|
||||
Utils.pprint ('RED', 'Please use an older or newer version.')
|
||||
print "IDN support: " + libidn + " (libidn)"
|
||||
print "Persistent history: " + sqlite + " (sqlite3)"
|
||||
print "Maemo integration: " + hildon + " (hildon)"
|
||||
|
||||
def set_options (opt):
|
||||
def is_maemo (): return os.path.exists ('/etc/osso-af-init/osso-gtk.defs')
|
||||
|
||||
def add_enable_option (option, desc, group=None, disable=False):
|
||||
if group == None:
|
||||
group = opt
|
||||
|
@ -258,15 +335,44 @@ def set_options (opt):
|
|||
add_enable_option ('libidn', 'international domain name support', group)
|
||||
add_enable_option ('sqlite', 'history database support', group)
|
||||
add_enable_option ('addons', 'building of extensions', group)
|
||||
add_enable_option ('hildon', 'Maemo integration', group)
|
||||
add_enable_option ('hildon', 'Maemo integration', group, disable=not is_maemo ())
|
||||
|
||||
def build (bld):
|
||||
def image_to_win32ico (task):
|
||||
'Converts an image to a Win32 ico'
|
||||
|
||||
if not os.path.exists (bld.env['CONVERT']):
|
||||
return 1
|
||||
|
||||
infile = task.inputs[0].abspath (task.env)
|
||||
outfile = task.outputs[0].abspath (task.env)
|
||||
command = bld.env['CONVERT'] + ' -background transparent \
|
||||
-geometry 16x16 -extent 16x16 ' + \
|
||||
infile + ' ' + outfile
|
||||
if Utils.exec_command (command):
|
||||
return 1
|
||||
|
||||
if task.chmod:
|
||||
os.chmod (outfile, task.chmod)
|
||||
return 0
|
||||
|
||||
if bld.env['WINRC']:
|
||||
obj = bld.new_task_gen ('copy',
|
||||
fun = image_to_win32ico,
|
||||
source = 'icons/16x16/midori.png',
|
||||
target = 'data/midori.ico',
|
||||
before = 'cc')
|
||||
|
||||
bld.add_group ()
|
||||
|
||||
bld.add_subdirs ('katze midori icons')
|
||||
|
||||
if option_enabled ('addons'):
|
||||
if bld.env['addons']:
|
||||
bld.add_subdirs ('extensions')
|
||||
|
||||
if option_enabled ('docs'):
|
||||
bld.add_group ()
|
||||
|
||||
if bld.env['docs']:
|
||||
bld.install_files ('${DOCDIR}/' + APPNAME + '/', \
|
||||
'AUTHORS ChangeLog COPYING EXPAT README TRANSLATE')
|
||||
|
||||
|
@ -295,20 +401,21 @@ def build (bld):
|
|||
bld.add_subdirs ('docs/api')
|
||||
bld.install_files ('${DOCDIR}/midori/api/', blddir + '/docs/api/*')
|
||||
|
||||
if not is_mingw (bld.env) and Options.platform != 'win32':
|
||||
if bld.env['HAVE_HILDON']:
|
||||
appdir = '${DATADIR}/applications/hildon'
|
||||
bld.install_files ('${DATADIR}/dbus-1/services',
|
||||
appdir = '${MDATADIR}/applications/hildon'
|
||||
bld.install_files ('${MDATADIR}/dbus-1/services',
|
||||
'data/com.nokia.' + APPNAME + '.service')
|
||||
else:
|
||||
appdir = '${DATADIR}/applications'
|
||||
appdir = '${MDATADIR}/applications'
|
||||
if bld.env['INTLTOOL']:
|
||||
obj = bld.new_task_gen ('intltool_in')
|
||||
obj.source = 'data/' + APPNAME + '.desktop.in'
|
||||
obj.install_path = appdir
|
||||
obj.flags = '-d'
|
||||
obj.flags = ['-d', '-c']
|
||||
bld.install_files (appdir, 'data/' + APPNAME + '.desktop')
|
||||
else:
|
||||
folder = os.path.dirname (bld.env['waf_config_files'][0]) + '/data'
|
||||
folder = os.path.abspath (blddir + '/default/data')
|
||||
Utils.check_dir (folder)
|
||||
desktop = APPNAME + '.desktop'
|
||||
pre = open ('data/' + desktop + '.in')
|
||||
|
@ -335,20 +442,20 @@ def build (bld):
|
|||
' -o ' + blddir + '/data/logo-shade.png ' + \
|
||||
srcdir + '/data/logo-shade.svg'
|
||||
if not Utils.exec_command (command):
|
||||
bld.install_files ('${DATADIR}/' + APPNAME + '/res', blddir + '/data/logo-shade.png')
|
||||
bld.install_files ('${MDATADIR}/' + APPNAME + '/res', blddir + '/data/logo-shade.png')
|
||||
else:
|
||||
Utils.pprint ('BLUE', "logo-shade could not be rasterized.")
|
||||
bld.install_files ('${DATADIR}/' + APPNAME + '/res', 'data/error.html')
|
||||
bld.install_files ('${DATADIR}/' + APPNAME + '/res', 'data/speeddial-head.html')
|
||||
bld.install_files ('${DATADIR}/' + APPNAME + '/res', 'data/speeddial.json')
|
||||
bld.install_files ('${DATADIR}/' + APPNAME + '/res', 'data/mootools.js')
|
||||
bld.install_files ('${MDATADIR}/' + APPNAME + '/res', 'data/error.html')
|
||||
bld.install_files ('${MDATADIR}/' + APPNAME + '/res', 'data/speeddial-head.html')
|
||||
bld.install_files ('${MDATADIR}/' + APPNAME + '/res', 'data/speeddial.json')
|
||||
bld.install_files ('${MDATADIR}/' + APPNAME + '/res', 'data/mootools.js')
|
||||
|
||||
if Options.commands['check']:
|
||||
bld.add_subdirs ('tests')
|
||||
|
||||
def shutdown ():
|
||||
if Options.commands['install'] or Options.commands['uninstall']:
|
||||
dir = Build.bld.get_install_path ('${DATADIR}/icons/hicolor')
|
||||
dir = Build.bld.get_install_path ('${MDATADIR}/icons/hicolor')
|
||||
icon_cache_updated = False
|
||||
if not Options.options.destdir:
|
||||
# update the pixmap cache directory
|
||||
|
@ -394,8 +501,10 @@ def shutdown ():
|
|||
Utils.pprint ('RED', "Make sure intltool is installed.")
|
||||
os.chdir ('..')
|
||||
elif Options.options.run:
|
||||
folder = os.path.dirname (Build.bld.env['waf_config_files'][0])
|
||||
folder = os.path.abspath (blddir + '/default')
|
||||
try:
|
||||
relfolder = folder
|
||||
if not is_mingw (Build.bld.env):
|
||||
relfolder = os.path.relpath (folder)
|
||||
except:
|
||||
pass
|
||||
|
@ -417,8 +526,14 @@ def shutdown ():
|
|||
'LC_MESSAGES' + os.sep + APPNAME + '.mo')
|
||||
except:
|
||||
pass
|
||||
command = relfolder + os.sep + APPNAME + os.sep + APPNAME
|
||||
print ext + ' ' + nls + ' ' + command
|
||||
Utils.exec_command (ext + ' ' + nls + ' ' + command)
|
||||
except:
|
||||
Utils.pprint ('RED', "Failed to run application.")
|
||||
command = ext + ' ' + nls + ' '
|
||||
if is_mingw (Build.bld.env):
|
||||
# This works only if everything is installed to that prefix
|
||||
os.chdir (Build.bld.env['PREFIX'] + os.sep + 'bin')
|
||||
command += ' wine cmd /k "PATH=%PATH%;' + Build.bld.env['PREFIX'] + os.sep + 'bin' + ' && ' + APPNAME + '.exe"'
|
||||
else:
|
||||
command += ' ' + relfolder + os.sep + APPNAME + os.sep + APPNAME
|
||||
print command
|
||||
Utils.exec_command (command)
|
||||
except Exception, msg:
|
||||
Utils.pprint ('RED', "Failed to run application: " + str (msg))
|
||||
|
|
Loading…
Reference in a new issue