Merge commit 'upstream/0.2.4'

This commit is contained in:
Ryan Niebur 2010-03-07 21:42:00 -08:00
commit 4435df3d8d
109 changed files with 29999 additions and 24286 deletions

2
.gitignore vendored
View file

@ -5,7 +5,9 @@ Makefile
_build_ _build_
po/.intltool-merge-cache po/.intltool-merge-cache
po/LINGUAS
po/POTFILES po/POTFILES
po/midori.pot
po/stamp-it po/stamp-it
po/*.gmo po/*.gmo

View file

@ -1,5 +1,43 @@
This file is licensed under the terms of the expat license, see the file EXPAT. This file is licensed under the terms of the expat license, see the file EXPAT.
v0.2.4
+ Prevent completion from overlapping
+ Fix tab order when restoring session
+ Ignore accidentally middle click search
+ Implement bookmark export to XBEL
+ Provide scroll hotkeys, default to Vim
+ Store and complete search in location
+ Fix opening externally with multiple windows
+ Only use icons in panel buttons
+ Fix build with different GTK+ versions
+ Omit micro version and arch from ident string
v0.2.3
+ Improve relocatability for Win32
+ Implement 'Close other tabs' menu item
+ Use new GTK+ accessors where available
+ Allow searching freely in History panel
+ Re-implement completion based on sqlite
+ Re-implement completion suggestion popup
+ Simplify sqlite use towards efficient calls
+ Move panel icons to the bottom
+ Merge Netscape Plugins and Extensions panels
+ Implement 'about:version' special page
+ Implement 'Preferred languages' preference
+ Improve window raising behaviour
+ Allow Ctrl+Right-click to suppress javascript menu
+ Add 'Open link as web app' in context menu
+ Add 'Block image' menu item to Adblock
+ Location progress and compat code refactored
+ Implement 'Paste and proceed' in location
+ Move DNS prefetching into the core
+ Allow selecting and deleting multiple cookies
+ Support attaching/ detaching web inspector
+ Always enable web inspector
+ --diagnostic-dialog command line switch
+ Faster file existence checks
+ Simplified, faster adblock implementation
v0.2.2 v0.2.2
+ Turn libnotify into a proper build-time dependency + Turn libnotify into a proper build-time dependency
+ Use Ctrl + Return to open tabs from the location entry + Use Ctrl + Return to open tabs from the location entry

64
HACKING
View file

@ -1,10 +1,68 @@
This file is licensed under the terms of the expat license, see the file EXPAT. This file is licensed under the terms of the expat license, see the file EXPAT.
It is 4 spaces, no tabs, preferrably at 80 columns per line. +++ Hacking guide for Midori +++
The preferred coding style is explained by example. Indentation is 4 spaces, no tabs, preferrably at 80 to 120 columns per line to
avoid automated line-breaks. Trailing whitespace is not desirable.
Source file example: Declarations go to the beginning of a block, not inline. Variables of one plain
type may be grouped in one declaration, pointer types may not be grouped. The
asterisk goes next to the type.
Variables should be ordered in the order they are used.
Comments explain functionality, they should not state facts. The appropriate
style is always C style /* */, not C++ style.
Variable and function names should be animal, animal_shelter or animalsc in
case it would otherwise be very long. Loop counters may be single letters.
Type names should be Animal, AnimalShelter or AnimalSC. No prefixes from third
party projects should be used, such as GTK or WebKit, while underlines may be
used but do not have a particular meaning.
There is a space between functions or keywords and round brackets, and curly
brackets always go on separate lines, at the indentation level of the
function, conditional or loop expression. Curly brackets are left out for single
statement conditionals and loops unless they notably help readability.
The type of a function goes on a separate line before the function.
Preprocessor instructions are indented with the code they relate to.
Code history is precious, so one should avoid renaming a lot of functions at
once or moving whole paragraphs only to add or remove a level of indentation.
Moving blocks of code around is also undesriable because it makes patches less
readable since the result looks like new code.
+++ Source files in the project +++
Core:
Files prefixed with "midori-" in the folder "midori" make up the core. They
are essential to running the browser and mostly tailored to the browser.
All header files prefixed with "midori-" are considered supported API and
can be used to implement extensions.
"sokoke" is a collection of very specialized helper functions which change
from time to time as needed. In the past some of the code was moved to
"katze" when it was considered generally useful.
"socket" is a socket implementation with no dependency on other parts of
the core, which is used if Midori is built without an external single
instance support library.
Panels:
Files in the "panels" folder are classes that implement MidoriViewable and
which are loaded into the MidoriPanel at startup. These panels are in
principle optional.
Katze:
Re-usable classes and utility functions that don't depend on the core and
some of that code indeed found its way into other projects.
Extensions:
These are extensions, written in C, which are loaded optionally if the user
so chooses. Extensions can use API from "midori-" and "katze-" headers. Each
module consists of either a single .c file or a folder with .c files.
Tests:
Unit tests are run regularly to verify possible regressions or measure
performance of implementations. Except for select cases code changes should
not cause failure of unit tests.
+++ Examplary source code +++
/* /*
Copyright Copyright

View file

@ -21,6 +21,10 @@ localizations are used from the build folder.
You can install it with './waf install' You can install it with './waf install'
If you need to do a clean rebuild, you can do either './waf clean'
in order to remove binaries or './waf distclean' which deletes generated
configuration files as well.
For further options run './waf --help' For further options run './waf --help'
+++ Debugging Midori +++ +++ Debugging Midori +++

74
TODO
View file

@ -1,9 +1,72 @@
This file is licensed under the terms of the expat license, see the file EXPAT. This file is licensed under the terms of the expat license, see the file EXPAT.
TODO: TODO:
. Detect opensearch engines on sites: http://searchplugins.net/pluginlist.aspx
. Request network if not connected and re-open the url on success
. Make cookie manager horizontal if the window is wide
. Handle SSL like SSH: confirm any cert on first connection, warn about any change in subsequent connections
. Open on startup: Ask (Last open pages, Blank, Homepage, [x] Don't ask anymore)
. Support @run-at document-start: http://dev.chromium.org/developers/design-documents/user-scripts
. Add an 'install' button to addons
. Dragging a link onto the web view to open it
. Extension: Ask Google if an address cannot be found, ie. typo
. View source is not always equal to Save As
. Show New Window icon in statusbar for new-window links
. Validate search engine tokens
. Easily register stock items in extensions (mouse gestures, input-mouse)
. Show graphical error when a bookmarklet fails to run
. Unit test katze array action
. There is no way to reset the toolbar
. Estimate download speed
. Implement no_proxy, https_proxy
. Make it possible to use extra C or C++ libraries in extensions
. Add icon cache size preference
. Fix icons with white background to be transparent?
. Visually indicate that a tab is being opened even if outside the visible tabs
. gget/ eatmonkey/ Transmission dbus in Transfers
. Add Midori to autostart, and remove it if it's quit, optionally disabled
. Use @include and @exclude with userstyles
. Support -moz-document domain: http://userstyles.org/styles/22837
. Need a throbber with invisible menubar: make compact-menu throbb?
. Implement live bookmarks, see http://johnbokma.com/firefox/rss-and-live-bookmarks.html
. Add a dialog (right-cick) to Addons, to edit @include and @exclude
. Show URI in css overlay tooltips if statusbar is hidden
. "Menu" tool buttons aren't depressed while a menu is open
. Statusbar doesn't show right-click menu
. Consider pango_layout_set_auto_dir
. Make it possible to change ident string for particular domains
. Support max-age for Flash cookies
. Update speed dial thumbnail when loading the according page from speed dial
. Implement "Open image" which opens an image with an external application
. Add custom actions extension; example Set Wallpaper
. Offer restoring session after crash, if session isn't opened at startup AND crash dialogue is enabled
. Vi extension, modelled after vimprobable
. Show loading tabs in the tab panel extension
. Let extensions add preferences
. Show syntax errors in userscripts/ styles
. Add HTTP_PRAGMA: no-cache when Ctrl+Shift+R
. Honor HTTP_PRAGMA: no-cache in web cache
. Switching browser window: Ctrl+Shift+PageUp/PageDown
. Switching panel: Ctrl+Alt+PageUp/PageDown
. Bookmark folder context menu, "Sort by Name"
. Adblock Block image: dialog to edit regex before adding
. KatzeArrayAction should support "activate" signal
. Remove extra inner panel border
. Move statusbar_contents below panel if statusbar is hidden
. Teplace "disable plugins" with showing a "load plugins automatically", where unchecking that keeps a placeholder that can be clicked to play
. Show "Type an address or keywords to search" in empty location even when focussed
. Show "Search hostname" in (can't resolve) error page, www.heyarnold.twotoastsde == typo?
. Enable extensions in private (app) mode
. Allow -e Set setting or so
. Remember if inspector was attached or not
. Icon in empty entry to paste from clipboard
. Show suggestions in error page, ie. missing www. or www. not existing for a domain: http://www.svcl.org/
. Warn when closing tab with unsubmitted form
. Always allow popups, keep hidden, show icon to ask whether to show popups
. Make Shift + Click download the link
. Use an update timeout in KatzePropertyProxy instead of only focus-out . Use an update timeout in KatzePropertyProxy instead of only focus-out
. Show a loading mouse pointer . Show a loading mouse pointer
. Import and export of the bookmarks file, or using one from a specific path . Export of the bookmarks file, or using one from a specific path
. Custom context menu actions, like in Thunar or Epiphany . Custom context menu actions, like in Thunar or Epiphany
. Analogus to blocked popups, blocked scripts moving layers on load (extension) . Analogus to blocked popups, blocked scripts moving layers on load (extension)
. Per-site blocking of individual elements on a page . Per-site blocking of individual elements on a page
@ -13,11 +76,8 @@ TODO:
. Automatic update checks (browser, extensions)? . Automatic update checks (browser, extensions)?
. Auto-group tabs by opener, with colors? . Auto-group tabs by opener, with colors?
. Mark (dogear) a selection so that it isn't cleared implicitly, multiply on one page . Mark (dogear) a selection so that it isn't cleared implicitly, multiply on one page
. Have an internal uri scheme, eg. 'res:', to reference eg. themed icons
. 'about:' uris: about, blank, cache, config, plugins
. Check specific bookmarks for updates automatically (extension) . Check specific bookmarks for updates automatically (extension)
. Mark "new" as well as "actually modified" tabs specially (even over sessions) . Mark "new" as well as "actually modified" tabs specially (even over sessions)
. SearchEngine: "Show in context menu"
. Save screenshot of a document? . Save screenshot of a document?
. Right-click a textbox in a search form and choose 'add to websearch' . Right-click a textbox in a search form and choose 'add to websearch'
. Honor design principle "no warnings but undo of backups"? . Honor design principle "no warnings but undo of backups"?
@ -25,11 +85,9 @@ TODO:
. Protected tabs prompt when attempting to close them . Protected tabs prompt when attempting to close them
. Provide a 'sleep mode' after a crash where open documents are loaded manually . 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 . Option to run plugins or scripts only on demand, like NoScript, per-site
. Optional http redirection manually or on timeout . Optional http redirection manually or on timeout via SoupMessage::restarted
. Style: none, compatible (b/w), default, [styles], "media", ["media" styles], ... . Style: none, compatible (b/w), default, [styles], "media", ["media" styles]
. Mouse pointer coordinates in the status bar (extension) . Mouse pointer coordinates in the status bar (extension)
. Draw rectangle with the mouse, x/y/x2/y2 in the statusbar (extension) . Draw rectangle with the mouse, x/y/x2/y2 in the statusbar (extension)
. Private browsing mode (no browsing, download or search history)
. Shared bookmarks and config . Shared bookmarks and config
. Custom-mode, e.g. hide menubar and use help icon to have a help viewer
. Prevent dead tabs: download, aborted page . Prevent dead tabs: download, aborted page

View file

@ -2,21 +2,25 @@ This file is licensed under the terms of the expat license, see the file EXPAT.
+++ Translating Midori +++ +++ Translating Midori +++
If you want to translate Midori, here are a few helpful tips. The recommended tool for translating Midori is Transifex, which is what all
Xfce projects use. It makes the life of translators and developers easier.
That said, it is also possible to manually create or update a .po file and
send a .po or .diff file via email or Flyspray.
Either way the following instructions should get you started.
To update the localization template: There is no template in the repository. To create a localization template:
./waf build --update-po ./waf build --update-po
You can use the same command in the future to update the template. It is
recommended to do that always before you update localizations.
If you want to add a new language 'aa', create it like this: If you want to add a new language 'aa', create it like this:
cd po cd po
msginit -l aa_CC -o aa.po -i midori.pot msginit -l aa_CC -o aa.po -i midori.pot
sed -i 's/PACKAGE/midori/g' aa.po sed -i 's/PACKAGE/midori/g' aa.po
Make sure you add your language to the file po/LINGUAS.
Just open the file with a text editor and add your code.
To check your language 'aa' for errors, do this: To check your language 'aa' for errors, do this:
msgfmt -c --check-accelerators=_ aa.po msgfmt -c --check-accelerators=_ aa.po

View file

@ -1,10 +1,8 @@
div.suggestions { div.suggestions {
-moz-box-sizing: border-box; -webkit-appearance: listbox;
box-sizing: border-box;
border: 1px solid #cccccc;
text-align: left; text-align: left;
background-color: #ffffff;
position: absolute; position: absolute;
z-index: 999;
} }
div.suggestions div { div.suggestions div {
cursor: default; cursor: default;

View file

@ -38,7 +38,6 @@ function AutoSuggestControl(oTextbox /*:HTMLInputElement*/,
* @param bTypeAhead If the control should provide a type ahead suggestion. * @param bTypeAhead If the control should provide a type ahead suggestion.
*/ */
AutoSuggestControl.prototype.autosuggest = function (aSuggestions /*:Array*/) { AutoSuggestControl.prototype.autosuggest = function (aSuggestions /*:Array*/) {
//make sure theres at least one suggestion
if (aSuggestions.length > 0) { if (aSuggestions.length > 0) {
this.showSuggestions(aSuggestions); this.showSuggestions(aSuggestions);
} else { } else {
@ -51,29 +50,16 @@ AutoSuggestControl.prototype.autosuggest = function (aSuggestions /*:Array*/) {
* @scope private * @scope private
*/ */
AutoSuggestControl.prototype.createDropDown = function () { AutoSuggestControl.prototype.createDropDown = function () {
var oThis = this; var sDiv = document.getElementById("suggestions_box");
if (sDiv) {
//create the layer and assign styles this.layer = sDiv;
return;
}
this.layer = document.createElement("div"); this.layer = document.createElement("div");
this.layer.className = "suggestions"; this.layer.className = "suggestions";
this.layer.id = "suggestions_box";
this.layer.style.visibility = "hidden"; this.layer.style.visibility = "hidden";
this.layer.style.width = this.textbox.offsetWidth; this.layer.style.width = this.textbox.offsetWidth;
this.layer.onmousedown =
this.layer.onmouseup =
this.layer.onmouseover = function (oEvent) {
oEvent = oEvent || window.event;
oTarget = oEvent.target || oEvent.srcElement;
if (oEvent.type == "mousedown") {
oThis.textbox.value = oTarget.firstChild.nodeValue;
oThis.hideSuggestions();
} else if (oEvent.type == "mouseover") {
oThis.highlightSuggestion(oTarget);
} else {
oThis.textbox.focus();
}
};
document.body.appendChild(this.layer); document.body.appendChild(this.layer);
}; };
@ -85,12 +71,10 @@ AutoSuggestControl.prototype.createDropDown = function () {
AutoSuggestControl.prototype.getLeft = function () /*:int*/ { AutoSuggestControl.prototype.getLeft = function () /*:int*/ {
var oNode = this.textbox; var oNode = this.textbox;
var iLeft = 0; var iLeft = 0;
while (oNode.tagName != "BODY") {
while(oNode.tagName != "BODY") {
iLeft += oNode.offsetLeft; iLeft += oNode.offsetLeft;
oNode = oNode.offsetParent; oNode = oNode.offsetParent;
} }
return iLeft; return iLeft;
}; };
@ -135,17 +119,15 @@ AutoSuggestControl.prototype.handleKeyDown = function (oEvent /*:Event*/) {
*/ */
AutoSuggestControl.prototype.handleKeyUp = function (oEvent /*:Event*/) { AutoSuggestControl.prototype.handleKeyUp = function (oEvent /*:Event*/) {
var iKeyCode = oEvent.keyCode; var iKeyCode = oEvent.keyCode;
//for backspace (8) and delete (46), shows suggestions without typeahead
if (iKeyCode == 8 || iKeyCode == 46) { if (iKeyCode == 8 || iKeyCode == 46) {
this.provider.requestSuggestions(this); this.provider.requestSuggestions(this);
//make sure not to interfere with non-character keys //make sure not to interfere with non-character keys
} else if (iKeyCode < 32 || (iKeyCode >= 33 && iKeyCode < 46) || (iKeyCode >= 112 && iKeyCode <= 123) ) { } else if (iKeyCode < 32 || (iKeyCode >= 33 && iKeyCode < 46) || (iKeyCode >= 112 && iKeyCode <= 123) ) {
//ignore //ignore
} else if (oEvent.ctrlKey) { } else if (oEvent.ctrlKey) {
iKeyCode = 0;
this.hideSuggestions(); this.hideSuggestions();
} else { } else {
//request suggestions from the suggestion provider with typeahead //request suggestions from the suggestion provider
this.provider.requestSuggestions(this); this.provider.requestSuggestions(this);
} }
}; };
@ -221,11 +203,15 @@ AutoSuggestControl.prototype.init = function () {
AutoSuggestControl.prototype.nextSuggestion = function () { AutoSuggestControl.prototype.nextSuggestion = function () {
var cSuggestionNodes = this.layer.childNodes; var cSuggestionNodes = this.layer.childNodes;
if (cSuggestionNodes.length > 0 && this.cur < cSuggestionNodes.length-1) { if (!cSuggestionNodes.length)
var oNode = cSuggestionNodes[++this.cur]; return;
this.highlightSuggestion(oNode);
this.textbox.value = oNode.firstChild.nodeValue; if (this.cur == cSuggestionNodes.length-1)
} this.cur = -1;
var oNode = cSuggestionNodes[++this.cur];
this.highlightSuggestion(oNode);
this.textbox.value = oNode.firstChild.nodeValue;
}; };
/** /**
@ -236,24 +222,15 @@ AutoSuggestControl.prototype.nextSuggestion = function () {
AutoSuggestControl.prototype.previousSuggestion = function () { AutoSuggestControl.prototype.previousSuggestion = function () {
var cSuggestionNodes = this.layer.childNodes; var cSuggestionNodes = this.layer.childNodes;
if (cSuggestionNodes.length > 0 && this.cur > 0) { if (!cSuggestionNodes.length)
var oNode = cSuggestionNodes[--this.cur]; return;
this.highlightSuggestion(oNode);
this.textbox.value = oNode.firstChild.nodeValue;
}
};
/** if (this.cur == -1 || this.cur == 0)
* Selects a range of text in the textbox. this.cur = cSuggestionNodes.length;
* @scope public
* @param iStart The start index (base 0) of the selection. var oNode = cSuggestionNodes[--this.cur];
* @param iLength The number of characters to select. this.highlightSuggestion(oNode);
*/ this.textbox.value = oNode.firstChild.nodeValue;
AutoSuggestControl.prototype.selectRange = function (iStart /*:int*/, iLength /*:int*/) {
if (this.textbox.setSelectionRange) {
this.textbox.setSelectionRange(iStart, iLength);
}
this.textbox.focus();
}; };
/** /**
@ -263,6 +240,7 @@ AutoSuggestControl.prototype.selectRange = function (iStart /*:int*/, iLength /*
* @param aSuggestions An array of suggestions for the control. * @param aSuggestions An array of suggestions for the control.
*/ */
AutoSuggestControl.prototype.showSuggestions = function (aSuggestions /*:Array*/) { AutoSuggestControl.prototype.showSuggestions = function (aSuggestions /*:Array*/) {
var oThis = this;
var oDiv = null; var oDiv = null;
this.layer.innerHTML = ""; //clear contents of the layer this.layer.innerHTML = ""; //clear contents of the layer
@ -275,6 +253,22 @@ AutoSuggestControl.prototype.showSuggestions = function (aSuggestions /*:Array*/
this.layer.style.left = this.getLeft() + "px"; this.layer.style.left = this.getLeft() + "px";
this.layer.style.top = (this.getTop()+this.textbox.offsetHeight) + "px"; this.layer.style.top = (this.getTop()+this.textbox.offsetHeight) + "px";
this.layer.style.visibility = "visible"; this.layer.style.visibility = "visible";
this.layer.style.position = "absolute";
this.layer.onmousedown =
this.layer.onmouseup =
this.layer.onmouseover = function (oEvent) {
var oEvent = oEvent || window.event;
var oTarget = oEvent.target || oEvent.srcElement;
if (oEvent.type == "mousedown") {
oThis.textbox.value = oTarget.firstChild.nodeValue;
oThis.hideSuggestions();
} else if (oEvent.type == "mouseover") {
oThis.highlightSuggestion(oTarget);
} else {
oThis.textbox.focus();
}
};
}; };
/** /**
@ -288,14 +282,13 @@ FormSuggestions.prototype.requestSuggestions = function (oAutoSuggestControl /*:
if (!this.suggestions) if (!this.suggestions)
return; return;
if (!sTextboxValue.length)
return;
//search for matching suggestions //search for matching suggestions
for (var i=0; i < this.suggestions.length; i++) { if (sTextboxValue.length)
if (this.suggestions[i].toLowerCase().indexOf(sTextboxValue) == 0) { for (var i=0; i < this.suggestions.length; i++) {
aSuggestions.push(this.suggestions[i]); if (this.suggestions[i].toLowerCase().indexOf(sTextboxValue) == 0) {
} aSuggestions.push(this.suggestions[i]);
}
} }
//provide suggestions to the control //provide suggestions to the control
oAutoSuggestControl.autosuggest(aSuggestions); oAutoSuggestControl.autosuggest(aSuggestions);
@ -308,9 +301,11 @@ function initSuggestions () {
{ {
var ename = inputs[i].getAttribute("name"); var ename = inputs[i].getAttribute("name");
var eid = inputs[i].getAttribute("id"); var eid = inputs[i].getAttribute("id");
var autocomplete = inputs[i].getAttribute ("autocomplete");
if (!ename && eid) if (!ename && eid)
ename=eid; ename=eid;
if (inputs[i].type == "text") if (inputs[i].type == "text" && autocomplete != "off")
var smth = new AutoSuggestControl(inputs[i], new FormSuggestions(ename)); var smth = new AutoSuggestControl (inputs[i], new FormSuggestions (ename));
} }
}; };

File diff suppressed because it is too large Load diff

View file

@ -64,13 +64,23 @@ colorful_tabs_browser_add_tab_cb (MidoriBrowser* browser,
G_CALLBACK (colorful_tabs_view_notify_uri_cb), extension); G_CALLBACK (colorful_tabs_view_notify_uri_cb), extension);
} }
static void
colorful_tabs_app_add_browser_cb (MidoriApp* app,
MidoriBrowser* browser,
MidoriExtension* extension);
static void static void
colorful_tabs_deactivate_cb (MidoriExtension* extension, colorful_tabs_deactivate_cb (MidoriExtension* extension,
MidoriBrowser* browser) MidoriBrowser* browser)
{ {
guint i; guint i;
GtkWidget* view; GtkWidget* view;
MidoriApp* app = midori_extension_get_app (extension);
g_signal_handlers_disconnect_by_func (
app, colorful_tabs_app_add_browser_cb, extension);
g_signal_handlers_disconnect_by_func (
browser, colorful_tabs_browser_add_tab_cb, extension);
g_signal_handlers_disconnect_by_func ( g_signal_handlers_disconnect_by_func (
extension, colorful_tabs_deactivate_cb, browser); extension, colorful_tabs_deactivate_cb, browser);
i = 0; i = 0;
@ -102,6 +112,7 @@ colorful_tabs_app_add_browser_cb (MidoriApp* app,
G_CALLBACK (colorful_tabs_deactivate_cb), browser); G_CALLBACK (colorful_tabs_deactivate_cb), browser);
} }
static void static void
colorful_tabs_activate_cb (MidoriExtension* extension, colorful_tabs_activate_cb (MidoriExtension* extension,
MidoriApp* app) MidoriApp* app)

View file

@ -10,6 +10,7 @@
*/ */
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <midori/midori.h> #include <midori/midori.h>
#include <midori/gtkiconentry.h> #include <midori/gtkiconentry.h>
@ -67,6 +68,8 @@ static void cm_tree_popup_collapse_activate_cb(GtkMenuItem *item, CookieManagerP
static void cm_tree_popup_expand_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_filter_tree(CookieManagerPage *cmp, const gchar *filter_text);
typedef void (*CMPathWalkFunc) (GtkTreePath *path);
G_DEFINE_TYPE_WITH_CODE(CookieManagerPage, cookie_manager_page, GTK_TYPE_VBOX, G_DEFINE_TYPE_WITH_CODE(CookieManagerPage, cookie_manager_page, GTK_TYPE_VBOX,
G_IMPLEMENT_INTERFACE(MIDORI_TYPE_VIEWABLE, G_IMPLEMENT_INTERFACE(MIDORI_TYPE_VIEWABLE,
@ -225,7 +228,6 @@ static void cookie_manager_page_set_property(GObject *object, guint prop_id, con
COOKIE_MANAGER_COL_VISIBLE); COOKIE_MANAGER_COL_VISIBLE);
gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview), GTK_TREE_MODEL(priv->filter)); gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview), GTK_TREE_MODEL(priv->filter));
g_object_unref(priv->filter); g_object_unref(priv->filter);
break; break;
} }
case PROP_PARENT: case PROP_PARENT:
@ -304,6 +306,28 @@ static void cm_set_button_sensitiveness(CookieManagerPage *cmp, gboolean set)
} }
static void cm_free_selection_list(GList *rows, GFunc func)
{
g_list_foreach(rows, func, NULL);
g_list_free(rows);
}
/* Fast version of g_list_length(). It only checks for the first few elements of
* the list and returns the length 0, 1 or 2 where 2 means 2 elements or more. */
static gint cm_list_length(GList *list)
{
if (list == NULL)
return 0;
else if (list->next == NULL)
return 1;
else if (list->next != NULL)
return 2;
return 0; /* safe default */
}
static void cm_tree_popup_collapse_activate_cb(GtkMenuItem *item, CookieManagerPage *cmp) static void cm_tree_popup_collapse_activate_cb(GtkMenuItem *item, CookieManagerPage *cmp)
{ {
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp); CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp);
@ -342,72 +366,165 @@ static void cm_delete_cookie(CookieManagerPage *cmp, GtkTreeModel *model, GtkTre
} }
static void cm_button_delete_clicked_cb(GtkToolButton *button, CookieManagerPage *cmp) static gboolean cm_try_to_select(CMPathWalkFunc path_func, GtkTreeSelection *selection,
GtkTreeModel *model, GtkTreePath *path)
{
GtkTreeIter iter;
if (gtk_tree_path_get_depth(path) <= 0) /* sanity check */
return FALSE;
/* modify the path using the passed function */
if (path_func != NULL)
path_func(path);
if (gtk_tree_path_get_depth(path) <= 0) /* sanity check */
return FALSE;
/* check whether the path points to something valid and if so, select it */
if (gtk_tree_model_get_iter(model, &iter, path))
{
GtkTreeView *treeview = gtk_tree_selection_get_tree_view(selection);
gboolean was_expanded = gtk_tree_view_row_expanded(treeview, path);
/* to get gtk_tree_selection_select_path() working, we need to expand the row first
* if it isn't expanded yet, at least when the row is a parent item */
if (! was_expanded)
gtk_tree_view_expand_to_path(treeview, path);
gtk_tree_selection_select_path(selection, path);
if (! was_expanded) /* restore the previous state */
gtk_tree_view_collapse_row(treeview, path);
return TRUE;
}
return FALSE;
}
/* select an item after deletion */
static void cm_select_path(CookieManagerPage *cmp, GtkTreeModel *model, GtkTreePath *path)
{
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp);
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview));
CMPathWalkFunc path_funcs[] = {
(CMPathWalkFunc) gtk_tree_path_prev, (CMPathWalkFunc) gtk_tree_path_up,
(CMPathWalkFunc) gtk_tree_path_next, NULL };
CMPathWalkFunc *path_func;
/* first try selecting the item directly to which path points */
if (! cm_try_to_select(NULL, selection, model, path))
{ /* if this failed, modify the path until we found something valid */
path_func = path_funcs;
while (*path_func != NULL)
{
if (cm_try_to_select(*path_func, selection, model, path))
break;
path_func++;
}
}
}
static void cm_delete_item(CookieManagerPage *cmp)
{ {
GtkTreeIter iter, iter_store, child; GtkTreeIter iter, iter_store, child;
GtkTreeModel *model; GtkTreeModel *model;
GtkTreePath *path, *last_path;
GtkTreeSelection *selection; GtkTreeSelection *selection;
GList *rows, *row;
GList *refs = NULL;
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp); CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp);
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview)); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview));
if (! gtk_tree_selection_get_selected(selection, &model, &iter)) rows = gtk_tree_selection_get_selected_rows(selection, &model);
if (cm_list_length(rows) == 0)
return; return;
if (gtk_tree_model_iter_has_child(model, &iter)) last_path = gtk_tree_path_copy(g_list_nth_data(rows, 0));
{
GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
while (gtk_tree_model_iter_children(model, &child, &iter)) /* as paths will change during delete, first create GtkTreeRowReferences for
* all selected rows */
row = rows;
do
{
refs = g_list_append(refs, gtk_tree_row_reference_new(model, (GtkTreePath*) (row->data)));
} while ((row = row->next) != NULL);
row = refs;
do
{
/* get iter */
path = gtk_tree_row_reference_get_path((GtkTreeRowReference*) row->data);
if (path == NULL)
continue;
gtk_tree_model_get_iter(model, &iter, path);
if (gtk_tree_model_iter_has_child(model, &iter))
{ {
cm_delete_cookie(cmp, model, &child); while (gtk_tree_model_iter_children(model, &child, &iter))
cm_store_remove(cmp, &child); {
/* we retrieve again the iter at path because it got invalid by the delete operation */ cm_delete_cookie(cmp, model, &child);
gtk_tree_model_get_iter(model, &iter, path); cm_store_remove(cmp, &child);
/* we retrieve again the iter at path because it got invalid by the delete operation */
gtk_tree_model_get_iter(model, &iter, path);
}
/* remove/hide the parent */
gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(priv->filter),
&iter_store, &iter);
if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(priv->store), &iter_store))
gtk_tree_store_set(priv->store, &iter_store, COOKIE_MANAGER_COL_VISIBLE, FALSE, -1);
else
cm_store_remove(cmp, &iter);
}
else
{
GtkTreePath *path_store, *path_model;
gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(priv->filter),
&iter_store, &iter);
path_store = gtk_tree_model_get_path(GTK_TREE_MODEL(priv->store), &iter_store);
path_model = gtk_tree_model_get_path(model, &iter);
cm_delete_cookie(cmp, model, &iter);
gtk_tree_store_remove(priv->store, &iter_store);
/* check whether the parent still has children, otherwise delete it */
if (gtk_tree_path_up(path_store))
{
gtk_tree_model_get_iter(GTK_TREE_MODEL(priv->store), &iter_store, path_store);
if (! gtk_tree_model_iter_has_child(GTK_TREE_MODEL(priv->store), &iter_store))
/* remove the empty parent */
gtk_tree_store_remove(priv->store, &iter_store);
}
/* now for the filter model */
if (gtk_tree_path_up(path_model))
{
gtk_tree_model_get_iter(model, &iter, path_model);
if (! gtk_tree_model_iter_has_child(model, &iter))
{
gtk_tree_model_filter_convert_iter_to_child_iter(
GTK_TREE_MODEL_FILTER(priv->filter), &iter_store, &iter);
/* hide the empty parent */
gtk_tree_store_set(priv->store, &iter_store, COOKIE_MANAGER_COL_VISIBLE, FALSE, -1);
}
}
gtk_tree_path_free(path_store);
gtk_tree_path_free(path_model);
} }
gtk_tree_path_free(path); gtk_tree_path_free(path);
/* remove/hide the parent */ } while ((row = row->next) != NULL);
gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(priv->filter), cm_free_selection_list(rows, (GFunc) gtk_tree_path_free);
&iter_store, &iter); cm_free_selection_list(refs, (GFunc) gtk_tree_row_reference_free);
if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(priv->store), &iter_store))
gtk_tree_store_set(priv->store, &iter_store, COOKIE_MANAGER_COL_VISIBLE, FALSE, -1);
else
cm_store_remove(cmp, &iter);
}
else
{
GtkTreePath *path_store, *path_model;
gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(priv->filter), cm_select_path(cmp, model, last_path);
&iter_store, &iter); gtk_tree_path_free(last_path);
path_store = gtk_tree_model_get_path(GTK_TREE_MODEL(priv->store), &iter_store); }
path_model = gtk_tree_model_get_path(model, &iter);
cm_delete_cookie(cmp, model, &iter);
gtk_tree_store_remove(priv->store, &iter_store);
/* check whether the parent still has children, otherwise delete it */ static void cm_button_delete_clicked_cb(GtkToolButton *button, CookieManagerPage *cmp)
if (gtk_tree_path_up(path_store)) {
{ cm_delete_item(cmp);
gtk_tree_model_get_iter(GTK_TREE_MODEL(priv->store), &iter_store, path_store);
if (! gtk_tree_model_iter_has_child(GTK_TREE_MODEL(priv->store), &iter_store))
/* remove the empty parent */
gtk_tree_store_remove(priv->store, &iter_store);
}
/* now for the filter model */
if (gtk_tree_path_up(path_model))
{
gtk_tree_model_get_iter(model, &iter, path_model);
if (! gtk_tree_model_iter_has_child(model, &iter))
{
gtk_tree_model_filter_convert_iter_to_child_iter(
GTK_TREE_MODEL_FILTER(priv->filter), &iter_store, &iter);
/* hide the empty parent */
gtk_tree_store_set(priv->store, &iter_store, COOKIE_MANAGER_COL_VISIBLE, FALSE, -1);
}
}
gtk_tree_path_free(path_store);
gtk_tree_path_free(path_model);
}
} }
@ -438,11 +555,12 @@ static void cm_delete_all_cookies_real(CookieManagerPage *cmp)
else else
cm_store_remove(cmp, &iter); cm_store_remove(cmp, &iter);
} }
gtk_tree_path_free(path_first);
/* now that we deleted all matching cookies, we reset the filter */ /* now that we deleted all matching cookies, we reset the filter */
gtk_entry_set_text(GTK_ENTRY(priv->filter_entry), ""); gtk_entry_set_text(GTK_ENTRY(priv->filter_entry), "");
cm_set_button_sensitiveness(cmp, FALSE); cm_set_button_sensitiveness(cmp, FALSE);
cm_select_path(cmp, model, path_first);
gtk_tree_path_free(path_first);
} }
@ -478,6 +596,12 @@ static void cm_button_delete_all_clicked_cb(GtkToolButton *button, CookieManager
} }
static const gchar *cm_skip_leading_dot(const gchar *text)
{
return (*text == '.') ? text + 1 : text;
}
static void cm_tree_drag_data_get_cb(GtkWidget *widget, GdkDragContext *drag_context, static void cm_tree_drag_data_get_cb(GtkWidget *widget, GdkDragContext *drag_context,
GtkSelectionData *data, guint info, guint ltime, GtkSelectionData *data, guint info, guint ltime,
CookieManagerPage *cmp) CookieManagerPage *cmp)
@ -485,11 +609,18 @@ static void cm_tree_drag_data_get_cb(GtkWidget *widget, GdkDragContext *drag_con
GtkTreeIter iter, iter_store; GtkTreeIter iter, iter_store;
GtkTreeSelection *selection; GtkTreeSelection *selection;
GtkTreeModel *model; GtkTreeModel *model;
GList *rows;
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp); CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp);
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview)); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview));
if (! gtk_tree_selection_get_selected(selection, &model, &iter)) rows = gtk_tree_selection_get_selected_rows(selection, &model);
if (cm_list_length(rows) != 1)
{
cm_free_selection_list(rows, (GFunc) gtk_tree_path_free);
return; return;
}
/* get iter */
gtk_tree_model_get_iter(model, &iter, (GtkTreePath*) (g_list_nth_data(rows, 0)));
gtk_tree_model_filter_convert_iter_to_child_iter( gtk_tree_model_filter_convert_iter_to_child_iter(
GTK_TREE_MODEL_FILTER(model), &iter_store, &iter); GTK_TREE_MODEL_FILTER(model), &iter_store, &iter);
@ -497,18 +628,25 @@ static void cm_tree_drag_data_get_cb(GtkWidget *widget, GdkDragContext *drag_con
if (gtk_tree_store_iter_is_valid(priv->store, &iter_store)) if (gtk_tree_store_iter_is_valid(priv->store, &iter_store))
{ {
SoupCookie *cookie; SoupCookie *cookie;
gchar *name, *text; gchar *name;
const gchar *text;
gtk_tree_model_get(model, &iter, gtk_tree_model_get(model, &iter,
COOKIE_MANAGER_COL_NAME, &name, COOKIE_MANAGER_COL_NAME, &name,
COOKIE_MANAGER_COL_COOKIE, &cookie, COOKIE_MANAGER_COL_COOKIE, &cookie,
-1); -1);
if (cookie == NULL && name != NULL) if (name != NULL)
{ {
/* skip a leading dot */ GtkTreeIter parent;
text = (*name == '.') ? name + 1 : name; /* get the name of the parent item which should be a domain item */
if (cookie != NULL && gtk_tree_model_iter_parent(model, &parent, &iter))
{
g_free(name);
gtk_tree_model_get(model, &parent, COOKIE_MANAGER_COL_NAME, &name, -1);
}
text = cm_skip_leading_dot(name);
gtk_selection_data_set_text(data, text, -1); gtk_selection_data_set_text(data, text, -1);
} }
g_free(name); g_free(name);
@ -552,6 +690,24 @@ static gchar *cm_get_cookie_description_text(SoupCookie *cookie)
} }
static gchar *cm_get_domain_description_text(const gchar *domain, gint cookie_count)
{
gchar *str, *text;
domain = cm_skip_leading_dot(domain);
text = g_markup_printf_escaped(
_("<b>Domain</b>: %s\n<b>Cookies</b>: %d"),
domain, cookie_count);
str = g_strconcat(text, "\n\n\n\n", NULL);
g_free(text);
return str;
}
#if GTK_CHECK_VERSION(2, 12, 0) #if GTK_CHECK_VERSION(2, 12, 0)
static gboolean cm_tree_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_mode, static gboolean cm_tree_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_mode,
GtkTooltip *tooltip, CookieManagerPage *cmp) GtkTooltip *tooltip, CookieManagerPage *cmp)
@ -683,24 +839,36 @@ static void cm_filter_entry_clear_icon_released_cb(GtkIconEntry *e, gint pos, gi
static void cm_tree_selection_changed_cb(GtkTreeSelection *selection, CookieManagerPage *cmp) static void cm_tree_selection_changed_cb(GtkTreeSelection *selection, CookieManagerPage *cmp)
{ {
GList *rows;
GtkTreeIter iter, iter_store; GtkTreeIter iter, iter_store;
GtkTreeModel *model; GtkTreeModel *model;
gchar *text; gchar *text, *name;
gboolean valid = TRUE; gboolean valid = TRUE;
gboolean delete_possible = FALSE; gboolean delete_possible = TRUE;
guint rows_len;
SoupCookie *cookie; SoupCookie *cookie;
CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp); CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp);
if (! gtk_tree_selection_get_selected(selection, &model, &iter)) rows = gtk_tree_selection_get_selected_rows(selection, &model);
rows_len = cm_list_length(rows);
if (rows_len == 0)
{
valid = FALSE; valid = FALSE;
else delete_possible = FALSE;
}
else if (rows_len == 1)
{
/* get iter */
gtk_tree_model_get_iter(model, &iter, (GtkTreePath*) (g_list_nth_data(rows, 0)));
gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(model), gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(model),
&iter_store, &iter); &iter_store, &iter);
}
else
valid = FALSE;
if (valid && gtk_tree_store_iter_is_valid(priv->store, &iter_store)) if (valid && gtk_tree_store_iter_is_valid(priv->store, &iter_store))
{ {
delete_possible = TRUE;
gtk_tree_model_get(model, &iter, COOKIE_MANAGER_COL_COOKIE, &cookie, -1); gtk_tree_model_get(model, &iter, COOKIE_MANAGER_COL_COOKIE, &cookie, -1);
if (cookie != NULL) if (cookie != NULL)
{ {
@ -711,13 +879,27 @@ static void cm_tree_selection_changed_cb(GtkTreeSelection *selection, CookieMana
g_free(text); g_free(text);
} }
else else
valid = FALSE; {
gtk_tree_model_get(model, &iter, COOKIE_MANAGER_COL_NAME, &name, -1);
if (name != NULL)
{
gint cookie_count = gtk_tree_model_iter_n_children(model, &iter);
text = cm_get_domain_description_text(name, cookie_count);
gtk_label_set_markup(GTK_LABEL(priv->desc_label), text);
g_free(text);
g_free(name);
}
}
} }
/* This is a bit hack'ish but we add some empty lines to get a minimum height of the /* This is a bit hack'ish but we add some empty lines to get a minimum height of the
* label at the bottom without any font size calculation. */ * label at the bottom without any font size calculation. */
if (! valid) if (! valid)
gtk_label_set_text(GTK_LABEL(priv->desc_label), CM_EMPTY_LABEL_TEXT); gtk_label_set_text(GTK_LABEL(priv->desc_label), CM_EMPTY_LABEL_TEXT);
cm_set_button_sensitiveness(cmp, delete_possible); cm_set_button_sensitiveness(cmp, delete_possible);
cm_free_selection_list(rows, (GFunc) gtk_tree_path_free);
} }
@ -760,19 +942,36 @@ static gboolean cm_tree_button_release_event_cb(GtkWidget *widget, GdkEventButto
} }
static gboolean cm_tree_key_press_cb(GtkWidget *widget, GdkEventKey *event, CookieManagerPage *cmp)
{
if (event->keyval == GDK_Delete && !
(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)))
{
cm_delete_item(cmp);
return TRUE;
}
return FALSE;
}
static gboolean cm_tree_button_press_event_cb(GtkWidget *widget, GdkEventButton *ev, static gboolean cm_tree_button_press_event_cb(GtkWidget *widget, GdkEventButton *ev,
CookieManagerPage *cmp) CookieManagerPage *cmp)
{ {
gboolean ret = FALSE;
if (ev->type == GDK_2BUTTON_PRESS) if (ev->type == GDK_2BUTTON_PRESS)
{ {
GtkTreeSelection *selection; GtkTreeSelection *selection;
GtkTreeModel *model; GtkTreeModel *model;
GtkTreeIter iter; GtkTreeIter iter;
GList *rows;
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
rows = gtk_tree_selection_get_selected_rows(selection, &model);
if (gtk_tree_selection_get_selected(selection, &model, &iter)) if (cm_list_length(rows) == 1)
{ {
/* get iter */
gtk_tree_model_get_iter(model, &iter, (GtkTreePath*) (g_list_nth_data(rows, 0)));
/* double click on parent node expands/collapses it */ /* double click on parent node expands/collapses it */
if (gtk_tree_model_iter_has_child(model, &iter)) if (gtk_tree_model_iter_has_child(model, &iter))
{ {
@ -785,12 +984,32 @@ static gboolean cm_tree_button_press_event_cb(GtkWidget *widget, GdkEventButton
gtk_tree_path_free(path); gtk_tree_path_free(path);
return TRUE; ret = TRUE;
} }
} }
cm_free_selection_list(rows, (GFunc) gtk_tree_path_free);
} }
return ret;
}
return FALSE;
static void cm_tree_render_text_cb(GtkTreeViewColumn *column, GtkCellRenderer *renderer, GtkTreeModel *model,
GtkTreeIter *iter, gpointer data)
{
gchar *name;
gtk_tree_model_get(model, iter, COOKIE_MANAGER_COL_NAME, &name, -1);
if (name != NULL && *name != '.')
{
gchar *display_name = g_strconcat(" ", name, NULL);
g_object_set(renderer, "text", display_name, NULL);
g_free(display_name);
}
else
g_object_set(renderer, "text", name, NULL);
g_free(name);
} }
@ -812,6 +1031,8 @@ static GtkWidget *cm_tree_prepare(CookieManagerPage *cmp)
gtk_tree_view_column_set_sort_indicator(column, TRUE); gtk_tree_view_column_set_sort_indicator(column, TRUE);
gtk_tree_view_column_set_sort_column_id(column, COOKIE_MANAGER_COL_NAME); gtk_tree_view_column_set_sort_column_id(column, COOKIE_MANAGER_COL_NAME);
gtk_tree_view_column_set_resizable(column, TRUE); gtk_tree_view_column_set_resizable(column, TRUE);
gtk_tree_view_column_set_cell_data_func(column, renderer,
(GtkTreeCellDataFunc) cm_tree_render_text_cb, NULL, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
@ -820,10 +1041,11 @@ static GtkWidget *cm_tree_prepare(CookieManagerPage *cmp)
/* selection handling */ /* selection handling */
sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
/* signals */ /* signals */
g_signal_connect(sel, "changed", G_CALLBACK(cm_tree_selection_changed_cb), cmp); g_signal_connect(sel, "changed", G_CALLBACK(cm_tree_selection_changed_cb), cmp);
g_signal_connect(treeview, "key-press-event", G_CALLBACK(cm_tree_key_press_cb), cmp);
g_signal_connect(treeview, "button-press-event", G_CALLBACK(cm_tree_button_press_event_cb), cmp); g_signal_connect(treeview, "button-press-event", G_CALLBACK(cm_tree_button_press_event_cb), cmp);
g_signal_connect(treeview, "button-release-event", G_CALLBACK(cm_tree_button_release_event_cb), cmp); g_signal_connect(treeview, "button-release-event", G_CALLBACK(cm_tree_button_release_event_cb), cmp);
g_signal_connect(treeview, "popup-menu", G_CALLBACK(cm_tree_popup_menu_cb), cmp); g_signal_connect(treeview, "popup-menu", G_CALLBACK(cm_tree_popup_menu_cb), cmp);
@ -843,7 +1065,6 @@ static GtkWidget *cm_tree_prepare(CookieManagerPage *cmp)
GDK_ACTION_COPY GDK_ACTION_COPY
); );
gtk_drag_source_add_text_targets(treeview); gtk_drag_source_add_text_targets(treeview);
/*gtk_drag_source_add_uri_targets(treeview);*/
g_signal_connect(treeview, "drag-data-get", G_CALLBACK(cm_tree_drag_data_get_cb), cmp); g_signal_connect(treeview, "drag-data-get", G_CALLBACK(cm_tree_drag_data_get_cb), cmp);
/* popup menu */ /* popup menu */

