Imported Upstream version 0.4.3+dfsg

This commit is contained in:
Ryan Niebur 2013-10-23 20:26:27 -07:00
parent fd240475ed
commit 405f565df8
230 changed files with 59174 additions and 63293 deletions

2
.gitignore vendored
View File

@ -2,7 +2,7 @@ Makefile
.waf-*
.lock-wscript
_build
_build_
po/.intltool-merge-cache
po/LINGUAS

129
ChangeLog
View File

@ -1,134 +1,5 @@
This file is licensed under the terms of the expat license, see the file EXPAT.
v0.4.7:
Unify download behavior: link fingerprints, space check, clearing, tooltips
GIO-based check for enough space and permissions, GIO-based themed icons
Show opener/ tab domain in download dialog:
http://lcamtuf.coredump.cx/fldl/ http://lcamtuf.coredump.cx/switch/
Extension to download with a specific command line
Size in download dialog and fallback filename heuristic
Windows: GTK+3, Faenza icons, gdb helper, Netscape plugins,
ship CA bundle, fix View source, --portable/ -P on Windows
Granite (Beta): about dialog, static notebook, no "New Tab" in toolbar, Print → Share
Support building with Wayland-enabled GTK+3
Theming: content view, secondary toolbar class, drop old icon names, bigger error icon
Introduce --plain mode equivalent to GtkLauncher, lazy URLs for --snapshot/ -s
Log bookmarks, history and downloads to zeitgeist
Show security details and export certificates with GCR, error out instead of colored urlbar
Only allow data: URLs in urlbar for images
Recognize and cache HSTS, system-wide /etc/xdg/midori/hsts
Strip HTTP Host to outsmart some filter proxies
Completion: Fix PageUp/Down, Shift+Tab and wrap: This is consistent with GTK+ (excluding Tab) and Firefox
Change Focus Current Tab to Ctrl+Alt+Home
Fix Shift+Space for scrolling upwards
Control+Alt+R: Readable mode
Handle access key in link hints
Drop speed dial keyboard access in favour of "." link hints
No Open, Bookmark bar, Customize toolbar, Inspect page in app menu; split panel menu
Use ellipsises instead of period thresomes
Hinted text in bookmarks, history and cookie manager
Ellipsize panels (except for Transfers)
Add icon to bookmark dialog and remove labels
Validate proxy server IP and render invalid URLs in GTK+3
Rename "Toplevel" folder to "Bookmarks"
Chrome identification option; "Automatic" user agent is Chrome-based
Search: Create engines from search forms, remove "icon" field
Copy Image s/Address// always copy both URL and data
Rework debugging by introducing MIDORI_DEBUG; about:paths
Adblock: Refresh filters based on file time and meta data, abp: links
Optionally save website including resources
Merged NextForward akin to StopReload
PanedAction, Viewable, SpeedDial, (most of) Settings, Paths in Vala
Improved database: requires sqlite 3.6.19 and 0.2.6 in import dialog
Confirm Caret Browsing before enabling it
Support for custom items in Statusbar Features (see FAQ)
Draggable favicon as URL or text, URL icon for URL entries
Remember if inspector was attached
Open tabs in the background by default
RTL support in special/ error pages
Fix progressbar text with GTK+3
Build fix: More robust GTK+2 version check
Ensure progress in urlbar and tab match
Zoom text and images by default
Don't mixup tokens starting with the same letters
Seemless running out of build folder
No speed dial in --app/ --private, fix layout with many tiles
Add X-GNOME-Fullname to .desktop and translate desktop shortcuts
Delayed Load extension
v0.4.6:
+ Fix crasher in geolocation infobar
+ Fix crasher in about:version on some systems
+ Fix crasher opening bookmarks from Unity global menu
+ Use WebKitFaviconDatabase as of WebKit 1.8.0
+ Use midori-prefixed temp folder in midori_view_save_source
+ Fix cancelling downloads with SteadyFlow or Aria2
+ Fix crash dialog instead of opening tab in a running window
+ Fix page icons in multi-frame sites (gmail, tumbler)
+ Distinguish Simplified and Traditional Chinese
+ Support go-jump-symbolic
+ Handle empty tabs due to download links with a target
+ Handle frame load interrupted in the unholy trinity
+ Fix libsoup version check and wrong SSL status in location
v0.4.5:
+ Work around black border around widgets on Win32
+ Whitelist direct/ re-directed navigation requests in adblock
+ Require Vala 0.14
+ Provide geolocation diagnostics in about:geolocation
+ List available about: URLs and app instance name in about:version
+ Replace illegal characters in download filenames
+ Tweak app options on Win32 and use ShellExecuteEx in sokoke_show_uri
+ Use sokoke_show_uri in midori_browser_download_status_cb
+ External Download manager Steadyflow and Aria2 (with cookies)
+ Ensure adblock config folder when blocking images
+ Use sqlite WAL mode for history if available
+ Allow relative -c/ --config path
+ Context menus on Back and Forward toolbar items
+ Always show the tabbar by default
+ Use ubuntu-bug if it exists
+ Show inline find while typing and statusbar text in overlay with GTK+ 3.2
+ Esc/ closing "downloads still active" should cancel, not continue
+ Optional Granite support for notebook and bookmark dialog as pop-over
+ Ctrl+j to toggle statusbar aka downloads
+ Show at most 3 search engines in completion
+ Don't replace existing onclick/ blur with autosuggest
+ Implement low_memory_profile for FreeBSD and Win32
+ Use var in internal javascript, to fix Google apps
+ Handle download requests in frames
v0.4.4:
+ Disable page cache with < 352 MB RAM
+ Display filename in download dialog
+ Fix box packing in GTK+3 (in most cases)
+ Enable experimental HTML5 fullscreen API
+ Harden IPv6 address recognition in location
+ Experimental site data policy support (see FAQ)
+ Close tabs by middle clicking close button
+ Merge cookies and other data in Clear Private Data
+ Improve KatzeArrayAction for Unity menuproxy compatibility
+ Use GDateTime for history to avoid broken C runtimes
+ Add Midori tag to DuckDuckGo default URI
+ Rewrite completion popup resizing
+ Streamline page icon loading stages and fallbacks
+ Disable clipboard work-around for WebKit >= 1.4.3
+ Re-word .desktop entry as an action
+ Display informative text in private browsing
+ Consistent clear icons in entries
+ Revised download filename generation
+ Add 'Open in Image Viewer' menu item
+ Formhistory 2.0 with GDOM support
+ Handle javascript: and mailto: links better
+ Handle = key in Ukrainian layout better
+ Fix bookmark export and deletion of bookmark folders
+ Speed dial shortcut re-reordering by DND
v0.4.3:
+ Implement about:widgets to test rendering
+ Fix resizing of inspector by applying a minimum size

23
INSTALL
View File

@ -37,7 +37,7 @@ Midori is now built with debugging symbols.
Make sure you have installed 'gdb', the GNU Debugger.
Run Midori as 'gdb _build/default/midori/midori'.
Run Midori as 'gdb _build_/default/midori/midori'.
Inside gdb, type 'run'.
@ -49,32 +49,27 @@ function names and line numbers.
If the problem is a warning and not a crash, try this:
'G_DEBUG=all gdb _build/default/midori/midori'
'G_DEBUG=all gdb _build_/default/midori/midori'
If you are interested in HTTP communication, try this:
'MIDORI_DEBUG=headers _build/default/midori/midori'
'MIDORI_SOUP_DEBUG=2 _build_/default/midori/midori'
Where 'headers' can be replaced with 'body' to get full message contents.
Where '2' can be a level between 0 and 3.
If you are interested in (non-) touchscreen behaviour, try this:
'MIDORI_TOUCHSCREEN=1 _build/default/midori/midori', or
'MIDORI_TOUCHSCREEN=1 _build_/default/midori/midori', or
'MIDORI_TOUCHSCREEN=0 _build/default/midori/midori'
'MIDORI_TOUCHSCREEN=0 _build_/default/midori/midori'
If you want to "dry run" without WebKitGTK+ rendering, try this:
'MIDORI_DEBUG=unarmed _build/default/midori/midori'
'MIDORI_UNARMED=1 _build_/default/midori/midori'
If you want to test bookmarks, you can enable database tracing:
To debug extensions you can specify the path:
'MIDORI_DEBUG=bookmarks _build/default/midori/midori'
To disable Netscape plugins, use MOZ_PLUGIN_PATH=/.
When running from the build folder, extensions will also be located
in the build folder (setting MIDORI_EXTENSION_PATH is no longer needed).
'export MIDORI_EXTENSION_PATH=_build_/default/extensions'
For further information a tutorial for gdb and
reading up on how you can install debugging

16
README
View File

@ -2,19 +2,19 @@ This file is licensed under the terms of the expat license, see the file EXPAT.
Midori is a lightweight web browser.
* Full integration with GTK+2 and GTK+3.
* Fast rendering with WebKit and HTML5 video with GStreamer.
* Full integration with GTK+2.
* Fast rendering with WebKit.
* Tabs, windows and session management.
* History completion and configurable Web Search.
* Flexibly configurable Web Search.
* User scripts and user styles support.
* Adblock Plus compatible, external download manager support.
* Straightforward bookmark management.
* Customizable interface, extensions written in C and Vala.
* Customizable and extensible interface.
* Extensions written in C.
Requirements: GLib 2.22, GTK+ 2.16, WebkitGTK+ 1.1.17, libXML2,
libsoup 2.27.90, sqlite 3.0, Vala 0.14
Requirements: GLib 2.22, GTK+ 2.10, WebkitGTK+ 1.1.17, libXML2,
libsoup 2.27.90, sqlite 3.0, Vala 0.10
Optional: GTK+ 3.0, Unique 0.9, libnotify, gcr
Optional: GTK+ 3.0, Unique 0.9, libnotify
For installation instructions read INSTALL.

2
configure vendored
View File

@ -130,7 +130,7 @@ clean:
distclean:
@$WAF distclean
@-rm -rf _build
@-rm -rf _build_
@-rm -f Makefile
check:

View File

@ -1,70 +0,0 @@
/*
about: page style template for Midori.
This file is licensed under the terms of the expat license, see the file EXPAT.
*/
body {
background-color: #eee;
margin: 0;
padding: 0;
}
#container {
background: #f6fff3;
min-width: 70%;
max-width: 70%;
margin: 2em auto 1em;
padding: 1em;
border: 0.2em solid #9acb7f;
-webkit-border-radius: 1em;
}
#icon {
float: left;
padding-left: 1%;
padding-top: 1%;
}
html[dir="rtl"] #icon {
float: right;
padding-right: 1%;
}
#main {
float: right;
width: 75%;
}
h1 {
font-size: 1.4em;
font-weight: bold;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#logo {
position: absolute; bottom: 15px;
z-index: -1;
}
html[dir="ltr"] #logo {
right: 15px;
}
html[dir="rtl"] #logo {
left: 15px;
}
button span,
button img {
vertical-align: middle;
padding: 2px 1px;
}
message {
font-size: 1.1em;
}
description {
font-size: 1em;
}

View File

@ -186,10 +186,10 @@ AutoSuggestControl.prototype.init = function () {
};
//assign onblur event handler (hides suggestions)
if (!this.textbox.onblur)
this.textbox.onblur = function () { oThis.hideSuggestions(); };
if (!this.textbox.onclick)
this.textbox.onclick = function () { oThis.hideSuggestions(); };
this.textbox.onblur =
this.textbox.onclick = function () {
oThis.hideSuggestions();
};
//create the suggestions dropdown
this.createDropDown();
@ -299,7 +299,7 @@ function initSuggestions () {
if (inputs.length == 0)
return false;
for (var i=0;i<inputs.length;i++)
for (i=0;i<inputs.length;i++)
{
var ename = inputs[i].getAttribute("name");
var eid = inputs[i].getAttribute("id");

View File

@ -2,11 +2,67 @@
Error page template for Midori.
This file is licensed under the terms of the expat license, see the file EXPAT.
-->
<html dir="{dir}">
<html>
<head>
<title>{title}</title>
<link rel="shortcut icon" href="{icon}" />
<link rel="stylesheet" type="text/css" href="res://about.css" />
<style type="text/css">
body {
background-color: #eee;
margin: 0;
padding: 0;
}
#container {
background: #f6fff3;
min-width: 70%;
max-width: 70%;
margin: 2em auto 1em;
padding: 1em;
border: 0.2em solid #9acb7f;
-webkit-border-radius: 1em;
}
icon {
float: left;
padding-left: 1%;
padding-top: 1%;
}
#main {
float: right;
width: 90%;
}
h1 {
font-size: 1.4em;
font-weight: bold;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#logo {
position: absolute; right: 15px; bottom: 15px;
z-index: -1;
}
button span,
button img {
vertical-align: middle;
padding: 2px 1px;
}
message {
font-size: 1.1em;
}
description {
font-size: 1em;
}
</style>
</head>
<body>
<div id="container">

View File

@ -8,64 +8,29 @@ Stylesheet for Midori's documentation based on a version of Enrico Troeger.
@media screen {
html, body {
width: 100% !important;
height: 100% !important;
margin: 0 !important;
padding: 0 !important;
body {
background-color: #f6fff3;
color: #404040;
margin-left: 0.4em;
width: 60em;
font-size: 90%;
}
* {
background: #f6fff3 !important;
color: #404040 !important;
font-size: 14pt !important;
font-family: serif !important;
text-align: justify !important;
line-height: 1.4em !important;
word-spacing: 0.4mm !important;
letter-spacing: 0.2mm !important;
-webkit-column-count: auto !important;
-webkit-column-width: auto !important;
-webkit-box-shadow: none !important;
width: auto !important;
word-wrap: break-word !important;
a {
color: #013100;
}
div, p {
padding: 5pt !important;
}
li {
padding-left: 5pt !important;
}
img, *[accesskey], form *, form, iframe,
*[id^=navigation], *[id$=navigation], *[id*=navigation], .collapsed, .expanded {
display: none !important
}
/* FIXME: we want "images bigger than 50px here" */
img[width] {
display: inline !important
}
:link, :link * {
color: #013100 !important;
text-decoration: underline !important;
}
:visited, :visited * {
color: #7E558E !important;
text-decoration: underline !important;
a:visited {
color: #7E558E;
}
a:hover {
text-decoration: none !important;
text-decoration: none;
}
h1, h2, h3 {
font-family: serif !important;
color: #002a00 !important;
font-family: sans-serif;
color: #002a00;
}
h1 {

View File

@ -7,7 +7,7 @@
<title>midori:faq</title>
<meta name="generator" content="DokuWiki"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="date" content="2012-09-18T16:25:52+0200"/>
<meta name="date" content="2011-11-08T02:51:30+0100"/>
<meta name="keywords" content="midori,faq"/>
<link rel="search" type="application/opensearchdescription+xml" href="/lib/exe/opensearch.php" title="Xfce Wiki"/>
<link rel="start" href="/"/>
@ -17,13 +17,11 @@
<link rel="alternate" type="text/html" title="Plain HTML" href="/_export/xhtml/midori/faq"/>
<link rel="alternate" type="text/plain" title="Wiki Markup" href="/_export/raw/midori/faq"/>
<link rel="canonical" href="http://wiki.xfce.org/midori/faq"/>
<link rel="stylesheet" href="faq.css" />
<link rel="stylesheet" href="faq.css" />
<link rel="stylesheet" href="faq.css" />
<link rel="stylesheet" type="text/css" href="faq.css" />
<script type="text/javascript"><!--//--><![CDATA[//><!--
var NS='midori';var JSINFO = {"id":"midori:faq","namespace":"midori"};
var NS='midori';var SIG=' --- //[[christian@twotoasts.de|Christian Dywan]] 2011/11/11 00:07//';var JSINFO = {"id":"midori:faq","namespace":"midori"};
//--><!]]></script>
<script type="text/javascript" charset="utf-8" src="/lib/exe/js.php?tseed=1334991875"></script>
<script type="text/javascript" charset="utf-8" src="/lib/exe/js.php?tseed=1316333533"></script>
</head>
<body>
<div class="dokuwiki export">
@ -34,35 +32,31 @@ var NS='midori';var JSINFO = {"id":"midori:faq","namespace":"midori"};
<ul class="toc">
<li class="level1"><div class="li"><span class="li"><a href="#midori_-_frequently_asked_questions" class="toc">Midori - Frequently asked questions</a></span></div></li>
<li class="level1"><div class="li"><span class="li"><a href="#getting_started" class="toc">Getting started</a></span></div></li>
<li class="level1"><div class="li"><span class="li"><a href="#common_problems" class="toc">Common problems</a></span></div>
<li class="level1"><div class="li"><span class="li"><a href="#getting_started" class="toc">Getting started</a></span></div>
<ul class="toc">
<li class="level2"><div class="li"><span class="li"><a href="#security_features" class="toc">Security features</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#flash_doesn_t_work" class="toc">Flash doesn&#039;t work</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#about_midori" class="toc">About Midori</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#common_problems" class="toc">Common problems</a></span></div></li>
</ul>
</li>
<li class="level1"><div class="li"><span class="li"><a href="#privacy" class="toc">Privacy</a></span></div>
<ul class="toc">
<li class="level2"><div class="li"><span class="li"><a href="#blacklist_cookies" class="toc">Blacklist cookies</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#adblock" class="toc">Adblock</a></span></div></li>
</ul>
</li>
<li class="level1"><div class="li"><span class="li"><a href="#modes" class="toc">Modes</a></span></div>
<li class="level1"><div class="li"><span class="li"><a href="#features" class="toc">Features</a></span></div>
<ul class="toc">
<li class="level2"><div class="li"><span class="li"><a href="#web_applications" class="toc">Web Applications</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#private_browsing" class="toc">Private Browsing</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#portable_modewin32" class="toc">Portable mode/ Win32</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#kiosk_mode" class="toc">Kiosk mode</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#proxy_servers" class="toc">Proxy servers</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#using_the_keyboard" class="toc">Using the Keyboard</a></span></div>
<ul class="toc">
<li class="level3"><div class="li"><span class="li"><a href="#hjkl" class="toc">HJKL</a></span></div></li>
<li class="level3"><div class="li"><span class="li"><a href="#following_links" class="toc">Following Links</a></span></div></li>
<li class="level3"><div class="li"><span class="li"><a href="#use_ctrl_shift_tab_to_switch_between_pages" class="toc">Use Ctrl(+Shift)+Tab to switch between pages</a></span></div></li>
<li class="level3"><div class="li"><span class="li"><a href="#customizing_keyboard_shortcuts" class="toc">Customizing keyboard shortcuts</a></span></div></li>
<li class="level3"><div class="li"><span class="li"><a href="#using_find" class="toc">Using Find</a></span></div></li>
</ul>
</li>
<li class="level1"><div class="li"><span class="li"><a href="#proxy_servers" class="toc">Proxy servers</a></span></div></li>
<li class="level1"><div class="li"><span class="li"><a href="#keyboard_hotkeys" class="toc">Keyboard Hotkeys</a></span></div></li>
<li class="level1"><div class="li"><span class="li"><a href="#mouse_gestures" class="toc">Mouse Gestures</a></span></div></li>
<li class="level1"><div class="li"><span class="li"><a href="#user_scripts_and_styles" class="toc">User scripts and styles</a></span></div>
<ul class="toc">
<li class="level2"><div class="li"><span class="li"><a href="#user_styles" class="toc">User styles</a></span></div></li>
</ul></li>
</ul>
<li class="level2"><div class="li"><span class="li"><a href="#mouse_gestures" class="toc">Mouse Gestures</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#spell_check" class="toc">Spell check</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#user_scripts" class="toc">User scripts</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#user_styles" class="toc">User styles</a></span></div></li></ul>
</li></ul>
</div>
</div>
<!-- TOC END -->
@ -82,10 +76,15 @@ This is a snapshot of Frequently Asked Questions designated for offline viewing.
<p/>
</div>
<!-- EDIT1 SECTION "Midori - Frequently asked questions" [1-289] -->
<h1 class="sectionedit2"><a name="getting_started" id="getting_started">Getting started</a></h1>
<div class="level1">
</div>
<!-- EDIT2 SECTION "Getting started" [290-319] -->
<h2 class="sectionedit3"><a name="about_midori" id="about_midori">About Midori</a></h2>
<div class="level2">
</div>
<h4><a name="what_is_midori_and_why_should_i_use_it" id="what_is_midori_and_why_should_i_use_it">What is &quot;Midori&quot; and why should I use it?</a></h4>
@ -132,9 +131,9 @@ Midori and all delivered artwork are licensed under the LGPL2.
</p>
</div>
<h1 class="sectionedit3"><a name="common_problems" id="common_problems">Common problems</a></h1>
<div class="level1">
<!-- EDIT3 SECTION "About Midori" [320-1212] -->
<h2 class="sectionedit4"><a name="common_problems" id="common_problems">Common problems</a></h2>
<div class="level2">
</div>
@ -194,12 +193,6 @@ Use a smaller toolbar:
</p>
<pre class="code">gtk-toolbar-icon-size = GTK_ICON_SIZE_SMALL_TOOLBAR</pre>
<p>
Only for those not running a complete DE like Xfce, Elementary, etc…<br/>
There is a preference: Preferences → Browsing → Toolbar Style: Small icons
</p>
<p>
Enable changing hotkeys while hovering menu items:
</p>
@ -216,80 +209,7 @@ There appears to be an issue with Glib 2.16. The recommended solution is to upgr
</div>
<h4><a name="how_can_i_change_the_cache_folder_to_tmpfs" id="how_can_i_change_the_cache_folder_to_tmpfs">How can I change the cache folder (to tmpfs)?</a></h4>
<div class="level4">
<p>
On Linux and BSD, you can set XDG_CACHE_HOME for all applications, or just Midori. Midori saves icons and cache files in that location. The default is ~/.cache.
</p>
<p>
export XDG_CACHE_HOME=/dev/shm
</p>
</div>
<h2 class="sectionedit4"><a name="security_features" id="security_features">Security features</a></h2>
<div class="level2">
</div>
<h4><a name="hstshttp_strict_transport_security" id="hstshttp_strict_transport_security">HSTS/ HTTP Strict Transport Security</a></h4>
<div class="level4">
<p>
Midori &gt;= 0.4.7 automatically picks up the Strict-Transport-Security header and caches sites locally. By design, there&#039;s no UI. System administrators can however place a pre-loaded cache at /etc/xdg/midori/hsts.
</p>
</div>
<h4><a name="certificate_handling" id="certificate_handling">Certificate Handling</a></h4>
<div class="level4">
<p>
Midori &gt;= 0.4.7 supports <a href="/midori/gcr" class="wikilink2" title="midori:gcr" rel="nofollow">http://git.gnome.org/browse/gcr/tree/gcr</a> for certificate display and management, you can click the lock in the urlbar to see detailed information. Earlier versions, or one without gcr will not handle certificates beyond the lock icon in the urlbar.
</p>
</div>
<h5><a name="error_granting_trustcouldn_t_find_a_place_to_store_the_imported_certificate" id="error_granting_trustcouldn_t_find_a_place_to_store_the_imported_certificate">Error granting trust: Couldn&#039;t find a place to store the imported certificate</a></h5>
<div class="level5">
<p>
No key store is available or it&#039;s incorrectly setup. By default GNOME keyring can do this. Under Xfce it is recommended to enable “GNOME services” under “Session and Startup settings”. Otherwise this can occur if a script doesn&#039;t correctly send the output of “gnome-keyring startup” to the environment.
</p>
</div>
<h5><a name="a_testcase_for_self-signed_certificates" id="a_testcase_for_self-signed_certificates">A testcase for self-signed certificates</a></h5>
<div class="level5">
<p>
<a href="https://selfsigned.notyours.dk:444/menu.gif" class="urlextern" title="https://selfsigned.notyours.dk:444/menu.gif" rel="nofollow">https://selfsigned.notyours.dk:444/menu.gif</a>
</p>
</div>
<h2 class="sectionedit5"><a name="flash_doesn_t_work" id="flash_doesn_t_work">Flash doesn&#039;t work</a></h2>
<div class="level2">
</div>
<h4><a name="windows_support" id="windows_support">Windows support</a></h4>
<div class="level4">
<p>
WebKitGTK+ and thusly Midori on Windows doesn&#039;t support Flash or any other plugins. If WebKitGTK+ adds the feature in the future, we will support it. For now there&#039;s nothing we can do.
</p>
<p>
Starting with WebkitGTK+ 1.8.2 (Midori 0.4.7) Netscape plugins are now supported.
Midori should pick them up from standard netscape plugins locations.
</p>
</div>
<h4><a name="netscape_plugins_on_linux_bsd_and_os_x" id="netscape_plugins_on_linux_bsd_and_os_x">Netscape plugins on Linux, BSD and OS X</a></h4>
<h4><a name="flashnetscape_plugins_don_t_work" id="flashnetscape_plugins_don_t_work">Flash/ Netscape plugins don&#039;t work</a></h4>
<div class="level4">
<p>
@ -307,17 +227,11 @@ You can either run that above line and run Midori in the same terminal afterward
</div>
<h4><a name="flash_is_crashingno_flash_with_gtk_3" id="flash_is_crashingno_flash_with_gtk_3">Flash is crashing/ No Flash with GTK+3</a></h4>
<h4><a name="flash_is_crashing_all_the_time" id="flash_is_crashing_all_the_time">Flash is crashing all the time</a></h4>
<div class="level4">
<p>
nspluginwrapper is a program that runs Flash and other Netscape plugins in a separate process. So a crash can&#039;t cresh the whole browser and Flash, which is GTK+2 can run in GTK+3.
</p>
<p>
sudo apt-get install nspluginwrapper
sudo nspluginwrapper -i /usr/lib/flashplugin-installer/libflashplayer.so
nspluginwrapper -v -a -n -i
Try searching for a package named nspluginwrapper or similar in your distribution repositories. It implements plugins in their own process so they can&#039;t drag down the whole browser.
</p>
</div>
@ -332,28 +246,13 @@ That&#039;s a problem with WebKit. You can work around it to some extent if you
</div>
<h4><a name="bit_encryption_isn_t_supported" id="bit_encryption_isn_t_supported">256-bit encryption isn&#039;t supported?</a></h4>
<div class="level4">
<p>
There&#039;s no official support right now. It&#039;s possible to <a href="https://opensource.conformal.com/fluxbb/viewtopic.php?pid=1332#p1332" class="urlextern" title="https://opensource.conformal.com/fluxbb/viewtopic.php?pid=1332#p1332" rel="nofollow">patch glib-networking to enable 256-bit SSL</a>.
</p>
</div>
<h4><a name="scroll_with_middle_mouse_buttonpan-scrolling" id="scroll_with_middle_mouse_buttonpan-scrolling">Scroll with middle mouse button/ pan-scrolling</a></h4>
<h4><a name="scroll_with_middle_mouse_button" id="scroll_with_middle_mouse_button">Scroll with middle mouse button</a></h4>
<div class="level4">
<p>
<a href="http://ubuntuforums.org/showthread.php?t=478418" class="urlextern" title="http://ubuntuforums.org/showthread.php?t=478418" rel="nofollow">http://ubuntuforums.org/showthread.php?t=478418</a>
</p>
<p>
Bug: <a href="https://bugs.launchpad.net/webkit/+bug/871425" class="urlextern" title="https://bugs.launchpad.net/webkit/+bug/871425" rel="nofollow">https://bugs.launchpad.net/webkit/+bug/871425</a><br/>
Upstream Bug: <a href="https://bugs.webkit.org/show_bug.cgi?id=50561" class="urlextern" title="https://bugs.webkit.org/show_bug.cgi?id=50561" rel="nofollow">https://bugs.webkit.org/show_bug.cgi?id=50561</a>
</p>
</div>
<h4><a name="html5_video_doesn_t_play" id="html5_video_doesn_t_play">HTML5 Video doesn&#039;t play</a></h4>
@ -367,6 +266,8 @@ You need to have GStreamer plugins installed which implement the codecs.
</li>
<li class="level1"><div class="li"> You may need gstreamer0.10-alsa for ALSA, depending on your distribution.</div>
</li>
<li class="level1"><div class="li"> With Arch Linux, you may need to install liboil explicitly if it is not installed already (see <a href="https://bugs.archlinux.org/task/20945" class="urlextern" title="https://bugs.archlinux.org/task/20945" rel="nofollow">this</a> bug report).</div>
</li>
<li class="level1"><div class="li"> You need plugins for Theora, gstreamer0.10-base and <acronym title="Moving Picture Experts Group">MPEG</acronym>-4 incluing aac (e.g. gst-plugins-faad), gstreamer0.10-bad. For WebM, you&#039;ll need plugins for vorbis (-base), matroska (-good), and vp8 (-bad). Have a look at <a href="http://www.gstreamer.net/documentation/plugins.html" class="urlextern" title="http://www.gstreamer.net/documentation/plugins.html" rel="nofollow">http://www.gstreamer.net/documentation/plugins.html</a> for details.</div>
</li>
<li class="level1"><div class="li"> For Youtube or Vimeo, you need WebKitGTK+ 1.1.20 or newer.</div>
@ -392,6 +293,36 @@ icedtea6 version 1.8 and above has been known to crash midori. If this is the c
</div>
<h4><a name="are_socks_proxy_servers_supported" id="are_socks_proxy_servers_supported">Are SOCKS proxy servers supported?</a></h4>
<div class="level4">
<p>
Currently only <acronym title="Hyper Text Transfer Protocol">HTTP</acronym> proxy servers are supported directly. A way to use SOCKS on Unix is to use tsocks with <acronym title="Secure Shell">SSH</acronym> as follows:
</p>
<ol>
<li class="level1"><div class="li"> Install &#039;tsocks&#039;</div>
</li>
<li class="level1"><div class="li"> Open /etc/tsocks.conf in an editor</div>
</li>
<li class="level1"><div class="li"> Type something like this, you can choose the port freely: <pre class="code">server = 127.0.0.1
server_type = 5
server_port = 5555</pre>
</div>
</li>
<li class="level1"><div class="li"> Open an <acronym title="Secure Shell">SSH</acronym> connection with the same port: <pre class="code"> ssh -D localhost:5555 myhost.com </pre>
</div>
</li>
<li class="level1"><div class="li"> Run Midori with “tsocks” in front of it: <pre class="code"> tsocks midori </pre>
</div>
</li>
<li class="level1"><div class="li"> Now you can use for example <a href="http://www.whatsmyip.org/" class="urlextern" title="http://www.whatsmyip.org/" rel="nofollow">http://www.whatsmyip.org/</a> to verify that you are using a SOCKS connection. The IP address should match the one of your <acronym title="Secure Shell">SSH</acronym> host. Remember to keep the <acronym title="Secure Shell">SSH</acronym> login running, and don&#039;t suspend it, otherwise it won&#039;t work.</div>
</li>
<li class="level1"><div class="li"> If the connection fails for some reason, you should see a connection error.</div>
</li>
</ol>
</div>
<h4><a name="how_do_i_get_rid_of_the_menubar" id="how_do_i_get_rid_of_the_menubar">How do I get rid of the menubar?</a></h4>
<div class="level4">
@ -500,138 +431,25 @@ As of git 2011-03-05 02:40:00 UTC and Midori 0.3.3 you can
<p>
Add a line to ~/.local/share/applications/mimeapps.list:
</p>
<pre class="code">x-scheme-handler/magnet=transmission-gtk.desktop</pre>
<pre class="code"> x-scheme-handler/magnet=transmission-gtk.desktop</pre>
<p>
Or install an application which advertises the scheme like so:
</p>
<pre class="code">MimeType=x-scheme-handler/magnet;</pre>
<pre class="code"> MimeType=x-scheme-handler/magnet;</pre>
<p>
Note that incomplete .desktop files will silently fail and it will look as if it doesn&#039;t exist.
</p>
</div>
<h4><a name="spell_check" id="spell_check">Spell check</a></h4>
<div class="level4">
<p>
First enable spell checking:
Edit→Preferences→Behavior and check “Enable Spell Checking”.
</p>
<p>
Now while typing any errors should get underlined in red. To get suggestions, highlight the word and right-click. You should see a list of suggestions at the top of the menu.
</p>
<p>
On Windows <a href="http://download.services.openoffice.org/files/contrib/dictionaries/" class="urlextern" title="http://download.services.openoffice.org/files/contrib/dictionaries/" rel="nofollow">you need to download OpenOffice dictionaries</a>, find the zipped file(s) for your locale(s) and unpack the contents into share/myspell/dicts/ in your Midori installation. The folder should contain *.aff and *.dic files
</p>
</div>
<h4><a name="is_it_possible_to_disable_same_origin_policy_what_webkit_settings_not_in_the_preferences_can_i_change" id="is_it_possible_to_disable_same_origin_policy_what_webkit_settings_not_in_the_preferences_can_i_change">Is it possible to disable Same Origin Policy? What Webkit settings not in the preferences can I change?</a></h4>
<div class="level4">
<p>
You can change <a href="http://webkitgtk.org/reference/webkitgtk/stable/WebKitWebSettings.html" class="urlextern" title="http://webkitgtk.org/reference/webkitgtk/stable/WebKitWebSettings.html" rel="nofollow">all values of WebKitWebSettings</a> in the config file (~/.config/midori/config on unices, %APPDATA%\midori\config [please check :)] on Windows). For example, to disable Same Origin Policy for local files, add
</p>
<pre class="code">enable-universal-access-from-file-uris=true</pre>
<p>
to your config file.
</p>
</div>
<h4><a name="how_do_i_change_the_proxy_server_from_the_toolbar_or_statusbar" id="how_do_i_change_the_proxy_server_from_the_toolbar_or_statusbar">How do I change the proxy server from the toolbar or statusbar?</a></h4>
<div class="level4">
<ol>
<li class="level1"><div class="li"> Activate the Statusbar Features plugin.</div>
</li>
<li class="level1"><div class="li"> Close Midori.</div>
</li>
<li class="level1"><div class="li"> Create a folder ~/.config/midori/extensions/libstatusbar-features.so/</div>
</li>
<li class="level1"><div class="li"> Create a text file “config”</div>
</li>
<li class="level1"><div class="li"> Type the following for the default setup:</div>
</li>
</ol>
<pre class="code"> [settings]
items=auto-load-images;enable-scripts;enable-plugins;identify-as;zoom-level</pre>
<p>
Add button types separated by semicolon:
</p>
<ul>
<li class="level1"><div class="li"> proxy-type Proxy Server</div>
</li>
<li class="level1"><div class="li"> preferred-encoding Character Set/ Encoding</div>
</li>
<li class="level1"><div class="li"> enable-spell-checking Spell Check</div>
</li>
<li class="level1"><div class="li"> zoom-text-and-images Only zoom in text, or text and images</div>
</li>
<li class="level1"><div class="li"> first-party-cookies-only First party cookies only</div>
</li>
<li class="level1"><div class="li"> site-data-rules see <a href="#blacklist_cookies" title="midori:faq &crarr;" class="wikilink1">Blacklisting cookies</a></div>
</li>
</ul>
<p>
Most settings listed at <a href="http://webkitgtk.org/reference/webkitgtk/stable/WebKitWebSettings.html" class="urlextern" title="http://webkitgtk.org/reference/webkitgtk/stable/WebKitWebSettings.html" rel="nofollow">http://webkitgtk.org/reference/webkitgtk/stable/WebKitWebSettings.html</a> will also work as button types.
</p>
</div>
<h1 class="sectionedit6"><a name="privacy" id="privacy">Privacy</a></h1>
<!-- EDIT4 SECTION "Common problems" [1213-8946] -->
<h1 class="sectionedit5"><a name="features" id="features">Features</a></h1>
<div class="level1">
</div>
<h2 class="sectionedit7"><a name="blacklist_cookies" id="blacklist_cookies">Blacklist cookies</a></h2>
<div class="level2">
<p>
As of Midori 0.4.4 you can add a hidden option to ~/.config/midori/config like so:
</p>
<pre class="code">site-data-rules=-google.com,-facebook.com,!bugzilla.gnome.org,+bugs.launchpad.net</pre>
<ol>
<li class="level1"><div class="li"> Values prefixed with ”-” are always blocked</div>
</li>
<li class="level1"><div class="li"> Values prefixed with ”+” are always accepted</div>
</li>
<li class="level1"><div class="li"> Values prefixed with ”!” are not cleared in Clear Private Data</div>
</li>
<li class="level1"><div class="li"> No wildcards.</div>
</li>
<li class="level1"><div class="li"> LSO, local storage and application caches ignore all policies.</div>
</li>
</ol>
<p>
The feature is currently experimental and will change in future versions.
</p>
</div>
<h2 class="sectionedit8"><a name="adblock" id="adblock">Adblock</a></h2>
<div class="level2">
<p>
The Advertisement Blocker can be activated under Extensions. It uses the same lists as Adblock Plus. URLs are blocked completely and never loaded. Lists can be added through the option button on the right side in the extension list.
</p>
</div>
<h1 class="sectionedit9"><a name="modes" id="modes">Modes</a></h1>
<div class="level1">
</div>
<h2 class="sectionedit10"><a name="web_applications" id="web_applications">Web Applications</a></h2>
<!-- EDIT5 SECTION "Features" [8947-8969] -->
<h2 class="sectionedit6"><a name="web_applications" id="web_applications">Web Applications</a></h2>
<div class="level2">
<p>
@ -651,13 +469,13 @@ There are two closely related features to open websites as dedicated windows of
</p>
</div>
<h2 class="sectionedit11"><a name="private_browsing" id="private_browsing">Private Browsing</a></h2>
<!-- EDIT6 SECTION "Web Applications" [8970-9486] -->
<h2 class="sectionedit7"><a name="private_browsing" id="private_browsing">Private Browsing</a></h2>
<div class="level2">
<p>
File menu/ App Menu button → Private Browsing
</p>
<ol>
<li class="level1"><div class="li"> File menu/ App Menu button → Private Browsing</div>
</li>
</ol>
<p>
A private window is a separate process, so crashes don&#039;t affect the normal browser session. No sensitive data such as cookies, history or bookmarks are stored. No extensions are loaded. Panels are not available.
@ -677,51 +495,10 @@ The same options available to -a/ app can be used for private browsing mode.
</p>
</div>
<h2 class="sectionedit12"><a name="portable_modewin32" id="portable_modewin32">Portable mode/ Win32</a></h2>
<!-- EDIT7 SECTION "Private Browsing" [9487-10410] -->
<h2 class="sectionedit8"><a name="proxy_servers" id="proxy_servers">Proxy servers</a></h2>
<div class="level2">
<p>
On Windows builds, -P/ portable causes all data to be written to the “profile” folder in the Midori folder. Everything, including temporary files and cache, is stored in a sub-folder without touching the system. So Midori can be run eg. from a USB stick on different machines.
</p>
</div>
<h2 class="sectionedit13"><a name="kiosk_mode" id="kiosk_mode">Kiosk mode</a></h2>
<div class="level2">
<p>
There is no specific mode, instead you use several command line switches. A typical fullscreen setup with no toolbar that opens about:blank and resets the session after 2 minutes of inactivity for instance:
</p>
<pre class="code bash">midori <span class="re5">-i</span> <span class="nu0">120</span> <span class="re5">-e</span> Fullscreen <span class="re5">-e</span> Navigationbar <span class="re5">-a</span> about:blank</pre>
<p>
Available commands for -e can be listed with “midori help-execute”.
</p>
<p>
If needed, a customized profile can be created with “midori -c /path/to/folder”. Using the shortcut editor extension, keyboard shortcuts can be removed as needed. Afterwards just append ”-c /path/to/folder” to the kiosk mode command line.
</p>
<p>
To restrict pages that can be opened, you can use a regular expression. The expression is a blacklist. To block undesirable sites you can do something like:
</p>
<pre class="code bash"><span class="re5">-b</span> <span class="st_h">'youtube|youporn'</span></pre>
<p>
By negating the expression you can also whitelist pages.
</p>
<pre class="code bash"><span class="re5">-b</span> <span class="st_h">'^(?!.*?(gmail|mail\.google|accounts\.google)).*'</span></pre>
<p>
Any links outside end up in an error page. All images and other files won&#039;t be loaded.
</p>
</div>
<h1 class="sectionedit14"><a name="proxy_servers" id="proxy_servers">Proxy servers</a></h1>
<div class="level1">
<p>
By running a local proxy you can modify web content even before it has reached Midori. That allows you to do things similar to what user scripts and user styles provide and even others that neither is suitable for.
</p>
@ -768,48 +545,14 @@ Mousehole is a scriptable proxy server written in Ruby.
</p>
</div>
<h4><a name="are_socks_proxy_servers_supported" id="are_socks_proxy_servers_supported">Are SOCKS proxy servers supported?</a></h4>
<div class="level4">
<p>
The coming libSoup 2.40 will support SOCKS proxies, <a href="https://bugzilla.gnome.org/show_bug.cgi?id=553269" class="urlextern" title="https://bugzilla.gnome.org/show_bug.cgi?id=553269" rel="nofollow">see the relevant bug report</a>.
</p>
<p>
libSoup &lt; 2.40 only supports <acronym title="Hyper Text Transfer Protocol">HTTP</acronym> proxy servers directly. A way to use SOCKS on Unix is to use tsocks with <acronym title="Secure Shell">SSH</acronym> as follows:
</p>
<ol>
<li class="level1"><div class="li"> Install &#039;tsocks&#039;</div>
</li>
<li class="level1"><div class="li"> Open /etc/tsocks.conf in an editor</div>
</li>
<li class="level1"><div class="li"> Type something like this, you can choose the port freely: <pre class="code">server = 127.0.0.1
server_type = 5
server_port = 5555</pre>
</div>
</li>
<li class="level1"><div class="li"> Open an <acronym title="Secure Shell">SSH</acronym> connection with the same port: <pre class="code"> ssh -D localhost:5555 myhost.com </pre>
</div>
</li>
<li class="level1"><div class="li"> Run Midori with “tsocks” in front of it: <pre class="code"> tsocks midori </pre>
</div>
</li>
<li class="level1"><div class="li"> Now you can use for example <a href="http://www.whatsmyip.org/" class="urlextern" title="http://www.whatsmyip.org/" rel="nofollow">http://www.whatsmyip.org/</a> to verify that you are using a SOCKS connection. The IP address should match the one of your <acronym title="Secure Shell">SSH</acronym> host. Remember to keep the <acronym title="Secure Shell">SSH</acronym> login running, and don&#039;t suspend it, otherwise it won&#039;t work.</div>
</li>
<li class="level1"><div class="li"> If the connection fails for some reason, you should see a connection error.</div>
</li>
</ol>
<!-- EDIT8 SECTION "Proxy servers" [10411-11241] -->
<h2 class="sectionedit9"><a name="using_the_keyboard" id="using_the_keyboard">Using the Keyboard</a></h2>
<div class="level2">
</div>
<h1 class="sectionedit15"><a name="keyboard_hotkeys" id="keyboard_hotkeys">Keyboard Hotkeys</a></h1>
<div class="level1">
</div>
<h4><a name="hjkl" id="hjkl">HJKL</a></h4>
<div class="level4">
<!-- EDIT9 SECTION "Using the Keyboard" [11242-11273] -->
<h3 class="sectionedit10"><a name="hjkl" id="hjkl">HJKL</a></h3>
<div class="level3">
<p>
You can use the Vim-like key bindings [hjkl] to navigate a page. h=left j=down k=up l=right In a picture:
@ -823,12 +566,12 @@ You can also use the arrow keys to do the same.
</p>
</div>
<h4><a name="following_links" id="following_links">Following Links</a></h4>
<div class="level4">
<!-- EDIT10 SECTION "HJKL" [11274-11481] -->
<h3 class="sectionedit11"><a name="following_links" id="following_links">Following Links</a></h3>
<div class="level3">
<p>
To enable Hints in Midori, similar to vimperator in Firefox or xxxterm, press .
To enable Hints in Midori [similar to those vimperator provides in Firefox], press .
</p>
<p>
@ -836,9 +579,9 @@ With hints enabled, type the link number, and press Enter to open the link in th
</p>
</div>
<h4><a name="use_ctrl_shift_tab_to_switch_between_pages" id="use_ctrl_shift_tab_to_switch_between_pages">Use Ctrl(+Shift)+Tab to switch between pages</a></h4>
<div class="level4">
<!-- EDIT11 SECTION "Following Links" [11482-11813] -->
<h3 class="sectionedit12"><a name="use_ctrl_shift_tab_to_switch_between_pages" id="use_ctrl_shift_tab_to_switch_between_pages">Use Ctrl(+Shift)+Tab to switch between pages</a></h3>
<div class="level3">
<p>
Since Midori 0.3.5 Ctrl+Tab is supported by default.
@ -849,18 +592,18 @@ In older versions you can enable the History List extension under Tools → Exte
</p>
</div>
<h4><a name="customizing_keyboard_shortcuts" id="customizing_keyboard_shortcuts">Customizing keyboard shortcuts</a></h4>
<div class="level4">
<!-- EDIT12 SECTION "Use Ctrl(+Shift)+Tab to switch between pages" [11814-12012] -->
<h3 class="sectionedit13"><a name="customizing_keyboard_shortcuts" id="customizing_keyboard_shortcuts">Customizing keyboard shortcuts</a></h3>
<div class="level3">
<p>
Enable the Shortcuts extension Tools → Extensions. To edit a keybinding Tools → Customize Shortcuts…
</p>
</div>
<h4><a name="using_find" id="using_find">Using Find</a></h4>
<div class="level4">
<!-- EDIT13 SECTION "Customizing keyboard shortcuts" [12013-12162] -->
<h3 class="sectionedit14"><a name="using_find" id="using_find">Using Find</a></h3>
<div class="level3">
<p>
Default shortcuts for Find are:
@ -869,7 +612,7 @@ Default shortcuts for Find are:
<p>
Find: Ctrl+f ”/” and ”,”<br/>
FindNext: Ctrl+g and Enter<br/>
FindNext: Ctrl+g<br/>
FindPrevious: Shift+Ctrl+g<br/>
@ -884,9 +627,9 @@ When using Ctrl+f to bring up Find, use Ctrl+f again or ESC. When using ”/”
</p>
</div>
<h1 class="sectionedit16"><a name="mouse_gestures" id="mouse_gestures">Mouse Gestures</a></h1>
<div class="level1">
<!-- EDIT14 SECTION "Using Find" [12163-12579] -->
<h2 class="sectionedit15"><a name="mouse_gestures" id="mouse_gestures">Mouse Gestures</a></h2>
<div class="level2">
<p>
By default the right mouse button initiates gestures.
@ -914,9 +657,28 @@ Additionally, there are programs allowing mouse gestures system-wide, for exampl
</p>
</div>
<!-- EDIT15 SECTION "Mouse Gestures" [12580-13253] -->
<h2 class="sectionedit16"><a name="spell_check" id="spell_check">Spell check</a></h2>
<div class="level2">
<h1 class="sectionedit17"><a name="user_scripts_and_styles" id="user_scripts_and_styles">User scripts and styles</a></h1>
<div class="level1">
<p>
First enable spell checking:
Edit→Preferences→Behavior and check “Enable Spell Checking”.
</p>
<p>
Now while typing any errors should get underlined in red. To get suggestions, highlight the word and right-click. Should see a list of suggestions on the top of the menu.
</p>
</div>
<!-- EDIT16 SECTION "Spell check" [13254-13543] -->
<h2 class="sectionedit17"><a name="user_scripts" id="user_scripts">User scripts</a></h2>
<div class="level2">
</div>
<h4><a name="overview" id="overview">Overview</a></h4>
<div class="level4">
<p>
UserScripts are scripts applied on some, or on all web pages. They can modify pages locally to add or alter functionality. That includes fixing bugs in web pages. User scripts are also available in other browsers, in the form of <a href="http://www.greasespot.net" class="urlextern" title="http://www.greasespot.net" rel="nofollow">Mozilla&#039;s Greasemonkey</a> or <a href="http://www.opera.com/support/tutorials/userjs/" class="urlextern" title="http://www.opera.com/support/tutorials/userjs/" rel="nofollow">Opera&#039;s User JavaScript</a>.
@ -975,10 +737,15 @@ You can also use <a href="http://rightfootin.blogspot.com/2009/04/flashblock-wan
</p>
</div>
<!-- EDIT17 SECTION "User scripts" [13544-16104] -->
<h2 class="sectionedit18"><a name="user_styles" id="user_styles">User styles</a></h2>
<div class="level2">
</div>
<h4><a name="overview1" id="overview1">Overview</a></h4>
<div class="level4">
<p>
User styles are <acronym title="Cascading Style Sheets">CSS</acronym> Cascading Style sheets that are loaded locally and applied on top of web pages, similar to User scripts, in order to add or alter functionality and also fix bugs.
</p>
@ -1037,6 +804,6 @@ Customize as needed:
}</pre>
</div>
<!-- EDIT16 SECTION "User styles" [18560-] --></div>
<!-- EDIT18 SECTION "User styles" [16105-] --></div>
</body>
</html>

View File

@ -1,28 +0,0 @@
.notebook tab .button {
-GtkButton-default-border: 0;
-GtkButton-default-outside-border: 0;
-GtkButton-inner-border: 0;
-GtkWidget-focus-line-width: 0;
-GtkWidget-focus-padding: 0;
padding: 0;
}
GtkOverlay > * {
padding: 4px;
border-style: solid;
border-radius: 0 5px 0 0;
border-width: 1px 1px 0 0;
}
GtkOverlay MidoriFindbar {
border-radius: 0 0 0 5px;
border-width: 0 0 1px 1px; /* top right bottom left */
}
/* Kill grey backround on inactive buttons */
GtkDrawingArea,
GtkImage,
GtkImage:insensitive,
GtkImage:selected {
background-color: @transparent;
}

View File

@ -3,8 +3,7 @@ Version=1.0
Type=Application
_Name=Midori
_GenericName=Web Browser
_X-GNOME-Fullname=Midori Web Browser
_Comment=Browse the Web
_Comment=Lightweight web browser
_X-GNOME-Keywords=Internet;WWW;Explorer
_X-AppInstall-Keywords=Internet;WWW;Explorer
Categories=GTK;Network;WebBrowser;
@ -18,17 +17,17 @@ X-Osso-Service=midori
X-Ayatana-Desktop-Shortcuts=TabNew;WindowNew;Private
[TabNew Shortcut Group]
_Name=New Tab
Name=New _Tab
Exec=midori -e TabNew
TargetEnvironment=Unity
[WindowNew Shortcut Group]
_Name=New Window
Name=New _Window
Exec=midori -e WindowNew
TargetEnvironment=Unity
[Private Shortcut Group]
_Name=New Private Browsing Window
Name=New P_rivate Browsing Window
Exec=midori --private
TargetEnvironment=Unity

View File

@ -55,7 +55,10 @@
width: 85%;
height: 75%;
margin: auto;
-webkit-box-shadow: 0 2px 5px rgba(0,0,0,.3), 0 0 0px #fff inset;
-webkit-box-shadow: 0 4px 18px rgba(0,0,0,.3), 0 0 2px #fff inset;
background-image: -webkit-gradient(
linear, center top, center bottom,
from(#f6f6f6), to(#e3e3e3));
border: 1px solid #bcbcbc;
border-bottom-color: #a0a0a0;
position: relative;
@ -72,15 +75,9 @@
div.shortcut .preview.new .add {
display: block;
height: 100%;
width: 100%;
width: 50%;
margin: 0 auto;
cursor: pointer;
-webkit-box-shadow: 0 2px 5px rgba(0,0,0,.3), 0 0 0px #fff inset;
background-image: -webkit-gradient(
linear, center top, center bottom,
from(#f6f6f6), to(#e3e3e3));
background-repeat: repeat-x;
-webkit-border-radius: 3px;
}
.title {
@ -114,148 +111,95 @@
display:none;
}
.selected {
outline: 1px dotted black;
background-color: #eef;
div.osd {
top: 9px;
position: fixed;
width: 100%;
text-align: right;
}
div.osd span {
border: 1px solid #999;
background-color: #f5f5f5;
padding: 8px;
color: #999;
-webkit-border-bottom-left-radius: 10px;
visibility: hidden;
}
</style>
<script type="text/javascript">
function add_tile (ev) {
ev.preventDefault();
var getAction = function (id)
{
var s = document.getElementById(id).childNodes[0];
if (s.className == 'preview')
return true;
var url = prompt ("{enter_shortcut_address}", "http://");
if (!url)
return false;
if (!url) return false;
if (url.indexOf ("://") == -1)
url = "http://" + url;
var id = ev.target.parentNode.parentNode.id;
console.log ("speed_dial-save-add " + id + " " + url + " ");
return false;
}
function rename_tile (ev) {
var old_name = ev.target.textContent;
var renameShortcut = function (id)
{
var old_name = document.getElementById(id).childNodes[1].textContent;
var name = prompt ("{enter_shortcut_name}", old_name);
if (!name)
return;
if (!name) return;
var id = ev.target.parentNode.id;
console.log ("speed_dial-save-rename " + id + " " + name);
}
function delete_tile (ev) {
ev.preventDefault();
if (!confirm("{are_you_sure}"))
var clearShortcut = function (id)
{
if(!confirm("{are_you_sure}"))
return;
var id = ev.target.parentNode.parentNode.id;
console.log ("speed_dial-save-delete " + id);
}
var key_id = 's';
var key_timeout;
var firstNode, secondNode;
var cursor;
document.onkeypress = function ()
{
key_id = key_id + String.fromCharCode (event.which);
var get_dial_div = function (ele) {
var dial_div;
if (ele.nodeName == 'IMG')
dial_div = ele.parentNode.parentNode.parentNode;
if (ele.className == 'title')
dial_div = ele.parentNode;
if (ele.className.indexOf ('shortcut') != -1)
dial_div = ele;
return dial_div;
}
clearTimeout (key_timeout);
function click (ev) {
if (ev == undefined)
return;
document.getElementById('dialing').innerText = key_id.substr(1);
document.getElementById('dialing').style.visibility = 'visible';
ev.preventDefault();
var ele = ev.target;
cursor = ele.style.cursor;
ele.style.cursor = 'move';
var eparent = get_dial_div (ele);
if (eparent != undefined) {
eparent.className = 'shortcut selected';
firstNode = eparent.id;
}
};
function up (ev) {
if (ev == undefined)
return;
ev.preventDefault();
ele = ev.target;
var eparent = get_dial_div (ele);
ele.style.cursor = cursor;
secondNode = eparent.id;
/* ommit just mere clicking the dial */
if (firstNode != secondNode && firstNode != undefined)
swap();
};
function over (ev) {
if (ev == undefined)
return;
ev.preventDefault();
var ele = ev.target;
var eparent = get_dial_div (ele);
var dial = document.getElementsByClassName("shortcut");
if (firstNode != undefined)
var div = document.getElementById(key_id);
if (div)
{
eparent.className = 'shortcut selected';
for (var i = 0; i < dial.length; i++) {
if (eparent.id != firstNode.id && dial[i].id != eparent.id) {
dial[i].className = 'shortcut';
}
if (key_id.substr(1) > 9)
{
if (getAction (key_id))
document.location = div.childNodes[0].childNodes[1].href;
key_id = 's';
}
else
key_timeout = setTimeout ('if (getAction (key_id)) document.location = document.getElementById(key_id).childNodes[0].childNodes[1].href; key_id = \'s\'', 1000);
}
ele.style.cursor = cursor;
else
key_id = 's';
if (key_id.length <= 1)
document.getElementById('dialing').style.visibility = 'hidden';
return false;
}
function swap () {
console.log ("speed_dial-save-swap " + firstNode + " " + secondNode);
};
function init () {
var new_tile = document.getElementsByClassName ("preview new");
new_tile[0].addEventListener ('click', add_tile, false);
var titles = document.getElementsByClassName ("title");
var len = titles.length;
for (var i = 0; i < len; i++) {
if (titles[i].parentNode.childNodes[0].className != "preview new")
titles[i].addEventListener ('click', rename_tile, false);
}
var crosses = document.getElementsByClassName ("cross");
var len = crosses.length;
for (var i = 0; i < len; i++)
crosses[i].addEventListener ('click', delete_tile, false);
var occupied_tiles = document.getElementsByClassName ("shortcut");
var len = occupied_tiles.length;
for (var i = 0; i < len; i++) {
if (occupied_tiles[i].childNodes[0].className != "preview new") {
occupied_tiles[i].addEventListener('mousedown', click, false);
occupied_tiles[i].addEventListener('mouseover', over, false);
occupied_tiles[i].addEventListener('mouseup', up, false);
}
}
}
</script>
</head>
<body onload="init ();">
<body>
<div class="osd" >
<span id="dialing"></span>
</div>
<div id="content">

View File

@ -6,20 +6,18 @@ import pproc as subprocess
import os
import Utils
blddir = '_build' # recognized by ack
for module in ('midori', 'katze'):
try:
if not os.access (blddir, os.F_OK):
Utils.check_dir (blddir)
if not os.access (blddir + '/docs', os.F_OK):
Utils.check_dir (blddir + '/docs')
if not os.access (blddir + '/docs/api', os.F_OK):
Utils.check_dir (blddir + '/docs/api')
if not os.access ('_build_', os.F_OK):
Utils.check_dir ('_build_')
if not os.access ('_build_/docs', os.F_OK):
Utils.check_dir ('_build_/docs')
if not os.access ('_build_/docs/api', os.F_OK):
Utils.check_dir ('_build_/docs/api')
subprocess.call (['gtkdoc-scan', '--module=' + module,
'--source-dir=' + module, '--output-dir=' + blddir + '/docs/api/' + module,
'--source-dir=' + module, '--output-dir=_build_/docs/api/' + module,
'--rebuild-sections', '--rebuild-types'])
os.chdir (blddir + '/docs/api/' + module)
os.chdir ('_build_/docs/api/' + module)
subprocess.call (['gtkdoc-mktmpl', '--module=' + module,
'--output-dir=.' + module])
subprocess.call (['gtkdoc-mkdb', '--module=' + module,

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,6 @@
/* This extensions add support for user addons: userscripts and userstyles */
#include <midori/midori.h>
#include "midori-core.h"
#include <glib/gstdio.h>
#include "config.h"
@ -183,8 +182,8 @@ addons_install_response (GtkWidget* infobar,
if (!filename)
filename = g_path_get_basename (uri);
folder_path = g_build_path (G_DIR_SEPARATOR_S,
midori_paths_get_user_data_dir (), PACKAGE_NAME, folder, NULL);
folder_path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (),
PACKAGE_NAME, folder, NULL);
if (!g_file_test (folder_path, G_FILE_TEST_EXISTS))
katze_mkdir_with_parents (folder_path, 0700);
@ -294,13 +293,13 @@ addons_button_add_clicked_cb (GtkToolItem* toolitem,
if (addons->kind == ADDONS_USER_SCRIPTS)
{
addons_type = g_strdup ("userscripts");
path = g_build_path (G_DIR_SEPARATOR_S, midori_paths_get_user_data_dir (),
path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (),
PACKAGE_NAME, "scripts", NULL);
}
else if (addons->kind == ADDONS_USER_STYLES)
{
addons_type = g_strdup ("userstyles");
path = g_build_path (G_DIR_SEPARATOR_S, midori_paths_get_user_data_dir (),
path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (),
PACKAGE_NAME, "styles", NULL);
}
else
@ -337,13 +336,23 @@ addons_button_add_clicked_cb (GtkToolItem* toolitem,
if (!g_file_test (path, G_FILE_TEST_EXISTS))
katze_mkdir_with_parents (path, 0700);
#if !GTK_CHECK_VERSION (2, 14, 0)
files = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (dialog));
#else
files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (dialog));
#endif
while (files)
{
GFile* src_file;
GError* error = NULL;
#if !GTK_CHECK_VERSION (2, 14, 0)
src_file = g_file_new_for_path (files);
#else
src_file = files->data;
#endif
if (G_IS_FILE (src_file))
{
GFile* dest_file;
@ -482,7 +491,7 @@ addons_open_in_editor_clicked_cb (GtkWidget* toolitem,
g_object_get (settings, "text-editor", &text_editor, NULL);
if (text_editor && *text_editor)
sokoke_spawn_program (text_editor, TRUE, element->fullpath, TRUE);
sokoke_spawn_program (text_editor, element->fullpath);
else
{
gchar* element_uri = g_filename_to_uri (element->fullpath, NULL, NULL);
@ -513,13 +522,10 @@ addons_open_target_folder_clicked_cb (GtkWidget* toolitem,
folder = g_path_get_dirname (element->fullpath);
}
else
{
folder = g_build_path (G_DIR_SEPARATOR_S, midori_paths_get_user_data_dir (),
PACKAGE_NAME, addons->kind == ADDONS_USER_SCRIPTS
? "scripts" : "styles", NULL);
katze_mkdir_with_parents (folder, 0700);
}
folder = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (),
PACKAGE_NAME,
addons->kind == ADDONS_USER_SCRIPTS
? "scripts" : "styles", NULL);
folder_uri = g_filename_to_uri (folder, NULL, NULL);
g_free (folder);
@ -777,10 +783,11 @@ addons_treeview_render_text_cb (GtkTreeViewColumn* column,
gtk_tree_model_get (model, iter, 0, &element, -1);
g_object_set (renderer, "text", element->displayname,
"sensitive", element->enabled,
"ellipsize", PANGO_ELLIPSIZE_END,
NULL);
g_object_set (renderer, "text", element->displayname, NULL);
if (!element->enabled)
g_object_set (renderer, "sensitive", false, NULL);
else
g_object_set (renderer, "sensitive", true, NULL);
}
static void
@ -824,16 +831,19 @@ addons_get_directories (AddonsKind kind)
else
g_assert_not_reached ();
path = g_build_path (G_DIR_SEPARATOR_S, midori_paths_get_user_data_dir (),
path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (),
PACKAGE_NAME, folder_name, 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 ();
while (*datadirs)
{
path = g_build_path (G_DIR_SEPARATOR_S, *datadirs,
PACKAGE_NAME, folder_name, NULL);
if (g_slist_find (directories, path) == NULL)
if (g_slist_find (directories, path) == NULL && g_access (path, X_OK) == 0)
directories = g_slist_prepend (directories, path);
else
g_free (path);
@ -1325,9 +1335,8 @@ addons_init (Addons* addons)
G_CALLBACK (addons_cell_renderer_toggled_cb), addons);
gtk_tree_view_append_column (GTK_TREE_VIEW (addons->treeview), column);
column = gtk_tree_view_column_new ();
gtk_tree_view_column_set_expand (column, TRUE);
renderer_text = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer_text, TRUE);
gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
(GtkTreeCellDataFunc)addons_treeview_render_text_cb,
addons->treeview, NULL);
@ -1678,10 +1687,10 @@ addons_save_settings (MidoriApp* app,
config_dir = midori_extension_get_config_dir (extension);
config_file = g_build_filename (config_dir, "addons", NULL);
if (config_dir != NULL)
katze_mkdir_with_parents (config_dir, 0700);
katze_mkdir_with_parents (config_dir, 0700);
sokoke_key_file_save_to_file (keyfile, config_file, &error);
if (error && midori_extension_get_config_dir (extension) != NULL)
/* If the folder is /, this is a test run, thus no error */
if (error && !g_str_equal (config_dir, "/"))
{
g_warning (_("The configuration of the extension '%s' couldn't be saved: %s\n"),
_("User addons"), error->message);

View File

@ -48,10 +48,11 @@ colorful_tabs_view_notify_uri_cb (MidoriView* view,
if (!midori_uri_is_blank (midori_view_get_display_uri (view))
&& (hostname = midori_uri_parse_hostname (midori_view_get_display_uri (view), NULL))
&& midori_view_get_icon_uri (view) != NULL)
&& katze_object_get_enum (view, "load-status") == MIDORI_LOAD_FINISHED)
{
icon = midori_view_get_icon (view);
if (icon != NULL)
if (midori_view_get_icon_uri (view) != NULL)
{
GdkPixbuf* newpix;
guchar* pixels;

View File

@ -702,6 +702,7 @@ static gchar *cm_get_domain_description_text(const gchar *domain, gint cookie_co
}
#if GTK_CHECK_VERSION(2, 12, 0)
static gboolean cm_tree_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_mode,
GtkTooltip *tooltip, CookieManagerPage *cmp)
{
@ -730,6 +731,8 @@ static gboolean cm_tree_query_tooltip(GtkWidget *widget, gint x, gint y, gboolea
return FALSE;
}
#endif
static gboolean cm_filter_match(const gchar *haystack, const gchar *needle)
{
@ -809,20 +812,25 @@ static void cm_filter_entry_changed_cb(GtkEditable *editable, CookieManagerPage
if (priv->ignore_changed_filter)
return;
if (!g_object_get_data (G_OBJECT (editable), "sokoke_has_default"))
text = gtk_entry_get_text(GTK_ENTRY(editable));
else
text = NULL;
text = gtk_entry_get_text(GTK_ENTRY(editable));
cm_filter_tree(cmp, text);
cookie_manager_update_filter(priv->parent, text);
if (text && *text)
gtk_tree_view_collapse_all(GTK_TREE_VIEW(priv->treeview));
else
if (*text != '\0')
gtk_tree_view_expand_all(GTK_TREE_VIEW(priv->treeview));
else
gtk_tree_view_collapse_all(GTK_TREE_VIEW(priv->treeview));
}
static void cm_filter_entry_clear_icon_released_cb(GtkIconEntry *e, gint pos, gint btn, gpointer data)
{
if (pos == GTK_ICON_ENTRY_SECONDARY)
gtk_entry_set_text(GTK_ENTRY(e), "");
}
static void cm_tree_selection_changed_cb(GtkTreeSelection *selection, CookieManagerPage *cmp)
{
GList *rows;
@ -994,7 +1002,6 @@ static void cm_tree_render_text_cb(GtkTreeViewColumn *column, GtkCellRenderer *r
}
else
g_object_set(renderer, "text", name, NULL);
g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
g_free(name);
}
@ -1015,7 +1022,6 @@ static GtkWidget *cm_tree_prepare(CookieManagerPage *cmp)
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(
_("Name"), renderer, "text", COOKIE_MANAGER_COL_NAME, NULL);
gtk_tree_view_column_set_expand (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_resizable(column, TRUE);
@ -1039,8 +1045,10 @@ static GtkWidget *cm_tree_prepare(CookieManagerPage *cmp)
g_signal_connect(treeview, "popup-menu", G_CALLBACK(cm_tree_popup_menu_cb), cmp);
/* tooltips */
#if GTK_CHECK_VERSION(2, 12, 0)
gtk_widget_set_has_tooltip(treeview, TRUE);
g_signal_connect(treeview, "query-tooltip", G_CALLBACK(cm_tree_query_tooltip), cmp);
#endif
/* drag'n'drop */
gtk_tree_view_enable_model_drag_source(
@ -1092,6 +1100,7 @@ static void cookie_manager_page_init(CookieManagerPage *self)
GtkWidget *desc_swin;
GtkWidget *paned;
GtkWidget *filter_hbox;
GtkWidget *filter_label;
GtkWidget *treeview;
CookieManagerPagePrivate *priv;
@ -1123,15 +1132,29 @@ static void cookie_manager_page_init(CookieManagerPage *self)
tree_swin = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(tree_swin),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(tree_swin), GTK_SHADOW_IN);
gtk_container_add(GTK_CONTAINER(tree_swin), treeview);
gtk_widget_show(tree_swin);
priv->filter_entry = sokoke_search_entry_new (_("Search Cookies by Name or Domain"));
filter_label = gtk_label_new(_("Filter:"));
gtk_widget_show(filter_label);
priv->filter_entry = gtk_icon_entry_new();
gtk_widget_set_tooltip_text(priv->filter_entry,
_("Enter a filter string to show only cookies whose name or domain "
"field match the entered filter"));
gtk_widget_show(priv->filter_entry);
gtk_icon_entry_set_icon_from_stock(GTK_ICON_ENTRY(priv->filter_entry),
GTK_ICON_ENTRY_SECONDARY, GTK_STOCK_CLEAR);
gtk_icon_entry_set_icon_highlight(GTK_ICON_ENTRY (priv->filter_entry),
GTK_ICON_ENTRY_SECONDARY, TRUE);
g_signal_connect(priv->filter_entry, "icon-release",
G_CALLBACK(cm_filter_entry_clear_icon_released_cb), NULL);
g_signal_connect(priv->filter_entry, "changed", G_CALLBACK(cm_filter_entry_changed_cb), self);
g_signal_connect(priv->filter_entry, "activate", G_CALLBACK(cm_filter_entry_changed_cb), self);
filter_hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(filter_hbox), filter_label, FALSE, FALSE, 3);
gtk_box_pack_start(GTK_BOX(filter_hbox), priv->filter_entry, TRUE, TRUE, 3);
gtk_widget_show(filter_hbox);

View File

@ -1,231 +0,0 @@
/*
Copyright (C) 2012 André Stösel <andre@stoesel.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.
*/
using Gtk;
using Katze;
using Midori;
namespace DelayedLoad {
private class PreferencesDialog : Dialog {
protected Manager dl_manager;
protected Scale slider;
public PreferencesDialog (Manager manager) {
this.dl_manager = manager;
this.title = _("Preferences for %s").printf ( _("Delayed load"));
if (this.get_class ().find_property ("has-separator") != null)
this.set ("has-separator", false);
this.border_width = 5;
this.set_modal (true);
this.set_default_size (350, 100);
this.create_widgets ();
this.response.connect (response_cb);
}
private void response_cb (Dialog source, int response_id) {
switch (response_id) {
case ResponseType.APPLY:
this.dl_manager.set_integer ("delay", (int) (this.slider.get_value () * 1000));
this.dl_manager.preferences_changed ();
this.destroy ();
break;
case ResponseType.CANCEL:
this.destroy ();
break;
}
}
private void create_widgets () {
Label text = new Label (_("Delay in seconds until loading the page:"));
#if HAVE_GTK3
this.slider = new Scale.with_range (Orientation.HORIZONTAL, 0, 15, 0.1);
#else
this.slider = new HScale.with_range (0, 15, 0.1);
#endif
int delay = this.dl_manager.get_integer ("delay");
if (delay > 0)
this.slider.set_value ((float)delay / 1000);
#if HAVE_GTK3
Gtk.Box vbox = get_content_area () as Gtk.Box;
vbox.pack_start (text, false, false, 0);
vbox.pack_start (this.slider, false, true, 0);
#else
this.vbox.pack_start (text, false, false, 0);
this.vbox.pack_start (this.slider, false, true, 0);
#endif
this.add_button (Gtk.STOCK_CANCEL, ResponseType.CANCEL);
this.add_button (Gtk.STOCK_APPLY, ResponseType.APPLY);
this.show_all ();
}
}
private class TabShaker : GLib.Object {
public unowned Midori.Browser browser;
public GLib.PtrArray tasks;
public bool reload_tab () {
if (tasks.len == 1) {
Midori.View? view = browser.tab as Midori.View;
Midori.View scheduled_view = tasks.index (0) as Midori.View;
if (scheduled_view == view) {
Katze.Item item = view.get_proxy_item ();
item.ref();
int64 delay = item.get_meta_integer ("delay");
if (delay == -2) {
view.reload (true);
}
}
}
tasks.remove_index (0);
return false;
}
public TabShaker (Midori.Browser browser) {
this.browser = browser;
}
construct {
this.tasks = new GLib.PtrArray ();
}
}
private class Manager : Midori.Extension {
private int timeout = 0;
private bool timeout_handler = false;
private HashTable<Midori.Browser, TabShaker> tasks;
public signal void preferences_changed ();
private void preferences_changed_cb () {
this.timeout = get_integer ("delay");
}
private void show_preferences () {
PreferencesDialog dialog = new PreferencesDialog (this);
dialog.show ();
}
private void schedule_reload (Midori.Browser browser, Midori.View view) {
if (this.timeout == 0)
view.reload (true);
else {
unowned TabShaker shaker = tasks.get (browser);
if (shaker != null) {
shaker.tasks.add (view);
Timeout.add (this.timeout, shaker.reload_tab);
}
}
}
private void tab_changed (Midori.View? old_view, Midori.View? new_view) {
if (new_view != null) {
Midori.App app = get_app ();
Midori.Browser browser = app.browser;
Katze.Item item = new_view.get_proxy_item ();
item.ref();
int64 delay = item.get_meta_integer ("delay");
if (delay == -2 && new_view.progress < 1.0) {
this.schedule_reload (browser, new_view);
}
}
}
private bool reload_first_tab () {
Midori.App app = get_app ();
Midori.Browser? browser = app.browser;
Midori.View? view = browser.tab as Midori.View;
if (view != null) {
Katze.Item item = view.get_proxy_item ();
item.ref();
int64 delay = item.get_meta_integer ("delay");
if (delay != 1) {
unowned WebKit.WebView web_view = view.get_web_view ();
WebKit.LoadStatus load_status = web_view.load_status;
if (load_status == WebKit.LoadStatus.FINISHED) {
if (this.timeout != 0)
this.tasks.set (browser, new TabShaker (browser));
if (view.progress < 1.0)
this.schedule_reload (browser, view);
return false;
}
}
}
return true;
}
private void browser_added (Midori.Browser browser) {
browser.switch_tab.connect_after (this.tab_changed);
}
private void browser_removed (Midori.Browser browser) {
browser.switch_tab.disconnect (this.tab_changed);
}
public void activated (Midori.App app) {
/* FIXME: override behavior without changing the preference */
app.settings.load_on_startup = MidoriStartup.DELAYED_PAGES;
this.preferences_changed ();
Midori.Browser? focused_browser = app.browser;
if (focused_browser == null)
Timeout.add (50, this.reload_first_tab);
foreach (Midori.Browser browser in app.get_browsers ()) {
browser_added (browser);
}
app.add_browser.connect (browser_added);
}
public void deactivated () {
Midori.App app = get_app ();
foreach (Midori.Browser browser in app.get_browsers ()) {
browser_removed (browser);
}
app.add_browser.disconnect (browser_added);
}
internal Manager () {
GLib.Object (name: _("Delayed load"),
description: _("Delay page load until you actually use the tab."),
version: "0.1",
authors: "André Stösel <andre@stoesel.de>");
install_integer ("delay", 0);
activate.connect (this.activated);
deactivate.connect (this.deactivated);
open_preferences.connect (show_preferences);
preferences_changed.connect (preferences_changed_cb);
this.tasks = new HashTable<Midori.Browser, TabShaker> (GLib.direct_hash, GLib.direct_equal);
}
}
}
public Midori.Extension extension_init () {
return new DelayedLoad.Manager ();
}

View File

@ -1,314 +0,0 @@
/*
Copyright (C) 2012 André Stösel <andre@stoesel.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.
*/
using Gtk;
using Soup;
using Katze;
using Midori;
using WebKit;
namespace EDM {
[DBus (name = "net.launchpad.steadyflow.App")]
interface SteadyflowInterface : GLib.Object {
public abstract void AddFile (string url) throws IOError;
}
private class DownloadRequest : GLib.Object {
public string uri;
public string auth;
public string referer;
public string? cookie_header;
}
internal Manager manager;
private class Manager : GLib.Object {
private CookieJar cookie_jar;
private GLib.PtrArray download_managers = new GLib.PtrArray ();
public bool download_requested (Midori.View view, WebKit.Download download) {
Midori.DownloadType download_type = download.get_data<Midori.DownloadType> ("midori-download-type");
if (download_type == Midori.DownloadType.SAVE) {
var dlReq = new DownloadRequest ();
dlReq.uri = download.get_uri ();
var request = download.get_network_request ();
var message = request.get_message ();
weak MessageHeaders headers = message.request_headers;
dlReq.auth = headers.get ("Authorization");
dlReq.referer = headers.get ("Referer");
dlReq.cookie_header = this.cookie_jar.get_cookies (new Soup.URI (dlReq.uri), true);
for (var i = 0 ; i < download_managers.len; i++) {
var dm = download_managers.index (i) as ExternalDownloadManager;
if (dm.download (dlReq))
return true;
}
}
return false;
}
public void tab_added (Midori.Browser browser, Midori.View view) {
view.download_requested.connect (download_requested);
}
public void tab_removed (Midori.Browser browser, Midori.View view) {
view.download_requested.disconnect(download_requested);
}
public void browser_added (Midori.Browser browser) {
foreach (var tab in browser.get_tabs ())
tab_added (browser, tab);
browser.add_tab.connect (tab_added);
browser.remove_tab.connect (tab_removed);
}
public void browser_removed (Midori.Browser browser) {
foreach (var tab in browser.get_tabs ())
tab_removed (browser, tab);
browser.add_tab.disconnect (tab_added);
browser.remove_tab.disconnect (tab_removed);
}
public void activated (Midori.Extension extension, Midori.App app) {
this.download_managers.add (extension);
if (this.download_managers.len == 1) {
foreach (var browser in app.get_browsers ())
browser_added (browser);
app.add_browser.connect (browser_added);
}
}
public void deactivated (Midori.Extension extension) {
this.download_managers.remove (extension);
if (this.download_managers.len == 0) {
var app = extension.get_app ();
foreach (var browser in app.get_browsers ())
browser_removed (browser);
app.add_browser.disconnect (browser_added);
}
}
construct {
var session = WebKit.get_default_session ();
this.cookie_jar = session.get_feature (typeof (CookieJar)) as CookieJar;
}
}
private abstract class ExternalDownloadManager : Midori.Extension {
public void activated (Midori.App app) {
manager.activated (this, app);
}
public void deactivated () {
manager.deactivated (this);
}
public void handle_exception (GLib.Error error) {
string ext_name;
this.get ("name",out ext_name);
var dialog = new MessageDialog (null, DialogFlags.MODAL,
MessageType.ERROR, ButtonsType.CLOSE,
_("An error occurred when attempting to download a file with the following plugin:\n" +
"%s\n\n" +
"Error:\n%s\n\n" +
"Carry on without this plugin."
),
ext_name, error.message);
dialog.response.connect ((a) => { dialog.destroy (); });
dialog.run ();
}
public abstract bool download (DownloadRequest dlReq);
}
private class Aria2 : ExternalDownloadManager {
public override bool download (DownloadRequest dlReq) {
var url = value_array_new ();
value_array_insert (url, 0, typeof (string), dlReq.uri);
GLib.HashTable<string, GLib.Value?> options = value_hash_new ();
var referer = new GLib.Value (typeof (string));
referer.set_string (dlReq.referer);
options.insert ("referer", referer);
var headers = value_array_new ();
if (dlReq.cookie_header != null) {
value_array_insert (headers, 0, typeof (string), "Cookie: %s".printf(dlReq.cookie_header));
}
if (headers.n_values > 0)
options.insert ("header", headers);
var message = XMLRPC.request_new ("http://127.0.0.1:6800/rpc",
"aria2.addUri",
typeof (ValueArray), url,
typeof(HashTable), options);
var session = new SessionSync ();
session.send_message (message);
try {
Value v;
XMLRPC.parse_method_response ((string) message.response_body.flatten ().data, -1, out v);
return true;
} catch (Error e) {
this.handle_exception (e);
}
return false;
}
internal Aria2 () {
GLib.Object (name: _("External Download Manager - Aria2"),
description: _("Download files with Aria2"),
version: "0.1" + Midori.VERSION_SUFFIX,
authors: "André Stösel <andre@stoesel.de>",
key: "aria2");
this.activate.connect (activated);
this.deactivate.connect (deactivated);
}
}
private class SteadyFlow : ExternalDownloadManager {
public override bool download (DownloadRequest dlReq) {
try {
SteadyflowInterface dm = Bus.get_proxy_sync (
BusType.SESSION,
"net.launchpad.steadyflow.App",
"/net/launchpad/steadyflow/app");
dm.AddFile (dlReq.uri);
return true;
} catch (Error e) {
this.handle_exception (e);
}
return false;
}
internal SteadyFlow () {
GLib.Object (name: _("External Download Manager - SteadyFlow"),
description: _("Download files with SteadyFlow"),
version: "0.1" + Midori.VERSION_SUFFIX,
authors: "André Stösel <andre@stoesel.de>",
key: "steadyflow");
this.activate.connect (activated);
this.deactivate.connect (deactivated);
}
}
private class CommandLinePreferences : Dialog {
protected Entry input;
protected CommandLine commandline;
public CommandLinePreferences(CommandLine cl) {
this.commandline = cl;
string ext_name;
this.get ("name",out ext_name);
this.title = _("Preferences for %s").printf (ext_name);
if (this.get_class ().find_property ("has-separator") != null)
this.set ("has-separator", false);
this.border_width = 5;
this.set_modal (true);
this.set_default_size (400, 100);
this.create_widgets ();
this.response.connect (response_cb);
}
private void response_cb (Dialog source, int response_id) {
switch (response_id) {
case ResponseType.APPLY:
this.commandline.set_string ("commandline", this.input.get_text ());
this.destroy ();
break;
case ResponseType.CANCEL:
this.destroy ();
break;
}
}
private void create_widgets () {
Label text = new Label (_("Command:"));
this.input = new Entry ();
this.input.set_text (this.commandline.get_string ("commandline"));
#if HAVE_GTK3
Gtk.Box vbox = get_content_area () as Gtk.Box;
vbox.pack_start (text, false, false, 0);
vbox.pack_start (this.input, false, true, 0);
#else
this.vbox.pack_start (text, false, false, 0);
this.vbox.pack_start (this.input, false, true, 0);
#endif
this.add_button (Gtk.STOCK_CANCEL, ResponseType.CANCEL);
this.add_button (Gtk.STOCK_APPLY, ResponseType.APPLY);
this.show_all ();
}
}
private class CommandLine : ExternalDownloadManager {
private void show_preferences () {
CommandLinePreferences dialog = new CommandLinePreferences (this);
dialog.show ();
}
public override bool download (DownloadRequest dlReq) {
try {
string cmd = this.get_string ("commandline");
cmd = cmd.replace("{REFERER}", GLib.Shell.quote (dlReq.referer));
if (dlReq.cookie_header != null) {
cmd = cmd.replace("{COOKIES}", GLib.Shell.quote ("Cookie: " + dlReq.cookie_header));
} else {
cmd = cmd.replace("{COOKIES}", "\'\'");
}
cmd = cmd.replace("{URL}", GLib.Shell.quote (dlReq.uri));
GLib.Process.spawn_command_line_async (cmd);
return true;
} catch (Error e) {
this.handle_exception (e);
}
return false;
}
internal CommandLine () {
GLib.Object (name: _("External Download Manager - CommandLine"),
description: _("Download files with a specified command"),
version: "0.1" + Midori.VERSION_SUFFIX,
authors: "André Stösel <andre@stoesel.de>",
key: "commandline");
this.install_string ("commandline", "wget --no-check-certificate --referer={REFERER} --header={COOKIES} {URL}");
this.activate.connect (activated);
this.deactivate.connect (deactivated);
this.open_preferences.connect (show_preferences);
}
}
}
public Katze.Array extension_init () {
EDM.manager = new EDM.Manager();
var extensions = new Katze.Array( typeof (Midori.Extension));
extensions.add_item (new EDM.Aria2 ());
extensions.add_item (new EDM.SteadyFlow ());
extensions.add_item (new EDM.CommandLine ());
return extensions;
}

View File

@ -840,8 +840,7 @@ feed_panel_init (FeedPanel* panel)
webview = webkit_web_view_new ();
#if GTK_CHECK_VERSION(3,0,0)
font_desc = (PangoFontDescription*)gtk_style_context_get_font (
gtk_widget_get_style_context (treeview), GTK_STATE_FLAG_NORMAL);
font_desc = gtk_style_context_get_font(gtk_widget_get_style_context(treeview), GTK_STATE_FLAG_NORMAL);
#else
font_desc = treeview->style->font_desc;
#endif

600
extensions/formhistory.c Normal file
View File

@ -0,0 +1,600 @@
/*
Copyright (C) 2009 Alexander Butenko <a.butenka@gmail.com>
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.
*/
#define MAXCHARS 60
#define MINCHARS 2
#include <midori/midori.h>
#include <glib/gstdio.h>
#include "config.h"
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
static GHashTable* global_keys;
static gchar* jsforms;
static void
formhistory_toggle_state_cb (GtkAction* action,
MidoriBrowser* browser);
static gboolean
formhistory_prepare_js ()
{
gchar* autosuggest;
gchar* style;
guint i;
gchar* file;
file = sokoke_find_data_filename ("autosuggestcontrol.js", TRUE);
if (!g_file_get_contents (file, &autosuggest, NULL, NULL))
{
g_free (file);
return FALSE;
}
g_strchomp (autosuggest);
katze_assign (file, sokoke_find_data_filename ("autosuggestcontrol.css", TRUE));
if (!g_file_get_contents (file, &style, NULL, NULL))
{
g_free (file);
return FALSE;
}
g_strchomp (style);
i = 0;
while (style[i])
{
if (style[i] == '\n')
style[i] = ' ';
i++;
}
jsforms = g_strdup_printf (
"%s"
"window.addEventListener ('DOMContentLoaded',"
"function () {"
" if (document.getElementById('formhistory'))"
" return;"
" if (!initSuggestions ())"
" return;"
" var mystyle = document.createElement('style');"
" mystyle.setAttribute('type', 'text/css');"
" mystyle.setAttribute('id', 'formhistory');"
" mystyle.appendChild(document.createTextNode('%s'));"
" var head = document.getElementsByTagName('head')[0];"
" if (head) head.appendChild(mystyle);"
"}, true);",
autosuggest,
style);
g_strstrip (jsforms);
g_free (file);
g_free (style);
g_free (autosuggest);
return TRUE;
}
static gchar*
formhistory_fixup_value (char* value)
{
guint i = 0;
g_strchomp (value);
while (value[i])
{
if (value[i] == '\n')
value[i] = ' ';
else if (value[i] == '"')
value[i] = '\'';
i++;
}
return value;
}
static gchar*
formhistory_build_js ()
{
GString* suggestions;
GHashTableIter iter;
gpointer key, value;
suggestions = g_string_new (
"function FormSuggestions(eid) { "
"arr = new Array();");
g_hash_table_iter_init (&iter, global_keys);
while (g_hash_table_iter_next (&iter, &key, &value))
{
g_string_append_printf (suggestions, " arr[\"%s\"] = [%s]; ",
(gchar*)key, (gchar*)value);
}
g_string_append (suggestions, "this.suggestions = arr[eid]; }");
g_string_append (suggestions, jsforms);
return g_string_free (suggestions, FALSE);
}
static void
formhistory_update_database (gpointer db,
const gchar* key,
const gchar* value)
{
gchar* sqlcmd;
gchar* errmsg;
gint success;
sqlcmd = sqlite3_mprintf ("INSERT INTO forms VALUES"
"('%q', '%q', '%q')",
NULL, key, value);
success = sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg);
sqlite3_free (sqlcmd);
if (success != SQLITE_OK)
{
g_printerr (_("Failed to add form value: %s\n"), errmsg);
g_free (errmsg);
return;
}
}
static gboolean
formhistory_update_main_hash (gchar* key,
gchar* value)
{
guint length;
gchar* tmp;
if (!(value && *value))
return FALSE;
length = strlen (value);
if (length > MAXCHARS || length < MINCHARS)
return FALSE;
formhistory_fixup_value (key);
formhistory_fixup_value (value);
if ((tmp = g_hash_table_lookup (global_keys, (gpointer)key)))
{
gchar* rvalue = g_strdup_printf ("\"%s\"",value);
gchar* patt = g_regex_escape_string (rvalue, -1);
if (!g_regex_match_simple (patt, tmp,
G_REGEX_CASELESS, G_REGEX_MATCH_NOTEMPTY))
{
gchar* new_value = g_strdup_printf ("%s%s,", tmp, rvalue);
g_hash_table_insert (global_keys, g_strdup (key), new_value);
g_free (rvalue);
g_free (patt);
}
else
{
g_free (rvalue);
g_free (patt);
return FALSE;
}
}
else
{
gchar* new_value = g_strdup_printf ("\"%s\",",value);
g_hash_table_replace (global_keys, g_strdup (key), new_value);
}
return TRUE;
}
static gboolean
formhistory_navigation_decision_cb (WebKitWebView* web_view,
WebKitWebFrame* web_frame,
WebKitNetworkRequest* request,
WebKitWebNavigationAction* action,
WebKitWebPolicyDecision* decision,
MidoriExtension* extension)
{
/* The script returns form data in the form "field_name|,|value|,|field_type".
We are handling only input fields with 'text' or 'password' type.
The field separator is "|||" */
const gchar* script = "function dumpForm (inputs) {"
" var out = '';"
" for (i=0;i<inputs.length;i++) {"
" if (inputs[i].getAttribute('autocomplete') == 'off')"
" continue;"
" if (inputs[i].value && (inputs[i].type == 'text' || inputs[i].type == 'password')) {"
" var ename = inputs[i].getAttribute('name');"
" var eid = inputs[i].getAttribute('id');"
" if (!ename && eid)"
" ename=eid;"
" if (inputs[i].getAttribute('autocomplete') != 'off')"
" out += ename+'|,|'+inputs[i].value +'|,|'+inputs[i].type +'|||';"
" }"
" }"
" return out;"
"}"
"dumpForm (document.getElementsByTagName('input'))";
if (webkit_web_navigation_action_get_reason (action) == WEBKIT_WEB_NAVIGATION_REASON_FORM_SUBMITTED)
{
JSContextRef js_context = webkit_web_frame_get_global_context (web_frame);
gchar* value = sokoke_js_script_eval (js_context, script, NULL);
if (value && *value)
{
gpointer db = g_object_get_data (G_OBJECT (extension), "formhistory-db");
gchar** inputs = g_strsplit (value, "|||", 0);
guint i = 0;
while (inputs[i] != NULL)
{
gchar** parts = g_strsplit (inputs[i], "|,|", 3);
if (parts && parts[0] && parts[1] && parts[2])
{
/* FIXME: We need to handle passwords */
if (strcmp (parts[2], "password"))
{
if (formhistory_update_main_hash (parts[0], parts[1]))
formhistory_update_database (db, parts[0], parts[1]);
}
}
g_strfreev (parts);
i++;
}
g_strfreev (inputs);
g_free (value);
}
}
return FALSE;
}
static void
formhistory_window_object_cleared_cb (WebKitWebView* web_view,
WebKitWebFrame* web_frame,
JSContextRef js_context,
JSObjectRef js_window)
{
gchar* script;
const gchar* page_uri;
page_uri = webkit_web_frame_get_uri (web_frame);
if (!midori_uri_is_http (page_uri))
return;
script = formhistory_build_js ();
sokoke_js_script_eval (js_context, script, NULL);
g_free (script);
}
static void
formhistory_add_tab_cb (MidoriBrowser* browser,
MidoriView* view,
MidoriExtension* extension)
{
GtkWidget* web_view = midori_view_get_web_view (view);
g_signal_connect (web_view, "window-object-cleared",
G_CALLBACK (formhistory_window_object_cleared_cb), NULL);
g_signal_connect (web_view, "navigation-policy-decision-requested",
G_CALLBACK (formhistory_navigation_decision_cb), extension);
}
static void
formhistory_deactivate_cb (MidoriExtension* extension,
MidoriBrowser* browser);
static void
formhistory_add_tab_foreach_cb (MidoriView* view,
MidoriBrowser* browser,
MidoriExtension* extension)
{
formhistory_add_tab_cb (browser, view, extension);
}
static void
formhistory_app_add_browser_cb (MidoriApp* app,
MidoriBrowser* browser,
MidoriExtension* extension)
{
GtkAccelGroup* acg = gtk_accel_group_new ();
GtkActionGroup* action_group = midori_browser_get_action_group (browser);
GtkAction* action = gtk_action_new ("FormHistoryToggleState",
_("Toggle form history state"),
_("Activate or deactivate form history for the current tab."), NULL);
gtk_window_add_accel_group (GTK_WINDOW (browser), acg);
g_object_set_data (G_OBJECT (browser), "FormHistoryExtension", extension);
g_signal_connect (action, "activate",
G_CALLBACK (formhistory_toggle_state_cb), browser);
gtk_action_group_add_action_with_accel (action_group, action, "<Ctrl><Shift>F");
gtk_action_set_accel_group (action, acg);
gtk_action_connect_accelerator (action);
if (midori_extension_get_boolean (extension, "always-load"))
{
midori_browser_foreach (browser,
(GtkCallback)formhistory_add_tab_foreach_cb, extension);
g_signal_connect (browser, "add-tab",
G_CALLBACK (formhistory_add_tab_cb), extension);
}
g_signal_connect (extension, "deactivate",
G_CALLBACK (formhistory_deactivate_cb), browser);
}
static void
formhistory_deactivate_tabs (MidoriView* view,
MidoriBrowser* browser,
MidoriExtension* extension)
{
GtkWidget* web_view = midori_view_get_web_view (view);
g_signal_handlers_disconnect_by_func (
web_view, formhistory_window_object_cleared_cb, NULL);
g_signal_handlers_disconnect_by_func (
web_view, formhistory_navigation_decision_cb, extension);
}
static void
formhistory_deactivate_cb (MidoriExtension* extension,
MidoriBrowser* browser)
{
MidoriApp* app = midori_extension_get_app (extension);
sqlite3* db;
GtkActionGroup* action_group = midori_browser_get_action_group (browser);
GtkAction* action;
g_signal_handlers_disconnect_by_func (
browser, formhistory_add_tab_cb, extension);
g_signal_handlers_disconnect_by_func (
extension, formhistory_deactivate_cb, browser);
g_signal_handlers_disconnect_by_func (
app, formhistory_app_add_browser_cb, extension);
midori_browser_foreach (browser,
(GtkCallback)formhistory_deactivate_tabs, extension);
g_object_set_data (G_OBJECT (browser), "FormHistoryExtension", NULL);
action = gtk_action_group_get_action ( action_group, "FormHistoryToggleState");
if (action != NULL)
{
gtk_action_group_remove_action (action_group, action);
g_object_unref (action);
}
katze_assign (jsforms, NULL);
if (global_keys)
g_hash_table_destroy (global_keys);
if ((db = g_object_get_data (G_OBJECT (extension), "formhistory-db")))
sqlite3_close (db);
}
static int
formhistory_add_field (gpointer data,
int argc,
char** argv,
char** colname)
{
gint i;
gint ncols = 3;
/* Test whether have the right number of columns */
g_return_val_if_fail (argc % ncols == 0, 1);
for (i = 0; i < (argc - ncols) + 1; i++)
{
if (argv[i])
{
if (colname[i] && !g_ascii_strcasecmp (colname[i], "domain")
&& colname[i + 1] && !g_ascii_strcasecmp (colname[i + 1], "field")
&& colname[i + 2] && !g_ascii_strcasecmp (colname[i + 2], "value"))
{
gchar* key = argv[i + 1];
formhistory_update_main_hash (g_strdup (key), g_strdup (argv[i + 2]));
}
}
}
return 0;
}
static void
formhistory_activate_cb (MidoriExtension* extension,
MidoriApp* app)
{
const gchar* config_dir;
gchar* filename;
sqlite3* db;
char* errmsg = NULL, *errmsg2 = NULL;
KatzeArray* browsers;
MidoriBrowser* browser;
global_keys = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)g_free);
if(!jsforms)
formhistory_prepare_js ();
config_dir = midori_extension_get_config_dir (extension);
katze_mkdir_with_parents (config_dir, 0700);
filename = g_build_filename (config_dir, "forms.db", NULL);
if (sqlite3_open (filename, &db) != SQLITE_OK)
{
/* If the folder is /, this is a test run, thus no error */
if (!g_str_equal (midori_extension_get_config_dir (extension), "/"))
g_warning (_("Failed to open database: %s\n"), sqlite3_errmsg (db));
sqlite3_close (db);
}
g_free (filename);
if ((sqlite3_exec (db, "CREATE TABLE IF NOT EXISTS "
"forms (domain text, field text, value text)",
NULL, NULL, &errmsg) == SQLITE_OK)
&& (sqlite3_exec (db, "SELECT domain, field, value FROM forms ",
formhistory_add_field,
NULL, &errmsg2) == SQLITE_OK))
g_object_set_data (G_OBJECT (extension), "formhistory-db", db);
else
{
if (errmsg)
{
g_critical (_("Failed to execute database statement: %s\n"), errmsg);
sqlite3_free (errmsg);
if (errmsg2)
{
g_critical (_("Failed to execute database statement: %s\n"), errmsg2);
sqlite3_free (errmsg2);
}
}
sqlite3_close (db);
}
browsers = katze_object_get_object (app, "browsers");
KATZE_ARRAY_FOREACH_ITEM (browser, browsers)
formhistory_app_add_browser_cb (app, browser, extension);
g_signal_connect (app, "add-browser",
G_CALLBACK (formhistory_app_add_browser_cb), extension);
g_object_unref (browsers);
}
static void
formhistory_preferences_response_cb (GtkWidget* dialog,
gint response_id,
MidoriExtension* extension)
{
GtkWidget* checkbox;
gboolean old_state;
gboolean new_state;
MidoriApp* app;
KatzeArray* browsers;
MidoriBrowser* browser;
if (response_id == GTK_RESPONSE_APPLY)
{
checkbox = g_object_get_data (G_OBJECT (dialog), "always-load-checkbox");
new_state = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox));
old_state = midori_extension_get_boolean (extension, "always-load");
if (old_state != new_state)
{
midori_extension_set_boolean (extension, "always-load", new_state);
app = midori_extension_get_app (extension);
browsers = katze_object_get_object (app, "browsers");
KATZE_ARRAY_FOREACH_ITEM (browser, browsers)
{
midori_browser_foreach (browser,
(GtkCallback)formhistory_deactivate_tabs, extension);
g_signal_handlers_disconnect_by_func (
browser, formhistory_add_tab_cb, extension);
if (new_state)
{
midori_browser_foreach (browser,
(GtkCallback)formhistory_add_tab_foreach_cb, extension);
g_signal_connect (browser, "add-tab",
G_CALLBACK (formhistory_add_tab_cb), extension);
}
}
}
}
gtk_widget_destroy (dialog);
}
static void
formhistory_preferences_cb (MidoriExtension* extension)
{
GtkWidget* dialog;
GtkWidget* content_area;
GtkWidget* checkbox;
dialog = gtk_dialog_new ();
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_APPLY, GTK_RESPONSE_APPLY);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
checkbox = gtk_check_button_new_with_label (_("only activate form history via hotkey (Ctrl+Shift+F) per tab"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbox),
!midori_extension_get_boolean (extension, "always-load"));
g_object_set_data (G_OBJECT (dialog), "always-load-checkbox", checkbox);
gtk_container_add (GTK_CONTAINER (content_area), checkbox);
g_signal_connect (dialog,
"response",
G_CALLBACK (formhistory_preferences_response_cb),
extension);
gtk_widget_show_all (dialog);
}
static void
formhistory_toggle_state_cb (GtkAction* action,
MidoriBrowser* browser)
{
MidoriView* view = MIDORI_VIEW (midori_browser_get_current_tab (browser));
MidoriExtension* extension = g_object_get_data (G_OBJECT (browser), "FormHistoryExtension");
GtkWidget* web_view = midori_view_get_web_view (view);
if (g_signal_handler_find (web_view, G_SIGNAL_MATCH_FUNC,
g_signal_lookup ("window-object-cleared", MIDORI_TYPE_VIEW), 0, NULL,
formhistory_window_object_cleared_cb, extension))
{
formhistory_deactivate_tabs (view, browser, extension);
} else {
formhistory_add_tab_cb (browser, view, extension);
}
}
#if G_ENABLE_DEBUG
/*
<html>
<head>
<title>autosuggest testcase</title>
</head>
<body>
<form method=post>
<p><input type="text" id="txt1" /></p>
<p><input type="text" name="txt2" /></p>
<input type=submit>
</form>
</body>
</html> */
#endif
MidoriExtension*
extension_init (void)
{
gboolean should_init = TRUE;
const gchar* ver;
gchar* desc;
MidoriExtension* extension;
if (formhistory_prepare_js ())
{
ver = "1.0" MIDORI_VERSION_SUFFIX;
desc = g_strdup (_("Stores history of entered form data"));
}
else
{
desc = g_strdup_printf (_("Not available: %s"),
_("Resource files not installed"));
ver = NULL;
should_init = FALSE;
}
extension = g_object_new (MIDORI_TYPE_EXTENSION,
"name", _("Form history filler"),
"description", desc,
"version", ver,
"authors", "Alexander V. Butenko <a.butenka@gmail.com>",
NULL);
g_free (desc);
if (should_init)
{
midori_extension_install_boolean (extension, "always-load", TRUE);
g_signal_connect (extension, "activate",
G_CALLBACK (formhistory_activate_cb), NULL);
g_signal_connect (extension, "open-preferences",
G_CALLBACK (formhistory_preferences_cb), NULL);
}
return extension;
}

View File

@ -1,74 +0,0 @@
/*
Copyright (C) 2009-2012 Alexander Butenko <a.butenka@gmail.com>
Copyright (C) 2009-2012 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.
*/
#ifndef __FORMHISTORY_FRONTEND_H__
#define __FORMHISTORY_FRONTEND_H__
#include <midori/midori.h>
#include <glib/gstdio.h>
#include "config.h"
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if WEBKIT_CHECK_VERSION (1, 3, 1)
#define FORMHISTORY_USE_GDOM 1
#else
#define FORMHISTORY_USE_JS 1
#endif
#define MAXPASSSIZE 64
typedef struct
{
sqlite3* db;
#ifdef FORMHISTORY_USE_GDOM
WebKitDOMElement* element;
int completion_timeout;
GtkTreeModel* completion_model;
GtkWidget* treeview;
GtkWidget* popup;
gchar* oldkeyword;
glong selection_index;
#else
gchar* jsforms;
#endif
gchar* master_password;
int master_password_canceled;
} FormHistoryPriv;
typedef struct
{
gchar* domain;
gchar* form_data;
FormHistoryPriv* priv;
} FormhistoryPasswordEntry;
FormHistoryPriv*
formhistory_private_new ();
void
formhistory_private_destroy (FormHistoryPriv *priv);
gboolean
formhistory_construct_popup_gui (FormHistoryPriv* priv);
void
formhistory_setup_suggestions (WebKitWebView* web_view,
JSContextRef js_context,
MidoriExtension* extension);
#ifdef FORMHISTORY_USE_GDOM
void
formhistory_suggestions_hide_cb (WebKitDOMElement* element,
WebKitDOMEvent* dom_event,
FormHistoryPriv* priv);
#endif
#endif

View File

@ -1,516 +0,0 @@
/*
Copyright (C) 2009-2012 Alexander Butenko <a.butenka@gmail.com>
Copyright (C) 2009-2012 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.
*/
#include "formhistory-frontend.h"
#ifdef FORMHISTORY_USE_GDOM
#define COMPLETION_DELAY 200
FormHistoryPriv*
formhistory_private_new ()
{
FormHistoryPriv* priv;
priv = g_slice_new (FormHistoryPriv);
priv->oldkeyword = g_strdup ("");
priv->selection_index = -1;
return priv;
}
void
formhistory_suggestions_hide_cb (WebKitDOMElement* element,
WebKitDOMEvent* dom_event,
FormHistoryPriv* priv)
{
if (gtk_widget_get_visible (priv->popup))
gtk_widget_hide (priv->popup);
priv->selection_index = -1;
}
static void
formhistory_suggestion_set (GtkTreePath* path,
FormHistoryPriv* priv)
{
GtkTreeIter iter;
gchar* value;
if (!gtk_tree_model_get_iter (priv->completion_model, &iter, path))
return;
gtk_tree_model_get (priv->completion_model, &iter, 0, &value, -1);
g_object_set (priv->element, "value", value, NULL);
g_free (value);
}
static gboolean
formhistory_suggestion_selected_cb (GtkWidget* treeview,
GdkEventButton* event,
FormHistoryPriv* priv)
{
GtkTreePath* path;
if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (treeview),
event->x, event->y, &path, NULL, NULL, NULL))
{
formhistory_suggestion_set (path, priv);
formhistory_suggestions_hide_cb (NULL, NULL, priv);
gtk_tree_path_free (path);
return TRUE;
}
return FALSE;
}
static void
formhistory_suggestion_remove (GtkTreePath* path,
FormHistoryPriv* priv)
{
GtkTreeIter iter;
gchar* sqlcmd;
char* errmsg = NULL;
gchar* name;
gchar* value;
if (!gtk_tree_model_get_iter (priv->completion_model, &iter, path))
return;
if (!priv->db)
return;
gtk_tree_model_get (priv->completion_model, &iter, 0, &value, -1);
g_object_get (priv->element, "name", &name, NULL);
gtk_list_store_remove (GTK_LIST_STORE (priv->completion_model), &iter);
sqlcmd = sqlite3_mprintf ("DELETE FROM forms WHERE field = '%q' AND value = '%q'",
name, value);
g_free (name);
g_free (value);
sqlite3_exec (priv->db, sqlcmd, NULL, NULL, &errmsg);
sqlite3_free (sqlcmd);
}
static void
get_absolute_offset_for_element (WebKitDOMElement* element,
WebKitDOMDocument* element_document,
WebKitDOMNodeList* frames,
glong* x,
glong* y,
gboolean ismainframe)
{
WebKitDOMElement* offset_parent;
gint offset_top = 0, offset_left = 0;
gulong i;
g_object_get (element, "offset-left", &offset_left,
"offset-top", &offset_top,
"offset-parent", &offset_parent,
NULL);
*x += offset_left;
*y += offset_top;
/* To avoid deadlock check only first element of the mainframe parent */
if (ismainframe == TRUE)
return;
if (offset_parent)
goto finish;
/* Element havent returned any parents. Thats mean or there is no parents or we are inside the frame
Loop over all frames we have to find frame == element_document which is a root for our element
and get its offsets */
for (i = 0; i < webkit_dom_node_list_get_length (frames); i++)
{
WebKitDOMDocument *fdoc;
WebKitDOMNode *frame = webkit_dom_node_list_item (frames, i);
if (WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (frame))
fdoc = webkit_dom_html_iframe_element_get_content_document (WEBKIT_DOM_HTML_IFRAME_ELEMENT (frame));
else
fdoc = webkit_dom_html_frame_element_get_content_document (WEBKIT_DOM_HTML_FRAME_ELEMENT (frame));
if (fdoc == element_document)
{
offset_parent = WEBKIT_DOM_ELEMENT (frame);
ismainframe = TRUE;
/* Add extra 4px to ~cover size of borders */
*y += 4;
break;
}
}
finish:
if (offset_parent)
get_absolute_offset_for_element (offset_parent, element_document, frames, x, y, ismainframe);
}
static void
formhistory_reposition_popup (FormHistoryPriv* priv)
{
WebKitDOMDocument* element_document;
WebKitDOMNodeList* frames;
GtkWidget* view;
GdkWindow* window;
GtkWidget* toplevel;
gint rx, ry;
gint wx, wy;
glong x = 0, y = 0;
glong height;
view = g_object_get_data (G_OBJECT (priv->element), "webview");
toplevel = gtk_widget_get_toplevel (view);
/* Position of a root window */
window = gtk_widget_get_window (toplevel);
gdk_window_get_position (window, &rx, &ry);
/* Postion of webview in root window */
window = gtk_widget_get_window (view);
gdk_window_get_position (window, &wx, &wy);
/* Position of editbox on the webview */
frames = g_object_get_data (G_OBJECT (priv->element), "framelist");
element_document = g_object_get_data (G_OBJECT (priv->element), "doc");
get_absolute_offset_for_element (priv->element, element_document, frames, &x, &y, FALSE);
/* Add height as menu should start under editbox, now on top of it */
g_object_get (priv->element, "client-height", &height, NULL);
y += height + 1;
gtk_window_move (GTK_WINDOW (priv->popup), rx + wx + x, ry +wy + y);
/* Window configuration */
gtk_window_set_screen (GTK_WINDOW (priv->popup), gtk_widget_get_screen (view));
gtk_window_set_transient_for (GTK_WINDOW (priv->popup), GTK_WINDOW (toplevel));
gtk_tree_view_columns_autosize (GTK_TREE_VIEW (priv->treeview));
/* FIXME: Adjust size according to treeview width and some reasonable height */
gtk_window_resize (GTK_WINDOW (priv->popup), 50, 80);
}
static gboolean
formhistory_suggestions_show (FormHistoryPriv* priv)
{
GtkListStore* store;
static sqlite3_stmt* stmt;
gchar* value, * name;
const char* sqlcmd;
gint result;
gchar* likedvalue;
int pos = 0;
g_return_val_if_fail (priv->element, FALSE);
g_object_get (priv->element,
"name", &name,
"value", &value,
NULL);
katze_assign (priv->oldkeyword, g_strdup (value));
if (!priv->popup)
formhistory_construct_popup_gui (priv);
if (!stmt)
{
if (!priv->db)
goto free_data;
sqlcmd = "SELECT DISTINCT value FROM forms WHERE field = ?1 and value like ?2";
sqlite3_prepare_v2 (priv->db, sqlcmd, strlen (sqlcmd) + 1, &stmt, NULL);
}
likedvalue = g_strdup_printf ("%s%%", value);
sqlite3_bind_text (stmt, 1, name, -1, NULL);
sqlite3_bind_text (stmt, 2, likedvalue, -1, g_free);
result = sqlite3_step (stmt);
if (result != SQLITE_ROW)
{
if (result == SQLITE_ERROR)
g_print (_("Failed to select suggestions\n"));
sqlite3_reset (stmt);
sqlite3_clear_bindings (stmt);
formhistory_suggestions_hide_cb (NULL, NULL, priv);
goto free_data;
}
store = GTK_LIST_STORE (priv->completion_model);
gtk_list_store_clear (store);
while (result == SQLITE_ROW)
{
const unsigned char* text = sqlite3_column_text (stmt, 0);
pos++;
gtk_list_store_insert_with_values (store, NULL, pos, 0, text, -1);
result = sqlite3_step (stmt);
}
sqlite3_reset (stmt);
sqlite3_clear_bindings (stmt);
if (!gtk_widget_get_visible (priv->popup))
{
formhistory_reposition_popup (priv);
gtk_widget_show_all (priv->popup);
}
free_data:
g_free (name);
g_free (value);
return FALSE;
}
static void
formhistory_editbox_key_pressed_cb (WebKitDOMElement* element,
WebKitDOMEvent* dom_event,
FormHistoryPriv* priv)
{
glong key;
GtkTreePath* path;
gchar* keyword;
gint matches;
/* FIXME: Priv is still set after module is disabled */
g_return_if_fail (priv);
g_return_if_fail (element);
if (priv->completion_timeout > 0)
g_source_remove (priv->completion_timeout);
katze_object_assign (priv->element, g_object_ref (element));
key = webkit_dom_ui_event_get_key_code (WEBKIT_DOM_UI_EVENT (dom_event));
switch (key)
{
/* ESC key*/
case 27:
case 35:
case 36:
/* Left key*/
case 37:
/* Right key*/
case 39:
/* Enter key*/
case 13:
if (key == 27)
g_object_set (element, "value", priv->oldkeyword, NULL);
formhistory_suggestions_hide_cb (element, dom_event, priv);
return;
break;
/* Del key */
case 46:
/* Up key */
case 38:
/* Down key */
case 40:
if (!gtk_widget_get_visible (priv->popup))
{
formhistory_suggestions_show (priv);
return;
}
matches = gtk_tree_model_iter_n_children (priv->completion_model, NULL);
if (key == 38)
{
if (priv->selection_index <= 0)
priv->selection_index = matches - 1;
else
priv->selection_index = MAX (priv->selection_index - 1, 0);
}
else if (key == 40)
{
if (priv->selection_index == matches - 1)
priv->selection_index = 0;
else
priv->selection_index = MIN (priv->selection_index + 1, matches -1);
}
if (priv->selection_index == -1)
{
/* No element is selected */
return;
}
path = gtk_tree_path_new_from_indices (priv->selection_index, -1);
if (key == 46)
{
g_object_set (element, "value", priv->oldkeyword, NULL);
formhistory_suggestion_remove (path, priv);
matches--;
}
if (matches == 0)
formhistory_suggestions_hide_cb (element, dom_event, priv);
else
{
gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->treeview), path, NULL, FALSE);
formhistory_suggestion_set (path, priv);
}
gtk_tree_path_free (path);
return;
break;
/* PgUp, PgDn, Ins */
case 33:
case 34:
case 45:
/* Shift, Ctrl, Alt, Tab, Caps Lock*/
case 16:
case 17:
case 18:
case 20:
case 9:
return;
break;
}
g_object_get (element, "value", &keyword, NULL);
if (!(keyword && *keyword && *keyword != ' '))
{
formhistory_suggestions_hide_cb (element, dom_event, priv);
goto free_data;
}
/* If the same keyword is submitted there's no need to regenerate suggestions */
if (gtk_widget_get_visible (priv->popup) &&
!g_strcmp0 (keyword, priv->oldkeyword))
goto free_data;
priv->completion_timeout = g_timeout_add (COMPLETION_DELAY,
(GSourceFunc)formhistory_suggestions_show, priv);
free_data:
g_free (keyword);
}
static void
formhistory_DOMContentLoaded_cb (WebKitDOMElement* window,
WebKitDOMEvent* dom_event,
FormHistoryPriv* priv)
{
gulong i;
WebKitDOMDocument* doc;
WebKitDOMNodeList* inputs;
WebKitDOMNodeList* frames;
GtkWidget* web_view;
if (WEBKIT_DOM_IS_DOCUMENT (window))
doc = WEBKIT_DOM_DOCUMENT (window);
else
doc = webkit_dom_dom_window_get_document (WEBKIT_DOM_DOM_WINDOW (window));
inputs = webkit_dom_document_query_selector_all (doc, "input[type='text']", NULL);
frames = g_object_get_data (G_OBJECT (window), "framelist");
web_view = g_object_get_data (G_OBJECT (window), "webview");
for (i = 0; i < webkit_dom_node_list_get_length (inputs); i++)
{
WebKitDOMNode* element = webkit_dom_node_list_item (inputs, i);
#if WEBKIT_CHECK_VERSION (1, 6, 1)
gchar* autocomplete = webkit_dom_html_input_element_get_autocomplete (
WEBKIT_DOM_HTML_INPUT_ELEMENT (element));
gboolean off = !g_strcmp0 (autocomplete, "off");
g_free (autocomplete);
if (off)
continue;
#endif
g_object_set_data (G_OBJECT (element), "doc", doc);
g_object_set_data (G_OBJECT (element), "webview", web_view);
g_object_set_data (G_OBJECT (element), "framelist", frames);
/* Add dblclick? */
webkit_dom_event_target_add_event_listener (
WEBKIT_DOM_EVENT_TARGET (element), "keyup",
G_CALLBACK (formhistory_editbox_key_pressed_cb), false,
priv);
webkit_dom_event_target_add_event_listener (
WEBKIT_DOM_EVENT_TARGET (element), "blur",
G_CALLBACK (formhistory_suggestions_hide_cb), false,
priv);
}
}
void
formhistory_setup_suggestions (WebKitWebView* web_view,
JSContextRef js_context,
MidoriExtension* extension)
{
WebKitDOMDocument* doc;
WebKitDOMNodeList* frames;
gulong i;
FormHistoryPriv* priv = g_object_get_data (G_OBJECT (extension), "priv");
doc = webkit_web_view_get_dom_document (web_view);
frames = webkit_dom_document_query_selector_all (doc, "iframe, frame", NULL);
g_object_set_data (G_OBJECT (doc), "framelist", frames);
g_object_set_data (G_OBJECT (doc), "webview", web_view);
/* Connect to DOMContentLoaded of the main frame */
webkit_dom_event_target_add_event_listener(
WEBKIT_DOM_EVENT_TARGET (doc), "DOMContentLoaded",
G_CALLBACK (formhistory_DOMContentLoaded_cb), false,
priv);
/* Connect to DOMContentLoaded of frames */
for (i = 0; i < webkit_dom_node_list_get_length (frames); i++)
{
WebKitDOMDOMWindow* framewin;
WebKitDOMNode* frame = webkit_dom_node_list_item (frames, i);
if (WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (frame))
framewin = webkit_dom_html_iframe_element_get_content_window (WEBKIT_DOM_HTML_IFRAME_ELEMENT (frame));
else
framewin = webkit_dom_html_frame_element_get_content_window (WEBKIT_DOM_HTML_FRAME_ELEMENT (frame));
g_object_set_data (G_OBJECT (framewin), "framelist", frames);
g_object_set_data (G_OBJECT (framewin), "webview", (GtkWidget*)web_view);
webkit_dom_event_target_add_event_listener (
WEBKIT_DOM_EVENT_TARGET (framewin), "DOMContentLoaded",
G_CALLBACK (formhistory_DOMContentLoaded_cb), false,
priv);
}
formhistory_suggestions_hide_cb (NULL, NULL, priv);
}
void
formhistory_private_destroy (FormHistoryPriv *priv)
{
if (priv->db)
{
sqlite3_close (priv->db);
priv->db = NULL;
}
katze_assign (priv->oldkeyword, NULL);
gtk_widget_destroy (priv->popup);
priv->popup = NULL;
katze_object_assign (priv->element, NULL);
g_slice_free (FormHistoryPriv, priv);
}
gboolean
formhistory_construct_popup_gui (FormHistoryPriv* priv)
{
GtkTreeModel* model = NULL;
GtkWidget* popup;
GtkWidget* popup_frame;
GtkWidget* scrolled;
GtkWidget* treeview;
GtkCellRenderer* renderer;
GtkTreeViewColumn* column;
model = (GtkTreeModel*) gtk_list_store_new (1, G_TYPE_STRING);
priv->completion_model = model;
popup = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_type_hint (GTK_WINDOW (popup), GDK_WINDOW_TYPE_HINT_COMBO);
popup_frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (popup_frame), GTK_SHADOW_ETCHED_IN);
gtk_container_add (GTK_CONTAINER (popup), popup_frame);
scrolled = g_object_new (GTK_TYPE_SCROLLED_WINDOW,
"hscrollbar-policy", GTK_POLICY_NEVER,
"vscrollbar-policy", GTK_POLICY_AUTOMATIC, NULL);
gtk_container_add (GTK_CONTAINER (popup_frame), scrolled);
treeview = gtk_tree_view_new_with_model (model);
priv->treeview = treeview;
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (treeview), TRUE);
gtk_container_add (GTK_CONTAINER (scrolled), treeview);
gtk_widget_set_size_request (gtk_scrolled_window_get_vscrollbar (
GTK_SCROLLED_WINDOW (scrolled)), -1, 0);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("suggestions", renderer, "text", 0, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
priv->popup = popup;
g_signal_connect (treeview, "button-press-event",
G_CALLBACK (formhistory_suggestion_selected_cb), priv);
return TRUE;
}
#endif

View File

@ -1,143 +0,0 @@
/*
Copyright (C) 2009-2012 Alexander Butenko <a.butenka@gmail.com>
Copyright (C) 2009-2012 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.
*/
#include "formhistory-frontend.h"
#ifdef FORMHISTORY_USE_JS
FormHistoryPriv*
formhistory_private_new ()
{
FormHistoryPriv* priv;
priv = g_slice_new (FormHistoryPriv);
return priv;
}
gboolean
formhistory_construct_popup_gui (FormHistoryPriv* priv)
{
gchar* autosuggest;
gchar* style;
guint i;
gchar* file;
file = midori_app_find_res_filename ("autosuggestcontrol.js");
if (!g_file_get_contents (file, &autosuggest, NULL, NULL))
{
g_free (file);
return FALSE;
}
g_strchomp (autosuggest);
katze_assign (file, midori_app_find_res_filename ("autosuggestcontrol.css"));
if (!g_file_get_contents (file, &style, NULL, NULL))
{
g_free (file);
return FALSE;
}
g_strchomp (style);
g_free (file);
i = 0;
while (style[i])
{
if (style[i] == '\n')
style[i] = ' ';
i++;
}
priv->jsforms = g_strdup_printf (
"%s"
"window.addEventListener ('DOMContentLoaded',"
"function () {"
" if (document.getElementById('formhistory'))"
" return;"
" if (!initSuggestions ())"
" return;"
" var mystyle = document.createElement('style');"
" mystyle.setAttribute('type', 'text/css');"
" mystyle.setAttribute('id', 'formhistory');"
" mystyle.appendChild(document.createTextNode('%s'));"
" var head = document.getElementsByTagName('head')[0];"
" if (head) head.appendChild(mystyle);"
"}, true);",
autosuggest,
style);
g_strstrip (priv->jsforms);
g_free (style);
g_free (autosuggest);
return TRUE;
}
void
formhistory_setup_suggestions (WebKitWebView* web_view,
JSContextRef js_context,
MidoriExtension* extension)
{
GString* suggestions;
FormHistoryPriv* priv;
static sqlite3_stmt* stmt;
const char* sqlcmd;
const unsigned char* key;
const unsigned char* value;
gint result, pos;
priv = g_object_get_data (G_OBJECT (extension), "priv");
if (!priv->db)
return;
if (!stmt)
{
sqlcmd = "SELECT DISTINCT group_concat(value,'\",\"'), field FROM forms \
GROUP BY field ORDER BY field";
sqlite3_prepare_v2 (priv->db, sqlcmd, strlen (sqlcmd) + 1, &stmt, NULL);
}
result = sqlite3_step (stmt);
if (result != SQLITE_ROW)
{
if (result == SQLITE_ERROR)
g_print (_("Failed to select suggestions\n"));
sqlite3_reset (stmt);
return;
}
suggestions = g_string_new (
"function FormSuggestions(eid) { "
"arr = new Array();");
while (result == SQLITE_ROW)
{
pos++;
value = sqlite3_column_text (stmt, 0);
key = sqlite3_column_text (stmt, 1);
if (value)
{
g_string_append_printf (suggestions, " arr[\"%s\"] = [\"%s\"]; ",
(gchar*)key, (gchar*)value);
}
result = sqlite3_step (stmt);
}
g_string_append (suggestions, "this.suggestions = arr[eid]; }");
g_string_append (suggestions, priv->jsforms);
sokoke_js_script_eval (js_context, suggestions->str, NULL);
g_string_free (suggestions, TRUE);
}
void
formhistory_private_destroy (FormHistoryPriv *priv)
{
if (priv->db)
{
sqlite3_close (priv->db);
priv->db = NULL;
}
katze_assign (priv->jsforms, NULL);
g_slice_free (FormHistoryPriv, priv);
}
#endif

View File

@ -1,681 +0,0 @@
/*
Copyright (C) 2009-2012 Alexander Butenko <a.butenka@gmail.com>
Copyright (C) 2009-2012 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.
*/
#define MAXCHARS 60
#define MINCHARS 2
#define GTK_RESPONSE_IGNORE 99
#include "formhistory-frontend.h"
static void
formhistory_toggle_state_cb (GtkAction* action,
MidoriBrowser* browser);
static void
formhistory_update_database (gpointer db,
const gchar* host,
const gchar* key,
const gchar* value)
{
gchar* sqlcmd;
gchar* errmsg;
gint success;
if (!(value && *value))
return;
sqlcmd = sqlite3_mprintf ("INSERT INTO forms VALUES"
"('%q', '%q', '%q')",
host, key, value);
success = sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg);
sqlite3_free (sqlcmd);
if (success != SQLITE_OK)
{
g_printerr (_("Failed to add form value: %s\n"), errmsg);
g_free (errmsg);
return;
}
}
static gchar*
formhistory_get_login_data (gpointer db,
const gchar* domain)
{
static sqlite3_stmt* stmt;
const char* sqlcmd;
gint result;
gchar* value = NULL;
if (!stmt)
{
sqlcmd = "SELECT value FROM forms WHERE domain = ?1 and field = 'MidoriPasswordManager' limit 1";
sqlite3_prepare_v2 (db, sqlcmd, strlen (sqlcmd) + 1, &stmt, NULL);
}
sqlite3_bind_text (stmt, 1, domain, -1, NULL);
result = sqlite3_step (stmt);
if (result == SQLITE_ROW)
value = g_strdup ((gchar*)sqlite3_column_text (stmt, 0));
sqlite3_reset (stmt);
sqlite3_clear_bindings (stmt);
return value;
}
static gboolean
formhistory_check_master_password (GtkWidget* parent,
FormHistoryPriv* priv)
{
GtkWidget* dialog;
GtkWidget* content_area;
GtkWidget* hbox;
GtkWidget* image;
GtkWidget* label;
GtkWidget* entry;
const gchar* title;
static int alive;
gboolean ret = FALSE;
/* Password is set */
if (priv->master_password && *priv->master_password)
return TRUE;
/* Other prompt is active */
if (alive == 1)
return FALSE;
/* Prompt was cancelled */
if (priv->master_password_canceled == 1)
return FALSE;
alive = 1;
title = _("Form history");
dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (parent),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_DIALOG_AUTHENTICATION);
gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
gtk_container_set_border_width (GTK_CONTAINER (content_area), 5);
hbox = gtk_hbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION,
GTK_ICON_SIZE_DIALOG);
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
label = gtk_label_new (_("Master password required\n"
"to open password database"));
gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (content_area), hbox);
entry = gtk_entry_new ();
g_object_set (entry, "truncate-multiline", TRUE, NULL);
gtk_entry_set_visibility(GTK_ENTRY (entry),FALSE);
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
gtk_container_add (GTK_CONTAINER (content_area), entry);
gtk_widget_show_all (entry);
gtk_widget_show_all (hbox);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
{
/* FIXME: add password verification */
katze_assign (priv->master_password,
g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))));
ret = TRUE;
}
else
priv->master_password_canceled = 1;
gtk_widget_destroy (dialog);
alive = 0;
return ret;
}
static gchar*
formhistory_encrypt (const gchar* data,
const gchar* password)
{
/* TODO: Implement persistent storage/ keyring support */
return NULL;
}
static void
formhistory_remember_password_response (GtkWidget* infobar,
gint response_id,
FormhistoryPasswordEntry* entry)
{
gchar* encrypted_form;
if (response_id == GTK_RESPONSE_IGNORE)
goto cleanup;
if (formhistory_check_master_password (NULL, entry->priv))
{
if (response_id != GTK_RESPONSE_ACCEPT)
katze_assign (entry->form_data, g_strdup ("never"));
if ((encrypted_form = formhistory_encrypt (entry->form_data,
entry->priv->master_password)))
formhistory_update_database (entry->priv->db, entry->domain, "MidoriPasswordManager", encrypted_form);
g_free (encrypted_form);
}
cleanup:
g_free (entry->form_data);
g_free (entry->domain);
g_slice_free (FormhistoryPasswordEntry, entry);
gtk_widget_destroy (infobar);
}
static gboolean
formhistory_navigation_decision_cb (WebKitWebView* web_view,
WebKitWebFrame* web_frame,
WebKitNetworkRequest* request,
WebKitWebNavigationAction* action,
WebKitWebPolicyDecision* decision,
MidoriExtension* extension)
{
FormHistoryPriv* priv;
JSContextRef js_context;
gchar* value;
/* The script returns form data in the form "field_name|,|value|,|field_type".
We are handling only input fields with 'text' or 'password' type.
The field separator is "|||" */
const gchar* script = "function dumpForm (inputs) {"
" var out = '';"
" for (var i = 0; i < inputs.length; i++) {"
" if (inputs[i].getAttribute('autocomplete') == 'off' && "
" inputs[i].type == 'text')"
" continue;"
" if (inputs[i].value && (inputs[i].type == 'text' || inputs[i].type == 'password')) {"
" var ename = inputs[i].getAttribute('name');"
" var eid = inputs[i].getAttribute('id');"
" if (!eid && ename)"
" eid=ename;"
" out += eid+'|,|'+inputs[i].value +'|,|'+inputs[i].type +'|||';"
" }"
" }"
" return out;"
"}"
"dumpForm (document.getElementsByTagName('input'))";
if (webkit_web_navigation_action_get_reason (action) != WEBKIT_WEB_NAVIGATION_REASON_FORM_SUBMITTED)
return FALSE;
priv = g_object_get_data (G_OBJECT (extension), "priv");
js_context = webkit_web_frame_get_global_context (web_frame);
value = sokoke_js_script_eval (js_context, script, NULL);
#ifdef FORMHISTORY_USE_GDOM
formhistory_suggestions_hide_cb (NULL, NULL, priv);
#endif
if (value && *value)
{
gchar** inputs = g_strsplit (value, "|||", 0);
guint i = 0;
while (inputs[i] != NULL)
{
gchar** parts = g_strsplit (inputs[i], "|,|", 3);
if (parts && parts[0] && parts[1] && parts[2])
{
if (strcmp (parts[2], "password"))
formhistory_update_database (priv->db, NULL, parts[0], parts[1]);
#if WEBKIT_CHECK_VERSION (1, 3, 8)
else
{
gchar* data;
gchar* domain;
#if 0
FormhistoryPasswordEntry* entry;
#endif
domain = midori_uri_parse_hostname (webkit_web_frame_get_uri (web_frame), NULL);
data = formhistory_get_login_data (priv->db, domain);
if (data)
{
g_free (data);
g_free (domain);
break;
}
#if 0
entry = g_slice_new (FormhistoryPasswordEntry);
/* Domain and form data are freed from infopanel callback*/
entry->form_data = g_strdup (value);
entry->domain = domain;
entry->priv = priv;
g_object_set_data (G_OBJECT (web_view), "FormHistoryPasswordEntry", entry);
#endif
}
#endif
}
g_strfreev (parts);
i++;
}
g_strfreev (inputs);
g_free (value);
}
return FALSE;
}
static void
formhistory_window_object_cleared_cb (WebKitWebView* web_view,
WebKitWebFrame* web_frame,
JSContextRef js_context,
JSObjectRef js_window,
MidoriExtension* extension)
{
const gchar* page_uri;
FormhistoryPasswordEntry* entry;
GtkWidget* view;
page_uri = webkit_web_frame_get_uri (web_frame);
if (!page_uri)
return;
if (!midori_uri_is_http (page_uri) && !g_str_has_prefix (page_uri, "file"))
return;
formhistory_setup_suggestions (web_view, js_context, extension);
#if WEBKIT_CHECK_VERSION (1, 3, 8)
entry = g_object_get_data (G_OBJECT (web_view), "FormHistoryPasswordEntry");
if (entry)
{
const gchar* message = _("Remember password on this page?");
view = midori_browser_get_current_tab (midori_app_get_browser (
midori_extension_get_app (extension)));
midori_view_add_info_bar (MIDORI_VIEW (view), GTK_MESSAGE_QUESTION, message,
G_CALLBACK (formhistory_remember_password_response), entry,
_("Remember"), GTK_RESPONSE_ACCEPT,
_("Not now"), GTK_RESPONSE_IGNORE,
_("Never for this page"), GTK_RESPONSE_CANCEL, NULL);
g_object_set_data (G_OBJECT (web_view), "FormHistoryPasswordEntry", NULL);
}
#endif
}
#if WEBKIT_CHECK_VERSION (1, 3, 8)
static gchar*
formhistory_decrypt (const gchar* data,
const gchar* password)
{
/* TODO: Implement persistent storage/ keyring support */
return NULL;
}
static void
formhistory_fill_login_data (JSContextRef js_context,
FormHistoryPriv* priv,
const gchar* data)
{
gchar* decrypted_data = NULL;
guint i = 0;
GString *script;
gchar** inputs;
/* Handle case that user dont want to store password */
if (!strncmp (data, "never", 5))
return;
#if 0
if (!formhistory_check_master_password (NULL, priv))
return;
#endif
if (!(decrypted_data = formhistory_decrypt (data, priv->master_password)))
return;
script = g_string_new ("");
inputs = g_strsplit (decrypted_data, "|||", 0);
while (inputs[i] != NULL)
{
gchar** parts = g_strsplit (inputs[i], "|,|", 3);
if (parts && parts[0] && parts[1] && parts[2])
{
g_string_append_printf (script, "node = null;"
"node = document.getElementById ('%s');"
"if (!node) { node = document.getElementsByName ('%s')[0]; }"
"if (node && node.type == '%s') { node.value = '%s'; }",
parts[0], parts[0], parts[2], parts[1]);
}
g_strfreev (parts);
i++;
}
g_free (decrypted_data);
g_strfreev (inputs);
g_free (sokoke_js_script_eval (js_context, script->str, NULL));
g_string_free (script, TRUE);
}
static void
formhistory_frame_loaded_cb (WebKitWebView* web_view,
WebKitWebFrame* web_frame,
MidoriExtension* extension)
{
const gchar* page_uri;
const gchar* count_request;
FormHistoryPriv* priv;
JSContextRef js_context;
gchar* data;
gchar* domain;
gchar* count;
page_uri = webkit_web_frame_get_uri (web_frame);
if (!page_uri)
return;
count_request = "document.querySelectorAll('input[type=password]').length";
js_context = webkit_web_frame_get_global_context (web_frame);
count = sokoke_js_script_eval (js_context, count_request, NULL);
if (count && count[0] == '0')
{
g_free (count);
return;
}
g_free (count);
priv = g_object_get_data (G_OBJECT (extension), "priv");
domain = midori_uri_parse_hostname (webkit_web_frame_get_uri (web_frame), NULL);
data = formhistory_get_login_data (priv->db, domain);
g_free (domain);
if (!data)
return;
formhistory_fill_login_data (js_context, priv, data);
g_free (data);
}
#endif
static void
formhistory_deactivate_cb (MidoriExtension* extension,
MidoriBrowser* browser);
static void
formhistory_add_tab_cb (MidoriBrowser* browser,
MidoriView* view,
MidoriExtension* extension)
{
GtkWidget* web_view = midori_view_get_web_view (view);
g_signal_connect (web_view, "window-object-cleared",
G_CALLBACK (formhistory_window_object_cleared_cb), extension);
g_signal_connect (web_view, "navigation-policy-decision-requested",
G_CALLBACK (formhistory_navigation_decision_cb), extension);
#if WEBKIT_CHECK_VERSION (1, 3, 8)
g_signal_connect (web_view, "onload-event",
G_CALLBACK (formhistory_frame_loaded_cb), extension);
#endif
}
static void
formhistory_add_tab_foreach_cb (MidoriView* view,
MidoriExtension* extension)
{
formhistory_add_tab_cb (NULL, view, extension);
}
static void
formhistory_app_add_browser_cb (MidoriApp* app,
MidoriBrowser* browser,
MidoriExtension* extension)
{
GtkAccelGroup* acg = gtk_accel_group_new ();
GtkActionGroup* action_group = midori_browser_get_action_group (browser);
GtkAction* action = gtk_action_new ("FormHistoryToggleState",
_("Toggle form history state"),
_("Activate or deactivate form history for the current tab."), NULL);
gtk_window_add_accel_group (GTK_WINDOW (browser), acg);
g_object_set_data (G_OBJECT (browser), "FormHistoryExtension", extension);
g_signal_connect (action, "activate",
G_CALLBACK (formhistory_toggle_state_cb), browser);
gtk_action_group_add_action_with_accel (action_group, action, "<Ctrl><Shift>F");
gtk_action_set_accel_group (action, acg);
gtk_action_connect_accelerator (action);
if (midori_extension_get_boolean (extension, "always-load"))
{
midori_browser_foreach (browser,
(GtkCallback)formhistory_add_tab_foreach_cb, extension);
g_signal_connect (browser, "add-tab",
G_CALLBACK (formhistory_add_tab_cb), extension);
}
g_signal_connect (extension, "deactivate",
G_CALLBACK (formhistory_deactivate_cb), browser);
}
static void
formhistory_deactivate_tab (MidoriView* view,
MidoriExtension* extension)
{
GtkWidget* web_view = midori_view_get_web_view (view);
g_signal_handlers_disconnect_by_func (
web_view, formhistory_window_object_cleared_cb, extension);
g_signal_handlers_disconnect_by_func (
web_view, formhistory_navigation_decision_cb, extension);
#if WEBKIT_CHECK_VERSION (1, 3, 8)
g_signal_handlers_disconnect_by_func (
web_view, formhistory_frame_loaded_cb, extension);
#endif
}
static void
formhistory_deactivate_cb (MidoriExtension* extension,
MidoriBrowser* browser)
{
MidoriApp* app = midori_extension_get_app (extension);
FormHistoryPriv* priv = g_object_get_data (G_OBJECT (extension), "priv");
GtkActionGroup* action_group = midori_browser_get_action_group (browser);
GtkAction* action;
g_signal_handlers_disconnect_by_func (
browser, formhistory_add_tab_cb, extension);
g_signal_handlers_disconnect_by_func (
extension, formhistory_deactivate_cb, browser);
g_signal_handlers_disconnect_by_func (
app, formhistory_app_add_browser_cb, extension);
midori_browser_foreach (browser,
(GtkCallback)formhistory_deactivate_tab, extension);
g_object_set_data (G_OBJECT (browser), "FormHistoryExtension", NULL);
action = gtk_action_group_get_action (action_group, "FormHistoryToggleState");
if (action != NULL)
{
gtk_action_group_remove_action (action_group, action);
g_object_unref (action);
}
formhistory_private_destroy (priv);
}
static void
formhistory_activate_cb (MidoriExtension* extension,
MidoriApp* app)
{
const gchar* config_dir;
gchar* filename;
sqlite3* db;
char* errmsg = NULL, *errmsg2 = NULL;
KatzeArray* browsers;
MidoriBrowser* browser;
FormHistoryPriv* priv;
priv = formhistory_private_new ();
priv->master_password = NULL;
priv->master_password_canceled = 0;
formhistory_construct_popup_gui (priv);
config_dir = midori_extension_get_config_dir (extension);
if (config_dir != NULL)
katze_mkdir_with_parents (config_dir, 0700);
filename = g_build_filename (config_dir, "forms.db", NULL);
if (sqlite3_open (filename, &db) != SQLITE_OK)
{
if (config_dir != NULL)
g_warning (_("Failed to open database: %s\n"), sqlite3_errmsg (db));
sqlite3_close (db);
}
g_free (filename);
if ((sqlite3_exec (db, "CREATE TABLE IF NOT EXISTS "
"forms (domain text, field text, value text)",
NULL, NULL, &errmsg) == SQLITE_OK))
{
sqlite3_exec (db,
/* "PRAGMA synchronous = OFF; PRAGMA temp_store = MEMORY" */
"PRAGMA count_changes = OFF; PRAGMA journal_mode = TRUNCATE;",
NULL, NULL, &errmsg);
priv->db = db;
}
else
{
if (errmsg)
{
g_critical (_("Failed to execute database statement: %s\n"), errmsg);
sqlite3_free (errmsg);
if (errmsg2)
{
g_critical (_("Failed to execute database statement: %s\n"), errmsg2);
sqlite3_free (errmsg2);
}
}
sqlite3_close (db);
}
g_object_set_data (G_OBJECT (extension), "priv", priv);
browsers = katze_object_get_object (app, "browsers");
KATZE_ARRAY_FOREACH_ITEM (browser, browsers)
formhistory_app_add_browser_cb (app, browser, extension);
g_signal_connect (app, "add-browser",
G_CALLBACK (formhistory_app_add_browser_cb), extension);
g_object_unref (browsers);
}
static void
formhistory_preferences_response_cb (GtkWidget* dialog,
gint response_id,
MidoriExtension* extension)
{
GtkWidget* checkbox;
gboolean old_state;
gboolean new_state;
MidoriApp* app;
KatzeArray* browsers;
MidoriBrowser* browser;
if (response_id == GTK_RESPONSE_APPLY)
{
checkbox = g_object_get_data (G_OBJECT (dialog), "always-load-checkbox");
new_state = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox));
old_state = midori_extension_get_boolean (extension, "always-load");
if (old_state != new_state)
{
midori_extension_set_boolean (extension, "always-load", new_state);
app = midori_extension_get_app (extension);
browsers = katze_object_get_object (app, "browsers");
KATZE_ARRAY_FOREACH_ITEM (browser, browsers)
{
midori_browser_foreach (browser,
(GtkCallback)formhistory_deactivate_tab, extension);
g_signal_handlers_disconnect_by_func (
browser, formhistory_add_tab_cb, extension);
if (new_state)
{
midori_browser_foreach (browser,
(GtkCallback)formhistory_add_tab_foreach_cb, extension);
g_signal_connect (browser, "add-tab",
G_CALLBACK (formhistory_add_tab_cb), extension);
}
}
}
}
gtk_widget_destroy (dialog);
}
static void
formhistory_preferences_cb (MidoriExtension* extension)
{
GtkWidget* dialog;
GtkWidget* content_area;
GtkWidget* checkbox;
dialog = gtk_dialog_new ();
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_APPLY, GTK_RESPONSE_APPLY);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
checkbox = gtk_check_button_new_with_label (_("Only activate form history via hotkey (Ctrl+Shift+F) per tab"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbox),
!midori_extension_get_boolean (extension, "always-load"));
g_object_set_data (G_OBJECT (dialog), "always-load-checkbox", checkbox);
gtk_container_add (GTK_CONTAINER (content_area), checkbox);
/* FIXME: Add pref to disable password manager */
g_signal_connect (dialog,
"response",
G_CALLBACK (formhistory_preferences_response_cb),
extension);
gtk_widget_show_all (dialog);
}
static void
formhistory_toggle_state_cb (GtkAction* action,
MidoriBrowser* browser)
{
MidoriView* view = MIDORI_VIEW (midori_browser_get_current_tab (browser));
MidoriExtension* extension = g_object_get_data (G_OBJECT (browser), "FormHistoryExtension");
GtkWidget* web_view = midori_view_get_web_view (view);
if (g_signal_handler_find (web_view, G_SIGNAL_MATCH_FUNC,
g_signal_lookup ("window-object-cleared", MIDORI_TYPE_VIEW), 0, NULL,
formhistory_window_object_cleared_cb, extension))
{
formhistory_deactivate_tab (view, extension);
}
else
formhistory_add_tab_cb (browser, view, extension);
}
MidoriExtension*
extension_init (void)
{
MidoriExtension* extension;
extension = g_object_new (MIDORI_TYPE_EXTENSION,
"name", _("Form history filler"),
"description", _("Stores history of entered form data"),
"version", "2.0" MIDORI_VERSION_SUFFIX,
"authors", "Alexander V. Butenko <a.butenka@gmail.com>",
NULL);
midori_extension_install_boolean (extension, "always-load", TRUE);
g_signal_connect (extension, "activate",
G_CALLBACK (formhistory_activate_cb), NULL);
g_signal_connect (extension, "open-preferences",
G_CALLBACK (formhistory_preferences_cb), NULL);
return extension;
}

View File

@ -462,7 +462,7 @@ namespace HistoryList {
tab_added (browser, tab);
browser.add_tab.connect (tab_added);
browser.remove_tab.connect (tab_removed);
browser.switch_tab.connect (this.tab_changed);
browser.notify["tab"].connect (this.tab_changed);
}
void browser_removed (Midori.Browser browser) {
@ -491,7 +491,7 @@ namespace HistoryList {
browser.add_tab.disconnect (tab_added);
browser.remove_tab.disconnect (tab_removed);
browser.switch_tab.disconnect (this.tab_changed);
browser.notify["tab"].disconnect (this.tab_changed);
}
void tab_added (Midori.Browser browser, Midori.View view) {
@ -520,18 +520,21 @@ namespace HistoryList {
}
}
void tab_changed (Midori.View? old_view, Midori.View? new_view) {
void tab_changed (GLib.Object window, GLib.ParamSpec pspec) {
if(this.ignoreNextChange) {
this.ignoreNextChange = false;
} else {
Midori.Browser? browser = Midori.Browser.get_for_widget (new_view);
Midori.View? last_view
= browser.get_data<Midori.View?> ("history-list-last-change");
Midori.Browser browser = window as Midori.Browser;
Midori.View view = null;
Midori.View last_view = null;
browser.get ("tab", ref view);
last_view = browser.get_data<Midori.View?> ("history-list-last-change");
if (last_view != null) {
this.tab_list_resort (browser, last_view);
}
browser.set_data<Midori.View?> ("history-list-last-change", new_view);
browser.set_data<Midori.View?> ("history-list-last-change", view);
}
}

View File

@ -180,6 +180,8 @@ shortcuts_get_preferences_dialog (MidoriExtension* extension)
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
#endif
NULL);
g_signal_connect (dialog, "destroy",
G_CALLBACK (gtk_widget_destroyed), &dialog);
gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_PROPERTIES);
sokoke_widget_get_text_size (dialog, "M", &width, &height);
gtk_window_set_default_size (GTK_WINDOW (dialog), width * 52, height * 24);

View File

@ -66,14 +66,11 @@ statusbar_features_browser_notify_tab_cb (MidoriBrowser* browser,
GtkWidget* combobox)
{
MidoriView* view = MIDORI_VIEW (midori_browser_get_current_tab (browser));
gchar* text;
if (view == NULL)
return;
text = g_strdup_printf ("%d%%", (gint)(midori_view_get_zoom_level (view) * 100));
gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (combobox))), text);
g_free (text);
gchar* zoom_level_text = g_strdup_printf ("%d%%",
(gint)(midori_view_get_zoom_level (view) * 100));
gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (combobox))),
zoom_level_text);
g_free (zoom_level_text);
}
static void
@ -107,81 +104,6 @@ statusbar_features_zoom_level_changed_cb (GtkWidget* combobox,
midori_view_set_zoom_level (view, zoom_level / 100.0);
}
GtkWidget*
statusbar_features_property_proxy (MidoriWebSettings* settings,
const gchar* property,
GtkWidget* toolbar)
{
const gchar* kind = NULL;
GtkWidget* button;
GtkWidget* image;
if (!strcmp (property, "auto-load-images")
|| !strcmp (property, "enable-scripts")
|| !strcmp (property, "enable-plugins"))
kind = "toggle";
else if (!strcmp (property, "identify-as"))
kind = "custom-user-agent";
else if (strstr (property, "font") != NULL)
kind = "font";
else if (!strcmp (property, "zoom-level"))
{
MidoriBrowser* browser = midori_browser_get_for_widget (toolbar);
gint i;
button = gtk_combo_box_text_new_with_entry ();
gtk_entry_set_width_chars (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (button))), 4);
for (i = 0; i < G_N_ELEMENTS (zoom_levels); i++)
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (button), zoom_levels[i].label);
g_signal_connect (button, "changed",
G_CALLBACK (statusbar_features_zoom_level_changed_cb), browser);
g_signal_connect (browser, "notify::tab",
G_CALLBACK (statusbar_features_browser_notify_tab_cb), button);
statusbar_features_browser_notify_tab_cb (browser, NULL, button);
return button;
}
button = katze_property_proxy (settings, property, kind);
if (GTK_IS_BIN (button))
{
GtkWidget* label = gtk_bin_get_child (GTK_BIN (button));
if (GTK_IS_LABEL (label))
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
}
if (!strcmp (property, "auto-load-images"))
{
g_object_set_data (G_OBJECT (button), "feature-label", _("Images"));
image = gtk_image_new_from_stock (STOCK_IMAGE, GTK_ICON_SIZE_MENU);
gtk_button_set_image (GTK_BUTTON (button), image);
gtk_widget_set_tooltip_text (button, _("Load images automatically"));
statusbar_features_toolbar_notify_toolbar_style_cb (toolbar, NULL, button);
g_signal_connect (toolbar, "notify::toolbar-style",
G_CALLBACK (statusbar_features_toolbar_notify_toolbar_style_cb), button);
}
if (!strcmp (property, "enable-scripts"))
{
g_object_set_data (G_OBJECT (button), "feature-label", _("Scripts"));
image = gtk_image_new_from_stock (STOCK_SCRIPT, GTK_ICON_SIZE_MENU);
gtk_button_set_image (GTK_BUTTON (button), image);
gtk_widget_set_tooltip_text (button, _("Enable scripts"));
statusbar_features_toolbar_notify_toolbar_style_cb (toolbar, NULL, button);
g_signal_connect (toolbar, "notify::toolbar-style",
G_CALLBACK (statusbar_features_toolbar_notify_toolbar_style_cb), button);
}
else if (!strcmp (property, "enable-plugins"))
{
if (!midori_web_settings_has_plugin_support ())
gtk_widget_hide (button);
g_object_set_data (G_OBJECT (button), "feature-label", _("Netscape plugins"));
image = gtk_image_new_from_stock (STOCK_PLUGINS, GTK_ICON_SIZE_MENU);
gtk_button_set_image (GTK_BUTTON (button), image);
gtk_widget_set_tooltip_text (button, _("Enable Netscape plugins"));
statusbar_features_toolbar_notify_toolbar_style_cb (toolbar, NULL, button);
g_signal_connect (toolbar, "notify::toolbar-style",
G_CALLBACK (statusbar_features_toolbar_notify_toolbar_style_cb), button);
}
return button;
}
static void
statusbar_features_app_add_browser_cb (MidoriApp* app,
MidoriBrowser* browser,
@ -192,8 +114,8 @@ statusbar_features_app_add_browser_cb (MidoriApp* app,
MidoriWebSettings* settings;
GtkWidget* toolbar;
GtkWidget* button;
GtkWidget* image;
gsize i;
gchar** filters;
/* FIXME: Monitor each view and modify its settings individually
instead of merely replicating the global preferences. */
@ -202,37 +124,48 @@ statusbar_features_app_add_browser_cb (MidoriApp* app,
bbox = gtk_hbox_new (FALSE, 0);
settings = midori_browser_get_settings (browser);
toolbar = katze_object_get_object (browser, "navigationbar");
filters = midori_extension_get_string_list (extension, "items", NULL);
if (filters && *filters)
{
i = 0;
while (filters[i] != NULL)
{
button = statusbar_features_property_proxy (settings, filters[i], toolbar);
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
i++;
}
}
else
{
button = statusbar_features_property_proxy (settings, "auto-load-images", toolbar);
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
button = statusbar_features_property_proxy (settings, "enable-scripts", toolbar);
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
button = statusbar_features_property_proxy (settings, "enable-plugins", toolbar);
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
button = statusbar_features_property_proxy (settings, "identify-as", toolbar);
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
button = statusbar_features_property_proxy (settings, "zoom-level", toolbar);
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
}
button = katze_property_proxy (settings, "auto-load-images", "toggle");
g_object_set_data (G_OBJECT (button), "feature-label", _("Images"));
image = gtk_image_new_from_stock (STOCK_IMAGE, GTK_ICON_SIZE_MENU);
gtk_button_set_image (GTK_BUTTON (button), image);
gtk_widget_set_tooltip_text (button, _("Load images automatically"));
statusbar_features_toolbar_notify_toolbar_style_cb (toolbar, NULL, button);
g_signal_connect (toolbar, "notify::toolbar-style",
G_CALLBACK (statusbar_features_toolbar_notify_toolbar_style_cb), button);
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
button = katze_property_proxy (settings, "enable-scripts", "toggle");
g_object_set_data (G_OBJECT (button), "feature-label", _("Scripts"));
image = gtk_image_new_from_stock (STOCK_SCRIPTS, GTK_ICON_SIZE_MENU);
gtk_button_set_image (GTK_BUTTON (button), image);
gtk_widget_set_tooltip_text (button, _("Enable scripts"));
statusbar_features_toolbar_notify_toolbar_style_cb (toolbar, NULL, button);
g_signal_connect (toolbar, "notify::toolbar-style",
G_CALLBACK (statusbar_features_toolbar_notify_toolbar_style_cb), button);
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
button = katze_property_proxy (settings, "enable-plugins", "toggle");
g_object_set_data (G_OBJECT (button), "feature-label", _("Netscape plugins"));
image = gtk_image_new_from_stock (STOCK_PLUGINS, GTK_ICON_SIZE_MENU);
gtk_button_set_image (GTK_BUTTON (button), image);
gtk_widget_set_tooltip_text (button, _("Enable Netscape plugins"));
statusbar_features_toolbar_notify_toolbar_style_cb (toolbar, NULL, button);
g_signal_connect (toolbar, "notify::toolbar-style",
G_CALLBACK (statusbar_features_toolbar_notify_toolbar_style_cb), button);
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
button = katze_property_proxy (settings, "identify-as", "custom-user-agent");
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
button = gtk_combo_box_text_new_with_entry ();
gtk_entry_set_width_chars (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (button))), 4);
for (i = 0; i < G_N_ELEMENTS (zoom_levels); i++)
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (button), zoom_levels[i].label);
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
g_signal_connect (button, "changed",
G_CALLBACK (statusbar_features_zoom_level_changed_cb), browser);
g_signal_connect (browser, "notify::tab",
G_CALLBACK (statusbar_features_browser_notify_tab_cb), button);
gtk_widget_show_all (bbox);
gtk_box_pack_end (GTK_BOX (statusbar), bbox, FALSE, FALSE, 3);
gtk_box_pack_start (GTK_BOX (statusbar), bbox, FALSE, FALSE, 3);
g_object_unref (statusbar);
g_object_unref (toolbar);
g_strfreev (filters);
g_signal_connect (extension, "deactivate",
G_CALLBACK (statusbar_features_deactivate_cb), bbox);
}
@ -261,7 +194,6 @@ extension_init (void)
"version", "0.1" MIDORI_VERSION_SUFFIX,
"authors", "Christian Dywan <christian@twotoasts.de>",
NULL);
midori_extension_install_string_list (extension, "items", NULL, G_MAXSIZE);
g_signal_connect (extension, "activate",
G_CALLBACK (statusbar_features_activate_cb), NULL);

View File

@ -143,6 +143,7 @@ midori_extension_cursor_or_row_changed_cb (GtkTreeView* treeview,
/* Nothing to do */
}
#if GTK_CHECK_VERSION (2, 12, 0)
static gboolean
tab_panel_treeview_query_tooltip_cb (GtkWidget* treeview,
gint x,
@ -170,6 +171,7 @@ tab_panel_treeview_query_tooltip_cb (GtkWidget* treeview,
return TRUE;
}
#endif
static void
midori_extension_row_activated_cb (GtkTreeView* treeview,
@ -229,12 +231,12 @@ midori_extension_button_release_event_cb (GtkWidget* widget,
if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget),
event->x, event->y, NULL, &column, NULL, NULL)
&& column == gtk_tree_view_get_column (GTK_TREE_VIEW (widget), 1))
midori_browser_remove_tab (browser, view);
gtk_widget_destroy (view);
else
midori_browser_set_current_tab (browser, view);
}
else if (event->button == 2)
midori_browser_remove_tab (midori_browser_get_for_widget (widget), view);
gtk_widget_destroy (view);
else
tab_panel_popup (widget, event, view);
@ -417,7 +419,8 @@ tab_panel_browser_add_tab_cb (MidoriBrowser* browser,
GtkWidget* view,
MidoriExtension* extension)
{
gint page = midori_browser_page_num (browser, view);
GtkWidget* notebook = katze_object_get_object (browser, "notebook");
gint page = gtk_notebook_page_num (GTK_NOTEBOOK (notebook), view);
MidoriWebSettings* settings = midori_browser_get_settings (browser);
gboolean minimized = katze_object_get_boolean (view, "minimized");
GdkPixbuf* icon = midori_view_get_icon (MIDORI_VIEW (view));
@ -465,6 +468,8 @@ tab_panel_browser_add_tab_cb (MidoriBrowser* browser,
g_signal_connect (view, "notify::title",
G_CALLBACK (tab_panel_view_notify_title_cb), extension);
}
g_object_unref (notebook);
}
static void
@ -532,9 +537,11 @@ tab_panel_app_add_browser_cb (MidoriApp* app,
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_show_expanders (GTK_TREE_VIEW (treeview), FALSE);
#if GTK_CHECK_VERSION (2, 12, 0)
g_signal_connect (treeview, "query-tooltip",
G_CALLBACK (tab_panel_treeview_query_tooltip_cb), NULL);
gtk_widget_set_has_tooltip (treeview, TRUE);
#endif
column = gtk_tree_view_column_new ();
renderer_pixbuf = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE);

View File

@ -46,6 +46,8 @@ static const GtkTargetEntry tb_editor_dnd_targets[] =
};
static const gint tb_editor_dnd_targets_len = G_N_ELEMENTS(tb_editor_dnd_targets);
static void tb_editor_browser_populate_tool_menu_cb(MidoriBrowser *browser, GtkWidget *menu, MidoriExtension *ext);
static void tb_editor_browser_populate_toolbar_menu_cb(MidoriBrowser *browser, GtkWidget *menu,
MidoriExtension *ext);
@ -56,6 +58,7 @@ static void tb_editor_deactivate_cb(MidoriExtension *extension, MidoriBrowser *b
{
MidoriApp *app = midori_extension_get_app(extension);
g_signal_handlers_disconnect_by_func(browser, tb_editor_browser_populate_tool_menu_cb, extension);
g_signal_handlers_disconnect_by_func(browser, tb_editor_browser_populate_toolbar_menu_cb, extension);
g_signal_handlers_disconnect_by_func(extension, tb_editor_deactivate_cb, browser);
g_signal_handlers_disconnect_by_func(app, tb_editor_app_add_browser_cb, extension);
@ -104,12 +107,7 @@ static GSList *tb_editor_array_to_list(const gchar **items)
name = items;
while (*name != NULL)
{
#ifdef HAVE_GRANITE
/* A "new tab" button is already part of the notebook */
if (*name[0] != '\0' && strcmp (*name, "TabNew"))
#else
if (*name[0] != '\0')
#endif
list = g_slist_append(list, g_strdup(*name));
name++;
}
@ -396,7 +394,11 @@ static TBEditorWidget *tb_editor_create_dialog(MidoriBrowser *parent)
GTK_WINDOW(parent),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
#if !GTK_CHECK_VERSION(3,0,0)
vbox = (GTK_DIALOG(dialog))->vbox;
#else
vbox = GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog)));
#endif
gtk_box_set_spacing(GTK_BOX(vbox), 6);
gtk_widget_set_name(dialog, "GeanyDialog");
gtk_window_set_default_size(GTK_WINDOW(dialog), -1, 400);
@ -408,7 +410,7 @@ static TBEditorWidget *tb_editor_create_dialog(MidoriBrowser *parent)
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
label = gtk_label_new(
_("Select items to be displayed on the toolbar. Items can be reordered by drag and drop."));
_("Select items to be displayed on the toolbar. Items can be reodered by drag and drop."));
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
tree_available = gtk_tree_view_new();
@ -576,6 +578,17 @@ static void tb_editor_menu_configure_toolbar_activate_cb(GtkWidget *menuitem, Mi
g_free(tbw);
}
static void tb_editor_browser_populate_tool_menu_cb(MidoriBrowser *browser, GtkWidget *menu, MidoriExtension *ext)
{
GtkWidget *menuitem;
menuitem = gtk_menu_item_new_with_mnemonic (_("Customize _Toolbar..."));
g_signal_connect (menuitem, "activate",
G_CALLBACK (tb_editor_menu_configure_toolbar_activate_cb), browser);
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
}
static void tb_editor_browser_populate_toolbar_menu_cb(MidoriBrowser *browser, GtkWidget *menu,
MidoriExtension *ext)
{
@ -585,7 +598,7 @@ static void tb_editor_browser_populate_toolbar_menu_cb(MidoriBrowser *browser, G
separator = gtk_separator_menu_item_new ();
gtk_widget_show (separator);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), separator);
menuitem = gtk_menu_item_new_with_mnemonic (_("_Customize Toolbar…"));
menuitem = gtk_menu_item_new_with_mnemonic (_("_Customize..."));
g_signal_connect (menuitem, "activate",
G_CALLBACK (tb_editor_menu_configure_toolbar_activate_cb), browser);
gtk_widget_show (menuitem);
@ -594,6 +607,7 @@ static void tb_editor_browser_populate_toolbar_menu_cb(MidoriBrowser *browser, G
static void tb_editor_app_add_browser_cb(MidoriApp *app, MidoriBrowser *browser, MidoriExtension *ext)
{
g_signal_connect(browser, "populate-tool-menu", G_CALLBACK(tb_editor_browser_populate_tool_menu_cb), ext);
g_signal_connect(browser, "populate-toolbar-menu", G_CALLBACK(tb_editor_browser_populate_toolbar_menu_cb), ext);
g_signal_connect(ext, "deactivate", G_CALLBACK(tb_editor_deactivate_cb), browser);
}

View File

@ -28,7 +28,8 @@ web_cache_get_cache_dir (void)
{
static gchar* cache_dir = NULL;
if (!cache_dir)
cache_dir = g_build_filename (midori_paths_get_cache_dir (), "web", NULL);
cache_dir = g_build_filename (g_get_user_cache_dir (),
PACKAGE_NAME, "web", NULL);
return cache_dir;
}

View File

@ -28,16 +28,13 @@ for extension in extensions:
continue
source = extension
if bld.env['platform'] == 'win32' and target in ['external-download-manager']:
continue
obj = bld.new_task_gen ('cc', 'shlib')
obj.target = target
obj.includes = '.. ../katze ../midori'
obj.includes = '..'
obj.source = source
obj.uselib = 'UNIQUE LIBSOUP GIO GTK SQLITE WEBKIT LIBXML HILDON'
obj.vapi_dirs = '../midori ../katze'
obj.packages = 'glib-2.0 gio-2.0 libsoup-2.4 midori midori-core katze'
obj.vapi_dirs = '../midori'
obj.packages = 'glib-2.0 gio-2.0 libsoup-2.4 midori'
if bld.env['HAVE_GTK3']:
obj.packages += ' gtk+-3.0 webkitgtk-3.0'
else:

View File

Before

Width:  |  Height:  |  Size: 832 B

After

Width:  |  Height:  |  Size: 832 B

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -41,4 +41,4 @@ def add_image (bld, category, name):
add_image (bld, 'categories', 'extension')
add_image (bld, 'apps', 'midori')
add_image (bld, 'status', 'internet-news-reader')
add_image (bld, 'status', 'news-feed')

View File

@ -27,9 +27,9 @@ sokoke_on_entry_focus_in_event (GtkEntry* entry,
g_object_get_data (G_OBJECT (entry), "sokoke_has_default"));
if (has_default)
{
gtk_entry_set_text (entry, "");
g_object_set_data (G_OBJECT (entry), "sokoke_has_default",
GINT_TO_POINTER (0));
gtk_entry_set_text (entry, "");
sokoke_widget_set_pango_font_style (GTK_WIDGET (entry),
PANGO_STYLE_NORMAL);
}
@ -46,9 +46,9 @@ sokoke_on_entry_focus_out_event (GtkEntry* entry,
{
const gchar* default_text = (const gchar*)g_object_get_data (
G_OBJECT (entry), "sokoke_default_text");
gtk_entry_set_text (entry, default_text);
g_object_set_data (G_OBJECT (entry),
"sokoke_has_default", GINT_TO_POINTER (1));
gtk_entry_set_text (entry, default_text);
sokoke_widget_set_pango_font_style (GTK_WIDGET (entry),
PANGO_STYLE_ITALIC);
}
@ -71,15 +71,14 @@ gtk_entry_set_placeholder_text (GtkEntry* entry,
const gchar* default_text)
{
/* Note: The default text initially overwrites any previous text */
gchar* old_value = g_object_get_data (G_OBJECT (entry), "sokoke_default_text");
g_object_set_data (G_OBJECT (entry), "sokoke_default_text", (gpointer)default_text);
if (default_text == NULL)
g_object_set_data (G_OBJECT (entry), "sokoke_has_default", GINT_TO_POINTER (0));
else if (!old_value)
gchar* old_value = g_object_get_data (G_OBJECT (entry),
"sokoke_default_text");
if (!old_value)
{
g_object_set_data (G_OBJECT (entry), "sokoke_has_default", GINT_TO_POINTER (1));
sokoke_widget_set_pango_font_style (GTK_WIDGET (entry), PANGO_STYLE_ITALIC);
g_object_set_data (G_OBJECT (entry), "sokoke_has_default",
GINT_TO_POINTER (1));
sokoke_widget_set_pango_font_style (GTK_WIDGET (entry),
PANGO_STYLE_ITALIC);
gtk_entry_set_text (entry, default_text);
g_signal_connect (entry, "drag-data-received",
G_CALLBACK (sokoke_on_entry_drag_data_received), NULL);
@ -90,19 +89,55 @@ gtk_entry_set_placeholder_text (GtkEntry* entry,
}
else if (!gtk_widget_has_focus (GTK_WIDGET (entry)))
{
gint has_default = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (entry), "sokoke_has_default"));
gint has_default = GPOINTER_TO_INT (
g_object_get_data (G_OBJECT (entry), "sokoke_has_default"));
if (has_default)
{
gtk_entry_set_text (entry, default_text);
sokoke_widget_set_pango_font_style (GTK_WIDGET (entry), PANGO_STYLE_ITALIC);
sokoke_widget_set_pango_font_style (GTK_WIDGET (entry),
PANGO_STYLE_ITALIC);
}
}
}
const gchar*
gtk_entry_get_placeholder_text (GtkEntry* entry)
{
return g_object_get_data (G_OBJECT (entry), "sokoke_default_text");
g_object_set_data (G_OBJECT (entry), "sokoke_default_text",
(gpointer)default_text);
}
#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

@ -6,7 +6,7 @@
G_BEGIN_DECLS
#if GTK_CHECK_VERSION (3, 2, 0) && defined (GTK_DISABLE_DEPRECATED)
#if GTK_CHECK_VERSION (3, 2, 0)
#define GTK_TYPE_VBOX GTK_TYPE_BOX
#define GtkVBox GtkBox
#define GtkVBoxClass GtkBoxClass
@ -39,6 +39,25 @@ G_BEGIN_DECLS
#define g_format_size(sz) g_format_size_for_display ((goffset)sz)
#endif
#if !GTK_CHECK_VERSION (2, 14, 0)
#define gtk_dialog_get_content_area(dlg) dlg->vbox
#define gtk_dialog_get_action_area(dlg) dlg->action_area
#define gtk_widget_get_window(wdgt) wdgt->window
#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
#endif
#if !GTK_CHECK_VERSION (2, 16, 0)
#define GTK_ACTIVATABLE GTK_WIDGET
#define gtk_activatable_get_related_action gtk_widget_get_action
#define gtk_menu_item_set_label(menuitem, label) \
gtk_label_set_label (GTK_LABEL (GTK_BIN (menuitem)->child), \
label ? label : "");
#define gtk_image_menu_item_set_always_show_image(menuitem, yesno) ()
#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)
@ -70,10 +89,24 @@ G_BEGIN_DECLS
#if !GTK_CHECK_VERSION (3, 2, 0) && defined (HAVE_HILDON_2_2)
#define gtk_entry_set_placeholder_text hildon_gtk_entry_set_placeholder_text
#define gtk_entry_get_placeholder_text hildon_gtk_entry_get_placeholder_text
#elif !GTK_CHECK_VERSION (3, 2, 0)
void gtk_entry_set_placeholder_text (GtkEntry* entry, const gchar* text);
const gchar* gtk_entry_get_placeholder_text (GtkEntry* entry);
#define gtk_entry_set_placeholder_text sokoke_entry_set_default_text
#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
#if !GTK_CHECK_VERSION (2, 24 ,0)
@ -116,10 +149,6 @@ G_BEGIN_DECLS
#define GDK_KEY_Return GDK_Return
#endif
#ifndef GDK_IS_X11_DISPLAY
#define GDK_IS_X11_DISPLAY(display) TRUE
#endif
G_END_DECLS
#endif

View File

@ -74,13 +74,6 @@ GList* kalistglobal;
static void
katze_array_finalize (GObject* object);
static void
_katze_array_update (KatzeArray* array)
{
g_object_set_data (G_OBJECT (array), "last-update",
GINT_TO_POINTER (time (NULL)));
}
static void
_katze_array_add_item (KatzeArray* array,
gpointer item)
@ -91,7 +84,6 @@ _katze_array_add_item (KatzeArray* array,
katze_item_set_parent (item, array);
array->items = g_list_append (array->items, item);
_katze_array_update (array);
}
static void
@ -103,7 +95,6 @@ _katze_array_remove_item (KatzeArray* array,
if (KATZE_IS_ITEM (item))
katze_item_set_parent (item, NULL);
g_object_unref (item);
_katze_array_update (array);
}
static void
@ -113,7 +104,6 @@ _katze_array_move_item (KatzeArray* array,
{
array->items = g_list_remove (array->items, item);
array->items = g_list_insert (array->items, item, position);
_katze_array_update (array);
}
static void
@ -122,10 +112,9 @@ _katze_array_clear (KatzeArray* array)
GObject* item;
while ((item = g_list_nth_data (array->items, 0)))
g_signal_emit (array, signals[REMOVE_ITEM], 0, item);
katze_array_remove_item (array, item);
g_list_free (array->items);
array->items = NULL;
_katze_array_update (array);
}
static void
@ -203,7 +192,7 @@ katze_array_class_init (KatzeArrayClass* class)
"update",
G_TYPE_FROM_CLASS (class),
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
G_STRUCT_OFFSET (KatzeArrayClass, update),
0,
0,
NULL,
g_cclosure_marshal_VOID__VOID,
@ -216,7 +205,6 @@ katze_array_class_init (KatzeArrayClass* class)
class->remove_item = _katze_array_remove_item;
class->move_item = _katze_array_move_item;
class->clear = _katze_array_clear;
class->update = _katze_array_update;
}
static void
@ -229,11 +217,14 @@ katze_array_init (KatzeArray* array)
static void
katze_array_finalize (GObject* object)
{
KatzeArray* array = KATZE_ARRAY (object);
GList* items;
KatzeArray* array;
guint i;
gpointer item;
for (items = array->items; items; items = g_list_next (items))
g_object_unref (items->data);
array = KATZE_ARRAY (object);
i = 0;
while ((item = g_list_nth_data (array->items, i++)))
g_object_unref (item);
g_list_free (array->items);
G_OBJECT_CLASS (katze_array_parent_class)->finalize (object);
@ -373,44 +364,37 @@ katze_array_get_item_index (KatzeArray* array,
/**
* katze_array_find_token:
* @array: a #KatzeArray
* @token: a token string, or "token keywords" string
* @token: a token string
*
* Looks up an item in the array which has the specified token.
*
* This function will fail if the type of the list
* is not based on #KatzeItem children.
* This function will silently fail if the type of the list
* is not based on #GObject and only #KatzeItem children
* are checked for their token, any other objects are skipped.
*
* Note that @token is by definition unique to one item.
*
* Since 0.4.4 @token can be a "token keywords" string.
*
* Return value: an item, or %NULL
**/
gpointer
katze_array_find_token (KatzeArray* array,
const gchar* token)
{
goffset token_length;
GList* items;
guint i;
gpointer item;
g_return_val_if_fail (KATZE_IS_ARRAY (array), NULL);
g_return_val_if_fail (katze_array_is_a (array, KATZE_TYPE_ITEM), NULL);
g_return_val_if_fail (token != NULL, NULL);
token_length = strchr (token, ' ') - token;
if (token_length < 1)
token_length = strlen (token);
for (items = array->items; items; items = g_list_next (items))
i = 0;
while ((item = g_list_nth_data (array->items, i++)))
{
const gchar* found_token = ((KatzeItem*)items->data)->token;
if (found_token != NULL)
{
guint bigger_item = strlen (found_token) > token_length ? strlen (found_token) : token_length;
const gchar* found_token;
if (strncmp (token, found_token, bigger_item) == 0)
return items->data;
}
if (!KATZE_IS_ITEM (item))
continue;
found_token = ((KatzeItem*)item)->token;
if (!g_strcmp0 (found_token, token))
return item;
}
return NULL;
}
@ -422,8 +406,9 @@ katze_array_find_token (KatzeArray* array,
*
* Looks up an item in the array which has the specified URI.
*
* This function will fail if the type of the list
* is not based on #KatzeItem children.
* This function will silently fail if the type of the list
* is not based on #GObject and only #KatzeItem children
* are checked for their token, any other objects are skipped.
*
* Return value: an item, or %NULL
*
@ -433,17 +418,19 @@ gpointer
katze_array_find_uri (KatzeArray* array,
const gchar* uri)
{
GList* items;
guint i;
gpointer item;
g_return_val_if_fail (KATZE_IS_ARRAY (array), NULL);
g_return_val_if_fail (katze_array_is_a (array, KATZE_TYPE_ITEM), NULL);
g_return_val_if_fail (uri != NULL, NULL);
for (items = array->items; items; items = g_list_next (items))
i = 0;
while ((item = g_list_nth_data (array->items, i++)))
{
const gchar* found_uri = ((KatzeItem*)items->data)->uri;
if (found_uri != NULL && !strcmp (found_uri, uri))
return items->data;
const gchar* found_uri;
if (!KATZE_IS_ITEM (item))
continue;
found_uri = ((KatzeItem*)item)->uri;
if (!g_strcmp0 (found_uri, uri))
return item;
}
return NULL;
}

View File

@ -355,16 +355,11 @@ katze_array_action_generate_menu (KatzeArrayAction* array_action,
gint summand;
KatzeItem* item;
GtkWidget* menuitem;
const gchar* icon_name;
GdkPixbuf* icon;
GtkWidget* image;
GtkWidget* submenu;
g_return_if_fail (KATZE_IS_ARRAY_ACTION (array_action));
g_return_if_fail (KATZE_IS_ITEM (array));
g_return_if_fail (GTK_IS_MENU_SHELL (menu));
g_return_if_fail (GTK_IS_TOOL_ITEM (proxy)
|| GTK_IS_MENU_ITEM (proxy)
|| GTK_IS_WINDOW (proxy));
if (!KATZE_IS_ARRAY (array))
return;
@ -390,7 +385,18 @@ katze_array_action_generate_menu (KatzeArrayAction* array_action,
}
menuitem = katze_image_menu_item_new_ellipsized (
katze_item_get_name (item));
image = katze_item_get_image (item);
if ((icon_name = katze_item_get_icon (item)) && *icon_name)
image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
else
{
if (KATZE_ITEM_IS_FOLDER (item))
icon = gtk_widget_render_icon (menuitem,
GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU, NULL);
else
icon = katze_load_cached_icon (katze_item_get_uri (item), proxy);
image = gtk_image_new_from_pixbuf (icon);
g_object_unref (icon);
}
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
gtk_image_menu_item_set_always_show_image (
GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
@ -400,13 +406,8 @@ katze_array_action_generate_menu (KatzeArrayAction* array_action,
{
submenu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
/* Make sure menu appears to contain items */
gtk_menu_shell_append (GTK_MENU_SHELL (submenu),
gtk_separator_menu_item_new ());
g_signal_connect (menuitem, "select",
G_CALLBACK (katze_array_action_menu_item_select_cb), array_action);
g_signal_connect (menuitem, "activate",
G_CALLBACK (katze_array_action_menu_item_select_cb), array_action);
}
else
{
@ -420,39 +421,21 @@ katze_array_action_generate_menu (KatzeArrayAction* array_action,
}
}
static gboolean
katze_array_action_menu_item_need_update (KatzeArrayAction* array_action,
GtkWidget* proxy)
{
GtkWidget* menu;
KatzeArray* array;
gint last_array_update, last_proxy_update;
gboolean handled;
array = g_object_get_data (G_OBJECT (proxy), "KatzeItem");
/* last-update is set on all arrays; consider public API */
last_array_update = GPOINTER_TO_INT (
g_object_get_data (G_OBJECT (array), "last-update"));
last_proxy_update = GPOINTER_TO_INT (
g_object_get_data (G_OBJECT (proxy), "last-update"));
if (last_proxy_update > last_array_update)
return FALSE;
menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy));
gtk_container_foreach (GTK_CONTAINER (menu),
(GtkCallback)(gtk_widget_destroy), NULL);
katze_array_action_generate_menu (array_action, array, GTK_MENU_SHELL (menu), proxy);
g_signal_emit (array_action, signals[POPULATE_FOLDER], 0, menu, array, &handled);
g_object_set_data (G_OBJECT (proxy), "last-update",
GINT_TO_POINTER (time (NULL)));
return TRUE;
}
static void
katze_array_action_menu_item_select_cb (GtkWidget* proxy,
KatzeArrayAction* array_action)
{
katze_array_action_menu_item_need_update (array_action, proxy);
GtkWidget* menu;
KatzeArray* array;
gboolean handled;
menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy));
gtk_container_foreach (GTK_CONTAINER (menu),
(GtkCallback)(gtk_widget_destroy), NULL);
array = g_object_get_data (G_OBJECT (proxy), "KatzeItem");
katze_array_action_generate_menu (array_action, array, GTK_MENU_SHELL (menu), proxy);
g_signal_emit (array_action, signals[POPULATE_FOLDER], 0, menu, array, &handled);
}
static void
@ -475,21 +458,20 @@ katze_array_action_proxy_clicked_cb (GtkWidget* proxy,
KatzeArray* array;
gboolean handled = FALSE;
array = (KatzeArray*)g_object_get_data (G_OBJECT (proxy), "KatzeItem");
if (GTK_IS_MENU_ITEM (proxy))
{
if (katze_array_action_menu_item_need_update (array_action, proxy))
{
g_signal_emit (array_action, signals[POPULATE_FOLDER], 0,
gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)),
array, &handled);
if (!handled)
g_signal_emit (array_action, signals[POPULATE_POPUP], 0,
gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)));
}
g_object_set_data (G_OBJECT (proxy), "KatzeItem", array_action->array);
katze_array_action_menu_item_select_cb (proxy, array_action);
g_signal_emit (array_action, signals[POPULATE_FOLDER], 0,
gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)),
array_action->array, &handled);
if (!handled)
g_signal_emit (array_action, signals[POPULATE_POPUP], 0,
gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)));
return;
}
array = (KatzeArray*)g_object_get_data (G_OBJECT (proxy), "KatzeArray");
if (KATZE_IS_ITEM (array) && katze_item_get_uri ((KatzeItem*)array))
{
katze_array_action_activate_item (array_action, KATZE_ITEM (array), 1);
@ -570,6 +552,7 @@ katze_array_action_item_notify_cb (KatzeItem* item,
const gchar* property;
const gchar* title;
const gchar* desc;
GdkPixbuf* icon;
GtkWidget* image;
if (!G_IS_PARAM_SPEC_STRING (pspec))
@ -596,13 +579,16 @@ katze_array_action_item_notify_cb (KatzeItem* item,
}
else if (KATZE_ITEM_IS_BOOKMARK (item) && !strcmp (property, "uri"))
{
image = katze_item_get_image (item);
icon = katze_load_cached_icon (katze_item_get_uri (item), GTK_WIDGET (toolitem));
image = gtk_image_new_from_pixbuf (icon);
g_object_unref (icon);
gtk_widget_show (image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image);
}
else if (!strcmp (property, "icon"))
{
image = katze_item_get_image (item);
image = gtk_image_new_from_icon_name (katze_item_get_icon (item),
GTK_ICON_SIZE_MENU);
gtk_widget_show (image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image);
}
@ -614,12 +600,25 @@ katze_array_action_proxy_create_menu_proxy_cb (GtkWidget* proxy,
{
KatzeArrayAction* array_action;
GtkWidget* menuitem;
const gchar* icon_name;
GtkWidget* image;
GdkPixbuf* icon;
array_action = g_object_get_data (G_OBJECT (proxy), "KatzeArrayAction");
menuitem = katze_image_menu_item_new_ellipsized (
katze_item_get_name (item));
image = katze_item_get_image (item);
if ((icon_name = katze_item_get_icon (item)) && *icon_name)
image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
else
{
if (KATZE_ITEM_IS_FOLDER (item))
icon = gtk_widget_render_icon (menuitem,
GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU, NULL);
else
icon = katze_load_cached_icon (katze_item_get_uri (item), proxy);
image = gtk_image_new_from_pixbuf (icon);
g_object_unref (icon);
}
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
gtk_image_menu_item_set_always_show_image (
GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
@ -675,6 +674,7 @@ katze_array_action_create_tool_item_for (KatzeArrayAction* array_action,
const gchar* uri;
const gchar* desc;
GtkToolItem* toolitem;
GdkPixbuf* icon;
GtkWidget* image;
GtkWidget* label;
@ -686,12 +686,20 @@ katze_array_action_create_tool_item_for (KatzeArrayAction* array_action,
return gtk_separator_tool_item_new ();
if (KATZE_ITEM_IS_FOLDER (item))
{
toolitem = gtk_toggle_tool_button_new ();
icon = gtk_widget_render_icon (GTK_WIDGET (toolitem),
GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU, NULL);
}
else
{
toolitem = gtk_tool_button_new (NULL, "");
icon = katze_load_cached_icon (uri, GTK_WIDGET (toolitem));
}
g_signal_connect (toolitem, "create-menu-proxy",
G_CALLBACK (katze_array_action_proxy_create_menu_proxy_cb), item);
image = katze_item_get_image (item);
image = gtk_image_new_from_pixbuf (icon);
g_object_unref (icon);
gtk_widget_show (image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image);
label = gtk_label_new (NULL);
@ -731,9 +739,6 @@ static void
katze_array_action_connect_proxy (GtkAction* action,
GtkWidget* proxy)
{
KatzeArrayAction* array_action = KATZE_ARRAY_ACTION (action);
g_object_set_data (G_OBJECT (proxy), "KatzeItem", array_action->array);
GTK_ACTION_CLASS (katze_array_action_parent_class)->connect_proxy (
action, proxy);
@ -745,10 +750,9 @@ katze_array_action_connect_proxy (GtkAction* action,
else if (GTK_IS_MENU_ITEM (proxy))
{
gtk_menu_item_set_submenu (GTK_MENU_ITEM (proxy), gtk_menu_new ());
/* FIXME: 'select' doesn't cover all ways of selection */
g_signal_connect (proxy, "select",
G_CALLBACK (katze_array_action_proxy_clicked_cb), action);
g_signal_connect (proxy, "activate",
G_CALLBACK (katze_array_action_proxy_clicked_cb), action);
}
}

View File

@ -27,7 +27,7 @@
#include <sqlite3.h>
#define QUERY_ALL "SELECT id, name, value, host, path, expiry, lastAccessed, isSecure, isHttpOnly FROM moz_cookies;"
#define CREATE_TABLE "CREATE TABLE IF NOT EXISTS moz_cookies (id INTEGER PRIMARY KEY, name TEXT, value TEXT, host TEXT, path TEXT,expiry INTEGER, lastAccessed INTEGER, isSecure INTEGER, isHttpOnly INTEGER)"
#define CREATE_TABLE "CREATE TABLE moz_cookies (id INTEGER PRIMARY KEY, name TEXT, value TEXT, host TEXT, path TEXT,expiry INTEGER, lastAccessed INTEGER, isSecure INTEGER, isHttpOnly INTEGER)"
#define QUERY_INSERT "INSERT INTO moz_cookies VALUES(NULL, %Q, %Q, %Q, %Q, %d, NULL, %d, %d);"
#define QUERY_DELETE "DELETE FROM moz_cookies WHERE name=%Q AND host=%Q;"
@ -71,6 +71,80 @@ G_DEFINE_TYPE_WITH_CODE (KatzeHttpCookiesSqlite, katze_http_cookies_sqlite, G_TY
Copyright (C) 2009 Collabora Ltd.
Mostly copied from libSoup 2.30, coding style retained */
static void
try_create_table (sqlite3 *db)
{
char *error = NULL;
if (sqlite3_exec (db, CREATE_TABLE, NULL, NULL, &error)) {
g_warning ("Failed to execute query: %s", error);
sqlite3_free (error);
}
}
static void
exec_query_with_try_create_table (sqlite3* db,
const char* sql,
int (*callback)(void*,int,char**,char**),
void *argument)
{
char *error = NULL;
gboolean try_create = TRUE;
try_exec:
if (sqlite3_exec (db, sql, callback, argument, &error)) {
if (try_create) {
try_create = FALSE;
try_create_table (db);
sqlite3_free (error);
error = NULL;
goto try_exec;
} else {
g_warning ("Failed to execute query: %s", error);
sqlite3_free (error);
}
}
}
static int
callback (void *data, int argc, char **argv, char **colname)
{
SoupCookie *cookie = NULL;
SoupCookieJar *jar = SOUP_COOKIE_JAR (data);
char *name, *value, *host, *path;
gint64 expire_time;
time_t now;
int max_age;
gboolean http_only = FALSE, secure = FALSE;
now = time (NULL);
name = argv[COL_NAME];
value = argv[COL_VALUE];
host = argv[COL_HOST];
path = argv[COL_PATH];
expire_time = g_ascii_strtoull (argv[COL_EXPIRY], NULL, 10);
if (now >= expire_time)
return 0;
max_age = (expire_time - now <= G_MAXINT ? expire_time - now : G_MAXINT);
http_only = (g_strcmp0 (argv[COL_HTTP_ONLY], "1") == 0);
secure = (g_strcmp0 (argv[COL_SECURE], "1") == 0);
cookie = soup_cookie_new (name, value, host, path, max_age);
if (secure)
soup_cookie_set_secure (cookie, TRUE);
if (http_only)
soup_cookie_set_http_only (cookie, TRUE);
soup_cookie_jar_add_cookie (jar, cookie);
return 0;
}
/* Follows sqlite3 convention; returns TRUE on error */
static gboolean
katze_http_cookies_sqlite_open_db (KatzeHttpCookiesSqlite* http_cookies)
@ -83,91 +157,23 @@ katze_http_cookies_sqlite_open_db (KatzeHttpCookiesSqlite* http_cookies)
return TRUE;
}
if (sqlite3_exec (http_cookies->db, CREATE_TABLE, NULL, NULL, &error)) {
if (sqlite3_exec (http_cookies->db, "PRAGMA synchronous = OFF; PRAGMA secure_delete = 1;", NULL, NULL, &error)) {
g_warning ("Failed to execute query: %s", error);
sqlite3_free (error);
}
if (sqlite3_exec (http_cookies->db, "PRAGMA secure_delete = 1;",
NULL, NULL, &error)) {
g_warning ("Failed to execute query: %s", error);
sqlite3_free (error);
}
sqlite3_exec (http_cookies->db,
/* Arguably cookies are like a cache, so performance over integrity */
"PRAGMA synchronous = OFF; PRAGMA temp_store = MEMORY;"
"PRAGMA count_changes = OFF; PRAGMA journal_mode = TRUNCATE;",
NULL, NULL, &error);
return FALSE;
}
static void
katze_http_cookies_sqlite_load (KatzeHttpCookiesSqlite* http_cookies)
{
const char *name, *value, *host, *path;
sqlite3_stmt* stmt;
SoupCookie *cookie = NULL;
gint64 expire_time;
time_t now;
int max_age;
gboolean http_only = FALSE, secure = FALSE;
char *query;
int result;
if (http_cookies->db == NULL) {
if (katze_http_cookies_sqlite_open_db (http_cookies))
return;
}
sqlite3_prepare_v2 (http_cookies->db, QUERY_ALL, strlen (QUERY_ALL) + 1, &stmt, NULL);
result = sqlite3_step (stmt);
if (result != SQLITE_ROW)
{
if (result == SQLITE_ERROR)
g_print (_("Failed to load cookies\n"));
sqlite3_reset (stmt);
return;
}
while (result == SQLITE_ROW)
{
now = time (NULL);
name = (const char*)sqlite3_column_text (stmt, COL_NAME);
value = (const char*)sqlite3_column_text (stmt, COL_VALUE);
host = (const char*)sqlite3_column_text (stmt, COL_HOST);
path = (const char*)sqlite3_column_text (stmt, COL_PATH);
expire_time = sqlite3_column_int64 (stmt,COL_EXPIRY);
secure = sqlite3_column_int (stmt, COL_SECURE);
http_only = sqlite3_column_int (stmt, COL_HTTP_ONLY);
if (now >= expire_time)
{
/* Cookie expired, remove it from database */
query = sqlite3_mprintf (QUERY_DELETE, name, host);
sqlite3_exec (http_cookies->db, QUERY_DELETE, NULL, NULL, NULL);
sqlite3_free (query);
result = sqlite3_step (stmt);
continue;
}
max_age = (expire_time - now <= G_MAXINT ? expire_time - now : G_MAXINT);
cookie = soup_cookie_new (name, value, host, path, max_age);
if (secure)
soup_cookie_set_secure (cookie, TRUE);
if (http_only)
soup_cookie_set_http_only (cookie, TRUE);
soup_cookie_jar_add_cookie (http_cookies->jar, cookie);
result = sqlite3_step (stmt);
}
if (stmt)
{
sqlite3_reset (stmt);
sqlite3_clear_bindings (stmt);
}
exec_query_with_try_create_table (http_cookies->db, QUERY_ALL, callback, http_cookies->jar);
}
static void
katze_http_cookies_sqlite_jar_changed_cb (SoupCookieJar* jar,
@ -207,14 +213,14 @@ katze_http_cookies_sqlite_jar_changed_cb (SoupCookieJar* jar,
}
}
if (!g_strcmp0 (g_getenv ("MIDORI_DEBUG"), "cookies"))
if (g_getenv ("MIDORI_COOKIES_DEBUG") != NULL)
http_cookies->counter++;
if (old_cookie) {
query = sqlite3_mprintf (QUERY_DELETE,
old_cookie->name,
old_cookie->domain);
sqlite3_exec (http_cookies->db, query, NULL, NULL, NULL);
exec_query_with_try_create_table (http_cookies->db, query, NULL, NULL);
sqlite3_free (query);
}
@ -228,7 +234,7 @@ katze_http_cookies_sqlite_jar_changed_cb (SoupCookieJar* jar,
expires,
new_cookie->secure,
new_cookie->http_only);
sqlite3_exec (http_cookies->db, query, NULL, NULL, NULL);
exec_query_with_try_create_table (http_cookies->db, query, NULL, NULL);
sqlite3_free (query);
}
}

View File

@ -211,7 +211,7 @@ katze_http_cookies_update_jar (KatzeHttpCookies* http_cookies)
goto failed;
g_free (temporary_filename);
if (!g_strcmp0 (g_getenv ("MIDORI_DEBUG"), "cookies"))
if (g_getenv ("MIDORI_COOKIES_DEBUG") != NULL)
{
g_print ("KatzeHttpCookies: %d cookies changed\n", http_cookies->counter);
http_cookies->counter = 0;
@ -223,7 +223,7 @@ failed:
fclose (f);
g_unlink (temporary_filename);
g_free (temporary_filename);
if (!g_strcmp0 (g_getenv ("MIDORI_DEBUG"), "cookies"))
if (g_getenv ("MIDORI_COOKIES_DEBUG") != NULL)
g_print ("KatzeHttpCookies: Failed to write '%s'\n",
http_cookies->filename);
return FALSE;
@ -263,7 +263,7 @@ katze_http_cookies_jar_changed_cb (SoupCookieJar* jar,
}
}
if (!g_strcmp0 (g_getenv ("MIDORI_DEBUG"), "cookies"))
if (g_getenv ("MIDORI_COOKIES_DEBUG") != NULL)
http_cookies->counter++;
if (!http_cookies->timeout && (old_cookie || new_cookie->expires))

View File

@ -15,8 +15,6 @@
#include <glib/gi18n.h>
#include <webkit/webkit.h>
/**
* SECTION:katze-item
* @short_description: A useful item
@ -317,8 +315,6 @@ katze_item_set_name (KatzeItem* item,
g_return_if_fail (KATZE_IS_ITEM (item));
katze_assign (item->name, g_strdup (name));
if (item->parent)
katze_array_update ((KatzeArray*)item->parent);
g_object_notify (G_OBJECT (item), "name");
}
@ -418,86 +414,9 @@ katze_item_set_icon (KatzeItem* item,
g_return_if_fail (KATZE_IS_ITEM (item));
katze_item_set_meta_string (item, "icon", icon);
if (item->parent)
katze_array_update ((KatzeArray*)item->parent);
g_object_notify (G_OBJECT (item), "icon");
}
/**
* katze_item_get_pixbuf:
* @item: a #KatzeItem
* @widget: a #GtkWidget, or %NULL
*
* Retrieves a #GdkPixbuf fit to display @item.
*
* Return value: the icon of the item
*
* Since: 0.4.6
**/
GdkPixbuf*
katze_item_get_pixbuf (KatzeItem* item,
GtkWidget* widget)
{
GdkPixbuf* pixbuf;
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
if (item->uri == NULL)
return NULL;
#if WEBKIT_CHECK_VERSION (1, 8, 0)
/* FIXME: Don't hard-code icon size */
if ((pixbuf = webkit_favicon_database_try_get_favicon_pixbuf (
webkit_get_favicon_database (), item->uri, 16, 16)))
return pixbuf;
#else
if ((pixbuf = g_object_get_data (G_OBJECT (item), "pixbuf")))
return pixbuf;
#endif
return NULL;
}
/**
* katze_item_get_image:
* @item: a #KatzeItem
*
* Retrieves a #GtkImage fit to display @item.
*
* Return value: the icon of the item
*
* Since: 0.4.4
**/
GtkWidget*
katze_item_get_image (KatzeItem* item)
{
GtkWidget* image;
GdkPixbuf* pixbuf;
const gchar* icon;
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
if (KATZE_ITEM_IS_FOLDER (item))
image = gtk_image_new_from_stock (GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU);
/* FIXME: Pass widget for icon size */
else if ((pixbuf = katze_item_get_pixbuf (item, NULL)))
image = gtk_image_new_from_pixbuf (pixbuf);
else if ((icon = katze_item_get_icon (item)) && !strchr (icon, '/'))
image = gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_MENU);
else
{
if (!(icon && (pixbuf = katze_load_cached_icon (icon, NULL))))
pixbuf = katze_load_cached_icon (item->uri, NULL);
if (pixbuf)
{
image = gtk_image_new_from_pixbuf (pixbuf);
g_object_unref (pixbuf);
}
else
image = gtk_image_new_from_stock (GTK_STOCK_FILE, GTK_ICON_SIZE_MENU);
}
return image;
}
/**
* katze_item_get_token:
* @item: a #KatzeItem
@ -608,22 +527,17 @@ katze_item_set_meta_data_value (KatzeItem* item,
* Return value: a string, or %NULL
*
* Since: 0.1.8
*
* Since 0.4.4 "" is treated like %NULL.
**/
const gchar*
katze_item_get_meta_string (KatzeItem* item,
const gchar* key)
{
const gchar* value;
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
g_return_val_if_fail (key != NULL, NULL);
if (g_str_has_prefix (key, "midori:"))
key = &key[7];
value = g_hash_table_lookup (item->metadata, key);
return value && *value ? value : NULL;
return g_hash_table_lookup (item->metadata, key);
}
/**

View File

@ -12,7 +12,7 @@
#ifndef __KATZE_ITEM_H__
#define __KATZE_ITEM_H__
#include <gtk/gtk.h>
#include <glib-object.h>
G_BEGIN_DECLS
@ -91,13 +91,6 @@ void
katze_item_set_icon (KatzeItem* item,
const gchar* icon);
GdkPixbuf*
katze_item_get_pixbuf (KatzeItem* item,
GtkWidget* widget);
GtkWidget*
katze_item_get_image (KatzeItem* item);
const gchar*
katze_item_get_token (KatzeItem* item);

View File

@ -27,6 +27,9 @@
struct _KatzeNet
{
GObject parent_instance;
gchar* cache_path;
guint cache_size;
};
struct _KatzeNetClass
@ -51,14 +54,37 @@ katze_net_class_init (KatzeNetClass* class)
static void
katze_net_init (KatzeNet* net)
{
net->cache_path = g_build_filename (g_get_user_cache_dir (),
PACKAGE_NAME, NULL);
}
static void
katze_net_finalize (GObject* object)
{
KatzeNet* net = KATZE_NET (object);
katze_assign (net->cache_path, NULL);
G_OBJECT_CLASS (katze_net_parent_class)->finalize (object);
}
static KatzeNet*
katze_net_new (void)
{
static KatzeNet* net = NULL;
if (!net)
{
net = g_object_new (KATZE_TYPE_NET, NULL);
/* Since this is a "singleton", keep an extra reference */
g_object_ref (net);
}
else
g_object_ref (net);
return net;
}
typedef struct
{
KatzeNetStatusCb status_cb;
@ -83,28 +109,29 @@ katze_net_get_cached_path (KatzeNet* net,
const gchar* uri,
const gchar* subfolder)
{
gchar* cache_path;
gchar* checksum;
gchar* extension;
gchar* cached_filename;
gchar* cached_path;
net = katze_net_new ();
if (subfolder)
cache_path = g_build_filename (net->cache_path, subfolder, NULL);
else
cache_path = net->cache_path;
katze_mkdir_with_parents (cache_path, 0700);
checksum = g_compute_checksum_for_string (G_CHECKSUM_MD5, uri, -1);
extension = g_strrstr (uri, ".");
cached_filename = g_strdup_printf ("%s%s", checksum,
extension ? extension : "");
g_free (checksum);
if (subfolder)
{
gchar* cache_path = g_build_filename (midori_paths_get_cache_dir (), subfolder, NULL);
katze_mkdir_with_parents (cache_path, 0700);
cached_path = g_build_filename (cache_path, cached_filename, NULL);
g_free (cache_path);
}
else
cached_path = g_build_filename (midori_paths_get_cache_dir (), cached_filename, NULL);
cached_path = g_build_filename (cache_path, cached_filename, NULL);
g_free (cached_filename);
if (subfolder)
g_free (cache_path);
return cached_path;
}

View File

@ -14,6 +14,8 @@
#include "katze-utils.h"
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define KATZE_TYPE_NET \

View File

@ -15,13 +15,6 @@
#include <config.h>
#endif
#ifdef HAVE_GRANITE
#if HAVE_OSX
#error FIXME granite on OSX is not implemented
#endif
#include <granite.h>
#endif
#if HAVE_HILDON
#include "katze-scrolled.h"
#include <hildon/hildon.h>
@ -110,8 +103,11 @@ katze_preferences_init (KatzePreferences* preferences)
gtk_dialog_add_buttons (GTK_DIALOG (preferences),
GTK_STOCK_HELP, GTK_RESPONSE_HELP,
NULL);
katze_widget_add_class (gtk_dialog_get_widget_for_response (
GTK_DIALOG (preferences), GTK_RESPONSE_HELP), "help_button");
#if GTK_CHECK_VERSION (3, 0, 0)
gtk_style_context_add_class (gtk_widget_get_style_context (
gtk_dialog_get_widget_for_response (GTK_DIALOG (preferences),
GTK_RESPONSE_HELP)), "help_button");
#endif
gtk_dialog_add_buttons (GTK_DIALOG (preferences),
#if HAVE_HILDON
@ -206,12 +202,7 @@ katze_preferences_prepare (KatzePreferences* preferences)
g_signal_connect (priv->scrolled, "destroy",
G_CALLBACK (gtk_widget_destroyed), &priv->scrolled);
#else
#ifdef HAVE_GRANITE
/* FIXME: granite: should return GtkWidget* like GTK+ */
priv->notebook = (GtkWidget*)granite_widgets_static_notebook_new (FALSE);
#else
priv->notebook = gtk_notebook_new ();
#endif
gtk_container_set_border_width (GTK_CONTAINER (priv->notebook), 6);
#if HAVE_OSX
@ -305,14 +296,8 @@ katze_preferences_add_category (KatzePreferences* preferences,
priv->sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
gtk_widget_show (priv->page);
gtk_container_set_border_width (GTK_CONTAINER (priv->page), 4);
#ifdef HAVE_GRANITE
granite_widgets_static_notebook_append_page (
GRANITE_WIDGETS_STATIC_NOTEBOOK (priv->notebook),
priv->page, GTK_LABEL (gtk_label_new (label)));
#else
gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
priv->page, gtk_label_new (label));
#endif
#if HAVE_OSX
priv->toolbutton = GTK_WIDGET (priv->toolbutton ?
gtk_radio_tool_button_new_from_widget (

View File

@ -97,12 +97,12 @@ katze_throbber_realize (GtkWidget* widget);
#if GTK_CHECK_VERSION (3, 0, 0)
static void
katze_throbber_get_preferred_height (GtkWidget *widget,
gint *minimal_height,
gint *natural_height);
gint *minimal_width,
gint *natural_width);
static void
katze_throbber_get_preferred_width (GtkWidget *widget,
gint *minimal_width,
gint *natural_width);
gint *minimal_width,
gint *natural_width);
#endif
static void
katze_throbber_unrealize (GtkWidget* widget);
@ -495,8 +495,8 @@ katze_throbber_set_animated (KatzeThrobber* throbber,
(GSourceFunc)katze_throbber_timeout,
throbber,
(GDestroyNotify)katze_throbber_timeout_destroy);
#endif
gtk_widget_queue_draw (GTK_WIDGET (throbber));
#endif
g_object_notify (G_OBJECT (throbber), "animated");
}
@ -857,14 +857,14 @@ katze_throbber_size_request (GtkWidget* widget,
#if GTK_CHECK_VERSION (3, 0, 0)
static void
katze_throbber_get_preferred_height (GtkWidget *widget,
gint *minimal_height,
gint *natural_height)
gint *minimal_width,
gint *natural_width)
{
GtkRequisition requisition;
katze_throbber_size_request (widget, &requisition);
*minimal_height = *natural_height = requisition.height;
*minimal_width = *natural_width = requisition.height;
}
static void
@ -902,7 +902,6 @@ katze_throbber_aligned_coords (GtkWidget* widget,
#endif
#if GTK_CHECK_VERSION (3, 0, 0)
allocation.x = allocation.y = 0;
allocation.width = gtk_widget_get_allocated_width (widget);
allocation.height = gtk_widget_get_allocated_height (widget);
gtk_widget_get_preferred_size (widget, &requisition, NULL);

View File

@ -277,6 +277,7 @@ proxy_combo_box_changed_cb (GtkComboBox* button,
if (custom_value)
{
#if GTK_CHECK_VERSION (2, 12, 0)
if (value == custom_value)
gtk_widget_set_tooltip_text (GTK_WIDGET (button), NULL);
else
@ -285,6 +286,7 @@ proxy_combo_box_changed_cb (GtkComboBox* button,
gtk_widget_set_tooltip_text (GTK_WIDGET (button), custom_text);
g_free (custom_text);
}
#endif
}
}
#endif
@ -329,13 +331,7 @@ proxy_widget_string_destroy_cb (GtkWidget* proxy,
static GList*
katze_app_info_get_all_for_category (const gchar* category)
{
#ifdef _WIN32
/* FIXME: Real filtering by category would be better */
const gchar* content_type = g_content_type_from_mime_type (category);
GList* all_apps = g_app_info_get_all_for_type (content_type);
#else
GList* all_apps = g_app_info_get_all ();
#endif
GList* apps = NULL;
guint i = 0;
GAppInfo* info;
@ -521,8 +517,14 @@ katze_property_proxy (gpointer object,
string = g_strdup (G_PARAM_SPEC_STRING (pspec)->default_value);
gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (widget),
string ? string : "");
#if GTK_CHECK_VERSION (2, 12, 0)
g_signal_connect (widget, "file-set",
G_CALLBACK (proxy_uri_file_set_cb), object);
#else
if (pspec->flags & G_PARAM_WRITABLE)
g_signal_connect (widget, "selection-changed",
G_CALLBACK (proxy_uri_file_set_cb), object);
#endif
}
else if (type == G_TYPE_PARAM_STRING && (_hint == I_("font")
|| _hint == I_("font-monospace")))
@ -810,10 +812,11 @@ katze_property_proxy (gpointer object,
G_CALLBACK (proxy_entry_focus_out_event_cb), object);
g_object_set_data_full (G_OBJECT (entry), "property",
g_strdup (custom), g_free);
gtk_widget_set_tooltip_text (widget, NULL);
}
#if GTK_CHECK_VERSION (2, 12, 0)
else
gtk_widget_set_tooltip_text (widget, custom_text);
#endif
g_free (custom_text);
@ -828,6 +831,10 @@ katze_property_proxy (gpointer object,
widget = gtk_label_new (gettext (nick));
g_free (string);
#if GTK_CHECK_VERSION (2, 12, 0)
if (!gtk_widget_get_tooltip_text (widget))
gtk_widget_set_tooltip_text (widget, g_param_spec_get_blurb (pspec));
#endif
gtk_widget_set_sensitive (widget, pspec->flags & G_PARAM_WRITABLE);
g_object_set_data_full (G_OBJECT (widget), "property",
@ -868,8 +875,16 @@ katze_property_label (gpointer object,
return gtk_label_new (property);
}
#ifdef HAVE_HILDON_2_2
if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_ENUM)
return gtk_label_new (NULL);
#endif
nick = g_param_spec_get_nick (pspec);
widget = gtk_label_new (nick);
#if GTK_CHECK_VERSION (2, 12, 0)
gtk_widget_set_tooltip_text (widget, g_param_spec_get_blurb (pspec));
#endif
gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
return widget;
@ -895,29 +910,21 @@ katze_widget_popup_position_menu (GtkMenu* menu,
GtkRequisition widget_req;
KatzePopupInfo* info = user_data;
GtkWidget* widget = info->widget;
GdkWindow* window = gtk_widget_get_window (widget);
gint widget_height;
if (!window)
return;
#if !GTK_CHECK_VERSION (3, 0, 0)
if (GTK_IS_ENTRY (widget))
window = gdk_window_get_parent (window);
#endif
gtk_widget_get_allocation (widget, &allocation);
/* Retrieve size and position of both widget and menu */
gtk_widget_get_allocation (widget, &allocation);
gdk_window_get_origin (window, &wx, &wy);
wx += allocation.x;
wy += allocation.y;
#if GTK_CHECK_VERSION (3, 0, 0)
gtk_widget_get_preferred_size (GTK_WIDGET (menu), &menu_req, NULL);
gtk_widget_get_preferred_size (widget, &widget_req, NULL);
#else
if (!gtk_widget_get_has_window (widget))
{
gdk_window_get_position (gtk_widget_get_window (widget), &wx, &wy);
wx += allocation.x;
wy += allocation.y;
}
else
gdk_window_get_origin (gtk_widget_get_window (widget), &wx, &wy);
gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
gtk_widget_size_request (widget, &widget_req);
#endif
menu_width = menu_req.width;
widget_height = widget_req.height; /* Better than allocation.height */
@ -1183,16 +1190,6 @@ katze_strip_mnemonics (const gchar* original)
return result;
}
const gchar*
katze_skip_whitespace (const gchar* str)
{
if (str == NULL)
return NULL;
while (*str == ' ' || *str == '\t' || *str == '\n')
str++;
return str;
}
/**
* katze_object_has_property:
* @object: a #GObject
@ -1502,7 +1499,8 @@ katze_load_cached_icon (const gchar* uri,
filename = g_strdup_printf ("%s%s", checksum, ext ? ext : "");
g_free (icon_uri);
g_free (checksum);
path = g_build_filename (midori_paths_get_cache_dir (), "icons", filename, NULL);
path = g_build_filename (g_get_user_cache_dir (), PACKAGE_NAME,
"icons", filename, NULL);
g_free (filename);
if ((icon = gdk_pixbuf_new_from_file_at_size (path, 16, 16, NULL)))
{
@ -1522,15 +1520,6 @@ katze_uri_entry_changed_cb (GtkWidget* entry,
{
const gchar* uri = gtk_entry_get_text (GTK_ENTRY (entry));
gboolean valid = midori_uri_is_location (uri);
if (!valid && g_object_get_data (G_OBJECT (entry), "allow_%s"))
valid = uri && g_str_has_prefix (uri, "%s");
if (!valid)
valid = midori_uri_is_ip_address (uri);
#if GTK_CHECK_VERSION (3, 2, 0)
g_object_set_data (G_OBJECT (entry), "invalid", GINT_TO_POINTER (*uri && !valid));
gtk_widget_queue_draw (entry);
#else
if (*uri && !valid)
{
GdkColor bg_color = { 0 };
@ -1545,34 +1534,11 @@ katze_uri_entry_changed_cb (GtkWidget* entry,
gtk_widget_modify_base (entry, GTK_STATE_NORMAL, NULL);
gtk_widget_modify_text (entry, GTK_STATE_NORMAL, NULL);
}
#endif
if (other_widget != NULL)
gtk_widget_set_sensitive (other_widget, valid);
}
#if GTK_CHECK_VERSION (3, 2, 0)
static gboolean
katze_uri_entry_draw_cb (GtkWidget* entry,
cairo_t* cr,
GtkWidget* other_widget)
{
const GdkRGBA color = { 0.9, 0., 0., 1. };
double width = gtk_widget_get_allocated_width (entry);
double height = gtk_widget_get_allocated_height (entry);
if (!g_object_get_data (G_OBJECT (entry), "invalid"))
return FALSE;
/* FIXME: error-underline-color requires GtkTextView */
gdk_cairo_set_source_rgba (cr, &color);
pango_cairo_show_error_underline (cr, width * 0.15, height / 1.9,
width * 0.75, height / 1.9 / 2);
return TRUE;
}
#endif
/**
* katze_uri_entry_new:
* @other_widget: a #GtkWidget, or %NULL
@ -1590,28 +1556,11 @@ GtkWidget*
katze_uri_entry_new (GtkWidget* other_widget)
{
GtkWidget* entry = gtk_entry_new ();
gtk_entry_set_icon_from_gicon (GTK_ENTRY (entry), GTK_ENTRY_ICON_PRIMARY,
g_themed_icon_new_with_default_fallbacks ("text-html-symbolic"));
g_signal_connect (entry, "changed",
G_CALLBACK (katze_uri_entry_changed_cb), other_widget);
#if GTK_CHECK_VERSION (3, 2, 0)
g_signal_connect_after (entry, "draw",
G_CALLBACK (katze_uri_entry_draw_cb), other_widget);
#endif
return entry;
}
void
katze_widget_add_class (GtkWidget* widget,
const gchar* class_name)
{
#if GTK_CHECK_VERSION (3,0,0)
GtkStyleContext* context = gtk_widget_get_style_context (widget);
gtk_style_context_add_class (context, class_name);
#endif
}
/**
* katze_assert_str_equal:
* @input: a string

View File

@ -58,20 +58,6 @@ G_BEGIN_DECLS
**/
#define katze_strv_assign(lvalue, rvalue) lvalue = (g_strfreev (lvalue), rvalue)
/**
* katze_str_non_null:
* @str: a string, or %NULL
*
* Returns "" if @str is %NULL.
*
* Since: 0.4.4
**/
static inline const gchar*
katze_str_non_null (const gchar* str)
{
return str ? str : "";
}
GtkWidget*
katze_property_proxy (gpointer object,
const gchar* property,
@ -115,9 +101,6 @@ katze_bookmark_populate_tree_view (KatzeArray* array,
gchar*
katze_strip_mnemonics (const gchar* original);
const gchar*
katze_skip_whitespace (const gchar* str);
gboolean
katze_object_has_property (gpointer object,
const gchar* property);
@ -160,10 +143,6 @@ katze_load_cached_icon (const gchar* uri,
GtkWidget*
katze_uri_entry_new (GtkWidget* other_widget);
void
katze_widget_add_class (GtkWidget* widget,
const gchar* class_name);
void
katze_assert_str_equal (const gchar* input,
const gchar* result,

View File

@ -1,25 +0,0 @@
/* Copyright (C) 2012 André Stösel <andre@stoesel.de>
This file is licensed under the terms of the expat license, see the file EXPAT. */
[CCode (cprefix = "Katze", lower_case_cprefix = "katze_")]
namespace Katze {
static string assert_str_equal (string input, string result, string expected);
[CCode (cheader_filename = "katze/katze.h")]
public class Array : Katze.Item {
public Array (GLib.Type type);
public void add_item (GLib.Object item);
}
[CCode (cheader_filename = "katze/katze.h")]
public class Item : GLib.Object {
public string? uri { get; set; }
public string? name { get; set; }
public string? text { get; set; }
public bool get_meta_boolean (string key);
public int64 get_meta_integer (string key);
public void set_meta_integer (string key, int64 value);
}
}

View File

@ -1,143 +0,0 @@
/*
Copyright (C) 2012 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.
*/
namespace Midori {
public class HSTS : GLib.Object, Soup.SessionFeature {
public class Directive {
public Soup.Date? expires = null;
public bool sub_domains = false;
public Directive (bool include_sub_domains) {
expires = new Soup.Date.from_now (int.MAX);
sub_domains = include_sub_domains;
}
public Directive.from_header (string header) {
var param_list = Soup.header_parse_param_list (header);
if (param_list == null)
return;
string? max_age = param_list.lookup ("max-age");
if (max_age != null)
expires = new Soup.Date.from_now (max_age.to_int ());
// if (param_list.lookup_extended ("includeSubDomains", null, null))
if ("includeSubDomains" in header)
sub_domains = true;
Soup.header_free_param_list (param_list);
}
public bool is_valid () {
return expires != null && !expires.is_past ();
}
}
File file;
HashTable<string, Directive> whitelist;
bool debug = false;
public HSTS (owned string filename) {
whitelist = new HashTable<string, Directive> (str_hash, str_equal);
read_cache (File.new_for_path (Paths.get_preset_filename (null, "hsts")));
file = File.new_for_path (filename);
read_cache (file);
if (strcmp (Environment.get_variable ("MIDORI_DEBUG"), "hsts") == 0)
debug = true;
}
async void read_cache (File file) {
try {
var stream = new DataInputStream (yield file.read_async ());
do {
string? line = yield stream.read_line_async ();
if (line == null)
break;
string[] parts = line.split (" ", 2);
if (parts[0] == null || parts[1] == null)
break;
var directive = new Directive.from_header (parts[1]);
if (directive.is_valid ())
append_to_whitelist (parts[0], directive);
} while (true);
}
catch (Error error) { }
}
/* No sub-features */
public bool add_feature (Type type) { return false; }
public bool remove_feature (Type type) { return false; }
public bool has_feature (Type type) { return false; }
public void attach (Soup.Session session) { session.request_queued.connect (queued); }
public void detach (Soup.Session session) { /* FIXME disconnect */ }
/* Never called but required by the interface */
public void request_started (Soup.Session session, Soup.Message msg, Soup.Socket socket) { }
public void request_queued (Soup.Session session, Soup.Message message) { }
public void request_unqueued (Soup.Session session, Soup.Message msg) { }
bool should_secure_host (string host) {
Directive? directive = whitelist.lookup (host);
if (directive == null)
directive = whitelist.lookup ("*." + host);
return directive != null && directive.is_valid ();
}
void queued (Soup.Session session, Soup.Message message) {
if (should_secure_host (message.uri.host)) {
message.uri.set_scheme ("https");
session.requeue_message (message);
if (debug)
stdout.printf ("HSTS: Enforce %s\n", message.uri.host);
}
else if (message.uri.scheme == "http")
message.finished.connect (strict_transport_security_handled);
}
void append_to_whitelist (string host, Directive directive) {
whitelist.insert (host, directive);
if (directive.sub_domains)
whitelist.insert ("*." + host, directive);
}
async void append_to_cache (string host, string header) {
if (Midori.Paths.is_readonly ())
return;
try {
var stream = file.append_to/* FIXME _async*/ (FileCreateFlags.NONE);
yield stream.write_async ((host + " " + header + "\n").data);
yield stream.flush_async ();
}
catch (Error error) {
critical ("Failed to update %s: %s", file.get_path (), error.message);
}
}
void strict_transport_security_handled (Soup.Message message) {
if (message == null || message.uri == null)
return;
unowned string? hsts = message.response_headers.get_one ("Strict-Transport-Security");
if (hsts == null)
return;
var directive = new Directive.from_header (hsts);
if (directive.is_valid ()) {
append_to_whitelist (message.uri.host, directive);
append_to_cache (message.uri.host, hsts);
}
if (debug)
stdout.printf ("HSTS: '%s' sets '%s' valid? %s\n",
message.uri.host, hsts, directive.is_valid ().to_string ());
}
}
}

View File

@ -1,244 +0,0 @@
/*
Copyright (C) 2012 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.
*/
namespace GLib {
#if HAVE_WIN32
extern static string win32_get_package_installation_directory_of_module (void* hmodule = null);
#endif
}
extern const string LIBDIR;
extern const string MDATADIR;
extern const string PACKAGE_NAME;
extern const string SYSCONFDIR;
extern const string MIDORI_VERSION_SUFFIX;
namespace Midori {
public enum RuntimeMode {
UNDEFINED,
NORMAL,
APP,
PRIVATE,
PORTABLE
}
namespace Paths {
static string? exec_path = null;
static string[] command_line = null;
static RuntimeMode mode = RuntimeMode.UNDEFINED;
static string? config_dir = null;
static string? readonly_dir = null;
static string? cache_dir = null;
static string? user_data_dir = null;
static string? tmp_dir = null;
public static string get_readonly_config_dir () {
assert (mode != RuntimeMode.UNDEFINED);
return readonly_dir ?? config_dir;
}
public static string get_readonly_config_filename (string filename) {
assert (mode != RuntimeMode.UNDEFINED);
return Path.build_path (Path.DIR_SEPARATOR_S,
readonly_dir ?? config_dir, filename);
}
public bool is_readonly () {
assert (mode != RuntimeMode.UNDEFINED);
return readonly_dir != null;
}
public static void init (RuntimeMode new_mode, string? config_base) {
assert (mode == RuntimeMode.UNDEFINED);
assert (new_mode != RuntimeMode.UNDEFINED);
mode = new_mode;
if (mode == RuntimeMode.PORTABLE) {
config_dir = Path.build_path (Path.DIR_SEPARATOR_S,
exec_path, "profile", "config");
cache_dir = Path.build_path (Path.DIR_SEPARATOR_S,
exec_path, "profile", "cache");
user_data_dir = Path.build_path (Path.DIR_SEPARATOR_S,
exec_path, "profile", "misc");
tmp_dir = Path.build_path (Path.DIR_SEPARATOR_S,
exec_path, "profile", "tmp");
}
else if (mode == RuntimeMode.PRIVATE || mode == RuntimeMode.APP) {
/* Use mock folders in development builds */
if ("." in MIDORI_VERSION_SUFFIX)
config_dir = cache_dir = user_data_dir = config_base;
else
config_dir = cache_dir = user_data_dir = "/";
readonly_dir = config_base ?? Path.build_path (Path.DIR_SEPARATOR_S,
Environment.get_user_config_dir (), PACKAGE_NAME);
tmp_dir = Path.build_path (Path.DIR_SEPARATOR_S,
Environment.get_tmp_dir (), "midori-" + Environment.get_user_name ());
}
else {
config_dir = config_base ?? Path.build_path (Path.DIR_SEPARATOR_S,
Environment.get_user_config_dir (), PACKAGE_NAME);
cache_dir = Path.build_path (Path.DIR_SEPARATOR_S,
Environment.get_user_cache_dir (), PACKAGE_NAME);
user_data_dir = Environment.get_user_data_dir ();
tmp_dir = Path.build_path (Path.DIR_SEPARATOR_S,
Environment.get_tmp_dir (), "midori-" + Environment.get_user_name ());
}
if (strcmp (Environment.get_variable ("MIDORI_DEBUG"), "paths") == 0) {
stdout.printf ("config: %s\ncache: %s\nuser_data: %s\ntmp: %s\n",
config_dir, cache_dir, user_data_dir, tmp_dir);
}
}
public static unowned string get_config_dir () {
assert (config_dir != null);
return config_dir;
}
public static string get_config_filename (string filename) {
assert (mode != RuntimeMode.UNDEFINED);
assert (config_dir != null);
return Path.build_path (Path.DIR_SEPARATOR_S, config_dir, filename);
}
public static unowned string get_cache_dir () {
assert (cache_dir != null);
return cache_dir;
}
public static unowned string get_user_data_dir () {
assert (user_data_dir != null);
return user_data_dir;
}
public static unowned string get_tmp_dir () {
assert (tmp_dir != null);
return tmp_dir;
}
public static void init_exec_path (string[] new_command_line) {
assert (command_line == null);
command_line = new_command_line;
#if HAVE_WIN32
exec_path = win32_get_package_installation_directory_of_module ();
#else
string? executable;
try {
if (!Path.is_absolute (command_line[0])) {
string program = Environment.find_program_in_path (command_line[0]);
if (FileUtils.test (program, FileTest.IS_SYMLINK))
executable = FileUtils.read_link (program);
else
executable = program;
}
else
executable = FileUtils.read_link (command_line[0]);
}
catch (Error error) {
executable = command_line[0];
}
exec_path = File.new_for_path (executable).get_parent ().get_parent ().get_path ();
#endif
if (strcmp (Environment.get_variable ("MIDORI_DEBUG"), "paths") == 0) {
stdout.printf ("command_line: %s\nexec_path: %s\nres: %s\nlib: %s\n",
get_command_line_str (), exec_path,
get_res_filename (""), get_lib_path (PACKAGE_NAME));
}
}
public static unowned string[] get_command_line () {
assert (command_line != null);
return command_line;
}
public static string get_command_line_str () {
assert (command_line != null);
return "".joinv (" ", command_line).replace (Environment.get_home_dir (), "~");
}
public static string get_lib_path (string package) {
assert (command_line != null);
#if HAVE_WIN32
return Path.build_filename (exec_path, "lib", package);
#else
string path = Path.build_filename (exec_path, "lib", package);
if (Posix.access (path, Posix.F_OK) == 0)
return path;
if (package == PACKAGE_NAME) {
/* Fallback to build folder */
path = Path.build_filename ((File.new_for_path (exec_path).get_path ()), "extensions");
if (Posix.access (path, Posix.F_OK) == 0)
return path;
}
return Path.build_filename (LIBDIR, PACKAGE_NAME);
#endif
}
public static string get_res_filename (string filename) {
assert (command_line != null);
#if HAVE_WIN32
return Path.build_filename (exec_path, "share", PACKAGE_NAME, "res", filename);
#else
string path = Path.build_filename (exec_path, "share", PACKAGE_NAME, "res", filename);
if (Posix.access (path, Posix.F_OK) == 0)
return path;
/* Fallback to build folder */
path = Path.build_filename ((File.new_for_path (exec_path)
.get_parent ().get_parent ().get_path ()), "data", filename);
if (Posix.access (path, Posix.F_OK) == 0)
return path;
return Path.build_filename (MDATADIR, PACKAGE_NAME, "res", filename);
#endif
}
public static string get_data_filename (string filename, bool res) {
assert (command_line != null);
string res1 = res ? PACKAGE_NAME : "";
string res2 = res ? "res" : "";
#if HAVE_WIN32
return Path.build_filename (exec_path, "share", res1, res2, filename);
#else
string path = Path.build_filename (get_user_data_dir (), res1, res2, filename);
if (Posix.access (path, Posix.F_OK) == 0)
return path;
foreach (string data_dir in Environment.get_system_data_dirs ()) {
path = Path.build_filename (data_dir, res1, res2, filename);
if (Posix.access (path, Posix.F_OK) == 0)
return path;
}
return Path.build_filename (MDATADIR, res1, res2, filename);
#endif
}
public static string get_preset_filename (string? folder, string filename) {
assert (config_dir != null);
#if HAVE_WIN32
return Path.build_filename (exec_path, "etc", "xdg", PACKAGE_NAME, folder ?? "", filename);
#else
foreach (string config_dir in Environment.get_system_config_dirs ()) {
string path = Path.build_filename (config_dir, PACKAGE_NAME, folder ?? "", filename);
if (Posix.access (path, Posix.F_OK) == 0)
return path;
}
return Path.build_filename (SYSCONFDIR, "xdg", PACKAGE_NAME, folder ?? "", filename);
#endif
}
}
}

View File

@ -85,9 +85,6 @@ namespace Midori {
if (uri == null)
return keywords;
string escaped = GLib.Uri.escape_string (keywords, ":/", true);
/* Allow DuckDuckGo to distinguish Midori and in turn share revenue */
if (uri == "https://duckduckgo.com/?q=%s")
return "https://duckduckgo.com/?q=%s&t=midori".printf (escaped);
if (uri.str ("%s") != null)
return uri.printf (escaped);
return uri + escaped;
@ -114,69 +111,43 @@ namespace Midori {
|| (uri.has_prefix ("geo:") && uri.chr (-1, ',') != null)
|| uri.has_prefix ("javascript:"));
}
public static bool is_email (string? uri) {
return uri != null
&& (uri.chr (-1, '@') != null || uri.has_prefix ("mailto:"))
/* :// and @ together would mean login credentials */
&& uri.str ("://") == null;
}
public static bool is_ip_address (string? uri) {
/* Quick check for IPv4 or IPv6, no validation.
FIXME: Schemes are not handled
hostname_is_ip_address () is not used because
we'd have to separate the path from the URI first. */
if (uri == null)
return false;
/* Skip leading user/ password */
if (uri.chr (-1, '@') != null)
return is_ip_address (uri.split ("@")[1]);
/* IPv4 */
if (uri[0] != '0' && uri[0].isdigit () && (uri.chr (4, '.') != null))
return true;
/* IPv6 */
if (uri[0].isalnum () && uri[1].isalnum ()
&& uri[2].isalnum () && uri[3].isalnum () && uri[4] == ':'
&& (uri[5] == ':' || uri[5].isalnum ()))
return true;
return false;
return uri != null && uri[0].isdigit ()
&& (uri.chr (4, '.') != null || uri.chr (4, ':') != null);
}
public static bool is_valid (string? uri) {
return uri != null
&& uri.chr (-1, ' ') == null
&& (URI.is_location (uri) || uri.chr (-1, '.') != null);
}
public static string? get_folder (string uri) {
/* Base the start folder on the current view's uri if it is local */
try {
string? filename = Filename.from_uri (uri);
if (filename != null) {
string? dirname = Path.get_dirname (filename);
if (dirname != null && FileUtils.test (dirname, FileTest.IS_DIR))
return dirname;
}
}
catch (Error error) { }
return null;
}
public static GLib.ChecksumType get_fingerprint (string uri,
out string checksum, out string label) {
/* http://foo.bar/baz/spam.eggs#!algo!123456 */
unowned string display = null;
GLib.ChecksumType type = (GLib.ChecksumType)int.MAX;
unowned string delimiter = "#!md5!";
unowned string display = _("MD5-Checksum:");
GLib.ChecksumType type = GLib.ChecksumType.MD5;
unowned string? fragment = uri.str (delimiter);
if (fragment != null) {
display = _("MD5-Checksum:");
type = GLib.ChecksumType.MD5;
}
delimiter = "#!sha1!";
fragment = uri.str (delimiter);
if (fragment != null) {
if (fragment == null) {
delimiter = "#!sha1!";
display = _("SHA1-Checksum:");
type = GLib.ChecksumType.SHA1;
fragment = uri.str (delimiter);
}
if (fragment == null) {
type = (GLib.ChecksumType)int.MAX;
display = null;
}
/* No SHA256: no known usage and no need for strong encryption */
if (&checksum != null)
checksum = fragment != null

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,7 @@
G_BEGIN_DECLS
#if GTK_CHECK_VERSION (2, 16, 0)
#define GtkIconEntry GtkEntry
#define GtkIconEntryPosition GtkEntryIconPosition
#define GTK_ICON_ENTRY_PRIMARY GTK_ENTRY_ICON_PRIMARY
@ -41,9 +42,99 @@ G_BEGIN_DECLS
GtkEntryIconPosition position,
GdkPixbuf* pixbuf);
#define gtk_icon_entry_set_tooltip gtk_entry_set_icon_tooltip_text
#define gtk_icon_entry_get_tooltip gtk_entry_get_icon_tooltip_text
#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
#define GTK_TYPE_ICON_ENTRY (gtk_icon_entry_get_type())
#define GTK_ICON_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_ICON_ENTRY, GtkIconEntry))
#define GTK_ICON_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_ICON_ENTRY, GtkIconEntryClass))
#define GTK_IS_ICON_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_ICON_ENTRY))
#define GTK_IS_ICON_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_ICON_ENTRY))
#define GTK_ICON_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ICON_ENTRY, GtkIconEntryClass))
typedef enum
{
GTK_ICON_ENTRY_PRIMARY,
GTK_ICON_ENTRY_SECONDARY
} GtkIconEntryPosition;
typedef struct _GtkIconEntry GtkIconEntry;
typedef struct _GtkIconEntryClass GtkIconEntryClass;
typedef struct _GtkIconEntryPrivate GtkIconEntryPrivate;
struct _GtkIconEntry
{
GtkEntry parent_object;
GtkIconEntryPrivate* priv;
};
struct _GtkIconEntryClass
{
GtkEntryClass parent_class;
/* Signals */
void (*icon_pressed) (GtkIconEntry *entry,
GtkIconEntryPosition icon_pos,
int button);
void (*icon_released) (GtkIconEntry *entry,
GtkIconEntryPosition icon_pos,
int button);
void (*gtk_reserved1) (void);
void (*gtk_reserved2) (void);
void (*gtk_reserved3) (void);
void (*gtk_reserved4) (void);
};
GType gtk_icon_entry_get_type (void) G_GNUC_CONST;
GtkWidget* gtk_icon_entry_new (void);
void gtk_icon_entry_set_icon_from_pixbuf (GtkIconEntry *entry,
GtkIconEntryPosition icon_pos,
GdkPixbuf *pixbuf);
void gtk_icon_entry_set_icon_from_stock (GtkIconEntry *entry,
GtkIconEntryPosition icon_pos,
const gchar *stock_id);
void gtk_icon_entry_set_icon_from_icon_name (GtkIconEntry *entry,
GtkIconEntryPosition icon_pos,
const gchar *icon_name);
void gtk_icon_entry_set_icon_from_gicon (const GtkIconEntry *entry,
GtkIconEntryPosition icon_pos,
GIcon *icon);
GdkPixbuf* gtk_icon_entry_get_pixbuf (const GtkIconEntry *entry,
GtkIconEntryPosition icon_pos);
GIcon* gtk_icon_entry_get_gicon (const GtkIconEntry *entry,
GtkIconEntryPosition icon_pos);
void gtk_icon_entry_set_icon_highlight (const GtkIconEntry *entry,
GtkIconEntryPosition icon_pos,
gboolean highlight);
gboolean gtk_icon_entry_get_icon_highlight (const GtkIconEntry *entry,
GtkIconEntryPosition icon_pos);
void gtk_icon_entry_set_cursor (const GtkIconEntry *icon_entry,
GtkIconEntryPosition icon_pos,
GdkCursorType cursor_type);
void gtk_icon_entry_set_tooltip (const GtkIconEntry *icon_entry,
GtkIconEntryPosition icon_pos,
const gchar *text);
void gtk_icon_entry_set_icon_sensitive (const GtkIconEntry *icon_entry,
GtkIconEntryPosition icon_pos,
gboolean sensitive);
void gtk_icon_entry_set_progress_fraction (GtkIconEntry *icon_entry,
gdouble fraction);
#endif
G_END_DECLS

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,6 @@ OBJECT:OBJECT
VOID:BOOLEAN,STRING
VOID:OBJECT,ENUM,BOOLEAN
VOID:OBJECT,INT,INT
VOID:OBJECT,OBJECT
VOID:POINTER,INT
VOID:STRING,BOOLEAN
VOID:STRING,INT,STRING

View File

@ -21,11 +21,9 @@
#include "midori-app.h"
#include "midori-platform.h"
#include "midori-core.h"
#include <string.h>
#include <gtk/gtk.h>
#include <glib/gstdio.h>
#include <glib/gi18n.h>
#if ENABLE_NLS
@ -70,6 +68,10 @@ struct _MidoriApp
{
GObject parent_instance;
MidoriBrowser* browser;
GtkAccelGroup* accel_group;
gchar* name;
MidoriWebSettings* settings;
KatzeArray* bookmarks;
KatzeArray* trash;
@ -79,7 +81,6 @@ struct _MidoriApp
KatzeArray* extensions;
KatzeArray* browsers;
MidoriBrowser* browser;
MidoriAppInstance instance;
#if !HAVE_HILDON || !HAVE_LIBNOTIFY
@ -87,8 +88,6 @@ struct _MidoriApp
#endif
};
static gchar* app_name = NULL;
struct _MidoriAppClass
{
GObjectClass parent_class;
@ -217,6 +216,7 @@ _midori_app_add_browser (MidoriApp* app,
g_return_if_fail (MIDORI_IS_APP (app));
g_return_if_fail (MIDORI_IS_BROWSER (browser));
gtk_window_add_accel_group (GTK_WINDOW (browser), app->accel_group);
g_object_connect (browser,
"signal::focus-in-event", midori_browser_focus_in_event_cb, app,
"signal::new-window", midori_browser_new_window_cb, app,
@ -229,32 +229,6 @@ _midori_app_add_browser (MidoriApp* app,
katze_array_add_item (app->browsers, browser);
#if GTK_CHECK_VERSION (3, 0, 0)
if (app->browser == NULL)
{
gchar* filename;
if ((filename = midori_paths_get_res_filename ("gtk3.css")))
{
GtkCssProvider* css_provider = gtk_css_provider_new ();
GError* error = NULL;
gtk_css_provider_load_from_path (css_provider, filename, &error);
if (error == NULL)
{
gtk_style_context_add_provider_for_screen (
gtk_widget_get_screen (GTK_WIDGET (browser)),
GTK_STYLE_PROVIDER (css_provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
else
{
g_warning ("Failed to load \"%s\": %s", filename, error->message);
g_error_free (error);
}
g_free (filename);
}
}
#endif
app->browser = browser;
#if HAVE_UNIQUE
/* We *do not* let unique watch windows because that includes
@ -746,35 +720,25 @@ midori_app_create_instance (MidoriApp* app)
GIOChannel* channel;
#endif
if (!app->name)
{
const gchar* config = sokoke_set_config_dir (NULL);
gchar* name_hash;
name_hash = g_compute_checksum_for_string (G_CHECKSUM_MD5, config, -1);
app->name = g_strconcat ("midori", "_", name_hash, NULL);
g_free (name_hash);
g_object_notify (G_OBJECT (app), "name");
}
if (!(display = gdk_display_get_default ()))
return MidoriAppInstanceNull;
{
#if HAVE_UNIQUE
const gchar* config = midori_paths_get_config_dir ();
gchar* name_hash;
name_hash = g_compute_checksum_for_string (G_CHECKSUM_MD5, config, -1);
katze_assign (app_name, g_strconcat ("midori", "_", name_hash, NULL));
g_free (name_hash);
g_object_notify (G_OBJECT (app), "name");
#else
katze_assign (app_name, g_strdup (PACKAGE_NAME));
#endif
}
#ifdef GDK_WINDOWING_X11
/* On X11: :0 or :0.0 which is equivalent */
display_name = g_strndup (gdk_display_get_name (display), 2);
#else
display_name = g_strdup (gdk_display_get_name (display));
#endif
n = strlen (display_name);
for (i = 0; i < n; i++)
if (strchr (":.\\/", display_name[i]))
display_name[i] = '_';
instance_name = g_strdup_printf ("de.twotoasts.%s_%s", app_name, display_name);
g_free (display_name);
katze_assign (app_name, instance_name);
instance_name = g_strdup_printf ("de.twotoasts.%s_%s", app->name, display_name);
#if HAVE_UNIQUE
instance = unique_app_new (instance_name, NULL);
@ -782,7 +746,7 @@ midori_app_create_instance (MidoriApp* app)
g_signal_connect (instance, "message-received",
G_CALLBACK (midori_browser_message_received_cb), app);
#else
instance = socket_init (instance_name, midori_paths_get_config_dir (), &exists);
instance = socket_init (instance_name, sokoke_set_config_dir (NULL), &exists);
g_object_set_data (G_OBJECT (app), "sock-exists",
exists ? (gpointer)0xdeadbeef : NULL);
if (instance != MidoriAppInstanceNull)
@ -792,19 +756,19 @@ midori_app_create_instance (MidoriApp* app)
(GIOFunc)midori_app_io_channel_watch_cb, app);
}
#endif
g_free (instance_name);
g_free (display_name);
#endif
return instance;
}
const gchar*
midori_app_get_name (MidoriApp* app)
{
return app_name;
}
static void
midori_app_init (MidoriApp* app)
{
app->accel_group = gtk_accel_group_new ();
app->settings = NULL;
app->bookmarks = NULL;
app->trash = NULL;
@ -829,7 +793,9 @@ midori_app_finalize (GObject* object)
{
MidoriApp* app = MIDORI_APP (object);
katze_assign (app_name, NULL);
g_object_unref (app->accel_group);
katze_assign (app->name, NULL);
katze_object_assign (app->settings, NULL);
katze_object_assign (app->bookmarks, NULL);
katze_object_assign (app->trash, NULL);
@ -869,7 +835,7 @@ midori_app_set_property (GObject* object,
switch (prop_id)
{
case PROP_NAME:
katze_assign (app_name, g_value_dup_string (value));
katze_assign (app->name, g_value_dup_string (value));
break;
case PROP_SETTINGS:
katze_object_assign (app->settings, g_value_dup_object (value));
@ -909,7 +875,7 @@ midori_app_get_property (GObject* object,
switch (prop_id)
{
case PROP_NAME:
g_value_set_string (value, app_name);
g_value_set_string (value, app->name);
break;
case PROP_SETTINGS:
g_value_set_object (value, app->settings);
@ -1145,19 +1111,7 @@ midori_app_send_command (MidoriApp* app,
/* g_return_val_if_fail (MIDORI_IS_APP (app), FALSE); */
g_return_val_if_fail (command != NULL, FALSE);
if (midori_app_instance_is_running (app))
{
MidoriBrowser* browser = midori_browser_new ();
int i;
for (i=0; command && command[i]; i++)
{
gboolean action_known = (gtk_action_group_get_action (midori_browser_get_action_group (browser), command[i]) != NULL);
if (!action_known)
g_warning (_("Unexpected action '%s'."), command[i]);
}
gtk_widget_destroy (GTK_WIDGET (browser));
}
else
if (!midori_app_instance_is_running (app))
return midori_app_command_received (app, "command", command, NULL);
#if HAVE_HILDON
@ -1350,39 +1304,144 @@ midori_app_send_notification (MidoriApp* app,
*
* Since: 0.4.2
**/
gboolean
midori_app_setup (gint *argc,
gchar** *argument_vector,
const GOptionEntry *entries,
GError* *error)
void
midori_app_setup (gchar** argument_vector)
{
GtkIconSource* icon_source;
GtkIconSet* icon_set;
GtkIconFactory* factory;
gsize i;
gboolean success;
static GtkStockItem items[] =
typedef struct
{
{ STOCK_IMAGE },
{ STOCK_WEB_BROWSER },
{ STOCK_NEWS_FEED },
{ STOCK_STYLE },
const gchar* stock_id;
const gchar* label;
GdkModifierType modifier;
guint keyval;
const gchar* fallback;
} FatStockItem;
static FatStockItem items[] =
{
{ STOCK_EXTENSION, NULL, 0, 0, GTK_STOCK_CONVERT },
{ STOCK_IMAGE, NULL, 0, 0, GTK_STOCK_ORIENTATION_PORTRAIT },
{ STOCK_WEB_BROWSER, NULL, 0, 0, "gnome-web-browser" },
{ STOCK_NEWS_FEED, NULL, 0, 0, GTK_STOCK_INDEX },
{ STOCK_SCRIPT, NULL, 0, 0, GTK_STOCK_EXECUTE },
{ STOCK_STYLE, NULL, 0, 0, GTK_STOCK_SELECT_COLOR },
{ STOCK_TRANSFER, NULL, 0, 0, GTK_STOCK_SAVE },
{ STOCK_BOOKMARKS, N_("_Bookmarks"), GDK_CONTROL_MASK | GDK_SHIFT_MASK, GDK_KEY_B },
{ STOCK_BOOKMARK_ADD, N_("Add Boo_kmark") },
{ STOCK_EXTENSION, N_("_Extensions") },
{ STOCK_HISTORY, N_("_History"), GDK_CONTROL_MASK | GDK_SHIFT_MASK, GDK_KEY_H },
{ STOCK_SCRIPT, N_("_Userscripts") },
{ STOCK_STYLE, N_("User_styles") },
{ STOCK_TAB_NEW, N_("New _Tab") },
{ STOCK_TRANSFER, N_("_Transfers"), GDK_CONTROL_MASK | GDK_SHIFT_MASK, GDK_KEY_J },
{ STOCK_PLUGINS, N_("Netscape p_lugins") },
{ STOCK_USER_TRASH, N_("_Closed Tabs") },
{ STOCK_WINDOW_NEW, N_("New _Window") },
{ STOCK_FOLDER_NEW, N_("New _Folder") },
{ STOCK_BOOKMARK, N_("_Bookmark"), 0, 0, GTK_STOCK_FILE },
{ STOCK_BOOKMARKS, N_("_Bookmarks"), GDK_CONTROL_MASK | GDK_SHIFT_MASK, GDK_KEY_B, GTK_STOCK_DIRECTORY },
{ STOCK_BOOKMARK_ADD, N_("Add Boo_kmark"), 0, 0, "stock_add-bookmark" },
{ STOCK_CONSOLE, N_("_Console"), 0, 0, GTK_STOCK_DIALOG_WARNING },
{ STOCK_EXTENSIONS, N_("_Extensions"), 0, 0, GTK_STOCK_CONVERT },
{ STOCK_HISTORY, N_("_History"), GDK_CONTROL_MASK | GDK_SHIFT_MASK, GDK_KEY_H, GTK_STOCK_SORT_ASCENDING },
{ STOCK_HOMEPAGE, N_("_Homepage"), 0, 0, GTK_STOCK_HOME },
{ STOCK_SCRIPTS, N_("_Userscripts"), 0, 0, GTK_STOCK_EXECUTE },
{ STOCK_TAB_NEW, N_("New _Tab"), 0, 0, GTK_STOCK_ADD },
{ STOCK_TRANSFERS, N_("_Transfers"), GDK_CONTROL_MASK | GDK_SHIFT_MASK, GDK_KEY_J, GTK_STOCK_SAVE },
{ STOCK_PLUGINS, N_("Netscape p_lugins"), 0, 0, GTK_STOCK_CONVERT },
{ STOCK_USER_TRASH, N_("_Closed Tabs"), 0, 0, "gtk-undo-ltr" },
{ STOCK_WINDOW_NEW, N_("New _Window"), 0, 0, GTK_STOCK_ADD },
{ GTK_STOCK_DIRECTORY, N_("New _Folder"), 0, 0, NULL },
};
/* Preserve argument vector */
sokoke_get_argv (argument_vector);
/* libSoup uses threads, therefore if WebKit is built with libSoup
* or Midori is using it, we need to initialize threads. */
if (!g_thread_supported ()) g_thread_init (NULL);
#if ENABLE_NLS
setlocale (LC_ALL, "");
if (g_getenv ("MIDORI_NLSPATH"))
bindtextdomain (GETTEXT_PACKAGE, g_getenv ("MIDORI_NLSPATH"));
else
#ifdef G_OS_WIN32
{
gchar* path = sokoke_find_data_filename ("locale", FALSE);
bindtextdomain (GETTEXT_PACKAGE, path);
g_free (path);
}
#else
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
#endif
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
#endif
g_type_init ();
factory = gtk_icon_factory_new ();
for (i = 0; i < G_N_ELEMENTS (items); i++)
{
icon_set = gtk_icon_set_new ();
icon_source = gtk_icon_source_new ();
if (items[i].fallback)
{
gtk_icon_source_set_icon_name (icon_source, items[i].fallback);
items[i].fallback = NULL;
gtk_icon_set_add_source (icon_set, icon_source);
}
gtk_icon_source_set_icon_name (icon_source, items[i].stock_id);
gtk_icon_set_add_source (icon_set, icon_source);
gtk_icon_source_free (icon_source);
gtk_icon_factory_add (factory, items[i].stock_id, icon_set);
gtk_icon_set_unref (icon_set);
}
gtk_stock_add_static ((GtkStockItem*)items, G_N_ELEMENTS (items));
gtk_icon_factory_add_default (factory);
g_object_unref (factory);
#if HAVE_HILDON
/* Maemo doesn't theme stock icons. So we map platform icons
to stock icons. These are all monochrome toolbar icons. */
typedef struct
{
const gchar* stock_id;
const gchar* icon_name;
} CompatItem;
static CompatItem compat_items[] =
{
{ GTK_STOCK_ADD, "general_add" },
{ GTK_STOCK_BOLD, "general_bold" },
{ GTK_STOCK_CLOSE, "general_close_b" },
{ GTK_STOCK_DELETE, "general_delete" },
{ GTK_STOCK_DIRECTORY, "general_toolbar_folder" },
{ GTK_STOCK_FIND, "general_search" },
{ GTK_STOCK_FULLSCREEN, "general_fullsize_b" },
{ GTK_STOCK_GO_BACK, "general_back" },
{ GTK_STOCK_GO_FORWARD, "general_forward" },
{ GTK_STOCK_GO_UP, "filemanager_folder_up" },
{ GTK_STOCK_GOTO_FIRST, "pdf_viewer_first_page" },
{ GTK_STOCK_GOTO_LAST, "pdf_viewer_last_page" },
{ GTK_STOCK_INFO, "general_information" },
{ GTK_STOCK_ITALIC, "general_italic" },
{ GTK_STOCK_JUMP_TO, "general_move_to_folder" },
{ GTK_STOCK_PREFERENCES,"general_settings" },
{ GTK_STOCK_REFRESH, "general_refresh" },
{ GTK_STOCK_SAVE, "notes_save" },
{ GTK_STOCK_STOP, "general_stop" },
{ GTK_STOCK_UNDERLINE, "notes_underline" },
{ GTK_STOCK_ZOOM_IN, "pdf_zoomin" },
{ GTK_STOCK_ZOOM_OUT, "pdf_zoomout" },
};
factory = gtk_icon_factory_new ();
for (i = 0; i < G_N_ELEMENTS (compat_items); i++)
{
icon_set = gtk_icon_set_new ();
icon_source = gtk_icon_source_new ();
gtk_icon_source_set_icon_name (icon_source, compat_items[i].icon_name);
gtk_icon_set_add_source (icon_set, icon_source);
gtk_icon_source_free (icon_source);
gtk_icon_factory_add (factory, compat_items[i].stock_id, icon_set);
gtk_icon_set_unref (icon_set);
}
gtk_icon_factory_add_default (factory);
g_object_unref (factory);
#endif
/* Print messages to stdout on Win32 console, cf. AbiWord
* http://svn.abisource.com/abiword/trunk/src/wp/main/win/Win32Main.cpp */
#ifdef _WIN32
@ -1405,90 +1464,5 @@ midori_app_setup (gint *argc,
}
}
#endif
/* libSoup uses threads, therefore if WebKit is built with libSoup
* or Midori is using it, we need to initialize threads. */
#if !GLIB_CHECK_VERSION (2, 32, 0)
if (!g_thread_supported ()) g_thread_init (NULL);
#endif
/* Midori.Paths uses GFile */
g_type_init ();
/* Preserve argument vector */
midori_paths_init_exec_path (*argument_vector, *argc);
#if ENABLE_NLS
if (g_getenv ("MIDORI_NLSPATH"))
bindtextdomain (GETTEXT_PACKAGE, g_getenv ("MIDORI_NLSPATH"));
else
#ifdef G_OS_WIN32
{
gchar* path = midori_paths_get_data_filename ("locale", FALSE);
bindtextdomain (GETTEXT_PACKAGE, path);
g_free (path);
}
#else
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
#endif
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
#endif
success = gtk_init_with_args (argc, argument_vector, _("[Addresses]"),
entries, GETTEXT_PACKAGE, error);
factory = gtk_icon_factory_new ();
for (i = 0; i < G_N_ELEMENTS (items); i++)
{
icon_set = gtk_icon_set_new ();
icon_source = gtk_icon_source_new ();
gtk_icon_source_set_icon_name (icon_source, items[i].stock_id);
gtk_icon_set_add_source (icon_set, icon_source);
gtk_icon_source_free (icon_source);
gtk_icon_factory_add (factory, items[i].stock_id, icon_set);
gtk_icon_set_unref (icon_set);
}
gtk_stock_add_static ((GtkStockItem*)items, G_N_ELEMENTS (items));
gtk_icon_factory_add_default (factory);
g_object_unref (factory);
return success;
}
gboolean
midori_debug (const gchar* token)
{
static const gchar* debug_token = NULL;
const gchar* debug = g_getenv ("MIDORI_DEBUG");
const gchar* debug_tokens = "headers body referer cookies paths hsts unarmed ";
const gchar* full_debug_tokens = "adblock:match adblock:time startup bookmarks ";
if (debug_token == NULL)
{
gchar* found_token;
if (debug && (found_token = strstr (full_debug_tokens, debug)) && *(found_token + strlen (debug)) == ' ')
{
#ifdef G_ENABLE_DEBUG
debug_token = g_intern_static_string (debug);
#else
g_warning ("Value '%s' for MIDORI_DEBUG requires a full debugging build.", debug);
#endif
}
else if (debug && (found_token = strstr (debug_tokens, debug)) && *(found_token + strlen (debug)) == ' ')
debug_token = g_intern_static_string (debug);
else if (debug)
g_warning ("Unrecognized value '%s' for MIDORI_DEBUG.", debug);
else
debug_token = "NONE";
if (!debug_token)
{
debug_token = "INVALID";
g_print ("Supported values: %s\nWith full debugging: %s\n",
debug_tokens, full_debug_tokens);
}
}
if (debug_token != g_intern_static_string ("NONE")
&& !strstr (debug_tokens, token) && !strstr (full_debug_tokens, token))
g_warning ("Token '%s' passed to midori_debug is not a known token.", token);
return debug_token == g_intern_static_string (token);
}

View File

@ -41,9 +41,6 @@ midori_app_get_type (void) G_GNUC_CONST;
MidoriApp*
midori_app_new (void);
const gchar*
midori_app_get_name (MidoriApp* app);
gboolean
midori_app_instance_is_running (MidoriApp* app);
@ -82,14 +79,8 @@ midori_app_send_notification (MidoriApp* app,
const gchar* title,
const gchar* message);
gboolean
midori_app_setup (gint *argc,
gchar** *argument_vector,
const GOptionEntry *entries,
GError* *error);
gboolean
midori_debug (const gchar* token);
void
midori_app_setup (gchar** argument_vector);
G_END_DECLS

View File

@ -982,26 +982,24 @@ katze_item_set_value_from_column (sqlite3_stmt* stmt,
item->added = date;
}
else if (g_str_equal (name, "day") || g_str_equal (name, "app")
|| g_str_equal (name, "toolbar") || g_str_equal (name, "id")
|| g_str_equal (name, "parentid") || g_str_equal (name, "seq")
|| g_str_equal (name, "pos_panel") || g_str_equal (name, "pos_bar"))
|| g_str_equal (name, "toolbar"))
{
gint value;
value = sqlite3_column_int64 (stmt, column);
katze_item_set_meta_integer (item, name, value);
}
else if (g_str_equal (name, "folder"))
{
const unsigned char* folder;
folder = sqlite3_column_text (stmt, column);
katze_item_set_meta_string (item, name, (gchar*)folder);
}
else if (g_str_equal (name, "desc"))
{
const unsigned char* text;
text = sqlite3_column_text (stmt, column);
item->text = g_strdup ((gchar*)text);
}
else if (g_str_equal (name, "sql"))
{
const unsigned char* sql;
sql = sqlite3_column_text (stmt, column);
katze_item_set_meta_string (item, name, (gchar*)sql);
}
else
g_warn_if_reached ();
}
@ -1068,74 +1066,6 @@ katze_array_from_sqlite (sqlite3* db,
return katze_array_from_statement (stmt);
}
/**
* midori_array_query_recursive:
* @array: the main bookmark array
* @fields: comma separated list of fields
* @condition: condition, like "folder = '%q'"
* @value: a value to be inserted if @condition contains %q
* @recursive: if %TRUE include children
*
* Stores the result in a #KatzeArray.
*
* Return value: a #KatzeArray on success, %NULL otherwise
*
* Since: 0.4.4
**/
KatzeArray*
midori_array_query_recursive (KatzeArray* bookmarks,
const gchar* fields,
const gchar* condition,
const gchar* value,
gboolean recursive)
{
sqlite3* db;
gchar* sqlcmd;
char* sqlcmd_value;
KatzeArray* array;
KatzeItem* item;
GList* list;
g_return_val_if_fail (KATZE_IS_ARRAY (bookmarks), NULL);
g_return_val_if_fail (fields, NULL);
g_return_val_if_fail (condition, NULL);
db = g_object_get_data (G_OBJECT (bookmarks), "db");
if (db == NULL)
return NULL;
sqlcmd = g_strdup_printf ("SELECT %s FROM bookmarks WHERE %s "
"ORDER BY (uri='') ASC, title DESC", fields, condition);
if (strstr (condition, "%q"))
{
sqlcmd_value = sqlite3_mprintf (sqlcmd, value ? value : "");
array = katze_array_from_sqlite (db, sqlcmd_value);
sqlite3_free (sqlcmd_value);
}
else
array = katze_array_from_sqlite (db, sqlcmd);
g_free (sqlcmd);
if (!recursive)
return array;
KATZE_ARRAY_FOREACH_ITEM_L (item, array, list)
{
if (KATZE_ITEM_IS_FOLDER (item))
{
gchar* parentid = g_strdup_printf ("%" G_GINT64_FORMAT,
katze_item_get_meta_integer (item, "id"));
KatzeArray* subarray = midori_array_query_recursive (bookmarks,
fields, "parentid=%q", parentid, TRUE);
katze_item_set_name (KATZE_ITEM (subarray), item->name);
katze_array_add_item (array, subarray);
g_free (parentid);
}
}
g_list_free (list);
return array;
}
/**
* midori_array_query:
* @array: the main bookmark array
@ -1148,8 +1078,6 @@ midori_array_query_recursive (KatzeArray* bookmarks,
* Return value: a #KatzeArray on success, %NULL otherwise
*
* Since: 0.4.3
*
* Deprecated: 0.4.4: Use midori_array_query_recursive() instead.
**/
KatzeArray*
midori_array_query (KatzeArray* bookmarks,
@ -1157,6 +1085,29 @@ midori_array_query (KatzeArray* bookmarks,
const gchar* condition,
const gchar* value)
{
return midori_array_query_recursive (bookmarks, fields, condition, value, FALSE);
sqlite3* db;
gchar* sqlcmd;
char* sqlcmd_value;
KatzeArray* array;
g_return_val_if_fail (KATZE_IS_ARRAY (bookmarks), NULL);
g_return_val_if_fail (fields, NULL);
g_return_val_if_fail (condition, NULL);
db = g_object_get_data (G_OBJECT (bookmarks), "db");
if (db == NULL)
return NULL;
sqlcmd = g_strdup_printf ("SELECT %s FROM bookmarks WHERE %s "
"ORDER BY title DESC", fields, condition);
if (strstr (condition, "%q"))
{
sqlcmd_value = sqlite3_mprintf (sqlcmd, value ? value : "");
array = katze_array_from_sqlite (db, sqlcmd_value);
sqlite3_free (sqlcmd_value);
}
else
array = katze_array_from_sqlite (db, sqlcmd);
g_free (sqlcmd);
return array;
}

View File

@ -36,13 +36,6 @@ midori_array_query (KatzeArray* array,
const gchar* condition,
const gchar* value);
KatzeArray*
midori_array_query_recursive (KatzeArray* array,
const gchar* fields,
const gchar* condition,
const gchar* value,
gboolean recursive);
KatzeArray*
katze_array_from_sqlite (sqlite3* db,
const gchar* sqlcmd);

View File

@ -1,335 +0,0 @@
/*
Copyright (C) 2010 Christian Dywan <christian@twotoasts.de>
Copyright (C) 2010 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.
See the file COPYING for the full license text.
*/
#include "midori-bookmarks.h"
#include "panels/midori-bookmarks.h"
#include "midori-array.h"
#include "sokoke.h"
#include "midori-core.h"
#include <glib/gstdio.h>
#include <glib/gi18n.h>
#include <config.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef G_ENABLE_DEBUG
void midori_bookmarks_dbtracer(void* dummy, const char* query)
{
g_printerr ("%s\n", query);
}
#endif
void
midori_bookmarks_add_item_cb (KatzeArray* array,
KatzeItem* item,
sqlite3* db)
{
midori_bookmarks_insert_item_db (db, item,
katze_item_get_meta_integer (item, "parentid"));
}
void
midori_bookmarks_remove_item_cb (KatzeArray* array,
KatzeItem* item,
sqlite3* db)
{
gchar* sqlcmd;
char* errmsg = NULL;
sqlcmd = sqlite3_mprintf (
"DELETE FROM bookmarks WHERE id = %" G_GINT64_FORMAT ";",
katze_item_get_meta_integer (item, "id"));
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);
}
#define _APPEND_TO_SQL_ERRORMSG(custom_errmsg) \
do { \
if (sql_errmsg) \
{ \
g_string_append_printf (errmsg_str, "%s : %s\n", custom_errmsg, sql_errmsg); \
sqlite3_free (sql_errmsg); \
} \
else \
g_string_append (errmsg_str, custom_errmsg); \
} while (0)
gboolean
midori_bookmarks_import_from_old_db (sqlite3* db,
const gchar* oldfile,
gchar** errmsg)
{
gint sql_errcode;
gboolean failure = FALSE;
gchar* sql_errmsg = NULL;
GString* errmsg_str = g_string_new (NULL);
gchar* attach_stmt = sqlite3_mprintf ("ATTACH DATABASE %Q AS old_db;", oldfile);
const gchar* convert_stmts =
"BEGIN TRANSACTION;"
"INSERT INTO main.bookmarks (parentid, title, uri, desc, app, toolbar) "
"SELECT NULL AS parentid, title, uri, desc, app, toolbar "
"FROM old_db.bookmarks;"
"UPDATE main.bookmarks SET parentid = ("
"SELECT id FROM main.bookmarks AS b1 WHERE b1.title = ("
"SELECT folder FROM old_db.bookmarks WHERE title = main.bookmarks.title));"
"COMMIT;";
const gchar* detach_stmt = "DETACH DATABASE old_db;";
*errmsg = NULL;
sql_errcode = sqlite3_exec (db, attach_stmt, NULL, NULL, &sql_errmsg);
sqlite3_free (attach_stmt);
if (sql_errcode != SQLITE_OK)
{
_APPEND_TO_SQL_ERRORMSG (_("failed to ATTACH old db"));
goto convert_failed;
}
if (sqlite3_exec (db, convert_stmts, NULL, NULL, &sql_errmsg) != SQLITE_OK)
{
failure = TRUE;
_APPEND_TO_SQL_ERRORMSG (_("failed to import from old db"));
/* try to get back to previous state */
if (sqlite3_exec (db, "ROLLBACK TRANSACTION;", NULL, NULL, &sql_errmsg) != SQLITE_OK)
_APPEND_TO_SQL_ERRORMSG (_("failed to rollback the transaction"));
}
if (sqlite3_exec (db, detach_stmt, NULL, NULL, &sql_errmsg) != SQLITE_OK)
_APPEND_TO_SQL_ERRORMSG (_("failed to DETACH "));
if (failure)
{
convert_failed:
*errmsg = g_string_free (errmsg_str, FALSE);
g_print ("ERRORR: %s\n", errmsg_str->str);
return FALSE;
}
return TRUE;
}
#undef _APPEND_TO_SQL_ERRORMSG
sqlite3*
midori_bookmarks_initialize (KatzeArray* array,
char** errmsg)
{
sqlite3* db;
gchar* oldfile;
gchar* newfile;
gboolean newfile_did_exist, oldfile_exists;
const gchar* create_stmt;
gchar* sql_errmsg = NULL;
gchar* import_errmsg = NULL;
g_return_val_if_fail (errmsg != NULL, NULL);
oldfile = g_build_filename (midori_paths_get_config_dir (), "bookmarks.db", NULL);
oldfile_exists = g_access (oldfile, F_OK) == 0;
newfile = g_build_filename (midori_paths_get_config_dir (), "bookmarks_v2.db", NULL);
newfile_did_exist = g_access (newfile, F_OK) == 0;
/* sqlite3_open will create the file if it did not exists already */
if (sqlite3_open (newfile, &db) != SQLITE_OK)
{
if (db)
*errmsg = g_strdup_printf (_("failed to open database: %s\n"),
sqlite3_errmsg (db));
else
*errmsg = g_strdup (_("failed to open database\n"));
goto init_failed;
}
#ifdef G_ENABLE_DEBUG
if (midori_debug ("bookmarks"))
sqlite3_trace (db, midori_bookmarks_dbtracer, NULL);
#endif
create_stmt = /* Table structure */
"CREATE TABLE IF NOT EXISTS bookmarks "
"(id INTEGER PRIMARY KEY AUTOINCREMENT, "
"parentid INTEGER DEFAULT NULL, "
"title TEXT, uri TEXT, desc TEXT, app INTEGER, toolbar INTEGER, "
"pos_panel INTEGER, pos_bar INTEGER, "
"created DATE DEFAULT CURRENT_TIMESTAMP, "
"last_visit DATE, visit_count INTEGER DEFAULT 0, "
"nick TEXT, "
"FOREIGN KEY(parentid) REFERENCES bookmarks(id) "
"ON DELETE CASCADE); PRAGMA foreign_keys = ON;"
/* trigger: insert panel position */
"CREATE TRIGGER IF NOT EXISTS bookmarkInsertPosPanel "
"AFTER INSERT ON bookmarks FOR EACH ROW "
"BEGIN UPDATE bookmarks SET pos_panel = ("
"SELECT ifnull(MAX(pos_panel),0)+1 FROM bookmarks WHERE "
"(NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
"OR (NEW.parentid IS NULL AND parentid IS NULL)) "
"WHERE id = NEW.id; END;"
/* trigger: insert Bookmarkbar position */
"CREATE TRIGGER IF NOT EXISTS bookmarkInsertPosBar "
"AFTER INSERT ON bookmarks FOR EACH ROW WHEN NEW.toolbar=1 "
"BEGIN UPDATE bookmarks SET pos_bar = ("
"SELECT ifnull(MAX(pos_bar),0)+1 FROM bookmarks WHERE "
"((NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
"OR (NEW.parentid IS NULL AND parentid IS NULL)) AND toolbar=1) "
"WHERE id = NEW.id; END;"
/* trigger: update panel position */
"CREATE TRIGGER IF NOT EXISTS bookmarkUpdatePosPanel "
"BEFORE UPDATE OF parentid ON bookmarks FOR EACH ROW "
"WHEN ((NEW.parentid IS NULL OR OLD.parentid IS NULL) "
"AND NEW.parentid IS NOT OLD.parentid) OR "
"((NEW.parentid IS NOT NULL AND OLD.parentid IS NOT NULL) "
"AND NEW.parentid!=OLD.parentid) "
"BEGIN UPDATE bookmarks SET pos_panel = pos_panel-1 "
"WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
"OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_panel > OLD.pos_panel; "
"UPDATE bookmarks SET pos_panel = ("
"SELECT ifnull(MAX(pos_panel),0)+1 FROM bookmarks "
"WHERE (NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
"OR (NEW.parentid IS NULL AND parentid IS NULL)) "
"WHERE id = OLD.id; END;"
/* trigger: update Bookmarkbar position */
"CREATE TRIGGER IF NOT EXISTS bookmarkUpdatePosBar0 "
"AFTER UPDATE OF parentid, toolbar ON bookmarks FOR EACH ROW "
"WHEN ((NEW.parentid IS NULL OR OLD.parentid IS NULL) "
"AND NEW.parentid IS NOT OLD.parentid) "
"OR ((NEW.parentid IS NOT NULL AND OLD.parentid IS NOT NULL) "
"AND NEW.parentid!=OLD.parentid) OR (OLD.toolbar=1 AND NEW.toolbar=0) "
"BEGIN UPDATE bookmarks SET pos_bar = NULL WHERE id = NEW.id; "
"UPDATE bookmarks SET pos_bar = pos_bar-1 "
"WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
"OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_bar > OLD.pos_bar; END;"
/* trigger: update Bookmarkbar position */
"CREATE TRIGGER IF NOT EXISTS bookmarkUpdatePosBar1 "
"BEFORE UPDATE OF parentid, toolbar ON bookmarks FOR EACH ROW "
"WHEN ((NEW.parentid IS NULL OR OLD.parentid IS NULL) "
"AND NEW.parentid IS NOT OLD.parentid) OR "
"((NEW.parentid IS NOT NULL AND OLD.parentid IS NOT NULL) "
"AND NEW.parentid!=OLD.parentid) OR (OLD.toolbar=0 AND NEW.toolbar=1) "
"BEGIN UPDATE bookmarks SET pos_bar = ("
"SELECT ifnull(MAX(pos_bar),0)+1 FROM bookmarks WHERE "
"(NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
"OR (NEW.parentid IS NULL AND parentid IS NULL)) "
"WHERE id = OLD.id; END;"
/* trigger: delete panel position */
"CREATE TRIGGER IF NOT EXISTS bookmarkDeletePosPanel "
"AFTER DELETE ON bookmarks FOR EACH ROW "
"BEGIN UPDATE bookmarks SET pos_panel = pos_panel-1 "
"WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
"OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_panel > OLD.pos_panel; END;"
/* trigger: delete Bookmarkbar position */
"CREATE TRIGGER IF NOT EXISTS bookmarkDeletePosBar "
"AFTER DELETE ON bookmarks FOR EACH ROW WHEN OLD.toolbar=1 "
"BEGIN UPDATE bookmarks SET pos_bar = pos_bar-1 "
"WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
"OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_bar > OLD.pos_bar; END;";
if (newfile_did_exist)
{
/* we are done */
goto init_success;
}
else
{
/* initial creation */
if (sqlite3_exec (db, create_stmt, NULL, NULL, &sql_errmsg) != SQLITE_OK)
{
if (errmsg)
{
if (sql_errmsg)
{
*errmsg = g_strdup_printf (_("could not create bookmarks table: %s\n"), sql_errmsg);
sqlite3_free (sql_errmsg);
}
else
*errmsg = g_strdup (_("could not create bookmarks table"));
}
/* we can as well remove the new file */
g_unlink (newfile);
goto init_failed;
}
}
if (oldfile_exists)
/* import from old db */
if (!midori_bookmarks_import_from_old_db (db, oldfile, &import_errmsg))
{
if (errmsg)
{
if (import_errmsg)
{
*errmsg = g_strdup_printf (_("could not import from old database: %s\n"), import_errmsg);
g_free (import_errmsg);
}
else
*errmsg = g_strdup_printf (_("could not import from old database"));
}
}
init_success:
g_free (newfile);
g_free (oldfile);
g_signal_connect (array, "add-item",
G_CALLBACK (midori_bookmarks_add_item_cb), db);
g_signal_connect (array, "remove-item",
G_CALLBACK (midori_bookmarks_remove_item_cb), db);
return db;
init_failed:
g_free (newfile);
g_free (oldfile);
if (db)
sqlite3_close (db);
return NULL;
}
void
midori_bookmarks_import (const gchar* filename,
sqlite3* db)
{
KatzeArray* bookmarks;
GError* error = NULL;
bookmarks = katze_array_new (KATZE_TYPE_ARRAY);
if (!midori_array_from_file (bookmarks, filename, "xbel", &error))
{
g_warning (_("The bookmarks couldn't be saved. %s"), error->message);
g_error_free (error);
return;
}
midori_bookmarks_import_array_db (db, bookmarks, 0);
}

View File

@ -1,32 +0,0 @@
/*
Copyright (C) 2010 Christian Dywan <christian@twotoasts.de>
Copyright (C) 2010 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.
See the file COPYING for the full license text.
*/
#include <sqlite3.h>
#include <katze/katze.h>
void
midori_bookmarks_add_item_cb (KatzeArray* array,
KatzeItem* item,
sqlite3* db);
void
midori_bookmarks_remove_item_cb (KatzeArray* array,
KatzeItem* item,
sqlite3* db);
sqlite3*
midori_bookmarks_initialize (KatzeArray* array,
char** errmsg);
void
midori_bookmarks_import (const gchar* filename,
sqlite3* db);

File diff suppressed because it is too large Load Diff

View File

@ -152,16 +152,9 @@ GtkWidget*
midori_browser_get_current_tab (MidoriBrowser* browser);
#define midori_browser_get_tab midori_browser_get_current_tab
gint
midori_browser_page_num (MidoriBrowser* browser,
GtkWidget* view);
GList*
midori_browser_get_tabs (MidoriBrowser* browser);
gint
midori_browser_get_n_pages (MidoriBrowser* browser);
KatzeArray*
midori_browser_get_proxy_items (MidoriBrowser* browser);
@ -180,11 +173,6 @@ midori_browser_get_toolbar_actions (MidoriBrowser* browser);
MidoriWebSettings*
midori_browser_get_settings (MidoriBrowser* browser);
void
midori_browser_update_history (KatzeItem* item,
const gchar* type,
const gchar* event);
G_END_DECLS
#endif /* __MIDORI_BROWSER_H__ */

View File

@ -1,320 +0,0 @@
/*
Copyright (C) 2012 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.
*/
namespace Sokoke {
extern static bool show_uri (Gdk.Screen screen, string uri, uint32 timestamp) throws Error;
extern static bool message_dialog (Gtk.MessageType type, string short, string detailed, bool modal);
}
namespace Midori {
namespace Download {
public static bool is_finished (WebKit.Download download) {
switch (download.status) {
case WebKit.DownloadStatus.FINISHED:
case WebKit.DownloadStatus.CANCELLED:
case WebKit.DownloadStatus.ERROR:
return true;
default:
return false;
}
}
public static int get_type (WebKit.Download download) {
return download.get_data<int> ("midori-download-type");
}
public static void set_type (WebKit.Download download, int type) {
download.set_data<int> ("midori-download-type", type);
}
public static double get_progress (WebKit.Download download) {
/* Avoid a bug in WebKit */
if (download.status == WebKit.DownloadStatus.CREATED)
return 0.0;
return download.progress;
}
public static string get_tooltip (WebKit.Download download) {
string filename = Path.get_basename (download.destination_uri);
/* i18n: Download tooltip (size): 4KB of 43MB */
string size = _("%s of %s").printf (
format_size (download.current_size),
format_size (download.total_size));
/* Finished, no speed or remaining time */
if (is_finished (download) || download.status == WebKit.DownloadStatus.CREATED)
return "%s\n%s".printf (filename, size);
uint64 total_size = download.total_size, current_size = download.current_size;
double elapsed = download.get_elapsed_time (),
diff = elapsed / current_size,
estimated = (total_size - current_size) * diff;
int hour = 3600, minute = 60;
int hours = (int)(estimated / hour),
minutes = (int)((estimated - (hours * hour)) / minute),
seconds = (int)((estimated - (hours * hour) - (minutes * minute)));
string hours_ = ngettext ("%d hour", "%d hours", hours).printf (hours);
string minutes_ = ngettext ("%d minute", "%d minutes", minutes).printf (minutes);
string seconds_ = ngettext ("%d second", "%d seconds", seconds).printf (seconds);
double last_time = download.get_data<int> ("last-time");
uint64 last_size = download.get_data<uint64> ("last-size");
string eta = "";
if (estimated > 0) {
if (hours > 0)
eta = hours_ + ", " + minutes_;
else if (minutes >= 10)
eta = minutes_;
else if (minutes < 10 && minutes > 0)
eta = minutes_ + ", " + seconds_;
else if (seconds > 0)
eta = seconds_;
if (eta != "")
/* i18n: Download tooltip (estimated time) : - 1 hour, 5 minutes remaning */
eta = _(" - %s remaining").printf (eta);
}
string speed;
if (elapsed != last_time) {
speed = format_size ((uint64)(
(current_size - last_size) / (elapsed - last_time)));
}
else
/* i18n: Unknown number of bytes, used for transfer rate like ?B/s */
speed = _("?B");
/* i18n: Download tooltip (transfer rate): (130KB/s) */
speed = _(" (%s/s)").printf (speed);
if (elapsed - last_time > 5.0) {
download.set_data<int> ("last-time", (int)elapsed);
download.set_data<uint64> ("last-size", current_size);
}
return "%s\n%s %s%s".printf (filename, size, speed, eta);
}
public static string get_content_type (WebKit.Download download, string? mime_type) {
string? content_type = ContentType.guess (download.suggested_filename, null, null);
if (content_type == null) {
content_type = ContentType.from_mime_type (mime_type);
if (content_type == null)
content_type = ContentType.from_mime_type ("application/octet-stream");
}
return content_type;
}
public static bool has_wrong_checksum (WebKit.Download download) {
int status = download.get_data<int> ("checksum-status");
if (status == 0) {
/* Link Fingerprint */
string? original_uri = download.network_request.get_data<string> ("midori-original-uri");
if (original_uri == null)
original_uri = download.get_uri ();
string? fingerprint;
ChecksumType checksum_type = URI.get_fingerprint (original_uri, out fingerprint, null);
/* By default, no wrong checksum */
status = 2;
if (fingerprint != null) {
try {
string filename = Filename.from_uri (download.destination_uri);
string contents;
size_t length;
bool y = FileUtils.get_contents (filename, out contents, out length);
string checksum = Checksum.compute_for_string (checksum_type, contents, length);
/* Checksums are case-insensitive */
if (!y || fingerprint.ascii_casecmp (checksum) != 0)
status = 1; /* wrong checksum */
}
catch (Error error) {
status = 1; /* wrong checksum */
}
}
download.set_data<int> ("checksum-status", status);
}
return status == 1;
}
public static bool action_clear (WebKit.Download download, Gtk.Widget widget) throws Error {
switch (download.status) {
case WebKit.DownloadStatus.CREATED:
case WebKit.DownloadStatus.STARTED:
download.cancel ();
break;
case WebKit.DownloadStatus.FINISHED:
if (open (download, widget))
return true;
break;
case WebKit.DownloadStatus.CANCELLED:
return true;
default:
critical ("action_clear: %d", download.status);
warn_if_reached ();
break;
}
return false;
}
public static string action_stock_id (WebKit.Download download) {
switch (download.status) {
case WebKit.DownloadStatus.CREATED:
case WebKit.DownloadStatus.STARTED:
return Gtk.Stock.CANCEL;
case WebKit.DownloadStatus.FINISHED:
if (has_wrong_checksum (download))
return Gtk.Stock.DIALOG_WARNING;
return Gtk.Stock.OPEN;
case WebKit.DownloadStatus.CANCELLED:
return Gtk.Stock.CLEAR;
default:
critical ("action_stock_id: %d", download.status);
warn_if_reached ();
return Gtk.Stock.MISSING_IMAGE;
}
}
public static bool open (WebKit.Download download, Gtk.Widget widget) throws Error {
if (!has_wrong_checksum (download))
return Sokoke.show_uri (widget.get_screen (),
download.destination_uri, Gtk.get_current_event_time ());
Sokoke.message_dialog (Gtk.MessageType.WARNING,
_("The downloaded file is erroneous."),
_("The checksum provided with the link did not match. This means the file is probably incomplete or was modified afterwards."),
true);
return false;
}
public unowned string fallback_extension (string? extension, string mime_type) {
if (extension != null && extension[0] != '\0')
return extension;
if ("css" in mime_type)
return ".css";
if ("javascript" in mime_type)
return ".js";
if ("html" in mime_type)
return ".htm";
if ("plain" in mime_type)
return ".txt";
return "";
}
public string clean_filename (string filename) {
#if HAVE_WIN32
return filename.delimit ("/\\<>:\"|?*", '_');
#else
return filename.delimit ("/", '_');
#endif
}
public string get_suggested_filename (WebKit.Download download) {
/* https://bugs.webkit.org/show_bug.cgi?id=83161
https://d19vezwu8eufl6.cloudfront.net/nlp/slides%2F03-01-FormalizingNB.pdf */
return clean_filename (download.get_suggested_filename ());
}
public string get_filename_suggestion_for_uri (string mime_type, string uri) {
/* Try to provide a good default filename, UTF-8 encoded */
string filename = clean_filename (Soup.URI.decode (uri));
/* Take the rest of the URI if needed */
if (filename.has_suffix ("/") || uri.index_of_char ('.') == -1)
return Path.build_filename (filename, fallback_extension (null, mime_type));
return filename;
}
public static string? get_extension_for_uri (string uri, out string basename = null) {
if (&basename != null)
basename = null;
/* Find the last slash and the last period *after* the last slash. */
int last_slash = uri.last_index_of_char ('/');
/* Huh, URI without slashes? */
if (last_slash == -1)
return null;
int period = uri.last_index_of_char ('.', last_slash);
if (period == -1)
return null;
/* The extension, or "." if it ended with a period */
string extension = uri.substring (period, -1);
if (&basename != null)
basename = uri.substring (0, period);
return extension;
}
public string get_unique_filename (string filename) {
if (Posix.access (filename, Posix.F_OK) == 0) {
string basename;
string? extension = get_extension_for_uri (filename, out basename);
string? new_filename = null;
int i = 0;
do {
new_filename = "%s-%d%s".printf (basename, i++, extension ?? "");
} while (Posix.access (new_filename, Posix.F_OK) == 0);
return new_filename;
}
return filename;
}
public string prepare_destination_uri (WebKit.Download download, string? folder) {
string suggested_filename = get_suggested_filename (download);
string basename = File.new_for_uri (suggested_filename).get_basename ();
string download_dir;
if (folder == null) {
download_dir = Paths.get_tmp_dir ();
Katze.mkdir_with_parents (download_dir, 0700);
}
else
download_dir = folder;
string destination_filename = Path.build_filename (download_dir, basename);
try {
return Filename.to_uri (get_unique_filename (destination_filename));
}
catch (Error error) {
return "file://" + destination_filename;
}
}
public static bool has_enough_space (WebKit.Download download, string uri) {
var folder = File.new_for_uri (uri).get_parent ();
bool can_write;
uint64 free_space;
try {
var info = folder.query_filesystem_info ("filesystem::free");
free_space = info.get_attribute_uint64 ("filesystem::free");
info = folder.query_info ("access::can-write", 0);
can_write = info.get_attribute_boolean ("access::can-write");
}
catch (Error error) {
can_write = false;
free_space = 0;
}
if (free_space < download.total_size || !can_write) {
string message;
string detailed_message;
if (!can_write) {
message = _("The file \"%s\" can't be saved in this folder.").printf (
Path.get_basename (uri));
detailed_message = _("You don't have permission to write in this location.");
}
else if (free_space < download.total_size) {
message = _("There is not enough free space to download \"%s\".").printf (
Path.get_basename (uri));
detailed_message = _("The file needs %s but only %s are left.").printf (
format_size (download.total_size), format_size (free_space));
}
else
assert_not_reached ();
Sokoke.message_dialog (Gtk.MessageType.ERROR, message, detailed_message, false);
return false;
}
return true;
}
}
}

View File

@ -14,7 +14,6 @@
#include <katze/katze.h>
#include "midori-platform.h"
#include "midori-core.h"
#include <glib/gi18n.h>
G_DEFINE_TYPE (MidoriExtension, midori_extension, G_TYPE_OBJECT);
@ -26,7 +25,6 @@ struct _MidoriExtensionPrivate
gchar* version;
gchar* authors;
gchar* website;
gchar* key;
MidoriApp* app;
gint active;
@ -129,8 +127,7 @@ enum
PROP_DESCRIPTION,
PROP_VERSION,
PROP_AUTHORS,
PROP_WEBSITE,
PROP_KEY
PROP_WEBSITE
};
enum {
@ -263,23 +260,6 @@ midori_extension_class_init (MidoriExtensionClass* class)
NULL,
flags));
/**
* MidoriExtension:key:
*
* The extension key.
* Needed if there is more than one extension object in a single module.
*
* Since: 0.4.5
*/
g_object_class_install_property (gobject_class,
PROP_KEY,
g_param_spec_string (
"key",
"Key",
"The extension key",
NULL,
flags));
g_type_class_add_private (class, sizeof (MidoriExtensionPrivate));
}
@ -318,10 +298,10 @@ midori_extension_activate_cb (MidoriExtension* extension,
strlen (filename) - strlen ("." G_MODULE_SUFFIX));
else
filename = g_strdup (filename);
folder = g_build_filename ("extensions", filename, NULL);
folder = g_strconcat ("extensions/", filename, NULL);
g_free (filename);
katze_assign (config_file,
midori_paths_get_preset_filename (folder, "config"));
sokoke_find_config_filename (folder, "config"));
g_free (folder);
g_key_file_load_from_file (extension->priv->key_file, config_file,
G_KEY_FILE_KEEP_COMMENTS, NULL);
@ -341,32 +321,29 @@ midori_extension_activate_cb (MidoriExtension* extension,
if (setting->type == G_TYPE_BOOLEAN)
{
MESettingBoolean* setting_ = (MESettingBoolean*)setting;
if (extension->priv->key_file
&& g_key_file_has_key (extension->priv->key_file, "settings", setting_->name, NULL))
setting_->value = g_key_file_get_boolean (extension->priv->key_file,
"settings", setting->name, NULL);
if (extension->priv->key_file)
setting_->value = sokoke_key_file_get_boolean_default (
extension->priv->key_file,
"settings", setting->name, setting_->default_value, NULL);
else
setting_->value = setting_->default_value;
}
else if (setting->type == G_TYPE_INT)
{
MESettingInteger* setting_ = (MESettingInteger*)setting;
if (extension->priv->key_file
&& g_key_file_has_key (extension->priv->key_file, "settings", setting_->name, NULL))
setting_->value = g_key_file_get_integer (extension->priv->key_file,
"settings", setting_->name, NULL);
if (extension->priv->key_file)
setting_->value = sokoke_key_file_get_integer_default (
extension->priv->key_file,
"settings", setting->name, setting_->default_value, NULL);
else
setting_->value = setting_->default_value;
}
else if (setting->type == G_TYPE_STRING)
{
if (extension->priv->key_file)
{
setting->value = g_key_file_get_string (
extension->priv->key_file, "settings", setting->name, NULL);
if (setting->value == NULL)
setting->value = setting->default_value;
}
setting->value = sokoke_key_file_get_string_default (
extension->priv->key_file,
"settings", setting->name, setting->default_value, NULL);
else
setting->value = g_strdup (setting->default_value);
}
@ -375,10 +352,10 @@ midori_extension_activate_cb (MidoriExtension* extension,
MESettingStringList* setting_ = (MESettingStringList*)setting;
if (extension->priv->key_file)
{
setting_->value = g_key_file_get_string_list (extension->priv->key_file,
"settings", setting->name, &setting_->length, NULL);
if (setting_->value == NULL)
setting_->value = g_strdupv (setting_->default_value);
setting_->value = sokoke_key_file_get_string_list_default (
extension->priv->key_file,
"settings", setting->name, &setting_->length,
setting_->default_value, &setting_->default_length, NULL);
}
else
setting_->value = g_strdupv (setting_->default_value);
@ -423,7 +400,6 @@ midori_extension_finalize (GObject* object)
katze_assign (extension->priv->version, NULL);
katze_assign (extension->priv->authors, NULL);
katze_assign (extension->priv->website, NULL);
katze_assign (extension->priv->key, NULL);
katze_assign (extension->priv->config_dir, NULL);
g_list_free (extension->priv->lsettings);
@ -470,9 +446,6 @@ midori_extension_set_property (GObject* object,
case PROP_WEBSITE:
katze_assign (extension->priv->website, g_value_dup_string (value));
break;
case PROP_KEY:
katze_assign (extension->priv->key, g_value_dup_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -504,9 +477,6 @@ midori_extension_get_property (GObject* object,
case PROP_WEBSITE:
g_value_set_string (value, extension->priv->website);
break;
case PROP_KEY:
g_value_set_string (value, extension->priv->key);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -649,11 +619,10 @@ midori_extension_get_config_dir (MidoriExtension* extension)
if (!extension->priv->config_dir)
{
gchar* filename = g_object_get_data (G_OBJECT (extension), "filename");
if (filename != NULL)
extension->priv->config_dir = g_build_filename (
midori_paths_get_config_dir (), "extensions", filename, NULL);
else
extension->priv->config_dir = NULL;
if (!filename)
return "/";
extension->priv->config_dir = g_build_filename (
sokoke_set_config_dir (NULL), "extensions", filename, NULL);
}
return extension->priv->config_dir;

File diff suppressed because it is too large Load Diff

227
midori/midori-panedaction.c Normal file
View File

@ -0,0 +1,227 @@
/*
Copyright (C) 2011 Peter Hatina <phatina@redhat.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.
See the file COPYING for the full license text.
*/
#include <string.h>
#include <katze/katze.h>
#include "midori-panedaction.h"
struct _MidoriPanedActionChild
{
GtkWidget* widget;
gchar* name;
gboolean resize;
gboolean shrink;
};
struct _MidoriPanedAction
{
GtkAction parent_instance;
GtkWidget* hpaned;
GtkWidget* toolitem;
struct _MidoriPanedActionChild child1;
struct _MidoriPanedActionChild child2;
};
struct _MidoriPanedActionClass
{
GtkActionClass parent_class;
};
G_DEFINE_TYPE (MidoriPanedAction, midori_paned_action, GTK_TYPE_ACTION);
static GtkWidget*
midori_paned_action_create_tool_item (GtkAction *action);
static void
midori_paned_action_finalize (GObject* object);
static void
midori_paned_action_init (MidoriPanedAction* paned_action)
{
paned_action->hpaned = NULL;
paned_action->toolitem = NULL;
memset ((void*) &paned_action->child1, 0, sizeof (struct _MidoriPanedActionChild));
memset ((void*) &paned_action->child2, 0, sizeof (struct _MidoriPanedActionChild));
}
static void
midori_paned_action_finalize (GObject* object)
{
MidoriPanedAction* paned_action = MIDORI_PANED_ACTION (object);
g_object_unref (G_OBJECT (paned_action->toolitem));
g_object_unref (G_OBJECT (paned_action->hpaned));
katze_assign (paned_action->child1.name, NULL);
katze_assign (paned_action->child2.name, NULL);
G_OBJECT_CLASS (midori_paned_action_parent_class)->finalize (object);
}
static void
midori_paned_action_class_init (MidoriPanedActionClass* class)
{
GObjectClass* gobject_class;
GtkActionClass* action_class;
gobject_class = G_OBJECT_CLASS (class);
gobject_class->finalize = midori_paned_action_finalize;
action_class = GTK_ACTION_CLASS (class);
action_class->create_tool_item = midori_paned_action_create_tool_item;
}
static GtkWidget*
midori_paned_action_create_tool_item (GtkAction* action)
{
MidoriPanedAction* paned_action = MIDORI_PANED_ACTION (action);
GtkWidget* alignment = gtk_alignment_new (0.0f, 0.5f, 1.0f, 0.1f);
paned_action->hpaned = gtk_hpaned_new ();
paned_action->toolitem = GTK_WIDGET (gtk_tool_item_new ());
gtk_tool_item_set_expand (GTK_TOOL_ITEM (paned_action->toolitem), TRUE);
gtk_container_add (GTK_CONTAINER (paned_action->toolitem), alignment);
gtk_container_add (GTK_CONTAINER (alignment), GTK_WIDGET (paned_action->hpaned));
gtk_paned_pack1 (GTK_PANED (paned_action->hpaned),
paned_action->child1.widget,
paned_action->child1.resize,
paned_action->child1.shrink);
gtk_paned_pack2 (GTK_PANED (paned_action->hpaned),
paned_action->child2.widget,
paned_action->child2.resize,
paned_action->child2.shrink);
gtk_widget_show_all (GTK_WIDGET (paned_action->toolitem));
return paned_action->toolitem;
}
/**
* midori_paned_action_set_child1:
* @paned_action: a #MidoriPanedAction
* @child1: a #GtkWidget to be added into GtkHPaned container
* @name: string name for the child2
* @resize: should child1 expand when the MidoriPanedAction is resized
* @shrink: can child1 be made smaller than its requisition
**/
void
midori_paned_action_set_child1 (MidoriPanedAction* paned_action,
GtkWidget* child1,
const gchar* name,
gboolean resize,
gboolean shrink)
{
g_return_if_fail (MIDORI_IS_PANED_ACTION (paned_action));
katze_assign (paned_action->child1.name, g_strdup (name));
paned_action->child1.widget = child1;
paned_action->child1.resize = resize;
paned_action->child1.shrink = shrink;
}
/**
* midori_paned_action_set_child1:
* @paned_action: a #MidoriPanedAction
* @child2: a #GtkWidget to be added into GtkHPaned container
* @name: string name for the child2
* @resize: should child2 expand when the MidoriPanedAction is resized
* @shrink: can child2 be made smaller than its requisition
**/
void
midori_paned_action_set_child2 (MidoriPanedAction* paned_action,
GtkWidget* child2,
const gchar* name,
gboolean resize,
gboolean shrink)
{
g_return_if_fail (MIDORI_IS_PANED_ACTION (paned_action));
katze_assign (paned_action->child2.name, g_strdup (name));
paned_action->child2.widget = child2;
paned_action->child2.resize = resize;
paned_action->child2.shrink = shrink;
}
/**
* midori_paned_action_get_child1:
* @paned_action: a #MidoriPanedAction
*
* returns the first child held in GtkHPaned container
**/
GtkWidget*
midori_paned_action_get_child1 (MidoriPanedAction* paned_action)
{
g_return_val_if_fail (MIDORI_IS_PANED_ACTION (paned_action), NULL);
return paned_action->child1.widget;
}
/**
* midori_paned_action_get_child1:
* @paned_action: a #MidoriPanedAction
*
* returns the second child held in GtkHPaned container
**/
GtkWidget*
midori_paned_action_get_child2 (MidoriPanedAction* paned_action)
{
g_return_val_if_fail (MIDORI_IS_PANED_ACTION (paned_action), NULL);
return paned_action->child2.widget;
}
/**
* midori_paned_action_get_child1:
* @paned_action: a #MidoriPanedAction
* @name: string name for one of the children
*
* returns a child specified by its name
**/
GtkWidget*
midori_paned_action_get_child_by_name (MidoriPanedAction* paned_action,
const gchar* name)
{
g_return_val_if_fail (MIDORI_IS_PANED_ACTION (paned_action), NULL);
g_return_val_if_fail (name != NULL, NULL);
if (g_strcmp0 (name, paned_action->child1.name) == 0)
return midori_paned_action_get_child1 (paned_action);
else if (g_strcmp0 (name, paned_action->child2.name) == 0)
return midori_paned_action_get_child2 (paned_action);
return NULL;
}
/**
* midori_paned_action_get_child1_name:
* @paned_action a #MidoriPanedAction
*
* Returns: The name of the first child
**/
const gchar*
midori_paned_action_get_child1_name (MidoriPanedAction* paned_action)
{
g_return_val_if_fail (MIDORI_IS_PANED_ACTION (paned_action), NULL);
return paned_action->child1.name;
}
/**
* midori_paned_action_get_child2_name:
* @paned_action a #MidoriPanedAction
*
* Returns: The name of the second child
**/
const gchar*
midori_paned_action_get_child2_name (MidoriPanedAction* paned_action)
{
g_return_val_if_fail (MIDORI_IS_PANED_ACTION (paned_action), NULL);
return paned_action->child2.name;
}

View File

@ -0,0 +1,70 @@
/*
Copyright (C) 2011 Peter Hatina <phatina@redhat.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.
See the file COPYING for the full license text.
*/
#ifndef __MIDORI_PANED_ACTION_H__
#define __MIDORI_PANED_ACTION_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define MIDORI_TYPE_PANED_ACTION \
(midori_paned_action_get_type ())
#define MIDORI_PANED_ACTION(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_PANED_ACTION, MidoriPanedAction))
#define MIDORI_PANED_ACTION_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_PANED_ACTION, MidoriPanedActionClass))
#define MIDORI_IS_PANED_ACTION(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_PANED_ACTION))
#define MIDORI_IS_PANED_ACTION_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_PANED_ACTION))
#define MIDORI_PANED_ACTION_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_PANED_ACTION, MidoriPanedActionClass))
typedef struct _MidoriPanedAction MidoriPanedAction;
typedef struct _MidoriPanedActionClass MidoriPanedActionClass;
GType
midori_paned_action_get_type (void) G_GNUC_CONST;
void
midori_paned_action_set_child1 (MidoriPanedAction* paned_action,
GtkWidget* child1,
const gchar* name,
gboolean resize,
gboolean shrink);
void
midori_paned_action_set_child2 (MidoriPanedAction* paned_action,
GtkWidget* child2,
const gchar* name,
gboolean resize,
gboolean shrink);
GtkWidget*
midori_paned_action_get_child1 (MidoriPanedAction* paned_action);
GtkWidget*
midori_paned_action_get_child2 (MidoriPanedAction* paned_action);
GtkWidget*
midori_paned_action_get_child_by_name (MidoriPanedAction* paned_action,
const gchar* name);
const gchar*
midori_paned_action_get_child1_name (MidoriPanedAction* paned_action);
const gchar*
midori_paned_action_get_child2_name (MidoriPanedAction* paned_action);
G_END_DECLS
#endif // __MIDORI_PANED_ACTION_H__

View File

@ -1,79 +0,0 @@
/*
Copyright (C) 2011 Peter Hatina <phatina@redhat.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.
See the file COPYING for the full license text.
*/
namespace Midori {
public class PanedAction : Gtk.Action {
Gtk.HPaned? hpaned = null;
Gtk.ToolItem? toolitem = null;
Child child1 = new Child();
Child child2 = new Child();
private struct Child {
protected Gtk.Widget widget;
string name;
bool resize;
bool shrink;
}
public override unowned Gtk.Widget create_tool_item () {
Gtk.Alignment alignment = new Gtk.Alignment (0.0f, 0.5f, 1.0f, 0.1f);
hpaned = new Gtk.HPaned ();
toolitem = new Gtk.ToolItem ();
toolitem.set_expand (true);
toolitem.add (alignment);
alignment.add (hpaned);
hpaned.pack1 (child1.widget, child1.resize, child1.shrink);
hpaned.pack2 (child2.widget, child2.resize, child2.shrink);
toolitem.show_all ();
return toolitem;
}
public void set_child1 (Gtk.Widget widget, string name, bool resize, bool shrink) {
child1.widget = widget;
child1.name = name;
child1.resize = resize;
child1.shrink = shrink;
}
public void set_child2 (Gtk.Widget widget, string name, bool resize, bool shrink) {
child2.widget = widget;
child2.name = name;
child2.resize = resize;
child2.shrink = shrink;
}
public Gtk.Widget? get_child1 () {
return child1.widget;
}
public Gtk.Widget? get_child2 () {
return child2.widget;
}
public Gtk.Widget? get_child_by_name (string name) {
if (name == child1.name)
return child1.widget;
else if (name == child2.name)
return child2.widget;
return null;
}
public string get_child1_name () {
return child1.name;
}
public string get_child2_name () {
return child2.name;
}
}
}

View File

@ -253,6 +253,36 @@ static GtkWidget*
_midori_panel_child_for_scrolled (MidoriPanel* panel,
GtkWidget* scrolled);
static gboolean
midori_panel_detached_window_delete_event_cb (GtkWidget* window,
GdkEvent* event,
MidoriPanel* panel)
{
/* FIXME: The panel will not end up at its original position */
/* FIXME: The menuitem may be mispositioned */
GtkWidget* vbox = gtk_bin_get_child (GTK_BIN (window));
GtkWidget* scrolled = g_object_get_data (G_OBJECT (window), "scrolled");
GtkWidget* toolbar = g_object_get_data (G_OBJECT (scrolled), "panel-toolbar");
GtkWidget* menuitem = g_object_get_data (G_OBJECT (scrolled), "panel-menuitem");
GtkWidget* viewable = _midori_panel_child_for_scrolled (panel, scrolled);
GtkToolItem* toolitem;
gint n;
g_object_ref (toolbar);
gtk_container_remove (GTK_CONTAINER (vbox), toolbar);
gtk_container_add (GTK_CONTAINER (panel->toolbook), toolbar);
g_object_unref (toolbar);
g_object_ref (scrolled);
gtk_container_remove (GTK_CONTAINER (vbox), scrolled);
n = gtk_notebook_append_page (GTK_NOTEBOOK (panel->notebook), scrolled, NULL);
g_object_unref (scrolled);
toolitem = midori_panel_construct_tool_item (panel, MIDORI_VIEWABLE (viewable));
if (menuitem)
g_object_set_data (G_OBJECT (menuitem), "toolitem", toolitem);
midori_panel_set_current_page (panel, n);
return FALSE;
}
static void
midori_panel_widget_destroy_cb (GtkWidget* viewable,
GtkWidget* widget)
@ -262,6 +292,57 @@ midori_panel_widget_destroy_cb (GtkWidget* viewable,
viewable, midori_panel_widget_destroy_cb, widget);
}
static void
midori_panel_detach_page (MidoriPanel* panel,
gint n)
{
GtkToolItem* toolitem = gtk_toolbar_get_nth_item (
GTK_TOOLBAR (panel->toolbar), n);
const gchar* title = gtk_tool_button_get_label (GTK_TOOL_BUTTON (toolitem));
GtkWidget* toolbar = gtk_notebook_get_nth_page (
GTK_NOTEBOOK (panel->toolbook), n);
GtkWidget* scrolled = gtk_notebook_get_nth_page (
GTK_NOTEBOOK (panel->notebook), n);
GtkWidget* vbox = gtk_vbox_new (FALSE, 0);
#if HAVE_HILDON
GtkWidget* window = hildon_window_new ();
hildon_program_add_window (hildon_program_get_instance (), HILDON_WINDOW (window));
#else
GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), TRUE);
gtk_window_set_default_size (GTK_WINDOW (window), 250, 400);
gtk_window_set_transient_for (GTK_WINDOW (window),
GTK_WINDOW (gtk_widget_get_toplevel (panel->notebook)));
#endif
gtk_widget_show (vbox);
gtk_container_add (GTK_CONTAINER (window), vbox);
g_object_set_data (G_OBJECT (window), "scrolled", scrolled);
gtk_window_set_title (GTK_WINDOW (window), title);
g_signal_handlers_disconnect_by_func (
_midori_panel_child_for_scrolled (panel, scrolled),
midori_panel_widget_destroy_cb, toolitem);
gtk_container_remove (GTK_CONTAINER (panel->toolbar), GTK_WIDGET (toolitem));
g_object_ref (toolbar);
gtk_container_remove (GTK_CONTAINER (panel->toolbook), toolbar);
#if HAVE_HILDON
hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (toolbar));
#else
gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, FALSE, 0);
#endif
g_object_unref (toolbar);
g_object_set_data (G_OBJECT (scrolled), "panel-toolbar", toolbar);
g_object_ref (scrolled);
gtk_container_remove (GTK_CONTAINER (panel->notebook), scrolled);
gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0);
g_object_unref (scrolled);
midori_panel_set_current_page (panel, n > 0 ? n - 1 : 0);
toolitem = gtk_toolbar_get_nth_item (GTK_TOOLBAR (panel->toolbar),
n > 0 ? n - 1 : 0);
g_signal_connect (window, "delete-event",
G_CALLBACK (midori_panel_detached_window_delete_event_cb), panel);
gtk_widget_show (window);
}
static void
midori_panel_button_align_clicked_cb (GtkWidget* toolitem,
MidoriPanel* panel)
@ -300,7 +381,6 @@ midori_panel_init (MidoriPanel* panel)
/* Create the titlebar */
labelbar = gtk_toolbar_new ();
katze_widget_add_class (labelbar, "secondary-toolbar");
panel->labelbar = labelbar;
gtk_toolbar_set_icon_size (GTK_TOOLBAR (labelbar), GTK_ICON_SIZE_MENU);
gtk_toolbar_set_style (GTK_TOOLBAR (labelbar), GTK_TOOLBAR_ICONS);
@ -346,7 +426,6 @@ midori_panel_init (MidoriPanel* panel)
/* Create the notebook */
panel->notebook = gtk_notebook_new ();
katze_widget_add_class (panel->notebook, "content-view");
gtk_notebook_set_show_border (GTK_NOTEBOOK (panel->notebook), FALSE);
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (panel->notebook), FALSE);
panel->frame = gtk_frame_new (NULL);
@ -491,15 +570,13 @@ midori_panel_set_right_aligned (MidoriPanel* panel,
/* Private function, used by MidoriBrowser */
/* static */ GtkWidget*
midori_panel_construct_menu_item (MidoriPanel* panel,
MidoriViewable* viewable,
gboolean popup)
MidoriViewable* viewable)
{
GtkAction* action;
GtkWidget* menuitem;
action = g_object_get_data (G_OBJECT (viewable), "midori-panel-action");
menuitem = popup ? sokoke_action_create_popup_menu_item (action)
: gtk_action_create_menu_item (action);
menuitem = gtk_action_create_menu_item (action);
g_object_set_data (G_OBJECT (menuitem), "page", viewable);
if (gtk_widget_get_visible (GTK_WIDGET (viewable)))
@ -561,9 +638,24 @@ midori_panel_action_activate_cb (GtkRadioAction* action,
GtkWidget* viewable = g_object_get_data (G_OBJECT (action), "viewable");
gint n = midori_panel_page_num (panel, viewable);
midori_panel_set_current_page (panel, n);
g_signal_emit (panel, signals[SWITCH_PAGE], 0, n);
gtk_widget_show (GTK_WIDGET (panel));
/* If the panel is detached, focus the window */
if (n == -1)
{
GtkWidget* toplevel = gtk_widget_get_toplevel (viewable);
gtk_window_present (GTK_WINDOW (toplevel));
return;
}
if (panel->open_panels_in_windows
&& gtk_radio_action_get_current_value (action)
== katze_object_get_int (action, "value"))
midori_panel_detach_page (panel, n);
else
{
midori_panel_set_current_page (panel, n);
g_signal_emit (panel, signals[SWITCH_PAGE], 0, n);
gtk_widget_show (GTK_WIDGET (panel));
}
}
/**
@ -618,7 +710,7 @@ midori_panel_append_page (MidoriPanel* panel,
{
scrolled = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_widget_set_can_focus (scrolled, TRUE);
gtk_widget_show (scrolled);

View File

@ -12,7 +12,11 @@
#ifndef __MIDORI_PANEL_H__
#define __MIDORI_PANEL_H__
#include "midori-core.h"
#include <gtk/gtk.h>
#include <katze/katze.h>
#include "midori-viewable.h"
G_BEGIN_DECLS

View File

@ -33,11 +33,15 @@
#endif
#define MIDORI_EVENT_NEW_TAB(evt) \
(evt != NULL \
&& ((((GdkEventButton*)evt)->button == 1 \
&& MIDORI_MOD_NEW_TAB(((GdkEventButton*)evt)->state)) \
|| (((GdkEventButton*)evt)->button == 2)))
((((GdkEventButton*)evt)->button == 1 \
&& MIDORI_MOD_NEW_TAB(((GdkEventButton*)evt)->state)) \
|| (((GdkEventButton*)evt)->button == 2))
#ifndef G_OS_WIN32
#define MIDORI_MODULE_PREFIX "lib"
#else
#define MIDORI_MODULE_PREFIX ""
#endif
#define MIDORI_MODULE_PREFIX "lib"
#endif /* !__MIDORI_PLATFORM_H__ */

View File

@ -11,8 +11,6 @@
#include "midori-preferences.h"
#include "midori-app.h"
#include "midori-core.h"
#include "midori-platform.h"
#include <string.h>
@ -294,7 +292,7 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
#define SPANNED_ADD(__widget) \
katze_preferences_add_widget (_preferences, __widget, "spanned")
/* Page "General" */
if (!midori_paths_is_readonly ())
if (!sokoke_is_app_or_private ())
{
PAGE_NEW (GTK_STOCK_HOME, _("Startup"));
FRAME_NEW (NULL);
@ -302,8 +300,7 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
INDENTED_ADD (label);
button = katze_property_proxy (settings, "load-on-startup", NULL);
SPANNED_ADD (button);
label = gtk_label_new (_("Homepage:"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
label = katze_property_label (settings, "homepage");
INDENTED_ADD (label);
entry = katze_property_proxy (settings, "homepage", "address");
SPANNED_ADD (entry);
@ -353,8 +350,7 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
button = katze_property_proxy (settings, "enforce-font-family", NULL);
INDENTED_ADD (button);
#endif
label = gtk_label_new (_("Preferred Encoding"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
label = katze_property_label (settings, "preferred-encoding");
INDENTED_ADD (label);
button = katze_property_proxy (settings, "preferred-encoding", "custom-default-encoding");
SPANNED_ADD (button);
@ -364,14 +360,12 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
FRAME_NEW (NULL);
#if !HAVE_HILDON
button = katze_property_proxy (settings, "auto-load-images", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Load images automatically"));
INDENTED_ADD (button);
button = katze_property_proxy (settings, "enable-spell-checking", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Enable Spell Checking"));
SPANNED_ADD (button);
/* Disable spell check option if there are no enchant modules */
{
gchar* enchant_path = midori_paths_get_lib_path ("enchant");
gchar* enchant_path = sokoke_find_lib_path ("enchant");
if (enchant_path == NULL)
{
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
@ -381,15 +375,11 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
g_free (enchant_path);
}
button = katze_property_proxy (settings, "enable-scripts", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Enable scripts"));
INDENTED_ADD (button);
button = katze_property_proxy (settings, "enable-plugins", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Enable Netscape plugins"));
gtk_widget_set_sensitive (button, midori_web_settings_has_plugin_support ());
SPANNED_ADD (button);
#endif
button = katze_property_proxy (settings, "zoom-text-and-images", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Zoom Text and Images"));
INDENTED_ADD (button);
button = katze_property_proxy (settings, "javascript-can-open-windows-automatically", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Allow scripts to open popups"));
@ -397,42 +387,23 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
SPANNED_ADD (button);
if (katze_widget_has_touchscreen_mode (parent ?
GTK_WIDGET (parent) : GTK_WIDGET (preferences)))
{
button = katze_property_proxy (settings, "kinetic-scrolling", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Kinetic scrolling"));
gtk_widget_set_tooltip_text (button, _("Whether scrolling should kinetically move according to speed"));
}
else
{
button = katze_property_proxy (settings, "middle-click-opens-selection", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Middle click opens Selection"));
gtk_widget_set_tooltip_text (button, _("Load an address from the selection via middle click"));
}
INDENTED_ADD (button);
if (katze_object_has_property (settings, "enable-webgl"))
{
button = katze_property_proxy (settings, "enable-webgl", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Enable WebGL support"));
SPANNED_ADD (button);
}
#ifndef G_OS_WIN32
button = katze_property_proxy (settings, "flash-window-on-new-bg-tabs", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Flash window on background tabs"));
INDENTED_ADD (button);
#endif
SPANNED_ADD (button);
FRAME_NEW (NULL);
button = gtk_label_new (_("Preferred languages"));
gtk_misc_set_alignment (GTK_MISC (button), 0.0, 0.5);
button = katze_property_label (settings, "preferred-languages");
INDENTED_ADD (button);
entry = katze_property_proxy (settings, "preferred-languages", "languages");
gtk_widget_set_tooltip_text (entry, _("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\""));
SPANNED_ADD (entry);
label = gtk_label_new (_("Save downloaded files to:"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
#if !HAVE_HILDON
label = katze_property_label (settings, "download-folder");
INDENTED_ADD (label);
button = katze_property_proxy (settings, "download-folder", "folder");
SPANNED_ADD (button);
#endif
/* Page "Interface" */
PAGE_NEW (GTK_STOCK_CONVERT, _("Browsing"));
@ -450,51 +421,45 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
INDENTED_ADD (label);
button = katze_property_proxy (settings, "open-new-pages-in", NULL);
SPANNED_ADD (button);
button = katze_property_proxy (settings, "close-buttons-on-tabs", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Close Buttons on Tabs"));
INDENTED_ADD (button);
#ifndef HAVE_GRANITE
#if !HAVE_HILDON
button = katze_property_proxy (settings, "always-show-tabbar", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Always Show Tabbar"));
INDENTED_ADD (button);
button = katze_property_proxy (settings, "close-buttons-on-tabs", NULL);
SPANNED_ADD (button);
#endif
button = katze_property_proxy (settings, "open-tabs-next-to-current", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Open Tabs next to Current"));
gtk_widget_set_tooltip_text (button, _("Whether to open new tabs next to the current tab or after the last one"));
INDENTED_ADD (button);
button = katze_property_proxy (settings, "open-tabs-in-the-background", NULL);
gtk_button_set_label (GTK_BUTTON (button), _("Open tabs in the background"));
SPANNED_ADD (button);
#if !HAVE_HILDON
INDENTED_ADD (gtk_label_new (NULL));
label = gtk_label_new (_("Text Editor"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
label = katze_property_label (settings, "text-editor");
INDENTED_ADD (label);
entry = katze_property_proxy (settings, "text-editor", "application-text/plain");
SPANNED_ADD (entry);
label = gtk_label_new (_("News Aggregator"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
label = katze_property_label (settings, "news-aggregator");
INDENTED_ADD (label);
entry = katze_property_proxy (settings, "news-aggregator", "application-News");
SPANNED_ADD (entry);
#endif
/* Page "Network" */
PAGE_NEW (GTK_STOCK_NETWORK, _("Network"));
FRAME_NEW (NULL);
label = gtk_label_new (_("Proxy server"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
#if !HAVE_HILDON
label = katze_property_label (settings, "proxy-type");
INDENTED_ADD (label);
button = katze_property_proxy (settings, "proxy-type", NULL);
SPANNED_ADD (button);
label = gtk_label_new (_("Hostname"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
INDENTED_ADD (label);
entry = katze_property_proxy (settings, "http-proxy", "address");
entry = katze_property_proxy (settings, "http-proxy", NULL);
SPANNED_ADD (entry);
g_signal_connect (settings, "notify::proxy-type",
G_CALLBACK (midori_preferences_notify_proxy_type_cb), entry);
midori_preferences_notify_proxy_type_cb (settings, NULL, entry);
label = gtk_label_new (_("Port"));
label = katze_property_label (settings, "http-proxy-port");
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
INDENTED_ADD (label);
entry = katze_property_proxy (settings, "http-proxy-port", NULL);
@ -502,14 +467,13 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
g_signal_connect (settings, "notify::proxy-type",
G_CALLBACK (midori_preferences_notify_proxy_type_cb), entry);
midori_preferences_notify_proxy_type_cb (settings, NULL, entry);
#endif
#if WEBKIT_CHECK_VERSION (1, 3, 11)
if (soup_session_get_feature (webkit_get_default_session (), SOUP_TYPE_CACHE))
{
label = gtk_label_new (_("Web Cache"));
gtk_widget_set_tooltip_text (label, _("The maximum size of cached pages on disk"));
label = katze_property_label (settings, "maximum-cache-size");
INDENTED_ADD (label);
button = katze_property_proxy (settings, "maximum-cache-size", NULL);
gtk_widget_set_tooltip_text (button, _("The maximum size of cached pages on disk"));
SPANNED_ADD (button);
label = gtk_label_new (_("MB"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);

View File

@ -311,7 +311,7 @@ midori_search_action_create_tool_item (GtkAction* action)
GtkWidget* alignment;
toolitem = GTK_WIDGET (gtk_tool_item_new ());
entry = sokoke_search_entry_new (NULL);
entry = gtk_icon_entry_new ();
gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_PRIMARY, TRUE);
alignment = gtk_alignment_new (0, 0.5, 1, 0.1);
@ -432,7 +432,7 @@ midori_search_action_get_icon (KatzeItem* item,
else if (gtk_icon_theme_has_icon (icon_theme, "edit-find-option"))
*icon_name = "edit-find-option";
else
*icon_name = STOCK_EDIT_FIND;
*icon_name = "edit-find";
return NULL;
}
@ -876,189 +876,21 @@ midori_search_action_editor_name_changed_cb (GtkWidget* entry,
GTK_RESPONSE_ACCEPT, text && *text);
}
gchar*
midori_search_action_token_for_uri (const gchar* uri)
static inline const gchar*
STR_NON_NULL (const gchar* string)
{
guint len, i;
gchar** parts;
gchar* hostname = NULL, *path = NULL;
path = midori_uri_parse_hostname (uri, NULL);
parts = g_strsplit (path, ".", -1);
g_free (path);
len = g_strv_length (parts);
if (len > 2)
{
for (i = len; i == 0; i--)
{
if (parts[i] && *parts[i])
if (strlen (parts[i]) > 3)
{
hostname = g_strdup (parts[i]);
break;
}
}
}
else
hostname = g_strdup (parts[0]);
if (!hostname)
hostname = g_strdup (parts[1]);
g_strfreev (parts);
if (strlen (hostname) > 4)
{
GString* str = g_string_new (NULL);
int j, count = 0;
for (j = 0; count < 4; j++)
{
if (hostname[j] == 'a'
|| hostname[j] == 'e'
|| hostname[j] == 'i'
|| hostname[j] == 'o'
|| hostname[j] == 'u')
continue;
else
{
g_string_append_c (str, hostname[j]);
count++;
}
}
return g_string_free (str, FALSE);
}
return g_strdup (hostname);
return string ? string : "";
}
KatzeItem*
midori_search_action_get_engine_for_form (WebKitWebView* web_view,
PangoEllipsizeMode ellipsize)
{
#if WEBKIT_CHECK_VERSION (1, 5, 0)
WebKitDOMDocument* doc;
WebKitDOMHTMLFormElement* active_form;
WebKitDOMHTMLCollection* form_nodes;
WebKitDOMElement* active_element;
gchar* token_element;
const gchar* title;
GString* uri_str;
gulong form_len;
const gchar* action;
guint i;
KatzeItem* item;
gchar** parts;
#if WEBKIT_CHECK_VERSION (1, 9, 5)
doc = webkit_web_frame_get_dom_document (web_view);
#else
if (webkit_web_view_get_focused_frame (web_view) != webkit_web_view_get_main_frame (web_view))
return NULL;
doc = webkit_web_view_get_dom_document (web_view);
#endif
active_element = webkit_dom_html_document_get_active_element ((WebKitDOMHTMLDocument*)doc);
active_form = webkit_dom_html_input_element_get_form ((WebKitDOMHTMLInputElement*)active_element);
if (!active_form)
return NULL;
token_element = webkit_dom_element_get_attribute (active_element, "name");
form_nodes = webkit_dom_html_form_element_get_elements (active_form);
form_len = webkit_dom_html_form_element_get_length (active_form);
/* action NULL or "": relative path */
if ((action = webkit_dom_html_form_element_get_action (active_form)) && *action)
uri_str = g_string_new (action);
else
{
gchar* hostname = midori_uri_parse_hostname (webkit_web_view_get_uri (web_view), NULL);
uri_str = g_string_new ("http://");
g_string_append (uri_str, hostname);
g_free (hostname);
}
g_string_append_c (uri_str, '?');
for (i = 0; i < form_len; i++)
{
WebKitDOMNode* form_node = webkit_dom_html_collection_item (form_nodes, i);
WebKitDOMElement* form_element = (WebKitDOMElement*) form_node;
gchar* name = webkit_dom_element_get_attribute (form_element, "name");
if (name && *name)
{
if (!g_strcmp0 (token_element, name))
g_string_append_printf (uri_str, "%s=%s&", name, "\%s");
else
{
gchar* value;
if (!g_strcmp0 (webkit_dom_element_get_tag_name (form_element), "SELECT"))
{
WebKitDOMHTMLSelectElement* select_element = (WebKitDOMHTMLSelectElement*) form_element;
gulong pos = webkit_dom_html_select_element_get_selected_index (select_element);
WebKitDOMNode* selected_node = webkit_dom_html_select_element_item (select_element, pos);
WebKitDOMElement* selected_element = (WebKitDOMElement*) selected_node;
value = webkit_dom_element_get_attribute (selected_element, "value");
}
else
value = webkit_dom_element_get_attribute (form_element, "value");
g_string_append_printf (uri_str, "%s=%s&", name, value);
g_free (value);
}
g_free (name);
}
}
title = webkit_web_view_get_title (web_view);
item = katze_item_new ();
item->uri = g_string_free (uri_str, FALSE);
item->token = midori_search_action_token_for_uri (webkit_web_view_get_uri (web_view));
if (strstr (title, " - "))
parts = g_strsplit (title, " - ", 2);
else if (strstr (title, ": "))
parts = g_strsplit (title, ": ", 2);
else
parts = NULL;
if (parts != NULL)
{
/* See midori_view_set_title: title can be first or last */
if (ellipsize == PANGO_ELLIPSIZE_END)
{
item->name = g_strdup (parts[0]);
item->text = g_strdup (parts[1]);
}
else
{
item->name = g_strdup (parts[1]);
item->text = g_strdup (parts[2]);
}
g_strfreev (parts);
}
else
item->name = g_strdup (title);
g_free (token_element);
return item;
#else
return NULL;
#endif
}
void
static void
midori_search_action_get_editor (MidoriSearchAction* search_action,
KatzeItem* item,
gboolean new_engine)
{
GtkWidget* toplevel;
GtkWidget* dialog;
GtkWidget* content_area;
GtkSizeGroup* sizegroup;
KatzeItem* item;
GtkWidget* hbox;
GtkWidget* label;
GtkTreeModel* liststore;
@ -1067,6 +899,7 @@ midori_search_action_get_editor (MidoriSearchAction* search_action,
GtkWidget* entry_name;
GtkWidget* entry_description;
GtkWidget* entry_uri;
GtkWidget* entry_icon;
GtkWidget* entry_token;
toplevel = gtk_widget_get_toplevel (search_action->treeview);
@ -1086,6 +919,7 @@ midori_search_action_get_editor (MidoriSearchAction* search_action,
if (new_engine)
{
item = katze_item_new ();
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
GTK_RESPONSE_ACCEPT, FALSE);
}
@ -1106,8 +940,9 @@ midori_search_action_get_editor (MidoriSearchAction* search_action,
g_signal_connect (entry_name, "changed",
G_CALLBACK (midori_search_action_editor_name_changed_cb), dialog);
gtk_entry_set_activates_default (GTK_ENTRY (entry_name), TRUE);
gtk_entry_set_text (GTK_ENTRY (entry_name),
katze_str_non_null (katze_item_get_name (item)));
if (!new_engine)
gtk_entry_set_text (GTK_ENTRY (entry_name),
STR_NON_NULL (katze_item_get_name (item)));
gtk_box_pack_start (GTK_BOX (hbox), entry_name, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (content_area), hbox);
gtk_widget_show_all (hbox);
@ -1119,8 +954,9 @@ midori_search_action_get_editor (MidoriSearchAction* search_action,
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
entry_description = gtk_entry_new ();
gtk_entry_set_activates_default (GTK_ENTRY (entry_description), TRUE);
gtk_entry_set_text (GTK_ENTRY (entry_description)
, katze_str_non_null (katze_item_get_text (item)));
if (!new_engine)
gtk_entry_set_text (GTK_ENTRY (entry_description)
, STR_NON_NULL (katze_item_get_text (item)));
gtk_box_pack_start (GTK_BOX (hbox), entry_description, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (content_area), hbox);
gtk_widget_show_all (hbox);
@ -1136,14 +972,28 @@ midori_search_action_get_editor (MidoriSearchAction* search_action,
#else
NULL);
#endif
g_object_set_data (G_OBJECT (entry_uri), "allow_%s", (void*)1);
gtk_entry_set_activates_default (GTK_ENTRY (entry_uri), TRUE);
gtk_entry_set_text (GTK_ENTRY (entry_uri),
katze_str_non_null (katze_item_get_uri (item)));
if (!new_engine)
gtk_entry_set_text (GTK_ENTRY (entry_uri)
, STR_NON_NULL (katze_item_get_uri (item)));
gtk_box_pack_start (GTK_BOX (hbox), entry_uri, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (content_area), hbox);
gtk_widget_show_all (hbox);
hbox = gtk_hbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
label = gtk_label_new_with_mnemonic (_("_Icon:"));
gtk_size_group_add_widget (sizegroup, label);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
entry_icon = gtk_entry_new ();
gtk_entry_set_activates_default (GTK_ENTRY (entry_icon), TRUE);
if (!new_engine)
gtk_entry_set_text (GTK_ENTRY (entry_icon)
, STR_NON_NULL (katze_item_get_icon (item)));
gtk_box_pack_start (GTK_BOX (hbox), entry_icon, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (content_area), hbox);
gtk_widget_show_all (hbox);
hbox = gtk_hbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
label = gtk_label_new_with_mnemonic (_("_Token:"));
@ -1151,8 +1001,9 @@ midori_search_action_get_editor (MidoriSearchAction* search_action,
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
entry_token = gtk_entry_new ();
gtk_entry_set_activates_default (GTK_ENTRY (entry_token), TRUE);
gtk_entry_set_text (GTK_ENTRY (entry_token)
, katze_str_non_null (katze_item_get_token (item)));
if (!new_engine)
gtk_entry_set_text (GTK_ENTRY (entry_token)
, STR_NON_NULL (katze_item_get_token (item)));
gtk_box_pack_start (GTK_BOX (hbox), entry_token, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (content_area), hbox);
gtk_widget_show_all (hbox);
@ -1164,6 +1015,7 @@ midori_search_action_get_editor (MidoriSearchAction* search_action,
"name", gtk_entry_get_text (GTK_ENTRY (entry_name)),
"text", gtk_entry_get_text (GTK_ENTRY (entry_description)),
"uri", gtk_entry_get_text (GTK_ENTRY (entry_uri)),
"icon", gtk_entry_get_text (GTK_ENTRY (entry_icon)),
"token", gtk_entry_get_text (GTK_ENTRY (entry_token)),
NULL);
@ -1188,7 +1040,7 @@ midori_search_action_activate_edit_cb (GtkTreeView *treeview,
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
if (gtk_tree_selection_get_selected (selection, NULL, NULL))
midori_search_action_get_editor (search_action, NULL, FALSE);
midori_search_action_get_editor (search_action, FALSE);
}
@ -1196,7 +1048,7 @@ static void
midori_search_action_dialog_add_cb (GtkWidget* widget,
MidoriSearchAction* search_action)
{
midori_search_action_get_editor (search_action, katze_item_new (), TRUE);
midori_search_action_get_editor (search_action, TRUE);
}
static void
@ -1209,7 +1061,7 @@ midori_search_action_dialog_edit_cb (GtkWidget* widget,
treeview = search_action->treeview;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
if (gtk_tree_selection_get_selected (selection, NULL, NULL))
midori_search_action_get_editor (search_action, NULL, FALSE);
midori_search_action_get_editor (search_action, FALSE);
}
static void
@ -1457,8 +1309,6 @@ midori_search_action_get_dialog (MidoriSearchAction* search_action)
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
#endif
NULL);
katze_widget_add_class (gtk_dialog_get_widget_for_response (
GTK_DIALOG (dialog), GTK_RESPONSE_HELP), "help_button");
g_signal_connect (dialog, "destroy",
G_CALLBACK (gtk_widget_destroyed), &search_action->dialog);
gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_PROPERTIES);
@ -1493,11 +1343,6 @@ midori_search_action_get_dialog (MidoriSearchAction* search_action)
gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf,
(GtkTreeCellDataFunc)midori_search_action_dialog_render_tick_cb,
treeview, NULL);
renderer_text = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
(GtkTreeCellDataFunc)midori_search_action_dialog_render_token,
treeview, NULL);
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,
@ -1508,6 +1353,11 @@ midori_search_action_get_dialog (MidoriSearchAction* search_action)
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
(GtkTreeCellDataFunc)midori_search_action_dialog_render_text,
treeview, NULL);
renderer_text = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer_text, TRUE);
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
(GtkTreeCellDataFunc)midori_search_action_dialog_render_token,
treeview, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
scrolled = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),

View File

@ -13,7 +13,6 @@
#define __MIDORI_SEARCH_ACTION_H__
#include <katze/katze.h>
#include <webkit/webkit.h>
G_BEGIN_DECLS
@ -73,15 +72,6 @@ midori_search_action_set_default_item (MidoriSearchAction* search_action,
GtkWidget*
midori_search_action_get_dialog (MidoriSearchAction* search_action);
void
midori_search_action_get_editor (MidoriSearchAction* search_action,
KatzeItem* item,
gboolean new_engine);
KatzeItem*
midori_search_action_get_engine_for_form (WebKitWebView* web_view,
PangoEllipsizeMode ellipsize);
G_END_DECLS
#endif /* __MIDORI_SEARCH_ACTION_H__ */

View File

@ -1,109 +0,0 @@
/*
Copyright (C) 2008-2012 Christian Dywan <christian@twotoasts.de>
Copyright (C) 2011 Peter Hatina <phatina@redhat.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.
See the file COPYING for the full license text.
*/
namespace Midori {
[CCode (cprefix = "MIDORI_WINDOW_")]
public enum WindowState {
NORMAL,
MINIMIZED,
MAXIMIZED,
FULLSCREEN
}
/* Since: 0.1.3 */
public class Settings : WebKit.WebSettings {
public bool remember_last_window_size { get; set; default = true; }
public int last_window_width { get; set; default = 0; }
public int last_window_height { get; set; default = 0; }
public int last_panel_position { get; set; default = 0; }
public int last_panel_page { get; set; default = 0; }
public int last_web_search { get; set; default = 0; }
/* Since: 0.4.3 */
// [IntegerType (min = 10, max = int.max)]
public int search_width { get; set; default = 200; }
/* Since: 0.4.7 */
public bool last_inspector_attached { get; set; default = false; }
/* Since: 0.1.3 */
public WindowState last_window_state { get; set; default = WindowState.NORMAL; }
public string? location_entry_search { get; set; default = null; }
/* Since: 0.1.7 */
public int clear_private_data { get; set; default = 0; }
/* Since: 0.2.9 */
public string? clear_data { get; set; default = null; }
public bool compact_sidepanel { get; set; default = false; }
/* Since: 0.2.2 */
public bool open_panels_in_windows { get; set; default = false; }
/* Since: 0.1.3 */
public bool right_align_sidepanel { get; set; default = false; }
public bool show_menubar { get; set; default = false; }
public bool show_navigationbar { get; set; default = true; }
public bool show_bookmarkbar { get; set; default = false; }
public bool show_panel { get; set; default = false; }
public bool show_statusbar { get; set; default = true; }
/* Since: 0.1.2 */
public bool show_crash_dialog { get; set; default = true; }
public string toolbar_items { get; set; default =
"TabNew,Back,NextForward,ReloadStop,BookmarkAdd,Location,Search,Trash,CompactMenu"; }
/* Since: 0.1.4 */
// [Deprecated (since = "0.4.7")]
public bool find_while_typing { get; set; default = false; }
public bool open_popups_in_tabs { get; set; default = true; }
/* Since: 0.1.3 */
public bool zoom_text_and_images { get; set; default = true; }
/* Since: 0.2.0 */
public bool kinetic_scrolling { get; set; default = true; }
public bool middle_click_opens_selection { get; set; default = true; }
public bool flash_window_on_new_bg_tabs { get; set; default = false; }
public bool close_buttons_on_tabs { get; set; default = true; }
public bool open_tabs_in_the_background { get; set; default = true; }
public bool open_tabs_next_to_current { get; set; default = true; }
public bool always_show_tabbar { get; set; default = true; }
public string homepage { get; set; default = "http://www.google.com"; }
static string default_download_folder () {
return Environment.get_user_special_dir (UserDirectory.DOWNLOAD)
?? Environment.get_home_dir ();
}
public string download_folder { get; set; default = default_download_folder (); }
public string? text_editor { get; set; default = null; }
/* Since: 0.1.6 */
public string? news_aggregator { get; set; default = null; }
public string http_proxy { get; set; default = null; }
/* Since: 0.4.2 */
// [IntegerType (min = 1, max = 65535)]
public int http_proxy_port { get; set; default = 8080; }
/* Since: 0.3.4 */
// [IntegerType (min = 0, int.max)]
public int maximum_cache_size { get; set; default = 100; }
/* Since: 0.3.4 */
public bool strip_referer { get; set; default = false; }
/* Since: 0.4.2 */
public bool first_party_cookies_only { get; set; default = true; }
// [IntegerType (min = 0, int.max)]
public int maximum_cookie_age { get; set; default = 30; }
// [IntegerType (min = 0, int.max)]
public int maximum_history_age { get; set; default = 30; }
/* Since: 0.4.7 */
public bool delay_saving (string property) {
return property.has_prefix ("last-")
|| property == "user-stylesheet-uri"
|| property.has_suffix ("-width");
}
}
}

View File

@ -1,401 +0,0 @@
/*
Copyright (C) 2011-2012 Christian Dywan <christian@twotoats.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.
*/
namespace Katze {
extern static string mkdir_with_parents (string pathname, int mode);
}
namespace Sokoke {
extern static string js_script_eval (void* ctx, string script, void* error);
}
namespace Midori {
public errordomain SpeedDialError {
INVALID_MESSAGE,
NO_ACTION,
NO_ID,
NO_URL,
NO_TITLE,
NO_ID2,
INVALID_ACTION,
}
public class SpeedDial : GLib.Object {
string filename;
string? html = null;
List<Spec> thumb_queue = null;
WebKit.WebView thumb_view = null;
Spec? spec = null;
public GLib.KeyFile keyfile;
public bool close_buttons_left { get; set; default = false; }
public signal void refresh ();
public class Spec {
public string dial_id;
public string uri;
public Spec (string dial_id, string uri) {
this.dial_id = dial_id;
this.uri = uri;
}
}
public SpeedDial (string new_filename, string? fallback = null) {
filename = new_filename;
keyfile = new GLib.KeyFile ();
try {
keyfile.load_from_file (filename, GLib.KeyFileFlags.NONE);
}
catch (GLib.Error io_error) {
string json;
size_t len;
try {
FileUtils.get_contents (fallback ?? (filename + ".json"),
out json, out len);
}
catch (GLib.Error fallback_error) {
json = "'{}'";
len = 4;
}
var script = new StringBuilder.sized (len);
script.append ("var json = JSON.parse (");
script.append_len (json, (ssize_t)len);
script.append ("""
);
var keyfile = '';
for (var i in json['shortcuts']) {
var tile = json['shortcuts'][i];
keyfile += '[Dial ' + tile['id'].substring (1) + ']\n'
+ 'uri=' + tile['href'] + '\n'
+ 'img=' + tile['img'] + '\n'
+ 'title=' + tile['title'] + '\n\n';
}
var columns = json['width'] ? json['width'] : 3;
var rows = json['shortcuts'] ? json['shortcuts'].length / columns : 0;
keyfile += '[settings]\n'
+ 'columns=' + columns + '\n'
+ 'rows=' + (rows > 3 ? rows : 3) + '\n\n';
keyfile;
""");
try {
keyfile.load_from_data (
Sokoke.js_script_eval (null, script.str, null),
-1, 0);
}
catch (GLib.Error eval_error) {
GLib.critical ("Failed to parse %s as speed dial JSON: %s",
fallback ?? (filename + ".json"), eval_error.message);
}
Katze.mkdir_with_parents (
Path.build_path (Path.DIR_SEPARATOR_S,
Environment.get_user_cache_dir (),
"midori", "thumbnails"), 0700);
foreach (string tile in keyfile.get_groups ()) {
try {
string img = keyfile.get_string (tile, "img");
keyfile.remove_key (tile, "img");
string uri = keyfile.get_string (tile, "uri");
if (img != null && uri[0] != '\0' && uri[0] != '#') {
uchar[] decoded = Base64.decode (img);
FileUtils.set_data (build_thumbnail_path (uri), decoded);
}
}
catch (GLib.Error img_error) {
/* img and uri can be missing */
}
}
}
}
public string get_next_free_slot (out uint count = null) {
uint slot_count = 0;
foreach (string tile in keyfile.get_groups ()) {
try {
if (keyfile.has_key (tile, "uri"))
slot_count++;
}
catch (KeyFileError error) { }
}
if (&count != null)
count = slot_count;
uint slot = 1;
while (slot <= slot_count) {
string tile = "Dial %u".printf (slot);
if (!keyfile.has_group (tile))
return tile;
slot++;
}
return "Dial %u".printf (slot_count + 1);
}
public void add (string uri, string title, Gdk.Pixbuf img) {
string id = get_next_free_slot ();
add_with_id (id, uri, title, img);
}
public void add_with_id (string id, string uri, string title, Gdk.Pixbuf img) {
keyfile.set_string (id, "uri", uri);
keyfile.set_string (id, "title", title);
Katze.mkdir_with_parents (Path.build_path (Path.DIR_SEPARATOR_S,
Paths.get_cache_dir (), "thumbnails"), 0700);
string filename = build_thumbnail_path (uri);
try {
img.save (filename, "png", null, "compression", "7", null);
}
catch (Error error) {
critical ("Failed to save speed dial thumbnail: %s", error.message);
}
save ();
}
string build_thumbnail_path (string filename) {
string thumbnail = Checksum.compute_for_string (ChecksumType.MD5, filename) + ".png";
return Path.build_filename (Paths.get_cache_dir (), "thumbnails", thumbnail);
}
public unowned string get_html () throws Error {
bool load_missing = true;
if (html != null)
return html;
string? head = null;
string filename = Paths.get_res_filename ("speeddial-head.html");
if (keyfile != null
&& FileUtils.get_contents (filename, out head, null)) {
string header = head.replace ("{title}", _("Speed Dial")).
replace ("{click_to_add}", _("Click to add a shortcut")).
replace ("{enter_shortcut_address}", _("Enter shortcut address")).
replace ("{enter_shortcut_name}", _("Enter shortcut title")).
replace ("{are_you_sure}", _("Are you sure you want to delete this shortcut?"));
var markup = new StringBuilder (header);
uint slot_count = 1;
string dial_id = get_next_free_slot (out slot_count);
uint next_slot = dial_id.substring (5, -1).to_int ();
/* Try to guess the best X by X grid size */
uint grid_index = 3;
while ((grid_index * grid_index) < slot_count)
grid_index++;
/* Percent width size of one slot */
uint slot_size = (100 / grid_index);
/* No editing in private/ app mode or without scripts */
markup.append_printf (
"%s<style>.cross { display:none }</style>%s" +
"<style> div.shortcut { height: %d%%; width: %d%%; }</style>\n",
Paths.is_readonly () ? "" : "<noscript>",
Paths.is_readonly () ? "" : "</noscript>",
slot_size + 1, slot_size - 4);
/* Combined width of slots should always be less than 100%.
* Use half of the remaining percentage as a margin size */
uint div_factor;
if (slot_size * grid_index >= 100 && grid_index > 4)
div_factor = 8;
else
div_factor = 2;
uint margin = (100 - ((slot_size - 4) * grid_index)) / div_factor;
if (margin > 9)
margin = margin % 10;
markup.append_printf (
"<style> body { overflow:hidden } #content { margin-left: %u%%; }</style>", margin);
if (close_buttons_left)
markup.append_printf (
"<style>.cross { left: -14px }</style>");
foreach (string tile in keyfile.get_groups ()) {
try {
string uri = keyfile.get_string (tile, "uri");
if (uri != null && uri.str ("://") != null && tile.has_prefix ("Dial ")) {
string title = keyfile.get_string (tile, "title");
string thumb_filename = build_thumbnail_path (uri);
uint slot = tile.substring (5, -1).to_int ();
string encoded;
try {
uint8[] thumb;
FileUtils.get_data (thumb_filename, out thumb);
encoded = Base64.encode (thumb);
}
catch (FileError error) {
encoded = null;
if (load_missing)
get_thumb (tile, uri);
}
markup.append_printf ("""
<div class="shortcut" id="%u"><div class="preview">
<a class="cross" href="#"></a>
<a href="%s"><img src="data:image/png;base64,%s" title='%s'></a>
</div><div class="title">%s</div></div>
""",
slot, uri, encoded ?? "", title, title ?? "");
}
else if (tile != "settings")
keyfile.remove_group (tile);
}
catch (KeyFileError error) { }
}
markup.append_printf ("""
<div class="shortcut" id="%u"><div class="preview new">
<a class="add" href="#"></a>
</div><div class="title">%s</div></div>
""",
next_slot, _("Click to add a shortcut"));
markup.append_printf ("</div>\n</body>\n</html>\n");
html = markup.str;
}
else
html = "";
return html;
}
public void save_message (string message) throws Error {
if (!message.has_prefix ("speed_dial-save-"))
throw new SpeedDialError.INVALID_MESSAGE ("Invalid message '%s'", message);
string msg = message.substring (16, -1);
string[] parts = msg.split (" ", 4);
if (parts[0] == null)
throw new SpeedDialError.NO_ACTION ("No action.");
string action = parts[0];
if (parts[1] == null)
throw new SpeedDialError.NO_ID ("No ID argument.");
string dial_id = "Dial " + parts[1];
if (action == "delete") {
string uri = keyfile.get_string (dial_id, "uri");
string file_path = build_thumbnail_path (uri);
keyfile.remove_group (dial_id);
FileUtils.unlink (file_path);
}
else if (action == "add") {
if (parts[2] == null)
throw new SpeedDialError.NO_URL ("No URL argument.");
keyfile.set_string (dial_id, "uri", parts[2]);
get_thumb (dial_id, parts[2]);
}
else if (action == "rename") {
if (parts[2] == null)
throw new SpeedDialError.NO_TITLE ("No title argument.");
string title = parts[2];
keyfile.set_string (dial_id, "title", title);
}
else if (action == "swap") {
if (parts[2] == null)
throw new SpeedDialError.NO_ID2 ("No ID2 argument.");
string dial2_id = "Dial " + parts[2];
string uri = keyfile.get_string (dial_id, "uri");
string title = keyfile.get_string (dial_id, "title");
string uri2 = keyfile.get_string (dial2_id, "uri");
string title2 = keyfile.get_string (dial2_id, "title");
keyfile.set_string (dial_id, "uri", uri2);
keyfile.set_string (dial2_id, "uri", uri);
keyfile.set_string (dial_id, "title", title2);
keyfile.set_string (dial2_id, "title", title);
}
else
throw new SpeedDialError.INVALID_ACTION ("Invalid action '%s'", action);
save ();
}
void save () {
html = null;
try {
FileUtils.set_contents (filename, keyfile.to_data ());
}
catch (Error error) {
critical ("Failed to update speed dial: %s", error.message);
}
refresh ();
}
void load_status (GLib.Object thumb_view_, ParamSpec pspec) {
if (thumb_view.load_status != WebKit.LoadStatus.FINISHED)
return;
return_if_fail (spec != null);
#if HAVE_OFFSCREEN
var img = (thumb_view.parent as Gtk.OffscreenWindow).get_pixbuf ();
var pixbuf_scaled = img.scale_simple (240, 160, Gdk.InterpType.TILES);
img = pixbuf_scaled;
#else
thumb_view.realize ();
var img = midori_view_web_view_get_snapshot (thumb_view, 240, 160);
#endif
unowned string title = thumb_view.get_title ();
add_with_id (spec.dial_id, spec.uri, title ?? spec.uri, img);
thumb_queue.remove (spec);
if (thumb_queue != null && thumb_queue.data != null) {
spec = thumb_queue.data;
thumb_view.load_uri (spec.uri);
}
else
/* disconnect_by_func (thumb_view, load_status) */;
}
void get_thumb (string dial_id, string uri) {
if (thumb_view == null) {
thumb_view = new WebKit.WebView ();
var settings = new WebKit.WebSettings ();
settings. set ("enable-scripts", false,
"enable-plugins", false,
"auto-load-images", true,
"enable-html5-database", false,
"enable-html5-local-storage", false);
if (settings.get_class ().find_property ("enable-java-applet") != null)
settings.set ("enable-java-applet", false);
thumb_view.settings = settings;
#if HAVE_OFFSCREEN
var offscreen = new Gtk.OffscreenWindow ();
offscreen.add (thumb_view);
thumb_view.set_size_request (800, 600);
offscreen.show_all ();
#else
/* What we are doing here is a bit of a hack. In order to render a
thumbnail we need a new view and load the url in it. But it has
to be visible and packed in a container. So we secretly pack it
into the notebook of the parent browser. */
notebook.add (thumb_view);
thumb_view.destroy.connect (Gtk.widget_destroyed);
/* We use an empty label. It's not invisible but hard to spot. */
notebook.set_tab_label (thumb_view, new Gtk.EventBox ());
thumb_view.show ();
#endif
}
thumb_queue.append (new Spec (dial_id, uri));
if (thumb_queue.nth_data (1) != null)
return;
spec = thumb_queue.data;
thumb_view.notify["load-status"].connect (load_status);
thumb_view.load_uri (spec.uri);
}
}
}

View File

@ -12,28 +12,42 @@
#ifndef __MIDORI_STOCK_H__
#define __MIDORI_STOCK_H__ 1
/* Stock items */
/* Custom stock items
We should distribute these
Names should match with epiphany and/ or xdg spec */
#define STOCK_BOOKMARK "stock_bookmark"
#define STOCK_BOOKMARKS "user-bookmarks"
#define STOCK_CONSOLE "terminal"
#define STOCK_EXTENSION "extension"
#define STOCK_EXTENSIONS "extension"
#define STOCK_HISTORY "document-open-recent"
#define STOCK_WEB_BROWSER "web-browser"
#define STOCK_NEWS_FEED "internet-news-reader"
#define STOCK_STYLE "preferences-desktop-theme"
#define STOCK_NEWS_FEED "news-feed"
#define STOCK_STYLE "gnome-settings-theme"
#define STOCK_TRANSFER "package"
#define STOCK_PLUGINS "application-x-shockwave-flash"
#define STOCK_TRANSFERS "package"
#define STOCK_PLUGINS "gnome-mime-application-x-shockwave-flash"
#define STOCK_BOOKMARK_ADD "bookmark-new"
#define STOCK_IMAGE "image-x-generic"
#define STOCK_HOMEPAGE "go-home"
#define STOCK_IMAGE "gnome-mime-image"
#define STOCK_NETWORK_OFFLINE "network-offline"
#define STOCK_SCRIPT "text-x-javascript"
#define STOCK_SEND "mail-send"
#define STOCK_TAB_NEW "tab-new"
#define STOCK_USER_TRASH "user-trash"
#define STOCK_WINDOW_NEW "window-new"
#define STOCK_FOLDER_NEW "folder-new"
#define STOCK_EDIT_CLEAR "edit-clear"
#define STOCK_EDIT_FIND "edit-find"
#define STOCK_STOP "stop"
#define STOCK_URL "text-html"
#define STOCK_SCRIPT "stock_script"
#define STOCK_SCRIPTS "gnome-settings-theme"
#define STOCK_SEND "stock_mail-send"
#define STOCK_TAB_NEW "stock_new-tab"
#define STOCK_USER_TRASH "gnome-stock-trash"
#define STOCK_WINDOW_NEW "stock_new-window"
#if defined (HAVE_HILDON) && HAVE_HILDON
#undef STOCK_BOOKMARKS
#define STOCK_BOOKMARKS "general_mybookmarks_folder"
#undef STOCK_NEWS_FEED
#define STOCK_NEWS_FEED "general_rss"
#undef STOCK_WEB_BROWSER
#define STOCK_WEB_BROWSER "general_web"
#endif
#endif /* !__MIDORI_STOCK_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -16,10 +16,6 @@
#include <katze/katze.h>
#ifdef HAVE_GRANITE
#include <granite/granite.h>
#endif
G_BEGIN_DECLS
#define MIDORI_LOAD_PROVISIONAL WEBKIT_LOAD_PROVISIONAL
@ -57,15 +53,6 @@ midori_security_get_type (void) G_GNUC_CONST;
#define MIDORI_TYPE_SECURITY \
(midori_security_get_type ())
typedef enum
{
MIDORI_DOWNLOAD_CANCEL,
MIDORI_DOWNLOAD_OPEN,
MIDORI_DOWNLOAD_SAVE,
MIDORI_DOWNLOAD_SAVE_AS,
MIDORI_DOWNLOAD_OPEN_IN_VIEWER,
} MidoriDownloadType;
#define MIDORI_VIEW(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_VIEW, MidoriView))
#define MIDORI_VIEW_CLASS(klass) \
@ -109,10 +96,6 @@ void
midori_view_set_uri (MidoriView* view,
const gchar* uri);
void
midori_view_set_overlay_text (MidoriView* view,
const gchar* text);
gboolean
midori_view_is_blank (MidoriView* view);
@ -155,17 +138,8 @@ midori_view_get_tab_menu (MidoriView* view);
PangoEllipsizeMode
midori_view_get_label_ellipsize (MidoriView* view);
#ifdef HAVE_GRANITE
GraniteWidgetsTab*
midori_view_get_tab (MidoriView* view);
void
midori_view_set_tab (MidoriView* view,
GraniteWidgetsTab* tab);
#else
GtkWidget*
midori_view_get_proxy_tab_label (MidoriView* view);
#endif
KatzeItem*
midori_view_get_proxy_item (MidoriView* view);
@ -183,6 +157,9 @@ void
midori_view_set_zoom_level (MidoriView* view,
gfloat zoom_level);
gboolean
midori_view_can_reload (MidoriView* view);
void
midori_view_reload (MidoriView* view,
gboolean from_cache);
@ -202,20 +179,15 @@ midori_view_can_go_forward (MidoriView* view);
void
midori_view_go_forward (MidoriView* view);
void midori_view_go_back_or_forward (MidoriView* view,
gint steps);
gboolean
midori_view_can_go_back_or_forward (MidoriView* view,
gint steps);
const gchar*
midori_view_get_previous_page (MidoriView* view);
const gchar*
midori_view_get_next_page (MidoriView* view);
gboolean
midori_view_can_print (MidoriView* view);
void
midori_view_print (MidoriView* view);
@ -225,10 +197,8 @@ midori_view_can_view_source (MidoriView* view);
gboolean
midori_view_can_save (MidoriView* view);
gchar*
midori_view_save_source (MidoriView* view,
const gchar* uri,
const gchar* outfile);
gboolean
midori_view_can_find (MidoriView* view);
void
midori_view_unmark_text_matches (MidoriView* view);
@ -261,9 +231,6 @@ midori_view_get_snapshot (MidoriView* view,
GtkWidget*
midori_view_get_web_view (MidoriView* view);
MidoriView*
midori_view_get_for_widget (GtkWidget* web_view);
MidoriSecurity
midori_view_get_security (MidoriView* view);
@ -281,9 +248,9 @@ midori_view_add_info_bar (MidoriView* view,
const gchar* first_button_text,
...);
const gchar*
midori_view_fallback_extension (MidoriView* view,
const gchar* extension);
void
midori_view_save_speed_dial_config (MidoriView* view,
GKeyFile* key_file);
G_END_DECLS

163
midori/midori-viewable.c Normal file
View File

@ -0,0 +1,163 @@
/*
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
See the file COPYING for the full license text.
*/
#include "midori-viewable.h"
#include <glib/gi18n.h>
enum {
POPULATE_OPTION_MENU,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
static void
midori_viewable_base_init (MidoriViewableIface* iface);
static void
midori_viewable_base_finalize (MidoriViewableIface* iface);
GType
midori_viewable_get_type (void)
{
static GType viewable_type = 0;
if (!viewable_type)
{
const GTypeInfo viewable_info =
{
sizeof (MidoriViewableIface),
(GBaseInitFunc) midori_viewable_base_init,
(GBaseFinalizeFunc) midori_viewable_base_finalize,
};
viewable_type = g_type_register_static (G_TYPE_INTERFACE,
"MidoriViewable",
&viewable_info, 0);
g_type_interface_add_prerequisite (viewable_type, GTK_TYPE_WIDGET);
}
return viewable_type;
}
static const gchar*
midori_viewable_default_get_stock_id (MidoriViewable* viewable)
{
return NULL;
}
static const gchar*
midori_viewable_default_get_label (MidoriViewable* viewable)
{
return NULL;
}
static GtkWidget*
midori_viewable_default_get_toolbar (MidoriViewable* viewable)
{
return NULL;
}
static void
midori_viewable_base_init (MidoriViewableIface* iface)
{
static gboolean initialized = FALSE;
if (initialized)
return;
/**
* MidoriViewable::populate-option-menu:
* @viewable: the object on which the signal is emitted
* @menu: the #GtkMenu to populate
*
* Emitted when an Option menu is displayed, for instance
* when the user clicks the Options button in the panel.
*
* Deprecated: 0.2.3
*/
signals[POPULATE_OPTION_MENU] = g_signal_new (
"populate-option-menu",
G_TYPE_FROM_INTERFACE (iface),
(GSignalFlags)(G_SIGNAL_RUN_LAST),
0,
0,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GTK_TYPE_MENU);
iface->get_stock_id = midori_viewable_default_get_stock_id;
iface->get_label = midori_viewable_default_get_label;
iface->get_toolbar = midori_viewable_default_get_toolbar;
initialized = TRUE;
}
static void
midori_viewable_base_finalize (MidoriViewableIface* iface)
{
}
/**
* midori_viewable_get_stock_id:
* @viewable: a #MidoriViewable
*
* Retrieves the stock ID of the viewable.
*
* Return value: a stock ID
**/
const gchar*
midori_viewable_get_stock_id (MidoriViewable* viewable)
{
g_return_val_if_fail (MIDORI_IS_VIEWABLE (viewable), NULL);
return MIDORI_VIEWABLE_GET_IFACE (viewable)->get_stock_id (viewable);
}
/**
* midori_viewable_get_label:
* @viewable: a #MidoriViewable
*
* Retrieves the label of the viewable.
*
* Return value: a label string
**/
const gchar*
midori_viewable_get_label (MidoriViewable* viewable)
{
g_return_val_if_fail (MIDORI_IS_VIEWABLE (viewable), NULL);
return MIDORI_VIEWABLE_GET_IFACE (viewable)->get_label (viewable);
}
/**
* midori_viewable_get_toolbar:
* @viewable: a #MidoriViewable
*
* Retrieves the toolbar of the viewable.
*
* Return value: a toolbar
**/
GtkWidget*
midori_viewable_get_toolbar (MidoriViewable* viewable)
{
GtkWidget* toolbar;
g_return_val_if_fail (MIDORI_IS_VIEWABLE (viewable), NULL);
toolbar = MIDORI_VIEWABLE_GET_IFACE (viewable)->get_toolbar (viewable);
if (!toolbar)
toolbar = gtk_toolbar_new ();
return toolbar;
}

61
midori/midori-viewable.h Normal file
View File

@ -0,0 +1,61 @@
/*
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
See the file COPYING for the full license text.
*/
#ifndef __MIDORI_VIEWABLE_H__
#define __MIDORI_VIEWABLE_H__
#include <katze/katze.h>
G_BEGIN_DECLS
#define MIDORI_TYPE_VIEWABLE \
(midori_viewable_get_type ())
#define MIDORI_VIEWABLE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_VIEWABLE, MidoriViewable))
#define MIDORI_IS_VIEWABLE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_VIEWABLE))
#define MIDORI_VIEWABLE_GET_IFACE(inst) \
(G_TYPE_INSTANCE_GET_INTERFACE ((inst), MIDORI_TYPE_VIEWABLE, \
MidoriViewableIface))
typedef struct _MidoriViewable MidoriViewable;
typedef struct _MidoriViewableIface MidoriViewableIface;
struct _MidoriViewableIface
{
GTypeInterface base_iface;
/* Virtual functions */
const gchar*
(*get_stock_id) (MidoriViewable* viewable);
const gchar*
(*get_label) (MidoriViewable* viewable);
GtkWidget*
(*get_toolbar) (MidoriViewable* viewable);
};
GType
midori_viewable_get_type (void) G_GNUC_CONST;
const gchar*
midori_viewable_get_stock_id (MidoriViewable* viewable);
const gchar*
midori_viewable_get_label (MidoriViewable* viewable);
GtkWidget*
midori_viewable_get_toolbar (MidoriViewable* viewable);
G_END_DECLS
#endif /* __MIDORI_VIEWABLE_H__ */

View File

@ -1,23 +0,0 @@
/*
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
See the file COPYING for the full license text.
*/
namespace Midori {
public interface Viewable {
public abstract unowned string get_stock_id ();
public abstract unowned string get_label ();
public abstract Gtk.Widget get_toolbar ();
/* Emitted when an Option menu is displayed, for instance
* when the user clicks the Options button in the panel.
* Deprecated: 0.2.3 */
public signal void populate_option_menu (Gtk.Menu menu);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -34,6 +34,8 @@ G_BEGIN_DECLS
typedef struct _MidoriWebSettings MidoriWebSettings;
typedef struct _MidoriWebSettingsClass MidoriWebSettingsClass;
#define MIDORI_PARAM_DELAY_SAVING (1 << 8)
enum
{
MIDORI_CLEAR_NONE = 0,
@ -47,6 +49,20 @@ enum
MIDORI_CLEAR_SESSION = 128,
};
typedef enum
{
MIDORI_WINDOW_NORMAL,
MIDORI_WINDOW_MINIMIZED,
MIDORI_WINDOW_MAXIMIZED,
MIDORI_WINDOW_FULLSCREEN,
} MidoriWindowState;
GType
midori_window_state_get_type (void) G_GNUC_CONST;
#define MIDORI_TYPE_WINDOW_STATE \
(midori_window_state_get_type ())
/* values >= MIDORI_STARTUP_LAST_OPEN_PAGES mean session is saved */
typedef enum
{
@ -64,8 +80,7 @@ midori_startup_get_type (void) G_GNUC_CONST;
typedef enum
{
MIDORI_ENCODING_CHINESE /* Traditional */,
MIDORI_ENCODING_CHINESE_SIMPLIFIED,
MIDORI_ENCODING_CHINESE,
MIDORI_ENCODING_JAPANESE,
MIDORI_ENCODING_KOREAN,
MIDORI_ENCODING_RUSSIAN,
@ -126,7 +141,6 @@ typedef enum
{
MIDORI_IDENT_MIDORI /* Automatic */,
MIDORI_IDENT_GENUINE /* Midori */,
MIDORI_IDENT_CHROME,
MIDORI_IDENT_SAFARI,
MIDORI_IDENT_IPHONE,
MIDORI_IDENT_FIREFOX,
@ -159,24 +173,6 @@ const gchar*
midori_web_settings_get_system_name (gchar** architecture,
gchar** platform);
gboolean
midori_web_settings_has_plugin_support (void);
typedef enum
{
MIDORI_SITE_DATA_UNDETERMINED,
MIDORI_SITE_DATA_BLOCK,
MIDORI_SITE_DATA_ACCEPT,
MIDORI_SITE_DATA_PRESERVE,
} MidoriSiteDataPolicy;
MidoriSiteDataPolicy
midori_web_settings_get_site_data_policy (MidoriWebSettings* settings,
const gchar* uri);
const gchar*
midori_web_settings_get_accept_language (MidoriWebSettings* settings);
G_END_DECLS
#endif /* __MIDORI_WEB_SETTINGS_H__ */

View File

@ -14,7 +14,6 @@
#include "midori-app.h"
#include "midori-array.h"
#include "midori-bookmarks.h"
#include "midori-browser.h"
#include "midori-extension.h"
#include "midori-locationaction.h"
@ -22,6 +21,7 @@
#include "midori-preferences.h"
#include "midori-searchaction.h"
#include "midori-view.h"
#include "midori-viewable.h"
#include "midori-websettings.h"
#include "midori-platform.h"
#include <midori/midori-core.h> /* Vala API */

View File

@ -14,19 +14,19 @@ namespace Midori {
[NoAccessorMethod]
public string name { get; set; }
[NoAccessorMethod]
public Midori.WebSettings settings { owned get; set; }
public Midori.WebSettings settings { get; set; }
[NoAccessorMethod]
public Katze.Array bookmarks { get; set; }
public GLib.Object bookmarks { get; set; }
[NoAccessorMethod]
public Katze.Array trash { get; set; }
public GLib.Object trash { get; set; }
[NoAccessorMethod]
public Katze.Array search_engines { get; set; }
public GLib.Object search_engines { get; set; }
[NoAccessorMethod]
public Katze.Array history { get; set; }
public GLib.Object history { get; set; }
[NoAccessorMethod]
public Katze.Array extensions { get; set; }
public GLib.Object extensions { get; set; }
[NoAccessorMethod]
public Katze.Array browsers { get; }
public GLib.Object browsers { get; }
public Browser? browser { get; }
[HasEmitter]
@ -35,20 +35,18 @@ namespace Midori {
[HasEmitter]
public signal void quit ();
}
[CCode (cheader_filename = "midori/midori.h")]
public class Browser : Gtk.Window {
public Browser ();
public int add_item (Katze.Item item);
public int add_item (GLib.Object item);
public int add_uri (string uri);
public unowned View get_nth_tab (int n);
public GLib.List<weak View> get_tabs ();
public void block_action (Gtk.Action action);
public void unblock_action (Gtk.Action action);
public unowned Gtk.ActionGroup get_action_group ();
public static unowned Browser get_for_widget (Gtk.Widget widget);
public unowned Browser get_for_widget (Gtk.Widget widget);
public unowned string[] get_toolbar_actions ();
public unowned Katze.Array get_proxy_items ();
public unowned GLib.Object get_proxy_items ();
[NoAccessorMethod]
public Gtk.MenuBar menubar { owned get; }
@ -69,13 +67,13 @@ namespace Midori {
public string statusbar_text { owned get; set; }
public Midori.WebSettings settings { get; set; }
[NoAccessorMethod]
public Katze.Array? bookmarks { owned get; set; }
public GLib.Object bookmarks { owned get; set; }
[NoAccessorMethod]
public Katze.Array? trash { owned get; set; }
public GLib.Object trash { owned get; set; }
[NoAccessorMethod]
public Katze.Array? search_engines { owned get; set; }
public GLib.Object search_engines { owned get; set; }
[NoAccessorMethod]
public Katze.Array? history { owned get; set; }
public GLib.Object history { owned get; set; }
[NoAccessorMethod]
public bool show_tabs { get; set; }
@ -84,10 +82,9 @@ namespace Midori {
public signal void add_tab (View tab);
[HasEmitter]
public signal void remove_tab (View tab);
public signal void switch_tab (View? old_view, View? new_view);
[HasEmitter]
public signal void activate_action (string name);
public signal void add_download (WebKit.Download download);
public signal void add_download (GLib.Object download);
public signal void populate_tool_menu (Gtk.Menu menu);
[HasEmitter]
public signal void quit ();
@ -118,17 +115,12 @@ namespace Midori {
public string version { get; set; }
[NoAccessorMethod]
public string authors { get; set; }
[NoAccessorMethod]
public string website { get; set; }
[NoAccessorMethod]
public string key { get; set; }
public signal void activate (Midori.App app);
public signal void deactivate ();
public signal void open_preferences ();
}
[CCode (cheader_filename = "midori/midori.h")]
public class View : Gtk.VBox {
[CCode (type = "GtkWidget*")]
public View (GLib.Object net);
@ -146,8 +138,9 @@ namespace Midori {
public Gtk.Menu get_tab_menu ();
public Pango.EllipsizeMode get_label_ellipsize ();
public Gtk.Label get_proxy_tab_label ();
public Katze.Item get_proxy_item ();
public GLib.Object get_proxy_item ();
public bool can_view_source ();
public bool can_find ();
public void search_text (string text, bool case_sensitive, bool forward);
public void mark_text_matches (string text, bool case_sensitive);
public void set_highlight_text_matches (bool highlight);
@ -155,7 +148,6 @@ namespace Midori {
public Gdk.Pixbuf get_snapshot (int width, int height);
public unowned WebKit.WebView get_web_view ();
public void populate_popup (Gtk.Menu menu, bool manual);
public void reload (bool from_cache);
public string uri { get; }
public string title { get; }
@ -166,42 +158,15 @@ namespace Midori {
public double progress { get; set; }
public bool minimized { get; }
public float zoom_level { get; }
public Katze.Array news_feeds { get; }
public GLib.Object news_feeds { get; }
public string statusbar_text { get; }
public WebSettings settings { get; set; }
public GLib.Object net { get; }
[HasEmitter]
public signal bool download_requested (WebKit.Download download);
}
[CCode (cheader_filename = "midori/midori.h")]
public class SearchAction : Gtk.Action {
public static Katze.Item? get_engine_for_form (WebKit.WebView web_view, Pango.EllipsizeMode ellipsize);
}
[CCode (cheader_filename = "midori/midori-view.h", cprefix = "MIDORI_DOWNLOAD_")]
public enum DownloadType {
CANCEL,
OPEN,
SAVE,
SAVE_AS,
OPEN_IN_VIEWER
}
public class WebSettings : WebKit.WebSettings {
public WebSettings ();
[NoAccessorMethod]
public MidoriStartup load_on_startup { get; set; }
}
[CCode (cheader_filename = "midori/midori-websettings.h", cprefix = "MIDORI_STARTUP_")]
public enum MidoriStartup {
BLANK_PAGE,
HOMEPAGE,
LAST_OPEN_PAGES,
DELAYED_PAGES
}
[CCode (cheader_filename = "midori/sokoke.h", lower_case_cprefix = "sokoke_")]

View File

@ -54,6 +54,9 @@
#endif
#include "socket.h"
#if USE_SSL
# include <openssl/ssl.h>
#endif
#ifdef G_ENABLE_DEBUG
# define debug_print g_debug
@ -559,6 +562,10 @@ gboolean sock_has_read_data(SockInfo *sock)
#ifdef G_OS_WIN32
gulong val;
#if USE_SSL
if (sock->ssl)
return TRUE;
#endif
if (ioctlsocket(sock->sock, FIONREAD, &val) < 0) {
g_warning("sock_has_read_data(): ioctlsocket() failed: %d\n",
WSAGetLastError());
@ -588,6 +595,22 @@ static gboolean sock_check(GSource *source)
fd_set fds;
GIOCondition condition = sock->condition;
#if USE_SSL
if (sock->ssl) {
if (condition & G_IO_IN) {
if (SSL_pending(sock->ssl) > 0)
return TRUE;
if (SSL_want_write(sock->ssl))
condition |= G_IO_OUT;
}
if (condition & G_IO_OUT) {
if (SSL_want_read(sock->ssl))
condition |= G_IO_IN;
}
}
#endif
FD_ZERO(&fds);
FD_SET(sock->sock, &fds);
@ -624,6 +647,19 @@ guint sock_add_watch(SockInfo *sock, GIOCondition condition, SockFunc func,
sock->callback = func;
sock->condition = condition;
sock->data = data;
#if USE_SSL
if (sock->ssl) {
GSource *source;
source = g_source_new(&sock_watch_funcs, sizeof(SockSource));
((SockSource *)source)->sock = sock;
g_source_set_priority(source, G_PRIORITY_DEFAULT);
g_source_set_can_recurse(source, FALSE);
return g_source_attach(source, NULL);
}
#endif
return g_io_add_watch(sock->sock_ch, condition, sock_watch_cb, sock);
}
@ -1339,6 +1375,10 @@ gint sock_read(SockInfo *sock, gchar *buf, gint len)
{
g_return_val_if_fail(sock != NULL, -1);
#if USE_SSL
if (sock->ssl)
return ssl_read(sock->ssl, buf, len);
#endif
return fd_read(sock->sock, buf, len);
}
@ -1354,10 +1394,44 @@ gint fd_read(gint fd, gchar *buf, gint len)
#endif
}
#if USE_SSL
gint ssl_read(SSL *ssl, gchar *buf, gint len)
{
gint err, ret;
if (SSL_pending(ssl) == 0) {
if (fd_check_io(SSL_get_rfd(ssl), G_IO_IN) < 0)
return -1;
}
ret = SSL_read(ssl, buf, len);
switch ((err = SSL_get_error(ssl, ret))) {
case SSL_ERROR_NONE:
return ret;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
errno = EAGAIN;
return -1;
case SSL_ERROR_ZERO_RETURN:
return 0;
default:
g_warning("SSL_read() returned error %d, ret = %d\n", err, ret);
if (ret == 0)
return 0;
return -1;
}
}
#endif
gint sock_write(SockInfo *sock, const gchar *buf, gint len)
{
g_return_val_if_fail(sock != NULL, -1);
#if USE_SSL
if (sock->ssl)
return ssl_write(sock->ssl, buf, len);
#endif
return fd_write(sock->sock, buf, len);
}
@ -1385,10 +1459,34 @@ gint fd_write(gint fd, const gchar *buf, gint len)
#endif
}
#if USE_SSL
gint ssl_write(SSL *ssl, const gchar *buf, gint len)
{
gint ret;
ret = SSL_write(ssl, buf, len);
switch (SSL_get_error(ssl, ret)) {
case SSL_ERROR_NONE:
return ret;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
errno = EAGAIN;
return -1;
default:
return -1;
}
}
#endif
gint sock_write_all(SockInfo *sock, const gchar *buf, gint len)
{
g_return_val_if_fail(sock != NULL, -1);
#if USE_SSL
if (sock->ssl)
return ssl_write_all(sock->ssl, buf, len);
#endif
return fd_write_all(sock->sock, buf, len);
}
@ -1408,6 +1506,24 @@ gint fd_write_all(gint fd, const gchar *buf, gint len)
return wrlen;
}
#if USE_SSL
gint ssl_write_all(SSL *ssl, const gchar *buf, gint len)
{
gint n, wrlen = 0;
while (len) {
n = ssl_write(ssl, buf, len);
if (n <= 0)
return -1;
len -= n;
wrlen += n;
buf += n;
}
return wrlen;
}
#endif
gint fd_recv(gint fd, gchar *buf, gint len, gint flags)
{
#ifdef G_OS_WIN32
@ -1454,10 +1570,38 @@ gint fd_gets(gint fd, gchar *buf, gint len)
return bp - buf;
}
#if USE_SSL
gint ssl_gets(SSL *ssl, gchar *buf, gint len)
{
gchar *newline, *bp = buf;
gint n;
if (--len < 1)
return -1;
do {
if ((n = ssl_peek(ssl, bp, len)) <= 0)
return -1;
if ((newline = memchr(bp, '\n', n)) != NULL)
n = newline - bp + 1;
if ((n = ssl_read(ssl, bp, n)) < 0)
return -1;
bp += n;
len -= n;
} while (!newline && len);
*bp = '\0';
return bp - buf;
}
#endif
gint sock_gets(SockInfo *sock, gchar *buf, gint len)
{
g_return_val_if_fail(sock != NULL, -1);
#if USE_SSL
if (sock->ssl)
return ssl_gets(sock->ssl, buf, len);
#endif
return fd_gets(sock->sock, buf, len);
}
@ -1486,11 +1630,42 @@ gint fd_getline(gint fd, gchar **line)
return (gint)size;
}
#if USE_SSL
gint ssl_getline(SSL *ssl, gchar **line)
{
gchar buf[BUFFSIZE];
gchar *str = NULL;
gint len;
gulong size = 0;
gulong cur_offset = 0;
while ((len = ssl_gets(ssl, buf, sizeof(buf))) > 0) {
size += len;
str = g_realloc(str, size + 1);
memcpy(str + cur_offset, buf, len + 1);
cur_offset += len;
if (buf[len - 1] == '\n')
break;
}
*line = str;
if (!str)
return -1;
else
return (gint)size;
}
#endif
gint sock_getline(SockInfo *sock, gchar **line)
{
g_return_val_if_fail(sock != NULL, -1);
g_return_val_if_fail(line != NULL, -1);
#if USE_SSL
if (sock->ssl)
return ssl_getline(sock->ssl, line);
#endif
return fd_getline(sock->sock, line);
}
@ -1504,10 +1679,44 @@ gint sock_puts(SockInfo *sock, const gchar *buf)
}
/* peek at the socket data without actually reading it */
#if USE_SSL
gint ssl_peek(SSL *ssl, gchar *buf, gint len)
{
gint err, ret;
if (SSL_pending(ssl) == 0) {
if (fd_check_io(SSL_get_rfd(ssl), G_IO_IN) < 0)
return -1;
}
ret = SSL_peek(ssl, buf, len);
switch ((err = SSL_get_error(ssl, ret))) {
case SSL_ERROR_NONE:
return ret;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
errno = EAGAIN;
return -1;
case SSL_ERROR_ZERO_RETURN:
return 0;
default:
g_warning("SSL_peek() returned error %d, ret = %d\n", err, ret);
if (ret == 0)
return 0;
return -1;
}
}
#endif
gint sock_peek(SockInfo *sock, gchar *buf, gint len)
{
g_return_val_if_fail(sock != NULL, -1);
#if USE_SSL
if (sock->ssl)
return ssl_peek(sock->ssl, buf, len);
#endif
return fd_recv(sock->sock, buf, len, MSG_PEEK);
}
@ -1518,6 +1727,11 @@ gint sock_close(SockInfo *sock)
if (!sock)
return 0;
#if USE_SSL
if (sock->ssl)
ssl_done_socket(sock);
#endif
if (sock->sock_ch) {
g_io_channel_shutdown(sock->sock_ch, FALSE, NULL);
g_io_channel_unref(sock->sock_ch);
@ -1545,4 +1759,13 @@ gint fd_close(gint fd)
#endif
}
#if USE_SSL
void ssl_done_socket(SockInfo *sockinfo)
{
if (sockinfo->ssl) {
SSL_free(sockinfo->ssl);
}
}
#endif
#endif

View File

@ -20,6 +20,10 @@
typedef struct _SockInfo SockInfo;
#if USE_SSL
# include <openssl/ssl.h>
#endif
typedef enum
{
CONN_READY,
@ -38,6 +42,11 @@ typedef gboolean (*SockFunc) (SockInfo *sock,
struct _SockInfo
{
gint sock;
#if USE_SSL
SSL *ssl;
#else
gpointer ssl;
#endif
GIOChannel *sock_ch;
gchar *hostname;
@ -102,4 +111,15 @@ gint fd_gets (gint sock, gchar *buf, gint len);
gint fd_getline (gint sock, gchar **line);
gint fd_close (gint sock);
/* Functions for SSL */
#if USE_SSL
gint ssl_read (SSL *ssl, gchar *buf, gint len);
gint ssl_write (SSL *ssl, const gchar *buf, gint len);
gint ssl_write_all (SSL *ssl, const gchar *buf, gint len);
gint ssl_gets (SSL *ssl, gchar *buf, gint len);
gint ssl_getline (SSL *ssl, gchar **line);
gint ssl_peek (SSL *ssl, gchar *buf, gint len);
void ssl_done_socket (SockInfo *sockinfo);
#endif
#endif /* __SYLPH_SOCKET_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,6 @@
#define __SOKOKE_H__ 1
#include <JavaScriptCore/JavaScript.h>
#include <webkit/webkit.h>
#include <midori/midori-websettings.h>
#include <katze/gtk3-compat.h>
@ -42,17 +41,9 @@ sokoke_show_uri (GdkScreen* screen,
guint32 timestamp,
GError** error);
gchar*
sokoke_prepare_command (const gchar* command,
gboolean quote_command,
const gchar* argument,
gboolean quote_argument);
gboolean
sokoke_spawn_program (const gchar* command,
gboolean quote_command,
const gchar* argument,
gboolean quote_argument);
const gchar* argument);
void
sokoke_spawn_app (const gchar* uri,
@ -72,6 +63,47 @@ GtkWidget*
sokoke_xfce_header_new (const gchar* icon,
const gchar* title);
void
sokoke_entry_set_default_text (GtkEntry* entry,
const gchar* default_text);
gchar*
sokoke_key_file_get_string_default (GKeyFile* key_file,
const gchar* group,
const gchar* key,
const gchar* default_value,
GError** error);
gint
sokoke_key_file_get_integer_default (GKeyFile* key_file,
const gchar* group,
const gchar* key,
const gint default_value,
GError** error);
gdouble
sokoke_key_file_get_double_default (GKeyFile* key_file,
const gchar* group,
const gchar* key,
gdouble default_value,
GError** error);
gboolean
sokoke_key_file_get_boolean_default (GKeyFile* key_file,
const gchar* group,
const gchar* key,
gboolean default_value,
GError** error);
gchar**
sokoke_key_file_get_string_list_default (GKeyFile* key_file,
const gchar* group,
const gchar* key,
gsize* length,
gchar** default_value,
gsize* default_length,
GError* error);
gboolean
sokoke_key_file_save_to_file (GKeyFile* key_file,
const gchar* filename,
@ -89,10 +121,34 @@ sokoke_action_create_popup_menu_item (GtkAction* action);
gint64
sokoke_time_t_to_julian (const time_t* timestamp);
gint
sokoke_days_between (const time_t* day1,
const time_t* day2);
const gchar*
sokoke_set_config_dir (const gchar* new_config_dir);
gboolean
sokoke_is_app_or_private (void);
gboolean
sokoke_remove_path (const gchar* path,
gboolean ignore_errors);
gchar*
sokoke_find_config_filename (const gchar* folder,
const gchar* filename);
gchar*
sokoke_find_lib_path (const gchar* folder);
gchar*
sokoke_find_data_filename (const gchar* filename,
gboolean res);
gchar**
sokoke_get_argv (gchar** argument_vector);
gchar*
sokoke_replace_variables (const gchar* template,
const gchar* variable_first, ...);
@ -117,6 +173,9 @@ sokoke_prefetch_uri (MidoriWebSettings* settings,
gboolean
sokoke_resolve_hostname (const gchar* hostname);
gchar *
sokoke_accept_languages (const gchar* const * lang_names);
gboolean
sokoke_recursive_fork_protection (const gchar* uri,
gboolean set_uri);
@ -134,12 +193,13 @@ sokoke_register_privacy_item (const gchar* name,
GCallback clear);
void
sokoke_widget_copy_clipboard (GtkWidget* widget,
const gchar* text,
GtkClipboardGetFunc get_cb,
gpointer owner);
sokoke_widget_copy_clipboard (GtkWidget* widget,
const gchar* text);
GtkWidget*
sokoke_search_entry_new (const gchar* placeholder_text);
gchar*
sokoke_build_thumbnail_path (const gchar* name);
gchar*
midori_download_prepare_tooltip_text (WebKitDownload* download);
#endif /* !__SOKOKE_H__ */

View File

@ -7,10 +7,10 @@ import platform
progressive = True
libs = 'M UNIQUE LIBSOUP GMODULE GTHREAD LIBIDN GIO GTK SQLITE ' \
'LIBNOTIFY WEBKIT JAVASCRIPTCOREGTK LIBXML X11 XSS WS2_32 HILDON' \
'HILDON_FM GCR GRANITE ZEITGEIST'
'LIBNOTIFY WEBKIT JAVASCRIPTCOREGTK LIBXML X11 XSS WS2_32 OPENSSL HILDON' \
'HILDON_FM'
if progressive:
if progressive or Options.commands['check']:
obj = bld.new_task_gen ('cc', 'staticlib')
obj.target = 'midori-core'
obj.includes = '.. ../katze . ../toolbars'
@ -18,14 +18,10 @@ if progressive:
obj.uselib = libs
obj.add_marshal_file ('marshal.list', 'midori_cclosure_marshal')
obj.install_path = None
obj.vapi_dirs = '../midori ../katze'
obj.packages = 'glib-2.0 gio-2.0 libsoup-2.4 posix'
if bld.env['HAVE_GTK3']:
obj.packages += ' gtk+-3.0 webkitgtk-3.0'
else:
obj.packages += ' gtk+-2.0 webkit-1.0'
obj.packages = 'glib-2.0 gio-2.0 gtk+-2.0 libsoup-2.4 webkit-1.0'
bld.add_group ()
if progressive:
obj = bld.new_task_gen ('cc', 'program')
obj.target = 'midori'
obj.includes = '.. ../katze . ../panels'
@ -34,3 +30,12 @@ if progressive:
obj.uselib_local = 'midori-core'
if bld.env['WINRC']:
obj.source += ' ../data/midori.rc'
else:
obj = bld.new_task_gen ('cc', 'program')
obj.target = 'midori'
obj.includes = '.. ../katze . ../panels ../toolbars'
obj.find_sources_in_dirs ('../katze . ../panels ../toolbars')
obj.add_marshal_file ('marshal.list', 'midori_cclosure_marshal')
obj.uselib = libs
if bld.env['WINRC']:
obj.source += ' ../data/midori.rc'

View File

@ -16,7 +16,7 @@
#include "midori-browser.h"
#include "midori-platform.h"
#include "midori-view.h"
#include "midori-core.h"
#include "midori-viewable.h"
#include <glib/gi18n.h>
#include <string.h>
@ -29,8 +29,7 @@ gboolean
midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser,
KatzeItem* bookmark,
gboolean new_bookmark,
gboolean is_folder,
GtkWidget* proxy);
gboolean is_folder);
void
midori_browser_open_bookmark (MidoriBrowser* browser,
@ -120,87 +119,66 @@ midori_bookmarks_get_stock_id (MidoriViewable* viewable)
return STOCK_BOOKMARKS;
}
/* TODO: Function never used */
void
midori_bookmarks_export_array_db (sqlite3* db,
KatzeArray* array,
gint64 parentid)
midori_bookmarks_export_array_db (sqlite3* db,
KatzeArray* array,
const gchar* folder)
{
KatzeArray* root_array;
KatzeArray* subarray;
KatzeItem* item;
GList* list;
gchar* parent_id;
parent_id = g_strdup_printf ("%" G_GINT64_FORMAT, parentid);
if (!(root_array = midori_array_query (array, "*", "parentid = %q", parent_id)))
{
g_free (parent_id);
if (!(root_array = midori_array_query (array, "*", "folder='%q'", folder)))
return;
}
KATZE_ARRAY_FOREACH_ITEM_L (item, root_array, list)
{
if (KATZE_ITEM_IS_FOLDER (item))
{
subarray = katze_array_new (KATZE_TYPE_ARRAY);
katze_item_set_name (KATZE_ITEM (subarray), katze_item_get_name (item));
midori_bookmarks_export_array_db (db, subarray,
katze_item_get_meta_integer (item, "parentid"));
midori_bookmarks_export_array_db (db, subarray, katze_item_get_name (item));
katze_array_add_item (array, subarray);
}
else
katze_array_add_item (array, item);
}
g_free (parent_id);
g_list_free (list);
}
void
midori_bookmarks_import_array_db (sqlite3* db,
KatzeArray* array,
gint64 parentid)
midori_bookmarks_import_array_db (sqlite3* db,
KatzeArray* array,
const gchar* folder)
{
GList* list;
KatzeItem* item;
gint64 id;
if (!db)
return;
KATZE_ARRAY_FOREACH_ITEM_L (item, array, list)
{
id = midori_bookmarks_insert_item_db (db, item, parentid);
if (KATZE_IS_ARRAY (item))
midori_bookmarks_import_array_db (db, KATZE_ARRAY (item), id);
midori_bookmarks_import_array_db (db, KATZE_ARRAY (item), folder);
midori_bookmarks_insert_item_db (db, item, folder);
}
g_list_free (list);
}
static KatzeArray*
midori_bookmarks_read_from_db (MidoriBookmarks* bookmarks,
gint64 parentid,
const gchar* folder,
const gchar* keyword)
{
KatzeArray* array;
if (keyword && *keyword)
array = midori_array_query (bookmarks->array,
"id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "title LIKE '%%%q%%'", keyword);
"uri, title, desc, app, toolbar, folder", "title LIKE '%%%q%%'", keyword);
else
{
if (parentid > 0)
{
gchar* parent_id = g_strdup_printf ("%" G_GINT64_FORMAT, parentid);
array = midori_array_query (bookmarks->array,
"id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid = %q", parent_id);
g_free (parent_id);
}
else
array = midori_array_query (bookmarks->array,
"id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid IS NULL", NULL);
}
array = midori_array_query (bookmarks->array,
"uri, title, desc, app, toolbar, folder", "folder = '%q'", folder);
return array ? array : katze_array_new (KATZE_TYPE_ITEM);
}
@ -208,7 +186,7 @@ static void
midori_bookmarks_read_from_db_to_model (MidoriBookmarks* bookmarks,
GtkTreeStore* model,
GtkTreeIter* parent,
gint64 parentid,
const gchar* folder,
const gchar* keyword)
{
KatzeArray* array;
@ -216,7 +194,7 @@ midori_bookmarks_read_from_db_to_model (MidoriBookmarks* bookmarks,
KatzeItem* item;
GtkTreeIter child;
array = midori_bookmarks_read_from_db (bookmarks, parentid, keyword);
array = midori_bookmarks_read_from_db (bookmarks, folder, keyword);
katze_bookmark_populate_tree_view (array, model, parent);
/* Remove invisible dummy row */
last = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), parent);
@ -230,30 +208,23 @@ midori_bookmarks_read_from_db_to_model (MidoriBookmarks* bookmarks,
g_object_unref (item);
}
gint64
midori_bookmarks_insert_item_db (sqlite3* db,
KatzeItem* item,
gint64 parentid)
void
midori_bookmarks_insert_item_db (sqlite3* db,
KatzeItem* item,
const gchar* folder)
{
gchar* sqlcmd;
char* errmsg = NULL;
KatzeItem* old_parent;
gchar* new_parentid;
gchar* id = NULL;
const gchar* parent;
const gchar* uri = NULL;
const gchar* desc = NULL;
gint64 seq = 0;
/* Bookmarks must have a name, import may produce invalid items */
g_return_val_if_fail (katze_item_get_name (item), seq);
g_return_if_fail (katze_item_get_name (item));
if (!db)
return seq;
if (katze_item_get_meta_integer (item, "id") > 0)
id = g_strdup_printf ("%" G_GINT64_FORMAT, katze_item_get_meta_integer(item, "id"));
else
id = g_strdup_printf ("NULL");
return;
if (KATZE_ITEM_IS_BOOKMARK (item))
uri = katze_item_get_uri (item);
@ -263,57 +234,30 @@ midori_bookmarks_insert_item_db (sqlite3* db,
/* Use folder, otherwise fallback to parent folder */
old_parent = katze_item_get_parent (item);
if (parentid > 0)
new_parentid = g_strdup_printf ("%" G_GINT64_FORMAT, parentid);
else if (old_parent && katze_item_get_meta_integer (old_parent, "id") > 0)
new_parentid = g_strdup_printf ("%" G_GINT64_FORMAT, katze_item_get_meta_integer (old_parent, "id"));
if (folder && *folder)
parent = folder;
else if (old_parent && katze_item_get_name (old_parent))
parent = katze_item_get_name (old_parent);
else
new_parentid = g_strdup_printf ("NULL");
parent = "";
sqlcmd = sqlite3_mprintf (
"INSERT INTO bookmarks (id, parentid, title, uri, desc, toolbar, app) "
"VALUES (%q, %q, '%q', '%q', '%q', %d, %d)",
id,
new_parentid,
"INSERT into bookmarks (uri, title, desc, folder, toolbar, app) values"
" ('%q', '%q', '%q', '%q', %d, %d)",
uri ? uri : "",
katze_item_get_name (item),
katze_str_non_null (uri),
katze_str_non_null (desc),
desc ? desc : "",
parent,
katze_item_get_meta_boolean (item, "toolbar"),
katze_item_get_meta_boolean (item, "app"));
if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) == SQLITE_OK)
{
/* Get insert id */
if (g_str_equal (id, "NULL"))
{
KatzeArray* seq_array;
sqlite3_free (sqlcmd);
sqlcmd = sqlite3_mprintf (
"SELECT seq FROM sqlite_sequence WHERE name = 'bookmarks'");
seq_array = katze_array_from_sqlite (db, sqlcmd);
if (katze_array_get_nth_item (seq_array, 0))
{
KatzeItem* seq_item = katze_array_get_nth_item (seq_array, 0);
seq = katze_item_get_meta_integer (seq_item, "seq");
katze_item_set_meta_integer (item, "id", seq);
}
g_object_unref (seq_array);
}
}
else
if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK)
{
g_printerr (_("Failed to add bookmark item: %s\n"), errmsg);
sqlite3_free (errmsg);
}
sqlite3_free (sqlcmd);
g_free (new_parentid);
g_free (id);
return seq;
}
static void
@ -323,9 +267,15 @@ midori_bookmarks_add_item_cb (KatzeArray* array,
{
GtkTreeModel* model;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));
gtk_tree_store_clear (GTK_TREE_STORE (model));
midori_bookmarks_read_from_db_to_model (bookmarks,
GTK_TREE_STORE (model), NULL, 0, bookmarks->filter);
if (!g_strcmp0 (katze_item_get_meta_string (item, "folder"), ""))
gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
NULL, NULL, G_MAXINT, 0, item, -1);
else
{
gtk_tree_store_clear (GTK_TREE_STORE (model));
midori_bookmarks_read_from_db_to_model (bookmarks,
GTK_TREE_STORE (model), NULL, NULL, bookmarks->filter);
}
}
static void
@ -336,7 +286,7 @@ midori_bookmarks_remove_item_cb (KatzeArray* array,
GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));
gtk_tree_store_clear (GTK_TREE_STORE (model));
midori_bookmarks_read_from_db_to_model (bookmarks,
GTK_TREE_STORE (model), NULL, 0, bookmarks->filter);
GTK_TREE_STORE (model), NULL, NULL, bookmarks->filter);
}
static void
@ -346,7 +296,7 @@ midori_bookmarks_update_cb (KatzeArray* array,
GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));
gtk_tree_store_clear (GTK_TREE_STORE (model));
midori_bookmarks_read_from_db_to_model (bookmarks,
GTK_TREE_STORE (model), NULL, 0, bookmarks->filter);
GTK_TREE_STORE (model), NULL, NULL, bookmarks->filter);
}
@ -359,7 +309,7 @@ midori_bookmarks_row_changed_cb (GtkTreeModel* model,
KatzeItem* item;
GtkTreeIter parent;
KatzeItem* new_parent = NULL;
gint64 parentid;
const gchar* parent_name;
gtk_tree_model_get (model, iter, 0, &item, -1);
@ -369,15 +319,15 @@ midori_bookmarks_row_changed_cb (GtkTreeModel* model,
/* Bookmarks must not be moved into non-folder items */
if (!KATZE_ITEM_IS_FOLDER (new_parent))
parentid = 0;
parent_name = "";
else
parentid = katze_item_get_meta_integer (new_parent, "id");
parent_name = katze_item_get_name (new_parent);
}
else
parentid = 0;
parent_name = "";
katze_array_remove_item (bookmarks->array, item);
katze_item_set_meta_integer (item, "parentid", parentid);
katze_item_set_meta_string (item, "folder", parent_name);
katze_array_add_item (bookmarks->array, item);
g_object_unref (item);
@ -391,9 +341,9 @@ midori_bookmarks_add_clicked_cb (GtkWidget* toolitem)
MidoriBrowser* browser = midori_browser_get_for_widget (toolitem);
/* FIXME: Take selected folder into account */
if (g_str_equal (gtk_widget_get_name (toolitem), "BookmarkFolderAdd"))
midori_browser_edit_bookmark_dialog_new (browser, NULL, TRUE, TRUE, toolitem);
midori_browser_edit_bookmark_dialog_new (browser, NULL, TRUE, TRUE);
else
midori_browser_edit_bookmark_dialog_new (browser, NULL, TRUE, FALSE, toolitem);
midori_browser_edit_bookmark_dialog_new (browser, NULL, TRUE, FALSE);
}
static void
@ -408,24 +358,14 @@ midori_bookmarks_edit_clicked_cb (GtkWidget* toolitem,
{
KatzeItem* item;
MidoriBrowser* browser;
gint64 parentid;
gtk_tree_model_get (model, &iter, 0, &item, -1);
g_assert (!KATZE_ITEM_IS_SEPARATOR (item));
browser = midori_browser_get_for_widget (bookmarks->treeview);
parentid = katze_item_get_meta_integer (item, "parentid");
midori_browser_edit_bookmark_dialog_new (
browser, item, FALSE, KATZE_ITEM_IS_FOLDER (item), NULL);
if (katze_item_get_meta_integer (item, "parentid") != parentid)
{
gtk_tree_store_clear (GTK_TREE_STORE (model));
midori_bookmarks_read_from_db_to_model (bookmarks, GTK_TREE_STORE (model),
NULL, 0, NULL);
}
browser, item, FALSE, KATZE_ITEM_IS_FOLDER (item));
g_object_unref (item);
}
}
@ -441,47 +381,6 @@ midori_bookmarks_toolbar_update (MidoriBookmarks *bookmarks)
gtk_widget_set_sensitive (GTK_WIDGET (bookmarks->edit), selected);
}
gboolean
midori_bookmarks_update_item_db (sqlite3* db,
KatzeItem* item)
{
gchar* sqlcmd;
char* errmsg = NULL;
gchar* parentid;
gboolean updated;
if (katze_item_get_meta_integer (item, "parentid") > 0)
parentid = g_strdup_printf ("%" G_GINT64_FORMAT,
katze_item_get_meta_integer (item, "parentid"));
else
parentid = g_strdup_printf ("NULL");
sqlcmd = sqlite3_mprintf (
"UPDATE bookmarks SET "
"parentid=%q, title='%q', uri='%q', desc='%q', toolbar=%d, app=%d "
"WHERE id = %" G_GINT64_FORMAT ";",
parentid,
katze_item_get_name (item),
katze_str_non_null (katze_item_get_uri (item)),
katze_str_non_null (katze_item_get_meta_string (item, "desc")),
katze_item_get_meta_boolean (item, "toolbar"),
katze_item_get_meta_boolean (item, "app"),
katze_item_get_meta_integer (item, "id"));
updated = TRUE;
if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK)
{
updated = FALSE;
g_printerr (_("Failed to update bookmark : %s\n"), errmsg);
sqlite3_free (errmsg);
}
sqlite3_free (sqlcmd);
g_free (parentid);
return updated;
}
static void
midori_bookmarks_delete_clicked_cb (GtkWidget* toolitem,
MidoriBookmarks* bookmarks)
@ -521,7 +420,7 @@ midori_bookmarks_get_toolbar (MidoriViewable* viewable)
gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON);
gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), FALSE);
bookmarks->toolbar = toolbar;
toolitem = gtk_tool_button_new_from_stock (STOCK_BOOKMARK_ADD);
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_ADD);
gtk_widget_set_name (GTK_WIDGET (toolitem), "BookmarkAdd");
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),
_("Add a new bookmark"));
@ -552,7 +451,7 @@ midori_bookmarks_get_toolbar (MidoriViewable* viewable)
gtk_tool_item_set_expand (toolitem, TRUE);
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
gtk_widget_show (GTK_WIDGET (toolitem));
toolitem = gtk_tool_button_new_from_stock (STOCK_FOLDER_NEW);
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_DIRECTORY);
gtk_widget_set_name (GTK_WIDGET (toolitem), "BookmarkFolderAdd");
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),
_("Add a new folder"));
@ -596,8 +495,8 @@ midori_bookmarks_set_app (MidoriBookmarks* bookmarks,
g_object_ref (app);
bookmarks->array = katze_object_get_object (app, "bookmarks");
midori_bookmarks_read_from_db_to_model (bookmarks, GTK_TREE_STORE (model), NULL, 0, NULL);
g_signal_connect_after (bookmarks->array, "add-item",
midori_bookmarks_read_from_db_to_model (bookmarks, GTK_TREE_STORE (model), NULL, "", NULL);
g_signal_connect (bookmarks->array, "add-item",
G_CALLBACK (midori_bookmarks_add_item_cb), bookmarks);
g_signal_connect (bookmarks->array, "remove-item",
G_CALLBACK (midori_bookmarks_remove_item_cb), bookmarks);
@ -663,8 +562,6 @@ midori_bookmarks_treeview_render_icon_cb (GtkTreeViewColumn* column,
if (KATZE_ITEM_IS_FOLDER (item))
pixbuf = gtk_widget_render_icon (treeview, GTK_STOCK_DIRECTORY,
GTK_ICON_SIZE_MENU, NULL);
else if ((pixbuf = katze_item_get_pixbuf (item, treeview)))
;
else if (KATZE_ITEM_IS_BOOKMARK (item))
pixbuf = katze_load_cached_icon (katze_item_get_uri (item), treeview);
g_object_set (renderer, "pixbuf", pixbuf, NULL);
@ -688,11 +585,8 @@ midori_bookmarks_treeview_render_text_cb (GtkTreeViewColumn* column,
gtk_tree_model_get (model, iter, 0, &item, -1);
if (item && katze_item_get_name (item))
{
g_object_set (renderer, "markup", NULL,
"ellipsize", PANGO_ELLIPSIZE_END,
"text", katze_item_get_name (item), NULL);
}
else
g_object_set (renderer, "markup", _("<i>Separator</i>"), NULL);
@ -790,9 +684,7 @@ midori_bookmarks_open_in_tab_activate_cb (GtkWidget* menuitem,
KatzeItem* child;
KatzeArray* array;
array = midori_bookmarks_read_from_db (bookmarks,
katze_item_get_meta_integer (item, "parentid"), NULL);
array = midori_bookmarks_read_from_db (bookmarks, katze_item_get_name (item), NULL);
g_return_if_fail (KATZE_IS_ARRAY (array));
KATZE_ARRAY_FOREACH_ITEM (child, array)
{
@ -948,7 +840,7 @@ midori_bookmarks_row_expanded_cb (GtkTreeView* treeview,
model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
gtk_tree_model_get (model, iter, 0, &item, -1);
midori_bookmarks_read_from_db_to_model (bookmarks, GTK_TREE_STORE (model),
iter, katze_item_get_meta_integer (item, "id"), NULL);
iter, katze_item_get_name (item), NULL);
g_object_unref (item);
}
@ -990,7 +882,7 @@ midori_bookmarks_filter_timeout_cb (gpointer data)
gtk_tree_store_clear (treestore);
midori_bookmarks_read_from_db_to_model (bookmarks,
treestore, NULL, 0, bookmarks->filter);
treestore, NULL, NULL, bookmarks->filter);
return FALSE;
}
@ -1001,16 +893,21 @@ midori_bookmarks_filter_entry_changed_cb (GtkEntry* entry,
{
if (bookmarks->filter_timeout)
g_source_remove (bookmarks->filter_timeout);
if (!g_object_get_data (G_OBJECT (entry), "sokoke_has_default"))
katze_assign (bookmarks->filter, g_strdup (gtk_entry_get_text (entry)));
else
katze_assign (bookmarks->filter, NULL);
katze_assign (bookmarks->filter, g_strdup (gtk_entry_get_text (entry)));
bookmarks->filter_timeout = g_timeout_add (COMPLETION_DELAY,
midori_bookmarks_filter_timeout_cb, bookmarks);
}
static void
midori_bookmarks_filter_entry_clear_cb (GtkEntry* entry,
gint icon_pos,
gint button,
MidoriBookmarks* bookmarks)
{
if (icon_pos == GTK_ICON_ENTRY_SECONDARY)
gtk_entry_set_text (entry, "");
}
static void
midori_bookmarks_init (MidoriBookmarks* bookmarks)
{
@ -1024,8 +921,18 @@ midori_bookmarks_init (MidoriBookmarks* bookmarks)
GtkTreeSelection* selection;
/* Create the filter entry */
entry = sokoke_search_entry_new (_("Search Bookmarks"));
g_signal_connect_after (entry, "changed",
entry = gtk_icon_entry_new ();
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_PRIMARY,
GTK_STOCK_FIND);
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_bookmarks_filter_entry_clear_cb), bookmarks);
g_signal_connect (entry, "changed",
G_CALLBACK (midori_bookmarks_filter_entry_changed_cb), bookmarks);
box = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (box), entry, TRUE, TRUE, 3);
@ -1038,14 +945,14 @@ midori_bookmarks_init (MidoriBookmarks* bookmarks)
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (treeview), 1);
column = gtk_tree_view_column_new ();
gtk_tree_view_column_set_expand (column, TRUE);
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
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_bookmarks_treeview_render_icon_cb,
treeview, NULL);
renderer_text = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer_text, TRUE);
gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
(GtkTreeCellDataFunc)midori_bookmarks_treeview_render_text_cb,
treeview, NULL);

View File

@ -40,19 +40,15 @@ midori_bookmarks_get_type (void);
GtkWidget*
midori_bookmarks_new (void);
gint64
midori_bookmarks_insert_item_db (sqlite3* db,
KatzeItem* item,
gint64 parentid);
void
midori_bookmarks_insert_item_db (sqlite3* db,
KatzeItem* item,
const gchar* folder);
void
midori_bookmarks_import_array_db (sqlite3* db,
KatzeArray* array,
gint64 parentid);
gboolean
midori_bookmarks_update_item_db (sqlite3* db,
KatzeItem* item);
midori_bookmarks_import_array_db (sqlite3* db,
KatzeArray* array,
const gchar* folder);
G_END_DECLS

View File

@ -14,6 +14,7 @@
#include "midori-app.h"
#include "midori-extension.h"
#include "midori-platform.h"
#include "midori-viewable.h"
#include "midori-core.h"
#include <glib/gi18n.h>
@ -93,7 +94,7 @@ midori_extensions_get_label (MidoriViewable* viewable)
static const gchar*
midori_extensions_get_stock_id (MidoriViewable* viewable)
{
return STOCK_EXTENSION;
return STOCK_EXTENSIONS;
}
static GtkWidget*
@ -284,7 +285,6 @@ midori_extensions_treeview_render_text_cb (GtkTreeViewColumn* column,
g_object_set (renderer,
"markup", text,
"ellipsize", PANGO_ELLIPSIZE_END,
"sensitive", midori_extension_is_prepared (extension),
NULL);
@ -305,17 +305,13 @@ midori_extensions_treeview_row_activated_cb (GtkTreeView* treeview,
if (gtk_tree_model_get_iter (model, &iter, path))
{
MidoriExtension* extension;
KatzeArray* array = katze_object_get_object (extensions->app, "extensions");
gtk_tree_model_get (model, &iter, 0, &extension, -1);
if (midori_extension_is_active (extension))
midori_extension_deactivate (extension);
else if (midori_extension_is_prepared (extension))
g_signal_emit_by_name (extension, "activate", extensions->app);
/* Make it easy for listeners to see that extensions changed */
katze_array_update (array);
g_object_unref (array);
g_object_unref (extension);
}
}
@ -332,17 +328,13 @@ midori_extensions_cell_renderer_toggled_cb (GtkCellRendererToggle* renderer,
if (gtk_tree_model_get_iter_from_string (model, &iter, path))
{
MidoriExtension* extension;
KatzeArray* array = katze_object_get_object (extensions->app, "extensions");
gtk_tree_model_get (model, &iter, 0, &extension, -1);
if (midori_extension_is_active (extension))
midori_extension_deactivate (extension);
else if (midori_extension_is_prepared (extension))
g_signal_emit_by_name (extension, "activate", extensions->app);
/* Make it easy for listeners to see that extensions changed */
katze_array_update (array);
g_object_unref (array);
g_object_unref (extension);
}
}
@ -462,9 +454,10 @@ midori_extensions_init (MidoriExtensions* extensions)
extensions->treeview, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (extensions->treeview), column);
column = gtk_tree_view_column_new ();
gtk_tree_view_column_set_expand (column, TRUE);
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
renderer_text = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer_text, TRUE);
gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
gtk_tree_view_column_set_expand (column, TRUE);
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
(GtkTreeCellDataFunc)midori_extensions_treeview_render_text_cb,
extensions->treeview, NULL);

View File

@ -16,7 +16,7 @@
#include "midori-browser.h"
#include "midori-platform.h"
#include "midori-view.h"
#include "midori-core.h"
#include "midori-viewable.h"
#include <glib/gi18n.h>
#include <string.h>
@ -28,8 +28,7 @@ void
midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser,
KatzeItem* bookmark,
gboolean new_bookmark,
gboolean is_folder,
GtkWidget* proxy);
gboolean is_folder);
struct _MidoriHistory
@ -117,59 +116,18 @@ midori_history_get_stock_id (MidoriViewable* viewable)
return STOCK_HISTORY;
}
#if !GLIB_CHECK_VERSION (2, 26, 0)
static 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;
}
#endif
static gchar*
midori_history_format_date (KatzeItem *item)
{
gint64 day = katze_item_get_added (item);
gchar* sdate;
gint age;
#if GLIB_CHECK_VERSION (2, 26, 0)
GDateTime* now = g_date_time_new_now_local ();
GDateTime* then = g_date_time_new_from_unix_local (day);
age = g_date_time_get_day_of_year (now) - g_date_time_get_day_of_year (then);
if (g_date_time_get_year (now) != g_date_time_get_year (then))
age = 999;
if (age == 0)
sdate = g_strdup (_("Today"));
else if (age == 1)
sdate = g_strdup (_("Yesterday"));
else if (age < 7)
sdate = g_strdup_printf (ngettext ("%d day ago",
"%d days ago", (gint)age), (gint)age);
else if (age == 7)
sdate = g_strdup (_("A week ago"));
else
sdate = g_date_time_format (then, "%x");
#else
gint64 day;
gchar token[50];
gchar* sdate;
time_t current_time;
current_time = time (NULL);
day = katze_item_get_added (item);
age = sokoke_days_between ((time_t*)&day, &current_time);
/* A negative age is a date in the future, the clock is probably off */
@ -189,7 +147,6 @@ midori_history_format_date (KatzeItem *item)
sdate = g_strdup (_("Today"));
else
sdate = g_strdup (_("Yesterday"));
#endif
return sdate;
}
@ -374,7 +331,6 @@ midori_history_bookmark_add_cb (GtkWidget* menuitem,
GtkTreeIter iter;
KatzeItem* item = NULL;
GtkWidget* proxy = GTK_IS_TOOL_ITEM (menuitem) ? menuitem : NULL;
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (history));
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (history->treeview),
&model, &iter))
@ -382,11 +338,11 @@ midori_history_bookmark_add_cb (GtkWidget* menuitem,
if (KATZE_IS_ITEM (item) && katze_item_get_uri (item))
{
midori_browser_edit_bookmark_dialog_new (browser, item, TRUE, FALSE, proxy);
midori_browser_edit_bookmark_dialog_new (browser, item, TRUE, FALSE);
g_object_unref (item);
}
else
midori_browser_edit_bookmark_dialog_new (browser, NULL, TRUE, FALSE, proxy);
midori_browser_edit_bookmark_dialog_new (browser, NULL, TRUE, FALSE);
}
static GtkWidget*
@ -456,8 +412,9 @@ midori_history_add_item_cb (KatzeArray* array,
GtkTreeModel* model = gtk_tree_view_get_model (treeview);
GtkTreeIter iter;
KatzeItem* today;
time_t current_time = time (NULL);
time_t current_time;
current_time = time (NULL);
if (gtk_tree_model_iter_children (model, &iter, NULL))
{
gint64 day;
@ -466,18 +423,7 @@ midori_history_add_item_cb (KatzeArray* array,
gtk_tree_model_get (model, &iter, 0, &today, -1);
day = katze_item_get_added (today);
#if GLIB_CHECK_VERSION (2, 26, 0)
has_today = g_date_time_get_day_of_month (
g_date_time_new_from_unix_local (day))
== g_date_time_get_day_of_month (
g_date_time_new_from_unix_local (current_time))
&& g_date_time_get_day_of_year (
g_date_time_new_from_unix_local (day))
== g_date_time_get_day_of_year (
g_date_time_new_from_unix_local (current_time));
#else
has_today = sokoke_days_between ((time_t*)&day, &current_time) == 0;
#endif
g_object_unref (today);
if (has_today)
{
@ -594,8 +540,6 @@ midori_history_treeview_render_icon_cb (GtkTreeViewColumn* column,
if (!item)
pixbuf = NULL;
else if ((pixbuf = katze_item_get_pixbuf (item, treeview)))
;
else if (katze_item_get_uri (item))
pixbuf = katze_load_cached_icon (katze_item_get_uri (item), treeview);
else
@ -624,14 +568,11 @@ midori_history_treeview_render_text_cb (GtkTreeViewColumn* column,
if (KATZE_ITEM_IS_BOOKMARK (item))
g_object_set (renderer, "markup", NULL,
"ellipsize", PANGO_ELLIPSIZE_END,
"text", katze_item_get_name (item), NULL);
else if (KATZE_ITEM_IS_FOLDER (item))
{
gchar* formatted = midori_history_format_date (item);
g_object_set (renderer, "markup", NULL, "text", formatted,
"ellipsize", PANGO_ELLIPSIZE_END,
NULL);
g_object_set (renderer, "markup", NULL, "text", formatted, NULL);
g_free (formatted);
}
else
@ -967,11 +908,17 @@ midori_history_filter_entry_changed_cb (GtkEntry* entry,
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)));
}
if (!g_object_get_data (G_OBJECT (entry), "sokoke_has_default"))
katze_assign (history->filter, g_strdup (gtk_entry_get_text (entry)));
else
katze_assign (history->filter, NULL);
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
@ -994,8 +941,19 @@ midori_history_init (MidoriHistory* history)
GtkTreeSelection* selection;
/* Create the filter entry */
entry = sokoke_search_entry_new (_("Search History"));
g_signal_connect_after (entry, "changed",
entry = gtk_icon_entry_new ();
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_PRIMARY,
GTK_STOCK_FIND);
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);
g_signal_connect (entry, "changed",
G_CALLBACK (midori_history_filter_entry_changed_cb), history);
box = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (box), entry, TRUE, TRUE, 3);
@ -1008,14 +966,14 @@ midori_history_init (MidoriHistory* history)
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (treeview), 1);
column = gtk_tree_view_column_new ();
gtk_tree_view_column_set_expand (column, TRUE);
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
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_history_treeview_render_icon_cb,
treeview, NULL);
renderer_text = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer_text, TRUE);
gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
(GtkTreeCellDataFunc)midori_history_treeview_render_text_cb,
treeview, NULL);

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