View file

@ -1,203 +0,0 @@
/*
Copyright (C) 2009 Alexander Butenko <a.butenka@gmail.com>
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.
*/
#include <midori/midori.h>
#include "config.h"
#include <glib/gstdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#define MAXHOSTS 50
static gchar* hosts = NULL;
static int host_count;
static bool
dnsprefetch_do_prefetch (const char* uri)
{
SoupURI* s_uri;
if (!uri)
return FALSE;
s_uri = soup_uri_new (uri);
if (!s_uri || !s_uri->host)
return FALSE;
#if GLIB_CHECK_VERSION (2, 22, 0)
if (g_hostname_is_ip_address (s_uri->host))
#else
if (g_ascii_isdigit (s_uri->host[0]) && g_strstr_len (s_uri->host, 4, "."))
#endif
{
soup_uri_free (s_uri);
return FALSE;
}
if (!g_str_has_prefix (uri, "http"))
{
soup_uri_free (s_uri);
return FALSE;
}
if (!g_regex_match_simple (s_uri->host, hosts,
G_REGEX_CASELESS, G_REGEX_MATCH_NOTEMPTY))
{
SoupAddress* address;
gchar* new_hosts;
address = soup_address_new (s_uri->host, SOUP_ADDRESS_ANY_PORT);
soup_address_resolve_async (address, 0, 0, 0, 0);
g_object_unref (address);
if (host_count > MAXHOSTS)
{
katze_assign (hosts, g_strdup (""));
host_count = 0;
}
host_count++;
new_hosts = g_strdup_printf ("%s|%s", hosts, s_uri->host);
katze_assign (hosts, new_hosts);
}
soup_uri_free (s_uri);
return TRUE;
}
static void
dnsprefetch_prefetch_cb (WebKitWebView* web_view,
const gchar* title,
const char* uri,
gpointer user_data)
{
dnsprefetch_do_prefetch (uri);
}
static void
dnsprefetch_add_tab_cb (MidoriBrowser* browser,
MidoriView* view)
{
GtkWidget* web_view = gtk_bin_get_child (GTK_BIN (view));
g_signal_connect (web_view, "hovering-over-link",
G_CALLBACK (dnsprefetch_prefetch_cb), 0);
}
static void
dnsprefetch_deactivate_cb (MidoriExtension* extension,
MidoriBrowser* browser);
static void
dnsprefetch_add_tab_foreach_cb (MidoriView* view,
MidoriBrowser* browser)
{
dnsprefetch_add_tab_cb (browser, view);
}
static void
dnsprefetch_app_add_browser_cb (MidoriApp* app,
MidoriBrowser* browser,
MidoriExtension* extension)
{
midori_browser_foreach (browser,
(GtkCallback)dnsprefetch_add_tab_foreach_cb, browser);
g_signal_connect (browser, "add-tab",
G_CALLBACK (dnsprefetch_add_tab_cb), 0);
g_signal_connect (extension, "deactivate",
G_CALLBACK (dnsprefetch_deactivate_cb), browser);
}
static void
dnsprefetch_deactivate_tabs (MidoriView* view,
MidoriBrowser* browser)
{
GtkWidget* web_view = gtk_bin_get_child (GTK_BIN (view));
g_signal_handlers_disconnect_by_func (
browser, dnsprefetch_add_tab_cb, 0);
g_signal_handlers_disconnect_by_func (
web_view, dnsprefetch_do_prefetch, 0);
}
static void
dnsprefetch_deactivate_cb (MidoriExtension* extension,
MidoriBrowser* browser)
{
MidoriApp* app = midori_extension_get_app (extension);
katze_assign (hosts, g_strdup (""));
host_count = 0;
g_signal_handlers_disconnect_by_func (
extension, dnsprefetch_deactivate_cb, browser);
g_signal_handlers_disconnect_by_func (
app, dnsprefetch_app_add_browser_cb, extension);
midori_browser_foreach (browser, (GtkCallback)dnsprefetch_deactivate_tabs, browser);
}
static void
dnsprefetch_activate_cb (MidoriExtension* extension,
MidoriApp* app)
{
KatzeArray* browsers;
MidoriBrowser* browser;
guint i;
katze_assign (hosts, g_strdup (""));
host_count = 0;
browsers = katze_object_get_object (app, "browsers");
i = 0;
while ((browser = katze_array_get_nth_item (browsers, i++)))
dnsprefetch_app_add_browser_cb (app, browser, extension);
g_signal_connect (app, "add-browser",
G_CALLBACK (dnsprefetch_app_add_browser_cb), extension);
g_object_unref (browsers);
}
#if G_ENABLE_DEBUG
static void
dnsprefetch_parse (void)
{
g_assert (!dnsprefetch_do_prefetch (NULL));
g_assert (dnsprefetch_do_prefetch ("http://google.com"));
g_assert (dnsprefetch_do_prefetch ("http://google.com"));
g_assert (dnsprefetch_do_prefetch ("http://googlecom"));
g_assert (dnsprefetch_do_prefetch ("http://1kino.com"));
g_assert (dnsprefetch_do_prefetch ("http://"));
g_assert (!dnsprefetch_do_prefetch ("http:/"));
g_assert (!dnsprefetch_do_prefetch ("http"));
g_assert (!dnsprefetch_do_prefetch ("ftp://ftphost.org"));
g_assert (!dnsprefetch_do_prefetch ("http://10.0.0.1"));
g_assert (!dnsprefetch_do_prefetch ("about:blank"));
g_assert (!dnsprefetch_do_prefetch ("javascript: alert()"));
}
void
extension_test (void)
{
katze_assign (hosts, g_strdup (""));
host_count = 0;
g_test_add_func ("/extensions/dnsprefetch/parse", dnsprefetch_parse);
}
#endif
MidoriExtension*
extension_init (void)
{
MidoriExtension* extension = g_object_new (MIDORI_TYPE_EXTENSION,
"name", _("DNS prefetching"),
"description", _("Prefetch IP addresses of hovered links"),
"version", "0.1",
"authors", "Alexander V. Butenko <a.butenka@gmail.com>",
NULL);
g_signal_connect (extension, "activate",
G_CALLBACK (dnsprefetch_activate_cb), NULL);
return extension;
}

View file

@ -263,7 +263,6 @@ parse_feed (gchar* data,
xerror->message); xerror->message);
xmlResetLastError (); xmlResetLastError ();
} }
xmlCleanupParser ();
xmlMemoryDump (); xmlMemoryDump ();
return *error ? FALSE : TRUE; return *error ? FALSE : TRUE;

View file

@ -105,6 +105,14 @@ feed_deactivate_cb (MidoriExtension* extension,
} }
} }
static void
feed_dialog_response_cb (GtkWidget* dialog,
gint response,
gpointer data)
{
gtk_widget_destroy (dialog);
}
static KatzeArray* static KatzeArray*
feed_add_item (KatzeArray* feeds, feed_add_item (KatzeArray* feeds,
const gchar* uri) const gchar* uri)
@ -126,8 +134,8 @@ feed_add_item (KatzeArray* feeds,
_("Feed '%s' already exists"), uri); _("Feed '%s' already exists"), uri);
gtk_window_set_title (GTK_WINDOW (dialog), EXTENSION_NAME); gtk_window_set_title (GTK_WINDOW (dialog), EXTENSION_NAME);
gtk_widget_show (dialog); gtk_widget_show (dialog);
g_signal_connect_swapped (dialog, "response", g_signal_connect (dialog, "response",
G_CALLBACK (gtk_widget_destroy), dialog); G_CALLBACK (feed_dialog_response_cb), NULL);
} }
else else

View file

@ -31,22 +31,24 @@ static gchar* jsforms;
static gboolean static gboolean
formhistory_prepare_js () formhistory_prepare_js ()
{ {
gchar* data_name;
gchar* data_path;
gchar* autosuggest; gchar* autosuggest;
gchar* style; gchar* style;
guint i; guint i;
gchar* file; gchar* file;
gchar* data_path = g_build_filename (MDATADIR, PACKAGE_NAME, "res", NULL); data_name = g_build_filename (PACKAGE_NAME, "res", NULL);
file = g_build_filename (data_path,"/autosuggestcontrol.js",NULL); data_path = sokoke_find_data_filename (data_name);
if (!g_file_test (file, G_FILE_TEST_EXISTS)) g_free (data_name);
file = g_build_filename (data_path, G_DIR_SEPARATOR_S, "autosuggestcontrol.js",NULL);
if (!g_file_get_contents (file, &autosuggest, NULL, NULL))
return FALSE; return FALSE;
g_file_get_contents (file, &autosuggest, NULL, NULL);
g_strchomp (autosuggest); g_strchomp (autosuggest);
file = g_build_filename (data_path,"/autosuggestcontrol.css",NULL); file = g_build_filename (data_path, G_DIR_SEPARATOR_S, "autosuggestcontrol.css",NULL);
if (!g_file_test (file, G_FILE_TEST_EXISTS)) if(!g_file_get_contents (file, &style, NULL, NULL))
return FALSE; return FALSE;
g_file_get_contents (file, &style, NULL, NULL);
g_strchomp (style); g_strchomp (style);
i = 0; i = 0;
while (style[i]) while (style[i])
@ -58,15 +60,17 @@ formhistory_prepare_js ()
jsforms = g_strdup_printf ( jsforms = g_strdup_printf (
"%s" "%s"
"window.addEventListener (\"load\", function () { initSuggestions (); }, true);"
"window.addEventListener ('DOMContentLoaded'," "window.addEventListener ('DOMContentLoaded',"
"function () {" "function () {"
"var mystyle = document.createElement(\"style\");" " if (document.getElementById('formhistory'))"
"mystyle.setAttribute(\"type\", \"text/css\");" " return;"
"mystyle.appendChild(document.createTextNode(\"%s\"));" " initSuggestions ();"
"var head = document.getElementsByTagName(\"head\")[0];" " var mystyle = document.createElement('style');"
"if (head) head.appendChild(mystyle);" " mystyle.setAttribute('type', 'text/css');"
"else document.documentElement.insertBefore(mystyle, document.documentElement.firstChild);" " mystyle.setAttribute('id', 'formhistory');"
" mystyle.appendChild(document.createTextNode('%s'));"
" var head = document.getElementsByTagName('head')[0];"
" if (head) head.appendChild(mystyle);"
"}, true);", "}, true);",
autosuggest, autosuggest,
style); style);
@ -191,7 +195,6 @@ formhistory_navigation_decision_cb (WebKitWebView* web_view,
WebKitWebPolicyDecision* decision, WebKitWebPolicyDecision* decision,
MidoriExtension* extension) MidoriExtension* extension)
{ {
JSContextRef js_context = webkit_web_frame_get_global_context (web_frame);
/* The script returns form data in the form "field_name|,|value|,|field_type". /* The script returns form data in the form "field_name|,|value|,|field_type".
We are handling only input fields with 'text' or 'password' type. We are handling only input fields with 'text' or 'password' type.
The field separator is "|||" */ The field separator is "|||" */
@ -203,18 +206,19 @@ formhistory_navigation_decision_cb (WebKitWebView* web_view,
" var eid = inputs[i].getAttribute('id');" " var eid = inputs[i].getAttribute('id');"
" if (!ename && eid)" " if (!ename && eid)"
" ename=eid;" " ename=eid;"
" out += ename+'|,|'+inputs[i].value +'|,|'+inputs[i].type +'|||';" " if (inputs[i].getAttribute('autocomplete') != 'off')"
" out += ename+'|,|'+inputs[i].value +'|,|'+inputs[i].type +'|||';"
" }" " }"
" }" " }"
" return out;" " return out;"
"}" "}"
"dumpForm (document.getElementsByTagName('input'))"; "dumpForm (document.getElementsByTagName('input'))";
if (webkit_web_navigation_action_get_reason (action) == WEBKIT_WEB_NAVIGATION_REASON_FORM_SUBMITTED if (webkit_web_navigation_action_get_reason (action) == WEBKIT_WEB_NAVIGATION_REASON_FORM_SUBMITTED)
|| webkit_web_navigation_action_get_reason (action) == WEBKIT_WEB_NAVIGATION_REASON_FORM_RESUBMITTED)
{ {
JSContextRef js_context = webkit_web_frame_get_global_context (web_frame);
gchar* value = sokoke_js_script_eval (js_context, script, NULL); gchar* value = sokoke_js_script_eval (js_context, script, NULL);
if (value) if (value && *value)
{ {
gpointer db = g_object_get_data (G_OBJECT (extension), "formhistory-db"); gpointer db = g_object_get_data (G_OBJECT (extension), "formhistory-db");
gchar** inputs = g_strsplit (value, "|||", 0); gchar** inputs = g_strsplit (value, "|||", 0);
@ -286,13 +290,15 @@ formhistory_session_request_queued_cb (SoupSession* session,
#endif #endif
static void static void
formhistory_window_object_cleared_cb (GtkWidget* web_view, formhistory_window_object_cleared_cb (WebKitWebView* web_view,
WebKitWebFrame* web_frame, WebKitWebFrame* web_frame,
JSContextRef js_context, JSContextRef js_context,
JSObjectRef js_window) JSObjectRef js_window)
{ {
webkit_web_view_execute_script (WEBKIT_WEB_VIEW (web_view), gchar* script;
formhistory_build_js ()); script = formhistory_build_js ();
sokoke_js_script_eval (js_context, script, NULL);
g_free (script);
} }
static void static void
@ -343,8 +349,6 @@ formhistory_deactivate_tabs (MidoriView* view,
MidoriExtension* extension) MidoriExtension* extension)
{ {
GtkWidget* web_view = gtk_bin_get_child (GTK_BIN (view)); GtkWidget* web_view = gtk_bin_get_child (GTK_BIN (view));
g_signal_handlers_disconnect_by_func (
browser, formhistory_add_tab_cb, extension);
g_signal_handlers_disconnect_by_func ( g_signal_handlers_disconnect_by_func (
web_view, formhistory_window_object_cleared_cb, NULL); web_view, formhistory_window_object_cleared_cb, NULL);
#if WEBKIT_CHECK_VERSION (1, 1, 4) #if WEBKIT_CHECK_VERSION (1, 1, 4)
@ -365,6 +369,8 @@ formhistory_deactivate_cb (MidoriExtension* extension,
sqlite3* db; sqlite3* db;
#endif #endif
g_signal_handlers_disconnect_by_func (
browser, formhistory_add_tab_cb, extension);
g_signal_handlers_disconnect_by_func ( g_signal_handlers_disconnect_by_func (
extension, formhistory_deactivate_cb, browser); extension, formhistory_deactivate_cb, browser);
g_signal_handlers_disconnect_by_func ( g_signal_handlers_disconnect_by_func (
@ -372,7 +378,7 @@ formhistory_deactivate_cb (MidoriExtension* extension,
midori_browser_foreach (browser, midori_browser_foreach (browser,
(GtkCallback)formhistory_deactivate_tabs, extension); (GtkCallback)formhistory_deactivate_tabs, extension);
jsforms = ""; katze_assign (jsforms, NULL);
if (global_keys) if (global_keys)
g_hash_table_destroy (global_keys); g_hash_table_destroy (global_keys);
@ -429,6 +435,8 @@ formhistory_activate_cb (MidoriExtension* extension,
global_keys = g_hash_table_new_full (g_str_hash, g_str_equal, global_keys = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free, (GDestroyNotify)g_free,
(GDestroyNotify)g_free); (GDestroyNotify)g_free);
if(!jsforms)
formhistory_prepare_js ();
#if HAVE_SQLITE #if HAVE_SQLITE
config_dir = midori_extension_get_config_dir (extension); config_dir = midori_extension_get_config_dir (extension);
katze_mkdir_with_parents (config_dir, 0700); katze_mkdir_with_parents (config_dir, 0700);
@ -498,7 +506,7 @@ extension_init (void)
if (formhistory_prepare_js ()) if (formhistory_prepare_js ())
{ {
ver = "0.1"; ver = "1.0";
desc = g_strdup (_("Stores history of entered form data")); desc = g_strdup (_("Stores history of entered form data"));
} }
else else

View file

@ -132,6 +132,14 @@ shortcuts_hotkey_for_action (GtkAction* action,
return FALSE; return FALSE;
} }
static void
shortcuts_preferences_response_cb (GtkWidget* dialog,
gint response,
gpointer data)
{
gtk_widget_destroy (dialog);
}
static GtkWidget* static GtkWidget*
shortcuts_get_preferences_dialog (MidoriExtension* extension) shortcuts_get_preferences_dialog (MidoriExtension* extension)
{ {
@ -172,7 +180,7 @@ shortcuts_get_preferences_dialog (MidoriExtension* extension)
sokoke_widget_get_text_size (dialog, "M", &width, &height); sokoke_widget_get_text_size (dialog, "M", &width, &height);
gtk_window_set_default_size (GTK_WINDOW (dialog), width * 52, height * 24); gtk_window_set_default_size (GTK_WINDOW (dialog), width * 52, height * 24);
g_signal_connect (dialog, "response", g_signal_connect (dialog, "response",
G_CALLBACK (gtk_widget_destroy), dialog); G_CALLBACK (shortcuts_preferences_response_cb), NULL);
if ((xfce_heading = sokoke_xfce_header_new ( if ((xfce_heading = sokoke_xfce_header_new (
gtk_window_get_icon_name (GTK_WINDOW (dialog)), dialog_title))) gtk_window_get_icon_name (GTK_WINDOW (dialog)), dialog_title)))
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),

View file

@ -13,8 +13,6 @@
#include "config.h" #include "config.h"
#if !HAVE_HILDON
typedef struct typedef struct
{ {
GtkWidget *dialog; GtkWidget *dialog;
@ -604,24 +602,16 @@ static void tb_editor_activate_cb(MidoriExtension *extension, MidoriApp *app)
g_object_unref(browsers); g_object_unref(browsers);
} }
#endif
MidoriExtension *extension_init(void) MidoriExtension *extension_init(void)
{ {
MidoriExtension* extension = g_object_new(MIDORI_TYPE_EXTENSION, MidoriExtension* extension = g_object_new(MIDORI_TYPE_EXTENSION,
"name", _("Toolbar Editor"), "name", _("Toolbar Editor"),
#if !HAVE_HILDON
"description", _("Easily edit the toolbar layout"), "description", _("Easily edit the toolbar layout"),
"version", "0.1", "version", "0.1",
#else
"description", _("Not available on this platform"),
#endif
"authors", "Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>", "authors", "Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>",
NULL); NULL);
#if !HAVE_HILDON
g_signal_connect(extension, "activate", G_CALLBACK(tb_editor_activate_cb), NULL); g_signal_connect(extension, "activate", G_CALLBACK(tb_editor_activate_cb), NULL);
#endif
return extension; return extension;
} }

View file

@ -21,8 +21,6 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
static gboolean offline_mode = FALSE;
#define HAVE_WEBKIT_RESOURCE_REQUEST WEBKIT_CHECK_VERSION (1, 1, 14)
#define MAXLENGTH 1024 * 1024 #define MAXLENGTH 1024 * 1024
static gchar* static gchar*
@ -43,7 +41,8 @@ web_cache_get_cached_path (MidoriExtension* extension,
checksum = g_compute_checksum_for_string (G_CHECKSUM_MD5, uri, -1); checksum = g_compute_checksum_for_string (G_CHECKSUM_MD5, uri, -1);
folder = g_strdup_printf ("%c%c", checksum[0], checksum[1]); folder = g_strdup_printf ("%c%c", checksum[0], checksum[1]);
sub_path = g_build_path (G_DIR_SEPARATOR_S, cache_path, folder, NULL); sub_path = g_build_path (G_DIR_SEPARATOR_S, cache_path, folder, NULL);
g_mkdir (sub_path, 0700); /* FIXME: Wrong place? */
katze_mkdir_with_parents (sub_path, 0700);
g_free (folder); g_free (folder);
encoded = soup_uri_encode (uri, "/"); encoded = soup_uri_encode (uri, "/");
@ -61,65 +60,6 @@ web_cache_get_cached_path (MidoriExtension* extension,
} }
static gboolean static gboolean
web_cache_replace_frame_uri (MidoriExtension* extension,
const gchar* uri,
WebKitWebFrame* web_frame)
{
gchar* filename;
gboolean handled = FALSE;
filename = web_cache_get_cached_path (extension, uri);
/* g_debug ("cache lookup: %s => %s", uri, filename); */
if (g_file_test (filename, G_FILE_TEST_EXISTS))
{
gchar* data;
g_file_get_contents (filename, &data, NULL, NULL);
webkit_web_frame_load_alternate_string (web_frame, data, NULL, uri);
g_free (data);
handled = TRUE;
}
g_free (filename);
return handled;
}
static gboolean
web_cache_navigation_decision_cb (WebKitWebView* web_view,
WebKitWebFrame* web_frame,
WebKitNetworkRequest* request,
WebKitWebNavigationAction* action,
WebKitWebPolicyDecision* decision,
MidoriExtension* extension)
{
const gchar* uri = webkit_network_request_get_uri (request);
if (!(uri && g_str_has_prefix (uri, "http://")))
return FALSE;
if (offline_mode == FALSE)
return FALSE;
return web_cache_replace_frame_uri (extension, uri, web_frame);
}
#if WEBKIT_CHECK_VERSION (1, 1, 6)
static gboolean
web_cache_load_error_cb (WebKitWebView* web_view,
WebKitWebFrame* web_frame,
const gchar* uri,
GError* error,
MidoriExtension* extension)
{
if (offline_mode == FALSE)
return FALSE;
if (!(uri && g_str_has_prefix (uri, "http://")))
return FALSE;
return web_cache_replace_frame_uri (extension, uri, web_frame);
}
#endif
static void
web_cache_save_headers (SoupMessage* msg, web_cache_save_headers (SoupMessage* msg,
gchar* filename) gchar* filename)
{ {
@ -131,11 +71,15 @@ web_cache_save_headers (SoupMessage* msg,
soup_message_headers_iter_init (&iter, hdrs); soup_message_headers_iter_init (&iter, hdrs);
dscfd = g_fopen (dsc_filename, "w"); dscfd = g_fopen (dsc_filename, "w");
g_free (dsc_filename);
if (!dscfd)
return FALSE;
while (soup_message_headers_iter_next (&iter, &name, &value)) while (soup_message_headers_iter_next (&iter, &name, &value))
g_fprintf (dscfd, "%s: %s\n", name, value); g_fprintf (dscfd, "%s: %s\n", name, value);
fclose (dscfd); fclose (dscfd);
g_free (dsc_filename); return TRUE;
} }
GHashTable* GHashTable*
@ -144,59 +88,60 @@ web_cache_get_headers (gchar* filename)
GHashTable* headers; GHashTable* headers;
FILE* file; FILE* file;
gchar* dsc_filename; gchar* dsc_filename;
gchar line[128];
if (!filename)
return NULL;
/* use g_access() instead of g_file_test for better performance */
if (g_access (filename, F_OK) != 0)
return NULL;
dsc_filename = g_strdup_printf ("%s.dsc", filename);
headers = g_hash_table_new_full (g_str_hash, g_str_equal, headers = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free, (GDestroyNotify)g_free,
(GDestroyNotify)g_free); (GDestroyNotify)g_free);
if (!filename) if (!(file = g_fopen (dsc_filename, "r")))
return headers;
if (!g_file_test (filename, G_FILE_TEST_EXISTS))
return headers;
dsc_filename = g_strdup_printf ("%s.dsc", filename);
if (!g_file_test (dsc_filename, G_FILE_TEST_EXISTS))
{ {
g_hash_table_destroy (headers);
g_free (dsc_filename); g_free (dsc_filename);
return headers; return NULL;
} }
if ((file = g_fopen (dsc_filename, "r"))) while (fgets (line, 128, file))
{ {
gchar line[128]; gchar** data;
while (fgets (line, 128, file))
{ if (line == NULL)
if (line==NULL) continue;
continue;
g_strchomp (line); g_strchomp (line);
gchar** data; data = g_strsplit (line, ":", 2);
data = g_strsplit (line, ":", 2); if (data[0] && data[1])
if (data[0] && data[1]) g_hash_table_insert (headers, g_strdup (data[0]),
g_hash_table_insert (headers, g_strdup (data[0]), g_strdup (g_strchug (data[1])));
g_strdup (g_strchug (data[1]))); g_strfreev (data);
g_strfreev (data);
}
} }
fclose (file); fclose (file);
/* g_hash_table_destroy (headers); */
g_free (dsc_filename); g_free (dsc_filename);
return headers; return headers;
} }
static gboolean static GFile*
web_cache_tmp_prepare (gchar* filename) web_cache_tmp_prepare (gchar* filename)
{ {
gchar* tmp_filename = g_strdup_printf ("%s.tmp", filename); GFile *file;
/* FIXME: If load was interruped we are ending up with a partical gchar* tmp_filename = g_strdup_printf ("%s.tmp", filename);
cache files forever */ if (g_access (tmp_filename, F_OK) == 0)
if (g_file_test (tmp_filename, G_FILE_TEST_EXISTS))
{ {
g_free (tmp_filename); g_free (tmp_filename);
return FALSE; return NULL;
} }
g_file_set_contents (tmp_filename, "", -1, NULL); file = g_file_new_for_path (tmp_filename);
g_free (tmp_filename); g_free (tmp_filename);
return TRUE;
return file;
} }
static void static void
@ -204,27 +149,36 @@ web_cache_set_content_type (SoupMessage* msg,
SoupBuffer* buffer) SoupBuffer* buffer)
{ {
#if WEBKIT_CHECK_VERSION (1, 1, 15) #if WEBKIT_CHECK_VERSION (1, 1, 15)
const char *ct; gchar* sniffed_type;
SoupContentSniffer* sniffer = soup_content_sniffer_new (); SoupContentSniffer* sniffer = soup_content_sniffer_new ();
ct = soup_content_sniffer_sniff (sniffer, msg, buffer, NULL); if ((sniffed_type = soup_content_sniffer_sniff (sniffer, msg, buffer, NULL)))
if (!ct) {
ct = soup_message_headers_get_one (msg->response_headers, "Content-Type"); g_signal_emit_by_name (msg, "content-sniffed", sniffed_type, NULL);
if (ct) g_free (sniffed_type);
g_signal_emit_by_name (msg, "content-sniffed", ct, NULL); }
else
{
const gchar* content_type = soup_message_headers_get_one (
msg->response_headers, "Content-Type");
g_signal_emit_by_name (msg, "content-sniffed", content_type, NULL);
}
#endif #endif
} }
static void static void
web_cache_message_finished_cb (SoupMessage* msg, web_cache_message_finished_cb (SoupMessage* msg,
gchar* filename) GOutputStream* stream)
{ {
gchar* headers; gchar* headers;
gchar* tmp_headers; gchar* tmp_headers;
gchar* tmp_data; gchar* tmp_data;
gchar* filename;
filename = g_object_get_data (G_OBJECT (stream), "filename");
headers = g_strdup_printf ("%s.dsc", filename); headers = g_strdup_printf ("%s.dsc", filename);
tmp_headers = g_strdup_printf ("%s.dsc.tmp", filename); tmp_headers = g_strdup_printf ("%s.dsc.tmp", filename);
tmp_data = g_strdup_printf ("%s.tmp", filename); tmp_data = g_strdup_printf ("%s.tmp", filename);
g_output_stream_close (stream, NULL, NULL);
if (msg->status_code == SOUP_STATUS_OK) if (msg->status_code == SOUP_STATUS_OK)
{ {
@ -237,92 +191,108 @@ web_cache_message_finished_cb (SoupMessage* msg,
g_unlink (tmp_headers); g_unlink (tmp_headers);
} }
g_object_unref (stream);
g_free (headers); g_free (headers);
g_free (tmp_headers); g_free (tmp_headers);
g_free (tmp_data); g_free (tmp_data);
} }
static void web_cache_pause_message (SoupMessage* msg)
{
SoupSession* session;
session = g_object_get_data (G_OBJECT (msg), "session");
soup_session_pause_message (session, msg);
}
static void web_cache_unpause_message (SoupMessage* msg)
{
SoupSession* session;
session = g_object_get_data (G_OBJECT (msg), "session");
soup_session_unpause_message (session, msg);
}
static void static void
web_cache_message_got_chunk_cb (SoupMessage* msg, web_cache_message_got_chunk_cb (SoupMessage* msg,
SoupBuffer* chunk, SoupBuffer* chunk,
gchar* filename) GOutputStream* stream)
{ {
GFile *file;
GOutputStream *stream;
gchar *tmp_filename;
if (!chunk->data || !chunk->length) if (!chunk->data || !chunk->length)
return; return;
/* FIXME g_output_stream_write_async (stream, chunk->data, chunk->length,
G_PRIORITY_DEFAULT, NULL, NULL, (gpointer)chunk->length); */
g_output_stream_write (stream, chunk->data, chunk->length, NULL, NULL);
}
tmp_filename = g_strdup_printf ("%s.tmp", filename); static void
file = g_file_new_for_path (tmp_filename); web_cache_message_rewrite_async_cb (GFile *file,
if ((stream = (GOutputStream*)g_file_append_to (file, 0, NULL, NULL))) GAsyncResult* res,
SoupMessage* msg)
{
SoupBuffer *buffer;
char *data;
gsize length;
GError *error = NULL;
if (g_file_load_contents_finish (file, res, &data, &length, NULL, &error))
{ {
g_output_stream_write (stream, chunk->data, chunk->length, NULL, NULL); buffer = soup_buffer_new (SOUP_MEMORY_TEMPORARY, data, length);
g_object_unref (stream); web_cache_set_content_type (msg, buffer);
soup_message_body_append_buffer (msg->response_body, buffer);
/* FIXME? */
web_cache_unpause_message (msg);
g_signal_emit_by_name (msg, "got-chunk", buffer, NULL);
soup_buffer_free (buffer);
g_free (data);
soup_message_got_body (msg);
soup_message_finished (msg);
} }
g_object_unref (file); g_object_unref (file);
g_free (tmp_filename); g_object_unref (msg);
} }
static void static void
web_cache_message_rewrite (SoupMessage* msg, web_cache_message_rewrite (SoupMessage* msg,
gchar* filename) gchar* filename)
{ {
GHashTable* cache_headers = web_cache_get_headers (filename);
GHashTableIter iter; GHashTableIter iter;
SoupBuffer *buffer;
gpointer key, value; gpointer key, value;
char *data; GFile *file;
gsize length;
GHashTable* cache_headers = web_cache_get_headers (filename);
if (!cache_headers)
return;
soup_message_set_status (msg, SOUP_STATUS_OK); soup_message_set_status (msg, SOUP_STATUS_OK);
g_hash_table_iter_init (&iter, cache_headers); g_hash_table_iter_init (&iter, cache_headers);
while (g_hash_table_iter_next (&iter, &key, &value)) while (g_hash_table_iter_next (&iter, &key, &value))
soup_message_headers_replace (msg->response_headers, key, value); soup_message_headers_replace (msg->response_headers, key, value);
g_signal_emit_by_name (msg, "got-headers", NULL); g_signal_emit_by_name (msg, "got-headers", NULL);
g_hash_table_destroy (cache_headers);
msg->response_body = soup_message_body_new (); /* FIXME? It seems libsoup already said "goodbye" by the time
g_file_get_contents (filename, &data, &length, NULL); the asynchronous function is starting to send data */
if (data && length) web_cache_pause_message (msg);
{ file = g_file_new_for_path (filename);
buffer = soup_buffer_new (SOUP_MEMORY_TEMPORARY, data, length); g_free (filename);
web_cache_set_content_type (msg, buffer); g_object_ref (msg);
soup_message_body_append_buffer (msg->response_body, buffer); g_file_load_contents_async (file, NULL,
g_signal_emit_by_name (msg, "got-chunk", buffer, NULL); (GAsyncReadyCallback)web_cache_message_rewrite_async_cb, msg);
soup_buffer_free (buffer);
}
soup_message_got_body (msg);
g_free (data);
#if 0
if (offline_mode == TRUE)
{
/* Workaroung for offline mode
FIXME: libsoup-CRITICAL **: queue_message: assertion `item != NULL' failed */
SoupSession *session = webkit_get_default_session ();
soup_session_requeue_message (session, msg);
}
soup_message_finished (msg);
#endif
} }
static void static void
web_cache_mesage_got_headers_cb (SoupMessage* msg, web_cache_mesage_got_headers_cb (SoupMessage* msg,
MidoriExtension* extension) gchar* filename)
{ {
SoupURI* soup_uri = soup_message_get_uri (msg);
gchar* uri;
gchar* filename;
const gchar* nocache; const gchar* nocache;
SoupMessageHeaders *hdrs = msg->response_headers; SoupMessageHeaders *hdrs = msg->response_headers;
const char* cl;
/* Skip files downloaded by the user */ /* Skip files downloaded by the user */
if (g_object_get_data (G_OBJECT (msg), "midori-web-cache-download")) if (g_object_get_data (G_OBJECT (msg), "midori-web-cache-download"))
return; return;
/* Skip big files */ /* Skip big files */
const char* cl = soup_message_headers_get_one (hdrs, "Content-Length"); cl = soup_message_headers_get_one (hdrs, "Content-Length");
if (cl && atoi (cl) > MAXLENGTH) if (cl && atoi (cl) > MAXLENGTH)
return; return;
@ -335,98 +305,64 @@ web_cache_mesage_got_headers_cb (SoupMessage* msg,
return; return;
} }
uri = soup_uri ? soup_uri_to_string (soup_uri, FALSE) : g_strdup ("");
filename = web_cache_get_cached_path (extension, uri);
if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) if (msg->status_code == SOUP_STATUS_NOT_MODIFIED)
{ {
/* g_debug ("loading from cache: %s -> %s", uri, filename); */ /* g_debug ("loading from cache: %s", filename); */
g_signal_handlers_disconnect_by_func (msg, g_signal_handlers_disconnect_by_func (msg,
web_cache_mesage_got_headers_cb, extension); web_cache_mesage_got_headers_cb, filename);
web_cache_message_rewrite (msg, filename); web_cache_message_rewrite (msg, filename);
g_free (filename);
} }
else if (msg->status_code == SOUP_STATUS_OK) else if (msg->status_code == SOUP_STATUS_OK)
{ {
/* g_debug ("updating cache: %s -> %s", uri, filename); */ GFile* file;
if (!web_cache_tmp_prepare (filename)) GOutputStream* ostream;
/* g_debug ("updating cache: %s", filename); */
if (!(file = web_cache_tmp_prepare (filename)))
return; return;
web_cache_save_headers (msg, filename); if (!web_cache_save_headers (msg, filename))
g_signal_connect_data (msg, "got-chunk", return;
G_CALLBACK (web_cache_message_got_chunk_cb),
filename, (GClosureNotify)g_free, 0); #if GLIB_CHECK_VERSION (2, 20, 0)
ostream = (GOutputStream*)g_file_append_to (file,
G_FILE_CREATE_PRIVATE | G_FILE_CREATE_REPLACE_DESTINATION, NULL, NULL);
#else
g_unlink (filename);
ostream = (GOutputStream*)g_file_append_to (file,
G_FILE_CREATE_PRIVATE, NULL, NULL);
#endif
g_object_unref (file);
if (!ostream)
return;
g_object_set_data_full (G_OBJECT (ostream), "filename",
filename, (GDestroyNotify)g_free);
g_signal_connect (msg, "got-chunk",
G_CALLBACK (web_cache_message_got_chunk_cb), ostream);
g_signal_connect (msg, "finished", g_signal_connect (msg, "finished",
G_CALLBACK (web_cache_message_finished_cb), filename); G_CALLBACK (web_cache_message_finished_cb), ostream);
} }
g_free (uri);
} }
#if HAVE_WEBKIT_RESOURCE_REQUEST
static void
web_cache_resource_request_starting_cb (WebKitWebView* web_view,
WebKitWebFrame* web_frame,
WebKitWebResource* web_resource,
WebKitNetworkRequest* request,
WebKitNetworkResponse* response,
MidoriExtension* extension)
{
const gchar* uri;
gchar* filename;
/* TODO: Good place to check are we offline */
uri = webkit_network_request_get_uri (request);
if (!(uri && g_str_has_prefix (uri, "http://")))
return;
if (offline_mode == FALSE)
return;
filename = web_cache_get_cached_path (extension, uri);
/* g_debug ("loading %s -> %s",uri, filename); */
if (!g_file_test (filename, G_FILE_TEST_EXISTS))
{
g_free (filename);
return;
}
if (!(g_strcmp0 (uri, webkit_web_frame_get_uri (web_frame))
&& g_strcmp0 (webkit_web_data_source_get_unreachable_uri (
webkit_web_frame_get_data_source (web_frame)), uri)))
{
web_cache_replace_frame_uri (extension, uri, web_frame);
g_free (filename);
return;
}
gchar* file_uri = g_filename_to_uri (filename, NULL, NULL);
webkit_network_request_set_uri (request, file_uri);
g_free (file_uri);
g_free (filename);
}
#endif
static void static void
web_cache_session_request_queued_cb (SoupSession* session, web_cache_session_request_queued_cb (SoupSession* session,
SoupMessage* msg, SoupMessage* msg,
MidoriExtension* extension) MidoriExtension* extension)
{ {
/*FIXME: Should we need to free soupuri? */
SoupURI* soup_uri = soup_message_get_uri (msg); SoupURI* soup_uri = soup_message_get_uri (msg);
gchar* uri = soup_uri ? soup_uri_to_string (soup_uri, FALSE) : g_strdup (""); gchar* uri = soup_uri_to_string (soup_uri, FALSE);
/* For now we are handling only online mode here */ if (uri && g_str_has_prefix (uri, "http") && !g_strcmp0 (msg->method, "GET"))
if (offline_mode == TRUE)
return;
if (g_str_has_prefix (uri, "http") && !g_strcmp0 (msg->method, "GET"))
{ {
gchar* filename = web_cache_get_cached_path (extension, uri); gchar* filename = web_cache_get_cached_path (extension, uri);
if (offline_mode == FALSE) GHashTable* cache_headers;
{ gchar* etag;
GHashTable* cache_headers; gchar* last_modified;
gchar* etag;
gchar* last_modified;
cache_headers = web_cache_get_headers (filename); cache_headers = web_cache_get_headers (filename);
if (cache_headers)
{
etag = g_hash_table_lookup (cache_headers, "ETag"); etag = g_hash_table_lookup (cache_headers, "ETag");
last_modified = g_hash_table_lookup (cache_headers, "Last-Modified"); last_modified = g_hash_table_lookup (cache_headers, "Last-Modified");
if (etag) if (etag)
@ -435,52 +371,16 @@ web_cache_session_request_queued_cb (SoupSession* session,
if (last_modified) if (last_modified)
soup_message_headers_replace (msg->request_headers, soup_message_headers_replace (msg->request_headers,
"If-Modified-Since", last_modified); "If-Modified-Since", last_modified);
g_signal_connect (msg, "got-headers", g_hash_table_destroy (cache_headers);
G_CALLBACK (web_cache_mesage_got_headers_cb), extension); }
g_object_set_data (G_OBJECT (msg), "session", session);
g_signal_connect (msg, "got-headers",
G_CALLBACK (web_cache_mesage_got_headers_cb), filename);
g_free (etag);
g_free (last_modified);
g_free (filename);
/* FIXME: uncoment this is leading to a crash
g_hash_table_destroy (cache_headers); */
return;
}
/*
else
{
g_debug("queued in offline mode: %s -> %s", uri, filename);
if (g_file_test (filename, G_FILE_TEST_EXISTS))
{
soup_message_set_status (msg, SOUP_STATUS_NOT_MODIFIED);
web_cache_message_rewrite (msg, filename);
}
}
*/
g_free (filename);
} }
g_free (uri); g_free (uri);
} }
static void
web_cache_add_tab_cb (MidoriBrowser* browser,
MidoriView* view,
MidoriExtension* extension)
{
GtkWidget* web_view = gtk_bin_get_child (GTK_BIN (view));
g_signal_connect (web_view, "navigation-policy-decision-requested",
G_CALLBACK (web_cache_navigation_decision_cb), extension);
#if WEBKIT_CHECK_VERSION (1, 1, 6)
g_signal_connect (web_view, "load-error",
G_CALLBACK (web_cache_load_error_cb), extension);
#endif
#if HAVE_WEBKIT_RESOURCE_REQUEST
g_signal_connect (web_view, "resource-request-starting",
G_CALLBACK (web_cache_resource_request_starting_cb), extension);
#endif
}
#if WEBKIT_CHECK_VERSION (1, 1, 3) #if WEBKIT_CHECK_VERSION (1, 1, 3)
static void static void
web_cache_add_download_cb (MidoriBrowser* browser, web_cache_add_download_cb (MidoriBrowser* browser,
@ -499,23 +399,11 @@ static void
web_cache_deactivate_cb (MidoriExtension* extension, web_cache_deactivate_cb (MidoriExtension* extension,
MidoriBrowser* browser); MidoriBrowser* browser);
static void
web_cache_add_tab_foreach_cb (MidoriView* view,
MidoriBrowser* browser,
MidoriExtension* extension)
{
web_cache_add_tab_cb (browser, view, extension);
}
static void static void
web_cache_app_add_browser_cb (MidoriApp* app, web_cache_app_add_browser_cb (MidoriApp* app,
MidoriBrowser* browser, MidoriBrowser* browser,
MidoriExtension* extension) MidoriExtension* extension)
{ {
midori_browser_foreach (browser,
(GtkCallback)web_cache_add_tab_foreach_cb, extension);
g_signal_connect (browser, "add-tab",
G_CALLBACK (web_cache_add_tab_cb), extension);
#if WEBKIT_CHECK_VERSION (1, 1, 3) #if WEBKIT_CHECK_VERSION (1, 1, 3)
g_signal_connect (browser, "add-download", g_signal_connect (browser, "add-download",
G_CALLBACK (web_cache_add_download_cb), extension); G_CALLBACK (web_cache_add_download_cb), extension);
@ -524,18 +412,6 @@ web_cache_app_add_browser_cb (MidoriApp* app,
G_CALLBACK (web_cache_deactivate_cb), browser); G_CALLBACK (web_cache_deactivate_cb), browser);
} }
static void
web_cache_deactivate_tabs (MidoriView* view,
MidoriExtension* extension)
{
#if HAVE_WEBKIT_RESOURCE_REQUEST
GtkWidget* web_view = gtk_bin_get_child (GTK_BIN (view));
g_signal_handlers_disconnect_by_func (
web_view, web_cache_resource_request_starting_cb, extension);
#endif
}
static void static void
web_cache_deactivate_cb (MidoriExtension* extension, web_cache_deactivate_cb (MidoriExtension* extension,
MidoriBrowser* browser) MidoriBrowser* browser)
@ -549,13 +425,10 @@ web_cache_deactivate_cb (MidoriExtension* extension,
extension, web_cache_deactivate_cb, browser); extension, web_cache_deactivate_cb, browser);
g_signal_handlers_disconnect_by_func ( g_signal_handlers_disconnect_by_func (
app, web_cache_app_add_browser_cb, extension); app, web_cache_app_add_browser_cb, extension);
g_signal_handlers_disconnect_by_func (
browser, web_cache_add_tab_cb, extension);
#if WEBKIT_CHECK_VERSION (1, 1, 3) #if WEBKIT_CHECK_VERSION (1, 1, 3)
g_signal_handlers_disconnect_by_func ( g_signal_handlers_disconnect_by_func (
browser, web_cache_add_download_cb, extension); browser, web_cache_add_download_cb, extension);
#endif #endif
midori_browser_foreach (browser, (GtkCallback)web_cache_deactivate_tabs, extension);
} }
static void static void

View file

@ -29,3 +29,5 @@ for extension in extensions:
obj.source = source obj.source = source
obj.uselib = 'UNIQUE LIBSOUP GIO GTK SQLITE WEBKIT LIBXML HILDON' obj.uselib = 'UNIQUE LIBSOUP GIO GTK SQLITE WEBKIT LIBXML HILDON'
obj.install_path = '${LIBDIR}/midori' obj.install_path = '${LIBDIR}/midori'
if bld.env['platform'] == 'win32':
obj.uselib_local = 'midori'

View file

@ -166,7 +166,7 @@ katze_array_class_init (KatzeArrayClass* class)
G_STRUCT_OFFSET (KatzeArrayClass, move_item), G_STRUCT_OFFSET (KatzeArrayClass, move_item),
0, 0,
NULL, NULL,
katze_cclosure_marshal_VOID__POINTER_INT, midori_cclosure_marshal_VOID__POINTER_INT,
G_TYPE_NONE, 2, G_TYPE_NONE, 2,
G_TYPE_POINTER, G_TYPE_POINTER,
G_TYPE_INT); G_TYPE_INT);

View file

@ -33,7 +33,7 @@ typedef struct _KatzeArray KatzeArray;
typedef struct _KatzeArrayClass KatzeArrayClass; typedef struct _KatzeArrayClass KatzeArrayClass;
GType GType
katze_array_get_type (void); katze_array_get_type (void) G_GNUC_CONST;
KatzeArray* KatzeArray*
katze_array_new (GType type); katze_array_new (GType type);

View file

@ -12,7 +12,6 @@
#include "katze-arrayaction.h" #include "katze-arrayaction.h"
#include "katze-net.h"
#include "katze-utils.h" #include "katze-utils.h"
#include "marshal.h" #include "marshal.h"
@ -29,7 +28,6 @@ struct _KatzeArrayAction
GtkAction parent_instance; GtkAction parent_instance;
KatzeArray* array; KatzeArray* array;
KatzeNet* net;
gboolean reversed; gboolean reversed;
}; };
@ -136,7 +134,7 @@ katze_array_action_class_init (KatzeArrayActionClass* class)
0, 0,
0, 0,
NULL, NULL,
katze_cclosure_marshal_BOOLEAN__OBJECT_UINT, midori_cclosure_marshal_BOOLEAN__OBJECT_UINT,
G_TYPE_BOOLEAN, 2, G_TYPE_BOOLEAN, 2,
KATZE_TYPE_ITEM, G_TYPE_UINT); KATZE_TYPE_ITEM, G_TYPE_UINT);
@ -182,7 +180,6 @@ static void
katze_array_action_init (KatzeArrayAction* array_action) katze_array_action_init (KatzeArrayAction* array_action)
{ {
array_action->array = NULL; array_action->array = NULL;
array_action->net = katze_net_new ();
array_action->reversed = FALSE; array_action->reversed = FALSE;
} }
@ -192,7 +189,6 @@ katze_array_action_finalize (GObject* object)
KatzeArrayAction* array_action = KATZE_ARRAY_ACTION (object); KatzeArrayAction* array_action = KATZE_ARRAY_ACTION (object);
katze_object_assign (array_action->array, NULL); katze_object_assign (array_action->array, NULL);
katze_object_assign (array_action->net, NULL);
G_OBJECT_CLASS (katze_array_action_parent_class)->finalize (object); G_OBJECT_CLASS (katze_array_action_parent_class)->finalize (object);
} }

View file

@ -35,7 +35,7 @@ typedef struct _KatzeArrayAction KatzeArrayAction;
typedef struct _KatzeArrayActionClass KatzeArrayActionClass; typedef struct _KatzeArrayActionClass KatzeArrayActionClass;
GType GType
katze_array_action_get_type (void); katze_array_action_get_type (void) G_GNUC_CONST;
KatzeArray* KatzeArray*
katze_array_action_get_array (KatzeArrayAction* array_action); katze_array_action_get_array (KatzeArrayAction* array_action);

View file

@ -20,6 +20,10 @@
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <glib/gstdio.h> #include <glib/gstdio.h>
#if !GTK_CHECK_VERSION (2, 14, 0)
#define gtk_dialog_get_content_area(dialog) dialog->vbox
#endif
struct _KatzeHttpAuth struct _KatzeHttpAuth
{ {
GObject parent_instance; GObject parent_instance;
@ -110,6 +114,7 @@ authentication_message_got_headers_cb (SoupMessage* msg,
fprintf (file, "%s\t%s\t%s\n", opaque_info, fprintf (file, "%s\t%s\t%s\n", opaque_info,
login->username, login->password); login->username, login->password);
fclose (file); fclose (file);
g_chmod (save->http_auth->filename, 0600);
} }
} }
else else
@ -215,9 +220,9 @@ katze_http_auth_session_authenticate_cb (SoupSession* session,
gtk_window_set_icon_name (GTK_WINDOW (dialog), gtk_window_set_icon_name (GTK_WINDOW (dialog),
GTK_STOCK_DIALOG_AUTHENTICATION); GTK_STOCK_DIALOG_AUTHENTICATION);
gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 5); gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 5);
gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 5); gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 5);
hbox = gtk_hbox_new (FALSE, 6); hbox = gtk_hbox_new (FALSE, 6);
image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION, image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION,
GTK_ICON_SIZE_DIALOG); GTK_ICON_SIZE_DIALOG);
@ -225,14 +230,14 @@ katze_http_auth_session_authenticate_cb (SoupSession* session,
label = gtk_label_new (_("A username and a password are required\n" label = gtk_label_new (_("A username and a password are required\n"
"to open this location:")); "to open this location:"));
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), hbox);
label = gtk_label_new (soup_auth_get_host (auth)); label = gtk_label_new (soup_auth_get_host (auth));
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), label); gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), label);
/* If the realm is merely the host, omit the realm label */ /* If the realm is merely the host, omit the realm label */
if (g_strcmp0 (soup_auth_get_host (auth), soup_auth_get_realm (auth))) if (g_strcmp0 (soup_auth_get_host (auth), soup_auth_get_realm (auth)))
{ {
label = gtk_label_new (soup_auth_get_realm (auth)); label = gtk_label_new (soup_auth_get_realm (auth));
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), label); gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), label);
} }
sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
hbox = gtk_hbox_new (FALSE, 6); hbox = gtk_hbox_new (FALSE, 6);
@ -247,28 +252,30 @@ katze_http_auth_session_authenticate_cb (SoupSession* session,
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
g_object_set_data (G_OBJECT (dialog), "username", entry); g_object_set_data (G_OBJECT (dialog), "username", entry);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), hbox);
hbox = gtk_hbox_new (FALSE, 6); hbox = gtk_hbox_new (FALSE, 6);
label = gtk_label_new (_("Password")); label = gtk_label_new (_("Password"));
align = gtk_alignment_new (0, 0.5, 0, 0); align = gtk_alignment_new (0, 0.5, 0, 0);
gtk_container_add (GTK_CONTAINER (align), label); gtk_container_add (GTK_CONTAINER (align), label);
gtk_size_group_add_widget (sizegroup, align); gtk_size_group_add_widget (sizegroup, align);
gtk_box_pack_start (GTK_BOX (hbox), align, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), align, TRUE, TRUE, 0);
entry = gtk_entry_new_with_max_length (32); entry = gtk_entry_new ();
gtk_entry_set_max_length (GTK_ENTRY (entry), 32);
if (login) if (login)
gtk_entry_set_text (GTK_ENTRY (entry), login->password); gtk_entry_set_text (GTK_ENTRY (entry), login->password);
gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE); gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
g_object_set_data (G_OBJECT (dialog), "password", entry); g_object_set_data (G_OBJECT (dialog), "password", entry);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), hbox);
hbox = gtk_hbox_new (FALSE, 6); hbox = gtk_hbox_new (FALSE, 6);
label = gtk_check_button_new_with_mnemonic (_("_Remember password")); label = gtk_check_button_new_with_mnemonic (_("_Remember password"));
gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
g_object_set_data (G_OBJECT (dialog), "remember", label); g_object_set_data (G_OBJECT (dialog), "remember", label);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (label), (login != NULL));
gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), hbox);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
gtk_widget_show_all (GTK_DIALOG (dialog)->vbox); gtk_widget_show_all (gtk_dialog_get_content_area (GTK_DIALOG (dialog)));
g_object_set_data (G_OBJECT (dialog), "session", session); g_object_set_data (G_OBJECT (dialog), "session", session);
g_object_set_data (G_OBJECT (dialog), "msg", msg); g_object_set_data (G_OBJECT (dialog), "msg", msg);

View file

@ -35,7 +35,7 @@ typedef struct _KatzeHttpAuth KatzeHttpAuth;
typedef struct _KatzeHttpAuthClass KatzeHttpAuthClass; typedef struct _KatzeHttpAuthClass KatzeHttpAuthClass;
GType GType
katze_http_auth_get_type (void); katze_http_auth_get_type (void) G_GNUC_CONST;
G_END_DECLS G_END_DECLS

View file

@ -35,7 +35,7 @@ typedef struct _KatzeHttpCookies KatzeHttpCookies;
typedef struct _KatzeHttpCookiesClass KatzeHttpCookiesClass; typedef struct _KatzeHttpCookiesClass KatzeHttpCookiesClass;
GType GType
katze_http_cookies_get_type (void); katze_http_cookies_get_type (void) G_GNUC_CONST;
G_END_DECLS G_END_DECLS

View file

@ -56,7 +56,7 @@ struct _KatzeItemClass
}; };
GType GType
katze_item_get_type (void); katze_item_get_type (void) G_GNUC_CONST;
KatzeItem* KatzeItem*
katze_item_new (void); katze_item_new (void);

View file

@ -13,8 +13,13 @@
#include <config.h> #include <config.h>
#endif #endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "katze-net.h" #include "katze-net.h"
#include <glib/gstdio.h>
#include <libsoup/soup.h> #include <libsoup/soup.h>
#include <webkit/webkit.h> #include <webkit/webkit.h>
@ -254,7 +259,7 @@ katze_net_local_cb (KatzeNetPriv* priv)
request = priv->request; request = priv->request;
filename = g_filename_from_uri (request->uri, NULL, NULL); filename = g_filename_from_uri (request->uri, NULL, NULL);
if (!filename || !g_file_test (filename, G_FILE_TEST_EXISTS)) if (!filename || g_access (filename, F_OK) != 0)
{ {
request->status = KATZE_NET_NOT_FOUND; request->status = KATZE_NET_NOT_FOUND;
if (priv->status_cb) if (priv->status_cb)
@ -429,6 +434,7 @@ katze_net_icon_transfer_cb (KatzeNetRequest* request,
GdkPixbuf* pixbuf_scaled; GdkPixbuf* pixbuf_scaled;
gint icon_width, icon_height; gint icon_width, icon_height;
size_t ret; size_t ret;
GtkSettings* settings;
if (request->status == KATZE_NET_MOVED) if (request->status == KATZE_NET_MOVED)
return; return;
@ -474,7 +480,14 @@ katze_net_icon_transfer_cb (KatzeNetRequest* request,
return; return;
} }
} }
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, &icon_height);
if (priv->widget)
settings = gtk_widget_get_settings (priv->widget);
else
settings = gtk_settings_get_for_screen (gdk_screen_get_default ());
gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU,
&icon_width, &icon_height);
pixbuf_scaled = gdk_pixbuf_scale_simple (pixbuf, icon_width, icon_height, pixbuf_scaled = gdk_pixbuf_scale_simple (pixbuf, icon_width, icon_height,
GDK_INTERP_BILINEAR); GDK_INTERP_BILINEAR);
g_object_unref (pixbuf); g_object_unref (pixbuf);
@ -531,6 +544,7 @@ katze_net_load_icon (KatzeNet* net,
GdkPixbuf* pixbuf; GdkPixbuf* pixbuf;
gint icon_width, icon_height; gint icon_width, icon_height;
GdkPixbuf* pixbuf_scaled; GdkPixbuf* pixbuf_scaled;
GtkSettings* settings;
g_return_val_if_fail (KATZE_IS_NET (net), NULL); g_return_val_if_fail (KATZE_IS_NET (net), NULL);
g_return_val_if_fail (!widget || GTK_IS_WIDGET (widget), NULL); g_return_val_if_fail (!widget || GTK_IS_WIDGET (widget), NULL);
@ -594,7 +608,14 @@ katze_net_load_icon (KatzeNet* net,
else else
return NULL; return NULL;
} }
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, &icon_height);
if (widget)
settings = gtk_widget_get_settings (widget);
else
settings = gtk_settings_get_for_screen (gdk_screen_get_default ());
gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU,
&icon_width, &icon_height);
pixbuf_scaled = gdk_pixbuf_scale_simple (pixbuf, icon_width, icon_height, pixbuf_scaled = gdk_pixbuf_scale_simple (pixbuf, icon_width, icon_height,
GDK_INTERP_BILINEAR); GDK_INTERP_BILINEAR);
g_object_unref (pixbuf); g_object_unref (pixbuf);

View file

@ -35,7 +35,7 @@ typedef struct _KatzeNet KatzeNet;
typedef struct _KatzeNetClass KatzeNetClass; typedef struct _KatzeNetClass KatzeNetClass;
GType GType
katze_net_get_type (void); katze_net_get_type (void) G_GNUC_CONST;
KatzeNet* KatzeNet*
katze_net_new (void); katze_net_new (void);

View file

@ -23,6 +23,10 @@
#include <string.h> #include <string.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
#if !GTK_CHECK_VERSION (2, 14, 0)
#define gtk_dialog_get_content_area(dialog) dialog->vbox
#endif
struct _KatzePreferencesPrivate struct _KatzePreferencesPrivate
{ {
#if HAVE_HILDON #if HAVE_HILDON
@ -177,7 +181,7 @@ katze_preferences_prepare (KatzePreferences* preferences)
GtkWidget* viewport; GtkWidget* viewport;
priv->scrolled = katze_scrolled_new (NULL, NULL); priv->scrolled = katze_scrolled_new (NULL, NULL);
gtk_box_pack_end (GTK_BOX (GTK_DIALOG (preferences)->vbox), gtk_box_pack_end (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (preferences))),
priv->scrolled, TRUE, TRUE, 4); priv->scrolled, TRUE, TRUE, 4);
viewport = gtk_viewport_new (NULL, NULL); viewport = gtk_viewport_new (NULL, NULL);
gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_NONE); gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_NONE);
@ -201,14 +205,14 @@ katze_preferences_prepare (KatzePreferences* preferences)
priv->toolbar = gtk_toolbar_new (); priv->toolbar = gtk_toolbar_new ();
gtk_toolbar_set_style (GTK_TOOLBAR (priv->toolbar), GTK_TOOLBAR_BOTH); gtk_toolbar_set_style (GTK_TOOLBAR (priv->toolbar), GTK_TOOLBAR_BOTH);
gtk_toolbar_set_show_arrow (GTK_TOOLBAR (priv->toolbar), FALSE); gtk_toolbar_set_show_arrow (GTK_TOOLBAR (priv->toolbar), FALSE);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (preferences)->vbox), gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (preferences))),
priv->toolbar, FALSE, FALSE, 0); priv->toolbar, FALSE, FALSE, 0);
#else #else
priv->toolbar = NULL; priv->toolbar = NULL;
#endif #endif
priv->toolbutton = NULL; priv->toolbutton = NULL;
gtk_box_pack_end (GTK_BOX (GTK_DIALOG (preferences)->vbox), gtk_box_pack_end (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (preferences))),
priv->notebook, FALSE, FALSE, 4); priv->notebook, TRUE, TRUE, 4);
priv->sizegroup = NULL; priv->sizegroup = NULL;
priv->sizegroup2 = NULL; priv->sizegroup2 = NULL;
@ -233,7 +237,7 @@ katze_preferences_prepare (KatzePreferences* preferences)
gtk_box_pack_end (GTK_BOX (GTK_DIALOG (preferences)->action_area), gtk_box_pack_end (GTK_BOX (GTK_DIALOG (preferences)->action_area),
hbox, FALSE, FALSE, 0); hbox, FALSE, FALSE, 0);
#endif #endif
gtk_widget_show_all (GTK_DIALOG (preferences)->vbox); gtk_widget_show_all (gtk_dialog_get_content_area (GTK_DIALOG (preferences)));
} }
/** /**

View file

@ -46,7 +46,7 @@ struct _KatzePreferencesClass
}; };
GType GType
katze_preferences_get_type (void); katze_preferences_get_type (void) G_GNUC_CONST;
GtkWidget* GtkWidget*
katze_preferences_new (GtkWindow* parent); katze_preferences_new (GtkWindow* parent);

View file

@ -18,6 +18,26 @@
#include "katze-scrolled.h" #include "katze-scrolled.h"
#include "katze-utils.h" #include "katze-utils.h"
#if !GTK_CHECK_VERSION (2, 14, 0)
#define gtk_adjustment_get_page_size(adj) adj->page_size
#define gtk_adjustment_get_upper(adj) adj->upper
#define gtk_adjustment_get_lower(adj) adj->lower
#define gtk_adjustment_get_value(adj) adj->value
#define gtk_widget_get_window(wdgt) wdgt->window
#endif
#if !GTK_CHECK_VERSION (2, 18, 0)
#define gtk_widget_set_window(wdgt, wndw) wdgt->window = wndw
#define gtk_widget_get_allocation(wdgt, alloc) *alloc = wdgt->allocation
#define gtk_widget_is_drawable GTK_WIDGET_DRAWABLE
#define gtk_widget_get_drawable GTK_WIDGET_VISIBLE
#define gtk_widget_get_visible(wdgt) GTK_WIDGET_VISIBLE (wdgt)
#endif
#if !GTK_CHECK_VERSION (2, 19, 6)
#define gtk_widget_set_realized(wdgt, real) \
if (real) GTK_WIDGET_SET_FLAGS (wdgt, GTK_REALIZED); \
else GTK_WIDGET_UNSET_FLAGS (wdgt, GTK_REALIZED)
#endif
#define DEFAULT_INTERVAL 50 #define DEFAULT_INTERVAL 50
#define DEFAULT_DECELERATION 0.7 #define DEFAULT_DECELERATION 0.7
#define DEFAULT_DRAGGING_STOPPED_DELAY 100 #define DEFAULT_DRAGGING_STOPPED_DELAY 100
@ -265,7 +285,7 @@ on_expose_event (GtkWidget* widget,
KatzeScrolledPrivate* priv = scrolled->priv; KatzeScrolledPrivate* priv = scrolled->priv;
gboolean ret = FALSE; gboolean ret = FALSE;
if (GTK_WIDGET_DRAWABLE (widget)) if (gtk_widget_is_drawable (widget))
{ {
if (event->window == priv->horizontal_scrollbar_window) if (event->window == priv->horizontal_scrollbar_window)
{ {
@ -305,19 +325,27 @@ adjust_scrollbar (KatzeScrolled* scrolled,
{ {
KatzeScrolledPrivate* priv = scrolled->priv; KatzeScrolledPrivate* priv = scrolled->priv;
GtkWidget* widget = GTK_WIDGET (scrolled); GtkWidget* widget = GTK_WIDGET (scrolled);
gdouble page_size, upper, lower, value;
gint x, y; gint x, y;
gint size; gint size;
double position; double position;
GtkAllocation allocation;
GtkWidget* window; GtkWidget* window;
if (adjustment->page_size >= adjustment->upper - adjustment->lower) page_size = gtk_adjustment_get_page_size (adjustment);
upper = gtk_adjustment_get_upper (adjustment);
lower = gtk_adjustment_get_lower (adjustment);
value = gtk_adjustment_get_value (adjustment);
if (page_size >= upper - lower)
{ {
*previous_size = 0; *previous_size = 0;
return FALSE; return FALSE;
} }
size = ((double)adjustment->page_size) / (adjustment->upper - adjustment->lower) * (horizontal gtk_widget_get_allocation (widget, &allocation);
? widget->allocation.height : widget->allocation.width); size = page_size / (upper - lower)
* (horizontal ? allocation.height : allocation.width);
if (size != *previous_size) if (size != *previous_size)
{ {
*previous_size = size; *previous_size = size;
@ -341,18 +369,18 @@ adjust_scrollbar (KatzeScrolled* scrolled,
} }
} }
position = (adjustment->value - adjustment->lower) / (adjustment->upper - adjustment->lower); position = (value - lower) / (upper - lower);
window = gtk_widget_get_toplevel (widget); window = gtk_widget_get_toplevel (widget);
if (horizontal) if (horizontal)
{ {
gtk_widget_translate_coordinates (widget, window, gtk_widget_translate_coordinates (widget, window,
widget->allocation.width - 20, position * widget->allocation.height, &x, &y); allocation.width - 20, position * allocation.height, &x, &y);
gdk_window_move (scrollbar_window, x, y); gdk_window_move (scrollbar_window, x, y);
} }
else else
{ {
gtk_widget_translate_coordinates (widget, window, gtk_widget_translate_coordinates (widget, window,
position * widget->allocation.width, widget->allocation.height - 20, &x, &y); position * allocation.width, allocation.height - 20, &x, &y);
gdk_window_move (scrollbar_window, x, y); gdk_window_move (scrollbar_window, x, y);
} }
@ -418,35 +446,45 @@ do_timeout_scroll (KatzeScrolled* scrolled)
GtkScrolledWindow* gtk_scrolled = GTK_SCROLLED_WINDOW (scrolled); GtkScrolledWindow* gtk_scrolled = GTK_SCROLLED_WINDOW (scrolled);
GtkAdjustment* hadjustment; GtkAdjustment* hadjustment;
GtkAdjustment* vadjustment; GtkAdjustment* vadjustment;
gdouble hvalue; gdouble hpage_size, hupper, hlower, hvalue, new_hvalue;
gdouble vvalue; gdouble vpage_size, vupper, vlower, vvalue, new_vvalue;
hadjustment = gtk_scrolled_window_get_hadjustment (gtk_scrolled); hadjustment = gtk_scrolled_window_get_hadjustment (gtk_scrolled);
vadjustment = gtk_scrolled_window_get_vadjustment (gtk_scrolled); hpage_size = gtk_adjustment_get_page_size (hadjustment);
hvalue = calculate_timeout_scroll_values (hadjustment->value, hupper = gtk_adjustment_get_upper (hadjustment);
hadjustment->upper - hadjustment->page_size, hlower = gtk_adjustment_get_lower (hadjustment);
hvalue = gtk_adjustment_get_value (hadjustment);
new_hvalue = calculate_timeout_scroll_values (hvalue,
hupper - hpage_size,
&priv->horizontal_speed, &priv->horizontal_speed,
priv->horizontal_deceleration, priv->horizontal_deceleration,
&priv->vertical_deceleration, &priv->vertical_deceleration,
priv->deceleration); priv->deceleration);
vvalue = calculate_timeout_scroll_values (vadjustment->value,
vadjustment->upper - vadjustment->page_size, vadjustment = gtk_scrolled_window_get_vadjustment (gtk_scrolled);
vpage_size = gtk_adjustment_get_page_size (vadjustment);
vupper = gtk_adjustment_get_upper (vadjustment);
vlower = gtk_adjustment_get_lower (vadjustment);
vvalue = gtk_adjustment_get_value (vadjustment);
new_vvalue = calculate_timeout_scroll_values (vvalue,
vupper - vpage_size,
&priv->vertical_speed, &priv->vertical_speed,
priv->vertical_deceleration, priv->vertical_deceleration,
&priv->horizontal_deceleration, &priv->horizontal_deceleration,
priv->deceleration); priv->deceleration);
if (vvalue != vadjustment->value)
if (new_vvalue != vvalue)
{ {
if (hvalue != hadjustment->value) if (new_hvalue != hvalue)
{ {
disable_hadjustment (scrolled); disable_hadjustment (scrolled);
gtk_adjustment_set_value (hadjustment, hvalue); gtk_adjustment_set_value (hadjustment, new_hvalue);
enable_hadjustment (scrolled); enable_hadjustment (scrolled);
} }
gtk_adjustment_set_value (vadjustment, vvalue); gtk_adjustment_set_value (vadjustment, new_vvalue);
} }
else if (hvalue != hadjustment->value) else if (new_hvalue != hvalue)
gtk_adjustment_set_value (hadjustment, hvalue); gtk_adjustment_set_value (hadjustment, new_hvalue);
adjust_scrollbar (scrolled, priv->horizontal_scrollbar_window, adjust_scrollbar (scrolled, priv->horizontal_scrollbar_window,
gtk_scrolled_window_get_hadjustment (gtk_scrolled), gtk_scrolled_window_get_hadjustment (gtk_scrolled),
@ -510,13 +548,14 @@ do_motion_scroll (KatzeScrolled* scrolled,
guint32 timestamp) guint32 timestamp)
{ {
KatzeScrolledPrivate* priv = scrolled->priv; KatzeScrolledPrivate* priv = scrolled->priv;
GtkAdjustment* hadjustment;
GtkAdjustment* vadjustment;
gdouble hvalue;
gdouble vvalue;
if (priv->dragged || gtk_drag_check_threshold (widget, priv->start_x, priv->start_y, x, y)) if (priv->dragged || gtk_drag_check_threshold (widget, priv->start_x, priv->start_y, x, y))
{ {
GtkAdjustment* hadjustment;
GtkAdjustment* vadjustment;
gdouble hpage_size, hupper, hvalue, new_hvalue;
gdouble vpage_size, vupper, vvalue, new_vvalue;
if (timestamp - priv->previous_time > priv->dragging_stopped_delay || !priv->dragged) if (timestamp - priv->previous_time > priv->dragging_stopped_delay || !priv->dragged)
{ {
priv->dragged = TRUE; priv->dragged = TRUE;
@ -554,23 +593,30 @@ do_motion_scroll (KatzeScrolled* scrolled,
} }
hadjustment = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled)); hadjustment = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled));
hpage_size = gtk_adjustment_get_page_size (hadjustment);
hupper = gtk_adjustment_get_upper (hadjustment);
hvalue = gtk_adjustment_get_value (hadjustment);
new_hvalue = calculate_motion_scroll_values (hvalue,
hupper - hpage_size, x, priv->previous_x);
vadjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled)); vadjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled));
hvalue = calculate_motion_scroll_values (hadjustment->value, vpage_size = gtk_adjustment_get_page_size (vadjustment);
hadjustment->upper - hadjustment->page_size, x, priv->previous_x); vupper = gtk_adjustment_get_upper (vadjustment);
vvalue = calculate_motion_scroll_values (vadjustment->value, vvalue = gtk_adjustment_get_value (vadjustment);
vadjustment->upper - vadjustment->page_size, y, priv->previous_y); new_vvalue = calculate_motion_scroll_values (vvalue,
if (vvalue != vadjustment->value) vupper - vpage_size, y, priv->previous_y);
if (new_vvalue != vvalue)
{ {
if (hvalue != hadjustment->value) if (new_hvalue != hvalue)
{ {
disable_hadjustment (scrolled); disable_hadjustment (scrolled);
gtk_adjustment_set_value (hadjustment, hvalue); gtk_adjustment_set_value (hadjustment, new_hvalue);
enable_hadjustment (scrolled); enable_hadjustment (scrolled);
} }
gtk_adjustment_set_value (vadjustment, vvalue); gtk_adjustment_set_value (vadjustment, new_vvalue);
} }
else if (hvalue != hadjustment->value) else if (new_hvalue != hvalue)
gtk_adjustment_set_value (hadjustment, hvalue); gtk_adjustment_set_value (hadjustment, new_hvalue);
} }
priv->previous_y = y; priv->previous_y = y;
@ -611,7 +657,8 @@ button_press_event (GtkWidget* widget,
g_source_remove (priv->scrolling_timeout_id); g_source_remove (priv->scrolling_timeout_id);
priv->scrolling_timeout_id = 0; priv->scrolling_timeout_id = 0;
} }
gdk_window_get_pointer (GTK_WIDGET (scrolled)->window, &x, &y, &mask); gdk_window_get_pointer (gtk_widget_get_window (GTK_WIDGET (scrolled)),
&x, &y, &mask);
/* do_motion_scroll (scrolled, widget, x, y, event->time); */ /* do_motion_scroll (scrolled, widget, x, y, event->time); */
} }
else else
@ -627,24 +674,29 @@ button_press_event (GtkWidget* widget,
priv->dragged = FALSE; priv->dragged = FALSE;
priv->previous_time = event->time; priv->previous_time = event->time;
} }
gdk_window_get_pointer (GTK_WIDGET (scrolled)->window, &x, &y, &mask); gdk_window_get_pointer (gtk_widget_get_window (GTK_WIDGET (scrolled)),
&x, &y, &mask);
priv->start_x = priv->previous_x = priv->farest_x = x; priv->start_x = priv->previous_x = priv->farest_x = x;
priv->start_y = priv->previous_y = priv->farest_y = y; priv->start_y = priv->previous_y = priv->farest_y = y;
priv->start_time = event->time; priv->start_time = event->time;
} }
if (priv->scrolling_hints && !GTK_SCROLLED_WINDOW (scrolled)->hscrollbar_visible && if (priv->scrolling_hints
adjust_scrollbar (scrolled, priv->horizontal_scrollbar_window, && !gtk_widget_get_visible (gtk_scrolled_window_get_hscrollbar (
gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled)), GTK_SCROLLED_WINDOW (scrolled)))
&priv->horizontal_scrollbar_size, FALSE)) && adjust_scrollbar (scrolled, priv->horizontal_scrollbar_window,
gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled)),
&priv->horizontal_scrollbar_size, FALSE))
{ {
gdk_window_raise (priv->horizontal_scrollbar_window); gdk_window_raise (priv->horizontal_scrollbar_window);
gdk_window_show (priv->horizontal_scrollbar_window); gdk_window_show (priv->horizontal_scrollbar_window);
} }
if (priv->scrolling_hints && !GTK_SCROLLED_WINDOW (scrolled)->vscrollbar_visible && if (priv->scrolling_hints
adjust_scrollbar (scrolled, priv->vertical_scrollbar_window, && !gtk_widget_get_visible (gtk_scrolled_window_get_vscrollbar (
gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled)), GTK_SCROLLED_WINDOW (scrolled)))
&priv->vertical_scrollbar_size, TRUE)) && adjust_scrollbar (scrolled, priv->vertical_scrollbar_window,
gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled)),
&priv->vertical_scrollbar_size, TRUE))
{ {
gdk_window_raise (priv->vertical_scrollbar_window); gdk_window_raise (priv->vertical_scrollbar_window);
gdk_window_show (priv->vertical_scrollbar_window); gdk_window_show (priv->vertical_scrollbar_window);
@ -668,7 +720,8 @@ button_release_event (GtkWidget* widget,
gint y; gint y;
GdkModifierType mask; GdkModifierType mask;
gdk_window_get_pointer (GTK_WIDGET (scrolled)->window, &x, &y, &mask); gdk_window_get_pointer (gtk_widget_get_window (GTK_WIDGET (scrolled)),
&x, &y, &mask);
if (priv->press_received && if (priv->press_received &&
gtk_drag_check_threshold (widget, priv->start_x, priv->start_y, x, y)) { gtk_drag_check_threshold (widget, priv->start_x, priv->start_y, x, y)) {
priv->dragged = TRUE; priv->dragged = TRUE;
@ -713,7 +766,8 @@ motion_notify_event (GtkWidget* widget,
if (priv->press_received) if (priv->press_received)
{ {
gdk_window_get_pointer (GTK_WIDGET (scrolled)->window, &x, &y, &mask); gdk_window_get_pointer (gtk_widget_get_window (GTK_WIDGET (scrolled)),
&x, &y, &mask);
do_motion_scroll (scrolled, widget, x, y, event->time); do_motion_scroll (scrolled, widget, x, y, event->time);
} }
@ -756,7 +810,8 @@ katze_scrolled_event_handler (GdkEvent* event,
crossing.type = GDK_LEAVE_NOTIFY; crossing.type = GDK_LEAVE_NOTIFY;
crossing.window = event->motion.window; crossing.window = event->motion.window;
crossing.send_event = event->motion.send_event; crossing.send_event = event->motion.send_event;
crossing.subwindow = GTK_WIDGET (current_scrolled_window)->window; crossing.subwindow = gtk_widget_get_window (
GTK_WIDGET (current_scrolled_window));
crossing.time = event->motion.time; crossing.time = event->motion.time;
crossing.x = event->motion.x; crossing.x = event->motion.x;
crossing.y = event->motion.y; crossing.y = event->motion.y;
@ -787,7 +842,8 @@ katze_scrolled_event_handler (GdkEvent* event,
crossing.type = GDK_ENTER_NOTIFY; crossing.type = GDK_ENTER_NOTIFY;
crossing.window = event->button.window; crossing.window = event->button.window;
crossing.send_event = event->button.send_event; crossing.send_event = event->button.send_event;
crossing.subwindow = GTK_WIDGET (current_scrolled_window)->window; crossing.subwindow = gtk_widget_get_window (
GTK_WIDGET (current_scrolled_window));
crossing.time = event->button.time; crossing.time = event->button.time;
crossing.x = event->button.x; crossing.x = event->button.x;
crossing.y = event->button.y; crossing.y = event->button.y;
@ -821,6 +877,7 @@ katze_scrolled_realize (GtkWidget* widget)
KatzeScrolledPrivate* priv = scrolled->priv; KatzeScrolledPrivate* priv = scrolled->priv;
gboolean drag_scrolling; gboolean drag_scrolling;
GtkPolicyType policy; GtkPolicyType policy;
GdkWindow* window;
GdkWindowAttr attr; GdkWindowAttr attr;
GdkColor color; GdkColor color;
@ -831,15 +888,16 @@ katze_scrolled_realize (GtkWidget* widget)
g_object_set (scrolled, "drag-scrolling", drag_scrolling, g_object_set (scrolled, "drag-scrolling", drag_scrolling,
"hscrollbar-policy", policy, "vscrollbar-policy", policy, NULL); "hscrollbar-policy", policy, "vscrollbar-policy", policy, NULL);
widget->window = g_object_ref (gtk_widget_get_parent_window (widget)); window = g_object_ref (gtk_widget_get_parent_window (widget));
gtk_widget_set_window (widget, window);
attr.height = attr.width = 10; attr.height = attr.width = 10;
attr.event_mask = GDK_EXPOSURE_MASK; attr.event_mask = GDK_EXPOSURE_MASK;
attr.wclass = GDK_INPUT_OUTPUT; attr.wclass = GDK_INPUT_OUTPUT;
attr.window_type = GDK_WINDOW_CHILD; attr.window_type = GDK_WINDOW_CHILD;
attr.override_redirect = TRUE; attr.override_redirect = TRUE;
priv->vertical_scrollbar_window = gdk_window_new (widget->window, &attr, 0); priv->vertical_scrollbar_window = gdk_window_new (window, &attr, 0);
priv->horizontal_scrollbar_window = gdk_window_new (widget->window, &attr, 0); priv->horizontal_scrollbar_window = gdk_window_new (window, &attr, 0);
gdk_window_set_user_data (priv->vertical_scrollbar_window, widget); gdk_window_set_user_data (priv->vertical_scrollbar_window, widget);
gdk_window_set_user_data (priv->horizontal_scrollbar_window, widget); gdk_window_set_user_data (priv->horizontal_scrollbar_window, widget);
@ -847,18 +905,18 @@ katze_scrolled_realize (GtkWidget* widget)
G_CALLBACK (on_expose_event), scrolled); G_CALLBACK (on_expose_event), scrolled);
color.red = color.green = color.blue = 0x9999; color.red = color.green = color.blue = 0x9999;
gdk_rgb_find_color (gdk_colormap_get_system (), &color); gdk_rgb_find_color (gtk_widget_get_colormap (widget), &color);
gdk_window_set_background (priv->vertical_scrollbar_window, &color); gdk_window_set_background (priv->vertical_scrollbar_window, &color);
gdk_window_set_background (priv->horizontal_scrollbar_window, &color); gdk_window_set_background (priv->horizontal_scrollbar_window, &color);
priv->hilight_gc = gdk_gc_new (widget->window); priv->hilight_gc = gdk_gc_new (window);
color.red = color.green = color.blue = 0xcccc; color.red = color.green = color.blue = 0xcccc;
gdk_gc_set_rgb_fg_color (priv->hilight_gc, &color); gdk_gc_set_rgb_fg_color (priv->hilight_gc, &color);
priv->shadow_gc = gdk_gc_new (widget->window); priv->shadow_gc = gdk_gc_new (window);
color.red = color.green = color.blue = 0x6666; color.red = color.green = color.blue = 0x6666;
gdk_gc_set_rgb_fg_color (priv->shadow_gc, &color); gdk_gc_set_rgb_fg_color (priv->shadow_gc, &color);
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); gtk_widget_set_realized (widget, TRUE);
} }
static void static void

View file

@ -48,7 +48,7 @@ struct _KatzeScrolledClass
}; };
GType GType
katze_scrolled_get_type (void); katze_scrolled_get_type (void) G_GNUC_CONST;
GtkWidget* GtkWidget*
katze_scrolled_new (GtkAdjustment* hadjustment, katze_scrolled_new (GtkAdjustment* hadjustment,

View file

@ -36,7 +36,7 @@ typedef struct _KatzeSeparatorAction KatzeSeparatorAction;
typedef struct _KatzeSeparatorActionClass KatzeSeparatorActionClass; typedef struct _KatzeSeparatorActionClass KatzeSeparatorActionClass;
GType GType
katze_separator_action_get_type (void); katze_separator_action_get_type (void) G_GNUC_CONST;
G_END_DECLS G_END_DECLS

View file

@ -16,6 +16,13 @@
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <math.h> #include <math.h>
#if !GTK_CHECK_VERSION (2, 18, 0)
#define gtk_widget_get_allocation(wdgt, alloc) *alloc = wdgt->allocation
#define gtk_widget_set_has_window(wdgt, wnd) \
if (wnd) GTK_WIDGET_UNSET_FLAGS (wdgt, GTK_NO_WINDOW); \
else GTK_WIDGET_SET_FLAGS (wdgt, GTK_NO_WINDOW)
#endif
struct _KatzeThrobber struct _KatzeThrobber
{ {
GtkMisc parent_instance; GtkMisc parent_instance;
@ -108,15 +115,20 @@ katze_throbber_timeout_destroy (KatzeThrobber* throbber);
static void static void
katze_throbber_class_init (KatzeThrobberClass* class) katze_throbber_class_init (KatzeThrobberClass* class)
{ {
GObjectClass* gobject_class = G_OBJECT_CLASS (class); GObjectClass* gobject_class;
GtkObjectClass* object_class;
GtkWidgetClass* widget_class;
GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
gobject_class = G_OBJECT_CLASS (class);
gobject_class->dispose = katze_throbber_dispose; gobject_class->dispose = katze_throbber_dispose;
gobject_class->set_property = katze_throbber_set_property; gobject_class->set_property = katze_throbber_set_property;
gobject_class->get_property = katze_throbber_get_property; gobject_class->get_property = katze_throbber_get_property;
GtkObjectClass* object_class = GTK_OBJECT_CLASS (class); object_class = GTK_OBJECT_CLASS (class);
object_class->destroy = katze_throbber_destroy; object_class->destroy = katze_throbber_destroy;
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (class); widget_class = GTK_WIDGET_CLASS (class);
widget_class->realize = katze_throbber_realize; widget_class->realize = katze_throbber_realize;
widget_class->unrealize = katze_throbber_unrealize; widget_class->unrealize = katze_throbber_unrealize;
widget_class->map = katze_throbber_map; widget_class->map = katze_throbber_map;
@ -126,8 +138,6 @@ katze_throbber_class_init (KatzeThrobberClass* class)
widget_class->size_request = katze_throbber_size_request; widget_class->size_request = katze_throbber_size_request;
widget_class->expose_event = katze_throbber_expose_event; widget_class->expose_event = katze_throbber_expose_event;
GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_ICON_SIZE, PROP_ICON_SIZE,
g_param_spec_int ( g_param_spec_int (
@ -195,7 +205,7 @@ katze_throbber_class_init (KatzeThrobberClass* class)
static void static void
katze_throbber_init (KatzeThrobber *throbber) katze_throbber_init (KatzeThrobber *throbber)
{ {
GTK_WIDGET_SET_FLAGS (throbber, GTK_NO_WINDOW); gtk_widget_set_has_window (GTK_WIDGET (throbber), FALSE);
throbber->timer_id = -1; throbber->timer_id = -1;
} }
@ -790,16 +800,20 @@ katze_throbber_aligned_coords (GtkWidget* widget,
{ {
gfloat xalign, yalign; gfloat xalign, yalign;
gint xpad, ypad; gint xpad, ypad;
GtkAllocation allocation;
GtkRequisition requisition;
gtk_misc_get_alignment (GTK_MISC (widget), &xalign, &yalign); gtk_misc_get_alignment (GTK_MISC (widget), &xalign, &yalign);
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
xalign = 1.0f - xalign; xalign = 1.0f - xalign;
gtk_misc_get_padding (GTK_MISC (widget), &xpad, &ypad); gtk_misc_get_padding (GTK_MISC (widget), &xpad, &ypad);
*ax = floor (widget->allocation.x + xpad gtk_widget_get_allocation (widget, &allocation);
+ ((widget->allocation.width - widget->requisition.width) * xalign)); gtk_widget_size_request (widget, &requisition);
*ay = floor (widget->allocation.y + ypad *ax = floor (allocation.x + xpad
+ ((widget->allocation.height - widget->requisition.height) * yalign)); + ((allocation.width - requisition.width) * xalign));
*ay = floor (allocation.y + ypad
+ ((allocation.height - requisition.height) * yalign));
} }
static gboolean static gboolean
@ -855,6 +869,8 @@ katze_throbber_expose_event (GtkWidget* widget,
} }
else else
{ {
gint cols, rows;
if (G_UNLIKELY (throbber->icon_name && !throbber->pixbuf)) if (G_UNLIKELY (throbber->icon_name && !throbber->pixbuf))
{ {
icon_theme_changed (KATZE_THROBBER (widget)); icon_theme_changed (KATZE_THROBBER (widget));
@ -868,8 +884,8 @@ katze_throbber_expose_event (GtkWidget* widget,
} }
} }
gint cols = gdk_pixbuf_get_width (throbber->pixbuf) / throbber->width; cols = gdk_pixbuf_get_width (throbber->pixbuf) / throbber->width;
gint rows = gdk_pixbuf_get_height (throbber->pixbuf) / throbber->height; rows = gdk_pixbuf_get_height (throbber->pixbuf) / throbber->height;
if (G_UNLIKELY (cols == 1 && cols == rows)) if (G_UNLIKELY (cols == 1 && cols == rows))
{ {

View file

@ -45,7 +45,7 @@ struct _KatzeThrobberClass
}; };
GType GType
katze_throbber_get_type (void); katze_throbber_get_type (void) G_GNUC_CONST;
GtkWidget* GtkWidget*
katze_throbber_new (void); katze_throbber_new (void);

View file

@ -21,22 +21,33 @@
#include "config.h" #include "config.h"
#endif #endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_HILDON_2_2 #ifdef HAVE_HILDON_2_2
#include <hildon/hildon.h> #include <hildon/hildon.h>
#endif #endif
#if !GTK_CHECK_VERSION (2, 18, 0)
#define gtk_widget_get_has_window(wdgt) !GTK_WIDGET_NO_WINDOW (wdgt)
#define gtk_widget_get_allocation(wdgt, alloc) *alloc = wdgt->allocation
#endif
static void static void
proxy_toggle_button_toggled_cb (GtkToggleButton* button, proxy_toggle_button_toggled_cb (GtkToggleButton* button,
GObject* object) GObject* object)
{ {
gboolean toggled; gboolean toggled;
const gchar* property;
#ifdef HAVE_HILDON_2_2 #ifdef HAVE_HILDON_2_2
if (HILDON_IS_CHECK_BUTTON (button)) if (HILDON_IS_CHECK_BUTTON (button))
toggled = hildon_check_button_get_active (HILDON_CHECK_BUTTON (button)); toggled = hildon_check_button_get_active (HILDON_CHECK_BUTTON (button));
#else #else
toggled = gtk_toggle_button_get_active (button); toggled = gtk_toggle_button_get_active (button);
#endif #endif
const gchar* property = g_object_get_data (G_OBJECT (button), "property"); property = g_object_get_data (G_OBJECT (button), "property");
g_object_set (object, property, toggled, NULL); g_object_set (object, property, toggled, NULL);
} }
@ -616,8 +627,12 @@ katze_property_proxy (gpointer object,
GtkComboBox* combo; GtkComboBox* combo;
GList* apps; GList* apps;
const gchar* app_type = &hint[12]; const gchar* app_type = &hint[12];
GtkSettings* settings;
gint icon_width = 16; gint icon_width = 16;
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, NULL);
settings = gtk_settings_get_for_screen (gdk_screen_get_default ());
gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU,
&icon_width, NULL);
model = gtk_list_store_new (4, G_TYPE_APP_INFO, G_TYPE_STRING, model = gtk_list_store_new (4, G_TYPE_APP_INFO, G_TYPE_STRING,
G_TYPE_STRING, G_TYPE_INT); G_TYPE_STRING, G_TYPE_INT);
@ -906,21 +921,24 @@ katze_widget_popup_position_menu (GtkMenu* menu,
{ {
gint wx, wy; gint wx, wy;
gint menu_width; gint menu_width;
GtkAllocation allocation;
GtkRequisition menu_req; GtkRequisition menu_req;
GtkRequisition widget_req; GtkRequisition widget_req;
KatzePopupInfo* info = user_data; KatzePopupInfo* info = user_data;
GtkWidget* widget = info->widget; GtkWidget* widget = info->widget;
gint widget_height; gint widget_height;
gtk_widget_get_allocation (widget, &allocation);
/* Retrieve size and position of both widget and menu */ /* Retrieve size and position of both widget and menu */
if (GTK_WIDGET_NO_WINDOW (widget)) if (!gtk_widget_get_has_window (widget))
{ {
gdk_window_get_position (widget->window, &wx, &wy); gdk_window_get_position (gtk_widget_get_window (widget), &wx, &wy);
wx += widget->allocation.x; wx += allocation.x;
wy += widget->allocation.y; wy += allocation.y;
} }
else else
gdk_window_get_origin (widget->window, &wx, &wy); gdk_window_get_origin (gtk_widget_get_window (widget), &wx, &wy);
gtk_widget_size_request (GTK_WIDGET (menu), &menu_req); gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
gtk_widget_size_request (widget, &widget_req); gtk_widget_size_request (widget, &widget_req);
menu_width = menu_req.width; menu_width = menu_req.width;
@ -931,7 +949,7 @@ katze_widget_popup_position_menu (GtkMenu* menu,
; /* Do nothing? */ ; /* Do nothing? */
else if (info->position == KATZE_MENU_POSITION_RIGHT) else if (info->position == KATZE_MENU_POSITION_RIGHT)
{ {
*x = wx + widget->allocation.width - menu_width; *x = wx + allocation.width - menu_width;
*y = wy + widget_height; *y = wy + widget_height;
} else if (info->position == KATZE_MENU_POSITION_LEFT) } else if (info->position == KATZE_MENU_POSITION_LEFT)
{ {
@ -1340,7 +1358,8 @@ katze_mkdir_with_parents (const gchar* pathname,
{ {
gchar* fn, *p; gchar* fn, *p;
if (g_file_test (pathname, G_FILE_TEST_EXISTS)) /* Use g_access instead of g_file_test for better performance */
if (g_access (pathname, F_OK) == 0)
return 0; return 0;
fn = g_strdup (pathname); fn = g_strdup (pathname);
@ -1360,7 +1379,7 @@ katze_mkdir_with_parents (const gchar* pathname,
else else
*p = '\0'; *p = '\0';
if (!g_file_test (fn, G_FILE_TEST_EXISTS)) if (g_access (fn, F_OK) != 0)
{ {
if (g_mkdir (fn, mode) == -1) if (g_mkdir (fn, mode) == -1)
{ {
@ -1452,17 +1471,18 @@ katze_load_cached_icon (const gchar* uri,
i++; i++;
if (uri[i] == '/') if (uri[i] == '/')
{ {
icon_uri = g_strdup (uri); gchar* ticon_uri = g_strdup (uri);
icon_uri[i] = '\0'; ticon_uri[i] = '\0';
icon_uri = g_strdup_printf ("%s/favicon.ico", icon_uri); icon_uri = g_strdup_printf ("%s/favicon.ico", ticon_uri);
g_free (ticon_uri);
} }
else else
icon_uri = g_strdup_printf ("%s/favicon.ico", uri); icon_uri = g_strdup_printf ("%s/favicon.ico", uri);
checksum = g_compute_checksum_for_string (G_CHECKSUM_MD5, icon_uri, -1); checksum = g_compute_checksum_for_string (G_CHECKSUM_MD5, icon_uri, -1);
ext = g_strrstr (icon_uri, "."); ext = g_strrstr (icon_uri, ".");
g_free (icon_uri);
filename = g_strdup_printf ("%s%s", checksum, ext ? ext : ""); filename = g_strdup_printf ("%s%s", checksum, ext ? ext : "");
g_free (icon_uri);
g_free (checksum); g_free (checksum);
path = g_build_filename (g_get_user_cache_dir (), PACKAGE_NAME, path = g_build_filename (g_get_user_cache_dir (), PACKAGE_NAME,
"icons", filename, NULL); "icons", filename, NULL);
@ -1477,3 +1497,96 @@ katze_load_cached_icon (const gchar* uri,
return icon || !widget ? icon : gtk_widget_render_icon (widget, return icon || !widget ? icon : gtk_widget_render_icon (widget,
GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL); GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL);
} }
/**
* katze_collfold:
* @str: a non-NULL UTF-8 string
*
* Computes a string without case and decomposited so
* it can be used for comparison.
*
* Return value: a normalized string
*
* Since: 0.2.3
**/
gchar*
katze_collfold (const gchar* str)
{
GString* result = g_string_new (NULL);
const gchar* p = str;
while (*p)
{
gunichar ch = g_unichar_tolower (g_utf8_get_char (p));
gsize len;
gunichar* sch = g_unicode_canonical_decomposition (ch, &len);
guint i = 0;
while (i < len)
g_string_append_unichar (result, sch[i++]);
p = g_utf8_next_char (p);
}
return g_string_free (result, FALSE);
}
/**
* katze_utf8_stristr:
* @haystack: a non-NULL UTF-8 string
* @needle: a normalized non-NULL UTF-8 string
*
* Determines whether @needle is in @haystack, disregarding
* differences in case.
*
* Return value: %TRUE if @needle is found in @haystack
*
* Since: 0.2.3
**/
gboolean
katze_utf8_stristr (const gchar* haystack,
const gchar* needle)
{
#if 0 /* 0,000159 seconds */
/* Too slow for use in completion */
gchar* nhaystack = g_utf8_normalize (haystack, -1, G_NORMALIZE_DEFAULT);
const gchar *p = nhaystack;
gsize len = strlen (needle);
gsize i;
while (*p)
{
for (i = 0; i < len; i++)
if (g_unichar_tolower (g_utf8_get_char (p + i))
!= g_unichar_tolower (g_utf8_get_char (needle + i)))
goto next;
g_free (nhaystack);
return TRUE;
next:
p = g_utf8_next_char (p);
}
g_free (nhaystack);
return FALSE;
#else /* 0,000044 seconds */
/* No unicode matching */
const gchar *p = haystack;
gsize len = strlen (needle);
gsize i;
while (*p)
{
for (i = 0; i < len; i++)
if (g_ascii_tolower (p[i]) != g_ascii_tolower (needle[i]))
goto next;
return TRUE;
next:
p++;
}
return FALSE;
#endif
}

View file

@ -151,6 +151,13 @@ GdkPixbuf*
katze_load_cached_icon (const gchar* uri, katze_load_cached_icon (const gchar* uri,
GtkWidget* widget); GtkWidget* widget);
gchar*
katze_collfold (const gchar* str);
gboolean
katze_utf8_stristr (const gchar* haystack,
const gchar* needle);
G_END_DECLS G_END_DECLS
#endif /* __KATZE_UTILS_H__ */ #endif /* __KATZE_UTILS_H__ */

View file

@ -1,2 +0,0 @@
VOID:POINTER,INT
BOOLEAN:OBJECT,UINT

View file

@ -1,14 +0,0 @@
#! /usr/bin/env python
# WAF build script for midori
# This file is licensed under the terms of the expat license, see the file EXPAT.
import platform
obj = bld.new_task_gen ('cc', 'staticlib')
obj.name = 'katze'
obj.target = 'katze'
obj.includes = '. ../.'
obj.find_sources_in_dirs ('.')
obj.add_marshal_file ('marshal.list', 'katze_cclosure_marshal')
obj.uselib = 'M GMODULE LIBSOUP GTK HILDON LIBXML WEBKIT'
obj.install_path = None

View file

@ -1,67 +0,0 @@
/*
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 "compat.h"
#include <string.h>
#if !GTK_CHECK_VERSION (2, 14, 0)
gboolean
gtk_show_uri (GdkScreen* screen,
const gchar* uri,
guint32 timestamp,
GError** error)
{
g_return_val_if_fail (uri != NULL, FALSE);
return g_app_info_launch_default_for_uri (uri, NULL, NULL);
}
#endif
#if !GTK_CHECK_VERSION(2, 12, 0)
void
gtk_widget_set_has_tooltip (GtkWidget* widget,
gboolean has_tooltip)
{
/* Do nothing */
}
void
gtk_widget_set_tooltip_text (GtkWidget* widget,
const gchar* text)
{
if (text && *text)
{
static GtkTooltips* tooltips = NULL;
if (G_UNLIKELY (!tooltips))
tooltips = gtk_tooltips_new ();
gtk_tooltips_set_tip (tooltips, widget, text, NULL);
}
}
void
gtk_tool_item_set_tooltip_text (GtkToolItem* toolitem,
const gchar* text)
{
if (text && *text)
{
static GtkTooltips* tooltips = NULL;
if (G_UNLIKELY (!tooltips))
tooltips = gtk_tooltips_new ();
gtk_tool_item_set_tooltip (toolitem, tooltips, text, NULL);
}
}
#endif

View file

@ -1,56 +0,0 @@
/*
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.
*/
#ifndef __COMPAT_H__
#define __COMPAT_H__
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <webkit/webkit.h>
G_BEGIN_DECLS
#if !GLIB_CHECK_VERSION (2, 14, 0)
#define G_PARAM_STATIC_STRINGS \
(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
#endif
#if !GTK_CHECK_VERSION (2, 14, 0)
gboolean
gtk_show_uri (GdkScreen* screen,
const gchar* uri,
guint32 timestamp,
GError** error);
#endif
#if !GTK_CHECK_VERSION(2, 12, 0)
void
gtk_widget_set_has_tooltip (GtkWidget* widget,
gboolean has_tooltip);
void
gtk_widget_set_tooltip_text (GtkWidget* widget,
const gchar* text);
void
gtk_tool_item_set_tooltip_text (GtkToolItem* toolitem,
const gchar* text);
#endif
G_END_DECLS
#endif /* __COMPAT_H__ */

View file

@ -86,6 +86,7 @@ typedef struct
typedef struct _GtkIconEntryPrivate typedef struct _GtkIconEntryPrivate
{ {
gdouble fraction;
EntryIconInfo icons[MAX_ICONS]; EntryIconInfo icons[MAX_ICONS];
gulong icon_released_id; gulong icon_released_id;
@ -314,9 +315,313 @@ gtk_icon_entry_editable_init (GtkEditableClass *iface)
{ {
}; };
/* GTK+/ GtkEntry internal helper function
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
Modified by the GTK+ Team and others 1997-2000
Copied from Gtk+ 2.13, whitespace adjusted */
static void
gtk_entry_get_pixel_ranges (GtkEntry *entry,
gint **ranges,
gint *n_ranges)
{
gint start_char, end_char;
if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry),
&start_char, &end_char))
{
PangoLayout *layout = gtk_entry_get_layout (entry);
PangoLayoutLine *line = pango_layout_get_lines (layout)->data;
const char *text = pango_layout_get_text (layout);
gsize start_index = g_utf8_offset_to_pointer (text, start_char) - text;
gsize end_index = g_utf8_offset_to_pointer (text, end_char) - text;
gint real_n_ranges, i;
pango_layout_line_get_x_ranges (line,
start_index, end_index, ranges, &real_n_ranges);
if (ranges)
{
gint *r = *ranges;
for (i = 0; i < real_n_ranges; ++i)
{
r[2 * i + 1] = (r[2 * i + 1] - r[2 * i]) / PANGO_SCALE;
r[2 * i] = r[2 * i] / PANGO_SCALE;
}
}
if (n_ranges)
*n_ranges = real_n_ranges;
}
else
{
if (n_ranges)
*n_ranges = 0;
if (ranges)
*ranges = NULL;
}
}
/* GTK+/ GtkEntry internal helper function
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
Modified by the GTK+ Team and others 1997-2000
Copied from Gtk+ 2.13, whitespace adjusted
Code adjusted to not rely on internal qdata */
static void
_gtk_entry_effective_inner_border (GtkEntry *entry,
GtkBorder *border)
{
static const GtkBorder default_inner_border = { 2, 2, 2, 2 };
GtkBorder *tmp_border;
tmp_border = (GtkBorder*) gtk_entry_get_inner_border (entry);
if (tmp_border)
{
*border = *tmp_border;
return;
}
gtk_widget_style_get (GTK_WIDGET (entry), "inner-border", &tmp_border, NULL);
if (tmp_border)
{
*border = *tmp_border;
gtk_border_free (tmp_border);
return;
}
*border = default_inner_border;
}
static void
gtk_entry_borders (GtkEntry* entry,
gint* xborder,
gint* yborder,
gboolean* interior_focus,
gint* focus_width)
{
GtkWidget *widget = GTK_WIDGET (entry);
if (entry->has_frame)
{
*xborder = widget->style->xthickness;
*yborder = widget->style->ythickness;
}
else
{
*xborder = 0;
*yborder = 0;
}
gtk_widget_style_get (widget, "interior-focus", interior_focus,
"focus-line-width", focus_width, NULL);
if (interior_focus)
{
*xborder += *focus_width;
*yborder += *focus_width;
}
}
/* GTK+/ GtkEntry internal helper function
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
Modified by the GTK+ Team and others 1997-2000
Copied from Gtk+ 2.13, whitespace adjusted */
static void
gtk_entry_get_text_area_size (GtkEntry *entry,
gint *x,
gint *y,
gint *width,
gint *height)
{
gint frame_height;
gint xborder, yborder;
gboolean interior_focus;
gint focus_width;
GtkRequisition requisition;
GtkWidget *widget = GTK_WIDGET (entry);
gtk_widget_get_child_requisition (widget, &requisition);
gtk_entry_borders (entry, &xborder, &yborder, &interior_focus, &focus_width);
if (GTK_WIDGET_REALIZED (widget))
gdk_drawable_get_size (widget->window, NULL, &frame_height);
else
frame_height = requisition.height;
if (GTK_WIDGET_HAS_FOCUS (widget) && interior_focus)
frame_height -= 2 * focus_width;
if (x)
*x = xborder;
if (y)
*y = frame_height / 2 - (requisition.height - yborder * 2) / 2;
if (width)
*width = GTK_WIDGET (entry)->allocation.width - xborder * 2;
if (height)
*height = requisition.height - yborder * 2;
}
/* GTK+/ GtkEntry internal helper function
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
Modified by the GTK+ Team and others 1997-2000
Copied from Gtk+ 2.13, whitespace adjusted */
static void
get_layout_position (GtkEntry *entry,
gint *x,
gint *y)
{
PangoLayout *layout;
PangoRectangle logical_rect;
gint area_width, area_height;
GtkBorder inner_border;
gint y_pos;
PangoLayoutLine *line;
layout = gtk_entry_get_layout (entry);
gtk_entry_get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
_gtk_entry_effective_inner_border (entry, &inner_border);
area_height = PANGO_SCALE *
(area_height - inner_border.top - inner_border.bottom);
line = pango_layout_get_lines (layout)->data;
pango_layout_line_get_extents (line, NULL, &logical_rect);
/* Align primarily for locale's ascent/descent */
y_pos = ((area_height - entry->ascent - entry->descent) / 2 +
entry->ascent + logical_rect.y);
/* Now see if we need to adjust to fit in actual drawn string */
if (logical_rect.height > area_height)
y_pos = (area_height - logical_rect.height) / 2;
else if (y_pos < 0)
y_pos = 0;
else if (y_pos + logical_rect.height > area_height)
y_pos = area_height - logical_rect.height;
y_pos = inner_border.top + y_pos / PANGO_SCALE;
if (x)
*x = inner_border.left - entry->scroll_offset;
if (y)
*y = y_pos;
}
/* GTK+/ GtkEntry internal helper function
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
Modified by the GTK+ Team and others 1997-2000
Copied from Gtk+ 2.13, whitespace adjusted
Code adjusted to not rely on internal _gtk_entry_ensure_layout */
static void
gtk_entry_draw_text (GtkEntry *entry)
{
GtkWidget *widget;
if (!entry->visible && entry->invisible_char == 0)
return;
if (GTK_WIDGET_DRAWABLE (entry))
{
PangoLayout *layout = gtk_entry_get_layout (entry);
cairo_t *cr;
gint x, y;
gint start_pos, end_pos;
widget = GTK_WIDGET (entry);
get_layout_position (entry, &x, &y);
cr = gdk_cairo_create (entry->text_area);
cairo_move_to (cr, x, y);
gdk_cairo_set_source_color (cr, &widget->style->text [widget->state]);
pango_cairo_show_layout (cr, layout);
if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry),
&start_pos, &end_pos))
{
gint *ranges;
gint n_ranges, i;
PangoRectangle logical_rect;
GdkColor *selection_color, *text_color;
GtkBorder inner_border;
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges);
if (GTK_WIDGET_HAS_FOCUS (entry))
{
selection_color = &widget->style->base [GTK_STATE_SELECTED];
text_color = &widget->style->text [GTK_STATE_SELECTED];
}
else
{
selection_color = &widget->style->base [GTK_STATE_ACTIVE];
text_color = &widget->style->text [GTK_STATE_ACTIVE];
}
_gtk_entry_effective_inner_border (entry, &inner_border);
for (i = 0; i < n_ranges; ++i)
cairo_rectangle (cr,
inner_border.left -
entry->scroll_offset + ranges[2 * i],
y,
ranges[2 * i + 1],
logical_rect.height);
cairo_clip (cr);
gdk_cairo_set_source_color (cr, selection_color);
cairo_paint (cr);
cairo_move_to (cr, x, y);
gdk_cairo_set_source_color (cr, text_color);
pango_cairo_show_layout (cr, layout);
g_free (ranges);
}
cairo_destroy (cr);
}
}
static gboolean
entry_expose_event (GtkWidget* entry,
GdkEventExpose* event,
GtkIconEntry* icon_entry)
{
GtkIconEntryPrivate *priv;
GdkWindow* text_area;
gint width, height;
priv = GTK_ICON_ENTRY_GET_PRIVATE (icon_entry);
text_area = GTK_ENTRY (entry)->text_area;
gdk_drawable_get_size (text_area, &width, &height);
if (priv->fraction > 0.0)
{
gtk_paint_box (entry->style, text_area,
GTK_STATE_SELECTED, GTK_SHADOW_OUT,
&event->area, entry, "entry-progress",
0, 0, priv->fraction * width, height);
gtk_entry_draw_text (GTK_ENTRY (entry));
}
return FALSE;
}
static void static void
gtk_icon_entry_init (GtkIconEntry *entry) gtk_icon_entry_init (GtkIconEntry *entry)
{ {
g_signal_connect_after (entry, "expose-event",
G_CALLBACK (entry_expose_event), entry);
} }
static void static void
@ -1380,7 +1685,7 @@ gtk_icon_entry_set_icon_from_gicon (const GtkIconEntry *entry,
GTK_ICON_SIZE_MENU, GTK_ICON_SIZE_MENU,
&width, &height); &width, &height);
#if #GTK_CHECK_VERSION (2, 14, 0) #if GTK_CHECK_VERSION (2, 14, 0)
info = gtk_icon_theme_lookup_by_gicon (icon_theme, info = gtk_icon_theme_lookup_by_gicon (icon_theme,
icon, icon,
MIN (width, height), 0); MIN (width, height), 0);
@ -1609,4 +1914,19 @@ gtk_icon_entry_set_icon_sensitive (const GtkIconEntry *icon_entry,
} }
} }
void
gtk_icon_entry_set_progress_fraction (GtkIconEntry *icon_entry,
gdouble fraction)
{
GtkIconEntryPrivate *priv;
g_return_if_fail (GTK_IS_ICON_ENTRY (icon_entry));
priv = GTK_ICON_ENTRY_GET_PRIVATE (icon_entry);
priv->fraction = CLAMP (fraction, 0.0, 1.0);
if (GTK_ENTRY (icon_entry)->text_area)
gdk_window_invalidate_rect (GTK_ENTRY (icon_entry)->text_area, NULL, FALSE);
}
#endif #endif

View file

@ -46,6 +46,7 @@ G_BEGIN_DECLS
GtkEntryIconPosition position, GtkEntryIconPosition position,
GdkPixbuf* pixbuf); GdkPixbuf* pixbuf);
#define gtk_icon_entry_set_icon_highlight gtk_entry_set_icon_activatable #define gtk_icon_entry_set_icon_highlight gtk_entry_set_icon_activatable
#define gtk_icon_entry_set_progress_fraction gtk_entry_set_progress_fraction
#else #else
#define GTK_TYPE_ICON_ENTRY (gtk_icon_entry_get_type()) #define GTK_TYPE_ICON_ENTRY (gtk_icon_entry_get_type())
@ -130,6 +131,9 @@ void gtk_icon_entry_set_icon_sensitive (const GtkIconEntry *icon_entr
GtkIconEntryPosition icon_pos, GtkIconEntryPosition icon_pos,
gboolean sensitive); gboolean sensitive);
void gtk_icon_entry_set_progress_fraction (GtkIconEntry *icon_entry,
gdouble fraction);
#endif #endif
G_END_DECLS G_END_DECLS

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,10 @@
BOOLEAN:OBJECT BOOLEAN:OBJECT
BOOLEAN:OBJECT,UINT
BOOLEAN:VOID BOOLEAN:VOID
OBJECT:OBJECT OBJECT:OBJECT
VOID:BOOLEAN,STRING VOID:BOOLEAN,STRING
VOID:OBJECT,ENUM VOID:OBJECT,ENUM
VOID:POINTER,INT
VOID:STRING,BOOLEAN VOID:STRING,BOOLEAN
VOID:STRING,INT,STRING VOID:STRING,INT,STRING
VOID:STRING,STRING VOID:STRING,STRING

View file

@ -62,7 +62,7 @@ struct _MidoriApp
MidoriAppInstance instance; MidoriAppInstance instance;
#if !HAVE_HILDON #if !HAVE_HILDON || !HAVE_LIBNOTIFY
gchar* program_notify_send; gchar* program_notify_send;
#endif #endif
}; };
@ -172,7 +172,10 @@ midori_browser_destroy_cb (MidoriBrowser* browser,
g_signal_emit (app, signals[REMOVE_BROWSER], 0, browser); g_signal_emit (app, signals[REMOVE_BROWSER], 0, browser);
katze_array_remove_item (app->browsers, browser); katze_array_remove_item (app->browsers, browser);
if (!katze_array_is_empty (app->browsers)) if (!katze_array_is_empty (app->browsers))
{
app->browser = katze_array_get_nth_item (app->browsers, 0);
return FALSE; return FALSE;
}
midori_app_quit (app); midori_app_quit (app);
return TRUE; return TRUE;
} }
@ -206,8 +209,10 @@ _midori_app_add_browser (MidoriApp* app,
app->browser = browser; app->browser = browser;
#if HAVE_UNIQUE #if HAVE_UNIQUE
/* We *do not* let unique watch windows because that includes
bringing windows in the foreground, even from other workspaces.
if (app->instance) if (app->instance)
unique_app_watch_window (app->instance, GTK_WINDOW (browser)); unique_app_watch_window (app->instance, GTK_WINDOW (browser)); */
#endif #endif
} }
@ -391,6 +396,15 @@ midori_app_class_init (MidoriAppClass* class)
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
} }
static void
midori_app_raise_window (GtkWindow* window,
GdkScreen* screen)
{
gtk_window_set_screen (window, screen);
gtk_window_present (window);
gtk_window_deiconify (window);
}
static gboolean static gboolean
midori_app_command_received (MidoriApp* app, midori_app_command_received (MidoriApp* app,
const gchar* command, const gchar* command,
@ -410,8 +424,7 @@ midori_app_command_received (MidoriApp* app,
if (!app->browser) if (!app->browser)
return FALSE; return FALSE;
gtk_window_set_screen (GTK_WINDOW (app->browser), screen); midori_app_raise_window (GTK_WINDOW (app->browser), screen);
gtk_window_present (GTK_WINDOW (app->browser));
return TRUE; return TRUE;
} }
else if (g_str_equal (command, "new")) else if (g_str_equal (command, "new"))
@ -421,8 +434,8 @@ midori_app_command_received (MidoriApp* app,
/* FIXME: Should open the homepage according to settings */ /* FIXME: Should open the homepage according to settings */
midori_browser_add_uri (browser, ""); midori_browser_add_uri (browser, "");
midori_browser_activate_action (browser, "Location"); midori_browser_activate_action (browser, "Location");
gtk_window_set_screen (GTK_WINDOW (app->browser), screen);
gtk_widget_show (GTK_WIDGET (browser)); gtk_widget_show (GTK_WIDGET (browser));
midori_app_raise_window (GTK_WINDOW (browser), screen);
return TRUE; return TRUE;
} }
else if (g_str_equal (command, "open")) else if (g_str_equal (command, "open"))
@ -430,8 +443,6 @@ midori_app_command_received (MidoriApp* app,
if (!app->browser) if (!app->browser)
return FALSE; return FALSE;
gtk_window_set_screen (GTK_WINDOW (app->browser), screen);
gtk_window_present (GTK_WINDOW (app->browser));
if (!uris) if (!uris)
return FALSE; return FALSE;
else else
@ -446,15 +457,19 @@ midori_app_command_received (MidoriApp* app,
{ {
browser = midori_app_create_browser (app); browser = midori_app_create_browser (app);
midori_app_add_browser (app, browser); midori_app_add_browser (app, browser);
gtk_window_set_screen (GTK_WINDOW (app->browser), screen);
gtk_widget_show (GTK_WIDGET (browser)); gtk_widget_show (GTK_WIDGET (browser));
} }
else else
browser = app->browser; browser = app->browser;
midori_app_raise_window (GTK_WINDOW (browser), screen);
first = (open_external_pages_in == MIDORI_NEW_PAGE_CURRENT); first = (open_external_pages_in == MIDORI_NEW_PAGE_CURRENT);
while (*uris) while (*uris)
{ {
gchar* fixed_uri = sokoke_magic_uri (*uris, NULL); gchar* fixed_uri = sokoke_magic_uri (*uris);
if (!fixed_uri)
fixed_uri = g_strdup (*uris);
if (first) if (first)
{ {
midori_browser_set_current_uri (browser, fixed_uri); midori_browser_set_current_uri (browser, fixed_uri);
@ -605,8 +620,6 @@ midori_app_io_channel_watch_cb (GIOChannel* channel,
} }
} }
gtk_window_present (GTK_WINDOW (app->browser));
fd_close (sock); fd_close (sock);
return TRUE; return TRUE;
@ -706,9 +719,10 @@ midori_app_init (MidoriApp* app)
#if HAVE_LIBNOTIFY #if HAVE_LIBNOTIFY
notify_init ("midori"); notify_init ("midori");
#else
app->program_notify_send = g_find_program_in_path ("notify-send");
#endif #endif
app->program_notify_send = g_find_program_in_path ("notify-send");
} }
static void static void
@ -739,8 +753,9 @@ midori_app_finalize (GObject* object)
#if HAVE_LIBNOTIFY #if HAVE_LIBNOTIFY
if (notify_is_initted ()) if (notify_is_initted ())
notify_uninit (); notify_uninit ();
#else
katze_assign (app->program_notify_send, NULL);
#endif #endif
katze_assign (app->program_notify_send, NULL);
G_OBJECT_CLASS (midori_app_parent_class)->finalize (object); G_OBJECT_CLASS (midori_app_parent_class)->finalize (object);
} }
@ -1165,8 +1180,7 @@ midori_app_send_notification (MidoriApp* app,
sent = notify_notification_show (note, NULL); sent = notify_notification_show (note, NULL);
g_object_unref (note); g_object_unref (note);
} }
#endif #else
/* Fall back to the command line program "notify-send" */ /* Fall back to the command line program "notify-send" */
if (!sent && app->program_notify_send) if (!sent && app->program_notify_send)
{ {
@ -1182,4 +1196,5 @@ midori_app_send_notification (MidoriApp* app,
g_free (command); g_free (command);
} }
#endif #endif
#endif
} }

View file

@ -36,7 +36,7 @@ typedef struct _MidoriApp MidoriApp;
typedef struct _MidoriAppClass MidoriAppClass; typedef struct _MidoriAppClass MidoriAppClass;
GType GType
midori_app_get_type (void); midori_app_get_type (void) G_GNUC_CONST;
MidoriApp* MidoriApp*
midori_app_new (void); midori_app_new (void);

View file

@ -23,6 +23,10 @@
#include <libxml/tree.h> #include <libxml/tree.h>
#endif #endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#define katze_str_equal(str1, str2) !strcmp (str1, str2) #define katze_str_equal(str1, str2) !strcmp (str1, str2)
static void static void
@ -416,7 +420,7 @@ midori_array_from_file (KatzeArray* array,
g_return_val_if_fail (filename != NULL, FALSE); g_return_val_if_fail (filename != NULL, FALSE);
g_return_val_if_fail (!error || !*error, FALSE); g_return_val_if_fail (!error || !*error, FALSE);
if (!g_file_test (filename, G_FILE_TEST_EXISTS)) if (g_access (filename, F_OK) != 0)
{ {
/* File doesn't exist */ /* File doesn't exist */
if (error) if (error)

File diff suppressed because it is too large Load diff

View file

@ -75,7 +75,7 @@ struct _MidoriBrowserClass
}; };
GType GType
midori_browser_get_type (void); midori_browser_get_type (void) G_GNUC_CONST;
MidoriBrowser* MidoriBrowser*
midori_browser_new (void); midori_browser_new (void);

View file

@ -46,7 +46,7 @@ struct _MidoriExtensionClass
}; };
GType GType
midori_extension_get_type (void); midori_extension_get_type (void) G_GNUC_CONST;
gboolean gboolean
midori_extension_is_prepared (MidoriExtension* extension); midori_extension_is_prepared (MidoriExtension* extension);

File diff suppressed because it is too large Load diff

View file

@ -12,8 +12,6 @@
#ifndef __MIDORI_LOCATION_ACTION_H__ #ifndef __MIDORI_LOCATION_ACTION_H__
#define __MIDORI_LOCATION_ACTION_H__ #define __MIDORI_LOCATION_ACTION_H__
#include "midori-locationentry.h"
#include <katze/katze.h> #include <katze/katze.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -35,7 +33,7 @@ typedef struct _MidoriLocationAction MidoriLocationAction;
typedef struct _MidoriLocationActionClass MidoriLocationActionClass; typedef struct _MidoriLocationActionClass MidoriLocationActionClass;
GType GType
midori_location_action_get_type (void); midori_location_action_get_type (void) G_GNUC_CONST;
void void
midori_location_action_freeze (MidoriLocationAction* location_action); midori_location_action_freeze (MidoriLocationAction* location_action);

View file

@ -1,441 +0,0 @@
/*
Copyright (C) 2008 Dale Whittaker <dayul@users.sf.net>
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-locationentry.h"
#include "gtkiconentry.h"
#include "sokoke.h"
#include <gdk/gdkkeysyms.h>
struct _MidoriLocationEntry
{
GtkComboBoxEntry parent_instance;
gdouble progress;
};
struct _MidoriLocationEntryClass
{
GtkComboBoxEntryClass parent_class;
};
G_DEFINE_TYPE (MidoriLocationEntry,
midori_location_entry, GTK_TYPE_COMBO_BOX_ENTRY)
static gboolean
entry_key_press_event (GtkWidget* widget,
GdkEventKey* event,
MidoriLocationEntry* location_entry);
static void
midori_location_entry_class_init (MidoriLocationEntryClass* class)
{
}
#if !GTK_CHECK_VERSION (2, 16, 0)
/* GTK+/ GtkEntry internal helper function
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
Modified by the GTK+ Team and others 1997-2000
Copied from Gtk+ 2.13, whitespace adjusted */
static void
gtk_entry_get_pixel_ranges (GtkEntry *entry,
gint **ranges,
gint *n_ranges)
{
gint start_char, end_char;
if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry),
&start_char, &end_char))
{
PangoLayout *layout = gtk_entry_get_layout (entry);
PangoLayoutLine *line = pango_layout_get_lines (layout)->data;
const char *text = pango_layout_get_text (layout);
gsize start_index = g_utf8_offset_to_pointer (text, start_char) - text;
gsize end_index = g_utf8_offset_to_pointer (text, end_char) - text;
gint real_n_ranges, i;
pango_layout_line_get_x_ranges (line,
start_index, end_index, ranges, &real_n_ranges);
if (ranges)
{
gint *r = *ranges;
for (i = 0; i < real_n_ranges; ++i)
{
r[2 * i + 1] = (r[2 * i + 1] - r[2 * i]) / PANGO_SCALE;
r[2 * i] = r[2 * i] / PANGO_SCALE;
}
}
if (n_ranges)
*n_ranges = real_n_ranges;
}
else
{
if (n_ranges)
*n_ranges = 0;
if (ranges)
*ranges = NULL;
}
}
/* GTK+/ GtkEntry internal helper function
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
Modified by the GTK+ Team and others 1997-2000
Copied from Gtk+ 2.13, whitespace adjusted
Code adjusted to not rely on internal qdata */
static void
_gtk_entry_effective_inner_border (GtkEntry *entry,
GtkBorder *border)
{
static const GtkBorder default_inner_border = { 2, 2, 2, 2 };
GtkBorder *tmp_border;
tmp_border = (GtkBorder*) gtk_entry_get_inner_border (entry);
if (tmp_border)
{
*border = *tmp_border;
return;
}
gtk_widget_style_get (GTK_WIDGET (entry), "inner-border", &tmp_border, NULL);
if (tmp_border)
{
*border = *tmp_border;
gtk_border_free (tmp_border);
return;
}
*border = default_inner_border;
}
static void
gtk_entry_borders (GtkEntry* entry,
gint* xborder,
gint* yborder,
gboolean* interior_focus,
gint* focus_width)
{
GtkWidget *widget = GTK_WIDGET (entry);
if (entry->has_frame)
{
*xborder = widget->style->xthickness;
*yborder = widget->style->ythickness;
}
else
{
*xborder = 0;
*yborder = 0;
}
gtk_widget_style_get (widget, "interior-focus", interior_focus,
"focus-line-width", focus_width, NULL);
if (interior_focus)
{
*xborder += *focus_width;
*yborder += *focus_width;
}
}
/* GTK+/ GtkEntry internal helper function
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
Modified by the GTK+ Team and others 1997-2000
Copied from Gtk+ 2.13, whitespace adjusted */
static void
gtk_entry_get_text_area_size (GtkEntry *entry,
gint *x,
gint *y,
gint *width,
gint *height)
{
gint frame_height;
gint xborder, yborder;
gboolean interior_focus;
gint focus_width;
GtkRequisition requisition;
GtkWidget *widget = GTK_WIDGET (entry);
gtk_widget_get_child_requisition (widget, &requisition);
gtk_entry_borders (entry, &xborder, &yborder, &interior_focus, &focus_width);
if (GTK_WIDGET_REALIZED (widget))
gdk_drawable_get_size (widget->window, NULL, &frame_height);
else
frame_height = requisition.height;
if (GTK_WIDGET_HAS_FOCUS (widget) && interior_focus)
frame_height -= 2 * focus_width;
if (x)
*x = xborder;
if (y)
*y = frame_height / 2 - (requisition.height - yborder * 2) / 2;
if (width)
*width = GTK_WIDGET (entry)->allocation.width - xborder * 2;
if (height)
*height = requisition.height - yborder * 2;
}
/* GTK+/ GtkEntry internal helper function
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
Modified by the GTK+ Team and others 1997-2000
Copied from Gtk+ 2.13, whitespace adjusted */
static void
get_layout_position (GtkEntry *entry,
gint *x,
gint *y)
{
PangoLayout *layout;
PangoRectangle logical_rect;
gint area_width, area_height;
GtkBorder inner_border;
gint y_pos;
PangoLayoutLine *line;
layout = gtk_entry_get_layout (entry);
gtk_entry_get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
_gtk_entry_effective_inner_border (entry, &inner_border);
area_height = PANGO_SCALE *
(area_height - inner_border.top - inner_border.bottom);
line = pango_layout_get_lines (layout)->data;
pango_layout_line_get_extents (line, NULL, &logical_rect);
/* Align primarily for locale's ascent/descent */
y_pos = ((area_height - entry->ascent - entry->descent) / 2 +
entry->ascent + logical_rect.y);
/* Now see if we need to adjust to fit in actual drawn string */
if (logical_rect.height > area_height)
y_pos = (area_height - logical_rect.height) / 2;
else if (y_pos < 0)
y_pos = 0;
else if (y_pos + logical_rect.height > area_height)
y_pos = area_height - logical_rect.height;
y_pos = inner_border.top + y_pos / PANGO_SCALE;
if (x)
*x = inner_border.left - entry->scroll_offset;
if (y)
*y = y_pos;
}
/* GTK+/ GtkEntry internal helper function
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
Modified by the GTK+ Team and others 1997-2000
Copied from Gtk+ 2.13, whitespace adjusted
Code adjusted to not rely on internal _gtk_entry_ensure_layout */
static void
gtk_entry_draw_text (GtkEntry *entry)
{
GtkWidget *widget;
if (!entry->visible && entry->invisible_char == 0)
return;
if (GTK_WIDGET_DRAWABLE (entry))
{
PangoLayout *layout = gtk_entry_get_layout (entry);
cairo_t *cr;
gint x, y;
gint start_pos, end_pos;
widget = GTK_WIDGET (entry);
get_layout_position (entry, &x, &y);
cr = gdk_cairo_create (entry->text_area);
cairo_move_to (cr, x, y);
gdk_cairo_set_source_color (cr, &widget->style->text [widget->state]);
pango_cairo_show_layout (cr, layout);
if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry),
&start_pos, &end_pos))
{
gint *ranges;
gint n_ranges, i;
PangoRectangle logical_rect;
GdkColor *selection_color, *text_color;
GtkBorder inner_border;
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges);
if (GTK_WIDGET_HAS_FOCUS (entry))
{
selection_color = &widget->style->base [GTK_STATE_SELECTED];
text_color = &widget->style->text [GTK_STATE_SELECTED];
}
else
{
selection_color = &widget->style->base [GTK_STATE_ACTIVE];
text_color = &widget->style->text [GTK_STATE_ACTIVE];
}
_gtk_entry_effective_inner_border (entry, &inner_border);
for (i = 0; i < n_ranges; ++i)
cairo_rectangle (cr,
inner_border.left -
entry->scroll_offset + ranges[2 * i],
y,
ranges[2 * i + 1],
logical_rect.height);
cairo_clip (cr);
gdk_cairo_set_source_color (cr, selection_color);
cairo_paint (cr);
cairo_move_to (cr, x, y);
gdk_cairo_set_source_color (cr, text_color);
pango_cairo_show_layout (cr, layout);
g_free (ranges);
}
cairo_destroy (cr);
}
}
static gboolean
entry_expose_event (GtkWidget* entry,
GdkEventExpose* event,
MidoriLocationEntry* location_entry)
{
GdkWindow* text_area;
gint width, height;
text_area = GTK_ENTRY (entry)->text_area;
gdk_drawable_get_size (text_area, &width, &height);
if (location_entry->progress > 0.0)
{
gtk_paint_box (entry->style, text_area,
GTK_STATE_SELECTED, GTK_SHADOW_OUT,
&event->area, entry, "bar",
0, 0, location_entry->progress * width, height);
gtk_entry_draw_text (GTK_ENTRY (entry));
}
return FALSE;
}
#endif
void
midori_location_entry_set_progress (MidoriLocationEntry* location_entry,
gdouble progress)
{
GtkWidget* child;
g_return_if_fail (MIDORI_IS_LOCATION_ENTRY (location_entry));
location_entry->progress = CLAMP (progress, 0.0, 1.0);
child = gtk_bin_get_child (GTK_BIN (location_entry));
#if !GTK_CHECK_VERSION (2, 16, 0)
if (GTK_ENTRY (child)->text_area)
gdk_window_invalidate_rect (GTK_ENTRY (child)->text_area, NULL, FALSE);
#else
gtk_entry_set_progress_fraction (GTK_ENTRY (child), progress);
#endif
}
static void
midori_location_entry_init (MidoriLocationEntry* location_entry)
{
GtkWidget* entry;
#if HAVE_HILDON
HildonGtkInputMode mode;
#endif
/* We want the widget to have appears-as-list applied */
gtk_rc_parse_string ("style \"midori-location-entry-style\" {\n"
" GtkComboBox::appears-as-list = 1\n }\n"
"widget_class \"*MidoriLocationEntry\" "
"style \"midori-location-entry-style\"\n");
location_entry->progress = 0.0;
#if HAVE_HILDON
entry = gtk_entry_new ();
mode = hildon_gtk_entry_get_input_mode (GTK_ENTRY (entry));
mode &= ~HILDON_GTK_INPUT_MODE_AUTOCAP;
hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry), mode);
#else
entry = gtk_icon_entry_new ();
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_PRIMARY, GTK_STOCK_FILE);
gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_SECONDARY, TRUE);
#endif
g_signal_connect_after (entry, "key-press-event",
G_CALLBACK (entry_key_press_event), location_entry);
#if !GTK_CHECK_VERSION (2, 16, 0)
g_signal_connect_after (entry, "expose-event",
G_CALLBACK (entry_expose_event), location_entry);
#endif
gtk_widget_show (entry);
gtk_container_add (GTK_CONTAINER (location_entry), entry);
}
static gboolean
entry_key_press_event (GtkWidget* widget,
GdkEventKey* event,
MidoriLocationEntry* location_entry)
{
switch (event->keyval)
{
case GDK_Down:
case GDK_Up:
{
if (!katze_object_get_boolean (location_entry, "popup-shown"))
gtk_combo_box_popup (GTK_COMBO_BOX (location_entry));
return TRUE;
}
case GDK_Page_Up:
case GDK_Page_Down:
{
return TRUE;
}
}
return FALSE;
}
/**
* midori_location_entry_new:
*
* Creates a new #MidoriLocationEntry.
*
* Return value: a new #MidoriLocationEntry
**/
GtkWidget*
midori_location_entry_new (void)
{
return g_object_new (MIDORI_TYPE_LOCATION_ENTRY, NULL);
}

View file

@ -1,41 +0,0 @@
/*
Copyright (C) 2008 Dale Whittaker <dayul@users.sf.net>
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_LOCATION_ENTRY_H__
#define __MIDORI_LOCATION_ENTRY_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define MIDORI_TYPE_LOCATION_ENTRY (midori_location_entry_get_type ())
#define MIDORI_LOCATION_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_LOCATION_ENTRY, MidoriLocationEntry))
#define MIDORI_LOCATION_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_LOCATION_ENTRY, MidoriLocationEntryClass))
#define MIDORI_IS_LOCATION_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_LOCATION_ENTRY))
#define MIDORI_IS_LOCATION_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_LOCATION_ENTRY))
#define MIDORI_LOCATION_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_LOCATION_ENTRY, MidoriLocationEntryClass))
typedef struct _MidoriLocationEntry MidoriLocationEntry;
typedef struct _MidoriLocationEntryClass MidoriLocationEntryClass;
GType
midori_location_entry_get_type (void);
GtkWidget*
midori_location_entry_new (void);
void
midori_location_entry_set_progress (MidoriLocationEntry* location_entry,
gdouble progress);
G_END_DECLS
#endif /* __MIDORI_LOCATION_ENTRY_H__ */

View file

@ -13,7 +13,6 @@
#include "midori-view.h" #include "midori-view.h"
#include "compat.h"
#include "marshal.h" #include "marshal.h"
#include "sokoke.h" #include "sokoke.h"
@ -33,6 +32,7 @@ struct _MidoriPanel
GtkWidget* toolbar; GtkWidget* toolbar;
GtkToolItem* button_align; GtkToolItem* button_align;
GtkToolItem* button_detach; GtkToolItem* button_detach;
GtkToolItem* button_controls;
GtkWidget* toolbar_label; GtkWidget* toolbar_label;
GtkWidget* frame; GtkWidget* frame;
GtkWidget* toolbook; GtkWidget* toolbook;
@ -197,7 +197,7 @@ midori_panel_class_init (MidoriPanelClass* class)
* *
* Whether to show panel titles. * Whether to show panel titles.
* *
* Since: 0.1.9 * Deprecated: 0.2.3
*/ */
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_SHOW_TITLES, PROP_SHOW_TITLES,
@ -405,14 +405,13 @@ midori_panel_init (MidoriPanel* panel)
/* Create the sidebar */ /* Create the sidebar */
panel->toolbar = gtk_toolbar_new (); panel->toolbar = gtk_toolbar_new ();
gtk_toolbar_set_style (GTK_TOOLBAR (panel->toolbar), GTK_TOOLBAR_BOTH); gtk_toolbar_set_style (GTK_TOOLBAR (panel->toolbar), GTK_TOOLBAR_ICONS);
gtk_toolbar_set_icon_size (GTK_TOOLBAR (panel->toolbar), gtk_toolbar_set_icon_size (GTK_TOOLBAR (panel->toolbar), GTK_ICON_SIZE_BUTTON);
GTK_ICON_SIZE_BUTTON); gtk_toolbar_set_show_arrow (GTK_TOOLBAR (panel->toolbar), FALSE);
g_object_set (panel->toolbar, "orientation", GTK_ORIENTATION_VERTICAL, NULL);
gtk_box_pack_start (GTK_BOX (panel), panel->toolbar, FALSE, FALSE, 0);
gtk_widget_show_all (panel->toolbar); gtk_widget_show_all (panel->toolbar);
vbox = gtk_vbox_new (FALSE, 0); vbox = gtk_vbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (panel), vbox, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (panel), vbox, TRUE, TRUE, 0);
gtk_box_pack_end (GTK_BOX (vbox), panel->toolbar, FALSE, FALSE, 0);
/* Create the titlebar */ /* Create the titlebar */
labelbar = gtk_toolbar_new (); labelbar = gtk_toolbar_new ();
@ -518,13 +517,16 @@ midori_panel_set_property (GObject* object,
break; break;
case PROP_SHOW_TITLES: case PROP_SHOW_TITLES:
panel->show_titles = g_value_get_boolean (value); panel->show_titles = g_value_get_boolean (value);
gtk_toolbar_set_style (GTK_TOOLBAR (panel->toolbar), /* Ignore */
panel->show_titles ? GTK_TOOLBAR_BOTH : GTK_TOOLBAR_ICONS);
break; break;
case PROP_SHOW_CONTROLS: case PROP_SHOW_CONTROLS:
panel->show_controls = g_value_get_boolean (value); panel->show_controls = g_value_get_boolean (value);
sokoke_widget_set_visible (panel->labelbar, panel->show_controls); sokoke_widget_set_visible (panel->labelbar, panel->show_controls);
sokoke_widget_set_visible (panel->toolbar, panel->show_controls); sokoke_widget_set_visible (panel->toolbar, panel->show_controls);
if (panel->button_controls)
gtk_toggle_tool_button_set_active (
GTK_TOGGLE_TOOL_BUTTON (panel->button_controls),
!panel->show_controls);
break; break;
case PROP_RIGHT_ALIGNED: case PROP_RIGHT_ALIGNED:
midori_panel_set_right_aligned (panel, g_value_get_boolean (value)); midori_panel_set_right_aligned (panel, g_value_get_boolean (value));
@ -692,54 +694,6 @@ midori_panel_construct_tool_item (MidoriPanel* panel,
return GTK_TOOL_ITEM (toolitem); return GTK_TOOL_ITEM (toolitem);
} }
#if !HAVE_HILDON
static void
midori_panel_show_titles_toggled_cb (GtkWidget* menuitem,
MidoriPanel* panel)
{
g_object_set (panel, "show-titles", !panel->show_titles, NULL);
}
static void
midori_panel_show_controls_toggled_cb (GtkWidget* menuitem,
MidoriPanel* panel)
{
g_object_set (panel, "show-controls", !panel->show_controls, NULL);
}
static void
midori_panel_options_clicked_cb (GtkToolItem* toolitem,
MidoriPanel* panel)
{
gint n;
GtkWidget* viewable;
GtkWidget* menu;
GtkWidget* menuitem;
n = midori_panel_get_current_page (panel);
viewable = midori_panel_get_nth_page (panel, n);
menu = gtk_menu_new ();
menuitem = gtk_check_menu_item_new_with_mnemonic (_("Show panel _titles"));
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
panel->show_titles);
g_signal_connect (menuitem, "toggled",
G_CALLBACK (midori_panel_show_titles_toggled_cb), panel);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
menuitem = gtk_check_menu_item_new_with_mnemonic (_("Show operating _controls"));
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
panel->show_controls);
g_signal_connect (menuitem, "toggled",
G_CALLBACK (midori_panel_show_controls_toggled_cb), panel);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
g_signal_emit_by_name (viewable, "populate-option-menu", menu);
katze_widget_popup (GTK_WIDGET (toolitem), GTK_MENU (menu),
NULL, KATZE_MENU_POSITION_LEFT);
}
#endif
static void static void
midori_panel_action_activate_cb (GtkRadioAction* action, midori_panel_action_activate_cb (GtkRadioAction* action,
MidoriPanel* panel) MidoriPanel* panel)
@ -767,6 +721,16 @@ midori_panel_action_activate_cb (GtkRadioAction* action,
} }
} }
#if !HAVE_HILDON
static void
midori_panel_show_controls_toggled_cb (GtkWidget* menuitem,
MidoriPanel* panel)
{
if (panel->show_controls != !gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (menuitem)))
g_object_set (panel, "show-controls", !panel->show_controls, NULL);
}
#endif
/** /**
* midori_panel_append_page: * midori_panel_append_page:
* @panel: a #MidoriPanel * @panel: a #MidoriPanel
@ -830,12 +794,15 @@ midori_panel_append_page (MidoriPanel* panel,
toolbar = midori_viewable_get_toolbar (viewable); toolbar = midori_viewable_get_toolbar (viewable);
#if !HAVE_HILDON #if !HAVE_HILDON
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_PROPERTIES); toolitem = gtk_toggle_tool_button_new_from_stock (GTK_STOCK_PROPERTIES);
gtk_tool_item_set_tooltip_text (toolitem, _("Options")); gtk_tool_item_set_tooltip_text (toolitem, _("Hide operating controls"));
gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (toolitem),
!panel->show_controls);
g_signal_connect (toolitem, "clicked", g_signal_connect (toolitem, "clicked",
G_CALLBACK (midori_panel_options_clicked_cb), panel); G_CALLBACK (midori_panel_show_controls_toggled_cb), panel);
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, 0); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, 0);
gtk_widget_show (GTK_WIDGET (toolitem)); gtk_widget_show (GTK_WIDGET (toolitem));
panel->button_controls = toolitem;
#endif #endif
gtk_widget_show (toolbar); gtk_widget_show (toolbar);
gtk_container_add (GTK_CONTAINER (panel->toolbook), toolbar); gtk_container_add (GTK_CONTAINER (panel->toolbook), toolbar);
@ -848,19 +815,19 @@ midori_panel_append_page (MidoriPanel* panel,
midori_viewable_get_stock_id (viewable), NULL); midori_viewable_get_stock_id (viewable), NULL);
action = (GtkAction*)gtk_radio_action_new (action_name, action = (GtkAction*)gtk_radio_action_new (action_name,
midori_viewable_get_label (viewable), midori_viewable_get_label (viewable),
NULL, midori_viewable_get_stock_id (viewable), n); midori_viewable_get_label (viewable),
midori_viewable_get_stock_id (viewable), n);
g_object_set_data (G_OBJECT (action), "viewable", viewable); g_object_set_data (G_OBJECT (action), "viewable", viewable);
g_signal_connect (action, "activate", g_signal_connect (action, "activate",
G_CALLBACK (midori_panel_action_activate_cb), panel); G_CALLBACK (midori_panel_action_activate_cb), panel);
if (panel->action_group) if (panel->action_group)
{ {
/* FIXME: For some reason the accelerator only works if a menuitem
is created, but not before that. */
GtkWidget* toplevel = gtk_widget_get_toplevel (GTK_WIDGET (panel)); GtkWidget* toplevel = gtk_widget_get_toplevel (GTK_WIDGET (panel));
GSList* groups = gtk_accel_groups_from_object (G_OBJECT (toplevel)); GSList* groups = gtk_accel_groups_from_object (G_OBJECT (toplevel));
gtk_action_set_accel_group (action, g_slist_nth_data (groups, 0)); gtk_action_set_accel_group (action, g_slist_nth_data (groups, 0));
gtk_action_group_add_action_with_accel (panel->action_group, gtk_action_group_add_action_with_accel (panel->action_group,
action, NULL); action, NULL);
gtk_action_connect_accelerator (action);
} }
if (n > 0) if (n > 0)
g_object_set (action, "group", g_object_get_data ( g_object_set (action, "group", g_object_get_data (
@ -1021,11 +988,19 @@ midori_panel_set_current_page (MidoriPanel* panel,
if ((viewable = midori_panel_get_nth_page (panel, n))) if ((viewable = midori_panel_get_nth_page (panel, n)))
{ {
GtkWidget* toolbar;
GList* items;
const gchar* label; const gchar* label;
if (!GTK_WIDGET_VISIBLE (viewable)) if (!GTK_WIDGET_VISIBLE (viewable))
return; return;
gtk_notebook_set_current_page (GTK_NOTEBOOK (panel->toolbook), n); gtk_notebook_set_current_page (GTK_NOTEBOOK (panel->toolbook), n);
toolbar = gtk_notebook_get_nth_page (GTK_NOTEBOOK (panel->toolbook), n);
items = gtk_container_get_children (GTK_CONTAINER (toolbar));
sokoke_widget_set_visible (panel->toolbook,
g_list_nth_data (items, 1) != NULL);
g_list_free (items);
gtk_notebook_set_current_page (GTK_NOTEBOOK (panel->notebook), n); gtk_notebook_set_current_page (GTK_NOTEBOOK (panel->notebook), n);
label = midori_viewable_get_label (MIDORI_VIEWABLE (viewable)); label = midori_viewable_get_label (MIDORI_VIEWABLE (viewable));
g_object_set (panel->toolbar_label, "label", label, NULL); g_object_set (panel->toolbar_label, "label", label, NULL);

View file

@ -37,7 +37,7 @@ typedef struct _MidoriPanel MidoriPanel;
typedef struct _MidoriPanelClass MidoriPanelClass; typedef struct _MidoriPanelClass MidoriPanelClass;
GType GType
midori_panel_get_type (void); midori_panel_get_type (void) G_GNUC_CONST;
GtkWidget* GtkWidget*
midori_panel_new (void); midori_panel_new (void);

View file

@ -16,7 +16,6 @@
#endif #endif
#include "sokoke.h" #include "sokoke.h"
#include "compat.h"
#include <string.h> #include <string.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
@ -390,7 +389,11 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
GTK_WIDGET (parent) : GTK_WIDGET (preferences))) GTK_WIDGET (parent) : GTK_WIDGET (preferences)))
button = katze_property_proxy (settings, "kinetic-scrolling", NULL); button = katze_property_proxy (settings, "kinetic-scrolling", NULL);
else else
button = katze_property_proxy (settings, "open-panels-in-windows", NULL); {
button = katze_property_proxy (settings, "enforce-96-dpi", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Enforce 96 dots per inch"));
gtk_widget_set_tooltip_text (button, _("Enforce a video dot density of 96 DPI"));
}
#else #else
button = katze_property_proxy (settings, "middle-click-opens-selection", NULL); button = katze_property_proxy (settings, "middle-click-opens-selection", NULL);
#endif #endif
@ -398,21 +401,15 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
#if !HAVE_HILDON #if !HAVE_HILDON
button = katze_property_proxy (settings, "enable-scripts", NULL); button = katze_property_proxy (settings, "enable-scripts", NULL);
INDENTED_ADD (button); INDENTED_ADD (button);
button = katze_property_proxy (settings, "open-panels-in-windows", NULL);
SPANNED_ADD (button);
button = katze_property_proxy (settings, "enable-plugins", NULL); button = katze_property_proxy (settings, "enable-plugins", NULL);
SPANNED_ADD (button);
button = katze_property_proxy (settings, "enforce-96-dpi", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Enforce 96 dots per inch"));
gtk_widget_set_tooltip_text (button, _("Enforce a video dot density of 96 DPI"));
INDENTED_ADD (button); INDENTED_ADD (button);
button = katze_property_proxy (settings, "enable-developer-extras", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Enable developer tools"));
gtk_widget_set_tooltip_text (button, _("Enable special extensions for developers"));
SPANNED_ADD (button);
#endif #endif
button = katze_property_proxy (settings, "zoom-text-and-images", NULL);
INDENTED_ADD (button);
button = katze_property_proxy (settings, "find-while-typing", NULL); button = katze_property_proxy (settings, "find-while-typing", NULL);
SPANNED_ADD (button); SPANNED_ADD (button);
button = katze_property_proxy (settings, "zoom-text-and-images", NULL);
INDENTED_ADD (button);
#if WEBKIT_CHECK_VERSION (1, 1, 6) #if WEBKIT_CHECK_VERSION (1, 1, 6)
FRAME_NEW (_("Spell Checking")); FRAME_NEW (_("Spell Checking"));
/* FIXME: Provide a nice dictionary selection */ /* FIXME: Provide a nice dictionary selection */
@ -420,6 +417,8 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
gtk_button_set_label (GTK_BUTTON (button), _("Enable Spell Checking")); gtk_button_set_label (GTK_BUTTON (button), _("Enable Spell Checking"));
gtk_widget_set_tooltip_text (button, _("Enable spell checking while typing")); gtk_widget_set_tooltip_text (button, _("Enable spell checking while typing"));
INDENTED_ADD (button); INDENTED_ADD (button);
button = gtk_label_new (_("Spelling dictionaries:"));
INDENTED_ADD (button);
entry = katze_property_proxy (settings, "spell-checking-languages", NULL); entry = katze_property_proxy (settings, "spell-checking-languages", NULL);
/* i18n: The example should be adjusted to contain a good local default */ /* i18n: The example should be adjusted to contain a good local default */
gtk_widget_set_tooltip_text (entry, _("A comma separated list of " gtk_widget_set_tooltip_text (entry, _("A comma separated list of "
@ -469,7 +468,7 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
SPANNED_ADD (entry); SPANNED_ADD (entry);
label = katze_property_label (settings, "download-manager"); label = katze_property_label (settings, "download-manager");
INDENTED_ADD (label); INDENTED_ADD (label);
entry = katze_property_proxy (settings, "download-manager", "application-Network"); entry = katze_property_proxy (settings, "download-manager", "application-FileTransfer");
SPANNED_ADD (entry); SPANNED_ADD (entry);
label = katze_property_label (settings, "news-aggregator"); label = katze_property_label (settings, "news-aggregator");
INDENTED_ADD (label); INDENTED_ADD (label);
@ -494,8 +493,13 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
#endif #endif
label = katze_property_label (settings, "identify-as"); label = katze_property_label (settings, "identify-as");
INDENTED_ADD (label); INDENTED_ADD (label);
button = katze_property_proxy (settings, "identify-as", "custom-ident-string"); button = katze_property_proxy (settings, "identify-as", "custom-user-agent");
SPANNED_ADD (button); SPANNED_ADD (button);
label = katze_property_label (settings, "preferred-languages");
INDENTED_ADD (label);
entry = katze_property_proxy (settings, "preferred-languages", NULL);
SPANNED_ADD (entry);
/* Page "Privacy" */ /* Page "Privacy" */
PAGE_NEW (GTK_STOCK_INDEX, _("Privacy")); PAGE_NEW (GTK_STOCK_INDEX, _("Privacy"));
@ -504,14 +508,19 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
INDENTED_ADD (label); INDENTED_ADD (label);
button = katze_property_proxy (settings, "accept-cookies", NULL); button = katze_property_proxy (settings, "accept-cookies", NULL);
SPANNED_ADD (button); SPANNED_ADD (button);
button = katze_property_proxy (settings, "original-cookies-only", NULL);
INDENTED_ADD (button);
label = katze_property_label (settings, "maximum-cookie-age"); label = katze_property_label (settings, "maximum-cookie-age");
INDENTED_ADD (label); INDENTED_ADD (label);
entry = katze_property_proxy (settings, "maximum-cookie-age", NULL); entry = katze_property_proxy (settings, "maximum-cookie-age", NULL);
SPANNED_ADD (entry); SPANNED_ADD (entry);
label = gtk_label_new (_("days")); label = gtk_label_new (_("days"));
SPANNED_ADD (label); SPANNED_ADD (label);
#if WEBKIT_CHECK_VERSION (1, 1, 8)
INDENTED_ADD (katze_property_proxy (settings, "enable-html5-database", NULL));
SPANNED_ADD (katze_property_proxy (settings, "enable-html5-local-storage", NULL));
#endif
#if WEBKIT_CHECK_VERSION (1, 1, 13)
INDENTED_ADD (katze_property_proxy (settings, "enable-offline-web-application-cache", NULL));
#endif
FRAME_NEW (_("History")); FRAME_NEW (_("History"));
button = katze_property_label (settings, "maximum-history-age"); button = katze_property_label (settings, "maximum-history-age");
INDENTED_ADD (button); INDENTED_ADD (button);

View file

@ -40,7 +40,7 @@ struct _MidoriPreferencesClass
}; };
GType GType
midori_preferences_get_type (void); midori_preferences_get_type (void) G_GNUC_CONST;
GtkWidget* GtkWidget*
midori_preferences_new (GtkWindow* parent, midori_preferences_new (GtkWindow* parent,

View file

@ -28,8 +28,6 @@ struct _MidoriSearchAction
KatzeItem* default_item; KatzeItem* default_item;
gchar* text; gchar* text;
KatzeNet* net;
GtkWidget* last_proxy; GtkWidget* last_proxy;
GtkWidget* dialog; GtkWidget* dialog;
@ -193,8 +191,6 @@ midori_search_action_init (MidoriSearchAction* search_action)
search_action->default_item = NULL; search_action->default_item = NULL;
search_action->text = NULL; search_action->text = NULL;
search_action->net = katze_net_new ();
search_action->last_proxy = NULL; search_action->last_proxy = NULL;
search_action->dialog = NULL; search_action->dialog = NULL;
@ -211,8 +207,6 @@ midori_search_action_finalize (GObject* object)
katze_assign (search_action->text, NULL); katze_assign (search_action->text, NULL);
katze_object_assign (search_action->net, NULL);
G_OBJECT_CLASS (midori_search_action_parent_class)->finalize (object); G_OBJECT_CLASS (midori_search_action_parent_class)->finalize (object);
} }
@ -357,15 +351,15 @@ midori_search_action_key_press_event_cb (GtkWidget* entry,
case GDK_Return: case GDK_Return:
text = gtk_entry_get_text (GTK_ENTRY (entry)); text = gtk_entry_get_text (GTK_ENTRY (entry));
g_signal_emit (search_action, signals[SUBMIT], 0, text, g_signal_emit (search_action, signals[SUBMIT], 0, text,
(event->state & GDK_MOD1_MASK) ? TRUE : FALSE); MIDORI_MOD_NEW_TAB (event->state));
search_action->last_proxy = entry; search_action->last_proxy = entry;
return TRUE; return TRUE;
case GDK_Up: case GDK_Up:
if (event->state & GDK_CONTROL_MASK) if (MIDORI_MOD_SCROLL (event->state))
_midori_search_action_move_index (search_action, - 1); _midori_search_action_move_index (search_action, - 1);
return TRUE; return TRUE;
case GDK_Down: case GDK_Down:
if (event->state & GDK_CONTROL_MASK) if (MIDORI_MOD_SCROLL (event->state))
_midori_search_action_move_index (search_action, + 1); _midori_search_action_move_index (search_action, + 1);
return TRUE; return TRUE;
} }
@ -413,6 +407,9 @@ midori_search_action_get_icon (KatzeItem* item,
{ {
const gchar* icon; const gchar* icon;
if ((icon = katze_item_get_uri (item)) && (g_strstr_len (icon, 8, "://")))
return katze_load_cached_icon (icon, widget);
if ((icon = katze_item_get_icon (item)) && *icon) if ((icon = katze_item_get_icon (item)) && *icon)
{ {
GdkScreen* screen; GdkScreen* screen;
@ -421,15 +418,12 @@ midori_search_action_get_icon (KatzeItem* item,
screen = gtk_widget_get_screen (widget); screen = gtk_widget_get_screen (widget);
icon_theme = gtk_icon_theme_get_for_screen (screen); icon_theme = gtk_icon_theme_get_for_screen (screen);
if (gtk_icon_theme_has_icon (icon_theme, icon)) if (gtk_icon_theme_has_icon (icon_theme, icon))
{
*icon_name = icon; *icon_name = icon;
else return NULL;
*icon_name = GTK_STOCK_FILE; }
return NULL;
} }
if ((icon = katze_item_get_uri (item)) && (g_strstr_len (icon, 8, "://")))
return katze_load_cached_icon (icon, widget);
*icon_name = GTK_STOCK_FILE; *icon_name = GTK_STOCK_FILE;
return NULL; return NULL;
} }
@ -440,10 +434,6 @@ midori_search_action_icon_released_cb (GtkWidget* entry,
gint button, gint button,
GtkAction* action) GtkAction* action)
{ {
if (icon_pos == GTK_ICON_ENTRY_SECONDARY)
return;
KatzeArray* search_engines; KatzeArray* search_engines;
GtkWidget* menu; GtkWidget* menu;
guint i; guint i;
@ -452,6 +442,9 @@ midori_search_action_icon_released_cb (GtkWidget* entry,
GdkPixbuf* icon; GdkPixbuf* icon;
GtkWidget* image; GtkWidget* image;
if (icon_pos == GTK_ICON_ENTRY_SECONDARY)
return;
search_engines = MIDORI_SEARCH_ACTION (action)->search_engines; search_engines = MIDORI_SEARCH_ACTION (action)->search_engines;
menu = gtk_menu_new (); menu = gtk_menu_new ();
i = 0; i = 0;
@ -812,7 +805,8 @@ midori_search_action_dialog_render_tick_cb (GtkTreeViewColumn* column,
gtk_tree_model_get (model, iter, 0, &item, -1); gtk_tree_model_get (model, iter, 0, &item, -1);
search_action = g_object_get_data (G_OBJECT (treeview), "search-action"); search_action = g_object_get_data (G_OBJECT (treeview), "search-action");
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, NULL); gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (treeview),
GTK_ICON_SIZE_MENU, &width, NULL);
g_object_set (renderer, "stock-id", g_object_set (renderer, "stock-id",
search_action->default_item == item ? GTK_STOCK_YES : NULL, search_action->default_item == item ? GTK_STOCK_YES : NULL,
"width", width + 4, NULL); "width", width + 4, NULL);
@ -1189,6 +1183,14 @@ midori_search_action_treeview_destroy_cb (GtkWidget* treeview,
} }
} }
static void
midori_search_action_dialog_respnse_cb (GtkWidget* dialog,
gint response,
gpointer data)
{
gtk_widget_destroy (dialog);
}
/** /**
* midori_search_action_get_dialog: * midori_search_action_get_dialog:
* @search_action: a #MidoriSearchAction * @search_action: a #MidoriSearchAction
@ -1251,7 +1253,7 @@ midori_search_action_get_dialog (MidoriSearchAction* search_action)
sokoke_widget_get_text_size (dialog, "M", &width, &height); sokoke_widget_get_text_size (dialog, "M", &width, &height);
gtk_window_set_default_size (GTK_WINDOW (dialog), width * 52, -1); gtk_window_set_default_size (GTK_WINDOW (dialog), width * 52, -1);
g_signal_connect (dialog, "response", g_signal_connect (dialog, "response",
G_CALLBACK (gtk_widget_destroy), dialog); G_CALLBACK (midori_search_action_dialog_respnse_cb), NULL);
/* TODO: Do we want tooltips for explainations or can we omit that? /* TODO: Do we want tooltips for explainations or can we omit that?
We need mnemonics */ We need mnemonics */
if ((xfce_heading = sokoke_xfce_header_new ( if ((xfce_heading = sokoke_xfce_header_new (

View file

@ -33,7 +33,7 @@ typedef struct _MidoriSearchAction MidoriSearchAction;
typedef struct _MidoriSearchActionClass MidoriSearchActionClass; typedef struct _MidoriSearchActionClass MidoriSearchActionClass;
GType GType
midori_search_action_get_type (void); midori_search_action_get_type (void) G_GNUC_CONST;
const gchar* const gchar*
midori_search_action_get_text (MidoriSearchAction* action); midori_search_action_get_text (MidoriSearchAction* action);

File diff suppressed because it is too large Load diff

View file

@ -61,7 +61,7 @@ typedef struct _MidoriView MidoriView;
typedef struct _MidoriViewClass MidoriViewClass; typedef struct _MidoriViewClass MidoriViewClass;
GType GType
midori_view_get_type (void); midori_view_get_type (void) G_GNUC_CONST;
GtkWidget* GtkWidget*
midori_view_new (KatzeNet* net); midori_view_new (KatzeNet* net);
@ -160,6 +160,12 @@ midori_view_can_go_forward (MidoriView* view);
void void
midori_view_go_forward (MidoriView* view); midori_view_go_forward (MidoriView* view);
const gchar*
midori_view_get_previous_page (MidoriView* view);
const gchar*
midori_view_get_next_page (MidoriView* view);
gboolean gboolean
midori_view_can_print (MidoriView* view); midori_view_can_print (MidoriView* view);

View file

@ -84,7 +84,7 @@ midori_viewable_base_init (MidoriViewableIface* iface)
* Emitted when an Option menu is displayed, for instance * Emitted when an Option menu is displayed, for instance
* when the user clicks the Options button in the panel. * when the user clicks the Options button in the panel.
* *
* Since: 0.1.9 * Deprecated: 0.2.3
*/ */
signals[POPULATE_OPTION_MENU] = g_signal_new ( signals[POPULATE_OPTION_MENU] = g_signal_new (
"populate-option-menu", "populate-option-menu",

View file

@ -50,7 +50,7 @@ struct _MidoriViewableIface
}; };
GType GType
midori_viewable_get_type (void); midori_viewable_get_type (void) G_GNUC_CONST;
GtkWidget* GtkWidget*
midori_viewable_new_from_uri (const gchar* uri); midori_viewable_new_from_uri (const gchar* uri);

View file

@ -86,6 +86,7 @@ struct _MidoriWebSettings
gboolean remember_last_downloaded_files; gboolean remember_last_downloaded_files;
gchar* http_proxy; gchar* http_proxy;
gchar* http_accept_language;
gboolean auto_detect_proxy; gboolean auto_detect_proxy;
MidoriIdentity identify_as; MidoriIdentity identify_as;
gchar* ident_string; gchar* ident_string;
@ -153,6 +154,11 @@ enum
PROP_AUTO_LOAD_IMAGES, PROP_AUTO_LOAD_IMAGES,
PROP_ENABLE_SCRIPTS, PROP_ENABLE_SCRIPTS,
PROP_ENABLE_PLUGINS, PROP_ENABLE_PLUGINS,
PROP_ENABLE_DEVELOPER_EXTRAS,
PROP_ENABLE_HTML5_DATABASE,
PROP_ENABLE_HTML5_LOCAL_STORAGE,
PROP_ENABLE_OFFLINE_WEB_APPLICATION_CACHE,
PROP_ENABLE_PAGE_CACHE,
PROP_ZOOM_TEXT_AND_IMAGES, PROP_ZOOM_TEXT_AND_IMAGES,
PROP_FIND_WHILE_TYPING, PROP_FIND_WHILE_TYPING,
PROP_KINETIC_SCROLLING, PROP_KINETIC_SCROLLING,
@ -167,7 +173,8 @@ enum
PROP_HTTP_PROXY, PROP_HTTP_PROXY,
PROP_AUTO_DETECT_PROXY, PROP_AUTO_DETECT_PROXY,
PROP_IDENTIFY_AS, PROP_IDENTIFY_AS,
PROP_IDENT_STRING, PROP_USER_AGENT,
PROP_PREFERRED_LANGUAGES,
PROP_CLEAR_PRIVATE_DATA PROP_CLEAR_PRIVATE_DATA
}; };
@ -525,7 +532,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
"toolbar-items", "toolbar-items",
_("Toolbar Items"), _("Toolbar Items"),
_("The items to show on the toolbar"), _("The items to show on the toolbar"),
"TabNew,Back,Forward,ReloadStop,Location,Panel,Search,Trash", "TabNew,Back,Forward,Next,ReloadStop,Location,Panel,Search,Trash",
flags)); flags));
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
@ -646,7 +653,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("The folder downloaded files are saved to"), _("The folder downloaded files are saved to"),
midori_get_download_dir (), midori_get_download_dir (),
#if WEBKIT_CHECK_VERSION (1, 1, 3) #if WEBKIT_CHECK_VERSION (1, 1, 3)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); flags));
#else #else
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
#endif #endif
@ -668,7 +675,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("Whether to ask for the destination folder when downloading a file"), _("Whether to ask for the destination folder when downloading a file"),
FALSE, FALSE,
#if WEBKIT_CHECK_VERSION (1, 1, 15) #if WEBKIT_CHECK_VERSION (1, 1, 15)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); flags));
#else #else
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
#endif #endif
@ -688,7 +695,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("Whether to show a notification when a transfer has been completed"), _("Whether to show a notification when a transfer has been completed"),
TRUE, TRUE,
#if WEBKIT_CHECK_VERSION (1, 1, 3) #if WEBKIT_CHECK_VERSION (1, 1, 3)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); flags));
#else #else
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
#endif #endif
@ -733,7 +740,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
"location-entry-search", "location-entry-search",
_("Location entry Search"), _("Location entry Search"),
_("The search to perform inside the location entry"), _("The search to perform inside the location entry"),
"http://www.google.com/search?q=%s", NULL,
flags)); flags));
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
@ -773,7 +780,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("Where to open new pages"), _("Where to open new pages"),
MIDORI_TYPE_NEW_PAGE, MIDORI_TYPE_NEW_PAGE,
MIDORI_NEW_PAGE_TAB, MIDORI_NEW_PAGE_TAB,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); flags));
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_OPEN_EXTERNAL_PAGES_IN, PROP_OPEN_EXTERNAL_PAGES_IN,
@ -783,7 +790,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("Where to open externally opened pages"), _("Where to open externally opened pages"),
MIDORI_TYPE_NEW_PAGE, MIDORI_TYPE_NEW_PAGE,
MIDORI_NEW_PAGE_TAB, MIDORI_NEW_PAGE_TAB,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); flags));
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_MIDDLE_CLICK_OPENS_SELECTION, PROP_MIDDLE_CLICK_OPENS_SELECTION,
@ -819,7 +826,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("Open popups in tabs"), _("Open popups in tabs"),
_("Whether to open popup windows in tabs"), _("Whether to open popup windows in tabs"),
TRUE, TRUE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); flags));
/* Override properties to localize them for preference proxies */ /* Override properties to localize them for preference proxies */
@ -847,6 +854,49 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("Enable embedded Netscape plugin objects"), _("Enable embedded Netscape plugin objects"),
TRUE, TRUE,
flags)); flags));
/* Override properties to override defaults */
g_object_class_install_property (gobject_class,
PROP_ENABLE_DEVELOPER_EXTRAS,
g_param_spec_boolean (
"enable-developer-extras",
"Enable developer tools",
"Enable special extensions for developers",
TRUE,
flags));
#if WEBKIT_CHECK_VERSION (1, 1, 8)
g_object_class_install_property (gobject_class,
PROP_ENABLE_HTML5_DATABASE,
g_param_spec_boolean ("enable-html5-database",
_("Enable HTML5 database support"),
_("Whether to enable HTML5 database support"),
FALSE,
flags));
g_object_class_install_property (gobject_class,
PROP_ENABLE_HTML5_LOCAL_STORAGE,
g_param_spec_boolean ("enable-html5-local-storage",
_("Enable HTML5 local storage support"),
_("Whether to enable HTML5 local storage support"),
FALSE,
flags));
#endif
#if WEBKIT_CHECK_VERSION (1, 1, 13)
g_object_class_install_property (gobject_class,
PROP_ENABLE_OFFLINE_WEB_APPLICATION_CACHE,
g_param_spec_boolean ("enable-offline-web-application-cache",
_("Enable offline web application cache"),
_("Whether to enable offline web application cache"),
FALSE,
flags));
#endif
#if WEBKIT_CHECK_VERSION (1, 1, 18)
g_object_class_install_property (gobject_class,
PROP_ENABLE_PAGE_CACHE,
g_param_spec_boolean ("enable-page-cache",
"Enable page cache",
"Whether the page cache should be used",
TRUE,
flags));
#endif
/** /**
* MidoriWebSettings:zoom-text-and-images: * MidoriWebSettings:zoom-text-and-images:
@ -862,7 +912,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("Zoom Text and Images"), _("Zoom Text and Images"),
_("Whether to zoom text and images"), _("Whether to zoom text and images"),
FALSE, FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); flags));
/** /**
* MidoriWebSettings:find-while-typing: * MidoriWebSettings:find-while-typing:
@ -904,8 +954,15 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("What type of cookies to accept"), _("What type of cookies to accept"),
MIDORI_TYPE_ACCEPT_COOKIES, MIDORI_TYPE_ACCEPT_COOKIES,
MIDORI_ACCEPT_COOKIES_ALL, MIDORI_ACCEPT_COOKIES_ALL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); flags));
/**
* MidoriWebSettings:original-cookies-only:
*
* Accept cookies from the original website only.
*
* Deprecated: 0.2.3: This value is not used.
*/
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_ORIGINAL_COOKIES_ONLY, PROP_ORIGINAL_COOKIES_ONLY,
g_param_spec_boolean ( g_param_spec_boolean (
@ -913,7 +970,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("Original cookies only"), _("Original cookies only"),
_("Accept cookies from the original website only"), _("Accept cookies from the original website only"),
FALSE, FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); flags));
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_MAXIMUM_COOKIE_AGE, PROP_MAXIMUM_COOKIE_AGE,
@ -922,7 +979,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("Maximum cookie age"), _("Maximum cookie age"),
_("The maximum number of days to save cookies for"), _("The maximum number of days to save cookies for"),
0, G_MAXINT, 30, 0, G_MAXINT, 30,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); flags));
@ -958,7 +1015,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("Remember last downloaded files"), _("Remember last downloaded files"),
_("Whether the last downloaded files are saved"), _("Whether the last downloaded files are saved"),
TRUE, TRUE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); flags));
@ -969,7 +1026,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("Proxy Server"), _("Proxy Server"),
_("The proxy server used for HTTP connections"), _("The proxy server used for HTTP connections"),
NULL, NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); flags));
/** /**
* MidoriWebSettings:auto-detect-proxy: * MidoriWebSettings:auto-detect-proxy:
@ -985,7 +1042,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("Detect proxy server automatically"), _("Detect proxy server automatically"),
_("Whether to detect the proxy server automatically from the environment"), _("Whether to detect the proxy server automatically from the environment"),
TRUE, TRUE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); flags));
/** /**
* MidoriWebSettings:identify-as: * MidoriWebSettings:identify-as:
@ -1003,23 +1060,39 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("What to identify as to web pages"), _("What to identify as to web pages"),
MIDORI_TYPE_IDENTITY, MIDORI_TYPE_IDENTITY,
MIDORI_IDENT_MIDORI, MIDORI_IDENT_MIDORI,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); flags));
/** /**
* MidoriWebSettings:ident-string: * MidoriWebSettings:user-agent:
* *
* The browser identification string. * The browser identification string.
* *
* Since: 0.1.2 * Since: 0.2.3
*/ */
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_IDENT_STRING, PROP_USER_AGENT,
g_param_spec_string ( g_param_spec_string (
"ident-string", "user-agent",
_("Identification string"), _("Identification string"),
_("The application identification string"), _("The application identification string"),
NULL, NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); flags));
/**
* MidoriWebSettings:preferred-languages:
*
* A comma separated list of languages preferred for rendering multilingual webpages.
*
* Since: 0.2.3
*/
g_object_class_install_property (gobject_class,
PROP_PREFERRED_LANGUAGES,
g_param_spec_string (
"preferred-languages",
_("Preferred languages"),
_("A comma separated list of languages preferred for rendering multilingual webpages, for example \"de\", \"ru,nl\" or \"en-us;q=1.0, fr-fr;q=0.667\""),
NULL,
flags));
/** /**
* MidoriWebSettings:clear-private-data: * MidoriWebSettings:clear-private-data:
@ -1115,7 +1188,7 @@ get_sys_name (void)
{ {
struct utsname name; struct utsname name;
if (uname (&name) != -1) if (uname (&name) != -1)
sys_name = g_strdup_printf ("%s %s", name.sysname, name.machine); sys_name = g_strdup(name.sysname);
else else
sys_name = "Unix"; sys_name = "Unix";
} }
@ -1141,15 +1214,10 @@ generate_ident_string (MidoriIdentity identify_as)
const gchar* os = const gchar* os =
#if HAVE_OSX #if HAVE_OSX
/* #if defined (HAVE_X86) */ "Mac OS X";
"Intel Mac OS X";
/* #else
"PPC Mac OS X";
#endif */
#elif defined (G_OS_UNIX) #elif defined (G_OS_UNIX)
get_sys_name (); get_sys_name ();
#elif defined (G_OS_WIN32) #elif defined (G_OS_WIN32)
// FIXME: Windows NT version
"Windows"; "Windows";
#else #else
"Unknown"; "Unknown";
@ -1157,8 +1225,7 @@ generate_ident_string (MidoriIdentity identify_as)
const gchar* appname = "Midori/" const gchar* appname = "Midori/"
G_STRINGIFY (MIDORI_MAJOR_VERSION) "." G_STRINGIFY (MIDORI_MAJOR_VERSION) "."
G_STRINGIFY (MIDORI_MINOR_VERSION) "." G_STRINGIFY (MIDORI_MINOR_VERSION);
G_STRINGIFY (MIDORI_MICRO_VERSION);
const gchar* lang = pango_language_to_string (gtk_get_default_language ()); const gchar* lang = pango_language_to_string (gtk_get_default_language ());
@ -1184,8 +1251,8 @@ generate_ident_string (MidoriIdentity identify_as)
"Safari/419.3 %s", "Safari/419.3 %s",
os, lang, appname); os, lang, appname);
case MIDORI_IDENT_FIREFOX: case MIDORI_IDENT_FIREFOX:
return g_strdup_printf ("Mozilla/5.0 (%s; U; %s; %s; rv:1.8.1) " return g_strdup_printf ("Mozilla/5.0 (%s; U; %s; %s; rv:1.9.0.2) "
"Gecko/20061010 Firefox/2.0 %s", "Gecko/2008092313 Firefox/3.8 %s",
platform, os, lang, appname); platform, os, lang, appname);
case MIDORI_IDENT_EXPLORER: case MIDORI_IDENT_EXPLORER:
return g_strdup_printf ("Mozilla/4.0 (compatible; " return g_strdup_printf ("Mozilla/4.0 (compatible; "
@ -1369,6 +1436,32 @@ midori_web_settings_set_property (GObject* object,
g_object_set (web_settings, "WebKitWebSettings::enable-plugins", g_object_set (web_settings, "WebKitWebSettings::enable-plugins",
g_value_get_boolean (value), NULL); g_value_get_boolean (value), NULL);
break; break;
case PROP_ENABLE_DEVELOPER_EXTRAS:
g_object_set (web_settings, "WebKitWebSettings::enable-developer-extras",
g_value_get_boolean (value), NULL);
break;
#if WEBKIT_CHECK_VERSION (1, 1, 8)
case PROP_ENABLE_HTML5_DATABASE:
g_object_set (web_settings, "WebKitWebSettings::enable-html5-database",
g_value_get_boolean (value), NULL);
break;
case PROP_ENABLE_HTML5_LOCAL_STORAGE:
g_object_set (web_settings, "WebKitWebSettings::enable-html5-local-storage",
g_value_get_boolean (value), NULL);
break;
#endif
#if WEBKIT_CHECK_VERSION (1, 1, 13)
case PROP_ENABLE_OFFLINE_WEB_APPLICATION_CACHE:
g_object_set (web_settings, "WebKitWebSettings::enable-offline-web-application-cache",
g_value_get_boolean (value), NULL);
break;
#endif
#if WEBKIT_CHECK_VERSION (1, 1, 18)
case PROP_ENABLE_PAGE_CACHE:
g_object_set (web_settings, "WebKitWebSettings::enable-page-cache",
g_value_get_boolean (value), NULL);
break;
#endif
case PROP_ZOOM_TEXT_AND_IMAGES: case PROP_ZOOM_TEXT_AND_IMAGES:
web_settings->zoom_text_and_images = g_value_get_boolean (value); web_settings->zoom_text_and_images = g_value_get_boolean (value);
break; break;
@ -1412,18 +1505,21 @@ midori_web_settings_set_property (GObject* object,
katze_assign (web_settings->ident_string, string); katze_assign (web_settings->ident_string, string);
#if WEBKIT_CHECK_VERSION (1, 1, 11) #if WEBKIT_CHECK_VERSION (1, 1, 11)
g_object_set (web_settings, "user-agent", string, NULL); g_object_set (web_settings, "user-agent", string, NULL);
#else
g_object_notify (object, "user-agent");
#endif #endif
g_object_notify (object, "ident-string");
} }
break; break;
case PROP_IDENT_STRING: case PROP_USER_AGENT:
if (web_settings->identify_as == MIDORI_IDENT_CUSTOM) if (web_settings->identify_as == MIDORI_IDENT_CUSTOM)
{
katze_assign (web_settings->ident_string, g_value_dup_string (value)); katze_assign (web_settings->ident_string, g_value_dup_string (value));
#if WEBKIT_CHECK_VERSION (1, 1, 11) #if WEBKIT_CHECK_VERSION (1, 1, 11)
g_object_set (web_settings, "user-agent", web_settings->ident_string, NULL); g_object_set (web_settings, "WebKitWebSettings::user-agent",
#endif web_settings->ident_string, NULL);
} #endif
break;
case PROP_PREFERRED_LANGUAGES:
katze_assign (web_settings->http_accept_language, g_value_dup_string (value));
break; break;
case PROP_CLEAR_PRIVATE_DATA: case PROP_CLEAR_PRIVATE_DATA:
web_settings->clear_private_data = g_value_get_int (value); web_settings->clear_private_data = g_value_get_int (value);
@ -1584,6 +1680,32 @@ midori_web_settings_get_property (GObject* object,
g_value_set_boolean (value, katze_object_get_boolean (web_settings, g_value_set_boolean (value, katze_object_get_boolean (web_settings,
"WebKitWebSettings::enable-plugins")); "WebKitWebSettings::enable-plugins"));
break; break;
case PROP_ENABLE_DEVELOPER_EXTRAS:
g_value_set_boolean (value, katze_object_get_boolean (web_settings,
"WebKitWebSettings::enable-developer-extras"));
break;
#if WEBKIT_CHECK_VERSION (1, 1, 8)
case PROP_ENABLE_HTML5_DATABASE:
g_value_set_boolean (value, katze_object_get_boolean (web_settings,
"WebKitWebSettings::enable-html5-database"));
break;
case PROP_ENABLE_HTML5_LOCAL_STORAGE:
g_value_set_boolean (value, katze_object_get_boolean (web_settings,
"WebKitWebSettings::enable-html5-local-storage"));
break;
#endif
#if WEBKIT_CHECK_VERSION (1, 1, 13)
case PROP_ENABLE_OFFLINE_WEB_APPLICATION_CACHE:
g_value_set_boolean (value, katze_object_get_boolean (web_settings,
"WebKitWebSettings::enable-offline-web-application-cache"));
break;
#endif
#if WEBKIT_CHECK_VERSION (1, 1, 18)
case PROP_ENABLE_PAGE_CACHE:
g_value_set_boolean (value, katze_object_get_boolean (web_settings,
"WebKitWebSettings::enable-page-cache"));
break;
#endif
case PROP_ZOOM_TEXT_AND_IMAGES: case PROP_ZOOM_TEXT_AND_IMAGES:
g_value_set_boolean (value, web_settings->zoom_text_and_images); g_value_set_boolean (value, web_settings->zoom_text_and_images);
break; break;
@ -1622,7 +1744,7 @@ midori_web_settings_get_property (GObject* object,
case PROP_IDENTIFY_AS: case PROP_IDENTIFY_AS:
g_value_set_enum (value, web_settings->identify_as); g_value_set_enum (value, web_settings->identify_as);
break; break;
case PROP_IDENT_STRING: case PROP_USER_AGENT:
if (!g_strcmp0 (web_settings->ident_string, "")) if (!g_strcmp0 (web_settings->ident_string, ""))
{ {
gchar* string = generate_ident_string (web_settings->identify_as); gchar* string = generate_ident_string (web_settings->identify_as);
@ -1630,6 +1752,9 @@ midori_web_settings_get_property (GObject* object,
} }
g_value_set_string (value, web_settings->ident_string); g_value_set_string (value, web_settings->ident_string);
break; break;
case PROP_PREFERRED_LANGUAGES:
g_value_set_string (value, web_settings->http_accept_language);
break;
case PROP_CLEAR_PRIVATE_DATA: case PROP_CLEAR_PRIVATE_DATA:
g_value_set_int (value, web_settings->clear_private_data); g_value_set_int (value, web_settings->clear_private_data);
break; break;

View file

@ -149,7 +149,7 @@ midori_identity_get_type (void) G_GNUC_CONST;
(midori_identity_get_type ()) (midori_identity_get_type ())
GType GType
midori_web_settings_get_type (void); midori_web_settings_get_type (void) G_GNUC_CONST;
MidoriWebSettings* MidoriWebSettings*
midori_web_settings_new (void); midori_web_settings_new (void);

View file

@ -17,7 +17,6 @@
#include "midori-browser.h" #include "midori-browser.h"
#include "midori-extension.h" #include "midori-extension.h"
#include "midori-locationaction.h" #include "midori-locationaction.h"
#include "midori-locationentry.h"
#include "midori-panel.h" #include "midori-panel.h"
#include "midori-preferences.h" #include "midori-preferences.h"
#include "midori-searchaction.h" #include "midori-searchaction.h"

View file

@ -142,6 +142,11 @@ GSourceFuncs sock_watch_funcs = {
NULL NULL
}; };
gint fd_recv (gint fd,
gchar *buf,
gint len,
gint flags);
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
static SockInfo *sock_find_from_fd (gint fd); static SockInfo *sock_find_from_fd (gint fd);
#endif #endif

View file

@ -1,6 +1,7 @@
/* /*
Copyright (C) 2007-2009 Christian Dywan <christian@twotoasts.de> Copyright (C) 2007-2009 Christian Dywan <christian@twotoasts.de>
Copyright (C) 2009 Dale Whittaker <dayul@users.sf.net> Copyright (C) 2009 Dale Whittaker <dayul@users.sf.net>
Copyright (C) 2009 Alexander Butenko <a.butenka@gmail.com>
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -16,7 +17,6 @@
#include <config.h> #include <config.h>
#endif #endif
#include "compat.h"
#include "midori-stock.h" #include "midori-stock.h"
#if HAVE_UNISTD_H #if HAVE_UNISTD_H
@ -51,6 +51,44 @@
#include <hildon-uri.h> #include <hildon-uri.h>
#endif #endif
#if !GTK_CHECK_VERSION(2, 12, 0)
void
gtk_widget_set_has_tooltip (GtkWidget* widget,
gboolean has_tooltip)
{
/* Do nothing */
}
void
gtk_widget_set_tooltip_text (GtkWidget* widget,
const gchar* text)
{
if (text && *text)
{
static GtkTooltips* tooltips = NULL;
if (G_UNLIKELY (!tooltips))
tooltips = gtk_tooltips_new ();
gtk_tooltips_set_tip (tooltips, widget, text, NULL);
}
}
void
gtk_tool_item_set_tooltip_text (GtkToolItem* toolitem,
const gchar* text)
{
if (text && *text)
{
static GtkTooltips* tooltips = NULL;
if (G_UNLIKELY (!tooltips))
tooltips = gtk_tooltips_new ();
gtk_tool_item_set_tooltip (toolitem, tooltips, text, NULL);
}
}
#endif
static gchar* static gchar*
sokoke_js_string_utf8 (JSStringRef js_string) sokoke_js_string_utf8 (JSStringRef js_string)
{ {
@ -80,16 +118,23 @@ sokoke_js_script_eval (JSContextRef js_context,
JSValueRef js_exception = NULL; JSValueRef js_exception = NULL;
JSValueRef js_value = JSEvaluateScript (js_context, js_script, JSValueRef js_value = JSEvaluateScript (js_context, js_script,
JSContextGetGlobalObject (js_context), NULL, 0, &js_exception); JSContextGetGlobalObject (js_context), NULL, 0, &js_exception);
if (!js_value && exception) JSStringRelease (js_script);
if (!js_value)
{ {
JSStringRef js_message = JSValueToStringCopy (js_context, JSStringRef js_message = JSValueToStringCopy (js_context,
js_exception, NULL); js_exception, NULL);
value = sokoke_js_string_utf8 (js_message);
if (exception) if (exception)
*exception = sokoke_js_string_utf8 (js_message); *exception = value;
else
{
g_warning ("%s", value);
g_free (value);
}
JSStringRelease (js_message); JSStringRelease (js_message);
js_value = JSValueMakeNull (js_context); return NULL;
} }
JSStringRelease (js_script);
js_value_string = JSValueToStringCopy (js_context, js_value, NULL); js_value_string = JSValueToStringCopy (js_context, js_value, NULL);
value = sokoke_js_string_utf8 (js_value_string); value = sokoke_js_string_utf8 (js_value_string);
@ -97,6 +142,14 @@ sokoke_js_script_eval (JSContextRef js_context,
return value; return value;
} }
static void
sokoke_message_dialog_response_cb (GtkWidget* dialog,
gint response,
gpointer data)
{
gtk_widget_destroy (dialog);
}
void void
sokoke_message_dialog (GtkMessageType message_type, sokoke_message_dialog (GtkMessageType message_type,
const gchar* short_message, const gchar* short_message,
@ -112,8 +165,8 @@ sokoke_message_dialog (GtkMessageType message_type,
"%s", short_message); "%s", short_message);
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", detailed_message); "%s", detailed_message);
g_signal_connect_swapped (dialog, "response", g_signal_connect (dialog, "response",
G_CALLBACK (gtk_widget_destroy), dialog); G_CALLBACK (sokoke_message_dialog_response_cb), NULL);
gtk_widget_show (dialog); gtk_widget_show (dialog);
} }
@ -223,6 +276,73 @@ sokoke_show_uri (GdkScreen* screen,
#if HAVE_HILDON #if HAVE_HILDON
HildonURIAction* action = hildon_uri_get_default_action_by_uri (uri, NULL); HildonURIAction* action = hildon_uri_get_default_action_by_uri (uri, NULL);
return hildon_uri_open (uri, action, error); return hildon_uri_open (uri, action, error);
#elif defined (G_OS_WIN32)
const gchar* fallbacks [] = { "explorer" };
gsize i;
GAppInfo *app_info;
GFile *file;
gchar *free_uri;
g_return_val_if_fail (uri != NULL, FALSE);
g_return_val_if_fail (!error || !*error, FALSE);
g_return_val_if_fail (GDK_IS_SCREEN (screen) || !screen, FALSE);
file = g_file_new_for_uri (uri);
app_info = g_file_query_default_handler (file, NULL, error);
if (app_info != NULL)
{
GdkAppLaunchContext *context;
gboolean result;
GList l;
context = gdk_app_launch_context_new ();
gdk_app_launch_context_set_screen (context, screen);
gdk_app_launch_context_set_timestamp (context, timestamp);
l.data = (char *)file;
l.next = l.prev = NULL;
result = g_app_info_launch (app_info, &l, (GAppLaunchContext*)context, error);
g_object_unref (context);
g_object_unref (app_info);
g_object_unref (file);
if (result)
return TRUE;
}
else
g_object_unref (file);
free_uri = g_filename_from_uri (uri, NULL, NULL);
if (free_uri)
{
gchar *quoted = g_shell_quote (free_uri);
uri = quoted;
g_free (free_uri);
free_uri = quoted;
}
for (i = 0; i < G_N_ELEMENTS (fallbacks); i++)
{
gchar* command = g_strconcat (fallbacks[i], " ", uri, NULL);
gboolean result = g_spawn_command_line_async (command, error);
g_free (command);
if (result)
{
g_free (free_uri);
return TRUE;
}
if (error)
*error = NULL;
}
g_free (free_uri);
return FALSE;
#else #else
const gchar* fallbacks [] = { "xdg-open", "exo-open", "gnome-open" }; const gchar* fallbacks [] = { "xdg-open", "exo-open", "gnome-open" };
@ -232,8 +352,13 @@ sokoke_show_uri (GdkScreen* screen,
g_return_val_if_fail (uri != NULL, FALSE); g_return_val_if_fail (uri != NULL, FALSE);
g_return_val_if_fail (!error || !*error, FALSE); g_return_val_if_fail (!error || !*error, FALSE);
#if GTK_CHECK_VERSION (2, 14, 0)
if (gtk_show_uri (screen, uri, timestamp, error)) if (gtk_show_uri (screen, uri, timestamp, error))
return TRUE; return TRUE;
#else
if (g_app_info_launch_default_for_uri (uri, NULL, NULL))
return TRUE;
#endif
for (i = 0; i < G_N_ELEMENTS (fallbacks); i++) for (i = 0; i < G_N_ELEMENTS (fallbacks); i++)
{ {
@ -320,9 +445,13 @@ sokoke_spawn_program (const gchar* command,
else else
{ {
/* FIXME: Implement Hildon specific version */ /* FIXME: Implement Hildon specific version */
gchar* uri_format;
gchar* command_ready; gchar* command_ready;
gchar** argv; gchar** argv;
if ((uri_format = strstr (command, "%u")))
uri_format[1] = 's';
if (strstr (command, "%s")) if (strstr (command, "%s"))
command_ready = g_strdup_printf (command, argument); command_ready = g_strdup_printf (command, argument);
else else
@ -362,9 +491,9 @@ sokoke_spawn_program (const gchar* command,
* @uri: an URI string * @uri: an URI string
* @path: location of a string pointer * @path: location of a string pointer
* *
* Returns the hostname of the specified URI, * Returns the hostname of the specified URI.
* and stores the path in @path. *
* @path is at least set to "" * If there is a path, it is stored in @path.
* *
* Return value: a newly allocated hostname * Return value: a newly allocated hostname
**/ **/
@ -374,24 +503,17 @@ sokoke_hostname_from_uri (const gchar* uri,
{ {
gchar* hostname; gchar* hostname;
*path = ""; if ((hostname = strchr (uri, '/')))
if ((hostname = g_utf8_strchr (uri, -1, '/')))
{ {
if (hostname[1] == '/') if (hostname[1] == '/')
hostname += 2; hostname += 2;
if ((*path = g_utf8_strchr (hostname, -1, '/'))) if ((*path = strchr (hostname, '/')))
{ return g_strndup (hostname, *path - hostname);
gulong offset = g_utf8_pointer_to_offset (hostname, *path);
gchar* buffer = g_malloc0 (offset + 1);
g_utf8_strncpy (buffer, hostname, offset);
hostname = buffer;
}
else else
hostname = g_strdup (hostname); return g_strdup (hostname);
} }
else
hostname = g_strdup (uri); return g_strdup (uri);
return hostname;
} }
/** /**
@ -441,9 +563,12 @@ sokoke_hostname_to_ascii (const gchar* hostname)
gchar* gchar*
sokoke_uri_to_ascii (const gchar* uri) sokoke_uri_to_ascii (const gchar* uri)
{ {
gchar* proto; gchar* proto = NULL;
gchar* path = NULL;
gchar* hostname;
gchar* encoded;
if ((proto = g_utf8_strchr (uri, -1, ':'))) if (strchr (uri, '/') && (proto = strchr (uri, ':')))
{ {
gulong offset; gulong offset;
gchar* buffer; gchar* buffer;
@ -454,9 +579,8 @@ sokoke_uri_to_ascii (const gchar* uri)
proto = buffer; proto = buffer;
} }
gchar* path; hostname = sokoke_hostname_from_uri (uri, &path);
gchar* hostname = sokoke_hostname_from_uri (uri, &path); encoded = sokoke_hostname_to_ascii (hostname);
gchar* encoded = sokoke_hostname_to_ascii (hostname);
if (encoded) if (encoded)
{ {
@ -499,9 +623,11 @@ gchar* sokoke_search_uri (const gchar* uri,
gchar* escaped; gchar* escaped;
gchar* search; gchar* search;
g_return_val_if_fail (uri != NULL, NULL);
g_return_val_if_fail (keywords != NULL, NULL); g_return_val_if_fail (keywords != NULL, NULL);
if (!uri)
return g_strdup (keywords);
escaped = g_uri_escape_string (keywords, " :/", TRUE); escaped = g_uri_escape_string (keywords, " :/", TRUE);
if (strstr (uri, "%s")) if (strstr (uri, "%s"))
search = g_strdup_printf (uri, escaped); search = g_strdup_printf (uri, escaped);
@ -514,32 +640,29 @@ gchar* sokoke_search_uri (const gchar* uri,
/** /**
* sokoke_magic_uri: * sokoke_magic_uri:
* @uri: a string typed by a user * @uri: a string typed by a user
* @search_engines: search engines
* *
* Takes a string that was typed by a user, * Takes a string that was typed by a user,
* guesses what it is, and returns an URI. * guesses what it is, and returns an URI.
* *
* Return value: a newly allocated URI * If it was a search, %NULL will be returned.
*
* Return value: a newly allocated URI, or %NULL
**/ **/
gchar* gchar*
sokoke_magic_uri (const gchar* uri, sokoke_magic_uri (const gchar* uri)
KatzeArray* search_engines)
{ {
gchar** parts; gchar** parts;
gchar* search; gchar* search;
const gchar* search_uri;
KatzeItem* item;
g_return_val_if_fail (uri, NULL); g_return_val_if_fail (uri, NULL);
g_return_val_if_fail (!search_engines ||
katze_array_is_a (search_engines, KATZE_TYPE_ITEM), NULL);
/* Just return if it's a javascript: or mailto: uri */ /* Just return if it's a javascript: or mailto: uri */
if (g_str_has_prefix (uri, "javascript:") if (!strncmp (uri, "javascript:", 11)
|| g_str_has_prefix (uri, "mailto:") || !strncmp (uri, "mailto:", 7)
|| g_str_has_prefix (uri, "tel:") || !strncmp (uri, "tel:", 4)
|| g_str_has_prefix (uri, "callto:") || !strncmp (uri, "callto:", 7)
|| g_str_has_prefix (uri, "data:")) || !strncmp (uri, "data:", 5)
|| !strncmp (uri, "about:", 6))
return g_strdup (uri); return g_strdup (uri);
/* Add file:// if we have a local path */ /* Add file:// if we have a local path */
if (g_path_is_absolute (uri)) if (g_path_is_absolute (uri))
@ -556,38 +679,26 @@ sokoke_magic_uri (const gchar* uri,
((search = strchr (uri, ':')) || (search = strchr (uri, '@'))) && ((search = strchr (uri, ':')) || (search = strchr (uri, '@'))) &&
search[0] && !g_ascii_isalpha (search[1])) search[0] && !g_ascii_isalpha (search[1]))
return sokoke_idn_to_punycode (g_strconcat ("http://", uri, NULL)); return sokoke_idn_to_punycode (g_strconcat ("http://", uri, NULL));
if (!strcmp (uri, "localhost") || g_str_has_prefix (uri, "localhost/")) if (!strncmp (uri, "localhost", 9) && (uri[9] == '\0' || uri[9] == '/'))
return g_strconcat ("http://", uri, NULL); return g_strconcat ("http://", uri, NULL);
parts = g_strsplit (uri, ".", 0); if (!search)
if (!search && parts[0] && parts[1])
{ {
if (!(parts[1][1] == '\0' && !g_ascii_isalpha (parts[1][0]))) parts = g_strsplit (uri, ".", 0);
if (!strchr (parts[0], ' ') && !strchr (parts[1], ' ')) if (parts[0] && parts[1])
{
search = g_strconcat ("http://", uri, NULL);
g_strfreev (parts);
return sokoke_idn_to_punycode (search);
}
}
g_strfreev (parts);
/* We don't want to search? So return early. */
if (!search_engines)
return g_strdup (uri);
search = NULL;
search_uri = NULL;
/* Do we have a keyword and a string? */
parts = g_strsplit (uri, " ", 2);
if (parts[0])
if ((item = katze_array_find_token (search_engines, parts[0])))
{ {
search_uri = katze_item_get_uri (item); if (!(parts[1][1] == '\0' && !g_ascii_isalpha (parts[1][0])))
search = sokoke_search_uri (search_uri, parts[1] ? parts[1] : ""); if (!strchr (parts[0], ' ') && !strchr (parts[1], ' '))
{
search = g_strconcat ("http://", uri, NULL);
g_strfreev (parts);
return sokoke_idn_to_punycode (search);
}
} }
g_strfreev (parts); g_strfreev (parts);
return search; }
return NULL;
} }
/** /**
* sokoke_format_uri_for_display: * sokoke_format_uri_for_display:
* @uri: an URI string * @uri: an URI string
@ -604,7 +715,7 @@ sokoke_format_uri_for_display (const gchar* uri)
{ {
gchar* unescaped = g_uri_unescape_string (uri, " +"); gchar* unescaped = g_uri_unescape_string (uri, " +");
#ifdef HAVE_LIBSOUP_2_27_90 #ifdef HAVE_LIBSOUP_2_27_90
gchar* path; gchar* path = NULL;
gchar* hostname; gchar* hostname;
gchar* decoded; gchar* decoded;
@ -1079,6 +1190,37 @@ sokoke_time_t_to_julian (const time_t* timestamp)
return julian; return julian;
} }
/**
* sokoke_days_between:
* @day1: a time_t timestamp value
* @day2: a time_t timestamp value
*
* Calculates the number of days between two timestamps.
*
* Return value: an integer.
**/
gint
sokoke_days_between (const time_t* day1,
const time_t* day2)
{
GDate* date1;
GDate* date2;
gint age;
date1 = g_date_new ();
date2 = g_date_new ();
g_date_set_time_t (date1, *day1);
g_date_set_time_t (date2, *day2);
age = g_date_days_between (date1, date2);
g_date_free (date1);
g_date_free (date2);
return age;
}
/** /**
* sokoke_register_stock_items: * sokoke_register_stock_items:
* *
@ -1287,7 +1429,7 @@ sokoke_find_config_filename (const gchar* folder,
while ((config_dir = config_dirs[i++])) while ((config_dir = config_dirs[i++]))
{ {
gchar* path = g_build_filename (config_dir, PACKAGE_NAME, folder, filename, NULL); gchar* path = g_build_filename (config_dir, PACKAGE_NAME, folder, filename, NULL);
if (g_file_test (path, G_FILE_TEST_EXISTS)) if (g_access (path, F_OK) == 0)
return path; return path;
g_free (path); g_free (path);
} }
@ -1313,13 +1455,32 @@ sokoke_find_data_filename (const gchar* filename)
while ((data_dir = data_dirs[i++])) while ((data_dir = data_dirs[i++]))
{ {
gchar* path = g_build_filename (data_dir, filename, NULL); gchar* path = g_build_filename (data_dir, filename, NULL);
if (g_file_test (path, G_FILE_TEST_EXISTS)) if (g_access (path, F_OK) == 0)
return path; return path;
g_free (path); g_free (path);
} }
return g_build_filename (MDATADIR, filename, NULL); return g_build_filename (MDATADIR, filename, NULL);
} }
/**
* sokoke_get_argv:
* @argument_vector: %NULL
*
* Retrieves the argument vector passed at program startup.
*
* Return value: the argument vector
**/
gchar**
sokoke_get_argv (gchar** argument_vector)
{
static gchar** stored_argv = NULL;
if (!stored_argv)
stored_argv = g_strdupv (argument_vector);
return stored_argv;
}
#if !WEBKIT_CHECK_VERSION (1, 1, 14) #if !WEBKIT_CHECK_VERSION (1, 1, 14)
static void static void
res_server_handler_cb (SoupServer* res_server, res_server_handler_cb (SoupServer* res_server,
@ -1463,6 +1624,10 @@ sokoke_window_activate_key (GtkWindow* window,
if (gtk_window_activate_key (window, event)) if (gtk_window_activate_key (window, event))
return TRUE; return TRUE;
/* Hack to allow Ctrl + Shift + Tab */
if (event->keyval == 65056)
event->keyval = GDK_Tab;
/* We don't use gtk_accel_groups_activate because it refuses to /* We don't use gtk_accel_groups_activate because it refuses to
activate anything that gtk_accelerator_valid doesn't like. */ activate anything that gtk_accelerator_valid doesn't like. */
accel_name = gtk_accelerator_name (event->keyval, (event->state & gtk_accelerator_get_default_mod_mask ())); accel_name = gtk_accelerator_name (event->keyval, (event->state & gtk_accelerator_get_default_mod_mask ()));
@ -1511,3 +1676,152 @@ sokoke_file_chooser_dialog_new (const gchar* title,
#endif #endif
return dialog; return dialog;
} }
/**
* sokoke_prefetch_uri:
* @uri: an URI string
*
* Attempts to prefetch the specified URI, that is
* it tries to resolve the hostname in advance.
*
* Return value: %TRUE on success
**/
gboolean
sokoke_prefetch_uri (const char* uri)
{
#define MAXHOSTS 50
static gchar* hosts = NULL;
static gint host_count = G_MAXINT;
SoupURI* s_uri;
if (!uri)
return FALSE;
s_uri = soup_uri_new (uri);
if (!s_uri || !s_uri->host)
return FALSE;
#if GLIB_CHECK_VERSION (2, 22, 0)
if (g_hostname_is_ip_address (s_uri->host))
#else
if (g_ascii_isdigit (s_uri->host[0]) && g_strstr_len (s_uri->host, 4, "."))
#endif
{
soup_uri_free (s_uri);
return FALSE;
}
if (!g_str_has_prefix (uri, "http"))
{
soup_uri_free (s_uri);
return FALSE;
}
if (!hosts ||
!g_regex_match_simple (s_uri->host, hosts,
G_REGEX_CASELESS, G_REGEX_MATCH_NOTEMPTY))
{
SoupAddress* address;
gchar* new_hosts;
address = soup_address_new (s_uri->host, SOUP_ADDRESS_ANY_PORT);
soup_address_resolve_async (address, 0, 0, 0, 0);
g_object_unref (address);
if (host_count > MAXHOSTS)
{
katze_assign (hosts, g_strdup (""));
host_count = 0;
}
host_count++;
new_hosts = g_strdup_printf ("%s|%s", hosts, s_uri->host);
katze_assign (hosts, new_hosts);
}
soup_uri_free (s_uri);
return TRUE;
}
/* Provide a new way for SoupSession to assume an 'Accept-Language'
string automatically from the return value of g_get_language_names(),
properly formatted according to RFC2616.
Copyright (C) 2009 Mario Sanchez Prada <msanchez@igalia.com>
Copyright (C) 2009 Dan Winship <danw@gnome.org>
Mostly copied from libSoup 2.29, coding style adjusted */
/* Converts a language in POSIX format and to be RFC2616 compliant */
/* Based on code from epiphany-webkit (ephy_langs_append_languages()) */
static gchar *
sokoke_posix_lang_to_rfc2616 (const gchar *language)
{
if (!strchr (language, '.') && !strchr (language, '@') && language[0] != 'C')
/* change to lowercase and '_' to '-' */
return g_strdelimit (g_ascii_strdown (language, -1), "_", '-');
return NULL;
}
/* Adds a quality value to a string (any value between 0 and 1). */
static gchar *
sokoke_add_quality_value (const gchar *str,
float qvalue)
{
if ((qvalue >= 0.0) && (qvalue <= 1.0))
{
int qv_int = (qvalue * 1000 + 0.5);
return g_strdup_printf ("%s;q=%d.%d",
str, (int) (qv_int / 1000), qv_int % 1000);
}
return g_strdup (str);
}
/* Returns a RFC2616 compliant languages list from system locales */
gchar *
sokoke_accept_languages (const gchar* const * lang_names)
{
GArray *langs_garray = NULL;
char *cur_lang = NULL;
char *prev_lang = NULL;
char **langs_array;
char *langs_str;
float delta;
int i, n_lang_names;
/* Calculate delta for setting the quality values */
n_lang_names = g_strv_length ((gchar **)lang_names);
delta = 0.999 / (n_lang_names - 1);
/* Build the array of languages */
langs_garray = g_array_new (TRUE, FALSE, sizeof (char*));
for (i = 0; lang_names[i] != NULL; i++)
{
cur_lang = sokoke_posix_lang_to_rfc2616 (lang_names[i]);
/* Apart from getting a valid RFC2616 compliant
language, also get rid of extra variants */
if (cur_lang && (!prev_lang ||
(!strcmp (prev_lang, cur_lang) || !strstr (prev_lang, cur_lang))))
{
gchar *qv_lang = NULL;
/* Save reference for further comparison */
prev_lang = cur_lang;
/* Add the quality value and append it */
qv_lang = sokoke_add_quality_value (cur_lang, 1 - i * delta);
g_array_append_val (langs_garray, qv_lang);
}
}
/* Fallback: add "en" if list is empty */
if (langs_garray->len == 0)
{
gchar* fallback = g_strdup ("en");
g_array_append_val (langs_garray, fallback);
}
langs_array = (char **) g_array_free (langs_garray, FALSE);
langs_str = g_strjoinv (", ", langs_array);
return langs_str;
}

View file

@ -13,19 +13,54 @@
#ifndef __SOKOKE_H__ #ifndef __SOKOKE_H__
#define __SOKOKE_H__ 1 #define __SOKOKE_H__ 1
/* Common behavior modifiers */
#define MIDORI_MOD_NEW_WINDOW(state) (state & GDK_SHIFT_MASK)
#define MIDORI_MOD_NEW_TAB(state) (state & GDK_CONTROL_MASK)
#define MIDORI_MOD_BACKGROUND(state) (state & GDK_SHIFT_MASK)
#define MIDORI_MOD_SCROLL(state) (state & GDK_CONTROL_MASK)
#include <katze/katze.h> #include <katze/katze.h>
#include <webkit/webkit.h> #include <webkit/webkit.h>
#include <JavaScriptCore/JavaScript.h> #include <JavaScriptCore/JavaScript.h>
#if !GLIB_CHECK_VERSION (2, 14, 0)
#define G_PARAM_STATIC_STRINGS \
(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
#define gtk_dialog_get_content_area(dlg) dlg->vbox
#endif
#if !GTK_CHECK_VERSION (2, 16, 0)
#define GTK_ACTIVATABLE GTK_WIDGET
#define gtk_activatable_get_related_action gtk_widget_get_action
#endif
#if !GTK_CHECK_VERSION (2, 18, 0)
#define gtk_widget_is_toplevel(widget) GTK_WIDGET_TOPLEVEL (widget)
#define gtk_widget_has_focus(widget) GTK_WIDGET_HAS_FOCUS (widget)
#endif
#if !GTK_CHECK_VERSION(2, 12, 0)
void
gtk_widget_set_has_tooltip (GtkWidget* widget,
gboolean has_tooltip);
void
gtk_widget_set_tooltip_text (GtkWidget* widget,
const gchar* text);
void
gtk_tool_item_set_tooltip_text (GtkToolItem* toolitem,
const gchar* text);
#endif
gchar* gchar*
sokoke_js_script_eval (JSContextRef js_context, sokoke_js_script_eval (JSContextRef js_context,
const gchar* script, const gchar* script,
gchar** exception); gchar** exception);
/* Many themes need this hack for small toolbars to work */
#define GTK_ICON_SIZE_SMALL_TOOLBAR GTK_ICON_SIZE_BUTTON
void void
sokoke_message_dialog (GtkMessageType message_type, sokoke_message_dialog (GtkMessageType message_type,
const gchar* short_message, const gchar* short_message,
@ -60,8 +95,7 @@ gchar*
sokoke_uri_to_ascii (const gchar* uri); sokoke_uri_to_ascii (const gchar* uri);
gchar* gchar*
sokoke_magic_uri (const gchar* uri, sokoke_magic_uri (const gchar* uri);
KatzeArray* search_engines);
gchar* gchar*
sokoke_format_uri_for_display (const gchar* uri); sokoke_format_uri_for_display (const gchar* uri);
@ -144,6 +178,10 @@ sokoke_action_create_popup_menu_item (GtkAction* action);
gint64 gint64
sokoke_time_t_to_julian (const time_t* timestamp); sokoke_time_t_to_julian (const time_t* timestamp);
gint
sokoke_days_between (const time_t* day1,
const time_t* day2);
void void
sokoke_register_stock_items (void); sokoke_register_stock_items (void);
@ -161,6 +199,9 @@ sokoke_find_config_filename (const gchar* folder,
gchar* gchar*
sokoke_find_data_filename (const gchar* filename); sokoke_find_data_filename (const gchar* filename);
gchar**
sokoke_get_argv (gchar** argument_vector);
#if !WEBKIT_CHECK_VERSION (1, 1, 14) #if !WEBKIT_CHECK_VERSION (1, 1, 14)
SoupServer* SoupServer*
sokoke_get_res_server (void); sokoke_get_res_server (void);
@ -179,4 +220,10 @@ sokoke_file_chooser_dialog_new (const gchar* title,
GtkWindow* window, GtkWindow* window,
GtkFileChooserAction action); GtkFileChooserAction action);
gboolean
sokoke_prefetch_uri (const char* uri);
gchar *
sokoke_accept_languages (const gchar* const * lang_names);
#endif /* !__SOKOKE_H__ */ #endif /* !__SOKOKE_H__ */

View file

@ -4,32 +4,35 @@
import platform import platform
obj = bld.new_task_gen ('cc', 'staticlib') progressive = True
obj.name = 'midori-core' libs = 'M UNIQUE LIBSOUP GMODULE GTHREAD LIBIDN GIO GTK SQLITE ' \
obj.target = 'midori' 'LIBNOTIFY WEBKIT LIBXML X11 WS2_32 OPENSSL HILDON HILDON_FM'
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 LIBNOTIFY WEBKIT LIBXML ' \
'WS2_32 OPENSSL ' \
'HILDON HILDON_FM'
obj.uselib_local = 'katze'
obj.install_path = None
obj = bld.new_task_gen ('cc', 'staticlib') if progressive or Options.commands['check']:
obj.name = 'panels' obj = bld.new_task_gen ('cc', 'staticlib')
obj.target = 'panels' obj.target = 'midori-core'
obj.includes = '. ..' obj.includes = '.. ../katze .'
obj.find_sources_in_dirs ('../panels') obj.find_sources_in_dirs ('../katze . ../panels', excludes=['main.c'])
obj.uselib = 'UNIQUE LIBSOUP GMODULE GTHREAD GIO GTK SQLITE WEBKIT LIBXML X11' obj.uselib = libs
obj.uselib_local = 'midori-core' obj.add_marshal_file ('marshal.list', 'midori_cclosure_marshal')
obj.install_path = None obj.install_path = None
bld.add_group ()
obj = bld.new_task_gen ('cc', 'program') if progressive:
obj.target = 'midori' obj = bld.new_task_gen ('cc', 'program')
obj.includes = '. .. ../panels' obj.target = 'midori'
obj.source = 'main.c' obj.includes = '.. ../katze . ../panels'
if bld.env['WINRC']: obj.source = './main.c'
obj.source += ' ../data/midori.rc' obj.uselib = libs
obj.uselib = 'UNIQUE LIBSOUP GMODULE GTHREAD GIO GTK SQLITE WEBKIT LIBXML' obj.uselib_local = 'midori-core'
obj.uselib_local = 'panels' if bld.env['WINRC']:
obj.source += ' ../data/midori.rc'
else:
obj = bld.new_task_gen ('cc', 'program')
obj.target = 'midori'
obj.includes = '.. ../katze . ../panels'
obj.find_sources_in_dirs ('../katze . ../panels')
obj.add_marshal_file ('marshal.list', 'midori_cclosure_marshal')
obj.uselib = libs
if bld.env['WINRC']:
obj.source += ' ../data/midori.rc'

View file

@ -22,9 +22,14 @@
#include <webkit/webkit.h> #include <webkit/webkit.h>
#include <JavaScriptCore/JavaScript.h> #include <JavaScriptCore/JavaScript.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <string.h> #include <string.h>
#include <gio/gio.h> #include <gio/gio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
struct _MidoriAddons struct _MidoriAddons
{ {
GtkVBox parent_instance; GtkVBox parent_instance;
@ -212,14 +217,20 @@ _addons_get_directories (MidoriAddons* addons)
{ {
path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (), path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (),
PACKAGE_NAME, folders[i], NULL); PACKAGE_NAME, folders[i], NULL);
directories = g_slist_prepend (directories, path); if (g_access (path, X_OK) == 0)
directories = g_slist_prepend (directories, path);
else
g_free (path);
datadirs = g_get_system_data_dirs (); datadirs = g_get_system_data_dirs ();
while (*datadirs) while (*datadirs)
{ {
path = g_build_path (G_DIR_SEPARATOR_S, *datadirs, path = g_build_path (G_DIR_SEPARATOR_S, *datadirs,
PACKAGE_NAME, folders[i], NULL); PACKAGE_NAME, folders[i], NULL);
directories = g_slist_prepend (directories, path); if (g_access (path, X_OK) == 0)
directories = g_slist_prepend (directories, path);
else
g_free (path);
datadirs++; datadirs++;
} }
} }
@ -796,8 +807,12 @@ midori_web_widget_context_ready_cb (GtkWidget* web_widget,
gchar* message; gchar* message;
uri = katze_object_get_string (web_widget, "uri"); uri = katze_object_get_string (web_widget, "uri");
if (!uri) /* Don't run scripts or styles on blank or special pages */
if (!(uri && *uri && strncmp (uri, "about:", 6)))
{
g_free (uri);
return; return;
}
elements = addons->elements; elements = addons->elements;
while (elements) while (elements)

View file

@ -46,7 +46,6 @@ struct _MidoriBookmarks
GtkWidget* treeview; GtkWidget* treeview;
MidoriApp* app; MidoriApp* app;
KatzeArray* array; KatzeArray* array;
KatzeNet* net;
}; };
struct _MidoriBookmarksClass struct _MidoriBookmarksClass
@ -906,8 +905,6 @@ midori_bookmarks_init (MidoriBookmarks* bookmarks)
GtkCellRenderer* renderer_pixbuf; GtkCellRenderer* renderer_pixbuf;
GtkCellRenderer* renderer_text; GtkCellRenderer* renderer_text;
bookmarks->net = katze_net_new ();
/* Create the treeview */ /* Create the treeview */
model = midori_bookmark_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)); treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
@ -952,7 +949,6 @@ midori_bookmarks_finalize (GObject* object)
midori_bookmarks_disconnect_folder (bookmarks, bookmarks->array); midori_bookmarks_disconnect_folder (bookmarks, bookmarks->array);
if (bookmarks->app) if (bookmarks->app)
g_object_unref (bookmarks->app); g_object_unref (bookmarks->app);
g_object_unref (bookmarks->net);
} }
/** /**

View file

@ -219,6 +219,7 @@ midori_console_treeview_render_text_cb (GtkTreeViewColumn* column,
gtk_tree_model_get (model, iter, 0, &message, 1, &line, 2, &source_id, -1); gtk_tree_model_get (model, iter, 0, &message, 1, &line, 2, &source_id, -1);
g_strchomp (message);
text = g_strdup_printf ("%d @ %s\n%s", line, source_id, message); text = g_strdup_printf ("%d @ %s\n%s", line, source_id, message);
g_object_set (renderer, "text", text, NULL); g_object_set (renderer, "text", text, NULL);
g_free (text); g_free (text);

View file

@ -103,14 +103,10 @@ midori_extensions_get_toolbar (MidoriViewable* extensions)
if (!MIDORI_EXTENSIONS (extensions)->toolbar) if (!MIDORI_EXTENSIONS (extensions)->toolbar)
{ {
GtkWidget* toolbar; GtkWidget* toolbar;
GtkToolItem* toolitem;
toolbar = gtk_toolbar_new (); toolbar = gtk_toolbar_new ();
gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ); gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ);
gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON); gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON);
toolitem = gtk_tool_item_new ();
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
gtk_widget_show (GTK_WIDGET (toolitem));
MIDORI_EXTENSIONS (extensions)->toolbar = toolbar; MIDORI_EXTENSIONS (extensions)->toolbar = toolbar;
} }
@ -227,7 +223,7 @@ midori_extensions_treeview_render_tick_cb (GtkTreeViewColumn* column,
g_object_set (renderer, g_object_set (renderer,
"activatable", midori_extension_is_prepared (extension), "activatable", midori_extension_is_prepared (extension),
"active", midori_extension_is_active (extension), "active", midori_extension_is_active (extension) || g_object_get_data (G_OBJECT (extension), "static"),
NULL); NULL);
g_object_unref (extension); g_object_unref (extension);

View file

@ -18,6 +18,7 @@
#include "midori-viewable.h" #include "midori-viewable.h"
#include "sokoke.h" #include "sokoke.h"
#include "gtkiconentry.h"
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <string.h> #include <string.h>
@ -31,6 +32,14 @@ midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser,
gboolean new_bookmark, gboolean new_bookmark,
gboolean is_folder); gboolean is_folder);
#include "config.h"
#if HAVE_SQLITE
#include <sqlite3.h>
#endif
#define COMPLETION_DELAY 150
struct _MidoriHistory struct _MidoriHistory
{ {
GtkVBox parent_instance; GtkVBox parent_instance;
@ -42,7 +51,9 @@ struct _MidoriHistory
GtkWidget* treeview; GtkWidget* treeview;
MidoriApp* app; MidoriApp* app;
KatzeArray* array; KatzeArray* array;
KatzeNet* net;
gint filter_timeout;
gchar* filter;
}; };
struct _MidoriHistoryClass struct _MidoriHistoryClass
@ -114,6 +125,217 @@ midori_history_get_stock_id (MidoriViewable* viewable)
return STOCK_HISTORY; return STOCK_HISTORY;
} }
#if HAVE_SQLITE
static void
midori_history_clear_db (MidoriHistory* history)
{
gchar* sqlcmd;
sqlite3* db;
char* errmsg = NULL;
db = g_object_get_data (G_OBJECT (history->array), "db");
sqlcmd = sqlite3_mprintf ("DELETE FROM history");
if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK)
{
g_printerr (_("Failed to remove history item: %s\n"), errmsg);
sqlite3_free (errmsg);
}
sqlite3_free (sqlcmd);
}
static void
midori_history_remove_item_from_db (MidoriHistory* history,
KatzeItem* item)
{
gchar* sqlcmd;
sqlite3* db;
char* errmsg = NULL;
db = g_object_get_data (G_OBJECT (history->array), "db");
if (katze_item_get_uri (item))
sqlcmd = sqlite3_mprintf (
"DELETE FROM history WHERE uri = '%q' AND"
" title = '%q' AND date = %llu",
katze_item_get_uri (item),
katze_item_get_name (item),
katze_item_get_added (item));
else
sqlcmd = sqlite3_mprintf (
"DELETE FROM history WHERE day = %d", katze_item_get_added (item));
if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK)
{
g_printerr (_("Failed to remove history item: %s\n"), errmsg);
sqlite3_free (errmsg);
}
sqlite3_free (sqlcmd);
}
/**
* midori_history_read_from_db:
* @history: a #MidoriHistory
* @model: a #GtkTreeStore
* @parent: a #GtkTreeIter, or %NULL
* @req_day: the timestamp of one day, or 0
* @filter: a filter string to search for
*
* Populates the model according to parameters:
* 1. If @req_day is 0, all dates are added as folders.
* 2. If @req_day is given, all pages for that day are added.
* 3. If @filter is given, all pages matching the filter are added.
**/
static gboolean
midori_history_read_from_db (MidoriHistory* history,
GtkTreeStore* model,
GtkTreeIter* parent,
int req_day,
const gchar* filter)
{
sqlite3* db;
sqlite3_stmt* statement;
gint result;
const gchar* sqlcmd;
time_t current_time;
GtkTreeIter iter;
GtkTreeIter root_iter;
db = g_object_get_data (G_OBJECT (history->array), "db");
if (filter && *filter)
{
gchar* filterstr;
sqlcmd = "SELECT uri, title, day FROM history_view "
"WHERE uri LIKE ? or title LIKE ? GROUP BY uri "
"UNION ALL "
"SELECT replace(uri, '%s', title) AS uri, title, day "
"FROM search_view WHERE title LIKE ?1 GROUP BY uri "
"ORDER BY day ASC";
result = sqlite3_prepare_v2 (db, sqlcmd, -1, &statement, NULL);
filterstr = g_strdup_printf ("%%%s%%", filter);
sqlite3_bind_text (statement, 1, filterstr, -1, g_free);
sqlite3_bind_text (statement, 2, g_strdup (filterstr), -1, g_free);
req_day = -1;
}
else if (req_day == 0)
{
sqlcmd = "SELECT day, date FROM history GROUP BY day ORDER BY day ASC";
result = sqlite3_prepare_v2 (db, sqlcmd, -1, &statement, NULL);
}
else
{
sqlcmd = "SELECT uri, title, date, day "
"FROM history WHERE day = ? "
"GROUP BY uri ORDER BY date ASC";
result = sqlite3_prepare_v2 (db, sqlcmd, -1, &statement, NULL);
sqlite3_bind_int64 (statement, 1, req_day);
}
if (result != SQLITE_OK)
return FALSE;
if (req_day == 0)
current_time = time (NULL);
while ((result = sqlite3_step (statement)) == SQLITE_ROW)
{
KatzeItem* item;
const unsigned char* uri;
const unsigned char* title;
sqlite3_int64 date;
sqlite3_int64 day;
if (req_day == 0)
{
gint age;
gchar token[50];
gchar* sdate;
day = sqlite3_column_int64 (statement, 0);
date = sqlite3_column_int64 (statement, 1);
item = katze_item_new ();
katze_item_set_added (item, day);
age = sokoke_days_between ((time_t*)&date, &current_time);
/* A negative age is a date in the future, the clock is probably off */
if (age < -1)
{
static gboolean clock_warning = FALSE;
if (!clock_warning)
{
midori_app_send_notification (history->app,
_("Erroneous clock time"),
_("The clock time lies in the past. "
"Please check the current date and time."));
clock_warning = TRUE;
}
}
if (age > 7 || age < 0)
{
strftime (token, sizeof (token), "%x", localtime ((time_t*)&date));
sdate = token;
}
else if (age > 6)
sdate = _("A week ago");
else if (age > 1)
sdate = g_strdup_printf (ngettext ("%d day ago",
"%d days ago", (gint)age), (gint)age);
else if (age == 0)
sdate = _("Today");
else
sdate = _("Yesterday");
gtk_tree_store_insert_with_values (model, &root_iter, NULL,
0, 0, item, 1, sdate, -1);
/* That's an invisible dummy, so we always have an expander */
gtk_tree_store_insert_with_values (model, &iter, &root_iter,
0, 0, NULL, 1, NULL, -1);
if (age > 1 && age < 7)
g_free (sdate);
}
else
{
uri = sqlite3_column_text (statement, 0);
title = sqlite3_column_text (statement, 1);
date = sqlite3_column_int64 (statement, 2);
day = sqlite3_column_int64 (statement, 3);
if (!uri)
continue;
item = katze_item_new ();
katze_item_set_added (item, date);
katze_item_set_uri (item, (gchar*)uri);
katze_item_set_name (item, (gchar*)title);
gtk_tree_store_insert_with_values (model, NULL, parent,
0, 0, item, 1, katze_item_get_name (item), -1);
}
}
if (req_day != 0 && !(filter && *filter))
{
/* Remove invisible dummy row */
GtkTreeIter child;
gint last = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), parent);
gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (model), &child, parent, last - 1);
gtk_tree_store_remove (model, &child);
}
if (result != SQLITE_DONE)
g_print (_("Failed to execute database statement: %s\n"),
sqlite3_errmsg (db));
sqlite3_finalize (statement);
return FALSE;
}
static void static void
midori_history_add_clicked_cb (GtkWidget* toolitem) midori_history_add_clicked_cb (GtkWidget* toolitem)
{ {
@ -133,16 +355,10 @@ midori_history_delete_clicked_cb (GtkWidget* toolitem,
&model, &iter)) &model, &iter))
{ {
KatzeItem* item; KatzeItem* item;
KatzeArray* parent;
gtk_tree_model_get (model, &iter, 0, &item, -1); gtk_tree_model_get (model, &iter, 0, &item, -1);
midori_history_remove_item_from_db (history, item);
/* FIXME: Even toplevel items should technically have a parent */ gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
g_return_if_fail (katze_item_get_parent (item));
parent = katze_item_get_parent (item);
katze_array_remove_item (parent, item);
g_object_unref (item); g_object_unref (item);
} }
} }
@ -165,7 +381,7 @@ midori_history_clear_clicked_cb (GtkWidget* toolitem,
if (result != GTK_RESPONSE_YES) if (result != GTK_RESPONSE_YES)
return; return;
katze_array_clear (history->array); midori_history_clear_db (history);
} }
static void static void
@ -185,11 +401,12 @@ midori_history_cursor_or_row_changed_cb (GtkTreeView* treeview,
gtk_tree_model_get (model, &iter, 0, &item, -1); gtk_tree_model_get (model, &iter, 0, &item, -1);
is_page = !KATZE_IS_ARRAY (item) && katze_item_get_uri (item); is_page = item && katze_item_get_uri (item);
gtk_widget_set_sensitive (history->bookmark, is_page); gtk_widget_set_sensitive (history->bookmark, is_page);
gtk_widget_set_sensitive (history->delete, TRUE); gtk_widget_set_sensitive (history->delete, TRUE);
g_object_unref (item); if (item)
g_object_unref (item);
} }
else else
{ {
@ -197,6 +414,7 @@ midori_history_cursor_or_row_changed_cb (GtkTreeView* treeview,
gtk_widget_set_sensitive (history->delete, FALSE); gtk_widget_set_sensitive (history->delete, FALSE);
} }
} }
#endif
static GtkWidget* static GtkWidget*
midori_history_get_toolbar (MidoriViewable* viewable) midori_history_get_toolbar (MidoriViewable* viewable)
@ -206,12 +424,15 @@ midori_history_get_toolbar (MidoriViewable* viewable)
if (!history->toolbar) if (!history->toolbar)
{ {
GtkWidget* toolbar; GtkWidget* toolbar;
#if HAVE_SQLITE
GtkToolItem* toolitem; GtkToolItem* toolitem;
#endif
toolbar = gtk_toolbar_new (); toolbar = gtk_toolbar_new ();
gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ); gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ);
gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON); gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON);
history->toolbar = toolbar; history->toolbar = toolbar;
#if HAVE_SQLITE
toolitem = gtk_tool_button_new_from_stock (STOCK_BOOKMARK_ADD); toolitem = gtk_tool_button_new_from_stock (STOCK_BOOKMARK_ADD);
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),
_("Bookmark the selected history item")); _("Bookmark the selected history item"));
@ -245,6 +466,7 @@ midori_history_get_toolbar (MidoriViewable* viewable)
G_CALLBACK (gtk_widget_destroyed), &history->delete); G_CALLBACK (gtk_widget_destroyed), &history->delete);
g_signal_connect (history->clear, "destroy", g_signal_connect (history->clear, "destroy",
G_CALLBACK (gtk_widget_destroyed), &history->clear); G_CALLBACK (gtk_widget_destroyed), &history->clear);
#endif
} }
return history->toolbar; return history->toolbar;
@ -258,222 +480,6 @@ midori_history_viewable_iface_init (MidoriViewableIface* iface)
iface->get_toolbar = midori_history_get_toolbar; iface->get_toolbar = midori_history_get_toolbar;
} }
static void
midori_history_add_item_cb (KatzeArray* array,
KatzeItem* added_item,
MidoriHistory* history);
static void
midori_history_remove_item_cb (KatzeArray* array,
KatzeItem* removed_item,
MidoriHistory* history);
static void
midori_history_clear_cb (KatzeArray* array,
MidoriHistory* history);
static void
midori_history_disconnect_folder (MidoriHistory* history,
KatzeArray* array,
gboolean unref)
{
KatzeItem* item;
guint i;
g_return_if_fail (KATZE_IS_ARRAY (array));
g_signal_handlers_disconnect_by_func (array,
midori_history_add_item_cb, history);
g_signal_handlers_disconnect_by_func (array,
midori_history_remove_item_cb, history);
g_signal_handlers_disconnect_by_func (array,
midori_history_clear_cb, history);
i = 0;
while ((item = katze_array_get_nth_item (array, i++)))
{
if (KATZE_IS_ARRAY (item))
midori_history_disconnect_folder (history, KATZE_ARRAY (item), unref);
if (unref)
g_object_unref (item);
}
}
static void
midori_history_add_item_cb (KatzeArray* array,
KatzeItem* added_item,
MidoriHistory* history)
{
GtkTreeModel* model;
GtkTreeIter iter;
guint i;
g_return_if_fail (KATZE_IS_ARRAY (array));
g_return_if_fail (KATZE_IS_ITEM (added_item));
g_return_if_fail (MIDORI_IS_HISTORY (history));
if (KATZE_IS_ARRAY (added_item))
{
g_signal_connect (added_item, "add-item",
G_CALLBACK (midori_history_add_item_cb), history);
g_signal_connect (added_item, "remove-item",
G_CALLBACK (midori_history_remove_item_cb), history);
g_signal_connect (added_item, "clear",
G_CALLBACK (midori_history_clear_cb), history);
}
g_object_ref (added_item);
model = gtk_tree_view_get_model (GTK_TREE_VIEW (history->treeview));
if (array == history->array)
{
gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
&iter, NULL, 0, 0, added_item, -1);
return;
}
i = 0;
/* FIXME: Recurse over children of folders, too */
while (gtk_tree_model_iter_nth_child (model, &iter, NULL, i))
{
KatzeItem* item;
gtk_tree_model_get (model, &iter, 0, &item, -1);
if (item == (KatzeItem*)array)
{
GtkTreeIter child_iter;
gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
&child_iter, &iter, 0, 0, added_item, -1);
break;
}
g_object_unref (item);
i++;
}
}
static void
midori_history_remove_iter (GtkTreeModel* model,
GtkTreeIter* parent,
KatzeItem* removed_item)
{
guint i;
GtkTreeIter iter;
i = 0;
while (gtk_tree_model_iter_nth_child (model, &iter, parent, i))
{
KatzeItem* item;
gtk_tree_model_get (model, &iter, 0, &item, -1);
if (item == removed_item)
{
gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
g_object_unref (item);
break;
}
if (KATZE_IS_ARRAY (item))
midori_history_remove_iter (model, &iter, removed_item);
g_object_unref (item);
i++;
}
}
static void
midori_history_remove_item_cb (KatzeArray* array,
KatzeItem* removed_item,
MidoriHistory* history)
{
GtkTreeModel* model;
g_assert (KATZE_IS_ARRAY (array));
g_assert (KATZE_IS_ITEM (removed_item));
if (KATZE_IS_ARRAY (removed_item))
midori_history_disconnect_folder (history, KATZE_ARRAY (removed_item), TRUE);
model = gtk_tree_view_get_model (GTK_TREE_VIEW (history->treeview));
midori_history_remove_iter (model, NULL, removed_item);
g_object_unref (removed_item);
}
static void
midori_history_clear_cb (KatzeArray* array,
MidoriHistory* history)
{
GtkTreeView* treeview;
GtkTreeStore* store;
g_assert (KATZE_IS_ARRAY (array));
if (array == history->array)
{
treeview = GTK_TREE_VIEW (history->treeview);
store = GTK_TREE_STORE (gtk_tree_view_get_model (treeview));
gtk_tree_store_clear (store);
}
else
{
KatzeItem* item;
guint i;
i = 0;
while ((item = katze_array_get_nth_item (array, i++)))
midori_history_remove_item_cb (array, item, history);
}
midori_history_disconnect_folder (history, array, TRUE);
}
static void
midori_history_insert_item (MidoriHistory* history,
GtkTreeStore* treestore,
GtkTreeIter* parent,
KatzeItem* item,
gint64 day)
{
GtkTreeIter iter;
gint64 age = -1;
g_return_if_fail (KATZE_IS_ITEM (item));
if (KATZE_IS_ARRAY (item))
{
GtkTreeIter* piter;
gint64 pday;
guint i;
KatzeItem* child;
g_signal_connect (item, "add-item",
G_CALLBACK (midori_history_add_item_cb), history);
g_signal_connect (item, "remove-item",
G_CALLBACK (midori_history_remove_item_cb), history);
g_signal_connect (item, "clear",
G_CALLBACK (midori_history_clear_cb), history);
piter = parent;
if ((pday = katze_item_get_added (item)))
{
age = day - pday;
gtk_tree_store_insert_with_values (treestore, &iter, parent,
0, 0, item, 1, age, -1);
piter = &iter;
}
i = 0;
while ((child = katze_array_get_nth_item (KATZE_ARRAY (item), i++)))
midori_history_insert_item (history, treestore, piter, child, day);
}
else
{
gtk_tree_store_insert_with_values (treestore, &iter, parent,
0, 0, item, 1, age, -1);
}
}
static void static void
midori_history_set_app (MidoriHistory* history, midori_history_set_app (MidoriHistory* history,
MidoriApp* app) MidoriApp* app)
@ -482,26 +488,22 @@ midori_history_set_app (MidoriHistory* history,
if (history->array) if (history->array)
{ {
midori_history_disconnect_folder (history, history->array, TRUE);
g_object_unref (history->array); g_object_unref (history->array);
model = gtk_tree_view_get_model (GTK_TREE_VIEW (history->treeview)); model = gtk_tree_view_get_model (GTK_TREE_VIEW (history->treeview));
gtk_tree_store_clear (GTK_TREE_STORE (model)); gtk_tree_store_clear (GTK_TREE_STORE (model));
} }
katze_assign (history->app, app); katze_assign (history->app, app);
if (!app) if (!app)
return; return;
g_object_ref (app); g_object_ref (app);
history->array = katze_object_get_object (app, "history");
if (history->array)
{
time_t now = time (NULL);
gint64 day = sokoke_time_t_to_julian (&now);
model = gtk_tree_view_get_model (GTK_TREE_VIEW (history->treeview)); history->array = katze_object_get_object (app, "history");
midori_history_insert_item (history, GTK_TREE_STORE (model), model = gtk_tree_view_get_model (GTK_TREE_VIEW (history->treeview));
NULL, KATZE_ITEM (history->array), day); #if HAVE_SQLITE
} if (history->array)
midori_history_read_from_db (history, GTK_TREE_STORE (model), NULL, 0, NULL);
#endif
} }
static void static void
@ -550,89 +552,28 @@ midori_history_treeview_render_icon_cb (GtkTreeViewColumn* column,
GtkWidget* treeview) GtkWidget* treeview)
{ {
KatzeItem* item; KatzeItem* item;
GdkPixbuf* pixbuf = NULL; GdkPixbuf* pixbuf;
gtk_tree_model_get (model, iter, 0, &item, -1); gtk_tree_model_get (model, iter, 0, &item, -1);
g_assert (KATZE_IS_ITEM (item)); if (!item)
pixbuf = NULL;
if (KATZE_IS_ARRAY (item)) else if (katze_item_get_uri (item))
pixbuf = katze_load_cached_icon (katze_item_get_uri (item), treeview);
else
pixbuf = gtk_widget_render_icon (treeview, GTK_STOCK_DIRECTORY, pixbuf = gtk_widget_render_icon (treeview, GTK_STOCK_DIRECTORY,
GTK_ICON_SIZE_MENU, NULL); GTK_ICON_SIZE_MENU, NULL);
else
pixbuf = katze_load_cached_icon (katze_item_get_uri (item), treeview);
g_object_set (renderer, "pixbuf", pixbuf, NULL); g_object_set (renderer, "pixbuf", pixbuf, NULL);
if (pixbuf) if (pixbuf)
g_object_unref (pixbuf);
g_object_unref (item);
}
static void
midori_history_treeview_render_text_cb (GtkTreeViewColumn* column,
GtkCellRenderer* renderer,
GtkTreeModel* model,
GtkTreeIter* iter,
MidoriHistory* history)
{
KatzeItem* item;
gint64 age;
gtk_tree_model_get (model, iter, 0, &item, 1, &age, -1);
g_assert (KATZE_IS_ITEM (item));
if (KATZE_IS_ARRAY (item))
{ {
gchar* sdate; g_object_unref (pixbuf);
g_object_unref (item);
/* A negative age is a date in the future, the clock is probably off */
if (age < -1)
{
static gboolean clock_warning = FALSE;
if (!clock_warning)
{
midori_app_send_notification (history->app,
_("Erroneous clock time"),
_("The clock time lies in the past. "
"Please check the current date and time."));
clock_warning = TRUE;
}
}
if (age > 7 || age < 0)
{
g_object_set (renderer, "text", katze_item_get_name (item), NULL);
}
else if (age > 6)
{
sdate = _("A week ago");
g_object_set (renderer, "text", sdate, NULL);
}
else if (age > 1)
{
sdate = g_strdup_printf (ngettext ("%d day ago",
"%d days ago", (gint)age), (gint)age);
g_object_set (renderer, "text", sdate, NULL);
g_free (sdate);
}
else
{
if (age == 0)
sdate = _("Today");
else
sdate = _("Yesterday");
g_object_set (renderer, "text", sdate, NULL);
}
} }
else
g_object_set (renderer, "text", katze_item_get_name (item), NULL);
g_object_unref (item);
} }
#if HAVE_SQLITE
static void static void
midori_history_row_activated_cb (GtkTreeView* treeview, midori_history_row_activated_cb (GtkTreeView* treeview,
GtkTreePath* path, GtkTreePath* path,
@ -649,6 +590,10 @@ midori_history_row_activated_cb (GtkTreeView* treeview,
if (gtk_tree_model_get_iter (model, &iter, path)) if (gtk_tree_model_get_iter (model, &iter, path))
{ {
gtk_tree_model_get (model, &iter, 0, &item, -1); gtk_tree_model_get (model, &iter, 0, &item, -1);
if (!item)
return;
uri = katze_item_get_uri (item); uri = katze_item_get_uri (item);
if (uri && *uri) if (uri && *uri)
{ {
@ -791,22 +736,6 @@ midori_history_bookmark_activate_cb (GtkWidget* menuitem,
} }
} }
static void
midori_history_delete_activate_cb (GtkWidget* menuitem,
MidoriHistory* history)
{
KatzeItem* item;
KatzeArray* parent;
item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem");
/* FIXME: Even toplevel items should technically have a parent */
g_return_if_fail (katze_item_get_parent (item));
parent = katze_item_get_parent (item);
katze_array_remove_item (parent, item);
}
static void static void
midori_history_popup (GtkWidget* widget, midori_history_popup (GtkWidget* widget,
GdkEventButton* event, GdkEventButton* event,
@ -836,7 +765,7 @@ midori_history_popup (GtkWidget* widget,
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem); gtk_widget_show (menuitem);
midori_history_popup_item (menu, GTK_STOCK_DELETE, NULL, midori_history_popup_item (menu, GTK_STOCK_DELETE, NULL,
item, midori_history_delete_activate_cb, history); item, midori_history_delete_clicked_cb, history);
katze_widget_popup (widget, GTK_MENU (menu), event, KATZE_MENU_POSITION_CURSOR); katze_widget_popup (widget, GTK_MENU (menu), event, KATZE_MENU_POSITION_CURSOR);
} }
@ -858,6 +787,9 @@ midori_history_button_release_event_cb (GtkWidget* widget,
gtk_tree_model_get (model, &iter, 0, &item, -1); gtk_tree_model_get (model, &iter, 0, &item, -1);
if (!item)
return FALSE;
if (event->button == 2) if (event->button == 2)
{ {
const gchar* uri = katze_item_get_uri (item); const gchar* uri = katze_item_get_uri (item);
@ -895,13 +827,10 @@ midori_history_key_release_event_cb (GtkWidget* widget,
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter)) if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter))
{ {
KatzeItem* item; KatzeItem* item;
KatzeArray* parent;
gtk_tree_model_get (model, &iter, 0, &item, -1); gtk_tree_model_get (model, &iter, 0, &item, -1);
midori_history_remove_item_from_db (history, item);
parent = katze_item_get_parent (item); gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
katze_array_remove_item (parent, item);
g_object_unref (item); g_object_unref (item);
} }
@ -924,20 +853,110 @@ midori_history_popup_menu_cb (GtkWidget* widget,
} }
} }
static void
midori_history_row_expanded_cb (GtkTreeView* treeview,
GtkTreeIter* iter,
GtkTreePath* path,
MidoriHistory* history)
{
GtkTreeModel* model;
KatzeItem* item;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
gtk_tree_model_get (model, iter, 0, &item, -1);
midori_history_read_from_db (history, GTK_TREE_STORE (model),
iter, katze_item_get_added (item), NULL);
g_object_unref (item);
}
static void
midori_history_row_collapsed_cb (GtkTreeView *treeview,
GtkTreeIter *parent,
GtkTreePath *path,
gpointer user_data)
{
GtkTreeModel* model;
GtkTreeStore* treestore;
GtkTreeIter child;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
treestore = GTK_TREE_STORE (model);
while (gtk_tree_model_iter_nth_child (model, &child, parent, 0))
gtk_tree_store_remove (treestore, &child);
/* That's an invisible dummy, so we always have an expander */
gtk_tree_store_insert_with_values (treestore, &child, parent,
0, 0, NULL, 1, NULL, -1);
}
static gboolean
midori_history_filter_timeout_cb (gpointer data)
{
MidoriHistory* history = data;
GtkTreeModel* model;
GtkTreeStore* treestore;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (history->treeview));
treestore = GTK_TREE_STORE (model);
gtk_tree_store_clear (treestore);
midori_history_read_from_db (history, treestore, NULL, 0, history->filter);
return FALSE;
}
static void
midori_history_filter_entry_changed_cb (GtkEntry* entry,
MidoriHistory* history)
{
if (history->filter_timeout)
g_source_remove (history->filter_timeout);
history->filter_timeout = g_timeout_add (COMPLETION_DELAY,
midori_history_filter_timeout_cb, history);
katze_assign (history->filter, g_strdup (gtk_entry_get_text (entry)));
}
#endif
static void
midori_history_filter_entry_clear_cb (GtkEntry* entry,
gint icon_pos,
gint button,
MidoriHistory* history)
{
if (icon_pos == GTK_ICON_ENTRY_SECONDARY)
gtk_entry_set_text (entry, "");
}
static void static void
midori_history_init (MidoriHistory* history) midori_history_init (MidoriHistory* history)
{ {
GtkWidget* entry;
GtkWidget* box;
GtkTreeStore* model; GtkTreeStore* model;
GtkWidget* treeview; GtkWidget* treeview;
GtkTreeViewColumn* column; GtkTreeViewColumn* column;
GtkCellRenderer* renderer_pixbuf; GtkCellRenderer* renderer_pixbuf;
GtkCellRenderer* renderer_text; GtkCellRenderer* renderer_text;
history->net = katze_net_new (); /* Create the filter entry */
/* FIXME: Dereference the net on finalization */ entry = gtk_icon_entry_new ();
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_SECONDARY, GTK_STOCK_CLEAR);
gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_SECONDARY, TRUE);
g_signal_connect (entry, "icon-release",
G_CALLBACK (midori_history_filter_entry_clear_cb), history);
#if HAVE_SQLITE
g_signal_connect (entry, "changed",
G_CALLBACK (midori_history_filter_entry_changed_cb), history);
#endif
box = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (box), gtk_label_new (_("Filter:")), FALSE, FALSE, 3);
gtk_box_pack_start (GTK_BOX (box), entry, TRUE, TRUE, 3);
gtk_widget_show_all (box);
gtk_box_pack_start (GTK_BOX (history), box, FALSE, FALSE, 5);
/* Create the treeview */ /* Create the treeview */
model = gtk_tree_store_new (2, KATZE_TYPE_ITEM, G_TYPE_INT64); model = gtk_tree_store_new (2, KATZE_TYPE_ITEM, G_TYPE_STRING);
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model)); treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
column = gtk_tree_view_column_new (); column = gtk_tree_view_column_new ();
@ -948,11 +967,11 @@ midori_history_init (MidoriHistory* history)
treeview, NULL); treeview, NULL);
renderer_text = gtk_cell_renderer_text_new (); renderer_text = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer_text, FALSE); gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
gtk_tree_view_column_set_cell_data_func (column, renderer_text, gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (column), renderer_text,
(GtkTreeCellDataFunc)midori_history_treeview_render_text_cb, "text", 1, NULL);
history, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
g_object_unref (model); g_object_unref (model);
#if HAVE_SQLITE
g_object_connect (treeview, g_object_connect (treeview,
"signal::row-activated", "signal::row-activated",
midori_history_row_activated_cb, history, midori_history_row_activated_cb, history,
@ -964,12 +983,20 @@ midori_history_init (MidoriHistory* history)
midori_history_button_release_event_cb, history, midori_history_button_release_event_cb, history,
"signal::key-release-event", "signal::key-release-event",
midori_history_key_release_event_cb, history, midori_history_key_release_event_cb, history,
"signal::row-expanded",
midori_history_row_expanded_cb, history,
"signal::row-collapsed",
midori_history_row_collapsed_cb, history,
"signal::popup-menu", "signal::popup-menu",
midori_history_popup_menu_cb, history, midori_history_popup_menu_cb, history,
NULL); NULL);
#endif
gtk_widget_show (treeview); gtk_widget_show (treeview);
gtk_box_pack_start (GTK_BOX (history), treeview, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (history), treeview, TRUE, TRUE, 0);
history->treeview = treeview; history->treeview = treeview;
/* FIXME: We need to connect a signal here, to add new pages into history */
history->filter = NULL;
} }
static void static void
@ -982,8 +1009,8 @@ midori_history_finalize (GObject* object)
/* FIXME: We don't unref items (last argument is FALSE) because /* FIXME: We don't unref items (last argument is FALSE) because
our reference counting is incorrect. */ our reference counting is incorrect. */
midori_history_disconnect_folder (history, history->array, FALSE);
g_object_unref (history->array); g_object_unref (history->array);
katze_assign (history->filter, NULL);
} }
/** /**

View file

@ -1,291 +0,0 @@
/*
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-plugins.h"
#include "midori-app.h"
#include "midori-stock.h"
#include "midori-viewable.h"
#include "sokoke.h"
#include <string.h>
#include <glib/gi18n.h>
struct _MidoriPlugins
{
GtkVBox parent_instance;
GtkWidget* toolbar;
GtkWidget* treeview;
MidoriApp* app;
};
struct _MidoriPluginsClass
{
GtkVBoxClass parent_class;
};
static void
midori_plugins_viewable_iface_init (MidoriViewableIface* iface);
G_DEFINE_TYPE_WITH_CODE (MidoriPlugins, midori_plugins, GTK_TYPE_VBOX,
G_IMPLEMENT_INTERFACE (MIDORI_TYPE_VIEWABLE,
midori_plugins_viewable_iface_init));
enum
{
PROP_0,
PROP_APP
};
static void
midori_plugins_set_property (GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec);
static void
midori_plugins_get_property (GObject* object,
guint prop_id,
GValue* value,
GParamSpec* pspec);
static void
midori_plugins_class_init (MidoriPluginsClass* class)
{
GObjectClass* gobject_class;
GParamFlags flags;
gobject_class = G_OBJECT_CLASS (class);
gobject_class->set_property = midori_plugins_set_property;
gobject_class->get_property = midori_plugins_get_property;
flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
g_object_class_install_property (gobject_class,
PROP_APP,
g_param_spec_object (
"app",
"App",
"The app",
MIDORI_TYPE_APP,
flags));
}
static const gchar*
midori_plugins_get_label (MidoriViewable* viewable)
{
return _("Netscape plugins");
}
static const gchar*
midori_plugins_get_stock_id (MidoriViewable* viewable)
{
return STOCK_PLUGINS;
}
static GtkWidget*
midori_plugins_get_toolbar (MidoriViewable* plugins)
{
if (!MIDORI_PLUGINS (plugins)->toolbar)
{
GtkWidget* toolbar;
GtkToolItem* toolitem;
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);
toolitem = gtk_tool_item_new ();
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
gtk_widget_show (GTK_WIDGET (toolitem));
MIDORI_PLUGINS (plugins)->toolbar = toolbar;
}
return MIDORI_PLUGINS (plugins)->toolbar;
}
static void
midori_plugins_viewable_iface_init (MidoriViewableIface* iface)
{
iface->get_stock_id = midori_plugins_get_stock_id;
iface->get_label = midori_plugins_get_label;
iface->get_toolbar = midori_plugins_get_toolbar;
}
static void
midori_plugins_set_property (GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec)
{
MidoriPlugins* plugins = MIDORI_PLUGINS (object);
switch (prop_id)
{
case PROP_APP:
plugins->app = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
midori_plugins_get_property (GObject* object,
guint prop_id,
GValue* value,
GParamSpec* pspec)
{
MidoriPlugins* plugins = MIDORI_PLUGINS (object);
switch (prop_id)
{
case PROP_APP:
g_value_set_object (value, plugins->app);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
midori_plugins_treeview_render_icon_cb (GtkTreeViewColumn* column,
GtkCellRenderer* renderer,
GtkTreeModel* model,
GtkTreeIter* iter,
GtkWidget* treeview)
{
g_object_set (renderer, "stock-id", GTK_STOCK_EXECUTE, NULL);
}
static void
midori_plugins_treeview_render_text_cb (GtkTreeViewColumn* column,
GtkCellRenderer* renderer,
GtkTreeModel* model,
GtkTreeIter* iter,
GtkWidget* treeview)
{
gchar* name;
gchar* text;
gchar* description;
gtk_tree_model_get (model, iter, 0, &name, 1, &description, -1);
text = g_strdup_printf ("%s\n%s", name, description);
g_free (name);
g_free (description);
g_object_set (renderer, "text", text, NULL);
g_free (text);
}
static void
midori_plugins_add_item (MidoriPlugins* plugins,
const gchar* name,
const gchar* description)
{
gchar* desc;
GtkTreeIter iter;
GtkTreeModel* model;
desc = g_strdup (description);
if (desc)
{
gsize i, n;
n = strlen (desc);
for (i = 0; i < n; i++)
if (desc[i] == ';')
desc[i] = '\n';
}
model = gtk_tree_view_get_model (GTK_TREE_VIEW (plugins->treeview));
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
0, name, 1, desc, -1);
g_free (desc);
}
static void
midori_plugins_init (MidoriPlugins* plugins)
{
/* Create the treeview */
GtkTreeViewColumn* column;
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 ();
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_plugins_treeview_render_icon_cb,
plugins->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_plugins_treeview_render_text_cb,
plugins->treeview, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (plugins->treeview), column);
g_object_unref (liststore);
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 */
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) "
"{ 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)
{
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 (items);
}
}
/**
* midori_plugins_new:
*
* Creates a new empty plugins.
*
* Return value: a new #MidoriPlugins
*
* Since: 0.1.3
**/
GtkWidget*
midori_plugins_new (void)
{
MidoriPlugins* plugins = g_object_new (MIDORI_TYPE_PLUGINS, NULL);
return GTK_WIDGET (plugins);
}

View file

@ -1,43 +0,0 @@
/*
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_PLUGINS_H__
#define __MIDORI_PLUGINS_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define MIDORI_TYPE_PLUGINS \
(midori_plugins_get_type ())
#define MIDORI_PLUGINS(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_PLUGINS, MidoriPlugins))
#define MIDORI_PLUGINS_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_PLUGINS, MidoriPluginsClass))
#define MIDORI_IS_PLUGINS(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_PLUGINS))
#define MIDORI_IS_PLUGINS_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_PLUGINS))
#define MIDORI_PLUGINS_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_PLUGINS, MidoriPluginsClass))
typedef struct _MidoriPlugins MidoriPlugins;
typedef struct _MidoriPluginsClass MidoriPluginsClass;
GType
midori_plugins_get_type (void);
GtkWidget*
midori_plugins_new (void);
G_END_DECLS
#endif /* __MIDORI_PLUGINS_H__ */

View file

@ -17,7 +17,6 @@
#include "midori-view.h" #include "midori-view.h"
#include "sokoke.h" #include "sokoke.h"
#include "compat.h"
#include <glib/gi18n.h> #include <glib/gi18n.h>
struct _MidoriTransfers struct _MidoriTransfers

View file

@ -1,2 +0,0 @@
# set of available languages (in alphabetic order)
ast ca cs da de el en_GB es et fi fr gl he hu id it ja ko nl no pl pt pt_BR ro ru sk sr sr@latin sv tr uk zh_CN zh_TW

View file

@ -6,7 +6,6 @@ midori/midori-app.c
midori/midori-array.c midori/midori-array.c
midori/midori-browser.c midori/midori-browser.c
midori/midori-locationaction.c midori/midori-locationaction.c
midori/midori-locationentry.c
midori/midori-panel.c midori/midori-panel.c
midori/midori-websettings.c midori/midori-websettings.c
midori/midori-view.c midori/midori-view.c
@ -18,7 +17,6 @@ panels/midori-bookmarks.c
panels/midori-console.c panels/midori-console.c
panels/midori-extensions.c panels/midori-extensions.c
panels/midori-history.c panels/midori-history.c
panels/midori-plugins.c
panels/midori-transfers.c panels/midori-transfers.c
katze/katze-http-auth.c katze/katze-http-auth.c
katze/katze-throbber.c katze/katze-throbber.c
@ -32,7 +30,6 @@ extensions/colorful-tabs.c
extensions/cookie-manager/cookie-manager.c extensions/cookie-manager/cookie-manager.c
extensions/cookie-manager/cookie-manager-page.c extensions/cookie-manager/cookie-manager-page.c
extensions/cookie-manager/main.c extensions/cookie-manager/main.c
extensions/dnsprefetch.c
extensions/feed-panel/feed-atom.c extensions/feed-panel/feed-atom.c
extensions/feed-panel/feed-panel.c extensions/feed-panel/feed-panel.c
extensions/feed-panel/feed-parse.c extensions/feed-panel/feed-parse.c

2064
po/ca.po

File diff suppressed because it is too large Load diff

1802
po/cs.po

File diff suppressed because it is too large Load diff

1989
po/da.po

File diff suppressed because it is too large Load diff

1823
po/de.po

File diff suppressed because it is too large Load diff

2128
po/el.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

2076
po/fr.po

File diff suppressed because it is too large Load diff

2619
po/gl.po

File diff suppressed because it is too large Load diff

2631
po/it.po

File diff suppressed because it is too large Load diff

1861
po/ja.po

File diff suppressed because it is too large Load diff

2004
po/ko.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

3102
po/nl.po

File diff suppressed because it is too large Load diff

2083
po/pt.po

File diff suppressed because it is too large Load diff

1878
po/ro.po

File diff suppressed because it is too large Load diff

1992
po/ru.po

File diff suppressed because it is too large Load diff

2380
po/sk.po

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more